Tk Source Code

Changes On Branch bug-e3888d5820-alt1
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Changes In Branch bug-e3888d5820-alt1 Excluding Merge-Ins

This is equivalent to a diff from 5c500188 to 99290d7d

2020-12-30
16:57
Merge bug-e3888d5820-alt1. This re-adds arroneously removed 'after 50' after warping commands, which is needed on Windows so that the tests are stable and don't depend on a race condition. check-in: 85be1768 user: fvogel tags: trunk, main
15:44
In Tk 8.7, warping is now synchronous (it was executed at idle time until and including 8.6), see [e3888d5820]. As a consequence we don't need to call 'update' in the tests anymore for 8.7. However, as detailed in ticket [69b48f427e] (specifically in comment there dated 2019-10-27 14:24:26), on Windows we still need to call 'after 50' to give time to SendInput to execute. This is independent from the fact warping happens sychronously or not and was committed as [e9becf44ab] in core-8-6-branch but was later erroneously removed from trunk branch in [d9d8c6bf] and [3e8ae688] under the wrong idea that is was not necessary with synchronous warping. Restore those calls, which makes bind-34.[123] and bind-36.1 always pass instead of rely on a race condition. Closed-Leaf check-in: 99290d7d user: fvogel tags: bug-e3888d5820-alt1
15:25
merge trunk check-in: c2d0773b user: fvogel tags: bug-e3888d5820-alt1
2020-07-06
21:18
Fix [e3888d5820]: Grab on master prevents mouse pointer warp into slave widget. Mouse pointer warping happens at idle time, and the fix does not change this. check-in: 7f3b5a11 user: fvogel tags: core-8-6-branch
2020-06-14
16:19
Rework test bind-35.1 and simplify it a bit, make it fail in core-8-6-branch that does not have the fix yet. Closed-Leaf check-in: 5c500188 user: fvogel tags: bug-e3888d5820
2020-06-07
19:58
Add comment explaining the result expected for bind-35.1 check-in: c5754760 user: fvogel tags: bug-e3888d5820
2020-02-18
21:19
Use TkGrabState() in function TestgrabObjCmd() instead of dispPtr->grabWinPtr to make the code clearer and the interface cleaner. check-in: 1e8dcf37 user: fvogel tags: bug-e3888d5820
2020-02-17
22:06
Refine test bind-35.1 once more since [grab current] returns the eventualGrabWin while we're interested in the grabWin instead. check-in: 0b310b17 user: fvogel tags: bug-e3888d5820

Changes to .fossil-settings/encoding-glob.
1
2
3
4

5





1
2


3
4
5
6
7
8
9


-
-
+

+
+
+
+
+
win/buildall.vc.bat
win/makefile.vc
win/mkd.bat
win/rmd.bat
win/rules-ext.vc
win/rules.vc
win/targets.vc
win/rc/*.bmp
win/rc/*.cur
win/rc/*.ico
win/rc/*.rc
Changes to .fossil-settings/ignore-glob.
1
2
3

4
5

6

7
8
9
10
11
12
13

14
15
16
17
18
19
20




21

22
23

24
25
26
27


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

29
30
31
32
33
34
35

36
37



+


+

+







+







+
+
+
+
-
+


+



-
+
+
*.a
*.dll
*.dylib
*.dylib.E
*.exe
*.exp
*.la
*.lib
*.lo
*.o
*.obj
*.pdb
*.res
*.sl
*.so
*/Makefile
*/autom4te.cache
*/config.cache
*/config.log
*/config.status
*/tkConfig.sh
*/wish*
*/tktest*
*/versions.vc
*/version.vc
*/libtk.vfs
*/libtk_*.zip
html
doc/man.macros
macosx/configure
win/Debug*
win/Release*
win/*.manifest
win/nmhlp-out.txt
win/nmakehlp.out
unix/tk.pc
html/*
unix/Tk-Info.plist
unix/Wish-Info.plist
Added .fossil-settings/manifest.

1
+
u
Added .gitattributes.











































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# Set the default behavior, in case people don't have core.autocrlf set.
* eol=lf
* text=auto

# Explicitly declare text files you want to always be normalized and converted
# to native line endings on checkout.
*.3 text
*.c text
*.css text
*.enc text
*.h text
*.htm text
*.html text
*.java text
*.js text
*.json text
*.n text
*.svg text
*.ts text
*.tcl text
*.test text

# Declare files that will always have CRLF line endings on checkout.
*.bat eol=crlf
*.rc eol=crlf
*.sln eol=crlf
*.vc eol=crlf

# Denote all files that are truly binary and should not be modified.
*.a binary
*.bmp binary
*.cur binary
*.dll binary
*.exe binary
*.gif binary
*.gz binary
*.ico binary
*.jpg binary
*.lib binary
*.pdf binary
*.png binary
*.xlsx binary
*.zip binary
Added .github/workflows/linux-build.yml.


























































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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" >> $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' }}
        uses: actions/upload-artifact@v2
        with:
          name: Tk ${{ env.VERSION }} Source distribution (unofficial)
          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 (unofficial)
          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" >> $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/mac-build.yml.
























































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
name: macOS
on: [push]
env:
  ERROR_ON_FAILURES: 1
jobs:
  xcode:
    runs-on: macos-11.0
    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
          }
  clang:
    runs-on: macos-11.0
    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
        run: |
          touch tkStubInit.c
          mkdir "$HOME/install dir"
          echo "USE_XVFB=$SET_DISPLAY" >> $GITHUB_ENV
        working-directory: tk/generic
        env:
          SET_DISPLAY: ${{ contains(matrix.options, '--disable-aqua') }}
      - name: Add X11 (if required)
        if: ${{ env.USE_XVFB }}
        # This involves black magic
        run: |
          brew cask install xquartz
          sudo /opt/X11/lib/X11/xinit/privileged_startx.d/10-tmpdirs || 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 {
              : do nothing
            }
          fi
          ( runXvfb :0; make test-classic; exit $? ) | tee out-classic.txt || {
            echo "::error::Failure during Test"
            exit 1
          }
          ( runXvfb :0; make test-ttk; exit $? ) | tee out-ttk.txt || {
            echo "::error::Failure during Test"
            exit 1
          }
          cat out-classic.txt out-ttk.txt | grep -q "Failed[[:space:]][[:space:]]*[1-9]" && {
            echo "::error::Failure during Test"
            exit 1
          }
        env:
          MAC_CI: 1
      - name: Carry out trial installation
        run: |
          make install || {
            cat config.log
            echo "::error::Failure during Install"
            exit 1
          }
Added .github/workflows/onefiledist.yml.





































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
name: Build Binaries
on: [push]
jobs:
  linux:
    name: Linux
    runs-on: ubuntu-16.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
          mkdir -p install/1dist.vfs
          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 tclzipfile 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: Pack Tk Library Files into Library Zip
        run: |
          unzip ../lib/libtcl*.zip
          cp -a ../lib/tk[0-9]* .
          zip -r ../1dist.zip .
        working-directory: ${{ env.INST_DIR }}/1dist.vfs
      - name: Package
        run: |
          cat ../tk/unix/wish 1dist.zip >> ${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 }}_unofficial
      - name: Upload
        uses: actions/upload-artifact@v2
        with:
          name: Wish ${{ env.TCL_PATCHLEVEL }} Linux single-file build (unofficial)
          path: ${{ env.INST_DIR }}/*.tar
      - name: Describe Installation Zip Contents
        if: ${{ always() }}
        run: |
          unzip -l 1dist.zip || true
        working-directory: ${{ env.INST_DIR }}
  macos:
    name: macOS
    runs-on: macos-11.0
    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/1dist.vfs 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
        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 tclzipfile 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: Pack Tk Library Files into Library Zip
        run: |
          unzip ../lib/libtcl*.zip
          cp -a ../lib/tk[0-9]* .
          zip -r ../1dist.zip .
        working-directory: ${{ env.INST_DIR }}/1dist.vfs
      - name: Package
        run: |
          cat ../tk/unix/wish 1dist.zip >> contents/${BUILD_NAME}
          chmod +x contents/${BUILD_NAME}
          cat > contents/README.txt <<EOF
          This is a single-file executable developer preview of Tcl/Tk $TCL_PATCHLEVEL

          It is not intended as an official release at all, so it is unsigned and unnotarized.
          Use strictly at your own risk.

          To run it, you need to copy the executable out and run:
              xattr -d com.apple.quarantine ${BUILD_NAME}
          to mark the executable as runnable on your machine.
          EOF
          $CREATE_DMG \
              --volname "TclTk $TCL_PATCHLEVEL (unofficial)" \
              --window-pos 200 120 \
              --window-size 800 400 \
              "TclTk-$TCL_PATCHLEVEL-(unofficial).dmg" \
              "contents/"
        working-directory: ${{ env.INST_DIR }}
        env:
          BUILD_NAME: wish${{ env.TCL_PATCHLEVEL }}_unofficial
      - name: Upload
        uses: actions/upload-artifact@v2
        with:
          name: Wish ${{ env.TCL_PATCHLEVEL }} macOS single-file build (unofficial)
          path: ${{ env.INST_DIR }}/*.dmg
  win:
    name: Windows
    runs-on: windows-latest
    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: |
          mkdir -p install/1dist
          mkdir -p install/combined
          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/win
      - name: Build & Install Tcl
        run: |
          make binaries libraries tclzipfile install
          echo "ZIP_BIN=`pwd`/minizip.exe" >> $GITHUB_ENV
          echo "TCL_ZIP=`pwd`/`echo libtcl*.zip`" >> $GITHUB_ENV
          $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: Pack Tk Library Files into Library Zip
        run: |
          unzip $TCL_ZIP
          cp -R ../lib/tk[0-9]* .
          $ZIP_BIN -o -r ../1dist.zip *
        working-directory: install/1dist
      - name: Package
        run: |
          cat ${TK_BIN} 1dist.zip > combined/${BUILD_NAME}.exe
        working-directory: install
        env:
          BUILD_NAME: wish${{ env.TCL_PATCHLEVEL }}_unofficial
      - name: Upload
        uses: actions/upload-artifact@v2
        with:
          name: Wish ${{ env.TCL_PATCHLEVEL }} Windows single-file build (unofficial)
          path: install/combined/wish${{ env.TCL_PATCHLEVEL }}_unofficial.exe
Added .github/workflows/win-build.yml.






























































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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: bash
        working-directory: win
    strategy:
      matrix:
        symbols:
          - "no"
          - "mem"
          - "all"
    # Using powershell means we need to explicitly stop on failure
    steps:
      - name: Checkout
        uses: actions/checkout@v2
      - name: Checkout
        uses: actions/checkout@v2
        with:
          repository: tcltk/tcl
          ref: core-8-6-branch
          path: tcl
      - name: Install MSYS2, Make
        run: choco install -y msys2 make
      - 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
          }
Added .gitignore.





























































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
*.a
*.bundle
*.dll
*.dylib
*.dylib.E
*.exe
*.exp
*.lib
*.o
*.obj
*.pdb
*.res
*.sl
*.so
.fslckout
Makefile
Tk-Info.plist
Wish-Info.plist
autom4te.cache
config.cache
config.log
config.status
config.status.lineno
html
manifest.uuid
_FOSSIL_
*/tkConfig.sh
*/wish*
*/tktest*
*/versions.vc
*/version.vc
*/libtcl.vfs
*/libtcl_*.zip
libtommath/bn.ilg
libtommath/bn.ind
libtommath/pretty.build
libtommath/tommath.src
libtommath/*.log
libtommath/*.pdf
libtommath/*.pl
libtommath/*.sh
libtommath/doc/*
libtommath/tombc/*
libtommath/pre_gen/*
libtommath/pics/*
libtommath/mtest/*
libtommath/logs/*
libtommath/etc/*
libtommath/demo/*
libtommath/*.out
libtommath/*.tex
macosx/configure
unix/autoMkindex.tcl
unix/dltest.marker
unix/tk.pc
unix/tclIndex
win/Debug*
win/Release*
win/*.manifest
win/nmakehlp.out
win/nmhlp-out.txt
Changes to .project.
1
2
3

4
5
6
7
8
9
10
1
2

3
4
5
6
7
8
9
10


-
+







<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
	<name>tk8.6</name>
	<name>tk8.7</name>
	<comment></comment>
	<projects>
	</projects>
	<buildSpec>
	</buildSpec>
	<natures>
	</natures>
Changes to .travis.yml.
1
2
3
4


5







6

7
8
9












10
11

12
13
14



15
16
17









18

19
20



21
22
23
24


25

26
27
28
29
30
31
32
33
34














35
36


37

38
39






















































40

41
42
43
44
45
46

47
48
49
50
51
52
53
54
55
56
57
58
59
60





















































































































61






62
63

64

65
66
67

68














1
2
3
4
5
6
7
8
9
10
11
12
13

14
15


16
17
18
19
20
21
22
23
24
25
26
27
28

29
30
31

32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

47
48

49
50
51
52
53

54
55
56

57
58








59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76

77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133

134
135
136


137

138
139
140
141
142
143
144
145
146


147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277

278


279
280

281
282
283
284
285
286
287
288
289
290
291
292
293
-



+
+

+
+
+
+
+
+
+
-
+

-
-
+
+
+
+
+
+
+
+
+
+
+
+

-
+


-
+
+
+



+
+
+
+
+
+
+
+
+
-
+

-
+
+
+


-

+
+
-
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+


+
+
-
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+


-
-

-
+








-
-




+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+


+
-
+
-
-

+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
sudo: required
language: c
addons:
  apt:
    sources:
      - ubuntu-toolchain-r-test
    packages:
      - binutils-mingw-w64-i686
      - binutils-mingw-w64-x86-64
      - gcc-mingw-w64
      - gcc-mingw-w64-base
      - gcc-mingw-w64-i686
      - gcc-mingw-w64-x86-64
      - gcc-multilib
      - tcl-dev
      - tcl8.6-dev
      - libx11-dev

matrix:
      - libnotify-dev
      - libglib2.0-dev
      - libxss-dev
      - xvfb
  homebrew:
    packages:
      - tcl-tk
      - libnotify
      - glib
#   casks:
#     - xquartz
jobs:
  include:
# Testing on Linux with various compilers
# Testing on Linux GCC
    - name: "Linux/GCC/Shared"
      os: linux
      dist: bionic
      dist: focal
      services:
        - xvfb
      compiler: gcc
      env:
        - BUILD_DIR=unix
      script: &x11gui
        - make binaries libraries tktest
        - make install
        - make test-classic >out-classic.txt
        - cat out-classic.txt
        - grep -q "Failed	0" out-classic.txt
        - make test-ttk >out-ttk.txt
        - cat out-ttk.txt
        - grep -q "Failed	0" out-ttk.txt
    - name: "Linux/GCC/Static"
    - name: "Linux/GCC/Shared: NO_DEPRECATED"
      os: linux
      dist: bionic
      dist: focal
      services:
        - xvfb
      compiler: gcc
      env:
        - CFGOPT="--disable-shared"
        - BUILD_DIR=unix
        - CFGOPT="CFLAGS=-DTK_NO_DEPRECATED=1"
      script: *x11gui
    - name: "Linux/GCC 7/Shared"
    - name: "Linux/GCC/Shared/no-xft"
      os: linux
      dist: bionic
      compiler: gcc-7
      addons:
        apt:
          sources:
            - ubuntu-toolchain-r-test
          packages:
            - g++-7
      dist: focal
      services:
        - 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 6/Shared"
    - name: "Linux/GCC/Shared/bionic"
      os: linux
      dist: bionic
      services:
        - xvfb
      compiler: gcc
      env:
        - BUILD_DIR=unix
      script: *x11gui
    - name: "Linux/GCC/Shared/xenial"
      os: linux
      dist: xenial
      services:
        - xvfb
      compiler: gcc
      env:
        - BUILD_DIR=unix
      script: *x11gui
    - name: "Linux/GCC/Static"
      os: linux
      dist: focal
      compiler: gcc
      env:
        - BUILD_DIR=unix
        - CFGOPT="--disable-shared"
    - name: "Linux/GCC/Debug"
      os: linux
      dist: focal
      compiler: gcc
      env:
        - BUILD_DIR=unix
        - CFGOPT="--enable-symbols"
    - name: "Linux/G++/Shared"
      os: linux
      dist: focal
      compiler: g++
      env:
        - BUILD_DIR=unix
        - CFGOPT="CC=g++ CFLAGS=-Dregister=dont+use+register"
    - name: "Linux/G++/Shared UTF_MAX=4"
      os: linux
      dist: focal
      compiler: g++
      env:
        - BUILD_DIR=unix
        - CFGOPT="CC=g++ CFLAGS=-DTCL_UTF_MAX=4"
    - name: "Linux/G++/Shared UTF_MAX=6"
      os: linux
      dist: focal
      compiler: g++
      env:
        - BUILD_DIR=unix
        - CFGOPT="CC=g++ CFLAGS=-DTCL_UTF_MAX=6"
# Newer/Older versions of GCC
    - name: "Linux/GCC 10/Shared"
      os: linux
      dist: focal
      compiler: gcc-6
      compiler: gcc-10
      addons:
        apt:
          sources:
            - ubuntu-toolchain-r-test
          packages:
            - g++-6
            - g++-10
      env:
        - BUILD_DIR=unix
    - name: "Linux/GCC 5/Shared"
      os: linux
      dist: bionic
      compiler: gcc-5
      addons:
        apt:
          sources:
            - ubuntu-toolchain-r-test
          packages:
            - g++-5
      env:
        - BUILD_DIR=unix
# Testing on Linux Clang
    - name: "Linux/Clang/Shared"
      os: linux
      dist: focal
      compiler: clang
      env:
        - BUILD_DIR=unix
    - name: "Linux/Clang/Shared: NO_DEPRECATED"
      os: linux
      dist: focal
      compiler: clang
      env:
        - BUILD_DIR=unix
        - CFGOPT="CFLAGS=-DTK_NO_DEPRECATED=1"
    - name: "Linux/Clang/Shared/no-xft"
      os: linux
      dist: focal
      compiler: clang
      env:
        - BUILD_DIR=unix
        - CFGOPT="--disable-xft"
    - name: "Linux/Clang/Static"
      os: linux
      dist: focal
      compiler: clang
      env:
        - CFGOPT="--disable-shared"
        - BUILD_DIR=unix
    - name: "Linux/Clang/Debug"
      os: linux
      dist: focal
      compiler: clang
      env:
        - BUILD_DIR=unix
        - CFGOPT="--enable-symbols"
# Testing on Mac, various styles
    - 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"
    - name: "macOS/Clang++/Xcode 12/Shared"
      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/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"
    - 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"
#   - 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"
    - name: "macOS/Xcode 10/Shared"
      os: osx
      osx_image: xcode10.3
      addons:
        homebrew:
          packages:
            - 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"
    - name: "macOS/Xcode 9/Shared"
      os: osx
      osx_image: xcode9.4
      addons:
        homebrew:
          packages:
            - 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"
# Test on Windows with MSVC native
#   - name: "Windows/MSVC/Shared"
#     os: windows
#     compiler: cl
#     env: &vcenv
#       - BUILD_DIR=win
#       - VCDIR="/C/Program Files (x86)/Microsoft Visual Studio/2017/BuildTools/VC/Auxiliary/Build"
#     before_install: &vcpreinst
#       - PATH="$PATH:$VCDIR"
#       - cd ${BUILD_DIR}
#     install: []
#     script:
#       - cmd.exe //C vcvarsall.bat x64 '&&' nmake '-f' makefile.vc all tktest
# "make dist" only
    - name: "Linux: make dist"
      os: linux
      dist: focal
      compiler: gcc
      env:
        - BUILD_DIR=unix
      script:
        - make dist
before_install:
  - |-
      case $TRAVIS_OS_NAME in
        windows)
          choco install -y magicsplat-tcl-tk
          ;;
      esac
  - cd ${BUILD_DIR}
install:
  - mkdir "$HOME/install dir"
  - ./configure ${CFGOPT} --prefix=$HOME || (cat config.log && exit 1)
  - ./configure ${CFGOPT} "--prefix=$HOME/install dir" || (cat config.log && exit 1)
before_script:
  - export ERROR_ON_FAILURES=1
script:
  - make all tktest
  - make binaries libraries 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
Changes to ChangeLog.
710
711
712
713
714
715
716
717

718
719
720
721
722
723
724
710
711
712
713
714
715
716

717
718
719
720
721
722
723
724







-
+







	* generic/tkObj.c (GetPixelsFromObjEx): [Bug 3431491]: Use a bit of
	type hackery to allow numbers to be interpreted as coordinates (most
	notably on a canvas) without reinterpreting via a string.

2011-10-27  Kevin B. Kenny  <[email protected]>

	* generic/tkInt.h:	[Bug 3410609]: Change the event mechanism
	* unix/tkUnixEvent.c:	for <KeyPress> events to use the keysym
	* unix/tkUnixEvent.c:	for <Key> events to use the keysym
	* unix/tkUnixKey.c:	returned by XLookupString in preference to
	the one that appears in the raw X event at any level. This change
	allows binding to ISO_Level3_Shift-ed characters, composed characters,
	and similar beasts. KeyRelease events still work as they did before,
	as does Tk with input methods disabled.

2011-10-13  Jan Nijtmans  <[email protected]>
5209
5210
5211
5212
5213
5214
5215
5216

5217
5218
5219
5220
5221
5222
5223
5209
5210
5211
5212
5213
5214
5215

5216
5217
5218
5219
5220
5221
5222
5223







-
+







2008-01-30  Donal K. Fellows  <[email protected]>

	* doc/canvas.n, doc/listbox.n, doc/message.n: [Bug 1882495]: Fix
	erroneous listing of "standard" options.

2008-01-29  Joe English  <[email protected]>

	* library/treeview.tcl: Fix bug in Shift-ButtonPress-1 binding (error
	* library/treeview.tcl: Fix bug in Shift-Button-1 binding (error
	if no current focus item; reported on c.l.t.)

2008-01-29  Donal K. Fellows  <[email protected]>

	* doc/ttk_*.n: [Bug 1876493]: Adjusted handling of the standard
	options part of the Ttk manual pages so that they are documented in
	the correct location.
Changes to ChangeLog.2002.
2234
2235
2236
2237
2238
2239
2240
2241

2242
2243
2244
2245
2246
2247
2248
2234
2235
2236
2237
2238
2239
2240

2241
2242
2243
2244
2245
2246
2247
2248







-
+







	Removed setting inputContext to null in Tk_MakeWindowExist as it
	was redundant.

	* unix/tkUnixWm.c (CreateWrapper): Removed redundat setting of
	inputContext to null.

	* win/Makefile.in: changed gdb and shell targets to properly build
	all binaries before running (otherwise an error often occured).
	all binaries before running (otherwise an error often occurred).

2002-03-28  David Gravereaux <[email protected]>

	* win/.cvsignore (new):
	* win/lamp.bmp (new):
	* win/makefile.vc:
	* win/nmakehlp.c (new):
Changes to ChangeLog.2004.
807
808
809
810
811
812
813
814

815
816
817
818
819
820
821
807
808
809
810
811
812
813

814
815
816
817
818
819
820
821







-
+








	* doc/canvas.n: Add paragraph to make clearer what is going on with the
	default canvas origin. [Bug 956681]

2004-07-05  George Peter Staplin <[email protected]>

	* generic/tkEvent.c: TK_XIM_SPOT preprocessor usage was modified
	slightly to fix a bug that occured when TK_XIM_SPOT was defined as 0.
	slightly to fix a bug that occurred when TK_XIM_SPOT was defined as 0.
	Thanks to Joe Mistachkin for reporting this bug.

2004-07-05  Donal K. Fellows  <[email protected]>

	TIP#158 IMPLEMENTATION

	* tests/bind.test:		   Allow Win apps to distinguish keys
3517
3518
3519
3520
3521
3522
3523
3524

3525
3526
3527
3528
3529
3530
3531
3517
3518
3519
3520
3521
3522
3523

3524
3525
3526
3527
3528
3529
3530
3531







-
+







	* win/configure.in:

	* unix/tcl.m4: correct HP-UX ia64 --enable-64bit build flags

2003-02-13  Kevin Kenny	 <[email protected]>

	* doc/wish.n: Added language to describe the handling of the
	end-of-file character \u001a in script files. [Bug 685505]
	end-of-file character \x1A in script files. [Bug 685505]

2003-02-10  Jim Ingham <[email protected]>

	* macosx/tkMacOSXCursor.c (TkMacOSXInstallCursor): Set all theme
	cursors using SetThemeCursor or SetAnimatedThemeCursors.
	(TkGetCursorByName): Use the theme cursors for arrow, ibeam, etc. Allow
	animatedCursor{NUM} form for an animated cursor with count.
Changes to README.md.
1
2
3

4
5
6
7









8
9
10
11
12
13
14
15

16
17
18
19
20
21

22
23
24
25
26
27

28
29
30
31
32
33
34
1
2

3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

24
25
26
27
28
29

30
31
32
33
34
35

36
37
38
39
40
41
42
43


-
+




+
+
+
+
+
+
+
+
+







-
+





-
+





-
+







# README:  Tk

This is the **Tk 8.6.10** source distribution.
This is the **Tk 8.7a4** 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)
<br>
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)

## <a id="intro">1.</a> 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.6 Web page](https://www.tcl.tk/software/tcltk/8.6.html)
this release, see [the Tcl/Tk 8.7 Web page](https://www.tcl.tk/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.

## <a id="tcl">2.</a> See Tcl README.md

Please see the README.md file that comes with the associated Tcl release
Changes to changes.
329
330
331
332
333
334
335
336

337
338
339
340
341
342
343
329
330
331
332
333
334
335

336
337
338
339
340
341
342
343







-
+







is necessary in order to allow several menu buttons to share the
same menu.
*** POTENTIAL INCOMPATIBILITY ***

4/12/92 (bug fix) Fixed core dump that occurred in tkError.c when
removing the first error record from the error list.

4/15/92 (bug fix) Fixed bug in tkBind.c that prevented <KeyPress-1>
4/15/92 (bug fix) Fixed bug in tkBind.c that prevented <Key-1>
event specifications from being processed correctly:  the "1" was
treated as a button name rather than a keysym.

4/18/92 (new feature) Added Tk_DefineCursor and Tk_UndefineCursor
procedures.

4/18/92 (new feature) Major revision to listboxes.  Can now scroll and
3484
3485
3486
3487
3488
3489
3490
3491

3492
3493
3494
3495
3496
3497
3498
3484
3485
3486
3487
3488
3489
3490

3491
3492
3493
3494
3495
3496
3497
3498







-
+








10/18/96 (new features) A -menu option has been added to the toplevel
widget command, which allows a menu to operate as a menubar. On the
Macintosh, the menubar is displayed accross the top of the main monitor,
just like with other applications. Under Windows and Unix, the menu is
attached to the toplevel window. Also, changed some semantics.
Tearoff menus will now reflect changes to the menu it was
torn off from, and are deleted when the master menu is
torn off from, and are deleted when the main menu is
deleted. Tearoffs also reflect more look-and-feel of the
platforms they are running on. (SRP)

10/31/96 (bug fix) Under Windows, missing system cursors would
generate an error instead of falling through to the Tk cursor of the
same name. (SS)

3994
3995
3996
3997
3998
3999
4000
4001

4002
4003
4004
4005
4006
4007
4008
3994
3995
3996
3997
3998
3999
4000

4001
4002
4003
4004
4005
4006
4007
4008







-
+







into account the "-displayof" option.  This problem also existed for the
"font metrics" and "font measure" commands. (CCS)

9/16/97 (new feature) Added "resource delete" and "resource files"
command to the Mac.  Also fixed "resource write" when the resource
was specified by id and already existed. (JI)

9/16/97 (bug fix) Added null bindings to <Command-KeyPress> for the
9/16/97 (bug fix) Added null bindings to <Command-Key> for the
text and entry widget on the Macintosh.  This prevents unbound command
key sequences from having the character echoed to the widget. Also
fixed Cut & Copy bindings.  (JI) (RJ)

9/18/97 (bug fix) Revamped Macintosh focus code.  Cut, Copy & Paste
virtual events now go to the correct (focus) window. (RJ)

5095
5096
5097
5098
5099
5100
5101
5102

5103
5104
5105
5106
5107
5108
5109
5095
5096
5097
5098
5099
5100
5101

5102
5103
5104
5105
5106
5107
5108
5109







-
+







correctly. (hobbs)

2001-08-28 (bug fix) fixed tk_chooseDirectory crash on Win95. (baker)

2001-08-28 (bug fix) removed 2 second 'raise' delay seen by some Unix
window managers. (hobbs, baker)

2001-09-14 (bug fix) fixed memory leaks that occured if errors were
2001-09-14 (bug fix) fixed memory leaks that occurred if errors were
thrown while initializing the channel for an image. (darley)

2001-09-20 (new feature) --enable-64bit support was added for HP 11 when
using the native compiler.

2001-10-03 (new feature) finalized Win64 support with latest RC1 release
and SDK. (hobbs, stacy)
7412
7413
7414
7415
7416
7417
7418























7419
7420
7421
7422
7423
7424
7425
7412
7413
7414
7415
7416
7417
7418
7419
7420
7421
7422
7423
7424
7425
7426
7427
7428
7429
7430
7431
7432
7433
7434
7435
7436
7437
7438
7439
7440
7441
7442
7443
7444
7445
7446
7447
7448







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








2017-08-08 (bug)[28d0b8] Follow ICCCM advice on X selection protocol (donchenko)

2017-08-08 (bug)[4966ca] Scidb race in notebook tab selection (cramer)

--- Released 8.6.7, August 9, 2017 --- https://core.tcl-lang.org/tk/ for details

Changes to 8.7a1 include all changes to the 8.6 line through 8.6.7,
plus the following, which focuses on the high-level feature changes
in this changeset (new minor version) rather than bug fixes:

2016-03-07 (feature)[841280] spinbox autoswap -to/-from to get ordering (vogel)

2016-03-27 (feature)[38dc27] Support <Button-6> & <Button-7> (nijtmans)

2016-08-29 (TIP 449) [text] undo/redo return character range (vogel)

2016-11-02 (feature) Removed undocumented command [tk_getFileType] (vogel)
        *** POTENTIAL INCOMPATIBILITY ***

2017-02-05 (bug)[c0dbdd] Compatibility fonts shadowed system fonts (vogel)

2017-03-21 (TIP 442) display text in a progressbar (zaumseil)

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

2017-08-24 (bug)[f1a3ca] Memory leak in [text] B-tree (edhume3)

2017-08-24 (bug)[ee40fd] Report [console] init errors (the)

2017-08-24 (bug)[3295446] Improve history visibility in [console] (goth)

2017-08-24 (bug) canvas closed polylines fully honor -joinstyle (vogel)
7500
7501
7502
7503
7504
7505
7506
7507

7508
7509
7510
7511
7512
7513
7514
7523
7524
7525
7526
7527
7528
7529

7530
7531
7532
7533
7534
7535
7536
7537







-
+








2017-12-31 (bug)[6525e1] encoding leak in tkMacOSXProcessFiles (werner)

2018-01-07 (bug)[925262] New option -state for ttk::scale (vogel)

2018-01-07 (bug)[fa8de7] Crash [ttk::checkbutton .x -variable {}] (werner)

2018-01-16 (bug)[382712] Crash in [event generate . <KeyPress>] (werner)
2018-01-16 (bug)[382712] Crash in [event generate . <Key>] (werner)

2018-01-19 (bug)[657c38] Crash in menu destroy with checkbutton entry (werner)

2018-01-25 (bug)[de156e] Deny PRIMARY selection access in safe interps (nash)

2018-01-28 (bug)[b68710] Fixes in [text] bindings (nash)

7536
7537
7538
7539
7540
7541
7542
7543

7544
7545
7546
7547
7548
7549
7550
7559
7560
7561
7562
7563
7564
7565

7566
7567
7568
7569
7570
7571
7572
7573







-
+








2018-07-04 (bug)[135696] Crash in [wm transient] (culler)

2018-07-04 (bug)[309b42] Improve ttk high-contrast-mode support (lemburg,vogel)

2018-07-17 (bug)[1088825] fix frame-2.17,3.9,3.10 on Mac (vogel)

2018-07-27 (bug)[fabed1] GIF photo support for "deferred clear code" (vogel)
2018-07-27 (bug)[fbaed1] GIF photo support for "deferred clear code" (vogel)

2018-08-08 (feature) Modern full-screen support on Mac OSX (walzer)

2018-08-12 (bug)[1875c1] scrollbar on Mac OSX (walzer)

2018-08-14 (bug)[1ba71a] KeyRelease events on Mac OSX(walzer)

7694
7695
7696
7697
7698
7699
7700





































7717
7718
7719
7720
7721
7722
7723
7724
7725
7726
7727
7728
7729
7730
7731
7732
7733
7734
7735
7736
7737
7738
7739
7740
7741
7742
7743
7744
7745
7746
7747
7748
7749
7750
7751
7752
7753
7754
7755
7756
7757
7758
7759
7760







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
2019-11-17 (bug)[53d280] [wm iconphoto] crash on empty image (culler)

2019-11-17 [90d555] workaround NSFontManager bad selections (culler)

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

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)
        *** POTENTIAL INCOMPATIBILITY ***

2017-12-07 [TIP 487] End support for pre-XP Windows (nijtmans)

2018-03-04 [TIP 489] New subcommand [$canvas image] (pitcher,vogel)

2018-05-13 [TIP 496] New options -placeholder* for entries (zaumseil,vogel)

2018-09-23 [TIP 517] New option -activerelief for menus (vogel)

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 <<NoMangedChild>> (oehlmann)

2019-04-14 [TIP 164] New subcommand [$canvas rotate] (fellows)

2019-04-14 [TIP 507] New photo image format 'svg' (zaumseil)

2019-04-14 [TIP 483] Record more configuration items (cassoff)

2019-04-14 [TIP 482] Record configured directory for demos (cassoff)

2019-05-25 [TIP 262] New frame options -backgroundimage, -tile (fellows)

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
Added compat/stdbool.h.





































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*===---- stdbool.h - Standard header for booleans -------------------------===
*
* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
* See https://llvm.org/LICENSE.txt for license information.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*
* Modified for use by pre-C99 compilers. (c) Jan Nijtmans.
*
*===-----------------------------------------------------------------------===
*/

#ifndef __STDBOOL_H
#define __STDBOOL_H

/* Don't define bool, true, and false in C++, except as a GNU extension. */
#ifndef __cplusplus
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
#define bool _Bool
#else
#define bool unsigned char
#endif
#define true 1
#define false 0
#elif defined(__GNUC__) && !defined(__STRICT_ANSI__)
/* Define _Bool as a GNU extension. */
#define _Bool bool
#if __cplusplus < 201103L
/* For C++98, define bool, false, true as a GNU extension. */
#define bool  bool
#define false false
#define true  true
#endif
#endif

#define __bool_true_false_are_defined 1

#endif /* __STDBOOL_H */
Added compat/stdint.h.























































































































































































































































































































































































































































































































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*  A portable stdint.h
 ****************************************************************************
 *  BSD License:
 ****************************************************************************
 *
 *  Copyright (c) 2005-2016 Paul Hsieh
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *  1. Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *  3. The name of the author may not be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 *  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************
 *
 *  Version 0.1.16.0
 *
 *  The ANSI C standard committee, for the C99 standard, specified the
 *  inclusion of a new standard include file called stdint.h.  This is
 *  a very useful and long desired include file which contains several
 *  very precise definitions for integer scalar types that is critically
 *  important for making several classes of applications portable
 *  including cryptography, hashing, variable length integer libraries
 *  and so on.  But for most developers its likely useful just for
 *  programming sanity.
 *
 *  The problem is that some compiler vendors chose to ignore the C99
 *  standard and some older compilers have no opportunity to be updated.
 *  Because of this situation, simply including stdint.h in your code
 *  makes it unportable.
 *
 *  So that's what this file is all about.  It's an attempt to build a
 *  single universal include file that works on as many platforms as
 *  possible to deliver what stdint.h is supposed to.  Even compilers
 *  that already come with stdint.h can use this file instead without
 *  any loss of functionality.  A few things that should be noted about
 *  this file:
 *
 *    1) It is not guaranteed to be portable and/or present an identical
 *       interface on all platforms.  The extreme variability of the
 *       ANSI C standard makes this an impossibility right from the
 *       very get go. Its really only meant to be useful for the vast
 *       majority of platforms that possess the capability of
 *       implementing usefully and precisely defined, standard sized
 *       integer scalars.  Systems which are not intrinsically 2s
 *       complement may produce invalid constants.
 *
 *    2) There is an unavoidable use of non-reserved symbols.
 *
 *    3) Other standard include files are invoked.
 *
 *    4) This file may come in conflict with future platforms that do
 *       include stdint.h.  The hope is that one or the other can be
 *       used with no real difference.
 *
 *    5) In the current version, if your platform can't represent
 *       int32_t, int16_t and int8_t, it just dumps out with a compiler
 *       error.
 *
 *    6) 64 bit integers may or may not be defined.  Test for their
 *       presence with the test: #ifdef INT64_MAX or #ifdef UINT64_MAX.
 *       Note that this is different from the C99 specification which
 *       requires the existence of 64 bit support in the compiler.  If
 *       this is not defined for your platform, yet it is capable of
 *       dealing with 64 bits then it is because this file has not yet
 *       been extended to cover all of your system's capabilities.
 *
 *    7) (u)intptr_t may or may not be defined.  Test for its presence
 *       with the test: #ifdef PTRDIFF_MAX.  If this is not defined
 *       for your platform, then it is because this file has not yet
 *       been extended to cover all of your system's capabilities, not
 *       because its optional.
 *
 *    8) The following might not been defined even if your platform is
 *       capable of defining it:
 *
 *       WCHAR_MIN
 *       WCHAR_MAX
 *       (u)int64_t
 *       PTRDIFF_MIN
 *       PTRDIFF_MAX
 *       (u)intptr_t
 *
 *    9) The following have not been defined:
 *
 *       WINT_MIN
 *       WINT_MAX
 *
 *   10) The criteria for defining (u)int_least(*)_t isn't clear,
 *       except for systems which don't have a type that precisely
 *       defined 8, 16, or 32 bit types (which this include file does
 *       not support anyways). Default definitions have been given.
 *
 *   11) The criteria for defining (u)int_fast(*)_t isn't something I
 *       would trust to any particular compiler vendor or the ANSI C
 *       committee.  It is well known that "compatible systems" are
 *       commonly created that have very different performance
 *       characteristics from the systems they are compatible with,
 *       especially those whose vendors make both the compiler and the
 *       system.  Default definitions have been given, but its strongly
 *       recommended that users never use these definitions for any
 *       reason (they do *NOT* deliver any serious guarantee of
 *       improved performance -- not in this file, nor any vendor's
 *       stdint.h).
 *
 *   12) The following macros:
 *
 *       PRINTF_INTMAX_MODIFIER
 *       PRINTF_INT64_MODIFIER
 *       PRINTF_INT32_MODIFIER
 *       PRINTF_INT16_MODIFIER
 *       PRINTF_LEAST64_MODIFIER
 *       PRINTF_LEAST32_MODIFIER
 *       PRINTF_LEAST16_MODIFIER
 *       PRINTF_INTPTR_MODIFIER
 *
 *       are strings which have been defined as the modifiers required
 *       for the "d", "u" and "x" printf formats to correctly output
 *       (u)intmax_t, (u)int64_t, (u)int32_t, (u)int16_t, (u)least64_t,
 *       (u)least32_t, (u)least16_t and (u)intptr_t types respectively.
 *       PRINTF_INTPTR_MODIFIER is not defined for some systems which
 *       provide their own stdint.h.  PRINTF_INT64_MODIFIER is not
 *       defined if INT64_MAX is not defined.  These are an extension
 *       beyond what C99 specifies must be in stdint.h.
 *
 *       In addition, the following macros are defined:
 *
 *       PRINTF_INTMAX_HEX_WIDTH
 *       PRINTF_INT64_HEX_WIDTH
 *       PRINTF_INT32_HEX_WIDTH
 *       PRINTF_INT16_HEX_WIDTH
 *       PRINTF_INT8_HEX_WIDTH
 *       PRINTF_INTMAX_DEC_WIDTH
 *       PRINTF_INT64_DEC_WIDTH
 *       PRINTF_INT32_DEC_WIDTH
 *       PRINTF_INT16_DEC_WIDTH
 *       PRINTF_UINT8_DEC_WIDTH
 *       PRINTF_UINTMAX_DEC_WIDTH
 *       PRINTF_UINT64_DEC_WIDTH
 *       PRINTF_UINT32_DEC_WIDTH
 *       PRINTF_UINT16_DEC_WIDTH
 *       PRINTF_UINT8_DEC_WIDTH
 *
 *       Which specifies the maximum number of characters required to
 *       print the number of that type in either hexadecimal or decimal.
 *       These are an extension beyond what C99 specifies must be in
 *       stdint.h.
 *
 *  Compilers tested (all with 0 warnings at their highest respective
 *  settings): Borland Turbo C 2.0, WATCOM C/C++ 11.0 (16 bits and 32
 *  bits), Microsoft Visual C++ 6.0 (32 bit), Microsoft Visual Studio
 *  .net (VC7), Intel C++ 4.0, GNU gcc v3.3.3
 *
 *  This file should be considered a work in progress.  Suggestions for
 *  improvements, especially those which increase coverage are strongly
 *  encouraged.
 *
 *  Acknowledgements
 *
 *  The following people have made significant contributions to the
 *  development and testing of this file:
 *
 *  Chris Howie
 *  John Steele Scott
 *  Dave Thorup
 *  John Dill
 *  Florian Wobbe
 *  Christopher Sean Morrison
 *  Mikkel Fahnoe Jorgensen
 *
 */

#include <stddef.h>
#include <limits.h>
#include <signal.h>

/*
 *  For gcc with _STDINT_H, fill in the PRINTF_INT*_MODIFIER macros, and
 *  do nothing else.  On the Mac OS X version of gcc this is _STDINT_H_.
 */

#if ((defined(__SUNPRO_C) && __SUNPRO_C >= 0x570) || (defined(_MSC_VER) && _MSC_VER >= 1600) || (defined(__STDC__) && __STDC__ && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || (defined (__WATCOMC__) && (defined (_STDINT_H_INCLUDED) || __WATCOMC__ >= 1250)) || (defined(__GNUC__) && (__GNUC__ > 3 || defined(_STDINT_H) || defined(_STDINT_H_) || defined (__UINT_FAST64_TYPE__)) )) && !defined (_PSTDINT_H_INCLUDED)
#include <stdint.h>
#define _PSTDINT_H_INCLUDED
# if defined(__GNUC__) && (defined(__x86_64__) || defined(__ppc64__)) && !(defined(__APPLE__) && defined(__MACH__))
#  ifndef PRINTF_INT64_MODIFIER
#   define PRINTF_INT64_MODIFIER "l"
#  endif
#  ifndef PRINTF_INT32_MODIFIER
#   define PRINTF_INT32_MODIFIER ""
#  endif
# else
#  ifndef PRINTF_INT64_MODIFIER
#   define PRINTF_INT64_MODIFIER "ll"
#  endif
#  ifndef PRINTF_INT32_MODIFIER
#   if (UINT_MAX == UINT32_MAX)
#    define PRINTF_INT32_MODIFIER ""
#   else
#    define PRINTF_INT32_MODIFIER "l"
#   endif
#  endif
# endif
# ifndef PRINTF_INT16_MODIFIER
#  define PRINTF_INT16_MODIFIER "h"
# endif
# ifndef PRINTF_INTMAX_MODIFIER
#  define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER
# endif
# ifndef PRINTF_INT64_HEX_WIDTH
#  define PRINTF_INT64_HEX_WIDTH "16"
# endif
# ifndef PRINTF_UINT64_HEX_WIDTH
#  define PRINTF_UINT64_HEX_WIDTH "16"
# endif
# ifndef PRINTF_INT32_HEX_WIDTH
#  define PRINTF_INT32_HEX_WIDTH "8"
# endif
# ifndef PRINTF_UINT32_HEX_WIDTH
#  define PRINTF_UINT32_HEX_WIDTH "8"
# endif
# ifndef PRINTF_INT16_HEX_WIDTH
#  define PRINTF_INT16_HEX_WIDTH "4"
# endif
# ifndef PRINTF_UINT16_HEX_WIDTH
#  define PRINTF_UINT16_HEX_WIDTH "4"
# endif
# ifndef PRINTF_INT8_HEX_WIDTH
#  define PRINTF_INT8_HEX_WIDTH "2"
# endif
# ifndef PRINTF_UINT8_HEX_WIDTH
#  define PRINTF_UINT8_HEX_WIDTH "2"
# endif
# ifndef PRINTF_INT64_DEC_WIDTH
#  define PRINTF_INT64_DEC_WIDTH "19"
# endif
# ifndef PRINTF_UINT64_DEC_WIDTH
#  define PRINTF_UINT64_DEC_WIDTH "20"
# endif
# ifndef PRINTF_INT32_DEC_WIDTH
#  define PRINTF_INT32_DEC_WIDTH "10"
# endif
# ifndef PRINTF_UINT32_DEC_WIDTH
#  define PRINTF_UINT32_DEC_WIDTH "10"
# endif
# ifndef PRINTF_INT16_DEC_WIDTH
#  define PRINTF_INT16_DEC_WIDTH "5"
# endif
# ifndef PRINTF_UINT16_DEC_WIDTH
#  define PRINTF_UINT16_DEC_WIDTH "5"
# endif
# ifndef PRINTF_INT8_DEC_WIDTH
#  define PRINTF_INT8_DEC_WIDTH "3"
# endif
# ifndef PRINTF_UINT8_DEC_WIDTH
#  define PRINTF_UINT8_DEC_WIDTH "3"
# endif
# ifndef PRINTF_INTMAX_HEX_WIDTH
#  define PRINTF_INTMAX_HEX_WIDTH PRINTF_UINT64_HEX_WIDTH
# endif
# ifndef PRINTF_UINTMAX_HEX_WIDTH
#  define PRINTF_UINTMAX_HEX_WIDTH PRINTF_UINT64_HEX_WIDTH
# endif
# ifndef PRINTF_INTMAX_DEC_WIDTH
#  define PRINTF_INTMAX_DEC_WIDTH PRINTF_UINT64_DEC_WIDTH
# endif
# ifndef PRINTF_UINTMAX_DEC_WIDTH
#  define PRINTF_UINTMAX_DEC_WIDTH PRINTF_UINT64_DEC_WIDTH
# endif

/*
 *  Something really weird is going on with Open Watcom.  Just pull some of
 *  these duplicated definitions from Open Watcom's stdint.h file for now.
 */

# if defined (__WATCOMC__) && __WATCOMC__ >= 1250
#  if !defined (INT64_C)
#   define INT64_C(x)   (x + (INT64_MAX - INT64_MAX))
#  endif
#  if !defined (UINT64_C)
#   define UINT64_C(x)  (x + (UINT64_MAX - UINT64_MAX))
#  endif
#  if !defined (INT32_C)
#   define INT32_C(x)   (x + (INT32_MAX - INT32_MAX))
#  endif
#  if !defined (UINT32_C)
#   define UINT32_C(x)  (x + (UINT32_MAX - UINT32_MAX))
#  endif
#  if !defined (INT16_C)
#   define INT16_C(x)   (x)
#  endif
#  if !defined (UINT16_C)
#   define UINT16_C(x)  (x)
#  endif
#  if !defined (INT8_C)
#   define INT8_C(x)   (x)
#  endif
#  if !defined (UINT8_C)
#   define UINT8_C(x)  (x)
#  endif
#  if !defined (UINT64_MAX)
#   define UINT64_MAX  18446744073709551615ULL
#  endif
#  if !defined (INT64_MAX)
#   define INT64_MAX  9223372036854775807LL
#  endif
#  if !defined (UINT32_MAX)
#   define UINT32_MAX  4294967295UL
#  endif
#  if !defined (INT32_MAX)
#   define INT32_MAX  2147483647L
#  endif
#  if !defined (INTMAX_MAX)
#   define INTMAX_MAX INT64_MAX
#  endif
#  if !defined (INTMAX_MIN)
#   define INTMAX_MIN INT64_MIN
#  endif
# endif
#endif

/*
 *  I have no idea what is the truly correct thing to do on older Solaris.
 *  From some online discussions, this seems to be what is being
 *  recommended.  For people who actually are developing on older Solaris,
 *  what I would like to know is, does this define all of the relevant
 *  macros of a complete stdint.h?  Remember, in pstdint.h 64 bit is
 *  considered optional.
 */

#if (defined(__SUNPRO_C) && __SUNPRO_C >= 0x420) && !defined(_PSTDINT_H_INCLUDED)
#include <sys/inttypes.h>
#define _PSTDINT_H_INCLUDED
#endif

#ifndef _PSTDINT_H_INCLUDED
#define _PSTDINT_H_INCLUDED

#ifndef SIZE_MAX
# define SIZE_MAX ((size_t)-1)
#endif

/*
 *  Deduce the type assignments from limits.h under the assumption that
 *  integer sizes in bits are powers of 2, and follow the ANSI
 *  definitions.
 */

#ifndef UINT8_MAX
# define UINT8_MAX 0xff
#endif
#if !defined(uint8_t) && !defined(_UINT8_T) && !defined(vxWorks)
# if (UCHAR_MAX == UINT8_MAX) || defined (S_SPLINT_S)
    typedef unsigned char uint8_t;
#   define UINT8_C(v) ((uint8_t) v)
# else
#   error "Platform not supported"
# endif
#endif

#ifndef INT8_MAX
# define INT8_MAX 0x7f
#endif
#ifndef INT8_MIN
# define INT8_MIN INT8_C(0x80)
#endif
#if !defined(int8_t) && !defined(_INT8_T) && !defined(vxWorks)
# if (SCHAR_MAX == INT8_MAX) || defined (S_SPLINT_S)
    typedef signed char int8_t;
#   define INT8_C(v) ((int8_t) v)
# else
#   error "Platform not supported"
# endif
#endif

#ifndef UINT16_MAX
# define UINT16_MAX 0xffff
#endif
#if !defined(uint16_t) && !defined(_UINT16_T) && !defined(vxWorks)
#if (UINT_MAX == UINT16_MAX) || defined (S_SPLINT_S)
  typedef unsigned int uint16_t;
# ifndef PRINTF_INT16_MODIFIER
#  define PRINTF_INT16_MODIFIER ""
# endif
# define UINT16_C(v) ((uint16_t) (v))
#elif (USHRT_MAX == UINT16_MAX)
  typedef unsigned short uint16_t;
# define UINT16_C(v) ((uint16_t) (v))
# ifndef PRINTF_INT16_MODIFIER
#  define PRINTF_INT16_MODIFIER "h"
# endif
#else
#error "Platform not supported"
#endif
#endif

#ifndef INT16_MAX
# define INT16_MAX 0x7fff
#endif
#ifndef INT16_MIN
# define INT16_MIN INT16_C(0x8000)
#endif
#if !defined(int16_t) && !defined(_INT16_T) && !defined(vxWorks)
#if (INT_MAX == INT16_MAX) || defined (S_SPLINT_S)
  typedef signed int int16_t;
# define INT16_C(v) ((int16_t) (v))
# ifndef PRINTF_INT16_MODIFIER
#  define PRINTF_INT16_MODIFIER ""
# endif
#elif (SHRT_MAX == INT16_MAX)
  typedef signed short int16_t;
# define INT16_C(v) ((int16_t) (v))
# ifndef PRINTF_INT16_MODIFIER
#  define PRINTF_INT16_MODIFIER "h"
# endif
#else
#error "Platform not supported"
#endif
#endif

#ifndef UINT32_MAX
# define UINT32_MAX (0xffffffffUL)
#endif
#if !defined(uint32_t) && !defined(_UINT32_T) && !defined(vxWorks)
#if (ULONG_MAX == UINT32_MAX) || defined (S_SPLINT_S)
  typedef unsigned long uint32_t;
# define UINT32_C(v) v ## UL
# ifndef PRINTF_INT32_MODIFIER
#  define PRINTF_INT32_MODIFIER "l"
# endif
#elif (UINT_MAX == UINT32_MAX)
  typedef unsigned int uint32_t;
# ifndef PRINTF_INT32_MODIFIER
#  define PRINTF_INT32_MODIFIER ""
# endif
# define UINT32_C(v) v ## U
#elif (USHRT_MAX == UINT32_MAX)
  typedef unsigned short uint32_t;
# define UINT32_C(v) ((unsigned short) (v))
# ifndef PRINTF_INT32_MODIFIER
#  define PRINTF_INT32_MODIFIER ""
# endif
#else
#error "Platform not supported"
#endif
#endif

#ifndef INT32_MAX
# define INT32_MAX (0x7fffffffL)
#endif
#ifndef INT32_MIN
# define INT32_MIN INT32_C(0x80000000)
#endif
#if !defined(int32_t) && !defined(_INT32_T) && !defined(vxWorks)
#if (LONG_MAX == INT32_MAX) || defined (S_SPLINT_S)
  typedef signed long int32_t;
# define INT32_C(v) v ## L
# ifndef PRINTF_INT32_MODIFIER
#  define PRINTF_INT32_MODIFIER "l"
# endif
#elif (INT_MAX == INT32_MAX)
  typedef signed int int32_t;
# define INT32_C(v) v
# ifndef PRINTF_INT32_MODIFIER
#  define PRINTF_INT32_MODIFIER ""
# endif
#elif (SHRT_MAX == INT32_MAX)
  typedef signed short int32_t;
# define INT32_C(v) ((short) (v))
# ifndef PRINTF_INT32_MODIFIER
#  define PRINTF_INT32_MODIFIER ""
# endif
#else
#error "Platform not supported"
#endif
#endif

/*
 *  The macro stdint_int64_defined is temporarily used to record
 *  whether or not 64 integer support is available.  It must be
 *  defined for any 64 integer extensions for new platforms that are
 *  added.
 */

#undef stdint_int64_defined
#if (defined(__STDC__) && defined(__STDC_VERSION__)) || defined (S_SPLINT_S)
# if (__STDC__ && __STDC_VERSION__ >= 199901L) || defined (S_SPLINT_S)
#  define stdint_int64_defined
   typedef long long int64_t;
   typedef unsigned long long uint64_t;
#  define UINT64_C(v) v ## ULL
#  define  INT64_C(v) v ## LL
#  ifndef PRINTF_INT64_MODIFIER
#   define PRINTF_INT64_MODIFIER "ll"
#  endif
# endif
#endif

#if !defined (stdint_int64_defined)
# if defined(__GNUC__) && !defined(vxWorks)
#  define stdint_int64_defined
   __extension__ typedef long long int64_t;
   __extension__ typedef unsigned long long uint64_t;
#  define UINT64_C(v) v ## ULL
#  define  INT64_C(v) v ## LL
#  ifndef PRINTF_INT64_MODIFIER
#   define PRINTF_INT64_MODIFIER "ll"
#  endif
# elif defined(__MWERKS__) || defined (__SUNPRO_C) || defined (__SUNPRO_CC) || defined (__APPLE_CC__) || defined (_LONG_LONG) || defined (_CRAYC) || defined (S_SPLINT_S)
#  define stdint_int64_defined
   typedef long long int64_t;
   typedef unsigned long long uint64_t;
#  define UINT64_C(v) v ## ULL
#  define  INT64_C(v) v ## LL
#  ifndef PRINTF_INT64_MODIFIER
#   define PRINTF_INT64_MODIFIER "ll"
#  endif
# elif (defined(__WATCOMC__) && defined(__WATCOM_INT64__)) || (defined(_MSC_VER) && _INTEGRAL_MAX_BITS >= 64) || (defined (__BORLANDC__) && __BORLANDC__ > 0x460) || defined (__alpha) || defined (__DECC)
#  define stdint_int64_defined
   typedef __int64 int64_t;
   typedef unsigned __int64 uint64_t;
#  define UINT64_C(v) v ## UI64
#  define  INT64_C(v) v ## I64
#  ifndef PRINTF_INT64_MODIFIER
#   define PRINTF_INT64_MODIFIER "I64"
#  endif
# endif
#endif

#if !defined (LONG_LONG_MAX) && defined (INT64_C)
# define LONG_LONG_MAX INT64_C (9223372036854775807)
#endif
#ifndef ULONG_LONG_MAX
# define ULONG_LONG_MAX UINT64_C (18446744073709551615)
#endif

#if !defined (INT64_MAX) && defined (INT64_C)
# define INT64_MAX INT64_C (9223372036854775807)
#endif
#if !defined (INT64_MIN) && defined (INT64_C)
# define INT64_MIN INT64_C (-9223372036854775808)
#endif
#if !defined (UINT64_MAX) && defined (INT64_C)
# define UINT64_MAX UINT64_C (18446744073709551615)
#endif

/*
 *  Width of hexadecimal for number field.
 */

#ifndef PRINTF_INT64_HEX_WIDTH
# define PRINTF_INT64_HEX_WIDTH "16"
#endif
#ifndef PRINTF_INT32_HEX_WIDTH
# define PRINTF_INT32_HEX_WIDTH "8"
#endif
#ifndef PRINTF_INT16_HEX_WIDTH
# define PRINTF_INT16_HEX_WIDTH "4"
#endif
#ifndef PRINTF_INT8_HEX_WIDTH
# define PRINTF_INT8_HEX_WIDTH "2"
#endif
#ifndef PRINTF_INT64_DEC_WIDTH
# define PRINTF_INT64_DEC_WIDTH "19"
#endif
#ifndef PRINTF_INT32_DEC_WIDTH
# define PRINTF_INT32_DEC_WIDTH "10"
#endif
#ifndef PRINTF_INT16_DEC_WIDTH
# define PRINTF_INT16_DEC_WIDTH "5"
#endif
#ifndef PRINTF_INT8_DEC_WIDTH
# define PRINTF_INT8_DEC_WIDTH "3"
#endif
#ifndef PRINTF_UINT64_DEC_WIDTH
# define PRINTF_UINT64_DEC_WIDTH "20"
#endif
#ifndef PRINTF_UINT32_DEC_WIDTH
# define PRINTF_UINT32_DEC_WIDTH "10"
#endif
#ifndef PRINTF_UINT16_DEC_WIDTH
# define PRINTF_UINT16_DEC_WIDTH "5"
#endif
#ifndef PRINTF_UINT8_DEC_WIDTH
# define PRINTF_UINT8_DEC_WIDTH "3"
#endif

/*
 *  Ok, lets not worry about 128 bit integers for now.  Moore's law says
 *  we don't need to worry about that until about 2040 at which point
 *  we'll have bigger things to worry about.
 */

#ifdef stdint_int64_defined
  typedef int64_t intmax_t;
  typedef uint64_t uintmax_t;
# define  INTMAX_MAX   INT64_MAX
# define  INTMAX_MIN   INT64_MIN
# define UINTMAX_MAX  UINT64_MAX
# define UINTMAX_C(v) UINT64_C(v)
# define  INTMAX_C(v)  INT64_C(v)
# ifndef PRINTF_INTMAX_MODIFIER
#   define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER
# endif
# ifndef PRINTF_INTMAX_HEX_WIDTH
#  define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH
# endif
# ifndef PRINTF_INTMAX_DEC_WIDTH
#  define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH
# endif
#else
  typedef int32_t intmax_t;
  typedef uint32_t uintmax_t;
# define  INTMAX_MAX   INT32_MAX
# define UINTMAX_MAX  UINT32_MAX
# define UINTMAX_C(v) UINT32_C(v)
# define  INTMAX_C(v)  INT32_C(v)
# ifndef PRINTF_INTMAX_MODIFIER
#   define PRINTF_INTMAX_MODIFIER PRINTF_INT32_MODIFIER
# endif
# ifndef PRINTF_INTMAX_HEX_WIDTH
#  define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT32_HEX_WIDTH
# endif
# ifndef PRINTF_INTMAX_DEC_WIDTH
#  define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT32_DEC_WIDTH
# endif
#endif

/*
 *  Because this file currently only supports platforms which have
 *  precise powers of 2 as bit sizes for the default integers, the
 *  least definitions are all trivial.  Its possible that a future
 *  version of this file could have different definitions.
 */

#ifndef stdint_least_defined
  typedef   int8_t   int_least8_t;
  typedef  uint8_t  uint_least8_t;
  typedef  int16_t  int_least16_t;
  typedef uint16_t uint_least16_t;
  typedef  int32_t  int_least32_t;
  typedef uint32_t uint_least32_t;
# define PRINTF_LEAST32_MODIFIER PRINTF_INT32_MODIFIER
# define PRINTF_LEAST16_MODIFIER PRINTF_INT16_MODIFIER
# define  UINT_LEAST8_MAX  UINT8_MAX
# define   INT_LEAST8_MAX   INT8_MAX
# define UINT_LEAST16_MAX UINT16_MAX
# define  INT_LEAST16_MAX  INT16_MAX
# define UINT_LEAST32_MAX UINT32_MAX
# define  INT_LEAST32_MAX  INT32_MAX
# define   INT_LEAST8_MIN   INT8_MIN
# define  INT_LEAST16_MIN  INT16_MIN
# define  INT_LEAST32_MIN  INT32_MIN
# ifdef stdint_int64_defined
    typedef  int64_t  int_least64_t;
    typedef uint64_t uint_least64_t;
#   define PRINTF_LEAST64_MODIFIER PRINTF_INT64_MODIFIER
#   define UINT_LEAST64_MAX UINT64_MAX
#   define  INT_LEAST64_MAX  INT64_MAX
#   define  INT_LEAST64_MIN  INT64_MIN
# endif
#endif
#undef stdint_least_defined

/*
 *  The ANSI C committee has defined *int*_fast*_t types as well.  This,
 *  of course, defies rationality -- you can't know what will be fast
 *  just from the type itself.  Even for a given architecture, compatible
 *  implementations might have different performance characteristics.
 *  Developers are warned to stay away from these types when using this
 *  or any other stdint.h.
 */

typedef   int_least8_t   int_fast8_t;
typedef  uint_least8_t  uint_fast8_t;
typedef  int_least16_t  int_fast16_t;
typedef uint_least16_t uint_fast16_t;
typedef  int_least32_t  int_fast32_t;
typedef uint_least32_t uint_fast32_t;
#define  UINT_FAST8_MAX  UINT_LEAST8_MAX
#define   INT_FAST8_MAX   INT_LEAST8_MAX
#define UINT_FAST16_MAX UINT_LEAST16_MAX
#define  INT_FAST16_MAX  INT_LEAST16_MAX
#define UINT_FAST32_MAX UINT_LEAST32_MAX
#define  INT_FAST32_MAX  INT_LEAST32_MAX
#define   INT_FAST8_MIN   INT_LEAST8_MIN
#define  INT_FAST16_MIN  INT_LEAST16_MIN
#define  INT_FAST32_MIN  INT_LEAST32_MIN
#ifdef stdint_int64_defined
  typedef  int_least64_t  int_fast64_t;
  typedef uint_least64_t uint_fast64_t;
# define UINT_FAST64_MAX UINT_LEAST64_MAX
# define  INT_FAST64_MAX  INT_LEAST64_MAX
# define  INT_FAST64_MIN  INT_LEAST64_MIN
#endif

#undef stdint_int64_defined

/*
 *  Whatever piecemeal, per compiler thing we can do about the wchar_t
 *  type limits.
 */

#if defined(__WATCOMC__) || defined(_MSC_VER) || defined (__GNUC__) && !defined(vxWorks)
# include <wchar.h>
# ifndef WCHAR_MIN
#  define WCHAR_MIN 0
# endif
# ifndef WCHAR_MAX
#  define WCHAR_MAX ((wchar_t)-1)
# endif
#endif

/*
 *  Whatever piecemeal, per compiler/platform thing we can do about the
 *  (u)intptr_t types and limits.
 */

#if (defined (_MSC_VER) && defined (_UINTPTR_T_DEFINED)) || defined (_UINTPTR_T)
# define STDINT_H_UINTPTR_T_DEFINED
#endif

#ifndef STDINT_H_UINTPTR_T_DEFINED
# if defined (__alpha__) || defined (__ia64__) || defined (__x86_64__) || defined (_WIN64) || defined (__ppc64__)
#  define stdint_intptr_bits 64
# elif defined (__WATCOMC__) || defined (__TURBOC__)
#  if defined(__TINY__) || defined(__SMALL__) || defined(__MEDIUM__)
#    define stdint_intptr_bits 16
#  else
#    define stdint_intptr_bits 32
#  endif
# elif defined (__i386__) || defined (_WIN32) || defined (WIN32) || defined (__ppc64__)
#  define stdint_intptr_bits 32
# elif defined (__INTEL_COMPILER)
/* TODO -- what did Intel do about x86-64? */
# else
/* #error "This platform might not be supported yet" */
# endif

# ifdef stdint_intptr_bits
#  define stdint_intptr_glue3_i(a,b,c)  a##b##c
#  define stdint_intptr_glue3(a,b,c)    stdint_intptr_glue3_i(a,b,c)
#  ifndef PRINTF_INTPTR_MODIFIER
#    define PRINTF_INTPTR_MODIFIER      stdint_intptr_glue3(PRINTF_INT,stdint_intptr_bits,_MODIFIER)
#  endif
#  ifndef PTRDIFF_MAX
#    define PTRDIFF_MAX                 stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX)
#  endif
#  ifndef PTRDIFF_MIN
#    define PTRDIFF_MIN                 stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN)
#  endif
#  ifndef UINTPTR_MAX
#    define UINTPTR_MAX                 stdint_intptr_glue3(UINT,stdint_intptr_bits,_MAX)
#  endif
#  ifndef INTPTR_MAX
#    define INTPTR_MAX                  stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX)
#  endif
#  ifndef INTPTR_MIN
#    define INTPTR_MIN                  stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN)
#  endif
#  ifndef INTPTR_C
#    define INTPTR_C(x)                 stdint_intptr_glue3(INT,stdint_intptr_bits,_C)(x)
#  endif
#  ifndef UINTPTR_C
#    define UINTPTR_C(x)                stdint_intptr_glue3(UINT,stdint_intptr_bits,_C)(x)
#  endif
  typedef stdint_intptr_glue3(uint,stdint_intptr_bits,_t) uintptr_t;
  typedef stdint_intptr_glue3( int,stdint_intptr_bits,_t)  intptr_t;
# else
/* TODO -- This following is likely wrong for some platforms, and does
   nothing for the definition of uintptr_t. */
  typedef ptrdiff_t intptr_t;
# endif
# define STDINT_H_UINTPTR_T_DEFINED
#endif

/*
 *  Assumes sig_atomic_t is signed and we have a 2s complement machine.
 */

#ifndef SIG_ATOMIC_MAX
# define SIG_ATOMIC_MAX ((((sig_atomic_t) 1) << (sizeof (sig_atomic_t)*CHAR_BIT-1)) - 1)
#endif

#endif

#if defined (__TEST_PSTDINT_FOR_CORRECTNESS)

/*
 *  Please compile with the maximum warning settings to make sure macros are
 *  not defined more than once.
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define glue3_aux(x,y,z) x ## y ## z
#define glue3(x,y,z) glue3_aux(x,y,z)

#define DECLU(bits) glue3(uint,bits,_t) glue3(u,bits,) = glue3(UINT,bits,_C) (0);
#define DECLI(bits) glue3(int,bits,_t) glue3(i,bits,) = glue3(INT,bits,_C) (0);

#define DECL(us,bits) glue3(DECL,us,) (bits)

#define TESTUMAX(bits) glue3(u,bits,) = ~glue3(u,bits,); if (glue3(UINT,bits,_MAX) != glue3(u,bits,)) printf ("Something wrong with UINT%d_MAX\n", bits)

#define REPORTERROR(msg) { err_n++; if (err_first <= 0) err_first = __LINE__; printf msg; }

#define X_SIZE_MAX ((size_t)-1)

int main () {
	int err_n = 0;
	int err_first = 0;
	DECL(I,8)
	DECL(U,8)
	DECL(I,16)
	DECL(U,16)
	DECL(I,32)
	DECL(U,32)
#ifdef INT64_MAX
	DECL(I,64)
	DECL(U,64)
#endif
	intmax_t imax = INTMAX_C(0);
	uintmax_t umax = UINTMAX_C(0);
	char str0[256], str1[256];

	sprintf (str0, "%" PRINTF_INT32_MODIFIER "d", INT32_C(2147483647));
	if (0 != strcmp (str0, "2147483647")) REPORTERROR (("Something wrong with PRINTF_INT32_MODIFIER : %s\n", str0));
	if (atoi(PRINTF_INT32_DEC_WIDTH) != (int) strlen(str0)) REPORTERROR (("Something wrong with PRINTF_INT32_DEC_WIDTH : %s\n", PRINTF_INT32_DEC_WIDTH));
	sprintf (str0, "%" PRINTF_INT32_MODIFIER "u", UINT32_C(4294967295));
	if (0 != strcmp (str0, "4294967295")) REPORTERROR (("Something wrong with PRINTF_INT32_MODIFIER : %s\n", str0));
	if (atoi(PRINTF_UINT32_DEC_WIDTH) != (int) strlen(str0)) REPORTERROR (("Something wrong with PRINTF_UINT32_DEC_WIDTH : %s\n", PRINTF_UINT32_DEC_WIDTH));
#ifdef INT64_MAX
	sprintf (str1, "%" PRINTF_INT64_MODIFIER "d", INT64_C(9223372036854775807));
	if (0 != strcmp (str1, "9223372036854775807")) REPORTERROR (("Something wrong with PRINTF_INT32_MODIFIER : %s\n", str1));
	if (atoi(PRINTF_INT64_DEC_WIDTH) != (int) strlen(str1)) REPORTERROR (("Something wrong with PRINTF_INT64_DEC_WIDTH : %s, %d\n", PRINTF_INT64_DEC_WIDTH, (int) strlen(str1)));
	sprintf (str1, "%" PRINTF_INT64_MODIFIER "u", UINT64_C(18446744073709550591));
	if (0 != strcmp (str1, "18446744073709550591")) REPORTERROR (("Something wrong with PRINTF_INT32_MODIFIER : %s\n", str1));
	if (atoi(PRINTF_UINT64_DEC_WIDTH) != (int) strlen(str1)) REPORTERROR (("Something wrong with PRINTF_UINT64_DEC_WIDTH : %s, %d\n", PRINTF_UINT64_DEC_WIDTH, (int) strlen(str1)));
#endif

	sprintf (str0, "%d %x\n", 0, ~0);

	sprintf (str1, "%d %x\n",  i8, ~0);
	if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with i8 : %s\n", str1));
	sprintf (str1, "%u %x\n",  u8, ~0);
	if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with u8 : %s\n", str1));
	sprintf (str1, "%d %x\n",  i16, ~0);
	if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with i16 : %s\n", str1));
	sprintf (str1, "%u %x\n",  u16, ~0);
	if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with u16 : %s\n", str1));
	sprintf (str1, "%" PRINTF_INT32_MODIFIER "d %x\n",  i32, ~0);
	if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with i32 : %s\n", str1));
	sprintf (str1, "%" PRINTF_INT32_MODIFIER "u %x\n",  u32, ~0);
	if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with u32 : %s\n", str1));
#ifdef INT64_MAX
	sprintf (str1, "%" PRINTF_INT64_MODIFIER "d %x\n",  i64, ~0);
	if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with i64 : %s\n", str1));
#endif
	sprintf (str1, "%" PRINTF_INTMAX_MODIFIER "d %x\n",  imax, ~0);
	if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with imax : %s\n", str1));
	sprintf (str1, "%" PRINTF_INTMAX_MODIFIER "u %x\n",  umax, ~0);
	if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with umax : %s\n", str1));

	TESTUMAX(8);
	TESTUMAX(16);
	TESTUMAX(32);
#ifdef INT64_MAX
	TESTUMAX(64);
#endif

#define STR(v) #v
#define Q(v) printf ("sizeof " STR(v) " = %u\n", (unsigned) sizeof (v));
	if (err_n) {
		printf ("pstdint.h is not correct.  Please use sizes below to correct it:\n");
	}

	Q(int)
	Q(unsigned)
	Q(long int)
	Q(short int)
	Q(int8_t)
	Q(int16_t)
	Q(int32_t)
#ifdef INT64_MAX
	Q(int64_t)
#endif

#if UINT_MAX < X_SIZE_MAX
	printf ("UINT_MAX < X_SIZE_MAX\n");
#else
	printf ("UINT_MAX >= X_SIZE_MAX\n");
#endif
	printf ("%" PRINTF_INT64_MODIFIER "u vs %" PRINTF_INT64_MODIFIER "u\n", UINT_MAX, X_SIZE_MAX);

	return EXIT_SUCCESS;
}

#endif
Deleted compat/stdlib.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40








































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*
 * stdlib.h --
 *
 *	Declares facilities exported by the "stdlib" portion of the C library.
 *	This file isn't complete in the ANSI-C sense; it only declares things
 *	that are needed by Tk. This file is needed even on many systems with
 *	their own stdlib.h (e.g. SunOS) because not all stdlib.h files declare
 *	all the procedures needed here (such as strtod).
 *
 * Copyright (c) 1991 The Regents of the University of California.
 * Copyright (c) 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.
 */

#ifndef _STDLIB
#define _STDLIB

#ifndef _TCL
#   include <tcl.h>
#endif

extern void		abort(void);
extern double		atof(const char *string);
extern int		atoi(const char *string);
extern long		atol(const char *string);
extern char *		calloc(unsigned int numElements, unsigned int size);
extern void		exit(int status);
extern int		free(char *blockPtr);
extern char *		getenv(const char *name);
extern char *		malloc(unsigned int numBytes);
extern void		qsort(void *base, int n, int size, int (*compar)(
			    const void *element1, const void *element2));
extern char *		realloc(char *ptr, unsigned int numBytes);
extern double		strtod(const char *string, char **endPtr);
extern long		strtol(const char *string, char **endPtr, int base);
extern unsigned long	strtoul(const char *string, char **endPtr, int base);

#endif /* _STDLIB */
Deleted compat/unistd.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
















































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*
 * unistd.h --
 *
 *      Macros, constants and prototypes for Posix conformance.
 *
 * Copyright 1989 Regents of the University of California Permission to use,
 * copy, modify, and distribute this software and its documentation for any
 * purpose and without fee is hereby granted, provided that the above
 * copyright notice appear in all copies. The University of California makes
 * no representations about the suitability of this software for any purpose.
 * It is provided "as is" without express or implied warranty.
 */

#ifndef _UNISTD
#define _UNISTD

#include <sys/types.h>
#ifndef _TCL
#   include <tcl.h>
#endif

#ifndef NULL
#define NULL    0
#endif

/*
 * Strict POSIX stuff goes here. Extensions go down below, in the ifndef
 * _POSIX_SOURCE section.
 */

extern void		_exit(int status);
extern int		access(const char *path, int mode);
extern int		chdir(const char *path);
extern int		chown(const char *path, uid_t owner, gid_t group);
extern int		close(int fd);
extern int		dup(int oldfd);
extern int		dup2(int oldfd, int newfd);
extern int		execl(const char *path, ...);
extern int		execle(const char *path, ...);
extern int		execlp(const char *file, ...);
extern int		execv(const char *path, char **argv);
extern int		execve(const char *path, char **argv, char **envp);
extern int		execvp(const char *file, char **argv);
extern pid_t		fork(void);
extern char *		getcwd(char *buf, size_t size);
extern gid_t		getegid(void);
extern uid_t		geteuid(void);
extern gid_t		getgid(void);
extern int		getgroups(int bufSize, int *buffer);
extern pid_t		getpid(void);
extern uid_t		getuid(void);
extern int		isatty(int fd);
extern long		lseek(int fd, long offset, int whence);
extern int		pipe(int *fildes);
extern int		read(int fd, char *buf, size_t size);
extern int		setgid(gid_t group);
extern int		setuid(uid_t user);
extern unsigned		sleep(unsigned seconds);
extern char *		ttyname(int fd);
extern int		unlink(const char *path);
extern int		write(int fd, const char *buf, size_t size);

#ifndef	_POSIX_SOURCE
extern char *		crypt(const char *, const char *);
extern int		fchown(int fd, uid_t owner, gid_t group);
extern int		flock(int fd, int operation);
extern int		ftruncate(int fd, unsigned long length);
extern int		ioctl(int fd, int request, ...);
extern int		readlink(const char *path, char *buf, int bufsize);
extern int		setegid(gid_t group);
extern int		seteuid(uid_t user);
extern int		setreuid(int ruid, int euid);
extern int		symlink(const char *, const char *);
extern int		ttyslot(void);
extern int		truncate(const char *path, unsigned long length);
extern int		vfork(void);
#endif /* _POSIX_SOURCE */

#endif /* _UNISTD */

Changes to doc/3DBorder.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1990-1993 The Regents of the University of California.
'\" Copyright (c) 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.
'\" 
'\"
.TH Tk_Alloc3DBorderFromObj 3 8.1 Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_Alloc3DBorderFromObj, Tk_Get3DBorder, Tk_Get3DBorderFromObj, Tk_Draw3DRectangle, Tk_Fill3DRectangle, Tk_Draw3DPolygon, Tk_Fill3DPolygon, Tk_3DVerticalBevel, Tk_3DHorizontalBevel, Tk_SetBackgroundFromBorder, Tk_NameOf3DBorder, Tk_3DBorderColor, Tk_3DBorderGC, Tk_Free3DBorderFromObj, Tk_Free3DBorder \- draw borders with three-dimensional appearance
.SH SYNOPSIS
.nf
Changes to doc/AddOption.3.
1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







'\"
'\" 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
.SH NAME
Tk_AddOption \- Add an option to the option database
Changes to doc/BindTable.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1994 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH Tk_CreateBindingTable 3 4.0 Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_CreateBindingTable, Tk_DeleteBindingTable, Tk_CreateBinding, Tk_DeleteBinding, Tk_GetBinding, Tk_GetAllBindings, Tk_DeleteAllBindings, Tk_BindEvent \- invoke scripts in response to X events
.SH SYNOPSIS
.nf
Changes to doc/CanvPsY.3.
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







'\"
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH Tk_CanvasPs 3 4.0 Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_CanvasPsY, Tk_CanvasPsBitmap, Tk_CanvasPsColor, Tk_CanvasPsFont, Tk_CanvasPsPath, Tk_CanvasPsStipple \- utility procedures for generating Postscript for canvases
.SH SYNOPSIS
.nf
Changes to doc/CanvTkwin.3.
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







'\"
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH Tk_CanvasTkwin 3 4.1 Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_CanvasTkwin, Tk_CanvasGetCoord, Tk_CanvasDrawableCoords, Tk_CanvasSetStippleOrigin, Tk_CanvasWindowCoords, Tk_CanvasEventuallyRedraw, Tk_CanvasTagsOption \- utility procedures for canvas type managers
.SH SYNOPSIS
.nf
Changes to doc/CanvTxtInfo.3.
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







'\"
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH Tk_CanvasTextInfo 3 4.0 Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_CanvasTextInfo \- additional information for managing text items in canvases
.SH SYNOPSIS
.nf
Changes to doc/Clipboard.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1994 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH Tk_ClipboardClear 3 4.0 Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_ClipboardClear, Tk_ClipboardAppend \- Manage the clipboard
.SH SYNOPSIS
.nf
Changes to doc/ClrSelect.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1992-1994 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH Tk_ClearSelection 3 4.0 Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_ClearSelection \- Deselect a selection
.SH SYNOPSIS
.nf
Changes to doc/ConfigWidg.3.
103
104
105
106
107
108
109
110

111
112
113
114
115
116
117
103
104
105
106
107
108
109

110
111
112
113
114
115
116
117







-
+







.CS
typedef struct {
    int \fItype\fR;
    const char *\fIargvName\fR;
    const char *\fIdbName\fR;
    const char *\fIdbClass\fR;
    const char *\fIdefValue\fR;
    int \fIoffset\fR;
    size_t \fIoffset\fR;
    int \fIspecFlags\fR;
    const Tk_CustomOption *\fIcustomPtr\fR;
} \fBTk_ConfigSpec\fR;
.CE
The \fItype\fR field indicates what type of configuration option this is
(e.g. \fBTK_CONFIG_COLOR\fR for a color value, or \fBTK_CONFIG_INT\fR for
an integer value).  The \fItype\fR field indicates how to use the
157
158
159
160
161
162
163
164

165
166

167
168
169
170
171
172
173
157
158
159
160
161
162
163

164


165
166
167
168
169
170
171
172







-
+
-
-
+







form, such as a color if \fItype\fR is \fBTK_CONFIG_COLOR\fR or an integer
if \fItype\fR is \fBTK_CONFIG_INT\fR.  This value is then stored in the
record pointed to by \fIwidgRec\fR.  This record is assumed to
contain information relevant to the manager of the widget;  its exact
type is unknown to \fBTk_ConfigureWidget\fR.  The \fIoffset\fR field
of each \fIspecs\fR entry indicates where in \fIwidgRec\fR to store
the information about this configuration option.  You should use the
\fBTk_Offset\fR macro to generate \fIoffset\fR values (see below for
\fBoffsetof\fR macro to generate \fIoffset\fR values.  The location
a description of \fBTk_Offset\fR).  The location indicated by
\fIwidgRec\fR and \fIoffset\fR will be referred to as the
indicated by \fIwidgRec\fR and \fIoffset\fR will be referred to as the
.QW target
in the descriptions below.
.PP
The \fItype\fR field of each entry in \fIspecs\fR determines what
to do with the string value of that configuration option.  The
legal values for \fItype\fR, and the corresponding actions, are:
.TP
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
464
465
466
467
468
469
470







471
472
473
474
475
476
477







-
-
-
-
-
-
-







for N different widget types, then N of the high-order bits will
be used.  Each \fIspecs\fR entry will have one of more of those
bits set in its \fIspecFlags\fR field to indicate the widget types
for which this entry is valid.  When calling \fBTk_ConfigureWidget\fR,
\fIflags\fR will have a single one of these bits set to select the
entries for the desired widget type.  For a working example of
this feature, see the code in tkButton.c.
.SH TK_OFFSET
.PP
The \fBTk_Offset\fR macro is provided as a safe way of generating
the \fIoffset\fR values for entries in Tk_ConfigSpec structures.
It takes two arguments:  the name of a type of record, and the
name of a field in that record.  It returns the byte offset of
the named field in records of the given type.
.SH TK_CONFIGUREINFO
.PP
The \fBTk_ConfigureInfo\fR procedure may be used to obtain
information about one or all of the options for a given widget.
Given a token for a window (\fItkwin\fR), a table describing the
configuration options for a class of widgets (\fIspecs\fR), a
pointer to a widget record containing the current information for
Changes to doc/ConfigWind.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1990-1993 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH Tk_ConfigureWindow 3 4.0 Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_ConfigureWindow, Tk_MoveWindow, Tk_ResizeWindow, Tk_MoveResizeWindow, Tk_SetWindowBorderWidth, Tk_ChangeWindowAttributes, Tk_SetWindowBackground, Tk_SetWindowBackgroundPixmap, Tk_SetWindowBorder, Tk_SetWindowBorderPixmap, Tk_SetWindowColormap, Tk_DefineCursor, Tk_UndefineCursor \- change window configuration or attributes
.SH SYNOPSIS
.nf
Changes to doc/CoordToWin.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1990-1993 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH Tk_CoordsToWindow 3 "" Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_CoordsToWindow \- Find window containing a point
.SH SYNOPSIS
.nf
Changes to doc/CrtCmHdlr.3.
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







'\"
'\" Copyright (c) 2000 Ajuba Solutions.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\"
.TH Tk_CreateClientMessageHandler 3 "8.4" Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_CreateClientMessageHandler, Tk_DeleteClientMessageHandler \- associate procedure callback with ClientMessage type X events
.SH SYNOPSIS
.nf
Changes to doc/CrtConsoleChan.3.
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







'\"
'\" Copyright (c) 2007 ActiveState Software Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\"
.TH Tk_InitConsoleChannels 3 8.5 Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_InitConsoleChannels \- Install the console channels as standard channels
.SH SYNOPSIS
.nf
Changes to doc/CrtErrHdlr.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1990 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH Tk_CreateErrorHandler 3 "" Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_CreateErrorHandler, Tk_DeleteErrorHandler \- handle X protocol errors
.SH SYNOPSIS
.nf
Changes to doc/CrtGenHdlr.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1992-1994 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH Tk_CreateGenericHandler 3 "" Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_CreateGenericHandler, Tk_DeleteGenericHandler \- associate procedure callback with all X events
.SH SYNOPSIS
.nf
Changes to doc/CrtImgType.3.
1
2
3
4
5
6
7

8
9
10
11
12

13
14
15
16
17
18
19
20

21
22
23
24
25
26
27
1
2
3
4
5
6

7
8
9
10
11

12
13
14
15
16
17
18
19

20
21
22
23
24
25
26
27






-
+




-
+







-
+







'\"
'\" Copyright (c) 1994 The Regents of the University of California.
'\" Copyright (c) 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.
'\" 
'\"
.TH Tk_CreateImageType 3 8.5 Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_CreateImageType, Tk_GetImageMasterData, Tk_InitImageArgs \- define new kind of image
Tk_CreateImageType, Tk_GetImageModelData, Tk_InitImageArgs \- define new kind of image
.SH SYNOPSIS
.nf
\fB#include <tk.h>\fR
.sp
\fBTk_CreateImageType\fR(\fItypePtr\fR)
.sp
ClientData
\fBTk_GetImageMasterData\fR(\fIinterp, name, typePtrPtr\fR)
\fBTk_GetImageModelData\fR(\fIinterp, name, typePtrPtr\fR)
.sp
\fBTk_InitImageArgs\fR(\fIinterp, argc, argvPtr\fR)
.SH ARGUMENTS
.AS "const Tk_ImageType" *typePtrPtr
.AP "const Tk_ImageType" *typePtr in
Structure that defines the new type of image.
For Tk 8.4 and earlier this must be static: a
67
68
69
70
71
72
73
74

75
76
77
78
79
80
81
67
68
69
70
71
72
73

74
75
76
77
78
79
80
81







-
+







    Tk_ImageDeleteProc *\fIdeleteProc\fR;
} \fBTk_ImageType\fR;
.CE
The fields of this structure will be described in later subsections
of this entry.
.PP
The second major data structure manipulated by an image manager
is called an \fIimage master\fR;  it contains overall information
is called an \fIimage model\fR;  it contains overall information
about a particular image, such as the values of the configuration
options specified in an \fBimage create\fR command.
There will usually be one of these structures for each
invocation of the \fBimage create\fR command.
.PP
The third data structure related to images is an \fIimage instance\fR.
There will usually be one of these structures for each usage of an
109
110
111
112
113
114
115
116
117


118
119
120
121
122
123
124
125
126

127
128
129
130

131
132

133
134

135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151

152
153
154
155


156
157
158
159
160
161
162
109
110
111
112
113
114
115


116
117
118
119
120
121
122
123
124
125

126
127
128
129

130
131

132
133

134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150

151
152
153


154
155
156
157
158
159
160
161
162







-
-
+
+








-
+



-
+

-
+

-
+
















-
+


-
-
+
+







.CS
typedef int \fBTk_ImageCreateProc\fR(
        Tcl_Interp *\fIinterp\fR,
        const char *\fIname\fR,
        int \fIobjc\fR,
        Tcl_Obj *const \fIobjv\fR[],
        const Tk_ImageType *\fItypePtr\fR,
        Tk_ImageMaster \fImaster\fR,
        ClientData *\fImasterDataPtr\fR);
        Tk_ImageModel \fImodel\fR,
        ClientData *\fImodelDataPtr\fR);
.CE
The \fIinterp\fR argument is the interpreter in which the \fBimage\fR
command was invoked, and \fIname\fR is the name for the new image,
which was either specified explicitly in the \fBimage\fR command
or generated automatically by the \fBimage\fR command.
The \fIobjc\fR and \fIobjv\fR arguments describe all the configuration
options for the new image (everything after the name argument to
\fBimage\fR).
The \fImaster\fR argument is a token that refers to Tk's information
The \fImodel\fR argument is a token that refers to Tk's information
about this image;  the image manager must return this token to
Tk when invoking the \fBTk_ImageChanged\fR procedure.
Typically \fIcreateProc\fR will parse \fIobjc\fR and \fIobjv\fR
and create an image master data structure for the new image.
and create an image model data structure for the new image.
\fIcreateProc\fR may store an arbitrary one-word value at
*\fImasterDataPtr\fR, which will be passed back to the
*\fImodelDataPtr\fR, which will be passed back to the
image manager when other callbacks are invoked.
Typically the value is a pointer to the master data
Typically the value is a pointer to the model data
structure for the image.
.PP
If \fIcreateProc\fR encounters an error, it should leave an error
message in the interpreter result and return \fBTCL_ERROR\fR;  otherwise
it should return \fBTCL_OK\fR.
.PP
\fIcreateProc\fR should call \fBTk_ImageChanged\fR in order to set the
size of the image and request an initial redisplay.
.SS GETPROC
.PP
\fItypePtr->getProc\fR is invoked by Tk whenever a widget
calls \fBTk_GetImage\fR to use a particular image.
This procedure must match the following prototype:
.CS
typedef ClientData \fBTk_ImageGetProc\fR(
        Tk_Window \fItkwin\fR,
        ClientData \fImasterData\fR);
        ClientData \fImodelData\fR);
.CE
The \fItkwin\fR argument identifies the window in which the
image will be used and \fImasterData\fR is the value
returned by \fIcreateProc\fR when the image master was created.
image will be used and \fImodelData\fR is the value
returned by \fIcreateProc\fR when the image model was created.
\fIgetProc\fR will usually create a data structure for the new
instance, including such things as the resources needed to
display the image in the given window.
\fIgetProc\fR returns a one-word token for the instance, which
is typically the address of the instance data structure.
Tk will pass this value back to the image manager when invoking
its \fIdisplayProc\fR and \fIfreeProc\fR procedures.
217
218
219
220
221
222
223
224

225
226
227


228
229
230
231

232
233

234
235

236
237
238
239
240
241
242

243
244
245
246
247
248
249
250
251
252
253
254
255
256


257
258
259
260
261
262
263
217
218
219
220
221
222
223

224
225


226
227
228
229
230

231
232

233
234

235
236
237
238
239
240
241

242
243
244
245
246
247
248
249
250
251
252
253
254


255
256
257
258
259
260
261
262
263







-
+

-
-
+
+



-
+

-
+

-
+






-
+












-
-
+
+







image is being deleted (i.e. when the \fBimage delete\fR command
is invoked).
Before invoking \fIdeleteProc\fR Tk will invoke \fIfreeProc\fR for
each of the image's instances.
\fIdeleteProc\fR must match the following prototype:
.CS
typedef void \fBTk_ImageDeleteProc\fR(
        ClientData \fImasterData\fR);
        ClientData \fImodelData\fR);
.CE
The \fImasterData\fR argument will be the same as the value
stored in \fI*masterDataPtr\fR by \fIcreateProc\fR when the
The \fImodelData\fR argument will be the same as the value
stored in \fI*modelDataPtr\fR by \fIcreateProc\fR when the
image was created.
\fIdeleteProc\fR should release any resources associated with
the image.
.SH TK_GETIMAGEMASTERDATA
.SH TK_GETIMAGEMODELDATA
.PP
The procedure \fBTk_GetImageMasterData\fR may be invoked to retrieve
The procedure \fBTk_GetImageModelData\fR may be invoked to retrieve
information about an image.  For example, an image manager can use this
procedure to locate its image master data for an image.
procedure to locate its image model data for an image.
If there exists an image named \fIname\fR
in the interpreter given by \fIinterp\fR, then \fI*typePtrPtr\fR is
filled in with type information for the image (the \fItypePtr\fR value
passed to \fBTk_CreateImageType\fR when the image type was registered)
and the return value is the ClientData value returned by the
\fIcreateProc\fR when the image was created (this is typically a
pointer to the image master data structure).  If no such image exists
pointer to the image model data structure).  If no such image exists
then NULL is returned and NULL is stored at \fI*typePtrPtr\fR.
.SH "LEGACY INTERFACE SUPPORT"
.PP
In Tk 8.2 and earlier, the definition of \fBTk_ImageCreateProc\fR
was incompatibly different, with the following prototype:
.CS
typedef int \fBTk_ImageCreateProc\fR(
        Tcl_Interp *\fIinterp\fR,
        char *\fIname\fR,
        int \fIargc\fR,
        char **\fIargv\fR,
        Tk_ImageType *\fItypePtr\fR,
        Tk_ImageMaster \fImaster\fR,
        ClientData *\fImasterDataPtr\fR);
        Tk_ImageModel \fImodel\fR,
        ClientData *\fImodelDataPtr\fR);
.CE
Legacy programs and libraries dating from those days may still
contain code that defines extended Tk image types using the old
interface.  The Tk header file will still support this legacy
interface if the code is compiled with the macro \fBUSE_OLD_IMAGE\fR
defined.
.PP
276
277
278
279
280
281
282
283

276
277
278
279
280
281
282

283







-
+
use Tk 8.4 headers and stub libraries to do so.
.PP
Any new code written today should not make use of the legacy
interfaces.  Expect their support to go away in Tk 9.
.SH "SEE ALSO"
Tk_ImageChanged, Tk_GetImage, Tk_FreeImage, Tk_RedrawImage, Tk_SizeOfImage
.SH KEYWORDS
image manager, image type, instance, master
image manager, image type, instance, model
Changes to doc/CrtItemType.3.
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







'\"
'\" Copyright (c) 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.
'\" 
'\"
.TH Tk_CreateItemType 3 4.0 Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_CreateItemType, Tk_GetItemTypes \- define new kind of canvas item
.SH SYNOPSIS
.nf
60
61
62
63
64
65
66
67

68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85



86
87
88
89
90
91
92
60
61
62
63
64
65
66

67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95







-
+


















+
+
+







The first data structure is a Tk_ItemType; it contains
information such as the name of the type and pointers to
the standard procedures implemented by the type manager:
.PP
.CS
typedef struct Tk_ItemType {
    const char *\fIname\fR;
    int \fIitemSize\fR;
    size_t \fIitemSize\fR;
    Tk_ItemCreateProc *\fIcreateProc\fR;
    const Tk_ConfigSpec *\fIconfigSpecs\fR;
    Tk_ItemConfigureProc *\fIconfigProc\fR;
    Tk_ItemCoordProc *\fIcoordProc\fR;
    Tk_ItemDeleteProc *\fIdeleteProc\fR;
    Tk_ItemDisplayProc *\fIdisplayProc\fR;
    int \fIalwaysRedraw\fR;
    Tk_ItemPointProc *\fIpointProc\fR;
    Tk_ItemAreaProc *\fIareaProc\fR;
    Tk_ItemPostscriptProc *\fIpostscriptProc\fR;
    Tk_ItemScaleProc *\fIscaleProc\fR;
    Tk_ItemTranslateProc *\fItranslateProc\fR;
    Tk_ItemIndexProc *\fIindexProc\fR;
    Tk_ItemCursorProc *\fIicursorProc\fR;
    Tk_ItemSelectionProc *\fIselectionProc\fR;
    Tk_ItemInsertProc *\fIinsertProc\fR;
    Tk_ItemDCharsProc *\fIdCharsProc\fR;
    Tk_ItemType *\fInextPtr\fR;
.VS "8.7, TIP164"
    Tk_ItemRotateProc *\fIrotateProc\fR;
.VE "8.7, TIP164"
} \fBTk_ItemType\fR;
.CE
.PP
The fields of a Tk_ItemType structure are described in more detail
later in this manual entry.
When \fBTk_CreateItemType\fR is called, its \fItypePtr\fR
argument must point to a structure with all of the fields initialized
545
546
547
548
549
550
551








































552
553
554
555
556
557
558
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







.CE
.PP
The \fIcanvas\fR and \fIitemPtr\fR arguments have the usual meaning,
and \fIdeltaX\fR and \fIdeltaY\fR give the amounts that should be
added to each x and y coordinate within the item.
The type manager should adjust the item's coordinates and
update the bounding box in the item's header.
.SS ROTATEPROC
.VS "8.7, TIP164"
.PP
\fItypePtr\->rotateProc\fR is invoked by Tk to rotate a canvas item
during the \fBrotate\fR widget command.
The procedure must match the following prototype:
.PP
.CS
typedef void \fBTk_ItemRotateProc\fR(
        Tk_Canvas \fIcanvas\fR,
        Tk_Item *\fIitemPtr\fR,
        double \fIoriginX\fR,
        double \fIoriginY\fR,
        double \fIangleRad\fR);
.CE
.PP
The \fIcanvas\fR and \fIitemPtr\fR arguments have the usual meaning.
\fIoriginX\fR and \fIoriginY\fR specify an origin relative to which
the item is to be rotated, and \fIangleRad\fR gives the anticlockwise
rotation to be applied in radians.
The item should adjust the coordinates of its control points so that where
they used to have coordinates \fIx\fR and \fIy\fR, they will have new
coordinates \fIx\(fm\fR and \fIy\(fm\fR, where
.PP
.CS
\fIrelX\fR = \fIx\fR - \fIoriginX\fR
\fIrelY\fR = \fIy\fR - \fIoriginY\fR
\fIx\(fm\fR = \fIoriginX\fR + \fIrelX\fR \(mu cos(\fIangleRad\fR) + \fIrelY\fR \(mu sin(\fIangleRad\fR)
\fIy\(fm\fR = \fIoriginY\fR \(mi \fIrelX\fR \(mu sin(\fIangleRad\fR) + \fIrelY\fR \(mu cos(\fIangleRad\fR)
.CE
.PP
The control points for an item are not necessarily the coordinates provided to
the item when it is created (or via the \fItypePtr\->coordProc\fR), but could
instead be derived from them.
\fIrotateProc\fR must also update the bounding box in the item's header.
.PP
Item types do not need to provide a \fItypePtr\->rotateProc\fR. If the
\fItypePtr\->rotateProc\fR is NULL, the \fItypePtr\->coordProc\fR will be
used instead to retrieve and update the list of coordinates.
.VE "8.7, TIP164"
.SS INDEXPROC
.PP
\fItypePtr\->indexProc\fR is invoked by Tk to translate a string
index specification into a numerical index, for example during the
\fBindex\fR widget command.
It is only relevant for item types that support indexable text or coordinates;
\fItypePtr\->indexProc\fR may be specified as NULL for non-textual
Changes to doc/CrtPhImgFmt.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1994 The Australian National University
'\" Copyright (c) 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 ([email protected]),
'\"	    Department of Computer Science,
'\"	    Australian National University.
'\"
.TH Tk_CreatePhotoImageFormat 3 8.5 Tk "Tk Library Procedures"
.so man.macros
.BS
Changes to doc/DeleteImg.3.
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







'\"
'\" Copyright (c) 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.
'\" 
'\"
.TH Tk_DeleteImage 3 4.0 Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_DeleteImage \- Destroy an image.
.SH SYNOPSIS
.nf
Changes to doc/DrawFocHlt.3.
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







'\"
'\" Copyright (c) 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.
'\" 
'\"
.TH Tk_DrawFocusHighlight 3 4.0 Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_DrawFocusHighlight \- draw the traversal highlight ring for a widget
.SH SYNOPSIS
.nf
Changes to doc/EventHndlr.3.
1
2
3
4
5
6
7

8
9
10
11
12

13
14
15
16
17
18
19




20
21






22
23
24
25
26
27
28
1
2
3
4
5
6

7
8
9
10
11

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38






-
+




-
+







+
+
+
+


+
+
+
+
+
+







'\"
'\" Copyright (c) 1990 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH Tk_CreateEventHandler 3 "" Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_CreateEventHandler, Tk_DeleteEventHandler \- associate procedure callback with an X event
Tk_CreateEventHandler, Tk_DeleteEventHandler, Tk_GetButtonMask, Tk_SendVirtualEvent \- associate procedure callback with an X event
.SH SYNOPSIS
.nf
\fB#include <tk.h>\fR
.sp
\fBTk_CreateEventHandler\fR(\fItkwin, mask, proc, clientData\fR)
.sp
\fBTk_DeleteEventHandler\fR(\fItkwin, mask, proc, clientData\fR)
.sp
\fBTk_GetButtonMask\fR(\fIbutton\fR)
.sp
\fBTk_SendVirtualEvent\fR(\fItkwin, eventName, detail\fR)
.SH ARGUMENTS
.AS "unsigned long" clientData
.AP unsigned button in
Button number.
.AP "const char" *eventName in
The name of the virtual event.
.AP Tcl_Obj *detail in
Detail information for the virtual event.
.AP Tk_Window tkwin in
Token for window in which events may occur.
.AP "unsigned long" mask in
Bit-mask of events (such as \fBButtonPressMask\fR)
for which \fIproc\fR should be called.
.AP Tk_EventProc *proc in
Procedure to invoke whenever an event in \fImask\fR occurs
67
68
69
70
71
72
73





74
75
77
78
79
80
81
82
83
84
85
86
87
88
89
90







+
+
+
+
+


When a window is deleted all of its handlers will be deleted
automatically;  in this case there is no need to call
\fBTk_DeleteEventHandler\fR.
.PP
If multiple handlers are declared for the same type of X event
on the same window, then the handlers will be invoked in the
order they were created.
.PP
\fBTk_GetButtonMask\fR returns the button mask corresponding to
the button. E.g it will return \fIButton1Mask\fR for button \fIButton1\fR.
.PP
\fBTk_SendVirtualEvent\fR sends a virtual event to Tk's event queue.
.SH KEYWORDS
bind, callback, event, handler
Changes to doc/FreeXId.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

28


















29
30






-
+




















-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-


'\"
'\" Copyright (c) 1990 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH Tk_FreeXId 3 4.0 Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_FreeXId \- make X resource identifier available for reuse
.SH SYNOPSIS
.nf
\fB#include <tk.h>\fR
.sp
\fBTk_FreeXId(\fIdisplay, id\fB)\fR
.SH ARGUMENTS
.AS Display *display out
.AP Display *display in
Display for which \fIid\fR was allocated.
.AP XID id in
Identifier of X resource (window, font, pixmap, cursor, graphics
context, or colormap) that is no longer in use.
.BE
.SH DESCRIPTION
.PP
The default allocator for resource identifiers provided by Xlib is very
This function is deprecated, it doesn't do anything since 2008-08-19.
simple-minded and does not allow resource identifiers to be re-used.
If a long-running application reaches the end of the resource id
space, it will generate an X protocol error and crash.
Tk replaces the default id allocator with its own allocator, which
allows identifiers to be reused.
In order for this to work, \fBTk_FreeXId\fR must be called to
tell the allocator about resources that have been freed.
Tk automatically calls \fBTk_FreeXId\fR whenever it frees a
resource, so if you use procedures like \fBTk_GetFont\fR,
\fBTk_GetGC\fR, and \fBTk_GetPixmap\fR then you need not call
\fBTk_FreeXId\fR.
However, if you allocate resources directly from Xlib, for example
by calling \fBXCreatePixmap\fR, then you should call \fBTk_FreeXId\fR
when you call the corresponding Xlib free procedure, such as
\fBXFreePixmap\fR.
If you do not call \fBTk_FreeXId\fR then the resource identifier will
be lost, which could cause problems if the application runs long enough
to lose all of the available identifiers.
.SH KEYWORDS
resource identifier
Changes to doc/GeomReq.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1990-1994 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH Tk_GeometryRequest 3 "8.4" Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_GeometryRequest, Tk_SetMinimumRequestSize, Tk_SetInternalBorder, Tk_SetInternalBorderEx \- specify desired geometry or internal border for a window
.SH SYNOPSIS
.nf
Changes to doc/GetAnchor.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1990 The Regents of the University of California.
'\" Copyright (c) 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.
'\" 
'\"
.TH Tk_GetAnchorFromObj 3 8.1 Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_GetAnchorFromObj, Tk_GetAnchor, Tk_NameOfAnchor \- translate between strings and anchor positions
.SH SYNOPSIS
.nf
Changes to doc/GetBitmap.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1990 The Regents of the University of California.
'\" Copyright (c) 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.
'\" 
'\"
.TH Tk_AllocBitmapFromObj 3 8.1 Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_AllocBitmapFromObj, Tk_GetBitmap, Tk_GetBitmapFromObj, Tk_DefineBitmap, Tk_NameOfBitmap, Tk_SizeOfBitmap, Tk_FreeBitmapFromObj, Tk_FreeBitmap \- maintain database of single-plane pixmaps
.SH SYNOPSIS
.nf
Changes to doc/GetCapStyl.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1990 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH Tk_GetCapStyle 3 "" Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_GetCapStyle, Tk_NameOfCapStyle \- translate between strings and cap styles
.SH SYNOPSIS
.nf
Changes to doc/GetClrmap.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1994 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH Tk_GetColormap 3 4.0 Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_GetColormap, Tk_PreserveColormap, Tk_FreeColormap \- allocate and free colormaps
.SH SYNOPSIS
.nf
Changes to doc/GetDash.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1989-1993 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH Tk_GetDash 3 8.3 Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_GetDash \- convert from string to valid dash structure.
.SH SYNOPSIS
.nf
Changes to doc/GetFont.3.
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
20
21
22
23
24
25



26
27
28
29
30
31
32
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35











-
+













+
+
+







'\"
'\" Copyright (c) 1990-1992 The Regents of the University of California.
'\" Copyright (c) 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.
'\"
.TH Tk_AllocFontFromObj 3 8.1 Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_AllocFontFromObj, Tk_GetFont, Tk_GetFontFromObj, Tk_NameOfFont, Tk_FreeFontFromObj, Tk_FreeFont \- maintain database of fonts
Tk_AllocFontFromObj, Tk_GetFont, Tk_GetFontFromObj, Tk_NameOfFont, Tk_FontGetDescription, Tk_FreeFontFromObj, Tk_FreeFont \- maintain database of fonts
.SH SYNOPSIS
.nf
\fB#include <tk.h>\fR
.sp
Tk_Font
\fBTk_AllocFontFromObj(\fIinterp, tkwin, objPtr\fB)\fR
.sp
Tk_Font
\fBTk_GetFont(\fIinterp, tkwin, string\fB)\fR
.sp
Tk_Font
\fBTk_GetFontFromObj(\fItkwin, objPtr\fB)\fR
.sp
Tcl_Obj *
\fBTk_FontGetDescription(\fItkfont\fB)\fR
.sp
const char *
\fBTk_NameOfFont(\fItkfont\fB)\fR
.sp
Tk_Font
\fBTk_FreeFontFromObj(\fItkwin, objPtr\fB)\fR
.sp
void
84
85
86
87
88
89
90



91
92
93
94
95
96
97
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103







+
+
+







\fBTk_AllocFontFromObj\fR and \fBTk_GetFont\fR maintain
a database of all fonts they have allocated.  If
the same font is requested multiple times (e.g. by different
windows or for different purposes), then a single Tk_Font will be
shared for all uses.  The underlying resources will be freed automatically
when no-one is using the font anymore.
.PP
The procedure \fBTk_FontGetDescription\fR returns information about the font
description as a Tcl list. One possible result is "{{DejaVu Sans} -16 bold underline}".
.PP
The procedure \fBTk_NameOfFont\fR is roughly the inverse of
\fBTk_GetFont\fR.  Given a \fItkfont\fR that was created by
\fBTk_GetFont\fR (or \fBTk_AllocFontFromObj\fR), the return value is
the \fIstring\fR argument that was
passed to \fBTk_GetFont\fR to create the font.  The string returned by
\fBTk_NameOfFont\fR is only guaranteed to persist until the \fItkfont\fR
is deleted.  The caller must not modify this string.
Changes to doc/GetGC.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1990 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH Tk_GetGC 3 "" Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_GetGC, Tk_FreeGC \- maintain database of read-only graphics contexts
.SH SYNOPSIS
.nf
Changes to doc/GetHINSTANCE.3.
1
2

3
4

5
6
7
8
9
10
11
1

2
3

4
5
6
7
8
9
10
11

-
+

-
+







'\"
'\" 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
.SH NAME
Tk_GetHINSTANCE \- retrieve the global application instance handle
.SH SYNOPSIS
.nf
Changes to doc/GetHWND.3.
1
2

3
4

5
6
7
8
9
10
11
1

2
3

4
5
6
7
8
9
10
11

-
+

-
+







'\"
'\" 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
.SH NAME
Tk_GetHWND, Tk_AttachHWND \- manage interactions between the Windows handle and an X window
.SH SYNOPSIS
.nf
Changes to doc/GetImage.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1994 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH Tk_GetImage 3 4.0 Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_GetImage, Tk_RedrawImage, Tk_SizeOfImage, Tk_FreeImage \- use an image in a widget
.SH SYNOPSIS
.nf
Changes to doc/GetJoinStl.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1990 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH Tk_GetJoinStyle 3 "" Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_GetJoinStyle, Tk_NameOfJoinStyle \- translate between strings and join styles
.SH SYNOPSIS
.nf
Changes to doc/GetJustify.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1990-1994 The Regents of the University of California.
'\" Copyright (c) 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.
'\" 
'\"
.TH Tk_GetJustifyFromObj 3 8.1 Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_GetJustifyFromObj, Tk_GetJustify, Tk_NameOfJustify \- translate between strings and justification styles
.SH SYNOPSIS
.nf
Changes to doc/GetOption.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1990 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH Tk_GetOption 3 "" Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_GetOption \- retrieve an option from the option database
.SH SYNOPSIS
.nf
Changes to doc/GetPixels.3.
1
2
3
4
5
6
7

8
9
10
11
12

13
14
15
16
17
18
19



20
21
22
23
24
25
26
1
2
3
4
5
6

7
8
9
10
11

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29






-
+




-
+







+
+
+







'\"
'\" Copyright (c) 1990 The Regents of the University of California.
'\" Copyright (c) 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.
'\" 
'\"
.TH Tk_GetPixelsFromObj 3 8.1 Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_GetPixelsFromObj, Tk_GetPixels, Tk_GetMMFromObj, Tk_GetScreenMM \- translate between strings and screen units
Tk_GetPixelsFromObj, Tk_GetPixels, Tk_GetMMFromObj, Tk_GetScreenMM, Tk_GetDoublePixelsFromObj \- translate between strings and screen units
.SH SYNOPSIS
.nf
\fB#include <tk.h>\fR
.sp
int
\fBTk_GetPixelsFromObj(\fIinterp, tkwin, objPtr, intPtr\fB)\fR
.sp
int
\fBTk_GetDoublePixelsFromObj(\fIinterp, tkwin, objPtr, doublePtr\fB)\fR
.sp
int
\fBTk_GetPixels(\fIinterp, tkwin, string, intPtr\fB)\fR
.sp
int
\fBTk_GetMMFromObj(\fIinterp, tkwin, objPtr, doublePtr\fB)\fR
.sp
int
76
77
78
79
80
81
82



83
84
85
86
87
88
89
90
91
92
93
94
95
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101







+
+
+













If an error occurs (e.g. \fIobjPtr\fR contains a number followed
by a character that is not one of the ones above) then
\fBTCL_ERROR\fR is returned and an error message is left
in \fIinterp\fR's result if \fIinterp\fR is not NULL.
\fBTk_GetPixelsFromObj\fR caches information about the return
value in \fIobjPtr\fR, which speeds up future calls to
\fBTk_GetPixelsFromObj\fR with the same \fIobjPtr\fR.
.PP
\fBTk_GetDoublePixelsFromObj\fR is identical to \fBTk_GetPixelsFromObj\fR
except it returns a double not rounded to the nearest integer.
.PP
\fBTk_GetPixels\fR is identical to \fBTk_GetPixelsFromObj\fR except
that the screen distance is specified with a string instead
of an object.  This prevents \fBTk_GetPixels\fR from caching the
return value, so \fBTk_GetPixels\fR is less efficient than
\fBTk_GetPixelsFromObj\fR.
.PP
\fBTk_GetMMFromObj\fR and \fBTk_GetScreenMM\fR are similar to
\fBTk_GetPixelsFromObj\fR and \fBTk_GetPixels\fR (respectively) except
that they convert the screen distance to millimeters and
store a double-precision floating-point result at \fI*doublePtr\fR.
.SH KEYWORDS
centimeters, convert, inches, millimeters, pixels, points, screen units
Changes to doc/GetPixmap.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1990 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH Tk_GetPixmap 3 4.0 Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_GetPixmap, Tk_FreePixmap \- allocate and free pixmaps
.SH SYNOPSIS
.nf
Changes to doc/GetRelief.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1990 The Regents of the University of California.
'\" Copyright (c) 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.
'\" 
'\"
.TH Tk_GetReliefFromObj 3 8.1 Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_GetReliefFromObj, Tk_GetRelief, Tk_NameOfRelief \- translate between strings and relief values
.SH SYNOPSIS
.nf
Changes to doc/GetRootCrd.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1990 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH Tk_GetRootCoords 3 "" Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_GetRootCoords \- Compute root-window coordinates of window
.SH SYNOPSIS
.nf
Changes to doc/GetScroll.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

29
30
31
32
33
34

35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54


55
56
57

58
59
60
61
62
63
64
65




66
67
68
69
70
71
72
73
74
75
1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

28
29
30
31
32
33

34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52


53
54
55
56

57
58
59
60
61
62



63
64
65
66
67
68
69
70
71
72
73
74
75
76






-
+




















-
+





-
+


















-
-
+
+


-
+





-
-
-
+
+
+
+










'\"
'\" Copyright (c) 1994 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH Tk_GetScrollInfo 3 8.0 Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_GetScrollInfoObj, Tk_GetScrollInfo \- parse arguments for scrolling commands
.SH SYNOPSIS
.nf
\fB#include <tk.h>\fR
.sp
int
\fBTk_GetScrollInfoObj(\fIinterp, objc, objv, fractionPtr, stepsPtr\fB)\fR
.sp
int
\fBTk_GetScrollInfo(\fIinterp, argc, argv, fractionPtr, stepsPtr\fB)\fR
.SH ARGUMENTS
.AS "Tcl_Interp" *fractionPtr
.AP Tcl_Interp *interp in
Interpreter to use for error reporting.
.AP int objc in
Number of Tcl_Obj's in \fIobjv\fR array.
.AP "Tcl_Obj *const" objv[] in
.AP "Tcl_Obj *const *" objv in
Argument objects.  These represent the entire widget command, of
which the first word is typically the widget name and the second
word is typically \fBxview\fR or \fByview\fR.
.AP int argc in
Number of strings in \fIargv\fR array.
.AP "const char" *argv[] in
.AP "const char **" argv in
Argument strings.  These represent the entire widget command, of
which the first word is typically the widget name and the second
word is typically \fBxview\fR or \fByview\fR.
.AP double *fractionPtr out
Filled in with fraction from \fBmoveto\fR option, if any.
.AP int *stepsPtr out
Filled in with line or page count from \fBscroll\fR option, if any.
The value may be negative.
.BE
.SH DESCRIPTION
.PP
\fBTk_GetScrollInfoObj\fR parses the arguments expected by widget
scrolling commands such as \fBxview\fR and \fByview\fR.
It receives the entire list of words that make up a widget command
and parses the words starting with \fIobjv\fR[2].
The words starting with \fIobjv\fR[2] must have one of the following forms:
.CS
\fBmoveto \fIfraction\fR
\fBscroll \fInumber\fB units\fR
\fBscroll \fInumber\fB pages\fR
\fBscroll \fInumber\fB pages\fR
\fBscroll \fInumber\fB units\fR
.CE
.LP
Any of the \fBmoveto\fR, \fBscroll\fR, \fBunits\fR, and \fBpages\fR
Any of the \fBmoveto\fR, \fBscroll\fR, \fBpages\fR, and \fBunits\fR
keywords may be abbreviated.
If \fIobjv\fR has the \fBmoveto\fR form, \fBTK_SCROLL_MOVETO\fR
is returned as result and \fI*fractionPtr\fR is filled in with the
\fIfraction\fR argument to the command, which must be a proper real
value.
If \fIobjv\fR has the \fBscroll\fR form, \fBTK_SCROLL_UNITS\fR
or \fBTK_SCROLL_PAGES\fR is returned and \fI*stepsPtr\fR is filled
in with the \fInumber\fR value, which must be a proper integer.
If \fIobjv\fR has the \fBscroll\fR form, \fBTK_SCROLL_PAGES\fR
or \fBTK_SCROLL_UNITS\fR is returned and \fI*stepsPtr\fR is filled
in with the \fInumber\fR value, which must be a  integer or a float,
but if it is a float then it is converted to an integer, rounded away from 0.
If an error occurs in parsing the arguments, \fBTK_SCROLL_ERROR\fR
is returned and an error message is left in interpreter
\fIinterp\fR's result.
.PP
\fBTk_GetScrollInfo\fR is identical in function to
\fBTk_GetScrollInfoObj\fR.  However, \fBTk_GetScrollInfo\fR accepts
string arguments, making it more appropriate for use with legacy
widgets.
.SH KEYWORDS
parse, scrollbar, scrolling command, xview, yview
Changes to doc/GetSelect.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1990-1994 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH Tk_GetSelection 3 4.0 Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_GetSelection \- retrieve the contents of a selection
.SH SYNOPSIS
.nf
Changes to doc/GetUid.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1990 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH Tk_GetUid 3 "" Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_GetUid, Tk_Uid \- convert from string to unique identifier
.SH SYNOPSIS
.nf
Changes to doc/GetVRoot.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1990 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH Tk_GetVRootGeometry 3 4.0 Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_GetVRootGeometry \- Get location and size of virtual root for window
.SH SYNOPSIS
.nf
Changes to doc/GetVisual.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1994 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH Tk_GetVisual 3 4.0 Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_GetVisual \- translate from string to visual
.SH SYNOPSIS
.nf
Changes to doc/Grab.3.
1
2

3
4

5
6
7
8
9
10
11
1

2
3

4
5
6
7
8
9
10
11

-
+

-
+







'\"
'\" 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
.SH NAME
Tk_Grab, Tk_Ungrab \- manipulate grab state in an application
.SH SYNOPSIS
.nf
Changes to doc/HWNDToWindow.3.
1
2

3
4

5
6
7
8
9
10
11
1

2
3

4
5
6
7
8
9
10
11

-
+

-
+







'\"
'\" 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
.SH NAME
Tk_HWNDToWindow \- Find Tk's window information for a Windows window
.SH SYNOPSIS
.nf
Changes to doc/HandleEvent.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1990-1992 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH Tk_HandleEvent 3 "" Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_HandleEvent \- invoke event handlers for window system events
.SH SYNOPSIS
.nf
Changes to doc/IdToWindow.3.
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







'\"
'\" Copyright (c) 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.
'\" 
'\"
.TH Tk_IdToWindow 3 4.0 Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_IdToWindow \- Find Tk's window information for an X window
.SH SYNOPSIS
.nf
Changes to doc/ImgChanged.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15
16
17

18
19
20


21
22
23
24
25
26
27
1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16

17
18


19
20
21
22
23
24
25
26
27






-
+









-
+

-
-
+
+







'\"
'\" Copyright (c) 1994 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH Tk_ImageChanged 3 4.0 Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_ImageChanged \- notify widgets that image needs to be redrawn
.SH SYNOPSIS
.nf
\fB#include <tk.h>\fR
.sp
\fBTk_ImageChanged\fR(\fIimageMaster, x, y, width, height, imageWidth, imageHeight\fR)
\fBTk_ImageChanged\fR(\fImodel, x, y, width, height, imageWidth, imageHeight\fR)
.SH ARGUMENTS
.AS Tk_ImageMaster imageHeight
.AP Tk_ImageMaster imageMaster in
.AS Tk_ImageModel imageHeight
.AP Tk_ImageModel model in
Token for image, which was passed to image's \fIcreateProc\fR when
the image was created.
.AP int x in
X-coordinate of upper-left corner of region that needs redisplay (measured
from upper-left corner of image).
.AP int y in
Y-coordinate of upper-left corner of region that needs redisplay (measured
38
39
40
41
42
43
44
45

46
47
48
49
50
51
52
38
39
40
41
42
43
44

45
46
47
48
49
50
51
52







-
+







.SH DESCRIPTION
.PP
An image manager calls \fBTk_ImageChanged\fR for an image
whenever anything happens that requires the image to be redrawn.
As a result of calling \fBTk_ImageChanged\fR, any widgets using
the image are notified so that they can redisplay themselves
appropriately.
The \fIimageMaster\fR argument identifies the image, and
The \fImodel\fR argument identifies the image, and
\fIx\fR, \fIy\fR, \fIwidth\fR, and \fIheight\fR
specify a rectangular region within the image that needs to
be redrawn.
\fIimageWidth\fR and \fIimageHeight\fR specify the image's (new) size.
.PP
An image manager should call \fBTk_ImageChanged\fR during
its \fIcreateProc\fR to specify the image's initial size and to
Changes to doc/Inactive.3.
1
2

3
4

5
6
7
8
9
10
11
1

2
3

4
5
6
7
8
9
10
11

-
+

-
+







'\"
'\" 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
.SH NAME
Tk_GetUserInactiveTime, Tk_ResetUserInactiveTime \- discover user inactivity time
.SH SYNOPSIS
.nf
Changes to doc/InternAtom.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1990 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH Tk_InternAtom 3 "" Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_InternAtom, Tk_GetAtomName \- manage cache of X atoms
.SH SYNOPSIS
.nf
Changes to doc/MainLoop.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1990-1992 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH Tk_MainLoop 3 "" Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_MainLoop \- loop for events until all windows are deleted
.SH SYNOPSIS
.nf
Changes to doc/MainWin.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1990 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH Tk_MainWindow 3 7.0 Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_MainWindow, Tk_GetNumMainWindows \- functions for querying main window information
.SH SYNOPSIS
.nf
Changes to doc/MaintGeom.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15
16
17

18
19

20
21
22


23
24
25


26
27
28
29



30
31
32
33



34
35

36
37

38
39
40
41
42

43
44

45
46
47
48



49
50
51


52
53

54
55
56


57
58
59
60



61
62
63
64
65



66
67
68


69
70
71


72
73
74


75
76
77


78
79
80
81
82
83
84
85
86

87
88
89
90

91
92
93
94

95
96

97
98
99

1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16

17
18

19
20


21
22
23


24
25
26



27
28
29
30



31
32
33
34

35
36

37
38
39
40
41

42
43

44
45



46
47
48
49


50
51
52

53
54


55
56
57



58
59
60
61
62



63
64
65
66


67
68
69


70
71
72


73
74
75


76
77
78
79
80
81
82
83
84
85

86
87
88
89

90
91
92
93

94
95

96
97
98

99






-
+









-
+

-
+

-
-
+
+

-
-
+
+

-
-
-
+
+
+

-
-
-
+
+
+

-
+

-
+




-
+

-
+

-
-
-
+
+
+

-
-
+
+

-
+

-
-
+
+

-
-
-
+
+
+


-
-
-
+
+
+

-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+








-
+



-
+



-
+

-
+


-
+
'\"
'\" Copyright (c) 1994 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH Tk_MaintainGeometry 3 4.0 Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_MaintainGeometry, Tk_UnmaintainGeometry \- maintain geometry of one window relative to another
.SH SYNOPSIS
.nf
\fB#include <tk.h>\fR
.sp
\fBTk_MaintainGeometry\fR(\fIslave, master, x, y, width, height\fR)
\fBTk_MaintainGeometry\fR(\fIwindow, container, x, y, width, height\fR)
.sp
\fBTk_UnmaintainGeometry\fR(\fIslave, master\fR)
\fBTk_UnmaintainGeometry\fR(\fIwindow, container\fR)
.SH ARGUMENTS
.AS Tk_Window master
.AP Tk_Window slave in
.AS Tk_Window container
.AP Tk_Window window in
Window whose geometry is to be controlled.
.AP Tk_Window master in
Window relative to which \fIslave\fR's geometry will be controlled.
.AP Tk_Window container in
Window relative to which \fIwindow\fR's geometry will be controlled.
.AP int x in
Desired x-coordinate of \fIslave\fR in \fImaster\fR, measured in pixels
from the inside of \fImaster\fR's left border to the outside of
\fIslave\fR's left border.
Desired x-coordinate of \fIwindow\fR in \fIcontainer\fR, measured in pixels
from the inside of \fIcontainer\fR's left border to the outside of
\fIwindow\fR's left border.
.AP int y in
Desired y-coordinate of \fIslave\fR in \fImaster\fR, measured in pixels
from the inside of \fImaster\fR's top border to the outside of
\fIslave\fR's top border.
Desired y-coordinate of \fIwindow\fR in \fIcontainer\fR, measured in pixels
from the inside of \fIcontainer\fR's top border to the outside of
\fIwindow\fR's top border.
.AP int width in
Desired width for \fIslave\fR, in pixels.
Desired width for \fIwindow\fR, in pixels.
.AP int height in
Desired height for \fIslave\fR, in pixels.
Desired height for \fIwindow\fR, in pixels.
.BE
.SH DESCRIPTION
.PP
\fBTk_MaintainGeometry\fR and \fBTk_UnmaintainGeometry\fR make it
easier for geometry managers to deal with slaves whose masters are not
easier for geometry managers to deal with windows whose containers are not
their parents.
Three problems arise if the master for a slave is not its parent:
Three problems arise if the container for a window is not its parent:
.IP [1]
The x- and y-position of the slave must be translated from the
coordinate system of the master to that of the parent before
positioning the slave.
The x- and y-position of the window must be translated from the
coordinate system of the container to that of the parent before
positioning the window.
.IP [2]
If the master window, or any of its ancestors up to the slave's
parent, is moved, then the slave must be repositioned within its
If the container window, or any of its ancestors up to the window's
parent, is moved, then the window must be repositioned within its
parent in order to maintain the correct position relative to the
master.
container.
.IP [3]
If the master or one of its ancestors is mapped or unmapped, then
the slave must be mapped or unmapped to correspond.
If the container or one of its ancestors is mapped or unmapped, then
the window must be mapped or unmapped to correspond.
.LP
None of these problems is an issue if the parent and master are
the same.  For example, if the master or one of its ancestors
is unmapped, the slave is automatically removed by the screen
None of these problems is an issue if the parent and container are
the same.  For example, if the container or one of its ancestors
is unmapped, the window is automatically removed by the screen
by X.
.PP
\fBTk_MaintainGeometry\fR deals with these problems for slaves
whose masters are not their parents, as well as handling the simpler
case of slaves whose masters are their parents.
\fBTk_MaintainGeometry\fR deals with these problems for windows
whose containers are not their parents, as well as handling the simpler
case of windows whose container are their parents.
\fBTk_MaintainGeometry\fR is typically called by a window manager
once it has decided where a slave should be positioned relative
to its master.
once it has decided where a window should be positioned relative
to its container.
\fBTk_MaintainGeometry\fR translates the coordinates to the
coordinate system of \fIslave\fR's parent and then moves and
resizes the slave appropriately.
coordinate system of \fIwindow\fR's parent and then moves and
resizes the window appropriately.
Furthermore, it remembers the desired position and creates event
handlers to monitor the master and all of its ancestors up
to (but not including) the slave's parent.
handlers to monitor the container and all of its ancestors up
to (but not including) the window's parent.
If any of these windows is moved, mapped, or unmapped,
the slave will be adjusted so that it is mapped only when the
master is mapped and its geometry relative to the master
the window will be adjusted so that it is mapped only when the
container is mapped and its geometry relative to the container
remains as specified by \fIx\fR, \fIy\fR, \fIwidth\fR, and
\fIheight\fR.
.PP
When a window manager relinquishes control over a window, or
if it decides that it does not want the window to appear on the
screen under any conditions, it calls \fBTk_UnmaintainGeometry\fR.
\fBTk_UnmaintainGeometry\fR unmaps the window and cancels any
previous calls to \fBTk_MaintainGeometry\fR for the
\fImaster\fR\-\fIslave\fR pair, so that the slave's
\fIcontainer\fR\-\fIwindow\fR pair, so that the window's
geometry and mapped state are no longer maintained
automatically.
\fBTk_UnmaintainGeometry\fR need not be called by a geometry
manager if the slave, the master, or any of the master's ancestors
manager if the window, the container, or any of the container's ancestors
is destroyed:  Tk will call it automatically.
.PP
If \fBTk_MaintainGeometry\fR is called repeatedly for the same
\fImaster\fR\-\fIslave\fR pair, the information from the most
\fIcontainer\fR\-\fIwindow\fR pair, the information from the most
recent call supersedes any older information.
If \fBTk_UnmaintainGeometry\fR is called for a \fImaster\fR\-\fIslave\fR
If \fBTk_UnmaintainGeometry\fR is called for a \fIcontainer\fR\-\fIwindow\fR
pair that is is not currently managed, the call has no effect.
.SH KEYWORDS
geometry manager, map, master, parent, position, slave, unmap
geometry manager, map, container, parent, position, window, unmap
Changes to doc/ManageGeom.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1990-1994 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH Tk_ManageGeometry 3 4.0 Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_ManageGeometry \- arrange to handle geometry requests for a window
.SH SYNOPSIS
.nf
28
29
30
31
32
33
34
35

36
37
38
39
40
41
42
43
44
45
46
47

48
49
50
51
52
53
54
55
56

57
58
59
60
61
62
63
64
65
66
67
68
69
70

71
72

73
74
75

76
77
78
79
80

81
82
83

84
85
86
87

88
89
90
28
29
30
31
32
33
34

35
36
37
38
39
40
41
42
43
44
45
46

47
48
49
50
51
52
53
54
55

56
57
58
59
60
61
62
63
64
65
66
67
68
69

70
71

72
73
74

75
76
77
78
79

80
81
82

83
84
85
86

87
88
89
90







-
+











-
+








-
+













-
+

-
+


-
+




-
+


-
+



-
+



.AP ClientData clientData in
Arbitrary one-word value to pass to geometry manager callbacks.
.BE
.SH DESCRIPTION
.PP
\fBTk_ManageGeometry\fR arranges for a particular geometry manager,
described by the \fImgrPtr\fR argument, to control the geometry
of a particular slave window, given by \fItkwin\fR.
of a particular content window, given by \fItkwin\fR.
If \fItkwin\fR was previously managed by some other geometry manager,
the previous manager loses control in favor of the new one.
If \fImgrPtr\fR is NULL, geometry management is cancelled for
\fItkwin\fR.
.PP
The structure pointed to by \fImgrPtr\fR contains information about
the geometry manager:
.CS
typedef struct {
    const char *\fIname\fR;
    Tk_GeomRequestProc *\fIrequestProc\fR;
    Tk_GeomLostSlaveProc *\fIlostSlaveProc\fR;
    Tk_GeomLostContentProc *\fIlostContentProc\fR;
} \fBTk_GeomMgr\fR;
.CE
The \fIname\fR field is the textual name for the geometry manager,
such as \fBpack\fR or \fBplace\fR;  this value will be returned
by the command \fBwinfo manager\fR.
.PP
\fIrequestProc\fR is a procedure in the geometry manager that
will be invoked whenever \fBTk_GeometryRequest\fR is called by the
slave to change its desired geometry.
content window to change its desired geometry.
\fIrequestProc\fR should have arguments and results that match the
type \fBTk_GeomRequestProc\fR:
.CS
typedef void \fBTk_GeomRequestProc\fR(
        ClientData \fIclientData\fR,
        Tk_Window \fItkwin\fR);
.CE
The parameters to \fIrequestProc\fR will be identical to the
corresponding parameters passed to \fBTk_ManageGeometry\fR.
\fIclientData\fR usually points to a data
structure containing application-specific information about
how to manage \fItkwin\fR's geometry.
.PP
The \fIlostSlaveProc\fR field of \fImgrPtr\fR points to another
The \fIlostContentProc\fR field of \fImgrPtr\fR points to another
procedure in the geometry manager.
Tk will invoke \fIlostSlaveProc\fR if some other manager
Tk will invoke \fIlostContentProc\fR if some other manager
calls \fBTk_ManageGeometry\fR to claim
\fItkwin\fR away from the current geometry manager.
\fIlostSlaveProc\fR is not invoked if \fBTk_ManageGeometry\fR is
\fIlostContentProc\fR is not invoked if \fBTk_ManageGeometry\fR is
called with a NULL value for \fImgrPtr\fR (presumably the current
geometry manager has made this call, so it already knows that the
window is no longer managed), nor is it called if \fImgrPtr\fR
is the same as the window's current geometry manager.
\fIlostSlaveProc\fR should have
\fIlostContentProc\fR should have
arguments and results that match the following prototype:
.CS
typedef void \fBTk_GeomLostSlaveProc\fR(
typedef void \fBTk_GeomLostContentProc\fR(
        ClientData \fIclientData\fR,
        Tk_Window \fItkwin\fR);
.CE
The parameters to \fIlostSlaveProc\fR will be identical to the
The parameters to \fIlostContentProc\fR will be identical to the
corresponding parameters passed to \fBTk_ManageGeometry\fR.
.SH KEYWORDS
callback, geometry, managed, request, unmanaged
Changes to doc/MoveToplev.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1990-1993 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH Tk_MoveToplevelWindow 3 "" Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_MoveToplevelWindow \- Adjust the position of a top-level window
.SH SYNOPSIS
.nf
Changes to doc/Name.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1990 The Regents of the University of California.
'\" Copyright (c) 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.
'\" 
'\"
.TH Tk_Name 3 "" Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_Name, Tk_PathName, Tk_NameToWindow \- convert between names and window tokens
.SH SYNOPSIS
.nf
Changes to doc/NameOfImg.3.
10
11
12
13
14
15
16
17

18
19
20


21
22
23
24
25
26
27
10
11
12
13
14
15
16

17
18


19
20
21
22
23
24
25
26
27







-
+

-
-
+
+







.SH NAME
Tk_NameOfImage \- Return name of image.
.SH SYNOPSIS
.nf
\fB#include <tk.h>\fR
.sp
const char *
\fBTk_NameOfImage\fR(\fIimageMaster\fR)
\fBTk_NameOfImage\fR(\fIimageModel\fR)
.SH ARGUMENTS
.AS Tk_ImageMaster imageMaster
.AP Tk_ImageMaster imageMaster in
.AS Tk_ImageModel imageModel
.AP Tk_ImageModel imageModel in
Token for image, which was passed to image manager's \fIcreateProc\fR when
the image was created.
.BE
.SH DESCRIPTION
.PP
This procedure is invoked by image managers to find out the name
of an image.  Given the token for the image, it returns the
Changes to doc/OwnSelect.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1990-1994 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH Tk_OwnSelection 3 4.0 Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_OwnSelection \- make a window the owner of the primary selection
.SH SYNOPSIS
.nf
Changes to doc/ParseArgv.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1990-1992 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH Tk_ParseArgv 3 "" Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_ParseArgv \- process command-line options
.SH SYNOPSIS
.nf
68
69
70
71
72
73
74
75
76


77
78
79
80
81
82
83
68
69
70
71
72
73
74


75
76
77
78
79
80
81
82
83







-
-
+
+







.PP
The \fIargTable\fR array specifies the kinds of arguments that are
expected;  each of its entries has the following structure:
.CS
typedef struct {
    const char *\fIkey\fR;
    int \fItype\fR;
    char *\fIsrc\fR;
    char *\fIdst\fR;
    void *\fIsrc\fR;
    void *\fIdst\fR;
    const char *\fIhelp\fR;
} \fBTk_ArgvInfo\fR;
.CE
The \fIkey\fR field is a string such as
.QW \-display
or
.QW \-bg
308
309
310
311
312
313
314
315

316
317

318
319

320
321

322
323
324
325
326
327
328
308
309
310
311
312
313
314

315
316

317
318

319
320

321
322
323
324
325
326
327
328







-
+

-
+

-
+

-
+







char *fileName = defaultFileName;
Boolean exec = FALSE;

/*
 * Define option descriptions.
 */
Tk_ArgvInfo argTable[] = {
    {"\-X", TK_ARGV_CONSTANT, (char *) 1, (char *) &debugFlag,
    {"\-X", TK_ARGV_CONSTANT, (char *) 1, &debugFlag,
        "Turn on debugging printfs"},
    {"\-N", TK_ARGV_INT, NULL, (char *) &numReps,
    {"\-N", TK_ARGV_INT, NULL, &numReps,
        "Number of repetitions"},
    {"\-of", TK_ARGV_STRING, NULL, (char *) &fileName,
    {"\-of", TK_ARGV_STRING, NULL, &fileName,
        "Name of file for output"},
    {"x", TK_ARGV_REST, NULL, (char *) &exec,
    {"x", TK_ARGV_REST, NULL, &exec,
        "File to exec, followed by any arguments (must be last argument)."},
    {NULL, TK_ARGV_END, NULL, NULL,
        NULL}
};

main(argc, argv)
    int argc;
Changes to doc/QWinEvent.3.
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







'\"
'\" Copyright (c) 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.
'\" 
'\"
.TH Tk_QueueWindowEvent 3 7.5 Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_CollapseMotionEvents, Tk_QueueWindowEvent \- Add a window event to the Tcl event queue
.SH SYNOPSIS
.nf
Changes to doc/Restack.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1990 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH Tk_RestackWindow 3 "" Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_RestackWindow \- Change a window's position in the stacking order
.SH SYNOPSIS
.nf
Changes to doc/RestrictEv.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1990 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH Tk_RestrictEvents 3 "" Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_RestrictEvents \- filter and selectively delay X events
.SH SYNOPSIS
.nf
Changes to doc/SetAppName.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1994 The Regents of the University of California.
'\" Copyright (c) 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.
'\" 
'\"
.TH Tk_SetAppName 3 4.0 Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_SetAppName \- Set the name of an application for 'send' commands
.SH SYNOPSIS
.nf
Changes to doc/SetCaret.3.
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







'\"
'\" Copyright (c) 2002 ActiveState Corporation.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\"
.TH Tk_SetCaretPos 3 8.4 Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_SetCaretPos \- set the display caret location
.SH SYNOPSIS
.nf
Changes to doc/SetClass.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1990 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH Tk_SetClass 3 "" Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_SetClass, Tk_Class \- set or retrieve a window's class
.SH SYNOPSIS
.nf
Changes to doc/SetClassProcs.3.
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







'\"
'\" Copyright (c) 2000 Ajuba Solutions.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\"
.TH Tk_SetClassProcs 3 8.4 Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_SetClassProcs \- register widget specific procedures
.SH SYNOPSIS
.nf
29
30
31
32
33
34
35
36

37
38
39
40
41
42
43
29
30
31
32
33
34
35

36
37
38
39
40
41
42
43







-
+







.PP
\fBTk_SetClassProcs\fR is called to register a set of procedures that
are used as callbacks in different places.
.PP
The structure pointed to by \fIprocs\fR contains the following:
.CS
typedef struct Tk_ClassProcs {
    unsigned int \fIsize\fR;
    size_t \fIsize\fR;
    Tk_ClassWorldChangedProc *\fIworldChangedProc\fR;
    Tk_ClassCreateProc *\fIcreateProc\fR;
    Tk_ClassModalProc *\fImodalProc\fR;
} \fBTk_ClassProcs\fR;
.CE
The \fIsize\fR field is used to simplify future expansion of the
structure. It should always be set to (literally) \fBsizeof(Tk_ClassProcs)\fR.
Changes to doc/SetGrid.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1990-1994 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH Tk_SetGrid 3 4.0 Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_SetGrid, Tk_UnsetGrid \- control the grid for interactive resizing
.SH SYNOPSIS
.nf
Changes to doc/SetOptions.3.
1
2
3
4
5
6

7
8
9
10
11

12
13
14
15
16
17
18
1
2
3
4
5

6
7
8
9
10

11
12
13
14
15
16
17
18





-
+




-
+







'\"
'\" Copyright (c) 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.
'\" 
'\"
.TH Tk_SetOptions 3 8.1 Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_CreateOptionTable, Tk_DeleteOptionTable, Tk_InitOptions, Tk_SetOptions, Tk_FreeSavedOptions, Tk_RestoreSavedOptions, Tk_GetOptionValue,  Tk_GetOptionInfo, Tk_FreeConfigOptions, Tk_Offset \- process configuration options
Tk_CreateOptionTable, Tk_DeleteOptionTable, Tk_InitOptions, Tk_SetOptions, Tk_FreeSavedOptions, Tk_RestoreSavedOptions, Tk_GetOptionValue,  Tk_GetOptionInfo, Tk_FreeConfigOptions \- process configuration options
.SH SYNOPSIS
.nf
\fB#include <tk.h>\fR
.sp
Tk_OptionTable
\fBTk_CreateOptionTable(\fIinterp, templatePtr\fB)\fR
.sp
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

56
57
58
59
60
61
62
63
64
65
66

67
68
69
70
71
72
73
31
32
33
34
35
36
37



38
39
40
41
42
43
44
45
46
47
48
49
50
51

52
53
54
55
56
57
58
59
60
61
62

63
64
65
66
67
68
69
70







-
-
-














-
+










-
+







Tcl_Obj *
\fBTk_GetOptionValue(\fIinterp, recordPtr, optionTable, namePtr, tkwin\fB)\fR
.sp
Tcl_Obj *
\fBTk_GetOptionInfo(\fIinterp, recordPtr, optionTable, namePtr, tkwin\fB)\fR
.sp
\fBTk_FreeConfigOptions(\fIrecordPtr, optionTable, tkwin\fB)\fR
.sp
int
\fBTk_Offset(\fItype, field\fB)\fR
.SH ARGUMENTS
.AS Tk_SavedOptions "*const objv[]" in/out
.AP Tcl_Interp *interp in
A Tcl interpreter.  Most procedures use this only for returning error
messages; if it is NULL then no error messages are returned.  For
\fBTk_CreateOptionTable\fR the value cannot be NULL; it gives the
interpreter in which the option table will be used.
.AP "const Tk_OptionSpec" *templatePtr in
Points to an array of static information that describes the configuration
options that are supported.  Used to build a Tk_OptionTable.  The information
pointed to by this argument must exist for the lifetime of the Tk_OptionTable.
.AP Tk_OptionTable optionTable in
Token for an option table.  Must have been returned by a previous call
to \fBTk_CreateOptionTable\fR.
.AP char *recordPtr in/out
.AP void *recordPtr in/out
Points to structure in which values of configuration options are stored;
fields of this record are modified by procedures such as \fBTk_SetOptions\fR
and read by procedures such as \fBTk_GetOptionValue\fR.
.AP Tk_Window tkwin in
For options such as \fBTK_OPTION_COLOR\fR, this argument indicates
the window in which the option will be used.  If \fIoptionTable\fR uses
no window-dependent options, then a NULL value may be supplied for
this argument.
.AP int objc in
Number of values in \fIobjv\fR.
.AP Tcl_Obj "*const objv[]" in
.AP Tcl_Obj "*const *objv" in
Command-line arguments for setting configuring options.
.AP Tk_SavedOptions *savePtr out
If not NULL, the structure pointed to by this argument is filled
in with the old values of any options that were modified and old
values are restored automatically if an error occurs in \fBTk_SetOptions\fR.
.AP int *maskPtr out
If not NULL, the word pointed to by \fImaskPtr\fR is filled in with the
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262


263
264
265
266
267
268
269
232
233
234
235
236
237
238






239
240
241
242
243
244
245
246
247
248
249
250
251


252
253
254
255
256
257
258
259
260







-
-
-
-
-
-













-
-
+
+







(e.g., because \fInamePtr\fR contains an unknown option name) then NULL
is returned and an error message is left in \fIinterp\fR's result unless
\fIinterp\fR is NULL.
.PP
\fBTk_FreeConfigOptions\fR must be invoked when a widget is deleted.
It frees all of the resources associated with any of the configuration
options defined in \fIrecordPtr\fR by \fIoptionTable\fR.
.PP
The \fBTk_Offset\fR macro is provided as a safe way of generating the
\fIobjOffset\fR and \fIinternalOffset\fR values for entries in
Tk_OptionSpec structures.  It takes two arguments: the name of a type
of record, and the name of a field in that record. It returns the byte
offset of the named field in records of the given type.
.SH "TEMPLATES"
.PP
The array of Tk_OptionSpec structures passed to \fBTk_CreateOptionTable\fR
via its \fItemplatePtr\fR argument describes the configuration options
supported by a particular class of widgets.  Each structure specifies
one configuration option and has the following fields:
.CS
typedef struct {
    Tk_OptionType \fItype\fR;
    const char *\fIoptionName\fR;
    const char *\fIdbName\fR;
    const char *\fIdbClass\fR;
    const char *\fIdefValue\fR;
    int \fIobjOffset\fR;
    int \fIinternalOffset\fR;
    size_t \fIobjOffset\fR;
    size_t \fIinternalOffset\fR;
    int \fIflags\fR;
    const void *\fIclientData\fR;
    int \fItypeMask\fR;
} \fBTk_OptionSpec\fR;
.CE
The \fItype\fR field indicates what kind of configuration option this is
(e.g. \fBTK_OPTION_COLOR\fR for a color value, or \fBTK_OPTION_INT\fR for
277
278
279
280
281
282
283
284

285
286
287
288
289
290
291
268
269
270
271
272
273
274

275
276
277
278
279
280
281
282







-
+







\fIdbName\fR is NULL then the option database is not used by
\fBTk_InitOptions\fR for this option.  The \fIdefValue\fR field
specifies a default value for this configuration option if no
value is specified in the option database.  The \fIobjOffset\fR and
\fIinternalOffset\fR fields indicate where to store the value of this
option in widget records (more on this below); values for the \fIobjOffset\fR
and \fIinternalOffset\fR fields should always be generated with the
\fBTk_Offset\fR macro.
\fBoffsetof\fR macro.
The \fIflags\fR field contains additional information
to control the processing of this configuration option (see below
for details).
\fIClientData\fR provides additional type-specific data needed
by certain types.  For instance, for \fBTK_OPTION_COLOR\fR types,
\fIclientData\fR is a string giving the default value to use on
monochrome displays.  See the descriptions of the different types
Changes to doc/SetVisual.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1992 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH Tk_SetWindowVisual 3 4.0 Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_SetWindowVisual \- change visual characteristics of window
.SH SYNOPSIS
.nf
Changes to doc/StrictMotif.3.
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







'\"
'\" Copyright (c) 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.
'\" 
'\"
.TH Tk_StrictMotif 3 4.0 Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_StrictMotif \- Return value of tk_strictMotif variable
.SH SYNOPSIS
.nf
Changes to doc/TkInitStubs.3.
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







'\"
'\" Copyright (c) 1999 Scriptics Corporation
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\"
.TH Tk_InitStubs 3 8.4 Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_InitStubs \- initialize the Tk stubs mechanism
.SH SYNOPSIS
.nf
Changes to doc/Tk_Init.3.
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







'\"
'\" Copyright (c) 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.
'\" 
'\"
.TH Tk_Init 3 8.0 Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_Init, Tk_SafeInit \- add Tk to an interpreter and make a new Tk application.
.SH SYNOPSIS
.nf
Changes to doc/WindowId.3.
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31



32
33
34
35
36
37
38
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41











-
+



















+
+
+







'\"
'\" Copyright (c) 1990-1993 The Regents of the University of California.
'\" Copyright (c) 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.
'\"
.TH Tk_WindowId 3 "8.4" Tk "Tk Library Procedures"
.so man.macros
.BS
.SH NAME
Tk_WindowId, Tk_Parent, Tk_Display, Tk_DisplayName, Tk_ScreenNumber, Tk_Screen, Tk_X, Tk_Y, Tk_Width, Tk_Height, Tk_Changes, Tk_Attributes, Tk_IsContainer, Tk_IsEmbedded, Tk_IsMapped, Tk_IsTopLevel, Tk_ReqWidth, Tk_ReqHeight, Tk_MinReqWidth, Tk_MinReqHeight, Tk_InternalBorderLeft, Tk_InternalBorderRight, Tk_InternalBorderTop, Tk_InternalBorderBottom, Tk_Visual, Tk_Depth, Tk_Colormap, Tk_Interp  \- retrieve information from Tk's local data structure
Tk_WindowId, Tk_Parent, Tk_Display, Tk_DisplayName, Tk_ScreenNumber, Tk_AlwaysShowSelection, Tk_Screen, Tk_X, Tk_Y, Tk_Width, Tk_Height, Tk_Changes, Tk_Attributes, Tk_IsContainer, Tk_IsEmbedded, Tk_IsMapped, Tk_IsTopLevel, Tk_ReqWidth, Tk_ReqHeight, Tk_MinReqWidth, Tk_MinReqHeight, Tk_InternalBorderLeft, Tk_InternalBorderRight, Tk_InternalBorderTop, Tk_InternalBorderBottom, Tk_Visual, Tk_Depth, Tk_Colormap, Tk_Interp, Tk_NewWindowObj  \- retrieve information from Tk's local data structure
.SH SYNOPSIS
.nf
\fB#include <tk.h>\fR
.sp
Window
\fBTk_WindowId\fR(\fItkwin\fR)
.sp
Tk_Window
\fBTk_Parent\fR(\fItkwin\fR)
.sp
Display *
\fBTk_Display\fR(\fItkwin\fR)
.sp
const char *
\fBTk_DisplayName\fR(\fItkwin\fR)
.sp
int
\fBTk_ScreenNumber\fR(\fItkwin\fR)
.sp
int
\fBTk_AlwaysShowSelection\fR(\fItkwin\fR)
.sp
Screen *
\fBTk_Screen\fR(\fItkwin\fR)
.sp
int
\fBTk_X\fR(\fItkwin\fR)
.sp
int
93
94
95
96
97
98
99



100
101
102
103
104
105
106
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112







+
+
+







\fBTk_Depth\fR(\fItkwin\fR)
.sp
Colormap
\fBTk_Colormap\fR(\fItkwin\fR)
.sp
Tcl_Interp *
\fBTk_Interp\fR(\fItkwin\fR)
.sp
Tcl_Obj *
\fBTk_NewWindowObj\fR(\fItkwin\fR)
.SH ARGUMENTS
.AS Tk_Window tkwin
.AP Tk_Window tkwin in
Token for window.
.BE
.SH DESCRIPTION
.PP
123
124
125
126
127
128
129


130
131
132
133
134
135
136
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144







+
+







.PP
\fBTk_Display\fR returns a pointer to the Xlib display structure
corresponding to \fItkwin\fR.  \fBTk_DisplayName\fR returns an
ASCII string identifying \fItkwin\fR's display.  \fBTk_ScreenNumber\fR
returns the index of \fItkwin\fR's screen among all the screens
of \fItkwin\fR's display.  \fBTk_Screen\fR returns a pointer to
the Xlib structure corresponding to \fItkwin\fR's screen.
\fBTk_AlwaysShowSelection\fR indicates whether text/entry widgets
should always display their selection, regardless of window focus.
.PP
\fBTk_X\fR, \fBTk_Y\fR, \fBTk_Width\fR, and \fBTk_Height\fR
return information about \fItkwin's\fR location within its
parent and its size.  The location information refers to the
upper-left pixel in the window, or its border if there is one.
The width and height information refers to the interior size
of the window, not including any border.  \fBTk_Changes\fR
178
179
180
181
182
183
184


185
186
187
188
186
187
188
189
190
191
192
193
194
195
196
197
198







+
+




information about the visual characteristics of a window.
\fBTk_Visual\fR returns the visual type for
the window, \fBTk_Depth\fR returns the number of bits per pixel,
and \fBTk_Colormap\fR returns the current
colormap for the window.  The visual characteristics are
normally set from the defaults for the window's screen, but
they may be overridden by calling \fBTk_SetWindowVisual\fR.
.PP
\fBTk_NewWindowObj\fR creates a new \fBTcl_Obj\fR from the window.
.SH KEYWORDS
attributes, colormap, depth, display, height, geometry manager,
identifier, mapped, requested size, screen, top-level,
visual, width, window, x, y
Changes to doc/bell.n.
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







'\"
'\" Copyright (c) 1994 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\" Copyright (c) 2000 Ajuba Solutions.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\"
.TH bell n 8.4 Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
bell \- Ring a display's bell
.SH SYNOPSIS
Changes to doc/bind.n.
1
2
3
4

5
6
7
8
9
10
11
1
2
3

4
5
6
7
8
9
10
11



-
+







'\"
'\" 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"
.so man.macros
.BS
66
67
68
69
70
71
72
73

74
75
76
77
78
79
80
66
67
68
69
70
71
72

73
74
75
76
77
78
79
80







-
+







.PP
The \fIsequence\fR argument specifies a sequence of one or more
event patterns, with optional white space between the patterns.  Each
event pattern may
take one of three forms.  In the simplest case it is a single
printing ASCII character, such as \fBa\fR or \fB[\fR.  The character
may not be a space character or the character \fB<\fR.  This form of
pattern matches a \fBKeyPress\fR event for the particular
pattern matches a \fBKey\fR event for the particular
character.  The second form of pattern is longer but more general.
It has the following syntax:
.CS
\fB<\fImodifier\-modifier\-type\-detail\fB>\fR
.CE
The entire event pattern is surrounded by angle brackets.
Inside the angle brackets are zero or more modifiers, an event
164
165
166
167
168
169
170
171

172
173

174
175
176
177
178

179
180
181
182
183
184
185
164
165
166
167
168
169
170

171
172

173
174
175
176
177

178
179
180
181
182
183
184
185







-
+

-
+




-
+







.PP
The \fItype\fR field may be any of the standard X event types, with a
few extra abbreviations.  The \fItype\fR field will also accept a
couple non-standard X event types that were added to better support
the Macintosh and Windows platforms.  Below is a list of all the valid
types; where two names appear together, they are synonyms.
.DS
.ta \w'\fBButtonPress, Button\0\0\0\fR'u +\w'\fBKeyPress, Key\0\0\0\fR'u
.ta \w'\fBButton, ButtonPress\0\0\0\fR'u +\w'\fBKey, KeyPress\0\0\0\fR'u
\fBActivate\fR	\fBDestroy\fR	\fBMap\fR
\fBButtonPress\fR, \fBButton\fR	\fBEnter\fR	\fBMapRequest\fR
\fBButton\fR, \fBButtonPress\fR	\fBEnter\fR	\fBMapRequest\fR
\fBButtonRelease\fR	\fBExpose\fR	\fBMotion\fR
\fBCirculate\fR	\fBFocusIn\fR	\fBMouseWheel\fR
\fBCirculateRequest\fR	\fBFocusOut\fR	\fBProperty\fR
\fBColormap\fR	\fBGravity\fR	\fBReparent\fR
\fBConfigure\fR	\fBKeyPress\fR, \fBKey\fR	\fBResizeRequest\fR
\fBConfigure\fR	\fBKey\fR, \fBKeyPress\fR	\fBResizeRequest\fR
\fBConfigureRequest\fR	\fBKeyRelease\fR	\fBUnmap\fR
\fBCreate\fR	\fBLeave\fR	\fBVisibility\fR
\fBDeactivate\fR
.DE
Most of the above events have the same fields and behaviors as events
in the X Windowing system.  You can find more detailed descriptions of
these events in any X window programming book.  A couple of the events
197
198
199
200
201
202
203
204
205


206
207

208
209

210
211









212
213
214



215
216
217


218
219
220

221
222
223
224
225
226

227
228
229
230
231
232
233
197
198
199
200
201
202
203


204
205
206

207
208

209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227


228
229
230
231

232
233
234
235
236
237

238
239
240
241
242
243
244
245







-
-
+
+

-
+

-
+


+
+
+
+
+
+
+
+
+



+
+
+

-
-
+
+


-
+





-
+







active.  Likewise, the \fBDeactive\fR event is sent when the window's
state changes from active to deactive.  There are no useful percent
substitutions you would make when binding to these events.
.IP \fBMouseWheel\fR 5
Many contemporary mice support a mouse wheel, which is used
for scrolling documents without using the scrollbars.  By rolling the
wheel, the system will generate \fBMouseWheel\fR events that the
application can use to scroll.  Like \fBKey\fR events the event is
always routed to the window that currently has focus. When the event
application can use to scroll.  The event is routed to the
window currently under the mouse pointer. When the event
is received you can use the \fB%D\fR substitution to get the
\fIdelta\fR field for the event, which is a integer value describing how
\fIdelta\fR field for the event, which is an integer value describing how
the mouse wheel has moved.  The smallest value for which the
system will report is defined by the OS. The sign of the
system will report is defined by the OS.  The sign of the
value determines which direction your widget should scroll.  Positive
values should scroll up and negative values should scroll down.
.RS
.PP
Horizontal scrolling uses \fBShift-MouseWheel\fR events, with positive
\fB%D\fR \fIdelta\fR substitution indicating left scrolling and negative
right scrolling.
Horizontal scrolling events may fire from
many different hardware units such as tilt wheels or touchpads.  Horizontal
scrolling can also be emulated by holding Shift and scrolling vertically.
.RE
.IP "\fBKeyPress\fR, \fBKeyRelease\fR" 5
The \fBKeyPress\fR and \fBKeyRelease\fR events are generated
whenever a key is pressed or released.  \fBKeyPress\fR and \fBKeyRelease\fR
.IP "\fBKey\fR, \fBKeyRelease\fR" 5
The \fBKey\fR and \fBKeyRelease\fR events are generated
whenever a key is pressed or released.  \fBKey\fR and \fBKeyRelease\fR
events are sent to the window which currently has the keyboard focus.
.IP "\fBButtonPress\fR, \fBButtonRelease\fR, \fBMotion\fR" 5
The \fBButtonPress\fR and \fBButtonRelease\fR events
.IP "\fBButton\fR, \fBButtonRelease\fR, \fBMotion\fR" 5
The \fBButton\fR and \fBButtonRelease\fR events
are generated when the user presses or releases a mouse button.
\fBMotion\fR events are generated whenever the pointer is moved.
\fBButtonPress\fR, \fBButtonRelease\fR, and \fBMotion\fR events are
\fBButton\fR, \fBButtonRelease\fR, and \fBMotion\fR events are
normally sent to the window containing the pointer.
.RS
.PP
When a mouse button is pressed, the window containing the pointer
automatically obtains a temporary pointer grab.
Subsequent \fBButtonPress\fR, \fBButtonRelease\fR, and \fBMotion\fR
Subsequent \fBButton\fR, \fBButtonRelease\fR, and \fBMotion\fR
events will be sent to that window,
regardless of which window contains the pointer,
until all buttons have been released.
.RE
.IP \fBConfigure\fR 5
A \fBConfigure\fR event is sent to a window whenever its
size, position, or border width changes, and sometimes
266
267
268
269
270
271
272
273


274
275
276
277
278
279
280
278
279
280
281
282
283
284

285
286
287
288
289
290
291
292
293







-
+
+







A \fBDestroy\fR event is delivered to a window when
it is destroyed.
.RS
.PP
When the \fBDestroy\fR event is delivered
to a widget, it is in a
.QW half-dead
state: the widget still exists, but most operations on it will fail.
state: the widget still exists, but operations that involve it
may return invalid results, or return an error.
.RE
.IP "\fBFocusIn\fR, \fBFocusOut\fR" 5
The \fBFocusIn\fR and \fBFocusOut\fR events are generated
whenever the keyboard focus changes.
A \fBFocusOut\fR event is sent to the old focus window,
and a \fBFocusIn\fR event is sent to the new one.
.RS
347
348
349
350
351
352
353
354
355


356
357
358
359
360
361
362
363
364


365
366

367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386

387
388

389
390
391
392
393
394
395
360
361
362
363
364
365
366


367
368
369
370
371
372
373
374
375


376
377
378

379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398

399
400

401
402
403
404
405
406
407
408







-
-
+
+







-
-
+
+

-
+



















-
+

-
+







This event type is included only for completeness;
there is no reliable way to track changes to a window's
position in the stacking order.
.RE
.SS "EVENT DETAILS"
.PP
The last part of a long event specification is \fIdetail\fR.  In the
case of a \fBButtonPress\fR or \fBButtonRelease\fR event, it is the
number of a button (1\-5).  If a button number is given, then only an
case of a \fBButton\fR or \fBButtonRelease\fR event, it is the
number of a button (1\-9).  If a button number is given, then only an
event on that particular button will match;  if no button number is
given, then an event on any button will match.  Note:  giving a
specific button number is different than specifying a button modifier;
in the first case, it refers to a button being pressed or released,
while in the second it refers to some other button that is already
depressed when the matching event occurs.  If a button
number is given then \fItype\fR may be omitted:  if will default
to \fBButtonPress\fR.  For example, the specifier \fB<1>\fR
is equivalent to \fB<ButtonPress\-1>\fR.
to \fBButton\fR.  For example, the specifier \fB<1>\fR
is equivalent to \fB<Button\-1>\fR.
.PP
If the event type is \fBKeyPress\fR or \fBKeyRelease\fR, then
If the event type is \fBKey\fR or \fBKeyRelease\fR, then
\fIdetail\fR may be specified in the form of an X keysym.  Keysyms
are textual specifications for particular keys on the keyboard;
they include all the alphanumeric ASCII characters (e.g.
.QW a
is the keysym for the ASCII character
.QW a ),
plus descriptions for non-alphanumeric characters
.PQ comma "is the keysym for the comma character" ,
plus descriptions for all the non-ASCII keys on the keyboard (e.g.
.QW Shift_L
is the keysym for the left shift key, and
.QW F1
is the keysym for the F1 function key, if it exists).  The
complete list of keysyms is not presented here;  it is
available in other X documentation and may vary from system to
system.
If necessary, you can use the \fB%K\fR notation described below
to print out the keysym name for a particular key.
If a keysym \fIdetail\fR is given, then the
\fItype\fR field may be omitted;  it will default to \fBKeyPress\fR.
\fItype\fR field may be omitted;  it will default to \fBKey\fR.
For example, \fB<Control\-comma>\fR is equivalent to
\fB<Control\-KeyPress\-comma>\fR.
\fB<Control\-Key\-comma>\fR.
.SH "BINDING SCRIPTS AND SUBSTITUTIONS"
.PP
The \fIscript\fR argument to \fBbind\fR is a Tcl script, called the
.QW "binding script",
which will be executed whenever the given event sequence occurs.
\fICommand\fR will be executed in the same interpreter that the
\fBbind\fR command was executed in, and it will run at global
417
418
419
420
421
422
423
424

425
426
427
428
429
430
431
430
431
432
433
434
435
436

437
438
439
440
441
442
443
444







-
+







formatted as a hexadecimal number.
Valid only for \fBConfigure\fR events.
Indicates the sibling window immediately below the receiving window
in the stacking order, or \fB0\fR if the receiving window is at the
bottom.
.IP \fB%b\fR 5
The number of the button that was pressed or released.  Valid only
for \fBButtonPress\fR and \fBButtonRelease\fR events.
for \fBButton\fR and \fBButtonRelease\fR events.
.IP \fB%c\fR 5
The \fIcount\fR field from the event.  Valid only for \fBExpose\fR events.
Indicates that there are \fIcount\fR pending \fBExpose\fR events which have not
yet been delivered to the window.
.IP \fB%d\fR 5
The \fIdetail\fR or \fIuser_data\fR
field from the event.  The \fB%d\fR is replaced by
464
465
466
467
468
469
470
471

472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487


488
489
490
491
492
493
494
477
478
479
480
481
482
483

484
485
486
487
488
489
490
491
492
493
494
495
496
497
498


499
500
501
502
503
504
505
506
507







-
+














-
-
+
+







\fBConfigureRequest\fR, \fBCreate\fR, \fBResizeRequest\fR, and
\fBExpose\fR events.
Indicates the new or requested height of the window.
.IP \fB%i\fR 5
The \fIwindow\fR field from the event, represented as a hexadecimal
integer.  Valid for all event types.
.IP \fB%k\fR 5
The \fIkeycode\fR field from the event.  Valid only for \fBKeyPress\fR
The \fIkeycode\fR field from the event.  Valid only for \fBKey\fR
and \fBKeyRelease\fR events.
.IP \fB%m\fR 5
The \fImode\fR field from the event.  The substituted string is one of
\fBNotifyNormal\fR, \fBNotifyGrab\fR, \fBNotifyUngrab\fR, or
\fBNotifyWhileGrabbed\fR.  Valid only for \fBEnter\fR,
\fBFocusIn\fR, \fBFocusOut\fR, and \fBLeave\fR events.
.IP \fB%o\fR 5
The \fIoverride_redirect\fR field from the event.  Valid only for
\fBMap\fR, \fBReparent\fR, and \fBConfigure\fR events.
.IP \fB%p\fR 5
The \fIplace\fR field from the event, substituted as one of the
strings \fBPlaceOnTop\fR or \fBPlaceOnBottom\fR.  Valid only
for \fBCirculate\fR and \fBCirculateRequest\fR events.
.IP \fB%s\fR 5
The \fIstate\fR field from the event.  For \fBButtonPress\fR,
\fBButtonRelease\fR, \fBEnter\fR, \fBKeyPress\fR, \fBKeyRelease\fR,
The \fIstate\fR field from the event.  For \fBButton\fR,
\fBButtonRelease\fR, \fBEnter\fR, \fBKey\fR, \fBKeyRelease\fR,
\fBLeave\fR, and \fBMotion\fR events, a decimal string
is substituted.  For \fBVisibility\fR, one of the strings
\fBVisibilityUnobscured\fR, \fBVisibilityPartiallyObscured\fR,
and \fBVisibilityFullyObscured\fR is substituted.
For \fBProperty\fR events, substituted with
either the string \fBNewValue\fR (indicating that the property
has been created or modified) or \fBDelete\fR (indicating that
502
503
504
505
506
507
508
509
510


511
512



513
514
515
516
517
518
519
520

521
522

523

524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541

542
543
544
545
546
547

548
549
550
551
552
553
554
515
516
517
518
519
520
521


522
523
524
525
526
527
528
529
530
531
532
533
534
535

536
537
538
539

540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557

558
559
560
561
562
563

564
565
566
567
568
569
570
571







-
-
+
+


+
+
+







-
+


+
-
+

















-
+





-
+







The \fIwidth\fR field from the event.
Indicates the new or requested width of the window.
Valid only for
\fBConfigure\fR, \fBConfigureRequest\fR, \fBCreate\fR,
\fBResizeRequest\fR, and \fBExpose\fR events.
.IP "\fB%x\fR, \fB%y\fR" 5
The \fIx\fR and \fIy\fR fields from the event.
For \fBButtonPress\fR, \fBButtonRelease\fR, \fBMotion\fR,
\fBKeyPress\fR, \fBKeyRelease\fR, and \fBMouseWheel\fR events,
For \fBButton\fR, \fBButtonRelease\fR, \fBMotion\fR,
\fBKey\fR, \fBKeyRelease\fR, and \fBMouseWheel\fR events,
\fB%x\fR and \fB%y\fR indicate the position of the mouse pointer
relative to the receiving window.
For key events on the Macintosh these are the coordinates of the
mouse at the moment when an X11 KeyEvent is sent to Tk, which could
be slightly later than the time of the physical press or release.
For \fBEnter\fR and \fBLeave\fR events, the position where the
mouse pointer crossed the window, relative to the receiving window.
For \fBConfigure\fR and \fBCreate\fR requests, the \fIx\fR and \fIy\fR
coordinates of the window relative to its parent window.
.IP \fB%A\fR 5
Substitutes the UNICODE character corresponding to the event, or
the empty string if the event does not correspond to a UNICODE character
(e.g. the shift key was pressed). \fBXmbLookupString\fR (or
(e.g. the shift key was pressed). On X11, \fBXmbLookupString\fR (or
\fBXLookupString\fR when input method support is turned off) does all
the work of translating from the event to a UNICODE character.
On X11, valid only for \fBKey\fR event. On Windows and macOS/aqua,
Valid only for \fBKeyPress\fR and \fBKeyRelease\fR events.
valid only for \fBKey\fR and \fBKeyRelease\fR events.
.IP \fB%B\fR 5
The \fIborder_width\fR field from the event.  Valid only for
\fBConfigure\fR, \fBConfigureRequest\fR, and \fBCreate\fR events.
.IP \fB%D\fR 5
This reports the \fIdelta\fR value of a \fBMouseWheel\fR event.  The
\fIdelta\fR value represents the rotation units the mouse wheel has
been moved. The sign of the value represents the direction the mouse
wheel was scrolled.
.IP \fB%E\fR 5
The \fIsend_event\fR field from the event.  Valid for all event types.
\fB0\fR indicates that this is a
.QW normal
event, \fB1\fR indicates that it is a
.QW synthetic
event generated by \fBSendEvent\fR.
.IP \fB%K\fR 5
The keysym corresponding to the event, substituted as a textual
string.  Valid only for \fBKeyPress\fR and \fBKeyRelease\fR events.
string.  Valid only for \fBKey\fR and \fBKeyRelease\fR events.
.IP \fB%M\fR 5
The number of script-based binding patterns matched so far for the
event.  Valid for all event types.
.IP \fB%N\fR 5
The keysym corresponding to the event, substituted as a decimal
number.  Valid only for \fBKeyPress\fR and \fBKeyRelease\fR events.
number.  Valid only for \fBKey\fR and \fBKeyRelease\fR events.
.IP \fB%P\fR 5
The name of the property being updated or deleted (which
may be converted to an XAtom using \fBwinfo atom\fR.) Valid
only for \fBProperty\fR events.
.IP \fB%R\fR 5
The \fIroot\fR window identifier from the event.  Valid only for
events containing a \fIroot\fR field.
562
563
564
565
566
567
568
569

570
571
572
573
574
575
576
579
580
581
582
583
584
585

586
587
588
589
590
591
592
593







-
+







The path name of the window to which the event was reported (the
\fIwindow\fR field from the event).  Valid for all event types.
.IP "\fB%X\fR, \fB%Y\fR" 5
The \fIx_root\fR and  \fIy_root\fR fields from the event.
If a virtual-root window manager is being used then the substituted
values are the corresponding x-coordinate and y-coordinate in the virtual root.
Valid only for
\fBButtonPress\fR, \fBButtonRelease\fR, \fBEnter\fR, \fBKeyPress\fR,
\fBButton\fR, \fBButtonRelease\fR, \fBEnter\fR, \fBKey\fR,
\fBKeyRelease\fR, \fBLeave\fR and \fBMotion\fR events.
Same meaning as \fB%x\fR and \fB%y\fR, except relative to the (virtual) root
window.
.LP
The replacement string for a %-replacement is formatted as a proper
Tcl list element.
This means that spaces or special characters such as \fB$\fR and
629
630
631
632
633
634
635
636
637



638
639
640
641
642
643
644
646
647
648
649
650
651
652


653
654
655
656
657
658
659
660
661
662







-
-
+
+
+







The following tests are applied, in order, to determine which of
several matching sequences is more specific:
.RS
.IP (a)
an event pattern that specifies a specific button or key is more specific
than one that does not;
.IP (b)
a longer sequence (in terms of number
of events matched) is more specific than a shorter sequence;
a sequence with the most highest-ordered patterns (in term of highest
repetition count) is more specific than a sequence with less
highest-ordered patterns;
.IP (c)
if the modifiers specified in one pattern are a subset of the
modifiers in another pattern, then the pattern with more modifiers
is more specific;
.IP (d)
a virtual event whose physical pattern matches the sequence is less
specific than the same physical pattern that is not associated with a
674
675
676
677
678
679
680
681

682
683
684
685
686


687
688
689
690
691



692
693
694
695
696
697
698
692
693
694
695
696
697
698

699
700
701
702


703
704
705
706



707
708
709
710
711
712
713
714
715
716







-
+



-
-
+
+


-
-
-
+
+
+







An unbound event is not considered to be an error.
.SH "MULTI-EVENT SEQUENCES AND IGNORED EVENTS"
.PP
When a \fIsequence\fR specified in a \fBbind\fR command contains
more than one event pattern, then its script is executed whenever
the recent events (leading up to and including the current event)
match the given sequence.  This means, for example, that if button 1 is
clicked repeatedly the sequence \fB<Double\-ButtonPress\-1>\fR will match
clicked repeatedly the sequence \fB<Double\-Button\-1>\fR will match
each button press but the first.
If extraneous events that would prevent a match occur in the middle
of an event sequence then the extraneous events are
ignored unless they are \fBKeyPress\fR or \fBButtonPress\fR events.
For example, \fB<Double\-ButtonPress\-1>\fR will match a sequence of
ignored unless they are \fBKey\fR or \fBButton\fR events.
For example, \fB<Double\-Button\-1>\fR will match a sequence of
presses of button 1, even though there will be \fBButtonRelease\fR
events (and possibly \fBMotion\fR events) between the
\fBButtonPress\fR events.
Furthermore, a \fBKeyPress\fR event may be preceded by any number
of other \fBKeyPress\fR events for modifier keys without the
\fBButton\fR events.
Furthermore, a \fBKey\fR event may be preceded by any number
of other \fBKey\fR events for modifier keys without the
modifier keys preventing a match.
For example, the event sequence \fBaB\fR will match a press of the
\fBa\fR key, a release of the \fBa\fR key, a press of the \fBShift\fR
key, and a press of the \fBb\fR key:  the press of \fBShift\fR is
ignored because it is a modifier key.
Finally, if several \fBMotion\fR events occur in a row, only
the last one is used for purposes of matching binding sequences.
Changes to doc/bindtags.n.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1990 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH bindtags n 4.0 Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
bindtags \- Determine which bindings apply to a window, and order of evaluation
.SH SYNOPSIS
Changes to doc/bitmap.n.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1994 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH bitmap n 4.0 Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
bitmap \- Images that display two colors
.SH SYNOPSIS
86
87
88
89
90
91
92
93

94
95
96
97
98
99
100
86
87
88
89
90
91
92

93
94
95
96
97
98
99
100







-
+







.PP
When a bitmap image is created, Tk also creates a new command
whose name is the same as the image.
This command may be used to invoke various operations
on the image.
It has the following general form:
.CS
\fIimageName option \fR?\fIarg arg ...\fR?
\fIimageName option \fR?\fIarg ...\fR?
.CE
\fIOption\fR and the \fIarg\fRs
determine the exact behavior of the command.  The following
commands are possible for bitmap images:
.TP
\fIimageName \fBcget\fR \fIoption\fR
.
Changes to doc/busy.n.
24
25
26
27
28
29
30
31

32
33


34
35
36
37
38
39
40
41
42
43
44
45
46
47
48


49
50
51
52
53
54
55
24
25
26
27
28
29
30

31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48


49
50
51
52
53
54
55
56
57







-
+


+
+













-
-
+
+







'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH busy n "" Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
busy \- confine pointer events to a window sub-tree
busy \- Make Tk widgets busy, temporarily blocking user interactions
.SH SYNOPSIS
\fBtk busy\fR \fIwindow \fR?\fIoptions\fR?
.sp
\fBtk busy busywindow \fIwindow\fR
.sp
\fBtk busy hold\fR \fIwindow \fR?\fIoptions\fR?
.sp
\fBtk busy configure \fIwindow\fR ?\fIoption value\fR?...
.sp
\fBtk busy forget\fR \fIwindow \fR?\fIwindow \fR?...
.sp
\fBtk busy current\fR ?\fIpattern\fR?
.sp
\fBtk busy status \fIwindow\fR
.BE
.SH DESCRIPTION
.PP
The \fBtk busy\fR command provides a simple means to block pointer events from
Tk widgets, while overriding the widget's cursor with a configurable busy
The \fBtk busy\fR command provides a simple means to block mouse pointer events
from Tk widgets, while overriding the widget's cursor with a configurable busy
cursor. Note this command does not prevent keyboard events from being sent to
the widgets made busy.
.SH INTRODUCTION
.PP
There are many times in applications where you want to temporarily restrict
what actions the user can take. For example, an application could have a
.QW Run
124
125
126
127
128
129
130
131

132
133
134
135

136
137

138
139
140
141
142
143

144
145
146
147
148
149
150
151
152
153
154
155
126
127
128
129
130
131
132

133
134



135


136






137





138
139
140
141
142
143
144







-
+

-
-
-
+
-
-
+
-
-
-
-
-
-
+
-
-
-
-
-







.PP
The following operations are available for the \fBtk busy\fR command:
.TP
\fBtk busy \fIwindow\fR ?\fIoption value\fR?...
.
Shortcut for \fBtk busy hold\fR command.
.TP
\fBtk busy hold \fIwindow\fR ?\fIoption value\fR?...
\fBtk busy busywindow \fIwindow\fR
.
Makes the specified \fIwindow\fR (and its descendants in the Tk window
hierarchy) appear busy. \fIWindow\fR must be a valid path name of a Tk widget.
A transparent window is put in front of the specified window. This transparent
Returns the pathname of the busy window (i.e. the transparent window
window is mapped the next time idle tasks are processed, and the specified
window and its descendants will be blocked from user interactions. Normally
shielding the window appearing busy) created by the \fBtk busy hold\fR
\fBupdate\fR should be called immediately afterward to insure that the hold
operation is in effect before the application starts its processing. The
following configuration options are valid:
.RS
.TP
\fB\-cursor \fIcursorName\fR
command for \fIwindow\fR, or the empty string if \fIwindow\fR is not busy.
.
Specifies the cursor to be displayed when the widget is made busy.
\fICursorName\fR can be in any form accepted by \fBTk_GetCursor\fR. The
default cursor is \fBwait\fR on Windows and \fBwatch\fR on other platforms.
.RE
.TP
\fBtk busy cget \fIwindow\fR \fIoption\fR
.
Queries the \fBtk busy\fR command configuration options for \fIwindow\fR.
\fIWindow\fR must be the path name of a widget previously made busy by the
\fBhold\fR operation. The command returns the present value of the specified
\fIoption\fR. \fIOption\fR may have any of the values accepted by the
176
177
178
179
180
181
182






183
184
185
186
187
188
189
190
191
192

193
194
195
196


















197
198
199
200
201
202
203
204
205
206
207
208
209
210


211
212
213
214

215
216
217
218

219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234


235
236
237
238
239
240
241
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186

187
188



189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218


219
220
221
222
223

224
225
226


227













228


229
230
231
232
233
234
235
236
237







+
+
+
+
+
+









-
+

-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+












-
-
+
+



-
+


-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
+
+







specified for it by either \fBoption\fR command:
.PP
.CS
option add *frame.busyCursor gumby
option add *Frame.BusyCursor gumby
.CE
.RE
.TP
\fBtk busy current \fR?\fIpattern\fR?
.
Returns the pathnames of all widgets that are currently busy. If a
\fIpattern\fR is given, only the path names of busy widgets matching
\fIpattern\fR are returned.
.TP
\fBtk busy forget \fIwindow\fR ?\fIwindow\fR?...
.
Releases resources allocated by the \fBtk busy\fR command for \fIwindow\fR,
including the transparent window. User events will again be received by
\fIwindow\fR. Resources are also released when \fIwindow\fR is destroyed.
\fIWindow\fR must be the name of a widget specified in the \fBhold\fR
operation, otherwise an error is reported.
.TP
\fBtk busy current \fR?\fIpattern\fR?
\fBtk busy hold \fIwindow\fR ?\fIoption value\fR?...
.
Returns the pathnames of all widgets that are currently busy. If a
\fIpattern\fR is given, only the path names of busy widgets matching
\fIpattern\fR are returned.
Makes the specified \fIwindow\fR (and its descendants in the Tk window
hierarchy) appear busy. \fIWindow\fR must be a valid path name of a Tk widget.
A transparent window is put in front of the specified window. This transparent
window is mapped the next time idle tasks are processed, and the specified
window and its descendants will be blocked from user interactions. Normally
\fBupdate\fR should be called immediately afterward to insure that the hold
operation is in effect before the application starts its processing. The
command returns the pathname of the busy window that was created (i.e. the
transparent window shielding the window appearing busy). The following
configuration options are valid:
.RS
.TP
\fB\-cursor \fIcursorName\fR
.
Specifies the cursor to be displayed when the widget is made busy.
\fICursorName\fR can be in any form accepted by \fBTk_GetCursor\fR. The
default cursor is \fBwait\fR on Windows and \fBwatch\fR on other platforms.
.RE
.TP
\fBtk busy status \fIwindow\fR
.
Returns the status of a widget \fIwindow\fR. If \fIwindow\fR presently can not
receive user interactions, \fB1\fR is returned, otherwise \fB0\fR.
.SH "EVENT HANDLING"
.SS BINDINGS
.PP
The event blocking feature is implemented by creating and mapping a
transparent window that completely covers the widget. When the busy window is
mapped, it invisibly shields the widget and its hierarchy from all events that
may be sent. Like Tk widgets, busy windows have widget names in the Tk window
hierarchy. This means that you can use the \fBbind\fR command, to handle
events in the busy window.
hierarchy. This means that you can use the \fBbind\fR command to handle
events in the busy window:
.PP
.CS
\fBtk busy\fR hold .frame.canvas
bind .frame.canvas_Busy <Enter> { ... }
bind [\fBtk busy\fR busywindow .frame.canvas] <Enter> { ... }
.CE
.PP
Normally the busy window is a sibling of the widget. The name of the busy
window is
or
.QW \fIwidget\fB_Busy\fR
where \fIwidget\fR is the name of the widget to be made busy. In the previous
example, the pathname of the busy window is
.QW \fB.frame.canvas_Busy\fR .
The exception is when the widget is a toplevel widget (such as
.QW . )
where the busy window can't be made a sibling. The busy window is then a child
of the widget named
.QW \fIwidget\fB._Busy\fR
where \fIwidget\fR is the name of the toplevel widget. In the following
example, the pathname of the busy window is
.QW \fB._Busy\fR .
.PP
.CS
\fBtk busy\fR hold .
bind ._Busy <Enter> { ... }
set busyWin [\fBtk busy\fR hold .frame.canvas]
bind $busyWin <Enter> { ... }
.CE
.SS "ENTER/LEAVE EVENTS"
.PP
Mapping and unmapping busy windows generates Enter/Leave events for all
widgets they cover. Please note this if you are tracking Enter/Leave events in
widgets.
.SS "KEYBOARD EVENTS"
Changes to doc/button.n.
105
106
107
108
109
110
111
112

113
114
115
116
117
118
119
105
106
107
108
109
110
111

112
113
114
115
116
117
118
119







-
+







.SH "WIDGET COMMAND"
.PP
The \fBbutton\fR command creates a new Tcl command whose
name is \fIpathName\fR.  This
command may be used to invoke various
operations on the widget.  It has the following general form:
.CS
\fIpathName option \fR?\fIarg arg ...\fR?
\fIpathName option \fR?\fIarg ...\fR?
.CE
\fIOption\fR and the \fIarg\fRs
determine the exact behavior of the command.  The following
commands are possible for button widgets:
.TP
\fIpathName \fBcget\fR \fIoption\fR
Returns the current value of the configuration option given
Changes to doc/canvas.n.
216
217
218
219
220
221
222
223
224






225
226
227
228
229
230
231
216
217
218
219
220
221
222


223
224
225
226
227
228
229
230
231
232
233
234
235







-
-
+
+
+
+
+
+







It is possible to adjust the origin of the canvas
coordinate system relative to the origin of the window using the
\fBxview\fR and \fByview\fR widget commands; this is typically used
for scrolling.
Canvases do not support scaling or rotation of the canvas coordinate
system relative to the window coordinate system.
.PP
Individual items may be moved or scaled using widget commands
described below, but they may not be rotated.
Individual items may be moved, scaled
.VS "8.7, TIP164"
or rotated
.VE "8.7, TIP164"
using widget commands
described below.
.PP
Note that the default origin of the canvas's visible area is
coincident with the origin for the whole window as that makes bindings
using the mouse position easier to work with; you only need to use the
\fBcanvasx\fR and \fBcanvasy\fR widget commands if you adjust the
origin of the visible area. However, this also means that any focus
ring (as controlled by the \fB\-highlightthickness\fR option) and
309
310
311
312
313
314
315

316
317
318
319
320
321
322
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327







+







.PP
The second possible syntax is a character list containing only
5 possible characters
.QW "\fB.,-_ \fR" .
The space can be used
to enlarge the space between other line elements, and cannot
occur as the first position in the string. Some examples:
.PP
.CS
\-dash .     \(-> \-dash {2 4}
\-dash -     \(-> \-dash {6 4}
\-dash -.    \(-> \-dash {6 4 2 4}
\-dash -..   \(-> \-dash {6 4 2 4 2 4}
\-dash {. }  \(-> \-dash {2 8}
\-dash ,     \(-> \-dash {4 4}
339
340
341
342
343
344
345
346

347
348
349
350
351
352

353
354
355
356
357
358
359
344
345
346
347
348
349
350

351
352
353
354
355
356

357
358
359
360
361
362
363
364







-
+





-
+







.SH "WIDGET COMMAND"
.PP
The \fBcanvas\fR command creates a new Tcl command whose
name is \fIpathName\fR. This
command may be used to invoke various
operations on the widget. It has the following general form:
.CS
\fIpathName option \fR?\fIarg arg ...\fR?
\fIpathName option \fR?\fIarg ...\fR?
.CE
\fIOption\fR and the \fIarg\fRs
determine the exact behavior of the command.
The following widget commands are possible for canvas widgets:
.TP
\fIpathName \fBaddtag \fItag searchSpec \fR?\fIarg arg ...\fR?
\fIpathName \fBaddtag \fItag searchSpec \fR?\fIarg ...\fR?
.
For each item that meets the constraints specified by
\fIsearchSpec\fR and the \fIarg\fRs, add
\fItag\fR to the list of tags associated with the item if it
is not already present on that list.
It is possible that no items will satisfy the constraints
given by \fIsearchSpec\fR and \fIarg\fRs, in which case the
461
462
463
464
465
466
467
468

469
470
471
472
473
474
475
466
467
468
469
470
471
472

473
474
475
476
477
478
479
480







-
+







If both \fIcommand\fR and \fIsequence\fR are omitted then the command
returns a list of all the sequences for which bindings have been
defined for \fItagOrId\fR.
.RS
.PP
The only events for which bindings may be specified are those related to
the mouse and keyboard (such as \fBEnter\fR, \fBLeave\fR,
\fBButtonPress\fR, \fBMotion\fR, and \fBKeyPress\fR) or virtual events.
\fBButton\fR, \fBMotion\fR, and \fBKey\fR) or virtual events.
The handling of events in canvases uses the current item defined in
\fBITEM IDS AND TAGS\fR above. \fBEnter\fR and \fBLeave\fR events
trigger for an
item when it becomes the current item or ceases to be the current item;
note that these events are different than \fBEnter\fR and \fBLeave\fR
events for windows. Mouse-related events are directed to the current
item, if any. Keyboard-related events are directed to the focus item, if
593
594
595
596
597
598
599
600

601
602
603
604
605
606
607
598
599
600
601
602
603
604

605
606
607
608
609
610
611
612







-
+







tag given by \fItagToDelete\fR from the list of those
associated with the item.
If an item does not have the tag \fItagToDelete\fR then
the item is unaffected by the command.
If \fItagToDelete\fR is omitted then it defaults to \fItagOrId\fR.
This command returns an empty string.
.TP
\fIpathName \fBfind \fIsearchCommand \fR?\fIarg arg ...\fR?
\fIpathName \fBfind \fIsearchCommand \fR?\fIarg ...\fR?
.
This command returns a list consisting of all the items that
meet the constraints specified by \fIsearchCommand\fR and
\fIarg\fR's.
\fISearchCommand\fR and \fIargs\fR have any of the forms
accepted by the \fBaddtag\fR command.
The items are returned in stacking order, with the lowest item first.
653
654
655
656
657
658
659
660














661
662

663
664
665
666
667
668
669
670
671
672
673
674
675
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680

681
682
683
684
685
686

687
688
689
690
691
692
693








+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+





-







See \fBINDICES\fR above for a description of the
legal forms for \fIindex\fR.
Note: the insertion cursor is only displayed in an item if
that item currently has the keyboard focus (see the \fBfocus\fR widget
command, above), but the cursor position may
be set even when the item does not have the focus.
This command returns an empty string.
.TP
\fIpathName \fBimage \fIimagename\fR ?\fIsubsample\fR? ?\fIzoom\fR?
.
Draw the canvas into the Tk photo image named \fIimagename\fR. If a \fB-scrollregion\fR
has been defined then this will be the boundaries of the canvas region drawn and the
final size of the photo image. Otherwise the widget width and height with an origin
of 0,0 will be the size of the canvas region drawn and the final size of the photo
image. Optionally an integer \fIsubsample\fR factor may be given and the photo image
will be reduced in size. In addition to the \fIsubsample\fR an integer \fIzoom\fR
factor can also be given and the photo image will be enlarged. The image background
will be filled with the canvas background colour. The canvas widget does not need to
be mapped for this widget command to work, but at least one of it's ancestors must be
mapped.
This command returns an empty string.
.TP
\fIpathName \fBimove \fItagOrId index x y\fR
.VS 8.6
.
This command causes the \fIindex\fR'th coordinate of each of the items
indicated by \fItagOrId\fR to be relocated to the location (\fIx\fR,\fIy\fR).
Each item interprets \fIindex\fR independently according to the rules
described in \fBINDICES\fR above. Out of the standard set of items, only line
and polygon items may have their coordinates relocated this way.
.VE 8.6
.TP
\fIpathName \fBindex \fItagOrId index\fR
.
This command returns a decimal string giving the numerical index
within \fItagOrId\fR corresponding to \fIindex\fR.
\fIIndex\fR gives a textual description of the desired position
as described in \fBINDICES\fR above.
747
748
749
750
751
752
753
754

755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
765
766
767
768
769
770
771

772
773
774
775
776
777
778
779
780
781

782
783
784
785
786
787
788







-
+









-







Move each of the items given by \fItagOrId\fR in the canvas coordinate
space by adding \fIxAmount\fR to the x-coordinate of each point
associated with the item and \fIyAmount\fR to the y-coordinate of
each point associated with the item.
This command returns an empty string.
.TP
\fIpathName \fBmoveto \fItagOrId xPos yPos\fR
.VS 8.6
.
Move the items given by \fItagOrId\fR in the canvas coordinate
space so that the first coordinate pair (the upper-left corner of the
bounding box) of the first item (the lowest in the display list) with
tag \fItagOrId\fR is located at
position (\fIxPos\fR,\fIyPos\fR). \fIxPos\fR and \fIyPos\fR may be
the empty string, in which case the corresponding coordinate
will be unchanged. All items matching
\fItagOrId\fR remain in the same positions relative to each other.
This command returns an empty string.
.VE 8.6
.TP
\fIpathName \fBpostscript \fR?\fIoption value option value ...\fR?
.
Generate a Postscript representation for part or all of the canvas.
If the \fB\-file\fR option is specified then the Postscript is written
to a file and an empty string is returned; otherwise the Postscript
is returned as the result of the command.
943
944
945
946
947
948
949
950

951
952
953
954
955
956
957
958




















959

960
961
962
963
964
965
966
960
961
962
963
964
965
966

967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995

996
997
998
999
1000
1001
1002
1003







-
+








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+







Note: this command has no effect on window items. Window items always
obscure other item types, and the stacking order of window items is
determined by the \fBraise\fR command and \fBlower\fR command, not the
\fBraise\fR widget command and \fBlower\fR widget command for canvases.
.RE
.TP
\fIpathName \fBrchars \fItagOrId first last string\fR
.VS 8.6
.
This command causes the text or coordinates between \fIfirst\fR and \fIlast\fR
for each of the items indicated by \fItagOrId\fR to be replaced by
\fIstring\fR. Each item interprets \fIfirst\fR and \fIlast\fR independently
according to the rules described in \fBINDICES\fR above. Out of the standard
set of items, text items support this operation by altering their text as
directed, and line and polygon items support this operation by altering their
coordinate list (in which case \fIstring\fR should be a list of coordinates to
use as a replacement). The other items ignore this operation.
.TP
\fIpathName \fBrotate \fItagOrId xOrigin yOrigin angle\fR
.VS "8.7, TIP164"
Rotate the coordinates of all of the items given by \fItagOrId\fR in canvas
coordinate space.
\fIXOrigin\fR and \fIyOrigin\fR identify the origin for the rotation
operation and \fIangle\fR identifies the amount to rotate the coordinates
anticlockwise, in degrees. (Negative values rotate clockwise.)
This command returns an empty string.
.RS
.PP
Implementation note: not all item types work the same with rotations. In
particular,\fB bitmap\fR,\fB image\fR,\fB text\fR and\fB window\fR items only
rotate their anchor points and do not rotate the items themselves about those
points, and the \fBarc\fR, \fBoval\fR and \fBrectangle\fR types rotate about a
computed center point instead of moving the bounding box coordinates directly.
.PP
Some items (currently \fBarc\fR and\fB text\fR) have angles in their options;
this command \fIdoes not\fR affect those options.
.RE
.VE 8.6
.VE "8.7, TIP164"
.TP
\fIpathName \fBscale \fItagOrId xOrigin yOrigin xScale yScale\fR
.
Rescale the coordinates of all of the items given by \fItagOrId\fR in canvas
coordinate space.
\fIXOrigin\fR and \fIyOrigin\fR identify the origin for the scaling
operation and \fIxScale\fR and \fIyScale\fR identify the scale
1106
1107
1108
1109
1110
1111
1112
1113
1114



1115
1116
1117
1118
1119
1120
1121
1122
1123



1124
1125
1126

1127
1128
1129
1130
1131
1132
1133
1143
1144
1145
1146
1147
1148
1149


1150
1151
1152
1153



1154
1155
1156
1157
1158
1159
1160
1161
1162
1163

1164
1165
1166
1167
1168
1169
1170
1171







-
-
+
+
+

-
-
-





+
+
+


-
+







total width of the canvas is off-screen to the left.
\fIFraction\fR must be a fraction between 0 and 1.
.TP
\fIpathName \fBxview scroll \fInumber what\fR
.
This command shifts the view in the window left or right according to
\fInumber\fR and \fIwhat\fR.
\fINumber\fR must be an integer.
\fIWhat\fR must be either \fBunits\fR or \fBpages\fR or an abbreviation
\fINumber\fR must be an integer or a float, but if it is a float then
it is converted to an integer, rounded away from 0.
\fIWhat\fR must be either \fBpages\fR or \fBunits\fR or an abbreviation
of one of these.
If \fIwhat\fR is \fBunits\fR, the view adjusts left or right in units
of the \fBxScrollIncrement\fR option, if it is greater than zero,
or in units of one-tenth the window's width otherwise.
If \fIwhat is \fBpages\fR then the view
adjusts in units of nine-tenths the window's width.
If \fInumber\fR is negative then information farther to the left
becomes visible; if it is positive then information farther to the right
becomes visible.
If \fIwhat\fR is \fBunits\fR, the view adjusts left or right in units
of the \fBxScrollIncrement\fR option, if it is greater than zero,
or in units of one-tenth the window's width otherwise.
.RE
.TP
\fIpathName \fByview \fI?args\fR?
\fIpathName \fByview ?\fIargs\fR?
.
This command is used to query and change the vertical position of the
information displayed in the canvas's window.
It can take any of the following forms:
.RS
.TP
\fIpathName \fByview\fR
1148
1149
1150
1151
1152
1153
1154
1155

1156
1157
1158
1159
1160
1161
1162
1163



1164
1165
1166
1167
1168
1169
1170
1186
1187
1188
1189
1190
1191
1192

1193



1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208







-
+
-
-
-





+
+
+







\fIFraction\fR is a fraction between 0 and 1.
.TP
\fIpathName \fByview scroll \fInumber what\fR
.
This command adjusts the view in the window up or down according to
\fInumber\fR and \fIwhat\fR.
\fINumber\fR must be an integer.
\fIWhat\fR must be either \fBunits\fR or \fBpages\fR.
\fIWhat\fR must be either \fBpages\fR or \fBunits\fR.
If \fIwhat\fR is \fBunits\fR, the view adjusts up or down in units
of the \fByScrollIncrement\fR option, if it is greater than zero,
or in units of one-tenth the window's height otherwise.
If \fIwhat\fR is \fBpages\fR then
the view adjusts in units of nine-tenths the window's height.
If \fInumber\fR is negative then higher information becomes
visible; if it is positive then lower information
becomes visible.
If \fIwhat\fR is \fBunits\fR, the view adjusts up or down in units
of the \fByScrollIncrement\fR option, if it is greater than zero,
or in units of one-tenth the window's height otherwise.
.RE
.SH "OVERVIEW OF ITEM TYPES"
.PP
The sections below describe the various types of items supported
by canvas widgets. Each item type is characterized by two things:
first, the form of the \fBcreate\fR command used to create
instances of the type; and second, a set of configuration options
1320
1321
1322
1323
1324
1325
1326
1327
1328


1329
1330
1331
1332
1333
1334
1335
1336



1337
1338
1339
1340
1341
1342
1343
1358
1359
1360
1361
1362
1363
1364


1365
1366
1367
1368
1369
1370
1371
1372
1373

1374
1375
1376
1377
1378
1379
1380
1381
1382
1383







-
-
+
+







-
+
+
+







For arcs, wide outlines will be drawn centered on the edges of the
arc's region.
.SH "STANDARD ITEM TYPES"
.SS "ARC ITEMS"
.PP
Items of type \fBarc\fR appear on the display as arc-shaped regions.
An arc is a section of an oval delimited by two angles (specified
by the \fB\-start\fR and \fB\-extent\fR options) and displayed in
one of several ways (specified by the \fB\-style\fR option).
by either the \fB\-start\fR and \fB\-extent\fR options or the \fB\-height\fR option)
and displayed in one of several ways (specified by the \fB\-style\fR option).
Arcs are created with widget commands of the following form:
.CS
\fIpathName \fBcreate arc \fIx1 y1 x2 y2 \fR?\fIoption value ...\fR?
\fIpathName \fBcreate arc \fIcoordList\fR ?\fIoption value ...\fR?
.CE
The arguments \fIx1\fR, \fIy1\fR, \fIx2\fR, and \fIy2\fR or \fIcoordList\fR give
the coordinates of two diagonally opposite corners of a
rectangular region enclosing the oval that defines the arc.
rectangular region enclosing the oval that defines the arc (except when
\fB\-height\fR is specified - see below).
.
After the coordinates there may be any number of \fIoption\fR\-\fIvalue\fR
pairs, each of which sets one of the configuration options
for the item. These same \fIoption\fR\-\fIvalue\fR pairs may be
used in \fBitemconfigure\fR widget commands to change the item's
configuration. An arc item becomes the current item when the mouse pointer is
over any part that is painted or (when fully transparent) that would be
painted if both the \fB\-fill\fR and \fB\-outline\fR options were non-empty.
1369
1370
1371
1372
1373
1374
1375




























1376
1377
1378
1379
1380
1381
1382
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







modulo 360 is used as the extent.
.TP
\fB\-start \fIdegrees\fR
Specifies the beginning of the angular range occupied by the
arc.
\fIDegrees\fR is given in units of degrees measured counter-clockwise
from the 3-o'clock position; it may be either positive or negative.
.TP
\fB\-height \fIdistance\fR
Provides a shortcut for creating a circular arc segment by defining the
distance of the mid-point of the arc from its chord. When this option
is used the coordinates are interpreted as the start and end coordinates
of the chord, and the options \fB\-start\fR and \fB-extent\fR are ignored.
The value of \fIdistance\fR has the following meaning:
.RS
.PP
.RS
\fIdistance\fR > 0 creates a clockwise arc
.br
\fIdistance\fR < 0 creates an counter-clockwise arc
.br
\fIdistance\fR = 0 creates an arc as if this option had not been specified
.RE
.PP
If you want the arc to have a specific radius, \fIr\fR, use the formula:
.PP
.RS
\fIdistance\fR = \fIr\fR \(+- sqrt(\fIr\fR**2 - (chordLength / 2)**2)
.RE
.PP
choosing the minus sign for the minor arc and the plus sign for the major arc.
.PP
Note that \fBitemcget \-height\fR always returns 0 so that introspection code
can be kept simple.
.RE
.TP
\fB\-style \fItype\fR
Specifies how to draw the arc. If \fItype\fR is \fBpieslice\fR
(the default) then the arc's region is defined by a section
of the oval's perimeter plus two line segments, one between the center
of the oval and each end of the perimeter section.
If \fItype\fR is \fBchord\fR then the arc's region is defined
1791
1792
1793
1794
1795
1796
1797
1798

1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1859
1860
1861
1862
1863
1864
1865

1866
1867
1868
1869
1870
1871

1872
1873
1874
1875
1876
1877
1878







-
+





-







\fB\-stipple\fR	\fB\-activestipple\fR
\fB\-disabledstipple\fR	\fB\-state\fR
\fB\-tags\fR
.DE
The following extra options are supported for text items:
.TP
\fB\-angle \fIrotationDegrees\fR
.VS 8.6
.
\fIRotationDegrees\fR tells how many degrees to rotate the text anticlockwise
about the positioning point for the text; it may have any floating-point value
from 0.0 to 360.0. For example, if \fIrotationDegrees\fR is \fB90\fR, then the
text will be drawn vertically from bottom to top.
This option defaults to \fB0.0\fR.
.VE 8.6
.TP
\fB\-font \fIfontName\fR
Specifies the font to use for the text item.
\fIFontName\fR may be any string acceptable to \fBTk_GetFont\fR.
If this option is not specified, it defaults to a system-dependent
font.
.TP
Changes to doc/checkbutton.n.
188
189
190
191
192
193
194
195

196
197
198
199
200
201
202
188
189
190
191
192
193
194

195
196
197
198
199
200
201
202







-
+







.SH "WIDGET COMMAND"
.PP
The \fBcheckbutton\fR command creates a new Tcl command whose
name is \fIpathName\fR.  This
command may be used to invoke various
operations on the widget.  It has the following general form:
.CS
\fIpathName option \fR?\fIarg arg ...\fR?
\fIpathName option \fR?\fIarg ...\fR?
.CE
\fIOption\fR and the \fIarg\fRs
determine the exact behavior of the command.  The following
commands are possible for checkbutton widgets:
.TP
\fIpathName \fBcget\fR \fIoption\fR
Returns the current value of the configuration option given
Changes to doc/chooseColor.n.
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







'\"
'\" Copyright (c) 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.
'\" 
'\"
.TH tk_chooseColor n 4.2 Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
tk_chooseColor \- pops up a dialog box for the user to select a color.
.SH SYNOPSIS
Changes to doc/chooseDirectory.n.
1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







'\"
'\" 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
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
Changes to doc/clipboard.n.
8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
8
9
10
11
12
13
14

15
16
17
18
19
20
21
22







-
+







.TH clipboard n 8.4 Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
clipboard \- Manipulate Tk clipboard
.SH SYNOPSIS
\fBclipboard \fIoption\fR ?\fIarg arg ...\fR?
\fBclipboard \fIoption\fR ?\fIarg ...\fR?
.BE
.SH DESCRIPTION
.PP
This command provides a Tcl interface to the Tk clipboard,
which stores data for later retrieval using the selection mechanism
(via the \fB\-selection CLIPBOARD\fR option).
In order to copy data into the clipboard, \fBclipboard clear\fR must
Changes to doc/colors.n.
1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







'\"
'\" 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 <[email protected]>
'\" Copyright (c) 2008 Donal K. Fellows
'\"
.TH colors n 8.3 Tk "Tk Built-In Commands"
.so man.macros
.BS
780
781
782
783
784
785
786
787
788
789
790





791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932




933
934
935
936
937
938





939
940

941
942
943
944
945
946
947




948

949
950










951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979









980
981
982
983

984
985
986
987
988
989
990
991
992
780
781
782
783
784
785
786




787
788
789
790
791
792
793
794

795
796

797
798
799
800





801
802
803

804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822

823

824
825

826


827
828
829
830
831
832
833

834
835


836
837
838
839
840
841


842
843

844
845







846
847

848



849




850
851
852







853






854
855

856
857
858
859
860
861







862
863
864
865


866

867



868
869
870


871
872
873
874






875
876
877
878
879


880
881
882
883
884
885


886
887
888
889
890
891
892

893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914

915
916
917
918
919
920
921









922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944







-
-
-
-
+
+
+
+
+



-


-




-
-
-
-
-



-



















-

-


-

-
-







-


-
-






-
-


-


-
-
-
-
-
-
-


-

-
-
-

-
-
-
-



-
-
-
-
-
-
-

-
-
-
-
-
-


-






-
-
-
-
-
-
-




-
-

-

-
-
-



-
-
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
-
-
+





-
-
+
+
+
+

+

-
+
+
+
+
+
+
+
+
+
+












-







-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+




+









yellow4	139	139 	0
YellowGreen	154	205 	50
.DE
.SH "PORTABILITY ISSUES"
.TP
\fBMac OS X\fR
.
On macOS, the following additional system colors are available.
This first group contains all colors available in the HIToolbox library.
(Note that in some cases the actual color values may depend on the
current Appearance.)
On macOS, the following additional system colors are available.  This
first group contains all of the HIBrush colors available in the
HIToolbox library. Note that on macOS 10.14 (Mojave) and later these
colors are unlikely to match the color actually used for the purpose
suggested by the color name.
.RS
.DS
systemActiveAreaFill
systemAlertActiveText
systemAlertBackgroundActive
systemAlertBackgroundInactive
systemAlertInactiveText
systemAlternatePrimaryHighlightColor
systemAppleGuideCoachmark
systemBevelActiveDark
systemBevelActiveLight
systemBevelButtonActiveText
systemBevelButtonInactiveText
systemBevelButtonPressedText
systemBevelButtonStickyActiveText
systemBevelButtonStickyInactiveText
systemBevelInactiveDark
systemBevelInactiveLight
systemBlack
systemBlackText
systemButtonActiveDarkHighlight
systemButtonActiveDarkShadow
systemButtonActiveLightHighlight
systemButtonActiveLightShadow
systemButtonFace
systemButtonFaceActive
systemButtonFaceInactive
systemButtonFacePressed
systemButtonFrame
systemButtonFrameActive
systemButtonFrameInactive
systemButtonInactiveDarkHighlight
systemButtonInactiveDarkShadow
systemButtonInactiveLightHighlight
systemButtonInactiveLightShadow
systemButtonPressedDarkHighlight
systemButtonPressedDarkShadow
systemButtonPressedLightHighlight
systemButtonPressedLightShadow
systemButtonText
systemChasingArrows
systemDialogActiveText
systemDialogBackgroundActive
systemDialogBackgroundInactive
systemDialogInactiveText
systemDocumentWindowBackground
systemDocumentWindowTitleActiveText
systemDocumentWindowTitleInactiveText
systemDragHilite
systemDrawerBackground
systemFinderWindowBackground
systemFocusHighlight
systemHighlight
systemHighlightAlternate
systemHighlightSecondary
systemHighlightText
systemIconLabelBackground
systemIconLabelBackgroundSelected
systemIconLabelSelectedText
systemIconLabelText
systemListViewBackground
systemListViewColumnDivider
systemListViewEvenRowBackground
systemListViewOddRowBackground
systemListViewSeparator
systemListViewSortColumnBackground
systemListViewText
systemListViewWindowHeaderBackground
systemMenu
systemMenuActive
systemMenuActiveText
systemMenuBackground
systemMenuBackgroundSelected
systemMenuDisabled
systemMenuItemActiveText
systemMenuItemDisabledText
systemMenuItemSelectedText
systemMenuText
systemMetalBackground
systemModelessDialogActiveText
systemModelessDialogBackgroundActive
systemModelessDialogBackgroundInactive
systemModelessDialogInactiveText
systemMovableModalBackground
systemMovableModalWindowTitleActiveText
systemMovableModalWindowTitleInactiveText
systemNotificationText
systemNotificationWindowBackground
systemPlacardActiveText
systemPlacardBackground
systemPlacardInactiveText
systemPlacardPressedText
systemPopupArrowActive
systemPopupArrowInactive
systemPopupArrowPressed
systemPopupButtonActiveText
systemPopupButtonInactiveText
systemPopupButtonPressedText
systemPopupLabelActiveText
systemPopupLabelInactiveText
systemPopupWindowTitleActiveText
systemPopupWindowTitleInactiveText
systemPrimaryHighlightColor
systemPushButtonActiveText
systemPushButtonInactiveText
systemPushButtonPressedText
systemRootMenuActiveText
systemRootMenuDisabledText
systemRootMenuSelectedText
systemScrollBarDelimiterActive
systemScrollBarDelimiterInactive
systemSecondaryGroupBoxBackground
systemSecondaryHighlightColor
systemSelectedTabTextColor
systemSheetBackground
systemSheetBackgroundOpaque
systemSheetBackgroundTransparent
systemStaticAreaFill
systemSystemDetailText
systemTabFrontActiveText
systemTabFrontInactiveText
systemTabNonFrontActiveText
systemTabNonFrontInactiveText
systemTabNonFrontPressedText
systemTabPaneBackground
systemToolbarBackground
systemTransparent
systemUtilityWindowBackgroundActive
systemUtilityWindowBackgroundInactive
systemUtilityWindowTitleActiveText
systemUtilityWindowTitleInactiveText
systemWhite
systemWhiteText
systemWindowBody
systemWindowHeaderActiveText
systemWindowHeaderBackground
systemWindowHeaderInactiveText
.DE
.RE
.
The second group of MacOS colors below are based on Apple's "semantic"
NScolors.  On OSX 10.14 (Mojave) and later these colors change value
Tk supports all of the NSColors in the macOS System ColorList.  The
convention for naming these colors is that the Tk name is generated by
capitalizing the macOS name and adding the prefix "system".  On OSX
10.14 (Mojave) and later many of these "semantic" colors will appear
when Dark Mode is enabled.  However, the change is only observable
when the Apple window manager is drawing to the screen. So the
\fBwinfo rgb\fR command will return the color coordinates used in the
standard Aqua mode, even if Dark Mode has been selected in the system
preferences.  The numbered systemWindowBackgroundColors are used in
the \fBttk::notebook\fR and \fBttk::labelframe\fR widgets to provide a
differently depending on whether the NSWindow in which they are used has
the Aqua or DarkAqua appearance.  The System ColorList differs between
releases of macOS and some colors, such as systemLinkColor and
systemControlAccentColor, are simulated on older systems which did not
provide them.  All of the colors below are available on all supported
contrasting background.  Each numbered color constrasts with its
predecessor.
macOS releases, but newer systems will support additional colors.
.RS
.DS
systemControlAccentColor
systemControlTextColor
systemDisabledControlTextColor
systemLabelColor  
systemSelectedTextBackgroundColor  
systemLabelColor
systemLinkColor
systemPlaceholderTextColor
systemSelectedTextBackgroundColor
systemSelectedTextColor
systemSeparatorColor
systemTextBackgroundColor
systemTextColor  
systemTextColor
.DE
.RE
.
The numbered systemWindowBackgroundColors below
are used in the \fBttk::notebook\fR and \fBttk::labelframe\fR widgets
to provide a contrasting background.  Each numbered color constrasts
with its predecessor.
.RS
.DS
systemWindowBackgroundColor
systemWindowBackgroundColor1
systemWindowBackgroundColor2
systemWindowBackgroundColor3
systemWindowBackgroundColor4
systemWindowBackgroundColor5
systemWindowBackgroundColor6
systemWindowBackgroundColor7
.DE
.RE
.TP


\fBWindows\fR
.
On Windows, the following additional system colors are available
(note that the actual color values depend on the currently active OS theme):
.RS
.DS
.ta 6c
system3dDarkShadow	systemHighlight
system3dLight	systemHighlightText
systemActiveBorder	systemInactiveBorder
systemActiveCaption	systemInactiveCaption
systemAppWorkspace	systemInactiveCaptionText
systemBackground	systemInfoBackground
systemButtonFace	systemInfoText
systemButtonHighlight	systemMenu
systemButtonShadow	systemMenuText
system3dDarkShadow	systemHighlightText
system3dLight	systemInactiveBorder
systemActiveBorder	systemInactiveCaption
systemActiveCaption	systemInactiveCaptionText
systemAppWorkspace	systemInfoBackground
systemBackground	systemInfoText
systemButtonFace	systemMenu
systemButtonHighlight	systemMenuText
systemButtonShadow	systemPlaceholderText
systemButtonText	systemScrollbar
systemCaptionText	systemWindow
systemDisabledText	systemWindowFrame
systemGrayText	systemWindowText
systemHighlight
.DE
.RE
.SH "SEE ALSO"
options(n), Tk_GetColor(3)
.SH KEYWORDS
color, option
'\" Local Variables:
'\" mode: nroff
'\" End:
Changes to doc/console.n.
1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

27
28
29
30






31
32
33
34
35
36
37
1
2
3
4
5

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

26
27



28
29
30
31
32
33
34
35
36
37
38
39
40





-
+



















-
+

-
-
-
+
+
+
+
+
+







'\"
'\" Copyright (c) 2001 Donal K. Fellows
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\"
.TH console n 8.4 Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
console \- Control the console on systems without a real console
.SH SYNOPSIS
\fBconsole\fR \fIsubcommand\fR ?\fIarg ...\fR?
.BE
.SH DESCRIPTION
.PP
The console window is a replacement for a real console to allow input
and output on the standard I/O channels on platforms that do not have
a real console.  It is implemented as a separate interpreter with the
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 only available when stdin is \fB/dev/null\fR
(as is the case e.g. when the application embedding Tk is started
from the Mac OS X Finder).
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
done by modifying the Info.plist file by adding the LSEnvironment key
to the main dict and setting its value to be a dict with the key \fBTK_CONSOLE\fR.
.PP
.TP
\fBconsole eval \fIscript\fR
Evaluate the \fIscript\fR argument as a Tcl script in the console
interpreter.  The normal interpreter is accessed through the
\fBconsoleinterp\fR command in the console interpreter.
.TP
Changes to doc/cursors.n.
1
2

3
4

5
6

7
8
9
10
11
12
13
1

2
3

4
5

6
7
8
9
10
11
12
13

-
+

-
+

-
+







'\"
'\" Copyright (c) 1998-2000 by Scriptics Corporation.
'\" Copyright (c) 1998-2000 Scriptics Corporation.
'\" All rights reserved.
'\" 
'\"
'\" Copyright (c) 2006-2007 Daniel A. Steffen <[email protected]>
'\" 
'\"
.TH cursors n 8.3 Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
cursors \- mouse cursors available in Tk
.BE
Changes to doc/destroy.n.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1990 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH destroy n "" Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
destroy \- Destroy one or more windows
.SH SYNOPSIS
Changes to doc/dialog.n.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1992 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH tk_dialog n 4.1 Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
tk_dialog \- Create modal dialog and wait for response
.SH SYNOPSIS
Changes to doc/entry.n.
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

26
27
28
29
30
31
32
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33







-
+

















+







'\"
'\" Copyright (c) 1990-1994 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\" Copyright (c) 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.
'\" 
'\"
.TH entry n 8.3 Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
entry \- Create and manipulate 'entry' one-line text entry widgets
.SH SYNOPSIS
\fBentry\fR \fIpathName \fR?\fIoptions\fR?
.SO
\-background	\-highlightthickness	\-selectbackground
\-borderwidth	\-insertbackground	\-selectborderwidth
\-cursor	\-insertborderwidth	\-selectforeground
\-exportselection	\-insertofftime	\-takefocus
\-font	\-insertontime	\-textvariable
\-foreground	\-insertwidth	\-xscrollcommand
\-highlightbackground	\-justify
\-highlightcolor	\-relief
\-placeholder	\-placeholderforeground
.SE
.SH "WIDGET-SPECIFIC OPTIONS"
.OP \-disabledbackground disabledBackground DisabledBackground
Specifies the background color to use when the entry is disabled.  If
this option is the empty string, the normal background color is used.
.OP \-disabledforeground disabledForeground DisabledForeground
Specifies the foreground color to use when the entry is disabled.  If
185
186
187
188
189
190
191
192

193
194
195
196
197
198
199
186
187
188
189
190
191
192

193
194
195
196
197
198
199
200







-
+







entry widget to become out of sync with the \fB\-textvariable\fR.
.SH "WIDGET COMMAND"
.PP
The \fBentry\fR command creates a new Tcl command whose
name is \fIpathName\fR.  This command may be used to invoke various
operations on the widget.  It has the following general form:
.CS
\fIpathName subcommand \fR?\fIarg arg ...\fR?
\fIpathName subcommand \fR?\fIarg ...\fR?
.CE
\fISubcommand\fR and the \fIarg\fRs
determine the exact behavior of the command.
.SS INDICES
.PP
Many of the widget commands for entries take one or more indices as
arguments.  An index specifies a particular character in the entry's
398
399
400
401
402
403
404
405
406



407
408
409
410
411
412



413


414
415
416
417
418
419
420
399
400
401
402
403
404
405


406
407
408
409





410
411
412
413
414
415
416
417
418
419
420
421
422







-
-
+
+
+

-
-
-
-
-
+
+
+

+
+







Adjusts the view in the window so that the character \fIfraction\fR of the
way through the text appears at the left edge of the window.
\fIFraction\fR must be a fraction between 0 and 1.
.TP
\fIpathName \fBxview scroll \fInumber what\fR
This command shifts the view in the window left or right according to
\fInumber\fR and \fIwhat\fR.
\fINumber\fR must be an integer.
\fIWhat\fR must be either \fBunits\fR or \fBpages\fR or an abbreviation
\fINumber\fR must be an integer or a float, but if it is a float then
it is converted to an integer, rounded away from 0.
\fIWhat\fR must be either \fBpages\fR or \fBunits\fR or an abbreviation
of one of these.
If \fIwhat\fR is \fBunits\fR, the view adjusts left or right by
\fInumber\fR average-width characters on the display;  if it is
\fBpages\fR then the view adjusts by \fInumber\fR screenfuls.
If \fInumber\fR is negative then characters farther to the left
become visible;  if it is positive then characters farther to the right
If \fIwhat\fR is \fBpages\fR then the view adjusts by \fInumber\fR screenfuls.
If \fInumber\fR is negative then characters farther to the left become
visible;  if it is positive then characters farther to the right
become visible.
If \fIwhat\fR is \fBunits\fR, the view adjusts left or right by
\fInumber\fR average-width characters on the display.
.RE
.SH "DEFAULT BINDINGS"
.PP
Tk automatically creates class bindings for entries that give them
the following default behavior. In the descriptions below,
.QW word
refers to a contiguous group of letters, digits, or
444
445
446
447
448
449
450
451
452
453




454
455
456
457
458
459
460
446
447
448
449
450
451
452



453
454
455
456
457
458
459
460
461
462
463







-
-
-
+
+
+
+







.IP [5]
Clicking mouse button 1 with the Control key down will position the
insertion cursor in the entry without affecting the selection.
.IP [6]
If any normal printing characters are typed in an entry, they are
inserted at the point of the insertion cursor.
.IP [7]
The view in the entry can be adjusted by dragging with mouse button 2.
If mouse button 2 is clicked without moving the mouse, the selection
is copied into the entry at the position of the mouse cursor.
The view in the entry can be adjusted by dragging with the middle
mouse button (button 2, or button 3 in TkAqua). If the middle mouse
button is clicked without moving the mouse, the selection is copied
into the entry at the position of the mouse cursor.
.IP [8]
If the mouse is dragged out of the entry on the left or right sides
while button 1 is pressed, the entry will automatically scroll to
make more text visible (if there is more text off-screen on the side
where the mouse left the window).
.IP [9]
The Left and Right keys move the insertion cursor one character to the
Changes to doc/event.n.
8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
8
9
10
11
12
13
14

15
16
17
18
19
20
21
22







-
+







.TH event n 8.3 Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
event \- Miscellaneous event facilities: define virtual events and generate events
.SH SYNOPSIS
\fBevent\fI option \fR?\fIarg arg ...\fR?
\fBevent\fI option \fR?\fIarg ...\fR?
.BE
.SH DESCRIPTION
.PP
The \fBevent\fR command provides several facilities for dealing with
window system events, such as defining virtual events and synthesizing
events.  The command has several different forms, determined by the
first argument.  The following forms are currently supported:
96
97
98
99
100
101
102
103

104
105
106
107
108
109
110
96
97
98
99
100
101
102

103
104
105
106
107
108
109
110







-
+







\fISize\fR must be a screen distance;  it specifies the
\fIborder_width\fR field for the event.
Valid for \fBConfigure\fR events.
Corresponds to the \fB%B\fR substitution for binding scripts.
.TP
\fB\-button\fI number\fR
\fINumber\fR must be an integer;  it specifies the \fIdetail\fR field
for a \fBButtonPress\fR or \fBButtonRelease\fR event, overriding
for a \fBButton\fR or \fBButtonRelease\fR event, overriding
any button  number provided in the base \fIevent\fR argument.
Corresponds to the \fB%b\fR substitution for binding scripts.
.TP
\fB\-count\fI number\fR
\fINumber\fR must be an integer;  it specifies the \fIcount\fR field
for the event.  Valid for \fBExpose\fR events.
Corresponds to the \fB%c\fR substitution for binding scripts.
151
152
153
154
155
156
157
158

159
160
161
162
163
164
165
166

167
168
169
170
171
172
173
151
152
153
154
155
156
157

158
159
160
161
162
163
164
165

166
167
168
169
170
171
172
173







-
+







-
+







\fISize\fR must be a screen distance;  it specifies the \fIheight\fR
field for the event.  Valid for \fBConfigure\fR events.
Corresponds to the \fB%h\fR substitution for binding scripts.
.TP
\fB\-keycode\fI number\fR
\fINumber\fR  must be an integer;  it specifies the \fIkeycode\fR
field for the event.
Valid for \fBKeyPress\fR and \fBKeyRelease\fR events.
Valid for \fBKey\fR and \fBKeyRelease\fR events.
Corresponds to the \fB%k\fR substitution for binding scripts.
.TP
\fB\-keysym\fI name\fR
\fIName\fR must be the name of a valid keysym, such as \fBg\fR,
\fBspace\fR, or \fBReturn\fR;  its corresponding
keycode value is used as the \fIkeycode\fR field for event, overriding
any detail specified in the base \fIevent\fR argument.
Valid for \fBKeyPress\fR and \fBKeyRelease\fR events.
Valid for \fBKey\fR and \fBKeyRelease\fR events.
Corresponds to the \fB%K\fR substitution for binding scripts.
.TP
\fB\-mode\fI notify\fR
\fINotify\fR specifies the \fImode\fR field for the event and must be
one of \fBNotifyNormal\fR, \fBNotifyGrab\fR, \fBNotifyUngrab\fR, or
\fBNotifyWhileGrabbed\fR.
Valid for \fBEnter\fR, \fBLeave\fR, \fBFocusIn\fR, and
185
186
187
188
189
190
191
192

193
194
195
196
197
198
199
200

201
202
203
204
205
206
207

208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224

225
226
227
228
229
230
231
232
233
234
235
236

237
238
239
240
241
242
243
244

245
246
247
248
249
250
251
252

253
254
255
256
257
258
259
185
186
187
188
189
190
191

192
193
194
195
196
197
198
199

200
201
202
203
204
205
206

207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223

224
225
226
227
228
229
230
231
232
233
234
235

236
237
238
239
240
241
242
243

244
245
246
247
248
249
250
251

252
253
254
255
256
257
258
259







-
+







-
+






-
+
















-
+











-
+







-
+







-
+







either \fBPlaceOnTop\fR or \fBPlaceOnBottom\fR.
Valid for \fBCirculate\fR events.
Corresponds to the \fB%p\fR substitution for binding scripts.
.TP
\fB\-root\fI window\fR
\fIWindow\fR must be either a window path name or an integer window
identifier;  it specifies the \fIroot\fR field for the event.
Valid for \fBKeyPress\fR, \fBKeyRelease\fR, \fBButtonPress\fR,
Valid for \fBKey\fR, \fBKeyRelease\fR, \fBButton\fR,
\fBButtonRelease\fR, \fBEnter\fR, \fBLeave\fR, and \fBMotion\fR
events.
Corresponds to the \fB%R\fR substitution for binding scripts.
.TP
\fB\-rootx\fI coord\fR
\fICoord\fR must be a screen distance;  it specifies the \fIx_root\fR
field for the event.
Valid for \fBKeyPress\fR, \fBKeyRelease\fR, \fBButtonPress\fR,
Valid for \fBKey\fR, \fBKeyRelease\fR, \fBButton\fR,
\fBButtonRelease\fR, \fBEnter\fR, \fBLeave\fR, and \fBMotion\fR
events.  Corresponds to the \fB%X\fR substitution for binding scripts.
.TP
\fB\-rooty\fI coord\fR
\fICoord\fR must be a screen distance;  it specifies the \fIy_root\fR
field for the event.
Valid for \fBKeyPress\fR, \fBKeyRelease\fR, \fBButtonPress\fR,
Valid for \fBKey\fR, \fBKeyRelease\fR, \fBButton\fR,
\fBButtonRelease\fR, \fBEnter\fR, \fBLeave\fR, and \fBMotion\fR
events.
Corresponds to the \fB%Y\fR substitution for binding scripts.
.TP
\fB\-sendevent\fI boolean\fR
\fIBoolean\fR must be a boolean value;  it specifies the \fIsend_event\fR
field for the event.  Valid for all events.  Corresponds to the
\fB%E\fR substitution for binding scripts.
.TP
\fB\-serial\fI number\fR
\fINumber\fR must be an integer;  it specifies the \fIserial\fR field
for the event.  Valid for all events.
Corresponds to the \fB%#\fR substitution for binding scripts.
.TP
\fB\-state\fI state\fR
\fIState\fR specifies the \fIstate\fR field for the event.
For \fBKeyPress\fR, \fBKeyRelease\fR, \fBButtonPress\fR,
For \fBKey\fR, \fBKeyRelease\fR, \fBButtons\fR,
\fBButtonRelease\fR, \fBEnter\fR, \fBLeave\fR, and \fBMotion\fR events
it must be an integer value.
For \fBVisibility\fR events it must be one of \fBVisibilityUnobscured\fR,
\fBVisibilityPartiallyObscured\fR, or \fBVisibilityFullyObscured\fR.
This option overrides any modifiers such as \fBMeta\fR or \fBControl\fR
specified in the base \fIevent\fR.
Corresponds to the \fB%s\fR substitution for binding scripts.
.TP
\fB\-subwindow\fI window\fR
\fIWindow\fR specifies the \fIsubwindow\fR field for the event, either
as a path name for a Tk widget or as an integer window identifier.
Valid for \fBKeyPress\fR, \fBKeyRelease\fR, \fBButtonPress\fR,
Valid for \fBKey\fR, \fBKeyRelease\fR, \fBButton\fR,
\fBButtonRelease\fR, \fBEnter\fR, \fBLeave\fR, and \fBMotion\fR events.
Similar to \fB%S\fR substitution for binding scripts.
.TP
\fB\-time\fI integer\fR
\fIInteger\fR must be an integer value;  it specifies the \fItime\fR field
for the event. Additonally the special value \fBcurrent\fR is allowed,
this value will be substituted by the current event time.
Valid for \fBKeyPress\fR, \fBKeyRelease\fR, \fBButtonPress\fR,
Valid for \fBKey\fR, \fBKeyRelease\fR, \fBButton\fR,
\fBButtonRelease\fR, \fBEnter\fR, \fBLeave\fR, \fBMotion\fR,
and \fBProperty\fR events.
Corresponds to the \fB%t\fR substitution for binding scripts.
.TP
\fB\-warp\fI boolean\fR
\fIboolean\fR must be a boolean value;  it specifies whether
the screen pointer should be warped as well.
Valid for \fBKeyPress\fR, \fBKeyRelease\fR, \fBButtonPress\fR,
Valid for \fBKey\fR, \fBKeyRelease\fR, \fBButton\fR,
\fBButtonRelease\fR, and \fBMotion\fR events.  The pointer will
only warp to a window if it is mapped.
.TP
\fB\-width\fI size\fR
\fISize\fR must be a screen distance;  it specifies the \fIwidth\fR field
for the event.
Valid for \fBConfigure\fR events.
278
279
280
281
282
283
284
285

286
287
288
289
290
291
292
293
294
295
296
297

298
299
300
301
302
303
304
278
279
280
281
282
283
284

285
286
287
288
289
290
291
292
293
294
295
296

297
298
299
300
301
302
303
304







-
+











-
+







This option is useful when generating a series of events that should
be processed in order but at the front of the queue.
.RE
.TP
\fB\-x\fI coord\fR
\fICoord\fR must be a screen distance;  it specifies the \fIx\fR field
for the event.
Valid for \fBKeyPress\fR, \fBKeyRelease\fR, \fBButtonPress\fR,
Valid for \fBKey\fR, \fBKeyRelease\fR, \fBButton\fR,
\fBButtonRelease\fR, \fBMotion\fR, \fBEnter\fR, \fBLeave\fR,
\fBExpose\fR, \fBConfigure\fR, \fBGravity\fR, and \fBReparent\fR
events.
Corresponds to the \fB%x\fR substitution for binding scripts.
If \fIWindow\fR is empty the coordinate is relative to the
screen, and this option corresponds to the \fB%X\fR substitution
for binding scripts.
.TP
\fB\-y\fI coord\fR
\fICoord\fR must be a screen distance;  it specifies the \fIy\fR
field for the event.
Valid for \fBKeyPress\fR, \fBKeyRelease\fR, \fBButtonPress\fR,
Valid for \fBKey\fR, \fBKeyRelease\fR, \fBButton\fR,
\fBButtonRelease\fR, \fBMotion\fR, \fBEnter\fR, \fBLeave\fR,
\fBExpose\fR, \fBConfigure\fR, \fBGravity\fR, and \fBReparent\fR
events.
Corresponds to the \fB%y\fR substitution for binding scripts.
If \fIWindow\fR is empty the coordinate is relative to the
screen, and this option corresponds to the \fB%Y\fR substitution
for binding scripts.
564
565
566
567
568
569
570
571

572
573
574
575
576
577
578
564
565
566
567
568
569
570

571
572
573
574
575
576
577
578







-
+







.PP
When a definition of a virtual event changes at run time, all windows
will respond immediately to the new definition.
Starting from the preceding example, if the following code is executed:
.PP
.CS
bind Entry <Control-y> {}
\fBevent add\fR <<Paste>> <Key-F6>
\fBevent add\fR <<Paste>> <F6>
.CE
.PP
the behavior will change such in two ways.  First, the shadowed
\fB<<Paste>>\fR binding will emerge.
Typing Control-y will no longer invoke the \fB<Control-y>\fR binding,
but instead invoke the virtual event \fB<<Paste>>\fR.  Second,
pressing the F6 key will now also invoke the \fB<<Paste>>\fR binding.
Changes to doc/focus.n.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15
16
17
18

19
20
21
22
23
24
25
1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16
17

18
19
20
21
22
23
24
25






-
+










-
+







'\"
'\" Copyright (c) 1990-1994 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH focus n 4.0 Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
focus \- Manage the input focus
.SH SYNOPSIS
.nf
\fBfocus\fR
\fBfocus \fIwindow\fR
\fBfocus \fIoption\fR ?\fIarg arg ...\fR?
\fBfocus \fIoption\fR ?\fIarg ...\fR?
.fi
.BE
.SH DESCRIPTION
.PP
The \fBfocus\fR command is used to manage the Tk input focus.
At any given time, one window on each display is designated as
the \fIfocus window\fR;  any key press or key release events for the
Changes to doc/focusNext.n.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1994 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH tk_focusNext n 4.0 Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
tk_focusNext, tk_focusPrev, tk_focusFollowsMouse \- Utility procedures for managing the input focus.
.SH SYNOPSIS
Changes to doc/font.n.
8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
8
9
10
11
12
13
14

15
16
17
18
19
20
21
22







-
+







.TH font n 8.0 Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
font \- Create and inspect fonts.
.SH SYNOPSIS
\fBfont\fI option \fR?\fIarg arg ...\fR?
\fBfont\fI option \fR?\fIarg ...\fR?
.BE
.SH DESCRIPTION
.PP
The \fBfont\fR command provides several facilities for dealing with
fonts, such as defining named fonts and inspecting the actual attributes of
a font.  The command has several different forms, determined by the
first argument.  The following forms are currently supported:
Changes to doc/fontchooser.n.
1
2
3
4
5
6

7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

35
36
37
38
39
40
41
1
2
3
4
5

6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

34
35
36
37
38
39
40
41





-
+







-
+



















-
+







'\"
'\" Copyright (c) 2008 Daniel A. Steffen <[email protected]>
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\"
.TH fontchooser n "" Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
fontchooser \- control font selection dialog
.SH SYNOPSIS
\fBtk fontchooser\fR \fBconfigure\fR ?\fI\-option value \-option value ...\fR?
\fBtk fontchooser\fR \fBconfigure\fR ?\fI\-option value ...\fR?
.sp
\fBtk fontchooser\fR \fBshow\fR
.sp
\fBtk fontchooser\fR \fBhide\fR
.BE
.SH DESCRIPTION
.PP
The \fBtk fontchooser\fR command controls the Tk font selection dialog. It uses
the native platform font selection dialog where available, or a dialog
implemented in Tcl otherwise.
.PP
Unlike most of the other Tk dialog commands, \fBtk fontchooser\fR does not
return an immediate result, as on some platforms (Mac OS X) the standard font
dialog is modeless while on others (Windows) it is modal. To accommodate this
difference, all user interaction with the dialog will be communicated to the
caller via callbacks or virtual events.
.PP
The \fBtk fontchooser\fR command can have one of the following forms:
.TP
\fBtk fontchooser\fR \fBconfigure \fR?\fI\-option value \-option value ...\fR?
\fBtk fontchooser\fR \fBconfigure \fR?\fI\-option value ...\fR?
.
Set or query one or more of the configurations options below (analogous to Tk
widget configuration).
.TP
\fBtk fontchooser\fR \fBshow\fR
.
Show the font selection dialog. Depending on the platform, may return
Changes to doc/frame.n.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27










28
29
30
31
32
33
34
1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44






-
+




















+
+
+
+
+
+
+
+
+
+







'\"
'\" Copyright (c) 1990-1994 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH frame n 8.4 Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
frame \- Create and manipulate 'frame' simple container widgets
.SH SYNOPSIS
\fBframe\fR \fIpathName\fR ?\fIoptions\fR?
.SO
\-borderwidth	\-highlightcolor	\-pady
\-cursor	\-highlightthickness	\-relief
\-highlightbackground	\-padx	\-takefocus
.SE
.SH "WIDGET-SPECIFIC OPTIONS"
.OP \-background background Background
This option is the same as the standard \fB\-background\fR option
except that its value may also be specified as an empty string.
In this case, the widget will display no background or border, and
no colors will be consumed from its colormap for its background
and border.
.VS "8.7, TIP262"
An empty background will disable drawing the background image.
.OP \-backgroundimage backgroundImage BackgroundImage
This specifies an image to display on the frame's background within
the border of the frame (i.e., the image will be clipped by the
frame's highlight ring and border, if either are present); subwidgets
of the frame will be drawn on top. The image must have been created
with the \fBimage create\fR command. If specified as the empty string,
no image will be displayed.
.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.
The \fB\-class\fR option may not be changed with the \fBconfigure\fR
widget command.
58
59
60
61
62
63
64









65
66
67
68
69
70
71
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90







+
+
+
+
+
+
+
+
+







Specifies the desired height for the window in any of the forms
acceptable to \fBTk_GetPixels\fR.  If this option is less than or equal
to zero then the window will not request any size at all.  Note that this
sets the total height of the frame, any \fB\-borderwidth\fR or similar is
not added.  Normally \fB\-height\fR should not be used if a propagating
geometry manager, such as \fBgrid\fR or \fBpack\fR, is used within the
frame since the geometry manager will override the height of the frame.
.OP \-tile tile Tile
.VS "8.7, TIP262"
This specifies how to draw the background image (see
\fB\-backgroundimage\fR) on the frame.
If true (according to \fBTcl_GetBoolean\fR), the image will be tiled
to fill the whole frame, with the origin of the first copy of the
image being the top left of the interior of the frame.
If false (the default), the image will be centered within the frame.
.VE "8.7, TIP262"
.OP \-visual visual Visual
Specifies visual information for the new window in any of the
forms accepted by \fBTk_GetVisual\fR.
If this option is not specified, the new window will use the same
visual as its parent.
The \fB\-visual\fR option may not be modified with the \fBconfigure\fR
widget command.
87
88
89
90
91
92
93
94

95
96
97
98
99
100
101
102
103
104

105
106
107
108
109
110
111
112
113
114
115
116
117
118
119

120
121
122
123
124
125
126
106
107
108
109
110
111
112

113
114
115
116
117
118
119
120
121
122

123
124
125
126
127
128
129
130
131
132
133
134
135
136
137

138
139
140
141
142
143
144
145







-
+









-
+














-
+







or in the option database
to configure aspects of the frame such as its background color
and relief.  The \fBframe\fR command returns the
path name of the new window.
.PP
A frame is a simple widget.  Its primary purpose is to act as a
spacer or container for complex window layouts.  The only features
of a frame are its background color and an optional 3-D border to make the
of a frame are its background and an optional 3-D border to make the
frame appear raised or sunken.
.SH "WIDGET COMMAND"
.PP
The \fBframe\fR command creates a new Tcl command whose
name is the same as the path name of the frame's window.  This
command may be used to invoke various
operations on the widget.  It has the following general form:
.PP
.CS
\fIpathName option \fR?\fIarg arg ...\fR?
\fIpathName option \fR?\fIarg ...\fR?
.CE
.PP
\fIPathName\fR is the name of the command, which is the same as
the frame widget's path name.  \fIOption\fR and the \fIarg\fRs
determine the exact behavior of the command.  The following
commands are possible for frame widgets:
.TP
\fIpathName \fBcget\fR \fIoption\fR
.
Returns the current value of the configuration option given
by \fIoption\fR.
\fIOption\fR may have any of the values accepted by the \fBframe\fR
command.
.TP
\fIpathName \fBconfigure\fR ?\fIoption\fR? \fI?value option value ...\fR?
\fIpathName \fBconfigure\fR ?\fIoption\fR? ?\fIvalue option value ...\fR?
.
Query or modify the configuration options of the widget.
If no \fIoption\fR is specified, returns a list describing all of
the available options for \fIpathName\fR (see \fBTk_ConfigureInfo\fR for
information on the format of this list).  If \fIoption\fR is specified
with no \fIvalue\fR, then the command returns a list describing the
one named option (this list will be identical to the corresponding
Changes to doc/grab.n.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15
16
17

18
19
20
21
22
23
24
1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16

17
18
19
20
21
22
23
24






-
+









-
+







'\"
'\" Copyright (c) 1992 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH grab n "" Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
grab \- Confine pointer and keyboard events to a window sub-tree
.SH SYNOPSIS
\fBgrab \fR?\fB\-global\fR? \fIwindow\fR
.sp
\fBgrab \fIoption \fR?\fIarg arg \fR...?
\fBgrab \fIoption \fR?\fIarg \fR...?
.BE
.SH DESCRIPTION
.PP
This command implements simple pointer and keyboard grabs for Tk.
Tk's grabs are different than the grabs
described in the Xlib documentation.
When a grab is set for a particular window, Tk restricts all pointer
Changes to doc/grid.n.
1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16
17
18
19
20

21
22
23
24

25
26

27
28
29
30
31
32

33
34

35
36
37
38

39
40
41
42
43

44
45
46
47
48
49
50
51

52
53
54

55
56
57
58
59
60
61
62



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83

84
85
86
87
88

89
90

91
92

93
94
95

96
97
98
99
100
101
102

103
104

105
106
107
108


109
110
111
112
113
114

115
116
117
118
119

120
121
122


123
124
125
126
127
128
129


130
131
132
133
134
135
136
137


138
139
140
141
142
143

144
145
146
147

148
149
150
151
152

153
154
155
156

157
158
159
160

161
162

163
164

165
166
167
168

169
170
171


172
173
174
175
176
177


178
179
180

181
182

183
184
185

186
187
188
189
190

191
192

193
194
195
196
197

198
199
200
201



202
203

204








205
206

207
208
209

210
211
212
213


214
215

216
217

218
219
220
221
222

223
224
225

226
227
228

229
230
231
232

233
234
235

236
237
238

239
240
241
242
243
244
245
246



247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267

268
269
270
271
272

273
274
275
276



277
278
279
280










281
282

283
284
285


286
287
288
289

290
291
292


293
294

295




296
297
298
299
300

301
302
303

304
305
306
307
308



309
310

311
312
313
314
315

316
317

318
319
320
321
322
323


324
325
326
327

328
329

330
331
332
333
334


335
336

337
338

339
340

341
342
343
344

345
346
347

348
349

350
351

352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372

373
374

375
376

377
378
379
380
381
382
383
384
385
386



387
388
389
390
391

392
393
394


395
396

397
398
399


400
401
402
403



404
405
406
407
408
409
410
411






412
413
414
415
416
417
418
1
2
3
4
5

6
7
8
9
10
11
12
13
14
15
16
17
18
19

20
21
22
23

24
25

26
27
28
29
30
31

32
33

34
35
36
37

38
39
40
41
42

43
44
45
46
47
48
49
50

51
52
53

54
55
56
57
58
59



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82

83
84
85
86
87

88
89

90
91

92
93
94

95
96
97
98
99
100
101

102
103

104
105
106


107
108
109
110
111
112
113

114
115
116
117
118

119
120


121
122
123
124
125
126
127


128
129
130
131
132
133
134
135


136
137
138
139
140
141
142

143
144
145
146

147
148
149
150
151

152
153
154
155

156
157
158
159

160
161

162
163

164
165
166
167

168
169


170
171
172
173
174
175


176
177
178
179

180
181

182
183
184

185
186
187
188
189

190
191

192
193
194
195
196

197
198



199
200
201
202

203
204
205
206
207
208
209
210
211
212
213

214
215
216

217
218
219


220
221
222

223
224

225
226
227
228
229

230
231
232

233
234
235

236
237
238
239

240
241
242

243
244
245

246
247
248
249
250
251



252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274

275
276
277
278
279

280
281



282
283
284
285



286
287
288
289
290
291
292
293
294
295
296

297
298


299
300
301
302
303

304
305


306
307
308

309
310
311
312
313
314
315
316
317
318

319
320
321

322
323
324



325
326
327
328

329
330
331
332
333

334
335

336
337
338
339
340


341
342
343
344
345

346
347

348
349
350
351


352
353
354

355
356

357
358

359
360
361
362

363
364
365

366
367

368
369

370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390

391
392

393
394

395
396
397
398
399
400
401
402



403
404
405
406
407
408
409

410
411


412
413
414

415
416


417
418
419



420
421
422
423
424






425
426
427
428
429
430
431
432
433
434
435
436
437





-
+













-
+



-
+

-
+





-
+

-
+



-
+




-
+







-
+


-
+





-
-
-
+
+
+




















-
+




-
+

-
+

-
+


-
+






-
+

-
+


-
-
+
+





-
+




-
+

-
-
+
+





-
-
+
+






-
-
+
+





-
+



-
+




-
+



-
+



-
+

-
+

-
+



-
+

-
-
+
+




-
-
+
+


-
+

-
+


-
+




-
+

-
+




-
+

-
-
-
+
+
+

-
+

+
+
+
+
+
+
+
+

-
+


-
+


-
-
+
+

-
+

-
+




-
+


-
+


-
+



-
+


-
+


-
+





-
-
-
+
+
+




















-
+




-
+

-
-
-
+
+
+

-
-
-
+
+
+
+
+
+
+
+
+
+

-
+

-
-
+
+



-
+

-
-
+
+

-
+

+
+
+
+




-
+


-
+


-
-
-
+
+
+

-
+




-
+

-
+




-
-
+
+



-
+

-
+



-
-
+
+

-
+

-
+

-
+



-
+


-
+

-
+

-
+




















-
+

-
+

-
+







-
-
-
+
+
+




-
+

-
-
+
+

-
+

-
-
+
+

-
-
-
+
+
+


-
-
-
-
-
-
+
+
+
+
+
+







'\"
'\" Copyright (c) 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.
'\" 
'\"
.TH grid n 8.5 Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
grid \- Geometry manager that arranges widgets in a grid
.SH SYNOPSIS
\fBgrid \fIoption arg \fR?\fIarg ...\fR?
.BE
.SH DESCRIPTION
.PP
The \fBgrid\fR command is used to communicate with the grid
geometry manager that arranges widgets in rows and columns inside
of another window, called the geometry master (or master window).
of another window, called the geometry container (or container window).
The \fBgrid\fR command can have any of several forms, depending
on the \fIoption\fR argument:
.TP
\fBgrid \fIslave \fR?\fIslave ...\fR? ?\fIoptions\fR?
\fBgrid \fIwindow \fR?\fIwindow ...\fR? ?\fIoptions\fR?
.
If the first argument to \fBgrid\fR is suitable as the first slave
If the first argument to \fBgrid\fR is suitable as the first window
argument to \fBgrid configure\fR, either a window name (any value
starting with \fB.\fR) or one of the characters \fBx\fR or \fB^\fR
(see the \fBRELATIVE PLACEMENT\fR section below), then the command is
processed in the same way as \fBgrid configure\fR.
.TP
\fBgrid anchor \fImaster\fR ?\fIanchor\fR?
\fBgrid anchor \fIwindow\fR ?\fIanchor\fR?
.
The anchor value controls how to place the grid within the master
The anchor value controls how to place the grid within the container window
when no row/column has any weight.  See \fBTHE GRID ALGORITHM\fR below
for further details.  The default \fIanchor\fR is \fInw\fR.
.TP
\fBgrid bbox \fImaster\fR ?\fIcolumn row\fR? ?\fIcolumn2 row2\fR?
\fBgrid bbox \fIwindow\fR ?\fIcolumn row\fR? ?\fIcolumn2 row2\fR?
.
With no arguments,
the bounding box (in pixels) of the grid is returned.
The return value consists of 4 integers.  The first two are the pixel
offset from the master window (x then y) of the top-left corner of the
offset from the container window (x then y) of the top-left corner of the
grid, and the second two integers are the width and height of the grid,
also in pixels.  If a single \fIcolumn\fR and \fIrow\fR is specified on
the command line, then the bounding box for that cell is returned, where the
top left cell is numbered from zero.  If both \fIcolumn\fR and \fIrow\fR
arguments are specified, then the bounding box spanning the rows and columns
indicated is returned.
.TP
\fBgrid columnconfigure \fImaster index \fR?\fI\-option value...\fR?
\fBgrid columnconfigure \fIwindow index \fR?\fI\-option value...\fR?
.
Query or set the column properties of the \fIindex\fR column of the
geometry master, \fImaster\fR.
geometry container, \fIwindow\fR.
The valid options are \fB\-minsize\fR, \fB\-weight\fR, \fB\-uniform\fR
and \fB\-pad\fR.
If one or more options are provided, then \fIindex\fR may be given as
a list of column indices to which the configuration options will operate on.
Indices may be integers, window names or the keyword \fIall\fR. For \fIall\fR
the options apply to all columns currently occupied be slave windows. For
a window name, that window must be a slave of this master and the options
apply to all columns currently occupied be the slave.
the options apply to all columns currently occupied be content windows. For
a window name, that window must be a content of this container and the options
apply to all columns currently occupied be the content.
The \fB\-minsize\fR option sets the minimum size, in screen units,
that will be permitted for this column.
The \fB\-weight\fR option (an integer value)
sets the relative weight for apportioning
any extra spaces among
columns.
A weight of zero (0) indicates the column will not deviate from its requested
size.  A column whose weight is two will grow at twice the rate as a column
of weight one when extra space is allocated to the layout.
The \fB\-uniform\fR option, when a non-empty value is supplied, places
the column in a \fIuniform group\fR with other columns that have the
same value for \fB\-uniform\fR.  The space for columns belonging to a
uniform group is allocated so that their sizes are always in strict
proportion to their \fB\-weight\fR values.  See
\fBTHE GRID ALGORITHM\fR below for further details.
The \fB\-pad\fR option specifies the number of screen units that will be
added to the largest window contained completely in that column when the
grid geometry manager requests a size from the containing window.
If only an option is specified, with no value,
the current value of that option is returned.
If only the master window and index is specified, all the current settings
If only the container window and index is specified, all the current settings
are returned in a list of
.QW "\-option value"
pairs.
.TP
\fBgrid configure \fIslave \fR?\fIslave ...\fR? ?\fIoptions\fR?
\fBgrid configure \fIwindow \fR?\fIwindow ...\fR? ?\fIoptions\fR?
.
The arguments consist of the names of one or more slave windows
The arguments consist of the names of one or more content windows
followed by pairs of arguments that specify how
to manage the slaves.
to manage the content.
The characters \fB\-\fR,  \fBx\fR and \fB^\fR,
can be specified instead of a window name to alter the default
location of a \fIslave\fR, as described in the \fBRELATIVE PLACEMENT\fR
location of a \fIwindow\fR, as described in the \fBRELATIVE PLACEMENT\fR
section, below.
The following options are supported:
.RS
.TP
\fB\-column \fIn\fR
.
Insert the slave so that it occupies the \fIn\fRth column in the grid.
Insert the window so that it occupies the \fIn\fRth column in the grid.
Column numbers start with 0.  If this option is not supplied, then the
slave is arranged just to the right of previous slave specified on this
window is arranged just to the right of previous window specified on this
call to \fBgrid\fR, or column
.QW 0
if it is the first slave.  For each
\fBx\fR that immediately precedes the \fIslave\fR, the column position
if it is the first window.  For each
\fBx\fR that immediately precedes the \fIwindow\fR, the column position
is incremented by one.  Thus the \fBx\fR represents a blank column
for this row in the grid.
.TP
\fB\-columnspan \fIn\fR
.
Insert the slave so that it occupies \fIn\fR columns in the grid.
Insert the window so that it occupies \fIn\fR columns in the grid.
The default is one column, unless the window name is followed by a
\fB\-\fR, in which case the columnspan is incremented once for each immediately
following \fB\-\fR.
.TP
\fB\-in \fIother\fR
\fB\-in \fIcontainer\fR
.
Insert the slave(s) in the master
window given by \fIother\fR.  The default is the first slave's
Insert the window(s) in the container
window given by \fIcontainer\fR.  The default is the first window's
parent window.
.TP
\fB\-ipadx \fIamount\fR
.
The \fIamount\fR specifies how much horizontal internal padding to
leave on each side of the slave(s).  This is space is added
inside the slave(s) border.
leave on each side of the content.  This is space is added
inside the content border.
The \fIamount\fR must be a valid screen distance, such as \fB2\fR or \fB.5c\fR.
It defaults to 0.
.TP
\fB\-ipady \fIamount\fR
.
The \fIamount\fR specifies how much vertical internal padding to
leave on the top and bottom of the slave(s).
This space is added inside the slave(s) border.
leave on the top and bottom of the content.
This space is added inside the content border.
The \fIamount\fR  defaults to 0.
.TP
\fB\-padx \fIamount\fR
.
The \fIamount\fR specifies how much horizontal external padding to
leave on each side of the slave(s), in screen units.
leave on each side of the content, in screen units.
\fIAmount\fR may be a list
of two values to specify padding for left and right separately.
The \fIamount\fR defaults to 0.
This space is added outside the slave(s) border.
This space is added outside the content border.
.TP
\fB\-pady \fIamount\fR
.
The \fIamount\fR specifies how much vertical external padding to
leave on the top and bottom of the slave(s), in screen units.
leave on the top and bottom of the content, in screen units.
\fIAmount\fR may be a list
of two values to specify padding for top and bottom separately.
The \fIamount\fR defaults to 0.
This space is added outside the slave(s) border.
This space is added outside the content border.
.TP
\fB\-row \fIn\fR
.
Insert the slave so that it occupies the \fIn\fRth row in the grid.
Insert the content so that it occupies the \fIn\fRth row in the grid.
Row numbers start with 0.  If this option is not supplied, then the
slave is arranged on the same row as the previous slave specified on this
content is arranged on the same row as the previous content specified on this
call to \fBgrid\fR, or the next row after the highest occupied row
if this is the first slave.
if this is the first content.
.TP
\fB\-rowspan \fIn\fR
.
Insert the slave so that it occupies \fIn\fR rows in the grid.
Insert the content so that it occupies \fIn\fR rows in the grid.
The default is one row.  If the next \fBgrid\fR command contains
\fB^\fR characters instead of \fIslaves\fR that line up with the columns
of this \fIslave\fR, then the \fBrowspan\fR of this \fIslave\fR is
\fB^\fR characters instead of \fIcontent\fR that line up with the columns
of this \fIcontent\fR, then the \fBrowspan\fR of this \fIcontent\fR is
extended by one.
.TP
\fB\-sticky \fIstyle\fR
.
If a slave's cell is larger than its requested dimensions, this
option may be used to position (or stretch) the slave within its cell.
If a content's cell is larger than its requested dimensions, this
option may be used to position (or stretch) the content within its cell.
\fIStyle\fR  is a string that contains zero or more of the characters
\fBn\fR, \fBs\fR, \fBe\fR or \fBw\fR.
The string can optionally contains spaces or
The string can optionally contain spaces or
commas, but they are ignored.  Each letter refers to a side (north, south,
east, or west) that the slave will
east, or west) that the content will
.QW stick
to.  If both \fBn\fR and \fBs\fR (or \fBe\fR and \fBw\fR) are
specified, the slave will be stretched to fill the entire
specified, the content will be stretched to fill the entire
height (or width) of its cavity.  The \fB\-sticky\fR option subsumes the
combination of \fB\-anchor\fR and \fB\-fill\fR that is used by \fBpack\fR.
The default is
.QW "" ,
which causes the slave to be centered in its cavity, at its requested size.
which causes the content to be centered in its cavity, at its requested size.
.LP
If any of the slaves are already managed by the geometry manager
If any of the content is already managed by the geometry manager
then any unspecified options for them retain their previous values rather
than receiving default values.
.RE
.TP
\fBgrid forget \fIslave \fR?\fIslave ...\fR?
\fBgrid forget \fIwindow \fR?\fIwindow ...\fR?
.
Removes each of the \fIslave\fRs from grid for its
master and unmaps their windows.
The slaves will no longer be managed by the grid geometry manager.
Removes each of the \fIwindow\fRs from grid for its
container and unmaps their windows.
The content will no longer be managed by the grid geometry manager.
The configuration options for that window are forgotten, so that if the
slave is managed once more by the grid geometry manager, the initial
window is managed once more by the grid geometry manager, the initial
default settings are used.
.RS
.PP
.VS "TIP 518"
If the last content window of the container becomes unmanaged, this will also send
the virtual event \fB<<NoManagedChild>>\fR to the container; the container
may choose to resize itself (or otherwise respond) to such a change.
.VE "TIP 518"
.RE
.TP
\fBgrid info \fIslave\fR
\fBgrid info \fIwindow\fR
.
Returns a list whose elements are the current configuration state of
the slave given by \fIslave\fR in the same option-value form that
the content given by \fIwindow\fR in the same option-value form that
might be specified to \fBgrid configure\fR.
The first two elements of the list are
.QW "\fB\-in \fImaster\fR"
where \fImaster\fR is the slave's master.
.QW "\fB\-in \fIcontainer\fR"
where \fIcontainer\fR is the windows's container window.
.TP
\fBgrid location \fImaster x y\fR
\fBgrid location \fIwindow x y\fR
.
Given  \fIx\fR and \fIy\fR values in screen units relative to the master window,
Given  \fIx\fR and \fIy\fR values in screen units relative to the container window,
the column and row number at that \fIx\fR and \fIy\fR location is returned.
For locations that are above or to the left of the grid, \fB\-1\fR is
returned.
.TP
\fBgrid propagate \fImaster\fR ?\fIboolean\fR?
\fBgrid propagate \fIwindow\fR ?\fIboolean\fR?
.
If \fIboolean\fR has a true boolean value such as \fB1\fR or \fBon\fR
then propagation is enabled for \fImaster\fR, which must be a window
then propagation is enabled for \fIwindow\fR, which must be a window
name (see \fBGEOMETRY PROPAGATION\fR below).
If \fIboolean\fR has a false boolean value then propagation is
disabled for \fImaster\fR.
disabled for \fIwindow\fR.
In either of these cases an empty string is returned.
If \fIboolean\fR is omitted then the command returns \fB0\fR or
\fB1\fR to indicate whether propagation is currently enabled
for \fImaster\fR.
for \fIwindow\fR.
Propagation is enabled by default.
.TP
\fBgrid rowconfigure \fImaster index \fR?\fI\-option value...\fR?
\fBgrid rowconfigure \fIwindow index \fR?\fI\-option value...\fR?
.
Query or set the row properties of the \fIindex\fR row of the
geometry master, \fImaster\fR.
geometry container, \fIwindow\fR.
The valid options are \fB\-minsize\fR, \fB\-weight\fR, \fB\-uniform\fR
and \fB\-pad\fR.
If one or more options are provided, then \fIindex\fR may be given as
a list of row indices to which the configuration options will operate on.
Indices may be integers, window names or the keyword \fIall\fR. For \fIall\fR
the options apply to all rows currently occupied be slave windows. For
a window name, that window must be a slave of this master and the options
apply to all rows currently occupied be the slave.
the options apply to all rows currently occupied by content windows. For
a window name, that window must be a content window of this container and the options
apply to all rows currently occupied by the container window.
The \fB\-minsize\fR option sets the minimum size, in screen units,
that will be permitted for this row.
The \fB\-weight\fR option (an integer value)
sets the relative weight for apportioning
any extra spaces among
rows.
A weight of zero (0) indicates the row will not deviate from its requested
size.  A row whose weight is two will grow at twice the rate as a row
of weight one when extra space is allocated to the layout.
The \fB\-uniform\fR option, when a non-empty value is supplied, places
the row in a \fIuniform group\fR with other rows that have the
same value for \fB\-uniform\fR.  The space for rows belonging to a
uniform group is allocated so that their sizes are always in strict
proportion to their \fB\-weight\fR values.  See
\fBTHE GRID ALGORITHM\fR below for further details.
The \fB\-pad\fR option specifies the number of screen units that will be
added to the largest window contained completely in that row when the
grid geometry manager requests a size from the containing window.
If only an option is specified, with no value,
the current value of that option is returned.
If only the master window and index is specified, all the current settings
If only the container window and index is specified, all the current settings
are returned in a list of
.QW "-option value"
pairs.
.TP
\fBgrid remove \fIslave \fR?\fIslave ...\fR?
\fBgrid remove \fIwindow \fR?\fIwindow ...\fR?
.
Removes each of the \fIslave\fRs from grid for its
master and unmaps their windows.
The slaves will no longer be managed by the grid geometry manager.
Removes each of the \fIwindow\fRs from grid for its
container and unmaps their windows.
The content will no longer be managed by the grid geometry manager.
However, the configuration options for that window are remembered,
so that if the
slave is managed once more by the grid geometry manager, the previous
values are retained.
so that if the content window is managed once more by the grid
geometry manager, the previous values are retained.
.RS
.PP
.VS "TIP 518"
If the last content window of the container becomes unmanaged, this will also send
the virtual event \fB<<NoManagedChild>>\fR to the container; the container
may choose to resize itself (or otherwise respond) to such a change.
.VE "TIP 518"
.RE
.TP
\fBgrid size \fImaster\fR
\fBgrid size \fIcontainer\fR
.
Returns the size of the grid (in columns then rows) for \fImaster\fR.
The size is determined either by the \fIslave\fR occupying the largest
Returns the size of the grid (in columns then rows) for \fIcontainer\fR.
The size is determined either by the \fIcontent\fR occupying the largest
row or column, or the largest column or row with a \fB\-minsize\fR,
\fB\-weight\fR, or \fB\-pad\fR that is non-zero.
.TP
\fBgrid slaves \fImaster\fR ?\fI\-option value\fR?
\fBgrid content \fIwindow\fR ?\fI\-option value\fR?
.
If no options are supplied, a list of all of the slaves in \fImaster\fR
are returned, most recently manages first.
If no options are supplied, a list of all of the content in \fIwindow\fR
is returned, most recently managed first.
\fIOption\fR can be either \fB\-row\fR or \fB\-column\fR which
causes only the slaves in the row (or column) specified by \fIvalue\fR
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?
.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 slave.  This permits slaves to be rearranged,
information for each content.  This permits content to be rearranged,
added, or removed without the need to explicitly specify row and
column information.
When no column or row information is specified for a \fIslave\fR,
When no column or row information is specified for a \fIcontent\fR,
default values are chosen for
\fB\-column\fR, \fB\-row\fR, \fB\-columnspan\fR and \fB\-rowspan\fR
at the time the \fIslave\fR is managed. The values are chosen
based upon the current layout of the grid, the position of the \fIslave\fR
relative to other \fIslave\fRs in the same grid command, and the presence
at the time the \fIcontent\fR is managed. The values are chosen
based upon the current layout of the grid, the position of the \fIcontent\fR
relative to other \fIcontent\fRs in the same grid command, and the presence
of the characters \fB\-\fR, \fBx\fR, and \fB^\fR in \fBgrid\fR
command where \fIslave\fR names are normally expected.
command where \fIcontent\fR names are normally expected.
.RS
.TP
\fB\-\fR
.
This increases the \fB\-columnspan\fR of the \fIslave\fR to the left.  Several
This increases the \fB\-columnspan\fR of the \fIcontent\fR to the left.  Several
\fB\-\fR's in a row will successively increase the number of columns spanned. A \fB\-\fR
may not follow a \fB^\fR or a \fBx\fR, nor may it be the first \fIslave\fR
may not follow a \fB^\fR or a \fBx\fR, nor may it be the first \fIcontent\fR
argument to \fBgrid configure\fR.
.TP
\fBx\fR
.
This leaves an empty column between the \fIslave\fR on the left and
the \fIslave\fR on the right.
This leaves an empty column between the \fIcontent\fR on the left and
the \fIcontent\fR on the right.
.TP
\fB^\fR
.
This extends the \fB\-rowspan\fR of the \fIslave\fR above the \fB^\fR's
This extends the \fB\-rowspan\fR of the \fIcontent\fR above the \fB^\fR's
in the grid.  The number of \fB^\fR's in a row must match the number of
columns spanned by the \fIslave\fR above it.
columns spanned by the \fIcontent\fR above it.
.RE
.SH "THE GRID ALGORITHM"
.PP
The grid geometry manager lays out its slaves in three steps.
In the first step, the minimum size needed to fit all of the slaves
The grid geometry manager lays out its content in three steps.
In the first step, the minimum size needed to fit all of the content
is computed, then (if propagation is turned on), a request is made
of the master window to become that size.
of the container window to become that size.
In the second step, the requested size is compared against the actual size
of the master.  If the sizes are different, then spaces is added to or taken
of the container.  If the sizes are different, then spaces is added to or taken
away from the layout as needed.
For the final step, each slave is positioned in its row(s) and column(s)
For the final step, each content is positioned in its row(s) and column(s)
based on the setting of its \fIsticky\fR flag.
.PP
To compute the minimum size of a layout, the grid geometry manager
first looks at all slaves whose \fB\-columnspan\fR and \fB\-rowspan\fR values are one,
first looks at all content whose \fB\-columnspan\fR and \fB\-rowspan\fR values are one,
and computes the nominal size of each row or column to be either the
\fIminsize\fR for that row or column, or the sum of the \fIpad\fRding
plus the size of the largest slave, whichever is greater.  After that
plus the size of the largest content, whichever is greater.  After that
the rows or columns in each uniform group adapt to each other.  Then
the slaves whose row-spans or column-spans are greater than one are
the content whose row-spans or column-spans are greater than one are
examined.  If a group of rows or columns need to be increased in size
in order to accommodate these slaves, then extra space is added to each
in order to accommodate these content, then extra space is added to each
row or column in the group according to its \fIweight\fR.  For each
group whose weights are all zero, the additional space is apportioned
equally.
.PP
When multiple rows or columns belong to a uniform group, the space
allocated to them is always in proportion to their weights. (A weight
of zero is considered to be 1.)  In other words, a row or column
configured with \fB\-weight 1 \-uniform a\fR will have exactly the same
size as any other row or column configured with \fB\-weight 1 \-uniform
a\fR.  A row or column configured with \fB\-weight 2 \-uniform b\fR will
be exactly twice as large as one that is configured with \fB\-weight 1
\-uniform b\fR.
.PP
More technically, each row or column in the group will have a size
equal to \fIk*weight\fR for some constant \fIk\fR.  The constant
\fIk\fR is chosen so that no row or column becomes smaller than its
minimum size.  For example, if all rows or columns in a group have the
same weight, then each row or column will have the same size as the
largest row or column in the group.
.PP
For masters whose size is larger than the requested layout, the additional
For containers whose size is larger than the requested layout, the additional
space is apportioned according to the row and column weights.  If all of
the weights are zero, the layout is placed within its master according to
the weights are zero, the layout is placed within its container according to
the \fIanchor\fR value.
For masters whose size is smaller than the requested layout, space is taken
For containers whose size is smaller than the requested layout, space is taken
away from columns and rows according to their weights.  However, once a
column or row shrinks to its minsize, its weight is taken to be zero.
If more space needs to be removed from a layout than would be permitted, as
when all the rows or columns are at their minimum sizes, the layout is
placed and clipped according to the \fIanchor\fR value.
.SH "GEOMETRY PROPAGATION"
.PP
The grid geometry manager normally computes how large a master must be to
just exactly meet the needs of its slaves, and it sets the
requested width and height of the master to these dimensions.
The grid geometry manager normally computes how large a container must be to
just exactly meet the needs of its content, and it sets the
requested width and height of the container to these dimensions.
This causes geometry information to propagate up through a
window hierarchy to a top-level window so that the entire
sub-tree sizes itself to fit the needs of the leaf windows.
However, the \fBgrid propagate\fR command may be used to
turn off propagation for one or more masters.
turn off propagation for one or more containers.
If propagation is disabled then grid will not set
the requested width and height of the master window.
This may be useful if, for example, you wish for a master
the requested width and height of the container window.
This may be useful if, for example, you wish for a container
window to have a fixed size that you specify.
.SH "RESTRICTIONS ON MASTER WINDOWS"
.SH "RESTRICTIONS ON CONTAINER WINDOWS"
.PP
The master for each slave must either be the slave's parent
(the default) or a descendant of the slave's parent.
The container for each content must either be the content's parent
(the default) or a descendant of the content's parent.
This restriction is necessary to guarantee that the
slave can be placed over any part of its master that is
visible without danger of the slave being clipped by its parent.
In addition, all slaves in one call to \fBgrid\fR must have the same master.
content can be placed over any part of its container that is
visible without danger of the content being clipped by its parent.
In addition, all content in one call to \fBgrid\fR must have the same container.
.SH "STACKING ORDER"
.PP
If the master for a slave is not its parent then you must make sure
that the slave is higher in the stacking order than the master.
Otherwise the master will obscure the slave and it will appear as
if the slave has not been managed correctly.
The easiest way to make sure the slave is higher than the master is
to create the master window first:  the most recently created window
If the container for a content is not its parent then you must make sure
that the content is higher in the stacking order than the container.
Otherwise the container will obscure the content and it will appear as
if the content has not been managed correctly.
The easiest way to make sure the content is higher than the container is
to create the container window first:  the most recently created window
will be highest in the stacking order.
.SH CREDITS
.PP
The \fBgrid\fR command is based on ideas taken from the \fIGridBag\fR
geometry manager written by Doug. Stein, and the \fBblt_table\fR geometry
manager, written by George Howlett.
.SH EXAMPLES
Changes to doc/image.n.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
1
2
3
4
5
6

7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
22






-
+







-
+







'\"
'\" Copyright (c) 1994 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH image n 4.0 Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
image \- Create and manipulate images
.SH SYNOPSIS
\fBimage\fR \fIoption \fR?\fIarg arg ...\fR?
\fBimage\fR \fIoption \fR?\fIarg ...\fR?
.BE
.SH DESCRIPTION
.PP
The \fBimage\fR command is used to create, delete, and query images.
It can take several different forms, depending on the
\fIoption\fR argument.  The legal forms are:
.TP
Changes to doc/keysyms.n.
1
2

3
4
5
6
7
8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
23
24
25
26
27

28
29
30


31
32
33
34




35
36
37
38
39
40





41
42
43
44
45
46
47
48
49
50
51
52

53
54
55

56

57

58
59
60
61
62
63
64
65
1

2
3
4
5
6
7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
22
23
24
25
26

27
28
29
30
31
32




33
34
35
36






37
38
39
40
41

42
43
44
45
46
47
48
49
50
51

52
53
54

55
56
57

58

59
60
61
62
63
64
65

-
+












-
+











-
+



+
+
-
-
-
-
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
-










-
+


-
+

+
-
+
-







'\"
'\" 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
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
keysyms \- keysyms recognized by Tk
.BE
.SH DESCRIPTION
.PP
Tk recognizes many keysyms when specifying key bindings (e.g.,
.QW "\fBbind\fR \fB. <Key-\fR\fIkeysym\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
of a particular keysym is dependent on the configuration of the
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
percent                             37     0x25
ampersand                           38     0x26
apostrophe                          39     0x27
parenleft                           40     0x28
' (apostrophe)                      39     0x27
( (parenleft)                       40     0x28
) (parenright)                      41     0x29
* (asterisk)                        42     0x2A
parenright                          41     0x29
asterisk                            42     0x2A
plus                                43     0x2B
comma                               44     0x2C
minus                               45     0x2D
period                              46     0x2E
+ (plus)                            43     0x2B
, (comma)                           44     0x2C
minus                               45     0x2D
. (period)                          46     0x2E
/ (slash)                           47     0x2F
slash                               47     0x2F
0                                   48     0x30
1                                   49     0x31
2                                   50     0x32
3                                   51     0x33
4                                   52     0x34
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
question                            63     0x3F
@ (at)                              64     0x40
at                                  64     0x40
A                                   65     0x41
B                                   66     0x42
C                                   67     0x43
D                                   68     0x44
E                                   69     0x45
F                                   70     0x46
G                                   71     0x47
81
82
83
84
85
86
87
88
89



90
91
92
93
94
95
96
97
81
82
83
84
85
86
87


88
89
90

91
92
93
94
95
96
97







-
-
+
+
+
-







W                                   87     0x57
X                                   88     0x58
Y                                   89     0x59
Z                                   90     0x5A
bracketleft                         91     0x5B
backslash                           92     0x5C
bracketright                        93     0x5D
asciicircum                         94     0x5E
underscore                          95     0x5F
^ (asciicircum)                     94     0x5E
_ (underscore)                      95     0x5F
` (grave)                           96     0x60
grave                               96     0x60
a                                   97     0x61
b                                   98     0x62
c                                   99     0x63
d                                  100     0x64
e                                  101     0x65
f                                  102     0x66
g                                  103     0x67
111
112
113
114
115
116
117
118

119
120

121
122
123
124
125



126
127
128
129
130
131
132
133









134
135
136
137


138
139
140
141
142
143





144
145
146
147



148
149

150
151
152
153
154
155










156
157
158
159
160
161





162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
















177
178

179
180
181
182
183
184
185







186
187
188
189
190
191
192
193








194
195
196
197
198






199
200
201
202
203




204
205
206
207
208
209
210
211
212
213
214
215
216
















217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
111
112
113
114
115
116
117

118
119

120
121




122
123
124








125
126
127
128
129
130
131
132
133
134



135
136






137
138
139
140
141




142
143
144


145






146
147
148
149
150
151
152
153
154
155






156
157
158
159
160















161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176


177







178
179
180
181
182
183
184








185
186
187
188
189
190
191
192





193
194
195
196
197
198





199
200
201
202













203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227


228
229
230
231
232
233
234







-
+

-
+

-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+

-
-
-
+
+
-
-
-
-
-
-
+
+
+
+
+
-
-
-
-
+
+
+
-
-
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+









-
-







u                                  117     0x75
v                                  118     0x76
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
\(r! (exclamdown)                     161     0xA1
\(ct (cent)                           162     0xA2
\(Po (sterling)                       163     0xA3
yen                                165     0xA5
brokenbar                          166     0xA6
section                            167     0xA7
diaeresis                          168     0xA8
copyright                          169     0xA9
ordfeminine                        170     0xAA
guillemotleft                      171     0xAB
notsign                            172     0xAC
\(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
\(rg (registered)                     174     0xAE
\(a- (macron)                         175     0xAF
plusminus                          177     0xB1
twosuperior                        178     0xB2
threesuperior                      179     0xB3
acute                              180     0xB4
mu                                 181     0xB5
paragraph                          182     0xB6
\(de (degree)                         176     0xB0
\(+- (plusminus)                      177     0xB1
\(S2 (twosuperior)                    178     0xB2
\(S3 (threesuperior)                  179     0xB3
\(aa (acute)                          180     0xB4
periodcentered                     183     0xB7
cedilla                            184     0xB8
onesuperior                        185     0xB9
masculine                          186     0xBA
\(mc (mu)                             181     0xB5
\(ps (paragraph)                      182     0xB6
\(pc (periodcentered)                 183     0xB7
guillemotright                     187     0xBB
onequarter                         188     0xBC
\(ac (cedilla)                        184     0xB8
onehalf                            189     0xBD
threequarters                      190     0xBE
questiondown                       191     0xBF
Agrave                             192     0xC0
Aacute                             193     0xC1
Acircumflex                        194     0xC2
\(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
Atilde                             195     0xC3
Adiaeresis                         196     0xC4
Aring                              197     0xC5
AE                                 198     0xC6
Ccedilla                           199     0xC7
Egrave                             200     0xC8
\(~A (Atilde)                         195     0xC3
\(:A (Adiaeresis)                     196     0xC4
\(oA (Aring)                          197     0xC5
\(AE (AE)                             198     0xC6
\(,C (Ccedilla)                       199     0xC7
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
\(`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
Oslash                             216     0xD8
Ugrave                             217     0xD9
\(/O (Oslash)                         216     0xD8
Uacute                             218     0xDA
Ucircumflex                        219     0xDB
Udiaeresis                         220     0xDC
Yacute                             221     0xDD
THORN                              222     0xDE
ssharp                             223     0xDF
agrave                             224     0xE0
\(`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
aacute                             225     0xE1
acircumflex                        226     0xE2
atilde                             227     0xE3
adiaeresis                         228     0xE4
aring                              229     0xE5
ae                                 230     0xE6
ccedilla                           231     0xE7
egrave                             232     0xE8
\(`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
eacute                             233     0xE9
ecircumflex                        234     0xEA
ediaeresis                         235     0xEB
igrave                             236     0xEC
iacute                             237     0xED
\(`e (egrave)                         232     0xE8
\('e (eacute)                         233     0xE9
\(^e (ecircumflex)                    234     0xEA
\(:e (ediaeresis)                     235     0xEB
\(`i (igrave)                         236     0xEC
\('i (iacute)                         237     0xED
icircumflex                        238     0xEE
idiaeresis                         239     0xEF
eth                                240     0xF0
ntilde                             241     0xF1
ograve                             242     0xF2
\(^i (icircumflex)                    238     0xEE
\(:i (idiaeresis)                     239     0xEF
\(Sd (eth)                            240     0xF0
\(~n (ntilde)                         241     0xF1
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
\(`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
lcaron                             437     0x1B5
sacute                             438     0x1B6
390
391
392
393
394
395
396


397
398
399
400
401
402
403
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405







+
+







kana_RU                           1241     0x4D9
kana_RE                           1242     0x4DA
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
Arabic_hamzaonalef                1475     0x5C3
Arabic_hamzaonwaw                 1476     0x5C4
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
427
428
429
430
431
432
433


434
435
436
437
438
439
440







-
-







Arabic_ghain                      1498     0x5DA
Arabic_tatweel                    1504     0x5E0
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
Arabic_fathatan                   1515     0x5EB
Arabic_dammatan                   1516     0x5EC
452
453
454
455
456
457
458

459
460
461
462
463
464
465
466
467
468
469
470
471
472
473

474
475
476
477
478
479
480
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482







+















+







Ukrainian_i                       1702     0x6A6
Ukrainian_yi                      1703     0x6A7
Cyrillic_je                       1704     0x6A8
Cyrillic_lje                      1705     0x6A9
Cyrillic_nje                      1706     0x6AA
Serbian_tshe                      1707     0x6AB
Macedonia_kje                     1708     0x6AC
Ukrainian_ghe_with_upturn         1709     0x6AD
Byelorussian_shortu               1710     0x6AE
Cyrillic_dzhe                     1711     0x6AF
numerosign                        1712     0x6B0
Serbian_DJE                       1713     0x6B1
Macedonia_GJE                     1714     0x6B2
Cyrillic_IO                       1715     0x6B3
Ukrainian_IE                      1716     0x6B4
Macedonia_DSE                     1717     0x6B5
Ukrainian_I                       1718     0x6B6
Ukrainian_YI                      1719     0x6B7
Cyrillic_JE                       1720     0x6B8
Cyrillic_LJE                      1721     0x6B9
Cyrillic_NJE                      1722     0x6BA
Serbian_TSHE                      1723     0x6BB
Macedonia_KJE                     1724     0x6BC
Ukrainian_GHE_WITH_UPTURN         1725     0x6BD
Byelorussian_SHORTU               1726     0x6BE
Cyrillic_DZHE                     1727     0x6BF
Cyrillic_yu                       1728     0x6C0
Cyrillic_a                        1729     0x6C1
Cyrillic_be                       1730     0x6C2
Cyrillic_tse                      1731     0x6C3
Cyrillic_de                       1732     0x6C4
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
540
541
542
543
544
545
546

547
548
549

550
551
552
553
554
555
556







-



-







Cyrillic_CHE                      1790     0x6FE
Cyrillic_HARDSIGN                 1791     0x6FF
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
Greek_etaaccent                   1971     0x7B3
Greek_iotaaccent                  1972     0x7B4
606
607
608
609
610
611
612


613
614
615
616
617
618
619
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621







+
+







Greek_finalsmallsigma             2035     0x7F3
Greek_tau                         2036     0x7F4
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
vertconnector                     2214     0x8A6
topleftsqbracket                  2215     0x8A7
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
631
632
633
634
635
636
637


638
639
640
641
642
643
644







-
-







topleftsummation                  2225     0x8B1
botleftsummation                  2226     0x8B2
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
variation                         2241     0x8C1
infinity                          2242     0x8C2
724
725
726
727
728
729
730

731
732
733
734
735
736
737
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738







+







emopencircle                      2766     0xACE
emopenrectangle                   2767     0xACF
leftsinglequotemark               2768     0xAD0
rightsinglequotemark              2769     0xAD1
leftdoublequotemark               2770     0xAD2
rightdoublequotemark              2771     0xAD3
prescription                      2772     0xAD4
permille                          2773     0xAD5
minutes                           2774     0xAD6
seconds                           2775     0xAD7
latincross                        2777     0xAD9
hexagram                          2778     0xADA
filledrectbullet                  2779     0xADB
filledlefttribullet               2780     0xADC
filledrighttribullet              2781     0xADD
811
812
813
814
815
816
817



































































































































































































































































































































































818
819
820
821
822
823
824
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







hebrew_pe                         3316     0xCF4
hebrew_finalzade                  3317     0xCF5
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
Thai_khorakhang                   3494     0xDA6
Thai_ngongu                       3495     0xDA7
Thai_chochan                      3496     0xDA8
Thai_choching                     3497     0xDA9
Thai_chochang                     3498     0xDAA
Thai_soso                         3499     0xDAB
Thai_chochoe                      3500     0xDAC
Thai_yoying                       3501     0xDAD
Thai_dochada                      3502     0xDAE
Thai_topatak                      3503     0xDAF
Thai_thothan                      3504     0xDB0
Thai_thonangmontho                3505     0xDB1
Thai_thophuthao                   3506     0xDB2
Thai_nonen                        3507     0xDB3
Thai_dodek                        3508     0xDB4
Thai_totao                        3509     0xDB5
Thai_thothung                     3510     0xDB6
Thai_thothahan                    3511     0xDB7
Thai_thothong                     3512     0xDB8
Thai_nonu                         3513     0xDB9
Thai_bobaimai                     3514     0xDBA
Thai_popla                        3515     0xDBB
Thai_phophung                     3516     0xDBC
Thai_fofa                         3517     0xDBD
Thai_phophan                      3518     0xDBE
Thai_fofan                        3519     0xDBF
Thai_phosamphao                   3520     0xDC0
Thai_moma                         3521     0xDC1
Thai_yoyak                        3522     0xDC2
Thai_rorua                        3523     0xDC3
Thai_ru                           3524     0xDC4
Thai_loling                       3525     0xDC5
Thai_lu                           3526     0xDC6
Thai_wowaen                       3527     0xDC7
Thai_sosala                       3528     0xDC8
Thai_sorusi                       3529     0xDC9
Thai_sosua                        3530     0xDCA
Thai_hohip                        3531     0xDCB
Thai_lochula                      3532     0xDCC
Thai_oang                         3533     0xDCD
Thai_honokhuk                     3534     0xDCE
Thai_paiyannoi                    3535     0xDCF
Thai_saraa                        3536     0xDD0
Thai_maihanakat                   3537     0xDD1
Thai_saraaa                       3538     0xDD2
Thai_saraam                       3539     0xDD3
Thai_sarai                        3540     0xDD4
Thai_saraii                       3541     0xDD5
Thai_saraue                       3542     0xDD6
Thai_sarauee                      3543     0xDD7
Thai_sarau                        3544     0xDD8
Thai_sarauu                       3545     0xDD9
Thai_phinthu                      3546     0xDDA
Thai_maihanakat_maitho            3550     0xDDE
Thai_baht                         3551     0xDDF
Thai_sarae                        3552     0xDE0
Thai_saraae                       3553     0xDE1
Thai_sarao                        3554     0xDE2
Thai_saraaimaimuan                3555     0xDE3
Thai_saraaimaimalai               3556     0xDE4
Thai_lakkhangyao                  3557     0xDE5
Thai_maiyamok                     3558     0xDE6
Thai_maitaikhu                    3559     0xDE7
Thai_maiek                        3560     0xDE8
Thai_maitho                       3561     0xDE9
Thai_maitri                       3562     0xDEA
Thai_maichattawa                  3563     0xDEB
Thai_thanthakhat                  3564     0xDEC
Thai_nikhahit                     3565     0xDED
Thai_leksun                       3568     0xDF0
Thai_leknung                      3569     0xDF1
Thai_leksong                      3570     0xDF2
Thai_leksam                       3571     0xDF3
Thai_leksi                        3572     0xDF4
Thai_lekha                        3573     0xDF5
Thai_lekhok                       3574     0xDF6
Thai_lekchet                      3575     0xDF7
Thai_lekpaet                      3576     0xDF8
Thai_lekkao                       3577     0xDF9
Hangul_Kiyeog                     3745     0xEA1
Hangul_SsangKiyeog                3746     0xEA2
Hangul_KiyeogSios                 3747     0xEA3
Hangul_Nieun                      3748     0xEA4
Hangul_NieunJieuj                 3749     0xEA5
Hangul_NieunHieuh                 3750     0xEA6
Hangul_Dikeud                     3751     0xEA7
Hangul_SsangDikeud                3752     0xEA8
Hangul_Rieul                      3753     0xEA9
Hangul_RieulKiyeog                3754     0xEAA
Hangul_RieulMieum                 3755     0xEAB
Hangul_RieulPieub                 3756     0xEAC
Hangul_RieulSios                  3757     0xEAD
Hangul_RieulTieut                 3758     0xEAE
Hangul_RieulPhieuf                3759     0xEAF
Hangul_RieulHieuh                 3760     0xEB0
Hangul_Mieum                      3761     0xEB1
Hangul_Pieub                      3762     0xEB2
Hangul_SsangPieub                 3763     0xEB3
Hangul_PieubSios                  3764     0xEB4
Hangul_Sios                       3765     0xEB5
Hangul_SsangSios                  3766     0xEB6
Hangul_Ieung                      3767     0xEB7
Hangul_Jieuj                      3768     0xEB8
Hangul_SsangJieuj                 3769     0xEB9
Hangul_Cieuc                      3770     0xEBA
Hangul_Khieuq                     3771     0xEBB
Hangul_Tieut                      3772     0xEBC
Hangul_Phieuf                     3773     0xEBD
Hangul_Hieuh                      3774     0xEBE
Hangul_A                          3775     0xEBF
Hangul_AE                         3776     0xEC0
Hangul_YA                         3777     0xEC1
Hangul_YAE                        3778     0xEC2
Hangul_EO                         3779     0xEC3
Hangul_E                          3780     0xEC4
Hangul_YEO                        3781     0xEC5
Hangul_YE                         3782     0xEC6
Hangul_O                          3783     0xEC7
Hangul_WA                         3784     0xEC8
Hangul_WAE                        3785     0xEC9
Hangul_OE                         3786     0xECA
Hangul_YO                         3787     0xECB
Hangul_U                          3788     0xECC
Hangul_WEO                        3789     0xECD
Hangul_WE                         3790     0xECE
Hangul_WI                         3791     0xECF
Hangul_YU                         3792     0xED0
Hangul_EU                         3793     0xED1
Hangul_YI                         3794     0xED2
Hangul_I                          3795     0xED3
Hangul_J_Kiyeog                   3796     0xED4
Hangul_J_SsangKiyeog              3797     0xED5
Hangul_J_KiyeogSios               3798     0xED6
Hangul_J_Nieun                    3799     0xED7
Hangul_J_NieunJieuj               3800     0xED8
Hangul_J_NieunHieuh               3801     0xED9
Hangul_J_Dikeud                   3802     0xEDA
Hangul_J_Rieul                    3803     0xEDB
Hangul_J_RieulKiyeog              3804     0xEDC
Hangul_J_RieulMieum               3805     0xEDD
Hangul_J_RieulPieub               3806     0xEDE
Hangul_J_RieulSios                3807     0xEDF
Hangul_J_RieulTieut               3808     0xEE0
Hangul_J_RieulPhieuf              3809     0xEE1
Hangul_J_RieulHieuh               3810     0xEE2
Hangul_J_Mieum                    3811     0xEE3
Hangul_J_Pieub                    3812     0xEE4
Hangul_J_PieubSios                3813     0xEE5
Hangul_J_Sios                     3814     0xEE6
Hangul_J_SsangSios                3815     0xEE7
Hangul_J_Ieung                    3816     0xEE8
Hangul_J_Jieuj                    3817     0xEE9
Hangul_J_Cieuc                    3818     0xEEA
Hangul_J_Khieuq                   3819     0xEEB
Hangul_J_Tieut                    3820     0xEEC
Hangul_J_Phieuf                   3821     0xEED
Hangul_J_Hieuh                    3822     0xEEE
Hangul_RieulYeorinHieuh           3823     0xEEF
Hangul_SunkyeongeumMieum          3824     0xEF0
Hangul_SunkyeongeumPieub          3825     0xEF1
Hangul_PanSios                    3826     0xEF2
Hangul_KkogjiDalrinIeung          3827     0xEF3
Hangul_SunkyeongeumPhieuf         3828     0xEF4
Hangul_YeorinHieuh                3829     0xEF5
Hangul_AraeA                      3830     0xEF6
Hangul_AraeAE                     3831     0xEF7
Hangul_J_PanSios                  3832     0xEF8
Hangul_J_KkogjiDalrinIeung        3833     0xEF9
Hangul_J_YeorinHieuh              3834     0xEFA
Korean_Won                        3839     0xEFF
OE                                5052     0x13BC
oe                                5053     0x13BD
Ydiaeresis                        5054     0x13BE
\(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
3270_EraseEOF                    64774     0xFD06
3270_EraseInput                  64775     0xFD07
3270_Reset                       64776     0xFD08
3270_Quit                        64777     0xFD09
3270_PA1                         64778     0xFD0A
3270_PA2                         64779     0xFD0B
3270_PA3                         64780     0xFD0C
3270_Test                        64781     0xFD0D
3270_Attn                        64782     0xFD0E
3270_CursorBlink                 64783     0xFD0F
3270_AltCursor                   64784     0xFD10
3270_KeyClick                    64785     0xFD11
3270_Jump                        64786     0xFD12
3270_Ident                       64787     0xFD13
3270_Rule                        64788     0xFD14
3270_Copy                        64789     0xFD15
3270_Play                        64790     0xFD16
3270_Setup                       64791     0xFD17
3270_Record                      64792     0xFD18
3270_ChangeScreen                64793     0xFD19
3270_DeleteWord                  64794     0xFD1A
3270_ExSelect                    64795     0xFD1B
3270_CursorSelect                64796     0xFD1C
3270_PrintScreen                 64797     0xFD1D
3270_Enter                       64798     0xFD1E
ISO_Lock                         65025     0xFE01
ISO_Level2_Latch                 65026     0xFE02
ISO_Level3_Shift                 65027     0xFE03
ISO_Level3_Latch                 65028     0xFE04
ISO_Level3_Lock                  65029     0xFE05
ISO_Group_Latch                  65030     0xFE06
ISO_Group_Lock                   65031     0xFE07
ISO_Next_Group                   65032     0xFE08
ISO_Next_Group_Lock              65033     0xFE09
ISO_Prev_Group                   65034     0xFE0A
ISO_Prev_Group_Lock              65035     0xFE0B
ISO_First_Group                  65036     0xFE0C
ISO_First_Group_Lock             65037     0xFE0D
ISO_Last_Group                   65038     0xFE0E
ISO_Last_Group_Lock              65039     0xFE0F
ISO_Level5_Shift                 65041     0xFE11
ISO_Level5_Latch                 65042     0xFE12
ISO_Level5_Lock                  65043     0xFE13
ISO_Left_Tab                     65056     0xFE20
ISO_Move_Line_Up                 65057     0xFE21
ISO_Move_Line_Down               65058     0xFE22
ISO_Partial_Line_Up              65059     0xFE23
ISO_Partial_Line_Down            65060     0xFE24
ISO_Partial_Space_Left           65061     0xFE25
ISO_Partial_Space_Right          65062     0xFE26
ISO_Set_Margin_Left              65063     0xFE27
ISO_Set_Margin_Right             65064     0xFE28
ISO_Release_Margin_Left          65065     0xFE29
ISO_Release_Margin_Right         65066     0xFE2A
ISO_Release_Both_Margins         65067     0xFE2B
ISO_Fast_Cursor_Left             65068     0xFE2C
ISO_Fast_Cursor_Right            65069     0xFE2D
ISO_Fast_Cursor_Up               65070     0xFE2E
ISO_Fast_Cursor_Down             65071     0xFE2F
ISO_Continuous_Underline         65072     0xFE30
ISO_Discontinuous_Underline      65073     0xFE31
ISO_Emphasize                    65074     0xFE32
ISO_Center_Object                65075     0xFE33
ISO_Enter                        65076     0xFE34
dead_grave                       65104     0xFE50
dead_acute                       65105     0xFE51
dead_circumflex                  65106     0xFE52
dead_tilde                       65107     0xFE53
dead_macron                      65108     0xFE54
dead_breve                       65109     0xFE55
dead_abovedot                    65110     0xFE56
dead_diaeresis                   65111     0xFE57
dead_abovering                   65112     0xFE58
dead_doubleacute                 65113     0xFE59
dead_caron                       65114     0xFE5A
dead_cedilla                     65115     0xFE5B
dead_ogonek                      65116     0xFE5C
dead_iota                        65117     0xFE5D
dead_voiced_sound                65118     0xFE5E
dead_semivoiced_sound            65119     0xFE5F
dead_belowdot                    65120     0xFE60
dead_hook                        65121     0xFE61
dead_horn                        65122     0xFE62
dead_stroke                      65123     0xFE63
dead_abovecomma                  65124     0xFE64
dead_abovereversedcomma          65125     0xFE65
dead_doublegrave                 65126     0xFE66
dead_belowring                   65127     0xFE67
dead_belowmacron                 65128     0xFE68
dead_belowcircumflex             65129     0xFE69
dead_belowtilde                  65130     0xFE6A
dead_belowbreve                  65131     0xFE6B
dead_belowdiaeresis              65132     0xFE6C
dead_invertedbreve               65133     0xFE6D
dead_belowcomma                  65134     0xFE6E
dead_currency                    65135     0xFE6F
AccessX_Enable                   65136     0xFE70
AccessX_Feedback_Enable          65137     0xFE71
RepeatKeys_Enable                65138     0xFE72
SlowKeys_Enable                  65139     0xFE73
BounceKeys_Enable                65140     0xFE74
StickyKeys_Enable                65141     0xFE75
MouseKeys_Enable                 65142     0xFE76
MouseKeys_Accel_Enable           65143     0xFE77
Overlay1_Enable                  65144     0xFE78
Overlay2_Enable                  65145     0xFE79
AudibleBell_Enable               65146     0xFE7A
dead_a                           65152     0xFE80
dead_A                           65153     0xFE81
dead_e                           65154     0xFE82
dead_E                           65155     0xFE83
dead_i                           65156     0xFE84
dead_I                           65157     0xFE85
dead_o                           65158     0xFE86
dead_O                           65159     0xFE87
dead_u                           65160     0xFE88
dead_U                           65161     0xFE89
dead_small_schwa                 65162     0xFE8A
dead_capital_schwa               65163     0xFE8B
dead_greek                       65164     0xFE8C
dead_lowline                     65168     0xFE90
dead_aboveverticalline           65169     0xFE91
dead_belowverticalline           65170     0xFE92
dead_longsolidusoverlay          65171     0xFE93
ch                               65184     0xFEA0
Ch                               65185     0xFEA1
CH                               65186     0xFEA2
c_h                              65187     0xFEA3
C_h                              65188     0xFEA4
C_H                              65189     0xFEA5
First_Virtual_Screen             65232     0xFED0
Prev_Virtual_Screen              65233     0xFED1
Next_Virtual_Screen              65234     0xFED2
Last_Virtual_Screen              65236     0xFED4
Terminate_Server                 65237     0xFED5
Pointer_Left                     65248     0xFEE0
Pointer_Right                    65249     0xFEE1
Pointer_Up                       65250     0xFEE2
Pointer_Down                     65251     0xFEE3
Pointer_UpLeft                   65252     0xFEE4
Pointer_UpRight                  65253     0xFEE5
Pointer_DownLeft                 65254     0xFEE6
Pointer_DownRight                65255     0xFEE7
Pointer_Button_Dflt              65256     0xFEE8
Pointer_Button1                  65257     0xFEE9
Pointer_Button2                  65258     0xFEEA
Pointer_Button3                  65259     0xFEEB
Pointer_Button4                  65260     0xFEEC
Pointer_Button5                  65261     0xFEED
Pointer_DblClick_Dflt            65262     0xFEEE
Pointer_DblClick1                65263     0xFEEF
Pointer_DblClick2                65264     0xFEF0
Pointer_DblClick3                65265     0xFEF1
Pointer_DblClick4                65266     0xFEF2
Pointer_DblClick5                65267     0xFEF3
Pointer_Drag_Dflt                65268     0xFEF4
Pointer_Drag1                    65269     0xFEF5
Pointer_Drag2                    65270     0xFEF6
Pointer_Drag3                    65271     0xFEF7
Pointer_Drag4                    65272     0xFEF8
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
Pause                            65299     0xFF13
Scroll_Lock                      65300     0xFF14
837
838
839
840
841
842
843















844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225


1226
1227
1228
1229
1230
1231
1232







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+











-
-







Zenkaku_Hankaku                  65322     0xFF2A
Touroku                          65323     0xFF2B
Massyo                           65324     0xFF2C
Kana_Lock                        65325     0xFF2D
Kana_Shift                       65326     0xFF2E
Eisu_Shift                       65327     0xFF2F
Eisu_toggle                      65328     0xFF30
Hangul                           65329     0xFF31
Hangul_Start                     65330     0xFF32
Hangul_End                       65331     0xFF33
Hangul_Hanja                     65332     0xFF34
Hangul_Jamo                      65333     0xFF35
Hangul_Romaja                    65334     0xFF36
Codeinput                        65335     0xFF37
Hangul_Jeonja                    65336     0xFF38
Hangul_Banja                     65337     0xFF39
Hangul_PreHanja                  65338     0xFF3A
Hangul_PostHanja                 65339     0xFF3B
SingleCandidate                  65340     0xFF3C
MultipleCandidate                65341     0xFF3D
PreviousCandidate                65342     0xFF3E
Hangul_Special                   65343     0xFF3F
Home                             65360     0xFF50
Left                             65361     0xFF51
Up                               65362     0xFF52
Right                            65363     0xFF53
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
948
949
950
951
952
953
954










955



















































956
957
958
959
960
961
962






















































































































































963
964
965
966
967
968
969
970
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550







+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








Meta_R                           65512     0xFFE8
Alt_L                            65513     0xFFE9
Alt_R                            65514     0xFFEA
Super_L                          65515     0xFFEB
Super_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
braille_dot_4                    65524     0xFFF4
braille_dot_5                    65525     0xFFF5
braille_dot_6                    65526     0xFFF6
braille_dot_7                    65527     0xFFF7
braille_dot_8                    65528     0xFFF8
braille_dot_9                    65529     0xFFF9
braille_dot_10                   65530     0xFFFA
Delete                           65535     0xFFFF
.CE
.CS
SunFA_Grave                  268828416     0x1005FF00
SunFA_Circum                 268828417     0x1005FF01
SunFA_Tilde                  268828418     0x1005FF02
SunFA_Acute                  268828419     0x1005FF03
SunFA_Diaeresis              268828420     0x1005FF04
SunFA_Cedilla                268828421     0x1005FF05
SunF36                       268828432     0x1005FF10
SunF37                       268828433     0x1005FF11
SunSys_Req                   268828512     0x1005FF60
SunProps                     268828528     0x1005FF70
SunFront                     268828529     0x1005FF71
SunCopy                      268828530     0x1005FF72
SunOpen                      268828531     0x1005FF73
SunPaste                     268828532     0x1005FF74
SunCut                       268828533     0x1005FF75
SunPowerSwitch               268828534     0x1005FF76
SunAudioLowerVolume          268828535     0x1005FF77
SunAudioMute                 268828536     0x1005FF78
SunAudioRaiseVolume          268828537     0x1005FF79
SunVideoDegauss              268828538     0x1005FF7A
SunVideoLowerBrightness      268828539     0x1005FF7B
SunVideoRaiseBrightness      268828540     0x1005FF7C
SunPowerSwitchShift          268828541     0x1005FF7D
XF86Switch_VT_1              269024769     0x1008FE01
XF86Switch_VT_2              269024770     0x1008FE02
XF86Switch_VT_3              269024771     0x1008FE03
XF86Switch_VT_4              269024772     0x1008FE04
XF86Switch_VT_5              269024773     0x1008FE05
XF86Switch_VT_6              269024774     0x1008FE06
XF86Switch_VT_7              269024775     0x1008FE07
XF86Switch_VT_8              269024776     0x1008FE08
XF86Switch_VT_9              269024777     0x1008FE09
XF86Switch_VT_10             269024778     0x1008FE0A
XF86Switch_VT_11             269024779     0x1008FE0B
XF86Switch_VT_12             269024780     0x1008FE0C
XF86Ungrab                   269024800     0x1008FE20
XF86ClearGrab                269024801     0x1008FE21
XF86Next_VMode               269024802     0x1008FE22
XF86Prev_VMode               269024803     0x1008FE23
XF86LogWindowTree            269024804     0x1008FE24
XF86LogGrabInfo              269024805     0x1008FE25
XF86ModeLock                 269025025     0x1008FF01
XF86MonBrightnessUp          269025026     0x1008FF02
XF86MonBrightnessDown        269025027     0x1008FF03
XF86KbdLightOnOff            269025028     0x1008FF04
XF86KbdBrightnessUp          269025029     0x1008FF05
XF86KbdBrightnessDown        269025030     0x1008FF06
XF86MonBrightnessCycle       269025031     0x1008FF07
XF86Standby                  269025040     0x1008FF10
XF86AudioLowerVolume         269025041     0x1008FF11
XF86AudioMute                269025042     0x1008FF12
XF86AudioRaiseVolume         269025043     0x1008FF13
XF86AudioPlay                269025044     0x1008FF14
XF86AudioStop                269025045     0x1008FF15
XF86AudioPrev                269025046     0x1008FF16
XF86AudioNext                269025047     0x1008FF17
XF86HomePage                 269025048     0x1008FF18
XF86Mail                     269025049     0x1008FF19
XF86Start                    269025050     0x1008FF1A
XF86Search                   269025051     0x1008FF1B
XF86AudioRecord              269025052     0x1008FF1C
XF86Calculator               269025053     0x1008FF1D
XF86Memo                     269025054     0x1008FF1E
XF86ToDoList                 269025055     0x1008FF1F
XF86Calendar                 269025056     0x1008FF20
XF86PowerDown                269025057     0x1008FF21
XF86ContrastAdjust           269025058     0x1008FF22
XF86RockerUp                 269025059     0x1008FF23
XF86RockerDown               269025060     0x1008FF24
XF86RockerEnter              269025061     0x1008FF25
XF86Back                     269025062     0x1008FF26
XF86Forward                  269025063     0x1008FF27
XF86Stop                     269025064     0x1008FF28
XF86Refresh                  269025065     0x1008FF29
XF86PowerOff                 269025066     0x1008FF2A
XF86WakeUp                   269025067     0x1008FF2B
XF86Eject                    269025068     0x1008FF2C
XF86ScreenSaver              269025069     0x1008FF2D
XF86WWW                      269025070     0x1008FF2E
XF86Sleep                    269025071     0x1008FF2F
XF86Favorites                269025072     0x1008FF30
XF86AudioPause               269025073     0x1008FF31
XF86AudioMedia               269025074     0x1008FF32
XF86MyComputer               269025075     0x1008FF33
XF86VendorHome               269025076     0x1008FF34
XF86LightBulb                269025077     0x1008FF35
XF86Shop                     269025078     0x1008FF36
XF86History                  269025079     0x1008FF37
XF86OpenURL                  269025080     0x1008FF38
XF86AddFavorite              269025081     0x1008FF39
XF86HotLinks                 269025082     0x1008FF3A
XF86BrightnessAdjust         269025083     0x1008FF3B
XF86Finance                  269025084     0x1008FF3C
XF86Community                269025085     0x1008FF3D
XF86AudioRewind              269025086     0x1008FF3E
XF86BackForward              269025087     0x1008FF3F
XF86Launch0                  269025088     0x1008FF40
XF86Launch1                  269025089     0x1008FF41
XF86Launch2                  269025090     0x1008FF42
XF86Launch3                  269025091     0x1008FF43
XF86Launch4                  269025092     0x1008FF44
XF86Launch5                  269025093     0x1008FF45
XF86Launch6                  269025094     0x1008FF46
XF86Launch7                  269025095     0x1008FF47
XF86Launch8                  269025096     0x1008FF48
XF86Launch9                  269025097     0x1008FF49
XF86LaunchA                  269025098     0x1008FF4A
XF86LaunchB                  269025099     0x1008FF4B
XF86LaunchC                  269025100     0x1008FF4C
XF86LaunchD                  269025101     0x1008FF4D
XF86LaunchE                  269025102     0x1008FF4E
XF86LaunchF                  269025103     0x1008FF4F
XF86ApplicationLeft          269025104     0x1008FF50
XF86ApplicationRight         269025105     0x1008FF51
XF86Book                     269025106     0x1008FF52
XF86CD                       269025107     0x1008FF53
XF86Calculater               269025108     0x1008FF54
XF86Clear                    269025109     0x1008FF55
XF86Close                    269025110     0x1008FF56
XF86Copy                     269025111     0x1008FF57
XF86Cut                      269025112     0x1008FF58
XF86Display                  269025113     0x1008FF59
XF86DOS                      269025114     0x1008FF5A
XF86Documents                269025115     0x1008FF5B
XF86Excel                    269025116     0x1008FF5C
XF86Explorer                 269025117     0x1008FF5D
XF86Game                     269025118     0x1008FF5E
XF86Go                       269025119     0x1008FF5F
XF86iTouch                   269025120     0x1008FF60
XF86LogOff                   269025121     0x1008FF61
XF86Market                   269025122     0x1008FF62
XF86Meeting                  269025123     0x1008FF63
XF86MenuKB                   269025125     0x1008FF65
XF86MenuPB                   269025126     0x1008FF66
XF86MySites                  269025127     0x1008FF67
XF86New                      269025128     0x1008FF68
XF86News                     269025129     0x1008FF69
XF86OfficeHome               269025130     0x1008FF6A
XF86Open                     269025131     0x1008FF6B
XF86Option                   269025132     0x1008FF6C
XF86Paste                    269025133     0x1008FF6D
XF86Phone                    269025134     0x1008FF6E
XF86Q                        269025136     0x1008FF70
XF86Reply                    269025138     0x1008FF72
XF86Reload                   269025139     0x1008FF73
XF86RotateWindows            269025140     0x1008FF74
XF86RotationPB               269025141     0x1008FF75
XF86RotationKB               269025142     0x1008FF76
XF86Save                     269025143     0x1008FF77
XF86ScrollUp                 269025144     0x1008FF78
XF86ScrollDown               269025145     0x1008FF79
XF86ScrollClick              269025146     0x1008FF7A
XF86Send                     269025147     0x1008FF7B
XF86Spell                    269025148     0x1008FF7C
XF86SplitScreen              269025149     0x1008FF7D
XF86Support                  269025150     0x1008FF7E
XF86TaskPane                 269025151     0x1008FF7F
XF86Terminal                 269025152     0x1008FF80
XF86Tools                    269025153     0x1008FF81
XF86Travel                   269025154     0x1008FF82
XF86UserPB                   269025156     0x1008FF84
XF86User1KB                  269025157     0x1008FF85
XF86User2KB                  269025158     0x1008FF86
XF86Video                    269025159     0x1008FF87
XF86WheelButton              269025160     0x1008FF88
XF86Word                     269025161     0x1008FF89
XF86Xfer                     269025162     0x1008FF8A
XF86ZoomIn                   269025163     0x1008FF8B
XF86ZoomOut                  269025164     0x1008FF8C
XF86Away                     269025165     0x1008FF8D
XF86Messenger                269025166     0x1008FF8E
XF86WebCam                   269025167     0x1008FF8F
XF86MailForward              269025168     0x1008FF90
XF86Pictures                 269025169     0x1008FF91
XF86Music                    269025170     0x1008FF92
XF86Battery                  269025171     0x1008FF93
XF86Bluetooth                269025172     0x1008FF94
XF86WLAN                     269025173     0x1008FF95
XF86UWB                      269025174     0x1008FF96
XF86AudioForward             269025175     0x1008FF97
XF86AudioRepeat              269025176     0x1008FF98
XF86AudioRandomPlay          269025177     0x1008FF99
XF86Subtitle                 269025178     0x1008FF9A
XF86AudioCycleTrack          269025179     0x1008FF9B
XF86CycleAngle               269025180     0x1008FF9C
XF86FrameBack                269025181     0x1008FF9D
XF86FrameForward             269025182     0x1008FF9E
XF86Time                     269025183     0x1008FF9F
XF86Select                   269025184     0x1008FFA0
XF86View                     269025185     0x1008FFA1
XF86TopMenu                  269025186     0x1008FFA2
XF86Red                      269025187     0x1008FFA3
XF86Green                    269025188     0x1008FFA4
XF86Yellow                   269025189     0x1008FFA5
XF86Blue                     269025190     0x1008FFA6
XF86Suspend                  269025191     0x1008FFA7
XF86Hibernate                269025192     0x1008FFA8
XF86TouchpadToggle           269025193     0x1008FFA9
XF86TouchpadOn               269025200     0x1008FFB0
XF86TouchpadOff              269025201     0x1008FFB1
XF86AudioMicMute             269025202     0x1008FFB2
XF86Keyboard                 269025203     0x1008FFB3
XF86WWAN                     269025204     0x1008FFB4
XF86RFKill                   269025205     0x1008FFB5
XF86AudioPreset              269025206     0x1008FFB6
XF86RotationLockToggle       269025207     0x1008FFB7
.CE
.SH "SEE ALSO"
bind(n), event(n)
.SH KEYWORDS
bind, binding, event, keysym
'\" Local Variables:
'\" mode: nroff
'\" End:
Changes to doc/label.n.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1990-1994 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH label n 4.0 Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
label \- Create and manipulate 'label' non-interactive text or image widgets
.SH SYNOPSIS
71
72
73
74
75
76
77
78

79
80
81
82
83
84
85
71
72
73
74
75
76
77

78
79
80
81
82
83
84
85







-
+







.SH "WIDGET COMMAND"
.PP
The \fBlabel\fR command creates a new Tcl command whose
name is \fIpathName\fR.  This
command may be used to invoke various
operations on the widget.  It has the following general form:
.CS
\fIpathName option \fR?\fIarg arg ...\fR?
\fIpathName option \fR?\fIarg ...\fR?
.CE
\fIOption\fR and the \fIarg\fRs
determine the exact behavior of the command.  The following
commands are possible for label widgets:
.TP
\fIpathName \fBcget\fR \fIoption\fR
Returns the current value of the configuration option given
Changes to doc/labelframe.n.
91
92
93
94
95
96
97
98

99
100
101
102
103
104
105
106
107
108
109
110
111

112
113
114
115
116
117
118
91
92
93
94
95
96
97

98
99
100
101
102
103
104
105
106
107
108
109
110

111
112
113
114
115
116
117
118







-
+












-
+







.SH "WIDGET COMMAND"
.PP
The \fBlabelframe\fR command creates a new Tcl command whose
name is the same as the path name of the labelframe's window.  This
command may be used to invoke various
operations on the widget.  It has the following general form:
.CS
\fIpathName option \fR?\fIarg arg ...\fR?
\fIpathName option \fR?\fIarg ...\fR?
.CE
\fIPathName\fR is the name of the command, which is the same as
the labelframe widget's path name.  \fIOption\fR and the \fIarg\fRs
determine the exact behavior of the command.  The following
commands are possible for frame widgets:
.TP
\fIpathName \fBcget\fR \fIoption\fR
Returns the current value of the configuration option given
by \fIoption\fR.
\fIOption\fR may have any of the values accepted by the \fBlabelframe\fR
command.
.TP
\fIpathName \fBconfigure\fR ?\fIoption\fR? \fI?value option value ...\fR?
\fIpathName \fBconfigure\fR ?\fIoption\fR? ?\fIvalue option value ...\fR?
Query or modify the configuration options of the widget.
If no \fIoption\fR is specified, returns a list describing all of
the available options for \fIpathName\fR (see \fBTk_ConfigureInfo\fR for
information on the format of this list).  If \fIoption\fR is specified
with no \fIvalue\fR, then the command returns a list describing the
one named option (this list will be identical to the corresponding
sublist of the value returned if no \fIoption\fR is specified).  If
Changes to doc/listbox.n.
132
133
134
135
136
137
138
139

140
141
142
143
144
145
146
132
133
134
135
136
137
138

139
140
141
142
143
144
145
146







-
+







.SH "WIDGET COMMAND"
.PP
The \fBlistbox\fR command creates a new Tcl command whose
name is \fIpathName\fR.  This
command may be used to invoke various
operations on the widget.  It has the following general form:
.CS
\fIpathName option \fR?\fIarg arg ...\fR?
\fIpathName option \fR?\fIarg ...\fR?
.CE
\fIOption\fR and the \fIarg\fRs
determine the exact behavior of the command.  The following
commands are possible for listbox widgets:
.TP
\fIpathName \fBactivate\fR \fIindex\fR
.
379
380
381
382
383
384
385
386
387



388
389
390
391

392
393
394
395



396
397
398
399
400
401
402
379
380
381
382
383
384
385


386
387
388
389



390
391
392
393
394
395
396
397
398
399
400
401
402
403
404







-
-
+
+
+

-
-
-
+




+
+
+







total width of the listbox text is off-screen to the left.
\fIfraction\fR must be a fraction between 0 and 1.
.TP
\fIpathName \fBxview scroll \fInumber what\fR
.
This command shifts the view in the window left or right according to
\fInumber\fR and \fIwhat\fR.
\fINumber\fR must be an integer.
\fIWhat\fR must be either \fBunits\fR or \fBpages\fR or an abbreviation
\fINumber\fR must be an integer or a float, but if it is a float then
it is converted to an integer, rounded away from 0.
\fIWhat\fR must be either \fBpages\fR or \fBunits\fR or an abbreviation
of one of these.
If \fIwhat\fR is \fBunits\fR, the view adjusts left or right by
\fInumber\fR character units (the width of the \fB0\fR character)
on the display;  if it is \fBpages\fR then the view adjusts by
If \fIwhat\fR is \fBpages\fR then the view adjusts by
\fInumber\fR screenfuls.
If \fInumber\fR is negative then characters farther to the left
become visible;  if it is positive then characters farther to the right
become visible.
If \fIwhat\fR is \fBunits\fR, the view adjusts left or right by
\fInumber\fR character units (the width of the \fB0\fR character)
on the display.
.RE
.TP
\fIpathName \fByview \fR?\fIargs\fR?
.
This command is used to query and change the vertical position of the
text in the widget's window.
It can take any of the following forms:
427
428
429
430
431
432
433
434
435


436
437
438
439
440


441
442
443
444
445
446
447
429
430
431
432
433
434
435


436
437

438
439
440
441
442
443
444
445
446
447
448
449
450







-
-
+
+
-




+
+







way through the listbox, and so on.
.TP
\fIpathName \fByview scroll \fInumber what\fR
.
This command adjusts the view in the window up or down according to
\fInumber\fR and \fIwhat\fR.
\fINumber\fR must be an integer.
\fIWhat\fR must be either \fBunits\fR or \fBpages\fR.
If \fIwhat\fR is \fBunits\fR, the view adjusts up or down by
\fIWhat\fR must be either \fBpages\fR or \fBunits\fR.
If \fIwhat\fR is \fBpages\fR then
\fInumber\fR lines;  if it is \fBpages\fR then
the view adjusts by \fInumber\fR screenfuls.
If \fInumber\fR is negative then earlier elements
become visible;  if it is positive then later elements
become visible.
If \fIwhat\fR is \fBunits\fR, the view adjusts up or down by
\fInumber\fR lines.
.RE
.SH "DEFAULT BINDINGS"
.PP
Tk automatically creates class bindings for listboxes that give them
Motif-like behavior.  Much of the behavior of a listbox is determined
by its \fB\-selectmode\fR option, which selects one of four ways
of dealing with the selection.
556
557
558
559
560
561
562
563

564
565
566
567
568
569
570
559
560
561
562
563
564
565

566
567
568
569
570
571
572
573







-
+







extend the selection to the active element just as if button 1
had been pressed with the Shift key down.
.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.
.IP [19]
The F16 key (labelled Copy on many Sun workstations) or Meta-w
Changes to doc/loadTk.n.
1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21













-
+







'\"
'\" Copyright (c) 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.
'\"
.TH "Safe Tk" n 8.0 Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
safe::loadTk \- Load Tk into a safe interpreter.
.SH SYNOPSIS
\fBsafe::loadTk \fIslave\fR ?\fB\-use\fR \fIwindowId\fR? ?\fB\-display\fR \fIdisplayName\fR?
\fBsafe::loadTk \fIchild\fR ?\fB\-use\fR \fIwindowId\fR? ?\fB\-display\fR \fIdisplayName\fR?
.BE
.SH DESCRIPTION
.PP
Safe Tk is based on Safe Tcl, which provides a mechanism that allows
restricted and mediated access to auto-loading and packages for safe
interpreters.  Safe Tk adds the ability to configure the interpreter for safe
Tk operations and load Tk into safe interpreters.
39
40
41
42
43
44
45
46

47
48
49
50
51
52



53
54
55
56
57
58
59
60
61
62
63
64
65
66


67
68
69
39
40
41
42
43
44
45

46
47
48
49



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64


65
66
67
68
69







-
+



-
-
-
+
+
+












-
-
+
+



another display than the default one, specify it with \fB\-display\fR.  See
the \fBSECURITY ISSUES\fR section below for implementation details.
.SH "SECURITY ISSUES"
.PP
Please read the \fBsafe\fR manual page for Tcl to learn about the basic
security considerations for Safe Tcl.
.PP
\fBsafe::loadTk\fR adds the value of \fBtk_library\fR taken from the master
\fBsafe::loadTk\fR adds the value of \fBtk_library\fR taken from the parent
interpreter to the virtual access path of the safe interpreter so that
auto-loading will work in the safe interpreter.
.PP
Tk initialization is now safe with respect to not trusting the slave's state
for startup. \fBsafe::loadTk\fR registers the slave's name so when the Tk
initialization (\fBTk_SafeInit\fR) is called and in turn calls the master's
Tk initialization is now safe with respect to not trusting the child's state
for startup. \fBsafe::loadTk\fR registers the child's name so when the Tk
initialization (\fBTk_SafeInit\fR) is called and in turn calls the parent's
\fBsafe::InitTk\fR it will return the desired \fBargv\fR equivalent
(\fB\-use\fR \fIwindowId\fR, correct \fB\-display\fR, etc.)
.PP
When \fB\-use\fR is not used, the new toplevel created is specially decorated
so the user is always aware that the user interface presented comes from a
potentially unsafe code and can easily delete the corresponding interpreter.
.PP
On X11, conflicting \fB\-use\fR and \fB\-display\fR are likely to generate a
fatal X error.
.SH "SEE ALSO"
safe(n), interp(n), library(n), load(n), package(n), source(n), unknown(n)
.SH KEYWORDS
alias, auto-loading, auto_mkindex, load, master interpreter, safe
interpreter, slave interpreter, source
alias, auto-loading, auto_mkindex, load, parent interpreter, safe
interpreter, child interpreter, source
'\" Local Variables:
'\" mode: nroff
'\" End:
Changes to doc/lower.n.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1990 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH lower n 3.3 Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
lower \- Change a window's position in the stacking order
.SH SYNOPSIS
Added doc/man.macros.











































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
.\"	and indent is equivalent to second arg of .IP (shouldn't ever be
.\"	needed;  use .AS below instead)
.\"
.\" .AS ?type? ?name?
.\"	Give maximum sizes of arguments for setting tab stops.  Type and
.\"	name are examples of largest possible arguments that will be passed
.\"	to .AP later.  If args are omitted, default tab stops are used.
.\"
.\" .BS
.\"	Start box enclosure.  From here until next .BE, everything will be
.\"	enclosed in one large box.
.\"
.\" .BE
.\"	End of box enclosure.
.\"
.\" .CS
.\"	Begin code excerpt.
.\"
.\" .CE
.\"	End code excerpt.
.\"
.\" .VS ?version? ?br?
.\"	Begin vertical sidebar, for use in marking newly-changed parts
.\"	of man pages.  The first argument is ignored and used for recording
.\"	the version when the .VS was added, so that the sidebars can be
.\"	found and removed when they reach a certain age.  If another argument
.\"	is present, then a line break is forced before starting the sidebar.
.\"
.\" .VE
.\"	End of vertical sidebar.
.\"
.\" .DS
.\"	Begin an indented unfilled display.
.\"
.\" .DE
.\"	End of indented unfilled display.
.\"
.\" .SO ?manpage?
.\"	Start of list of standard options for a Tk widget. The manpage
.\"	argument defines where to look up the standard options; if
.\"	omitted, defaults to "options". The options follow on successive
.\"	lines, in three columns separated by tabs.
.\"
.\" .SE
.\"	End of list of standard options for a Tk widget.
.\"
.\" .OP cmdName dbName dbClass
.\"	Start of description of a specific option.  cmdName gives the
.\"	option's name as specified in the class command, dbName gives
.\"	the option's name in the option database, and dbClass gives
.\"	the option's class in the option database.
.\"
.\" .UL arg1 arg2
.\"	Print arg1 underlined, then print arg2 normally.
.\"
.\" .QW arg1 ?arg2?
.\"	Print arg1 in quotes, then arg2 normally (for trailing punctuation).
.\"
.\" .PQ arg1 ?arg2?
.\"	Print an open parenthesis, arg1 in quotes, then arg2 normally
.\"	(for trailing punctuation) and then a closing parenthesis.
.\"
.\"	# Set up traps and other miscellaneous stuff for Tcl/Tk man pages.
.if t .wh -1.3i ^B
.nr ^l \n(.l
.ad b
.\"	# Start an argument description
.de AP
.ie !"\\$4"" .TP \\$4
.el \{\
.   ie !"\\$2"" .TP \\n()Cu
.   el          .TP 15
.\}
.ta \\n()Au \\n()Bu
.ie !"\\$3"" \{\
\&\\$1 \\fI\\$2\\fP (\\$3)
.\".b
.\}
.el \{\
.br
.ie !"\\$2"" \{\
\&\\$1	\\fI\\$2\\fP
.\}
.el \{\
\&\\fI\\$1\\fP
.\}
.\}
..
.\"	# define tabbing values for .AP
.de AS
.nr )A 10n
.if !"\\$1"" .nr )A \\w'\\$1'u+3n
.nr )B \\n()Au+15n
.\"
.if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n
.nr )C \\n()Bu+\\w'(in/out)'u+2n
..
.AS Tcl_Interp Tcl_CreateInterp in/out
.\"	# BS - start boxed text
.\"	# ^y = starting y location
.\"	# ^b = 1
.de BS
.br
.mk ^y
.nr ^b 1u
.if n .nf
.if n .ti 0
.if n \l'\\n(.lu\(ul'
.if n .fi
..
.\"	# BE - end boxed text (draw box now)
.de BE
.nf
.ti 0
.mk ^t
.ie n \l'\\n(^lu\(ul'
.el \{\
.\"	Draw four-sided box normally, but don't draw top of
.\"	box if the box started on an earlier page.
.ie !\\n(^b-1 \{\
\h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
.\}
.el \}\
\h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
.\}
.\}
.fi
.br
.nr ^b 0
..
.\"	# VS - start vertical sidebar
.\"	# ^Y = starting y location
.\"	# ^v = 1 (for troff;  for nroff this doesn't matter)
.de VS
.if !"\\$2"" .br
.mk ^Y
.ie n 'mc \s12\(br\s0
.el .nr ^v 1u
..
.\"	# VE - end of vertical sidebar
.de VE
.ie n 'mc
.el \{\
.ev 2
.nf
.ti 0
.mk ^t
\h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n'
.sp -1
.fi
.ev
.\}
.nr ^v 0
..
.\"	# Special macro to handle page bottom:  finish off current
.\"	# box/sidebar if in box/sidebar mode, then invoked standard
.\"	# page bottom macro.
.de ^B
.ev 2
'ti 0
'nf
.mk ^t
.if \\n(^b \{\
.\"	Draw three-sided box if this is the box's first page,
.\"	draw two sides but no top otherwise.
.ie !\\n(^b-1 \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
.el \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
.\}
.if \\n(^v \{\
.nr ^x \\n(^tu+1v-\\n(^Yu
\kx\h'-\\nxu'\h'|\\n(^lu+3n'\ky\L'-\\n(^xu'\v'\\n(^xu'\h'|0u'\c
.\}
.bp
'fi
.ev
.if \\n(^b \{\
.mk ^y
.nr ^b 2
.\}
.if \\n(^v \{\
.mk ^Y
.\}
..
.\"	# DS - begin display
.de DS
.RS
.nf
.sp
..
.\"	# DE - end display
.de DE
.fi
.RE
.sp
..
.\"	# SO - start of list of standard options
.de SO
'ie '\\$1'' .ds So \\fBoptions\\fR
'el .ds So \\fB\\$1\\fR
.SH "STANDARD OPTIONS"
.LP
.nf
.ta 5.5c 11c
.ft B
..
.\"	# SE - end of list of standard options
.de SE
.fi
.ft R
.LP
See the \\*(So manual entry for details on the standard options.
..
.\"	# OP - start of full description for a single option
.de OP
.LP
.nf
.ta 4c
Command-Line Name:	\\fB\\$1\\fR
Database Name:	\\fB\\$2\\fR
Database Class:	\\fB\\$3\\fR
.fi
.IP
..
.\"	# CS - begin code excerpt
.de CS
.RS
.nf
.ta .25i .5i .75i 1i
..
.\"	# CE - end code excerpt
.de CE
.fi
.RE
..
.\"	# UL - underline word
.de UL
\\$1\l'|0\(ul'\\$2
..
.\"	# QW - apply quotation marks to word
.de QW
.ie '\\*(lq'"' ``\\$1''\\$2
.\"" fix emacs highlighting
.el \\*(lq\\$1\\*(rq\\$2
..
.\"	# PQ - apply parens and quotation marks to word
.de PQ
.ie '\\*(lq'"' (``\\$1''\\$2)\\$3
.\"" fix emacs highlighting
.el (\\*(lq\\$1\\*(rq\\$2)\\$3
..
.\"	# QR - quoted range
.de QR
.ie '\\*(lq'"' ``\\$1''\\-``\\$2''\\$3
.\"" fix emacs highlighting
.el \\*(lq\\$1\\*(rq\\-\\*(lq\\$2\\*(rq\\$3
..
.\"	# MT - "empty" string
.de MT
.QW ""
..
Changes to doc/menu.n.
15
16
17
18
19
20
21
22

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43







44
45
46
47
48
49
50
51
52
53
54
55
56
57

58
59
60
61
62
63
64
15
16
17
18
19
20
21

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36







37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

57
58
59
60
61
62
63
64







-
+














-
-
-
-
-
-
-
+
+
+
+
+
+
+













-
+







.nf
\fBmenu\fR \fIpathName \fR?\fIoptions\fR?
\fBtk_menuSetFocus\fR \fIpathName\fR
.SO
\-activebackground	\-borderwidth	\-foreground
\-activeborderwidth	\-cursor	\-relief
\-activeforeground	\-disabledforeground	\-takefocus
\-background	\-font
\-background	\-font	\-activerelief
.SE
.SH "WIDGET-SPECIFIC OPTIONS"
.OP \-postcommand postCommand Command
If this option is specified then it provides a Tcl command to execute
each time the menu is posted.  The command is invoked by the \fBpost\fR
widget command before posting the menu. Note that in Tk 8.0 on Macintosh
and Windows, all post-commands in a system of menus are executed before any
of those menus are posted.
This is due to the limitations in the individual platforms' menu managers.
.OP \-selectcolor selectColor Background
For menu entries that are check buttons or radio buttons, this option
specifies the color to display in the indicator when the check button
or radio button is selected.
.OP \-tearoff tearOff TearOff
This option must have a proper boolean value, 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 must have a proper boolean value (default is false),
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/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
by the name of the menu window, followed by a space, followed by
the name of the name of the torn off menu window.  For example, if
the option's value is
.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
was invoked.
.OP \-type type Type
263
264
265
266
267
268
269
270

271
272
273
274
275
276
277
263
264
265
266
267
268
269

270
271
272
273
274
275
276
277







-
+







contents are inserted into the standard Window menu of the user's
menubar whenever the window's menubar is in front. The first items in
the menu are provided by Mac OS X, and the names of the current
toplevels are automatically appended after all the Tk-defined items and
a separator. The Window menu on the Mac also allows toggling the
window into a fullscreen state, and managing a tabbed window interface
(multiple windows grouped into a single window) if supported by that
version of the operating system. 
version of the operating system.
.PP
When Tk sees a .menubar.help menu on the Macintosh, the menu's contents
are appended to the standard Help menu of the user's menubar whenever
the window's menubar is in front. The first items in the menu
are provided by Mac OS X.
.PP
When Tk sees a System menu on Windows, its items are appended to the
299
300
301
302
303
304
305
306

307
308
309
310
311
312
313
299
300
301
302
303
304
305

306
307
308
309
310
311
312
313







-
+







.SH "WIDGET COMMAND"
.PP
The \fBmenu\fR command creates a new Tcl command whose
name is \fIpathName\fR.  This
command may be used to invoke various
operations on the widget.  It has the following general form:
.CS
\fIpathName option \fR?\fIarg arg ...\fR?
\fIpathName option \fR?\fIarg ...\fR?
.CE
\fIOption\fR and the \fIarg\fRs
determine the exact behavior of the command.
.PP
Many of the widget commands for a menu take as one argument an
indicator of which entry of the menu to operate on. These
indicators are called \fIindex\fRes and may be specified in
519
520
521
522
523
524
525
526
527


528
529
530
531
532
533
534
535
536
537

538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554

555

556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576

577
578
579
580
581
582
583
519
520
521
522
523
524
525


526
527
528
529
530
531
532
533
534
535
536

537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555

556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576

577
578
579
580
581
582
583
584







-
-
+
+









-
+

















+
-
+




















-
+







.SH "MENU ENTRY OPTIONS"
The following options are allowed on menu entries. Most options are not
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
.
Specifies a string to display at the right side of the menu entry.
Normally describes an accelerator keystroke sequence that may be
used to invoke the same function as the menu entry. This is a display
option, it does not actually set the corresponding binding (which can
be achieved using the \fBbind\fR command). This option is not available
for separator or tear-off entries.
.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).
This option is ignored on Aqua/macOS.
If this option is specified as an empty string (the default), then the
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
.
Specifies a bitmap to display in the menu instead of a textual
label, in any of the forms accepted by \fBTk_GetBitmap\fR.
This option overrides the \fB\-label\fR option
(as controlled by the \fB\-compound\fR option)
but may be reset
to an empty string to enable a textual label to be displayed.
If a \fB\-image\fR option has been specified, it overrides
\fB\-bitmap\fR.
This option is not available for separator or tear-off entries.
.TP
\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.
Not available for separator or tear-off entries.
.TP
599
600
601
602
603
604
605

606

607
608
609
610
611
612
613
600
601
602
603
604
605
606
607

608
609
610
611
612
613
614
615







+
-
+







the \fB\-font\fR option for the overall menu is used.
This option is not available for separator or tear-off entries.
.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).
This option is ignored on Aqua/macOS.
If this option is specified as an empty string (the default), then the
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
.
Specifies whether the standard margins should be drawn for this menu
entry. This is useful when creating palette with images in them, i.e.,
Changes to doc/menubar.n.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15
16
17

18
19
20
21
22
23
24
1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16

17
18
19
20
21
22
23
24






-
+









-
+







'\"
'\" Copyright (c) 1992 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH tk_menuBar n "" Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
tk_menuBar, tk_bindForTraversal \- Obsolete support for menu bars
.SH SYNOPSIS
\fBtk_menuBar \fIframe \fR?\fImenu menu ...\fR?
.sp
\fBtk_bindForTraversal \fIarg arg ... \fR
\fBtk_bindForTraversal \fIarg ... \fR
.BE
.SH DESCRIPTION
.PP
These procedures were used in Tk 3.6 and earlier releases to help
manage pulldown menus and to implement keyboard traversal of menus.
In Tk 4.0 and later releases they are no
longer needed.  Stubs for these procedures have been retained for
Changes to doc/menubutton.n.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1990-1994 The Regents of the University of California.
'\" Copyright (c) 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.
'\" 
'\"
.TH menubutton n 4.0 Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
menubutton \- Create and manipulate 'menubutton' pop-up menu indicator widgets
.SH SYNOPSIS
113
114
115
116
117
118
119
120

121
122
123
124
125
126
127
113
114
115
116
117
118
119

120
121
122
123
124
125
126
127







-
+







.SH "WIDGET COMMAND"
.PP
The \fBmenubutton\fR command creates a new Tcl command whose
name is \fIpathName\fR.  This
command may be used to invoke various
operations on the widget.  It has the following general form:
.CS
\fIpathName option \fR?\fIarg arg ...\fR?
\fIpathName option \fR?\fIarg ...\fR?
.CE
\fIOption\fR and the \fIarg\fRs
determine the exact behavior of the command.  The following
commands are possible for menubutton widgets:
.TP
\fIpathName \fBcget \fIoption\fR
.
Changes to doc/message.n.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1990-1994 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH message n 4.0 Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
message \- Create and manipulate 'message' non-interactive text widgets
.SH SYNOPSIS
102
103
104
105
106
107
108
109

110
111
112
113
114
115
116
102
103
104
105
106
107
108

109
110
111
112
113
114
115
116







-
+







.SH "WIDGET COMMAND"
.PP
The \fBmessage\fR command creates a new Tcl command whose
name is \fIpathName\fR.  This
command may be used to invoke various
operations on the widget.  It has the following general form:
.CS
\fIpathName option \fR?\fIarg arg ...\fR?
\fIpathName option \fR?\fIarg ...\fR?
.CE
\fIOption\fR and the \fIarg\fRs
determine the exact behavior of the command.  The following
commands are possible for message widgets:
.TP
\fIpathName \fBcget \fIoption\fR
.
Changes to doc/option.n.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1990 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH option n "" Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
option \- Add/retrieve window options to/from the option database
.SH SYNOPSIS
Changes to doc/optionMenu.n.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1990-1994 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH tk_optionMenu n 4.0 Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
tk_optionMenu \- Create an option menubutton and its menu
.SH SYNOPSIS
Changes to doc/options.n.
54
55
56
57
58
59
60



61
62
63
64
65
66
67
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70







+
+
+







definition of active elements.
The value may have any of the forms acceptable to \fBTk_GetPixels\fR.
This option is typically only available in widgets displaying more
than one element at a time (e.g. menus but not buttons).
.OP \-activeforeground activeForeground Background
Specifies foreground color to use when drawing active elements.
See above for definition of active elements.
.OP \-activerelief activeRelief Relief
Specifies the 3-D effect desired for the active item of the widget.
See the \fB-relief\fR option for details.
.OP \-anchor anchor Anchor
Specifies how the information in a widget (e.g. text or a bitmap)
is to be displayed in the widget.
Must be one of the values \fBn\fR, \fBne\fR, \fBe\fR, \fBse\fR,
\fBs\fR, \fBsw\fR, \fBw\fR, \fBnw\fR, or \fBcenter\fR.
For example, \fBnw\fR means display the information such that its
top-left corner is at the top-left corner of the widget.
217
218
219
220
221
222
223







224
225
226
227
228
229
230
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240







+
+
+
+
+
+
+







this amount to the height it would normally need (as determined by
the height of the things displayed in the widget);  if the geometry
manager can satisfy this request, the widget will end up with extra
internal space above and/or below what it displays inside.
Most widgets only use this option for padding text:  if they are
displaying a bitmap or image, then they usually ignore padding
options.
.OP \-placeholder placeHolder PlaceHolder
Specifies a help text string to display if no text is otherwise displayed,
that is when the widget is empty. The placeholder text is displayed using
the values of the \fB\-font\fR and \fB\-justify\fR options.
.OP \-placeholderforeground placeholderForeground PlaceholderForeground
Specifies the foreground color to use when the placeholder text is
displayed. The default color is platform-specific.
.OP \-relief relief Relief
Specifies the 3-D effect desired for the widget.  Acceptable
values are \fBraised\fR, \fBsunken\fR, \fBflat\fR, \fBridge\fR,
\fBsolid\fR, and \fBgroove\fR.
The value
indicates how the interior of the widget should appear relative
to its exterior;  for example, \fBraised\fR means the interior of
Changes to doc/pack-old.n.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1990-1994 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH pack-old n 4.0 Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
pack-old \- Obsolete syntax for packer geometry manager
.SH SYNOPSIS
Changes to doc/pack.n.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

26
27
28
29
30
31
32


33
34

35
36
37
38
39
40
41
42
43


44
45
46
47

48
49
50
51
52
53
54


55
56
57
58


59
60
61
62
63
64
65


66
67
68
69
70

71
72
73
74

75
76
77
78

79
80
81
82

83
84
85
86
87



88
89
90
91

92
93
94
95
96
97

98
99
100
101
102

103
104
105
106
107
108

109
110
111
112
113

114
115
116
117
118

119
120
121

122
123

124
125
126
127
128
129
130
131












132
133

134
135

136
137
138
139


140
141

142
143

144
145
146

147
148
149
150

151
152
153
154
155



156
157





158
159
160
161


162
163

164
165

166
167
168

169
170
171
172
173




174
175

176
177
178


179
180
181

182
183
184

185
186
187
188
189


190
191

192
193
194

195
196
197

198
199
200
201
202



203
204
205

206
207

208
209
210
211



212
213

214
215

216
217

218
219
220
221
222



223
224
225

226
227

228
229
230
231
232



233
234
235
236
237

238
239
240

241
242

243
244
245


246
247
248


249
250
251
252
253
254
255
256






257
258
259

260
261
262
263
264
265
266
1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

25
26
27
28
29
30


31
32
33

34
35
36
37
38
39
40
41


42
43
44
45
46

47
48
49
50
51
52


53
54
55
56


57
58
59
60
61
62
63


64
65
66
67
68
69

70
71
72
73

74
75
76
77

78
79
80
81

82
83
84



85
86
87
88
89
90

91
92
93
94
95
96

97
98
99
100
101

102
103
104
105
106
107

108
109
110
111
112

113
114
115
116
117

118
119
120

121
122

123
124
125
126
127




128
129
130
131
132
133
134
135
136
137
138
139
140

141
142

143
144
145


146
147
148

149
150

151
152
153

154
155
156
157

158
159
160



161
162
163
164

165
166
167
168
169
170
171


172
173
174

175
176

177
178
179

180
181




182
183
184
185
186

187
188


189
190
191
192

193
194
195

196
197
198
199


200
201
202

203
204
205

206
207
208

209
210
211



212
213
214
215
216

217
218

219
220



221
222
223
224

225
226

227
228

229
230
231



232
233
234
235
236

237
238

239
240
241



242
243
244
245
246
247
248

249
250
251

252
253

254
255


256
257
258


259
260
261
262






263
264
265
266
267
268
269
270

271
272
273
274
275
276
277
278






-
+

















-
+





-
-
+
+

-
+







-
-
+
+



-
+





-
-
+
+


-
-
+
+





-
-
+
+




-
+



-
+



-
+



-
+


-
-
-
+
+
+



-
+





-
+




-
+





-
+




-
+




-
+


-
+

-
+




-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+

-
+

-
+


-
-
+
+

-
+

-
+


-
+



-
+


-
-
-
+
+
+

-
+
+
+
+
+


-
-
+
+

-
+

-
+


-
+

-
-
-
-
+
+
+
+

-
+

-
-
+
+


-
+


-
+



-
-
+
+

-
+


-
+


-
+


-
-
-
+
+
+


-
+

-
+

-
-
-
+
+
+

-
+

-
+

-
+


-
-
-
+
+
+


-
+

-
+


-
-
-
+
+
+




-
+


-
+

-
+

-
-
+
+

-
-
+
+


-
-
-
-
-
-
+
+
+
+
+
+


-
+







'\"
'\" Copyright (c) 1990-1994 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH pack n 4.0 Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
pack \- Geometry manager that packs around edges of cavity
.SH SYNOPSIS
\fBpack \fIoption arg \fR?\fIarg ...\fR?
.BE
.SH DESCRIPTION
.PP
The \fBpack\fR command is used to communicate with the packer,
a geometry manager that arranges the children of a parent by
packing them in order around the edges of the parent.
The \fBpack\fR command can have any of several forms, depending
on the \fIoption\fR argument:
.TP
\fBpack \fIslave \fR?\fIslave ...\fR? ?\fIoptions\fR?
\fBpack \fIwindow \fR?\fIwindow ...\fR? ?\fIoptions\fR?
If the first argument to \fBpack\fR is a window name (any value
starting with
.QW . ),
then the command is processed in the same way as \fBpack configure\fR.
.TP
\fBpack configure \fIslave \fR?\fIslave ...\fR? ?\fIoptions\fR?
The arguments consist of the names of one or more slave windows
\fBpack configure \fIwindow \fR?\fIwindow ...\fR? ?\fIoptions\fR?
The arguments consist of the names of one or more content windows
followed by pairs of arguments that specify how
to manage the slaves.
to manage the content.
See \fBTHE PACKER ALGORITHM\fR below for details on how the options
are used by the packer.
The following options are supported:
.RS
.TP
\fB\-after \fIother\fR
\fIOther\fR must the name of another window.
Use its master as the master for the slaves, and insert
the slaves just after \fIother\fR in the packing order.
Use its container as the container for the content, and insert
the content just after \fIother\fR in the packing order.
.TP
\fB\-anchor \fIanchor\fR
\fIAnchor\fR must be a valid anchor position such as \fBn\fR
or \fBsw\fR; it specifies where to position each slave in its
or \fBsw\fR; it specifies where to position each content in its
parcel.
Defaults to \fBcenter\fR.
.TP
\fB\-before \fIother\fR
\fIOther\fR must the name of another window.
Use its master as the master for the slaves, and insert
the slaves just before \fIother\fR in the packing order.
Use its container as the container for the content, and insert
the content just before \fIother\fR in the packing order.
.TP
\fB\-expand \fIboolean\fR
Specifies whether the slaves should be expanded to consume
extra space in their master.
Specifies whether the content should be expanded to consume
extra space in their container.
\fIBoolean\fR may have any proper boolean value, such as \fB1\fR
or \fBno\fR.
Defaults to 0.
.TP
\fB\-fill \fIstyle\fR
If a slave's parcel is larger than its requested dimensions, this
option may be used to stretch the slave.
If a content's parcel is larger than its requested dimensions, this
option may be used to stretch the content.
\fIStyle\fR must have one of the following values:
.RS
.TP
\fBnone\fR
Give the slave its requested dimensions plus any internal padding
Give the content its requested dimensions plus any internal padding
requested with \fB\-ipadx\fR or \fB\-ipady\fR.  This is the default.
.TP
\fBx\fR
Stretch the slave horizontally to fill the entire width of its
Stretch the content horizontally to fill the entire width of its
parcel (except leave external padding as specified by \fB\-padx\fR).
.TP
\fBy\fR
Stretch the slave vertically to fill the entire height of its
Stretch the content vertically to fill the entire height of its
parcel (except leave external padding as specified by \fB\-pady\fR).
.TP
\fBboth\fR
Stretch the slave both horizontally and vertically.
Stretch the content both horizontally and vertically.
.RE
.TP
\fB\-in \fIother\fR
Insert the slave(s) at the end of the packing order for the master
window given by \fIother\fR.
\fB\-in \fIcontainer\fR
Insert the window at the end of the packing order for the container
window given by \fIcontainer\fR.
.TP
\fB\-ipadx \fIamount\fR
\fIAmount\fR specifies how much horizontal internal padding to
leave on each side of the slave(s).
leave on each side of the content.
\fIAmount\fR must be a valid screen distance, such as \fB2\fR or \fB.5c\fR.
It defaults to 0.
.TP
\fB\-ipady \fIamount\fR
\fIAmount\fR specifies how much vertical internal padding to
leave on each side of the slave(s).
leave on each side of the content.
\fIAmount\fR  defaults to 0.
.TP
\fB\-padx \fIamount\fR
\fIAmount\fR specifies how much horizontal external padding to
leave on each side of the slave(s).  \fIAmount\fR may be a list
leave on each side of the content.  \fIAmount\fR may be a list
of two values to specify padding for left and right separately.
\fIAmount\fR defaults to 0.
.TP
\fB\-pady \fIamount\fR
\fIAmount\fR specifies how much vertical external padding to
leave on each side of the slave(s).  \fIAmount\fR may be a list
leave on each side of the content.  \fIAmount\fR may be a list
of two values to specify padding for top and bottom separately.
\fIAmount\fR defaults to 0.
.TP
\fB\-side \fIside\fR
Specifies which side of the master the slave(s) will be packed against.
Specifies which side of the container the content will be packed against.
Must be \fBleft\fR, \fBright\fR, \fBtop\fR, or \fBbottom\fR.
Defaults to \fBtop\fR.
.LP
If no \fB\-in\fR, \fB\-after\fR or \fB\-before\fR option is specified
then each of the slaves will be inserted at the end of the packing list
then each of the content will be inserted at the end of the packing list
for its parent unless it is already managed by the packer (in which
case it will be left where it is).
If one of these options is specified then all the slaves will be
If one of these options is specified then all the content will be
inserted at the specified point.
If any of the slaves are already managed by the geometry manager
If any of the content are already managed by the geometry manager
then any unspecified options for them retain their previous values rather
than receiving default values.
.RE
.TP
\fBpack forget \fIslave \fR?\fIslave ...\fR?
Removes each of the \fIslave\fRs from the packing order for its
master and unmaps their windows.
The slaves will no longer be managed by the packer.
\fBpack forget \fIwindow \fR?\fIwindow ...\fR?
Removes each of the \fIwindow\fRs from the packing order for its
container and unmaps their windows.
The content will no longer be managed by the packer.
.RS
.PP
.VS "TIP 518"
If the last content window of the container becomes unmanaged, this will also send
the virtual event \fB<<NoManagedChild>>\fR to the container; the container
may choose to resize itself (or otherwise respond) to such a change.
.VE "TIP 518"
.RE
.TP
\fBpack info \fIslave\fR
\fBpack info \fIwindow\fR
Returns a list whose elements are the current configuration state of
the slave given by \fIslave\fR in the same option-value form that
the window given by \fIwindow\fR in the same option-value form that
might be specified to \fBpack configure\fR.
The first two elements of the list are
.QW "\fB\-in \fImaster\fR"
where \fImaster\fR is the slave's master.
.QW "\fB\-in \fIcontainer\fR"
where \fIcontainer\fR is the window's container.
.TP
\fBpack propagate \fImaster\fR ?\fIboolean\fR?
\fBpack propagate \fIcontainer\fR ?\fIboolean\fR?
If \fIboolean\fR has a true boolean value such as \fB1\fR or \fBon\fR
then propagation is enabled for \fImaster\fR, which must be a window
then propagation is enabled for \fIcontainer\fR, which must be a window
name (see \fBGEOMETRY PROPAGATION\fR below).
If \fIboolean\fR has a false boolean value then propagation is
disabled for \fImaster\fR.
disabled for \fIcontainer\fR.
In either of these cases an empty string is returned.
If \fIboolean\fR is omitted then the command returns \fB0\fR or
\fB1\fR to indicate whether propagation is currently enabled
for \fImaster\fR.
for \fIcontainer\fR.
Propagation is enabled by default.
.TP
\fBpack slaves \fImaster\fR
Returns a list of all of the slaves in the packing order for \fImaster\fR.
The order of the slaves in the list is the same as their order in
\fBpack content \fIwindow\fR
Returns a list of all of the content windows in the packing order for \fIwindow\fR.
The order of the content windows in the list is the same as their order in
the packing order.
If \fImaster\fR has no slaves then an empty string is returned.
If \fIwindow\fR has no content then an empty string is returned.
.TP
\fBpack slaves \fIwindow\fR
.
Synonym for . \fBpack content \fIwindow\fR
.SH "THE PACKER ALGORITHM"
.PP
For each master the packer maintains an ordered list of slaves
called the \fIpacking list\fR.
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
options are used to specify the master for each slave and the slave's
options are used to specify the container for each content and the content's
position in the packing list.
If none of these options is given for a slave then the slave
If none of these options is given for a content then the content
is added to the end of the packing list for its parent.
.PP
The packer arranges the slaves for a master by scanning the
The packer arranges the content windows for a container by scanning the
packing list in order.
At the time it processes each slave, a rectangular area within
the master is still unallocated.
This area is called the \fIcavity\fR;  for the first slave it
is the entire area of the master.
At the time it processes each content, a rectangular area within
the container is still unallocated.
This area is called the \fIcavity\fR;  for the first content it
is the entire area of the container.
.PP
For each slave the packer carries out the following steps:
For each content the packer carries out the following steps:
.IP [1]
The packer allocates a rectangular \fIparcel\fR for the slave
along the side of the cavity given by the slave's \fB\-side\fR option.
The packer allocates a rectangular \fIparcel\fR for the content
along the side of the cavity given by the content's \fB\-side\fR option.
If the side is top or bottom then the width of the parcel is
the width of the cavity and its height is the requested height
of the slave plus the \fB\-ipady\fR and \fB\-pady\fR options.
of the content plus the \fB\-ipady\fR and \fB\-pady\fR options.
For the left or right side the height of the parcel is
the height of the cavity and the width is the requested width
of the slave plus the \fB\-ipadx\fR and \fB\-padx\fR options.
of the content plus the \fB\-ipadx\fR and \fB\-padx\fR options.
The parcel may be enlarged further because of the \fB\-expand\fR
option (see \fBEXPANSION\fR below)
.IP [2]
The packer chooses the dimensions of the slave.
The width will normally be the slave's requested width plus
The packer chooses the dimensions of the content.
The width will normally be the content's requested width plus
twice its \fB\-ipadx\fR option and the height will normally be
the slave's requested height plus twice its \fB\-ipady\fR
the content's requested height plus twice its \fB\-ipady\fR
option.
However, if the \fB\-fill\fR option is \fBx\fR or \fBboth\fR
then the width of the slave is expanded to fill the width of the parcel,
then the width of the content is expanded to fill the width of the parcel,
minus twice the \fB\-padx\fR option.
If the \fB\-fill\fR option is \fBy\fR or \fBboth\fR
then the height of the slave is expanded to fill the width of the parcel,
then the height of the content is expanded to fill the width of the parcel,
minus twice the \fB\-pady\fR option.
.IP [3]
The packer positions the slave over its parcel.
If the slave is smaller than the parcel then the \fB\-anchor\fR
option determines where in the parcel the slave will be placed.
The packer positions the content over its parcel.
If the content is smaller than the parcel then the \fB\-anchor\fR
option determines where in the parcel the content will be placed.
If \fB\-padx\fR or \fB\-pady\fR is non-zero, then the given
amount of external padding will always be left between the
slave and the edges of the parcel.
content and the edges of the parcel.
.PP
Once a given slave has been packed, the area of its parcel
Once a given content has been packed, the area of its parcel
is subtracted from the cavity, leaving a smaller rectangular
cavity for the next slave.
If a slave does not use all of its parcel, the unused space
in the parcel will not be used by subsequent slaves.
cavity for the next content.
If a content does not use all of its parcel, the unused space
in the parcel will not be used by subsequent content.
If the cavity should become too small to meet the needs of
a slave then the slave will be given whatever space is
a content then the content will be given whatever space is
left in the cavity.
If the cavity shrinks to zero size, then all remaining slaves
If the cavity shrinks to zero size, then all remaining content
on the packing list will be unmapped from the screen until
the master window becomes large enough to hold them again.
the container window becomes large enough to hold them again.
.SS "EXPANSION"
.PP
If a master window is so large that there will be extra space
left over after all of its slaves have been packed, then the
extra space is distributed uniformly among all of the slaves
If a container window is so large that there will be extra space
left over after all of its content have been packed, then the
extra space is distributed uniformly among all of the content
for which the \fB\-expand\fR option is set.
Extra horizontal space is distributed among the expandable
slaves whose \fB\-side\fR is \fBleft\fR or \fBright\fR,
content whose \fB\-side\fR is \fBleft\fR or \fBright\fR,
and extra vertical space is distributed among the expandable
slaves whose \fB\-side\fR is \fBtop\fR or \fBbottom\fR.
content whose \fB\-side\fR is \fBtop\fR or \fBbottom\fR.
.SS "GEOMETRY PROPAGATION"
.PP
The packer normally computes how large a master must be to
just exactly meet the needs of its slaves, and it sets the
requested width and height of the master to these dimensions.
The packer normally computes how large a container must be to
just exactly meet the needs of its content, and it sets the
requested width and height of the container to these dimensions.
This causes geometry information to propagate up through a
window hierarchy to a top-level window so that the entire
sub-tree sizes itself to fit the needs of the leaf windows.
However, the \fBpack propagate\fR command may be used to
turn off propagation for one or more masters.
turn off propagation for one or more containers.
If propagation is disabled then the packer will not set
the requested width and height of the packer.
This may be useful if, for example, you wish for a master
This may be useful if, for example, you wish for a container
window to have a fixed size that you specify.
.SH "RESTRICTIONS ON MASTER WINDOWS"
.SH "RESTRICTIONS ON CONTAINER WINDOWS"
.PP
The master for each slave must either be the slave's parent
(the default) or a descendant of the slave's parent.
The container for each content must either be the content's parent
(the default) or a descendant of the content's parent.
This restriction is necessary to guarantee that the
slave can be placed over any part of its master that is
visible without danger of the slave being clipped by its parent.
content can be placed over any part of its container that is
visible without danger of the content being clipped by its parent.
.SH "PACKING ORDER"
.PP
If the master for a slave is not its parent then you must make sure
that the slave is higher in the stacking order than the master.
Otherwise the master will obscure the slave and it will appear as
if the slave has not been packed correctly.
The easiest way to make sure the slave is higher than the master is
to create the master window first:  the most recently created window
If the container for a content is not its parent then you must make sure
that the content is higher in the stacking order than the container.
Otherwise the container will obscure the content and it will appear as
if the content has not been packed correctly.
The easiest way to make sure the content is higher than the container is
to create the container window first:  the most recently created window
will be highest in the stacking order.
Or, you can use the \fBraise\fR and \fBlower\fR commands to change
the stacking order of either the master or the slave.
the stacking order of either the container or the content.
.SH EXAMPLE
.PP
.CS
# Make the widgets
label .t \-text "This widget is at the top"    \-bg red
label .b \-text "This widget is at the bottom" \-bg green
label .l \-text "Left\enHand\enSide"
Changes to doc/palette.n.
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







'\"
'\" Copyright (c) 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.
'\" 
'\"
.TH tk_setPalette n 4.0 Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
tk_setPalette, tk_bisque \- Modify the Tk color palette
.SH SYNOPSIS
Changes to doc/panedwindow.n.
88
89
90
91
92
93
94
95

96
97
98
99
100
101
102
88
89
90
91
92
93
94

95
96
97
98
99
100
101
102







-
+







.SH "WIDGET COMMAND"
.PP
The \fBpanedwindow\fR command creates a new Tcl command whose name is
the same as the path name of the panedwindow's window.  This command
may be used to invoke various operations on the widget.  It has the
following general form:
.CS
\fIpathName option \fR?\fIarg arg ...\fR?
\fIpathName option \fR?\fIarg ...\fR?
.CE
\fIPathName\fR is the name of the command, which is the same as
the panedwindow widget's path name.  \fIOption\fR and the \fIarg\fRs
determine the exact behavior of the command.  The following
commands are possible for panedwindow widgets:
.TP
\fIpathName \fBadd \fIwindow \fR?\fIwindow ...\fR? ?\fIoption value ...\fR?
326
327
328
329
330
331
332
333

334
335
336
337
338
339
340
326
327
328
329
330
331
332

333
334
335
336
337
338
339
340







-
+







on each side of the sash, and thus the widgets in those panes, are
adjusted.
.PP
When a pane is resized from outside (e.g. it is packed to expand and
fill, and the containing toplevel is resized), space is added to the final
(rightmost or bottommost) pane in the window.
.PP
Unlike slave windows managed by e.g. pack or grid, the panes managed by a
Unlike child windows managed by e.g. pack or grid, the panes managed by a
panedwindow do not change width or height to accommodate changes in the
requested widths or heights of the panes, once these have become mapped.
Therefore it may be advisable, particularly when creating layouts
interactively, to not add a pane to the panedwindow widget until after the
geometry requests of that pane has been finalized (i.e., all components of
the pane inserted, all options affecting geometry set to their proper
values, etc.).
Changes to doc/photo.n.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

28
29
30
31

32
33
34
35
36
37
38
39
40
41
42






43
44
45
46
47
48
49
50
51






52
53
54
55
56
57
58
59
60
61






62
63
64
65
66
67




68
69

70
71
72




73
74
75
76
77
78
79
1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

27
28
29
30

31
32
33
34
35
36






37
38
39
40
41
42
43
44
45






46
47
48
49
50
51
52
53
54
55
56
57
58
59


60
61
62
63
64
65
66





67
68
69
70
71

72
73
74

75
76
77
78
79
80
81
82
83
84
85






-
+



















-
+



-
+





-
-
-
-
-
-
+
+
+
+
+
+



-
-
-
-
-
-
+
+
+
+
+
+








-
-
+
+
+
+
+
+

-
-
-
-
-
+
+
+
+

-
+


-
+
+
+
+







'\"
'\" Copyright (c) 1994 The Australian National University
'\" Copyright (c) 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 ([email protected]),
'\"	    Department of Computer Science,
'\"	    Australian National University.
'\"
.TH photo n 4.0 Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
photo \- Full-color images
.SH SYNOPSIS
.nf
\fBimage create photo \fR?\fIname\fR? ?\fIoptions\fR?

\fIimageName \fBblank\fR
\fIimageName \fBcget \fIoption\fR
\fIimageName \fBconfigure\fR ?\fIoption\fR? ?\fIvalue option value ...\fR?
\fIimageName \fBcopy \fIsourceImage\fR ?\fIoption value(s) ...\fR?
\fIimageName \fBdata\fR ?\fIoption value(s) ...\fR?
\fIimageName \fBget \fIx y\fR
\fIimageName \fBget \fIx y\fR ?\fIoption\fR?
\fIimageName \fBput \fIdata\fR ?\fIoption value(s) ...\fR?
\fIimageName \fBread \fIfilename\fR ?\fIoption value(s) ...\fR?
\fIimageName \fBredither\fR
\fIimageName \fBtransparency \fIsubcommand \fR?\fIarg arg ...\fR?
\fIimageName \fBtransparency \fIsubcommand \fR?\fIarg ...\fR?
\fIimageName \fBwrite \fIfilename\fR ?\fIoption value(s) ...\fR?
.fi
.BE
.SH DESCRIPTION
.PP
A photo is an image whose pixels can display any color or be
transparent.  A photo image is stored internally in full color (32
bits per pixel), and is displayed using dithering if necessary.  Image
data for a photo image can be obtained from a file or a string, or it
can be supplied from
C code through a procedural interface.  At present, only
A photo is an image whose pixels can display any color with a varying
degree of transparency (the alpha channel). A photo image is stored
internally in full color (32 bits per pixel), and is displayed using
dithering if necessary.  Image data for a photo image can be obtained
from a file or a string, or it can be supplied from C code through a
procedural interface.  At present, only
.VS 8.6
PNG,
.VE 8.6
GIF and PPM/PGM
formats are supported, but an interface exists to allow additional
image file formats to be added easily.  A photo image is transparent
in regions where no image data has been supplied
or where it has been set transparent by the \fBtransparency set\fR
subcommand.
GIF and PPM/PGM formats are supported, but an interface exists to
allow additional image file formats to be added easily.  A photo image
is (semi)transparent if the image data it was obtained from had
transparency informaton. In regions where no image data has been
supplied, it is fully transparent. Transparency may also be modified
with the \fBtransparency set\fR subcommand.
.SH "CREATING PHOTOS"
.PP
Like all images, photos are created using the \fBimage create\fR
command.
Photos support the following \fIoptions\fR:
.TP
\fB\-data \fIstring\fR
.
Specifies the contents of the image as a string.  The string should
contain binary data or, for some formats, base64-encoded data (this is
Specifies the contents of the image as a string.
.VS 8.7
The string should
contain data in the default list-of-lists form,
.VE 8.7
binary data or, for some formats, base64-encoded data (this is
currently guaranteed to be supported for PNG and GIF images). The
format of the
string must be one of those for which there is an image file format
handler that will accept string data.  If both the \fB\-data\fR
and \fB\-file\fR options are specified, the \fB\-file\fR option takes
precedence.
format of the string must be one of those for which there is an image
file format handler that will accept string data.  If both the
\fB\-data\fR and \fB\-file\fR options are specified, the \fB\-file\fR
option takes precedence.
.TP
\fB\-format \fIformat-name\fR
\fB\-format\fR {\fIformat-name\fR ?\fIoption value ...\fR?}
.
Specifies the name of the file format for the data specified with the
\fB\-data\fR or \fB\-file\fR option.
\fB\-data\fR or \fB\-file\fR option and optional arguments passed to
the format handler. 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.
.TP
\fB\-file \fIname\fR
.
\fIname\fR gives the name of a file that is to be read to supply data
for the photo image.  The file format must be one of those for which
there is an image file format handler that can read data.
.TP
118
119
120
121
122
123
124
125

126
127
128
129
130
131
132
124
125
126
127
128
129
130

131
132
133
134
135
136
137
138







-
+







.PP
When a photo image is created, Tk also creates a new command
whose name is the same as the image.
This command may be used to invoke various operations
on the image.
It has the following general form:
.CS
\fIimageName option \fR?\fIarg arg ...\fR?
\fIimageName option \fR?\fIarg ...\fR?
.CE
\fIOption\fR and the \fIarg\fRs
determine the exact behavior of the command.
.PP
Those options that write data to the image generally expand the size
of the image, if necessary, to accommodate the data written to the
image, unless the user has specified non-zero values for the
229
230
231
232
233
234
235
236
237








238
239
240
241
242
243
244
245
246

247
248
249
250
251
252
253
254
255









256
257

258




259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274

275
276

277
278
279
280





281
282
283
284

285

286
287
288

289
290

291
292
293
294

295
296
297

298
299


300
301
302



303
304
305
306
307
308
309
310


311

312
313
314
315
316
317
318
319
320
321
322
323
324
325
326

327
328


329
330
331



332
333
334
335
336
337
338
235
236
237
238
239
240
241


242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257

258
259








260
261
262
263
264
265
266
267
268
269

270

271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292

293
294
295
296

297
298
299
300
301
302
303
304
305
306

307
308
309

310


311




312
313
314

315
316

317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334

335
336
337
338
339
340
341
342
343
344
345
346
347
348
349

350
351

352
353
354
355
356
357
358
359
360
361
362
363
364
365
366







-
-
+
+
+
+
+
+
+
+








-
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+

-
+
-
+
+
+
+
















+

-
+



-
+
+
+
+
+




+
-
+


-
+
-
-
+
-
-
-
-
+


-
+

-
+
+



+
+
+








+
+
-
+














-
+

-
+
+



+
+
+







is set, the old contents of the destination image are discarded and
the source image is used as-is.  The default compositing rule is
\fIoverlay\fR.
.RE
.TP
\fIimageName \fBdata\fR ?\fIoption value(s) ...\fR?
.
Returns image data in the form of a string. The following options
may be specified:
Returns image data in the form of a string.
.VS 8.7
The format of the string depends on the format handler. By default, a
human readable format as a list of lists of pixel data is used, other
formats can be chosen with the \fB-format\fR option.
See \fBIMAGE FORMATS\fR below for details.
.VE 8.7
The following options may be specified:
.RS
.TP
\fB\-background\fI color\fR
.
If the color is specified, the data will not contain any transparency
information. In all transparent pixels the color will be replaced by
the specified color.
.TP
\fB\-format\fI format-name\fR
\fB\-format\fR {\fIformat-name\fR ?\fIoption value ...\fR?}
.
Specifies the name of the image file format handler to be used.
Specifically, this subcommand searches
for the first handler whose name matches an initial substring of
\fIformat-name\fR and which has the capability to write a string
containing this image data.
If this option is not given, this subcommand uses a format that
consists of a list (one element per row) of lists (one element per
pixel/column) of colors in
Specifies the name of the image file format handler to use and,
optionally, arguments to the format handler.  Specifically, this
subcommand searches for the first handler whose name matches an
initial substring of \fIformat-name\fR and which has the capability to
write a string containing this image data.
.VS 8.7
If this option is not given, this subcommand uses the default format
that consists of a list (one element per row) of lists (one element
per pixel/column) of colors in
.QW \fB#\fIrrggbb\fR
format (where \fIrr\fR is a pair of hexadecimal digits for the red
format (see \fBIMAGE FORMATS\fR below).
channel, \fIgg\fR for green, and \fIbb\fR for blue).
.VE 8.7
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.
.TP
\fB\-from \fIx1 y1 x2 y2\fR
.
Specifies a rectangular region of \fIimageName\fR to be returned.
If only \fIx1\fR and \fIy1\fR are specified, the region
extends from \fI(x1,y1)\fR to the bottom-right corner of
\fIimageName\fR.  If all four coordinates are given, they specify
diagonally opposite corners of the rectangular region, including x1,y1
and excluding x2,y2.  The default, if this option is not given, is the
whole image.
.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
\fIimageName \fBget\fR \fIx y\fR
\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.
red, green and blue components respectively. If the \fB-withalpha\fR
option is specified, the returned list will have a fourth element
representing the alpha value of the pixel as an integer between 0 and
255.
.VE 8.7
.TP
\fIimageName \fBput\fR \fIdata\fR ?\fIoption value(s) ...\fR?
.
Sets pixels in \fI imageName\fR to the data specified in \fIdata\fR.
.VS 8.7
This command first searches the list of image file format handlers for
This command searches the list of image file format handlers for
a handler that can interpret the data in \fIdata\fR, and then reads
the image encoded within into \fIimageName\fR (the destination image).
If \fIdata\fR does not match any known format, an attempt to interpret
See \fBIMAGE FORMATS\fR below for details on formats for image data.
it as a (top-to-bottom) list of scan-lines is made, with each
scan-line being a (left-to-right) list of pixel colors (see
.VE 8.7
\fBTk_GetColor\fR for a description of valid colors.)  Every scan-line
must be of the same length.  Note that when \fIdata\fR is a single
color name, you are instructing Tk to fill a rectangular region with
that color.  The following options may be specified:
The following options may be specified:
.RS
.TP
\fB\-format \fIformat-name\fR
\fB\-format\fR {\fIformat-name\fR ?\fIoption value ..\fR?}
.
Specifies the format of the image data in \fIdata\fR.
Specifies the format of the image data in \fIdata\fR and, optionally,
arguments to be passed to the format handler.
Specifically, only image file format handlers whose names begin with
\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.
.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
copied.  The default position is (0,0).  If \fIx2\fR,\fIy2\fR is given
and \fIdata\fR is not large enough to cover the rectangle specified by
this option, the image data extracted will be tiled so it covers the
entire destination rectangle. If the region specified with this opion
is smaller than the supplied \fIdata\fR, the exceeding data is silently
entire destination rectangle.  Note that if \fIdata\fR specifies a
discarded. Note that if \fIdata\fR specifies a
single color value, then a region extending to the bottom-right corner
represented by (\fIx2\fR,\fIy2\fR) will be filled with that color.
.RE
.TP
\fIimageName \fBread\fR \fIfilename\fR ?\fIoption value(s) ...\fR?
.
Reads image data from the file named \fIfilename\fR into the image.
This command first searches the list of
image file format handlers for a handler that can interpret the data
in \fIfilename\fR, and then reads the image in \fIfilename\fR into
\fIimageName\fR (the destination image).  The following options may be
specified:
.RS
.TP
\fB\-format \fIformat-name\fR
\fB\-format {\fIformat-name\fR ?\fIoption value ..\fR?}
.
Specifies the format of the image data in \fIfilename\fR.
Specifies the format of the image data in \fIfilename\fR and,
optionally, additional options to the format handler.
Specifically, only image file format handlers whose names begin with
\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.
.TP
\fB\-from \fIx1 y1 x2 y2\fR
.
Specifies a rectangular sub-region of the image file data to be copied
to the destination image.  If only \fIx1\fR and \fIy1\fR are
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
362
363
364
365
366
367
368
369

370
371
372
373

374
375

376
377
378






379
380

381
382
383







384
385
386
387
388
389
390
391
392
393
394
395
396
397
398

399
400

401
402
403
404
405
406









407
408
409
410
411
412
413
390
391
392
393
394
395
396

397
398
399
400
401
402
403

404
405


406
407
408
409
410
411
412

413
414


415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435

436
437
438
439






440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455







-
+




+

-
+

-
-
+
+
+
+
+
+

-
+

-
-
+
+
+
+
+
+
+














-
+


+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+







quantization errors from one pixel to its neighbors.
If the image data for \fIimageName\fR is supplied in pieces, the
dithered image may not be exactly correct.  Normally the difference is
not noticeable, but if it is a problem, this command can be used to
recalculate the dithered image in each window where the image is
displayed.
.TP
\fIimageName \fBtransparency \fIsubcommand \fR?\fIarg arg ...\fR?
\fIimageName \fBtransparency \fIsubcommand \fR?\fIarg ...\fR?
.
Allows examination and manipulation of the transparency information in
the photo image.  Several subcommands are available:
.RS
.VS 8.7
.TP
\fIimageName \fBtransparency get \fIx y\fR
\fIimageName \fBtransparency get \fIx y\fR ?\fB-alpha\fR?
.
Returns a boolean indicating if the pixel at (\fIx\fR,\fIy\fR) is
transparent.
Returns true if the pixel at (\fIx\fR,\fIy\fR) is fully transparent,
false otherwise.  If the option \fB-alpha\fR is passed, returns the
alpha value of the pixel instead, as an integer in the range 0 to 255.
.VE 8.7

.VS 8.7
.TP
\fIimageName \fBtransparency set \fIx y boolean\fR
\fIimageName \fBtransparency set \fIx y\fR \fInewVal\fR ?\fB-alpha\fR?
.
Makes the pixel at (\fIx\fR,\fIy\fR) transparent if \fIboolean\fR is
true, and makes that pixel opaque otherwise.
Change the transparency of the pixel at (\fIx\fR,\fIy\fR) to
\fInewVal.\fR If no additional option is passed, \fInewVal\fR is
interpreted as a boolean and the pixel is made fully transparent if
that value is true, fully opaque otherwise.  If the \fB-alpha\fR
option is passed, \fInewVal\fR is interpreted as an integral alpha
value for the pixel, which must be in the range 0 to 255.
.VE 8.7
.RE
.TP
\fIimageName \fBwrite \fIfilename\fR ?\fIoption value(s) ...\fR?
.
Writes image data from \fIimageName\fR to a file named \fIfilename\fR.
The following options may be specified:
.RS
.TP
\fB\-background\fI color\fR
.
If the color is specified, the data will not contain any transparency
information. In all transparent pixels the color will be replaced by
the specified color.
.TP
\fB\-format\fI format-name\fR
\fB\-format\fR {\fIformat-name\fR ?\fIoption value ...\fR?}
.
Specifies the name of the image file format handler to be used to
write the data to the file and, optionally, options to pass to the
write the data to the file.  Specifically, this subcommand searches
for the first handler whose name matches an initial substring of
\fIformat-name\fR and which has the capability to write an image
file.  If this option is not given, the format is guessed from
the file extension. If that cannot be determined, this subcommand
uses the first handler that has the capability to write an image file.
format handler.  Specifically, this subcommand searches for the first
handler whose name matches an initial substring of \fIformat-name\fR
and which has the capability to write an image file.  If this option
is not given, the format is guessed from the file extension. If that
cannot be determined, this subcommand uses the first handler that has
the capability to write an image file.
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.
.TP
\fB\-from \fIx1 y1 x2 y2\fR
.
Specifies a rectangular region of \fIimageName\fR to be written to the
image file.  If only \fIx1\fR and \fIy1\fR are specified, the region
extends from \fI(x1,y1)\fR to the bottom-right corner of
\fIimageName\fR.  If all four coordinates are given, they specify
422
423
424
425
426
427
428





429

430
431
432
433
434
435
436
437







438
439
440
441
442




443
444
445
446
447
448
449
450
451
452


















453
454
455
456
457
458


















459
460
461

462
463
464
465




466
467
468

469
470
471
472


























































473















































474
475
476
477
478
479
480
464
465
466
467
468
469
470
471
472
473
474
475

476
477







478
479
480
481
482
483
484





485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519



520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541




542
543
544
545
546
547
548
549




550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662







+
+
+
+
+
-
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+










+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



+
-
-
-
-
+
+
+
+



+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







.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
a list of these handlers.  Handlers are added to the list by
registering them with a call to \fBTk_CreatePhotoImageFormat\fR.  The
standard Tk distribution comes with handlers for PPM/PGM, PNG and GIF
formats,
.VS 8.7
as well as the \fBdefault\fR handler to encode/decode image
data in a human readable form.
.VE 8.7
formats, which are automatically registered on initialization.
These handlers are automatically registered on initialization.
.PP
When reading an image file or processing
string data specified with the \fB\-data\fR configuration option, the
photo image code invokes each handler in turn until one is
found that claims to be able to read the data in the file or string.
Usually this will find the correct handler, but if it does not, the
user may give a format name with the \fB\-format\fR option to specify
which handler to use.  In fact the photo image code will try those
When reading an image file or processing string data specified with
the \fB\-data\fR configuration option, the photo image code invokes
each handler in turn until one is found that claims to be able to read
the data in the file or string.  Usually this will find the correct
handler, but if it does not, the user may give a format name with the
\fB\-format\fR option to specify which handler to use.  In this case,
the photo image code will try those handlers whose names begin with
handlers whose names begin with the string specified for the
\fB\-format\fR option (the comparison is case-insensitive).  For
example, if the user specifies \fB\-format gif\fR, then a handler
named GIF87 or GIF89 may be invoked, but a handler
named JPEG may not (assuming that such handlers had been
the string specified for the \fB\-format\fR option (the comparison is
case-insensitive).  For example, if the user specifies \fB\-format
gif\fR, then a handler named GIF87 or GIF89 may be invoked, but a
handler named JPEG may not (assuming that such handlers had been
registered).
.PP
When writing image data to a file, the processing of the
\fB\-format\fR option is slightly different: the string value given
for the \fB\-format\fR option must begin with the complete name of the
requested handler, and may contain additional information following
that, which the handler can use, for example, to specify which variant
to use of the formats supported by the handler.
Note that not all image handlers may support writing transparency data
to a file, even where the target image format does.
.VS 8.7
.SS "THE DEFAULT IMAGE HANDLER"
.PP
The \fBdefault\fR image handler cannot be used to read or write data
from/to a file. Its sole purpose is to encode and decode image data in
string form in a clear text, human readable, form. The \fIimageName\fR
\fBdata\fR subcommand uses this handler when no other format is
specified. When reading image data from a string with \fIimageName\fR
\fBput\fR or the \fB-data\fR option, the default handler is treated
as the other handlers.
.PP
Image data in the \fBdefault\fR string format is a (top-to-bottom)
list of scan-lines, with each scan-line being a (left-to-right) list
of pixel data. Every scan-line has the same length. The color
and, optionally, alpha value of each pixel is specified in any of
the forms described in the \fBCOLOR FORMATS\fR section below.
.VE 8.7

.SS "FORMAT SUBOPTIONS"
.PP
.VS 8.6
Some image formats support sub-options, which are specified at the time that
the image is loaded using additional words in the \fB\-format\fR option. At
the time of writing, the following are supported:
Image formats may support sub-options, wich ahre specified using
additional words in the value to the \fB\-format\fR option. These
suboptions can affect how image data is read or written to file or
string. The nature and values of these options is up to the format
handler.
The built-in handlers support these suboptions:
.VS 8.7
.TP
\fBdefault \-colorformat\fI formatType\fR
.
The option is allowed when writing image data to a string with
\fIimageName\fR \fBdata\fR. Specifies the format to use for the color
string of each pixel. \fIformatType\fR may be one of: \fBrgb\fR to
encode pixel data in the form \fB#\fIRRGGBB\fR, \fBrgba\fR to encode
pixel data in the form \fB#\fIRRGGBBAA\fR or \fBlist\fR to encode
pixel data as a list with four elements. See \fBCOLOR FORMATS\fR
below for details. The default is \fBrgb\fR.
.VE 8.7
.TP
\fBgif \-index\fI indexValue\fR
.
The option has effect when reading image data from a file. When
When parsing a multi-part GIF image, Tk normally only accesses the first
image. By giving the \fB\-index\fR sub-option, the \fIindexValue\fR'th value
may be used instead. The \fIindexValue\fR must be an integer from 0 up to the
number of image parts in the GIF data.
parsing a multi-part GIF image, Tk normally only accesses the first
image. By giving the \fB\-index\fR sub-option, the \fIindexValue\fR'th
value may be used instead. The \fIindexValue\fR must be an integer
from 0 up to the number of image parts in the GIF data.
.TP
\fBpng \-alpha\fI alphaValue\fR
.
The option has effect when reading image data from a file. Specifies
An additional alpha filtering for the overall image, which allows the
background on which the image is displayed to show through. This usually also
has the effect of desaturating the image. The \fIalphaValue\fR must be between
0.0 and 1.0.
an additional alpha filtering for the overall image, which allows the
background on which the image is displayed to show through.  This
usually also has the effect of desaturating the image.  The
\fIalphaValue\fR must be between 0.0 and 1.0.
.TP
\fBsvg \-dpi\fI dpiValue\fB \-scale\fI scaleValue\fB \-scaletowidth \fI width\fB \-scaletoheight\fI height\fR
.
\fIdpiValue\fR is used in conversion between given coordinates and
screen resolution. The value must be greater than 0 and the default
value is 96.
\fIscaleValue\fR is used to scale the resulting image. The value must
be greater than 0 and the default value is 1.
\fIwidth\fR and \fIheight\fR are the width or height that the image
will be adjusted to. Only one parameter among \fB\-scale\fR,
\fB\-scaletowidth\fR and \fB\-scaletoheight\fR can be given at a time
and the aspect ratio of the original image is always preserved.
The svg format supports a wide range of SVG features, but the
full SVG standard is not available, for instance the 'text' feature
is missing and silently ignored when reading the SVG data.
The supported SVG features are:
.
.RS
\fB elements:\fR g, path, rect, circle, ellipse, line, polyline, polygon,
linearGradient, radialGradient, stop, defs, svg, style
.PP
\fB attributes:\fR width, height, viewBox,
preserveAspectRatio with none, xMin, xMid, xMax, yMin, yMid, yMax, slice
.PP
\fB gradient attributes:\fR gradientUnits with objectBoundingBox,
gradientTransform, cx, cy, r fx, fy x1, y1, x2, y2
spreadMethod with pad, reflect or repeat,
xlink:href
.PP
\fB poly attributes: \fR points
.PP
\fB line attributes: \fR x1, y1, x2, y2
.PP
\fB ellipse attributes: \fR cx, cy, rx, ry
.PP
\fB circle attributes: \fR cx, cy, r
.PP
\fB rectangle attributes: \fR x, y, width, height, rx, ry
.PP
\fB path attributes: \fR d with m, M, l, L, h, H, v, V, c, C, s, S, q, Q, t, T, a, A, z, Z
.PP
\fB style attributes: \fR display with none, visibility, hidden, visible,
fill with nonzero and evenodd, opacity, fill-opacity,
stroke, stroke-width, stroke-dasharray, stroke-dashoffset, stroke-opacity,
stroke-linecap with butt, round and square,
stroke-linejoin with miter, round and  bevel, stroke-miterlimit
fill-rule, font-size,
transform with matrix, translate, scale, rotate, skewX and  skewY,
stop-color, stop-opacity, offset, id, class
.RE
.
Currently only SVG images reading and conversion into (pixel-based
format) photos is supported: Tk does not (yet) support bundling photo
images in SVG vector graphics.
.VE 8.6
.VS 8.7
.SH "COLOR FORMATS"
.PP
The default image handler can represent/parse color and alpha values
of a pixel in one of the formats listed below. If a color format does
not contain transparency information, full opacity is assumed.  The
available color formats are:
.IP \(bu 3
The empty string - interpreted as full transparency, the color value
is undefined.
.IP \(bu 3
Any value accepted by \fBTk_GetColor\fR, optionally followed by an
alpha suffix. The alpha suffix may be one of:
.RS
.TP
\fB@\fR\fIA\fR
.
The alpha value \fIA\fR must be a fractional value in the range  0.0
(fully transparent) to 1.0 (fully opaque).
.TP
\fB#\fR\fIX\fR
.
The alpha value \fIX\fR is a hexadecimal digit that specifies an integer
alpha value in the range 0 (fully transparent) to 255 (fully opaque).
This is expanded in range from 4 bits wide to 8 bits wide by
multiplication by 0x11.
.TP
\fB#\fR\fIXX\fR
.
The alpha value \fIXX\fR is passed as two hexadecimal digits that
specify an integer alpha value in the range 0 (fully transparent) to 255
(fully opaque).
.RE
.IP \(bu 3
A Tcl list with three or four integers in the range 0 to 255,
specifying the values for the red, green, blue and (optionally)
alpha channels respectively.
.IP \(bu 3
\fB#\fR\fIRGBA\fR format: a \fB#\fR followed by four hexadecimal digits,
where each digit is the value for the red, green, blue and alpha
channels respectively. Each digit will be expanded internally to
8 bits by multiplication by 0x11.
.IP \(bu 3
\fB#\fR\fIRRGGBBAA\fR format: \fB#\fR followed by eight hexadecimal digits,
where each pair of  subsequent digits represents the value for the red,
green, blue and alpha channels respectively.
.VE 8.7
.SH "COLOR ALLOCATION"
.PP
When a photo image is displayed in a window, the photo image code
allocates colors to use to display the image and dithers the image, if
necessary, to display a reasonable approximation to the image using
the colors that are available.  The colors are allocated as a color
cube, that is, the number of colors allocated is the product of the
530
531
532
533
534
535
536

















537
538
539
540
541
542
543
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







.CS
\fBimage create photo\fR icon \-file "icon.png"
\fBimage create photo\fR iconDisabled \-file "icon.png" \e
        \-format "png \-alpha 0.5"
button .b \-image icon \-disabledimage iconDisabled
.CE
.VE 8.6
.PP
.VS 8.7
Create a green box with a simple shadow effect
.PP
.CS
\fBimage create photo\fR foo

# Make a simple graduated fill varying in alpha for the shadow
for {set i 14} {$i > 0} {incr i -1} {
   set i2 [expr {$i + 30}]
   foo \fBput\fR [format black#%x [expr {15-$i}]] -to $i $i $i2 $i2
}

# Put a solid green rectangle on top
foo \fBput\fR #F080 -to 0 0 30 30
.VE 8.7
.CE
.SH "SEE ALSO"
image(n)
.SH KEYWORDS
photo, image, color
'\" Local Variables:
'\" mode: nroff
'\" End:
Changes to doc/place.n.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22


23
24
25
26



27
28
29


30
31
32
33

34
35
36
37
38
39
40

41
42
43
44
45
46
47
1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16
17
18
19
20


21
22
23



24
25
26
27


28
29
30
31
32

33
34
35
36
37
38
39

40
41
42
43
44
45
46
47






-
+













-
-
+
+

-
-
-
+
+
+

-
-
+
+



-
+






-
+







'\"
'\" Copyright (c) 1992 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH place n "" Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
place \- Geometry manager for fixed or rubber-sheet placement
.SH SYNOPSIS
\fBplace \fIoption arg \fR?\fIarg ...\fR?
.BE
.SH DESCRIPTION
.PP
The placer is a geometry manager for Tk.
It provides simple fixed placement of windows, where you specify
the exact size and location of one window, called the \fIslave\fR,
within another window, called the \fImaster\fR.
the exact size and location of one window, called the \fIcontent\fR,
within another window, called the \fIcontainer\fR.
The placer also provides rubber-sheet placement, where you specify the
size and location of the slave in terms of the dimensions of
the master, so that the slave changes size and location
in response to changes in the size of the master.
size and location of the content in terms of the dimensions of
the container, so that the content changes size and location
in response to changes in the size of the container.
Lastly, the placer allows you to mix these styles of placement so
that, for example, the slave has a fixed width and height but is
centered inside the master.
that, for example, the content has a fixed width and height but is
centered inside the container.
.PP
.TP
\fBplace \fIwindow option value \fR?\fIoption value ...\fR?
Arrange for the placer to manage the geometry of a slave whose
Arrange for the placer to manage the geometry of a content whose
pathName is \fIwindow\fR.  The remaining arguments consist of one or
more \fIoption\-value\fR pairs that specify the way in which
\fIwindow\fR's geometry is managed.  \fIOption\fR may have any of the
values accepted by the \fBplace configure\fR command.
.TP
\fBplace configure \fIwindow \fR?\fIoption\fR? ?\fIvalue option value ...\fR?
Query or modify the geometry options of the slave given by
Query or modify the geometry options of the content given by
\fIwindow\fR.  If no \fIoption\fR is specified, this command returns a
list describing the available options (see \fBTk_ConfigureInfo\fR for
information on the format of this list).  If \fIoption\fR is specified
with no \fIvalue\fR, then the command returns a list describing the
one named option (this list will be identical to the corresponding
sublist of the value returned if no \fIoption\fR is specified).  If
one or more \fIoption\-value\fR pairs are specified, then the command
55
56
57
58
59
60
61
62

63
64
65
66
67

68
69
70


71
72
73

74
75
76
77
78

79
80

81
82

83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98


99
100

101
102

103
104
105
106


107
108
109
110
111
112
113
114
115




116
117

118
119
120
121
122
123
124
125




126
127

128
129
130

131
132
133
134

135
136

137
138
139


140
141
142

143
144
145
146

147
148

149
150
151


152
153
154
155
156
157
158
159
160
161
162
163

164
165
166
167

168
169
170

171
172
173
174

175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196







197
198
199
200
201
202
203
204
205
206


207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224

225
226
227
228
229
230
231
232

233
234
235
236
237

238
239
240
241
242
243
244
245
246
247
248
249
250
251
252

253
254
255
55
56
57
58
59
60
61

62
63
64
65
66

67
68


69
70
71
72

73
74
75
76
77

78
79

80
81

82
83
84
85
86
87
88
89
90
91
92
93
94
95
96


97
98
99

100
101

102
103
104


105
106
107
108
109
110
111




112
113
114
115
116

117
118
119
120
121




122
123
124
125
126

127
128
129

130
131
132
133

134
135

136
137


138
139
140
141

142
143
144
145

146
147

148
149


150
151
152
153
154
155
156
157
158
159
160
161
162

163
164
165
166

167
168
169

170
171
172
173

174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193



194
195
196
197
198
199
200
201
202
203
204
205
206
207
208


209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227

228
229
230
231
232
233
234
235

236
237
238
239
240

241
242
243
244
245
246
247
248
249
250
251
252
253
254
255

256
257
258
259







-
+




-
+

-
-
+
+


-
+




-
+

-
+

-
+














-
-
+
+

-
+

-
+


-
-
+
+





-
-
-
-
+
+
+
+

-
+




-
-
-
-
+
+
+
+

-
+


-
+



-
+

-
+

-
-
+
+


-
+



-
+

-
+

-
-
+
+











-
+



-
+


-
+



-
+



















-
-
-
+
+
+
+
+
+
+








-
-
+
+

















-
+







-
+




-
+














-
+



\fIWhere\fR specifies which point of \fIwindow\fR is to be positioned
at the (x,y) location selected by the \fB\-x\fR, \fB\-y\fR,
\fB\-relx\fR, and \fB\-rely\fR options.
The anchor point is in terms of the outer area of \fIwindow\fR
including its border, if any.
Thus if \fIwhere\fR is \fBse\fR then the lower-right corner of
\fIwindow\fR's border will appear at the given (x,y) location
in the master.
in the container.
The anchor position defaults to \fBnw\fR.
.TP
\fB\-bordermode \fImode\fR
\fIMode\fR determines the degree to which borders within the
master are used in determining the placement of the slave.
container are used in determining the placement of the content.
The default and most common value is \fBinside\fR.
In this case the placer considers the area of the master to
be the innermost area of the master, inside any border:
In this case the placer considers the area of the container to
be the innermost area of the container, inside any border:
an option of \fB\-x 0\fR corresponds to an x-coordinate just
inside the border and an option of \fB\-relwidth 1.0\fR
means \fIwindow\fR will fill the area inside the master's
means \fIwindow\fR will fill the area inside the container's
border.
.RS
.PP
If \fImode\fR is \fBoutside\fR then the placer considers
the area of the master to include its border;
the area of the container to include its border;
this mode is typically used when placing \fIwindow\fR
outside its master, as with the options \fB\-x 0 \-y 0 \-anchor ne\fR.
outside its container, as with the options \fB\-x 0 \-y 0 \-anchor ne\fR.
Lastly, \fImode\fR may be specified as \fBignore\fR, in which
case borders are ignored:  the area of the master is considered
case borders are ignored:  the area of the container is considered
to be its official X area, which includes any internal border but
no external border.  A bordermode of \fBignore\fR is probably
not very useful.
.RE
.TP
\fB\-height \fIsize\fR
\fISize\fR specifies the height for \fIwindow\fR in screen units
(i.e. any of the forms accepted by \fBTk_GetPixels\fR).
The height will be the outer dimension of \fIwindow\fR including its
border, if any.
If \fIsize\fR is an empty string, or if no \fB\-height\fR or
\fB\-relheight\fR option is specified, then the height requested
internally by the window will be used.
.TP
\fB\-in \fImaster\fR
\fIMaster\fR specifies the path name of the window relative
\fB\-in \fIcontainer\fR
\fIContainer\fR specifies the path name of the window relative
to which \fIwindow\fR is to be placed.
\fIMaster\fR must either be \fIwindow\fR's parent or a descendant
\fIContainer\fR must either be \fIwindow\fR's parent or a descendant
of \fIwindow\fR's parent.
In addition, \fImaster\fR and \fIwindow\fR must both be descendants
In addition, \fIcontainer\fR and \fIwindow\fR must both be descendants
of the same top-level window.
These restrictions are necessary to guarantee
that \fIwindow\fR is visible whenever \fImaster\fR is visible.
If this option is not specified then the master defaults to
that \fIwindow\fR is visible whenever \fIcontainer\fR is visible.
If this option is not specified then the other window defaults to
\fIwindow\fR's parent.
.TP
\fB\-relheight \fIsize\fR
\fISize\fR specifies the height for \fIwindow\fR.
In this case the height is specified as a floating-point number
relative to the height of the master: 0.5 means \fIwindow\fR will
be half as high as the master, 1.0 means \fIwindow\fR will have
the same height as the master, and so on.
If both \fB\-height\fR and \fB\-relheight\fR are specified for a slave,
relative to the height of the container: 0.5 means \fIwindow\fR will
be half as high as the container, 1.0 means \fIwindow\fR will have
the same height as the container, and so on.
If both \fB\-height\fR and \fB\-relheight\fR are specified for a content,
their values are summed.  For example, \fB\-relheight 1.0 \-height \-2\fR
makes the slave 2 pixels shorter than the master.
makes the content 2 pixels shorter than the container.
.TP
\fB\-relwidth \fIsize\fR
\fISize\fR specifies the width for \fIwindow\fR.
In this case the width is specified as a floating-point number
relative to the width of the master: 0.5 means \fIwindow\fR will
be half as wide as the master, 1.0 means \fIwindow\fR will have
the same width as the master, and so on.
If both \fB\-width\fR and \fB\-relwidth\fR are specified for a slave,
relative to the width of the container: 0.5 means \fIwindow\fR will
be half as wide as the container, 1.0 means \fIwindow\fR will have
the same width as the container, and so on.
If both \fB\-width\fR and \fB\-relwidth\fR are specified for a content,
their values are summed.  For example, \fB\-relwidth 1.0 \-width 5\fR
makes the slave 5 pixels wider than the master.
makes the content 5 pixels wider than the container.
.TP
\fB\-relx \fIlocation\fR
\fILocation\fR specifies the x-coordinate within the master window
\fILocation\fR specifies the x-coordinate within the container window
of the anchor point for \fIwindow\fR.
In this case the location is specified in a relative fashion
as a floating-point number:  0.0 corresponds to the left edge
of the master and 1.0 corresponds to the right edge of the master.
of the container and 1.0 corresponds to the right edge of the container.
\fILocation\fR need not be in the range 0.0\-1.0.
If both \fB\-x\fR and \fB\-relx\fR are specified for a slave
If both \fB\-x\fR and \fB\-relx\fR are specified for a content
then their values are summed.  For example, \fB\-relx 0.5 \-x \-2\fR
positions the left edge of the slave 2 pixels to the left of the
center of its master.
positions the left edge of the content 2 pixels to the left of the
center of its container.
.TP
\fB\-rely \fIlocation\fR
\fILocation\fR specifies the y-coordinate within the master window
\fILocation\fR specifies the y-coordinate within the container window
of the anchor point for \fIwindow\fR.
In this case the value is specified in a relative fashion
as a floating-point number:  0.0 corresponds to the top edge
of the master and 1.0 corresponds to the bottom edge of the master.
of the container and 1.0 corresponds to the bottom edge of the container.
\fILocation\fR need not be in the range 0.0\-1.0.
If both \fB\-y\fR and \fB\-rely\fR are specified for a slave
If both \fB\-y\fR and \fB\-rely\fR are specified for a content
then their values are summed.  For example, \fB\-rely 0.5 \-x 3\fR
positions the top edge of the slave 3 pixels below the
center of its master.
positions the top edge of the content 3 pixels below the
center of its container.
.TP
\fB\-width \fIsize\fR
\fISize\fR specifies the width for \fIwindow\fR in screen units
(i.e. any of the forms accepted by \fBTk_GetPixels\fR).
The width will be the outer width of \fIwindow\fR including its
border, if any.
If \fIsize\fR is an empty string, or if no \fB\-width\fR
or \fB\-relwidth\fR option is specified, then the width requested
internally by the window will be used.
.TP
\fB\-x \fIlocation\fR
\fILocation\fR specifies the x-coordinate within the master window
\fILocation\fR specifies the x-coordinate within the container window
of the anchor point for \fIwindow\fR.
The location is specified in screen units (i.e. any of the forms
accepted by \fBTk_GetPixels\fR) and need not lie within the bounds
of the master window.
of the container window.
.TP
\fB\-y \fIlocation\fR
\fILocation\fR specifies the y-coordinate within the master window
\fILocation\fR specifies the y-coordinate within the container window
of the anchor point for \fIwindow\fR.
The location is specified in screen units (i.e. any of the forms
accepted by \fBTk_GetPixels\fR) and need not lie within the bounds
of the master window.
of the container window.
.PP
If the same value is specified separately with
two different options, such as \fB\-x\fR and \fB\-relx\fR, then
the most recent option is used and the older one is ignored.
.RE
.TP
\fBplace forget \fIwindow\fR
Causes the placer to stop managing the geometry of \fIwindow\fR.  As a
side effect of this command \fIwindow\fR will be unmapped so that it
does not appear on the screen.  If \fIwindow\fR is not currently managed
by the placer then the command has no effect.  This command returns an
empty string.
.TP
\fBplace info \fIwindow\fR
Returns a list giving the current configuration of \fIwindow\fR.
The list consists of \fIoption\-value\fR pairs in exactly the
same form as might be specified to the \fBplace configure\fR
command.
.TP
\fBplace slaves \fIwindow\fR
Returns a list of all the slave windows for which \fIwindow\fR is the master.
If there are no slaves for \fIwindow\fR then an empty string is returned.
\fBplace content \fIwindow\fR
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
.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
the saved information.
.SH "FINE POINTS"
.PP
It is not necessary for the master window to be the parent
of the slave window.
It is not necessary for the container window to be the parent
of the content window.
This feature is useful in at least two situations.
First, for complex window layouts it means you can create a
hierarchy of subwindows whose only purpose
is to assist in the layout of the parent.
The
.QW "real children"
of the parent (i.e. the windows that
are significant for the application's user interface) can be
children of the parent yet be placed inside the windows
of the geometry-management hierarchy.
This means that the path names of the
.QW "real children"
do not reflect the geometry-management hierarchy and users
can specify options for the real children
without being aware of the structure of the geometry-management
hierarchy.
.PP
A second reason for having a master different than the slave's
A second reason for having a container different than the content's
parent is to tie two siblings together.
For example, the placer can be used to force a window always to
be positioned centered just below one of its
siblings by specifying the configuration
.CS
\fB\-in \fIsibling\fB \-relx 0.5 \-rely 1.0 \-anchor n \-bordermode outside\fR
.CE
Whenever the sibling is repositioned in the future, the slave
Whenever the sibling is repositioned in the future, the content
will be repositioned as well.
.PP
Unlike many other geometry managers (such as the packer)
the placer does not make any attempt to manipulate the geometry of
the master windows or the parents of slave windows (i.e. it does not
the container windows or the parents of content windows (i.e. it does not
set their requested sizes).
To control the sizes of these windows, make them windows like
frames and canvases that provide configuration options for this purpose.
.SH EXAMPLE
.PP
Make the label occupy the middle bit of the toplevel, no matter how it
is resized:
.CS
label .l \-text "In the\enMiddle!" \-bg black \-fg white
\fBplace\fR .l \-relwidth .3 \-relx .35 \-relheight .3 \-rely .35
.CE
.SH "SEE ALSO"
grid(n), pack(n)
.SH KEYWORDS
geometry manager, height, location, master, place, rubber sheet, slave, width
geometry manager, height, location, container, place, rubber sheet, content, width
'\" Local Variables:
'\" mode: nroff
'\" End:
Changes to doc/popup.n.
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







'\"
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH tk_popup n 4.0 Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
tk_popup \- Post a popup menu
.SH SYNOPSIS
34
35
36
37
38
39
40
41

42
43
44
45
46
47
48
49
34
35
36
37
38
39
40

41
42
43
44
45
46
47
48
49







-
+








$m add command \-label "Example 1" \-command bell
$m add command \-label "Example 2" \-command bell

# Create something to attach it to
pack [label .l \-text "Click me!"]

# Arrange for the menu to pop up when the label is clicked
bind .l <1> {\fBtk_popup\fR .popupMenu %X %Y}
bind .l <Button-1> {\fBtk_popup\fR .popupMenu %X %Y}
.CE
.SH "SEE ALSO"
bind(n), menu(n), tk_optionMenu(n)
.SH KEYWORDS
menu, popup
'\" Local Variables:
'\" mode: nroff
'\" End:
Changes to doc/radiobutton.n.
172
173
174
175
176
177
178
179

180
181
182
183
184
185
186
172
173
174
175
176
177
178

179
180
181
182
183
184
185
186







-
+







.SH "WIDGET COMMAND"
.PP
The \fBradiobutton\fR command creates a new Tcl command whose
name is \fIpathName\fR.  This
command may be used to invoke various
operations on the widget.  It has the following general form:
.CS
\fIpathName option \fR?\fIarg arg ...\fR?
\fIpathName option \fR?\fIarg ...\fR?
.CE
\fIOption\fR and the \fIarg\fRs
determine the exact behavior of the command.  The following
commands are possible for radiobutton widgets:
.TP
\fIpathName \fBcget\fR \fIoption\fR
.
Changes to doc/raise.n.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1990 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH raise n 3.3 Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
raise \- Change a window's position in the stacking order
.SH SYNOPSIS
Changes to doc/scale.n.
74
75
76
77
78
79
80
81

82
83
84
85
86
87
88
74
75
76
77
78
79
80

81
82
83
84
85
86
87
88







-
+







If the scale is disabled then the value may not be changed and the scale
will not activate.
If the scale is active, the slider is displayed using the color
specified by the \fB\-activebackground\fR option.
.OP \-tickinterval tickInterval TickInterval
Must be a real value.
Determines the spacing between numerical
tick marks displayed below or to the left of the slider. The values will all be displayed with the same number of decimal places, which will be enough to ensure they are all accurate to within 20% of a tick interval. 
tick marks displayed below or to the left of the slider. The values will all be displayed with the same number of decimal places, which will be enough to ensure they are all accurate to within 20% of a tick interval.
If 0, no tick marks will be displayed.
.OP \-to to To
Specifies a real value corresponding
to the right or bottom end of the scale.
This value may be either less than or greater than the \fB\-from\fR option.
.OP \-variable variable Variable
Specifies the name of a global variable to link to the scale.  Whenever the
134
135
136
137
138
139
140
141

142
143
144
145
146
147
148
134
135
136
137
138
139
140

141
142
143
144
145
146
147
148







-
+







.SH "WIDGET COMMAND"
.PP
The \fBscale\fR command creates a new Tcl command whose
name is \fIpathName\fR.  This
command may be used to invoke various
operations on the widget.  It has the following general form:
.CS
\fIpathName option \fR?\fIarg arg ...\fR?
\fIpathName option \fR?\fIarg ...\fR?
.CE
\fIOption\fR and the \fIarg\fRs
determine the exact behavior of the command.  The following
commands are possible for scale widgets:
.TP
\fIpathName \fBcget\fR \fIoption\fR
.
Changes to doc/scrollbar.n.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1990-1994 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH scrollbar n 4.1 Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
scrollbar \- Create and manipulate 'scrollbar' scrolling control and indicator widgets
.SH SYNOPSIS
99
100
101
102
103
104
105
106

107
108
109
110
111
112
113
99
100
101
102
103
104
105

106
107
108
109
110
111
112
113







-
+







.SH "WIDGET COMMAND"
.PP
The \fBscrollbar\fR command creates a new Tcl command whose
name is \fIpathName\fR.  This
command may be used to invoke various
operations on the widget.  It has the following general form:
.CS
\fIpathName option \fR?\fIarg arg ...\fR?
\fIpathName option \fR?\fIarg ...\fR?
.CE
\fIOption\fR and the \fIarg\fRs
determine the exact behavior of the command.  The following
commands are possible for scrollbar widgets:
.TP
\fIpathName \fBactivate \fR?\fIelement\fR?
.
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235













236
237
238
239
240
241
242
211
212
213
214
215
216
217









218
219
220
221
222
223
224
225

226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245







-
-
-
-
-
-
-
-
-








-
+
+
+
+
+
+
+
+
+
+
+
+
+







The widget should adjust its view so that the point given
by \fIfraction\fR appears at the beginning of the widget.
If \fIfraction\fR is 0 it refers to the beginning of the
document.  1.0 refers to the end of the document, 0.333
refers to a point one-third of the way through the document,
and so on.
.TP
\fIprefix \fBscroll \fInumber \fBunits\fR
.
The widget should adjust its view by \fInumber\fR units.
The units are defined in whatever way makes sense for the widget,
such as characters or lines in a text widget.
\fINumber\fR is either 1, which means one unit should scroll off
the top or left of the window, or \-1, which means that one unit
should scroll off the bottom or right of the window.
.TP
\fIprefix \fBscroll \fInumber \fBpages\fR
.
The widget should adjust its view by \fInumber\fR pages.
It is up to the widget to define the meaning of a page;  typically
it is slightly less than what fits in the window, so that there
is a slight overlap between the old and new views.
\fINumber\fR is either 1, which means the next page should
become visible, or \-1, which means that the previous page should
become visible.
become visible. Fractional number are rounded away from 0, so
scrolling 0.001 pages has the same effect as scrolling 1 page.
.TP
\fIprefix \fBscroll \fInumber \fBunits\fR
.
The widget should adjust its view by \fInumber\fR units.
The units are defined in whatever way makes sense for the widget,
such as characters or lines in a text widget.
\fINumber\fR is either 1, which means one unit should scroll off
the top or left of the window, or \-1, which means that one unit
should scroll off the bottom or right of the window. Fractional
numbers are rounded away from 0, so scrolling 0.001 units has
the same effect as scrolling 1 unit.
.SH "OLD COMMAND SYNTAX"
.PP
In versions of Tk before 4.0, the \fBset\fR and \fBget\fR widget
commands used a different form.
This form is still supported for backward compatibility, but it
is deprecated.
In the old command syntax, the \fBset\fR widget command has the
Changes to doc/selection.n.
8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
8
9
10
11
12
13
14

15
16
17
18
19
20
21
22







-
+







.TH selection n 8.1 Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
selection \- Manipulate the X selection
.SH SYNOPSIS
\fBselection \fIoption\fR ?\fIarg arg ...\fR?
\fBselection \fIoption\fR ?\fIarg ...\fR?
.BE
.SH DESCRIPTION
.PP
This command provides a Tcl interface to the X selection mechanism and
implements the full selection functionality described in the
X Inter-Client Communication Conventions Manual (ICCCM).
.PP
146
147
148
149
150
151
152
153

154
155
156
157
158
159
160
146
147
148
149
150
151
152

153
154
155
156
157
158
159
160







-
+







.PP
A GUI event, for example \fB<<PasteSelection>>\fR, can copy the \fBPRIMARY\fR selection to certain widgets.  This copy is implemented by a widget binding to the event.  The binding script makes appropriate calls to the \fBselection\fR command.
.PP
.SH PORTABILITY ISSUES
.PP
On X11, the \fBPRIMARY\fR selection is a system-wide feature of the X server, allowing communication between different processes that are X11 clients.
.PP
On Windows, the \fBPRIMARY\fR selection is not provided by the system, but only by Tk, and so it is shared only between windows of a master interpreter and its unsafe slave interpreters.  It is not shared between interpreters in different processes or different threads.  Each master interpreter has a separate \fBPRIMARY\fR selection that is shared only with its unsafe slaves.
On Windows, the \fBPRIMARY\fR selection is not provided by the system, but only by Tk, and so it is shared only between windows of a parent interpreter and its child interpreters.  It is not shared between interpreters in different processes or different threads.  Each parent interpreter has a separate \fBPRIMARY\fR selection that is shared only with its child interpreters which are not safe interpreters.
.PP
.SH SECURITY
.PP
A safe interpreter cannot read from the \fBPRIMARY\fR selection because its \fBselection\fR command is hidden.  For this reason the \fBPRIMARY\fR selection cannot be written to the Tk widgets of a safe interpreter.
.PP
A Tk widget can have its option \fB\-exportselection\fR set to boolean \fBtrue\fR, but in a safe interpreter this option has no effect: writing from the widget to the \fBPRIMARY\fR selection is disabled.
.PP
Changes to doc/send.n.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
1
2
3
4
5
6

7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
22






-
+







-
+







'\"
'\" Copyright (c) 1990-1994 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH send n 4.0 Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
send \- Execute a command in a different application
.SH SYNOPSIS
\fBsend ?\fIoptions\fR? \fIapp cmd \fR?\fIarg arg ...\fR?
\fBsend ?\fIoptions\fR? \fIapp cmd \fR?\fIarg ...\fR?
.BE
.SH DESCRIPTION
.PP
This command arranges for \fIcmd\fR (and \fIarg\fRs) to be executed in the
application named by \fIapp\fR.  It returns the result or
error from that command execution.
\fIApp\fR may be the name of any application whose main window is
Changes to doc/spinbox.n.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

26
27
28
29
30
31
32
1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33






-
+


















+







'\"
'\" Copyright (c) 2000 Jeffrey Hobbs.
'\" Copyright (c) 2000 Ajuba Solutions.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\"
.TH spinbox n 8.4 Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
spinbox \- Create and manipulate 'spinbox' value spinner widgets
.SH SYNOPSIS
\fBspinbox\fR \fIpathName \fR?\fIoptions\fR?
.SO
\-activebackground	\-highlightthickness	\-repeatinterval
\-background	\-insertbackground	\-selectbackground
\-borderwidth	\-insertborderwidth	\-selectborderwidth
\-cursor	\-insertontime	\-selectforeground
\-exportselection	\-insertwidth	\-takefocus
\-font	\-insertofftime	\-textvariable
\-foreground	\-justify	\-xscrollcommand
\-highlightbackground	\-relief
\-highlightcolor	\-repeatdelay
\-placeholder	\-placeholderforeground
.SE
.SH "WIDGET-SPECIFIC OPTIONS"
.OP \-buttonbackground buttonBackground Background
The background color to be used for the spin buttons.
.OP \-buttoncursor buttonCursor Cursor
The cursor to be used when over the spin buttons.  If this is empty
(the default), a default cursor will be used.
50
51
52
53
54
55
56
57


58
59
60
61
62
63
64
51
52
53
54
55
56
57

58
59
60
61
62
63
64
65
66







-
+
+







when using the \fB\-from\fR and \fB\-to\fR range.
This must be a format specifier of the form \fB%<pad>.<pad>f\fR,
as it will format a floating-point number.
.OP \-from from From
A floating-point value corresponding to the lowest value for a spinbox, to
be used in conjunction with \fB\-to\fR and \fB\-increment\fR.  When all
are specified correctly, the spinbox will use these values to control its
contents.  This value must be less than the \fB\-to\fR option.
contents. If this value is greater than the \fB\-to\fR option, then
\fB\-from\fR and \fB\-to\fR values are automatically swapped.
If \fB\-values\fR is specified, it supersedes this option.
.OP "\-invalidcommand or \-invcmd" invalidCommand InvalidCommand
Specifies a script to eval when \fB\-validatecommand\fR returns 0.  Setting
it to an empty string disables this feature (the default).  The best use of
this option is to set it to \fIbell\fR.  See \fBVALIDATION\fR below for
more information.
.OP \-increment increment Increment
79
80
81
82
83
84
85
86


87
88
89
90
91
92
93
81
82
83
84
85
86
87

88
89
90
91
92
93
94
95
96







-
+
+







displayed, the contents will not be selectable, and the spinbox may
be displayed in a different color, depending on the values of the
\fB\-disabledforeground\fR and \fB\-disabledbackground\fR options.
.OP \-to to To
A floating-point value corresponding to the highest value for the spinbox,
to be used in conjunction with \fB\-from\fR and \fB\-increment\fR.  When
all are specified correctly, the spinbox will use these values to control
its contents.  This value must be greater than the \fB\-from\fR option.
its contents. If this value is less than the \fB\-from\fR option, then
\fB\-from\fR and \fB\-to\fR values are automatically swapped.
If \fB\-values\fR is specified, it supersedes this option.
.OP \-validate validate Validate
Specifies the mode in which validation should operate: \fBnone\fR,
\fBfocus\fR, \fBfocusin\fR, \fBfocusout\fR, \fBkey\fR, or \fBall\fR.
It defaults to \fBnone\fR.  When you want validation, you must explicitly
state which mode you wish to use.  See \fBVALIDATION\fR below for more.
.OP "\-validatecommand or \-vcmd" validateCommand ValidateCommand
217
218
219
220
221
222
223
224

225
226
227
228
229
230
231
232
233
234
235
236
237
238
239

240
241
242
243
244
245
246
220
221
222
223
224
225
226

227
228
229
230
231
232
233
234
235
236
237
238
239
240
241

242
243
244
245
246
247
248
249







-
+














-
+







associated \fB\-textvariable\fR during validation, as that can cause the
spinbox widget to become out of sync with the \fB\-textvariable\fR.
.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
Moreover, forced validation is performed when invoking any spinbutton of
the spinbox. If the validation script returns false in this situation,
then the \fB-validate\fR option will be automatically set to \fBnone\fR.
.SH "WIDGET COMMAND"
.PP
The \fBspinbox\fR command creates a new Tcl command whose
name is \fIpathName\fR.  This command may be used to invoke various
operations on the widget.  It has the following general form:
.CS
\fIpathName option \fR?\fIarg arg ...\fR?
\fIpathName option \fR?\fIarg ...\fR?
.CE
\fIOption\fR and the \fIarg\fRs
determine the exact behavior of the command.
.SS INDICES
.PP
Many of the widget commands for spinboxes take one or more indices as
arguments.  An index specifies a particular character in the spinbox's
463
464
465
466
467
468
469
470
471



472
473
474
475
476


477
478


479
480
481
482
483
484
485
466
467
468
469
470
471
472


473
474
475
476




477
478
479
480
481
482
483
484
485
486
487
488
489







-
-
+
+
+

-
-
-
-
+
+


+
+







Adjusts the view in the window so that the character \fIfraction\fR of the
way through the text appears at the left edge of the window.
\fIFraction\fR must be a fraction between 0 and 1.
.TP
\fIpathName \fBxview scroll \fInumber what\fR
This command shifts the view in the window left or right according to
\fInumber\fR and \fIwhat\fR.
\fINumber\fR must be an integer.
\fIWhat\fR must be either \fBunits\fR or \fBpages\fR or an abbreviation
\fINumber\fR must be an integer or a float, but if it is a float then
it is converted to an integer, rounded away from 0.
\fIWhat\fR must be either \fBpages\fR or \fBunits\fR or an abbreviation
of one of these.
If \fIwhat\fR is \fBunits\fR, the view adjusts left or right by
\fInumber\fR average-width characters on the display;  if it is
\fBpages\fR then the view adjusts by \fInumber\fR screenfuls.
If \fInumber\fR is negative then characters farther to the left
If \fIwhat\fR is \fBpages\fR then the view adjusts by \fInumber\fR
screenfuls. If \fInumber\fR is negative then characters farther to the left
become visible;  if it is positive then characters farther to the right
become visible.
If \fIwhat\fR is \fBunits\fR, the view adjusts left or right by
\fInumber\fR average-width characters on the display.
.RE
.SH "DEFAULT BINDINGS"
.PP
Tk automatically creates class bindings for spinboxes that give them
the following default behavior.
In the descriptions below,
.QW word
510
511
512
513
514
515
516
517
518
519




520
521
522
523
524
525
526
514
515
516
517
518
519
520



521
522
523
524
525
526
527
528
529
530
531







-
-
-
+
+
+
+







.IP [5]
Clicking mouse button 1 with the Control key down will position the
insertion cursor in the spinbox without affecting the selection.
.IP [6]
If any normal printing characters are typed in a spinbox, they are
inserted at the point of the insertion cursor.
.IP [7]
The view in the spinbox can be adjusted by dragging with mouse button 2.
If mouse button 2 is clicked without moving the mouse, the selection
is copied into the spinbox at the position of the mouse cursor.
The view in the spinbox can be adjusted by dragging with the middle
mouse button (button 2, or button 3 in TkAqua). If the middle mouse
button is clicked without moving the mouse, the selection is copied
into the spinbox at the position of the mouse cursor.
.IP [8]
If the mouse is dragged out of the spinbox on the left or right sides
while button 1 is pressed, the spinbox will automatically scroll to
make more text visible (if there is more text off-screen on the side
where the mouse left the window).
.IP [9]
The Left and Right keys move the insertion cursor one character to the
Added doc/sysnotify.n.





























































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
.\" 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:
.CS
     tk sysnotify "Alert" "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 embeds two separate under-the-hood implementations
using different notification APIs.  The choice of which one to use
depends on which version of the OS is being run and the state of the
Tk application code. The newer API, introduced in macOS 10.14,
requires that the application accessing the API be code-signed, or the
notification will not display.  (A self-signed certificate seems to be
sufficient.) The older API was deprecated but not removed in macOS
11.0. Tk uses the newer API only for signed applications running on
macOS 10.14 or newer.  Otherwise it falls back to the older API.  A
quirk which developers should be aware of is that if an unsigned
version of Wish (or an application derived from it) is installed on
top of a signed version after the signed version has been registered
with System Preferences then neither API will be allowed to show
notifications, making Tk's automatic fallback to the older API
ineffective.  To re-enable notifications the application must be
deleted from Apple's System Preferences Notifications section. (There
is no removal button, so this is done by selecting the application and
pressing the Delete key.)
.
.TP
\fBWindows\fR
.
The image is taken from the systray i.e. a sysnotify can only be
called when a systray was installed.
.
.SH KEYWORDS
notify, alert
Added doc/systray.n.

































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
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 <Button-1> and <Button-3>.
.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
Changes to doc/text.n.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1992 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH text n 8.5 Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note: do not modify the .SH NAME line immediately below!
.SH NAME
text, tk_textCopy, tk_textCut, tk_textPaste \- Create and manipulate 'text' hypertext editing widgets
.SH SYNOPSIS
1048
1049
1050
1051
1052
1053
1054
1055

1056
1057
1058
1059
1060
1061
1062
1048
1049
1050
1051
1052
1053
1054

1055
1056
1057
1058
1059
1060
1061
1062







-
+







.CE
.SH "WIDGET COMMAND"
.PP
The \fBtext\fR command creates a new Tcl command whose name is the same as the
path name of the text's window. This command may be used to invoke various
operations on the widget. It has the following general form:
.CS
\fIpathName option \fR?\fIarg arg ...\fR?
\fIpathName option \fR?\fIarg ...\fR?
.CE
\fIPathName\fR is the name of the command, which is the same as the text
widget's path name. \fIOption\fR and the \fIarg\fRs determine the exact
behavior of the command. The following commands are possible for text widgets:
.TP
\fIpathName \fBbbox \fIindex\fR
.
1078
1079
1080
1081
1082
1083
1084
1085

1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098

1099
1100
1101
1102
1103
1104
1105
1078
1079
1080
1081
1082
1083
1084

1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097

1098
1099
1100
1101
1102
1103
1104
1105







-
+












-
+







Compares the indices given by \fIindex1\fR and \fIindex2\fR according to the
relational operator given by \fIop\fR, and returns 1 if the relationship is
satisfied and 0 if it is not. \fIOp\fR must be one of the operators <, <=, ==,
>=, >, or !=. If \fIop\fR is == then 1 is returned if the two indices refer to
the same character, if \fIop\fR is < then 1 is returned if \fIindex1\fR refers
to an earlier character in the text than \fIindex2\fR, and so on.
.TP
\fIpathName \fBconfigure\fR ?\fIoption\fR? \fI?value option value ...\fR?
\fIpathName \fBconfigure\fR ?\fIoption\fR? ?\fIvalue option value ...\fR?
.
Query or modify the configuration options of the widget. If no \fIoption\fR is
specified, returns a list describing all of the available options for
\fIpathName\fR (see \fBTk_ConfigureInfo\fR for information on the format of
this list). If \fIoption\fR is specified with no \fIvalue\fR, then the command
returns a list describing the one named option (this list will be identical to
the corresponding sublist of the value returned if no \fIoption\fR is
specified). 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. \fIOption\fR may have any of
the values accepted by the \fBtext\fR command.
.TP
\fIpathName \fBcount\fR \fI?options\fR? \fIindex1 index2\fR
\fIpathName \fBcount\fR ?\fIoptions\fR? \fIindex1 index2\fR
.
Counts the number of relevant things between the two indices. If \fIindex1\fR
is after \fIindex2\fR, the result will be a negative number (and this holds
for each of the possible options). The actual items which are counted depend
on the options given. The result is a list of integers, one for the result of
each counting option given. Valid counting options are \fB\-chars\fR,
\fB\-displaychars\fR, \fB\-displayindices\fR, \fB\-displaylines\fR,
1277
1278
1279
1280
1281
1282
1283
1284

1285
1286
1287
1288
1289
1290
1291
1277
1278
1279
1280
1281
1282
1283

1284
1285
1286
1287
1288
1289
1290
1291







-
+







.
Include information about embedded windows in the dump results. The value of a
window is its Tk pathname, unless the window has not been created yet. (It
must have a create script.) In this case an empty string is returned, and you
must query the window by its index position to get more information.
.RE
.TP
\fIpathName \fBedit \fIoption \fR?\fIarg arg ...\fR?
\fIpathName \fBedit \fIoption \fR?\fIarg ...\fR?
.
This command controls the undo mechanism and the modified flag. The exact
behavior of the command depends on the \fIoption\fR argument that follows the
\fBedit\fR argument. The following forms of the command are currently
supported:
.RS
.TP
1305
1306
1307
1308
1309
1310
1311
1312
1313



1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328




1329
1330
1331
1332
1333
1334
1335
1305
1306
1307
1308
1309
1310
1311


1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326



1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337







-
-
+
+
+












-
-
-
+
+
+
+







The insert, delete, edit undo and edit redo commands or the user can set or
clear the modified flag. If \fIboolean\fR is specified, sets the modified flag
of the widget to \fIboolean\fR.
.TP
\fIpathName \fBedit redo\fR
.
When the \fB\-undo\fR option is true, reapplies the last undone edits provided
no other edits were done since then. Generates an error when the redo stack is
empty. Does nothing when the \fB\-undo\fR option is false.
no other edits were done since then, and returns a list of indices indicating
what ranges were changed by the redo operation. Generates an error when the
redo stack is empty. Does nothing when the \fB\-undo\fR option is false.
.TP
\fIpathName \fBedit reset\fR
.
Clears the undo and redo stacks.
.TP
\fIpathName \fBedit separator\fR
.
Inserts a separator (boundary) on the undo stack. Does nothing when the
\fB\-undo\fR option is false.
.TP
\fIpathName \fBedit undo\fR
.
Undoes the last edit action when the \fB\-undo\fR option is true. An edit
action is defined as all the insert and delete commands that are recorded on
the undo stack in between two separators. Generates an error when the undo
Undoes the last edit action when the \fB\-undo\fR option is true, and returns a
list of indices indicating what ranges were changed by the undo operation. An
edit action is defined as all the insert and delete commands that are recorded
on the undo stack in between two separators. Generates an error when the undo
stack is empty. Does nothing when the \fB\-undo\fR option is false.
.RE
.TP
\fIpathName \fBget\fR ?\fB\-displaychars\fR? ?\fB\-\-\fR? \fIindex1\fR ?\fIindex2 ...\fR?
.
Return a range of characters from the text. The return value will be all the
characters in the text starting with the one whose index is \fIindex1\fR and
1343
1344
1345
1346
1347
1348
1349
1350

1351
1352
1353
1354
1355
1356
1357
1345
1346
1347
1348
1349
1350
1351

1352
1353
1354
1355
1356
1357
1358
1359







-
+







ranges of text will be returned in a list. Invalid ranges will not be
represented with empty strings in the list. The ranges are returned in the
order passed to \fIpathName \fBget\fR. If the \fB\-displaychars\fR option is
given, then, within each range, only those characters which are not elided
will be returned. This may have the effect that some of the returned ranges
are empty strings.
.TP
\fIpathName \fBimage \fIoption \fR?\fIarg arg ...\fR?
\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
argument. The following forms of the command are currently supported:
.RS
.TP
\fIpathName \fBimage cget \fIindex option\fR
1408
1409
1410
1411
1412
1413
1414
1415

1416
1417
1418
1419
1420
1421
1422
1410
1411
1412
1413
1414
1415
1416

1417
1418
1419
1420
1421
1422
1423
1424







-
+







characters will receive all of the tags in this list and no others, regardless
of the tags present around the insertion point. If multiple
\fIchars\fR\-\fItagList\fR argument pairs are present, they produce the same
effect as if a separate \fIpathName \fBinsert\fR widget command had been
issued for each pair, in order. The last \fItagList\fR argument may be
omitted.
.TP
\fIpathName \fBmark \fIoption \fR?\fIarg arg ...\fR?
\fIpathName \fBmark \fIoption \fR?\fIarg ...\fR?
.
This command is used to manipulate marks. The exact behavior of the command
depends on the \fIoption\fR argument that follows the \fBmark\fR argument. The
following forms of the command are currently supported:
.RS
.TP
\fIpathName \fBmark gravity \fImarkName\fR ?\fIdirection\fR?
1688
1689
1690
1691
1692
1693
1694
1695

1696
1697
1698
1699
1700
1701
1702
1690
1691
1692
1693
1694
1695
1696

1697
1698
1699
1700
1701
1702
1703
1704







-
+







\fIpathName \fBsync -command \fIcommand\fR
Schedules \fIcommand\fR to be executed (by the event loop) exactly once as soon
as all line heights are up-to-date. If there are no pending line metrics
calculations, the scheduling is immediate. The command returns the empty
string. \fBbgerror\fR is called on \fIcommand\fR failure.
.RE
.TP
\fIpathName \fBtag \fIoption \fR?\fIarg arg ...\fR?
\fIpathName \fBtag \fIoption \fR?\fIarg ...\fR?
.
This command is used to manipulate tags. The exact behavior of the command
depends on the \fIoption\fR argument that follows the \fBtag\fR argument. The
following forms of the command are currently supported:
.RS
.TP
\fIpathName \fBtag add \fItagName index1 \fR?\fIindex2 index1 index2 ...\fR?
1727
1728
1729
1730
1731
1732
1733
1734
1735


1736
1737
1738
1739
1740
1741
1742
1729
1730
1731
1732
1733
1734
1735


1736
1737
1738
1739
1740
1741
1742
1743
1744







-
-
+
+







the command returns the \fIscript\fR associated with \fItagName\fR and
\fIsequence\fR (an error occurs if there is no such binding). If both
\fIscript\fR and \fIsequence\fR are omitted then the command returns a list of
all the sequences for which bindings have been defined for \fItagName\fR.
.RS
.PP
The only events for which bindings may be specified are those related to the
mouse and keyboard (such as \fBEnter\fR, \fBLeave\fR, \fBButtonPress\fR,
\fBMotion\fR, and \fBKeyPress\fR) or virtual events. Event bindings for a text
mouse and keyboard (such as \fBEnter\fR, \fBLeave\fR, \fBButton\fR,
\fBMotion\fR, and \fBKey\fR) or virtual events. Event bindings for a text
widget use the \fBcurrent\fR mark described under \fBMARKS\fR above. An
\fBEnter\fR event triggers for a tag when the tag first becomes present on the
current character, and a \fBLeave\fR event triggers for a tag when it ceases
to be present on the current character. \fBEnter\fR and \fBLeave\fR events can
happen either because the \fBcurrent\fR mark moved or because the character at
that position changed. Note that these events are different than \fBEnter\fR
and \fBLeave\fR events for windows. Mouse and keyboard events are directed to
1855
1856
1857
1858
1859
1860
1861
1862

1863
1864
1865
1866
1867
1868
1869
1857
1858
1859
1860
1861
1862
1863

1864
1865
1866
1867
1868
1869
1870
1871







-
+







\fIindex1\fR\-\fIindex2\fR pairs. If the last \fIindex2\fR is omitted then the
tag is removed from the single character at \fIindex1\fR. If there are no
characters in the specified range (e.g. \fIindex1\fR is past the end of the
file or \fIindex2\fR is less than or equal to \fIindex1\fR) then the command
has no effect. This command returns an empty string.
.RE
.TP
\fIpathName \fBwindow \fIoption \fR?\fIarg arg ...\fR?
\fIpathName \fBwindow \fIoption \fR?\fIarg ...\fR?
.
This command is used to manipulate embedded windows. The behavior of the
command depends on the \fIoption\fR argument that follows the \fBwindow\fR
argument. The following forms of the command are currently supported:
.RS
.TP
\fIpathName \fBwindow cget \fIindex option\fR
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934




1935
1936
1937
1938
1939
1940




1941
1942
1943
1944
1945
1946
1947
1948
1949
1926
1927
1928
1929
1930
1931
1932




1933
1934
1935
1936
1937
1938
1939
1940


1941
1942
1943
1944


1945
1946
1947
1948
1949
1950
1951







-
-
-
-
+
+
+
+




-
-
+
+
+
+
-
-







Adjusts the view in the window so that \fIfraction\fR of the horizontal span
of the text is off-screen to the left. \fIFraction\fR is a fraction between 0
and 1.
.TP
\fIpathName \fBxview scroll \fInumber what\fR
.
This command shifts the view in the window left or right according to
\fInumber\fR and \fIwhat\fR. \fIWhat\fR must be \fBunits\fR, \fBpages\fR or
\fBpixels\fR. If \fIwhat\fR is \fBunits\fR or \fBpages\fR then \fInumber\fR
must be an integer, otherwise number may be specified in any of the forms
acceptable to \fBTk_GetPixels\fR, such as
\fInumber\fR and \fIwhat\fR. \fIWhat\fR must be \fBpages\fR,
\fBpixels\fR, or \fBunits\fR. If \fIwhat\fR is \fBpages\fR or
\fBunits\fR then \fInumber\fR must be an integer, otherwise number may be
specified in any of the forms acceptable to \fBTk_GetPixels\fR, such as
.QW 2.0c
or
.QW 1i
(the result is rounded to the nearest integer value. If no units are given,
pixels are assumed). If \fIwhat\fR is \fBunits\fR, the view adjusts left or
right by \fInumber\fR average-width characters on the display; if it is
pixels are assumed). If \fIwhat\fR is \fBpages\fR then the view adjusts by
\fInumber\fR screenfuls; if it is \fBpixels\fR then the view adjusts by
\fInumber\fR pixels; if it is \fBunits\fR, the view adjusts left or
right by \fInumber\fR average-width characters on the display. If \fInumber\fR is
\fBpages\fR then the view adjusts by \fInumber\fR screenfuls; if it is
\fBpixels\fR then the view adjusts by \fInumber\fR pixels. If \fInumber\fR is
negative then characters farther to the left become visible; if it is positive
then characters farther to the right become visible.
.RE
.TP
\fIpathName \fByview \fR?\fIargs\fR?
.
This command is used to query and change the vertical position of the text in
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982




1983
1984
1985
1986
1987
1988
1989
1974
1975
1976
1977
1978
1979
1980




1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991







-
-
-
-
+
+
+
+







the widget will never scroll beyond the last pixel, and so a value of 1 will
effectively be rounded back to whatever fraction ensures the last pixel is at
the bottom of the window, and some other pixel is at the top.
.TP
\fIpathName \fByview scroll \fInumber what\fR
.
This command adjust the view in the window up or down according to
\fInumber\fR and \fIwhat\fR. \fIWhat\fR must be \fBunits\fR, \fBpages\fR or
\fBpixels\fR. If \fIwhat\fR is \fBunits\fR or \fBpages\fR then \fInumber\fR
must be an integer, otherwise number may be specified in any of the forms
acceptable to \fBTk_GetPixels\fR, such as
\fInumber\fR and \fIwhat\fR. \fIWhat\fR must be \fBpages\fR,
\fBpixels\fR, or \fBunits\fR. If \fIwhat\fR is \fBunits\fR or \fBpages\fR then
\fInumber\fR must be an integer, otherwise number may be specified in any of
the forms acceptable to \fBTk_GetPixels\fR, such as
.QW 2.0c
or
.QW 1i
(the result is rounded to the nearest integer value. If no units are given,
pixels are assumed). If \fIwhat\fR is \fBunits\fR, the view adjusts up or down
by \fInumber\fR lines on the display; if it is \fBpages\fR then the view
adjusts by \fInumber\fR screenfuls; if it is \fBpixels\fR then the view
2021
2022
2023
2024
2025
2026
2027
2028


2029
2030
2031


2032
2033
2034
2035
2036
2037
2038
2023
2024
2025
2026
2027
2028
2029

2030
2031
2032


2033
2034
2035
2036
2037
2038
2039
2040
2041







-
+
+

-
-
+
+







This command makes the first character on the line after the one given by
\fInumber\fR visible at the top of the window. \fINumber\fR must be an
integer. This command used to be used for scrolling, but now it is obsolete.
.RE
.SH BINDINGS
.PP
Tk automatically creates class bindings for texts that give them the following
default behavior. In the descriptions below,
default behavior.
In the descriptions below,
.QW word
is dependent on the value of the \fBtcl_wordchars\fR variable. See
\fBtclvars\fR(n).
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
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]
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063





2064
2065
2066
2067
2068
2069
2070
2056
2057
2058
2059
2060
2061
2062




2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074







-
-
-
-
+
+
+
+
+







.IP [5]
Clicking mouse button 1 with the Control key down will reposition the
insertion cursor without affecting the selection.
.IP [6]
If any normal printing characters are typed, they are inserted at the point of
the insertion cursor.
.IP [7]
The view in the widget can be adjusted by dragging with mouse button 2. If
mouse button 2 is clicked without moving the mouse, the selection is copied
into the text at the position of the mouse cursor. The Insert key also inserts
the selection, but at the position of the insertion cursor.
The view in the widget can be adjusted by dragging with the middle mouse
button (button 2, or button 3 in TkAqua). If the middle mouse button is
clicked without moving the mouse, the selection is copied into the text at the
position of the mouse cursor. The Insert key also inserts the selection,
but at the position of the insertion cursor.
.IP [8]
If the mouse is dragged out of the widget while button 1 is pressed, the entry
will automatically scroll to make more text visible (if there is more text
off-screen on the side where the mouse left the window).
.IP [9]
The Left and Right keys move the insertion cursor one character to the left or
right; they also clear any selection in the text. If Left or Right is typed
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162



2163
2164
2165
2166
2167
2168
2169
2155
2156
2157
2158
2159
2160
2161



2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173







-
-
-


+
+
+







.IP [28]
Control-o opens a new line by inserting a newline character in front of the
insertion cursor without moving the insertion cursor.
.IP [29]
Meta-backspace and Meta-Delete delete the word to the left of the insertion
cursor.
.IP [30]
Control-x deletes whatever is selected in the text widget after copying it to
the clipboard.
.IP [31]
Control-t reverses the order of the two characters to the right of the
insertion cursor.
.IP [31]
Control-x deletes whatever is selected in the text widget after copying it to
the clipboard.
.IP [32]
Control-z undoes the last edit action if the \fB\-undo\fR option is true.
Does nothing otherwise.
.IP [33]
Control-Z (or Control-y on Windows) reapplies the last undone edit action if
the \fB\-undo\fR option is true. Does nothing otherwise.
.PP
Changes to doc/tk.n.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
1
2
3
4
5
6

7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
22






-
+







-
+







'\"
'\" Copyright (c) 1992 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH tk n 8.4 Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
tk \- Manipulate Tk internal state
.SH SYNOPSIS
\fBtk\fR \fIoption \fR?\fIarg arg ...\fR?
\fBtk\fR \fIoption \fR?\fIarg ...\fR?
.BE
.SH DESCRIPTION
.PP
The \fBtk\fR command provides access to miscellaneous
elements of Tk's internal state.
Most of the information manipulated by this command pertains to the
application as a whole, or to a screen or display, rather than to a
107
108
109
110
111
112
113












114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130

131
132

133
134
135
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141

142
143

144
145
146
147







+
+
+
+
+
+
+
+
+
+
+
+
















-
+

-
+



factor is set when the application starts, based on properties of the
installed monitor, but it can be changed at any time.  Measurements made
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  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  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
feature is only significant on X.  If XIM support is not available, this
will always return 0.  If the \fIwindow\fR argument is omitted, it defaults
to the main window.  If the \fIboolean\fR argument is omitted, the current
state is returned.  This is turned on by default for the main display.
.TP
\fBtk windowingsystem\fR
.
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), send(n), sysnotify(n), systray(n), winfo(n)
.SH KEYWORDS
application name, send
application name, send, sysnotify, systray
'\" Local Variables:
'\" mode: nroff
'\" End:
Changes to doc/tk4.0.ps.
12
13
14
15
16
17
18
19

20
21
22
23
24
25
26
12
13
14
15
16
17
18

19
20
21
22
23
24
25
26







-
+







% FrameMaker.
% NOTE
% This file fixes the problem with NeWS printers dithering color output.
% Any questions should be sent to [email protected]
%
% Known Problems:
%	Due to bugs in Transcript, the 'PS-Adobe-' is omitted from line 1
/FMversion (3.0) def 
/FMversion (3.0) def
% Set up Color vs. Black-and-White

/FMPrintInColor { % once-thru loop gimmick
    % See if we're a NeWSprint printer
     /currentcanvas where {
        pop systemdict /separationdict known
	exit
34
35
36
37
38
39
40
41

42
43
44
45
46
47
48




49
50
51
52
53
54
55



56
57
58
59
60
61
62
63
64
65





66
67
68


69
70
71
72
73
74
75
76
77
78
79

80
81
82
83
84



85
86
87
88
89
90
91
92
93
94
95
96
97
98


99
100
101
102
103
104
105
106
107
108
109
110
111
112



113
114
115


116
117
118
119
120


121
122
123
124
125


126
127
128
129
130
131
132


133
134

135
136

137
138
139


140
141
142
143
144
145





146
147
148


149
150
151
152
153


154
155
156
157
158
159



160
161
162
163
164
165

166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181







182
183
184


185
186
187
188

189
190

191
192
193
194
195
196
197
198
199
200


201
202
203
204
205
206


207
208

209
210
211
212
213
214
215
34
35
36
37
38
39
40

41
42
43
44




45
46
47
48
49
50
51
52



53
54
55
56
57
58
59
60





61
62
63
64
65
66


67
68
69
70
71
72
73
74
75
76
77
78

79
80
81



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96


97
98
99
100
101
102
103
104
105
106
107
108
109



110
111
112
113


114
115
116
117
118


119
120
121
122
123


124
125
126
127
128
129
130


131
132
133

134
135

136
137


138
139
140





141
142
143
144
145
146


147
148
149
150
151


152
153
154
155
156



157
158
159
160
161
162
163
164

165
166
167
168
169
170
171
172
173
174







175
176
177
178
179
180
181
182


183
184
185
186
187

188
189

190
191
192
193
194
195
196
197
198


199
200
201
202
203
204


205
206
207

208
209
210
211
212
213
214
215







-
+



-
-
-
-
+
+
+
+




-
-
-
+
+
+





-
-
-
-
-
+
+
+
+
+

-
-
+
+










-
+


-
-
-
+
+
+












-
-
+
+











-
-
-
+
+
+

-
-
+
+



-
-
+
+



-
-
+
+





-
-
+
+

-
+

-
+

-
-
+
+

-
-
-
-
-
+
+
+
+
+

-
-
+
+



-
-
+
+



-
-
-
+
+
+





-
+









-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
+
+



-
+

-
+








-
-
+
+




-
-
+
+

-
+







%    } if
    systemdict /colorimage known
    systemdict /currentcolortransfer known and
exit } loop def

% Uncomment the following line to force b&w on color printer
%   /FMPrintInColor false def
/FrameDict 195 dict def 
/FrameDict 195 dict def
systemdict /errordict known not {/errordict 10 dict def
		errordict /rangecheck {stop} put} if
% The readline in 23.0 doesn't recognize cr's as nl's on AppleTalk
FrameDict /tmprangecheck errordict /rangecheck get put 
errordict /rangecheck {FrameDict /bug true put} put 
FrameDict /bug false put 
mark 
FrameDict /tmprangecheck errordict /rangecheck get put
errordict /rangecheck {FrameDict /bug true put} put
FrameDict /bug false put
mark
% Some PS machines read past the CR, so keep the following 3 lines together!
currentfile 5 string readline
00
0000000000
cleartomark 
errordict /rangecheck FrameDict /tmprangecheck get put 
FrameDict /bug get { 
cleartomark
errordict /rangecheck FrameDict /tmprangecheck get put
FrameDict /bug get {
	/readline {
		/gstring exch def
		/gfile exch def
		/gindex 0 def
		{
			gfile read pop 
			dup 10 eq {exit} if 
			dup 13 eq {exit} if 
			gstring exch gindex exch put 
			/gindex gindex 1 add def 
			gfile read pop
			dup 10 eq {exit} if
			dup 13 eq {exit} if
			gstring exch gindex exch put
			/gindex gindex 1 add def
		} loop
		pop 
		gstring 0 gindex getinterval true 
		pop
		gstring 0 gindex getinterval true
		} def
	} if
/FMVERSION {
	FMversion ne {
		/Times-Roman findfont 18 scalefont setfont
		100 100 moveto
		(FrameMaker version does not match postscript_prolog!)
		dup =
		show showpage
		} if
	} def 
	} def
/FMLOCAL {
	FrameDict begin
	0 def 
	end 
	} def 
	0 def
	end
	} def
	/gstring FMLOCAL
	/gfile FMLOCAL
	/gindex FMLOCAL
	/orgxfer FMLOCAL
	/orgproc FMLOCAL
	/organgle FMLOCAL
	/orgfreq FMLOCAL
	/yscale FMLOCAL
	/xscale FMLOCAL
	/manualfeed FMLOCAL
	/paperheight FMLOCAL
	/paperwidth FMLOCAL
/FMDOCUMENT { 
	array /FMfonts exch def 
/FMDOCUMENT {
	array /FMfonts exch def
	/#copies exch def
	FrameDict begin
	0 ne dup {setmanualfeed} if
	/manualfeed exch def
	/paperheight exch def
	/paperwidth exch def
	/yscale exch def
	/xscale exch def
	currenttransfer cvlit /orgxfer exch def
	currentscreen cvlit /orgproc exch def
	/organgle exch def /orgfreq exch def
	setpapername 
	manualfeed {true} {papersize} ifelse 
	{manualpapersize} {false} ifelse 
	setpapername
	manualfeed {true} {papersize} ifelse
	{manualpapersize} {false} ifelse
	{desperatepapersize} if
	end 
	} def 
	end
	} def
	/pagesave FMLOCAL
	/orgmatrix FMLOCAL
	/landscape FMLOCAL
/FMBEGINPAGE { 
	FrameDict begin 
/FMBEGINPAGE {
	FrameDict begin
	/pagesave save def
	3.86 setmiterlimit
	/landscape exch 0 ne def
	landscape { 
		90 rotate 0 exch neg translate pop 
	landscape {
		90 rotate 0 exch neg translate pop
		}
		{pop pop}
		ifelse
	xscale yscale scale
	/orgmatrix matrix def
	gsave 
	} def 
	gsave
	} def
/FMENDPAGE {
	grestore 
	grestore
	pagesave restore
	end 
	end
	showpage
	} def 
/FMFONTDEFINE { 
	} def
/FMFONTDEFINE {
	FrameDict begin
	findfont 
	ReEncode 
	1 index exch 
	definefont 
	FMfonts 3 1 roll 
	findfont
	ReEncode
	1 index exch
	definefont
	FMfonts 3 1 roll
	put
	end 
	} def 
	end
	} def
/FMFILLS {
	FrameDict begin
	array /fillvals exch def
	end 
	} def 
	end
	} def
/FMFILL {
	FrameDict begin
	 fillvals 3 1 roll put
	end 
	} def 
/FMNORMALIZEGRAPHICS { 
	end
	} def
/FMNORMALIZEGRAPHICS {
	newpath
	0.0 0.0 moveto
	1 setlinewidth
	0 setlinecap
	0 0 0 sethsbcolor
	0 setgray 
	0 setgray
	} bind def
	/fx FMLOCAL
	/fy FMLOCAL
	/fh FMLOCAL
	/fw FMLOCAL
	/llx FMLOCAL
	/lly FMLOCAL
	/urx FMLOCAL
	/ury FMLOCAL
/FMBEGINEPSF { 
	end 
	/FMEPSF save def 
	/showpage {} def 
	FMNORMALIZEGRAPHICS 
	[/fy /fx /fh /fw /ury /urx /lly /llx] {exch def} forall 
	fx fy translate 
/FMBEGINEPSF {
	end
	/FMEPSF save def
	/showpage {} def
	FMNORMALIZEGRAPHICS
	[/fy /fx /fh /fw /ury /urx /lly /llx] {exch def} forall
	fx fy translate
	rotate
	fw urx llx sub div fh ury lly sub div scale 
	llx neg lly neg translate 
	fw urx llx sub div fh ury lly sub div scale
	llx neg lly neg translate
	} bind def
/FMENDEPSF {
	FMEPSF restore
	FrameDict begin 
	FrameDict begin
	} bind def
FrameDict begin 
FrameDict begin
/setmanualfeed {
%%BeginFeature *ManualFeed True
	 statusdict /manualfeed true put
%%EndFeature
	} def
/max {2 copy lt {exch} if pop} bind def
/min {2 copy gt {exch} if pop} bind def
/inch {72 mul} def
/pagedimen { 
	paperheight sub abs 16 lt exch 
/pagedimen {
	paperheight sub abs 16 lt exch
	paperwidth sub abs 16 lt and
	{/papername exch def} {pop} ifelse
	} def
	/papersizedict FMLOCAL
/setpapername { 
	/papersizedict 14 dict def 
/setpapername {
	/papersizedict 14 dict def
	papersizedict begin
	/papername /unknown def 
	/papername /unknown def
		/Letter 8.5 inch 11.0 inch pagedimen
		/LetterSmall 7.68 inch 10.16 inch pagedimen
		/Tabloid 11.0 inch 17.0 inch pagedimen
		/Ledger 17.0 inch 11.0 inch pagedimen
		/Legal 8.5 inch 14.0 inch pagedimen
		/Statement 5.5 inch 8.5 inch pagedimen
		/Executive 7.5 inch 10.0 inch pagedimen
233
234
235
236
237
238
239
240
241
242



243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261

262
263
264
265
266

267
268

269
270
271
272
273
274
275
233
234
235
236
237
238
239



240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260

261
262
263
264
265

266
267

268
269
270
271
272
273
274
275







-
-
-
+
+
+


















-
+




-
+

-
+







		/A4 {a4tray a4} def
		/A4Small {a4tray a4small} def
		/B4 {b4tray b4} def
		/B5 {b5tray b5} def
		/unknown {unknown} def
	papersizedict dup papername known {papername} {/unknown} ifelse get
	end
	/FMdicttop countdictstack 1 add def 
	statusdict begin stopped end 
	countdictstack -1 FMdicttop {pop end} for 
	/FMdicttop countdictstack 1 add def
	statusdict begin stopped end
	countdictstack -1 FMdicttop {pop end} for
	} def
/manualpapersize {
	papersizedict begin
		/Letter {letter} def
		/LetterSmall {lettersmall} def
		/Tabloid {11x17} def
		/Ledger {ledger} def
		/Legal {legal} def
		/Statement {statement} def
		/Executive {executive} def
		/A3 {a3} def
		/A4 {a4} def
		/A4Small {a4small} def
		/B4 {b4} def
		/B5 {b5} def
		/unknown {unknown} def
	papersizedict dup papername known {papername} {/unknown} ifelse get
	end
	stopped 
	stopped
	} def
/desperatepapersize {
	statusdict /setpageparams known
		{
		paperwidth paperheight 0 1 
		paperwidth paperheight 0 1
		statusdict begin
		{setpageparams} stopped pop 
		{setpageparams} stopped pop
		end
		} if
	} def
/savematrix {
	orgmatrix currentmatrix pop
	} bind def
/restorematrix {
310
311
312
313
314
315
316
317
318
319
320




321
322
323
324
325
326
327
328







329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345

346
347
348
349
350
351
352
310
311
312
313
314
315
316




317
318
319
320
321







322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344

345
346
347
348
349
350
351
352







-
-
-
-
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+
















-
+







/fraction /currency /guilsinglleft /guilsinglright /fi /fl /daggerdbl
/periodcentered /quotesinglbase /quotedblbase /perthousand
/Acircumflex /Ecircumflex /Aacute /Edieresis /Egrave /Iacute
/Icircumflex /Idieresis /Igrave /Oacute /Ocircumflex /.notdef /Ograve
/Uacute /Ucircumflex /Ugrave /dotlessi /circumflex /tilde /macron
/breve /dotaccent /ring /cedilla /hungarumlaut /ogonek /caron
] def
/ReEncode { 
	dup 
	length 
	dict begin 
/ReEncode {
	dup
	length
	dict begin
	{
	1 index /FID ne 
		{def} 
		{pop pop} ifelse 
	} forall 
	0 eq {/Encoding DiacriticEncoding def} if 
	currentdict 
	end 
	1 index /FID ne
		{def}
		{pop pop} ifelse
	} forall
	0 eq {/Encoding DiacriticEncoding def} if
	currentdict
	end
	} bind def
/graymode true def
	/bwidth FMLOCAL
	/bpside FMLOCAL
	/bstring FMLOCAL
	/onbits FMLOCAL
	/offbits FMLOCAL
	/xindex FMLOCAL
	/yindex FMLOCAL
	/x FMLOCAL
	/y FMLOCAL
/setpattern {
	 /bwidth  exch def
	 /bpside  exch def
	 /bstring exch def
	 /onbits 0 def  /offbits 0 def
	 freq sangle landscape {90 add} if 
	 freq sangle landscape {90 add} if
		{/y exch def
		 /x exch def
		 /xindex x 1 add 2 div bpside mul cvi def
		 /yindex y 1 add 2 div bpside mul cvi def
		 bstring yindex bwidth mul xindex 8 idiv add get
		 1 7 xindex 8 mod sub bitshift and 0 ne
		 {/onbits  onbits  1 add def 1}
366
367
368
369
370
371
372
373
374


375
376
377
378
379
380

381
382
383
384
385
386
387
388
389
390
391


392
393

394
395

396
397

398
399

400
401

402
403
404
405

406
407
408
409


410
411
412

413
414
415
416

417
418

419
420

421
422

423
424

425
426
427

428
429
430
431
432
433
434
435
436
437
438

439
440
441

442
443
444
445
446
447
448

449
450
451

452
453
454
455

456
457
458

459
460
461
462
463
464
465
466

467
468
469
470

471
472
473
474


475
476
477
478
479
480
481
482

483
484
485
486
487
488
489
490
491

492
493

494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510

511
512
513

514
515
516
517

518
519
520
521
522

523
524

525
526

527
528
529

530
531
532
533

534
535

536
537
538
539
540

541
542
543
544

545
546

547
548
549
550
551

552
553
554
555

556
557
558
559
560
561
562

563
564
565
566

567
568
569
570
571
572
573

574
575
576
577
578



579
580
581
582

583
584
585
586
587
588
589
590





591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608



609
610
611
612



613
614
615
616
617
618



619
620
621
622
623
624
625
626







627
628

629
630
631
632
633
634




635
636

637
638
639
640
641
642
643
366
367
368
369
370
371
372


373
374
375
376
377
378
379

380
381
382
383
384
385
386
387
388
389


390
391
392

393
394

395
396

397
398

399
400

401
402
403
404

405
406
407


408
409
410
411

412
413
414
415

416
417

418
419

420
421

422
423

424
425
426

427
428
429
430
431
432
433
434
435
436
437

438
439
440

441
442
443
444
445
446
447

448
449
450

451
452
453
454

455
456
457

458
459
460
461
462
463
464
465

466
467
468
469

470
471
472


473
474
475
476
477
478
479
480
481

482
483
484
485
486
487
488
489
490

491
492

493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509

510
511
512

513
514
515
516

517
518
519
520
521

522
523

524
525

526
527
528

529
530
531
532

533
534

535
536
537
538
539

540
541
542
543

544
545

546
547
548
549
550

551
552
553
554

555
556
557
558
559
560
561

562
563
564
565

566
567
568
569
570
571
572

573
574
575



576
577
578
579
580
581

582
583
584
585





586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605



606
607
608
609



610
611
612
613
614
615



616
617
618
619







620
621
622
623
624
625
626
627

628
629
630




631
632
633
634
635

636
637
638
639
640
641
642
643







-
-
+
+





-
+









-
-
+
+

-
+

-
+

-
+

-
+

-
+



-
+


-
-
+
+


-
+



-
+

-
+

-
+

-
+

-
+


-
+










-
+


-
+






-
+


-
+



-
+


-
+







-
+



-
+


-
-
+
+







-
+








-
+

-
+
















-
+


-
+



-
+




-
+

-
+

-
+


-
+



-
+

-
+




-
+



-
+

-
+




-
+



-
+






-
+



-
+






-
+


-
-
-
+
+
+



-
+



-
-
-
-
-
+
+
+
+
+















-
-
-
+
+
+

-
-
-
+
+
+



-
-
-
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
+


-
-
-
-
+
+
+
+

-
+







		orgfreq organgle orgproc cvx setscreen
		} if
	} bind def
	/HUE FMLOCAL
	/SAT FMLOCAL
	/BRIGHT FMLOCAL
	/Colors FMLOCAL
FMPrintInColor 
	
FMPrintInColor

	{
	/HUE 0 def
	/SAT 0 def
	/BRIGHT 0 def
	% array of arrays Hue and Sat values for the separations [HUE BRIGHT]
	/Colors   
	/Colors
	[[0    0  ]    % black
	 [0    0  ]    % white
	 [0.00 1.0]    % red
	 [0.37 1.0]    % green
	 [0.60 1.0]    % blue
	 [0.50 1.0]    % cyan
	 [0.83 1.0]    % magenta
	 [0.16 1.0]    % comment / yellow
	 ] def
      
	/BEGINBITMAPCOLOR { 

	/BEGINBITMAPCOLOR {
		BITMAPCOLOR} def
	/BEGINBITMAPCOLORc { 
	/BEGINBITMAPCOLORc {
		BITMAPCOLORc} def
	/BEGINBITMAPTRUECOLOR { 
	/BEGINBITMAPTRUECOLOR {
		BITMAPTRUECOLOR } def
	/BEGINBITMAPTRUECOLORc { 
	/BEGINBITMAPTRUECOLORc {
		BITMAPTRUECOLORc } def
	/K { 
	/K {
		Colors exch get dup
		0 get /HUE exch store 
		0 get /HUE exch store
		1 get /BRIGHT exch store
		  HUE 0 eq BRIGHT 0 eq and
			{1.0 SAT sub setgray}
			{HUE SAT BRIGHT sethsbcolor} 
			{HUE SAT BRIGHT sethsbcolor}
		  ifelse
		} def
	/FMsetgray { 
		/SAT exch 1.0 exch sub store 
	/FMsetgray {
		/SAT exch 1.0 exch sub store
		  HUE 0 eq BRIGHT 0 eq and
			{1.0 SAT sub setgray}
			{HUE SAT BRIGHT sethsbcolor} 
			{HUE SAT BRIGHT sethsbcolor}
		  ifelse
		} bind def
	}
	

	{
	/BEGINBITMAPCOLOR { 
	/BEGINBITMAPCOLOR {
		BITMAPGRAY} def
	/BEGINBITMAPCOLORc { 
	/BEGINBITMAPCOLORc {
		BITMAPGRAYc} def
	/BEGINBITMAPTRUECOLOR { 
	/BEGINBITMAPTRUECOLOR {
		BITMAPTRUEGRAY } def
	/BEGINBITMAPTRUECOLORc { 
	/BEGINBITMAPTRUECOLORc {
		BITMAPTRUEGRAYc } def
	/FMsetgray {setgray} bind def
	/K { 
	/K {
		pop
		} def
	}
ifelse
/normalize {
	transform round exch round exch itransform
	} bind def
/dnormalize {
	dtransform round exch round exch idtransform
	} bind def
/lnormalize { 
/lnormalize {
	0 dtransform exch cvi 2 idiv 2 mul 1 add exch idtransform pop
	} bind def
/H { 
/H {
	lnormalize setlinewidth
	} bind def
/Z {
	setlinecap
	} bind def
	/fillvals FMLOCAL
/X { 
/X {
	fillvals exch get
	dup type /stringtype eq
	{8 1 setpattern} 
	{8 1 setpattern}
	{grayness}
	ifelse
	} bind def
/V { 
/V {
	gsave eofill grestore
	} bind def
/N { 
/N {
	stroke
	} bind def
/M {newpath moveto} bind def
/E {lineto} bind def
/D {curveto} bind def
/O {closepath} bind def
	/n FMLOCAL
/L { 
/L {
 	/n exch def
	newpath
	normalize
	moveto 
	moveto
	2 1 n {pop normalize lineto} for
	} bind def
/Y { 
	L 
/Y {
	L
	closepath
	} bind def
	/x1 FMLOCAL
	/x2 FMLOCAL
	/y1 FMLOCAL
	/y2 FMLOCAL
	/rad FMLOCAL
/R { 
/R {
	/y2 exch def
	/x2 exch def
	/y1 exch def
	/x1 exch def
	x1 y1
	x2 y1
	x2 y2
	x1 y2
	4 Y 
	4 Y
	} bind def
/RR { 
/RR {
	/rad exch def
	normalize
	/y2 exch def
	/x2 exch def
	normalize
	/y1 exch def
	/x1 exch def
	newpath
	x1 y1 rad add moveto
	x1 y2 x2 y2 rad arcto
	x2 y2 x2 y1 rad arcto
	x2 y1 x1 y1 rad arcto
	x1 y1 x1 y2 rad arcto
	closepath
	16 {pop} repeat
	} bind def
/C { 
/C {
	grestore
	gsave
	R 
	R
	clip
	} bind def
	/FMpointsize FMLOCAL
/F { 
/F {
	FMfonts exch get
	FMpointsize scalefont
	setfont
	} bind def
/Q { 
/Q {
	/FMpointsize exch def
	F 
	F
	} bind def
/T { 
/T {
	moveto show
	} bind def
/RF { 
/RF {
	rotate
	0 ne {-1 1 scale} if
	} bind def
/TF { 
/TF {
	gsave
	moveto 
	moveto
	RF
	show
	grestore
	} bind def
/P { 
/P {
	moveto
	0 32 3 2 roll widthshow
	} bind def
/PF { 
/PF {
	gsave
	moveto 
	moveto
	RF
	0 32 3 2 roll widthshow
	grestore
	} bind def
/S { 
/S {
	moveto
	0 exch ashow
	} bind def
/SF { 
/SF {
	gsave
	moveto
	RF
	0 exch ashow
	grestore
	} bind def
/B { 
/B {
	moveto
	0 32 4 2 roll 0 exch awidthshow
	} bind def
/BF { 
/BF {
	gsave
	moveto
	RF
	0 32 4 2 roll 0 exch awidthshow
	grestore
	} bind def
/G { 
/G {
	gsave
	newpath
	normalize translate 0.0 0.0 moveto 
	dnormalize scale 
	0.0 0.0 1.0 5 3 roll arc 
	normalize translate 0.0 0.0 moveto
	dnormalize scale
	0.0 0.0 1.0 5 3 roll arc
	closepath fill
	grestore
	} bind def
/A { 
/A {
	gsave
	savematrix
	newpath
	2 index 2 div add exch 3 index 2 div sub exch 
	normalize 2 index 2 div sub exch 3 index 2 div add exch 
	translate 
	scale 
	0.0 0.0 1.0 5 3 roll arc 
	2 index 2 div add exch 3 index 2 div sub exch
	normalize 2 index 2 div sub exch 3 index 2 div add exch
	translate
	scale
	0.0 0.0 1.0 5 3 roll arc
	restorematrix
	stroke
	grestore
	} bind def
	/x FMLOCAL
	/y FMLOCAL
	/w FMLOCAL
	/h FMLOCAL
	/xx FMLOCAL
	/yy FMLOCAL
	/ww FMLOCAL
	/hh FMLOCAL
	/FMsaveobject FMLOCAL
	/FMoptop FMLOCAL
	/FMdicttop FMLOCAL
/BEGINPRINTCODE { 
	/FMdicttop countdictstack 1 add def 
	/FMoptop count 4 sub def 
/BEGINPRINTCODE {
	/FMdicttop countdictstack 1 add def
	/FMoptop count 4 sub def
	/FMsaveobject save def
	userdict begin 
	/showpage {} def 
	FMNORMALIZEGRAPHICS 
	userdict begin
	/showpage {} def
	FMNORMALIZEGRAPHICS
	3 index neg 3 index neg translate
	} bind def
/ENDPRINTCODE {
	count -1 FMoptop {pop pop} for 
	countdictstack -1 FMdicttop {pop end} for 
	FMsaveobject restore 
	count -1 FMoptop {pop pop} for
	countdictstack -1 FMdicttop {pop end} for
	FMsaveobject restore
	} bind def
/gn { 
	0 
	{	46 mul 
		cf read pop 
		32 sub 
		dup 46 lt {exit} if 
		46 sub add 
/gn {
	0
	{	46 mul
		cf read pop
		32 sub
		dup 46 lt {exit} if
		46 sub add
		} loop
	add 
	add
	} bind def
	/str FMLOCAL
/cfs { 
	/str sl string def 
	0 1 sl 1 sub {str exch val put} for 
	str def 
/cfs {
	/str sl string def
	0 1 sl 1 sub {str exch val put} for
	str def
	} bind def
/ic [ 
/ic [
	0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0223
	0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0223
	0
	{0 hx} {1 hx} {2 hx} {3 hx} {4 hx} {5 hx} {6 hx} {7 hx} {8 hx} {9 hx}
	{10 hx} {11 hx} {12 hx} {13 hx} {14 hx} {15 hx} {16 hx} {17 hx} {18 hx}
	{19 hx} {gn hx} {0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10} {11} {12}
	{13} {14} {15} {16} {17} {18} {19} {gn} {0 wh} {1 wh} {2 wh} {3 wh}
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665








666
667
668
669
670
671
672
673
674
675
676










677
678
679
680



681
682

683
684
685
686



687
688

689
690
691
692
693



694
695
696

697
698
699
700



701
702
703
704
705
706
707
708
709
710


711
712
713

714
715
716

717
718
719

720
721
722

723
724
725
726
727
728
729
730
731
732
733
734
735
736










737
738
739

740
741
742

743
744
745

746
747
748

749
750
751
752
753
754


755
756
757


758
759

760
761
762
763
764
765
766
651
652
653
654
655
656
657








658
659
660
661
662
663
664
665
666










667
668
669
670
671
672
673
674
675
676
677



678
679
680
681

682
683



684
685
686
687

688
689
690



691
692
693
694
695

696
697



698
699
700
701
702
703
704
705
706
707
708


709
710
711
712

713
714
715

716
717
718

719
720
721

722
723
724
725
726










727
728
729
730
731
732
733
734
735
736
737
738

739
740
741

742
743
744

745
746
747

748
749
750
751
752


753
754
755


756
757
758

759
760
761
762
763
764
765
766







-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+

-
-
-
+
+
+

-
+

-
-
-
+
+
+

-
+


-
-
-
+
+
+


-
+

-
-
-
+
+
+








-
-
+
+


-
+


-
+


-
+


-
+




-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+


-
+


-
+


-
+


-
+




-
-
+
+

-
-
+
+

-
+







	/val FMLOCAL
	/ws FMLOCAL
	/im FMLOCAL
	/bs FMLOCAL
	/cs FMLOCAL
	/len FMLOCAL
	/pos FMLOCAL
/ms { 
	/sl exch def 
	/val 255 def 
	/ws cfs 
	/im cfs 
	/val 0 def 
	/bs cfs 
	/cs cfs 
/ms {
	/sl exch def
	/val 255 def
	/ws cfs
	/im cfs
	/val 0 def
	/bs cfs
	/cs cfs
	} bind def
400 ms 
/ip { 
	is 
	0 
	cf cs readline pop 
	{	ic exch get exec 
		add 
		} forall 
	pop 
	
400 ms
/ip {
	is
	0
	cf cs readline pop
	{	ic exch get exec
		add
		} forall
	pop

	} bind def
/wh { 
	/len exch def 
	/pos exch def 
/wh {
	/len exch def
	/pos exch def
	ws 0 len getinterval im pos len getinterval copy pop
	pos len 
	pos len
	} bind def
/bl { 
	/len exch def 
	/pos exch def 
/bl {
	/len exch def
	/pos exch def
	bs 0 len getinterval im pos len getinterval copy pop
	pos len 
	pos len
	} bind def
/s1 1 string def
/fl { 
	/len exch def 
	/pos exch def 
/fl {
	/len exch def
	/pos exch def
	/val cf s1 readhexstring pop 0 get def
	pos 1 pos len add 1 sub {im exch val put} for
	pos len 
	pos len
	} bind def
/hx { 
	3 copy getinterval 
	cf exch readhexstring pop pop 
/hx {
	3 copy getinterval
	cf exch readhexstring pop pop
	} bind def
	/h FMLOCAL
	/w FMLOCAL
	/d FMLOCAL
	/lb FMLOCAL
	/bitmapsave FMLOCAL
	/is FMLOCAL
	/cf FMLOCAL
/wbytes { 
	dup 
/wbytes {
	dup
	8 eq {pop} {1 eq {7 add 8 idiv} {3 add 4 idiv} ifelse} ifelse
	} bind def
/BEGINBITMAPBWc { 
/BEGINBITMAPBWc {
	1 {} COMMONBITMAPc
	} bind def
/BEGINBITMAPGRAYc { 
/BEGINBITMAPGRAYc {
	8 {} COMMONBITMAPc
	} bind def
/BEGINBITMAP2BITc { 
/BEGINBITMAP2BITc {
	2 {} COMMONBITMAPc
	} bind def
/COMMONBITMAPc { 
/COMMONBITMAPc {
	/r exch def
	/d exch def
	gsave
	translate rotate scale /h exch def /w exch def
	/lb w d wbytes def 
	sl lb lt {lb ms} if 
	/bitmapsave save def 
	r                    
	/is im 0 lb getinterval def 
	ws 0 lb getinterval is copy pop 
	/cf currentfile def 
	w h d [w 0 0 h neg 0 h] 
	{ip} image 
	bitmapsave restore 
	/lb w d wbytes def
	sl lb lt {lb ms} if
	/bitmapsave save def
	r
	/is im 0 lb getinterval def
	ws 0 lb getinterval is copy pop
	/cf currentfile def
	w h d [w 0 0 h neg 0 h]
	{ip} image
	bitmapsave restore
	grestore
	} bind def
/BEGINBITMAPBW { 
/BEGINBITMAPBW {
	1 {} COMMONBITMAP
	} bind def
/BEGINBITMAPGRAY { 
/BEGINBITMAPGRAY {
	8 {} COMMONBITMAP
	} bind def
/BEGINBITMAP2BIT { 
/BEGINBITMAP2BIT {
	2 {} COMMONBITMAP
	} bind def
/COMMONBITMAP { 
/COMMONBITMAP {
	/r exch def
	/d exch def
	gsave
	translate rotate scale /h exch def /w exch def
	/bitmapsave save def 
	r                    
	/bitmapsave save def
	r
	/is w d wbytes string def
	/cf currentfile def 
	w h d [w 0 0 h neg 0 h] 
	/cf currentfile def
	w h d [w 0 0 h neg 0 h]
	{cf is readhexstring pop} image
	bitmapsave restore 
	bitmapsave restore
	grestore
	} bind def
	/proc1 FMLOCAL
	/proc2 FMLOCAL
	/newproc FMLOCAL
/Fmcc {
    /proc2 exch cvlit def
809
810
811
812
813
814
815
816

817
818
819
820
821
822
823
824
825
826

827
828
829
830

831
832
833
834
835
836




837
838
839

840
841
842
843
844
845



846
847
848
849
850




851
852

853
854
855

856
857
858
859


860
861
862
863
864




865
866

867
868
869

870
871
872

873
874
875
876
877
878
879
880
881
882







883
884
885

886
887
888
889


890
891
892
893
894




895
896

897
898
899
900
901
902
903
904

905
906
907
908
909
910
911
912
913

914
915
916

917
918
919
920
921
922
923




924
925

926
927
928

929
930
931

932
933
934
935
936

937
938
939
940
941
942
943
809
810
811
812
813
814
815

816
817
818
819
820
821
822
823
824
825

826
827
828
829

830
831
832




833
834
835
836
837
838

839
840
841
842



843
844
845
846




847
848
849
850
851

852
853
854

855
856
857


858
859
860




861
862
863
864
865

866
867
868

869
870
871

872
873
874
875







876
877
878
879
880
881
882
883
884

885
886
887


888
889
890




891
892
893
894
895

896
897
898
899
900
901
902
903

904
905
906
907
908
909
910
911
912

913
914
915

916
917
918
919




920
921
922
923
924

925
926
927

928
929
930

931
932
933
934
935

936
937
938
939
940
941
942
943







-
+









-
+



-
+


-
-
-
-
+
+
+
+


-
+



-
-
-
+
+
+

-
-
-
-
+
+
+
+

-
+


-
+


-
-
+
+

-
-
-
-
+
+
+
+

-
+


-
+


-
+



-
-
-
-
-
-
-
+
+
+
+
+
+
+


-
+


-
-
+
+

-
-
-
-
+
+
+
+

-
+







-
+








-
+


-
+



-
-
-
-
+
+
+
+

-
+


-
+


-
+




-
+







	setcolortransfer
	{pop 0} setundercolorremoval
	{} setblackgeneration
	} bind def
	/tran FMLOCAL
/fakecolorsetup {
	/tran 256 string def
	0 1 255 {/indx exch def 
	0 1 255 {/indx exch def
		tran indx
		red indx get 77 mul
		green indx get 151 mul
		blue indx get 28 mul
		add add 256 idiv put} for
	currenttransfer
	{255 mul cvi tran exch get 255.0 div}
	exch Fmcc settransfer
} bind def
/BITMAPCOLOR { 
/BITMAPCOLOR {
	/d 8 def
	gsave
	translate rotate scale /h exch def /w exch def
	/bitmapsave save def 
	/bitmapsave save def
	colorsetup
	/is w d wbytes string def
	/cf currentfile def 
	w h d [w 0 0 h neg 0 h] 
	{cf is readhexstring pop} {is} {is} true 3 colorimage 
	bitmapsave restore 
	/cf currentfile def
	w h d [w 0 0 h neg 0 h]
	{cf is readhexstring pop} {is} {is} true 3 colorimage
	bitmapsave restore
	grestore
	} bind def
/BITMAPCOLORc { 
/BITMAPCOLORc {
	/d 8 def
	gsave
	translate rotate scale /h exch def /w exch def
	/lb w d wbytes def 
	sl lb lt {lb ms} if 
	/bitmapsave save def 
	/lb w d wbytes def
	sl lb lt {lb ms} if
	/bitmapsave save def
	colorsetup
	/is im 0 lb getinterval def 
	ws 0 lb getinterval is copy pop 
	/cf currentfile def 
	w h d [w 0 0 h neg 0 h] 
	/is im 0 lb getinterval def
	ws 0 lb getinterval is copy pop
	/cf currentfile def
	w h d [w 0 0 h neg 0 h]
	{ip} {is} {is} true 3 colorimage
	bitmapsave restore 
	bitmapsave restore
	grestore
	} bind def
/BITMAPTRUECOLORc { 
/BITMAPTRUECOLORc {
        gsave
        translate rotate scale /h exch def /w exch def
        /bitmapsave save def 
        
        /bitmapsave save def

        /is w string def
        
        ws 0 w getinterval is copy pop 
        /cf currentfile def 
        w h 8 [w 0 0 h neg 0 h] 

        ws 0 w getinterval is copy pop
        /cf currentfile def
        w h 8 [w 0 0 h neg 0 h]
        {ip} {gip} {bip} true 3 colorimage
        bitmapsave restore 
        bitmapsave restore
        grestore
        } bind def
/BITMAPTRUECOLOR { 
/BITMAPTRUECOLOR {
        gsave
        translate rotate scale /h exch def /w exch def
        /bitmapsave save def 
        /bitmapsave save def
        /is w string def
        /gis w string def
        /bis w string def
        /cf currentfile def 
        w h 8 [w 0 0 h neg 0 h] 
        { cf is readhexstring pop } 
        { cf gis readhexstring pop } 
        { cf bis readhexstring pop } 
        true 3 colorimage 
        bitmapsave restore 
        /cf currentfile def
        w h 8 [w 0 0 h neg 0 h]
        { cf is readhexstring pop }
        { cf gis readhexstring pop }
        { cf bis readhexstring pop }
        true 3 colorimage
        bitmapsave restore
        grestore
        } bind def
/BITMAPTRUEGRAYc { 
/BITMAPTRUEGRAYc {
        gsave
        translate rotate scale /h exch def /w exch def
        /bitmapsave save def 
        
        /bitmapsave save def

        /is w string def
        
        ws 0 w getinterval is copy pop 
        /cf currentfile def 
        w h 8 [w 0 0 h neg 0 h] 

        ws 0 w getinterval is copy pop
        /cf currentfile def
        w h 8 [w 0 0 h neg 0 h]
        {ip gip bip w gray} image
        bitmapsave restore 
        bitmapsave restore
        grestore
        } bind def
/ww FMLOCAL
/r FMLOCAL
/g FMLOCAL
/b FMLOCAL
/i FMLOCAL
/gray { 
/gray {
        /ww exch def
        /b exch def
        /g exch def
        /r exch def
        0 1 ww 1 sub { /i exch def r i get .299 mul g i get .587 mul
			b i get .114 mul add add r i 3 -1 roll floor cvi put } for
        r
        } bind def
/BITMAPTRUEGRAY { 
/BITMAPTRUEGRAY {
        gsave
        translate rotate scale /h exch def /w exch def
        /bitmapsave save def 
        /bitmapsave save def
        /is w string def
        /gis w string def
        /bis w string def
        /cf currentfile def 
        w h 8 [w 0 0 h neg 0 h] 
        { cf is readhexstring pop 
          cf gis readhexstring pop 
        /cf currentfile def
        w h 8 [w 0 0 h neg 0 h]
        { cf is readhexstring pop
          cf gis readhexstring pop
          cf bis readhexstring pop w gray}  image
        bitmapsave restore 
        bitmapsave restore
        grestore
        } bind def
/BITMAPGRAY { 
/BITMAPGRAY {
	8 {fakecolorsetup} COMMONBITMAP
	} bind def
/BITMAPGRAYc { 
/BITMAPGRAYc {
	8 {fakecolorsetup} COMMONBITMAPc
	} bind def
/ENDBITMAP {
	} bind def
end 
end
	/ALDsave FMLOCAL
	/ALDmatrix matrix def ALDmatrix currentmatrix pop
/StartALD {
	/ALDsave save def
	 savematrix
	 ALDmatrix setmatrix
	} bind def
1380
1381
1382
1383
1384
1385
1386
1387

1388
1389
1390
1391
1392
1393
1394
1380
1381
1382
1383
1384
1385
1386

1387
1388
1389
1390
1391
1392
1393
1394







-
+







-0.27 ( binding, and) 457.95 580 P
(a binding on) 152.1 567.89 T
5 F
(<Control-a>) 204.57 567.89 T
3 F
( takes precedence over a binding on) 270.54 567.89 T
5 F
(<KeyPress>.) 416.24 567.89 T
(<Key>.) 416.24 567.89 T
3 F
-0.26 (The mechanism for con\337ict resolution is similar in Tk 4.0 except that one binding can) 170.1 555.89 P
-0.35 (trigger for) 152.1 543.78 P
2 F
-0.35 (each) 194.7 543.78 P
3 F
-0.35 ( binding tag on the window where the event occurs. The bindings trigger in) 213.57 543.78 P
1574
1575
1576
1577
1578
1579
1580
1581

1582
1583
1584
1585
1586
1587
1588
1589
1590

1591
1592
1593
1594
1595
1596
1597
1574
1575
1576
1577
1578
1579
1580

1581
1582
1583
1584
1585
1586
1587
1588
1589

1590
1591
1592
1593
1594
1595
1596
1597







-
+








-
+







5 F
(Control) 391.17 608.33 T
3 F
(, or any combina-) 433.15 608.33 T
(tion of them. If you wish for a binding not to trigger when a modi\336er is present, you can) 152.1 596.33 T
(just de\336ne an empty binding for that modi\336er combination. For example,) 152.1 584.33 T
5 9 Q
(bind .b <Control-ButtonPress-1> {# this script is a no-op}) 179.1 570 T
(bind .b <Control-Button-1> {# this script is a no-op}) 179.1 570 T
3 10 Q
(creates a binding that will trigger on mouse button presses when the) 152.1 556.33 T
5 F
(Control) 426.36 556.33 T
3 F
( key is) 468.34 556.33 T
-0.22 (down. If there is also a) 152.1 544.33 P
5 F
-0.52 (<ButtonPress-1>) 244.35 544.33 P
-0.52 (<Button-1>) 244.35 544.33 P
3 F
-0.22 ( binding for) 334.3 544.33 P
5 F
-0.52 (.b) 383.35 544.33 P
3 F
-0.22 (, it will no longer be invoked) 395.34 544.33 P
-0.02 (if the) 152.1 532.33 P
Changes to doc/tk_mac.n.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 2011 Kevin Walzer.
'\" Copyright (c) 2011 Donal K. Fellows.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\"
.TH tk::mac n 8.6 Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
tk::mac \- Access Mac-Specific Functionality on OS X from Tk
.SH SYNOPSIS
44
45
46
47
48
49
50
51

52
53
54

55
56
57
58
59
60
61
44
45
46
47
48
49
50

51
52
53

54
55
56
57
58
59
60
61







-
+


-
+







The Aqua/Mac OS X application environment defines a number of additional
events that applications should respond to. These events are mapped by Tk to
calls to commands in the \fB::tk::mac\fR namespace; unless otherwise noted, if
the command is absent, no action will be taken.
.TP
\fB::tk::mac::DoScriptFile\fR
.
The default Apple Event handler for AEDoScriptHandler. This command 
The default Apple Event handler for AEDoScriptHandler. This command
executes a Tcl file when an AppleScript sends a
.QW "do script"
command to Wish with a file path as a parameter. 
command to Wish with a file path as a parameter.
.TP
\fB::tk::mac::DoScriptText\fR
.
The default Apple Event handler for AEDoScriptHandler. This command
executes Tcl code when an AppleScript sends a
.QW "do script"
command to Wish with Tcl code or a Tcl procedure as a parameter.
127
128
129
130
131
132
133
134

135
136
137
138
139
140
141
127
128
129
130
131
132
133

134
135
136
137
138
139
140
141







-
+







.TP
\fB::tk::mac::PrintDocument \fIfile...\fR
.
If a proc of this name is defined it is the default Apple Event handler for
kAEPrintDocuments,
.QW pdoc ,
the Apple Event sent when your application is asked to print a
document.  It takes a single absolute file path as an argument. 
document.  It takes a single absolute file path as an argument.
.TP
\fB::tk::mac::Quit\fR
.
If a proc of this name is defined it is the default Apple Event handler for
kAEQuitApplication,
.QW quit ,
the Apple Event sent when your application is asked to be quit, e.g. via the
161
162
163
164
165
166
167
168
169


170
171
172
173
174
175
176

177
178
179
180
181
182
183
184
185
186
187

188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206

207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224








225



226
227
228
229
230
231
232
161
162
163
164
165
166
167


168
169
170
171
172
173
174
175

176
177
178
179
180
181
182
183
184
185
186

187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205

206
207
208
209
210
211
212
213
214
215
216
217
218
219
220




221
222
223
224
225
226
227
228

229
230
231
232
233
234
235
236
237
238







-
-
+
+






-
+










-
+


















-
+














-
-
-
-
+
+
+
+
+
+
+
+
-
+
+
+







.QW "YourApp Help"
performs the default Cocoa action of showing the Help Book configured in the
application's Info.plist (or displaying an alert if no Help Book is
set).
.TP
\fB::tk::mac::PerformService\fR
.
Executes a Tcl procedure called from the macOS 
.QW Services 
Executes a Tcl procedure called from the macOS
.QW Services
menu in the Application menu item. The
.QW Services
menu item allows for inter-application communication; data from one
application, such as selected text, can be sent to another application
for processing, for example to Safari as a search item for Google, or
to TextEdit to be appended to a file. An example of the proc is below,
and should be rewritten in an application script for customization: 
and should be rewritten in an application script for customization:
.RS
.PP
.CS
proc ::tk::mac::PerformService {} {
    set data [clipboard get]
    $w insert end $data
}
.CE
.RE
Note that the mechanism for retrieving the data is from the clipboard;
there is no other supported way to obtain the data.  If the Services 
there is no other supported way to obtain the data.  If the Services
process is not desired, the NSServices keys can be deleted from
the application's Info.plist file. The underlying code supporting this
command also allows the text, entry and ttk::entry widgets to access
services from other applications via the Services menu. The NSPortName
key in Wish's Info.plist file is currently set as
.QW "Wish"
; if a developer changes the name of the Wish executable to something
  else, this key should be modified with the same name.
.TP
\fB::tk::mac::LaunchURL \fIURL...\fR
.
If defined, launches a URL within Tk. This would be used if a Tk
application wants to handle a URL itself, such as displaying data from
an RSS feed, rather than launching a default application to handle the
URL, although it can defined as such. Wish includes a stub URL scheme
of
.QW foo://
in the CFBundleURLSchemes key of its Info.plist file; this should be customized for the specific URL
scheme the developer wants to support. 
scheme the developer wants to support.
.TP
\fB::tk::mac::GetAppPath\fR
.
Returns the current applications's file path.
.TP


.SH "ADDITIONAL DIALOGS"
.PP
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
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:]
Info.plist keys and app bundle files used by the about panel.
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
\fB::tk::mac::useCompatibilityMetrics \fIboolean\fR
.
Changes to doc/tkvars.n.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1990-1994 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH tkvars n 4.1 Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
geometry, tk_library, tk_patchLevel, tk_strictMotif, tk_version \- Variables used or set by Tk
.BE
46
47
48
49
50
51
52
53

54
55
56
57
58
59
60
46
47
48
49
50
51
52

53
54
55
56
57
58
59
60







-
+







Contains a dot-separated sequence of decimal integers giving the
current patch level for Tk.
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.
If an application sets it to one, then Tk attempts to adhere as
closely as possible to Motif look-and-feel standards.
Changes to doc/tkwait.n.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1992 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH tkwait n "" Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
tkwait \- Wait for variable to change or window to be destroyed
.SH SYNOPSIS
Changes to doc/toplevel.n.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27











28
29
30
31
32
33
34
1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45






-
+




















+
+
+
+
+
+
+
+
+
+
+







'\"
'\" Copyright (c) 1990-1994 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH toplevel n 8.4 Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
toplevel \- Create and manipulate 'toplevel' main and popup window widgets
.SH SYNOPSIS
\fBtoplevel\fR \fIpathName \fR?\fIoptions\fR?
.SO
\-borderwidth	\-highlightcolor	\-pady
\-cursor	\-highlightthickness	\-relief
\-highlightbackground	\-padx	\-takefocus
.SE
.SH "WIDGET-SPECIFIC OPTIONS"
.OP \-background background Background
This option is the same as the standard \fB\-background\fR option
except that its value may also be specified as an empty string.
In this case, the widget will display no background or border, and
no colors will be consumed from its colormap for its background
and border.
.VS "8.7, TIP262"
An empty background will disable drawing the background image.
.OP \-backgroundimage backgroundImage BackgroundImage
This specifies an image to display on the toplevel's background within
the border of the toplevel (i.e., the image will be clipped by the
toplevel's highlight ring and border, if either are present) on top of
the background;
subwidgets of the toplevel will be drawn on top. The image must have
been created with the \fBimage create\fR command. If specified as the
empty string, no image will be displayed.
.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.
The \fB\-class\fR option may not be changed with the \fBconfigure\fR
widget command.
67
68
69
70
71
72
73









74
75
76
77
78
79
80
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100







+
+
+
+
+
+
+
+
+







Specifies the screen on which to place the new window.
Any valid screen name may be used, even one associated with a
different display.
Defaults to the same screen as its parent.
This option is special in that it may not be specified via the option
database, and it may not be modified with the \fBconfigure\fR
widget command.
.OP \-tile tile Tile
.VS "8.7, TIP262"
This specifies how to draw the background image (see
\fB\-backgroundimage\fR) on the toplevel.
If true (according to \fBTcl_GetBoolean\fR), the image will be tiled
to fill the whole toplevel, with the origin of the first copy of the
image being the top left of the interior of the toplevel.
If false (the default), the image will be centered within the toplevel.
.VE "8.7, TIP262"
.OP \-use use Use
This option is used for embedding. If the value is not an empty string,
it must be the window identifier of a container window, specified as
a hexadecimal string like the ones returned by the \fBwinfo id\fR
command. The toplevel widget will be created as a child of the given
container instead of the root window for the screen.  If the container
window is in a Tk application, it must be a frame or toplevel widget for
105
106
107
108
109
110
111
112

113
114
115
116
117
118
119
120
121
122

123
124
125
126
127
128
129
125
126
127
128
129
130
131

132
133
134
135
136
137
138
139
140
141

142
143
144
145
146
147
148
149







-
+









-
+







path name of the new window.
.PP
A toplevel is similar to a \fBframe\fR except that it is created as a
top-level window:  its X parent is the root window of a screen
rather than the logical parent from its Tk path name.  The primary
purpose of a toplevel is to serve as a container for dialog boxes
and other collections of widgets.  The only visible features
of a toplevel are its background color and an optional 3-D border
of a toplevel are its background and an optional 3-D border
to make the toplevel appear raised or sunken.
.SH "WIDGET COMMAND"
.PP
The \fBtoplevel\fR command creates a new Tcl command whose
name is the same as the path name of the toplevel's window.  This
command may be used to invoke various
operations on the widget.  It has the following general form:
.PP
.CS
\fIpathName option \fR?\fIarg arg ...\fR?
\fIpathName option \fR?\fIarg ...\fR?
.CE
.PP
\fIPathName\fR is the name of the command, which is the same as
the toplevel widget's path name.  \fIOption\fR and the \fIarg\fRs
determine the exact behavior of the command.  The following
commands are possible for toplevel widgets:
.TP
Changes to doc/ttk_Geometry.3.
62
63
64
65
66
67
68

69
70

71
72
73
74
75
76
77
78
79
80
81

82
83

84
85
86
87
88

89
90
91
92
93
94
95
96
97
98

99
100
101
102
103
104




105
106
107
108
109
110
111
62
63
64
65
66
67
68
69
70

71
72
73
74
75
76
77
78
79
80
81
82
83
84

85
86
87
88
89

90
91
92
93
94
95
96
97
98
99

100
101
102




103
104
105
106
107
108
109
110
111
112
113







+

-
+











+

-
+




-
+









-
+


-
-
-
-
+
+
+
+







.AP "Ttk_Box *" cavity in/out
A rectangular region from which a parcel is allocated.
.AP short border in
Extra padding (in pixels) to add uniformly to each side of a region.
.AP short bottom in
Extra padding (in pixels) to add to the bottom of a region.
.AP Ttk_Box box in
Specifies a rectangular region.
.AP "Ttk_Box *" box_rtn out
Specifies a rectangular region.
A rectangular region.
.AP int height in
The height in pixels of a region.
.AP "Tcl_Interp *" interp in
Used to store error messages.
.AP int left in
Extra padding (in pixels) to add to the left side of a region.
.AP "Tcl_Obj *" objPtr in
String value contains a symbolic name
to be converted to an enumerated value or bitmask.
Internal rep may be be modified to cache corresponding value.
.AP Ttk_Padding padding in
Extra padding to add on the inside of a region.
.AP "Ttk_Padding *" padding_rtn out
Extra padding to add on the inside of a region.
Padding present in the inside of a region.
.AP Ttk_Box parcel in
A rectangular region, allocated from a cavity.
.AP int relief in
One of the standard Tk relief options
(TK_RELIEF_RAISED, TK_RELIEF_SUNKEN, etc.).
(\fBTK_RELIEF_RAISED\fR, \fBTK_RELIEF_SUNKEN\fR, etc.).
See \fBTk_GetReliefFromObj\fR.
.AP short right in
Extra padding (in pixels) to add to the right side of a region.
.AP Ttk_Side side in
One of \fBTTK_SIDE_LEFT\fR, \fBTTK_SIDE_TOP\fR,
\fBTTK_SIDE_RIGHT\fR, or \fBTTK_SIDE_BOTTOM\fR.
.AP unsigned sticky in
A bitmask containing one or more of the bits
\fBTTK_STICK_W\fR (west, or left),
\fBTTK_STICK_E\fR (east, or right,
\fBTTK_STICK_E\fR (east, or right),
\fBTTK_STICK_N\fR (north, or top), and
\fBTTK_STICK_S\fR (south, or bottom).
\fBTTK_FILL_X\fR is defined as a synonym for (TTK_STICK_W|TTK_STICK_E),
\fBTTK_FILL_Y\fR is a synonym for (TTK_STICK_N|TTK_STICK_S),
and  \fBTTK_FILL_BOTH\fR and \fBTTK_STICK_ALL\fR
are synonyms for (TTK_FILL_X|TTK_FILL_Y).
\fBTTK_FILL_X\fR is defined as a synonym for (\fBTTK_STICK_W\fR|\fBTTK_STICK_E\fR),
\fBTTK_FILL_Y\fR is a synonym for (\fBTTK_STICK_N\fR|\fBTTK_STICK_S\fR),
and  \fBTTK_FILL_BOTH\fR
is a synonym for (\fBTTK_FILL_X\fR|\fBTTK_FILL_Y\fR).
See also: \fIgrid(n)\fR.
.AP Tk_Window tkwin in
Window whose screen geometry determines
the conversion between absolute units and pixels.
.AP short top in
Extra padding at the top of a region.
.AP int width in
Changes to doc/ttk_Theme.3.
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







'\"
'\" Copyright (c) 2003 Joe English
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\"
.TH Ttk_CreateTheme 3 8.5 Tk "Tk Themed Widget"
.so man.macros
.BS
.SH NAME
Ttk_CreateTheme, Ttk_GetTheme, Ttk_GetDefaultTheme, Ttk_GetCurrentTheme \- create and use Tk themes.
.SH SYNOPSIS
.nf
Changes to doc/ttk_button.n.
13
14
15
16
17
18
19
20

21
22
23
24
25
26
27
13
14
15
16
17
18
19

20
21
22
23
24
25
26
27







-
+







\fBttk::button\fR \fIpathName \fR?\fIoptions\fR?
.BE
.SH DESCRIPTION
A \fBttk::button\fR widget displays a textual label and/or image,
and evaluates a command when pressed.
.SO ttk_widget
\-class	\-compound	\-cursor
\-image	\-state	\-style
\-image	\-justify	\-state	\-style
\-takefocus	\-text	\-textvariable
\-underline	\-width
.SE
.SH "WIDGET-SPECIFIC OPTIONS"
.OP \-command command Command
A script to evaluate when the widget is invoked.
.OP \-default default Default
44
45
46
47
48
49
50
51
52




53
54
55
56
57
58
59
44
45
46
47
48
49
50


51
52
53
54
55
56
57
58
59
60
61







-
-
+
+
+
+







.\" .OP \-foreground foreground Foreground
.\" .OP \-font font Font
.\" .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
\fBTtk::button\fR widgets support the \fBToolbutton\fR style in all standard
themes, which is useful for creating widgets for toolbars.
Changes to doc/ttk_checkbutton.n.
33
34
35
36
37
38
39
40
41




42
43
44
45
46
47
48
49
33
34
35
36
37
38
39


40
41
42
43

44
45
46
47
48
49
50







-
-
+
+
+
+
-







when the widget is selected.  Defaults to \fB1\fR.
.OP \-variable variable Variable
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
\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:
widget 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
to the \fB\-offvalue\fR and deselects the widget;
otherwise, sets the \fB\-variable\fR to the \fB\-onvalue\fR
Changes to doc/ttk_combobox.n.
15
16
17
18
19
20
21
22

23
24
25
26
27
28
29
15
16
17
18
19
20
21

22
23
24
25
26
27
28
29







-
+







.SH DESCRIPTION
.PP
A \fBttk::combobox\fR combines a text field with a pop-down list of values;
the user may select the value of the text field from among the
values in the list.
.SO ttk_widget
\-class	\-cursor	\-takefocus
\-style
\-style	\-placeholder	\-placeholderforeground
.SE
.\" ALSO: Other entry widget options
.SH "WIDGET-SPECIFIC OPTIONS"
.OP \-exportselection exportSelection ExportSelection
Boolean value.
If set, the widget selection is linked to the X selection.
.OP \-justify justify Justify
51
52
53
54
55
56
57
58

59
60

61
62


63
64
65

66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95

96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
51
52
53
54
55
56
57

58


59


60
61



62

63
64
65
66
67
68
69
70
71
72
73








74
75
76




77
78

79
80
81
82
83
84
85







86
87
88
89
90
91
92







-
+
-
-
+
-
-
+
+
-
-
-
+
-











-
-
-
-
-
-
-
-



-
-
-
-


-
+






-
-
-
-
-
-
-







.OP \-values values Values
Specifies the list of values to display in the drop-down listbox.
.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:
In addition to the standard
'\".TP
'\"\fIpathName \fBcget\fR \fIoption\fR
\fBcget\fR, \fBconfigure\fR, \fBidentify element\fR, \fBinstate\fR,
'\"Returns the current value of the specified \fIoption\fR.
'\"See \fIttk::widget(n)\fR.
\fBstate\fR and \fBstyle\fR
commands (see \fBttk::widget\fR),
'\".TP
'\"\fIpathName \fBconfigure\fR ?\fIoption\fR? ?\fIvalue option value ...\fR?
'\"Modify or query widget options.
combobox widgets support the following additional commands:
'\"See \fIttk::widget(n)\fR.
.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
the last element of the list).
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<<ComboboxSelected>>\fR virtual event
when the user selects an element from the list of values.
If the selection action unposts the listbox,
this event is delivered after the listbox is unposted.
.SH "STYLING OPTIONS"
138
139
140
141
142
143
144


145
146
147
148
149


150
151
152
153
154
155
156
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137







+
+





+
+







.br
\fB\-foreground\fP \fIcolor\fP
.br
\fB\-fieldbackground\fP \fIcolor\fP
.RS
Can only be changed when using non-native and non-graphical themes.
.RE
\fB\-insertcolor\fP \fIcolor\fP
.br
\fB\-insertwidth\fP \fIamount\fP
.br
\fB\-lightcolor\fP \fIcolor\fP
.br
\fB\-padding\fP \fIpadding\fP
.br
\fB\-placeholderforeground\fP \fIcolor\fP
.br
\fB\-postoffset\fP \fIpadding\fP
.br
\fB\-selectbackground\fP \fIcolor\fP
.RS
Text entry select background.
.RE
Changes to doc/ttk_entry.n.
19
20
21
22
23
24
25
26
27




28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
19
20
21
22
23
24
25


26
27
28
29
30
31
32
33
34
35
36
37
38


39
40
41
42
43
44
45







-
-
+
+
+
+









-
-







An \fBttk::entry\fR widget displays a one-line text string and
allows that string to be edited by the user.
The value of the string may be linked to a Tcl variable
with the \fB\-textvariable\fR option.
Entry widgets support horizontal scrolling with the
standard \fB\-xscrollcommand\fR option and \fBxview\fR widget command.
.SO ttk_widget
\-class	\-cursor	\-style
\-takefocus	\-xscrollcommand
\-class	\-cursor
\-font	\-foreground
\-style
\-takefocus	\-xscrollcommand	\-placeholder	\-placeholderforeground
.SE
.SH "WIDGET-SPECIFIC OPTIONS"
.OP \-exportselection exportSelection ExportSelection
A boolean value specifying whether or not
a selection in the widget should be linked to the X selection.
If the selection is exported, then selecting in the widget deselects
the current X selection, selecting outside the widget deselects any
widget selection, and the widget will respond to selection retrieval
requests when it has a selection.
.\" MAYBE: .OP \-font font Font
.\" MAYBE: .OP \-foreground foreground Foreground
.\" MAYBE: .OP \-insertbackground insertBackground Foreground
.\" MAYBE: .OP \-insertwidth insertWidth InsertWidth
.OP \-invalidcommand invalidCommand InvalidCommand
A script template to evaluate whenever the \fB\-validatecommand\fR returns 0.
See \fBVALIDATION\fR below for more information.
.OP \-justify justify Justify
Specifies how the text is aligned within the entry widget.
135
136
137
138
139
140
141




142

143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
135
136
137
138
139
140
141
142
143
144
145

146
147
148
149
150
151
152
153
154
155
156








157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172




173
174
175
176
177
178
179




180
181
182
183
184
185
186







+
+
+
+
-
+










-
-
-
-
-
-
-
-
















-
-
-
-







-
-
-
-







.QW \fBe\fR
or
.QW \fBsel.l\fR .
In general, out-of-range indices are automatically rounded to the
nearest legal value.
.SH "WIDGET COMMAND"
.PP
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),
The following subcommands are possible for entry widgets:
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
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
one to delete.
If \fIlast\fR is not specified it defaults to \fIfirst\fR+1,
i.e. a single character is deleted.
This command returns the empty string.
.TP
\fIpathName \fBget\fR
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
.TP
\fIpathName \fBselection clear\fR
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
195
196
197
198
199
200
201




202
203
204
205
206
207
208








209
210
211
212
213
214
215







-
-
-
-







-
-
-
-
-
-
-
-







\fIpathName \fBselection range \fIstart\fR \fIend\fR
Sets the selection to include the characters starting with
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"
.PP
There are two main validation modes: \fIprevalidation\fR,
349
350
351
352
353
354
355
356
357
358




359
360
361
362
363
364
365
325
326
327
328
329
330
331



332
333
334
335
336
337
338
339
340
341
342







-
-
-
+
+
+
+







.IP \0\(bu 4
Clicking mouse button 1 with the Control key down will position the
insert cursor in the entry without affecting the selection.
.IP \0\(bu 4
If any normal printing characters are typed in an entry, they are
inserted at the point of the insert cursor.
.IP \0\(bu 4
The view in the entry can be adjusted by dragging with mouse button 2.
If mouse button 2 is clicked without moving the mouse, the selection
is copied into the entry at the position of the mouse cursor.
The view in the entry can be adjusted by dragging with the middle
mouse button (button 2, or button 3 in TkAqua). If the middle mouse
button is clicked without moving the mouse, the selection is copied
into the entry at the position of the mouse cursor.
.IP \0\(bu 4
If the mouse is dragged out of the entry on the left or right sides
while button 1 is pressed, the entry will automatically scroll to
make more text visible (if there is more text off-screen on the side
where the mouse left the window).
.IP \0\(bu 4
The Left and Right keys move the insert cursor one character to the
442
443
444
445
446
447
448


449
450
451
452
453
454


455
456
457
458
459
460
461
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442







+
+






+
+







\fB\-darkcolor\fP \fIcolor\fP
.br
\fB\-fieldbackground\fP \fIcolor\fP
.RS
Some themes use a graphical background and their field background colors cannot be changed.
.RE
\fB\-foreground\fP \fIcolor\fP
.br
\fB\-insertcolor\fP \fIcolor\fP
.br
\fB\-insertwidth\fP \fIamount\fP
.br
\fB\-lightcolor\fP \fIcolor\fP
.br
\fB\-padding\fP \fIpadding\fP
.br
\fB\-placeholderforeground\fP \fIcolor\fP
.br
\fB\-relief\fP \fIrelief\fP
.br
\fB\-selectbackground\fP \fIcolor\fP
.br
\fB\-selectborderwidth\fP \fIamount\fP
.br
Changes to doc/ttk_frame.n.
31
32
33
34
35
36
37
38
39
40




41
42
43
44
45
46
47
31
32
33
34
35
36
37



38
39
40
41
42
43
44
45
46
47
48







-
-
-
+
+
+
+







Defaults to \fBflat\fR.
.OP \-width width Width
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
over the \fBframe\fR widget's \fB\-width\fR and \fB\-height\fR options.
\fBpack propagate\fR and \fBgrid propagate\fR can be used
Changes to doc/ttk_intro.n.
82
83
84
85
86
87
88
89

90
91
92
93
94
95
96
82
83
84
85
86
87
88

89
90
91
92
93
94
95
96







-
+







For example, the layout for a horizontal scrollbar is:
.PP
.CS
ttk::\fBstyle layout\fR Horizontal.TScrollbar {
    Scrollbar.trough \-children {
	Scrollbar.leftarrow \-side left \-sticky w
	Scrollbar.rightarrow \-side right \-sticky e
	Scrollbar.thumb \-side left \-expand true \-sticky ew
	Scrollbar.thumb \-sticky ew
    }
}
.CE
.PP
By default, the layout for a widget is the same as its class name.
Some widgets may override this (for example, the \fBttk::scrollbar\fR
widget chooses different layouts based on the \fB\-orient\fR option).
117
118
119
120
121
122
123
124

125
126
127
128
129
130
131
117
118
119
120
121
122
123

124
125
126
127
128
129
130
131







-
+







.PP
For example, the class bindings for the \fBttk::button\fR
widget are:
.PP
.CS
bind TButton <Enter>		{ %W state active }
bind TButton <Leave>		{ %W state !active }
bind TButton <ButtonPress-1>	{ %W state pressed }
bind TButton <Button-1>		{ %W state pressed }
bind TButton <Button1-Leave>	{ %W state !pressed }
bind TButton <Button1-Enter>	{ %W state pressed }
bind TButton <ButtonRelease-1>	\e
    { %W instate {pressed} { %W state !pressed ; %W invoke } }
.CE
.PP
This specifies that the widget becomes \fBactive\fR when
Changes to doc/ttk_label.n.
14
15
16
17
18
19
20
21
22



23
24

25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62




63
64
65
66
67
68
69
14
15
16
17
18
19
20


21
22
23
24

25
26
27






28
29
30










31
32
33
34
35
36
37
38
39
40
41
42
43
44



45
46
47
48
49
50
51
52
53
54
55







-
-
+
+
+

-
+


-
-
-
-
-
-



-
-
-
-
-
-
-
-
-
-














-
-
-
+
+
+
+







.BE
.SH DESCRIPTION
.PP
A \fBttk::label\fR widget displays a textual label and/or image.
The label may be linked to a Tcl variable
to automatically change the displayed text.
.SO ttk_widget
\-class	\-compound	\-cursor
\-image	\-padding	\-state	\-style	\-takefocus
\-anchor	\-class	\-compound	\-cursor
\-font	\-foreground
\-image	\-justify	\-padding	\-state	\-style	\-takefocus
\-text	\-textvariable	\-underline
\-width
\-width	\-wraplength
.SE
.SH "WIDGET-SPECIFIC OPTIONS"
.OP \-anchor anchor Anchor
Specifies how the information in the widget is positioned
relative to the inner margins.  Legal values are
\fBn\fR, \fBne\fR, \fBe\fR, \fBse\fR,
\fBs\fR, \fBsw\fR, \fBw\fR, \fBnw\fR, and \fBcenter\fR.
See also \fB\-justify\fR.
.OP \-background frameColor FrameColor
The widget's background color.
If unspecified, the theme default is used.
.OP \-font font Font
Font to use for label text.
.OP \-foreground textColor TextColor
The widget's foreground color.
If unspecified, the theme default is used.
.OP \-justify justify Justify
If there are multiple lines of text, specifies how
the lines are laid out relative to one another.
One of \fBleft\fR, \fBcenter\fR, or \fBright\fR.
See also \fB\-anchor\fR.
.OP \-relief relief Relief
.\" Rewrite this:
Specifies the 3-D effect desired for the widget border.
Valid values are
\fBflat\fR, \fBgroove\fR, \fBraised\fR, \fBridge\fR, \fBsolid\fR,
and \fBsunken\fR.
.OP \-wraplength wrapLength WrapLength
Specifies the maximum line length (in pixels).
If this option is less than or equal to zero,
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.
.PP
\fBTLabel\fP styling options configurable with \fBttk::style\fP
Changes to doc/ttk_labelframe.n.
58
59
60
61
62
63
64
65
66
67




68
69
70
71
72
73
74
58
59
60
61
62
63
64



65
66
67
68
69
70
71
72
73
74
75







-
-
-
+
+
+
+







The underlined character is used for mnemonic activation.
Mnemonic activation for a \fBttk::labelframe\fR
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.
.PP
Dynamic states: \fBdisabled\fP, \fBreadonly\fP.
Changes to doc/ttk_menubutton.n.
34
35
36
37
38
39
40
41
42
43




44
45
46
47
48
49
50
34
35
36
37
38
39
40



41
42
43
44
45
46
47
48
49
50
51







-
-
-
+
+
+
+







To be on the safe side, the menu ought to be a direct child of the
menubutton.
.\" 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"
.PP
The class name for a \fBttk::menubutton\fP is \fBTMenubutton\fP.
Changes to doc/ttk_notebook.n.
16
17
18
19
20
21
22
23

24
25
26
27
28
29
30
16
17
18
19
20
21
22

23
24
25
26
27
28
29
30







-
+







\fIpathname \fBadd\fR \fIwindow\fR ?\fIoptions...\fR?
\fIpathname \fBinsert\fR \fIindex\fR \fIwindow\fR ?\fIoptions...\fR?
.fi
.BE
.SH DESCRIPTION
A \fBttk::notebook\fR widget manages a collection of windows
and displays a single one at a time.
Each slave window is associated with a \fItab\fR,
Each content window is associated with a \fItab\fR,
which the user may select to change the currently-displayed window.
.SO ttk_widget
\-class	\-cursor	\-takefocus
\-style
.SE
.SH "WIDGET-SPECIFIC OPTIONS"
.OP \-height height Height
52
53
54
55
56
57
58
59

60
61
62
63

64
65
66
67
68
69
70
52
53
54
55
56
57
58

59
60
61
62

63
64
65
66
67
68
69
70







-
+



-
+







.SH "TAB OPTIONS"
The following options may be specified for individual notebook panes:
.OP \-state state State
Either \fBnormal\fR, \fBdisabled\fR or \fBhidden\fR.
If \fBdisabled\fR, then the tab is not selectable.
If \fBhidden\fR, then the tab is not shown.
.OP \-sticky sticky Sticky
Specifies how the slave window is positioned within the pane area.
Specifies how the content window is positioned within the pane area.
Value is a string containing zero or more of the characters
\fBn, s, e,\fR or \fBw\fR.
Each letter refers to a side (north, south, east, or west)
that the slave window will
that the content window will
.QW stick
to, as per the \fBgrid\fR geometry manager.
.OP \-padding padding Padding
Specifies the amount of extra space to add between the notebook and this pane.
Syntax is the same as for the widget \fB\-padding\fR option.
.OP \-text text Text
Specifies a string to be displayed in the tab.
82
83
84
85
86
87
88
89

90
91
92
93
94
95
96
97
98
99
100
101
102
103
104






105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
82
83
84
85
86
87
88

89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117






118
119
120
121
122
123
124







-
+















+
+
+
+
+
+







-
-
-
-
-
-







if \fBttk::notebook::enableTraversal\fR is called.
.SH "TAB IDENTIFIERS"
The \fItabid\fR argument to the following commands may take
any of the following forms:
.IP \(bu
An integer between zero and the number of tabs;
.IP \(bu
The name of a slave window;
The name of a content window;
.IP \(bu
A positional specification of the form
.QW @\fIx\fR,\fIy\fR ,
which identifies the tab
.IP \(bu
The literal string
.QW \fBcurrent\fR ,
which identifies the currently-selected tab; or:
.IP \(bu
The literal string
.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
Hides the tab specified by \fItabid\fR.
The tab will not be displayed, but the associated window
147
148
149
150
151
152
153
154
155
156
157
158
159

160
161
162
163
164
165
166
167
168
169
170
171
172
173
147
148
149
150
151
152
153



154
155

156
157
158
159
160



161
162
163
164
165
166
167







-
-
-


-
+




-
-
-







Inserts a pane at the specified position.
\fIpos\fR is either the string \fBend\fR, an integer index,
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 slave window will be displayed,
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,
returns the value of that \fIoption\fR.
Otherwise, sets the \fI\-option\fRs to the corresponding \fIvalue\fRs.
Changes to doc/ttk_panedwindow.n.
44
45
46
47
48
49
50


51
52
53




54
55
56
57
58
59
60
44
45
46
47
48
49
50
51
52



53
54
55
56
57
58
59
60
61
62
63







+
+
-
-
-
+
+
+
+







.SH "PANE OPTIONS"
The following options may be specified for each pane:
.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"
.PP
In addition to the standard
Supports the standard \fBconfigure\fR, \fBcget\fR, \fBstate\fR,
and \fBinstate\fR commands; see \fIttk::widget(n)\fR for details.
Additional commands:
\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
\fIpathname \fBforget \fIpane\fR
Removes the specified subpane from the widget.
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
105
106
107
108
109
110
111








112
113
114
115
116
117
118







-
-
-
-
-
-
-
-







Sash positions are further constrained to be between 0
and the total size of the widget.
.\" 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<<EnteredChild>>\fR virtual event on
LeaveNotify/NotifyInferior events, because Tk does not execute binding scripts
for <Leave> events when the pointer crosses from a parent to a child. The
panedwindow widget needs to know when that happens.
.SH "STYLING OPTIONS"
Changes to doc/ttk_progressbar.n.
15
16
17
18
19
20
21






22
23
24



25
26
27
28
29


30
31
32
33
34
35
36
15
16
17
18
19
20
21
22
23
24
25
26
27
28


29
30
31
32
33
34
35

36
37
38
39
40
41
42
43
44







+
+
+
+
+
+

-
-
+
+
+




-
+
+







.SH DESCRIPTION
.PP
A \fBttk::progressbar\fR widget shows the status of a long-running
operation.  They can operate in two modes: \fIdeterminate\fR mode shows the
amount completed relative to the total amount of work to be done, and
\fIindeterminate\fR mode provides an animated display to let the user know
that something is happening.
.PP
If the value of \fB-orient\fR is \fBhorizontal\fR a text string can be
displayed inside the progressbar. This string can be configured using
the \fB-anchor\fR, \fB-font\fR, \fB-foreground\fR, \fB-justify\fR,
\fB-text\fR and \fB-wraplength\fR options. If the value of \fB-orient\fR
is \fBvertical\fR then these options are ignored.
.SO ttk_widget
\-class	\-cursor	\-takefocus
\-style
\-anchor	\-class	\-cursor
\-font	\-foreground	\-justify	\-style
\-takefocus	\-text	\-wraplength
.SE
.SH "WIDGET-SPECIFIC OPTIONS"
.OP \-length length Length
Specifies the length of the long axis of the progress bar
(width if horizontal, height if vertical).
(width if horizontal, height if vertical). The value may have any of the forms
acceptable to \fBTk_GetPixels\fR.
.OP \-maximum maximum Maximum
A floating point number specifying the maximum \fB\-value\fR.
Defaults to 100.
.OP \-mode mode Mode
One of \fBdeterminate\fR or \fBindeterminate\fR.
.OP \-orient orient Orient
One of \fBhorizontal\fR or \fBvertical\fR.
54
55
56
57
58
59
60
61
62

63
64
65

66
67
68

69
70

71
72
73

74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
62
63
64
65
66
67
68


69



70



71


72



73
74
75
76
77
78
79
80



81
82
83
84
85
86
87







-
-
+
-
-
-
+
-
-
-
+
-
-
+
-
-
-
+







-
-
-







.OP \-variable variable Variable
The name of a global Tcl variable which is linked to the \fB\-value\fR.
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
In addition to the standard
Returns the current value of the specified \fIoption\fR; see \fIttk::widget(n)\fR.
.TP
\fIpathName \fBconfigure\fR ?\fIoption\fR? ?\fIvalue option value ...\fR?
\fBcget\fR, \fBconfigure\fR, \fBidentify element\fR, \fBinstate\fR,
Modify or query widget options; see \fIttk::widget(n)\fR.
.TP
\fIpathName \fBidentify \fIx y\fR
\fBstate\fR and \fBstyle\fR
Returns the name of the element at position \fIx\fR, \fIy\fR.
See \fIttk::widget(n)\fR.
commands (see \fBttk::widget\fR),
.TP
\fIpathName \fBinstate \fIstatespec\fR ?\fIscript\fR?
Test the widget state; see \fIttk::widget(n)\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
Stop autoincrement mode:
cancels any recurring timer event initiated by \fIpathName \fBstart\fR.
Changes to doc/ttk_radiobutton.n.
33
34
35
36
37
38
39
40
41




42
43
44
45
46
47
48
49
33
34
35
36
37
38
39


40
41
42
43

44
45
46
47
48
49
50







-
-
+
+
+
+
-







when the widget is selected.
.OP \-variable variable Variable
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
\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:
widget 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
string if no \fB\-command\fR is specified.
.\" Missing: select, deselect.  Useful?
Changes to doc/ttk_scale.n.
47
48
49
50
51
52
53
54
55

56
57
58



59
60
61
62

63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
47
48
49
50
51
52
53


54



55
56
57




58
59
60

61
62
63
64








65

66
67
68
69




70
71
72
73

74
75
76
77
78
79
80







-
-
+
-
-
-
+
+
+
-
-
-
-
+


-




-
-
-
-
-
-
-
-

-




-
-
-
-




-







.OP \-variable variable Variable
Specifies the name of a global variable to link to the scale. Whenever the
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
In addition to the standard
.
Returns the current value of the specified \fIoption\fR; see
\fIttk::widget(n)\fR.
\fBcget\fR, \fBconfigure\fR, \fBidentify element\fR, \fBinstate\fR,
\fBstate\fR and \fBstyle\fR
commands (see \fBttk::widget\fR),
.TP
\fIpathName \fBconfigure \fR?\fIoption\fR? ?\fIvalue option value ...\fR?
.
Modify or query widget options; see \fIttk::widget(n)\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
Changes to doc/ttk_scrollbar.n.
43
44
45
46
47
48
49
50
51

52
53
54
55




56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
43
44
45
46
47
48
49


50




51
52
53
54
55
56
57
58
59







60
61
62
63
64



65
66
67
68
69
70
71







-
-
+
-
-
-
-
+
+
+
+





-
-
-
-
-
-
-





-
-
-







or \fByview\fR (for vertical scrollbars).
.RE
.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
In addition to the standard
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.
\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
\fIpathName \fBdelta \fIdeltaX deltaY\fR
Returns a real number indicating the fractional change in
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136








137
138
139
140
141
142
143
103
104
105
106
107
108
109








110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132







-
-
-
-
-
-
-
-








+
+
+
+
+
+
+
+







The widget should adjust its view so that the point given
by \fIfraction\fR appears at the beginning of the widget.
If \fIfraction\fR is 0 it refers to the beginning of the
document.  1.0 refers to the end of the document, 0.333
refers to a point one-third of the way through the document,
and so on.
.TP
\fIprefix \fBscroll \fInumber \fBunits\fR
The widget should adjust its view by \fInumber\fR units.
The units are defined in whatever way makes sense for the widget,
such as characters or lines in a text widget.
\fINumber\fR is either 1, which means one unit should scroll off
the top or left of the window, or \-1, which means that one unit
should scroll off the bottom or right of the window.
.TP
\fIprefix \fBscroll \fInumber \fBpages\fR
The widget should adjust its view by \fInumber\fR pages.
It is up to the widget to define the meaning of a page;  typically
it is slightly less than what fits in the window, so that there
is a slight overlap between the old and new views.
\fINumber\fR is either 1, which means the next page should
become visible, or \-1, which means that the previous page should
become visible.
.TP
\fIprefix \fBscroll \fInumber \fBunits\fR
The widget should adjust its view by \fInumber\fR units.
The units are defined in whatever way makes sense for the widget,
such as characters or lines in a text widget.
\fINumber\fR is either 1, which means one unit should scroll off
the top or left of the window, or \-1, which means that one unit
should scroll off the bottom or right of the window.
.SH "WIDGET STATES"
.PP
The scrollbar automatically sets the \fBdisabled\fR state bit.
when the entire range is visible (range is 0.0 to 1.0),
and clears it otherwise.
It also sets the \fBactive\fR and \fBpressed\fR state flags
of individual elements, based on the position and state of the mouse pointer.
Changes to doc/ttk_separator.n.
22
23
24
25
26
27
28
29
30
31




32
33
34
35
36
37
38
22
23
24
25
26
27
28



29
30
31
32
33
34
35
36
37
38
39







-
-
-
+
+
+
+







.SE
.SH "WIDGET-SPECIFIC OPTIONS"
.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
\fBTSeparator\fP styling options configurable with \fBttk::style\fP
are:
Changes to doc/ttk_sizegrip.n.
19
20
21
22
23
24
25
26
27
28




29
30
31
32
33
34
35
19
20
21
22
23
24
25



26
27
28
29
30
31
32
33
34
35
36







-
-
-
+
+
+
+







by pressing and dragging the grip.
.SO ttk_widget
\-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
the built-in grip will just mask the widget.
.SH EXAMPLES
Changes to doc/ttk_spinbox.n.
18
19
20
21
22
23
24
25

26
27
28
29
30
31
32
18
19
20
21
22
23
24

25
26
27
28
29
30
31
32







-
+







up and down buttons that are used to either modify a numeric value or
to select among a set of values. The widget implements all the features
of the \fBttk::entry\fR widget including support of the
\fB\-textvariable\fR option to link the value displayed by the widget
to a Tcl variable.
.SO ttk_widget
\-class	\-cursor	\-state	\-style
\-takefocus	\-xscrollcommand
\-takefocus	\-xscrollcommand	\-placeholder	\-placeholderforeground
.SE
.SO ttk_entry
\-validate	\-validatecommand
.SE
.SH "WIDGET-SPECIFIC OPTIONS"
.OP \-command command Command
Specifies a Tcl command to be invoked whenever a spinbutton is invoked.
103
104
105
106
107
108
109




110
111
112


113
114
115
116
117
118
119
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125







+
+
+
+



+
+







.br
\fB\-darkcolor\fP \fIcolor\fP
.br
\fB\-fieldbackground\fP \fIcolor\fP
.br
\fB\-foreground\fP \fIcolor\fP
.br
\fB\-insertcolor\fP \fIcolor\fP
.br
\fB\-insertwidth\fP \fIamount\fP
.br
\fB\-lightcolor\fP \fIcolor\fP
.br
\fB\-padding\fP \fIpadding\fP
.br
\fB\-placeholderforeground\fP \fIcolor\fP
.br
\fB\-selectbackground\fP \fIcolor\fP
.br
\fB\-selectforeground\fP \fIcolor\fP
.PP
Some options are only available for specific themes.
.PP
Changes to doc/ttk_style.n.
23
24
25
26
27
28
29



30
31
32
33
34
35
36
37
38

39
40
41
42
43
44


45
46

47
48
49

50
51
52
53
54

55
56
57
58

59
60
61
62
63
64
65
66
67
68
69
70
71
72

































73
74
75
76
77
78
79
80



81
82
83
84
85
86
87
88



89
90
91
92
93

94
95
96
97
98
99
100


101












102
103
104
105



106


107
108


109
110
111
112
113






114
115
116
117
118
119
120
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38



39






40
41


42



43



44

45




46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110


111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148

149
150
151
152
153
154





155
156
157
158
159
160
161
162
163
164
165
166
167







+
+
+






-
-
-
+
-
-
-
-
-
-
+
+
-
-
+
-
-
-
+
-
-
-

-
+
-
-
-
-
+














+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








+
+
+






-
-
+
+
+





+







+
+

+
+
+
+
+
+
+
+
+
+
+
+




+
+
+
-
+
+


+
+
-
-
-
-
-
+
+
+
+
+
+







and how they are arranged, along with dynamic and default
settings for element options.
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.
.TP
\fBttk::style map \fIstyle\fR ?\fI\-option\fB { \fIstatespec value...\fB }\fR?
Sets dynamic values of the specified option(s) in \fIstyle\fR.
If \fIstyle\fR does not exist, it is created.
Each \fIstatespec / value\fR pair is examined in order;
the value corresponding to the first matching \fIstatespec\fR
is used.
.TP
\fBttk::style lookup \fIstyle\fR \fI\-option \fR?\fIstate \fR?\fIdefault\fR??
Returns the value specified for \fI\-option\fR in style \fIstyle\fR
If only \fIstyle\fR and \fI-option\fR are specified, get the default value
for option \fI-option\fR of style \fIstyle\fR.
in state \fIstate\fR, using the standard lookup rules for element options.
\fIstate\fR is a list of state names; if omitted,
If only \fIstyle\fR is specified, get the default value for all options
it defaults to all bits off (the
.QW normal
state).
of style \fIstyle\fR.
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.
.TP
\fBttk::style layout \fIstyle\fR ?\fIlayoutSpec\fR?
\fBttk::style element\fR \fIargs\fR
Define the widget layout for style \fIstyle\fR.
See \fBLAYOUTS\fR below for the format of \fIlayoutSpec\fR.
If \fIlayoutSpec\fR is omitted, return the layout specification
for style \fIstyle\fR.
.RS
.TP
\fBttk::style element create\fR \fIelementName\fR \fItype\fR ?\fIargs...\fR?
Creates a new element in the current theme of type \fItype\fR.
The only cross-platform built-in element type is \fIimage\fR
(see \fBttk_image\fR(n)) but themes may define other element types
(see \fBTtk_RegisterElementFactory\fR). On suitable versions of Windows
an element factory is registered to create Windows theme elements
(see \fBttk_vsapi\fR(n)).
.TP
\fBttk::style element names\fR
Returns the list of elements defined in the current theme.
.TP
\fBttk::style element options \fIelement\fR
Returns the list of \fIelement\fR's options.
.RE
.TP
\fBttk::style layout \fIstyle\fR ?\fIlayoutSpec\fR?
Define the widget layout for style \fIstyle\fR.
See \fBLAYOUTS\fR below for the format of \fIlayoutSpec\fR.
If \fIlayoutSpec\fR is omitted, return the layout specification
for style \fIstyle\fR.
.TP
\fBttk::style lookup \fIstyle\fR \fI\-option \fR?\fIstate \fR?\fIdefault\fR??
Returns the value specified for \fI\-option\fR in style \fIstyle\fR
in state \fIstate\fR, using the standard lookup rules for element options.
\fIstate\fR is a list of state names; if omitted,
it defaults to all bits off (the
.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 (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 ?
Creates a new theme.  It is an error if \fIthemeName\fR already exists.
If \fB\-parent\fR is specified, the new theme will inherit
styles, elements, and layouts from the parent theme \fIbasedon\fR.
If \fB\-settings\fR is present, \fIscript\fR is evaluated in the
context of the new theme as per \fBttk::style theme settings\fR.
.TP
\fBttk::style theme names\fR
Returns a list of all known themes.
.TP
\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 names\fR
Returns a list of all known themes.
\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.
.RE
.SH LAYOUTS
.PP
A \fIlayout\fR specifies a list of elements, each followed
by one or more options specifying how to arrange the element.
The layout mechanism uses a simplified version of the \fBpack\fR
geometry manager: given an initial cavity,
each element is allocated a parcel.
Then the parcel actually used by the element is adjusted within
the allocated parcel.
Valid options are:
.\" -border should remain undocumented for now (dubious usefulness)
.\" .TP
.\" \fB\-border\fR \fIboolean\fR
.\" Specifies whether the element is drawn after its children. Defaults to 0.
.TP
\fB\-children { \fIsublayout...\fB }\fR
Specifies a list of elements to place inside the element.
.TP
\fB\-expand\fR \fIboolean\fR
Specifies whether the allocated parcel is the entire cavity. If so,
simultaneous specification of \fB\-side\fR is ignored.
Defaults to 0.
.TP
\fB\-side \fIside\fR
Specifies which side of the cavity to place the element;
one of \fBleft\fR, \fBright\fR, \fBtop\fR, or \fBbottom\fR.
For instance, \fB\-side top\fR allocates the parcel along the top of
the cavity having width and height respectively the width of the cavity
and the height of the element.
If omitted, the element occupies the entire cavity.
If omitted, the allocated parcel is the entire cavity (same effect
as \fB\-expand\fR 1).
.TP
\fB\-sticky\fR \fB[\fInswe\fB]\fR
Specifies the actual parcel position and size inside the allocated parcel.
If specified as an empty string then the actual parcel is centered in
Specifies where the element is placed inside its allocated parcel.
.TP
\fB\-children { \fIsublayout... \fB}\fR
Specifies a list of elements to place inside the element.
.\" Also: -border, -unit, -expand: may go away.
the allocated parcel. Default is \fBnswe\fR.
.\" -unit should remain undocumented for now (dubious usefulness)
.\" .TP
.\" \fB\-unit\fR \fIboolean\fR
.\" Specifies whether the element propagates its state to its children.
.\" Defaults to 0.
.PP
For example:
.CS
ttk::style layout Horizontal.TScrollbar {
    Scrollbar.trough \-children {
        Scrollbar.leftarrow \-side left
        Scrollbar.rightarrow \-side right
Changes to doc/ttk_treeview.n.
88
89
90
91
92
93
94





95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109



110
111
112
113
114
115
116







+
+
+
+
+










-
-
-







The default is \fBtree headings\fR, i.e., show all elements.
.PP
\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.
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
If \fInewchildren\fR is specified, replaces \fIitem\fR's child list
with \fInewchildren\fR.
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
158
159
160
161
162
163
164



165
166
167
168
169
170
171







-
-
-







column width may be changed by Tk in order to honor \fB\-stretch\fR
and/or \fB\-minwidth\fR, or when the widget is resized or the user drags a
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
\fIpathname \fBdetach \fIitemList\fR
Unlinks all of the specified items in \fIitemList\fR from the tree.
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
267
268
269
270
271
272
273



274
275
276
277
278
279
280







-
-
-







.RS
.PP
\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,
returns the value of that option.
Otherwise, the item's options are updated with the specified values.
334
335
336
337
338
339
340
341
342
343
344
345
346





347
348
349
350
351
352
353
354

355
356

357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374






375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
330
331
332
333
334
335
336



337
338
339
340
341
342
343
344
345
346
347
348
349
350
351

352
353

354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387





388
389
390
391
392
393







394
395
396
397
398
399
400







-
-
-



+
+
+
+
+







-
+

-
+


















+
+
+
+
+
+









-
-
-
-
-






-
-
-
-
-
-
-







With one argument, returns a dictionary of column/value pairs
for the specified \fIitem\fR.
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.
If \fItag\fR is already present for a particular item,
then the \fB\-tags\fR for that item are unchanged.
.TP
\fIpathName \fBtag bind \fItagName \fR?\fIsequence\fR? ?\fIscript\fR?
Add a Tk binding script for the event sequence \fIsequence\fR
to the tag \fItagName\fR.  When an X event is delivered to an item,
binding scripts for each of the item's \fB\-tags\fR are evaluated
in order as per \fIbindtags(n)\fR.
.RS
.PP
\fB<KeyPress>\fR, \fB<KeyRelease>\fR, and virtual events
\fB<Key>\fR, \fB<KeyRelease>\fR, and virtual events
are sent to the focus item.
\fB<ButtonPress>\fR, \fB<ButtonRelease>\fR, and \fB<Motion>\fR events
\fB<Button>\fR, \fB<ButtonRelease>\fR, and \fB<Motion>\fR events
are sent to the item under the mouse pointer.
No other event types are supported.
.PP
The binding \fIscript\fR undergoes \fB%\fR-substitutions before
evaluation; see \fBbind(n)\fR for details.
.RE
.TP
\fIpathName \fBtag configure \fItagName\fR ?\fIoption\fR? ?\fIvalue option value...\fR?
Query or modify the options for the specified \fItagName\fR.
If one or more \fIoption/value\fR pairs are specified,
sets the value of those options for the specified tag.
If a single \fIoption\fR is specified,
returns the value of that option
(or the empty string if the option has not been specified for \fItagName\fR).
With no additional arguments,
returns a dictionary of the option settings for \fItagName\fR.
See \fBTAG OPTIONS\fR for the list of available options.
.TP
\fIpathName \fBtag delete \fItagName\fR
Deletes all tag information for the \fItagName\fR argument. The
command removes the tag from all items in the widget and also deletes any
other information associated with the tag, such as bindings and display
information. The command returns an empty string.
.TP
\fIpathName \fBtag has \fItagName\fR ?\fIitem\fR?
If \fIitem\fR is specified, returns 1 or 0
depending on whether the specified item has the named tag.
Otherwise, returns a list of all items which have
the specified tag.
.TP
\fIpathName \fBtag names\fR
Returns a list of all tags used by the widget.
.TP
\fIpathName \fBtag add \fItag items\fR
Adds the specified \fItag\fR to each of the listed \fIitems\fR.
If \fItag\fR is already present for a particular item,
then the \fB\-tags\fR for that item are unchanged.
.TP
\fIpathName \fBtag remove \fItag\fR ?\fIitems\fR?
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
The textual label to display for the item.
.OP \-image image Image
Changes to doc/ttk_widget.n.
67
68
69
70
71
72
73






74
75
76
77
78
79
80
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86







+
+
+
+
+
+







.RE
.OP \-yscrollcommand yScrollCommand ScrollCommand
A command prefix, used to communicate with vertical scrollbars.
See the description of \fB\-xscrollcommand\fR above for details.
.SH "LABEL OPTIONS"
The following options are supported by labels, buttons,
and other button-like widgets:
.OP \-anchor anchor Anchor
Specifies how the information in the widget is positioned
relative to the inner margins.  Legal values are
\fBn\fR, \fBne\fR, \fBe\fR, \fBse\fR,
\fBs\fR, \fBsw\fR, \fBw\fR, \fBnw\fR, and \fBcenter\fR.
See also \fB\-justify\fR (for widgets supporting this option).
.OP \-compound compound Compound
Specifies how to display the image relative to the text,
in the case both \fB\-text\fR and \fB\-image\fR are present.
If set to the empty string (the default), the rules described in the
"Elements" section of \fIttk::intro(n)\fR explain which value is actually
used.
Valid values are:
89
90
91
92
93
94
95





96
97
98
99
100
101
102
103





104
105
106
107
108
109
110
111
112
113
114
115
116
117

118
119
120
121
122
123
124
125
126
127
128
129

















130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170


171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198



199
200
201
202
203
204
205
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132

133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176

177
178
179
180

181
182
183
184
185
186
187
188
189
190
191
192
193
194
195

196
197
198
199

200
201
202
203

204
205
206
207
208
209
210
211
212

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237







+
+
+
+
+








+
+
+
+
+













-
+












+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+














-




-















-




-
+
+


-









-















+
+
+







.IP bottom
.IP left
.IP right
Display image above, below, left of, or right of the text, respectively.
.IP none
Display the image if present, otherwise the text.
.RE
.OP \-font font Font
Font to use for the text displayed by the widget.
.OP \-foreground textColor TextColor
The widget's foreground color.
If unspecified, the theme default is used.
.OP \-image image Image
Specifies an image to display.
This is a list of 1 or more elements.
The first element is the default image name.
The rest of the list is a sequence of \fIstatespec / value\fR pairs
as per \fBstyle map\fR, specifying different images to use when
the widget is in a particular state or combination of states.
All images in the list should have the same size.
.OP \-justify justify Justify
If there are multiple lines of text, specifies how
the lines are laid out relative to one another.
One of \fBleft\fR, \fBcenter\fR, or \fBright\fR.
See also \fB\-anchor\fR (for widgets supporting this option).
.OP \-padding padding Padding
Specifies the internal padding for the widget.
The padding is a list of up to four length specifications
\fIleft top right bottom\fR.
If fewer than four elements are specified,
\fIbottom\fR defaults to \fItop\fR,
\fIright\fR defaults to \fIleft\fR, and
\fItop\fR defaults to \fIleft\fR.
In other words, a list of three numbers specify the left, vertical, and right padding;
a list of two numbers specify the horizontal and the vertical padding;
a single number specifies the same padding all the way around the widget.
.OP \-text text Text
Specifies a text string to be displayed inside the widget
(unless overridden by \fB\-textvariable\fR).
(unless overridden by \fB\-textvariable\fR for the widgets supporting this option).
.OP \-textvariable textVariable Variable
Specifies the name of a global variable whose value will be used
in place of the \fB\-text\fR resource.
.OP \-underline underline Underline
If set, specifies the integer index (0-based) of a character to underline
in the text string.
The underlined character is used for mnemonic activation.
.OP \-width width Width
If greater than zero, specifies how much space, in character widths,
to allocate for the text label.
If less than zero, specifies a minimum width.
If zero or unspecified, the natural width of the text label is used.
Note that some themes may specify a non-zero \fB\-width\fR
in the style.
.OP \-wraplength wrapLength WrapLength
Specifies the maximum line length. The value may have any of the forms
acceptable to \fBTk_GetPixels\fR. If this option is less than or equal
to zero, then automatic wrapping is not performed; otherwise
the text is split into lines such that no line is longer
than the specified value.
.SH "ENTRY OPTIONS"
The following options are supported by entry, spinbox and combobox:
.OP \-placeholder placeHolder PlaceHolder
Specifies a help text string to display if no text is otherwise displayed,
that is when the widget is empty. The placeholder text is displayed using
the values of the \fB\-font\fR, \fB\-justify\fR and
\fB\-placeholderforeground\fR options.
.OP \-placeholderforeground placeHolderForeground PlaceHolderForeground
Specifies the foreground color of the placeholder text.
.SH "COMPATIBILITY OPTIONS"
This option is only available for themed widgets that have
.QW corresponding
traditional Tk widgets.
.OP \-state state State
May be set to \fBnormal\fR or \fBdisabled\fR
to control the \fBdisabled\fR state bit.
This is a write-only option:
setting it changes the widget state,
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.
If \fIoption\fR is specified with no \fIvalue\fR,
then the command returns a list describing the named option:
the elements of the list are the
option name, database name, database class, default value,
and current value.
.\" 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
Returns a new state spec indicating which flags were changed:
.CS
set changes [\fIpathName \fRstate \fIspec\fR]
\fIpathName \fRstate $changes
.CE
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
.TP
\fIpathName \fBxview\fR
220
221
222
223
224
225
226
227
228



229
230

231
232
233
234
235


236
237
238
239
240
241
242
252
253
254
255
256
257
258


259
260
261
262

263

264
265
266
267
268
269
270
271
272
273
274
275
276







-
-
+
+
+

-
+
-




+
+







Adjusts the view in the window so that the character \fIfraction\fR of the
way through the content appears at the left edge of the window.
\fIFraction\fR must be a fraction between 0 and 1.
.TP
\fIpathName \fBxview scroll \fInumber what\fR
This command shifts the view in the window left or right according to
\fInumber\fR and \fIwhat\fR.
\fINumber\fR must be an integer.
\fIWhat\fR must be either \fBunits\fR or \fBpages\fR.
\fINumber\fR must be an integer or a float, but if it is a float then
it is converted to an integer, rounded away from 0.
\fIWhat\fR must be either \fBpages\fR or \fBunits\fR.
'\" or an abbreviation of one of these, but we don't document that.
If \fIwhat\fR is \fBunits\fR, the view adjusts left or right by
If \fIwhat\fR is
\fInumber\fR average-width characters on the display;  if it is
\fBpages\fR then the view adjusts by \fInumber\fR screenfuls.
If \fInumber\fR is negative then characters farther to the left
become visible;  if it is positive then characters farther to the right
become visible.
If \fIwhat\fR is \fBunits\fR, the view adjusts left or right by
\fInumber\fR average-width characters on the display.
.RE
.TP
\fIpathName \fByview \fIargs\fR
This command is used to query and change the vertical position of the
content in the widget's window.  It can take any of the following
forms:
.RS
260
261
262
263
264
265
266
267

268
269

270
271
272
273
274


275
276
277
278
279
280
281
294
295
296
297
298
299
300

301
302

303

304
305
306
307
308
309
310
311
312
313
314
315
316







-
+

-
+
-




+
+







way through the content appears at the top edge of the window.
\fIFraction\fR must be a fraction between 0 and 1.
.TP
\fIpathName \fByview scroll \fInumber what\fR
This command shifts the view in the window up or down according to
\fInumber\fR and \fIwhat\fR.
\fINumber\fR must be an integer.
\fIWhat\fR must be either \fBunits\fR or \fBpages\fR.
\fIWhat\fR must be either \fBpages\fR or \fBunits\fR.
'\" or an abbreviation of one of these, but we don't document that.
If \fIwhat\fR is \fBunits\fR, the view adjusts up or down by
If \fIwhat\fR is
\fInumber\fR average-width characters on the display;  if it is
\fBpages\fR then the view adjusts by \fInumber\fR screenfuls.
If \fInumber\fR is negative then items farther to the top
become visible;  if it is positive then items farther to the bottom
become visible.
If \fIwhat\fR is \fBunits\fR, the view adjusts up or down by
\fInumber\fR average-width characters on the display.
.RE
.SH "WIDGET STATES"
The widget state is a bitmap of independent state flags.
Widget state flags include:
.TP
\fBactive\fR
.
Changes to doc/winfo.n.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
1
2
3
4
5
6

7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
22






-
+







-
+







'\"
'\" Copyright (c) 1990-1994 The Regents of the University of California.
'\" Copyright (c) 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.
'\" 
'\"
.TH winfo n 4.3 Tk "Tk Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
winfo \- Return window-related information
.SH SYNOPSIS
\fBwinfo\fR \fIoption \fR?\fIarg arg ...\fR?
\fBwinfo\fR \fIoption \fR?\fIarg ...\fR?
.BE
.SH DESCRIPTION
.PP
The \fBwinfo\fR command is used to retrieve information about windows
managed by Tk.  It can take any of a number of different forms,
depending on the \fIoption\fR argument.  The legal forms are:
.TP
Changes to doc/wish.1.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
1
2
3
4
5
6

7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
22






-
+







-
+







'\"
'\" Copyright (c) 1991-1994 The Regents of the University of California.
'\" Copyright (c) 1994-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.
'\" 
'\"
.TH wish 1 8.0 Tk "Tk Applications"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
wish \- Simple windowing shell
.SH SYNOPSIS
\fBwish\fR ?\fB\-encoding \fIname\fR? ?\fIfileName arg arg ...\fR?
\fBwish\fR ?\fB\-encoding \fIname\fR? ?\fIfileName arg ...\fR?
.SH OPTIONS
.IP "\fB\-encoding \fIname\fR" 20
Specifies the encoding of the text stored in \fIfileName\fR.
This option is only recognized prior to the \fIfileName\fR argument.
.IP "\fB\-colormap \fInew\fR" 20
Specifies that the window should have a new private colormap instead of
using the default colormap for the screen.
73
74
75
76
77
78
79
80

81
82
83
84
85
86
87
73
74
75
76
77
78
79

80
81
82
83
84
85
86
87







-
+







It will continue processing commands until all windows have been
deleted or until end-of-file is reached on standard input.
If there exists a file
.QW \fB.wishrc\fR
in the home directory of the user, \fBwish\fR evaluates the file as a
Tcl script just before reading the first command from standard input.
.PP
If arguments to \fBwish\fR do specify a \fIfileName\fR, then 
If arguments to \fBwish\fR do specify a \fIfileName\fR, then
\fIfileName\fR is treated as the name of a script file.
\fBWish\fR will evaluate the script in \fIfileName\fR (which
presumably creates a user interface), then it will respond to events
until all windows have been deleted.
Commands will not be read from standard input.
There is no automatic evaluation of
.QW \fB.wishrc\fR
Changes to doc/wm.n.
490
491
492
493
494
495
496
497

498
499
500
501
502
503
504
490
491
492
493
494
495
496

497
498
499
500
501
502
503
504







-
+







.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
parameters as support for multiple sizes/resolutions on macOS is outside Tk's
scope. Developers should use the largest icon they can support
(preferably 512 pixels) to ensure smooth rendering on the Mac. 
(preferably 512 pixels) to ensure smooth rendering on the Mac.
.RE
.TP
\fBwm iconposition \fIwindow\fR ?\fIx y\fR?
.
If \fIx\fR and \fIy\fR are specified, they are passed to the window
manager as a hint about where to position the icon for \fIwindow\fR.
In this case an empty string is returned.  If \fIx\fR and \fIy\fR are
704
705
706
707
708
709
710
711

712
713

714
715
716


717
718
719

720
721
722


723
724
725
726
727
728
729
704
705
706
707
708
709
710

711
712

713
714


715
716
717
718

719
720


721
722
723
724
725
726
727
728
729







-
+

-
+

-
-
+
+


-
+

-
-
+
+







If \fIstring\fR is specified, then it will be passed to the window
manager for use as the title for \fIwindow\fR (the window manager
should display this string in \fIwindow\fR's title bar).  In this
case the command returns an empty string.  If \fIstring\fR is not
specified then the command returns the current title for the
\fIwindow\fR.  The title for a window defaults to its name.
.TP
\fBwm transient \fIwindow\fR ?\fImaster\fR?
\fBwm transient \fIwindow\fR ?\fIcontainer\fR?
.
If \fImaster\fR is specified, then the window manager is informed that
If \fIcontainer\fR is specified, then the window manager is informed that
\fIwindow\fR is a transient window (e.g. pull-down menu) working on
behalf of \fImaster\fR (where \fImaster\fR is the path name for a
top-level window).  If \fImaster\fR is specified as an empty string
behalf of \fIcontainer\fR (where \fIcontainer\fR is the path name for a
top-level window).  If \fIcontainer\fR is specified as an empty string
then \fIwindow\fR is marked as not being a transient window any more.
Otherwise the command returns the path name of \fIwindow\fR's current
master, or an empty string if \fIwindow\fR is not currently a
container, or an empty string if \fIwindow\fR is not currently a
transient window.  A transient window will mirror state changes in the
master and inherit the state of the master when initially mapped. The
directed graph with an edge from each transient to its master must be
container and inherit the state of the container when initially mapped. The
directed graph with an edge from each transient to its container must be
acyclic.  In particular, it is an error to attempt to make a window a
transient of itself.  The window manager may also decorate a transient
window differently, removing some features normally present (e.g.,
minimize and maximize buttons) though this is entirely at the
discretion of the window manager.
.TP
\fBwm withdraw \fIwindow\fR
Changes to generic/ks_names.h.
18
19
20
21
22
23
24




25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41



42
43
44
45
46
47
48
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55







+
+
+
+

















+
+
+







{ "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 },
{ "Hiragana", 0xFF25 },
{ "Katakana", 0xFF26 },
{ "Hiragana_Katakana", 0xFF27 },
{ "Zenkaku", 0xFF28 },
{ "Hankaku", 0xFF29 },
{ "Zenkaku_Hankaku", 0xFF2A },
{ "Touroku", 0xFF2B },
{ "Massyo", 0xFF2C },
{ "Kana_Lock", 0xFF2D },
{ "Kana_Shift", 0xFF2E },
{ "Eisu_Shift", 0xFF2F },
{ "Eisu_toggle", 0xFF30 },
{ "Kanji_Bangou", 0xFF37 },
{ "Zen_Koho", 0xFF3D },
{ "Mae_Koho", 0xFF3E },
{ "Home", 0xFF50 },
{ "Left", 0xFF51 },
{ "Up", 0xFF52 },
{ "Right", 0xFF53 },
{ "Down", 0xFF54 },
{ "Prior", 0xFF55 },
{ "Page_Up", 0xFF55 },
174
175
176
177
178
179
180














































































































































































181

182

183
184
185

186
187
188
189
190
191
192
193
194

195

196
197
198
199
200
201
202
203
204
205
206
207
208

209
210

211

212

213
214
215
216
217
218
219
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+

+



+









+

+













+


+

+

+







{ "Meta_R", 0xFFE8 },
{ "Alt_L", 0xFFE9 },
{ "Alt_R", 0xFFEA },
{ "Super_L", 0xFFEB },
{ "Super_R", 0xFFEC },
{ "Hyper_L", 0xFFED },
{ "Hyper_R", 0xFFEE },
{ "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 },
{ "ISO_Prev_Group_Lock", 0xFE0B },
{ "ISO_First_Group", 0xFE0C },
{ "ISO_First_Group_Lock", 0xFE0D },
{ "ISO_Last_Group", 0xFE0E },
{ "ISO_Last_Group_Lock", 0xFE0F },
{ "ISO_Left_Tab", 0xFE20 },
{ "ISO_Move_Line_Up", 0xFE21 },
{ "ISO_Move_Line_Down", 0xFE22 },
{ "ISO_Partial_Line_Up", 0xFE23 },
{ "ISO_Partial_Line_Down", 0xFE24 },
{ "ISO_Partial_Space_Left", 0xFE25 },
{ "ISO_Partial_Space_Right", 0xFE26 },
{ "ISO_Set_Margin_Left", 0xFE27 },
{ "ISO_Set_Margin_Right", 0xFE28 },
{ "ISO_Release_Margin_Left", 0xFE29 },
{ "ISO_Release_Margin_Right", 0xFE2A },
{ "ISO_Release_Both_Margins", 0xFE2B },
{ "ISO_Fast_Cursor_Left", 0xFE2C },
{ "ISO_Fast_Cursor_Right", 0xFE2D },
{ "ISO_Fast_Cursor_Up", 0xFE2E },
{ "ISO_Fast_Cursor_Down", 0xFE2F },
{ "ISO_Continuous_Underline", 0xFE30 },
{ "ISO_Discontinuous_Underline", 0xFE31 },
{ "ISO_Emphasize", 0xFE32 },
{ "ISO_Center_Object", 0xFE33 },
{ "ISO_Enter", 0xFE34 },
{ "dead_grave", 0xFE50 },
{ "dead_acute", 0xFE51 },
{ "dead_circumflex", 0xFE52 },
{ "dead_tilde", 0xFE53 },
{ "dead_perispomeni", 0xFE53 },
{ "dead_macron", 0xFE54 },
{ "dead_breve", 0xFE55 },
{ "dead_abovedot", 0xFE56 },
{ "dead_diaeresis", 0xFE57 },
{ "dead_abovering", 0xFE58 },
{ "dead_doubleacute", 0xFE59 },
{ "dead_caron", 0xFE5A },
{ "dead_cedilla", 0xFE5B },
{ "dead_ogonek", 0xFE5C },
{ "dead_iota", 0xFE5D },
{ "dead_voiced_sound", 0xFE5E },
{ "dead_semivoiced_sound", 0xFE5F },
{ "dead_belowdot", 0xFE60 },
{ "dead_hook", 0xFE61 },
{ "dead_horn", 0xFE62 },
{ "dead_stroke", 0xFE63 },
{ "dead_abovecomma", 0xFE64 },
{ "dead_psili", 0xFE64 },
{ "dead_abovereversedcomma", 0xFE65 },
{ "dead_dasia", 0xFE65 },
{ "dead_doublegrave", 0xFE66 },
{ "dead_belowring", 0xFE67 },
{ "dead_belowmacron", 0xFE68 },
{ "dead_belowcircumflex", 0xFE69 },
{ "dead_belowtilde", 0xFE6A },
{ "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 },
{ "dead_a", 0xFE80 },
{ "dead_A", 0xFE81 },
{ "dead_e", 0xFE82 },
{ "dead_E", 0xFE83 },
{ "dead_i", 0xFE84 },
{ "dead_I", 0xFE85 },
{ "dead_o", 0xFE86 },
{ "dead_O", 0xFE87 },
{ "dead_u", 0xFE88 },
{ "dead_U", 0xFE89 },
{ "dead_small_schwa", 0xFE8A },
{ "dead_capital_schwa", 0xFE8B },
{ "dead_greek", 0xFE8C },
{ "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 },
{ "Pointer_UpRight", 0xFEE5 },
{ "Pointer_DownLeft", 0xFEE6 },
{ "Pointer_DownRight", 0xFEE7 },
{ "Pointer_Button_Dflt", 0xFEE8 },
{ "Pointer_Button1", 0xFEE9 },
{ "Pointer_Button2", 0xFEEA },
{ "Pointer_Button3", 0xFEEB },
{ "Pointer_Button4", 0xFEEC },
{ "Pointer_Button5", 0xFEED },
{ "Pointer_DblClick_Dflt", 0xFEEE },
{ "Pointer_DblClick1", 0xFEEF },
{ "Pointer_DblClick2", 0xFEF0 },
{ "Pointer_DblClick3", 0xFEF1 },
{ "Pointer_DblClick4", 0xFEF2 },
{ "Pointer_DblClick5", 0xFEF3 },
{ "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 },
{ "3270_Duplicate", 0xFD01 },
{ "3270_FieldMark", 0xFD02 },
{ "3270_Right2", 0xFD03 },
{ "3270_Left2", 0xFD04 },
{ "3270_BackTab", 0xFD05 },
{ "3270_EraseEOF", 0xFD06 },
{ "3270_EraseInput", 0xFD07 },
{ "3270_Reset", 0xFD08 },
{ "3270_Quit", 0xFD09 },
{ "3270_PA1", 0xFD0A },
{ "3270_PA2", 0xFD0B },
{ "3270_PA3", 0xFD0C },
{ "3270_Test", 0xFD0D },
{ "3270_Attn", 0xFD0E },
{ "3270_CursorBlink", 0xFD0F },
{ "3270_AltCursor", 0xFD10 },
{ "3270_KeyClick", 0xFD11 },
{ "3270_Jump", 0xFD12 },
{ "3270_Ident", 0xFD13 },
{ "3270_Rule", 0xFD14 },
{ "3270_Copy", 0xFD15 },
{ "3270_Play", 0xFD16 },
{ "3270_Setup", 0xFD17 },
{ "3270_Record", 0xFD18 },
{ "3270_ChangeScreen", 0xFD19 },
{ "3270_DeleteWord", 0xFD1A },
{ "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 },
{ "3", 0x33 },
{ "4", 0x34 },
{ "5", 0x35 },
{ "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 },
{ "D", 0x44 },
{ "E", 0x45 },
234
235
236
237
238
239
240

241
242
243

244
245
246
247
248
249
250
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442







+



+







{ "T", 0x54 },
{ "U", 0x55 },
{ "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 },
{ "b", 0x62 },
{ "c", 0x63 },
267
268
269
270
271
272
273

274

275

276

277

278

279
280
281
282
283
284
285
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483







+

+

+

+

+

+







{ "t", 0x74 },
{ "u", 0x75 },
{ "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 },
{ "brokenbar", 0xA6 },
{ "section", 0xA7 },
329
330
331
332
333
334
335

336

337
338
339
340
341
342
343
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543







+

+







{ "Ograve", 0xD2 },
{ "Oacute", 0xD3 },
{ "Ocircumflex", 0xD4 },
{ "Otilde", 0xD5 },
{ "Odiaeresis", 0xD6 },
{ "multiply", 0xD7 },
{ "Oslash", 0xD8 },
#ifndef TK_NO_DEPRECATED
{ "Ooblique", 0xD8 },
#endif
{ "Ugrave", 0xD9 },
{ "Uacute", 0xDA },
{ "Ucircumflex", 0xDB },
{ "Udiaeresis", 0xDC },
{ "Yacute", 0xDD },
{ "THORN", 0xDE },
{ "Thorn", 0xDE },
363
364
365
366
367
368
369



370
371
372
373
374
375
376

377
378
379
380
381
382
383
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587







+
+
+







+







{ "ograve", 0xF2 },
{ "oacute", 0xF3 },
{ "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 },
{ "Scaron", 0x1A9 },
{ "Scedilla", 0x1AA },
450
451
452
453
454
455
456

457

458
459
460
461
462
463
464
465
466
467
468

469

470
471
472
473
474
475
476
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684







+

+











+

+







{ "cabovedot", 0x2E5 },
{ "ccircumflex", 0x2E6 },
{ "gabovedot", 0x2F5 },
{ "gcircumflex", 0x2F8 },
{ "ubreve", 0x2FD },
{ "scircumflex", 0x2FE },
{ "kra", 0x3A2 },
#ifndef TK_NO_DEPRECATED
{ "kappa", 0x3A2 },
#endif
{ "Rcedilla", 0x3A3 },
{ "Itilde", 0x3A5 },
{ "Lcedilla", 0x3A6 },
{ "Emacron", 0x3AA },
{ "Gcedilla", 0x3AB },
{ "Tslash", 0x3AC },
{ "rcedilla", 0x3B3 },
{ "itilde", 0x3B5 },
{ "lcedilla", 0x3B6 },
{ "emacron", 0x3BA },
{ "gcedilla", 0x3BB },
#ifndef TK_NO_DEPRECATED
{ "gacute", 0x3BB },
#endif
{ "tslash", 0x3BC },
{ "ENG", 0x3BD },
{ "eng", 0x3BF },
{ "Amacron", 0x3C0 },
{ "Iogonek", 0x3C7 },
{ "Eabovedot", 0x3CC },
{ "Imacron", 0x3CF },
486
487
488
489
490
491
492



493
494
495
496
497
498

499

500
501
502
503
504
505
506
507
508
509

510

511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528

529

530

531

532
533
534
535
536
537
538
539
540
541

542

543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783

784
785
786
787
788
789
790







+
+
+






+

+










+

+


















+

+

+

+










+

+




















-







{ "imacron", 0x3EF },
{ "ncedilla", 0x3F1 },
{ "omacron", 0x3F2 },
{ "kcedilla", 0x3F3 },
{ "uogonek", 0x3F9 },
{ "utilde", 0x3FD },
{ "umacron", 0x3FE },
{ "OE", 0x13BC },
{ "oe", 0x13BD },
{ "Ydiaeresis", 0x13BE },
{ "overline", 0x47E },
{ "kana_fullstop", 0x4A1 },
{ "kana_openingbracket", 0x4A2 },
{ "kana_closingbracket", 0x4A3 },
{ "kana_comma", 0x4A4 },
{ "kana_conjunctive", 0x4A5 },
#ifndef TK_NO_DEPRECATED
{ "kana_middledot", 0x4A5 },
#endif
{ "kana_WO", 0x4A6 },
{ "kana_a", 0x4A7 },
{ "kana_i", 0x4A8 },
{ "kana_u", 0x4A9 },
{ "kana_e", 0x4AA },
{ "kana_o", 0x4AB },
{ "kana_ya", 0x4AC },
{ "kana_yu", 0x4AD },
{ "kana_yo", 0x4AE },
{ "kana_tsu", 0x4AF },
#ifndef TK_NO_DEPRECATED
{ "kana_tu", 0x4AF },
#endif
{ "prolongedsound", 0x4B0 },
{ "kana_A", 0x4B1 },
{ "kana_I", 0x4B2 },
{ "kana_U", 0x4B3 },
{ "kana_E", 0x4B4 },
{ "kana_O", 0x4B5 },
{ "kana_KA", 0x4B6 },
{ "kana_KI", 0x4B7 },
{ "kana_KU", 0x4B8 },
{ "kana_KE", 0x4B9 },
{ "kana_KO", 0x4BA },
{ "kana_SA", 0x4BB },
{ "kana_SHI", 0x4BC },
{ "kana_SU", 0x4BD },
{ "kana_SE", 0x4BE },
{ "kana_SO", 0x4BF },
{ "kana_TA", 0x4C0 },
{ "kana_CHI", 0x4C1 },
#ifndef TK_NO_DEPRECATED
{ "kana_TI", 0x4C1 },
#endif
{ "kana_TSU", 0x4C2 },
#ifndef TK_NO_DEPRECATED
{ "kana_TU", 0x4C2 },
#endif
{ "kana_TE", 0x4C3 },
{ "kana_TO", 0x4C4 },
{ "kana_NA", 0x4C5 },
{ "kana_NI", 0x4C6 },
{ "kana_NU", 0x4C7 },
{ "kana_NE", 0x4C8 },
{ "kana_NO", 0x4C9 },
{ "kana_HA", 0x4CA },
{ "kana_HI", 0x4CB },
{ "kana_FU", 0x4CC },
#ifndef TK_NO_DEPRECATED
{ "kana_HU", 0x4CC },
#endif
{ "kana_HE", 0x4CD },
{ "kana_HO", 0x4CE },
{ "kana_MA", 0x4CF },
{ "kana_MI", 0x4D0 },
{ "kana_MU", 0x4D1 },
{ "kana_ME", 0x4D2 },
{ "kana_MO", 0x4D3 },
{ "kana_YA", 0x4D4 },
{ "kana_YU", 0x4D5 },
{ "kana_YO", 0x4D6 },
{ "kana_RA", 0x4D7 },
{ "kana_RI", 0x4D8 },
{ "kana_RU", 0x4D9 },
{ "kana_RE", 0x4DA },
{ "kana_RO", 0x4DB },
{ "kana_WA", 0x4DC },
{ "kana_N", 0x4DD },
{ "voicedsound", 0x4DE },
{ "semivoicedsound", 0x4DF },
{ "kana_switch", 0xFF7E },
{ "Arabic_comma", 0x5AC },
{ "Arabic_semicolon", 0x5BB },
{ "Arabic_question_mark", 0x5BF },
{ "Arabic_hamza", 0x5C1 },
{ "Arabic_maddaonalef", 0x5C2 },
{ "Arabic_hamzaonalef", 0x5C3 },
{ "Arabic_hamzaonwaw", 0x5C4 },
{ "Arabic_hamzaunderalef", 0x5C5 },
593
594
595
596
597
598
599

600

601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616

617

618
619

620

621

622

623

624

625

626

627

628

629
630
631
632
633

634

635
636
637
638
639

640

641
642

643

644

645

646

647

648

649

650

651

652
653
654
655
656

657

658
659
660
661
662
663
664
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833

834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913







+

+











-




+

+


+

+

+

+

+

+

+

+

+

+





+

+





+

+


+

+

+

+

+

+

+

+

+

+





+

+







{ "Arabic_feh", 0x5E1 },
{ "Arabic_qaf", 0x5E2 },
{ "Arabic_kaf", 0x5E3 },
{ "Arabic_lam", 0x5E4 },
{ "Arabic_meem", 0x5E5 },
{ "Arabic_noon", 0x5E6 },
{ "Arabic_ha", 0x5E7 },
#ifndef TK_NO_DEPRECATED
{ "Arabic_heh", 0x5E7 },
#endif
{ "Arabic_waw", 0x5E8 },
{ "Arabic_alefmaksura", 0x5E9 },
{ "Arabic_yeh", 0x5EA },
{ "Arabic_fathatan", 0x5EB },
{ "Arabic_dammatan", 0x5EC },
{ "Arabic_kasratan", 0x5ED },
{ "Arabic_fatha", 0x5EE },
{ "Arabic_damma", 0x5EF },
{ "Arabic_kasra", 0x5F0 },
{ "Arabic_shadda", 0x5F1 },
{ "Arabic_sukun", 0x5F2 },
{ "Arabic_switch", 0xFF7E },
{ "Serbian_dje", 0x6A1 },
{ "Macedonia_gje", 0x6A2 },
{ "Cyrillic_io", 0x6A3 },
{ "Ukrainian_ie", 0x6A4 },
#ifndef TK_NO_DEPRECATED
{ "Ukranian_je", 0x6A4 },
#endif
{ "Macedonia_dse", 0x6A5 },
{ "Ukrainian_i", 0x6A6 },
#ifndef TK_NO_DEPRECATED
{ "Ukranian_i", 0x6A6 },
#endif
{ "Ukrainian_yi", 0x6A7 },
#ifndef TK_NO_DEPRECATED
{ "Ukranian_yi", 0x6A7 },
#endif
{ "Cyrillic_je", 0x6A8 },
#ifndef TK_NO_DEPRECATED
{ "Serbian_je", 0x6A8 },
#endif
{ "Cyrillic_lje", 0x6A9 },
#ifndef TK_NO_DEPRECATED
{ "Serbian_lje", 0x6A9 },
#endif
{ "Cyrillic_nje", 0x6AA },
#ifndef TK_NO_DEPRECATED
{ "Serbian_nje", 0x6AA },
#endif
{ "Serbian_tshe", 0x6AB },
{ "Macedonia_kje", 0x6AC },
{ "Ukrainian_ghe_with_upturn", 0x6AD },
{ "Byelorussian_shortu", 0x6AE },
{ "Cyrillic_dzhe", 0x6AF },
#ifndef TK_NO_DEPRECATED
{ "Serbian_dze", 0x6AF },
#endif
{ "numerosign", 0x6B0 },
{ "Serbian_DJE", 0x6B1 },
{ "Macedonia_GJE", 0x6B2 },
{ "Cyrillic_IO", 0x6B3 },
{ "Ukrainian_IE", 0x6B4 },
#ifndef TK_NO_DEPRECATED
{ "Ukranian_JE", 0x6B4 },
#endif
{ "Macedonia_DSE", 0x6B5 },
{ "Ukrainian_I", 0x6B6 },
#ifndef TK_NO_DEPRECATED
{ "Ukranian_I", 0x6B6 },
#endif
{ "Ukrainian_YI", 0x6B7 },
#ifndef TK_NO_DEPRECATED
{ "Ukranian_YI", 0x6B7 },
#endif
{ "Cyrillic_JE", 0x6B8 },
#ifndef TK_NO_DEPRECATED
{ "Serbian_JE", 0x6B8 },
#endif
{ "Cyrillic_LJE", 0x6B9 },
#ifndef TK_NO_DEPRECATED
{ "Serbian_LJE", 0x6B9 },
#endif
{ "Cyrillic_NJE", 0x6BA },
#ifndef TK_NO_DEPRECATED
{ "Serbian_NJE", 0x6BA },
#endif
{ "Serbian_TSHE", 0x6BB },
{ "Macedonia_KJE", 0x6BC },
{ "Ukrainian_GHE_WITH_UPTURN", 0x6BD },
{ "Byelorussian_SHORTU", 0x6BE },
{ "Cyrillic_DZHE", 0x6BF },
#ifndef TK_NO_DEPRECATED
{ "Serbian_DZE", 0x6BF },
#endif
{ "Cyrillic_yu", 0x6C0 },
{ "Cyrillic_a", 0x6C1 },
{ "Cyrillic_be", 0x6C2 },
{ "Cyrillic_tse", 0x6C3 },
{ "Cyrillic_de", 0x6C4 },
{ "Cyrillic_ie", 0x6C5 },
{ "Cyrillic_ef", 0x6C6 },
971
972
973
974
975
976
977

978

979

980

981

982

983
984
985

986

987

988

989

990

991
992
993
994
995
996
997
998
999

1000

1001
1002
1003
1004

1005

1006

1007

1008

1009

1010
1011
1012

1013

1014









































































































































































































1015
1016
1017
1018
1019
1020
1021
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493







+

+

+

+

+

+



+

+

+

+

+

+









+

+




+

+

+

+

+

+



+

+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







{ "rightshoe", 0xBD8 },
{ "leftshoe", 0xBDA },
{ "lefttack", 0xBDC },
{ "righttack", 0xBFC },
{ "hebrew_doublelowline", 0xCDF },
{ "hebrew_aleph", 0xCE0 },
{ "hebrew_bet", 0xCE1 },
#ifndef TK_NO_DEPRECATED
{ "hebrew_beth", 0xCE1 },
#endif
{ "hebrew_gimel", 0xCE2 },
#ifndef TK_NO_DEPRECATED
{ "hebrew_gimmel", 0xCE2 },
#endif
{ "hebrew_dalet", 0xCE3 },
#ifndef TK_NO_DEPRECATED
{ "hebrew_daleth", 0xCE3 },
#endif
{ "hebrew_he", 0xCE4 },
{ "hebrew_waw", 0xCE5 },
{ "hebrew_zain", 0xCE6 },
#ifndef TK_NO_DEPRECATED
{ "hebrew_zayin", 0xCE6 },
#endif
{ "hebrew_chet", 0xCE7 },
#ifndef TK_NO_DEPRECATED
{ "hebrew_het", 0xCE7 },
#endif
{ "hebrew_tet", 0xCE8 },
#ifndef TK_NO_DEPRECATED
{ "hebrew_teth", 0xCE8 },
#endif
{ "hebrew_yod", 0xCE9 },
{ "hebrew_finalkaph", 0xCEA },
{ "hebrew_kaph", 0xCEB },
{ "hebrew_lamed", 0xCEC },
{ "hebrew_finalmem", 0xCED },
{ "hebrew_mem", 0xCEE },
{ "hebrew_finalnun", 0xCEF },
{ "hebrew_nun", 0xCF0 },
{ "hebrew_samech", 0xCF1 },
#ifndef TK_NO_DEPRECATED
{ "hebrew_samekh", 0xCF1 },
#endif
{ "hebrew_ayin", 0xCF2 },
{ "hebrew_finalpe", 0xCF3 },
{ "hebrew_pe", 0xCF4 },
{ "hebrew_finalzade", 0xCF5 },
#ifndef TK_NO_DEPRECATED
{ "hebrew_finalzadi", 0xCF5 },
#endif
{ "hebrew_zade", 0xCF6 },
#ifndef TK_NO_DEPRECATED
{ "hebrew_zadi", 0xCF6 },
#endif
{ "hebrew_qoph", 0xCF7 },
#ifndef TK_NO_DEPRECATED
{ "hebrew_kuf", 0xCF7 },
#endif
{ "hebrew_resh", 0xCF8 },
{ "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 },
{ "Thai_khorakhang", 0xDA6 },
{ "Thai_ngongu", 0xDA7 },
{ "Thai_chochan", 0xDA8 },
{ "Thai_choching", 0xDA9 },
{ "Thai_chochang", 0xDAA },
{ "Thai_soso", 0xDAB },
{ "Thai_chochoe", 0xDAC },
{ "Thai_yoying", 0xDAD },
{ "Thai_dochada", 0xDAE },
{ "Thai_topatak", 0xDAF },
{ "Thai_thothan", 0xDB0 },
{ "Thai_thonangmontho", 0xDB1 },
{ "Thai_thophuthao", 0xDB2 },
{ "Thai_nonen", 0xDB3 },
{ "Thai_dodek", 0xDB4 },
{ "Thai_totao", 0xDB5 },
{ "Thai_thothung", 0xDB6 },
{ "Thai_thothahan", 0xDB7 },
{ "Thai_thothong", 0xDB8 },
{ "Thai_nonu", 0xDB9 },
{ "Thai_bobaimai", 0xDBA },
{ "Thai_popla", 0xDBB },
{ "Thai_phophung", 0xDBC },
{ "Thai_fofa", 0xDBD },
{ "Thai_phophan", 0xDBE },
{ "Thai_fofan", 0xDBF },
{ "Thai_phosamphao", 0xDC0 },
{ "Thai_moma", 0xDC1 },
{ "Thai_yoyak", 0xDC2 },
{ "Thai_rorua", 0xDC3 },
{ "Thai_ru", 0xDC4 },
{ "Thai_loling", 0xDC5 },
{ "Thai_lu", 0xDC6 },
{ "Thai_wowaen", 0xDC7 },
{ "Thai_sosala", 0xDC8 },
{ "Thai_sorusi", 0xDC9 },
{ "Thai_sosua", 0xDCA },
{ "Thai_hohip", 0xDCB },
{ "Thai_lochula", 0xDCC },
{ "Thai_oang", 0xDCD },
{ "Thai_honokhuk", 0xDCE },
{ "Thai_paiyannoi", 0xDCF },
{ "Thai_saraa", 0xDD0 },
{ "Thai_maihanakat", 0xDD1 },
{ "Thai_saraaa", 0xDD2 },
{ "Thai_saraam", 0xDD3 },
{ "Thai_sarai", 0xDD4 },
{ "Thai_saraii", 0xDD5 },
{ "Thai_saraue", 0xDD6 },
{ "Thai_sarauee", 0xDD7 },
{ "Thai_sarau", 0xDD8 },
{ "Thai_sarauu", 0xDD9 },
{ "Thai_phinthu", 0xDDA },
{ "Thai_maihanakat_maitho", 0xDDE },
{ "Thai_baht", 0xDDF },
{ "Thai_sarae", 0xDE0 },
{ "Thai_saraae", 0xDE1 },
{ "Thai_sarao", 0xDE2 },
{ "Thai_saraaimaimuan", 0xDE3 },
{ "Thai_saraaimaimalai", 0xDE4 },
{ "Thai_lakkhangyao", 0xDE5 },
{ "Thai_maiyamok", 0xDE6 },
{ "Thai_maitaikhu", 0xDE7 },
{ "Thai_maiek", 0xDE8 },
{ "Thai_maitho", 0xDE9 },
{ "Thai_maitri", 0xDEA },
{ "Thai_maichattawa", 0xDEB },
{ "Thai_thanthakhat", 0xDEC },
{ "Thai_nikhahit", 0xDED },
{ "Thai_leksun", 0xDF0 },
{ "Thai_leknung", 0xDF1 },
{ "Thai_leksong", 0xDF2 },
{ "Thai_leksam", 0xDF3 },
{ "Thai_leksi", 0xDF4 },
{ "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 },
{ "Hangul_NieunHieuh", 0xEA6 },
{ "Hangul_Dikeud", 0xEA7 },
{ "Hangul_SsangDikeud", 0xEA8 },
{ "Hangul_Rieul", 0xEA9 },
{ "Hangul_RieulKiyeog", 0xEAA },
{ "Hangul_RieulMieum", 0xEAB },
{ "Hangul_RieulPieub", 0xEAC },
{ "Hangul_RieulSios", 0xEAD },
{ "Hangul_RieulTieut", 0xEAE },
{ "Hangul_RieulPhieuf", 0xEAF },
{ "Hangul_RieulHieuh", 0xEB0 },
{ "Hangul_Mieum", 0xEB1 },
{ "Hangul_Pieub", 0xEB2 },
{ "Hangul_SsangPieub", 0xEB3 },
{ "Hangul_PieubSios", 0xEB4 },
{ "Hangul_Sios", 0xEB5 },
{ "Hangul_SsangSios", 0xEB6 },
{ "Hangul_Ieung", 0xEB7 },
{ "Hangul_Jieuj", 0xEB8 },
{ "Hangul_SsangJieuj", 0xEB9 },
{ "Hangul_Cieuc", 0xEBA },
{ "Hangul_Khieuq", 0xEBB },
{ "Hangul_Tieut", 0xEBC },
{ "Hangul_Phieuf", 0xEBD },
{ "Hangul_Hieuh", 0xEBE },
{ "Hangul_A", 0xEBF },
{ "Hangul_AE", 0xEC0 },
{ "Hangul_YA", 0xEC1 },
{ "Hangul_YAE", 0xEC2 },
{ "Hangul_EO", 0xEC3 },
{ "Hangul_E", 0xEC4 },
{ "Hangul_YEO", 0xEC5 },
{ "Hangul_YE", 0xEC6 },
{ "Hangul_O", 0xEC7 },
{ "Hangul_WA", 0xEC8 },
{ "Hangul_WAE", 0xEC9 },
{ "Hangul_OE", 0xECA },
{ "Hangul_YO", 0xECB },
{ "Hangul_U", 0xECC },
{ "Hangul_WEO", 0xECD },
{ "Hangul_WE", 0xECE },
{ "Hangul_WI", 0xECF },
{ "Hangul_YU", 0xED0 },
{ "Hangul_EU", 0xED1 },
{ "Hangul_YI", 0xED2 },
{ "Hangul_I", 0xED3 },
{ "Hangul_J_Kiyeog", 0xED4 },
{ "Hangul_J_SsangKiyeog", 0xED5 },
{ "Hangul_J_KiyeogSios", 0xED6 },
{ "Hangul_J_Nieun", 0xED7 },
{ "Hangul_J_NieunJieuj", 0xED8 },
{ "Hangul_J_NieunHieuh", 0xED9 },
{ "Hangul_J_Dikeud", 0xEDA },
{ "Hangul_J_Rieul", 0xEDB },
{ "Hangul_J_RieulKiyeog", 0xEDC },
{ "Hangul_J_RieulMieum", 0xEDD },
{ "Hangul_J_RieulPieub", 0xEDE },
{ "Hangul_J_RieulSios", 0xEDF },
{ "Hangul_J_RieulTieut", 0xEE0 },
{ "Hangul_J_RieulPhieuf", 0xEE1 },
{ "Hangul_J_RieulHieuh", 0xEE2 },
{ "Hangul_J_Mieum", 0xEE3 },
{ "Hangul_J_Pieub", 0xEE4 },
{ "Hangul_J_PieubSios", 0xEE5 },
{ "Hangul_J_Sios", 0xEE6 },
{ "Hangul_J_SsangSios", 0xEE7 },
{ "Hangul_J_Ieung", 0xEE8 },
{ "Hangul_J_Jieuj", 0xEE9 },
{ "Hangul_J_Cieuc", 0xEEA },
{ "Hangul_J_Khieuq", 0xEEB },
{ "Hangul_J_Tieut", 0xEEC },
{ "Hangul_J_Phieuf", 0xEED },
{ "Hangul_J_Hieuh", 0xEEE },
{ "Hangul_RieulYeorinHieuh", 0xEEF },
{ "Hangul_SunkyeongeumMieum", 0xEF0 },
{ "Hangul_SunkyeongeumPieub", 0xEF1 },
{ "Hangul_PanSios", 0xEF2 },
{ "Hangul_KkogjiDalrinIeung", 0xEF3 },
{ "Hangul_SunkyeongeumPhieuf", 0xEF4 },
{ "Hangul_YeorinHieuh", 0xEF5 },
{ "Hangul_AraeA", 0xEF6 },
{ "Hangul_AraeAE", 0xEF7 },
{ "Hangul_J_PanSios", 0xEF8 },
{ "Hangul_J_KkogjiDalrinIeung", 0xEF9 },
{ "Hangul_J_YeorinHieuh", 0xEFA },
{ "Korean_Won", 0xEFF },
{ "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 },
{ "XF86ModeLock", 0x1008FF01 },
{ "XF86MonBrightnessUp", 0x1008FF02 },
{ "XF86MonBrightnessDown", 0x1008FF03 },
{ "XF86KbdLightOnOff", 0x1008FF04 },
{ "XF86KbdBrightnessUp", 0x1008FF05 },
{ "XF86KbdBrightnessDown", 0x1008FF06 },
{ "XF86MonBrightnessCycle", 0x1008FF07 },
1191
1192
1193
1194
1195
1196
1197























1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{ "XF86Switch_VT_12", 0x1008FE0C },
{ "XF86Ungrab", 0x1008FE20 },
{ "XF86ClearGrab", 0x1008FE21 },
{ "XF86Next_VMode", 0x1008FE22 },
{ "XF86Prev_VMode", 0x1008FE23 },
{ "XF86LogWindowTree", 0x1008FE24 },
{ "XF86LogGrabInfo", 0x1008FE25 },
{ "SunFA_Grave", 0x1005FF00 },
{ "SunFA_Circum", 0x1005FF01 },
{ "SunFA_Tilde", 0x1005FF02 },
{ "SunFA_Acute", 0x1005FF03 },
{ "SunFA_Diaeresis", 0x1005FF04 },
{ "SunFA_Cedilla", 0x1005FF05 },
{ "SunF36", 0x1005FF10 },
{ "SunF37", 0x1005FF11 },
{ "SunSys_Req", 0x1005FF60 },
{ "SunProps", 0x1005FF70 },
{ "SunFront", 0x1005FF71 },
{ "SunCopy", 0x1005FF72 },
{ "SunOpen", 0x1005FF73 },
{ "SunPaste", 0x1005FF74 },
{ "SunCut", 0x1005FF75 },
{ "SunPowerSwitch", 0x1005FF76 },
{ "SunAudioLowerVolume", 0x1005FF77 },
{ "SunAudioMute", 0x1005FF78 },
{ "SunAudioRaiseVolume", 0x1005FF79 },
{ "SunVideoDegauss", 0x1005FF7A },
{ "SunVideoLowerBrightness", 0x1005FF7B },
{ "SunVideoRaiseBrightness", 0x1005FF7C },
{ "SunPowerSwitchShift", 0x1005FF7D },
Added generic/nanosvg.h.


























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
 * Copyright (c) 2013-14 Mikko Mononen [email protected]
 *
 * This software is provided 'as-is', without any express or implied
 * warranty.  In no event will the authors be held liable for any damages
 * arising from the use of this software.
 *
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
 *
 * 1. The origin of this software must not be misrepresented; you must not
 * claim that you wrote the original software. If you use this software
 * in a product, an acknowledgment in the product documentation would be
 * appreciated but is not required.
 * 2. Altered source versions must be plainly marked as such, and must not be
 * misrepresented as being the original software.
 * 3. This notice may not be removed or altered from any source distribution.
 *
 * The SVG parser is based on Anti-Grain Geometry 2.4 SVG example
 * Copyright (C) 2002-2004 Maxim Shemanarev (McSeem) (http://www.antigrain.com/)
 *
 * Arc calculation code based on canvg (https://code.google.com/p/canvg/)
 *
 * Bounding box calculation based on http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html
 *
 */

#ifndef NANOSVG_H
#define NANOSVG_H

#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.
 */


/* Example Usage:
	// Load SVG
	NSVGimage* image;
	image = nsvgParseFromFile("test.svg", "px", 96);
	printf("size: %f x %f\n", image->width, image->height);
	// Use...
	for (NSVGshape *shape = image->shapes; shape != NULL; shape = shape->next) {
		for (NSVGpath *path = shape->paths; path != NULL; path = path->next) {
			for (int i = 0; i < path->npts-1; i += 3) {
				float* p = &path->pts[i*2];
				drawCubicBez(p[0],p[1], p[2],p[3], p[4],p[5], p[6],p[7]);
			}
		}
	}
	// Delete
	nsvgDelete(image);
*/

#ifndef NANOSVG_SCOPE
#define NANOSVG_SCOPE
#endif

#ifndef NANOSVG_malloc
#define NANOSVG_malloc malloc
#endif

#ifndef NANOSVG_realloc
#define NANOSVG_realloc realloc
#endif

#ifndef NANOSVG_free
#define NANOSVG_free free
#endif

/* 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)
#define fabsf(a) (float)fabs(a)
#define acosf(a) (float)acos(a)
#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 */
#if defined(_MSC_VER) && (_MSC_VER == 1400)
#define fabsf(a) (float)fabs(a)
#endif

enum NSVGpaintType {
	NSVG_PAINT_NONE = 0,
	NSVG_PAINT_COLOR = 1,
	NSVG_PAINT_LINEAR_GRADIENT = 2,
	NSVG_PAINT_RADIAL_GRADIENT = 3
};

enum NSVGspreadType {
	NSVG_SPREAD_PAD = 0,
	NSVG_SPREAD_REFLECT = 1,
	NSVG_SPREAD_REPEAT = 2
};

enum NSVGlineJoin {
	NSVG_JOIN_MITER = 0,
	NSVG_JOIN_ROUND = 1,
	NSVG_JOIN_BEVEL = 2
};

enum NSVGlineCap {
	NSVG_CAP_BUTT = 0,
	NSVG_CAP_ROUND = 1,
	NSVG_CAP_SQUARE = 2
};

enum NSVGfillRule {
	NSVG_FILLRULE_NONZERO = 0,
	NSVG_FILLRULE_EVENODD = 1
};

enum NSVGflags {
	NSVG_FLAGS_VISIBLE = 0x01
};

typedef struct NSVGgradientStop {
	unsigned int color;
	float offset;
} NSVGgradientStop;

typedef struct NSVGgradient {
	float xform[6];
	char spread;
	float fx, fy;
	int nstops;
	NSVGgradientStop stops[1];
} NSVGgradient;

typedef struct NSVGpaint {
	char type;
	union {
		unsigned int color;
		NSVGgradient* gradient;
	};
} 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. */
} 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. */
} 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. */
} NSVGimage;

/* 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. */
NANOSVG_SCOPE NSVGimage* nsvgParse(char* input, const char* units, float dpi);

/* Deletes list of paths. */
NANOSVG_SCOPE void nsvgDelete(NSVGimage* image);

#ifdef __cplusplus
}
#endif

#endif /* NANOSVG_H */

#ifdef NANOSVG_IMPLEMENTATION

#include <string.h>
#include <stdlib.h>
#include <math.h>

#define NSVG_PI (3.14159265358979323846264338327f)
#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
#define NSVG_ALIGN_MEET 1
#define NSVG_ALIGN_SLICE 2

#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 */
	#ifdef __cplusplus
	#define NSVG_INLINE inline
	#else
	#define NSVG_INLINE
	#endif
	#if !defined(strtoll)           /* old MSVC versions do not have strtoll() */
		#define strtoll _strtoi64
	#endif
#else
	#define NSVG_INLINE inline
#endif


static int nsvg__isspace(char c)
{
	return strchr(" \t\n\v\f\r", c) != 0;
}

static int nsvg__isdigit(char c)
{
	return c >= '0' && c <= '9';
}

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 */

#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 */
	while (*s && nsvg__isspace(*s)) s++;
	if (!*s) return;

	if (contentCb)
		(*contentCb)(ud, s);
}

static void nsvg__parseElement(char* s,
							   void (*startelCb)(void* ud, const char* el, const char** attr),
							   void (*endelCb)(void* ud, const char* el),
							   void* ud)
{
	const char* attr[NSVG_XML_MAX_ATTRIBS];
	int nattr = 0;
	char* cbname;
	int start = 0;
	int end = 0;
	char quote;

	/* Skip white space after the '<' */
	while (*s && nsvg__isspace(*s)) s++;

	/* Check if the tag is end tag */
	if (*s == '/') {
		s++;
		end = 1;
	} else {
		start = 1;
	}

	/* Skip comments, data and preprocessor stuff. */
	if (!*s || *s == '?' || *s == '!')
		return;

	/* Get tag name */
	cbname = s;
	while (*s && !nsvg__isspace(*s)) s++;
	if (*s) { *s++ = '\0'; }

	/* Get attribs */
	while (!end && *s && nattr < NSVG_XML_MAX_ATTRIBS-3) {
		char* name = NULL;
		char* value = NULL;

		/* 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. */
		while (*s && !nsvg__isspace(*s) && *s != '=') s++;
		if (*s) { *s++ = '\0'; }
		/* 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. */
		value = s;
		while (*s && *s != quote) s++;
		if (*s) { *s++ = '\0'; }

		/* Store only well formed attributes */
		if (name && value) {
			attr[nattr++] = name;
			attr[nattr++] = value;
		}
	}

	/* List terminator */
	attr[nattr++] = 0;
	attr[nattr++] = 0;

	/* Call callbacks. */
	if (start && startelCb)
		(*startelCb)(ud, cbname, attr);
	if (end && endelCb)
		(*endelCb)(ud, cbname);
}

NANOSVG_SCOPE
int nsvg__parseXML(char* input,
				   void (*startelCb)(void* ud, const char* el, const char** attr),
				   void (*endelCb)(void* ud, const char* el),
				   void (*contentCb)(void* ud, const char* s),
				   void* ud)
{
	char* s = input;
	char* mark = s;
	int state = NSVG_XML_CONTENT;
	while (*s) {
		if (*s == '<' && state == NSVG_XML_CONTENT) {
			/* 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. */
			*s++ = '\0';
			nsvg__parseContent(mark, contentCb, ud);
			nsvg__parseElement(mark, startelCb, endelCb, ud);
			mark = s;
			state = NSVG_XML_CONTENT;
		} else {
			s++;
		}
	}

	return 1;
}


/* Simple SVG parser. */

#define NSVG_MAX_ATTR 128

enum NSVGgradientUnits {
	NSVG_USER_SPACE = 0,
	NSVG_OBJECT_SPACE = 1
};

#define NSVG_MAX_DASHES 8

enum NSVGunits {
	NSVG_UNITS_USER,
	NSVG_UNITS_PX,
	NSVG_UNITS_PT,
	NSVG_UNITS_PC,
	NSVG_UNITS_MM,
	NSVG_UNITS_CM,
	NSVG_UNITS_IN,
	NSVG_UNITS_PERCENT,
	NSVG_UNITS_EM,
	NSVG_UNITS_EX
};

enum NSVGvisible {
	NSVG_VIS_DISPLAY = 1,
	NSVG_VIS_VISIBLE = 2
};

typedef struct NSVGcoordinate {
	float value;
	int units;
} NSVGcoordinate;

typedef struct NSVGlinearData {
	NSVGcoordinate x1, y1, x2, y2;
} NSVGlinearData;

typedef struct NSVGradialData {
	NSVGcoordinate cx, cy, r, fx, fy;
} NSVGradialData;

typedef struct NSVGgradientData
{
	char id[64];
	char ref[64];
	char type;
	union {
		NSVGlinearData linear;
		NSVGradialData radial;
	};
	char spread;
	char units;
	float xform[6];
	int nstops;
	NSVGgradientStop* stops;
	struct NSVGgradientData* next;
} NSVGgradientData;

typedef struct NSVGattrib
{
	char id[64];
	float xform[6];
	unsigned int fillColor;
	unsigned int strokeColor;
	float opacity;
	float fillOpacity;
	float strokeOpacity;
	char fillGradient[64];
	char strokeGradient[64];
	float strokeWidth;
	float strokeDashOffset;
	float strokeDashArray[NSVG_MAX_DASHES];
	int strokeDashCount;
	char strokeLineJoin;
	char strokeLineCap;
	float miterLimit;
	char fillRule;
	float fontSize;
	unsigned int stopColor;
	float stopOpacity;
	float stopOffset;
	char hasFill;
	char hasStroke;
	char visible;
} NSVGattrib;

typedef struct NSVGstyles
{
	char*	name;
	char* description;
	struct NSVGstyles* next;
} NSVGstyles;

typedef struct NSVGparser
{
	NSVGattrib attr[NSVG_MAX_ATTR];
	int attrHead;
	float* pts;
	int npts;
	int cpts;
	NSVGpath* plist;
	NSVGimage* image;
	NSVGstyles* styles;
	NSVGgradientData* gradients;
	NSVGshape* shapesTail;
	float viewMinx, viewMiny, viewWidth, viewHeight;
	int alignX, alignY, alignType;
	float dpi;
	char pathFlag;
	char defsFlag;
	char styleFlag;
} NSVGparser;

static void nsvg__xformIdentity(float* t)
{
	t[0] = 1.0f; t[1] = 0.0f;
	t[2] = 0.0f; t[3] = 1.0f;
	t[4] = 0.0f; t[5] = 0.0f;
}

static void nsvg__xformSetTranslation(float* t, float tx, float ty)
{
	t[0] = 1.0f; t[1] = 0.0f;
	t[2] = 0.0f; t[3] = 1.0f;
	t[4] = tx; t[5] = ty;
}

static void nsvg__xformSetScale(float* t, float sx, float sy)
{
	t[0] = sx; t[1] = 0.0f;
	t[2] = 0.0f; t[3] = sy;
	t[4] = 0.0f; t[5] = 0.0f;
}

static void nsvg__xformSetSkewX(float* t, float a)
{
	t[0] = 1.0f; t[1] = 0.0f;
	t[2] = tanf(a); t[3] = 1.0f;
	t[4] = 0.0f; t[5] = 0.0f;
}

static void nsvg__xformSetSkewY(float* t, float a)
{
	t[0] = 1.0f; t[1] = tanf(a);
	t[2] = 0.0f; t[3] = 1.0f;
	t[4] = 0.0f; t[5] = 0.0f;
}

static void nsvg__xformSetRotation(float* t, float a)
{
	float cs = cosf(a), sn = sinf(a);
	t[0] = cs; t[1] = sn;
	t[2] = -sn; t[3] = cs;
	t[4] = 0.0f; t[5] = 0.0f;
}

static void nsvg__xformMultiply(float* t, float* s)
{
	float t0 = t[0] * s[0] + t[1] * s[2];
	float t2 = t[2] * s[0] + t[3] * s[2];
	float t4 = t[4] * s[0] + t[5] * s[2] + s[4];
	t[1] = t[0] * s[1] + t[1] * s[3];
	t[3] = t[2] * s[1] + t[3] * s[3];
	t[5] = t[4] * s[1] + t[5] * s[3] + s[5];
	t[0] = t0;
	t[2] = t2;
	t[4] = t4;
}

static void nsvg__xformInverse(float* inv, float* t)
{
	double invdet, det = (double)t[0] * t[3] - (double)t[2] * t[1];
	if (det > -1e-6 && det < 1e-6) {
		nsvg__xformIdentity(t);
		return;
	}
	invdet = 1.0 / det;
	inv[0] = (float)(t[3] * invdet);
	inv[2] = (float)(-t[2] * invdet);
	inv[4] = (float)(((double)t[2] * t[5] - (double)t[3] * t[4]) * invdet);
	inv[1] = (float)(-t[1] * invdet);
	inv[3] = (float)(t[0] * invdet);
	inv[5] = (float)(((double)t[1] * t[4] - (double)t[0] * t[5]) * invdet);
}

static void nsvg__xformPremultiply(float* t, float* s)
{
	float s2[6];
	memcpy(s2, s, sizeof(float)*6);
	nsvg__xformMultiply(s2, t);
	memcpy(t, s2, sizeof(float)*6);
}

static void nsvg__xformPoint(float* dx, float* dy, float x, float y, float* t)
{
	*dx = x*t[0] + y*t[2] + t[4];
	*dy = x*t[1] + y*t[3] + t[5];
}

static void nsvg__xformVec(float* dx, float* dy, float x, float y, float* t)
{
	*dx = x*t[0] + y*t[2];
	*dy = x*t[1] + y*t[3];
}

#define NSVG_EPSILON (1e-12)

static int nsvg__ptInBounds(float* pt, float* bounds)
{
	return pt[0] >= bounds[0] && pt[0] <= bounds[2] && pt[1] >= bounds[1] && pt[1] <= bounds[3];
}


static double nsvg__evalBezier(double t, double p0, double p1, double p2, double p3)
{
	double it = 1.0-t;
	return it*it*it*p0 + 3.0*it*it*t*p1 + 3.0*it*t*t*p2 + t*t*t*p3;
}

static void nsvg__curveBounds(float* bounds, float* curve)
{
	int i, j, count;
	double roots[2], a, b, c, b2ac, t, v;
	float* v0 = &curve[0];
	float* v1 = &curve[2];
	float* v2 = &curve[4];
	float* v3 = &curve[6];

	/* 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. */
	if (nsvg__ptInBounds(v1, bounds) && nsvg__ptInBounds(v2, bounds))
		return;

	/* 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;
		if (fabs(a) < NSVG_EPSILON) {
			if (fabs(b) > NSVG_EPSILON) {
				t = -c / b;
				if (t > NSVG_EPSILON && t < 1.0-NSVG_EPSILON)
					roots[count++] = t;
			}
		} else {
			b2ac = b*b - 4.0*c*a;
			if (b2ac > NSVG_EPSILON) {
				t = (-b + sqrt(b2ac)) / (2.0 * a);
				if (t > NSVG_EPSILON && t < 1.0-NSVG_EPSILON)
					roots[count++] = t;
				t = (-b - sqrt(b2ac)) / (2.0 * a);
				if (t > NSVG_EPSILON && t < 1.0-NSVG_EPSILON)
					roots[count++] = t;
			}
		}
		for (j = 0; j < count; j++) {
			v = nsvg__evalBezier(roots[j], v0[i], v1[i], v2[i], v3[i]);
			bounds[0+i] = nsvg__minf(bounds[0+i], (float)v);
			bounds[2+i] = nsvg__maxf(bounds[2+i], (float)v);
		}
	}
}

static NSVGparser* nsvg__createParser(void)
{
	NSVGparser* p;
	p = (NSVGparser*)NANOSVG_malloc(sizeof(NSVGparser));
	if (p == NULL) goto error;
	memset(p, 0, sizeof(NSVGparser));

	p->image = (NSVGimage*)NANOSVG_malloc(sizeof(NSVGimage));
	if (p->image == NULL) goto error;
	memset(p->image, 0, sizeof(NSVGimage));

	/* 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;
	p->attr[0].fillOpacity = 1;
	p->attr[0].strokeOpacity = 1;
	p->attr[0].stopOpacity = 1;
	p->attr[0].strokeWidth = 1;
	p->attr[0].strokeLineJoin = NSVG_JOIN_MITER;
	p->attr[0].strokeLineCap = NSVG_CAP_BUTT;
	p->attr[0].miterLimit = 4;
	p->attr[0].fillRule = NSVG_FILLRULE_NONZERO;
	p->attr[0].hasFill = 1;
	p->attr[0].visible = NSVG_VIS_DISPLAY | NSVG_VIS_VISIBLE;

	return p;

error:
	if (p) {
		if (p->image) NANOSVG_free(p->image);
		NANOSVG_free(p);
	}
	return NULL;
}

static void nsvg__deleteStyles(NSVGstyles* style) {
	while (style) {
		NSVGstyles *next = style->next;
		if (style->name!= NULL)
			NANOSVG_free(style->name);
		if (style->description != NULL)
			NANOSVG_free(style->description);
		NANOSVG_free(style);
		style = next;
	}
}

static void nsvg__deletePaths(NSVGpath* path)
{
	while (path) {
		NSVGpath *next = path->next;
		if (path->pts != NULL)
			NANOSVG_free(path->pts);
		NANOSVG_free(path);
		path = next;
	}
}

static void nsvg__deletePaint(NSVGpaint* paint)
{
	if (paint->type == NSVG_PAINT_LINEAR_GRADIENT || paint->type == NSVG_PAINT_RADIAL_GRADIENT)
		NANOSVG_free(paint->gradient);
}

static void nsvg__deleteGradientData(NSVGgradientData* grad)
{
	NSVGgradientData* next;
	while (grad != NULL) {
		next = grad->next;
		NANOSVG_free(grad->stops);
		NANOSVG_free(grad);
		grad = next;
	}
}

static void nsvg__deleteParser(NSVGparser* p)
{
	if (p != NULL) {
		nsvg__deleteStyles(p->styles);
		nsvg__deletePaths(p->plist);
		nsvg__deleteGradientData(p->gradients);
		nsvgDelete(p->image);
		NANOSVG_free(p->pts);
		NANOSVG_free(p);
	}
}

static void nsvg__resetPath(NSVGparser* p)
{
	p->npts = 0;
}

static void nsvg__addPoint(NSVGparser* p, float x, float y)
{
	if (p->npts+1 > p->cpts) {
		p->cpts = p->cpts ? p->cpts*2 : 8;
		p->pts = (float*)NANOSVG_realloc(p->pts, p->cpts*2*sizeof(float));
		if (!p->pts) return;
	}
	p->pts[p->npts*2+0] = x;
	p->pts[p->npts*2+1] = y;
	p->npts++;
}

static void nsvg__moveTo(NSVGparser* p, float x, float y)
{
	if (p->npts > 0) {
		p->pts[(p->npts-1)*2+0] = x;
		p->pts[(p->npts-1)*2+1] = y;
	} else {
		nsvg__addPoint(p, x, y);
	}
}

static void nsvg__lineTo(NSVGparser* p, float x, float y)
{
	float px,py, dx,dy;
	if (p->npts > 0) {
		px = p->pts[(p->npts-1)*2+0];
		py = p->pts[(p->npts-1)*2+1];
		dx = x - px;
		dy = y - py;
		nsvg__addPoint(p, px + dx/3.0f, py + dy/3.0f);
		nsvg__addPoint(p, x - dx/3.0f, y - dy/3.0f);
		nsvg__addPoint(p, x, y);
	}
}

static void nsvg__cubicBezTo(NSVGparser* p, float cpx1, float cpy1, float cpx2, float cpy2, float x, float y)
{
	if (p->npts > 0) {
		nsvg__addPoint(p, cpx1, cpy1);
		nsvg__addPoint(p, cpx2, cpy2);
		nsvg__addPoint(p, x, y);
	}
}

static NSVGattrib* nsvg__getAttr(NSVGparser* p)
{
	return &p->attr[p->attrHead];
}

static void nsvg__pushAttr(NSVGparser* p)
{
	if (p->attrHead < NSVG_MAX_ATTR-1) {
		p->attrHead++;
		memcpy(&p->attr[p->attrHead], &p->attr[p->attrHead-1], sizeof(NSVGattrib));
	}
}

static void nsvg__popAttr(NSVGparser* p)
{
	if (p->attrHead > 0)
		p->attrHead--;
}

static float nsvg__actualOrigX(NSVGparser* p)
{
	return p->viewMinx;
}

static float nsvg__actualOrigY(NSVGparser* p)
{
	return p->viewMiny;
}

static float nsvg__actualWidth(NSVGparser* p)
{
	return p->viewWidth;
}

static float nsvg__actualHeight(NSVGparser* p)
{
	return p->viewHeight;
}

static float nsvg__actualLength(NSVGparser* p)
{
	float w = nsvg__actualWidth(p), h = nsvg__actualHeight(p);
	return sqrtf(w*w + h*h) / sqrtf(2.0f);
}

static float nsvg__convertToPixels(NSVGparser* p, NSVGcoordinate c, float orig, float length)
{
	NSVGattrib* attr = nsvg__getAttr(p);
	switch (c.units) {
		case NSVG_UNITS_USER:		return c.value;
		case NSVG_UNITS_PX:			return c.value;
		case NSVG_UNITS_PT:			return c.value / 72.0f * p->dpi;
		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_PERCENT:	return orig + c.value / 100.0f * length;
		default:					return c.value;
	}
	return c.value;
}

static NSVGgradientData* nsvg__findGradientData(NSVGparser* p, const char* id)
{
	NSVGgradientData* grad = p->gradients;
	if (id == NULL || *id == '\0')
		return NULL;
	while (grad != NULL) {
		if (strcmp(grad->id, id) == 0)
			return grad;
		grad = grad->next;
	}
	return NULL;
}

static NSVGgradient* nsvg__createGradient(NSVGparser* p, const char* id, const float* localBounds, char* paintType)
{
	NSVGattrib* attr = nsvg__getAttr(p);
	NSVGgradientData* data = NULL;
	NSVGgradientData* ref = NULL;
	NSVGgradientStop* stops = NULL;
	NSVGgradient* grad;
	float ox, oy, sw, sh, sl;
	int nstops = 0;
	int refIter;

	data = nsvg__findGradientData(p, id);
	if (data == NULL) return NULL;

	/* 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) {
			stops = ref->stops;
			nstops = ref->nstops;
			break;
		}
		nextRef = nsvg__findGradientData(p, ref->ref);
		if (nextRef == ref) break; /* prevent infite loops on malformed data */
		ref = nextRef;
		refIter++;
		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. */
	if (data->units == NSVG_OBJECT_SPACE) {
		ox = localBounds[0];
		oy = localBounds[1];
		sw = localBounds[2] - localBounds[0];
		sh = localBounds[3] - localBounds[1];
	} else {
		ox = nsvg__actualOrigX(p);
		oy = nsvg__actualOrigY(p);
		sw = nsvg__actualWidth(p);
		sh = nsvg__actualHeight(p);
	}
	sl = sqrtf(sw*sw + sh*sh) / sqrtf(2.0f);

	if (data->type == NSVG_PAINT_LINEAR_GRADIENT) {
		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 */
		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;
	} else {
		float cx, cy, fx, fy, r;
		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 */
		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;
	}

	nsvg__xformMultiply(grad->xform, data->xform);
	nsvg__xformMultiply(grad->xform, attr->xform);

	grad->spread = data->spread;
	memcpy(grad->stops, stops, nstops*sizeof(NSVGgradientStop));
	grad->nstops = nstops;

	*paintType = data->type;

	return grad;
}

static float nsvg__getAverageScale(float* t)
{
	float sx = sqrtf(t[0]*t[0] + t[2]*t[2]);
	float sy = sqrtf(t[1]*t[1] + t[3]*t[3]);
	return (sx + sy) * 0.5f;
}

static void nsvg__getLocalBounds(float* bounds, NSVGshape *shape, float* xform)
{
	NSVGpath* path;
	float curve[4*2], curveBounds[4];
	int i, first = 1;
	for (path = shape->paths; path != NULL; path = path->next) {
		nsvg__xformPoint(&curve[0], &curve[1], path->pts[0], path->pts[1], xform);
		for (i = 0; i < path->npts-1; i += 3) {
			nsvg__xformPoint(&curve[2], &curve[3], path->pts[(i+1)*2], path->pts[(i+1)*2+1], xform);
			nsvg__xformPoint(&curve[4], &curve[5], path->pts[(i+2)*2], path->pts[(i+2)*2+1], xform);
			nsvg__xformPoint(&curve[6], &curve[7], path->pts[(i+3)*2], path->pts[(i+3)*2+1], xform);
			nsvg__curveBounds(curveBounds, curve);
			if (first) {
				bounds[0] = curveBounds[0];
				bounds[1] = curveBounds[1];
				bounds[2] = curveBounds[2];
				bounds[3] = curveBounds[3];
				first = 0;
			} else {
				bounds[0] = nsvg__minf(bounds[0], curveBounds[0]);
				bounds[1] = nsvg__minf(bounds[1], curveBounds[1]);
				bounds[2] = nsvg__maxf(bounds[2], curveBounds[2]);
				bounds[3] = nsvg__maxf(bounds[3], curveBounds[3]);
			}
			curve[0] = curve[6];
			curve[1] = curve[7];
		}
	}
}

static void nsvg__addShape(NSVGparser* p)
{
	NSVGattrib* attr = nsvg__getAttr(p);
	float scale = 1.0f;
	NSVGshape* shape;
	NSVGpath* path;
	int i;

	if (p->plist == NULL)
		return;

	shape = (NSVGshape*)NANOSVG_malloc(sizeof(NSVGshape));
	if (shape == NULL) goto error;
	memset(shape, 0, sizeof(NSVGshape));

	memcpy(shape->id, attr->id, sizeof shape->id);
	scale = nsvg__getAverageScale(attr->xform);
	shape->strokeWidth = attr->strokeWidth * scale;
	shape->strokeDashOffset = attr->strokeDashOffset * scale;
	shape->strokeDashCount = (char)attr->strokeDashCount;
	for (i = 0; i < attr->strokeDashCount; i++)
		shape->strokeDashArray[i] = attr->strokeDashArray[i] * scale;
	shape->strokeLineJoin = attr->strokeLineJoin;
	shape->strokeLineCap = attr->strokeLineCap;
	shape->miterLimit = attr->miterLimit;
	shape->fillRule = attr->fillRule;
	shape->opacity = attr->opacity;

	shape->paths = p->plist;
	p->plist = NULL;

	/* 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) {
		shape->bounds[0] = nsvg__minf(shape->bounds[0], path->bounds[0]);
		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 */
	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;
		shape->fill.color |= (unsigned int)(attr->fillOpacity*255) << 24;
	} else if (attr->hasFill == 2) {
		float inv[6], localBounds[4];
		nsvg__xformInverse(inv, attr->xform);
		nsvg__getLocalBounds(localBounds, shape, inv);
		shape->fill.gradient = nsvg__createGradient(p, attr->fillGradient, localBounds, &shape->fill.type);
		if (shape->fill.gradient == NULL) {
			shape->fill.type = NSVG_PAINT_NONE;
		}
	}

	/* 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;
		shape->stroke.color |= (unsigned int)(attr->strokeOpacity*255) << 24;
	} else if (attr->hasStroke == 2) {
		float inv[6], localBounds[4];
		nsvg__xformInverse(inv, attr->xform);
		nsvg__getLocalBounds(localBounds, shape, inv);
		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 */
	shape->flags = ((attr->visible & NSVG_VIS_DISPLAY) && (attr->visible & NSVG_VIS_VISIBLE) ? NSVG_FLAGS_VISIBLE : 0x00);

	/* Add to tail */
	if (p->image->shapes == NULL)
		p->image->shapes = shape;
	else
		p->shapesTail->next = shape;
	p->shapesTail = shape;

	return;

error:
	if (shape) NANOSVG_free(shape);
}

static void nsvg__addPath(NSVGparser* p, char closed)
{
	NSVGattrib* attr = nsvg__getAttr(p);
	NSVGpath* path = NULL;
	float bounds[4];
	float* curve;
	int i;

	if (p->npts < 4)
		return;

	if (closed)
		nsvg__lineTo(p, p->pts[0], p->pts[1]);

	/* 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;
	memset(path, 0, sizeof(NSVGpath));

	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. */
	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 */
	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];
			path->bounds[1] = bounds[1];
			path->bounds[2] = bounds[2];
			path->bounds[3] = bounds[3];
		} else {
			path->bounds[0] = nsvg__minf(path->bounds[0], bounds[0]);
			path->bounds[1] = nsvg__minf(path->bounds[1], bounds[1]);
			path->bounds[2] = nsvg__maxf(path->bounds[2], bounds[2]);
			path->bounds[3] = nsvg__maxf(path->bounds[3], bounds[3]);
		}
	}

	path->next = p->plist;
	p->plist = path;

	return;

error:
	if (path != NULL) {
		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. */
static double nsvg__atof(const char* s)
{
	char* cur = (char*)s;
	char* end = NULL;
	double res = 0.0, sign = 1.0;
#if defined(_MSC_VER) && (_MSC_VER == 1200)
	__int64 intPart = 0, fracPart = 0;
#else
	long long intPart = 0, fracPart = 0;
#endif
	char hasIntPart = 0, hasFracPart = 0;

	/* Parse optional sign */
	if (*cur == '+') {
		cur++;
	} else if (*cur == '-') {
		sign = -1;
		cur++;
	}

	/* Parse integer part */
	if (nsvg__isdigit(*cur)) {
		/* Parse digit sequence */
#if defined(_MSC_VER) && (_MSC_VER == 1200)
		intPart = strtol(cur, &end, 10);
#else
		intPart = strtoll(cur, &end, 10);
#endif
		if (cur != end) {
			res = (double)intPart;
			hasIntPart = 1;
			cur = end;
		}
	}

	/* Parse fractional part. */
	if (*cur == '.') {
		cur++; /* Skip '.' */
		if (nsvg__isdigit(*cur)) {
			/* Parse digit sequence */
#if defined(_MSC_VER) && (_MSC_VER == 1200)
			fracPart = strtol(cur, &end, 10);
#else
			fracPart = strtoll(cur, &end, 10);
#endif
			if (cur != end) {
				res += (double)fracPart / pow(10.0, (double)(end - cur));
				hasFracPart = 1;
				cur = end;
			}
		}
	}

	/* A valid number should have integer or fractional part. */
	if (!hasIntPart && !hasFracPart)
		return 0.0;

	/* Parse optional exponent */
	if (*cur == 'e' || *cur == 'E') {
		int expPart = 0;
		cur++; /* skip 'E' */
		expPart = strtol(cur, &end, 10); /* Parse digit sequence with sign */
		if (cur != end) {
			res *= pow(10.0, (double)expPart);
		}
	}

	return res * sign;
}


static const char* nsvg__parseNumber(const char* s, char* it, const int size)
{
	const int last = size-1;
	int i = 0;

	/* sign */
	if (*s == '-' || *s == '+') {
		if (i < last) it[i++] = *s;
		s++;
	}
	/* integer part */
	while (*s && nsvg__isdigit(*s)) {
		if (i < last) it[i++] = *s;
		s++;
	}
	if (*s == '.') {
		/* decimal point */
		if (i < last) it[i++] = *s;
		s++;
		/* fraction part */
		while (*s && nsvg__isdigit(*s)) {
			if (i < last) it[i++] = *s;
			s++;
		}
	}
	/* exponent */
	if (*s == 'e' || *s == 'E') {
		if (i < last) it[i++] = *s;
		s++;
		if (*s == '-' || *s == '+') {
			if (i < last) it[i++] = *s;
			s++;
		}
		while (*s && nsvg__isdigit(*s)) {
			if (i < last) it[i++] = *s;
			s++;
		}
	}
	it[i] = '\0';

	return s;
}

static const char* nsvg__getNextPathItem(const char* s, char* it)
{
	it[0] = '\0';
	/* 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 */
		it[0] = *s++;
		it[1] = '\0';
		return s;
	}

	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);
}

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);
	}
}

typedef struct NSVGNamedColor {
	const char* name;
	unsigned int color;
} NSVGNamedColor;

NSVGNamedColor nsvg__colors[] = {

	{ "red", NSVG_RGB(255, 0, 0) },
	{ "green", NSVG_RGB( 0, 128, 0) },
	{ "blue", NSVG_RGB( 0, 0, 255) },
	{ "yellow", NSVG_RGB(255, 255, 0) },
	{ "cyan", NSVG_RGB( 0, 255, 255) },
	{ "magenta", NSVG_RGB(255, 0, 255) },
	{ "black", NSVG_RGB( 0, 0, 0) },
	{ "grey", NSVG_RGB(128, 128, 128) },
	{ "gray", NSVG_RGB(128, 128, 128) },
	{ "white", NSVG_RGB(255, 255, 255) },

#ifdef NANOSVG_ALL_COLOR_KEYWORDS
	{ "aliceblue", NSVG_RGB(240, 248, 255) },
	{ "antiquewhite", NSVG_RGB(250, 235, 215) },
	{ "aqua", NSVG_RGB( 0, 255, 255) },
	{ "aquamarine", NSVG_RGB(127, 255, 212) },
	{ "azure", NSVG_RGB(240, 255, 255) },
	{ "beige", NSVG_RGB(245, 245, 220) },
	{ "bisque", NSVG_RGB(255, 228, 196) },
	{ "blanchedalmond", NSVG_RGB(255, 235, 205) },
	{ "blueviolet", NSVG_RGB(138, 43, 226) },
	{ "brown", NSVG_RGB(165, 42, 42) },
	{ "burlywood", NSVG_RGB(222, 184, 135) },
	{ "cadetblue", NSVG_RGB( 95, 158, 160) },
	{ "chartreuse", NSVG_RGB(127, 255, 0) },
	{ "chocolate", NSVG_RGB(210, 105, 30) },
	{ "coral", NSVG_RGB(255, 127, 80) },
	{ "cornflowerblue", NSVG_RGB(100, 149, 237) },
	{ "cornsilk", NSVG_RGB(255, 248, 220) },
	{ "crimson", NSVG_RGB(220, 20, 60) },
	{ "darkblue", NSVG_RGB( 0, 0, 139) },
	{ "darkcyan", NSVG_RGB( 0, 139, 139) },
	{ "darkgoldenrod", NSVG_RGB(184, 134, 11) },
	{ "darkgray", NSVG_RGB(169, 169, 169) },
	{ "darkgreen", NSVG_RGB( 0, 100, 0) },
	{ "darkgrey", NSVG_RGB(169, 169, 169) },
	{ "darkkhaki", NSVG_RGB(189, 183, 107) },
	{ "darkmagenta", NSVG_RGB(139, 0, 139) },
	{ "darkolivegreen", NSVG_RGB( 85, 107, 47) },
	{ "darkorange", NSVG_RGB(255, 140, 0) },
	{ "darkorchid", NSVG_RGB(153, 50, 204) },
	{ "darkred", NSVG_RGB(139, 0, 0) },
	{ "darksalmon", NSVG_RGB(233, 150, 122) },
	{ "darkseagreen", NSVG_RGB(143, 188, 143) },
	{ "darkslateblue", NSVG_RGB( 72, 61, 139) },
	{ "darkslategray", NSVG_RGB( 47, 79, 79) },
	{ "darkslategrey", NSVG_RGB( 47, 79, 79) },
	{ "darkturquoise", NSVG_RGB( 0, 206, 209) },
	{ "darkviolet", NSVG_RGB(148, 0, 211) },
	{ "deeppink", NSVG_RGB(255, 20, 147) },
	{ "deepskyblue", NSVG_RGB( 0, 191, 255) },
	{ "dimgray", NSVG_RGB(105, 105, 105) },
	{ "dimgrey", NSVG_RGB(105, 105, 105) },
	{ "dodgerblue", NSVG_RGB( 30, 144, 255) },
	{ "firebrick", NSVG_RGB(178, 34, 34) },
	{ "floralwhite", NSVG_RGB(255, 250, 240) },
	{ "forestgreen", NSVG_RGB( 34, 139, 34) },
	{ "fuchsia", NSVG_RGB(255, 0, 255) },
	{ "gainsboro", NSVG_RGB(220, 220, 220) },
	{ "ghostwhite", NSVG_RGB(248, 248, 255) },
	{ "gold", NSVG_RGB(255, 215, 0) },
	{ "goldenrod", NSVG_RGB(218, 165, 32) },
	{ "greenyellow", NSVG_RGB(173, 255, 47) },
	{ "honeydew", NSVG_RGB(240, 255, 240) },
	{ "hotpink", NSVG_RGB(255, 105, 180) },
	{ "indianred", NSVG_RGB(205, 92, 92) },
	{ "indigo", NSVG_RGB( 75, 0, 130) },
	{ "ivory", NSVG_RGB(255, 255, 240) },
	{ "khaki", NSVG_RGB(240, 230, 140) },
	{ "lavender", NSVG_RGB(230, 230, 250) },
	{ "lavenderblush", NSVG_RGB(255, 240, 245) },
	{ "lawngreen", NSVG_RGB(124, 252, 0) },
	{ "lemonchiffon", NSVG_RGB(255, 250, 205) },
	{ "lightblue", NSVG_RGB(173, 216, 230) },
	{ "lightcoral", NSVG_RGB(240, 128, 128) },
	{ "lightcyan", NSVG_RGB(224, 255, 255) },
	{ "lightgoldenrodyellow", NSVG_RGB(250, 250, 210) },
	{ "lightgray", NSVG_RGB(211, 211, 211) },
	{ "lightgreen", NSVG_RGB(144, 238, 144) },
	{ "lightgrey", NSVG_RGB(211, 211, 211) },
	{ "lightpink", NSVG_RGB(255, 182, 193) },
	{ "lightsalmon", NSVG_RGB(255, 160, 122) },
	{ "lightseagreen", NSVG_RGB( 32, 178, 170) },
	{ "lightskyblue", NSVG_RGB(135, 206, 250) },
	{ "lightslategray", NSVG_RGB(119, 136, 153) },
	{ "lightslategrey", NSVG_RGB(119, 136, 153) },
	{ "lightsteelblue", NSVG_RGB(176, 196, 222) },
	{ "lightyellow", NSVG_RGB(255, 255, 224) },
	{ "lime", NSVG_RGB( 0, 255, 0) },
	{ "limegreen", NSVG_RGB( 50, 205, 50) },
	{ "linen", NSVG_RGB(250, 240, 230) },
	{ "maroon", NSVG_RGB(128, 0, 0) },
	{ "mediumaquamarine", NSVG_RGB(102, 205, 170) },
	{ "mediumblue", NSVG_RGB( 0, 0, 205) },
	{ "mediumorchid", NSVG_RGB(186, 85, 211) },
	{ "mediumpurple", NSVG_RGB(147, 112, 219) },
	{ "mediumseagreen", NSVG_RGB( 60, 179, 113) },
	{ "mediumslateblue", NSVG_RGB(123, 104, 238) },
	{ "mediumspringgreen", NSVG_RGB( 0, 250, 154) },
	{ "mediumturquoise", NSVG_RGB( 72, 209, 204) },
	{ "mediumvioletred", NSVG_RGB(199, 21, 133) },
	{ "midnightblue", NSVG_RGB( 25, 25, 112) },
	{ "mintcream", NSVG_RGB(245, 255, 250) },
	{ "mistyrose", NSVG_RGB(255, 228, 225) },
	{ "moccasin", NSVG_RGB(255, 228, 181) },
	{ "navajowhite", NSVG_RGB(255, 222, 173) },
	{ "navy", NSVG_RGB( 0, 0, 128) },
	{ "oldlace", NSVG_RGB(253, 245, 230) },
	{ "olive", NSVG_RGB(128, 128, 0) },
	{ "olivedrab", NSVG_RGB(107, 142, 35) },
	{ "orange", NSVG_RGB(255, 165, 0) },
	{ "orangered", NSVG_RGB(255, 69, 0) },
	{ "orchid", NSVG_RGB(218, 112, 214) },
	{ "palegoldenrod", NSVG_RGB(238, 232, 170) },
	{ "palegreen", NSVG_RGB(152, 251, 152) },
	{ "paleturquoise", NSVG_RGB(175, 238, 238) },
	{ "palevioletred", NSVG_RGB(219, 112, 147) },
	{ "papayawhip", NSVG_RGB(255, 239, 213) },
	{ "peachpuff", NSVG_RGB(255, 218, 185) },
	{ "peru", NSVG_RGB(205, 133, 63) },
	{ "pink", NSVG_RGB(255, 192, 203) },
	{ "plum", NSVG_RGB(221, 160, 221) },
	{ "powderblue", NSVG_RGB(176, 224, 230) },
	{ "purple", NSVG_RGB(128, 0, 128) },
	{ "rosybrown", NSVG_RGB(188, 143, 143) },
	{ "royalblue", NSVG_RGB( 65, 105, 225) },
	{ "saddlebrown", NSVG_RGB(139, 69, 19) },
	{ "salmon", NSVG_RGB(250, 128, 114) },
	{ "sandybrown", NSVG_RGB(244, 164, 96) },
	{ "seagreen", NSVG_RGB( 46, 139, 87) },
	{ "seashell", NSVG_RGB(255, 245, 238) },
	{ "sienna", NSVG_RGB(160, 82, 45) },
	{ "silver", NSVG_RGB(192, 192, 192) },
	{ "skyblue", NSVG_RGB(135, 206, 235) },
	{ "slateblue", NSVG_RGB(106, 90, 205) },
	{ "slategray", NSVG_RGB(112, 128, 144) },
	{ "slategrey", NSVG_RGB(112, 128, 144) },
	{ "snow", NSVG_RGB(255, 250, 250) },
	{ "springgreen", NSVG_RGB( 0, 255, 127) },
	{ "steelblue", NSVG_RGB( 70, 130, 180) },
	{ "tan", NSVG_RGB(210, 180, 140) },
	{ "teal", NSVG_RGB( 0, 128, 128) },
	{ "thistle", NSVG_RGB(216, 191, 216) },
	{ "tomato", NSVG_RGB(255, 99, 71) },
	{ "turquoise", NSVG_RGB( 64, 224, 208) },
	{ "violet", NSVG_RGB(238, 130, 238) },
	{ "wheat", NSVG_RGB(245, 222, 179) },
	{ "whitesmoke", NSVG_RGB(245, 245, 245) },
	{ "yellowgreen", NSVG_RGB(154, 205, 50) },
#endif
};

static unsigned int nsvg__parseColorName(const char* str)
{
	int i, ncolors = sizeof(nsvg__colors) / sizeof(NSVGNamedColor);

	for (i = 0; i < ncolors; i++) {
		if (strcmp(nsvg__colors[i].name, str) == 0) {
			return nsvg__colors[i].color;
		}
	}

	return NSVG_RGB(128, 128, 128);
}

static unsigned int nsvg__parseColor(const char* str)
{
	size_t len = 0;
	while(*str == ' ') ++str;
	len = strlen(str);
	if (len >= 1 && *str == '#')
		return nsvg__parseColorHex(str);
	else if (len >= 4 && str[0] == 'r' && str[1] == 'g' && str[2] == 'b' && str[3] == '(')
		return nsvg__parseColorRGB(str);
	return nsvg__parseColorName(str);
}

static float nsvg__parseOpacity(const char* str)
{
	float val = 0;
	sscanf(str, "%f", &val);
	if (val < 0.0f) val = 0.0f;
	if (val > 1.0f) val = 1.0f;
	return val;
}

static float nsvg__parseMiterLimit(const char* str)
{
	float val = 0;
	sscanf(str, "%f", &val);
	if (val < 0.0f) val = 0.0f;
	return val;
}

static int nsvg__parseUnits(const char* units)
{
	if (units[0] == 'p' && units[1] == 'x')
		return NSVG_UNITS_PX;
	else if (units[0] == 'p' && units[1] == 't')
		return NSVG_UNITS_PT;
	else if (units[0] == 'p' && units[1] == 'c')
		return NSVG_UNITS_PC;
	else if (units[0] == 'm' && units[1] == 'm')
		return NSVG_UNITS_MM;
	else if (units[0] == 'c' && units[1] == 'm')
		return NSVG_UNITS_CM;
	else if (units[0] == 'i' && units[1] == 'n')
		return NSVG_UNITS_IN;
	else if (units[0] == '%')
		return NSVG_UNITS_PERCENT;
	else if (units[0] == 'e' && units[1] == 'm')
		return NSVG_UNITS_EM;
	else if (units[0] == 'e' && units[1] == 'x')
		return NSVG_UNITS_EX;
	return NSVG_UNITS_USER;
}

static int nsvg__isCoordinate(const char* s)
{
	/* optional sign */
	if (*s == '-' || *s == '+')
		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};
	char units[32]="";
	sscanf(str, "%f%s", &coord.value, units);
	coord.units = nsvg__parseUnits(units);
	return coord;
}

static NSVGcoordinate nsvg__coord(float v, int units)
{
	NSVGcoordinate coord = {v, units};
	return coord;
}

static float nsvg__parseCoordinate(NSVGparser* p, const char* str, float orig, float length)
{
	NSVGcoordinate coord = nsvg__parseCoordinateRaw(str);
	return nsvg__convertToPixels(p, coord, orig, length);
}

static int nsvg__parseTransformArgs(const char* str, float* args, int maxNa, int* na)
{
	const char* end;
	const char* ptr;
	char it[64];

	*na = 0;
	ptr = str;
	while (*ptr && *ptr != '(') ++ptr;
	if (*ptr == 0)
		return 1;
	end = ptr;
	while (*end && *end != ')') ++end;
	if (*end == 0)
		return 1;

	while (ptr < end) {
		if (*ptr == '-' || *ptr == '+' || *ptr == '.' || nsvg__isdigit(*ptr)) {
			if (*na >= maxNa) return 0;
			ptr = nsvg__parseNumber(ptr, it, 64);
			args[(*na)++] = (float)nsvg__atof(it);
		} else {
			++ptr;
		}
	}
	return (int)(end - str);
}


static int nsvg__parseMatrix(float* xform, const char* str)
{
	float t[6];
	int na = 0;
	int len = nsvg__parseTransformArgs(str, t, 6, &na);
	if (na != 6) return len;
	memcpy(xform, t, sizeof(float)*6);
	return len;
}

static int nsvg__parseTranslate(float* xform, const char* str)
{
	float args[2];
	float t[6];
	int na = 0;
	int len = nsvg__parseTransformArgs(str, args, 2, &na);
	if (na == 1) args[1] = 0.0;

	nsvg__xformSetTranslation(t, args[0], args[1]);
	memcpy(xform, t, sizeof(float)*6);
	return len;
}

static int nsvg__parseScale(float* xform, const char* str)
{
	float args[2];
	int na = 0;
	float t[6];
	int len = nsvg__parseTransformArgs(str, args, 2, &na);
	if (na == 1) args[1] = args[0];
	nsvg__xformSetScale(t, args[0], args[1]);
	memcpy(xform, t, sizeof(float)*6);
	return len;
}

static int nsvg__parseSkewX(float* xform, const char* str)
{
	float args[1];
	int na = 0;
	float t[6];
	int len = nsvg__parseTransformArgs(str, args, 1, &na);
	nsvg__xformSetSkewX(t, args[0]/180.0f*NSVG_PI);
	memcpy(xform, t, sizeof(float)*6);
	return len;
}

static int nsvg__parseSkewY(float* xform, const char* str)
{
	float args[1];
	int na = 0;
	float t[6];
	int len = nsvg__parseTransformArgs(str, args, 1, &na);
	nsvg__xformSetSkewY(t, args[0]/180.0f*NSVG_PI);
	memcpy(xform, t, sizeof(float)*6);
	return len;
}

static int nsvg__parseRotate(float* xform, const char* str)
{
	float args[3];
	int na = 0;
	float m[6];
	float t[6];
	int len = nsvg__parseTransformArgs(str, args, 3, &na);
	if (na == 1)
		args[1] = args[2] = 0.0f;
	nsvg__xformIdentity(m);

	if (na > 1) {
		nsvg__xformSetTranslation(t, -args[1], -args[2]);
		nsvg__xformMultiply(m, t);
	}

	nsvg__xformSetRotation(t, args[0]/180.0f*NSVG_PI);
	nsvg__xformMultiply(m, t);

	if (na > 1) {
		nsvg__xformSetTranslation(t, args[1], args[2]);
		nsvg__xformMultiply(m, t);
	}

	memcpy(xform, m, sizeof(float)*6);

	return len;
}

static void nsvg__parseTransform(float* xform, const char* str)
{
	float t[6];
        int len;
	nsvg__xformIdentity(xform);
	while (*str)
	{
		if (strncmp(str, "matrix", 6) == 0)
			len = nsvg__parseMatrix(t, str);
		else if (strncmp(str, "translate", 9) == 0)
			len = nsvg__parseTranslate(t, str);
		else if (strncmp(str, "scale", 5) == 0)
			len = nsvg__parseScale(t, str);
		else if (strncmp(str, "rotate", 6) == 0)
			len = nsvg__parseRotate(t, str);
		else if (strncmp(str, "skewX", 5) == 0)
			len = nsvg__parseSkewX(t, str);
		else if (strncmp(str, "skewY", 5) == 0)
			len = nsvg__parseSkewY(t, str);
		else{
			++str;
			continue;
		}
                if (len != 0) {
			str += len;
                } else {
			++str;
			continue;
                }

		nsvg__xformPremultiply(xform, t);
	}
}

static void nsvg__parseUrl(char* id, const char* str)
{
	int i = 0;
	str += 4; /* "url("; */
	if (*str == '#')
		str++;
	while (i < 63 && *str != ')') {
		id[i] = *str++;
		i++;
	}
	id[i] = '\0';
}

static char nsvg__parseLineCap(const char* str)
{
	if (strcmp(str, "butt") == 0)
		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. */
	return NSVG_CAP_BUTT;
}

static char nsvg__parseLineJoin(const char* str)
{
	if (strcmp(str, "miter") == 0)
		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. */
	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. */
	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 */
	while (*s && (nsvg__isspace(*s) || *s == ',')) s++;
	/* Advance until whitespace, comma or end. */
	while (*s && (!nsvg__isspace(*s) && *s != ',')) {
		if (n < 63)
			it[n++] = *s;
		s++;
	}
	it[n++] = '\0';
	return s;
}

static int nsvg__parseStrokeDashArray(NSVGparser* p, const char* str, float* strokeDashArray)
{
	char item[64];
	int count = 0, i;
	float sum = 0.0f;

	/* Handle "none" */
	if (str[0] == 'n')
		return 0;

	/* 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)));
	}

	for (i = 0; i < count; i++)
		sum += strokeDashArray[i];
	if (sum <= 1e-6f)
		count = 0;

	return count;
}

static void nsvg__parseStyle(NSVGparser* p, const char* str);

static int nsvg__parseAttr(NSVGparser* p, const char* name, const char* value)
{
	float xform[6];
	NSVGattrib* attr = nsvg__getAttr(p);
	if (!attr) return 0;

	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 */

	} else if (strcmp(name, "visibility") == 0) {
		if (strcmp(value, "hidden") == 0) {
			attr->visible &= ~NSVG_VIS_VISIBLE;
		} else if (strcmp(value, "visible") == 0) {
			attr->visible |= NSVG_VIS_VISIBLE;
		}
	} else if (strcmp(name, "fill") == 0) {
		if (strcmp(value, "none") == 0) {
			attr->hasFill = 0;
		} else if (strncmp(value, "url(", 4) == 0) {
			attr->hasFill = 2;
			nsvg__parseUrl(attr->fillGradient, value);
		} else {
			attr->hasFill = 1;
			attr->fillColor = nsvg__parseColor(value);
		}
	} else if (strcmp(name, "opacity") == 0) {
		attr->opacity = nsvg__parseOpacity(value);
	} else if (strcmp(name, "fill-opacity") == 0) {
		attr->fillOpacity = nsvg__parseOpacity(value);
	} else if (strcmp(name, "stroke") == 0) {
		if (strcmp(value, "none") == 0) {
			attr->hasStroke = 0;
		} else if (strncmp(value, "url(", 4) == 0) {
			attr->hasStroke = 2;
			nsvg__parseUrl(attr->strokeGradient, value);
		} else {
			attr->hasStroke = 1;
			attr->strokeColor = nsvg__parseColor(value);
		}
	} else if (strcmp(name, "stroke-width") == 0) {
		attr->strokeWidth = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p));
	} else if (strcmp(name, "stroke-dasharray") == 0) {
		attr->strokeDashCount = nsvg__parseStrokeDashArray(p, value, attr->strokeDashArray);
	} else if (strcmp(name, "stroke-dashoffset") == 0) {
		attr->strokeDashOffset = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p));
	} else if (strcmp(name, "stroke-opacity") == 0) {
		attr->strokeOpacity = nsvg__parseOpacity(value);
	} else if (strcmp(name, "stroke-linecap") == 0) {
		attr->strokeLineCap = nsvg__parseLineCap(value);
	} else if (strcmp(name, "stroke-linejoin") == 0) {
		attr->strokeLineJoin = nsvg__parseLineJoin(value);
	} else if (strcmp(name, "stroke-miterlimit") == 0) {
		attr->miterLimit = nsvg__parseMiterLimit(value);
	} else if (strcmp(name, "fill-rule") == 0) {
		attr->fillRule = nsvg__parseFillRule(value);
	} else if (strcmp(name, "font-size") == 0) {
		attr->fontSize = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p));
	} else if (strcmp(name, "transform") == 0) {
		nsvg__parseTransform(xform, value);
		nsvg__xformPremultiply(attr->xform, xform);
	} else if (strcmp(name, "stop-color") == 0) {
		attr->stopColor = nsvg__parseColor(value);
	} else if (strcmp(name, "stop-opacity") == 0) {
		attr->stopOpacity = nsvg__parseOpacity(value);
	} else if (strcmp(name, "offset") == 0) {
		attr->stopOffset = nsvg__parseCoordinate(p, value, 0.0f, 1.0f);
	} else if (strcmp(name, "id") == 0) {
		strncpy(attr->id, value, 63);
		attr->id[63] = '\0';
	} else if (strcmp(name, "class") == 0) {
		NSVGstyles* style = p->styles;
		while (style) {
			if (strcmp(style->name + 1, value) == 0) {
				break;
			}
			style = style->next;
		}
		if (style) {
			nsvg__parseStyle(p, style->description);
		}
	} else {
		return 0;
	}
	return 1;
}

static int nsvg__parseNameValue(NSVGparser* p, const char* start, const char* end)
{
	const char* str;
	const char* val;
	char name[512];
	char value[512];
	int n;

	str = start;
	while (str < end && *str != ':') ++str;

	val = str;

	/* Right Trim */
	while (str > start &&  (*str == ':' || nsvg__isspace(*str))) --str;
	++str;

	n = (int)(str - start);
	if (n > 511) n = 511;
	if (n) memcpy(name, start, n);
	name[n] = 0;

	while (val < end && (*val == ':' || nsvg__isspace(*val))) ++val;

	n = (int)(end - val);
	if (n > 511) n = 511;
	if (n) memcpy(value, val, n);
	value[n] = 0;

	return nsvg__parseAttr(p, name, value);
}

static void nsvg__parseStyle(NSVGparser* p, const char* str)
{
	const char* start;
	const char* end;

	while (*str) {
		/* Left Trim */
		while(*str && nsvg__isspace(*str)) ++str;
		start = str;
		while(*str && *str != ';') ++str;
		end = str;

		/* Right Trim */
		while (end > start &&  (*end == ';' || nsvg__isspace(*end))) --end;
		++end;

		nsvg__parseNameValue(p, start, end);
		if (*str) ++str;
	}
}

static void nsvg__parseAttribs(NSVGparser* p, const char** attr)
{
	int i;
	for (i = 0; attr[i]; i += 2)
	{
		if (strcmp(attr[i], "style") == 0)
			nsvg__parseStyle(p, attr[i + 1]);
		else
			nsvg__parseAttr(p, attr[i], attr[i + 1]);
	}
}

static int nsvg__getArgsPerElement(char cmd)
{
	switch (cmd) {
		case 'v':
		case 'V':
		case 'h':
		case 'H':
			return 1;
		case 'm':
		case 'M':
		case 'l':
		case 'L':
		case 't':
		case 'T':
			return 2;
		case 'q':
		case 'Q':
		case 's':
		case 'S':
			return 4;
		case 'c':
		case 'C':
			return 6;
		case 'a':
		case 'A':
			return 7;
		case 'z':
		case 'Z':
			return 0;
	}
	return -1;
}

static void nsvg__pathMoveTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel)
{
	if (rel) {
		*cpx += args[0];
		*cpy += args[1];
	} else {
		*cpx = args[0];
		*cpy = args[1];
	}
	nsvg__moveTo(p, *cpx, *cpy);
}

static void nsvg__pathLineTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel)
{
	if (rel) {
		*cpx += args[0];
		*cpy += args[1];
	} else {
		*cpx = args[0];
		*cpy = args[1];
	}
	nsvg__lineTo(p, *cpx, *cpy);
}

static void nsvg__pathHLineTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel)
{
	if (rel)
		*cpx += args[0];
	else
		*cpx = args[0];
	nsvg__lineTo(p, *cpx, *cpy);
}

static void nsvg__pathVLineTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel)
{
	if (rel)
		*cpy += args[0];
	else
		*cpy = args[0];
	nsvg__lineTo(p, *cpx, *cpy);
}

static void nsvg__pathCubicBezTo(NSVGparser* p, float* cpx, float* cpy,
								 float* cpx2, float* cpy2, float* args, int rel)
{
	float x2, y2, cx1, cy1, cx2, cy2;

	if (rel) {
		cx1 = *cpx + args[0];
		cy1 = *cpy + args[1];
		cx2 = *cpx + args[2];
		cy2 = *cpy + args[3];
		x2 = *cpx + args[4];
		y2 = *cpy + args[5];
	} else {
		cx1 = args[0];
		cy1 = args[1];
		cx2 = args[2];
		cy2 = args[3];
		x2 = args[4];
		y2 = args[5];
	}

	nsvg__cubicBezTo(p, cx1,cy1, cx2,cy2, x2,y2);

	*cpx2 = cx2;
	*cpy2 = cy2;
	*cpx = x2;
	*cpy = y2;
}

static void nsvg__pathCubicBezShortTo(NSVGparser* p, float* cpx, float* cpy,
									  float* cpx2, float* cpy2, float* args, int rel)
{
	float x1, y1, x2, y2, cx1, cy1, cx2, cy2;

	x1 = *cpx;
	y1 = *cpy;
	if (rel) {
		cx2 = *cpx + args[0];
		cy2 = *cpy + args[1];
		x2 = *cpx + args[2];
		y2 = *cpy + args[3];
	} else {
		cx2 = args[0];
		cy2 = args[1];
		x2 = args[2];
		y2 = args[3];
	}

	cx1 = 2*x1 - *cpx2;
	cy1 = 2*y1 - *cpy2;

	nsvg__cubicBezTo(p, cx1,cy1, cx2,cy2, x2,y2);

	*cpx2 = cx2;
	*cpy2 = cy2;
	*cpx = x2;
	*cpy = y2;
}

static void nsvg__pathQuadBezTo(NSVGparser* p, float* cpx, float* cpy,
								float* cpx2, float* cpy2, float* args, int rel)
{
	float x1, y1, x2, y2, cx, cy;
	float cx1, cy1, cx2, cy2;

	x1 = *cpx;
	y1 = *cpy;
	if (rel) {
		cx = *cpx + args[0];
		cy = *cpy + args[1];
		x2 = *cpx + args[2];
		y2 = *cpy + args[3];
	} else {
		cx = args[0];
		cy = args[1];
		x2 = args[2];
		y2 = args[3];
	}

	/* 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);

	nsvg__cubicBezTo(p, cx1,cy1, cx2,cy2, x2,y2);

	*cpx2 = cx;
	*cpy2 = cy;
	*cpx = x2;
	*cpy = y2;
}

static void nsvg__pathQuadBezShortTo(NSVGparser* p, float* cpx, float* cpy,
									 float* cpx2, float* cpy2, float* args, int rel)
{
	float x1, y1, x2, y2, cx, cy;
	float cx1, cy1, cx2, cy2;

	x1 = *cpx;
	y1 = *cpy;
	if (rel) {
		x2 = *cpx + args[0];
		y2 = *cpy + args[1];
	} else {
		x2 = args[0];
		y2 = args[1];
	}

	cx = 2*x1 - *cpx2;
	cy = 2*y1 - *cpy2;

	/* 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);

	nsvg__cubicBezTo(p, cx1,cy1, cx2,cy2, x2,y2);

	*cpx2 = cx;
	*cpy2 = cy;
	*cpx = x2;
	*cpy = y2;
}

static float nsvg__sqr(float x) { return x*x; }
static float nsvg__vmag(float x, float y) { return sqrtf(x*x + y*y); }

static float nsvg__vecrat(float ux, float uy, float vx, float vy)
{
	return (ux*vx + uy*vy) / (nsvg__vmag(ux,uy) * nsvg__vmag(vx,vy));
}

static float nsvg__vecang(float ux, float uy, float vx, float vy)
{
	float r = nsvg__vecrat(ux,uy, vx,vy);
	if (r < -1.0f) r = -1.0f;
	if (r > 1.0f) r = 1.0f;
	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/) */
	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];
	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 */
	y1 = *cpy;
	if (rel) {							/* end point */
		x2 = *cpx + args[5];
		y2 = *cpy + args[6];
	} else {
		x2 = args[5];
		y2 = args[6];
	}

	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 */
		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' */
	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' */
	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)
		s = sqrtf(sa / sb);
	if (fa == fs)
		s = -s;
	cxp = s * rx * y1p / ry;
	cyp = s * -ry * x1p / rx;

	/* 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. */
	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 */

/*	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. */
	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. */
	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));
	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 */
		if (i > 0)
			nsvg__cubicBezTo(p, px+ptanx,py+ptany, x-tanx, y-tany, x, y);
		px = x;
		py = y;
		ptanx = tanx;
		ptany = tany;
	}

	*cpx = x2;
	*cpy = y2;
}

static void nsvg__parsePath(NSVGparser* p, const char** attr)
{
	const char* s = NULL;
	char cmd = '\0';
	float args[10];
	int nargs;
	int rargs = 0;
	char initPoint;
	float cpx, cpy, cpx2, cpy2;
	const char* tmp[4];
	char closedFlag;
	int i;
	char item[64];

	for (i = 0; attr[i]; i += 2) {
		if (strcmp(attr[i], "d") == 0) {
			s = attr[i + 1];
		} else {
			tmp[0] = attr[i];
			tmp[1] = attr[i + 1];
			tmp[2] = 0;
			tmp[3] = 0;
			nsvg__parseAttribs(p, tmp);
		}
	}

	if (s) {
		nsvg__resetPath(p);
		cpx = 0; cpy = 0;
		cpx2 = 0; cpy2 = 0;
		initPoint = 0;
		closedFlag = 0;
		nargs = 0;

		while (*s) {
			s = nsvg__getNextPathItem(s, item);
			if (!*item) break;
			if (cmd != '\0' && nsvg__isCoordinate(item)) {
				if (nargs < 10)
					args[nargs++] = (float)nsvg__atof(item);
				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. */
							cmd = (cmd == 'm') ? 'l' : 'L';
							rargs = nsvg__getArgsPerElement(cmd);
							cpx2 = cpx; cpy2 = cpy;
							initPoint = 1;
							break;
						case 'l':
						case 'L':
							nsvg__pathLineTo(p, &cpx, &cpy, args, cmd == 'l' ? 1 : 0);
							cpx2 = cpx; cpy2 = cpy;
							break;
						case 'H':
						case 'h':
							nsvg__pathHLineTo(p, &cpx, &cpy, args, cmd == 'h' ? 1 : 0);
							cpx2 = cpx; cpy2 = cpy;
							break;
						case 'V':
						case 'v':
							nsvg__pathVLineTo(p, &cpx, &cpy, args, cmd == 'v' ? 1 : 0);
							cpx2 = cpx; cpy2 = cpy;
							break;
						case 'C':
						case 'c':
							nsvg__pathCubicBezTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 'c' ? 1 : 0);
							break;
						case 'S':
						case 's':
							nsvg__pathCubicBezShortTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 's' ? 1 : 0);
							break;
						case 'Q':
						case 'q':
							nsvg__pathQuadBezTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 'q' ? 1 : 0);
							break;
						case 'T':
						case 't':
							nsvg__pathQuadBezShortTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 't' ? 1 : 0);
							break;
						case 'A':
						case 'a':
							nsvg__pathArcTo(p, &cpx, &cpy, args, cmd == 'a' ? 1 : 0);
							cpx2 = cpx; cpy2 = cpy;
							break;
						default:
							if (nargs >= 2) {
								cpx = args[nargs-2];
								cpy = args[nargs-1];
								cpx2 = cpx; cpy2 = cpy;
							}
							break;
					}
					nargs = 0;
				}
			} else {
				cmd = item[0];
				if (cmd == 'M' || cmd == 'm') {
					/* Commit path. */
					if (p->npts > 0)
						nsvg__addPath(p, closedFlag);
					/* 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). */
					cmd = '\0';
				}
				if (cmd == 'Z' || cmd == 'z') {
					closedFlag = 1;
					/* Commit path. */
					if (p->npts > 0) {
						/* 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. */
					nsvg__resetPath(p);
					nsvg__moveTo(p, cpx, cpy);
					closedFlag = 0;
					nargs = 0;
				}
				rargs = nsvg__getArgsPerElement(cmd);
				if (rargs == -1) {
					/* Command not recognized */
					cmd = '\0';
					rargs = 0;
				}
			}
		}
		/* Commit path. */
		if (p->npts)
			nsvg__addPath(p, closedFlag);
	}

	nsvg__addShape(p);
}

static void nsvg__parseRect(NSVGparser* p, const char** attr)
{
	float x = 0.0f;
	float y = 0.0f;
	float w = 0.0f;
	float h = 0.0f;
	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])) {
			if (strcmp(attr[i], "x") == 0) x = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
			if (strcmp(attr[i], "y") == 0) y = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
			if (strcmp(attr[i], "width") == 0) w = nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualWidth(p));
			if (strcmp(attr[i], "height") == 0) h = nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualHeight(p));
			if (strcmp(attr[i], "rx") == 0) rx = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualWidth(p)));
			if (strcmp(attr[i], "ry") == 0) ry = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualHeight(p)));
		}
	}

	if (rx < 0.0f && ry > 0.0f) rx = ry;
	if (ry < 0.0f && rx > 0.0f) ry = rx;
	if (rx < 0.0f) rx = 0.0f;
	if (ry < 0.0f) ry = 0.0f;
	if (rx > w/2.0f) rx = w/2.0f;
	if (ry > h/2.0f) ry = h/2.0f;

	if (w != 0.0f && h != 0.0f) {
		nsvg__resetPath(p);

		if (rx < 0.00001f || ry < 0.0001f) {
			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 */
			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);
			nsvg__lineTo(p, x+rx, y+h);
			nsvg__cubicBezTo(p, x+rx*(1-NSVG_KAPPA90), y+h, x, y+h-ry*(1-NSVG_KAPPA90), x, y+h-ry);
			nsvg__lineTo(p, x, y+ry);
			nsvg__cubicBezTo(p, x, y+ry*(1-NSVG_KAPPA90), x+rx*(1-NSVG_KAPPA90), y, x+rx, y);
		}

		nsvg__addPath(p, 1);

		nsvg__addShape(p);
	}
}

static void nsvg__parseCircle(NSVGparser* p, const char** attr)
{
	float cx = 0.0f;
	float cy = 0.0f;
	float r = 0.0f;
	int i;

	for (i = 0; attr[i]; i += 2) {
		if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
			if (strcmp(attr[i], "cx") == 0) cx = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
			if (strcmp(attr[i], "cy") == 0) cy = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
			if (strcmp(attr[i], "r") == 0) r = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualLength(p)));
		}
	}

	if (r > 0.0f) {
		nsvg__resetPath(p);

		nsvg__moveTo(p, cx+r, cy);
		nsvg__cubicBezTo(p, cx+r, cy+r*NSVG_KAPPA90, cx+r*NSVG_KAPPA90, cy+r, cx, cy+r);
		nsvg__cubicBezTo(p, cx-r*NSVG_KAPPA90, cy+r, cx-r, cy+r*NSVG_KAPPA90, cx-r, cy);
		nsvg__cubicBezTo(p, cx-r, cy-r*NSVG_KAPPA90, cx-r*NSVG_KAPPA90, cy-r, cx, cy-r);
		nsvg__cubicBezTo(p, cx+r*NSVG_KAPPA90, cy-r, cx+r, cy-r*NSVG_KAPPA90, cx+r, cy);

		nsvg__addPath(p, 1);

		nsvg__addShape(p);
	}
}

static void nsvg__parseEllipse(NSVGparser* p, const char** attr)
{
	float cx = 0.0f;
	float cy = 0.0f;
	float rx = 0.0f;
	float ry = 0.0f;
	int i;

	for (i = 0; attr[i]; i += 2) {
		if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
			if (strcmp(attr[i], "cx") == 0) cx = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
			if (strcmp(attr[i], "cy") == 0) cy = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
			if (strcmp(attr[i], "rx") == 0) rx = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualWidth(p)));
			if (strcmp(attr[i], "ry") == 0) ry = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualHeight(p)));
		}
	}

	if (rx > 0.0f && ry > 0.0f) {

		nsvg__resetPath(p);

		nsvg__moveTo(p, cx+rx, cy);
		nsvg__cubicBezTo(p, cx+rx, cy+ry*NSVG_KAPPA90, cx+rx*NSVG_KAPPA90, cy+ry, cx, cy+ry);
		nsvg__cubicBezTo(p, cx-rx*NSVG_KAPPA90, cy+ry, cx-rx, cy+ry*NSVG_KAPPA90, cx-rx, cy);
		nsvg__cubicBezTo(p, cx-rx, cy-ry*NSVG_KAPPA90, cx-rx*NSVG_KAPPA90, cy-ry, cx, cy-ry);
		nsvg__cubicBezTo(p, cx+rx*NSVG_KAPPA90, cy-ry, cx+rx, cy-ry*NSVG_KAPPA90, cx+rx, cy);

		nsvg__addPath(p, 1);

		nsvg__addShape(p);
	}
}

static void nsvg__parseLine(NSVGparser* p, const char** attr)
{
	float x1 = 0.0;
	float y1 = 0.0;
	float x2 = 0.0;
	float y2 = 0.0;
	int i;

	for (i = 0; attr[i]; i += 2) {
		if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
			if (strcmp(attr[i], "x1") == 0) x1 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
			if (strcmp(attr[i], "y1") == 0) y1 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
			if (strcmp(attr[i], "x2") == 0) x2 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
			if (strcmp(attr[i], "y2") == 0) y2 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
		}
	}

	nsvg__resetPath(p);

	nsvg__moveTo(p, x1, y1);
	nsvg__lineTo(p, x2, y2);

	nsvg__addPath(p, 0);

	nsvg__addShape(p);
}

static void nsvg__parsePoly(NSVGparser* p, const char** attr, int closeFlag)
{
	int i;
	const char* s;
	float args[2];
	int nargs, npts = 0;
	char item[64];

	nsvg__resetPath(p);

	for (i = 0; attr[i]; i += 2) {
		if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
			if (strcmp(attr[i], "points") == 0) {
				s = attr[i + 1];
				nargs = 0;
				while (*s) {
					s = nsvg__getNextPathItem(s, item);
					args[nargs++] = (float)nsvg__atof(item);
					if (nargs >= 2) {
						if (npts == 0)
							nsvg__moveTo(p, args[0], args[1]);
						else
							nsvg__lineTo(p, args[0], args[1]);
						nargs = 0;
						npts++;
					}
				}
			}
		}
	}

	nsvg__addPath(p, (char)closeFlag);

	nsvg__addShape(p);
}

static void nsvg__parseSVG(NSVGparser* p, const char** attr)
{
	int i;
	for (i = 0; attr[i]; i += 2) {
		if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
			if (strcmp(attr[i], "width") == 0) {
				p->image->width = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, 0.0f);
			} else if (strcmp(attr[i], "height") == 0) {
				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 */
					p->alignType = NSVG_ALIGN_NONE;
				} else {
					/* 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 */
					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 */
					p->alignType = NSVG_ALIGN_MEET;
					if (strstr(attr[i + 1], "slice") != 0)
						p->alignType = NSVG_ALIGN_SLICE;
				}
			}
		}
	}
}

static void nsvg__parseGradient(NSVGparser* p, const char** attr, char type)
{
	int i;
	NSVGgradientData* grad = (NSVGgradientData*)NANOSVG_malloc(sizeof(NSVGgradientData));
	if (grad == NULL) return;
	memset(grad, 0, sizeof(NSVGgradientData));
	grad->units = NSVG_OBJECT_SPACE;
	grad->type = type;
	if (grad->type == NSVG_PAINT_LINEAR_GRADIENT) {
		grad->linear.x1 = nsvg__coord(0.0f, NSVG_UNITS_PERCENT);
		grad->linear.y1 = nsvg__coord(0.0f, NSVG_UNITS_PERCENT);
		grad->linear.x2 = nsvg__coord(100.0f, NSVG_UNITS_PERCENT);
		grad->linear.y2 = nsvg__coord(0.0f, NSVG_UNITS_PERCENT);
	} else if (grad->type == NSVG_PAINT_RADIAL_GRADIENT) {
		grad->radial.cx = nsvg__coord(50.0f, NSVG_UNITS_PERCENT);
		grad->radial.cy = nsvg__coord(50.0f, NSVG_UNITS_PERCENT);
		grad->radial.r = nsvg__coord(50.0f, NSVG_UNITS_PERCENT);
	}

	nsvg__xformIdentity(grad->xform);

	for (i = 0; attr[i]; i += 2) {
		if (strcmp(attr[i], "id") == 0) {
			strncpy(grad->id, attr[i+1], 63);
			grad->id[63] = '\0';
		} else if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
			if (strcmp(attr[i], "gradientUnits") == 0) {
				if (strcmp(attr[i+1], "objectBoundingBox") == 0)
					grad->units = NSVG_OBJECT_SPACE;
				else
					grad->units = NSVG_USER_SPACE;
			} else if (strcmp(attr[i], "gradientTransform") == 0) {
				nsvg__parseTransform(grad->xform, attr[i + 1]);
			} else if (strcmp(attr[i], "cx") == 0) {
				grad->radial.cx = nsvg__parseCoordinateRaw(attr[i + 1]);
			} else if (strcmp(attr[i], "cy") == 0) {
				grad->radial.cy = nsvg__parseCoordinateRaw(attr[i + 1]);
			} else if (strcmp(attr[i], "r") == 0) {
				grad->radial.r = nsvg__parseCoordinateRaw(attr[i + 1]);
			} else if (strcmp(attr[i], "fx") == 0) {
				grad->radial.fx = nsvg__parseCoordinateRaw(attr[i + 1]);
			} else if (strcmp(attr[i], "fy") == 0) {
				grad->radial.fy = nsvg__parseCoordinateRaw(attr[i + 1]);
			} else if (strcmp(attr[i], "x1") == 0) {
				grad->linear.x1 = nsvg__parseCoordinateRaw(attr[i + 1]);
			} else if (strcmp(attr[i], "y1") == 0) {
				grad->linear.y1 = nsvg__parseCoordinateRaw(attr[i + 1]);
			} else if (strcmp(attr[i], "x2") == 0) {
				grad->linear.x2 = nsvg__parseCoordinateRaw(attr[i + 1]);
			} else if (strcmp(attr[i], "y2") == 0) {
				grad->linear.y2 = nsvg__parseCoordinateRaw(attr[i + 1]);
			} else if (strcmp(attr[i], "spreadMethod") == 0) {
				if (strcmp(attr[i+1], "pad") == 0)
					grad->spread = NSVG_SPREAD_PAD;
				else if (strcmp(attr[i+1], "reflect") == 0)
					grad->spread = NSVG_SPREAD_REFLECT;
				else if (strcmp(attr[i+1], "repeat") == 0)
					grad->spread = NSVG_SPREAD_REPEAT;
			} else if (strcmp(attr[i], "xlink:href") == 0) {
				const char *href = attr[i+1];
				strncpy(grad->ref, href+1, 62);
				grad->ref[62] = '\0';
			}
		}
	}

	grad->next = p->gradients;
	p->gradients = grad;
}

static void nsvg__parseGradientStop(NSVGparser* p, const char** attr)
{
	NSVGattrib* curAttr = nsvg__getAttr(p);
	NSVGgradientData* grad;
	NSVGgradientStop* stop;
	int i, idx;

	curAttr->stopOffset = 0;
	curAttr->stopColor = 0;
	curAttr->stopOpacity = 1.0f;

	for (i = 0; attr[i]; i += 2) {
		nsvg__parseAttr(p, attr[i], attr[i + 1]);
	}

	/* 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 */
	idx = grad->nstops-1;
	for (i = 0; i < grad->nstops-1; i++) {
		if (curAttr->stopOffset < grad->stops[i].offset) {
			idx = i;
			break;
		}
	}
	if (idx != grad->nstops-1) {
		for (i = grad->nstops-1; i > idx; i--)
			grad->stops[i] = grad->stops[i-1];
	}

	stop = &grad->stops[idx];
	stop->color = curAttr->stopColor;
	stop->color |= (unsigned int)(curAttr->stopOpacity*255) << 24;
	stop->offset = curAttr->stopOffset;
}

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 */
		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) {
			nsvg__parseGradientStop(p, attr);
		}
		return;
	}

	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. */
			return;
		nsvg__pushAttr(p);
		nsvg__parsePath(p, attr);
		nsvg__popAttr(p);
	} else if (strcmp(el, "rect") == 0) {
		nsvg__pushAttr(p);
		nsvg__parseRect(p, attr);
		nsvg__popAttr(p);
	} else if (strcmp(el, "circle") == 0) {
		nsvg__pushAttr(p);
		nsvg__parseCircle(p, attr);
		nsvg__popAttr(p);
	} else if (strcmp(el, "ellipse") == 0) {
		nsvg__pushAttr(p);
		nsvg__parseEllipse(p, attr);
		nsvg__popAttr(p);
	} else if (strcmp(el, "line") == 0)  {
		nsvg__pushAttr(p);
		nsvg__parseLine(p, attr);
		nsvg__popAttr(p);
	} else if (strcmp(el, "polyline") == 0)  {
		nsvg__pushAttr(p);
		nsvg__parsePoly(p, attr, 0);
		nsvg__popAttr(p);
	} else if (strcmp(el, "polygon") == 0)  {
		nsvg__pushAttr(p);
		nsvg__parsePoly(p, attr, 1);
		nsvg__popAttr(p);
	} else  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) {
		nsvg__parseGradientStop(p, attr);
	} else if (strcmp(el, "defs") == 0) {
		p->defsFlag = 1;
	} else if (strcmp(el, "svg") == 0) {
		nsvg__parseSVG(p, attr);
	} else if (strcmp(el, "style") == 0) {
		p->styleFlag = 1;
	}
}

static void nsvg__endElement(void* ud, const char* el)
{
	NSVGparser* p = (NSVGparser*)ud;

	if (strcmp(el, "g") == 0) {
		nsvg__popAttr(p);
	} else if (strcmp(el, "path") == 0) {
		p->pathFlag = 0;
	} else if (strcmp(el, "defs") == 0) {
		p->defsFlag = 0;
	} else if (strcmp(el, "style") == 0) {
		p->styleFlag = 0;
	}
}

static char *nsvg__strndup(const char *s, size_t n)
{
	char *result;
	size_t len = strlen(s);

	if (n < len)
		len = n;

	result = (char*)NANOSVG_malloc(len+1);
	if (!result)
		return 0;

	result[len] = '\0';
	return (char *)memcpy(result, s, len);
}

static void nsvg__content(void* ud, const char* s)
{
	NSVGparser* p = (NSVGparser*)ud;
	if (p->styleFlag) {

		int state = 0;
		const char* start = NULL;
		while (*s) {
			char c = *s;
			if (nsvg__isspace(c) || c == '{') {
				if (state == 1) {
					NSVGstyles* next = p->styles;

					p->styles = (NSVGstyles*)NANOSVG_malloc(sizeof(NSVGstyles));
					p->styles->next = next;
					p->styles->name = nsvg__strndup(start, (size_t)(s - start));
					start = s + 1;
					state = 2;
				}
			} else if (state == 2 && c == '}') {
				p->styles->description = nsvg__strndup(start, (size_t)(s - start));
				state = 0;
			}
			else if (state == 0) {
				start = s;
				state = 1;
			}
			s++;
		/*
			if (*s == '{' && state == NSVG_XML_CONTENT) {
				// 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.
				*s++ = '\0';
				nsvg__parseElement(mark, startelCb, endelCb, ud);
				mark = s;
				state = NSVG_XML_CONTENT;
			}
			else {
				s++;
			}
		*/
		}

	}
}

static void nsvg__imageBounds(NSVGparser* p, float* bounds)
{
	NSVGshape* shape;
	shape = p->image->shapes;
	if (shape == NULL) {
		bounds[0] = bounds[1] = bounds[2] = bounds[3] = 0.0;
		return;
	}
	bounds[0] = shape->bounds[0];
	bounds[1] = shape->bounds[1];
	bounds[2] = shape->bounds[2];
	bounds[3] = shape->bounds[3];
	for (shape = shape->next; shape != NULL; shape = shape->next) {
		bounds[0] = nsvg__minf(bounds[0], shape->bounds[0]);
		bounds[1] = nsvg__minf(bounds[1], shape->bounds[1]);
		bounds[2] = nsvg__maxf(bounds[2], shape->bounds[2]);
		bounds[3] = nsvg__maxf(bounds[3], shape->bounds[3]);
	}
}

static float nsvg__viewAlign(float content, float container, int type)
{
	if (type == NSVG_ALIGN_MIN)
		return 0;
	else if (type == NSVG_ALIGN_MAX)
		return container - content;
	/* mid */
	return (container - content) * 0.5f;
}

static void nsvg__scaleGradient(NSVGgradient* grad, float tx, float ty, float sx, float sy)
{
	float t[6];
	nsvg__xformSetTranslation(t, tx, ty);
	nsvg__xformMultiply (grad->xform, t);

	nsvg__xformSetScale(t, sx, sy);
	nsvg__xformMultiply (grad->xform, t);
}

static void nsvg__scaleToViewbox(NSVGparser* p, const char* units)
{
	NSVGshape* shape;
	NSVGpath* path;
	float tx, ty, sx, sy, us, bounds[4], t[6], avgs;
	int i;
	float* pt;

	/* 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;
		} else {
			p->viewMinx = bounds[0];
			p->viewWidth = bounds[2] - bounds[0];
		}
	}
	if (p->viewHeight == 0) {
		if (p->image->height > 0) {
			p->viewHeight = p->image->height;
		} else {
			p->viewMiny = bounds[1];
			p->viewHeight = bounds[3] - bounds[1];
		}
	}
	if (p->image->width == 0)
		p->image->width = p->viewWidth;
	if (p->image->height == 0)
		p->image->height = p->viewHeight;

	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 */
	us = 1.0f / nsvg__convertToPixels(p, nsvg__coord(1.0f, nsvg__parseUnits(units)), 0.0f, 1.0f);

	/* Fix aspect ratio */
	if (p->alignType == NSVG_ALIGN_MEET) {
		/* 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 */
		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 */
	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;
		shape->bounds[1] = (shape->bounds[1] + ty) * sy;
		shape->bounds[2] = (shape->bounds[2] + tx) * sx;
		shape->bounds[3] = (shape->bounds[3] + ty) * sy;
		for (path = shape->paths; path != NULL; path = path->next) {
			path->bounds[0] = (path->bounds[0] + tx) * sx;
			path->bounds[1] = (path->bounds[1] + ty) * sy;
			path->bounds[2] = (path->bounds[2] + tx) * sx;
			path->bounds[3] = (path->bounds[3] + ty) * sy;
			for (i =0; i < path->npts; i++) {
				pt = &path->pts[i*2];
				pt[0] = (pt[0] + tx) * sx;
				pt[1] = (pt[1] + ty) * sy;
			}
		}

		if (shape->fill.type == NSVG_PAINT_LINEAR_GRADIENT || shape->fill.type == NSVG_PAINT_RADIAL_GRADIENT) {
			nsvg__scaleGradient(shape->fill.gradient, tx,ty, sx,sy);
			memcpy(t, shape->fill.gradient->xform, sizeof(float)*6);
			nsvg__xformInverse(shape->fill.gradient->xform, t);
		}
		if (shape->stroke.type == NSVG_PAINT_LINEAR_GRADIENT || shape->stroke.type == NSVG_PAINT_RADIAL_GRADIENT) {
			nsvg__scaleGradient(shape->stroke.gradient, tx,ty, sx,sy);
			memcpy(t, shape->stroke.gradient->xform, sizeof(float)*6);
			nsvg__xformInverse(shape->stroke.gradient->xform, t);
		}

		shape->strokeWidth *= avgs;
		shape->strokeDashOffset *= avgs;
		for (i = 0; i < shape->strokeDashCount; i++)
			shape->strokeDashArray[i] *= avgs;
	}
}

NANOSVG_SCOPE
NSVGimage* nsvgParse(char* input, const char* units, float dpi)
{
	NSVGparser* p;
	NSVGimage* ret = 0;

	p = nsvg__createParser();
	if (p == NULL) {
		return NULL;
	}
	p->dpi = dpi;

	nsvg__parseXML(input, nsvg__startElement, nsvg__endElement, nsvg__content, p);

	/* Scale to viewBox */
	nsvg__scaleToViewbox(p, units);

	ret = p->image;
	p->image = NULL;

	nsvg__deleteParser(p);

	return ret;
}

NANOSVG_SCOPE
NSVGimage* nsvgParseFromFile(const char* filename, const char* units, float dpi)
{
	FILE* fp = NULL;
	size_t size;
	char* data = NULL;
	NSVGimage* image = NULL;

	fp = fopen(filename, "rb");
	if (!fp) goto error;
	fseek(fp, 0, SEEK_END);
	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. */
	fclose(fp);
	image = nsvgParse(data, units, dpi);
	NANOSVG_free(data);

	return image;

error:
	if (fp) fclose(fp);
	if (data) NANOSVG_free(data);
	if (image) nsvgDelete(image);
	return NULL;
}

NANOSVG_SCOPE
void nsvgDelete(NSVGimage* image)
{
	NSVGshape *snext, *shape;
	if (image == NULL) return;
	shape = image->shapes;
	while (shape != NULL) {
		snext = shape->next;
		nsvg__deletePaths(shape->paths);
		nsvg__deletePaint(&shape->fill);
		nsvg__deletePaint(&shape->stroke);
		NANOSVG_free(shape);
		shape = snext;
	}
	NANOSVG_free(image);
}

#endif
Added generic/nanosvgrast.h.





























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
 * Copyright (c) 2013-14 Mikko Mononen [email protected]
 *
 * This software is provided 'as-is', without any express or implied
 * warranty.  In no event will the authors be held liable for any damages
 * arising from the use of this software.
 *
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
 *
 * 1. The origin of this software must not be misrepresented; you must not
 * claim that you wrote the original software. If you use this software
 * in a product, an acknowledgment in the product documentation would be
 * appreciated but is not required.
 * 2. Altered source versions must be plainly marked as such, and must not be
 * misrepresented as being the original software.
 * 3. This notice may not be removed or altered from any source distribution.
 *
 * The polygon rasterization is heavily based on stb_truetype rasterizer
 * by Sean Barrett - http://nothings.org/
 *
 */

#ifndef NANOSVGRAST_H
#define NANOSVGRAST_H

#ifdef __cplusplus
extern "C" {
#endif

#ifndef NANOSVG_SCOPE
#define NANOSVG_SCOPE
#endif

#ifndef NANOSVG_malloc
#define NANOSVG_malloc malloc
#endif

#ifndef NANOSVG_realloc
#define NANOSVG_realloc realloc
#endif

#ifndef NANOSVG_free
#define NANOSVG_free free
#endif

typedef struct NSVGrasterizer NSVGrasterizer;

/* Example Usage:
	// Load SVG
	struct SNVGImage* image = nsvgParseFromFile("test.svg.");

	// Create rasterizer (can be used to render multiple images).
	struct NSVGrasterizer* rast = nsvgCreateRasterizer();
	// Allocate memory for image
	unsigned char* img = malloc(w*h*4);
	// Rasterize
	nsvgRasterize(rast, image, 0,0,1, img, w, h, w*4);
*/

/* 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
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. */
NANOSVG_SCOPE void nsvgDeleteRasterizer(NSVGrasterizer*);


#ifdef __cplusplus
}
#endif

#endif /* NANOSVGRAST_H */

#ifdef NANOSVGRAST_IMPLEMENTATION

#include <math.h>

#define NSVG__SUBSAMPLES	5
#define NSVG__FIXSHIFT		10
#define NSVG__FIX			(1 << NSVG__FIXSHIFT)
#define NSVG__FIXMASK		(NSVG__FIX-1)
#define NSVG__MEMPAGE_SIZE	1024

typedef struct NSVGedge {
	float x0,y0, x1,y1;
	int dir;
	struct NSVGedge* next;
} NSVGedge;

typedef struct NSVGpoint {
	float x, y;
	float dx, dy;
	float len;
	float dmx, dmy;
	unsigned char flags;
} NSVGpoint;

typedef struct NSVGactiveEdge {
	int x,dx;
	float ey;
	int dir;
	struct NSVGactiveEdge *next;
} NSVGactiveEdge;

typedef struct NSVGmemPage {
	unsigned char mem[NSVG__MEMPAGE_SIZE];
	int size;
	struct NSVGmemPage* next;
} NSVGmemPage;

typedef struct NSVGcachedPaint {
	char type;
	char spread;
	float xform[6];
	unsigned int colors[256];
} NSVGcachedPaint;

struct NSVGrasterizer
{
	float px, py;

	float tessTol;
	float distTol;

	NSVGedge* edges;
	int nedges;
	int cedges;

	NSVGpoint* points;
	int npoints;
	int cpoints;

	NSVGpoint* points2;
	int npoints2;
	int cpoints2;

	NSVGactiveEdge* freelist;
	NSVGmemPage* pages;
	NSVGmemPage* curpage;

	unsigned char* scanline;
	int cscanline;

	unsigned char* bitmap;
	int width, height, stride;
};

NANOSVG_SCOPE
NSVGrasterizer* nsvgCreateRasterizer(void)
{
	NSVGrasterizer* r = (NSVGrasterizer*)NANOSVG_malloc(sizeof(NSVGrasterizer));
	if (r == NULL) goto error;
	memset(r, 0, sizeof(NSVGrasterizer));

	r->tessTol = 0.25f;
	r->distTol = 0.01f;

	return r;

error:
	nsvgDeleteRasterizer(r);
	return NULL;
}

NANOSVG_SCOPE
void nsvgDeleteRasterizer(NSVGrasterizer* r)
{
	NSVGmemPage* p;

	if (r == NULL) return;

	p = r->pages;
	while (p != NULL) {
		NSVGmemPage* next = p->next;
		NANOSVG_free(p);
		p = next;
	}

	if (r->edges) NANOSVG_free(r->edges);
	if (r->points) NANOSVG_free(r->points);
	if (r->points2) NANOSVG_free(r->points2);
	if (r->scanline) NANOSVG_free(r->scanline);

	NANOSVG_free(r);
}

static NSVGmemPage* nsvg__nextPage(NSVGrasterizer* r, NSVGmemPage* cur)
{
	NSVGmemPage *newp;

	/* If using existing chain, return the next page in chain */
	if (cur != NULL && cur->next != NULL) {
		return cur->next;
	}

	/* Alloc new page */
	newp = (NSVGmemPage*)NANOSVG_malloc(sizeof(NSVGmemPage));
	if (newp == NULL) return NULL;
	memset(newp, 0, sizeof(NSVGmemPage));

	/* Add to linked list */
	if (cur != NULL)
		cur->next = newp;
	else
		r->pages = newp;

	return newp;
}

static void nsvg__resetPool(NSVGrasterizer* r)
{
	NSVGmemPage* p = r->pages;
	while (p != NULL) {
		p->size = 0;
		p = p->next;
	}
	r->curpage = r->pages;
}

static unsigned char* nsvg__alloc(NSVGrasterizer* r, int size)
{
	unsigned char* buf;
	if (size > NSVG__MEMPAGE_SIZE) return NULL;
	if (r->curpage == NULL || r->curpage->size+size > NSVG__MEMPAGE_SIZE) {
		r->curpage = nsvg__nextPage(r, r->curpage);
	}
	buf = &r->curpage->mem[r->curpage->size];
	r->curpage->size += size;
	return buf;
}

static int nsvg__ptEquals(float x1, float y1, float x2, float y2, float tol)
{
	float dx = x2 - x1;
	float dy = y2 - y1;
	return dx*dx + dy*dy < tol*tol;
}

static void nsvg__addPathPoint(NSVGrasterizer* r, float x, float y, int flags)
{
	NSVGpoint* pt;

	if (r->npoints > 0) {
		pt = &r->points[r->npoints-1];
		if (nsvg__ptEquals(pt->x,pt->y, x,y, r->distTol)) {
			pt->flags = (unsigned char)(pt->flags | flags);
			return;
		}
	}

	if (r->npoints+1 > r->cpoints) {
		r->cpoints = r->cpoints > 0 ? r->cpoints * 2 : 64;
		r->points = (NSVGpoint*)NANOSVG_realloc(r->points, sizeof(NSVGpoint) * r->cpoints);
		if (r->points == NULL) return;
	}

	pt = &r->points[r->npoints];
	pt->x = x;
	pt->y = y;
	pt->flags = (unsigned char)flags;
	r->npoints++;
}

static void nsvg__appendPathPoint(NSVGrasterizer* r, NSVGpoint pt)
{
	if (r->npoints+1 > r->cpoints) {
		r->cpoints = r->cpoints > 0 ? r->cpoints * 2 : 64;
		r->points = (NSVGpoint*)NANOSVG_realloc(r->points, sizeof(NSVGpoint) * r->cpoints);
		if (r->points == NULL) return;
	}
	r->points[r->npoints] = pt;
	r->npoints++;
}

static void nsvg__duplicatePoints(NSVGrasterizer* r)
{
	if (r->npoints > r->cpoints2) {
		r->cpoints2 = r->npoints;
		r->points2 = (NSVGpoint*)NANOSVG_realloc(r->points2, sizeof(NSVGpoint) * r->cpoints2);
		if (r->points2 == NULL) return;
	}

	memcpy(r->points2, r->points, sizeof(NSVGpoint) * r->npoints);
	r->npoints2 = r->npoints;
}

static void nsvg__addEdge(NSVGrasterizer* r, float x0, float y0, float x1, float y1)
{
	NSVGedge* e;

	/* Skip horizontal edges */
	if (y0 == y1)
		return;

	if (r->nedges+1 > r->cedges) {
		r->cedges = r->cedges > 0 ? r->cedges * 2 : 64;
		r->edges = (NSVGedge*)NANOSVG_realloc(r->edges, sizeof(NSVGedge) * r->cedges);
		if (r->edges == NULL) return;
	}

	e = &r->edges[r->nedges];
	r->nedges++;

	if (y0 < y1) {
		e->x0 = x0;
		e->y0 = y0;
		e->x1 = x1;
		e->y1 = y1;
		e->dir = 1;
	} else {
		e->x0 = x1;
		e->y0 = y1;
		e->x1 = x0;
		e->y1 = y0;
		e->dir = -1;
	}
}

static float nsvg__normalize(float *x, float* y)
{
	float d = sqrtf((*x)*(*x) + (*y)*(*y));
	if (d > 1e-6f) {
		float id = 1.0f / d;
		*x *= id;
		*y *= id;
	}
	return d;
}

static float nsvg__absf(float x) { return x < 0 ? -x : x; }

static void nsvg__flattenCubicBez(NSVGrasterizer* r,
								  float x1, float y1, float x2, float y2,
								  float x3, float y3, float x4, float y4,
								  int level, int type)
{
	float x12,y12,x23,y23,x34,y34,x123,y123,x234,y234,x1234,y1234;
	float dx,dy,d2,d3;

	if (level > 10) return;

	x12 = (x1+x2)*0.5f;
	y12 = (y1+y2)*0.5f;
	x23 = (x2+x3)*0.5f;
	y23 = (y2+y3)*0.5f;
	x34 = (x3+x4)*0.5f;
	y34 = (y3+y4)*0.5f;
	x123 = (x12+x23)*0.5f;
	y123 = (y12+y23)*0.5f;

	dx = x4 - x1;
	dy = y4 - y1;
	d2 = nsvg__absf(((x2 - x4) * dy - (y2 - y4) * dx));
	d3 = nsvg__absf(((x3 - x4) * dy - (y3 - y4) * dx));

	if ((d2 + d3)*(d2 + d3) < r->tessTol * (dx*dx + dy*dy)) {
		nsvg__addPathPoint(r, x4, y4, type);
		return;
	}

	x234 = (x23+x34)*0.5f;
	y234 = (y23+y34)*0.5f;
	x1234 = (x123+x234)*0.5f;
	y1234 = (y123+y234)*0.5f;

	nsvg__flattenCubicBez(r, x1,y1, x12,y12, x123,y123, x1234,y1234, level+1, 0);
	nsvg__flattenCubicBez(r, x1234,y1234, x234,y234, x34,y34, x4,y4, level+1, type);
}

static void nsvg__flattenShape(NSVGrasterizer* r, NSVGshape* shape, float scale)
{
	int i, j;
	NSVGpath* path;

	for (path = shape->paths; path != NULL; path = path->next) {
		r->npoints = 0;
		/* 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 */
		nsvg__addPathPoint(r, path->pts[0]*scale, path->pts[1]*scale, 0);
		/* 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);
	}
}

enum NSVGpointFlags
{
	NSVG_PT_CORNER = 0x01,
	NSVG_PT_BEVEL = 0x02,
	NSVG_PT_LEFT = 0x04
};

static void nsvg__initClosed(NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1, float lineWidth)
{
	float w = lineWidth * 0.5f;
	float dx = p1->x - p0->x;
	float dy = p1->y - p0->y;
	float len = nsvg__normalize(&dx, &dy);
	float px = p0->x + dx*len*0.5f, py = p0->y + dy*len*0.5f;
	float dlx = dy, dly = -dx;
	float lx = px - dlx*w, ly = py - dly*w;
	float rx = px + dlx*w, ry = py + dly*w;
	left->x = lx; left->y = ly;
	right->x = rx; right->y = ry;
}

static void nsvg__buttCap(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p, float dx, float dy, float lineWidth, int connect)
{
	float w = lineWidth * 0.5f;
	float px = p->x, py = p->y;
	float dlx = dy, dly = -dx;
	float lx = px - dlx*w, ly = py - dly*w;
	float rx = px + dlx*w, ry = py + dly*w;

	nsvg__addEdge(r, lx, ly, rx, ry);

	if (connect) {
		nsvg__addEdge(r, left->x, left->y, lx, ly);
		nsvg__addEdge(r, rx, ry, right->x, right->y);
	}
	left->x = lx; left->y = ly;
	right->x = rx; right->y = ry;
}

static void nsvg__squareCap(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p, float dx, float dy, float lineWidth, int connect)
{
	float w = lineWidth * 0.5f;
	float px = p->x - dx*w, py = p->y - dy*w;
	float dlx = dy, dly = -dx;
	float lx = px - dlx*w, ly = py - dly*w;
	float rx = px + dlx*w, ry = py + dly*w;

	nsvg__addEdge(r, lx, ly, rx, ry);

	if (connect) {
		nsvg__addEdge(r, left->x, left->y, lx, ly);
		nsvg__addEdge(r, rx, ry, right->x, right->y);
	}
	left->x = lx; left->y = ly;
	right->x = rx; right->y = ry;
}

#ifndef NSVG_PI
#define NSVG_PI (3.14159265358979323846264338327f)
#endif

static void nsvg__roundCap(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p, float dx, float dy, float lineWidth, int ncap, int connect)
{
	int i;
	float w = lineWidth * 0.5f;
	float px = p->x, py = p->y;
	float dlx = dy, dly = -dx;
	float lx = 0, ly = 0, rx = 0, ry = 0, prevx = 0, prevy = 0;

	for (i = 0; i < ncap; i++) {
		float a = (float)i/(float)(ncap-1)*NSVG_PI;
		float ax = cosf(a) * w, ay = sinf(a) * w;
		float x = px - dlx*ax - dx*ay;
		float y = py - dly*ax - dy*ay;

		if (i > 0)
			nsvg__addEdge(r, prevx, prevy, x, y);

		prevx = x;
		prevy = y;

		if (i == 0) {
			lx = x; ly = y;
		} else if (i == ncap-1) {
			rx = x; ry = y;
		}
	}

	if (connect) {
		nsvg__addEdge(r, left->x, left->y, lx, ly);
		nsvg__addEdge(r, rx, ry, right->x, right->y);
	}

	left->x = lx; left->y = ly;
	right->x = rx; right->y = ry;
}

static void nsvg__bevelJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1, float lineWidth)
{
	float w = lineWidth * 0.5f;
	float dlx0 = p0->dy, dly0 = -p0->dx;
	float dlx1 = p1->dy, dly1 = -p1->dx;
	float lx0 = p1->x - (dlx0 * w), ly0 = p1->y - (dly0 * w);
	float rx0 = p1->x + (dlx0 * w), ry0 = p1->y + (dly0 * w);
	float lx1 = p1->x - (dlx1 * w), ly1 = p1->y - (dly1 * w);
	float rx1 = p1->x + (dlx1 * w), ry1 = p1->y + (dly1 * w);

	nsvg__addEdge(r, lx0, ly0, left->x, left->y);
	nsvg__addEdge(r, lx1, ly1, lx0, ly0);

	nsvg__addEdge(r, right->x, right->y, rx0, ry0);
	nsvg__addEdge(r, rx0, ry0, rx1, ry1);

	left->x = lx1; left->y = ly1;
	right->x = rx1; right->y = ry1;
}

static void nsvg__miterJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1, float lineWidth)
{
	float w = lineWidth * 0.5f;
	float dlx0 = p0->dy, dly0 = -p0->dx;
	float dlx1 = p1->dy, dly1 = -p1->dx;
	float lx0, rx0, lx1, rx1;
	float ly0, ry0, ly1, ry1;

	if (p1->flags & NSVG_PT_LEFT) {
		lx0 = lx1 = p1->x - p1->dmx * w;
		ly0 = ly1 = p1->y - p1->dmy * w;
		nsvg__addEdge(r, lx1, ly1, left->x, left->y);

		rx0 = p1->x + (dlx0 * w);
		ry0 = p1->y + (dly0 * w);
		rx1 = p1->x + (dlx1 * w);
		ry1 = p1->y + (dly1 * w);
		nsvg__addEdge(r, right->x, right->y, rx0, ry0);
		nsvg__addEdge(r, rx0, ry0, rx1, ry1);
	} else {
		lx0 = p1->x - (dlx0 * w);
		ly0 = p1->y - (dly0 * w);
		lx1 = p1->x - (dlx1 * w);
		ly1 = p1->y - (dly1 * w);
		nsvg__addEdge(r, lx0, ly0, left->x, left->y);
		nsvg__addEdge(r, lx1, ly1, lx0, ly0);

		rx0 = rx1 = p1->x + p1->dmx * w;
		ry0 = ry1 = p1->y + p1->dmy * w;
		nsvg__addEdge(r, right->x, right->y, rx1, ry1);
	}

	left->x = lx1; left->y = ly1;
	right->x = rx1; right->y = ry1;
}

static void nsvg__roundJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1, float lineWidth, int ncap)
{
	int i, n;
	float w = lineWidth * 0.5f;
	float dlx0 = p0->dy, dly0 = -p0->dx;
	float dlx1 = p1->dy, dly1 = -p1->dx;
	float a0 = atan2f(dly0, dlx0);
	float a1 = atan2f(dly1, dlx1);
	float da = a1 - a0;
	float lx, ly, rx, ry;

	if (da < NSVG_PI) da += NSVG_PI*2;
	if (da > NSVG_PI) da -= NSVG_PI*2;

	n = (int)ceilf((nsvg__absf(da) / NSVG_PI) * (float)ncap);
	if (n < 2) n = 2;
	if (n > ncap) n = ncap;

	lx = left->x;
	ly = left->y;
	rx = right->x;
	ry = right->y;

	for (i = 0; i < n; i++) {
		float u = (float)i/(float)(n-1);
		float a = a0 + u*da;
		float ax = cosf(a) * w, ay = sinf(a) * w;
		float lx1 = p1->x - ax, ly1 = p1->y - ay;
		float rx1 = p1->x + ax, ry1 = p1->y + ay;

		nsvg__addEdge(r, lx1, ly1, lx, ly);
		nsvg__addEdge(r, rx, ry, rx1, ry1);

		lx = lx1; ly = ly1;
		rx = rx1; ry = ry1;
	}

	left->x = lx; left->y = ly;
	right->x = rx; right->y = ry;
}

static void nsvg__straightJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p1, float lineWidth)
{
	float w = lineWidth * 0.5f;
	float lx = p1->x - (p1->dmx * w), ly = p1->y - (p1->dmy * w);
	float rx = p1->x + (p1->dmx * w), ry = p1->y + (p1->dmy * w);

	nsvg__addEdge(r, lx, ly, left->x, left->y);
	nsvg__addEdge(r, right->x, right->y, rx, ry);

	left->x = lx; left->y = ly;
	right->x = rx; right->y = ry;
}

static int nsvg__curveDivs(float r, float arc, float tol)
{
	float da = acosf(r / (r + tol)) * 2.0f;
	int divs = (int)ceilf(arc / da);
	if (divs < 2) divs = 2;
	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. */
	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 */
	if (closed) {
		/* Looping */
		p0 = &points[npoints-1];
		p1 = &points[0];
		s = 0;
		e = npoints;
	} else {
		/* Add cap */
		p0 = &points[0];
		p1 = &points[1];
		s = 1;
		e = npoints-1;
	}

	if (closed) {
		nsvg__initClosed(&left, &right, p0, p1, lineWidth);
		firstLeft = left;
		firstRight = right;
	} else {
		/* 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);
		else if (lineCap == NSVG_CAP_SQUARE)
			nsvg__squareCap(r, &left, &right, p0, dx, dy, lineWidth, 0);
		else if (lineCap == NSVG_CAP_ROUND)
			nsvg__roundCap(r, &left, &right, p0, dx, dy, lineWidth, ncap, 0);
	}

	for (j = s; j < e; ++j) {
		if (p1->flags & NSVG_PT_CORNER) {
			if (lineJoin == NSVG_JOIN_ROUND)
				nsvg__roundJoin(r, &left, &right, p0, p1, lineWidth, ncap);
			else if (lineJoin == NSVG_JOIN_BEVEL || (p1->flags & NSVG_PT_BEVEL))
				nsvg__bevelJoin(r, &left, &right, p0, p1, lineWidth);
			else
				nsvg__miterJoin(r, &left, &right, p0, p1, lineWidth);
		} else {
			nsvg__straightJoin(r, &left, &right, p1, lineWidth);
		}
		p0 = p1++;
	}

	if (closed) {
		/* 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 */
		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);
		else if (lineCap == NSVG_CAP_SQUARE)
			nsvg__squareCap(r, &right, &left, p1, -dx, -dy, lineWidth, 1);
		else if (lineCap == NSVG_CAP_ROUND)
			nsvg__roundCap(r, &right, &left, p1, -dx, -dy, lineWidth, ncap, 1);
	}
}

static void nsvg__prepareStroke(NSVGrasterizer* r, float miterLimit, int lineJoin)
{
	int i, j;
	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 */
		p0->dx = p1->x - p0->x;
		p0->dy = p1->y - p0->y;
		p0->len = nsvg__normalize(&p0->dx, &p0->dy);
		/* Advance */
		p0 = p1++;
	}

	/* 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 */
		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;
			if (s2 > 600.0f) {
				s2 = 600.0f;
			}
			p1->dmx *= s2;
			p1->dmy *= s2;
		}

		/* Clear flags, but keep the corner. */
		p1->flags = (p1->flags & NSVG_PT_CORNER) ? NSVG_PT_CORNER : 0;

		/* 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. */
		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;
			}
		}

		p0 = p1++;
	}
}

static void nsvg__flattenShapeStroke(NSVGrasterizer* r, NSVGshape* shape, float scale)
{
	int i, j, closed;
	NSVGpath* path;
	NSVGpoint* p0, *p1;
	float miterLimit = shape->miterLimit;
	int lineJoin = shape->strokeLineJoin;
	int lineCap = shape->strokeLineCap;
	float lineWidth = shape->strokeWidth * scale;

	for (path = shape->paths; path != NULL; path = path->next) {
		/* 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);
		}
		if (r->npoints < 2)
			continue;

		closed = path->closed;

		/* 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];
			closed = 1;
		}

		if (shape->strokeDashCount > 0) {
			int idash = 0, dashState = 1;
			float totalDist = 0, dashLen, allDashLen, dashOffset;
			NSVGpoint cur;

			if (closed)
				nsvg__appendPathPoint(r, r->points[0]);

			/* Duplicate points -> points2. */
			nsvg__duplicatePoints(r);

			r->npoints = 0;
 			cur = r->points2[0];
			nsvg__appendPathPoint(r, cur);

			/* 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 */
			dashOffset = fmodf(shape->strokeDashOffset, allDashLen);
			if (dashOffset < 0.0f)
				dashOffset += allDashLen;

			while (dashOffset > shape->strokeDashArray[idash]) {
				dashOffset -= shape->strokeDashArray[idash];
				idash = (idash + 1) % shape->strokeDashCount;
			}
			dashLen = (shape->strokeDashArray[idash] - dashOffset) * scale;

			for (j = 1; j < r->npoints2; ) {
				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 */
					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 */
					if (r->npoints > 1 && dashState) {
						nsvg__prepareStroke(r, miterLimit, lineJoin);
						nsvg__expandStroke(r, r->points, r->npoints, 0, lineJoin, lineCap, lineWidth);
					}
					/* Advance dash pattern */
					dashState = !dashState;
					idash = (idash+1) % shape->strokeDashCount;
					dashLen = shape->strokeDashArray[idash] * scale;
					/* Restart */
					cur.x = x;
					cur.y = y;
					cur.flags = NSVG_PT_CORNER;
					totalDist = 0.0f;
					r->npoints = 0;
					nsvg__appendPathPoint(r, cur);
				} else {
					totalDist += dist;
					cur = r->points2[j];
					nsvg__appendPathPoint(r, cur);
					j++;
				}
			}
			/* 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);
		}
	}
}

static int nsvg__cmpEdge(const void *p, const void *q)
{
	const NSVGedge* a = (const NSVGedge*)p;
	const NSVGedge* b = (const NSVGedge*)q;

	if (a->y0 < b->y0) return -1;
	if (a->y0 > b->y0) return  1;
	return 0;
}


static NSVGactiveEdge* nsvg__addActive(NSVGrasterizer* r, NSVGedge* e, float startPoint)
{
	 NSVGactiveEdge* z;
	float dxdy;

	if (r->freelist != NULL) {
		/* Restore from freelist. */
		z = r->freelist;
		r->freelist = z->next;
	} else {
		/* 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 */
	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->ey = e->y1;
	z->next = 0;
	z->dir = e->dir;

	return z;
}

static void nsvg__freeActive(NSVGrasterizer* r, NSVGactiveEdge* z)
{
	z->next = r->freelist;
	r->freelist = z;
}

static void nsvg__fillScanline(unsigned char* scanline, int len, int x0, int x1, int maxWeight, int* xmin, int* xmax)
{
	int i = x0 >> NSVG__FIXSHIFT;
	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 */
			scanline[i] = (unsigned char)(scanline[i] + ((x1 - x0) * maxWeight >> NSVG__FIXSHIFT));
		} else {
			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 */

			if (j < len) /* add antialiasing for x1 */
				scanline[j] = (unsigned char)(scanline[j] + (((x1 & NSVG__FIXMASK) * maxWeight) >> NSVG__FIXSHIFT));
			else
				j = len; /* clip */

			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
 */
static void nsvg__fillActiveEdges(unsigned char* scanline, int len, NSVGactiveEdge* e, int maxWeight, int* xmin, int* xmax, char fillRule)
{
	/* non-zero winding fill */
	int x0 = 0, w = 0;

	if (fillRule == NSVG_FILLRULE_NONZERO) {
		/* Non-zero */
		while (e != NULL) {
			if (w == 0) {
				/* 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 (w == 0)
					nsvg__fillScanline(scanline, len, x0, x1, maxWeight, xmin, xmax);
			}
			e = e->next;
		}
	} else if (fillRule == NSVG_FILLRULE_EVENODD) {
		/* Even-odd */
		while (e != NULL) {
			if (w == 0) {
				/* 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);
			}
			e = e->next;
		}
	}
}

static float nsvg__clampf(float a, float mn, float mx) { return a < mn ? mn : (a > mx ? mx : a); }

static unsigned int nsvg__RGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
{
	return (r) | (g << 8) | (b << 16) | (a << 24);
}

static unsigned int nsvg__lerpRGBA(unsigned int c0, unsigned int c1, float u)
{
	int iu = (int)(nsvg__clampf(u, 0.0f, 1.0f) * 256.0f);
	int r = (((c0) & 0xff)*(256-iu) + (((c1) & 0xff)*iu)) >> 8;
	int g = (((c0>>8) & 0xff)*(256-iu) + (((c1>>8) & 0xff)*iu)) >> 8;
	int b = (((c0>>16) & 0xff)*(256-iu) + (((c1>>16) & 0xff)*iu)) >> 8;
	int a = (((c0>>24) & 0xff)*(256-iu) + (((c1>>24) & 0xff)*iu)) >> 8;
	return nsvg__RGBA((unsigned char)r, (unsigned char)g, (unsigned char)b, (unsigned char)a);
}

static unsigned int nsvg__applyOpacity(unsigned int c, float u)
{
	int iu = (int)(nsvg__clampf(u, 0.0f, 1.0f) * 256.0f);
	int r = (c) & 0xff;
	int g = (c>>8) & 0xff;
	int b = (c>>16) & 0xff;
	int a = (((c>>24) & 0xff)*iu) >> 8;
	return nsvg__RGBA((unsigned char)r, (unsigned char)g, (unsigned char)b, (unsigned char)a);
}

static inline int nsvg__div255(int x)
{
    return ((x+1) * 257) >> 16;
}

static void nsvg__scanlineSolid(unsigned char* dst, int count, unsigned char* cover, int x, int y,
								float tx, float ty, float scale, NSVGcachedPaint* cache)
{

	if (cache->type == NSVG_PAINT_COLOR) {
		int i, cr, cg, cb, ca;
		cr = cache->colors[0] & 0xff;
		cg = (cache->colors[0] >> 8) & 0xff;
		cb = (cache->colors[0] >> 16) & 0xff;
		ca = (cache->colors[0] >> 24) & 0xff;

		for (i = 0; i < count; i++) {
			int r,g,b;
			int a = nsvg__div255((int)cover[0] * ca);
			int ia = 255 - a;
			/* Premultiply */
			r = nsvg__div255(cr * a);
			g = nsvg__div255(cg * a);
			b = nsvg__div255(cb * a);

			/* 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]);

			dst[0] = (unsigned char)r;
			dst[1] = (unsigned char)g;
			dst[2] = (unsigned char)b;
			dst[3] = (unsigned char)a;

			cover++;
			dst += 4;
		}
	} else if (cache->type == NSVG_PAINT_LINEAR_GRADIENT) {
		/* 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;

		fx = ((float)x - tx) / scale;
		fy = ((float)y - ty) / scale;
		dx = 1.0f / scale;

		for (i = 0; i < count; i++) {
			int r,g,b,a,ia;
			gy = fx*t[1] + fy*t[3] + t[5];
			c = cache->colors[(int)nsvg__clampf(gy*255.0f, 0, 255.0f)];
			cr = (c) & 0xff;
			cg = (c >> 8) & 0xff;
			cb = (c >> 16) & 0xff;
			ca = (c >> 24) & 0xff;

			a = nsvg__div255((int)cover[0] * ca);
			ia = 255 - a;

			/* Premultiply */
			r = nsvg__div255(cr * a);
			g = nsvg__div255(cg * a);
			b = nsvg__div255(cb * a);

			/* 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]);

			dst[0] = (unsigned char)r;
			dst[1] = (unsigned char)g;
			dst[2] = (unsigned char)b;
			dst[3] = (unsigned char)a;

			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) */
		float fx, fy, dx, gx, gy, gd;
		float* t = cache->xform;
		int i, cr, cg, cb, ca;
		unsigned int c;

		fx = ((float)x - tx) / scale;
		fy = ((float)y - ty) / scale;
		dx = 1.0f / scale;

		for (i = 0; i < count; i++) {
			int r,g,b,a,ia;
			gx = fx*t[0] + fy*t[2] + t[4];
			gy = fx*t[1] + fy*t[3] + t[5];
			gd = sqrtf(gx*gx + gy*gy);
			c = cache->colors[(int)nsvg__clampf(gd*255.0f, 0, 255.0f)];
			cr = (c) & 0xff;
			cg = (c >> 8) & 0xff;
			cb = (c >> 16) & 0xff;
			ca = (c >> 24) & 0xff;

			a = nsvg__div255((int)cover[0] * ca);
			ia = 255 - a;

			/* Premultiply */
			r = nsvg__div255(cr * a);
			g = nsvg__div255(cg * a);
			b = nsvg__div255(cb * a);

			/* 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]);

			dst[0] = (unsigned char)r;
			dst[1] = (unsigned char)g;
			dst[2] = (unsigned char)b;
			dst[3] = (unsigned char)a;

			cover++;
			dst += 4;
			fx += dx;
		}
	}
}

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 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 */
			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 */
			while (*step) {
				NSVGactiveEdge *z = *step;
				if (z->ey <= scany) {
					*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 */
				}
			}

			/* resort the list if needed */
			for (;;) {
				int changed = 0;
				step = &active;
				while (*step && (*step)->next) {
					if ((*step)->x > (*step)->next->x) {
						NSVGactiveEdge* t = *step;
						NSVGactiveEdge* q = t->next;
						t->next = q->next;
						q->next = t;
						*step = q;
						changed = 1;
					}
					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 */
			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 */
					if (active == NULL) {
						active = z;
					} else if (z->x < active->x) {
						/* insert at front */
						z->next = active;
						active = z;
					} else {
						/* 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 */
						z->next = p->next;
						p->next = z;
					}
				}
				e++;
			}

			/* now process all active edges in non-zero fashion */
			if (active != NULL)
				nsvg__fillActiveEdges(r->scanline, r->width, active, maxWeight, &xmin, &xmax, fillRule);
		}
		/* 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);
		}
	}

}

static void nsvg__unpremultiplyAlpha(unsigned char* image, int w, int h, int stride)
{
	int x,y;

	/* 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) {
				row[0] = (unsigned char)(r*255/a);
				row[1] = (unsigned char)(g*255/a);
				row[2] = (unsigned char)(b*255/a);
			}
			row += 4;
		}
	}

	/* 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) {
				if (x-1 > 0 && row[-1] != 0) {
					r += row[-4];
					g += row[-3];
					b += row[-2];
					n++;
				}
				if (x+1 < w && row[7] != 0) {
					r += row[4];
					g += row[5];
					b += row[6];
					n++;
				}
				if (y-1 > 0 && row[-stride+3] != 0) {
					r += row[-stride];
					g += row[-stride+1];
					b += row[-stride+2];
					n++;
				}
				if (y+1 < h && row[stride+3] != 0) {
					r += row[stride];
					g += row[stride+1];
					b += row[stride+2];
					n++;
				}
				if (n > 0) {
					row[0] = (unsigned char)(r/n);
					row[1] = (unsigned char)(g/n);
					row[2] = (unsigned char)(b/n);
				}
			}
			row += 4;
		}
	}
}


static void nsvg__initPaint(NSVGcachedPaint* cache, NSVGpaint* paint, float opacity)
{
	int i, j;
	NSVGgradient* grad;

	cache->type = paint->type;

	if (paint->type == NSVG_PAINT_COLOR) {
		cache->colors[0] = nsvg__applyOpacity(paint->color, opacity);
		return;
	}

	grad = paint->gradient;

	cache->spread = grad->spread;
	memcpy(cache->xform, grad->xform, sizeof(float)*6);

	if (grad->nstops == 0) {
		for (i = 0; i < 256; i++)
			cache->colors[i] = 0;
	} if (grad->nstops == 1) {
		for (i = 0; i < 256; i++)
			cache->colors[i] = nsvg__applyOpacity(grad->stops[i].color, opacity);
	} else {
		unsigned int ca, cb = 0;
		float ua, ub, du, u;
		int ia, ib, count;

		ca = nsvg__applyOpacity(grad->stops[0].color, opacity);
		ua = nsvg__clampf(grad->stops[0].offset, 0, 1);
		ub = nsvg__clampf(grad->stops[grad->nstops-1].offset, ua, 1);
		ia = (int)(ua * 255.0f);
		ib = (int)(ub * 255.0f);
		for (i = 0; i < ia; i++) {
			cache->colors[i] = ca;
		}

		for (i = 0; i < grad->nstops-1; i++) {
			ca = nsvg__applyOpacity(grad->stops[i].color, opacity);
			cb = nsvg__applyOpacity(grad->stops[i+1].color, opacity);
			ua = nsvg__clampf(grad->stops[i].offset, 0, 1);
			ub = nsvg__clampf(grad->stops[i+1].offset, 0, 1);
			ia = (int)(ua * 255.0f);
			ib = (int)(ub * 255.0f);
			count = ib - ia;
			if (count <= 0) continue;
			u = 0;
			du = 1.0f / (float)count;
			for (j = 0; j < count; j++) {
				cache->colors[ia+j] = nsvg__lerpRGBA(ca,cb,u);
				u += du;
			}
		}

		for (i = ib; i < 256; i++)
			cache->colors[i] = cb;
	}

}

/*
static void dumpEdges(NSVGrasterizer* r, const char* name)
{
	float xmin = 0, xmax = 0, ymin = 0, ymax = 0;
	NSVGedge *e = NULL;
	int i;
	if (r->nedges == 0) return;
	FILE* fp = fopen(name, "w");
	if (fp == NULL) return;

	xmin = xmax = r->edges[0].x0;
	ymin = ymax = r->edges[0].y0;
	for (i = 0; i < r->nedges; i++) {
		e = &r->edges[i];
		xmin = nsvg__minf(xmin, e->x0);
		xmin = nsvg__minf(xmin, e->x1);
		xmax = nsvg__maxf(xmax, e->x0);
		xmax = nsvg__maxf(xmax, e->x1);
		ymin = nsvg__minf(ymin, e->y0);
		ymin = nsvg__minf(ymin, e->y1);
		ymax = nsvg__maxf(ymax, e->y0);
		ymax = nsvg__maxf(ymax, e->y1);
	}

	fprintf(fp, "<svg viewBox=\"%f %f %f %f\" xmlns=\"http://www.w3.org/2000/svg\">", xmin, ymin, (xmax - xmin), (ymax - ymin));

	for (i = 0; i < r->nedges; i++) {
		e = &r->edges[i];
		fprintf(fp ,"<line x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" style=\"stroke:#000;\" />", e->x0,e->y0, e->x1,e->y1);
	}

	for (i = 0; i < r->npoints; i++) {
		if (i+1 < r->npoints)
			fprintf(fp ,"<line x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" style=\"stroke:#f00;\" />", r->points[i].x, r->points[i].y, r->points[i+1].x, r->points[i+1].y);
		fprintf(fp ,"<circle cx=\"%f\" cy=\"%f\" r=\"1\" style=\"fill:%s;\" />", r->points[i].x, r->points[i].y, r->points[i].flags == 0 ? "#f00" : "#0f0");
	}

	fprintf(fp, "</svg>");
	fclose(fp);
}
*/

NANOSVG_SCOPE
void nsvgRasterize(NSVGrasterizer* r,
				   NSVGimage* image, float tx, float ty, float scale,
				   unsigned char* dst, int w, int h, int stride)
{
	NSVGshape *shape = NULL;
	NSVGedge *e = NULL;
	NSVGcachedPaint cache;
	int i;

	r->bitmap = dst;
	r->width = w;
	r->height = h;
	r->stride = stride;

	if (w > r->cscanline) {
		r->cscanline = w;
		r->scanline = (unsigned char*)NANOSVG_realloc(r->scanline, w);
		if (r->scanline == NULL) return;
	}

	for (i = 0; i < h; i++)
		memset(&dst[i*stride], 0, w*4);

	for (shape = image->shapes; shape != NULL; shape = shape->next) {
		if (!(shape->flags & NSVG_FLAGS_VISIBLE))
			continue;

		if (shape->fill.type != NSVG_PAINT_NONE) {
			nsvg__resetPool(r);
			r->freelist = NULL;
			r->nedges = 0;

			nsvg__flattenShape(r, shape, scale);

			/* 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 */
			qsort(r->edges, r->nedges, sizeof(NSVGedge), nsvg__cmpEdge);

			/* 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) {
			nsvg__resetPool(r);
			r->freelist = NULL;
			r->nedges = 0;

			nsvg__flattenShapeStroke(r, shape, scale);

/*			dumpEdges(r, "edge.svg"); */

			/* 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 */
			qsort(r->edges, r->nedges, sizeof(NSVGedge), nsvg__cmpEdge);

			/* 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);
		}
	}

	nsvg__unpremultiplyAlpha(dst, w, h, stride);

	r->bitmap = NULL;
	r->width = 0;
	r->height = 0;
	r->stride = 0;
}

#endif
Changes to generic/tk.decls.
1
2
3
4
5
6
7
8
9


10
11
12
13
14
15
16
1
2
3
4
5
6
7


8
9
10
11
12
13
14
15
16







-
-
+
+







# tk.decls --
#
#	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 <[email protected]>
# Copyright © 1998-2000 Ajuba Solutions.
# Copyright © 2007 Daniel A. Steffen <[email protected]>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

library tk

# Define the tk interface with 3 sub interfaces:
101
102
103
104
105
106
107
108

109
110
111
112
113
114
115
101
102
103
104
105
106
107

108
109
110
111
112
113
114
115







-
+







    void Tk_CanvasSetStippleOrigin(Tk_Canvas canvas, GC gc)
}
declare 18 {
    int Tk_CanvasTagsParseProc(ClientData clientData, Tcl_Interp *interp,
	    Tk_Window tkwin, const char *value, char *widgRec, int offset)
}
declare 19 {
    CONST86 char *Tk_CanvasTagsPrintProc(ClientData clientData, Tk_Window tkwin,
    const char *Tk_CanvasTagsPrintProc(ClientData clientData, Tk_Window tkwin,
	    char *widgRec, int offset, Tcl_FreeProc **freeProcPtr)
}
declare 20 {
    Tk_Window	Tk_CanvasTkwin(Tk_Canvas canvas)
}
declare 21 {
    void Tk_CanvasWindowCoords(Tk_Canvas canvas, double x, double y,
142
143
144
145
146
147
148
149

150
151
152
153
154
155
156
142
143
144
145
146
147
148

149
150
151
152
153
154
155
156







-
+







    int Tk_ConfigureValue(Tcl_Interp *interp,
	    Tk_Window tkwin, const Tk_ConfigSpec *specs,
	    char *widgRec, const char *argvName, int flags)
}
declare 29 {
    int Tk_ConfigureWidget(Tcl_Interp *interp,
	    Tk_Window tkwin, const Tk_ConfigSpec *specs,
	    int argc, CONST84 char **argv, char *widgRec,
	    int argc, const char **argv, char *widgRec,
	    int flags)
}
declare 30 {
    void Tk_ConfigureWindow(Tk_Window tkwin,
	    unsigned int valueMask, XWindowChanges *valuePtr)
}
declare 31 {
241
242
243
244
245
246
247
248

249
250
251
252
253
254
255
241
242
243
244
245
246
247

248
249
250
251
252
253
254
255







-
+







declare 53 {
    void Tk_DeleteSelHandler(Tk_Window tkwin, Atom selection, Atom target)
}
declare 54 {
    void Tk_DestroyWindow(Tk_Window tkwin)
}
declare 55 {
    CONST84_RETURN char *Tk_DisplayName(Tk_Window tkwin)
    const char *Tk_DisplayName(Tk_Window tkwin)
}
declare 56 {
    int Tk_DistanceToTextLayout(Tk_TextLayout layout, int x, int y)
}
declare 57 {
    void Tk_Draw3DPolygon(Tk_Window tkwin,
	    Drawable drawable, Tk_3DBorder border,
322
323
324
325
326
327
328
329

330
331
332
333
334
335
336
322
323
324
325
326
327
328

329
330
331
332
333
334
335
336







-
+







}
declare 75 {
    void Tk_FreePixmap(Display *display, Pixmap pixmap)
}
declare 76 {
    void Tk_FreeTextLayout(Tk_TextLayout textLayout)
}
declare 77 {
declare 77 {deprecated {function does nothing, call can be removed}} {
    void Tk_FreeXId(Display *display, XID xid)
}
declare 78 {
    GC Tk_GCForColor(XColor *colorPtr, Drawable drawable)
}
declare 79 {
    void Tk_GeometryRequest(Tk_Window tkwin, int reqWidth,  int reqHeight)
344
345
346
347
348
349
350
351

352
353
354

355
356
357
358
359
360
361
344
345
346
347
348
349
350

351
352
353

354
355
356
357
358
359
360
361







-
+


-
+







	    Tk_BindingTable bindingTable, ClientData object)
}
declare 82 {
    int Tk_GetAnchor(Tcl_Interp *interp,
	    const char *str, Tk_Anchor *anchorPtr)
}
declare 83 {
    CONST84_RETURN char *Tk_GetAtomName(Tk_Window tkwin, Atom atom)
    const char *Tk_GetAtomName(Tk_Window tkwin, Atom atom)
}
declare 84 {
    CONST84_RETURN char *Tk_GetBinding(Tcl_Interp *interp,
    const char *Tk_GetBinding(Tcl_Interp *interp,
	    Tk_BindingTable bindingTable, ClientData object,
	    const char *eventStr)
}
declare 85 {
    Pixmap Tk_GetBitmap(Tcl_Interp *interp, Tk_Window tkwin, const char *str)
}
declare 86 {
399
400
401
402
403
404
405
406
407


408
409
410
411
412
413
414
399
400
401
402
403
404
405


406
407
408
409
410
411
412
413
414







-
-
+
+







    GC Tk_GetGC(Tk_Window tkwin, unsigned long valueMask, XGCValues *valuePtr)
}
declare 97 {
    Tk_Image Tk_GetImage(Tcl_Interp *interp, Tk_Window tkwin, const char *name,
	    Tk_ImageChangedProc *changeProc, ClientData clientData)
}
declare 98 {
    ClientData Tk_GetImageMasterData(Tcl_Interp *interp,
	    const char *name, CONST86 Tk_ImageType **typePtrPtr)
    ClientData Tk_GetImageModelData(Tcl_Interp *interp,
	    const char *name, const Tk_ImageType **typePtrPtr)
}
declare 99 {
    Tk_ItemType *Tk_GetItemTypes(void)
}
declare 100 {
    int Tk_GetJoinStyle(Tcl_Interp *interp, const char *str, int *joinPtr)
}
435
436
437
438
439
440
441
442

443
444
445
446
447
448
449
435
436
437
438
439
440
441

442
443
444
445
446
447
448
449







-
+







    int Tk_GetRelief(Tcl_Interp *interp, const char *name, int *reliefPtr)
}
declare 107 {
    void Tk_GetRootCoords(Tk_Window tkwin, int *xPtr, int *yPtr)
}
declare 108 {
    int Tk_GetScrollInfo(Tcl_Interp *interp,
	    int argc, CONST84 char **argv, double *dblPtr, int *intPtr)
	    int argc, const char **argv, double *dblPtr, int *intPtr)
}
declare 109 {
    int Tk_GetScreenMM(Tcl_Interp *interp,
	    Tk_Window tkwin, const char *str, double *doublePtr)
}
declare 110 {
    int Tk_GetSelection(Tcl_Interp *interp,
468
469
470
471
472
473
474
475

476
477
478
479
480
481
482
483
484
485
486
487
488
489
490


491
492
493
494
495
496
497
468
469
470
471
472
473
474

475
476
477
478
479
480
481
482
483
484
485
486
487
488


489
490
491
492
493
494
495
496
497







-
+













-
-
+
+







declare 115 {
    void Tk_HandleEvent(XEvent *eventPtr)
}
declare 116 {
    Tk_Window Tk_IdToWindow(Display *display, Window window)
}
declare 117 {
    void Tk_ImageChanged(Tk_ImageMaster master, int x, int y,
    void Tk_ImageChanged(Tk_ImageModel model, int x, int y,
	    int width, int height, int imageWidth, int imageHeight)
}
declare 118 {
    int Tk_Init(Tcl_Interp *interp)
}
declare 119 {
    Atom Tk_InternAtom(Tk_Window tkwin, const char *name)
}
declare 120 {
    int Tk_IntersectTextLayout(Tk_TextLayout layout, int x, int y,
	    int width, int height)
}
declare 121 {
    void Tk_MaintainGeometry(Tk_Window slave,
	    Tk_Window master, int x, int y, int width, int height)
    void Tk_MaintainGeometry(Tk_Window window,
	    Tk_Window container, int x, int y, int width, int height)
}
declare 122 {
    Tk_Window Tk_MainWindow(Tcl_Interp *interp)
}
declare 123 {
    void Tk_MakeWindowExist(Tk_Window tkwin)
}
514
515
516
517
518
519
520
521

522
523
524

525
526
527

528
529
530

531
532
533

534
535
536

537
538
539

540
541
542

543
544
545

546
547
548

549
550
551

552
553
554
555
556
557
558
559
560
561
562
563
564

565
566
567

568
569
570
571
572

573
574
575
576
577
578
579
580
581
582
583
584

585
586
587
588
589
590

591
592
593
594
595
596
597
514
515
516
517
518
519
520

521
522
523

524
525
526

527
528
529

530
531
532

533
534
535

536
537
538

539
540
541

542
543
544

545
546
547

548
549
550

551
552
553
554
555
556
557
558
559
560
561
562
563

564
565
566

567
568
569
570
571

572
573
574
575
576
577
578
579
580
581
582
583

584
585
586
587
588
589

590
591
592
593
594
595
596
597







-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+












-
+


-
+




-
+











-
+





-
+







declare 128 {
    void Tk_MoveWindow(Tk_Window tkwin, int x, int y)
}
declare 129 {
    void Tk_MoveToplevelWindow(Tk_Window tkwin, int x, int y)
}
declare 130 {
    CONST84_RETURN char *Tk_NameOf3DBorder(Tk_3DBorder border)
    const char *Tk_NameOf3DBorder(Tk_3DBorder border)
}
declare 131 {
    CONST84_RETURN char *Tk_NameOfAnchor(Tk_Anchor anchor)
    const char *Tk_NameOfAnchor(Tk_Anchor anchor)
}
declare 132 {
    CONST84_RETURN char *Tk_NameOfBitmap(Display *display, Pixmap bitmap)
    const char *Tk_NameOfBitmap(Display *display, Pixmap bitmap)
}
declare 133 {
    CONST84_RETURN char *Tk_NameOfCapStyle(int cap)
    const char *Tk_NameOfCapStyle(int cap)
}
declare 134 {
    CONST84_RETURN char *Tk_NameOfColor(XColor *colorPtr)
    const char *Tk_NameOfColor(XColor *colorPtr)
}
declare 135 {
    CONST84_RETURN char *Tk_NameOfCursor(Display *display, Tk_Cursor cursor)
    const char *Tk_NameOfCursor(Display *display, Tk_Cursor cursor)
}
declare 136 {
    CONST84_RETURN char *Tk_NameOfFont(Tk_Font font)
    const char *Tk_NameOfFont(Tk_Font font)
}
declare 137 {
    CONST84_RETURN char *Tk_NameOfImage(Tk_ImageMaster imageMaster)
    const char *Tk_NameOfImage(Tk_ImageModel model)
}
declare 138 {
    CONST84_RETURN char *Tk_NameOfJoinStyle(int join)
    const char *Tk_NameOfJoinStyle(int join)
}
declare 139 {
    CONST84_RETURN char *Tk_NameOfJustify(Tk_Justify justify)
    const char *Tk_NameOfJustify(Tk_Justify justify)
}
declare 140 {
    CONST84_RETURN char *Tk_NameOfRelief(int relief)
    const char *Tk_NameOfRelief(int relief)
}
declare 141 {
    Tk_Window Tk_NameToWindow(Tcl_Interp *interp,
	    const char *pathName, Tk_Window tkwin)
}
declare 142 {
    void Tk_OwnSelection(Tk_Window tkwin,
	    Atom selection, Tk_LostSelProc *proc,
	    ClientData clientData)
}
declare 143 {
    int Tk_ParseArgv(Tcl_Interp *interp,
	    Tk_Window tkwin, int *argcPtr, CONST84 char **argv,
	    Tk_Window tkwin, int *argcPtr, const char **argv,
	    const Tk_ArgvInfo *argTable, int flags)
}
declare 144 {
declare 144 {deprecated {function signature changed}} {
    void Tk_PhotoPutBlock_NoComposite(Tk_PhotoHandle handle,
	    Tk_PhotoImageBlock *blockPtr, int x, int y,
	    int width, int height)
}
declare 145 {
declare 145 {deprecated {function signature changed}} {
    void Tk_PhotoPutZoomedBlock_NoComposite(Tk_PhotoHandle handle,
	    Tk_PhotoImageBlock *blockPtr, int x, int y,
	    int width, int height, int zoomX, int zoomY,
	    int subsampleX, int subsampleY)
}
declare 146 {
    int Tk_PhotoGetImage(Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr)
}
declare 147 {
    void Tk_PhotoBlank(Tk_PhotoHandle handle)
}
declare 148 {
declare 148 {deprecated {function signature changed}} {
    void Tk_PhotoExpand_Panic(Tk_PhotoHandle handle, int width, int height )
}
declare 149 {
    void Tk_PhotoGetSize(Tk_PhotoHandle handle, int *widthPtr, int *heightPtr)
}
declare 150 {
declare 150 {deprecated {function signature changed}} {
    void Tk_PhotoSetSize_Panic(Tk_PhotoHandle handle, int width, int height)
}
declare 151 {
    int Tk_PointToChar(Tk_TextLayout layout, int x, int y)
}
declare 152 {
    int Tk_PostscriptFontName(Tk_Font tkfont, Tcl_DString *dsPtr)
688
689
690
691
692
693
694
695

696
697
698
699
700
701
702
688
689
690
691
692
693
694

695
696
697
698
699
700
701
702







-
+







	    Tk_TextLayout layout, int x, int y,
	    int underline)
}
declare 180 {
    void Tk_Ungrab(Tk_Window tkwin)
}
declare 181 {
    void Tk_UnmaintainGeometry(Tk_Window slave, Tk_Window master)
    void Tk_UnmaintainGeometry(Tk_Window window, Tk_Window container)
}
declare 182 {
    void Tk_UnmapWindow(Tk_Window tkwin)
}
declare 183 {
    void Tk_UnsetGrid(Tk_Window tkwin)
}
740
741
742
743
744
745
746
747

748
749
750
751
752
753
754
740
741
742
743
744
745
746

747
748
749
750
751
752
753
754







-
+







declare 193 {
    void  Tk_FreeBitmapFromObj(Tk_Window tkwin, Tcl_Obj *objPtr)
}
declare 194 {
    void  Tk_FreeColorFromObj(Tk_Window tkwin, Tcl_Obj *objPtr)
}
declare 195 {
    void  Tk_FreeConfigOptions(char *recordPtr, Tk_OptionTable optionToken,
    void  Tk_FreeConfigOptions(void *recordPtr, Tk_OptionTable optionToken,
	    Tk_Window tkwin)
}
declare 196 {
    void  Tk_FreeSavedOptions(Tk_SavedOptions *savePtr)
}
declare 197 {
    void  Tk_FreeCursorFromObj(Tk_Window tkwin, Tcl_Obj *objPtr)
770
771
772
773
774
775
776
777

778
779
780
781

782
783
784
785
786
787
788
770
771
772
773
774
775
776

777
778
779
780

781
782
783
784
785
786
787
788







-
+



-
+







    XColor *Tk_GetColorFromObj(Tk_Window tkwin, Tcl_Obj *objPtr)
}
declare 203 {
    Tk_Cursor Tk_GetCursorFromObj(Tk_Window tkwin, Tcl_Obj *objPtr)
}
declare 204 {
    Tcl_Obj *Tk_GetOptionInfo(Tcl_Interp *interp,
	    char *recordPtr, Tk_OptionTable optionTable,
	    void *recordPtr, Tk_OptionTable optionTable,
	    Tcl_Obj *namePtr, Tk_Window tkwin)
}
declare 205 {
    Tcl_Obj *Tk_GetOptionValue(Tcl_Interp *interp, char *recordPtr,
    Tcl_Obj *Tk_GetOptionValue(Tcl_Interp *interp, void *recordPtr,
	    Tk_OptionTable optionTable, Tcl_Obj *namePtr, Tk_Window tkwin)
}
declare 206 {
    int	 Tk_GetJustifyFromObj(Tcl_Interp *interp,
	    Tcl_Obj *objPtr, Tk_Justify *justifyPtr)
}
declare 207 {
798
799
800
801
802
803
804
805

806
807
808

809
810
811
812
813
814
815
816

817
818
819
820
821
822
823
798
799
800
801
802
803
804

805
806
807

808
809
810
811
812
813
814
815

816
817
818
819
820
821
822
823







-
+


-
+







-
+







	    Tcl_Obj *objPtr, int *resultPtr)
}
declare 210 {
    int	 Tk_GetScrollInfoObj(Tcl_Interp *interp,
	    int objc, Tcl_Obj *const objv[], double *dblPtr, int *intPtr)
}
declare 211 {
    int	 Tk_InitOptions(Tcl_Interp *interp, char *recordPtr,
    int	 Tk_InitOptions(Tcl_Interp *interp, void *recordPtr,
	    Tk_OptionTable optionToken, Tk_Window tkwin)
}
declare 212 {
declare 212 {nostub {Don't use this function in a stub-enabled extension}} {
    void  Tk_MainEx(int argc, char **argv, Tcl_AppInitProc *appInitProc,
	    Tcl_Interp *interp)
}
declare 213 {
    void  Tk_RestoreSavedOptions(Tk_SavedOptions *savePtr)
}
declare 214 {
    int	 Tk_SetOptions(Tcl_Interp *interp, char *recordPtr,
    int	 Tk_SetOptions(Tcl_Interp *interp, void *recordPtr,
	    Tk_OptionTable optionTable, int objc,
	    Tcl_Obj *const objv[], Tk_Window tkwin,
	    Tk_SavedOptions *savePtr, int *maskPtr)
}
declare 215 {
    void Tk_InitConsoleChannels(Tcl_Interp *interp)
}
939
940
941
942
943
944
945
946

947
948
949
950
951

952
953
954
955
956
957
958
939
940
941
942
943
944
945

946
947
948
949
950

951
952
953
954
955
956
957
958







-
+




-
+







}

# New in 8.4a5
#
declare 245 {
    void Tk_SetCaretPos(Tk_Window tkwin, int x, int y, int height)
}
declare 246 {
declare 246 {deprecated {function signature changed}} {
    void Tk_PhotoPutBlock_Panic(Tk_PhotoHandle handle,
	    Tk_PhotoImageBlock *blockPtr, int x, int y,
	    int width, int height, int compRule)
}
declare 247 {
declare 247 {deprecated {function signature changed}} {
    void Tk_PhotoPutZoomedBlock_Panic(Tk_PhotoHandle handle,
	    Tk_PhotoImageBlock *blockPtr, int x, int y,
	    int width, int height, int zoomX, int zoomY,
	    int subsampleX, int subsampleY, int compRule)
}
declare 248 {
    int Tk_CollapseMotionEvents(Display *display, int collapse)
997
998
999
1000
1001
1002
1003
1004

1005
1006
1007
1008
1009

1010
1011
1012
1013
1014
1015

1016
1017
1018
1019

1020
1021
1022
1023
1024
1025
1026
997
998
999
1000
1001
1002
1003

1004
1005
1006
1007
1008

1009
1010
1011
1012
1013
1014

1015
1016
1017
1018

1019
1020
1021
1022
1023
1024
1025
1026







-
+




-
+





-
+



-
+







}
declare 260 {
    Tk_StyledElement Tk_GetStyledElement(Tk_Style style, int elementId,
	Tk_OptionTable optionTable)
}
declare 261 {
    void Tk_GetElementSize(Tk_Style style, Tk_StyledElement element,
	    char *recordPtr, Tk_Window tkwin, int width, int height,
	    void *recordPtr, Tk_Window tkwin, int width, int height,
	    int inner, int *widthPtr, int *heightPtr)
}
declare 262 {
    void Tk_GetElementBox(Tk_Style style, Tk_StyledElement element,
	    char *recordPtr, Tk_Window tkwin, int x, int y, int width,
	    void *recordPtr, Tk_Window tkwin, int x, int y, int width,
	    int height, int inner, int *xPtr, int *yPtr, int *widthPtr,
	    int *heightPtr)
}
declare 263 {
    int Tk_GetElementBorderWidth(Tk_Style style, Tk_StyledElement element,
	    char *recordPtr, Tk_Window tkwin)
	    void *recordPtr, Tk_Window tkwin)
}
declare 264 {
    void Tk_DrawElement(Tk_Style style, Tk_StyledElement element,
	    char *recordPtr, Tk_Window tkwin, Drawable d, int x, int y,
	    void *recordPtr, Tk_Window tkwin, Drawable d, int x, int y,
	    int width, int height, int state)
}

# TIP#116
declare 265 {
    int Tk_PhotoExpand(Tcl_Interp *interp, Tk_PhotoHandle handle,
	    int width, int height)
1064
1065
1066
1067
1068
1069
1070






















1071
1072
1073
1074
1075
1076
1077
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







# build against legacy sources.
declare 272 {
    void Tk_CreateOldImageType(const Tk_ImageType *typePtr)
}
declare 273 {
    void Tk_CreateOldPhotoImageFormat(const Tk_PhotoImageFormat *formatPtr)
}

# TIP#580
declare 274 {
    int Tk_AlwaysShowSelection(Tk_Window tkwin)
}
declare 275 {
    unsigned Tk_GetButtonMask(unsigned button)
}
declare 276 {
    int Tk_GetDoublePixelsFromObj(Tcl_Interp *interp, Tk_Window tkwin,
	    Tcl_Obj *objPtr, double *doublePtr)
}
declare 277 {
    Tcl_Obj *Tk_NewWindowObj(Tk_Window tkwin)
}
declare 278 {
    void Tk_SendVirtualEvent(Tk_Window tkwin, const char *eventName,
	    Tcl_Obj *detail)
}
declare 279 {
    Tcl_Obj *Tk_FontGetDescription(Tk_Font tkfont)
}

# Define the platform specific public Tk interface.  These functions are
# only available on the designated platform.

interface tkPlat

################################
1095
1096
1097
1098
1099
1100
1101
1102

1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118


1119

1120
1121
1122
1123
1124

1125
1126
1127
1128
1129

1130
1131


1132

1133
1134
1135
1136
1137
1138
1139
1140
1141














1142
1143
1144
1145
1146
1147
1148
1149
1150








1151
1152
1153
1154
1117
1118
1119
1120
1121
1122
1123

1124
















1125
1126

1127
1128
1129
1130
1131

1132
1133
1134
1135
1136
1137
1138


1139
1140

1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185







-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
+




-
+





+
-
-
+
+
-
+









+
+
+
+
+
+
+
+
+
+
+
+
+
+









+
+
+
+
+
+
+
+




declare 5 win {
    int Tk_TranslateWinEvent(HWND hwnd,
	    UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result)
}

################################
# Aqua specific functions

# Stub removed because the function no longer exists.
declare 0 aqua {
    void Tk_MacOSXSetEmbedHandler(
	    Tk_MacOSXEmbedRegisterWinProc *registerWinProcPtr,
	    Tk_MacOSXEmbedGetGrafPortProc *getPortProcPtr,
	    Tk_MacOSXEmbedMakeContainerExistProc *containerExistProcPtr,
	    Tk_MacOSXEmbedGetClipProc *getClipProc,
	    Tk_MacOSXEmbedGetOffsetInParentProc *getOffsetProc)
}
declare 1 aqua {
    void Tk_MacOSXTurnOffMenus(void)
}
declare 2 aqua {
    void Tk_MacOSXTkOwnsCursor(int tkOwnsIt)
}
declare 3 aqua {
    void TkMacOSXInitMenus(Tcl_Interp *interp)
#declare 3 aqua {
#    void TkMacOSXInitMenus(Tcl_Interp *interp)
}
#}
declare 4 aqua {
    void TkMacOSXInitAppleEvents(Tcl_Interp *interp)
}
declare 5 aqua {
    void TkGenWMConfigureEvent(Tk_Window tkwin, int x, int y, int width,
    void TkGenWMConfigureEvent_(Tk_Window tkwin, int x, int y, int width,
	    int height, int flags)
}
declare 6 aqua {
    void TkMacOSXInvalClipRgns(Tk_Window tkwin)
}
# Stub removed because it just returned NULL.
declare 7 aqua {
    void *TkMacOSXGetDrawablePort(Drawable drawable)
#declare 7 aqua {
#    void *TkMacOSXGetDrawablePort(Drawable drawable)
}
#}
declare 8 aqua {
    void *TkMacOSXGetRootControl(Drawable drawable)
}
declare 9 aqua {
    void Tk_MacOSXSetupTkNotifier(void)
}
declare 10 aqua {
    int Tk_MacOSXIsAppInFront(void)
}
declare 11 aqua {
    Tk_Window Tk_MacOSXGetTkWindow(void *w)
}
declare 12 aqua {
    void *Tk_MacOSXGetCGContextForDrawable(Drawable drawable)
}
# Replaces TkMacOSXDrawable
declare 13 aqua {
    void *Tk_MacOSXGetNSWindowForDrawable(Drawable drawable)
}
declare 16 aqua {
    void TkGenWMConfigureEvent(Tk_Window tkwin, int x, int y, int width,
	    int height, int flags)
}

##############################################################################

# Public functions that are not accessible via the stubs table.

export {
    const char *Tk_PkgInitStubsCheck(Tcl_Interp *interp, const char *version,
	    int exact)
}
export {
    void Tk_MainEx(int argc, char **argv, Tcl_AppInitProc *appInitProc,
	    Tcl_Interp *interp)
}
export {
    void Tk_MainExW(int argc, wchar_t **argv,
	    Tcl_AppInitProc *appInitProc, Tcl_Interp *interp);
}

# Local Variables:
# mode: tcl
# End:
Changes to generic/tk.h.
13
14
15
16
17
18
19
20
21


22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
13
14
15
16
17
18
19


20
21
22
23







24
25
26
27
28
29
30







-
-
+
+


-
-
-
-
-
-
-







 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#ifndef _TK
#define _TK

#include <tcl.h>
#if (TCL_MAJOR_VERSION != 8) || (TCL_MINOR_VERSION < 6)
#	error Tk 8.6 must be compiled with tcl.h from Tcl 8.6 or better
#if (TCL_MAJOR_VERSION < 8) || (TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION < 6)
#	error Tk 8.7 must be compiled with tcl.h from Tcl 8.6 or better
#endif

#ifndef CONST84
#   define CONST84 const
#   define CONST84_RETURN const
#endif
#ifndef CONST86
#   define CONST86 CONST84
#endif
#ifndef EXTERN
#   define EXTERN extern TCL_STORAGE_CLASS
#endif

/*
 * Utility macros: STRINGIFY takes an argument and wraps it in "" (double
 * quotation marks), JOIN joins two arguments.
55
56
57
58
59
60
61
62
63


64
65
66
67
68
69
70
71
72
73
74
75
76
77
78



79
80
81


82
83
84
85
86
87
88
89
90
91
92
93
94
95



96
97
98
99
100
101
102
103
104
105
106
107
108




109
110
111
112
113
114
115
116
117

118
119
120
121
122
123
124

125
126
127
128
129
130
131

132
133
134
135
136
137
138
48
49
50
51
52
53
54


55
56
57
58
59
60
61
62
63
64
65
66
67
68



69
70
71
72


73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116

117
118
119
120
121
122
123
124
125
126
127
128
129
130
131

132
133
134
135
136
137
138
139







-
-
+
+












-
-
-
+
+
+

-
-
+
+














+
+
+













+
+
+
+








-
+







+






-
+







#endif

/*
 * When version numbers change here, you must also go into the following files
 * and update the version numbers:
 *
 * library/tk.tcl	(1 LOC patch)
 * unix/configure.in	(2 LOC Major, 2 LOC minor, 1 LOC patch)
 * win/configure.in	(as above)
 * unix/configure.ac	(2 LOC Major, 2 LOC minor, 1 LOC patch)
 * win/configure.ac	(as above)
 * README		(sections 0 and 1)
 * macosx/Tk-Common.xcconfig (not patchlevel) 1 LOC
 * win/README		(not patchlevel)
 * unix/README		(not patchlevel)
 * unix/tk.spec		(1 LOC patch)
 * win/tcl.m4		(not patchlevel)
 *
 * You may also need to update some of these files when the numbers change for
 * the version of Tcl that this release of Tk is compiled against.
 */

#define TK_MAJOR_VERSION	8
#define TK_MINOR_VERSION	6
#define TK_RELEASE_LEVEL	TCL_FINAL_RELEASE
#define TK_RELEASE_SERIAL	10
#define TK_MINOR_VERSION	7
#define TK_RELEASE_LEVEL	TCL_ALPHA_RELEASE
#define TK_RELEASE_SERIAL	4

#define TK_VERSION		"8.6"
#define TK_PATCH_LEVEL		"8.6.10"
#define TK_VERSION		"8.7"
#define TK_PATCH_LEVEL		"8.7a4"

/*
 * 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
 * for macintosh.
 *
 * Resource compilers don't like all the C stuff, like typedefs and procedure
 * declarations, that occur below, so block them out.
 */

#ifndef RC_INVOKED

#if !defined(_XLIB_H) && !defined(_X11_XLIB_H_)
#if defined(__GNUC__) && !defined(__cplusplus)
#   pragma GCC diagnostic ignored "-Wc++-compat"
#endif
#   include <X11/Xlib.h>
#   ifdef MAC_OSX_TK
#	include <X11/X.h>
#   endif
#endif
#if defined(STDC_HEADERS) || defined(__STDC__) || defined(__C99__FUNC__) \
     || defined(__cplusplus) || defined(_MSC_VER) || defined(__ICC)
#   include <stddef.h>
#endif

#ifdef BUILD_tk
#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS	DLLEXPORT
#else
# ifndef TCL_STORAGE_CLASS
#   define TCL_STORAGE_CLASS DLLIMPORT
# endif
#endif

/*
 *----------------------------------------------------------------------
 *
 * Decide whether or not to use input methods.
 */

#ifdef XNQueryInputStyle
#if defined(XNQueryInputStyle) && !defined(_WIN32) && !defined(MAC_OSX_TK)
#define TK_USE_INPUT_METHODS
#endif

/*
 * Dummy types that are used by clients:
 */

#define Tk_ImageMaster Tk_ImageModel
typedef struct Tk_BindingTable_ *Tk_BindingTable;
typedef struct Tk_Canvas_ *Tk_Canvas;
typedef struct Tk_Cursor_ *Tk_Cursor;
typedef struct Tk_ErrorHandler_ *Tk_ErrorHandler;
typedef struct Tk_Font_ *Tk_Font;
typedef struct Tk_Image__ *Tk_Image;
typedef struct Tk_ImageMaster_ *Tk_ImageMaster;
typedef struct Tk_ImageModel_ *Tk_ImageModel;
typedef struct Tk_OptionTable_ *Tk_OptionTable;
typedef struct Tk_PostscriptInfo_ *Tk_PostscriptInfo;
typedef struct Tk_TextLayout_ *Tk_TextLayout;
typedef struct Tk_Window_ *Tk_Window;
typedef struct Tk_3DBorder_ *Tk_3DBorder;
typedef struct Tk_Style_ *Tk_Style;
typedef struct Tk_StyleEngine_ *Tk_StyleEngine;
187
188
189
190
191
192
193

194

195
196
197
198
199
200




201
202
203
204
205
206
207








208
209
210
211
212
213
214
188
189
190
191
192
193
194
195

196
197
198




199
200
201
202
203
204
205




206
207
208
209
210
211
212
213
214
215
216
217
218
219
220







+
-
+


-
-
-
-
+
+
+
+



-
-
-
-
+
+
+
+
+
+
+
+







    const char *optionName;	/* Name used to specify option in Tcl
				 * commands. */
    const char *dbName;		/* Name for option in option database. */
    const char *dbClass;	/* Class for option in database. */
    const char *defValue;	/* Default value for option if not specified
				 * in command line, the option database, or
				 * the system. */
#if TCL_MAJOR_VERSION > 8
    int objOffset;		/* Where in record to store a Tcl_Obj * that
    size_t objOffset;		/* Where in record to store a Tcl_Obj * that
				 * holds the value of this option, specified
				 * as an offset in bytes from the start of the
				 * record. Use the Tk_Offset macro to generate
				 * values for this. -1 means don't store the
				 * Tcl_Obj in the record. */
    int internalOffset;		/* Where in record to store the internal
				 * record. Use the offsetof macro to generate
				 * values for this. TCL_INDEX_NONE means don't
				 * store the Tcl_Obj in the record. */
    size_t internalOffset;		/* Where in record to store the internal
				 * representation of the value of this option,
				 * such as an int or XColor *. This field is
				 * specified as an offset in bytes from the
				 * start of the record. Use the Tk_Offset
				 * macro to generate values for it. -1 means
				 * don't store the internal representation in
				 * the record. */
				 * start of the record. Use the offsetof
				 * macro to generate values for it.
				 * TCL_INDEX_NONE means don't store the
				 * internal representation in the record. */
#else
    int objOffset;
    int internalOffset;
#endif
    int flags;			/* Any combination of the values defined
				 * below. */
    const void *clientData;	/* An alternate place to put option-specific
				 * data. Used for the monochrome default value
				 * for colors, etc. */
    int typeMask;		/* An arbitrary bit mask defined by the class
				 * manager; typically bits correspond to
229
230
231
232
233
234
235







236
237
238
239
240

241
242
243
244
245
246
247
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261







+
+
+
+
+
+
+





+








/*
 * The following structure and function types are used by TK_OPTION_CUSTOM
 * options; the structure holds pointers to the functions needed by the Tk
 * option config code to handle a custom option.
 */

#if TCL_MAJOR_VERSION > 8
typedef int (Tk_CustomOptionSetProc) (ClientData clientData,
	Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj **value, char *widgRec,
	size_t offset, char *saveInternalPtr, int flags);
typedef Tcl_Obj *(Tk_CustomOptionGetProc) (ClientData clientData,
	Tk_Window tkwin, char *widgRec, size_t offset);
#else
typedef int (Tk_CustomOptionSetProc) (ClientData clientData,
	Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj **value, char *widgRec,
	int offset, char *saveInternalPtr, int flags);
typedef Tcl_Obj *(Tk_CustomOptionGetProc) (ClientData clientData,
	Tk_Window tkwin, char *widgRec, int offset);
#endif
typedef void (Tk_CustomOptionRestoreProc) (ClientData clientData,
	Tk_Window tkwin, char *internalPtr, char *saveInternalPtr);
typedef void (Tk_CustomOptionFreeProc) (ClientData clientData, Tk_Window tkwin,
	char *internalPtr);

typedef struct Tk_ObjCustomOption {
    const char *name;		/* Name of the custom option. */
263
264
265
266
267
268
269

270


271
272
273
274
275
276
277
277
278
279
280
281
282
283
284

285
286
287
288
289
290
291
292
293







+
-
+
+







} Tk_ObjCustomOption;

/*
 * Macro to use to fill in "offset" fields of the Tk_OptionSpec structure.
 * Computes number of bytes from beginning of structure to a given field.
 */

#ifndef TK_NO_DEPRECATED
#define Tk_Offset(type, field) ((int) offsetof(type, field))
#   define Tk_Offset(type, field) ((int) offsetof(type, field))
#endif
/* Workaround for platforms missing offsetof(), e.g. VC++ 6.0 */
#ifndef offsetof
#   define offsetof(type, field) ((size_t) ((char *) &((type *) 0)->field))
#endif

/*
 * The following two structures are used for error handling. When config
287
288
289
290
291
292
293
294

295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310

311
312
313

314




315
316
317
318
319
320
321
303
304
305
306
307
308
309

310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325

326
327
328
329
330

331
332
333
334
335
336
337
338
339
340
341







-
+















-
+



+
-
+
+
+
+







				 * option. */
    Tcl_Obj *valuePtr;		/* The old value of the option, in the form of
				 * a Tcl object; may be NULL if the value was
				 * not saved as an object. */
    double internalForm;	/* The old value of the option, in some
				 * internal representation such as an int or
				 * (XColor *). Valid only if the field
				 * optionPtr->specPtr->objOffset is < 0. The
				 * optionPtr->specPtr->objOffset is -1. The
				 * space must be large enough to accommodate a
				 * double, a long, or a pointer; right now it
				 * looks like a double (i.e., 8 bytes) is big
				 * enough. Also, using a double guarantees
				 * that the field is properly aligned for
				 * storing large values. */
} Tk_SavedOption;

#ifdef TCL_MEM_DEBUG
#   define TK_NUM_SAVED_OPTIONS 2
#else
#   define TK_NUM_SAVED_OPTIONS 20
#endif

typedef struct Tk_SavedOptions {
    char *recordPtr;		/* The data structure in which to restore
    void *recordPtr;		/* The data structure in which to restore
				 * configuration options. */
    Tk_Window tkwin;		/* Window associated with recordPtr; needed to
				 * restore certain options. */
#if TCL_MAJOR_VERSION > 8
    int numItems;		/* The number of valid items in items field. */
    size_t numItems;		/* The number of valid items in items field. */
#else
    int numItems;
#endif
    Tk_SavedOption items[TK_NUM_SAVED_OPTIONS];
				/* Items used to hold old values. */
    struct Tk_SavedOptions *nextPtr;
				/* Points to next structure in list; needed if
				 * too many options changed to hold all the
				 * old values in a single structure. NULL
				 * means no more structures. */
331
332
333
334
335
336
337

338





339
340


341

342
343
344
345
346
347
348
351
352
353
354
355
356
357
358
359
360
361
362
363
364


365
366
367
368
369
370
371
372
373
374
375







+

+
+
+
+
+
-
-
+
+

+







/*
 * This is a temporary flag used while tkObjConfig and new widgets are in
 * development.
 */

#ifndef __NO_OLD_CONFIG

#if TCL_MAJOR_VERSION > 8
typedef int (Tk_OptionParseProc) (ClientData clientData, Tcl_Interp *interp,
	Tk_Window tkwin, const char *value, char *widgRec, size_t offset);
typedef const char *(Tk_OptionPrintProc) (ClientData clientData,
	Tk_Window tkwin, char *widgRec, size_t offset, Tcl_FreeProc **freeProcPtr);
#else
typedef int (Tk_OptionParseProc) (ClientData clientData, Tcl_Interp *interp,
	Tk_Window tkwin, CONST84 char *value, char *widgRec, int offset);
typedef CONST86 char *(Tk_OptionPrintProc) (ClientData clientData,
	Tk_Window tkwin, const char *value, char *widgRec, int offset);
typedef const char *(Tk_OptionPrintProc) (ClientData clientData,
	Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr);
#endif

typedef struct Tk_CustomOption {
    Tk_OptionParseProc *parseProc;
				/* Procedure to call to parse an option and
				 * store it in converted form. */
    Tk_OptionPrintProc *printProc;
				/* Procedure to return a printable string
359
360
361
362
363
364
365
366

367
368
369
370
371

372
373


374



375
376
377
378

379
380
381
382
383
384
385
386
387
388
389
390
391
392

393
394
395
396
397
398
399


400
401
402
403
404
405
406
407
408

409
410
411
412
413
414
415
416







-
+





+
-
-
+
+

+
+
+



-
+







 * database, etc.
 */

typedef struct Tk_ConfigSpec {
    int type;			/* Type of option, such as TK_CONFIG_COLOR;
				 * see definitions below. Last option in table
				 * must have type TK_CONFIG_END. */
    CONST86 char *argvName;	/* Switch used to specify option in argv. NULL
    const char *argvName;	/* Switch used to specify option in argv. NULL
				 * means this spec is part of a group. */
    Tk_Uid dbName;		/* Name for option in option database. */
    Tk_Uid dbClass;		/* Class for option in database. */
    Tk_Uid defValue;		/* Default value for option if not specified
				 * in command line or database. */
#if TCL_MAJOR_VERSION > 8
    int offset;			/* Where in widget record to store value; use
				 * Tk_Offset macro to generate values for
    size_t offset;			/* Where in widget record to store value; use
				 * offsetof macro to generate values for
				 * this. */
#else
    int offset;
#endif
    int specFlags;		/* Any combination of the values defined
				 * below; other bits are used internally by
				 * tkConfig.c. */
    CONST86 Tk_CustomOption *customPtr;
    const Tk_CustomOption *customPtr;
				/* If type is TK_CONFIG_CUSTOM then this is a
				 * pointer to info about how to parse and
				 * print the option. Otherwise it is
				 * irrelevant. */
} Tk_ConfigSpec;

/*
411
412
413
414
415
416
417

418


419
420
421
422
423
424
425
426
427

428
429
430

431
432

433
434

435
436
437
438
439
440
441
442
443
444
445
446
447
448
449

450
451
452
453
454
455
456
457
458
459

460
461
462

463
464

465
466

467
468
469
470
471
472
473
474







+
-
+
+








-
+


-
+

-
+

-
+







 * (internal-use-only flags are defined there).
 */

#define TK_CONFIG_NULL_OK		(1 << 0)
#define TK_CONFIG_COLOR_ONLY		(1 << 1)
#define TK_CONFIG_MONO_ONLY		(1 << 2)
#define TK_CONFIG_DONT_SET_DEFAULT	(1 << 3)
#ifndef TK_NO_DEPRECATED
#define TK_CONFIG_OPTION_SPECIFIED      (1 << 4)
#  define TK_CONFIG_OPTION_SPECIFIED      (1 << 4)
#endif /* !TK_NO_DEPRECATED */
#define TK_CONFIG_USER_BIT		0x100
#endif /* __NO_OLD_CONFIG */

/*
 * Structure used to specify how to handle argv options.
 */

typedef struct {
    CONST86 char *key;		/* The key string that flags the option in the
    const char *key;		/* The key string that flags the option in the
				 * argv array. */
    int type;			/* Indicates option type; see below. */
    char *src;			/* Value to be used in setting dst; usage
    void *src;			/* Value to be used in setting dst; usage
				 * depends on type. */
    char *dst;			/* Address of value to be modified; usage
    void *dst;			/* Address of value to be modified; usage
				 * depends on type. */
    CONST86 char *help;		/* Documentation message describing this
    const char *help;		/* Documentation message describing this
				 * option. */
} Tk_ArgvInfo;

/*
 * Legal values for the type field of a Tk_ArgvInfo: see the user
 * documentation for details.
 */
572
573
574
575
576
577
578



579

580
581
582
583
584
585
586
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623







+
+
+

+








typedef Window (Tk_ClassCreateProc) (Tk_Window tkwin, Window parent,
	ClientData instanceData);
typedef void (Tk_ClassWorldChangedProc) (ClientData instanceData);
typedef void (Tk_ClassModalProc) (Tk_Window tkwin, XEvent *eventPtr);

typedef struct Tk_ClassProcs {
#if TCL_MAJOR_VERSION > 8
    size_t size;
#else
    unsigned int size;
#endif
    Tk_ClassWorldChangedProc *worldChangedProc;
				/* Procedure to invoke when the widget needs
				 * to respond in some way to a change in the
				 * world (font changes, etc.) */
    Tk_ClassCreateProc *createProc;
				/* Procedure to invoke when the platform-
				 * dependent window needs to be created. */
597
598
599
600
601
602
603
604

605
606
607
608
609

610
611
612
613
614
615
616

617
618

619
620
621
622
623
624
625

626
627
628


629
630
631

632
633
634
635
636
637
638
634
635
636
637
638
639
640

641
642
643
644
645

646
647
648
649
650
651
652
653
654
655

656
657
658
659
660
661
662

663
664


665
666
667
668

669
670
671
672
673
674
675
676







-
+




-
+







+

-
+






-
+

-
-
+
+


-
+







 * (or NULL if the structure is NULL).
 *
 * A more general version of this function may be useful if other
 * size-versioned structure pop up in the future:
 *
 *	#define Tk_GetField(name, who, which) \
 *	    (((who) == NULL) ? NULL :
 *	    (((who)->size <= Tk_Offset(name, which)) ? NULL :(name)->which))
 *	    (((who)->size <= offsetof(name, which)) ? NULL :(name)->which))
 */

#define Tk_GetClassProc(procs, which) \
    (((procs) == NULL) ? NULL : \
    (((procs)->size <= Tk_Offset(Tk_ClassProcs, which)) ? NULL:(procs)->which))
    (((procs)->size <= offsetof(Tk_ClassProcs, which)) ? NULL:(procs)->which))

/*
 * Each geometry manager (the packer, the placer, etc.) is represented by a
 * structure of the following form, which indicates procedures to invoke in
 * the geometry manager to carry out certain functions.
 */

#define Tk_GeomLostSlaveProc Tk_GeomLostContentProc
typedef void (Tk_GeomRequestProc) (ClientData clientData, Tk_Window tkwin);
typedef void (Tk_GeomLostSlaveProc) (ClientData clientData, Tk_Window tkwin);
typedef void (Tk_GeomLostContentProc) (ClientData clientData, Tk_Window tkwin);

typedef struct Tk_GeomMgr {
    const char *name;		/* Name of the geometry manager (command used
				 * to invoke it, or name of widget class that
				 * allows embedded widgets). */
    Tk_GeomRequestProc *requestProc;
				/* Procedure to invoke when a slave's
				/* Procedure to invoke when a content's
				 * requested geometry changes. */
    Tk_GeomLostSlaveProc *lostSlaveProc;
				/* Procedure to invoke when a slave is taken
    Tk_GeomLostContentProc *lostContentProc;
				/* Procedure to invoke when content is taken
				 * away from one geometry manager by another.
				 * NULL means geometry manager doesn't care
				 * when slaves are lost. */
				 * when content lost. */
} Tk_GeomMgr;

/*
 * Result values returned by Tk_GetScrollInfo:
 */

#define TK_SCROLL_MOVETO	1
743
744
745
746
747
748
749
750

751
752

753
754
755
756
757
758
759
781
782
783
784
785
786
787

788
789
790
791
792
793
794
795
796
797
798







-
+


+







    (((Tk_FakeWin *) (tkwin))->flags & TK_WIN_MANAGED)
#define Tk_TopWinHierarchy(tkwin) \
    (((Tk_FakeWin *) (tkwin))->flags & TK_TOP_HIERARCHY)
#define Tk_IsManageable(tkwin) \
    (((Tk_FakeWin *) (tkwin))->flags & TK_WM_MANAGEABLE)
#define Tk_ReqWidth(tkwin)	(((Tk_FakeWin *) (tkwin))->reqWidth)
#define Tk_ReqHeight(tkwin)	(((Tk_FakeWin *) (tkwin))->reqHeight)
/* Tk_InternalBorderWidth is deprecated */
#ifndef TK_NO_DEPRECATED
#define Tk_InternalBorderWidth(tkwin) \
    (((Tk_FakeWin *) (tkwin))->internalBorderLeft)
#endif /* !TK_NO_DEPRECATED */
#define Tk_InternalBorderLeft(tkwin) \
    (((Tk_FakeWin *) (tkwin))->internalBorderLeft)
#define Tk_InternalBorderRight(tkwin) \
    (((Tk_FakeWin *) (tkwin))->internalBorderRight)
#define Tk_InternalBorderTop(tkwin) \
    (((Tk_FakeWin *) (tkwin))->internalBorderTop)
#define Tk_InternalBorderBottom(tkwin) \
790
791
792
793
794
795
796
797

798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817

818
819
820
821




822
823
824
825
826
827
828
829
830
831
832
833
834
835

836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855

856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871







-
+



















-
+




+
+
+
+







    Tk_Uid classUid;
    XWindowChanges changes;
    unsigned int dummy6;	/* dirtyChanges */
    XSetWindowAttributes atts;
    unsigned long dummy7;	/* dirtyAtts */
    unsigned int flags;
    char *dummy8;		/* handlerList */
#ifdef TK_USE_INPUT_METHODS
#if defined(TK_USE_INPUT_METHODS) || (TCL_MAJOR_VERSION > 8)
    XIC dummy9;			/* inputContext */
#endif /* TK_USE_INPUT_METHODS */
    ClientData *dummy10;	/* tagPtr */
    int dummy11;		/* numTags */
    int dummy12;		/* optionLevel */
    char *dummy13;		/* selHandlerList */
    char *dummy14;		/* geomMgrPtr */
    ClientData dummy15;		/* geomData */
    int reqWidth, reqHeight;
    int internalBorderLeft;
    char *dummy16;		/* wmInfoPtr */
    char *dummy17;		/* classProcPtr */
    ClientData dummy18;		/* instanceData */
    char *dummy19;		/* privatePtr */
    int internalBorderRight;
    int internalBorderTop;
    int internalBorderBottom;
    int minReqWidth;
    int minReqHeight;
#ifdef TK_USE_INPUT_METHODS
#if defined(TK_USE_INPUT_METHODS) || (TCL_MAJOR_VERSION > 8)
    int dummy20;
#endif /* TK_USE_INPUT_METHODS */
    char *dummy21;		/* geomMgrName */
    Tk_Window dummy22;		/* maintainerPtr */
#if !defined(TK_USE_INPUT_METHODS) && (TCL_MAJOR_VERSION < 9)
    XIC dummy9;			/* inputContext */
    int dummy20;
#endif /* TK_USE_INPUT_METHODS */
} Tk_FakeWin;

/*
 * Flag values for TkWindow (and Tk_FakeWin) structures are:
 *
 * TK_MAPPED:			1 means window is currently mapped,
 *				0 means unmapped.
880
881
882
883
884
885
886




887
888
889
890
891
892
893
894
895
896
897
898
899

900
901
902
903
904
905
906
907

908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923

924
925
926
927
928
929
930
931
932
933
934
935
936
937
938

939

940



941
942
943
944
945
946
947
948

949

950
951

952



953
954
955
956
957
958
959
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971

972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988

989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002

1003
1004

1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016







+
+
+
+













+








+















-
+















+
-
+

+
+
+








+
-
+

-
+

+
+
+







 *				window's parent either doesn't exist or is not
 *				owned by this Tk application.
 * TK_PROP_PROPCHANGE		1 means that PropertyNotify events in the
 *				window's children should propagate up to this
 *				window.
 * TK_WM_MANAGEABLE		1 marks a window as capable of being converted
 *				into a toplevel using [wm manage].
 * TK_CAN_INPUT_TEXT            1 means that this window accepts text input.
 *                              Used on macOS to indicate that key events can be
 *                              processed with the NSTextInputClient protocol.
 *                              Not currently accessible through the public API.
 */

#define TK_MAPPED		1
#define TK_TOP_LEVEL		2
#define TK_ALREADY_DEAD		4
#define TK_NEED_CONFIG_NOTIFY	8
#define TK_GRAB_FLAG		0x10
#define TK_CHECKED_IC		0x20
#define TK_DONT_DESTROY_WINDOW	0x40
#define TK_WM_COLORMAP_WINDOW	0x80
#define TK_EMBEDDED		0x100
#define TK_CONTAINER		0x200
#define TK_BOTH_HALVES		0x400

#define TK_WRAPPER		0x1000
#define TK_REPARENTED		0x2000
#define TK_ANONYMOUS_WINDOW	0x4000
#define TK_HAS_WRAPPER		0x8000
#define TK_WIN_MANAGED		0x10000
#define TK_TOP_HIERARCHY	0x20000
#define TK_PROP_PROPCHANGE	0x40000
#define TK_WM_MANAGEABLE	0x80000
#define TK_CAN_INPUT_TEXT       0x100000

/*
 *----------------------------------------------------------------------
 *
 * Procedure prototypes and structures used for defining new canvas items:
 *
 *----------------------------------------------------------------------
 */

typedef enum {
    TK_STATE_NULL = -1, TK_STATE_ACTIVE, TK_STATE_DISABLED,
    TK_STATE_NORMAL, TK_STATE_HIDDEN
} Tk_State;

typedef struct Tk_SmoothMethod {
    CONST86 char *name;
    const char *name;
    int (*coordProc) (Tk_Canvas canvas, double *pointPtr, int numPoints,
	    int numSteps, XPoint xPoints[], double dblPoints[]);
    void (*postscriptProc) (Tcl_Interp *interp, Tk_Canvas canvas,
	    double *coordPtr, int numPoints, int numSteps);
} Tk_SmoothMethod;

/*
 * For each item in a canvas widget there exists one record with the following
 * structure. Each actual item is represented by a record with the following
 * stuff at its beginning, plus additional type-specific stuff after that.
 */

#define TK_TAG_SPACE 3

typedef struct Tk_Item {
#if TCL_MAJOR_VERSION > 8
    int id;			/* Unique identifier for this item (also
    size_t id;		/* Unique identifier for this item (also
				 * serves as first tag for item). */
#else
    int id;
#endif
    struct Tk_Item *nextPtr;	/* Next in display list of all items in this
				 * canvas. Later items in list are drawn on
				 * top of earlier ones. */
    Tk_Uid staticTagSpace[TK_TAG_SPACE];
				/* Built-in space for limited # of tags. */
    Tk_Uid *tagPtr;		/* Pointer to array of tags. Usually points to
				 * staticTagSpace, but may point to malloc-ed
				 * space if there are lots of tags. */
#if TCL_MAJOR_VERSION > 8
    int tagSpace;		/* Total amount of tag space available at
    size_t tagSpace;		/* Total amount of tag space available at
				 * tagPtr. */
    int numTags;		/* Number of tag slots actually used at
    size_t numTags;		/* Number of tag slots actually used at
				 * *tagPtr. */
#else
    int tagSpace, numTags;
#endif
    struct Tk_ItemType *typePtr;/* Table of procedures that implement this
				 * type of item. */
    int x1, y1, x2, y2;		/* Bounding box for item, in integer canvas
				 * units. Set by item-specific code and
				 * guaranteed to contain every pixel drawn in
				 * item. Item area includes x1 and y1 but not
				 * x2 and y2. */
988
989
990
991
992
993
994
995

996
997
998
999
1000
1001




1002
1003
1004
1005
1006
1007
1008
1009











1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021


1022
1023
1024
1025
1026
1027
1028
1029







1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046

1047
1048
1049
1050
1051

1052

1053

1054



1055
1056
1057
1058

1059
1060
1061
1062
1063
1064
1065
1045
1046
1047
1048
1049
1050
1051

1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100



1101
1102
1103
1104
1105
1106
1107
1108



1109
1110
1111
1112







1113
1114
1115
1116
1117
1118
1119

1120
1121
1122

1123
1124
1125
1126
1127
1128
1129
1130

1131
1132
1133
1134
1135
1136
1137
1138







-
+






+
+
+
+








+
+
+
+
+
+
+
+
+
+
+












+
+





-
-
-
+
+
+
+
+
+
+

-
-
-




-
-
-
-
-
-
-


+




-
+

+
-
+

+
+
+



-
+







#define TK_ITEM_DONT_REDRAW		2

/*
 * Records of the following type are used to describe a type of item (e.g.
 * lines, circles, etc.) that can form part of a canvas widget.
 */

#ifdef USE_OLD_CANVAS
#if defined(USE_OLD_CANVAS) && TCL_MAJOR_VERSION < 9
typedef int	(Tk_ItemCreateProc)(Tcl_Interp *interp, Tk_Canvas canvas,
		    Tk_Item *itemPtr, int argc, char **argv);
typedef int	(Tk_ItemConfigureProc)(Tcl_Interp *interp, Tk_Canvas canvas,
		    Tk_Item *itemPtr, int argc, char **argv, int flags);
typedef int	(Tk_ItemCoordProc)(Tcl_Interp *interp, Tk_Canvas canvas,
		    Tk_Item *itemPtr, int argc, char **argv);
typedef void	(Tk_ItemInsertProc)(Tk_Canvas canvas, Tk_Item *itemPtr,
		    int beforeThis, char *string);
typedef int	(Tk_ItemIndexProc)(Tcl_Interp *interp, Tk_Canvas canvas,
		    Tk_Item *itemPtr, char *indexString, int *indexPtr);
#else
typedef int	(Tk_ItemCreateProc)(Tcl_Interp *interp, Tk_Canvas canvas,
		    Tk_Item *itemPtr, int argc, Tcl_Obj *const objv[]);
typedef int	(Tk_ItemConfigureProc)(Tcl_Interp *interp, Tk_Canvas canvas,
		    Tk_Item *itemPtr, int argc, Tcl_Obj *const objv[],
		    int flags);
typedef int	(Tk_ItemCoordProc)(Tcl_Interp *interp, Tk_Canvas canvas,
		    Tk_Item *itemPtr, int argc, Tcl_Obj *const argv[]);
#if TCL_MAJOR_VERSION > 8
typedef void	(Tk_ItemInsertProc)(Tk_Canvas canvas, Tk_Item *itemPtr,
		    size_t beforeThis, Tcl_Obj *string);
typedef int	(Tk_ItemIndexProc)(Tcl_Interp *interp, Tk_Canvas canvas,
		    Tk_Item *itemPtr, Tcl_Obj *indexString, size_t *indexPtr);
#else
typedef void	(Tk_ItemInsertProc)(Tk_Canvas canvas, Tk_Item *itemPtr,
		    int beforeThis, Tcl_Obj *string);
typedef int	(Tk_ItemIndexProc)(Tcl_Interp *interp, Tk_Canvas canvas,
		    Tk_Item *itemPtr, Tcl_Obj *indexString, int *indexPtr);
#endif
#endif /* USE_OLD_CANVAS */
typedef void	(Tk_ItemDeleteProc)(Tk_Canvas canvas, Tk_Item *itemPtr,
		    Display *display);
typedef void	(Tk_ItemDisplayProc)(Tk_Canvas canvas, Tk_Item *itemPtr,
		    Display *display, Drawable dst, int x, int y, int width,
		    int height);
typedef double	(Tk_ItemPointProc)(Tk_Canvas canvas, Tk_Item *itemPtr,
		    double *pointPtr);
typedef int	(Tk_ItemAreaProc)(Tk_Canvas canvas, Tk_Item *itemPtr,
		    double *rectPtr);
typedef int	(Tk_ItemPostscriptProc)(Tcl_Interp *interp, Tk_Canvas canvas,
		    Tk_Item *itemPtr, int prepass);
typedef void	(Tk_ItemRotateProc)(Tk_Canvas canvas, Tk_Item *itemPtr,
		    double originX, double originY, double angleRadians);
typedef void	(Tk_ItemScaleProc)(Tk_Canvas canvas, Tk_Item *itemPtr,
		    double originX, double originY, double scaleX,
		    double scaleY);
typedef void	(Tk_ItemTranslateProc)(Tk_Canvas canvas, Tk_Item *itemPtr,
		    double deltaX, double deltaY);
#ifdef USE_OLD_CANVAS
typedef int	(Tk_ItemIndexProc)(Tcl_Interp *interp, Tk_Canvas canvas,
		    Tk_Item *itemPtr, char *indexString, int *indexPtr);
#if TCL_MAJOR_VERSION > 8
typedef void	(Tk_ItemCursorProc)(Tk_Canvas canvas, Tk_Item *itemPtr,
		    size_t index);
typedef size_t	(Tk_ItemSelectionProc)(Tk_Canvas canvas, Tk_Item *itemPtr,
		    size_t offset, char *buffer, size_t maxBytes);
typedef void	(Tk_ItemDCharsProc)(Tk_Canvas canvas, Tk_Item *itemPtr,
		    size_t first, size_t last);
#else
typedef int	(Tk_ItemIndexProc)(Tcl_Interp *interp, Tk_Canvas canvas,
		    Tk_Item *itemPtr, Tcl_Obj *indexString, int *indexPtr);
#endif /* USE_OLD_CANVAS */
typedef void	(Tk_ItemCursorProc)(Tk_Canvas canvas, Tk_Item *itemPtr,
		    int index);
typedef int	(Tk_ItemSelectionProc)(Tk_Canvas canvas, Tk_Item *itemPtr,
		    int offset, char *buffer, int maxBytes);
#ifdef USE_OLD_CANVAS
typedef void	(Tk_ItemInsertProc)(Tk_Canvas canvas, Tk_Item *itemPtr,
		    int beforeThis, char *string);
#else
typedef void	(Tk_ItemInsertProc)(Tk_Canvas canvas, Tk_Item *itemPtr,
		    int beforeThis, Tcl_Obj *string);
#endif /* USE_OLD_CANVAS */
typedef void	(Tk_ItemDCharsProc)(Tk_Canvas canvas, Tk_Item *itemPtr,
		    int first, int last);
#endif

#ifndef __NO_OLD_CONFIG

typedef struct Tk_ItemType {
    CONST86 char *name;		/* The name of this type of item, such as
    const char *name;		/* The name of this type of item, such as
				 * "line". */
#if TCL_MAJOR_VERSION > 8
    int itemSize;		/* Total amount of space needed for item's
    size_t itemSize;		/* Total amount of space needed for item's
				 * record. */
#else
    int itemSize;
#endif
    Tk_ItemCreateProc *createProc;
				/* Procedure to create a new item of this
				 * type. */
    CONST86 Tk_ConfigSpec *configSpecs; /* Pointer to array of configuration specs for
    const Tk_ConfigSpec *configSpecs; /* Pointer to array of configuration specs for
				 * this type. Used for returning configuration
				 * info. */
    Tk_ItemConfigureProc *configProc;
				/* Procedure to call to change configuration
				 * options. */
    Tk_ItemCoordProc *coordProc;/* Procedure to call to get and set the item's
				 * coordinates. */
1094
1095
1096
1097
1098
1099
1100


1101

1102
1103
1104
1105
1106
1107
1108
1167
1168
1169
1170
1171
1172
1173
1174
1175

1176
1177
1178
1179
1180
1181
1182
1183







+
+
-
+







    Tk_ItemInsertProc *insertProc;
				/* Procedure to insert something into an
				 * item. */
    Tk_ItemDCharsProc *dCharsProc;
				/* Procedure to delete characters from an
				 * item. */
    struct Tk_ItemType *nextPtr;/* Used to link types together into a list. */
    Tk_ItemRotateProc *rotateProc;
				/* Procedure to rotate an item's coordinates
    char *reserved1;		/* Reserved for future extension. */
				 * about a point. */
    int reserved2;		/* Carefully compatible with */
    char *reserved3;		/* Jan Nijtmans dash patch */
    char *reserved4;
} Tk_ItemType;

/*
 * Flag (used in the alwaysRedraw field) to say whether an item supports
1127
1128
1129
1130
1131
1132
1133

1134

1135
1136

1137



1138
1139
1140

1141

1142
1143
1144



1145
1146
1147
1148
1149
1150
1151
1202
1203
1204
1205
1206
1207
1208
1209

1210
1211

1212
1213
1214
1215
1216
1217
1218
1219
1220

1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234







+
-
+

-
+

+
+
+



+
-
+



+
+
+







    int selBorderWidth;		/* Width of border around selection. Read-only
				 * to items. */
    XColor *selFgColorPtr;	/* Foreground color for selected text.
				 * Read-only to items. */
    Tk_Item *selItemPtr;	/* Pointer to selected item. NULL means
				 * selection isn't in this canvas. Writable by
				 * items. */
#if TCL_MAJOR_VERSION > 8
    int selectFirst;		/* Character index of first selected
    size_t selectFirst;		/* Character index of first selected
				 * character. Writable by items. */
    int selectLast;		/* Character index of last selected character.
    size_t selectLast;		/* Character index of last selected character.
				 * Writable by items. */
#else
    int selectFirst, selectLast;
#endif
    Tk_Item *anchorItemPtr;	/* Item corresponding to "selectAnchor": not
				 * necessarily selItemPtr. Read-only to
				 * items. */
#if TCL_MAJOR_VERSION > 8
    int selectAnchor;		/* Character index of fixed end of selection
    size_t selectAnchor;		/* Character index of fixed end of selection
				 * (i.e. "select to" operation will use this
				 * as one end of the selection). Writable by
				 * items. */
#else
    int selectAnchor;
#endif
    Tk_3DBorder insertBorder;	/* Used to draw vertical bar for insertion
				 * cursor. Read-only to items. */
    int insertWidth;		/* Total width of insertion cursor. Read-only
				 * to items. */
    int insertBorderWidth;	/* Width of 3-D border around insert cursor.
				 * Read-only to items. */
    Tk_Item *focusItemPtr;	/* Item that currently has the input focus, or
1216
1217
1218
1219
1220
1221
1222
1223

1224
1225
1226


1227
1228
1229
1230



1231
1232
1233


1234
1235
1236
1237


1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253

1254
1255
1256
1257
1258
1259
1260
1299
1300
1301
1302
1303
1304
1305

1306
1307


1308
1309
1310



1311
1312
1313
1314


1315
1316
1317
1318


1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335

1336
1337
1338
1339
1340
1341
1342
1343







-
+

-
-
+
+

-
-
-
+
+
+

-
-
+
+


-
-
+
+















-
+







 *
 * Procedure prototypes and structures used for managing images:
 *
 *----------------------------------------------------------------------
 */

typedef struct Tk_ImageType Tk_ImageType;
#ifdef USE_OLD_IMAGE
#if !defined(TK_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9 && defined(USE_OLD_IMAGE)
typedef int (Tk_ImageCreateProc) (Tcl_Interp *interp, char *name, int argc,
	char **argv, Tk_ImageType *typePtr, Tk_ImageMaster master,
	ClientData *masterDataPtr);
	char **argv, Tk_ImageType *typePtr, Tk_ImageModel model,
	ClientData *clientDataPtr);
#else
typedef int (Tk_ImageCreateProc) (Tcl_Interp *interp, CONST86 char *name, int objc,
	Tcl_Obj *const objv[], CONST86 Tk_ImageType *typePtr, Tk_ImageMaster master,
	ClientData *masterDataPtr);
typedef int (Tk_ImageCreateProc) (Tcl_Interp *interp, const char *name, int objc,
	Tcl_Obj *const objv[], const Tk_ImageType *typePtr, Tk_ImageModel model,
	ClientData *clientDataPtr);
#endif /* USE_OLD_IMAGE */
typedef ClientData (Tk_ImageGetProc) (Tk_Window tkwin, ClientData masterData);
typedef void (Tk_ImageDisplayProc) (ClientData instanceData, Display *display,
typedef ClientData (Tk_ImageGetProc) (Tk_Window tkwin, ClientData clientData);
typedef void (Tk_ImageDisplayProc) (ClientData clientData, Display *display,
	Drawable drawable, int imageX, int imageY, int width, int height,
	int drawableX, int drawableY);
typedef void (Tk_ImageFreeProc) (ClientData instanceData, Display *display);
typedef void (Tk_ImageDeleteProc) (ClientData masterData);
typedef void (Tk_ImageFreeProc) (ClientData clientData, Display *display);
typedef void (Tk_ImageDeleteProc) (ClientData clientData);
typedef void (Tk_ImageChangedProc) (ClientData clientData, int x, int y,
	int width, int height, int imageWidth, int imageHeight);
typedef int (Tk_ImagePostscriptProc) (ClientData clientData,
	Tcl_Interp *interp, Tk_Window tkwin, Tk_PostscriptInfo psinfo,
	int x, int y, int width, int height, int prepass);

/*
 * The following structure represents a particular type of image (bitmap, xpm
 * image, etc.). It provides information common to all images of that type,
 * such as the type name and a collection of procedures in the image manager
 * that respond to various events. Each image manager is represented by one of
 * these structures.
 */

struct Tk_ImageType {
    CONST86 char *name;		/* Name of image type. */
    const char *name;		/* Name of image type. */
    Tk_ImageCreateProc *createProc;
				/* Procedure to call to create a new image of
				 * this type. */
    Tk_ImageGetProc *getProc;	/* Procedure to call the first time
				 * Tk_GetImage is called in a new way (new
				 * visual or screen). */
    Tk_ImageDisplayProc *displayProc;
1358
1359
1360
1361
1362
1363
1364
1365

1366
1367
1368
1369
1370
1371
1372
1441
1442
1443
1444
1445
1446
1447

1448
1449
1450
1451
1452
1453
1454
1455







-
+







/*
 * 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.
 */

struct Tk_PhotoImageFormat {
    CONST86 char *name;		/* Name of image file format */
    const char *name;		/* Name of image file format */
    Tk_ImageFileMatchProc *fileMatchProc;
				/* Procedure to call to determine whether an
				 * image file matches this format. */
    Tk_ImageStringMatchProc *stringMatchProc;
				/* Procedure to call to determine whether the
				 * data in a string matches this format. */
    Tk_ImageFileReadProc *fileReadProc;
1462
1463
1464
1465
1466
1467
1468

1469
1470
1471
1472
1473
1474
1475
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559







+







 * The definitions below provide backward compatibility for functions and
 * types related to event handling that used to be in Tk but have moved to
 * Tcl.
 *
 *----------------------------------------------------------------------
 */

#if !defined(TK_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9
#define TK_READABLE		TCL_READABLE
#define TK_WRITABLE		TCL_WRITABLE
#define TK_EXCEPTION		TCL_EXCEPTION

#define TK_DONT_WAIT		TCL_DONT_WAIT
#define TK_X_EVENTS		TCL_WINDOW_EVENTS
#define TK_WINDOW_EVENTS	TCL_WINDOW_EVENTS
1495
1496
1497
1498
1499
1500
1501

1502
1503
1504
1505
1506
1507
1508
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593







+








/* Additional stuff that has moved to Tcl: */

#define Tk_EventuallyFree	Tcl_EventuallyFree
#define Tk_FreeProc		Tcl_FreeProc
#define Tk_Preserve		Tcl_Preserve
#define Tk_Release		Tcl_Release
#endif

/* Removed Tk_Main, use macro instead */
#if defined(_WIN32) || defined(__CYGWIN__)
#define Tk_Main(argc, argv, proc) Tk_MainEx(argc, argv, proc, \
	(Tcl_FindExecutable(0), (Tcl_CreateInterp)()))
#else
#define Tk_Main(argc, argv, proc) Tk_MainEx(argc, argv, proc, \
1529
1530
1531
1532
1533
1534
1535
1536

1537
1538
1539




1540
1541

1542
1543
1544
1545
1546
1547
1548
1614
1615
1616
1617
1618
1619
1620

1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638







-
+



+
+
+
+


+







 */

typedef int (Tk_ErrorProc) (ClientData clientData, XErrorEvent *errEventPtr);
typedef void (Tk_EventProc) (ClientData clientData, XEvent *eventPtr);
typedef int (Tk_GenericProc) (ClientData clientData, XEvent *eventPtr);
typedef int (Tk_ClientMessageProc) (Tk_Window tkwin, XEvent *eventPtr);
typedef int (Tk_GetSelProc) (ClientData clientData, Tcl_Interp *interp,
	CONST86 char *portion);
	const char *portion);
typedef void (Tk_LostSelProc) (ClientData clientData);
typedef Tk_RestrictAction (Tk_RestrictProc) (ClientData clientData,
	XEvent *eventPtr);
#if TCL_MAJOR_VERSION > 8
typedef size_t (Tk_SelectionProc) (ClientData clientData, size_t offset,
	char *buffer, size_t maxBytes);
#else
typedef int (Tk_SelectionProc) (ClientData clientData, int offset,
	char *buffer, int maxBytes);
#endif

/*
 *----------------------------------------------------------------------
 *
 * Platform independent exported procedures and variables.
 *
 *----------------------------------------------------------------------
1557
1558
1559
1560
1561
1562
1563
1564

1565
1566
1567
1568
1569

1570
1571
1572
1573
1574
1575
1576
1647
1648
1649
1650
1651
1652
1653

1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667







-
+





+







#define Tk_CreatePhotoImageFormat	Tk_CreateOldPhotoImageFormat
#endif /* USE_OLD_IMAGE */

/*
 *----------------------------------------------------------------------
 *
 * Allow users to say that they don't want to alter their source to add extra
 * arguments to Tk_PhotoPutBlock() et al; DO NOT DEFINE THIS WHEN BUILDING TK.
 * arguments to Tk_PhotoPutBlock() et al.
 *
 * This goes after the inclusion of the stubbed-decls so that the declarations
 * of what is actually there can be correct.
 */

#if !defined(TK_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9
#ifdef USE_COMPOSITELESS_PHOTO_PUT_BLOCK
#   ifdef Tk_PhotoPutBlock
#	undef Tk_PhotoPutBlock
#   endif
#   define Tk_PhotoPutBlock		Tk_PhotoPutBlock_NoComposite
#   ifdef Tk_PhotoPutZoomedBlock
#	undef Tk_PhotoPutZoomedBlock
1595
1596
1597
1598
1599
1600
1601

1602
1603
1604
1605
1606
1607
1608
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700







+







#   endif
#   define Tk_PhotoExpand		Tk_PhotoExpand_Panic
#   ifdef Tk_PhotoSetSize
#	undef Tk_PhotoSetSize
#   endif
#   define Tk_PhotoSetSize		Tk_PhotoSetSize_Panic
#endif /* USE_PANIC_ON_PHOTO_ALLOC_FAILURE */
#endif /* !TK_NO_DEPRECATED */

#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLIMPORT

#endif /* RC_INVOKED */

/*
Changes to generic/tk3d.c.
1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15






-
-
+
+







/*
 * 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.
 */

#include "tkInt.h"
#include "tk3d.h"
86
87
88
89
90
91
92
93

94
95
96
97
98
99
100
86
87
88
89
90
91
92

93
94
95
96
97
98
99
100







-
+







				 * background. */
{
    TkBorder *borderPtr;

    if (objPtr->typePtr != &tkBorderObjType) {
	InitBorderObj(objPtr);
    }
    borderPtr = objPtr->internalRep.twoPtrValue.ptr1;
    borderPtr = (TkBorder *)objPtr->internalRep.twoPtrValue.ptr1;

    /*
     * If the object currently points to a TkBorder, see if it's the one we
     * want. If so, increment its reference count and return.
     */

    if (borderPtr != NULL) {
123
124
125
126
127
128
129
130

131
132
133
134
135
136
137
123
124
125
126
127
128
129

130
131
132
133
134
135
136
137







-
+







     *
     * If the value is not NULL, the internal rep is the value of the color
     * the last time this object was accessed. Check the screen and colormap
     * of the last access, and if they match, we are done.
     */

    if (borderPtr != NULL) {
	TkBorder *firstBorderPtr = Tcl_GetHashValue(borderPtr->hashPtr);
	TkBorder *firstBorderPtr = (TkBorder *)Tcl_GetHashValue(borderPtr->hashPtr);

	FreeBorderObj(objPtr);
	for (borderPtr = firstBorderPtr ; borderPtr != NULL;
		borderPtr = borderPtr->nextPtr) {
	    if ((Tk_Screen(tkwin) == borderPtr->screen)
		    && (Tk_Colormap(tkwin) == borderPtr->colormap)) {
		borderPtr->resourceRefCount++;
196
197
198
199
200
201
202
203

204
205
206
207
208
209
210
196
197
198
199
200
201
202

203
204
205
206
207
208
209
210







-
+








    if (!dispPtr->borderInit) {
	BorderInit(dispPtr);
    }

    hashPtr = Tcl_CreateHashEntry(&dispPtr->borderTable, colorName, &isNew);
    if (!isNew) {
	existingBorderPtr = Tcl_GetHashValue(hashPtr);
	existingBorderPtr = (TkBorder *)Tcl_GetHashValue(hashPtr);
	for (borderPtr = existingBorderPtr; borderPtr != NULL;
		borderPtr = borderPtr->nextPtr) {
	    if ((Tk_Screen(tkwin) == borderPtr->screen)
		    && (Tk_Colormap(tkwin) == borderPtr->colormap)) {
		borderPtr->resourceRefCount++;
		return (Tk_3DBorder) borderPtr;
	    }
416
417
418
419
420
421
422
423
424

425
426
427
428

429
430
431
432
433
434
435
416
417
418
419
420
421
422


423
424
425
426

427
428
429
430
431
432
433
434







-
-
+



-
+







Tk_Free3DBorder(
    Tk_3DBorder border)		/* Token for border to be released. */
{
    TkBorder *borderPtr = (TkBorder *) border;
    Display *display = DisplayOfScreen(borderPtr->screen);
    TkBorder *prevPtr;

    borderPtr->resourceRefCount--;
    if (borderPtr->resourceRefCount > 0) {
    if (borderPtr->resourceRefCount-- > 1) {
	return;
    }

    prevPtr = Tcl_GetHashValue(borderPtr->hashPtr);
    prevPtr = (TkBorder *)Tcl_GetHashValue(borderPtr->hashPtr);
    TkpFreeBorder(borderPtr);
    if (borderPtr->bgColorPtr != NULL) {
	Tk_FreeColor(borderPtr->bgColorPtr);
    }
    if (borderPtr->darkColorPtr != NULL) {
	Tk_FreeColor(borderPtr->darkColorPtr);
    }
523
524
525
526
527
528
529
530

531
532
533
534
535
536
537
522
523
524
525
526
527
528

529
530
531
532
533
534
535
536







-
+







    objPtr->typePtr = NULL;
}

static void
FreeBorderObj(
    Tcl_Obj *objPtr)		/* The object we are releasing. */
{
    TkBorder *borderPtr = objPtr->internalRep.twoPtrValue.ptr1;
    TkBorder *borderPtr = (TkBorder *)objPtr->internalRep.twoPtrValue.ptr1;

    if (borderPtr != NULL) {
	borderPtr->objRefCount--;
	if ((borderPtr->objRefCount == 0)
		&& (borderPtr->resourceRefCount == 0)) {
	    ckfree(borderPtr);
	}
558
559
560
561
562
563
564
565

566
567
568
569
570
571
572
557
558
559
560
561
562
563

564
565
566
567
568
569
570
571







-
+







 */

static void
DupBorderObjProc(
    Tcl_Obj *srcObjPtr,		/* The object we are copying from. */
    Tcl_Obj *dupObjPtr)		/* The object we are copying to. */
{
    TkBorder *borderPtr = srcObjPtr->internalRep.twoPtrValue.ptr1;
    TkBorder *borderPtr = (TkBorder *)srcObjPtr->internalRep.twoPtrValue.ptr1;

    dupObjPtr->typePtr = srcObjPtr->typePtr;
    dupObjPtr->internalRep.twoPtrValue.ptr1 = borderPtr;

    if (borderPtr != NULL) {
	borderPtr->objRefCount++;
    }
590
591
592
593
594
595
596
597

598
599
600
601
602
603
604
589
590
591
592
593
594
595

596
597
598
599
600
601
602
603







-
+







 */

void
Tk_SetBackgroundFromBorder(
    Tk_Window tkwin,		/* Window whose background is to be set. */
    Tk_3DBorder border)		/* Token for border. */
{
    register TkBorder *borderPtr = (TkBorder *) border;
    TkBorder *borderPtr = (TkBorder *) border;

    Tk_SetWindowBackground(tkwin, borderPtr->bgColorPtr->pixel);
}

/*
 *----------------------------------------------------------------------
 *
755
756
757
758
759
760
761
762

763
764
765
766
767
768
769
754
755
756
757
758
759
760

761
762
763
764
765
766
767
768







-
+







				 * negative. */
    int leftRelief)		/* TK_RELIEF_RAISED or TK_RELIEF_SUNKEN:
				 * indicates how stuff to left of trajectory
				 * looks relative to stuff on right. */
{
    XPoint poly[4], b1, b2, newB1, newB2;
    XPoint perp, c, shift1, shift2;	/* Used for handling parallel lines. */
    register XPoint *p1Ptr, *p2Ptr;
    XPoint *p1Ptr, *p2Ptr;
    TkBorder *borderPtr = (TkBorder *) border;
    GC gc;
    int i, lightOnLeft, dx, dy, parallel, pointsSeen;
    Display *display = Tk_Display(tkwin);

    if (borderPtr->lightGC == NULL) {
	TkpGetShadows(borderPtr, tkwin);
952
953
954
955
956
957
958
959

960
961
962
963
964
965
966
951
952
953
954
955
956
957

958
959
960
961
962
963
964
965







-
+







    int x, int y, int width, int height,
				/* Outside area of rectangular region. */
    int borderWidth,		/* Desired width for border, in pixels. Border
				 * will be *inside* region. */
    int relief)			/* Indicates 3D effect: TK_RELIEF_FLAT,
				 * TK_RELIEF_RAISED, or TK_RELIEF_SUNKEN. */
{
    register TkBorder *borderPtr = (TkBorder *) border;
    TkBorder *borderPtr = (TkBorder *) border;
    int doubleBorder;

    /*
     * This code is slightly tricky because it only draws the background in
     * areas not covered by the 3D border. This avoids flashing effects on the
     * screen for the border region.
     */
1023
1024
1025
1026
1027
1028
1029
1030

1031
1032
1033
1034
1035
1036
1037
1022
1023
1024
1025
1026
1027
1028

1029
1030
1031
1032
1033
1034
1035
1036







-
+







				 * left of the polygon's trajectory. May be
				 * negative. */
    int leftRelief)		/* Indicates 3D effect of left side of
				 * trajectory relative to right:
				 * TK_RELIEF_FLAT, TK_RELIEF_RAISED, or
				 * TK_RELIEF_SUNKEN. */
{
    register TkBorder *borderPtr = (TkBorder *) border;
    TkBorder *borderPtr = (TkBorder *) border;

    XFillPolygon(Tk_Display(tkwin), drawable, borderPtr->bgGC,
	    pointPtr, numPoints, Complex, CoordModeOrigin);
    if (leftRelief != TK_RELIEF_FLAT) {
	Tk_Draw3DPolygon(tkwin, drawable, border, pointPtr, numPoints,
		borderWidth, leftRelief);
    }
1249
1250
1251
1252
1253
1254
1255
1256

1257
1258
1259
1260
1261
1262
1263
1248
1249
1250
1251
1252
1253
1254

1255
1256
1257
1258
1259
1260
1261
1262







-
+








    /*
     * If we are lucky (and the user doesn't use too many different displays,
     * screens, or colormaps...) then the TkBorder structure we need will be
     * cached in the internal representation of the Tcl_Obj. Check it out...
     */

    borderPtr = objPtr->internalRep.twoPtrValue.ptr1;
    borderPtr = (TkBorder *)objPtr->internalRep.twoPtrValue.ptr1;
    if ((borderPtr != NULL)
	    && (borderPtr->resourceRefCount > 0)
	    && (Tk_Screen(tkwin) == borderPtr->screen)
	    && (Tk_Colormap(tkwin) == borderPtr->colormap)) {
	/*
	 * The object already points to the right border structure. Just
	 * return it.
1277
1278
1279
1280
1281
1282
1283
1284

1285
1286
1287
1288
1289
1290
1291
1276
1277
1278
1279
1280
1281
1282

1283
1284
1285
1286
1287
1288
1289
1290







-
+







     * find the right TkBorder structure.
     */

    hashPtr = Tcl_FindHashEntry(&dispPtr->borderTable, Tcl_GetString(objPtr));
    if (hashPtr == NULL) {
	goto error;
    }
    for (borderPtr = Tcl_GetHashValue(hashPtr); borderPtr != NULL;
    for (borderPtr = (TkBorder *)Tcl_GetHashValue(hashPtr); borderPtr != NULL;
	    borderPtr = borderPtr->nextPtr) {
	if ((Tk_Screen(tkwin) == borderPtr->screen)
		&& (Tk_Colormap(tkwin) == borderPtr->colormap)) {
	    FreeBorderObj(objPtr);
	    objPtr->internalRep.twoPtrValue.ptr1 = borderPtr;
	    borderPtr->objRefCount++;
	    return (Tk_3DBorder) borderPtr;
1367
1368
1369
1370
1371
1372
1373
1374

1375
1376
1377
1378
1379
1380
1381
1382
1383

1384
1385

1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1366
1367
1368
1369
1370
1371
1372

1373
1374
1375
1376
1377
1378
1379
1380
1381

1382
1383

1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397







-
+








-
+

-
+













    Tcl_HashEntry *hashPtr;
    Tcl_Obj *resultPtr;
    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;

    resultPtr = Tcl_NewObj();
    hashPtr = Tcl_FindHashEntry(&dispPtr->borderTable, name);
    if (hashPtr != NULL) {
	TkBorder *borderPtr = Tcl_GetHashValue(hashPtr);
	TkBorder *borderPtr = (TkBorder *)Tcl_GetHashValue(hashPtr);

	if (borderPtr == NULL) {
	    Tcl_Panic("TkDebugBorder found empty hash table entry");
	}
	for ( ; (borderPtr != NULL); borderPtr = borderPtr->nextPtr) {
	    Tcl_Obj *objPtr = Tcl_NewObj();

	    Tcl_ListObjAppendElement(NULL, objPtr,
		    Tcl_NewIntObj(borderPtr->resourceRefCount));
		    Tcl_NewWideIntObj(borderPtr->resourceRefCount));
	    Tcl_ListObjAppendElement(NULL, objPtr,
		    Tcl_NewIntObj(borderPtr->objRefCount));
		    Tcl_NewWideIntObj(borderPtr->objRefCount));
	    Tcl_ListObjAppendElement(NULL, resultPtr, objPtr);
	}
    }
    return resultPtr;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Changes to generic/tk3d.h.
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







/*
 * 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.
 */

#ifndef _TK3D
#define _TK3D
24
25
26
27
28
29
30
31

32
33
34
35
36
37
38
39
40

41
42
43
44
45
46
47
24
25
26
27
28
29
30

31
32
33
34
35
36
37
38
39

40
41
42
43
44
45
46
47







-
+








-
+







    Screen *screen;		/* Screen on which the border will be used. */
    Visual *visual;		/* Visual for all windows and pixmaps using
				 * the border. */
    int depth;			/* Number of bits per pixel of drawables where
				 * the border will be used. */
    Colormap colormap;		/* Colormap out of which pixels are
				 * allocated. */
    int resourceRefCount;	/* Number of active uses of this color (each
    TkSizeT resourceRefCount;	/* Number of active uses of this color (each
				 * active use corresponds to a call to
				 * Tk_Alloc3DBorderFromObj or Tk_Get3DBorder).
				 * If this count is 0, then this structure is
				 * no longer valid and it isn't present in
				 * borderTable: it is being kept around only
				 * because there are objects referring to it.
				 * The structure is freed when objRefCount and
				 * resourceRefCount are both 0. */
    int objRefCount;		/* The number of Tcl objects that reference
    TkSizeT objRefCount;		/* The number of Tcl objects that reference
				 * this structure. */
    XColor *bgColorPtr;		/* Background color (intensity between
				 * lightColorPtr and darkColorPtr). */
    XColor *darkColorPtr;	/* Color for darker areas (must free when
				 * deleting structure). NULL means shadows
				 * haven't been allocated yet.*/
    XColor *lightColorPtr;	/* Color used for lighter areas of border
Changes to generic/tkArgv.c.
1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15






-
-
+
+







/*
 * 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.
 */

#include "tkInt.h"

63
64
65
66
67
68
69
70

71
72
73
74
75

76
77
78
79
80
81
82
63
64
65
66
67
68
69

70
71
72
73
74

75
76
77
78
79
80
81
82







-
+




-
+







				 * hold # args left in argv at end. */
    const char **argv,		/* Array of arguments. Modified to hold those
				 * that couldn't be processed here. */
    const Tk_ArgvInfo *argTable,	/* Array of option descriptions */
    int flags)			/* Or'ed combination of various flag bits,
				 * such as TK_ARGV_NO_DEFAULTS. */
{
    register const Tk_ArgvInfo *infoPtr;
    const Tk_ArgvInfo *infoPtr;
				/* Pointer to the current entry in the table
				 * of argument descriptions. */
    const Tk_ArgvInfo *matchPtr;/* Descriptor that matches current argument. */
    const char *curArg;		/* Current argument */
    register char c;		/* Second character of current arg (used for
    char c;		/* Second character of current arg (used for
				 * quick check for matching; use 2nd char.
				 * because first char. will almost always be
				 * '-'). */
    int srcIndex;		/* Location from which to read next argument
				 * from argv. */
    int dstIndex;		/* Index into argv to which next unused
				 * argument should be copied (never greater
224
225
226
227
228
229
230
231

232
233

234
235
236
237
238
239
240
241
242

243
244

245
246
247
248
249
250
251
252
253
254
255
256

257
258
259
260
261
262
263

264
265
266
267
268
269
270
224
225
226
227
228
229
230

231
232

233
234
235
236
237
238
239
240
241

242
243

244
245
246
247
248
249
250
251
252
253
254
255

256
257
258
259
260
261
262

263
264
265
266
267
268
269
270







-
+

-
+








-
+

-
+











-
+






-
+







		return TCL_ERROR;
	    }
	    srcIndex++;
	    argc--;
	    break;
	case TK_ARGV_FUNC: {
	    typedef int (ArgvFunc)(char *, const char *, const char *);
	    ArgvFunc *handlerProc = (ArgvFunc *) infoPtr->src;
	    ArgvFunc *handlerProc = (ArgvFunc *)infoPtr->src;

	    if (handlerProc(infoPtr->dst, infoPtr->key, argv[srcIndex])) {
	    if (handlerProc((char *)infoPtr->dst, infoPtr->key, argv[srcIndex])) {
		srcIndex++;
		argc--;
	    }
	    break;
	}
	case TK_ARGV_GENFUNC: {
	    typedef int (ArgvGenFunc)(char *, Tcl_Interp *, const char *, int,
		    const char **);
	    ArgvGenFunc *handlerProc = (ArgvGenFunc *) infoPtr->src;
	    ArgvGenFunc *handlerProc = (ArgvGenFunc *)infoPtr->src;

	    argc = handlerProc(infoPtr->dst, interp, infoPtr->key, argc,
	    argc = handlerProc((char *)infoPtr->dst, interp, infoPtr->key, argc,
		    argv+srcIndex);
	    if (argc < 0) {
		return TCL_ERROR;
	    }
	    break;
	}
	case TK_ARGV_HELP:
	    PrintUsage(interp, argTable, flags);
	    Tcl_SetErrorCode(interp, "TK", "ARG", "HELP", NULL);
	    return TCL_ERROR;
	case TK_ARGV_CONST_OPTION:
	    Tk_AddOption(tkwin, infoPtr->dst, infoPtr->src,
	    Tk_AddOption(tkwin, (char *)infoPtr->dst, (char *)infoPtr->src,
		    TK_INTERACTIVE_PRIO);
	    break;
	case TK_ARGV_OPTION_VALUE:
	    if (argc < 1) {
		goto missingArg;
	    }
	    Tk_AddOption(tkwin, infoPtr->dst, argv[srcIndex],
	    Tk_AddOption(tkwin, (char *)infoPtr->dst, argv[srcIndex],
		    TK_INTERACTIVE_PRIO);
	    srcIndex++;
	    argc--;
	    break;
	case TK_ARGV_OPTION_NAME_VALUE:
	    if (argc < 2) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
334
335
336
337
338
339
340
341

342
343
344
345
346
347
348
334
335
336
337
338
339
340

341
342
343
344
345
346
347
348







-
+







				 * area. */
    const Tk_ArgvInfo *argTable,/* Array of command-specific argument
				 * descriptions. */
    int flags)			/* If the TK_ARGV_NO_DEFAULTS bit is set in
				 * this word, then don't generate information
				 * for default options. */
{
    register const Tk_ArgvInfo *infoPtr;
    const Tk_ArgvInfo *infoPtr;
    size_t width, i, numSpaces;
    Tcl_Obj *message;

    /*
     * First, compute the width of the widest option key, so that we can make
     * everything line up.
     */
Changes to generic/tkArray.h.
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







/*
 * tkArray.h --
 *
 * 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.
 */

/*
 * Note that this file will not be included in header files, it is the purpose
184
185
186
187
188
189
190
191

192
193
194
195
196
197
198
184
185
186
187
188
189
190

191
192
193
194
195
196
197
198







-
+







    assert(arr);								\
    arr->size = 0;								\
    arr->capacity = 0;								\
}										\
										\
__TK_ARRAY_UNUSED								\
static size_t									\
AT##_ElemSize()									\
AT##_ElemSize(void)									\
{										\
    return sizeof(ElemType);							\
}										\
										\
__TK_ARRAY_UNUSED								\
static size_t									\
AT##_BufferSize(size_t numElems)						\
269
270
271
272
273
274
275
276

277
278
279
280
281
282
283
269
270
271
272
273
274
275

276
277
278
279
280
281
282
283







-
+







    if (newSize == 0) {								\
	assert(!*arrp || ((*arrp)->size = 0xdeadbeef));				\
	ckfree(*arrp);								\
	*arrp = NULL;								\
    } else {									\
	int init = *arrp == NULL;						\
	size_t memSize = AT##_BufferSize(newSize - 1) + sizeof(AT);		\
	*arrp = ckrealloc(*arrp, memSize);					\
	*arrp = (AT *)ckrealloc(*arrp, memSize);					\
	if (init) {								\
	    (*arrp)->size = 0;							\
	} else if (newSize < (*arrp)->size) {					\
	    (*arrp)->size = newSize;						\
	}									\
	(*arrp)->capacity = newSize;						\
    }										\
395
396
397
398
399
400
401
402

403
404
405
406
407
408
409
395
396
397
398
399
400
401

402
403
404
405
406
407
408
409







-
+







    size_t size;								\
    size_t capacity;								\
    ElemType *buf[1];								\
} AT;										\
										\
__TK_ARRAY_UNUSED								\
static size_t									\
AT##_ElemSize()									\
AT##_ElemSize(void)									\
{										\
    return sizeof(ElemType);							\
}										\
										\
__TK_ARRAY_UNUSED								\
static size_t									\
AT##_BufferSize(size_t numElems)						\
480
481
482
483
484
485
486
487

488
489
490
491
492
493
494
480
481
482
483
484
485
486

487
488
489
490
491
492
493
494







-
+







    if (newCapacity == 0) {							\
	assert(!*arrp || ((*arrp)->size = 0xdeadbeef));				\
	ckfree(*arrp);								\
	*arrp = NULL;								\
    } else {									\
	int init = *arrp == NULL;						\
	size_t memSize = AT##_BufferSize(newCapacity - 1) + sizeof(AT);		\
	*arrp = ckrealloc(*arrp, memSize);					\
	*arrp = (AT *)ckrealloc(*arrp, memSize);					\
	if (init) {								\
	    (*arrp)->size = 0;							\
	} else if (newCapacity < (*arrp)->size) {				\
	    (*arrp)->size = newCapacity;					\
	}									\
	(*arrp)->capacity = newCapacity;					\
    }										\
Changes to generic/tkAtom.c.
1
2
3
4
5
6
7
8
9
10


11
12
13
14
15
16
17
1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
16
17








-
-
+
+







/*
 * tkAtom.c --
 *
 *	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.
 */

#include "tkInt.h"

150
151
152
153
154
155
156
157

158
159

160
161

162
163
164
165
166
167
168
150
151
152
153
154
155
156

157
158

159
160

161
162
163
164
165
166
167
168







-
+

-
+

-
+







	}
	Tk_DeleteErrorHandler(handler);
	hPtr = Tcl_CreateHashEntry(&dispPtr->nameTable, name, &isNew);
	Tcl_SetHashValue(hPtr, INT2PTR(atom));
	if (mustFree) {
	    XFree(mustFree);
	}
	name = Tcl_GetHashKey(&dispPtr->nameTable, hPtr);
	name = (const char *)Tcl_GetHashKey(&dispPtr->nameTable, hPtr);
	hPtr = Tcl_CreateHashEntry(&dispPtr->atomTable, INT2PTR(atom), &isNew);
	Tcl_SetHashValue(hPtr, name);
	Tcl_SetHashValue(hPtr, (char *)name);
    }
    return Tcl_GetHashValue(hPtr);
    return (const char *)Tcl_GetHashValue(hPtr);
}

/*
 *--------------------------------------------------------------
 *
 * AtomInit --
 *
196
197
198
199
200
201
202
203

204
205

206
207
208
209
210
211
212
213
214
215
196
197
198
199
200
201
202

203
204

205
206
207
208
209
210
211
212
213
214
215







-
+

-
+










	if (hPtr != NULL) {
	    continue;
	}

	name = atomNameArray[atom - 1];
	hPtr = Tcl_CreateHashEntry(&dispPtr->nameTable, name, &isNew);
	Tcl_SetHashValue(hPtr, INT2PTR(atom));
	name = Tcl_GetHashKey(&dispPtr->nameTable, hPtr);
	name = (const char *)Tcl_GetHashKey(&dispPtr->nameTable, hPtr);
	hPtr = Tcl_CreateHashEntry(&dispPtr->atomTable, INT2PTR(atom), &isNew);
	Tcl_SetHashValue(hPtr, name);
	Tcl_SetHashValue(hPtr, (char *)name);
    }
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Changes to generic/tkBind.c.
1
2
3
4
5
6
7
8
9
10




11
12
13
14
15
16
17
1
2
3
4
5
6




7
8
9
10
11
12
13
14
15
16
17






-
-
-
-
+
+
+
+







/*
 * 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.
 */

#include "tkInt.h"
#include "tkDList.h"
55
56
57
58
59
60
61
62
63




64
65
66
67

68
69
70
71
72
73


74
75
76
77

78
79
80
81
82
83
84
55
56
57
58
59
60
61


62
63
64
65
66
67
68

69
70
71
72
73


74
75
76
77
78

79
80
81
82
83
84
85
86







-
-
+
+
+
+



-
+




-
-
+
+



-
+







 * Package-specific common helpers.
 *
 * Non-package-specific helpers.
 */

/*
 * In old implementation (the one that used an event ring), <Double-1> and <1><1> were
 * equivalent sequences. However it is logical to give <Double-1> higher precedence.
 * This can be achieved by setting PREFER_MOST_SPECIALIZED_EVENT to 1.
 * equivalent sequences. However it is logical to give <Double-1> higher precedence
 * since it is more specific. Indeed <Double-1> includes time and space requirements,
 * which is not the case for <1><1>.
 * This is achieved by setting PREFER_MOST_SPECIALIZED_EVENT to 1.
 */

#ifndef PREFER_MOST_SPECIALIZED_EVENT
# define PREFER_MOST_SPECIALIZED_EVENT 0
# define PREFER_MOST_SPECIALIZED_EVENT 1
#endif

/*
 * Traditionally motion events can be combined with buttons in this way: <B1-B2-Motion>.
 * However it should be allowed to express this as <Motion-1-2> in addition. This can be
 * achieved by setting SUPPORT_ADDITIONAL_MOTION_SYNTAX to 1.
 * However it should be allowed to express this as <Motion-1-2> in addition. This is achieved
 * by setting SUPPORT_ADDITIONAL_MOTION_SYNTAX to 1.
 */

#ifndef SUPPORT_ADDITIONAL_MOTION_SYNTAX
# define SUPPORT_ADDITIONAL_MOTION_SYNTAX 0 /* set to 1 if wanted */
# define SUPPORT_ADDITIONAL_MOTION_SYNTAX 1
#endif

/*
 * The output for motion events is of the type <B1-Motion>. This can be changed to become
 * <Motion-1> instead by setting PRINT_SHORT_MOTION_SYNTAX to 1, however this would be a
 * backwards incompatibility.
 */
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148

149
150
151
152
153
154
155
133
134
135
136
137
138
139







140
141
142

143
144
145
146
147
148
149
150







-
-
-
-
-
-
-



-
+







    unsigned countAny;	/* Count of multi-events, like multi-clicks, or repeated key pressing,
    			 * this count does not depend on detail (keySym or button). */
    unsigned countDetailed;
    			/* Count of multi-events, like multi-clicks, or repeated key pressing,
    			 * this count considers the detail (keySym or button). */
} Event;

/*
 * We need a structure providing a list of pattern sequences.
 */

typedef unsigned EventMask;
typedef unsigned long ModMask;

struct PatSeq; /* forward declaration */

/* We need this array for bookkeeping the last matching modifier mask per pattern. */
TK_ARRAY_DEFINE(PSModMaskArr, ModMask);
TK_ARRAY_DEFINE(PSModMaskArr, unsigned);

typedef struct PSEntry {
    TK_DLIST_LINKS(PSEntry);	/* Makes this struct a double linked list; must be first entry. */
    Window window;		/* Window of last match. */
    struct PatSeq* psPtr;	/* Pointer to pattern sequence. */
    PSModMaskArr *lastModMaskArr;
    				/* Last matching modifier mask per pattern (except last pattern).
197
198
199
200
201
202
203
204

205
206
207
208
209
210
211
192
193
194
195
196
197
198

199
200
201
202
203
204
205
206







-
+







TK_ARRAY_DEFINE(PromArr, PSList);

typedef struct Tk_BindingTable_ {
    Event eventInfo[TK_LASTEVENT];
    				/* Containing the most recent event for every event type. */
    PromArr *promArr;		/* Contains the promoted pattern sequences. */
    Event *curEvent;		/* Pointing to most recent event. */
    ModMask curModMask;		/* Containing the current modifier mask. */
    unsigned curModMask;		/* Containing the current modifier mask. */
    LookupTables lookupTables;	/* Containing hash tables for fast lookup. */
    Tcl_HashTable objectTable;	/* Used to map from an object to a list of patterns associated with
    				 * that object. Keys are ClientData, values are (PatSeq *). */
    Tcl_Interp *interp;		/* Interpreter in which commands are executed. */
} BindingTable;

/*
259
260
261
262
263
264
265
266

267
268
269
270
271
272
273
254
255
256
257
258
259
260

261
262
263
264
265
266
267
268







-
+







 * For technical reasons we do not use 'union Detail', although this would
 * be possible, instead 'info' and 'name' are both included.
 */

typedef struct {
    unsigned eventType;		/* Type of X event, e.g. ButtonPress. */
    unsigned count;		/* Multi-event count, e.g. double-clicks, triple-clicks, etc. */
    ModMask modMask;		/* Mask of modifiers that must be present (zero means no modifiers
    unsigned modMask;		/* Mask of modifiers that must be present (zero means no modifiers
    				 * are required). */
    Info info;			/* Additional information that must match event. Normally this is zero,
    				 * meaning no additional information must match. For KeyPress and
				 * KeyRelease events, it may be specified to select a particular
				 * keystroke (zero means any keystrokes). For button events, specifies
				 * a particular button (zero means any buttons are OK). */
    Tk_Uid name;		/* Specifies the Tk_Uid of the virtual event name. NULL if not a
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
334
335
336
337
338
339
340








341
342
343
344
345
346
347







-
-
-
-
-
-
-
-







 * Constants that define how close together two events must be in milliseconds
 * or pixels to meet the PAT_NEARBY constraint:
 */

#define NEARBY_PIXELS	5
#define NEARBY_MS	500

/*
 * Needed as "no-number" constant for integers. The value of this constant is
 * outside of integer range (type "int"). (Unfortunatly current version of
 * Tcl/Tk does not provide C99 integer support.)
 */

#define NO_NUMBER (((Tcl_WideInt) (~ (unsigned) 0)) + 1)

/*
 * The following structure is used in the nameTable of a virtual event table
 * to associate a virtual event with all the physical events that can trigger
 * it.
 */

TK_PTR_ARRAY_DEFINE(PhysOwned, PatSeq); /* define array of pattern seqs */
418
419
420
421
422
423
424
425

426
427
428
429
430
431
432
405
406
407
408
409
410
411

412
413
414
415
416
417
418
419







-
+







 * information about those modifiers. The structure for storing this
 * information, and the hash table built at initialization time, are defined
 * below.
 */

typedef struct {
    const char *name;	/* Name of modifier. */
    ModMask mask;	/* Button/modifier mask value, such as Button1Mask. */
    unsigned mask;	/* Button/modifier mask value, such as Button1Mask. */
    unsigned flags;	/* Various flags; see below for definitions. */
} ModInfo;

/*
 * Flags for ModInfo structures:
 *
 * DOUBLE -		Non-zero means duplicate this event, e.g. for double-clicks.
441
442
443
444
445
446
447

448

449
450
451
452
453
454
455
456
457
458
459
460








461
462

463





464
465

466



467
468
469
470
471
472
473
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480







+

+












+
+
+
+
+
+
+
+


+

+
+
+
+
+


+

+
+
+







#define MULT_CLICKS	(DOUBLE|TRIPLE|QUADRUPLE)

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},
    {"Button2",		Button2Mask,	0},
    {"B3",		Button3Mask,	0},
    {"Button3",		Button3Mask,	0},
    {"B4",		Button4Mask,	0},
    {"Button4",		Button4Mask,	0},
    {"B5",		Button5Mask,	0},
    {"Button5",		Button5Mask,	0},
    {"B6",		Button6Mask,	0},
    {"Button6",		Button6Mask,	0},
    {"B7",		Button7Mask,	0},
    {"Button7",		Button7Mask,	0},
    {"B8",		Button8Mask,	0},
    {"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},
    {"M5",		Mod5Mask,	0},
    {"Double",		0,		DOUBLE},
495
496
497
498
499
500
501

502

503
504

505

506
507
508
509
510
511
512
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523







+

+


+

+







 * This is necessary because X doesn't report up events unless you also ask
 * for down events. Also, X doesn't report button state in motion events
 * 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},
    {"FocusOut",	FocusOut,		FocusChangeMask},
    {"Expose",		Expose,			ExposureMask},
557
558
559
560
561
562
563

564
565
566
567




568





569
570















571
572
573
574
575
576
577
568
569
570
571
572
573
574
575




576
577
578
579
580
581
582
583
584
585


586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607







+
-
-
-
-
+
+
+
+

+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







#define CONFIG			(1<<12)
#define GRAVITY			(1<<13)
#define CIRC			(1<<14)
#define PROP			(1<<15)
#define COLORMAP		(1<<16)
#define VIRTUAL			(1<<17)
#define ACTIVATE		(1<<18)
#define WHEEL			(1<<19)
#define	MAPREQ			(1<<19)
#define	CONFIGREQ		(1<<20)
#define	RESIZEREQ		(1<<21)
#define CIRCREQ			(1<<22)
#define	MAPREQ			(1<<20)
#define	CONFIGREQ		(1<<21)
#define	RESIZEREQ		(1<<22)
#define CIRCREQ			(1<<23)

/*
 * These structs agree with xkey for the fields type, serial, send_event, display,
 * window, root, subwindow, time, x, y, x_root, and y_root.  So when accessing
 * these fields we may pretend that we are using a struct xkey.
 */
#define KEY_BUTTON_MOTION_VIRTUAL	(KEY|BUTTON|MOTION|VIRTUAL)
#define KEY_BUTTON_MOTION_CROSSING	(KEY|BUTTON|MOTION|VIRTUAL|CROSSING)

#define HAS_XKEY_HEAD (KEY|BUTTON|MOTION|VIRTUAL|CROSSING|WHEEL)

/*
 * The xcrossing struct puts the state field in a different location, but the other
 * events above agree on where state is located.
 */

#define HAS_XKEY_HEAD_AND_STATE (KEY|BUTTON|MOTION|VIRTUAL|WHEEL)

/*
 * Event types which support -warp.
 */

#define CAN_WARP (KEY|BUTTON|MOTION|WHEEL)

static const int flagArray[TK_LASTEVENT] = {
   /* Not used */		0,
   /* Not used */		0,
   /* KeyPress */		KEY,
   /* KeyRelease */		KEY,
   /* ButtonPress */		BUTTON,
604
605
606
607
608
609
610
611

612
613
614
615
616
617
618
634
635
636
637
638
639
640

641
642
643
644
645
646
647
648







-
+







   /* SelectionNotify */	0,
   /* ColormapNotify */		COLORMAP,
   /* ClientMessage */		0,
   /* MappingNotify */		0,
   /* VirtualEvent */		VIRTUAL,
   /* Activate */		ACTIVATE,
   /* Deactivate */		ACTIVATE,
   /* MouseWheel */		KEY
   /* MouseWheel */		WHEEL
};

/*
 * The following table is used to map between the location where an generated
 * event should be queued and the string used to specify the location.
 */

696
697
698
699
700
701
702
703

704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719

720
721
722
723
724
725
726
727
726
727
728
729
730
731
732

733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748

749

750
751
752
753
754
755
756







-
+















-
+
-







static int		DeleteVirtualEvent(Tcl_Interp *interp, VirtualEventTable *vetPtr,
			    char *virtString, const char *eventString);
static void		DeleteVirtualEventTable(VirtualEventTable *vetPtr);
static void		ExpandPercents(TkWindow *winPtr, const char *before, Event *eventPtr,
			    unsigned scriptCount, Tcl_DString *dsPtr);
static PatSeq *		FindSequence(Tcl_Interp *interp, LookupTables *lookupTables,
			    ClientData object, const char *eventString, int create,
			    int allowVirtual, EventMask *maskPtr);
			    int allowVirtual, unsigned *maskPtr);
static void		GetAllVirtualEvents(Tcl_Interp *interp, VirtualEventTable *vetPtr);
static const char *	GetField(const char *p, char *copy, unsigned size);
static Tcl_Obj *	GetPatternObj(const PatSeq *psPtr);
static int		GetVirtualEvent(Tcl_Interp *interp, VirtualEventTable *vetPtr,
			    Tcl_Obj *virtName);
static Tk_Uid		GetVirtualEventUid(Tcl_Interp *interp, char *virtString);
static int		HandleEventGenerate(Tcl_Interp *interp, Tk_Window main,
			    int objc, Tcl_Obj *const objv[]);
static void		InitVirtualEventTable(VirtualEventTable *vetPtr);
static PatSeq *		MatchPatterns(TkDisplay *dispPtr, Tk_BindingTable bindPtr, PSList *psList,
			    PSList *psSuccList, unsigned patIndex, const Event *eventPtr,
			    ClientData object, PatSeq **physPtrPtr);
static int		NameToWindow(Tcl_Interp *interp, Tk_Window main,
			    Tcl_Obj *objPtr, Tk_Window *tkwinPtr);
static unsigned		ParseEventDescription(Tcl_Interp *interp, const char **eventStringPtr,
			    TkPattern *patPtr, EventMask *eventMaskPtr);
			    TkPattern *patPtr, unsigned *eventMaskPtr);
static void		DoWarp(ClientData clientData);
static PSList *		GetLookupForEvent(LookupTables* lookupPtr, const Event *eventPtr,
			    Tcl_Obj *object, int onlyConsiderDetailedEvents);
static void		ClearLookupTable(LookupTables *lookupTables, ClientData object);
static void		ClearPromotionLists(Tk_BindingTable bindPtr, ClientData object);
static PSEntry *	MakeListEntry(PSList *pool, PatSeq *psPtr, int needModMasks);
static void		RemovePatSeqFromLookup(LookupTables *lookupTables, PatSeq *psPtr);
static void		RemovePatSeqFromPromotionLists(Tk_BindingTable bindPtr, PatSeq *psPtr);
744
745
746
747
748
749
750
751
752


753
754
755
756
757
758
759
773
774
775
776
777
778
779


780
781
782
783
784
785
786
787
788







-
-
+
+







static int IsOdd(int n) { return n & 1; }

static int TestNearbyTime(int lhs, int rhs) { return Abs(lhs - rhs) <= NEARBY_MS; }
static int TestNearbyCoords(int lhs, int rhs) { return Abs(lhs - rhs) <= NEARBY_PIXELS; }

static int
IsSubsetOf(
    ModMask lhsMask,	/* this is a subset */
    ModMask rhsMask)	/* of this bit field? */
    unsigned lhsMask,	/* this is a subset */
    unsigned rhsMask)	/* of this bit field? */
{
    return (lhsMask & rhsMask) == lhsMask;
}

static const char*
SkipSpaces(
    const char* s)
775
776
777
778
779
780
781

782
783


784
785
786
787

788
789
790
791
792
793
794
804
805
806
807
808
809
810
811
812

813
814
815
816
817

818
819
820
821
822
823
824
825







+

-
+
+



-
+







    return s;
}

static unsigned
GetButtonNumber(
    const char *field)
{
    unsigned button;
    assert(field);
    return (field[0] >= '1' && field[0] <= '5' && field[1] == '\0') ? field[0] - '0' : 0;
    button = (field[0] >= '1' && field[0] <= '9' && field[1] == '\0') ? field[0] - '0' : 0;
    return (button > 3) ? (button + 4) : button;
}

static Time
CurrentTimeInMilliSecs()
CurrentTimeInMilliSecs(void)
{
    Tcl_Time now;
    Tcl_GetTime(&now);
    return ((Time) now.sec)*1000 + ((Time) now.usec)/1000;
}

static Info
830
831
832
833
834
835
836














837
838
839
840
841
842
843
844
845

846
847
848
849
850
851
852
853
854
855
856
857
858


859
860
861
862

863
864
865
866


867
868
869
870
871
872
873
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889

890
891
892
893
894
895
896
897
898
899
900
901


902
903
904
905
906

907
908
909


910
911
912
913
914
915
916
917
918







+
+
+
+
+
+
+
+
+
+
+
+
+
+








-
+











-
-
+
+



-
+


-
-
+
+







    }
    for (i = 0; i < sndMatchPtr->numPats; ++i) {
	if (GetInfo(sndMatchPtr, i)) { sndCount += GetCount(sndMatchPtr, i); }
    }

    return sndCount - fstCount;
}

int
IsKeyEventType(
    unsigned eventType)
{
    return eventType == KeyPress || eventType == KeyRelease;
}

int
IsButtonEventType(
    unsigned eventType)
{
    return eventType == ButtonPress || eventType == ButtonRelease;
}

static int
MatchEventNearby(
    const XEvent *lhs,	/* previous button event */
    const XEvent *rhs)	/* current button event */
{
    assert(lhs);
    assert(rhs);
    assert(lhs->type == ButtonPress || lhs->type == ButtonRelease);
    assert(IsButtonEventType(lhs->type));
    assert(lhs->type == rhs->type);

    /* assert: lhs->xbutton.time <= rhs->xbutton.time */

    return TestNearbyTime(rhs->xbutton.time, lhs->xbutton.time)
	    && TestNearbyCoords(rhs->xbutton.x_root, lhs->xbutton.x_root)
	    && TestNearbyCoords(rhs->xbutton.y_root, lhs->xbutton.y_root);
}

static int
MatchEventRepeat(
    const XEvent *lhs,	/* previous key event */
    const XEvent *rhs)	/* current key event */
    const XKeyEvent *lhs,	/* previous key event */
    const XKeyEvent *rhs)	/* current key event */
{
    assert(lhs);
    assert(rhs);
    assert(lhs->type == KeyPress || lhs->type == KeyRelease);
    assert(IsKeyEventType(lhs->type));
    assert(lhs->type == rhs->type);

    /* assert: lhs->xkey.time <= rhs->xkey.time */
    return TestNearbyTime(rhs->xkey.time, lhs->xkey.time);
    /* assert: lhs->time <= rhs->time */
    return lhs->keycode == rhs->keycode && TestNearbyTime(lhs->time, rhs->time);
}

static void
FreePatSeq(
    PatSeq *psPtr)
{
    assert(psPtr);
918
919
920
921
922
923
924
925

926
927
928

929
930
931
932
933
934
935
936
937
938
939
940
941
942
943

944
945
946
947
948
949

950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965




966

967
968
969
970
971
972
973
963
964
965
966
967
968
969

970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988

989
990
991
992
993
994

995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015

1016
1017
1018
1019
1020
1021
1022
1023







-
+



+














-
+





-
+
















+
+
+
+
-
+







    } else {
	PSList_Move(pool, psList);
    }
}

static PSEntry *
FreePatSeqEntry(
    PSList *pool,
    TCL_UNUSED(PSList *),
    PSEntry *entry)
{
    PSEntry *next = PSList_Next(entry);

    PSModMaskArr_Free(&entry->lastModMaskArr);
    ckfree(entry);
    return next;
}

static unsigned
ResolveModifiers(
    TkDisplay *dispPtr,
    unsigned modMask)
{
    assert(dispPtr);

    if (dispPtr->metaModMask) {
	if (modMask & META_MASK) {
	    modMask &= ~(ModMask)META_MASK;
	    modMask &= ~META_MASK;
	    modMask |= dispPtr->metaModMask;
	}
    }
    if (dispPtr->altModMask) {
	if (modMask & ALT_MASK) {
	    modMask &= ~(ModMask)ALT_MASK;
	    modMask &= ~ALT_MASK;
	    modMask |= dispPtr->altModMask;
	}
    }

    return modMask;
}

static int
ButtonNumberFromState(
    unsigned state)
{
    if (!(state & ALL_BUTTONS)) { return 0; }
    if (state & Button1Mask) { return 1; }
    if (state & Button2Mask) { return 2; }
    if (state & Button3Mask) { return 3; }
    if (state & Button4Mask) { return 4; }
    if (state & Button5Mask) { return 5; }
    if (state & Button6Mask) { return 6; }
    if (state & Button7Mask) { return 7; }
    if (state & Button8Mask) { return 8; }
    return 5;
    return 9;
}

static void
SetupPatternKey(
    PatternTableKey *key,
    const PatSeq *psPtr)
{
1019
1020
1021
1022
1023
1024
1025
1026

1027
1028
1029
1030
1031
1032
1033
1069
1070
1071
1072
1073
1074
1075

1076
1077
1078
1079
1080
1081
1082
1083







-
+








    assert(pool);
    assert(psPtr);
    assert(psPtr->numPats > 0);
    assert(TEST_PSENTRY(psPtr));

    if (PSList_IsEmpty(pool)) {
	newEntry = ckalloc(sizeof(PSEntry));
	newEntry = (PSEntry *)ckalloc(sizeof(PSEntry));
	newEntry->lastModMaskArr = NULL;
	DEBUG(countEntryItems += 1;)
    } else {
	newEntry = PSList_First(pool);
	PSList_RemoveHead(pool);
    }

1096
1097
1098
1099
1100
1101
1102
1103

1104
1105
1106
1107
1108
1109
1110
1146
1147
1148
1149
1150
1151
1152

1153
1154
1155
1156
1157
1158
1159
1160







-
+







	    return NULL;
	}
    }

    key.object = object;
    key.type = eventPtr->xev.type;
    hPtr = Tcl_FindHashEntry(&lookupTables->listTable, (char *) &key);
    return hPtr ? Tcl_GetHashValue(hPtr) : NULL;
    return hPtr ? (PSList *)Tcl_GetHashValue(hPtr) : NULL;
}

/*
 *--------------------------------------------------------------
 *
 * ClearLookupTable --
 *
1134
1135
1136
1137
1138
1139
1140
1141

1142
1143
1144
1145
1146
1147

1148
1149
1150
1151
1152
1153
1154
1184
1185
1186
1187
1188
1189
1190

1191
1192
1193
1194
1195
1196

1197
1198
1199
1200
1201
1202
1203
1204







-
+





-
+








    for (hPtr = Tcl_FirstHashEntry(&lookupTables->listTable, &search); hPtr; hPtr = nextPtr) {
	PSList *psList;

	nextPtr = Tcl_NextHashEntry(&search);

	if (object) {
	    const PatternTableKey *key = Tcl_GetHashKey(&lookupTables->listTable, hPtr);
	    const PatternTableKey *key = (const PatternTableKey *)Tcl_GetHashKey(&lookupTables->listTable, hPtr);
	    if (key->object != object) {
		continue;
	    }
	}

	psList = Tcl_GetHashValue(hPtr);
	psList = (PSList *)Tcl_GetHashValue(hPtr);
	PSList_Move(pool, psList);
	ckfree(psList);
	DEBUG(countListItems -= 1;)
	Tcl_DeleteHashEntry(hPtr);
    }
}

1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259

1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301








































1302
1303
1304
1305
1306
1307
1308
1280
1281
1282
1283
1284
1285
1286




1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304

1305
1306
1307








































1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354







-
-
-
-


















-
+


-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    /* type of TkPattern.info is well defined? */
    assert(sizeof(Info) >= sizeof(KeySym));
    assert(sizeof(Info) >= sizeof(unsigned));

    /* ensure that our matching algorithm is working (when testing detail) */
    assert(sizeof(Detail) == sizeof(Tk_Uid));

    /* test that constant NO_NUMBER is indeed out of integer range */
    assert(sizeof(NO_NUMBER) > sizeof(int));
    assert(((int) NO_NUMBER) == 0 && NO_NUMBER != 0);

    /* test expected indices of Button1..Button5, otherwise our button handling is not working */
    assert(Button1 == 1 && Button2 == 2 && Button3 == 3 && Button4 == 4 && Button5 == 5);
    assert(Button2Mask == (Button1Mask << 1));
    assert(Button3Mask == (Button1Mask << 2));
    assert(Button4Mask == (Button1Mask << 3));
    assert(Button5Mask == (Button1Mask << 4));

    /* test expected values of button motion masks, otherwise our button handling is not working */
    assert(Button1MotionMask == Button1Mask);
    assert(Button2MotionMask == Button2Mask);
    assert(Button3MotionMask == Button3Mask);
    assert(Button4MotionMask == Button4Mask);
    assert(Button5MotionMask == Button5Mask);

    /* because we expect zero if keySym is empty */
    assert(NoSymbol == 0L);

    /* this must be a union, not a struct, otherwise comparison with NULL will not work */
    assert(Tk_Offset(Detail, name) == Tk_Offset(Detail, info));
    assert(offsetof(Detail, name) == offsetof(Detail, info));

    /* we use some constraints about X*Event */
    assert(Tk_Offset(XButtonEvent, time) == Tk_Offset(XMotionEvent, time));
    assert(Tk_Offset(XButtonEvent, x_root) == Tk_Offset(XMotionEvent, x_root));
    assert(Tk_Offset(XButtonEvent, y_root) == Tk_Offset(XMotionEvent, y_root));
    assert(Tk_Offset(XCreateWindowEvent, border_width) == Tk_Offset(XConfigureEvent, border_width));
    assert(Tk_Offset(XCreateWindowEvent, width) == Tk_Offset(XConfigureEvent, width));
    assert(Tk_Offset(XCreateWindowEvent, window) == Tk_Offset(XCirculateRequestEvent, window));
    assert(Tk_Offset(XCreateWindowEvent, window) == Tk_Offset(XConfigureEvent, window));
    assert(Tk_Offset(XCreateWindowEvent, window) == Tk_Offset(XGravityEvent, window));
    assert(Tk_Offset(XCreateWindowEvent, window) == Tk_Offset(XMapEvent, window));
    assert(Tk_Offset(XCreateWindowEvent, window) == Tk_Offset(XReparentEvent, window));
    assert(Tk_Offset(XCreateWindowEvent, window) == Tk_Offset(XUnmapEvent, window));
    assert(Tk_Offset(XCreateWindowEvent, x) == Tk_Offset(XConfigureEvent, x));
    assert(Tk_Offset(XCreateWindowEvent, x) == Tk_Offset(XGravityEvent, x));
    assert(Tk_Offset(XCreateWindowEvent, y) == Tk_Offset(XConfigureEvent, y));
    assert(Tk_Offset(XCreateWindowEvent, y) == Tk_Offset(XGravityEvent, y));
    assert(Tk_Offset(XCrossingEvent, time) == Tk_Offset(XEnterWindowEvent, time));
    assert(Tk_Offset(XCrossingEvent, time) == Tk_Offset(XLeaveWindowEvent, time));
    assert(Tk_Offset(XCrossingEvent, time) == Tk_Offset(XKeyEvent, time));
    assert(Tk_Offset(XKeyEvent, root) == Tk_Offset(XButtonEvent, root));
    assert(Tk_Offset(XKeyEvent, root) == Tk_Offset(XCrossingEvent, root));
    assert(Tk_Offset(XKeyEvent, root) == Tk_Offset(XMotionEvent, root));
    assert(Tk_Offset(XKeyEvent, state) == Tk_Offset(XButtonEvent, state));
    assert(Tk_Offset(XKeyEvent, state) == Tk_Offset(XMotionEvent, state));
    assert(Tk_Offset(XKeyEvent, subwindow) == Tk_Offset(XButtonEvent, subwindow));
    assert(Tk_Offset(XKeyEvent, subwindow) == Tk_Offset(XCrossingEvent, subwindow));
    assert(Tk_Offset(XKeyEvent, subwindow) == Tk_Offset(XMotionEvent, subwindow));
    assert(Tk_Offset(XKeyEvent, time) == Tk_Offset(XButtonEvent, time));
    assert(Tk_Offset(XKeyEvent, time) == Tk_Offset(XMotionEvent, time));
    assert(Tk_Offset(XKeyEvent, x) == Tk_Offset(XButtonEvent, x));
    assert(Tk_Offset(XKeyEvent, x) == Tk_Offset(XCrossingEvent, x));
    assert(Tk_Offset(XKeyEvent, x) == Tk_Offset(XMotionEvent, x));
    assert(Tk_Offset(XKeyEvent, x_root) == Tk_Offset(XButtonEvent, x_root));
    assert(Tk_Offset(XKeyEvent, x_root) == Tk_Offset(XCrossingEvent, x_root));
    assert(Tk_Offset(XKeyEvent, x_root) == Tk_Offset(XMotionEvent, x_root));
    assert(Tk_Offset(XKeyEvent, y) == Tk_Offset(XButtonEvent, y));
    assert(Tk_Offset(XKeyEvent, y) == Tk_Offset(XCrossingEvent, y));
    assert(Tk_Offset(XKeyEvent, y) == Tk_Offset(XMotionEvent, y));
    assert(Tk_Offset(XKeyEvent, y_root) == Tk_Offset(XButtonEvent, y_root));
    assert(Tk_Offset(XKeyEvent, y_root) == Tk_Offset(XCrossingEvent, y_root));
    assert(Tk_Offset(XKeyEvent, y_root) == Tk_Offset(XMotionEvent, y_root));
    assert(offsetof(XButtonEvent, time) == offsetof(XMotionEvent, time));
    assert(offsetof(XButtonEvent, x_root) == offsetof(XMotionEvent, x_root));
    assert(offsetof(XButtonEvent, y_root) == offsetof(XMotionEvent, y_root));
    assert(offsetof(XCreateWindowEvent, border_width) == offsetof(XConfigureEvent, border_width));
    assert(offsetof(XCreateWindowEvent, width) == offsetof(XConfigureEvent, width));
    assert(offsetof(XCreateWindowEvent, window) == offsetof(XCirculateRequestEvent, window));
    assert(offsetof(XCreateWindowEvent, window) == offsetof(XConfigureEvent, window));
    assert(offsetof(XCreateWindowEvent, window) == offsetof(XGravityEvent, window));
    assert(offsetof(XCreateWindowEvent, window) == offsetof(XMapEvent, window));
    assert(offsetof(XCreateWindowEvent, window) == offsetof(XReparentEvent, window));
    assert(offsetof(XCreateWindowEvent, window) == offsetof(XUnmapEvent, window));
    assert(offsetof(XCreateWindowEvent, x) == offsetof(XConfigureEvent, x));
    assert(offsetof(XCreateWindowEvent, x) == offsetof(XGravityEvent, x));
    assert(offsetof(XCreateWindowEvent, y) == offsetof(XConfigureEvent, y));
    assert(offsetof(XCreateWindowEvent, y) == offsetof(XGravityEvent, y));
    assert(offsetof(XCrossingEvent, time) == offsetof(XEnterWindowEvent, time));
    assert(offsetof(XCrossingEvent, time) == offsetof(XLeaveWindowEvent, time));
    assert(offsetof(XCrossingEvent, time) == offsetof(XKeyEvent, time));
    assert(offsetof(XKeyEvent, root) == offsetof(XButtonEvent, root));
    assert(offsetof(XKeyEvent, root) == offsetof(XCrossingEvent, root));
    assert(offsetof(XKeyEvent, root) == offsetof(XMotionEvent, root));
    assert(offsetof(XKeyEvent, state) == offsetof(XButtonEvent, state));
    assert(offsetof(XKeyEvent, state) == offsetof(XMotionEvent, state));
    assert(offsetof(XKeyEvent, subwindow) == offsetof(XButtonEvent, subwindow));
    assert(offsetof(XKeyEvent, subwindow) == offsetof(XCrossingEvent, subwindow));
    assert(offsetof(XKeyEvent, subwindow) == offsetof(XMotionEvent, subwindow));
    assert(offsetof(XKeyEvent, time) == offsetof(XButtonEvent, time));
    assert(offsetof(XKeyEvent, time) == offsetof(XMotionEvent, time));
    assert(offsetof(XKeyEvent, x) == offsetof(XButtonEvent, x));
    assert(offsetof(XKeyEvent, x) == offsetof(XCrossingEvent, x));
    assert(offsetof(XKeyEvent, x) == offsetof(XMotionEvent, x));
    assert(offsetof(XKeyEvent, x_root) == offsetof(XButtonEvent, x_root));
    assert(offsetof(XKeyEvent, x_root) == offsetof(XCrossingEvent, x_root));
    assert(offsetof(XKeyEvent, x_root) == offsetof(XMotionEvent, x_root));
    assert(offsetof(XKeyEvent, y) == offsetof(XButtonEvent, y));
    assert(offsetof(XKeyEvent, y) == offsetof(XCrossingEvent, y));
    assert(offsetof(XKeyEvent, y) == offsetof(XMotionEvent, y));
    assert(offsetof(XKeyEvent, y_root) == offsetof(XButtonEvent, y_root));
    assert(offsetof(XKeyEvent, y_root) == offsetof(XCrossingEvent, y_root));
    assert(offsetof(XKeyEvent, y_root) == offsetof(XMotionEvent, y_root));

    /*
     * Initialize the static data structures used by the binding package. They
     * are only initialized once, no matter how many interps are created.
     */

    if (!initialized) {
1355
1356
1357
1358
1359
1360
1361
1362

1363
1364
1365
1366
1367
1368
1369
1401
1402
1403
1404
1405
1406
1407

1408
1409
1410
1411
1412
1413
1414
1415







-
+







	    initialized = 1;
	}
	Tcl_MutexUnlock(&bindMutex);
    }

    mainPtr->bindingTable = Tk_CreateBindingTable(mainPtr->interp);

    bindInfoPtr = ckalloc(sizeof(BindInfo));
    bindInfoPtr = (BindInfo *)ckalloc(sizeof(BindInfo));
    InitVirtualEventTable(&bindInfoPtr->virtualEventTable);
    bindInfoPtr->screenInfo.curDispPtr = NULL;
    bindInfoPtr->screenInfo.curScreenIndex = -1;
    bindInfoPtr->screenInfo.bindingDepth = 0;
    bindInfoPtr->deleted = 0;
    bindInfoPtr->lastCurrentTime = CurrentTimeInMilliSecs();
    bindInfoPtr->lastEventTime = 0;
1431
1432
1433
1434
1435
1436
1437
1438

1439
1440
1441
1442
1443
1444
1445
1477
1478
1479
1480
1481
1482
1483

1484
1485
1486
1487
1488
1489
1490
1491







-
+







 */

Tk_BindingTable
Tk_CreateBindingTable(
    Tcl_Interp *interp)		/* Interpreter to associate with the binding table: commands are
    				 * executed in this interpreter. */
{
    BindingTable *bindPtr = ckalloc(sizeof(BindingTable));
    BindingTable *bindPtr = (BindingTable *)ckalloc(sizeof(BindingTable));
    unsigned i;

    assert(interp);
    DEBUG(countTableItems += 1;)

    /*
     * Create and initialize a new binding table.
1490
1491
1492
1493
1494
1495
1496
1497

1498
1499
1500
1501
1502
1503
1504
1536
1537
1538
1539
1540
1541
1542

1543
1544
1545
1546
1547
1548
1549
1550







-
+







     */

    hPtr = Tcl_FirstHashEntry(&bindPtr->lookupTables.patternTable, &search);
    for ( ; hPtr; hPtr = Tcl_NextHashEntry(&search)) {
	PatSeq *nextPtr;
	PatSeq *psPtr;

	for (psPtr = Tcl_GetHashValue(hPtr); psPtr; psPtr = nextPtr) {
	for (psPtr = (PatSeq *)Tcl_GetHashValue(hPtr); psPtr; psPtr = nextPtr) {
	    assert(TEST_PSENTRY(psPtr));
	    nextPtr = psPtr->nextSeqPtr;
	    FreePatSeq(psPtr);
	}
    }

    /*
1557
1558
1559
1560
1561
1562
1563
1564

1565
1566
1567
1568
1569

1570
1571
1572
1573
1574
1575
1576
1603
1604
1605
1606
1607
1608
1609

1610
1611
1612
1613
1614

1615
1616
1617
1618
1619
1620
1621
1622







-
+




-
+







	PSList *psList;
	PSEntry *psEntry;

	SetupPatternKey(&key, psPtr);
	hPtr = Tcl_CreateHashEntry(&lookupTables->listTable, (char *) &key, &isNew);

	if (isNew) {
	    psList = ckalloc(sizeof(PSList));
	    psList = (PSList *)ckalloc(sizeof(PSList));
	    PSList_Init(psList);
	    Tcl_SetHashValue(hPtr, psList);
	    DEBUG(countListItems += 1;)
	} else {
	    psList = Tcl_GetHashValue(hPtr);
	    psList = (PSList *)Tcl_GetHashValue(hPtr);
	}

	psEntry = MakeListEntry(&lookupTables->entryPool, psPtr, 0);
	PSList_Append(psList, psEntry);
	psPtr->added = 1;
    }
}
1601
1602
1603
1604
1605
1606
1607
1608

1609
1610
1611
1612
1613
1614

1615
1616
1617
1618
1619
1620
1621
1647
1648
1649
1650
1651
1652
1653

1654
1655
1656
1657
1658
1659

1660
1661
1662
1663
1664
1665
1666
1667







-
+





-
+







unsigned long
Tk_CreateBinding(
    Tcl_Interp *interp,		/* Used for error reporting. */
    Tk_BindingTable bindPtr,	/* Table in which to create binding. */
    ClientData object,		/* Token for object with which binding is associated. */
    const char *eventString,	/* String describing event sequence that triggers binding. */
    const char *script,		/* Contains Tcl script to execute when binding triggers. */
    int append)		/* 0 means replace any existing binding for eventString;
    int append)			/* 0 means replace any existing binding for eventString;
    				 * 1 means append to that binding. If the existing binding is
				 * for a callback function and not a Tcl command string, the
				 * existing binding will always be replaced. */
{
    PatSeq *psPtr;
    EventMask eventMask;
    unsigned eventMask;
    char *oldStr;
    char *newStr;

    assert(bindPtr);
    assert(object);
    assert(eventString);
    assert(script);
1650
1651
1652
1653
1654
1655
1656
1657

1658
1659
1660
1661
1662
1663
1664
1665
1666
1667

1668
1669
1670
1671
1672
1673
1674

1675
1676
1677
1678
1679
1680
1681
1696
1697
1698
1699
1700
1701
1702

1703
1704
1705
1706
1707
1708
1709
1710
1711
1712

1713
1714
1715
1716
1717
1718
1719

1720
1721
1722
1723
1724
1725
1726
1727







-
+









-
+






-
+







	/*
	 * This pattern sequence was just created. Link the pattern into the
	 * list associated with the object, so that if the object goes away,
	 * these bindings will all automatically be deleted.
	 */

	hPtr = Tcl_CreateHashEntry(&bindPtr->objectTable, (char *) object, &isNew);
	psPtr->ptr.nextObj = isNew ? NULL : Tcl_GetHashValue(hPtr);
	psPtr->ptr.nextObj = isNew ? NULL : (PatSeq *)Tcl_GetHashValue(hPtr);
	Tcl_SetHashValue(hPtr, psPtr);
	InsertPatSeq(&bindPtr->lookupTables, psPtr);
    }

    oldStr = psPtr->script;
    if (append && oldStr) {
	size_t length1 = strlen(oldStr);
	size_t length2 = strlen(script);

	newStr = ckalloc(length1 + length2 + 2);
	newStr = (char *)ckalloc(length1 + length2 + 2);
	memcpy(newStr, oldStr, length1);
	newStr[length1] = '\n';
	memcpy(newStr + length1 + 1, script, length2 + 1);
    } else {
	size_t length = strlen(script);

	newStr = ckalloc(length + 1);
	newStr = (char *)ckalloc(length + 1);
	memcpy(newStr, script, length + 1);
    }
    ckfree(oldStr);
    psPtr->script = newStr;
    return eventMask;
}

1722
1723
1724
1725
1726
1727
1728
1729

1730
1731
1732
1733
1734
1735
1736
1768
1769
1770
1771
1772
1773
1774

1775
1776
1777
1778
1779
1780
1781
1782







-
+







	/*
	 * Unlink the binding from the list for its object.
	 */

	if (!(hPtr = Tcl_FindHashEntry(&bindPtr->objectTable, (char *) object))) {
	    Tcl_Panic("Tk_DeleteBinding couldn't find object table entry");
	}
	prevPtr = Tcl_GetHashValue(hPtr);
	prevPtr = (PatSeq *)Tcl_GetHashValue(hPtr);
	if (prevPtr == psPtr) {
	    Tcl_SetHashValue(hPtr, psPtr->ptr.nextObj);
	} else {
	    for ( ; ; prevPtr = prevPtr->ptr.nextObj) {
		if (!prevPtr) {
		    Tcl_Panic("Tk_DeleteBinding couldn't find on object list");
		}
1823
1824
1825
1826
1827
1828
1829
1830

1831
1832
1833
1834
1835
1836
1837
1869
1870
1871
1872
1873
1874
1875

1876
1877
1878
1879
1880
1881
1882
1883







-
+







	const PatSeq *psPtr;
	Tcl_Obj *resultObj = Tcl_NewObj();

	/*
	 * For each binding, output information about each of the patterns in its sequence.
	 */

	for (psPtr = Tcl_GetHashValue(hPtr); psPtr; psPtr = psPtr->ptr.nextObj) {
	for (psPtr = (const PatSeq *)Tcl_GetHashValue(hPtr); psPtr; psPtr = psPtr->ptr.nextObj) {
	    assert(TEST_PSENTRY(psPtr));
	    Tcl_ListObjAppendElement(NULL, resultObj, GetPatternObj(psPtr));
	}
	Tcl_SetObjResult(interp, resultObj);
    }
}

1862
1863
1864
1865
1866
1867
1868
1869

1870
1871
1872
1873
1874
1875
1876
1908
1909
1910
1911
1912
1913
1914

1915
1916
1917
1918
1919
1920
1921
1922







-
+








    assert(lookupTables);
    assert(psPtr);

    SetupPatternKey(&key, psPtr);

    if ((hPtr = Tcl_FindHashEntry(&lookupTables->listTable, (char *) &key))) {
	PSList *psList = Tcl_GetHashValue(hPtr);
	PSList *psList = (PSList *)Tcl_GetHashValue(hPtr);
	PSEntry *psEntry;

	TK_DLIST_FOREACH(psEntry, psList) {
	    if (psEntry->psPtr == psPtr) {
		psPtr->added = 0;
		RemoveListEntry(&lookupTables->entryPool, psEntry);
		return;
1946
1947
1948
1949
1950
1951
1952
1953

1954
1955
1956
1957
1958
1959
1960
1992
1993
1994
1995
1996
1997
1998

1999
2000
2001
2002
2003
2004
2005
2006







-
+







    PatSeq *prevPtr;
    PatSeq *nextPtr;

    assert(psPtr);
    assert(!psPtr->added);
    assert(!psPtr->owned);

    prevPtr = Tcl_GetHashValue(psPtr->hPtr);
    prevPtr = (PatSeq *)Tcl_GetHashValue(psPtr->hPtr);
    nextPtr = psPtr->ptr.nextObj;

    /*
     * Be sure to remove each binding from its hash chain in the pattern
     * table. If this is the last pattern in the chain, then delete the
     * hash entry too.
     */
2017
2018
2019
2020
2021
2022
2023
2024

2025
2026
2027
2028
2029
2030
2031
2063
2064
2065
2066
2067
2068
2069

2070
2071
2072
2073
2074
2075
2076
2077







-
+







    /*
     * Don't forget to clear lookup tables.
     */

    ClearLookupTable(&bindPtr->lookupTables, object);
    ClearPromotionLists(bindPtr, object);

    for (psPtr = Tcl_GetHashValue(hPtr); psPtr; psPtr = nextPtr) {
    for (psPtr = (PatSeq *)Tcl_GetHashValue(hPtr); psPtr; psPtr = nextPtr) {
	assert(TEST_PSENTRY(psPtr));
	DEBUG(psPtr->added = 0;)
	nextPtr = DeletePatSeq(psPtr);
    }

    Tcl_DeleteHashEntry(hPtr);
}
2132
2133
2134
2135
2136
2137
2138
2139

2140
2141
2142
2143
2144
2145
2146
2178
2179
2180
2181
2182
2183
2184

2185
2186
2187
2188
2189
2190
2191
2192







-
+







    ClientData *objArr)		/* Array of one or more objects to check for a matching binding. */
{
    Tcl_Interp *interp;
    ScreenInfo *screenPtr;
    TkDisplay *dispPtr;
    TkDisplay *oldDispPtr;
    Event *curEvent;
    TkWindow *winPtr = (TkWindow *) tkwin;
    TkWindow *winPtr = (TkWindow *)tkwin;
    BindInfo *bindInfoPtr;
    Tcl_InterpState interpState;
    LookupTables *physTables;
    PatSeq *psPtr[2];
    PatSeq *matchPtrBuf[32];
    PatSeq **matchPtrArr = matchPtrBuf;
    PSList *psl[2];
2174
2175
2176
2177
2178
2179
2180
2181

2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195

2196
2197
2198
2199
2200
2201
2202
2220
2221
2222
2223
2224
2225
2226

2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240

2241
2242
2243
2244
2245
2246
2247
2248







-
+













-
+







     * Ignore event types which are not in flagArray and all zeroes there.
     */

    if (eventPtr->type >= TK_LASTEVENT || !flags) {
	return;
    }

    if (flags & KEY_BUTTON_MOTION_VIRTUAL) {
    if (flags & HAS_XKEY_HEAD_AND_STATE) {
	bindPtr->curModMask = eventPtr->xkey.state;
    } else if (flags & CROSSING) {
	bindPtr->curModMask = eventPtr->xcrossing.state;
    }

    dispPtr = ((TkWindow *) tkwin)->dispPtr;
    bindInfoPtr = winPtr->mainPtr->bindInfo;
    curEvent = bindPtr->eventInfo + eventPtr->type;

    /*
     * Ignore the event completely if it is an Enter, Leave, FocusIn, or
     * FocusOut event with detail NotifyInferior. The reason for ignoring
     * these events is that we don't want transitions between a window and its
     * children to visible to bindings on the parent: this would cause
     * children to be visible to bindings on the parent: this would cause
     * problems for mega-widgets, since the internal structure of a
     * mega-widget isn't supposed to be visible to people watching the parent.
     *
     * Furthermore we have to compute current time, needed for "event generate".
     */

    switch (eventPtr->type) {
2272
2273
2274
2275
2276
2277
2278
2279

2280
2281
2282
2283
2284
2285
2286
2318
2319
2320
2321
2322
2323
2324

2325
2326
2327
2328
2329
2330
2331
2332







-
+







     */

    /* NOTE: if curEvent is not yet set, then the following cannot match: */
    if (curEvent->xev.xany.window == eventPtr->xany.window) {
	switch (eventPtr->type) {
	case KeyPress:
	case KeyRelease:
	    if (MatchEventRepeat(&curEvent->xev, eventPtr)) {
	    if (MatchEventRepeat(&curEvent->xev.xkey, &eventPtr->xkey)) {
		if (curEvent->xev.xkey.keycode == eventPtr->xkey.keycode) {
		    ++curEvent->countDetailed;
		} else {
		    curEvent->countDetailed = 1;
		}
		++curEvent->countAny;
	    } else {
2342
2343
2344
2345
2346
2347
2348
2349

2350
2351
2352
2353
2354
2355
2356
2388
2389
2390
2391
2392
2393
2394

2395
2396
2397
2398
2399
2400
2401
2402







-
+







    physTables = &bindPtr->lookupTables;
    scriptCount = 0;
    arraySize = 0;
    Tcl_DStringInit(&scripts);

    if ((size_t) numObjects > SIZE_OF_ARRAY(matchPtrBuf)) {
	/* it's unrealistic that the buffer size is too small, but who knows? */
	matchPtrArr = ckalloc(numObjects*sizeof(matchPtrArr[0]));
	matchPtrArr = (PatSeq **)ckalloc(numObjects*sizeof(matchPtrArr[0]));
    }
    memset(matchPtrArr, 0, numObjects*sizeof(matchPtrArr[0]));

    if (!PromArr_IsEmpty(bindPtr->promArr)) {
	for (k = 0; k < (unsigned) numObjects; ++k) {
	    psl[1] = PromArr_Last(bindPtr->promArr);
	    psl[0] = psl[1] - 1;
2383
2384
2385
2386
2387
2388
2389
2390
2391


2392
2393
2394
2395
2396
2397
2398
2429
2430
2431
2432
2433
2434
2435


2436
2437
2438
2439
2440
2441
2442
2443
2444







-
-
+
+







     * 2. Look for bindings without detail.
     */

    for (k = 0; k < (unsigned) numObjects; ++k) {
	PSList *psSuccList = PromArr_First(bindPtr->promArr);
	PatSeq *bestPtr;

	psl[0] = GetLookupForEvent(physTables, curEvent, objArr[k], 1);
	psl[1] = GetLookupForEvent(physTables, curEvent, objArr[k], 0);
	psl[0] = GetLookupForEvent(physTables, curEvent, (Tcl_Obj *)objArr[k], 1);
	psl[1] = GetLookupForEvent(physTables, curEvent, (Tcl_Obj *)objArr[k], 0);

	assert(psl[0] == NULL || psl[0] != psl[1]);

	psPtr[0] = MatchPatterns(dispPtr, bindPtr, psl[0], psSuccList, 0, curEvent, objArr[k], NULL);
	psPtr[1] = MatchPatterns(dispPtr, bindPtr, psl[1], psSuccList, 0, curEvent, objArr[k], NULL);

	if (!PSList_IsEmpty(psSuccList)) {
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2468
2469
2470
2471
2472
2473
2474

2475
2476
2477
2478
2479
2480
2481







-








	    matchPtrArr[k] = bestPtr;

	    if (eventPtr->type != VirtualEvent) {
		LookupTables *virtTables = &bindInfoPtr->virtualEventTable.lookupTables;
		PatSeq *matchPtr = matchPtrArr[k];
		PatSeq *mPtr;
		PSList *psl[2];

		/*
		 * Note that virtual events cannot promote.
		 */

		psl[0] = GetLookupForEvent(virtTables, curEvent, NULL, 1);
		psl[1] = GetLookupForEvent(virtTables, curEvent, NULL, 0);
2496
2497
2498
2499
2500
2501
2502
2503

2504
2505
2506
2507
2508
2509

2510
2511
2512
2513
2514
2515
2516
2541
2542
2543
2544
2545
2546
2547

2548
2549
2550
2551
2552
2553

2554
2555
2556
2557
2558
2559
2560
2561







-
+





-
+







			&& patPtr->eventType == (unsigned) curEvent->xev.type
			&& patPtr->info != curEvent->detail.info)) {
		RemoveListEntry(&bindPtr->lookupTables.entryPool, psEntry);
	    } else {
		switch (patPtr->eventType) {
		case ButtonPress:
		case ButtonRelease:
		    if (curEvent->xev.type == KeyPress || curEvent->xev.type == KeyRelease) {
		    if (IsKeyEventType(curEvent->xev.type)) {
			RemoveListEntry(&bindPtr->lookupTables.entryPool, psEntry);
		    }
		    break;
		case KeyPress:
		case KeyRelease:
		    if (curEvent->xev.type == ButtonPress || curEvent->xev.type == ButtonRelease) {
		    if (IsButtonEventType(curEvent->xev.type)) {
			RemoveListEntry(&bindPtr->lookupTables.entryPool, psEntry);
		    }
		    break;
		}
	    }
	}

2700
2701
2702
2703
2704
2705
2706
2707
2708


2709
2710
2711
2712
2713
2714
2715
2745
2746
2747
2748
2749
2750
2751


2752
2753
2754
2755
2756
2757
2758
2759
2760







-
-
+
+







}

/* helper function */
static int
CompareModMasks(
    const PSModMaskArr *fstModMaskArr,
    const PSModMaskArr *sndModMaskArr,
    ModMask fstModMask,
    ModMask sndModMask)
    unsigned fstModMask,
    unsigned sndModMask)
{
    int fstCount = 0;
    int sndCount = 0;
    int i;

    if (PSModMaskArr_IsEmpty(fstModMaskArr)) {
	if (!PSModMaskArr_IsEmpty(sndModMaskArr)) {
2725
2726
2727
2728
2729
2730
2731
2732
2733


2734
2735
2736


2737
2738
2739
2740
2741
2742
2743
2770
2771
2772
2773
2774
2775
2776


2777
2778
2779


2780
2781
2782
2783
2784
2785
2786
2787
2788







-
-
+
+

-
-
+
+







		++fstCount;
	    }
	}
    } else {
	assert(PSModMaskArr_Size(fstModMaskArr) == PSModMaskArr_Size(sndModMaskArr));

	for (i = PSModMaskArr_Size(fstModMaskArr) - 1; i >= 0; --i) {
	    ModMask fstModMask = *PSModMaskArr_Get(fstModMaskArr, i);
	    ModMask sndModMask = *PSModMaskArr_Get(sndModMaskArr, i);
	    unsigned fstiModMask = *PSModMaskArr_Get(fstModMaskArr, i);
	    unsigned sndiModMask = *PSModMaskArr_Get(sndModMaskArr, i);

	    if (IsSubsetOf(fstModMask, sndModMask)) { ++sndCount; }
	    if (IsSubsetOf(sndModMask, fstModMask)) { ++fstCount; }
	    if (IsSubsetOf(fstiModMask, sndiModMask)) { ++sndCount; }
	    if (IsSubsetOf(sndiModMask, fstiModMask)) { ++fstCount; }
	}
    }

    /* Finally compare modifier masks of last pattern. */

    if (IsSubsetOf(fstModMask, sndModMask)) { ++sndCount; }
    if (IsSubsetOf(sndModMask, fstModMask)) { ++fstCount; }
2759
2760
2761
2762
2763
2764
2765
2766

2767

2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780




















2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795






2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807


2808
2809

2810
2811

2812
2813
2814
2815
2816
2817
2818
2804
2805
2806
2807
2808
2809
2810

2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877


2878
2879
2880
2881
2882
2883

2884
2885
2886
2887
2888
2889
2890
2891







-
+

+













+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+















+
+
+
+
+
+










-
-
+
+


+

-
+







    				 * Output: the associated physical event for the best matching virtual
				 * event; NULL when we match physical events. */
{
    Window window;
    PSEntry *psEntry;
    PatSeq *bestPtr;
    PatSeq *bestPhysPtr;
    ModMask bestModMask;
    unsigned bestModMask;
    const PSModMaskArr *bestModMaskArr = NULL;
    int i, isModKeyOnly = 0;

    assert(dispPtr);
    assert(bindPtr);
    assert(curEvent);

    if (!psList) {
	return NULL;
    }

    bestModMask = 0;
    bestPtr = NULL;
    bestPhysPtr = NULL;
    window = curEvent->xev.xany.window;

    /*
     * Modifier key events interlaced between patterns parts of a
     * sequence shall not prevent a sequence from ultimately
     * matching. Example: when trying to trigger <a><Control-c>
     * from the keyboard, the sequence of events actually seen is
     * <a> then <Control_L> (possibly repeating if the key is hold
     * down), and finally <Control-c>. At the time <Control_L> is
     * seen, we shall keep the <a><Control-c> pattern sequence in
     * the promotion list, otherwise it is impossible to trigger
     * it from the keyboard. See bug [16ef161925].
     */
    if (IsKeyEventType(curEvent->xev.type)) {
        for (i = 0; i < dispPtr->numModKeyCodes; ++i) {
            if (dispPtr->modKeyCodes[i] == curEvent->xev.xkey.keycode) {
                isModKeyOnly = 1;
                break;
            }
        }
    }

    for (psEntry = PSList_First(psList); psEntry; psEntry = PSList_Next(psEntry)) {
	if (patIndex == 0 || psEntry->window == window) {
	    PatSeq* psPtr = psEntry->psPtr;

	    assert(TEST_PSENTRY(psPtr));
	    assert((psPtr->object == NULL) == (physPtrPtr != NULL));
	    assert(psPtr->object || patIndex == 0);
	    assert(psPtr->numPats > patIndex);

	    if (psPtr->object
		    ? psPtr->object == object
		    : VirtPatIsBound(bindPtr, psPtr, object, physPtrPtr)) {
		TkPattern *patPtr = psPtr->pats + patIndex;

                /* ignore modifier key events, and KeyRelease events if the current event
                 * is of a different type (e.g. a Button event)
                 */
                psEntry->keepIt = isModKeyOnly || \
                        ((patPtr->eventType != (unsigned) curEvent->xev.type) && curEvent->xev.type == KeyRelease);

		if (patPtr->eventType == (unsigned) curEvent->xev.type
			&& (curEvent->xev.type != CreateNotify
				|| curEvent->xev.xcreatewindow.parent == window)
			&& (!patPtr->name || patPtr->name == curEvent->detail.name)
			&& (!patPtr->info || patPtr->info == curEvent->detail.info)) {
		    /*
		     * Resolve the modifier mask for Alt and Mod keys. Unfortunately this
		     * cannot be done in ParseEventDescription, otherwise this function would
		     * be the better place.
		     */
		    ModMask modMask = ResolveModifiers(dispPtr, patPtr->modMask);
		    ModMask curModMask = ResolveModifiers(dispPtr, bindPtr->curModMask);
		    unsigned modMask = ResolveModifiers(dispPtr, patPtr->modMask);
		    unsigned curModMask = ResolveModifiers(dispPtr, bindPtr->curModMask);

		    psEntry->expired = 1; /* remove it from promotion list */
                    psEntry->keepIt = 0; /* don't keep matching patterns */

		    if ((modMask & ~curModMask) == 0) {
		    if (IsSubsetOf(modMask, curModMask)) {
			unsigned count = patPtr->info ? curEvent->countDetailed : curEvent->countAny;

			if (patIndex < PSModMaskArr_Size(psEntry->lastModMaskArr)) {
			    PSModMaskArr_Set(psEntry->lastModMaskArr, patIndex, &modMask);
			}

			/*
2919
2920
2921
2922
2923
2924
2925










2926
2927
2928
2929
2930


2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956

2957
2958
2959
2960
2961
2962
2963
2964
2965
2966

2967
2968
2969
2970
2971

2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991

2992
2993
2994
2995
2996

2997
2998

2999
3000

3001
3002

3003
3004

3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021


3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033

3034
3035

3036
3037

3038
3039

3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051


3052
3053

3054
3055
3056
3057
3058
3059
3060
3061
3062


3063
3064
3065
3066

3067
3068
3069
3070

3071
3072
3073
3074

3075
3076

3077
3078

3079
3080

3081
3082

3083
3084
3085
3086
3087


3088
3089
3090
3091

3092
3093

3094
3095

3096
3097
3098
3099

3100
3101
3102
3103
3104


3105
3106

3107
3108

3109
3110

3111
3112
3113
3114
3115
3116

3117
3118
3119
3120

3121
3122
3123
3124
3125
3126
3127

3128
3129

3130
3131

3132
3133
3134
3135
3136
3137
3138
3139


3140
3141
3142
3143

3144
3145
3146

3147
3148
3149
3150
3151
3152
3153
3154

3155
3156
3157
3158


3159
3160
3161
3162
3163
3164
3165
3166
3167

3168
3169
3170
3171
3172
3173

3174
3175
3176
3177
3178
3179

3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190


3191
3192
3193
3194
3195


3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221



3222
3223
3224
3225
3226
3227
3228
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012

3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034

3035

3036
3037

3038
3039
3040
3041
3042
3043
3044
3045
3046
3047

3048
3049
3050
3051
3052

3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072

3073
3074
3075
3076
3077

3078
3079

3080
3081

3082
3083

3084
3085

3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101


3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114

3115
3116

3117
3118

3119
3120

3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131


3132
3133
3134

3135
3136
3137
3138
3139
3140
3141
3142


3143
3144


3145

3146
3147
3148
3149

3150
3151
3152
3153

3154
3155

3156
3157

3158
3159

3160
3161

3162
3163
3164
3165


3166
3167


3168

3169
3170

3171
3172

3173


3174

3175
3176
3177
3178


3179
3180
3181

3182
3183

3184
3185

3186




3187

3188
3189
3190
3191

3192
3193
3194
3195
3196
3197
3198

3199
3200

3201
3202

3203
3204
3205
3206





3207
3208
3209
3210
3211

3212
3213
3214

3215
3216
3217
3218
3219
3220
3221
3222

3223
3224
3225


3226
3227
3228
3229
3230
3231
3232
3233
3234
3235

3236
3237
3238
3239
3240
3241

3242
3243
3244
3245
3246
3247

3248
3249
3250
3251
3252
3253
3254
3255
3256
3257


3258
3259
3260
3261
3262


3263
3264
3265
3266
3267
3268
3269
3270
3271
3272





3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295







+
+
+
+
+
+
+
+
+
+




-
+
+




















-

-


-
+









-
+




-
+



















-
+




-
+

-
+

-
+

-
+

-
+















-
-
+
+











-
+

-
+

-
+

-
+










-
-
+
+

-
+







-
-
+
+
-
-

-
+



-
+



-
+

-
+

-
+

-
+

-
+



-
-
+
+
-
-

-
+

-
+

-
+
-
-

-
+



-
-
+
+

-
+

-
+

-
+
-
-
-
-

-
+



-
+






-
+

-
+

-
+



-
-
-
-
-
+
+



-
+


-
+







-
+


-
-
+
+








-
+





-
+





-
+









-
-
+
+



-
-
+
+








-
-
-
-
-













+
+
+







    assert(before);
    assert(eventPtr);
    assert(dsPtr);

    Tcl_DStringInit(&buf);
    evPtr = &eventPtr->xev;
    flags = (evPtr->type < TK_LASTEVENT) ? flagArray[evPtr->type] : 0;

#define SET_NUMBER(value)   { number = (value);			     \
    snprintf(numStorage, sizeof(numStorage), "%" TCL_LL_MODIFIER "d", number);	     \
    string = numStorage;					     \
    }

#define SET_UNUMBER(value)  { unumber = (value);				\
	snprintf(numStorage, sizeof(numStorage), "%" TCL_LL_MODIFIER "u", unumber);	\
	string = numStorage;						\
    }

    while (1) {
	char numStorage[TCL_INTEGER_SPACE];
	const char *string;
	Tcl_WideInt number;
	Tcl_WideInt number;     /* signed */
	Tcl_WideUInt unumber;   /* unsigned */

	/*
	 * Find everything up to the next % character and append it to the
	 * result string.
	 */

	for (string = before; *string && *string != '%'; ++string)
	    ;
	if (string != before) {
	    Tcl_DStringAppend(dsPtr, before, string - before);
	    before = string;
	}
	if (!*before) {
	    break;
	}

	/*
	 * There's a percent sequence here. Process it.
	 */

	number = NO_NUMBER;
	string = "??";

	switch (before[1]) {
	case '#':
	    number = evPtr->xany.serial;
	    SET_UNUMBER(evPtr->xany.serial);
	    break;
	case 'a':
	    if (flags & CONFIG) {
		TkpPrintWindowId(numStorage, evPtr->xconfigure.above);
		string = numStorage;
	    }
	    break;
	case 'b':
	    if (flags & BUTTON) {
		number = evPtr->xbutton.button;
		SET_UNUMBER(evPtr->xbutton.button);
	    }
	    break;
	case 'c':
	    if (flags & EXPOSE) {
		number = evPtr->xexpose.count;
		SET_NUMBER(evPtr->xexpose.count);
	    }
	    break;
	case 'd':
	    if (flags & (CROSSING|FOCUS)) {
		int detail = (flags & FOCUS) ? evPtr->xfocus.detail : evPtr->xcrossing.detail;
		string = TkFindStateString(notifyDetail, detail);
	    } else if (flags & CONFIGREQ) {
		if (evPtr->xconfigurerequest.value_mask & CWStackMode) {
		    string = TkFindStateString(configureRequestDetail, evPtr->xconfigurerequest.detail);
		} else {
		    string = "";
		}
	    } else if (flags & VIRTUAL) {
		XVirtualEvent *vePtr = (XVirtualEvent *) evPtr;
		string = vePtr->user_data ? Tcl_GetString(vePtr->user_data) : "";
	    }
	    break;
	case 'f':
	    if (flags & CROSSING) {
		number = evPtr->xcrossing.focus;
		SET_NUMBER(evPtr->xcrossing.focus != 0);
	    }
	    break;
	case 'h':
	    if (flags & EXPOSE) {
		number = evPtr->xexpose.height;
		SET_NUMBER(evPtr->xexpose.height);
	    } else if (flags & CONFIG) {
		number = evPtr->xconfigure.height;
		SET_NUMBER(evPtr->xconfigure.height);
	    } else if (flags & CREATE) {
		number = evPtr->xcreatewindow.height;
		SET_NUMBER(evPtr->xcreatewindow.height);
	    } else if (flags & CONFIGREQ) {
		number = evPtr->xconfigurerequest.height;
		SET_NUMBER(evPtr->xconfigurerequest.height);
	    } else if (flags & RESIZEREQ) {
		number = evPtr->xresizerequest.height;
		SET_NUMBER(evPtr->xresizerequest.height);
	    }
	    break;
	case 'i':
	    if (flags & CREATE) {
		TkpPrintWindowId(numStorage, evPtr->xcreatewindow.window);
	    } else if (flags & CONFIGREQ) {
		TkpPrintWindowId(numStorage, evPtr->xconfigurerequest.window);
	    } else if (flags & MAPREQ) {
		TkpPrintWindowId(numStorage, evPtr->xmaprequest.window);
	    } else {
		TkpPrintWindowId(numStorage, evPtr->xany.window);
	    }
	    string = numStorage;
	    break;
	case 'k':
	    if ((flags & KEY) && evPtr->type != MouseWheelEvent) {
		number = evPtr->xkey.keycode;
	    if (flags & KEY) {
		SET_UNUMBER(evPtr->xkey.keycode);
	    }
	    break;
	case 'm':
	    if (flags & CROSSING) {
		string = TkFindStateString(notifyMode, evPtr->xcrossing.mode);
	    } else if (flags & FOCUS) {
		string = TkFindStateString(notifyMode, evPtr->xfocus.mode);
	    }
	    break;
	case 'o':
	    if (flags & CREATE) {
		number = evPtr->xcreatewindow.override_redirect;
		SET_NUMBER(evPtr->xcreatewindow.override_redirect != 0);
	    } else if (flags & MAP) {
		number = evPtr->xmap.override_redirect;
		SET_NUMBER(evPtr->xmap.override_redirect != 0);
	    } else if (flags & REPARENT) {
		number = evPtr->xreparent.override_redirect;
		SET_NUMBER(evPtr->xreparent.override_redirect != 0);
	    } else if (flags & CONFIG) {
		number = evPtr->xconfigure.override_redirect;
		SET_NUMBER(evPtr->xconfigure.override_redirect != 0);
	    }
	    break;
	case 'p':
	    if (flags & CIRC) {
		string = TkFindStateString(circPlace, evPtr->xcirculate.place);
	    } else if (flags & CIRCREQ) {
		string = TkFindStateString(circPlace, evPtr->xcirculaterequest.place);
	    }
	    break;
	case 's':
	    if (flags & KEY_BUTTON_MOTION_VIRTUAL) {
		number = evPtr->xkey.state;
	    if (flags & HAS_XKEY_HEAD_AND_STATE) {
		SET_UNUMBER(evPtr->xkey.state);
	    } else if (flags & CROSSING) {
		number = evPtr->xcrossing.state;
		SET_UNUMBER(evPtr->xcrossing.state);
	    } else if (flags & PROP) {
		string = TkFindStateString(propNotify, evPtr->xproperty.state);
	    } else if (flags & VISIBILITY) {
		string = TkFindStateString(visNotify, evPtr->xvisibility.state);
	    }
	    break;
	case 't':
	    if (flags & KEY_BUTTON_MOTION_VIRTUAL) {
		number = (int) evPtr->xkey.time;
	    if (flags & HAS_XKEY_HEAD) {
		SET_UNUMBER(evPtr->xkey.time);
	    } else if (flags & CROSSING) {
		number = (int) evPtr->xcrossing.time;
	    } else if (flags & PROP) {
		number = (int) evPtr->xproperty.time;
		SET_UNUMBER(evPtr->xproperty.time);
	    }
	    break;
	case 'v':
	    number = evPtr->xconfigurerequest.value_mask;
	    SET_UNUMBER(evPtr->xconfigurerequest.value_mask);
	    break;
	case 'w':
	    if (flags & EXPOSE) {
		number = evPtr->xexpose.width;
		SET_NUMBER(evPtr->xexpose.width);
	    } else if (flags & CONFIG) {
		number = evPtr->xconfigure.width;
		SET_NUMBER(evPtr->xconfigure.width);
	    } else if (flags & CREATE) {
		number = evPtr->xcreatewindow.width;
		SET_NUMBER(evPtr->xcreatewindow.width);
	    } else if (flags & CONFIGREQ) {
		number = evPtr->xconfigurerequest.width;
		SET_NUMBER(evPtr->xconfigurerequest.width);
	    } else if (flags & RESIZEREQ) {
		number = evPtr->xresizerequest.width;
		SET_NUMBER(evPtr->xresizerequest.width);
	    }
	    break;
	case 'x':
	    if (flags & KEY_BUTTON_MOTION_VIRTUAL) {
		number = evPtr->xkey.x;
	    if (flags & HAS_XKEY_HEAD) {
		SET_NUMBER(evPtr->xkey.x);
	    } else if (flags & CROSSING) {
		number = evPtr->xcrossing.x;
	    } else if (flags & EXPOSE) {
		number = evPtr->xexpose.x;
		SET_NUMBER(evPtr->xexpose.x);
	    } else if (flags & (CREATE|CONFIG|GRAVITY)) {
		number = evPtr->xcreatewindow.x;
		SET_NUMBER(evPtr->xcreatewindow.x);
	    } else if (flags & REPARENT) {
		number = evPtr->xreparent.x;
		SET_NUMBER(evPtr->xreparent.x);
	    } else if (flags & CREATE) {
		number = evPtr->xcreatewindow.x;
	    } else if (flags & CONFIGREQ) {
		number = evPtr->xconfigurerequest.x;
		SET_NUMBER(evPtr->xconfigurerequest.x);
	    }
	    break;
	case 'y':
	    if (flags & KEY_BUTTON_MOTION_VIRTUAL) {
		number = evPtr->xkey.y;
	    if (flags & HAS_XKEY_HEAD) {
		SET_NUMBER(evPtr->xkey.y);
	    } else if (flags & EXPOSE) {
		number = evPtr->xexpose.y;
		SET_NUMBER(evPtr->xexpose.y);
	    } else if (flags & (CREATE|CONFIG|GRAVITY)) {
		number = evPtr->xcreatewindow.y;
		SET_NUMBER(evPtr->xcreatewindow.y);
	    } else if (flags & REPARENT) {
		number = evPtr->xreparent.y;
		SET_NUMBER(evPtr->xreparent.y);
	    } else if (flags & CROSSING) {
		number = evPtr->xcrossing.y;
	    } else if (flags & CREATE) {
		number = evPtr->xcreatewindow.y;
	    } else if (flags & CONFIGREQ) {
		number = evPtr->xconfigurerequest.y;
		SET_NUMBER(evPtr->xconfigurerequest.y);
	    }
	    break;
	case 'A':
	    if ((flags & KEY) && evPtr->type != MouseWheelEvent) {
	    if (flags & KEY) {
		Tcl_DStringFree(&buf);
		string = TkpGetString(winPtr, evPtr, &buf);
	    }
	    break;
	case 'B':
	    if (flags & CREATE) {
		number = evPtr->xcreatewindow.border_width;
		SET_NUMBER(evPtr->xcreatewindow.border_width);
	    } else if (flags & CONFIGREQ) {
		number = evPtr->xconfigurerequest.border_width;
		SET_NUMBER(evPtr->xconfigurerequest.border_width);
	    } else if (flags & CONFIG) {
		number = evPtr->xconfigure.border_width;
		SET_NUMBER(evPtr->xconfigure.border_width);
	    }
	    break;
	case 'D':
	    /*
	     * This is used only by the MouseWheel event.
	     */
	    if ((flags & KEY) && evPtr->type == MouseWheelEvent) {
		number = evPtr->xkey.keycode;
	    if (flags & WHEEL) {
		SET_NUMBER((int)evPtr->xbutton.button); /* mis-use button field for this */
	    }
	    break;
	case 'E':
	    number = (int) evPtr->xany.send_event;
	    SET_NUMBER(evPtr->xany.send_event != 0);
	    break;
	case 'K':
	    if ((flags & KEY) && evPtr->type != MouseWheelEvent) {
	    if (flags & KEY) {
		const char *name = TkKeysymToString(eventPtr->detail.info);
		if (name) {
		    string = name;
		}
	    }
	    break;
	case 'M':
	    number = scriptCount;
	    SET_UNUMBER(scriptCount);
	    break;
	case 'N':
	    if ((flags & KEY) && evPtr->type != MouseWheelEvent) {
		number = (int) eventPtr->detail.info;
	    if (flags & KEY) {
		SET_UNUMBER(eventPtr->detail.info);
	    }
	    break;
	case 'P':
	    if (flags & PROP) {
		string = Tk_GetAtomName((Tk_Window) winPtr, evPtr->xproperty.atom);
	    }
	    break;
	case 'R':
	    if (flags & KEY_BUTTON_MOTION_CROSSING) {
	    if (flags & HAS_XKEY_HEAD) {
		TkpPrintWindowId(numStorage, evPtr->xkey.root);
		string = numStorage;
	    }
	    break;
	case 'S':
	    if (flags & KEY_BUTTON_MOTION_CROSSING) {
	    if (flags & HAS_XKEY_HEAD) {
		TkpPrintWindowId(numStorage, evPtr->xkey.subwindow);
		string = numStorage;
	    }
	    break;
	case 'T':
	    number = evPtr->type;
	    SET_NUMBER(evPtr->type);
	    break;
	case 'W': {
	    Tk_Window tkwin = Tk_IdToWindow(evPtr->xany.display, evPtr->xany.window);
	    if (tkwin) {
		string = Tk_PathName(tkwin);
	    }
	    break;
	}
	case 'X':
	    if (flags & KEY_BUTTON_MOTION_CROSSING) {
		number = evPtr->xkey.x_root;
	    if (flags & HAS_XKEY_HEAD) {
		SET_NUMBER(evPtr->xkey.x_root);
	    }
	    break;
	case 'Y':
	    if (flags & KEY_BUTTON_MOTION_CROSSING) {
		number = evPtr->xkey.y_root;
	    if (flags & HAS_XKEY_HEAD) {
		SET_NUMBER(evPtr->xkey.y_root);
	    }
	    break;
	default:
	    numStorage[0] = before[1];
	    numStorage[1] = '\0';
	    string = numStorage;
	    break;
	}

	if (number != NO_NUMBER) {
	    snprintf(numStorage, sizeof(numStorage), "%d", (int) number);
	    string = numStorage;
	}
	{   /* local scope */
	    int cvtFlags;
	    unsigned spaceNeeded = Tcl_ScanElement(string, &cvtFlags);
	    unsigned length = Tcl_DStringLength(dsPtr);

	    Tcl_DStringSetLength(dsPtr, length + spaceNeeded);
	    spaceNeeded = Tcl_ConvertElement(
		    string, Tcl_DStringValue(dsPtr) + length, cvtFlags | TCL_DONT_USE_BRACES);
	    Tcl_DStringSetLength(dsPtr, length + spaceNeeded);
	    before += 2;
	}
    }

#undef SET_NUMBER
#undef SET_UNUMBER

    Tcl_DStringFree(&buf);
}

/*
 *----------------------------------------------------------------------
 *
 * ChangeScreen --
3426
3427
3428
3429
3430
3431
3432
3433

3434
3435
3436
3437
3438
3439
3440
3493
3494
3495
3496
3497
3498
3499

3500
3501
3502
3503
3504
3505
3506
3507







-
+







    assert(vetPtr);

    hPtr = Tcl_FirstHashEntry(&vetPtr->lookupTables.patternTable, &search);
    for ( ; hPtr; hPtr = Tcl_NextHashEntry(&search)) {
	PatSeq *nextPtr;
	PatSeq *psPtr;

	for (psPtr = Tcl_GetHashValue(hPtr); psPtr; psPtr = nextPtr) {
	for (psPtr = (PatSeq *)Tcl_GetHashValue(hPtr); psPtr; psPtr = nextPtr) {
	    assert(TEST_PSENTRY(psPtr));
	    nextPtr = psPtr->nextSeqPtr;
	    DEBUG(psPtr->owned = 0;)
	    FreePatSeq(psPtr);
	}
    }
    Tcl_DeleteHashTable(&vetPtr->lookupTables.patternTable);
3457
3458
3459
3460
3461
3462
3463
3464

3465
3466
3467
3468
3469
3470
3471
3524
3525
3526
3527
3528
3529
3530

3531
3532
3533
3534
3535
3536
3537
3538







-
+







 *
 * CreateVirtualEvent --
 *
 *	Add a new definition for a virtual event. If the virtual event is
 *	already defined, the new definition augments those that already exist.
 *
 * Results:
 *	The return value is TCL_ERROR if an error occured while creating the
 *	The return value is TCL_ERROR if an error occurred while creating the
 *	virtual binding. In this case, an error message will be left in the
 *	interp's result. If all went well then the return value is TCL_OK.
 *
 * Side effects:
 *	The virtual event may cause future calls to Tk_BindEvent to behave
 *	differently than they did previously.
 *
3508
3509
3510
3511
3512
3513
3514
3515

3516
3517
3518
3519
3520
3521
3522
3575
3576
3577
3578
3579
3580
3581

3582
3583
3584
3585
3586
3587
3588
3589







-
+








    vhPtr = Tcl_CreateHashEntry(&vetPtr->nameTable, virtUid, &dummy);

    /*
     * Make virtual event own the physical event.
     */

    owned = Tcl_GetHashValue(vhPtr);
    owned = (PhysOwned *)Tcl_GetHashValue(vhPtr);

    if (!PhysOwned_Contains(owned, psPtr)) {
	PhysOwned_Append(&owned, psPtr);
	Tcl_SetHashValue(vhPtr, owned);
	DEBUG(psPtr->owned = 1;)
	InsertPatSeq(&vetPtr->lookupTables, psPtr);
	/* Make physical event so it can trigger the virtual event. */
3570
3571
3572
3573
3574
3575
3576
3577

3578
3579
3580
3581
3582
3583
3584
3637
3638
3639
3640
3641
3642
3643

3644
3645
3646
3647
3648
3649
3650
3651







-
+







    if (!(virtUid = GetVirtualEventUid(interp, virtString))) {
	return TCL_ERROR;
    }

    if (!(vhPtr = Tcl_FindHashEntry(&vetPtr->nameTable, virtUid))) {
	return TCL_OK;
    }
    owned = Tcl_GetHashValue(vhPtr);
    owned = (PhysOwned *)Tcl_GetHashValue(vhPtr);

    eventPSPtr = NULL;
    if (eventString) {
	LookupTables *lookupTables = &vetPtr->lookupTables;

	/*
	 * Delete only the specific physical event associated with the virtual
3702
3703
3704
3705
3706
3707
3708
3709

3710
3711
3712
3713
3714
3715
3716
3769
3770
3771
3772
3773
3774
3775

3776
3777
3778
3779
3780
3781
3782
3783







-
+







    }

    if (!(vhPtr = Tcl_FindHashEntry(&vetPtr->nameTable, virtUid))) {
	return TCL_OK;
    }

    resultObj = Tcl_NewObj();
    owned = Tcl_GetHashValue(vhPtr);
    owned = (const PhysOwned *)Tcl_GetHashValue(vhPtr);
    for (iPhys = 0; iPhys < PhysOwned_Size(owned); ++iPhys) {
	Tcl_ListObjAppendElement(NULL, resultObj, GetPatternObj(PhysOwned_Get(owned, iPhys)));
    }
    Tcl_SetObjResult(interp, resultObj);

    return TCL_OK;
}
3791
3792
3793
3794
3795
3796
3797
3798

3799
3800
3801
3802
3803
3804
3805
3806
3807
3808

3809
3810
3811
3812
3813
3814
3815
3858
3859
3860
3861
3862
3863
3864

3865
3866
3867
3868
3869
3870
3871
3872
3873
3874

3875
3876
3877
3878
3879
3880
3881
3882







-
+









-
+







static int
HandleEventGenerate(
    Tcl_Interp *interp,		/* Interp for errors return and name lookup. */
    Tk_Window mainWin,		/* Main window associated with interp. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    union { XEvent general; XVirtualEvent virtual; } event;
    union { XEvent general; XVirtualEvent virt; } event;

    const char *p;
    const char *name;
    const char *windowName;
    Tcl_QueuePosition pos;
    TkPattern pat;
    Tk_Window tkwin;
    Tk_Window tkwin2;
    TkWindow *mainPtr;
    EventMask eventMask;
    unsigned eventMask;
    Tcl_Obj *userDataObj;
    int synch;
    int warp;
    unsigned count;
    unsigned flags;
    int number;
    unsigned i;
3887
3888
3889
3890
3891
3892
3893
3894

3895
3896

3897
3898
3899
3900
3901

3902
3903
3904
3905
3906
3907
3908

3909
3910
3911
3912
3913
3914
3915
3954
3955
3956
3957
3958
3959
3960

3961
3962

3963
3964
3965
3966
3967

3968
3969
3970
3971
3972
3973
3974

3975
3976
3977
3978
3979
3980
3981
3982







-
+

-
+




-
+






-
+







    if (flags & DESTROY) {
	/*
	 * Event DestroyNotify should be generated by destroying the window.
	 */
	Tk_DestroyWindow(tkwin);
	return TCL_OK;
    }
    if (flags & KEY_BUTTON_MOTION_VIRTUAL) {
    if (flags & HAS_XKEY_HEAD_AND_STATE) {
	event.general.xkey.state = pat.modMask;
	if ((flags & KEY) && event.general.xany.type != MouseWheelEvent) {
	if (flags & KEY) {
	    TkpSetKeycodeAndState(tkwin, pat.info, &event.general);
	} else if (flags & BUTTON) {
	    event.general.xbutton.button = pat.info;
	} else if (flags & VIRTUAL) {
	    event.virtual.name = pat.name;
	    event.virt.name = pat.name;
	}
    }
    if (flags & (CREATE|UNMAP|MAP|REPARENT|CONFIG|GRAVITY|CIRC)) {
	event.general.xcreatewindow.window = event.general.xany.window;
    }

    if (flags & KEY_BUTTON_MOTION_CROSSING) {
    if (flags & HAS_XKEY_HEAD) {
	event.general.xkey.x_root = -1;
	event.general.xkey.y_root = -1;
    }

    if (event.general.xany.type == FocusIn || event.general.xany.type == FocusOut) {
	event.general.xany.send_event = GENERATED_FOCUS_EVENT_MAGIC;
    }
3949
3950
3951
3952
3953
3954
3955
3956

3957
3958
3959
3960
3961
3962
3963
4016
4017
4018
4019
4020
4021
4022

4023
4024
4025
4026
4027
4028
4029
4030







-
+







	}

	switch ((enum field) index) {
	case EVENT_WARP:
	    if (Tcl_GetBooleanFromObj(interp, valuePtr, &warp) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if (!(flags & KEY_BUTTON_MOTION_VIRTUAL)) {
	    if (!(flags & CAN_WARP)) {
		badOpt = 1;
	    }
	    break;
	case EVENT_WHEN:
	    pos = (Tcl_QueuePosition) TkFindStateNumObj(interp, optionPtr, queuePosition, valuePtr);
	    if ((int) pos < -1) {
		return TCL_ERROR;
3985
3986
3987
3988
3989
3990
3991



3992
3993
3994
3995
3996
3997
3998
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068







+
+
+







	    }
	    break;
	case EVENT_BUTTON:
	    if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if (flags & BUTTON) {
		if (number >= Button4) {
		    number += (Button8 - Button4);
		}
		event.general.xbutton.button = number;
	    } else {
		badOpt = 1;
	    }
	    break;
	case EVENT_COUNT:
	    if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) {
4016
4017
4018
4019
4020
4021
4022
4023
4024


4025
4026
4027
4028
4029
4030
4031
4086
4087
4088
4089
4090
4091
4092


4093
4094
4095
4096
4097
4098
4099
4100
4101







-
-
+
+







		badOpt = 1;
	    }
	    break;
	case EVENT_DELTA:
	    if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if ((flags & KEY) && event.general.xkey.type == MouseWheelEvent) {
		event.general.xkey.keycode = number;
	    if (flags & WHEEL) {
		event.general.xbutton.button = (unsigned)number; /* mis-use button field for this */
	    } else {
		badOpt = 1;
	    }
	    break;
	case EVENT_DETAIL:
	    number = TkFindStateNumObj(interp, optionPtr, notifyDetail, valuePtr);
	    if (number < 0) {
4061
4062
4063
4064
4065
4066
4067
4068

4069
4070
4071
4072
4073
4074
4075
4131
4132
4133
4134
4135
4136
4137

4138
4139
4140
4141
4142
4143
4144
4145







-
+







		badOpt = 1;
	    }
	    break;
	case EVENT_KEYCODE:
	    if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if ((flags & KEY) && event.general.xkey.type != MouseWheelEvent) {
	    if (flags & KEY) {
		event.general.xkey.keycode = number;
	    } else {
		badOpt = 1;
	    }
	    break;
	case EVENT_KEYSYM: {
	    KeySym keysym;
4085
4086
4087
4088
4089
4090
4091
4092

4093
4094
4095
4096
4097
4098
4099
4155
4156
4157
4158
4159
4160
4161

4162
4163
4164
4165
4166
4167
4168
4169







-
+








	    TkpSetKeycodeAndState(tkwin, keysym, &event.general);
	    if (event.general.xkey.keycode == 0) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf("no keycode for keysym \"%s\"", value));
		Tcl_SetErrorCode(interp, "TK", "LOOKUP", "KEYCODE", value, NULL);
		return TCL_ERROR;
	    }
	    if (!(flags & KEY) || (event.general.xkey.type == MouseWheelEvent)) {
	    if (!(flags & KEY)) {
		badOpt = 1;
	    }
	    break;
	}
	case EVENT_MODE:
	    if ((number = TkFindStateNumObj(interp, optionPtr, notifyMode, valuePtr)) < 0) {
		return TCL_ERROR;
4132
4133
4134
4135
4136
4137
4138
4139

4140
4141
4142
4143
4144
4145
4146
4147
4148
4149

4150
4151
4152
4153
4154
4155
4156
4157
4158
4159

4160
4161
4162
4163
4164
4165
4166
4202
4203
4204
4205
4206
4207
4208

4209
4210
4211
4212
4213
4214
4215
4216
4217
4218

4219
4220
4221
4222
4223
4224
4225
4226
4227
4228

4229
4230
4231
4232
4233
4234
4235
4236







-
+









-
+









-
+







		badOpt = 1;
	    }
	    break;
	case EVENT_ROOT:
	    if (!NameToWindow(interp, tkwin, valuePtr, &tkwin2)) {
		return TCL_ERROR;
	    }
	    if (flags & KEY_BUTTON_MOTION_CROSSING) {
	    if (flags & HAS_XKEY_HEAD) {
		event.general.xkey.root = Tk_WindowId(tkwin2);
	    } else {
		badOpt = 1;
	    }
	    break;
	case EVENT_ROOTX:
	    if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr, &number) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if (flags & KEY_BUTTON_MOTION_CROSSING) {
	    if (flags & HAS_XKEY_HEAD) {
		event.general.xkey.x_root = number;
	    } else {
		badOpt = 1;
	    }
	    break;
	case EVENT_ROOTY:
	    if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr, &number) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if (flags & KEY_BUTTON_MOTION_CROSSING) {
	    if (flags & HAS_XKEY_HEAD) {
		event.general.xkey.y_root = number;
	    } else {
		badOpt = 1;
	    }
	    break;
	case EVENT_SEND: {
	    const char *value;
4191
4192
4193
4194
4195
4196
4197
4198

4199
4200
4201
4202

4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220

4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234

4235
4236
4237
4238
4239
4240
4241
4261
4262
4263
4264
4265
4266
4267

4268
4269
4270
4271

4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289

4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303

4304
4305
4306
4307
4308
4309
4310
4311







-
+



-
+

















-
+













-
+







	case EVENT_SERIAL:
	    if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) {
		return TCL_ERROR;
	    }
	    event.general.xany.serial = number;
	    break;
	case EVENT_STATE:
	    if (flags & KEY_BUTTON_MOTION_CROSSING) {
	    if (flags & HAS_XKEY_HEAD) {
		if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) {
		    return TCL_ERROR;
		}
		if (flags & KEY_BUTTON_MOTION_VIRTUAL) {
		if (flags & HAS_XKEY_HEAD_AND_STATE) {
		    event.general.xkey.state = number;
		} else {
		    event.general.xcrossing.state = number;
		}
	    } else if (flags & VISIBILITY) {
		if ((number = TkFindStateNumObj(interp, optionPtr, visNotify, valuePtr)) < 0) {
		    return TCL_ERROR;
		}
		event.general.xvisibility.state = number;
	    } else {
		badOpt = 1;
	    }
	    break;
	case EVENT_SUBWINDOW:
	    if (!NameToWindow(interp, tkwin, valuePtr, &tkwin2)) {
		return TCL_ERROR;
	    }
	    if (flags & KEY_BUTTON_MOTION_CROSSING) {
	    if (flags & HAS_XKEY_HEAD) {
		event.general.xkey.subwindow = Tk_WindowId(tkwin2);
	    } else {
		badOpt = 1;
	    }
	    break;
	case EVENT_TIME: {
	    if (strcmp(Tcl_GetString(valuePtr), "current") == 0) {
		TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
		BindInfo *biPtr = mainPtr->mainPtr->bindInfo;
		number = dispPtr->lastEventTime + (CurrentTimeInMilliSecs() - biPtr->lastCurrentTime);
	    } else if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if (flags & KEY_BUTTON_MOTION_CROSSING) {
	    if (flags & HAS_XKEY_HEAD) {
		event.general.xkey.time = number;
	    } else if (flags & PROP) {
		event.general.xproperty.time = number;
	    } else {
		badOpt = 1;
	    }
	    break;
4262
4263
4264
4265
4266
4267
4268
4269

4270
4271
4272
4273
4274
4275
4276
4332
4333
4334
4335
4336
4337
4338

4339
4340
4341
4342
4343
4344
4345
4346







-
+







		badOpt = 1;
	    }
	    break;
	case EVENT_X:
	    if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr, &number) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if (flags & KEY_BUTTON_MOTION_CROSSING) {
	    if (flags & HAS_XKEY_HEAD) {
		event.general.xkey.x = number;

		/*
		 * Only modify rootx as well if it hasn't been changed.
		 */

		if (event.general.xkey.x_root == -1) {
4289
4290
4291
4292
4293
4294
4295
4296

4297
4298
4299
4300
4301
4302
4303
4359
4360
4361
4362
4363
4364
4365

4366
4367
4368
4369
4370
4371
4372
4373







-
+







		badOpt = 1;
	    }
	    break;
	case EVENT_Y:
	    if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr, &number) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if (flags & KEY_BUTTON_MOTION_CROSSING) {
	    if (flags & HAS_XKEY_HEAD) {
		event.general.xkey.y = number;

		/*
		 * Only modify rooty as well if it hasn't been changed.
		 */

		if (event.general.xkey.y_root == -1) {
4334
4335
4336
4337
4338
4339
4340
4341

4342
4343
4344
4345
4346
4347
4348
4404
4405
4406
4407
4408
4409
4410

4411
4412
4413
4414
4415
4416
4417
4418







-
+







	if (userDataObj) {
	    /*
	     * Must be virtual event to set that variable to non-NULL. Now we want
	     * to install the object into the event. Note that we must incr the
	     * refcount before firing it into the low-level event subsystem; the
	     * refcount will be decremented once the event has been processed.
	     */
	    event.virtual.user_data = userDataObj;
	    event.virt.user_data = userDataObj;
	    Tcl_IncrRefCount(userDataObj);
	}

	/*
	 * We only allow warping if the window is mapped.
	 */

4360
4361
4362
4363
4364
4365
4366








4367
4368
4369
4370





4371
4372
4373
4374
4375
4376
4377
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444




4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456







+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+







		}
		dispPtr->warpWindow = warpWindow;
	    }
	    dispPtr->warpMainwin = mainWin;
	    dispPtr->warpX = event.general.xmotion.x;
	    dispPtr->warpY = event.general.xmotion.y;

            /*
             * Warping with respect to a window will be done when Tk_handleEvent
             * below will run the event handlers and in particular TkPointerEvent.
             * This allows to make grabs and warping work together robustly, that
             * is without depending on a precise sequence of events.
             * Warping with respect to the whole screen (i.e. dispPtr->warpWindow
             * is NULL) is run directly here.
             */
	    if (!(dispPtr->flags & TK_DISPLAY_IN_WARP)) {
		Tcl_DoWhenIdle(DoWarp, dispPtr);
		dispPtr->flags |= TK_DISPLAY_IN_WARP;
	    }

            if (!dispPtr->warpWindow) {
                TkpWarpPointer(dispPtr);
                XForceScreenSaver(dispPtr->display, ScreenSaverReset);
            }
	}

	/*
	 * Now we have constructed the event, inject it into the event handling
	 * code.
	 */

4447
4448
4449
4450
4451
4452
4453
4454

4455
4456

4457
4458
4459
4460
4461
4462

4463
4464
4465
4466
4467
4468
4469



4470
4471

4472




4473


4474
4475
4476
4477
4478





4479
4480
4481


4482
4483
4484
4485
4486
4487




4488
4489
4490
4491


4492
4493
4494
4495
4496
4497
4498
4499
4500
4526
4527
4528
4529
4530
4531
4532

4533
4534

4535
4536
4537
4538
4539
4540

4541
4542
4543
4544
4545



4546
4547
4548
4549

4550
4551
4552
4553
4554
4555

4556
4557
4558




4559
4560
4561
4562
4563



4564
4565
4566





4567
4568
4569
4570




4571
4572
4573

4574
4575
4576
4577
4578
4579
4580







-
+

-
+





-
+




-
-
-
+
+
+

-
+

+
+
+
+
-
+
+

-
-
-
-
+
+
+
+
+
-
-
-
+
+

-
-
-
-
-
+
+
+
+
-
-
-
-
+
+

-







    *tkwinPtr = tkwin;
    return 1;
}

/*
 *-------------------------------------------------------------------------
 *
 * DoWarp --
 * TkDoWarpWrtWin --
 *
 *	Perform Warping of X pointer. Executed as an idle handler only.
 *	Perform warping of mouse pointer with respect to a window.
 *
 * Results:
 *	None
 *
 * Side effects:
 *	X Pointer will move to a new location.
 *	Mouse pointer moves to a new location.
 *
 *-------------------------------------------------------------------------
 */

static void
DoWarp(
    ClientData clientData)
void
TkDoWarpWrtWin(
    TkDisplay *dispPtr)
{
    TkDisplay *dispPtr = clientData;
    assert(dispPtr);

    /*
     * A NULL warpWindow means warping with respect to the whole screen.
     * We want to warp here only if we're warping with respect to a window.
     */
    assert(clientData);

    if (dispPtr->warpWindow) {

    /*
     * DoWarp was scheduled only if the window was mapped. It needs to be
     * still mapped at the time the present idle callback is executed. Also
     * one needs to guard against window destruction in the meantime.
        /*
         * Warping with respect to a window can only be done if the window is
         * mapped. This was checked in HandleEvent. The window needs to be
         * still mapped at the time the present code is executed. Also
         * one needs to guard against window destruction in the meantime,
     * Finally, the case warpWindow == NULL is special in that it means
     * the whole screen.
     */
         * which could have happened as a side effect of an event handler.
         */

    if (!dispPtr->warpWindow ||
            (Tk_IsMapped(dispPtr->warpWindow) && Tk_WindowId(dispPtr->warpWindow) != None)) {
        TkpWarpPointer(dispPtr);
        XForceScreenSaver(dispPtr->display, ScreenSaverReset);
    }
        if (Tk_IsMapped(dispPtr->warpWindow) && Tk_WindowId(dispPtr->warpWindow) != None) {
            TkpWarpPointer(dispPtr);
            XForceScreenSaver(dispPtr->display, ScreenSaverReset);
        }

    if (dispPtr->warpWindow) {
	Tcl_Release(dispPtr->warpWindow);
	dispPtr->warpWindow = NULL;
        Tcl_Release(dispPtr->warpWindow);
        dispPtr->warpWindow = NULL;
    }
    dispPtr->flags &= ~TK_DISPLAY_IN_WARP;
}

/*
 *-------------------------------------------------------------------------
 *
 * GetVirtualEventUid --
 *
4569
4570
4571
4572
4573
4574
4575
4576

4577
4578
4579
4580

4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595


4596
4597
4598
4599
4600
4601

4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613

4614
4615
4616
4617
4618
4619
4620
4649
4650
4651
4652
4653
4654
4655

4656
4657
4658
4659

4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673


4674
4675
4676
4677
4678
4679
4680

4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692

4693
4694
4695
4696
4697
4698
4699
4700







-
+



-
+













-
-
+
+





-
+











-
+







FindSequence(
    Tcl_Interp *interp,		/* Interpreter to use for error reporting. */
    LookupTables *lookupTables,	/* Tables used for lookup. */
    ClientData object,		/* For binding table, token for object with which binding is
    				 * associated. For virtual event table, NULL. */
    const char *eventString,	/* String description of pattern to match on. See user
    				 * documentation for details. */
    int create,		/* 0 means don't create the entry if it doesn't already exist.
    int create,			/* 0 means don't create the entry if it doesn't already exist.
    				 * 1 means create. */
    int allowVirtual,		/* 0 means that virtual events are not allowed in the sequence.
    				 * 1 otherwise. */
    EventMask *maskPtr)		/* *maskPtr is filled in with the event types on which this
    unsigned *maskPtr)		/* *maskPtr is filled in with the event types on which this
    				 * pattern sequence depends. */
{
    unsigned patsBufSize = 1;
    unsigned numPats;
    unsigned totalCount = 0;
    int virtualFound = 0;
    const char *p = eventString;
    TkPattern *patPtr;
    PatSeq *psPtr;
    Tcl_HashEntry *hPtr;
    int isNew;
    unsigned count;
    unsigned maxCount = 0;
    EventMask eventMask = 0;
    ModMask modMask = 0;
    unsigned eventMask = 0;
    unsigned modMask = 0;
    PatternTableKey key;

    assert(lookupTables);
    assert(eventString);

    psPtr = ckalloc(PATSEQ_MEMSIZE(patsBufSize));
    psPtr = (PatSeq *)ckalloc(PATSEQ_MEMSIZE(patsBufSize));

    /*
     *------------------------------------------------------------------
     * Step 1: parse the pattern string to produce an array of Patterns.
     *------------------------------------------------------------------
     */

    for (patPtr = psPtr->pats, numPats = 0; *(p = SkipSpaces(p)); ++patPtr, ++numPats) {
	if (numPats >= patsBufSize) {
	    unsigned pos = patPtr - psPtr->pats;
	    patsBufSize += patsBufSize;
	    psPtr = ckrealloc(psPtr, PATSEQ_MEMSIZE(patsBufSize));
	    psPtr = (PatSeq *)ckrealloc(psPtr, PATSEQ_MEMSIZE(patsBufSize));
	    patPtr = psPtr->pats + pos;
	}

	if ((count = ParseEventDescription(interp, &p, patPtr, &eventMask)) == 0) {
	    /* error encountered */
	    ckfree(psPtr);
	    return NULL;
4655
4656
4657
4658
4659
4660
4661
4662

4663
4664
4665
4666

4667
4668
4669
4670
4671
4672
4673

4674
4675
4676
4677
4678
4679
4680
4735
4736
4737
4738
4739
4740
4741

4742
4743
4744
4745

4746
4747
4748
4749
4750
4751
4752

4753
4754
4755
4756
4757
4758
4759
4760







-
+



-
+






-
+







    if (numPats > 1u && virtualFound) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("virtual events may not be composed", -1));
	Tcl_SetErrorCode(interp, "TK", "EVENT", "VIRTUAL", "COMPOSITION", NULL);
	ckfree(psPtr);
	return NULL;
    }
    if (patsBufSize > numPats) {
	psPtr = ckrealloc(psPtr, PATSEQ_MEMSIZE(numPats));
	psPtr = (PatSeq *)ckrealloc(psPtr, PATSEQ_MEMSIZE(numPats));
    }

    patPtr = psPtr->pats;
    psPtr->object = object;
    psPtr->object = (Tcl_Obj *)object;
    SetupPatternKey(&key, psPtr);
    hPtr = Tcl_CreateHashEntry(&lookupTables->patternTable, (char *) &key, &isNew);
    if (!isNew) {
	unsigned sequenceSize = numPats*sizeof(TkPattern);
	PatSeq *psPtr2;

	for (psPtr2 = Tcl_GetHashValue(hPtr); psPtr2; psPtr2 = psPtr2->nextSeqPtr) {
	for (psPtr2 = (PatSeq *)Tcl_GetHashValue(hPtr); psPtr2; psPtr2 = psPtr2->nextSeqPtr) {
	    assert(TEST_PSENTRY(psPtr2));
	    if (numPats == psPtr2->numPats && memcmp(patPtr, psPtr2->pats, sequenceSize) == 0) {
		ckfree(psPtr);
		if (maskPtr) {
		    *maskPtr = eventMask;
		}
		return psPtr2;
4702
4703
4704
4705
4706
4707
4708
4709

4710
4711
4712
4713
4714
4715
4716
4782
4783
4784
4785
4786
4787
4788

4789
4790
4791
4792
4793
4794
4795
4796







-
+








    psPtr->numPats = numPats;
    psPtr->count = totalCount;
    psPtr->number = lookupTables->number++;
    psPtr->added = 0;
    psPtr->modMaskUsed = (modMask != 0);
    psPtr->script = NULL;
    psPtr->nextSeqPtr = Tcl_GetHashValue(hPtr);
    psPtr->nextSeqPtr = (PatSeq *)Tcl_GetHashValue(hPtr);
    psPtr->hPtr = hPtr;
    psPtr->ptr.nextObj = NULL;
    assert(psPtr->ptr.owners == NULL);
    DEBUG(psPtr->owned = 0;)
    Tcl_SetHashValue(hPtr, psPtr);

    if (maskPtr) {
4762
4763
4764
4765
4766
4767
4768
4769

4770
4771
4772

4773
4774
4775
4776
4777
4778
4779
4842
4843
4844
4845
4846
4847
4848

4849
4850
4851

4852
4853
4854
4855
4856
4857
4858
4859







-
+


-
+








static unsigned
ParseEventDescription(
    Tcl_Interp *interp,		/* For error messages. */
    const char **eventStringPtr,/* On input, holds a pointer to start of event string. On exit,
    				 * gets pointer to rest of string after parsed event. */
    TkPattern *patPtr,		/* Filled with the pattern parsed from the event string. */
    EventMask *eventMaskPtr)	/* Filled with event mask of matched event. */
    unsigned *eventMaskPtr)	/* Filled with event mask of matched event. */
{
    const char *p;
    EventMask eventMask = 0;
    unsigned eventMask = 0;
    unsigned count = 1;

    assert(eventStringPtr);
    assert(patPtr);
    assert(eventMaskPtr);

    p = *eventStringPtr;
4844
4845
4846
4847
4848
4849
4850
4851

4852
4853
4854
4855
4856
4857
4858
4924
4925
4926
4927
4928
4929
4930

4931
4932
4933
4934
4935
4936
4937
4938







-
+







			interp,
			patPtr, 0,
			Tcl_NewStringObj("missing \">\" in virtual binding", -1), "MALFORMED");
	    }

	    size = p - field;
	    if (size >= sizeof(buf)) {
		bufPtr = ckalloc(size + 1);
		bufPtr = (char *)ckalloc(size + 1);
	    }
	    strncpy(bufPtr, field, size);
	    bufPtr[size] = '\0';
	    eventMask = VirtualEventMask;
	    patPtr->eventType = VirtualEvent;
	    patPtr->name = Tk_GetUid(bufPtr);
	    if (bufPtr != buf) {
4876
4877
4878
4879
4880
4881
4882
4883

4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898

4899
4900
4901
4902
4903
4904
4905
4956
4957
4958
4959
4960
4961
4962

4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977

4978
4979
4980
4981
4982
4983
4984
4985







-
+














-
+







		     */

		     break;
		}
		if (!(hPtr = Tcl_FindHashEntry(&modTable, field))) {
		    break;
		}
		modPtr = Tcl_GetHashValue(hPtr);
		modPtr = (ModInfo *)Tcl_GetHashValue(hPtr);
		patPtr->modMask |= modPtr->mask;
		if (modPtr->flags & MULT_CLICKS) {
		    unsigned i = modPtr->flags & MULT_CLICKS;

		    count = 2;
		    while (i >>= 1) {
			++count;
		    }
		}
		p = SkipFieldDelims(p);
	    }

	    eventFlags = 0;
	    if ((hPtr = Tcl_FindHashEntry(&eventTable, field))) {
		const EventInfo *eiPtr = Tcl_GetHashValue(hPtr);
		const EventInfo *eiPtr = (const EventInfo *)Tcl_GetHashValue(hPtr);

		patPtr->eventType = eiPtr->type;
		eventFlags = flagArray[eiPtr->type];
		eventMask = eiPtr->eventMask;
		p = GetField(SkipFieldDelims(p), field, sizeof(field));
	    }
	    if (*field) {
4938
4939
4940
4941
4942
4943
4944
4945

4946
4947
4948
4949
4950
4951
4952
4953
4954
4955

4956
4957
4958
4959
4960
4961
4962
5018
5019
5020
5021
5022
5023
5024

5025
5026
5027
5028
5029
5030
5031
5032
5033
5034

5035
5036
5037
5038
5039
5040
5041
5042







-
+









-
+







			return FinalizeParseEventDescription(
				interp,
				patPtr, 0,
				Tcl_ObjPrintf("specified button \"%s\" for non-button event", field),
				"NON_BUTTON");
		    }
#if SUPPORT_ADDITIONAL_MOTION_SYNTAX
		    patPtr->modMask |= TkGetButtonMask(button);
		    patPtr->modMask |= Tk_GetButtonMask(button);
		    p = SkipFieldDelims(p);
		    while (*p && *p != '>') {
			p = SkipFieldDelims(GetField(p, field, sizeof(field)));
			if ((button = GetButtonNumber(field)) == 0) {
			    return FinalizeParseEventDescription(
				    interp,
				    patPtr, 0,
				    Tcl_ObjPrintf("bad button number \"%s\"", field), "BUTTON");
			}
			patPtr->modMask |= TkGetButtonMask(button);
			patPtr->modMask |= Tk_GetButtonMask(button);
		    }
		    patPtr->info = ButtonNumberFromState(patPtr->modMask);
#endif
		} else {
		    return FinalizeParseEventDescription(
			    interp,
			    patPtr, 0,
5078
5079
5080
5081
5082
5083
5084
5085

5086
5087
5088
5089
5090
5091
5092
5158
5159
5160
5161
5162
5163
5164

5165
5166
5167
5168
5169
5170
5171
5172







-
+







		&& patPtr->info != ' ') {
	    char c = (char) patPtr->info;
	    Tcl_AppendToObj(patternObj, &c, 1);
	} else if (patPtr->eventType == VirtualEvent) {
	    assert(patPtr->name);
	    Tcl_AppendPrintfToObj(patternObj, "<<%s>>", patPtr->name);
	} else {
	    ModMask modMask;
	    unsigned modMask;
	    const ModInfo *modPtr;

	    /*
	     * It's a more general event specification. First check for "Double",
	     * "Triple", "Quadruple", then modifiers, then event type, then keysym
	     * or button detail.
	     */
5126
5127
5128
5129
5130
5131
5132
5133
5134


5135
5136
5137
5138

5139
5140
5141
5142


5143
5144
5145
5146
5147
5148
5149
5206
5207
5208
5209
5210
5211
5212


5213
5214
5215
5216
5217

5218
5219
5220


5221
5222
5223
5224
5225
5226
5227
5228
5229







-
-
+
+



-
+


-
-
+
+







			Tcl_AppendToObj(patternObj, "-", 1);
			Tcl_AppendToObj(patternObj, string, -1);
		    }
		    break;
		}
		case ButtonPress:
		case ButtonRelease:
		    assert(patPtr->info <= Button5);
		    Tcl_AppendPrintfToObj(patternObj, "-%d", (int) patPtr->info);
		    assert(patPtr->info <= 13);
		    Tcl_AppendPrintfToObj(patternObj, "-%u", (unsigned) ((patPtr->info > 7) ? (patPtr->info - 4) : patPtr->info));
		    break;
#if PRINT_SHORT_MOTION_SYNTAX
		case MotionNotify: {
		    ModMask mask = patPtr->modMask;
		    unsigned mask = patPtr->modMask;
		    while (mask & ALL_BUTTONS) {
			unsigned button = ButtonNumberFromState(mask);
			Tcl_AppendPrintfToObj(patternObj, "-%u", button);
			mask &= ~TkGetButtonMask(button);
			Tcl_AppendPrintfToObj(patternObj, "-%u", (button > 7) ? (button - 4) : button);
			mask &= ~Tk_GetButtonMask(button);
		    }
		    break;
		}
#endif
		}
	    }

5172
5173
5174
5175
5176
5177
5178
5179



5180

































5181
5182
5183
5184

5185
5186

5187
5188
5189
5190
5191
5192
5193
5252
5253
5254
5255
5256
5257
5258

5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298

5299


5300
5301
5302
5303
5304
5305
5306
5307







-
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
+
-
-
+







 */

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 (((unsigned)(name[0]-1) < 0x7F) && !name[1]) {
    if (strlen(name) == 1u) {
	KeySym keysym = (KeySym) (unsigned char) name[0];
	keysym = (unsigned char) name[0];

	if (TkKeysymToString(keysym)) {
	    return keysym;
	}
    }
#endif /* REDO_KEYSYM_LOOKUP */
    assert(name);
5212
5213
5214
5215
5216
5217
5218
5219


5220























5221
5222

5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5326
5327
5328
5329
5330
5331
5332

5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359

5360
5361
5362
5363



5364
5365
5366
5367
5368
5369
5370







-
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+



-
-
-







 */

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 Tcl_GetHashValue(hPtr);
	return (const char *)Tcl_GetHashValue(hPtr);
    }
#endif /* REDO_KEYSYM_LOOKUP */

    if (keysym > (KeySym)0x1008FFFF) {
	return NULL;
    }
    return XKeysymToString(keysym);
}

/*
 *----------------------------------------------------------------------
 *
 * TkpGetBindingXEvent --
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5388
5389
5390
5391
5392
5393
5394





























5395
5396
5397
5398
5399
5400
5401







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







    Tcl_Interp *interp)		/* Interpreter. */
{
    TkWindow *winPtr = (TkWindow *) Tk_MainWindow(interp);
    BindingTable *bindPtr = winPtr->mainPtr->bindingTable;

    return &bindPtr->curEvent->xev;
}

/*
 *----------------------------------------------------------------------
 *
 * TkpCancelWarp --
 *
 *	This function cancels an outstanding pointer warp and
 *	is called during tear down of the display.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void
TkpCancelWarp(
    TkDisplay *dispPtr)
{
    assert(dispPtr);

    if (dispPtr->flags & TK_DISPLAY_IN_WARP) {
	Tcl_CancelIdleCall(DoWarp, dispPtr);
	dispPtr->flags &= ~TK_DISPLAY_IN_WARP;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TkpDumpPS --
 *
 *	Dump given pattern sequence to stdout.
Changes to generic/tkBitmap.c.
1
2
3
4
5
6
7
8
9


10
11
12
13
14
15
16
1
2
3
4
5
6
7


8
9
10
11
12
13
14
15
16







-
-
+
+







/*
 * tkBitmap.c --
 *
 *	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.
 */

#include "tkInt.h"

163
164
165
166
167
168
169
170

171
172
173
174
175
176
177
163
164
165
166
167
168
169

170
171
172
173
174
175
176
177







-
+







				 * for legal syntax of string value. */
{
    TkBitmap *bitmapPtr;

    if (objPtr->typePtr != &tkBitmapObjType) {
	InitBitmapObj(objPtr);
    }
    bitmapPtr = objPtr->internalRep.twoPtrValue.ptr1;
    bitmapPtr = (TkBitmap *)objPtr->internalRep.twoPtrValue.ptr1;

    /*
     * If the object currently points to a TkBitmap, see if it's the one we
     * want. If so, increment its reference count and return.
     */

    if (bitmapPtr != NULL) {
193
194
195
196
197
198
199
200

201
202
203
204
205
206
207
193
194
195
196
197
198
199

200
201
202
203
204
205
206
207







-
+







    /*
     * The object didn't point to the TkBitmap that we wanted. Search the list
     * of TkBitmaps with the same name to see if one of the others is the
     * right one.
     */

    if (bitmapPtr != NULL) {
	TkBitmap *firstBitmapPtr = Tcl_GetHashValue(bitmapPtr->nameHashPtr);
	TkBitmap *firstBitmapPtr = (TkBitmap *)Tcl_GetHashValue(bitmapPtr->nameHashPtr);

	FreeBitmapObj(objPtr);
	for (bitmapPtr = firstBitmapPtr; bitmapPtr != NULL;
		bitmapPtr = bitmapPtr->nextPtr) {
	    if ((Tk_Display(tkwin) == bitmapPtr->display) &&
		    (Tk_ScreenNumber(tkwin) == bitmapPtr->screenNum)) {
		bitmapPtr->resourceRefCount++;
303
304
305
306
307
308
309
310

311
312
313
314
315
316
317
318
319
320

321
322
323
324
325
326
327
303
304
305
306
307
308
309

310
311
312
313
314
315
316
317
318
319

320
321
322
323
324
325
326
327







-
+









-
+







{
    Tcl_HashEntry *nameHashPtr, *predefHashPtr;
    TkBitmap *bitmapPtr, *existingBitmapPtr;
    TkPredefBitmap *predefPtr;
    Pixmap bitmap;
    int isNew, width = 0, height = 0, dummy2;
    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (!dispPtr->bitmapInit) {
	BitmapInit(dispPtr);
    }

    nameHashPtr = Tcl_CreateHashEntry(&dispPtr->bitmapNameTable, string,
	    &isNew);
    if (!isNew) {
	existingBitmapPtr = Tcl_GetHashValue(nameHashPtr);
	existingBitmapPtr = (TkBitmap *)Tcl_GetHashValue(nameHashPtr);
	for (bitmapPtr = existingBitmapPtr; bitmapPtr != NULL;
		bitmapPtr = bitmapPtr->nextPtr) {
	    if ((Tk_Display(tkwin) == bitmapPtr->display) &&
		    (Tk_ScreenNumber(tkwin) == bitmapPtr->screenNum)) {
		bitmapPtr->resourceRefCount++;
		return bitmapPtr;
	    }
391
392
393
394
395
396
397
398

399
400
401
402
403
404
405
406
407
408
409
410

411
412
413
414
415
416
417
418
419

420
421
422
423
424
425
426
391
392
393
394
395
396
397

398
399
400
401
402
403
404
405
406
407
408
409

410
411
412
413
414
415
416
417
418

419
420
421
422
423
424
425
426







-
+











-
+








-
+







			    "bitmap \"%s\" not defined", string));
		    Tcl_SetErrorCode(interp, "TK", "LOOKUP", "BITMAP", string,
			    NULL);
		}
		goto error;
	    }
	} else {
	    predefPtr = Tcl_GetHashValue(predefHashPtr);
	    predefPtr = (TkPredefBitmap *)Tcl_GetHashValue(predefHashPtr);
	    width = predefPtr->width;
	    height = predefPtr->height;
	    if (predefPtr->native) {
		bitmap = TkpCreateNativeBitmap(Tk_Display(tkwin),
		    predefPtr->source);
		if (bitmap == None) {
		    Tcl_Panic("native bitmap creation failed");
		}
	    } else {
		bitmap = XCreateBitmapFromData(Tk_Display(tkwin),
			RootWindowOfScreen(Tk_Screen(tkwin)),
			predefPtr->source, (unsigned)width, (unsigned)height);
			(const char *)predefPtr->source, (unsigned)width, (unsigned)height);
	    }
	}
    }

    /*
     * Add information about this bitmap to our database.
     */

    bitmapPtr = ckalloc(sizeof(TkBitmap));
    bitmapPtr = (TkBitmap *)ckalloc(sizeof(TkBitmap));
    bitmapPtr->bitmap = bitmap;
    bitmapPtr->width = width;
    bitmapPtr->height = height;
    bitmapPtr->display = Tk_Display(tkwin);
    bitmapPtr->screenNum = Tk_ScreenNumber(tkwin);
    bitmapPtr->resourceRefCount = 1;
    bitmapPtr->objRefCount = 0;
470
471
472
473
474
475
476
477

478
479
480
481
482
483
484
470
471
472
473
474
475
476

477
478
479
480
481
482
483
484







-
+







    const void *source,		/* Address of bits for bitmap. */
    int width,			/* Width of bitmap. */
    int height)			/* Height of bitmap. */
{
    int isNew;
    Tcl_HashEntry *predefHashPtr;
    TkPredefBitmap *predefPtr;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    /*
     * Initialize the Bitmap module if not initialized already for this
     * thread. Since the current TkDisplay structure cannot be introspected
     * from here, pass a NULL pointer to BitmapInit, which will know to
     * initialize only the data in the ThreadSpecificData structure for the
493
494
495
496
497
498
499
500

501
502
503
504
505
506
507
493
494
495
496
497
498
499

500
501
502
503
504
505
506
507







-
+







	    name, &isNew);
    if (!isNew) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"bitmap \"%s\" is already defined", name));
	Tcl_SetErrorCode(interp, "TK", "BITMAP", "EXISTS", NULL);
	return TCL_ERROR;
    }
    predefPtr = ckalloc(sizeof(TkPredefBitmap));
    predefPtr = (TkPredefBitmap *)ckalloc(sizeof(TkPredefBitmap));
    predefPtr->source = source;
    predefPtr->width = width;
    predefPtr->height = height;
    predefPtr->native = 0;
    Tcl_SetHashValue(predefHashPtr, predefPtr);
    return TCL_OK;
}
532
533
534
535
536
537
538
539

540
541
542
543

544
545
546
547
548
549
550
532
533
534
535
536
537
538

539
540
541
542

543
544
545
546
547
548
549
550







-
+



-
+







    TkDisplay *dispPtr = TkGetDisplay(display);

    if (dispPtr == NULL || !dispPtr->bitmapInit) {
    unknown:
	Tcl_Panic("Tk_NameOfBitmap received unknown bitmap argument");
    }

    idHashPtr = Tcl_FindHashEntry(&dispPtr->bitmapIdTable, (char *) bitmap);
    idHashPtr = Tcl_FindHashEntry(&dispPtr->bitmapIdTable, bitmap);
    if (idHashPtr == NULL) {
	goto unknown;
    }
    bitmapPtr = Tcl_GetHashValue(idHashPtr);
    bitmapPtr = (TkBitmap *)Tcl_GetHashValue(idHashPtr);
    return bitmapPtr->nameHashPtr->key.string;
}

/*
 *--------------------------------------------------------------
 *
 * Tk_SizeOfBitmap --
574
575
576
577
578
579
580
581

582
583
584
585

586
587
588
589
590
591
592
574
575
576
577
578
579
580

581
582
583
584

585
586
587
588
589
590
591
592







-
+



-
+







    TkDisplay *dispPtr = TkGetDisplay(display);

    if (!dispPtr->bitmapInit) {
    unknownBitmap:
	Tcl_Panic("Tk_SizeOfBitmap received unknown bitmap argument");
    }

    idHashPtr = Tcl_FindHashEntry(&dispPtr->bitmapIdTable, (char *) bitmap);
    idHashPtr = Tcl_FindHashEntry(&dispPtr->bitmapIdTable, bitmap);
    if (idHashPtr == NULL) {
	goto unknownBitmap;
    }
    bitmapPtr = Tcl_GetHashValue(idHashPtr);
    bitmapPtr = (TkBitmap *)Tcl_GetHashValue(idHashPtr);
    *widthPtr = bitmapPtr->width;
    *heightPtr = bitmapPtr->height;
}

/*
 *----------------------------------------------------------------------
 *
608
609
610
611
612
613
614
615
616

617
618
619
620
621
622

623
624
625
626
627
628
629
608
609
610
611
612
613
614


615
616
617
618
619
620

621
622
623
624
625
626
627
628







-
-
+





-
+








static void
FreeBitmap(
    TkBitmap *bitmapPtr)	/* Bitmap to be released. */
{
    TkBitmap *prevPtr;

    bitmapPtr->resourceRefCount--;
    if (bitmapPtr->resourceRefCount > 0) {
    if (bitmapPtr->resourceRefCount-- > 1) {
	return;
    }

    Tk_FreePixmap(bitmapPtr->display, bitmapPtr->bitmap);
    Tcl_DeleteHashEntry(bitmapPtr->idHashPtr);
    prevPtr = Tcl_GetHashValue(bitmapPtr->nameHashPtr);
    prevPtr = (TkBitmap *)Tcl_GetHashValue(bitmapPtr->nameHashPtr);
    if (prevPtr == bitmapPtr) {
	if (bitmapPtr->nextPtr == NULL) {
	    Tcl_DeleteHashEntry(bitmapPtr->nameHashPtr);
	} else {
	    Tcl_SetHashValue(bitmapPtr->nameHashPtr, bitmapPtr->nextPtr);
	}
    } else {
663
664
665
666
667
668
669
670

671
672
673
674

675
676
677
678
679
680
681
662
663
664
665
666
667
668

669
670
671
672

673
674
675
676
677
678
679
680







-
+



-
+







    Tcl_HashEntry *idHashPtr;
    TkDisplay *dispPtr = TkGetDisplay(display);

    if (!dispPtr->bitmapInit) {
	Tcl_Panic("Tk_FreeBitmap called before Tk_GetBitmap");
    }

    idHashPtr = Tcl_FindHashEntry(&dispPtr->bitmapIdTable, (char *) bitmap);
    idHashPtr = Tcl_FindHashEntry(&dispPtr->bitmapIdTable, bitmap);
    if (idHashPtr == NULL) {
	Tcl_Panic("Tk_FreeBitmap received unknown bitmap argument");
    }
    FreeBitmap(Tcl_GetHashValue(idHashPtr));
    FreeBitmap((TkBitmap *)Tcl_GetHashValue(idHashPtr));
}

/*
 *----------------------------------------------------------------------
 *
 * Tk_FreeBitmapFromObj --
 *
731
732
733
734
735
736
737
738

739
740
741
742
743
744
745
730
731
732
733
734
735
736

737
738
739
740
741
742
743
744







-
+







    objPtr->typePtr = NULL;
}

static void
FreeBitmapObj(
    Tcl_Obj *objPtr)		/* The object we are releasing. */
{
    TkBitmap *bitmapPtr = objPtr->internalRep.twoPtrValue.ptr1;
    TkBitmap *bitmapPtr = (TkBitmap *)objPtr->internalRep.twoPtrValue.ptr1;

    if (bitmapPtr != NULL) {
	bitmapPtr->objRefCount--;
	if ((bitmapPtr->objRefCount == 0)
		&& (bitmapPtr->resourceRefCount == 0)) {
	    ckfree(bitmapPtr);
	}
766
767
768
769
770
771
772
773

774
775
776
777
778
779
780
765
766
767
768
769
770
771

772
773
774
775
776
777
778
779







-
+







 */

static void
DupBitmapObjProc(
    Tcl_Obj *srcObjPtr,		/* The object we are copying from. */
    Tcl_Obj *dupObjPtr)		/* The object we are copying to. */
{
    TkBitmap *bitmapPtr = srcObjPtr->internalRep.twoPtrValue.ptr1;
    TkBitmap *bitmapPtr = (TkBitmap *)srcObjPtr->internalRep.twoPtrValue.ptr1;

    dupObjPtr->typePtr = srcObjPtr->typePtr;
    dupObjPtr->internalRep.twoPtrValue.ptr1 = bitmapPtr;

    if (bitmapPtr != NULL) {
	bitmapPtr->objRefCount++;
    }
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823

824
825
826
827
828
829
830

831
832
833
834
835
836

837
838
839
840
841
842
843
801
802
803
804
805
806
807

808
809
810
811
812
813
814
815
816
817
818
819
820

821
822
823
824
825
826
827

828
829
830
831
832
833

834
835
836
837
838
839
840
841







-













-
+






-
+





-
+







 *	For each call to this function, there should eventually be a call to
 *	Tk_FreeBitmap, so that the database can be cleaned up when bitmaps
 *	aren't needed anymore.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
Pixmap
Tk_GetBitmapFromData(
    Tcl_Interp *interp,		/* Interpreter to use for error reporting. */
    Tk_Window tkwin,		/* Window in which bitmap will be used. */
    const void *source,		/* Bitmap data for bitmap shape. */
    int width, int height)	/* Dimensions of bitmap. */
{
    DataKey nameKey;
    Tcl_HashEntry *dataHashPtr;
    int isNew;
    char string[16 + TCL_INTEGER_SPACE];
    char *name;
    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (!tsdPtr->initialized) {
	BitmapInit(dispPtr);
    }

    nameKey.source = source;
    nameKey.source = (const char *)source;
    nameKey.width = width;
    nameKey.height = height;
    dataHashPtr = Tcl_CreateHashEntry(&dispPtr->bitmapDataTable,
	    (char *) &nameKey, &isNew);
    if (!isNew) {
	name = Tcl_GetHashValue(dataHashPtr);
	name = (char *)Tcl_GetHashValue(dataHashPtr);
    } else {
	dispPtr->bitmapAutoNumber++;
	sprintf(string, "_tk%d", dispPtr->bitmapAutoNumber);
	name = string;
	Tcl_SetHashValue(dataHashPtr, name);
	if (Tk_DefineBitmap(interp, name, source, width, height) != TCL_OK) {
	    Tcl_DeleteHashEntry(dataHashPtr);
907
908
909
910
911
912
913
914

915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935

936
937
938
939
940
941
942
905
906
907
908
909
910
911

912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932

933
934
935
936
937
938
939
940







-
+




















-
+







    Tcl_HashEntry *hashPtr;
    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;

    if (objPtr->typePtr != &tkBitmapObjType) {
	InitBitmapObj(objPtr);
    }

    bitmapPtr = objPtr->internalRep.twoPtrValue.ptr1;
    bitmapPtr = (TkBitmap *)objPtr->internalRep.twoPtrValue.ptr1;
    if (bitmapPtr != NULL) {
	if ((bitmapPtr->resourceRefCount > 0)
		&& (Tk_Display(tkwin) == bitmapPtr->display)) {
	    return bitmapPtr;
	}
	hashPtr = bitmapPtr->nameHashPtr;
	FreeBitmapObj(objPtr);
    } else {
	hashPtr = Tcl_FindHashEntry(&dispPtr->bitmapNameTable,
		Tcl_GetString(objPtr));
	if (hashPtr == NULL) {
	    goto error;
	}
    }

    /*
     * At this point we've got a hash table entry, off of which hang one or
     * more TkBitmap structures. See if any of them will work.
     */

    for (bitmapPtr = Tcl_GetHashValue(hashPtr); bitmapPtr != NULL;
    for (bitmapPtr = (TkBitmap *)Tcl_GetHashValue(hashPtr); bitmapPtr != NULL;
	    bitmapPtr = bitmapPtr->nextPtr) {
	if (Tk_Display(tkwin) == bitmapPtr->display) {
	    objPtr->internalRep.twoPtrValue.ptr1 = bitmapPtr;
	    bitmapPtr->objRefCount++;
	    return bitmapPtr;
	}
    }
1008
1009
1010
1011
1012
1013
1014
1015

1016
1017
1018
1019
1020
1021
1022
1006
1007
1008
1009
1010
1011
1012

1013
1014
1015
1016
1017
1018
1019
1020







-
+







static void
BitmapInit(
    TkDisplay *dispPtr)		/* TkDisplay structure encapsulating
				 * thread-specific data used by this module,
				 * or NULL if unavailable. */
{
    Tcl_Interp *dummy;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    /*
     * First initialize the data in the ThreadSpecificData strucuture, if
     * needed.
     */

1146
1147
1148
1149
1150
1151
1152
1153

1154
1155
1156
1157
1158
1159
1160

1161
1162

1163
1164
1165
1166
1167
1168
1169
1144
1145
1146
1147
1148
1149
1150

1151
1152
1153
1154
1155
1156
1157

1158
1159

1160
1161
1162
1163
1164
1165
1166
1167







-
+






-
+

-
+







    Tcl_HashEntry *hashPtr;
    Tcl_Obj *resultPtr, *objPtr;
    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;

    resultPtr = Tcl_NewObj();
    hashPtr = Tcl_FindHashEntry(&dispPtr->bitmapNameTable, name);
    if (hashPtr != NULL) {
	bitmapPtr = Tcl_GetHashValue(hashPtr);
	bitmapPtr = (TkBitmap *)Tcl_GetHashValue(hashPtr);
	if (bitmapPtr == NULL) {
	    Tcl_Panic("TkDebugBitmap found empty hash table entry");
	}
	for ( ; (bitmapPtr != NULL); bitmapPtr = bitmapPtr->nextPtr) {
	    objPtr = Tcl_NewObj();
	    Tcl_ListObjAppendElement(NULL, objPtr,
		    Tcl_NewIntObj(bitmapPtr->resourceRefCount));
		    Tcl_NewWideIntObj(bitmapPtr->resourceRefCount));
	    Tcl_ListObjAppendElement(NULL, objPtr,
		    Tcl_NewIntObj(bitmapPtr->objRefCount));
		    Tcl_NewWideIntObj(bitmapPtr->objRefCount));
	    Tcl_ListObjAppendElement(NULL, resultPtr, objPtr);
	}
    }
    return resultPtr;
}

/*
1186
1187
1188
1189
1190
1191
1192
1193

1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1184
1185
1186
1187
1188
1189
1190

1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203







-
+












 *
 *----------------------------------------------------------------------
 */

Tcl_HashTable *
TkGetBitmapPredefTable(void)
{
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    return &tsdPtr->predefBitmapTable;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Changes to generic/tkBusy.c.
19
20
21
22
23
24
25
26

27
28
29
30
31
32
33
19
20
21
22
23
24
25

26
27
28
29
30
31
32
33







-
+







/*
 * Things about the busy system that may be configured. Note that on some
 * platforms this may or may not have an effect.
 */

static const Tk_OptionSpec busyOptionSpecs[] = {
    {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
	DEF_BUSY_CURSOR, -1, Tk_Offset(Busy, cursor),
	DEF_BUSY_CURSOR, TCL_INDEX_NONE, offsetof(Busy, cursor),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0}
};

/*
 * Forward declarations of functions defined in this file.
 */
50
51
52
53
54
55
56
57

58
59
60
61
62
63
64
50
51
52
53
54
55
56

57
58
59
60
61
62
63
64







-
+







static int		HoldBusy(Tcl_HashTable *busyTablePtr,
			    Tcl_Interp *interp, Tcl_Obj *const windowObj,
			    int configObjc, Tcl_Obj *const configObjv[]);
static void		MakeTransparentWindowExist(Tk_Window tkwin,
			    Window parent);
static inline Tk_Window	NextChild(Tk_Window tkwin);
static void		RefWinEventProc(ClientData clientData,
			    register XEvent *eventPtr);
			    XEvent *eventPtr);
static inline void	SetWindowInstanceData(Tk_Window tkwin,
			    ClientData instanceData);

/*
 * The "busy" geometry manager definition.
 */

118
119
120
121
122
123
124
125
126
127
128
129

130
131

132
133
134
135
136
137
138
118
119
120
121
122
123
124

125
126
127

128
129

130
131
132
133
134
135
136
137







-



-
+

-
+







 *
 * Side effects:
 *	The Busy structure is freed at the next idle point.
 *
 *----------------------------------------------------------------------
 */

/* ARGSUSED */
static void
BusyCustodyProc(
    ClientData clientData,	/* Information about the busy window. */
    Tk_Window tkwin)		/* Not used. */
    TCL_UNUSED(Tk_Window))		/* Not used. */
{
    Busy *busyPtr = clientData;
    Busy *busyPtr = (Busy *)clientData;

    Tk_DeleteEventHandler(busyPtr->tkBusy, StructureNotifyMask, BusyEventProc,
	    busyPtr);
    TkpHideBusyWindow(busyPtr);
    busyPtr->tkBusy = NULL;
    Tcl_EventuallyFree(busyPtr, (Tcl_FreeProc *)DestroyBusy);
}
152
153
154
155
156
157
158
159
160
161
162

163
164

165
166
167
168
169
170
171
151
152
153
154
155
156
157

158
159

160
161

162
163
164
165
166
167
168
169







-


-
+

-
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

/* ARGSUSED */
static void
BusyGeometryProc(
    ClientData clientData,	/* Information about window that got new
    TCL_UNUSED(void *),	/* Information about window that got new
				 * preferred geometry. */
    Tk_Window tkwin)		/* Other Tk-related information about the
    TCL_UNUSED(Tk_Window))		/* Other Tk-related information about the
				 * window. */
{
    /* Should never get here */
}

/*
 *----------------------------------------------------------------------
245
246
247
248
249
250
251
252

253
254

255
256
257
258
259
260
261
243
244
245
246
247
248
249

250
251

252
253
254
255
256
257
258
259







-
+

-
+







 *
 *----------------------------------------------------------------------
 */

static void
RefWinEventProc(
    ClientData clientData,	/* Busy window record */
    register XEvent *eventPtr)	/* Event which triggered call to routine */
    XEvent *eventPtr)	/* Event which triggered call to routine */
{
    register Busy *busyPtr = clientData;
    Busy *busyPtr = (Busy *)clientData;

    switch (eventPtr->type) {
    case ReparentNotify:
    case DestroyNotify:
	/*
	 * Arrange for the busy structure to be removed at a proper time.
	 */
329
330
331
332
333
334
335
336

337
338
339
340
341
342
343
327
328
329
330
331
332
333

334
335
336
337
338
339
340
341







-
+







 *----------------------------------------------------------------------
 */

static void
DestroyBusy(
    void *data)			/* Busy window structure record */
{
    register Busy *busyPtr = data;
    Busy *busyPtr = (Busy *)data;

    if (busyPtr->hashPtr != NULL) {
	Tcl_DeleteHashEntry(busyPtr->hashPtr);
    }
    Tk_DeleteEventHandler(busyPtr->tkRef, StructureNotifyMask,
	    RefWinEventProc, busyPtr);

373
374
375
376
377
378
379
380

381
382
383
384
385
386
387
371
372
373
374
375
376
377

378
379
380
381
382
383
384
385







-
+







 */

static void
BusyEventProc(
    ClientData clientData,	/* Busy window record */
    XEvent *eventPtr)		/* Event which triggered call to routine */
{
    Busy *busyPtr = clientData;
    Busy *busyPtr = (Busy *)clientData;

    if (eventPtr->type == DestroyNotify) {
	busyPtr->tkBusy = NULL;
	Tcl_EventuallyFree(busyPtr, (Tcl_FreeProc *)DestroyBusy);
    }
}

523
524
525
526
527
528
529
530

531
532
533

534
535
536
537
538
539
540
521
522
523
524
525
526
527

528
529
530

531
532
533
534
535
536
537
538







-
+


-
+







    int x, y;
    const char *fmt;
    char *name;
    Tk_Window tkBusy, tkChild, tkParent;
    Window parent;
    Tk_FakeWin *winPtr;

    busyPtr = ckalloc(sizeof(Busy));
    busyPtr = (Busy *)ckalloc(sizeof(Busy));
    x = y = 0;
    length = strlen(Tk_Name(tkRef));
    name = ckalloc(length + 6);
    name = (char *)ckalloc(length + 6);
    if (Tk_IsTopLevel(tkRef)) {
	fmt = "_Busy";		/* Child */
	tkParent = tkRef;
    } else {
	Tk_Window tkwin;

	fmt = "%s_Busy";	/* Sibling */
568
569
570
571
572
573
574
575

576
577
578
579
580
581
582
566
567
568
569
570
571
572

573
574
575
576
577
578
579
580







-
+







    busyPtr->width = Tk_Width(tkRef);
    busyPtr->height = Tk_Height(tkRef);
    busyPtr->x = Tk_X(tkRef);
    busyPtr->y = Tk_Y(tkRef);
    busyPtr->cursor = NULL;
    Tk_SetClass(tkBusy, "Busy");
    busyPtr->optionTable = Tk_CreateOptionTable(interp, busyOptionSpecs);
    if (Tk_InitOptions(interp, (char *) busyPtr, busyPtr->optionTable,
    if (Tk_InitOptions(interp, busyPtr, busyPtr->optionTable,
	    tkBusy) != TCL_OK) {
	Tk_DestroyWindow(tkBusy);
	return NULL;
    }
    SetWindowInstanceData(tkBusy, busyPtr);
    winPtr = (Tk_FakeWin *) tkRef;

635
636
637
638
639
640
641
642

643
644
645
646
647
648
649
633
634
635
636
637
638
639

640
641
642
643
644
645
646
647







-
+







    Tcl_Interp *interp,
    Busy *busyPtr,
    int objc,
    Tcl_Obj *const objv[])
{
    Tk_Cursor oldCursor = busyPtr->cursor;

    if (Tk_SetOptions(interp, (char *) busyPtr, busyPtr->optionTable, objc,
    if (Tk_SetOptions(interp, busyPtr, busyPtr->optionTable, objc,
	    objv, busyPtr->tkBusy, NULL, NULL) != TCL_OK) {
	return TCL_ERROR;
    }
    if (busyPtr->cursor != oldCursor) {
	if (busyPtr->cursor == NULL) {
	    Tk_UndefineCursor(busyPtr->tkBusy);
	} else {
684
685
686
687
688
689
690
691

692
693
694
695
696
697
698
699

700
701
702
703
704
705
706
682
683
684
685
686
687
688

689
690
691
692
693
694
695
696

697
698
699
700
701
702
703
704







-
+







-
+







    Tcl_HashEntry *hPtr;
    Tk_Window tkwin;

    if (TkGetWindowFromObj(interp, Tk_MainWindow(interp), windowObj,
	    &tkwin) != TCL_OK) {
	return NULL;
    }
    hPtr = Tcl_FindHashEntry(busyTablePtr, (char *) tkwin);
    hPtr = Tcl_FindHashEntry(busyTablePtr, tkwin);
    if (hPtr == NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"can't find busy window \"%s\"", Tcl_GetString(windowObj)));
	Tcl_SetErrorCode(interp, "TK", "LOOKUP", "BUSY",
		Tcl_GetString(windowObj), NULL);
	return NULL;
    }
    return Tcl_GetHashValue(hPtr);
    return (Busy *)Tcl_GetHashValue(hPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * HoldBusy --
 *
742
743
744
745
746
747
748
749

750
751
752
753
754
755
756
757
758
759
760
761
762
763
764



765
766
767
768
769
770
771
740
741
742
743
744
745
746

747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772







-
+















+
+
+







	busyPtr = CreateBusy(interp, tkwin);
	if (busyPtr == NULL) {
	    return TCL_ERROR;
	}
	Tcl_SetHashValue(hPtr, busyPtr);
	busyPtr->hashPtr = hPtr;
    } else {
	busyPtr = Tcl_GetHashValue(hPtr);
	busyPtr = (Busy *)Tcl_GetHashValue(hPtr);
    }

    busyPtr->tablePtr = busyTablePtr;
    result = ConfigureBusy(interp, busyPtr, configObjc, configObjv);

    /*
     * Don't map the busy window unless the reference window is also currently
     * displayed.
     */

    if (Tk_IsMapped(busyPtr->tkRef)) {
	TkpShowBusyWindow(busyPtr);
    } else {
	TkpHideBusyWindow(busyPtr);
    }
    if (result == TCL_OK) {
        Tcl_SetObjResult(interp, Tcl_NewStringObj(Tk_PathName(busyPtr->tkBusy), -1));
    }
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * Tk_BusyObjCmd --
785
786
787
788
789
790
791
792

793
794
795
796
797
798


799
800
801
802


803
804
805
806

807
808
809
810
811
812
813
814
815
816

817
818
819
820
821
822
823
824
825
826













827
828
829
830
831
832
833
834
835
836
837

838
839
840
841
842
843
844
845
846
847
848
849

850
851
852
853
854
855
856
857
858

859
860
861
862
863
864
865
786
787
788
789
790
791
792

793
794
795
796
797
798

799
800
801
802


803
804
805
806
807

808
809
810
811
812
813
814
815
816
817

818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851

852
853
854
855
856
857
858
859
860
861
862
863

864
865
866
867
868
869
870
871
872

873
874
875
876
877
878
879
880







-
+





-
+
+


-
-
+
+



-
+









-
+










+
+
+
+
+
+
+
+
+
+
+
+
+










-
+











-
+








-
+







int
Tk_BusyObjCmd(
    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;
    Tcl_HashTable *busyTablePtr = &((TkWindow *) tkwin)->mainPtr->busyTable;
    Busy *busyPtr;
    Tcl_Obj *objPtr;
    int index, result = TCL_OK;
    static const char *const optionStrings[] = {
	"cget", "configure", "current", "forget", "hold", "status", NULL
	"busywindow", "cget", "configure", "current", "forget", "hold",
        "status", NULL
    };
    enum options {
	BUSY_CGET, BUSY_CONFIGURE, BUSY_CURRENT, BUSY_FORGET, BUSY_HOLD,
	BUSY_STATUS
	BUSY_BUSYWINDOW, BUSY_CGET, BUSY_CONFIGURE, BUSY_CURRENT, BUSY_FORGET,
	BUSY_HOLD, BUSY_STATUS
    };

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "options ?arg arg ...?");
	Tcl_WrongNumArgs(interp, 1, objv, "options ?arg ...?");
	return TCL_ERROR;
    }

    /*
     * [tk busy <window>] command shortcut.
     */

    if (Tcl_GetString(objv[1])[0] == '.') {
	if (objc%2 == 1) {
	    Tcl_WrongNumArgs(interp, 1, objv, "window ?option value ...?");
	    Tcl_WrongNumArgs(interp, 1, objv, "window ?-option value ...?");
	    return TCL_ERROR;
	}
	return HoldBusy(busyTablePtr, interp, objv[1], objc-2, objv+2);
    }

    if (Tcl_GetIndexFromObjStruct(interp, objv[1], optionStrings,
	    sizeof(char *), "option", 0, &index) != TCL_OK) {
	return TCL_ERROR;
    }
    switch ((enum options) index) {
    case BUSY_BUSYWINDOW:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "window");
	    return TCL_ERROR;
	}
	busyPtr = GetBusy(interp, busyTablePtr, objv[2]);
	if (busyPtr == NULL) {
	    Tcl_ResetResult(interp);
            return TCL_OK;
	}
        Tcl_SetObjResult(interp, Tcl_NewStringObj(Tk_PathName(busyPtr->tkBusy), -1));
        return TCL_OK;

    case BUSY_CGET:
	if (objc != 4) {
	    Tcl_WrongNumArgs(interp, 2, objv, "window option");
	    return TCL_ERROR;
	}
	busyPtr = GetBusy(interp, busyTablePtr, objv[2]);
	if (busyPtr == NULL) {
	    return TCL_ERROR;
	}
	Tcl_Preserve(busyPtr);
	objPtr = Tk_GetOptionValue(interp, (char *) busyPtr,
	objPtr = Tk_GetOptionValue(interp, busyPtr,
		busyPtr->optionTable, objv[3], busyPtr->tkBusy);
	if (objPtr == NULL) {
	    result = TCL_ERROR;
	} else {
	    Tcl_SetObjResult(interp, objPtr);
	}
	Tcl_Release(busyPtr);
	return result;

    case BUSY_CONFIGURE:
	if (objc < 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "window ?option? ?value ...?");
	    Tcl_WrongNumArgs(interp, 2, objv, "window ?-option value ...?");
	    return TCL_ERROR;
	}
	busyPtr = GetBusy(interp, busyTablePtr, objv[2]);
	if (busyPtr == NULL) {
	    return TCL_ERROR;
	}
	Tcl_Preserve(busyPtr);
	if (objc <= 4) {
	    objPtr = Tk_GetOptionInfo(interp, (char *) busyPtr,
	    objPtr = Tk_GetOptionInfo(interp, busyPtr,
		    busyPtr->optionTable, (objc == 4) ? objv[3] : NULL,
		    busyPtr->tkBusy);
	    if (objPtr == NULL) {
		result = TCL_ERROR;
	    } else {
		Tcl_SetObjResult(interp, objPtr);
	    }
873
874
875
876
877
878
879
880

881
882
883
884

885
886
887
888
889
890
891
888
889
890
891
892
893
894

895
896
897
898

899
900
901
902
903
904
905
906







-
+



-
+







	Tcl_HashEntry *hPtr;
	Tcl_HashSearch cursor;
	const char *pattern = (objc == 3 ? Tcl_GetString(objv[2]) : NULL);

	objPtr = Tcl_NewObj();
	for (hPtr = Tcl_FirstHashEntry(busyTablePtr, &cursor); hPtr != NULL;
		hPtr = Tcl_NextHashEntry(&cursor)) {
	    busyPtr = Tcl_GetHashValue(hPtr);
	    busyPtr = (Busy *)Tcl_GetHashValue(hPtr);
	    if (pattern == NULL ||
		    Tcl_StringCaseMatch(Tk_PathName(busyPtr->tkRef), pattern, 0)) {
		Tcl_ListObjAppendElement(interp, objPtr,
			TkNewWindowObj(busyPtr->tkRef));
			Tk_NewWindowObj(busyPtr->tkRef));
	    }
	}
	Tcl_SetObjResult(interp, objPtr);
	return TCL_OK;
    }

    case BUSY_FORGET:
899
900
901
902
903
904
905
906

907
908
909
910
911
912
913
914
915
916
917
918
919
920

921
922
923
924
925
926
927
928







-
+







	}
	TkpHideBusyWindow(busyPtr);
	Tcl_EventuallyFree(busyPtr, (Tcl_FreeProc *)DestroyBusy);
	return TCL_OK;

    case BUSY_HOLD:
	if (objc < 3 || objc%2 != 1) {
	    Tcl_WrongNumArgs(interp, 2, objv, "window ?option value ...?");
	    Tcl_WrongNumArgs(interp, 2, objv, "window ?-option value ...?");
	    return TCL_ERROR;
	}
	return HoldBusy(busyTablePtr, interp, objv[2], objc-3, objv+3);

    case BUSY_STATUS:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "window");
Changes to generic/tkButton.c.
1
2
3
4
5
6
7
8
9


10
11
12
13
14
15
16
1
2
3
4
5
6
7


8
9
10
11
12
13
14
15
16







-
-
+
+







/*
 * tkButton.c --
 *
 *	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.
 */

#include "tkInt.h"
#include "tkButton.h"
66
67
68
69
70
71
72
73

74
75
76

77
78
79

80
81

82
83
84

85
86

87
88

89
90
91
92


93
94

95
96
97

98
99
100
101

102
103
104

105
106

107
108

109
110

111
112
113

114
115
116

117
118
119
120
121


122
123

124
125
126

127
128
129


130
131
132


133
134

135
136

137
138
139

140
141
142

143
144

145
146
147

148
149

150
151
152


153
154
155
156
157
158

159
160
161

162
163
164

165
166

167
168
169

170
171

172
173

174
175
176
177


178
179

180
181
182

183
184
185

186
187
188

189
190
191
192

193
194
195

196
197

198
199

200
201

202
203
204

205
206
207

208
209
210
211
212


213
214

215
216
217

218
219

220
221
222
223


224
225
226


227
228

229
230
231

232
233
234

235
236
237

238
239
240

241
242
243

244
245

246
247
248

249
250

251
252
253
254



255
256
257
258
259

260
261
262

263
264
265

266
267

268
269
270

271
272

273
274

275
276
277
278


279
280

281
282
283

284
285
286

287
288
289
290

291
292
293

294
295

296
297

298
299

300
301
302

303
304
305

306
307
308
309
310


311
312

313
314
315

316
317

318
319

320
321

322
323

324
325

326
327
328
329


330
331
332


333
334

335
336

337
338
339

340
341
342

343
344
345

346
347
348

349
350

351
352
353

354
355
356

357
358

359
360

361
362
363

364
365
366
367



368
369
370
371
372

373
374
375

376
377
378

379
380

381
382
383

384
385

386
387

388
389
390
391


392
393

394
395
396

397
398
399

400
401
402
403

404
405
406

407
408

409
410

411
412

413
414
415

416
417
418

419
420
421
422
423


424
425

426
427
428

429
430
431

432
433

434
435

436
437
438
439


440
441
442


443
444

445
446

447
448
449

450
451
452

453
454
455

456
457
458

459
460

461
462
463

464
465
466

467
468

469
470

471
472

473
474
475

476
477
478
479



480
481
482
483
484
485
486
66
67
68
69
70
71
72

73
74
75

76
77
78

79
80

81
82
83

84
85

86
87

88
89
90


91
92
93

94
95
96

97
98
99
100

101
102
103

104
105

106
107

108
109

110
111
112

113
114
115

116
117
118
119


120
121
122

123
124
125

126
127


128
129
130


131
132
133

134
135

136
137
138

139
140
141

142
143

144
145
146

147
148

149
150


151
152
153
154
155
156
157

158
159
160

161
162
163

164
165

166
167
168

169
170

171
172

173
174
175


176
177
178

179
180
181

182
183
184

185
186
187

188
189
190
191

192
193
194

195
196

197
198

199
200

201
202
203

204
205
206

207
208
209
210


211
212
213

214
215
216

217
218

219
220
221


222
223
224


225
226
227

228
229
230

231
232
233

234
235
236

237
238
239

240
241
242

243
244

245
246
247

248
249

250
251



252
253
254
255
256
257
258

259
260
261

262
263
264

265
266

267
268
269

270
271

272
273

274
275
276


277
278
279

280
281
282

283
284
285

286
287
288
289

290
291
292

293
294

295
296

297
298

299
300
301

302
303
304

305
306
307
308


309
310
311

312
313
314

315
316

317
318

319
320

321
322

323
324

325
326
327


328
329
330


331
332
333

334
335

336
337
338

339
340
341

342
343
344

345
346
347

348
349

350
351
352

353
354
355

356
357

358
359

360
361
362

363
364



365
366
367
368
369
370
371

372
373
374

375
376
377

378
379

380
381
382

383
384

385
386

387
388
389


390
391
392

393
394
395

396
397
398

399
400
401
402

403
404
405

406
407

408
409

410
411

412
413
414

415
416
417

418
419
420
421


422
423
424

425
426
427

428
429
430

431
432

433
434

435
436
437


438
439
440


441
442
443

444
445

446
447
448

449
450
451

452
453
454

455
456
457

458
459

460
461
462

463
464
465

466
467

468
469

470
471

472
473
474

475
476



477
478
479
480
481
482
483
484
485
486







-
+


-
+


-
+

-
+


-
+

-
+

-
+


-
-
+
+

-
+


-
+



-
+


-
+

-
+

-
+

-
+


-
+


-
+



-
-
+
+

-
+


-
+

-
-
+
+

-
-
+
+

-
+

-
+


-
+


-
+

-
+


-
+

-
+

-
-
+
+





-
+


-
+


-
+

-
+


-
+

-
+

-
+


-
-
+
+

-
+


-
+


-
+


-
+



-
+


-
+

-
+

-
+

-
+


-
+


-
+



-
-
+
+

-
+


-
+

-
+


-
-
+
+

-
-
+
+

-
+


-
+


-
+


-
+


-
+


-
+

-
+


-
+

-
+

-
-
-
+
+
+




-
+


-
+


-
+

-
+


-
+

-
+

-
+


-
-
+
+

-
+


-
+


-
+



-
+


-
+

-
+

-
+

-
+


-
+


-
+



-
-
+
+

-
+


-
+

-
+

-
+

-
+

-
+

-
+


-
-
+
+

-
-
+
+

-
+

-
+


-
+


-
+


-
+


-
+

-
+


-
+


-
+

-
+

-
+


-
+

-
-
-
+
+
+




-
+


-
+


-
+

-
+


-
+

-
+

-
+


-
-
+
+

-
+


-
+


-
+



-
+


-
+

-
+

-
+

-
+


-
+


-
+



-
-
+
+

-
+


-
+


-
+

-
+

-
+


-
-
+
+

-
-
+
+

-
+

-
+


-
+


-
+


-
+


-
+

-
+


-
+


-
+

-
+

-
+

-
+


-
+

-
-
-
+
+
+







/*
 * Information used for parsing configuration options.  There is a
 * separate table for each of the four widget classes.
 */

static const Tk_OptionSpec labelOptionSpecs[] = {
    {TK_OPTION_BORDER, "-activebackground", "activeBackground", "Foreground",
	DEF_BUTTON_ACTIVE_BG_COLOR, -1, Tk_Offset(TkButton, activeBorder),
	DEF_BUTTON_ACTIVE_BG_COLOR, TCL_INDEX_NONE, offsetof(TkButton, activeBorder),
	0, DEF_BUTTON_ACTIVE_BG_MONO, 0},
    {TK_OPTION_COLOR, "-activeforeground", "activeForeground", "Background",
	DEF_BUTTON_ACTIVE_FG_COLOR, -1, Tk_Offset(TkButton, activeFg),
	DEF_BUTTON_ACTIVE_FG_COLOR, TCL_INDEX_NONE, offsetof(TkButton, activeFg),
	TK_OPTION_NULL_OK, DEF_BUTTON_ACTIVE_FG_MONO, 0},
    {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",
	DEF_BUTTON_ANCHOR, -1, Tk_Offset(TkButton, anchor), 0, 0, 0},
	DEF_BUTTON_ANCHOR, TCL_INDEX_NONE, offsetof(TkButton, anchor), 0, 0, 0},
    {TK_OPTION_BORDER, "-background", "background", "Background",
	DEF_BUTTON_BG_COLOR, -1, Tk_Offset(TkButton, normalBorder),
	DEF_BUTTON_BG_COLOR, TCL_INDEX_NONE, offsetof(TkButton, normalBorder),
	0, DEF_BUTTON_BG_MONO, 0},
    {TK_OPTION_SYNONYM, "-bd", NULL, NULL,
	NULL, 0, -1, 0, "-borderwidth", 0},
	NULL, 0, TCL_INDEX_NONE, 0, "-borderwidth", 0},
    {TK_OPTION_SYNONYM, "-bg", NULL, NULL,
	NULL, 0, -1, 0, "-background", 0},
	NULL, 0, TCL_INDEX_NONE, 0, "-background", 0},
    {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap",
	DEF_BUTTON_BITMAP, -1, Tk_Offset(TkButton, bitmap),
	DEF_BUTTON_BITMAP, TCL_INDEX_NONE, offsetof(TkButton, bitmap),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
	tkDefButtonBorderWidth, Tk_Offset(TkButton, borderWidthPtr),
	Tk_Offset(TkButton, borderWidth), 0, 0, 0},
	tkDefButtonBorderWidth, offsetof(TkButton, borderWidthPtr),
	offsetof(TkButton, borderWidth), 0, 0, 0},
    {TK_OPTION_STRING_TABLE, "-compound", "compound", "Compound",
	 DEF_BUTTON_COMPOUND, -1, Tk_Offset(TkButton, compound), 0,
	 DEF_BUTTON_COMPOUND, TCL_INDEX_NONE, offsetof(TkButton, compound), 0,
	 compoundStrings, 0},
    {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
	DEF_BUTTON_CURSOR, -1, Tk_Offset(TkButton, cursor),
	DEF_BUTTON_CURSOR, TCL_INDEX_NONE, offsetof(TkButton, cursor),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground",
	"DisabledForeground", DEF_BUTTON_DISABLED_FG_COLOR,
	-1, Tk_Offset(TkButton, disabledFg), TK_OPTION_NULL_OK,
	TCL_INDEX_NONE, offsetof(TkButton, disabledFg), TK_OPTION_NULL_OK,
	(ClientData) DEF_BUTTON_DISABLED_FG_MONO, 0},
    {TK_OPTION_SYNONYM, "-fg", "foreground", NULL,
	NULL, 0, -1, 0, "-foreground", 0},
	NULL, 0, TCL_INDEX_NONE, 0, "-foreground", 0},
    {TK_OPTION_FONT, "-font", "font", "Font",
	DEF_BUTTON_FONT, -1, Tk_Offset(TkButton, tkfont), 0, 0, 0},
	DEF_BUTTON_FONT, TCL_INDEX_NONE, offsetof(TkButton, tkfont), 0, 0, 0},
    {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
	DEF_BUTTON_FG, -1, Tk_Offset(TkButton, normalFg), 0, 0, 0},
	DEF_BUTTON_FG, TCL_INDEX_NONE, offsetof(TkButton, normalFg), 0, 0, 0},
    {TK_OPTION_STRING, "-height", "height", "Height",
	DEF_BUTTON_HEIGHT, Tk_Offset(TkButton, heightPtr), -1, 0, 0, 0},
	DEF_BUTTON_HEIGHT, offsetof(TkButton, heightPtr), TCL_INDEX_NONE, 0, 0, 0},
    {TK_OPTION_BORDER, "-highlightbackground", "highlightBackground",
	"HighlightBackground", DEF_BUTTON_HIGHLIGHT_BG_COLOR,
	-1, Tk_Offset(TkButton, highlightBorder), 0,
	TCL_INDEX_NONE, offsetof(TkButton, highlightBorder), 0,
	(ClientData) DEF_BUTTON_HIGHLIGHT_BG_MONO, 0},
    {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
	DEF_BUTTON_HIGHLIGHT, -1, Tk_Offset(TkButton, highlightColorPtr),
	DEF_BUTTON_HIGHLIGHT, TCL_INDEX_NONE, offsetof(TkButton, highlightColorPtr),
	0, 0, 0},
    {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
	"HighlightThickness", tkDefLabelHighlightWidth,
	Tk_Offset(TkButton, highlightWidthPtr),
	Tk_Offset(TkButton, highlightWidth), 0, 0, 0},
	offsetof(TkButton, highlightWidthPtr),
	offsetof(TkButton, highlightWidth), 0, 0, 0},
    {TK_OPTION_STRING, "-image", "image", "Image",
	DEF_BUTTON_IMAGE, Tk_Offset(TkButton, imagePtr), -1,
	DEF_BUTTON_IMAGE, offsetof(TkButton, imagePtr), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",
	DEF_BUTTON_JUSTIFY, -1, Tk_Offset(TkButton, justify), 0, 0, 0},
	DEF_BUTTON_JUSTIFY, TCL_INDEX_NONE, offsetof(TkButton, justify), 0, 0, 0},
    {TK_OPTION_PIXELS, "-padx", "padX", "Pad",
	tkDefLabelPadx, Tk_Offset(TkButton, padXPtr),
	Tk_Offset(TkButton, padX), 0, 0, 0},
	tkDefLabelPadx, offsetof(TkButton, padXPtr),
	offsetof(TkButton, padX), 0, 0, 0},
    {TK_OPTION_PIXELS, "-pady", "padY", "Pad",
	tkDefLabelPady, Tk_Offset(TkButton, padYPtr),
	Tk_Offset(TkButton, padY), 0, 0, 0},
	tkDefLabelPady, offsetof(TkButton, padYPtr),
	offsetof(TkButton, padY), 0, 0, 0},
    {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
	DEF_LABCHKRAD_RELIEF, -1, Tk_Offset(TkButton, relief), 0, 0, 0},
	DEF_LABCHKRAD_RELIEF, TCL_INDEX_NONE, offsetof(TkButton, relief), 0, 0, 0},
    {TK_OPTION_STRING_TABLE, "-state", "state", "State",
	DEF_BUTTON_STATE, -1, Tk_Offset(TkButton, state),
	DEF_BUTTON_STATE, TCL_INDEX_NONE, offsetof(TkButton, state),
	0, stateStrings, 0},
    {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
	DEF_LABEL_TAKE_FOCUS, Tk_Offset(TkButton, takeFocusPtr), -1,
	DEF_LABEL_TAKE_FOCUS, offsetof(TkButton, takeFocusPtr), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_STRING, "-text", "text", "Text",
	DEF_BUTTON_TEXT, Tk_Offset(TkButton, textPtr), -1, 0, 0, 0},
	DEF_BUTTON_TEXT, offsetof(TkButton, textPtr), TCL_INDEX_NONE, 0, 0, 0},
    {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable",
	DEF_BUTTON_TEXT_VARIABLE, Tk_Offset(TkButton, textVarNamePtr), -1,
	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, -1, Tk_Offset(TkButton, underline), 0, 0, 0},
	DEF_BUTTON_UNDERLINE, TCL_INDEX_NONE, offsetof(TkButton, underline), 0, 0, 0},
    {TK_OPTION_STRING, "-width", "width", "Width",
	DEF_BUTTON_WIDTH, Tk_Offset(TkButton, widthPtr), -1, 0, 0, 0},
	DEF_BUTTON_WIDTH, offsetof(TkButton, widthPtr), TCL_INDEX_NONE, 0, 0, 0},
    {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength",
	DEF_BUTTON_WRAP_LENGTH, Tk_Offset(TkButton, wrapLengthPtr),
	Tk_Offset(TkButton, wrapLength), 0, 0, 0},
	DEF_BUTTON_WRAP_LENGTH, offsetof(TkButton, wrapLengthPtr),
	offsetof(TkButton, wrapLength), 0, 0, 0},
    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0}
};

static const Tk_OptionSpec buttonOptionSpecs[] = {
    {TK_OPTION_BORDER, "-activebackground", "activeBackground", "Foreground",
	DEF_BUTTON_ACTIVE_BG_COLOR, -1, Tk_Offset(TkButton, activeBorder),
	DEF_BUTTON_ACTIVE_BG_COLOR, TCL_INDEX_NONE, offsetof(TkButton, activeBorder),
	0, DEF_BUTTON_ACTIVE_BG_MONO, 0},
    {TK_OPTION_COLOR, "-activeforeground", "activeForeground", "Background",
	DEF_BUTTON_ACTIVE_FG_COLOR, -1, Tk_Offset(TkButton, activeFg),
	DEF_BUTTON_ACTIVE_FG_COLOR, TCL_INDEX_NONE, offsetof(TkButton, activeFg),
	TK_OPTION_NULL_OK, DEF_BUTTON_ACTIVE_FG_MONO, 0},
    {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",
	DEF_BUTTON_ANCHOR, -1, Tk_Offset(TkButton, anchor), 0, 0, 0},
	DEF_BUTTON_ANCHOR, TCL_INDEX_NONE, offsetof(TkButton, anchor), 0, 0, 0},
    {TK_OPTION_BORDER, "-background", "background", "Background",
	DEF_BUTTON_BG_COLOR, -1, Tk_Offset(TkButton, normalBorder),
	DEF_BUTTON_BG_COLOR, TCL_INDEX_NONE, offsetof(TkButton, normalBorder),
	0, DEF_BUTTON_BG_MONO, 0},
    {TK_OPTION_SYNONYM, "-bd", NULL, NULL,
	NULL, 0, -1, 0, "-borderwidth", 0},
	NULL, 0, TCL_INDEX_NONE, 0, "-borderwidth", 0},
    {TK_OPTION_SYNONYM, "-bg", NULL, NULL,
	NULL, 0, -1, 0, "-background", 0},
	NULL, 0, TCL_INDEX_NONE, 0, "-background", 0},
    {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap",
	DEF_BUTTON_BITMAP, -1, Tk_Offset(TkButton, bitmap),
	DEF_BUTTON_BITMAP, TCL_INDEX_NONE, offsetof(TkButton, bitmap),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
	tkDefButtonBorderWidth, Tk_Offset(TkButton, borderWidthPtr),
	Tk_Offset(TkButton, borderWidth), 0, 0, 0},
	tkDefButtonBorderWidth, offsetof(TkButton, borderWidthPtr),
	offsetof(TkButton, borderWidth), 0, 0, 0},
    {TK_OPTION_STRING, "-command", "command", "Command",
	DEF_BUTTON_COMMAND, Tk_Offset(TkButton, commandPtr), -1,
	DEF_BUTTON_COMMAND, offsetof(TkButton, commandPtr), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_STRING_TABLE, "-compound", "compound", "Compound",
	 DEF_BUTTON_COMPOUND, -1, Tk_Offset(TkButton, compound), 0,
	 DEF_BUTTON_COMPOUND, TCL_INDEX_NONE, offsetof(TkButton, compound), 0,
	 compoundStrings, 0},
    {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
	DEF_BUTTON_CURSOR, -1, Tk_Offset(TkButton, cursor),
	DEF_BUTTON_CURSOR, TCL_INDEX_NONE, offsetof(TkButton, cursor),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_STRING_TABLE, "-default", "default", "Default",
        DEF_BUTTON_DEFAULT, -1, Tk_Offset(TkButton, defaultState),
        DEF_BUTTON_DEFAULT, TCL_INDEX_NONE, offsetof(TkButton, defaultState),
	0, defaultStrings, 0},
    {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground",
	"DisabledForeground", DEF_BUTTON_DISABLED_FG_COLOR,
	-1, Tk_Offset(TkButton, disabledFg), TK_OPTION_NULL_OK,
	TCL_INDEX_NONE, offsetof(TkButton, disabledFg), TK_OPTION_NULL_OK,
	(ClientData) DEF_BUTTON_DISABLED_FG_MONO, 0},
    {TK_OPTION_SYNONYM, "-fg", "foreground", NULL,
	NULL, 0, -1, 0, "-foreground", 0},
	NULL, 0, TCL_INDEX_NONE, 0, "-foreground", 0},
    {TK_OPTION_FONT, "-font", "font", "Font",
	DEF_BUTTON_FONT, -1, Tk_Offset(TkButton, tkfont), 0, 0, 0},
	DEF_BUTTON_FONT, TCL_INDEX_NONE, offsetof(TkButton, tkfont), 0, 0, 0},
    {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
	DEF_BUTTON_FG, -1, Tk_Offset(TkButton, normalFg), 0, 0, 0},
	DEF_BUTTON_FG, TCL_INDEX_NONE, offsetof(TkButton, normalFg), 0, 0, 0},
    {TK_OPTION_STRING, "-height", "height", "Height",
	DEF_BUTTON_HEIGHT, Tk_Offset(TkButton, heightPtr), -1, 0, 0, 0},
	DEF_BUTTON_HEIGHT, offsetof(TkButton, heightPtr), TCL_INDEX_NONE, 0, 0, 0},
    {TK_OPTION_BORDER, "-highlightbackground", "highlightBackground",
	"HighlightBackground", DEF_BUTTON_HIGHLIGHT_BG_COLOR,
	-1, Tk_Offset(TkButton, highlightBorder), 0,
	TCL_INDEX_NONE, offsetof(TkButton, highlightBorder), 0,
	(ClientData) DEF_BUTTON_HIGHLIGHT_BG_MONO, 0},
    {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
	DEF_BUTTON_HIGHLIGHT, -1, Tk_Offset(TkButton, highlightColorPtr),
	DEF_BUTTON_HIGHLIGHT, TCL_INDEX_NONE, offsetof(TkButton, highlightColorPtr),
	0, 0, 0},
    {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
	"HighlightThickness", tkDefButtonHighlightWidth,
	Tk_Offset(TkButton, highlightWidthPtr),
	Tk_Offset(TkButton, highlightWidth), 0, 0, 0},
	offsetof(TkButton, highlightWidthPtr),
	offsetof(TkButton, highlightWidth), 0, 0, 0},
    {TK_OPTION_STRING, "-image", "image", "Image",
	DEF_BUTTON_IMAGE, Tk_Offset(TkButton, imagePtr), -1,
	DEF_BUTTON_IMAGE, offsetof(TkButton, imagePtr), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",
	DEF_BUTTON_JUSTIFY, -1, Tk_Offset(TkButton, justify), 0, 0, 0},
	DEF_BUTTON_JUSTIFY, TCL_INDEX_NONE, offsetof(TkButton, justify), 0, 0, 0},
    {TK_OPTION_RELIEF, "-overrelief", "overRelief", "OverRelief",
	 DEF_BUTTON_OVER_RELIEF, -1, Tk_Offset(TkButton, overRelief),
	 DEF_BUTTON_OVER_RELIEF, TCL_INDEX_NONE, offsetof(TkButton, overRelief),
	 TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_PIXELS, "-padx", "padX", "Pad",
	tkDefButtonPadx, Tk_Offset(TkButton, padXPtr),
	Tk_Offset(TkButton, padX), 0, 0, 0},
	tkDefButtonPadx, offsetof(TkButton, padXPtr),
	offsetof(TkButton, padX), 0, 0, 0},
    {TK_OPTION_PIXELS, "-pady", "padY", "Pad",
	tkDefButtonPady, Tk_Offset(TkButton, padYPtr),
	Tk_Offset(TkButton, padY), 0, 0, 0},
	tkDefButtonPady, offsetof(TkButton, padYPtr),
	offsetof(TkButton, padY), 0, 0, 0},
    {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
	DEF_BUTTON_RELIEF, -1, Tk_Offset(TkButton, relief),
	DEF_BUTTON_RELIEF, TCL_INDEX_NONE, offsetof(TkButton, relief),
	 0, 0, 0},
    {TK_OPTION_INT, "-repeatdelay", "repeatDelay", "RepeatDelay",
	 DEF_BUTTON_REPEAT_DELAY, -1, Tk_Offset(TkButton, repeatDelay),
	 DEF_BUTTON_REPEAT_DELAY, TCL_INDEX_NONE, offsetof(TkButton, repeatDelay),
	 0, 0, 0},
    {TK_OPTION_INT, "-repeatinterval", "repeatInterval", "RepeatInterval",
	 DEF_BUTTON_REPEAT_INTERVAL, -1, Tk_Offset(TkButton, repeatInterval),
	 DEF_BUTTON_REPEAT_INTERVAL, TCL_INDEX_NONE, offsetof(TkButton, repeatInterval),
	 0, 0, 0},
    {TK_OPTION_STRING_TABLE, "-state", "state", "State",
	DEF_BUTTON_STATE, -1, Tk_Offset(TkButton, state),
	DEF_BUTTON_STATE, TCL_INDEX_NONE, offsetof(TkButton, state),
	0, stateStrings, 0},
    {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
	DEF_BUTTON_TAKE_FOCUS, Tk_Offset(TkButton, takeFocusPtr), -1,
	DEF_BUTTON_TAKE_FOCUS, offsetof(TkButton, takeFocusPtr), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_STRING, "-text", "text", "Text",
	DEF_BUTTON_TEXT, Tk_Offset(TkButton, textPtr), -1, 0, 0, 0},
	DEF_BUTTON_TEXT, offsetof(TkButton, textPtr), TCL_INDEX_NONE, 0, 0, 0},
    {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable",
	DEF_BUTTON_TEXT_VARIABLE, Tk_Offset(TkButton, textVarNamePtr), -1,
	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, -1, Tk_Offset(TkButton, underline), 0, 0, 0},
	DEF_BUTTON_UNDERLINE, TCL_INDEX_NONE, offsetof(TkButton, underline), 0, 0, 0},
    {TK_OPTION_STRING, "-width", "width", "Width",
	DEF_BUTTON_WIDTH, Tk_Offset(TkButton, widthPtr), -1, 0, 0, 0},
	DEF_BUTTON_WIDTH, offsetof(TkButton, widthPtr), TCL_INDEX_NONE, 0, 0, 0},
    {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength",
	DEF_BUTTON_WRAP_LENGTH, Tk_Offset(TkButton, wrapLengthPtr),
	Tk_Offset(TkButton, wrapLength), 0, 0, 0},
    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0, 0, 0}
	DEF_BUTTON_WRAP_LENGTH, offsetof(TkButton, wrapLengthPtr),
	offsetof(TkButton, wrapLength), 0, 0, 0},
    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, TCL_INDEX_NONE, 0, 0, 0}
};

static const Tk_OptionSpec checkbuttonOptionSpecs[] = {
    {TK_OPTION_BORDER, "-activebackground", "activeBackground", "Foreground",
	DEF_BUTTON_ACTIVE_BG_COLOR, -1, Tk_Offset(TkButton, activeBorder),
	DEF_BUTTON_ACTIVE_BG_COLOR, TCL_INDEX_NONE, offsetof(TkButton, activeBorder),
	0, DEF_BUTTON_ACTIVE_BG_MONO, 0},
    {TK_OPTION_COLOR, "-activeforeground", "activeForeground", "Background",
	DEF_CHKRAD_ACTIVE_FG_COLOR, -1, Tk_Offset(TkButton, activeFg),
	DEF_CHKRAD_ACTIVE_FG_COLOR, TCL_INDEX_NONE, offsetof(TkButton, activeFg),
	TK_OPTION_NULL_OK, DEF_BUTTON_ACTIVE_FG_MONO, 0},
    {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",
	DEF_BUTTON_ANCHOR, -1, Tk_Offset(TkButton, anchor), 0, 0, 0},
	DEF_BUTTON_ANCHOR, TCL_INDEX_NONE, offsetof(TkButton, anchor), 0, 0, 0},
    {TK_OPTION_BORDER, "-background", "background", "Background",
	DEF_BUTTON_BG_COLOR, -1, Tk_Offset(TkButton, normalBorder),
	DEF_BUTTON_BG_COLOR, TCL_INDEX_NONE, offsetof(TkButton, normalBorder),
	0, DEF_BUTTON_BG_MONO, 0},
    {TK_OPTION_SYNONYM, "-bd", NULL, NULL,
	NULL, 0, -1, 0, "-borderwidth", 0},
	NULL, 0, TCL_INDEX_NONE, 0, "-borderwidth", 0},
    {TK_OPTION_SYNONYM, "-bg", NULL, NULL,
	NULL, 0, -1, 0, "-background", 0},
	NULL, 0, TCL_INDEX_NONE, 0, "-background", 0},
    {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap",
	DEF_BUTTON_BITMAP, -1, Tk_Offset(TkButton, bitmap),
	DEF_BUTTON_BITMAP, TCL_INDEX_NONE, offsetof(TkButton, bitmap),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
	tkDefButtonBorderWidth, Tk_Offset(TkButton, borderWidthPtr),
	Tk_Offset(TkButton, borderWidth), 0, 0, 0},
	tkDefButtonBorderWidth, offsetof(TkButton, borderWidthPtr),
	offsetof(TkButton, borderWidth), 0, 0, 0},
    {TK_OPTION_STRING, "-command", "command", "Command",
	DEF_BUTTON_COMMAND, Tk_Offset(TkButton, commandPtr), -1,
	DEF_BUTTON_COMMAND, offsetof(TkButton, commandPtr), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_STRING_TABLE, "-compound", "compound", "Compound",
	 DEF_BUTTON_COMPOUND, -1, Tk_Offset(TkButton, compound), 0,
	 DEF_BUTTON_COMPOUND, TCL_INDEX_NONE, offsetof(TkButton, compound), 0,
	 compoundStrings, 0},
    {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
	DEF_BUTTON_CURSOR, -1, Tk_Offset(TkButton, cursor),
	DEF_BUTTON_CURSOR, TCL_INDEX_NONE, offsetof(TkButton, cursor),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground",
	"DisabledForeground", DEF_BUTTON_DISABLED_FG_COLOR,
	-1, Tk_Offset(TkButton, disabledFg), TK_OPTION_NULL_OK,
	TCL_INDEX_NONE, offsetof(TkButton, disabledFg), TK_OPTION_NULL_OK,
	(ClientData) DEF_BUTTON_DISABLED_FG_MONO, 0},
    {TK_OPTION_SYNONYM, "-fg", "foreground", NULL,
	NULL, 0, -1, 0, "-foreground", 0},
	NULL, 0, TCL_INDEX_NONE, 0, "-foreground", 0},
    {TK_OPTION_FONT, "-font", "font", "Font",
	DEF_BUTTON_FONT, -1, Tk_Offset(TkButton, tkfont), 0, 0, 0},
	DEF_BUTTON_FONT, TCL_INDEX_NONE, offsetof(TkButton, tkfont), 0, 0, 0},
    {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
	DEF_CHKRAD_FG, -1, Tk_Offset(TkButton, normalFg), 0, 0, 0},
	DEF_CHKRAD_FG, TCL_INDEX_NONE, offsetof(TkButton, normalFg), 0, 0, 0},
    {TK_OPTION_STRING, "-height", "height", "Height",
	DEF_BUTTON_HEIGHT, Tk_Offset(TkButton, heightPtr), -1, 0, 0, 0},
	DEF_BUTTON_HEIGHT, offsetof(TkButton, heightPtr), TCL_INDEX_NONE, 0, 0, 0},
    {TK_OPTION_BORDER, "-highlightbackground", "highlightBackground",
	"HighlightBackground", DEF_BUTTON_HIGHLIGHT_BG_COLOR,
	-1, Tk_Offset(TkButton, highlightBorder), 0,
	TCL_INDEX_NONE, offsetof(TkButton, highlightBorder), 0,
	(ClientData) DEF_BUTTON_HIGHLIGHT_BG_MONO, 0},
    {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
	DEF_BUTTON_HIGHLIGHT, -1, Tk_Offset(TkButton, highlightColorPtr),
	DEF_BUTTON_HIGHLIGHT, TCL_INDEX_NONE, offsetof(TkButton, highlightColorPtr),
	0, 0, 0},
    {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
	"HighlightThickness", tkDefButtonHighlightWidth,
	Tk_Offset(TkButton, highlightWidthPtr),
	Tk_Offset(TkButton, highlightWidth), 0, 0, 0},
	offsetof(TkButton, highlightWidthPtr),
	offsetof(TkButton, highlightWidth), 0, 0, 0},
    {TK_OPTION_STRING, "-image", "image", "Image",
	DEF_BUTTON_IMAGE, Tk_Offset(TkButton, imagePtr), -1,
	DEF_BUTTON_IMAGE, offsetof(TkButton, imagePtr), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_BOOLEAN, "-indicatoron", "indicatorOn", "IndicatorOn",
	DEF_BUTTON_INDICATOR, -1, Tk_Offset(TkButton, indicatorOn), 0, 0, 0},
	DEF_BUTTON_INDICATOR, TCL_INDEX_NONE, offsetof(TkButton, indicatorOn), 0, 0, 0},
    {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",
	DEF_BUTTON_JUSTIFY, -1, Tk_Offset(TkButton, justify), 0, 0, 0},
	DEF_BUTTON_JUSTIFY, TCL_INDEX_NONE, offsetof(TkButton, justify), 0, 0, 0},
    {TK_OPTION_RELIEF, "-offrelief", "offRelief", "OffRelief",
	 DEF_BUTTON_RELIEF, -1, Tk_Offset(TkButton, offRelief), 0, 0, 0},
	 DEF_BUTTON_RELIEF, TCL_INDEX_NONE, offsetof(TkButton, offRelief), 0, 0, 0},
    {TK_OPTION_STRING, "-offvalue", "offValue", "Value",
	DEF_BUTTON_OFF_VALUE, Tk_Offset(TkButton, offValuePtr), -1, 0, 0, 0},
	DEF_BUTTON_OFF_VALUE, offsetof(TkButton, offValuePtr), TCL_INDEX_NONE, 0, 0, 0},
    {TK_OPTION_STRING, "-onvalue", "onValue", "Value",
	DEF_BUTTON_ON_VALUE, Tk_Offset(TkButton, onValuePtr), -1, 0, 0, 0},
	DEF_BUTTON_ON_VALUE, offsetof(TkButton, onValuePtr), TCL_INDEX_NONE, 0, 0, 0},
    {TK_OPTION_RELIEF, "-overrelief", "overRelief", "OverRelief",
	 DEF_BUTTON_OVER_RELIEF, -1, Tk_Offset(TkButton, overRelief),
	 DEF_BUTTON_OVER_RELIEF, TCL_INDEX_NONE, offsetof(TkButton, overRelief),
	 TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_PIXELS, "-padx", "padX", "Pad",
	tkDefLabelPadx, Tk_Offset(TkButton, padXPtr),
	Tk_Offset(TkButton, padX), 0, 0, 0},
	tkDefLabelPadx, offsetof(TkButton, padXPtr),
	offsetof(TkButton, padX), 0, 0, 0},
    {TK_OPTION_PIXELS, "-pady", "padY", "Pad",
	tkDefLabelPady, Tk_Offset(TkButton, padYPtr),
	Tk_Offset(TkButton, padY), 0, 0, 0},
	tkDefLabelPady, offsetof(TkButton, padYPtr),
	offsetof(TkButton, padY), 0, 0, 0},
    {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
	DEF_LABCHKRAD_RELIEF, -1, Tk_Offset(TkButton, relief), 0, 0, 0},
	DEF_LABCHKRAD_RELIEF, TCL_INDEX_NONE, offsetof(TkButton, relief), 0, 0, 0},
    {TK_OPTION_BORDER, "-selectcolor", "selectColor", "Background",
	DEF_BUTTON_SELECT_COLOR, -1, Tk_Offset(TkButton, selectBorder),
	DEF_BUTTON_SELECT_COLOR, TCL_INDEX_NONE, offsetof(TkButton, selectBorder),
	TK_OPTION_NULL_OK, DEF_BUTTON_SELECT_MONO, 0},
    {TK_OPTION_STRING, "-selectimage", "selectImage", "SelectImage",
	DEF_BUTTON_SELECT_IMAGE, Tk_Offset(TkButton, selectImagePtr), -1,
	DEF_BUTTON_SELECT_IMAGE, offsetof(TkButton, selectImagePtr), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_STRING_TABLE, "-state", "state", "State",
	DEF_BUTTON_STATE, -1, Tk_Offset(TkButton, state),
	DEF_BUTTON_STATE, TCL_INDEX_NONE, offsetof(TkButton, state),
	0, stateStrings, 0},
    {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
	DEF_BUTTON_TAKE_FOCUS, Tk_Offset(TkButton, takeFocusPtr), -1,
	DEF_BUTTON_TAKE_FOCUS, offsetof(TkButton, takeFocusPtr), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_STRING, "-text", "text", "Text",
	DEF_BUTTON_TEXT, Tk_Offset(TkButton, textPtr), -1, 0, 0, 0},
	DEF_BUTTON_TEXT, offsetof(TkButton, textPtr), TCL_INDEX_NONE, 0, 0, 0},
    {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable",
	DEF_BUTTON_TEXT_VARIABLE, Tk_Offset(TkButton, textVarNamePtr), -1,
	DEF_BUTTON_TEXT_VARIABLE, offsetof(TkButton, textVarNamePtr), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_STRING, "-tristateimage", "tristateImage", "TristateImage",
	DEF_BUTTON_IMAGE, Tk_Offset(TkButton, tristateImagePtr), -1,
	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, Tk_Offset(TkButton, tristateValuePtr), -1, 0, 0, 0},
	DEF_BUTTON_TRISTATE_VALUE, offsetof(TkButton, tristateValuePtr), TCL_INDEX_NONE, 0, 0, 0},
    {TK_OPTION_INT, "-underline", "underline", "Underline",
	DEF_BUTTON_UNDERLINE, -1, Tk_Offset(TkButton, underline), 0, 0, 0},
	DEF_BUTTON_UNDERLINE, TCL_INDEX_NONE, offsetof(TkButton, underline), 0, 0, 0},
    {TK_OPTION_STRING, "-variable", "variable", "Variable",
	DEF_CHECKBUTTON_VARIABLE, Tk_Offset(TkButton, selVarNamePtr), -1,
	DEF_CHECKBUTTON_VARIABLE, offsetof(TkButton, selVarNamePtr), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_STRING, "-width", "width", "Width",
	DEF_BUTTON_WIDTH, Tk_Offset(TkButton, widthPtr), -1, 0, 0, 0},
	DEF_BUTTON_WIDTH, offsetof(TkButton, widthPtr), TCL_INDEX_NONE, 0, 0, 0},
    {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength",
	DEF_BUTTON_WRAP_LENGTH, Tk_Offset(TkButton, wrapLengthPtr),
	Tk_Offset(TkButton, wrapLength), 0, 0, 0},
    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0, 0, 0}
	DEF_BUTTON_WRAP_LENGTH, offsetof(TkButton, wrapLengthPtr),
	offsetof(TkButton, wrapLength), 0, 0, 0},
    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, TCL_INDEX_NONE, 0, 0, 0}
};

static const Tk_OptionSpec radiobuttonOptionSpecs[] = {
    {TK_OPTION_BORDER, "-activebackground", "activeBackground", "Foreground",
	DEF_BUTTON_ACTIVE_BG_COLOR, -1, Tk_Offset(TkButton, activeBorder),
	DEF_BUTTON_ACTIVE_BG_COLOR, TCL_INDEX_NONE, offsetof(TkButton, activeBorder),
	0, DEF_BUTTON_ACTIVE_BG_MONO, 0},
    {TK_OPTION_COLOR, "-activeforeground", "activeForeground", "Background",
	DEF_CHKRAD_ACTIVE_FG_COLOR, -1, Tk_Offset(TkButton, activeFg),
	DEF_CHKRAD_ACTIVE_FG_COLOR, TCL_INDEX_NONE, offsetof(TkButton, activeFg),
	TK_OPTION_NULL_OK, DEF_BUTTON_ACTIVE_FG_MONO, 0},
    {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",
	DEF_BUTTON_ANCHOR, -1, Tk_Offset(TkButton, anchor), 0, 0, 0},
	DEF_BUTTON_ANCHOR, TCL_INDEX_NONE, offsetof(TkButton, anchor), 0, 0, 0},
    {TK_OPTION_BORDER, "-background", "background", "Background",
	DEF_BUTTON_BG_COLOR, -1, Tk_Offset(TkButton, normalBorder),
	DEF_BUTTON_BG_COLOR, TCL_INDEX_NONE, offsetof(TkButton, normalBorder),
	0, DEF_BUTTON_BG_MONO, 0},
    {TK_OPTION_SYNONYM, "-bd", NULL, NULL,
	NULL, 0, -1, 0, "-borderwidth", 0},
	NULL, 0, TCL_INDEX_NONE, 0, "-borderwidth", 0},
    {TK_OPTION_SYNONYM, "-bg", NULL, NULL,
	NULL, 0, -1, 0, "-background", 0},
	NULL, 0, TCL_INDEX_NONE, 0, "-background", 0},
    {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap",
	DEF_BUTTON_BITMAP, -1, Tk_Offset(TkButton, bitmap),
	DEF_BUTTON_BITMAP, TCL_INDEX_NONE, offsetof(TkButton, bitmap),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
	tkDefButtonBorderWidth, Tk_Offset(TkButton, borderWidthPtr),
	Tk_Offset(TkButton, borderWidth), 0, 0, 0},
	tkDefButtonBorderWidth, offsetof(TkButton, borderWidthPtr),
	offsetof(TkButton, borderWidth), 0, 0, 0},
    {TK_OPTION_STRING, "-command", "command", "Command",
	DEF_BUTTON_COMMAND, Tk_Offset(TkButton, commandPtr), -1,
	DEF_BUTTON_COMMAND, offsetof(TkButton, commandPtr), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_STRING_TABLE, "-compound", "compound", "Compound",
	 DEF_BUTTON_COMPOUND, -1, Tk_Offset(TkButton, compound), 0,
	 DEF_BUTTON_COMPOUND, TCL_INDEX_NONE, offsetof(TkButton, compound), 0,
	 compoundStrings, 0},
    {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
	DEF_BUTTON_CURSOR, -1, Tk_Offset(TkButton, cursor),
	DEF_BUTTON_CURSOR, TCL_INDEX_NONE, offsetof(TkButton, cursor),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground",
	"DisabledForeground", DEF_BUTTON_DISABLED_FG_COLOR,
	-1, Tk_Offset(TkButton, disabledFg), TK_OPTION_NULL_OK,
	TCL_INDEX_NONE, offsetof(TkButton, disabledFg), TK_OPTION_NULL_OK,
	(ClientData) DEF_BUTTON_DISABLED_FG_MONO, 0},
    {TK_OPTION_SYNONYM, "-fg", "foreground", NULL,
	NULL, 0, -1, 0, "-foreground", 0},
	NULL, 0, TCL_INDEX_NONE, 0, "-foreground", 0},
    {TK_OPTION_FONT, "-font", "font", "Font",
	DEF_BUTTON_FONT, -1, Tk_Offset(TkButton, tkfont), 0, 0, 0},
	DEF_BUTTON_FONT, TCL_INDEX_NONE, offsetof(TkButton, tkfont), 0, 0, 0},
    {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
	DEF_CHKRAD_FG, -1, Tk_Offset(TkButton, normalFg), 0, 0, 0},
	DEF_CHKRAD_FG, TCL_INDEX_NONE, offsetof(TkButton, normalFg), 0, 0, 0},
    {TK_OPTION_STRING, "-height", "height", "Height",
	DEF_BUTTON_HEIGHT, Tk_Offset(TkButton, heightPtr), -1, 0, 0, 0},
	DEF_BUTTON_HEIGHT, offsetof(TkButton, heightPtr), TCL_INDEX_NONE, 0, 0, 0},
    {TK_OPTION_BORDER, "-highlightbackground", "highlightBackground",
	"HighlightBackground", DEF_BUTTON_HIGHLIGHT_BG_COLOR,
	-1, Tk_Offset(TkButton, highlightBorder), 0,
	TCL_INDEX_NONE, offsetof(TkButton, highlightBorder), 0,
	(ClientData) DEF_BUTTON_HIGHLIGHT_BG_MONO, 0},
    {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
	DEF_BUTTON_HIGHLIGHT, -1, Tk_Offset(TkButton, highlightColorPtr),
	DEF_BUTTON_HIGHLIGHT, TCL_INDEX_NONE, offsetof(TkButton, highlightColorPtr),
	0, 0, 0},
    {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
	"HighlightThickness", tkDefButtonHighlightWidth,
	Tk_Offset(TkButton, highlightWidthPtr),
	Tk_Offset(TkButton, highlightWidth), 0, 0, 0},
	offsetof(TkButton, highlightWidthPtr),
	offsetof(TkButton, highlightWidth), 0, 0, 0},
    {TK_OPTION_STRING, "-image", "image", "Image",
	DEF_BUTTON_IMAGE, Tk_Offset(TkButton, imagePtr), -1,
	DEF_BUTTON_IMAGE, offsetof(TkButton, imagePtr), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_BOOLEAN, "-indicatoron", "indicatorOn", "IndicatorOn",
	DEF_BUTTON_INDICATOR, -1, Tk_Offset(TkButton, indicatorOn),
	DEF_BUTTON_INDICATOR, TCL_INDEX_NONE, offsetof(TkButton, indicatorOn),
	0, 0, 0},
    {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",
	DEF_BUTTON_JUSTIFY, -1, Tk_Offset(TkButton, justify), 0, 0, 0},
	DEF_BUTTON_JUSTIFY, TCL_INDEX_NONE, offsetof(TkButton, justify), 0, 0, 0},
    {TK_OPTION_RELIEF, "-offrelief", "offRelief", "OffRelief",
	 DEF_BUTTON_RELIEF, -1, Tk_Offset(TkButton, offRelief), 0, 0, 0},
	 DEF_BUTTON_RELIEF, TCL_INDEX_NONE, offsetof(TkButton, offRelief), 0, 0, 0},
    {TK_OPTION_RELIEF, "-overrelief", "overRelief", "OverRelief",
	 DEF_BUTTON_OVER_RELIEF, -1, Tk_Offset(TkButton, overRelief),
	 DEF_BUTTON_OVER_RELIEF, TCL_INDEX_NONE, offsetof(TkButton, overRelief),
	 TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_PIXELS, "-padx", "padX", "Pad",
	tkDefLabelPadx, Tk_Offset(TkButton, padXPtr),
	Tk_Offset(TkButton, padX), 0, 0, 0},
	tkDefLabelPadx, offsetof(TkButton, padXPtr),
	offsetof(TkButton, padX), 0, 0, 0},
    {TK_OPTION_PIXELS, "-pady", "padY", "Pad",
	tkDefLabelPady, Tk_Offset(TkButton, padYPtr),
	Tk_Offset(TkButton, padY), 0, 0, 0},
	tkDefLabelPady, offsetof(TkButton, padYPtr),
	offsetof(TkButton, padY), 0, 0, 0},
    {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
	DEF_LABCHKRAD_RELIEF, -1, Tk_Offset(TkButton, relief), 0, 0, 0},
	DEF_LABCHKRAD_RELIEF, TCL_INDEX_NONE, offsetof(TkButton, relief), 0, 0, 0},
    {TK_OPTION_BORDER, "-selectcolor", "selectColor", "Background",
	DEF_BUTTON_SELECT_COLOR, -1, Tk_Offset(TkButton, selectBorder),
	DEF_BUTTON_SELECT_COLOR, TCL_INDEX_NONE, offsetof(TkButton, selectBorder),
	TK_OPTION_NULL_OK, DEF_BUTTON_SELECT_MONO, 0},
    {TK_OPTION_STRING, "-selectimage", "selectImage", "SelectImage",
	DEF_BUTTON_SELECT_IMAGE, Tk_Offset(TkButton, selectImagePtr), -1,
	DEF_BUTTON_SELECT_IMAGE, offsetof(TkButton, selectImagePtr), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_STRING_TABLE, "-state", "state", "State",
	DEF_BUTTON_STATE, -1, Tk_Offset(TkButton, state),
	DEF_BUTTON_STATE, TCL_INDEX_NONE, offsetof(TkButton, state),
	0, stateStrings, 0},
    {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
	DEF_BUTTON_TAKE_FOCUS, Tk_Offset(TkButton, takeFocusPtr), -1,
	DEF_BUTTON_TAKE_FOCUS, offsetof(TkButton, takeFocusPtr), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_STRING, "-text", "text", "Text",
	DEF_BUTTON_TEXT, Tk_Offset(TkButton, textPtr), -1, 0, 0, 0},
	DEF_BUTTON_TEXT, offsetof(TkButton, textPtr), TCL_INDEX_NONE, 0, 0, 0},
    {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable",
	DEF_BUTTON_TEXT_VARIABLE, Tk_Offset(TkButton, textVarNamePtr), -1,
	DEF_BUTTON_TEXT_VARIABLE, offsetof(TkButton, textVarNamePtr), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_STRING, "-tristateimage", "tristateImage", "TristateImage",
	DEF_BUTTON_IMAGE, Tk_Offset(TkButton, tristateImagePtr), -1,
	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, Tk_Offset(TkButton, tristateValuePtr), -1, 0, 0, 0},
	DEF_BUTTON_TRISTATE_VALUE, offsetof(TkButton, tristateValuePtr), TCL_INDEX_NONE, 0, 0, 0},
    {TK_OPTION_INT, "-underline", "underline", "Underline",
	DEF_BUTTON_UNDERLINE, -1, Tk_Offset(TkButton, underline), 0, 0, 0},
	DEF_BUTTON_UNDERLINE, TCL_INDEX_NONE, offsetof(TkButton, underline), 0, 0, 0},
    {TK_OPTION_STRING, "-value", "value", "Value",
	DEF_BUTTON_VALUE, Tk_Offset(TkButton, onValuePtr), -1, 0, 0, 0},
	DEF_BUTTON_VALUE, offsetof(TkButton, onValuePtr), TCL_INDEX_NONE, 0, 0, 0},
    {TK_OPTION_STRING, "-variable", "variable", "Variable",
	DEF_RADIOBUTTON_VARIABLE, Tk_Offset(TkButton, selVarNamePtr), -1,
	DEF_RADIOBUTTON_VARIABLE, offsetof(TkButton, selVarNamePtr), TCL_INDEX_NONE,
	0, 0, 0},
    {TK_OPTION_STRING, "-width", "width", "Width",
	DEF_BUTTON_WIDTH, Tk_Offset(TkButton, widthPtr), -1, 0, 0, 0},
	DEF_BUTTON_WIDTH, offsetof(TkButton, widthPtr), TCL_INDEX_NONE, 0, 0, 0},
    {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength",
	DEF_BUTTON_WRAP_LENGTH, Tk_Offset(TkButton, wrapLengthPtr),
	Tk_Offset(TkButton, wrapLength), 0, 0, 0},
    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0, 0, 0}
	DEF_BUTTON_WRAP_LENGTH, offsetof(TkButton, wrapLengthPtr),
	offsetof(TkButton, wrapLength), 0, 0, 0},
    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, TCL_INDEX_NONE, 0, 0, 0}
};

/*
 * The following table maps from one of the type values defined in tkButton.h,
 * such as TYPE_LABEL, to the option template for that class of widgets.
 */

624
625
626
627
628
629
630
631

632
633
634
635
636
637
638
639
640
641
642

643

644
645
646
647
648
649
650
624
625
626
627
628
629
630

631
632
633
634
635
636
637
638
639
640
641

642
643
644
645
646
647
648
649
650
651







-
+










-
+

+







 *	See the user documentation.
 *
 *--------------------------------------------------------------
 */

static int
ButtonCreate(
    ClientData clientData,	/* NULL. */
    ClientData dummy,	/* NULL. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[],	/* Argument values. */
    int type)			/* Type of button to create: TYPE_LABEL,
				 * TYPE_BUTTON, TYPE_CHECK_BUTTON, or
				 * TYPE_RADIO_BUTTON. */
{
    TkButton *butPtr;
    Tk_OptionTable optionTable;
    Tk_Window tkwin;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    (void)dummy;

    if (!tsdPtr->defaultsInitialized) {
	TkpButtonSetDefaults();
	tsdPtr->defaultsInitialized = 1;
    }

    if (objc < 2) {
745
746
747
748
749
750
751
752

753
754
755
756
757
758
759
760
761
762

763
764
765
766
767
768
769
746
747
748
749
750
751
752

753
754
755
756
757
758
759
760
761
762

763
764
765
766
767
768
769
770







-
+









-
+







    butPtr->commandPtr = NULL;
    butPtr->flags = 0;

    Tk_CreateEventHandler(butPtr->tkwin,
	    ExposureMask|StructureNotifyMask|FocusChangeMask,
	    ButtonEventProc, butPtr);

    if (Tk_InitOptions(interp, (char *) butPtr, optionTable, tkwin)
    if (Tk_InitOptions(interp, butPtr, optionTable, tkwin)
	    != TCL_OK) {
	Tk_DestroyWindow(butPtr->tkwin);
	return TCL_ERROR;
    }
    if (ConfigureButton(interp, butPtr, objc - 2, objv + 2) != TCL_OK) {
	Tk_DestroyWindow(butPtr->tkwin);
	return TCL_ERROR;
    }

    Tcl_SetObjResult(interp, TkNewWindowObj(butPtr->tkwin));
    Tcl_SetObjResult(interp, Tk_NewWindowObj(butPtr->tkwin));
    return TCL_OK;
}

/*
 *--------------------------------------------------------------
 *
 * ButtonWidgetCmd --
784
785
786
787
788
789
790
791

792
793
794
795
796
797
798
785
786
787
788
789
790
791

792
793
794
795
796
797
798
799







-
+







static int
ButtonWidgetObjCmd(
    ClientData clientData,	/* Information about button widget. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument values. */
{
    TkButton *butPtr = clientData;
    TkButton *butPtr = (TkButton *)clientData;
    int index;
    int result;
    Tcl_Obj *objPtr;

    if (objc < 2) {
        Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
	return TCL_ERROR;
806
807
808
809
810
811
812
813

814
815
816
817
818
819
820
821
822
823

824
825
826
827
828
829
830
807
808
809
810
811
812
813

814
815
816
817
818
819
820
821
822
823

824
825
826
827
828
829
830
831







-
+









-
+








    switch (map[butPtr->type][index]) {
    case COMMAND_CGET:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 1, objv, "cget option");
	    goto error;
	}
	objPtr = Tk_GetOptionValue(interp, (char *) butPtr,
	objPtr = Tk_GetOptionValue(interp, butPtr,
		butPtr->optionTable, objv[2], butPtr->tkwin);
	if (objPtr == NULL) {
	    goto error;
	}
	Tcl_SetObjResult(interp, objPtr);
	break;

    case COMMAND_CONFIGURE:
	if (objc <= 3) {
	    objPtr = Tk_GetOptionInfo(interp, (char *) butPtr,
	    objPtr = Tk_GetOptionInfo(interp, butPtr,
		    butPtr->optionTable, (objc == 3) ? objv[2] : NULL,
		    butPtr->tkwin);
	    if (objPtr == NULL) {
		goto error;
	    }
	    Tcl_SetObjResult(interp, objPtr);
	} else {
1032
1033
1034
1035
1036
1037
1038
1039

1040
1041
1042
1043
1044
1045
1046
1033
1034
1035
1036
1037
1038
1039

1040
1041
1042
1043
1044
1045
1046
1047







-
+







 *
 *----------------------------------------------------------------------
 */

static int
ConfigureButton(
    Tcl_Interp *interp,		/* Used for error reporting. */
    register TkButton *butPtr,	/* Information about widget;  may or may
    TkButton *butPtr,	/* Information about widget;  may or may
				 * not already have values for some fields. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument values. */
{
    Tk_SavedOptions savedOptions;
    Tcl_Obj *errorResult = NULL;
    int error, haveImage;
1070
1071
1072
1073
1074
1075
1076
1077

1078
1079
1080
1081
1082
1083
1084
1071
1072
1073
1074
1075
1076
1077

1078
1079
1080
1081
1082
1083
1084
1085







-
+








    for (error = 0; error <= 1; error++) {
	if (!error) {
	    /*
	     * First pass: set options to new values.
	     */

	    if (Tk_SetOptions(interp, (char *) butPtr,
	    if (Tk_SetOptions(interp, butPtr,
		    butPtr->optionTable, objc, objv,
		    butPtr->tkwin, &savedOptions, NULL) != TCL_OK) {
		continue;
	    }
	} else {
	    /*
	     * Second pass: restore options to old values.
1122
1123
1124
1125
1126
1127
1128
1129

1130
1131
1132
1133
1134
1135
1136
1123
1124
1125
1126
1127
1128
1129

1130
1131
1132
1133
1134
1135
1136
1137







-
+







	}

	if (butPtr->type >= TYPE_CHECK_BUTTON) {
	    Tcl_Obj *valuePtr, *namePtr;

	    if (butPtr->selVarNamePtr == NULL) {
		butPtr->selVarNamePtr = Tcl_NewStringObj(
			Tk_Name(butPtr->tkwin), -1);
			Tk_Name(butPtr->tkwin), TCL_INDEX_NONE);
		Tcl_IncrRefCount(butPtr->selVarNamePtr);
	    }
	    namePtr = butPtr->selVarNamePtr;

	    /*
	     * Select the button if the associated variable has the
	     * appropriate value, initialize the variable if it doesn't exist,
1344
1345
1346
1347
1348
1349
1350
1351

1352
1353
1354
1355
1356
1357
1358
1345
1346
1347
1348
1349
1350
1351

1352
1353
1354
1355
1356
1357
1358
1359







-
+







void
TkButtonWorldChanged(
    ClientData instanceData)	/* Information about widget. */
{
    XGCValues gcValues;
    GC newGC;
    unsigned long mask;
    TkButton *butPtr = instanceData;
    TkButton *butPtr = (TkButton *)instanceData;

    /*
     * Recompute GCs.
     */

    gcValues.font = Tk_FontId(butPtr->tkfont);
    gcValues.foreground = butPtr->normalFg->pixel;
1455
1456
1457
1458
1459
1460
1461
1462

1463
1464
1465
1466
1467
1468
1469
1456
1457
1458
1459
1460
1461
1462

1463
1464
1465
1466
1467
1468
1469
1470







-
+







 */

static void
ButtonEventProc(
    ClientData clientData,	/* Information about window. */
    XEvent *eventPtr)		/* Information about event. */
{
    TkButton *butPtr = clientData;
    TkButton *butPtr = (TkButton *)clientData;
    if ((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0)) {
	goto redraw;
    } else if (eventPtr->type == ConfigureNotify) {
	/*
	 * Must redraw after size changes, since layout could have changed and
	 * borders will need to be redrawn.
	 */
1513
1514
1515
1516
1517
1518
1519
1520

1521
1522
1523
1524
1525
1526
1527
1514
1515
1516
1517
1518
1519
1520

1521
1522
1523
1524
1525
1526
1527
1528







-
+







 *----------------------------------------------------------------------
 */

static void
ButtonCmdDeletedProc(
    ClientData clientData)	/* Pointer to widget record for widget. */
{
    TkButton *butPtr = clientData;
    TkButton *butPtr = (TkButton *)clientData;

    /*
     * This function could be invoked either because the window was destroyed
     * and the command was then deleted or because the command was deleted,
     * and then this function destroys the widget. The BUTTON_DELETED flag
     * distinguishes these cases.
     */
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615

1616
1617


1618
1619
1620
1621
1622
1623
1624
1600
1601
1602
1603
1604
1605
1606

1607
1608
1609
1610
1611
1612
1613
1614

1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626







-








-
+


+
+







 *
 * Side effects:
 *	The button may become selected or deselected.
 *
 *--------------------------------------------------------------
 */

	/* ARGSUSED */
static char *
ButtonVarProc(
    ClientData clientData,	/* Information about button. */
    Tcl_Interp *interp,		/* Interpreter containing variable. */
    const char *name1,		/* Name of variable. */
    const char *name2,		/* Second part of variable name. */
    int flags)			/* Information about what happened. */
{
    register TkButton *butPtr = clientData;
    TkButton *butPtr = (TkButton *)clientData;
    const char *value;
    Tcl_Obj *valuePtr;
    (void)name1;
    (void)name2;

    /*
     * If the variable is being unset, then just re-establish the trace unless
     * the whole interpreter is going away.
     */

    if (flags & TCL_TRACE_UNSETS) {
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725

1726


1727
1728
1729
1730
1731
1732
1733
1711
1712
1713
1714
1715
1716
1717

1718
1719
1720
1721
1722
1723
1724
1725

1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736







-








-
+

+
+







 *
 * Side effects:
 *	The text displayed in the button will change to match the variable.
 *
 *--------------------------------------------------------------
 */

	/* ARGSUSED */
static char *
ButtonTextVarProc(
    ClientData clientData,	/* Information about button. */
    Tcl_Interp *interp,		/* Interpreter containing variable. */
    const char *name1,		/* Not used. */
    const char *name2,		/* Not used. */
    int flags)			/* Information about what happened. */
{
    TkButton *butPtr = clientData;
    TkButton *butPtr = (TkButton *)clientData;
    Tcl_Obj *valuePtr;
    (void)name1;
    (void)name2;

    if (butPtr->flags & BUTTON_DELETED) {
	return NULL;
    }

    /*
     * If the variable is unset, then immediately recreate it unless the whole
1813
1814
1815
1816
1817
1818
1819
1820







1821
1822
1823
1824
1825
1826
1827
1816
1817
1818
1819
1820
1821
1822

1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836







-
+
+
+
+
+
+
+







    ClientData clientData,	/* Pointer to widget record. */
    int x, int y,		/* Upper left pixel (within image) that must
				 * be redisplayed. */
    int width, int height,	/* Dimensions of area to redisplay (might be
				 * <= 0). */
    int imgWidth, int imgHeight)/* New dimensions of image. */
{
    register TkButton *butPtr = clientData;
    TkButton *butPtr = (TkButton *)clientData;
    (void)x;
    (void)y;
    (void)width;
    (void)height;
    (void)imgWidth;
    (void)imgHeight;

    if (butPtr->tkwin != NULL) {
	TkpComputeButtonGeometry(butPtr);
	if (Tk_IsMapped(butPtr->tkwin) && !(butPtr->flags & REDRAW_PENDING)) {
	    Tcl_DoWhenIdle(TkpDisplayButton, butPtr);
	    butPtr->flags |= REDRAW_PENDING;
	}
1851
1852
1853
1854
1855
1856
1857
1858







1859
1860
1861
1862
1863
1864
1865
1860
1861
1862
1863
1864
1865
1866

1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880







-
+
+
+
+
+
+
+







    ClientData clientData,	/* Pointer to widget record. */
    int x, int y,		/* Upper left pixel (within image) that must
				 * be redisplayed. */
    int width, int height,	/* Dimensions of area to redisplay (might be
				 * <= 0). */
    int imgWidth, int imgHeight)/* New dimensions of image. */
{
    register TkButton *butPtr = clientData;
    TkButton *butPtr = (TkButton *)clientData;
    (void)x;
    (void)y;
    (void)width;
    (void)height;
    (void)imgWidth;
    (void)imgHeight;

#ifdef MAC_OSX_TK
    if (butPtr->tkwin != NULL) {
	TkpComputeButtonGeometry(butPtr);
    }
#else
    /*
1898
1899
1900
1901
1902
1903
1904
1905







1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919

1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933







-
+
+
+
+
+
+
+







    ClientData clientData,	/* Pointer to widget record. */
    int x, int y,		/* Upper left pixel (within image) that must
				 * be redisplayed. */
    int width, int height,	/* Dimensions of area to redisplay (might be
				 * <= 0). */
    int imgWidth, int imgHeight)/* New dimensions of image. */
{
    register TkButton *butPtr = clientData;
    TkButton *butPtr = (TkButton *)clientData;
    (void)x;
    (void)y;
    (void)width;
    (void)height;
    (void)imgWidth;
    (void)imgHeight;

#ifdef MAC_OSX_TK
    if (butPtr->tkwin != NULL) {
	TkpComputeButtonGeometry(butPtr);
    }
#else
    /*
Changes to generic/tkButton.h.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







/*
 * 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.
 */

#ifndef _TKBUTTON
#define _TKBUTTON
302
303
304
305
306
307
308
309

310
311
312
313
314
315
316
317
318
319
320
321
322
302
303
304
305
306
307
308

309
310
311
312
313
314
315
316
317
318
319
320
321
322







-
+













MODULE_SCOPE char tkDefLabelPady[TCL_INTEGER_SPACE];

/*
 * Declaration of functions used in the implementation of the button widget.
 */

#ifndef TkpButtonSetDefaults
MODULE_SCOPE void	TkpButtonSetDefaults();
MODULE_SCOPE void	TkpButtonSetDefaults(void);
#endif
MODULE_SCOPE void	TkButtonWorldChanged(ClientData instanceData);
MODULE_SCOPE void	TkpComputeButtonGeometry(TkButton *butPtr);
MODULE_SCOPE TkButton	*TkpCreateButton(Tk_Window tkwin);
#ifndef TkpDestroyButton
MODULE_SCOPE void 	TkpDestroyButton(TkButton *butPtr);
#endif
#ifndef TkpDisplayButton
MODULE_SCOPE void	TkpDisplayButton(ClientData clientData);
#endif
MODULE_SCOPE int	TkInvokeButton(TkButton *butPtr);

#endif /* _TKBUTTON */
Changes to generic/tkCanvArc.c.
1
2
3
4
5
6
7


8
9
10
11
12
13
14
15


16
17
18
19
20
21
22
1
2
3
4
5


6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24





-
-
+
+








+
+







/*
 * 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.
 */

#include "tkInt.h"
#include "tkCanvas.h"
#include "default.h"

#include "float.h"

/*
 * The structure below defines the record for each arc item.
 */

typedef enum {
    PIESLICE_STYLE, CHORD_STYLE, ARC_STYLE
59
60
61
62
63
64
65






66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83

84
85

86
87
88
89
90
91
92
93
94

95
96
97
98
99
100
101
102
103
104
105
106
107
108

109
110
111

112
113

114
115

116
117

118
119

120
121
122

123
124
125

126
127

128
129
130

131
132

133
134

135
136

137
138

139
140
141

142
143



144
145

146
147
148

149
150

151
152
153

154
155

156
157

158
159

160
161

162
163
164
165
166

167
168
169
170
171
172
173
174
175
176
177
178

179
180
181
182
183
184
185
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90

91
92

93
94
95
96
97
98
99
100
101

102
103
104
105
106
107
108
109
110
111
112
113
114
115

116
117
118

119
120

121
122

123
124

125
126

127
128
129

130
131
132

133
134

135
136
137

138
139

140
141

142
143

144
145

146
147
148

149
150

151
152
153
154

155
156
157

158
159

160
161
162

163
164

165
166

167
168

169
170

171
172
173
174
175

176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196







+
+
+
+
+
+

















-
+

-
+








-
+













-
+


-
+

-
+

-
+

-
+

-
+


-
+


-
+

-
+


-
+

-
+

-
+

-
+

-
+


-
+

-
+
+
+

-
+


-
+

-
+


-
+

-
+

-
+

-
+

-
+




-
+












+







    Style style;		/* How to draw arc: arc, chord, or
				 * pieslice. */
    GC fillGC;			/* Graphics context for filling item. */
    double center1[2];		/* Coordinates of center of arc outline at
				 * start (see ComputeArcOutline). */
    double center2[2];		/* Coordinates of center of arc outline at
				 * start+extent (see ComputeArcOutline). */
    double height;              /* Distance from the arc's chord to its
				 * mid-point. */
    double startPoint[2];       /* Start point of arc used when specifying
				 * height. */
    double endPoint[2];         /* End point of arc used when specifying
				 * height. */
} ArcItem;

/*
 * The definitions below define the sizes of the polygons used to display
 * outline information for various styles of arcs:
 */

#define CHORD_OUTLINE_PTS	7
#define PIE_OUTLINE1_PTS	6
#define PIE_OUTLINE2_PTS	7

/*
 * Information used for parsing configuration specs:
 */

static int	StyleParseProc(ClientData clientData, Tcl_Interp *interp,
		    Tk_Window tkwin, const char *value,
		    char *widgRec, int offset);
		    char *widgRec, TkSizeT offset);
static const char * StylePrintProc(ClientData clientData, Tk_Window tkwin,
		    char *widgRec, int offset, Tcl_FreeProc **freeProcPtr);
		    char *widgRec, TkSizeT offset, Tcl_FreeProc **freeProcPtr);

static const Tk_CustomOption stateOption = {
    TkStateParseProc, TkStatePrintProc, INT2PTR(2)
};
static const Tk_CustomOption styleOption = {
    StyleParseProc, StylePrintProc, NULL
};
static const Tk_CustomOption tagsOption = {
    Tk_CanvasTagsParseProc, Tk_CanvasTagsPrintProc, NULL
    TkCanvasTagsParseProc, TkCanvasTagsPrintProc, NULL
};
static const Tk_CustomOption dashOption = {
    TkCanvasDashParseProc, TkCanvasDashPrintProc, NULL
};
static const Tk_CustomOption offsetOption = {
    TkOffsetParseProc, TkOffsetPrintProc, INT2PTR(TK_OFFSET_RELATIVE)
};
static const Tk_CustomOption pixelOption = {
    TkPixelParseProc, TkPixelPrintProc, NULL
};

static const Tk_ConfigSpec configSpecs[] = {
    {TK_CONFIG_CUSTOM, "-activedash", NULL, NULL,
	NULL, Tk_Offset(ArcItem, outline.activeDash),
	NULL, offsetof(ArcItem, outline.activeDash),
	TK_CONFIG_NULL_OK, &dashOption},
    {TK_CONFIG_COLOR, "-activefill", NULL, NULL,
	NULL, Tk_Offset(ArcItem, activeFillColor), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(ArcItem, activeFillColor), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_COLOR, "-activeoutline", NULL, NULL,
	NULL, Tk_Offset(ArcItem, outline.activeColor), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(ArcItem, outline.activeColor), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_BITMAP, "-activeoutlinestipple", NULL, NULL,
	NULL, Tk_Offset(ArcItem, outline.activeStipple), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(ArcItem, outline.activeStipple), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_BITMAP, "-activestipple", NULL, NULL,
	NULL, Tk_Offset(ArcItem, activeFillStipple), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(ArcItem, activeFillStipple), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_CUSTOM, "-activewidth", NULL, NULL,
	"0.0", Tk_Offset(ArcItem, outline.activeWidth),
	"0.0", offsetof(ArcItem, outline.activeWidth),
	TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
    {TK_CONFIG_CUSTOM, "-dash", NULL, NULL,
	NULL, Tk_Offset(ArcItem, outline.dash),
	NULL, offsetof(ArcItem, outline.dash),
	TK_CONFIG_NULL_OK, &dashOption},
    {TK_CONFIG_PIXELS, "-dashoffset", NULL, NULL,
	"0", Tk_Offset(ArcItem, outline.offset), TK_CONFIG_DONT_SET_DEFAULT, NULL},
	"0", offsetof(ArcItem, outline.offset), TK_CONFIG_DONT_SET_DEFAULT, NULL},
    {TK_CONFIG_CUSTOM, "-disableddash", NULL, NULL,
	NULL, Tk_Offset(ArcItem, outline.disabledDash),
	NULL, offsetof(ArcItem, outline.disabledDash),
	TK_CONFIG_NULL_OK, &dashOption},
    {TK_CONFIG_COLOR, "-disabledfill", NULL, NULL,
	NULL, Tk_Offset(ArcItem, disabledFillColor), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(ArcItem, disabledFillColor), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_COLOR, "-disabledoutline", NULL, NULL,
	NULL, Tk_Offset(ArcItem, outline.disabledColor), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(ArcItem, outline.disabledColor), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_BITMAP, "-disabledoutlinestipple", NULL, NULL,
	NULL, Tk_Offset(ArcItem, outline.disabledStipple), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(ArcItem, outline.disabledStipple), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_BITMAP, "-disabledstipple", NULL, NULL,
	NULL, Tk_Offset(ArcItem, disabledFillStipple), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(ArcItem, disabledFillStipple), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_CUSTOM, "-disabledwidth", NULL, NULL,
	"0.0", Tk_Offset(ArcItem, outline.disabledWidth),
	"0.0", offsetof(ArcItem, outline.disabledWidth),
	TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
    {TK_CONFIG_DOUBLE, "-extent", NULL, NULL,
	"90", Tk_Offset(ArcItem, extent), TK_CONFIG_DONT_SET_DEFAULT, NULL},
	"90", offsetof(ArcItem, extent), TK_CONFIG_DONT_SET_DEFAULT, NULL},
    {TK_CONFIG_COLOR, "-fill", NULL, NULL,
	NULL, Tk_Offset(ArcItem, fillColor), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(ArcItem, fillColor), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_DOUBLE, "-height", NULL, NULL,
	0, offsetof(ArcItem, height), TK_CONFIG_DONT_SET_DEFAULT, NULL},
    {TK_CONFIG_CUSTOM, "-offset", NULL, NULL,
	"0,0", Tk_Offset(ArcItem, tsoffset),
	"0,0", offsetof(ArcItem, tsoffset),
	TK_CONFIG_DONT_SET_DEFAULT, &offsetOption},
    {TK_CONFIG_COLOR, "-outline", NULL, NULL,
	DEF_CANVITEM_OUTLINE, Tk_Offset(ArcItem, outline.color), TK_CONFIG_NULL_OK, NULL},
	DEF_CANVITEM_OUTLINE, offsetof(ArcItem, outline.color), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_CUSTOM, "-outlineoffset", NULL, NULL,
	"0,0", Tk_Offset(ArcItem, outline.tsoffset),
	"0,0", offsetof(ArcItem, outline.tsoffset),
	TK_CONFIG_DONT_SET_DEFAULT, &offsetOption},
    {TK_CONFIG_BITMAP, "-outlinestipple", NULL, NULL,
	NULL, Tk_Offset(ArcItem, outline.stipple), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(ArcItem, outline.stipple), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_DOUBLE, "-start", NULL, NULL,
	"0", Tk_Offset(ArcItem, start), TK_CONFIG_DONT_SET_DEFAULT, NULL},
	"0", offsetof(ArcItem, start), TK_CONFIG_DONT_SET_DEFAULT, NULL},
    {TK_CONFIG_CUSTOM, "-state", NULL, NULL,
	NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK, &stateOption},
	NULL, offsetof(Tk_Item, state), TK_CONFIG_NULL_OK, &stateOption},
    {TK_CONFIG_BITMAP, "-stipple", NULL, NULL,
	NULL, Tk_Offset(ArcItem, fillStipple), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(ArcItem, fillStipple), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_CUSTOM, "-style", NULL, NULL,
	NULL, Tk_Offset(ArcItem, style), TK_CONFIG_DONT_SET_DEFAULT,
	NULL, offsetof(ArcItem, style), TK_CONFIG_DONT_SET_DEFAULT,
	&styleOption},
    {TK_CONFIG_CUSTOM, "-tags", NULL, NULL,
	NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},
    {TK_CONFIG_CUSTOM, "-width", NULL, NULL,
	"1.0", Tk_Offset(ArcItem, outline.width), TK_CONFIG_DONT_SET_DEFAULT,
	"1.0", offsetof(ArcItem, outline.width), TK_CONFIG_DONT_SET_DEFAULT,
	&pixelOption},
    {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL}
};

/*
 * Prototypes for functions defined in this file:
 */

static void		ComputeArcBbox(Tk_Canvas canvas, ArcItem *arcPtr);
static int		ConfigureArc(Tcl_Interp *interp,
			    Tk_Canvas canvas, Tk_Item *itemPtr, int objc,
			    Tcl_Obj *const objv[], int flags);
static void		ComputeArcParametersFromHeight(ArcItem *arcPtr);
static int		CreateArc(Tcl_Interp *interp,
			    Tk_Canvas canvas, struct Tk_Item *itemPtr,
			    int objc, Tcl_Obj *const objv[]);
static void		DeleteArc(Tk_Canvas canvas,
			    Tk_Item *itemPtr, Display *display);
static void		DisplayArc(Tk_Canvas canvas,
			    Tk_Item *itemPtr, Display *display, Drawable dst,
202
203
204
205
206
207
208


209
210
211
212
213
214
215
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228







+
+







static void		ComputeArcOutline(Tk_Canvas canvas, ArcItem *arcPtr);
static int		HorizLineToArc(double x1, double x2,
			    double y, double rx, double ry,
			    double start, double extent);
static int		VertLineToArc(double x, double y1,
			    double y2, double rx, double ry,
			    double start, double extent);
static void		RotateArc(Tk_Canvas canvas, Tk_Item *itemPtr,
			    double originX, double originY, double angleRad);

/*
 * The structures below defines the arc item types by means of functions that
 * can be invoked by generic item code.
 */

Tk_ItemType tkArcType = {
229
230
231
232
233
234
235

236

237
238
239
240
241
242
243
242
243
244
245
246
247
248
249

250
251
252
253
254
255
256
257







+
-
+







    TranslateArc,		/* translateProc */
    NULL,			/* indexProc */
    NULL,			/* icursorProc */
    NULL,			/* selectionProc */
    NULL,			/* insertProc */
    NULL,			/* dTextProc */
    NULL,			/* nextPtr */
    RotateArc,			/* rotateProc */
    NULL, 0, NULL, NULL
    0, NULL, NULL
};

/*
 *--------------------------------------------------------------
 *
 * CreateArc --
 *
288
289
290
291
292
293
294

295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316







+







    arcPtr->activeFillColor = NULL;
    arcPtr->disabledFillColor = NULL;
    arcPtr->fillStipple = None;
    arcPtr->activeFillStipple = None;
    arcPtr->disabledFillStipple = None;
    arcPtr->style = PIESLICE_STYLE;
    arcPtr->fillGC = NULL;
    arcPtr->height = 0;

    /*
     * Process the arguments to fill in the item record.
     */

    for (i = 1; i < objc; i++) {
	const char *arg = Tcl_GetString(objv[i]);
348
349
350
351
352
353
354
355
356


357
358
359
360
361
362
363
363
364
365
366
367
368
369


370
371
372
373
374
375
376
377
378







-
-
+
+







	Tcl_Obj *objs[4];

	objs[0] = Tcl_NewDoubleObj(arcPtr->bbox[0]);
	objs[1] = Tcl_NewDoubleObj(arcPtr->bbox[1]);
	objs[2] = Tcl_NewDoubleObj(arcPtr->bbox[2]);
	objs[3] = Tcl_NewDoubleObj(arcPtr->bbox[3]);
	Tcl_SetObjResult(interp, Tcl_NewListObj(4, objs));
    } else if ((objc == 1)||(objc == 4)) {
	if (objc==1) {
    } else if ((objc == 1) || (objc == 4)) {
	if (objc == 1) {
	    if (Tcl_ListObjGetElements(interp, objv[0], &objc,
		    (Tcl_Obj ***) &objv) != TCL_OK) {
		return TCL_ERROR;
	    } else if (objc != 4) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"wrong # coordinates: expected 4, got %d", objc));
		Tcl_SetErrorCode(interp, "TK", "CANVAS", "COORDS", "ARC",
371
372
373
374
375
376
377











378
379
380
381
382
383
384
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410







+
+
+
+
+
+
+
+
+
+
+







		    &arcPtr->bbox[1]) != TCL_OK)
		|| (Tk_CanvasGetCoordFromObj(interp, canvas, objv[2],
			&arcPtr->bbox[2]) != TCL_OK)
		|| (Tk_CanvasGetCoordFromObj(interp, canvas, objv[3],
			&arcPtr->bbox[3]) != TCL_OK)) {
	    return TCL_ERROR;
	}

	/*
	 * Store bbox as start and end points so they can be used if either
	 * radius or height is specified.
	 */

	arcPtr->startPoint[0] = arcPtr->bbox[0];
	arcPtr->startPoint[1] = arcPtr->bbox[1];
	arcPtr->endPoint[0] = arcPtr->bbox[2];
	arcPtr->endPoint[1] = arcPtr->bbox[3];

	ComputeArcBbox(canvas, arcPtr);
    } else {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"wrong # coordinates: expected 0 or 4, got %d", objc));
	Tcl_SetErrorCode(interp, "TK", "CANVAS", "COORDS", "ARC", NULL);
	return TCL_ERROR;
    }
444
445
446
447
448
449
450
















451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509








510
511
512
513
514
515
516







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

















-
-
-
-
-
-
-
-







	    arcPtr->activeFillColor != NULL ||
	    arcPtr->activeFillStipple != None) {
	itemPtr->redraw_flags |= TK_ITEM_STATE_DEPENDANT;
    } else {
	itemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT;
    }

    /*
     * Override the start and extent if the height is given.
     */

    ComputeArcParametersFromHeight(arcPtr);

    ComputeArcBbox(canvas, arcPtr);

    i = (int) (arcPtr->start/360.0);
    arcPtr->start -= i*360.0;
    if (arcPtr->start < 0) {
	arcPtr->start += 360.0;
    }
    i = (int) (arcPtr->extent/360.0);
    arcPtr->extent -= i*360.0;

    tsoffset = &arcPtr->outline.tsoffset;
    flags = tsoffset->flags;
    if (flags & TK_OFFSET_LEFT) {
	tsoffset->xoffset = (int) (arcPtr->bbox[0] + 0.5);
    } else if (flags & TK_OFFSET_CENTER) {
	tsoffset->xoffset = (int) ((arcPtr->bbox[0]+arcPtr->bbox[2]+1)/2);
    } else if (flags & TK_OFFSET_RIGHT) {
	tsoffset->xoffset = (int) (arcPtr->bbox[2] + 0.5);
    }
    if (flags & TK_OFFSET_TOP) {
	tsoffset->yoffset = (int) (arcPtr->bbox[1] + 0.5);
    } else if (flags & TK_OFFSET_MIDDLE) {
	tsoffset->yoffset = (int) ((arcPtr->bbox[1]+arcPtr->bbox[3]+1)/2);
    } else if (flags & TK_OFFSET_BOTTOM) {
	tsoffset->yoffset = (int) (arcPtr->bbox[2] + 0.5);
    }

    i = (int) (arcPtr->start/360.0);
    arcPtr->start -= i*360.0;
    if (arcPtr->start < 0) {
	arcPtr->start += 360.0;
    }
    i = (int) (arcPtr->extent/360.0);
    arcPtr->extent -= i*360.0;

    mask = Tk_ConfigOutlineGC(&gcValues, canvas, itemPtr, &(arcPtr->outline));
    if (mask) {
	gcValues.cap_style = CapButt;
	mask |= GCCapStyle;
	newGC = Tk_GetGC(tkwin, mask, &gcValues);
    } else {
	newGC = NULL;
506
507
508
509
510
511
512
513

514
515
516
517
518
519
520
540
541
542
543
544
545
546

547
548
549
550
551
552
553
554







-
+







    } else if (state==TK_STATE_DISABLED) {
	if (arcPtr->disabledFillColor!=NULL) {
	    color = arcPtr->disabledFillColor;
	}
	if (arcPtr->disabledFillStipple!=None) {
	    stipple = arcPtr->disabledFillStipple;
	}
      }
    }

    if (arcPtr->style == ARC_STYLE) {
	newGC = NULL;
    } else if (color == NULL) {
	newGC = NULL;
    } else {
	gcValues.foreground = color->pixel;
556
557
558
559
560
561
562

































































































563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579

580
581
582
583

584
585
586
587
588
589
590
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709

710
711
712
713

714
715
716
717
718
719
720
721







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
















-
+



-
+







    ComputeArcBbox(canvas, arcPtr);
    return TCL_OK;
}

/*
 *--------------------------------------------------------------
 *
 * ComputeArcParametersFromHeight --
 *
 *	This function calculates the arc parameters given start-point,
 *	end-point and height (!= 0).
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The height parameter is set to 0 on exit.
 *
 *--------------------------------------------------------------
 */

static void
ComputeArcParametersFromHeight(
    ArcItem* arcPtr)
{
    double chordLen, chordDir[2], chordCen[2], arcCen[2], d, radToDeg, radius;

    /*
     * Do nothing if no height has been specified.
     */

    if (arcPtr->height == 0)
        return;

    /*
     * Calculate the chord length, return early if it is too small.
     */

    chordLen = hypot(arcPtr->endPoint[1] - arcPtr->startPoint[1],
	    arcPtr->startPoint[0] - arcPtr->endPoint[0]);

    if (chordLen < DBL_EPSILON) {
        arcPtr->start = arcPtr->extent = arcPtr->height = 0;
        return;
    }

    chordDir[0] = (arcPtr->endPoint[0] - arcPtr->startPoint[0]) / chordLen;
    chordDir[1] = (arcPtr->endPoint[1] - arcPtr->startPoint[1]) / chordLen;
    chordCen[0] = (arcPtr->startPoint[0] + arcPtr->endPoint[0]) / 2;
    chordCen[1] = (arcPtr->startPoint[1] + arcPtr->endPoint[1]) / 2;

    /*
     * Calculate the radius (assumes height != 0).
     */

    radius = (4*pow(arcPtr->height, 2) + pow(chordLen, 2))
	    / (8 * arcPtr->height);

    /*
     * The arc centre.
     */

    d = radius - arcPtr->height;
    arcCen[0] = chordCen[0] - d * chordDir[1];
    arcCen[1] = chordCen[1] + d * chordDir[0];

    /*
     * The arc start and span. Angles are negated because the coordinate
     * system is left-handed.
     */

    radToDeg = 45 / atan(1);
    arcPtr->start = atan2(arcCen[1] - arcPtr->startPoint[1],
	    arcPtr->startPoint[0] - arcCen[0]) * radToDeg;
    arcPtr->extent = -2 * asin(chordLen / (2 * radius)) * radToDeg;

    /*
     * Handle spans > 180.
     */

    if (fabs(2 * arcPtr->height) > chordLen) {
	arcPtr->extent = arcPtr->extent > 0 ? (360 - arcPtr->extent)
		: -(360 + arcPtr->extent);
    }

    /*
     * Create the bounding box.
     */

    arcPtr->bbox[0] = arcCen[0] - radius;
    arcPtr->bbox[1] = arcCen[1] - radius;
    arcPtr->bbox[2] = arcCen[0] + radius;
    arcPtr->bbox[3] = arcCen[1] + radius;

    /*
     * Set the height to 0 so that itemcget -height returns 0.
     */

    arcPtr->height = 0;
}

/*
 *--------------------------------------------------------------
 *
 * DeleteArc --
 *
 *	This function is called to clean up the data structure associated with
 *	an arc item.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Resources associated with itemPtr are released.
 *
 *--------------------------------------------------------------
 */

static void
DeleteArc(
    Tk_Canvas canvas,		/* Info about overall canvas. */
    TCL_UNUSED(Tk_Canvas),		/* Info about overall canvas. */
    Tk_Item *itemPtr,		/* Item that is being deleted. */
    Display *display)		/* Display containing window for canvas. */
{
    ArcItem *arcPtr = (ArcItem *) itemPtr;
    ArcItem *arcPtr = (ArcItem *)itemPtr;

    Tk_DeleteOutline(display, &(arcPtr->outline));
    if (arcPtr->numOutlinePoints != 0) {
	ckfree(arcPtr->outlinePtr);
    }
    if (arcPtr->fillColor != NULL) {
	Tk_FreeColor(arcPtr->fillColor);
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
753
754
755
756
757
758
759

760
761
762
763
764
765
766







-







 *
 * Side effects:
 *	The fields x1, y1, x2, and y2 are updated in the header for itemPtr.
 *
 *--------------------------------------------------------------
 */

	/* ARGSUSED */
static void
ComputeArcBbox(
    Tk_Canvas canvas,		/* Canvas that contains item. */
    ArcItem *arcPtr)		/* Item whose bbox is to be recomputed. */
{
    double tmp, center[2], point[2];
    double width;
659
660
661
662
663
664
665
666

667
668
669
670
671
672

673
674
675
676
677
678
679
680
681

682
683
684
685
686
687
688
789
790
791
792
793
794
795

796
797
798
799
800
801

802
803
804
805
806
807
808
809
810

811
812
813
814
815
816
817
818







-
+





-
+








-
+







    }

    /*
     * Make sure that the first coordinates are the lowest ones.
     */

    if (arcPtr->bbox[1] > arcPtr->bbox[3]) {
	double tmp = arcPtr->bbox[3];
	tmp = arcPtr->bbox[3];

	arcPtr->bbox[3] = arcPtr->bbox[1];
	arcPtr->bbox[1] = tmp;
    }
    if (arcPtr->bbox[0] > arcPtr->bbox[2]) {
	double tmp = arcPtr->bbox[2];
	tmp = arcPtr->bbox[2];

	arcPtr->bbox[2] = arcPtr->bbox[0];
	arcPtr->bbox[0] = tmp;
    }

    ComputeArcOutline(canvas,arcPtr);

    /*
     * To compute the bounding box, start with the the bbox formed by the two
     * To compute the bounding box, start with the bbox formed by the two
     * endpoints of the arc. Then add in the center of the arc's oval (if
     * relevant) and the 3-o'clock, 6-o'clock, 9-o'clock, and 12-o'clock
     * positions, if they are relevant.
     */

    arcPtr->header.x1 = arcPtr->header.x2 = (int) arcPtr->center1[0];
    arcPtr->header.y1 = arcPtr->header.y2 = (int) arcPtr->center1[1];
765
766
767
768
769
770
771
772
773




774
775
776
777
778
779
780
895
896
897
898
899
900
901


902
903
904
905
906
907
908
909
910
911
912







-
-
+
+
+
+








static void
DisplayArc(
    Tk_Canvas canvas,		/* Canvas that contains item. */
    Tk_Item *itemPtr,		/* Item to be displayed. */
    Display *display,		/* Display on which to draw item. */
    Drawable drawable,		/* Pixmap or window in which to draw item. */
    int x, int y,		/* Describes region of canvas that must be */
    int width, int height)	/* redisplayed (not used). */
    TCL_UNUSED(int),		/* Describes region of canvas that must be */
    TCL_UNUSED(int),	/* redisplayed (not used). */
    TCL_UNUSED(int),
    TCL_UNUSED(int))
{
    ArcItem *arcPtr = (ArcItem *) itemPtr;
    short x1, y1, x2, y2;
    int start, extent, dashnumber;
    double lineWidth;
    Tk_State state = itemPtr->state;
    Pixmap stipple;
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
1070
1071
1072
1073
1074
1075
1076

1077
1078
1079
1080
1081
1082
1083







-







 *
 * Side effects:
 *	None.
 *
 *--------------------------------------------------------------
 */

	/* ARGSUSED */
static double
ArcToPoint(
    Tk_Canvas canvas,		/* Canvas containing item. */
    Tk_Item *itemPtr,		/* Item to check against point. */
    double *pointPtr)		/* Pointer to x and y coordinates. */
{
    ArcItem *arcPtr = (ArcItem *) itemPtr;
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1234
1235
1236
1237
1238
1239
1240

1241
1242
1243
1244
1245
1246
1247







-







 *
 * Side effects:
 *	None.
 *
 *--------------------------------------------------------------
 */

	/* ARGSUSED */
static int
ArcToArea(
    Tk_Canvas canvas,		/* Canvas containing item. */
    Tk_Item *itemPtr,		/* Item to check against arc. */
    double *rectPtr)		/* Pointer to array of four coordinates (x1,
				 * y1, x2, y2) describing rectangular area. */
{
1376
1377
1378
1379
1380
1381
1382






















































1383
1384
1385
1386
1387
1388
1389
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    arcPtr->bbox[3] = originY + scaleY*(arcPtr->bbox[3] - originY);
    ComputeArcBbox(canvas, arcPtr);
}

/*
 *--------------------------------------------------------------
 *
 * RotateArc --
 *
 *	This function is called to rotate an arc by a given amount.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The position of the arc is rotated by angleRad radians about (originX,
 *	originY), and the bounding box is updated in the generic part of the
 *	item structure.
 *
 *--------------------------------------------------------------
 */

static void
RotateArc(
    Tk_Canvas canvas,
    Tk_Item *itemPtr,
    double originX,
    double originY,
    double angleRad)
{
    ArcItem *arcPtr = (ArcItem *) itemPtr;
    double newX, newY, oldX, oldY;

    /*
     * Compute the centre of the box, then rotate that about the origin.
     */

    newX = oldX = (arcPtr->bbox[0] + arcPtr->bbox[2]) / 2.0;
    newY = oldY = (arcPtr->bbox[1] + arcPtr->bbox[3]) / 2.0;
    TkRotatePoint(originX, originY, sin(angleRad), cos(angleRad),
	    &newX, &newY);

    /*
     * Apply the translation to the box.
     */

    arcPtr->bbox[0] += newX - oldX;
    arcPtr->bbox[1] += newY - oldY;
    arcPtr->bbox[2] += newX - oldX;
    arcPtr->bbox[3] += newY - oldY;

    /*
     * TODO: update the arc endpoints?
     */

    ComputeArcBbox(canvas, arcPtr);
}

/*
 *--------------------------------------------------------------
 *
 * TranslateArc --
 *
 *	This function is called to move an arc by a given amount.
 *
 * Results:
 *	None.
 *
1443
1444
1445
1446
1447
1448
1449
1450

1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464

1465
1466
1467
1468
1469
1470
1471
1627
1628
1629
1630
1631
1632
1633

1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647

1648
1649
1650
1651
1652
1653
1654
1655







-
+













-
+








    /*
     * Make sure that the outlinePtr array is large enough to hold either a
     * chord or pie-slice outline.
     */

    if (arcPtr->numOutlinePoints == 0) {
	arcPtr->outlinePtr = ckalloc(26 * sizeof(double));
	arcPtr->outlinePtr = (double *)ckalloc(26 * sizeof(double));
	arcPtr->numOutlinePoints = 22;
    }
    outlinePtr = arcPtr->outlinePtr;

    if (state == TK_STATE_NULL) {
	state = Canvas(canvas)->canvas_state;
    }

    /*
     * First compute the two points that lie at the centers of the ends of the
     * curved arc segment, which are marked with X's in the figure below:
     *
     *
     *				  * * *
     *			          * * *
     *			      *          *
     *			   *      * *      *
     *			 *    *         *    *
     *			*   *             *   *
     *			 X *               * X
     *
     * The code is tricky because the arc can be ovular in shape. It computes
1810
1811
1812
1813
1814
1815
1816
1817

1818
1819
1820
1821
1822
1823
1824
1994
1995
1996
1997
1998
1999
2000

2001
2002
2003
2004
2005
2006
2007
2008







-
+







 */

static int
ArcToPostscript(
    Tcl_Interp *interp,		/* Leave Postscript or error message here. */
    Tk_Canvas canvas,		/* Information about overall canvas. */
    Tk_Item *itemPtr,		/* Item for which Postscript is wanted. */
    int prepass)		/* 1 means this is a prepass to collect font
    TCL_UNUSED(int))		/* 1 means this is a prepass to collect font
				 * information; 0 means final Postscript is
				 * being created. */
{
    ArcItem *arcPtr = (ArcItem *) itemPtr;
    double y1, y2, ang1, ang2;
    XColor *color;
    Pixmap stipple;
1895
1896
1897
1898
1899
1900
1901
1902

1903
1904
1905
1906
1907
1908
1909
1910
1911

1912
1913
1914
1915
1916
1917
1918
1919
1920
2079
2080
2081
2082
2083
2084
2085

2086


2087
2088
2089
2090
2091
2092

2093


2094
2095
2096
2097
2098
2099
2100







-
+
-
-






-
+
-
-







	    Tcl_AppendToObj(psObj, "0 0 moveto ", -1);
	}
	Tcl_AppendPrintfToObj(psObj,
		"0 0 1 %.15g %.15g arc closepath\nsetmatrix\n",
		ang1, ang2);

	Tcl_ResetResult(interp);
	if (Tk_CanvasPsColor(interp, canvas, fillColor) != TCL_OK) {
	Tk_CanvasPsColor(interp, canvas, fillColor);
	    goto error;
	}
	Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));

	if (fillStipple != None) {
	    Tcl_AppendToObj(psObj, "clip ", -1);

	    Tcl_ResetResult(interp);
	    if (Tk_CanvasPsStipple(interp, canvas, fillStipple) != TCL_OK) {
	    Tk_CanvasPsStipple(interp, canvas, fillStipple);
		goto error;
	    }
	    Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));

	    if (arcPtr->outline.gc != NULL) {
		Tcl_AppendToObj(psObj, "grestore gsave\n", -1);
	    }
	} else {
	    Tcl_AppendToObj(psObj, "fill\n", -1);
1932
1933
1934
1935
1936
1937
1938
1939

1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954

1955
1956
1957
1958
1959
1960
1961
1962
1963

1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977

1978
1979
1980
1981
1982
1983
1984
1985
1986

1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2112
2113
2114
2115
2116
2117
2118

2119


2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131

2132


2133
2134
2135
2136
2137
2138

2139


2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150

2151


2152
2153
2154
2155
2156
2157

2158


2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173





2174
2175
2176
2177
2178
2179
2180







-
+
-
-












-
+
-
-






-
+
-
-











-
+
-
-






-
+
-
-















-
-
-
-
-







		(arcPtr->bbox[0] + arcPtr->bbox[2])/2, (y1 + y2)/2,
		(arcPtr->bbox[2] - arcPtr->bbox[0])/2, (y1 - y2)/2);
	Tcl_AppendPrintfToObj(psObj,
		"0 0 1 %.15g %.15g arc\nsetmatrix\n0 setlinecap\n",
		ang1, ang2);

	Tcl_ResetResult(interp);
	if (Tk_CanvasPsOutline(canvas, itemPtr, &arcPtr->outline) != TCL_OK) {
	Tk_CanvasPsOutline(canvas, itemPtr, &arcPtr->outline);
	    goto error;
	}
	Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));

	if (arcPtr->style != ARC_STYLE) {
	    Tcl_AppendToObj(psObj, "grestore gsave\n", -1);

	    Tcl_ResetResult(interp);
	    if (arcPtr->style == CHORD_STYLE) {
		Tk_CanvasPsPath(interp, canvas, arcPtr->outlinePtr,
			CHORD_OUTLINE_PTS);
	    } else {
		Tk_CanvasPsPath(interp, canvas, arcPtr->outlinePtr,
			PIE_OUTLINE1_PTS);
		if (Tk_CanvasPsColor(interp, canvas, color) != TCL_OK) {
		Tk_CanvasPsColor(interp, canvas, color);
		    goto error;
		}
		Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));

		if (stipple != None) {
		    Tcl_AppendToObj(psObj, "clip ", -1);

		    Tcl_ResetResult(interp);
		    if (Tk_CanvasPsStipple(interp, canvas, stipple) !=TCL_OK){
		    Tk_CanvasPsStipple(interp, canvas, stipple);
			goto error;
		    }
		    Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
		} else {
		    Tcl_AppendToObj(psObj, "fill\n", -1);
		}
		Tcl_AppendToObj(psObj, "grestore gsave\n", -1);

		Tcl_ResetResult(interp);
		Tk_CanvasPsPath(interp, canvas,
			arcPtr->outlinePtr + 2*PIE_OUTLINE1_PTS,
			PIE_OUTLINE2_PTS);
	    }
	    if (Tk_CanvasPsColor(interp, canvas, color) != TCL_OK) {
	    Tk_CanvasPsColor(interp, canvas, color);
		goto error;
	    }
	    Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));

	    if (stipple != None) {
		Tcl_AppendToObj(psObj, "clip ", -1);

		Tcl_ResetResult(interp);
		if (Tk_CanvasPsStipple(interp, canvas, stipple) != TCL_OK) {
		Tk_CanvasPsStipple(interp, canvas, stipple);
		    goto error;
		}
		Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
	    } else {
		Tcl_AppendToObj(psObj, "fill\n", -1);
	    }
	}
    }

    /*
     * Plug the accumulated postscript back into the result.
     */

    (void) Tcl_RestoreInterpState(interp, interpState);
    Tcl_AppendObjToObj(Tcl_GetObjResult(interp), psObj);
    Tcl_DecrRefCount(psObj);
    return TCL_OK;

  error:
    Tcl_DiscardInterpState(interpState);
    Tcl_DecrRefCount(psObj);
    return TCL_ERROR;
}

/*
 *--------------------------------------------------------------
 *
 * StyleParseProc --
 *
2024
2025
2026
2027
2028
2029
2030
2031

2032
2033

2034
2035
2036

2037
2038
2039
2040
2041

2042
2043
2044
2045
2046
2047
2048
2189
2190
2191
2192
2193
2194
2195

2196
2197

2198
2199
2200

2201
2202
2203
2204


2205
2206
2207
2208
2209
2210
2211
2212







-
+

-
+


-
+



-
-
+







 *	value argument.
 *
 *--------------------------------------------------------------
 */

static int
StyleParseProc(
    ClientData clientData,	/* some flags.*/
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Used for reporting errors. */
    Tk_Window tkwin,		/* Window containing canvas widget. */
    TCL_UNUSED(Tk_Window),		/* Window containing canvas widget. */
    const char *value,		/* Value of option. */
    char *widgRec,		/* Pointer to record for item. */
    int offset)			/* Offset into item. */
    TkSizeT offset)			/* Offset into item. */
{
    int c;
    size_t length;

    register Style *stylePtr = (Style *) (widgRec + offset);
    Style *stylePtr = (Style *) (widgRec + offset);

    if (value == NULL || *value == 0) {
	*stylePtr = PIESLICE_STYLE;
	return TCL_OK;
    }

    c = value[0];
2088
2089
2090
2091
2092
2093
2094
2095
2096


2097
2098
2099


2100
2101
2102
2103

2104
2105
2106
2107
2108
2109
2110
2252
2253
2254
2255
2256
2257
2258


2259
2260
2261


2262
2263
2264
2265
2266

2267
2268
2269
2270
2271
2272
2273
2274







-
-
+
+

-
-
+
+



-
+







 *	None.
 *
 *--------------------------------------------------------------
 */

static const char *
StylePrintProc(
    ClientData clientData,	/* Ignored. */
    Tk_Window tkwin,		/* Ignored. */
    TCL_UNUSED(void *),	/* Ignored. */
    TCL_UNUSED(Tk_Window),		/* Ignored. */
    char *widgRec,		/* Pointer to record for item. */
    int offset,			/* Offset into item. */
    Tcl_FreeProc **freeProcPtr)	/* Pointer to variable to fill in with
    TkSizeT offset,			/* Offset into item. */
    TCL_UNUSED(Tcl_FreeProc **))	/* Pointer to variable to fill in with
				 * information about how to reclaim storage
				 * for return string. */
{
    register Style *stylePtr = (Style *) (widgRec + offset);
    Style *stylePtr = (Style *) (widgRec + offset);

    if (*stylePtr == ARC_STYLE) {
	return "arc";
    } else if (*stylePtr == CHORD_STYLE) {
	return "chord";
    } else {
	return "pieslice";
Changes to generic/tkCanvBmap.c.
1
2
3
4
5
6
7


8
9
10
11
12
13
14
1
2
3
4
5


6
7
8
9
10
11
12
13
14





-
-
+
+







/*
 * 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.
 */

#include "tkInt.h"
#include "tkCanvas.h"
41
42
43
44
45
46
47
48

49
50
51
52
53

54
55

56
57

58
59

60
61

62
63

64
65

66
67
68

69
70
71

72
73
74

75
76

77
78
79
80
81
82
83
41
42
43
44
45
46
47

48
49
50
51
52

53
54

55
56

57
58

59
60

61
62

63
64

65
66
67

68
69
70

71
72
73

74
75

76
77
78
79
80
81
82
83







-
+




-
+

-
+

-
+

-
+

-
+

-
+

-
+


-
+


-
+


-
+

-
+







 * Information used for parsing configuration specs:
 */

static const Tk_CustomOption stateOption = {
    TkStateParseProc, TkStatePrintProc, INT2PTR(2)
};
static const Tk_CustomOption tagsOption = {
    Tk_CanvasTagsParseProc, Tk_CanvasTagsPrintProc, NULL
    TkCanvasTagsParseProc, TkCanvasTagsPrintProc, NULL
};

static const Tk_ConfigSpec configSpecs[] = {
    {TK_CONFIG_COLOR, "-activebackground", NULL, NULL,
	NULL, Tk_Offset(BitmapItem, activeBgColor), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(BitmapItem, activeBgColor), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_BITMAP, "-activebitmap", NULL, NULL,
	NULL, Tk_Offset(BitmapItem, activeBitmap), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(BitmapItem, activeBitmap), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_COLOR, "-activeforeground", NULL, NULL,
	NULL, Tk_Offset(BitmapItem, activeFgColor), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(BitmapItem, activeFgColor), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_ANCHOR, "-anchor", NULL, NULL,
	"center", Tk_Offset(BitmapItem, anchor), TK_CONFIG_DONT_SET_DEFAULT, NULL},
	"center", offsetof(BitmapItem, anchor), TK_CONFIG_DONT_SET_DEFAULT, NULL},
    {TK_CONFIG_COLOR, "-background", NULL, NULL,
	NULL, Tk_Offset(BitmapItem, bgColor), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(BitmapItem, bgColor), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_BITMAP, "-bitmap", NULL, NULL,
	NULL, Tk_Offset(BitmapItem, bitmap), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(BitmapItem, bitmap), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_COLOR, "-disabledbackground", NULL, NULL,
	NULL, Tk_Offset(BitmapItem, disabledBgColor),
	NULL, offsetof(BitmapItem, disabledBgColor),
	TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_BITMAP, "-disabledbitmap", NULL, NULL,
	NULL, Tk_Offset(BitmapItem, disabledBitmap),
	NULL, offsetof(BitmapItem, disabledBitmap),
	TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_COLOR, "-disabledforeground", NULL, NULL,
	NULL, Tk_Offset(BitmapItem, disabledFgColor),
	NULL, offsetof(BitmapItem, disabledFgColor),
	TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_COLOR, "-foreground", NULL, NULL,
	DEF_CANVBMAP_FG, Tk_Offset(BitmapItem, fgColor), 0, NULL},
	DEF_CANVBMAP_FG, offsetof(BitmapItem, fgColor), 0, NULL},
    {TK_CONFIG_CUSTOM, "-state", NULL, NULL,
	NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK,
	NULL, offsetof(Tk_Item, state), TK_CONFIG_NULL_OK,
	&stateOption},
    {TK_CONFIG_CUSTOM, "-tags", NULL, NULL,
	NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},
    {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL}
};

/*
102
103
104
105
106
107
108


109
110
111
112
113
114
115
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117







+
+







			    Tk_Canvas canvas, struct Tk_Item *itemPtr,
			    int objc, Tcl_Obj *const objv[]);
static void		DeleteBitmap(Tk_Canvas canvas,
			    Tk_Item *itemPtr, Display *display);
static void		DisplayBitmap(Tk_Canvas canvas,
			    Tk_Item *itemPtr, Display *display, Drawable dst,
			    int x, int y, int width, int height);
static void		RotateBitmap(Tk_Canvas canvas, Tk_Item *itemPtr,
			    double originX, double originY, double angleRad);
static void		ScaleBitmap(Tk_Canvas canvas,
			    Tk_Item *itemPtr, double originX, double originY,
			    double scaleX, double scaleY);
static void		TranslateBitmap(Tk_Canvas canvas, Tk_Item *itemPtr,
			    double deltaX, double deltaY);

/*
134
135
136
137
138
139
140

141

142
143
144
145
146
147
148
136
137
138
139
140
141
142
143

144
145
146
147
148
149
150
151







+
-
+







    TranslateBitmap,		/* translateProc */
    NULL,			/* indexProc */
    NULL,			/* icursorProc */
    NULL,			/* selectionProc */
    NULL,			/* insertProc */
    NULL,			/* dTextProc */
    NULL,			/* nextPtr */
    RotateBitmap,		/* rotateProc */
    NULL, 0, NULL, NULL
    0, NULL, NULL
};

/*
 *--------------------------------------------------------------
 *
 * TkcCreateBitmap --
 *
415
416
417
418
419
420
421

422
423
424
425
426
427
428
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432







+







static void
DeleteBitmap(
    Tk_Canvas canvas,		/* Info about overall canvas widget. */
    Tk_Item *itemPtr,		/* Item that is being deleted. */
    Display *display)		/* Display containing window for canvas. */
{
    BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
    (void)canvas;

    if (bmapPtr->bitmap != None) {
	Tk_FreeBitmap(display, bmapPtr->bitmap);
    }
    if (bmapPtr->activeBitmap != None) {
	Tk_FreeBitmap(display, bmapPtr->activeBitmap);
    }
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
470
471
472
473
474
475
476

477
478
479
480
481
482
483







-







 *
 * Side effects:
 *	The fields x1, y1, x2, and y2 are updated in the header for itemPtr.
 *
 *--------------------------------------------------------------
 */

	/* ARGSUSED */
static void
ComputeBitmapBbox(
    Tk_Canvas canvas,		/* Canvas that contains item. */
    BitmapItem *bmapPtr)	/* Item whose bbox is to be recomputed. */
{
    int width, height;
    int x, y;
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679

680
681
682
683
684
685
686
667
668
669
670
671
672
673

674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689







-








+







 *
 * Side effects:
 *	None.
 *
 *--------------------------------------------------------------
 */

	/* ARGSUSED */
static double
BitmapToPoint(
    Tk_Canvas canvas,		/* Canvas containing item. */
    Tk_Item *itemPtr,		/* Item to check against point. */
    double *coordPtr)		/* Pointer to x and y coordinates. */
{
    BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
    double x1, x2, y1, y2, xDiff, yDiff;
    (void)canvas;

    x1 = bmapPtr->header.x1;
    y1 = bmapPtr->header.y1;
    x2 = bmapPtr->header.x2;
    y2 = bmapPtr->header.y2;

    /*
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737

738
739
740
741
742
743
744
724
725
726
727
728
729
730

731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747







-









+







 *
 * Side effects:
 *	None.
 *
 *--------------------------------------------------------------
 */

	/* ARGSUSED */
static int
BitmapToArea(
    Tk_Canvas canvas,		/* Canvas containing item. */
    Tk_Item *itemPtr,		/* Item to check against rectangle. */
    double *rectPtr)		/* Pointer to array of four coordinates
				 * (x1,y1,x2,y2) describing rectangular
				 * area. */
{
    BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
    (void)canvas;

    if ((rectPtr[2] <= bmapPtr->header.x1)
	    || (rectPtr[0] >= bmapPtr->header.x2)
	    || (rectPtr[3] <= bmapPtr->header.y1)
	    || (rectPtr[1] >= bmapPtr->header.y2)) {
	return -1;
    }
783
784
785
786
787
788
789

































790
791
792
793
794
795
796
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







{
    BitmapItem *bmapPtr = (BitmapItem *) itemPtr;

    bmapPtr->x = originX + scaleX*(bmapPtr->x - originX);
    bmapPtr->y = originY + scaleY*(bmapPtr->y - originY);
    ComputeBitmapBbox(canvas, bmapPtr);
}

/*
 *--------------------------------------------------------------
 *
 * RotateBitmap --
 *
 *	This function is called to rotate a bitmap's origin by a given amount.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The position of the bitmap is rotated by angleRad radians about
 *	(originX, originY), and the bounding box is updated in the generic
 *	part of the item structure.
 *
 *--------------------------------------------------------------
 */

static void
RotateBitmap(
    Tk_Canvas canvas,
    Tk_Item *itemPtr,
    double originX,
    double originY,
    double angleRad)
{
    BitmapItem *bmapPtr = (BitmapItem *) itemPtr;

    TkRotatePoint(originX, originY, sin(angleRad), cos(angleRad),
	    &bmapPtr->x, &bmapPtr->y);
    ComputeBitmapBbox(canvas, bmapPtr);
}

/*
 *--------------------------------------------------------------
 *
 * TranslateBitmap --
 *
 *	This function is called to move an item by a given amount.
853
854
855
856
857
858
859

860
861
862
863
864
865
866
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903







+







    int curRow;
    XColor *fgColor;
    XColor *bgColor;
    Pixmap bitmap;
    Tk_State state = itemPtr->state;
    Tcl_Obj *psObj;
    Tcl_InterpState interpState;
    (void)prepass;

    if (state == TK_STATE_NULL) {
	state = Canvas(canvas)->canvas_state;
    }
    fgColor = bmapPtr->fgColor;
    bgColor = bmapPtr->bgColor;
    bitmap = bmapPtr->bitmap;
925
926
927
928
929
930
931
932

933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949

950
951
952
953
954
955
956
957
958
962
963
964
965
966
967
968

969


970
971
972
973
974
975
976
977
978
979
980
981
982
983

984


985
986
987
988
989
990
991







-
+
-
-














-
+
-
-







    if (bgColor != NULL) {
	Tcl_AppendPrintfToObj(psObj,
		"%.15g %.15g moveto %d 0 rlineto 0 %d rlineto "
		"%d 0 rlineto closepath\n",
		x, y, width, height, -width);

	Tcl_ResetResult(interp);
	if (Tk_CanvasPsColor(interp, canvas, bgColor) != TCL_OK) {
	Tk_CanvasPsColor(interp, canvas, bgColor);
	    goto error;
	}
	Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));

	Tcl_AppendToObj(psObj, "fill\n", -1);
    }

    /*
     * Draw the bitmap, if there is a foreground color. If the bitmap is very
     * large, then chop it up into multiple bitmaps, each consisting of one or
     * more rows. This is needed because Postscript can't handle single
     * strings longer than 64 KBytes long.
     */

    if (fgColor != NULL) {
	Tcl_ResetResult(interp);
	if (Tk_CanvasPsColor(interp, canvas, fgColor) != TCL_OK) {
	Tk_CanvasPsColor(interp, canvas, fgColor);
	    goto error;
	}
	Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));

	if (width > 60000) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "can't generate Postscript for bitmaps more than 60000"
		    " pixels wide", -1));
	    Tcl_SetErrorCode(interp, "TK", "CANVAS", "PS", "MEMLIMIT", NULL);
973
974
975
976
977
978
979
980
981


982
983
984
985
986
987
988
989
990
1006
1007
1008
1009
1010
1011
1012


1013
1014


1015
1016
1017
1018
1019
1020
1021







-
-
+
+
-
-







	    }

	    Tcl_AppendPrintfToObj(psObj,
		    "0 -%.15g translate\n%d %d true matrix {\n",
		    (double) rowsThisTime, width, rowsThisTime);

	    Tcl_ResetResult(interp);
	    if (Tk_CanvasPsBitmap(interp, canvas, bitmap,
		    0, curRow, width, rowsThisTime) != TCL_OK) {
	    Tk_CanvasPsBitmap(interp, canvas, bitmap, 0, curRow, width,
		    rowsThisTime);
		goto error;
	    }
	    Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));

	    Tcl_AppendToObj(psObj, "\n} imagemask\n", -1);
	}
    }

    /*
Changes to generic/tkCanvImg.c.
1
2
3
4
5
6
7


8
9
10
11
12
13
14
1
2
3
4
5


6
7
8
9
10
11
12
13
14





-
-
+
+







/*
 * 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.
 */

#include "tkInt.h"
#include "tkCanvas.h"
43
44
45
46
47
48
49
50

51
52
53
54
55

56
57

58
59

60
61

62
63

64
65
66
67
68
69
70
43
44
45
46
47
48
49

50
51
52
53
54

55
56

57
58

59
60

61
62

63
64
65
66
67
68
69
70







-
+




-
+

-
+

-
+

-
+

-
+







 * Information used for parsing configuration specs:
 */

static const Tk_CustomOption stateOption = {
    TkStateParseProc, TkStatePrintProc, INT2PTR(2)
};
static const Tk_CustomOption tagsOption = {
    Tk_CanvasTagsParseProc, Tk_CanvasTagsPrintProc, NULL
    TkCanvasTagsParseProc, TkCanvasTagsPrintProc, NULL
};

static const Tk_ConfigSpec configSpecs[] = {
    {TK_CONFIG_STRING, "-activeimage", NULL, NULL,
	NULL, Tk_Offset(ImageItem, activeImageString), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(ImageItem, activeImageString), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_ANCHOR, "-anchor", NULL, NULL,
	"center", Tk_Offset(ImageItem, anchor), TK_CONFIG_DONT_SET_DEFAULT, NULL},
	"center", offsetof(ImageItem, anchor), TK_CONFIG_DONT_SET_DEFAULT, NULL},
    {TK_CONFIG_STRING, "-disabledimage", NULL, NULL,
	NULL, Tk_Offset(ImageItem, disabledImageString), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(ImageItem, disabledImageString), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_STRING, "-image", NULL, NULL,
	NULL, Tk_Offset(ImageItem, imageString), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(ImageItem, imageString), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_CUSTOM, "-state", NULL, NULL,
	NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK, &stateOption},
	NULL, offsetof(Tk_Item, state), TK_CONFIG_NULL_OK, &stateOption},
    {TK_CONFIG_CUSTOM, "-tags", NULL, NULL,
	NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},
    {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL}
};

/*
 * Prototypes for functions defined in this file:
90
91
92
93
94
95
96


97
98
99
100
101
102
103
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105







+
+







			    Tk_Canvas canvas, struct Tk_Item *itemPtr,
			    int argc, Tcl_Obj *const argv[]);
static void		DeleteImage(Tk_Canvas canvas,
			    Tk_Item *itemPtr, Display *display);
static void		DisplayImage(Tk_Canvas canvas,
			    Tk_Item *itemPtr, Display *display, Drawable dst,
			    int x, int y, int width, int height);
static void		RotateImage(Tk_Canvas canvas, Tk_Item *itemPtr,
			    double originX, double originY, double angleRad);
static void		ScaleImage(Tk_Canvas canvas,
			    Tk_Item *itemPtr, double originX, double originY,
			    double scaleX, double scaleY);
static void		TranslateImage(Tk_Canvas canvas,
			    Tk_Item *itemPtr, double deltaX, double deltaY);

/*
122
123
124
125
126
127
128

129

130
131
132
133
134
135
136
124
125
126
127
128
129
130
131

132
133
134
135
136
137
138
139







+
-
+







    TranslateImage,		/* translateProc */
    NULL,			/* indexProc */
    NULL,			/* icursorProc */
    NULL,			/* selectionProc */
    NULL,			/* insertProc */
    NULL,			/* dTextProc */
    NULL,			/* nextPtr */
    RotateImage,		/* rotateProc */
    NULL, 0, NULL, NULL
    0, NULL, NULL
};

/*
 *--------------------------------------------------------------
 *
 * CreateImage --
 *
378
379
380
381
382
383
384


385
386
387
388
389
390
391
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396







+
+







static void
DeleteImage(
    Tk_Canvas canvas,		/* Info about overall canvas widget. */
    Tk_Item *itemPtr,		/* Item that is being deleted. */
    Display *display)		/* Display containing window for canvas. */
{
    ImageItem *imgPtr = (ImageItem *) itemPtr;
    (void)canvas;
    (void)display;

    if (imgPtr->imageString != NULL) {
	ckfree(imgPtr->imageString);
    }
    if (imgPtr->activeImageString != NULL) {
	ckfree(imgPtr->activeImageString);
    }
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
422
423
424
425
426
427
428

429
430
431
432
433
434
435







-







 *
 * Side effects:
 *	The fields x1, y1, x2, and y2 are updated in the header for itemPtr.
 *
 *--------------------------------------------------------------
 */

	/* ARGSUSED */
static void
ComputeImageBbox(
    Tk_Canvas canvas,		/* Canvas that contains item. */
    ImageItem *imgPtr)		/* Item whose bbox is to be recomputed. */
{
    int width, height;
    int x, y;
530
531
532
533
534
535
536

537
538
539
540
541
542
543
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548







+







				/* Describes region of canvas that must be
				 * redisplayed (not used). */
{
    ImageItem *imgPtr = (ImageItem *) itemPtr;
    short drawableX, drawableY;
    Tk_Image image;
    Tk_State state = itemPtr->state;
    (void)display;

    if (state == TK_STATE_NULL) {
	state = Canvas(canvas)->canvas_state;
    }

    image = imgPtr->image;
    if (Canvas(canvas)->currentItemPtr == itemPtr) {
588
589
590
591
592
593
594

595
596
597
598
599
600
601
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607







+







ImageToPoint(
    Tk_Canvas canvas,		/* Canvas containing item. */
    Tk_Item *itemPtr,		/* Item to check against point. */
    double *coordPtr)		/* Pointer to x and y coordinates. */
{
    ImageItem *imgPtr = (ImageItem *) itemPtr;
    double x1, x2, y1, y2, xDiff, yDiff;
    (void)canvas;

    x1 = imgPtr->header.x1;
    y1 = imgPtr->header.y1;
    x2 = imgPtr->header.x2;
    y2 = imgPtr->header.y2;

    /*
645
646
647
648
649
650
651

652
653
654
655
656
657
658
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665







+







    Tk_Canvas canvas,		/* Canvas containing item. */
    Tk_Item *itemPtr,		/* Item to check against rectangle. */
    double *rectPtr)		/* Pointer to array of four coordinates
				 * (x1,y1,x2,y2) describing rectangular
				 * area. */
{
    ImageItem *imgPtr = (ImageItem *) itemPtr;
    (void)canvas;

    if ((rectPtr[2] <= imgPtr->header.x1)
	    || (rectPtr[0] >= imgPtr->header.x2)
	    || (rectPtr[3] <= imgPtr->header.y1)
	    || (rectPtr[1] >= imgPtr->header.y2)) {
	return -1;
    }
757
758
759
760
761
762
763


































764
765
766
767
768
769
770
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    return Tk_PostscriptImage(image, interp, canvasWin,
	    ((TkCanvas *) canvas)->psInfo, 0, 0, width, height, prepass);
}

/*
 *--------------------------------------------------------------
 *
 * RotateImage --
 *
 *	This function is called to rotate an image's origin by a given amount.
 *	This does *not* rotate the contents of the image.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The position of the image anchor is rotated by angleRad radians about
 *	(originX, originY), and the bounding box is updated in the generic
 *	part of the item structure.
 *
 *--------------------------------------------------------------
 */

static void
RotateImage(
    Tk_Canvas canvas,
    Tk_Item *itemPtr,
    double originX,
    double originY,
    double angleRad)
{
    ImageItem *imgPtr = (ImageItem *) itemPtr;

    TkRotatePoint(originX, originY, sin(angleRad), cos(angleRad),
	    &imgPtr->x, &imgPtr->y);
    ComputeImageBbox(canvas, imgPtr);
}

/*
 *--------------------------------------------------------------
 *
 * ScaleImage --
 *
 *	This function is invoked to rescale an item.
 *
 * Results:
 *	None.
 *
847
848
849
850
851
852
853
854

855
856
857
858
859
860
861
888
889
890
891
892
893
894

895
896
897
898
899
900
901
902







-
+







    ClientData clientData,	/* Pointer to canvas item for image. */
    int x, int y,		/* Upper left pixel (within image) that must
				 * be redisplayed. */
    int width, int height,	/* Dimensions of area to redisplay (may be <=
				 * 0). */
    int imgWidth, int imgHeight)/* New dimensions of image. */
{
    ImageItem *imgPtr = clientData;
    ImageItem *imgPtr = (ImageItem *)clientData;

    /*
     * If the image's size changed and it's not anchored at its northwest
     * corner then just redisplay the entire area of the image. This is a bit
     * over-conservative, but we need to do something because a size change
     * also means a position change.
     */
Changes to generic/tkCanvLine.c.
1
2
3
4
5
6
7
8



9
10
11
12
13
14
15
1
2
3
4
5



6
7
8
9
10
11
12
13
14
15





-
-
-
+
+
+







/*
 * 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.
 */

#include "tkInt.h"
#include "tkCanvas.h"
88
89
90
91
92
93
94
95

96
97
98
99
100

101
102

103
104
105
106
107
108
109
110
111

112
113

114
115
116
117

118
119

120


121
122
123
124
125
126
127
88
89
90
91
92
93
94

95
96
97
98
99

100
101

102
103
104
105
106
107
108
109
110

111
112

113
114
115
116

117
118

119
120
121
122
123
124
125
126
127
128
129







-
+




-
+

-
+








-
+

-
+



-
+

-
+

+
+







static void		DeleteLine(Tk_Canvas canvas,
			    Tk_Item *itemPtr, Display *display);
static void		DisplayLine(Tk_Canvas canvas,
			    Tk_Item *itemPtr, Display *display, Drawable dst,
			    int x, int y, int width, int height);
static int		GetLineIndex(Tcl_Interp *interp,
			    Tk_Canvas canvas, Tk_Item *itemPtr,
			    Tcl_Obj *obj, int *indexPtr);
			    Tcl_Obj *obj, TkSizeT *indexPtr);
static int		LineCoords(Tcl_Interp *interp,
			    Tk_Canvas canvas, Tk_Item *itemPtr,
			    int objc, Tcl_Obj *const objv[]);
static void		LineDeleteCoords(Tk_Canvas canvas,
			    Tk_Item *itemPtr, int first, int last);
			    Tk_Item *itemPtr, TkSizeT first, TkSizeT last);
static void		LineInsert(Tk_Canvas canvas,
			    Tk_Item *itemPtr, int beforeThis, Tcl_Obj *obj);
			    Tk_Item *itemPtr, TkSizeT beforeThis, Tcl_Obj *obj);
static int		LineToArea(Tk_Canvas canvas,
			    Tk_Item *itemPtr, double *rectPtr);
static double		LineToPoint(Tk_Canvas canvas,
			    Tk_Item *itemPtr, double *coordPtr);
static int		LineToPostscript(Tcl_Interp *interp,
			    Tk_Canvas canvas, Tk_Item *itemPtr, int prepass);
static int		ArrowParseProc(ClientData clientData,
			    Tcl_Interp *interp, Tk_Window tkwin,
			    const char *value, char *recordPtr, int offset);
			    const char *value, char *recordPtr, TkSizeT offset);
static const char * ArrowPrintProc(ClientData clientData,
			    Tk_Window tkwin, char *recordPtr, int offset,
			    Tk_Window tkwin, char *recordPtr, TkSizeT offset,
			    Tcl_FreeProc **freeProcPtr);
static int		ParseArrowShape(ClientData clientData,
			    Tcl_Interp *interp, Tk_Window tkwin,
			    const char *value, char *recordPtr, int offset);
			    const char *value, char *recordPtr, TkSizeT offset);
static const char * PrintArrowShape(ClientData clientData,
			    Tk_Window tkwin, char *recordPtr, int offset,
			    Tk_Window tkwin, char *recordPtr, TkSizeT offset,
			    Tcl_FreeProc **freeProcPtr);
static void		RotateLine(Tk_Canvas canvas, Tk_Item *itemPtr,
			    double originX, double originY, double angleRad);
static void		ScaleLine(Tk_Canvas canvas,
			    Tk_Item *itemPtr, double originX, double originY,
			    double scaleX, double scaleY);
static void		TranslateLine(Tk_Canvas canvas,
			    Tk_Item *itemPtr, double deltaX, double deltaY);

/*
139
140
141
142
143
144
145
146

147
148
149
150
151
152
153
154
155
156
157
158
159
160
161

162
163
164

165
166

167
168

169
170
171

172
173
174

175
176
177

178
179

180
181

182
183
184

185
186

187
188
189

190
191

192
193

194
195
196

197
198

199
200
201

202
203
204

205
206

207
208

209
210
211
212

213
214
215
216
217
218
219
141
142
143
144
145
146
147

148
149
150
151
152
153
154
155
156
157
158
159
160
161
162

163
164
165

166
167

168
169

170
171
172

173
174
175

176
177
178

179
180

181
182

183
184
185

186
187

188
189
190

191
192

193
194

195
196
197

198
199

200
201
202

203
204
205

206
207

208
209

210
211
212
213

214
215
216
217
218
219
220
221







-
+














-
+


-
+

-
+

-
+


-
+


-
+


-
+

-
+

-
+


-
+

-
+


-
+

-
+

-
+


-
+

-
+


-
+


-
+

-
+

-
+



-
+







static const Tk_CustomOption smoothOption = {
    TkSmoothParseProc, TkSmoothPrintProc, NULL
};
static const Tk_CustomOption stateOption = {
    TkStateParseProc, TkStatePrintProc, INT2PTR(2)
};
static const Tk_CustomOption tagsOption = {
    Tk_CanvasTagsParseProc, Tk_CanvasTagsPrintProc, NULL
    TkCanvasTagsParseProc, TkCanvasTagsPrintProc, NULL
};
static const Tk_CustomOption dashOption = {
    TkCanvasDashParseProc, TkCanvasDashPrintProc, NULL
};
static const Tk_CustomOption offsetOption = {
    TkOffsetParseProc, TkOffsetPrintProc,
    INT2PTR(TK_OFFSET_RELATIVE|TK_OFFSET_INDEX)
};
static const Tk_CustomOption pixelOption = {
    TkPixelParseProc, TkPixelPrintProc, NULL
};

static const Tk_ConfigSpec configSpecs[] = {
    {TK_CONFIG_CUSTOM, "-activedash", NULL, NULL,
	NULL, Tk_Offset(LineItem, outline.activeDash),
	NULL, offsetof(LineItem, outline.activeDash),
	TK_CONFIG_NULL_OK, &dashOption},
    {TK_CONFIG_COLOR, "-activefill", NULL, NULL,
	NULL, Tk_Offset(LineItem, outline.activeColor), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(LineItem, outline.activeColor), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_BITMAP, "-activestipple", NULL, NULL,
	NULL, Tk_Offset(LineItem, outline.activeStipple), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(LineItem, outline.activeStipple), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_CUSTOM, "-activewidth", NULL, NULL,
	"0.0", Tk_Offset(LineItem, outline.activeWidth),
	"0.0", offsetof(LineItem, outline.activeWidth),
	TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
    {TK_CONFIG_CUSTOM, "-arrow", NULL, NULL,
	"none", Tk_Offset(LineItem, arrow),
	"none", offsetof(LineItem, arrow),
	TK_CONFIG_DONT_SET_DEFAULT, &arrowOption},
    {TK_CONFIG_CUSTOM, "-arrowshape", NULL, NULL,
	"8 10 3", Tk_Offset(LineItem, arrowShapeA),
	"8 10 3", offsetof(LineItem, arrowShapeA),
	TK_CONFIG_DONT_SET_DEFAULT, &arrowShapeOption},
    {TK_CONFIG_CAP_STYLE, "-capstyle", NULL, NULL,
	"butt", Tk_Offset(LineItem, capStyle), TK_CONFIG_DONT_SET_DEFAULT, NULL},
	"butt", offsetof(LineItem, capStyle), TK_CONFIG_DONT_SET_DEFAULT, NULL},
    {TK_CONFIG_COLOR, "-fill", NULL, NULL,
	DEF_CANVITEM_OUTLINE, Tk_Offset(LineItem, outline.color), TK_CONFIG_NULL_OK, NULL},
	DEF_CANVITEM_OUTLINE, offsetof(LineItem, outline.color), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_CUSTOM, "-dash", NULL, NULL,
	NULL, Tk_Offset(LineItem, outline.dash),
	NULL, offsetof(LineItem, outline.dash),
	TK_CONFIG_NULL_OK, &dashOption},
    {TK_CONFIG_PIXELS, "-dashoffset", NULL, NULL,
	"0", Tk_Offset(LineItem, outline.offset), TK_CONFIG_DONT_SET_DEFAULT, NULL},
	"0", offsetof(LineItem, outline.offset), TK_CONFIG_DONT_SET_DEFAULT, NULL},
    {TK_CONFIG_CUSTOM, "-disableddash", NULL, NULL,
	NULL, Tk_Offset(LineItem, outline.disabledDash),
	NULL, offsetof(LineItem, outline.disabledDash),
	TK_CONFIG_NULL_OK, &dashOption},
    {TK_CONFIG_COLOR, "-disabledfill", NULL, NULL,
	NULL, Tk_Offset(LineItem, outline.disabledColor), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(LineItem, outline.disabledColor), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_BITMAP, "-disabledstipple", NULL, NULL,
	NULL, Tk_Offset(LineItem, outline.disabledStipple), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(LineItem, outline.disabledStipple), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_CUSTOM, "-disabledwidth", NULL, NULL,
	"0.0", Tk_Offset(LineItem, outline.disabledWidth),
	"0.0", offsetof(LineItem, outline.disabledWidth),
	TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
    {TK_CONFIG_JOIN_STYLE, "-joinstyle", NULL, NULL,
	"round", Tk_Offset(LineItem, joinStyle), TK_CONFIG_DONT_SET_DEFAULT, NULL},
	"round", offsetof(LineItem, joinStyle), TK_CONFIG_DONT_SET_DEFAULT, NULL},
    {TK_CONFIG_CUSTOM, "-offset", NULL, NULL,
	"0,0", Tk_Offset(LineItem, outline.tsoffset),
	"0,0", offsetof(LineItem, outline.tsoffset),
	TK_CONFIG_DONT_SET_DEFAULT, &offsetOption},
    {TK_CONFIG_CUSTOM, "-smooth", NULL, NULL,
	"0", Tk_Offset(LineItem, smooth),
	"0", offsetof(LineItem, smooth),
	TK_CONFIG_DONT_SET_DEFAULT, &smoothOption},
    {TK_CONFIG_INT, "-splinesteps", NULL, NULL,
	"12", Tk_Offset(LineItem, splineSteps), TK_CONFIG_DONT_SET_DEFAULT, NULL},
	"12", offsetof(LineItem, splineSteps), TK_CONFIG_DONT_SET_DEFAULT, NULL},
    {TK_CONFIG_CUSTOM, "-state", NULL, NULL,
	NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK, &stateOption},
	NULL, offsetof(Tk_Item, state), TK_CONFIG_NULL_OK, &stateOption},
    {TK_CONFIG_BITMAP, "-stipple", NULL, NULL,
	NULL, Tk_Offset(LineItem, outline.stipple), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(LineItem, outline.stipple), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_CUSTOM, "-tags", NULL, NULL,
	NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},
    {TK_CONFIG_CUSTOM, "-width", NULL, NULL,
	"1.0", Tk_Offset(LineItem, outline.width),
	"1.0", offsetof(LineItem, outline.width),
	TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
    {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL}
};

/*
 * The structures below defines the line item type by means of functions that
 * can be invoked by generic item code.
236
237
238
239
240
241
242

243

244
245
246
247
248
249
250
238
239
240
241
242
243
244
245

246
247
248
249
250
251
252
253







+
-
+







    TranslateLine,			/* translateProc */
    GetLineIndex,			/* indexProc */
    NULL,				/* icursorProc */
    NULL,				/* selectionProc */
    LineInsert,				/* insertProc */
    LineDeleteCoords,			/* dTextProc */
    NULL,				/* nextPtr */
    RotateLine,				/* rotateProc */
    NULL, 0, NULL, NULL
    0, NULL, NULL
};

/*
 * The definition below determines how large are static arrays used to hold
 * spline points (splines larger than this have to have their arrays
 * malloc-ed).
 */
402
403
404
405
406
407
408
409

410
411
412
413
414
415
416
405
406
407
408
409
410
411

412
413
414
415
416
417
418
419







-
+







		"wrong # coordinates: expected at least 4, got %d", objc));
	Tcl_SetErrorCode(interp, "TK", "CANVAS", "COORDS", "LINE", NULL);
	return TCL_ERROR;
    }

    numPoints = objc/2;
    if (linePtr->numPoints != numPoints) {
	coordPtr = ckalloc(sizeof(double) * objc);
	coordPtr = (double *)ckalloc(sizeof(double) * objc);
	if (linePtr->coordPtr != NULL) {
	    ckfree(linePtr->coordPtr);
	}
	linePtr->coordPtr = coordPtr;
	linePtr->numPoints = numPoints;
    }
    coordPtr = linePtr->coordPtr;
598
599
600
601
602
603
604
605

606
607
608
609
610
611
612
601
602
603
604
605
606
607

608
609
610
611
612
613
614
615







-
+







 *	Resources associated with itemPtr are released.
 *
 *--------------------------------------------------------------
 */

static void
DeleteLine(
    Tk_Canvas canvas,		/* Info about overall canvas widget. */
    TCL_UNUSED(Tk_Canvas),		/* Info about overall canvas widget. */
    Tk_Item *itemPtr,		/* Item that is being deleted. */
    Display *display)		/* Display containing window for canvas. */
{
    LineItem *linePtr = (LineItem *) itemPtr;

    Tk_DeleteOutline(display, &linePtr->outline);
    if (linePtr->coordPtr != NULL) {
702
703
704
705
706
707
708
709

710
711
712
713
714
715
716
705
706
707
708
709
710
711

712
713
714
715
716
717
718
719







-
+







	if (linePtr->arrow != ARROWS_FIRST) {
	    TkIncludePoint((Tk_Item *) linePtr, linePtr->lastArrowPtr);
	}
    }

    tsoffset = &linePtr->outline.tsoffset;
    if (tsoffset->flags & TK_OFFSET_INDEX) {
	double *coordPtr = linePtr->coordPtr
	coordPtr = linePtr->coordPtr
		+ (tsoffset->flags & ~TK_OFFSET_INDEX);

	if (tsoffset->flags <= 0) {
	    coordPtr = linePtr->coordPtr;
	    if ((linePtr->arrow == ARROWS_FIRST)
		    || (linePtr->arrow == ARROWS_BOTH)) {
		coordPtr = linePtr->firstArrowPtr;
826
827
828
829
830
831
832
833
834
835




836
837

838
839
840
841
842
843
844
829
830
831
832
833
834
835



836
837
838
839
840

841
842
843
844
845
846
847
848







-
-
-
+
+
+
+

-
+








static void
DisplayLine(
    Tk_Canvas canvas,		/* Canvas that contains item. */
    Tk_Item *itemPtr,		/* Item to be displayed. */
    Display *display,		/* Display on which to draw item. */
    Drawable drawable,		/* Pixmap or window in which to draw item. */
    int x, int y, int width, int height)
				/* Describes region of canvas that must be
				 * redisplayed (not used). */
    TCL_UNUSED(int),		/* Describes region of canvas that must be */
    TCL_UNUSED(int),		/* redisplayed (not used). */
    TCL_UNUSED(int),
    TCL_UNUSED(int))
{
    LineItem *linePtr = (LineItem *) itemPtr;
    LineItem *linePtr = (LineItem *)itemPtr;
    XPoint staticPoints[MAX_STATIC_POINTS*3];
    XPoint *pointPtr;
    double linewidth;
    int numPoints;
    Tk_State state = itemPtr->state;

    if (!linePtr->numPoints || (linePtr->outline.gc == NULL)) {
871
872
873
874
875
876
877
878

879
880
881
882
883
884
885
875
876
877
878
879
880
881

882
883
884
885
886
887
888
889







-
+







    } else {
	numPoints = linePtr->numPoints;
    }

    if (numPoints <= MAX_STATIC_POINTS) {
	pointPtr = staticPoints;
    } else {
	pointPtr = ckalloc(numPoints * 3 * sizeof(XPoint));
	pointPtr = (XPoint *)ckalloc(numPoints * 3 * sizeof(XPoint));
    }

    if ((linePtr->smooth) && (linePtr->numPoints > 2)) {
	numPoints = linePtr->smooth->coordProc(canvas, linePtr->coordPtr,
		linePtr->numPoints, linePtr->splineSteps, pointPtr, NULL);
    } else {
	numPoints = TkCanvTranslatePath((TkCanvas *) canvas, numPoints,
947
948
949
950
951
952
953
954

955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973

974
975
976

977
978
979
980
981
982
983
984
985
986
987
988


989
990
991
992
993
994
995
951
952
953
954
955
956
957

958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976

977
978
979

980
981
982
983
984
985
986
987
988
989
990


991
992
993
994
995
996
997
998
999







-
+


















-
+


-
+










-
-
+
+







 *--------------------------------------------------------------
 */

static void
LineInsert(
    Tk_Canvas canvas,		/* Canvas containing text item. */
    Tk_Item *itemPtr,		/* Line item to be modified. */
    int beforeThis,		/* Index before which new coordinates are to
    TkSizeT beforeThis,		/* Index before which new coordinates are to
				 * be inserted. */
    Tcl_Obj *obj)		/* New coordinates to be inserted. */
{
    LineItem *linePtr = (LineItem *) itemPtr;
    int length, objc, i;
    double *newCoordPtr, *coordPtr;
    Tk_State state = itemPtr->state;
    Tcl_Obj **objv;

    if (state == TK_STATE_NULL) {
	state = Canvas(canvas)->canvas_state;
    }

    if (!obj || (Tcl_ListObjGetElements(NULL, obj, &objc, &objv) != TCL_OK)
	    || !objc || objc&1) {
	return;
    }
    length = 2*linePtr->numPoints;
    if (beforeThis < 0) {
    if (beforeThis == TCL_INDEX_NONE) {
	beforeThis = 0;
    }
    if (beforeThis > length) {
    if (beforeThis + 1 > (TkSizeT)length + 1) {
	beforeThis = length;
    }
    if (linePtr->firstArrowPtr != NULL) {
	linePtr->coordPtr[0] = linePtr->firstArrowPtr[0];
	linePtr->coordPtr[1] = linePtr->firstArrowPtr[1];
    }
    if (linePtr->lastArrowPtr != NULL) {
	linePtr->coordPtr[length-2] = linePtr->lastArrowPtr[0];
	linePtr->coordPtr[length-1] = linePtr->lastArrowPtr[1];
    }
    newCoordPtr = ckalloc(sizeof(double) * (length + objc));
    for (i=0; i<beforeThis; i++) {
    newCoordPtr = (double *)ckalloc(sizeof(double) * (length + objc));
    for (i=0; i<(int)beforeThis; i++) {
	newCoordPtr[i] = linePtr->coordPtr[i];
    }
    for (i=0; i<objc; i++) {
	if (Tcl_GetDoubleFromObj(NULL, objv[i],
		&newCoordPtr[i + beforeThis]) != TCL_OK) {
	    Tcl_ResetResult(Canvas(canvas)->interp);
	    ckfree(newCoordPtr);
1015
1016
1017
1018
1019
1020
1021
1022

1023
1024
1025
1026

1027
1028
1029
1030

1031
1032
1033
1034

1035
1036
1037
1038
1039
1040

1041
1042
1043
1044
1045
1046
1047
1048
1049
1050

1051
1052
1053
1054
1055
1056
1057
1019
1020
1021
1022
1023
1024
1025

1026
1027
1028
1029

1030
1031
1032
1033

1034
1035
1036
1037

1038
1039
1040
1041
1042
1043

1044
1045
1046
1047
1048
1049
1050
1051
1052
1053

1054
1055
1056
1057
1058
1059
1060
1061







-
+



-
+



-
+



-
+





-
+









-
+







	 * the general canvas code not to redraw the whole object. If this
	 * flag is not set, the canvas will do the redrawing, otherwise I have
	 * to do it here.
	 */

	itemPtr->redraw_flags |= TK_ITEM_DONT_REDRAW;

	if (beforeThis > 0) {
	if ((int)beforeThis > 0) {
	    beforeThis -= 2;
	    objc += 2;
	}
	if (beforeThis+objc < length) {
	if ((int)beforeThis+objc < length) {
	    objc += 2;
	}
	if (linePtr->smooth) {
	    if (beforeThis > 0) {
	    if ((int)beforeThis > 0) {
		beforeThis -= 2;
		objc += 2;
	    }
	    if (beforeThis+objc+2 < length) {
	    if ((int)beforeThis+objc+2 < length) {
		objc += 2;
	    }
	}
	itemPtr->x1 = itemPtr->x2 = (int) linePtr->coordPtr[beforeThis];
	itemPtr->y1 = itemPtr->y2 = (int) linePtr->coordPtr[beforeThis+1];
	if ((linePtr->firstArrowPtr != NULL) && (beforeThis < 1)) {
	if ((linePtr->firstArrowPtr != NULL) && ((int)beforeThis < 1)) {
	    /*
	     * Include old first arrow.
	     */

	    for (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW;
		    i++, coordPtr += 2) {
		TkIncludePoint(itemPtr, coordPtr);
	    }
	}
	if ((linePtr->lastArrowPtr != NULL) && (beforeThis+objc >= length)) {
	if ((linePtr->lastArrowPtr != NULL) && ((int)beforeThis+objc >= length)) {
	    /*
	     * Include old last arrow.
	     */

	    for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW;
		    i++, coordPtr += 2) {
		TkIncludePoint(itemPtr, coordPtr);
1075
1076
1077
1078
1079
1080
1081
1082

1083
1084
1085
1086
1087
1088
1089
1090
1091
1092

1093
1094
1095
1096
1097
1098
1099
1079
1080
1081
1082
1083
1084
1085

1086
1087
1088
1089
1090
1091
1092
1093
1094
1095

1096
1097
1098
1099
1100
1101
1102
1103







-
+









-
+







	ConfigureArrows(canvas, linePtr);
    }

    if (itemPtr->redraw_flags & TK_ITEM_DONT_REDRAW) {
	double width;
	int intWidth;

	if ((linePtr->firstArrowPtr != NULL) && (beforeThis > 2)) {
	if ((linePtr->firstArrowPtr != NULL) && ((int)beforeThis > 2)) {
	    /*
	     * Include new first arrow.
	     */

	    for (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW;
		    i++, coordPtr += 2) {
		TkIncludePoint(itemPtr, coordPtr);
	    }
	}
	if ((linePtr->lastArrowPtr != NULL) && (beforeThis+objc < length-2)) {
	if ((linePtr->lastArrowPtr != NULL) && ((int)beforeThis+objc < length-2)) {
	    /*
	     * Include new right arrow.
	     */

	    for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW;
		    i++, coordPtr += 2) {
		TkIncludePoint(itemPtr, coordPtr);
1141
1142
1143
1144
1145
1146
1147
1148
1149


1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164

1165
1166
1167

1168
1169
1170

1171
1172
1173
1174
1175
1176
1177
1145
1146
1147
1148
1149
1150
1151


1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167

1168
1169
1170

1171
1172
1173

1174
1175
1176
1177
1178
1179
1180
1181







-
-
+
+














-
+


-
+


-
+







 *--------------------------------------------------------------
 */

static void
LineDeleteCoords(
    Tk_Canvas canvas,		/* Canvas containing itemPtr. */
    Tk_Item *itemPtr,		/* Item in which to delete characters. */
    int first,			/* Index of first character to delete. */
    int last)			/* Index of last character to delete. */
    TkSizeT first,			/* Index of first character to delete. */
    TkSizeT last)			/* Index of last character to delete. */
{
    LineItem *linePtr = (LineItem *) itemPtr;
    int count, i, first1, last1;
    int length = 2*linePtr->numPoints;
    double *coordPtr;
    Tk_State state = itemPtr->state;

    if (state == TK_STATE_NULL) {
	state = Canvas(canvas)->canvas_state;
    }

    first &= -2;
    last &= -2;

    if (first < 0) {
    if ((int)first < 0) {
	first = 0;
    }
    if (last >= length) {
    if ((int)last >= length) {
	last = length-2;
    }
    if (first > last) {
    if ((int)first > (int)last) {
	return;
    }
    if (linePtr->firstArrowPtr != NULL) {
	linePtr->coordPtr[0] = linePtr->firstArrowPtr[0];
	linePtr->coordPtr[1] = linePtr->firstArrowPtr[1];
    }
    if (linePtr->lastArrowPtr != NULL) {
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1319
1320
1321
1322
1323
1324
1325

1326
1327
1328
1329
1330
1331
1332







-







 *
 * Side effects:
 *	None.
 *
 *--------------------------------------------------------------
 */

	/* ARGSUSED */
static double
LineToPoint(
    Tk_Canvas canvas,		/* Canvas containing item. */
    Tk_Item *itemPtr,		/* Item to check against point. */
    double *pointPtr)		/* Pointer to x and y coordinates. */
{
    Tk_State state = itemPtr->state;
1361
1362
1363
1364
1365
1366
1367
1368

1369
1370
1371
1372
1373
1374
1375
1364
1365
1366
1367
1368
1369
1370

1371
1372
1373
1374
1375
1376
1377
1378







-
+








    if ((linePtr->smooth) && (linePtr->numPoints > 2)) {
	numPoints = linePtr->smooth->coordProc(canvas, NULL,
		linePtr->numPoints, linePtr->splineSteps, NULL, NULL);
	if (numPoints <= MAX_STATIC_POINTS) {
	    linePoints = staticSpace;
	} else {
	    linePoints = ckalloc(2 * numPoints * sizeof(double));
	    linePoints = (double *)ckalloc(2 * numPoints * sizeof(double));
	}
	numPoints = linePtr->smooth->coordProc(canvas, linePtr->coordPtr,
		linePtr->numPoints, linePtr->splineSteps, NULL, linePoints);
    } else {
	numPoints = linePtr->numPoints;
	linePoints = linePtr->coordPtr;
    }
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1546
1547
1548
1549
1550
1551
1552

1553
1554
1555
1556
1557
1558
1559







-







 *
 * Side effects:
 *	None.
 *
 *--------------------------------------------------------------
 */

	/* ARGSUSED */
static int
LineToArea(
    Tk_Canvas canvas,		/* Canvas containing item. */
    Tk_Item *itemPtr,		/* Item to check against line. */
    double *rectPtr)
{
    LineItem *linePtr = (LineItem *) itemPtr;
1596
1597
1598
1599
1600
1601
1602
1603

1604
1605
1606
1607
1608
1609
1610
1598
1599
1600
1601
1602
1603
1604

1605
1606
1607
1608
1609
1610
1611
1612







-
+








    if ((linePtr->smooth) && (linePtr->numPoints > 2)) {
	numPoints = linePtr->smooth->coordProc(canvas, NULL,
		linePtr->numPoints, linePtr->splineSteps, NULL, NULL);
	if (numPoints <= MAX_STATIC_POINTS) {
	    linePoints = staticSpace;
	} else {
	    linePoints = ckalloc(2 * numPoints * sizeof(double));
	    linePoints = (double *)ckalloc(2 * numPoints * sizeof(double));
	}
	numPoints = linePtr->smooth->coordProc(canvas, linePtr->coordPtr,
		linePtr->numPoints, linePtr->splineSteps, NULL, linePoints);
    } else {
	numPoints = linePtr->numPoints;
	linePoints = linePtr->coordPtr;
    }
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1693
1694
1695
1696
1697
1698
1699


1700
1701
1702
1703
1704
1705
1706







-
-







    if (linePtr->firstArrowPtr != NULL) {
	linePtr->coordPtr[0] = linePtr->firstArrowPtr[0];
	linePtr->coordPtr[1] = linePtr->firstArrowPtr[1];
	ckfree(linePtr->firstArrowPtr);
	linePtr->firstArrowPtr = NULL;
    }
    if (linePtr->lastArrowPtr != NULL) {
	int i;

	i = 2*(linePtr->numPoints-1);
	linePtr->coordPtr[i] = linePtr->lastArrowPtr[0];
	linePtr->coordPtr[i+1] = linePtr->lastArrowPtr[1];
	ckfree(linePtr->lastArrowPtr);
	linePtr->lastArrowPtr = NULL;
    }
    for (i = 0, coordPtr = linePtr->coordPtr; i < linePtr->numPoints;
1737
1738
1739
1740
1741
1742
1743
1744

1745

1746
1747


1748

1749
1750
1751




1752





1753
1754
1755




1756
1757
1758
1759
1760
1761
1762
1737
1738
1739
1740
1741
1742
1743

1744
1745
1746
1747

1748
1749
1750
1751



1752
1753
1754
1755
1756
1757
1758
1759
1760
1761



1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772







-
+

+

-
+
+

+
-
-
-
+
+
+
+

+
+
+
+
+
-
-
-
+
+
+
+







GetLineIndex(
    Tcl_Interp *interp,		/* Used for error reporting. */
    Tk_Canvas canvas,		/* Canvas containing item. */
    Tk_Item *itemPtr,		/* Item for which the index is being
				 * specified. */
    Tcl_Obj *obj,		/* Specification of a particular coord in
				 * itemPtr's line. */
    int *indexPtr)		/* Where to store converted index. */
    TkSizeT *indexPtr)		/* Where to store converted index. */
{
    TkSizeT idx, length;
    LineItem *linePtr = (LineItem *) itemPtr;
    const char *string = Tcl_GetString(obj);
    const char *string;
    (void)canvas;

    if (TCL_OK == TkGetIntForIndex(obj, 2*linePtr->numPoints - 1, 0, &idx)) {
    if (string[0] == 'e') {
	if (strncmp(string, "end", obj->length) == 0) {
	    *indexPtr = 2*linePtr->numPoints;
	if (idx == TCL_INDEX_NONE) {
	    idx = 0;
	} else if (idx > (2*(TkSizeT)linePtr->numPoints)) {
	    idx = 2*linePtr->numPoints;
	} else {
	    idx &= (TkSizeT)-2;	/* If index is odd, make it even. */
	}
	*indexPtr = idx;
	return TCL_OK;
    }
	    goto badIndex;
	}
    } else if (string[0] == '@') {

    string = TkGetStringFromObj(obj, &length);

    if (string[0] == '@') {
	int i;
	double x, y, bestDist, dist, *coordPtr;
	char *end;
	const char *p;

	p = string+1;
	x = strtod(p, &end);
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785

1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798




1799
1800

1801
1802
1803
1804





1805
1806
1807
1808
1809
1810
1811
1786
1787
1788
1789
1790
1791
1792



1793













1794
1795
1796
1797
1798

1799




1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811







-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+

-
+
-
-
-
-
+
+
+
+
+







	    if (dist < bestDist) {
		bestDist = dist;
		*indexPtr = 2*i;
	    }
	    coordPtr += 2;
	}
    } else {
	if (Tcl_GetIntFromObj(interp, obj, indexPtr) != TCL_OK) {
	    goto badIndex;
	}

	*indexPtr &= -2;	/* If index is odd, make it even. */
	if (*indexPtr < 0){
	    *indexPtr = 0;
	} else if (*indexPtr > (2*linePtr->numPoints)) {
	    *indexPtr = (2*linePtr->numPoints);
	}
    }
    return TCL_OK;

    /*
     * Some of the paths here leave messages in interp->result, so we have to
     * clear it out before storing our own message.
     */
	/*
	 * Some of the paths here leave messages in interp->result, so we have to
	 * clear it out before storing our own message.
	 */

  badIndex:
    badIndex:
    Tcl_ResetResult(interp);
    Tcl_SetObjResult(interp, Tcl_ObjPrintf("bad index \"%s\"", string));
    Tcl_SetErrorCode(interp, "TK", "CANVAS", "ITEM_INDEX", "LINE", NULL);
    return TCL_ERROR;
	Tcl_SetObjResult(interp, Tcl_ObjPrintf("bad index \"%s\"", string));
	Tcl_SetErrorCode(interp, "TK", "CANVAS", "ITEM_INDEX", "LINE", NULL);
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 *--------------------------------------------------------------
 *
 * TranslateLine --
 *
1853
1854
1855
1856
1857
1858
1859


















































1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879

1880
1881

1882
1883
1884
1885

1886
1887
1888
1889
1890
1891
1892
1893

1894
1895
1896
1897
1898
1899
1900
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925

1926
1927

1928
1929

1930
1931
1932
1933

1934
1935
1936
1937
1938
1939
1940
1941

1942
1943
1944
1945
1946
1947
1948
1949







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
















-


-
+

-
+



-
+







-
+







    }
    ComputeLineBbox(canvas, linePtr);
}

/*
 *--------------------------------------------------------------
 *
 * RotateLine --
 *
 *	This function is called to rotate a line by a given amount about a
 *	point.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The position of the line is rotated by angleRad about (originX,
 *	originY), and the bounding box is updated in the generic part of the
 *	item structure.
 *
 *--------------------------------------------------------------
 */

static void
RotateLine(
    Tk_Canvas canvas,		/* Canvas containing item. */
    Tk_Item *itemPtr,		/* Item that is being moved. */
    double originX, double originY,
    double angleRad)		/* Amount by which item is to be rotated. */
{
    LineItem *linePtr = (LineItem *) itemPtr;
    double *coordPtr;
    int i;
    double s = sin(angleRad), c = cos(angleRad);

    for (i = 0, coordPtr = linePtr->coordPtr; i < linePtr->numPoints;
	    i++, coordPtr += 2) {
	TkRotatePoint(originX, originY, s, c, &coordPtr[0], &coordPtr[1]);
    }
    if (linePtr->firstArrowPtr != NULL) {
	for (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW;
		i++, coordPtr += 2) {
	    TkRotatePoint(originX, originY, s, c, &coordPtr[0], &coordPtr[1]);
	}
    }
    if (linePtr->lastArrowPtr != NULL) {
	for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW;
		i++, coordPtr += 2) {
	    TkRotatePoint(originX, originY, s, c, &coordPtr[0], &coordPtr[1]);
	}
    }
    ComputeLineBbox(canvas, linePtr);
}

/*
 *--------------------------------------------------------------
 *
 * ParseArrowShape --
 *
 *	This function is called back during option parsing to parse arrow
 *	shape information.
 *
 * Results:
 *	The return value is a standard Tcl result: TCL_OK means that the arrow
 *	shape information was parsed ok, and TCL_ERROR means it couldn't be
 *	parsed.
 *
 * Side effects:
 *	Arrow information in recordPtr is updated.
 *
 *--------------------------------------------------------------
 */

	/* ARGSUSED */
static int
ParseArrowShape(
    ClientData clientData,	/* Not used. */
    TCL_UNUSED(void *),	/* Not used. */
    Tcl_Interp *interp,		/* Used for error reporting. */
    Tk_Window tkwin,		/* Not used. */
    TCL_UNUSED(Tk_Window),		/* Not used. */
    const char *value,		/* Textual specification of arrow shape. */
    char *recordPtr,		/* Pointer to item record in which to store
				 * arrow information. */
    int offset)			/* Offset of shape information in widget
    TkSizeT offset)			/* Offset of shape information in widget
				 * record. */
{
    LineItem *linePtr = (LineItem *) recordPtr;
    double a, b, c;
    int argc;
    const char **argv = NULL;

    if (offset != Tk_Offset(LineItem, arrowShapeA)) {
    if ((size_t)offset != offsetof(LineItem, arrowShapeA)) {
	Tcl_Panic("ParseArrowShape received bogus offset");
    }

    if (Tcl_SplitList(interp, (char *) value, &argc, &argv) != TCL_OK) {
	goto syntaxError;
    } else if (argc != 3) {
	goto syntaxError;
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949


1950
1951
1952

1953
1954
1955
1956
1957

1958
1959
1960
1961
1962
1963
1964
1987
1988
1989
1990
1991
1992
1993

1994
1995


1996
1997
1998
1999

2000
2001
2002
2003
2004

2005
2006
2007
2008
2009
2010
2011
2012







-


-
-
+
+


-
+




-
+







 *
 * Side effects:
 *	None.
 *
 *--------------------------------------------------------------
 */

    /* ARGSUSED */
static const char *
PrintArrowShape(
    ClientData clientData,	/* Not used. */
    Tk_Window tkwin,		/* Window associated with linePtr's widget. */
    TCL_UNUSED(void *),	/* Not used. */
    TCL_UNUSED(Tk_Window),		/* Window associated with linePtr's widget. */
    char *recordPtr,		/* Pointer to item record containing current
				 * shape information. */
    int offset,			/* Offset of arrow information in record. */
    TCL_UNUSED(TkSizeT),			/* Offset of arrow information in record. */
    Tcl_FreeProc **freeProcPtr)	/* Store address of function to call to free
				 * string here. */
{
    LineItem *linePtr = (LineItem *) recordPtr;
    char *buffer = ckalloc(120);
    char *buffer = (char *)ckalloc(120);

    sprintf(buffer, "%.5g %.5g %.5g", linePtr->arrowShapeA,
	    linePtr->arrowShapeB, linePtr->arrowShapeC);
    *freeProcPtr = TCL_DYNAMIC;
    return buffer;
}

1978
1979
1980
1981
1982
1983
1984
1985

1986
1987

1988
1989
1990

1991
1992
1993
1994
1995

1996
1997
1998
1999
2000
2001
2002
2026
2027
2028
2029
2030
2031
2032

2033
2034

2035
2036
2037

2038
2039
2040
2041


2042
2043
2044
2045
2046
2047
2048
2049







-
+

-
+


-
+



-
-
+







 *	value argument.
 *
 *--------------------------------------------------------------
 */

static int
ArrowParseProc(
    ClientData clientData,	/* some flags.*/
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Used for reporting errors. */
    Tk_Window tkwin,		/* Window containing canvas widget. */
    TCL_UNUSED(Tk_Window),		/* Window containing canvas widget. */
    const char *value,		/* Value of option. */
    char *widgRec,		/* Pointer to record for item. */
    int offset)			/* Offset into item. */
    TkSizeT offset)			/* Offset into item. */
{
    int c;
    size_t length;

    register Arrows *arrowPtr = (Arrows *) (widgRec + offset);
    Arrows *arrowPtr = (Arrows *) (widgRec + offset);

    if (value == NULL || *value == 0) {
	*arrowPtr = ARROWS_NONE;
	return TCL_OK;
    }

    c = value[0];
2046
2047
2048
2049
2050
2051
2052
2053
2054


2055
2056
2057


2058
2059
2060
2061

2062
2063
2064
2065
2066
2067
2068
2093
2094
2095
2096
2097
2098
2099


2100
2101
2102


2103
2104
2105
2106
2107

2108
2109
2110
2111
2112
2113
2114
2115







-
-
+
+

-
-
+
+



-
+







 *	None.
 *
 *--------------------------------------------------------------
 */

static const char *
ArrowPrintProc(
    ClientData clientData,	/* Ignored. */
    Tk_Window tkwin,		/* Window containing canvas widget. */
    TCL_UNUSED(void *),	/* Ignored. */
    TCL_UNUSED(Tk_Window),		/* Window containing canvas widget. */
    char *widgRec,		/* Pointer to record for item. */
    int offset,			/* Offset into item. */
    Tcl_FreeProc **freeProcPtr)	/* Pointer to variable to fill in with
    TkSizeT offset,			/* Offset into item. */
    TCL_UNUSED(Tcl_FreeProc **))	/* Pointer to variable to fill in with
				 * information about how to reclaim storage
				 * for return string. */
{
    register Arrows *arrowPtr = (Arrows *) (widgRec + offset);
    Arrows *arrowPtr = (Arrows *) (widgRec + offset);

    switch (*arrowPtr) {
    case ARROWS_FIRST:
	return "first";
    case ARROWS_LAST:
	return "last";
    case ARROWS_BOTH:
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2135
2136
2137
2138
2139
2140
2141

2142
2143
2144
2145
2146
2147
2148







-







 *	firstArrowPtr and lastArrowPtr polygons are allocated and initialized,
 *	if need be, and the end points of the line are adjusted so that a
 *	thick line doesn't stick out past the arrowheads.
 *
 *--------------------------------------------------------------
 */

	/* ARGSUSED */
static int
ConfigureArrows(
    Tk_Canvas canvas,		/* Canvas in which arrows will be displayed
				 * (interp and tkwin fields are needed). */
    LineItem *linePtr)		/* Item to configure for arrows. */
{
    double *poly, *coordPtr;
2149
2150
2151
2152
2153
2154
2155
2156

2157
2158
2159
2160
2161
2162
2163
2195
2196
2197
2198
2199
2200
2201

2202
2203
2204
2205
2206
2207
2208
2209







-
+







     */

    fracHeight = (width/2.0)/shapeC;
    backup = fracHeight*shapeB + shapeA*(1.0 - fracHeight)/2.0;
    if (linePtr->arrow != ARROWS_LAST) {
	poly = linePtr->firstArrowPtr;
	if (poly == NULL) {
	    poly = ckalloc(2 * PTS_IN_ARROW * sizeof(double));
	    poly = (double *)ckalloc(2 * PTS_IN_ARROW * sizeof(double));
	    poly[0] = poly[10] = linePtr->coordPtr[0];
	    poly[1] = poly[11] = linePtr->coordPtr[1];
	    linePtr->firstArrowPtr = poly;
	}
	dx = poly[0] - linePtr->coordPtr[2];
	dy = poly[1] - linePtr->coordPtr[3];
	length = hypot(dx, dy);
2193
2194
2195
2196
2197
2198
2199
2200

2201
2202
2203
2204
2205
2206
2207
2239
2240
2241
2242
2243
2244
2245

2246
2247
2248
2249
2250
2251
2252
2253







-
+







     * Similar arrowhead calculation for the last point of the line.
     */

    if (linePtr->arrow != ARROWS_FIRST) {
	coordPtr = linePtr->coordPtr + 2*(linePtr->numPoints-2);
	poly = linePtr->lastArrowPtr;
	if (poly == NULL) {
	    poly = ckalloc(2 * PTS_IN_ARROW * sizeof(double));
	    poly = (double *)ckalloc(2 * PTS_IN_ARROW * sizeof(double));
	    poly[0] = poly[10] = coordPtr[2];
	    poly[1] = poly[11] = coordPtr[3];
	    linePtr->lastArrowPtr = poly;
	}
	dx = poly[0] - coordPtr[0];
	dy = poly[1] - coordPtr[1];
	length = hypot(dx, dy);
2250
2251
2252
2253
2254
2255
2256
2257

2258
2259
2260
2261
2262
2263
2264
2296
2297
2298
2299
2300
2301
2302

2303
2304
2305
2306
2307
2308
2309
2310







-
+







 */

static int
LineToPostscript(
    Tcl_Interp *interp,		/* Leave Postscript or error message here. */
    Tk_Canvas canvas,		/* Information about overall canvas. */
    Tk_Item *itemPtr,		/* Item for which Postscript is wanted. */
    int prepass)		/* 1 means this is a prepass to collect font
    TCL_UNUSED(int))		/* 1 means this is a prepass to collect font
				 * information; 0 means final Postscript is
				 * being created. */
{
    LineItem *linePtr = (LineItem *) itemPtr;
    int style;
    double width;
    XColor *color;
2316
2317
2318
2319
2320
2321
2322
2323

2324
2325
2326
2327
2328
2329
2330
2331

2332
2333
2334
2335
2336
2337
2338
2339
2340
2362
2363
2364
2365
2366
2367
2368

2369


2370
2371
2372
2373
2374

2375


2376
2377
2378
2379
2380
2381
2382







-
+
-
-





-
+
-
-







	Tcl_AppendPrintfToObj(psObj, "%.15g %.15g translate %.15g %.15g",
		linePtr->coordPtr[0], Tk_CanvasPsY(canvas, linePtr->coordPtr[1]),
		width/2.0, width/2.0);
	Tcl_AppendToObj(psObj,
		" scale 1 0 moveto 0 0 1 0 360 arc\nsetmatrix\n", -1);

	Tcl_ResetResult(interp);
	if (Tk_CanvasPsColor(interp, canvas, color) != TCL_OK) {
	Tk_CanvasPsColor(interp, canvas, color);
	    goto error;
	}
	Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));

	if (stipple != None) {
	    Tcl_AppendToObj(psObj, "clip ", -1);
	    Tcl_ResetResult(interp);
	    if (Tk_CanvasPsStipple(interp, canvas, stipple) != TCL_OK) {
	    Tk_CanvasPsStipple(interp, canvas, stipple);
		goto error;
	    }
	    Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
	} else {
	    Tcl_AppendToObj(psObj, "fill\n", -1);
	}
	goto done;
    }

2362
2363
2364
2365
2366
2367
2368
2369

2370
2371
2372
2373
2374
2375
2376
2404
2405
2406
2407
2408
2409
2410

2411
2412
2413
2414
2415
2416
2417
2418







-
+







	double *pointPtr;
	int numPoints;

	numPoints = linePtr->smooth->coordProc(canvas, NULL,
		linePtr->numPoints, linePtr->splineSteps, NULL, NULL);
	pointPtr = staticPoints;
	if (numPoints > MAX_STATIC_POINTS) {
	    pointPtr = ckalloc(numPoints * 2 * sizeof(double));
	    pointPtr = (double *)ckalloc(numPoints * 2 * sizeof(double));
	}
	numPoints = linePtr->smooth->coordProc(canvas, linePtr->coordPtr,
		linePtr->numPoints, linePtr->splineSteps, NULL, pointPtr);
	Tk_CanvasPsPath(interp, canvas, pointPtr, numPoints);
	if (pointPtr != staticPoints) {
	    ckfree(pointPtr);
	}
2395
2396
2397
2398
2399
2400
2401
2402

2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416


2417
2418
2419
2420
2421
2422
2423
2424
2425


2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2437
2438
2439
2440
2441
2442
2443

2444


2445
2446
2447
2448
2449
2450
2451
2452
2453
2454


2455
2456


2457
2458
2459
2460
2461


2462
2463


2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474





2475
2476
2477
2478
2479
2480
2481







-
+
-
-










-
-
+
+
-
-





-
-
+
+
-
-











-
-
-
-
-







	style = 2;
    } else {
	style = 0;
    }
    Tcl_AppendPrintfToObj(psObj, "%d setlinejoin\n", style);

    Tcl_ResetResult(interp);
    if (Tk_CanvasPsOutline(canvas, itemPtr, &linePtr->outline) != TCL_OK) {
    Tk_CanvasPsOutline(canvas, itemPtr, &linePtr->outline);
	goto error;
    }
    Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));

    /*
     * Output polygons for the arrowheads, if there are any.
     */

    if (linePtr->firstArrowPtr != NULL) {
	if (stipple != None) {
	    Tcl_AppendToObj(psObj, "grestore gsave\n", -1);
	}
	if (ArrowheadPostscript(interp, canvas, linePtr,
		linePtr->firstArrowPtr, psObj) != TCL_OK) {
	ArrowheadPostscript(interp, canvas, linePtr,
		linePtr->firstArrowPtr, psObj);
	    goto error;
	}
    }
    if (linePtr->lastArrowPtr != NULL) {
	if (stipple != None) {
	    Tcl_AppendToObj(psObj, "grestore gsave\n", -1);
	}
	if (ArrowheadPostscript(interp, canvas, linePtr,
		linePtr->lastArrowPtr, psObj) != TCL_OK) {
	ArrowheadPostscript(interp, canvas, linePtr,
		linePtr->lastArrowPtr, psObj);
	    goto error;
	}
    }

    /*
     * Plug the accumulated postscript back into the result.
     */

  done:
    (void) Tcl_RestoreInterpState(interp, interpState);
    Tcl_AppendObjToObj(Tcl_GetObjResult(interp), psObj);
    Tcl_DecrRefCount(psObj);
    return TCL_OK;

  error:
    Tcl_DiscardInterpState(interpState);
    Tcl_DecrRefCount(psObj);
    return TCL_ERROR;
}

/*
 *--------------------------------------------------------------
 *
 * ArrowheadPostscript --
 *
2496
2497
2498
2499
2500
2501
2502
2503

2504
2505
2506
2507
2508
2509
2510
2511
2512
2527
2528
2529
2530
2531
2532
2533

2534


2535
2536
2537
2538
2539
2540
2541







-
+
-
-







    Tk_CanvasPsPath(interp, canvas, arrowPtr, PTS_IN_ARROW);
    Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));

    if (stipple != None) {
	Tcl_AppendToObj(psObj, "clip ", -1);

	Tcl_ResetResult(interp);
	if (Tk_CanvasPsStipple(interp, canvas, stipple) != TCL_OK) {
	Tk_CanvasPsStipple(interp, canvas, stipple);
	    return TCL_ERROR;
	}
	Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
    } else {
	Tcl_AppendToObj(psObj, "fill\n", -1);
    }
    return TCL_OK;
}

Changes to generic/tkCanvPoly.c.
1
2
3
4
5
6
7
8



9
10
11
12
13
14
15
1
2
3
4
5



6
7
8
9
10
11
12
13
14
15





-
-
-
+
+
+







/*
 * 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.
 */

#include "tkInt.h"
#include "tkCanvas.h"
58
59
60
61
62
63
64
65

66
67
68
69
70
71
72
73
74
75
76
77
78
79
80

81
82
83

84
85

86
87

88
89
90

91
92

93
94
95

96
97
98

99
100
101

102
103
104

105
106

107
108
109

110
111
112

113
114

115
116
117
118

119
120

121
122

123
124
125

126
127

128
129
130

131
132

133
134
135

136
137

138
139

140
141
142
143

144
145
146
147
148
149
150
58
59
60
61
62
63
64

65
66
67
68
69
70
71
72
73
74
75
76
77
78
79

80
81
82

83
84

85
86

87
88
89

90
91

92
93
94

95
96
97

98
99
100

101
102
103

104
105

106
107
108

109
110
111

112
113

114
115

116

117
118

119
120

121
122
123

124
125

126
127
128

129
130

131
132
133

134
135

136
137

138
139
140
141

142
143
144
145
146
147
148
149







-
+














-
+


-
+

-
+

-
+


-
+

-
+


-
+


-
+


-
+


-
+

-
+


-
+


-
+

-
+

-

-
+

-
+

-
+


-
+

-
+


-
+

-
+


-
+

-
+

-
+



-
+







static const Tk_CustomOption smoothOption = {
    TkSmoothParseProc, TkSmoothPrintProc, NULL
};
static const Tk_CustomOption stateOption = {
    TkStateParseProc, TkStatePrintProc, INT2PTR(2)
};
static const Tk_CustomOption tagsOption = {
    Tk_CanvasTagsParseProc, Tk_CanvasTagsPrintProc, NULL
    TkCanvasTagsParseProc, TkCanvasTagsPrintProc, NULL
};
static const Tk_CustomOption dashOption = {
    TkCanvasDashParseProc, TkCanvasDashPrintProc, NULL
};
static const Tk_CustomOption offsetOption = {
    TkOffsetParseProc, TkOffsetPrintProc,
    INT2PTR(TK_OFFSET_RELATIVE|TK_OFFSET_INDEX)
};
static const Tk_CustomOption pixelOption = {
    TkPixelParseProc, TkPixelPrintProc, NULL
};

static const Tk_ConfigSpec configSpecs[] = {
    {TK_CONFIG_CUSTOM, "-activedash", NULL, NULL,
	NULL, Tk_Offset(PolygonItem, outline.activeDash),
	NULL, offsetof(PolygonItem, outline.activeDash),
	TK_CONFIG_NULL_OK, &dashOption},
    {TK_CONFIG_COLOR, "-activefill", NULL, NULL,
	NULL, Tk_Offset(PolygonItem, activeFillColor), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(PolygonItem, activeFillColor), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_COLOR, "-activeoutline", NULL, NULL,
	NULL, Tk_Offset(PolygonItem, outline.activeColor), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(PolygonItem, outline.activeColor), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_BITMAP, "-activeoutlinestipple", NULL, NULL,
	NULL, Tk_Offset(PolygonItem, outline.activeStipple),
	NULL, offsetof(PolygonItem, outline.activeStipple),
	TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_BITMAP, "-activestipple", NULL, NULL,
	NULL, Tk_Offset(PolygonItem, activeFillStipple), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(PolygonItem, activeFillStipple), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_CUSTOM, "-activewidth", NULL, NULL,
	"0.0", Tk_Offset(PolygonItem, outline.activeWidth),
	"0.0", offsetof(PolygonItem, outline.activeWidth),
	TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
    {TK_CONFIG_CUSTOM, "-dash", NULL, NULL,
	NULL, Tk_Offset(PolygonItem, outline.dash),
	NULL, offsetof(PolygonItem, outline.dash),
	TK_CONFIG_NULL_OK, &dashOption},
    {TK_CONFIG_PIXELS, "-dashoffset", NULL, NULL,
	"0", Tk_Offset(PolygonItem, outline.offset),
	"0", offsetof(PolygonItem, outline.offset),
	TK_CONFIG_DONT_SET_DEFAULT, NULL},
    {TK_CONFIG_CUSTOM, "-disableddash", NULL, NULL,
	NULL, Tk_Offset(PolygonItem, outline.disabledDash),
	NULL, offsetof(PolygonItem, outline.disabledDash),
	TK_CONFIG_NULL_OK, &dashOption},
    {TK_CONFIG_COLOR, "-disabledfill", NULL, NULL,
	NULL, Tk_Offset(PolygonItem, disabledFillColor), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(PolygonItem, disabledFillColor), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_COLOR, "-disabledoutline", NULL, NULL,
	NULL, Tk_Offset(PolygonItem, outline.disabledColor),
	NULL, offsetof(PolygonItem, outline.disabledColor),
	TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_BITMAP, "-disabledoutlinestipple", NULL, NULL,
	NULL, Tk_Offset(PolygonItem, outline.disabledStipple),
	NULL, offsetof(PolygonItem, outline.disabledStipple),
	TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_BITMAP, "-disabledstipple", NULL, NULL,
	NULL, Tk_Offset(PolygonItem, disabledFillStipple), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(PolygonItem, disabledFillStipple), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_CUSTOM, "-disabledwidth", NULL, NULL,
	"0.0", Tk_Offset(PolygonItem, outline.disabledWidth),
	"0.0", offsetof(PolygonItem, outline.disabledWidth),
	TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
    /* Remark: Default for -fill should be NULL, see [2860519]. Will be fixed in Tk 8.7 */
    {TK_CONFIG_COLOR, "-fill", NULL, NULL,
 	DEF_CANVITEM_OUTLINE, Tk_Offset(PolygonItem, fillColor), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(PolygonItem, fillColor), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_JOIN_STYLE, "-joinstyle", NULL, NULL,
	"round", Tk_Offset(PolygonItem, joinStyle), TK_CONFIG_DONT_SET_DEFAULT, NULL},
	"round", offsetof(PolygonItem, joinStyle), TK_CONFIG_DONT_SET_DEFAULT, NULL},
    {TK_CONFIG_CUSTOM, "-offset", NULL, NULL,
	"0,0", Tk_Offset(PolygonItem, tsoffset),
	"0,0", offsetof(PolygonItem, tsoffset),
	TK_CONFIG_NULL_OK, &offsetOption},
    {TK_CONFIG_COLOR, "-outline", NULL, NULL,
	NULL, Tk_Offset(PolygonItem, outline.color), TK_CONFIG_NULL_OK, NULL},
	DEF_CANVITEM_OUTLINE, offsetof(PolygonItem, outline.color), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_CUSTOM, "-outlineoffset", NULL, NULL,
	"0,0", Tk_Offset(PolygonItem, outline.tsoffset),
	"0,0", offsetof(PolygonItem, outline.tsoffset),
	TK_CONFIG_NULL_OK, &offsetOption},
    {TK_CONFIG_BITMAP, "-outlinestipple", NULL, NULL,
	NULL, Tk_Offset(PolygonItem, outline.stipple), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(PolygonItem, outline.stipple), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_CUSTOM, "-smooth", NULL, NULL,
	"0", Tk_Offset(PolygonItem, smooth),
	"0", offsetof(PolygonItem, smooth),
	TK_CONFIG_DONT_SET_DEFAULT, &smoothOption},
    {TK_CONFIG_INT, "-splinesteps", NULL, NULL,
	"12", Tk_Offset(PolygonItem, splineSteps), TK_CONFIG_DONT_SET_DEFAULT, NULL},
	"12", offsetof(PolygonItem, splineSteps), TK_CONFIG_DONT_SET_DEFAULT, NULL},
    {TK_CONFIG_CUSTOM, "-state", NULL, NULL,
	NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK, &stateOption},
	NULL, offsetof(Tk_Item, state), TK_CONFIG_NULL_OK, &stateOption},
    {TK_CONFIG_BITMAP, "-stipple", NULL, NULL,
	NULL, Tk_Offset(PolygonItem, fillStipple), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(PolygonItem, fillStipple), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_CUSTOM, "-tags", NULL, NULL,
	NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},
    {TK_CONFIG_CUSTOM, "-width", NULL, NULL,
	"1.0", Tk_Offset(PolygonItem, outline.width),
	"1.0", offsetof(PolygonItem, outline.width),
	TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
    {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL}
};

/*
 * Prototypes for functions defined in this file:
 */
160
161
162
163
164
165
166
167

168
169
170
171
172

173
174

175
176
177
178
179
180


181
182
183
184
185
186
187
159
160
161
162
163
164
165

166
167
168
169
170

171
172

173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188







-
+




-
+

-
+






+
+







static void		DeletePolygon(Tk_Canvas canvas,
			    Tk_Item *itemPtr,  Display *display);
static void		DisplayPolygon(Tk_Canvas canvas,
			    Tk_Item *itemPtr, Display *display, Drawable dst,
			    int x, int y, int width, int height);
static int		GetPolygonIndex(Tcl_Interp *interp,
			    Tk_Canvas canvas, Tk_Item *itemPtr,
			    Tcl_Obj *obj, int *indexPtr);
			    Tcl_Obj *obj, TkSizeT *indexPtr);
static int		PolygonCoords(Tcl_Interp *interp,
			    Tk_Canvas canvas, Tk_Item *itemPtr,
			    int objc, Tcl_Obj *const objv[]);
static void		PolygonDeleteCoords(Tk_Canvas canvas,
			    Tk_Item *itemPtr, int first, int last);
			    Tk_Item *itemPtr, TkSizeT first, TkSizeT last);
static void		PolygonInsert(Tk_Canvas canvas,
			    Tk_Item *itemPtr, int beforeThis, Tcl_Obj *obj);
			    Tk_Item *itemPtr, TkSizeT beforeThis, Tcl_Obj *obj);
static int		PolygonToArea(Tk_Canvas canvas,
			    Tk_Item *itemPtr, double *rectPtr);
static double		PolygonToPoint(Tk_Canvas canvas,
			    Tk_Item *itemPtr, double *pointPtr);
static int		PolygonToPostscript(Tcl_Interp *interp,
			    Tk_Canvas canvas, Tk_Item *itemPtr, int prepass);
static void		RotatePolygon(Tk_Canvas canvas, Tk_Item *itemPtr,
			    double originX, double originY, double angleRad);
static void		ScalePolygon(Tk_Canvas canvas,
			    Tk_Item *itemPtr, double originX, double originY,
			    double scaleX, double scaleY);
static void		TranslatePolygon(Tk_Canvas canvas,
			    Tk_Item *itemPtr, double deltaX, double deltaY);

/*
206
207
208
209
210
211
212

213

214
215
216
217
218
219
220
207
208
209
210
211
212
213
214

215
216
217
218
219
220
221
222







+
-
+







    TranslatePolygon,			/* translateProc */
    GetPolygonIndex,	/* indexProc */
    NULL,				/* icursorProc */
    NULL,				/* selectionProc */
    PolygonInsert,		/* insertProc */
    PolygonDeleteCoords,		/* dTextProc */
    NULL,				/* nextPtr */
    RotatePolygon,			/* rotateProc */
    NULL, 0, NULL, NULL
    0, NULL, NULL
};

/*
 * The definition below determines how large are static arrays used to hold
 * spline points (splines larger than this have to have their arrays
 * malloc-ed).
 */
372
373
374
375
376
377
378
379

380
381
382
383
384
385
386
374
375
376
377
378
379
380

381
382
383
384
385
386
387
388







-
+







	}

	/*
	 * One extra point gets allocated here, because we always add
	 * another point to close the polygon.
	 */

	polyPtr->coordPtr = ckalloc(sizeof(double) * (objc+2));
	polyPtr->coordPtr = (double *)ckalloc(sizeof(double) * (objc+2));
	polyPtr->pointsAllocated = numPoints+1;
    }
    for (i = objc-1; i >= 0; i--) {
	if (Tk_CanvasGetCoordFromObj(interp, canvas, objv[i],
		&polyPtr->coordPtr[i]) != TCL_OK) {
	    return TCL_ERROR;
	}
560
561
562
563
564
565
566
567

568
569
570
571
572
573
574
562
563
564
565
566
567
568

569
570
571
572
573
574
575
576







-
+







 *	Resources associated with itemPtr are released.
 *
 *--------------------------------------------------------------
 */

static void
DeletePolygon(
    Tk_Canvas canvas,		/* Info about overall canvas widget. */
    TCL_UNUSED(Tk_Canvas),		/* Info about overall canvas widget. */
    Tk_Item *itemPtr,		/* Item that is being deleted. */
    Display *display)		/* Display containing window for canvas. */
{
    PolygonItem *polyPtr = (PolygonItem *) itemPtr;

    Tk_DeleteOutline(display, &polyPtr->outline);
    if (polyPtr->coordPtr != NULL) {
821
822
823
824
825
826
827
828

829
830
831
832
833
834
835
823
824
825
826
827
828
829

830
831
832
833
834
835
836
837







-
+







     * unless the polygon has an enormous number of points; in this case,
     * dynamically allocate an array.
     */

    if (numPoints <= MAX_STATIC_POINTS) {
	pointPtr = staticPoints;
    } else {
	pointPtr = ckalloc(numPoints * sizeof(XPoint));
	pointPtr = (XPoint *)ckalloc(numPoints * sizeof(XPoint));
    }

    for (i=0, pPtr=pointPtr ; i<numPoints; i+=1, coordPtr+=2, pPtr++) {
	Tk_CanvasDrawableCoords(canvas, coordPtr[0], coordPtr[1], &pPtr->x,
		&pPtr->y);
    }

870
871
872
873
874
875
876
877
878
879




880
881
882
883
884
885
886
872
873
874
875
876
877
878



879
880
881
882
883
884
885
886
887
888
889







-
-
-
+
+
+
+








static void
DisplayPolygon(
    Tk_Canvas canvas,		/* Canvas that contains item. */
    Tk_Item *itemPtr,		/* Item to be displayed. */
    Display *display,		/* Display on which to draw item. */
    Drawable drawable,		/* Pixmap or window in which to draw item. */
    int x, int y, int width, int height)
				/* Describes region of canvas that must be
				 * redisplayed (not used). */
    TCL_UNUSED(int),	/* Describes region of canvas that must be */
    TCL_UNUSED(int),	/* redisplayed (not used). */
    TCL_UNUSED(int),
    TCL_UNUSED(int))
{
    PolygonItem *polyPtr = (PolygonItem *) itemPtr;
    Tk_State state = itemPtr->state;
    Pixmap stipple = polyPtr->fillStipple;
    double linewidth = polyPtr->outline.width;

    if (((polyPtr->fillGC == NULL) && (polyPtr->outline.gc == NULL)) ||
967
968
969
970
971
972
973
974

975
976
977
978
979
980
981
970
971
972
973
974
975
976

977
978
979
980
981
982
983
984







-
+







	 */

	numPoints = polyPtr->smooth->coordProc(canvas, NULL,
		polyPtr->numPoints, polyPtr->splineSteps, NULL, NULL);
	if (numPoints <= MAX_STATIC_POINTS) {
	    pointPtr = staticPoints;
	} else {
	    pointPtr = ckalloc(numPoints * sizeof(XPoint));
	    pointPtr = (XPoint *)ckalloc(numPoints * sizeof(XPoint));
	}
	numPoints = polyPtr->smooth->coordProc(canvas, polyPtr->coordPtr,
		polyPtr->numPoints, polyPtr->splineSteps, pointPtr, NULL);
	if (polyPtr->fillGC != NULL) {
	    XFillPolygon(display, drawable, polyPtr->fillGC, pointPtr,
		    numPoints, Complex, CoordModeOrigin);
	}
994
995
996
997
998
999
1000
1001

1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016

1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035

1036
1037
1038

1039
1040
1041
1042


1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053

1054
1055
1056
1057
1058
1059
1060
997
998
999
1000
1001
1002
1003

1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018

1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037

1038
1039
1040

1041
1042
1043


1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055

1056
1057
1058
1059
1060
1061
1062
1063







-
+














-
+


















-
+


-
+


-
-
+
+










-
+







}

/*
 *--------------------------------------------------------------
 *
 * PolygonInsert --
 *
 *	Insert coords into a polugon item at a given index.
 *	Insert coords into a polygon item at a given index.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The coords in the given item is modified.
 *
 *--------------------------------------------------------------
 */

static void
PolygonInsert(
    Tk_Canvas canvas,		/* Canvas containing text item. */
    Tk_Item *itemPtr,		/* Line item to be modified. */
    int beforeThis,		/* Index before which new coordinates are to
    TkSizeT beforeThis,		/* Index before which new coordinates are to
				 * be inserted. */
    Tcl_Obj *obj)		/* New coordinates to be inserted. */
{
    PolygonItem *polyPtr = (PolygonItem *) itemPtr;
    int length, objc, i;
    Tcl_Obj **objv;
    double *newCoordPtr;
    Tk_State state = itemPtr->state;

    if (state == TK_STATE_NULL) {
	state = Canvas(canvas)->canvas_state;
    }

    if (!obj || (Tcl_ListObjGetElements(NULL, obj, &objc, &objv) != TCL_OK)
	    || !objc || objc&1) {
	return;
    }
    length = 2*(polyPtr->numPoints - polyPtr->autoClosed);
    while (beforeThis > length) {
    while ((int)beforeThis > length) {
	beforeThis -= length;
    }
    while (beforeThis < 0) {
    while ((int)beforeThis < 0) {
	beforeThis += length;
    }
    newCoordPtr = ckalloc(sizeof(double) * (length + 2 + objc));
    for (i=0; i<beforeThis; i++) {
    newCoordPtr = (double *)ckalloc(sizeof(double) * (length + 2 + objc));
    for (i=0; i<(int)beforeThis; i++) {
	newCoordPtr[i] = polyPtr->coordPtr[i];
    }
    for (i=0; i<objc; i++) {
	if (Tcl_GetDoubleFromObj(NULL, objv[i],
		&newCoordPtr[i+beforeThis]) != TCL_OK){
	    ckfree(newCoordPtr);
	    return;
	}
    }

    for (i=beforeThis; i<length; i++) {
    for (i=(int)beforeThis; i<length; i++) {
	newCoordPtr[i+objc] = polyPtr->coordPtr[i];
    }
    if (polyPtr->coordPtr) {
	ckfree(polyPtr->coordPtr);
    }
    length += objc;
    polyPtr->coordPtr = newCoordPtr;
1112
1113
1114
1115
1116
1117
1118
1119

1120
1121
1122
1123
1124
1125
1126
1115
1116
1117
1118
1119
1120
1121

1122
1123
1124
1125
1126
1127
1128
1129







-
+







	    objc += 4;
	}

	/*
	 * Be careful; beforeThis could now be negative
	 */

	for (i=beforeThis; i<beforeThis+objc; i+=2) {
	for (i=beforeThis; i<(int)beforeThis+objc; i+=2) {
	    j = i;
	    if (j < 0) {
		j += length;
	    } else if (j >= length) {
		j -= length;
	    }
	    TkIncludePoint(itemPtr, polyPtr->coordPtr+j);
1163
1164
1165
1166
1167
1168
1169
1170
1171


1172
1173
1174
1175
1176
1177

1178
1179
1180

1181
1182
1183

1184
1185
1186

1187
1188
1189
1190
1191
1192
1193
1166
1167
1168
1169
1170
1171
1172


1173
1174
1175
1176
1177
1178
1179

1180
1181
1182

1183
1184
1185

1186
1187
1188

1189
1190
1191
1192
1193
1194
1195
1196







-
-
+
+





-
+


-
+


-
+


-
+







 *--------------------------------------------------------------
 */

static void
PolygonDeleteCoords(
    Tk_Canvas canvas,		/* Canvas containing itemPtr. */
    Tk_Item *itemPtr,		/* Item in which to delete characters. */
    int first,			/* Index of first character to delete. */
    int last)			/* Index of last character to delete. */
    TkSizeT first,			/* Index of first character to delete. */
    TkSizeT last)			/* Index of last character to delete. */
{
    PolygonItem *polyPtr = (PolygonItem *) itemPtr;
    int count, i;
    int length = 2*(polyPtr->numPoints - polyPtr->autoClosed);

    while (first >= length) {
    while ((int)first >= length) {
	first -= length;
    }
    while (first < 0) {
    while ((int)first < 0) {
	first += length;
    }
    while (last >= length) {
    while ((int)last >= length) {
	last -= length;
    }
    while (last < 0) {
    while ((int)last < 0) {
	last += length;
    }

    first &= -2;
    last &= -2;

    count = last + 2 - first;
1206
1207
1208
1209
1210
1211
1212
1213

1214
1215
1216
1217
1218
1219
1220
1209
1210
1211
1212
1213
1214
1215

1216
1217
1218
1219
1220
1221
1222
1223







-
+







    }

    if (last >= first) {
	for (i=last+2; i<length; i++) {
	    polyPtr->coordPtr[i-count] = polyPtr->coordPtr[i];
	}
    } else {
	for (i=last; i<=first; i++) {
	for (i=last; i<=(int)first; i++) {
	    polyPtr->coordPtr[i-last] = polyPtr->coordPtr[i];
	}
    }
    polyPtr->coordPtr[length-count] = polyPtr->coordPtr[0];
    polyPtr->coordPtr[length-count+1] = polyPtr->coordPtr[1];
    polyPtr->numPoints -= count/2;
    ComputePolygonBbox(canvas, polyPtr);
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1239
1240
1241
1242
1243
1244
1245

1246
1247
1248
1249
1250
1251
1252







-







 *
 * Side effects:
 *	None.
 *
 *--------------------------------------------------------------
 */

	/* ARGSUSED */
static double
PolygonToPoint(
    Tk_Canvas canvas,		/* Canvas containing item. */
    Tk_Item *itemPtr,		/* Item to check against point. */
    double *pointPtr)		/* Pointer to x and y coordinates. */
{
    PolygonItem *polyPtr = (PolygonItem *) itemPtr;
1284
1285
1286
1287
1288
1289
1290
1291

1292
1293
1294
1295
1296
1297
1298
1286
1287
1288
1289
1290
1291
1292

1293
1294
1295
1296
1297
1298
1299
1300







-
+








    if ((polyPtr->smooth) && (polyPtr->numPoints > 2)) {
	numPoints = polyPtr->smooth->coordProc(canvas, NULL,
		polyPtr->numPoints, polyPtr->splineSteps, NULL, NULL);
	if (numPoints <= MAX_STATIC_POINTS) {
	    polyPoints = staticSpace;
	} else {
	    polyPoints = ckalloc(2 * numPoints * sizeof(double));
	    polyPoints = (double *)ckalloc(2 * numPoints * sizeof(double));
	}
	numPoints = polyPtr->smooth->coordProc(canvas, polyPtr->coordPtr,
		polyPtr->numPoints, polyPtr->splineSteps, NULL, polyPoints);
    } else {
	numPoints = polyPtr->numPoints;
	polyPoints = polyPtr->coordPtr;
    }
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1428
1429
1430
1431
1432
1433
1434

1435
1436
1437
1438
1439
1440
1441







-







 *
 * Side effects:
 *	None.
 *
 *--------------------------------------------------------------
 */

	/* ARGSUSED */
static int
PolygonToArea(
    Tk_Canvas canvas,		/* Canvas containing item. */
    Tk_Item *itemPtr,		/* Item to check against polygon. */
    double *rectPtr)		/* Pointer to array of four coordinates
				 * (x1,y1,x2,y2) describing rectangular
				 * area. */
1493
1494
1495
1496
1497
1498
1499
1500

1501
1502
1503
1504
1505
1506
1507
1494
1495
1496
1497
1498
1499
1500

1501
1502
1503
1504
1505
1506
1507
1508







-
+








    if (polyPtr->smooth) {
	numPoints = polyPtr->smooth->coordProc(canvas, NULL,
		polyPtr->numPoints, polyPtr->splineSteps, NULL, NULL);
	if (numPoints <= MAX_STATIC_POINTS) {
	    polyPoints = staticSpace;
	} else {
	    polyPoints = ckalloc(2 * numPoints * sizeof(double));
	    polyPoints = (double *)ckalloc(2 * numPoints * sizeof(double));
	}
	numPoints = polyPtr->smooth->coordProc(canvas, polyPtr->coordPtr,
		polyPtr->numPoints, polyPtr->splineSteps, NULL, polyPoints);
    } else {
	numPoints = polyPtr->numPoints;
	polyPoints = polyPtr->coordPtr;
    }
1663
1664
1665
1666
1667
1668
1669
1670

1671
1672
1673
1674
1675

1676

1677
1678


1679

1680
1681
1682
1683
1684
1685












1686
1687
1688
1689
1690
1691
1692
1664
1665
1666
1667
1668
1669
1670

1671
1672
1673
1674
1675

1676
1677
1678
1679

1680
1681
1682
1683






1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702







-
+




-
+

+

-
+
+

+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+







 *
 *--------------------------------------------------------------
 */

static int
GetPolygonIndex(
    Tcl_Interp *interp,		/* Used for error reporting. */
    Tk_Canvas canvas,		/* Canvas containing item. */
    TCL_UNUSED(Tk_Canvas),		/* Canvas containing item. */
    Tk_Item *itemPtr,		/* Item for which the index is being
				 * specified. */
    Tcl_Obj *obj,		/* Specification of a particular coord in
				 * itemPtr's line. */
    int *indexPtr)		/* Where to store converted index. */
    TkSizeT *indexPtr)		/* Where to store converted index. */
{
    TkSizeT length, idx;
    PolygonItem *polyPtr = (PolygonItem *) itemPtr;
    const char *string = Tcl_GetString(obj);
    const char *string;
    TkSizeT count = 2*(polyPtr->numPoints - polyPtr->autoClosed);

    if (TCL_OK == TkGetIntForIndex(obj,  (INT_MAX - 1) - ((INT_MAX) % count), 1, &idx)) {
    if (string[0] == 'e') {
	if (strncmp(string, "end", obj->length) != 0) {
	    goto badIndex;
	}
	*indexPtr = 2*(polyPtr->numPoints - polyPtr->autoClosed);
    } else if (string[0] == '@') {
	if (idx == TCL_INDEX_NONE) {
	    idx = 0;
	} else {
	    idx = (idx & (TkSizeT)-2) % count;
	}
	*indexPtr = idx;
	return TCL_OK;
    }

    string = TkGetStringFromObj(obj, &length);

    if (string[0] == '@') {
	int i;
	double x, y, bestDist, dist, *coordPtr;
	char *end;
	const char *p;

	p = string+1;
	x = strtod(p, &end);
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732




1733
1734
1735
1736
1737












































1738
1739
1740
1741
1742
1743
1744
1716
1717
1718
1719
1720
1721
1722




















1723
1724
1725
1726
1727




1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+

-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	    if (dist < bestDist) {
		bestDist = dist;
		*indexPtr = 2*i;
	    }
	    coordPtr += 2;
	}
    } else {
	int count = 2*(polyPtr->numPoints - polyPtr->autoClosed);

	if (Tcl_GetIntFromObj(interp, obj, indexPtr) != TCL_OK) {
	    goto badIndex;
	}
	*indexPtr &= -2; /* if odd, make it even */
	if (!count) {
	    *indexPtr = 0;
	} else if (*indexPtr > 0) {
	    *indexPtr = ((*indexPtr - 2) % count) + 2;
	} else {
	    *indexPtr = -((-(*indexPtr)) % count);
	}
    }
    return TCL_OK;

    /*
     * Some of the paths here leave messages in interp->result, so we have to
     * clear it out before storing our own message.
     */
	/*
	 * Some of the paths here leave messages in interp->result, so we have to
	 * clear it out before storing our own message.
	 */

  badIndex:
    Tcl_SetObjResult(interp, Tcl_ObjPrintf("bad index \"%s\"", string));
    Tcl_SetErrorCode(interp, "TK", "CANVAS", "ITEM_INDEX", "POLY", NULL);
    return TCL_ERROR;
    badIndex:
	Tcl_SetObjResult(interp, Tcl_ObjPrintf("bad index \"%s\"", string));
	Tcl_SetErrorCode(interp, "TK", "CANVAS", "ITEM_INDEX", "POLY", NULL);
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 *--------------------------------------------------------------
 *
 * RotatePolygon --
 *
 *	This function is called to rotate a polygon by a given amount about a
 *	point.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The position of the polygon is rotated by angleRad about (originX,
 *	originY), and the bounding box is updated in the generic part of the
 *	item structure.
 *
 *--------------------------------------------------------------
 */

static void
RotatePolygon(
    Tk_Canvas canvas,		/* Canvas containing item. */
    Tk_Item *itemPtr,		/* Item that is being moved. */
    double originX, double originY,
    double angleRad)		/* Amount by which item is to be rotated. */
{
    PolygonItem *polyPtr = (PolygonItem *) itemPtr;
    double *coordPtr;
    int i;
    double s = sin(angleRad), c = cos(angleRad);

    for (i = 0, coordPtr = polyPtr->coordPtr; i < polyPtr->numPoints;
	    i++, coordPtr += 2) {
	TkRotatePoint(originX, originY, s, c, &coordPtr[0], &coordPtr[1]);
    }
    ComputePolygonBbox(canvas, polyPtr);
}

/*
 *--------------------------------------------------------------
 *
 * TranslatePolygon --
 *
1793
1794
1795
1796
1797
1798
1799
1800

1801
1802
1803
1804
1805
1806
1807
1827
1828
1829
1830
1831
1832
1833

1834
1835
1836
1837
1838
1839
1840
1841







-
+







 */

static int
PolygonToPostscript(
    Tcl_Interp *interp,		/* Leave Postscript or error message here. */
    Tk_Canvas canvas,		/* Information about overall canvas. */
    Tk_Item *itemPtr,		/* Item for which Postscript is wanted. */
    int prepass)		/* 1 means this is a prepass to collect font
    TCL_UNUSED(int))	/* 1 means this is a prepass to collect font
				 * information; 0 means final Postscript is
				 * being created. */
{
    PolygonItem *polyPtr = (PolygonItem *) itemPtr;
    int style;
    XColor *color;
    XColor *fillColor;
1887
1888
1889
1890
1891
1892
1893
1894

1895
1896
1897
1898
1899
1900
1901
1902
1903

1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926

1927
1928
1929
1930
1931
1932
1933
1934
1935

1936
1937
1938
1939
1940
1941
1942
1943
1944
1921
1922
1923
1924
1925
1926
1927

1928


1929
1930
1931
1932
1933
1934

1935


1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955

1956


1957
1958
1959
1960
1961
1962

1963


1964
1965
1966
1967
1968
1969
1970







-
+
-
-






-
+
-
-




















-
+
-
-






-
+
-
-







		width/2.0, width/2.0);

	/*
	 * Color it in.
	 */

	Tcl_ResetResult(interp);
	if (Tk_CanvasPsColor(interp, canvas, color) != TCL_OK) {
	Tk_CanvasPsColor(interp, canvas, color);
	    goto error;
	}
	Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));

	if (stipple != None) {
	    Tcl_AppendToObj(psObj, "clip ", -1);

	    Tcl_ResetResult(interp);
	    if (Tk_CanvasPsStipple(interp, canvas, stipple) != TCL_OK) {
	    Tk_CanvasPsStipple(interp, canvas, stipple);
		goto error;
	    }
	    Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
	} else {
	    Tcl_AppendToObj(psObj, "fill\n", -1);
	}
	goto done;
    }

    /*
     * Fill the area of the polygon.
     */

    if (fillColor != NULL && polyPtr->numPoints > 3) {
	Tcl_ResetResult(interp);
	if (!polyPtr->smooth || !polyPtr->smooth->postscriptProc) {
	    Tk_CanvasPsPath(interp, canvas, polyPtr->coordPtr,
		    polyPtr->numPoints);
	} else {
	    polyPtr->smooth->postscriptProc(interp, canvas, polyPtr->coordPtr,
		    polyPtr->numPoints, polyPtr->splineSteps);
	}
	if (Tk_CanvasPsColor(interp, canvas, fillColor) != TCL_OK) {
	Tk_CanvasPsColor(interp, canvas, fillColor);
	    goto error;
	}
	Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));

	if (fillStipple != None) {
	    Tcl_AppendToObj(psObj, "eoclip ", -1);

	    Tcl_ResetResult(interp);
	    if (Tk_CanvasPsStipple(interp, canvas, fillStipple) != TCL_OK) {
	    Tk_CanvasPsStipple(interp, canvas, fillStipple);
		goto error;
	    }
	    Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));

	    if (color != NULL) {
		Tcl_AppendToObj(psObj, "grestore gsave\n", -1);
	    }
	} else {
	    Tcl_AppendToObj(psObj, "eofill\n", -1);
1966
1967
1968
1969
1970
1971
1972
1973

1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
1992
1993
1994
1995
1996
1997
1998

1999


2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011





2012
2013
2014
2015
2016
2017
2018
2019
2020







-
+
-
-












-
-
-
-
-









	    style = 2;
	} else {
	    style = 0;
	}
	Tcl_AppendPrintfToObj(psObj, "%d setlinejoin 1 setlinecap\n", style);

	Tcl_ResetResult(interp);
	if (Tk_CanvasPsOutline(canvas, itemPtr, &polyPtr->outline) != TCL_OK){
	Tk_CanvasPsOutline(canvas, itemPtr, &polyPtr->outline);
	    goto error;
	}
	Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
    }

    /*
     * Plug the accumulated postscript back into the result.
     */

  done:
    (void) Tcl_RestoreInterpState(interp, interpState);
    Tcl_AppendObjToObj(Tcl_GetObjResult(interp), psObj);
    Tcl_DecrRefCount(psObj);
    return TCL_OK;

  error:
    Tcl_DiscardInterpState(interpState);
    Tcl_DecrRefCount(psObj);
    return TCL_ERROR;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Changes to generic/tkCanvPs.c.
1
2
3
4
5
6
7
8
9


10
11
12
13
14
15
16
1
2
3
4
5
6
7


8
9
10
11
12
13
14
15
16







-
-
+
+







/*
 * tkCanvPs.c --
 *
 *	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.
 */

#include "tkInt.h"
#include "tkCanvas.h"
90
91
92
93
94
95
96
97

98
99

100
101

102
103

104
105

106
107

108
109

110
111

112
113

114
115

116
117

118
119

120
121

122
123

124
125

126
127

128
129
130
131
132
133
134
90
91
92
93
94
95
96

97
98

99
100

101
102

103
104

105
106

107
108

109
110

111
112

113
114

115
116

117
118

119
120

121
122

123
124

125
126

127
128
129
130
131
132
133
134







-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+







/*
 * The table below provides a template that's used to process arguments to the
 * canvas "postscript" command and fill in TkPostscriptInfo structures.
 */

static const Tk_ConfigSpec configSpecs[] = {
    {TK_CONFIG_STRING, "-colormap", NULL, NULL,
	"", Tk_Offset(TkPostscriptInfo, colorVar), 0, NULL},
	"", offsetof(TkPostscriptInfo, colorVar), 0, NULL},
    {TK_CONFIG_STRING, "-colormode", NULL, NULL,
	"", Tk_Offset(TkPostscriptInfo, colorMode), 0, NULL},
	"", offsetof(TkPostscriptInfo, colorMode), 0, NULL},
    {TK_CONFIG_STRING, "-file", NULL, NULL,
	"", Tk_Offset(TkPostscriptInfo, fileName), 0, NULL},
	"", offsetof(TkPostscriptInfo, fileName), 0, NULL},
    {TK_CONFIG_STRING, "-channel", NULL, NULL,
	"", Tk_Offset(TkPostscriptInfo, channelName), 0, NULL},
	"", offsetof(TkPostscriptInfo, channelName), 0, NULL},
    {TK_CONFIG_STRING, "-fontmap", NULL, NULL,
	"", Tk_Offset(TkPostscriptInfo, fontVar), 0, NULL},
	"", offsetof(TkPostscriptInfo, fontVar), 0, NULL},
    {TK_CONFIG_PIXELS, "-height", NULL, NULL,
	"", Tk_Offset(TkPostscriptInfo, height), 0, NULL},
	"", offsetof(TkPostscriptInfo, height), 0, NULL},
    {TK_CONFIG_ANCHOR, "-pageanchor", NULL, NULL,
	"", Tk_Offset(TkPostscriptInfo, pageAnchor), 0, NULL},
	"", offsetof(TkPostscriptInfo, pageAnchor), 0, NULL},
    {TK_CONFIG_STRING, "-pageheight", NULL, NULL,
	"", Tk_Offset(TkPostscriptInfo, pageHeightString), 0, NULL},
	"", offsetof(TkPostscriptInfo, pageHeightString), 0, NULL},
    {TK_CONFIG_STRING, "-pagewidth", NULL, NULL,
	"", Tk_Offset(TkPostscriptInfo, pageWidthString), 0, NULL},
	"", offsetof(TkPostscriptInfo, pageWidthString), 0, NULL},
    {TK_CONFIG_STRING, "-pagex", NULL, NULL,
	"", Tk_Offset(TkPostscriptInfo, pageXString), 0, NULL},
	"", offsetof(TkPostscriptInfo, pageXString), 0, NULL},
    {TK_CONFIG_STRING, "-pagey", NULL, NULL,
	"", Tk_Offset(TkPostscriptInfo, pageYString), 0, NULL},
	"", offsetof(TkPostscriptInfo, pageYString), 0, NULL},
    {TK_CONFIG_BOOLEAN, "-prolog", NULL, NULL,
	"", Tk_Offset(TkPostscriptInfo, prolog), 0, NULL},
	"", offsetof(TkPostscriptInfo, prolog), 0, NULL},
    {TK_CONFIG_BOOLEAN, "-rotate", NULL, NULL,
	"", Tk_Offset(TkPostscriptInfo, rotate), 0, NULL},
	"", offsetof(TkPostscriptInfo, rotate), 0, NULL},
    {TK_CONFIG_PIXELS, "-width", NULL, NULL,
	"", Tk_Offset(TkPostscriptInfo, width), 0, NULL},
	"", offsetof(TkPostscriptInfo, width), 0, NULL},
    {TK_CONFIG_PIXELS, "-x", NULL, NULL,
	"", Tk_Offset(TkPostscriptInfo, x), 0, NULL},
	"", offsetof(TkPostscriptInfo, x), 0, NULL},
    {TK_CONFIG_PIXELS, "-y", NULL, NULL,
	"", Tk_Offset(TkPostscriptInfo, y), 0, NULL},
	"", offsetof(TkPostscriptInfo, y), 0, NULL},
    {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL}
};

/*
 * Forward declarations for functions defined later in this file:
 */

153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
153
154
155
156
157
158
159

160
161
162
163
164
165
166







-







 *
 * Side effects:
 *	See the user documentation.
 *
 *--------------------------------------------------------------
 */

    /* ARGSUSED */
int
TkCanvPostscriptCmd(
    TkCanvas *canvasPtr,	/* Information about canvas widget. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. Caller has already parsed
				 * this command enough to know that argv[1] is
189
190
191
192
193
194
195
196

197
198
199
200
201
202
203
188
189
190
191
192
193
194

195
196
197
198
199
200
201
202







-
+








    /*
     * Get the generic preamble. We only ever bother with the ASCII encoding;
     * the others just make life too complicated and never actually worked as
     * such.
     */

    result = Tcl_EvalEx(interp, "::tk::ensure_psenc_is_loaded", -1, 0);
    result = Tcl_EvalEx(interp, "::tk::ensure_psenc_is_loaded", -1, TCL_EVAL_GLOBAL);
    if (result != TCL_OK) {
	return result;
    }
    preambleObj = Tcl_GetVar2Ex(interp, "::tk::ps_preamble", NULL,
	    TCL_LEAVE_ERR_MSG);
    if (preambleObj == NULL) {
	return TCL_ERROR;
487
488
489
490
491
492
493
494

495
496
497
498
499
500
501
486
487
488
489
490
491
492

493
494
495
496
497
498
499
500







-
+







	/*
	 * Insert the prolog
	 */

	Tcl_AppendObjToObj(psObj, preambleObj);

	if (psInfo.chan != NULL) {
	    if (Tcl_WriteObj(psInfo.chan, psObj) == -1) {
	    if (Tcl_WriteObj(psInfo.chan, psObj) == TCL_IO_FAILURE) {
	    channelWriteFailed:
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"problem writing postscript data to channel: %s",
			Tcl_PosixError(interp)));
		result = TCL_ERROR;
		goto cleanup;
	    }
541
542
543
544
545
546
547
548

549
550
551
552
553
554
555
540
541
542
543
544
545
546

547
548
549
550
551
552
553
554







-
+







		psInfo.x2, Tk_PostscriptY((double)psInfo.y,
			(Tk_PostscriptInfo)psInfoPtr),
		psInfo.x2, Tk_PostscriptY((double)psInfo.y2,
			(Tk_PostscriptInfo)psInfoPtr),
		psInfo.x, Tk_PostscriptY((double)psInfo.y2,
			(Tk_PostscriptInfo)psInfoPtr));
	if (psInfo.chan != NULL) {
	    if (Tcl_WriteObj(psInfo.chan, psObj) == -1) {
	    if (Tcl_WriteObj(psInfo.chan, psObj) == TCL_IO_FAILURE) {
		goto channelWriteFailed;
	    }
	    Tcl_DecrRefCount(psObj);
	    psObj = Tcl_NewObj();
	}
    }

568
569
570
571
572
573
574
575
576
577
578
579
580
581

582
583
584
585
586
587

588
589
590

591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611

612
613
614
615
616
617
618
567
568
569
570
571
572
573

574
575
576
577
578

579
580
581
582
583
584
585
586
587
588

589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609

610
611
612
613
614
615
616
617







-





-
+






+


-
+




















-
+







	if (itemPtr->typePtr->postscriptProc == NULL) {
	    continue;
	}
	if (itemPtr->state == TK_STATE_HIDDEN) {
	    continue;
	}

	Tcl_ResetResult(interp);
	result = itemPtr->typePtr->postscriptProc(interp,
		(Tk_Canvas) canvasPtr, itemPtr, 0);
	if (result != TCL_OK) {
	    Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
		    "\n    (generating Postscript for item %d)",
		    itemPtr->id));
		    (int)itemPtr->id));
	    goto cleanup;
	}

	Tcl_AppendToObj(psObj, "gsave\n", -1);
	Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
	Tcl_AppendToObj(psObj, "grestore\n", -1);
	Tcl_ResetResult(interp);

	if (psInfo.chan != NULL) {
	    if (Tcl_WriteObj(psInfo.chan, psObj) == -1) {
	    if (Tcl_WriteObj(psInfo.chan, psObj) == TCL_IO_FAILURE) {
		goto channelWriteFailed;
	    }
	    Tcl_DecrRefCount(psObj);
	    psObj = Tcl_NewObj();
	}
    }

    /*
     * Output page-end information, such as commands to print the page and
     * document trailer stuff.
     */

    if (psInfo.prolog) {
	Tcl_AppendToObj(psObj,
		"restore showpage\n\n"
		"%%Trailer\n"
		"end\n"
		"%%EOF\n", -1);

	if (psInfo.chan != NULL) {
	    if (Tcl_WriteObj(psInfo.chan, psObj) == -1) {
	    if (Tcl_WriteObj(psInfo.chan, psObj) == TCL_IO_FAILURE) {
		goto channelWriteFailed;
	    }
	}
    }

    if (psInfo.chan == NULL) {
	Tcl_SetObjResult(interp, psObj);
1190
1191
1192
1193
1194
1195
1196


1197
1198
1199
1200
1201
1202
1203
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204







+
+







static void
TkImageGetColor(
    TkColormapData *cdata,	/* Colormap data */
    unsigned long pixel,	/* Pixel value to look up */
    double *red, double *green, double *blue)
				/* Color data to return */
{
    (void)cdata;

    *red   = (double) GetRValue(pixel) / 255.0;
    *green = (double) GetGValue(pixel) / 255.0;
    *blue  = (double) GetBValue(pixel) / 255.0;
}
#else /* ! (_WIN32 || MAC_OSX_TK) */
static void
TkImageGetColor(
1258
1259
1260
1261
1262
1263
1264

1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279

1280
1281
1282
1283
1284
1285
1286
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280

1281
1282
1283
1284
1285
1286
1287
1288







+














-
+







    int bytesPerLine = 0, maxWidth = 0;
    int level = psInfoPtr->colorLevel;
    Colormap cmap;
    int i, ncolors;
    Visual *visual;
    TkColormapData cdata;
    Tcl_Obj *psObj;
    (void)y;

    if (psInfoPtr->prepass) {
	return TCL_OK;
    }

    cmap = Tk_Colormap(tkwin);
    visual = Tk_Visual(tkwin);

    /*
     * Obtain information about the colormap, ie the mapping between pixel
     * values and RGB values. The code below should work for all Visual types.
     */

    ncolors = visual->map_entries;
    cdata.colors = ckalloc(sizeof(XColor) * ncolors);
    cdata.colors = (XColor *)ckalloc(sizeof(XColor) * ncolors);
    cdata.ncolors = ncolors;

    if (visual->c_class == DirectColor || visual->c_class == TrueColor) {
	cdata.separated = 1;
	cdata.red_mask = visual->red_mask;
	cdata.green_mask = visual->green_mask;
	cdata.blue_mask = visual->blue_mask;
1597
1598
1599
1600
1601
1602
1603
1604

1605
1606
1607
1608
1609
1610
1611
1599
1600
1601
1602
1603
1604
1605

1606
1607
1608
1609
1610
1611
1612
1613







-
+








    for (yy = 0, lineLen=0; yy < height; yy++) {
	switch (colorLevel) {
	case 0: {
	    /*
	     * Generate data for image in monochrome mode. No attempt at
	     * dithering is made--instead, just set a threshold. To handle
	     * transparecies we need to output two lines: one for the black
	     * transparencies we need to output two lines: one for the black
	     * pixels, one for the white ones.
	     */

	    unsigned char mask = 0x80;
	    unsigned char data = 0x00;

	    for (xx = 0; xx< width; xx ++) {
Changes to generic/tkCanvText.c.
1
2
3
4
5
6
7


8
9
10
11
12
13
14
1
2
3
4
5


6
7
8
9
10
11
12
13
14





-
-
+
+







/*
 * 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.
 */

#include "tkInt.h"
#include "tkCanvas.h"
28
29
30
31
32
33
34
35

36
37
38
39
40
41
42
28
29
30
31
32
33
34

35
36
37
38
39
40
41
42







-
+







				 * (and shared with) the generic canvas
				 * code. */
    /*
     * Fields that are set by widget commands other than "configure".
     */

    double x, y;		/* Positioning point for text. */
    int insertPos;		/* Character index of character just before
    TkSizeT insertPos;		/* Character index of character just before
				 * which the insertion cursor is displayed. */

    /*
     * Configuration settings that are updated by Tk_ConfigureWidget.
     */

    Tk_Anchor anchor;		/* Where to anchor text relative to (x,y). */
58
59
60
61
62
63
64
65
66


67
68
69
70
71
72
73
58
59
60
61
62
63
64


65
66
67
68
69
70
71
72
73







-
-
+
+







				 * at. */

    /*
     * Fields whose values are derived from the current values of the
     * configuration settings above.
     */

    int numChars;		/* Length of text in characters. */
    int numBytes;		/* Length of text in bytes. */
    TkSizeT numChars;		/* Length of text in characters. */
    TkSizeT numBytes;		/* Length of text in bytes. */
    Tk_TextLayout textLayout;	/* Cached text layout information. */
    int actualWidth;		/* Width of text as computed. Used to make
				 * selections of wrapped text display
				 * right. */
    double drawOrigin[2];	/* Where we start drawing from. */
    GC gc;			/* Graphics context for drawing text. */
    GC selTextGC;		/* Graphics context for selected text. */
83
84
85
86
87
88
89
90

91
92
93
94
95
96
97
98

99
100

101
102

103
104

105
106

107
108

109
110

111
112

113
114

115
116

117
118
119

120
121

122
123
124
125

126
127

128
129

130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151



152
153
154

155
156
157
158
159

160
161
162
163
164

165
166

167
168
169
170
171
172


173
174
175
176
177
178
179
83
84
85
86
87
88
89

90
91
92
93
94
95
96
97

98
99

100
101

102
103

104
105

106
107

108
109

110
111

112
113

114
115

116
117
118

119
120

121
122
123
124

125
126

127
128

129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148



149
150
151
152
153

154
155
156
157
158

159
160
161
162
163

164
165

166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181







-
+







-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+


-
+

-
+



-
+

-
+

-
+



















-
-
-
+
+
+


-
+




-
+




-
+

-
+






+
+







 * Information used for parsing configuration specs:
 */

static const Tk_CustomOption stateOption = {
    TkStateParseProc, TkStatePrintProc, INT2PTR(2)
};
static const Tk_CustomOption tagsOption = {
    Tk_CanvasTagsParseProc, Tk_CanvasTagsPrintProc, NULL
    TkCanvasTagsParseProc, TkCanvasTagsPrintProc, NULL
};
static const Tk_CustomOption offsetOption = {
    TkOffsetParseProc, TkOffsetPrintProc, INT2PTR(TK_OFFSET_RELATIVE)
};

static const Tk_ConfigSpec configSpecs[] = {
    {TK_CONFIG_COLOR, "-activefill", NULL, NULL,
	NULL, Tk_Offset(TextItem, activeColor), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(TextItem, activeColor), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_BITMAP, "-activestipple", NULL, NULL,
	NULL, Tk_Offset(TextItem, activeStipple), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(TextItem, activeStipple), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_ANCHOR, "-anchor", NULL, NULL,
	"center", Tk_Offset(TextItem, anchor), TK_CONFIG_DONT_SET_DEFAULT, NULL},
	"center", offsetof(TextItem, anchor), TK_CONFIG_DONT_SET_DEFAULT, NULL},
    {TK_CONFIG_DOUBLE, "-angle", NULL, NULL,
	"0.0", Tk_Offset(TextItem, angle), TK_CONFIG_DONT_SET_DEFAULT, NULL},
	"0.0", offsetof(TextItem, angle), TK_CONFIG_DONT_SET_DEFAULT, NULL},
    {TK_CONFIG_COLOR, "-disabledfill", NULL, NULL,
	NULL, Tk_Offset(TextItem, disabledColor), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(TextItem, disabledColor), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_BITMAP, "-disabledstipple", NULL, NULL,
	NULL, Tk_Offset(TextItem, disabledStipple), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(TextItem, disabledStipple), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_COLOR, "-fill", NULL, NULL,
	DEF_CANVITEM_OUTLINE, Tk_Offset(TextItem, color), TK_CONFIG_NULL_OK, NULL},
	DEF_CANVITEM_OUTLINE, offsetof(TextItem, color), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_FONT, "-font", NULL, NULL,
	DEF_CANVTEXT_FONT, Tk_Offset(TextItem, tkfont), 0, NULL},
	DEF_CANVTEXT_FONT, offsetof(TextItem, tkfont), 0, NULL},
    {TK_CONFIG_JUSTIFY, "-justify", NULL, NULL,
	"left", Tk_Offset(TextItem, justify), TK_CONFIG_DONT_SET_DEFAULT, NULL},
	"left", offsetof(TextItem, justify), TK_CONFIG_DONT_SET_DEFAULT, NULL},
    {TK_CONFIG_CUSTOM, "-offset", NULL, NULL,
	"0,0", Tk_Offset(TextItem, tsoffset),
	"0,0", offsetof(TextItem, tsoffset),
	TK_CONFIG_DONT_SET_DEFAULT, &offsetOption},
    {TK_CONFIG_CUSTOM, "-state", NULL, NULL,
	NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK, &stateOption},
	NULL, offsetof(Tk_Item, state), TK_CONFIG_NULL_OK, &stateOption},
    {TK_CONFIG_BITMAP, "-stipple", NULL, NULL,
	NULL, Tk_Offset(TextItem, stipple), TK_CONFIG_NULL_OK, NULL},
	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,
	"", Tk_Offset(TextItem, text), 0, NULL},
	"", offsetof(TextItem, text), 0, NULL},
    {TK_CONFIG_INT, "-underline", NULL, NULL,
	"-1", Tk_Offset(TextItem, underline), 0, NULL},
	"-1", offsetof(TextItem, underline), 0, NULL},
    {TK_CONFIG_PIXELS, "-width", NULL, NULL,
	"0", Tk_Offset(TextItem, width), TK_CONFIG_DONT_SET_DEFAULT, NULL},
	"0", offsetof(TextItem, width), TK_CONFIG_DONT_SET_DEFAULT, NULL},
    {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL}
};

/*
 * Prototypes for functions defined in this file:
 */

static void		ComputeTextBbox(Tk_Canvas canvas, TextItem *textPtr);
static int		ConfigureText(Tcl_Interp *interp,
			    Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
			    Tcl_Obj *const objv[], int flags);
static int		CreateText(Tcl_Interp *interp,
			    Tk_Canvas canvas, struct Tk_Item *itemPtr,
			    int argc, Tcl_Obj *const objv[]);
static void		DeleteText(Tk_Canvas canvas,
			    Tk_Item *itemPtr, Display *display);
static void		DisplayCanvText(Tk_Canvas canvas,
			    Tk_Item *itemPtr, Display *display, Drawable dst,
			    int x, int y, int width, int height);
static int		GetSelText(Tk_Canvas canvas,
			    Tk_Item *itemPtr, int offset, char *buffer,
			    int maxBytes);
static TkSizeT	GetSelText(Tk_Canvas canvas,
			    Tk_Item *itemPtr, TkSizeT offset, char *buffer,
			    TkSizeT maxBytes);
static int		GetTextIndex(Tcl_Interp *interp,
			    Tk_Canvas canvas, Tk_Item *itemPtr,
			    Tcl_Obj *obj, int *indexPtr);
			    Tcl_Obj *obj, TkSizeT *indexPtr);
static void		ScaleText(Tk_Canvas canvas,
			    Tk_Item *itemPtr, double originX, double originY,
			    double scaleX, double scaleY);
static void		SetTextCursor(Tk_Canvas canvas,
			    Tk_Item *itemPtr, int index);
			    Tk_Item *itemPtr, TkSizeT index);
static int		TextCoords(Tcl_Interp *interp,
			    Tk_Canvas canvas, Tk_Item *itemPtr,
			    int argc, Tcl_Obj *const objv[]);
static void		TextDeleteChars(Tk_Canvas canvas,
			    Tk_Item *itemPtr, int first, int last);
			    Tk_Item *itemPtr, TkSizeT first, TkSizeT last);
static void		TextInsert(Tk_Canvas canvas,
			    Tk_Item *itemPtr, int beforeThis, Tcl_Obj *obj);
			    Tk_Item *itemPtr, TkSizeT beforeThis, Tcl_Obj *obj);
static int		TextToArea(Tk_Canvas canvas,
			    Tk_Item *itemPtr, double *rectPtr);
static double		TextToPoint(Tk_Canvas canvas,
			    Tk_Item *itemPtr, double *pointPtr);
static int		TextToPostscript(Tcl_Interp *interp,
			    Tk_Canvas canvas, Tk_Item *itemPtr, int prepass);
static void		RotateText(Tk_Canvas canvas, Tk_Item *itemPtr,
			    double originX, double originY, double angleRad);
static void		TranslateText(Tk_Canvas canvas,
			    Tk_Item *itemPtr, double deltaX, double deltaY);

/*
 * The structures below defines the rectangle and oval item types by means of
 * functions that can be invoked by generic item code.
 */
195
196
197
198
199
200
201

202

203
204
205
206
207
208
209
197
198
199
200
201
202
203
204

205
206
207
208
209
210
211
212







+
-
+







    TranslateText,		/* translateProc */
    GetTextIndex,		/* indexProc */
    SetTextCursor,		/* icursorProc */
    GetSelText,			/* selectionProc */
    TextInsert,			/* insertProc */
    TextDeleteChars,		/* dTextProc */
    NULL,			/* nextPtr */
    RotateText,			/* rotateProc */
    NULL, 0, NULL, NULL
    0, NULL, NULL
};

#define ROUND(d) ((int) floor((d) + 0.5))

/*
 *--------------------------------------------------------------
 *
503
504
505
506
507
508
509
510

511
512
513

514
515
516
517

518
519
520
521
522

523
524
525
526
527
528
529
506
507
508
509
510
511
512

513
514
515

516
517
518
519

520
521
522
523
524

525
526
527
528
529
530
531
532







-
+


-
+



-
+




-
+







     * keep them inside the item.
     */

    textPtr->numBytes = strlen(textPtr->text);
    textPtr->numChars = Tcl_NumUtfChars(textPtr->text, textPtr->numBytes);
    if (textInfoPtr->selItemPtr == itemPtr) {

	if (textInfoPtr->selectFirst >= textPtr->numChars) {
	if (textInfoPtr->selectFirst + 1 >= textPtr->numChars + 1) {
	    textInfoPtr->selItemPtr = NULL;
	} else {
	    if (textInfoPtr->selectLast >= textPtr->numChars) {
	    if (textInfoPtr->selectLast + 1 >= textPtr->numChars + 1) {
		textInfoPtr->selectLast = textPtr->numChars - 1;
	    }
	    if ((textInfoPtr->anchorItemPtr == itemPtr)
		    && (textInfoPtr->selectAnchor >= textPtr->numChars)) {
		    && (textInfoPtr->selectAnchor + 1 >= textPtr->numChars + 1)) {
		textInfoPtr->selectAnchor = textPtr->numChars - 1;
	    }
	}
    }
    if (textPtr->insertPos >= textPtr->numChars) {
    if (textPtr->insertPos + 1 >= textPtr->numChars + 1) {
	textPtr->insertPos = textPtr->numChars;
    }

    /*
     * Restrict so that 0.0 <= angle < 360.0, and then recompute the cached
     * sine and cosine of the angle. Note that fmod() can produce negative
     * results, and we try to avoid negative zero as well.
563
564
565
566
567
568
569

570
571
572
573
574
575
576
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580







+







static void
DeleteText(
    Tk_Canvas canvas,		/* Info about overall canvas widget. */
    Tk_Item *itemPtr,		/* Item that is being deleted. */
    Display *display)		/* Display containing window for canvas. */
{
    TextItem *textPtr = (TextItem *) itemPtr;
    (void)canvas;

    if (textPtr->color != NULL) {
	Tk_FreeColor(textPtr->color);
    }
    if (textPtr->activeColor != NULL) {
	Tk_FreeColor(textPtr->activeColor);
    }
794
795
796
797
798
799
800
801

802
803
804
805
806
807
808
798
799
800
801
802
803
804

805
806
807
808
809
810
811
812







-
+







    Drawable drawable,		/* Pixmap or window in which to draw item. */
    int x, int y, int width, int height)
				/* Describes region of canvas that must be
				 * redisplayed (not used). */
{
    TextItem *textPtr;
    Tk_CanvasTextInfo *textInfoPtr;
    int selFirstChar, selLastChar;
    TkSizeT selFirstChar, selLastChar;
    short drawableX, drawableY;
    Pixmap stipple;
    Tk_State state = itemPtr->state;

    textPtr = (TextItem *) itemPtr;
    textInfoPtr = textPtr->textInfoPtr;

830
831
832
833
834
835
836
837
838


839
840
841
842
843
844
845

846
847
848

849
850
851
852
853
854
855
834
835
836
837
838
839
840


841
842
843
844
845
846
847
848

849
850
851

852
853
854
855
856
857
858
859







-
-
+
+






-
+


-
+







     * read-only.
     */

    if (stipple != None) {
	Tk_CanvasSetOffset(canvas, textPtr->gc, &textPtr->tsoffset);
    }

    selFirstChar = -1;
    selLastChar = 0;		/* lint. */
    selFirstChar = TCL_INDEX_NONE;
    selLastChar = 0;
    Tk_CanvasDrawableCoords(canvas, textPtr->drawOrigin[0],
	    textPtr->drawOrigin[1], &drawableX, &drawableY);

    if (textInfoPtr->selItemPtr == itemPtr) {
	selFirstChar = textInfoPtr->selectFirst;
	selLastChar = textInfoPtr->selectLast;
	if (selLastChar > textPtr->numChars) {
	if (selLastChar + 1 > textPtr->numChars + 1 ) {
	    selLastChar = textPtr->numChars - 1;
	}
	if ((selFirstChar >= 0) && (selFirstChar <= selLastChar)) {
	if (((int)selFirstChar >= 0) && (selFirstChar + 1 <= selLastChar + 1 )) {
	    int xFirst, yFirst, hFirst;
	    int xLast, yLast, wLast;

	    /*
	     * Draw a special background under the selection.
	     */

952
953
954
955
956
957
958
959
960
961
962






963
964
965

966
967
968




969
970
971
972

973
974
975
976
977
978
979
956
957
958
959
960
961
962




963
964
965
966
967
968
969
970
971
972



973
974
975
976
977
978
979

980
981
982
983
984
985
986
987







-
-
-
-
+
+
+
+
+
+



+
-
-
-
+
+
+
+



-
+







     * there is selected text and the foregrounds differ, draw the regular
     * text up to the selection, draw the selection, then draw the rest of the
     * regular text. Drawing the regular text and then the selected text over
     * it would causes problems with anti-aliased text because the two
     * anti-aliasing colors would blend together.
     */

    if ((selFirstChar >= 0) && (textPtr->selTextGC != textPtr->gc)) {
	TkDrawAngledTextLayout(display, drawable, textPtr->gc,
		textPtr->textLayout, drawableX, drawableY, textPtr->angle,
		0, selFirstChar);
    if ((selFirstChar != TCL_INDEX_NONE) && (textPtr->selTextGC != textPtr->gc)) {
	if (0 < selFirstChar) {
	    TkDrawAngledTextLayout(display, drawable, textPtr->gc,
		    textPtr->textLayout, drawableX, drawableY, textPtr->angle,
		    0, selFirstChar);
	}
	TkDrawAngledTextLayout(display, drawable, textPtr->selTextGC,
		textPtr->textLayout, drawableX, drawableY, textPtr->angle,
		selFirstChar, selLastChar + 1);
	if (selLastChar + 1 < textPtr->numChars) {
	TkDrawAngledTextLayout(display, drawable, textPtr->gc,
		textPtr->textLayout, drawableX, drawableY, textPtr->angle,
		selLastChar + 1, -1);
	    TkDrawAngledTextLayout(display, drawable, textPtr->gc,
		    textPtr->textLayout, drawableX, drawableY, textPtr->angle,
		    selLastChar + 1, textPtr->numChars);
	}
    } else {
	TkDrawAngledTextLayout(display, drawable, textPtr->gc,
		textPtr->textLayout, drawableX, drawableY, textPtr->angle,
		0, -1);
		0, textPtr->numChars);
    }
    TkUnderlineAngledTextLayout(display, drawable, textPtr->gc,
	    textPtr->textLayout, drawableX, drawableY, textPtr->angle,
	    textPtr->underline);

    if (stipple != None) {
	XSetTSOrigin(display, textPtr->gc, 0, 0);
997
998
999
1000
1001
1002
1003
1004

1005
1006
1007
1008
1009


1010
1011
1012
1013
1014

1015
1016
1017
1018

1019
1020
1021

1022
1023
1024
1025
1026
1027
1028
1029
1030
1031


1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047

1048
1049
1050

1051
1052
1053
1054

1055
1056
1057
1058

1059
1060
1061
1062
1063
1064
1065
1005
1006
1007
1008
1009
1010
1011

1012
1013
1014
1015
1016

1017
1018
1019
1020
1021
1022

1023
1024
1025
1026

1027
1028
1029

1030
1031
1032
1033
1034
1035
1036
1037
1038


1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055

1056
1057
1058

1059
1060
1061
1062

1063
1064
1065
1066

1067
1068
1069
1070
1071
1072
1073
1074







-
+




-
+
+




-
+



-
+


-
+








-
-
+
+















-
+


-
+



-
+



-
+







 *----------------------------------------------------------------------
 */

static void
TextInsert(
    Tk_Canvas canvas,		/* Canvas containing text item. */
    Tk_Item *itemPtr,		/* Text item to be modified. */
    int index,			/* Character index before which string is to
    TkSizeT index,			/* Character index before which string is to
				 * be inserted. */
    Tcl_Obj *obj)		/* New characters to be inserted. */
{
    TextItem *textPtr = (TextItem *) itemPtr;
    int byteIndex, byteCount, charsAdded;
    int byteIndex, charsAdded;
    TkSizeT byteCount;
    char *newStr, *text;
    const char *string;
    Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr;

    string = Tcl_GetStringFromObj(obj, &byteCount);
    string = TkGetStringFromObj(obj, &byteCount);

    text = textPtr->text;

    if (index < 0) {
    if (index == TCL_INDEX_NONE) {
	index = 0;
    }
    if (index > textPtr->numChars) {
    if (index + 1 > textPtr->numChars + 1) {
	index = textPtr->numChars;
    }
    byteIndex = Tcl_UtfAtIndex(text, index) - text;
    byteCount = strlen(string);
    if (byteCount == 0) {
	return;
    }

    newStr = ckalloc(textPtr->numBytes + byteCount + 1);
    memcpy(newStr, text, (size_t) byteIndex);
    newStr = (char *)ckalloc(textPtr->numBytes + byteCount + 1);
    memcpy(newStr, text, byteIndex);
    strcpy(newStr + byteIndex, string);
    strcpy(newStr + byteIndex + byteCount, text + byteIndex);

    ckfree(text);
    textPtr->text = newStr;
    charsAdded = Tcl_NumUtfChars(string, byteCount);
    textPtr->numChars += charsAdded;
    textPtr->numBytes += byteCount;

    /*
     * Inserting characters invalidates indices such as those for the
     * selection and cursor. Update the indices appropriately.
     */

    if (textInfoPtr->selItemPtr == itemPtr) {
	if (textInfoPtr->selectFirst >= index) {
	if (textInfoPtr->selectFirst + 1 >= index + 1) {
	    textInfoPtr->selectFirst += charsAdded;
	}
	if (textInfoPtr->selectLast >= index) {
	if (textInfoPtr->selectLast + 1 >= index + 1) {
	    textInfoPtr->selectLast += charsAdded;
	}
	if ((textInfoPtr->anchorItemPtr == itemPtr)
		&& (textInfoPtr->selectAnchor >= index)) {
		&& (textInfoPtr->selectAnchor + 1 >= index + 1)) {
	    textInfoPtr->selectAnchor += charsAdded;
	}
    }
    if (textPtr->insertPos >= index) {
    if (textPtr->insertPos + 1 >= index + 1) {
	textPtr->insertPos += charsAdded;
    }
    ComputeTextBbox(canvas, textPtr);
}

/*
 *--------------------------------------------------------------
1078
1079
1080
1081
1082
1083
1084
1085

1086
1087

1088
1089
1090
1091
1092
1093
1094
1095
1096

1097
1098
1099

1100
1101
1102

1103
1104
1105
1106
1107
1108
1109
1110
1111
1112


1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126

1127
1128

1129
1130
1131
1132

1133
1134

1135
1136
1137
1138

1139
1140
1141
1142

1143
1144

1145
1146
1147
1148
1149

1150
1151

1152
1153
1154
1155
1156
1157
1158
1087
1088
1089
1090
1091
1092
1093

1094
1095

1096
1097
1098
1099
1100
1101
1102
1103
1104

1105
1106
1107

1108
1109
1110

1111
1112
1113
1114
1115
1116
1117
1118
1119


1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134

1135
1136

1137
1138
1139
1140

1141
1142

1143
1144
1145
1146

1147
1148
1149
1150

1151
1152

1153
1154
1155
1156
1157

1158
1159

1160
1161
1162
1163
1164
1165
1166
1167







-
+

-
+








-
+


-
+


-
+








-
-
+
+













-
+

-
+



-
+

-
+



-
+



-
+

-
+




-
+

-
+







 *--------------------------------------------------------------
 */

static void
TextDeleteChars(
    Tk_Canvas canvas,		/* Canvas containing itemPtr. */
    Tk_Item *itemPtr,		/* Item in which to delete characters. */
    int first,			/* Character index of first character to
    TkSizeT first,			/* Character index of first character to
				 * delete. */
    int last)			/* Character index of last character to delete
    TkSizeT last)			/* Character index of last character to delete
				 * (inclusive). */
{
    TextItem *textPtr = (TextItem *) itemPtr;
    int byteIndex, byteCount, charsRemoved;
    char *newStr, *text;
    Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr;

    text = textPtr->text;
    if (first < 0) {
    if ((int)first < 0) {
	first = 0;
    }
    if (last >= textPtr->numChars) {
    if (last + 1 >= textPtr->numChars + 1) {
	last = textPtr->numChars - 1;
    }
    if (first > last) {
    if (first + 1 > last + 1) {
	return;
    }
    charsRemoved = last + 1 - first;

    byteIndex = Tcl_UtfAtIndex(text, first) - text;
    byteCount = Tcl_UtfAtIndex(text + byteIndex, charsRemoved)
	- (text + byteIndex);

    newStr = ckalloc(textPtr->numBytes + 1 - byteCount);
    memcpy(newStr, text, (size_t) byteIndex);
    newStr = (char *)ckalloc(textPtr->numBytes + 1 - byteCount);
    memcpy(newStr, text, byteIndex);
    strcpy(newStr + byteIndex, text + byteIndex + byteCount);

    ckfree(text);
    textPtr->text = newStr;
    textPtr->numChars -= charsRemoved;
    textPtr->numBytes -= byteCount;

    /*
     * Update indexes for the selection and cursor to reflect the renumbering
     * of the remaining characters.
     */

    if (textInfoPtr->selItemPtr == itemPtr) {
	if (textInfoPtr->selectFirst > first) {
	if (textInfoPtr->selectFirst + 1 > first + 1) {
	    textInfoPtr->selectFirst -= charsRemoved;
	    if (textInfoPtr->selectFirst < first) {
	    if ((int)textInfoPtr->selectFirst + 1 < (int)first + 1) {
		textInfoPtr->selectFirst = first;
	    }
	}
	if (textInfoPtr->selectLast >= first) {
	if (textInfoPtr->selectLast + 1 >= first + 1) {
	    textInfoPtr->selectLast -= charsRemoved;
	    if (textInfoPtr->selectLast < first - 1) {
	    if (textInfoPtr->selectLast + 1 < first) {
		textInfoPtr->selectLast = first - 1;
	    }
	}
	if (textInfoPtr->selectFirst > textInfoPtr->selectLast) {
	if ((int)textInfoPtr->selectFirst + 1 > (int)textInfoPtr->selectLast + 1) {
	    textInfoPtr->selItemPtr = NULL;
	}
	if ((textInfoPtr->anchorItemPtr == itemPtr)
		&& (textInfoPtr->selectAnchor > first)) {
		&& (textInfoPtr->selectAnchor + 1 > first + 1)) {
	    textInfoPtr->selectAnchor -= charsRemoved;
	    if (textInfoPtr->selectAnchor < first) {
	    if (textInfoPtr->selectAnchor + 1 < first + 1) {
		textInfoPtr->selectAnchor = first;
	    }
	}
    }
    if (textPtr->insertPos > first) {
    if (textPtr->insertPos + 1 > first + 1) {
	textPtr->insertPos -= charsRemoved;
	if (textPtr->insertPos < first) {
	if ((int)textPtr->insertPos + 1 < (int)first + 1) {
	    textPtr->insertPos = first;
	}
    }
    ComputeTextBbox(canvas, textPtr);
    return;
}

1245
1246
1247
1248
1249
1250
1251

































1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307

1308
1309
1310
1311
1312
1313
1314







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+














-







	    (int) (rectPtr[3] - rectPtr[1] + 0.5),
	    textPtr->angle);
}

/*
 *--------------------------------------------------------------
 *
 * RotateText --
 *
 *	This function is called to rotate a text item by a given amount about a
 *	point. Note that this does *not* rotate the text of the item.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The position of the text anchor is rotated by angleRad about (originX,
 *	originY), and the bounding box is updated in the generic part of the
 *	item structure.
 *
 *--------------------------------------------------------------
 */

static void
RotateText(
    Tk_Canvas canvas,		/* Canvas containing item. */
    Tk_Item *itemPtr,		/* Item that is being rotated. */
    double originX, double originY,
    double angleRad)		/* Amount by which item is to be rotated. */
{
    TextItem *textPtr = (TextItem *) itemPtr;

    TkRotatePoint(originX, originY, sin(angleRad), cos(angleRad),
	    &textPtr->x, &textPtr->y);
    ComputeTextBbox(canvas, textPtr);
}

/*
 *--------------------------------------------------------------
 *
 * ScaleText --
 *
 *	This function is invoked to rescale a text item.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Scales the position of the text, but not the size of the font for the
 *	text.
 *
 *--------------------------------------------------------------
 */

	/* ARGSUSED */
static void
ScaleText(
    Tk_Canvas canvas,		/* Canvas containing rectangle. */
    Tk_Item *itemPtr,		/* Rectangle to be scaled. */
    double originX, double originY,
				/* Origin about which to scale rect. */
    double scaleX,		/* Amount to scale in X direction. */
1330
1331
1332
1333
1334
1335
1336
1337

1338
1339
1340
1341
1342

1343
1344
1345
1346

1347
1348
1349

1350


1351
1352




1353
1354
1355
1356









1357
1358
1359

1360
1361
1362
1363
1364
1365
1366
1367
1368

1369
1370
1371
1372
1373
1374
1375
1376
1377
1378

1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397

1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1371
1372
1373
1374
1375
1376
1377

1378
1379
1380
1381
1382

1383
1384
1385
1386

1387
1388
1389

1390
1391
1392
1393


1394
1395
1396
1397




1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408

1409
1410
1411
1412
1413
1414
1415
1416
1417

1418
1419
1420
1421
1422
1423
1424
1425
1426
1427

1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446

1447






1448
1449
1450
1451
1452
1453
1454







-
+




-
+



-
+


-
+

+
+
-
-
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+


-
+








-
+









-
+


















-
+
-
-
-
-
-
-







 *
 *--------------------------------------------------------------
 */

static int
GetTextIndex(
    Tcl_Interp *interp,		/* Used for error reporting. */
    Tk_Canvas canvas,		/* Canvas containing item. */
    TCL_UNUSED(Tk_Canvas),		/* Canvas containing item. */
    Tk_Item *itemPtr,		/* Item for which the index is being
				 * specified. */
    Tcl_Obj *obj,		/* Specification of a particular character in
				 * itemPtr's text. */
    int *indexPtr)		/* Where to store converted character
    TkSizeT *indexPtr)		/* Where to store converted character
				 * index. */
{
    TextItem *textPtr = (TextItem *) itemPtr;
    int length;
    TkSizeT length, idx;
    int c;
    Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr;
    const char *string = Tcl_GetStringFromObj(obj, &length);
    const char *string;

    if (TCL_OK == TkGetIntForIndex(obj, textPtr->numChars - 1, 1, &idx)) {
	if (idx == TCL_INDEX_NONE) {
    c = string[0];

	    idx = 0;
	} else if (idx > textPtr->numChars) {
	    idx = textPtr->numChars;
	}
    if ((c == 'e') && (strncmp(string, "end", (unsigned) length) == 0)) {
	*indexPtr = textPtr->numChars;
    } else if ((c == 'i')
	    && (strncmp(string, "insert", (unsigned) length) == 0)) {
	*indexPtr = idx;
	return TCL_OK;
    }

    string = TkGetStringFromObj(obj, &length);
    c = string[0];

    if ((c == 'i')
	    && (strncmp(string, "insert", length) == 0)) {
	*indexPtr = textPtr->insertPos;
    } else if ((c == 's') && (length >= 5)
	    && (strncmp(string, "sel.first", (unsigned) length) == 0)) {
	    && (strncmp(string, "sel.first", length) == 0)) {
	if (textInfoPtr->selItemPtr != itemPtr) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "selection isn't in item", -1));
	    Tcl_SetErrorCode(interp, "TK", "CANVAS", "UNSELECTED", NULL);
	    return TCL_ERROR;
	}
	*indexPtr = textInfoPtr->selectFirst;
    } else if ((c == 's') && (length >= 5)
	    && (strncmp(string, "sel.last", (unsigned) length) == 0)) {
	    && (strncmp(string, "sel.last", length) == 0)) {
	if (textInfoPtr->selItemPtr != itemPtr) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "selection isn't in item", -1));
	    Tcl_SetErrorCode(interp, "TK", "CANVAS", "UNSELECTED", NULL);
	    return TCL_ERROR;
	}
	*indexPtr = textInfoPtr->selectLast;
    } else if (c == '@') {
	int x, y;
	double tmp, c = textPtr->cosine, s = textPtr->sine;
	double tmp, cs = textPtr->cosine, s = textPtr->sine;
	char *end;
	const char *p;

	p = string+1;
	tmp = strtod(p, &end);
	if ((end == p) || (*end != ',')) {
	    goto badIndex;
	}
	x = (int) ((tmp < 0) ? tmp - 0.5 : tmp + 0.5);
	p = end+1;
	tmp = strtod(p, &end);
	if ((end == p) || (*end != 0)) {
	    goto badIndex;
	}
	y = (int) ((tmp < 0) ? tmp - 0.5 : tmp + 0.5);
	x -= (int) textPtr->drawOrigin[0];
	y -= (int) textPtr->drawOrigin[1];
	*indexPtr = Tk_PointToChar(textPtr->textLayout,
		(int) (x*c - y*s), (int) (y*c + x*s));
		(int) (x*cs - y*s), (int) (y*cs + x*s));
    } else if (Tcl_GetIntFromObj(NULL, obj, indexPtr) == TCL_OK) {
	if (*indexPtr < 0) {
	    *indexPtr = 0;
	} else if (*indexPtr > textPtr->numChars) {
	    *indexPtr = textPtr->numChars;
	}
    } else {
	/*
	 * Some of the paths here leave messages in the interp's result, so we
	 * have to clear it out before storing our own message.
	 */

    badIndex:
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437

1438
1439
1440

1441
1442
1443
1444
1445

1446
1447
1448
1449
1450
1451
1452
1471
1472
1473
1474
1475
1476
1477

1478
1479

1480
1481
1482

1483
1484
1485
1486
1487

1488
1489
1490
1491
1492
1493
1494
1495







-


-
+


-
+




-
+







 *
 * Side effects:
 *	The cursor position will change.
 *
 *--------------------------------------------------------------
 */

	/* ARGSUSED */
static void
SetTextCursor(
    Tk_Canvas canvas,		/* Record describing canvas widget. */
    TCL_UNUSED(Tk_Canvas),		/* Record describing canvas widget. */
    Tk_Item *itemPtr,		/* Text item in which cursor position is to be
				 * set. */
    int index)			/* Character index of character just before
    TkSizeT index)			/* Character index of character just before
				 * which cursor is to be positioned. */
{
    TextItem *textPtr = (TextItem *) itemPtr;

    if (index < 0) {
    if (index == TCL_INDEX_NONE) {
	textPtr->insertPos = 0;
    } else if (index > textPtr->numChars) {
	textPtr->insertPos = textPtr->numChars;
    } else {
	textPtr->insertPos = index;
    }
}
1467
1468
1469
1470
1471
1472
1473
1474

1475
1476

1477
1478

1479
1480
1481

1482
1483
1484
1485
1486

1487
1488
1489
1490
1491
1492


1493
1494
1495
1496
1497
1498



1499
1500
1501
1502
1503
1504
1505
1506

1507
1508
1509
1510
1511
1512
1513
1510
1511
1512
1513
1514
1515
1516

1517
1518

1519
1520

1521
1522
1523

1524
1525
1526
1527
1528

1529
1530
1531
1532
1533


1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548




1549
1550
1551
1552
1553
1554
1555
1556







-
+

-
+

-
+


-
+




-
+




-
-
+
+






+
+
+




-
-
-
-
+







 *
 * Side effects:
 *	None.
 *
 *--------------------------------------------------------------
 */

static int
static TkSizeT
GetSelText(
    Tk_Canvas canvas,		/* Canvas containing selection. */
    TCL_UNUSED(Tk_Canvas),		/* Canvas containing selection. */
    Tk_Item *itemPtr,		/* Text item containing selection. */
    int offset,			/* Byte offset within selection of first
    TkSizeT offset,			/* Byte offset within selection of first
				 * character to be returned. */
    char *buffer,		/* Location in which to place selection. */
    int maxBytes)		/* Maximum number of bytes to place at buffer,
    TkSizeT maxBytes)		/* Maximum number of bytes to place at buffer,
				 * not including terminating NULL
				 * character. */
{
    TextItem *textPtr = (TextItem *) itemPtr;
    int byteCount;
    TkSizeT byteCount;
    char *text;
    const char *selStart, *selEnd;
    Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr;

    if ((textInfoPtr->selectFirst < 0) ||
	    (textInfoPtr->selectFirst > textInfoPtr->selectLast)) {
    if (((int)textInfoPtr->selectFirst < 0) ||
	    (textInfoPtr->selectFirst + 1 > textInfoPtr->selectLast + 1)) {
	return 0;
    }
    text = textPtr->text;
    selStart = Tcl_UtfAtIndex(text, textInfoPtr->selectFirst);
    selEnd = Tcl_UtfAtIndex(selStart,
	    textInfoPtr->selectLast + 1 - textInfoPtr->selectFirst);
    if (selEnd  <= selStart + offset) {
	return 0;
    }
    byteCount = selEnd - selStart - offset;
    if (byteCount > maxBytes) {
	byteCount = maxBytes;
    }
    if (byteCount <= 0) {
	return 0;
    }
    memcpy(buffer, selStart + offset, (size_t) byteCount);
    memcpy(buffer, selStart + offset, byteCount);
    buffer[byteCount] = '\0';
    return byteCount;
}

/*
 *--------------------------------------------------------------
 *
1588
1589
1590
1591
1592
1593
1594
1595

1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607

1608
1609
1610
1611
1612
1613
1614
1631
1632
1633
1634
1635
1636
1637

1638


1639
1640
1641
1642
1643
1644
1645
1646
1647

1648
1649
1650
1651
1652
1653
1654
1655







-
+
-
-









-
+







    Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));

    if (prepass != 0) {
	goto done;
    }

    Tcl_ResetResult(interp);
    if (Tk_CanvasPsColor(interp, canvas, color) != TCL_OK) {
    Tk_CanvasPsColor(interp, canvas, color);
	goto error;
    }
    Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));

    if (stipple != None) {
	Tcl_ResetResult(interp);
	Tk_CanvasPsStipple(interp, canvas, stipple);
	Tcl_AppendPrintfToObj(psObj, "/StippleText {\n    %s} bind def\n",
		Tcl_GetString(Tcl_GetObjResult(interp)));
    }

    x = 0;  y = 0;  justify = NULL;	/* lint. */
    x = 0;  y = 0;  justify = NULL;
    switch (textPtr->anchor) {
    case TK_ANCHOR_NW:	   x = 0; y = 0; break;
    case TK_ANCHOR_N:	   x = 1; y = 0; break;
    case TK_ANCHOR_NE:	   x = 2; y = 0; break;
    case TK_ANCHOR_E:	   x = 2; y = 1; break;
    case TK_ANCHOR_SE:	   x = 2; y = 2; break;
    case TK_ANCHOR_S:	   x = 1; y = 2; break;
Changes to generic/tkCanvUtil.c.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







/*
 * 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.
 */

#include "tkInt.h"
#include "tkCanvas.h"
24
25
26
27
28
29
30
31

32
33
34
35
36
37

38

39
40
41
42
43
44
45
24
25
26
27
28
29
30

31
32
33
34
35
36

37
38
39
40
41
42
43
44
45
46







-
+





-
+

+







				 * option. */
} SmoothAssocData;

const Tk_SmoothMethod tkBezierSmoothMethod = {
    "true",
    TkMakeBezierCurve,
    (void (*) (Tcl_Interp *interp, Tk_Canvas canvas, double *coordPtr,
	    int numPoints, int numSteps)) TkMakeBezierPostscript,
	    int numPoints, int numSteps))(void *)TkMakeBezierPostscript,
};
static const Tk_SmoothMethod tkRawSmoothMethod = {
    "raw",
    TkMakeRawCurve,
    (void (*) (Tcl_Interp *interp, Tk_Canvas canvas, double *coordPtr,
	    int numPoints, int numSteps)) TkMakeRawCurvePostscript,
	    int numPoints, int numSteps))(void *)TkMakeRawCurvePostscript,
};


/*
 * Function forward-declarations.
 */

static void		SmoothMethodCleanupProc(ClientData clientData,
			    Tcl_Interp *interp);
226
227
228
229
230
231
232
233

234
235
236
237
238


239
240
241
242
243
244
245
227
228
229
230
231
232
233

234
235
236
237
238
239
240
241
242
243
244
245
246
247
248







-
+





+
+







 *	None.
 *
 *--------------------------------------------------------------
 */

int
Tk_CanvasGetCoord(
    Tcl_Interp *interp,		/* Interpreter for error reporting. */
    Tcl_Interp *dummy,		/* Interpreter for error reporting. */
    Tk_Canvas canvas,		/* Canvas to which coordinate applies. */
    const char *string,		/* Describes coordinate (any screen coordinate
				 * form may be used here). */
    double *doublePtr)		/* Place to store converted coordinate. */
{
    (void)dummy;

    if (Tk_GetScreenMM(Canvas(canvas)->interp, Canvas(canvas)->tkwin, string,
	    doublePtr) != TCL_OK) {
	return TCL_ERROR;
    }
    *doublePtr *= Canvas(canvas)->pixelsPerMM;
    return TCL_OK;
}
262
263
264
265
266
267
268
269

270
271
272
273
274


275
276
277
278
279
280
281
265
266
267
268
269
270
271

272
273
274
275
276
277
278
279
280
281
282
283
284
285
286







-
+





+
+







 *	None.
 *
 *--------------------------------------------------------------
 */

int
Tk_CanvasGetCoordFromObj(
    Tcl_Interp *interp,		/* Interpreter for error reporting. */
    Tcl_Interp *dummy,		/* Interpreter for error reporting. */
    Tk_Canvas canvas,		/* Canvas to which coordinate applies. */
    Tcl_Obj *obj,		/* Describes coordinate (any screen coordinate
				 * form may be used here). */
    double *doublePtr)		/* Place to store converted coordinate. */
{
    (void)dummy;

    return Tk_GetDoublePixelsFromObj(Canvas(canvas)->interp, Canvas(canvas)->tkwin, obj, doublePtr);
}

/*
 *----------------------------------------------------------------------
 *
 * Tk_CanvasSetStippleOrigin --
327
328
329
330
331
332
333
334

335
336
337
338
339
340
341
332
333
334
335
336
337
338

339
340
341
342
343
344
345
346







-
+







Tk_CanvasSetOffset(
    Tk_Canvas canvas,		/* Token for a canvas. */
    GC gc,			/* Graphics context that is about to be used
				 * to draw a stippled pattern as part of
				 * redisplaying the canvas. */
    Tk_TSOffset *offset)	/* Offset (may be NULL pointer)*/
{
    register TkCanvas *canvasPtr = Canvas(canvas);
    TkCanvas *canvasPtr = Canvas(canvas);
    int flags = 0;
    int x = - canvasPtr->drawableXOrigin;
    int y = - canvasPtr->drawableYOrigin;

    if (offset != NULL) {
	flags = offset->flags;
	x += offset->xoffset;
393
394
395
396
397
398
399
400
401


402
403
404
405
406

407
408

409
410
411



412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427



428
429
430
431
432
433
434
398
399
400
401
402
403
404


405
406
407
408
409
410

411
412

413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432



433
434
435
436
437
438
439
440
441
442







-
-
+
+




-
+

-
+



+
+
+













-
-
-
+
+
+







 *	The tags for a given item get replaced by those indicated in the value
 *	argument.
 *
 *--------------------------------------------------------------
 */

int
Tk_CanvasTagsParseProc(
    ClientData clientData,	/* Not used.*/
TkCanvasTagsParseProc(
    ClientData dummy,	/* Not used.*/
    Tcl_Interp *interp,		/* Used for reporting errors. */
    Tk_Window tkwin,		/* Window containing canvas widget. */
    const char *value,		/* Value of option (list of tag names). */
    char *widgRec,		/* Pointer to record for item. */
    int offset)			/* Offset into item (ignored). */
    TkSizeT offset)			/* Offset into item (ignored). */
{
    register Tk_Item *itemPtr = (Tk_Item *) widgRec;
    Tk_Item *itemPtr = (Tk_Item *) widgRec;
    int argc, i;
    const char **argv;
    Tk_Uid *newPtr;
    (void)dummy;
    (void)tkwin;
    (void)offset;

    /*
     * Break the value up into the individual tag names.
     */

    if (Tcl_SplitList(interp, value, &argc, &argv) != TCL_OK) {
	return TCL_ERROR;
    }

    /*
     * Make sure that there's enough space in the item to hold the tag names.
     */

    if (itemPtr->tagSpace < argc) {
	newPtr = ckalloc(argc * sizeof(Tk_Uid));
	for (i = itemPtr->numTags-1; i >= 0; i--) {
    if ((int)itemPtr->tagSpace < argc) {
	newPtr = (Tk_Uid *)ckalloc(argc * sizeof(Tk_Uid));
	for (i = (int)itemPtr->numTags - 1; i >= 0; i--) {
	    newPtr[i] = itemPtr->tagPtr[i];
	}
	if (itemPtr->tagPtr != itemPtr->staticTagSpace) {
	    ckfree(itemPtr->tagPtr);
	}
	itemPtr->tagPtr = newPtr;
	itemPtr->tagSpace = argc;
460
461
462
463
464
465
466
467
468


469
470
471

472
473
474
475
476




477
478
479
480
481
482
483
468
469
470
471
472
473
474


475
476
477
478

479
480
481
482
483

484
485
486
487
488
489
490
491
492
493
494







-
-
+
+


-
+




-
+
+
+
+







 * Side effects:
 *	None.
 *
 *--------------------------------------------------------------
 */

const char *
Tk_CanvasTagsPrintProc(
    ClientData clientData,	/* Ignored. */
TkCanvasTagsPrintProc(
    ClientData dummy,	/* Ignored. */
    Tk_Window tkwin,		/* Window containing canvas widget. */
    char *widgRec,		/* Pointer to record for item. */
    int offset,			/* Ignored. */
    TkSizeT offset,			/* Ignored. */
    Tcl_FreeProc **freeProcPtr)	/* Pointer to variable to fill in with
				 * information about how to reclaim storage
				 * for return string. */
{
    register Tk_Item *itemPtr = (Tk_Item *) widgRec;
    Tk_Item *itemPtr = (Tk_Item *) widgRec;
    (void)dummy;
    (void)tkwin;
    (void)offset;

    if (itemPtr->numTags == 0) {
	*freeProcPtr = NULL;
	return "";
    }
    if (itemPtr->numTags == 1) {
	*freeProcPtr = NULL;
503
504
505
506
507
508
509
510

511
512
513
514
515

516



517
518
519
520
521
522
523
514
515
516
517
518
519
520

521
522
523
524
525

526
527
528
529
530
531
532
533
534
535
536
537







-
+




-
+

+
+
+







 *	indicated in the value argument.
 *
 *--------------------------------------------------------------
 */

int
TkCanvasDashParseProc(
    ClientData clientData,	/* Not used.*/
    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. */
    int offset)			/* Offset into item. */
    TkSizeT offset)			/* Offset into item. */
{
    (void)dummy;
    (void)tkwin;

    return Tk_GetDash(interp, value, (Tk_Dash *) (widgRec+offset));
}

/*
 *--------------------------------------------------------------
 *
 * TkCanvasDashPrintProc --
537
538
539
540
541
542
543
544

545
546
547

548
549
550
551
552
553
554


555
556
557
558
559

560
561
562
563
564
565
566
567
568

569
570
571
572
573
574
575
551
552
553
554
555
556
557

558
559
560

561
562
563
564
565
566
567
568
569
570
571
572
573
574

575
576
577
578
579
580
581
582
583

584
585
586
587
588
589
590
591







-
+


-
+







+
+




-
+








-
+







 *	None.
 *
 *--------------------------------------------------------------
 */

const char *
TkCanvasDashPrintProc(
    ClientData clientData,	/* Ignored. */
    ClientData dummy,	/* Ignored. */
    Tk_Window tkwin,		/* Window containing canvas widget. */
    char *widgRec,		/* Pointer to record for item. */
    int offset,			/* Offset in record for item. */
    TkSizeT offset,			/* Offset in record for item. */
    Tcl_FreeProc **freeProcPtr)	/* Pointer to variable to fill in with
				 * information about how to reclaim storage
				 * for return string. */
{
    Tk_Dash *dash = (Tk_Dash *) (widgRec+offset);
    char *buffer, *p;
    int i = dash->number;
    (void)dummy;
    (void)tkwin;

    if (i < 0) {
	i = -i;
	*freeProcPtr = TCL_DYNAMIC;
	buffer = ckalloc(i + 1);
	buffer = (char *)ckalloc(i + 1);
	p = (i > (int)sizeof(char *)) ? dash->pattern.pt : dash->pattern.array;
	memcpy(buffer, p, (unsigned int) i);
	buffer[i] = 0;
	return buffer;
    } else if (!i) {
	*freeProcPtr = NULL;
	return "";
    }
    buffer = ckalloc(4 * i);
    buffer = (char *)ckalloc(4 * i);
    *freeProcPtr = TCL_DYNAMIC;

    p = (i > (int)sizeof(char *)) ? dash->pattern.pt : dash->pattern.array;
    sprintf(buffer, "%d", *p++ & 0xff);
    while (--i) {
	sprintf(buffer+strlen(buffer), " %d", *p++ & 0xff);
    }
597
598
599
600
601
602
603
604

605
606
607
608
609

610
611
612
613
614
615
616
613
614
615
616
617
618
619

620
621
622
623
624

625
626
627
628
629
630
631
632







-
+




-
+








static SmoothAssocData *
InitSmoothMethods(
    Tcl_Interp *interp)
{
    SmoothAssocData *methods, *ptr;

    methods = ckalloc(sizeof(SmoothAssocData));
    methods = (SmoothAssocData *)ckalloc(sizeof(SmoothAssocData));
    methods->smooth.name = tkRawSmoothMethod.name;
    methods->smooth.coordProc = tkRawSmoothMethod.coordProc;
    methods->smooth.postscriptProc = tkRawSmoothMethod.postscriptProc;

    ptr = methods->nextPtr = ckalloc(sizeof(SmoothAssocData));
    ptr = methods->nextPtr = (SmoothAssocData *)ckalloc(sizeof(SmoothAssocData));
    ptr->smooth.name = tkBezierSmoothMethod.name;
    ptr->smooth.coordProc = tkBezierSmoothMethod.coordProc;
    ptr->smooth.postscriptProc = tkBezierSmoothMethod.postscriptProc;
    ptr->nextPtr = NULL;

    Tcl_SetAssocData(interp, "smoothMethod", SmoothMethodCleanupProc,methods);
    return methods;
636
637
638
639
640
641
642
643

644
645
646
647
648
649
650
652
653
654
655
656
657
658

659
660
661
662
663
664
665
666







-
+








void
Tk_CreateSmoothMethod(
    Tcl_Interp *interp,
    const Tk_SmoothMethod *smooth)
{
    SmoothAssocData *methods, *typePtr2, *prevPtr, *ptr;
    methods = Tcl_GetAssocData(interp, "smoothMethod", NULL);
    methods = (SmoothAssocData *)Tcl_GetAssocData(interp, "smoothMethod", NULL);

    /*
     * Initialize if we were not previously initialized.
     */

    if (methods == NULL) {
	methods = InitSmoothMethods(interp);
662
663
664
665
666
667
668
669

670
671
672
673
674
675
676
678
679
680
681
682
683
684

685
686
687
688
689
690
691
692







-
+







	    } else {
		prevPtr->nextPtr = typePtr2->nextPtr;
	    }
	    ckfree(typePtr2);
	    break;
	}
    }
    ptr = ckalloc(sizeof(SmoothAssocData));
    ptr = (SmoothAssocData *)ckalloc(sizeof(SmoothAssocData));
    ptr->smooth.name = smooth->name;
    ptr->smooth.coordProc = smooth->coordProc;
    ptr->smooth.postscriptProc = smooth->postscriptProc;
    ptr->nextPtr = methods;
    Tcl_SetAssocData(interp, "smoothMethod", SmoothMethodCleanupProc, ptr);
}

691
692
693
694
695
696
697
698

699
700


701
702
703
704
705
706
707
707
708
709
710
711
712
713

714
715

716
717
718
719
720
721
722
723
724







-
+

-
+
+







 *----------------------------------------------------------------------
 */

static void
SmoothMethodCleanupProc(
    ClientData clientData,	/* Points to "smoothMethod" AssocData for the
				 * interpreter. */
    Tcl_Interp *interp)		/* Interpreter that is being deleted. */
    Tcl_Interp *dummy)		/* Interpreter that is being deleted. */
{
    SmoothAssocData *ptr, *methods = clientData;
    SmoothAssocData *ptr, *methods = (SmoothAssocData *)clientData;
    (void)dummy;

    while (methods != NULL) {
	ptr = methods;
	methods = methods->nextPtr;
	ckfree(ptr);
    }
}
721
722
723
724
725
726
727
728

729
730
731
732
733

734
735

736
737
738
739
740


741
742
743
744
745
746
747

748
749
750
751
752
753
754
755
756
757
758

759
760
761
762
763
764
765
738
739
740
741
742
743
744

745
746
747
748
749

750
751

752
753
754
755
756
757
758
759
760
761
762
763
764
765

766
767
768
769
770
771
772
773
774
775
776

777
778
779
780
781
782
783
784







-
+




-
+

-
+





+
+






-
+










-
+







 *	indicated in the value argument.
 *
 *--------------------------------------------------------------
 */

int
TkSmoothParseProc(
    ClientData clientData,	/* Ignored. */
    ClientData dummy,	/* Ignored. */
    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. */
    int offset)			/* Offset into item. */
    TkSizeT offset)			/* Offset into item. */
{
    register const Tk_SmoothMethod **smoothPtr =
    const Tk_SmoothMethod **smoothPtr =
	    (const Tk_SmoothMethod **) (widgRec + offset);
    const Tk_SmoothMethod *smooth = NULL;
    int b;
    size_t length;
    SmoothAssocData *methods;
    (void)dummy;
    (void)tkwin;

    if (value == NULL || *value == 0) {
	*smoothPtr = NULL;
	return TCL_OK;
    }
    length = strlen(value);
    methods = Tcl_GetAssocData(interp, "smoothMethod", NULL);
    methods = (SmoothAssocData *)Tcl_GetAssocData(interp, "smoothMethod", NULL);

    /*
     * Not initialized yet; fix that now.
     */

    if (methods == NULL) {
	methods = InitSmoothMethods(interp);
    }

    /*
     * Backward compatability hack.
     * Backward compatibility hack.
     */

    if (strncmp(value, "bezier", length) == 0) {
	smooth = &tkBezierSmoothMethod;
    }

    /*
813
814
815
816
817
818
819
820

821
822
823

824
825
826
827
828

829



830
831
832
833
834
835
836
832
833
834
835
836
837
838

839
840
841

842
843
844
845
846

847
848
849
850
851
852
853
854
855
856
857
858







-
+


-
+




-
+

+
+
+







 *	None.
 *
 *--------------------------------------------------------------
 */

const char *
TkSmoothPrintProc(
    ClientData clientData,	/* Ignored. */
    ClientData dummy,	/* Ignored. */
    Tk_Window tkwin,		/* Window containing canvas widget. */
    char *widgRec,		/* Pointer to record for item. */
    int offset,			/* Offset into item. */
    TkSizeT offset,			/* Offset into item. */
    Tcl_FreeProc **freeProcPtr)	/* Pointer to variable to fill in with
				 * information about how to reclaim storage
				 * for return string. */
{
    register const Tk_SmoothMethod *smoothPtr =
    const Tk_SmoothMethod *smoothPtr =
	    * (Tk_SmoothMethod **) (widgRec + offset);
    (void)dummy;
	(void)tkwin;
    (void)freeProcPtr;

    return smoothPtr ? smoothPtr->name : "0";
}
/*
 *--------------------------------------------------------------
 *
 * Tk_GetDash
872
873
874
875
876
877
878
879

880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897

898
899
900
901
902
903
904
894
895
896
897
898
899
900

901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918

919
920
921
922
923
924
925
926







-
+

















-
+







    case '.': case ',': case '-': case '_':
	i = DashConvert(NULL, value, -1, 0.0);
	if (i <= 0) {
	    goto badDashList;
	}
	i = strlen(value);
	if (i > (int) sizeof(char *)) {
	    dash->pattern.pt = pt = ckalloc(strlen(value));
	    dash->pattern.pt = pt = (char *)ckalloc(strlen(value));
	} else {
	    pt = dash->pattern.array;
	}
	memcpy(pt, value, (unsigned) i);
	dash->number = -i;
	return TCL_OK;
    }

    if (Tcl_SplitList(interp, (char *) value, &argc, &argv) != TCL_OK) {
	Tcl_ResetResult(interp);
	goto badDashList;
    }

    if ((unsigned) ABS(dash->number) > sizeof(char *)) {
	ckfree(dash->pattern.pt);
    }
    if (argc > (int) sizeof(char *)) {
	dash->pattern.pt = pt = ckalloc(argc);
	dash->pattern.pt = pt = (char *)ckalloc(argc);
    } else {
	pt = dash->pattern.array;
    }
    dash->number = argc;

    largv = argv;
    while (argc > 0) {
1221
1222
1223
1224
1225
1226
1227
1228

1229
1230
1231
1232
1233
1234
1235
1243
1244
1245
1246
1247
1248
1249

1250
1251
1252
1253
1254
1255
1256
1257







-
+








    if ((dash->number<-1) ||
	    ((dash->number == -1) && (dash->pattern.array[0] != ','))) {
	char *q;
	int i = -dash->number;

	p = (i > (int)sizeof(char *)) ? dash->pattern.pt : dash->pattern.array;
	q = ckalloc(2 * i);
	q = (char *)ckalloc(2 * i);
	i = DashConvert(q, p, i, width);
	XSetDashes(Canvas(canvas)->display, outline->gc, outline->offset, q,i);
	ckfree(q);
    } else if (dash->number>2 || (dash->number==2 &&
	    (dash->pattern.array[0]!=dash->pattern.array[1]))) {
	p = (dash->number > (int) sizeof(char *))
		? dash->pattern.pt : dash->pattern.array;
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1282
1283
1284
1285
1286
1287
1288

1289
1290
1291
1292
1293
1294
1295







-







	Tk_CanvasSetOffset(canvas, outline->gc, tsoffset);
	tsoffset->xoffset += w;
	tsoffset->yoffset += h;
	return 1;
    }
    return 0;
}


/*
 *--------------------------------------------------------------
 *
 * Tk_ResetOutlineGC
 *
 *	Restores the GC to the situation before Tk_ChangeOutlineGC() was
1443
1444
1445
1446
1447
1448
1449
1450

1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471

1472
1473
1474
1475
1476
1477
1478
1479
1480
1481

1482
1483
1484
1485
1486
1487
1488
1489
1490
1464
1465
1466
1467
1468
1469
1470

1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491

1492






1493
1494
1495

1496


1497
1498
1499
1500
1501
1502
1503







-
+




















-
+
-
-
-
-
-
-



-
+
-
-







	    Tcl_AppendToObj(psObj, " ", -1);
	    Tcl_AppendObjToObj(psObj, converted);
	}
	Tcl_DecrRefCount(converted);
	Tcl_AppendPrintfToObj(psObj, "] %d setdash\n", outline->offset);
    } else if (dash->number < 0) {
	if (dash->number < -5) {
	    lptr = ckalloc(1 - 2*dash->number);
	    lptr = (char *)ckalloc(1 - 2*dash->number);
	}
	i = DashConvert(lptr, ptr, -dash->number, width);
	if (i > 0) {
	    char *p = lptr;

	    Tcl_AppendPrintfToObj(psObj, "%d", *p++ & 0xff);
	    for (; --i>0 ;) {
		Tcl_AppendPrintfToObj(psObj, " %d", *p++ & 0xff);
	    }
	    Tcl_AppendPrintfToObj(psObj, "] %d setdash\n", outline->offset);
	} else {
	    Tcl_AppendToObj(psObj, "] 0 setdash\n", -1);
	}
	if (lptr != pattern) {
	    ckfree(lptr);
	}
    } else {
	Tcl_AppendToObj(psObj, "] 0 setdash\n", -1);
    }

    if (Tk_CanvasPsColor(interp, canvas, color) != TCL_OK) {
    Tk_CanvasPsColor(interp, canvas, color);
	return TCL_ERROR;
    }

    /*
     * Note that psObj might hold an invalid reference now.
     */

    if (stipple != None) {
	Tcl_AppendToObj(GetPostscriptBuffer(interp), "StrokeClip ", -1);
	if (Tk_CanvasPsStipple(interp, canvas, stipple) != TCL_OK) {
	Tk_CanvasPsStipple(interp, canvas, stipple);
	    return TCL_ERROR;
	}
    } else {
	Tcl_AppendToObj(GetPostscriptBuffer(interp), "stroke\n", -1);
    }

    return TCL_OK;
}

1656
1657
1658
1659
1660
1661
1662

1663
1664
1665
1666
1667
1668
1669
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683







+







    double top, btm;		/* Top and bottom sizes of the bounding box */
    double *tempArr;		/* Temporary storage used by the clipper */
    double *a, *b, *t;		/* Pointers to parts of the temporary
				 * storage */
    int i, j;			/* Loop counters */
    double limit[4];		/* Boundries at which clipping occurs */
    double staticSpace[480];	/* Temp space from the stack */
    (void)closedPath;

    /*
     * Constrain all vertices of the path to be within a box that is no larger
     * than 32000 pixels wide or height. The top-left corner of this clipping
     * box is 1000 pixels above and to the left of the top left corner of the
     * window on which the canvas is displayed.
     *
1715
1716
1717
1718
1719
1720
1721
1722

1723
1724
1725
1726
1727
1728
1729
1729
1730
1731
1732
1733
1734
1735

1736
1737
1738
1739
1740
1741
1742
1743







-
+







     * coordArr[] requires. Divide this space into two separate arrays a[] and
     * b[]. Initialize a[] to be equal to coordArr[].
     */

    if (numVertex*12 <= (int) (sizeof(staticSpace) / sizeof(double))) {
	tempArr = staticSpace;
    } else {
	tempArr = ckalloc(numVertex * 12 * sizeof(double));
	tempArr = (double *)ckalloc(numVertex * 12 * sizeof(double));
    }
    for (i=0; i<numVertex*2; i++){
	tempArr[i] = coordArr[i];
    }
    a = tempArr;
    b = &tempArr[numVertex*6];

1858
1859
1860
1861
1862
1863
1864





































1865
1866
1867
1868
1869
1870
1871
1872
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








	TranslateAndAppendCoords(canvPtr, a[i*2], a[i*2+1], outArr, i);
    }
    if (tempArr != staticSpace) {
	ckfree(tempArr);
    }
    return numOutput;
}

/*
 *--------------------------------------------------------------
 *
 * TkRotatePoint --
 *
 *	Rotate a point about another point. The angle should be converted into
 *	its sine and cosine before calling this function.
 *
 * Results:
 *	None
 *
 * Side effects:
 *	The point in (*xPtr,*yPtr) is updated to be rotated about
 *	(originX,originY) by the amount given by the sine and cosine of the
 *	angle to rotate.
 *
 *--------------------------------------------------------------
 */

void
TkRotatePoint(
    double originX, double originY,	/* The point about which to rotate. */
    double sine, double cosine,		/* How much to rotate? */
    double *xPtr, double *yPtr)		/* The point to be rotated. (INOUT) */
{
    double x = *xPtr - originX;
    double y = *yPtr - originY;

    /*
     * Beware! The canvas coordinate space is flipped vertically, so rotations
     * go the "wrong" way with respect to mathematics.
     */

    *xPtr = originX + x * cosine + y * sine;
    *yPtr = originY - x * sine + y * cosine;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Changes to generic/tkCanvWind.c.
1
2
3
4
5
6
7


8
9
10
11
12
13
14
1
2
3
4
5


6
7
8
9
10
11
12
13
14





-
-
+
+







/*
 * 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.
 */

#include "tkInt.h"
#include "tkCanvas.h"
37
38
39
40
41
42
43
44

45
46
47
48
49

50
51

52
53

54
55
56
57

58
59

60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79


80
81
82
83
84
85
86
87
88

89
90
91
92
93
94
95
37
38
39
40
41
42
43

44
45
46
47
48

49
50

51
52

53
54
55
56

57
58

59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89

90
91
92
93
94
95
96
97







-
+




-
+

-
+

-
+



-
+

-
+




















+
+








-
+







 * Information used for parsing configuration specs:
 */

static const Tk_CustomOption stateOption = {
    TkStateParseProc, TkStatePrintProc, INT2PTR(2)
};
static const Tk_CustomOption tagsOption = {
    Tk_CanvasTagsParseProc, Tk_CanvasTagsPrintProc, NULL
    TkCanvasTagsParseProc, TkCanvasTagsPrintProc, NULL
};

static const Tk_ConfigSpec configSpecs[] = {
    {TK_CONFIG_ANCHOR, "-anchor", NULL, NULL,
	"center", Tk_Offset(WindowItem, anchor), TK_CONFIG_DONT_SET_DEFAULT, NULL},
	"center", offsetof(WindowItem, anchor), TK_CONFIG_DONT_SET_DEFAULT, NULL},
    {TK_CONFIG_PIXELS, "-height", NULL, NULL,
	"0", Tk_Offset(WindowItem, height), TK_CONFIG_DONT_SET_DEFAULT, NULL},
	"0", offsetof(WindowItem, height), TK_CONFIG_DONT_SET_DEFAULT, NULL},
    {TK_CONFIG_CUSTOM, "-state", NULL, NULL,
	NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK, &stateOption},
	NULL, offsetof(Tk_Item, state), TK_CONFIG_NULL_OK, &stateOption},
    {TK_CONFIG_CUSTOM, "-tags", NULL, NULL,
	NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},
    {TK_CONFIG_PIXELS, "-width", NULL, NULL,
	"0", Tk_Offset(WindowItem, width), TK_CONFIG_DONT_SET_DEFAULT, NULL},
	"0", offsetof(WindowItem, width), TK_CONFIG_DONT_SET_DEFAULT, NULL},
    {TK_CONFIG_WINDOW, "-window", NULL, NULL,
	NULL, Tk_Offset(WindowItem, tkwin), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(WindowItem, tkwin), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL}
};

/*
 * Prototypes for functions defined in this file:
 */

static void		ComputeWindowBbox(Tk_Canvas canvas,
			    WindowItem *winItemPtr);
static int		ConfigureWinItem(Tcl_Interp *interp,
			    Tk_Canvas canvas, Tk_Item *itemPtr, int objc,
			    Tcl_Obj *const objv[], int flags);
static int		CreateWinItem(Tcl_Interp *interp,
			    Tk_Canvas canvas, struct Tk_Item *itemPtr,
			    int objc, Tcl_Obj *const objv[]);
static void		DeleteWinItem(Tk_Canvas canvas,
			    Tk_Item *itemPtr, Display *display);
static void		DisplayWinItem(Tk_Canvas canvas,
			    Tk_Item *itemPtr, Display *display, Drawable dst,
			    int x, int y, int width, int height);
static void		RotateWinItem(Tk_Canvas canvas, Tk_Item *itemPtr,
			    double originX, double originY, double angleRad);
static void		ScaleWinItem(Tk_Canvas canvas,
			    Tk_Item *itemPtr, double originX, double originY,
			    double scaleX, double scaleY);
static void		TranslateWinItem(Tk_Canvas canvas,
			    Tk_Item *itemPtr, double deltaX, double deltaY);
static int		WinItemCoords(Tcl_Interp *interp,
			    Tk_Canvas canvas, Tk_Item *itemPtr, int objc,
			    Tcl_Obj *const objv[]);
static void		WinItemLostSlaveProc(ClientData clientData,
static void		WinItemLostContentProc(ClientData clientData,
			    Tk_Window tkwin);
static void		WinItemRequestProc(ClientData clientData,
			    Tk_Window tkwin);
static void		WinItemStructureProc(ClientData clientData,
			    XEvent *eventPtr);
static int		WinItemToArea(Tk_Canvas canvas,
			    Tk_Item *itemPtr, double *rectPtr);
126
127
128
129
130
131
132

133

134
135
136
137
138
139
140
141
142
143
144

145
146
147
148
149
150
151
128
129
130
131
132
133
134
135

136
137
138
139
140
141
142
143
144
145
146

147
148
149
150
151
152
153
154







+
-
+










-
+







    TranslateWinItem,		/* translateProc */
    NULL,			/* indexProc */
    NULL,			/* cursorProc */
    NULL,			/* selectionProc */
    NULL,			/* insertProc */
    NULL,			/* dTextProc */
    NULL,			/* nextPtr */
    RotateWinItem,		/* rotateProc */
    NULL, 0, NULL, NULL
    0, NULL, NULL
};

/*
 * The structure below defines the official type record for the canvas (as
 * geometry manager):
 */

static const Tk_GeomMgr canvasGeomType = {
    "canvas",				/* name */
    WinItemRequestProc,			/* requestProc */
    WinItemLostSlaveProc,		/* lostSlaveProc */
    WinItemLostContentProc,		/* lostContentProc */
};

/*
 *--------------------------------------------------------------
 *
 * CreateWinItem --
 *
401
402
403
404
405
406
407

408
409
410
411
412
413
414
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418







+







DeleteWinItem(
    Tk_Canvas canvas,		/* Overall info about widget. */
    Tk_Item *itemPtr,		/* Item that is being deleted. */
    Display *display)		/* Display containing window for canvas. */
{
    WindowItem *winItemPtr = (WindowItem *) itemPtr;
    Tk_Window canvasTkwin = Tk_CanvasTkwin(canvas);
    (void)display;

    if (winItemPtr->tkwin != NULL) {
	Tk_DeleteEventHandler(winItemPtr->tkwin, StructureNotifyMask,
		WinItemStructureProc, winItemPtr);
	Tk_ManageGeometry(winItemPtr->tkwin, NULL, NULL);
	if (canvasTkwin != Tk_Parent(winItemPtr->tkwin)) {
	    Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin);
563
564
565
566
567
568
569





570
571
572
573
574
575
576
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585







+
+
+
+
+







				 * redisplayed (not used). */
{
    WindowItem *winItemPtr = (WindowItem *) itemPtr;
    int width, height;
    short x, y;
    Tk_Window canvasTkwin = Tk_CanvasTkwin(canvas);
    Tk_State state = itemPtr->state;
    (void)display;
    (void)regionX;
    (void)regionY;
    (void)regionWidth;
    (void)regionHeight;

    if (winItemPtr->tkwin == NULL) {
	return;
    }
    if (state == TK_STATE_NULL) {
	state = Canvas(canvas)->canvas_state;
    }
651
652
653
654
655
656
657

658
659
660
661
662
663
664
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674







+







WinItemToPoint(
    Tk_Canvas canvas,		/* Canvas containing item. */
    Tk_Item *itemPtr,		/* Item to check against point. */
    double *pointPtr)		/* Pointer to x and y coordinates. */
{
    WindowItem *winItemPtr = (WindowItem *) itemPtr;
    double x1, x2, y1, y2, xDiff, yDiff;
    (void)canvas;

    x1 = winItemPtr->header.x1;
    y1 = winItemPtr->header.y1;
    x2 = winItemPtr->header.x2;
    y2 = winItemPtr->header.y2;

    /*
708
709
710
711
712
713
714

715
716
717
718
719
720
721
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732







+







    Tk_Canvas canvas,		/* Canvas containing item. */
    Tk_Item *itemPtr,		/* Item to check against rectangle. */
    double *rectPtr)		/* Pointer to array of four coordinates
				 * (x1,y1,x2,y2) describing rectangular
				 * area.  */
{
    WindowItem *winItemPtr = (WindowItem *) itemPtr;
    (void)canvas;

    if ((rectPtr[2] <= winItemPtr->header.x1)
	    || (rectPtr[0] >= winItemPtr->header.x2)
	    || (rectPtr[3] <= winItemPtr->header.y1)
	    || (rectPtr[1] >= winItemPtr->header.y2)) {
	return -1;
    }
744
745
746
747
748
749
750
751

752
753



754
755
756
757
758
759
760
755
756
757
758
759
760
761

762
763
764
765
766
767
768
769
770
771
772
773
774







-
+


+
+
+







 *
 *--------------------------------------------------------------
 */

#ifdef X_GetImage
static int
xerrorhandler(
    ClientData clientData,
    ClientData dummy,
    XErrorEvent *e)
{
    (void)dummy;
    (void)e;

    return 0;
}
#endif /* X_GetImage */

/*
 *--------------------------------------------------------------
 *
911
912
913
914
915
916
917


































918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    Tcl_DecrRefCount(psObj);
    return result;
}

/*
 *--------------------------------------------------------------
 *
 * RotateWinItem --
 *
 *	This function is called to rotate a window item by a given amount
 *	about a point. Note that this does *not* rotate the window of the
 *	item.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The position of the window anchor is rotated by angleRad about (originX,
 *	originY), and the bounding box is updated in the generic part of the
 *	item structure.
 *
 *--------------------------------------------------------------
 */

static void
RotateWinItem(
    Tk_Canvas canvas,		/* Canvas containing item. */
    Tk_Item *itemPtr,		/* Item that is being rotated. */
    double originX, double originY,
    double angleRad)		/* Amount by which item is to be rotated. */
{
    WindowItem *winItemPtr = (WindowItem *) itemPtr;

    TkRotatePoint(originX, originY, sin(angleRad), cos(angleRad),
	    &winItemPtr->x, &winItemPtr->y);
    ComputeWindowBbox(canvas, winItemPtr);
}

/*
 *--------------------------------------------------------------
 *
 * ScaleWinItem --
 *
 *	This function is invoked to rescale a window item.
 *
 * Results:
 *	None.
 *
1003
1004
1005
1006
1007
1008
1009
1010

1011
1012
1013
1014
1015
1016
1017
1051
1052
1053
1054
1055
1056
1057

1058
1059
1060
1061
1062
1063
1064
1065







-
+







 */

static void
WinItemStructureProc(
    ClientData clientData,	/* Pointer to record describing window item. */
    XEvent *eventPtr)		/* Describes what just happened. */
{
    WindowItem *winItemPtr = clientData;
    WindowItem *winItemPtr = (WindowItem *)clientData;

    if (eventPtr->type == DestroyNotify) {
	winItemPtr->tkwin = NULL;
    }
}

/*
1033
1034
1035
1036
1037
1038
1039
1040


1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056

1057
1058
1059

1060
1061
1062
1063
1064
1065

1066
1067
1068
1069
1070
1071
1072
1073


1074
1075

1076
1077

1078

1079
1080
1081
1082
1083
1084
1085
1081
1082
1083
1084
1085
1086
1087

1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104

1105
1106
1107

1108
1109
1110
1111
1112
1113

1114
1115
1116
1117
1118

1119


1120
1121
1122

1123
1124

1125
1126
1127
1128
1129
1130
1131
1132
1133
1134







-
+
+















-
+


-
+





-
+




-

-
-
+
+

-
+

-
+

+







 */

static void
WinItemRequestProc(
    ClientData clientData,	/* Pointer to record for window item. */
    Tk_Window tkwin)		/* Window that changed its desired size. */
{
    WindowItem *winItemPtr = clientData;
    WindowItem *winItemPtr = (WindowItem *)clientData;
    (void)tkwin;

    ComputeWindowBbox(winItemPtr->canvas, winItemPtr);

    /*
     * A drawable argument of None to DisplayWinItem is used by the canvas
     * UnmapNotify handler to indicate that we should no longer display
     * ourselves, so need to pass a (bogus) non-zero drawable value here.
     */
    DisplayWinItem(winItemPtr->canvas, (Tk_Item *) winItemPtr, NULL,
	    (Drawable) -1, 0, 0, 0, 0);
}

/*
 *--------------------------------------------------------------
 *
 * WinItemLostSlaveProc --
 * WinItemLostContentProc --
 *
 *	This function is invoked by Tk whenever some other geometry claims
 *	control over a slave that used to be managed by us.
 *	control over a content window that used to be managed by us.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Forgets all canvas-related information about the slave.
 *	Forgets all canvas-related information about the content window.
 *
 *--------------------------------------------------------------
 */

	/* ARGSUSED */
static void
WinItemLostSlaveProc(
    ClientData clientData,	/* WindowItem structure for slave window that
WinItemLostContentProc(
    ClientData clientData,	/* WindowItem structure for content window window that
				 * was stolen away. */
    Tk_Window tkwin)		/* Tk's handle for the slave window. */
    Tk_Window tkwin)		/* Tk's handle for the content window. */
{
    WindowItem *winItemPtr = clientData;
    WindowItem *winItemPtr = (WindowItem *)clientData;
    Tk_Window canvasTkwin = Tk_CanvasTkwin(winItemPtr->canvas);
    (void)tkwin;

    Tk_DeleteEventHandler(winItemPtr->tkwin, StructureNotifyMask,
	    WinItemStructureProc, winItemPtr);
    if (canvasTkwin != Tk_Parent(winItemPtr->tkwin)) {
	Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin);
    }
    Tk_UnmapWindow(winItemPtr->tkwin);
Changes to generic/tkCanvas.c.
1
2
3
4
5
6
7
8
9
10



11
12
13
14
15
16
17
18
19
20



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
1
2
3
4
5
6
7



8
9
10
11
12
13
14
15





16
17
18
19
20
21
22
23
24
25
26
27
28




















29
30
31
32
33
34
35







-
-
-
+
+
+





-
-
-
-
-
+
+
+










-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







/*
 * tkCanvas.c --
 *
 *	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.
 */

/* #define USE_OLD_TAG_SEARCH 1 */

#include "default.h"
#include "tkInt.h"
#include "tkCanvas.h"
#include "tkInt.h"
#include "tkCanvas.h"
#include "default.h"
#ifdef TK_NO_DOUBLE_BUFFERING
#ifdef MAC_OSX_TK
#include "tkMacOSXInt.h"
#endif
#endif /* TK_NO_DOUBLE_BUFFERING */

/*
 * See tkCanvas.h for key data structures used to implement canvases.
 */

#ifdef USE_OLD_TAG_SEARCH
/*
 * The structure defined below is used to keep track of a tag search in
 * progress. No field should be accessed by anyone other than StartTagSearch
 * and NextItem.
 */

typedef struct TagSearch {
    TkCanvas *canvasPtr;	/* Canvas widget being searched. */
    Tk_Uid tag;			/* Tag to search for. 0 means return all
				 * items. */
    Tk_Item *currentPtr;	/* Pointer to last item returned. */
    Tk_Item *lastPtr;		/* The item right before the currentPtr is
				 * tracked so if the currentPtr is deleted we
				 * don't have to start from the beginning. */
    int searchOver;		/* Non-zero means NextItem should always
				 * return NULL. */
} TagSearch;

#else /* USE_OLD_TAG_SEARCH */
/*
 * The structure defined below is used to keep track of a tag search in
 * progress. No field should be accessed by anyone other than TagSearchScan,
 * TagSearchFirst, TagSearchNext, TagSearchScanExpr, TagSearchEvalExpr,
 * TagSearchExprInit, TagSearchExprDestroy, TagSearchDestroy.
 * (
 *   Not quite accurate: the TagSearch structure is also accessed from:
70
71
72
73
74
75
76
77

78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118

119
120
121

122
123
124
125
126

127
128

129
130

131
132

133
134

135
136
137

138
139

140
141
142

143
144

145
146
147

148
149
150

151
152

153
154

155
156

157
158

159
160
161

162
163

164
165
166

167
168
169

170
171
172
173

174
175

176
177
178

179
180
181

182
183
184

185
186
187

188
189
190

191
192

193
194
195
196

197
198
199

200
201
202
203

204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253


254
255
256
257
258
259

260
261
262
263
264
265
266
267
268
269



270


271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
48
49
50
51
52
53
54

55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74


75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93

94
95
96

97
98
99
100
101

102
103

104
105

106
107

108
109

110
111
112

113
114

115
116
117

118
119

120
121
122

123
124
125

126
127

128
129

130
131

132
133

134
135
136

137
138

139
140
141

142
143
144

145
146
147
148

149
150

151
152
153

154
155
156

157
158
159

160
161
162

163
164
165

166
167

168
169
170
171

172
173
174

175
176
177
178

179
180
181
182
183
184
185
186
187
188
189
190
191
192
193

194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213

214
215
216
217
218
219
220
221
222
223
224
225


226
227
228
229
230
231
232

233
234
235
236
237
238
239
240
241
242
243
244
245
246

247
248
249
250
251
252
253





254
255
256
257

258
259
260
261
262



263
264
265






266
267
268
269
270
271
272
273
274
275
276
277
278

279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295











296
297
298
299
300
301
302
303
304
305
306
307
308
309
310

311
312
313
314
315
316
317







-
+



















-
-



















-
+


-
+




-
+

-
+

-
+

-
+

-
+


-
+

-
+


-
+

-
+


-
+


-
+

-
+

-
+

-
+

-
+


-
+

-
+


-
+


-
+



-
+

-
+


-
+


-
+


-
+


-
+


-
+

-
+



-
+


-
+



-
+














-




















-












-
-
+
+





-
+










+
+
+
-
+
+





-
-
-
-
-




-





-
-
-



-
-
-
-
-
-













-

















-
-
-
-
-
-
-
-
-
-
-















-







    Tk_Item *currentPtr;	/* Pointer to last item returned. */
    Tk_Item *lastPtr;		/* The item right before the currentPtr is
				 * tracked so if the currentPtr is deleted we
				 * don't have to start from the beginning. */
    int searchOver;		/* Non-zero means NextItem should always
				 * return NULL. */
    int type;			/* Search type (see #defs below) */
    int id;			/* Item id for searches by id */
    TkSizeT id;			/* Item id for searches by id */
    const char *string;		/* Tag expression string */
    int stringIndex;		/* Current position in string scan */
    int stringLength;		/* Length of tag expression string */
    char *rewritebuffer;	/* Tag string (after removing escapes) */
    unsigned int rewritebufferAllocated;
				/* Available space for rewrites. */
    TagSearchExpr *expr;	/* Compiled tag expression. */
} TagSearch;

/*
 * Values for the TagSearch type field.
 */

#define SEARCH_TYPE_EMPTY	0	/* Looking for empty tag */
#define SEARCH_TYPE_ID		1	/* Looking for an item by id */
#define SEARCH_TYPE_ALL		2	/* Looking for all items */
#define SEARCH_TYPE_TAG		3	/* Looking for an item by simple tag */
#define SEARCH_TYPE_EXPR	4	/* Compound search */

#endif /* USE_OLD_TAG_SEARCH */

/*
 * Custom option for handling "-state" and "-offset"
 */

static const Tk_CustomOption stateOption = {
    TkStateParseProc, TkStatePrintProc,
    NULL		/* Only "normal" and "disabled". */
};

static const Tk_CustomOption offsetOption = {
    TkOffsetParseProc, TkOffsetPrintProc, INT2PTR(TK_OFFSET_RELATIVE)
};

/*
 * Information used for argv parsing.
 */

static const Tk_ConfigSpec configSpecs[] = {
    {TK_CONFIG_BORDER, "-background", "background", "Background",
	DEF_CANVAS_BG_COLOR, Tk_Offset(TkCanvas, bgBorder),
	DEF_CANVAS_BG_COLOR, offsetof(TkCanvas, bgBorder),
	TK_CONFIG_COLOR_ONLY, NULL},
    {TK_CONFIG_BORDER, "-background", "background", "Background",
	DEF_CANVAS_BG_MONO, Tk_Offset(TkCanvas, bgBorder),
	DEF_CANVAS_BG_MONO, offsetof(TkCanvas, bgBorder),
	TK_CONFIG_MONO_ONLY, NULL},
    {TK_CONFIG_SYNONYM, "-bd", "borderWidth", NULL, NULL, 0, 0, NULL},
    {TK_CONFIG_SYNONYM, "-bg", "background", NULL, NULL, 0, 0, NULL},
    {TK_CONFIG_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
	DEF_CANVAS_BORDER_WIDTH, Tk_Offset(TkCanvas, borderWidth), 0, NULL},
	DEF_CANVAS_BORDER_WIDTH, offsetof(TkCanvas, borderWidth), 0, NULL},
    {TK_CONFIG_DOUBLE, "-closeenough", "closeEnough", "CloseEnough",
	DEF_CANVAS_CLOSE_ENOUGH, Tk_Offset(TkCanvas, closeEnough), 0, NULL},
	DEF_CANVAS_CLOSE_ENOUGH, offsetof(TkCanvas, closeEnough), 0, NULL},
    {TK_CONFIG_BOOLEAN, "-confine", "confine", "Confine",
	DEF_CANVAS_CONFINE, Tk_Offset(TkCanvas, confine), 0, NULL},
	DEF_CANVAS_CONFINE, offsetof(TkCanvas, confine), 0, NULL},
    {TK_CONFIG_ACTIVE_CURSOR, "-cursor", "cursor", "Cursor",
	DEF_CANVAS_CURSOR, Tk_Offset(TkCanvas, cursor), TK_CONFIG_NULL_OK, NULL},
	DEF_CANVAS_CURSOR, offsetof(TkCanvas, cursor), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_PIXELS, "-height", "height", "Height",
	DEF_CANVAS_HEIGHT, Tk_Offset(TkCanvas, height), 0, NULL},
	DEF_CANVAS_HEIGHT, offsetof(TkCanvas, height), 0, NULL},
    {TK_CONFIG_COLOR, "-highlightbackground", "highlightBackground",
	"HighlightBackground", DEF_CANVAS_HIGHLIGHT_BG,
	Tk_Offset(TkCanvas, highlightBgColorPtr), 0, NULL},
	offsetof(TkCanvas, highlightBgColorPtr), 0, NULL},
    {TK_CONFIG_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
	DEF_CANVAS_HIGHLIGHT, Tk_Offset(TkCanvas, highlightColorPtr), 0, NULL},
	DEF_CANVAS_HIGHLIGHT, offsetof(TkCanvas, highlightColorPtr), 0, NULL},
    {TK_CONFIG_PIXELS, "-highlightthickness", "highlightThickness",
	"HighlightThickness",
	DEF_CANVAS_HIGHLIGHT_WIDTH, Tk_Offset(TkCanvas, highlightWidth), 0, NULL},
	DEF_CANVAS_HIGHLIGHT_WIDTH, offsetof(TkCanvas, highlightWidth), 0, NULL},
    {TK_CONFIG_BORDER, "-insertbackground", "insertBackground", "Foreground",
	DEF_CANVAS_INSERT_BG, Tk_Offset(TkCanvas, textInfo.insertBorder), 0, NULL},
	DEF_CANVAS_INSERT_BG, offsetof(TkCanvas, textInfo.insertBorder), 0, NULL},
    {TK_CONFIG_PIXELS, "-insertborderwidth", "insertBorderWidth", "BorderWidth",
	DEF_CANVAS_INSERT_BD_COLOR,
	Tk_Offset(TkCanvas, textInfo.insertBorderWidth), TK_CONFIG_COLOR_ONLY, NULL},
	offsetof(TkCanvas, textInfo.insertBorderWidth), TK_CONFIG_COLOR_ONLY, NULL},
    {TK_CONFIG_PIXELS, "-insertborderwidth", "insertBorderWidth", "BorderWidth",
	DEF_CANVAS_INSERT_BD_MONO,
	Tk_Offset(TkCanvas, textInfo.insertBorderWidth), TK_CONFIG_MONO_ONLY, NULL},
	offsetof(TkCanvas, textInfo.insertBorderWidth), TK_CONFIG_MONO_ONLY, NULL},
    {TK_CONFIG_INT, "-insertofftime", "insertOffTime", "OffTime",
	DEF_CANVAS_INSERT_OFF_TIME, Tk_Offset(TkCanvas, insertOffTime), 0, NULL},
	DEF_CANVAS_INSERT_OFF_TIME, offsetof(TkCanvas, insertOffTime), 0, NULL},
    {TK_CONFIG_INT, "-insertontime", "insertOnTime", "OnTime",
	DEF_CANVAS_INSERT_ON_TIME, Tk_Offset(TkCanvas, insertOnTime), 0, NULL},
	DEF_CANVAS_INSERT_ON_TIME, offsetof(TkCanvas, insertOnTime), 0, NULL},
    {TK_CONFIG_PIXELS, "-insertwidth", "insertWidth", "InsertWidth",
	DEF_CANVAS_INSERT_WIDTH, Tk_Offset(TkCanvas, textInfo.insertWidth), 0, NULL},
	DEF_CANVAS_INSERT_WIDTH, offsetof(TkCanvas, textInfo.insertWidth), 0, NULL},
    {TK_CONFIG_CUSTOM, "-offset", "offset", "Offset", "0,0",
	Tk_Offset(TkCanvas, tsoffset),TK_CONFIG_DONT_SET_DEFAULT,
	offsetof(TkCanvas, tsoffset),TK_CONFIG_DONT_SET_DEFAULT,
	&offsetOption},
    {TK_CONFIG_RELIEF, "-relief", "relief", "Relief",
	DEF_CANVAS_RELIEF, Tk_Offset(TkCanvas, relief), 0, NULL},
	DEF_CANVAS_RELIEF, offsetof(TkCanvas, relief), 0, NULL},
    {TK_CONFIG_STRING, "-scrollregion", "scrollRegion", "ScrollRegion",
	DEF_CANVAS_SCROLL_REGION, Tk_Offset(TkCanvas, regionString),
	DEF_CANVAS_SCROLL_REGION, offsetof(TkCanvas, regionString),
	TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_BORDER, "-selectbackground", "selectBackground", "Foreground",
	DEF_CANVAS_SELECT_COLOR, Tk_Offset(TkCanvas, textInfo.selBorder),
	DEF_CANVAS_SELECT_COLOR, offsetof(TkCanvas, textInfo.selBorder),
	TK_CONFIG_COLOR_ONLY, NULL},
    {TK_CONFIG_BORDER, "-selectbackground", "selectBackground", "Foreground",
	DEF_CANVAS_SELECT_MONO, Tk_Offset(TkCanvas, textInfo.selBorder),
	DEF_CANVAS_SELECT_MONO, offsetof(TkCanvas, textInfo.selBorder),
	TK_CONFIG_MONO_ONLY, NULL},
    {TK_CONFIG_PIXELS, "-selectborderwidth", "selectBorderWidth", "BorderWidth",
	DEF_CANVAS_SELECT_BD_COLOR,
	Tk_Offset(TkCanvas, textInfo.selBorderWidth), TK_CONFIG_COLOR_ONLY, NULL},
	offsetof(TkCanvas, textInfo.selBorderWidth), TK_CONFIG_COLOR_ONLY, NULL},
    {TK_CONFIG_PIXELS, "-selectborderwidth", "selectBorderWidth", "BorderWidth",
	DEF_CANVAS_SELECT_BD_MONO, Tk_Offset(TkCanvas, textInfo.selBorderWidth),
	DEF_CANVAS_SELECT_BD_MONO, offsetof(TkCanvas, textInfo.selBorderWidth),
	TK_CONFIG_MONO_ONLY, NULL},
    {TK_CONFIG_COLOR, "-selectforeground", "selectForeground", "Background",
	DEF_CANVAS_SELECT_FG_COLOR, Tk_Offset(TkCanvas, textInfo.selFgColorPtr),
	DEF_CANVAS_SELECT_FG_COLOR, offsetof(TkCanvas, textInfo.selFgColorPtr),
	TK_CONFIG_COLOR_ONLY|TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_COLOR, "-selectforeground", "selectForeground", "Background",
	DEF_CANVAS_SELECT_FG_MONO, Tk_Offset(TkCanvas, textInfo.selFgColorPtr),
	DEF_CANVAS_SELECT_FG_MONO, offsetof(TkCanvas, textInfo.selFgColorPtr),
	TK_CONFIG_MONO_ONLY|TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_CUSTOM, "-state", "state", "State",
	"normal", Tk_Offset(TkCanvas, canvas_state), TK_CONFIG_DONT_SET_DEFAULT,
	"normal", offsetof(TkCanvas, canvas_state), TK_CONFIG_DONT_SET_DEFAULT,
	&stateOption},
    {TK_CONFIG_STRING, "-takefocus", "takeFocus", "TakeFocus",
	DEF_CANVAS_TAKE_FOCUS, Tk_Offset(TkCanvas, takeFocus),
	DEF_CANVAS_TAKE_FOCUS, offsetof(TkCanvas, takeFocus),
	TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_PIXELS, "-width", "width", "Width",
	DEF_CANVAS_WIDTH, Tk_Offset(TkCanvas, width), 0, NULL},
	DEF_CANVAS_WIDTH, offsetof(TkCanvas, width), 0, NULL},
    {TK_CONFIG_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand",
	DEF_CANVAS_X_SCROLL_CMD, Tk_Offset(TkCanvas, xScrollCmd),
	DEF_CANVAS_X_SCROLL_CMD, offsetof(TkCanvas, xScrollCmd),
	TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_PIXELS, "-xscrollincrement", "xScrollIncrement",
	"ScrollIncrement",
	DEF_CANVAS_X_SCROLL_INCREMENT, Tk_Offset(TkCanvas, xScrollIncrement),
	DEF_CANVAS_X_SCROLL_INCREMENT, offsetof(TkCanvas, xScrollIncrement),
	0, NULL},
    {TK_CONFIG_STRING, "-yscrollcommand", "yScrollCommand", "ScrollCommand",
	DEF_CANVAS_Y_SCROLL_CMD, Tk_Offset(TkCanvas, yScrollCmd),
	DEF_CANVAS_Y_SCROLL_CMD, offsetof(TkCanvas, yScrollCmd),
	TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_PIXELS, "-yscrollincrement", "yScrollIncrement",
	"ScrollIncrement",
	DEF_CANVAS_Y_SCROLL_INCREMENT, Tk_Offset(TkCanvas, yScrollIncrement),
	DEF_CANVAS_Y_SCROLL_INCREMENT, offsetof(TkCanvas, yScrollIncrement),
	0, NULL},
    {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL}
};

/*
 * List of all the item types known at present. This is *global* and is
 * protected by typeListMutex.
 */

static Tk_ItemType *typeList = NULL;
				/* NULL means initialization hasn't been done
				 * yet. */
TCL_DECLARE_MUTEX(typeListMutex)

#ifndef USE_OLD_TAG_SEARCH
/*
 * Uids for operands in compiled advanced tag search expressions.
 * Initialization is done by GetStaticUids()
 */

typedef struct {
    Tk_Uid allUid;
    Tk_Uid currentUid;
    Tk_Uid andUid;
    Tk_Uid orUid;
    Tk_Uid xorUid;
    Tk_Uid parenUid;
    Tk_Uid negparenUid;
    Tk_Uid endparenUid;
    Tk_Uid tagvalUid;
    Tk_Uid negtagvalUid;
} SearchUids;

static Tcl_ThreadDataKey dataKey;
static SearchUids *	GetStaticUids(void);
#endif /* USE_OLD_TAG_SEARCH */

/*
 * Prototypes for functions defined later in this file:
 */

static void		CanvasBindProc(ClientData clientData,
			    XEvent *eventPtr);
static void		CanvasBlinkProc(ClientData clientData);
static void		CanvasCmdDeletedProc(ClientData clientData);
static void		CanvasDoEvent(TkCanvas *canvasPtr, XEvent *eventPtr);
static void		CanvasEventProc(ClientData clientData,
			    XEvent *eventPtr);
static int		CanvasFetchSelection(ClientData clientData, int offset,
			    char *buffer, int maxBytes);
static TkSizeT	CanvasFetchSelection(ClientData clientData, TkSizeT offset,
			    char *buffer, TkSizeT maxBytes);
static Tk_Item *	CanvasFindClosest(TkCanvas *canvasPtr,
			    double coords[2]);
static void		CanvasFocusProc(TkCanvas *canvasPtr, int gotFocus);
static void		CanvasLostSelection(ClientData clientData);
static void		CanvasSelectTo(TkCanvas *canvasPtr,
			    Tk_Item *itemPtr, int index);
			    Tk_Item *itemPtr, TkSizeT index);
static void		CanvasSetOrigin(TkCanvas *canvasPtr,
			    int xOrigin, int yOrigin);
static void		CanvasUpdateScrollbars(TkCanvas *canvasPtr);
static int		CanvasWidgetCmd(ClientData clientData,
			    Tcl_Interp *interp, int argc,
			    Tcl_Obj *const *argv);
static void		CanvasWorldChanged(ClientData instanceData);
static int		ConfigureCanvas(Tcl_Interp *interp,
			    TkCanvas *canvasPtr, int argc,
			    Tcl_Obj *const *argv, int flags);
static void		DefaultRotateImplementation(TkCanvas *canvasPtr,
			    Tk_Item *itemPtr, double x, double y,
			    double angleRadians);
static void		DestroyCanvas(char *memPtr);
static void		DestroyCanvas(void *memPtr);
static int		DrawCanvas(Tcl_Interp *interp, ClientData clientData, Tk_PhotoHandle photohandle, int subsample, int zoom);
static void		DisplayCanvas(ClientData clientData);
static void		DoItem(Tcl_Obj *accumObj,
			    Tk_Item *itemPtr, Tk_Uid tag);
static void		EventuallyRedrawItem(TkCanvas *canvasPtr,
			    Tk_Item *itemPtr);
#ifdef USE_OLD_TAG_SEARCH
static int		FindItems(Tcl_Interp *interp, TkCanvas *canvasPtr,
			    int argc, Tcl_Obj *const *argv,
			    Tcl_Obj *newTagObj, int first);
#else /* USE_OLD_TAG_SEARCH */
static int		FindItems(Tcl_Interp *interp, TkCanvas *canvasPtr,
			    int argc, Tcl_Obj *const *argv,
			    Tcl_Obj *newTagObj, int first,
			    TagSearch **searchPtrPtr);
#endif /* USE_OLD_TAG_SEARCH */
static int		FindArea(Tcl_Interp *interp, TkCanvas *canvasPtr,
			    Tcl_Obj *const *argv, Tk_Uid uid, int enclosed);
static double		GridAlign(double coord, double spacing);
static const char**	TkGetStringsFromObjs(int argc, Tcl_Obj *const *objv);
static void		InitCanvas(void);
#ifdef USE_OLD_TAG_SEARCH
static Tk_Item *	NextItem(TagSearch *searchPtr);
#endif /* USE_OLD_TAG_SEARCH */
static void		PickCurrentItem(TkCanvas *canvasPtr, XEvent *eventPtr);
static Tcl_Obj *	ScrollFractions(int screen1,
			    int screen2, int object1, int object2);
#ifdef USE_OLD_TAG_SEARCH
static void		RelinkItems(TkCanvas *canvasPtr,
			    Tcl_Obj *tag, Tk_Item *prevPtr);
static Tk_Item *	StartTagSearch(TkCanvas *canvasPtr,
			    Tcl_Obj *tag, TagSearch *searchPtr);
#else /* USE_OLD_TAG_SEARCH */
static int		RelinkItems(TkCanvas *canvasPtr, Tcl_Obj *tag,
			    Tk_Item *prevPtr, TagSearch **searchPtrPtr);
static void 		TagSearchExprInit(TagSearchExpr **exprPtrPtr);
static void		TagSearchExprDestroy(TagSearchExpr *expr);
static void		TagSearchDestroy(TagSearch *searchPtr);
static int		TagSearchScan(TkCanvas *canvasPtr,
			    Tcl_Obj *tag, TagSearch **searchPtrPtr);
static int		TagSearchScanExpr(Tcl_Interp *interp,
			    TagSearch *searchPtr, TagSearchExpr *expr);
static int		TagSearchEvalExpr(TagSearchExpr *expr,
			    Tk_Item *itemPtr);
static Tk_Item *	TagSearchFirst(TagSearch *searchPtr);
static Tk_Item *	TagSearchNext(TagSearch *searchPtr);
#endif /* USE_OLD_TAG_SEARCH */

/*
 * The structure below defines canvas class behavior by means of functions
 * that can be invoked from generic window code.
 */

static const Tk_ClassProcs canvasClass = {
    sizeof(Tk_ClassProcs),	/* size */
    CanvasWorldChanged,		/* worldChangedProc */
    NULL,					/* createProc */
    NULL					/* modalProc */
};

/*
 * Macros that significantly simplify all code that finds items.
 */

#ifdef USE_OLD_TAG_SEARCH
#define FIRST_CANVAS_ITEM_MATCHING(objPtr,searchPtrPtr,errorExitClause) \
    itemPtr = StartTagSearch(canvasPtr,(objPtr),&search)
#define FOR_EVERY_CANVAS_ITEM_MATCHING(objPtr,searchPtrPtr,errorExitClause) \
    for (itemPtr = StartTagSearch(canvasPtr, (objPtr), &search); \
	    itemPtr != NULL; itemPtr = NextItem(&search))
#define FIND_ITEMS(objPtr, n) \
    FindItems(interp, canvasPtr, objc, objv, (objPtr), (n))
#define RELINK_ITEMS(objPtr, itemPtr) \
    RelinkItems(canvasPtr, (objPtr), (itemPtr))
#else /* USE_OLD_TAG_SEARCH */
#define FIRST_CANVAS_ITEM_MATCHING(objPtr,searchPtrPtr,errorExitClause) \
    if ((result=TagSearchScan(canvasPtr,(objPtr),(searchPtrPtr))) != TCL_OK){ \
	errorExitClause; \
    } \
    itemPtr = TagSearchFirst(*(searchPtrPtr));
#define FOR_EVERY_CANVAS_ITEM_MATCHING(objPtr,searchPtrPtr,errorExitClause) \
    if ((result=TagSearchScan(canvasPtr,(objPtr),(searchPtrPtr))) != TCL_OK){ \
	errorExitClause; \
    } \
    for (itemPtr = TagSearchFirst(*(searchPtrPtr)); \
	    itemPtr != NULL; itemPtr = TagSearchNext(*(searchPtrPtr)))
#define FIND_ITEMS(objPtr, n) \
    FindItems(interp, canvasPtr, objc, objv, (objPtr), (n), &searchPtr)
#define RELINK_ITEMS(objPtr, itemPtr) \
    result = RelinkItems(canvasPtr, (objPtr), (itemPtr), &searchPtr)
#endif /* USE_OLD_TAG_SEARCH */

/*
 * ----------------------------------------------------------------------
 *
 * AlwaysRedraw, ItemConfigure, ItemCoords, etc. --
 *
 *	Helper functions that make access to canvas item functions simpler.
513
514
515
516
517
518
519
520

521
522
523
524
525

526
527
528
529
530
531
532
463
464
465
466
467
468
469

470
471
472
473
474

475
476
477
478
479
480
481
482







-
+




-
+







    int screenX1, int screenY1,
    int width, int height)
{
    itemPtr->typePtr->displayProc((Tk_Canvas) canvasPtr, itemPtr,
	    canvasPtr->display, pixmap, screenX1, screenY1, width, height);
}

static inline int
static int
ItemIndex(
    TkCanvas *canvasPtr,
    Tk_Item *itemPtr,
    Tcl_Obj *objPtr,
    int *indexPtr)
    TkSizeT *indexPtr)
{
    Tcl_Interp *interp = canvasPtr->interp;

    if (itemPtr->typePtr->indexProc == NULL) {
	return TCL_OK;
    } else if (itemPtr->typePtr->alwaysRedraw & TK_CONFIG_OBJS) {
	return itemPtr->typePtr->indexProc(interp, (Tk_Canvas) canvasPtr,
609
610
611
612
613
614
615
































































































616
617
618
619
620
621
622
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    Tk_Item *itemPtr,
    double xDelta,
    double yDelta)
{
    itemPtr->typePtr->translateProc((Tk_Canvas) canvasPtr, itemPtr,
	    xDelta, yDelta);
}

static inline void
ItemRotate(
    TkCanvas *canvasPtr,
    Tk_Item *itemPtr,
    double x,
    double y,
    double angleRadians)
{
    if (itemPtr->typePtr->rotateProc != NULL) {
	itemPtr->typePtr->rotateProc((Tk_Canvas) canvasPtr,
		itemPtr, x, y, angleRadians);
    } else {
	DefaultRotateImplementation(canvasPtr, itemPtr, x, y, angleRadians);
    }
}

/*
 *--------------------------------------------------------------
 *
 * DefaultRotateImplementation --
 *
 *	The default implementation of the rotation operation, used when items
 *	do not provide their own version.
 *
 *--------------------------------------------------------------
 */

static void
DefaultRotateImplementation(
    TkCanvas *canvasPtr,
    Tk_Item *itemPtr,
    double x,
    double y,
    double angleRadians)
{
    int objc, i, ok = 1;
    Tcl_Obj **objv, **newObjv;
    double *coordv;
    double s = sin(angleRadians);
    double c = cos(angleRadians);
    Tcl_Interp *interp = canvasPtr->interp;

    /*
     * Get the coordinates out of the item.
     */

    if (ItemCoords(canvasPtr, itemPtr, 0, NULL) == TCL_OK &&
	    Tcl_ListObjGetElements(NULL, Tcl_GetObjResult(interp),
		    &objc, &objv) == TCL_OK) {
	coordv = (double *) ckalloc(sizeof(double) * objc);
	for (i=0 ; i<objc ; i++) {
	    if (Tcl_GetDoubleFromObj(NULL, objv[i], &coordv[i]) != TCL_OK) {
		ok = 0;
		break;
	    }
	}
	if (ok) {
	    /*
	     * Apply the rotation.
	     */

	    for (i=0 ; i<objc ; i+=2) {
		double px = coordv[i+0] - x;
		double py = coordv[i+1] - y;
		double nx = px * c - py * s;
		double ny = px * s + py * c;

		coordv[i+0] = nx + x;
		coordv[i+1] = ny + y;
	    }

	    /*
	     * Write the coordinates back into the item.
	     */

	    newObjv = (Tcl_Obj **) ckalloc(sizeof(Tcl_Obj *) * objc);
	    for (i=0 ; i<objc ; i++) {
		newObjv[i] = Tcl_NewDoubleObj(coordv[i]);
		Tcl_IncrRefCount(newObjv[i]);
	    }
	    ItemCoords(canvasPtr, itemPtr, objc, newObjv);
	    for (i=0 ; i<objc ; i++) {
		Tcl_DecrRefCount(newObjv[i]);
	    }
	    ckfree((char *) newObjv);
	}
	ckfree((char *) coordv);
    }

    /*
     * The interpreter result was (probably) modified above; reset it.
     */

    Tcl_ResetResult(interp);
}

/*
 *--------------------------------------------------------------
 *
 * Tk_CanvasObjCmd --
 *
 *	This function is invoked to process the "canvas" Tcl command. See the
634
635
636
637
638
639
640
641

642
643
644
645
646
647
648
680
681
682
683
684
685
686

687
688
689
690
691
692
693
694







-
+







int
Tk_CanvasObjCmd(
    ClientData clientData,	/* Main window associated with interpreter. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    Tcl_Obj *const argv[])	/* Argument objects. */
{
    Tk_Window tkwin = clientData;
    Tk_Window tkwin = (Tk_Window)clientData;
    TkCanvas *canvasPtr;
    Tk_Window newWin;

    if (typeList == NULL) {
	InitCanvas();
    }

658
659
660
661
662
663
664
665

666
667
668
669
670
671
672
704
705
706
707
708
709
710

711
712
713
714
715
716
717
718







-
+








    /*
     * Initialize fields that won't be initialized by ConfigureCanvas, or
     * which ConfigureCanvas expects to have reasonable values (e.g. resource
     * pointers).
     */

    canvasPtr = ckalloc(sizeof(TkCanvas));
    canvasPtr = (TkCanvas *)ckalloc(sizeof(TkCanvas));
    canvasPtr->tkwin = newWin;
    canvasPtr->display = Tk_Display(newWin);
    canvasPtr->interp = interp;
    canvasPtr->widgetCmd = Tcl_CreateObjCommand(interp,
	    Tk_PathName(canvasPtr->tkwin), CanvasWidgetCmd, canvasPtr,
	    CanvasCmdDeletedProc);
    canvasPtr->firstItemPtr = NULL;
682
683
684
685
686
687
688
689
690


691
692
693
694
695
696
697
728
729
730
731
732
733
734


735
736
737
738
739
740
741
742
743







-
-
+
+







    canvasPtr->width = None;
    canvasPtr->height = None;
    canvasPtr->confine = 0;
    canvasPtr->textInfo.selBorder = NULL;
    canvasPtr->textInfo.selBorderWidth = 0;
    canvasPtr->textInfo.selFgColorPtr = NULL;
    canvasPtr->textInfo.selItemPtr = NULL;
    canvasPtr->textInfo.selectFirst = -1;
    canvasPtr->textInfo.selectLast = -1;
    canvasPtr->textInfo.selectFirst = TCL_INDEX_NONE;
    canvasPtr->textInfo.selectLast = TCL_INDEX_NONE;
    canvasPtr->textInfo.anchorItemPtr = NULL;
    canvasPtr->textInfo.selectAnchor = 0;
    canvasPtr->textInfo.insertBorder = NULL;
    canvasPtr->textInfo.insertWidth = 0;
    canvasPtr->textInfo.insertBorderWidth = 0;
    canvasPtr->textInfo.focusItemPtr = NULL;
    canvasPtr->textInfo.gotFocus = 0;
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758

759
760
761
762
763
764
765
777
778
779
780
781
782
783

784

785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801

802
803
804
805
806
807
808
809







-

-

















-
+







    canvasPtr->flags = 0;
    canvasPtr->nextId = 1;
    canvasPtr->psInfo = NULL;
    canvasPtr->canvas_state = TK_STATE_NORMAL;
    canvasPtr->tsoffset.flags = 0;
    canvasPtr->tsoffset.xoffset = 0;
    canvasPtr->tsoffset.yoffset = 0;
#ifndef USE_OLD_TAG_SEARCH
    canvasPtr->bindTagExprs = NULL;
#endif
    Tcl_InitHashTable(&canvasPtr->idTable, TCL_ONE_WORD_KEYS);

    Tk_SetClass(canvasPtr->tkwin, "Canvas");
    Tk_SetClassProcs(canvasPtr->tkwin, &canvasClass, canvasPtr);
    Tk_CreateEventHandler(canvasPtr->tkwin,
	    ExposureMask|StructureNotifyMask|FocusChangeMask,
	    CanvasEventProc, canvasPtr);
    Tk_CreateEventHandler(canvasPtr->tkwin, KeyPressMask|KeyReleaseMask
	    |ButtonPressMask|ButtonReleaseMask|EnterWindowMask
	    |LeaveWindowMask|PointerMotionMask|VirtualEventMask,
	    CanvasBindProc, canvasPtr);
    Tk_CreateSelHandler(canvasPtr->tkwin, XA_PRIMARY, XA_STRING,
	    CanvasFetchSelection, canvasPtr, XA_STRING);
    if (ConfigureCanvas(interp, canvasPtr, argc-2, argv+2, 0) != TCL_OK) {
	goto error;
    }

    Tcl_SetObjResult(interp, TkNewWindowObj(canvasPtr->tkwin));
    Tcl_SetObjResult(interp, Tk_NewWindowObj(canvasPtr->tkwin));
    return TCL_OK;

  error:
    Tk_DestroyWindow(canvasPtr->tkwin);
    return TCL_ERROR;
}

784
785
786
787
788
789
790
791

792
793
794
795
796
797
798
799
800
801
802
803


804
805
806
807
808
809


810
811
812
813



814
815

816
817
818
819
820
821


822
823
824



825
826
827
828
829
830
831
832


833
834
835
836
837
838

839
840
841
842
843
844
845
828
829
830
831
832
833
834

835
836
837
838



839
840

841


842
843
844
845
846
847


848
849
850



851
852
853
854

855
856
857
858
859


860
861
862


863
864
865
866
867
868
869
870
871


872
873
874
875
876
877
878

879
880
881
882
883
884
885
886







-
+



-
-
-


-

-
-
+
+




-
-
+
+

-
-
-
+
+
+

-
+




-
-
+
+

-
-
+
+
+






-
-
+
+





-
+







static int
CanvasWidgetCmd(
    ClientData clientData,	/* Information about canvas widget. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    TkCanvas *canvasPtr = clientData;
    TkCanvas *canvasPtr = (TkCanvas *)clientData;
    int c, result;
    Tk_Item *itemPtr = NULL;	/* Initialization needed only to prevent
				 * compiler warning. */
#ifdef USE_OLD_TAG_SEARCH
    TagSearch search;
#else /* USE_OLD_TAG_SEARCH */
    TagSearch *searchPtr = NULL;/* Allocated by first TagSearchScan, freed by
				 * TagSearchDestroy */
#endif /* USE_OLD_TAG_SEARCH */

    int index;
    static const char *const optionStrings[] = {
    int idx;
    static const char *const canvasOptionStrings[] = {
	"addtag",	"bbox",		"bind",		"canvasx",
	"canvasy",	"cget",		"configure",	"coords",
	"create",	"dchars",	"delete",	"dtag",
	"find",		"focus",	"gettags",	"icursor",
	"imove",	"index",	"insert",	"itemcget",
	"itemconfigure",
        "image",	"imove",	"index",	"insert",
	"itemcget",	"itemconfigure",
	"lower",	"move",		"moveto",	"postscript",
	"raise",	"rchars",	"scale",	"scan",
	"select",	"type",		"xview",	"yview",
	NULL
	"raise",	"rchars",	"rotate",	"scale",
	"scan",		"select",	"type",		"xview",
	"yview",	NULL
    };
    enum options {
    enum canvasOptionStringsEnum {
	CANV_ADDTAG,	CANV_BBOX,	CANV_BIND,	CANV_CANVASX,
	CANV_CANVASY,	CANV_CGET,	CANV_CONFIGURE,	CANV_COORDS,
	CANV_CREATE,	CANV_DCHARS,	CANV_DELETE,	CANV_DTAG,
	CANV_FIND,	CANV_FOCUS,	CANV_GETTAGS,	CANV_ICURSOR,
	CANV_IMOVE,	CANV_INDEX,	CANV_INSERT,	CANV_ITEMCGET,
	CANV_ITEMCONFIGURE,
        CANV_IMAGE,	CANV_IMOVE,	CANV_INDEX,	CANV_INSERT,
	CANV_ITEMCGET,	CANV_ITEMCONFIGURE,
	CANV_LOWER,	CANV_MOVE,	CANV_MOVETO,	CANV_POSTSCRIPT,
	CANV_RAISE,	CANV_RCHARS,	CANV_SCALE,	CANV_SCAN,
	CANV_SELECT,	CANV_TYPE,	CANV_XVIEW,	CANV_YVIEW
	CANV_RAISE,	CANV_RCHARS,	CANV_ROTATE,	CANV_SCALE,
	CANV_SCAN,	CANV_SELECT,	CANV_TYPE,	CANV_XVIEW,
	CANV_YVIEW
    };

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
	return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0,
	    &index) != TCL_OK) {
    if (Tcl_GetIndexFromObj(interp, objv[1], canvasOptionStrings, "option", 0,
	    &idx) != TCL_OK) {
	return TCL_ERROR;
    }
    Tcl_Preserve(canvasPtr);

    result = TCL_OK;
    switch ((enum options) index) {
    switch ((enum canvasOptionStringsEnum)idx) {
    case CANV_ADDTAG:
	if (objc < 4) {
	    Tcl_WrongNumArgs(interp, 2, objv, "tag searchCommand ?arg ...?");
	    result = TCL_ERROR;
	    goto done;
	}
	result = FIND_ITEMS(objv[2], 3);
884
885
886
887
888
889
890
891
892
893
894




895
896
897
898
899
900

901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951

952
953

954
955
956
957
958
959
960
961
962
963
964
965
966

967
968
969
970
971
972
973
974
975
976
977
978
979
980

981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
925
926
927
928
929
930
931




932
933
934
935
936
937
938
939
940

941
942
943
944
945
946
947
948
949
950
951
952
953
954





























955
956
957
958
959
960
961
962

963
964

965
966
967
968
969
970
971
972
973
974
975
976
977

978
979

980
981
982
983
984
985
986
987
988
989
990

991
992
993
994
995
996
997
998

999
1000
1001
1002
1003
1004
1005







-
-
-
-
+
+
+
+





-
+













-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-








-
+

-
+












-
+

-











-
+







-







		    }
		}
	    }
	}
	if (gotAny) {
	    Tcl_Obj *resultObjs[4];

	    resultObjs[0] = Tcl_NewIntObj(x1);
	    resultObjs[1] = Tcl_NewIntObj(y1);
	    resultObjs[2] = Tcl_NewIntObj(x2);
	    resultObjs[3] = Tcl_NewIntObj(y2);
	    resultObjs[0] = Tcl_NewWideIntObj(x1);
	    resultObjs[1] = Tcl_NewWideIntObj(y1);
	    resultObjs[2] = Tcl_NewWideIntObj(x2);
	    resultObjs[3] = Tcl_NewWideIntObj(y2);
	    Tcl_SetObjResult(interp, Tcl_NewListObj(4, resultObjs));
	}
	break;
    }
    case CANV_BIND: {
	ClientData object;
	void *object;

	if ((objc < 3) || (objc > 5)) {
	    Tcl_WrongNumArgs(interp, 2, objv, "tagOrId ?sequence? ?command?");
	    result = TCL_ERROR;
	    goto done;
	}

	/*
	 * Figure out what object to use for the binding (individual item vs.
	 * tag).
	 */

	object = NULL;
#ifdef USE_OLD_TAG_SEARCH
	if (isdigit(UCHAR(Tcl_GetString(objv[2])[0]))) {
	    int id;
	    char *end;
	    Tcl_HashEntry *entryPtr;

	    id = strtoul(Tcl_GetString(objv[2]), &end, 0);
	    if (*end != 0) {
		goto bindByTag;
	    }
	    entryPtr = Tcl_FindHashEntry(&canvasPtr->idTable, (char *) id);
	    if (entryPtr != NULL) {
		itemPtr = Tcl_GetHashValue(entryPtr);
		object = itemPtr;
	    }

	    if (object == NULL) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"item \"%s\" doesn't exist", Tcl_GetString(objv[2])));
		Tcl_SetErrorCode(interp, "TK", "LOOKUP", "CANVAS_ITEM",
			Tcl_GetString(objv[2]), NULL);
		result = TCL_ERROR;
		goto done;
	    }
	} else {
	bindByTag:
	    object = Tk_GetUid(Tcl_GetString(objv[2]));
	}
#else /* USE_OLD_TAG_SEARCH */
	result = TagSearchScan(canvasPtr, objv[2], &searchPtr);
	if (result != TCL_OK) {
	    goto done;
	}
	if (searchPtr->type == SEARCH_TYPE_ID) {
	    Tcl_HashEntry *entryPtr;

	    entryPtr = Tcl_FindHashEntry(&canvasPtr->idTable,
		    (char *) INT2PTR(searchPtr->id));
		    INT2PTR(searchPtr->id));
	    if (entryPtr != NULL) {
		itemPtr = Tcl_GetHashValue(entryPtr);
		itemPtr = (Tk_Item *)Tcl_GetHashValue(entryPtr);
		object = itemPtr;
	    }

	    if (object == 0) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"item \"%s\" doesn't exist", Tcl_GetString(objv[2])));
		Tcl_SetErrorCode(interp, "TK", "LOOKUP", "CANVAS_ITEM",
			Tcl_GetString(objv[2]), NULL);
		result = TCL_ERROR;
		goto done;
	    }
	} else {
    	    object = (ClientData) searchPtr->expr->uid;
	    object = (char *)searchPtr->expr->uid;
	}
#endif /* USE_OLD_TAG_SEARCH */

	/*
	 * Make a binding table if the canvas doesn't already have one.
	 */

	if (canvasPtr->bindingTable == NULL) {
	    canvasPtr->bindingTable = Tk_CreateBindingTable(interp);
	}

	if (objc == 5) {
	    int append = 0;
	    unsigned long mask;
	    unsigned int mask;
	    const char *argv4 = Tcl_GetString(objv[4]);

	    if (argv4[0] == 0) {
		result = Tk_DeleteBinding(interp, canvasPtr->bindingTable,
			object, Tcl_GetString(objv[3]));
		goto done;
	    }
#ifndef USE_OLD_TAG_SEARCH
	    if (searchPtr->type == SEARCH_TYPE_EXPR) {
		/*
		 * If new tag expression, then insert in linked list.
		 */

	    	TagSearchExpr *expr, **lastPtr;

1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030

1031
1032
1033
1034
1035
1036
1037
1022
1023
1024
1025
1026
1027
1028

1029
1030
1031
1032
1033
1034
1035
1036
1037
1038

1039
1040
1041
1042
1043
1044
1045
1046







-










-
+







		     * Flag in TagSearch that expr has changed ownership so
		     * that TagSearchDestroy doesn't try to free it.
		     */

		    searchPtr->expr = NULL;
		}
	    }
#endif /* not USE_OLD_TAG_SEARCH */
	    if (argv4[0] == '+') {
		argv4++;
		append = 1;
	    }
	    mask = Tk_CreateBinding(interp, canvasPtr->bindingTable,
		    object, Tcl_GetString(objv[3]), argv4, append);
	    if (mask == 0) {
		result = TCL_ERROR;
		goto done;
	    }
	    if (mask & ~(unsigned long)(ButtonMotionMask|Button1MotionMask
	    if (mask & ~(ButtonMotionMask|Button1MotionMask
		    |Button2MotionMask|Button3MotionMask|Button4MotionMask
		    |Button5MotionMask|ButtonPressMask|ButtonReleaseMask
		    |EnterWindowMask|LeaveWindowMask|KeyPressMask
		    |KeyReleaseMask|PointerMotionMask|VirtualEventMask)) {
		Tk_DeleteBinding(interp, canvasPtr->bindingTable,
			object, Tcl_GetString(objv[3]));
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
1181
1182
1183
1184
1185
1186
1187
1188

1189
1190
1191
1192
1193
1194
1195
1190
1191
1192
1193
1194
1195
1196

1197
1198
1199
1200
1201
1202
1203
1204







-
+







	 * Make a temporary object here that we can reuse for all the
	 * modifications in the loop.
	 */

	tmpObj = Tcl_NewListObj(2, objv+4);

	FOR_EVERY_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto doneImove) {
	    int index;
	    TkSizeT index;
	    int x1, x2, y1, y2;
	    int dontRedraw1, dontRedraw2;

	    /*
	     * The TK_MOVABLE_POINTS flag should only be set for types that
	     * support the same semantics of index, dChars and insert methods
	     * as lines and canvases.
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245

1246
1247
1248
1249
1250
1251
1252

1253
1254
1255
1256
1257
1258
1259
1260
1243
1244
1245
1246
1247
1248
1249

1250
1251
1252

1253
1254
1255
1256
1257
1258
1259

1260

1261
1262
1263
1264
1265
1266
1267







-



-
+






-
+
-







    doneImove:
	Tcl_DecrRefCount(tmpObj);
	break;
    }
    case CANV_CREATE: {
	Tk_ItemType *typePtr;
	Tk_ItemType *matchPtr = NULL;
	Tk_Item *itemPtr;
	int isNew = 0;
	Tcl_HashEntry *entryPtr;
	const char *arg;
	size_t length;
	TkSizeT length;

	if (objc < 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "type coords ?arg ...?");
	    result = TCL_ERROR;
	    goto done;
	}
	arg = Tcl_GetString(objv[2]);
	arg = TkGetStringFromObj(objv[2], &length);
	length = 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
	 * impossible.
	 */
1293
1294
1295
1296
1297
1298
1299
1300
1301


1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318

1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332

1333
1334
1335
1336

1337
1338
1339
1340
1341
1342
1343
1300
1301
1302
1303
1304
1305
1306


1307
1308

1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323

1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337

1338
1339
1340
1341

1342
1343
1344
1345
1346
1347
1348
1349







-
-
+
+
-















-
+













-
+



-
+








	    Tcl_WrongNumArgs(interp, 3, objv, "coords ?arg ...?");
	    result = TCL_ERROR;
	    goto done;
	}

	typePtr = matchPtr;
	itemPtr = ckalloc(typePtr->itemSize);
	itemPtr->id = canvasPtr->nextId;
	itemPtr = (Tk_Item *)ckalloc(typePtr->itemSize);
	itemPtr->id = canvasPtr->nextId++;
	canvasPtr->nextId++;
	itemPtr->tagPtr = itemPtr->staticTagSpace;
	itemPtr->tagSpace = TK_TAG_SPACE;
	itemPtr->numTags = 0;
	itemPtr->typePtr = typePtr;
	itemPtr->state = TK_STATE_NULL;
	itemPtr->redraw_flags = 0;

	if (ItemCreate(canvasPtr, itemPtr, objc, objv) != TCL_OK) {
	    ckfree(itemPtr);
	    result = TCL_ERROR;
	    goto done;
	}

	itemPtr->nextPtr = NULL;
	entryPtr = Tcl_CreateHashEntry(&canvasPtr->idTable,
		(char *) INT2PTR(itemPtr->id), &isNew);
		INT2PTR(itemPtr->id), &isNew);
	Tcl_SetHashValue(entryPtr, itemPtr);
	itemPtr->prevPtr = canvasPtr->lastItemPtr;
	canvasPtr->hotPtr = itemPtr;
	canvasPtr->hotPrevPtr = canvasPtr->lastItemPtr;
	if (canvasPtr->lastItemPtr == NULL) {
	    canvasPtr->firstItemPtr = itemPtr;
	} else {
	    canvasPtr->lastItemPtr->nextPtr = itemPtr;
	}
	canvasPtr->lastItemPtr = itemPtr;
	itemPtr->redraw_flags |= FORCE_REDRAW;
	EventuallyRedrawItem(canvasPtr, itemPtr);
	canvasPtr->flags |= REPICK_NEEDED;
	Tcl_SetObjResult(interp, Tcl_NewIntObj(itemPtr->id));
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(itemPtr->id));
	break;
    }
    case CANV_DCHARS: {
	int first, last;
	TkSizeT first, last;
	int x1, x2, y1, y2;

	if ((objc != 4) && (objc != 5)) {
	    Tcl_WrongNumArgs(interp, 2, objv, "tagOrId first ?last?");
	    result = TCL_ERROR;
	    goto done;
	}
1390
1391
1392
1393
1394
1395
1396
1397

1398
1399
1400
1401
1402
1403
1404
1396
1397
1398
1399
1400
1401
1402

1403
1404
1405
1406
1407
1408
1409
1410







-
+







		    Tk_DeleteAllBindings(canvasPtr->bindingTable, itemPtr);
		}
		ItemDelete(canvasPtr, itemPtr);
		if (itemPtr->tagPtr != itemPtr->staticTagSpace) {
		    ckfree(itemPtr->tagPtr);
		}
		entryPtr = Tcl_FindHashEntry(&canvasPtr->idTable,
			(char *) INT2PTR(itemPtr->id));
			INT2PTR(itemPtr->id));
		Tcl_DeleteHashEntry(entryPtr);
		if (itemPtr->nextPtr != NULL) {
		    itemPtr->nextPtr->prevPtr = itemPtr->prevPtr;
		}
		if (itemPtr->prevPtr != NULL) {
		    itemPtr->prevPtr->nextPtr = itemPtr->nextPtr;
		}
1445
1446
1447
1448
1449
1450
1451
1452

1453
1454
1455
1456
1457
1458
1459
1451
1452
1453
1454
1455
1456
1457

1458
1459
1460
1461
1462
1463
1464
1465







-
+







	}
	if (objc == 4) {
	    tag = Tk_GetUid(Tcl_GetString(objv[3]));
	} else {
	    tag = Tk_GetUid(Tcl_GetString(objv[2]));
	}
	FOR_EVERY_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done) {
	    for (i = itemPtr->numTags-1; i >= 0; i--) {
	    for (i = (int)itemPtr->numTags-1; i >= 0; i--) {
		if (itemPtr->tagPtr[i] == tag) {

                    /*
                     * Don't shuffle the tags sequence: memmove the tags.
                     */

                    memmove((void *)(itemPtr->tagPtr + i),
1484
1485
1486
1487
1488
1489
1490
1491

1492
1493
1494
1495
1496
1497
1498
1490
1491
1492
1493
1494
1495
1496

1497
1498
1499
1500
1501
1502
1503
1504







-
+







	    Tcl_WrongNumArgs(interp, 2, objv, "?tagOrId?");
	    result = TCL_ERROR;
	    goto done;
	}
	itemPtr = canvasPtr->textInfo.focusItemPtr;
	if (objc == 2) {
	    if (itemPtr != NULL) {
		Tcl_SetObjResult(interp, Tcl_NewIntObj(itemPtr->id));
		Tcl_SetObjResult(interp, Tcl_NewWideIntObj(itemPtr->id));
	    }
	    goto done;
	}
	if (canvasPtr->textInfo.gotFocus) {
	    EventuallyRedrawItem(canvasPtr, itemPtr);
	}
	if (Tcl_GetString(objv[2])[0] == 0) {
1519
1520
1521
1522
1523
1524
1525
1526

1527
1528
1529
1530
1531
1532
1533
1534

1535
1536
1537
1538
1539
1540
1541
1525
1526
1527
1528
1529
1530
1531

1532
1533
1534
1535
1536
1537
1538
1539

1540
1541
1542
1543
1544
1545
1546
1547







-
+







-
+







	    goto done;
	}
	FIRST_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done);
	if (itemPtr != NULL) {
	    int i;
	    Tcl_Obj *resultObj = Tcl_NewObj();

	    for (i = 0; i < itemPtr->numTags; i++) {
	    for (i = 0; i < (int)itemPtr->numTags; i++) {
		Tcl_ListObjAppendElement(NULL, resultObj,
			Tcl_NewStringObj(itemPtr->tagPtr[i], -1));
	    }
	    Tcl_SetObjResult(interp, resultObj);
	}
	break;
    case CANV_ICURSOR: {
	int index;
	TkSizeT index;

	if (objc != 4) {
	    Tcl_WrongNumArgs(interp, 2, objv, "tagOrId index");
	    result = TCL_ERROR;
	    goto done;
	}
	FOR_EVERY_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done) {
1552
1553
1554
1555
1556
1557
1558
1559

1560
1561
1562
1563
1564
1565
1566
1558
1559
1560
1561
1562
1563
1564

1565
1566
1567
1568
1569
1570
1571
1572







-
+







		    && (canvasPtr->textInfo.cursorOn)) {
		EventuallyRedrawItem(canvasPtr, itemPtr);
	    }
	}
	break;
    }
    case CANV_INDEX: {
	int index;
	TkSizeT index;

	if (objc != 4) {
	    Tcl_WrongNumArgs(interp, 2, objv, "tagOrId string");
	    result = TCL_ERROR;
	    goto done;
	}
	FOR_EVERY_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done) {
1576
1577
1578
1579
1580
1581
1582
1583

1584
1585
1586
1587

1588
1589
1590
1591
1592
1593
1594
1582
1583
1584
1585
1586
1587
1588

1589
1590
1591
1592

1593
1594
1595
1596
1597
1598
1599
1600







-
+



-
+







	    result = TCL_ERROR;
	    goto done;
	}
	result = ItemIndex(canvasPtr, itemPtr, objv[3], &index);
	if (result != TCL_OK) {
	    goto done;
	}
	Tcl_SetObjResult(interp, Tcl_NewIntObj(index));
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(index));
	break;
    }
    case CANV_INSERT: {
	int beforeThis;
	TkSizeT beforeThis;
	int x1, x2, y1, y2;

	if (objc != 5) {
	    Tcl_WrongNumArgs(interp, 2, objv, "tagOrId beforeThis string");
	    result = TCL_ERROR;
	    goto done;
	}
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1658
1659
1660
1661
1662
1663
1664

1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680





1681
1682
1683
1684
1685
1686
1687







-
















-
-
-
-
-







	    }
	    if ((result != TCL_OK) || (objc < 5)) {
		break;
	    }
	}
	break;
    case CANV_LOWER: {
	Tk_Item *itemPtr;

	if ((objc != 3) && (objc != 4)) {
	    Tcl_WrongNumArgs(interp, 2, objv, "tagOrId ?belowThis?");
	    result = TCL_ERROR;
	    goto done;
	}

	/*
	 * First find the item just after which we'll insert the named items.
	 */

	if (objc == 3) {
	    itemPtr = NULL;
	} else {
	    FIRST_CANVAS_ITEM_MATCHING(objv[3], &searchPtr, goto done);
	    if (itemPtr == NULL) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"tagOrId \"%s\" doesn't match any items",
			Tcl_GetString(objv[3])));
		Tcl_SetErrorCode(interp, "TK", "CANVAS", "ITEM", NULL);
		result = TCL_ERROR;
		goto done;
	    }
	    itemPtr = itemPtr->prevPtr;
	}
	RELINK_ITEMS(objv[2], itemPtr);
	break;
    }
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815

1816
1817
1818
1819
1820
1821
1822
1796
1797
1798
1799
1800
1801
1802





1803
1804
1805
1806
1807
1808
1809

1810
1811
1812
1813
1814
1815
1816
1817







-
-
-
-
-







-
+







	    prevPtr = canvasPtr->lastItemPtr;
	} else {
	    prevPtr = NULL;
	    FOR_EVERY_CANVAS_ITEM_MATCHING(objv[3], &searchPtr, goto done) {
		prevPtr = itemPtr;
	    }
	    if (prevPtr == NULL) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"tagOrId \"%s\" doesn't match any items",
			Tcl_GetString(objv[3])));
		Tcl_SetErrorCode(interp, "TK", "CANVAS", "ITEM", NULL);
		result = TCL_ERROR;
		goto done;
	    }
	}
	RELINK_ITEMS(objv[2], prevPtr);
	break;
    }
    case CANV_RCHARS: {
	int first, last;
	TkSizeT first, last;
	int x1, x2, y1, y2;
	int dontRedraw1, dontRedraw2;

	if (objc != 6) {
	    Tcl_WrongNumArgs(interp, 2, objv, "tagOrId first last string");
	    result = TCL_ERROR;
	    goto done;
1857
1858
1859
1860
1861
1862
1863
























1864
1865
1866
1867
1868
1869
1870
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







            if (!(dontRedraw1 && dontRedraw2)) {
		Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,
			x1, y1, x2, y2);
		EventuallyRedrawItem(canvasPtr, itemPtr);
	    }
	    itemPtr->redraw_flags &= ~TK_ITEM_DONT_REDRAW;
	}
	break;
    }
    case CANV_ROTATE: {
	double x, y, angle;
	Tk_Canvas canvas = (Tk_Canvas) canvasPtr;

	if (objc != 6) {
	    Tcl_WrongNumArgs(interp, 2, objv, "tagOrId x y angle");
	    result = TCL_ERROR;
	    goto done;
	}
	if (Tk_CanvasGetCoordFromObj(interp, canvas, objv[3], &x) != TCL_OK ||
		Tk_CanvasGetCoordFromObj(interp, canvas, objv[4], &y) != TCL_OK ||
		Tcl_GetDoubleFromObj(interp, objv[5], &angle) != TCL_OK) {
	    result = TCL_ERROR;
	    goto done;
	}
	angle = angle * 3.1415927 / 180.0;
	FOR_EVERY_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done) {
	    EventuallyRedrawItem(canvasPtr, itemPtr);
	    ItemRotate(canvasPtr, itemPtr, x, y, angle);
	    EventuallyRedrawItem(canvasPtr, itemPtr);
	    canvasPtr->flags |= REPICK_NEEDED;
	}
	break;
    }
    case CANV_SCALE: {
	double xOrigin, yOrigin, xScale, yScale;

	if (objc != 7) {
	    Tcl_WrongNumArgs(interp, 2, objv,
1902
1903
1904
1905
1906
1907
1908
1909

1910
1911
1912


1913
1914
1915
1916
1917
1918
1919
1920

1921
1922
1923
1924
1925
1926
1927
1921
1922
1923
1924
1925
1926
1927

1928
1929


1930
1931
1932
1933
1934
1935
1936
1937
1938

1939
1940
1941
1942
1943
1944
1945
1946







-
+

-
-
+
+







-
+







	    "mark", "dragto", NULL
	};

	if (objc < 5) {
	    Tcl_WrongNumArgs(interp, 2, objv, "mark|dragto x y ?dragGain?");
	    result = TCL_ERROR;
	} else if (Tcl_GetIndexFromObj(interp, objv[2], optionStrings,
		"scan option", 0, &index) != TCL_OK) {
		"scan option", 0, &idx) != TCL_OK) {
	    result = TCL_ERROR;
	} else if ((objc != 5) && (objc != 5+index)) {
	    Tcl_WrongNumArgs(interp, 3, objv, index?"x y ?gain?":"x y");
	} else if ((objc != 5) && (objc != 5+idx)) {
	    Tcl_WrongNumArgs(interp, 3, objv, idx?"x y ?gain?":"x y");
	    result = TCL_ERROR;
	} else if ((Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK)
		|| (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK)){
	    result = TCL_ERROR;
	} else if ((objc == 6) &&
		(Tcl_GetIntFromObj(interp, objv[5], &gain) != TCL_OK)) {
	    result = TCL_ERROR;
	} else if (!index) {
	} else if (!idx) {
	    canvasPtr->scanX = x;
	    canvasPtr->scanXOrigin = canvasPtr->xOrigin;
	    canvasPtr->scanY = y;
	    canvasPtr->scanYOrigin = canvasPtr->yOrigin;
	} else {
	    int newXOrigin, newYOrigin, tmp;

1937
1938
1939
1940
1941
1942
1943

1944

1945
1946
1947
1948
1949
1950
1951
1956
1957
1958
1959
1960
1961
1962
1963

1964
1965
1966
1967
1968
1969
1970
1971







+
-
+







		    - canvasPtr->scrollY1;
	    newYOrigin = canvasPtr->scrollY1 + tmp;
	    CanvasSetOrigin(canvasPtr, newXOrigin, newYOrigin);
	}
	break;
    }
    case CANV_SELECT: {
	TkSizeT index;
	int index, optionindex;
	int optionindex;
	static const char *const optionStrings[] = {
	    "adjust", "clear", "from", "item", "to", NULL
	};
	enum options {
	    CANV_ADJUST, CANV_CLEAR, CANV_FROM, CANV_ITEM, CANV_TO
	};

1986
1987
1988
1989
1990
1991
1992
1993
1994


1995
1996
1997
1998
1999
2000
2001
2006
2007
2008
2009
2010
2011
2012


2013
2014
2015
2016
2017
2018
2019
2020
2021







-
-
+
+







	case CANV_ADJUST:
	    if (objc != 5) {
		Tcl_WrongNumArgs(interp, 3, objv, "tagOrId index");
		result = TCL_ERROR;
		goto done;
	    }
	    if (canvasPtr->textInfo.selItemPtr == itemPtr) {
		if (index < (canvasPtr->textInfo.selectFirst
			+ canvasPtr->textInfo.selectLast)/2) {
		if (index + 1 <= ((canvasPtr->textInfo.selectFirst
			+ canvasPtr->textInfo.selectLast)/2)) {
		    canvasPtr->textInfo.selectAnchor =
			    canvasPtr->textInfo.selectLast + 1;
		} else {
		    canvasPtr->textInfo.selectAnchor =
			    canvasPtr->textInfo.selectFirst;
		}
	    }
2023
2024
2025
2026
2027
2028
2029
2030

2031
2032
2033
2034
2035
2036
2037
2043
2044
2045
2046
2047
2048
2049

2050
2051
2052
2053
2054
2055
2056
2057







-
+







	    if (objc != 3) {
		Tcl_WrongNumArgs(interp, 3, objv, NULL);
		result = TCL_ERROR;
		goto done;
	    }
	    if (canvasPtr->textInfo.selItemPtr != NULL) {
		Tcl_SetObjResult(interp,
			Tcl_NewIntObj(canvasPtr->textInfo.selItemPtr->id));
			Tcl_NewWideIntObj(canvasPtr->textInfo.selItemPtr->id));
	    }
	    break;
	case CANV_TO:
	    if (objc != 5) {
		Tcl_WrongNumArgs(interp, 2, objv, "tagOrId index");
		result = TCL_ERROR;
		goto done;
2140
2141
2142
2143
2144
2145
2146



2147
2148







































2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169


2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209

2210

2211
2212
2213
2214
2215
2216
2217







+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-

-







			* (Tk_Height(canvasPtr->tkwin) - 2*canvasPtr->inset));
	    }
	    break;
	}
	CanvasSetOrigin(canvasPtr, canvasPtr->xOrigin, newY);
	break;
    }
    case CANV_IMAGE: {
        Tk_PhotoHandle photohandle;
        int subsample = 1, zoom = 1;
    }


        if (objc < 3 || objc > 5) {
            Tcl_WrongNumArgs(interp, 2, objv, "imagename ?subsample? ?zoom?");
            result = TCL_ERROR;
            goto done;
        }

        if ((photohandle = Tk_FindPhoto(interp, Tcl_GetString(objv[2]) )) == 0) {
            result = TCL_ERROR;
            goto done;
        }

        /*
         * If we are given a subsample or a zoom then grab them.
         */

        if (objc >= 4 && Tcl_GetIntFromObj(interp, objv[3], &subsample) != TCL_OK) {
            result = TCL_ERROR;
            goto done;
        }
        if (objc >= 5 && Tcl_GetIntFromObj(interp, objv[4], &zoom) != TCL_OK) {
            result = TCL_ERROR;
            goto done;
        }

        /*
         * Set the image size to zero, which allows the DrawCanvas() function
         * to expand the image automatically when it copies the pixmap into it.
         */

        if (Tk_PhotoSetSize(interp, photohandle, 0, 0) != TCL_OK) {
            result = TCL_ERROR;
            goto done;
        }

        result = DrawCanvas(interp, clientData, photohandle, subsample, zoom);
    }
    }

  done:
#ifndef USE_OLD_TAG_SEARCH
    TagSearchDestroy(searchPtr);
#endif /* not USE_OLD_TAG_SEARCH */
    Tcl_Release(canvasPtr);
    return result;
}

/*
 *----------------------------------------------------------------------
 *
2170
2171
2172
2173
2174
2175
2176
2177

2178
2179

2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2228
2229
2230
2231
2232
2233
2234

2235
2236

2237
2238

2239

2240
2241
2242
2243
2244
2245
2246







-
+

-
+

-

-







 *	Everything associated with the canvas is freed up.
 *
 *----------------------------------------------------------------------
 */

static void
DestroyCanvas(
    char *memPtr)		/* Info about canvas widget. */
    void *memPtr)		/* Info about canvas widget. */
{
    TkCanvas *canvasPtr = (TkCanvas *) memPtr;
    TkCanvas *canvasPtr = (TkCanvas *)memPtr;
    Tk_Item *itemPtr;
#ifndef USE_OLD_TAG_SEARCH
    TagSearchExpr *expr, *next;
#endif

    /*
     * Free up all of the items in the canvas.
     */

    for (itemPtr = canvasPtr->firstItemPtr; itemPtr != NULL;
	    itemPtr = canvasPtr->firstItemPtr) {
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2257
2258
2259
2260
2261
2262
2263

2264
2265
2266
2267
2268
2269

2270
2271
2272
2273
2274
2275
2276







-






-







     * Tk_FreeOptions handle all the standard option-related stuff.
     */

    Tcl_DeleteHashTable(&canvasPtr->idTable);
    if (canvasPtr->pixmapGC != NULL) {
	Tk_FreeGC(canvasPtr->display, canvasPtr->pixmapGC);
    }
#ifndef USE_OLD_TAG_SEARCH
    expr = canvasPtr->bindTagExprs;
    while (expr) {
	next = expr->next;
	TagSearchExprDestroy(expr);
	expr = next;
    }
#endif /* USE_OLD_TAG_SEARCH */
    Tcl_DeleteTimerHandler(canvasPtr->insertBlinkHandler);
    if (canvasPtr->bindingTable != NULL) {
	Tk_DeleteBindingTable(canvasPtr->bindingTable);
    }
    Tk_FreeOptions(configSpecs, (char *) canvasPtr, canvasPtr->display, 0);
    canvasPtr->tkwin = NULL;
    ckfree(canvasPtr);
2409
2410
2411
2412
2413
2414
2415
2416

2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431














































































































































































































































































































































































































































































































2432
2433
2434
2435
2436
2437
2438
2463
2464
2465
2466
2467
2468
2469

2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986







-
+















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







 *----------------------------------------------------------------------
 */

static void
CanvasWorldChanged(
    ClientData instanceData)	/* Information about widget. */
{
    TkCanvas *canvasPtr = instanceData;
    TkCanvas *canvasPtr = (TkCanvas *)instanceData;
    Tk_Item *itemPtr;

    itemPtr = canvasPtr->firstItemPtr;
    for ( ; itemPtr != NULL; itemPtr = itemPtr->nextPtr) {
	if (ItemConfigure(canvasPtr, itemPtr, 0, NULL) != TCL_OK) {
	    Tcl_ResetResult(canvasPtr->interp);
	}
    }
    canvasPtr->flags |= REPICK_NEEDED;
    Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,
	    canvasPtr->xOrigin, canvasPtr->yOrigin,
	    canvasPtr->xOrigin + Tk_Width(canvasPtr->tkwin),
	    canvasPtr->yOrigin + Tk_Height(canvasPtr->tkwin));
}

/*
 *----------------------------------------------------------------------
 *
 * DecomposeMaskToShiftAndBits --
 *
 *      Given a 32 bit pixel mask, we find the position of the lowest bit and the
 *      width of the mask bits.
 *
 * Results:
 *	None.
 *
 * Side effects:
*       None.
 *
 *----------------------------------------------------------------------
 */
static void
DecomposeMaskToShiftAndBits(
    unsigned int mask,     /* The pixel mask to examine */
    int *shift,             /* Where to put the shift count (position of lowest bit) */
    int *bits)              /* Where to put the bit count (width of the pixel mask) */
{
    int i;

    *shift = 0;
    *bits = 0;

    /*
     * Find the lowest '1' bit in the mask.
     */

    for (i = 0; i < 32; ++i) {
        if (mask & 1 << i)
            break;
    }
    if (i < 32) {
        *shift = i;

        /*
        * Now find the next '0' bit and the width of the mask.
        */

        for ( ; i < 32; ++i) {
            if ((mask & 1 << i) == 0)
                break;
            else
                ++*bits;
        }

        /*
        * Limit to the top 8 bits if the mask was wider than 8.
        */

        if (*bits > 8) {
            *shift += *bits - 8;
            *bits = 8;
        }
    }
}

/*
 *----------------------------------------------------------------------
 *
 * DrawCanvas --
 *
 *      This function draws the contents of a canvas into the given Photo image.
 *      This function is called from the widget "image" subcommand.
 *      The canvas does not need to be mapped (one of it's ancestors must be)
 *      in order for this function to work.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *      Canvas contents from within the -scrollregion or widget size are rendered
 *      into the Photo. Any errors are left in the result.
 *
 *----------------------------------------------------------------------
 */

#define OVERDRAW_PIXELS 32        /* How much larger we make the pixmap
                                   * that the canvas objects are drawn into */

/* From stackoverflow.com/questions/2100331/c-macro-definition-to-determine-big-endian-or-little-endian-machine */
#define IS_BIG_ENDIAN (*(unsigned short *)"\0\xff" < 0x100)

#define BYTE_SWAP16(n) ((((unsigned short)n)>>8) | (((unsigned short)n)<<8))
#define BYTE_SWAP32(n) (((n>>24)&0x000000FF) | ((n<<8)&0x00FF0000) | ((n>>8)&0x0000FF00) | ((n<<24)&0xFF000000))

static int
DrawCanvas(
    Tcl_Interp *interp,           /* As passed to the widget command, and we will leave errors here */
    ClientData clientData,
    Tk_PhotoHandle photohandle,   /* The photo we are rendering into */
    int subsample,                /* If either subsample or zoom are not 1 then we call Tk_PhotoPutZoomedBlock() */
    int zoom)
{
    TkCanvas *canvasPtr = (TkCanvas *)clientData;
    Tk_Window tkwin;
    Display *displayPtr;
    Tk_PhotoImageBlock blockPtr = {0,0,0,0,0,{0,0,0,0}};
    Window wid;
    Tk_Item *itemPtr;
    Pixmap pixmap = 0;
    XImage *ximagePtr = NULL;
    Visual *visualPtr;
    GC xgc = 0;
    XGCValues xgcValues;
    int canvasX1, canvasY1, canvasX2, canvasY2, cWidth, cHeight,
        pixmapX1, pixmapY1, pixmapX2, pixmapY2, pmWidth, pmHeight,
        bitsPerPixel, bytesPerPixel, x, y, result = TCL_OK,
        rshift, gshift, bshift, rbits, gbits, bbits;

#ifdef DEBUG_DRAWCANVAS
    char buffer[128];
#endif

    if ((tkwin = canvasPtr->tkwin) == NULL) {
        Tcl_AppendResult(interp, "canvas tkwin is NULL!", NULL);
        result = TCL_ERROR;
        goto done;
    }

    /*
     * If this canvas is unmapped, then we won't have a window id, so we will
     * try the ancestors of the canvas until we find a window that has a
     * valid window id. The Tk_GetPixmap() call requires a valid window id.
     */

    do {

        if ((displayPtr = Tk_Display(tkwin)) == NULL) {
            Tcl_AppendResult(interp, "canvas (or parent) display is NULL!", NULL);
            result = TCL_ERROR;
            goto done;
        }

        if ((wid = Tk_WindowId(tkwin)) != 0) {
            continue;
        }

        if ((tkwin = Tk_Parent(tkwin)) == NULL) {
            Tcl_AppendResult(interp, "canvas has no parent with a valid window id! Is the toplevel window mapped?", NULL);
            result = TCL_ERROR;
            goto done;
        }

    } while (wid == 0);

    bitsPerPixel = Tk_Depth(tkwin);
    visualPtr = Tk_Visual(tkwin);

    if (subsample == 0) {
        Tcl_AppendResult(interp, "subsample cannot be zero", NULL);
        result = TCL_ERROR;
        goto done;
    }

    /*
    * Scan through the item list, registering the bounding box for all items
    * that didn't do that for the final coordinates yet. This can be
    * determined by the FORCE_REDRAW flag.
    */

    for (itemPtr = canvasPtr -> firstItemPtr; itemPtr != NULL;
            itemPtr = itemPtr -> nextPtr) {
        if (itemPtr -> redraw_flags & FORCE_REDRAW) {
            itemPtr -> redraw_flags &= ~FORCE_REDRAW;
            EventuallyRedrawItem(canvasPtr, itemPtr);
            itemPtr -> redraw_flags &= ~FORCE_REDRAW;
        }
    }

    /*
     * The DisplayCanvas() function works out the region that needs redrawing,
     * but we don't do this. We grab the whole scrollregion or canvas window
     * area. If we have a defined -scrollregion we use that as the drawing
     * region, otherwise use the canvas window height and width with an origin
     * of 0,0.
     */
    if (canvasPtr->scrollX1 != 0 || canvasPtr->scrollY1 != 0 ||
            canvasPtr->scrollX2 != 0 || canvasPtr->scrollY2 != 0) {

        canvasX1 = canvasPtr->scrollX1;
        canvasY1 = canvasPtr->scrollY1;
        canvasX2 = canvasPtr->scrollX2;
        canvasY2 = canvasPtr->scrollY2;
        cWidth = canvasX2 - canvasX1 + 1;
        cHeight = canvasY2 - canvasY1 + 1;

    } else {

        cWidth = Tk_Width(tkwin);
        cHeight = Tk_Height(tkwin);
        canvasX1 = 0;
        canvasY1 = 0;
        canvasX2 = canvasX1 + cWidth - 1;
        canvasY2 = canvasY1 + cHeight - 1;
    }

    /*
     * Allocate a pixmap to draw into. We add OVERDRAW_PIXELS in the same way
     * that DisplayCanvas() does to avoid problems on some systems when objects
     * are being drawn too close to the edge.
     */

    pixmapX1 = canvasX1 - OVERDRAW_PIXELS;
    pixmapY1 = canvasY1 - OVERDRAW_PIXELS;
    pixmapX2 = canvasX2 + OVERDRAW_PIXELS;
    pixmapY2 = canvasY2 + OVERDRAW_PIXELS;
    pmWidth = pixmapX2 - pixmapX1 + 1;
    pmHeight = pixmapY2 - pixmapY1 + 1;
    if ((pixmap = Tk_GetPixmap(displayPtr, Tk_WindowId(tkwin), pmWidth, pmHeight,
            bitsPerPixel)) == 0) {
        Tcl_AppendResult(interp, "failed to create drawing Pixmap", NULL);
        result = TCL_ERROR;
        goto done;
    }

    /*
     * Before we can draw the canvas objects into the pixmap it's background
     * should be filled with canvas background colour.
     */

    xgcValues.function = GXcopy;
    xgcValues.foreground = Tk_3DBorderColor(canvasPtr->bgBorder)->pixel;
    xgc = XCreateGC(displayPtr, pixmap, GCFunction|GCForeground, &xgcValues);
    XFillRectangle(displayPtr,pixmap,xgc,0,0,pmWidth,pmHeight);

    /*
     * Draw all the cavas items into the pixmap
     */

    canvasPtr->drawableXOrigin = pixmapX1;
    canvasPtr->drawableYOrigin = pixmapY1;
    for (itemPtr = canvasPtr->firstItemPtr; itemPtr != NULL;
            itemPtr = itemPtr->nextPtr) {
        if ((itemPtr->x1 >= pixmapX2) || (itemPtr->y1 >= pixmapY2) ||
                (itemPtr->x2 < pixmapX1) || (itemPtr->y2 < pixmapY1)) {
            if (!AlwaysRedraw(itemPtr)) {
                continue;
            }
        }
        if (itemPtr->state == TK_STATE_HIDDEN ||
                (itemPtr->state == TK_STATE_NULL && canvasPtr->canvas_state
                == TK_STATE_HIDDEN)) {
            continue;
        }
        ItemDisplay(canvasPtr, itemPtr, pixmap, pixmapX1, pixmapY1, pmWidth,
                pmHeight);
    }

    /*
     * Copy the Pixmap into an ZPixmap format XImage so we can copy it across
     * to the photo image. This seems to be the only way to get Pixmap image
     * data out of an image. Note we have to account for the OVERDRAW_PIXELS
     * border width.
     */

    if ((ximagePtr = XGetImage(displayPtr, pixmap, -pixmapX1, -pixmapY1, cWidth,
            cHeight, AllPlanes, ZPixmap)) == NULL) {
        Tcl_AppendResult(interp, "failed to copy Pixmap to XImage", NULL);
        result = TCL_ERROR;
        goto done;
    }

#ifdef DEBUG_DRAWCANVAS
    Tcl_AppendResult(interp, "ximagePtr {", NULL);
    sprintf(buffer,"%d",ximagePtr->width);   Tcl_AppendResult(interp, " width ", buffer, NULL);
    sprintf(buffer,"%d",ximagePtr->height);  Tcl_AppendResult(interp, " height ", buffer, NULL);
    sprintf(buffer,"%d",ximagePtr->xoffset); Tcl_AppendResult(interp, " xoffset ", buffer, NULL);
    sprintf(buffer,"%d",ximagePtr->format);  Tcl_AppendResult(interp, " format ", buffer, NULL);
                                             Tcl_AppendResult(interp, " ximagePtr->data", NULL);
    if (ximagePtr->data != NULL) {
	int ix, iy;

        Tcl_AppendResult(interp, " {", NULL);
	for (iy = 0; iy < ximagePtr->height; ++ iy) {
	    Tcl_AppendResult(interp, " {", NULL);
	    for (ix = 0; ix < ximagePtr->bytes_per_line; ++ ix) {
	        if (ix > 0) {
                    if (ix % 4 == 0)
                        Tcl_AppendResult(interp, "-", NULL);
                    else
                        Tcl_AppendResult(interp, " ", NULL);
                }
	        sprintf(buffer,"%2.2x",ximagePtr->data[ximagePtr->bytes_per_line * iy + ix]&0xFF);
	        Tcl_AppendResult(interp, buffer, NULL);
	    }
	    Tcl_AppendResult(interp, " }", NULL);
	}
	Tcl_AppendResult(interp, " }", NULL);
    } else
	sprintf(buffer," NULL");
    sprintf(buffer,"%d",ximagePtr->byte_order);       Tcl_AppendResult(interp, " byte_order ", buffer, NULL);
    sprintf(buffer,"%d",ximagePtr->bitmap_unit);      Tcl_AppendResult(interp, " bitmap_unit ", buffer, NULL);
    sprintf(buffer,"%d",ximagePtr->bitmap_bit_order); Tcl_AppendResult(interp, " bitmap_bit_order ", buffer, NULL);
    sprintf(buffer,"%d",ximagePtr->bitmap_pad);       Tcl_AppendResult(interp, " bitmap_pad ", buffer, NULL);
    sprintf(buffer,"%d",ximagePtr->depth);            Tcl_AppendResult(interp, " depth ", buffer, NULL);
    sprintf(buffer,"%d",ximagePtr->bytes_per_line);   Tcl_AppendResult(interp, " bytes_per_line ", buffer, NULL);
    sprintf(buffer,"%d",ximagePtr->bits_per_pixel);   Tcl_AppendResult(interp, " bits_per_pixel ", buffer, NULL);
    sprintf(buffer,"0x%8.8lx",ximagePtr->red_mask);   Tcl_AppendResult(interp, " red_mask ", buffer, NULL);
    sprintf(buffer,"0x%8.8lx",ximagePtr->green_mask); Tcl_AppendResult(interp, " green_mask ", buffer, NULL);
    sprintf(buffer,"0x%8.8lx",ximagePtr->blue_mask);  Tcl_AppendResult(interp, " blue_mask ", buffer, NULL);
    Tcl_AppendResult(interp, " }", NULL);

    Tcl_AppendResult(interp, "\nvisualPtr {", NULL);
    sprintf(buffer,"0x%8.8lx",visualPtr->red_mask);   Tcl_AppendResult(interp, " red_mask ", buffer, NULL);
    sprintf(buffer,"0x%8.8lx",visualPtr->green_mask); Tcl_AppendResult(interp, " green_mask ", buffer, NULL);
    sprintf(buffer,"0x%8.8lx",visualPtr->blue_mask);  Tcl_AppendResult(interp, " blue_mask ", buffer, NULL);
    Tcl_AppendResult(interp, " }", NULL);

#endif

    /*
     * Fill in the PhotoImageBlock structure abd allocate a block of memory
     * for the converted image data. Note we allocate an alpha channel even
     * though we don't use one, because this layout helps Tk_PhotoPutBlock()
     * use memcpy() instead of the slow pixel or line copy.
     */

    blockPtr.width = cWidth;
    blockPtr.height = cHeight;
    blockPtr.pixelSize = 4;
    blockPtr.pitch = blockPtr.pixelSize * blockPtr.width;
    blockPtr.offset[0] = 0;
    blockPtr.offset[1] = 1;
    blockPtr.offset[2] = 2;
    blockPtr.offset[3] = 3;
    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().
     */

    DecomposeMaskToShiftAndBits(visualPtr->red_mask,&rshift,&rbits);
    DecomposeMaskToShiftAndBits(visualPtr->green_mask,&gshift,&gbits);
    DecomposeMaskToShiftAndBits(visualPtr->blue_mask,&bshift,&bbits);

#ifdef DEBUG_DRAWCANVAS
    sprintf(buffer,"%d",rshift); Tcl_AppendResult(interp, "\nbits { rshift ", buffer, NULL);
    sprintf(buffer,"%d",gshift); Tcl_AppendResult(interp, " gshift ", buffer, NULL);
    sprintf(buffer,"%d",bshift); Tcl_AppendResult(interp, " bshift ", buffer, NULL);
    sprintf(buffer,"%d",rbits);  Tcl_AppendResult(interp, " rbits ", buffer, NULL);
    sprintf(buffer,"%d",gbits);  Tcl_AppendResult(interp, " gbits ", buffer, NULL);
    sprintf(buffer,"%d",bbits);  Tcl_AppendResult(interp, " bbits ", buffer, " }", NULL);
    Tcl_AppendResult(interp, "\nConverted_image {", NULL);
#endif

    /* Ok, had to use ximagePtr->bits_per_pixel here and in the switch (...)
     * below to get this to work on Windows. X11 correctly sets the bitmap
     *_pad and bitmap_unit fields to 32, but on Windows they are 0 and 8
     * respectively!
     */

    bytesPerPixel = ximagePtr->bits_per_pixel/8;
    for (y = 0; y < blockPtr.height; ++y) {

#ifdef DEBUG_DRAWCANVAS
        Tcl_AppendResult(interp, " {", NULL);
#endif

        for(x = 0; x < blockPtr.width; ++x) {
            unsigned int pixel = 0;

            switch (ximagePtr->bits_per_pixel) {

                /*
                 * Get an 8 bit pixel from the XImage.
                 */

                case 8 :
                    pixel = *((unsigned char *)(ximagePtr->data + bytesPerPixel * x
                            + ximagePtr->bytes_per_line * y));
                    break;

                /*
                 * Get a 16 bit pixel from the XImage, and correct the
                 * byte order as necessary.
                 */

                case 16 :
                    pixel = *((unsigned short *)(ximagePtr->data + bytesPerPixel * x
                            + ximagePtr->bytes_per_line * y));
                    if ((IS_BIG_ENDIAN && ximagePtr->byte_order == LSBFirst)
                            || (!IS_BIG_ENDIAN && ximagePtr->byte_order == MSBFirst))
                        pixel = BYTE_SWAP16(pixel);
                    break;

                /*
                 * Grab a 32 bit pixel from the XImage, and correct the
                 * byte order as necessary.
                 */

                case 32 :
                    pixel = *((unsigned int *)(ximagePtr->data + bytesPerPixel * x
                            + ximagePtr->bytes_per_line * y));
                    if ((IS_BIG_ENDIAN && ximagePtr->byte_order == LSBFirst)
                            || (!IS_BIG_ENDIAN && ximagePtr->byte_order == MSBFirst))
                        pixel = BYTE_SWAP32(pixel);
                    break;
            }

            /*
             * We have a pixel with the correct byte order, so pull out the
             * colours and place them in the photo block. Perhaps we could
             * just not bother with the alpha byte because we are using
             * TK_PHOTO_COMPOSITE_SET later?
             * ***Windows: We have to swap the red and blue values. The
             * XImage storage is B - G - R - A which becomes a 32bit ARGB
             * quad. However the visual mask is a 32bit ABGR quad. And
             * Tk_PhotoPutBlock() wants R-G-B-A which is a 32bit ABGR quad.
             * 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
#else
#define   R_OFFSET 0
#define   B_OFFSET 2
#endif
            blockPtr.pixelPtr[blockPtr.pitch * y + blockPtr.pixelSize * x + R_OFFSET] =
                    (unsigned char)((pixel & visualPtr->red_mask) >> rshift);
            blockPtr.pixelPtr[blockPtr.pitch * y + blockPtr.pixelSize * x +1] =
                    (unsigned char)((pixel & visualPtr->green_mask) >> gshift);
            blockPtr.pixelPtr[blockPtr.pitch * y + blockPtr.pixelSize * x + B_OFFSET] =
                    (unsigned char)((pixel & visualPtr->blue_mask) >> bshift);
            blockPtr.pixelPtr[blockPtr.pitch * y + blockPtr.pixelSize * x +3] = 0xFF;

#ifdef DEBUG_DRAWCANVAS
            {
		int ix;
                if (x > 0)
                    Tcl_AppendResult(interp, "-", NULL);
	        for (ix = 0; ix < 4; ++ix) {
                    if (ix > 0)
                        Tcl_AppendResult(interp, " ", NULL);
		    sprintf(buffer,"%2.2x",blockPtr.pixelPtr[blockPtr.pitch * y
                            + blockPtr.pixelSize * x + ix]&0xFF);
                    Tcl_AppendResult(interp, buffer, NULL);
                }
            }
#endif

        }

#ifdef DEBUG_DRAWCANVAS
        Tcl_AppendResult(interp, " }", NULL);
#endif

    }

#ifdef DEBUG_DRAWCANVAS
    Tcl_AppendResult(interp, " }", NULL);
#endif

    /*
     * Now put the copied pixmap into the photo.
     * If either zoom or subsample are not 1, we use the zoom function.
     */

    if (subsample != 1 || zoom != 1) {
        if ((result = Tk_PhotoPutZoomedBlock(interp, photohandle, &blockPtr,
                0, 0, cWidth * zoom / subsample, cHeight * zoom / subsample,
                zoom, zoom, subsample, subsample, TK_PHOTO_COMPOSITE_SET))
                != TCL_OK) {
            goto done;
        }
    } else {
        if ((result = Tk_PhotoPutBlock(interp, photohandle, &blockPtr, 0, 0,
            cWidth, cHeight, TK_PHOTO_COMPOSITE_SET)) != TCL_OK) {
            goto done;
        }
    }

    /*
     * Clean up anything we have allocated and exit.
     */

done:
    if (blockPtr.pixelPtr)
        ckfree(blockPtr.pixelPtr);
    if (pixmap)
        Tk_FreePixmap(Tk_Display(tkwin), pixmap);
    if (ximagePtr)
        XDestroyImage(ximagePtr);
    if (xgc)
        XFreeGC(displayPtr,xgc);
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * DisplayCanvas --
 *
 *	This function redraws the contents of a canvas window. It is invoked
 *	as a do-when-idle handler, so it only runs when there's nothing else
2447
2448
2449
2450
2451
2452
2453
2454

2455
2456
2457
2458
2459
2460
2461
2995
2996
2997
2998
2999
3000
3001

3002
3003
3004
3005
3006
3007
3008
3009







-
+







 *----------------------------------------------------------------------
 */

static void
DisplayCanvas(
    ClientData clientData)	/* Information about widget. */
{
    TkCanvas *canvasPtr = clientData;
    TkCanvas *canvasPtr = (TkCanvas *)clientData;
    Tk_Window tkwin = canvasPtr->tkwin;
    Tk_Item *itemPtr;
    Pixmap pixmap;
    int screenX1, screenX2, screenY1, screenY2, width, height;

    if (canvasPtr->tkwin == NULL) {
	return;
2701
2702
2703
2704
2705
2706
2707
2708

2709
2710
2711
2712
2713
2714
2715
3249
3250
3251
3252
3253
3254
3255

3256
3257
3258
3259
3260
3261
3262
3263







-
+







 */

static void
CanvasEventProc(
    ClientData clientData,	/* Information about window. */
    XEvent *eventPtr)		/* Information about event. */
{
    TkCanvas *canvasPtr = clientData;
    TkCanvas *canvasPtr = (TkCanvas *)clientData;

    if (eventPtr->type == Expose) {
	int x, y;

	x = eventPtr->xexpose.x + canvasPtr->xOrigin;
	y = eventPtr->xexpose.y + canvasPtr->yOrigin;
	Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr, x, y,
2791
2792
2793
2794
2795
2796
2797
2798

2799
2800
2801
2802
2803
2804
2805
3339
3340
3341
3342
3343
3344
3345

3346
3347
3348
3349
3350
3351
3352
3353







-
+







 *----------------------------------------------------------------------
 */

static void
CanvasCmdDeletedProc(
    ClientData clientData)	/* Pointer to widget record for widget. */
{
    TkCanvas *canvasPtr = clientData;
    TkCanvas *canvasPtr = (TkCanvas *)clientData;
    Tk_Window tkwin = canvasPtr->tkwin;

    /*
     * This function could be invoked either because the window was destroyed
     * and the command was then deleted (in which case tkwin is NULL) or
     * because the command was deleted, and then this function destroys the
     * widget.
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3607
3608
3609
3610
3611
3612
3613










































































































































































































3614
3615
3616
3617
3618
3619
3620







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







    tkOvalType.nextPtr = &tkBitmapType;
    tkBitmapType.nextPtr = &tkArcType;
    tkArcType.nextPtr = &tkWindowType;
    tkWindowType.nextPtr = NULL;
    Tcl_MutexUnlock(&typeListMutex);
}

#ifdef USE_OLD_TAG_SEARCH
/*
 *--------------------------------------------------------------
 *
 * StartTagSearch --
 *
 *	This function is called to initiate an enumeration of all items in a
 *	given canvas that contain a given tag.
 *
 * Results:
 *	The return value is a pointer to the first item in canvasPtr that
 *	matches tag, or NULL if there is no such item. The information at
 *	*searchPtr is initialized such that successive calls to NextItem will
 *	return successive items that match tag.
 *
 * Side effects:
 *	SearchPtr is linked into a list of searches in progress on canvasPtr,
 *	so that elements can safely be deleted while the search is in
 *	progress. EndTagSearch must be called at the end of the search to
 *	unlink searchPtr from this list.
 *
 *--------------------------------------------------------------
 */

static Tk_Item *
StartTagSearch(
    TkCanvas *canvasPtr,	/* Canvas whose items are to be searched. */
    Tcl_Obj *tagObj,		/* Object giving tag value. */
    TagSearch *searchPtr)	/* Record describing tag search; will be
				 * initialized here. */
{
    int id;
    Tk_Item *itemPtr, *lastPtr;
    Tk_Uid *tagPtr;
    Tk_Uid uid;
    char *tag = Tcl_GetString(tagObj);
    int count;
    TkWindow *tkwin = (TkWindow *) canvasPtr->tkwin;
    TkDisplay *dispPtr = tkwin->dispPtr;

    /*
     * Initialize the search.
     */

    searchPtr->canvasPtr = canvasPtr;
    searchPtr->searchOver = 0;

    /*
     * Find the first matching item in one of several ways. If the tag is a
     * number then it selects the single item with the matching identifier.
     * In this case see if the item being requested is the hot item, in which
     * case the search can be skipped.
     */

    if (isdigit(UCHAR(*tag))) {
	char *end;
	Tcl_HashEntry *entryPtr;

	dispPtr->numIdSearches++;
	id = strtoul(tag, &end, 0);
	if (*end == 0) {
	    itemPtr = canvasPtr->hotPtr;
	    lastPtr = canvasPtr->hotPrevPtr;
	    if ((itemPtr == NULL) || (itemPtr->id != id) || (lastPtr == NULL)
		    || (lastPtr->nextPtr != itemPtr)) {
		dispPtr->numSlowSearches++;
		entryPtr = Tcl_FindHashEntry(&canvasPtr->idTable, (char*) id);
		if (entryPtr != NULL) {
		    itemPtr = Tcl_GetHashValue(entryPtr);
		    lastPtr = itemPtr->prevPtr;
		} else {
		    lastPtr = itemPtr = NULL;
		}
	    }
	    searchPtr->lastPtr = lastPtr;
	    searchPtr->searchOver = 1;
	    canvasPtr->hotPtr = itemPtr;
	    canvasPtr->hotPrevPtr = lastPtr;
	    return itemPtr;
	}
    }

    searchPtr->tag = uid = Tk_GetUid(tag);
    if (uid == Tk_GetUid("all")) {
	/*
	 * All items match.
	 */

	searchPtr->tag = NULL;
	searchPtr->lastPtr = NULL;
	searchPtr->currentPtr = canvasPtr->firstItemPtr;
	return canvasPtr->firstItemPtr;
    }

    /*
     * None of the above. Search for an item with a matching tag.
     */

    for (lastPtr = NULL, itemPtr = canvasPtr->firstItemPtr; itemPtr != NULL;
	    lastPtr = itemPtr, itemPtr = itemPtr->nextPtr) {
	for (tagPtr = itemPtr->tagPtr, count = itemPtr->numTags;
		count > 0; tagPtr++, count--) {
	    if (*tagPtr == uid) {
		searchPtr->lastPtr = lastPtr;
		searchPtr->currentPtr = itemPtr;
		return itemPtr;
	    }
	}
    }
    searchPtr->lastPtr = lastPtr;
    searchPtr->searchOver = 1;
    return NULL;
}

/*
 *--------------------------------------------------------------
 *
 * NextItem --
 *
 *	This function returns successive items that match a given tag; it
 *	should be called only after StartTagSearch has been used to begin a
 *	search.
 *
 * Results:
 *	The return value is a pointer to the next item that matches the tag
 *	specified to StartTagSearch, or NULL if no such item exists.
 *	*SearchPtr is updated so that the next call to this function will
 *	return the next item.
 *
 * Side effects:
 *	None.
 *
 *--------------------------------------------------------------
 */

static Tk_Item *
NextItem(
    TagSearch *searchPtr)	/* Record describing search in progress. */
{
    Tk_Item *itemPtr, *lastPtr;
    int count;
    Tk_Uid uid;
    Tk_Uid *tagPtr;

    /*
     * Find next item in list (this may not actually be a suitable one to
     * return), and return if there are no items left.
     */

    lastPtr = searchPtr->lastPtr;
    if (lastPtr == NULL) {
	itemPtr = searchPtr->canvasPtr->firstItemPtr;
    } else {
	itemPtr = lastPtr->nextPtr;
    }
    if ((itemPtr == NULL) || (searchPtr->searchOver)) {
	searchPtr->searchOver = 1;
	return NULL;
    }
    if (itemPtr != searchPtr->currentPtr) {
	/*
	 * The structure of the list has changed. Probably the previously-
	 * returned item was removed from the list. In this case, don't
	 * advance lastPtr; just return its new successor (i.e. do nothing
	 * here).
	 */
    } else {
	lastPtr = itemPtr;
	itemPtr = lastPtr->nextPtr;
    }

    /*
     * Handle special case of "all" search by returning next item.
     */

    uid = searchPtr->tag;
    if (uid == NULL) {
	searchPtr->lastPtr = lastPtr;
	searchPtr->currentPtr = itemPtr;
	return itemPtr;
    }

    /*
     * Look for an item with a particular tag.
     */

    for ( ; itemPtr != NULL; lastPtr = itemPtr, itemPtr = itemPtr->nextPtr) {
	for (tagPtr = itemPtr->tagPtr, count = itemPtr->numTags;
		count > 0; tagPtr++, count--) {
	    if (*tagPtr == uid) {
		searchPtr->lastPtr = lastPtr;
		searchPtr->currentPtr = itemPtr;
		return itemPtr;
	    }
	}
    }
    searchPtr->lastPtr = lastPtr;
    searchPtr->searchOver = 1;
    return NULL;
}

#else /* !USE_OLD_TAG_SEARCH */
/*
 *----------------------------------------------------------------------
 *
 * GetStaticUids --
 *
 *	This function is invoked to return a structure filled with the Uids
 *	used when doing tag searching. If it was never before called in the
3283
3284
3285
3286
3287
3288
3289
3290

3291
3292
3293
3294
3295
3296
3297
3629
3630
3631
3632
3633
3634
3635

3636
3637
3638
3639
3640
3641
3642
3643







-
+







 *
 *----------------------------------------------------------------------
 */

static SearchUids *
GetStaticUids(void)
{
    SearchUids *searchUids =
    SearchUids *searchUids = (SearchUids *)
	    Tcl_GetThreadData(&dataKey, sizeof(SearchUids));

    if (searchUids->allUid == NULL) {
	searchUids->allUid       = Tk_GetUid("all");
	searchUids->currentUid   = Tk_GetUid("current");
	searchUids->andUid       = Tk_GetUid("&&");
	searchUids->orUid        = Tk_GetUid("||");
3322
3323
3324
3325
3326
3327
3328
3329

3330
3331
3332
3333
3334
3335
3336
3668
3669
3670
3671
3672
3673
3674

3675
3676
3677
3678
3679
3680
3681
3682







-
+







static void
TagSearchExprInit(
    TagSearchExpr **exprPtrPtr)
{
    TagSearchExpr *expr = *exprPtrPtr;

    if (expr == NULL) {
	expr = ckalloc(sizeof(TagSearchExpr));
	expr = (TagSearchExpr *)ckalloc(sizeof(TagSearchExpr));
	expr->allocated = 0;
	expr->uids = NULL;
	expr->next = NULL;
    }
    expr->uid = NULL;
    expr->index = 0;
    expr->length = 0;
3403
3404
3405
3406
3407
3408
3409
3410

3411
3412
3413
3414
3415
3416
3417
3418

3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435

3436
3437
3438
3439
3440
3441
3442
3749
3750
3751
3752
3753
3754
3755

3756
3757
3758
3759
3760
3761
3762
3763

3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780

3781
3782
3783
3784
3785
3786
3787
3788







-
+







-
+
















-
+







    if (*searchPtrPtr != NULL) {
	searchPtr = *searchPtrPtr;
    } else {
	/*
	 * Allocate primary search struct on first call.
	 */

	*searchPtrPtr = searchPtr = ckalloc(sizeof(TagSearch));
	*searchPtrPtr = searchPtr = (TagSearch *)ckalloc(sizeof(TagSearch));
	searchPtr->expr = NULL;

	/*
	 * Allocate buffer for rewritten tags (after de-escaping).
	 */

	searchPtr->rewritebufferAllocated = 100;
	searchPtr->rewritebuffer = ckalloc(searchPtr->rewritebufferAllocated);
	searchPtr->rewritebuffer = (char *)ckalloc(searchPtr->rewritebufferAllocated);
    }
    TagSearchExprInit(&searchPtr->expr);

    /*
     * How long is the tagOrId?
     */

    searchPtr->stringLength = strlen(tag);

    /*
     * Make sure there is enough buffer to hold rewritten tags.
     */

    if ((unsigned) searchPtr->stringLength >=
	    searchPtr->rewritebufferAllocated) {
	searchPtr->rewritebufferAllocated = searchPtr->stringLength + 100;
	searchPtr->rewritebuffer =
	searchPtr->rewritebuffer = (char *)
		ckrealloc(searchPtr->rewritebuffer,
		searchPtr->rewritebufferAllocated);
    }

    /*
     * Initialize search.
     */
3611
3612
3613
3614
3615
3616
3617
3618

3619
3620
3621

3622
3623
3624
3625
3626
3627
3628
3957
3958
3959
3960
3961
3962
3963

3964
3965
3966

3967
3968
3969
3970
3971
3972
3973
3974







-
+


-
+







	/*
	 * Need two slots free at this point, not one. [Bug 2931374]
	 */

	if (expr->index >= expr->allocated-1) {
	    expr->allocated += 15;
	    if (expr->uids) {
		expr->uids = ckrealloc(expr->uids,
		expr->uids = (Tk_Uid *)ckrealloc(expr->uids,
			expr->allocated * sizeof(Tk_Uid));
	    } else {
		expr->uids = ckalloc(expr->allocated * sizeof(Tk_Uid));
		expr->uids = (Tk_Uid *)ckalloc(expr->allocated * sizeof(Tk_Uid));
	    }
	}

	if (looking_for_tag) {
	    switch (c) {
	    case ' ':		/* Ignore unquoted whitespace */
	    case '\t':
3871
3872
3873
3874
3875
3876
3877
3878

3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898

3899
3900
3901
3902
3903
3904
3905
4217
4218
4219
4220
4221
4222
4223

4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243

4244
4245
4246
4247
4248
4249
4250
4251







-
+



















-
+







		uid = expr->uids[expr->index++];
		result = 0;

		/*
		 * set result 1 if tag is found in item's tags
		 */

		for (tagPtr = itemPtr->tagPtr, count = itemPtr->numTags;
		for (tagPtr = itemPtr->tagPtr, count = (int)itemPtr->numTags;
			count > 0; tagPtr++, count--) {
		    if (*tagPtr == uid) {
			result = 1;
			break;
		    }
		}

	    } else if (uid == searchUids->negtagvalUid) {
		negate_result = ! negate_result;
/*
 *		assert(expr->index < expr->length);
 */
		uid = expr->uids[expr->index++];
		result = 0;

		/*
		 * set result 1 if tag is found in item's tags.
		 */

		for (tagPtr = itemPtr->tagPtr, count = itemPtr->numTags;
		for (tagPtr = itemPtr->tagPtr, count = (int)itemPtr->numTags;
			count > 0; tagPtr++, count--) {
		    if (*tagPtr == uid) {
			result = 1;
			break;
		    }
		}

4024
4025
4026
4027
4028
4029
4030
4031

4032
4033

4034
4035
4036
4037
4038
4039
4040
4370
4371
4372
4373
4374
4375
4376

4377
4378

4379
4380
4381
4382
4383
4384
4385
4386







-
+

-
+







	Tcl_HashEntry *entryPtr;

	itemPtr = searchPtr->canvasPtr->hotPtr;
	lastPtr = searchPtr->canvasPtr->hotPrevPtr;
	if ((itemPtr == NULL) || (itemPtr->id != searchPtr->id)
		|| (lastPtr == NULL) || (lastPtr->nextPtr != itemPtr)) {
	    entryPtr = Tcl_FindHashEntry(&searchPtr->canvasPtr->idTable,
		    (char *) INT2PTR(searchPtr->id));
		    INT2PTR(searchPtr->id));
	    if (entryPtr != NULL) {
		itemPtr = Tcl_GetHashValue(entryPtr);
		itemPtr = (Tk_Item *)Tcl_GetHashValue(entryPtr);
		lastPtr = itemPtr->prevPtr;
	    } else {
		lastPtr = itemPtr = NULL;
	    }
	}
	searchPtr->lastPtr = lastPtr;
	searchPtr->searchOver = 1;
4057
4058
4059
4060
4061
4062
4063
4064

4065
4066
4067
4068
4069
4070
4071
4403
4404
4405
4406
4407
4408
4409

4410
4411
4412
4413
4414
4415
4416
4417







-
+







	/*
	 * Optimized single-tag search
	 */

	uid = searchPtr->expr->uid;
	for (lastPtr = NULL, itemPtr = searchPtr->canvasPtr->firstItemPtr;
		itemPtr != NULL; lastPtr=itemPtr, itemPtr=itemPtr->nextPtr) {
	    for (tagPtr = itemPtr->tagPtr, count = itemPtr->numTags;
	    for (tagPtr = itemPtr->tagPtr, count = (int)itemPtr->numTags;
		    count > 0; tagPtr++, count--) {
		if (*tagPtr == uid) {
		    searchPtr->lastPtr = lastPtr;
		    searchPtr->currentPtr = itemPtr;
		    return itemPtr;
		}
	    }
4159
4160
4161
4162
4163
4164
4165
4166

4167
4168
4169
4170
4171
4172
4173
4505
4506
4507
4508
4509
4510
4511

4512
4513
4514
4515
4516
4517
4518
4519







-
+







    if (searchPtr->type == SEARCH_TYPE_TAG) {
	/*
	 * Optimized single-tag search
	 */

	uid = searchPtr->expr->uid;
	for (; itemPtr != NULL; lastPtr = itemPtr, itemPtr = itemPtr->nextPtr) {
	    for (tagPtr = itemPtr->tagPtr, count = itemPtr->numTags;
	    for (tagPtr = itemPtr->tagPtr, count = (int)itemPtr->numTags;
		    count > 0; tagPtr++, count--) {
		if (*tagPtr == uid) {
		    searchPtr->lastPtr = lastPtr;
		    searchPtr->currentPtr = itemPtr;
		    return itemPtr;
		}
	    }
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4535
4536
4537
4538
4539
4540
4541

4542
4543
4544
4545
4546
4547
4548







-







	    return itemPtr;
	}
    }
    searchPtr->lastPtr = lastPtr;
    searchPtr->searchOver = 1;
    return NULL;
}
#endif /* USE_OLD_TAG_SEARCH */

/*
 *--------------------------------------------------------------
 *
 * DoItem --
 *
 *	This is a utility function called by FindItems. It either adds
4226
4227
4228
4229
4230
4231
4232
4233

4234
4235
4236
4237

4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252

4253
4254
4255
4256
4257
4258
4259
4571
4572
4573
4574
4575
4576
4577

4578
4579
4580
4581

4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596

4597
4598
4599
4600
4601
4602
4603
4604







-
+



-
+














-
+







    int count;

    /*
     * Handle the "add-to-result" case and return, if appropriate.
     */

    if (tag == NULL) {
	Tcl_ListObjAppendElement(NULL, accumObj, Tcl_NewIntObj(itemPtr->id));
	Tcl_ListObjAppendElement(NULL, accumObj, Tcl_NewWideIntObj(itemPtr->id));
	return;
    }

    for (tagPtr = itemPtr->tagPtr, count = itemPtr->numTags;
    for (tagPtr = itemPtr->tagPtr, count = (int)itemPtr->numTags;
	    count > 0; tagPtr++, count--) {
	if (tag == *tagPtr) {
	    return;
	}
    }

    /*
     * Grow the tag space if there's no more room left in the current block.
     */

    if (itemPtr->tagSpace == itemPtr->numTags) {
	Tk_Uid *newTagPtr;

	itemPtr->tagSpace += 5;
	newTagPtr = ckalloc(itemPtr->tagSpace * sizeof(Tk_Uid));
	newTagPtr = (Tk_Uid *)ckalloc(itemPtr->tagSpace * sizeof(Tk_Uid));
	memcpy((void *) newTagPtr, itemPtr->tagPtr,
		itemPtr->numTags * sizeof(Tk_Uid));
	if (itemPtr->tagPtr != itemPtr->staticTagSpace) {
	    ckfree(itemPtr->tagPtr);
	}
	itemPtr->tagPtr = newTagPtr;
	tagPtr = &itemPtr->tagPtr[itemPtr->numTags];
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4647
4648
4649
4650
4651
4652
4653

4654

4655
4656



4657
4658
4659
4660
4661
4662
4663







-

-


-
-
-







    Tcl_Obj *newTag,		/* If non-NULL, gives new tag to set on all
				 * found items; if NULL, then ids of found
				 * items are returned in the interp's
				 * result. */
    int first			/* For error messages: gives number of
				 * elements of objv which are already
				 * handled. */
#ifndef USE_OLD_TAG_SEARCH
    ,TagSearch **searchPtrPtr	/* From CanvasWidgetCmd local vars*/
#endif /* not USE_OLD_TAG_SEARCH */
    )
{
#ifdef USE_OLD_TAG_SEARCH
    TagSearch search;
#endif /* USE_OLD_TAG_SEARCH */
    Tk_Item *itemPtr;
    Tk_Uid uid;
    int index, result;
    Tcl_Obj *resultObj;
    static const char *const optionStrings[] = {
	"above", "all", "below", "closest",
	"enclosed", "overlapping", "withtag", NULL
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4966
4967
4968
4969
4970
4971
4972










4973
4974
4975
4976
4977
4978
4979
4980
4981

4982
4983



4984
4985
4986
4987
4988
4989
4990







-
-
-
-
-
-
-
-
-
-









-


-
-
-







 *	The items identified by "tag" are moved so that they are all together
 *	in the display list and immediately after prevPtr. The order of the
 *	moved items relative to each other is not changed.
 *
 *--------------------------------------------------------------
 */

#ifdef USE_OLD_TAG_SEARCH
static void
RelinkItems(
    TkCanvas *canvasPtr,	/* Canvas to be modified. */
    Tcl_Obj *tag,		/* Tag identifying items to be moved in the
				 * redisplay list. */
    Tk_Item *prevPtr)		/* Reposition the items so that they go just
				 * after this item (NULL means put at
				 * beginning of list). */
#else /* USE_OLD_TAG_SEARCH */
static int
RelinkItems(
    TkCanvas *canvasPtr,	/* Canvas to be modified. */
    Tcl_Obj *tag,		/* Tag identifying items to be moved in the
				 * redisplay list. */
    Tk_Item *prevPtr,		/* Reposition the items so that they go just
				 * after this item (NULL means put at
				 * beginning of list). */
    TagSearch **searchPtrPtr)	/* From CanvasWidgetCmd local vars */
#endif /* USE_OLD_TAG_SEARCH */
{
    Tk_Item *itemPtr;
#ifdef USE_OLD_TAG_SEARCH
    TagSearch search;
#endif /* USE_OLD_TAG_SEARCH */
    Tk_Item *firstMovePtr, *lastMovePtr;
    int result;

    /*
     * Find all of the items to be moved and remove them from the list, making
     * an auxiliary list running from firstMovePtr to lastMovePtr. Record
     * their areas for redisplay.
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
5028
5029
5030
5031
5032
5033
5034



5035

5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055

5056

5057
5058
5059
5060
5061
5062
5063







-
-
-

-




















-

-








    /*
     * Insert the list of to-be-moved items back into the canvas's at the
     * desired position.
     */

    if (firstMovePtr == NULL) {
#ifdef USE_OLD_TAG_SEARCH
	return;
#else /* USE_OLD_TAG_SEARCH */
	return TCL_OK;
#endif /* USE_OLD_TAG_SEARCH */
    }
    if (prevPtr == NULL) {
	if (canvasPtr->firstItemPtr != NULL) {
	    canvasPtr->firstItemPtr->prevPtr = lastMovePtr;
	}
	lastMovePtr->nextPtr = canvasPtr->firstItemPtr;
	canvasPtr->firstItemPtr = firstMovePtr;
    } else {
	if (prevPtr->nextPtr != NULL) {
	    prevPtr->nextPtr->prevPtr = lastMovePtr;
	}
	lastMovePtr->nextPtr = prevPtr->nextPtr;
	if (firstMovePtr != NULL) {
	    firstMovePtr->prevPtr = prevPtr;
	}
	prevPtr->nextPtr = firstMovePtr;
    }
    if (canvasPtr->lastItemPtr == prevPtr) {
	canvasPtr->lastItemPtr = lastMovePtr;
    }
#ifndef USE_OLD_TAG_SEARCH
    return TCL_OK;
#endif /* not USE_OLD_TAG_SEARCH */
}

/*
 *--------------------------------------------------------------
 *
 * CanvasBindProc --
 *
4755
4756
4757
4758
4759
4760
4761
4762
4763


4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776

4777
4778
4779
4780
4781
4782
4783
5075
5076
5077
5078
5079
5080
5081


5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095

5096
5097
5098
5099
5100
5101
5102
5103







-
-
+
+












-
+







 */

static void
CanvasBindProc(
    ClientData clientData,	/* Pointer to canvas structure. */
    XEvent *eventPtr)		/* Pointer to X event that just happened. */
{
    TkCanvas *canvasPtr = clientData;
    unsigned long mask;
    TkCanvas *canvasPtr = (TkCanvas *)clientData;
    unsigned mask;

    Tcl_Preserve(canvasPtr);

    /*
     * This code below keeps track of the current modifier state in
     * canvasPtr>state. This information is used to defer repicks of the
     * current item while buttons are down.
     */

    switch (eventPtr->type) {
    case ButtonPress:
    case ButtonRelease:
	mask = TkGetButtonMask(eventPtr->xbutton.button);
	mask = Tk_GetButtonMask(eventPtr->xbutton.button);

	/*
	 * For button press events, repick the current item using the button
	 * state before the event, then process the event. For button release
	 * events, first process the event, then repick the current item using
	 * the button state *after* the event (the button has logically gone
	 * up before we change the current item).
4852
4853
4854
4855
4856
4857
4858
4859

4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
5172
5173
5174
5175
5176
5177
5178

5179
5180

5181

5182
5183
5184
5185
5186
5187
5188







-
+

-

-







    TkCanvas *canvasPtr,	/* Canvas widget in which to select current
				 * item. */
    XEvent *eventPtr)		/* Event describing location of mouse cursor.
				 * Must be EnterWindow, LeaveWindow,
				 * ButtonRelease, or MotionNotify. */
{
    double coords[2];
    unsigned long buttonDown;
    unsigned int buttonDown;
    Tk_Item *prevItemPtr;
#ifndef USE_OLD_TAG_SEARCH
    SearchUids *searchUids = GetStaticUids();
#endif

    /*
     * Check whether or not a button is down. If so, we'll log entry and exit
     * into and out of the current item, but not entry into any other item.
     * This implements a form of grabbing equivalent to what the X server does
     * for windows.
     */
4977
4978
4979
4980
4981
4982
4983
4984

4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
5295
5296
5297
5298
5299
5300
5301

5302



5303

5304
5305
5306
5307
5308
5309
5310







-
+
-
-
-

-








	/*
	 * The check below is needed because there could be an event handler
	 * for <LeaveNotify> that deletes the current item.
	 */

	if ((itemPtr == canvasPtr->currentItemPtr) && !buttonDown) {
	    for (i = itemPtr->numTags-1; i >= 0; i--) {
	    for (i = (int)itemPtr->numTags-1; i >= 0; i--) {
#ifdef USE_OLD_TAG_SEARCH
		if (itemPtr->tagPtr[i] == Tk_GetUid("current"))
#else /* USE_OLD_TAG_SEARCH */
		if (itemPtr->tagPtr[i] == searchUids->currentUid)
#endif /* USE_OLD_TAG_SEARCH */
		    /* then */ {
                    memmove((void *)(itemPtr->tagPtr + i),
                            itemPtr->tagPtr + i + 1,
                            (itemPtr->numTags - (i+1)) * sizeof(Tk_Uid));
		    itemPtr->numTags--;
		    break;
		}
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5335
5336
5337
5338
5339
5340
5341



5342

5343
5344
5345
5346
5347
5348
5349







-
-
-

-







	    (prevItemPtr->redraw_flags & TK_ITEM_STATE_DEPENDANT)) {
	EventuallyRedrawItem(canvasPtr, prevItemPtr);
	ItemConfigure(canvasPtr, prevItemPtr, 0, NULL);
    }
    if (canvasPtr->currentItemPtr != NULL) {
	XEvent event;

#ifdef USE_OLD_TAG_SEARCH
	DoItem(NULL, canvasPtr->currentItemPtr, Tk_GetUid("current"));
#else /* USE_OLD_TAG_SEARCH */
	DoItem(NULL, canvasPtr->currentItemPtr, searchUids->currentUid);
#endif /* USE_OLD_TAG_SEARCH */
	if ((canvasPtr->currentItemPtr->redraw_flags & TK_ITEM_STATE_DEPENDANT
		&& prevItemPtr != canvasPtr->currentItemPtr)) {
	    ItemConfigure(canvasPtr, canvasPtr->currentItemPtr, 0, NULL);
	    EventuallyRedrawItem(canvasPtr, canvasPtr->currentItemPtr);
	}
	event = canvasPtr->pickEvent;
	event.type = EnterNotify;
5119
5120
5121
5122
5123
5124
5125
5126
5127


5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5429
5430
5431
5432
5433
5434
5435


5436
5437
5438
5439

5440
5441
5442

5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455










5456
5457
5458
5459
5460
5461
5462







-
-
+
+


-



-













-
-
-
-
-
-
-
-
-
-







static void
CanvasDoEvent(
    TkCanvas *canvasPtr,	/* Canvas widget in which event occurred. */
    XEvent *eventPtr)		/* Real or simulated X event that is to be
				 * processed. */
{
#define NUM_STATIC 3
    ClientData staticObjects[NUM_STATIC];
    ClientData *objectPtr;
    void *staticObjects[NUM_STATIC];
    void **objectPtr;
    int numObjects, i;
    Tk_Item *itemPtr;
#ifndef USE_OLD_TAG_SEARCH
    TagSearchExpr *expr;
    int numExprs;
    SearchUids *searchUids = GetStaticUids();
#endif /* not USE_OLD_TAG_SEARCH */

    if (canvasPtr->bindingTable == NULL) {
	return;
    }

    itemPtr = canvasPtr->currentItemPtr;
    if ((eventPtr->type == KeyPress) || (eventPtr->type == KeyRelease)) {
	itemPtr = canvasPtr->textInfo.focusItemPtr;
    }
    if (itemPtr == NULL) {
	return;
    }

#ifdef USE_OLD_TAG_SEARCH
    /*
     * Set up an array with all the relevant objects for processing this
     * event. The relevant objects are (a) the event's item, (b) the tags
     * associated with the event's item, and (c) the tag "all". If there are a
     * lot of tags then malloc an array to hold all of the objects.
     */

    numObjects = itemPtr->numTags + 2;
#else /* USE_OLD_TAG_SEARCH */
    /*
     * Set up an array with all the relevant objects for processing this
     * event. The relevant objects are:
     * (a) the event's item,
     * (b) the tags associated with the event's item,
     * (c) the expressions that are true for the event's item's tags, and
     * (d) the tag "all".
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190

5191
5192
5193
5194
5195

5196
5197
5198


5199
5200

5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5477
5478
5479
5480
5481
5482
5483

5484
5485
5486

5487
5488




5489



5490
5491
5492

5493
5494

5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506

5507
5508
5509
5510
5511
5512
5513







-



-
+

-
-
-
-
+
-
-
-
+
+

-
+

-












-







	if (expr->match) {
	    numExprs++;
	}
	expr = expr->next;
    }

    numObjects = itemPtr->numTags + numExprs + 2;
#endif /* not USE_OLD_TAG_SEARCH */
    if (numObjects <= NUM_STATIC) {
	objectPtr = staticObjects;
    } else {
	objectPtr = ckalloc(numObjects * sizeof(ClientData));
	objectPtr = (void **)ckalloc(numObjects * sizeof(void *));
    }
#ifdef USE_OLD_TAG_SEARCH
    objectPtr[0] = (ClientData) Tk_GetUid("all");
#else /* USE_OLD_TAG_SEARCH */
    objectPtr[0] = (ClientData) searchUids->allUid;
    objectPtr[0] = (char *)searchUids->allUid;
#endif /* USE_OLD_TAG_SEARCH */
    for (i = itemPtr->numTags-1; i >= 0; i--) {
	objectPtr[i+1] = (ClientData) itemPtr->tagPtr[i];
    for (i = (int)itemPtr->numTags - 1; i >= 0; i--) {
	objectPtr[i+1] = (char *)itemPtr->tagPtr[i];
    }
    objectPtr[itemPtr->numTags+1] = itemPtr;
    objectPtr[itemPtr->numTags + 1] = itemPtr;

#ifndef USE_OLD_TAG_SEARCH
    /*
     * Copy uids of matching expressions into object array
     */

    i = itemPtr->numTags+2;
    expr = canvasPtr->bindTagExprs;
    while (expr) {
    	if (expr->match) {
	    objectPtr[i++] = (int *) expr->uid;
	}
	expr = expr->next;
    }
#endif /* not USE_OLD_TAG_SEARCH */

    /*
     * Invoke the binding system, then free up the object array if it was
     * malloc-ed.
     */

    if (canvasPtr->tkwin != NULL) {
5246
5247
5248
5249
5250
5251
5252
5253

5254
5255
5256
5257
5258
5259
5260
5537
5538
5539
5540
5541
5542
5543

5544
5545
5546
5547
5548
5549
5550
5551







-
+







 *----------------------------------------------------------------------
 */

static void
CanvasBlinkProc(
    ClientData clientData)	/* Pointer to record describing entry. */
{
    TkCanvas *canvasPtr = clientData;
    TkCanvas *canvasPtr = (TkCanvas *)clientData;

    if (!canvasPtr->textInfo.gotFocus || (canvasPtr->insertOffTime == 0)) {
	return;
    }
    if (canvasPtr->textInfo.cursorOn) {
	canvasPtr->textInfo.cursorOn = 0;
	canvasPtr->insertBlinkHandler = Tcl_CreateTimerHandler(
5331
5332
5333
5334
5335
5336
5337
5338

5339
5340
5341

5342
5343
5344
5345
5346
5347
5348
5622
5623
5624
5625
5626
5627
5628

5629
5630
5631

5632
5633
5634
5635
5636
5637
5638
5639







-
+


-
+







 *----------------------------------------------------------------------
 */

static void
CanvasSelectTo(
    TkCanvas *canvasPtr,	/* Information about widget. */
    Tk_Item *itemPtr,		/* Item that is to hold selection. */
    int index)			/* Index of element that is to become the
    TkSizeT index)			/* Index of element that is to become the
				 * "other" end of the selection. */
{
    int oldFirst, oldLast;
    TkSizeT oldFirst, oldLast;
    Tk_Item *oldSelPtr;

    oldFirst = canvasPtr->textInfo.selectFirst;
    oldLast = canvasPtr->textInfo.selectLast;
    oldSelPtr = canvasPtr->textInfo.selItemPtr;

    /*
5357
5358
5359
5360
5361
5362
5363
5364

5365
5366
5367
5368

5369
5370
5371
5372
5373
5374
5375
5648
5649
5650
5651
5652
5653
5654

5655
5656
5657
5658

5659
5660
5661
5662
5663
5664
5665
5666







-
+



-
+







    }
    canvasPtr->textInfo.selItemPtr = itemPtr;

    if (canvasPtr->textInfo.anchorItemPtr != itemPtr) {
	canvasPtr->textInfo.anchorItemPtr = itemPtr;
	canvasPtr->textInfo.selectAnchor = index;
    }
    if (canvasPtr->textInfo.selectAnchor <= index) {
    if (canvasPtr->textInfo.selectAnchor + 1 <= index + 1) {
	canvasPtr->textInfo.selectFirst = canvasPtr->textInfo.selectAnchor;
	canvasPtr->textInfo.selectLast = index;
    } else {
	canvasPtr->textInfo.selectFirst = index;
	canvasPtr->textInfo.selectFirst = ((int)index < 0) ? TCL_INDEX_NONE : index;
	canvasPtr->textInfo.selectLast = canvasPtr->textInfo.selectAnchor - 1;
    }
    if ((canvasPtr->textInfo.selectFirst != oldFirst)
	    || (canvasPtr->textInfo.selectLast != oldLast)
	    || (itemPtr != oldSelPtr)) {
	EventuallyRedrawItem(canvasPtr, itemPtr);
    }
5392
5393
5394
5395
5396
5397
5398
5399

5400
5401
5402

5403
5404
5405

5406
5407
5408
5409

5410
5411
5412
5413
5414
5415
5416
5683
5684
5685
5686
5687
5688
5689

5690
5691
5692

5693
5694
5695

5696
5697
5698
5699

5700
5701
5702
5703
5704
5705
5706
5707







-
+


-
+


-
+



-
+







 *
 * Side effects:
 *	None.
 *
 *--------------------------------------------------------------
 */

static int
static TkSizeT
CanvasFetchSelection(
    ClientData clientData,	/* Information about canvas widget. */
    int offset,			/* Offset within selection of first character
    TkSizeT offset,			/* Offset within selection of first character
				 * to be returned. */
    char *buffer,		/* Location in which to place selection. */
    int maxBytes)		/* Maximum number of bytes to place at buffer,
    TkSizeT maxBytes)		/* Maximum number of bytes to place at buffer,
				 * not including terminating NULL
				 * character. */
{
    TkCanvas *canvasPtr = clientData;
    TkCanvas *canvasPtr = (TkCanvas *)clientData;

    return ItemSelection(canvasPtr, canvasPtr->textInfo.selItemPtr, offset,
	    buffer, maxBytes);
}

/*
 *----------------------------------------------------------------------
5430
5431
5432
5433
5434
5435
5436
5437

5438
5439
5440
5441
5442
5443
5444
5721
5722
5723
5724
5725
5726
5727

5728
5729
5730
5731
5732
5733
5734
5735







-
+







 *----------------------------------------------------------------------
 */

static void
CanvasLostSelection(
    ClientData clientData)	/* Information about entry widget. */
{
    TkCanvas *canvasPtr = clientData;
    TkCanvas *canvasPtr = (TkCanvas *)clientData;

    EventuallyRedrawItem(canvasPtr, canvasPtr->textInfo.selItemPtr);
    canvasPtr->textInfo.selItemPtr = NULL;
}

/*
 *--------------------------------------------------------------
5552
5553
5554
5555
5556
5557
5558
5559
5560


5561
5562
5563
5564
5565
5566
5567
5843
5844
5845
5846
5847
5848
5849


5850
5851
5852
5853
5854
5855
5856
5857
5858







-
-
+
+







    Tcl_Interp *interp;
    int xOrigin, yOrigin, inset, width, height;
    int scrollX1, scrollX2, scrollY1, scrollY2;
    char *xScrollCmd, *yScrollCmd;
    Tcl_DString buf;

    /*
     * Save all the relevant values from the canvasPtr, because it might be
     * deleted as part of either of the two calls to Tcl_VarEval below.
     * Preserve the relevant values from the canvasPtr, because it might be
     * deleted as part of either of the two calls to Tcl_EvalEx below.
     */

    interp = canvasPtr->interp;
    Tcl_Preserve(interp);
    xScrollCmd = canvasPtr->xScrollCmd;
    if (xScrollCmd != NULL) {
	Tcl_Preserve(xScrollCmd);
5584
5585
5586
5587
5588
5589
5590
5591

5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609

5610
5611
5612
5613
5614
5615
5616
5875
5876
5877
5878
5879
5880
5881

5882
5883
5884
5885
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
5897
5898
5899

5900
5901
5902
5903
5904
5905
5906
5907







-
+

















-
+







	Tcl_Obj *fractions = ScrollFractions(xOrigin + inset,
		xOrigin + width - inset, scrollX1, scrollX2);

	Tcl_DStringInit(&buf);
	Tcl_DStringAppend(&buf, xScrollCmd, -1);
	Tcl_DStringAppend(&buf, " ", -1);
	Tcl_DStringAppend(&buf, Tcl_GetString(fractions), -1);
	result = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, 0);
	result = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, TCL_EVAL_GLOBAL);
	Tcl_DStringFree(&buf);
	Tcl_DecrRefCount(fractions);
	if (result != TCL_OK) {
	    Tcl_BackgroundException(interp, result);
	}
	Tcl_ResetResult(interp);
	Tcl_Release(xScrollCmd);
    }

    if (yScrollCmd != NULL) {
	Tcl_Obj *fractions = ScrollFractions(yOrigin + inset,
		yOrigin + height - inset, scrollY1, scrollY2);

	Tcl_DStringInit(&buf);
	Tcl_DStringAppend(&buf, yScrollCmd, -1);
	Tcl_DStringAppend(&buf, " ", -1);
	Tcl_DStringAppend(&buf, Tcl_GetString(fractions), -1);
	result = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, 0);
	result = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, TCL_EVAL_GLOBAL);
	Tcl_DStringFree(&buf);
	Tcl_DecrRefCount(fractions);
	if (result != TCL_OK) {
	    Tcl_BackgroundException(interp, result);
	}
	Tcl_ResetResult(interp);
	Tcl_Release(yScrollCmd);
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772

5773
5774
5775
5776
5777
5778

5779
5780
5781
5782
5783
5784
5785
6050
6051
6052
6053
6054
6055
6056

6057
6058
6059
6060
6061

6062
6063
6064
6065
6066
6067

6068
6069
6070
6071
6072
6073
6074
6075







-





-
+





-
+







 * Side effects:
 *	Memory is allocated for the objv array, which must be freed using
 *	ckfree() when no longer needed.
 *
 *----------------------------------------------------------------------
 */

/* ARGSUSED */
static const char **
TkGetStringsFromObjs(
    int objc,
    Tcl_Obj *const objv[])
{
    register int i;
    int i;
    const char **argv;

    if (objc <= 0) {
	return NULL;
    }
    argv = ckalloc((objc+1) * sizeof(char *));
    argv = (const char **)ckalloc((objc+1) * sizeof(char *));
    for (i = 0; i < objc; i++) {
	argv[i] = Tcl_GetString(objv[i]);
    }
    argv[objc] = 0;
    return argv;
}

Changes to generic/tkCanvas.h.
1
2
3
4
5
6
7
8



9
10
11
12
13
14
15
1
2
3
4
5



6
7
8
9
10
11
12
13
14
15





-
-
-
+
+
+







/*
 * 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.
 */

#ifndef _TKCANVAS
#define _TKCANVAS
143
144
145
146
147
148
149
150

151
152
153
154
155
156
157
143
144
145
146
147
148
149

150
151
152
153
154
155
156
157







-
+







				 * of the previous current item. */
    double closeEnough;		/* The mouse is assumed to be inside an item
				 * if it is this close to it. */
    XEvent pickEvent;		/* The event upon which the current choice of
				 * currentItem is based. Must be saved so that
				 * if the currentItem is deleted, can pick
				 * another. */
    int state;			/* Last known modifier state. Used to defer
    unsigned int state;		/* Last known modifier state. Used to defer
				 * picking a new current object while buttons
				 * are down. */

    /*
     * Information used for managing scrollbars:
     */

210
211
212
213
214
215
216
217

218
219
220
221
222
223
224
210
211
212
213
214
215
216

217
218
219
220
221
222
223
224







-
+







    char *takeFocus;		/* Value of -takefocus option; not used in the
				 * C code, but used by keyboard traversal
				 * scripts. Malloc'ed, but may be NULL. */
    double pixelsPerMM;		/* Scale factor between MM and pixels; used
				 * when converting coordinates. */
    int flags;			/* Various flags; see below for
				 * definitions. */
    int nextId;			/* Number to use as id for next item created
    TkSizeT nextId;			/* Number to use as id for next item created
				 * in widget. */
    Tk_PostscriptInfo psInfo;	/* Pointer to information used for generating
				 * Postscript for the canvas. NULL means no
				 * Postscript is currently being generated. */
    Tcl_HashTable idTable;	/* Table of integer indices. */

    /*
Changes to generic/tkClipboard.c.
1
2
3
4
5
6
7
8
9


10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27






28
29
30
31
32
33
34
1
2
3
4
5
6
7


8
9
10
11
12
13
14
15
16
17
18
19
20
21






22
23
24
25
26
27
28
29
30
31
32
33
34







-
-
+
+












-
-
-
-
-
-
+
+
+
+
+
+







/*
 * tkClipboard.c --
 *
 * 	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.
 */

#include "tkInt.h"
#include "tkSelect.h"

/*
 * Prototypes for functions used only in this file:
 */

static int		ClipboardAppHandler(ClientData clientData,
			    int offset, char *buffer, int maxBytes);
static int		ClipboardHandler(ClientData clientData,
			    int offset, char *buffer, int maxBytes);
static int		ClipboardWindowHandler(ClientData clientData,
			    int offset, char *buffer, int maxBytes);
static TkSizeT	ClipboardAppHandler(ClientData clientData,
			    TkSizeT offset, char *buffer, TkSizeT maxBytes);
static TkSizeT	ClipboardHandler(ClientData clientData,
			    TkSizeT offset, char *buffer, TkSizeT maxBytes);
static TkSizeT	ClipboardWindowHandler(ClientData clientData,
			    TkSizeT offset, char *buffer, TkSizeT maxBytes);
static void		ClipboardLostSel(ClientData clientData);
static int		ClipboardGetProc(ClientData clientData,
			    Tcl_Interp *interp, const char *portion);

/*
 *----------------------------------------------------------------------
 *
44
45
46
47
48
49
50
51

52
53
54

55
56
57

58
59

60
61
62
63
64



65
66
67
68
69
70
71
44
45
46
47
48
49
50

51
52
53

54
55
56

57
58

59
60
61



62
63
64
65
66
67
68
69
70
71







-
+


-
+


-
+

-
+


-
-
-
+
+
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
static TkSizeT
ClipboardHandler(
    ClientData clientData,	/* Information about data to fetch. */
    int offset,			/* Return selection bytes starting at this
    TkSizeT offset,			/* Return selection bytes starting at this
				 * offset. */
    char *buffer,		/* Place to store converted selection. */
    int maxBytes)		/* Maximum # of bytes to store at buffer. */
    TkSizeT maxBytes)		/* Maximum # of bytes to store at buffer. */
{
    TkClipboardTarget *targetPtr = clientData;
    TkClipboardTarget *targetPtr = (TkClipboardTarget *)clientData;
    TkClipboardBuffer *cbPtr;
    char *srcPtr, *destPtr;
    size_t count = 0;
    int scanned = 0;
    size_t length, freeCount;
    TkSizeT count = 0;
    TkSizeT scanned = 0;
    TkSizeT length, freeCount;

    /*
     * Skip to buffer containing offset byte
     */

    for (cbPtr = targetPtr->firstBufferPtr; ; cbPtr = cbPtr->nextPtr) {
	if (cbPtr == NULL) {
98
99
100
101
102
103
104
105

106
107
108
109
110
111
112
98
99
100
101
102
103
104

105
106
107
108
109
110
111
112







-
+







	cbPtr = cbPtr->nextPtr;
	if (cbPtr == NULL) {
	    break;
	}
	srcPtr = cbPtr->buffer;
	length = cbPtr->length;
    }
    return (int)count;
    return count;
}

/*
 *----------------------------------------------------------------------
 *
 * ClipboardAppHandler --
 *
122
123
124
125
126
127
128
129

130
131
132

133
134
135

136
137
138


139
140
141
142
143
144

145
146

147

148
149
150
151
152

153
154
155
156
157
158
159
122
123
124
125
126
127
128

129
130
131

132
133
134

135
136


137
138
139
140
141
142


143
144
145
146

147
148
149
150
151

152
153
154
155
156
157
158
159







-
+


-
+


-
+

-
-
+
+




-
-
+


+
-
+




-
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
static TkSizeT
ClipboardAppHandler(
    ClientData clientData,	/* Pointer to TkDisplay structure. */
    int offset,			/* Return selection bytes starting at this
    TkSizeT offset,			/* Return selection bytes starting at this
				 * offset. */
    char *buffer,		/* Place to store converted selection. */
    int maxBytes)		/* Maximum # of bytes to store at buffer. */
    TkSizeT maxBytes)		/* Maximum # of bytes to store at buffer. */
{
    TkDisplay *dispPtr = clientData;
    size_t length;
    TkDisplay *dispPtr = (TkDisplay *)clientData;
    TkSizeT length;
    const char *p;

    p = dispPtr->clipboardAppPtr->winPtr->nameUid;
    length = strlen(p);
    length -= offset;
    if (length <= 0) {
    if (length <= offset) {
	return 0;
    }
    length -= offset;
    if (length > (size_t) maxBytes) {
    if (length > maxBytes) {
	length = maxBytes;
    }
    memcpy(buffer, p, length);
    buffer[length] = 0;
    return (int)length;
    return length;
}

/*
 *----------------------------------------------------------------------
 *
 * ClipboardWindowHandler --
 *
167
168
169
170
171
172
173
174

175
176
177


178
179
180

181
182
183
184
185
186
187
167
168
169
170
171
172
173

174
175


176
177
178
179

180
181
182
183
184
185
186
187







-
+

-
-
+
+


-
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
static TkSizeT
ClipboardWindowHandler(
    ClientData clientData,	/* Not used. */
    int offset,			/* Return selection bytes starting at this
    TCL_UNUSED(void *),	/* Not used. */
    TCL_UNUSED(TkSizeT),			/* Return selection bytes starting at this
				 * offset. */
    char *buffer,		/* Place to store converted selection. */
    int maxBytes)		/* Maximum # of bytes to store at buffer. */
    TCL_UNUSED(TkSizeT))		/* Maximum # of bytes to store at buffer. */
{
    buffer[0] = '.';
    buffer[1] = 0;
    return 1;
}

/*
202
203
204
205
206
207
208
209

210
211
212
213
214
215
216
202
203
204
205
206
207
208

209
210
211
212
213
214
215
216







-
+







 *----------------------------------------------------------------------
 */

static void
ClipboardLostSel(
    ClientData clientData)	/* Pointer to TkDisplay structure. */
{
    TkDisplay *dispPtr = clientData;
    TkDisplay *dispPtr = (TkDisplay *)clientData;

    dispPtr->clipboardActive = 0;
}

/*
 *----------------------------------------------------------------------
 *
355
356
357
358
359
360
361
362

363
364
365
366
367
368
369
355
356
357
358
359
360
361

362
363
364
365
366
367
368
369







-
+







    for (targetPtr = dispPtr->clipTargetPtr; targetPtr != NULL;
	    targetPtr = targetPtr->nextPtr) {
	if (targetPtr->type == type) {
	    break;
	}
    }
    if (targetPtr == NULL) {
	targetPtr = ckalloc(sizeof(TkClipboardTarget));
	targetPtr = (TkClipboardTarget *)ckalloc(sizeof(TkClipboardTarget));
	targetPtr->type = type;
	targetPtr->format = format;
	targetPtr->firstBufferPtr = targetPtr->lastBufferPtr = NULL;
	targetPtr->nextPtr = dispPtr->clipTargetPtr;
	dispPtr->clipTargetPtr = targetPtr;
	Tk_CreateSelHandler(dispPtr->clipWindow, dispPtr->clipboardAtom,
		type, ClipboardHandler, targetPtr, format);
377
378
379
380
381
382
383
384

385
386
387
388
389
390
391
392
393
394

395
396
397
398
399
400
401
377
378
379
380
381
382
383

384
385
386
387
388
389
390
391
392
393

394
395
396
397
398
399
400
401







-
+









-
+







	return TCL_ERROR;
    }

    /*
     * Append a new buffer to the buffer chain.
     */

    cbPtr = ckalloc(sizeof(TkClipboardBuffer));
    cbPtr = (TkClipboardBuffer *)ckalloc(sizeof(TkClipboardBuffer));
    cbPtr->nextPtr = NULL;
    if (targetPtr->lastBufferPtr != NULL) {
	targetPtr->lastBufferPtr->nextPtr = cbPtr;
    } else {
	targetPtr->firstBufferPtr = cbPtr;
    }
    targetPtr->lastBufferPtr = cbPtr;

    cbPtr->length = strlen(buffer);
    cbPtr->buffer = ckalloc(cbPtr->length + 1);
    cbPtr->buffer = (char *)ckalloc(cbPtr->length + 1);
    strcpy(cbPtr->buffer, buffer);

    TkSelUpdateClipboard((TkWindow *) dispPtr->clipWindow, targetPtr);

    return TCL_OK;
}

419
420
421
422
423
424
425
426

427
428
429
430
431
432
433
419
420
421
422
423
424
425

426
427
428
429
430
431
432
433







-
+







int
Tk_ClipboardObjCmd(
    ClientData clientData,	/* Main window associated with interpreter. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument strings. */
{
    Tk_Window tkwin = (Tk_Window) clientData;
    Tk_Window tkwin = (Tk_Window)clientData;
    const char *path = NULL;
    Atom selection;
    static const char *const optionStrings[] = { "append", "clear", "get", NULL };
    enum options { CLIPBOARD_APPEND, CLIPBOARD_CLEAR, CLIPBOARD_GET };
    int index, i;

    if (objc < 2) {
446
447
448
449
450
451
452
453


454
455
456

457
458
459
460
461
462
463
446
447
448
449
450
451
452

453
454
455
456

457
458
459
460
461
462
463
464







-
+
+


-
+







	const char *targetName = NULL;
	const char *formatName = NULL;
	const char *string;
	static const char *const appendOptionStrings[] = {
	    "-displayof", "-format", "-type", NULL
	};
	enum appendOptions { APPEND_DISPLAYOF, APPEND_FORMAT, APPEND_TYPE };
	int subIndex, length;
	int subIndex;
	TkSizeT length;

	for (i = 2; i < objc - 1; i++) {
	    string = Tcl_GetStringFromObj(objv[i], &length);
	    string = TkGetStringFromObj(objv[i], &length);
	    if (string[0] != '-') {
		break;
	    }

	    /*
	     * If the argument is "--", it signifies the end of arguments.
	     */
632
633
634
635
636
637
638
639
640


641
642
643
644
645
646
647
633
634
635
636
637
638
639


640
641
642
643
644
645
646
647
648







-
-
+
+







 *	Sets up the clipWindow and related data structures.
 *
 *----------------------------------------------------------------------
 */

int
TkClipInit(
    Tcl_Interp *interp,		/* Interpreter to use for error reporting. */
    register TkDisplay *dispPtr)/* Display to initialize. */
    TCL_UNUSED(Tcl_Interp *),		/* Interpreter to use for error reporting. */
    TkDisplay *dispPtr)/* Display to initialize. */
{
    XSetWindowAttributes atts;

    dispPtr->clipTargetPtr = NULL;
    dispPtr->clipboardActive = 0;
    dispPtr->clipboardAppPtr = NULL;

696
697
698
699
700
701
702
703
704
705
706
707
708

709
710
711
712

713
714
715
716
717
718
719
720
721
722
697
698
699
700
701
702
703

704
705
706
707

708
709
710
711

712
713
714
715
716
717
718
719
720
721
722







-




-
+



-
+










 * Side effects:
 *	Bytes get appended to the dynamic string pointed to by the clientData
 *	argument.
 *
 *--------------------------------------------------------------
 */

	/* ARGSUSED */
static int
ClipboardGetProc(
    ClientData clientData,	/* Dynamic string holding partially assembled
				 * selection. */
    Tcl_Interp *interp,		/* Interpreter used for error reporting (not
    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_DStringAppend((Tcl_DString *)clientData, portion, -1);
    return TCL_OK;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Changes to generic/tkCmds.c.
1
2
3
4
5
6
7
8
9



10
11
12
13
14
15
16
1
2
3
4
5
6



7
8
9
10
11
12
13
14
15
16






-
-
-
+
+
+







/*
 * 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.
 */

#include "tkInt.h"

95
96
97
98
99
100
101
102

103
104
105
106
107
108
109
95
96
97
98
99
100
101

102
103
104
105
106
107
108
109







-
+







    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    static const char *const bellOptions[] = {
	"-displayof", "-nice", NULL
    };
    enum options { TK_BELL_DISPLAYOF, TK_BELL_NICE };
    Tk_Window tkwin = clientData;
    Tk_Window tkwin = (Tk_Window)clientData;
    int i, index, nice = 0;
    Tk_ErrorHandler handler;

    if (objc > 4) {
    wrongArgs:
	Tcl_WrongNumArgs(interp, 1, objv, "?-displayof window? ?-nice?");
	return TCL_ERROR;
159
160
161
162
163
164
165
166

167
168
169
170
171
172
173
159
160
161
162
163
164
165

166
167
168
169
170
171
172
173







-
+







int
Tk_BindObjCmd(
    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;
    TkWindow *winPtr;
    ClientData object;
    const char *string;

    if ((objc < 2) || (objc > 4)) {
	Tcl_WrongNumArgs(interp, 1, objv, "window ?pattern? ?command?");
	return TCL_ERROR;
183
184
185
186
187
188
189
190

191
192
193
194
195
196
197
183
184
185
186
187
188
189

190
191
192
193
194
195
196
197







-
+







    if (string[0] == '.') {
	winPtr = (TkWindow *) Tk_NameToWindow(interp, string, tkwin);
	if (winPtr == NULL) {
	    return TCL_ERROR;
	}
	object = (ClientData) winPtr->pathName;
    } else {
	winPtr = clientData;
	winPtr = (TkWindow *)clientData;
	object = (ClientData) Tk_GetUid(string);
    }

    /*
     * If there are four arguments, the command is modifying a binding. If
     * there are three arguments, the command is querying a binding. If there
     * are only two arguments, the command is querying all the bindings for
281
282
283
284
285
286
287
288

289
290
291

292
293
294
295
296
297
298
281
282
283
284
285
286
287

288
289
290

291
292
293
294
295
296
297
298







-
+


-
+







    if (winPtr->numTags != 0) {
	/*
	 * Make a copy of the tags for the window, replacing window names with
	 * pointers to the pathName from the appropriate window.
	 */

	if (winPtr->numTags > MAX_OBJS) {
	    objPtr = ckalloc(winPtr->numTags * sizeof(ClientData));
	    objPtr = (void **)ckalloc(winPtr->numTags * sizeof(void *));
	}
	for (i = 0; i < winPtr->numTags; i++) {
	    p = winPtr->tagPtr[i];
	    p = (const char *)winPtr->tagPtr[i];
	    if (*p == '.') {
		hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->nameTable, p);
		if (hPtr != NULL) {
		    p = ((TkWindow *) Tcl_GetHashValue(hPtr))->pathName;
		} else {
		    p = NULL;
		}
343
344
345
346
347
348
349
350

351
352
353
354
355
356
357
343
344
345
346
347
348
349

350
351
352
353
354
355
356
357







-
+







int
Tk_BindtagsObjCmd(
    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;
    TkWindow *winPtr, *winPtr2;
    int i, length;
    const char *p;
    Tcl_Obj *listPtr, **tags;

    if ((objc < 2) || (objc > 3)) {
	Tcl_WrongNumArgs(interp, 1, objv, "window ?taglist?");
395
396
397
398
399
400
401
402

403
404
405
406
407
408
409
410
411
412
413
414
415

416
417
418
419
420
421
422
395
396
397
398
399
400
401

402
403
404
405
406
407
408
409
410
411
412
413
414

415
416
417
418
419
420
421
422







-
+












-
+







	return TCL_ERROR;
    }
    if (length == 0) {
	return TCL_OK;
    }

    winPtr->numTags = length;
    winPtr->tagPtr = ckalloc(length * sizeof(ClientData));
    winPtr->tagPtr = (void **)ckalloc(length * sizeof(void *));
    for (i = 0; i < length; i++) {
	p = Tcl_GetString(tags[i]);
	if (p[0] == '.') {
	    char *copy;

	    /*
	     * Handle names starting with "." specially: store a malloc'ed
	     * string, rather than a Uid; at event time we'll look up the name
	     * in the window table and use the corresponding window, if there
	     * is one.
	     */

	    copy = ckalloc(strlen(p) + 1);
	    copy = (char *)ckalloc(strlen(p) + 1);
	    strcpy(copy, p);
	    winPtr->tagPtr[i] = (ClientData) copy;
	} else {
	    winPtr->tagPtr[i] = (ClientData) Tk_GetUid(p);
	}
    }
    return TCL_OK;
444
445
446
447
448
449
450
451

452
453
454
455
456
457
458
444
445
446
447
448
449
450

451
452
453
454
455
456
457
458







-
+







TkFreeBindingTags(
    TkWindow *winPtr)		/* Window whose tags are to be released. */
{
    int i;
    const char *p;

    for (i = 0; i < winPtr->numTags; i++) {
	p = winPtr->tagPtr[i];
	p = (const char *)winPtr->tagPtr[i];
	if (*p == '.') {
	    /*
	     * Names starting with "." are malloced rather than Uids, so they
	     * have to be freed.
	     */

	    ckfree((char *)p);
484
485
486
487
488
489
490
491

492
493
494
495
496
497
498
484
485
486
487
488
489
490

491
492
493
494
495
496
497
498







-
+







Tk_DestroyObjCmd(
    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 window;
    Tk_Window tkwin = clientData;
    Tk_Window tkwin = (Tk_Window)clientData;
    int i;

    for (i = 1; i < objc; i++) {
	window = Tk_NameToWindow(interp, Tcl_GetString(objv[i]), tkwin);
	if (window == NULL) {
	    Tcl_ResetResult(interp);
	    continue;
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538

539
540
541
542
543
544
545
523
524
525
526
527
528
529

530
531
532
533
534
535
536

537
538
539
540
541
542
543
544







-







-
+







 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
int
Tk_LowerObjCmd(
    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 mainwin = clientData;
    Tk_Window mainwin = (Tk_Window)clientData;
    Tk_Window tkwin, other;

    if ((objc != 2) && (objc != 3)) {
	Tcl_WrongNumArgs(interp, 1, objv, "window ?belowThis?");
	return TCL_ERROR;
    }

583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598

599
600
601
602
603
604
605
582
583
584
585
586
587
588

589
590
591
592
593
594
595

596
597
598
599
600
601
602
603







-







-
+







 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
int
Tk_RaiseObjCmd(
    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 mainwin = clientData;
    Tk_Window mainwin = (Tk_Window)clientData;
    Tk_Window tkwin, other;

    if ((objc != 2) && (objc != 3)) {
	Tcl_WrongNumArgs(interp, 1, objv, "window ?aboveThis?");
	return TCL_ERROR;
    }

679
680
681
682
683
684
685
686

687
688
689
690
691
692
693
677
678
679
680
681
682
683

684
685
686
687
688
689
690
691







-
+







int
AppnameCmd(
    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;
    TkWindow *winPtr;
    const char *string;

    if (Tcl_IsSafe(interp)) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"appname not accessible in a safe interpreter", -1));
	Tcl_SetErrorCode(interp, "TK", "SAFE", "APPLICATION", NULL);
711
712
713
714
715
716
717
718

719
720
721
722
723
724
725
709
710
711
712
713
714
715

716
717
718
719
720
721
722
723







-
+







int
CaretCmd(
    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;
    int index;
    Tcl_Obj *objPtr;
    TkCaret *caretPtr;
    Tk_Window window;
    static const char *const caretStrings[] = {
	"-x",	"-y", "-height", NULL
    };
742
743
744
745
746
747
748
749

750
751
752
753

754
755
756
757

758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777

778
779
780
781
782
783
784
740
741
742
743
744
745
746

747
748
749
750

751
752
753
754

755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774

775
776
777
778
779
780
781
782







-
+



-
+



-
+



















-
+







	 * Return all the current values
	 */

	objPtr = Tcl_NewObj();
	Tcl_ListObjAppendElement(interp, objPtr,
		Tcl_NewStringObj("-height", 7));
	Tcl_ListObjAppendElement(interp, objPtr,
		Tcl_NewIntObj(caretPtr->height));
		Tcl_NewWideIntObj(caretPtr->height));
	Tcl_ListObjAppendElement(interp, objPtr,
		Tcl_NewStringObj("-x", 2));
	Tcl_ListObjAppendElement(interp, objPtr,
		Tcl_NewIntObj(caretPtr->x));
		Tcl_NewWideIntObj(caretPtr->x));
	Tcl_ListObjAppendElement(interp, objPtr,
		Tcl_NewStringObj("-y", 2));
	Tcl_ListObjAppendElement(interp, objPtr,
		Tcl_NewIntObj(caretPtr->y));
		Tcl_NewWideIntObj(caretPtr->y));
	Tcl_SetObjResult(interp, objPtr);
    } else if (objc == 3) {
	int value;

	/*
	 * Return the current value of the selected option
	 */

	if (Tcl_GetIndexFromObj(interp, objv[2], caretStrings,
		"caret option", 0, &index) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (index == TK_CARET_X) {
	    value = caretPtr->x;
	} else if (index == TK_CARET_Y) {
	    value = caretPtr->y;
	} else /* if (index == TK_CARET_HEIGHT) -- last case */ {
	    value = caretPtr->height;
	}
	Tcl_SetObjResult(interp, Tcl_NewIntObj(value));
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(value));
    } else {
	int i, value, x = 0, y = 0, height = -1;

	for (i = 2; i < objc; i += 2) {
	    if ((Tcl_GetIndexFromObj(interp, objv[i], caretStrings,
		    "caret option", 0, &index) != TCL_OK) ||
		    Tcl_GetIntFromObj(interp,objv[i+1],&value) != TCL_OK) {
803
804
805
806
807
808
809
810

811
812
813
814
815
816
817
801
802
803
804
805
806
807

808
809
810
811
812
813
814
815







-
+







int
ScalingCmd(
    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;
    Screen *screenPtr;
    int skip, width, height;
    double d;

    if (Tcl_IsSafe(interp)) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"scaling not accessible in a safe interpreter", -1));
854
855
856
857
858
859
860
861

862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891

892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909

910
911
912
913
914
915
916
852
853
854
855
856
857
858

859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875





876
877
878
879
880
881
882


883
884
885
886
887

888
889
890
891
892
893
894
895
896
897
898
899

900
901
902
903
904
905
906
907







-
+
















-
-
-
-
-







-
-
+




-












-
+







int
UseinputmethodsCmd(
    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;
    TkDisplay *dispPtr;
    int skip;

    if (Tcl_IsSafe(interp)) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"useinputmethods not accessible in a safe interpreter", -1));
	Tcl_SetErrorCode(interp, "TK", "SAFE", "INPUT_METHODS", NULL);
	return TCL_ERROR;
    }

    skip = TkGetDisplayOf(interp, objc-1, objv+1, &tkwin);
    if (skip < 0) {
	return TCL_ERROR;
    }
    dispPtr = ((TkWindow *) tkwin)->dispPtr;
    if ((objc - skip) == 2) {
	/*
	 * In the case where TK_USE_INPUT_METHODS is not defined, this
	 * will be ignored and we will always return 0. That will indicate
	 * to the user that input methods are just not available.
	 */

	int boolVal;

	if (Tcl_GetBooleanFromObj(interp, objv[1+skip],
		&boolVal) != TCL_OK) {
	    return TCL_ERROR;
	}
#ifdef TK_USE_INPUT_METHODS
	if (boolVal) {
	if (boolVal && (dispPtr->inputMethod != NULL)) {
	    dispPtr->flags |= TK_DISPLAY_USE_IM;
	} else {
	    dispPtr->flags &= ~TK_DISPLAY_USE_IM;
	}
#endif /* TK_USE_INPUT_METHODS */
    } else if ((objc - skip) != 1) {
	Tcl_WrongNumArgs(interp, 1, objv,
		"?-displayof window? ?boolean?");
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp,
	    Tcl_NewBooleanObj(dispPtr->flags & TK_DISPLAY_USE_IM));
    return TCL_OK;
}

int
WindowingsystemCmd(
    ClientData clientData,	/* Main window associated with interpreter. */
    TCL_UNUSED(void *),	/* Main window associated with interpreter. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    const char *windowingsystem;

    if (objc != 1) {
931
932
933
934
935
936
937
938

939
940
941
942
943
944
945

946
947
948
949

950
951
952
953
954
955
956
922
923
924
925
926
927
928

929
930
931
932
933
934
935

936
937
938
939

940
941
942
943
944
945
946
947







-
+






-
+



-
+







int
InactiveCmd(
    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;
    int skip = TkGetDisplayOf(interp, objc - 1, objv + 1, &tkwin);

    if (skip < 0) {
	return TCL_ERROR;
    }
    if (objc - skip == 1) {
	long inactive;
	Tcl_WideInt inactive;

	inactive = (Tcl_IsSafe(interp) ? -1 :
		Tk_GetUserInactiveTime(Tk_Display(tkwin)));
	Tcl_SetObjResult(interp, Tcl_NewLongObj(inactive));
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(inactive));
    } else if (objc - skip == 2) {
	const char *string;

	string = Tcl_GetString(objv[objc-1]);
	if (strcmp(string, "reset") != 0) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "bad option \"%s\": must be reset", string));
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002

1003
1004
1005
1006
1007
1008
1009
978
979
980
981
982
983
984

985
986
987
988
989
990
991

992
993
994
995
996
997
998
999







-







-
+







 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
int
Tk_TkwaitObjCmd(
    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;
    int done, index;
    int code = TCL_OK;
    static const char *const optionStrings[] = {
	"variable", "visibility", "window", NULL
    };
    enum options {
	TKWAIT_VARIABLE, TKWAIT_VISIBILITY, TKWAIT_WINDOW
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130




1131
1132

1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144

1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158

1159
1160
1161
1162
1163
1164
1165
1106
1107
1108
1109
1110
1111
1112

1113
1114
1115




1116
1117
1118
1119
1120

1121
1122
1123
1124
1125
1126

1127
1128
1129
1130
1131

1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145

1146
1147
1148
1149
1150
1151
1152
1153







-



-
-
-
-
+
+
+
+

-
+





-





-
+













-
+








    if (code == TCL_OK)
    Tcl_ResetResult(interp);

    return code;
}

	/* ARGSUSED */
static char *
WaitVariableProc(
    ClientData clientData,	/* Pointer to integer to set to 1. */
    Tcl_Interp *interp,		/* Interpreter containing variable. */
    const char *name1,		/* Name of variable. */
    const char *name2,		/* Second part of variable name. */
    int flags)			/* Information about what happened. */
    TCL_UNUSED(Tcl_Interp *),		/* Interpreter containing variable. */
    TCL_UNUSED(const char *),		/* Name of variable. */
    TCL_UNUSED(const char *),		/* Second part of variable name. */
    TCL_UNUSED(int))			/* Information about what happened. */
{
    int *donePtr = clientData;
    int *donePtr = (int *)clientData;

    *donePtr = 1;
    return NULL;
}

	/*ARGSUSED*/
static void
WaitVisibilityProc(
    ClientData clientData,	/* Pointer to integer to set to 1. */
    XEvent *eventPtr)		/* Information about event (not used). */
{
    int *donePtr = clientData;
    int *donePtr = (int *)clientData;

    if (eventPtr->type == VisibilityNotify) {
	*donePtr = 1;
    } else if (eventPtr->type == DestroyNotify) {
	*donePtr = 2;
    }
}

static void
WaitWindowProc(
    ClientData clientData,	/* Pointer to integer to set to 1. */
    XEvent *eventPtr)		/* Information about event. */
{
    int *donePtr = clientData;
    int *donePtr = (int *)clientData;

    if (eventPtr->type == DestroyNotify) {
	*donePtr = 1;
    }
}

/*
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185

1186
1187
1188
1189
1190
1191
1192
1163
1164
1165
1166
1167
1168
1169

1170
1171

1172
1173
1174
1175
1176
1177
1178
1179







-


-
+







 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
int
Tk_UpdateObjCmd(
    ClientData clientData,	/* Main window associated with interpreter. */
    TCL_UNUSED(void *),	/* Main window associated with interpreter. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    static const char *const updateOptions[] = {"idletasks", NULL};
    int flags, index;
    TkDisplay *dispPtr;
1284
1285
1286
1287
1288
1289
1290
1291

1292
1293
1294
1295
1296
1297
1298
1271
1272
1273
1274
1275
1276
1277

1278
1279
1280
1281
1282
1283
1284
1285







-
+







    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int index, x, y, width, height, useX, useY, c_class, skip;
    const char *string;
    TkWindow *winPtr;
    Tk_Window tkwin = clientData;
    Tk_Window tkwin = (Tk_Window)clientData;

    static const TkStateMap visualMap[] = {
	{PseudoColor,	"pseudocolor"},
	{GrayScale,	"grayscale"},
	{DirectColor,	"directcolor"},
	{TrueColor,	"truecolor"},
	{StaticColor,	"staticcolor"},
1359
1360
1361
1362
1363
1364
1365
1366

1367
1368
1369
1370
1371
1372
1373
1346
1347
1348
1349
1350
1351
1352

1353
1354
1355
1356
1357
1358
1359
1360







-
+







	}
    }
    winPtr = (TkWindow *) tkwin;

    switch ((enum options) index) {
    case WIN_CELLS:
	Tcl_SetObjResult(interp,
		Tcl_NewIntObj(Tk_Visual(tkwin)->map_entries));
		Tcl_NewWideIntObj(Tk_Visual(tkwin)->map_entries));
	break;
    case WIN_CHILDREN: {
	Tcl_Obj *strPtr, *resultPtr = Tcl_NewObj();

	winPtr = winPtr->childList;
	for ( ; winPtr != NULL; winPtr = winPtr->nextPtr) {
	    if (!(winPtr->flags & TK_ANONYMOUS_WINDOW)) {
1382
1383
1384
1385
1386
1387
1388
1389

1390
1391
1392
1393
1394
1395
1396

1397
1398
1399
1400
1401
1402
1403
1369
1370
1371
1372
1373
1374
1375

1376
1377
1378
1379
1380
1381
1382

1383
1384
1385
1386
1387
1388
1389
1390







-
+






-
+







	Tcl_SetObjResult(interp, Tcl_NewStringObj(Tk_Class(tkwin), -1));
	break;
    case WIN_COLORMAPFULL:
	Tcl_SetObjResult(interp,
		Tcl_NewBooleanObj(TkpCmapStressed(tkwin,Tk_Colormap(tkwin))));
	break;
    case WIN_DEPTH:
	Tcl_SetObjResult(interp, Tcl_NewIntObj(Tk_Depth(tkwin)));
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(Tk_Depth(tkwin)));
	break;
    case WIN_GEOMETRY:
	Tcl_SetObjResult(interp, Tcl_ObjPrintf("%dx%d+%d+%d",
		Tk_Width(tkwin), Tk_Height(tkwin), Tk_X(tkwin), Tk_Y(tkwin)));
	break;
    case WIN_HEIGHT:
	Tcl_SetObjResult(interp, Tcl_NewIntObj(Tk_Height(tkwin)));
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(Tk_Height(tkwin)));
	break;
    case WIN_ID: {
	char buf[TCL_INTEGER_SPACE];

	Tk_MakeWindowExist(tkwin);
	TkpPrintWindowId(buf, Tk_WindowId(tkwin));
	Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, -1));
1440
1441
1442
1443
1444
1445
1446
1447
1448


1449
1450
1451

1452
1453

1454
1455
1456
1457

1458
1459
1460

1461
1462
1463
1464

1465
1466
1467
1468

1469
1470
1471
1472
1473
1474
1475
1476

1477
1478
1479
1480

1481
1482
1483
1484

1485
1486
1487
1488

1489
1490
1491
1492

1493
1494
1495
1496

1497
1498
1499
1500
1501
1502
1503
1427
1428
1429
1430
1431
1432
1433


1434
1435
1436
1437

1438
1439

1440
1441
1442
1443

1444
1445
1446

1447
1448
1449
1450

1451
1452
1453
1454

1455
1456
1457
1458
1459
1460
1461
1462

1463
1464
1465
1466

1467
1468
1469
1470

1471
1472
1473
1474

1475
1476
1477
1478

1479
1480
1481
1482

1483
1484
1485
1486
1487
1488
1489
1490







-
-
+
+


-
+

-
+



-
+


-
+



-
+



-
+







-
+



-
+



-
+



-
+



-
+



-
+







	    y = -1;
	} else {
	    TkGetPointerCoords((Tk_Window) winPtr, &x, &y);
	}
	if (useX & useY) {
	    Tcl_Obj *xyObj[2];

	    xyObj[0] = Tcl_NewIntObj(x);
	    xyObj[1] = Tcl_NewIntObj(y);
	    xyObj[0] = Tcl_NewWideIntObj(x);
	    xyObj[1] = Tcl_NewWideIntObj(y);
	    Tcl_SetObjResult(interp, Tcl_NewListObj(2, xyObj));
	} else if (useX) {
	    Tcl_SetObjResult(interp, Tcl_NewIntObj(x));
	    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(x));
	} else {
	    Tcl_SetObjResult(interp, Tcl_NewIntObj(y));
	    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(y));
	}
	break;
    case WIN_REQHEIGHT:
	Tcl_SetObjResult(interp, Tcl_NewIntObj(Tk_ReqHeight(tkwin)));
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(Tk_ReqHeight(tkwin)));
	break;
    case WIN_REQWIDTH:
	Tcl_SetObjResult(interp, Tcl_NewIntObj(Tk_ReqWidth(tkwin)));
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(Tk_ReqWidth(tkwin)));
	break;
    case WIN_ROOTX:
	Tk_GetRootCoords(tkwin, &x, &y);
	Tcl_SetObjResult(interp, Tcl_NewIntObj(x));
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(x));
	break;
    case WIN_ROOTY:
	Tk_GetRootCoords(tkwin, &x, &y);
	Tcl_SetObjResult(interp, Tcl_NewIntObj(y));
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(y));
	break;
    case WIN_SCREEN:
	Tcl_SetObjResult(interp, Tcl_ObjPrintf("%s.%d",
		Tk_DisplayName(tkwin), Tk_ScreenNumber(tkwin)));
	break;
    case WIN_SCREENCELLS:
	Tcl_SetObjResult(interp,
		Tcl_NewIntObj(CellsOfScreen(Tk_Screen(tkwin))));
		Tcl_NewWideIntObj(CellsOfScreen(Tk_Screen(tkwin))));
	break;
    case WIN_SCREENDEPTH:
	Tcl_SetObjResult(interp,
		Tcl_NewIntObj(DefaultDepthOfScreen(Tk_Screen(tkwin))));
		Tcl_NewWideIntObj(DefaultDepthOfScreen(Tk_Screen(tkwin))));
	break;
    case WIN_SCREENHEIGHT:
	Tcl_SetObjResult(interp,
		Tcl_NewIntObj(HeightOfScreen(Tk_Screen(tkwin))));
		Tcl_NewWideIntObj(HeightOfScreen(Tk_Screen(tkwin))));
	break;
    case WIN_SCREENWIDTH:
	Tcl_SetObjResult(interp,
		Tcl_NewIntObj(WidthOfScreen(Tk_Screen(tkwin))));
		Tcl_NewWideIntObj(WidthOfScreen(Tk_Screen(tkwin))));
	break;
    case WIN_SCREENMMHEIGHT:
	Tcl_SetObjResult(interp,
		Tcl_NewIntObj(HeightMMOfScreen(Tk_Screen(tkwin))));
		Tcl_NewWideIntObj(HeightMMOfScreen(Tk_Screen(tkwin))));
	break;
    case WIN_SCREENMMWIDTH:
	Tcl_SetObjResult(interp,
		Tcl_NewIntObj(WidthMMOfScreen(Tk_Screen(tkwin))));
		Tcl_NewWideIntObj(WidthMMOfScreen(Tk_Screen(tkwin))));
	break;
    case WIN_SCREENVISUAL:
	c_class = DefaultVisualOfScreen(Tk_Screen(tkwin))->c_class;
	goto visual;
    case WIN_SERVER:
	TkGetServerInfo(interp, tkwin);
	break;
1535
1536
1537
1538
1539
1540
1541
1542

1543
1544
1545
1546

1547
1548
1549
1550

1551
1552
1553
1554

1555
1556
1557

1558
1559
1560

1561
1562
1563

1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582

1583
1584
1585
1586

1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597

1598
1599
1600
1601
1602
1603
1604
1522
1523
1524
1525
1526
1527
1528

1529
1530
1531
1532

1533
1534
1535
1536

1537
1538
1539
1540

1541
1542
1543

1544
1545
1546

1547
1548
1549

1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568

1569
1570
1571
1572

1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583

1584
1585
1586
1587
1588
1589
1590
1591







-
+



-
+



-
+



-
+


-
+


-
+


-
+


















-
+



-
+










-
+







	break;
    case WIN_VISUALID:
	Tcl_SetObjResult(interp, Tcl_ObjPrintf("0x%x", (unsigned)
		XVisualIDFromVisual(Tk_Visual(tkwin))));
	break;
    case WIN_VROOTHEIGHT:
	Tk_GetVRootGeometry(tkwin, &x, &y, &width, &height);
	Tcl_SetObjResult(interp, Tcl_NewIntObj(height));
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(height));
	break;
    case WIN_VROOTWIDTH:
	Tk_GetVRootGeometry(tkwin, &x, &y, &width, &height);
	Tcl_SetObjResult(interp, Tcl_NewIntObj(width));
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(width));
	break;
    case WIN_VROOTX:
	Tk_GetVRootGeometry(tkwin, &x, &y, &width, &height);
	Tcl_SetObjResult(interp, Tcl_NewIntObj(x));
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(x));
	break;
    case WIN_VROOTY:
	Tk_GetVRootGeometry(tkwin, &x, &y, &width, &height);
	Tcl_SetObjResult(interp, Tcl_NewIntObj(y));
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(y));
	break;
    case WIN_WIDTH:
	Tcl_SetObjResult(interp, Tcl_NewIntObj(Tk_Width(tkwin)));
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(Tk_Width(tkwin)));
	break;
    case WIN_X:
	Tcl_SetObjResult(interp, Tcl_NewIntObj(Tk_X(tkwin)));
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(Tk_X(tkwin)));
	break;
    case WIN_Y:
	Tcl_SetObjResult(interp, Tcl_NewIntObj(Tk_Y(tkwin)));
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(Tk_Y(tkwin)));
	break;

	/*
	 * Uses -displayof.
	 */

    case WIN_ATOM:
	skip = TkGetDisplayOf(interp, objc - 2, objv + 2, &tkwin);
	if (skip < 0) {
	    return TCL_ERROR;
	}
	if (objc - skip != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?-displayof window? name");
	    return TCL_ERROR;
	}
	objv += skip;
	string = Tcl_GetString(objv[2]);
	Tcl_SetObjResult(interp,
		Tcl_NewLongObj((long) Tk_InternAtom(tkwin, string)));
		Tcl_NewWideIntObj(Tk_InternAtom(tkwin, string)));
	break;
    case WIN_ATOMNAME: {
	const char *name;
	long id;
	Tcl_WideInt id;

	skip = TkGetDisplayOf(interp, objc - 2, objv + 2, &tkwin);
	if (skip < 0) {
	    return TCL_ERROR;
	}
	if (objc - skip != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?-displayof window? id");
	    return TCL_ERROR;
	}
	objv += skip;
	if (Tcl_GetLongFromObj(interp, objv[2], &id) != TCL_OK) {
	if (Tcl_GetWideIntFromObj(interp, objv[2], &id) != TCL_OK) {
	    return TCL_ERROR;
	}
	name = Tk_GetAtomName(tkwin, (Atom) id);
	if (strcmp(name, "?bad atom?") == 0) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "no atom exists with id \"%s\"", Tcl_GetString(objv[2])));
	    Tcl_SetErrorCode(interp, "TK", "LOOKUP", "ATOM",
1731
1732
1733
1734
1735
1736
1737
1738

1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750











1751






1752
1753
1754
1755
1756
1757
1758
1759
1760
1761

1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782

1783
1784

1785
1786
1787
1788
1789
1790
1791
1718
1719
1720
1721
1722
1723
1724

1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748

1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763

1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784

1785
1786

1787
1788
1789
1790
1791
1792
1793
1794







-
+












+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+









-
+




















-
+

-
+







	if (TkGetWindowFromObj(interp, tkwin, objv[2], &tkwin) != TCL_OK) {
	    return TCL_ERROR;
	}
	string = Tcl_GetString(objv[3]);
	if (Tk_GetPixels(interp, tkwin, string, &pixels) != TCL_OK) {
	    return TCL_ERROR;
	}
	Tcl_SetObjResult(interp, Tcl_NewIntObj(pixels));
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(pixels));
	break;
    }
    case WIN_RGB: {
	XColor *colorPtr;

	if (objc != 4) {
	    Tcl_WrongNumArgs(interp, 2, objv, "window colorName");
	    return TCL_ERROR;
	}
	if (TkGetWindowFromObj(interp, tkwin, objv[2], &tkwin) != TCL_OK) {
	    return TCL_ERROR;
	}
#ifdef TK_HAS_DYNAMIC_COLORS

	/*
	 * Make sure that the TkColor used for the winfo rgb command is
	 * destroyed when we are through with it, so we do not get stale RGB
	 * values next time.
	 */

	{
	    Colormap temp = Tk_Colormap(tkwin);
	    Tk_Colormap(tkwin) = TK_DYNAMIC_COLORMAP;
	colorPtr = Tk_GetColor(interp, tkwin, Tcl_GetString(objv[3]));
	    colorPtr = Tk_GetColor(interp, tkwin, Tcl_GetString(objv[3]));
	    Tk_Colormap(tkwin) = temp;
	}
#else
	colorPtr = Tk_GetColor(interp, tkwin, Tcl_GetString(objv[3]));
#endif
	if (colorPtr == NULL) {
	    return TCL_ERROR;
	}
	Tcl_SetObjResult(interp, Tcl_ObjPrintf("%d %d %d",
		colorPtr->red, colorPtr->green, colorPtr->blue));
	Tk_FreeColor(colorPtr);
	break;
    }
    case WIN_VISUALSAVAILABLE: {
	XVisualInfo template, *visInfoPtr;
	XVisualInfo templ, *visInfoPtr;
	int count, i;
	int includeVisualId;
	Tcl_Obj *strPtr, *resultPtr;
	char buf[16 + TCL_INTEGER_SPACE];
	char visualIdString[TCL_INTEGER_SPACE];

	if (objc == 3) {
	    includeVisualId = 0;
	} else if ((objc == 4)
		&& (strcmp(Tcl_GetString(objv[3]), "includeids") == 0)) {
	    includeVisualId = 1;
	} else {
	    Tcl_WrongNumArgs(interp, 2, objv, "window ?includeids?");
	    return TCL_ERROR;
	}

	if (TkGetWindowFromObj(interp, tkwin, objv[2], &tkwin) != TCL_OK) {
	    return TCL_ERROR;
	}

	template.screen = Tk_ScreenNumber(tkwin);
	templ.screen = Tk_ScreenNumber(tkwin);
	visInfoPtr = XGetVisualInfo(Tk_Display(tkwin), VisualScreenMask,
		&template, &count);
		&templ, &count);
	if (visInfoPtr == NULL) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "can't find any visuals for screen", -1));
	    Tcl_SetErrorCode(interp, "TK", "VISUAL", "NONE", NULL);
	    return TCL_ERROR;
	}
	resultPtr = Tcl_NewObj();
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818

1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
1811
1812
1813
1814
1815
1816
1817




1818






















































































































































































































1819
1820
1821
1822
1823
1824
1825







-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







	XFree((char *) visInfoPtr);
	break;
    }
    }
    return TCL_OK;
}

#if 0
/*
 *----------------------------------------------------------------------
 *

 * Tk_WmObjCmd --
 *
 *	This function is invoked to process the "wm" Tcl command. See the user
 *	documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
int
Tk_WmObjCmd(
    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;
    TkWindow *winPtr;

    static const char *const optionStrings[] = {
	"aspect",	"client",	"command",	"deiconify",
	"focusmodel",	"frame",	"geometry",	"grid",
	"group",	"iconbitmap",	"iconify",	"iconmask",
	"iconname",	"iconposition",	"iconwindow",	"maxsize",
	"minsize",	"overrideredirect",	"positionfrom",	"protocol",
	"resizable",	"sizefrom",	"state",	"title",
	"tracing",	"transient",	"withdraw",	NULL
    };
    enum options {
	TKWM_ASPECT,	TKWM_CLIENT,	TKWM_COMMAND,	TKWM_DEICONIFY,
	TKWM_FOCUSMOD,	TKWM_FRAME,	TKWM_GEOMETRY,	TKWM_GRID,
	TKWM_GROUP,	TKWM_ICONBMP,	TKWM_ICONIFY,	TKWM_ICONMASK,
	TKWM_ICONNAME,	TKWM_ICONPOS,	TKWM_ICONWIN,	TKWM_MAXSIZE,
	TKWM_MINSIZE,	TKWM_OVERRIDE,	TKWM_POSFROM,	TKWM_PROTOCOL,
	TKWM_RESIZABLE,	TKWM_SIZEFROM,	TKWM_STATE,	TKWM_TITLE,
	TKWM_TRACING,	TKWM_TRANSIENT,	TKWM_WITHDRAW
    };

    tkwin = (Tk_Window) clientData;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "option window ?arg?");
	return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0,
	    &index) != TCL_OK) {
	return TCL_ERROR;
    }

    if (index == TKWM_TRACING) {
	int wmTracing;
	TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;

	if ((objc != 2) && (objc != 3)) {
	    Tcl_WrongNumArgs(interp, 1, objv, "tracing ?boolean?");
	    return TCL_ERROR;
	}
	if (objc == 2) {
	    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(
		    dispPtr->flags & TK_DISPLAY_WM_TRACING));
	    return TCL_OK;
	}
	if (Tcl_GetBooleanFromObj(interp, objv[2], &wmTracing) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (wmTracing) {
	    dispPtr->flags |= TK_DISPLAY_WM_TRACING;
	} else {
	    dispPtr->flags &= ~TK_DISPLAY_WM_TRACING;
	}
	return TCL_OK;
    }

    if (objc < 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?arg?");
	return TCL_ERROR;
    }

    winPtr = (TkWindow *) Tk_NameToWindow(interp,
	    Tcl_GetString(objv[2]), tkwin);
    if (winPtr == NULL) {
	return TCL_ERROR;
    }
    if (!(winPtr->flags & TK_TOP_LEVEL)) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"window \"%s\" isn't a top-level window", winPtr->pathName));
	Tcl_SetErrorCode(interp, "TK", "LOOKUP", "TOPLEVEL", winPtr->pathName,
		NULL);
	return TCL_ERROR;
    }

    switch ((enum options) index) {
    case TKWM_ASPECT:
	TkpWmAspectCmd(interp, tkwin, winPtr, objc, objv);
	break;
    case TKWM_CLIENT:
	TkpWmClientCmd(interp, tkwin, winPtr, objc, objv);
	break;
    case TKWM_COMMAND:
	TkpWmCommandCmd(interp, tkwin, winPtr, objc, objv);
	break;
    case TKWM_DEICONIFY:
	TkpWmDeiconifyCmd(interp, tkwin, winPtr, objc, objv);
	break;
    case TKWM_FOCUSMOD:
	TkpWmFocusmodCmd(interp, tkwin, winPtr, objc, objv);
	break;
    case TKWM_FRAME:
	TkpWmFrameCmd(interp, tkwin, winPtr, objc, objv);
	break;
    case TKWM_GEOMETRY:
	TkpWmGeometryCmd(interp, tkwin, winPtr, objc, objv);
	break;
    case TKWM_GRID:
	TkpWmGridCmd(interp, tkwin, winPtr, objc, objv);
	break;
    case TKWM_GROUP:
	TkpWmGroupCmd(interp, tkwin, winPtr, objc, objv);
	break;
    case TKWM_ICONBMP:
	TkpWmIconbitmapCmd(interp, tkwin, winPtr, objc, objv);
	break;
    case TKWM_ICONIFY:
	TkpWmIconifyCmd(interp, tkwin, winPtr, objc, objv);
	break;
    case TKWM_ICONMASK:
	TkpWmIconmaskCmd(interp, tkwin, winPtr, objc, objv);
	break;
    case TKWM_ICONNAME:
	/*
	 * Slight Unix variation.
	 */
	TkpWmIconnameCmd(interp, tkwin, winPtr, objc, objv);
	break;
    case TKWM_ICONPOS:
	/*
	 * nearly same - 1 line more on Unix.
	 */
	TkpWmIconpositionCmd(interp, tkwin, winPtr, objc, objv);
	break;
    case TKWM_ICONWIN:
	TkpWmIconwindowCmd(interp, tkwin, winPtr, objc, objv);
	break;
    case TKWM_MAXSIZE:
	/*
	 * Nearly same, win diffs.
	 */
	TkpWmMaxsizeCmd(interp, tkwin, winPtr, objc, objv);
	break;
    case TKWM_MINSIZE:
	/*
	 * Nearly same, win diffs
	 */
	TkpWmMinsizeCmd(interp, tkwin, winPtr, objc, objv);
	break;
    case TKWM_OVERRIDE:
	/*
	 * Almost same.
	 */
	TkpWmOverrideCmd(interp, tkwin, winPtr, objc, objv);
	break;
    case TKWM_POSFROM:
	/*
	 * Equal across platforms
	 */
	TkpWmPositionfromCmd(interp, tkwin, winPtr, objc, objv);
	break;
    case TKWM_PROTOCOL:
	/*
	 * Equal across platforms
	 */
	TkpWmProtocolCmd(interp, tkwin, winPtr, objc, objv);
	break;
    case TKWM_RESIZABLE:
	/*
	 * Almost same
	 */
	TkpWmResizableCmd(interp, tkwin, winPtr, objc, objv);
	break;
    case TKWM_SIZEFROM:
	/*
	 * Equal across platforms
	 */
	TkpWmSizefromCmd(interp, tkwin, winPtr, objc, objv);
	break;
    case TKWM_STATE:
	TkpWmStateCmd(interp, tkwin, winPtr, objc, objv);
	break;
    case TKWM_TITLE:
	TkpWmTitleCmd(interp, tkwin, winPtr, objc, objv);
	break;
    case TKWM_TRANSIENT:
	TkpWmTransientCmd(interp, tkwin, winPtr, objc, objv);
	break;
    case TKWM_WITHDRAW:
	TkpWmWithdrawCmd(interp, tkwin, winPtr, objc, objv);
	break;
    }

  updateGeom:
    if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {
	Tcl_DoWhenIdle(UpdateGeometryInfo, winPtr);
	wmPtr->flags |= WM_UPDATE_PENDING;
    }
    return TCL_OK;
}
#endif

/*
 *----------------------------------------------------------------------
 *
 * TkGetDisplayOf --
 *
 *	Parses a "-displayof window" option for various commands. If present,
 *	the literal "-displayof" should be in objv[0] and the window name in
2067
2068
2069
2070
2071
2072
2073
2074

2075
2076
2077
2078
2079

2080
2081

2082
2083
2084
2085
2086
2087
2088
1853
1854
1855
1856
1857
1858
1859

1860
1861
1862
1863
1864

1865
1866

1867
1868
1869
1870
1871
1872
1873
1874







-
+




-
+

-
+







				 * application associated with interp. On
				 * output, filled with window specified as
				 * option to "-displayof" argument, or
				 * unmodified if "-displayof" argument was not
				 * present. */
{
    const char *string;
    int length;
    TkSizeT length;

    if (objc < 1) {
	return 0;
    }
    string = Tcl_GetStringFromObj(objv[0], &length);
    string = TkGetStringFromObj(objv[0], &length);
    if ((length >= 2) &&
	    (strncmp(string, "-displayof", (unsigned) length) == 0)) {
	    (strncmp(string, "-displayof", length) == 0)) {
        if (objc < 2) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "value for \"-displayof\" missing", -1));
	    Tcl_SetErrorCode(interp, "TK", "NO_VALUE", "DISPLAYOF", NULL);
	    return -1;
	}
	*tkwinPtr = Tk_NameToWindow(interp, Tcl_GetString(objv[1]), *tkwinPtr);
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118

2119
2120

2121
2122
2123
2124
2125
2126
2127
1894
1895
1896
1897
1898
1899
1900

1901
1902

1903
1904

1905
1906
1907
1908
1909
1910
1911
1912







-


-
+

-
+







 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
int
TkDeadAppObjCmd(
    ClientData clientData,	/* Dummy. */
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    TCL_UNUSED(int),			/* Number of arguments. */
    Tcl_Obj *const objv[])		/* Argument strings. */
{
    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
	    "can't invoke \"%s\" command: application has been destroyed",
	    Tcl_GetString(objv[0])));
    return TCL_ERROR;
}
Changes to generic/tkColor.c.
1
2
3
4
5
6
7
8
9


10
11
12
13
14
15
16
1
2
3
4
5
6
7


8
9
10
11
12
13
14
15
16







-
-
+
+







/*
 * tkColor.c --
 *
 *	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.
 */

#include "tkInt.h"
#include "tkColor.h"
124
125
126
127
128
129
130
131

132
133
134
135
136
137
138
124
125
126
127
128
129
130

131
132
133
134
135
136
137
138







-
+







    /*
     * The object didn't point to the TkColor that we wanted. Search the list
     * of TkColors with the same name to see if one of the other TkColors is
     * the right one.
     */

    if (tkColPtr != NULL) {
	TkColor *firstColorPtr = Tcl_GetHashValue(tkColPtr->hashPtr);
	TkColor *firstColorPtr = (TkColor *)Tcl_GetHashValue(tkColPtr->hashPtr);

	FreeColorObj(objPtr);
	for (tkColPtr = firstColorPtr; tkColPtr != NULL;
		tkColPtr = tkColPtr->nextPtr) {
	    if ((Tk_Screen(tkwin) == tkColPtr->screen)
		    && (Tk_Colormap(tkwin) == tkColPtr->colormap)) {
		tkColPtr->resourceRefCount++;
199
200
201
202
203
204
205
206

207
208
209
210
211
212
213
199
200
201
202
203
204
205

206
207
208
209
210
211
212
213







-
+








    /*
     * First, check to see if there's already a mapping for this color name.
     */

    nameHashPtr = Tcl_CreateHashEntry(&dispPtr->colorNameTable, name, &isNew);
    if (!isNew) {
	existingColPtr = Tcl_GetHashValue(nameHashPtr);
	existingColPtr = (TkColor *)Tcl_GetHashValue(nameHashPtr);
	for (tkColPtr = existingColPtr; tkColPtr != NULL;
		tkColPtr = tkColPtr->nextPtr) {
	    if ((tkColPtr->screen == Tk_Screen(tkwin))
		    && (Tk_Colormap(tkwin) == tkColPtr->colormap)) {
		tkColPtr->resourceRefCount++;
		return &tkColPtr->color;
	    }
310
311
312
313
314
315
316
317

318
319
320
321
322
323
324
310
311
312
313
314
315
316

317
318
319
320
321
322
323
324







-
+







    valueKey.green = colorPtr->green;
    valueKey.blue = colorPtr->blue;
    valueKey.colormap = Tk_Colormap(tkwin);
    valueKey.display = display;
    valueHashPtr = Tcl_CreateHashEntry(&dispPtr->colorValueTable,
	    (char *) &valueKey, &isNew);
    if (!isNew) {
	tkColPtr = Tcl_GetHashValue(valueHashPtr);
	tkColPtr = (TkColor *)Tcl_GetHashValue(valueHashPtr);
	tkColPtr->resourceRefCount++;
	return &tkColPtr->color;
    }

    /*
     * The name isn't currently known. Find a pixel value for this color and
     * add a new structure to colorValueTable (in TkDisplay).
359
360
361
362
363
364
365
366

367
368
369
370
371

372
373
374
375
376
377
378
359
360
361
362
363
364
365

366
367
368
369
370

371
372
373
374
375
376
377
378







-
+




-
+







 *--------------------------------------------------------------
 */

const char *
Tk_NameOfColor(
    XColor *colorPtr)		/* Color whose name is desired. */
{
    register TkColor *tkColPtr = (TkColor *) colorPtr;
    TkColor *tkColPtr = (TkColor *) colorPtr;

    if (tkColPtr->magic==COLOR_MAGIC && tkColPtr->type==TK_COLOR_BY_NAME) {
	return tkColPtr->hashPtr->key.string;
    } else {
	ThreadSpecificData *tsdPtr =
	ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
		Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

	sprintf(tsdPtr->rgbString, "#%04x%04x%04x", colorPtr->red,
		colorPtr->green, colorPtr->blue);

	/*
	 * If the string has the form #RSRSTUTUVWVW (where equal letters
476
477
478
479
480
481
482
483
484

485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500

501
502
503
504
505
506
507
476
477
478
479
480
481
482


483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498

499
500
501
502
503
504
505
506







-
-
+















-
+







     * Tk_GetColor.
     */

    if (tkColPtr->magic != COLOR_MAGIC) {
	Tcl_Panic("Tk_FreeColor called with bogus color");
    }

    tkColPtr->resourceRefCount--;
    if (tkColPtr->resourceRefCount > 0) {
    if (tkColPtr->resourceRefCount-- > 1) {
	return;
    }

    /*
     * This color is no longer being actively used, so free the color
     * resources associated with it and remove it from the hash table. No
     * longer any objects referencing it.
     */

    if (tkColPtr->gc != NULL) {
	XFreeGC(DisplayOfScreen(screen), tkColPtr->gc);
	tkColPtr->gc = NULL;
    }
    TkpFreeColor(tkColPtr);

    prevPtr = Tcl_GetHashValue(tkColPtr->hashPtr);
    prevPtr = (TkColor *)Tcl_GetHashValue(tkColPtr->hashPtr);
    if (prevPtr == tkColPtr) {
	if (tkColPtr->nextPtr == NULL) {
	    Tcl_DeleteHashEntry(tkColPtr->hashPtr);
	} else {
	    Tcl_SetHashValue(tkColPtr->hashPtr, tkColPtr->nextPtr);
	}
    } else {
580
581
582
583
584
585
586
587

588
589
590
591

592
593
594
595
596
597
598
579
580
581
582
583
584
585

586
587
588


589
590
591
592
593
594
595
596







-
+


-
-
+







    objPtr->typePtr = NULL;
}

static void
FreeColorObj(
    Tcl_Obj *objPtr)		/* The object we are releasing. */
{
    TkColor *tkColPtr = objPtr->internalRep.twoPtrValue.ptr1;
    TkColor *tkColPtr = (TkColor *)objPtr->internalRep.twoPtrValue.ptr1;

    if (tkColPtr != NULL) {
	tkColPtr->objRefCount--;
	if ((tkColPtr->objRefCount == 0)
	if ((tkColPtr->objRefCount-- <= 1)
		&& (tkColPtr->resourceRefCount == 0)) {
	    ckfree(tkColPtr);
	}
	objPtr->internalRep.twoPtrValue.ptr1 = NULL;
    }
}

615
616
617
618
619
620
621
622

623
624
625
626
627
628
629
613
614
615
616
617
618
619

620
621
622
623
624
625
626
627







-
+







 */

static void
DupColorObjProc(
    Tcl_Obj *srcObjPtr,		/* The object we are copying from. */
    Tcl_Obj *dupObjPtr)		/* The object we are copying to. */
{
    TkColor *tkColPtr = srcObjPtr->internalRep.twoPtrValue.ptr1;
    TkColor *tkColPtr = (TkColor *)srcObjPtr->internalRep.twoPtrValue.ptr1;

    dupObjPtr->typePtr = srcObjPtr->typePtr;
    dupObjPtr->internalRep.twoPtrValue.ptr1 = tkColPtr;

    if (tkColPtr != NULL) {
	tkColPtr->objRefCount++;
    }
665
666
667
668
669
670
671
672

673
674
675
676
677
678
679
663
664
665
666
667
668
669

670
671
672
673
674
675
676
677







-
+








    /*
     * First check to see if the internal representation of the object is
     * defined and is a color that is valid for the current screen and color
     * map. If it is, we are done.
     */

    tkColPtr = objPtr->internalRep.twoPtrValue.ptr1;
    tkColPtr = (TkColor *)objPtr->internalRep.twoPtrValue.ptr1;
    if ((tkColPtr != NULL)
	    && (tkColPtr->resourceRefCount > 0)
	    && (Tk_Screen(tkwin) == tkColPtr->screen)
	    && (Tk_Colormap(tkwin) == tkColPtr->colormap)) {
	/*
	 * The object already points to the right TkColor structure. Just
	 * return it.
691
692
693
694
695
696
697
698

699
700
701
702
703
704
705
689
690
691
692
693
694
695

696
697
698
699
700
701
702
703







-
+







     */

    hashPtr = Tcl_FindHashEntry(&dispPtr->colorNameTable,
	    Tcl_GetString(objPtr));
    if (hashPtr == NULL) {
	goto error;
    }
    for (tkColPtr = Tcl_GetHashValue(hashPtr);
    for (tkColPtr = (TkColor *)Tcl_GetHashValue(hashPtr);
	    (tkColPtr != NULL); tkColPtr = tkColPtr->nextPtr) {
	if ((Tk_Screen(tkwin) == tkColPtr->screen)
		&& (Tk_Colormap(tkwin) == tkColPtr->colormap)) {
	    FreeColorObj(objPtr);
	    objPtr->internalRep.twoPtrValue.ptr1 = tkColPtr;
	    tkColPtr->objRefCount++;
	    return (XColor *) tkColPtr;
807
808
809
810
811
812
813
814

815
816
817
818
819
820
821
822
823

824
825

826
827
828
829
830
831
832
805
806
807
808
809
810
811

812
813
814
815
816
817
818
819
820

821
822

823
824
825
826
827
828
829
830







-
+








-
+

-
+







    Tcl_HashEntry *hashPtr;
    Tcl_Obj *resultPtr;
    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;

    resultPtr = Tcl_NewObj();
    hashPtr = Tcl_FindHashEntry(&dispPtr->colorNameTable, name);
    if (hashPtr != NULL) {
	TkColor *tkColPtr = Tcl_GetHashValue(hashPtr);
	TkColor *tkColPtr = (TkColor *)Tcl_GetHashValue(hashPtr);

	if (tkColPtr == NULL) {
	    Tcl_Panic("TkDebugColor found empty hash table entry");
	}
	for ( ; (tkColPtr != NULL); tkColPtr = tkColPtr->nextPtr) {
	    Tcl_Obj *objPtr = Tcl_NewObj();

	    Tcl_ListObjAppendElement(NULL, objPtr,
		    Tcl_NewIntObj(tkColPtr->resourceRefCount));
		    Tcl_NewWideIntObj(tkColPtr->resourceRefCount));
	    Tcl_ListObjAppendElement(NULL, objPtr,
		    Tcl_NewIntObj(tkColPtr->objRefCount));
		    Tcl_NewWideIntObj(tkColPtr->objRefCount));
	    Tcl_ListObjAppendElement(NULL, resultPtr, objPtr);
	}
    }
    return resultPtr;
}

#ifndef _WIN32
Changes to generic/tkColor.h.
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







/*
 * 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.
 */

#ifndef _TKCOLOR
#define _TKCOLOR
34
35
36
37
38
39
40
41

42
43
44
45
46
47
48
49
50
51

52
53
54
55
56
57
58
34
35
36
37
38
39
40

41
42
43
44
45
46
47
48
49
50

51
52
53
54
55
56
57
58







-
+









-
+







				 * color and all other fields defaulted. May
				 * be NULL. */
    Screen *screen;		/* Screen where this color is valid. Used to
				 * delete it, and to find its display. */
    Colormap colormap;		/* Colormap from which this entry was
				 * allocated. */
    Visual *visual;		/* Visual associated with colormap. */
    int resourceRefCount;	/* Number of active uses of this color (each
    TkSizeT resourceRefCount;	/* Number of active uses of this color (each
				 * active use corresponds to a call to
				 * Tk_AllocColorFromObj or Tk_GetColor). If
				 * this count is 0, then this TkColor
				 * structure is no longer valid and it isn't
				 * present in a hash table: it is being kept
				 * around only because there are objects
				 * referring to it. The structure is freed
				 * when resourceRefCount and objRefCount are
				 * both 0. */
    int objRefCount;		/* The number of Tcl objects that reference
    TkSizeT objRefCount;		/* The number of Tcl objects that reference
				 * this structure. */
    int type;			/* TK_COLOR_BY_NAME or TK_COLOR_BY_VALUE. */
    Tcl_HashEntry *hashPtr;	/* Pointer to hash table entry for this
				 * structure. (for use in deleting entry). */
    struct TkColor *nextPtr;	/* Points to the next TkColor structure with
				 * the same color name. Colors with the same
				 * name but different screens or colormaps are
Changes to generic/tkConfig.c.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







/*
 * 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.
 */

/*
 * Temporary flag for working on new config package.
63
64
65
66
67
68
69
70

71
72
73
74
75
76
77
63
64
65
66
67
68
69

70
71
72
73
74
75
76
77







-
+







    Tcl_Obj *defaultPtr;	/* Default value for this option. */
    union {
	Tcl_Obj *monoColorPtr;	/* For color and border options, this is an
				 * alternate default value to use on
				 * monochrome displays. */
	struct TkOption *synonymPtr;
				/* For synonym options, this points to the
				 * master entry. */
				 * original entry. */
	const struct Tk_ObjCustomOption *custom;
				/* For TK_OPTION_CUSTOM. */
    } extra;
    int flags;			/* Miscellaneous flag values; see below for
				 * definitions. */
} Option;

87
88
89
90
91
92
93
94

95
96
97
98
99
100
101
102
103
104
105
106

107
108
109
110
111
112
113
114
115
116
117
118

119
120
121
122
123


124
125

126
127
128
129
130
131
132
87
88
89
90
91
92
93

94
95
96
97
98
99
100
101
102
103
104
105

106
107
108
109
110
111
112
113
114
115
116
117

118
119
120
121


122
123
124

125
126
127
128
129
130
131
132







-
+











-
+











-
+



-
-
+
+

-
+








/*
 * One of the following exists for each Tk_OptionSpec array that has been
 * passed to Tk_CreateOptionTable.
 */

typedef struct OptionTable {
    int refCount;		/* Counts the number of uses of this table
    size_t refCount;		/* Counts the number of uses of this table
				 * (the number of times Tk_CreateOptionTable
				 * has returned it). This can be greater than
				 * 1 if it is shared along several option
				 * table chains, or if the same table is used
				 * for multiple purposes. */
    Tcl_HashEntry *hashEntryPtr;/* Hash table entry that refers to this table;
				 * used to delete the entry. */
    struct OptionTable *nextPtr;/* If templatePtr was part of a chain of
				 * templates, this points to the table
				 * corresponding to the next template in the
				 * chain. */
    int numOptions;		/* The number of items in the options array
    size_t numOptions;		/* The number of items in the options array
				 * below. */
    Option options[1];		/* Information about the individual options in
				 * the table. This must be the last field in
				 * the structure: the actual size of the array
				 * will be numOptions, not 1. */
} OptionTable;

/*
 * Forward declarations for functions defined later in this file:
 */

static int		DoObjConfig(Tcl_Interp *interp, char *recordPtr,
static int		DoObjConfig(Tcl_Interp *interp, void *recordPtr,
			    Option *optionPtr, Tcl_Obj *valuePtr,
			    Tk_Window tkwin, Tk_SavedOption *savePtr);
static void		FreeResources(Option *optionPtr, Tcl_Obj *objPtr,
			    char *internalPtr, Tk_Window tkwin);
static Tcl_Obj *	GetConfigList(char *recordPtr,
			    void *internalPtr, Tk_Window tkwin);
static Tcl_Obj *	GetConfigList(void *recordPtr,
			    Option *optionPtr, Tk_Window tkwin);
static Tcl_Obj *	GetObjectForOption(char *recordPtr,
static Tcl_Obj *	GetObjectForOption(void *recordPtr,
			    Option *optionPtr, Tk_Window tkwin);
static Option *		GetOption(const char *name, OptionTable *tablePtr);
static Option *		GetOptionFromObj(Tcl_Interp *interp,
			    Tcl_Obj *objPtr, OptionTable *tablePtr);
static int		ObjectIsEmpty(Tcl_Obj *objPtr);
static void		FreeOptionInternalRep(Tcl_Obj *objPtr);
static void		DupOptionInternalRep(Tcl_Obj *, Tcl_Obj *);
173
174
175
176
177
178
179
180
181


182
183
184
185
186
187
188
173
174
175
176
177
178
179


180
181
182
183
184
185
186
187
188







-
-
+
+







				 * options. */
{
    Tcl_HashEntry *hashEntryPtr;
    int newEntry;
    OptionTable *tablePtr;
    const Tk_OptionSpec *specPtr, *specPtr2;
    Option *optionPtr;
    int numOptions, i;
    ThreadSpecificData *tsdPtr =
    size_t numOptions, i;
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    /*
     * We use an TSD in the thread to keep a hash table of
     * all the option tables we've created for this application. This is
     * used for allowing us to share the tables (e.g. in several chains).
     * The code below finds the hash table or creates a new one if it
198
199
200
201
202
203
204
205

206
207
208
209
210
211
212
213
214
215
216
217
218
219

220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241


242
243
244
245
246
247
248
198
199
200
201
202
203
204

205
206
207
208
209
210
211
212
213
214
215
216
217
218

219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239


240
241
242
243
244
245
246
247
248







-
+













-
+




















-
-
+
+







     * See if a table has already been created for this template. If so, just
     * reuse the existing table.
     */

    hashEntryPtr = Tcl_CreateHashEntry(&tsdPtr->hashTable, (char *) templatePtr,
	    &newEntry);
    if (!newEntry) {
	tablePtr = Tcl_GetHashValue(hashEntryPtr);
	tablePtr = (OptionTable *)Tcl_GetHashValue(hashEntryPtr);
	tablePtr->refCount++;
	return (Tk_OptionTable) tablePtr;
    }

    /*
     * Count the number of options in the template, then create the table
     * structure.
     */

    numOptions = 0;
    for (specPtr = templatePtr; specPtr->type != TK_OPTION_END; specPtr++) {
	numOptions++;
    }
    tablePtr = ckalloc(sizeof(OptionTable) + (numOptions * sizeof(Option)));
    tablePtr = (OptionTable *)ckalloc(sizeof(OptionTable) + (numOptions * sizeof(Option)));
    tablePtr->refCount = 1;
    tablePtr->hashEntryPtr = hashEntryPtr;
    tablePtr->nextPtr = NULL;
    tablePtr->numOptions = numOptions;

    /*
     * Initialize all of the Option structures in the table.
     */

    for (specPtr = templatePtr, optionPtr = tablePtr->options;
	    specPtr->type != TK_OPTION_END; specPtr++, optionPtr++) {
	optionPtr->specPtr = specPtr;
	optionPtr->dbNameUID = NULL;
	optionPtr->dbClassUID = NULL;
	optionPtr->defaultPtr = NULL;
	optionPtr->extra.monoColorPtr = NULL;
	optionPtr->flags = 0;

	if (specPtr->type == TK_OPTION_SYNONYM) {
	    /*
	     * This is a synonym option; find the master option that it refers
	     * to and create a pointer from the synonym to the master.
	     * This is a synonym option; find the original option that it refers
	     * to and create a pointer from the synonym to the origin.
	     */

	    for (specPtr2 = templatePtr, i = 0; ; specPtr2++, i++) {
		if (specPtr2->type == TK_OPTION_END) {
		    Tcl_Panic("Tk_CreateOptionTable couldn't find synonym");
		}
		if (strcmp(specPtr2->optionName,
262
263
264
265
266
267
268
269

270
271
272
273
274
275
276
277
278

279
280
281
282

283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303

304
305
306
307
308
309
310
262
263
264
265
266
267
268

269
270
271
272
273
274
275
276
277

278
279
280
281

282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302

303
304
305
306
307
308
309
310







-
+








-
+



-
+




















-
+







		optionPtr->defaultPtr = Tcl_NewStringObj(specPtr->defValue,-1);
		Tcl_IncrRefCount(optionPtr->defaultPtr);
	    }
	    if (((specPtr->type == TK_OPTION_COLOR)
		    || (specPtr->type == TK_OPTION_BORDER))
		    && (specPtr->clientData != NULL)) {
		optionPtr->extra.monoColorPtr =
			Tcl_NewStringObj(specPtr->clientData, -1);
			Tcl_NewStringObj((const char *)specPtr->clientData, -1);
		Tcl_IncrRefCount(optionPtr->extra.monoColorPtr);
	    }

	    if (specPtr->type == TK_OPTION_CUSTOM) {
		/*
		 * Get the custom parsing, etc., functions.
		 */

		optionPtr->extra.custom = specPtr->clientData;
		optionPtr->extra.custom = (const Tk_ObjCustomOption *)specPtr->clientData;
	    }
	}
	if (((specPtr->type == TK_OPTION_STRING)
		&& (specPtr->internalOffset >= 0))
		&& (specPtr->internalOffset != TCL_INDEX_NONE))
		|| (specPtr->type == TK_OPTION_COLOR)
		|| (specPtr->type == TK_OPTION_FONT)
		|| (specPtr->type == TK_OPTION_BITMAP)
		|| (specPtr->type == TK_OPTION_BORDER)
		|| (specPtr->type == TK_OPTION_CURSOR)
		|| (specPtr->type == TK_OPTION_CUSTOM)) {
	    optionPtr->flags |= OPTION_NEEDS_FREEING;
	}
    }
    tablePtr->hashEntryPtr = hashEntryPtr;
    Tcl_SetHashValue(hashEntryPtr, tablePtr);

    /*
     * Finally, check to see if this template chains to another template with
     * additional options. If so, call ourselves recursively to create the
     * next table(s).
     */

    if (specPtr->clientData != NULL) {
	tablePtr->nextPtr = (OptionTable *)
		Tk_CreateOptionTable(interp, specPtr->clientData);
		Tk_CreateOptionTable(interp, (Tk_OptionSpec *)specPtr->clientData);
    }

    return (Tk_OptionTable) tablePtr;
}

/*
 *----------------------------------------------------------------------
326
327
328
329
330
331
332
333

334
335
336

337
338
339
340
341
342
343
326
327
328
329
330
331
332

333
334


335
336
337
338
339
340
341
342







-
+

-
-
+








void
Tk_DeleteOptionTable(
    Tk_OptionTable optionTable)	/* The option table to delete. */
{
    OptionTable *tablePtr = (OptionTable *) optionTable;
    Option *optionPtr;
    int count;
    size_t count;

    tablePtr->refCount--;
    if (tablePtr->refCount > 0) {
    if (tablePtr->refCount-- > 1) {
	return;
    }

    if (tablePtr->nextPtr != NULL) {
	Tk_DeleteOptionTable((Tk_OptionTable) tablePtr->nextPtr);
    }

378
379
380
381
382
383
384
385

386
387
388
389
390
391
392
377
378
379
380
381
382
383

384
385
386
387
388
389
390
391







-
+







 *--------------------------------------------------------------
 */

int
Tk_InitOptions(
    Tcl_Interp *interp,		/* Interpreter for error reporting. NULL means
				 * don't leave an error message. */
    char *recordPtr,		/* Pointer to the record to configure. Note:
    void *recordPtr,		/* Pointer to the record to configure. Note:
				 * the caller should have properly initialized
				 * the record with NULL pointers for each
				 * option value. */
    Tk_OptionTable optionTable,	/* The token which matches the config specs
				 * for the widget in question. */
    Tk_Window tkwin)		/* Certain options types (such as
				 * TK_OPTION_COLOR) need fields out of the
549
550
551
552
553
554
555
556

557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572

573
574
575

576
577
578
579
580
581
582
583
584
585
586
587
588
589


590
591
592
593
594
595
596
597
598
599
600
601
602


603
604
605
606
607
608
609
548
549
550
551
552
553
554

555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570

571
572
573

574
575
576
577
578
579
580
581
582
583
584
585
586


587
588
589
590
591
592
593
594
595
596
597
598
599


600
601
602
603
604
605
606
607
608







-
+















-
+


-
+












-
-
+
+











-
-
+
+







 */

static int
DoObjConfig(
    Tcl_Interp *interp,		/* Interpreter for error reporting. If NULL,
				 * then no message is left if an error
				 * occurs. */
    char *recordPtr,		/* The record to modify to hold the new option
    void *recordPtr,		/* The record to modify to hold the new option
				 * value. */
    Option *optionPtr,		/* Pointer to information about the option. */
    Tcl_Obj *valuePtr,		/* New value for option. */
    Tk_Window tkwin,		/* Window in which option will be used (needed
				 * to allocate resources for some options).
				 * May be NULL if the option doesn't require
				 * window-related resources. */
    Tk_SavedOption *savedOptionPtr)
				/* If NULL, the old value for the option will
				 * be freed. If non-NULL, the old value will
				 * be stored here, and it becomes the property
				 * of the caller (the caller must eventually
				 * free the old value). */
{
    Tcl_Obj **slotPtrPtr, *oldPtr;
    char *internalPtr;		/* Points to location in record where internal
    void *internalPtr;		/* Points to location in record where internal
				 * representation of value should be stored,
				 * or NULL. */
    char *oldInternalPtr;	/* Points to location in which to save old
    void *oldInternalPtr;	/* Points to location in which to save old
				 * internal representation of value. */
    Tk_SavedOption internal;	/* Used to save the old internal
				 * representation of the value if
				 * savedOptionPtr is NULL. */
    const Tk_OptionSpec *specPtr;
    int nullOK;

    /*
     * Save the old object form for the value, if there is one.
     */

    specPtr = optionPtr->specPtr;
    if (specPtr->objOffset >= 0) {
	slotPtrPtr = (Tcl_Obj **) (recordPtr + specPtr->objOffset);
    if (specPtr->objOffset != TCL_INDEX_NONE) {
	slotPtrPtr = (Tcl_Obj **) ((char *)recordPtr + specPtr->objOffset);
	oldPtr = *slotPtrPtr;
    } else {
	slotPtrPtr = NULL;
	oldPtr = NULL;
    }

    /*
     * Apply the new value in a type-specific way. Also remember the old
     * object and internal forms, if they exist.
     */

    if (specPtr->internalOffset >= 0) {
	internalPtr = recordPtr + specPtr->internalOffset;
    if (specPtr->internalOffset != TCL_INDEX_NONE) {
	internalPtr = (char *)recordPtr + specPtr->internalOffset;
    } else {
	internalPtr = NULL;
    }
    if (savedOptionPtr != NULL) {
	savedOptionPtr->optionPtr = optionPtr;
	savedOptionPtr->valuePtr = oldPtr;
	oldInternalPtr = (char *) &savedOptionPtr->internalForm;
653
654
655
656
657
658
659
660

661
662
663
664
665
666
667
668


669
670
671
672
673
674
675
652
653
654
655
656
657
658

659
660
661
662
663
664
665


666
667
668
669
670
671
672
673
674







-
+






-
-
+
+







	    *((double *) internalPtr) = newDbl;
	}
	break;
    }
    case TK_OPTION_STRING: {
	char *newStr;
	const char *value;
	int length;
	TkSizeT length;

	if (nullOK && ObjectIsEmpty(valuePtr)) {
	    valuePtr = NULL;
	}
	if (internalPtr != NULL) {
	    if (valuePtr != NULL) {
		value = Tcl_GetStringFromObj(valuePtr, &length);
		newStr = ckalloc(length + 1);
		value = TkGetStringFromObj(valuePtr, &length);
		newStr = (char *)ckalloc(length + 1);
		strcpy(newStr, value);
	    } else {
		newStr = NULL;
	    }
	    *((char **) oldInternalPtr) = *((char **) internalPtr);
	    *((char **) internalPtr) = newStr;
	}
880
881
882
883
884
885
886
887

888
889
890
891
892
893
894
879
880
881
882
883
884
885

886
887
888
889
890
891
892
893







-
+







	}
	break;
    }
    case TK_OPTION_CUSTOM: {
	const Tk_ObjCustomOption *custom = optionPtr->extra.custom;

	if (custom->setProc(custom->clientData, interp, tkwin,
		&valuePtr, recordPtr, optionPtr->specPtr->internalOffset,
		&valuePtr, (char *)recordPtr, optionPtr->specPtr->internalOffset,
		(char *)oldInternalPtr, optionPtr->specPtr->flags) != TCL_OK) {
	    return TCL_ERROR;
	}
	break;
    }

    default:
976
977
978
979
980
981
982
983

984
985
986
987
988
989
990
975
976
977
978
979
980
981

982
983
984
985
986
987
988
989







-
+







    const char *name,		/* String balue to be looked up in the option
				 * table. */
    OptionTable *tablePtr)	/* Table in which to look up name. */
{
    Option *bestPtr, *optionPtr;
    OptionTable *tablePtr2;
    const char *p1, *p2;
    int count;
    size_t count;

    /*
     * Search through all of the option tables in the chain to find the best
     * match. Some tricky aspects:
     *
     * 1. We have to accept unique abbreviations.
     * 2. The same name could appear in different tables in the chain. If this
1162
1163
1164
1165
1166
1167
1168
1169

1170
1171

1172
1173
1174
1175
1176
1177
1178
1161
1162
1163
1164
1165
1166
1167

1168
1169

1170
1171
1172
1173
1174
1175
1176
1177







-
+

-
+







 *	cleanup is delayed until the last reference goes away.
 *
 *----------------------------------------------------------------------
 */

static void
FreeOptionInternalRep(
    register Tcl_Obj *objPtr)	/* Object whose internal rep to free. */
    Tcl_Obj *objPtr)	/* Object whose internal rep to free. */
{
    register Tk_OptionTable tablePtr = (Tk_OptionTable) objPtr->internalRep.twoPtrValue.ptr1;
    Tk_OptionTable tablePtr = (Tk_OptionTable) objPtr->internalRep.twoPtrValue.ptr1;

    Tk_DeleteOptionTable(tablePtr);
    objPtr->typePtr = NULL;
    objPtr->internalRep.twoPtrValue.ptr1 = NULL;
    objPtr->internalRep.twoPtrValue.ptr2 = NULL;
}

1188
1189
1190
1191
1192
1193
1194
1195

1196
1197
1198
1199
1200
1201
1202
1187
1188
1189
1190
1191
1192
1193

1194
1195
1196
1197
1198
1199
1200
1201







-
+







 */

static void
DupOptionInternalRep(
    Tcl_Obj *srcObjPtr,		/* The object we are copying from. */
    Tcl_Obj *dupObjPtr)		/* The object we are copying to. */
{
    register OptionTable *tablePtr = (OptionTable *) srcObjPtr->internalRep.twoPtrValue.ptr1;
    OptionTable *tablePtr = (OptionTable *) srcObjPtr->internalRep.twoPtrValue.ptr1;
    tablePtr->refCount++;
    dupObjPtr->typePtr = srcObjPtr->typePtr;
    dupObjPtr->internalRep = srcObjPtr->internalRep;
}

/*
 *--------------------------------------------------------------
1224
1225
1226
1227
1228
1229
1230
1231

1232
1233
1234
1235
1236
1237
1238
1223
1224
1225
1226
1227
1228
1229

1230
1231
1232
1233
1234
1235
1236
1237







-
+







 *--------------------------------------------------------------
 */

int
Tk_SetOptions(
    Tcl_Interp *interp,		/* Interpreter for error reporting. If NULL,
				 * then no error message is returned.*/
    char *recordPtr,	    	/* The record to configure. */
    void *recordPtr,	    	/* The record to configure. */
    Tk_OptionTable optionTable,	/* Describes valid options. */
    int objc,			/* The number of elements in objv. */
    Tcl_Obj *const objv[],	/* Contains one or more name-value pairs. */
    Tk_Window tkwin,		/* Window associated with the thing being
				 * configured; needed for some options (such
				 * as colors). */
    Tk_SavedOptions *savePtr,	/* If non-NULL, the old values of modified
1285
1286
1287
1288
1289
1290
1291
1292

1293
1294
1295
1296
1297
1298
1299
1284
1285
1286
1287
1288
1289
1290

1291
1292
1293
1294
1295
1296
1297
1298







-
+







	if ((savePtr != NULL)
		&& (lastSavePtr->numItems >= TK_NUM_SAVED_OPTIONS)) {
	    /*
	     * We've run out of space for saving old option values. Allocate
	     * more space.
	     */

	    newSavePtr = ckalloc(sizeof(Tk_SavedOptions));
	    newSavePtr = (Tk_SavedOptions *)ckalloc(sizeof(Tk_SavedOptions));
	    newSavePtr->recordPtr = recordPtr;
	    newSavePtr->tkwin = tkwin;
	    newSavePtr->numItems = 0;
	    newSavePtr->nextPtr = NULL;
	    lastSavePtr->nextPtr = newSavePtr;
	    lastSavePtr = newSavePtr;
	}
1342
1343
1344
1345
1346
1347
1348
1349

1350
1351
1352
1353
1354

1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369

1370
1371
1372
1373
1374
1375
1376
1377
1378
1379


1380
1381
1382
1383
1384


1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400


1401
1402
1403
1404


1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1341
1342
1343
1344
1345
1346
1347

1348
1349
1350
1351
1352

1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367

1368
1369
1370
1371
1372
1373
1374
1375
1376


1377
1378
1379
1380
1381


1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397


1398
1399
1400
1401


1402
1403
1404
1405
1406
1407


1408
1409
1410
1411
1412
1413
1414







-
+




-
+














-
+








-
-
+
+



-
-
+
+














-
-
+
+


-
-
+
+




-
-







 */

void
Tk_RestoreSavedOptions(
    Tk_SavedOptions *savePtr)	/* Holds saved option information; must have
				 * been passed to Tk_SetOptions. */
{
    int i;
    size_t i;
    Option *optionPtr;
    Tcl_Obj *newPtr;		/* New object value of option, which we
				 * replace with old value and free. Taken from
				 * record. */
    char *internalPtr;		/* Points to internal value of option in
    void *internalPtr;		/* Points to internal value of option in
				 * record. */
    const Tk_OptionSpec *specPtr;

    /*
     * Be sure to restore the options in the opposite order they were set.
     * This is important because it's possible that the same option name was
     * used twice in a single call to Tk_SetOptions.
     */

    if (savePtr->nextPtr != NULL) {
	Tk_RestoreSavedOptions(savePtr->nextPtr);
	ckfree(savePtr->nextPtr);
	savePtr->nextPtr = NULL;
    }
    for (i = savePtr->numItems - 1; i >= 0; i--) {
    for (i = savePtr->numItems - 1; i != (size_t)-1; i--) {
	optionPtr = savePtr->items[i].optionPtr;
	specPtr = optionPtr->specPtr;

	/*
	 * First free the new value of the option, which is currently in the
	 * record.
	 */

	if (specPtr->objOffset >= 0) {
	    newPtr = *((Tcl_Obj **) (savePtr->recordPtr + specPtr->objOffset));
	if (specPtr->objOffset != TCL_INDEX_NONE) {
	    newPtr = *((Tcl_Obj **) ((char *)savePtr->recordPtr + specPtr->objOffset));
	} else {
	    newPtr = NULL;
	}
	if (specPtr->internalOffset >= 0) {
	    internalPtr = savePtr->recordPtr + specPtr->internalOffset;
	if (specPtr->internalOffset != TCL_INDEX_NONE) {
	    internalPtr = (char *)savePtr->recordPtr + specPtr->internalOffset;
	} else {
	    internalPtr = NULL;
	}
	if (optionPtr->flags & OPTION_NEEDS_FREEING) {
	    FreeResources(optionPtr, newPtr, internalPtr, savePtr->tkwin);
	}
	if (newPtr != NULL) {
	    Tcl_DecrRefCount(newPtr);
	}

	/*
	 * Now restore the old value of the option.
	 */

	if (specPtr->objOffset >= 0) {
	    *((Tcl_Obj **) (savePtr->recordPtr + specPtr->objOffset))
	if (specPtr->objOffset != TCL_INDEX_NONE) {
	    *((Tcl_Obj **) ((char *)savePtr->recordPtr + specPtr->objOffset))
		    = savePtr->items[i].valuePtr;
	}
	if (specPtr->internalOffset >= 0) {
	    register char *ptr = (char *) &savePtr->items[i].internalForm;
	if (specPtr->internalOffset != TCL_INDEX_NONE) {
	    char *ptr = (char *) &savePtr->items[i].internalForm;

	    CLANG_ASSERT(internalPtr);
	    switch (specPtr->type) {
	    case TK_OPTION_BOOLEAN:
		*((int *) internalPtr) = *((int *) ptr);
		break;
	    case TK_OPTION_INT:
		*((int *) internalPtr) = *((int *) ptr);
		break;
	    case TK_OPTION_DOUBLE:
		*((double *) internalPtr) = *((double *) ptr);
		break;
	    case TK_OPTION_STRING:
1455
1456
1457
1458
1459
1460
1461
1462

1463
1464
1465
1466
1467
1468
1469
1452
1453
1454
1455
1456
1457
1458

1459
1460
1461
1462
1463
1464
1465
1466







-
+







		*((Tk_Window *) internalPtr) = *((Tk_Window *) ptr);
		break;
	    case TK_OPTION_CUSTOM: {
		const Tk_ObjCustomOption *custom = optionPtr->extra.custom;

		if (custom->restoreProc != NULL) {
		    custom->restoreProc(custom->clientData, savePtr->tkwin,
			    internalPtr, ptr);
			    (char *)internalPtr, ptr);
		}
		break;
	    }
	    default:
		Tcl_Panic("bad option type in Tk_RestoreSavedOptions");
	    }
	}
1489
1490
1491
1492
1493
1494
1495
1496

1497
1498
1499
1500
1501
1502
1503
1504


1505
1506
1507
1508
1509
1510
1511
1512
1486
1487
1488
1489
1490
1491
1492

1493
1494
1495
1496
1497
1498
1499


1500
1501

1502
1503
1504
1505
1506
1507
1508







-
+






-
-
+
+
-







 */

void
Tk_FreeSavedOptions(
    Tk_SavedOptions *savePtr)	/* Contains options saved in a previous call
				 * to Tk_SetOptions. */
{
    int count;
    size_t count;
    Tk_SavedOption *savedOptionPtr;

    if (savePtr->nextPtr != NULL) {
	Tk_FreeSavedOptions(savePtr->nextPtr);
	ckfree(savePtr->nextPtr);
    }
    for (count = savePtr->numItems,
	    savedOptionPtr = &savePtr->items[savePtr->numItems-1];
    for (count = savePtr->numItems; count > 0; count--) {
	savedOptionPtr = &savePtr->items[count-1];
	    count > 0;  count--, savedOptionPtr--) {
	if (savedOptionPtr->optionPtr->flags & OPTION_NEEDS_FREEING) {
	    FreeResources(savedOptionPtr->optionPtr, savedOptionPtr->valuePtr,
		    (char *) &savedOptionPtr->internalForm, savePtr->tkwin);
	}
	if (savedOptionPtr->valuePtr != NULL) {
	    Tcl_DecrRefCount(savedOptionPtr->valuePtr);
	}
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536

1537
1538
1539
1540
1541
1542
1543
1544

1545
1546

1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558


1559
1560
1561
1562
1563
1564
1565


1566
1567
1568
1569
1570
1571
1572
1522
1523
1524
1525
1526
1527
1528

1529
1530

1531
1532
1533
1534
1535
1536
1537
1538

1539
1540

1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551


1552
1553
1554
1555
1556
1557
1558


1559
1560
1561
1562
1563
1564
1565
1566
1567







-


-
+







-
+

-
+










-
-
+
+





-
-
+
+







 * Side effects:
 *	All of the Tcl_Obj's in recordPtr that are controlled by configuration
 *	options in optionTable are freed.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
void
Tk_FreeConfigOptions(
    char *recordPtr,		/* Record whose fields contain current values
    void *recordPtr,		/* Record whose fields contain current values
				 * for options. */
    Tk_OptionTable optionTable,	/* Describes legal options. */
    Tk_Window tkwin)		/* Window associated with recordPtr; needed
				 * for freeing some options. */
{
    OptionTable *tablePtr;
    Option *optionPtr;
    int count;
    size_t count;
    Tcl_Obj **oldPtrPtr, *oldPtr;
    char *oldInternalPtr;
    void *oldInternalPtr;
    const Tk_OptionSpec *specPtr;

    for (tablePtr = (OptionTable *) optionTable; tablePtr != NULL;
	    tablePtr = tablePtr->nextPtr) {
	for (optionPtr = tablePtr->options, count = tablePtr->numOptions;
		count > 0; optionPtr++, count--) {
	    specPtr = optionPtr->specPtr;
	    if (specPtr->type == TK_OPTION_SYNONYM) {
		continue;
	    }
	    if (specPtr->objOffset >= 0) {
		oldPtrPtr = (Tcl_Obj **) (recordPtr + specPtr->objOffset);
	    if (specPtr->objOffset != TCL_INDEX_NONE) {
		oldPtrPtr = (Tcl_Obj **) ((char *)recordPtr + specPtr->objOffset);
		oldPtr = *oldPtrPtr;
		*oldPtrPtr = NULL;
	    } else {
		oldPtr = NULL;
	    }
	    if (specPtr->internalOffset >= 0) {
		oldInternalPtr = recordPtr + specPtr->internalOffset;
	    if (specPtr->internalOffset != TCL_INDEX_NONE) {
		oldInternalPtr = (char *)recordPtr + specPtr->internalOffset;
	    } else {
		oldInternalPtr = NULL;
	    }
	    if (optionPtr->flags & OPTION_NEEDS_FREEING) {
		FreeResources(optionPtr, oldPtr, oldInternalPtr, tkwin);
	    }
	    if (oldPtr != NULL) {
1595
1596
1597
1598
1599
1600
1601
1602

1603
1604
1605

1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616

1617
1618
1619
1620
1621
1622
1623
1590
1591
1592
1593
1594
1595
1596

1597
1598
1599

1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610

1611
1612
1613
1614
1615
1616
1617
1618







-
+


-
+










-
+







 */

static void
FreeResources(
    Option *optionPtr,		/* Description of the configuration option. */
    Tcl_Obj *objPtr,		/* The current value of the option, specified
				 * as an object. */
    char *internalPtr,		/* A pointer to an internal representation for
    void *internalPtr,		/* A pointer to an internal representation for
				 * the option's value, such as an int or
				 * (XColor *). Only valid if
				 * optionPtr->specPtr->internalOffset >= 0. */
				 * optionPtr->specPtr->internalOffset != -1. */
    Tk_Window tkwin)		/* The window in which this option is used. */
{
    int internalFormExists;

    /*
     * If there exists an internal form for the value, use it to free
     * resources (also zero out the internal form). If there is no internal
     * form, then use the object form.
     */

    internalFormExists = optionPtr->specPtr->internalOffset >= 0;
    internalFormExists = optionPtr->specPtr->internalOffset != TCL_INDEX_NONE;
    switch (optionPtr->specPtr->type) {
    case TK_OPTION_STRING:
	if (internalFormExists) {
	    if (*((char **) internalPtr) != NULL) {
		ckfree(*((char **) internalPtr));
		*((char **) internalPtr) = NULL;
	    }
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1636
1637
1638
1639
1640
1641
1642


1643
1644
1645
1646
1647
1648
1649







-
-







	    Tk_FreeFontFromObj(tkwin, objPtr);
	}
	break;
    case TK_OPTION_STYLE:
	if (internalFormExists) {
	    Tk_FreeStyle(*((Tk_Style *) internalPtr));
	    *((Tk_Style *) internalPtr) = NULL;
	} else if (objPtr != NULL) {
	    Tk_FreeStyleFromObj(objPtr);
	}
	break;
    case TK_OPTION_BITMAP:
	if (internalFormExists) {
	    if (*((Pixmap *) internalPtr) != None) {
		Tk_FreeBitmap(Tk_Display(tkwin), *((Pixmap *) internalPtr));
		*((Pixmap *) internalPtr) = None;
1678
1679
1680
1681
1682
1683
1684
1685

1686
1687
1688
1689
1690
1691
1692
1671
1672
1673
1674
1675
1676
1677

1678
1679
1680
1681
1682
1683
1684
1685







-
+







	} else if (objPtr != NULL) {
	    Tk_FreeCursorFromObj(tkwin, objPtr);
	}
	break;
    case TK_OPTION_CUSTOM: {
	const Tk_ObjCustomOption *custom = optionPtr->extra.custom;
	if (internalFormExists && custom->freeProc != NULL) {
	    custom->freeProc(custom->clientData, tkwin, internalPtr);
	    custom->freeProc(custom->clientData, tkwin, (char *)internalPtr);
	}
	break;
    }
    default:
	break;
    }
}
1717
1718
1719
1720
1721
1722
1723
1724

1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738

1739
1740
1741
1742
1743
1744
1745
1710
1711
1712
1713
1714
1715
1716

1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730

1731
1732
1733
1734
1735
1736
1737
1738







-
+













-
+







 *--------------------------------------------------------------
 */

Tcl_Obj *
Tk_GetOptionInfo(
    Tcl_Interp *interp,		/* Interpreter for error reporting. If NULL,
				 * then no error message is created. */
    char *recordPtr,		/* Record whose fields contain current values
    void *recordPtr,		/* Record whose fields contain current values
				 * for options. */
    Tk_OptionTable optionTable,	/* Describes all the legal options. */
    Tcl_Obj *namePtr,		/* If non-NULL, the string value selects a
				 * single option whose info is to be returned.
				 * Otherwise info is returned for all options
				 * in optionTable. */
    Tk_Window tkwin)		/* Window associated with recordPtr; needed to
				 * compute correct default value for some
				 * options. */
{
    Tcl_Obj *resultPtr;
    OptionTable *tablePtr = (OptionTable *) optionTable;
    Option *optionPtr;
    int count;
    size_t count;

    /*
     * If information is only wanted for a single configuration spec, then
     * handle that one spec specially.
     */

    if (namePtr != NULL) {
1785
1786
1787
1788
1789
1790
1791
1792

1793
1794
1795
1796
1797
1798
1799
1778
1779
1780
1781
1782
1783
1784

1785
1786
1787
1788
1789
1790
1791
1792







-
+







 *	Memory is allocated.
 *
 *--------------------------------------------------------------
 */

static Tcl_Obj *
GetConfigList(
    char *recordPtr,		/* Pointer to record holding current values of
    void *recordPtr,		/* Pointer to record holding current values of
				 * configuration options. */
    Option *optionPtr,		/* Pointer to information describing a
				 * particular option. */
    Tk_Window tkwin)		/* Window corresponding to recordPtr. */
{
    Tcl_Obj *listPtr, *elementPtr;

1828
1829
1830
1831
1832
1833
1834
1835
1836


1837
1838
1839
1840
1841
1842
1843
1821
1822
1823
1824
1825
1826
1827


1828
1829
1830
1831
1832
1833
1834
1835
1836







-
-
+
+







	} else if (optionPtr->defaultPtr != NULL) {
	    elementPtr = optionPtr->defaultPtr;
	} else {
	    elementPtr = Tcl_NewObj();
	}
	Tcl_ListObjAppendElement(NULL, listPtr, elementPtr);

	if (optionPtr->specPtr->objOffset >= 0) {
	    elementPtr = *((Tcl_Obj **) (recordPtr
	if (optionPtr->specPtr->objOffset != TCL_INDEX_NONE) {
	    elementPtr = *((Tcl_Obj **) ((char *)recordPtr
		    + optionPtr->specPtr->objOffset));
	    if (elementPtr == NULL) {
		elementPtr = Tcl_NewObj();
	    }
	} else {
	    elementPtr = GetObjectForOption(recordPtr, optionPtr, tkwin);
	}
1863
1864
1865
1866
1867
1868
1869
1870

1871
1872
1873
1874
1875
1876
1877
1878

1879
1880
1881
1882


1883
1884


1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901















1902
1903
1904
1905
1906
1907
1908
1909







1910
1911
1912
1913
1914
1915
1916
1917







1918
1919
1920
1921
1922
1923
1924
1925







1926
1927
1928


1929
1930
1931
1932
1933
1934





1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945










1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965



















1966
1967
1968
1969
1970
1971
1972
1973







1974
1975
1976
1977
1978
1979
1980







1981
1982
1983
1984
1985
1986
1987
1856
1857
1858
1859
1860
1861
1862

1863
1864
1865
1866
1867
1868
1869
1870

1871
1872
1873

1874
1875
1876


1877
1878

















1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894







1895
1896
1897
1898
1899
1900
1901
1902







1903
1904
1905
1906
1907
1908
1909
1910







1911
1912
1913
1914
1915
1916
1917
1918


1919
1920
1921





1922
1923
1924
1925
1926
1927










1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938



















1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958







1959
1960
1961
1962
1963
1964
1965
1966






1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980







-
+







-
+


-

+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
+
+

-
-
-
-
-
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static Tcl_Obj *
GetObjectForOption(
    char *recordPtr,		/* Pointer to record holding current values of
    void *recordPtr,		/* Pointer to record holding current values of
				 * configuration options. */
    Option *optionPtr,		/* Pointer to information describing an option
				 * whose internal value is stored in
				 * *recordPtr. */
    Tk_Window tkwin)		/* Window corresponding to recordPtr. */
{
    Tcl_Obj *objPtr;
    char *internalPtr;		/* Points to internal value of option in
    void *internalPtr;		/* Points to internal value of option in
				 * record. */

    internalPtr = recordPtr + optionPtr->specPtr->internalOffset;
    objPtr = NULL;
    if (optionPtr->specPtr->internalOffset != TCL_INDEX_NONE) {
	internalPtr = (char *)recordPtr + optionPtr->specPtr->internalOffset;
    switch (optionPtr->specPtr->type) {
    case TK_OPTION_BOOLEAN:
	switch (optionPtr->specPtr->type) {
	case TK_OPTION_BOOLEAN:
	objPtr = Tcl_NewIntObj(*((int *) internalPtr));
	break;
    case TK_OPTION_INT:
	objPtr = Tcl_NewIntObj(*((int *) internalPtr));
	break;
    case TK_OPTION_DOUBLE:
	objPtr = Tcl_NewDoubleObj(*((double *) internalPtr));
	break;
    case TK_OPTION_STRING:
	objPtr = Tcl_NewStringObj(*((char **) internalPtr), -1);
	break;
    case TK_OPTION_STRING_TABLE:
	objPtr = Tcl_NewStringObj(((char **) optionPtr->specPtr->clientData)[
		*((int *) internalPtr)], -1);
	break;
    case TK_OPTION_COLOR: {
	XColor *colorPtr = *((XColor **) internalPtr);
	case TK_OPTION_INT:
	    objPtr = Tcl_NewWideIntObj(*((int *)internalPtr));
	    break;
	case TK_OPTION_DOUBLE:
	    objPtr = Tcl_NewDoubleObj(*((double *) internalPtr));
	    break;
	case TK_OPTION_STRING:
	    objPtr = Tcl_NewStringObj(*((char **)internalPtr), -1);
	    break;
	case TK_OPTION_STRING_TABLE:
	    objPtr = Tcl_NewStringObj(((char **) optionPtr->specPtr->clientData)[
		    *((int *) internalPtr)], -1);
	    break;
	case TK_OPTION_COLOR: {
	    XColor *colorPtr = *((XColor **)internalPtr);

	if (colorPtr != NULL) {
	    objPtr = Tcl_NewStringObj(Tk_NameOfColor(colorPtr), -1);
	}
	break;
    }
    case TK_OPTION_FONT: {
	Tk_Font tkfont = *((Tk_Font *) internalPtr);
	    if (colorPtr != NULL) {
		objPtr = Tcl_NewStringObj(Tk_NameOfColor(colorPtr), -1);
	    }
	    break;
	}
	case TK_OPTION_FONT: {
	    Tk_Font tkfont = *((Tk_Font *)internalPtr);

	if (tkfont != NULL) {
	    objPtr = Tcl_NewStringObj(Tk_NameOfFont(tkfont), -1);
	}
	break;
    }
    case TK_OPTION_STYLE: {
	Tk_Style style = *((Tk_Style *) internalPtr);
	    if (tkfont != NULL) {
		objPtr = Tcl_NewStringObj(Tk_NameOfFont(tkfont), -1);
	    }
	    break;
	}
	case TK_OPTION_STYLE: {
	    Tk_Style style = *((Tk_Style *)internalPtr);

	if (style != NULL) {
	    objPtr = Tcl_NewStringObj(Tk_NameOfStyle(style), -1);
	}
	break;
    }
    case TK_OPTION_BITMAP: {
	Pixmap pixmap = *((Pixmap *) internalPtr);
	    if (style != NULL) {
		objPtr = Tcl_NewStringObj(Tk_NameOfStyle(style), -1);
	    }
	    break;
	}
	case TK_OPTION_BITMAP: {
	    Pixmap pixmap = *((Pixmap *)internalPtr);

	if (pixmap != None) {
	    objPtr = Tcl_NewStringObj(
	    if (pixmap != None) {
		objPtr = Tcl_NewStringObj(
		    Tk_NameOfBitmap(Tk_Display(tkwin), pixmap), -1);
	}
	break;
    }
    case TK_OPTION_BORDER: {
	Tk_3DBorder border = *((Tk_3DBorder *) internalPtr);
	    }
	    break;
	}
	case TK_OPTION_BORDER: {
	    Tk_3DBorder border = *((Tk_3DBorder *)internalPtr);

	if (border != NULL) {
	    objPtr = Tcl_NewStringObj(Tk_NameOf3DBorder(border), -1);
	}
	break;
    }
    case TK_OPTION_RELIEF:
	objPtr = Tcl_NewStringObj(Tk_NameOfRelief(*((int *) internalPtr)), -1);
	break;
    case TK_OPTION_CURSOR: {
	Tk_Cursor cursor = *((Tk_Cursor *) internalPtr);
	    if (border != NULL) {
		objPtr = Tcl_NewStringObj(Tk_NameOf3DBorder(border), -1);
	    }
	    break;
	}
	case TK_OPTION_RELIEF:
	    objPtr = Tcl_NewStringObj(Tk_NameOfRelief(*((int *)internalPtr)), -1);
	    break;
	case TK_OPTION_CURSOR: {
	    Tk_Cursor cursor = *((Tk_Cursor *)internalPtr);

	if (cursor != NULL) {
	    objPtr = Tcl_NewStringObj(
		    Tk_NameOfCursor(Tk_Display(tkwin), cursor), -1);
	}
	break;
    }
    case TK_OPTION_JUSTIFY:
	objPtr = Tcl_NewStringObj(Tk_NameOfJustify(
		*((Tk_Justify *) internalPtr)), -1);
	break;
    case TK_OPTION_ANCHOR:
	objPtr = Tcl_NewStringObj(Tk_NameOfAnchor(
		*((Tk_Anchor *) internalPtr)), -1);
	break;
    case TK_OPTION_PIXELS:
	objPtr = Tcl_NewIntObj(*((int *) internalPtr));
	break;
    case TK_OPTION_WINDOW: {
	Tk_Window tkwin = *((Tk_Window *) internalPtr);
	    if (cursor != NULL) {
		objPtr = Tcl_NewStringObj(
		Tk_NameOfCursor(Tk_Display(tkwin), cursor), -1);
	    }
	    break;
	}
	case TK_OPTION_JUSTIFY:
	    objPtr = Tcl_NewStringObj(Tk_NameOfJustify(
		    *((Tk_Justify *)internalPtr)), -1);
	    break;
	case TK_OPTION_ANCHOR:
	    objPtr = Tcl_NewStringObj(Tk_NameOfAnchor(
		    *((Tk_Anchor *)internalPtr)), -1);
	    break;
	case TK_OPTION_PIXELS:
	    objPtr = Tcl_NewWideIntObj(*((int *)internalPtr));
	    break;
	case TK_OPTION_WINDOW: {
	    tkwin = *((Tk_Window *) internalPtr);

	if (tkwin != NULL) {
	    objPtr = Tcl_NewStringObj(Tk_PathName(tkwin), -1);
	}
	break;
    }
    case TK_OPTION_CUSTOM: {
	const Tk_ObjCustomOption *custom = optionPtr->extra.custom;
	    if (tkwin != NULL) {
		objPtr = Tcl_NewStringObj(Tk_PathName(tkwin), -1);
	    }
	    break;
	}
	case TK_OPTION_CUSTOM: {
	    const Tk_ObjCustomOption *custom = optionPtr->extra.custom;

	objPtr = custom->getProc(custom->clientData, tkwin, recordPtr,
		optionPtr->specPtr->internalOffset);
	break;
    }
    default:
	Tcl_Panic("bad option type in GetObjectForOption");
	    objPtr = custom->getProc(custom->clientData, tkwin, (char *)recordPtr,
		    optionPtr->specPtr->internalOffset);
	    break;
        }
        default:
	    Tcl_Panic("bad option type in GetObjectForOption");
	}
    }
    if (objPtr == NULL) {
	objPtr = Tcl_NewObj();
    }
    return objPtr;
}

2005
2006
2007
2008
2009
2010
2011
2012

2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031


2032
2033
2034
2035
2036
2037
2038
1998
1999
2000
2001
2002
2003
2004

2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022


2023
2024
2025
2026
2027
2028
2029
2030
2031







-
+

















-
-
+
+







 */

Tcl_Obj *
Tk_GetOptionValue(
    Tcl_Interp *interp,		/* Interpreter for error reporting. If NULL
				 * then no messages are provided for
				 * errors. */
    char *recordPtr,		/* Record whose fields contain current values
    void *recordPtr,		/* Record whose fields contain current values
				 * for options. */
    Tk_OptionTable optionTable,	/* Describes legal options. */
    Tcl_Obj *namePtr,		/* Gives the command-line name for the option
				 * whose value is to be returned. */
    Tk_Window tkwin)		/* Window corresponding to recordPtr. */
{
    OptionTable *tablePtr = (OptionTable *) optionTable;
    Option *optionPtr;
    Tcl_Obj *resultPtr;

    optionPtr = GetOptionFromObj(interp, namePtr, tablePtr);
    if (optionPtr == NULL) {
	return NULL;
    }
    if (optionPtr->specPtr->type == TK_OPTION_SYNONYM) {
	optionPtr = optionPtr->extra.synonymPtr;
    }
    if (optionPtr->specPtr->objOffset >= 0) {
	resultPtr = *((Tcl_Obj **) (recordPtr+optionPtr->specPtr->objOffset));
    if (optionPtr->specPtr->objOffset != TCL_INDEX_NONE) {
	resultPtr = *((Tcl_Obj **) ((char *)recordPtr+optionPtr->specPtr->objOffset));
	if (resultPtr == NULL) {
	    /*
	     * This option has a null value and is represented by a null
	     * object pointer. We can't return the null pointer, since that
	     * would indicate an error. Instead, return a new empty object.
	     */

2065
2066
2067
2068
2069
2070
2071
2072

2073
2074
2075
2076
2077
2078
2079
2080
2081
2082

2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101

2102
2103

2104
2105
2106
2107
2108
2109
2110
2058
2059
2060
2061
2062
2063
2064

2065
2066
2067
2068
2069
2070
2071
2072
2073
2074

2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093

2094
2095

2096
2097
2098
2099
2100
2101
2102
2103







-
+









-
+


















-
+

-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

Tcl_Obj *
TkDebugConfig(
    Tcl_Interp *interp,		/* Interpreter in which the table is
    TCL_UNUSED(Tcl_Interp *),		/* Interpreter in which the table is
				 * defined. */
    Tk_OptionTable table)	/* Table about which information is to be
				 * returned. May not necessarily exist in the
				 * interpreter anymore. */
{
    OptionTable *tablePtr = (OptionTable *) table;
    Tcl_HashEntry *hashEntryPtr;
    Tcl_HashSearch search;
    Tcl_Obj *objPtr;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    objPtr = Tcl_NewObj();
    if (!tablePtr || !tsdPtr->initialized) {
	return objPtr;
    }

    /*
     * Scan all the tables for this interpreter to make sure that the one we
     * want still is valid.
     */

    for (hashEntryPtr = Tcl_FirstHashEntry(&tsdPtr->hashTable, &search);
	    hashEntryPtr != NULL;
	    hashEntryPtr = Tcl_NextHashEntry(&search)) {
	if (tablePtr == (OptionTable *) Tcl_GetHashValue(hashEntryPtr)) {
	    for ( ; tablePtr != NULL; tablePtr = tablePtr->nextPtr) {
		Tcl_ListObjAppendElement(NULL, objPtr,
			Tcl_NewIntObj(tablePtr->refCount));
			Tcl_NewWideIntObj(tablePtr->refCount));
		Tcl_ListObjAppendElement(NULL, objPtr,
			Tcl_NewIntObj(tablePtr->numOptions));
			Tcl_NewWideIntObj(tablePtr->numOptions));
		Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewStringObj(
			tablePtr->options[0].specPtr->optionName, -1));
	    }
	    break;
	}
    }
    return objPtr;
Changes to generic/tkConsole.c.
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

47
48
49
50
51
52
53
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54







-
+


















-
+



















+







/*
 * tkConsole.c --
 *
 *	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.
 */

#include "tkInt.h"

/*
 * Each console is associated with an instance of the ConsoleInfo struct.
 * It keeps track of what interp holds the Tk application that displays
 * the console, and what interp is controlled by the interactions in that
 * console.  A refCount permits the struct to be shared as instance data
 * by commands and by channels.
 */

typedef struct ConsoleInfo {
    Tcl_Interp *consoleInterp;	/* Interpreter displaying the console. */
    Tcl_Interp *interp;		/* Interpreter controlled by console. */
    int refCount;
    size_t refCount;
} ConsoleInfo;

/*
 * Each console channel holds an instance of the ChannelData struct as
 * its instance data.  It contains ConsoleInfo, so the channel can work
 * with the appropriate console window, and a type value to distinguish
 * the stdout channel from the stderr channel.
 */

typedef struct ChannelData {
    ConsoleInfo *info;
    int type;			/* TCL_STDOUT or TCL_STDERR */
} ChannelData;

/*
 * Prototypes for local procedures defined in this file:
 */

static int	ConsoleClose(ClientData instanceData, Tcl_Interp *interp);
static int	Console2Close(ClientData instanceData, Tcl_Interp *interp, int flags);
static void	ConsoleDeleteProc(ClientData clientData);
static void	ConsoleEventProc(ClientData clientData, XEvent *eventPtr);
static int	ConsoleHandle(ClientData instanceData, int direction,
		    ClientData *handlePtr);
static int	ConsoleInput(ClientData instanceData, char *buf, int toRead,
		    int *errorCode);
static int	ConsoleObjCmd(ClientData clientData, Tcl_Interp *interp,
62
63
64
65
66
67
68
69
70


71
72
73
74
75
76
77
78

79
80
81
82
83
84
85
63
64
65
66
67
68
69


70
71
72
73
74
75
76
77
78

79
80
81
82
83
84
85
86







-
-
+
+







-
+








/*
 * This structure describes the channel type structure for file based IO:
 */

static const Tcl_ChannelType consoleChannelType = {
    "console",			/* Type name. */
    TCL_CHANNEL_VERSION_4,	/* v4 channel */
    ConsoleClose,		/* Close proc. */
    TCL_CHANNEL_VERSION_5,	/* v5 channel */
    (Tcl_DriverCloseProc *)ConsoleClose,		/* Close proc. */
    ConsoleInput,		/* Input proc. */
    ConsoleOutput,		/* Output proc. */
    NULL,			/* Seek proc. */
    NULL,			/* Set option proc. */
    NULL,			/* Get option proc. */
    ConsoleWatch,		/* Watch for events on console. */
    ConsoleHandle,		/* Get a handle from the device. */
    NULL,			/* close2proc. */
    Console2Close,			/* close2proc. */
    NULL,			/* Always non-blocking.*/
    NULL,			/* flush proc. */
    NULL,			/* handler proc. */
    NULL,			/* wide seek proc */
    NULL,			/* thread action proc */
    NULL
};
219
220
221
222
223
224
225
226

227
228
229
230

231
232
233
234
235
236
237
220
221
222
223
224
225
226

227
228
229
230

231
232
233
234
235
236
237
238







-
+



-
+







    ConsoleInfo *info;
    Tcl_Channel consoleChannel;

    /*
     * Ensure that we are getting a compatible version of Tcl.
     */

    if (Tcl_InitStubs(interp, "8.6", 0) == NULL) {
    if (Tcl_InitStubs(interp, "8.6-", 0) == NULL) {
        return;
    }

    consoleInitPtr = Tcl_GetThreadData(&consoleInitKey, (int) sizeof(int));
    consoleInitPtr = (int *)Tcl_GetThreadData(&consoleInitKey, (int) sizeof(int));
    if (*consoleInitPtr) {
	/*
	 * We've already initialized console channels in this thread.
	 */

	return;
    }
251
252
253
254
255
256
257
258

259
260
261
262
263
264

265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281

282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298

299
300
301
302
303
304
305
252
253
254
255
256
257
258

259
260
261
262
263
264

265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281

282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298

299
300
301
302
303
304
305
306







-
+





-
+
















-
+
















-
+







    }

    /*
     * At least one std channel wants to be tied to the console, so create the
     * interp for it to live in.
     */

    info = ckalloc(sizeof(ConsoleInfo));
    info = (ConsoleInfo *) ckalloc(sizeof(ConsoleInfo));
    info->consoleInterp = NULL;
    info->interp = NULL;
    info->refCount = 0;

    if (doIn) {
	ChannelData *data = ckalloc(sizeof(ChannelData));
	ChannelData *data = (ChannelData *)ckalloc(sizeof(ChannelData));

	data->info = info;
	data->info->refCount++;
	data->type = TCL_STDIN;
	consoleChannel = Tcl_CreateChannel(&consoleChannelType, "console0",
		data, TCL_READABLE);
	if (consoleChannel != NULL) {
	    Tcl_SetChannelOption(NULL, consoleChannel, "-translation", "lf");
	    Tcl_SetChannelOption(NULL, consoleChannel, "-buffering", "none");
	    Tcl_SetChannelOption(NULL, consoleChannel, "-encoding", "utf-8");
	}
	Tcl_SetStdChannel(consoleChannel, TCL_STDIN);
	Tcl_RegisterChannel(NULL, consoleChannel);
    }

    if (doOut) {
	ChannelData *data = ckalloc(sizeof(ChannelData));
	ChannelData *data = (ChannelData *)ckalloc(sizeof(ChannelData));

	data->info = info;
	data->info->refCount++;
	data->type = TCL_STDOUT;
	consoleChannel = Tcl_CreateChannel(&consoleChannelType, "console1",
		data, TCL_WRITABLE);
	if (consoleChannel != NULL) {
	    Tcl_SetChannelOption(NULL, consoleChannel, "-translation", "lf");
	    Tcl_SetChannelOption(NULL, consoleChannel, "-buffering", "none");
	    Tcl_SetChannelOption(NULL, consoleChannel, "-encoding", "utf-8");
	}
	Tcl_SetStdChannel(consoleChannel, TCL_STDOUT);
	Tcl_RegisterChannel(NULL, consoleChannel);
    }

    if (doErr) {
	ChannelData *data = ckalloc(sizeof(ChannelData));
	ChannelData *data = (ChannelData *)ckalloc(sizeof(ChannelData));

	data->info = info;
	data->info->refCount++;
	data->type = TCL_STDERR;
	consoleChannel = Tcl_CreateChannel(&consoleChannelType, "console2",
		data, TCL_WRITABLE);
	if (consoleChannel != NULL) {
373
374
375
376
377
378
379
380

381
382
383
384
385
386
387
374
375
376
377
378
379
380

381
382
383
384
385
386
387
388







-
+







	ChannelData *data = (ChannelData *) Tcl_GetChannelInstanceData(chan);
	info = data->info;
	if (info->consoleInterp) {
	    /*
	     * New ConsoleInfo for a new console window.
	     */

	    info = ckalloc(sizeof(ConsoleInfo));
	    info = (ConsoleInfo *)ckalloc(sizeof(ConsoleInfo));
	    info->refCount = 0;

	    /*
	     * Update any console channels to make use of the new console.
	     */

	    if (Tcl_GetChannelType(chan = Tcl_GetStdChannel(TCL_STDIN))
403
404
405
406
407
408
409
410

411
412
413
414
415
416
417
404
405
406
407
408
409
410

411
412
413
414
415
416
417
418







-
+







		data = (ChannelData *) Tcl_GetChannelInstanceData(chan);
		data->info->refCount--;
		data->info = info;
		data->info->refCount++;
	    }
	}
    } else {
	info = ckalloc(sizeof(ConsoleInfo));
	info = (ConsoleInfo *)ckalloc(sizeof(ConsoleInfo));
	info->refCount = 0;
    }

    info->consoleInterp = consoleInterp;
    info->interp = interp;

    Tcl_CallWhenDeleted(consoleInterp, InterpDeleteProc, info);
452
453
454
455
456
457
458
459

460
461
462
463
464
465
466
453
454
455
456
457
458
459

460
461
462
463
464
465
466
467







-
+







    Tcl_Release(consoleInterp);
    if (result == TCL_ERROR) {
	Tcl_DeleteCommandFromToken(interp, token);
	mainWindow = Tk_MainWindow(interp);
	if (mainWindow) {
	    Tk_DeleteEventHandler(mainWindow, StructureNotifyMask,
		    ConsoleEventProc, info);
	    if (--info->refCount <= 0) {
	    if (info->refCount-- <= 1) {
		ckfree(info);
	    }
	}
	goto error;
    }
    return TCL_OK;

493
494
495
496
497
498
499
500

501
502
503
504
505
506
507
494
495
496
497
498
499
500

501
502
503
504
505
506
507
508







-
+







static int
ConsoleOutput(
    ClientData instanceData,	/* Indicates which device to use. */
    const char *buf,		/* The data buffer. */
    int toWrite,		/* How many bytes to write? */
    int *errorCode)		/* Where to store error code. */
{
    ChannelData *data = instanceData;
    ChannelData *data = (ChannelData *)instanceData;
    ConsoleInfo *info = data->info;

    *errorCode = 0;
    Tcl_SetErrno(0);

    if (info) {
	Tcl_Interp *consoleInterp = info->consoleInterp;
554
555
556
557
558
559
560
561
562
563
564
565
566



567
568

569
570
571
572
573
574
575
576

577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593


594
595

596
597
598
599

600
601
602
603
604
605
606
607
608
609












610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633


634
635
636
637
638
639
640
555
556
557
558
559
560
561

562
563



564
565
566
567

568
569
570
571
572
573
574
575

576
577
578
579
580
581
582
583
584
585
586
587
588

589
590


591
592
593

594
595
596
597

598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639

640
641


642
643
644
645
646
647
648
649
650







-


-
-
-
+
+
+

-
+







-
+












-


-
-
+
+

-
+



-
+










+
+
+
+
+
+
+
+
+
+
+
+



















-


-
-
+
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
ConsoleInput(
    ClientData instanceData,	/* Unused. */
    char *buf,			/* Where to store data read. */
    int bufSize,		/* How much space is available in the
    TCL_UNUSED(void *),
    TCL_UNUSED(char *),			/* Where to store data read. */
    TCL_UNUSED(int),		/* How much space is available in the
				 * buffer? */
    int *errorCode)		/* Where to store error code. */
    TCL_UNUSED(int *))		/* Where to store error code. */
{
    return 0;			/* Always return EOF. */
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleClose --
 * ConsoleClose/Console2Close --
 *
 *	Closes the IO channel.
 *
 * Results:
 *	Always returns 0 (success).
 *
 * Side effects:
 *	Frees the dummy file associated with the channel.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
ConsoleClose(
    ClientData instanceData,	/* Unused. */
    Tcl_Interp *interp)		/* Unused. */
    ClientData instanceData,
    TCL_UNUSED(Tcl_Interp *))
{
    ChannelData *data = instanceData;
    ChannelData *data = (ChannelData *)instanceData;
    ConsoleInfo *info = data->info;

    if (info) {
	if (--info->refCount <= 0) {
	if (info->refCount-- <= 1) {
	    /*
	     * Assuming the Tcl_Interp * fields must already be NULL.
	     */

	    ckfree(info);
	}
    }
    ckfree(data);
    return 0;
}

static int
Console2Close(
    ClientData instanceData,	/* Unused. */
    Tcl_Interp *interp,		/* Unused. */
    int flags)
{
    if ((flags&(TCL_CLOSE_READ|TCL_CLOSE_WRITE))==0) {
	return ConsoleClose(instanceData, interp);
    }
    return EINVAL;
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleWatch --
 *
 *	Called by the notifier to set up the console device so that events
 *	will be noticed. Since there are no events on the console, this
 *	routine just returns without doing anything.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static void
ConsoleWatch(
    ClientData instanceData,	/* Device ID for the channel. */
    int mask)			/* OR-ed combination of TCL_READABLE,
    TCL_UNUSED(void *),	/* Device ID for the channel. */
    TCL_UNUSED(int))			/* OR-ed combination of TCL_READABLE,
				 * TCL_WRITABLE and TCL_EXCEPTION, for the
				 * events we are interested in. */
{
}

/*
 *----------------------------------------------------------------------
649
650
651
652
653
654
655
656
657
658
659
660


661
662
663

664
665
666
667
668
669
670
659
660
661
662
663
664
665

666
667


668
669
670
671

672
673
674
675
676
677
678
679







-


-
-
+
+


-
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
ConsoleHandle(
    ClientData instanceData,	/* Device ID for the channel. */
    int direction,		/* TCL_READABLE or TCL_WRITABLE to indicate
    TCL_UNUSED(void *),	/* Device ID for the channel. */
    TCL_UNUSED(int),		/* TCL_READABLE or TCL_WRITABLE to indicate
				 * which direction of the channel is being
				 * requested. */
    ClientData *handlePtr)	/* Where to store handle */
    TCL_UNUSED(void **))	/* Where to store handle */
{
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
690
691
692
693
694
695
696
697

698
699
700
701
702
703
704
699
700
701
702
703
704
705

706
707
708
709
710
711
712
713







-
+







    Tcl_Obj *const objv[])	/* Argument objects */
{
    int index, result;
    static const char *const options[] = {
	"eval", "hide", "show", "title", NULL};
    enum option {CON_EVAL, CON_HIDE, CON_SHOW, CON_TITLE};
    Tcl_Obj *cmd = NULL;
    ConsoleInfo *info = clientData;
    ConsoleInfo *info = (ConsoleInfo *)clientData;
    Tcl_Interp *consoleInterp = info->consoleInterp;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "option ?arg?");
	return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObjStruct(interp, objv[1], options,
780
781
782
783
784
785
786
787

788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806

807
808
809
810
811
812
813
789
790
791
792
793
794
795

796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814

815
816
817
818
819
820
821
822







-
+


















-
+







    Tcl_Interp *interp,		/* Current interpreter */
    int objc,			/* Number of arguments */
    Tcl_Obj *const objv[])	/* Argument objects */
{
    int index, result = TCL_OK;
    static const char *const options[] = {"eval", "record", NULL};
    enum option {OTHER_EVAL, OTHER_RECORD};
    ConsoleInfo *info = clientData;
    ConsoleInfo *info = (ConsoleInfo *)clientData;
    Tcl_Interp *otherInterp = info->interp;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "option arg");
	return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObjStruct(interp, objv[1], options,
	    sizeof(char *), "option", 0, &index) != TCL_OK) {
	return TCL_ERROR;
    }

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "script");
	return TCL_ERROR;
    }

    if ((otherInterp == NULL) || Tcl_InterpDeleted(otherInterp)) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"no active master interp", -1));
		"no active parent interp", -1));
	Tcl_SetErrorCode(interp, "TK", "CONSOLE", "NO_INTERP", NULL);
	return TCL_ERROR;
    }

    Tcl_Preserve(otherInterp);
    switch ((enum option) index) {
    case OTHER_EVAL:
848
849
850
851
852
853
854
855

856
857
858
859
860
861
862
857
858
859
860
861
862
863

864
865
866
867
868
869
870
871







-
+







 *----------------------------------------------------------------------
 */

static void
DeleteConsoleInterp(
    ClientData clientData)
{
    Tcl_Interp *interp = clientData;
    Tcl_Interp *interp = (Tcl_Interp *)clientData;

    Tcl_DeleteInterp(interp);
}

/*
 *----------------------------------------------------------------------
 *
875
876
877
878
879
880
881
882

883
884
885
886
887
888

889
890
891
892
893
894
895
884
885
886
887
888
889
890

891
892
893
894
895
896

897
898
899
900
901
902
903
904







-
+





-
+







 */

static void
InterpDeleteProc(
    ClientData clientData,
    Tcl_Interp *interp)
{
    ConsoleInfo *info = clientData;
    ConsoleInfo *info = (ConsoleInfo *)clientData;

    if (info->consoleInterp == interp) {
	Tcl_DeleteThreadExitHandler(DeleteConsoleInterp, info->consoleInterp);
	info->consoleInterp = NULL;
    }
    if (--info->refCount <= 0) {
    if (info->refCount-- <= 1) {
	ckfree(info);
    }
}

/*
 *----------------------------------------------------------------------
 *
907
908
909
910
911
912
913
914

915
916
917
918
919

920
921
922
923
924
925
926
927
928
929

930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949

950
951
952
953
954
955
956

957
958
959
960
961
962
963
964
965
966
967
968
916
917
918
919
920
921
922

923
924
925
926
927

928
929
930
931
932
933
934
935
936
937

938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957

958
959
960
961
962
963
964

965
966
967
968
969
970
971
972
973
974
975
976
977







-
+




-
+









-
+



















-
+






-
+












 *----------------------------------------------------------------------
 */

static void
ConsoleDeleteProc(
    ClientData clientData)
{
    ConsoleInfo *info = clientData;
    ConsoleInfo *info = (ConsoleInfo *)clientData;

    if (info->consoleInterp) {
	Tcl_DeleteInterp(info->consoleInterp);
    }
    if (--info->refCount <= 0) {
    if (info->refCount-- <= 1) {
	ckfree(info);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleEventProc --
 *
 *	This event function is registered on the main window of the slave
 *	This event function is registered on the main window of the child
 *	interpreter. If the user or a running script causes the main window to
 *	be destroyed, then we need to inform the console interpreter by
 *	invoking "::tk::ConsoleExit".
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Invokes the "::tk::ConsoleExit" command in the console interp.
 *
 *----------------------------------------------------------------------
 */

static void
ConsoleEventProc(
    ClientData clientData,
    XEvent *eventPtr)
{
    if (eventPtr->type == DestroyNotify) {
	ConsoleInfo *info = clientData;
	ConsoleInfo *info = (ConsoleInfo *)clientData;
	Tcl_Interp *consoleInterp = info->consoleInterp;

	if (consoleInterp && !Tcl_InterpDeleted(consoleInterp)) {
	    Tcl_EvalEx(consoleInterp, "tk::ConsoleExit", -1, TCL_EVAL_GLOBAL);
	}

	if (--info->refCount <= 0) {
	if (info->refCount-- <= 1) {
	    ckfree(info);
	}
    }
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Changes to generic/tkCursor.c.
1
2
3
4
5
6
7
8
9


10
11
12
13
14
15
16
1
2
3
4
5
6
7


8
9
10
11
12
13
14
15
16







-
-
+
+







/*
 * tkCursor.c --
 *
 *	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.
 */

#include "tkInt.h"

96
97
98
99
100
101
102
103

104
105
106
107
108
109
110
96
97
98
99
100
101
102

103
104
105
106
107
108
109
110







-
+







				 * obj's string rep. */
{
    TkCursor *cursorPtr;

    if (objPtr->typePtr != &tkCursorObjType) {
	InitCursorObj(objPtr);
    }
    cursorPtr = objPtr->internalRep.twoPtrValue.ptr1;
    cursorPtr = (TkCursor *)objPtr->internalRep.twoPtrValue.ptr1;

    /*
     * If the object currently points to a TkCursor, see if it's the one we
     * want. If so, increment its reference count and return.
     */

    if (cursorPtr != NULL) {
125
126
127
128
129
130
131
132

133
134
135
136
137
138
139
125
126
127
128
129
130
131

132
133
134
135
136
137
138
139







-
+







    /*
     * The object didn't point to the TkCursor that we wanted. Search the list
     * of TkCursors with the same name to see if one of the other TkCursors is
     * the right one.
     */

    if (cursorPtr != NULL) {
	TkCursor *firstCursorPtr = Tcl_GetHashValue(cursorPtr->hashPtr);
	TkCursor *firstCursorPtr = (TkCursor *)Tcl_GetHashValue(cursorPtr->hashPtr);

	FreeCursorObj(objPtr);
	for (cursorPtr = firstCursorPtr;  cursorPtr != NULL;
		cursorPtr = cursorPtr->nextPtr) {
	    if (Tk_Display(tkwin) == cursorPtr->display) {
		cursorPtr->resourceRefCount++;
		cursorPtr->objRefCount++;
225
226
227
228
229
230
231
232

233
234
235
236
237
238
239
240
241
242
243
244

245
246
247
248
249
250
251
225
226
227
228
229
230
231

232
233
234
235
236
237
238
239
240
241
242
243

244
245
246
247
248
249
250
251







-
+











-
+







TkcGetCursor(
    Tcl_Interp *interp,		/* Interpreter to use for error reporting. */
    Tk_Window tkwin,		/* Window in which cursor will be used. */
    const char *string)		/* Description of cursor. See manual entry for
				 * details on legal syntax. */
{
    Tcl_HashEntry *nameHashPtr;
    register TkCursor *cursorPtr;
    TkCursor *cursorPtr;
    TkCursor *existingCursorPtr = NULL;
    int isNew;
    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;

    if (!dispPtr->cursorInit) {
	CursorInit(dispPtr);
    }

    nameHashPtr = Tcl_CreateHashEntry(&dispPtr->cursorNameTable,
	    string, &isNew);
    if (!isNew) {
	existingCursorPtr = Tcl_GetHashValue(nameHashPtr);
	existingCursorPtr = (TkCursor *)Tcl_GetHashValue(nameHashPtr);
	for (cursorPtr = existingCursorPtr; cursorPtr != NULL;
		cursorPtr = cursorPtr->nextPtr) {
	    if (Tk_Display(tkwin) == cursorPtr->display) {
		cursorPtr->resourceRefCount++;
		return cursorPtr;
	    }
	}
316
317
318
319
320
321
322
323

324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344

345
346
347
348
349
350
351
316
317
318
319
320
321
322

323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343

344
345
346
347
348
349
350
351







-
+




















-
+







    int width, int height,	/* Dimensions of cursor. */
    int xHot, int yHot,		/* Location of hot-spot in cursor. */
    Tk_Uid fg,			/* Foreground color for cursor. */
    Tk_Uid bg)			/* Background color for cursor. */
{
    DataKey dataKey;
    Tcl_HashEntry *dataHashPtr;
    register TkCursor *cursorPtr;
    TkCursor *cursorPtr;
    int isNew;
    XColor fgColor, bgColor;
    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;

    if (!dispPtr->cursorInit) {
	CursorInit(dispPtr);
    }

    dataKey.source = source;
    dataKey.mask = mask;
    dataKey.width = width;
    dataKey.height = height;
    dataKey.xHot = xHot;
    dataKey.yHot = yHot;
    dataKey.fg = fg;
    dataKey.bg = bg;
    dataKey.display = Tk_Display(tkwin);
    dataHashPtr = Tcl_CreateHashEntry(&dispPtr->cursorDataTable,
	    (char *) &dataKey, &isNew);
    if (!isNew) {
	cursorPtr = Tcl_GetHashValue(dataHashPtr);
	cursorPtr = (TkCursor *)Tcl_GetHashValue(dataHashPtr);
	cursorPtr->resourceRefCount++;
	return cursorPtr->cursor;
    }

    /*
     * No suitable cursor exists yet. Make one using the data available and
     * add it to the database.
424
425
426
427
428
429
430
431

432
433
434
435

436
437
438
439
440
441
442
424
425
426
427
428
429
430

431
432
433
434

435
436
437
438
439
440
441
442







-
+



-
+







    dispPtr = TkGetDisplay(display);

    if (!dispPtr->cursorInit) {
    printid:
	sprintf(dispPtr->cursorString, "cursor id 0x%" TCL_Z_MODIFIER "x", (size_t)cursor);
	return dispPtr->cursorString;
    }
    idHashPtr = Tcl_FindHashEntry(&dispPtr->cursorIdTable, (char *) cursor);
    idHashPtr = Tcl_FindHashEntry(&dispPtr->cursorIdTable, cursor);
    if (idHashPtr == NULL) {
	goto printid;
    }
    cursorPtr = Tcl_GetHashValue(idHashPtr);
    cursorPtr = (TkCursor *)Tcl_GetHashValue(idHashPtr);
    if (cursorPtr->otherTable != &dispPtr->cursorNameTable) {
	goto printid;
    }
    return cursorPtr->hashPtr->key.string;
}

/*
459
460
461
462
463
464
465
466
467

468
469
470
471
472

473
474
475
476
477
478
479
459
460
461
462
463
464
465


466
467
468
469
470

471
472
473
474
475
476
477
478







-
-
+




-
+








static void
FreeCursor(
    TkCursor *cursorPtr)	/* Cursor to be released. */
{
    TkCursor *prevPtr;

    cursorPtr->resourceRefCount--;
    if (cursorPtr->resourceRefCount > 0) {
    if (cursorPtr->resourceRefCount-- > 1) {
	return;
    }

    Tcl_DeleteHashEntry(cursorPtr->idHashPtr);
    prevPtr = Tcl_GetHashValue(cursorPtr->hashPtr);
    prevPtr = (TkCursor *)Tcl_GetHashValue(cursorPtr->hashPtr);
    if (prevPtr == cursorPtr) {
	if (cursorPtr->nextPtr == NULL) {
	    Tcl_DeleteHashEntry(cursorPtr->hashPtr);
	} else {
	    Tcl_SetHashValue(cursorPtr->hashPtr, cursorPtr->nextPtr);
	}
    } else {
514
515
516
517
518
519
520
521

522
523
524
525

526
527
528
529
530
531
532
513
514
515
516
517
518
519

520
521
522
523

524
525
526
527
528
529
530
531







-
+



-
+







    Tcl_HashEntry *idHashPtr;
    TkDisplay *dispPtr = TkGetDisplay(display);

    if (!dispPtr->cursorInit) {
	Tcl_Panic("Tk_FreeCursor called before Tk_GetCursor");
    }

    idHashPtr = Tcl_FindHashEntry(&dispPtr->cursorIdTable, (char *) cursor);
    idHashPtr = Tcl_FindHashEntry(&dispPtr->cursorIdTable, cursor);
    if (idHashPtr == NULL) {
	Tcl_Panic("Tk_FreeCursor received unknown cursor argument");
    }
    FreeCursor(Tcl_GetHashValue(idHashPtr));
    FreeCursor((TkCursor *)Tcl_GetHashValue(idHashPtr));
}

/*
 *----------------------------------------------------------------------
 *
 * Tk_FreeCursorFromObj --
 *
583
584
585
586
587
588
589
590

591
592
593
594

595
596
597
598
599
600
601
582
583
584
585
586
587
588

589
590
591


592
593
594
595
596
597
598
599







-
+


-
-
+







    objPtr->typePtr = NULL;
}

static void
FreeCursorObj(
    Tcl_Obj *objPtr)		/* The object we are releasing. */
{
    TkCursor *cursorPtr = objPtr->internalRep.twoPtrValue.ptr1;
    TkCursor *cursorPtr = (TkCursor *)objPtr->internalRep.twoPtrValue.ptr1;

    if (cursorPtr != NULL) {
	cursorPtr->objRefCount--;
	if ((cursorPtr->objRefCount == 0)
	if ((cursorPtr->objRefCount-- <= 1)
		&& (cursorPtr->resourceRefCount == 0)) {
	    ckfree(cursorPtr);
	}
	objPtr->internalRep.twoPtrValue.ptr1 = NULL;
    }
}

618
619
620
621
622
623
624
625

626
627
628
629
630
631
632
616
617
618
619
620
621
622

623
624
625
626
627
628
629
630







-
+







 */

static void
DupCursorObjProc(
    Tcl_Obj *srcObjPtr,		/* The object we are copying from. */
    Tcl_Obj *dupObjPtr)		/* The object we are copying to. */
{
    TkCursor *cursorPtr = srcObjPtr->internalRep.twoPtrValue.ptr1;
    TkCursor *cursorPtr = (TkCursor *)srcObjPtr->internalRep.twoPtrValue.ptr1;

    dupObjPtr->typePtr = srcObjPtr->typePtr;
    dupObjPtr->internalRep.twoPtrValue.ptr1 = cursorPtr;

    if (cursorPtr != NULL) {
	cursorPtr->objRefCount++;
    }
703
704
705
706
707
708
709
710

711
712
713
714
715
716
717
718
719
720
721
722
723
724
725

726
727
728
729
730
731
732
701
702
703
704
705
706
707

708
709
710
711
712
713
714
715
716
717
718
719
720
721
722

723
724
725
726
727
728
729
730







-
+














-
+







    /*
     * The internal representation is a cache of the last cursor used with the
     * given name. But there can be lots different cursors for each cursor
     * name; one cursor for each display. Check to see if the cursor we have
     * cached is the one that is needed.
     */

    cursorPtr = objPtr->internalRep.twoPtrValue.ptr1;
    cursorPtr = (TkCursor *)objPtr->internalRep.twoPtrValue.ptr1;
    if ((cursorPtr != NULL) && (Tk_Display(tkwin) == cursorPtr->display)) {
	return cursorPtr;
    }

    /*
     * If we get to here, it means the cursor we need is not in the cache.
     * Try to look up the cursor in the TkDisplay structure of the window.
     */

    hashPtr = Tcl_FindHashEntry(&dispPtr->cursorNameTable,
	    Tcl_GetString(objPtr));
    if (hashPtr == NULL) {
	goto error;
    }
    for (cursorPtr = Tcl_GetHashValue(hashPtr);
    for (cursorPtr = (TkCursor *)Tcl_GetHashValue(hashPtr);
	    cursorPtr != NULL; cursorPtr = cursorPtr->nextPtr) {
	if (Tk_Display(tkwin) == cursorPtr->display) {
	    FreeCursorObj(objPtr);
	    objPtr->internalRep.twoPtrValue.ptr1 = cursorPtr;
	    cursorPtr->objRefCount++;
	    return cursorPtr;
	}
853
854
855
856
857
858
859
860

861
862
863
864
865
866
867

868
869

870
871
872
873
874
875
876
877
878
879
880
881
882
851
852
853
854
855
856
857

858
859
860
861
862
863
864

865
866

867
868
869
870
871
872
873
874
875
876
877
878
879
880







-
+






-
+

-
+














    if (!dispPtr->cursorInit) {
	CursorInit(dispPtr);
    }
    resultPtr = Tcl_NewObj();
    hashPtr = Tcl_FindHashEntry(&dispPtr->cursorNameTable, name);
    if (hashPtr != NULL) {
	cursorPtr = Tcl_GetHashValue(hashPtr);
	cursorPtr = (TkCursor *)Tcl_GetHashValue(hashPtr);
	if (cursorPtr == NULL) {
	    Tcl_Panic("TkDebugCursor found empty hash table entry");
	}
	for ( ; (cursorPtr != NULL); cursorPtr = cursorPtr->nextPtr) {
	    objPtr = Tcl_NewObj();
	    Tcl_ListObjAppendElement(NULL, objPtr,
		    Tcl_NewIntObj(cursorPtr->resourceRefCount));
		    Tcl_NewWideIntObj(cursorPtr->resourceRefCount));
	    Tcl_ListObjAppendElement(NULL, objPtr,
		    Tcl_NewIntObj(cursorPtr->objRefCount));
		    Tcl_NewWideIntObj(cursorPtr->objRefCount));
	    Tcl_ListObjAppendElement(NULL, resultPtr, objPtr);
	}
    }
    return resultPtr;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Changes to generic/tkDList.h.
1
2
3
4
5
6
7
8
9
10

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32


33
34
35
36
37
38
39
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30


31
32
33
34
35
36
37
38
39









-
+




















-
-
+
+







/*
 * tkDList.h --
 *
 * A list is headed by pointers to first and last element. The elements
 * 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.
 */

/*
 * Note that this file will not be included in header files, it is the purpose
 * of this file to be included in source files only. Thus we are not using the
 * prefix "Tk_" here for functions, because all the functions have private scope.
 */

/*
 * -------------------------------------------------------------------------------
 * Use the double linked list in the following way:
 * -------------------------------------------------------------------------------
 * typedef struct MyListEntry { TK_DLIST_LINKS(MyListEntry); int value; } MyListEntry;
 * TK_DLIST_DEFINE(MyList, MyListEntry);
 * MyList listHdr = TK_DLIST_LIST_INITIALIZER; // or MyList_Init(&listHdr)
 * MyListEntry *p;
 * int i = 0;
 * MyList_Append(&listHdr, ckalloc(sizeof(MyListEntry)));
 * MyList_Append(&listHdr, ckalloc(sizeof(MyListEntry)));
 * MyList_Append(&listHdr, (MyListEntry *)ckalloc(sizeof(MyListEntry)));
 * MyList_Append(&listHdr, (MyListEntry *)ckalloc(sizeof(MyListEntry)));
 * TK_DLIST_FOREACH(p, &listHdr) { p->value = i++; }
 * // ...
 * MyList_RemoveHead(&listHdr);
 * MyList_RemoveHead(&listHdr);
 * MyList_Clear(MyListEntry, &listHdr); // invokes ckfree() for each element
 * -------------------------------------------------------------------------------
 * IMPORTANT NOTE: TK_DLIST_LINKS must be used at start of struct!
357
358
359
360
361
362
363
364

365
366

367
368
369
370
371
372
373
374
375
376
377
378
379
380
381

382
383

384
385
386
387
388
389
390
357
358
359
360
361
362
363

364
365

366
367
368
369
370
371
372
373
374
375
376
377
378
379
380

381
382

383
384
385
386
387
388
389
390







-
+

-
+














-
+

-
+







										\
__TK_DLIST_UNUSED								\
static void									\
LT##_Prepend(LT *head, struct ElemType *elem)					\
{										\
    assert(head);								\
    assert(elem);								\
    elem->_dl_.prev = (void *) head;						\
    elem->_dl_.prev = (PSEntry *) head;						\
    if (!head->first) {								\
	elem->_dl_.next = (void *) head;					\
	elem->_dl_.next = (PSEntry *) head;					\
	head->last = elem;							\
    } else {									\
	elem->_dl_.next = head->first;						\
	head->first->_dl_.prev = elem;						\
    }										\
    head->first = elem;								\
}										\
										\
__TK_DLIST_UNUSED								\
static void									\
LT##_Append(LT *head, struct ElemType *elem)					\
{										\
    assert(head);								\
    assert(elem);								\
    elem->_dl_.next = (void *) head;						\
    elem->_dl_.next = (PSEntry *) head;						\
    if (!head->first) {								\
	elem->_dl_.prev = (void *) head;					\
	elem->_dl_.prev = (PSEntry *) head;					\
	head->first = elem;							\
    } else {									\
	elem->_dl_.prev = head->last;						\
	head->last->_dl_.next = elem;						\
    }										\
    head->last = elem;								\
}										\
398
399
400
401
402
403
404
405

406
407

408
409
410
411
412
413
414
398
399
400
401
402
403
404

405
406

407
408
409
410
411
412
413
414







-
+

-
+







    if (src->first) {								\
	if (dst->first) {							\
	    dst->last->_dl_.next = src->first;					\
	    src->first->_dl_.prev = dst->last;					\
	    dst->last = src->last;						\
	} else {								\
	    *dst = *src;							\
	    dst->first->_dl_.prev = (void *) dst;				\
	    dst->first->_dl_.prev = (PSEntry *) dst;				\
	}									\
	dst->last->_dl_.next = (void *) dst;					\
	dst->last->_dl_.next = (PSEntry *) dst;					\
	LT##_Init(src);								\
    }										\
}										\
										\
__TK_DLIST_UNUSED								\
static void									\
LT##_Remove(struct ElemType *elem)						\
524
525
526
527
528
529
530
531

532
533
534
535

536
537
538
539
540
541
542
543
544
545
546
524
525
526
527
528
529
530

531
532
533
534

535
536
537
538
539
540
541
542
543
544
545
546







-
+



-
+











	next = func(head, p);							\
    }										\
}										\
/* ------------------------------------------------------------------------- */

#define TK_DLIST_FOREACH(var, head)						\
    assert(head);								\
    for (var = head->first ? head->first : (void *) head; var != (void *) head; var = var->_dl_.next)
    for (var = head->first ? head->first : (PSEntry *) head; var != (PSEntry *) head; var = var->_dl_.next)

#define TK_DLIST_FOREACH_REVERSE(var, head)					\
    assert(head);								\
    for (var = head->last ? head->last : (void *) head; var != (void *) head; var = var->_dl_.prev)
    for (var = head->last ? head->last : (PSEntry *) head; var != (PSEntry *) head; var = var->_dl_.prev)

#endif /* TK_DLIST_DEFINED */

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 105
 * End:
 * vi:set ts=8 sw=4:
 */
Changes to generic/tkDecls.h.
1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16
17
18








19
20
21
22
23
24
25
1
2
3
4
5

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33





-
+












+
+
+
+
+
+
+
+







/*
 * 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.
 */

#ifndef _TKDECLS
#define _TKDECLS

#ifdef BUILD_tk
#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLEXPORT
#endif

#if !defined(BUILD_tk)
# define TK_DEPRECATED(msg) EXTERN TCL_DEPRECATED_API(msg)
#elif defined(TK_NO_DEPRECATED)
# define TK_DEPRECATED(msg) MODULE_SCOPE
#else
# define TK_DEPRECATED(msg) EXTERN
#endif

/*
 * WARNING: This file is automatically generated by the tools/genStubs.tcl
 * script.  Any modifications to the function declarations below should be made
 * in the generic/tk.decls script.
 */

91
92
93
94
95
96
97
98

99
100
101
102
103
104
105
99
100
101
102
103
104
105

106
107
108
109
110
111
112
113







-
+







/* 17 */
EXTERN void		Tk_CanvasSetStippleOrigin(Tk_Canvas canvas, GC gc);
/* 18 */
EXTERN int		Tk_CanvasTagsParseProc(ClientData clientData,
				Tcl_Interp *interp, Tk_Window tkwin,
				const char *value, char *widgRec, int offset);
/* 19 */
EXTERN CONST86 char *	Tk_CanvasTagsPrintProc(ClientData clientData,
EXTERN const char *	Tk_CanvasTagsPrintProc(ClientData clientData,
				Tk_Window tkwin, char *widgRec, int offset,
				Tcl_FreeProc **freeProcPtr);
/* 20 */
EXTERN Tk_Window	Tk_CanvasTkwin(Tk_Canvas canvas);
/* 21 */
EXTERN void		Tk_CanvasWindowCoords(Tk_Canvas canvas, double x,
				double y, short *screenXPtr,
129
130
131
132
133
134
135
136

137
138
139
140
141
142
143
137
138
139
140
141
142
143

144
145
146
147
148
149
150
151







-
+







EXTERN int		Tk_ConfigureValue(Tcl_Interp *interp,
				Tk_Window tkwin, const Tk_ConfigSpec *specs,
				char *widgRec, const char *argvName,
				int flags);
/* 29 */
EXTERN int		Tk_ConfigureWidget(Tcl_Interp *interp,
				Tk_Window tkwin, const Tk_ConfigSpec *specs,
				int argc, CONST84 char **argv, char *widgRec,
				int argc, const char **argv, char *widgRec,
				int flags);
/* 30 */
EXTERN void		Tk_ConfigureWindow(Tk_Window tkwin,
				unsigned int valueMask,
				XWindowChanges *valuePtr);
/* 31 */
EXTERN Tk_TextLayout	Tk_ComputeTextLayout(Tk_Font font, const char *str,
211
212
213
214
215
216
217
218

219
220
221
222
223
224
225
219
220
221
222
223
224
225

226
227
228
229
230
231
232
233







-
+







EXTERN void		Tk_DeleteImage(Tcl_Interp *interp, const char *name);
/* 53 */
EXTERN void		Tk_DeleteSelHandler(Tk_Window tkwin, Atom selection,
				Atom target);
/* 54 */
EXTERN void		Tk_DestroyWindow(Tk_Window tkwin);
/* 55 */
EXTERN CONST84_RETURN char * Tk_DisplayName(Tk_Window tkwin);
EXTERN const char *	Tk_DisplayName(Tk_Window tkwin);
/* 56 */
EXTERN int		Tk_DistanceToTextLayout(Tk_TextLayout layout, int x,
				int y);
/* 57 */
EXTERN void		Tk_Draw3DPolygon(Tk_Window tkwin, Drawable drawable,
				Tk_3DBorder border, XPoint *pointPtr,
				int numPoints, int borderWidth,
277
278
279
280
281
282
283

284

285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301

302
303

304
305
306
307
308
309
310
285
286
287
288
289
290
291
292

293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309

310
311

312
313
314
315
316
317
318
319







+
-
+
















-
+

-
+







				char *widgRec, Display *display,
				int needFlags);
/* 75 */
EXTERN void		Tk_FreePixmap(Display *display, Pixmap pixmap);
/* 76 */
EXTERN void		Tk_FreeTextLayout(Tk_TextLayout textLayout);
/* 77 */
TK_DEPRECATED("function does nothing, call can be removed")
EXTERN void		Tk_FreeXId(Display *display, XID xid);
void			Tk_FreeXId(Display *display, XID xid);
/* 78 */
EXTERN GC		Tk_GCForColor(XColor *colorPtr, Drawable drawable);
/* 79 */
EXTERN void		Tk_GeometryRequest(Tk_Window tkwin, int reqWidth,
				int reqHeight);
/* 80 */
EXTERN Tk_3DBorder	Tk_Get3DBorder(Tcl_Interp *interp, Tk_Window tkwin,
				Tk_Uid colorName);
/* 81 */
EXTERN void		Tk_GetAllBindings(Tcl_Interp *interp,
				Tk_BindingTable bindingTable,
				ClientData object);
/* 82 */
EXTERN int		Tk_GetAnchor(Tcl_Interp *interp, const char *str,
				Tk_Anchor *anchorPtr);
/* 83 */
EXTERN CONST84_RETURN char * Tk_GetAtomName(Tk_Window tkwin, Atom atom);
EXTERN const char *	Tk_GetAtomName(Tk_Window tkwin, Atom atom);
/* 84 */
EXTERN CONST84_RETURN char * Tk_GetBinding(Tcl_Interp *interp,
EXTERN const char *	Tk_GetBinding(Tcl_Interp *interp,
				Tk_BindingTable bindingTable,
				ClientData object, const char *eventStr);
/* 85 */
EXTERN Pixmap		Tk_GetBitmap(Tcl_Interp *interp, Tk_Window tkwin,
				const char *str);
/* 86 */
EXTERN Pixmap		Tk_GetBitmapFromData(Tcl_Interp *interp,
342
343
344
345
346
347
348
349

350
351

352
353
354
355
356
357
358
351
352
353
354
355
356
357

358
359

360
361
362
363
364
365
366
367







-
+

-
+







				XGCValues *valuePtr);
/* 97 */
EXTERN Tk_Image		Tk_GetImage(Tcl_Interp *interp, Tk_Window tkwin,
				const char *name,
				Tk_ImageChangedProc *changeProc,
				ClientData clientData);
/* 98 */
EXTERN ClientData	Tk_GetImageMasterData(Tcl_Interp *interp,
EXTERN ClientData	Tk_GetImageModelData(Tcl_Interp *interp,
				const char *name,
				CONST86 Tk_ImageType **typePtrPtr);
				const Tk_ImageType **typePtrPtr);
/* 99 */
EXTERN Tk_ItemType *	Tk_GetItemTypes(void);
/* 100 */
EXTERN int		Tk_GetJoinStyle(Tcl_Interp *interp, const char *str,
				int *joinPtr);
/* 101 */
EXTERN int		Tk_GetJustify(Tcl_Interp *interp, const char *str,
372
373
374
375
376
377
378
379

380
381
382
383
384
385
386
381
382
383
384
385
386
387

388
389
390
391
392
393
394
395







-
+







EXTERN int		Tk_GetRelief(Tcl_Interp *interp, const char *name,
				int *reliefPtr);
/* 107 */
EXTERN void		Tk_GetRootCoords(Tk_Window tkwin, int *xPtr,
				int *yPtr);
/* 108 */
EXTERN int		Tk_GetScrollInfo(Tcl_Interp *interp, int argc,
				CONST84 char **argv, double *dblPtr,
				const char **argv, double *dblPtr,
				int *intPtr);
/* 109 */
EXTERN int		Tk_GetScreenMM(Tcl_Interp *interp, Tk_Window tkwin,
				const char *str, double *doublePtr);
/* 110 */
EXTERN int		Tk_GetSelection(Tcl_Interp *interp, Tk_Window tkwin,
				Atom selection, Atom target,
398
399
400
401
402
403
404
405

406
407
408
409
410
411
412
413
414
415
416
417


418
419
420
421
422
423
424
407
408
409
410
411
412
413

414
415
416
417
418
419
420
421
422
423
424


425
426
427
428
429
430
431
432
433







-
+










-
-
+
+







EXTERN int		Tk_Grab(Tcl_Interp *interp, Tk_Window tkwin,
				int grabGlobal);
/* 115 */
EXTERN void		Tk_HandleEvent(XEvent *eventPtr);
/* 116 */
EXTERN Tk_Window	Tk_IdToWindow(Display *display, Window window);
/* 117 */
EXTERN void		Tk_ImageChanged(Tk_ImageMaster master, int x, int y,
EXTERN void		Tk_ImageChanged(Tk_ImageModel model, int x, int y,
				int width, int height, int imageWidth,
				int imageHeight);
/* 118 */
EXTERN int		Tk_Init(Tcl_Interp *interp);
/* 119 */
EXTERN Atom		Tk_InternAtom(Tk_Window tkwin, const char *name);
/* 120 */
EXTERN int		Tk_IntersectTextLayout(Tk_TextLayout layout, int x,
				int y, int width, int height);
/* 121 */
EXTERN void		Tk_MaintainGeometry(Tk_Window slave,
				Tk_Window master, int x, int y, int width,
EXTERN void		Tk_MaintainGeometry(Tk_Window window,
				Tk_Window container, int x, int y, int width,
				int height);
/* 122 */
EXTERN Tk_Window	Tk_MainWindow(Tcl_Interp *interp);
/* 123 */
EXTERN void		Tk_MakeWindowExist(Tk_Window tkwin);
/* 124 */
EXTERN void		Tk_ManageGeometry(Tk_Window tkwin,
434
435
436
437
438
439
440
441

442
443

444
445

446
447

448
449

450
451

452
453
454

455
456

457
458

459
460

461
462

463
464
465
466
467
468
469
470
471

472
473

474

475
476
477

478

479
480
481
482
483
484
485
486
487
488

489

490
491
492
493
494

495

496
497
498
499
500
501
502
443
444
445
446
447
448
449

450
451

452
453

454
455

456
457

458
459

460

461

462
463

464
465

466
467

468
469

470
471
472
473
474
475
476
477
478

479
480
481
482

483
484
485
486
487

488
489
490
491
492
493
494
495
496
497
498
499

500
501
502
503
504
505
506

507
508
509
510
511
512
513
514







-
+

-
+

-
+

-
+

-
+

-
+
-

-
+

-
+

-
+

-
+

-
+








-
+


+
-
+



+
-
+










+
-
+





+
-
+







EXTERN void		Tk_MoveResizeWindow(Tk_Window tkwin, int x, int y,
				int width, int height);
/* 128 */
EXTERN void		Tk_MoveWindow(Tk_Window tkwin, int x, int y);
/* 129 */
EXTERN void		Tk_MoveToplevelWindow(Tk_Window tkwin, int x, int y);
/* 130 */
EXTERN CONST84_RETURN char * Tk_NameOf3DBorder(Tk_3DBorder border);
EXTERN const char *	Tk_NameOf3DBorder(Tk_3DBorder border);
/* 131 */
EXTERN CONST84_RETURN char * Tk_NameOfAnchor(Tk_Anchor anchor);
EXTERN const char *	Tk_NameOfAnchor(Tk_Anchor anchor);
/* 132 */
EXTERN CONST84_RETURN char * Tk_NameOfBitmap(Display *display, Pixmap bitmap);
EXTERN const char *	Tk_NameOfBitmap(Display *display, Pixmap bitmap);
/* 133 */
EXTERN CONST84_RETURN char * Tk_NameOfCapStyle(int cap);
EXTERN const char *	Tk_NameOfCapStyle(int cap);
/* 134 */
EXTERN CONST84_RETURN char * Tk_NameOfColor(XColor *colorPtr);
EXTERN const char *	Tk_NameOfColor(XColor *colorPtr);
/* 135 */
EXTERN CONST84_RETURN char * Tk_NameOfCursor(Display *display,
EXTERN const char *	Tk_NameOfCursor(Display *display, Tk_Cursor cursor);
				Tk_Cursor cursor);
/* 136 */
EXTERN CONST84_RETURN char * Tk_NameOfFont(Tk_Font font);
EXTERN const char *	Tk_NameOfFont(Tk_Font font);
/* 137 */
EXTERN CONST84_RETURN char * Tk_NameOfImage(Tk_ImageMaster imageMaster);
EXTERN const char *	Tk_NameOfImage(Tk_ImageModel model);
/* 138 */
EXTERN CONST84_RETURN char * Tk_NameOfJoinStyle(int join);
EXTERN const char *	Tk_NameOfJoinStyle(int join);
/* 139 */
EXTERN CONST84_RETURN char * Tk_NameOfJustify(Tk_Justify justify);
EXTERN const char *	Tk_NameOfJustify(Tk_Justify justify);
/* 140 */
EXTERN CONST84_RETURN char * Tk_NameOfRelief(int relief);
EXTERN const char *	Tk_NameOfRelief(int relief);
/* 141 */
EXTERN Tk_Window	Tk_NameToWindow(Tcl_Interp *interp,
				const char *pathName, Tk_Window tkwin);
/* 142 */
EXTERN void		Tk_OwnSelection(Tk_Window tkwin, Atom selection,
				Tk_LostSelProc *proc, ClientData clientData);
/* 143 */
EXTERN int		Tk_ParseArgv(Tcl_Interp *interp, Tk_Window tkwin,
				int *argcPtr, CONST84 char **argv,
				int *argcPtr, const char **argv,
				const Tk_ArgvInfo *argTable, int flags);
/* 144 */
TK_DEPRECATED("function signature changed")
EXTERN void		Tk_PhotoPutBlock_NoComposite(Tk_PhotoHandle handle,
void			Tk_PhotoPutBlock_NoComposite(Tk_PhotoHandle handle,
				Tk_PhotoImageBlock *blockPtr, int x, int y,
				int width, int height);
/* 145 */
TK_DEPRECATED("function signature changed")
EXTERN void		Tk_PhotoPutZoomedBlock_NoComposite(
void			Tk_PhotoPutZoomedBlock_NoComposite(
				Tk_PhotoHandle handle,
				Tk_PhotoImageBlock *blockPtr, int x, int y,
				int width, int height, int zoomX, int zoomY,
				int subsampleX, int subsampleY);
/* 146 */
EXTERN int		Tk_PhotoGetImage(Tk_PhotoHandle handle,
				Tk_PhotoImageBlock *blockPtr);
/* 147 */
EXTERN void		Tk_PhotoBlank(Tk_PhotoHandle handle);
/* 148 */
TK_DEPRECATED("function signature changed")
EXTERN void		Tk_PhotoExpand_Panic(Tk_PhotoHandle handle,
void			Tk_PhotoExpand_Panic(Tk_PhotoHandle handle,
				int width, int height);
/* 149 */
EXTERN void		Tk_PhotoGetSize(Tk_PhotoHandle handle, int *widthPtr,
				int *heightPtr);
/* 150 */
TK_DEPRECATED("function signature changed")
EXTERN void		Tk_PhotoSetSize_Panic(Tk_PhotoHandle handle,
void			Tk_PhotoSetSize_Panic(Tk_PhotoHandle handle,
				int width, int height);
/* 151 */
EXTERN int		Tk_PointToChar(Tk_TextLayout layout, int x, int y);
/* 152 */
EXTERN int		Tk_PostscriptFontName(Tk_Font tkfont,
				Tcl_DString *dsPtr);
/* 153 */
578
579
580
581
582
583
584
585
586


587
588
589
590
591
592
593
590
591
592
593
594
595
596


597
598
599
600
601
602
603
604
605







-
-
+
+







EXTERN void		Tk_UnderlineTextLayout(Display *display,
				Drawable drawable, GC gc,
				Tk_TextLayout layout, int x, int y,
				int underline);
/* 180 */
EXTERN void		Tk_Ungrab(Tk_Window tkwin);
/* 181 */
EXTERN void		Tk_UnmaintainGeometry(Tk_Window slave,
				Tk_Window master);
EXTERN void		Tk_UnmaintainGeometry(Tk_Window window,
				Tk_Window container);
/* 182 */
EXTERN void		Tk_UnmapWindow(Tk_Window tkwin);
/* 183 */
EXTERN void		Tk_UnsetGrid(Tk_Window tkwin);
/* 184 */
EXTERN void		Tk_UpdatePointer(Tk_Window tkwin, int x, int y,
				int state);
616
617
618
619
620
621
622
623

624
625
626
627
628
629
630
628
629
630
631
632
633
634

635
636
637
638
639
640
641
642







-
+







				Tcl_Obj *objPtr);
/* 193 */
EXTERN void		Tk_FreeBitmapFromObj(Tk_Window tkwin,
				Tcl_Obj *objPtr);
/* 194 */
EXTERN void		Tk_FreeColorFromObj(Tk_Window tkwin, Tcl_Obj *objPtr);
/* 195 */
EXTERN void		Tk_FreeConfigOptions(char *recordPtr,
EXTERN void		Tk_FreeConfigOptions(void *recordPtr,
				Tk_OptionTable optionToken, Tk_Window tkwin);
/* 196 */
EXTERN void		Tk_FreeSavedOptions(Tk_SavedOptions *savePtr);
/* 197 */
EXTERN void		Tk_FreeCursorFromObj(Tk_Window tkwin,
				Tcl_Obj *objPtr);
/* 198 */
638
639
640
641
642
643
644
645

646
647
648
649
650

651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670

671
672
673
674
675
676
677
678
679

680
681
682
683
684
685
686
650
651
652
653
654
655
656

657
658
659
660
661

662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681

682
683
684
685
686
687
688
689
690

691
692
693
694
695
696
697
698







-
+




-
+



















-
+








-
+







/* 201 */
EXTERN Pixmap		Tk_GetBitmapFromObj(Tk_Window tkwin, Tcl_Obj *objPtr);
/* 202 */
EXTERN XColor *		Tk_GetColorFromObj(Tk_Window tkwin, Tcl_Obj *objPtr);
/* 203 */
EXTERN Tk_Cursor	Tk_GetCursorFromObj(Tk_Window tkwin, Tcl_Obj *objPtr);
/* 204 */
EXTERN Tcl_Obj *	Tk_GetOptionInfo(Tcl_Interp *interp, char *recordPtr,
EXTERN Tcl_Obj *	Tk_GetOptionInfo(Tcl_Interp *interp, void *recordPtr,
				Tk_OptionTable optionTable, Tcl_Obj *namePtr,
				Tk_Window tkwin);
/* 205 */
EXTERN Tcl_Obj *	Tk_GetOptionValue(Tcl_Interp *interp,
				char *recordPtr, Tk_OptionTable optionTable,
				void *recordPtr, Tk_OptionTable optionTable,
				Tcl_Obj *namePtr, Tk_Window tkwin);
/* 206 */
EXTERN int		Tk_GetJustifyFromObj(Tcl_Interp *interp,
				Tcl_Obj *objPtr, Tk_Justify *justifyPtr);
/* 207 */
EXTERN int		Tk_GetMMFromObj(Tcl_Interp *interp, Tk_Window tkwin,
				Tcl_Obj *objPtr, double *doublePtr);
/* 208 */
EXTERN int		Tk_GetPixelsFromObj(Tcl_Interp *interp,
				Tk_Window tkwin, Tcl_Obj *objPtr,
				int *intPtr);
/* 209 */
EXTERN int		Tk_GetReliefFromObj(Tcl_Interp *interp,
				Tcl_Obj *objPtr, int *resultPtr);
/* 210 */
EXTERN int		Tk_GetScrollInfoObj(Tcl_Interp *interp, int objc,
				Tcl_Obj *const objv[], double *dblPtr,
				int *intPtr);
/* 211 */
EXTERN int		Tk_InitOptions(Tcl_Interp *interp, char *recordPtr,
EXTERN int		Tk_InitOptions(Tcl_Interp *interp, void *recordPtr,
				Tk_OptionTable optionToken, Tk_Window tkwin);
/* 212 */
EXTERN void		Tk_MainEx(int argc, char **argv,
				Tcl_AppInitProc *appInitProc,
				Tcl_Interp *interp);
/* 213 */
EXTERN void		Tk_RestoreSavedOptions(Tk_SavedOptions *savePtr);
/* 214 */
EXTERN int		Tk_SetOptions(Tcl_Interp *interp, char *recordPtr,
EXTERN int		Tk_SetOptions(Tcl_Interp *interp, void *recordPtr,
				Tk_OptionTable optionTable, int objc,
				Tcl_Obj *const objv[], Tk_Window tkwin,
				Tk_SavedOptions *savePtr, int *maskPtr);
/* 215 */
EXTERN void		Tk_InitConsoleChannels(Tcl_Interp *interp);
/* 216 */
EXTERN int		Tk_CreateConsoleWindow(Tcl_Interp *interp);
772
773
774
775
776
777
778

779

780
781
782

783

784
785
786
787
788
789
790
784
785
786
787
788
789
790
791

792
793
794
795
796

797
798
799
800
801
802
803
804







+
-
+



+
-
+







/* 244 */
EXTERN void		Tk_SetMinimumRequestSize(Tk_Window tkwin,
				int minWidth, int minHeight);
/* 245 */
EXTERN void		Tk_SetCaretPos(Tk_Window tkwin, int x, int y,
				int height);
/* 246 */
TK_DEPRECATED("function signature changed")
EXTERN void		Tk_PhotoPutBlock_Panic(Tk_PhotoHandle handle,
void			Tk_PhotoPutBlock_Panic(Tk_PhotoHandle handle,
				Tk_PhotoImageBlock *blockPtr, int x, int y,
				int width, int height, int compRule);
/* 247 */
TK_DEPRECATED("function signature changed")
EXTERN void		Tk_PhotoPutZoomedBlock_Panic(Tk_PhotoHandle handle,
void			Tk_PhotoPutZoomedBlock_Panic(Tk_PhotoHandle handle,
				Tk_PhotoImageBlock *blockPtr, int x, int y,
				int width, int height, int zoomX, int zoomY,
				int subsampleX, int subsampleY, int compRule);
/* 248 */
EXTERN int		Tk_CollapseMotionEvents(Display *display,
				int collapse);
/* 249 */
814
815
816
817
818
819
820
821

822
823
824
825
826

827
828
829
830
831
832

833
834
835
836

837
838
839
840
841
842
843
828
829
830
831
832
833
834

835
836
837
838
839

840
841
842
843
844
845

846
847
848
849

850
851
852
853
854
855
856
857







-
+




-
+





-
+



-
+







/* 259 */
EXTERN void		Tk_FreeStyleFromObj(Tcl_Obj *objPtr);
/* 260 */
EXTERN Tk_StyledElement	 Tk_GetStyledElement(Tk_Style style, int elementId,
				Tk_OptionTable optionTable);
/* 261 */
EXTERN void		Tk_GetElementSize(Tk_Style style,
				Tk_StyledElement element, char *recordPtr,
				Tk_StyledElement element, void *recordPtr,
				Tk_Window tkwin, int width, int height,
				int inner, int *widthPtr, int *heightPtr);
/* 262 */
EXTERN void		Tk_GetElementBox(Tk_Style style,
				Tk_StyledElement element, char *recordPtr,
				Tk_StyledElement element, void *recordPtr,
				Tk_Window tkwin, int x, int y, int width,
				int height, int inner, int *xPtr, int *yPtr,
				int *widthPtr, int *heightPtr);
/* 263 */
EXTERN int		Tk_GetElementBorderWidth(Tk_Style style,
				Tk_StyledElement element, char *recordPtr,
				Tk_StyledElement element, void *recordPtr,
				Tk_Window tkwin);
/* 264 */
EXTERN void		Tk_DrawElement(Tk_Style style,
				Tk_StyledElement element, char *recordPtr,
				Tk_StyledElement element, void *recordPtr,
				Tk_Window tkwin, Drawable d, int x, int y,
				int width, int height, int state);
/* 265 */
EXTERN int		Tk_PhotoExpand(Tcl_Interp *interp,
				Tk_PhotoHandle handle, int width, int height);
/* 266 */
EXTERN int		Tk_PhotoPutBlock(Tcl_Interp *interp,
860
861
862
863
864
865
866















867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







/* 271 */
EXTERN Tcl_Interp *	Tk_Interp(Tk_Window tkwin);
/* 272 */
EXTERN void		Tk_CreateOldImageType(const Tk_ImageType *typePtr);
/* 273 */
EXTERN void		Tk_CreateOldPhotoImageFormat(
				const Tk_PhotoImageFormat *formatPtr);
/* 274 */
EXTERN int		Tk_AlwaysShowSelection(Tk_Window tkwin);
/* 275 */
EXTERN unsigned		Tk_GetButtonMask(unsigned button);
/* 276 */
EXTERN int		Tk_GetDoublePixelsFromObj(Tcl_Interp *interp,
				Tk_Window tkwin, Tcl_Obj *objPtr,
				double *doublePtr);
/* 277 */
EXTERN Tcl_Obj *	Tk_NewWindowObj(Tk_Window tkwin);
/* 278 */
EXTERN void		Tk_SendVirtualEvent(Tk_Window tkwin,
				const char *eventName, Tcl_Obj *detail);
/* 279 */
EXTERN Tcl_Obj *	Tk_FontGetDescription(Tk_Font tkfont);

typedef struct {
    const struct TkPlatStubs *tkPlatStubs;
    const struct TkIntStubs *tkIntStubs;
    const struct TkIntPlatStubs *tkIntPlatStubs;
    const struct TkIntXlibStubs *tkIntXlibStubs;
} TkStubHooks;
891
892
893
894
895
896
897
898

899
900
901
902
903
904
905
906
907
908

909
910
911
912
913
914
915
920
921
922
923
924
925
926

927
928
929
930
931
932
933
934
935
936

937
938
939
940
941
942
943
944







-
+









-
+







    int (*tk_CanvasPsColor) (Tcl_Interp *interp, Tk_Canvas canvas, XColor *colorPtr); /* 12 */
    int (*tk_CanvasPsFont) (Tcl_Interp *interp, Tk_Canvas canvas, Tk_Font font); /* 13 */
    void (*tk_CanvasPsPath) (Tcl_Interp *interp, Tk_Canvas canvas, double *coordPtr, int numPoints); /* 14 */
    int (*tk_CanvasPsStipple) (Tcl_Interp *interp, Tk_Canvas canvas, Pixmap bitmap); /* 15 */
    double (*tk_CanvasPsY) (Tk_Canvas canvas, double y); /* 16 */
    void (*tk_CanvasSetStippleOrigin) (Tk_Canvas canvas, GC gc); /* 17 */
    int (*tk_CanvasTagsParseProc) (ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, int offset); /* 18 */
    CONST86 char * (*tk_CanvasTagsPrintProc) (ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr); /* 19 */
    const char * (*tk_CanvasTagsPrintProc) (ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr); /* 19 */
    Tk_Window (*tk_CanvasTkwin) (Tk_Canvas canvas); /* 20 */
    void (*tk_CanvasWindowCoords) (Tk_Canvas canvas, double x, double y, short *screenXPtr, short *screenYPtr); /* 21 */
    void (*tk_ChangeWindowAttributes) (Tk_Window tkwin, unsigned long valueMask, XSetWindowAttributes *attsPtr); /* 22 */
    int (*tk_CharBbox) (Tk_TextLayout layout, int index, int *xPtr, int *yPtr, int *widthPtr, int *heightPtr); /* 23 */
    void (*tk_ClearSelection) (Tk_Window tkwin, Atom selection); /* 24 */
    int (*tk_ClipboardAppend) (Tcl_Interp *interp, Tk_Window tkwin, Atom target, Atom format, const char *buffer); /* 25 */
    int (*tk_ClipboardClear) (Tcl_Interp *interp, Tk_Window tkwin); /* 26 */
    int (*tk_ConfigureInfo) (Tcl_Interp *interp, Tk_Window tkwin, const Tk_ConfigSpec *specs, char *widgRec, const char *argvName, int flags); /* 27 */
    int (*tk_ConfigureValue) (Tcl_Interp *interp, Tk_Window tkwin, const Tk_ConfigSpec *specs, char *widgRec, const char *argvName, int flags); /* 28 */
    int (*tk_ConfigureWidget) (Tcl_Interp *interp, Tk_Window tkwin, const Tk_ConfigSpec *specs, int argc, CONST84 char **argv, char *widgRec, int flags); /* 29 */
    int (*tk_ConfigureWidget) (Tcl_Interp *interp, Tk_Window tkwin, const Tk_ConfigSpec *specs, int argc, const char **argv, char *widgRec, int flags); /* 29 */
    void (*tk_ConfigureWindow) (Tk_Window tkwin, unsigned int valueMask, XWindowChanges *valuePtr); /* 30 */
    Tk_TextLayout (*tk_ComputeTextLayout) (Tk_Font font, const char *str, int numChars, int wrapLength, Tk_Justify justify, int flags, int *widthPtr, int *heightPtr); /* 31 */
    Tk_Window (*tk_CoordsToWindow) (int rootX, int rootY, Tk_Window tkwin); /* 32 */
    unsigned long (*tk_CreateBinding) (Tcl_Interp *interp, Tk_BindingTable bindingTable, ClientData object, const char *eventStr, const char *script, int append); /* 33 */
    Tk_BindingTable (*tk_CreateBindingTable) (Tcl_Interp *interp); /* 34 */
    Tk_ErrorHandler (*tk_CreateErrorHandler) (Display *display, int errNum, int request, int minorCode, Tk_ErrorProc *errorProc, ClientData clientData); /* 35 */
    void (*tk_CreateEventHandler) (Tk_Window token, unsigned long mask, Tk_EventProc *proc, ClientData clientData); /* 36 */
927
928
929
930
931
932
933
934

935
936
937
938
939
940
941
956
957
958
959
960
961
962

963
964
965
966
967
968
969
970







-
+







    void (*tk_DeleteBindingTable) (Tk_BindingTable bindingTable); /* 48 */
    void (*tk_DeleteErrorHandler) (Tk_ErrorHandler handler); /* 49 */
    void (*tk_DeleteEventHandler) (Tk_Window token, unsigned long mask, Tk_EventProc *proc, ClientData clientData); /* 50 */
    void (*tk_DeleteGenericHandler) (Tk_GenericProc *proc, ClientData clientData); /* 51 */
    void (*tk_DeleteImage) (Tcl_Interp *interp, const char *name); /* 52 */
    void (*tk_DeleteSelHandler) (Tk_Window tkwin, Atom selection, Atom target); /* 53 */
    void (*tk_DestroyWindow) (Tk_Window tkwin); /* 54 */
    CONST84_RETURN char * (*tk_DisplayName) (Tk_Window tkwin); /* 55 */
    const char * (*tk_DisplayName) (Tk_Window tkwin); /* 55 */
    int (*tk_DistanceToTextLayout) (Tk_TextLayout layout, int x, int y); /* 56 */
    void (*tk_Draw3DPolygon) (Tk_Window tkwin, Drawable drawable, Tk_3DBorder border, XPoint *pointPtr, int numPoints, int borderWidth, int leftRelief); /* 57 */
    void (*tk_Draw3DRectangle) (Tk_Window tkwin, Drawable drawable, Tk_3DBorder border, int x, int y, int width, int height, int borderWidth, int relief); /* 58 */
    void (*tk_DrawChars) (Display *display, Drawable drawable, GC gc, Tk_Font tkfont, const char *source, int numBytes, int x, int y); /* 59 */
    void (*tk_DrawFocusHighlight) (Tk_Window tkwin, GC gc, int width, Drawable drawable); /* 60 */
    void (*tk_DrawTextLayout) (Display *display, Drawable drawable, GC gc, Tk_TextLayout layout, int x, int y, int firstChar, int lastChar); /* 61 */
    void (*tk_Fill3DPolygon) (Tk_Window tkwin, Drawable drawable, Tk_3DBorder border, XPoint *pointPtr, int numPoints, int borderWidth, int leftRelief); /* 62 */
949
950
951
952
953
954
955
956

957
958
959
960
961
962
963


964
965
966
967
968
969
970
971
972
973
974
975
976
977

978
979
980
981
982
983
984
985
986
987

988
989
990
991
992
993
994
995
996

997
998
999
1000

1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019











1020
1021
1022
1023
1024



1025
1026
1027

1028
1029

1030
1031
1032
1033
1034
1035
1036
978
979
980
981
982
983
984

985
986
987
988
989
990


991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005

1006
1007
1008
1009
1010
1011
1012
1013
1014
1015

1016
1017
1018
1019
1020
1021
1022
1023
1024

1025
1026
1027
1028

1029
1030
1031
1032
1033
1034
1035
1036
1037











1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050



1051
1052
1053
1054
1055

1056
1057

1058
1059
1060
1061
1062
1063
1064
1065







-
+





-
-
+
+













-
+









-
+








-
+



-
+








-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+


-
-
-
+
+
+


-
+

-
+







    void (*tk_FreeCursor) (Display *display, Tk_Cursor cursor); /* 70 */
    void (*tk_FreeFont) (Tk_Font f); /* 71 */
    void (*tk_FreeGC) (Display *display, GC gc); /* 72 */
    void (*tk_FreeImage) (Tk_Image image); /* 73 */
    void (*tk_FreeOptions) (const Tk_ConfigSpec *specs, char *widgRec, Display *display, int needFlags); /* 74 */
    void (*tk_FreePixmap) (Display *display, Pixmap pixmap); /* 75 */
    void (*tk_FreeTextLayout) (Tk_TextLayout textLayout); /* 76 */
    void (*tk_FreeXId) (Display *display, XID xid); /* 77 */
    TCL_DEPRECATED_API("function does nothing, call can be removed") void (*tk_FreeXId) (Display *display, XID xid); /* 77 */
    GC (*tk_GCForColor) (XColor *colorPtr, Drawable drawable); /* 78 */
    void (*tk_GeometryRequest) (Tk_Window tkwin, int reqWidth, int reqHeight); /* 79 */
    Tk_3DBorder (*tk_Get3DBorder) (Tcl_Interp *interp, Tk_Window tkwin, Tk_Uid colorName); /* 80 */
    void (*tk_GetAllBindings) (Tcl_Interp *interp, Tk_BindingTable bindingTable, ClientData object); /* 81 */
    int (*tk_GetAnchor) (Tcl_Interp *interp, const char *str, Tk_Anchor *anchorPtr); /* 82 */
    CONST84_RETURN char * (*tk_GetAtomName) (Tk_Window tkwin, Atom atom); /* 83 */
    CONST84_RETURN char * (*tk_GetBinding) (Tcl_Interp *interp, Tk_BindingTable bindingTable, ClientData object, const char *eventStr); /* 84 */
    const char * (*tk_GetAtomName) (Tk_Window tkwin, Atom atom); /* 83 */
    const char * (*tk_GetBinding) (Tcl_Interp *interp, Tk_BindingTable bindingTable, ClientData object, const char *eventStr); /* 84 */
    Pixmap (*tk_GetBitmap) (Tcl_Interp *interp, Tk_Window tkwin, const char *str); /* 85 */
    Pixmap (*tk_GetBitmapFromData) (Tcl_Interp *interp, Tk_Window tkwin, const void *source, int width, int height); /* 86 */
    int (*tk_GetCapStyle) (Tcl_Interp *interp, const char *str, int *capPtr); /* 87 */
    XColor * (*tk_GetColor) (Tcl_Interp *interp, Tk_Window tkwin, Tk_Uid name); /* 88 */
    XColor * (*tk_GetColorByValue) (Tk_Window tkwin, XColor *colorPtr); /* 89 */
    Colormap (*tk_GetColormap) (Tcl_Interp *interp, Tk_Window tkwin, const char *str); /* 90 */
    Tk_Cursor (*tk_GetCursor) (Tcl_Interp *interp, Tk_Window tkwin, Tk_Uid str); /* 91 */
    Tk_Cursor (*tk_GetCursorFromData) (Tcl_Interp *interp, Tk_Window tkwin, const char *source, const char *mask, int width, int height, int xHot, int yHot, Tk_Uid fg, Tk_Uid bg); /* 92 */
    Tk_Font (*tk_GetFont) (Tcl_Interp *interp, Tk_Window tkwin, const char *str); /* 93 */
    Tk_Font (*tk_GetFontFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 94 */
    void (*tk_GetFontMetrics) (Tk_Font font, Tk_FontMetrics *fmPtr); /* 95 */
    GC (*tk_GetGC) (Tk_Window tkwin, unsigned long valueMask, XGCValues *valuePtr); /* 96 */
    Tk_Image (*tk_GetImage) (Tcl_Interp *interp, Tk_Window tkwin, const char *name, Tk_ImageChangedProc *changeProc, ClientData clientData); /* 97 */
    ClientData (*tk_GetImageMasterData) (Tcl_Interp *interp, const char *name, CONST86 Tk_ImageType **typePtrPtr); /* 98 */
    ClientData (*tk_GetImageModelData) (Tcl_Interp *interp, const char *name, const Tk_ImageType **typePtrPtr); /* 98 */
    Tk_ItemType * (*tk_GetItemTypes) (void); /* 99 */
    int (*tk_GetJoinStyle) (Tcl_Interp *interp, const char *str, int *joinPtr); /* 100 */
    int (*tk_GetJustify) (Tcl_Interp *interp, const char *str, Tk_Justify *justifyPtr); /* 101 */
    int (*tk_GetNumMainWindows) (void); /* 102 */
    Tk_Uid (*tk_GetOption) (Tk_Window tkwin, const char *name, const char *className); /* 103 */
    int (*tk_GetPixels) (Tcl_Interp *interp, Tk_Window tkwin, const char *str, int *intPtr); /* 104 */
    Pixmap (*tk_GetPixmap) (Display *display, Drawable d, int width, int height, int depth); /* 105 */
    int (*tk_GetRelief) (Tcl_Interp *interp, const char *name, int *reliefPtr); /* 106 */
    void (*tk_GetRootCoords) (Tk_Window tkwin, int *xPtr, int *yPtr); /* 107 */
    int (*tk_GetScrollInfo) (Tcl_Interp *interp, int argc, CONST84 char **argv, double *dblPtr, int *intPtr); /* 108 */
    int (*tk_GetScrollInfo) (Tcl_Interp *interp, int argc, const char **argv, double *dblPtr, int *intPtr); /* 108 */
    int (*tk_GetScreenMM) (Tcl_Interp *interp, Tk_Window tkwin, const char *str, double *doublePtr); /* 109 */
    int (*tk_GetSelection) (Tcl_Interp *interp, Tk_Window tkwin, Atom selection, Atom target, Tk_GetSelProc *proc, ClientData clientData); /* 110 */
    Tk_Uid (*tk_GetUid) (const char *str); /* 111 */
    Visual * (*tk_GetVisual) (Tcl_Interp *interp, Tk_Window tkwin, const char *str, int *depthPtr, Colormap *colormapPtr); /* 112 */
    void (*tk_GetVRootGeometry) (Tk_Window tkwin, int *xPtr, int *yPtr, int *widthPtr, int *heightPtr); /* 113 */
    int (*tk_Grab) (Tcl_Interp *interp, Tk_Window tkwin, int grabGlobal); /* 114 */
    void (*tk_HandleEvent) (XEvent *eventPtr); /* 115 */
    Tk_Window (*tk_IdToWindow) (Display *display, Window window); /* 116 */
    void (*tk_ImageChanged) (Tk_ImageMaster master, int x, int y, int width, int height, int imageWidth, int imageHeight); /* 117 */
    void (*tk_ImageChanged) (Tk_ImageModel model, int x, int y, int width, int height, int imageWidth, int imageHeight); /* 117 */
    int (*tk_Init) (Tcl_Interp *interp); /* 118 */
    Atom (*tk_InternAtom) (Tk_Window tkwin, const char *name); /* 119 */
    int (*tk_IntersectTextLayout) (Tk_TextLayout layout, int x, int y, int width, int height); /* 120 */
    void (*tk_MaintainGeometry) (Tk_Window slave, Tk_Window master, int x, int y, int width, int height); /* 121 */
    void (*tk_MaintainGeometry) (Tk_Window window, Tk_Window container, int x, int y, int width, int height); /* 121 */
    Tk_Window (*tk_MainWindow) (Tcl_Interp *interp); /* 122 */
    void (*tk_MakeWindowExist) (Tk_Window tkwin); /* 123 */
    void (*tk_ManageGeometry) (Tk_Window tkwin, const Tk_GeomMgr *mgrPtr, ClientData clientData); /* 124 */
    void (*tk_MapWindow) (Tk_Window tkwin); /* 125 */
    int (*tk_MeasureChars) (Tk_Font tkfont, const char *source, int numBytes, int maxPixels, int flags, int *lengthPtr); /* 126 */
    void (*tk_MoveResizeWindow) (Tk_Window tkwin, int x, int y, int width, int height); /* 127 */
    void (*tk_MoveWindow) (Tk_Window tkwin, int x, int y); /* 128 */
    void (*tk_MoveToplevelWindow) (Tk_Window tkwin, int x, int y); /* 129 */
    CONST84_RETURN char * (*tk_NameOf3DBorder) (Tk_3DBorder border); /* 130 */
    CONST84_RETURN char * (*tk_NameOfAnchor) (Tk_Anchor anchor); /* 131 */
    CONST84_RETURN char * (*tk_NameOfBitmap) (Display *display, Pixmap bitmap); /* 132 */
    CONST84_RETURN char * (*tk_NameOfCapStyle) (int cap); /* 133 */
    CONST84_RETURN char * (*tk_NameOfColor) (XColor *colorPtr); /* 134 */
    CONST84_RETURN char * (*tk_NameOfCursor) (Display *display, Tk_Cursor cursor); /* 135 */
    CONST84_RETURN char * (*tk_NameOfFont) (Tk_Font font); /* 136 */
    CONST84_RETURN char * (*tk_NameOfImage) (Tk_ImageMaster imageMaster); /* 137 */
    CONST84_RETURN char * (*tk_NameOfJoinStyle) (int join); /* 138 */
    CONST84_RETURN char * (*tk_NameOfJustify) (Tk_Justify justify); /* 139 */
    CONST84_RETURN char * (*tk_NameOfRelief) (int relief); /* 140 */
    const char * (*tk_NameOf3DBorder) (Tk_3DBorder border); /* 130 */
    const char * (*tk_NameOfAnchor) (Tk_Anchor anchor); /* 131 */
    const char * (*tk_NameOfBitmap) (Display *display, Pixmap bitmap); /* 132 */
    const char * (*tk_NameOfCapStyle) (int cap); /* 133 */
    const char * (*tk_NameOfColor) (XColor *colorPtr); /* 134 */
    const char * (*tk_NameOfCursor) (Display *display, Tk_Cursor cursor); /* 135 */
    const char * (*tk_NameOfFont) (Tk_Font font); /* 136 */
    const char * (*tk_NameOfImage) (Tk_ImageModel model); /* 137 */
    const char * (*tk_NameOfJoinStyle) (int join); /* 138 */
    const char * (*tk_NameOfJustify) (Tk_Justify justify); /* 139 */
    const char * (*tk_NameOfRelief) (int relief); /* 140 */
    Tk_Window (*tk_NameToWindow) (Tcl_Interp *interp, const char *pathName, Tk_Window tkwin); /* 141 */
    void (*tk_OwnSelection) (Tk_Window tkwin, Atom selection, Tk_LostSelProc *proc, ClientData clientData); /* 142 */
    int (*tk_ParseArgv) (Tcl_Interp *interp, Tk_Window tkwin, int *argcPtr, CONST84 char **argv, const Tk_ArgvInfo *argTable, int flags); /* 143 */
    void (*tk_PhotoPutBlock_NoComposite) (Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height); /* 144 */
    void (*tk_PhotoPutZoomedBlock_NoComposite) (Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height, int zoomX, int zoomY, int subsampleX, int subsampleY); /* 145 */
    int (*tk_ParseArgv) (Tcl_Interp *interp, Tk_Window tkwin, int *argcPtr, const char **argv, const Tk_ArgvInfo *argTable, int flags); /* 143 */
    TCL_DEPRECATED_API("function signature changed") void (*tk_PhotoPutBlock_NoComposite) (Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height); /* 144 */
    TCL_DEPRECATED_API("function signature changed") void (*tk_PhotoPutZoomedBlock_NoComposite) (Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height, int zoomX, int zoomY, int subsampleX, int subsampleY); /* 145 */
    int (*tk_PhotoGetImage) (Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr); /* 146 */
    void (*tk_PhotoBlank) (Tk_PhotoHandle handle); /* 147 */
    void (*tk_PhotoExpand_Panic) (Tk_PhotoHandle handle, int width, int height); /* 148 */
    TCL_DEPRECATED_API("function signature changed") void (*tk_PhotoExpand_Panic) (Tk_PhotoHandle handle, int width, int height); /* 148 */
    void (*tk_PhotoGetSize) (Tk_PhotoHandle handle, int *widthPtr, int *heightPtr); /* 149 */
    void (*tk_PhotoSetSize_Panic) (Tk_PhotoHandle handle, int width, int height); /* 150 */
    TCL_DEPRECATED_API("function signature changed") void (*tk_PhotoSetSize_Panic) (Tk_PhotoHandle handle, int width, int height); /* 150 */
    int (*tk_PointToChar) (Tk_TextLayout layout, int x, int y); /* 151 */
    int (*tk_PostscriptFontName) (Tk_Font tkfont, Tcl_DString *dsPtr); /* 152 */
    void (*tk_PreserveColormap) (Display *display, Colormap colormap); /* 153 */
    void (*tk_QueueWindowEvent) (XEvent *eventPtr, Tcl_QueuePosition position); /* 154 */
    void (*tk_RedrawImage) (Tk_Image image, int imageX, int imageY, int width, int height, Drawable drawable, int drawableX, int drawableY); /* 155 */
    void (*tk_ResizeWindow) (Tk_Window tkwin, int width, int height); /* 156 */
    int (*tk_RestackWindow) (Tk_Window tkwin, int aboveBelow, Tk_Window other); /* 157 */
1053
1054
1055
1056
1057
1058
1059
1060

1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074

1075
1076
1077
1078
1079
1080
1081
1082
1083
1084


1085
1086
1087
1088
1089
1090
1091


1092
1093

1094
1095
1096
1097
1098
1099
1100
1082
1083
1084
1085
1086
1087
1088

1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102

1103
1104
1105
1106
1107
1108
1109
1110
1111


1112
1113
1114
1115
1116
1117
1118


1119
1120
1121

1122
1123
1124
1125
1126
1127
1128
1129







-
+













-
+








-
-
+
+





-
-
+
+

-
+







    int (*tk_StrictMotif) (Tk_Window tkwin); /* 174 */
    void (*tk_TextLayoutToPostscript) (Tcl_Interp *interp, Tk_TextLayout layout); /* 175 */
    int (*tk_TextWidth) (Tk_Font font, const char *str, int numBytes); /* 176 */
    void (*tk_UndefineCursor) (Tk_Window window); /* 177 */
    void (*tk_UnderlineChars) (Display *display, Drawable drawable, GC gc, Tk_Font tkfont, const char *source, int x, int y, int firstByte, int lastByte); /* 178 */
    void (*tk_UnderlineTextLayout) (Display *display, Drawable drawable, GC gc, Tk_TextLayout layout, int x, int y, int underline); /* 179 */
    void (*tk_Ungrab) (Tk_Window tkwin); /* 180 */
    void (*tk_UnmaintainGeometry) (Tk_Window slave, Tk_Window master); /* 181 */
    void (*tk_UnmaintainGeometry) (Tk_Window window, Tk_Window container); /* 181 */
    void (*tk_UnmapWindow) (Tk_Window tkwin); /* 182 */
    void (*tk_UnsetGrid) (Tk_Window tkwin); /* 183 */
    void (*tk_UpdatePointer) (Tk_Window tkwin, int x, int y, int state); /* 184 */
    Pixmap (*tk_AllocBitmapFromObj) (Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr); /* 185 */
    Tk_3DBorder (*tk_Alloc3DBorderFromObj) (Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr); /* 186 */
    XColor * (*tk_AllocColorFromObj) (Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr); /* 187 */
    Tk_Cursor (*tk_AllocCursorFromObj) (Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr); /* 188 */
    Tk_Font (*tk_AllocFontFromObj) (Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr); /* 189 */
    Tk_OptionTable (*tk_CreateOptionTable) (Tcl_Interp *interp, const Tk_OptionSpec *templatePtr); /* 190 */
    void (*tk_DeleteOptionTable) (Tk_OptionTable optionTable); /* 191 */
    void (*tk_Free3DBorderFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 192 */
    void (*tk_FreeBitmapFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 193 */
    void (*tk_FreeColorFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 194 */
    void (*tk_FreeConfigOptions) (char *recordPtr, Tk_OptionTable optionToken, Tk_Window tkwin); /* 195 */
    void (*tk_FreeConfigOptions) (void *recordPtr, Tk_OptionTable optionToken, Tk_Window tkwin); /* 195 */
    void (*tk_FreeSavedOptions) (Tk_SavedOptions *savePtr); /* 196 */
    void (*tk_FreeCursorFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 197 */
    void (*tk_FreeFontFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 198 */
    Tk_3DBorder (*tk_Get3DBorderFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 199 */
    int (*tk_GetAnchorFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Tk_Anchor *anchorPtr); /* 200 */
    Pixmap (*tk_GetBitmapFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 201 */
    XColor * (*tk_GetColorFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 202 */
    Tk_Cursor (*tk_GetCursorFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 203 */
    Tcl_Obj * (*tk_GetOptionInfo) (Tcl_Interp *interp, char *recordPtr, Tk_OptionTable optionTable, Tcl_Obj *namePtr, Tk_Window tkwin); /* 204 */
    Tcl_Obj * (*tk_GetOptionValue) (Tcl_Interp *interp, char *recordPtr, Tk_OptionTable optionTable, Tcl_Obj *namePtr, Tk_Window tkwin); /* 205 */
    Tcl_Obj * (*tk_GetOptionInfo) (Tcl_Interp *interp, void *recordPtr, Tk_OptionTable optionTable, Tcl_Obj *namePtr, Tk_Window tkwin); /* 204 */
    Tcl_Obj * (*tk_GetOptionValue) (Tcl_Interp *interp, void *recordPtr, Tk_OptionTable optionTable, Tcl_Obj *namePtr, Tk_Window tkwin); /* 205 */
    int (*tk_GetJustifyFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Tk_Justify *justifyPtr); /* 206 */
    int (*tk_GetMMFromObj) (Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr, double *doublePtr); /* 207 */
    int (*tk_GetPixelsFromObj) (Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr, int *intPtr); /* 208 */
    int (*tk_GetReliefFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int *resultPtr); /* 209 */
    int (*tk_GetScrollInfoObj) (Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], double *dblPtr, int *intPtr); /* 210 */
    int (*tk_InitOptions) (Tcl_Interp *interp, char *recordPtr, Tk_OptionTable optionToken, Tk_Window tkwin); /* 211 */
    void (*tk_MainEx) (int argc, char **argv, Tcl_AppInitProc *appInitProc, Tcl_Interp *interp); /* 212 */
    int (*tk_InitOptions) (Tcl_Interp *interp, void *recordPtr, Tk_OptionTable optionToken, Tk_Window tkwin); /* 211 */
    TCL_DEPRECATED_API("Don't use this function in a stub-enabled extension") void (*tk_MainEx) (int argc, char **argv, Tcl_AppInitProc *appInitProc, Tcl_Interp *interp); /* 212 */
    void (*tk_RestoreSavedOptions) (Tk_SavedOptions *savePtr); /* 213 */
    int (*tk_SetOptions) (Tcl_Interp *interp, char *recordPtr, Tk_OptionTable optionTable, int objc, Tcl_Obj *const objv[], Tk_Window tkwin, Tk_SavedOptions *savePtr, int *maskPtr); /* 214 */
    int (*tk_SetOptions) (Tcl_Interp *interp, void *recordPtr, Tk_OptionTable optionTable, int objc, Tcl_Obj *const objv[], Tk_Window tkwin, Tk_SavedOptions *savePtr, int *maskPtr); /* 214 */
    void (*tk_InitConsoleChannels) (Tcl_Interp *interp); /* 215 */
    int (*tk_CreateConsoleWindow) (Tcl_Interp *interp); /* 216 */
    void (*tk_CreateSmoothMethod) (Tcl_Interp *interp, const Tk_SmoothMethod *method); /* 217 */
    void (*reserved218)(void);
    void (*reserved219)(void);
    int (*tk_GetDash) (Tcl_Interp *interp, const char *value, Tk_Dash *dash); /* 220 */
    void (*tk_CreateOutline) (Tk_Outline *outline); /* 221 */
1118
1119
1120
1121
1122
1123
1124
1125
1126


1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143




1144
1145
1146
1147
1148
1149
1150
1151
1152






1153
1154
1155
1156
1157
1158
1159
1147
1148
1149
1150
1151
1152
1153


1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168




1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194







-
-
+
+













-
-
-
-
+
+
+
+









+
+
+
+
+
+







    void (*tk_CreateClientMessageHandler) (Tk_ClientMessageProc *proc); /* 239 */
    void (*tk_DeleteClientMessageHandler) (Tk_ClientMessageProc *proc); /* 240 */
    Tk_Window (*tk_CreateAnonymousWindow) (Tcl_Interp *interp, Tk_Window parent, const char *screenName); /* 241 */
    void (*tk_SetClassProcs) (Tk_Window tkwin, const Tk_ClassProcs *procs, ClientData instanceData); /* 242 */
    void (*tk_SetInternalBorderEx) (Tk_Window tkwin, int left, int right, int top, int bottom); /* 243 */
    void (*tk_SetMinimumRequestSize) (Tk_Window tkwin, int minWidth, int minHeight); /* 244 */
    void (*tk_SetCaretPos) (Tk_Window tkwin, int x, int y, int height); /* 245 */
    void (*tk_PhotoPutBlock_Panic) (Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height, int compRule); /* 246 */
    void (*tk_PhotoPutZoomedBlock_Panic) (Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height, int zoomX, int zoomY, int subsampleX, int subsampleY, int compRule); /* 247 */
    TCL_DEPRECATED_API("function signature changed") void (*tk_PhotoPutBlock_Panic) (Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height, int compRule); /* 246 */
    TCL_DEPRECATED_API("function signature changed") void (*tk_PhotoPutZoomedBlock_Panic) (Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height, int zoomX, int zoomY, int subsampleX, int subsampleY, int compRule); /* 247 */
    int (*tk_CollapseMotionEvents) (Display *display, int collapse); /* 248 */
    Tk_StyleEngine (*tk_RegisterStyleEngine) (const char *name, Tk_StyleEngine parent); /* 249 */
    Tk_StyleEngine (*tk_GetStyleEngine) (const char *name); /* 250 */
    int (*tk_RegisterStyledElement) (Tk_StyleEngine engine, Tk_ElementSpec *templatePtr); /* 251 */
    int (*tk_GetElementId) (const char *name); /* 252 */
    Tk_Style (*tk_CreateStyle) (const char *name, Tk_StyleEngine engine, ClientData clientData); /* 253 */
    Tk_Style (*tk_GetStyle) (Tcl_Interp *interp, const char *name); /* 254 */
    void (*tk_FreeStyle) (Tk_Style style); /* 255 */
    const char * (*tk_NameOfStyle) (Tk_Style style); /* 256 */
    Tk_Style (*tk_AllocStyleFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr); /* 257 */
    Tk_Style (*tk_GetStyleFromObj) (Tcl_Obj *objPtr); /* 258 */
    void (*tk_FreeStyleFromObj) (Tcl_Obj *objPtr); /* 259 */
    Tk_StyledElement (*tk_GetStyledElement) (Tk_Style style, int elementId, Tk_OptionTable optionTable); /* 260 */
    void (*tk_GetElementSize) (Tk_Style style, Tk_StyledElement element, char *recordPtr, Tk_Window tkwin, int width, int height, int inner, int *widthPtr, int *heightPtr); /* 261 */
    void (*tk_GetElementBox) (Tk_Style style, Tk_StyledElement element, char *recordPtr, Tk_Window tkwin, int x, int y, int width, int height, int inner, int *xPtr, int *yPtr, int *widthPtr, int *heightPtr); /* 262 */
    int (*tk_GetElementBorderWidth) (Tk_Style style, Tk_StyledElement element, char *recordPtr, Tk_Window tkwin); /* 263 */
    void (*tk_DrawElement) (Tk_Style style, Tk_StyledElement element, char *recordPtr, Tk_Window tkwin, Drawable d, int x, int y, int width, int height, int state); /* 264 */
    void (*tk_GetElementSize) (Tk_Style style, Tk_StyledElement element, void *recordPtr, Tk_Window tkwin, int width, int height, int inner, int *widthPtr, int *heightPtr); /* 261 */
    void (*tk_GetElementBox) (Tk_Style style, Tk_StyledElement element, void *recordPtr, Tk_Window tkwin, int x, int y, int width, int height, int inner, int *xPtr, int *yPtr, int *widthPtr, int *heightPtr); /* 262 */
    int (*tk_GetElementBorderWidth) (Tk_Style style, Tk_StyledElement element, void *recordPtr, Tk_Window tkwin); /* 263 */
    void (*tk_DrawElement) (Tk_Style style, Tk_StyledElement element, void *recordPtr, Tk_Window tkwin, Drawable d, int x, int y, int width, int height, int state); /* 264 */
    int (*tk_PhotoExpand) (Tcl_Interp *interp, Tk_PhotoHandle handle, int width, int height); /* 265 */
    int (*tk_PhotoPutBlock) (Tcl_Interp *interp, Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height, int compRule); /* 266 */
    int (*tk_PhotoPutZoomedBlock) (Tcl_Interp *interp, Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height, int zoomX, int zoomY, int subsampleX, int subsampleY, int compRule); /* 267 */
    int (*tk_PhotoSetSize) (Tcl_Interp *interp, Tk_PhotoHandle handle, int width, int height); /* 268 */
    long (*tk_GetUserInactiveTime) (Display *dpy); /* 269 */
    void (*tk_ResetUserInactiveTime) (Display *dpy); /* 270 */
    Tcl_Interp * (*tk_Interp) (Tk_Window tkwin); /* 271 */
    void (*tk_CreateOldImageType) (const Tk_ImageType *typePtr); /* 272 */
    void (*tk_CreateOldPhotoImageFormat) (const Tk_PhotoImageFormat *formatPtr); /* 273 */
    int (*tk_AlwaysShowSelection) (Tk_Window tkwin); /* 274 */
    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 */
} TkStubs;

extern const TkStubs *tkStubsPtr;

#ifdef __cplusplus
}
#endif
1356
1357
1358
1359
1360
1361
1362
1363
1364


1365
1366
1367
1368
1369
1370
1371
1391
1392
1393
1394
1395
1396
1397


1398
1399
1400
1401
1402
1403
1404
1405
1406







-
-
+
+







	(tkStubsPtr->tk_GetFontFromObj) /* 94 */
#define Tk_GetFontMetrics \
	(tkStubsPtr->tk_GetFontMetrics) /* 95 */
#define Tk_GetGC \
	(tkStubsPtr->tk_GetGC) /* 96 */
#define Tk_GetImage \
	(tkStubsPtr->tk_GetImage) /* 97 */
#define Tk_GetImageMasterData \
	(tkStubsPtr->tk_GetImageMasterData) /* 98 */
#define Tk_GetImageModelData \
	(tkStubsPtr->tk_GetImageModelData) /* 98 */
#define Tk_GetItemTypes \
	(tkStubsPtr->tk_GetItemTypes) /* 99 */
#define Tk_GetJoinStyle \
	(tkStubsPtr->tk_GetJoinStyle) /* 100 */
#define Tk_GetJustify \
	(tkStubsPtr->tk_GetJustify) /* 101 */
#define Tk_GetNumMainWindows \
1706
1707
1708
1709
1710
1711
1712












1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723








1724
1725
1726
1727
1728
1729











1730
1731
1732


1733
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801







+
+
+
+
+
+
+
+
+
+
+
+











+
+
+
+
+
+
+
+






+
+
+
+
+
+
+
+
+
+
+



+
+

	(tkStubsPtr->tk_ResetUserInactiveTime) /* 270 */
#define Tk_Interp \
	(tkStubsPtr->tk_Interp) /* 271 */
#define Tk_CreateOldImageType \
	(tkStubsPtr->tk_CreateOldImageType) /* 272 */
#define Tk_CreateOldPhotoImageFormat \
	(tkStubsPtr->tk_CreateOldPhotoImageFormat) /* 273 */
#define Tk_AlwaysShowSelection \
	(tkStubsPtr->tk_AlwaysShowSelection) /* 274 */
#define Tk_GetButtonMask \
	(tkStubsPtr->tk_GetButtonMask) /* 275 */
#define Tk_GetDoublePixelsFromObj \
	(tkStubsPtr->tk_GetDoublePixelsFromObj) /* 276 */
#define Tk_NewWindowObj \
	(tkStubsPtr->tk_NewWindowObj) /* 277 */
#define Tk_SendVirtualEvent \
	(tkStubsPtr->tk_SendVirtualEvent) /* 278 */
#define Tk_FontGetDescription \
	(tkStubsPtr->tk_FontGetDescription) /* 279 */

#endif /* defined(USE_TK_STUBS) */

/* !END!: Do not edit above this line. */

/* Functions that don't belong in the stub table */
#undef Tk_MainEx
#undef Tk_Init
#undef Tk_SafeInit
#undef Tk_CreateConsoleWindow

#undef Tk_FreeXId
#define Tk_FreeXId(display,xid)
#undef Tk_GetStyleFromObj
#undef Tk_FreeStyleFromObj
#define Tk_GetStyleFromObj(obj) Tk_AllocStyleFromObj(NULL, obj)
#define Tk_FreeStyleFromObj(obj) /* no-op */
#define Tk_GetImageMasterData Tk_GetImageModelData

#if defined(_WIN32) && defined(UNICODE)
#   define Tk_MainEx Tk_MainExW
    EXTERN void Tk_MainExW(int argc, wchar_t **argv,
	    Tcl_AppInitProc *appInitProc, Tcl_Interp *interp);
#endif


#if defined(TK_NO_DEPRECATED) || TCL_MAJOR_VERSION > 8
#undef Tk_PhotoPutBlock_NoComposite
#undef Tk_PhotoPutZoomedBlock_NoComposite
#undef Tk_PhotoExpand_Panic
#undef Tk_PhotoPutBlock_Panic
#undef Tk_PhotoPutZoomedBlock_Panic
#undef Tk_PhotoSetSize_Panic
#undef Tk_CreateOldPhotoImageFormat
#endif /* TK_NO_DEPRECATED */

#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLIMPORT

#undef TkUnusedStubEntry

#endif /* _TKDECLS */
Changes to generic/tkEntry.c.
1
2
3
4
5
6
7
8
9
10
11
12




13
14
15
16
17
18
19
20

21
22
23
24
25
26
27
1
2
3
4
5
6
7
8




9
10
11
12
13
14
15
16
17
18

19
20
21
22
23
24
25
26
27








-
-
-
-
+
+
+
+






-

+







/*
 * tkEntry.c --
 *
 *	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.
 */

#include "tkInt.h"
#include "default.h"
#include "tkEntry.h"
#include "default.h"

/*
 * The following macro defines how many extra pixels to leave on each side of
 * the text in the entry.
 */

#define XPAD 1
59
60
61
62
63
64
65
66

67
68
69

70
71

72
73

74
75

76
77
78
79


80
81
82
83


84
85
86


87
88

89
90

91
92

93
94
95

96
97

98
99
100


101
102

103
104
105


106
107
108

109
110
111

112
113

114
115

116
117
118

119
120







121
122
123


124
125
126

127
128

129
130
131
132


133
134
135

136
137
138

139
140
141

142
143
144

145
146
147

148
149
150

151
152
153

154
155

156
157

158
159

160
161

162
163
164
165
166
167
168
59
60
61
62
63
64
65

66
67
68

69
70

71
72

73
74

75
76
77


78
79
80
81


82
83
84


85
86
87

88
89

90
91

92
93
94

95
96

97
98


99
100
101

102
103


104
105
106
107

108
109
110

111
112

113
114

115
116
117

118
119

120
121
122
123
124
125
126
127


128
129
130
131

132
133

134
135
136


137
138
139
140

141
142
143

144
145
146

147
148
149

150
151
152

153
154
155

156
157
158

159
160

161
162

163
164

165
166

167
168
169
170
171
172
173
174







-
+


-
+

-
+

-
+

-
+


-
-
+
+


-
-
+
+

-
-
+
+

-
+

-
+

-
+


-
+

-
+

-
-
+
+

-
+

-
-
+
+


-
+


-
+

-
+

-
+


-
+

-
+
+
+
+
+
+
+

-
-
+
+


-
+

-
+


-
-
+
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+

-
+

-
+

-
+

-
+








/*
 * Information used for Entry objv parsing.
 */

static const Tk_OptionSpec entryOptSpec[] = {
    {TK_OPTION_BORDER, "-background", "background", "Background",
	DEF_ENTRY_BG_COLOR, -1, Tk_Offset(Entry, normalBorder),
	DEF_ENTRY_BG_COLOR, TCL_INDEX_NONE, offsetof(Entry, normalBorder),
	0, DEF_ENTRY_BG_MONO, 0},
    {TK_OPTION_SYNONYM, "-bd", NULL, NULL,
	NULL, 0, -1, 0, "-borderwidth", 0},
	NULL, 0, TCL_INDEX_NONE, 0, "-borderwidth", 0},
    {TK_OPTION_SYNONYM, "-bg", NULL, NULL,
	NULL, 0, -1, 0, "-background", 0},
	NULL, 0, TCL_INDEX_NONE, 0, "-background", 0},
    {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
	DEF_ENTRY_BORDER_WIDTH, -1, Tk_Offset(Entry, borderWidth), 0, 0, 0},
	DEF_ENTRY_BORDER_WIDTH, TCL_INDEX_NONE, offsetof(Entry, borderWidth), 0, 0, 0},
    {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
	DEF_ENTRY_CURSOR, -1, Tk_Offset(Entry, cursor),
	DEF_ENTRY_CURSOR, TCL_INDEX_NONE, offsetof(Entry, cursor),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_BORDER, "-disabledbackground", "disabledBackground",
	"DisabledBackground", DEF_ENTRY_DISABLED_BG_COLOR, -1,
	Tk_Offset(Entry, disabledBorder), TK_OPTION_NULL_OK,
	"DisabledBackground", DEF_ENTRY_DISABLED_BG_COLOR, TCL_INDEX_NONE,
	offsetof(Entry, disabledBorder), TK_OPTION_NULL_OK,
	(ClientData) DEF_ENTRY_DISABLED_BG_MONO, 0},
    {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground",
	"DisabledForeground", DEF_ENTRY_DISABLED_FG, -1,
	Tk_Offset(Entry, dfgColorPtr), TK_OPTION_NULL_OK, 0, 0},
	"DisabledForeground", DEF_ENTRY_DISABLED_FG, TCL_INDEX_NONE,
	offsetof(Entry, dfgColorPtr), TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_BOOLEAN, "-exportselection", "exportSelection",
	"ExportSelection", DEF_ENTRY_EXPORT_SELECTION, -1,
	Tk_Offset(Entry, exportSelection), 0, 0, 0},
	"ExportSelection", DEF_ENTRY_EXPORT_SELECTION, TCL_INDEX_NONE,
	offsetof(Entry, exportSelection), 0, 0, 0},
    {TK_OPTION_SYNONYM, "-fg", "foreground", NULL,
	NULL, 0, -1, 0, "-foreground", 0},
	NULL, 0, TCL_INDEX_NONE, 0, "-foreground", 0},
    {TK_OPTION_FONT, "-font", "font", "Font",
	DEF_ENTRY_FONT, -1, Tk_Offset(Entry, tkfont), 0, 0, 0},
	DEF_ENTRY_FONT, TCL_INDEX_NONE, offsetof(Entry, tkfont), 0, 0, 0},
    {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
	DEF_ENTRY_FG, -1, Tk_Offset(Entry, fgColorPtr), 0, 0, 0},
	DEF_ENTRY_FG, TCL_INDEX_NONE, offsetof(Entry, fgColorPtr), 0, 0, 0},
    {TK_OPTION_COLOR, "-highlightbackground", "highlightBackground",
	"HighlightBackground", DEF_ENTRY_HIGHLIGHT_BG,
	-1, Tk_Offset(Entry, highlightBgColorPtr), 0, 0, 0},
	TCL_INDEX_NONE, offsetof(Entry, highlightBgColorPtr), 0, 0, 0},
    {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
	DEF_ENTRY_HIGHLIGHT, -1, Tk_Offset(Entry, highlightColorPtr), 0, 0, 0},
	DEF_ENTRY_HIGHLIGHT, TCL_INDEX_NONE, offsetof(Entry, highlightColorPtr), 0, 0, 0},
    {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
	"HighlightThickness", DEF_ENTRY_HIGHLIGHT_WIDTH, -1,
	Tk_Offset(Entry, highlightWidth), 0, 0, 0},
	"HighlightThickness", DEF_ENTRY_HIGHLIGHT_WIDTH, TCL_INDEX_NONE,
	offsetof(Entry, highlightWidth), 0, 0, 0},
    {TK_OPTION_BORDER, "-insertbackground", "insertBackground", "Foreground",
	DEF_ENTRY_INSERT_BG, -1, Tk_Offset(Entry, insertBorder), 0, 0, 0},
	DEF_ENTRY_INSERT_BG, TCL_INDEX_NONE, offsetof(Entry, insertBorder), 0, 0, 0},
    {TK_OPTION_PIXELS, "-insertborderwidth", "insertBorderWidth",
	"BorderWidth", DEF_ENTRY_INSERT_BD_COLOR, -1,
	Tk_Offset(Entry, insertBorderWidth), 0,
	"BorderWidth", DEF_ENTRY_INSERT_BD_COLOR, TCL_INDEX_NONE,
	offsetof(Entry, insertBorderWidth), 0,
	(ClientData) DEF_ENTRY_INSERT_BD_MONO, 0},
    {TK_OPTION_INT, "-insertofftime", "insertOffTime", "OffTime",
	DEF_ENTRY_INSERT_OFF_TIME, -1, Tk_Offset(Entry, insertOffTime),
	DEF_ENTRY_INSERT_OFF_TIME, TCL_INDEX_NONE, offsetof(Entry, insertOffTime),
	0, 0, 0},
    {TK_OPTION_INT, "-insertontime", "insertOnTime", "OnTime",
	DEF_ENTRY_INSERT_ON_TIME, -1, Tk_Offset(Entry, insertOnTime), 0, 0, 0},
	DEF_ENTRY_INSERT_ON_TIME, TCL_INDEX_NONE, offsetof(Entry, insertOnTime), 0, 0, 0},
    {TK_OPTION_PIXELS, "-insertwidth", "insertWidth", "InsertWidth",
	DEF_ENTRY_INSERT_WIDTH, -1, Tk_Offset(Entry, insertWidth), 0, 0, 0},
	DEF_ENTRY_INSERT_WIDTH, TCL_INDEX_NONE, offsetof(Entry, insertWidth), 0, 0, 0},
    {TK_OPTION_STRING, "-invalidcommand", "invalidCommand", "InvalidCommand",
	DEF_ENTRY_INVALIDCMD, -1, Tk_Offset(Entry, invalidCmd),
	DEF_ENTRY_INVALIDCMD, TCL_INDEX_NONE, offsetof(Entry, invalidCmd),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_SYNONYM, "-invcmd", NULL, NULL,
	NULL, 0, -1, 0, "-invalidcommand", 0},
	NULL, 0, TCL_INDEX_NONE, 0, "-invalidcommand", 0},
    {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",
	DEF_ENTRY_JUSTIFY, -1, Tk_Offset(Entry, justify), 0, 0, 0},
	DEF_ENTRY_JUSTIFY, TCL_INDEX_NONE, offsetof(Entry, justify), 0, 0, 0},
    {TK_OPTION_STRING, "-placeholder", "placeHolder", "PlaceHolder",
	DEF_ENTRY_PLACEHOLDER, TCL_INDEX_NONE, offsetof(Entry, placeholderString),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_COLOR, "-placeholderforeground", "placeholderForeground",
        "PlaceholderForeground", DEF_ENTRY_PLACEHOLDERFG, TCL_INDEX_NONE,
        offsetof(Entry, placeholderColorPtr), 0, 0, 0},
    {TK_OPTION_BORDER, "-readonlybackground", "readonlyBackground",
	"ReadonlyBackground", DEF_ENTRY_READONLY_BG_COLOR, -1,
	Tk_Offset(Entry, readonlyBorder), TK_OPTION_NULL_OK,
	"ReadonlyBackground", DEF_ENTRY_READONLY_BG_COLOR, TCL_INDEX_NONE,
	offsetof(Entry, readonlyBorder), TK_OPTION_NULL_OK,
	(ClientData) DEF_ENTRY_READONLY_BG_MONO, 0},
    {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
	DEF_ENTRY_RELIEF, -1, Tk_Offset(Entry, relief), 0, 0, 0},
	DEF_ENTRY_RELIEF, TCL_INDEX_NONE, offsetof(Entry, relief), 0, 0, 0},
    {TK_OPTION_BORDER, "-selectbackground", "selectBackground", "Foreground",
	DEF_ENTRY_SELECT_COLOR, -1, Tk_Offset(Entry, selBorder),
	DEF_ENTRY_SELECT_COLOR, TCL_INDEX_NONE, offsetof(Entry, selBorder),
	0, DEF_ENTRY_SELECT_MONO, 0},
    {TK_OPTION_PIXELS, "-selectborderwidth", "selectBorderWidth",
	"BorderWidth", DEF_ENTRY_SELECT_BD_COLOR, -1,
	Tk_Offset(Entry, selBorderWidth),
	"BorderWidth", DEF_ENTRY_SELECT_BD_COLOR, TCL_INDEX_NONE,
	offsetof(Entry, selBorderWidth),
	0, DEF_ENTRY_SELECT_BD_MONO, 0},
    {TK_OPTION_COLOR, "-selectforeground", "selectForeground", "Background",
	DEF_ENTRY_SELECT_FG_COLOR, -1, Tk_Offset(Entry, selFgColorPtr),
	DEF_ENTRY_SELECT_FG_COLOR, TCL_INDEX_NONE, offsetof(Entry, selFgColorPtr),
	TK_OPTION_NULL_OK, DEF_ENTRY_SELECT_FG_MONO, 0},
    {TK_OPTION_STRING, "-show", "show", "Show",
	DEF_ENTRY_SHOW, -1, Tk_Offset(Entry, showChar),
	DEF_ENTRY_SHOW, TCL_INDEX_NONE, offsetof(Entry, showChar),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_STRING_TABLE, "-state", "state", "State",
	DEF_ENTRY_STATE, -1, Tk_Offset(Entry, state),
	DEF_ENTRY_STATE, TCL_INDEX_NONE, offsetof(Entry, state),
	0, stateStrings, 0},
    {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
	DEF_ENTRY_TAKE_FOCUS, -1, Tk_Offset(Entry, takeFocus),
	DEF_ENTRY_TAKE_FOCUS, TCL_INDEX_NONE, offsetof(Entry, takeFocus),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable",
	DEF_ENTRY_TEXT_VARIABLE, -1, Tk_Offset(Entry, textVarName),
	DEF_ENTRY_TEXT_VARIABLE, TCL_INDEX_NONE, offsetof(Entry, textVarName),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_STRING_TABLE, "-validate", "validate", "Validate",
	DEF_ENTRY_VALIDATE, -1, Tk_Offset(Entry, validate),
	DEF_ENTRY_VALIDATE, TCL_INDEX_NONE, offsetof(Entry, validate),
	0, validateStrings, 0},
    {TK_OPTION_STRING, "-validatecommand", "validateCommand","ValidateCommand",
	NULL, -1, Tk_Offset(Entry, validateCmd), TK_OPTION_NULL_OK, 0, 0},
	NULL, TCL_INDEX_NONE, offsetof(Entry, validateCmd), TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_SYNONYM, "-vcmd", NULL, NULL,
	NULL, 0, -1, 0, "-validatecommand", 0},
	NULL, 0, TCL_INDEX_NONE, 0, "-validatecommand", 0},
    {TK_OPTION_INT, "-width", "width", "Width",
	DEF_ENTRY_WIDTH, -1, Tk_Offset(Entry, prefWidth), 0, 0, 0},
	DEF_ENTRY_WIDTH, TCL_INDEX_NONE, offsetof(Entry, prefWidth), 0, 0, 0},
    {TK_OPTION_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand",
	DEF_ENTRY_SCROLL_COMMAND, -1, Tk_Offset(Entry, scrollCmd),
	DEF_ENTRY_SCROLL_COMMAND, TCL_INDEX_NONE, offsetof(Entry, scrollCmd),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0, 0, 0}
    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, TCL_INDEX_NONE, 0, 0, 0}
};

/*
 * Information used for Spinbox objv parsing.
 */

#define DEF_SPINBOX_REPEAT_DELAY	"400"
176
177
178
179
180
181
182
183

184
185
186

187
188
189

190
191

192
193

194
195

196
197
198

199
200
201

202
203

204
205

206
207
208

209
210
211
212


213
214
215
216


217
218
219


220
221

222
223

224
225

226
227

228
229
230

231
232
233

234
235

236
237
238


239
240

241
242

243
244
245


246
247
248

249
250
251

252
253

254
255

256
257
258

259
260







261
262

263
264
265


266
267
268

269
270
271

272
273
274

275
276
277
278


279
280
281

282
283
284

285
286
287

288
289
290

291
292
293

294
295

296
297
298

299
300

301
302
303

304
305

306
307

308
309

310
311

312
313
314
315
316
317
318
182
183
184
185
186
187
188

189
190
191

192
193
194

195
196

197
198

199
200

201
202
203

204
205
206

207
208

209
210

211
212
213

214
215
216


217
218
219
220


221
222
223


224
225
226

227
228

229
230

231
232

233
234
235

236
237
238

239
240

241
242


243
244
245

246
247

248
249


250
251
252
253

254
255
256

257
258

259
260

261
262
263

264
265

266
267
268
269
270
271
272
273

274
275


276
277
278
279

280
281
282

283
284
285

286
287
288


289
290
291
292

293
294
295

296
297
298

299
300
301

302
303
304

305
306

307
308
309

310
311

312
313
314

315
316

317
318

319
320

321
322

323
324
325
326
327
328
329
330







-
+


-
+


-
+

-
+

-
+

-
+


-
+


-
+

-
+

-
+


-
+


-
-
+
+


-
-
+
+

-
-
+
+

-
+

-
+

-
+

-
+


-
+


-
+

-
+

-
-
+
+

-
+

-
+

-
-
+
+


-
+


-
+

-
+

-
+


-
+

-
+
+
+
+
+
+
+

-
+

-
-
+
+


-
+


-
+


-
+


-
-
+
+


-
+


-
+


-
+


-
+


-
+

-
+


-
+

-
+


-
+

-
+

-
+

-
+

-
+







#define DEF_SPINBOX_FORMAT		""

#define DEF_SPINBOX_VALUES		""
#define DEF_SPINBOX_WRAP		"0"

static const Tk_OptionSpec sbOptSpec[] = {
    {TK_OPTION_BORDER, "-activebackground", "activeBackground", "Background",
	DEF_BUTTON_ACTIVE_BG_COLOR, -1, Tk_Offset(Spinbox, activeBorder),
	DEF_BUTTON_ACTIVE_BG_COLOR, TCL_INDEX_NONE, offsetof(Spinbox, activeBorder),
	0, DEF_BUTTON_ACTIVE_BG_MONO, 0},
    {TK_OPTION_BORDER, "-background", "background", "Background",
	DEF_ENTRY_BG_COLOR, -1, Tk_Offset(Entry, normalBorder),
	DEF_ENTRY_BG_COLOR, TCL_INDEX_NONE, offsetof(Entry, normalBorder),
	0, DEF_ENTRY_BG_MONO, 0},
    {TK_OPTION_SYNONYM, "-bd", NULL, NULL,
	NULL, 0, -1, 0, "-borderwidth", 0},
	NULL, 0, TCL_INDEX_NONE, 0, "-borderwidth", 0},
    {TK_OPTION_SYNONYM, "-bg", NULL, NULL,
	NULL, 0, -1, 0, "-background", 0},
	NULL, 0, TCL_INDEX_NONE, 0, "-background", 0},
    {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
	DEF_ENTRY_BORDER_WIDTH, -1, Tk_Offset(Entry, borderWidth), 0, 0, 0},
	DEF_ENTRY_BORDER_WIDTH, TCL_INDEX_NONE, offsetof(Entry, borderWidth), 0, 0, 0},
    {TK_OPTION_BORDER, "-buttonbackground", "buttonBackground", "Background",
	DEF_BUTTON_BG_COLOR, -1, Tk_Offset(Spinbox, buttonBorder),
	DEF_BUTTON_BG_COLOR, TCL_INDEX_NONE, offsetof(Spinbox, buttonBorder),
	0, DEF_BUTTON_BG_MONO, 0},
    {TK_OPTION_CURSOR, "-buttoncursor", "buttonCursor", "Cursor",
	DEF_BUTTON_CURSOR, -1, Tk_Offset(Spinbox, bCursor),
	DEF_BUTTON_CURSOR, TCL_INDEX_NONE, offsetof(Spinbox, bCursor),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_RELIEF, "-buttondownrelief", "buttonDownRelief", "Relief",
	DEF_BUTTON_RELIEF, -1, Tk_Offset(Spinbox, bdRelief), 0, 0, 0},
	DEF_BUTTON_RELIEF, TCL_INDEX_NONE, offsetof(Spinbox, bdRelief), 0, 0, 0},
    {TK_OPTION_RELIEF, "-buttonuprelief", "buttonUpRelief", "Relief",
	DEF_BUTTON_RELIEF, -1, Tk_Offset(Spinbox, buRelief), 0, 0, 0},
	DEF_BUTTON_RELIEF, TCL_INDEX_NONE, offsetof(Spinbox, buRelief), 0, 0, 0},
    {TK_OPTION_STRING, "-command", "command", "Command",
	DEF_SPINBOX_CMD, -1, Tk_Offset(Spinbox, command),
	DEF_SPINBOX_CMD, TCL_INDEX_NONE, offsetof(Spinbox, command),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
	DEF_ENTRY_CURSOR, -1, Tk_Offset(Entry, cursor),
	DEF_ENTRY_CURSOR, TCL_INDEX_NONE, offsetof(Entry, cursor),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_BORDER, "-disabledbackground", "disabledBackground",
	"DisabledBackground", DEF_ENTRY_DISABLED_BG_COLOR, -1,
	Tk_Offset(Entry, disabledBorder), TK_OPTION_NULL_OK,
	"DisabledBackground", DEF_ENTRY_DISABLED_BG_COLOR, TCL_INDEX_NONE,
	offsetof(Entry, disabledBorder), TK_OPTION_NULL_OK,
	(ClientData) DEF_ENTRY_DISABLED_BG_MONO, 0},
    {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground",
	"DisabledForeground", DEF_ENTRY_DISABLED_FG, -1,
	Tk_Offset(Entry, dfgColorPtr), TK_OPTION_NULL_OK, 0, 0},
	"DisabledForeground", DEF_ENTRY_DISABLED_FG, TCL_INDEX_NONE,
	offsetof(Entry, dfgColorPtr), TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_BOOLEAN, "-exportselection", "exportSelection",
	"ExportSelection", DEF_ENTRY_EXPORT_SELECTION, -1,
	Tk_Offset(Entry, exportSelection), 0, 0, 0},
	"ExportSelection", DEF_ENTRY_EXPORT_SELECTION, TCL_INDEX_NONE,
	offsetof(Entry, exportSelection), 0, 0, 0},
    {TK_OPTION_SYNONYM, "-fg", "foreground", NULL,
	NULL, 0, -1, 0, "-foreground", 0},
	NULL, 0, TCL_INDEX_NONE, 0, "-foreground", 0},
    {TK_OPTION_FONT, "-font", "font", "Font",
	DEF_ENTRY_FONT, -1, Tk_Offset(Entry, tkfont), 0, 0, 0},
	DEF_ENTRY_FONT, TCL_INDEX_NONE, offsetof(Entry, tkfont), 0, 0, 0},
    {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
	DEF_ENTRY_FG, -1, Tk_Offset(Entry, fgColorPtr), 0, 0, 0},
	DEF_ENTRY_FG, TCL_INDEX_NONE, offsetof(Entry, fgColorPtr), 0, 0, 0},
    {TK_OPTION_STRING, "-format", "format", "Format",
	DEF_SPINBOX_FORMAT, -1, Tk_Offset(Spinbox, reqFormat),
	DEF_SPINBOX_FORMAT, TCL_INDEX_NONE, offsetof(Spinbox, reqFormat),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_DOUBLE, "-from", "from", "From",
	DEF_SPINBOX_FROM, -1, Tk_Offset(Spinbox, fromValue), 0, 0, 0},
	DEF_SPINBOX_FROM, TCL_INDEX_NONE, offsetof(Spinbox, fromValue), 0, 0, 0},
    {TK_OPTION_COLOR, "-highlightbackground", "highlightBackground",
	"HighlightBackground", DEF_ENTRY_HIGHLIGHT_BG,
	-1, Tk_Offset(Entry, highlightBgColorPtr), 0, 0, 0},
	TCL_INDEX_NONE, offsetof(Entry, highlightBgColorPtr), 0, 0, 0},
    {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
	DEF_ENTRY_HIGHLIGHT, -1, Tk_Offset(Entry, highlightColorPtr), 0, 0, 0},
	DEF_ENTRY_HIGHLIGHT, TCL_INDEX_NONE, offsetof(Entry, highlightColorPtr), 0, 0, 0},
    {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
	"HighlightThickness", DEF_ENTRY_HIGHLIGHT_WIDTH, -1,
	Tk_Offset(Entry, highlightWidth), 0, 0, 0},
	"HighlightThickness", DEF_ENTRY_HIGHLIGHT_WIDTH, TCL_INDEX_NONE,
	offsetof(Entry, highlightWidth), 0, 0, 0},
    {TK_OPTION_DOUBLE, "-increment", "increment", "Increment",
	DEF_SPINBOX_INCREMENT, -1, Tk_Offset(Spinbox, increment), 0, 0, 0},
	DEF_SPINBOX_INCREMENT, TCL_INDEX_NONE, offsetof(Spinbox, increment), 0, 0, 0},
    {TK_OPTION_BORDER, "-insertbackground", "insertBackground", "Foreground",
	DEF_ENTRY_INSERT_BG, -1, Tk_Offset(Entry, insertBorder), 0, 0, 0},
	DEF_ENTRY_INSERT_BG, TCL_INDEX_NONE, offsetof(Entry, insertBorder), 0, 0, 0},
    {TK_OPTION_PIXELS, "-insertborderwidth", "insertBorderWidth",
	"BorderWidth", DEF_ENTRY_INSERT_BD_COLOR, -1,
	Tk_Offset(Entry, insertBorderWidth), 0,
	"BorderWidth", DEF_ENTRY_INSERT_BD_COLOR, TCL_INDEX_NONE,
	offsetof(Entry, insertBorderWidth), 0,
	(ClientData) DEF_ENTRY_INSERT_BD_MONO, 0},
    {TK_OPTION_INT, "-insertofftime", "insertOffTime", "OffTime",
	DEF_ENTRY_INSERT_OFF_TIME, -1, Tk_Offset(Entry, insertOffTime),
	DEF_ENTRY_INSERT_OFF_TIME, TCL_INDEX_NONE, offsetof(Entry, insertOffTime),
	0, 0, 0},
    {TK_OPTION_INT, "-insertontime", "insertOnTime", "OnTime",
	DEF_ENTRY_INSERT_ON_TIME, -1, Tk_Offset(Entry, insertOnTime), 0, 0, 0},
	DEF_ENTRY_INSERT_ON_TIME, TCL_INDEX_NONE, offsetof(Entry, insertOnTime), 0, 0, 0},
    {TK_OPTION_PIXELS, "-insertwidth", "insertWidth", "InsertWidth",
	DEF_ENTRY_INSERT_WIDTH, -1, Tk_Offset(Entry, insertWidth), 0, 0, 0},
	DEF_ENTRY_INSERT_WIDTH, TCL_INDEX_NONE, offsetof(Entry, insertWidth), 0, 0, 0},
    {TK_OPTION_STRING, "-invalidcommand", "invalidCommand", "InvalidCommand",
	DEF_ENTRY_INVALIDCMD, -1, Tk_Offset(Entry, invalidCmd),
	DEF_ENTRY_INVALIDCMD, TCL_INDEX_NONE, offsetof(Entry, invalidCmd),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_SYNONYM, "-invcmd", NULL, NULL,
	NULL, 0, -1, 0, "-invalidcommand", 0},
	NULL, 0, TCL_INDEX_NONE, 0, "-invalidcommand", 0},
    {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",
	DEF_ENTRY_JUSTIFY, -1, Tk_Offset(Entry, justify), 0, 0, 0},
	DEF_ENTRY_JUSTIFY, TCL_INDEX_NONE, offsetof(Entry, justify), 0, 0, 0},
    {TK_OPTION_STRING, "-placeholder", "placeHolder", "PlaceHolder",
	DEF_ENTRY_PLACEHOLDER, TCL_INDEX_NONE, offsetof(Entry, placeholderString),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_COLOR, "-placeholderforeground", "placeholderForeground",
        "PlaceholderForeground", DEF_ENTRY_PLACEHOLDERFG, TCL_INDEX_NONE,
        offsetof(Entry, placeholderColorPtr), 0, 0, 0},
    {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
	DEF_ENTRY_RELIEF, -1, Tk_Offset(Entry, relief), 0, 0, 0},
	DEF_ENTRY_RELIEF, TCL_INDEX_NONE, offsetof(Entry, relief), 0, 0, 0},
    {TK_OPTION_BORDER, "-readonlybackground", "readonlyBackground",
	"ReadonlyBackground", DEF_ENTRY_READONLY_BG_COLOR, -1,
	Tk_Offset(Entry, readonlyBorder), TK_OPTION_NULL_OK,
	"ReadonlyBackground", DEF_ENTRY_READONLY_BG_COLOR, TCL_INDEX_NONE,
	offsetof(Entry, readonlyBorder), TK_OPTION_NULL_OK,
	(ClientData) DEF_ENTRY_READONLY_BG_MONO, 0},
    {TK_OPTION_INT, "-repeatdelay", "repeatDelay", "RepeatDelay",
	DEF_SPINBOX_REPEAT_DELAY, -1, Tk_Offset(Spinbox, repeatDelay),
	DEF_SPINBOX_REPEAT_DELAY, TCL_INDEX_NONE, offsetof(Spinbox, repeatDelay),
	0, 0, 0},
    {TK_OPTION_INT, "-repeatinterval", "repeatInterval", "RepeatInterval",
	DEF_SPINBOX_REPEAT_INTERVAL, -1, Tk_Offset(Spinbox, repeatInterval),
	DEF_SPINBOX_REPEAT_INTERVAL, TCL_INDEX_NONE, offsetof(Spinbox, repeatInterval),
	0, 0, 0},
    {TK_OPTION_BORDER, "-selectbackground", "selectBackground", "Foreground",
	DEF_ENTRY_SELECT_COLOR, -1, Tk_Offset(Entry, selBorder),
	DEF_ENTRY_SELECT_COLOR, TCL_INDEX_NONE, offsetof(Entry, selBorder),
	0, DEF_ENTRY_SELECT_MONO, 0},
    {TK_OPTION_PIXELS, "-selectborderwidth", "selectBorderWidth",
	"BorderWidth", DEF_ENTRY_SELECT_BD_COLOR, -1,
	Tk_Offset(Entry, selBorderWidth),
	"BorderWidth", DEF_ENTRY_SELECT_BD_COLOR, TCL_INDEX_NONE,
	offsetof(Entry, selBorderWidth),
	0, DEF_ENTRY_SELECT_BD_MONO, 0},
    {TK_OPTION_COLOR, "-selectforeground", "selectForeground", "Background",
	DEF_ENTRY_SELECT_FG_COLOR, -1, Tk_Offset(Entry, selFgColorPtr),
	DEF_ENTRY_SELECT_FG_COLOR, TCL_INDEX_NONE, offsetof(Entry, selFgColorPtr),
	TK_OPTION_NULL_OK, DEF_ENTRY_SELECT_FG_MONO, 0},
    {TK_OPTION_STRING_TABLE, "-state", "state", "State",
	DEF_ENTRY_STATE, -1, Tk_Offset(Entry, state),
	DEF_ENTRY_STATE, TCL_INDEX_NONE, offsetof(Entry, state),
	0, stateStrings, 0},
    {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
	DEF_ENTRY_TAKE_FOCUS, -1, Tk_Offset(Entry, takeFocus),
	DEF_ENTRY_TAKE_FOCUS, TCL_INDEX_NONE, offsetof(Entry, takeFocus),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable",
	DEF_ENTRY_TEXT_VARIABLE, -1, Tk_Offset(Entry, textVarName),
	DEF_ENTRY_TEXT_VARIABLE, TCL_INDEX_NONE, offsetof(Entry, textVarName),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_DOUBLE, "-to", "to", "To",
	DEF_SPINBOX_TO, -1, Tk_Offset(Spinbox, toValue), 0, 0, 0},
	DEF_SPINBOX_TO, TCL_INDEX_NONE, offsetof(Spinbox, toValue), 0, 0, 0},
    {TK_OPTION_STRING_TABLE, "-validate", "validate", "Validate",
	DEF_ENTRY_VALIDATE, -1, Tk_Offset(Entry, validate),
	DEF_ENTRY_VALIDATE, TCL_INDEX_NONE, offsetof(Entry, validate),
	0, validateStrings, 0},
    {TK_OPTION_STRING, "-validatecommand", "validateCommand","ValidateCommand",
	NULL, -1, Tk_Offset(Entry, validateCmd), TK_OPTION_NULL_OK, 0, 0},
	NULL, TCL_INDEX_NONE, offsetof(Entry, validateCmd), TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_STRING, "-values", "values", "Values",
	DEF_SPINBOX_VALUES, -1, Tk_Offset(Spinbox, valueStr),
	DEF_SPINBOX_VALUES, TCL_INDEX_NONE, offsetof(Spinbox, valueStr),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_SYNONYM, "-vcmd", NULL, NULL,
	NULL, 0, -1, 0, "-validatecommand", 0},
	NULL, 0, TCL_INDEX_NONE, 0, "-validatecommand", 0},
    {TK_OPTION_INT, "-width", "width", "Width",
	DEF_ENTRY_WIDTH, -1, Tk_Offset(Entry, prefWidth), 0, 0, 0},
	DEF_ENTRY_WIDTH, TCL_INDEX_NONE, offsetof(Entry, prefWidth), 0, 0, 0},
    {TK_OPTION_BOOLEAN, "-wrap", "wrap", "Wrap",
	DEF_SPINBOX_WRAP, -1, Tk_Offset(Spinbox, wrap), 0, 0, 0},
	DEF_SPINBOX_WRAP, TCL_INDEX_NONE, offsetof(Spinbox, wrap), 0, 0, 0},
    {TK_OPTION_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand",
	DEF_ENTRY_SCROLL_COMMAND, -1, Tk_Offset(Entry, scrollCmd),
	DEF_ENTRY_SCROLL_COMMAND, TCL_INDEX_NONE, offsetof(Entry, scrollCmd),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0, 0, 0}
    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, TCL_INDEX_NONE, 0, 0, 0}
};

/*
 * The following tables define the entry widget commands (and sub-commands)
 * and map the indexes into the string tables into enumerated types used to
 * dispatch the entry widget command.
 */
387
388
389
390
391
392
393
394

395
396
397
398
399
400
401
402
403
404


405
406
407
408
409

410
411
412
413
414
415
416

417
418

419
420
421
422
423
424
425
426
427
428
429
430


431
432
433
434
435
436
437
399
400
401
402
403
404
405

406
407
408
409
410
411
412
413
414


415
416
417
418
419
420

421
422
423
424
425
426
427

428
429

430
431
432
433
434
435
436
437
438
439
440


441
442
443
444
445
446
447
448
449







-
+








-
-
+
+




-
+






-
+

-
+










-
-
+
+








/*
 * Forward declarations for functions defined later in this file:
 */

static int		ConfigureEntry(Tcl_Interp *interp, Entry *entryPtr,
			    int objc, Tcl_Obj *const objv[]);
static int		DeleteChars(Entry *entryPtr, int index, int count);
static int		DeleteChars(Entry *entryPtr, TkSizeT index, TkSizeT count);
static void		DestroyEntry(void *memPtr);
static void		DisplayEntry(ClientData clientData);
static void		EntryBlinkProc(ClientData clientData);
static void		EntryCmdDeletedProc(ClientData clientData);
static void		EntryComputeGeometry(Entry *entryPtr);
static void		EntryEventProc(ClientData clientData,
			    XEvent *eventPtr);
static void		EntryFocusProc(Entry *entryPtr, int gotFocus);
static int		EntryFetchSelection(ClientData clientData, int offset,
			    char *buffer, int maxBytes);
static TkSizeT	EntryFetchSelection(ClientData clientData, TkSizeT offset,
			    char *buffer, TkSizeT maxBytes);
static void		EntryLostSelection(ClientData clientData);
static void		EventuallyRedraw(Entry *entryPtr);
static void		EntryScanTo(Entry *entryPtr, int y);
static void		EntrySetValue(Entry *entryPtr, const char *value);
static void		EntrySelectTo(Entry *entryPtr, int index);
static void		EntrySelectTo(Entry *entryPtr, TkSizeT index);
static char *		EntryTextVarProc(ClientData clientData,
			    Tcl_Interp *interp, const char *name1,
			    const char *name2, int flags);
static void		EntryUpdateScrollbar(Entry *entryPtr);
static int		EntryValidate(Entry *entryPtr, char *cmd);
static int		EntryValidateChange(Entry *entryPtr, const char *change,
			    const char *newStr, int index, int type);
			    const char *newStr, TkSizeT index, int type);
static void		ExpandPercents(Entry *entryPtr, const char *before,
			    const char *change, const char *newStr, int index,
			    const char *change, const char *newStr, TkSizeT index,
			    int type, Tcl_DString *dsPtr);
static int		EntryValueChanged(Entry *entryPtr,
			    const char *newValue);
static void		EntryVisibleRange(Entry *entryPtr,
			    double *firstPtr, double *lastPtr);
static int		EntryWidgetObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static void		EntryWorldChanged(ClientData instanceData);
static int		GetEntryIndex(Tcl_Interp *interp, Entry *entryPtr,
			    Tcl_Obj *indexObj, int *indexPtr);
static int		InsertChars(Entry *entryPtr, int index, const char *string);
			    Tcl_Obj *indexObj, TkSizeT *indexPtr);
static int		InsertChars(Entry *entryPtr, TkSizeT index, const char *string);

/*
 * These forward declarations are the spinbox specific ones:
 */

static int		SpinboxWidgetObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
468
469
470
471
472
473
474
475

476
477
478
479
480

481
482
483

484
485
486
487
488
489
490
480
481
482
483
484
485
486

487
488
489
490
491

492
493
494
495
496
497
498
499
500
501
502
503







-
+




-
+



+







 *	See the user documentation.
 *
 *--------------------------------------------------------------
 */

int
Tk_EntryObjCmd(
    ClientData clientData,	/* NULL. */
    ClientData dummy,	/* NULL. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    register Entry *entryPtr;
    Entry *entryPtr;
    Tk_OptionTable optionTable;
    Tk_Window tkwin;
    char *tmp;
    (void)dummy;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "pathName ?-option value ...?");
	return TCL_ERROR;
    }

    tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp),
503
504
505
506
507
508
509
510

511
512
513
514
515
516
517
518
519
520
521

522
523
524
525


526
527
528
529
530
531
532
533
534
535
536
537
538


539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555

556
557
558
559
560
561
562

563
564
565
566
567
568
569
516
517
518
519
520
521
522

523
524
525
526
527
528
529
530
531
532
533

534
535
536


537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569

570
571
572
573
574
575
576

577
578
579
580
581
582
583
584







-
+










-
+


-
-
+
+













+
+
















-
+






-
+







    /*
     * Initialize the fields of the structure that won't be initialized by
     * ConfigureEntry, or that ConfigureEntry requires to be initialized
     * already (e.g. resource pointers). Only the non-NULL/0 data must be
     * initialized as memset covers the rest.
     */

    entryPtr = ckalloc(sizeof(Entry));
    entryPtr = (Entry *)ckalloc(sizeof(Entry));
    memset(entryPtr, 0, sizeof(Entry));

    entryPtr->tkwin		= tkwin;
    entryPtr->display		= Tk_Display(tkwin);
    entryPtr->interp		= interp;
    entryPtr->widgetCmd		= Tcl_CreateObjCommand(interp,
	    Tk_PathName(entryPtr->tkwin), EntryWidgetObjCmd, entryPtr,
	    EntryCmdDeletedProc);
    entryPtr->optionTable	= optionTable;
    entryPtr->type		= TK_ENTRY;
    tmp				= ckalloc(1);
    tmp				= (char *)ckalloc(1);
    tmp[0]			= '\0';
    entryPtr->string		= tmp;
    entryPtr->selectFirst	= -1;
    entryPtr->selectLast	= -1;
    entryPtr->selectFirst	= TCL_INDEX_NONE;
    entryPtr->selectLast	= TCL_INDEX_NONE;

    entryPtr->cursor		= NULL;
    entryPtr->exportSelection	= 1;
    entryPtr->justify		= TK_JUSTIFY_LEFT;
    entryPtr->relief		= TK_RELIEF_FLAT;
    entryPtr->state		= STATE_NORMAL;
    entryPtr->displayString	= entryPtr->string;
    entryPtr->inset		= XPAD;
    entryPtr->textGC		= NULL;
    entryPtr->selTextGC		= NULL;
    entryPtr->highlightGC	= NULL;
    entryPtr->avgWidth		= 1;
    entryPtr->validate		= VALIDATE_NONE;

    entryPtr->placeholderGC	= NULL;

    /*
     * Keep a hold of the associated tkwin until we destroy the entry,
     * otherwise Tk might free it while we still need it.
     */

    Tcl_Preserve(entryPtr->tkwin);

    Tk_SetClass(entryPtr->tkwin, "Entry");
    Tk_SetClassProcs(entryPtr->tkwin, &entryClass, entryPtr);
    Tk_CreateEventHandler(entryPtr->tkwin,
	    ExposureMask|StructureNotifyMask|FocusChangeMask,
	    EntryEventProc, entryPtr);
    Tk_CreateSelHandler(entryPtr->tkwin, XA_PRIMARY, XA_STRING,
	    EntryFetchSelection, entryPtr, XA_STRING);

    if ((Tk_InitOptions(interp, (char *) entryPtr, optionTable, tkwin)
    if ((Tk_InitOptions(interp, entryPtr, optionTable, tkwin)
	    != TCL_OK) ||
	    (ConfigureEntry(interp, entryPtr, objc-2, objv+2) != TCL_OK)) {
	Tk_DestroyWindow(entryPtr->tkwin);
	return TCL_ERROR;
    }

    Tcl_SetObjResult(interp, TkNewWindowObj(entryPtr->tkwin));
    Tcl_SetObjResult(interp, Tk_NewWindowObj(entryPtr->tkwin));
    return TCL_OK;
}

/*
 *--------------------------------------------------------------
 *
 * EntryWidgetObjCmd --
584
585
586
587
588
589
590
591

592
593
594
595
596
597
598
599
600
601
602
603
604
605

606
607
608
609
610
611
612
613







-
+







static int
EntryWidgetObjCmd(
    ClientData clientData,	/* Information about entry widget. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Entry *entryPtr = clientData;
    Entry *entryPtr = (Entry *)clientData;
    int cmdIndex, selIndex, result;
    Tcl_Obj *objPtr;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
	return TCL_ERROR;
    }
607
608
609
610
611
612
613

614

615
616
617
618
619
620
621
622
623
624
625

626
627
628
629
630
631
632




633
634
635
636
637
638
639
640
641
642
643

644
645
646
647
648
649
650
651
652
653

654
655
656
657
658
659
660
661
662
663
664
665
666
667


668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683

684
685
686
687
688
689
690
691
692
693
694
695
696
697

698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713

714
715
716
717
718
719
720
721
722
723

724
725
726
727

728

729
730
731
732
733
734
735
622
623
624
625
626
627
628
629

630
631
632
633
634
635
636
637
638
639
640

641
642
643
644




645
646
647
648
649
650
651
652
653
654
655
656
657
658

659
660
661
662
663
664
665
666
667
668

669
670
671
672
673
674
675
676
677
678
679
680
681
682

683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699

700
701
702
703
704
705
706
707
708
709
710
711
712
713

714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729

730
731
732
733
734
735
736
737
738
739

740
741
742
743
744
745

746
747
748
749
750
751
752
753







+
-
+










-
+



-
-
-
-
+
+
+
+










-
+









-
+













-
+
+















-
+













-
+















-
+









-
+




+
-
+







    if (result != TCL_OK) {
	return result;
    }

    Tcl_Preserve(entryPtr);
    switch ((enum entryCmd) cmdIndex) {
    case COMMAND_BBOX: {
	TkSizeT index;
	int index, x, y, width, height;
	int x, y, width, height;
	Tcl_Obj *bbox[4];

	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "index");
	    goto error;
	}
	if (GetEntryIndex(interp, entryPtr, objv[2],
		&index) != TCL_OK) {
	    goto error;
	}
	if ((index == entryPtr->numChars) && (index > 0)) {
	if ((index == entryPtr->numChars) && (index + 1 > 1)) {
	    index--;
	}
	Tk_CharBbox(entryPtr->textLayout, index, &x, &y, &width, &height);
	bbox[0] = Tcl_NewIntObj(x + entryPtr->layoutX);
	bbox[1] = Tcl_NewIntObj(y + entryPtr->layoutY);
	bbox[2] = Tcl_NewIntObj(width);
	bbox[3] = Tcl_NewIntObj(height);
	bbox[0] = Tcl_NewWideIntObj(x + entryPtr->layoutX);
	bbox[1] = Tcl_NewWideIntObj(y + entryPtr->layoutY);
	bbox[2] = Tcl_NewWideIntObj(width);
	bbox[3] = Tcl_NewWideIntObj(height);
	Tcl_SetObjResult(interp, Tcl_NewListObj(4, bbox));
	break;
    }

    case COMMAND_CGET:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "option");
	    goto error;
	}

	objPtr = Tk_GetOptionValue(interp, (char *) entryPtr,
	objPtr = Tk_GetOptionValue(interp, entryPtr,
		entryPtr->optionTable, objv[2], entryPtr->tkwin);
	if (objPtr == NULL) {
	    goto error;
	}
	Tcl_SetObjResult(interp, objPtr);
	break;

    case COMMAND_CONFIGURE:
	if (objc <= 3) {
	    objPtr = Tk_GetOptionInfo(interp, (char *) entryPtr,
	    objPtr = Tk_GetOptionInfo(interp, entryPtr,
		    entryPtr->optionTable,
		    (objc == 3) ? objv[2] : NULL,
		    entryPtr->tkwin);
	    if (objPtr == NULL) {
		goto error;
	    }
	    Tcl_SetObjResult(interp, objPtr);
	} else {
	    result = ConfigureEntry(interp, entryPtr, objc-2, objv+2);
	}
	break;

    case COMMAND_DELETE: {
	int first, last, code;
	TkSizeT first, last;
	int code;

	if ((objc < 3) || (objc > 4)) {
	    Tcl_WrongNumArgs(interp, 2, objv, "firstIndex ?lastIndex?");
	    goto error;
	}
	if (GetEntryIndex(interp, entryPtr, objv[2],
		&first) != TCL_OK) {
	    goto error;
	}
	if (objc == 3) {
	    last = first + 1;
	} else if (GetEntryIndex(interp, entryPtr, objv[3],
		&last) != TCL_OK) {
	    goto error;
	}
	if ((last >= first) && (entryPtr->state == STATE_NORMAL)) {
	if ((last + 1 >= first + 1 ) && (entryPtr->state == STATE_NORMAL)) {
	    code = DeleteChars(entryPtr, first, last - first);
            if (code != TCL_OK) {
                goto error;
            }
	}
	break;
    }

    case COMMAND_GET:
	if (objc != 2) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    goto error;
	}
	Tcl_SetObjResult(interp, Tcl_NewStringObj(entryPtr->string, -1));
	Tcl_SetObjResult(interp, Tcl_NewStringObj(entryPtr->string, TCL_INDEX_NONE));
	break;

    case COMMAND_ICURSOR:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "pos");
	    goto error;
	}
	if (GetEntryIndex(interp, entryPtr, objv[2],
		&entryPtr->insertPos) != TCL_OK) {
	    goto error;
	}
	EventuallyRedraw(entryPtr);
	break;

    case COMMAND_INDEX: {
	int index;
	TkSizeT index;

	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "string");
	    goto error;
	}
	if (GetEntryIndex(interp, entryPtr, objv[2],
		&index) != TCL_OK) {
	    goto error;
	}
	Tcl_SetObjResult(interp, Tcl_NewIntObj(index));
	Tcl_SetObjResult(interp, TkNewIndexObj(index));
	break;
    }

    case COMMAND_INSERT: {
	TkSizeT index;
	int index, code;
	int code;

	if (objc != 4) {
	    Tcl_WrongNumArgs(interp, 2, objv, "index text");
	    goto error;
	}
	if (GetEntryIndex(interp, entryPtr, objv[2],
		&index) != TCL_OK) {
772
773
774
775
776
777
778
779

780
781
782
783
784
785
786
790
791
792
793
794
795
796

797
798
799
800
801
802
803
804







-
+







		    minorCmd, NULL);
	    goto error;
	}
	break;
    }

    case COMMAND_SELECTION: {
	int index, index2;
	TkSizeT index, index2;

	if (objc < 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "option ?index?");
	    goto error;
	}

	/*
810
811
812
813
814
815
816
817
818


819
820
821
822

823
824

825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843



844
845
846
847
848
849
850
828
829
830
831
832
833
834


835
836
837
838
839

840
841

842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858



859
860
861
862
863
864
865
866
867
868







-
-
+
+



-
+

-
+
















-
-
-
+
+
+







		Tcl_WrongNumArgs(interp, 3, objv, "index");
		goto error;
	    }
	    if (GetEntryIndex(interp, entryPtr,
		    objv[3], &index) != TCL_OK) {
		goto error;
	    }
	    if (entryPtr->selectFirst >= 0) {
		int half1, half2;
	    if (entryPtr->selectFirst != TCL_INDEX_NONE) {
		TkSizeT half1, half2;

		half1 = (entryPtr->selectFirst + entryPtr->selectLast)/2;
		half2 = (entryPtr->selectFirst + entryPtr->selectLast + 1)/2;
		if (index < half1) {
		if (index + 1 < half1 + 1 ) {
		    entryPtr->selectAnchor = entryPtr->selectLast;
		} else if (index > half2) {
		} else if (index + 1 > half2 + 1 ) {
		    entryPtr->selectAnchor = entryPtr->selectFirst;
		} else {
		    /*
		     * We're at about the halfway point in the selection; just
		     * keep the existing anchor.
		     */
		}
	    }
	    EntrySelectTo(entryPtr, index);
	    break;

	case SELECTION_CLEAR:
	    if (objc != 3) {
		Tcl_WrongNumArgs(interp, 3, objv, NULL);
		goto error;
	    }
	    if (entryPtr->selectFirst >= 0) {
		entryPtr->selectFirst = -1;
		entryPtr->selectLast = -1;
	    if (entryPtr->selectFirst != TCL_INDEX_NONE) {
		entryPtr->selectFirst = TCL_INDEX_NONE;
		entryPtr->selectLast = TCL_INDEX_NONE;
		EventuallyRedraw(entryPtr);
	    }
	    goto done;

	case SELECTION_FROM:
	    if (objc != 4) {
		Tcl_WrongNumArgs(interp, 3, objv, "index");
859
860
861
862
863
864
865
866

867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884



885
886
887
888
889
890
891
877
878
879
880
881
882
883

884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899



900
901
902
903
904
905
906
907
908
909







-
+















-
-
-
+
+
+








	case SELECTION_PRESENT:
	    if (objc != 3) {
		Tcl_WrongNumArgs(interp, 3, objv, NULL);
		goto error;
	    }
	    Tcl_SetObjResult(interp,
		    Tcl_NewBooleanObj(entryPtr->selectFirst >= 0));
		    Tcl_NewWideIntObj(entryPtr->selectFirst != TCL_INDEX_NONE));
	    goto done;

	case SELECTION_RANGE:
	    if (objc != 5) {
		Tcl_WrongNumArgs(interp, 3, objv, "start end");
		goto error;
	    }
	    if (GetEntryIndex(interp, entryPtr, objv[3],
		    &index) != TCL_OK) {
		goto error;
	    }
	    if (GetEntryIndex(interp, entryPtr, objv[4],
		    &index2) != TCL_OK) {
		goto error;
	    }
	    if (index >= index2) {
		entryPtr->selectFirst = -1;
		entryPtr->selectLast = -1;
	    if (index + 1 >= index2 + 1 ) {
		entryPtr->selectFirst = TCL_INDEX_NONE;
		entryPtr->selectLast = TCL_INDEX_NONE;
	    } else {
		entryPtr->selectFirst = index;
		entryPtr->selectLast = index2;
	    }
	    if (!(entryPtr->flags & GOT_SELECTION)
		    && (entryPtr->exportSelection)
		    && (!Tcl_IsSafe(entryPtr->interp))) {
926
927
928
929
930
931
932
933

934
935
936
937
938
939
940
944
945
946
947
948
949
950

951
952
953
954
955
956
957
958







-
+







	    entryPtr->validate = selIndex;
	}
	Tcl_SetObjResult(interp, Tcl_NewBooleanObj(code == TCL_OK));
	break;
    }

    case COMMAND_XVIEW: {
	int index;
	TkSizeT index;

	if (objc == 2) {
	    double first, last;
	    Tcl_Obj *span[2];

	    EntryVisibleRange(entryPtr, &first, &last);
	    span[0] = Tcl_NewDoubleObj(first);
970
971
972
973
974
975
976
977

978
979
980

981
982
983
984
985
986
987
988
989
990
991
992
993
994

995
996
997

998
999
1000
1001
1002
1003
1004
1005







-
+


-
+







		break;
	    }
	    case TK_SCROLL_UNITS:
		index += count;
		break;
	    }
	}
	if (index >= entryPtr->numChars) {
	if (index + 1 >= entryPtr->numChars + 1) {
	    index = entryPtr->numChars - 1;
	}
	if (index < 0) {
	if ((int)index < 0) {
	    index = 0;
	}
	entryPtr->leftIndex = index;
	entryPtr->flags |= UPDATE_SCROLLBAR;
	EntryComputeGeometry(entryPtr);
	EventuallyRedraw(entryPtr);
	break;
1015
1016
1017
1018
1019
1020
1021
1022

1023
1024
1025
1026
1027
1028
1029
1033
1034
1035
1036
1037
1038
1039

1040
1041
1042
1043
1044
1045
1046
1047







-
+







 *----------------------------------------------------------------------
 */

static void
DestroyEntry(
    void *memPtr)		/* Info about entry widget. */
{
    Entry *entryPtr = memPtr;
    Entry *entryPtr = (Entry *)memPtr;

    /*
     * Free up all the stuff that requires special handling, then let
     * Tk_FreeOptions handle all the standard option-related stuff.
     */

    ckfree((char *)entryPtr->string);
1093
1094
1095
1096
1097
1098
1099
1100
1101


1102
1103
1104
1105
1106




1107
1108
1109
1110
1111
1112
1113
1111
1112
1113
1114
1115
1116
1117


1118
1119
1120




1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131







-
-
+
+

-
-
-
-
+
+
+
+







{
    Tk_SavedOptions savedOptions;
    Tk_3DBorder border;
    Tcl_Obj *errorResult = NULL;
    Spinbox *sbPtr = (Spinbox *) entryPtr;
				/* Only used when this widget is of type
				 * TK_SPINBOX */
    char *oldValues = NULL;	/* lint initialization */
    char *oldFormat = NULL;	/* lint initialization */
    char *oldValues = NULL;
    char *oldFormat = NULL;
    int error;
    int oldExport = 0;		/* lint initialization */
    int valuesChanged = 0;	/* lint initialization */
    double oldFrom = 0.0;	/* lint initialization */
    double oldTo = 0.0;		/* lint initialization */
    int oldExport = 0;
    int valuesChanged = 0;
    double oldFrom = 0.0;
    double oldTo = 0.0;
    int code;

    /*
     * Eliminate any existing trace on a variable monitored by the entry.
     */

    if ((entryPtr->textVarName != NULL)
1133
1134
1135
1136
1137
1138
1139
1140

1141
1142
1143
1144
1145
1146
1147
1151
1152
1153
1154
1155
1156
1157

1158
1159
1160
1161
1162
1163
1164
1165







-
+








    for (error = 0; error <= 1; error++) {
	if (!error) {
	    /*
	     * First pass: set options to new values.
	     */

	    if (Tk_SetOptions(interp, (char *) entryPtr,
	    if (Tk_SetOptions(interp, entryPtr,
		    entryPtr->optionTable, objc, objv,
		    entryPtr->tkwin, &savedOptions, NULL) != TCL_OK) {
		continue;
	    }
	} else {
	    /*
	     * Second pass: restore options to old values.
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183






1184
1185
1186



1187
1188
1189
1190
1191
1192
1193
1191
1192
1193
1194
1195
1196
1197




1198
1199
1200
1201
1202
1203



1204
1205
1206
1207
1208
1209
1210
1211
1212
1213







-
-
-
-
+
+
+
+
+
+
-
-
-
+
+
+







	}
	if (entryPtr->insertBorderWidth > entryPtr->insertWidth/2) {
	    entryPtr->insertBorderWidth = entryPtr->insertWidth/2;
	}

	if (entryPtr->type == TK_SPINBOX) {
	    if (sbPtr->fromValue > sbPtr->toValue) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"-to value must be greater than -from value",
			-1));
		Tcl_SetErrorCode(interp, "TK", "SPINBOX", "RANGE_SANITY",
                /*
                 * Swap -from and -to values.
                 */

                double tmpFromTo = sbPtr->fromValue;

			NULL);
		continue;
	    }
                sbPtr->fromValue = sbPtr->toValue;
                sbPtr->toValue = tmpFromTo;
            }

	    if (sbPtr->reqFormat && (oldFormat != sbPtr->reqFormat)) {
		/*
		 * Make sure that the given format is somewhat correct, and
		 * calculate the minimum space we'll need for the values as
		 * strings.
		 */
1216
1217
1218
1219
1220
1221
1222
1223

1224
1225
1226
1227
1228
1229
1230
1236
1237
1238
1239
1240
1241
1242

1243
1244
1245
1246
1247
1248
1249
1250







-
+







		    formatSpace = min + 1;
		} else {
		    goto badFormatOpt;
		}
		if (formatSpace < TCL_DOUBLE_SPACE) {
		    formatSpace = TCL_DOUBLE_SPACE;
		}
		sbPtr->formatBuf = ckrealloc(sbPtr->formatBuf, formatSpace);
		sbPtr->formatBuf = (char *)ckrealloc(sbPtr->formatBuf, formatSpace);

		/*
		 * We perturb the value of oldFrom to allow us to go into the
		 * branch below that will reformat the displayed value.
		 */

		oldFrom = sbPtr->fromValue - 1;
1239
1240
1241
1242
1243
1244
1245
1246

1247
1248
1249
1250
1251
1252
1253
1259
1260
1261
1262
1263
1264
1265

1266
1267
1268
1269
1270
1271
1272
1273







-
+







		    Tcl_DecrRefCount(sbPtr->listObj);
		}
		sbPtr->listObj = NULL;
		if (sbPtr->valueStr != NULL) {
		    Tcl_Obj *newObjPtr;
		    int nelems;

		    newObjPtr = Tcl_NewStringObj(sbPtr->valueStr, -1);
		    newObjPtr = Tcl_NewStringObj(sbPtr->valueStr, TCL_INDEX_NONE);
		    if (Tcl_ListObjLength(interp, newObjPtr, &nelems)
			    != TCL_OK) {
			valuesChanged = -1;
			continue;
		    }
		    sbPtr->listObj = newObjPtr;
		    Tcl_IncrRefCount(sbPtr->listObj);
1274
1275
1276
1277
1278
1279
1280
1281

1282
1283
1284
1285
1286
1287
1288
1294
1295
1296
1297
1298
1299
1300

1301
1302
1303
1304
1305
1306
1307
1308







-
+








	/*
	 * Claim the selection if we've suddenly started exporting it.
	 */

	if (entryPtr->exportSelection && (!oldExport)
		&& (!Tcl_IsSafe(entryPtr->interp))
		&& (entryPtr->selectFirst != -1)
		&& (entryPtr->selectFirst != TCL_INDEX_NONE)
		&& !(entryPtr->flags & GOT_SELECTION)) {
	    Tk_OwnSelection(entryPtr->tkwin, XA_PRIMARY, EntryLostSelection,
		    entryPtr);
	    entryPtr->flags |= GOT_SELECTION;
	}

	/*
1430
1431
1432
1433
1434
1435
1436
1437

1438
1439
1440
1441
1442
1443
1444
1450
1451
1452
1453
1454
1455
1456

1457
1458
1459
1460
1461
1462
1463
1464







-
+







    ClientData instanceData)	/* Information about widget. */
{
    XGCValues gcValues;
    GC gc = NULL;
    unsigned long mask;
    Tk_3DBorder border;
    XColor *colorPtr;
    Entry *entryPtr = instanceData;
    Entry *entryPtr = (Entry *)instanceData;

    entryPtr->avgWidth = Tk_TextWidth(entryPtr->tkfont, "0", 1);
    if (entryPtr->avgWidth == 0) {
	entryPtr->avgWidth = 1;
    }

    if (entryPtr->type == TK_SPINBOX) {
1482
1483
1484
1485
1486
1487
1488










1489
1490
1491


1492
1493
1494
1495
1496
1497
1498
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530







+
+
+
+
+
+
+
+
+
+



+
+







    gcValues.graphics_exposures = False;
    mask = GCForeground | GCFont | GCGraphicsExposures;
    gc = Tk_GetGC(entryPtr->tkwin, mask, &gcValues);
    if (entryPtr->textGC != NULL) {
	Tk_FreeGC(entryPtr->display, entryPtr->textGC);
    }
    entryPtr->textGC = gc;

    if (entryPtr->placeholderColorPtr != NULL) {
	gcValues.foreground = entryPtr->placeholderColorPtr->pixel;
    }
    mask = GCForeground | GCFont | GCGraphicsExposures;
    gc = Tk_GetGC(entryPtr->tkwin, mask, &gcValues);
    if (entryPtr->placeholderGC != NULL) {
	Tk_FreeGC(entryPtr->display, entryPtr->placeholderGC);
    }
    entryPtr->placeholderGC = gc;

    if (entryPtr->selFgColorPtr != NULL) {
	gcValues.foreground = entryPtr->selFgColorPtr->pixel;
    } else {
        gcValues.foreground = colorPtr->pixel;
    }
    gcValues.font = Tk_FontId(entryPtr->tkfont);
    mask = GCForeground | GCFont;
    gc = Tk_GetGC(entryPtr->tkwin, mask, &gcValues);
    if (entryPtr->selTextGC != NULL) {
	Tk_FreeGC(entryPtr->display, entryPtr->selTextGC);
    }
1528
1529
1530
1531
1532
1533
1534




1535
1536
1537
1538
1539
1540
1541
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577







+
+
+
+








int
TkpDrawEntryBorderAndFocus(
    Entry *entryPtr,
    Drawable pixmap,
    int isSpinbox)
{
    (void)entryPtr;
    (void)pixmap;
    (void)isSpinbox;

    return 0;
}

/*
 *--------------------------------------------------------------
 *
 * TkpDrawSpinboxButtons --
1554
1555
1556
1557
1558
1559
1560



1561
1562
1563
1564
1565
1566
1567
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606







+
+
+







 */

int
TkpDrawSpinboxButtons(
    Spinbox *sbPtr,
    Pixmap pixmap)
{
    (void)sbPtr;
    (void)pixmap;

    return 0;
}
#endif /* Not MAC_OSX_TK */

/*
 *--------------------------------------------------------------
 *
1578
1579
1580
1581
1582
1583
1584
1585

1586
1587
1588
1589
1590
1591
1592
1617
1618
1619
1620
1621
1622
1623

1624
1625
1626
1627
1628
1629
1630
1631







-
+







 *--------------------------------------------------------------
 */

static void
DisplayEntry(
    ClientData clientData)	/* Information about window. */
{
    Entry *entryPtr = clientData;
    Entry *entryPtr = (Entry *)clientData;
    Tk_Window tkwin = entryPtr->tkwin;
    int baseY, selStartX, selEndX, cursorX;
    int showSelection, xBound;
    Tk_FontMetrics fm;
    Pixmap pixmap;
    Tk_3DBorder border;

1641
1642
1643
1644
1645
1646
1647
1648

1649
1650
1651
1652
1653
1654
1655
1680
1681
1682
1683
1684
1685
1686

1687
1688
1689
1690
1691
1692
1693
1694







-
+







    xBound = Tk_Width(tkwin) - entryPtr->inset - entryPtr->xWidth;
    baseY = (Tk_Height(tkwin) + fm.ascent - fm.descent) / 2;

    /*
     * Hide the selection whenever we don't have the focus, unless we
     * always want to show selection.
     */
    if (TkpAlwaysShowSelection(entryPtr->tkwin)) {
    if (Tk_AlwaysShowSelection(entryPtr->tkwin)) {
	showSelection = 1;
    } else {
	showSelection = (entryPtr->flags & GOT_FOCUS);
    }

    /*
     * Draw the background in three layers. From bottom to top the layers are:
1666
1667
1668
1669
1670
1671
1672
1673

1674
1675
1676
1677
1678
1679
1680
1705
1706
1707
1708
1709
1710
1711

1712
1713
1714
1715
1716
1717
1718
1719







-
+







    } else {
	border = entryPtr->normalBorder;
    }
    Tk_Fill3DRectangle(tkwin, pixmap, border,
	    0, 0, Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT);

    if (showSelection && (entryPtr->state != STATE_DISABLED)
	    && (entryPtr->selectLast > entryPtr->leftIndex)) {
	    && (entryPtr->selectLast + 1  > entryPtr->leftIndex + 1)) {
	if (entryPtr->selectFirst <= entryPtr->leftIndex) {
	    selStartX = entryPtr->leftX;
	} else {
	    Tk_CharBbox(entryPtr->textLayout, entryPtr->selectFirst,
		    &selStartX, NULL, NULL, NULL);
	    selStartX += entryPtr->layoutX;
	}
1709
1710
1711
1712
1713
1714
1715
1716

1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729


1730
1731


1732
1733

1734
1735
1736
1737



1738


1739
1740
1741
1742









1743
1744
1745
1746
1747
1748
1749
1750
1751




























1752
1753
1754
1755
1756
1757
1758
1748
1749
1750
1751
1752
1753
1754

1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770


1771
1772


1773
1774



1775
1776
1777
1778
1779
1780




1781
1782
1783
1784
1785
1786
1787
1788
1789
1790








1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825







-
+













+
+
-
-
+
+
-
-
+

-
-
-
+
+
+

+
+
-
-
-
-
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    if ((entryPtr->state == STATE_NORMAL) && (entryPtr->flags & GOT_FOCUS)) {
	Tk_CharBbox(entryPtr->textLayout, entryPtr->insertPos, &cursorX, NULL,
		NULL, NULL);
	cursorX += entryPtr->layoutX;
	cursorX -= (entryPtr->insertWidth == 1) ? 1 : (entryPtr->insertWidth)/2;
	Tk_SetCaretPos(entryPtr->tkwin, cursorX, baseY - fm.ascent,
		fm.ascent + fm.descent);
	if (entryPtr->insertPos >= entryPtr->leftIndex && cursorX < xBound) {
	if ((entryPtr->insertPos + 1 >= entryPtr->leftIndex + 1) && cursorX < xBound) {
	    if (entryPtr->flags & CURSOR_ON) {
		Tk_Fill3DRectangle(tkwin, pixmap, entryPtr->insertBorder,
			cursorX, baseY - fm.ascent, entryPtr->insertWidth,
			fm.ascent + fm.descent, entryPtr->insertBorderWidth,
			TK_RELIEF_RAISED);
	    } else if (entryPtr->insertBorder == entryPtr->selBorder) {
		Tk_Fill3DRectangle(tkwin, pixmap, border, cursorX,
			baseY - fm.ascent, entryPtr->insertWidth,
			fm.ascent + fm.descent, 0, TK_RELIEF_FLAT);
	    }
	}
    }

    if ((entryPtr->numChars == 0) && (entryPtr->placeholderChars != 0)) {

    /*
     * Draw the text in two pieces: first the unselected portion, then the
        /*
         * Draw the placeholder text.
     * selected portion on top of it.
     */
         */

    Tk_DrawTextLayout(entryPtr->display, pixmap, entryPtr->textGC,
	    entryPtr->textLayout, entryPtr->layoutX, entryPtr->layoutY,
	    entryPtr->leftIndex, entryPtr->numChars);
        Tk_DrawTextLayout(entryPtr->display, pixmap, entryPtr->placeholderGC,
	    entryPtr->placeholderLayout, entryPtr->placeholderX, entryPtr->layoutY,
	    entryPtr->placeholderLeftIndex, entryPtr->placeholderChars);

    } else {

    if (showSelection && (entryPtr->state != STATE_DISABLED)
	    && (entryPtr->selTextGC != entryPtr->textGC)
	    && (entryPtr->selectFirst < entryPtr->selectLast)) {
	int selFirst;
        if (showSelection && (entryPtr->state != STATE_DISABLED)
	        && (entryPtr->selTextGC != entryPtr->textGC)
	        && (entryPtr->selectFirst + 1 < entryPtr->selectLast + 1)) {

	    /*
	     * Draw the selected and unselected portions separately.
	     */

	    TkSizeT selFirst;

	if (entryPtr->selectFirst < entryPtr->leftIndex) {
	    selFirst = entryPtr->leftIndex;
	} else {
	    selFirst = entryPtr->selectFirst;
	}
	Tk_DrawTextLayout(entryPtr->display, pixmap, entryPtr->selTextGC,
		entryPtr->textLayout, entryPtr->layoutX, entryPtr->layoutY,
		selFirst, entryPtr->selectLast);
	    if (entryPtr->selectFirst + 1 < entryPtr->leftIndex + 1) {
	        selFirst = entryPtr->leftIndex;
	    } else {
	        selFirst = entryPtr->selectFirst;
	    }
	    if (entryPtr->leftIndex < selFirst) {
	        Tk_DrawTextLayout(entryPtr->display, pixmap, entryPtr->textGC,
		        entryPtr->textLayout, entryPtr->layoutX, entryPtr->layoutY,
		        entryPtr->leftIndex, selFirst);
	    }
	    Tk_DrawTextLayout(entryPtr->display, pixmap, entryPtr->selTextGC,
		    entryPtr->textLayout, entryPtr->layoutX, entryPtr->layoutY,
		    selFirst, entryPtr->selectLast);
	    if (entryPtr->selectLast < entryPtr->numChars) {
	        Tk_DrawTextLayout(entryPtr->display, pixmap, entryPtr->textGC,
		        entryPtr->textLayout, entryPtr->layoutX, entryPtr->layoutY,
		        entryPtr->selectLast, entryPtr->numChars);
	    }
        } else {

            /*
             * Draw the entire visible text
             */

	    Tk_DrawTextLayout(entryPtr->display, pixmap, entryPtr->textGC,
		    entryPtr->textLayout, entryPtr->layoutX, entryPtr->layoutY,
		    entryPtr->leftIndex, entryPtr->numChars);
        }
    }

    if (entryPtr->type == TK_SPINBOX) {
	int startx, height, inset, pad, tHeight, xWidth;
	Spinbox *sbPtr = (Spinbox *) entryPtr;

	/*
1901
1902
1903
1904
1905
1906
1907
1908


1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926

1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940

1941
1942
1943

1944
1945
1946
1947
1948




















































1949
1950
1951
1952
1953
1954
1955
1968
1969
1970
1971
1972
1973
1974

1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993

1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007

2008
2009
2010

2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075







-
+
+

















-
+













-
+


-
+





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







 *----------------------------------------------------------------------
 */

static void
EntryComputeGeometry(
    Entry *entryPtr)		/* Widget record for entry. */
{
    int totalLength, overflow, maxOffScreen, rightX;
    int totalLength, overflow, rightX;
    TkSizeT maxOffScreen;
    int height, width, i;
    Tk_FontMetrics fm;
    char *p;

    if (entryPtr->displayString != entryPtr->string) {
	ckfree((char *)entryPtr->displayString);
	entryPtr->displayString = entryPtr->string;
	entryPtr->numDisplayBytes = entryPtr->numBytes;
    }

    /*
     * If we're displaying a special character instead of the value of the
     * entry, recompute the displayString.
     */

    if (entryPtr->showChar != NULL) {
	int ch;
	char buf[4];
	char buf[6];
	int size;

	/*
	 * Normalize the special character so we can safely duplicate it in
	 * the display string. If we didn't do this, then two malformed
	 * characters might end up looking like one valid UTF character in the
	 * resulting string.
	 */

	TkUtfToUniChar(entryPtr->showChar, &ch);
	size = TkUniCharToUtf(ch, buf);

	entryPtr->numDisplayBytes = entryPtr->numChars * size;
	p = ckalloc(entryPtr->numDisplayBytes + 1);
	p = (char *)ckalloc(entryPtr->numDisplayBytes + 1);
	entryPtr->displayString = p;

	for (i = entryPtr->numChars; --i >= 0; ) {
	for (i = entryPtr->numChars; i-- > 0; ) {
	    memcpy(p, buf, size);
	    p += size;
	}
	*p = '\0';
    }

    /* Recompute layout of placeholder text.
     * Only the placeholderX and placeholderLeftIndex value is needed.
     * We use the same font so we can use the layoutY value from below.
     */

    Tk_FreeTextLayout(entryPtr->placeholderLayout);
    if (entryPtr->placeholderString) {
        entryPtr->placeholderChars = strlen(entryPtr->placeholderString);
        entryPtr->placeholderLayout = Tk_ComputeTextLayout(entryPtr->tkfont,
	        entryPtr->placeholderString, entryPtr->placeholderChars, 0,
	        entryPtr->justify, TK_IGNORE_NEWLINES, &totalLength, NULL);
	overflow = totalLength -
	        (Tk_Width(entryPtr->tkwin) - 2*entryPtr->inset - entryPtr->xWidth);
	if (overflow <= 0) {
	    entryPtr->placeholderLeftIndex = 0;
	    if (entryPtr->justify == TK_JUSTIFY_LEFT) {
		entryPtr->placeholderX = entryPtr->inset;
	    } else if (entryPtr->justify == TK_JUSTIFY_RIGHT) {
		entryPtr->placeholderX = Tk_Width(entryPtr->tkwin) - entryPtr->inset
		        - entryPtr->xWidth - totalLength;
	    } else {
		entryPtr->placeholderX = (Tk_Width(entryPtr->tkwin)
		        - entryPtr->xWidth - totalLength)/2;
	    }
    	} else {

	    /*
	     * The whole string can't fit in the window. Compute the maximum
	     * number of characters that may be off-screen to the left without
	     * leaving empty space on the right of the window, then don't let
	     * placeholderLeftIndex be any greater than that.
	     */

	    maxOffScreen = Tk_PointToChar(entryPtr->placeholderLayout, overflow, 0);
	    Tk_CharBbox(entryPtr->placeholderLayout, maxOffScreen,
		&rightX, NULL, NULL, NULL);
	    if (rightX < overflow) {
		maxOffScreen++;
	    }
	    entryPtr->placeholderLeftIndex = maxOffScreen;
	    Tk_CharBbox(entryPtr->placeholderLayout, entryPtr->placeholderLeftIndex, &rightX,
		NULL, NULL, NULL);
	    entryPtr->placeholderX = entryPtr->inset -rightX;
        }
    } else {
        entryPtr->placeholderChars = 0;
        entryPtr->placeholderLayout = Tk_ComputeTextLayout(entryPtr->tkfont,
	        entryPtr->placeholderString, 0, 0,
	        entryPtr->justify, TK_IGNORE_NEWLINES, NULL, NULL);
	entryPtr->placeholderX = entryPtr->inset;
    }

    Tk_FreeTextLayout(entryPtr->textLayout);
    entryPtr->textLayout = Tk_ComputeTextLayout(entryPtr->tkfont,
	    entryPtr->displayString, entryPtr->numChars, 0,
	    entryPtr->justify, TK_IGNORE_NEWLINES, &totalLength, &height);

    entryPtr->layoutY = (Tk_Height(entryPtr->tkwin) - height) / 2;
1985
1986
1987
1988
1989
1990
1991
1992

1993
1994
1995
1996
1997
1998
1999
2105
2106
2107
2108
2109
2110
2111

2112
2113
2114
2115
2116
2117
2118
2119







-
+








	maxOffScreen = Tk_PointToChar(entryPtr->textLayout, overflow, 0);
	Tk_CharBbox(entryPtr->textLayout, maxOffScreen,
		&rightX, NULL, NULL, NULL);
	if (rightX < overflow) {
	    maxOffScreen++;
	}
	if (entryPtr->leftIndex > maxOffScreen) {
	if (entryPtr->leftIndex + 1 > maxOffScreen + 1) {
	    entryPtr->leftIndex = maxOffScreen;
	}
	Tk_CharBbox(entryPtr->textLayout, entryPtr->leftIndex, &rightX,
		NULL, NULL, NULL);
	entryPtr->leftX = entryPtr->inset;
	entryPtr->layoutX = entryPtr->leftX - rightX;
    }
2033
2034
2035
2036
2037
2038
2039
2040

2041
2042
2043
2044
2045
2046
2047

2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059

2060
2061
2062
2063
2064
2065
2066
2153
2154
2155
2156
2157
2158
2159

2160
2161
2162
2163
2164



2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176

2177
2178
2179
2180
2181
2182
2183
2184







-
+




-
-
-
+











-
+







 *
 *----------------------------------------------------------------------
 */

static int
InsertChars(
    Entry *entryPtr,		/* Entry that is to get the new elements. */
    int index,			/* Add the new elements before this character
    TkSizeT index,			/* Add the new elements before this character
				 * index. */
    const char *value)		/* New characters to add (NULL-terminated
				 * string). */
{
    ptrdiff_t byteIndex;
    size_t byteCount, newByteCount;
    int oldChars, charsAdded;
    size_t byteIndex, byteCount, newByteCount, oldChars, charsAdded;
    const char *string;
    char *newStr;

    string = entryPtr->string;
    byteIndex = Tcl_UtfAtIndex(string, index) - string;
    byteCount = strlen(value);
    if (byteCount == 0) {
	return TCL_OK;
    }

    newByteCount = entryPtr->numBytes + byteCount + 1;
    newStr = ckalloc(newByteCount);
    newStr = (char *)ckalloc(newByteCount);
    memcpy(newStr, string, byteIndex);
    strcpy(newStr + byteIndex, value);
    strcpy(newStr + byteIndex + byteCount, string + byteIndex);

    if ((entryPtr->validate == VALIDATE_KEY ||
	    entryPtr->validate == VALIDATE_ALL) &&
	    EntryValidateChange(entryPtr, value, newStr, index,
2078
2079
2080
2081
2082
2083
2084
2085

2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102

2103
2104
2105

2106
2107
2108

2109
2110
2111

2112
2113
2114

2115
2116
2117
2118
2119
2120
2121
2196
2197
2198
2199
2200
2201
2202

2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219

2220
2221
2222

2223
2224
2225

2226
2227
2228

2229
2230
2231

2232
2233
2234
2235
2236
2237
2238
2239







-
+
















-
+


-
+


-
+


-
+


-
+







     * result in actually forming valid UTF-8 sequences; the number of
     * characters added may not be Tcl_NumUtfChars(string, -1), because of
     * context. The actual number of characters added is how many characters
     * are in the string now minus the number that used to be there.
     */

    oldChars = entryPtr->numChars;
    entryPtr->numChars = Tcl_NumUtfChars(newStr, -1);
    entryPtr->numChars = Tcl_NumUtfChars(newStr, TCL_INDEX_NONE);
    charsAdded = entryPtr->numChars - oldChars;
    entryPtr->numBytes += byteCount;

    if (entryPtr->displayString == string) {
	entryPtr->displayString = newStr;
	entryPtr->numDisplayBytes = entryPtr->numBytes;
    }

    /*
     * Inserting characters invalidates all indexes into the string. Touch up
     * the indexes so that they still refer to the same characters (at new
     * positions). When updating the selection end-points, don't include the
     * new text in the selection unless it was completely surrounded by the
     * selection.
     */

    if (entryPtr->selectFirst >= index) {
    if (entryPtr->selectFirst + 1 >= index + 1) {
	entryPtr->selectFirst += charsAdded;
    }
    if (entryPtr->selectLast > index) {
    if (entryPtr->selectLast + 1 > index + 1) {
	entryPtr->selectLast += charsAdded;
    }
    if ((entryPtr->selectAnchor > index) || (entryPtr->selectFirst >= index)) {
    if ((entryPtr->selectAnchor + 1 > index + 1) || (entryPtr->selectFirst + 1 >= index + 1)) {
	entryPtr->selectAnchor += charsAdded;
    }
    if (entryPtr->leftIndex > index) {
    if (entryPtr->leftIndex + 1 > index + 1) {
	entryPtr->leftIndex += charsAdded;
    }
    if (entryPtr->insertPos >= index) {
    if (entryPtr->insertPos + 1 >= index + 1) {
	entryPtr->insertPos += charsAdded;
    }
    return EntryValueChanged(entryPtr, NULL);
}

/*
 *----------------------------------------------------------------------
2134
2135
2136
2137
2138
2139
2140
2141
2142


2143
2144
2145
2146
2147
2148

2149
2150
2151

2152
2153
2154
2155
2156
2157
2158
2159
2160

2161
2162
2163
2164

2165
2166
2167
2168
2169
2170
2171
2252
2253
2254
2255
2256
2257
2258


2259
2260
2261
2262
2263
2264
2265

2266
2267
2268

2269
2270
2271
2272
2273
2274
2275
2276
2277

2278
2279
2280
2281

2282
2283
2284
2285
2286
2287
2288
2289







-
-
+
+





-
+


-
+








-
+



-
+







 *
 *----------------------------------------------------------------------
 */

static int
DeleteChars(
    Entry *entryPtr,		/* Entry widget to modify. */
    int index,			/* Index of first character to delete. */
    int count)			/* How many characters to delete. */
    TkSizeT index,			/* Index of first character to delete. */
    TkSizeT count)			/* How many characters to delete. */
{
    int byteIndex, byteCount, newByteCount;
    const char *string;
    char *newStr, *toDelete;

    if ((index + count) > entryPtr->numChars) {
    if (index + count + 1 > entryPtr->numChars + 1) {
	count = entryPtr->numChars - index;
    }
    if (count <= 0) {
    if ((int)count <= 0) {
	return TCL_OK;
    }

    string = entryPtr->string;
    byteIndex = Tcl_UtfAtIndex(string, index) - string;
    byteCount = Tcl_UtfAtIndex(string + byteIndex, count) - (string+byteIndex);

    newByteCount = entryPtr->numBytes + 1 - byteCount;
    newStr = ckalloc(newByteCount);
    newStr = (char *)ckalloc(newByteCount);
    memcpy(newStr, string, (size_t) byteIndex);
    strcpy(newStr + byteIndex, string + byteIndex + byteCount);

    toDelete = ckalloc(byteCount + 1);
    toDelete = (char *)ckalloc(byteCount + 1);
    memcpy(toDelete, string + byteIndex, (size_t) byteCount);
    toDelete[byteCount] = '\0';

    if ((entryPtr->validate == VALIDATE_KEY ||
	    entryPtr->validate == VALIDATE_ALL) &&
	    EntryValidateChange(entryPtr, toDelete, newStr, index,
		    VALIDATE_DELETE) != TCL_OK) {
2187
2188
2189
2190
2191
2192
2193
2194
2195


2196
2197
2198
2199
2200
2201
2202


2203
2204
2205
2206
2207
2208
2209
2210



2211
2212
2213


2214
2215
2216
2217
2218
2219
2220


2221
2222
2223
2224
2225
2226
2227


2228
2229
2230
2231
2232
2233
2234
2305
2306
2307
2308
2309
2310
2311


2312
2313
2314
2315
2316
2317
2318


2319
2320
2321
2322
2323
2324
2325



2326
2327
2328
2329


2330
2331
2332
2333
2334
2335
2336


2337
2338
2339
2340
2341
2342
2343


2344
2345
2346
2347
2348
2349
2350
2351
2352







-
-
+
+





-
-
+
+





-
-
-
+
+
+

-
-
+
+





-
-
+
+





-
-
+
+








    /*
     * Deleting characters results in the remaining characters being
     * renumbered. Update the various indexes into the string to reflect this
     * change.
     */

    if (entryPtr->selectFirst >= index) {
	if (entryPtr->selectFirst >= (index + count)) {
    if (entryPtr->selectFirst + 1 >= index + 1) {
	if (entryPtr->selectFirst + 1 >= index + count + 1) {
	    entryPtr->selectFirst -= count;
	} else {
	    entryPtr->selectFirst = index;
	}
    }
    if (entryPtr->selectLast >= index) {
	if (entryPtr->selectLast >= (index + count)) {
    if (entryPtr->selectLast + 1 >= index + 1) {
	if (entryPtr->selectLast + 1 >= index + count + 1) {
	    entryPtr->selectLast -= count;
	} else {
	    entryPtr->selectLast = index;
	}
    }
    if (entryPtr->selectLast <= entryPtr->selectFirst) {
	entryPtr->selectFirst = -1;
	entryPtr->selectLast = -1;
    if (entryPtr->selectLast + 1 <= entryPtr->selectFirst + 1) {
	entryPtr->selectFirst = TCL_INDEX_NONE;
	entryPtr->selectLast = TCL_INDEX_NONE;
    }
    if (entryPtr->selectAnchor >= index) {
	if (entryPtr->selectAnchor >= (index+count)) {
    if (entryPtr->selectAnchor + 1 >= index + 1) {
	if (entryPtr->selectAnchor + 1 >= index + count + 1) {
	    entryPtr->selectAnchor -= count;
	} else {
	    entryPtr->selectAnchor = index;
	}
    }
    if (entryPtr->leftIndex > index) {
	if (entryPtr->leftIndex >= (index + count)) {
    if (entryPtr->leftIndex + 1 > index + 1) {
	if (entryPtr->leftIndex + 1 >= index + count + 1) {
	    entryPtr->leftIndex -= count;
	} else {
	    entryPtr->leftIndex = index;
	}
    }
    if (entryPtr->insertPos >= index) {
	if (entryPtr->insertPos >= (index + count)) {
    if (entryPtr->insertPos + 1 >= index + 1) {
	if (entryPtr->insertPos + 1 >= index + count + 1) {
	    entryPtr->insertPos -= count;
	} else {
	    entryPtr->insertPos = index;
	}
    }
    return EntryValueChanged(entryPtr, NULL);
}
2343
2344
2345
2346
2347
2348
2349
2350

2351
2352
2353
2354
2355
2356
2357
2461
2462
2463
2464
2465
2466
2467

2468
2469
2470
2471
2472
2473
2474
2475







-
+







    } else {
	/*
	 * If we validate, we create a copy of the value, as it may point to
	 * volatile memory, like the value of the -textvar which may get freed
	 * during validation
	 */

	char *tmp = ckalloc(valueLen + 1);
	char *tmp = (char *)ckalloc(valueLen + 1);

	strcpy(tmp, value);
	value = tmp;
	malloced = 1;

	entryPtr->flags |= VALIDATE_VAR;
	(void) EntryValidateChange(entryPtr, NULL, value, -1,
2372
2373
2374
2375
2376
2377
2378
2379

2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396





2397
2398
2399
2400
2401


2402
2403
2404
2405
2406
2407

2408
2409
2410
2411
2412
2413
2414
2490
2491
2492
2493
2494
2495
2496

2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509





2510
2511
2512
2513
2514
2515
2516
2517


2518
2519
2520
2521
2522
2523
2524

2525
2526
2527
2528
2529
2530
2531
2532







-
+












-
-
-
-
-
+
+
+
+
+



-
-
+
+





-
+








    oldSource = entryPtr->string;
    ckfree((char *)entryPtr->string);

    if (malloced) {
	entryPtr->string = value;
    } else {
	char *tmp = ckalloc(valueLen + 1);
	char *tmp = (char *)ckalloc(valueLen + 1);

	strcpy(tmp, value);
	entryPtr->string = tmp;
    }
    entryPtr->numBytes = valueLen;
    entryPtr->numChars = Tcl_NumUtfChars(value, valueLen);

    if (entryPtr->displayString == oldSource) {
	entryPtr->displayString = entryPtr->string;
	entryPtr->numDisplayBytes = entryPtr->numBytes;
    }

    if (entryPtr->selectFirst >= 0) {
	if (entryPtr->selectFirst >= entryPtr->numChars) {
	    entryPtr->selectFirst = -1;
	    entryPtr->selectLast = -1;
	} else if (entryPtr->selectLast > entryPtr->numChars) {
    if (entryPtr->selectFirst != TCL_INDEX_NONE) {
	if (entryPtr->selectFirst + 1 >= entryPtr->numChars + 1) {
	    entryPtr->selectFirst = TCL_INDEX_NONE;
	    entryPtr->selectLast = TCL_INDEX_NONE;
	} else if (entryPtr->selectLast + 1 > entryPtr->numChars + 1) {
	    entryPtr->selectLast = entryPtr->numChars;
	}
    }
    if (entryPtr->leftIndex >= entryPtr->numChars) {
	if (entryPtr->numChars > 0) {
    if (entryPtr->leftIndex + 1 >= entryPtr->numChars + 1) {
	if (entryPtr->numChars + 1 > 1) {
	    entryPtr->leftIndex = entryPtr->numChars - 1;
	} else {
	    entryPtr->leftIndex = 0;
	}
    }
    if (entryPtr->insertPos > entryPtr->numChars) {
    if (entryPtr->insertPos + 1 > entryPtr->numChars + 1) {
	entryPtr->insertPos = entryPtr->numChars;
    }

    entryPtr->flags |= UPDATE_SCROLLBAR;
    EntryComputeGeometry(entryPtr);
    EventuallyRedraw(entryPtr);
}
2432
2433
2434
2435
2436
2437
2438
2439

2440
2441
2442

2443
2444
2445
2446
2447
2448
2449
2550
2551
2552
2553
2554
2555
2556

2557
2558
2559

2560
2561
2562
2563
2564
2565
2566
2567







-
+


-
+







 */

static void
EntryEventProc(
    ClientData clientData,	/* Information about window. */
    XEvent *eventPtr)		/* Information about event. */
{
    Entry *entryPtr = clientData;
    Entry *entryPtr = (Entry *)clientData;

    if ((entryPtr->type == TK_SPINBOX) && (eventPtr->type == MotionNotify)) {
	Spinbox *sbPtr = clientData;
	Spinbox *sbPtr = (Spinbox *)clientData;
	int elem;

	elem = GetSpinboxElement(sbPtr, eventPtr->xmotion.x,
		eventPtr->xmotion.y);
	if (elem != sbPtr->curElement) {
	    Tk_Cursor cursor;

2513
2514
2515
2516
2517
2518
2519
2520

2521
2522
2523
2524
2525
2526
2527
2631
2632
2633
2634
2635
2636
2637

2638
2639
2640
2641
2642
2643
2644
2645







-
+







 *----------------------------------------------------------------------
 */

static void
EntryCmdDeletedProc(
    ClientData clientData)	/* Pointer to widget record for widget. */
{
    Entry *entryPtr = clientData;
    Entry *entryPtr = (Entry *)clientData;

    /*
     * This function could be invoked either because the window was destroyed
     * and the command was then deleted (in which case tkwin is NULL) or
     * because the command was deleted, and then this function destroys the
     * widget.
     */
2553
2554
2555
2556
2557
2558
2559
2560

2561

2562
2563













2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585

2586
2587
2588
2589
2590
2591
2592
2671
2672
2673
2674
2675
2676
2677

2678
2679
2680


2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701






2702
2703
2704
2705
2706
2707
2708

2709
2710
2711
2712
2713
2714
2715
2716







-
+

+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+








-
-
-
-
-
-







-
+








static int
GetEntryIndex(
    Tcl_Interp *interp,		/* For error messages. */
    Entry *entryPtr,		/* Entry for which the index is being
				 * specified. */
    Tcl_Obj *indexObj,	/* Specifies character in entryPtr. */
    int *indexPtr)		/* Where to store converted character index */
    TkSizeT *indexPtr)		/* Where to store converted character index */
{
    TkSizeT length, idx;
    const char *string = Tcl_GetString(indexObj);
    size_t length = indexObj->length;
    const char *string;

    if (TCL_OK == TkGetIntForIndex(indexObj, entryPtr->numChars - 1, 1, &idx)) {
	if (idx == TCL_INDEX_NONE) {
	    idx = 0;
	} else if (idx > entryPtr->numChars) {
	    idx = entryPtr->numChars;
	}
	*indexPtr = idx;
	return TCL_OK;
    }

    string = TkGetStringFromObj(indexObj, &length);

    switch (string[0]) {
    case 'a':
	if (strncmp(string, "anchor", length) != 0) {
	    goto badIndex;
	}
	*indexPtr = entryPtr->selectAnchor;
	break;
    case 'e':
	if (strncmp(string, "end", length) != 0) {
	    goto badIndex;
	}
	*indexPtr = entryPtr->numChars;
	break;
    case 'i':
	if (strncmp(string, "insert", length) != 0) {
	    goto badIndex;
	}
	*indexPtr = entryPtr->insertPos;
	break;
    case 's':
	if (entryPtr->selectFirst < 0) {
	if (entryPtr->selectFirst == TCL_INDEX_NONE) {
	    Tcl_ResetResult(interp);
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "selection isn't in widget %s",
		    Tk_PathName(entryPtr->tkwin)));
	    Tcl_SetErrorCode(interp, "TK",
		    (entryPtr->type == TK_ENTRY) ? "ENTRY" : "SPINBOX",
		    "NO_SELECTION", NULL);
2625
2626
2627
2628
2629
2630
2631
2632

2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655









2656
2657
2658
2659
2660
2661
2662
2749
2750
2751
2752
2753
2754
2755

2756
2757
2758
2759
2760
2761


















2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777







-
+





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+







	/*
	 * Special trick: if the x-position was off-screen to the right, round
	 * the index up to refer to the character just after the last visible
	 * one on the screen. This is needed to enable the last character to
	 * be selected, for example.
	 */

	if (roundUp && (*indexPtr < entryPtr->numChars)) {
	if (roundUp && (*indexPtr + 1 < entryPtr->numChars + 1)) {
	    *indexPtr += 1;
	}
	break;
    }
    default:
	if (Tcl_GetIntFromObj(NULL, indexObj, indexPtr) != TCL_OK) {
	    goto badIndex;
	}
	if (*indexPtr < 0){
	    *indexPtr = 0;
	} else if (*indexPtr > entryPtr->numChars) {
	    *indexPtr = entryPtr->numChars;
	}
    }
    return TCL_OK;

  badIndex:
    Tcl_SetObjResult(interp, Tcl_ObjPrintf("bad %s index \"%s\"",
	    (entryPtr->type == TK_ENTRY) ? "entry" : "spinbox", string));
    Tcl_SetErrorCode(interp, "TK",
	    (entryPtr->type == TK_ENTRY) ? "ENTRY" : "SPINBOX",
	    "BAD_INDEX", NULL);
    return TCL_ERROR;
	  badIndex:
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf("bad %s index \"%s\"",
		    (entryPtr->type == TK_ENTRY) ? "entry" : "spinbox", string));
	    Tcl_SetErrorCode(interp, "TK",
		    (entryPtr->type == TK_ENTRY) ? "ENTRY" : "SPINBOX",
		    "BAD_INDEX", NULL);
	    return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * EntryScanTo --
 *
2673
2674
2675
2676
2677
2678
2679
2680

2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695

2696
2697
2698
2699

2700
2701
2702
2703
2704
2705
2706
2788
2789
2790
2791
2792
2793
2794

2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809

2810
2811
2812
2813

2814
2815
2816
2817
2818
2819
2820
2821







-
+














-
+



-
+







 */

static void
EntryScanTo(
    Entry *entryPtr,		/* Information about widget. */
    int x)			/* X-coordinate to use for scan operation. */
{
    int newLeftIndex;
    TkSizeT newLeftIndex;

    /*
     * Compute new leftIndex for entry by amplifying the difference between
     * the current position and the place where the scan started (the "mark"
     * position). If we run off the left or right side of the entry, then
     * reset the mark point so that the current position continues to
     * correspond to the edge of the window. This means that the picture will
     * start dragging as soon as the mouse reverses direction (without this
     * reset, might have to slide mouse a long ways back before the picture
     * starts moving again).
     */

    newLeftIndex = entryPtr->scanMarkIndex
	    - (10 * (x - entryPtr->scanMarkX)) / entryPtr->avgWidth;
    if (newLeftIndex >= entryPtr->numChars) {
    if (newLeftIndex + 1 >= entryPtr->numChars + 1) {
	newLeftIndex = entryPtr->scanMarkIndex = entryPtr->numChars - 1;
	entryPtr->scanMarkX = x;
    }
    if (newLeftIndex < 0) {
    if (newLeftIndex == TCL_INDEX_NONE) {
	newLeftIndex = entryPtr->scanMarkIndex = 0;
	entryPtr->scanMarkX = x;
    }

    if (newLeftIndex != entryPtr->leftIndex) {
	entryPtr->leftIndex = newLeftIndex;
	entryPtr->flags |= UPDATE_SCROLLBAR;
2729
2730
2731
2732
2733
2734
2735
2736

2737
2738
2739

2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756

2757
2758
2759

2760
2761
2762
2763
2764
2765
2766


2767
2768
2769
2770
2771
2772
2773
2844
2845
2846
2847
2848
2849
2850

2851
2852
2853

2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870

2871
2872
2873

2874
2875
2876
2877
2878
2879


2880
2881
2882
2883
2884
2885
2886
2887
2888







-
+


-
+
















-
+


-
+





-
-
+
+







 *
 *----------------------------------------------------------------------
 */

static void
EntrySelectTo(
    Entry *entryPtr,		/* Information about widget. */
    int index)			/* Character index of element that is to
    TkSizeT index)			/* Character index of element that is to
				 * become the "other" end of the selection. */
{
    int newFirst, newLast;
    TkSizeT newFirst, newLast;

    /*
     * Grab the selection if we don't own it already.
     */

    if (!(entryPtr->flags & GOT_SELECTION) && (entryPtr->exportSelection)
	    && (!Tcl_IsSafe(entryPtr->interp))) {
	Tk_OwnSelection(entryPtr->tkwin, XA_PRIMARY, EntryLostSelection,
		entryPtr);
	entryPtr->flags |= GOT_SELECTION;
    }

    /*
     * Pick new starting and ending points for the selection.
     */

    if (entryPtr->selectAnchor > entryPtr->numChars) {
    if (entryPtr->selectAnchor + 1 > entryPtr->numChars + 1) {
	entryPtr->selectAnchor = entryPtr->numChars;
    }
    if (entryPtr->selectAnchor <= index) {
    if (entryPtr->selectAnchor + 1 <= index + 1) {
	newFirst = entryPtr->selectAnchor;
	newLast = index;
    } else {
	newFirst = index;
	newLast = entryPtr->selectAnchor;
	if (newLast < 0) {
	    newFirst = newLast = -1;
	if (newLast == TCL_INDEX_NONE) {
	    newFirst = newLast = TCL_INDEX_NONE;
	}
    }
    if ((entryPtr->selectFirst == newFirst)
	    && (entryPtr->selectLast == newLast)) {
	return;
    }
    entryPtr->selectFirst = newFirst;
2792
2793
2794
2795
2796
2797
2798
2799

2800
2801
2802

2803
2804
2805

2806
2807
2808
2809


2810
2811
2812
2813

2814
2815
2816
2817
2818
2819
2820



2821
2822
2823
2824
2825
2826
2827
2828

2829
2830
2831
2832
2833
2834
2835
2907
2908
2909
2910
2911
2912
2913

2914
2915
2916

2917
2918
2919

2920
2921
2922


2923
2924
2925
2926
2927

2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942




2943
2944
2945
2946
2947
2948
2949
2950







-
+


-
+


-
+


-
-
+
+



-
+







+
+
+




-
-
-
-
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
static TkSizeT
EntryFetchSelection(
    ClientData clientData,	/* Information about entry widget. */
    int offset,			/* Byte offset within selection of first
    TkSizeT offset,			/* Byte offset within selection of first
				 * character to be returned. */
    char *buffer,		/* Location in which to place selection. */
    int maxBytes)		/* Maximum number of bytes to place at buffer,
    TkSizeT maxBytes)		/* Maximum number of bytes to place at buffer,
				 * not including terminating NUL character. */
{
    Entry *entryPtr = clientData;
    int byteCount;
    Entry *entryPtr = (Entry *)clientData;
    TkSizeT byteCount;
    const char *string;
    const char *selStart, *selEnd;

    if ((entryPtr->selectFirst < 0) || (!entryPtr->exportSelection)
    if ((entryPtr->selectFirst == TCL_INDEX_NONE) || (!entryPtr->exportSelection)
	    || Tcl_IsSafe(entryPtr->interp)) {
	return -1;
    }
    string = entryPtr->displayString;
    selStart = Tcl_UtfAtIndex(string, entryPtr->selectFirst);
    selEnd = Tcl_UtfAtIndex(selStart,
	    entryPtr->selectLast - entryPtr->selectFirst);
    if (selEnd <= selStart + offset) {
	return 0;
    }
    byteCount = selEnd - selStart - offset;
    if (byteCount > maxBytes) {
	byteCount = maxBytes;
    }
    if (byteCount <= 0) {
	return 0;
    }
    memcpy(buffer, selStart + offset, (size_t) byteCount);
    memcpy(buffer, selStart + offset, byteCount);
    buffer[byteCount] = '\0';
    return byteCount;
}

/*
 *----------------------------------------------------------------------
 *
2848
2849
2850
2851
2852
2853
2854
2855

2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867


2868
2869
2870


2871
2872
2873
2874
2875
2876
2877
2963
2964
2965
2966
2967
2968
2969

2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980


2981
2982
2983


2984
2985
2986
2987
2988
2989
2990
2991
2992







-
+










-
-
+
+

-
-
+
+







 *----------------------------------------------------------------------
 */

static void
EntryLostSelection(
    ClientData clientData)	/* Information about entry widget. */
{
    Entry *entryPtr = clientData;
    Entry *entryPtr = (Entry *)clientData;

    entryPtr->flags &= ~GOT_SELECTION;

    /*
     * On Windows and Mac systems, we want to remember the selection for the
     * next time the focus enters the window. On Unix, we need to clear the
     * selection since it is always visible.
     * This is controlled by ::tk::AlwaysShowSelection.
     */

    if (TkpAlwaysShowSelection(entryPtr->tkwin)
	    && (entryPtr->selectFirst >= 0) && entryPtr->exportSelection
    if (Tk_AlwaysShowSelection(entryPtr->tkwin)
	    && (entryPtr->selectFirst != TCL_INDEX_NONE) && entryPtr->exportSelection
	    && (!Tcl_IsSafe(entryPtr->interp))) {
	entryPtr->selectFirst = -1;
	entryPtr->selectLast = -1;
	entryPtr->selectFirst = TCL_INDEX_NONE;
	entryPtr->selectLast = TCL_INDEX_NONE;
	EventuallyRedraw(entryPtr);
    }
}

/*
 *----------------------------------------------------------------------
 *
2942
2943
2944
2945
2946
2947
2948
2949

2950
2951
2952
2953
2954
2955
2956
3057
3058
3059
3060
3061
3062
3063

3064
3065
3066
3067
3068
3069
3070
3071







-
+







    if (entryPtr->numChars == 0) {
	*firstPtr = 0.0;
	*lastPtr = 1.0;
    } else {
	charsInWindow = Tk_PointToChar(entryPtr->textLayout,
		Tk_Width(entryPtr->tkwin) - entryPtr->inset
		- entryPtr->xWidth - entryPtr->layoutX - 1, 0);
	if (charsInWindow < entryPtr->numChars) {
	if (charsInWindow < (int)entryPtr->numChars) {
	    charsInWindow++;
	}
	charsInWindow -= entryPtr->leftIndex;
	if (charsInWindow == 0) {
	    charsInWindow = 1;
	}

2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008






3009
3010
3011
3012
3013
3014
3015
3111
3112
3113
3114
3115
3116
3117






3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130







-
-
-
-
-
-
+
+
+
+
+
+








    interp = entryPtr->interp;
    Tcl_Preserve(interp);
    EntryVisibleRange(entryPtr, &first, &last);
    Tcl_PrintDouble(NULL, first, firstStr);
    Tcl_PrintDouble(NULL, last, lastStr);
    Tcl_DStringInit(&buf);
    Tcl_DStringAppend(&buf, entryPtr->scrollCmd, -1);
    Tcl_DStringAppend(&buf, " ", -1);
    Tcl_DStringAppend(&buf, firstStr, -1);
    Tcl_DStringAppend(&buf, " ", -1);
    Tcl_DStringAppend(&buf, lastStr, -1);
    code = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, 0);
    Tcl_DStringAppend(&buf, entryPtr->scrollCmd, TCL_INDEX_NONE);
    Tcl_DStringAppend(&buf, " ", TCL_INDEX_NONE);
    Tcl_DStringAppend(&buf, firstStr, TCL_INDEX_NONE);
    Tcl_DStringAppend(&buf, " ", TCL_INDEX_NONE);
    Tcl_DStringAppend(&buf, lastStr, TCL_INDEX_NONE);
    code = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), TCL_INDEX_NONE, TCL_EVAL_GLOBAL);
    Tcl_DStringFree(&buf);
    if (code != TCL_OK) {
	Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
		"\n    (horizontal scrolling command executed by %s)",
		Tk_PathName(entryPtr->tkwin)));
	Tcl_BackgroundException(interp, code);
    }
3035
3036
3037
3038
3039
3040
3041
3042

3043
3044
3045
3046
3047
3048
3049
3150
3151
3152
3153
3154
3155
3156

3157
3158
3159
3160
3161
3162
3163
3164







-
+







 *----------------------------------------------------------------------
 */

static void
EntryBlinkProc(
    ClientData clientData)	/* Pointer to record describing entry. */
{
    Entry *entryPtr = clientData;
    Entry *entryPtr = (Entry *)clientData;

    if ((entryPtr->state == STATE_DISABLED) ||
	    (entryPtr->state == STATE_READONLY) ||
	    !(entryPtr->flags & GOT_FOCUS) || (entryPtr->insertOffTime == 0)) {
	return;
    }
    if (entryPtr->flags & CURSOR_ON) {
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137

3138


3139
3140
3141
3142
3143
3144
3145
3236
3237
3238
3239
3240
3241
3242

3243
3244
3245
3246
3247
3248
3249
3250

3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261







-








-
+

+
+







 *
 * Side effects:
 *	The text displayed in the entry will change to match the variable.
 *
 *--------------------------------------------------------------
 */

	/* ARGSUSED */
static char *
EntryTextVarProc(
    ClientData clientData,	/* Information about button. */
    Tcl_Interp *interp,		/* Interpreter containing variable. */
    const char *name1,		/* Not used. */
    const char *name2,		/* Not used. */
    int flags)			/* Information about what happened. */
{
    Entry *entryPtr = clientData;
    Entry *entryPtr = (Entry *)clientData;
    const char *value;
    (void)name1;
    (void)name2;

    if (entryPtr->flags & ENTRY_DELETED) {
	/*
	 * Just abort early if we entered here while being deleted.
	 */
	return NULL;
    }
3213
3214
3215
3216
3217
3218
3219
3220
3221


3222
3223
3224

3225
3226
3227

3228
3229
3230
3231
3232
3233
3234
3329
3330
3331
3332
3333
3334
3335


3336
3337
3338
3339

3340
3341
3342

3343
3344
3345
3346
3347
3348
3349
3350







-
-
+
+


-
+


-
+







 *	An error condition may arise
 *
 *--------------------------------------------------------------
 */

static int
EntryValidate(
     register Entry *entryPtr,	/* Entry that needs validation. */
     register char *cmd)	/* Validation command (NULL-terminated
     Entry *entryPtr,	/* Entry that needs validation. */
     char *cmd)	/* Validation command (NULL-terminated
				 * string). */
{
    register Tcl_Interp *interp = entryPtr->interp;
    Tcl_Interp *interp = entryPtr->interp;
    int code, isOK;

    code = Tcl_EvalEx(interp, cmd, -1, TCL_EVAL_GLOBAL | TCL_EVAL_DIRECT);
    code = Tcl_EvalEx(interp, cmd, TCL_INDEX_NONE, TCL_EVAL_GLOBAL | TCL_EVAL_DIRECT);

    /*
     * We accept TCL_OK and TCL_RETURN as valid return codes from the command
     * callback.
     */

    if (code != TCL_OK && code != TCL_RETURN) {
3262
3263
3264
3265
3266
3267
3268
3269

3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280

3281
3282
3283
3284

3285
3286
3287
3288
3289
3290
3291
3292
3293



3294
3295
3296
3297
3298
3299
3300



3301
3302
3303
3304

3305
3306
3307
3308
3309
3310
3311
3378
3379
3380
3381
3382
3383
3384

3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395

3396
3397
3398
3399

3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416



3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431







-
+










-
+



-
+









+
+
+




-
-
-
+
+
+




+







 * EntryValidateChange --
 *
 *	This function is invoked when any character is added or removed from
 *	the entry widget, or a focus has trigerred validation.
 *
 * Results:
 *	TCL_OK if the validatecommand accepts the new string, TCL_ERROR if any
 *	problems occured with validatecommand.
 *	problems occurred with validatecommand.
 *
 * Side effects:
 *	The insertion/deletion may be aborted, and the validatecommand might
 *	turn itself off (if an error or loop condition arises).
 *
 *--------------------------------------------------------------
 */

static int
EntryValidateChange(
     register Entry *entryPtr,	/* Entry that needs validation. */
     Entry *entryPtr,	/* Entry that needs validation. */
     const char *change,	/* Characters to be added/deleted
				 * (NUL-terminated string). */
     const char *newValue,	/* Potential new value of entry string */
     int index,			/* index of insert/delete, -1 otherwise */
     TkSizeT index,			/* index of insert/delete, -1 otherwise */
     int type)			/* forced, delete, insert, focusin or
				 * focusout */
{
    int code, varValidate = (entryPtr->flags & VALIDATE_VAR);
    char *p;
    Tcl_DString script;

    if (entryPtr->validateCmd == NULL ||
	entryPtr->validate == VALIDATE_NONE) {
        if (entryPtr->flags & VALIDATING) {
            entryPtr->flags |= VALIDATE_ABORT;
        }
	return (varValidate ? TCL_ERROR : TCL_OK);
    }

    /*
     * If we're already validating, then we're hitting a loop condition Return
     * and set validate to 0 to disallow further validations and prevent
     * current validation from finishing
     * If we're already validating, then we're hitting a loop condition. Set
     * validate to none to disallow further validations, arrange for flags
     * to prevent current validation from finishing, and return.
     */

    if (entryPtr->flags & VALIDATING) {
	entryPtr->validate = VALIDATE_NONE;
        entryPtr->flags |= VALIDATE_ABORT;
	return (varValidate ? TCL_ERROR : TCL_OK);
    }

    entryPtr->flags |= VALIDATING;

    /*
     * Now form command string and run through the -validatecommand
3319
3320
3321
3322
3323
3324
3325
3326

3327
3328
3329
3330
3331
3332
3333
3439
3440
3441
3442
3443
3444
3445

3446
3447
3448
3449
3450
3451
3452
3453







-
+







    p = Tcl_DStringValue(&script);
    code = EntryValidate(entryPtr, p);
    Tcl_DStringFree(&script);

    /*
     * If e->validate has become VALIDATE_NONE during the validation, or we
     * now have VALIDATE_VAR set (from EntrySetValue) and didn't before, it
     * means that a loop condition almost occured. Do not allow this
     * means that a loop condition almost occurred. Do not allow this
     * validation result to finish.
     */

    if (entryPtr->validate == VALIDATE_NONE
	    || (!varValidate && (entryPtr->flags & VALIDATE_VAR))) {
	code = TCL_ERROR;
    }
3412
3413
3414
3415
3416
3417
3418
3419
3420


3421
3422
3423
3424
3425
3426

3427
3428
3429
3430
3431
3432
3433
3434

3435
3436
3437
3438
3439
3440
3441
3532
3533
3534
3535
3536
3537
3538


3539
3540
3541
3542
3543
3544
3545

3546
3547
3548
3549
3550
3551
3552
3553

3554
3555
3556
3557
3558
3559
3560
3561







-
-
+
+





-
+







-
+







 *	None.
 *
 *--------------------------------------------------------------
 */

static void
ExpandPercents(
     register Entry *entryPtr,	/* Entry that needs validation. */
     register const char *before,
     Entry *entryPtr,	/* Entry that needs validation. */
     const char *before,
				/* Command containing percent expressions to
				 * be replaced. */
     const char *change,	/* Characters to added/deleted (NUL-terminated
				 * string). */
     const char *newValue,	/* Potential new value of entry string */
     int index,			/* index of insert/delete */
     TkSizeT index,			/* index of insert/delete */
     int type,			/* INSERT or DELETE */
     Tcl_DString *dsPtr)	/* Dynamic string in which to append new
				 * command. */
{
    int spaceNeeded, cvtFlags;	/* Used to substitute string as proper Tcl
				 * list element. */
    int number, length;
    register const char *string;
    const char *string;
    int ch;
    char numStorage[2*TCL_INTEGER_SPACE];

    while (1) {
	if (*before == '\0') {
	    break;
	}
3508
3509
3510
3511
3512
3513
3514
3515

3516
3517
3518
3519
3520
3521
3522
3628
3629
3630
3631
3632
3633
3634

3635
3636
3637
3638
3639
3640
3641
3642







-
+







		    number = -1;
		    break;
		}
		sprintf(numStorage, "%d", number);
		string = numStorage;
		break;
	    case 'i':		/* index of insert/delete */
		sprintf(numStorage, "%d", index);
		sprintf(numStorage, "%d", (int)index);
		string = numStorage;
		break;
	    case 'P':		/* 'Peeked' new value of the string */
		string = newValue;
		break;
	    case 's':		/* Current string value of spinbox */
		string = entryPtr->string;
3577
3578
3579
3580
3581
3582
3583
3584

3585
3586
3587
3588
3589
3590


3591
3592
3593

3594
3595
3596
3597
3598
3599
3600
3697
3698
3699
3700
3701
3702
3703

3704
3705
3706
3707
3708


3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721







-
+




-
-
+
+



+







 *	See the user documentation.
 *
 *--------------------------------------------------------------
 */

int
Tk_SpinboxObjCmd(
    ClientData clientData,	/* NULL. */
    ClientData dummy,	/* NULL. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    register Entry *entryPtr;
    register Spinbox *sbPtr;
    Entry *entryPtr;
    Spinbox *sbPtr;
    Tk_OptionTable optionTable;
    Tk_Window tkwin;
    char *tmp;
    (void)dummy;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "pathName ?-option value ...?");
	return TCL_ERROR;
    }

    tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp),
3613
3614
3615
3616
3617
3618
3619
3620

3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632

3633
3634
3635
3636


3637
3638
3639
3640
3641
3642
3643
3734
3735
3736
3737
3738
3739
3740

3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752

3753
3754
3755


3756
3757
3758
3759
3760
3761
3762
3763
3764







-
+











-
+


-
-
+
+







    /*
     * Initialize the fields of the structure that won't be initialized by
     * ConfigureEntry, or that ConfigureEntry requires to be initialized
     * already (e.g. resource pointers). Only the non-NULL/0 data must be
     * initialized as memset covers the rest.
     */

    sbPtr = ckalloc(sizeof(Spinbox));
    sbPtr = (Spinbox *)ckalloc(sizeof(Spinbox));
    entryPtr			= (Entry *) sbPtr;
    memset(sbPtr, 0, sizeof(Spinbox));

    entryPtr->tkwin		= tkwin;
    entryPtr->display		= Tk_Display(tkwin);
    entryPtr->interp		= interp;
    entryPtr->widgetCmd		= Tcl_CreateObjCommand(interp,
	    Tk_PathName(entryPtr->tkwin), SpinboxWidgetObjCmd, sbPtr,
	    EntryCmdDeletedProc);
    entryPtr->optionTable	= optionTable;
    entryPtr->type		= TK_SPINBOX;
    tmp				= ckalloc(1);
    tmp				= (char *)ckalloc(1);
    tmp[0]			= '\0';
    entryPtr->string		= tmp;
    entryPtr->selectFirst	= -1;
    entryPtr->selectLast	= -1;
    entryPtr->selectFirst	= TCL_INDEX_NONE;
    entryPtr->selectLast	= TCL_INDEX_NONE;

    entryPtr->cursor		= NULL;
    entryPtr->exportSelection	= 1;
    entryPtr->justify		= TK_JUSTIFY_LEFT;
    entryPtr->relief		= TK_RELIEF_FLAT;
    entryPtr->state		= STATE_NORMAL;
    entryPtr->displayString	= entryPtr->string;
3652
3653
3654
3655
3656
3657
3658
3659

3660
3661


3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678

3679
3680
3681
3682
3683
3684
3685
3686
3687

3688
3689
3690
3691
3692
3693
3694
3773
3774
3775
3776
3777
3778
3779

3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800

3801
3802
3803
3804
3805
3806
3807
3808
3809

3810
3811
3812
3813
3814
3815
3816
3817







-
+


+
+
















-
+








-
+







    sbPtr->curElement		= SEL_NONE;
    sbPtr->bCursor		= NULL;
    sbPtr->repeatDelay		= 400;
    sbPtr->repeatInterval	= 100;
    sbPtr->fromValue		= 0.0;
    sbPtr->toValue		= 100.0;
    sbPtr->increment		= 1.0;
    sbPtr->formatBuf		= ckalloc(TCL_DOUBLE_SPACE);
    sbPtr->formatBuf		= (char *)ckalloc(TCL_DOUBLE_SPACE);
    sbPtr->bdRelief		= TK_RELIEF_FLAT;
    sbPtr->buRelief		= TK_RELIEF_FLAT;

    entryPtr->placeholderGC	= NULL;

    /*
     * Keep a hold of the associated tkwin until we destroy the spinbox,
     * otherwise Tk might free it while we still need it.
     */

    Tcl_Preserve(entryPtr->tkwin);

    Tk_SetClass(entryPtr->tkwin, "Spinbox");
    Tk_SetClassProcs(entryPtr->tkwin, &entryClass, entryPtr);
    Tk_CreateEventHandler(entryPtr->tkwin,
	    PointerMotionMask|ExposureMask|StructureNotifyMask|FocusChangeMask,
	    EntryEventProc, entryPtr);
    Tk_CreateSelHandler(entryPtr->tkwin, XA_PRIMARY, XA_STRING,
	    EntryFetchSelection, entryPtr, XA_STRING);

    if (Tk_InitOptions(interp, (char *) sbPtr, optionTable, tkwin)
    if (Tk_InitOptions(interp, sbPtr, optionTable, tkwin)
	    != TCL_OK) {
	Tk_DestroyWindow(entryPtr->tkwin);
	return TCL_ERROR;
    }
    if (ConfigureEntry(interp, entryPtr, objc-2, objv+2) != TCL_OK) {
	goto error;
    }

    Tcl_SetObjResult(interp, TkNewWindowObj(entryPtr->tkwin));
    Tcl_SetObjResult(interp, Tk_NewWindowObj(entryPtr->tkwin));
    return TCL_OK;

  error:
    Tk_DestroyWindow(entryPtr->tkwin);
    return TCL_ERROR;
}

3713
3714
3715
3716
3717
3718
3719
3720
3721


3722
3723
3724
3725
3726
3727
3728
3836
3837
3838
3839
3840
3841
3842


3843
3844
3845
3846
3847
3848
3849
3850
3851







-
-
+
+







static int
SpinboxWidgetObjCmd(
    ClientData clientData,	/* Information about spinbox widget. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Entry *entryPtr = clientData;
    Spinbox *sbPtr = clientData;
    Entry *entryPtr = (Entry *)clientData;
    Spinbox *sbPtr = (Spinbox *)clientData;
    int cmdIndex, selIndex, result;
    Tcl_Obj *objPtr;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
	return TCL_ERROR;
    }
3737
3738
3739
3740
3741
3742
3743

3744

3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755

3756
3757
3758
3759
3760
3761
3762




3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773

3774
3775
3776
3777
3778
3779
3780
3781
3782
3783

3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796


3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814

3815
3816
3817
3818
3819
3820
3821
3860
3861
3862
3863
3864
3865
3866
3867

3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878

3879
3880
3881
3882




3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896

3897
3898
3899
3900
3901
3902
3903
3904
3905
3906

3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919

3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938

3939
3940
3941
3942
3943
3944
3945
3946







+
-
+










-
+



-
-
-
-
+
+
+
+










-
+









-
+












-
+
+

















-
+







    if (result != TCL_OK) {
	return result;
    }

    Tcl_Preserve(entryPtr);
    switch ((enum sbCmd) cmdIndex) {
    case SB_CMD_BBOX: {
	TkSizeT index;
	int index, x, y, width, height;
	int x, y, width, height;
	Tcl_Obj *bbox[4];

	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "index");
	    goto error;
	}
	if (GetEntryIndex(interp, entryPtr, objv[2],
		&index) != TCL_OK) {
	    goto error;
	}
	if ((index == entryPtr->numChars) && (index > 0)) {
	if ((index == entryPtr->numChars) && (index + 1 > 1)) {
	    index--;
	}
	Tk_CharBbox(entryPtr->textLayout, index, &x, &y, &width, &height);
	bbox[0] = Tcl_NewIntObj(x + entryPtr->layoutX);
	bbox[1] = Tcl_NewIntObj(y + entryPtr->layoutY);
	bbox[2] = Tcl_NewIntObj(width);
	bbox[3] = Tcl_NewIntObj(height);
	bbox[0] = Tcl_NewWideIntObj(x + entryPtr->layoutX);
	bbox[1] = Tcl_NewWideIntObj(y + entryPtr->layoutY);
	bbox[2] = Tcl_NewWideIntObj(width);
	bbox[3] = Tcl_NewWideIntObj(height);
	Tcl_SetObjResult(interp, Tcl_NewListObj(4, bbox));
	break;
    }

    case SB_CMD_CGET:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "option");
	    goto error;
	}

	objPtr = Tk_GetOptionValue(interp, (char *) entryPtr,
	objPtr = Tk_GetOptionValue(interp, entryPtr,
		entryPtr->optionTable, objv[2], entryPtr->tkwin);
	if (objPtr == NULL) {
	    goto error;
	}
	Tcl_SetObjResult(interp, objPtr);
	break;

    case SB_CMD_CONFIGURE:
	if (objc <= 3) {
	    objPtr = Tk_GetOptionInfo(interp, (char *) entryPtr,
	    objPtr = Tk_GetOptionInfo(interp, entryPtr,
		    entryPtr->optionTable, (objc == 3) ? objv[2] : NULL,
		    entryPtr->tkwin);
	    if (objPtr == NULL) {
		goto error;
	    }
	    Tcl_SetObjResult(interp, objPtr);
	} else {
	    result = ConfigureEntry(interp, entryPtr, objc-2, objv+2);
	}
	break;

    case SB_CMD_DELETE: {
	int first, last, code;
	TkSizeT first, last;
	int code;

	if ((objc < 3) || (objc > 4)) {
	    Tcl_WrongNumArgs(interp, 2, objv, "firstIndex ?lastIndex?");
	    goto error;
	}
	if (GetEntryIndex(interp, entryPtr, objv[2],
		&first) != TCL_OK) {
	    goto error;
	}
	if (objc == 3) {
	    last = first + 1;
	} else {
	    if (GetEntryIndex(interp, entryPtr, objv[3],
		    &last) != TCL_OK) {
		goto error;
	    }
	}
	if ((last >= first) && (entryPtr->state == STATE_NORMAL)) {
	if ((last + 1 >= first + 1) && (entryPtr->state == STATE_NORMAL)) {
	    code = DeleteChars(entryPtr, first, last - first);
            if (code != TCL_OK) {
                goto error;
            }
	}
	break;
    }
3856
3857
3858
3859
3860
3861
3862
3863

3864
3865
3866
3867
3868
3869
3870
3871
3872
3873

3874
3875
3876
3877

3878

3879
3880
3881
3882
3883
3884
3885
3981
3982
3983
3984
3985
3986
3987

3988
3989
3990
3991
3992
3993
3994
3995
3996
3997

3998
3999
4000
4001
4002
4003

4004
4005
4006
4007
4008
4009
4010
4011







-
+









-
+




+
-
+







	    Tcl_SetObjResult(interp,
		    Tcl_NewStringObj(selElementNames[elem], -1));
	}
	break;
    }

    case SB_CMD_INDEX: {
	int index;
	TkSizeT index;

	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "string");
	    goto error;
	}
	if (GetEntryIndex(interp, entryPtr, objv[2],
		&index) != TCL_OK) {
	    goto error;
	}
	Tcl_SetObjResult(interp, Tcl_NewIntObj(index));
	Tcl_SetObjResult(interp, TkNewIndexObj(index));
	break;
    }

    case SB_CMD_INSERT: {
	TkSizeT index;
	int index, code;
	int code;

	if (objc != 4) {
	    Tcl_WrongNumArgs(interp, 2, objv, "index text");
	    goto error;
	}
	if (GetEntryIndex(interp, entryPtr, objv[2],
		&index) != TCL_OK) {
3939
3940
3941
3942
3943
3944
3945
3946

3947
3948
3949
3950
3951
3952
3953
4065
4066
4067
4068
4069
4070
4071

4072
4073
4074
4075
4076
4077
4078
4079







-
+







		    minorCmd, NULL);
	    goto error;
	}
	break;
    }

    case SB_CMD_SELECTION: {
	int index, index2;
	TkSizeT index, index2;

	if (objc < 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "option ?index?");
	    goto error;
	}

	/*
3977
3978
3979
3980
3981
3982
3983
3984
3985


3986
3987
3988
3989

3990
3991

3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010



4011
4012
4013
4014
4015
4016
4017
4103
4104
4105
4106
4107
4108
4109


4110
4111
4112
4113
4114

4115
4116

4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133



4134
4135
4136
4137
4138
4139
4140
4141
4142
4143







-
-
+
+



-
+

-
+
















-
-
-
+
+
+







		Tcl_WrongNumArgs(interp, 3, objv, "index");
		goto error;
	    }
	    if (GetEntryIndex(interp, entryPtr,
		    objv[3], &index) != TCL_OK) {
		goto error;
	    }
	    if (entryPtr->selectFirst >= 0) {
		int half1, half2;
	    if (entryPtr->selectFirst != TCL_INDEX_NONE) {
		TkSizeT half1, half2;

		half1 = (entryPtr->selectFirst + entryPtr->selectLast)/2;
		half2 = (entryPtr->selectFirst + entryPtr->selectLast + 1)/2;
		if (index < half1) {
		if (index + 1 < half1 + 1) {
		    entryPtr->selectAnchor = entryPtr->selectLast;
		} else if (index > half2) {
		} else if (index + 1 > half2 + 1) {
		    entryPtr->selectAnchor = entryPtr->selectFirst;
		} else {
		    /*
		     * We're at about the halfway point in the selection; just
		     * keep the existing anchor.
		     */
		}
	    }
	    EntrySelectTo(entryPtr, index);
	    break;

	case SB_SEL_CLEAR:
	    if (objc != 3) {
		Tcl_WrongNumArgs(interp, 3, objv, NULL);
		goto error;
	    }
	    if (entryPtr->selectFirst >= 0) {
		entryPtr->selectFirst = -1;
		entryPtr->selectLast = -1;
	    if (entryPtr->selectFirst != TCL_INDEX_NONE) {
		entryPtr->selectFirst = TCL_INDEX_NONE;
		entryPtr->selectLast = TCL_INDEX_NONE;
		EventuallyRedraw(entryPtr);
	    }
	    goto done;

	case SB_SEL_FROM:
	    if (objc != 4) {
		Tcl_WrongNumArgs(interp, 3, objv, "index");
4026
4027
4028
4029
4030
4031
4032
4033

4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051



4052
4053
4054
4055
4056
4057
4058
4152
4153
4154
4155
4156
4157
4158

4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174



4175
4176
4177
4178
4179
4180
4181
4182
4183
4184







-
+















-
-
-
+
+
+








	case SB_SEL_PRESENT:
	    if (objc != 3) {
		Tcl_WrongNumArgs(interp, 3, objv, NULL);
		goto error;
	    }
	    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(
		    entryPtr->selectFirst >= 0));
		    entryPtr->selectFirst != TCL_INDEX_NONE));
	    goto done;

	case SB_SEL_RANGE:
	    if (objc != 5) {
		Tcl_WrongNumArgs(interp, 3, objv, "start end");
		goto error;
	    }
	    if (GetEntryIndex(interp, entryPtr,
		    objv[3], &index) != TCL_OK) {
		goto error;
	    }
	    if (GetEntryIndex(interp, entryPtr,
		    objv[4],& index2) != TCL_OK) {
		goto error;
	    }
	    if (index >= index2) {
		entryPtr->selectFirst = -1;
		entryPtr->selectLast = -1;
	    if (index + 1 >= index2 + 1) {
		entryPtr->selectFirst = TCL_INDEX_NONE;
		entryPtr->selectLast = TCL_INDEX_NONE;
	    } else {
		entryPtr->selectFirst = index;
		entryPtr->selectLast = index2;
	    }
	    if (!(entryPtr->flags & GOT_SELECTION)
		    && entryPtr->exportSelection
		    && (!Tcl_IsSafe(entryPtr->interp))) {
4133
4134
4135
4136
4137
4138
4139
4140

4141
4142
4143
4144
4145
4146
4147
4259
4260
4261
4262
4263
4264
4265

4266
4267
4268
4269
4270
4271
4272
4273







-
+







	}

	Tcl_SetObjResult(interp, Tcl_NewBooleanObj(code == TCL_OK));
	break;
    }

    case SB_CMD_XVIEW: {
	int index;
	TkSizeT index;

	if (objc == 2) {
	    double first, last;
	    Tcl_Obj *span[2];

	    EntryVisibleRange(entryPtr, &first, &last);
	    span[0] = Tcl_NewDoubleObj(first);
4159
4160
4161
4162
4163
4164
4165
4166

4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185

4186
4187
4188

4189
4190
4191
4192
4193
4194
4195
4285
4286
4287
4288
4289
4290
4291

4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310

4311
4312
4313

4314
4315
4316
4317
4318
4319
4320
4321







-
+


















-
+


-
+








	    index = entryPtr->leftIndex;
	    switch (Tk_GetScrollInfoObj(interp, objc, objv, &fraction,
		    &count)) {
	    case TK_SCROLL_ERROR:
		goto error;
	    case TK_SCROLL_MOVETO:
		index = (int) ((fraction * entryPtr->numChars) + 0.5);
		index = ((fraction * entryPtr->numChars) + 0.5);
		break;
	    case TK_SCROLL_PAGES: {
		int charsPerPage;

		charsPerPage = ((Tk_Width(entryPtr->tkwin)
			- 2 * entryPtr->inset - entryPtr->xWidth)
			/ entryPtr->avgWidth) - 2;
		if (charsPerPage < 1) {
		    charsPerPage = 1;
		}
		index += count * charsPerPage;
		break;
	    }
	    case TK_SCROLL_UNITS:
		index += count;
		break;
	    }
	}
	if (index >= entryPtr->numChars) {
	if (index + 1 >= entryPtr->numChars + 1) {
	    index = entryPtr->numChars - 1;
	}
	if (index < 0) {
	if (index == TCL_INDEX_NONE) {
	    index = 0;
	}
	entryPtr->leftIndex = index;
	entryPtr->flags |= UPDATE_SCROLLBAR;
	EntryComputeGeometry(entryPtr);
	EventuallyRedraw(entryPtr);
	break;
4260
4261
4262
4263
4264
4265
4266
4267
4268


4269
4270
4271
4272
4273
4274
4275
4386
4387
4388
4389
4390
4391
4392


4393
4394
4395
4396
4397
4398
4399
4400
4401







-
-
+
+







 *	The widget value may change.
 *
 *--------------------------------------------------------------
 */

static int
SpinboxInvoke(
    register Tcl_Interp *interp,/* Current interpreter. */
    register Spinbox *sbPtr,	/* Spinbox to invoke. */
    Tcl_Interp *interp,/* Current interpreter. */
    Spinbox *sbPtr,	/* Spinbox to invoke. */
    int element)		/* Element to invoke, either the "up" or
				 * "down" button. */
{
    Entry *entryPtr = (Entry *) sbPtr;
    const char *type;
    int code, up;
    Tcl_DString script;
4296
4297
4298
4299
4300
4301
4302

4303

4304
4305
4306
4307
4308
4309

4310
4311
4312

4313
4314
4315
4316
4317
4318
4319
4422
4423
4424
4425
4426
4427
4428
4429

4430
4431
4432
4433
4434
4435

4436
4437
4438

4439
4440
4441
4442
4443
4444
4445
4446







+
-
+





-
+


-
+







	    if (strcmp(Tcl_GetString(objPtr), entryPtr->string)) {
		/*
		 * Somehow the string changed from what we expected, so let's
		 * do a search on the list to see if the current value is
		 * there. If not, move to the first element of the list.
		 */

		int i, listc;
		int i, listc, elemLen, length = entryPtr->numChars;
		TkSizeT elemLen, length = entryPtr->numChars;
		const char *bytes;
		Tcl_Obj **listv;

		Tcl_ListObjGetElements(interp, sbPtr->listObj, &listc, &listv);
		for (i = 0; i < listc; i++) {
		    bytes = Tcl_GetStringFromObj(listv[i], &elemLen);
		    bytes = TkGetStringFromObj(listv[i], &elemLen);
		    if ((length == elemLen) &&
			    (memcmp(bytes, entryPtr->string,
				    (size_t) length) == 0)) {
				    length) == 0)) {
			sbPtr->eIndex = i;
			break;
		    }
		}
	    }
	    if (up) {
		if (++sbPtr->eIndex >= sbPtr->nElements) {
Changes to generic/tkEntry.h.
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
16








-
+







/*
 *  tkEntry.h --
 *
 * 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

#ifndef _TKINT
#include "tkInt.h"
41
42
43
44
45
46
47
48

49
50
51
52
53
54
55

56
57

58
59

60
61
62
63
64
65
66
41
42
43
44
45
46
47

48
49
50
51
52
53
54

55
56

57
58

59
60
61
62
63
64
65
66







-
+






-
+

-
+

-
+








    /*
     * Fields that are set by widget commands other than "configure".
     */

    const char *string;		/* Pointer to storage for string;
				 * NULL-terminated; malloc-ed. */
    int insertPos;		/* Character index before which next typed
    TkSizeT insertPos;		/* Character index before which next typed
				 * character will be inserted. */

    /*
     * Information about what's selected, if any.
     */

    int selectFirst;		/* Character index of first selected character
    TkSizeT selectFirst;		/* Character index of first selected character
				 * (-1 means nothing selected. */
    int selectLast;		/* Character index just after last selected
    TkSizeT selectLast;		/* Character index just after last selected
				 * character (-1 means nothing selected. */
    int selectAnchor;		/* Fixed end of selection (i.e. "select to"
    TkSizeT selectAnchor;		/* Fixed end of selection (i.e. "select to"
				 * operation will use this as one end of the
				 * selection). */

    /*
     * Information for scanning:
     */

124
125
126
127
128
129
130













131
132
133
134
135
136
137
138
139
140
141
142


143
144
145
146
147

148
149
150
151
152
153
154
155
156

157
158
159
160
161
162
163
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153


154
155
156
157
158
159

160
161
162
163
164
165
166
167
168

169
170
171
172
173
174
175
176







+
+
+
+
+
+
+
+
+
+
+
+
+










-
-
+
+




-
+








-
+







				 * scrollbar(s). Malloc'ed. NULL means no
				 * command to issue. */
    char *showChar;		/* Value of -show option. If non-NULL, first
				 * character is used for displaying all
				 * characters in entry. Malloc'ed. This is
				 * only used by the Entry widget. */

    /*
     * Fields used in displaying help text if entry value is empty
     */

    Tk_TextLayout placeholderLayout;/* Cached placeholder text layout information. */
    char *placeholderString;	/* String value of placeholder. */
    TkSizeT placeholderChars;	/* Number of chars in placeholder. */
    XColor *placeholderColorPtr;/* Color value of placeholder foreground. */
    GC placeholderGC;		/* For drawing placeholder text. */
    int placeholderX;		/* Origin for layout. */
    int placeholderLeftIndex;	/* Character index of left-most character
				 * visible in window. */

    /*
     * Fields whose values are derived from the current values of the
     * configuration settings above.
     */

    const char *displayString;	/* String to use when displaying. This may be
				 * a pointer to string, or a pointer to
				 * malloced memory with the same character
				 * length as string but whose characters are
				 * all equal to showChar. */
    int numBytes;		/* Length of string in bytes. */
    int numChars;		/* Length of string in characters. Both string
    TkSizeT numBytes;		/* Length of string in bytes. */
    TkSizeT numChars;		/* Length of string in characters. Both string
				 * and displayString have the same character
				 * length, but may have different byte lengths
				 * due to being made from different UTF-8
				 * characters. */
    int numDisplayBytes;	/* Length of displayString in bytes. */
    TkSizeT numDisplayBytes;	/* Length of displayString in bytes. */
    int inset;			/* Number of pixels on the left and right
				 * sides that are taken up by XPAD,
				 * borderWidth (if any), and highlightWidth
				 * (if any). */
    Tk_TextLayout textLayout;	/* Cached text layout information. */
    int layoutX, layoutY;	/* Origin for layout. */
    int leftX;			/* X position at which character at leftIndex
				 * is drawn (varies depending on justify). */
    int leftIndex;		/* Character index of left-most character
    TkSizeT leftIndex;		/* Character index of left-most character
				 * visible in window. */
    Tcl_TimerToken insertBlinkHandler;
				/* Timer handler used to blink cursor on and
				 * off. */
    GC textGC;			/* For drawing normal text. */
    GC selTextGC;		/* For drawing selected text. */
    GC highlightGC;		/* For drawing traversal highlight. */
Changes to generic/tkError.c.
1
2
3
4
5
6
7
8
9
10


11
12
13
14
15
16
17
1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
16
17








-
-
+
+







/*
 * tkError.c --
 *
 *	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.
 */

#include "tkInt.h"

103
104
105
106
107
108
109
110

111
112
113
114
115
116
117
103
104
105
106
107
108
109

110
111
112
113
114
115
116
117







-
+







	defaultHandler = XSetErrorHandler(ErrorProc);
    }

    /*
     * Create the handler record.
     */

    errorPtr = ckalloc(sizeof(TkErrorHandler));
    errorPtr = (TkErrorHandler *)ckalloc(sizeof(TkErrorHandler));
    errorPtr->dispPtr = dispPtr;
    errorPtr->firstRequest = NextRequest(display);
    errorPtr->lastRequest = (unsigned) -1;
    errorPtr->error = error;
    errorPtr->request = request;
    errorPtr->minorCode = minorCode;
    errorPtr->errorProc = errorProc;
160
161
162
163
164
165
166
167
168

169
170
171

172
173
174
175
176
177
178
179

180
181
182
183
184
185
186
187

188
189
190
191
192
193
194
160
161
162
163
164
165
166


167
168
169

170
171
172
173
174
175
176
177

178
179
180
181
182
183
184
185

186
187
188
189
190
191
192
193







-
-
+


-
+







-
+







-
+







     * collection. To reduce the cost of the cleanup, let a few dead handlers
     * pile up, then clean them all at once. This adds a bit of overhead to
     * errors that might occur while the dead handlers are hanging around, but
     * reduces the overhead of scanning the list to clean up (particularly if
     * there are many handlers that stay around forever).
     */

    dispPtr->deleteCount += 1;
    if (dispPtr->deleteCount >= 10) {
    if (dispPtr->deleteCount++ >= 9) {
	TkErrorHandler *prevPtr;
	TkErrorHandler *nextPtr;
	int lastSerial = LastKnownRequestProcessed(dispPtr->display);
	unsigned long lastSerial = LastKnownRequestProcessed(dispPtr->display);

	/*
	 * Last chance to catch errors for this handler: if no event/error
	 * processing took place to follow up the end of this error handler
	 * we need a round trip with the X server now.
	 */

	if (errorPtr->lastRequest > (unsigned long) lastSerial) {
	if (errorPtr->lastRequest > lastSerial) {
	    XSync(dispPtr->display, False);
	}
	dispPtr->deleteCount = 0;
	errorPtr = dispPtr->errorPtr;
	for (prevPtr = NULL; errorPtr != NULL; errorPtr = nextPtr) {
	    nextPtr = errorPtr->nextPtr;
	    if ((errorPtr->lastRequest != (unsigned long) -1)
		    && (errorPtr->lastRequest <= (unsigned long) lastSerial)) {
		    && (errorPtr->lastRequest <= lastSerial)) {
		if (prevPtr == NULL) {
		    dispPtr->errorPtr = nextPtr;
		} else {
		    prevPtr->nextPtr = nextPtr;
		}
		ckfree(errorPtr);
		continue;
Changes to generic/tkEvent.c.
1
2
3
4
5
6
7
8
9
10




11
12
13
14
15
16








17
18
19
20
21
22
23
1
2
3
4
5
6




7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31






-
-
-
-
+
+
+
+






+
+
+
+
+
+
+
+







/*
 * 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.
 */

#include "tkInt.h"

#ifdef _WIN32
#include "tkWinInt.h"
#elif defined(MAC_OSX_TK)
#include "tkMacOSXInt.h"
#else
#include "tkUnixInt.h"
#endif

/*
 * There's a potential problem if a handler is deleted while it's current
 * (i.e. its function is executing), since Tk_HandleEvent will need to read
 * the handler's "nextPtr" field when the function returns. To handle this
 * problem, structures of the type below indicate the next handler to be
 * processed for any (recursively nested) dispatches in progress. The
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
209
210
211
212
213
214
215

216

217
218
219
220
221
222
223







-

-







static int		InvokeMouseHandlers(TkWindow *winPtr,
			    unsigned long mask, XEvent *eventPtr);
static Window		ParentXId(Display *display, Window w);
static int		RefreshKeyboardMappingIfNeeded(XEvent *eventPtr);
static int		TkXErrorHandler(ClientData clientData,
			    XErrorEvent *errEventPtr);
static int		WindowEventProc(Tcl_Event *evPtr, int flags);
#ifdef TK_USE_INPUT_METHODS
static void		CreateXIC(TkWindow *winPtr);
#endif /* TK_USE_INPUT_METHODS */

/*
 *----------------------------------------------------------------------
 *
 * InvokeFocusHandlers --
 *
 *	Call focus-related code to look at FocusIn, FocusOut, Enter, and Leave
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
317
318
319
320
321
322
323

324
325
326
327
328
329
330







-







 *
 *	Create the X input context for our winPtr.
 *	XIM is only ever enabled on Unix.
 *
 *----------------------------------------------------------------------
 */

#ifdef TK_USE_INPUT_METHODS
static void
CreateXIC(
    TkWindow *winPtr)
{
    TkDisplay *dispPtr = winPtr->dispPtr;
    long im_event_mask = 0L;
    const char *preedit_attname = NULL;
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
363
364
365
366
367
368
369

370
371
372
373
374
375
376







-







     */
    XGetICValues(winPtr->inputContext, XNFilterEvents, &im_event_mask, NULL);
    if ((winPtr->atts.event_mask & im_event_mask) != im_event_mask) {
	winPtr->atts.event_mask |= im_event_mask;
	XSelectInput(winPtr->display, winPtr->window, winPtr->atts.event_mask);
    }
}
#endif

/*
 *----------------------------------------------------------------------
 *
 * GetTkWindowFromXEvent --
 *
 *	Attempt to find which TkWindow is associated with an event. If it
505
506
507
508
509
510
511
512

513
514




515
516
517
518
519
520
521
522
523
524
525
526



527
528
529
530
531



532
533

534
535
536
537
538
539
540
509
510
511
512
513
514
515

516
517

518
519
520
521
522
523
524
525
526
527
528
529
530
531


532
533
534
535
536



537
538
539
540

541
542
543
544
545
546
547
548







-
+

-
+
+
+
+










-
-
+
+
+


-
-
-
+
+
+

-
+







    }
    return 0;
}

/*
 *----------------------------------------------------------------------
 *
 * TkGetButtonMask --
 * Tk_GetButtonMask --
 *
 *	Return the proper Button${n}Mask for the button.
 *	Return the proper Button${n}Mask for the button. Don't care about
 *	Button4 - Button7, because those are not actually buttons: Those
 *	are used for the horizontal or vertical mouse wheels. Button4Mask
 *	and higher is actually used for Button 8 and higher.
 *
 * Results:
 *	A button mask.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static const unsigned long buttonMasks[] = {
    0, Button1Mask, Button2Mask, Button3Mask, Button4Mask, Button5Mask
static const unsigned buttonMasks[] = {
    0, Button1Mask, Button2Mask, Button3Mask, 0, 0, 0, 0, Button4Mask, \
	    Button5Mask, Button6Mask, Button7Mask, Button8Mask, Button9Mask
};

unsigned long
TkGetButtonMask(
    unsigned int button)
unsigned
Tk_GetButtonMask(
    unsigned button)
{
    return (button > Button5) ? 0 : buttonMasks[button];
    return (button > Button9) ? 0 : buttonMasks[button];
}

/*
 *----------------------------------------------------------------------
 *
 * InvokeClientMessageHandlers --
 *
681
682
683
684
685
686
687
688
689


690
691
692
693
694
695
696
697
698
699
700
701
702
703
704

705
706
707
708
709
710
711
689
690
691
692
693
694
695


696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711

712
713
714
715
716
717
718
719







-
-
+
+














-
+







Tk_CreateEventHandler(
    Tk_Window token,		/* Token for window in which to create
				 * handler. */
    unsigned long mask,		/* Events for which proc should be called. */
    Tk_EventProc *proc,		/* Function to call for each selected event */
    ClientData clientData)	/* Arbitrary data to pass to proc. */
{
    register TkEventHandler *handlerPtr;
    register TkWindow *winPtr = (TkWindow *) token;
    TkEventHandler *handlerPtr;
    TkWindow *winPtr = (TkWindow *)token;

    /*
     * Skim through the list of existing handlers to (a) compute the overall
     * event mask for the window (so we can pass this new value to the X
     * system) and (b) see if there's already a handler declared with the same
     * callback and clientData (if so, just change the mask). If no existing
     * handler matches, then create a new handler.
     */

    if (winPtr->handlerList == NULL) {
	/*
	 * No event handlers defined at all, so must create.
	 */

	handlerPtr = ckalloc(sizeof(TkEventHandler));
	handlerPtr = (TkEventHandler *)ckalloc(sizeof(TkEventHandler));
	winPtr->handlerList = handlerPtr;
    } else {
	int found = 0;

	for (handlerPtr = winPtr->handlerList; ;
		handlerPtr = handlerPtr->nextPtr) {
	    if ((handlerPtr->proc == proc)
728
729
730
731
732
733
734
735

736
737
738
739
740
741
742
736
737
738
739
740
741
742

743
744
745
746
747
748
749
750







-
+







	    return;
	}

	/*
	 * No event handler matched, so create a new one.
	 */

	handlerPtr->nextPtr = ckalloc(sizeof(TkEventHandler));
	handlerPtr->nextPtr = (TkEventHandler *)ckalloc(sizeof(TkEventHandler));
	handlerPtr = handlerPtr->nextPtr;
    }

    /*
     * Initialize the new event handler.
     */

771
772
773
774
775
776
777
778
779


780
781
782


783
784
785
786
787
788
789
779
780
781
782
783
784
785


786
787
788


789
790
791
792
793
794
795
796
797







-
-
+
+

-
-
+
+







void
Tk_DeleteEventHandler(
    Tk_Window token,		/* Same as corresponding arguments passed */
    unsigned long mask,		/* previously to Tk_CreateEventHandler. */
    Tk_EventProc *proc,
    ClientData clientData)
{
    register TkEventHandler *handlerPtr;
    register InProgress *ipPtr;
    TkEventHandler *handlerPtr;
    InProgress *ipPtr;
    TkEventHandler *prevPtr;
    register TkWindow *winPtr = (TkWindow *) token;
    ThreadSpecificData *tsdPtr =
    TkWindow *winPtr = (TkWindow *) token;
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    /*
     * Find the event handler to be deleted, or return immediately if it
     * doesn't exist.
     */

847
848
849
850
851
852
853
854

855
856
857

858
859
860
861
862
863
864
855
856
857
858
859
860
861

862
863
864

865
866
867
868
869
870
871
872







-
+


-
+








void
Tk_CreateGenericHandler(
    Tk_GenericProc *proc,	/* Function to call on every event. */
    ClientData clientData)	/* One-word value to pass to proc. */
{
    GenericHandler *handlerPtr;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    handlerPtr = ckalloc(sizeof(GenericHandler));
    handlerPtr = (GenericHandler *)ckalloc(sizeof(GenericHandler));

    handlerPtr->proc		= proc;
    handlerPtr->clientData	= clientData;
    handlerPtr->deleteFlag	= 0;
    handlerPtr->nextPtr		= NULL;
    if (tsdPtr->genericList == NULL) {
	tsdPtr->genericList	= handlerPtr;
888
889
890
891
892
893
894
895

896
897
898
899
900
901
902
896
897
898
899
900
901
902

903
904
905
906
907
908
909
910







-
+








void
Tk_DeleteGenericHandler(
    Tk_GenericProc *proc,
    ClientData clientData)
{
    GenericHandler * handler;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    for (handler=tsdPtr->genericList ; handler ; handler=handler->nextPtr) {
	if ((handler->proc == proc) && (handler->clientData == clientData)) {
	    handler->deleteFlag = 1;
	}
    }
921
922
923
924
925
926
927
928

929
930
931
932
933
934
935
936

937
938
939
940
941
942
943
929
930
931
932
933
934
935

936
937
938
939
940
941
942
943

944
945
946
947
948
949
950
951







-
+







-
+







 */

void
Tk_CreateClientMessageHandler(
    Tk_ClientMessageProc *proc)	/* Function to call on event. */
{
    GenericHandler *handlerPtr;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    /*
     * We use a GenericHandler struct, because it's basically the same, except
     * with an extra clientData field we'll never use.
     */

    handlerPtr = ckalloc(sizeof(GenericHandler));
    handlerPtr = (GenericHandler *)ckalloc(sizeof(GenericHandler));

    handlerPtr->proc = (Tk_GenericProc *) proc;
    handlerPtr->clientData = NULL;	/* never used */
    handlerPtr->deleteFlag = 0;
    handlerPtr->nextPtr = NULL;
    if (tsdPtr->cmList == NULL) {
	tsdPtr->cmList = handlerPtr;
967
968
969
970
971
972
973
974

975
976
977
978
979
980
981
975
976
977
978
979
980
981

982
983
984
985
986
987
988
989







-
+







 */

void
Tk_DeleteClientMessageHandler(
    Tk_ClientMessageProc *proc)
{
    GenericHandler * handler;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    for (handler=tsdPtr->cmList ; handler!=NULL ; handler=handler->nextPtr) {
	if (handler->proc == (Tk_GenericProc *) proc) {
	    handler->deleteFlag = 1;
	}
    }
998
999
1000
1001
1002
1003
1004
1005

1006
1007
1008
1009
1010
1011
1012
1006
1007
1008
1009
1010
1011
1012

1013
1014
1015
1016
1017
1018
1019
1020







-
+







 *
 *----------------------------------------------------------------------
 */

void
TkEventInit(void)
{
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    tsdPtr->handlersActive	= 0;
    tsdPtr->pendingPtr		= NULL;
    tsdPtr->genericList		= NULL;
    tsdPtr->lastGenericPtr	= NULL;
    tsdPtr->cmList		= NULL;
1031
1032
1033
1034
1035
1036
1037
1038

1039
1040

1041
1042
1043
1044
1045
1046
1047
1039
1040
1041
1042
1043
1044
1045

1046
1047

1048
1049
1050
1051
1052
1053
1054
1055







-
+

-
+







 *
 *----------------------------------------------------------------------
 */

static int
TkXErrorHandler(
    ClientData clientData,	/* Pointer to flag we set. */
    XErrorEvent *errEventPtr)	/* X error info. */
    TCL_UNUSED(XErrorEvent *))	/* X error info. */
{
    int *error = clientData;
    int *error = (int *)clientData;

    *error = 1;
    return 0;
}

/*
 *----------------------------------------------------------------------
1120
1121
1122
1123
1124
1125
1126
1127

1128
1129
1130
1131
1132

1133
1134

1135
1136
1137
1138
1139













1140
1141
1142
1143
1144
1145
1146
1128
1129
1130
1131
1132
1133
1134

1135
1136
1137
1138
1139

1140
1141
1142
1143





1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163







-
+




-
+


+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+







 *----------------------------------------------------------------------
 */

void
Tk_HandleEvent(
    XEvent *eventPtr)	/* Event to dispatch. */
{
    register TkEventHandler *handlerPtr;
    TkEventHandler *handlerPtr;
    TkWindow *winPtr;
    unsigned long mask;
    InProgress ip;
    Tcl_Interp *interp = NULL;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));


#if !defined(MAC_OSX_TK) && !defined(_WIN32)
    if (((eventPtr->type == ButtonPress) || (eventPtr->type == ButtonRelease))
	    && ((eventPtr->xbutton.button - 6) < 2)) {
	eventPtr->xbutton.button -= 2;
	eventPtr->xbutton.state ^= ShiftMask;
#if !defined(_WIN32) && !defined(MAC_OSX_TK)
    if ((eventPtr->xbutton.button >= Button4) && (eventPtr->xbutton.button < Button8)) {
	if (eventPtr->type == ButtonRelease) {
	    return;
	} else if (eventPtr->type == ButtonPress) {
	    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;
	    }
	}
    }
#endif

    /*
     * If the generic handler processed this event we are done and can return.
     */

1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1219
1220
1221
1222
1223
1224
1225

1226
1227
1228
1229
1230
1231
1232







-







    /*
     * Create the input context for the window if it hasn't already been done
     * (XFilterEvent needs this context). When the event is a FocusIn event,
     * set the input context focus to the receiving window. This code is only
     * ever active for X11.
     */

#ifdef TK_USE_INPUT_METHODS
    /*
     * If the XIC has been invalidated, it must be recreated.
     */
    if (winPtr->dispPtr->ximGeneration != winPtr->ximGeneration) {
	winPtr->flags &= ~TK_CHECKED_IC;
	winPtr->inputContext = NULL;
    }
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1240
1241
1242
1243
1244
1245
1246

1247
1248
1249
1250
1251
1252
1253







-







	}
	if ((eventPtr->type == FocusIn) &&
		(winPtr->dispPtr->inputMethod != NULL) &&
		(winPtr->inputContext != NULL)) {
	    XSetICFocus(winPtr->inputContext);
	}
    }
#endif /*TK_USE_INPUT_METHODS*/

    /*
     * For events where it hasn't already been done, update the current time
     * in the display.
     */

    if (eventPtr->type == PropertyNotify) {
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342



1343
1344
1345
1346
1347
1348
1349
1348
1349
1350
1351
1352
1353
1354



1355
1356
1357
1358
1359
1360
1361
1362
1363
1364







-
-
-
+
+
+







 */

void
TkEventDeadWindow(
    TkWindow *winPtr)		/* Information about the window that is being
				 * deleted. */
{
    register TkEventHandler *handlerPtr;
    register InProgress *ipPtr;
    ThreadSpecificData *tsdPtr =
    TkEventHandler *handlerPtr;
    InProgress *ipPtr;
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    /*
     * While deleting all the handlers, be careful to check for Tk_HandleEvent
     * being about to process one of the deleted handlers. If it is, tell it
     * to quit (all of the handlers are being deleted).
     */
1383
1384
1385
1386
1387
1388
1389
1390
1391


1392
1393
1394
1395
1396
1397
1398
1398
1399
1400
1401
1402
1403
1404


1405
1406
1407
1408
1409
1410
1411
1412
1413







-
-
+
+







 *----------------------------------------------------------------------
 */

Time
TkCurrentTime(
    TkDisplay *dispPtr)		/* Display for which the time is desired. */
{
    register XEvent *eventPtr;
    ThreadSpecificData *tsdPtr =
    XEvent *eventPtr;
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (tsdPtr->pendingPtr == NULL) {
	return dispPtr->lastEventTime;
    }
    eventPtr = tsdPtr->pendingPtr->eventPtr;
    switch (eventPtr->type) {
1438
1439
1440
1441
1442
1443
1444
1445

1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459

1460
1461
1462
1463
1464
1465
1466
1467







-
+







Tk_RestrictEvents(
    Tk_RestrictProc *proc,	/* Function to call for each incoming event */
    ClientData arg,		/* Arbitrary argument to pass to proc. */
    ClientData *prevArgPtr)	/* Place to store information about previous
				 * argument. */
{
    Tk_RestrictProc *prev;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    prev = tsdPtr->restrictProc;
    *prevArgPtr = tsdPtr->restrictArg;
    tsdPtr->restrictProc = proc;
    tsdPtr->restrictArg = arg;
    return prev;
1531
1532
1533
1534
1535
1536
1537
1538

1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552

1553
1554
1555
1556
1557
1558
1559
1560







-
+







    /*
     * Don't filter motion events if the user defaulting to true (1), which
     * could be set to false (0) when the user wishes to receive all the
     * motion data)
     */

    if (!(dispPtr->flags & TK_DISPLAY_COLLAPSE_MOTION_EVENTS)) {
	wevPtr = ckalloc(sizeof(TkWindowEvent));
	wevPtr = (TkWindowEvent *)ckalloc(sizeof(TkWindowEvent));
	wevPtr->header.proc = WindowEventProc;
	wevPtr->event = *eventPtr;
	Tcl_QueueEvent(&wevPtr->header, position);
	return;
    }

    if ((dispPtr->delayedMotionPtr != NULL) && (position == TCL_QUEUE_TAIL)) {
1563
1564
1565
1566
1567
1568
1569
1570

1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584

1585
1586
1587
1588
1589
1590
1591
1592







-
+








	    Tcl_QueueEvent(&dispPtr->delayedMotionPtr->header, position);
	    dispPtr->delayedMotionPtr = NULL;
	    Tcl_CancelIdleCall(DelayedMotionProc, dispPtr);
	}
    }

    wevPtr = ckalloc(sizeof(TkWindowEvent));
    wevPtr = (TkWindowEvent *)ckalloc(sizeof(TkWindowEvent));
    wevPtr->header.proc = WindowEventProc;
    wevPtr->event = *eventPtr;
    if ((eventPtr->type == MotionNotify) && (position == TCL_QUEUE_TAIL)) {
	/*
	 * The new event is a motion event so don't queue it immediately; save
	 * it around in case another motion event arrives that it can be
	 * collapsed with.
1626
1627
1628
1629
1630
1631
1632









































1633
1634
1635
1636
1637
1638
1639
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	childPtr = childPtr->nextPtr;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TkGenerateActivateEvents --
 *
 *	This function is called by the Mac and Windows window manager routines
 *	when a toplevel window is activated or deactivated.
 *	Activate/Deactivate events will be sent to every subwindow of the
 *	toplevel followed by a FocusIn/FocusOut message.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Generates X events.
 *
 *----------------------------------------------------------------------
 */

void
TkGenerateActivateEvents(
    TkWindow *winPtr,		/* Toplevel to activate. */
    int active)			/* Non-zero if the window is being activated,
				 * else 0.*/
{
    XEvent event;

    /*
     * Generate Activate and Deactivate events. This event is sent to every
     * subwindow in a toplevel window.
     */

    event.xany.serial = NextRequest(winPtr->display);
    event.xany.send_event = False;
    event.xany.display = winPtr->display;
    event.xany.window = winPtr->window;

    event.xany.type = active ? ActivateNotify : DeactivateNotify;
    TkQueueEventForAllChildren(winPtr, &event);
}

/*
 *----------------------------------------------------------------------
 *
 * WindowEventProc --
 *
 *	This function is called by Tcl_DoOneEvent when a window event reaches
 *	the front of the event queue. This function is responsible for
 *	actually handling the event.
 *
 * Results:
1653
1654
1655
1656
1657
1658
1659
1660

1661
1662
1663
1664
1665
1666
1667
1709
1710
1711
1712
1713
1714
1715

1716
1717
1718
1719
1720
1721
1722
1723







-
+







WindowEventProc(
    Tcl_Event *evPtr,		/* Event to service. */
    int flags)			/* Flags that indicate what events to handle,
				 * such as TCL_WINDOW_EVENTS. */
{
    TkWindowEvent *wevPtr = (TkWindowEvent *) evPtr;
    Tk_RestrictAction result;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (!(flags & TCL_WINDOW_EVENTS)) {
	return 0;
    }
    if (tsdPtr->restrictProc != NULL) {
	result = tsdPtr->restrictProc(tsdPtr->restrictArg, &wevPtr->event);
1706
1707
1708
1709
1710
1711
1712
1713
1714


1715
1716
1717
1718
1719

1720
1721
1722
1723
1724
1725
1726
1762
1763
1764
1765
1766
1767
1768

1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784







-

+
+





+







static void
CleanUpTkEvent(
    XEvent *eventPtr)
{
    switch (eventPtr->type) {
    case KeyPress:
    case KeyRelease: {
	TkKeyEvent *kePtr = (TkKeyEvent *) eventPtr;

#if !defined(_WIN32) && !defined(MAC_OSX_TK)
	TkKeyEvent *kePtr = (TkKeyEvent *) eventPtr;
	if (kePtr->charValuePtr != NULL) {
	    ckfree(kePtr->charValuePtr);
	    kePtr->charValuePtr = NULL;
	    kePtr->charValueLen = 0;
	}
#endif
	break;
    }

    case VirtualEvent: {
	XVirtualEvent *vePtr = (XVirtualEvent *) eventPtr;

	if (vePtr->user_data != NULL) {
1752
1753
1754
1755
1756
1757
1758
1759

1760
1761
1762
1763
1764
1765
1766
1810
1811
1812
1813
1814
1815
1816

1817
1818
1819
1820
1821
1822
1823
1824







-
+







 */

static void
DelayedMotionProc(
    ClientData clientData)	/* Pointer to display containing a delayed
				 * motion event to be serviced. */
{
    TkDisplay *dispPtr = clientData;
    TkDisplay *dispPtr = (TkDisplay *)clientData;

    if (dispPtr->delayedMotionPtr == NULL) {
	Tcl_Panic("DelayedMotionProc found no delayed mouse motion event");
    }
    Tcl_QueueEvent(&dispPtr->delayedMotionPtr->header, TCL_QUEUE_TAIL);
    dispPtr->delayedMotionPtr = NULL;
}
1784
1785
1786
1787
1788
1789
1790
1791

1792
1793
1794
1795
1796
1797
1798
1842
1843
1844
1845
1846
1847
1848

1849
1850
1851
1852
1853
1854
1855
1856







-
+







void
TkCreateExitHandler(
    Tcl_ExitProc *proc,		/* Function to invoke. */
    ClientData clientData)	/* Arbitrary value to pass to proc. */
{
    ExitHandler *exitPtr;

    exitPtr = ckalloc(sizeof(ExitHandler));
    exitPtr = (ExitHandler *)ckalloc(sizeof(ExitHandler));
    exitPtr->proc = proc;
    exitPtr->clientData = clientData;
    Tcl_MutexLock(&exitMutex);

    /*
     * The call to TclInExit() is disabled here. That's a private Tcl routine,
     * and calling it is causing some trouble with portability of building Tk.
1880
1881
1882
1883
1884
1885
1886
1887

1888
1889
1890

1891
1892
1893
1894
1895
1896
1897
1938
1939
1940
1941
1942
1943
1944

1945
1946
1947

1948
1949
1950
1951
1952
1953
1954
1955







-
+


-
+








void
TkCreateThreadExitHandler(
    Tcl_ExitProc *proc,		/* Function to invoke. */
    ClientData clientData)	/* Arbitrary value to pass to proc. */
{
    ExitHandler *exitPtr;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    exitPtr = ckalloc(sizeof(ExitHandler));
    exitPtr = (ExitHandler *)ckalloc(sizeof(ExitHandler));
    exitPtr->proc = proc;
    exitPtr->clientData = clientData;

    /*
     * See comments in TkCreateExitHandler().
     */

1921
1922
1923
1924
1925
1926
1927
1928

1929
1930
1931
1932
1933
1934
1935
1979
1980
1981
1982
1983
1984
1985

1986
1987
1988
1989
1990
1991
1992
1993







-
+








void
TkDeleteThreadExitHandler(
    Tcl_ExitProc *proc,		/* Function that was previously registered. */
    ClientData clientData)	/* Arbitrary value to pass to proc. */
{
    ExitHandler *exitPtr, *prevPtr;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    for (prevPtr = NULL, exitPtr = tsdPtr->firstExitPtr; exitPtr != NULL;
	    prevPtr = exitPtr, exitPtr = exitPtr->nextPtr) {
	if ((exitPtr->proc == proc)
		&& (exitPtr->clientData == clientData)) {
	    if (prevPtr == NULL) {
1960
1961
1962
1963
1964
1965
1966
1967

1968
1969
1970
1971
1972
1973
1974
2018
2019
2020
2021
2022
2023
2024

2025
2026
2027
2028
2029
2030
2031
2032







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

void
TkFinalize(
    ClientData clientData)	/* Arbitrary value to pass to proc. */
    TCL_UNUSED(void *))	/* Arbitrary value to pass to proc. */
{
    ExitHandler *exitPtr;

#if defined(_WIN32) && !defined(STATIC_BUILD)
    if (!tclStubsPtr) {
	return;
    }
2012
2013
2014
2015
2016
2017
2018
2019

2020
2021
2022

2023
2024
2025
2026
2027
2028
2029
2070
2071
2072
2073
2074
2075
2076

2077
2078
2079

2080
2081
2082
2083
2084
2085
2086
2087







-
+


-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

void
TkFinalizeThread(
    ClientData clientData)	/* Arbitrary value to pass to proc. */
    TCL_UNUSED(void *))	/* Arbitrary value to pass to proc. */
{
    ExitHandler *exitPtr;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    Tcl_DeleteThreadExitHandler(TkFinalizeThread, NULL);

    if (tsdPtr != NULL) {
	tsdPtr->inExit = 1;

Changes to generic/tkFileFilter.c.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







/*
 * 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.
 */

#include "tkInt.h"
#include "tkFileFilter.h"
160
161
162
163
164
165
166
167

168
169
170
171
172
173
174
160
161
162
163
164
165
166

167
168
169
170
171
172
173
174







-
+







TkFreeFileFilters(
    FileFilterList *flistPtr)	/* List of file filters to free */
{
    FileFilter *filterPtr;
    FileFilterClause *clausePtr;
    GlobPattern *globPtr;
    MacFileType *mfPtr;
    register void *toFree;	/* A pointer that we are about to free. */
    void *toFree;	/* A pointer that we are about to free. */

    for (filterPtr = flistPtr->filters; filterPtr != NULL; ) {
	for (clausePtr = filterPtr->clauses; clausePtr != NULL; ) {
	    /*
	     * Squelch each of the glob patterns.
	     */

258
259
260
261
262
263
264
265
266


267
268
269
270
271
272
273
258
259
260
261
262
263
264


265
266
267
268
269
270
271
272
273







-
-
+
+







	/*
	 * Might be cleaner to use 'Tcl_GetOSTypeFromObj' but that is actually
	 * static to the MacOS X/Darwin version of Tcl, and would therefore
	 * require further code refactoring.
	 */

	for (i=0; i<ostypeCount; i++) {
	    int len;
	    const char *strType = Tcl_GetStringFromObj(ostypeList[i], &len);
	    TkSizeT len;
	    const char *strType = TkGetStringFromObj(ostypeList[i], &len);

	    /*
	     * If len is < 4, it is definitely an error. If equal or longer,
	     * we need to use the macRoman encoding to determine the correct
	     * length (assuming there may be non-ascii characters, e.g.,
	     * embedded nulls or accented characters in the string, the
	     * macRoman length will be different).
301
302
303
304
305
306
307
308

309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326



327
328
329
330
331
332
333
334

335
336
337
338
339

340
341
342
343
344
345
346
347
348

349
350
351

352
353
354
355

356
357
358
359
360
361
362
301
302
303
304
305
306
307

308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323



324
325
326
327
328
329
330
331
332
333

334
335
336
337
338

339
340
341
342
343
344
345
346
347

348
349
350

351
352
353
354

355
356
357
358
359
360
361
362







-
+















-
-
-
+
+
+







-
+




-
+








-
+


-
+



-
+







	}
    }

    /*
     * Add the clause into the list of clauses
     */

    clausePtr = ckalloc(sizeof(FileFilterClause));
    clausePtr = (FileFilterClause *)ckalloc(sizeof(FileFilterClause));
    clausePtr->patterns = NULL;
    clausePtr->patternsTail = NULL;
    clausePtr->macTypes = NULL;
    clausePtr->macTypesTail = NULL;

    if (filterPtr->clauses == NULL) {
	filterPtr->clauses = filterPtr->clausesTail = clausePtr;
    } else {
	filterPtr->clausesTail->next = clausePtr;
	filterPtr->clausesTail = clausePtr;
    }
    clausePtr->next = NULL;

    if (globCount > 0 && globList != NULL) {
	for (i=0; i<globCount; i++) {
	    GlobPattern *globPtr = ckalloc(sizeof(GlobPattern));
	    int len;
	    const char *str = Tcl_GetStringFromObj(globList[i], &len);
	    GlobPattern *globPtr = (GlobPattern *)ckalloc(sizeof(GlobPattern));
	    TkSizeT len;
	    const char *str = TkGetStringFromObj(globList[i], &len);

	    len = (len + 1) * sizeof(char);
	    if (str[0] && str[0] != '*') {
		/*
		 * Prepend a "*" to patterns that do not have a leading "*"
		 */

		globPtr->pattern = ckalloc(len + 1);
		globPtr->pattern = (char *)ckalloc(len + 1);
		globPtr->pattern[0] = '*';
		strcpy(globPtr->pattern+1, str);
	    } else if (isWindows) {
		if (strcmp(str, "*") == 0) {
		    globPtr->pattern = ckalloc(4);
		    globPtr->pattern = (char *)ckalloc(4);
		    strcpy(globPtr->pattern, "*.*");
		} else if (strcmp(str, "") == 0) {
		    /*
		     * An empty string means "match all files with no
		     * extensions"
		     * TODO: "*." actually matches with all files on Win95
		     */

		    globPtr->pattern = ckalloc(3);
		    globPtr->pattern = (char *)ckalloc(3);
		    strcpy(globPtr->pattern, "*.");
		} else {
		    globPtr->pattern = ckalloc(len);
		    globPtr->pattern = (char *)ckalloc(len);
		    strcpy(globPtr->pattern, str);
		}
	    } else {
		globPtr->pattern = ckalloc(len);
		globPtr->pattern = (char *)ckalloc(len);
		strcpy(globPtr->pattern, str);
	    }

	    /*
	     * Add the glob pattern into the list of patterns.
	     */

371
372
373
374
375
376
377
378
379
380



381
382
383
384
385
386
387
371
372
373
374
375
376
377



378
379
380
381
382
383
384
385
386
387







-
-
-
+
+
+







    }
    if (ostypeList != NULL && ostypeCount > 0) {
	if (macRoman == NULL) {
	    macRoman = Tcl_GetEncoding(NULL, "macRoman");
	}
	for (i=0; i<ostypeCount; i++) {
	    Tcl_DString osTypeDS;
	    int len;
	    MacFileType *mfPtr = ckalloc(sizeof(MacFileType));
	    const char *strType = Tcl_GetStringFromObj(ostypeList[i], &len);
	    TkSizeT len;
	    MacFileType *mfPtr = (MacFileType *)ckalloc(sizeof(MacFileType));
	    const char *strType = TkGetStringFromObj(ostypeList[i], &len);
	    char *string;

	    /*
	     * Convert utf to macRoman, since MacOS types are defined to be 4
	     * macRoman characters long
	     */

441
442
443
444
445
446
447
448

449
450
451
452

453
454
455
456
457
458
459
441
442
443
444
445
446
447

448
449
450
451

452
453
454
455
456
457
458
459







-
+



-
+








    for (; filterPtr; filterPtr=filterPtr->next) {
	if (strcmp(filterPtr->name, name) == 0) {
	    return filterPtr;
	}
    }

    filterPtr = ckalloc(sizeof(FileFilter));
    filterPtr = (FileFilter *)ckalloc(sizeof(FileFilter));
    filterPtr->clauses = NULL;
    filterPtr->clausesTail = NULL;
    len = strlen(name) + 1;
    filterPtr->name = ckalloc(len);
    filterPtr->name = (char *)ckalloc(len);
    memcpy(filterPtr->name, name, len);

    if (flistPtr->filters == NULL) {
	flistPtr->filters = flistPtr->filtersTail = filterPtr;
    } else {
	flistPtr->filtersTail->next = filterPtr;
	flistPtr->filtersTail = filterPtr;
Changes to generic/tkFileFilter.h.
1
2
3
4
5
6
7

8
9
10
11
12
13
14




15
16
17
18
19
20
21
1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25






-
+







+
+
+
+







/*
 * tkFileFilter.h --
 *
 *	Declarations for the file filter processing routines needed by the
 *	file selection dialogs.
 *
 * 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.
 */

#ifndef _TK_FILE_FILTER
#define _TK_FILE_FILTER

#ifdef __cplusplus
extern "C" {
#endif

#define OSType long

typedef struct GlobPattern {
    struct GlobPattern *next;	/* Chains to the next glob pattern in a glob
				 * pattern list */
    char *pattern;		/* String value of the pattern, such as
70
71
72
73
74
75
76
77




78
74
75
76
77
78
79
80
81
82
83
84
85
86








+
+
+
+

} FileFilterList;

MODULE_SCOPE void	TkFreeFileFilters(FileFilterList *flistPtr);
MODULE_SCOPE void	TkInitFileFilters(FileFilterList *flistPtr);
MODULE_SCOPE int	TkGetFileFilters(Tcl_Interp *interp,
    			    FileFilterList *flistPtr, Tcl_Obj *valuePtr,
			    int isWindows);

#ifdef __cplusplus
}
#endif

#endif	/* _TK_FILE_FILTER */
Changes to generic/tkFocus.c.
1
2
3
4
5
6
7


8
9
10
11
12
13
14
1
2
3
4
5


6
7
8
9
10
11
12
13
14





-
-
+
+







/*
 * tkFocus.c --
 *
 *	This file contains functions that manage the input focus 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.
 */

#include "tkInt.h"

109
110
111
112
113
114
115
116
117


118
119
120
121
122
123
124
125
126
127
128
129
130
131

132
133
134
135
136
137
138
109
110
111
112
113
114
115


116
117
118
119
120
121
122
123
124
125
126
127
128
129
130

131
132
133
134
135
136
137
138







-
-
+
+













-
+







    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    static const char *const focusOptions[] = {
	"-displayof", "-force", "-lastfor", NULL
    };
    Tk_Window tkwin = clientData;
    TkWindow *winPtr = clientData;
    Tk_Window tkwin = (Tk_Window)clientData;
    TkWindow *winPtr = (TkWindow *)clientData;
    TkWindow *newPtr, *topLevelPtr;
    ToplevelFocusInfo *tlFocusPtr;
    const char *windowName;
    int index;

    /*
     * If invoked with no arguments, just return the current focus window.
     */

    if (objc == 1) {
	Tk_Window focusWin = (Tk_Window) TkGetFocusWin(winPtr);

	if (focusWin != NULL) {
	    Tcl_SetObjResult(interp, TkNewWindowObj(focusWin));
	    Tcl_SetObjResult(interp, Tk_NewWindowObj(focusWin));
	}
	return TCL_OK;
    }

    /*
     * If invoked with a single argument beginning with "." then focus on that
     * window.
175
176
177
178
179
180
181
182

183
184
185
186
187
188
189
175
176
177
178
179
180
181

182
183
184
185
186
187
188
189







-
+







	windowName = Tcl_GetString(objv[2]);
	newPtr = (TkWindow *) Tk_NameToWindow(interp, windowName, tkwin);
	if (newPtr == NULL) {
	    return TCL_ERROR;
	}
	newPtr = TkGetFocusWin(newPtr);
	if (newPtr != NULL) {
	    Tcl_SetObjResult(interp, TkNewWindowObj((Tk_Window) newPtr));
	    Tcl_SetObjResult(interp, Tk_NewWindowObj((Tk_Window) newPtr));
	}
	break;
    case 1:			/* -force */
	windowName = Tcl_GetString(objv[2]);

	/*
	 * The empty string case exists for backwards compatibility.
208
209
210
211
212
213
214
215

216
217
218
219
220

221
222
223
224
225
226
227
208
209
210
211
212
213
214

215
216
217
218
219

220
221
222
223
224
225
226
227







-
+




-
+







		topLevelPtr = topLevelPtr->parentPtr) {
	    if (!(topLevelPtr->flags & TK_TOP_HIERARCHY)) {
		continue;
	    }
	    for (tlFocusPtr = newPtr->mainPtr->tlFocusPtr; tlFocusPtr != NULL;
		    tlFocusPtr = tlFocusPtr->nextPtr) {
		if (tlFocusPtr->topLevelPtr == topLevelPtr) {
		    Tcl_SetObjResult(interp, TkNewWindowObj((Tk_Window)
		    Tcl_SetObjResult(interp, Tk_NewWindowObj((Tk_Window)
			    tlFocusPtr->focusWinPtr));
		    return TCL_OK;
		}
	    }
	    Tcl_SetObjResult(interp, TkNewWindowObj((Tk_Window) topLevelPtr));
	    Tcl_SetObjResult(interp, Tk_NewWindowObj((Tk_Window) topLevelPtr));
	    return TCL_OK;
	}
	break;
    default:
	Tcl_Panic("bad const entries to focusOptions in focus command");
    }
    return TCL_OK;
411
412
413
414
415
416
417
418

419
420
421
422
423
424
425
411
412
413
414
415
416
417

418
419
420
421
422
423
424
425







-
+







    for (tlFocusPtr = winPtr->mainPtr->tlFocusPtr; tlFocusPtr != NULL;
	    tlFocusPtr = tlFocusPtr->nextPtr) {
	if (tlFocusPtr->topLevelPtr == winPtr) {
	    break;
	}
    }
    if (tlFocusPtr == NULL) {
	tlFocusPtr = ckalloc(sizeof(ToplevelFocusInfo));
	tlFocusPtr = (ToplevelFocusInfo *)ckalloc(sizeof(ToplevelFocusInfo));
	tlFocusPtr->topLevelPtr = tlFocusPtr->focusWinPtr = winPtr;
	tlFocusPtr->nextPtr = winPtr->mainPtr->tlFocusPtr;
	winPtr->mainPtr->tlFocusPtr = tlFocusPtr;
    }
    newFocusPtr = tlFocusPtr->focusWinPtr;

    /*
599
600
601
602
603
604
605
606

607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625

626
627
628
629
630
631
632
599
600
601
602
603
604
605

606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624

625
626
627
628
629
630
631
632







-
+


















-
+







     * an event handler that will set the focus to this window once it gets
     * mapped. At the same time, delete any old handler that might be around;
     * it's no longer relevant.
     */

    if (displayFocusPtr->focusOnMapPtr != NULL) {
	Tk_DeleteEventHandler((Tk_Window) displayFocusPtr->focusOnMapPtr,
		StructureNotifyMask, FocusMapProc,
		VisibilityChangeMask, FocusMapProc,
		displayFocusPtr->focusOnMapPtr);
	displayFocusPtr->focusOnMapPtr = NULL;
    }
    if (!allMapped) {
	Tk_CreateEventHandler((Tk_Window) winPtr, VisibilityChangeMask,
		FocusMapProc, winPtr);
	displayFocusPtr->focusOnMapPtr = winPtr;
	displayFocusPtr->forceFocus = force;
	return;
    }

    for (tlFocusPtr = winPtr->mainPtr->tlFocusPtr; tlFocusPtr != NULL;
	    tlFocusPtr = tlFocusPtr->nextPtr) {
	if (tlFocusPtr->topLevelPtr == topLevelPtr) {
	    break;
	}
    }
    if (tlFocusPtr == NULL) {
	tlFocusPtr = ckalloc(sizeof(ToplevelFocusInfo));
	tlFocusPtr = (ToplevelFocusInfo *)ckalloc(sizeof(ToplevelFocusInfo));
	tlFocusPtr->topLevelPtr = topLevelPtr;
	tlFocusPtr->nextPtr = winPtr->mainPtr->tlFocusPtr;
	winPtr->mainPtr->tlFocusPtr = tlFocusPtr;
    }
    tlFocusPtr->focusWinPtr = winPtr;

    if (topLevelPtr->flags & TK_EMBEDDED &&
803
804
805
806
807
808
809
810

811
812
813
814
815
816
817
803
804
805
806
807
808
809

810
811
812
813
814
815
816
817







-
+







 *	Various things get cleaned up and recycled.
 *
 *----------------------------------------------------------------------
 */

void
TkFocusDeadWindow(
    register TkWindow *winPtr)	/* Information about the window that is being
    TkWindow *winPtr)	/* Information about the window that is being
				 * deleted. */
{
    ToplevelFocusInfo *tlFocusPtr, *prevPtr;
    DisplayFocusInfo *displayFocusPtr;
    TkDisplay *dispPtr = winPtr->dispPtr;

    /*
957
958
959
960
961
962
963
964

965
966
967
968
969
970
971
957
958
959
960
961
962
963

964
965
966
967
968
969
970
971







-
+







 */

static void
FocusMapProc(
    ClientData clientData,	/* Toplevel window. */
    XEvent *eventPtr)		/* Information about event. */
{
    TkWindow *winPtr = clientData;
    TkWindow *winPtr = (TkWindow *)clientData;
    DisplayFocusInfo *displayFocusPtr;

    if (eventPtr->type == VisibilityNotify) {
	displayFocusPtr = FindDisplayFocusInfo(winPtr->mainPtr,
		winPtr->dispPtr);
	DEBUG(winPtr->dispPtr, ("auto-focussing on %s, force %d\n",
		winPtr->pathName, displayFocusPtr->forceFocus));
1011
1012
1013
1014
1015
1016
1017
1018

1019
1020
1021
1022
1023
1024
1025
1011
1012
1013
1014
1015
1016
1017

1018
1019
1020
1021
1022
1023
1024
1025







-
+







	}
    }

    /*
     * The record doesn't exist yet. Make a new one.
     */

    displayFocusPtr = ckalloc(sizeof(DisplayFocusInfo));
    displayFocusPtr = (DisplayFocusInfo *)ckalloc(sizeof(DisplayFocusInfo));
    displayFocusPtr->dispPtr = dispPtr;
    displayFocusPtr->focusWinPtr = NULL;
    displayFocusPtr->focusOnMapPtr = NULL;
    displayFocusPtr->forceFocus = 0;
    displayFocusPtr->focusSerial = 0;
    displayFocusPtr->nextPtr = mainPtr->displayFocusPtr;
    mainPtr->displayFocusPtr = displayFocusPtr;
1139
1140
1141
1142
1143
1144
1145
1146

1147
1148
1149
1150
1151
1152
1153
1139
1140
1141
1142
1143
1144
1145

1146
1147
1148
1149
1150
1151
1152
1153







-
+







    }

    if (subWinPtr == winPtr) {
	/*
	 * Move focus to new toplevel.
	 */

	ToplevelFocusInfo *newTlFocusPtr = ckalloc(sizeof(ToplevelFocusInfo));
	ToplevelFocusInfo *newTlFocusPtr = (ToplevelFocusInfo *)ckalloc(sizeof(ToplevelFocusInfo));

	newTlFocusPtr->topLevelPtr = winPtr;
	newTlFocusPtr->focusWinPtr = tlFocusPtr->focusWinPtr;
	newTlFocusPtr->nextPtr = winPtr->mainPtr->tlFocusPtr;
	winPtr->mainPtr->tlFocusPtr = newTlFocusPtr;

	/*
Changes to generic/tkFont.c.
1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
16
17

18

19
20
21
22
23
24
25
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15
16

17
18
19
20
21
22
23
24
25
26






-
-
+
+








-
+

+







/*
 * tkFont.c --
 *
 *	This file maintains a database of fonts for the Tk toolkit. It also
 *	provides several utility functions for measuring and displaying text.
 *
 * 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.
 */

#include "tkInt.h"
#include "tkFont.h"
#if defined(MAC_OSX_TK)
#include "tkMacOSXInt.h"
#include "tkMacOSXInt.h"    /* Defines TK_DRAW_IN_CONTEXT */
#endif

/*
 * The following structure is used to keep track of all the fonts that exist
 * in the current application. It must be stored in the TkMainInfo for the
 * application.
 */

typedef struct TkFontInfo {
39
40
41
42
43
44
45
46

47
48
49
50
51
52
53
40
41
42
43
44
45
46

47
48
49
50
51
52
53
54







-
+







/*
 * The following data structure is used to keep track of the font attributes
 * for each named font that has been defined. The named font is only deleted
 * when the last reference to it goes away.
 */

typedef struct NamedFont {
    int refCount;		/* Number of users of named font. */
    size_t refCount;		/* Number of users of named font. */
    int deletePending;		/* Non-zero if font should be deleted when
				 * last reference goes away. */
    TkFontAttributes fa;	/* Desired attributes for named font. */
} NamedFont;

/*
 * The following two structures are used to keep track of string measurement
91
92
93
94
95
96
97
98

99
100
101
102
103
104
105
92
93
94
95
96
97
98

99
100
101
102
103
104
105
106







-
+







typedef struct TextLayout {
    Tk_Font tkfont;		/* The font used when laying out the text. */
    const char *string;		/* The string that was layed out. */
    int width;			/* The maximum width of all lines in the text
				 * layout. */
    int numChunks;		/* Number of chunks actually used in following
				 * array. */
    LayoutChunk chunks[1];	/* Array of chunks. The actual size will be
    LayoutChunk chunks[TKFLEXARRAY];/* Array of chunks. The actual size will be
				 * maxChunks. THIS FIELD MUST BE THE LAST IN
				 * THE STRUCTURE. */
} TextLayout;

/*
 * The following structures are used as two-way maps between the values for
 * the fields in the TkFontAttributes structure and the strings used in Tcl,
349
350
351
352
353
354
355
356

357
358
359
360
361
362
363
350
351
352
353
354
355
356

357
358
359
360
361
362
363
364







-
+







 */

const Tcl_ObjType tkFontObjType = {
    "font",			/* name */
    FreeFontObjProc,		/* freeIntRepProc */
    DupFontObjProc,		/* dupIntRepProc */
    NULL,			/* updateStringProc */
    SetFontFromAny		/* setFromAnyProc */
    NULL			/* setFromAnyProc */
};

/*
 *---------------------------------------------------------------------------
 *
 * TkFontPkgInit --
 *
375
376
377
378
379
380
381
382

383
384
385
386
387
388
389
376
377
378
379
380
381
382

383
384
385
386
387
388
389
390







-
+







 *---------------------------------------------------------------------------
 */

void
TkFontPkgInit(
    TkMainInfo *mainPtr)	/* The application being created. */
{
    TkFontInfo *fiPtr = ckalloc(sizeof(TkFontInfo));
    TkFontInfo *fiPtr = (TkFontInfo *)ckalloc(sizeof(TkFontInfo));

    Tcl_InitHashTable(&fiPtr->fontCache, TCL_STRING_KEYS);
    Tcl_InitHashTable(&fiPtr->namedTable, TCL_STRING_KEYS);
    fiPtr->mainPtr = mainPtr;
    fiPtr->updatePending = 0;
    mainPtr->fontInfoPtr = fiPtr;

468
469
470
471
472
473
474
475

476
477
478
479
480
481
482
469
470
471
472
473
474
475

476
477
478
479
480
481
482
483







-
+







Tk_FontObjCmd(
    ClientData clientData,	/* Main window associated with interpreter. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int index;
    Tk_Window tkwin = clientData;
    Tk_Window tkwin = (Tk_Window)clientData;
    TkFontInfo *fiPtr = ((TkWindow *) tkwin)->mainPtr->fontInfoPtr;
    static const char *const optionStrings[] = {
	"actual",	"configure",	"create",	"delete",
	"families",	"measure",	"metrics",	"names",
	NULL
    };
    enum options {
551
552
553
554
555
556
557
558

559
560
561
562
563
564
565
566
567
568

569
570

571
572
573
574
575
576
577
552
553
554
555
556
557
558

559
560
561
562
563
564
565
566
567
568

569
570

571
572
573
574
575
576
577
578







-
+









-
+

-
+








	/*
	 * If there were fewer than 3 args, or args remain, that's an error.
	 */

	if (objc < 3 || n < objc) {
	    Tcl_WrongNumArgs(interp, 2, objv,
		    "font ?-displayof window? ?option? ?--? ?char?");
		    "font ?-displayof window? ?-option? ?--? ?char?");
	    return TCL_ERROR;
	}

	/*
	 * The 'charPtr' arg must be a single Unicode.
	 */

	if (charPtr != NULL) {
	    const char *string = Tcl_GetString(charPtr);
	    int len = TkUtfToUniChar(string, &uniChar);
	    size_t len = TkUtfToUniChar(string, &uniChar);

	    if (len != charPtr->length) {
	    if (len != (size_t)charPtr->length) {
		resultPtr = Tcl_NewStringObj(
			"expected a single character but got \"", -1);
		Tcl_AppendLimitedToObj(resultPtr, string,
			-1, 40, "...");
		Tcl_AppendToObj(resultPtr, "\"", -1);
		Tcl_SetObjResult(interp, resultPtr);
		Tcl_SetErrorCode(interp, "TK", "VALUE", "FONT_SAMPLE", NULL);
612
613
614
615
616
617
618
619

620
621

622
623
624
625
626
627
628
613
614
615
616
617
618
619

620
621

622
623
624
625
626
627
628
629







-
+

-
+








    	if (objc < 3) {
    	    Tcl_WrongNumArgs(interp, 2, objv, "fontname ?-option value ...?");
    	    return TCL_ERROR;
    	}
    	string = Tcl_GetString(objv[2]);
    	namedHashPtr = Tcl_FindHashEntry(&fiPtr->namedTable, string);
	nfPtr = NULL;		/* lint. */
	nfPtr = NULL;
    	if (namedHashPtr != NULL) {
    	    nfPtr = Tcl_GetHashValue(namedHashPtr);
    	    nfPtr = (NamedFont *)Tcl_GetHashValue(namedHashPtr);
    	}
    	if ((namedHashPtr == NULL) || nfPtr->deletePending) {
    	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
    		    "named font \"%s\" doesn't exist", string));
    	    Tcl_SetErrorCode(interp, "TK", "LOOKUP", "FONT", string, NULL);
    	    return TCL_ERROR;
    	}
710
711
712
713
714
715
716

717

718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735


736
737
738
739
740
741
742

743
744
745
746
747
748
749
750
751
752
753
754

755
756
757
758
759
760
761
711
712
713
714
715
716
717
718

719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735


736
737
738
739
740
741
742
743

744
745
746
747
748
749
750
751
752
753
754
755

756
757
758
759
760
761
762
763







+
-
+
















-
-
+
+






-
+











-
+







	}
	TkpGetFontFamilies(interp, tkwin);
	break;
    }
    case FONT_MEASURE: {
	const char *string;
	Tk_Font tkfont;
	TkSizeT length = 0;
	int length = 0, skip = 0;
	int skip = 0;

	if (objc > 4) {
	    skip = TkGetDisplayOf(interp, objc - 3, objv + 3, &tkwin);
	    if (skip < 0) {
		return TCL_ERROR;
	    }
	}
	if (objc - skip != 4) {
	    Tcl_WrongNumArgs(interp, 2, objv,
		    "font ?-displayof window? text");
	    return TCL_ERROR;
	}
	tkfont = Tk_AllocFontFromObj(interp, tkwin, objv[2]);
	if (tkfont == NULL) {
	    return TCL_ERROR;
	}
	string = Tcl_GetStringFromObj(objv[3 + skip], &length);
	Tcl_SetObjResult(interp, Tcl_NewIntObj(
	string = TkGetStringFromObj(objv[3 + skip], &length);
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(
		Tk_TextWidth(tkfont, string, length)));
	Tk_FreeFont(tkfont);
	break;
    }
    case FONT_METRICS: {
	Tk_Font tkfont;
	int skip, index, i;
	int skip, i;
	const TkFontMetrics *fmPtr;
	static const char *const switches[] = {
	    "-ascent", "-descent", "-linespace", "-fixed", NULL
	};

	skip = TkGetDisplayOf(interp, objc - 3, objv + 3, &tkwin);
	if (skip < 0) {
	    return TCL_ERROR;
	}
	if ((objc < 3) || ((objc - skip) > 4)) {
	    Tcl_WrongNumArgs(interp, 2, objv,
		    "font ?-displayof window? ?option?");
		    "font ?-displayof window? ?-option?");
	    return TCL_ERROR;
	}
	tkfont = Tk_AllocFontFromObj(interp, tkwin, objv[2]);
	if (tkfont == NULL) {
	    return TCL_ERROR;
	}
	objc -= skip;
775
776
777
778
779
780
781
782

783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799

800
801
802

803
804
805
806
807
808
809
777
778
779
780
781
782
783

784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800

801
802
803

804
805
806
807
808
809
810
811







-
+
















-
+


-
+







	    i = 0;		/* Needed only to prevent compiler warning. */
	    switch (index) {
	    case 0: i = fmPtr->ascent;			break;
	    case 1: i = fmPtr->descent;			break;
	    case 2: i = fmPtr->ascent + fmPtr->descent;	break;
	    case 3: i = fmPtr->fixed;			break;
	    }
	    Tcl_SetObjResult(interp, Tcl_NewIntObj(i));
	    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(i));
	}
	Tk_FreeFont(tkfont);
	break;
    }
    case FONT_NAMES: {
	Tcl_HashSearch search;
	Tcl_HashEntry *namedHashPtr;
	Tcl_Obj *resultPtr;

	if (objc != 2) {
	    Tcl_WrongNumArgs(interp, 1, objv, "names");
	    return TCL_ERROR;
	}
	resultPtr = Tcl_NewObj();
	namedHashPtr = Tcl_FirstHashEntry(&fiPtr->namedTable, &search);
	while (namedHashPtr != NULL) {
	    NamedFont *nfPtr = Tcl_GetHashValue(namedHashPtr);
	    NamedFont *nfPtr = (NamedFont *)Tcl_GetHashValue(namedHashPtr);

	    if (!nfPtr->deletePending) {
		char *string = Tcl_GetHashKey(&fiPtr->namedTable,
		char *string = (char *)Tcl_GetHashKey(&fiPtr->namedTable,
			namedHashPtr);

		Tcl_ListObjAppendElement(NULL, resultPtr,
			Tcl_NewStringObj(string, -1));
	    }
	    namedHashPtr = Tcl_NextHashEntry(&search);
	}
838
839
840
841
842
843
844
845

846
847
848
849
850
851
852
853
854
855
856
857
858

859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876

877
878
879
880
881
882

883
884
885

886
887
888

889
890
891
892
893
894
895
840
841
842
843
844
845
846

847
848
849
850
851
852
853
854
855
856
857
858
859

860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877

878

879
880
881
882
883
884
885
886

887
888
889

890
891
892
893
894
895
896
897







-
+












-
+

















-
+
-





+


-
+


-
+







    TkFontInfo *fiPtr,		/* Info about application's fonts. */
    Tk_Window tkwin,		/* A window in the application. */
    Tcl_HashEntry *namedHashPtr)/* The named font that is changing. */
{
    Tcl_HashEntry *cacheHashPtr;
    Tcl_HashSearch search;
    TkFont *fontPtr;
    NamedFont *nfPtr = Tcl_GetHashValue(namedHashPtr);
    NamedFont *nfPtr = (NamedFont *)Tcl_GetHashValue(namedHashPtr);

    if (nfPtr->refCount == 0) {
	/*
	 * Well nobody's using this named font, so don't have to tell any
	 * widgets to recompute themselves.
	 */

	return;
    }

    cacheHashPtr = Tcl_FirstHashEntry(&fiPtr->fontCache, &search);
    while (cacheHashPtr != NULL) {
	for (fontPtr = Tcl_GetHashValue(cacheHashPtr);
	for (fontPtr = (TkFont *)Tcl_GetHashValue(cacheHashPtr);
		fontPtr != NULL; fontPtr = fontPtr->nextPtr) {
	    if (fontPtr->namedHashPtr == namedHashPtr) {
		TkpGetFontFromAttributes(fontPtr, tkwin, &nfPtr->fa);
		if (!fiPtr->updatePending) {
		    fiPtr->updatePending = 1;
		    Tcl_DoWhenIdle(TheWorldHasChanged, fiPtr);
		}
	    }
	}
	cacheHashPtr = Tcl_NextHashEntry(&search);
    }
}

static void
TheWorldHasChanged(
    ClientData clientData)	/* Info about application's fonts. */
{
    TkFontInfo *fiPtr = clientData;
    TkFontInfo *fiPtr = (TkFontInfo *)clientData;
#if defined(MAC_OSX_TK)

    /*
     * On macOS it is catastrophic to recompute all widgets while the
     * [NSView drawRect] method is drawing. The best that we can do in
     * that situation is to abort the recomputation and hope for the best.
     * This is ignored on other platforms.
     */

    if (TkpAppIsDrawing()) {
    if (TkpWillDrawWidget(NULL)) {
	return;
    }
#endif

    fiPtr->updatePending = 0;
    RecomputeWidgets(fiPtr->mainPtr->winPtr);
}

static void
RecomputeWidgets(
    TkWindow *winPtr)		/* Window to which command is sent. */
959
960
961
962
963
964
965
966

967
968
969
970
971
972
973
961
962
963
964
965
966
967

968
969
970
971
972
973
974
975







-
+







    TkFontInfo *fiPtr = ((TkWindow *) tkwin)->mainPtr->fontInfoPtr;
    Tcl_HashEntry *namedHashPtr;
    int isNew;
    NamedFont *nfPtr;

    namedHashPtr = Tcl_CreateHashEntry(&fiPtr->namedTable, name, &isNew);
    if (!isNew) {
	nfPtr = Tcl_GetHashValue(namedHashPtr);
	nfPtr = (NamedFont *)Tcl_GetHashValue(namedHashPtr);
	if (!nfPtr->deletePending) {
	    if (interp) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"named font \"%s\" already exists", name));
		Tcl_SetErrorCode(interp, "TK", "FONT", "EXISTS", NULL);
	    }
	    return TCL_ERROR;
981
982
983
984
985
986
987
988

989
990
991
992
993
994
995
983
984
985
986
987
988
989

990
991
992
993
994
995
996
997







-
+








	nfPtr->fa = *faPtr;
	nfPtr->deletePending = 0;
	UpdateDependentFonts(fiPtr, tkwin, namedHashPtr);
	return TCL_OK;
    }

    nfPtr = ckalloc(sizeof(NamedFont));
    nfPtr = (NamedFont *)ckalloc(sizeof(NamedFont));
    nfPtr->deletePending = 0;
    Tcl_SetHashValue(namedHashPtr, nfPtr);
    nfPtr->fa = *faPtr;
    nfPtr->refCount = 0;
    nfPtr->deletePending = 0;
    return TCL_OK;
}
1020
1021
1022
1023
1024
1025
1026
1027

1028
1029
1030
1031
1032
1033
1034
1022
1023
1024
1025
1026
1027
1028

1029
1030
1031
1032
1033
1034
1035
1036







-
+







	if (interp) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "named font \"%s\" doesn't exist", name));
	    Tcl_SetErrorCode(interp, "TK", "LOOKUP", "FONT", name, NULL);
	}
	return TCL_ERROR;
    }
    nfPtr = Tcl_GetHashValue(namedHashPtr);
    nfPtr = (NamedFont *)Tcl_GetHashValue(namedHashPtr);
    if (nfPtr->refCount != 0) {
	nfPtr->deletePending = 1;
    } else {
	Tcl_DeleteHashEntry(namedHashPtr);
	ckfree(nfPtr);
    }
    return TCL_OK;
1109
1110
1111
1112
1113
1114
1115
1116

1117
1118
1119
1120
1121
1122
1123
1111
1112
1113
1114
1115
1116
1117

1118
1119
1120
1121
1122
1123
1124
1125







-
+







    NamedFont *nfPtr;

    if (objPtr->typePtr != &tkFontObjType
	    || objPtr->internalRep.twoPtrValue.ptr2 != fiPtr) {
	SetFontFromAny(interp, objPtr);
    }

    oldFontPtr = objPtr->internalRep.twoPtrValue.ptr1;
    oldFontPtr = (TkFont *)objPtr->internalRep.twoPtrValue.ptr1;
    if (oldFontPtr != NULL) {
	if (oldFontPtr->resourceRefCount == 0) {
	    /*
	     * This is a stale reference: it refers to a TkFont that's no
	     * longer in use. Clear the reference.
	     */

1138
1139
1140
1141
1142
1143
1144
1145

1146
1147
1148
1149
1150
1151
1152
1140
1141
1142
1143
1144
1145
1146

1147
1148
1149
1150
1151
1152
1153
1154







-
+







    if (oldFontPtr != NULL) {
	cacheHashPtr = oldFontPtr->cacheHashPtr;
	FreeFontObj(objPtr);
    } else {
	cacheHashPtr = Tcl_CreateHashEntry(&fiPtr->fontCache,
		Tcl_GetString(objPtr), &isNew);
    }
    firstFontPtr = Tcl_GetHashValue(cacheHashPtr);
    firstFontPtr = (TkFont *)Tcl_GetHashValue(cacheHashPtr);
    for (fontPtr = firstFontPtr; (fontPtr != NULL);
	    fontPtr = fontPtr->nextPtr) {
	if (Tk_Screen(tkwin) == fontPtr->screen) {
	    fontPtr->resourceRefCount++;
	    fontPtr->objRefCount++;
	    objPtr->internalRep.twoPtrValue.ptr1 = fontPtr;
	    objPtr->internalRep.twoPtrValue.ptr2 = fiPtr;
1161
1162
1163
1164
1165
1166
1167
1168

1169
1170
1171
1172
1173
1174
1175
1163
1164
1165
1166
1167
1168
1169

1170
1171
1172
1173
1174
1175
1176
1177







-
+







    namedHashPtr = Tcl_FindHashEntry(&fiPtr->namedTable,
	    Tcl_GetString(objPtr));
    if (namedHashPtr != NULL) {
	/*
	 * Construct a font based on a named font.
	 */

	nfPtr = Tcl_GetHashValue(namedHashPtr);
	nfPtr = (NamedFont *)Tcl_GetHashValue(namedHashPtr);
	nfPtr->refCount++;

	fontPtr = TkpGetFontFromAttributes(NULL, tkwin, &nfPtr->fa);
    } else {
	/*
	 * Native font?
	 */
1294
1295
1296
1297
1298
1299
1300
1301

1302
1303
1304
1305
1306
1307
1308
1296
1297
1298
1299
1300
1301
1302

1303
1304
1305
1306
1307
1308
1309
1310







-
+







    Tcl_HashEntry *hashPtr;

    if (objPtr->typePtr != &tkFontObjType
	    || objPtr->internalRep.twoPtrValue.ptr2 != fiPtr) {
	SetFontFromAny(NULL, objPtr);
    }

    fontPtr = objPtr->internalRep.twoPtrValue.ptr1;
    fontPtr = (TkFont *)objPtr->internalRep.twoPtrValue.ptr1;
    if (fontPtr != NULL) {
	if (fontPtr->resourceRefCount == 0) {
	    /*
	     * This is a stale reference: it refers to a TkFont that's no
	     * longer in use. Clear the reference.
	     */

1321
1322
1323
1324
1325
1326
1327
1328

1329
1330
1331
1332
1333
1334
1335
1323
1324
1325
1326
1327
1328
1329

1330
1331
1332
1333
1334
1335
1336
1337







-
+







    if (fontPtr != NULL) {
	hashPtr = fontPtr->cacheHashPtr;
	FreeFontObj(objPtr);
    } else {
	hashPtr = Tcl_FindHashEntry(&fiPtr->fontCache, Tcl_GetString(objPtr));
    }
    if (hashPtr != NULL) {
	for (fontPtr = Tcl_GetHashValue(hashPtr); fontPtr != NULL;
	for (fontPtr = (TkFont *)Tcl_GetHashValue(hashPtr); fontPtr != NULL;
		fontPtr = fontPtr->nextPtr) {
	    if (Tk_Screen(tkwin) == fontPtr->screen) {
		fontPtr->objRefCount++;
		objPtr->internalRep.twoPtrValue.ptr1 = fontPtr;
		objPtr->internalRep.twoPtrValue.ptr2 = fiPtr;
		return (Tk_Font) fontPtr;
	    }
1356
1357
1358
1359
1360
1361
1362
1363

1364
1365
1366
1367
1368
1369
1370
1358
1359
1360
1361
1362
1363
1364

1365
1366
1367
1368
1369
1370
1371
1372







-
+







 *	TkFont pointer is NULL.
 *
 *----------------------------------------------------------------------
 */

static int
SetFontFromAny(
    Tcl_Interp *interp,		/* Used for error reporting if not NULL. */
    TCL_UNUSED(Tcl_Interp *),	/* Used for error reporting if not NULL. */
    Tcl_Obj *objPtr)		/* The object to convert. */
{
    const Tcl_ObjType *typePtr;

    /*
     * Free the old internalRep before setting the new one.
     */
1432
1433
1434
1435
1436
1437
1438
1439
1440

1441
1442
1443
1444
1445
1446
1447
1448
1449

1450
1451

1452
1453
1454
1455
1456
1457

1458
1459
1460
1461
1462
1463
1464
1434
1435
1436
1437
1438
1439
1440


1441
1442
1443
1444
1445
1446
1447
1448
1449

1450


1451
1452
1453
1454
1455
1456

1457
1458
1459
1460
1461
1462
1463
1464







-
-
+








-
+
-
-
+





-
+







{
    TkFont *fontPtr = (TkFont *) tkfont, *prevPtr;
    NamedFont *nfPtr;

    if (fontPtr == NULL) {
	return;
    }
    fontPtr->resourceRefCount--;
    if (fontPtr->resourceRefCount > 0) {
    if (fontPtr->resourceRefCount-- > 1) {
	return;
    }
    if (fontPtr->namedHashPtr != NULL) {
	/*
	 * This font derived from a named font. Reduce the reference count on
	 * the named font and free it if no-one else is using it.
	 */

	nfPtr = Tcl_GetHashValue(fontPtr->namedHashPtr);
	nfPtr = (NamedFont *)Tcl_GetHashValue(fontPtr->namedHashPtr);
	nfPtr->refCount--;
	if ((nfPtr->refCount == 0) && nfPtr->deletePending) {
	if ((nfPtr->refCount-- <= 1) && nfPtr->deletePending) {
	    Tcl_DeleteHashEntry(fontPtr->namedHashPtr);
	    ckfree(nfPtr);
	}
    }

    prevPtr = Tcl_GetHashValue(fontPtr->cacheHashPtr);
    prevPtr = (TkFont *)Tcl_GetHashValue(fontPtr->cacheHashPtr);
    if (prevPtr == fontPtr) {
	if (fontPtr->nextPtr == NULL) {
	    Tcl_DeleteHashEntry(fontPtr->cacheHashPtr);
	} else {
	    Tcl_SetHashValue(fontPtr->cacheHashPtr, fontPtr->nextPtr);
	}
    } else {
1528
1529
1530
1531
1532
1533
1534
1535

1536
1537
1538

1539
1540
1541
1542
1543
1544
1545
1546
1528
1529
1530
1531
1532
1533
1534

1535
1536
1537

1538

1539
1540
1541
1542
1543
1544
1545







-
+


-
+
-







    objPtr->typePtr = NULL;
}

static void
FreeFontObj(
    Tcl_Obj *objPtr)		/* The object we are releasing. */
{
    TkFont *fontPtr = objPtr->internalRep.twoPtrValue.ptr1;
    TkFont *fontPtr = (TkFont *)objPtr->internalRep.twoPtrValue.ptr1;

    if (fontPtr != NULL) {
	fontPtr->objRefCount--;
	if ((fontPtr->objRefCount-- <= 1) && (fontPtr->resourceRefCount == 0)) {
	if ((fontPtr->resourceRefCount == 0) && (fontPtr->objRefCount == 0)) {
	    ckfree(fontPtr);
	}
	objPtr->internalRep.twoPtrValue.ptr1 = NULL;
	objPtr->internalRep.twoPtrValue.ptr2 = NULL;
    }
}

1563
1564
1565
1566
1567
1568
1569
1570

1571
1572
1573
1574
1575
1576
1577
1562
1563
1564
1565
1566
1567
1568

1569
1570
1571
1572
1573
1574
1575
1576







-
+







 */

static void
DupFontObjProc(
    Tcl_Obj *srcObjPtr,		/* The object we are copying from. */
    Tcl_Obj *dupObjPtr)		/* The object we are copying to. */
{
    TkFont *fontPtr = srcObjPtr->internalRep.twoPtrValue.ptr1;
    TkFont *fontPtr = (TkFont *)srcObjPtr->internalRep.twoPtrValue.ptr1;

    dupObjPtr->typePtr = srcObjPtr->typePtr;
    dupObjPtr->internalRep.twoPtrValue.ptr1 = fontPtr;
    dupObjPtr->internalRep.twoPtrValue.ptr2
	    = srcObjPtr->internalRep.twoPtrValue.ptr2;

    if (fontPtr != NULL) {
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736





1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1723
1724
1725
1726
1727
1728
1729






1730
1731
1732
1733
1734



1735
1736
1737
1738
1739
1740
1741







-
-
-
-
-
-
+
+
+
+
+
-
-
-







	upper = 1;
	for (; *src != '\0'; ) {
	    while (isspace(UCHAR(*src))) { /* INTL: ISO space */
		src++;
		upper = 1;
	    }
	    src += TkUtfToUniChar(src, &ch);
	    if (ch <= 0xffff) {
		if (upper) {
		    ch = Tcl_UniCharToUpper(ch);
		    upper = 0;
		} else {
		    ch = Tcl_UniCharToLower(ch);
	    if (upper) {
		ch = Tcl_UniCharToUpper(ch);
		upper = 0;
	    } else {
		ch = Tcl_UniCharToLower(ch);
		}
	    } else {
		upper = 0;
	    }
	    dest += TkUniCharToUtf(ch, dest);
	}
	*dest = '\0';
	Tcl_DStringSetLength(dsPtr, dest - Tcl_DStringValue(dsPtr));
	family = Tcl_DStringValue(dsPtr) + len;
    }
1969
1970
1971
1972
1973
1974
1975
1976

1977
1978
1979
1980
1981
1982
1983
1964
1965
1966
1967
1968
1969
1970

1971
1972
1973
1974
1975
1976
1977
1978







-
+







				 * expanded. TK_IGNORE_NEWLINES means that
				 * newline characters should not cause a line
				 * break. */
    int *widthPtr,		/* Filled with width of string. */
    int *heightPtr)		/* Filled with height of string. */
{
    TkFont *fontPtr = (TkFont *) tkfont;
    const char *start, *end, *special;
    const char *start, *endp, *special;
    int n, y, bytesThisChunk, maxChunks, curLine, layoutHeight;
    int baseline, height, curX, newX, maxWidth, *lineLengths;
    TextLayout *layoutPtr;
    LayoutChunk *chunkPtr;
    const TkFontMetrics *fmPtr;
    Tcl_DString lineBuffer;

2002
2003
2004
2005
2006
2007
2008
2009
2010


2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024

2025
2026
2027
2028
2029

2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040

2041
2042
2043
2044
2045
2046
2047
1997
1998
1999
2000
2001
2002
2003


2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018

2019
2020
2021
2022
2023

2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034

2035
2036
2037
2038
2039
2040
2041
2042







-
-
+
+













-
+




-
+










-
+







    }
    if (wrapLength == 0) {
	wrapLength = -1;
    }

    maxChunks = 1;

    layoutPtr = ckalloc(sizeof(TextLayout)
	    + (maxChunks-1) * sizeof(LayoutChunk));
    layoutPtr = (TextLayout *)ckalloc(offsetof(TextLayout, chunks)
	    + maxChunks * sizeof(LayoutChunk));
    layoutPtr->tkfont = tkfont;
    layoutPtr->string = string;
    layoutPtr->numChunks = 0;

    baseline = fmPtr->ascent;
    maxWidth = 0;

    /*
     * Divide the string up into simple strings and measure each string.
     */

    curX = 0;

    end = Tcl_UtfAtIndex(string, numChars);
    endp = Tcl_UtfAtIndex(string, numChars);
    special = string;

    flags &= TK_IGNORE_TABS | TK_IGNORE_NEWLINES;
    flags |= TK_WHOLE_WORDS | TK_AT_LEAST_ONE;
    for (start = string; start < end; ) {
    for (start = string; start < endp; ) {
	if (start >= special) {
	    /*
	     * Find the next special character in the string.
	     *
	     * INTL: Note that it is safe to increment by byte, because we are
	     * looking for 7-bit characters that will appear unchanged in
	     * UTF-8. At some point we may need to support the full Unicode
	     * whitespace set.
	     */

	    for (special = start; special < end; special++) {
	    for (special = start; special < endp; special++) {
		if (!(flags & TK_IGNORE_NEWLINES)) {
		    if ((*special == '\n') || (*special == '\r')) {
			break;
		    }
		}
		if (!(flags & TK_IGNORE_TABS)) {
		    if (*special == '\t') {
2067
2068
2069
2070
2071
2072
2073
2074

2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091

2092
2093
2094
2095
2096
2097
2098
2062
2063
2064
2065
2066
2067
2068

2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085

2086
2087
2088
2089
2090
2091
2092
2093







-
+
















-
+







			bytesThisChunk, curX, newX, baseline);

		start += bytesThisChunk;
		curX = newX;
	    }
	}

	if ((start == special) && (special < end)) {
	if ((start == special) && (special < endp)) {
	    /*
	     * Handle the special character.
	     *
	     * INTL: Special will be pointing at a 7-bit character so we can
	     * safely treat it as a single byte.
	     */

	    chunkPtr = NULL;
	    if (*special == '\t') {
		newX = curX + fontPtr->tabWidth;
		newX -= newX % fontPtr->tabWidth;
		NewChunk(&layoutPtr, &maxChunks, start, 1, curX, newX,
			baseline)->numDisplayChars = -1;
		start++;
		curX = newX;
		flags &= ~TK_AT_LEAST_ONE;
		if ((start < end) &&
		if ((start < endp) &&
			((wrapLength <= 0) || (newX <= wrapLength))) {
		    /*
		     * More chars can still fit on this line.
		     */

		    continue;
		}
2106
2107
2108
2109
2110
2111
2112
2113

2114
2115
2116
2117
2118
2119
2120
2101
2102
2103
2104
2105
2106
2107

2108
2109
2110
2111
2112
2113
2114
2115







-
+








	/*
	 * No more characters are going to go on this line, either because no
	 * more characters can fit or there are no more characters left.
	 * Consume all extra spaces at end of line.
	 */

	while ((start < end) && isspace(UCHAR(*start))) { /* INTL: ISO space */
	while ((start < endp) && isspace(UCHAR(*start))) { /* INTL: ISO space */
	    if (!(flags & TK_IGNORE_NEWLINES)) {
		if ((*start == '\n') || (*start == '\r')) {
		    break;
		}
	    }
	    if (!(flags & TK_IGNORE_TABS)) {
		if (*start == '\t') {
2294
2295
2296
2297
2298
2299
2300
2301

2302
2303
2304
2305
2306




2307
2308
2309
2310
2311
2312
2313
2289
2290
2291
2292
2293
2294
2295

2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312







-
+





+
+
+
+







    GC gc,			/* Graphics context to use for drawing
				 * text. */
    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 firstChar,		/* The index of the first character to draw
				 * from the given text item. 0 specfies the
				 * from the given text item. 0 specifies the
				 * beginning. */
    int lastChar)		/* The index just after the last character to
				 * draw from the given text item. A number < 0
				 * means to draw all characters. */
{
#if 0
    /* Use TkDrawAngledTextLayout() implementation - testing purposes at this point */
    TkDrawAngledTextLayout(display, drawable, gc, layout, x, y, 0.0, firstChar, lastChar);
#else
    TextLayout *layoutPtr = (TextLayout *) layout;
    int i, numDisplayChars, drawX;
    const char *firstByte, *lastByte;
    LayoutChunk *chunkPtr;

    if (layoutPtr == NULL) {
	return;
2329
2330
2331
2332
2333
2334
2335






2336
2337

2338
2339
2340
2341
2342
2343
2344
2345

2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360

2361
2362
2363
2364
2365
2366
2367
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366

2367
2368
2369
2370
2371
2372
2373
2374







+
+
+
+
+
+


+








+














-
+







		Tk_MeasureChars(layoutPtr->tkfont, chunkPtr->start,
			firstByte - chunkPtr->start, -1, 0, &drawX);
	    }
	    if (lastChar < numDisplayChars) {
		numDisplayChars = lastChar;
	    }
	    lastByte = Tcl_UtfAtIndex(chunkPtr->start, numDisplayChars);
#ifdef TK_DRAW_IN_CONTEXT
	    TkpDrawCharsInContext(display, drawable, gc, layoutPtr->tkfont,
		    chunkPtr->start, chunkPtr->numBytes,
		    firstByte - chunkPtr->start, lastByte - firstByte,
		    x+chunkPtr->x, y+chunkPtr->y);
#else /* !TK_DRAW_IN_CONTEXT */
	    Tk_DrawChars(display, drawable, gc, layoutPtr->tkfont, firstByte,
		    lastByte - firstByte, x+chunkPtr->x+drawX, y+chunkPtr->y);
#endif /* TK_DRAW_IN_CONTEXT */
	}
	firstChar -= chunkPtr->numChars;
	lastChar -= chunkPtr->numChars;
	if (lastChar <= 0) {
	    break;
	}
	chunkPtr++;
    }
#endif /* Use TkDrawAngledTextLayout() implementation */
}

void
TkDrawAngledTextLayout(
    Display *display,		/* Display on which to draw. */
    Drawable drawable,		/* Window or pixmap in which to draw. */
    GC gc,			/* Graphics context to use for drawing
				 * text. */
    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). */
    double angle,
    int firstChar,		/* The index of the first character to draw
				 * from the given text item. 0 specfies the
				 * from the given text item. 0 specifies the
				 * beginning. */
    int lastChar)		/* The index just after the last character to
				 * draw from the given text item. A number < 0
				 * means to draw all characters. */
{
    TextLayout *layoutPtr = (TextLayout *) layout;
    int i, numDisplayChars, drawX;
2391
2392
2393
2394
2395
2396
2397















2398
2399
2400
2401
2402
2403
2404
2405
2406
2407

2408
2409
2410
2411
2412
2413
2414
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+










+







		Tk_MeasureChars(layoutPtr->tkfont, chunkPtr->start,
			firstByte - chunkPtr->start, -1, 0, &drawX);
	    }
	    if (lastChar < numDisplayChars) {
		numDisplayChars = lastChar;
	    }
	    lastByte = Tcl_UtfAtIndex(chunkPtr->start, numDisplayChars);
#ifdef TK_DRAW_IN_CONTEXT
	    dx = cosA * (chunkPtr->x) + sinA * (chunkPtr->y);
	    dy = -sinA * (chunkPtr->x) + cosA * (chunkPtr->y);
	    if (angle == 0.0) {
		TkpDrawCharsInContext(display, drawable, gc,
			layoutPtr->tkfont, chunkPtr->start, chunkPtr->numBytes,
			firstByte - chunkPtr->start, lastByte - firstByte,
			(int)(x + dx), (int)(y + dy));
	    } else {
		TkpDrawAngledCharsInContext(display, drawable, gc,
			layoutPtr->tkfont, chunkPtr->start, chunkPtr->numBytes,
			firstByte - chunkPtr->start, lastByte - firstByte,
			x+dx, y+dy, angle);
	    }
#else /* !TK_DRAW_IN_CONTEXT */
	    dx = cosA * (chunkPtr->x + drawX) + sinA * (chunkPtr->y);
	    dy = -sinA * (chunkPtr->x + drawX) + cosA * (chunkPtr->y);
	    if (angle == 0.0) {
		Tk_DrawChars(display, drawable, gc, layoutPtr->tkfont,
			firstByte, lastByte - firstByte,
			(int)(x + dx), (int)(y + dy));
	    } else {
		TkDrawAngledChars(display, drawable, gc, layoutPtr->tkfont,
			firstByte, lastByte - firstByte, x+dx, y+dy, angle);
	    }
#endif /* TK_DRAW_IN_CONTEXT */
	}
	firstChar -= chunkPtr->numChars;
	lastChar -= chunkPtr->numChars;
	if (lastChar <= 0) {
	    break;
	}
	chunkPtr++;
2710
2711
2712
2713
2714
2715
2716
2717

2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745

2746

2747
2748
2749
2750
2751
2752
2753
2754
2733
2734
2735
2736
2737
2738
2739

2740
2741
2742
2743
2744
2745
2746
2747
2748
2749

2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768

2769

2770
2771
2772
2773
2774
2775
2776







-
+









-


















+
-
+
-







				 * non-NULL. */
    int *widthPtr, int *heightPtr)
				/* Filled with the width and height of the
				 * bounding box for the character specified by
				 * index, if non-NULL. */
{
    TextLayout *layoutPtr = (TextLayout *) layout;
    LayoutChunk *chunkPtr;
    LayoutChunk *chunkPtr = layoutPtr->chunks;
    int i, x = 0, w;
    Tk_Font tkfont;
    TkFont *fontPtr;
    const char *end;

    if (index < 0) {
	return 0;
    }

    chunkPtr = layoutPtr->chunks;
    tkfont = layoutPtr->tkfont;
    fontPtr = (TkFont *) tkfont;

    for (i = 0; i < layoutPtr->numChunks; i++) {
	if (chunkPtr->numDisplayChars < 0) {
	    if (index == 0) {
		x = chunkPtr->x;
		w = chunkPtr->totalWidth;
		goto check;
	    }
	} else if (index < chunkPtr->numChars) {
	    end = Tcl_UtfAtIndex(chunkPtr->start, index);
	    if (xPtr != NULL) {
		Tk_MeasureChars(tkfont, chunkPtr->start,
			end - chunkPtr->start, -1, 0, &x);
		x += chunkPtr->x;
	    }
	    if (widthPtr != NULL) {
		int ch;
		Tk_MeasureChars(tkfont, end, Tcl_UtfNext(end) - end,
		Tk_MeasureChars(tkfont, end, TkUtfToUniChar(end, &ch), -1, 0, &w);
			-1, 0, &w);
	    }
	    goto check;
	}
	index -= chunkPtr->numChars;
	chunkPtr++;
    }
    if (index != 0) {
3259
3260
3261
3262
3263
3264
3265
3266


3267
3268
3269
3270
3271
3272
3273
3281
3282
3283
3284
3285
3286
3287

3288
3289
3290
3291
3292
3293
3294
3295
3296







-
+
+







    Tcl_Interp *interp,		/* Filled with Postscript code. */
    Tk_TextLayout layout)	/* The layout to be rendered. */
{
    TextLayout *layoutPtr = (TextLayout *) layout;
    LayoutChunk *chunkPtr = layoutPtr->chunks;
    int baseline = chunkPtr->y;
    Tcl_Obj *psObj = Tcl_NewObj();
    int i, j, len;
    int i, j;
    TkSizeT len;
    const char *p, *glyphname;
    char uindex[5], c, *ps;
    int ch;

    Tcl_AppendToObj(psObj, "[(", -1);
    for (i = 0; i < layoutPtr->numChunks; i++, chunkPtr++) {
	if (baseline != chunkPtr->y) {
3317
3318
3319
3320
3321
3322
3323
3324

3325
3326
3327
3328
3329
3330
3331
3340
3341
3342
3343
3344
3345
3346

3347
3348
3349
3350
3351
3352
3353
3354







-
+








	    if (ch > 0xffff) {
		goto noMapping;
	    }
	    sprintf(uindex, "%04X", ch);		/* endianness? */
	    glyphname = Tcl_GetVar2(interp, "::tk::psglyphs", uindex, 0);
	    if (glyphname) {
		ps = Tcl_GetStringFromObj(psObj, &len);
		ps = TkGetStringFromObj(psObj, &len);
		if (ps[len-1] == '(') {
		    /*
		     * In-place edit. Ewww!
		     */

		    ps[len-1] = '/';
		} else {
3372
3373
3374
3375
3376
3377
3378
3379

3380
3381
3382
3383
3384
3385
3386
3395
3396
3397
3398
3399
3400
3401

3402
3403
3404
3405
3406
3407
3408
3409







-
+







 *
 *---------------------------------------------------------------------------
 */

static int
ConfigAttributesObj(
    Tcl_Interp *interp,		/* Interp for error return. */
    Tk_Window tkwin,		/* For display on which font will be used. */
    TCL_UNUSED(Tk_Window),	/* For display on which font will be used. */
    int objc,			/* Number of elements in argv. */
    Tcl_Obj *const objv[],	/* Command line options. */
    TkFontAttributes *faPtr)	/* Font attributes structure whose fields are
				 * to be modified. Structure must already be
				 * properly initialized. */
{
    int i, n, index;
3508
3509
3510
3511
3512
3513
3514
3515

3516
3517

3518
3519
3520
3521
3522
3523
3524
3531
3532
3533
3534
3535
3536
3537

3538
3539

3540
3541
3542
3543
3544
3545
3546
3547







-
+

-
+







	case FONT_FAMILY:
	    str = faPtr->family;
	    valuePtr = Tcl_NewStringObj(str, ((str == NULL) ? 0 : -1));
	    break;

	case FONT_SIZE:
	    if (faPtr->size >= 0.0) {
		valuePtr = Tcl_NewIntObj((int)(faPtr->size + 0.5));
		valuePtr = Tcl_NewWideIntObj((Tcl_WideInt)(faPtr->size + 0.5));
	    } else {
		valuePtr = Tcl_NewIntObj(-(int)(-faPtr->size + 0.5));
		valuePtr = Tcl_NewWideIntObj(-(Tcl_WideInt)(-faPtr->size + 0.5));
	    }
	    break;

	case FONT_WEIGHT:
	    str = TkFindStateString(weightMap, faPtr->weight);
	    valuePtr = Tcl_NewStringObj(str, -1);
	    break;
3543
3544
3545
3546
3547
3548
3549



















































3550
3551
3552
3553
3554
3555
3556
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	Tcl_ListObjAppendElement(NULL, resultPtr,
		Tcl_NewStringObj(fontOpt[i], -1));
	Tcl_ListObjAppendElement(NULL, resultPtr, valuePtr);
    }
    Tcl_SetObjResult(interp, resultPtr);
    return TCL_OK;
}

/*
 *---------------------------------------------------------------------------
 *
 * Tk_FontGetDescription --
 *
 *	Return information about the font description as a Tcl list. One
 *	possible result is "{{DejaVu Sans} -16 bold underline}".
 *
 * Results:
 *	The list of descriptions.
 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

Tcl_Obj *
Tk_FontGetDescription(
    Tk_Font tkfont)		/* Font whose description is desired. */
{
    const TkFontAttributes *faPtr = GetFontAttributes(tkfont);
    Tcl_Obj *resultPtr = Tcl_NewObj();
    const char *str;

    str = faPtr->family;
    Tcl_ListObjAppendElement(NULL, resultPtr, Tcl_NewStringObj(str, str ? -1 : 0));
    if (faPtr->size >= 0.0) {
    	Tcl_ListObjAppendElement(NULL, resultPtr, Tcl_NewWideIntObj((int)(faPtr->size + 0.5)));
    } else {
    	Tcl_ListObjAppendElement(NULL, resultPtr, Tcl_NewWideIntObj(-(int)(-faPtr->size + 0.5)));
    }
    if (faPtr->weight != TK_FW_NORMAL) {
	str = TkFindStateString(weightMap, faPtr->weight);
	Tcl_ListObjAppendElement(NULL, resultPtr, Tcl_NewStringObj(str, -1));
    }
    if (faPtr->slant != TK_FS_ROMAN) {
	str = TkFindStateString(slantMap, faPtr->slant);
	Tcl_ListObjAppendElement(NULL, resultPtr, Tcl_NewStringObj(str, -1));
    }
    if (faPtr->underline) {
	str = TkFindStateString(underlineMap, faPtr->underline);
	Tcl_ListObjAppendElement(NULL, resultPtr, Tcl_NewStringObj(str, -1));
    }
    if (faPtr->overstrike) {
	str = TkFindStateString(overstrikeMap, faPtr->overstrike);
	Tcl_ListObjAppendElement(NULL, resultPtr, Tcl_NewStringObj(str, -1));
    }
    return resultPtr;
}

/*
 *---------------------------------------------------------------------------
 *
 * ParseFontNameObj --
 *
 *	Converts a object into a set of font attributes that can be used to
3747
3748
3749
3750
3751
3752
3753
3754
3755


3756
3757
3758
3759
3760
3761
3762
3821
3822
3823
3824
3825
3826
3827


3828
3829
3830
3831
3832
3833
3834
3835
3836







-
-
+
+







    int maxChunks, numChars;
    size_t s;

    layoutPtr = *layoutPtrPtr;
    maxChunks = *maxPtr;
    if (layoutPtr->numChunks == maxChunks) {
	maxChunks *= 2;
	s = sizeof(TextLayout) + ((maxChunks - 1) * sizeof(LayoutChunk));
	layoutPtr = ckrealloc(layoutPtr, s);
	s = offsetof(TextLayout, chunks) + (maxChunks * sizeof(LayoutChunk));
	layoutPtr = (TextLayout *)ckrealloc(layoutPtr, s);

	*layoutPtrPtr = layoutPtr;
	*maxPtr = maxChunks;
    }
    numChars = Tcl_NumUtfChars(start, numBytes);
    chunkPtr = &layoutPtr->chunks[layoutPtr->numChunks];
    chunkPtr->start		= start;
4211
4212
4213
4214
4215
4216
4217
4218

4219
4220
4221
4222
4223
4224
4225

4226
4227

4228
4229
4230
4231
4232
4233
4234
4285
4286
4287
4288
4289
4290
4291

4292
4293
4294
4295
4296
4297
4298

4299
4300

4301
4302
4303
4304
4305
4306
4307
4308







-
+






-
+

-
+







    Tcl_HashEntry *hashPtr;
    Tcl_Obj *resultPtr, *objPtr;

    resultPtr = Tcl_NewObj();
    hashPtr = Tcl_FindHashEntry(
	    &((TkWindow *) tkwin)->mainPtr->fontInfoPtr->fontCache, name);
    if (hashPtr != NULL) {
	fontPtr = Tcl_GetHashValue(hashPtr);
	fontPtr = (TkFont *)Tcl_GetHashValue(hashPtr);
	if (fontPtr == NULL) {
	    Tcl_Panic("TkDebugFont found empty hash table entry");
	}
	for ( ; (fontPtr != NULL); fontPtr = fontPtr->nextPtr) {
	    objPtr = Tcl_NewObj();
	    Tcl_ListObjAppendElement(NULL, objPtr,
		    Tcl_NewIntObj(fontPtr->resourceRefCount));
		    Tcl_NewWideIntObj(fontPtr->resourceRefCount));
	    Tcl_ListObjAppendElement(NULL, objPtr,
		    Tcl_NewIntObj(fontPtr->objRefCount));
		    Tcl_NewWideIntObj(fontPtr->objRefCount));
	    Tcl_ListObjAppendElement(NULL, resultPtr, objPtr);
	}
    }
    return resultPtr;
}

/*
4264
4265
4266
4267
4268
4269
4270
4271

4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4338
4339
4340
4341
4342
4343
4344

4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356







-
+











    if ((layoutPtr == NULL) || (layoutPtr->numChunks == 0)
	    || (layoutPtr->chunks->numDisplayChars <= 0)) {
	dst[0] = '\0';
	return 0;
    }
    chunkPtr = layoutPtr->chunks;
    numBytesInChunk = chunkPtr->numBytes;
    strncpy(dst, chunkPtr->start, (size_t) numBytesInChunk);
    strncpy(dst, chunkPtr->start, numBytesInChunk);
    *font = layoutPtr->tkfont;
    return numBytesInChunk;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Changes to generic/tkFont.h.
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15




16
17
18
19
20
21
22
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26







-
+







+
+
+
+







/*
 * tkFont.h --
 *
 *	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.
 */

#ifndef _TKFONT
#define _TKFONT

#ifdef __cplusplus
extern "C" {
#endif

/*
 * The following structure keeps track of the attributes of a font. It can be
 * used to keep track of either the desired attributes or the actual
 * attributes gotten when the font was instantiated.
 */

81
82
83
84
85
86
87
88

89
90
91
92
93
94
95
96
97
98

99
100
101
102
103
104
105
85
86
87
88
89
90
91

92
93
94
95
96
97
98
99
100
101

102
103
104
105
106
107
108
109







-
+









-
+







 */

typedef struct TkFont {
    /*
     * Fields used and maintained exclusively by generic code.
     */

    int resourceRefCount;	/* Number of active uses of this font (each
    TkSizeT resourceRefCount;	/* Number of active uses of this font (each
				 * active use corresponds to a call to
				 * Tk_AllocFontFromTable or Tk_GetFont). If
				 * this count is 0, then this TkFont structure
				 * is no longer valid and it isn't present in
				 * a hash table: it is being kept around only
				 * because there are objects referring to it.
				 * The structure is freed when
				 * resourceRefCount and objRefCount are both
				 * 0. */
    int objRefCount;		/* The number of Tcl objects that reference
    TkSizeT objRefCount;		/* The number of Tcl objects that reference
				 * this structure. */
    Tcl_HashEntry *cacheHashPtr;/* Entry in font cache for this structure,
				 * used when deleting it. */
    Tcl_HashEntry *namedHashPtr;/* Pointer to hash table entry that
				 * corresponds to the named font that the
				 * tkfont was based on, or NULL if the tkfont
				 * was not based on a named font. */
216
217
218
219
220
221
222
223




224
220
221
222
223
224
225
226
227
228
229
230
231
232








+
+
+
+

MODULE_SCOPE void	TkpDeleteFont(TkFont *tkFontPtr);
MODULE_SCOPE void	TkpFontPkgInit(TkMainInfo *mainPtr);
MODULE_SCOPE TkFont *	TkpGetFontFromAttributes(TkFont *tkFontPtr,
			    Tk_Window tkwin, const TkFontAttributes *faPtr);
MODULE_SCOPE void	TkpGetFontFamilies(Tcl_Interp *interp,
			    Tk_Window tkwin);
MODULE_SCOPE TkFont *	TkpGetNativeFont(Tk_Window tkwin, const char *name);

#ifdef __cplusplus
}
#endif

#endif	/* _TKFONT */
Changes to generic/tkFrame.c.
1
2
3
4
5
6
7
8
9


10
11
12
13
14
15
16


17
18
19
20
21
22
23
1
2
3
4
5
6
7


8
9
10
11
12
13
14


15
16
17
18
19
20
21
22
23







-
-
+
+





-
-
+
+







/*
 * tkFrame.c --
 *
 *	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.
 */

#include "default.h"
#include "tkInt.h"
#include "tkInt.h"
#include "default.h"

/*
 * The following enum is used to define the type of the frame.
 */

enum FrameType {
    TYPE_FRAME, TYPE_TOPLEVEL, TYPE_LABELFRAME
90
91
92
93
94
95
96










97
98
99
100
101
102
103
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113







+
+
+
+
+
+
+
+
+
+







				 * pixels of extra space to leave on left and
				 * right of child area. */
    int padX;			/* Integer value corresponding to padXPtr. */
    Tcl_Obj *padYPtr;		/* Value of -padx option: specifies how many
				 * pixels of extra space to leave above and
				 * below child area. */
    int padY;			/* Integer value corresponding to padYPtr. */
    Tcl_Obj *bgimgPtr;		/* Value of -backgroundimage option: specifies
				 * image to display on window's background, or
				 * NULL if none. */
    Tk_Image bgimg;		/* Derived from bgimgPtr by calling
				 * Tk_GetImage, or NULL if bgimgPtr is
				 * NULL. */
    int tile;			/* Whether to tile the bgimg. */
#ifndef TK_NO_DOUBLE_BUFFERING
    GC copyGC;			/* GC for copying when double-buffering. */
#endif /* TK_NO_DOUBLE_BUFFERING */
} Frame;

/*
 * A data structure of the following type is kept for each labelframe widget
 * managed by this file:
 */

170
171
172
173
174
175
176
177

178
179
180

181
182

183
184
185
186
187
188
189

190
191

192
193
194

195
196
197


198
199

200
201
202
203


204
205
206


207
208
209


210
211

212
213
214

215
216
217

218
219
220
221



222
223



224
225

226
227

228
229



230
231
232
233
234



235
236



237
238

239
240

241
242

243
244
245

246
247

248


249
250

251
252
253
254
255
256
257
258

259
260

261
262
263

264
265

266
267

268
269

270
271

272
273
274

275
276

277
278

279
280
281
282
283
284
285
180
181
182
183
184
185
186

187
188
189

190
191

192
193
194
195
196
197
198

199
200

201
202
203

204
205


206
207
208

209
210
211


212
213
214


215
216
217


218
219
220

221
222
223

224
225
226

227
228
229
230
231
232
233
234
235

236
237
238
239

240
241

242
243

244
245
246
247
248
249
250
251
252
253
254
255

256
257
258
259

260
261

262
263

264
265
266

267
268

269
270
271
272
273

274
275
276
277
278
279
280
281

282
283

284
285
286

287
288

289
290

291
292

293
294

295
296
297

298
299

300
301

302
303
304
305
306
307
308
309







-
+


-
+

-
+






-
+

-
+


-
+

-
-
+
+

-
+


-
-
+
+

-
-
+
+

-
-
+
+

-
+


-
+


-
+




+
+
+

-
+
+
+

-
+

-
+

-
+
+
+





+
+
+

-
+
+
+

-
+

-
+

-
+


-
+

-
+

+
+

-
+







-
+

-
+


-
+

-
+

-
+

-
+

-
+


-
+

-
+

-
+







/*
 * Information used for parsing configuration options. There are one common
 * table used by all and one table for each widget class.
 */

static const Tk_OptionSpec commonOptSpec[] = {
    {TK_OPTION_BORDER, "-background", "background", "Background",
	DEF_FRAME_BG_COLOR, -1, Tk_Offset(Frame, border),
	DEF_FRAME_BG_COLOR, TCL_INDEX_NONE, offsetof(Frame, border),
	TK_OPTION_NULL_OK, DEF_FRAME_BG_MONO, 0},
    {TK_OPTION_SYNONYM, "-bg", NULL, NULL,
	NULL, 0, -1, 0, "-background", 0},
	NULL, 0, TCL_INDEX_NONE, 0, "-background", 0},
    {TK_OPTION_STRING, "-colormap", "colormap", "Colormap",
	DEF_FRAME_COLORMAP, -1, Tk_Offset(Frame, colormapName),
	DEF_FRAME_COLORMAP, TCL_INDEX_NONE, offsetof(Frame, colormapName),
	TK_OPTION_NULL_OK, 0, 0},
    /*
     * Having -container is useless in a labelframe since a container has
     * no border. It should be deprecated.
     */
    {TK_OPTION_BOOLEAN, "-container", "container", "Container",
	DEF_FRAME_CONTAINER, -1, Tk_Offset(Frame, isContainer), 0, 0, 0},
	DEF_FRAME_CONTAINER, TCL_INDEX_NONE, offsetof(Frame, isContainer), 0, 0, 0},
    {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
	DEF_FRAME_CURSOR, -1, Tk_Offset(Frame, cursor),
	DEF_FRAME_CURSOR, TCL_INDEX_NONE, offsetof(Frame, cursor),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_PIXELS, "-height", "height", "Height",
	DEF_FRAME_HEIGHT, -1, Tk_Offset(Frame, height), 0, 0, 0},
	DEF_FRAME_HEIGHT, TCL_INDEX_NONE, offsetof(Frame, height), 0, 0, 0},
    {TK_OPTION_COLOR, "-highlightbackground", "highlightBackground",
	"HighlightBackground", DEF_FRAME_HIGHLIGHT_BG, -1,
	Tk_Offset(Frame, highlightBgColorPtr), 0, 0, 0},
	"HighlightBackground", DEF_FRAME_HIGHLIGHT_BG, TCL_INDEX_NONE,
	offsetof(Frame, highlightBgColorPtr), 0, 0, 0},
    {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
	DEF_FRAME_HIGHLIGHT, -1, Tk_Offset(Frame, highlightColorPtr),
	DEF_FRAME_HIGHLIGHT, TCL_INDEX_NONE, offsetof(Frame, highlightColorPtr),
	0, 0, 0},
    {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
	"HighlightThickness", DEF_FRAME_HIGHLIGHT_WIDTH, -1,
	Tk_Offset(Frame, highlightWidth), 0, 0, 0},
	"HighlightThickness", DEF_FRAME_HIGHLIGHT_WIDTH, TCL_INDEX_NONE,
	offsetof(Frame, highlightWidth), 0, 0, 0},
    {TK_OPTION_PIXELS, "-padx", "padX", "Pad",
	DEF_FRAME_PADX, Tk_Offset(Frame, padXPtr),
	Tk_Offset(Frame, padX), 0, 0, 0},
	DEF_FRAME_PADX, offsetof(Frame, padXPtr),
	offsetof(Frame, padX), 0, 0, 0},
    {TK_OPTION_PIXELS, "-pady", "padY", "Pad",
	DEF_FRAME_PADY, Tk_Offset(Frame, padYPtr),
	Tk_Offset(Frame, padY), 0, 0, 0},
	DEF_FRAME_PADY, offsetof(Frame, padYPtr),
	offsetof(Frame, padY), 0, 0, 0},
    {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
	DEF_FRAME_TAKE_FOCUS, -1, Tk_Offset(Frame, takeFocus),
	DEF_FRAME_TAKE_FOCUS, TCL_INDEX_NONE, offsetof(Frame, takeFocus),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_STRING, "-visual", "visual", "Visual",
	DEF_FRAME_VISUAL, -1, Tk_Offset(Frame, visualName),
	DEF_FRAME_VISUAL, TCL_INDEX_NONE, offsetof(Frame, visualName),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_PIXELS, "-width", "width", "Width",
	DEF_FRAME_WIDTH, -1, Tk_Offset(Frame, width), 0, 0, 0},
	DEF_FRAME_WIDTH, TCL_INDEX_NONE, offsetof(Frame, width), 0, 0, 0},
    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0}
};

static const Tk_OptionSpec frameOptSpec[] = {
    {TK_OPTION_STRING, "-backgroundimage", "backgroundImage", "BackgroundImage",
	DEF_FRAME_BG_IMAGE, offsetof(Frame, bgimgPtr), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_SYNONYM, "-bd", NULL, NULL,
	NULL, 0, -1, 0, "-borderwidth", 0},
	NULL, 0, TCL_INDEX_NONE, 0, "-borderwidth", 0},
    {TK_OPTION_SYNONYM, "-bgimg", NULL, NULL,
	NULL, 0, TCL_INDEX_NONE, 0, "-backgroundimage", 0},
    {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
	DEF_FRAME_BORDER_WIDTH, -1, Tk_Offset(Frame, borderWidth), 0, 0, 0},
	DEF_FRAME_BORDER_WIDTH, TCL_INDEX_NONE, offsetof(Frame, borderWidth), 0, 0, 0},
    {TK_OPTION_STRING, "-class", "class", "Class",
	DEF_FRAME_CLASS, -1, Tk_Offset(Frame, className), 0, 0, 0},
	DEF_FRAME_CLASS, TCL_INDEX_NONE, offsetof(Frame, className), 0, 0, 0},
    {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
	DEF_FRAME_RELIEF, -1, Tk_Offset(Frame, relief), 0, 0, 0},
	DEF_FRAME_RELIEF, TCL_INDEX_NONE, offsetof(Frame, relief), 0, 0, 0},
    {TK_OPTION_BOOLEAN, "-tile", "tile", "Tile",
	DEF_FRAME_BG_TILE, TCL_INDEX_NONE, offsetof(Frame, tile), 0, 0, 0},
    {TK_OPTION_END, NULL, NULL, NULL,
	NULL, 0, 0, 0, commonOptSpec, 0}
};

static const Tk_OptionSpec toplevelOptSpec[] = {
    {TK_OPTION_STRING, "-backgroundimage", "backgroundImage", "BackgroundImage",
	DEF_FRAME_BG_IMAGE, offsetof(Frame, bgimgPtr), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_SYNONYM, "-bd", NULL, NULL,
	NULL, 0, -1, 0, "-borderwidth", 0},
	NULL, 0, TCL_INDEX_NONE, 0, "-borderwidth", 0},
    {TK_OPTION_SYNONYM, "-bgimg", NULL, NULL,
	NULL, 0, TCL_INDEX_NONE, 0, "-backgroundimage", 0},
    {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
	DEF_FRAME_BORDER_WIDTH, -1, Tk_Offset(Frame, borderWidth), 0, 0, 0},
	DEF_FRAME_BORDER_WIDTH, TCL_INDEX_NONE, offsetof(Frame, borderWidth), 0, 0, 0},
    {TK_OPTION_STRING, "-class", "class", "Class",
	DEF_TOPLEVEL_CLASS, -1, Tk_Offset(Frame, className), 0, 0, 0},
	DEF_TOPLEVEL_CLASS, TCL_INDEX_NONE, offsetof(Frame, className), 0, 0, 0},
    {TK_OPTION_STRING, "-menu", "menu", "Menu",
	DEF_TOPLEVEL_MENU, -1, Tk_Offset(Frame, menuName),
	DEF_TOPLEVEL_MENU, TCL_INDEX_NONE, offsetof(Frame, menuName),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
	DEF_FRAME_RELIEF, -1, Tk_Offset(Frame, relief), 0, 0, 0},
	DEF_FRAME_RELIEF, TCL_INDEX_NONE, offsetof(Frame, relief), 0, 0, 0},
    {TK_OPTION_STRING, "-screen", "screen", "Screen",
	DEF_TOPLEVEL_SCREEN, -1, Tk_Offset(Frame, screenName),
	DEF_TOPLEVEL_SCREEN, TCL_INDEX_NONE, offsetof(Frame, screenName),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_BOOLEAN, "-tile", "tile", "Tile",
	DEF_FRAME_BG_TILE, TCL_INDEX_NONE, offsetof(Frame, tile), 0, 0, 0},
    {TK_OPTION_STRING, "-use", "use", "Use",
	DEF_TOPLEVEL_USE, -1, Tk_Offset(Frame, useThis),
	DEF_TOPLEVEL_USE, TCL_INDEX_NONE, offsetof(Frame, useThis),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_END, NULL, NULL, NULL,
	NULL, 0, 0, 0, commonOptSpec, 0}
};

static const Tk_OptionSpec labelframeOptSpec[] = {
    {TK_OPTION_SYNONYM, "-bd", NULL, NULL,
	NULL, 0, -1, 0, "-borderwidth", 0},
	NULL, 0, TCL_INDEX_NONE, 0, "-borderwidth", 0},
    {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
	DEF_LABELFRAME_BORDER_WIDTH, -1, Tk_Offset(Frame, borderWidth),
	DEF_LABELFRAME_BORDER_WIDTH, TCL_INDEX_NONE, offsetof(Frame, borderWidth),
	0, 0, 0},
    {TK_OPTION_STRING, "-class", "class", "Class",
	DEF_LABELFRAME_CLASS, -1, Tk_Offset(Frame, className), 0, 0, 0},
	DEF_LABELFRAME_CLASS, TCL_INDEX_NONE, offsetof(Frame, className), 0, 0, 0},
    {TK_OPTION_SYNONYM, "-fg", "foreground", NULL,
	NULL, 0, -1, 0, "-foreground", 0},
	NULL, 0, TCL_INDEX_NONE, 0, "-foreground", 0},
    {TK_OPTION_FONT, "-font", "font", "Font",
	DEF_LABELFRAME_FONT, -1, Tk_Offset(Labelframe, tkfont), 0, 0, 0},
	DEF_LABELFRAME_FONT, TCL_INDEX_NONE, offsetof(Labelframe, tkfont), 0, 0, 0},
    {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
	DEF_LABELFRAME_FG, -1, Tk_Offset(Labelframe, textColorPtr), 0, 0, 0},
	DEF_LABELFRAME_FG, TCL_INDEX_NONE, offsetof(Labelframe, textColorPtr), 0, 0, 0},
    {TK_OPTION_STRING_TABLE, "-labelanchor", "labelAnchor", "LabelAnchor",
	DEF_LABELFRAME_LABELANCHOR, -1, Tk_Offset(Labelframe, labelAnchor),
	DEF_LABELFRAME_LABELANCHOR, TCL_INDEX_NONE, offsetof(Labelframe, labelAnchor),
	0, labelAnchorStrings, 0},
    {TK_OPTION_WINDOW, "-labelwidget", "labelWidget", "LabelWidget",
	NULL, -1, Tk_Offset(Labelframe, labelWin), TK_OPTION_NULL_OK, 0, 0},
	NULL, TCL_INDEX_NONE, offsetof(Labelframe, labelWin), TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
	DEF_LABELFRAME_RELIEF, -1, Tk_Offset(Frame, relief), 0, 0, 0},
	DEF_LABELFRAME_RELIEF, TCL_INDEX_NONE, offsetof(Frame, relief), 0, 0, 0},
    {TK_OPTION_STRING, "-text", "text", "Text",
	DEF_LABELFRAME_TEXT, Tk_Offset(Labelframe, textPtr), -1,
	DEF_LABELFRAME_TEXT, offsetof(Labelframe, textPtr), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_END, NULL, NULL, NULL,
	NULL, 0, 0, 0, commonOptSpec, 0}
};

/*
 * Class names for widgets, indexed by FrameType.
307
308
309
310
311
312
313






314
315
316
317

318
319
320
321
322
323
324
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346

347
348
349
350
351
352
353
354







+
+
+
+
+
+



-
+







			    int objc, Tcl_Obj *const objv[]);
static int		CreateFrame(ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *const argv[],
			    enum FrameType type, const char *appName);
static void		DestroyFrame(void *memPtr);
static void		DestroyFramePartly(Frame *framePtr);
static void		DisplayFrame(ClientData clientData);
static void		DrawFrameBackground(Tk_Window tkwin, Pixmap pixmap,
			    int highlightWidth, int borderWidth,
			    Tk_Image bgimg, int bgtile);
static void		FrameBgImageProc(ClientData clientData,
			    int x, int y, int width, int height,
			    int imgWidth, int imgHeight);
static void		FrameCmdDeletedProc(ClientData clientData);
static void		FrameEventProc(ClientData clientData,
			    XEvent *eventPtr);
static void		FrameLostSlaveProc(ClientData clientData,
static void		FrameLostContentProc(ClientData clientData,
			    Tk_Window tkwin);
static void		FrameRequestProc(ClientData clientData,
			    Tk_Window tkwin);
static void		FrameStructureProc(ClientData clientData,
			    XEvent *eventPtr);
static int		FrameWidgetObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
342
343
344
345
346
347
348
349

350
351
352
353
354
355
356
372
373
374
375
376
377
378

379
380
381
382
383
384
385
386







-
+







 * The structure below defines the official type record for the labelframe's
 * geometry manager:
 */

static const Tk_GeomMgr frameGeomType = {
    "labelframe",		/* name */
    FrameRequestProc,		/* requestProc */
    FrameLostSlaveProc		/* lostSlaveProc */
    FrameLostContentProc		/* lostContentProc */
};

/*
 *--------------------------------------------------------------
 *
 * Tk_FrameObjCmd, Tk_ToplevelObjCmd, Tk_LabelframeObjCmd --
 *
427
428
429
430
431
432
433
434

435
436
437
438
439
440
441
457
458
459
460
461
462
463

464
465
466
467
468
469
470
471







-
+







				 * zero means create a frame. */
    const char *appName)	/* Should only be non-NULL if there is no main
				 * window associated with the interpreter.
				 * Gives the base name to use for the new
				 * application. */
{
    int result, i;
    Tcl_Obj **objv = ckalloc((argc+1) * sizeof(Tcl_Obj **));
    Tcl_Obj **objv = (Tcl_Obj **)ckalloc((argc+1) * sizeof(Tcl_Obj **));

    for (i=0; i<argc; i++) {
	objv[i] = Tcl_NewStringObj(argv[i], -1);
	Tcl_IncrRefCount(objv[i]);
    }
    objv[argc] = NULL;
    result = CreateFrame(clientData, interp, argc, objv,
468
469
470
471
472
473
474
475

476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491


492
493
494

495
496
497
498
499
500
501
498
499
500
501
502
503
504

505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520

521
522
523
524
525
526
527
528
529
530
531
532
533







-
+















-
+
+



+







    return CreateFrame(clientData, interp, objc, objv,
	    toplevel ? TYPE_TOPLEVEL : TYPE_FRAME,
	    nameObj ? Tcl_GetString(nameObj) : NULL);
}

static int
CreateFrame(
    ClientData clientData,	/* NULL. */
    ClientData dummy,	/* NULL. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[],	/* Argument objects. */
    enum FrameType type,	/* What widget type to create. */
    const char *appName)	/* Should only be non-NULL if there are no
				 * Main window associated with the
				 * interpreter. Gives the base name to use for
				 * the new application. */
{
    Tk_Window tkwin;
    Frame *framePtr;
    Tk_OptionTable optionTable;
    Tk_Window newWin;
    const char *className, *screenName, *visualName, *colormapName;
    const char *arg, *useOption;
    int i, length, depth;
    int i, depth;
    TkSizeT length;
    unsigned int mask;
    Colormap colormap;
    Visual *visual;
    (void)dummy;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "pathName ?-option value ...?");
	return TCL_ERROR;
    }

    /*
511
512
513
514
515
516
517
518

519
520
521
522
523

524
525
526

527
528
529

530
531
532

533
534
535

536
537
538
539
540
541
542
543
544
545
546
547
548
549

550
551
552
553
554

555
556
557

558
559
560

561
562
563

564
565
566

567
568
569
570
571
572
573
574







-
+




-
+


-
+


-
+


-
+


-
+







     * be processed specially, before the window is configured using the usual
     * Tk mechanisms.
     */

    className = colormapName = screenName = visualName = useOption = NULL;
    colormap = None;
    for (i = 2; i < objc; i += 2) {
	arg = Tcl_GetStringFromObj(objv[i], &length);
	arg = TkGetStringFromObj(objv[i], &length);
	if (length < 2) {
	    continue;
	}
	if ((arg[1] == 'c') && (length >= 3)
		&& (strncmp(arg, "-class", (unsigned) length) == 0)) {
		&& (strncmp(arg, "-class", length) == 0)) {
	    className = Tcl_GetString(objv[i+1]);
	} else if ((arg[1] == 'c') && (length >= 3)
		&& (strncmp(arg, "-colormap", (unsigned) length) == 0)) {
		&& (strncmp(arg, "-colormap", length) == 0)) {
	    colormapName = Tcl_GetString(objv[i+1]);
	} else if ((arg[1] == 's') && (type == TYPE_TOPLEVEL)
		&& (strncmp(arg, "-screen", (unsigned) length) == 0)) {
		&& (strncmp(arg, "-screen", length) == 0)) {
	    screenName = Tcl_GetString(objv[i+1]);
	} else if ((arg[1] == 'u') && (type == TYPE_TOPLEVEL)
		&& (strncmp(arg, "-use", (unsigned) length) == 0)) {
		&& (strncmp(arg, "-use", length) == 0)) {
	    useOption = Tcl_GetString(objv[i+1]);
	} else if ((arg[1] == 'v')
		&& (strncmp(arg, "-visual", (unsigned) length) == 0)) {
		&& (strncmp(arg, "-visual", length) == 0)) {
	    visualName = Tcl_GetString(objv[i+1]);
	}
    }

    /*
     * Create the window, and deal with the special options -use, -classname,
     * -colormap, -screenname, and -visual. These options must be handle
643
644
645
646
647
648
649
650

651
652
653

654
655
656
657
658
659
660
675
676
677
678
679
680
681

682
683
684

685
686
687
688
689
690
691
692







-
+


-
+







    /*
     * Create the widget record, process configuration options, and create
     * event handlers. Then fill in a few additional fields in the widget
     * record from the special options.
     */

    if (type == TYPE_LABELFRAME) {
	framePtr = ckalloc(sizeof(Labelframe));
	framePtr = (Frame *)ckalloc(sizeof(Labelframe));
	memset(framePtr, 0, sizeof(Labelframe));
    } else {
	framePtr = ckalloc(sizeof(Frame));
	framePtr = (Frame *)ckalloc(sizeof(Frame));
	memset(framePtr, 0, sizeof(Frame));
    }
    framePtr->tkwin = newWin;
    framePtr->display = Tk_Display(newWin);
    framePtr->interp = interp;
    framePtr->widgetCmd	= Tcl_CreateObjCommand(interp, Tk_PathName(newWin),
	    FrameWidgetObjCmd, framePtr, FrameCmdDeletedProc);
678
679
680
681
682
683
684
685

686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703

704
705
706
707
708
709
710
710
711
712
713
714
715
716

717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734

735
736
737
738
739
740
741
742







-
+

















-
+







    Tk_SetClassProcs(newWin, &frameClass, framePtr);

    mask = ExposureMask | StructureNotifyMask | FocusChangeMask;
    if (type == TYPE_TOPLEVEL) {
	mask |= ActivateMask;
    }
    Tk_CreateEventHandler(newWin, mask, FrameEventProc, framePtr);
    if ((Tk_InitOptions(interp, (char *) framePtr, optionTable, newWin)
    if ((Tk_InitOptions(interp, framePtr, optionTable, newWin)
	    != TCL_OK) ||
	    (ConfigureFrame(interp, framePtr, objc-2, objv+2) != TCL_OK)) {
	goto error;
    }
    if (framePtr->isContainer) {
	if (framePtr->useThis != NULL) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "windows cannot have both the -use and the -container"
		    " option set", -1));
	    Tcl_SetErrorCode(interp, "TK", "FRAME", "CONTAINMENT", NULL);
	    goto error;
	}
	TkpMakeContainer(framePtr->tkwin);
    }
    if (type == TYPE_TOPLEVEL) {
	Tcl_DoWhenIdle(MapFrame, framePtr);
    }
    Tcl_SetObjResult(interp, TkNewWindowObj(newWin));
    Tcl_SetObjResult(interp, Tk_NewWindowObj(newWin));
    return TCL_OK;

  error:
    if (newWin != NULL) {
	Tk_DestroyWindow(newWin);
    }
    return TCL_ERROR;
737
738
739
740
741
742
743
744

745
746


747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765

766
767
768
769
770
771
772
773
774
775

776
777
778
779
780
781
782
783
784
785
786
787
788
789
790

791
792
793
794
795
796
797

798
799

800
801

802
803

804
805

806
807

808
809

810
811
812
813
814
815
816
769
770
771
772
773
774
775

776
777

778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797

798
799
800
801
802
803
804
805
806
807

808
809
810
811
812
813
814
815
816
817
818
819
820
821
822

823
824
825
826
827
828
829

830
831

832
833

834
835

836
837

838
839

840
841

842
843
844
845
846
847
848
849







-
+

-
+
+


















-
+









-
+














-
+






-
+

-
+

-
+

-
+

-
+

-
+

-
+







{
    static const char *const frameOptions[] = {
	"cget", "configure", NULL
    };
    enum options {
	FRAME_CGET, FRAME_CONFIGURE
    };
    register Frame *framePtr = clientData;
    Frame *framePtr = (Frame *)clientData;
    int result = TCL_OK, index;
    int c, i, length;
    int c, i;
    TkSizeT length;
    Tcl_Obj *objPtr;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
	return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObjStruct(interp, objv[1], frameOptions,
	    sizeof(char *), "option", 0, &index) != TCL_OK) {
	return TCL_ERROR;
    }
    Tcl_Preserve(framePtr);
    switch ((enum options) index) {
    case FRAME_CGET:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "option");
	    result = TCL_ERROR;
	    goto done;
	}
	objPtr = Tk_GetOptionValue(interp, (char *) framePtr,
	objPtr = Tk_GetOptionValue(interp, framePtr,
		framePtr->optionTable, objv[2], framePtr->tkwin);
	if (objPtr == NULL) {
	    result = TCL_ERROR;
	    goto done;
	}
	Tcl_SetObjResult(interp, objPtr);
	break;
    case FRAME_CONFIGURE:
	if (objc <= 3) {
	    objPtr = Tk_GetOptionInfo(interp, (char *) framePtr,
	    objPtr = Tk_GetOptionInfo(interp, framePtr,
		    framePtr->optionTable, (objc == 3) ? objv[2] : NULL,
		    framePtr->tkwin);
	    if (objPtr == NULL) {
		result = TCL_ERROR;
		goto done;
	    }
	    Tcl_SetObjResult(interp, objPtr);
	} else {
	    /*
	     * Don't allow the options -class, -colormap, -container, -screen,
	     * -use, or -visual to be changed.
	     */

	    for (i = 2; i < objc; i++) {
		const char *arg = Tcl_GetStringFromObj(objv[i], &length);
		const char *arg = TkGetStringFromObj(objv[i], &length);

		if (length < 2) {
		    continue;
		}
		c = arg[1];
		if (((c == 'c') && (length >= 2)
			&& (strncmp(arg, "-class", (unsigned)length) == 0))
			&& (strncmp(arg, "-class", length) == 0))
		    || ((c == 'c') && (length >= 3)
			&& (strncmp(arg, "-colormap", (unsigned)length) == 0))
			&& (strncmp(arg, "-colormap", length) == 0))
		    || ((c == 'c') && (length >= 3)
			&& (strncmp(arg, "-container", (unsigned)length) == 0))
			&& (strncmp(arg, "-container", length) == 0))
		    || ((c == 's') && (framePtr->type == TYPE_TOPLEVEL)
			&& (strncmp(arg, "-screen", (unsigned)length) == 0))
			&& (strncmp(arg, "-screen", length) == 0))
		    || ((c == 'u') && (framePtr->type == TYPE_TOPLEVEL)
			&& (strncmp(arg, "-use", (unsigned)length) == 0))
			&& (strncmp(arg, "-use", length) == 0))
		    || ((c == 'v')
			&& (strncmp(arg, "-visual", (unsigned)length) == 0))) {
			&& (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) {
			    result = TCL_ERROR;
			    goto done;
855
856
857
858
859
860
861
862
863


864
865
866
867
868
869
870





871
872
873



874
875
876
877
878
879
880
888
889
890
891
892
893
894


895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921







-
-
+
+







+
+
+
+
+



+
+
+







 *----------------------------------------------------------------------
 */

static void
DestroyFrame(
    void *memPtr)		/* Info about frame widget. */
{
    register Frame *framePtr = memPtr;
    register Labelframe *labelframePtr = memPtr;
    Frame *framePtr = (Frame *)memPtr;
    Labelframe *labelframePtr = (Labelframe *)memPtr;

    if (framePtr->type == TYPE_LABELFRAME) {
	Tk_FreeTextLayout(labelframePtr->textLayout);
	if (labelframePtr->textGC != NULL) {
	    Tk_FreeGC(framePtr->display, labelframePtr->textGC);
	}
    }
#ifndef TK_NO_DOUBLE_BUFFERING
    if (framePtr->copyGC != NULL) {
	Tk_FreeGC(framePtr->display, framePtr->copyGC);
    }
#endif /* TK_NO_DOUBLE_BUFFERING */
    if (framePtr->colormap != None) {
	Tk_FreeColormap(framePtr->display, framePtr->colormap);
    }
    if (framePtr->bgimg) {
	Tk_FreeImage(framePtr->bgimg);
    }
    ckfree(framePtr);
}

/*
 *----------------------------------------------------------------------
 *
 * DestroyFramePartly --
892
893
894
895
896
897
898
899

900
901
902
903
904
905
906
933
934
935
936
937
938
939

940
941
942
943
944
945
946
947







-
+







 *----------------------------------------------------------------------
 */

static void
DestroyFramePartly(
    Frame *framePtr)		/* Info about frame widget. */
{
    register Labelframe *labelframePtr = (Labelframe *) framePtr;
    Labelframe *labelframePtr = (Labelframe *) framePtr;

    if (framePtr->type == TYPE_LABELFRAME && labelframePtr->labelWin != NULL) {
	Tk_DeleteEventHandler(labelframePtr->labelWin, StructureNotifyMask,
		FrameStructureProc, framePtr);
	Tk_ManageGeometry(labelframePtr->labelWin, NULL, NULL);
	if (framePtr->tkwin != Tk_Parent(labelframePtr->labelWin)) {
	    Tk_UnmaintainGeometry(labelframePtr->labelWin, framePtr->tkwin);
932
933
934
935
936
937
938
939

940
941
942
943
944
945
946
947

948
949
950
951
952
953
954
955
956

957
958
959
960
961
962
963

964
965
966
967
968
969
970














971
972
973
974
975
976
977
973
974
975
976
977
978
979

980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997

998
999
1000
1001
1002
1003
1004

1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033







-
+








+








-
+






-
+







+
+
+
+
+
+
+
+
+
+
+
+
+
+







 *
 *----------------------------------------------------------------------
 */

static int
ConfigureFrame(
    Tcl_Interp *interp,		/* Used for error reporting. */
    register Frame *framePtr,	/* Information about widget; may or may not
    Frame *framePtr,	/* Information about widget; may or may not
				 * already have values for some fields. */
    int objc,			/* Number of valid entries in objv. */
    Tcl_Obj *const objv[])	/* Arguments. */
{
    Tk_SavedOptions savedOptions;
    char *oldMenuName;
    Tk_Window oldWindow = NULL;
    Labelframe *labelframePtr = (Labelframe *) framePtr;
    Tk_Image image = NULL;

    /*
     * Need the old menubar name for the menu code to delete it.
     */

    if (framePtr->menuName == NULL) {
    	oldMenuName = NULL;
    } else {
    	oldMenuName = ckalloc(strlen(framePtr->menuName) + 1);
    	oldMenuName = (char *)ckalloc(strlen(framePtr->menuName) + 1);
    	strcpy(oldMenuName, framePtr->menuName);
    }

    if (framePtr->type == TYPE_LABELFRAME) {
	oldWindow = labelframePtr->labelWin;
    }
    if (Tk_SetOptions(interp, (char *) framePtr,
    if (Tk_SetOptions(interp, framePtr,
	    framePtr->optionTable, objc, objv,
	    framePtr->tkwin, &savedOptions, NULL) != TCL_OK) {
	if (oldMenuName != NULL) {
	    ckfree(oldMenuName);
	}
	return TCL_ERROR;
    }

    if (framePtr->bgimgPtr) {
	image = Tk_GetImage(interp, framePtr->tkwin,
		Tcl_GetString(framePtr->bgimgPtr), FrameBgImageProc, framePtr);
	if (image == NULL) {
	    Tk_RestoreSavedOptions(&savedOptions);
	    return TCL_ERROR;
	}
    }
    if (framePtr->bgimg) {
	Tk_FreeImage(framePtr->bgimg);
    }
    framePtr->bgimg = image;

    Tk_FreeSavedOptions(&savedOptions);

    /*
     * A few of the options require additional processing.
     */

    if ((((oldMenuName == NULL) && (framePtr->menuName != NULL))
1090
1091
1092
1093
1094
1095
1096
1097
1098


1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111









1112
1113
1114
1115
1116
1117
1118
1146
1147
1148
1149
1150
1151
1152


1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183







-
-
+
+













+
+
+
+
+
+
+
+
+







 *---------------------------------------------------------------------------
 */

static void
FrameWorldChanged(
    ClientData instanceData)	/* Information about widget. */
{
    Frame *framePtr = instanceData;
    Labelframe *labelframePtr = instanceData;
    Frame *framePtr = (Frame *)instanceData;
    Labelframe *labelframePtr = (Labelframe *)instanceData;
    Tk_Window tkwin = framePtr->tkwin;
    XGCValues gcValues;
    GC gc;
    int anyTextLabel, anyWindowLabel;
    int bWidthLeft, bWidthRight, bWidthTop, bWidthBottom;
    const char *labelText;

    anyTextLabel = (framePtr->type == TYPE_LABELFRAME) &&
	    (labelframePtr->textPtr != NULL) &&
	    (labelframePtr->labelWin == NULL);
    anyWindowLabel = (framePtr->type == TYPE_LABELFRAME) &&
	    (labelframePtr->labelWin != NULL);

#ifndef TK_NO_DOUBLE_BUFFERING
    gcValues.graphics_exposures = False;
    gc = Tk_GetGC(tkwin, GCGraphicsExposures, &gcValues);
    if (framePtr->copyGC != NULL) {
	Tk_FreeGC(framePtr->display, framePtr->copyGC);
    }
    framePtr->copyGC = gc;
#endif /* TK_NO_DOUBLE_BUFFERING */

    if (framePtr->type == TYPE_LABELFRAME) {
	/*
	 * The textGC is needed even in the labelWin case, so it's always
	 * created for a labelframe.
	 */

	gcValues.font = Tk_FontId(labelframePtr->tkfont);
1259
1260
1261
1262
1263
1264
1265
1266

1267
1268
1269
1270
1271
1272
1273
1324
1325
1326
1327
1328
1329
1330

1331
1332
1333
1334
1335
1336
1337
1338







-
+







 *	Display-related numbers get changed in *framePtr.
 *
 *----------------------------------------------------------------------
 */

static void
ComputeFrameGeometry(
    register Frame *framePtr)	/* Information about widget. */
    Frame *framePtr)	/* Information about widget. */
{
    int otherWidth, otherHeight, otherWidthT, otherHeightT, padding;
    int maxWidth, maxHeight;
    Tk_Window tkwin;
    Labelframe *labelframePtr = (Labelframe *) framePtr;

    /*
1408
1409
1410
1411
1412
1413
1414
1415
1416


1417
1418
1419
1420
1421
1422
1423
1473
1474
1475
1476
1477
1478
1479


1480
1481
1482
1483
1484
1485
1486
1487
1488







-
-
+
+







 *----------------------------------------------------------------------
 */

static void
DisplayFrame(
    ClientData clientData)	/* Information about widget. */
{
    register Frame *framePtr = clientData;
    register Tk_Window tkwin = framePtr->tkwin;
    Frame *framePtr = (Frame *)clientData;
    Tk_Window tkwin = framePtr->tkwin;
    int bdX1, bdY1, bdX2, bdY2, hlWidth;
    Pixmap pixmap;
    TkRegion clipRegion = NULL;

    framePtr->flags &= ~REDRAW_PENDING;
    if ((framePtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {
	return;
1449
1450
1451
1452
1453
1454
1455














1456
1457
1458
1459
1460
1461
1462
1463

1464




1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541

1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555














1556
1557
1558
1559
1560
1561
1562







+
+
+
+
+
+
+
+
+
+
+
+
+
+







-
+

+
+
+
+








-
-
-
-
-
-
-
-
-
-
-
-
-
-







     * If -background is set to "", no interior is drawn.
     */

    if (framePtr->border == NULL) {
	return;
    }

#ifndef TK_NO_DOUBLE_BUFFERING
    /*
     * In order to avoid screen flashes, this function redraws the frame into
     * off-screen memory, then copies it back on-screen in a single operation.
     * This means there's no point in time where the on-screen image has been
     * cleared.
     */

    pixmap = Tk_GetPixmap(framePtr->display, Tk_WindowId(tkwin),
	    Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin));
#else
    pixmap = Tk_WindowId(tkwin);
#endif /* TK_NO_DOUBLE_BUFFERING */

    if (framePtr->type != TYPE_LABELFRAME) {
	/*
	 * Pass to platform specific draw function. In general, it just draws
	 * a simple rectangle, but it may "theme" the background.
	 */

    noLabel:
	TkpDrawFrame(tkwin, framePtr->border, hlWidth,
	TkpDrawFrameEx(tkwin, pixmap, framePtr->border, hlWidth,
		framePtr->borderWidth, framePtr->relief);
	if (framePtr->bgimg) {
	    DrawFrameBackground(tkwin, pixmap, hlWidth, framePtr->borderWidth,
		    framePtr->bgimg, framePtr->tile);
	}
    } else {
	Labelframe *labelframePtr = (Labelframe *) framePtr;

	if ((labelframePtr->textPtr == NULL) &&
		(labelframePtr->labelWin == NULL)) {
	    goto noLabel;
	}

#ifndef TK_NO_DOUBLE_BUFFERING
	/*
	 * In order to avoid screen flashes, this function redraws the frame
	 * into off-screen memory, then copies it back on-screen in a single
	 * operation. This means there's no point in time where the on-screen
	 * image has been cleared.
	 */

	pixmap = Tk_GetPixmap(framePtr->display, Tk_WindowId(tkwin),
		Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin));
#else
	pixmap = Tk_WindowId(tkwin);
#endif /* TK_NO_DOUBLE_BUFFERING */

	/*
	 * Clear the pixmap.
	 */

	Tk_Fill3DRectangle(tkwin, pixmap, framePtr->border, 0, 0,
		Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT);

1591
1592
1593
1594
1595
1596
1597
1598


1599
1600
1601
1602
1603




1604
1605
1606
1607
1608
1609
1610






1611
1612
1613

































1614
1615
1616
1617
1618
1619
1620
1660
1661
1662
1663
1664
1665
1666

1667
1668
1669




1670
1671
1672
1673
1674






1675
1676
1677
1678
1679
1680
1681


1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721







-
+
+

-
-
-
-
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+

-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	    } else {
		Tk_MaintainGeometry(labelframePtr->labelWin, framePtr->tkwin,
			labelframePtr->labelBox.x, labelframePtr->labelBox.y,
			labelframePtr->labelBox.width,
			labelframePtr->labelBox.height);
	    }
	}

    }

#ifndef TK_NO_DOUBLE_BUFFERING
	/*
	 * Everything's been redisplayed; now copy the pixmap onto the screen
	 * and free up the pixmap.
	 */
    /*
     * Everything's been redisplayed; now copy the pixmap onto the screen and
     * free up the pixmap.
     */

	XCopyArea(framePtr->display, pixmap, Tk_WindowId(tkwin),
		labelframePtr->textGC, hlWidth, hlWidth,
		(unsigned) (Tk_Width(tkwin) - 2 * hlWidth),
		(unsigned) (Tk_Height(tkwin) - 2 * hlWidth),
		hlWidth, hlWidth);
	Tk_FreePixmap(framePtr->display, pixmap);
    XCopyArea(framePtr->display, pixmap, Tk_WindowId(tkwin),
	    framePtr->copyGC, hlWidth, hlWidth,
	    (unsigned) (Tk_Width(tkwin) - 2 * hlWidth),
	    (unsigned) (Tk_Height(tkwin) - 2 * hlWidth),
	    hlWidth, hlWidth);
    Tk_FreePixmap(framePtr->display, pixmap);
#endif /* TK_NO_DOUBLE_BUFFERING */
    }

}

/*
 *----------------------------------------------------------------------
 *
 * TkpDrawFrame --
 *
 *	This procedure draws the rectangular frame area.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Draws inside the tkwin area.
 *
 *----------------------------------------------------------------------
 */

void
TkpDrawFrame(
    Tk_Window tkwin,
    Tk_3DBorder border,
    int highlightWidth,
    int borderWidth,
    int relief)
{
    /*
     * Legacy shim to allow for external callers. Internal ones use
     * non-exposed TkpDrawFrameEx directly so they can use double-buffering.
     */

    TkpDrawFrameEx(tkwin, Tk_WindowId(tkwin), border,
	    highlightWidth, borderWidth, relief);
}

/*
 *--------------------------------------------------------------
 *
 * FrameEventProc --
 *
1631
1632
1633
1634
1635
1636
1637
1638

1639
1640

1641
1642
1643
1644
1645
1646
1647
1732
1733
1734
1735
1736
1737
1738

1739
1740

1741
1742
1743
1744
1745
1746
1747
1748







-
+

-
+







 *
 *--------------------------------------------------------------
 */

static void
FrameEventProc(
    ClientData clientData,	/* Information about window. */
    register XEvent *eventPtr)	/* Information about event. */
    XEvent *eventPtr)	/* Information about event. */
{
    register Frame *framePtr = clientData;
    Frame *framePtr = (Frame *)clientData;

    if ((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0)) {
	goto redraw;
    } else if (eventPtr->type == ConfigureNotify) {
	ComputeFrameGeometry(framePtr);
	goto redraw;
    } else if (eventPtr->type == DestroyNotify) {
1725
1726
1727
1728
1729
1730
1731
1732

1733
1734
1735
1736
1737
1738
1739
1826
1827
1828
1829
1830
1831
1832

1833
1834
1835
1836
1837
1838
1839
1840







-
+







 *----------------------------------------------------------------------
 */

static void
FrameCmdDeletedProc(
    ClientData clientData)	/* Pointer to widget record for widget. */
{
    Frame *framePtr = clientData;
    Frame *framePtr = (Frame *)clientData;
    Tk_Window tkwin = framePtr->tkwin;

    if (framePtr->menuName != NULL) {
	TkSetWindowMenuBar(framePtr->interp, framePtr->tkwin,
		framePtr->menuName, NULL);
	ckfree(framePtr->menuName);
	framePtr->menuName = NULL;
1776
1777
1778
1779
1780
1781
1782
1783

1784
1785
1786
1787
1788
1789
1790
1877
1878
1879
1880
1881
1882
1883

1884
1885
1886
1887
1888
1889
1890
1891







-
+







 *----------------------------------------------------------------------
 */

static void
MapFrame(
    ClientData clientData)		/* Pointer to frame structure. */
{
    Frame *framePtr = clientData;
    Frame *framePtr = (Frame *)clientData;

    /*
     * Wait for all other background events to be processed before mapping
     * window. This ensures that the window's correct geometry will have been
     * determined before it is first mapped, so that the window manager
     * doesn't get a false idea of its desired geometry.
     */
1831
1832
1833
1834
1835
1836
1837
1838

1839
1840
1841
1842
1843
1844
1845
1932
1933
1934
1935
1936
1937
1938

1939
1940
1941
1942
1943
1944
1945
1946







-
+







void
TkInstallFrameMenu(
    Tk_Window tkwin)		/* The window that was just created. */
{
    TkWindow *winPtr = (TkWindow *) tkwin;

    if (winPtr->mainPtr != NULL) {
	Frame *framePtr = winPtr->instanceData;
	Frame *framePtr = (Frame *)winPtr->instanceData;

	if (framePtr == NULL) {
	    Tcl_Panic("TkInstallFrameMenu couldn't get frame pointer");
	}
	TkpMenuNotifyToplevelCreate(winPtr->mainPtr->interp,
		framePtr->menuName);
    }
1864
1865
1866
1867
1868
1869
1870
1871

1872
1873
1874
1875
1876
1877
1878
1965
1966
1967
1968
1969
1970
1971

1972
1973
1974
1975
1976
1977
1978
1979







-
+







 */

static void
FrameStructureProc(
    ClientData clientData,	/* Pointer to record describing frame. */
    XEvent *eventPtr)		/* Describes what just happened. */
{
    Labelframe *labelframePtr = clientData;
    Labelframe *labelframePtr = (Labelframe *)clientData;

    if (eventPtr->type == DestroyNotify) {
	/*
	 * This should only happen in a labelframe but it doesn't hurt to be
	 * careful.
	 */

1902
1903
1904
1905
1906
1907
1908
1909


1910
1911
1912
1913
1914
1915
1916
1917

1918
1919
1920

1921
1922
1923
1924
1925
1926

1927
1928
1929
1930
1931
1932
1933


1934
1935

1936
1937
1938



1939
1940
1941
1942
1943
1944
1945
2003
2004
2005
2006
2007
2008
2009

2010
2011
2012
2013
2014
2015
2016
2017
2018

2019
2020
2021

2022
2023
2024
2025
2026
2027

2028
2029
2030
2031
2032
2033


2034
2035
2036

2037
2038


2039
2040
2041
2042
2043
2044
2045
2046
2047
2048







-
+
+







-
+


-
+





-
+





-
-
+
+

-
+

-
-
+
+
+







 */

static void
FrameRequestProc(
    ClientData clientData,	/* Pointer to record for frame. */
    Tk_Window tkwin)		/* Window that changed its desired size. */
{
    Frame *framePtr = clientData;
    Frame *framePtr = (Frame *)clientData;
    (void)tkwin;

    FrameWorldChanged(framePtr);
}

/*
 *--------------------------------------------------------------
 *
 * FrameLostSlaveProc --
 * FrameLostContentProc --
 *
 *	This function is invoked by Tk whenever some other geometry claims
 *	control over a slave that used to be managed by us.
 *	control over a content window that used to be managed by us.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Forgets all frame-related information about the slave.
 *	Forgets all frame-related information about the content window.
 *
 *--------------------------------------------------------------
 */

static void
FrameLostSlaveProc(
    ClientData clientData,	/* Frame structure for slave window that was
FrameLostContentProc(
    ClientData clientData,	/* Frame structure for content window window that was
				 * stolen away. */
    Tk_Window tkwin)		/* Tk's handle for the slave window. */
    Tk_Window tkwin)		/* Tk's handle for the content window window. */
{
    Frame *framePtr = clientData;
    Labelframe *labelframePtr = clientData;
    Frame *framePtr = (Frame *)clientData;
    Labelframe *labelframePtr = (Labelframe *)clientData;
    (void)tkwin;

    /*
     * This should only happen in a labelframe but it doesn't hurt to be
     * careful.
     */

    if (labelframePtr->frame.type == TYPE_LABELFRAME) {
1954
1955
1956
1957
1958
1959
1960
1961

1962
1963
1964
1965
1966
1967
1968
2057
2058
2059
2060
2061
2062
2063

2064
2065
2066
2067
2068
2069
2070
2071







-
+







    FrameWorldChanged(framePtr);
}

void
TkMapTopFrame(
     Tk_Window tkwin)
{
    Frame *framePtr = ((TkWindow *) tkwin)->instanceData;
    Frame *framePtr = (Frame *)((TkWindow *) tkwin)->instanceData;
    Tk_OptionTable optionTable;

    if (Tk_IsTopLevel(tkwin) && framePtr->type == TYPE_FRAME) {
	framePtr->type = TYPE_TOPLEVEL;
	Tcl_DoWhenIdle(MapFrame, framePtr);
	if (framePtr->menuName != NULL) {
	    TkSetWindowMenuBar(framePtr->interp, framePtr->tkwin, NULL,
2018
2019
2020
2021
2022
2023
2024
2025

2026
2027
2028
2029
2030

































































































































2031
2032
2033
2034
2035
2036
2037
2038
2121
2122
2123
2124
2125
2126
2127

2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270







-
+





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+









    if (Tcl_GetCommandInfo(interp, cmdName, &cmdInfo) == 0) {
	return NULL;
    }
    if (cmdInfo.objProc != FrameWidgetObjCmd) {
	return NULL;
    }
    framePtr = cmdInfo.objClientData;
    framePtr = (Frame *)cmdInfo.objClientData;
    if (framePtr->type != TYPE_TOPLEVEL) {
	return NULL;
    }
    return framePtr->tkwin;
}

/*
 *----------------------------------------------------------------------
 *
 * FrameBgImageProc --
 *
 *	This function is invoked by the image code whenever the manager for an
 *	image does something that affects the size or contents of an image
 *	displayed on a frame's background.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Arranges for the button to get redisplayed.
 *
 *----------------------------------------------------------------------
 */

static void
FrameBgImageProc(
    ClientData clientData,	/* Pointer to widget record. */
    int x, int y,		/* Upper left pixel (within image) that must
				 * be redisplayed. */
    int width, int height,	/* Dimensions of area to redisplay (might be
				 * <= 0). */
    int imgWidth, int imgHeight)/* New dimensions of image. */
{
    Frame *framePtr = (Frame *)clientData;
    (void)x;
    (void)y;
    (void)width;
    (void)height;
    (void)imgWidth;
    (void)imgHeight;


    /*
     * Changing the background image never alters the dimensions of the frame.
     */

    if (framePtr->tkwin && Tk_IsMapped(framePtr->tkwin) &&
	    !(framePtr->flags & REDRAW_PENDING)) {
	Tcl_DoWhenIdle(DisplayFrame, framePtr);
	framePtr->flags |= REDRAW_PENDING;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * DrawFrameBackground --
 *
 *	This function draws the background image of a rectangular frame area.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Draws inside the tkwin area.
 *
 *----------------------------------------------------------------------
 */

static void
DrawFrameBackground(
    Tk_Window tkwin,
    Pixmap pixmap,
    int highlightWidth,
    int borderWidth,
    Tk_Image bgimg,
    int bgtile)
{
    int width, height;			/* Area to paint on. */
    int imageWidth, imageHeight;	/* Dimensions of image. */
    const int bw = highlightWidth + borderWidth;

    Tk_SizeOfImage(bgimg, &imageWidth, &imageHeight);
    width = Tk_Width(tkwin) - 2*bw;
    height = Tk_Height(tkwin) - 2*bw;

    if (bgtile) {
	/*
	 * Draw the image tiled in the widget (inside the border).
	 */

	int x, y;

	for (x = bw; x - bw < width; x += imageWidth) {
	    int w = imageWidth;
	    if (x - bw + imageWidth > width) {
		w = (width + bw) - x;
	    }
	    for (y = bw; y < height + bw; y += imageHeight) {
		int h = imageHeight;
		if (y - bw + imageHeight > height) {
		    h = (height + bw) - y;
		}
		Tk_RedrawImage(bgimg, 0, 0, w, h, pixmap, x, y);
	    }
	}
    } else {
	/*
	 * Draw the image centred in the widget (inside the border).
	 */

	int x, y, xOff, yOff, w, h;

	if (width > imageWidth) {
	    x = 0;
	    xOff = (Tk_Width(tkwin) - imageWidth) / 2;
	    w = imageWidth;
	} else {
	    x = (imageWidth - width) / 2;
	    xOff = bw;
	    w = width;
	}
	if (height > imageHeight) {
	    y = 0;
	    yOff = (Tk_Height(tkwin) - imageHeight) / 2;
	    h = imageHeight;
	} else {
	    y = (imageHeight - height) / 2;
	    yOff = bw;
	    h = height;
	}
	Tk_RedrawImage(bgimg, x, y, w, h, pixmap, xOff, yOff);
    }
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Changes to generic/tkGC.c.
1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

27
28
29
30
31
32
33
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

26
27
28
29
30
31
32
33






-
-
+
+

















-
+







/*
 * 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.
 */

#include "tkInt.h"

/*
 * One of the following data structures exists for each GC that is currently
 * active. The structure is indexed with two hash tables, one based on the
 * values in the graphics context and the other based on the display and GC
 * identifier.
 */

typedef struct {
    GC gc;			/* Graphics context. */
    Display *display;		/* Display to which gc belongs. */
    int refCount;		/* Number of active uses of gc. */
    size_t refCount;		/* Number of active uses of gc. */
    Tcl_HashEntry *valueHashPtr;/* Entry in valueTable (needed when deleting
				 * this structure). */
} TkGC;

typedef struct {
    XGCValues values;		/* Desired values for GC. */
    Display *display;		/* Display for which GC is valid. */
62
63
64
65
66
67
68
69

70
71
72
73

74
75
76
77
78
79

80
81
82
83
84
85
86
62
63
64
65
66
67
68

69
70
71
72

73
74
75
76
77
78

79
80
81
82
83
84
85
86







-
+



-
+





-
+







 *
 *----------------------------------------------------------------------
 */

GC
Tk_GetGC(
    Tk_Window tkwin,		/* Window in which GC will be used. */
    register unsigned long valueMask,
    unsigned long valueMask,
				/* 1 bits correspond to values specified in
				 * *valuesPtr; other values are set from
				 * defaults. */
    register XGCValues *valuePtr)
    XGCValues *valuePtr)
				/* Values are specified here for bits set in
				 * valueMask. */
{
    ValueKey valueKey;
    Tcl_HashEntry *valueHashPtr, *idHashPtr;
    register TkGC *gcPtr;
    TkGC *gcPtr;
    int isNew;
    Drawable d, freeDrawable;
    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;

    if (dispPtr->gcInit <= 0) {
	GCInit(dispPtr);
    }
214
215
216
217
218
219
220
221

222
223
224
225
226
227
228
229
230
231

232
233
234
235
236
237
238
214
215
216
217
218
219
220

221
222
223
224
225
226
227
228
229
230

231
232
233
234
235
236
237
238







-
+









-
+







    }
    valueKey.display = Tk_Display(tkwin);
    valueKey.screenNum = Tk_ScreenNumber(tkwin);
    valueKey.depth = Tk_Depth(tkwin);
    valueHashPtr = Tcl_CreateHashEntry(&dispPtr->gcValueTable,
	    (char *) &valueKey, &isNew);
    if (!isNew) {
	gcPtr = Tcl_GetHashValue(valueHashPtr);
	gcPtr = (TkGC *)Tcl_GetHashValue(valueHashPtr);
	gcPtr->refCount++;
	return gcPtr->gc;
    }

    /*
     * No GC is currently available for this set of values. Allocate a new GC
     * and add a new structure to the database.
     */

    gcPtr = ckalloc(sizeof(TkGC));
    gcPtr = (TkGC *)ckalloc(sizeof(TkGC));

    /*
     * Find or make a drawable to use to specify the screen and depth of the
     * GC. We may have to make a small pixmap, to avoid doing
     * Tk_MakeWindowExist on the window.
     */

287
288
289
290
291
292
293
294

295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310

311
312
313
314

315
316

317
318
319
320
321
322
323
287
288
289
290
291
292
293

294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309

310
311
312
313

314


315
316
317
318
319
320
321
322







-
+















-
+



-
+
-
-
+








void
Tk_FreeGC(
    Display *display,		/* Display for which gc was allocated. */
    GC gc)			/* Graphics context to be released. */
{
    Tcl_HashEntry *idHashPtr;
    register TkGC *gcPtr;
    TkGC *gcPtr;
    TkDisplay *dispPtr = TkGetDisplay(display);

    if (!dispPtr->gcInit) {
	Tcl_Panic("Tk_FreeGC called before Tk_GetGC");
    }
    if (dispPtr->gcInit < 0) {
	/*
	 * The GCCleanup has been called, and remaining GCs have been freed.
	 * This may still get called by other things shutting down, but the
	 * GCs should no longer be in use.
	 */

	return;
    }

    idHashPtr = Tcl_FindHashEntry(&dispPtr->gcIdTable, (char *) gc);
    idHashPtr = Tcl_FindHashEntry(&dispPtr->gcIdTable, gc);
    if (idHashPtr == NULL) {
	Tcl_Panic("Tk_FreeGC received unknown gc argument");
    }
    gcPtr = Tcl_GetHashValue(idHashPtr);
    gcPtr = (TkGC *)Tcl_GetHashValue(idHashPtr);
    gcPtr->refCount--;
    if (gcPtr->refCount == 0) {
    if (gcPtr->refCount-- <= 1) {
	XFreeGC(gcPtr->display, gcPtr->gc);
	Tcl_DeleteHashEntry(gcPtr->valueHashPtr);
	Tcl_DeleteHashEntry(idHashPtr);
	ckfree(gcPtr);
    }
}

344
345
346
347
348
349
350
351

352
353
354
355
356
357
358
343
344
345
346
347
348
349

350
351
352
353
354
355
356
357







-
+







{
    Tcl_HashEntry *entryPtr;
    Tcl_HashSearch search;
    TkGC *gcPtr;

    for (entryPtr = Tcl_FirstHashEntry(&dispPtr->gcIdTable, &search);
	    entryPtr != NULL; entryPtr = Tcl_NextHashEntry(&search)) {
	gcPtr = Tcl_GetHashValue(entryPtr);
	gcPtr = (TkGC *)Tcl_GetHashValue(entryPtr);

	XFreeGC(gcPtr->display, gcPtr->gc);
	Tcl_DeleteHashEntry(gcPtr->valueHashPtr);
	Tcl_DeleteHashEntry(entryPtr);
	ckfree(gcPtr);
    }
    Tcl_DeleteHashTable(&dispPtr->gcValueTable);
Changes to generic/tkGeometry.c.
1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
16
17
18
19


20
21
22
23
24



25
26
27
28
29
30





31
32
33


34
35
36

37
38
39
40

41
42
43
44
45
46
47
48
49
50



51
52
53
54
55
56
57

58
59

60
61
62
63
64
65
66
67
68

69
70
71
72
73
74
75
76
77
78

79
80
81
82
83
84
85
86
87
88
89
90
91
92
93

94
95
96
97
98
99


100
101
102
103
104
105
106
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15
16
17


18
19
20
21



22
23
24
25





26
27
28
29
30
31


32
33
34
35

36
37
38
39

40
41
42
43
44
45
46
47



48
49
50
51
52
53
54
55
56

57
58

59
60
61
62
63
64
65
66
67

68
69
70
71
72
73
74
75
76
77

78
79
80
81
82
83
84
85
86
87
88
89
90
91
92

93
94
95
96
97


98
99
100
101
102
103
104
105
106






-
-
+
+









-
-
+
+


-
-
-
+
+
+

-
-
-
-
-
+
+
+
+
+

-
-
+
+


-
+



-
+







-
-
-
+
+
+






-
+

-
+








-
+









-
+














-
+




-
-
+
+







/*
 * 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.
 */

#include "tkInt.h"

/*
 * Data structures of the following type are used by Tk_MaintainGeometry. For
 * each slave managed by Tk_MaintainGeometry, there is one of these structures
 * associated with its master.
 * each content managed by Tk_MaintainGeometry, there is one of these structures
 * associated with its container.
 */

typedef struct MaintainSlave {
    Tk_Window slave;		/* The slave window being positioned. */
    Tk_Window master;		/* The master that determines slave's
typedef struct MaintainContent {
    Tk_Window content;		/* The content window being positioned. */
    Tk_Window container;		/* The container that determines content's
				 * position; it must be a descendant of
				 * slave's parent. */
    int x, y;			/* Desired position of slave relative to
				 * master. */
    int width, height;		/* Desired dimensions of slave. */
    struct MaintainSlave *nextPtr;
				 * content's parent. */
    int x, y;			/* Desired position of content relative to
				 * container. */
    int width, height;		/* Desired dimensions of content. */
    struct MaintainContent *nextPtr;
				/* Next in list of Maintains associated with
				 * master. */
} MaintainSlave;
				 * container. */
} MaintainContent;

/*
 * For each window that has been specified as a master to Tk_MaintainGeometry,
 * For each window that has been specified as a content to Tk_MaintainGeometry,
 * there is a structure of the following type:
 */

typedef struct MaintainMaster {
typedef struct MaintainContainer {
    Tk_Window ancestor;		/* The lowest ancestor of this window for
				 * which we have *not* created a
				 * StructureNotify handler. May be the same as
				 * the window itself. */
    int checkScheduled;		/* Non-zero means that there is already a call
				 * to MaintainCheckProc scheduled as an idle
				 * handler. */
    MaintainSlave *slavePtr;	/* First in list of all slaves associated with
				 * this master. */
} MaintainMaster;
    MaintainContent *contentPtr;	/* First in list of all content associated with
				 * this container. */
} MaintainContainer;

/*
 * Prototypes for static procedures in this file:
 */

static void		MaintainCheckProc(ClientData clientData);
static void		MaintainMasterProc(ClientData clientData,
static void		MaintainContainerProc(ClientData clientData,
			    XEvent *eventPtr);
static void		MaintainSlaveProc(ClientData clientData,
static void		MaintainContentProc(ClientData clientData,
			    XEvent *eventPtr);

/*
 *--------------------------------------------------------------
 *
 * Tk_ManageGeometry --
 *
 *	Arrange for a particular procedure to manage the geometry of a given
 *	slave window.
 *	content window.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Proc becomes the new geometry manager for tkwin, replacing any
 *	previous geometry manager. The geometry manager will be notified (by
 *	calling procedures in *mgrPtr) when interesting things happen in the
 *	future. If there was an existing geometry manager for tkwin different
 *	from the new one, it is notified by calling its lostSlaveProc.
 *	from the new one, it is notified by calling its lostContentProc.
 *
 *--------------------------------------------------------------
 */

void
Tk_ManageGeometry(
    Tk_Window tkwin,		/* Window whose geometry is to be managed by
				 * proc. */
    const Tk_GeomMgr *mgrPtr,	/* Static structure describing the geometry
				 * manager. This structure must never go
				 * away. */
    ClientData clientData)	/* Arbitrary one-word argument to pass to
				 * geometry manager procedures. */
{
    register TkWindow *winPtr = (TkWindow *) tkwin;
    TkWindow *winPtr = (TkWindow *) tkwin;

    if ((winPtr->geomMgrPtr != NULL) && (mgrPtr != NULL)
	    && ((winPtr->geomMgrPtr != mgrPtr)
		|| (winPtr->geomData != clientData))
	    && (winPtr->geomMgrPtr->lostSlaveProc != NULL)) {
	winPtr->geomMgrPtr->lostSlaveProc(winPtr->geomData, tkwin);
	    && (winPtr->geomMgrPtr->lostContentProc != NULL)) {
	winPtr->geomMgrPtr->lostContentProc(winPtr->geomData, tkwin);
    }

    winPtr->geomMgrPtr = mgrPtr;
    winPtr->geomData = clientData;
}

/*
128
129
130
131
132
133
134
135

136
137
138
139
140
141
142
128
129
130
131
132
133
134

135
136
137
138
139
140
141
142







-
+







void
Tk_GeometryRequest(
    Tk_Window tkwin,		/* Window that geometry information pertains
				 * to. */
    int reqWidth, int reqHeight)/* Minimum desired dimensions for window, in
				 * pixels. */
{
    register TkWindow *winPtr = (TkWindow *) tkwin;
    TkWindow *winPtr = (TkWindow *) tkwin;

    /*
     * X gets very upset if a window requests a width or height of zero, so
     * rounds requested sizes up to at least 1.
     */

    if (reqWidth <= 0) {
178
179
180
181
182
183
184
185
186


187
188
189
190
191
192
193
178
179
180
181
182
183
184


185
186
187
188
189
190
191
192
193







-
-
+
+








void
Tk_SetInternalBorderEx(
    Tk_Window tkwin,		/* Window that will have internal border. */
    int left, int right,	/* Width of internal border, in pixels. */
    int top, int bottom)
{
    register TkWindow *winPtr = (TkWindow *) tkwin;
    register int changed = 0;
    TkWindow *winPtr = (TkWindow *) tkwin;
    int changed = 0;

    if (left < 0) {
	left = 0;
    }
    if (left != winPtr->internalBorderLeft) {
	winPtr->internalBorderLeft = left;
	changed = 1;
214
215
216
217
218
219
220
221

222
223
224
225
226
227
228
214
215
216
217
218
219
220

221
222
223
224
225
226
227
228







-
+







    }
    if (bottom != winPtr->internalBorderBottom) {
	winPtr->internalBorderBottom = bottom;
	changed = 1;
    }

    /*
     * All the slaves for which this is the master window must now be
     * All the content for which this is the container window must now be
     * repositioned to take account of the new internal border width. To
     * signal all the geometry managers to do this, trigger a ConfigureNotify
     * event. This will cause geometry managers to recompute everything.
     */

    if (changed) {
	TkDoConfigureNotify(winPtr);
275
276
277
278
279
280
281
282

283
284
285
286
287
288
289
275
276
277
278
279
280
281

282
283
284
285
286
287
288
289







-
+







 */

void
Tk_SetMinimumRequestSize(
    Tk_Window tkwin,		/* Window that will have internal border. */
    int minWidth, int minHeight)/* Minimum requested size, in pixels. */
{
    register TkWindow *winPtr = (TkWindow *) tkwin;
    TkWindow *winPtr = (TkWindow *) tkwin;

    if ((winPtr->minReqWidth == minWidth) &&
	    (winPtr->minReqHeight == minHeight)) {
	return;
    }

    winPtr->minReqWidth = minWidth;
299
300
301
302
303
304
305
306

307
308

309
310
311
312
313
314
315

316
317
318
319
320
321

322
323

324
325

326
327

328
329
330

331
332
333
334
335
336
337
338



339
340
341
342
343
344
345


346
347
348
349
350
351
352

353
354

355
356
357
358
359
360
361

362
363
364
365
366
367
368


369
370

371
372

373
374
375

376
377

378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395






396
397
398
399
400
401
402
403

404
405
406
407
408
409
410
411
412
413
414
415
416
417
418





419
420
421
422


423
424
425

426
427

428
429
430

431
432

433
434
435
436
437
438

439
440
441
442


443
444
445
446
447


448
449
450
451
452
453
454
455
456
457
458

459
460
461
462

463
464

465
466

467
468
469
470
471
472





473
474
475
476

477
478
479
480
481
482
483




484
485
486
487
488
489
490
491
492







493
494
495
496
497
498



499
500
501

502
503

504
505
506


507
508
509
510
511
512
513
514
515
516
517
518
519





520
521

522
523
524
525
526
527
528
529
530





531
532
533

534
535

536
537
538
539
540
541
542
543
544
545
546
547
548
549
550

551
552
553
554
555
556
557
558



559
560
561
562
563
564
565
566
567



568
569
570
571


572
573

574
575

576
577
578

579
580

581
582
583
584
585
586
587
588
589
590
591
592
593


594
595

596
597
598
599
600
601
602




603
604
605
606



607
608
609
610


611
612
613
614
615
616
617
618
619
620






621
622
623


624
625
626
627
628
629


630
631
632

633
634
635
636
637
638
639

640
641
642

643
644
645
646
647
648
649
650
651

652
653
654
655
656
657
658
659
660



661
662
663
664


665
666
667
668
669
670
671
672



673
674
675
676
677


678
679
680
681
682
683
684


685
686
687

688
689
690
691
692
693
694
695

696
697
698

699
700
701
702
703
704
705
706

707
708
709
710
711
712
713
714



715
716
717

718
719
720

721
722
723
724
725
726
727
728
729
730
731
732
733




734
735
736
737
738
739

740
741
742
743
744
745
746
747


748
749
750


751
752
753
754
755
756
757
758
759






760
761

762
763
764
765
766
767
768



769
770
771

772
773

774
775
776
777
778
779
780
299
300
301
302
303
304
305

306
307

308
309
310
311
312
313
314

315
316
317
318
319
320

321
322

323
324

325
326

327
328
329

330
331
332
333
334
335



336
337
338
339
340
341
342
343


344
345
346
347
348
349
350
351

352
353

354
355
356
357
358
359
360

361
362
363
364
365
366


367
368
369

370
371

372
373
374

375
376

377
378
379
380
381
382
383
384
385
386
387
388
389






390
391
392
393
394
395
396
397
398
399
400
401
402

403
404
405
406
407
408
409
410
411
412
413





414
415
416
417
418
419
420


421
422
423
424

425
426

427
428


429
430

431
432
433
434
435
436

437
438
439


440
441
442
443
444


445
446
447
448
449
450
451
452
453
454
455
456

457
458
459
460

461
462

463
464

465
466





467
468
469
470
471
472
473
474

475
476
477
478




479
480
481
482
483
484







485
486
487
488
489
490
491
492
493
494



495
496
497
498
499

500
501

502
503


504
505
506
507
508
509
510
511
512
513





514
515
516
517
518
519

520
521
522
523
524





525
526
527
528
529
530
531

532
533

534
535
536
537
538
539
540
541
542
543
544
545
546
547
548

549
550
551
552
553
554



555
556
557
558
559
560
561
562
563



564
565
566
567
568


569
570
571

572
573

574
575


576
577

578
579
580
581
582
583
584
585
586
587
588
589


590
591
592

593
594
595
596




597
598
599
600
601



602
603
604
605
606


607
608
609
610
611
612






613
614
615
616
617
618
619


620
621
622
623
624
625


626
627
628
629

630
631
632
633
634
635
636

637
638
639

640
641
642
643
644
645
646
647
648

649
650
651
652
653
654
655



656
657
658
659
660


661
662
663
664
665
666
667



668
669
670
671
672
673


674
675
676
677
678
679
680


681
682
683
684

685
686
687
688
689
690
691
692

693
694
695

696
697
698
699
700
701
702
703

704
705
706
707
708
709



710
711
712
713
714

715
716
717

718
719
720
721
722
723
724
725
726
727




728
729
730
731
732
733
734
735
736

737
738
739
740
741
742
743


744
745
746


747
748
749
750
751






752
753
754
755
756
757
758

759
760
761
762
763



764
765
766
767
768

769
770

771
772
773
774
775
776
777
778







-
+

-
+






-
+





-
+

-
+

-
+

-
+


-
+





-
-
-
+
+
+





-
-
+
+






-
+

-
+






-
+





-
-
+
+

-
+

-
+


-
+

-
+












-
-
-
-
-
-
+
+
+
+
+
+







-
+










-
-
-
-
-
+
+
+
+
+


-
-
+
+


-
+

-
+

-
-
+

-
+





-
+


-
-
+
+



-
-
+
+










-
+



-
+

-
+

-
+

-
-
-
-
-
+
+
+
+
+



-
+



-
-
-
-
+
+
+
+


-
-
-
-
-
-
-
+
+
+
+
+
+
+



-
-
-
+
+
+


-
+

-
+

-
-
+
+








-
-
-
-
-
+
+
+
+
+

-
+




-
-
-
-
-
+
+
+
+
+


-
+

-
+














-
+





-
-
-
+
+
+






-
-
-
+
+
+


-
-
+
+

-
+

-
+

-
-
+

-
+











-
-
+
+

-
+



-
-
-
-
+
+
+
+

-
-
-
+
+
+


-
-
+
+




-
-
-
-
-
-
+
+
+
+
+
+

-
-
+
+




-
-
+
+


-
+






-
+


-
+








-
+






-
-
-
+
+
+


-
-
+
+





-
-
-
+
+
+



-
-
+
+





-
-
+
+


-
+







-
+


-
+







-
+





-
-
-
+
+
+


-
+


-
+









-
-
-
-
+
+
+
+





-
+






-
-
+
+

-
-
+
+



-
-
-
-
-
-
+
+
+
+
+
+

-
+




-
-
-
+
+
+


-
+

-
+








    Tk_ResizeWindow(tkwin, Tk_Width(tkwin), Tk_Height(tkwin));
}

/*
 *----------------------------------------------------------------------
 *
 * TkSetGeometryMaster --
 * TkSetGeometryContainer --
 *
 *	Set a geometry master for this window. Only one master may own
 *	Set a geometry container for this window. Only one container may own
 *	a window at any time.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	The geometry master is recorded for the window.
 *	The geometry container is recorded for the window.
 *
 *----------------------------------------------------------------------
 */

int
TkSetGeometryMaster(
TkSetGeometryContainer(
    Tcl_Interp *interp,		/* Current interpreter, for error. */
    Tk_Window tkwin,		/* Window that will have geometry master
    Tk_Window tkwin,		/* Window that will have geometry container
				 * set. */
    const char *master)		/* The master identity. */
    const char *name)		/* The name of the geometry manager. */
{
    register TkWindow *winPtr = (TkWindow *) tkwin;
    TkWindow *winPtr = (TkWindow *) tkwin;

    if (winPtr->geomMgrName != NULL &&
	    strcmp(winPtr->geomMgrName, master) == 0) {
	    strcmp(winPtr->geomMgrName, name) == 0) {
	return TCL_OK;
    }
    if (winPtr->geomMgrName != NULL) {
	if (interp != NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "cannot use geometry manager %s inside %s which already"
		    " has slaves managed by %s",
		    master, Tk_PathName(tkwin), winPtr->geomMgrName));
		    "cannot use geometry manager %s inside %s because"
		    " %s is already managing it's content windows",
		    name, Tk_PathName(tkwin), winPtr->geomMgrName));
	    Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "FIGHT", NULL);
	}
	return TCL_ERROR;
    }

    winPtr->geomMgrName = ckalloc(strlen(master) + 1);
    strcpy(winPtr->geomMgrName, master);
    winPtr->geomMgrName = (char *)ckalloc(strlen(name) + 1);
    strcpy(winPtr->geomMgrName, name);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TkFreeGeometryMaster --
 * TkFreeGeometryContainer --
 *
 *	Remove a geometry master for this window. Only one master may own
 *	Remove a geometry container for this window. Only one container may own
 *	a window at any time.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The geometry master is cleared for the window.
 *	The geometry container is cleared for the window.
 *
 *----------------------------------------------------------------------
 */

void
TkFreeGeometryMaster(
    Tk_Window tkwin,		/* Window that will have geometry master
TkFreeGeometryContainer(
    Tk_Window tkwin,		/* Window that will have geometry container
				 * cleared. */
    const char *master)		/* The master identity. */
    const char *name)		/* The name of the geometry manager. */
{
    register TkWindow *winPtr = (TkWindow *) tkwin;
    TkWindow *winPtr = (TkWindow *) tkwin;

    if (winPtr->geomMgrName != NULL &&
	    strcmp(winPtr->geomMgrName, master) != 0) {
	    strcmp(winPtr->geomMgrName, name) != 0) {
	Tcl_Panic("Trying to free %s from geometry manager %s",
		winPtr->geomMgrName, master);
		winPtr->geomMgrName, name);
    }
    if (winPtr->geomMgrName != NULL) {
	ckfree(winPtr->geomMgrName);
	winPtr->geomMgrName = NULL;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tk_MaintainGeometry --
 *
 *	This procedure is invoked by geometry managers to handle slaves whose
 *	master's are not their parents. It translates the desired geometry for
 *	the slave into the coordinate system of the parent and respositions
 *	the slave if it isn't already at the right place. Furthermore, it sets
 *	up event handlers so that if the master (or any of its ancestors up to
 *	the slave's parent) is mapped, unmapped, or moved, then the slave will
 *	This procedure is invoked by geometry managers to handle content whose
 *	container's are not their parents. It translates the desired geometry for
 *	the content into the coordinate system of the parent and respositions
 *	the content if it isn't already at the right place. Furthermore, it sets
 *	up event handlers so that if the container (or any of its ancestors up to
 *	the content's parent) is mapped, unmapped, or moved, then the content will
 *	be adjusted to match.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Event handlers are created and state is allocated to keep track of
 *	slave. Note: if slave was already managed for master by
 *	content. Note: if content was already managed for container by
 *	Tk_MaintainGeometry, then the previous information is replaced with
 *	the new information. The caller must eventually call
 *	Tk_UnmaintainGeometry to eliminate the correspondence (or, the state
 *	is automatically freed when either window is destroyed).
 *
 *----------------------------------------------------------------------
 */

void
Tk_MaintainGeometry(
    Tk_Window slave,		/* Slave for geometry management. */
    Tk_Window master,		/* Master for slave; must be a descendant of
				 * slave's parent. */
    int x, int y,		/* Desired position of slave within master. */
    int width, int height)	/* Desired dimensions for slave. */
    Tk_Window window,		/* Window for geometry management. */
    Tk_Window container,		/* Container for window; must be a descendant of
				 * window's parent. */
    int x, int y,		/* Desired position of window within container. */
    int width, int height)	/* Desired dimensions for window. */
{
    Tcl_HashEntry *hPtr;
    MaintainMaster *masterPtr;
    register MaintainSlave *slavePtr;
    MaintainContainer *containerPtr;
    MaintainContent *contentPtr;
    int isNew, map;
    Tk_Window ancestor, parent;
    TkDisplay *dispPtr = ((TkWindow *) master)->dispPtr;
    TkDisplay *dispPtr = ((TkWindow *) container)->dispPtr;

    ((TkWindow *)slave)->maintainerPtr = (TkWindow *)master;
    ((TkWindow *)window)->maintainerPtr = (TkWindow *)container;

    ((TkWindow *)slave)->maintainerPtr = (TkWindow *)master;
    if (master == Tk_Parent(slave)) {
    if (container == Tk_Parent(window)) {
	/*
	 * If the slave is a direct descendant of the master, don't bother
	 * If the window is a direct descendant of the container, don't bother
	 * setting up the extra infrastructure for management, just make a
	 * call to Tk_MoveResizeWindow; the parent/child relationship will
	 * take care of the rest.
	 */

	Tk_MoveResizeWindow(slave, x, y, width, height);
	Tk_MoveResizeWindow(window, x, y, width, height);

	/*
	 * Map the slave if the master is already mapped; otherwise, wait
	 * until the master is mapped later (in which case mapping the slave
	 * Map the window if the container is already mapped; otherwise, wait
	 * until the container is mapped later (in which case mapping the window
	 * is taken care of elsewhere).
	 */

	if (Tk_IsMapped(master)) {
	    Tk_MapWindow(slave);
	if (Tk_IsMapped(container)) {
	    Tk_MapWindow(window);
	}
	return;
    }

    if (!dispPtr->geomInit) {
	dispPtr->geomInit = 1;
	Tcl_InitHashTable(&dispPtr->maintainHashTable, TCL_ONE_WORD_KEYS);
    }

    /*
     * See if there is already a MaintainMaster structure for the master; if
     * See if there is already a MaintainContainer structure for the container; if
     * not, then create one.
     */

    parent = Tk_Parent(slave);
    parent = Tk_Parent(window);
    hPtr = Tcl_CreateHashEntry(&dispPtr->maintainHashTable,
	    (char *) master, &isNew);
	    (char *) container, &isNew);
    if (!isNew) {
	masterPtr = Tcl_GetHashValue(hPtr);
	containerPtr = (MaintainContainer *)Tcl_GetHashValue(hPtr);
    } else {
	masterPtr = ckalloc(sizeof(MaintainMaster));
	masterPtr->ancestor = master;
	masterPtr->checkScheduled = 0;
	masterPtr->slavePtr = NULL;
	Tcl_SetHashValue(hPtr, masterPtr);
	containerPtr = (MaintainContainer *)ckalloc(sizeof(MaintainContainer));
	containerPtr->ancestor = container;
	containerPtr->checkScheduled = 0;
	containerPtr->contentPtr = NULL;
	Tcl_SetHashValue(hPtr, containerPtr);
    }

    /*
     * Create a MaintainSlave structure for the slave if there isn't already
     * Create a MaintainContent structure for the window if there isn't already
     * one.
     */

    for (slavePtr = masterPtr->slavePtr; slavePtr != NULL;
	    slavePtr = slavePtr->nextPtr) {
	if (slavePtr->slave == slave) {
	    goto gotSlave;
    for (contentPtr = containerPtr->contentPtr; contentPtr != NULL;
	    contentPtr = contentPtr->nextPtr) {
	if (contentPtr->content == window) {
	    goto gotContent;
	}
    }
    slavePtr = ckalloc(sizeof(MaintainSlave));
    slavePtr->slave = slave;
    slavePtr->master = master;
    slavePtr->nextPtr = masterPtr->slavePtr;
    masterPtr->slavePtr = slavePtr;
    Tk_CreateEventHandler(slave, StructureNotifyMask, MaintainSlaveProc,
	    slavePtr);
    contentPtr = (MaintainContent *)ckalloc(sizeof(MaintainContent));
    contentPtr->content = window;
    contentPtr->container = container;
    contentPtr->nextPtr = containerPtr->contentPtr;
    containerPtr->contentPtr = contentPtr;
    Tk_CreateEventHandler(window, StructureNotifyMask, MaintainContentProc,
	    contentPtr);

    /*
     * Make sure that there are event handlers registered for all the windows
     * between master and slave's parent (including master but not slave's
     * parent). There may already be handlers for master and some of its
     * ancestors (masterPtr->ancestor tells how many).
     * between container and windows's parent (including container but not window's
     * parent). There may already be handlers for container and some of its
     * ancestors (containerPtr->ancestor tells how many).
     */

    for (ancestor = master; ancestor != parent;
    for (ancestor = container; ancestor != parent;
	    ancestor = Tk_Parent(ancestor)) {
	if (ancestor == masterPtr->ancestor) {
	if (ancestor == containerPtr->ancestor) {
	    Tk_CreateEventHandler(ancestor, StructureNotifyMask,
		    MaintainMasterProc, masterPtr);
	    masterPtr->ancestor = Tk_Parent(ancestor);
		    MaintainContainerProc, containerPtr);
	    containerPtr->ancestor = Tk_Parent(ancestor);
	}
    }

    /*
     * Fill in up-to-date information in the structure, then update the window
     * if it's not currently in the right place or state.
     */

  gotSlave:
    slavePtr->x = x;
    slavePtr->y = y;
    slavePtr->width = width;
    slavePtr->height = height;
  gotContent:
    contentPtr->x = x;
    contentPtr->y = y;
    contentPtr->width = width;
    contentPtr->height = height;
    map = 1;
    for (ancestor = slavePtr->master; ; ancestor = Tk_Parent(ancestor)) {
    for (ancestor = contentPtr->container; ; ancestor = Tk_Parent(ancestor)) {
	if (!Tk_IsMapped(ancestor) && (ancestor != parent)) {
	    map = 0;
	}
	if (ancestor == parent) {
	    if ((x != Tk_X(slavePtr->slave))
		    || (y != Tk_Y(slavePtr->slave))
		    || (width != Tk_Width(slavePtr->slave))
		    || (height != Tk_Height(slavePtr->slave))) {
		Tk_MoveResizeWindow(slavePtr->slave, x, y, width, height);
	    if ((x != Tk_X(contentPtr->content))
		    || (y != Tk_Y(contentPtr->content))
		    || (width != Tk_Width(contentPtr->content))
		    || (height != Tk_Height(contentPtr->content))) {
		Tk_MoveResizeWindow(contentPtr->content, x, y, width, height);
	    }
	    if (map) {
		Tk_MapWindow(slavePtr->slave);
		Tk_MapWindow(contentPtr->content);
	    } else {
		Tk_UnmapWindow(slavePtr->slave);
		Tk_UnmapWindow(contentPtr->content);
	    }
	    break;
	}
	x += Tk_X(ancestor) + Tk_Changes(ancestor)->border_width;
	y += Tk_Y(ancestor) + Tk_Changes(ancestor)->border_width;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tk_UnmaintainGeometry --
 *
 *	This procedure cancels a previous Tk_MaintainGeometry call, so that
 *	the relationship between slave and master is no longer maintained.
 *	the relationship between window and container is no longer maintained.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The slave is unmapped and state is released, so that slave won't track
 *	master any more. If we weren't previously managing slave relative to
 *	master, then this procedure has no effect.
 *	The window is unmapped and state is released, so that window won't track
 *	container any more. If we weren't previously managing window relative to
 *	container, then this procedure has no effect.
 *
 *----------------------------------------------------------------------
 */

void
Tk_UnmaintainGeometry(
    Tk_Window slave,		/* Slave for geometry management. */
    Tk_Window master)		/* Master for slave; must be a descendant of
				 * slave's parent. */
    Tk_Window window,		/* WIndow for geometry management. */
    Tk_Window container)		/* Container for window; must be a descendant of
				 * window's parent. */
{
    Tcl_HashEntry *hPtr;
    MaintainMaster *masterPtr;
    register MaintainSlave *slavePtr, *prevPtr;
    MaintainContainer *containerPtr;
    MaintainContent *contentPtr, *prevPtr;
    Tk_Window ancestor;
    TkDisplay *dispPtr = ((TkWindow *) slave)->dispPtr;
    TkDisplay *dispPtr = ((TkWindow *) window)->dispPtr;

    ((TkWindow *)slave)->maintainerPtr = NULL;
    ((TkWindow *)window)->maintainerPtr = NULL;

    ((TkWindow *)slave)->maintainerPtr = NULL;
    if (master == Tk_Parent(slave)) {
    if (container == Tk_Parent(window)) {
	/*
	 * If the slave is a direct descendant of the master,
	 * If the window is a direct descendant of the container,
	 * Tk_MaintainGeometry will not have set up any of the extra
	 * infrastructure. Don't even bother to look for it, just return.
	 */
	return;
    }

    if (!dispPtr->geomInit) {
	dispPtr->geomInit = 1;
	Tcl_InitHashTable(&dispPtr->maintainHashTable, TCL_ONE_WORD_KEYS);
    }

    if (!(((TkWindow *) slave)->flags & TK_ALREADY_DEAD)) {
	Tk_UnmapWindow(slave);
    if (!(((TkWindow *) window)->flags & TK_ALREADY_DEAD)) {
	Tk_UnmapWindow(window);
    }
    hPtr = Tcl_FindHashEntry(&dispPtr->maintainHashTable, (char *) master);
    hPtr = Tcl_FindHashEntry(&dispPtr->maintainHashTable, container);
    if (hPtr == NULL) {
	return;
    }
    masterPtr = Tcl_GetHashValue(hPtr);
    slavePtr = masterPtr->slavePtr;
    if (slavePtr->slave == slave) {
	masterPtr->slavePtr = slavePtr->nextPtr;
    containerPtr = (MaintainContainer *)Tcl_GetHashValue(hPtr);
    contentPtr = containerPtr->contentPtr;
    if (contentPtr->content == window) {
	containerPtr->contentPtr = contentPtr->nextPtr;
    } else {
	for (prevPtr = slavePtr, slavePtr = slavePtr->nextPtr; ;
		prevPtr = slavePtr, slavePtr = slavePtr->nextPtr) {
	    if (slavePtr == NULL) {
	for (prevPtr = contentPtr, contentPtr = contentPtr->nextPtr; ;
		prevPtr = contentPtr, contentPtr = contentPtr->nextPtr) {
	    if (contentPtr == NULL) {
		return;
	    }
	    if (slavePtr->slave == slave) {
		prevPtr->nextPtr = slavePtr->nextPtr;
	    if (contentPtr->content == window) {
		prevPtr->nextPtr = contentPtr->nextPtr;
		break;
	    }
	}
    }
    Tk_DeleteEventHandler(slavePtr->slave, StructureNotifyMask,
	    MaintainSlaveProc, slavePtr);
    ckfree(slavePtr);
    if (masterPtr->slavePtr == NULL) {
	if (masterPtr->ancestor != NULL) {
	    for (ancestor = master; ; ancestor = Tk_Parent(ancestor)) {
    Tk_DeleteEventHandler(contentPtr->content, StructureNotifyMask,
	    MaintainContentProc, contentPtr);
    ckfree(contentPtr);
    if (containerPtr->contentPtr == NULL) {
	if (containerPtr->ancestor != NULL) {
	    for (ancestor = container; ; ancestor = Tk_Parent(ancestor)) {
		Tk_DeleteEventHandler(ancestor, StructureNotifyMask,
			MaintainMasterProc, masterPtr);
		if (ancestor == masterPtr->ancestor) {
			MaintainContainerProc, containerPtr);
		if (ancestor == containerPtr->ancestor) {
		    break;
		}
	    }
	}
	if (masterPtr->checkScheduled) {
	    Tcl_CancelIdleCall(MaintainCheckProc, masterPtr);
	if (containerPtr->checkScheduled) {
	    Tcl_CancelIdleCall(MaintainCheckProc, containerPtr);
	}
	Tcl_DeleteHashEntry(hPtr);
	ckfree(masterPtr);
	ckfree(containerPtr);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * MaintainMasterProc --
 * MaintainContainerProc --
 *
 *	This procedure is invoked by the Tk event dispatcher in response to
 *	StructureNotify events on the master or one of its ancestors, on
 *	StructureNotify events on the container or one of its ancestors, on
 *	behalf of Tk_MaintainGeometry.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	It schedules a call to MaintainCheckProc, which will eventually caused
 *	the postions and mapped states to be recalculated for all the
 *	maintained slaves of the master. Or, if the master window is being
 *	maintained windows of the container. Or, if the container window is being
 *	deleted then state is cleaned up.
 *
 *----------------------------------------------------------------------
 */

static void
MaintainMasterProc(
    ClientData clientData,	/* Pointer to MaintainMaster structure for the
				 * master window. */
MaintainContainerProc(
    ClientData clientData,	/* Pointer to MaintainContainer structure for the
				 * container window. */
    XEvent *eventPtr)		/* Describes what just happened. */
{
    MaintainMaster *masterPtr = clientData;
    MaintainSlave *slavePtr;
    MaintainContainer *containerPtr = (MaintainContainer *)clientData;
    MaintainContent *contentPtr;
    int done;

    if ((eventPtr->type == ConfigureNotify)
	    || (eventPtr->type == MapNotify)
	    || (eventPtr->type == UnmapNotify)) {
	if (!masterPtr->checkScheduled) {
	    masterPtr->checkScheduled = 1;
	    Tcl_DoWhenIdle(MaintainCheckProc, masterPtr);
	if (!containerPtr->checkScheduled) {
	    containerPtr->checkScheduled = 1;
	    Tcl_DoWhenIdle(MaintainCheckProc, containerPtr);
	}
    } else if (eventPtr->type == DestroyNotify) {
	/*
	 * Delete all of the state associated with this master, but be careful
	 * not to use masterPtr after the last slave is deleted, since its
	 * Delete all of the state associated with this container, but be careful
	 * not to use containerPtr after the last window is deleted, since its
	 * memory will have been freed.
	 */

	done = 0;
	do {
	    slavePtr = masterPtr->slavePtr;
	    if (slavePtr->nextPtr == NULL) {
	    contentPtr = containerPtr->contentPtr;
	    if (contentPtr->nextPtr == NULL) {
		done = 1;
	    }
	    Tk_UnmaintainGeometry(slavePtr->slave, slavePtr->master);
	    Tk_UnmaintainGeometry(contentPtr->content, contentPtr->container);
	} while (!done);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * MaintainSlaveProc --
 * MaintainContentProc --
 *
 *	This procedure is invoked by the Tk event dispatcher in response to
 *	StructureNotify events on a slave being managed by
 *	StructureNotify events on a window being managed by
 *	Tk_MaintainGeometry.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	If the event is a DestroyNotify event then the Maintain state and
 *	event handlers for this slave are deleted.
 *	event handlers for this window are deleted.
 *
 *----------------------------------------------------------------------
 */

static void
MaintainSlaveProc(
    ClientData clientData,	/* Pointer to MaintainSlave structure for
				 * master-slave pair. */
MaintainContentProc(
    ClientData clientData,	/* Pointer to MaintainContent structure for
				 * container-window pair. */
    XEvent *eventPtr)		/* Describes what just happened. */
{
    MaintainSlave *slavePtr = clientData;
    MaintainContent *contentPtr = (MaintainContent *)clientData;

    if (eventPtr->type == DestroyNotify) {
	Tk_UnmaintainGeometry(slavePtr->slave, slavePtr->master);
	Tk_UnmaintainGeometry(contentPtr->content, contentPtr->container);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * MaintainCheckProc --
 *
 *	This procedure is invoked by the Tk event dispatcher as an idle
 *	handler, when a master or one of its ancestors has been reconfigured,
 *	mapped, or unmapped. Its job is to scan all of the slaves for the
 *	master and reposition them, map them, or unmap them as needed to
 *	maintain their geometry relative to the master.
 *	handler, when a container or one of its ancestors has been reconfigured,
 *	mapped, or unmapped. Its job is to scan all of the windows for the
 *	container and reposition them, map them, or unmap them as needed to
 *	maintain their geometry relative to the container.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Slaves can get repositioned, mapped, or unmapped.
 *	Windows can get repositioned, mapped, or unmapped.
 *
 *----------------------------------------------------------------------
 */

static void
MaintainCheckProc(
    ClientData clientData)	/* Pointer to MaintainMaster structure for the
				 * master window. */
    ClientData clientData)	/* Pointer to MaintainContainer structure for the
				 * container window. */
{
    MaintainMaster *masterPtr = clientData;
    MaintainSlave *slavePtr;
    MaintainContainer *containerPtr = (MaintainContainer *)clientData;
    MaintainContent *contentPtr;
    Tk_Window ancestor, parent;
    int x, y, map;

    masterPtr->checkScheduled = 0;
    for (slavePtr = masterPtr->slavePtr; slavePtr != NULL;
	    slavePtr = slavePtr->nextPtr) {
	parent = Tk_Parent(slavePtr->slave);
	x = slavePtr->x;
	y = slavePtr->y;
    containerPtr->checkScheduled = 0;
    for (contentPtr = containerPtr->contentPtr; contentPtr != NULL;
	    contentPtr = contentPtr->nextPtr) {
	parent = Tk_Parent(contentPtr->content);
	x = contentPtr->x;
	y = contentPtr->y;
	map = 1;
	for (ancestor = slavePtr->master; ; ancestor = Tk_Parent(ancestor)) {
	for (ancestor = contentPtr->container; ; ancestor = Tk_Parent(ancestor)) {
	    if (!Tk_IsMapped(ancestor) && (ancestor != parent)) {
		map = 0;
	    }
	    if (ancestor == parent) {
		if ((x != Tk_X(slavePtr->slave))
			|| (y != Tk_Y(slavePtr->slave))) {
		    Tk_MoveWindow(slavePtr->slave, x, y);
		if ((x != Tk_X(contentPtr->content))
			|| (y != Tk_Y(contentPtr->content))) {
		    Tk_MoveWindow(contentPtr->content, x, y);
		}
		if (map) {
		    Tk_MapWindow(slavePtr->slave);
		    Tk_MapWindow(contentPtr->content);
		} else {
		    Tk_UnmapWindow(slavePtr->slave);
		    Tk_UnmapWindow(contentPtr->content);
		}
		break;
	    }
	    x += Tk_X(ancestor) + Tk_Changes(ancestor)->border_width;
	    y += Tk_Y(ancestor) + Tk_Changes(ancestor)->border_width;
	}
    }
Changes to generic/tkGet.c.
1
2
3
4
5
6
7
8
9
10


11
12
13
14
15
16
17
1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
16
17








-
-
+
+







/*
 * tkGet.c --
 *
 *	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.
 */

#include "tkInt.h"

489
490
491
492
493
494
495
496

497
498
499


500
501
502
503
504
505
506
489
490
491
492
493
494
495

496
497


498
499
500
501
502
503
504
505
506







-
+

-
-
+
+







 *	All information in the identifier table is deleted.
 *
 *----------------------------------------------------------------------
 */

static void
FreeUidThreadExitProc(
    ClientData clientData)		/* Not used. */
    TCL_UNUSED(void *))
{
    ThreadSpecificData *tsdPtr =
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    Tcl_DeleteHashTable(&tsdPtr->uidTable);
    tsdPtr->initialized = 0;
}

/*
 *----------------------------------------------------------------------
525
526
527
528
529
530
531
532

533
534
535
536
537
538
539
525
526
527
528
529
530
531

532
533
534
535
536
537
538
539







-
+







 */

Tk_Uid
Tk_GetUid(
    const char *string)		/* String to convert. */
{
    int dummy;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    Tcl_HashTable *tablePtr = &tsdPtr->uidTable;

    if (!tsdPtr->initialized) {
	Tcl_InitHashTable(tablePtr, TCL_STRING_KEYS);
	Tcl_CreateThreadExitHandler(FreeUidThreadExitProc, NULL);
	tsdPtr->initialized = 1;
690
691
692
693
694
695
696





697
698
699
700
701
702
703
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708







+
+
+
+
+







				 * units. */
    const char *string,		/* String describing a number of pixels. */
    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))) {
	end++;
    }
Changes to generic/tkGrab.c.
1
2
3
4
5
6
7


8
9
10
11
12
13
14
1
2
3
4
5


6
7
8
9
10
11
12
13
14





-
-
+
+







/*
 * 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.
 */

#include "tkInt.h"

162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182

183
184
185
186
187
188
189
162
163
164
165
166
167
168

169
170
171
172
173
174
175
176
177
178
179
180

181
182
183
184
185
186
187
188







-












-
+







 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
int
Tk_GrabObjCmd(
    ClientData clientData,	/* Main window associated with interpreter. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int globalGrab;
    Tk_Window tkwin;
    TkDisplay *dispPtr;
    const char *arg;
    int index;
    int len;
    TkSizeT len;
    static const char *const optionStrings[] = {
	"current", "release", "set", "status", NULL
    };
    static const char *const flagStrings[] = {
	"-global", NULL
    };
    enum options {
212
213
214
215
216
217
218
219

220
221
222
223
224
225
226

227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242

243
244
245
246
247
248
249
211
212
213
214
215
216
217

218
219
220
221
222
223
224

225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240

241
242
243
244
245
246
247
248







-
+






-
+















-
+







	return TCL_ERROR;
    }

    /*
     * First check for a window name or "-global" as the first argument.
     */

    arg = Tcl_GetStringFromObj(objv[1], &len);
    arg = TkGetStringFromObj(objv[1], &len);
    if (arg[0] == '.') {
	/* [grab window] */
	if (objc != 2) {
	    Tcl_WrongNumArgs(interp, 1, objv, "?-global? window");
	    return TCL_ERROR;
	}
	tkwin = Tk_NameToWindow(interp, arg, clientData);
	tkwin = Tk_NameToWindow(interp, arg, (Tk_Window)clientData);
	if (tkwin == NULL) {
	    return TCL_ERROR;
	}
	return Tk_Grab(interp, tkwin, 0);
    } else if (arg[0] == '-' && len > 1) {
	if (Tcl_GetIndexFromObj(interp, objv[1], flagStrings, "option", 0,
		&index) != TCL_OK) {
	    return TCL_ERROR;
	}

	/* [grab -global window] */
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 1, objv, "?-global? window");
	    return TCL_ERROR;
	}
	tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), clientData);
	tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), (Tk_Window)clientData);
	if (tkwin == NULL) {
	    return TCL_ERROR;
	}
	return Tk_Grab(interp, tkwin, 1);
    }

    /*
261
262
263
264
265
266
267
268

269
270
271
272
273
274

275
276
277
278
279
280
281
282
283

284
285
286
287
288
289
290
291
292
293
294
295
296
297

298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314

315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330

331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347

348
349
350
351
352
353
354
260
261
262
263
264
265
266

267
268
269
270
271
272

273
274
275
276
277
278
279
280
281

282
283
284
285
286
287
288
289
290
291
292
293
294
295

296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312

313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328

329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345

346
347
348
349
350
351
352
353







-
+





-
+








-
+













-
+
















-
+















-
+
















-
+







	/* [grab current ?window?] */
	if (objc > 3) {
	    Tcl_WrongNumArgs(interp, 1, objv, "current ?window?");
	    return TCL_ERROR;
	}
	if (objc == 3) {
	    tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[2]),
		    clientData);
		    (Tk_Window)clientData);
	    if (tkwin == NULL) {
		return TCL_ERROR;
	    }
	    dispPtr = ((TkWindow *) tkwin)->dispPtr;
	    if (dispPtr->eventualGrabWinPtr != NULL) {
		Tcl_SetObjResult(interp, TkNewWindowObj((Tk_Window)
		Tcl_SetObjResult(interp, Tk_NewWindowObj((Tk_Window)
			dispPtr->eventualGrabWinPtr));
	    }
	} else {
	    Tcl_Obj *resultObj = Tcl_NewObj();

	    for (dispPtr = TkGetDisplayList(); dispPtr != NULL;
		    dispPtr = dispPtr->nextPtr) {
		if (dispPtr->eventualGrabWinPtr != NULL) {
		    Tcl_ListObjAppendElement(NULL, resultObj, TkNewWindowObj(
		    Tcl_ListObjAppendElement(NULL, resultObj, Tk_NewWindowObj(
			    (Tk_Window) dispPtr->eventualGrabWinPtr));
		}
	    }
	    Tcl_SetObjResult(interp, resultObj);
	}
	return TCL_OK;

    case GRABCMD_RELEASE:
	/* [grab release window] */
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 1, objv, "release window");
	    return TCL_ERROR;
	}
	tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), clientData);
	tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), (Tk_Window)clientData);
	if (tkwin == NULL) {
	    Tcl_ResetResult(interp);
	} else {
	    Tk_Ungrab(tkwin);
	}
	break;

    case GRABCMD_SET:
	/* [grab set ?-global? window] */
	if ((objc != 3) && (objc != 4)) {
	    Tcl_WrongNumArgs(interp, 1, objv, "set ?-global? window");
	    return TCL_ERROR;
	}
	if (objc == 3) {
	    globalGrab = 0;
	    tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[2]),
		    clientData);
		    (Tk_Window)clientData);
	} else {
	    globalGrab = 1;

	    /*
	     * We could just test the argument by hand instead of using
	     * Tcl_GetIndexFromObj; the benefit of using the function is that
	     * it sets up the error message for us, so we are certain to be
	     * consistant with the rest of Tcl.
	     */

	    if (Tcl_GetIndexFromObj(interp, objv[2], flagStrings, "option",
		    0, &index) != TCL_OK) {
		return TCL_ERROR;
	    }
	    tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[3]),
		    clientData);
		    (Tk_Window)clientData);
	}
	if (tkwin == NULL) {
	    return TCL_ERROR;
	}
	return Tk_Grab(interp, tkwin, globalGrab);

    case GRABCMD_STATUS: {
	/* [grab status window] */
	TkWindow *winPtr;
	const char *statusString;

	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 1, objv, "status window");
	    return TCL_ERROR;
	}
	winPtr = (TkWindow *) Tk_NameToWindow(interp, Tcl_GetString(objv[2]),
		clientData);
		(Tk_Window)clientData);
	if (winPtr == NULL) {
	    return TCL_ERROR;
	}
	dispPtr = winPtr->dispPtr;
	if (dispPtr->eventualGrabWinPtr != winPtr) {
	    statusString = "none";
	} else if (dispPtr->grabFlags & GRAB_GLOBAL) {
634
635
636
637
638
639
640
641

642
643
644
645
646
647
648
633
634
635
636
637
638
639

640
641
642
643
644
645
646
647







-
+







 *	to its current window.
 *
 *----------------------------------------------------------------------
 */

static void
ReleaseButtonGrab(
    register TkDisplay *dispPtr)/* Display whose button grab is to be
    TkDisplay *dispPtr)/* Display whose button grab is to be
				 * released. */
{
    unsigned int serial;

    if (dispPtr->buttonWinPtr != NULL) {
	if (dispPtr->buttonWinPtr != dispPtr->serverWinPtr) {
	    MovePointer2(dispPtr->buttonWinPtr, dispPtr->serverWinPtr,
663
664
665
666
667
668
669



670
671
672
673
674
675
676
677
678
679
680

681
682
683
684
685
686
687

688
689
690
691

692
693
694
695
696
697
698
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689

690
691
692
693

694
695
696
697
698
699
700
701







+
+
+











+






-
+



-
+







 *----------------------------------------------------------------------
 *
 * TkPointerEvent --
 *
 *	This function is called for each pointer-related event, before the
 *	event has been processed. It does various things to make grabs work
 *	correctly.
 *	Also, this function takes care of warping the mouse pointer with
 *	respect to a given window, both when there is a grab in effect and
 *	when there is none.
 *
 * Results:
 *	If the return value is 1 it means the event should be processed (event
 *	handlers should be invoked). If the return value is 0 it means the
 *	event should be ignored in order to make grabs work correctly. In some
 *	cases this function modifies the event.
 *
 * Side effects:
 *	Grab state information may be updated. New events may also be pushed
 *	back onto the event queue to replace or augment the one passed in
 *	here.
 *	The mouse pointer may be moved.
 *
 *----------------------------------------------------------------------
 */

int
TkPointerEvent(
    register XEvent *eventPtr,	/* Pointer to the event. */
    XEvent *eventPtr,	/* Pointer to the event. */
    TkWindow *winPtr)		/* Tk's information for window where event was
				 * reported. */
{
    register TkWindow *winPtr2;
    TkWindow *winPtr2;
    TkDisplay *dispPtr = winPtr->dispPtr;
    unsigned int serial;
    int outsideGrabTree = 0;
    int ancestorOfGrab = 0;
    int appGrabbed = 0;		/* Non-zero means event is being reported to
				 * an application that is affected by the
				 * grab. */
769
770
771
772
773
774
775










776
777
778
779
780




781
782
783
784
785
786
787
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804







+
+
+
+
+
+
+
+
+
+





+
+
+
+







	    if ((dispPtr->buttonWinPtr != NULL)
		    && (winPtr != dispPtr->buttonWinPtr)) {
		return 0;
	    }
	}
	return 1;
    }

    if ((eventPtr->type == MotionNotify) && !appGrabbed) {

        /*
         * Warp the mouse pointer with respect to window dispPtr->warpWindow
         * if such a window was set in HandleEventGenerate.
         */

        TkDoWarpWrtWin(dispPtr);
    }

    if (!appGrabbed) {
	return 1;
    }

    /*
     * From this point on, there is a grab in effect.
     */

    if (eventPtr->type == MotionNotify) {
	/*
	 * When grabs are active, X reports motion events relative to the
	 * window under the pointer. Instead, it should report the events
	 * relative to the window the button went down in, if there is a
	 * button down. Otherwise, if the pointer window is outside the
	 * subtree of the grab window, the events should be reported relative
796
797
798
799
800
801
802







803
804
805
806
807
808
809
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833







+
+
+
+
+
+
+







	    winPtr2 = dispPtr->grabWinPtr;
	}
	if (winPtr2 != winPtr) {
	    TkChangeEventWindow(eventPtr, winPtr2);
	    Tk_QueueWindowEvent(eventPtr, TCL_QUEUE_HEAD);
	    return 0;
	}

        /*
         * Warp the mouse pointer with respect to window dispPtr->warpWindow
         * if such a window was set in HandleEventGenerate.
         */

        TkDoWarpWrtWin(dispPtr);
	return 1;
    }

    /*
     * Process ButtonPress and ButtonRelease events:
     * 1. Keep track of whether a button is down and what window it went down
     *    in.
868
869
870
871
872
873
874
875

876
877
878
879
880
881
882
892
893
894
895
896
897
898

899
900
901
902
903
904
905
906







-
+







		}
		dispPtr->buttonWinPtr = winPtr;
		return 1;
	    }
	} else {
	    if (eventPtr->xbutton.button != AnyButton &&
		    ((eventPtr->xbutton.state & ALL_BUTTONS)
		    == (unsigned int)TkGetButtonMask(eventPtr->xbutton.button))) {
		    == Tk_GetButtonMask(eventPtr->xbutton.button))) {
		ReleaseButtonGrab(dispPtr);			/* Note 4. */
	    }
	}
	if (winPtr2 != winPtr) {
	    TkChangeEventWindow(eventPtr, winPtr2);
	    Tk_QueueWindowEvent(eventPtr, TCL_QUEUE_HEAD);
	    return 0;						/* Note 3. */
903
904
905
906
907
908
909
910

911
912
913
914
915
916
917

918
919
920
921
922
923
924
927
928
929
930
931
932
933

934
935
936
937
938
939
940

941
942
943
944
945
946
947
948







-
+






-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

void
TkChangeEventWindow(
    register XEvent *eventPtr,	/* Event to retarget. Must have type
    XEvent *eventPtr,	/* Event to retarget. Must have type
				 * ButtonPress, ButtonRelease, KeyPress,
				 * KeyRelease, MotionNotify, EnterNotify, or
				 * LeaveNotify. */
    TkWindow *winPtr)		/* New target window for event. */
{
    int x, y, sameScreen, bd;
    register TkWindow *childPtr;
    TkWindow *childPtr;

    eventPtr->xmotion.window = Tk_WindowId(winPtr);
    if (eventPtr->xmotion.root ==
	    RootWindow(winPtr->display, winPtr->screenNum)) {
	Tk_GetRootCoords((Tk_Window) winPtr, &x, &y);
	eventPtr->xmotion.x = eventPtr->xmotion.x_root - x;
	eventPtr->xmotion.y = eventPtr->xmotion.y_root - y;
991
992
993
994
995
996
997
998

999
1000
1001
1002
1003
1004
1005
1015
1016
1017
1018
1019
1020
1021

1022
1023
1024
1025
1026
1027
1028
1029







-
+







				 * means don't generate leave events. */
    int enterType,		/* Type of events to generate for windows
				 * being entered (EnterNotify or FocusIn). 0
				 * means don't generate enter events. */
    Tcl_QueuePosition position)	/* Position at which events are added to the
				 * system event queue. */
{
    register TkWindow *winPtr;
    TkWindow *winPtr;
    int upLevels, downLevels, i, j, focus;

    /*
     * There are four possible cases to deal with:
     *
     * 1. SourcePtr and destPtr are the same. There's nothing to do in this
     *    case.
1184
1185
1186
1187
1188
1189
1190
1191

1192
1193
1194
1195
1196
1197
1198
1208
1209
1210
1211
1212
1213
1214

1215
1216
1217
1218
1219
1220
1221
1222







-
+







 *	code.
 *
 *----------------------------------------------------------------------
 */

void
TkGrabDeadWindow(
    register TkWindow *winPtr)	/* Window that is in the process of being
    TkWindow *winPtr)	/* Window that is in the process of being
				 * deleted. */
{
    TkDisplay *dispPtr = winPtr->dispPtr;

    if (dispPtr->eventualGrabWinPtr == winPtr) {
	/*
	 * Grab window was deleted. Release the grab.
1274
1275
1276
1277
1278
1279
1280
1281

1282
1283
1284
1285
1286
1287
1288
1298
1299
1300
1301
1302
1303
1304

1305
1306
1307
1308
1309
1310
1311
1312







-
+







 */

static Tk_RestrictAction
GrabRestrictProc(
    ClientData arg,
    XEvent *eventPtr)
{
    GrabInfo *info = arg;
    GrabInfo *info = (GrabInfo *)arg;
    int mode, diff;

    /*
     * The diff caculation is trickier than it may seem. Don't forget that
     * serial numbers can wrap around, so can't compare the two serial numbers
     * directly.
     */
1332
1333
1334
1335
1336
1337
1338
1339

1340
1341
1342
1343
1344
1345
1346
1356
1357
1358
1359
1360
1361
1362

1363
1364
1365
1366
1367
1368
1369
1370







-
+







    TkDisplay *dispPtr,		/* Display on which to change the grab
				 * window. */
    TkWindow *grabWinPtr)	/* Window that is to become the new grab
				 * window (may be NULL). */
{
    NewGrabWinEvent *grabEvPtr;

    grabEvPtr = ckalloc(sizeof(NewGrabWinEvent));
    grabEvPtr = (NewGrabWinEvent *)ckalloc(sizeof(NewGrabWinEvent));
    grabEvPtr->header.proc = GrabWinEventProc;
    grabEvPtr->dispPtr = dispPtr;
    if (grabWinPtr == NULL) {
	grabEvPtr->grabWindow = None;
    } else {
	grabEvPtr->grabWindow = grabWinPtr->window;
    }
1367
1368
1369
1370
1371
1372
1373
1374

1375
1376
1377
1378
1379
1380
1381
1391
1392
1393
1394
1395
1396
1397

1398
1399
1400
1401
1402
1403
1404
1405







-
+







 *
 *----------------------------------------------------------------------
 */

static int
GrabWinEventProc(
    Tcl_Event *evPtr,		/* Event of type NewGrabWinEvent. */
    int flags)			/* Flags argument to Tcl_DoOneEvent: indicates
    TCL_UNUSED(int))			/* Flags argument to Tcl_DoOneEvent: indicates
				 * what kinds of events are being processed
				 * right now. */
{
    NewGrabWinEvent *grabEvPtr = (NewGrabWinEvent *) evPtr;

    grabEvPtr->dispPtr->grabWinPtr = (TkWindow *) Tk_IdToWindow(
	    grabEvPtr->dispPtr->display, grabEvPtr->grabWindow);
1412
1413
1414
1415
1416
1417
1418
1419

1420
1421
1422
1423
1424
1425
1426
1436
1437
1438
1439
1440
1441
1442

1443
1444
1445
1446
1447
1448
1449
1450







-
+







    TkWindow *winPtr1,		/* First window. May be NULL. */
    TkWindow *winPtr2,		/* Second window. May be NULL. */
    int *countPtr1,		/* Store nesting level of winPtr1 within
				 * common ancestor here. */
    int *countPtr2)		/* Store nesting level of winPtr2 within
				 * common ancestor here. */
{
    register TkWindow *winPtr;
    TkWindow *winPtr;
    TkWindow *ancestorPtr;
    int count1, count2, i;

    /*
     * Mark winPtr1 and all of its ancestors with a special flag bit.
     */

Changes to generic/tkGrid.c.
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







/*
 * 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.
 */

#include "tkInt.h"

62
63
64
65
66
67
68
69

70
71
72
73
74
75
76
77
78
79
80
81
82
83

84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103


104
105
106
107
108

109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127

128
129
130
131
132
133

134
135
136
137

138
139
140
141
142

143
144

145
146
147

148
149
150
151

152
153
154
155
156
157
158
159
160

161
162
163

164
165
166
167
168




169
170
171

172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188

189
190
191
192
193

194
195
196
197
198
199
200
201
202

203
204

205
206
207
208
209
210
211
62
63
64
65
66
67
68

69
70
71
72
73
74
75
76
77
78
79
80
81
82

83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101


102
103
104
105
106
107

108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126

127
128
129
130
131
132

133
134
135
136

137
138
139
140
141

142
143

144
145
146

147
148
149
150

151
152
153
154
155
156
157
158
159

160
161
162

163
164




165
166
167
168
169
170

171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187

188
189
190
191
192

193
194
195
196
197
198
199
200
201

202
203

204
205
206
207
208
209
210
211







-
+













-
+


















-
-
+
+




-
+


















-
+





-
+



-
+




-
+

-
+


-
+



-
+








-
+


-
+

-
-
-
-
+
+
+
+


-
+
















-
+




-
+








-
+

-
+







/*
 * Default value for 'grid anchor'.
 */

#define GRID_DEFAULT_ANCHOR TK_ANCHOR_NW

/*
 * Structure to hold information for grid masters. A slot is either a row or
 * Structure to hold information for grid containers. A slot is either a row or
 * column.
 */

typedef struct SlotInfo {
    int minSize;		/* The minimum size of this slot (in pixels).
				 * It is set via the rowconfigure or
				 * columnconfigure commands. */
    int weight;			/* The resize weight of this slot. (0) means
				 * this slot doesn't resize. Extra space in
				 * the layout is given distributed among slots
				 * inproportion to their weights. */
    int pad;			/* Extra padding, in pixels, required for this
				 * slot. This amount is "added" to the largest
				 * slave in the slot. */
				 * content in the slot. */
    Tk_Uid uniform;		/* Value of -uniform option. It is used to
				 * group slots that should have the same
				 * size. */
    int offset;			/* This is a cached value used for
				 * introspection. It is the pixel offset of
				 * the right or bottom edge of this slot from
				 * the beginning of the layout. */
    int temp;			/* This is a temporary value used for
				 * calculating adjusted weights when shrinking
				 * the layout below its nominal size. */
} SlotInfo;

/*
 * Structure to hold information during layout calculations. There is one of
 * these for each slot, an array for each of the rows or columns.
 */

typedef struct GridLayout {
    struct Gridder *binNextPtr;	/* The next slave window in this bin. Each bin
    				 * contains a list of all slaves whose spans
    struct Gridder *binNextPtr;	/* The next content window in this bin. Each bin
    				 * contains a list of all content whose spans
    				 * are >1 and whose right edges fall in this
    				 * slot. */
    int minSize;		/* Minimum size needed for this slot, in
    				 * pixels. This is the space required to hold
    				 * any slaves contained entirely in this slot,
    				 * any content contained entirely in this slot,
    				 * adjusted for any slot constrants, such as
    				 * size or padding. */
    int pad;			/* Padding needed for this slot */
    int weight;			/* Slot weight, controls resizing. */
    Tk_Uid uniform;		/* Value of -uniform option. It is used to
				 * group slots that should have the same
				 * size. */
    int minOffset;		/* The minimum offset, in pixels, from the
    				 * beginning of the layout to the bottom/right
    				 * edge of the slot calculated from top/left
    				 * to bottom/right. */
    int maxOffset;		/* The maximum offset, in pixels, from the
    				 * beginning of the layout to the bottom/right
    				 * edge of the slot calculated from
    				 * bottom/right to top/left. */
} GridLayout;

/*
 * Keep one of these for each geometry master.
 * Keep one of these for each geometry container.
 */

typedef struct {
    SlotInfo *columnPtr;	/* Pointer to array of column constraints. */
    SlotInfo *rowPtr;		/* Pointer to array of row constraints. */
    int columnEnd;		/* The last column occupied by any slave. */
    int columnEnd;		/* The last column occupied by any content. */
    int columnMax;		/* The number of columns with constraints. */
    int columnSpace;		/* The number of slots currently allocated for
    				 * column constraints. */
    int rowEnd;			/* The last row occupied by any slave. */
    int rowEnd;			/* The last row occupied by any content. */
    int rowMax;			/* The number of rows with constraints. */
    int rowSpace;		/* The number of slots currently allocated for
    				 * row constraints. */
    int startX;			/* Pixel offset of this layout within its
    				 * master. */
    				 * container. */
    int startY;			/* Pixel offset of this layout within its
    				 * master. */
    				 * container. */
    Tk_Anchor anchor;		/* Value of anchor option: specifies where a
				 * grid without weight should be placed. */
} GridMaster;
} GridContainer;

/*
 * For each window that the grid cares about (either because the window is
 * managed by the grid or because the window has slaves that are managed by
 * managed by the grid or because the window has content that are managed by
 * the grid), there is a structure of the following type:
 */

typedef struct Gridder {
    Tk_Window tkwin;		/* Tk token for window. NULL means that the
				 * window has been deleted, but the gridder
				 * hasn't had a chance to clean up yet because
				 * the structure is still in use. */
    struct Gridder *masterPtr;	/* Master window within which this window is
    struct Gridder *containerPtr;	/* Container window within which this window is
				 * managed (NULL means this window isn't
				 * managed by the gridder). */
    struct Gridder *nextPtr;	/* Next window managed within same master.
    struct Gridder *nextPtr;	/* Next window managed within same container.
				 * List order doesn't matter. */
    struct Gridder *slavePtr;	/* First in list of slaves managed inside this
				 * window (NULL means no grid slaves). */
    GridMaster *masterDataPtr;	/* Additional data for geometry master. */
    Tcl_Obj *in;                /* Store master name when removed. */
    struct Gridder *contentPtr;	/* First in list of content managed inside this
				 * window (NULL means no grid content). */
    GridContainer *containerDataPtr;	/* Additional data for geometry container. */
    Tcl_Obj *in;                /* Store container name when removed. */
    int column, row;		/* Location in the grid (starting from
				 * zero). */
    int numCols, numRows;	/* Number of columns or rows this slave spans.
    int numCols, numRows;	/* Number of columns or rows this content spans.
				 * Should be at least 1. */
    int padX, padY;		/* Total additional pixels to leave around the
				 * window. Some is of this space is on each
				 * side. This is space *outside* the window:
				 * we'll allocate extra space in frame but
				 * won't enlarge window). */
    int padLeft, padTop;	/* The part of padX or padY to use on the left
				 * or top of the widget, respectively. By
				 * default, this is half of padX or padY. */
    int iPadX, iPadY;		/* Total extra pixels to allocate inside the
				 * window (half this amount will appear on
				 * each side). */
    int sticky;			/* which sides of its cavity this window
				 * sticks to. See below for definitions */
    int doubleBw;		/* Twice the window's last known border width.
				 * If this changes, the window must be
				 * re-arranged within its master. */
				 * re-arranged within its container. */
    int *abortPtr;		/* If non-NULL, it means that there is a
				 * nested call to ArrangeGrid already working
				 * on this window. *abortPtr may be set to 1
				 * to abort that nested call. This happens,
				 * for example, if tkwin or any of its slaves
				 * for example, if tkwin or any of its content
				 * is deleted. */
    int flags;			/* Miscellaneous flags; see below for
				 * definitions. */

    /*
     * These fields are used temporarily for layout calculations only.
     */

    struct Gridder *binNextPtr;	/* Link to next span>1 slave in this bin. */
    struct Gridder *binNextPtr;	/* Link to next span>1 content in this bin. */
    int size;			/* Nominal size (width or height) in pixels of
    				 * the slave. This includes the padding. */
    				 * the content. This includes the padding. */
} Gridder;

/*
 * Flag values for "sticky"ness. The 16 combinations subsume the packer's
 * notion of anchor and fill.
 *
 * STICK_NORTH			This window sticks to the top of its cavity.
231
232
233
234
235
236
237
238

239
240
241

242
243
244
245



246
247
248
249
250

251
252
253
254
255
256

257
258
259
260
261

262
263

264
265
266
267
268
269
270
231
232
233
234
235
236
237

238
239
240

241
242



243
244
245
246
247
248
249

250
251
252
253
254
255

256
257
258
259
260

261
262

263
264
265
266
267
268
269
270







-
+


-
+

-
-
-
+
+
+




-
+





-
+




-
+

-
+







    int minSize;
} UniformGroup;

/*
 * Flag values for Grid structures:
 *
 * REQUESTED_RELAYOUT		1 means a Tcl_DoWhenIdle request has already
 *				been made to re-arrange all the slaves of this
 *				been made to re-arrange all the content of this
 *				window.
 * DONT_PROPAGATE		1 means don't set this window's requested
 *				size. 0 means if this window is a master then
 *				size. 0 means if this window is a container then
 *				Tk will set its requested size to fit the
 *				needs of its slaves.
 * ALLOCED_MASTER               1 means that Grid has allocated itself as
 *                              geometry master for this window.
 *				needs of its content.
 * ALLOCED_CONTAINER		1 means that Grid has allocated itself as
 *				geometry container for this window.
 */

#define REQUESTED_RELAYOUT	1
#define DONT_PROPAGATE		2
#define ALLOCED_MASTER		4
#define ALLOCED_CONTAINER	4

/*
 * Prototypes for procedures used only in this file:
 */

static void		AdjustForSticky(Gridder *slavePtr, int *xPtr,
static void		AdjustForSticky(Gridder *contentPtr, int *xPtr,
			    int *yPtr, int *widthPtr, int *heightPtr);
static int		AdjustOffsets(int width, int elements,
			    SlotInfo *slotPtr);
static void		ArrangeGrid(ClientData clientData);
static int		CheckSlotData(Gridder *masterPtr, int slot,
static int		CheckSlotData(Gridder *containerPtr, int slot,
			    int slotType, int checkOnly);
static int		ConfigureSlaves(Tcl_Interp *interp, Tk_Window tkwin,
static int		ConfigureContent(Tcl_Interp *interp, Tk_Window tkwin,
			    int objc, Tcl_Obj *const objv[]);
static void		DestroyGrid(void *memPtr);
static Gridder *	GetGrid(Tk_Window tkwin);
static int		GridAnchorCommand(Tk_Window tkwin, Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
static int		GridBboxCommand(Tk_Window tkwin, Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
280
281
282
283
284
285
286
287

288
289
290
291

292
293
294
295
296



297
298
299
300

301
302

303
304
305
306
307
308
309
310
311

312
313
314
315
316
317
318
280
281
282
283
284
285
286

287
288
289
290

291
292
293



294
295
296
297
298
299

300
301

302
303
304
305
306
307
308
309
310

311
312
313
314
315
316
317
318







-
+



-
+


-
-
-
+
+
+



-
+

-
+








-
+







			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static int		GridRowColumnConfigureCommand(Tk_Window tkwin,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static int		GridSizeCommand(Tk_Window tkwin, Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
static int		GridSlavesCommand(Tk_Window tkwin, Tcl_Interp *interp,
static int		GridContentCommand(Tk_Window tkwin, Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
static void		GridStructureProc(ClientData clientData,
			    XEvent *eventPtr);
static void		GridLostSlaveProc(ClientData clientData,
static void		GridLostContentProc(ClientData clientData,
			    Tk_Window tkwin);
static void		GridReqProc(ClientData clientData, Tk_Window tkwin);
static void		InitMasterData(Gridder *masterPtr);
static Tcl_Obj *	NewPairObj(int, int);
static Tcl_Obj *	NewQuadObj(int, int, int, int);
static void		InitContainerData(Gridder *containerPtr);
static Tcl_Obj *	NewPairObj(Tcl_WideInt, Tcl_WideInt);
static Tcl_Obj *	NewQuadObj(Tcl_WideInt, Tcl_WideInt, Tcl_WideInt, Tcl_WideInt);
static int		ResolveConstraints(Gridder *gridPtr, int rowOrColumn,
			    int maxOffset);
static void		SetGridSize(Gridder *gridPtr);
static int		SetSlaveColumn(Tcl_Interp *interp, Gridder *slavePtr,
static int		SetContentColumn(Tcl_Interp *interp, Gridder *contentPtr,
			    int column, int numCols);
static int		SetSlaveRow(Tcl_Interp *interp, Gridder *slavePtr,
static int		SetContentRow(Tcl_Interp *interp, Gridder *contentPtr,
			    int row, int numRows);
static Tcl_Obj *	StickyToObj(int flags);
static int		StringToSticky(const char *string);
static void		Unlink(Gridder *gridPtr);

static const Tk_GeomMgr gridMgrType = {
    "grid",			/* name */
    GridReqProc,		/* requestProc */
    GridLostSlaveProc,		/* lostSlaveProc */
    GridLostContentProc,		/* lostContentProc */
};

/*
 *----------------------------------------------------------------------
 *
 * Tk_GridCmd --
 *
331
332
333
334
335
336
337
338

339
340
341
342







343
344
345
346
347


348
349
350
351
352
353
354
355
356

357
358
359
360
361
362
363








364
365


366
367
368
369
370
371
372
373
374
375

376
377
378
379
380
381
382
383
384
385
386
387

388

389
390
391
392
393
394
395
396





397
398
399
400
401
402
403
331
332
333
334
335
336
337

338
339
340


341
342
343
344
345
346
347
348
349
350


351
352
353
354
355
356
357
358
359
360

361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376


377
378
379
380
381
382
383
384
385
386
387

388
389
390
391
392
393
394
395
396
397
398
399
400
401

402
403
404
405





406
407
408
409
410
411
412
413
414
415
416
417







-
+


-
-
+
+
+
+
+
+
+



-
-
+
+








-
+







+
+
+
+
+
+
+
+
-
-
+
+









-
+












+
-
+



-
-
-
-
-
+
+
+
+
+







int
Tk_GridObjCmd(
    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;
    static const char *const optionStrings[] = {
	"anchor", "bbox", "columnconfigure", "configure",
	"forget", "info", "location", "propagate", "remove",
	"rowconfigure", "size",	"slaves", NULL
	"content", "forget", "info", "location", "propagate",
	"remove", "rowconfigure", "size", "slaves", NULL
    };
    static const char *const optionStringsNoDep[] = {
	"anchor", "bbox", "columnconfigure", "configure",
	"content", "forget", "info", "location", "propagate",
	"remove", "rowconfigure", "size", NULL
    };
    enum options {
	GRID_ANCHOR, GRID_BBOX, GRID_COLUMNCONFIGURE, GRID_CONFIGURE,
	GRID_FORGET, GRID_INFO, GRID_LOCATION, GRID_PROPAGATE, GRID_REMOVE,
	GRID_ROWCONFIGURE, GRID_SIZE, GRID_SLAVES
	GRID_CONTENT, GRID_FORGET, GRID_INFO, GRID_LOCATION, GRID_PROPAGATE,
	GRID_REMOVE, GRID_ROWCONFIGURE, GRID_SIZE, GRID_SLAVES
    };
    int index;

    if (objc >= 2) {
	const char *argv1 = Tcl_GetString(objv[1]);

	if ((argv1[0] == '.') || (argv1[0] == REL_SKIP) ||
    		(argv1[0] == REL_VERT)) {
	    return ConfigureSlaves(interp, tkwin, objc-1, objv+1);
	    return ConfigureContent(interp, tkwin, objc-1, objv+1);
	}
    }
    if (objc < 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?");
	return TCL_ERROR;
    }

    if (Tcl_GetIndexFromObjStruct(NULL, objv[1], optionStrings,
	    sizeof(char *), "option", 0, &index) != TCL_OK) {
	/*
	 * Call it again without the deprecated ones to get a proper error
	 * message. This works well since there can't be any ambiguity between
	 * deprecated and new options.
	 */

    if (Tcl_GetIndexFromObjStruct(interp, objv[1], optionStrings,
	    sizeof(char *), "option", 0, &index) != TCL_OK) {
	Tcl_GetIndexFromObjStruct(interp, objv[1], optionStringsNoDep,
		sizeof(char *), "option", 0, &index);
	return TCL_ERROR;
    }

    switch ((enum options) index) {
    case GRID_ANCHOR:
	return GridAnchorCommand(tkwin, interp, objc, objv);
    case GRID_BBOX:
	return GridBboxCommand(tkwin, interp, objc, objv);
    case GRID_CONFIGURE:
	return ConfigureSlaves(interp, tkwin, objc-2, objv+2);
	return ConfigureContent(interp, tkwin, objc-2, objv+2);
    case GRID_FORGET:
    case GRID_REMOVE:
	return GridForgetRemoveCommand(tkwin, interp, objc, objv);
    case GRID_INFO:
	return GridInfoCommand(tkwin, interp, objc, objv);
    case GRID_LOCATION:
	return GridLocationCommand(tkwin, interp, objc, objv);
    case GRID_PROPAGATE:
	return GridPropagateCommand(tkwin, interp, objc, objv);
    case GRID_SIZE:
	return GridSizeCommand(tkwin, interp, objc, objv);
    case GRID_SLAVES:
    case GRID_CONTENT:
	return GridSlavesCommand(tkwin, interp, objc, objv);
	return GridContentCommand(tkwin, interp, objc, objv);

    /*
     * Sample argument combinations:
     *  grid columnconfigure <master> <index> -option
     *  grid columnconfigure <master> <index> -option value -option value
     *  grid rowconfigure <master> <index>
     *  grid rowconfigure <master> <index> -option
     *  grid rowconfigure <master> <index> -option value -option value.
     *  grid columnconfigure <container> <index> -option
     *  grid columnconfigure <container> <index> -option value -option value
     *  grid rowconfigure <container> <index>
     *  grid rowconfigure <container> <index> -option
     *  grid rowconfigure <container> <index> -option value -option value.
     */

    case GRID_COLUMNCONFIGURE:
    case GRID_ROWCONFIGURE:
	return GridRowColumnConfigureCommand(tkwin, interp, objc, objv);
    }

427
428
429
430
431
432
433
434
435
436



437
438
439
440
441
442
443
444

445
446
447

448
449
450

451
452
453
454
455
456
457
458


459
460
461
462
463
464
465
466
467
468
469
470


471
472
473
474



475
476
477
478
479
480
481
441
442
443
444
445
446
447



448
449
450
451
452
453
454
455
456
457

458
459
460

461
462
463

464
465
466
467
468
469
470


471
472
473
474
475
476
477
478
479
480
481
482


483
484
485



486
487
488
489
490
491
492
493
494
495







-
-
-
+
+
+







-
+


-
+


-
+






-
-
+
+










-
-
+
+

-
-
-
+
+
+







static int
GridAnchorCommand(
    Tk_Window tkwin,		/* Main window of the application. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tk_Window master;
    Gridder *masterPtr;
    GridMaster *gridPtr;
    Tk_Window container;
    Gridder *containerPtr;
    GridContainer *gridPtr;
    Tk_Anchor old;

    if (objc > 4) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?anchor?");
	return TCL_ERROR;
    }

    if (TkGetWindowFromObj(interp, tkwin, objv[2], &master) != TCL_OK) {
    if (TkGetWindowFromObj(interp, tkwin, objv[2], &container) != TCL_OK) {
	return TCL_ERROR;
    }
    masterPtr = GetGrid(master);
    containerPtr = GetGrid(container);

    if (objc == 3) {
	gridPtr = masterPtr->masterDataPtr;
	gridPtr = containerPtr->containerDataPtr;
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		Tk_NameOfAnchor(gridPtr?gridPtr->anchor:GRID_DEFAULT_ANCHOR),
		-1));
	return TCL_OK;
    }

    InitMasterData(masterPtr);
    gridPtr = masterPtr->masterDataPtr;
    InitContainerData(containerPtr);
    gridPtr = containerPtr->containerDataPtr;
    old = gridPtr->anchor;
    if (Tk_GetAnchorFromObj(interp, objv[3], &gridPtr->anchor) != TCL_OK) {
	return TCL_ERROR;
    }

    /*
     * Only request a relayout if the anchor changes.
     */

    if (old != gridPtr->anchor) {
	if (masterPtr->abortPtr != NULL) {
	    *masterPtr->abortPtr = 1;
	if (containerPtr->abortPtr != NULL) {
	    *containerPtr->abortPtr = 1;
	}
	if (!(masterPtr->flags & REQUESTED_RELAYOUT)) {
	    masterPtr->flags |= REQUESTED_RELAYOUT;
	    Tcl_DoWhenIdle(ArrangeGrid, masterPtr);
	if (!(containerPtr->flags & REQUESTED_RELAYOUT)) {
	    containerPtr->flags |= REQUESTED_RELAYOUT;
	    Tcl_DoWhenIdle(ArrangeGrid, containerPtr);
	}
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
496
497
498
499
500
501
502
503
504
505



506
507
508
509
510
511
512
513

514
515
516
517

518
519
520

521
522
523
524
525
526
527
510
511
512
513
514
515
516



517
518
519
520
521
522
523
524
525
526

527
528
529
530

531
532
533

534
535
536
537
538
539
540
541







-
-
-
+
+
+







-
+



-
+


-
+







static int
GridBboxCommand(
    Tk_Window tkwin,		/* Main window of the application. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tk_Window master;
    Gridder *masterPtr;		/* master grid record */
    GridMaster *gridPtr;	/* pointer to grid data */
    Tk_Window container;
    Gridder *containerPtr;		/* container grid record */
    GridContainer *gridPtr;	/* pointer to grid data */
    int row, column;		/* origin for bounding box */
    int row2, column2;		/* end of bounding box */
    int endX, endY;		/* last column/row in the layout */
    int x=0, y=0;		/* starting pixels for this bounding box */
    int width, height;		/* size of the bounding box */

    if (objc!=3 && objc != 5 && objc != 7) {
	Tcl_WrongNumArgs(interp, 2, objv, "master ?column row ?column row??");
	Tcl_WrongNumArgs(interp, 2, objv, "window ?column row ?column row??");
	return TCL_ERROR;
    }

    if (TkGetWindowFromObj(interp, tkwin, objv[2], &master) != TCL_OK) {
    if (TkGetWindowFromObj(interp, tkwin, objv[2], &container) != TCL_OK) {
	return TCL_ERROR;
    }
    masterPtr = GetGrid(master);
    containerPtr = GetGrid(container);

    if (objc >= 5) {
	if (Tcl_GetIntFromObj(interp, objv[3], &column) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (Tcl_GetIntFromObj(interp, objv[4], &row) != TCL_OK) {
	    return TCL_ERROR;
535
536
537
538
539
540
541
542

543
544
545
546
547
548

549
550
551
552
553
554
555
549
550
551
552
553
554
555

556
557
558
559
560
561

562
563
564
565
566
567
568
569







-
+





-
+







	    return TCL_ERROR;
	}
	if (Tcl_GetIntFromObj(interp, objv[6], &row2) != TCL_OK) {
	    return TCL_ERROR;
	}
    }

    gridPtr = masterPtr->masterDataPtr;
    gridPtr = containerPtr->containerDataPtr;
    if (gridPtr == NULL) {
	Tcl_SetObjResult(interp, NewQuadObj(0, 0, 0, 0));
	return TCL_OK;
    }

    SetGridSize(masterPtr);
    SetGridSize(containerPtr);
    endX = MAX(gridPtr->columnEnd, gridPtr->columnMax);
    endY = MAX(gridPtr->rowEnd, gridPtr->rowMax);

    if ((endX == 0) || (endY == 0)) {
	Tcl_SetObjResult(interp, NewQuadObj(0, 0, 0, 0));
	return TCL_OK;
    }
626
627
628
629
630
631
632
633
634


635
636
637
638
639
640

641
642
643
644
645


646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663













664
665
666
667



668
669
670


671
672
673
674


675
676
677
678
679



680
681
682
683
684




685
686
687
688
689
690




691
692
693


694
695
696
697
698
699
700
640
641
642
643
644
645
646


647
648
649
650
651
652
653

654
655
656
657


658
659
660
661
662
663
664













665
666
667
668
669
670
671
672
673
674
675
676
677
678



679
680
681
682


683
684
685
686


687
688
689
690



691
692
693
694




695
696
697
698
699
700




701
702
703
704
705


706
707
708
709
710
711
712
713
714







-
-
+
+





-
+



-
-
+
+





-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
+
+
+

-
-
+
+


-
-
+
+


-
-
-
+
+
+

-
-
-
-
+
+
+
+


-
-
-
-
+
+
+
+

-
-
+
+







static int
GridForgetRemoveCommand(
    Tk_Window tkwin,		/* Main window of the application. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tk_Window slave;
    Gridder *slavePtr;
    Tk_Window content;
    Gridder *contentPtr;
    int i;
    const char *string = Tcl_GetString(objv[1]);
    char c = string[0];

    for (i = 2; i < objc; i++) {
	if (TkGetWindowFromObj(interp, tkwin, objv[i], &slave) != TCL_OK) {
	if (TkGetWindowFromObj(interp, tkwin, objv[i], &content) != TCL_OK) {
	    return TCL_ERROR;
	}

	slavePtr = GetGrid(slave);
	if (slavePtr->masterPtr != NULL) {
	contentPtr = GetGrid(content);
	if (contentPtr->containerPtr != NULL) {
	    /*
	     * For "forget", reset all the settings to their defaults
	     */

	    if (c == 'f') {
		slavePtr->column = -1;
		slavePtr->row = -1;
		slavePtr->numCols = 1;
		slavePtr->numRows = 1;
		slavePtr->padX = 0;
		slavePtr->padY = 0;
		slavePtr->padLeft = 0;
		slavePtr->padTop = 0;
		slavePtr->iPadX = 0;
		slavePtr->iPadY = 0;
		if (slavePtr->in != NULL) {
		    Tcl_DecrRefCount(slavePtr->in);
		    slavePtr->in = NULL;
		contentPtr->column = -1;
		contentPtr->row = -1;
		contentPtr->numCols = 1;
		contentPtr->numRows = 1;
		contentPtr->padX = 0;
		contentPtr->padY = 0;
		contentPtr->padLeft = 0;
		contentPtr->padTop = 0;
		contentPtr->iPadX = 0;
		contentPtr->iPadY = 0;
		if (contentPtr->in != NULL) {
		    Tcl_DecrRefCount(contentPtr->in);
		    contentPtr->in = NULL;
		}
		slavePtr->doubleBw = 2*Tk_Changes(tkwin)->border_width;
		if (slavePtr->flags & REQUESTED_RELAYOUT) {
		    Tcl_CancelIdleCall(ArrangeGrid, slavePtr);
		contentPtr->doubleBw = 2*Tk_Changes(tkwin)->border_width;
		if (contentPtr->flags & REQUESTED_RELAYOUT) {
		    Tcl_CancelIdleCall(ArrangeGrid, contentPtr);
		}
		slavePtr->flags = 0;
		slavePtr->sticky = 0;
		contentPtr->flags = 0;
		contentPtr->sticky = 0;
	    } else {
		/*
		 * When removing, store name of master to be able to
		 * restore it later, even if the master is recreated.
		 * When removing, store name of container to be able to
		 * restore it later, even if the container is recreated.
		 */

		if (slavePtr->in != NULL) {
		    Tcl_DecrRefCount(slavePtr->in);
		    slavePtr->in = NULL;
		if (contentPtr->in != NULL) {
		    Tcl_DecrRefCount(contentPtr->in);
		    contentPtr->in = NULL;
		}
		if (slavePtr->masterPtr != NULL) {
		    slavePtr->in = Tcl_NewStringObj(
			    Tk_PathName(slavePtr->masterPtr->tkwin), -1);
		    Tcl_IncrRefCount(slavePtr->in);
		if (contentPtr->containerPtr != NULL) {
		    contentPtr->in = Tcl_NewStringObj(
			    Tk_PathName(contentPtr->containerPtr->tkwin), -1);
		    Tcl_IncrRefCount(contentPtr->in);
		}
	    }
	    Tk_ManageGeometry(slave, NULL, NULL);
	    if (slavePtr->masterPtr->tkwin != Tk_Parent(slavePtr->tkwin)) {
		Tk_UnmaintainGeometry(slavePtr->tkwin,
			slavePtr->masterPtr->tkwin);
	    Tk_ManageGeometry(content, NULL, NULL);
	    if (contentPtr->containerPtr->tkwin != Tk_Parent(contentPtr->tkwin)) {
		Tk_UnmaintainGeometry(contentPtr->tkwin,
			contentPtr->containerPtr->tkwin);
	    }
	    Unlink(slavePtr);
	    Tk_UnmapWindow(slavePtr->tkwin);
	    Unlink(contentPtr);
	    Tk_UnmapWindow(contentPtr->tkwin);
	}
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
716
717
718
719
720
721
722
723
724


725
726
727
728
729
730
731

732
733
734
735


736
737
738
739
740
741
742

743
744

745
746

747
748

749
750
751
752
753
754





755
756

757
758
759
760
761
762
763
730
731
732
733
734
735
736


737
738
739
740
741
742
743
744

745
746
747


748
749
750
751
752
753
754
755

756
757

758
759

760
761

762
763





764
765
766
767
768
769

770
771
772
773
774
775
776
777







-
-
+
+






-
+


-
-
+
+






-
+

-
+

-
+

-
+

-
-
-
-
-
+
+
+
+
+

-
+







static int
GridInfoCommand(
    Tk_Window tkwin,		/* Main window of the application. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    register Gridder *slavePtr;
    Tk_Window slave;
    Gridder *contentPtr;
    Tk_Window content;
    Tcl_Obj *infoObj;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "window");
	return TCL_ERROR;
    }
    if (TkGetWindowFromObj(interp, tkwin, objv[2], &slave) != TCL_OK) {
    if (TkGetWindowFromObj(interp, tkwin, objv[2], &content) != TCL_OK) {
	return TCL_ERROR;
    }
    slavePtr = GetGrid(slave);
    if (slavePtr->masterPtr == NULL) {
    contentPtr = GetGrid(content);
    if (contentPtr->containerPtr == NULL) {
	Tcl_ResetResult(interp);
	return TCL_OK;
    }

    infoObj = Tcl_NewObj();
    Tcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj("-in", -1),
	    TkNewWindowObj(slavePtr->masterPtr->tkwin));
	    Tk_NewWindowObj(contentPtr->containerPtr->tkwin));
    Tcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj("-column", -1),
	    Tcl_NewIntObj(slavePtr->column));
	    Tcl_NewWideIntObj(contentPtr->column));
    Tcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj("-row", -1),
	    Tcl_NewIntObj(slavePtr->row));
	    Tcl_NewWideIntObj(contentPtr->row));
    Tcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj("-columnspan", -1),
	    Tcl_NewIntObj(slavePtr->numCols));
	    Tcl_NewWideIntObj(contentPtr->numCols));
    Tcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj("-rowspan", -1),
	    Tcl_NewIntObj(slavePtr->numRows));
    TkAppendPadAmount(infoObj, "-ipadx", slavePtr->iPadX/2, slavePtr->iPadX);
    TkAppendPadAmount(infoObj, "-ipady", slavePtr->iPadY/2, slavePtr->iPadY);
    TkAppendPadAmount(infoObj, "-padx", slavePtr->padLeft, slavePtr->padX);
    TkAppendPadAmount(infoObj, "-pady", slavePtr->padTop, slavePtr->padY);
	    Tcl_NewWideIntObj(contentPtr->numRows));
    TkAppendPadAmount(infoObj, "-ipadx", contentPtr->iPadX/2, contentPtr->iPadX);
    TkAppendPadAmount(infoObj, "-ipady", contentPtr->iPadY/2, contentPtr->iPadY);
    TkAppendPadAmount(infoObj, "-padx", contentPtr->padLeft, contentPtr->padX);
    TkAppendPadAmount(infoObj, "-pady", contentPtr->padTop, contentPtr->padY);
    Tcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj("-sticky", -1),
	    StickyToObj(slavePtr->sticky));
	    StickyToObj(contentPtr->sticky));
    Tcl_SetObjResult(interp, infoObj);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
778
779
780
781
782
783
784
785
786
787
788
789





790
791
792
793
794





795
796
797
798
799
800
801
802

803
804
805

806
807
808
809
810


811
812
813
814

815
816
817
818
819
820
821
822
823
824



825
826

827
828
829
830
831


832
833
834

835
836
837
838
839
840
841


842
843
844

845
846
847
848
849
850
851
792
793
794
795
796
797
798





799
800
801
802
803
804
805
806
807

808
809
810
811
812
813
814
815





816
817
818

819
820
821
822


823
824
825
826
827

828
829
830
831
832
833
834
835



836
837
838
839

840
841
842
843


844
845
846
847

848
849
850
851
852
853


854
855
856
857

858
859
860
861
862
863
864
865







-
-
-
-
-
+
+
+
+
+




-
+
+
+
+
+



-
-
-
-
-
+


-
+



-
-
+
+



-
+







-
-
-
+
+
+

-
+



-
-
+
+


-
+





-
-
+
+


-
+







static int
GridLocationCommand(
    Tk_Window tkwin,		/* Main window of the application. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tk_Window master;
    Gridder *masterPtr;		/* Master grid record. */
    GridMaster *gridPtr;	/* Pointer to grid data. */
    register SlotInfo *slotPtr;
    int x, y;			/* Offset in pixels, from edge of master. */
    Tk_Window container;
    Gridder *containerPtr;		/* Container grid record. */
    GridContainer *gridPtr;	/* Pointer to grid data. */
    SlotInfo *slotPtr;
    int x, y;			/* Offset in pixels, from edge of container. */
    int i, j;			/* Corresponding column and row indeces. */
    int endX, endY;		/* End of grid. */

    if (objc != 5) {
	Tcl_WrongNumArgs(interp, 2, objv, "master x y");
	Tcl_WrongNumArgs(interp, 2, objv, "window x y");
	return TCL_ERROR;
    }

    if (TkGetWindowFromObj(interp, tkwin, objv[2], &container) != TCL_OK) {
	return TCL_ERROR;
    }

    if (TkGetWindowFromObj(interp, tkwin, objv[2], &master) != TCL_OK) {
	return TCL_ERROR;
    }

    if (Tk_GetPixelsFromObj(interp, master, objv[3], &x) != TCL_OK) {
    if (Tk_GetPixelsFromObj(interp, container, objv[3], &x) != TCL_OK) {
	return TCL_ERROR;
    }
    if (Tk_GetPixelsFromObj(interp, master, objv[4], &y) != TCL_OK) {
    if (Tk_GetPixelsFromObj(interp, container, objv[4], &y) != TCL_OK) {
	return TCL_ERROR;
    }

    masterPtr = GetGrid(master);
    if (masterPtr->masterDataPtr == NULL) {
    containerPtr = GetGrid(container);
    if (containerPtr->containerDataPtr == NULL) {
	Tcl_SetObjResult(interp, NewPairObj(-1, -1));
	return TCL_OK;
    }
    gridPtr = masterPtr->masterDataPtr;
    gridPtr = containerPtr->containerDataPtr;

    /*
     * Update any pending requests. This is not always the steady state value,
     * as more configure events could be in the pipeline, but its as close as
     * its easy to get.
     */

    while (masterPtr->flags & REQUESTED_RELAYOUT) {
	Tcl_CancelIdleCall(ArrangeGrid, masterPtr);
	ArrangeGrid(masterPtr);
    while (containerPtr->flags & REQUESTED_RELAYOUT) {
	Tcl_CancelIdleCall(ArrangeGrid, containerPtr);
	ArrangeGrid(containerPtr);
    }
    SetGridSize(masterPtr);
    SetGridSize(containerPtr);
    endX = MAX(gridPtr->columnEnd, gridPtr->columnMax);
    endY = MAX(gridPtr->rowEnd, gridPtr->rowMax);

    slotPtr = masterPtr->masterDataPtr->columnPtr;
    if (x < masterPtr->masterDataPtr->startX) {
    slotPtr = containerPtr->containerDataPtr->columnPtr;
    if (x < containerPtr->containerDataPtr->startX) {
	i = -1;
    } else {
	x -= masterPtr->masterDataPtr->startX;
	x -= containerPtr->containerDataPtr->startX;
	for (i = 0; slotPtr[i].offset < x && i < endX; i++) {
	    /* null body */
	}
    }

    slotPtr = masterPtr->masterDataPtr->rowPtr;
    if (y < masterPtr->masterDataPtr->startY) {
    slotPtr = containerPtr->containerDataPtr->rowPtr;
    if (y < containerPtr->containerDataPtr->startY) {
	j = -1;
    } else {
	y -= masterPtr->masterDataPtr->startY;
	y -= containerPtr->containerDataPtr->startY;
	for (j = 0; slotPtr[j].offset < y && j < endY; j++) {
	    /* null body */
	}
    }

    Tcl_SetObjResult(interp, NewPairObj(i, j));
    return TCL_OK;
871
872
873
874
875
876
877
878
879


880
881
882
883
884
885
886
887

888
889
890

891
892
893

894
895
896
897
898
899
900
901
902
903
904

905
906
907
908

909
910
911
912


913
914
915

916
917

918
919
920
921



922
923

924
925
926
927
928


929
930
931
932


933
934
935
936



937
938
939
940
941
942
943
885
886
887
888
889
890
891


892
893
894
895
896
897
898
899
900

901
902
903

904
905
906

907
908
909
910
911
912
913
914
915
916
917

918
919
920
921

922
923
924


925
926
927
928

929
930

931
932



933
934
935
936

937
938
939
940


941
942
943
944


945
946
947



948
949
950
951
952
953
954
955
956
957







-
-
+
+







-
+


-
+


-
+










-
+



-
+


-
-
+
+


-
+

-
+

-
-
-
+
+
+

-
+



-
-
+
+


-
-
+
+

-
-
-
+
+
+







static int
GridPropagateCommand(
    Tk_Window tkwin,		/* Main window of the application. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tk_Window master;
    Gridder *masterPtr;
    Tk_Window container;
    Gridder *containerPtr;
    int propagate, old;

    if (objc > 4) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?boolean?");
	return TCL_ERROR;
    }

    if (TkGetWindowFromObj(interp, tkwin, objv[2], &master) != TCL_OK) {
    if (TkGetWindowFromObj(interp, tkwin, objv[2], &container) != TCL_OK) {
	return TCL_ERROR;
    }
    masterPtr = GetGrid(master);
    containerPtr = GetGrid(container);
    if (objc == 3) {
	Tcl_SetObjResult(interp,
		Tcl_NewBooleanObj(!(masterPtr->flags & DONT_PROPAGATE)));
		Tcl_NewBooleanObj(!(containerPtr->flags & DONT_PROPAGATE)));
	return TCL_OK;
    }
    if (Tcl_GetBooleanFromObj(interp, objv[3], &propagate) != TCL_OK) {
	return TCL_ERROR;
    }

    /*
     * Only request a relayout if the propagation bit changes.
     */

    old = !(masterPtr->flags & DONT_PROPAGATE);
    old = !(containerPtr->flags & DONT_PROPAGATE);
    if (propagate != old) {
	if (propagate) {
	    /*
	     * If we have slaves, we need to register as geometry master.
	     * If we have content, we need to register as geometry container.
	     */

	    if (masterPtr->slavePtr != NULL) {
		if (TkSetGeometryMaster(interp, master, "grid")	!= TCL_OK) {
	    if (containerPtr->contentPtr != NULL) {
		if (TkSetGeometryContainer(interp, container, "grid")	!= TCL_OK) {
		    return TCL_ERROR;
		}
		masterPtr->flags |= ALLOCED_MASTER;
		containerPtr->flags |= ALLOCED_CONTAINER;
	    }
	    masterPtr->flags &= ~DONT_PROPAGATE;
	    containerPtr->flags &= ~DONT_PROPAGATE;
	} else {
	    if (masterPtr->flags & ALLOCED_MASTER) {
		TkFreeGeometryMaster(master, "grid");
		masterPtr->flags &= ~ALLOCED_MASTER;
	    if (containerPtr->flags & ALLOCED_CONTAINER) {
		TkFreeGeometryContainer(container, "grid");
		containerPtr->flags &= ~ALLOCED_CONTAINER;
	    }
	    masterPtr->flags |= DONT_PROPAGATE;
	    containerPtr->flags |= DONT_PROPAGATE;
	}

	/*
	 * Re-arrange the master to allow new geometry information to
	 * propagate upwards to the master's master.
	 * Re-arrange the container to allow new geometry information to
	 * propagate upwards to the container's container.
	 */

	if (masterPtr->abortPtr != NULL) {
	    *masterPtr->abortPtr = 1;
	if (containerPtr->abortPtr != NULL) {
	    *containerPtr->abortPtr = 1;
	}
	if (!(masterPtr->flags & REQUESTED_RELAYOUT)) {
	    masterPtr->flags |= REQUESTED_RELAYOUT;
	    Tcl_DoWhenIdle(ArrangeGrid, masterPtr);
	if (!(containerPtr->flags & REQUESTED_RELAYOUT)) {
	    containerPtr->flags |= REQUESTED_RELAYOUT;
	    Tcl_DoWhenIdle(ArrangeGrid, containerPtr);
	}
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
959
960
961
962
963
964
965
966
967


968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987

988
989
990
991

992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014



1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032

1033
1034
1035
1036


1037
1038
1039
1040
1041
1042
1043
973
974
975
976
977
978
979


980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000

1001
1002
1003
1004

1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025



1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045

1046
1047
1048


1049
1050
1051
1052
1053
1054
1055
1056
1057







-
-
+
+



















-
+



-
+




















-
-
-
+
+
+

















-
+


-
-
+
+







static int
GridRowColumnConfigureCommand(
    Tk_Window tkwin,		/* Main window of the application. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tk_Window master, slave;
    Gridder *masterPtr, *slavePtr;
    Tk_Window container, content;
    Gridder *containerPtr, *contentPtr;
    SlotInfo *slotPtr = NULL;
    int slot;			/* the column or row number */
    int slotType;		/* COLUMN or ROW */
    int size;			/* the configuration value */
    int lObjc;			/* Number of items in index list */
    Tcl_Obj **lObjv;		/* array of indices */
    int ok;			/* temporary TCL result code */
    int i, j, first, last;
    const char *string;
    static const char *const optionStrings[] = {
	"-minsize", "-pad", "-uniform", "-weight", NULL
    };
    enum options {
	ROWCOL_MINSIZE, ROWCOL_PAD, ROWCOL_UNIFORM, ROWCOL_WEIGHT
    };
    int index;
    Tcl_Obj *listCopy;

    if (((objc % 2 != 0) && (objc > 6)) || (objc < 4)) {
	Tcl_WrongNumArgs(interp, 2, objv, "master index ?-option value ...?");
	Tcl_WrongNumArgs(interp, 2, objv, "window index ?-option value ...?");
	return TCL_ERROR;
    }

    if (TkGetWindowFromObj(interp, tkwin, objv[2], &master) != TCL_OK) {
    if (TkGetWindowFromObj(interp, tkwin, objv[2], &container) != TCL_OK) {
	return TCL_ERROR;
    }

    listCopy = Tcl_DuplicateObj(objv[3]);
    Tcl_IncrRefCount(listCopy);
    if (Tcl_ListObjGetElements(interp, listCopy, &lObjc, &lObjv) != TCL_OK) {
	Tcl_DecrRefCount(listCopy);
	return TCL_ERROR;
    }

    string = Tcl_GetString(objv[1]);
    slotType = (*string == 'c') ? COLUMN : ROW;
    if (lObjc == 0) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf("no %s indices specified",
		(slotType == COLUMN) ? "column" : "row"));
	Tcl_SetErrorCode(interp, "TK", "GRID", "NO_INDEX", NULL);
	Tcl_DecrRefCount(listCopy);
	return TCL_ERROR;
    }

    masterPtr = GetGrid(master);
    first = 0; /* lint */
    last = 0; /* lint */
    containerPtr = GetGrid(container);
    first = 0;
    last = 0;

    if ((objc == 4) || (objc == 5)) {
	if (lObjc != 1) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "must specify a single element on retrieval", -1));
	    Tcl_SetErrorCode(interp, "TK", "GRID", "USAGE", NULL);
	    Tcl_DecrRefCount(listCopy);
	    return TCL_ERROR;
	}
	if (Tcl_GetIntFromObj(interp, lObjv[0], &slot) != TCL_OK) {
	    Tcl_AppendResult(interp,
		    " (when retrieving options only integer indices are "
		    "allowed)", NULL);
	    Tcl_SetErrorCode(interp, "TK", "GRID", "INDEX_FORMAT", NULL);
	    Tcl_DecrRefCount(listCopy);
	    return TCL_ERROR;
	}
	ok = CheckSlotData(masterPtr, slot, slotType, /* checkOnly */ 1);
	ok = CheckSlotData(containerPtr, slot, slotType, /* checkOnly */ 1);
	if (ok == TCL_OK) {
	    slotPtr = (slotType == COLUMN) ?
		    masterPtr->masterDataPtr->columnPtr :
		    masterPtr->masterDataPtr->rowPtr;
		    containerPtr->containerDataPtr->columnPtr :
		    containerPtr->containerDataPtr->rowPtr;
	}

	/*
	 * Return all of the options for this row or column. If the request is
	 * out of range, return all 0's.
	 */

1051
1052
1053
1054
1055
1056
1057
1058

1059
1060
1061

1062
1063
1064
1065
1066
1067
1068

1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085

1086
1087
1088

1089
1090
1091
1092
1093
1094
1095
1096

1097
1098
1099
1100
1101
1102
1103
1104

1105
1106
1107
1108
1109

1110
1111
1112

1113
1114
1115

1116
1117
1118


1119
1120
1121
1122


1123
1124
1125

1126
1127
1128
1129


1130
1131
1132
1133

1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150

1151
1152

1153
1154

1155
1156
1157
1158

1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170


1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184

1185
1186
1187
1188
1189
1190
1191
1065
1066
1067
1068
1069
1070
1071

1072
1073
1074

1075
1076
1077
1078
1079
1080
1081

1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098

1099
1100
1101

1102
1103
1104
1105
1106
1107
1108
1109

1110
1111
1112
1113
1114
1115
1116
1117

1118
1119
1120
1121
1122

1123
1124
1125

1126
1127
1128

1129
1130


1131
1132
1133
1134


1135
1136
1137
1138

1139
1140
1141


1142
1143
1144
1145
1146

1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163

1164
1165

1166
1167

1168
1169
1170
1171

1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182


1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197

1198
1199
1200
1201
1202
1203
1204
1205







-
+


-
+






-
+
















-
+


-
+







-
+







-
+




-
+


-
+


-
+

-
-
+
+


-
-
+
+


-
+


-
-
+
+



-
+
















-
+

-
+

-
+



-
+










-
-
+
+













-
+







		pad     = slotPtr[slot].pad;
		weight  = slotPtr[slot].weight;
		uniform = slotPtr[slot].uniform;
	    }

	    Tcl_ListObjAppendElement(interp, res,
		    Tcl_NewStringObj("-minsize", -1));
	    Tcl_ListObjAppendElement(interp, res, Tcl_NewIntObj(minsize));
	    Tcl_ListObjAppendElement(interp, res, Tcl_NewWideIntObj(minsize));
	    Tcl_ListObjAppendElement(interp, res,
		    Tcl_NewStringObj("-pad", -1));
	    Tcl_ListObjAppendElement(interp, res, Tcl_NewIntObj(pad));
	    Tcl_ListObjAppendElement(interp, res, Tcl_NewWideIntObj(pad));
	    Tcl_ListObjAppendElement(interp, res,
		    Tcl_NewStringObj("-uniform", -1));
	    Tcl_ListObjAppendElement(interp, res,
		    Tcl_NewStringObj(uniform == NULL ? "" : uniform, -1));
	    Tcl_ListObjAppendElement(interp, res,
		    Tcl_NewStringObj("-weight", -1));
	    Tcl_ListObjAppendElement(interp, res, Tcl_NewIntObj(weight));
	    Tcl_ListObjAppendElement(interp, res, Tcl_NewWideIntObj(weight));
	    Tcl_SetObjResult(interp, res);
	    Tcl_DecrRefCount(listCopy);
	    return TCL_OK;
	}

	/*
	 * If only one option is given, with no value, the current value is
	 * returned.
	 */

	if (Tcl_GetIndexFromObjStruct(interp, objv[4], optionStrings,
		sizeof(char *), "option", 0, &index) != TCL_OK) {
	    Tcl_DecrRefCount(listCopy);
	    return TCL_ERROR;
	}
	if (index == ROWCOL_MINSIZE) {
	    Tcl_SetObjResult(interp, Tcl_NewIntObj(
	    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(
		    (ok == TCL_OK) ? slotPtr[slot].minSize : 0));
	} else if (index == ROWCOL_WEIGHT) {
	    Tcl_SetObjResult(interp, Tcl_NewIntObj(
	    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(
		    (ok == TCL_OK) ? slotPtr[slot].weight : 0));
	} else if (index == ROWCOL_UNIFORM) {
	    Tk_Uid value = (ok == TCL_OK) ? slotPtr[slot].uniform : "";

	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    (value == NULL) ? "" : value, -1));
	} else if (index == ROWCOL_PAD) {
	    Tcl_SetObjResult(interp, Tcl_NewIntObj(
	    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(
		    (ok == TCL_OK) ? slotPtr[slot].pad : 0));
	}
	Tcl_DecrRefCount(listCopy);
	return TCL_OK;
    }

    for (j = 0; j < lObjc; j++) {
	int allSlaves = 0;
	int allContent = 0;

	if (Tcl_GetIntFromObj(NULL, lObjv[j], &slot) == TCL_OK) {
	    first = slot;
	    last = slot;
	    slavePtr = NULL;
	    contentPtr = NULL;
	} else if (strcmp(Tcl_GetString(lObjv[j]), "all") == 0) {
	    /*
	     * Make sure master is initialised.
	     * Make sure container is initialised.
	     */

	    InitMasterData(masterPtr);
	    InitContainerData(containerPtr);

	    slavePtr = masterPtr->slavePtr;
	    if (slavePtr == NULL) {
	    contentPtr = containerPtr->contentPtr;
	    if (contentPtr == NULL) {
		continue;
	    }
	    allSlaves = 1;
	} else if (TkGetWindowFromObj(NULL, tkwin, lObjv[j], &slave)
	    allContent = 1;
	} else if (TkGetWindowFromObj(NULL, tkwin, lObjv[j], &content)
		== TCL_OK) {
	    /*
	     * Is it gridded in this master?
	     * Is it gridded in this container?
	     */

	    slavePtr = GetGrid(slave);
	    if (slavePtr->masterPtr != masterPtr) {
	    contentPtr = GetGrid(content);
	    if (contentPtr->containerPtr != containerPtr) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"the window \"%s\" is not managed by \"%s\"",
			Tcl_GetString(lObjv[j]), Tcl_GetString(objv[2])));
		Tcl_SetErrorCode(interp, "TK", "GRID", "NOT_MASTER", NULL);
		Tcl_SetErrorCode(interp, "TK", "GRID", "NOT_MANAGED", NULL);
		Tcl_DecrRefCount(listCopy);
		return TCL_ERROR;
	    }
	} else {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "illegal index \"%s\"", Tcl_GetString(lObjv[j])));
	    Tcl_SetErrorCode(interp, "TK", "VALUE", "GRID_INDEX", NULL);
	    Tcl_DecrRefCount(listCopy);
	    return TCL_ERROR;
	}

	/*
	 * The outer loop is only to handle "all".
	 */

	do {
	    if (slavePtr != NULL) {
	    if (contentPtr != NULL) {
		first = (slotType == COLUMN) ?
			slavePtr->column : slavePtr->row;
			contentPtr->column : contentPtr->row;
		last = first - 1 + ((slotType == COLUMN) ?
			slavePtr->numCols : slavePtr->numRows);
			contentPtr->numCols : contentPtr->numRows);
	    }

	    for (slot = first; slot <= last; slot++) {
		ok = CheckSlotData(masterPtr, slot, slotType, /*checkOnly*/ 0);
		ok = CheckSlotData(containerPtr, slot, slotType, /*checkOnly*/ 0);
		if (ok != TCL_OK) {
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			    "\"%s\" is out of range",
			    Tcl_GetString(lObjv[j])));
		    Tcl_SetErrorCode(interp, "TK", "GRID", "INDEX_RANGE",
			    NULL);
		    Tcl_DecrRefCount(listCopy);
		    return TCL_ERROR;
		}
		slotPtr = (slotType == COLUMN) ?
			masterPtr->masterDataPtr->columnPtr :
			masterPtr->masterDataPtr->rowPtr;
			containerPtr->containerDataPtr->columnPtr :
			containerPtr->containerDataPtr->rowPtr;

		/*
		 * Loop through each option value pair, setting the values as
		 * required.
		 */

		for (i = 4; i < objc; i += 2) {
		    if (Tcl_GetIndexFromObjStruct(interp, objv[i], optionStrings,
			    sizeof(char *), "option", 0, &index) != TCL_OK) {
			Tcl_DecrRefCount(listCopy);
			return TCL_ERROR;
		    }
		    if (index == ROWCOL_MINSIZE) {
			if (Tk_GetPixelsFromObj(interp, master, objv[i+1],
			if (Tk_GetPixelsFromObj(interp, container, objv[i+1],
				&size) != TCL_OK) {
			    Tcl_DecrRefCount(listCopy);
			    return TCL_ERROR;
			} else {
			    slotPtr[slot].minSize = size;
			}
		    } else if (index == ROWCOL_WEIGHT) {
1204
1205
1206
1207
1208
1209
1210
1211

1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225


1226
1227

1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238

1239
1240
1241
1242
1243
1244
1245

1246
1247

1248
1249
1250
1251
1252
1253
1254

1255
1256
1257
1258
1259


1260
1261
1262
1263



1264
1265
1266
1267
1268
1269
1270
1218
1219
1220
1221
1222
1223
1224

1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237


1238
1239
1240

1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251

1252
1253
1254
1255
1256
1257
1258

1259
1260

1261
1262
1263
1264
1265
1266
1267

1268
1269
1270
1271


1272
1273
1274



1275
1276
1277
1278
1279
1280
1281
1282
1283
1284







-
+












-
-
+
+

-
+










-
+






-
+

-
+






-
+



-
-
+
+

-
-
-
+
+
+







			slotPtr[slot].uniform =
				Tk_GetUid(Tcl_GetString(objv[i+1]));
			if (slotPtr[slot].uniform != NULL &&
				slotPtr[slot].uniform[0] == 0) {
			    slotPtr[slot].uniform = NULL;
			}
		    } else if (index == ROWCOL_PAD) {
			if (Tk_GetPixelsFromObj(interp, master, objv[i+1],
			if (Tk_GetPixelsFromObj(interp, container, objv[i+1],
				&size) != TCL_OK) {
			    Tcl_DecrRefCount(listCopy);
			    return TCL_ERROR;
			} else if (size < 0) {
			    Tcl_DecrRefCount(listCopy);
			    goto negativeIndex;
			} else {
			    slotPtr[slot].pad = size;
			}
		    }
		}
	    }
	    if (slavePtr != NULL) {
		slavePtr = slavePtr->nextPtr;
	    if (contentPtr != NULL) {
		contentPtr = contentPtr->nextPtr;
	    }
	} while ((allSlaves == 1) && (slavePtr != NULL));
	} while ((allContent == 1) && (contentPtr != NULL));
    }
    Tcl_DecrRefCount(listCopy);

    /*
     * We changed a property, re-arrange the table, and check for constraint
     * shrinkage. A null slotPtr will occur for 'all' checks.
     */

    if (slotPtr != NULL) {
	if (slotType == ROW) {
	    int last = masterPtr->masterDataPtr->rowMax - 1;
	    last = containerPtr->containerDataPtr->rowMax - 1;

	    while ((last >= 0) && (slotPtr[last].weight == 0)
		    && (slotPtr[last].pad == 0) && (slotPtr[last].minSize == 0)
		    && (slotPtr[last].uniform == NULL)) {
		last--;
	    }
	    masterPtr->masterDataPtr->rowMax = last+1;
	    containerPtr->containerDataPtr->rowMax = last+1;
	} else {
	    int last = masterPtr->masterDataPtr->columnMax - 1;
	    last = containerPtr->containerDataPtr->columnMax - 1;

	    while ((last >= 0) && (slotPtr[last].weight == 0)
		    && (slotPtr[last].pad == 0) && (slotPtr[last].minSize == 0)
		    && (slotPtr[last].uniform == NULL)) {
		last--;
	    }
	    masterPtr->masterDataPtr->columnMax = last + 1;
	    containerPtr->containerDataPtr->columnMax = last + 1;
	}
    }

    if (masterPtr->abortPtr != NULL) {
	*masterPtr->abortPtr = 1;
    if (containerPtr->abortPtr != NULL) {
	*containerPtr->abortPtr = 1;
    }
    if (!(masterPtr->flags & REQUESTED_RELAYOUT)) {
	masterPtr->flags |= REQUESTED_RELAYOUT;
	Tcl_DoWhenIdle(ArrangeGrid, masterPtr);
    if (!(containerPtr->flags & REQUESTED_RELAYOUT)) {
	containerPtr->flags |= REQUESTED_RELAYOUT;
	Tcl_DoWhenIdle(ArrangeGrid, containerPtr);
    }
    return TCL_OK;

  negativeIndex:
    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
	    "invalid arg \"%s\": should be non-negative",
	    Tcl_GetString(objv[i])));
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301



1302
1303
1304
1305
1306
1307
1308

1309
1310
1311

1312
1313
1314
1315



1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328

1329
1330

1331
1332
1333
1334
1335
1336
1337
1338


1339
1340
1341
1342
1343
1344

1345
1346
1347
1348
1349
1350
1351
1352



1353
1354
1355
1356
1357
1358

1359
1360
1361
1362
1363
1364
1365
1306
1307
1308
1309
1310
1311
1312



1313
1314
1315
1316
1317
1318
1319
1320
1321

1322
1323
1324

1325
1326



1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341

1342
1343

1344
1345
1346
1347
1348
1349
1350


1351
1352
1353
1354
1355
1356
1357

1358
1359
1360
1361
1362
1363



1364
1365
1366
1367
1368
1369
1370
1371

1372
1373
1374
1375
1376
1377
1378
1379







-
-
-
+
+
+






-
+


-
+

-
-
-
+
+
+












-
+

-
+






-
-
+
+





-
+





-
-
-
+
+
+





-
+







static int
GridSizeCommand(
    Tk_Window tkwin,		/* Main window of the application. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tk_Window master;
    Gridder *masterPtr;
    GridMaster *gridPtr;	/* pointer to grid data */
    Tk_Window container;
    Gridder *containerPtr;
    GridContainer *gridPtr;	/* pointer to grid data */

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "window");
	return TCL_ERROR;
    }

    if (TkGetWindowFromObj(interp, tkwin, objv[2], &master) != TCL_OK) {
    if (TkGetWindowFromObj(interp, tkwin, objv[2], &container) != TCL_OK) {
	return TCL_ERROR;
    }
    masterPtr = GetGrid(master);
    containerPtr = GetGrid(container);

    if (masterPtr->masterDataPtr != NULL) {
	SetGridSize(masterPtr);
	gridPtr = masterPtr->masterDataPtr;
    if (containerPtr->containerDataPtr != NULL) {
	SetGridSize(containerPtr);
	gridPtr = containerPtr->containerDataPtr;
	Tcl_SetObjResult(interp, NewPairObj(
		MAX(gridPtr->columnEnd, gridPtr->columnMax),
		MAX(gridPtr->rowEnd, gridPtr->rowMax)));
    } else {
	Tcl_SetObjResult(interp, NewPairObj(0, 0));
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * GridSlavesCommand --
 * GridContentCommand --
 *
 *	Implementation of the [grid slaves] subcommand. See the user
 *	Implementation of the [grid content] subcommand. See the user
 *	documentation for details on what it does.
 *
 * Results:
 *	Standard Tcl result.
 *
 * Side effects:
 *	Places a list of slaves of the specified window in the interpreter's
 *	result field.
 *	Places a list of content windows of the specified window in the
 *	interpreter's result field.
 *
 *----------------------------------------------------------------------
 */

static int
GridSlavesCommand(
GridContentCommand(
    Tk_Window tkwin,		/* Main window of the application. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tk_Window master;
    Gridder *masterPtr;		/* master grid record */
    Gridder *slavePtr;
    Tk_Window container;
    Gridder *containerPtr;		/* container grid record */
    Gridder *contentPtr;
    int i, value, index;
    int row = -1, column = -1;
    static const char *const optionStrings[] = {
	"-column", "-row", NULL
    };
    enum options { SLAVES_COLUMN, SLAVES_ROW };
    enum options { CONTENT_COLUMN, CONTENT_ROW };
    Tcl_Obj *res;

    if ((objc < 3) || ((objc % 2) == 0)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?-option value ...?");
	return TCL_ERROR;
    }

1373
1374
1375
1376
1377
1378
1379
1380

1381
1382
1383
1384
1385
1386
1387

1388
1389
1390

1391
1392
1393
1394
1395
1396




1397
1398
1399
1400


1401
1402
1403

1404
1405
1406
1407
1408
1409
1410
1387
1388
1389
1390
1391
1392
1393

1394
1395
1396
1397
1398
1399
1400

1401
1402
1403

1404
1405
1406




1407
1408
1409
1410
1411
1412


1413
1414
1415
1416

1417
1418
1419
1420
1421
1422
1423
1424







-
+






-
+


-
+


-
-
-
-
+
+
+
+


-
-
+
+


-
+







	}
	if (value < 0) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "%d is an invalid value: should NOT be < 0", value));
	    Tcl_SetErrorCode(interp, "TK", "GRID", "NEG_INDEX", NULL);
	    return TCL_ERROR;
	}
	if (index == SLAVES_COLUMN) {
	if (index == CONTENT_COLUMN) {
	    column = value;
	} else {
	    row = value;
	}
    }

    if (TkGetWindowFromObj(interp, tkwin, objv[2], &master) != TCL_OK) {
    if (TkGetWindowFromObj(interp, tkwin, objv[2], &container) != TCL_OK) {
	return TCL_ERROR;
    }
    masterPtr = GetGrid(master);
    containerPtr = GetGrid(container);

    res = Tcl_NewListObj(0, NULL);
    for (slavePtr = masterPtr->slavePtr; slavePtr != NULL;
	    slavePtr = slavePtr->nextPtr) {
	if ((column >= 0) && (slavePtr->column > column
		|| slavePtr->column+slavePtr->numCols-1 < column)) {
    for (contentPtr = containerPtr->contentPtr; contentPtr != NULL;
	    contentPtr = contentPtr->nextPtr) {
	if ((column >= 0) && (contentPtr->column > column
		|| contentPtr->column+contentPtr->numCols-1 < column)) {
	    continue;
	}
	if ((row >= 0) && (slavePtr->row > row ||
		slavePtr->row+slavePtr->numRows-1 < row)) {
	if ((row >= 0) && (contentPtr->row > row ||
		contentPtr->row+contentPtr->numRows-1 < row)) {
	    continue;
	}
	Tcl_ListObjAppendElement(interp,res, TkNewWindowObj(slavePtr->tkwin));
	Tcl_ListObjAppendElement(interp,res, Tk_NewWindowObj(contentPtr->tkwin));
    }
    Tcl_SetObjResult(interp, res);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
1424
1425
1426
1427
1428
1429
1430
1431

1432
1433
1434

1435
1436

1437
1438
1439
1440
1441
1442
1443
1444
1445
1446

1447
1448
1449

1450
1451
1452
1453
1454
1455

1456
1457
1458
1459
1460
1461
1462


1463
1464

1465
1466

1467
1468
1469


1470
1471
1472


1473
1474
1475
1476
1477
1478
1479
1438
1439
1440
1441
1442
1443
1444

1445
1446
1447

1448
1449

1450
1451
1452
1453
1454
1455
1456
1457
1458
1459

1460
1461
1462

1463
1464
1465
1466
1467
1468

1469
1470
1471
1472
1473
1474


1475
1476
1477

1478
1479

1480
1481


1482
1483
1484


1485
1486
1487
1488
1489
1490
1491
1492
1493







-
+


-
+

-
+









-
+


-
+





-
+





-
-
+
+

-
+

-
+

-
-
+
+

-
-
+
+







 *----------------------------------------------------------------------
 */

static void
GridReqProc(
    ClientData clientData,	/* Grid's information about window that got
				 * new preferred geometry. */
    Tk_Window tkwin)		/* Other Tk-related information about the
    TCL_UNUSED(Tk_Window))		/* Other Tk-related information about the
				 * window. */
{
    register Gridder *gridPtr = clientData;
    Gridder *gridPtr = (Gridder *)clientData;

    gridPtr = gridPtr->masterPtr;
    gridPtr = gridPtr->containerPtr;
    if (gridPtr && !(gridPtr->flags & REQUESTED_RELAYOUT)) {
	gridPtr->flags |= REQUESTED_RELAYOUT;
	Tcl_DoWhenIdle(ArrangeGrid, gridPtr);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * GridLostSlaveProc --
 * GridLostContentProc --
 *
 *	This procedure is invoked by Tk whenever some other geometry claims
 *	control over a slave that used to be managed by us.
 *	control over a content that used to be managed by us.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Forgets all grid-related information about the slave.
 *	Forgets all grid-related information about the content.
 *
 *----------------------------------------------------------------------
 */

static void
GridLostSlaveProc(
    ClientData clientData,	/* Grid structure for slave window that was
GridLostContentProc(
    ClientData clientData,	/* Grid structure for content window that was
				 * stolen away. */
    Tk_Window tkwin)		/* Tk's handle for the slave window. */
    TCL_UNUSED(Tk_Window))		/* Tk's handle for the content window. */
{
    register Gridder *slavePtr = clientData;
    Gridder *contentPtr = (Gridder *)clientData;

    if (slavePtr->masterPtr->tkwin != Tk_Parent(slavePtr->tkwin)) {
	Tk_UnmaintainGeometry(slavePtr->tkwin, slavePtr->masterPtr->tkwin);
    if (contentPtr->containerPtr->tkwin != Tk_Parent(contentPtr->tkwin)) {
	Tk_UnmaintainGeometry(contentPtr->tkwin, contentPtr->containerPtr->tkwin);
    }
    Unlink(slavePtr);
    Tk_UnmapWindow(slavePtr->tkwin);
    Unlink(contentPtr);
    Tk_UnmapWindow(contentPtr->tkwin);
}

/*
 *----------------------------------------------------------------------
 *
 * AdjustOffsets --
 *
1492
1493
1494
1495
1496
1497
1498
1499

1500
1501

1502
1503
1504
1505
1506
1507
1508
1506
1507
1508
1509
1510
1511
1512

1513
1514

1515
1516
1517
1518
1519
1520
1521
1522







-
+

-
+







 *----------------------------------------------------------------------
 */

static int
AdjustOffsets(
    int size,			/* The total layout size (in pixels). */
    int slots,			/* Number of slots. */
    register SlotInfo *slotPtr)	/* Pointer to slot array. */
    SlotInfo *slotPtr)	/* Pointer to slot array. */
{
    register int slot;		/* Current slot. */
    int slot;		/* Current slot. */
    int diff;			/* Extra pixels needed to add to the layout. */
    int totalWeight;		/* Sum of the weights for all the slots. */
    int weight;			/* Sum of the weights so far. */
    int minSize;		/* Minimum possible layout size. */
    int newDiff;		/* The most pixels that can be added on the
    				 * current pass. */

1639
1640
1641
1642
1643
1644
1645
1646

1647
1648
1649
1650
1651

1652
1653
1654
1655
1656
1657
1658
1659
1660
1661

1662
1663
1664
1665
1666
1667
1668
1669



1670
1671
1672
1673
1674




1675
1676
1677
1678



1679
1680
1681
1682
1683



1684
1685
1686
1687
1688
1689
1690
1653
1654
1655
1656
1657
1658
1659

1660
1661
1662
1663
1664

1665
1666
1667
1668
1669
1670
1671
1672
1673
1674

1675
1676
1677
1678
1679
1680



1681
1682
1683
1684




1685
1686
1687
1688
1689



1690
1691
1692
1693
1694



1695
1696
1697
1698
1699
1700
1701
1702
1703
1704







-
+




-
+









-
+





-
-
-
+
+
+

-
-
-
-
+
+
+
+

-
-
-
+
+
+


-
-
-
+
+
+







}

/*
 *----------------------------------------------------------------------
 *
 * AdjustForSticky --
 *
 *	This procedure adjusts the size of a slave in its cavity based on its
 *	This procedure adjusts the size of a content in its cavity based on its
 *	"sticky" flags.
 *
 * Results:
 *	The input x, y, width, and height are changed to represent the desired
 *	coordinates of the slave.
 *	coordinates of the content.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
AdjustForSticky(
    Gridder *slavePtr,	/* Slave window to arrange in its cavity. */
    Gridder *contentPtr,	/* Content window to arrange in its cavity. */
    int *xPtr,		/* Pixel location of the left edge of the cavity. */
    int *yPtr,		/* Pixel location of the top edge of the cavity. */
    int *widthPtr,	/* Width of the cavity (in pixels). */
    int *heightPtr)	/* Height of the cavity (in pixels). */
{
    int diffx = 0;	/* Cavity width - slave width. */
    int diffy = 0;	/* Cavity hight - slave height. */
    int sticky = slavePtr->sticky;
    int diffx = 0;	/* Cavity width - content width. */
    int diffy = 0;	/* Cavity hight - content height. */
    int sticky = contentPtr->sticky;

    *xPtr += slavePtr->padLeft;
    *widthPtr -= slavePtr->padX;
    *yPtr += slavePtr->padTop;
    *heightPtr -= slavePtr->padY;
    *xPtr += contentPtr->padLeft;
    *widthPtr -= contentPtr->padX;
    *yPtr += contentPtr->padTop;
    *heightPtr -= contentPtr->padY;

    if (*widthPtr > (Tk_ReqWidth(slavePtr->tkwin) + slavePtr->iPadX)) {
	diffx = *widthPtr - (Tk_ReqWidth(slavePtr->tkwin) + slavePtr->iPadX);
	*widthPtr = Tk_ReqWidth(slavePtr->tkwin) + slavePtr->iPadX;
    if (*widthPtr > (Tk_ReqWidth(contentPtr->tkwin) + contentPtr->iPadX)) {
	diffx = *widthPtr - (Tk_ReqWidth(contentPtr->tkwin) + contentPtr->iPadX);
	*widthPtr = Tk_ReqWidth(contentPtr->tkwin) + contentPtr->iPadX;
    }

    if (*heightPtr > (Tk_ReqHeight(slavePtr->tkwin) + slavePtr->iPadY)) {
	diffy = *heightPtr - (Tk_ReqHeight(slavePtr->tkwin) + slavePtr->iPadY);
	*heightPtr = Tk_ReqHeight(slavePtr->tkwin) + slavePtr->iPadY;
    if (*heightPtr > (Tk_ReqHeight(contentPtr->tkwin) + contentPtr->iPadY)) {
	diffy = *heightPtr - (Tk_ReqHeight(contentPtr->tkwin) + contentPtr->iPadY);
	*heightPtr = Tk_ReqHeight(contentPtr->tkwin) + contentPtr->iPadY;
    }

    if (sticky&STICK_EAST && sticky&STICK_WEST) {
	*widthPtr += diffx;
    }
    if (sticky&STICK_NORTH && sticky&STICK_SOUTH) {
	*heightPtr += diffy;
1707
1708
1709
1710
1711
1712
1713
1714

1715
1716
1717
1718
1719
1720
1721

1722
1723
1724
1725
1726



1727
1728
1729
1730
1731
1732

1733
1734
1735
1736
1737



1738
1739
1740
1741

1742
1743
1744
1745

1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756


1757
1758

1759
1760

1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772







1773
1774
1775


1776
1777
1778


1779
1780
1781
1782
1783
1784




1785
1786
1787


1788
1789
1790


1791
1792
1793
1794
1795

1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806






1807
1808
1809
1810
1811

1812
1813
1814
1815

1816
1817
1818
1819
1820


1821
1822
1823
1824


1825
1826
1827
1828
1829
1830


1831
1832
1833
1834
1835

1836
1837
1838
1839

1840
1841
1842
1843

1844
1845

1846
1847
1848
1849
1850
1851





1852
1853
1854
1855
1856
1857
1858
1859


1860
1861
1862
1863


1864
1865
1866
1867
1868


1869
1870

1871
1872
1873
1874
1875
1876


1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894

1895
1896
1897
1898
1899
1900
1901

1902
1903
1904
1905
1906
1907


1908
1909
1910
1911
1912
1913
1914
1915
1916

1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933

1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946



1947
1948
1949
1950



1951
1952
1953
1954
1955
1956
1957
1958
1959

1960
1961
1962
1963
1964
1965
1966
1721
1722
1723
1724
1725
1726
1727

1728
1729
1730
1731
1732
1733
1734

1735
1736
1737



1738
1739
1740
1741
1742
1743
1744
1745

1746
1747
1748



1749
1750
1751

1752
1753

1754
1755
1756
1757

1758
1759
1760
1761
1762
1763
1764
1765
1766
1767


1768
1769
1770

1771
1772

1773
1774
1775
1776
1777
1778







1779
1780
1781
1782
1783
1784
1785
1786


1787
1788
1789


1790
1791
1792
1793




1794
1795
1796
1797
1798


1799
1800
1801


1802
1803
1804
1805
1806
1807

1808
1809
1810
1811
1812
1813






1814
1815
1816
1817
1818
1819
1820
1821
1822
1823

1824
1825
1826
1827

1828
1829
1830
1831


1832
1833
1834



1835
1836
1837
1838
1839
1840


1841
1842
1843
1844
1845
1846

1847
1848
1849
1850

1851
1852
1853
1854

1855
1856

1857
1858





1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869


1870
1871
1872
1873


1874
1875
1876
1877
1878


1879
1880
1881

1882
1883
1884
1885
1886


1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905

1906
1907
1908
1909
1910
1911
1912

1913
1914
1915
1916
1917


1918
1919
1920
1921
1922
1923
1924
1925
1926
1927

1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944

1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955



1956
1957
1958
1959



1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970

1971
1972
1973
1974
1975
1976
1977
1978







-
+






-
+


-
-
-
+
+
+





-
+


-
-
-
+
+
+
-


-
+



-
+









-
-
+
+

-
+

-
+





-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
+
+

-
-
+
+


-
-
-
-
+
+
+
+

-
-
+
+

-
-
+
+




-
+





-
-
-
-
-
-
+
+
+
+
+
+




-
+



-
+



-
-
+
+

-
-
-
+
+




-
-
+
+




-
+



-
+



-
+

-
+

-
-
-
-
-
+
+
+
+
+






-
-
+
+


-
-
+
+



-
-
+
+

-
+




-
-
+
+

















-
+






-
+




-
-
+
+








-
+
















-
+










-
-
-
+
+
+

-
-
-
+
+
+








-
+







 *	time so that a series of grid requests can be merged into a single
 *	layout operation.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The slaves of masterPtr may get resized or moved.
 *	The content of containerPtr may get resized or moved.
 *
 *----------------------------------------------------------------------
 */

static void
ArrangeGrid(
    ClientData clientData)	/* Structure describing master whose slaves
    ClientData clientData)	/* Structure describing container whose content
				 * are to be re-layed out. */
{
    register Gridder *masterPtr = clientData;
    register Gridder *slavePtr;
    GridMaster *slotPtr = masterPtr->masterDataPtr;
    Gridder *containerPtr = (Gridder *)clientData;
    Gridder *contentPtr;
    GridContainer *slotPtr = containerPtr->containerDataPtr;
    int abort;
    int width, height;		/* Requested size of layout, in pixels. */
    int realWidth, realHeight;	/* Actual size layout should take-up. */
    int usedX, usedY;

    masterPtr->flags &= ~REQUESTED_RELAYOUT;
    containerPtr->flags &= ~REQUESTED_RELAYOUT;

    /*
     * If the master has no slaves anymore, then don't do anything at all:
     * just leave the master's size as-is. Otherwise there is no way to
     * "relinquish" control over the master so another geometry manager can
     * If the container has no content anymore, then don't change the container size.
     * Otherwise there is no way to "relinquish" control over the container
     * so another geometry manager can take over.
     * take over.
     */

    if (masterPtr->slavePtr == NULL) {
    if (containerPtr->contentPtr == NULL) {
	return;
    }

    if (masterPtr->masterDataPtr == NULL) {
    if (containerPtr->containerDataPtr == NULL) {
	return;
    }

    /*
     * Abort any nested call to ArrangeGrid for this window, since we'll do
     * everything necessary here, and set up so this call can be aborted if
     * necessary.
     */

    if (masterPtr->abortPtr != NULL) {
	*masterPtr->abortPtr = 1;
    if (containerPtr->abortPtr != NULL) {
	*containerPtr->abortPtr = 1;
    }
    masterPtr->abortPtr = &abort;
    containerPtr->abortPtr = &abort;
    abort = 0;
    Tcl_Preserve(masterPtr);
    Tcl_Preserve(containerPtr);

    /*
     * Call the constraint engine to fill in the row and column offsets.
     */

    SetGridSize(masterPtr);
    width = ResolveConstraints(masterPtr, COLUMN, 0);
    height = ResolveConstraints(masterPtr, ROW, 0);
    width += Tk_InternalBorderLeft(masterPtr->tkwin) +
	    Tk_InternalBorderRight(masterPtr->tkwin);
    height += Tk_InternalBorderTop(masterPtr->tkwin) +
	    Tk_InternalBorderBottom(masterPtr->tkwin);
    SetGridSize(containerPtr);
    width = ResolveConstraints(containerPtr, COLUMN, 0);
    height = ResolveConstraints(containerPtr, ROW, 0);
    width += Tk_InternalBorderLeft(containerPtr->tkwin) +
	    Tk_InternalBorderRight(containerPtr->tkwin);
    height += Tk_InternalBorderTop(containerPtr->tkwin) +
	    Tk_InternalBorderBottom(containerPtr->tkwin);

    if (width < Tk_MinReqWidth(masterPtr->tkwin)) {
	width = Tk_MinReqWidth(masterPtr->tkwin);
    if (width < Tk_MinReqWidth(containerPtr->tkwin)) {
	width = Tk_MinReqWidth(containerPtr->tkwin);
    }
    if (height < Tk_MinReqHeight(masterPtr->tkwin)) {
	height = Tk_MinReqHeight(masterPtr->tkwin);
    if (height < Tk_MinReqHeight(containerPtr->tkwin)) {
	height = Tk_MinReqHeight(containerPtr->tkwin);
    }

    if (((width != Tk_ReqWidth(masterPtr->tkwin))
	    || (height != Tk_ReqHeight(masterPtr->tkwin)))
	    && !(masterPtr->flags & DONT_PROPAGATE)) {
	Tk_GeometryRequest(masterPtr->tkwin, width, height);
    if (((width != Tk_ReqWidth(containerPtr->tkwin))
	    || (height != Tk_ReqHeight(containerPtr->tkwin)))
	    && !(containerPtr->flags & DONT_PROPAGATE)) {
	Tk_GeometryRequest(containerPtr->tkwin, width, height);
	if (width>1 && height>1) {
	    masterPtr->flags |= REQUESTED_RELAYOUT;
	    Tcl_DoWhenIdle(ArrangeGrid, masterPtr);
	    containerPtr->flags |= REQUESTED_RELAYOUT;
	    Tcl_DoWhenIdle(ArrangeGrid, containerPtr);
	}
	masterPtr->abortPtr = NULL;
	Tcl_Release(masterPtr);
	containerPtr->abortPtr = NULL;
	Tcl_Release(containerPtr);
	return;
    }

    /*
     * If the currently requested layout size doesn't match the master's
     * If the currently requested layout size doesn't match the container's
     * window size, then adjust the slot offsets according to the weights. If
     * all of the weights are zero, place the layout according to the anchor
     * value.
     */

    realWidth = Tk_Width(masterPtr->tkwin) -
	    Tk_InternalBorderLeft(masterPtr->tkwin) -
	    Tk_InternalBorderRight(masterPtr->tkwin);
    realHeight = Tk_Height(masterPtr->tkwin) -
	    Tk_InternalBorderTop(masterPtr->tkwin) -
	    Tk_InternalBorderBottom(masterPtr->tkwin);
    realWidth = Tk_Width(containerPtr->tkwin) -
	    Tk_InternalBorderLeft(containerPtr->tkwin) -
	    Tk_InternalBorderRight(containerPtr->tkwin);
    realHeight = Tk_Height(containerPtr->tkwin) -
	    Tk_InternalBorderTop(containerPtr->tkwin) -
	    Tk_InternalBorderBottom(containerPtr->tkwin);
    usedX = AdjustOffsets(realWidth,
	    MAX(slotPtr->columnEnd, slotPtr->columnMax), slotPtr->columnPtr);
    usedY = AdjustOffsets(realHeight, MAX(slotPtr->rowEnd, slotPtr->rowMax),
	    slotPtr->rowPtr);
    TkComputeAnchor(masterPtr->masterDataPtr->anchor, masterPtr->tkwin,
    TkComputeAnchor(containerPtr->containerDataPtr->anchor, containerPtr->tkwin,
	    0, 0, usedX, usedY, &slotPtr->startX, &slotPtr->startY);

    /*
     * Now adjust the actual size of the slave to its cavity by computing the
     * Now adjust the actual size of the content to its cavity by computing the
     * cavity size, and adjusting the widget according to its stickyness.
     */

    for (slavePtr = masterPtr->slavePtr; slavePtr != NULL && !abort;
	    slavePtr = slavePtr->nextPtr) {
    for (contentPtr = containerPtr->contentPtr; contentPtr != NULL && !abort;
	    contentPtr = contentPtr->nextPtr) {
	int x, y;			/* Top left coordinate */
	int width, height;		/* Slot or slave size */
	int col = slavePtr->column;
	int row = slavePtr->row;
	int col = contentPtr->column;
	int row = contentPtr->row;

	x = (col>0) ? slotPtr->columnPtr[col-1].offset : 0;
	y = (row>0) ? slotPtr->rowPtr[row-1].offset : 0;

	width = slotPtr->columnPtr[slavePtr->numCols+col-1].offset - x;
	height = slotPtr->rowPtr[slavePtr->numRows+row-1].offset - y;
	width = slotPtr->columnPtr[contentPtr->numCols+col-1].offset - x;
	height = slotPtr->rowPtr[contentPtr->numRows+row-1].offset - y;

	x += slotPtr->startX;
	y += slotPtr->startY;

	AdjustForSticky(slavePtr, &x, &y, &width, &height);
	AdjustForSticky(contentPtr, &x, &y, &width, &height);

	/*
	 * Now put the window in the proper spot. (This was taken directly
	 * from tkPack.c.) If the slave is a child of the master, then do this
	 * from tkPack.c.) If the content is a child of the container, then do this
	 * here. Otherwise let Tk_MaintainGeometry do the work.
	 */

	if (masterPtr->tkwin == Tk_Parent(slavePtr->tkwin)) {
	if (containerPtr->tkwin == Tk_Parent(contentPtr->tkwin)) {
	    if ((width <= 0) || (height <= 0)) {
		Tk_UnmapWindow(slavePtr->tkwin);
		Tk_UnmapWindow(contentPtr->tkwin);
	    } else {
		if ((x != Tk_X(slavePtr->tkwin))
			|| (y != Tk_Y(slavePtr->tkwin))
			|| (width != Tk_Width(slavePtr->tkwin))
			|| (height != Tk_Height(slavePtr->tkwin))) {
		    Tk_MoveResizeWindow(slavePtr->tkwin, x, y, width, height);
		if ((x != Tk_X(contentPtr->tkwin))
			|| (y != Tk_Y(contentPtr->tkwin))
			|| (width != Tk_Width(contentPtr->tkwin))
			|| (height != Tk_Height(contentPtr->tkwin))) {
		    Tk_MoveResizeWindow(contentPtr->tkwin, x, y, width, height);
		}
		if (abort) {
		    break;
		}

		/*
		 * Don't map the slave if the master isn't mapped: wait until
		 * the master gets mapped later.
		 * Don't map the content if the container isn't mapped: wait until
		 * the container gets mapped later.
		 */

		if (Tk_IsMapped(masterPtr->tkwin)) {
		    Tk_MapWindow(slavePtr->tkwin);
		if (Tk_IsMapped(containerPtr->tkwin)) {
		    Tk_MapWindow(contentPtr->tkwin);
		}
	    }
	} else if ((width <= 0) || (height <= 0)) {
	    Tk_UnmaintainGeometry(slavePtr->tkwin, masterPtr->tkwin);
	    Tk_UnmapWindow(slavePtr->tkwin);
	    Tk_UnmaintainGeometry(contentPtr->tkwin, containerPtr->tkwin);
	    Tk_UnmapWindow(contentPtr->tkwin);
	} else {
	    Tk_MaintainGeometry(slavePtr->tkwin, masterPtr->tkwin, x, y,
	    Tk_MaintainGeometry(contentPtr->tkwin, containerPtr->tkwin, x, y,
		    width, height);
	}
    }

    masterPtr->abortPtr = NULL;
    Tcl_Release(masterPtr);
    containerPtr->abortPtr = NULL;
    Tcl_Release(containerPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * ResolveConstraints --
 *
 *	Resolve all of the column and row boundaries. Most of the calculations
 *	are identical for rows and columns, so this procedure is called twice,
 *	once for rows, and again for columns.
 *
 * Results:
 *	The offset (in pixels) from the left/top edge of this layout is
 *	returned.
 *
 * Side effects:
 *	The slot offsets are copied into the SlotInfo structure for the
 *	geometry master.
 *	geometry container.
 *
 *----------------------------------------------------------------------
 */

static int
ResolveConstraints(
    Gridder *masterPtr,		/* The geometry master for this grid. */
    Gridder *containerPtr,		/* The geometry container for this grid. */
    int slotType,		/* Either ROW or COLUMN. */
    int maxOffset)		/* The actual maximum size of this layout in
				 * pixels, or 0 (not currently used). */
{
    register SlotInfo *slotPtr;	/* Pointer to row/col constraints. */
    register Gridder *slavePtr;	/* List of slave windows in this grid. */
    SlotInfo *slotPtr;	/* Pointer to row/col constraints. */
    Gridder *contentPtr;	/* List of content windows in this grid. */
    int constraintCount;	/* Count of rows or columns that have
				 * constraints. */
    int slotCount;		/* Last occupied row or column. */
    int gridCount;		/* The larger of slotCount and
				 * constraintCount. */
    GridLayout *layoutPtr;	/* Temporary layout structure. */
    int requiredSize;		/* The natural size of the grid (pixels).
				 * This is the minimum size needed to
				 * accommodate all of the slaves at their
				 * accommodate all of the content at their
				 * requested sizes. */
    int offset;			/* The pixel offset of the right edge of the
				 * current slot from the beginning of the
				 * layout. */
    int slot;			/* The current slot. */
    int start;			/* The first slot of a contiguous set whose
				 * constraints are not yet fully resolved. */
    int end;			/* The Last slot of a contiguous set whose
				 * constraints are not yet fully resolved. */
    UniformGroup uniformPre[UNIFORM_PREALLOC];
				/* Pre-allocated space for uniform groups. */
    UniformGroup *uniformGroupPtr;
				/* Uniform groups data. */
    int uniformGroups;		/* Number of currently used uniform groups. */
    int uniformGroupsAlloced;	/* Size of allocated space for uniform
				 * groups. */
    int weight, minSize;
    int minSize;
    int prevGrow, accWeight, grow;

    /*
     * For typical sized tables, we'll use stack space for the layout data to
     * avoid the overhead of a malloc and free for every layout.
     */

    GridLayout layoutData[TYPICAL_SIZE + 1];

    if (slotType == COLUMN) {
	constraintCount = masterPtr->masterDataPtr->columnMax;
	slotCount = masterPtr->masterDataPtr->columnEnd;
	slotPtr = masterPtr->masterDataPtr->columnPtr;
	constraintCount = containerPtr->containerDataPtr->columnMax;
	slotCount = containerPtr->containerDataPtr->columnEnd;
	slotPtr = containerPtr->containerDataPtr->columnPtr;
    } else {
	constraintCount = masterPtr->masterDataPtr->rowMax;
	slotCount = masterPtr->masterDataPtr->rowEnd;
	slotPtr = masterPtr->masterDataPtr->rowPtr;
	constraintCount = containerPtr->containerDataPtr->rowMax;
	slotCount = containerPtr->containerDataPtr->rowEnd;
	slotPtr = containerPtr->containerDataPtr->rowPtr;
    }

    /*
     * Make sure there is enough memory for the layout.
     */

    gridCount = MAX(constraintCount, slotCount);
    if (gridCount >= TYPICAL_SIZE) {
	layoutPtr = ckalloc(sizeof(GridLayout) * (1+gridCount));
	layoutPtr = (GridLayout *)ckalloc(sizeof(GridLayout) * (1+gridCount));
    } else {
	layoutPtr = layoutData;
    }

    /*
     * Allocate an extra layout slot to represent the left/top edge of the 0th
     * slot to make it easier to calculate slot widths from offsets without
1993
1994
1995
1996
1997
1998
1999
2000
2001


2002
2003
2004
2005

2006
2007

2008
2009
2010
2011
2012
2013
2014



2015
2016
2017
2018
2019
2020





2021
2022

2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033



2034
2035
2036
2037
2038
2039





2040
2041

2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061

2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081

2082
2083
2084
2085
2086
2087
2088
2005
2006
2007
2008
2009
2010
2011


2012
2013
2014
2015
2016

2017
2018

2019
2020
2021
2022
2023



2024
2025
2026
2027





2028
2029
2030
2031
2032
2033

2034
2035
2036
2037
2038
2039
2040
2041
2042



2043
2044
2045
2046





2047
2048
2049
2050
2051
2052

2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093

2094
2095
2096
2097
2098
2099
2100
2101







-
-
+
+



-
+

-
+




-
-
-
+
+
+

-
-
-
-
-
+
+
+
+
+

-
+








-
-
-
+
+
+

-
-
-
-
-
+
+
+
+
+

-
+




















+



















-
+







	layoutPtr[slot].uniform = NULL;
	layoutPtr[slot].pad = 0;
	layoutPtr[slot].binNextPtr = NULL;
    }

    /*
     * Step 2.
     * Slaves with a span of 1 are used to determine the minimum size of each
     * slot. Slaves whose span is two or more slots don't contribute to the
     * Content with a span of 1 are used to determine the minimum size of each
     * slot. Content whose span is two or more slots don't contribute to the
     * minimum size of each slot directly, but can cause slots to grow if
     * their size exceeds the the sizes of the slots they span.
     *
     * Bin all slaves whose spans are > 1 by their right edges. This allows
     * Bin all content whose spans are > 1 by their right edges. This allows
     * the computation on minimum and maximum possible layout sizes at each
     * slot boundary, without the need to re-sort the slaves.
     * slot boundary, without the need to re-sort the content.
     */

    switch (slotType) {
    case COLUMN:
	for (slavePtr = masterPtr->slavePtr; slavePtr != NULL;
		slavePtr = slavePtr->nextPtr) {
	    int rightEdge = slavePtr->column + slavePtr->numCols - 1;
	for (contentPtr = containerPtr->contentPtr; contentPtr != NULL;
		contentPtr = contentPtr->nextPtr) {
	    int rightEdge = contentPtr->column + contentPtr->numCols - 1;

	    slavePtr->size = Tk_ReqWidth(slavePtr->tkwin) + slavePtr->padX
		    + slavePtr->iPadX + slavePtr->doubleBw;
	    if (slavePtr->numCols > 1) {
		slavePtr->binNextPtr = layoutPtr[rightEdge].binNextPtr;
		layoutPtr[rightEdge].binNextPtr = slavePtr;
	    contentPtr->size = Tk_ReqWidth(contentPtr->tkwin) + contentPtr->padX
		    + contentPtr->iPadX + contentPtr->doubleBw;
	    if (contentPtr->numCols > 1) {
		contentPtr->binNextPtr = layoutPtr[rightEdge].binNextPtr;
		layoutPtr[rightEdge].binNextPtr = contentPtr;
	    } else if (rightEdge >= 0) {
		int size = slavePtr->size + layoutPtr[rightEdge].pad;
		int size = contentPtr->size + layoutPtr[rightEdge].pad;

		if (size > layoutPtr[rightEdge].minSize) {
		    layoutPtr[rightEdge].minSize = size;
		}
	    }
	}
	break;
    case ROW:
	for (slavePtr = masterPtr->slavePtr; slavePtr != NULL;
		slavePtr = slavePtr->nextPtr) {
	    int rightEdge = slavePtr->row + slavePtr->numRows - 1;
	for (contentPtr = containerPtr->contentPtr; contentPtr != NULL;
		contentPtr = contentPtr->nextPtr) {
	    int rightEdge = contentPtr->row + contentPtr->numRows - 1;

	    slavePtr->size = Tk_ReqHeight(slavePtr->tkwin) + slavePtr->padY
		    + slavePtr->iPadY + slavePtr->doubleBw;
	    if (slavePtr->numRows > 1) {
		slavePtr->binNextPtr = layoutPtr[rightEdge].binNextPtr;
		layoutPtr[rightEdge].binNextPtr = slavePtr;
	    contentPtr->size = Tk_ReqHeight(contentPtr->tkwin) + contentPtr->padY
		    + contentPtr->iPadY + contentPtr->doubleBw;
	    if (contentPtr->numRows > 1) {
		contentPtr->binNextPtr = layoutPtr[rightEdge].binNextPtr;
		layoutPtr[rightEdge].binNextPtr = contentPtr;
	    } else if (rightEdge >= 0) {
		int size = slavePtr->size + layoutPtr[rightEdge].pad;
		int size = contentPtr->size + layoutPtr[rightEdge].pad;

		if (size > layoutPtr[rightEdge].minSize) {
		    layoutPtr[rightEdge].minSize = size;
		}
	    }
	}
	break;
    }

    /*
     * Step 2b.
     * Consider demands on uniform sizes.
     */

    uniformGroupPtr = uniformPre;
    uniformGroupsAlloced = UNIFORM_PREALLOC;
    uniformGroups = 0;

    for (slot = 0; slot < gridCount; slot++) {
	if (layoutPtr[slot].uniform != NULL) {
		int weight;
	    for (start = 0; start < uniformGroups; start++) {
		if (uniformGroupPtr[start].group == layoutPtr[slot].uniform) {
		    break;
		}
	    }
	    if (start >= uniformGroups) {
		/*
		 * Have not seen that group before, set up data for it.
		 */

		if (uniformGroups >= uniformGroupsAlloced) {
		    /*
		     * We need to allocate more space.
		     */

		    size_t oldSize = uniformGroupsAlloced
			    * sizeof(UniformGroup);
		    size_t newSize = (uniformGroupsAlloced + UNIFORM_PREALLOC)
			    * sizeof(UniformGroup);
		    UniformGroup *newUG = ckalloc(newSize);
		    UniformGroup *newUG = (UniformGroup *)ckalloc(newSize);
		    UniformGroup *oldUG = uniformGroupPtr;

		    memcpy(newUG, oldUG, oldSize);
		    if (oldUG != uniformPre) {
			ckfree(oldUG);
		    }
		    uniformGroupPtr = newUG;
2107
2108
2109
2110
2111
2112
2113
2114

2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132

2133
2134
2135
2136
2137
2138


2139
2140
2141


2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152

2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174


2175
2176
2177


2178
2179
2180
2181
2182
2183
2184
2120
2121
2122
2123
2124
2125
2126

2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144

2145
2146
2147
2148
2149


2150
2151
2152


2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164

2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185


2186
2187
2188


2189
2190
2191
2192
2193
2194
2195
2196
2197







-
+

















-
+




-
-
+
+

-
-
+
+










-
+




















-
-
+
+

-
-
+
+








    if (uniformGroups > 0) {
	for (slot = 0; slot < gridCount; slot++) {
	    if (layoutPtr[slot].uniform != NULL) {
		for (start = 0; start < uniformGroups; start++) {
		    if (uniformGroupPtr[start].group ==
			    layoutPtr[slot].uniform) {
			weight = layoutPtr[slot].weight;
			int weight = layoutPtr[slot].weight;
			weight = weight > 0 ? weight : 1;
			layoutPtr[slot].minSize =
				uniformGroupPtr[start].minSize * weight;
			break;
		    }
		}
	    }
	}
    }

    if (uniformGroupPtr != uniformPre) {
	ckfree(uniformGroupPtr);
    }

    /*
     * Step 3.
     * Determine the minimum slot offsets going from left to right that would
     * fit all of the slaves. This determines the minimum
     * fit all of the content. This determines the minimum
     */

    for (offset=0,slot=0; slot < gridCount; slot++) {
	layoutPtr[slot].minOffset = layoutPtr[slot].minSize + offset;
	for (slavePtr = layoutPtr[slot].binNextPtr; slavePtr != NULL;
		slavePtr = slavePtr->binNextPtr) {
	for (contentPtr = layoutPtr[slot].binNextPtr; contentPtr != NULL;
		contentPtr = contentPtr->binNextPtr) {
	    int span = (slotType == COLUMN) ?
		    slavePtr->numCols : slavePtr->numRows;
	    int required = slavePtr->size + layoutPtr[slot - span].minOffset;
		    contentPtr->numCols : contentPtr->numRows;
	    int required = contentPtr->size + layoutPtr[slot - span].minOffset;

	    if (required > layoutPtr[slot].minOffset) {
		layoutPtr[slot].minOffset = required;
	    }
	}
	offset = layoutPtr[slot].minOffset;
    }

    /*
     * At this point, we know the minimum required size of the entire layout.
     * It might be prudent to stop here if our "master" will resize itself to
     * It might be prudent to stop here if our "container" will resize itself to
     * this size.
     */

    requiredSize = offset;
    if (maxOffset > offset) {
	offset=maxOffset;
    }

    /*
     * Step 4.
     * Determine the minimum slot offsets going from right to left, bounding
     * the pixel range of each slot boundary. Pre-fill all of the right
     * offsets with the actual size of the table; they will be reduced as
     * required.
     */

    for (slot=0; slot < gridCount; slot++) {
	layoutPtr[slot].maxOffset = offset;
    }
    for (slot=gridCount-1; slot > 0;) {
	for (slavePtr = layoutPtr[slot].binNextPtr; slavePtr != NULL;
		slavePtr = slavePtr->binNextPtr) {
	for (contentPtr = layoutPtr[slot].binNextPtr; contentPtr != NULL;
		contentPtr = contentPtr->binNextPtr) {
	    int span = (slotType == COLUMN) ?
		    slavePtr->numCols : slavePtr->numRows;
	    int require = offset - slavePtr->size;
		    contentPtr->numCols : contentPtr->numRows;
	    int require = offset - contentPtr->size;
	    int startSlot = slot - span;

	    if (startSlot >=0 && require < layoutPtr[startSlot].maxOffset) {
		layoutPtr[startSlot].maxOffset = require;
	    }
	}
	offset -= layoutPtr[slot].minSize;
2380
2381
2382
2383
2384
2385
2386
2387

2388
2389
2390
2391
2392
2393
2394
2393
2394
2395
2396
2397
2398
2399

2400
2401
2402
2403
2404
2405
2406
2407







-
+







	    }
	}
    }

    /*
     * Step 6.
     * All of the space has been apportioned; copy the layout information back
     * into the master.
     * into the container.
     */

    for (slot=0; slot < gridCount; slot++) {
	slotPtr[slot].offset = layoutPtr[slot].minOffset;
    }

    --layoutPtr;
2418
2419
2420
2421
2422
2423
2424
2425

2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442

2443
2444

2445
2446
2447


2448
2449

2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469

2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481

2482
2483
2484
2485
2486
2487

2488
2489
2490
2491
2492
2493
2494
2495
2496

2497
2498

2499
2500
2501
2502
2503
2504




2505
2506
2507
2508
2509




2510
2511
2512
2513
2514
2515

2516
2517

2518
2519
2520
2521
2522
2523
2524

2525
2526
2527
2528
2529
2530

2531
2532

2533
2534
2535
2536
2537
2538
2539


2540
2541
2542
2543
2544
2545
2546
2547
2548
2549


2550
2551
2552
2553
2554
2555
2556

2557
2558

2559
2560
2561
2562
2563
2564
2565

2566
2567
2568
2569
2570
2571

2572
2573

2574
2575
2576
2577
2578
2579
2580


2581
2582
2583
2584
2585
2586
2587
2588
2589
2590


2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606

2607
2608
2609
2610
2611
2612
2613
2614
2615
2616

2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632

2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644



2645
2646
2647
2648
2649


2650
2651
2652
2653
2654

2655
2656
2657


2658
2659
2660
2661
2662
2663
2664


2665
2666
2667


2668
2669
2670
2671
2672

2673
2674

2675
2676
2677
2678
2679
2680
2681
2682
2683
2684

2685
2686
2687

2688
2689
2690
2691
2692
2693

2694
2695
2696
2697
2698
2699
2700
2701


2702
2703
2704
2705



2706
2707
2708
2709
2710

2711
2712
2713
2714

2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730

2731
2732
2733
2734
2735
2736

2737
2738
2739
2740
2741
2742
2743
2744

2745
2746

2747
2748
2749


2750
2751
2752
2753
2754


2755
2756
2757


2758
2759
2760
2761


2762
2763
2764
2765
2766
2767
2768



2769
2770
2771


2772
2773
2774
2775


2776
2777
2778

2779



2780
2781
2782
2783
2784




2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796

2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812

2813
2814
2815
2816



2817
2818
2819


2820
2821

2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842

2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853

2854
2855
2856
2857

2858
2859
2860
2861
2862

2863
2864

2865
2866
2867


2868
2869
2870
2871

2872
2873

2874
2875
2876
2877
2878
2879
2880
2881
2882







2883
2884
2885

2886
2887
2888
2889
2890
2891
2892

2893
2894
2895
2896
2897
2898

2899
2900
2901
2902



2903
2904
2905
2906
2907
2908
2909
2910

2911
2912
2913
2914


2915
2916
2917
2918
2919
2920
2921
2922

2923
2924
2925
2926
2927
2928

2929
2930
2931

2932
2933
2934
2935
2936
2937
2938
2939
2940
2941




2942
2943
2944
2945
2946
2947
2948
2431
2432
2433
2434
2435
2436
2437

2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454

2455
2456

2457
2458


2459
2460
2461

2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481

2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493

2494
2495
2496
2497
2498
2499

2500
2501
2502
2503
2504
2505
2506
2507
2508

2509
2510

2511
2512
2513




2514
2515
2516
2517
2518




2519
2520
2521
2522
2523
2524
2525
2526
2527

2528
2529

2530
2531
2532
2533
2534
2535
2536

2537
2538
2539
2540
2541
2542

2543
2544

2545
2546
2547
2548
2549
2550


2551
2552
2553
2554
2555
2556
2557
2558
2559
2560


2561
2562
2563
2564
2565
2566
2567
2568

2569
2570

2571
2572
2573
2574
2575
2576
2577

2578
2579
2580
2581
2582
2583

2584
2585

2586
2587
2588
2589
2590
2591


2592
2593
2594
2595
2596
2597
2598
2599
2600
2601


2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618

2619
2620
2621
2622
2623
2624
2625
2626
2627
2628

2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644

2645
2646
2647
2648
2649
2650
2651
2652
2653
2654



2655
2656
2657
2658
2659
2660


2661
2662
2663
2664
2665
2666

2667
2668


2669
2670
2671
2672
2673
2674
2675


2676
2677
2678


2679
2680
2681
2682
2683
2684

2685
2686

2687
2688
2689
2690
2691
2692
2693
2694
2695
2696

2697
2698
2699

2700
2701
2702
2703
2704
2705

2706
2707
2708
2709
2710
2711
2712


2713
2714
2715



2716
2717
2718
2719
2720
2721
2722

2723
2724
2725
2726

2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742

2743
2744
2745
2746
2747
2748

2749
2750
2751
2752
2753
2754
2755
2756

2757
2758

2759
2760


2761
2762
2763
2764
2765


2766
2767
2768


2769
2770
2771
2772


2773
2774
2775
2776
2777
2778



2779
2780
2781
2782


2783
2784
2785
2786


2787
2788
2789
2790

2791
2792
2793
2794
2795
2796
2797



2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812

2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828

2829
2830



2831
2832
2833
2834


2835
2836
2837

2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858

2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869

2870
2871
2872
2873

2874
2875
2876
2877
2878

2879
2880

2881
2882


2883
2884
2885
2886
2887

2888
2889

2890
2891
2892







2893
2894
2895
2896
2897
2898
2899
2900
2901

2902
2903
2904
2905
2906
2907
2908

2909
2910
2911
2912
2913
2914

2915
2916



2917
2918
2919
2920
2921
2922
2923
2924
2925
2926

2927
2928
2929


2930
2931
2932
2933
2934
2935
2936
2937
2938

2939
2940
2941
2942
2943
2944

2945
2946
2947

2948
2949
2950
2951
2952
2953
2954




2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965







-
+
















-
+

-
+

-
-
+
+

-
+



















-
+











-
+





-
+








-
+

-
+


-
-
-
-
+
+
+
+

-
-
-
-
+
+
+
+





-
+

-
+






-
+





-
+

-
+





-
-
+
+








-
-
+
+






-
+

-
+






-
+





-
+

-
+





-
-
+
+








-
-
+
+















-
+









-
+















-
+









-
-
-
+
+
+



-
-
+
+




-
+

-
-
+
+





-
-
+
+

-
-
+
+




-
+

-
+









-
+


-
+





-
+






-
-
+
+

-
-
-
+
+
+




-
+



-
+















-
+





-
+







-
+

-
+

-
-
+
+



-
-
+
+

-
-
+
+


-
-
+
+




-
-
-
+
+
+

-
-
+
+


-
-
+
+


-
+

+
+
+


-
-
-
+
+
+
+











-
+















-
+

-
-
-
+
+
+

-
-
+
+

-
+




















-
+










-
+



-
+




-
+

-
+

-
-
+
+



-
+

-
+


-
-
-
-
-
-
-
+
+
+
+
+
+
+


-
+






-
+





-
+

-
-
-
+
+
+







-
+


-
-
+
+







-
+





-
+


-
+






-
-
-
-
+
+
+
+







 */

static Gridder *
GetGrid(
    Tk_Window tkwin)		/* Token for window for which grid structure
				 * is desired. */
{
    register Gridder *gridPtr;
    Gridder *gridPtr;
    Tcl_HashEntry *hPtr;
    int isNew;
    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;

    if (!dispPtr->gridInit) {
	Tcl_InitHashTable(&dispPtr->gridHashTable, TCL_ONE_WORD_KEYS);
	dispPtr->gridInit = 1;
    }

    /*
     * See if there's already grid for this window. If not, then create a new
     * one.
     */

    hPtr = Tcl_CreateHashEntry(&dispPtr->gridHashTable, (char*) tkwin, &isNew);
    if (!isNew) {
	return Tcl_GetHashValue(hPtr);
	return (Gridder *)Tcl_GetHashValue(hPtr);
    }
    gridPtr = ckalloc(sizeof(Gridder));
    gridPtr = (Gridder *)ckalloc(sizeof(Gridder));
    gridPtr->tkwin = tkwin;
    gridPtr->masterPtr = NULL;
    gridPtr->masterDataPtr = NULL;
    gridPtr->containerPtr = NULL;
    gridPtr->containerDataPtr = NULL;
    gridPtr->nextPtr = NULL;
    gridPtr->slavePtr = NULL;
    gridPtr->contentPtr = NULL;
    gridPtr->binNextPtr = NULL;

    gridPtr->column = -1;
    gridPtr->row = -1;
    gridPtr->numCols = 1;
    gridPtr->numRows = 1;

    gridPtr->padX = 0;
    gridPtr->padY = 0;
    gridPtr->padLeft = 0;
    gridPtr->padTop = 0;
    gridPtr->iPadX = 0;
    gridPtr->iPadY = 0;
    gridPtr->doubleBw = 2 * Tk_Changes(tkwin)->border_width;
    gridPtr->abortPtr = NULL;
    gridPtr->flags = 0;
    gridPtr->sticky = 0;
    gridPtr->size = 0;
    gridPtr->in = NULL;
    gridPtr->masterDataPtr = NULL;
    gridPtr->containerDataPtr = NULL;
    Tcl_SetHashValue(hPtr, gridPtr);
    Tk_CreateEventHandler(tkwin, StructureNotifyMask,
	    GridStructureProc, gridPtr);
    return gridPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * SetGridSize --
 *
 *	This internal procedure sets the size of the grid occupied by slaves.
 *	This internal procedure sets the size of the grid occupied by content.
 *
 * Results:
 *	None
 *
 * Side effects:
 *	The width and height arguments are filled in the master data
 *	The width and height arguments are filled in the container data
 *	structure. Additional space is allocated for the constraints to
 *	accommodate the offsets.
 *
 *----------------------------------------------------------------------
 */

static void
SetGridSize(
    Gridder *masterPtr)		/* The geometry master for this grid. */
    Gridder *containerPtr)		/* The geometry container for this grid. */
{
    register Gridder *slavePtr;	/* Current slave window. */
    Gridder *contentPtr;	/* Current content window. */
    int maxX = 0, maxY = 0;

    for (slavePtr = masterPtr->slavePtr; slavePtr != NULL;
	    slavePtr = slavePtr->nextPtr) {
	maxX = MAX(maxX, slavePtr->numCols + slavePtr->column);
	maxY = MAX(maxY, slavePtr->numRows + slavePtr->row);
    for (contentPtr = containerPtr->contentPtr; contentPtr != NULL;
	    contentPtr = contentPtr->nextPtr) {
	maxX = MAX(maxX, contentPtr->numCols + contentPtr->column);
	maxY = MAX(maxY, contentPtr->numRows + contentPtr->row);
    }
    masterPtr->masterDataPtr->columnEnd = maxX;
    masterPtr->masterDataPtr->rowEnd = maxY;
    CheckSlotData(masterPtr, maxX, COLUMN, CHECK_SPACE);
    CheckSlotData(masterPtr, maxY, ROW, CHECK_SPACE);
    containerPtr->containerDataPtr->columnEnd = maxX;
    containerPtr->containerDataPtr->rowEnd = maxY;
    CheckSlotData(containerPtr, maxX, COLUMN, CHECK_SPACE);
    CheckSlotData(containerPtr, maxY, ROW, CHECK_SPACE);
}

/*
 *----------------------------------------------------------------------
 *
 * SetSlaveColumn --
 * SetContentColumn --
 *
 *	Update column data for a slave, checking that MAX_ELEMENT bound
 *	Update column data for a content, checking that MAX_ELEMENT bound
 *      is not passed.
 *
 * Results:
 *	TCL_ERROR if out of bounds, TCL_OK otherwise
 *
 * Side effects:
 *	Slave fields are updated.
 *	Content fields are updated.
 *
 *----------------------------------------------------------------------
 */

static int
SetSlaveColumn(
SetContentColumn(
    Tcl_Interp *interp,		/* Interp for error message. */
    Gridder *slavePtr,		/* Slave to be updated. */
    Gridder *contentPtr,		/* Content to be updated. */
    int column,			/* New column or -1 to be unchanged. */
    int numCols)		/* New columnspan or -1 to be unchanged. */
{
    int newColumn, newNumCols, lastCol;

    newColumn = (column >= 0) ? column : slavePtr->column;
    newNumCols = (numCols >= 1) ? numCols : slavePtr->numCols;
    newColumn = (column >= 0) ? column : contentPtr->column;
    newNumCols = (numCols >= 1) ? numCols : contentPtr->numCols;

    lastCol = ((newColumn >= 0) ? newColumn : 0) + newNumCols;
    if (lastCol >= MAX_ELEMENT) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("column out of bounds",-1));
	Tcl_SetErrorCode(interp, "TK", "GRID", "BAD_COLUMN", NULL);
	return TCL_ERROR;
    }

    slavePtr->column = newColumn;
    slavePtr->numCols = newNumCols;
    contentPtr->column = newColumn;
    contentPtr->numCols = newNumCols;
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * SetSlaveRow --
 * SetContentRow --
 *
 *	Update row data for a slave, checking that MAX_ELEMENT bound
 *	Update row data for a content, checking that MAX_ELEMENT bound
 *      is not passed.
 *
 * Results:
 *	TCL_ERROR if out of bounds, TCL_OK otherwise
 *
 * Side effects:
 *	Slave fields are updated.
 *	Content fields are updated.
 *
 *----------------------------------------------------------------------
 */

static int
SetSlaveRow(
SetContentRow(
    Tcl_Interp *interp,		/* Interp for error message. */
    Gridder *slavePtr,		/* Slave to be updated. */
    Gridder *contentPtr,		/* Content to be updated. */
    int row,			/* New row or -1 to be unchanged. */
    int numRows)		/* New rowspan or -1 to be unchanged. */
{
    int newRow, newNumRows, lastRow;

    newRow = (row >= 0) ? row : slavePtr->row;
    newNumRows = (numRows >= 1) ? numRows : slavePtr->numRows;
    newRow = (row >= 0) ? row : contentPtr->row;
    newNumRows = (numRows >= 1) ? numRows : contentPtr->numRows;

    lastRow = ((newRow >= 0) ? newRow : 0) + newNumRows;
    if (lastRow >= MAX_ELEMENT) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("row out of bounds", -1));
	Tcl_SetErrorCode(interp, "TK", "GRID", "BAD_ROW", NULL);
	return TCL_ERROR;
    }

    slavePtr->row = newRow;
    slavePtr->numRows = newNumRows;
    contentPtr->row = newRow;
    contentPtr->numRows = newNumRows;
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * CheckSlotData --
 *
 *	This internal procedure is used to manage the storage for row and
 *	column (slot) constraints.
 *
 * Results:
 *	TRUE if the index is OK, False otherwise.
 *
 * Side effects:
 *	A new master grid structure may be created. If so, then it is
 *	A new container grid structure may be created. If so, then it is
 *	initialized. In addition, additional storage for a row or column
 *	constraints may be allocated, and the constraint maximums are
 *	adjusted.
 *
 *----------------------------------------------------------------------
 */

static int
CheckSlotData(
    Gridder *masterPtr,		/* The geometry master for this grid. */
    Gridder *containerPtr,		/* The geometry container for this grid. */
    int slot,			/* Which slot to look at. */
    int slotType,		/* ROW or COLUMN. */
    int checkOnly)		/* Don't allocate new space if true. */
{
    int numSlot;		/* Number of slots already allocated (Space) */
    int end;			/* Last used constraint. */

    /*
     * If slot is out of bounds, return immediately.
     */

    if (slot < 0 || slot >= MAX_ELEMENT) {
	return TCL_ERROR;
    }

    if ((checkOnly == CHECK_ONLY) && (masterPtr->masterDataPtr == NULL)) {
    if ((checkOnly == CHECK_ONLY) && (containerPtr->containerDataPtr == NULL)) {
	return TCL_ERROR;
    }

    /*
     * If we need to allocate more space, allocate a little extra to avoid
     * repeated re-alloc's for large tables. We need enough space to hold all
     * of the offsets as well.
     */

    InitMasterData(masterPtr);
    end = (slotType == ROW) ? masterPtr->masterDataPtr->rowMax :
	    masterPtr->masterDataPtr->columnMax;
    InitContainerData(containerPtr);
    end = (slotType == ROW) ? containerPtr->containerDataPtr->rowMax :
	    containerPtr->containerDataPtr->columnMax;
    if (checkOnly == CHECK_ONLY) {
    	return ((end < slot) ? TCL_ERROR : TCL_OK);
    } else {
    	numSlot = (slotType == ROW) ? masterPtr->masterDataPtr->rowSpace
		: masterPtr->masterDataPtr->columnSpace;
    	numSlot = (slotType == ROW) ? containerPtr->containerDataPtr->rowSpace
		: containerPtr->containerDataPtr->columnSpace;
    	if (slot >= numSlot) {
	    int newNumSlot = slot + PREALLOC;
	    size_t oldSize = numSlot * sizeof(SlotInfo);
	    size_t newSize = newNumSlot * sizeof(SlotInfo);
	    SlotInfo *newSI = ckalloc(newSize);
	    SlotInfo *newSI = (SlotInfo *)ckalloc(newSize);
	    SlotInfo *oldSI = (slotType == ROW)
		    ? masterPtr->masterDataPtr->rowPtr
		    : masterPtr->masterDataPtr->columnPtr;
		    ? containerPtr->containerDataPtr->rowPtr
		    : containerPtr->containerDataPtr->columnPtr;

	    memcpy(newSI, oldSI, oldSize);
	    memset(newSI+numSlot, 0, newSize - oldSize);
	    ckfree(oldSI);
	    if (slotType == ROW) {
	 	masterPtr->masterDataPtr->rowPtr = newSI;
	    	masterPtr->masterDataPtr->rowSpace = newNumSlot;
	 	containerPtr->containerDataPtr->rowPtr = newSI;
	    	containerPtr->containerDataPtr->rowSpace = newNumSlot;
	    } else {
	    	masterPtr->masterDataPtr->columnPtr = newSI;
	    	masterPtr->masterDataPtr->columnSpace = newNumSlot;
	    	containerPtr->containerDataPtr->columnPtr = newSI;
	    	containerPtr->containerDataPtr->columnSpace = newNumSlot;
	    }
	}
	if (slot >= end && checkOnly != CHECK_SPACE) {
	    if (slotType == ROW) {
		masterPtr->masterDataPtr->rowMax = slot+1;
		containerPtr->containerDataPtr->rowMax = slot+1;
	    } else {
		masterPtr->masterDataPtr->columnMax = slot+1;
		containerPtr->containerDataPtr->columnMax = slot+1;
	    }
	}
    	return TCL_OK;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * InitMasterData --
 * InitContainerData --
 *
 *	This internal procedure is used to allocate and initialize the data
 *	for a geometry master, if the data doesn't exist already.
 *	for a geometry container, if the data doesn't exist already.
 *
 * Results:
 *	none
 *
 * Side effects:
 *	A new master grid structure may be created. If so, then it is
 *	A new container grid structure may be created. If so, then it is
 *	initialized.
 *
 *----------------------------------------------------------------------
 */

static void
InitMasterData(
    Gridder *masterPtr)
InitContainerData(
    Gridder *containerPtr)
{
    if (masterPtr->masterDataPtr == NULL) {
	GridMaster *gridPtr = masterPtr->masterDataPtr =
		ckalloc(sizeof(GridMaster));
    if (containerPtr->containerDataPtr == NULL) {
	GridContainer *gridPtr = containerPtr->containerDataPtr = (GridContainer *)
		ckalloc(sizeof(GridContainer));
	size_t size = sizeof(SlotInfo) * TYPICAL_SIZE;

	gridPtr->columnEnd = 0;
	gridPtr->columnMax = 0;
	gridPtr->columnPtr = ckalloc(size);
	gridPtr->columnPtr = (SlotInfo *)ckalloc(size);
	gridPtr->columnSpace = TYPICAL_SIZE;
	gridPtr->rowEnd = 0;
	gridPtr->rowMax = 0;
	gridPtr->rowPtr = ckalloc(size);
	gridPtr->rowPtr = (SlotInfo *)ckalloc(size);
	gridPtr->rowSpace = TYPICAL_SIZE;
	gridPtr->startX = 0;
	gridPtr->startY = 0;
	gridPtr->anchor = GRID_DEFAULT_ANCHOR;

	memset(gridPtr->columnPtr, 0, size);
	memset(gridPtr->rowPtr, 0, size);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Unlink --
 *
 *	Remove a grid from its master's list of slaves.
 *	Remove a grid from its container's list of content.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The master will be scheduled for re-arranging, and the size of the
 *	The container will be scheduled for re-arranging, and the size of the
 *	grid will be adjusted accordingly
 *
 *----------------------------------------------------------------------
 */

static void
Unlink(
    register Gridder *slavePtr)	/* Window to unlink. */
    Gridder *contentPtr)	/* Window to unlink. */
{
    register Gridder *masterPtr, *slavePtr2;
    Gridder *containerPtr, *contentPtr2;

    masterPtr = slavePtr->masterPtr;
    if (masterPtr == NULL) {
    containerPtr = contentPtr->containerPtr;
    if (containerPtr == NULL) {
	return;
    }

    if (masterPtr->slavePtr == slavePtr) {
	masterPtr->slavePtr = slavePtr->nextPtr;
    if (containerPtr->contentPtr == contentPtr) {
	containerPtr->contentPtr = contentPtr->nextPtr;
    } else {
	for (slavePtr2=masterPtr->slavePtr ; ; slavePtr2=slavePtr2->nextPtr) {
	    if (slavePtr2 == NULL) {
	for (contentPtr2=containerPtr->contentPtr ; ; contentPtr2=contentPtr2->nextPtr) {
	    if (contentPtr2 == NULL) {
		Tcl_Panic("Unlink couldn't find previous window");
	    }
	    if (slavePtr2->nextPtr == slavePtr) {
		slavePtr2->nextPtr = slavePtr->nextPtr;
	    if (contentPtr2->nextPtr == contentPtr) {
		contentPtr2->nextPtr = contentPtr->nextPtr;
		break;
	    }
	}
    }
    if (!(masterPtr->flags & REQUESTED_RELAYOUT)) {
	masterPtr->flags |= REQUESTED_RELAYOUT;
	Tcl_DoWhenIdle(ArrangeGrid, masterPtr);
    if (!(containerPtr->flags & REQUESTED_RELAYOUT)) {
	containerPtr->flags |= REQUESTED_RELAYOUT;
	Tcl_DoWhenIdle(ArrangeGrid, containerPtr);
    }
    if (masterPtr->abortPtr != NULL) {
	*masterPtr->abortPtr = 1;
    if (containerPtr->abortPtr != NULL) {
	*containerPtr->abortPtr = 1;
    }

    SetGridSize(slavePtr->masterPtr);
    slavePtr->masterPtr = NULL;
    SetGridSize(contentPtr->containerPtr);
    contentPtr->containerPtr = NULL;

    /*
     * If we have emptied this master from slaves it means we are no longer
     * If we have emptied this container from content it means we are no longer
     * handling it and should mark it as free.
     *
     * Send the event "NoManagedChild" to the container to inform it about there
     * being no managed children inside it.
     */

    if ((masterPtr->slavePtr == NULL) && (masterPtr->flags & ALLOCED_MASTER)) {
	TkFreeGeometryMaster(masterPtr->tkwin, "grid");
	masterPtr->flags &= ~ALLOCED_MASTER;
    if ((containerPtr->contentPtr == NULL) && (containerPtr->flags & ALLOCED_CONTAINER)) {
	TkFreeGeometryContainer(containerPtr->tkwin, "grid");
	containerPtr->flags &= ~ALLOCED_CONTAINER;
	Tk_SendVirtualEvent(containerPtr->tkwin, "NoManagedChild", NULL);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * DestroyGrid --
 *
 *	This procedure is invoked by Tcl_EventuallyFree or Tcl_Release to
 *	clean up the internal structure of a grid at a safe time (when no-one
 *	is using it anymore). Cleaning up the grid involves freeing the main
 *	structure for all windows and the master structure for geometry
 *	structure for all windows and the container structure for geometry
 *	managers.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Everything associated with the grid is freed up.
 *
 *----------------------------------------------------------------------
 */

static void
DestroyGrid(
    void *memPtr)		/* Info about window that is now dead. */
{
    register Gridder *gridPtr = memPtr;
    Gridder *gridPtr = (Gridder *)memPtr;

    if (gridPtr->masterDataPtr != NULL) {
	if (gridPtr->masterDataPtr->rowPtr != NULL) {
	    ckfree(gridPtr->masterDataPtr -> rowPtr);
    if (gridPtr->containerDataPtr != NULL) {
	if (gridPtr->containerDataPtr->rowPtr != NULL) {
	    ckfree(gridPtr->containerDataPtr -> rowPtr);
	}
	if (gridPtr->masterDataPtr->columnPtr != NULL) {
	    ckfree(gridPtr->masterDataPtr -> columnPtr);
	if (gridPtr->containerDataPtr->columnPtr != NULL) {
	    ckfree(gridPtr->containerDataPtr -> columnPtr);
	}
	ckfree(gridPtr->masterDataPtr);
	ckfree(gridPtr->containerDataPtr);
    }
    if (gridPtr->in != NULL) {
	Tcl_DecrRefCount(gridPtr->in);
    }
    ckfree(gridPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * GridStructureProc --
 *
 *	This procedure is invoked by the Tk event dispatcher in response to
 *	StructureNotify events.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	If a window was just deleted, clean up all its grid-related
 *	information. If it was just resized, re-configure its slaves, if any.
 *	information. If it was just resized, re-configure its content, if any.
 *
 *----------------------------------------------------------------------
 */

static void
GridStructureProc(
    ClientData clientData,	/* Our information about window referred to by
				 * eventPtr. */
    XEvent *eventPtr)		/* Describes what just happened. */
{
    register Gridder *gridPtr = clientData;
    Gridder *gridPtr = (Gridder *)clientData;
    TkDisplay *dispPtr = ((TkWindow *) gridPtr->tkwin)->dispPtr;

    if (eventPtr->type == ConfigureNotify) {
	if ((gridPtr->slavePtr != NULL)
	if ((gridPtr->contentPtr != NULL)
		&& !(gridPtr->flags & REQUESTED_RELAYOUT)) {
	    gridPtr->flags |= REQUESTED_RELAYOUT;
	    Tcl_DoWhenIdle(ArrangeGrid, gridPtr);
	}
	if ((gridPtr->masterPtr != NULL) &&
	if ((gridPtr->containerPtr != NULL) &&
		(gridPtr->doubleBw != 2*Tk_Changes(gridPtr->tkwin)->border_width)) {
	    if (!(gridPtr->masterPtr->flags & REQUESTED_RELAYOUT)) {
	    if (!(gridPtr->containerPtr->flags & REQUESTED_RELAYOUT)) {
		gridPtr->doubleBw = 2*Tk_Changes(gridPtr->tkwin)->border_width;
		gridPtr->masterPtr->flags |= REQUESTED_RELAYOUT;
		Tcl_DoWhenIdle(ArrangeGrid, gridPtr->masterPtr);
		gridPtr->containerPtr->flags |= REQUESTED_RELAYOUT;
		Tcl_DoWhenIdle(ArrangeGrid, gridPtr->containerPtr);
	    }
	}
    } else if (eventPtr->type == DestroyNotify) {
	register Gridder *slavePtr, *nextPtr;
	Gridder *contentPtr, *nextPtr;

	if (gridPtr->masterPtr != NULL) {
	if (gridPtr->containerPtr != NULL) {
	    Unlink(gridPtr);
	}
	for (slavePtr = gridPtr->slavePtr; slavePtr != NULL;
		slavePtr = nextPtr) {
	    Tk_ManageGeometry(slavePtr->tkwin, NULL, NULL);
	    Tk_UnmapWindow(slavePtr->tkwin);
	    slavePtr->masterPtr = NULL;
	    nextPtr = slavePtr->nextPtr;
	    slavePtr->nextPtr = NULL;
	for (contentPtr = gridPtr->contentPtr; contentPtr != NULL;
		contentPtr = nextPtr) {
	    Tk_ManageGeometry(contentPtr->tkwin, NULL, NULL);
	    Tk_UnmapWindow(contentPtr->tkwin);
	    contentPtr->containerPtr = NULL;
	    nextPtr = contentPtr->nextPtr;
	    contentPtr->nextPtr = NULL;
	}
	Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->gridHashTable,
		(char *) gridPtr->tkwin));
		gridPtr->tkwin));
	if (gridPtr->flags & REQUESTED_RELAYOUT) {
	    Tcl_CancelIdleCall(ArrangeGrid, gridPtr);
	}
	gridPtr->tkwin = NULL;
	Tcl_EventuallyFree(gridPtr, (Tcl_FreeProc *)DestroyGrid);
    } else if (eventPtr->type == MapNotify) {
	if ((gridPtr->slavePtr != NULL)
	if ((gridPtr->contentPtr != NULL)
		&& !(gridPtr->flags & REQUESTED_RELAYOUT)) {
	    gridPtr->flags |= REQUESTED_RELAYOUT;
	    Tcl_DoWhenIdle(ArrangeGrid, gridPtr);
	}
    } else if (eventPtr->type == UnmapNotify) {
	register Gridder *slavePtr;
	Gridder *contentPtr;

	for (slavePtr = gridPtr->slavePtr; slavePtr != NULL;
		slavePtr = slavePtr->nextPtr) {
	    Tk_UnmapWindow(slavePtr->tkwin);
	for (contentPtr = gridPtr->contentPtr; contentPtr != NULL;
		contentPtr = contentPtr->nextPtr) {
	    Tk_UnmapWindow(contentPtr->tkwin);
	}
    }
}

/*
 *----------------------------------------------------------------------
 *
 * ConfigureSlaves --
 * ConfigureContent --
 *
 *	This implements the guts of the "grid configure" command. Given a list
 *	of slaves and configuration options, it arranges for the grid to
 *	manage the slaves and sets the specified options. Arguments consist
 *	of content and configuration options, it arranges for the grid to
 *	manage the content and sets the specified options. Arguments consist
 *	of windows or window shortcuts followed by "-option value" pairs.
 *
 * Results:
 *	TCL_OK is returned if all went well. Otherwise, TCL_ERROR is returned
 *	and the interp's result is set to contain an error message.
 *
 * Side effects:
 *	Slave windows get taken over by the grid.
 *	Content windows get taken over by the grid.
 *
 *----------------------------------------------------------------------
 */

static int
ConfigureSlaves(
ConfigureContent(
    Tcl_Interp *interp,		/* Interpreter for error reporting. */
    Tk_Window tkwin,		/* Any window in application containing
				 * slaves. Used to look up slave names. */
				 * content. Used to look up content names. */
    int objc,			/* Number of elements in argv. */
    Tcl_Obj *const objv[])	/* Argument objects: contains one or more
				 * window names followed by any number of
				 * "option value" pairs. Caller must make sure
				 * that there is at least one window name. */
{
    Gridder *masterPtr = NULL;
    Gridder *slavePtr;
    Tk_Window other, slave, parent, ancestor;
    TkWindow *master;
    Gridder *containerPtr = NULL;
    Gridder *contentPtr;
    Tk_Window other, content, parent, ancestor;
    TkWindow *container;
    int i, j, tmp;
    int numWindows;
    int width;
    int defaultRow = -1;
    int defaultColumn = 0;	/* Default column number */
    int defaultColumnSpan = 1;	/* Default number of columns */
    const char *lastWindow;	/* Use this window to base current row/col
2962
2963
2964
2965
2966
2967
2968
2969

2970
2971
2972

2973
2974
2975
2976
2977

2978
2979
2980
2981

2982
2983
2984

2985
2986

2987
2988

2989
2990
2991
2992
2993



2994
2995
2996


2997
2998
2999
3000
3001


3002
3003
3004


3005
3006
3007
3008
3009
3010
3011
2979
2980
2981
2982
2983
2984
2985

2986
2987
2988

2989
2990
2991
2992
2993

2994
2995
2996
2997

2998
2999
3000

3001
3002

3003
3004

3005
3006
3007



3008
3009
3010
3011


3012
3013
3014
3015
3016


3017
3018
3019


3020
3021
3022
3023
3024
3025
3026
3027
3028







-
+


-
+




-
+



-
+


-
+

-
+

-
+


-
-
-
+
+
+

-
-
+
+



-
-
+
+

-
-
+
+








    /*
     * Count the number of windows, or window short-cuts.
     */

    firstChar = 0;
    for (numWindows=0, i=0; i < objc; i++) {
	int length;
	TkSizeT length;
	char prevChar = firstChar;

	string = Tcl_GetStringFromObj(objv[i], &length);
	string = TkGetStringFromObj(objv[i], &length);
    	firstChar = string[0];

	if (firstChar == '.') {
	    /*
	     * Check that windows are valid, and locate the first slave's
	     * Check that windows are valid, and locate the first content's
	     * parent window (default for -in).
	     */

	    if (TkGetWindowFromObj(interp, tkwin, objv[i], &slave) != TCL_OK) {
	    if (TkGetWindowFromObj(interp, tkwin, objv[i], &content) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if (masterPtr == NULL) {
	    if (containerPtr == NULL) {
		/*
		 * Is there any saved -in from a removed slave?
		 * Is there any saved -in from a removed content?
		 * If there is, it becomes default for -in.
		 * If the stored master does not exist, just ignore it.
		 * If the stored container does not exist, just ignore it.
		 */

		struct Gridder *slavePtr = GetGrid(slave);
		if (slavePtr->in != NULL) {
		    if (TkGetWindowFromObj(interp, slave, slavePtr->in, &parent)
		contentPtr = GetGrid(content);
		if (contentPtr->in != NULL) {
		    if (TkGetWindowFromObj(interp, content, contentPtr->in, &parent)
			    == TCL_OK) {
			masterPtr = GetGrid(parent);
			InitMasterData(masterPtr);
			containerPtr = GetGrid(parent);
			InitContainerData(containerPtr);
		    }
		}
	    }
	    if (masterPtr == NULL) {
		parent = Tk_Parent(slave);
	    if (containerPtr == NULL) {
		parent = Tk_Parent(content);
		if (parent != NULL) {
		    masterPtr = GetGrid(parent);
		    InitMasterData(masterPtr);
		    containerPtr = GetGrid(parent);
		    InitContainerData(containerPtr);
		}
	    }
	    numWindows++;
	    continue;
    	}
	if (length > 1 && i == 0) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
3065
3066
3067
3068
3069
3070
3071
3072
3073


3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089

3090
3091
3092
3093
3094
3095



3096
3097
3098
3099
3100
3101
3102
3103
3104
3105




3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118

3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131

3132
3133
3134
3135
3136
3137
3138

3139
3140
3141
3142

3143
3144
3145
3146
3147
3148
3149

3150
3151
3152
3153
3154

3155
3156
3157
3158

3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179

3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192

3193
3194
3195
3196
3197
3198
3199
3200
3201

3202
3203
3204
3205
3206
3207
3208
3209


3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222

3223
3224
3225
3226

3227
3228
3229
3230
3231
3232
3233
3234

3235
3236
3237

3238
3239
3240
3241
3242
3243
3244
3245

3246
3247
3248
3249

3250
3251
3252
3253
3254
3255

3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268

3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281

3282
3283
3284
3285
3286
3287
3288
3289

3290
3291
3292
3293
3294


3295
3296
3297
3298
3299
3300
3301
3302
3303

3304
3305
3306
3307
3308

3309
3310

3311
3312
3313
3314
3315
3316




3317
3318
3319
3320
3321



3322
3323
3324


3325
3326
3327
3328


3329
3330
3331
3332



3333
3334
3335
3336
3337


3338
3339
3340
3341

3342
3343
3344
3345
3346
3347
3348


3349
3350

3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361



3362
3363
3364


3365
3366

3367
3368
3369
3370
3371


3372
3373
3374

3375
3376
3377


3378
3379
3380


3381
3382
3383

3384
3385
3386
3387
3388
3389
3390
3391


3392
3393
3394
3395
3396


3397
3398
3399
3400


3401
3402
3403
3404

3405
3406
3407
3408

3409
3410
3411
3412
3413


3414
3415
3416
3417



3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433

3434
3435

3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446

3447
3448

3449
3450
3451
3452
3453
3454
3455
3456
3457
3458

3459
3460
3461
3462
3463
3464
3465
3082
3083
3084
3085
3086
3087
3088


3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105

3106
3107
3108
3109



3110
3111
3112
3113
3114
3115
3116
3117
3118




3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134

3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147

3148
3149
3150
3151
3152
3153
3154

3155
3156
3157
3158

3159
3160
3161
3162
3163
3164
3165

3166
3167
3168
3169
3170

3171
3172
3173
3174

3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195

3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208

3209
3210
3211
3212
3213
3214
3215
3216
3217

3218
3219
3220
3221
3222
3223
3224


3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238

3239
3240
3241
3242

3243
3244
3245
3246
3247
3248
3249
3250

3251
3252
3253

3254
3255
3256
3257
3258
3259
3260
3261

3262
3263
3264
3265

3266
3267
3268
3269
3270
3271

3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284

3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297

3298
3299
3300
3301
3302
3303
3304
3305

3306
3307
3308
3309


3310
3311
3312
3313
3314
3315
3316
3317
3318
3319

3320
3321
3322
3323
3324

3325
3326

3327
3328
3329




3330
3331
3332
3333
3334
3335



3336
3337
3338
3339


3340
3341
3342
3343


3344
3345
3346



3347
3348
3349
3350
3351
3352


3353
3354
3355
3356
3357

3358
3359
3360
3361
3362
3363


3364
3365
3366

3367
3368
3369
3370
3371
3372
3373
3374
3375



3376
3377
3378
3379


3380
3381
3382

3383
3384
3385
3386


3387
3388
3389
3390

3391
3392


3393
3394
3395


3396
3397
3398
3399

3400
3401
3402
3403
3404
3405
3406


3407
3408
3409
3410
3411


3412
3413
3414
3415


3416
3417
3418
3419
3420

3421
3422
3423
3424

3425
3426
3427
3428


3429
3430
3431



3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449

3450
3451

3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462

3463
3464

3465
3466
3467
3468
3469
3470
3471
3472
3473
3474

3475
3476
3477
3478
3479
3480
3481
3482







-
-
+
+















-
+



-
-
-
+
+
+






-
-
-
-
+
+
+
+












-
+












-
+






-
+



-
+






-
+




-
+



-
+




















-
+












-
+








-
+






-
-
+
+












-
+



-
+







-
+


-
+







-
+



-
+





-
+












-
+












-
+







-
+



-
-
+
+








-
+




-
+

-
+


-
-
-
-
+
+
+
+


-
-
-
+
+
+

-
-
+
+


-
-
+
+

-
-
-
+
+
+



-
-
+
+



-
+





-
-
+
+

-
+








-
-
-
+
+
+

-
-
+
+

-
+



-
-
+
+


-
+

-
-
+
+

-
-
+
+


-
+






-
-
+
+



-
-
+
+


-
-
+
+



-
+



-
+



-
-
+
+

-
-
-
+
+
+















-
+

-
+










-
+

-
+









-
+







	    return TCL_ERROR;
	}
	if (index == CONF_IN) {
	    if (TkGetWindowFromObj(interp, tkwin, objv[i+1], &other) !=
		    TCL_OK) {
		return TCL_ERROR;
	    }
	    masterPtr = GetGrid(other);
	    InitMasterData(masterPtr);
	    containerPtr = GetGrid(other);
	    InitContainerData(containerPtr);
	} else if (index == CONF_ROW) {
	    if (Tcl_GetIntFromObj(interp, objv[i+1], &tmp) != TCL_OK
		    || tmp < 0) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"bad row value \"%s\": must be a non-negative integer",
			Tcl_GetString(objv[i+1])));
		Tcl_SetErrorCode(interp, "TK", "VALUE", "POSITIVE_INT", NULL);
		return TCL_ERROR;
	    }
	    defaultRow = tmp;
	}
    }

    /*
     * If no -row is given, use the next row after the highest occupied row
     * of the master.
     * of the container.
     */

    if (defaultRow < 0) {
	if (masterPtr != NULL && masterPtr->masterDataPtr != NULL) {
	    SetGridSize(masterPtr);
	    defaultRow = masterPtr->masterDataPtr->rowEnd;
	if (containerPtr != NULL && containerPtr->containerDataPtr != NULL) {
	    SetGridSize(containerPtr);
	    defaultRow = containerPtr->containerDataPtr->rowEnd;
	} else {
	    defaultRow = 0;
	}
    }

    /*
     * Iterate over all of the slave windows and short-cuts, parsing options
     * for each slave. It's a bit wasteful to re-parse the options for each
     * slave, but things get too messy if we try to parse the arguments just
     * once at the beginning. For example, if a slave already is managed we
     * Iterate over all of the content windows and short-cuts, parsing options
     * for each content. It's a bit wasteful to re-parse the options for each
     * content, but things get too messy if we try to parse the arguments just
     * once at the beginning. For example, if a content already is managed we
     * want to just change a few existing values without resetting everything.
     * If there are multiple windows, the -in option only gets processed for
     * the first window.
     */

    positionGiven = 0;
    for (j = 0; j < numWindows; j++) {
	string = Tcl_GetString(objv[j]);
    	firstChar = string[0];

	/*
	 * '^' and 'x' cause us to skip a column. '-' is processed as part of
	 * its preceeding slave.
	 * its preceeding content.
	 */

	if ((firstChar == REL_VERT) || (firstChar == REL_SKIP)) {
	    defaultColumn++;
	    continue;
	}
	if (firstChar == REL_HORIZ) {
	    continue;
	}

	for (defaultColumnSpan = 1; j + defaultColumnSpan < numWindows;
		defaultColumnSpan++) {
	    const char *string = Tcl_GetString(objv[j + defaultColumnSpan]);
	    string = Tcl_GetString(objv[j + defaultColumnSpan]);

	    if (*string != REL_HORIZ) {
		break;
	    }
	}

	if (TkGetWindowFromObj(interp, tkwin, objv[j], &slave) != TCL_OK) {
	if (TkGetWindowFromObj(interp, tkwin, objv[j], &content) != TCL_OK) {
	    return TCL_ERROR;
	}

	if (Tk_TopWinHierarchy(slave)) {
	if (Tk_TopWinHierarchy(content)) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "can't manage \"%s\": it's a top-level window",
		    Tcl_GetString(objv[j])));
	    Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "TOPLEVEL", NULL);
	    return TCL_ERROR;
	}
	slavePtr = GetGrid(slave);
	contentPtr = GetGrid(content);

	/*
	 * The following statement is taken from tkPack.c:
	 *
	 * "If the slave isn't currently managed, reset all of its
	 * "If the content isn't currently managed, reset all of its
	 * configuration information to default values (there could be old
	 * values left from a previous packer)."
	 *
	 * I [D.S.] disagree with this statement. If a slave is disabled
	 * I [D.S.] disagree with this statement. If a content is disabled
	 * (using "forget") and then re-enabled, I submit that 90% of the time
	 * the programmer will want it to retain its old configuration
	 * information. If the programmer doesn't want this behavior, then the
	 * defaults can be reestablished by hand, without having to worry
	 * about keeping track of the old state.
	 */

	for (i = numWindows; i < objc; i += 2) {
	    Tcl_GetIndexFromObjStruct(interp, objv[i], optionStrings,
		    sizeof(char *), "option", 0, &index);
	    switch ((enum options) index) {
	    case CONF_COLUMN:
		if (Tcl_GetIntFromObj(NULL, objv[i+1], &tmp) != TCL_OK
			|| tmp < 0) {
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			    "bad column value \"%s\": must be a non-negative integer",
			    Tcl_GetString(objv[i+1])));
		    Tcl_SetErrorCode(interp, "TK", "VALUE", "COLUMN", NULL);
		    return TCL_ERROR;
		}
		if (SetSlaveColumn(interp, slavePtr, tmp, -1) != TCL_OK) {
		if (SetContentColumn(interp, contentPtr, tmp, -1) != TCL_OK) {
		    return TCL_ERROR;
		}
		break;
	    case CONF_COLUMNSPAN:
		if (Tcl_GetIntFromObj(NULL, objv[i+1], &tmp) != TCL_OK
			|| tmp <= 0) {
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			    "bad columnspan value \"%s\": must be a positive integer",
			    Tcl_GetString(objv[i+1])));
		    Tcl_SetErrorCode(interp, "TK", "VALUE", "SPAN", NULL);
		    return TCL_ERROR;
		}
		if (SetSlaveColumn(interp, slavePtr, -1, tmp) != TCL_OK) {
		if (SetContentColumn(interp, contentPtr, -1, tmp) != TCL_OK) {
		    return TCL_ERROR;
		}
		break;
	    case CONF_IN:
		if (TkGetWindowFromObj(interp, tkwin, objv[i+1],
			&other) != TCL_OK) {
		    return TCL_ERROR;
		}
		if (other == slave) {
		if (other == content) {
		    Tcl_SetObjResult(interp, Tcl_NewStringObj(
			    "window can't be managed in itself", -1));
		    Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "SELF", NULL);
		    return TCL_ERROR;
		}
		positionGiven = 1;
		masterPtr = GetGrid(other);
		InitMasterData(masterPtr);
		containerPtr = GetGrid(other);
		InitContainerData(containerPtr);
		break;
	    case CONF_STICKY: {
		int sticky = StringToSticky(Tcl_GetString(objv[i+1]));

		if (sticky == -1) {
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			    "bad stickyness value \"%s\": must be"
			    " a string containing n, e, s, and/or w",
			    Tcl_GetString(objv[i+1])));
		    Tcl_SetErrorCode(interp, "TK", "VALUE", "STICKY", NULL);
		    return TCL_ERROR;
		}
		slavePtr->sticky = sticky;
		contentPtr->sticky = sticky;
		break;
	    }
	    case CONF_IPADX:
		if ((Tk_GetPixelsFromObj(NULL, slave, objv[i+1],
		if ((Tk_GetPixelsFromObj(NULL, content, objv[i+1],
			&tmp) != TCL_OK) || (tmp < 0)) {
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			    "bad ipadx value \"%s\": must be positive screen distance",
			    Tcl_GetString(objv[i+1])));
		    Tcl_SetErrorCode(interp, "TK", "VALUE", "INT_PAD", NULL);
		    return TCL_ERROR;
		}
		slavePtr->iPadX = tmp * 2;
		contentPtr->iPadX = tmp * 2;
		break;
	    case CONF_IPADY:
		if ((Tk_GetPixelsFromObj(NULL, slave, objv[i+1],
		if ((Tk_GetPixelsFromObj(NULL, content, objv[i+1],
			&tmp) != TCL_OK) || (tmp < 0)) {
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			    "bad ipady value \"%s\": must be positive screen distance",
			    Tcl_GetString(objv[i+1])));
		    Tcl_SetErrorCode(interp, "TK", "VALUE", "INT_PAD", NULL);
		    return TCL_ERROR;
		}
		slavePtr->iPadY = tmp * 2;
		contentPtr->iPadY = tmp * 2;
		break;
	    case CONF_PADX:
		if (TkParsePadAmount(interp, tkwin, objv[i+1],
			&slavePtr->padLeft, &slavePtr->padX) != TCL_OK) {
			&contentPtr->padLeft, &contentPtr->padX) != TCL_OK) {
		    return TCL_ERROR;
		}
		break;
	    case CONF_PADY:
		if (TkParsePadAmount(interp, tkwin, objv[i+1],
			&slavePtr->padTop, &slavePtr->padY) != TCL_OK) {
			&contentPtr->padTop, &contentPtr->padY) != TCL_OK) {
		    return TCL_ERROR;
		}
		break;
	    case CONF_ROW:
		if (Tcl_GetIntFromObj(NULL, objv[i+1], &tmp) != TCL_OK
			|| tmp < 0) {
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			    "bad row value \"%s\": must be a non-negative integer",
			    Tcl_GetString(objv[i+1])));
		    Tcl_SetErrorCode(interp, "TK", "VALUE", "COLUMN", NULL);
		    return TCL_ERROR;
		}
		if (SetSlaveRow(interp, slavePtr, tmp, -1) != TCL_OK) {
		if (SetContentRow(interp, contentPtr, tmp, -1) != TCL_OK) {
		    return TCL_ERROR;
		}
		break;
	    case CONF_ROWSPAN:
		if ((Tcl_GetIntFromObj(NULL, objv[i+1], &tmp) != TCL_OK)
			|| tmp <= 0) {
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			    "bad rowspan value \"%s\": must be a positive integer",
			    Tcl_GetString(objv[i+1])));
		    Tcl_SetErrorCode(interp, "TK", "VALUE", "SPAN", NULL);
		    return TCL_ERROR;
		}
		if (SetSlaveRow(interp, slavePtr, -1, tmp) != TCL_OK) {
		if (SetContentRow(interp, contentPtr, -1, tmp) != TCL_OK) {
		    return TCL_ERROR;
		}
		break;
	    }
	}

	/*
	 * If no position was specified via -in and the slave is already
	 * If no position was specified via -in and the content is already
	 * packed, then leave it in its current location.
	 */

    	if (!positionGiven && (slavePtr->masterPtr != NULL)) {
	    masterPtr = slavePtr->masterPtr;
    	if (!positionGiven && (contentPtr->containerPtr != NULL)) {
	    containerPtr = contentPtr->containerPtr;
	    goto scheduleLayout;
    	}

	/*
	 * If the same -in window is passed in again, then just leave it in
	 * its current location.
	 */

	if (positionGiven && (masterPtr == slavePtr->masterPtr)) {
	if (positionGiven && (containerPtr == contentPtr->containerPtr)) {
	    goto scheduleLayout;
	}

	/*
	 * Make sure we have a geometry master. We look at:
	 * Make sure we have a geometry container. We look at:
	 *  1)   the -in flag
	 *  2)   the parent of the first slave.
	 *  2)   the parent of the first content.
	 */

	parent = Tk_Parent(slave);
    	if (masterPtr == NULL) {
	    masterPtr = GetGrid(parent);
	    InitMasterData(masterPtr);
	parent = Tk_Parent(content);
    	if (containerPtr == NULL) {
	    containerPtr = GetGrid(parent);
	    InitContainerData(containerPtr);
    	}

	if (slavePtr->masterPtr != NULL && slavePtr->masterPtr != masterPtr) {
            if (slavePtr->masterPtr->tkwin != Tk_Parent(slavePtr->tkwin)) {
                Tk_UnmaintainGeometry(slavePtr->tkwin, slavePtr->masterPtr->tkwin);
	if (contentPtr->containerPtr != NULL && contentPtr->containerPtr != containerPtr) {
            if (contentPtr->containerPtr->tkwin != Tk_Parent(contentPtr->tkwin)) {
                Tk_UnmaintainGeometry(contentPtr->tkwin, contentPtr->containerPtr->tkwin);
            }
	    Unlink(slavePtr);
	    slavePtr->masterPtr = NULL;
	    Unlink(contentPtr);
	    contentPtr->containerPtr = NULL;
	}

	if (slavePtr->masterPtr == NULL) {
	    Gridder *tempPtr = masterPtr->slavePtr;
	if (contentPtr->containerPtr == NULL) {
	    Gridder *tempPtr = containerPtr->contentPtr;

	    slavePtr->masterPtr = masterPtr;
	    masterPtr->slavePtr = slavePtr;
	    slavePtr->nextPtr = tempPtr;
	    contentPtr->containerPtr = containerPtr;
	    containerPtr->contentPtr = contentPtr;
	    contentPtr->nextPtr = tempPtr;
	}

	/*
	 * Make sure that the slave's parent is either the master or an
	 * ancestor of the master, and that the master and slave aren't the
	 * Make sure that the content's parent is either the container or an
	 * ancestor of the container, and that the container and content aren't the
	 * same.
	 */

	for (ancestor = masterPtr->tkwin; ; ancestor = Tk_Parent(ancestor)) {
	for (ancestor = containerPtr->tkwin; ; ancestor = Tk_Parent(ancestor)) {
	    if (ancestor == parent) {
		break;
	    }
	    if (Tk_TopWinHierarchy(ancestor)) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"can't put %s inside %s", Tcl_GetString(objv[j]),
			Tk_PathName(masterPtr->tkwin)));
			"can't put \"%s\" inside \"%s\"", Tcl_GetString(objv[j]),
			Tk_PathName(containerPtr->tkwin)));
		Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "HIERARCHY", NULL);
		Unlink(slavePtr);
		Unlink(contentPtr);
		return TCL_ERROR;
	    }
	}

	/*
	 * Check for management loops.
	 */

	for (master = (TkWindow *)masterPtr->tkwin; master != NULL;
	     master = (TkWindow *)TkGetGeomMaster(master)) {
	    if (master == (TkWindow *)slave) {
	for (container = (TkWindow *)containerPtr->tkwin; container != NULL;
	     container = (TkWindow *)TkGetContainer(container)) {
	    if (container == (TkWindow *)content) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "can't put %s inside %s, would cause management loop",
	            Tcl_GetString(objv[j]), Tk_PathName(masterPtr->tkwin)));
		    "can't put \"%s\" inside \"%s\": would cause management loop",
	            Tcl_GetString(objv[j]), Tk_PathName(containerPtr->tkwin)));
		Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "LOOP", NULL);
		Unlink(slavePtr);
		Unlink(contentPtr);
		return TCL_ERROR;
	    }
	}
	if (masterPtr->tkwin != Tk_Parent(slave)) {
	    ((TkWindow *)slave)->maintainerPtr = (TkWindow *)masterPtr->tkwin;
	if (containerPtr->tkwin != Tk_Parent(content)) {
	    ((TkWindow *)content)->maintainerPtr = (TkWindow *)containerPtr->tkwin;
	}

	Tk_ManageGeometry(slave, &gridMgrType, slavePtr);
	Tk_ManageGeometry(content, &gridMgrType, contentPtr);

	if (!(masterPtr->flags & DONT_PROPAGATE)) {
	    if (TkSetGeometryMaster(interp, masterPtr->tkwin, "grid")
	if (!(containerPtr->flags & DONT_PROPAGATE)) {
	    if (TkSetGeometryContainer(interp, containerPtr->tkwin, "grid")
		    != TCL_OK) {
		Tk_ManageGeometry(slave, NULL, NULL);
		Unlink(slavePtr);
		Tk_ManageGeometry(content, NULL, NULL);
		Unlink(contentPtr);
		return TCL_ERROR;
	    }
	    masterPtr->flags |= ALLOCED_MASTER;
	    containerPtr->flags |= ALLOCED_CONTAINER;
	}

	/*
	 * Assign default position information.
	 */

	if (slavePtr->column == -1) {
	    if (SetSlaveColumn(interp, slavePtr, defaultColumn,-1) != TCL_OK){
	if (contentPtr->column == -1) {
	    if (SetContentColumn(interp, contentPtr, defaultColumn,-1) != TCL_OK){
		return TCL_ERROR;
	    }
	}
	if (SetSlaveColumn(interp, slavePtr, -1,
		slavePtr->numCols + defaultColumnSpan - 1) != TCL_OK) {
	if (SetContentColumn(interp, contentPtr, -1,
		contentPtr->numCols + defaultColumnSpan - 1) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (slavePtr->row == -1) {
	    if (SetSlaveRow(interp, slavePtr, defaultRow, -1) != TCL_OK) {
	if (contentPtr->row == -1) {
	    if (SetContentRow(interp, contentPtr, defaultRow, -1) != TCL_OK) {
		return TCL_ERROR;
	    }
	}
	defaultColumn += slavePtr->numCols;
	defaultColumn += contentPtr->numCols;
	defaultColumnSpan = 1;

	/*
	 * Arrange for the master to be re-arranged at the first idle moment.
	 * Arrange for the container to be re-arranged at the first idle moment.
	 */

    scheduleLayout:
	if (masterPtr->abortPtr != NULL) {
	    *masterPtr->abortPtr = 1;
	if (containerPtr->abortPtr != NULL) {
	    *containerPtr->abortPtr = 1;
	}
	if (!(masterPtr->flags & REQUESTED_RELAYOUT)) {
	    masterPtr->flags |= REQUESTED_RELAYOUT;
	    Tcl_DoWhenIdle(ArrangeGrid, masterPtr);
	if (!(containerPtr->flags & REQUESTED_RELAYOUT)) {
	    containerPtr->flags |= REQUESTED_RELAYOUT;
	    Tcl_DoWhenIdle(ArrangeGrid, containerPtr);
	}
    }

    /*
     * Now look for all the "^"'s.
     */

    lastWindow = NULL;
    numSkip = 0;
    for (j = 0; j < numWindows; j++) {
	struct Gridder *otherPtr;
	int match;			/* Found a match for the ^ */
	int lastRow, lastColumn;	/* Implied end of table. */

	string = Tcl_GetString(objv[j]);
    	firstChar = string[0];
	firstChar = string[0];

    	if (firstChar == '.') {
	if (firstChar == '.') {
	    lastWindow = string;
	    numSkip = 0;
	}
	if (firstChar == REL_SKIP) {
	    numSkip++;
	}
	if (firstChar != REL_VERT) {
	    continue;
	}

	if (masterPtr == NULL) {
	if (containerPtr == NULL) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "can't use '^', cant find master", -1));
		    "can't use '^', can't find container window", -1));
	    Tcl_SetErrorCode(interp, "TK", "GRID", "SHORTCUT_USAGE", NULL);
	    return TCL_ERROR;
	}

	/*
	 * Count the number of consecutive ^'s starting from this position.
	 */

	for (width = 1; width + j < numWindows; width++) {
	    const char *string = Tcl_GetString(objv[j+width]);
	    string = Tcl_GetString(objv[j+width]);

	    if (*string != REL_VERT) {
		break;
	    }
	}

	/*
3475
3476
3477
3478
3479
3480
3481
3482
3483


3484
3485
3486
3487
3488
3489





3490
3491
3492
3493
3494


3495
3496
3497
3498
3499
3500
3501
3502

3503
3504
3505
3506
3507
3508

3509
3510

3511
3512
3513
3514

3515
3516
3517

3518



3519
3520
3521
3522
3523




3524
3525
3526
3527
3528
3529
3530
3492
3493
3494
3495
3496
3497
3498


3499
3500
3501





3502
3503
3504
3505
3506
3507
3508
3509


3510
3511
3512
3513
3514
3515
3516
3517
3518

3519
3520
3521
3522
3523
3524

3525
3526

3527
3528
3529
3530

3531
3532
3533

3534
3535
3536
3537
3538
3539
3540



3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551







-
-
+
+

-
-
-
-
-
+
+
+
+
+



-
-
+
+







-
+





-
+

-
+



-
+


-
+

+
+
+


-
-
-
+
+
+
+







	    lastRow = otherPtr->row + otherPtr->numRows - 2;
	    lastColumn = otherPtr->column + otherPtr->numCols;
	}

	lastColumn += numSkip;

	match = 0;
	for (slavePtr = masterPtr->slavePtr; slavePtr != NULL;
		slavePtr = slavePtr->nextPtr) {
	for (contentPtr = containerPtr->contentPtr; contentPtr != NULL;
		contentPtr = contentPtr->nextPtr) {

	    if (slavePtr->column == lastColumn
		    && slavePtr->row + slavePtr->numRows - 1 == lastRow) {
		if (slavePtr->numCols <= width) {
		    if (SetSlaveRow(interp, slavePtr, -1,
			    slavePtr->numRows + 1) != TCL_OK) {
	    if (contentPtr->column == lastColumn
		    && contentPtr->row + contentPtr->numRows - 1 == lastRow) {
		if (contentPtr->numCols <= width) {
		    if (SetContentRow(interp, contentPtr, -1,
			    contentPtr->numRows + 1) != TCL_OK) {
			return TCL_ERROR;
		    }
		    match++;
		    j += slavePtr->numCols - 1;
		    lastWindow = Tk_PathName(slavePtr->tkwin);
		    j += contentPtr->numCols - 1;
		    lastWindow = Tk_PathName(contentPtr->tkwin);
		    numSkip = 0;
		    break;
		}
	    }
	}
	if (!match) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "can't find slave to extend with \"^\"", -1));
		    "can't find content to extend with \"^\"", -1));
	    Tcl_SetErrorCode(interp, "TK", "GRID", "SHORTCUT_USAGE", NULL);
	    return TCL_ERROR;
	}
    }

    if (masterPtr == NULL) {
    if (containerPtr == NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"can't determine master window", -1));
		"can't determine container window", -1));
	Tcl_SetErrorCode(interp, "TK", "GRID", "SHORTCUT_USAGE", NULL);
	return TCL_ERROR;
    }
    SetGridSize(masterPtr);
    SetGridSize(containerPtr);

    /*
     * If we have emptied this master from slaves it means we are no longer
     * If we have emptied this container from content it means we are no longer
     * handling it and should mark it as free.
     *
     * Send the event "NoManagedChild" to the container to inform it about there
     * being no managed children inside it.
     */

    if (masterPtr->slavePtr == NULL && masterPtr->flags & ALLOCED_MASTER) {
	TkFreeGeometryMaster(masterPtr->tkwin, "grid");
	masterPtr->flags &= ~ALLOCED_MASTER;
    if (containerPtr->contentPtr == NULL && containerPtr->flags & ALLOCED_CONTAINER) {
	TkFreeGeometryContainer(containerPtr->tkwin, "grid");
	containerPtr->flags &= ~ALLOCED_CONTAINER;
	Tk_SendVirtualEvent(containerPtr->tkwin, "NoManagedChild", NULL);
    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
3627
3628
3629
3630
3631
3632
3633
3634

3635
3636
3637
3638
3639


3640
3641
3642
3643
3644
3645
3646
3648
3649
3650
3651
3652
3653
3654

3655
3656
3657
3658


3659
3660
3661
3662
3663
3664
3665
3666
3667







-
+



-
-
+
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static Tcl_Obj *
NewPairObj(
    int val1, int val2)
    Tcl_WideInt val1, Tcl_WideInt val2)
{
    Tcl_Obj *ary[2];

    ary[0] = Tcl_NewIntObj(val1);
    ary[1] = Tcl_NewIntObj(val2);
    ary[0] = Tcl_NewWideIntObj(val1);
    ary[1] = Tcl_NewWideIntObj(val2);
    return Tcl_NewListObj(2, ary);
}

/*
 *----------------------------------------------------------------------
 *
 * NewQuadObj --
3654
3655
3656
3657
3658
3659
3660
3661

3662
3663
3664
3665
3666
3667
3668




3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3675
3676
3677
3678
3679
3680
3681

3682
3683
3684
3685




3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699







-
+



-
-
-
-
+
+
+
+










 *	None.
 *
 *----------------------------------------------------------------------
 */

static Tcl_Obj *
NewQuadObj(
    int val1, int val2, int val3, int val4)
    Tcl_WideInt val1, Tcl_WideInt val2, Tcl_WideInt val3, Tcl_WideInt val4)
{
    Tcl_Obj *ary[4];

    ary[0] = Tcl_NewIntObj(val1);
    ary[1] = Tcl_NewIntObj(val2);
    ary[2] = Tcl_NewIntObj(val3);
    ary[3] = Tcl_NewIntObj(val4);
    ary[0] = Tcl_NewWideIntObj(val1);
    ary[1] = Tcl_NewWideIntObj(val2);
    ary[2] = Tcl_NewWideIntObj(val3);
    ary[3] = Tcl_NewWideIntObj(val4);
    return Tcl_NewListObj(4, ary);
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Changes to generic/tkImage.c.
1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30


31
32
33
34
35
36
37
38
39
40
41
42
43

44
45
46
47
48

49
50
51
52
53


54
55
56
57
58
59
60
61
62
63
64
65
66
67

68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86


87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107

108
109
110

111
112
113
114
115
116
117
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28


29
30
31
32
33
34
35
36
37
38
39
40
41
42

43
44
45
46
47

48
49
50
51


52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84


85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

107
108
109

110
111
112
113
114
115
116
117






-
-
+
+




















-
-
+
+












-
+




-
+



-
-
+
+













-
+

















-
-
+
+




















-
+


-
+







/*
 * 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.
 */

#include "tkInt.h"

/*
 * Each call to Tk_GetImage returns a pointer to one of the following
 * structures, which is used as a token by clients (widgets) that display
 * images.
 */

typedef struct Image {
    Tk_Window tkwin;		/* Window passed to Tk_GetImage (needed to
				 * "re-get" the image later if the manager
				 * changes). */
    Display *display;		/* Display for tkwin. Needed because when the
				 * image is eventually freed tkwin may not
				 * exist anymore. */
    struct ImageMaster *masterPtr;
				/* Master for this image (identifiers image
    struct ImageModel *modelPtr;
				/* Model for this image (identifiers image
				 * manager, for example). */
    ClientData instanceData;	/* One word argument to pass to image manager
				 * when dealing with this image instance. */
    Tk_ImageChangedProc *changeProc;
				/* Code in widget to call when image changes
				 * in a way that affects redisplay. */
    ClientData widgetClientData;/* Argument to pass to changeProc. */
    struct Image *nextPtr;	/* Next in list of all image instances
				 * associated with the same name. */
} Image;

/*
 * For each image master there is one of the following structures, which
 * For each image model there is one of the following structures, which
 * represents a name in the image table and all of the images instantiated
 * from it. Entries in mainPtr->imageTable point to these structures.
 */

typedef struct ImageMaster {
typedef struct ImageModel {
    Tk_ImageType *typePtr;	/* Information about image type. NULL means
				 * that no image manager owns this image: the
				 * image was deleted. */
    ClientData masterData;	/* One-word argument to pass to image mgr when
				 * dealing with the master, as opposed to
    ClientData modelData;	/* One-word argument to pass to image mgr when
				 * dealing with the model, as opposed to
				 * instances. */
    int width, height;		/* Last known dimensions for image. */
    Tcl_HashTable *tablePtr;	/* Pointer to hash table containing image (the
				 * imageTable field in some TkMainInfo
				 * structure). */
    Tcl_HashEntry *hPtr;	/* Hash entry in mainPtr->imageTable for this
				 * structure (used to delete the hash
				 * entry). */
    Image *instancePtr;		/* Pointer to first in list of instances
				 * derived from this name. */
    int deleted;		/* Flag set when image is being deleted. */
    TkWindow *winPtr;		/* Main window of interpreter (used to detect
				 * when the world is falling apart.) */
} ImageMaster;
} ImageModel;

typedef struct {
    Tk_ImageType *imageTypeList;/* First in a list of all known image
				 * types. */
    Tk_ImageType *oldImageTypeList;
				/* First in a list of all known old-style
				 * image types. */
    int initialized;		/* Set to 1 if we've initialized the
				 * structure. */
} ThreadSpecificData;
static Tcl_ThreadDataKey dataKey;

/*
 * Prototypes for local functions:
 */

static void		ImageTypeThreadExitProc(ClientData clientData);
static void		DeleteImage(ImageMaster *masterPtr);
static void		EventuallyDeleteImage(ImageMaster *masterPtr,
static void		DeleteImage(ImageModel *modelPtr);
static void		EventuallyDeleteImage(ImageModel *modelPtr,
			    int forgetImageHashNow);

/*
 *----------------------------------------------------------------------
 *
 * ImageTypeThreadExitProc --
 *
 *	Clean up the registered list of image types.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The thread's linked lists of photo image formats is deleted.
 *
 *----------------------------------------------------------------------
 */

static void
ImageTypeThreadExitProc(
    ClientData clientData)	/* not used */
    TCL_UNUSED(void *))
{
    Tk_ImageType *freePtr;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    while (tsdPtr->oldImageTypeList != NULL) {
	freePtr = tsdPtr->oldImageTypeList;
	tsdPtr->oldImageTypeList = tsdPtr->oldImageTypeList->nextPtr;
	ckfree(freePtr);
    }
145
146
147
148
149
150
151
152

153
154
155
156
157
158
159

160
161
162
163
164
165
166
167
168
169
170
171
172
173

174
175
176
177
178
179
180

181
182
183
184
185
186
187
145
146
147
148
149
150
151

152
153
154
155
156
157
158

159
160
161
162
163
164
165
166
167
168
169
170
171
172

173
174
175
176
177
178
179

180
181
182
183
184
185
186
187







-
+






-
+













-
+






-
+







Tk_CreateOldImageType(
    const Tk_ImageType *typePtr)
				/* Structure describing the type. All of the
				 * fields except "nextPtr" must be filled in
				 * by caller. */
{
    Tk_ImageType *copyPtr;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (!tsdPtr->initialized) {
	tsdPtr->initialized = 1;
	Tcl_CreateThreadExitHandler(ImageTypeThreadExitProc, NULL);
    }
    copyPtr = ckalloc(sizeof(Tk_ImageType));
    copyPtr = (Tk_ImageType *)ckalloc(sizeof(Tk_ImageType));
    *copyPtr = *typePtr;
    copyPtr->nextPtr = tsdPtr->oldImageTypeList;
    tsdPtr->oldImageTypeList = copyPtr;
}

void
Tk_CreateImageType(
    const Tk_ImageType *typePtr)
				/* Structure describing the type. All of the
				 * fields except "nextPtr" must be filled in
				 * by caller. */
{
    Tk_ImageType *copyPtr;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (!tsdPtr->initialized) {
	tsdPtr->initialized = 1;
	Tcl_CreateThreadExitHandler(ImageTypeThreadExitProc, NULL);
    }
    copyPtr = ckalloc(sizeof(Tk_ImageType));
    copyPtr = (Tk_ImageType *)ckalloc(sizeof(Tk_ImageType));
    *copyPtr = *typePtr;
    copyPtr->nextPtr = tsdPtr->imageTypeList;
    tsdPtr->imageTypeList = copyPtr;
}

/*
 *----------------------------------------------------------------------
211
212
213
214
215
216
217
218

219
220
221

222
223
224
225
226
227
228
229

230
231
232
233
234
235
236
211
212
213
214
215
216
217

218
219
220

221
222
223
224
225
226
227
228

229
230
231
232
233
234
235
236







-
+


-
+







-
+







	"create", "delete", "height", "inuse", "names", "type", "types",
	"width", NULL
    };
    enum options {
	IMAGE_CREATE, IMAGE_DELETE, IMAGE_HEIGHT, IMAGE_INUSE, IMAGE_NAMES,
	IMAGE_TYPE, IMAGE_TYPES, IMAGE_WIDTH
    };
    TkWindow *winPtr = clientData;
    TkWindow *winPtr = (TkWindow *)clientData;
    int i, isNew, firstOption, index;
    Tk_ImageType *typePtr;
    ImageMaster *masterPtr;
    ImageModel *modelPtr;
    Image *imagePtr;
    Tcl_HashEntry *hPtr;
    Tcl_HashSearch search;
    char idString[16 + TCL_INTEGER_SPACE];
    TkDisplay *dispPtr = winPtr->dispPtr;
    const char *arg, *name;
    Tcl_Obj *resultObj;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "option ?args?");
	return TCL_ERROR;
    }

293
294
295
296
297
298
299
300

301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331











332
333
334
335

336
337
338
339
340



341
342

343
344
345
346


347
348
349


350
351

352
353
354
355
356
357
358
359
360
361
362
363
364
365
366

367
368
369
370
371
372

373
374
375
376



377
378
379
380
381
382

383
384
385
386
387


388
389
390

391
392
393

394
395
396
397
398
399
400
401
402
403
404


405
406
407

408
409
410
411
412
413
414
415
416
417
418
419


420
421
422
423

424
425
426
427
428
429
430
293
294
295
296
297
298
299

300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320











321
322
323
324
325
326
327
328
329
330
331
332
333
334

335
336
337



338
339
340
341

342
343
344


345
346
347


348
349
350

351
352
353
354
355
356
357
358
359
360
361
362
363



364
365
366
367
368
369

370
371



372
373
374
375
376
377
378
379

380
381
382
383


384
385
386
387

388
389
390

391
392
393
394
395
396
397
398
399
400


401
402
403
404

405
406
407
408
409
410
411
412
413
414
415


416
417
418
419
420

421
422
423
424
425
426
427
428







-
+




















-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+



-
+


-
-
-
+
+
+

-
+


-
-
+
+

-
-
+
+

-
+












-
-
-
+





-
+

-
-
-
+
+
+





-
+



-
-
+
+


-
+


-
+









-
-
+
+


-
+










-
-
+
+



-
+







	    TkWindow *topWin;

	    name = arg;
	    firstOption = 4;

	    /*
	     * Need to check if the _command_ that we are about to create is
	     * the name of the current master widget command (normally "." but
	     * the name of the current model widget command (normally "." but
	     * could have been renamed) and fail in that case before a really
	     * nasty and hard to stop crash happens.
	     */

	    topWin = (TkWindow *) TkToplevelWindowForCommand(interp, name);
	    if (topWin != NULL && winPtr->mainPtr->winPtr == topWin) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"images may not be named the same as the main window",
			-1));
		Tcl_SetErrorCode(interp, "TK", "IMAGE", "SMASH_MAIN", NULL);
		return TCL_ERROR;
	    }
	}

	/*
	 * Create the data structure for the new image.
	 */

	hPtr = Tcl_CreateHashEntry(&winPtr->mainPtr->imageTable, name, &isNew);
	if (isNew) {
	    masterPtr = ckalloc(sizeof(ImageMaster));
	    masterPtr->typePtr = NULL;
	    masterPtr->masterData = NULL;
	    masterPtr->width = masterPtr->height = 1;
	    masterPtr->tablePtr = &winPtr->mainPtr->imageTable;
	    masterPtr->hPtr = hPtr;
	    masterPtr->instancePtr = NULL;
	    masterPtr->deleted = 0;
	    masterPtr->winPtr = winPtr->mainPtr->winPtr;
	    Tcl_Preserve(masterPtr->winPtr);
	    Tcl_SetHashValue(hPtr, masterPtr);
	    modelPtr = (ImageModel *)ckalloc(sizeof(ImageModel));
	    modelPtr->typePtr = NULL;
	    modelPtr->modelData = NULL;
	    modelPtr->width = modelPtr->height = 1;
	    modelPtr->tablePtr = &winPtr->mainPtr->imageTable;
	    modelPtr->hPtr = hPtr;
	    modelPtr->instancePtr = NULL;
	    modelPtr->deleted = 0;
	    modelPtr->winPtr = winPtr->mainPtr->winPtr;
	    Tcl_Preserve(modelPtr->winPtr);
	    Tcl_SetHashValue(hPtr, modelPtr);
	} else {
	    /*
	     * An image already exists by this name. Disconnect the instances
	     * from the master.
	     * from the model.
	     */

	    masterPtr = Tcl_GetHashValue(hPtr);
	    if (masterPtr->typePtr != NULL) {
		for (imagePtr = masterPtr->instancePtr; imagePtr != NULL;
	    modelPtr = (ImageModel *)Tcl_GetHashValue(hPtr);
	    if (modelPtr->typePtr != NULL) {
		for (imagePtr = modelPtr->instancePtr; imagePtr != NULL;
			imagePtr = imagePtr->nextPtr) {
		    masterPtr->typePtr->freeProc(imagePtr->instanceData,
		    modelPtr->typePtr->freeProc(imagePtr->instanceData,
			    imagePtr->display);
		    imagePtr->changeProc(imagePtr->widgetClientData, 0, 0,
			    masterPtr->width, masterPtr->height,
			    masterPtr->width, masterPtr->height);
			    modelPtr->width, modelPtr->height,
			    modelPtr->width, modelPtr->height);
		}
		masterPtr->typePtr->deleteProc(masterPtr->masterData);
		masterPtr->typePtr = NULL;
		modelPtr->typePtr->deleteProc(modelPtr->modelData);
		modelPtr->typePtr = NULL;
	    }
	    masterPtr->deleted = 0;
	    modelPtr->deleted = 0;
	}

	/*
	 * Call the image type manager so that it can perform its own
	 * initialization, then re-"get" for any existing instances of the
	 * image.
	 */

	objv += firstOption;
	objc -= firstOption;
	args = (Tcl_Obj **) objv;
	if (oldimage) {
	    int i;

	    args = ckalloc((objc+1) * sizeof(char *));
	    args = (Tcl_Obj **)ckalloc((objc+1) * sizeof(Tcl_Obj *));
	    for (i = 0; i < objc; i++) {
		args[i] = (Tcl_Obj *) Tcl_GetString(objv[i]);
	    }
	    args[objc] = NULL;
	}
	Tcl_Preserve(masterPtr);
	Tcl_Preserve(modelPtr);
	if (typePtr->createProc(interp, name, objc, args, typePtr,
		(Tk_ImageMaster)masterPtr, &masterPtr->masterData) != TCL_OK){
	    EventuallyDeleteImage(masterPtr, 0);
	    Tcl_Release(masterPtr);
		(Tk_ImageModel)modelPtr, &modelPtr->modelData) != TCL_OK){
	    EventuallyDeleteImage(modelPtr, 0);
	    Tcl_Release(modelPtr);
	    if (oldimage) {
		ckfree(args);
	    }
	    return TCL_ERROR;
	}
	Tcl_Release(masterPtr);
	Tcl_Release(modelPtr);
	if (oldimage) {
	    ckfree(args);
	}
	masterPtr->typePtr = typePtr;
	for (imagePtr = masterPtr->instancePtr; imagePtr != NULL;
	modelPtr->typePtr = typePtr;
	for (imagePtr = modelPtr->instancePtr; imagePtr != NULL;
		imagePtr = imagePtr->nextPtr) {
	    imagePtr->instanceData = typePtr->getProc(imagePtr->tkwin,
		    masterPtr->masterData);
		    modelPtr->modelData);
	}
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		Tcl_GetHashKey(&winPtr->mainPtr->imageTable, hPtr), -1));
		(const char *)Tcl_GetHashKey(&winPtr->mainPtr->imageTable, hPtr), -1));
	break;
    }
    case IMAGE_DELETE:
	for (i = 2; i < objc; i++) {
	    arg = Tcl_GetString(objv[i]);
	    hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, arg);
	    if (hPtr == NULL) {
		goto alreadyDeleted;
	    }
	    masterPtr = Tcl_GetHashValue(hPtr);
	    if (masterPtr->deleted) {
	    modelPtr = (ImageModel *)Tcl_GetHashValue(hPtr);
	    if (modelPtr->deleted) {
		goto alreadyDeleted;
	    }
	    DeleteImage(masterPtr);
	    DeleteImage(modelPtr);
	}
	break;
    case IMAGE_NAMES:
	if (objc != 2) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	hPtr = Tcl_FirstHashEntry(&winPtr->mainPtr->imageTable, &search);
	resultObj = Tcl_NewObj();
	for ( ; hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
	    masterPtr = Tcl_GetHashValue(hPtr);
	    if (masterPtr->deleted) {
	    modelPtr = (ImageModel *)Tcl_GetHashValue(hPtr);
	    if (modelPtr->deleted) {
		continue;
	    }
	    Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewStringObj(
		    Tcl_GetHashKey(&winPtr->mainPtr->imageTable, hPtr), -1));
		    (const char *)Tcl_GetHashKey(&winPtr->mainPtr->imageTable, hPtr), -1));
	}
	Tcl_SetObjResult(interp, resultObj);
	break;
    case IMAGE_TYPES:
	if (objc != 2) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
445
446
447
448
449
450
451
452

453
454
455
456
457
458
459
460
461
462
463
464
465
466
467


468
469
470
471
472
473
474
475
476
477

478
479
480
481

482
483
484

485
486

487
488
489
490

491
492
493
494
495
496
497
443
444
445
446
447
448
449

450
451
452
453
454
455
456
457
458
459
460
461
462
463


464
465
466
467
468
469
470
471
472
473
474

475
476
477
478

479
480
481

482
483

484
485
486
487

488
489
490
491
492
493
494
495







-
+













-
-
+
+









-
+



-
+


-
+

-
+



-
+








    case IMAGE_HEIGHT:
    case IMAGE_INUSE:
    case IMAGE_TYPE:
    case IMAGE_WIDTH:
	/*
	 * These operations all parse virtually identically. First check to
	 * see if three args are given. Then get a non-deleted master from the
	 * see if three args are given. Then get a non-deleted model from the
	 * third arg.
	 */

	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "name");
	    return TCL_ERROR;
	}

	arg = Tcl_GetString(objv[2]);
	hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, arg);
	if (hPtr == NULL) {
	    goto alreadyDeleted;
	}
	masterPtr = Tcl_GetHashValue(hPtr);
	if (masterPtr->deleted) {
	modelPtr = (ImageModel *)Tcl_GetHashValue(hPtr);
	if (modelPtr->deleted) {
	    goto alreadyDeleted;
	}

	/*
	 * Now we read off the specific piece of data we were asked for.
	 */

	switch ((enum options) index) {
	case IMAGE_HEIGHT:
	    Tcl_SetObjResult(interp, Tcl_NewIntObj(masterPtr->height));
	    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(modelPtr->height));
	    break;
	case IMAGE_INUSE:
	    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(
		    masterPtr->typePtr && masterPtr->instancePtr));
		    modelPtr->typePtr && modelPtr->instancePtr));
	    break;
	case IMAGE_TYPE:
	    if (masterPtr->typePtr != NULL) {
	    if (modelPtr->typePtr != NULL) {
		Tcl_SetObjResult(interp,
			Tcl_NewStringObj(masterPtr->typePtr->name, -1));
			Tcl_NewStringObj(modelPtr->typePtr->name, -1));
	    }
	    break;
	case IMAGE_WIDTH:
	    Tcl_SetObjResult(interp, Tcl_NewIntObj(masterPtr->width));
	    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(modelPtr->width));
	    break;
	default:
	    Tcl_Panic("can't happen");
	}
	break;
    }
    return TCL_OK;
519
520
521
522
523
524
525
526

527
528
529
530
531
532
533
534
535
536
537

538
539
540
541
542



543
544
545
546
547
548
549
550
551
552
553
554

555
556
557
558

559
560
561
562
563
564
565
566
567
568

569
570

571
572

573
574
575

576
577
578
579
580
581
582
517
518
519
520
521
522
523

524
525
526
527
528
529
530
531
532
533
534

535
536
537



538
539
540
541
542
543
544
545
546
547
548
549
550
551

552
553
554
555

556
557
558
559
560
561
562
563
564
565

566
567

568
569

570
571
572

573
574
575
576
577
578
579
580







-
+










-
+


-
-
-
+
+
+











-
+



-
+









-
+

-
+

-
+


-
+







 *	redisplay themselves as appropriate.
 *
 *----------------------------------------------------------------------
 */

void
Tk_ImageChanged(
    Tk_ImageMaster imageMaster,	/* Image that needs redisplay. */
    Tk_ImageModel imageModel,	/* Image that needs redisplay. */
    int x, int y,		/* Coordinates of upper-left pixel of region
				 * of image that needs to be redrawn. */
    int width, int height,	/* Dimensions (in pixels) of region of image
				 * to redraw. If either dimension is zero then
				 * the image doesn't need to be redrawn
				 * (perhaps all that happened is that its size
				 * changed). */
    int imageWidth, int imageHeight)
				/* New dimensions of image. */
{
    ImageMaster *masterPtr = (ImageMaster *) imageMaster;
    ImageModel *modelPtr = (ImageModel *) imageModel;
    Image *imagePtr;

    masterPtr->width = imageWidth;
    masterPtr->height = imageHeight;
    for (imagePtr = masterPtr->instancePtr; imagePtr != NULL;
    modelPtr->width = imageWidth;
    modelPtr->height = imageHeight;
    for (imagePtr = modelPtr->instancePtr; imagePtr != NULL;
	    imagePtr = imagePtr->nextPtr) {
	imagePtr->changeProc(imagePtr->widgetClientData, x, y, width, height,
		imageWidth, imageHeight);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tk_NameOfImage --
 *
 *	Given a token for an image master, this function returns the name of
 *	Given a token for an image model, this function returns the name of
 *	the image.
 *
 * Results:
 *	The return value is the string name for imageMaster.
 *	The return value is the string name for imageModel.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

const char *
Tk_NameOfImage(
    Tk_ImageMaster imageMaster)	/* Token for image. */
    Tk_ImageModel imageModel)	/* Token for image. */
{
    ImageMaster *masterPtr = (ImageMaster *) imageMaster;
    ImageModel *modelPtr = (ImageModel *) imageModel;

    if (masterPtr->hPtr == NULL) {
    if (modelPtr->hPtr == NULL) {
	return NULL;
    }
    return Tcl_GetHashKey(masterPtr->tablePtr, masterPtr->hPtr);
    return (const char *)Tcl_GetHashKey(modelPtr->tablePtr, modelPtr->hPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * Tk_GetImage --
 *
606
607
608
609
610
611
612
613

614
615
616
617
618
619
620
621


622
623
624

625
626
627

628
629
630

631
632

633
634
635
636


637
638
639
640
641
642
643
604
605
606
607
608
609
610

611
612
613
614
615
616
617


618
619
620
621

622
623
624

625
626
627

628
629

630
631
632


633
634
635
636
637
638
639
640
641







-
+






-
-
+
+


-
+


-
+


-
+

-
+


-
-
+
+







    const char *name,		/* Name of desired image. */
    Tk_ImageChangedProc *changeProc,
				/* Function to invoke when redisplay is needed
				 * because image's pixels or size changed. */
    ClientData clientData)	/* One-word argument to pass to damageProc. */
{
    Tcl_HashEntry *hPtr;
    ImageMaster *masterPtr;
    ImageModel *modelPtr;
    Image *imagePtr;

    hPtr = Tcl_FindHashEntry(&((TkWindow *) tkwin)->mainPtr->imageTable, name);
    if (hPtr == NULL) {
	goto noSuchImage;
    }
    masterPtr = Tcl_GetHashValue(hPtr);
    if (masterPtr->typePtr == NULL) {
    modelPtr = (ImageModel *)Tcl_GetHashValue(hPtr);
    if (modelPtr->typePtr == NULL) {
	goto noSuchImage;
    }
    if (masterPtr->deleted) {
    if (modelPtr->deleted) {
	goto noSuchImage;
    }
    imagePtr = ckalloc(sizeof(Image));
    imagePtr = (Image *)ckalloc(sizeof(Image));
    imagePtr->tkwin = tkwin;
    imagePtr->display = Tk_Display(tkwin);
    imagePtr->masterPtr = masterPtr;
    imagePtr->modelPtr = modelPtr;
    imagePtr->instanceData =
	    masterPtr->typePtr->getProc(tkwin, masterPtr->masterData);
	    modelPtr->typePtr->getProc(tkwin, modelPtr->modelData);
    imagePtr->changeProc = changeProc;
    imagePtr->widgetClientData = clientData;
    imagePtr->nextPtr = masterPtr->instancePtr;
    masterPtr->instancePtr = imagePtr;
    imagePtr->nextPtr = modelPtr->instancePtr;
    modelPtr->instancePtr = imagePtr;
    return (Tk_Image) imagePtr;

  noSuchImage:
    if (interp) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"image \"%s\" doesn't exist", name));
	Tcl_SetErrorCode(interp, "TK", "LOOKUP", "IMAGE", name, NULL);
665
666
667
668
669
670
671
672

673
674
675
676
677
678
679
680


681
682
683

684
685

686
687
688
689
690
691
692
693
694
695
696


697
698
699
700
701



702
703
704


705
706
707
708
709
710
711
663
664
665
666
667
668
669

670
671
672
673
674
675
676


677
678
679
680

681
682

683
684
685
686
687
688
689
690
691
692


693
694
695
696



697
698
699
700


701
702
703
704
705
706
707
708
709







-
+






-
-
+
+


-
+

-
+









-
-
+
+


-
-
-
+
+
+

-
-
+
+








void
Tk_FreeImage(
    Tk_Image image)		/* Token for image that is no longer needed by
				 * a widget. */
{
    Image *imagePtr = (Image *) image;
    ImageMaster *masterPtr = imagePtr->masterPtr;
    ImageModel *modelPtr = imagePtr->modelPtr;
    Image *prevPtr;

    /*
     * Clean up the particular instance.
     */

    if (masterPtr->typePtr != NULL) {
	masterPtr->typePtr->freeProc(imagePtr->instanceData,
    if (modelPtr->typePtr != NULL) {
	modelPtr->typePtr->freeProc(imagePtr->instanceData,
		imagePtr->display);
    }
    prevPtr = masterPtr->instancePtr;
    prevPtr = modelPtr->instancePtr;
    if (prevPtr == imagePtr) {
	masterPtr->instancePtr = imagePtr->nextPtr;
	modelPtr->instancePtr = imagePtr->nextPtr;
    } else {
	while (prevPtr->nextPtr != imagePtr) {
	    prevPtr = prevPtr->nextPtr;
	}
	prevPtr->nextPtr = imagePtr->nextPtr;
    }
    ckfree(imagePtr);

    /*
     * If there are no more instances left for the master, and if the master
     * image has been deleted, then delete the master too.
     * If there are no more instances left for the model, and if the model
     * image has been deleted, then delete the model too.
     */

    if ((masterPtr->typePtr == NULL) && (masterPtr->instancePtr == NULL)) {
	if (masterPtr->hPtr != NULL) {
	    Tcl_DeleteHashEntry(masterPtr->hPtr);
    if ((modelPtr->typePtr == NULL) && (modelPtr->instancePtr == NULL)) {
	if (modelPtr->hPtr != NULL) {
	    Tcl_DeleteHashEntry(modelPtr->hPtr);
	}
	Tcl_Release(masterPtr->winPtr);
	ckfree(masterPtr);
	Tcl_Release(modelPtr->winPtr);
	ckfree(modelPtr);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tk_PostscriptImage --
737
738
739
740
741
742
743
744

745
746

747
748
749
750
751
752
753
754
755
756
757
758
759



760
761
762
763
764
765
766
735
736
737
738
739
740
741

742
743

744
745
746
747
748
749
750
751
752
753
754



755
756
757
758
759
760
761
762
763
764







-
+

-
+










-
-
-
+
+
+







    Image *imagePtr = (Image *) image;
    int result;
    XImage *ximage;
    Pixmap pmap;
    GC newGC;
    XGCValues gcValues;

    if (imagePtr->masterPtr->typePtr == NULL) {
    if (imagePtr->modelPtr->typePtr == NULL) {
	/*
	 * No master for image, so nothing to display on postscript.
	 * No model for image, so nothing to display on postscript.
	 */

	return TCL_OK;
    }

    /*
     * Check if an image specific postscript-generation function exists;
     * otherwise go on with generic code.
     */

    if (imagePtr->masterPtr->typePtr->postscriptProc != NULL) {
	return imagePtr->masterPtr->typePtr->postscriptProc(
		imagePtr->masterPtr->masterData, interp, tkwin, psinfo,
    if (imagePtr->modelPtr->typePtr->postscriptProc != NULL) {
	return imagePtr->modelPtr->typePtr->postscriptProc(
		imagePtr->modelPtr->modelData, interp, tkwin, psinfo,
		x, y, width, height, prepass);
    }

    if (prepass) {
	return TCL_OK;
    }

833
834
835
836
837
838
839
840

841
842

843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863


864
865
866


867
868

869
870
871
872
873
874
875
831
832
833
834
835
836
837

838
839

840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859


860
861
862


863
864
865

866
867
868
869
870
871
872
873







-
+

-
+



















-
-
+
+

-
-
+
+

-
+







				 * the Tk_GetImage call for the image. */
    int drawableX, int drawableY)
				/* Coordinates in drawable that correspond to
				 * imageX and imageY. */
{
    Image *imagePtr = (Image *) image;

    if (imagePtr->masterPtr->typePtr == NULL) {
    if (imagePtr->modelPtr->typePtr == NULL) {
	/*
	 * No master for image, so nothing to display.
	 * No model for image, so nothing to display.
	 */

	return;
    }

    /*
     * Clip the redraw area to the area of the image.
     */

    if (imageX < 0) {
	width += imageX;
	drawableX -= imageX;
	imageX = 0;
    }
    if (imageY < 0) {
	height += imageY;
	drawableY -= imageY;
	imageY = 0;
    }
    if ((imageX + width) > imagePtr->masterPtr->width) {
	width = imagePtr->masterPtr->width - imageX;
    if ((imageX + width) > imagePtr->modelPtr->width) {
	width = imagePtr->modelPtr->width - imageX;
    }
    if ((imageY + height) > imagePtr->masterPtr->height) {
	height = imagePtr->masterPtr->height - imageY;
    if ((imageY + height) > imagePtr->modelPtr->height) {
	height = imagePtr->modelPtr->height - imageY;
    }
    imagePtr->masterPtr->typePtr->displayProc(imagePtr->instanceData,
    imagePtr->modelPtr->typePtr->displayProc(imagePtr->instanceData,
	    imagePtr->display, drawable, imageX, imageY, width, height,
	    drawableX, drawableY);
}

/*
 *----------------------------------------------------------------------
 *
891
892
893
894
895
896
897
898
899


900
901
902
903
904
905
906
889
890
891
892
893
894
895


896
897
898
899
900
901
902
903
904







-
-
+
+







Tk_SizeOfImage(
    Tk_Image image,		/* Token for image whose size is wanted. */
    int *widthPtr,		/* Return width of image here. */
    int *heightPtr)		/* Return height of image here. */
{
    Image *imagePtr = (Image *) image;

    *widthPtr = imagePtr->masterPtr->width;
    *heightPtr = imagePtr->masterPtr->height;
    *widthPtr = imagePtr->modelPtr->width;
    *heightPtr = imagePtr->modelPtr->height;
}

/*
 *----------------------------------------------------------------------
 *
 * Tk_DeleteImage --
 *
929
930
931
932
933
934
935
936

937
938
939
940
941
942
943
944
945
946
947
948
949
950
951

952
953
954
955
956
957
958
959

960
961
962
963
964
965


966
967

968
969
970
971
972


973
974

975
976
977
978



979
980
981


982
983

984
985
986
987
988
989
990
927
928
929
930
931
932
933

934
935
936
937
938
939
940
941
942
943
944
945
946
947
948

949
950
951
952
953
954
955
956

957
958
959
960
961


962
963
964

965
966
967
968


969
970
971

972
973



974
975
976
977


978
979
980

981
982
983
984
985
986
987
988







-
+














-
+







-
+




-
-
+
+

-
+



-
-
+
+

-
+

-
-
-
+
+
+

-
-
+
+

-
+







    if (winPtr == NULL) {
	return;
    }
    hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, name);
    if (hPtr == NULL) {
	return;
    }
    DeleteImage(Tcl_GetHashValue(hPtr));
    DeleteImage((ImageModel *)Tcl_GetHashValue(hPtr));
}

/*
 *----------------------------------------------------------------------
 *
 * DeleteImage --
 *
 *	This function is responsible for deleting an image.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The connection is dropped between instances of this image and an image
 *	master. Image instances will redisplay themselves as empty areas, but
 *	model. Image instances will redisplay themselves as empty areas, but
 *	existing instances will not be deleted.
 *
 *----------------------------------------------------------------------
 */

static void
DeleteImage(
    ImageMaster *masterPtr)	/* Pointer to main data structure for image. */
    ImageModel *modelPtr)	/* Pointer to main data structure for image. */
{
    Image *imagePtr;
    Tk_ImageType *typePtr;

    typePtr = masterPtr->typePtr;
    masterPtr->typePtr = NULL;
    typePtr = modelPtr->typePtr;
    modelPtr->typePtr = NULL;
    if (typePtr != NULL) {
	for (imagePtr = masterPtr->instancePtr; imagePtr != NULL;
	for (imagePtr = modelPtr->instancePtr; imagePtr != NULL;
		imagePtr = imagePtr->nextPtr) {
	    typePtr->freeProc(imagePtr->instanceData, imagePtr->display);
	    imagePtr->changeProc(imagePtr->widgetClientData, 0, 0,
		    masterPtr->width, masterPtr->height, masterPtr->width,
		    masterPtr->height);
		    modelPtr->width, modelPtr->height, modelPtr->width,
		    modelPtr->height);
	}
	typePtr->deleteProc(masterPtr->masterData);
	typePtr->deleteProc(modelPtr->modelData);
    }
    if (masterPtr->instancePtr == NULL) {
	if (masterPtr->hPtr != NULL) {
	    Tcl_DeleteHashEntry(masterPtr->hPtr);
    if (modelPtr->instancePtr == NULL) {
	if (modelPtr->hPtr != NULL) {
	    Tcl_DeleteHashEntry(modelPtr->hPtr);
	}
	Tcl_Release(masterPtr->winPtr);
	ckfree(masterPtr);
	Tcl_Release(modelPtr->winPtr);
	ckfree(modelPtr);
    } else {
	masterPtr->deleted = 1;
	modelPtr->deleted = 1;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * EventuallyDeleteImage --
1000
1001
1002
1003
1004
1005
1006
1007

1008
1009
1010
1011
1012

1013
1014
1015
1016



1017
1018
1019
1020
1021
1022
1023
998
999
1000
1001
1002
1003
1004

1005
1006
1007
1008
1009

1010
1011



1012
1013
1014
1015
1016
1017
1018
1019
1020
1021







-
+




-
+

-
-
-
+
+
+







 *	ill effects.
 *
 *----------------------------------------------------------------------
 */

static void
EventuallyDeleteImage(
    ImageMaster *masterPtr,	/* Pointer to main data structure for image. */
    ImageModel *modelPtr,	/* Pointer to main data structure for image. */
    int forgetImageHashNow)	/* Flag to say whether the hash table is about
				 * to vanish. */
{
    if (forgetImageHashNow) {
	masterPtr->hPtr = NULL;
	modelPtr->hPtr = NULL;
    }
    if (!masterPtr->deleted) {
	masterPtr->deleted = 1;
	Tcl_EventuallyFree(masterPtr, (Tcl_FreeProc *) DeleteImage);
    if (!modelPtr->deleted) {
	modelPtr->deleted = 1;
	Tcl_EventuallyFree(modelPtr, (Tcl_FreeProc *) DeleteImage);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TkDeleteAllImages --
1041
1042
1043
1044
1045
1046
1047
1048

1049
1050
1051
1052
1053
1054
1055
1056

1057
1058
1059

1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074

1075
1076
1077
1078
1079
1080
1081
1082
1083
1084

1085
1086
1087
1088
1089
1090
1091
1092


1093
1094
1095
1096
1097


1098
1099
1100
1101
1102
1103
1104
1039
1040
1041
1042
1043
1044
1045

1046
1047
1048
1049
1050
1051
1052
1053

1054
1055
1056

1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071

1072
1073
1074
1075
1076
1077
1078
1079
1080
1081

1082
1083
1084
1085
1086
1087
1088


1089
1090
1091
1092
1093


1094
1095
1096
1097
1098
1099
1100
1101
1102







-
+







-
+


-
+














-
+









-
+






-
-
+
+



-
-
+
+







				 * going away. */
{
    Tcl_HashSearch search;
    Tcl_HashEntry *hPtr;

    for (hPtr = Tcl_FirstHashEntry(&mainPtr->imageTable, &search);
	    hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
	EventuallyDeleteImage(Tcl_GetHashValue(hPtr), 1);
	EventuallyDeleteImage((ImageModel *)Tcl_GetHashValue(hPtr), 1);
    }
    Tcl_DeleteHashTable(&mainPtr->imageTable);
}

/*
 *----------------------------------------------------------------------
 *
 * Tk_GetImageMasterData --
 * Tk_GetImageModelData --
 *
 *	Given the name of an image, this function returns the type of the
 *	image and the clientData associated with its master.
 *	image and the clientData associated with its model.
 *
 * Results:
 *	If there is no image by the given name, then NULL is returned and a
 *	NULL value is stored at *typePtrPtr. Otherwise the return value is the
 *	clientData returned by the createProc when the image was created and a
 *	pointer to the type structure for the image is stored at *typePtrPtr.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

ClientData
Tk_GetImageMasterData(
Tk_GetImageModelData(
    Tcl_Interp *interp,		/* Interpreter in which the image was
				 * created. */
    const char *name,		/* Name of image. */
    const Tk_ImageType **typePtrPtr)
				/* Points to location to fill in with pointer
				 * to type information for image. */
{
    TkWindow *winPtr = (TkWindow *) Tk_MainWindow(interp);
    Tcl_HashEntry *hPtr;
    ImageMaster *masterPtr;
    ImageModel *modelPtr;

    hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, name);
    if (hPtr == NULL) {
	*typePtrPtr = NULL;
	return NULL;
    }
    masterPtr = Tcl_GetHashValue(hPtr);
    if (masterPtr->deleted) {
    modelPtr = (ImageModel *)Tcl_GetHashValue(hPtr);
    if (modelPtr->deleted) {
	*typePtrPtr = NULL;
	return NULL;
    }
    *typePtrPtr = masterPtr->typePtr;
    return masterPtr->masterData;
    *typePtrPtr = modelPtr->typePtr;
    return modelPtr->modelData;
}

/*
 *----------------------------------------------------------------------
 *
 * Tk_SetTSOrigin --
 *
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1112
1113
1114
1115
1116
1117
1118

1119
1120
1121
1122
1123
1124
1125







-







 * Side Effects:
 *	The GCTileStipOrigin is reset in the GC. This will cause the tile
 *	origin to change when the GC is used for drawing.
 *
 *----------------------------------------------------------------------
 */

/*ARGSUSED*/
void
Tk_SetTSOrigin(
    Tk_Window tkwin,
    GC gc,
    int x, int y)
{
    while (!Tk_TopWinHierarchy(tkwin)) {
Changes to generic/tkImgBmap.c.
1
2
3
4
5
6
7
8



9
10
11
12
13
14
15
16
17

18
19
20
21
22


23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44


45
46
47
48
49
50
51
52

53
54

55
56
57
58
59
60
61
62
63
64
65
66
67
68

69
70
71
72
73
74
75
76
77
78
79

80
81
82
83
84
85
86
1
2
3
4
5



6
7
8
9
10
11
12
13
14
15
16

17
18
19
20


21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42


43
44
45
46
47
48
49
50
51

52
53

54
55
56
57
58
59
60
61
62
63
64
65
66
67

68
69
70
71
72
73
74
75
76
77
78

79
80
81
82
83
84
85
86





-
-
-
+
+
+








-
+



-
-
+
+




















-
-
+
+







-
+

-
+













-
+










-
+







/*
 * 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.
 */

#include "tkInt.h"

/*
 * The following data structure represents the master for a bitmap
 * The following data structure represents the model for a bitmap
 * image:
 */

typedef struct BitmapMaster {
    Tk_ImageMaster tkMaster;	/* Tk's token for image master. NULL means the
typedef struct {
    Tk_ImageModel tkModel;	/* Tk's token for image model. NULL means the
				 * image is being deleted. */
    Tcl_Interp *interp;		/* Interpreter for application that is using
				 * image. */
    Tcl_Command imageCmd;	/* Token for image command (used to delete it
				 * when the image goes away). NULL means the
				 * image command has already been deleted. */
    int width, height;		/* Dimensions of image. */
    char *data;			/* Data comprising bitmap (suitable for input
				 * to XCreateBitmapFromData). May be NULL if
				 * no data. Malloc'ed. */
    char *maskData;		/* Data for bitmap's mask (suitable for input
				 * to XCreateBitmapFromData). Malloc'ed. */
    Tk_Uid fgUid;		/* Value of -foreground option (malloc'ed). */
    Tk_Uid bgUid;		/* Value of -background option (malloc'ed). */
    char *fileString;		/* Value of -file option (malloc'ed). */
    char *dataString;		/* Value of -data option (malloc'ed). */
    char *maskFileString;	/* Value of -maskfile option (malloc'ed). */
    char *maskDataString;	/* Value of -maskdata option (malloc'ed). */
    struct BitmapInstance *instancePtr;
				/* First in list of all instances associated
				 * with this master. */
} BitmapMaster;
				 * with this model. */
} BitmapModel;

/*
 * The following data structure represents all of the instances of an image
 * that lie within a particular window:
 */

typedef struct BitmapInstance {
    int refCount;		/* Number of instances that share this data
    size_t refCount;		/* Number of instances that share this data
				 * structure. */
    BitmapMaster *masterPtr;	/* Pointer to master for image. */
    BitmapModel *modelPtr;	/* Pointer to model for image. */
    Tk_Window tkwin;		/* Window in which the instances will be
				 * displayed. */
    XColor *fg;			/* Foreground color for displaying image. */
    XColor *bg;			/* Background color for displaying image. */
    Pixmap bitmap;		/* The bitmap to display. */
    Pixmap mask;		/* Mask: only display bitmap pixels where
				 * there are 1's here. */
    GC gc;			/* Graphics context for displaying bitmap.
				 * None means there was an error while setting
				 * up the instance, so it cannot be
				 * displayed. */
    struct BitmapInstance *nextPtr;
				/* Next in list of all instance structures
				 * associated with masterPtr (NULL means end
				 * associated with modelPtr (NULL means end
				 * of list). */
} BitmapInstance;

/*
 * The type record for bitmap images:
 */

static int		GetByte(Tcl_Channel chan);
static int		ImgBmapCreate(Tcl_Interp *interp,
			    const char *name, int argc, Tcl_Obj *const objv[],
			    const Tk_ImageType *typePtr, Tk_ImageMaster master,
			    const Tk_ImageType *typePtr, Tk_ImageModel model,
			    ClientData *clientDataPtr);
static ClientData	ImgBmapGet(Tk_Window tkwin, ClientData clientData);
static void		ImgBmapDisplay(ClientData clientData,
			    Display *display, Drawable drawable,
			    int imageX, int imageY, int width, int height,
			    int drawableX, int drawableY);
static void		ImgBmapFree(ClientData clientData, Display *display);
104
105
106
107
108
109
110
111

112
113

114
115

116
117

118
119

120
121

122
123
124
125
126
127
128
104
105
106
107
108
109
110

111
112

113
114

115
116

117
118

119
120

121
122
123
124
125
126
127
128







-
+

-
+

-
+

-
+

-
+

-
+








/*
 * Information used for parsing configuration specs:
 */

static const Tk_ConfigSpec configSpecs[] = {
    {TK_CONFIG_UID, "-background", NULL, NULL,
	"", Tk_Offset(BitmapMaster, bgUid), 0, NULL},
	"", offsetof(BitmapModel, bgUid), 0, NULL},
    {TK_CONFIG_STRING, "-data", NULL, NULL,
	NULL, Tk_Offset(BitmapMaster, dataString), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(BitmapModel, dataString), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_STRING, "-file", NULL, NULL,
	NULL, Tk_Offset(BitmapMaster, fileString), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(BitmapModel, fileString), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_UID, "-foreground", NULL, NULL,
	"#000000", Tk_Offset(BitmapMaster, fgUid), 0, NULL},
	"#000000", offsetof(BitmapModel, fgUid), 0, NULL},
    {TK_CONFIG_STRING, "-maskdata", NULL, NULL,
	NULL, Tk_Offset(BitmapMaster, maskDataString), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(BitmapModel, maskDataString), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_STRING, "-maskfile", NULL, NULL,
	NULL, Tk_Offset(BitmapMaster, maskFileString), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(BitmapModel, maskFileString), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL}
};

/*
 * The following data structure is used to describe the state of parsing a
 * bitmap file or string. It is used for communication between TkGetBitmapData
 * and NextBitmapWord.
145
146
147
148
149
150
151
152

153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182

183
184
185
186
187


188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
















205
206
207

208
209
210
211
212
213
214

215
216
217
218
219
220
221
222

223
224
225
226
227
228
229
230
231
232
233


234
235
236
237
238
239
240
241
242

243
244
245
246
247
248
249
250


251
252
253
254
255
256
257
258
259
260
261
262
263



264
265
266
267
268
269





270
271
272
273
274
275



276
277
278
279
280




281
282

283
284
285
286
287


288
289

290
291
292
293
294
295
296





297
298

299
300
301
302
303
304
305
306
307
308
309
310

311
312
313
314
315


316
317
318
319
320
321
322
323
324
325
326


327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343

344
345
346
347
348
349
350
351

352
353
354
355
356
357



358
359
360
361
362
363
364
365
366
367
368
369
370


371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391

392
393
394
395
396


397
398

399
400
401
402
403


404
405
406
407
408
409
410
411
412
413

414
415
416
417
418
419
420
145
146
147
148
149
150
151

152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171

172
173
174
175
176
177
178
179
180

181
182
183
184
185

186
187
188
















189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206

207
208
209
210
211
212
213

214
215
216
217
218
219
220
221

222
223
224
225
226
227
228
229
230
231


232
233
234
235
236
237
238
239
240
241

242
243
244
245
246
247
248


249
250
251
252
253
254
255
256
257
258
259
260



261
262
263
264





265
266
267
268
269
270
271
272



273
274
275
276




277
278
279
280
281

282
283
284
285


286
287
288

289
290
291





292
293
294
295
296
297

298
299
300
301
302
303
304
305
306
307
308
309

310
311
312
313


314
315
316
317
318
319
320
321
322
323
324


325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342

343
344
345
346
347
348
349
350

351
352
353
354



355
356
357
358
359
360
361
362
363
364
365
366
367
368


369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390

391
392
393
394


395
396
397

398
399
400
401


402
403
404
405
406
407
408
409
410
411
412

413
414
415
416
417
418
419
420







-
+



















-









-
+




-
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
+






-
+







-
+









-
-
+
+








-
+






-
-
+
+










-
-
-
+
+
+

-
-
-
-
-
+
+
+
+
+



-
-
-
+
+
+

-
-
-
-
+
+
+
+

-
+



-
-
+
+

-
+


-
-
-
-
-
+
+
+
+
+

-
+











-
+



-
-
+
+









-
-
+
+
















-
+







-
+



-
-
-
+
+
+











-
-
+
+




















-
+



-
-
+
+

-
+



-
-
+
+









-
+







 * Prototypes for procedures used only locally in this file:
 */

static int		ImgBmapCmd(ClientData clientData, Tcl_Interp *interp,
			    int argc, Tcl_Obj *const objv[]);
static void		ImgBmapCmdDeletedProc(ClientData clientData);
static void		ImgBmapConfigureInstance(BitmapInstance *instancePtr);
static int		ImgBmapConfigureMaster(BitmapMaster *masterPtr,
static int		ImgBmapConfigureModel(BitmapModel *modelPtr,
			    int argc, Tcl_Obj *const objv[], int flags);
static int		NextBitmapWord(ParseInfo *parseInfoPtr);

/*
 *----------------------------------------------------------------------
 *
 * ImgBmapCreate --
 *
 *	This procedure is called by the Tk image code to create "test" images.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	The data structure for a new image is allocated.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
ImgBmapCreate(
    Tcl_Interp *interp,		/* Interpreter for application containing
				 * image. */
    const char *name,			/* Name to use for image. */
    int argc,			/* Number of arguments. */
    Tcl_Obj *const argv[],	/* Argument objects for options (doesn't
				 * include image name or type). */
    const Tk_ImageType *typePtr,/* Pointer to our type record (not used). */
    Tk_ImageMaster master,	/* Token for image, to be used by us in later
    Tk_ImageModel model,	/* Token for image, to be used by us in later
				 * callbacks. */
    ClientData *clientDataPtr)	/* Store manager's token for image here; it
				 * will be returned in later callbacks. */
{
    BitmapMaster *masterPtr = ckalloc(sizeof(BitmapMaster));
    BitmapModel *modelPtr = (BitmapModel *)ckalloc(sizeof(BitmapModel));
    (void)typePtr;

    masterPtr->tkMaster = master;
    masterPtr->interp = interp;
    masterPtr->imageCmd = Tcl_CreateObjCommand(interp, name, ImgBmapCmd,
	    masterPtr, ImgBmapCmdDeletedProc);
    masterPtr->width = masterPtr->height = 0;
    masterPtr->data = NULL;
    masterPtr->maskData = NULL;
    masterPtr->fgUid = NULL;
    masterPtr->bgUid = NULL;
    masterPtr->fileString = NULL;
    masterPtr->dataString = NULL;
    masterPtr->maskFileString = NULL;
    masterPtr->maskDataString = NULL;
    masterPtr->instancePtr = NULL;
    if (ImgBmapConfigureMaster(masterPtr, argc, argv, 0) != TCL_OK) {
	ImgBmapDelete(masterPtr);
    modelPtr->tkModel = model;
    modelPtr->interp = interp;
    modelPtr->imageCmd = Tcl_CreateObjCommand(interp, name, ImgBmapCmd,
	    modelPtr, ImgBmapCmdDeletedProc);
    modelPtr->width = modelPtr->height = 0;
    modelPtr->data = NULL;
    modelPtr->maskData = NULL;
    modelPtr->fgUid = NULL;
    modelPtr->bgUid = NULL;
    modelPtr->fileString = NULL;
    modelPtr->dataString = NULL;
    modelPtr->maskFileString = NULL;
    modelPtr->maskDataString = NULL;
    modelPtr->instancePtr = NULL;
    if (ImgBmapConfigureModel(modelPtr, argc, argv, 0) != TCL_OK) {
	ImgBmapDelete(modelPtr);
	return TCL_ERROR;
    }
    *clientDataPtr = masterPtr;
    *clientDataPtr = modelPtr;
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * ImgBmapConfigureMaster --
 * ImgBmapConfigureModel --
 *
 *	This procedure is called when a bitmap image is created or
 *	reconfigured. It process configuration options and resets any
 *	instances of the image.
 *
 * Results:
 *	A standard Tcl return value. If TCL_ERROR is returned then an error
 *	message is left in the masterPtr->interp's result.
 *	message is left in the modelPtr->interp's result.
 *
 * Side effects:
 *	Existing instances of the image will be redisplayed to match the new
 *	configuration options.
 *
 *----------------------------------------------------------------------
 */

static int
ImgBmapConfigureMaster(
    BitmapMaster *masterPtr,	/* Pointer to data structure describing
ImgBmapConfigureModel(
    BitmapModel *modelPtr,	/* Pointer to data structure describing
				 * overall bitmap image to (reconfigure). */
    int objc,			/* Number of entries in objv. */
    Tcl_Obj *const objv[],	/* Pairs of configuration options for image. */
    int flags)			/* Flags to pass to Tk_ConfigureWidget, such
				 * as TK_CONFIG_ARGV_ONLY. */
{
    BitmapInstance *instancePtr;
    int maskWidth, maskHeight, dummy1, dummy2;
    const char **argv = ckalloc((objc+1) * sizeof(char *));
    const char **argv = (const char **)ckalloc((objc+1) * sizeof(char *));

    for (dummy1 = 0; dummy1 < objc; dummy1++) {
	argv[dummy1] = Tcl_GetString(objv[dummy1]);
    }
    argv[objc] = NULL;

    if (Tk_ConfigureWidget(masterPtr->interp, Tk_MainWindow(masterPtr->interp),
	    configSpecs, objc, argv, (char *) masterPtr, flags) != TCL_OK) {
    if (Tk_ConfigureWidget(modelPtr->interp, Tk_MainWindow(modelPtr->interp),
	    configSpecs, objc, argv, (char *) modelPtr, flags) != TCL_OK) {
	ckfree(argv);
	return TCL_ERROR;
    }
    ckfree(argv);

    /*
     * Parse the bitmap and/or mask to create binary data. Make sure that the
     * bitmap and mask have the same dimensions.
     */

    if (masterPtr->data != NULL) {
	ckfree(masterPtr->data);
	masterPtr->data = NULL;
    if (modelPtr->data != NULL) {
	ckfree(modelPtr->data);
	modelPtr->data = NULL;
    }
    if ((masterPtr->fileString != NULL) || (masterPtr->dataString != NULL)) {
	masterPtr->data = TkGetBitmapData(masterPtr->interp,
		masterPtr->dataString, masterPtr->fileString,
		&masterPtr->width, &masterPtr->height, &dummy1, &dummy2);
	if (masterPtr->data == NULL) {
    if ((modelPtr->fileString != NULL) || (modelPtr->dataString != NULL)) {
	modelPtr->data = TkGetBitmapData(modelPtr->interp,
		modelPtr->dataString, modelPtr->fileString,
		&modelPtr->width, &modelPtr->height, &dummy1, &dummy2);
	if (modelPtr->data == NULL) {
	    return TCL_ERROR;
	}
    }
    if (masterPtr->maskData != NULL) {
	ckfree(masterPtr->maskData);
	masterPtr->maskData = NULL;
    if (modelPtr->maskData != NULL) {
	ckfree(modelPtr->maskData);
	modelPtr->maskData = NULL;
    }
    if ((masterPtr->maskFileString != NULL)
	    || (masterPtr->maskDataString != NULL)) {
	if (masterPtr->data == NULL) {
	    Tcl_SetObjResult(masterPtr->interp, Tcl_NewStringObj(
    if ((modelPtr->maskFileString != NULL)
	    || (modelPtr->maskDataString != NULL)) {
	if (modelPtr->data == NULL) {
	    Tcl_SetObjResult(modelPtr->interp, Tcl_NewStringObj(
		    "can't have mask without bitmap", -1));
	    Tcl_SetErrorCode(masterPtr->interp, "TK", "IMAGE", "BITMAP",
	    Tcl_SetErrorCode(modelPtr->interp, "TK", "IMAGE", "BITMAP",
		    "NO_BITMAP", NULL);
	    return TCL_ERROR;
	}
	masterPtr->maskData = TkGetBitmapData(masterPtr->interp,
		masterPtr->maskDataString, masterPtr->maskFileString,
	modelPtr->maskData = TkGetBitmapData(modelPtr->interp,
		modelPtr->maskDataString, modelPtr->maskFileString,
		&maskWidth, &maskHeight, &dummy1, &dummy2);
	if (masterPtr->maskData == NULL) {
	if (modelPtr->maskData == NULL) {
	    return TCL_ERROR;
	}
	if ((maskWidth != masterPtr->width)
		|| (maskHeight != masterPtr->height)) {
	    ckfree(masterPtr->maskData);
	    masterPtr->maskData = NULL;
	    Tcl_SetObjResult(masterPtr->interp, Tcl_NewStringObj(
	if ((maskWidth != modelPtr->width)
		|| (maskHeight != modelPtr->height)) {
	    ckfree(modelPtr->maskData);
	    modelPtr->maskData = NULL;
	    Tcl_SetObjResult(modelPtr->interp, Tcl_NewStringObj(
		    "bitmap and mask have different sizes", -1));
	    Tcl_SetErrorCode(masterPtr->interp, "TK", "IMAGE", "BITMAP",
	    Tcl_SetErrorCode(modelPtr->interp, "TK", "IMAGE", "BITMAP",
		    "MASK_SIZE", NULL);
	    return TCL_ERROR;
	}
    }

    /*
     * Cycle through all of the instances of this image, regenerating the
     * information for each instance. Then force the image to be redisplayed
     * everywhere that it is used.
     */

    for (instancePtr = masterPtr->instancePtr; instancePtr != NULL;
    for (instancePtr = modelPtr->instancePtr; instancePtr != NULL;
	    instancePtr = instancePtr->nextPtr) {
	ImgBmapConfigureInstance(instancePtr);
    }
    Tk_ImageChanged(masterPtr->tkMaster, 0, 0, masterPtr->width,
	    masterPtr->height, masterPtr->width, masterPtr->height);
    Tk_ImageChanged(modelPtr->tkModel, 0, 0, modelPtr->width,
	    modelPtr->height, modelPtr->width, modelPtr->height);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * ImgBmapConfigureInstance --
 *
 *	This procedure is called to create displaying information for a bitmap
 *	image instance based on the configuration information in the master.
 *	It is invoked both when new instances are created and when the master
 *	image instance based on the configuration information in the model.
 *	It is invoked both when new instances are created and when the model
 *	is reconfigured.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Generates errors via Tcl_BackgroundException if there are problems in
 *	setting up the instance.
 *
 *----------------------------------------------------------------------
 */

static void
ImgBmapConfigureInstance(
    BitmapInstance *instancePtr)/* Instance to reconfigure. */
{
    BitmapMaster *masterPtr = instancePtr->masterPtr;
    BitmapModel *modelPtr = instancePtr->modelPtr;
    XColor *colorPtr;
    XGCValues gcValues;
    GC gc;
    unsigned int mask;
    Pixmap oldBitmap, oldMask;

    /*
     * For each of the options in masterPtr, translate the string form into an
     * For each of the options in modelPtr, translate the string form into an
     * internal form appropriate for instancePtr.
     */

    if (*masterPtr->bgUid != 0) {
	colorPtr = Tk_GetColor(masterPtr->interp, instancePtr->tkwin,
		masterPtr->bgUid);
    if (*modelPtr->bgUid != 0) {
	colorPtr = Tk_GetColor(modelPtr->interp, instancePtr->tkwin,
		modelPtr->bgUid);
	if (colorPtr == NULL) {
	    goto error;
	}
    } else {
	colorPtr = NULL;
    }
    if (instancePtr->bg != NULL) {
	Tk_FreeColor(instancePtr->bg);
    }
    instancePtr->bg = colorPtr;

    colorPtr = Tk_GetColor(masterPtr->interp, instancePtr->tkwin,
	    masterPtr->fgUid);
    colorPtr = Tk_GetColor(modelPtr->interp, instancePtr->tkwin,
	    modelPtr->fgUid);
    if (colorPtr == NULL) {
	goto error;
    }
    if (instancePtr->fg != NULL) {
	Tk_FreeColor(instancePtr->fg);
    }
    instancePtr->fg = colorPtr;

    /*
     * Careful: We have to allocate new Pixmaps before deleting the old ones.
     * Otherwise, The XID allocator will always return the same XID for the
     * new Pixmaps as was used for the old Pixmaps. And that will prevent the
     * data and/or mask from changing in the GC below.
     */

    oldBitmap = instancePtr->bitmap;
    instancePtr->bitmap = None;
    oldMask = instancePtr->mask;
    instancePtr->mask = None;

    if (masterPtr->data != NULL) {
    if (modelPtr->data != NULL) {
	instancePtr->bitmap = XCreateBitmapFromData(
		Tk_Display(instancePtr->tkwin),
		RootWindowOfScreen(Tk_Screen(instancePtr->tkwin)),
		masterPtr->data, (unsigned) masterPtr->width,
		(unsigned) masterPtr->height);
		modelPtr->data, (unsigned) modelPtr->width,
		(unsigned) modelPtr->height);
    }
    if (masterPtr->maskData != NULL) {
    if (modelPtr->maskData != NULL) {
	instancePtr->mask = XCreateBitmapFromData(
		Tk_Display(instancePtr->tkwin),
		RootWindowOfScreen(Tk_Screen(instancePtr->tkwin)),
		masterPtr->maskData, (unsigned) masterPtr->width,
		(unsigned) masterPtr->height);
		modelPtr->maskData, (unsigned) modelPtr->width,
		(unsigned) modelPtr->height);
    }

    if (oldMask != None) {
	Tk_FreePixmap(Tk_Display(instancePtr->tkwin), oldMask);
    }
    if (oldBitmap != None) {
	Tk_FreePixmap(Tk_Display(instancePtr->tkwin), oldBitmap);
    }

    if (masterPtr->data != NULL) {
    if (modelPtr->data != NULL) {
	gcValues.foreground = instancePtr->fg->pixel;
	gcValues.graphics_exposures = False;
	mask = GCForeground|GCGraphicsExposures;
	if (instancePtr->bg != NULL) {
	    gcValues.background = instancePtr->bg->pixel;
	    mask |= GCBackground;
	    if (instancePtr->mask != None) {
441
442
443
444
445
446
447
448

449
450
451


452
453
454
455
456
457
458
441
442
443
444
445
446
447

448
449


450
451
452
453
454
455
456
457
458







-
+

-
-
+
+







     * it clear that this instance cannot be displayed. Then report the error.
     */

    if (instancePtr->gc != NULL) {
	Tk_FreeGC(Tk_Display(instancePtr->tkwin), instancePtr->gc);
    }
    instancePtr->gc = NULL;
    Tcl_AppendObjToErrorInfo(masterPtr->interp, Tcl_ObjPrintf(
    Tcl_AppendObjToErrorInfo(modelPtr->interp, Tcl_ObjPrintf(
	    "\n    (while configuring image \"%s\")", Tk_NameOfImage(
	    masterPtr->tkMaster)));
    Tcl_BackgroundException(masterPtr->interp, TCL_ERROR);
	    modelPtr->tkModel)));
    Tcl_BackgroundException(modelPtr->interp, TCL_ERROR);
}

/*
 *----------------------------------------------------------------------
 *
 * TkGetBitmapData --
 *
616
617
618
619
620
621
622
623

624
625
626
627
628
629
630
616
617
618
619
620
621
622

623
624
625
626
627
628
629
630







-
+







     */

  getData:
    if ((width <= 0) || (height <= 0)) {
	goto error;
    }
    numBytes = ((width+7)/8) * height;
    data = ckalloc(numBytes);
    data = (char *)ckalloc(numBytes);
    for (p = data; numBytes > 0; p++, numBytes--) {
	if (NextBitmapWord(&pi) != TCL_OK) {
	    goto error;
	}
	*p = (char) strtol(pi.word, &end, 0);
	if (end == pi.word) {
	    goto error;
747
748
749
750
751
752
753
754

755
756
757
758
759
760

761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778

779
780
781
782

783
784
785

786
787
788

789
790
791
792
793
794
795
747
748
749
750
751
752
753

754
755
756
757
758
759

760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777

778
779
780
781

782
783
784

785
786
787

788
789
790
791
792
793
794
795







-
+





-
+

















-
+



-
+


-
+


-
+







 *	See the user documentation.
 *
 *--------------------------------------------------------------
 */

static int
ImgBmapCmd(
    ClientData clientData,	/* Information about the image master. */
    ClientData clientData,	/* Information about the image model. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    static const char *const bmapOptions[] = {"cget", "configure", NULL};
    BitmapMaster *masterPtr = clientData;
    BitmapModel *modelPtr = (BitmapModel *)clientData;
    int index;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
	return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObjStruct(interp, objv[1], bmapOptions,
	    sizeof(char *), "option", 0, &index) != TCL_OK) {
	return TCL_ERROR;
    }
    switch (index) {
    case 0: /* cget */
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "option");
	    return TCL_ERROR;
	}
	return Tk_ConfigureValue(interp, Tk_MainWindow(interp), configSpecs,
		(char *) masterPtr, Tcl_GetString(objv[2]), 0);
		(char *) modelPtr, Tcl_GetString(objv[2]), 0);
    case 1: /* configure */
	if (objc == 2) {
	    return Tk_ConfigureInfo(interp, Tk_MainWindow(interp),
		    configSpecs, (char *) masterPtr, NULL, 0);
		    configSpecs, (char *) modelPtr, NULL, 0);
	} else if (objc == 3) {
	    return Tk_ConfigureInfo(interp, Tk_MainWindow(interp),
		    configSpecs, (char *) masterPtr,
		    configSpecs, (char *) modelPtr,
		    Tcl_GetString(objv[2]), 0);
	} else {
	    return ImgBmapConfigureMaster(masterPtr, objc-2, objv+2,
	    return ImgBmapConfigureModel(modelPtr, objc-2, objv+2,
		    TK_CONFIG_ARGV_ONLY);
	}
    default:
	Tcl_Panic("bad const entries to bmapOptions in ImgBmapCmd");
	return TCL_OK;
    }
}
812
813
814
815
816
817
818
819

820
821
822

823
824
825
826
827
828
829
830

831
832
833
834
835
836
837
838
839
840
841
842
843

844
845

846
847
848
849
850
851
852
853


854
855
856
857
858
859
860
861
862


863
864
865
866
867
868
869
812
813
814
815
816
817
818

819
820
821

822
823
824
825
826
827
828
829

830
831
832
833
834
835
836
837
838
839
840
841
842

843
844

845
846
847
848
849
850
851


852
853
854
855
856
857
858
859
860


861
862
863
864
865
866
867
868
869







-
+


-
+







-
+












-
+

-
+






-
-
+
+







-
-
+
+







 *----------------------------------------------------------------------
 */

static ClientData
ImgBmapGet(
    Tk_Window tkwin,		/* Window in which the instance will be
				 * used. */
    ClientData masterData)	/* Pointer to our master structure for the
    ClientData modelData)	/* Pointer to our model structure for the
				 * image. */
{
    BitmapMaster *masterPtr = masterData;
    BitmapModel *modelPtr = (BitmapModel *)modelData;
    BitmapInstance *instancePtr;

    /*
     * See if there is already an instance for this window. If so then just
     * re-use it.
     */

    for (instancePtr = masterPtr->instancePtr; instancePtr != NULL;
    for (instancePtr = modelPtr->instancePtr; instancePtr != NULL;
	    instancePtr = instancePtr->nextPtr) {
	if (instancePtr->tkwin == tkwin) {
	    instancePtr->refCount++;
	    return instancePtr;
	}
    }

    /*
     * The image isn't already in use in this window. Make a new instance of
     * the image.
     */

    instancePtr = ckalloc(sizeof(BitmapInstance));
    instancePtr = (BitmapInstance *)ckalloc(sizeof(BitmapInstance));
    instancePtr->refCount = 1;
    instancePtr->masterPtr = masterPtr;
    instancePtr->modelPtr = modelPtr;
    instancePtr->tkwin = tkwin;
    instancePtr->fg = NULL;
    instancePtr->bg = NULL;
    instancePtr->bitmap = None;
    instancePtr->mask = None;
    instancePtr->gc = NULL;
    instancePtr->nextPtr = masterPtr->instancePtr;
    masterPtr->instancePtr = instancePtr;
    instancePtr->nextPtr = modelPtr->instancePtr;
    modelPtr->instancePtr = instancePtr;
    ImgBmapConfigureInstance(instancePtr);

    /*
     * If this is the first instance, must set the size of the image.
     */

    if (instancePtr->nextPtr == NULL) {
	Tk_ImageChanged(masterPtr->tkMaster, 0, 0, 0, 0, masterPtr->width,
		masterPtr->height);
	Tk_ImageChanged(modelPtr->tkModel, 0, 0, 0, 0, modelPtr->width,
		modelPtr->height);
    }

    return instancePtr;
}

/*
 *----------------------------------------------------------------------
890
891
892
893
894
895
896
897

898
899
900
901
902
903
904
890
891
892
893
894
895
896

897
898
899
900
901
902
903
904







-
+







    int imageX, int imageY,	/* Upper-left corner of region within image to
				 * draw. */
    int width, int height,	/* Dimensions of region within image to draw. */
    int drawableX, int drawableY)
				/* Coordinates within drawable that correspond
				 * to imageX and imageY. */
{
    BitmapInstance *instancePtr = clientData;
    BitmapInstance *instancePtr = (BitmapInstance *)clientData;
    int masking;

    /*
     * If there's no graphics context, it means that an error occurred while
     * creating the image instance so it can't be displayed.
     */

944
945
946
947
948
949
950
951

952
953
954
955

956
957
958
959
960
961
962
944
945
946
947
948
949
950

951
952
953


954
955
956
957
958
959
960
961







-
+


-
-
+








static void
ImgBmapFree(
    ClientData clientData,	/* Pointer to BitmapInstance structure for
				 * instance to be displayed. */
    Display *display)		/* Display containing window that used image. */
{
    BitmapInstance *instancePtr = clientData;
    BitmapInstance *instancePtr = (BitmapInstance *)clientData;
    BitmapInstance *prevPtr;

    instancePtr->refCount--;
    if (instancePtr->refCount > 0) {
    if (instancePtr->refCount-- > 1) {
	return;
    }

    /*
     * There are no more uses of the image within this widget. Free the
     * instance structure.
     */
972
973
974
975
976
977
978
979
980


981
982

983
984
985
986
987
988
989
990
991
992
993
994
995
996

997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010

1011
1012
1013

1014
1015

1016
1017
1018
1019
1020



1021
1022
1023


1024
1025
1026


1027
1028
1029


1030
1031
1032
1033
1034
1035
1036
971
972
973
974
975
976
977


978
979
980

981
982
983
984
985
986
987
988
989
990
991
992
993
994

995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008

1009
1010
1011

1012
1013

1014
1015
1016



1017
1018
1019
1020


1021
1022
1023


1024
1025
1026


1027
1028
1029
1030
1031
1032
1033
1034
1035







-
-
+
+

-
+













-
+













-
+


-
+

-
+


-
-
-
+
+
+

-
-
+
+

-
-
+
+

-
-
+
+







    }
    if (instancePtr->mask != None) {
	Tk_FreePixmap(display, instancePtr->mask);
    }
    if (instancePtr->gc != NULL) {
	Tk_FreeGC(display, instancePtr->gc);
    }
    if (instancePtr->masterPtr->instancePtr == instancePtr) {
	instancePtr->masterPtr->instancePtr = instancePtr->nextPtr;
    if (instancePtr->modelPtr->instancePtr == instancePtr) {
	instancePtr->modelPtr->instancePtr = instancePtr->nextPtr;
    } else {
	for (prevPtr = instancePtr->masterPtr->instancePtr;
	for (prevPtr = instancePtr->modelPtr->instancePtr;
		prevPtr->nextPtr != instancePtr; prevPtr = prevPtr->nextPtr) {
	    /* Empty loop body */
	}
	prevPtr->nextPtr = instancePtr->nextPtr;
    }
    ckfree(instancePtr);
}

/*
 *----------------------------------------------------------------------
 *
 * ImgBmapDelete --
 *
 *	This procedure is called by the image code to delete the master
 *	This procedure is called by the image code to delete the model
 *	structure for an image.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Resources associated with the image get freed.
 *
 *----------------------------------------------------------------------
 */

static void
ImgBmapDelete(
    ClientData masterData)	/* Pointer to BitmapMaster structure for
    ClientData modelData)	/* Pointer to BitmapModel structure for
				 * image. Must not have any more instances. */
{
    BitmapMaster *masterPtr = masterData;
    BitmapModel *modelPtr = (BitmapModel *)modelData;

    if (masterPtr->instancePtr != NULL) {
    if (modelPtr->instancePtr != NULL) {
	Tcl_Panic("tried to delete bitmap image when instances still exist");
    }
    masterPtr->tkMaster = NULL;
    if (masterPtr->imageCmd != NULL) {
	Tcl_DeleteCommandFromToken(masterPtr->interp, masterPtr->imageCmd);
    modelPtr->tkModel = NULL;
    if (modelPtr->imageCmd != NULL) {
	Tcl_DeleteCommandFromToken(modelPtr->interp, modelPtr->imageCmd);
    }
    if (masterPtr->data != NULL) {
	ckfree(masterPtr->data);
    if (modelPtr->data != NULL) {
	ckfree(modelPtr->data);
    }
    if (masterPtr->maskData != NULL) {
	ckfree(masterPtr->maskData);
    if (modelPtr->maskData != NULL) {
	ckfree(modelPtr->maskData);
    }
    Tk_FreeOptions(configSpecs, (char *) masterPtr, NULL, 0);
    ckfree(masterPtr);
    Tk_FreeOptions(configSpecs, (char *) modelPtr, NULL, 0);
    ckfree(modelPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * ImgBmapCmdDeletedProc --
 *
1044
1045
1046
1047
1048
1049
1050
1051

1052
1053
1054

1055
1056
1057
1058



1059
1060
1061
1062
1063
1064
1065
1043
1044
1045
1046
1047
1048
1049

1050
1051
1052

1053
1054



1055
1056
1057
1058
1059
1060
1061
1062
1063
1064







-
+


-
+

-
-
-
+
+
+







 *	The image is deleted.
 *
 *----------------------------------------------------------------------
 */

static void
ImgBmapCmdDeletedProc(
    ClientData clientData)	/* Pointer to BitmapMaster structure for
    ClientData clientData)	/* Pointer to BitmapModel structure for
				 * image. */
{
    BitmapMaster *masterPtr = clientData;
    BitmapModel *modelPtr = (BitmapModel *)clientData;

    masterPtr->imageCmd = NULL;
    if (masterPtr->tkMaster != NULL) {
	Tk_DeleteImage(masterPtr->interp, Tk_NameOfImage(masterPtr->tkMaster));
    modelPtr->imageCmd = NULL;
    if (modelPtr->tkModel != NULL) {
	Tk_DeleteImage(modelPtr->interp, Tk_NameOfImage(modelPtr->tkModel));
    }
}

/*
 *----------------------------------------------------------------------
 *
 * GetByte --
1076
1077
1078
1079
1080
1081
1082
1083

1084
1085
1086

1087
1088
1089
1090
1091
1092
1093
1075
1076
1077
1078
1079
1080
1081

1082
1083
1084

1085
1086
1087
1088
1089
1090
1091
1092







-
+


-
+







 */

static int
GetByte(
    Tcl_Channel chan)	/* The channel we read from. */
{
    char buffer;
    int size;
    size_t size;

    size = Tcl_Read(chan, &buffer, 1);
    if (size <= 0) {
    if (size != 1) {
	return EOF;
    } else {
	return buffer;
    }
}

/*
1194
1195
1196
1197
1198
1199
1200
1201

1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213

1214
1215
1216
1217
1218
1219
1220
1221
1222
1223

1224
1225
1226
1227
1228
1229
1230
1193
1194
1195
1196
1197
1198
1199

1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211

1212
1213
1214
1215
1216
1217
1218
1219
1220
1221

1222
1223
1224
1225
1226
1227
1228
1229







-
+











-
+









-
+







    ClientData clientData,
    Tcl_Interp *interp,
    Tk_Window tkwin,
    Tk_PostscriptInfo psinfo,
    int x, int y, int width, int height,
    int prepass)
{
    BitmapMaster *masterPtr = clientData;
    BitmapModel *modelPtr = (BitmapModel *)clientData;
    Tcl_InterpState interpState;
    Tcl_Obj *psObj;

    if (prepass) {
	return TCL_OK;
    }

    /*
     * There is nothing to do for bitmaps with zero width or height.
     */

    if (width<=0 || height<=0 || masterPtr->width<=0 || masterPtr->height<=0){
    if (width<=0 || height<=0 || modelPtr->width<=0 || modelPtr->height<=0){
	return TCL_OK;
    }

    /*
     * Some postscript implementations cannot handle bitmap strings longer
     * than about 60k characters. If the bitmap data is that big or bigger,
     * we bail out.
     */

    if (masterPtr->width*masterPtr->height > 60000) {
    if (modelPtr->width*modelPtr->height > 60000) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"unable to generate postscript for bitmaps larger than 60000"
		" pixels", -1));
	Tcl_SetErrorCode(interp, "TK", "CANVAS", "PS", "MEMLIMIT", NULL);
	return TCL_ERROR;
    }

1255
1256
1257
1258
1259
1260
1261
1262

1263
1264
1265

1266
1267
1268
1269
1270
1271
1272
1273

1274
1275
1276
1277
1278
1279


1280
1281
1282
1283
1284
1285
1286
1287

1288
1289
1290

1291
1292
1293
1294
1295
1296
1297
1298
1299


1300
1301
1302
1303
1304
1305
1306
1254
1255
1256
1257
1258
1259
1260

1261
1262
1263

1264
1265
1266
1267
1268
1269
1270
1271

1272
1273
1274
1275
1276


1277
1278
1279
1280
1281
1282
1283
1284
1285

1286
1287
1288

1289
1290
1291
1292
1293
1294
1295
1296


1297
1298
1299
1300
1301
1302
1303
1304
1305







-
+


-
+







-
+




-
-
+
+







-
+


-
+







-
-
+
+







     * Color the background, if there is one. This step is skipped if the
     * background is transparent. If the background is not transparent and
     * there is no background mask, then color the complete rectangle that
     * encloses the bitmap. If there is a background mask, then only apply
     * color to the bits specified by the mask.
     */

    if ((masterPtr->bgUid != NULL) && (masterPtr->bgUid[0] != '\000')) {
    if ((modelPtr->bgUid != NULL) && (modelPtr->bgUid[0] != '\000')) {
	XColor color;

	TkParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), masterPtr->bgUid,
	TkParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), modelPtr->bgUid,
		&color);
	Tcl_ResetResult(interp);
	if (Tk_PostscriptColor(interp, psinfo, &color) != TCL_OK) {
	    goto error;
	}
	Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));

	if (masterPtr->maskData == NULL) {
	if (modelPtr->maskData == NULL) {
	    Tcl_AppendToObj(psObj,
		    "0 0 moveto 1 0 rlineto 0 1 rlineto -1 0 rlineto "
		    "closepath fill\n", -1);
	} else {
	    ImgBmapPsImagemask(psObj, masterPtr->width, masterPtr->height,
		    masterPtr->maskData);
	    ImgBmapPsImagemask(psObj, modelPtr->width, modelPtr->height,
		    modelPtr->maskData);
	}
    }

    /*
     * Draw the bitmap foreground, assuming there is one.
     */

    if ((masterPtr->fgUid != NULL) && (masterPtr->data != NULL)) {
    if ((modelPtr->fgUid != NULL) && (modelPtr->data != NULL)) {
	XColor color;

	TkParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), masterPtr->fgUid,
	TkParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), modelPtr->fgUid,
		&color);
	Tcl_ResetResult(interp);
	if (Tk_PostscriptColor(interp, psinfo, &color) != TCL_OK) {
	    goto error;
	}
	Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));

	ImgBmapPsImagemask(psObj, masterPtr->width, masterPtr->height,
		masterPtr->data);
	ImgBmapPsImagemask(psObj, modelPtr->width, modelPtr->height,
		modelPtr->data);
    }

    /*
     * Plug the accumulated postscript back into the result.
     */

    (void) Tcl_RestoreInterpState(interp, interpState);
Changes to generic/tkImgGIF.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14




15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10




11
12
13
14
15
16
17
18
19
20
21










-
-
-
-
+
+
+
+







/*
 * tkImgGIF.c --
 *
 *	A photo image file handler for GIF files. Reads 87a and 89a GIF files.
 *	At present, there only is a file write function. GIF images may be
 *	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 ([email protected]), 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 ([email protected]), 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
 * copyrighted as follows:
 *
51
52
53
54
55
56
57
58

59
60
61
62
63
64
65
51
52
53
54
55
56
57

58
59
60
61
62
63
64
65







-
+







 * state keeps track of which byte we are about to read, or EOF.
 */

typedef struct mFile {
    unsigned char *data;	/* mmencoded source string */
    int c;			/* bits left over from previous character */
    int state;			/* decoder state (0-4 or GIF_DONE) */
    int length;			/* Total amount of bytes in data */
    size_t length;			/* Total amount of bytes in data */
} MFile;

/*
 * Non-ASCII encoding support:
 * Most data in a GIF image is binary and is treated as such. However, a few
 * key bits are stashed in ASCII. If we try to compare those pieces to the
 * char they represent, it will fail on any non-ASCII (eg, EBCDIC) system. To
107
108
109
110
111
112
113
114
115


116
117
118
119
120
121
122
107
108
109
110
111
112
113


114
115
116
117
118
119
120
121
122







-
-
+
+







} GIFImageConfig;

/*
 * Type of a function used to do the writing to a file or buffer when
 * serializing in the GIF format.
 */

typedef int (WriteBytesFunc) (ClientData clientData, const char *bytes,
			    int byteCount);
typedef size_t (WriteBytesFunc) (ClientData clientData, const char *bytes,
			    size_t byteCount);

/*
 * The format record for the GIF file format:
 */

static int		FileMatchGIF(Tcl_Channel chan, const char *fileName,
			    Tcl_Obj *format, int *widthPtr, int *heightPtr,
183
184
185
186
187
188
189
190

191
192

193
194
195
196
197

198
199
200
201
202
203
204
183
184
185
186
187
188
189

190
191

192
193
194
195
196

197
198
199
200
201
202
203
204







-
+

-
+




-
+







			    unsigned char cmap[MAXCOLORMAPSIZE][4], int srcX,
			    int srcY, int interlace, int transparent);

/*
 * these are for the BASE64 image reader code only
 */

static int		Fread(GIFImageConfig *gifConfPtr, unsigned char *dst,
static size_t		Fread(GIFImageConfig *gifConfPtr, unsigned char *dst,
			    size_t size, size_t count, Tcl_Channel chan);
static int		Mread(unsigned char *dst, size_t size, size_t count,
static size_t		Mread(unsigned char *dst, size_t size, size_t count,
			    MFile *handle);
static int		Mgetc(MFile *handle);
static int		char64(int c);
static void		mInit(unsigned char *string, MFile *handle,
			    int length);
			    size_t length);

/*
 * Types, defines and variables needed to write and compress a GIF.
 */

#define LSB(a)		((unsigned char) (((short)(a)) & 0x00FF))
#define MSB(a)		((unsigned char) (((short)(a)) >> 8))
347
348
349
350
351
352
353
354

355
356



357
358
359
360
361
362
363
347
348
349
350
351
352
353

354
355
356
357
358
359
360
361
362
363
364
365
366







-
+


+
+
+







FileMatchGIF(
    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. */
    int *widthPtr, int *heightPtr,
				/* The dimensions of the image are returned
				 * here if the file is a valid raw GIF file. */
    Tcl_Interp *interp)		/* not used */
    Tcl_Interp *dummy)		/* not used */
{
    GIFImageConfig gifConf;
    (void)fileName;
    (void)format;
    (void)dummy;

    memset(&gifConf, 0, sizeof(GIFImageConfig));
    return ReadGIFHeader(&gifConf, chan, widthPtr, heightPtr);
}

/*
 *----------------------------------------------------------------------
593
594
595
596
597
598
599
600

601
602
603
604
605
606
607
596
597
598
599
600
601
602

603
604
605
606
607
608
609
610







-
+







	     */

	    if (trashBuffer == NULL) {
		if (fileWidth > (int)((UINT_MAX/3)/fileHeight)) {
		    goto error;
		}
		nBytes = fileWidth * fileHeight * 3;
		trashBuffer = ckalloc(nBytes);
		trashBuffer = (unsigned char *)ckalloc(nBytes);
		if (trashBuffer) {
		    memset(trashBuffer, 0, nBytes);
		}
	    }

	    /*
	     * Slurp! Process the data for this image and stuff it in a trash
688
689
690
691
692
693
694
695

696
697
698
699
700
701
702
691
692
693
694
695
696
697

698
699
700
701
702
703
704
705







-
+







	    goto error;
	}
	block.pitch = block.pixelSize * imageWidth;
	if (imageHeight > (int)(UINT_MAX/block.pitch)) {
	    goto error;
	}
	nBytes = block.pitch * imageHeight;
	block.pixelPtr = ckalloc(nBytes);
	block.pixelPtr = (unsigned char *)ckalloc(nBytes);
	if (block.pixelPtr) {
	    memset(block.pixelPtr, 0, nBytes);
	}

	if (ReadImage(gifConfPtr, interp, block.pixelPtr, chan, imageWidth,
		imageHeight, colorMap, srcX, srcY, BitSet(buf[8], INTERLACE),
		transparent) != TCL_OK) {
750
751
752
753
754
755
756
757

758
759
760

761


762
763

764
765
766
767
768
769
770
753
754
755
756
757
758
759

760
761
762

763
764
765
766
767

768
769
770
771
772
773
774
775







-
+


-
+

+
+

-
+








static int
StringMatchGIF(
    Tcl_Obj *dataObj,		/* the object containing the image data */
    Tcl_Obj *format,		/* the image format object, or NULL */
    int *widthPtr,		/* where to put the string width */
    int *heightPtr,		/* where to put the string height */
    Tcl_Interp *interp)		/* not used */
    Tcl_Interp *dummy)		/* not used */
{
    unsigned char *data, header[10];
    int got, length;
    TkSizeT got, length;
    MFile handle;
    (void)format;
    (void)dummy;

    data = Tcl_GetByteArrayFromObj(dataObj, &length);
    data = TkGetByteArrayFromObj(dataObj, &length);

    /*
     * Header is a minimum of 10 bytes.
     */

    if (length < 10) {
	return 0;
822
823
824
825
826
827
828
829

830
831

832
833
834
835
836
837
838
827
828
829
830
831
832
833

834
835

836
837
838
839
840
841
842
843







-
+

-
+







    Tcl_Obj *format,		/* format object, or 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)
{
    MFile handle, *hdlPtr = &handle;
    int length;
    TkSizeT length;
    const char *xferFormat;
    unsigned char *data = Tcl_GetByteArrayFromObj(dataObj, &length);
    unsigned char *data = TkGetByteArrayFromObj(dataObj, &length);

    mInit(data, hdlPtr, length);

    /*
     * Check whether the data is Base64 encoded by doing a character-by-
     * charcter comparison with the binary-format headers; BASE64-encoded
     * never matches (matching the other way is harder because of potential
913
914
915
916
917
918
919
920

921
922
923
924
925
926
927
918
919
920
921
922
923
924

925
926
927
928
929
930
931
932







-
+







    int number,
    unsigned char buffer[MAXCOLORMAPSIZE][4])
{
    int i;
    unsigned char rgb[3];

    for (i = 0; i < number; ++i) {
	if (Fread(gifConfPtr, rgb, sizeof(rgb), 1, chan) <= 0) {
	if (((size_t)Fread(gifConfPtr, rgb, sizeof(rgb), 1, chan) + 1) < 2) {
	    return 0;
	}

	if (buffer) {
	    buffer[i][CM_RED] = rgb[0];
	    buffer[i][CM_GREEN] = rgb[1];
	    buffer[i][CM_BLUE] = rgb[2];
979
980
981
982
983
984
985
986

987
988
989
990

991
992
993
994
995
996
997
984
985
986
987
988
989
990

991
992
993
994

995
996
997
998
999
1000
1001
1002







-
+



-
+







GetDataBlock(
    GIFImageConfig *gifConfPtr,
    Tcl_Channel chan,
    unsigned char *buf)
{
    unsigned char count;

    if (Fread(gifConfPtr, &count, 1, 1, chan) <= 0) {
    if (((size_t)Fread(gifConfPtr, &count, 1, 1, chan) + 1) < 2) {
	return -1;
    }

    if ((count != 0) && (Fread(gifConfPtr, buf, count, 1, chan) <= 0)) {
    if ((count != 0) && (((size_t)Fread(gifConfPtr, buf, count, 1, chan) + 1) < 2)) {
	return -1;
    }

    return count;
}

/*
1031
1032
1033
1034
1035
1036
1037
1038

1039
1040
1041
1042
1043
1044

1045
1046


1047
1048
1049
1050
1051
1052

1053
1054
1055
1056
1057
1058
1059
1036
1037
1038
1039
1040
1041
1042

1043
1044
1045
1046
1047
1048

1049
1050
1051
1052
1053
1054
1055
1056
1057
1058

1059
1060
1061
1062
1063
1064
1065
1066







-
+





-
+


+
+





-
+







    unsigned char cmap[MAXCOLORMAPSIZE][4],
    int srcX, int srcY,
    int interlace,
    int transparent)
{
    unsigned char initialCodeSize;
    int xpos = 0, ypos = 0, pass = 0, i, count;
    register unsigned char *pixelPtr;
    unsigned char *pixelPtr;
    static const int interlaceStep[] = { 8, 8, 4, 2 };
    static const int interlaceStart[] = { 0, 4, 2, 1 };
    unsigned short prefix[(1 << MAX_LWZ_BITS)];
    unsigned char append[(1 << MAX_LWZ_BITS)];
    unsigned char stack[(1 << MAX_LWZ_BITS)*2];
    register unsigned char *top;
    unsigned char *top;
    int codeSize, clearCode, inCode, endCode, oldCode, maxCode;
    int code, firstCode, v;
    (void)srcX;
    (void)srcY;

    /*
     * Initialize the decoder
     */

    if (Fread(gifConfPtr, &initialCodeSize, 1, 1, chan) <= 0) {
    if (((size_t)Fread(gifConfPtr, &initialCodeSize, 1, 1, chan) + 1) < 2) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"error reading GIF image: %s", Tcl_PosixError(interp)));
	return TCL_ERROR;
    }

    if (initialCodeSize > MAX_LWZ_BITS) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("malformed image", -1));
1388
1389
1390
1391
1392
1393
1394
1395

1396
1397
1398
1399
1400
1401
1402
1395
1396
1397
1398
1399
1400
1401

1402
1403
1404
1405
1406
1407
1408
1409







-
+







 *----------------------------------------------------------------------
 */

static void
mInit(
    unsigned char *string,	/* string containing initial mmencoded data */
    MFile *handle,		/* mmdecode "file" handle */
    int length)			/* Number of bytes in string */
    size_t length)			/* Number of bytes in string */
{
    handle->data = string;
    handle->state = 0;
    handle->c = 0;
    handle->length = length;
}

1414
1415
1416
1417
1418
1419
1420
1421

1422
1423
1424
1425
1426
1427
1428
1429


1430
1431
1432
1433
1434
1435
1436
1421
1422
1423
1424
1425
1426
1427

1428
1429
1430
1431
1432
1433
1434


1435
1436
1437
1438
1439
1440
1441
1442
1443







-
+






-
-
+
+







 *
 * Side effects:
 *	The base64 handle will change state.
 *
 *----------------------------------------------------------------------
 */

static int
static size_t
Mread(
    unsigned char *dst,		/* where to put the result */
    size_t chunkSize,		/* size of each transfer */
    size_t numChunks,		/* number of chunks */
    MFile *handle)		/* mmdecode "file" handle */
{
    register int i, c;
    int count = chunkSize * numChunks;
    int c;
    size_t i, count = chunkSize * numChunks;

    for (i=0; i<count && (c=Mgetc(handle)) != GIF_DONE; i++) {
	*dst++ = c;
    }
    return i;
}

1563
1564
1565
1566
1567
1568
1569
1570

1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585


1586
1587

1588
1589
1590

1591
1592
1593
1594
1595
1596
1597

1598
1599
1600
1601
1602
1603
1604
1570
1571
1572
1573
1574
1575
1576

1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590


1591
1592
1593

1594
1595
1596

1597
1598
1599
1600
1601
1602
1603

1604
1605
1606
1607
1608
1609
1610
1611







-
+













-
-
+
+

-
+


-
+






-
+







 *	a base64 encoded string.
 *
 * Results: - same as POSIX fread() or Tcl Tcl_Read()
 *
 *----------------------------------------------------------------------
 */

static int
static size_t
Fread(
    GIFImageConfig *gifConfPtr,
    unsigned char *dst,		/* where to put the result */
    size_t hunk, size_t count,	/* how many */
    Tcl_Channel chan)
{
    if (gifConfPtr->fromData == INLINE_DATA_BASE64) {
	return Mread(dst, hunk, count, (MFile *) chan);
    }

    if (gifConfPtr->fromData == INLINE_DATA_BINARY) {
	MFile *handle = (MFile *) chan;

	if (handle->length <= 0 || (size_t) handle->length < hunk*count) {
	    return -1;
	if ((handle->length + 1 < 2) || (handle->length < hunk*count)) {
	    return (size_t)-1;
	}
	memcpy(dst, handle->data, (size_t) (hunk * count));
	memcpy(dst, handle->data, hunk * count);
	handle->data += hunk * count;
	handle->length -= hunk * count;
	return (int)(hunk * count);
	return hunk * count;
    }

    /*
     * Otherwise we've got a real file to read.
     */

    return Tcl_Read(chan, (char *) dst, (int) (hunk * count));
    return Tcl_Read(chan, (char *) dst, hunk * count);
}

/*
 * ChanWriteGIF - writes a image in GIF format.
 *-------------------------------------------------------------------------
 * Author:		Lolo
 *			Engeneering Projects Area
1669
1670
1671
1672
1673
1674
1675
1676

1677
1678
1679
1680

1681
1682

1683
1684
1685
1686
1687

1688
1689
1690
1691

1692
1693

1694
1695
1696
1697
1698
1699
1700
1676
1677
1678
1679
1680
1681
1682

1683
1684
1685
1686

1687
1688

1689
1690
1691
1692
1693

1694
1695
1696
1697

1698
1699

1700
1701
1702
1703
1704
1705
1706
1707







-
+



-
+

-
+




-
+



-
+

-
+







    if (result == TCL_OK) {
	Tcl_SetObjResult(interp, objPtr);
    }
    Tcl_DecrRefCount(objPtr);
    return result;
}

static int
static size_t
WriteToChannel(
    ClientData clientData,
    const char *bytes,
    int byteCount)
    size_t byteCount)
{
    Tcl_Channel handle = clientData;
    Tcl_Channel handle = (Tcl_Channel)clientData;

    return Tcl_Write(handle, bytes, byteCount);
}

static int
static size_t
WriteToByteArray(
    ClientData clientData,
    const char *bytes,
    int byteCount)
    size_t byteCount)
{
    Tcl_Obj *objPtr = clientData;
    Tcl_Obj *objPtr = (Tcl_Obj *)clientData;
    Tcl_Obj *tmpObj = Tcl_NewByteArrayObj((unsigned char *) bytes, byteCount);

    Tcl_IncrRefCount(tmpObj);
    Tcl_AppendObjToObj(objPtr, tmpObj);
    Tcl_DecrRefCount(tmpObj);
    return byteCount;
}
1708
1709
1710
1711
1712
1713
1714

1715
1716
1717
1718
1719
1720
1721
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729







+







    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));

    state.pixelSize = blockPtr->pixelSize;
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162



2163
2164
2165
2166
2167
2168
2169
2161
2162
2163
2164
2165
2166
2167



2168
2169
2170
2171
2172
2173
2174
2175
2176
2177







-
-
-
+
+
+







}

static void
ClearHashTable(			/* Reset code table. */
    GIFState_t *statePtr,
    int hSize)
{
    register int *hashTablePtr = statePtr->hashTable + hSize;
    register long i;
    register long m1 = -1;
    int *hashTablePtr = statePtr->hashTable + hSize;
    long i;
    long m1 = -1;

    i = hSize - 16;
    do {			/* might use Sys V memset(3) here */
	*(hashTablePtr-16) = m1;
	*(hashTablePtr-15) = m1;
	*(hashTablePtr-14) = m1;
	*(hashTablePtr-13) = m1;
Added generic/tkImgListFormat.c.

























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
 * tkImgListFormat.c --
 *
 *      Implements the default image data format. I.e. the format used for
 *      [imageName data] and [imageName put] if no other format is specified.
 *
 *      The default format consits of a list of scan lines (rows) with each
 *      list element being itself a list of pixels (or columns). For details,
 *      see the manpage photo.n
 *
 *      This image format cannot read/write files, it is meant for string
 *      data only.
 *
 *
 * 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:
 *      Paul Mackerras ([email protected]),
 *              Department of Computer Science,
 *              Australian National University.
 *
 *      Simon Bachmann ([email protected])
 */


#include "tkImgPhoto.h"

/*
 * Message to generate when an attempt to allocate memory for an image fails.
 */

#define TK_PHOTO_ALLOC_FAILURE_MESSAGE \
        "not enough free memory for image buffer"


/*
 * 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

/*
 * Symbols for the different formats of a color string.
 */

enum ColorFormatType {
    COLORFORMAT_TKCOLOR,
    COLORFORMAT_EMPTYSTRING,
    COLORFORMAT_LIST,
    COLORFORMAT_RGB1,
    COLORFORMAT_RGB2,
    COLORFORMAT_RGBA1,
    COLORFORMAT_RGBA2
};

/*
 * Names for the color format types above.
 * Order must match the one in enum ColorFormatType
 */

static const char *const colorFormatNames[] = {
    "tkcolor",
    "emptystring",
    "list",
    "rgb-short",
    "rgb",
    "rgba-short",
    "rgba",
    NULL
};

/*
 * The following data structure is used to return information from
 * ParseFormatOptions:
 */

struct FormatOptions {
    int options;         /* Individual bits indicate which options were
                          * specified - see below. */
    Tcl_Obj *formatName; /* Name specified without an option. */
    enum ColorFormatType colorFormat;
                         /* The color format type given with the
                          * -colorformat option */
};

/*
 * Bit definitions for use with ParseFormatOptions: each bit is set in the
 * allowedOptions parameter on a call to ParseFormatOptions if that option
 * is allowed for the current photo image subcommand. On return, the bit is
 * set in the options field of the FormatOptions structure if that option
 * was specified.
 *
 * OPT_COLORFORMAT:         Set if -alpha option allowed/specified.
 */

#define OPT_COLORFORMAT     1

/*
 * List of format option names. The order here must match the order of
 * declarations of the FMT_OPT_* constants above.
 */

static const char *const formatOptionNames[] = {
    "-colorformat",
    NULL
};

/*
 * Forward declarations
 */

static int      ParseFormatOptions(Tcl_Interp *interp, int allowedOptions,
                    int objc, Tcl_Obj *const objv[], int *indexPtr,
                    struct FormatOptions *optPtr);
static Tcl_Obj  *GetBadOptMsg(const char *badValue, int allowedOpts);
static int      StringMatchDef(Tcl_Obj *data, Tcl_Obj *formatString,
                    int *widthPtr, int *heightPtr, Tcl_Interp *interp);
static int      StringReadDef(Tcl_Interp *interp, Tcl_Obj *data,
                    Tcl_Obj *formatString, Tk_PhotoHandle imageHandle,
                    int destX, int destY, int width, int height,
                    int srcX, int srcY);
static int      StringWriteDef(Tcl_Interp *interp,
                    Tcl_Obj *formatString,
                    Tk_PhotoImageBlock *blockPtr);
static int      ParseColor(Tcl_Interp *interp, Tcl_Obj *specObj,
                    Display *display, Colormap colormap, unsigned char *redPtr,
                    unsigned char *greenPtr, unsigned char *bluePtr,
                    unsigned char *alphaPtr);
static int      ParseColorAsList(Tcl_Interp *interp, const char *colorString,
                    int colorStrLen, unsigned char *redPtr,
                    unsigned char *greenPtr, unsigned char *bluePtr,
                    unsigned char *alphaPtr);
static int      ParseColorAsHex(Tcl_Interp *interp, const char *colorString,
                    int colorStrLen, Display *display, Colormap colormap,
                    unsigned char *redPtr, unsigned char *greenPtr,
                    unsigned char *bluePtr, unsigned char *alphaPtr);
static int      ParseColorAsStandard(Tcl_Interp *interp,
                    const char *colorString, int colorStrLen,
                    Display *display, Colormap colormap,
                    unsigned char *redPtr, unsigned char *greenPtr,
                    unsigned char *bluePtr, unsigned char *alphaPtr);

/*
 * The format record for the default image handler
 */

Tk_PhotoImageFormat tkImgFmtDefault = {
    "default",      /* name */
    NULL,           /* fileMatchProc: format doesn't support file ops */
    StringMatchDef, /* stringMatchProc */
    NULL,           /* fileReadProc: format doesn't support file read */
    StringReadDef,  /* stringReadProc */
    NULL,           /* fileWriteProc: format doesn't support file write */
    StringWriteDef, /* stringWriteProc */
    NULL            /* nextPtr */
};

/*
 *----------------------------------------------------------------------
 *
 * ParseFormatOptions --
 *
 *      Parse the options passed to the image format handler.
 *
 * Results:
 *      On success, the structure pointed to by optPtr is filled with the
 *      values passed or with the defaults and TCL_OK returned.
 *      If an error occurs, leaves an error message in interp and returns
 *      TCL_ERROR.
 *
 * Side effects:
 *      The value in *indexPtr is updated to the index of the fist
 *      element in argv[] that does not look like an option/value, or to
 *      argc if parsing reached the end of argv[].
 *
 *----------------------------------------------------------------------
 */
static int
ParseFormatOptions(
    Tcl_Interp *interp,               /* For error messages */
    int allowedOptions,               /* Bitfield specifying which options are
                                       * to be considered allowed */
    int objc,                         /* Number of elements in argv[] */
    Tcl_Obj *const objv[],            /* The arguments to parse */
    int *indexPtr,                    /* Index giving the first element to
                                       * parse. The value is updated to the
                                       * index where parsing ended */
    struct FormatOptions *optPtr)     /* Parsed option values are written to
                                       * this struct */

{
    int index, optIndex, first;
    enum ColorFormatType typeIndex;
    const char *option;

    first = 1;

    /*
     * Fill in default values
     */
    optPtr->options = 0;
    optPtr->formatName = NULL;
    optPtr->colorFormat = COLORFORMAT_RGB2;
    for (index = *indexPtr; index < objc; *indexPtr = ++index) {
        int optionExists;

        /*
         * The first value can be the format handler's name. It goes to
         * optPtr->name.
         */
        option = Tcl_GetString(objv[index]);
        if (option[0] != '-') {
            if (first) {
                optPtr->formatName = objv[index];
                first = 0;
                continue;
            } else {
                break;
            }
        }
        first = 0;

        /*
         * Check if option is known and allowed
         */

        optionExists = 1;
        if (Tcl_GetIndexFromObj(NULL, objv[index], formatOptionNames,
                "format option", 0, &optIndex) != TCL_OK) {
            optionExists = 0;
        }
        if (!optionExists || !((1 << optIndex) & allowedOptions)) {
            Tcl_SetObjResult(interp, GetBadOptMsg(Tcl_GetString(objv[index]),
                    allowedOptions));
            Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", "BAD_OPTION", NULL);
            return TCL_ERROR;
        }

        /*
         * Option-specific checks
         */

        switch (1 << optIndex) {
        case OPT_COLORFORMAT:
            *indexPtr = ++index;
            if (index >= objc) {
                Tcl_SetObjResult(interp, Tcl_ObjPrintf("the \"%s\" option "
                        "requires a value", Tcl_GetString(objv[index - 1])));
                Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO",
                        "MISSING_VALUE", NULL);
                return TCL_ERROR;
            }
            if (Tcl_GetIndexFromObj(NULL, objv[index], colorFormatNames, "",
                    TCL_EXACT, (int *)&typeIndex) != TCL_OK
                    || (typeIndex != COLORFORMAT_LIST
                    && typeIndex != COLORFORMAT_RGB2
                    && typeIndex != COLORFORMAT_RGBA2) ) {
                Tcl_SetObjResult(interp, Tcl_ObjPrintf("bad color format "
                        "\"%s\": must be rgb, rgba, or list",
                        Tcl_GetString(objv[index])));
                Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO",
                        "BAD_COLOR_FORMAT", NULL);
                return TCL_ERROR;
            }
            optPtr->colorFormat = typeIndex;
            break;
        default:
            Tcl_Panic("ParseFormatOptions: unexpected switch fallthrough");
        }

        /*
         * Add option to bitfield in optPtr
         */
        optPtr->options |= (1 << optIndex);
    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 *  GetBadOptMsg --
 *
 *      Build a Tcl_Obj containing an error message in the form "bad option
 *      "xx": must be y, or z", based on the bits set in allowedOpts.
 *
 * Results:
 *      A Tcl Object containig the error message.
 *
 * Side effects:
 *      None
 *----------------------------------------------------------------------
 */
static Tcl_Obj *
GetBadOptMsg(
    const char *badValue,   /* the erroneous option */
    int allowedOpts)        /* bitfield specifying the allowed options */
{
    int i, bit;
    Tcl_Obj *resObj = Tcl_ObjPrintf("bad format option \"%s\": ", badValue);

    if (allowedOpts == 0) {
        Tcl_AppendToObj(resObj, "no options allowed", -1);
    } else {
        Tcl_AppendToObj(resObj, "must be ", -1);
        bit = 1;
        for (i = 0; formatOptionNames[i] != NULL; i++) {
            if (allowedOpts & bit) {
                if (allowedOpts & (bit -1)) {
                    /*
                     * not the first option
                     */
                    if (allowedOpts & ~((bit << 1) - 1)) {
                        /*
                         * not the last option
                         */
                        Tcl_AppendToObj(resObj, ", ", -1);
                    } else {
                        Tcl_AppendToObj(resObj, ", or ", -1);
                    }
                }
                Tcl_AppendToObj(resObj, formatOptionNames[i], -1);
            }
            bit <<=1;
        }
    }
    return resObj;
}

/*
 *----------------------------------------------------------------------
 *
 * StringMatchDef --
 *
 *      Default string match function. Test if image data in string form
 *      appears to be in the default list-of-list-of-pixel-data format
 *      accepted by the "<img> put" command.
 *
 * Results:
 *      If thte data is in the default format, writes the size of the image
 *      to widthPtr and heightPtr and returns 1. Otherwise, leaves an error
 *      message in interp (if not NULL) and returns 0.
 *      Note that this function does not parse all data points. A return
 *      value of 1 does not guarantee that the data can be read without
 *      errors.
 *
 * Side effects:
 *      None
 *----------------------------------------------------------------------
 */
static int
StringMatchDef(
    Tcl_Obj *data,          /* The data to check */
    Tcl_Obj *formatString,  /* Value of the -format option, not used here */
    int *widthPtr,          /* Width of image is written to this location */
    int *heightPtr,         /* Height of image is written to this location */
    Tcl_Interp *interp)     /* Error messages are left in this interpreter */
{
    int y, rowCount, colCount, curColCount;
    unsigned char dummy;
    Tcl_Obj **rowListPtr, *pixelData;
    (void)formatString;

    /*
     * See if data can be parsed as a list, if every element is itself a valid
     * list and all sublists have the same length.
     */

    if (Tcl_ListObjGetElements(interp, data, &rowCount, &rowListPtr)
            != TCL_OK) {
        return 0;
    }
    if (rowCount == 0) {
        /*
         * empty list is valid data
         */

        *widthPtr = 0;
        *heightPtr = 0;
        return 1;
    }
    colCount = -1;
    for (y = 0; y < rowCount; y++) {
        if (Tcl_ListObjLength(interp, rowListPtr[y], &curColCount) != TCL_OK) {
            return 0;
        }
        if (colCount < 0) {
            colCount = curColCount;
        } else if (curColCount != colCount) {
            if (interp != NULL) {
                Tcl_SetObjResult(interp, Tcl_ObjPrintf("invalid row # %d: "
                        "all rows must have the same number of elements", y));
                Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO",
                        "INVALID_DATA", NULL);
            }
            return 0;
        }
    }

    /*
     * Data in base64 encoding (or even binary data), might actually pass
     * these tests. To avoid parsing it as list of lists format, check one
     * pixel for validity.
     */
    if (Tcl_ListObjIndex(interp, rowListPtr[0], 0, &pixelData) != TCL_OK) {
        return 0;
    }
    if (Tcl_GetCharLength(pixelData) > TK_PHOTO_MAX_COLOR_CHARS) {
        return 0;
    }
    if (ParseColor(interp, pixelData, Tk_Display(Tk_MainWindow(interp)),
            Tk_Colormap(Tk_MainWindow(interp)), &dummy, &dummy, &dummy, &dummy)
            != TCL_OK) {
        return 0;
    }

    /*
     * Looks like we have valid data for this format.
     * We do not check any pixel values - that's the job of ImgStringRead()
     */

    *widthPtr = colCount;
    *heightPtr = rowCount;

    return 1;

}

/*
 *----------------------------------------------------------------------
 *
 * StringReadDef --
 *
 *      String read function for default format. (see manpage for details on
 *      the format).
 *
 * Results:
 *      A standard Tcl result.
 *
 * Side effects:
 *      If the data has valid format, write it to the image identified by
 *      imageHandle.
 *      If the image data cannot be parsed, an error message is left in
 *      interp.
 *
 *----------------------------------------------------------------------
*/

static int
StringReadDef(
    Tcl_Interp *interp,         /* leave error messages here */
    Tcl_Obj *data,              /* the data to parse */
    Tcl_Obj *formatString,      /* value of the -format option */
    Tk_PhotoHandle imageHandle, /* write data to this image */
    int destX, int destY,       /* start writing data at this point
                                 * in destination image*/
    int width, int height,      /* dimensions of area to write to */
    int srcX, int srcY)         /* start reading source data at these
                                 * coordinates */
{
    Tcl_Obj **rowListPtr, **colListPtr;
    Tcl_Obj **objv;
    int objc;
    unsigned char *curPixelPtr;
    int x, y, rowCount, colCount, curColCount;
    Tk_PhotoImageBlock srcBlock;
    Display *display;
    Colormap colormap;
    struct FormatOptions opts;
    int optIndex;

    /*
     * Parse format suboptions
     * We don't use any format suboptions, but we still need to provide useful
     * error messages if suboptions were specified.
     */

    memset(&opts, 0, sizeof(opts));
    if (formatString != NULL) {
        if (Tcl_ListObjGetElements(interp, formatString, &objc, &objv)
                != TCL_OK) {
            return TCL_ERROR;
        }
        optIndex = 0;
        if (ParseFormatOptions(interp, 0, objc, objv, &optIndex, &opts)
                != TCL_OK) {
            return TCL_ERROR;
        }
        if (optIndex < objc) {
            Tcl_SetObjResult(interp,
                    GetBadOptMsg(Tcl_GetString(objv[optIndex]), 0));
            Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", "BAD_OPTION", NULL);
            return TCL_ERROR;
        }
    }

    /*
     * Check input data
     */

    if (Tcl_ListObjGetElements(interp, data, &rowCount, &rowListPtr)
            != TCL_OK ) {
        return TCL_ERROR;
    }
    if ( rowCount > 0 && Tcl_ListObjLength(interp, rowListPtr[0], &colCount)
            != TCL_OK) {
        return TCL_ERROR;
    }
    if (width <= 0 || height <= 0 || rowCount == 0 || colCount == 0) {
        /*
         * No changes with zero sized input or zero sized output region
         */

        return TCL_OK;
    }
    if (srcX < 0 || srcY < 0 || srcX >= rowCount || srcY >= colCount) {
        Tcl_SetObjResult(interp, Tcl_ObjPrintf("source coordinates out of range"));
        Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", "COORDINATES", NULL);
        return TCL_ERROR;
    }

    /*
     * Memory allocation overflow protection.
     * May not be able to trigger/ demo / test this.
     */

    if (colCount > (int)(UINT_MAX / 4 / rowCount)) {
        Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                        "photo image dimensions exceed Tcl memory limits"));
        Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO",
                "OVERFLOW", NULL);
        return TCL_OK;
    }

    /*
     * Read data and put it to imageHandle
     */

    srcBlock.width = colCount - srcX;
    srcBlock.height = rowCount - srcY;
    srcBlock.pixelSize = 4;
    srcBlock.pitch = srcBlock.width * 4;
    srcBlock.offset[0] = 0;
    srcBlock.offset[1] = 1;
    srcBlock.offset[2] = 2;
    srcBlock.offset[3] = 3;
    srcBlock.pixelPtr = (unsigned char *)attemptckalloc(srcBlock.pitch * srcBlock.height);
    if (srcBlock.pixelPtr == NULL) {
        Tcl_SetObjResult(interp, Tcl_ObjPrintf(TK_PHOTO_ALLOC_FAILURE_MESSAGE));
        Tcl_SetErrorCode(interp, "TK", "MALLOC", NULL);
        return TCL_ERROR;
    }
    curPixelPtr = srcBlock.pixelPtr;
    display = Tk_Display(Tk_MainWindow(interp));
    colormap = Tk_Colormap(Tk_MainWindow(interp));
    for (y = srcY; y < rowCount; y++) {
        /*
         * We don't test the length of row, as that's been done in
         * ImgStringMatch()
         */

        if (Tcl_ListObjGetElements(interp, rowListPtr[y], &curColCount,
                &colListPtr) != TCL_OK) {
            goto errorExit;
        }
        for (x = srcX; x < colCount; x++) {
            if (ParseColor(interp, colListPtr[x], display, colormap,
                    curPixelPtr, curPixelPtr + 1, curPixelPtr + 2,
                    curPixelPtr + 3) != TCL_OK) {
                goto errorExit;
            }
            curPixelPtr += 4;
        }
    }

    /*
     * Write image data to destHandle
     */
    if (Tk_PhotoPutBlock(interp, imageHandle, &srcBlock, destX, destY,
            width, height, TK_PHOTO_COMPOSITE_SET) != TCL_OK) {
        goto errorExit;
    }

    ckfree(srcBlock.pixelPtr);

    return TCL_OK;

  errorExit:
    ckfree(srcBlock.pixelPtr);

    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * StringWriteDef --
 *
 *      String write function for default image data format. See the user
 *      documentation for details.
 *
 * Results:
 *      The converted data is set as the result of interp. Returns a standard
 *      Tcl result.
 *
 * Side effects:
 *      None.
 *
 *----------------------------------------------------------------------
 */

static int
StringWriteDef(
    Tcl_Interp *interp,                 /* For the result and errors */
    Tcl_Obj *formatString,              /* The value of the -format option */
    Tk_PhotoImageBlock *blockPtr)       /* The image data to convert */
{
    int greenOffset, blueOffset, alphaOffset, hasAlpha;
    Tcl_Obj *result, **objv = NULL;
    int objc, allowedOpts, optIndex;
    struct FormatOptions opts;

    /*
     * Parse format suboptions
     */
    if (Tcl_ListObjGetElements(interp, formatString, &objc, &objv)
            != TCL_OK) {
        return TCL_ERROR;
    }
    allowedOpts = OPT_COLORFORMAT;
    optIndex = 0;
    if (ParseFormatOptions(interp, allowedOpts, objc, objv, &optIndex, &opts)
            != TCL_OK) {
        return TCL_ERROR;
    }
    if (optIndex < objc) {
        Tcl_SetObjResult(interp,
                GetBadOptMsg(Tcl_GetString(objv[optIndex]), allowedOpts));
        Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", "BAD_OPTION", NULL);
        return TCL_ERROR;
    }

    greenOffset = blockPtr->offset[1] - blockPtr->offset[0];
    blueOffset = blockPtr->offset[2] - blockPtr->offset[0];

    /*
     * A negative alpha offset signals that the image is fully opaque.
     * That's not really documented anywhere, but it's the way it is!
     */

    if (blockPtr->offset[3] < 0) {
        hasAlpha = 0;
        alphaOffset = 0;
    } else {
        hasAlpha = 1;
        alphaOffset = blockPtr->offset[3] - blockPtr->offset[0];
    }

    if ((blockPtr->width > 0) && (blockPtr->height > 0)) {
        int row, col;
        Tcl_DString data, line;
        char colorBuf[11];
        unsigned char *pixelPtr;
        unsigned char alphaVal = 255;

        Tcl_DStringInit(&data);
        for (row=0; row<blockPtr->height; row++) {
            pixelPtr = blockPtr->pixelPtr + blockPtr->offset[0]
                    + row * blockPtr->pitch;
            Tcl_DStringInit(&line);
            for (col=0; col<blockPtr->width; col++) {
                if (hasAlpha) {
                    alphaVal = pixelPtr[alphaOffset];
                }

                /*
                 * We don't build lines as a list for #RGBA and #RGB. Since
                 * these color formats look like comments, the first element
                 * of the list would get quoted with an additional {} .
                 * While this is not a problem if the data is used as
                 * a list, it would cause problems if someone decides to parse
                 * it as a string (and it looks kinda strange)
                 */

                switch (opts.colorFormat) {
                case COLORFORMAT_RGB2:
                    sprintf(colorBuf, "#%02x%02x%02x ",  pixelPtr[0],
                            pixelPtr[greenOffset], pixelPtr[blueOffset]);
                    Tcl_DStringAppend(&line, colorBuf, -1);
                    break;
                case COLORFORMAT_RGBA2:
                    sprintf(colorBuf, "#%02x%02x%02x%02x ",
                            pixelPtr[0], pixelPtr[greenOffset],
                            pixelPtr[blueOffset], alphaVal);
                    Tcl_DStringAppend(&line, colorBuf, -1);
                    break;
                case COLORFORMAT_LIST:
                    Tcl_DStringStartSublist(&line);
                    sprintf(colorBuf, "%d", pixelPtr[0]);
                    Tcl_DStringAppendElement(&line, colorBuf);
                    sprintf(colorBuf, "%d", pixelPtr[greenOffset]);
                    Tcl_DStringAppendElement(&line, colorBuf);
                    sprintf(colorBuf, "%d", pixelPtr[blueOffset]);
                    Tcl_DStringAppendElement(&line, colorBuf);
                    sprintf(colorBuf, "%d", alphaVal);
                    Tcl_DStringAppendElement(&line, colorBuf);
                    Tcl_DStringEndSublist(&line);
                    break;
                default:
                    Tcl_Panic("unexpected switch fallthrough");
                }
                pixelPtr += blockPtr->pixelSize;
            }
            if (opts.colorFormat != COLORFORMAT_LIST) {
                /*
                 * For the #XXX formats, we need to remove the last
                 * whitespace.
                 */

                *(Tcl_DStringValue(&line) + Tcl_DStringLength(&line) - 1)
                        = '\0';
            }
            Tcl_DStringAppendElement(&data, Tcl_DStringValue(&line));
            Tcl_DStringFree(&line);
        }
        result = Tcl_NewStringObj(Tcl_DStringValue(&data), -1);
        Tcl_DStringFree(&data);
    } else {
        result = Tcl_NewObj();
    }

    Tcl_SetObjResult(interp, result);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * ParseColor --
 *
 *      This function extracts color and alpha values from a string. It
 *      understands standard Tk color formats, alpha suffixes and the color
 *      formats specific to photo images, which include alpha data.
 *
 * Results:
 *      On success, writes red, green, blue and alpha values to the
 *      corresponding pointers. If the color spec contains no alpha
 *      information, 255 is taken as transparency value.
 *      If the input cannot be parsed, leaves an error message in
 *      interp. Returns a standard Tcl result.
 *
 * Side effects:
 *      None.
 *
 *----------------------------------------------------------------------
 */
static int
ParseColor(
    Tcl_Interp *interp,         /* error messages go there */
    Tcl_Obj *specObj,           /* the color data to parse */
    Display *display,           /* display of main window, needed to parse
                                 * standard Tk colors */
    Colormap colormap,          /* colormap of current display */
    unsigned char *redPtr,      /* the result is written to these pointers */
    unsigned char *greenPtr,
    unsigned char *bluePtr,
    unsigned char *alphaPtr)
{
    const char *specString;
    TkSizeT charCount;

    /*
     * Find out which color format we have
     */

    specString = TkGetStringFromObj(specObj, &charCount);

    if (charCount == 0) {
        /* Empty string */
        *redPtr = *greenPtr = *bluePtr = *alphaPtr = 0;
        return TCL_OK;
    }
    if (charCount > TK_PHOTO_MAX_COLOR_CHARS) {
        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,
                colormap, redPtr, greenPtr, bluePtr, alphaPtr);
    }
    if (ParseColorAsList(interp, specString, charCount,
            redPtr, greenPtr, bluePtr, alphaPtr) == TCL_OK) {
        return TCL_OK;
    }

    /*
     * 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,
            colormap, redPtr, greenPtr, bluePtr, alphaPtr);

}

/*
 *----------------------------------------------------------------------
 *
 * ParseColorAsList --
 *
 *      This function extracts color and alpha values from a list of 3 or 4
 *      integers (the list color format).
 *
 * Results:
 *      On success, writes red, green, blue and alpha values to the
 *      corresponding pointers. If the color spec contains no alpha
 *      information, 255 is taken as transparency value.
 *      Returns a standard Tcl result.
 *
 * Side effects:
 *      Does *not* leave error messages in interp. The reason is that
 *      it is not always possible to tell if the list format was even
 *      intended and thus it is hard to return meaningful messages.
 *      A general error message from the caller is probably the best
 *      alternative.
 *
 *----------------------------------------------------------------------
 */
static int
ParseColorAsList(
    Tcl_Interp *dummy,         /* not used */
    const char *colorString,    /* the color data to parse */
    int colorStrLen,            /* length of the color string */
    unsigned char *redPtr,      /* the result is written to these pointers */
    unsigned char *greenPtr,
    unsigned char *bluePtr,
    unsigned char *alphaPtr)
{
    /*
     * This is kinda ugly. The code would be certainly nicer if it
     * used Tcl_ListObjGetElements() and Tcl_GetIntFromObj(). But with
     * strtol() it's *much* faster.
     */

    const char *curPos;
    int values[4];
    int i;
    (void)dummy;
    (void)colorStrLen;

    curPos = colorString;
    i = 0;

    /*
     * strtol can give false positives with a sequence of space chars.
     * To avoid that, avance the pointer to the next non-blank char.
     */

    while(isspace(UCHAR(*curPos))) {
        ++curPos;
    }
    while (i < 4 && *curPos != '\0') {
        values[i] = strtol(curPos, (char **)&curPos, 0);
        if (values[i] < 0 || values[i] > 255) {
            return TCL_ERROR;
        }
        while(isspace(UCHAR(*curPos))) {
            ++curPos;
        }
        ++i;
    }

    if (i < 3 || *curPos != '\0') {
        return TCL_ERROR;
    }
    if (i < 4) {
        values[3] = 255;
    }

    *redPtr = (unsigned char) values[0];
    *greenPtr = (unsigned char) values[1];
    *bluePtr = (unsigned char) values[2];
    *alphaPtr = (unsigned char) values[3];

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * ParseColorAsHex --
 *
 *      This function extracts color and alpha values from a string
 *      starting with '#', followed by hex digits. It undestands both
 *      the #RGBA form and the #RBG (with optional suffix)
 *
 * Results:
 *      On success, writes red, green, blue and alpha values to the
 *      corresponding pointers. If the color spec contains no alpha
 *      information, 255 is taken as transparency value.
 *      Returns a standard Tcl result.
 *
 * Side effects:
 *      None.
 *
 *----------------------------------------------------------------------
 */
static int
ParseColorAsHex(
    Tcl_Interp *interp,         /* error messages are left here */
    const char *colorString,    /* the color data to parse */
    int colorStrLen,            /* length of the color string */
    Display *display,           /* display of main window */
    Colormap colormap,          /* colormap of current display */
    unsigned char *redPtr,      /* the result is written to these pointers */
    unsigned char *greenPtr,
    unsigned char *bluePtr,
    unsigned char *alphaPtr)
{
    int i;
    unsigned long int colorValue = 0;

    if (colorStrLen - 1 != 4 && colorStrLen - 1 != 8) {
        return ParseColorAsStandard(interp, colorString, colorStrLen,
                display, colormap, redPtr, greenPtr, bluePtr, alphaPtr);
    }
    for (i = 1; i < colorStrLen; i++) {
        if (!isxdigit(UCHAR(colorString[i]))) {
            /*
             * There still is a chance that this is a Tk color with
             * an alpha suffix
             */

            return ParseColorAsStandard(interp, colorString, colorStrLen,
                    display, colormap, redPtr, greenPtr, bluePtr, alphaPtr);
        }
    }

    colorValue = strtoul(colorString + 1, NULL, 16);
    switch (colorStrLen - 1) {
    case 4:
        /* #RGBA format */
        *redPtr = (unsigned char) ((colorValue >> 12) * 0x11);
        *greenPtr = (unsigned char) (((colorValue >> 8) & 0xf) * 0x11);
        *bluePtr = (unsigned char) (((colorValue >> 4) & 0xf) * 0x11);
        *alphaPtr = (unsigned char) ((colorValue & 0xf) * 0x11);
        return TCL_OK;
    case 8:
        /* #RRGGBBAA format */
        *redPtr = (unsigned char) (colorValue >> 24);
        *greenPtr = (unsigned char) ((colorValue >> 16) & 0xff);
        *bluePtr = (unsigned char) ((colorValue >> 8) & 0xff);
        *alphaPtr = (unsigned char) (colorValue & 0xff);
        return TCL_OK;
    default:
        Tcl_Panic("unexpected switch fallthrough");
    }

    /* Shouldn't get here */
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * ParseColorAsStandard --
 *
 *      This function tries to split a color stirng in a color and a
 *      suffix part and to extract color and alpha values from them. The
 *      color part is treated as regular Tk color.
 *
 * Results:
 *      On success, writes red, green, blue and alpha values to the
 *      corresponding pointers. If the color spec contains no alpha
 *      information, 255 is taken as transparency value.
 *      Returns a standard Tcl result.
 *
 * Side effects:
 *      None.
 *
 *----------------------------------------------------------------------
 */
static int
ParseColorAsStandard(
    Tcl_Interp *interp,         /* error messages are left here */
    const char *specString,    /* the color data to parse */
    int specStrLen,            /* length of the color string */
    Display *display,           /* display of main window */
    Colormap colormap,          /* colormap of current display */
    unsigned char *redPtr,      /* the result is written to these pointers */
    unsigned char *greenPtr,
    unsigned char *bluePtr,
    unsigned char *alphaPtr)
{
    XColor parsedColor;
    const char *suffixString, *colorString;
    char colorBuffer[TK_PHOTO_MAX_COLOR_CHARS + 1];
    char *tmpString;
    double fracAlpha;
    unsigned int suffixAlpha;
    int i;

    /*
     * Split color data string in color and suffix parts
     */

    if ((suffixString = strrchr(specString, '@')) == NULL
            && ((suffixString = strrchr(specString, '#')) == NULL
                    || suffixString == specString)) {
        suffixString = specString + specStrLen;
        colorString = specString;
    } else {
        strncpy(colorBuffer, specString, suffixString - specString);
        colorBuffer[suffixString - specString] = '\0';
        colorString = (const char*)colorBuffer;
    }

    /*
     * Try to parse as standard Tk color.
     *
     * We don't use Tk_GetColor() et al. here, as those functions
     * migth return a color that does not exaxtly match the given name
     * if the colormap is full. Also, we don't really want the color to be
     * added to the colormap.
     */

    if ( ! TkParseColor(display, colormap, colorString, &parsedColor)) {
         Tcl_SetObjResult(interp, Tcl_ObjPrintf(
            "invalid color name \"%s\"", specString));
         Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO",
                 "INVALID_COLOR", NULL);
         return TCL_ERROR;
    }

    /*
     * parse the Suffix
     */

    switch (suffixString[0]) {
    case '\0':
        suffixAlpha = 255;
        break;
    case '@':
        fracAlpha = strtod(suffixString + 1, &tmpString);
        if (*tmpString != '\0') {
            Tcl_SetObjResult(interp, Tcl_ObjPrintf("invalid alpha "
                    "suffix \"%s\": expected floating-point value",
                    suffixString));
            Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO",
                    "INVALID COLOR", NULL);
            return TCL_ERROR;
        }
        if (fracAlpha < 0 || fracAlpha > 1) {
            Tcl_SetObjResult(interp, Tcl_ObjPrintf("invalid alpha suffix"
                    " \"%s\": value must be in the range from 0 to 1",
                    suffixString));
            Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO",
                    "INVALID_COLOR", NULL);
            return TCL_ERROR;
        }
        suffixAlpha = (unsigned int) floor(fracAlpha * 255 + 0.5);
        break;
    case '#':
        if (strlen(suffixString + 1) < 1 || strlen(suffixString + 1)> 2) {
            Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                    "invalid alpha suffix \"%s\"", suffixString));
            Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO",
                    "INVALID_COLOR", NULL);
            return TCL_ERROR;
        }
        for (i = 1; i <= (int)strlen(suffixString + 1); i++) {
            if ( ! isxdigit(UCHAR(suffixString[i]))) {
                Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                        "invalid alpha suffix \"%s\": expected hex digit",
                        suffixString));
                Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO",
                        "INVALID_COLOR", NULL);
                return TCL_ERROR;
            }
        }
        if (strlen(suffixString + 1) == 1) {
            sscanf(suffixString, "#%1x", &suffixAlpha);
            suffixAlpha *= 0x11;
        } else {
            sscanf(suffixString, "#%2x", &suffixAlpha);
        }
        break;
    default:
        Tcl_Panic("unexpected switch fallthrough");
    }

    *redPtr = (unsigned char) (parsedColor.red >> 8);
    *greenPtr = (unsigned char) (parsedColor.green >> 8);
    *bluePtr = (unsigned char) (parsedColor.blue >> 8);
    *alphaPtr = (unsigned char) suffixAlpha;

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TkDebugStringMatchDef --
 *
 *      Debugging function for StringMatchDef. Basically just an alias for
 *      that function, intended to expose it directly to tests, as
 *      StirngMatchDef cannot be sufficiently tested otherwise.
 *
 * Results:
 *      See StringMatchDef.
 *
 * Side effects:
 *      None
 *----------------------------------------------------------------------
 */
int
TkDebugPhotoStringMatchDef(
    Tcl_Interp *interp,     /* Error messages are left in this interpreter */
    Tcl_Obj *data,          /* The data to check */
    Tcl_Obj *formatString,  /* Value of the -format option, not used here */
    int *widthPtr,          /* Width of image is written to this location */
    int *heightPtr)         /* Height of image is written to this location */
{
    return StringMatchDef(data, formatString, widthPtr, heightPtr, interp);
}


/* Local Variables: */
/* mode: c */
/* fill-column: 78 */
/* c-basic-offset: 4 */
/* tab-width: 8 */
/* indent-tabs-mode: nil */
/* End: */
Changes to generic/tkImgPNG.c.
1
2
3
4
5
6
7


8
9
10
11
12
13
14
1
2
3
4
5


6
7
8
9
10
11
12
13
14





-
-
+
+







/*
 * 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.
 */

#include "tkInt.h"

122
123
124
125
126
127
128
129

130
131
132
133
134
135
136
122
123
124
125
126
127
128

129
130
131
132
133
134
135
136







-
+







    /*
     * PNG data source/destination channel/object/byte array.
     */

    Tcl_Channel channel;	/* Channel for from-file reads. */
    Tcl_Obj *objDataPtr;
    unsigned char *strDataBuf;	/* Raw source data for from-string reads. */
    int strDataLen;		/* Length of source data. */
    TkSizeT strDataLen;		/* Length of source data. */
    unsigned char *base64Data;	/* base64 encoded string data. */
    unsigned char base64Bits;	/* Remaining bits from last base64 read. */
    unsigned char base64State;	/* Current state of base64 decoder. */
    double alpha;		/* Alpha from -format option. */

    /*
     * Image header information.
210
211
212
213
214
215
216
217

218
219
220

221
222
223

224
225
226

227
228
229
230
231
232
233
210
211
212
213
214
215
216

217
218
219

220
221
222

223
224
225

226
227
228
229
230
231
232
233







-
+


-
+


-
+


-
+







			    Tcl_Obj *fmtObj, 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);
static int		ReadBase64(Tcl_Interp *interp, PNGImage *pngPtr,
			    unsigned char *destPtr, int destSz,
			    unsigned char *destPtr, size_t destSz,
			    unsigned long *crcPtr);
static int		ReadByteArray(Tcl_Interp *interp, PNGImage *pngPtr,
			    unsigned char *destPtr, int destSz,
			    unsigned char *destPtr, size_t destSz,
			    unsigned long *crcPtr);
static int		ReadData(Tcl_Interp *interp, PNGImage *pngPtr,
			    unsigned char *destPtr, int destSz,
			    unsigned char *destPtr, size_t destSz,
			    unsigned long *crcPtr);
static int		ReadChunkHeader(Tcl_Interp *interp, PNGImage *pngPtr,
			    int *sizePtr, unsigned long *typePtr,
			    size_t *sizePtr, unsigned long *typePtr,
			    unsigned long *crcPtr);
static int		ReadIDAT(Tcl_Interp *interp, PNGImage *pngPtr,
			    int chunkSz, unsigned long crc);
static int		ReadIHDR(Tcl_Interp *interp, PNGImage *pngPtr);
static inline int	ReadInt32(Tcl_Interp *interp, PNGImage *pngPtr,
			    unsigned long *resultPtr, unsigned long *crcPtr);
static int		ReadPLTE(Tcl_Interp *interp, PNGImage *pngPtr,
246
247
248
249
250
251
252
253

254
255

256
257
258
259
260
261
262
246
247
248
249
250
251
252

253
254

255
256
257
258
259
260
261
262







-
+

-
+







static int		StringWritePNG(Tcl_Interp *interp, Tcl_Obj *fmtObj,
			    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,
			    unsigned long chunkType,
			    const unsigned char *dataPtr, int dataSize);
			    const unsigned char *dataPtr, size_t dataSize);
static int		WriteData(Tcl_Interp *interp, PNGImage *pngPtr,
			    const unsigned char *srcPtr, int srcSz,
			    const unsigned char *srcPtr, size_t srcSz,
			    unsigned long *crcPtr);
static int		WriteExtraChunks(Tcl_Interp *interp,
			    PNGImage *pngPtr);
static int		WriteIHDR(Tcl_Interp *interp, PNGImage *pngPtr,
			    Tk_PhotoImageBlock *blockPtr);
static int		WriteIDAT(Tcl_Interp *interp, PNGImage *pngPtr,
			    Tk_PhotoImageBlock *blockPtr);
315
316
317
318
319
320
321
322

323
324
325
326
327
328
329
315
316
317
318
319
320
321

322
323
324
325
326
327
328
329







-
+







     * reading with ReadData().
     */

    if (objPtr) {
	Tcl_IncrRefCount(objPtr);
	pngPtr->objDataPtr = objPtr;
	pngPtr->strDataBuf =
		Tcl_GetByteArrayFromObj(objPtr, &pngPtr->strDataLen);
		TkGetByteArrayFromObj(objPtr, &pngPtr->strDataLen);
    }

    /*
     * Initialize the palette transparency table to fully opaque.
     */

    memset(pngPtr->palette, 255, sizeof(pngPtr->palette));
426
427
428
429
430
431
432
433

434
435
436
437
438
439
440
426
427
428
429
430
431
432

433
434
435
436
437
438
439
440







-
+







 */

static int
ReadBase64(
    Tcl_Interp *interp,
    PNGImage *pngPtr,
    unsigned char *destPtr,
    int destSz,
    size_t destSz,
    unsigned long *crcPtr)
{
    static const unsigned char from64[] = {
	0x82, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x80, 0x80,
	0x83, 0x80, 0x80, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
	0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x80,
	0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x3e,
551
552
553
554
555
556
557
558

559
560
561
562
563
564
565

566
567
568
569
570
571
572
573

574
575
576
577
578
579
580
551
552
553
554
555
556
557

558
559
560
561
562
563
564

565
566
567
568
569
570
571
572

573
574
575
576
577
578
579
580







-
+






-
+







-
+







 */

static int
ReadByteArray(
    Tcl_Interp *interp,
    PNGImage *pngPtr,
    unsigned char *destPtr,
    int destSz,
    size_t destSz,
    unsigned long *crcPtr)
{
    /*
     * Check to make sure the number of requested bytes are available.
     */

    if (pngPtr->strDataLen < destSz) {
    if ((size_t)pngPtr->strDataLen < destSz) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"unexpected end of image data", -1));
	Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "EARLY_END", NULL);
	return TCL_ERROR;
    }

    while (destSz) {
	int blockSz = PNG_MIN(destSz, PNG_BLOCK_SZ);
	size_t blockSz = PNG_MIN(destSz, PNG_BLOCK_SZ);

	memcpy(destPtr, pngPtr->strDataBuf, blockSz);

	pngPtr->strDataBuf += blockSz;
	pngPtr->strDataLen -= blockSz;

	if (crcPtr) {
609
610
611
612
613
614
615
616

617
618
619
620
621
622
623
624
625
626

627
628
629

630
631
632
633
634
635
636
609
610
611
612
613
614
615

616
617
618
619
620
621
622
623
624
625

626
627
628

629
630
631
632
633
634
635
636







-
+









-
+


-
+







 */

static int
ReadData(
    Tcl_Interp *interp,
    PNGImage *pngPtr,
    unsigned char *destPtr,
    int destSz,
    size_t destSz,
    unsigned long *crcPtr)
{
    if (pngPtr->base64Data) {
	return ReadBase64(interp, pngPtr, destPtr, destSz, crcPtr);
    } else if (pngPtr->strDataBuf) {
	return ReadByteArray(interp, pngPtr, destPtr, destSz, crcPtr);
    }

    while (destSz) {
	int blockSz = PNG_MIN(destSz, PNG_BLOCK_SZ);
	TkSizeT blockSz = PNG_MIN(destSz, PNG_BLOCK_SZ);

	blockSz = Tcl_Read(pngPtr->channel, (char *)destPtr, blockSz);
	if (blockSz < 0) {
	if (blockSz == TCL_IO_FAILURE) {
	    /* TODO: failure info... */
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "channel read failed: %s", Tcl_PosixError(interp)));
	    return TCL_ERROR;
	}

	/*
854
855
856
857
858
859
860
861

862
863
864
865
866
867
868
854
855
856
857
858
859
860

861
862
863
864
865
866
867
868







-
+







 *----------------------------------------------------------------------
 */

static int
ReadChunkHeader(
    Tcl_Interp *interp,
    PNGImage *pngPtr,
    int *sizePtr,
    size_t *sizePtr,
    unsigned long *typePtr,
    unsigned long *crcPtr)
{
    unsigned long chunkType = 0;
    int chunkSz = 0;
    unsigned long crc = 0;

1235
1236
1237
1238
1239
1240
1241
1242

1243
1244
1245
1246
1247
1248
1249
1235
1236
1237
1238
1239
1240
1241

1242
1243
1244
1245
1246
1247
1248
1249







-
+







static int
ReadIHDR(
    Tcl_Interp *interp,
    PNGImage *pngPtr)
{
    unsigned char sigBuf[PNG_SIG_SZ];
    unsigned long chunkType;
    int chunkSz;
    size_t chunkSz;
    unsigned long crc;
    unsigned long width, height;
    int mismatch;

    /*
     * Read the appropriate number of bytes for the PNG signature.
     */
1259
1260
1261
1262
1263
1264
1265
1266

1267
1268
1269
1270
1271
1272
1273
1259
1260
1261
1262
1263
1264
1265

1266
1267
1268
1269
1270
1271
1272
1273







-
+







    mismatch = memcmp(sigBuf, pngSignature, PNG_SIG_SZ);

    /*
     * If reading from string, reset position and try base64 decode.
     */

    if (mismatch && pngPtr->strDataBuf) {
	pngPtr->strDataBuf = Tcl_GetByteArrayFromObj(pngPtr->objDataPtr,
	pngPtr->strDataBuf = TkGetByteArrayFromObj(pngPtr->objDataPtr,
		&pngPtr->strDataLen);
	pngPtr->base64Data = pngPtr->strDataBuf;

	if (ReadData(interp, pngPtr, sigBuf, PNG_SIG_SZ, NULL) == TCL_ERROR) {
	    return TCL_ERROR;
	}

2093
2094
2095
2096
2097
2098
2099
2100

2101
2102
2103
2104
2105
2106
2107
2093
2094
2095
2096
2097
2098
2099

2100
2101
2102
2103
2104
2105
2106
2107







-
+







    unsigned long crc)
{
    /*
     * Process IDAT contents until there is no more in this chunk.
     */

    while (chunkSz && !Tcl_ZlibStreamEof(pngPtr->stream)) {
	int len1, len2;
	TkSizeT len1, len2;

	/*
	 * Read another block of input into the zlib stream if data remains.
	 */

	if (chunkSz) {
	    Tcl_Obj *inputObj = NULL;
2142
2143
2144
2145
2146
2147
2148
2149

2150
2151
2152
2153
2154

2155
2156

2157
2158
2159
2160
2161
2162
2163
2142
2143
2144
2145
2146
2147
2148

2149
2150
2151
2152
2153

2154
2155

2156
2157
2158
2159
2160
2161
2162
2163







-
+




-
+

-
+








	/*
	 * Inflate, processing each output buffer's worth as a line of pixels,
	 * until we cannot fill the buffer any more.
	 */

    getNextLine:
	Tcl_GetByteArrayFromObj(pngPtr->thisLineObj, &len1);
	TkGetByteArrayFromObj(pngPtr->thisLineObj, &len1);
	if (Tcl_ZlibStreamGet(pngPtr->stream, pngPtr->thisLineObj,
		pngPtr->phaseSize - len1) == TCL_ERROR) {
	    return TCL_ERROR;
	}
	Tcl_GetByteArrayFromObj(pngPtr->thisLineObj, &len2);
	TkGetByteArrayFromObj(pngPtr->thisLineObj, &len2);

	if (len2 == pngPtr->phaseSize) {
	if (len2 == (TkSizeT)pngPtr->phaseSize) {
	    if (pngPtr->phase > 7) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"extra data after final scan line of final phase",
			-1));
		Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "EXTRA_DATA",
			NULL);
		return TCL_ERROR;
2233
2234
2235
2236
2237
2238
2239
2240

2241
2242
2243
2244
2245
2246
2247

2248
2249
2250
2251
2252
2253
2254
2233
2234
2235
2236
2237
2238
2239

2240
2241
2242
2243
2244
2245
2246

2247
2248
2249
2250
2251
2252
2253
2254







-
+






-
+







 */

static void
ApplyAlpha(
    PNGImage *pngPtr)
{
    if (pngPtr->alpha != 1.0) {
	register unsigned char *p = pngPtr->block.pixelPtr;
	unsigned char *p = pngPtr->block.pixelPtr;
	unsigned char *endPtr = p + pngPtr->blockLen;
	int offset = pngPtr->block.offset[3];

	p += offset;

	if (16 == pngPtr->bitDepth) {
	    register unsigned int channel;
	    unsigned int channel;

	    while (p < endPtr) {
		channel = (unsigned int)
			(((p[0] << 8) | p[1]) * pngPtr->alpha);

		*p++ = (unsigned char) (channel >> 8);
		*p++ = (unsigned char) (channel & 0xff);
2291
2292
2293
2294
2295
2296
2297
2298

2299
2300
2301
2302
2303
2304
2305
2291
2292
2293
2294
2295
2296
2297

2298
2299
2300
2301
2302
2303
2304
2305







-
+







    PNGImage *pngPtr)
{
    Tcl_Obj **objv = NULL;
    int objc = 0;
    static const char *const fmtOptions[] = {
	"-alpha", NULL
    };
    enum fmtOptions {
    enum fmtOptionsEnum {
	OPT_ALPHA
    };

    /*
     * Extract elements of format specification as a list.
     */

2328
2329
2330
2331
2332
2333
2334
2335

2336
2337
2338
2339
2340
2341
2342
2328
2329
2330
2331
2332
2333
2334

2335
2336
2337
2338
2339
2340
2341
2342







-
+







	    Tcl_WrongNumArgs(interp, 1, objv, "value");
	    return TCL_ERROR;
	}

	objc--;
	objv++;

	switch ((enum fmtOptions) optIndex) {
	switch ((enum fmtOptionsEnum) optIndex) {
	case OPT_ALPHA:
	    if (Tcl_GetDoubleFromObj(interp, objv[0],
		    &pngPtr->alpha) == TCL_ERROR) {
		return TCL_ERROR;
	    }

	    if ((pngPtr->alpha < 0.0) || (pngPtr->alpha > 1.0)) {
2378
2379
2380
2381
2382
2383
2384
2385

2386
2387
2388
2389
2390
2391
2392
2378
2379
2380
2381
2382
2383
2384

2385
2386
2387
2388
2389
2390
2391
2392







-
+







    PNGImage *pngPtr,
    Tcl_Obj *fmtObj,
    Tk_PhotoHandle imageHandle,
    int destX,
    int destY)
{
    unsigned long chunkType;
    int chunkSz;
    size_t chunkSz;
    unsigned long crc;

    /*
     * Parse the PNG signature and IHDR (header) chunk.
     */

    if (ReadIHDR(interp, pngPtr) == TCL_ERROR) {
2516
2517
2518
2519
2520
2521
2522
2523

2524
2525
2526
2527
2528
2529
2530
2516
2517
2518
2519
2520
2521
2522

2523
2524
2525
2526
2527
2528
2529
2530







-
+







     */

    pngPtr->lastLineObj = Tcl_NewObj();
    Tcl_IncrRefCount(pngPtr->lastLineObj);
    pngPtr->thisLineObj = Tcl_NewObj();
    Tcl_IncrRefCount(pngPtr->thisLineObj);

    pngPtr->block.pixelPtr = attemptckalloc(pngPtr->blockLen);
    pngPtr->block.pixelPtr = (unsigned char *)attemptckalloc(pngPtr->blockLen);
    if (!pngPtr->block.pixelPtr) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"memory allocation failed", -1));
	Tcl_SetErrorCode(interp, "TK", "MALLOC", NULL);
	return TCL_ERROR;
    }

2672
2673
2674
2675
2676
2677
2678


2679
2680
2681
2682
2683
2684
2685
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687







+
+







    Tcl_Obj *fmtObj,
    int *widthPtr,
    int *heightPtr,
    Tcl_Interp *interp)
{
    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;
	*heightPtr = png.block.height;
	match = 1;
2721
2722
2723
2724
2725
2726
2727





2728
2729
2730
2731
2732
2733
2734
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741







+
+
+
+
+







    int width,
    int height,
    int srcX,
    int srcY)
{
    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);
    }

2760
2761
2762
2763
2764
2765
2766

2767
2768
2769
2770

2771
2772
2773
2774
2775
2776
2777
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777

2778
2779
2780
2781
2782
2783
2784
2785







+



-
+







    Tcl_Obj *fmtObj,
    int *widthPtr,
    int *heightPtr,
    Tcl_Interp *interp)
{
    PNGImage png;
    int match = 0;
    (void)fmtObj;

    InitPNGImage(NULL, &png, NULL, pObjData, TCL_ZLIB_STREAM_INFLATE);

    png.strDataBuf = Tcl_GetByteArrayFromObj(pObjData, &png.strDataLen);
    png.strDataBuf = TkGetByteArrayFromObj(pObjData, &png.strDataLen);

    if (ReadIHDR(interp, &png) == TCL_OK) {
	*widthPtr = png.block.width;
	*heightPtr = png.block.height;
	match = 1;
    }

2808
2809
2810
2811
2812
2813
2814




2815
2816
2817
2818
2819
2820
2821
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833







+
+
+
+







    int width,
    int height,
    int srcX,
    int srcY)
{
    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);
    }
2841
2842
2843
2844
2845
2846
2847
2848

2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865

2866
2867
2868

2869
2870

2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887

2888
2889
2890
2891
2892
2893
2894
2853
2854
2855
2856
2857
2858
2859

2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876

2877
2878
2879

2880
2881

2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898

2899
2900
2901
2902
2903
2904
2905
2906







-
+
















-
+


-
+

-
+
















-
+







 */

static int
WriteData(
    Tcl_Interp *interp,
    PNGImage *pngPtr,
    const unsigned char *srcPtr,
    int srcSz,
    size_t srcSz,
    unsigned long *crcPtr)
{
    if (!srcPtr || !srcSz) {
	return TCL_OK;
    }

    if (crcPtr) {
	*crcPtr = Tcl_ZlibCRC32(*crcPtr, srcPtr, srcSz);
    }

    /*
     * TODO: is Tcl_AppendObjToObj faster here? i.e., does Tcl join the
     * objects immediately or store them in a multi-object rep?
     */

    if (pngPtr->objDataPtr) {
	int objSz;
	TkSizeT objSz;
	unsigned char *destPtr;

	Tcl_GetByteArrayFromObj(pngPtr->objDataPtr, &objSz);
	TkGetByteArrayFromObj(pngPtr->objDataPtr, &objSz);

	if (objSz > INT_MAX - srcSz) {
	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);
	    return TCL_ERROR;
	}

	destPtr = Tcl_SetByteArrayLength(pngPtr->objDataPtr, objSz + srcSz);

	if (!destPtr) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "memory allocation failed", -1));
	    Tcl_SetErrorCode(interp, "TK", "MALLOC", NULL);
	    return TCL_ERROR;
	}

	memcpy(destPtr+objSz, srcPtr, srcSz);
    } else if (Tcl_Write(pngPtr->channel, (const char *) srcPtr, srcSz) < 0) {
    } else if (Tcl_Write(pngPtr->channel, (const char *) srcPtr, srcSz) == TCL_IO_FAILURE) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"write to channel failed: %s", Tcl_PosixError(interp)));
	return TCL_ERROR;
    }

    return TCL_OK;
}
2956
2957
2958
2959
2960
2961
2962
2963

2964
2965
2966
2967
2968
2969
2970
2968
2969
2970
2971
2972
2973
2974

2975
2976
2977
2978
2979
2980
2981
2982







-
+








static inline int
WriteChunk(
    Tcl_Interp *interp,
    PNGImage *pngPtr,
    unsigned long chunkType,
    const unsigned char *dataPtr,
    int dataSize)
    size_t dataSize)
{
    unsigned long crc = Tcl_ZlibCRC32(0, NULL, 0);
    int result = TCL_OK;

    /*
     * Write the length field for the chunk.
     */
3127
3128
3129
3130
3131
3132
3133
3134

3135
3136

3137
3138
3139
3140
3141
3142
3143
3139
3140
3141
3142
3143
3144
3145

3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156







-
+


+








static int
WriteIDAT(
    Tcl_Interp *interp,
    PNGImage *pngPtr,
    Tk_PhotoImageBlock *blockPtr)
{
    int rowNum, flush = TCL_ZLIB_NO_FLUSH, outputSize, result;
    int rowNum, flush = TCL_ZLIB_NO_FLUSH, result;
    Tcl_Obj *outputObj;
    unsigned char *outputBytes;
    TkSizeT outputSize;

    /*
     * Filter and compress each row one at a time.
     */

    for (rowNum=0 ; rowNum < blockPtr->height ; rowNum++) {
	int colNum;
3221
3222
3223
3224
3225
3226
3227
3228

3229
3230
3231
3232
3233
3234
3235
3234
3235
3236
3237
3238
3239
3240

3241
3242
3243
3244
3245
3246
3247
3248







-
+








    /*
     * Now get the compressed data and write it as one big IDAT chunk.
     */

    outputObj = Tcl_NewObj();
    (void) Tcl_ZlibStreamGet(pngPtr->stream, outputObj, -1);
    outputBytes = Tcl_GetByteArrayFromObj(outputObj, &outputSize);
    outputBytes = TkGetByteArrayFromObj(outputObj, &outputSize);
    result = WriteChunk(interp, pngPtr, CHUNK_IDAT, outputBytes, outputSize);
    Tcl_DecrRefCount(outputObj);
    return result;
}

/*
 *----------------------------------------------------------------------
3454
3455
3456
3457
3458
3459
3460

3461
3462
3463
3464
3465
3466
3467
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481







+







    const char *filename,
    Tcl_Obj *fmtObj,
    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.
     */

    chan = Tcl_OpenFileChannel(interp, filename, "w", 0644);
3524
3525
3526
3527
3528
3529
3530

3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552







+







    Tcl_Interp *interp,
    Tcl_Obj *fmtObj,
    Tk_PhotoImageBlock *blockPtr)
{
    Tcl_Obj *resultObj = Tcl_NewObj();
    PNGImage png;
    int result = TCL_ERROR;
    (void)fmtObj;

    /*
     * Initalize PNGImage instance for encoding.
     */

    if (InitPNGImage(interp, &png, NULL, resultObj,
	    TCL_ZLIB_STREAM_DEFLATE) == TCL_ERROR) {
Changes to generic/tkImgPPM.c.
1
2
3
4
5
6
7


8
9
10
11
12
13
14
1
2
3
4
5


6
7
8
9
10
11
12
13
14





-
-
+
+







/*
 * 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 ([email protected]),
 *	Department of Computer Science,
 *	Australian National University.
90
91
92
93
94
95
96
97
98


99
100
101
102
103

104
105
106
107
108
109
110
90
91
92
93
94
95
96


97
98
99
100
101
102

103
104
105
106
107
108
109
110







-
-
+
+




-
+







 *
 *----------------------------------------------------------------------
 */

static int
FileMatchPPM(
    Tcl_Channel chan,		/* The image file, open for reading. */
    const char *fileName,	/* The name of the image file. */
    Tcl_Obj *format,		/* User-specified format string, or NULL. */
    TCL_UNUSED(const char *),	/* The name of the image file. */
    TCL_UNUSED(Tcl_Obj *),		/* User-specified format string, or NULL. */
    int *widthPtr, int *heightPtr,
				/* The dimensions of the image are returned
				 * here if the file is a valid raw PPM
				 * file. */
    Tcl_Interp *interp)		/* unused */
    TCL_UNUSED(Tcl_Interp *))		/* unused */
{
    int dummy;

    return ReadPPMFileHeader(chan, widthPtr, heightPtr, &dummy);
}

/*
127
128
129
130
131
132
133
134

135
136
137
138
139
140
141
142
143
144


145
146
147
148
149
150
151
127
128
129
130
131
132
133

134
135
136
137
138
139
140
141
142
143

144
145
146
147
148
149
150
151
152







-
+









-
+
+







 */

static int
FileReadPPM(
    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 string, or NULL. */
    TCL_UNUSED(Tcl_Obj *),		/* User-specified format string, or 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
				 * image being read. */
{
    int fileWidth, fileHeight, maxIntensity;
    int nLines, nBytes, h, type, count, bytesPerChannel = 1;
    int nLines, h, type, bytesPerChannel = 1;
    size_t nBytes, count;
    unsigned char *pixelPtr;
    Tk_PhotoImageBlock block;

    type = ReadPPMFileHeader(chan, &fileWidth, &fileHeight, &maxIntensity);
    if (type == 0) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"couldn't read raw PPM header from file \"%s\"", fileName));
207
208
209
210
211
212
213
214

215
216
217
218
219
220
221
208
209
210
211
212
213
214

215
216
217
218
219
220
221
222







-
+







    if (nLines > height) {
	nLines = height;
    }
    if (nLines <= 0) {
	nLines = 1;
    }
    nBytes = nLines * block.pitch;
    pixelPtr = ckalloc(nBytes);
    pixelPtr = (unsigned char *)ckalloc(nBytes);
    block.pixelPtr = pixelPtr + srcX * block.pixelSize;

    for (h = height; h > 0; h -= nLines) {
	if (nLines > h) {
	    nLines = h;
	    nBytes = nLines * block.pitch;
	}
277
278
279
280
281
282
283
284

285
286
287
288


289
290
291
292
293
294
295
278
279
280
281
282
283
284

285
286
287
288

289
290
291
292
293
294
295
296
297







-
+



-
+
+







 *----------------------------------------------------------------------
 */

static int
FileWritePPM(
    Tcl_Interp *interp,
    const char *fileName,
    Tcl_Obj *format,
    TCL_UNUSED(Tcl_Obj *),
    Tk_PhotoImageBlock *blockPtr)
{
    Tcl_Channel chan;
    int w, h, greenOffset, blueOffset, nBytes;
    int w, h, greenOffset, blueOffset;
    size_t nBytes;
    unsigned char *pixelPtr, *pixLinePtr;
    char header[16 + TCL_INTEGER_SPACE * 2];

    chan = Tcl_OpenFileChannel(interp, fileName, "w", 0666);
    if (chan == NULL) {
	return TCL_ERROR;
    }
311
312
313
314
315
316
317
318

319
320
321
322
323
324
325
326
327



328
329
330
331
332
333
334
313
314
315
316
317
318
319

320
321
322
323
324
325
326



327
328
329
330
331
332
333
334
335
336







-
+






-
-
-
+
+
+







    pixLinePtr = blockPtr->pixelPtr + blockPtr->offset[0];
    greenOffset = blockPtr->offset[1] - blockPtr->offset[0];
    blueOffset = blockPtr->offset[2] - blockPtr->offset[0];

    if ((greenOffset == 1) && (blueOffset == 2) && (blockPtr->pixelSize == 3)
	    && (blockPtr->pitch == (blockPtr->width * 3))) {
	nBytes = blockPtr->height * blockPtr->pitch;
	if (Tcl_Write(chan, (char *) pixLinePtr, nBytes) != nBytes) {
	if ((size_t)Tcl_Write(chan, (char *) pixLinePtr, nBytes) != nBytes) {
	    goto writeerror;
	}
    } else {
	for (h = blockPtr->height; h > 0; h--) {
	    pixelPtr = pixLinePtr;
	    for (w = blockPtr->width; w > 0; w--) {
		if (    Tcl_Write(chan,(char *)&pixelPtr[0], 1) == -1 ||
			Tcl_Write(chan,(char *)&pixelPtr[greenOffset],1)==-1 ||
			Tcl_Write(chan,(char *)&pixelPtr[blueOffset],1) ==-1) {
		if (Tcl_Write(chan,(char *)&pixelPtr[0], 1) == TCL_IO_FAILURE ||
			Tcl_Write(chan,(char *)&pixelPtr[greenOffset],1) == TCL_IO_FAILURE ||
			Tcl_Write(chan,(char *)&pixelPtr[blueOffset],1) == TCL_IO_FAILURE) {
		    goto writeerror;
		}
		pixelPtr += blockPtr->pixelSize;
	    }
	    pixLinePtr += blockPtr->pitch;
	}
    }
364
365
366
367
368
369
370
371

372
373
374
375
376
377
378
366
367
368
369
370
371
372

373
374
375
376
377
378
379
380







-
+







 *
 *----------------------------------------------------------------------
 */

static int
StringWritePPM(
    Tcl_Interp *interp,
    Tcl_Obj *format,
    TCL_UNUSED(Tcl_Obj *),
    Tk_PhotoImageBlock *blockPtr)
{
    int w, h, size, greenOffset, blueOffset;
    unsigned char *pixLinePtr, *byteArray;
    char header[16 + TCL_INTEGER_SPACE * 2];
    Tcl_Obj *byteArrayObj;

440
441
442
443
444
445
446
447

448
449
450
451
452

453
454
455
456
457
458
459
442
443
444
445
446
447
448

449
450
451
452
453

454
455
456
457
458
459
460
461







-
+




-
+







 *
 *----------------------------------------------------------------------
 */

static int
StringMatchPPM(
    Tcl_Obj *dataObj,		/* The image data. */
    Tcl_Obj *format,		/* User-specified format string, or NULL. */
    TCL_UNUSED(Tcl_Obj *),		/* User-specified format string, or NULL. */
    int *widthPtr, int *heightPtr,
				/* The dimensions of the image are returned
				 * here if the file is a valid raw PPM
				 * file. */
    Tcl_Interp *interp)		/* unused */
    TCL_UNUSED(Tcl_Interp *))		/* unused */
{
    int dummy;

    return ReadPPMStringHeader(dataObj, widthPtr, heightPtr,
	    &dummy, NULL, NULL);
}

475
476
477
478
479
480
481
482

483
484
485
486
487
488
489
477
478
479
480
481
482
483

484
485
486
487
488
489
490
491







-
+







 *----------------------------------------------------------------------
 */

static int
StringReadPPM(
    Tcl_Interp *interp,		/* Interpreter to use for reporting errors. */
    Tcl_Obj *dataObj,		/* The image data. */
    Tcl_Obj *format,		/* User-specified format string, or NULL. */
    TCL_UNUSED(Tcl_Obj *),		/* User-specified format string, or 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
				 * image being read. */
574
575
576
577
578
579
580
581

582
583
584
585
586
587
588
576
577
578
579
580
581
582

583
584
585
586
587
588
589
590







-
+







    if (nLines > height) {
	nLines = height;
    }
    if (nLines <= 0) {
	nLines = 1;
    }
    nBytes = nLines * block.pitch;
    pixelPtr = ckalloc(nBytes);
    pixelPtr = (unsigned char *)ckalloc(nBytes);
    block.pixelPtr = pixelPtr + srcX * block.pixelSize;

    for (h = height; h > 0; h -= nLines) {
	unsigned char *p;

	if (nLines > h) {
	    nLines = h;
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
598
599
600
601
602
603
604

605
606
607
608
609
610
611







-







	    return TCL_ERROR;
	}
	if (maxIntensity < 0x00ff) {
	    for (p=pixelPtr,count=nBytes ; count>0 ; count--,p++,dataBuffer++) {
		*p = (((int) *dataBuffer) * 255)/maxIntensity;
	    }
	} else {
	    unsigned char *p;
	    unsigned int value;

	    for (p = pixelPtr,count=nBytes; count > 1; count-=2, p += 2) {
		value = ((unsigned int) p[0]) * 256 + ((unsigned int) p[1]);
		value = value * 255 / maxIntensity;
		p[0] = p[1] = (unsigned char) value;
	    }
758
759
760
761
762
763
764
765


766
767
768

769
770
771
772
773
774
775
759
760
761
762
763
764
765

766
767
768
769

770
771
772
773
774
775
776
777







-
+
+


-
+







    int *maxIntensityPtr,	/* The maximum intensity value for the image
				 * is stored here. */
    unsigned char **dataBufferPtr,
    int *dataSizePtr)
{
#define BUFFER_SIZE 1000
    char buffer[BUFFER_SIZE], c;
    int i, numFields, dataSize, type = 0;
    int i, numFields, type = 0;
    TkSizeT dataSize;
    unsigned char *dataBuffer;

    dataBuffer = Tcl_GetByteArrayFromObj(dataPtr, &dataSize);
    dataBuffer = TkGetByteArrayFromObj(dataPtr, &dataSize);

    /*
     * Read 4 space-separated fields from the string, ignoring comments (any
     * line that starts with "#").
     */

    if (dataSize-- < 1) {
Changes to generic/tkImgPhInstance.c.
1
2
3
4
5
6
7
8
9
10
11




12
13
14
15
16
17
18
19
20
21
22

23
24
25
26
27
28
29




30




31
32
33
34
35
36
37
38
39
40
41
42

43
44
45
46
47
48
49
1
2
3
4
5
6
7




8
9
10
11
12
13
14
15
16
17
18
19
20
21

22


23
24
25
26

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

47
48
49
50
51
52
53
54







-
-
-
-
+
+
+
+










-
+
-
-




-
+
+
+
+

+
+
+
+











-
+







/*
 * tkImgPhInstance.c --
 *
 *	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 ([email protected]),
 *	   Department of Computer Science,
 *	   Australian National University.
 */

#include "tkImgPhoto.h"
#ifdef MAC_OSX_TK
#include "tkPort.h"
#define TKPUTIMAGE_CAN_BLEND
#endif

/*
 * Declaration for internal Xlib function used here:
 */

#if !defined(_WIN32) && !defined(__CYGWIN__) && !defined(MAC_OSX_TK)
#ifdef __cplusplus
extern "C" {
#endif
extern int		_XInitImageFuncPtrs(XImage *image);
#ifdef __cplusplus
}
#endif
#endif

/*
 * Forward declarations
 */

#ifndef TKPUTIMAGE_CAN_BLEND
static void		BlendComplexAlpha(XImage *bgImg, PhotoInstance *iPtr,
			    int xOffset, int yOffset, int width, int height);
#endif
static int		IsValidPalette(PhotoInstance *instancePtr,
			    const char *palette);
static int		CountBits(pixel mask);
static int		CountBits(unsigned mask);
static void		GetColorTable(PhotoInstance *instancePtr);
static void		FreeColorTable(ColorTable *colorPtr, int force);
static void		AllocateColors(ColorTable *colorPtr);
static void		DisposeColorTable(ClientData clientData);
static int		ReclaimColors(ColorTableId *id, int numColors);

/*
57
58
59
60
61
62
63
64
65


66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82

83
84
85
86
87
88
89

90
91

92
93
94
95
96



97
98
99
100

101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118

119
120
121
122
123
124
125
62
63
64
65
66
67
68


69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86

87
88
89
90
91
92
93

94
95

96
97
98



99
100
101
102
103
104

105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122

123
124
125
126
127
128
129
130







-
-
+
+
















-
+






-
+

-
+


-
-
-
+
+
+



-
+

















-
+








/*
 *----------------------------------------------------------------------
 *
 * TkImgPhotoConfigureInstance --
 *
 *	This function is called to create displaying information for a photo
 *	image instance based on the configuration information in the master.
 *	It is invoked both when new instances are created and when the master
 *	image instance based on the configuration information in the model.
 *	It is invoked both when new instances are created and when the model
 *	is reconfigured.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Generates errors via Tcl_BackgroundException if there are problems in
 *	setting up the instance.
 *
 *----------------------------------------------------------------------
 */

void
TkImgPhotoConfigureInstance(
    PhotoInstance *instancePtr)	/* Instance to reconfigure. */
{
    PhotoMaster *masterPtr = instancePtr->masterPtr;
    PhotoModel *modelPtr = instancePtr->modelPtr;
    XImage *imagePtr;
    int bitsPerPixel;
    ColorTable *colorTablePtr;
    XRectangle validBox;

    /*
     * If the -palette configuration option has been set for the master, use
     * If the -palette configuration option has been set for the model, use
     * the value specified for our palette, but only if it is a valid palette
     * for our windows. Use the gamma value specified the master.
     * for our windows. Use the gamma value specified the model.
     */

    if ((masterPtr->palette && masterPtr->palette[0])
	    && IsValidPalette(instancePtr, masterPtr->palette)) {
	instancePtr->palette = masterPtr->palette;
    if ((modelPtr->palette && modelPtr->palette[0])
	    && IsValidPalette(instancePtr, modelPtr->palette)) {
	instancePtr->palette = modelPtr->palette;
    } else {
	instancePtr->palette = instancePtr->defaultPalette;
    }
    instancePtr->gamma = masterPtr->gamma;
    instancePtr->gamma = modelPtr->gamma;

    /*
     * If we don't currently have a color table, or if the one we have no
     * longer applies (e.g. because our palette or gamma has changed), get a
     * new one.
     */

    colorTablePtr = instancePtr->colorTablePtr;
    if ((colorTablePtr == NULL)
	    || (instancePtr->colormap != colorTablePtr->id.colormap)
	    || (instancePtr->palette != colorTablePtr->id.palette)
	    || (instancePtr->gamma != colorTablePtr->id.gamma)) {
	/*
	 * Free up our old color table, and get a new one.
	 */

	if (colorTablePtr != NULL) {
	    colorTablePtr->liveRefCount -= 1;
	    colorTablePtr->liveRefCount--;
	    FreeColorTable(colorTablePtr, 0);
	}
	GetColorTable(instancePtr);

	/*
	 * Create a new XImage structure for sending data to the X server, if
	 * necessary.
157
158
159
160
161
162
163
164

165
166
167
168
169
170
171
172


173
174
175
176
177
178
179
180

181
182

183
184
185
186
187
188
189
162
163
164
165
166
167
168

169
170
171
172
173
174
175


176
177
178
179
180
181
182
183
184

185
186

187
188
189
190
191
192
193
194







-
+






-
-
+
+







-
+

-
+







#endif
		_XInitImageFuncPtrs(imagePtr);
	    }
	}
    }

    /*
     * If the user has specified a width and/or height for the master which is
     * If the user has specified a width and/or height for the model which is
     * different from our current width/height, set the size to the values
     * specified by the user. If we have no pixmap, we do this also, since it
     * has the side effect of allocating a pixmap for us.
     */

    if ((instancePtr->pixels == None) || (instancePtr->error == NULL)
	    || (instancePtr->width != masterPtr->width)
	    || (instancePtr->height != masterPtr->height)) {
	    || (instancePtr->width != modelPtr->width)
	    || (instancePtr->height != modelPtr->height)) {
	TkImgPhotoInstanceSetSize(instancePtr);
    }

    /*
     * Redither this instance if necessary.
     */

    if ((masterPtr->flags & IMAGE_CHANGED)
    if ((modelPtr->flags & IMAGE_CHANGED)
	    || (instancePtr->colorTablePtr != colorTablePtr)) {
	TkClipBox(masterPtr->validRegion, &validBox);
	TkClipBox(modelPtr->validRegion, &validBox);
	if ((validBox.width > 0) && (validBox.height > 0)) {
	    TkImgDitherInstance(instancePtr, validBox.x, validBox.y,
		    validBox.width, validBox.height);
	}
    }
}

205
206
207
208
209
210
211
212

213
214
215

216
217
218
219
220
221
222
210
211
212
213
214
215
216

217
218
219

220
221
222
223
224
225
226
227







-
+


-
+







 *----------------------------------------------------------------------
 */

ClientData
TkImgPhotoGet(
    Tk_Window tkwin,		/* Window in which the instance will be
				 * used. */
    ClientData masterData)	/* Pointer to our master structure for the
    ClientData modelData)	/* Pointer to our model structure for the
				 * image. */
{
    PhotoMaster *masterPtr = masterData;
    PhotoModel *modelPtr = (PhotoModel *)modelData;
    PhotoInstance *instancePtr;
    Colormap colormap;
    int mono, nRed, nGreen, nBlue, numVisuals;
    XVisualInfo visualInfo, *visInfoPtr;
    char buf[TCL_INTEGER_SPACE * 3];
    XColor *white, *black;
    XGCValues gcValues;
245
246
247
248
249
250
251
252

253
254
255
256
257
258
259
250
251
252
253
254
255
256

257
258
259
260
261
262
263
264







-
+








    /*
     * See if there is already an instance for windows using the same
     * colormap. If so then just re-use it.
     */

    colormap = Tk_Colormap(tkwin);
    for (instancePtr = masterPtr->instancePtr; instancePtr != NULL;
    for (instancePtr = modelPtr->instancePtr; instancePtr != NULL;
	    instancePtr = instancePtr->nextPtr) {
	if ((colormap == instancePtr->colormap)
		&& (Tk_Display(tkwin) == instancePtr->display)) {
	    /*
	     * Re-use this instance.
	     */

274
275
276
277
278
279
280
281
282


283
284
285
286
287
288
289
290
291
292
293
294


295
296
297
298
299
300
301
279
280
281
282
283
284
285


286
287
288
289
290
291
292
293
294
295
296
297


298
299
300
301
302
303
304
305
306







-
-
+
+










-
-
+
+







    }

    /*
     * The image isn't already in use in a window with the same colormap. Make
     * a new instance of the image.
     */

    instancePtr = ckalloc(sizeof(PhotoInstance));
    instancePtr->masterPtr = masterPtr;
    instancePtr = (PhotoInstance *)ckalloc(sizeof(PhotoInstance));
    instancePtr->modelPtr = modelPtr;
    instancePtr->display = Tk_Display(tkwin);
    instancePtr->colormap = Tk_Colormap(tkwin);
    Tk_PreserveColormap(instancePtr->display, instancePtr->colormap);
    instancePtr->refCount = 1;
    instancePtr->colorTablePtr = NULL;
    instancePtr->pixels = None;
    instancePtr->error = NULL;
    instancePtr->width = 0;
    instancePtr->height = 0;
    instancePtr->imagePtr = 0;
    instancePtr->nextPtr = masterPtr->instancePtr;
    masterPtr->instancePtr = instancePtr;
    instancePtr->nextPtr = modelPtr->instancePtr;
    modelPtr->instancePtr = instancePtr;

    /*
     * Obtain information about the visual and decide on the default palette.
     */

    visualInfo.screen = Tk_ScreenNumber(tkwin);
    visualInfo.visualid = XVisualIDFromVisual(Tk_Visual(tkwin));
347
348
349
350
351
352
353
354
355


356
357
358
359
360
361
362
352
353
354
355
356
357
358


359
360
361
362
363
364
365
366
367







-
-
+
+







    }
    instancePtr->defaultPalette = Tk_GetUid(buf);

    /*
     * Make a GC with background = black and foreground = white.
     */

    white = Tk_GetColor(masterPtr->interp, tkwin, "white");
    black = Tk_GetColor(masterPtr->interp, tkwin, "black");
    white = Tk_GetColor(modelPtr->interp, tkwin, "white");
    black = Tk_GetColor(modelPtr->interp, tkwin, "black");
    gcValues.foreground = (white != NULL)? white->pixel:
	    WhitePixelOfScreen(Tk_Screen(tkwin));
    gcValues.background = (black != NULL)? black->pixel:
	    BlackPixelOfScreen(Tk_Screen(tkwin));
    Tk_FreeColor(white);
    Tk_FreeColor(black);
    gcValues.graphics_exposures = False;
371
372
373
374
375
376
377
378
379


380
381
382
383
384
385
386
376
377
378
379
380
381
382


383
384
385
386
387
388
389
390
391







-
-
+
+







    TkImgPhotoConfigureInstance(instancePtr);

    /*
     * If this is the first instance, must set the size of the image.
     */

    if (instancePtr->nextPtr == NULL) {
	Tk_ImageChanged(masterPtr->tkMaster, 0, 0, 0, 0,
		masterPtr->width, masterPtr->height);
	Tk_ImageChanged(modelPtr->tkModel, 0, 0, 0, 0,
		modelPtr->width, modelPtr->height);
    }

    return instancePtr;
}

/*
 *----------------------------------------------------------------------
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
410
411
412
413
414
415
416



417
418
419
420
421
422
423







-
-
-







 *	This should work on all platforms that set mask and shift data
 *	properly from the visualInfo. RGB is really only a 24+ bpp version
 *	whereas RGB15 is the correct version and works for 15bpp+, but it
 *	slower, so it's only used for 15bpp+.
 *
 *	Note that Win32 pre-defines those operations that we really need.
 *
 *	Note that on MacOS, if the background comes from a Retina display
 *	then it will be twice as wide and twice as high as the photoimage.
 *
 *----------------------------------------------------------------------
 */
#ifndef TKPUTIMAGE_CAN_BLEND
#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))
435
436
437
438
439
440
441
442
443


444
445
446
447
448
449
450
437
438
439
440
441
442
443


444
445
446
447
448
449
450
451
452







-
-
+
+







    PhotoInstance *iPtr,	/* Image instance to draw. */
    int xOffset, int yOffset,	/* X & Y offset into image instance to
				 * draw. */
    int width, int height)	/* Width & height of image to draw. */
{
    int x, y, line;
    unsigned long pixel;
    unsigned char r, g, b, alpha, unalpha, *masterPtr;
    unsigned char *alphaAr = iPtr->masterPtr->pix32;
    unsigned char r, g, b, alpha, unalpha, *modelPtr;
    unsigned char *alphaAr = iPtr->modelPtr->pix32;

    /*
     * This blending is an integer version of the Source-Over compositing rule
     * (see Porter&Duff, "Compositing Digital Images", proceedings of SIGGRAPH
     * 1984) that has been hard-coded (for speed) to work with targetting a
     * solid surface.
     *
493
494
495
496
497
498
499
500

501
502
503


504
505
506
507
508
509
510
511
512
513
514
515
516
517



518
519
520
521
522
523
524
495
496
497
498
499
500
501

502
503


504
505
506
507
508
509
510
511
512
513
514
515
516



517
518
519
520
521
522
523
524
525
526







-
+

-
-
+
+











-
-
-
+
+
+







    if (bgImg->depth < 24) {
	unsigned char red_mlen, green_mlen, blue_mlen;

	red_mlen = 8 - CountBits(red_mask >> red_shift);
	green_mlen = 8 - CountBits(green_mask >> green_shift);
	blue_mlen = 8 - CountBits(blue_mask >> blue_shift);
	for (y = 0; y < height; y++) {
	    line = (y + yOffset) * iPtr->masterPtr->width;
	    line = (y + yOffset) * iPtr->modelPtr->width;
	    for (x = 0; x < width; x++) {
		masterPtr = alphaAr + ((line + x + xOffset) * 4);
		alpha = masterPtr[3];
		modelPtr = alphaAr + ((line + x + xOffset) * 4);
		alpha = modelPtr[3];

		/*
		 * Ignore pixels that are fully transparent
		 */

		if (alpha) {
		    /*
		     * We could perhaps be more efficient than XGetPixel for
		     * 24 and 32 bit displays, but this seems "fast enough".
		     */

		    r = masterPtr[0];
		    g = masterPtr[1];
		    b = masterPtr[2];
		    r = modelPtr[0];
		    g = modelPtr[1];
		    b = modelPtr[2];
		    if (alpha != 255) {
			/*
			 * Only blend pixels that have some transparency
			 */

			unsigned char ra, ga, ba;

536
537
538
539
540
541
542
543

544
545
546


547
548
549
550
551
552
553
554
555
556
557
558
559
560



561
562
563
564
565
566
567
538
539
540
541
542
543
544

545
546


547
548
549
550
551
552
553
554
555
556
557
558
559



560
561
562
563
564
565
566
567
568
569







-
+

-
-
+
+











-
-
-
+
+
+







	    }
	}
	return;
    }
#endif /* !_WIN32 */

    for (y = 0; y < height; y++) {
	line = (y + yOffset) * iPtr->masterPtr->width;
	line = (y + yOffset) * iPtr->modelPtr->width;
	for (x = 0; x < width; x++) {
	    masterPtr = alphaAr + ((line + x + xOffset) * 4);
	    alpha = masterPtr[3];
	    modelPtr = alphaAr + ((line + x + xOffset) * 4);
	    alpha = modelPtr[3];

	    /*
	     * Ignore pixels that are fully transparent
	     */

	    if (alpha) {
		/*
		 * We could perhaps be more efficient than XGetPixel for 24
		 * and 32 bit displays, but this seems "fast enough".
		 */

		r = masterPtr[0];
		g = masterPtr[1];
		b = masterPtr[2];
		r = modelPtr[0];
		g = modelPtr[1];
		b = modelPtr[2];
		if (alpha != 255) {
		    /*
		     * Only blend pixels that have some transparency
		     */

		    unsigned char ra, ga, ba;

607
608
609
610
611
612
613
614

615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634

635
636
637
638
639
640
641
642
643
644
645
646

647
648
649
650
651
652
653
609
610
611
612
613
614
615

616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635

636
637
638
639
640
641
642
643
644
645
646
647

648
649
650
651
652
653
654
655







-
+



















-
+











-
+







    int imageX, int imageY,	/* Upper-left corner of region within image to
				 * draw. */
    int width, int height,	/* Dimensions of region within image to
				 * draw. */
    int drawableX,int drawableY)/* Coordinates within drawable that correspond
				 * to imageX and imageY. */
{
    PhotoInstance *instancePtr = clientData;
    PhotoInstance *instancePtr = (PhotoInstance *)clientData;
#ifndef TKPUTIMAGE_CAN_BLEND
    XVisualInfo visInfo = instancePtr->visualInfo;
#endif

    /*
     * If there's no pixmap, it means that an error occurred while creating
     * the image instance so it can't be displayed.
     */

    if (instancePtr->pixels == None) {
	return;
    }

#ifdef TKPUTIMAGE_CAN_BLEND
    /*
     * If TkPutImage can handle RGBA Ximages directly there is
     * no need to call XGetImage or to do the Porter-Duff compositing by hand.
     */

    unsigned char *rgbaPixels = instancePtr->masterPtr->pix32;
    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,
	       photo, imageX, imageY, drawableX, drawableY,
	       (unsigned int) width, (unsigned int) height);
    photo->data = NULL;
    XDestroyImage(photo);
#else

    if ((instancePtr->masterPtr->flags & COMPLEX_ALPHA)
    if ((instancePtr->modelPtr->flags & COMPLEX_ALPHA)
	    && visInfo.depth >= 15
	    && (visInfo.c_class == DirectColor || visInfo.c_class == TrueColor)) {
	Tk_ErrorHandler handler;
	XImage *bgImg = NULL;

	/*
	 * Create an error handler to suppress the case where the input was
680
681
682
683
684
685
686
687

688
689
690
691
692
693
694

695
696
697
698
699
700
701
682
683
684
685
686
687
688

689
690
691
692
693
694
695

696
697
698
699
700
701
702
703







-
+






-
+







	TkPutImage(NULL, 0, display, drawable, instancePtr->gc,
		bgImg, 0, 0, drawableX, drawableY,
		(unsigned int) width, (unsigned int) height);
	XDestroyImage(bgImg);
	Tk_DeleteErrorHandler(handler);
    } else {
	/*
	 * masterPtr->region describes which parts of the image contain valid
	 * modelPtr->region describes which parts of the image contain valid
	 * data. We set this region as the clip mask for the gc, setting its
	 * origin appropriately, and use it when drawing the image.
	 */

    fallBack:
	TkSetRegion(display, instancePtr->gc,
		instancePtr->masterPtr->validRegion);
		instancePtr->modelPtr->validRegion);
	XSetClipOrigin(display, instancePtr->gc, drawableX - imageX,
		drawableY - imageY);
	XCopyArea(display, instancePtr->pixels, drawable, instancePtr->gc,
		imageX, imageY, (unsigned) width, (unsigned) height,
		drawableX, drawableY);
	XSetClipMask(display, instancePtr->gc, None);
	XSetClipOrigin(display, instancePtr->gc, 0, 0);
725
726
727
728
729
730
731
732

733

734
735
736
737
738
739
740
741
742
743
744
745
746
747
748

749
750
751
752
753
754
755
727
728
729
730
731
732
733

734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750

751
752
753
754
755
756
757
758







-
+

+














-
+







void
TkImgPhotoFree(
    ClientData clientData,	/* Pointer to PhotoInstance structure for
				 * instance to be displayed. */
    Display *display)		/* Display containing window that used
				 * image. */
{
    PhotoInstance *instancePtr = clientData;
    PhotoInstance *instancePtr = (PhotoInstance *)clientData;
    ColorTable *colorPtr;
    (void)display;

    if (instancePtr->refCount-- > 1) {
	return;
    }

    /*
     * There are no more uses of the image within this widget. Decrement the
     * count of live uses of its color table, so that its colors can be
     * reclaimed if necessary, and set up an idle call to free the instance
     * structure.
     */

    colorPtr = instancePtr->colorTablePtr;
    if (colorPtr != NULL) {
	colorPtr->liveRefCount -= 1;
	colorPtr->liveRefCount--;
    }

    Tcl_DoWhenIdle(TkImgDisposeInstance, instancePtr);
}

/*
 *----------------------------------------------------------------------
769
770
771
772
773
774
775
776

777
778
779
780
781
782
783


784
785
786


787
788
789
790
791
792


793
794
795
796
797
798
799
772
773
774
775
776
777
778

779
780
781
782
783
784


785
786
787


788
789
790
791
792
793


794
795
796
797
798
799
800
801
802







-
+





-
-
+
+

-
-
+
+




-
-
+
+







 *----------------------------------------------------------------------
 */

void
TkImgPhotoInstanceSetSize(
    PhotoInstance *instancePtr)	/* Instance whose size is to be changed. */
{
    PhotoMaster *masterPtr;
    PhotoModel *modelPtr;
    schar *newError, *errSrcPtr, *errDestPtr;
    int h, offset;
    XRectangle validBox;
    Pixmap newPixmap;

    masterPtr = instancePtr->masterPtr;
    TkClipBox(masterPtr->validRegion, &validBox);
    modelPtr = instancePtr->modelPtr;
    TkClipBox(modelPtr->validRegion, &validBox);

    if ((instancePtr->width != masterPtr->width)
	    || (instancePtr->height != masterPtr->height)
    if ((instancePtr->width != modelPtr->width)
	    || (instancePtr->height != modelPtr->height)
	    || (instancePtr->pixels == None)) {
	newPixmap = Tk_GetPixmap(instancePtr->display,
		RootWindow(instancePtr->display,
			instancePtr->visualInfo.screen),
		(masterPtr->width > 0) ? masterPtr->width: 1,
		(masterPtr->height > 0) ? masterPtr->height: 1,
		(modelPtr->width > 0) ? modelPtr->width: 1,
		(modelPtr->height > 0) ? modelPtr->height: 1,
		instancePtr->visualInfo.depth);
	if (!newPixmap) {
	    Tcl_Panic("Fail to create pixmap with Tk_GetPixmap in TkImgPhotoInstanceSetSize");
	}

	/*
	 * The following is a gross hack needed to properly support colormaps
815
816
817
818
819
820
821
822
823


824
825

826
827
828
829
830
831
832

833
834
835
836
837
838
839
840
841
842


843
844
845

846
847
848
849
850
851




852
853
854
855

856
857
858
859
860
861
862
863
864
865
866
867
868


869
870
871


872
873
874
875

876
877
878
879
880
881
882

883
884
885
886
887
888
889
890
891
892
893


894
895
896
897
898
899
900
818
819
820
821
822
823
824


825
826
827

828
829
830
831
832
833
834

835
836
837
838
839
840
841
842
843


844
845
846
847

848
849
850




851
852
853
854
855
856
857

858
859
860
861
862
863
864
865
866
867
868
869


870
871
872


873
874
875
876
877

878
879
880
881
882
883
884

885
886
887
888
889
890
891
892
893
894


895
896
897
898
899
900
901
902
903







-
-
+
+

-
+






-
+








-
-
+
+


-
+


-
-
-
-
+
+
+
+



-
+











-
-
+
+

-
-
+
+



-
+






-
+









-
-
+
+







		    instancePtr->gc, validBox.x, validBox.y,
		    validBox.width, validBox.height, validBox.x, validBox.y);
	    Tk_FreePixmap(instancePtr->display, instancePtr->pixels);
	}
	instancePtr->pixels = newPixmap;
    }

    if ((instancePtr->width != masterPtr->width)
	    || (instancePtr->height != masterPtr->height)
    if ((instancePtr->width != modelPtr->width)
	    || (instancePtr->height != modelPtr->height)
	    || (instancePtr->error == NULL)) {
	if (masterPtr->height > 0 && masterPtr->width > 0) {
	if (modelPtr->height > 0 && modelPtr->width > 0) {
	    /*
	     * TODO: use attemptckalloc() here once there is a strategy that
	     * will allow us to recover from failure. Right now, there's no
	     * such possibility.
	     */

	    newError = ckalloc(masterPtr->height * masterPtr->width
	    newError = (schar *)ckalloc(modelPtr->height * modelPtr->width
		    * 3 * sizeof(schar));

	    /*
	     * Zero the new array so that we don't get bogus error values
	     * propagating into areas we dither later.
	     */

	    if ((instancePtr->error != NULL)
		    && ((instancePtr->width == masterPtr->width)
		    || (validBox.width == masterPtr->width))) {
		    && ((instancePtr->width == modelPtr->width)
		    || (validBox.width == modelPtr->width))) {
		if (validBox.y > 0) {
		    memset(newError, 0, (size_t)
			    validBox.y * masterPtr->width * 3 * sizeof(schar));
			    validBox.y * modelPtr->width * 3 * sizeof(schar));
		}
		h = validBox.y + validBox.height;
		if (h < masterPtr->height) {
		    memset(newError + h*masterPtr->width*3, 0,
			    (size_t) (masterPtr->height - h)
			    * masterPtr->width * 3 * sizeof(schar));
		if (h < modelPtr->height) {
		    memset(newError + h*modelPtr->width*3, 0,
			    (size_t) (modelPtr->height - h)
			    * modelPtr->width * 3 * sizeof(schar));
		}
	    } else {
		memset(newError, 0, (size_t)
			masterPtr->height * masterPtr->width *3*sizeof(schar));
			modelPtr->height * modelPtr->width *3*sizeof(schar));
	    }
	} else {
	    newError = NULL;
	}

	if (instancePtr->error != NULL) {
	    /*
	     * Copy the common area over to the new array and free the old
	     * array.
	     */

	    if (masterPtr->width == instancePtr->width) {
		offset = validBox.y * masterPtr->width * 3;
	    if (modelPtr->width == instancePtr->width) {
		offset = validBox.y * modelPtr->width * 3;
		memcpy(newError + offset, instancePtr->error + offset,
			(size_t) (validBox.height
			* masterPtr->width * 3 * sizeof(schar)));
			(size_t) validBox.height
			* modelPtr->width * 3 * sizeof(schar));

	    } else if (validBox.width > 0 && validBox.height > 0) {
		errDestPtr = newError +
			(validBox.y * masterPtr->width + validBox.x) * 3;
			(validBox.y * modelPtr->width + validBox.x) * 3;
		errSrcPtr = instancePtr->error +
			(validBox.y * instancePtr->width + validBox.x) * 3;

		for (h = validBox.height; h > 0; --h) {
		    memcpy(errDestPtr, errSrcPtr,
			    validBox.width * 3 * sizeof(schar));
		    errDestPtr += masterPtr->width * 3;
		    errDestPtr += modelPtr->width * 3;
		    errSrcPtr += instancePtr->width * 3;
		}
	    }
	    ckfree(instancePtr->error);
	}

	instancePtr->error = newError;
    }

    instancePtr->width = masterPtr->width;
    instancePtr->height = masterPtr->height;
    instancePtr->width = modelPtr->width;
    instancePtr->height = modelPtr->height;
}

/*
 *----------------------------------------------------------------------
 *
 * IsValidPalette --
 *
992
993
994
995
996
997
998
999

1000
1001
1002
1003
1004
1005
1006
995
996
997
998
999
1000
1001

1002
1003
1004
1005
1006
1007
1008
1009







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
CountBits(
    pixel mask)			/* Value to count the 1 bits in. */
    unsigned mask)			/* Value to count the 1 bits in. */
{
    int n;

    for (n=0 ; mask!=0 ; mask&=mask-1) {
	n++;
    }
    return n;
1054
1055
1056
1057
1058
1059
1060
1061

1062
1063
1064
1065
1066
1067

1068
1069
1070
1071
1072
1073
1074
1057
1058
1059
1060
1061
1062
1063

1064
1065
1066
1067
1068
1069

1070
1071
1072
1073
1074
1075
1076
1077







-
+





-
+







    entry = Tcl_CreateHashEntry(&imgPhotoColorHash, (char *) &id, &isNew);

    if (!isNew) {
	/*
	 * Re-use the existing entry.
	 */

	colorPtr = Tcl_GetHashValue(entry);
	colorPtr = (ColorTable *)Tcl_GetHashValue(entry);
    } else {
	/*
	 * No color table currently available; need to make one.
	 */

	colorPtr = ckalloc(sizeof(ColorTable));
	colorPtr = (ColorTable *)ckalloc(sizeof(ColorTable));

	/*
	 * The following line of code should not normally be needed due to the
	 * assignment in the following line. However, it compensates for bugs
	 * in some compilers (HP, for example) where sizeof(ColorTable) is 24
	 * but the assignment only copies 20 bytes, leaving 4 bytes
	 * uninitialized; these cause problems when using the id for lookups
1124
1125
1126
1127
1128
1129
1130
1131
1132

1133
1134
1135
1136
1137
1138
1139
1127
1128
1129
1130
1131
1132
1133


1134
1135
1136
1137
1138
1139
1140
1141







-
-
+








static void
FreeColorTable(
    ColorTable *colorPtr,	/* Pointer to the color table which is no
				 * longer required by an instance. */
    int force)			/* Force free to happen immediately. */
{
    colorPtr->refCount--;
    if (colorPtr->refCount > 0) {
    if (colorPtr->refCount-- > 1) {
	return;
    }

    if (force) {
	if (colorPtr->flags & DISPOSE_PENDING) {
	    Tcl_CancelIdleCall(DisposeColorTable, colorPtr);
	    colorPtr->flags &= ~DISPOSE_PENDING;
1222
1223
1224
1225
1226
1227
1228
1229

1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249

1250
1251
1252
1253
1254
1255
1256
1224
1225
1226
1227
1228
1229
1230

1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250

1251
1252
1253
1254
1255
1256
1257
1258







-
+



















-
+







	     */

	    if (mono) {
		numColors = nGreen = nBlue = nRed;
	    } else {
		numColors = MAX(MAX(nRed, nGreen), nBlue);
	    }
	    colors = ckalloc(numColors * sizeof(XColor));
	    colors = (XColor *)ckalloc(numColors * sizeof(XColor));

	    for (i = 0; i < numColors; ++i) {
		if (igam == 1.0) {
		    colors[i].red = CFRAC(i, nRed - 1);
		    colors[i].green = CFRAC(i, nGreen - 1);
		    colors[i].blue = CFRAC(i, nBlue - 1);
		} else {
		    colors[i].red = CGFRAC(i, nRed - 1, igam);
		    colors[i].green = CGFRAC(i, nGreen - 1, igam);
		    colors[i].blue = CGFRAC(i, nBlue - 1, igam);
		}
	    }
	} else {
	    /*
	     * PseudoColor, StaticColor, GrayScale or StaticGray visual: we
	     * have to allocate each color in the color cube separately.
	     */

	    numColors = (mono) ? nRed: (nRed * nGreen * nBlue);
	    colors = ckalloc(numColors * sizeof(XColor));
	    colors = (XColor *)ckalloc(numColors * sizeof(XColor));

	    if (!mono) {
		/*
		 * Color display using a PseudoColor or StaticColor visual.
		 */

		i = 0;
1286
1287
1288
1289
1290
1291
1292
1293

1294
1295
1296
1297
1298
1299
1300
1288
1289
1290
1291
1292
1293
1294

1295
1296
1297
1298
1299
1300
1301
1302







-
+







	    }
	}

	/*
	 * Now try to allocate the colors we've calculated.
	 */

	pixels = ckalloc(numColors * sizeof(unsigned long));
	pixels = (unsigned long *)ckalloc(numColors * sizeof(unsigned long));
	for (i = 0; i < numColors; ++i) {
	    if (!XAllocColor(colorPtr->id.display, colorPtr->id.colormap,
		    &colors[i])) {
		/*
		 * Can't get all the colors we want in the default colormap;
		 * first try freeing colors from other unused color tables.
		 */
1446
1447
1448
1449
1450
1451
1452
1453

1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465

1466
1467
1468
1469
1470
1471
1472
1448
1449
1450
1451
1452
1453
1454

1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466

1467
1468
1469
1470
1471
1472
1473
1474







-
+











-
+







 */

static void
DisposeColorTable(
    ClientData clientData)	/* Pointer to the ColorTable whose
				 * colors are to be released. */
{
    ColorTable *colorPtr = clientData;
    ColorTable *colorPtr = (ColorTable *)clientData;
    Tcl_HashEntry *entry;

    if (colorPtr->pixelMap != NULL) {
	if (colorPtr->numColors > 0) {
	    XFreeColors(colorPtr->id.display, colorPtr->id.colormap,
		    colorPtr->pixelMap, colorPtr->numColors, 0);
	    Tk_FreeColormap(colorPtr->id.display, colorPtr->id.colormap);
	}
	ckfree(colorPtr->pixelMap);
    }

    entry = Tcl_FindHashEntry(&imgPhotoColorHash, (char *) &colorPtr->id);
    entry = Tcl_FindHashEntry(&imgPhotoColorHash, &colorPtr->id);
    if (entry == NULL) {
	Tcl_Panic("DisposeColorTable couldn't find hash entry");
    }
    Tcl_DeleteHashEntry(entry);

    ckfree(colorPtr);
}
1506
1507
1508
1509
1510
1511
1512
1513

1514
1515
1516
1517
1518
1519
1520
1508
1509
1510
1511
1512
1513
1514

1515
1516
1517
1518
1519
1520
1521
1522







-
+







    /*
     * First scan through the color hash table to get an upper bound on how
     * many colors we might be able to free.
     */

    entry = Tcl_FirstHashEntry(&imgPhotoColorHash, &srch);
    while (entry != NULL) {
	colorPtr = Tcl_GetHashValue(entry);
	colorPtr = (ColorTable *)Tcl_GetHashValue(entry);
	if ((colorPtr->id.display == id->display)
		&& (colorPtr->id.colormap == id->colormap)
		&& (colorPtr->liveRefCount == 0 )&& (colorPtr->numColors != 0)
		&& ((colorPtr->id.palette != id->palette)
			|| (colorPtr->id.gamma != id->gamma))) {
	    /*
	     * We could take this guy's colors off him.
1535
1536
1537
1538
1539
1540
1541
1542

1543
1544
1545
1546
1547
1548
1549
1537
1538
1539
1540
1541
1542
1543

1544
1545
1546
1547
1548
1549
1550
1551







-
+








    /*
     * Scan through a second time freeing colors.
     */

    entry = Tcl_FirstHashEntry(&imgPhotoColorHash, &srch);
    while ((entry != NULL) && (numColors > 0)) {
	colorPtr = Tcl_GetHashValue(entry);
	colorPtr = (ColorTable *)Tcl_GetHashValue(entry);
	if ((colorPtr->id.display == id->display)
		&& (colorPtr->id.colormap == id->colormap)
		&& (colorPtr->liveRefCount == 0) && (colorPtr->numColors != 0)
		&& ((colorPtr->id.palette != id->palette)
			|| (colorPtr->id.gamma != id->gamma))) {
	    /*
	     * Free the colors that this ColorTable has.
1580
1581
1582
1583
1584
1585
1586
1587

1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607


1608
1609

1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625

1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643

1644
1645
1646
1647
1648
1649
1650

1651
1652
1653
1654
1655
1656
1657
1582
1583
1584
1585
1586
1587
1588

1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607


1608
1609
1610

1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626

1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644

1645
1646
1647
1648
1649
1650
1651

1652
1653
1654
1655
1656
1657
1658
1659







-
+


















-
-
+
+

-
+















-
+

















-
+






-
+







 */

void
TkImgDisposeInstance(
    ClientData clientData)	/* Pointer to the instance whose resources are
				 * to be released. */
{
    PhotoInstance *instancePtr = clientData;
    PhotoInstance *instancePtr = (PhotoInstance *)clientData;
    PhotoInstance *prevPtr;

    if (instancePtr->pixels != None) {
	Tk_FreePixmap(instancePtr->display, instancePtr->pixels);
    }
    if (instancePtr->gc != NULL) {
	Tk_FreeGC(instancePtr->display, instancePtr->gc);
    }
    if (instancePtr->imagePtr != NULL) {
	XDestroyImage(instancePtr->imagePtr);
    }
    if (instancePtr->error != NULL) {
	ckfree(instancePtr->error);
    }
    if (instancePtr->colorTablePtr != NULL) {
	FreeColorTable(instancePtr->colorTablePtr, 1);
    }

    if (instancePtr->masterPtr->instancePtr == instancePtr) {
	instancePtr->masterPtr->instancePtr = instancePtr->nextPtr;
    if (instancePtr->modelPtr->instancePtr == instancePtr) {
	instancePtr->modelPtr->instancePtr = instancePtr->nextPtr;
    } else {
	for (prevPtr = instancePtr->masterPtr->instancePtr;
	for (prevPtr = instancePtr->modelPtr->instancePtr;
		prevPtr->nextPtr != instancePtr; prevPtr = prevPtr->nextPtr) {
	    /* Empty loop body. */
	}
	prevPtr->nextPtr = instancePtr->nextPtr;
    }
    Tk_FreeColormap(instancePtr->display, instancePtr->colormap);
    ckfree(instancePtr);
}

/*
 *----------------------------------------------------------------------
 *
 * TkImgDitherInstance --
 *
 *	This function is called to update an area of an instance's pixmap by
 *	dithering the corresponding area of the master.
 *	dithering the corresponding area of the model.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The instance's pixmap gets updated.
 *
 *----------------------------------------------------------------------
 */

void
TkImgDitherInstance(
    PhotoInstance *instancePtr,	/* The instance to be updated. */
    int xStart, int yStart,	/* Coordinates of the top-left pixel in the
				 * block to be dithered. */
    int width, int height)	/* Dimensions of the block to be dithered. */
{
    PhotoMaster *masterPtr = instancePtr->masterPtr;
    PhotoModel *modelPtr = instancePtr->modelPtr;
    ColorTable *colorPtr = instancePtr->colorTablePtr;
    XImage *imagePtr;
    int nLines, bigEndian, i, c, x, y, xEnd, doDithering = 1;
    int bitsPerPixel, bytesPerLine, lineLength;
    unsigned char *srcLinePtr;
    schar *errLinePtr;
    pixel firstBit, word, mask;
    unsigned firstBit, word, mask;

    /*
     * Turn dithering off in certain cases where it is not needed (TrueColor,
     * DirectColor with many colors).
     */

    if ((colorPtr->visualInfo.c_class == DirectColor)
1690
1691
1692
1693
1694
1695
1696
1697

1698
1699
1700
1701
1702


1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723

1724
1725
1726
1727
1728
1729
1730
1692
1693
1694
1695
1696
1697
1698

1699
1700
1701
1702


1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724

1725
1726
1727
1728
1729
1730
1731
1732







-
+



-
-
+
+




















-
+







    imagePtr->bytes_per_line = bytesPerLine;

    /*
     * TODO: use attemptckalloc() here once we have some strategy for
     * recovering from the failure.
     */

    imagePtr->data = ckalloc(imagePtr->bytes_per_line * nLines);
    imagePtr->data = (char *)ckalloc(imagePtr->bytes_per_line * nLines);
    bigEndian = imagePtr->bitmap_bit_order == MSBFirst;
    firstBit = bigEndian? (1 << (imagePtr->bitmap_unit - 1)): 1;

    lineLength = masterPtr->width * 3;
    srcLinePtr = masterPtr->pix32 + (yStart * masterPtr->width + xStart) * 4;
    lineLength = modelPtr->width * 3;
    srcLinePtr = modelPtr->pix32 + (yStart * modelPtr->width + xStart) * 4;
    errLinePtr = instancePtr->error + yStart * lineLength + xStart * 3;
    xEnd = xStart + width;

    /*
     * Loop over the image, doing at most nLines lines before updating the
     * screen image.
     */

    for (; height > 0; height -= nLines) {
	unsigned char *dstLinePtr = (unsigned char *) imagePtr->data;
	int yEnd;

	if (nLines > height) {
	    nLines = height;
	}
	yEnd = yStart + nLines;
	for (y = yStart; y < yEnd; ++y) {
	    unsigned char *srcPtr = srcLinePtr;
	    schar *errPtr = errLinePtr;
	    unsigned char *destBytePtr = dstLinePtr;
	    pixel *destLongPtr = (pixel *) dstLinePtr;
	    unsigned *destLongPtr = (unsigned *) dstLinePtr;

	    if (colorPtr->flags & COLOR_WINDOW) {
		/*
		 * Color window. We dither the three components independently,
		 * using Floyd-Steinberg dithering, which propagates errors
		 * from the quantization of pixels to the pixels below and to
		 * the right.
1750
1751
1752
1753
1754
1755
1756
1757

1758
1759
1760
1761
1762
1763
1764
1752
1753
1754
1755
1756
1757
1758

1759
1760
1761
1762
1763
1764
1765
1766







-
+








			    c = (x > 0) ? errPtr[-3] * 7: 0;
			    if (y > 0) {
				if (x > 0) {
				    c += errPtr[-lineLength-3];
				}
				c += errPtr[-lineLength] * 5;
				if ((x + 1) < masterPtr->width) {
				if ((x + 1) < modelPtr->width) {
				    c += errPtr[-lineLength+3] * 3;
				}
			    }

			    /*
			     * Add the propagated error to the value of this
			     * component, quantize it, and store the
1807
1808
1809
1810
1811
1812
1813
1814

1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828

1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840

1841
1842
1843
1844
1845
1846

1847
1848
1849
1850
1851
1852
1853
1809
1810
1811
1812
1813
1814
1815

1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829

1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841

1842
1843
1844
1845
1846
1847

1848
1849
1850
1851
1852
1853
1854
1855







-
+













-
+











-
+





-
+







			 * image format is different from the pixel format in
			 * Win32. Eventually we need to fix the image code in
			 * Tk to use the Windows native image ordering. This
			 * would speed up the image code for all of the common
			 * sizes.
			 */

		    case NBBY * sizeof(pixel):
		    case NBBY * sizeof(unsigned):
			*destLongPtr++ = i;
			break;
#endif
		    default:
			XPutPixel(imagePtr, x - xStart, y - yStart,
				(unsigned) i);
		    }
		}

	    } else if (bitsPerPixel > 1) {
		/*
		 * Multibit monochrome window. The operation here is similar
		 * to the color window case above, except that there is only
		 * one component. If the master image is in color, use the
		 * one component. If the model image is in color, use the
		 * luminance computed as
		 *	0.344 * red + 0.5 * green + 0.156 * blue.
		 */

		for (x = xStart; x < xEnd; ++x) {
		    c = (x > 0) ? errPtr[-1] * 7: 0;
		    if (y > 0) {
			if (x > 0) {
			    c += errPtr[-lineLength-1];
			}
			c += errPtr[-lineLength] * 5;
			if (x + 1 < masterPtr->width) {
			if (x + 1 < modelPtr->width) {
			    c += errPtr[-lineLength+1] * 3;
			}
		    }
		    c = ((c + 2056) >> 4) - 128;

		    if (masterPtr->flags & COLOR_IMAGE) {
		    if (modelPtr->flags & COLOR_IMAGE) {
			c += (unsigned) (srcPtr[0] * 11 + srcPtr[1] * 16
				+ srcPtr[2] * 5 + 16) >> 5;
		    } else {
			c += srcPtr[0];
		    }
		    srcPtr += 4;

1869
1870
1871
1872
1873
1874
1875
1876

1877
1878
1879
1880
1881
1882
1883
1871
1872
1873
1874
1875
1876
1877

1878
1879
1880
1881
1882
1883
1884
1885







-
+







			 * image format is different from the pixel format in
			 * Win32. Eventually we need to fix the image code in
			 * Tk to use the Windows native image ordering. This
			 * would speed up the image code for all of the common
			 * sizes.
			 */

		    case NBBY * sizeof(pixel):
		    case NBBY * sizeof(unsigned):
			*destLongPtr++ = i;
			break;
#endif
		    default:
			XPutPixel(imagePtr, x - xStart, y - yStart,
				(unsigned) i);
		    }
1906
1907
1908
1909
1910
1911
1912
1913

1914
1915
1916
1917
1918
1919

1920
1921
1922
1923
1924
1925
1926
1908
1909
1910
1911
1912
1913
1914

1915
1916
1917
1918
1919
1920

1921
1922
1923
1924
1925
1926
1927
1928







-
+





-
+








		    c = (x > 0) ? errPtr[-1] * 7: 0;
		    if (y > 0) {
			if (x > 0) {
			    c += errPtr[-lineLength-1];
			}
			c += errPtr[-lineLength] * 5;
			if (x + 1 < masterPtr->width) {
			if (x + 1 < modelPtr->width) {
			    c += errPtr[-lineLength+1] * 3;
			}
		    }
		    c = ((c + 2056) >> 4) - 128;

		    if (masterPtr->flags & COLOR_IMAGE) {
		    if (modelPtr->flags & COLOR_IMAGE) {
			c += (unsigned)(srcPtr[0] * 11 + srcPtr[1] * 16
				+ srcPtr[2] * 5 + 16) >> 5;
		    } else {
			c += srcPtr[0];
		    }
		    srcPtr += 4;

1935
1936
1937
1938
1939
1940
1941
1942

1943
1944
1945
1946
1947
1948
1949
1937
1938
1939
1940
1941
1942
1943

1944
1945
1946
1947
1948
1949
1950
1951







-
+







		    } else {
			*errPtr++ = c;
		    }
		    mask = bigEndian? (mask >> 1): (mask << 1);
		}
		*destLongPtr = word;
	    }
	    srcLinePtr += masterPtr->width * 4;
	    srcLinePtr += modelPtr->width * 4;
	    errLinePtr += lineLength;
	    dstLinePtr += bytesPerLine;
	}

	/*
	 * Update the pixmap for this instance with the block of pixels that
	 * we have just computed.
1979
1980
1981
1982
1983
1984
1985
1986
1987


1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1981
1982
1983
1984
1985
1986
1987


1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999







-
-
+
+











void
TkImgResetDither(
    PhotoInstance *instancePtr)
{
    if (instancePtr->error) {
	memset(instancePtr->error, 0,
	       /*(size_t)*/ (instancePtr->masterPtr->width
		* instancePtr->masterPtr->height * 3 * sizeof(schar)));
		(size_t) instancePtr->modelPtr->width
		* instancePtr->modelPtr->height * 3 * sizeof(schar));
    }
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Changes to generic/tkImgPhoto.c.
1
2
3
4
5
6
7
8
9
10
11




12
13
14
15
16
17
18
1
2
3
4
5
6
7




8
9
10
11
12
13
14
15
16
17
18







-
-
-
-
+
+
+
+







/*
 * tkImgPhoto.c --
 *
 *	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 ([email protected]),
 *	   Department of Computer Science,
 *	   Australian National University.
44
45
46
47
48
49
50

51
52
53
54
55
56
57
58

59
60
61

62
63
64
65
66
67
68
69
70










71
72
73
74
75
76
77

78
79
80
81
82
83
84
85

86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104

105
106
107
108
109
110
111
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64









65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109

110
111
112
113
114
115
116
117







+








+



+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+







+








+


















-
+







/*
 * Bit definitions for use with ParseSubcommandOptions: each bit is set in the
 * allowedOptions parameter on a call to ParseSubcommandOptions if that option
 * is allowed for the current photo image subcommand. On return, the bit is
 * set in the options field of the SubcommandOptions structure if that option
 * was specified.
 *
 * OPT_ALPHA:			Set if -alpha option allowed/specified.
 * 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_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.
 */

#define OPT_ALPHA	1
#define OPT_BACKGROUND	1
#define OPT_COMPOSITE	2
#define OPT_FORMAT	4
#define OPT_FROM	8
#define OPT_GRAYSCALE	0x10
#define OPT_SHRINK	0x20
#define OPT_SUBSAMPLE	0x40
#define OPT_TO		0x80
#define OPT_ZOOM	0x100
#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

/*
 * List of option names. The order here must match the order of declarations
 * of the OPT_* constants above.
 */

static const char *const optionNames[] = {
    "-alpha",
    "-background",
    "-compositingrule",
    "-format",
    "-from",
    "-grayscale",
    "-shrink",
    "-subsample",
    "-to",
    "-withalpha",
    "-zoom",
    NULL
};

/*
 * Message to generate when an attempt to resize an image fails due to memory
 * problems.
 */

#define TK_PHOTO_ALLOC_FAILURE_MESSAGE \
	"not enough free memory for image buffer"

/*
 * Functions used in the type record for photo images.
 */

static int		ImgPhotoCreate(Tcl_Interp *interp, const char *name,
			    int objc, Tcl_Obj *const objv[],
			    const Tk_ImageType *typePtr, Tk_ImageMaster master,
			    const Tk_ImageType *typePtr, Tk_ImageModel model,
			    ClientData *clientDataPtr);
static void		ImgPhotoDelete(ClientData clientData);
static int		ImgPhotoPostscript(ClientData clientData,
			    Tcl_Interp *interp, Tk_Window tkwin,
			    Tk_PostscriptInfo psInfo, int x, int y, int width,
			    int height, int prepass);

125
126
127
128
129
130
131

132
133
134

135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155

156
157

158
159

160
161

162
163

164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180


181
182
183


184
185
186
187
188

189
190
191
192
193
194
195
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162

163
164

165
166

167
168

169
170

171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186


187
188
189


190
191
192




193
194
195
196
197
198
199
200







+



+




















-
+

-
+

-
+

-
+

-
+















-
-
+
+

-
-
+
+

-
-
-
-
+







    NULL
};

typedef struct {
    Tk_PhotoImageFormat *formatList;
				/* Pointer to the first in the list of known
				 * photo image formats.*/
#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
    int initialized;		/* Set to 1 if we've initialized the
				 * structure. */
} ThreadSpecificData;
static Tcl_ThreadDataKey dataKey;

/*
 * Default configuration
 */

#define DEF_PHOTO_GAMMA		"1"
#define DEF_PHOTO_HEIGHT	"0"
#define DEF_PHOTO_PALETTE	""
#define DEF_PHOTO_WIDTH		"0"

/*
 * Information used for parsing configuration specifications:
 */

static const Tk_ConfigSpec configSpecs[] = {
    {TK_CONFIG_STRING, "-file", NULL, NULL,
	 NULL, Tk_Offset(PhotoMaster, fileString), TK_CONFIG_NULL_OK, NULL},
	 NULL, offsetof(PhotoModel, fileString), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_DOUBLE, "-gamma", NULL, NULL,
	 DEF_PHOTO_GAMMA, Tk_Offset(PhotoMaster, gamma), 0, NULL},
	 DEF_PHOTO_GAMMA, offsetof(PhotoModel, gamma), 0, NULL},
    {TK_CONFIG_INT, "-height", NULL, NULL,
	 DEF_PHOTO_HEIGHT, Tk_Offset(PhotoMaster, userHeight), 0, NULL},
	 DEF_PHOTO_HEIGHT, offsetof(PhotoModel, userHeight), 0, NULL},
    {TK_CONFIG_UID, "-palette", NULL, NULL,
	 DEF_PHOTO_PALETTE, Tk_Offset(PhotoMaster, palette), 0, NULL},
	 DEF_PHOTO_PALETTE, offsetof(PhotoModel, palette), 0, NULL},
    {TK_CONFIG_INT, "-width", NULL, NULL,
	 DEF_PHOTO_WIDTH, Tk_Offset(PhotoMaster, userWidth), 0, NULL},
	 DEF_PHOTO_WIDTH, offsetof(PhotoModel, userWidth), 0, NULL},
    {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL}
};

/*
 * Forward declarations
 */

static void		PhotoFormatThreadExitProc(ClientData clientData);
static int		ImgPhotoCmd(ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
static int		ParseSubcommandOptions(
			    struct SubcommandOptions *optPtr,
			    Tcl_Interp *interp, int allowedOptions,
			    int *indexPtr, int objc, Tcl_Obj *const objv[]);
static void		ImgPhotoCmdDeletedProc(ClientData clientData);
static int		ImgPhotoConfigureMaster(Tcl_Interp *interp,
			    PhotoMaster *masterPtr, int objc,
static int		ImgPhotoConfigureModel(Tcl_Interp *interp,
			    PhotoModel *modelPtr, int objc,
			    Tcl_Obj *const objv[], int flags);
static int		ToggleComplexAlphaIfNeeded(PhotoMaster *mPtr);
static int		ImgPhotoSetSize(PhotoMaster *masterPtr, int width,
static int		ToggleComplexAlphaIfNeeded(PhotoModel *mPtr);
static int		ImgPhotoSetSize(PhotoModel *modelPtr, int width,
			    int height);
static int		ImgStringWrite(Tcl_Interp *interp,
			    Tcl_Obj *formatString,
			    Tk_PhotoImageBlock *blockPtr);
static char *		ImgGetPhoto(PhotoMaster *masterPtr,
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,
			    Tk_PhotoImageFormat **imageFormatPtr,
			    int *widthPtr, int *heightPtr, int *oldformat);
static int		MatchStringFormat(Tcl_Interp *interp, Tcl_Obj *data,
212
213
214
215
216
217
218
219

220
221
222

223
224

225
226
227
228
229

230
231
232
233
234
235
236
217
218
219
220
221
222
223

224
225
226

227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243







-
+


-
+


+





+







 *	The thread's linked lists of photo image formats is deleted.
 *
 *----------------------------------------------------------------------
 */

static void
PhotoFormatThreadExitProc(
    ClientData clientData)	/* not used */
    TCL_UNUSED(void *))	/* not used */
{
    Tk_PhotoImageFormat *freePtr;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

#if !defined(TK_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9
    while (tsdPtr->oldFormatList != NULL) {
	freePtr = tsdPtr->oldFormatList;
	tsdPtr->oldFormatList = tsdPtr->oldFormatList->nextPtr;
	ckfree(freePtr);
    }
#endif
    while (tsdPtr->formatList != NULL) {
	freePtr = tsdPtr->formatList;
	tsdPtr->formatList = tsdPtr->formatList->nextPtr;
	ckfree((char *)freePtr->name);
	ckfree(freePtr);
    }
}
250
251
252
253
254
255
256

257
258
259
260
261
262
263
264
265

266
267
268
269
270
271
272

273
274
275
276

277
278
279
280
281
282
283
284
285
286

287
288
289
290
291
292
293

294

295
296
297
298



299
300

301
302
303
304
305
306
307
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272

273
274
275
276
277
278
279

280
281
282
283
284
285
286
287
288
289
290
291
292
293
294

295
296
297
298
299
300
301

302
303
304
305
306
307

308
309
310
311

312
313
314
315
316
317
318
319







+








-
+






-
+




+









-
+






-
+

+



-
+
+
+

-
+







 * Side effects:
 *	The new image file format is entered into a table used in the photo
 *	image "read" and "write" subcommands.
 *
 *----------------------------------------------------------------------
 */

#if !defined(TK_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9
void
Tk_CreateOldPhotoImageFormat(
    const Tk_PhotoImageFormat *formatPtr)
				/* Structure describing the format. All of the
				 * fields except "nextPtr" must be filled in
				 * by caller. */
{
    Tk_PhotoImageFormat *copyPtr;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (!tsdPtr->initialized) {
	tsdPtr->initialized = 1;
	Tcl_CreateThreadExitHandler(PhotoFormatThreadExitProc, NULL);
    }
    copyPtr = ckalloc(sizeof(Tk_PhotoImageFormat));
    copyPtr = (Tk_PhotoImageFormat *)ckalloc(sizeof(Tk_PhotoImageFormat));
    *copyPtr = *formatPtr;
    copyPtr->nextPtr = tsdPtr->oldFormatList;
    tsdPtr->oldFormatList = copyPtr;
}
#endif

void
Tk_CreatePhotoImageFormat(
    const Tk_PhotoImageFormat *formatPtr)
				/* Structure describing the format. All of the
				 * fields except "nextPtr" must be filled in
				 * by caller. */
{
    Tk_PhotoImageFormat *copyPtr;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (!tsdPtr->initialized) {
	tsdPtr->initialized = 1;
	Tcl_CreateThreadExitHandler(PhotoFormatThreadExitProc, NULL);
    }
    copyPtr = ckalloc(sizeof(Tk_PhotoImageFormat));
    copyPtr = (Tk_PhotoImageFormat *)ckalloc(sizeof(Tk_PhotoImageFormat));
    *copyPtr = *formatPtr;
#if !defined(TK_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9
    if (isupper((unsigned char) *formatPtr->name)) {
	copyPtr->nextPtr = tsdPtr->oldFormatList;
	tsdPtr->oldFormatList = copyPtr;
    } else {
    } else
#endif
    {
	/* for compatibility with aMSN: make a copy of formatPtr->name */
	char *name = ckalloc(strlen(formatPtr->name) + 1);
	char *name = (char *)ckalloc(strlen(formatPtr->name) + 1);
	strcpy(name, formatPtr->name);
	copyPtr->name = name;
	copyPtr->nextPtr = tsdPtr->formatList;
	tsdPtr->formatList = copyPtr;
    }
}

326
327
328
329
330
331
332
333
334


335
336
337
338
339

340
341
342

343
344
345
346
347
348
349
350
351
352
353
354










355
356
357
358
359
360
361


362
363
364
365

366
367
368
369
370
371
372
338
339
340
341
342
343
344


345
346
347
348
349
350

351
352
353

354
355
356










357
358
359
360
361
362
363
364
365
366
367
368
369
370
371


372
373
374
375
376

377
378
379
380
381
382
383
384







-
-
+
+




-
+


-
+


-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+





-
-
+
+



-
+







ImgPhotoCreate(
    Tcl_Interp *interp,		/* Interpreter for application containing
				 * image. */
    const char *name,		/* Name to use for image. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[],	/* Argument objects for options (doesn't
				 * include image name or type). */
    const Tk_ImageType *typePtr,/* Pointer to our type record (not used). */
    Tk_ImageMaster master,	/* Token for image, to be used by us in later
    TCL_UNUSED(const Tk_ImageType *),/* Pointer to our type record (not used). */
    Tk_ImageModel model,	/* Token for image, to be used by us in later
				 * callbacks. */
    ClientData *clientDataPtr)	/* Store manager's token for image here; it
				 * will be returned in later callbacks. */
{
    PhotoMaster *masterPtr;
    PhotoModel *modelPtr;

    /*
     * Allocate and initialize the photo image master record.
     * Allocate and initialize the photo image model record.
     */

    masterPtr = ckalloc(sizeof(PhotoMaster));
    memset(masterPtr, 0, sizeof(PhotoMaster));
    masterPtr->tkMaster = master;
    masterPtr->interp = interp;
    masterPtr->imageCmd = Tcl_CreateObjCommand(interp, name, ImgPhotoCmd,
	    masterPtr, ImgPhotoCmdDeletedProc);
    masterPtr->palette = NULL;
    masterPtr->pix32 = NULL;
    masterPtr->instancePtr = NULL;
    masterPtr->validRegion = TkCreateRegion();
    modelPtr = (PhotoModel *)ckalloc(sizeof(PhotoModel));
    memset(modelPtr, 0, sizeof(PhotoModel));
    modelPtr->tkModel = model;
    modelPtr->interp = interp;
    modelPtr->imageCmd = Tcl_CreateObjCommand(interp, name, ImgPhotoCmd,
	    modelPtr, ImgPhotoCmdDeletedProc);
    modelPtr->palette = NULL;
    modelPtr->pix32 = NULL;
    modelPtr->instancePtr = NULL;
    modelPtr->validRegion = TkCreateRegion();

    /*
     * Process configuration options given in the image create command.
     */

    if (ImgPhotoConfigureMaster(interp, masterPtr, objc, objv, 0) != TCL_OK) {
	ImgPhotoDelete(masterPtr);
    if (ImgPhotoConfigureModel(interp, modelPtr, objc, objv, 0) != TCL_OK) {
	ImgPhotoDelete(modelPtr);
	return TCL_ERROR;
    }

    *clientDataPtr = masterPtr;
    *clientDataPtr = modelPtr;
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * ImgPhotoCmd --
382
383
384
385
386
387
388
389

390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405


406
407
408
409
410
411
412

413
414
415
416

417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436

437
438
439
440
441
442
443
444
445
446
447
448
449
450

451
452
453
454


455
456
457
458


459
460
461
462

463
464
465
466
467
468
469
470
471
472
473
474
475
476

477
478
479
480
481
482
483


484
485
486
487
488
489
490


491
492
493
494
495
496
497
498
499
500

501
502
503
504
505

506
507
508
509
510
511

512
513
514
515
516
517
518
519

520
521
522
523
524
525

526
527
528
529
530
531
532

533
534
535

536
537
538
539
540
541
542
394
395
396
397
398
399
400

401
402
403
404
405
406
407
408
409
410
411
412
413
414
415


416
417
418

419
420

421

422
423
424
425

426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445

446
447
448
449
450
451
452
453
454
455
456
457
458
459

460

461


462
463
464
465


466
467
468
469
470

471
472
473
474
475
476
477
478
479
480
481
482
483
484

485
486
487
488
489
490


491
492
493
494
495
496
497


498
499
500
501
502
503
504
505
506
507
508

509
510

511
512

513
514
515
516
517
518

519
520
521
522
523
524
525
526

527
528
529
530
531
532

533
534
535
536
537
538
539

540
541
542

543
544
545
546
547
548
549
550







-
+














-
-
+
+

-


-

-
+



-
+



















-
+













-
+
-

-
-
+
+


-
-
+
+



-
+













-
+





-
-
+
+





-
-
+
+









-
+

-


-
+





-
+







-
+





-
+






-
+


-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
ImgPhotoCmd(
    ClientData clientData,	/* Information about photo master. */
    ClientData clientData,	/* Information about photo model. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    static const char *const photoOptions[] = {
	"blank", "cget", "configure", "copy", "data", "get", "put",
	"read", "redither", "transparency", "write", NULL
    };
    enum PhotoOptions {
	PHOTO_BLANK, PHOTO_CGET, PHOTO_CONFIGURE, PHOTO_COPY, PHOTO_DATA,
	PHOTO_GET, PHOTO_PUT, PHOTO_READ, PHOTO_REDITHER, PHOTO_TRANS,
	PHOTO_WRITE
    };

    PhotoMaster *masterPtr = clientData;
    int result, index, x, y, width, height, dataWidth, dataHeight, listObjc;
    PhotoModel *modelPtr = (PhotoModel *)clientData;
    int result, index, x, y, width, height;
    struct SubcommandOptions options;
    Tcl_Obj **listObjv, **srcObjv;
    unsigned char *pixelPtr;
    Tk_PhotoImageBlock block;
    Tk_Window tkwin;
    Tk_PhotoImageFormat *imageFormat;
    size_t length;
    TkSizeT length;
    int imageWidth, imageHeight, matched, oldformat = 0;
    Tcl_Channel chan;
    Tk_PhotoHandle srcHandle;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
	return TCL_ERROR;
    }

    if (Tcl_GetIndexFromObj(interp, objv[1], photoOptions, "option", 0,
	    &index) != TCL_OK) {
	return TCL_ERROR;
    }

    switch ((enum PhotoOptions) index) {
    case PHOTO_BLANK:
	/*
	 * photo blank command - just call Tk_PhotoBlank.
	 */

	if (objc == 2) {
	    Tk_PhotoBlank(masterPtr);
	    Tk_PhotoBlank(modelPtr);
	    return TCL_OK;
	} else {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}

    case PHOTO_CGET: {
	const char *arg;

	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "option");
	    return TCL_ERROR;
	}
	arg = Tcl_GetString(objv[2]);
	arg = TkGetStringFromObj(objv[2], &length);
	length = objv[2]->length;
	if (strncmp(arg,"-data", length) == 0) {
	    if (masterPtr->dataString) {
		Tcl_SetObjResult(interp, masterPtr->dataString);
	    if (modelPtr->dataString) {
		Tcl_SetObjResult(interp, modelPtr->dataString);
	    }
	} else if (strncmp(arg,"-format", length) == 0) {
	    if (masterPtr->format) {
		Tcl_SetObjResult(interp, masterPtr->format);
	    if (modelPtr->format) {
		Tcl_SetObjResult(interp, modelPtr->format);
	    }
	} else {
	    Tk_ConfigureValue(interp, Tk_MainWindow(interp), configSpecs,
		    (char *) masterPtr, Tcl_GetString(objv[2]), 0);
		    (char *) modelPtr, Tcl_GetString(objv[2]), 0);
	}
	return TCL_OK;
    }

    case PHOTO_CONFIGURE:
	/*
	 * photo configure command - handle this in the standard way.
	 */

	if (objc == 2) {
	    Tcl_Obj *obj, *subobj;

	    result = Tk_ConfigureInfo(interp, Tk_MainWindow(interp),
		    configSpecs, (char *) masterPtr, NULL, 0);
		    configSpecs, (char *) modelPtr, NULL, 0);
	    if (result != TCL_OK) {
		return result;
	    }
	    obj = Tcl_NewObj();
	    subobj = Tcl_NewStringObj("-data {} {} {}", 14);
	    if (masterPtr->dataString) {
		Tcl_ListObjAppendElement(NULL, subobj, masterPtr->dataString);
	    if (modelPtr->dataString) {
		Tcl_ListObjAppendElement(NULL, subobj, modelPtr->dataString);
	    } else {
		Tcl_AppendStringsToObj(subobj, " {}", NULL);
	    }
	    Tcl_ListObjAppendElement(interp, obj, subobj);
	    subobj = Tcl_NewStringObj("-format {} {} {}", 16);
	    if (masterPtr->format) {
		Tcl_ListObjAppendElement(NULL, subobj, masterPtr->format);
	    if (modelPtr->format) {
		Tcl_ListObjAppendElement(NULL, subobj, modelPtr->format);
	    } 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 = Tcl_GetString(objv[2]);
	    const char *arg = TkGetStringFromObj(objv[2], &length);

	    length = objv[2]->length;
	    if (length > 1 && !strncmp(arg, "-data", length)) {
		Tcl_AppendResult(interp, "-data {} {} {}", NULL);
		if (masterPtr->dataString) {
		if (modelPtr->dataString) {
		    /*
		     * TODO: Modifying result is bad!
		     */

		    Tcl_ListObjAppendElement(NULL, Tcl_GetObjResult(interp),
			    masterPtr->dataString);
			    modelPtr->dataString);
		} else {
		    Tcl_AppendResult(interp, " {}", NULL);
		}
		return TCL_OK;
	    } else if (length > 1 &&
		    !strncmp(arg, "-format", length)) {
		Tcl_AppendResult(interp, "-format {} {} {}", NULL);
		if (masterPtr->format) {
		if (modelPtr->format) {
		    /*
		     * TODO: Modifying result is bad!
		     */

		    Tcl_ListObjAppendElement(NULL, Tcl_GetObjResult(interp),
			    masterPtr->format);
			    modelPtr->format);
		} else {
		    Tcl_AppendResult(interp, " {}", NULL);
		}
		return TCL_OK;
	    } else {
		return Tk_ConfigureInfo(interp, Tk_MainWindow(interp),
			configSpecs, (char *) masterPtr, arg, 0);
			configSpecs, (char *) modelPtr, arg, 0);
	    }
	} else {
	    return ImgPhotoConfigureMaster(interp, masterPtr, objc-2, objv+2,
	    return ImgPhotoConfigureModel(interp, modelPtr, objc-2, objv+2,
		    TK_CONFIG_ARGV_ONLY);
	}

    case PHOTO_COPY:
	/*
	 * photo copy command - first parse options.
	 */
587
588
589
590
591
592
593
594

595
596
597
598
599
600
601
595
596
597
598
599
600
601

602
603
604
605
606
607
608
609







-
+







	}

	/*
	 * Hack to pass through the message that the place we're coming from
	 * has a simple alpha channel.
	 */

	if (!(((PhotoMaster *) srcHandle)->flags & COMPLEX_ALPHA)) {
	if (!(((PhotoModel *) srcHandle)->flags & COMPLEX_ALPHA)) {
	    options.compositingRule |= SOURCE_IS_SIMPLE_ALPHA_PHOTO;
	}

	/*
	 * Fill in default values for unspecified parameters.
	 */

631
632
633
634
635
636
637
638

639
640
641
642
643
644
645
646
647
648
649
650
651
652

653
654
655
656
657
658
659
660
661
662
663
664


665
666
667
668
669
670
671


672
673
674
675
676
677
678
679

680
681
682
683
684
685
686
687
688
689
690

691
692
693
694
695
696
697




698
699
700
701
702
703
704
705
706
707
708
709
710






711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751




































752
753
754
755

756
757
758
759
760
761
762

763
764
765
766
767
768
769
770
771

772
773
774
775
776
777
778
779
780
781
782
783

784
785
786
787
788
789
790
791



792












793
794
795
796
797
798
799
800


801







802
803


804
805




806
807
808
809
810
811


812
813
814
815
816
817
818
819
820
821

822
823
824
825
826
827
828






829
830
831
832



833
834

835
836
837
838
839

840
841
842
843
844
845
846
847
848



849
850
851



852


853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873





















874
875
876
877
878
879
880

881
882
883
884
885

886
887
888
889
890
891
892
893
894
895
896
897
898
899
900

901
902
903

904
905
906
907
908
909
910
911

912
913
914
915
916
917
918
919

920
921
922
923
924
925
926
927
928
929
930

931
932
933
934
935
936
937
938
939
940


941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964

965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991


992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
639
640
641
642
643
644
645

646
647
648
649
650
651
652
653
654
655
656
657
658
659

660
661
662
663
664
665
666
667
668
669
670


671
672
673
674
675
676
677
678

679
680
681
682
683
684
685
686
687

688
689
690
691
692
693
694
695
696
697
698

699
700
701
702




703
704
705
706
707
708
709
710
711
712
713
714
715
716
717


718
719
720
721
722
723
724
725
726
727
728
729



































730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765




766
767
768
769
770
771
772

773
774
775
776
777
778
779
780
781

782
783
784
785
786
787
788
789
790
791
792
793

794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825

826
827
828
829
830
831
832
833
834
835


836
837
838
839
840
841
842
843
844
845
846
847


848
849
850
851
852
853
854
855
856
857
858

859
860
861





862
863
864
865
866
867
868
869
870

871
872
873
874

875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893



894
895
896

897
898
899




















900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920







921





922
923
924













925



926








927








928











929










930
931
























932



























933
934

























935
936
937
938
939
940
941







-
+













-
+










-
-
+
+






-
+
+







-
+










-
+



-
-
-
-
+
+
+
+











-
-
+
+
+
+
+
+






-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+






-
+








-
+











-
+








+
+
+

+
+
+
+
+
+
+
+
+
+
+
+







-
+
+

+
+
+
+
+
+
+
-
-
+
+


+
+
+
+




-
-
+
+









-
+


-
-
-
-
-
+
+
+
+
+
+



-
+
+
+

-
+





+









+
+
+
-
-
-
+
+
+
-
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
-
-
-
-
-
+


-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
+
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







	 * Copy the image data over using Tk_PhotoPutZoomedBlock.
	 */

	block.pixelPtr += options.fromX * block.pixelSize
		+ options.fromY * block.pitch;
	block.width = options.fromX2 - options.fromX;
	block.height = options.fromY2 - options.fromY;
	result = Tk_PhotoPutZoomedBlock(interp, (Tk_PhotoHandle) masterPtr,
	result = Tk_PhotoPutZoomedBlock(interp, (Tk_PhotoHandle) modelPtr,
		&block, options.toX, options.toY, options.toX2 - options.toX,
		options.toY2 - options.toY, options.zoomX, options.zoomY,
		options.subsampleX, options.subsampleY,
		options.compositingRule);

	/*
	 * Set the destination image size if the -shrink option was specified.
	 * This has to be done _after_ copying the data. Otherwise, if source
	 * and destination are the same image, block.pixelPtr would point to
	 * an invalid memory block (bug [5239fd749b]).
	 */

	if (options.options & OPT_SHRINK) {
	    if (ImgPhotoSetSize(masterPtr, options.toX2,
	    if (ImgPhotoSetSize(modelPtr, options.toX2,
		    options.toY2) != TCL_OK) {
		if (options.background) {
		    Tk_FreeColor(options.background);
		}
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			TK_PHOTO_ALLOC_FAILURE_MESSAGE, -1));
		Tcl_SetErrorCode(interp, "TK", "MALLOC", NULL);
		return TCL_ERROR;
	    }
	}
	Tk_ImageChanged(masterPtr->tkMaster, 0, 0, 0, 0,
		masterPtr->width, masterPtr->height);
	Tk_ImageChanged(modelPtr->tkModel, 0, 0, 0, 0,
		modelPtr->width, modelPtr->height);
	if (options.background) {
	    Tk_FreeColor(options.background);
	}
	return result;

    case PHOTO_DATA: {
	char *data;
        char *data = NULL;
        Tcl_Obj *freeObj = NULL;

	/*
	 * photo data command - first parse and check any options given.
	 */

	Tk_ImageStringWriteProc *stringWriteProc = NULL;

	index = 2;
	index = 1;
	memset(&options, 0, sizeof(options));
	options.name = NULL;
	options.format = NULL;
	options.fromX = 0;
	options.fromY = 0;
	if (ParseSubcommandOptions(&options, interp,
		OPT_FORMAT | OPT_FROM | OPT_GRAYSCALE | OPT_BACKGROUND,
		&index, objc, objv) != TCL_OK) {
	    return TCL_ERROR;
	}
	if ((options.name != NULL) || (index < objc)) {
	if ((options.name == NULL) || (index < objc)) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?-option value ...?");
	    return TCL_ERROR;
	}
	if ((options.fromX > masterPtr->width)
		|| (options.fromY > masterPtr->height)
		|| (options.fromX2 > masterPtr->width)
		|| (options.fromY2 > masterPtr->height)) {
	if ((options.fromX > modelPtr->width)
		|| (options.fromY > modelPtr->height)
		|| (options.fromX2 > modelPtr->width)
		|| (options.fromY2 > modelPtr->height)) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "coordinates for -from option extend outside image", -1));
	    Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", "BAD_FROM", NULL);
	    return TCL_ERROR;
	}

	/*
	 * Fill in default values for unspecified parameters.
	 */

	if (!(options.options & OPT_FROM) || (options.fromX2 < 0)) {
	    options.fromX2 = masterPtr->width;
	    options.fromY2 = masterPtr->height;
	    options.fromX2 = modelPtr->width;
	    options.fromY2 = modelPtr->height;
	}
	if (!(options.options & OPT_FORMAT)) {
            options.format = Tcl_NewStringObj("default", -1);
            freeObj = options.format;
	}

	/*
	 * Search for an appropriate image string format handler.
	 */

	if (options.options & OPT_FORMAT) {
	    matched = 0;
	    for (imageFormat = tsdPtr->formatList; imageFormat != NULL;
	 	imageFormat = imageFormat->nextPtr) {
		if ((strncasecmp(Tcl_GetString(options.format),
			imageFormat->name, strlen(imageFormat->name)) == 0)) {
		    matched = 1;
		    if (imageFormat->stringWriteProc != NULL) {
			stringWriteProc = imageFormat->stringWriteProc;
			break;
		    }
		}
	    }
	    if (stringWriteProc == NULL) {
		oldformat = 1;
		for (imageFormat = tsdPtr->oldFormatList; imageFormat != NULL;
			imageFormat = imageFormat->nextPtr) {
		    if ((strncasecmp(Tcl_GetString(options.format),
			    imageFormat->name,
			    strlen(imageFormat->name)) == 0)) {
			matched = 1;
			if (imageFormat->stringWriteProc != NULL) {
			    stringWriteProc = imageFormat->stringWriteProc;
			    break;
			}
		    }
		}
	    }
	    if (stringWriteProc == NULL) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"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);
	matched = 0;
	for (imageFormat = tsdPtr->formatList; imageFormat != NULL;
                imageFormat = imageFormat->nextPtr) {
	    if ((strncasecmp(Tcl_GetString(options.format),
                    imageFormat->name, strlen(imageFormat->name)) == 0)) {
                matched = 1;
                if (imageFormat->stringWriteProc != NULL) {
                    stringWriteProc = imageFormat->stringWriteProc;
                    break;
                }
	    }
	}
#if !defined(TK_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9
	if (stringWriteProc == NULL) {
	    oldformat = 1;
	    for (imageFormat = tsdPtr->oldFormatList; imageFormat != NULL;
                    imageFormat = imageFormat->nextPtr) {
                if ((strncasecmp(Tcl_GetString(options.format),
                        imageFormat->name,
                        strlen(imageFormat->name)) == 0)) {
                    matched = 1;
                    if (imageFormat->stringWriteProc != NULL) {
                        stringWriteProc = imageFormat->stringWriteProc;
                        break;
                    }
                }
	    }
	}
#endif
	if (stringWriteProc == NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                    "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);
		return TCL_ERROR;
	    }
	} else {
	    stringWriteProc = ImgStringWrite;
	    goto dataErrorExit;
	}

	/*
	 * Call the handler's string write function to write out the image.
	 */

	data = ImgGetPhoto(masterPtr, &block, &options);
	data = ImgGetPhoto(modelPtr, &block, &options);

	if (oldformat) {
	    Tcl_DString buffer;
	    typedef int (*OldStringWriteProc)(Tcl_Interp *interp,
		    Tcl_DString *dataPtr, const char *formatString,
		    Tk_PhotoImageBlock *blockPtr);

	    Tcl_DStringInit(&buffer);
	    result = ((OldStringWriteProc) stringWriteProc)(interp, &buffer,
	    result = ((OldStringWriteProc)(void *)stringWriteProc)(interp, &buffer,
		    Tcl_GetString(options.format), &block);
	    if (result == TCL_OK) {
		Tcl_DStringResult(interp, &buffer);
	    } else {
		Tcl_DStringFree(&buffer);
	    }
	} else {
	    typedef int (*NewStringWriteProc)(Tcl_Interp *interp,
		    Tcl_Obj *formatString, Tk_PhotoImageBlock *blockPtr,
		    void *dummy);

	    result = ((NewStringWriteProc) stringWriteProc)(interp,
	    result = ((NewStringWriteProc)(void *)stringWriteProc)(interp,
		    options.format, &block, NULL);
	}
	if (options.background) {
	    Tk_FreeColor(options.background);
	}
	if (data) {
	    ckfree(data);
	}
        if (freeObj != NULL) {
            Tcl_DecrRefCount(freeObj);
        }
	return result;

      dataErrorExit:
        if (options.background) {
	    Tk_FreeColor(options.background);
	}
	if (data) {
	    ckfree(data);
	}
        if (freeObj != NULL) {
            Tcl_DecrRefCount(freeObj);
        }
	return TCL_ERROR;
    }

    case PHOTO_GET: {
	/*
	 * photo get command - first parse and check parameters.
	 */

	Tcl_Obj *channels[3];
	Tcl_Obj *channels[4];
	int channelCount = 3;

        index = 3;
        memset(&options, 0, sizeof(options));
        options.name = NULL;
        if (ParseSubcommandOptions(&options, interp, OPT_WITHALPHA,
                &index, objc, objv) != TCL_OK) {
            return TCL_ERROR;
        }
	if (objc != 4) {
	    Tcl_WrongNumArgs(interp, 2, objv, "x y");
        if (options.name == NULL || index < objc) {
	    Tcl_WrongNumArgs(interp, 2, objv, "x y ?-withalpha?");
	    return TCL_ERROR;
	}
        if (options.options & OPT_WITHALPHA) {
            channelCount = 4;
        }

	if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK)
		|| (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) {
	    return TCL_ERROR;
	}
	if ((x < 0) || (x >= masterPtr->width)
		|| (y < 0) || (y >= masterPtr->height)) {
	if ((x < 0) || (x >= modelPtr->width)
		|| (y < 0) || (y >= modelPtr->height)) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "%s get: coordinates out of range",
		    Tcl_GetString(objv[0])));
	    Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", "COORDINATES",
		    NULL);
	    return TCL_ERROR;
	}

	/*
	 * Extract the value of the desired pixel and format it as a string.
	 * Extract the value of the desired pixel and format it as a list.
	 */

	pixelPtr = masterPtr->pix32 + (y * masterPtr->width + x) * 4;
	channels[0] = Tcl_NewIntObj(pixelPtr[0]);
	channels[1] = Tcl_NewIntObj(pixelPtr[1]);
	channels[2] = Tcl_NewIntObj(pixelPtr[2]);
	Tcl_SetObjResult(interp, Tcl_NewListObj(3, channels));
	pixelPtr = modelPtr->pix32 + (y * modelPtr->width + x) * 4;
	channels[0] = Tcl_NewWideIntObj(pixelPtr[0]);
	channels[1] = Tcl_NewWideIntObj(pixelPtr[1]);
	channels[2] = Tcl_NewWideIntObj(pixelPtr[2]);
	channels[3] = Tcl_NewWideIntObj(pixelPtr[3]);
	Tcl_SetObjResult(interp, Tcl_NewListObj(channelCount, channels));
	return TCL_OK;
    }

    case PHOTO_PUT:
    case PHOTO_PUT: {
	Tcl_Obj *format, *data;

	/*
	 * photo put command - first parse the options and colors specified.
	 * photo put command - first parse the options.
	 */

	index = 2;
	memset(&options, 0, sizeof(options));
	options.name = NULL;
	options.format = NULL;
	if (ParseSubcommandOptions(&options, interp, OPT_TO|OPT_FORMAT,
		&index, objc, objv) != TCL_OK) {
	    return TCL_ERROR;
	}
	if ((options.name == NULL) || (index < objc)) {
	    Tcl_WrongNumArgs(interp, 2, objv, "data ?-option value ...?");
	    return TCL_ERROR;
	}

	/*
	 * See if there's a format that can read the data
	 */
	if (MatchStringFormat(interp, options.name ? objv[2]:NULL,
		options.format, &imageFormat, &imageWidth,
		&imageHeight, &oldformat) == TCL_OK) {

	if (MatchStringFormat(interp, objv[2], options.format, &imageFormat,
		&imageWidth, &imageHeight, &oldformat) != TCL_OK) {
	    Tcl_Obj *format, *data;
	    return TCL_ERROR;
	}

	    if (!(options.options & OPT_TO) || (options.toX2 < 0)) {
		options.toX2 = options.toX + imageWidth;
		options.toY2 = options.toY + imageHeight;
	    }
	    if (imageWidth > options.toX2 - options.toX) {
		imageWidth = options.toX2 - options.toX;
	    }
	    if (imageHeight > options.toY2 - options.toY) {
		imageHeight = options.toY2 - options.toY;
	    }
	    format = options.format;
	    data = objv[2];
	    if (oldformat) {
		if (format) {
		    format = (Tcl_Obj *) Tcl_GetString(format);
		}
		data = (Tcl_Obj *) Tcl_GetString(data);
	    }
	    if (imageFormat->stringReadProc(interp, data, format,
		    (Tk_PhotoHandle) masterPtr, options.toX, options.toY,
	if (!(options.options & OPT_TO) || (options.toX2 < 0)) {
	    options.toX2 = options.toX + imageWidth;
	    options.toY2 = options.toY + imageHeight;
	}
	if (imageWidth > options.toX2 - options.toX) {
	    imageWidth = options.toX2 - options.toX;
	}
	if (imageHeight > options.toY2 - options.toY) {
	    imageHeight = options.toY2 - options.toY;
	}
	format = options.format;
	data = objv[2];
	if (oldformat) {
	    if (format) {
		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,
		    imageWidth, imageHeight, 0, 0) != TCL_OK) {
		return TCL_ERROR;
	    }
	    masterPtr->flags |= IMAGE_CHANGED;
	    return TCL_OK;
	}
	if (options.options & OPT_FORMAT) {
		options.toX2 - options.toX,
	    return TCL_ERROR;
	}
	Tcl_ResetResult(interp);
	if (Tcl_ListObjGetElements(interp, options.name,
		&dataHeight, &srcObjv) != TCL_OK) {
		options.toY2 - options.toY, 0, 0) != TCL_OK) {
	    return TCL_ERROR;
	}
	tkwin = Tk_MainWindow(interp);
	block.pixelPtr = NULL;
	dataWidth = 0;
	pixelPtr = NULL;
	for (y = 0; y < dataHeight; ++y) {
	    if (Tcl_ListObjGetElements(interp, srcObjv[y],
		    &listObjc, &listObjv) != TCL_OK) {
		break;
	    }

	    if (y == 0) {
		if (listObjc == 0) {
		    /*
	/*
		     * Lines must be non-empty...
		     */

	 * SB: is the next line really needed? The stringReadProc
		    break;
		}
		dataWidth = listObjc;
		/*
 		 * Memory allocation overflow protection.
 		 * May not be able to trigger/ demo / test this.
 		 */

	 * writes image data with Tk_PhotoPutBlock(), which in turn
		if (dataWidth > (int)((UINT_MAX/3) / dataHeight)) {
		    Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"photo image dimensions exceed Tcl memory limits", -1));
		    Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO",
			"OVERFLOW", NULL);
		    break;
		}

	 * takes care to notify the changed image and to set/unset the
		pixelPtr = ckalloc(dataWidth * dataHeight * 3);
		block.pixelPtr = pixelPtr;
	    } else if (listObjc != dataWidth) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"all elements of color list must have the same"
			" number of elements", -1));
		Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO",
			"NON_RECTANGULAR", NULL);
		break;
	    }

	 * IMAGE_CHANGED bit.
	    for (x = 0; x < dataWidth; ++x) {
		const char *colorString = Tcl_GetString(listObjv[x]);
		XColor color;
		int tmpr, tmpg, tmpb;

		/*
		 * We do not use Tk_GetColorFromObj() because we absolutely do
		 * not want to invoke the fallback code.
		 */

	 */
	modelPtr->flags |= IMAGE_CHANGED;
		if (colorString[0] == '#') {
		    if (isxdigit(UCHAR(colorString[1])) &&
			    isxdigit(UCHAR(colorString[2])) &&
			    isxdigit(UCHAR(colorString[3]))) {
			if (colorString[4] == '\0') {
			    /* Got #rgb */
			    sscanf(colorString+1, "%1x%1x%1x",
				    &tmpr, &tmpg, &tmpb);
			    *pixelPtr++ = tmpr * 0x11;
			    *pixelPtr++ = tmpg * 0x11;
			    *pixelPtr++ = tmpb * 0x11;
			    continue;
			} else if (isxdigit(UCHAR(colorString[4])) &&
				isxdigit(UCHAR(colorString[5])) &&
				isxdigit(UCHAR(colorString[6])) &&
				colorString[7] == '\0') {
			    /* Got #rrggbb */
			    sscanf(colorString+1, "%2x%2x%2x",
				    &tmpr, &tmpg, &tmpb);
			    *pixelPtr++ = tmpr;
			    *pixelPtr++ = tmpg;
			    *pixelPtr++ = tmpb;
			    continue;
			}

		    }
		}

		if (!TkParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin),
			colorString, &color)) {
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			    "can't parse color \"%s\"", colorString));
		    Tcl_SetErrorCode(interp, "TK", "VALUE", "COLOR", NULL);
		    break;
		}
		*pixelPtr++ = color.red >> 8;
		*pixelPtr++ = color.green >> 8;
		*pixelPtr++ = color.blue >> 8;
	    }
	    if (x < dataWidth) {
		break;
	    }
	}
	if (y < dataHeight || dataHeight == 0 || dataWidth == 0) {
	    if (block.pixelPtr != NULL) {
		ckfree(block.pixelPtr);
	    }
	    if (y < dataHeight) {
		return TCL_ERROR;
	    }
	    return TCL_OK;
	}
	return TCL_OK;
    }

	/*
	 * Fill in default values for the -to option, then copy the block in
	 * using Tk_PhotoPutBlock.
	 */

	if (!(options.options & OPT_TO) || (options.toX2 < 0)) {
	    options.toX2 = options.toX + dataWidth;
	    options.toY2 = options.toY + dataHeight;
	}
	block.width = dataWidth;
	block.height = dataHeight;
	block.pitch = dataWidth * 3;
	block.pixelSize = 3;
	block.offset[0] = 0;
	block.offset[1] = 1;
	block.offset[2] = 2;
	block.offset[3] = 0;
	result = Tk_PhotoPutBlock(interp, masterPtr, &block,
		options.toX, options.toY, options.toX2 - options.toX,
		options.toY2 - options.toY,
		TK_PHOTO_COMPOSITE_SET);
	ckfree(block.pixelPtr);
	return result;

    case PHOTO_READ: {
	Tcl_Obj *format;

	/*
	 * photo read command - first parse the options specified.
	 */

1096
1097
1098
1099
1100
1101
1102
1103

1104
1105
1106
1107
1108

1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124

1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147





1148
1149

1150
1151
1152
1153



1154
1155
1156

1157
1158
1159
1160
1161
1162
1163



1164
1165
1166
1167
1168
1169
1170
1014
1015
1016
1017
1018
1019
1020

1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042

1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061





1062
1063
1064
1065
1066
1067

1068
1069



1070
1071
1072
1073
1074

1075
1076
1077
1078
1079



1080
1081
1082
1083
1084
1085
1086
1087
1088
1089







-
+





+















-
+


















-
-
-
-
-
+
+
+
+
+

-
+

-
-
-
+
+
+


-
+




-
-
-
+
+
+







	}

	/*
	 * If the -shrink option was specified, set the size of the image.
	 */

	if (options.options & OPT_SHRINK) {
	    if (ImgPhotoSetSize(masterPtr, options.toX + width,
	    if (ImgPhotoSetSize(modelPtr, options.toX + width,
		    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;
	    }
	}

	/*
	 * Call the handler's file read function to read the data into the
	 * image.
	 */

	format = options.format;
	if (oldformat && format) {
	    format = (Tcl_Obj *) Tcl_GetString(format);
	}
	result = imageFormat->fileReadProc(interp, chan,
		Tcl_GetString(options.name),
		format, (Tk_PhotoHandle) masterPtr, options.toX,
		format, (Tk_PhotoHandle) modelPtr, options.toX,
		options.toY, width, height, options.fromX, options.fromY);
	if (chan != NULL) {
	    Tcl_Close(NULL, chan);
	}
	return result;
    }

    case PHOTO_REDITHER:
	if (objc != 2) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}

	/*
	 * Call Dither if any part of the image is not correctly dithered at
	 * present.
	 */

	x = masterPtr->ditherX;
	y = masterPtr->ditherY;
	if (masterPtr->ditherX != 0) {
	    Tk_DitherPhoto((Tk_PhotoHandle) masterPtr, x, y,
		    masterPtr->width - x, 1);
	x = modelPtr->ditherX;
	y = modelPtr->ditherY;
	if (modelPtr->ditherX != 0) {
	    Tk_DitherPhoto((Tk_PhotoHandle) modelPtr, x, y,
		    modelPtr->width - x, 1);
	}
	if (masterPtr->ditherY < masterPtr->height) {
	if (modelPtr->ditherY < modelPtr->height) {
	    x = 0;
	    Tk_DitherPhoto((Tk_PhotoHandle)masterPtr, 0,
		    masterPtr->ditherY, masterPtr->width,
		    masterPtr->height - masterPtr->ditherY);
	    Tk_DitherPhoto((Tk_PhotoHandle)modelPtr, 0,
		    modelPtr->ditherY, modelPtr->width,
		    modelPtr->height - modelPtr->ditherY);
	}

	if (y < masterPtr->height) {
	if (y < modelPtr->height) {
	    /*
	     * Tell the core image code that part of the image has changed.
	     */

	    Tk_ImageChanged(masterPtr->tkMaster, x, y,
		    (masterPtr->width - x), (masterPtr->height - y),
		    masterPtr->width, masterPtr->height);
	    Tk_ImageChanged(modelPtr->tkModel, x, y,
		    (modelPtr->width - x), (modelPtr->height - y),
		    modelPtr->width, modelPtr->height);
	}
	return TCL_OK;

    case PHOTO_TRANS: {
	static const char *const photoTransOptions[] = {
	    "get", "set", NULL
	};
1179
1180
1181
1182
1183
1184
1185

1186
1187




1188
1189
1190


1191
1192
1193
1194
1195
1196




















1197
1198


1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209




1210
1211
1212


1213
1214
1215
1216
1217
1218


1219

1220
1221
1222
1223
1224

1225

1226




1227
1228


1229
1230
1231
1232
1233
1234








1235
1236













1237
1238


1239
1240
1241
1242
1243
1244
1245
1246


1247
1248
1249
1250













1251
1252
1253
1254
1255
1256






1257




1258
1259


1260
1261
1262
1263
1264
1265

1266
1267


1268






1269



1270
1271
1272
1273
1274

1275
1276

1277
1278

1279
1280
1281
1282
1283
1284
1285
1286
1287



1288
1289
1290
1291
1292
1293
1294
1098
1099
1100
1101
1102
1103
1104
1105


1106
1107
1108
1109
1110


1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138


1139
1140
1141
1142
1143
1144
1145
1146
1147
1148



1149
1150
1151
1152



1153
1154






1155
1156

1157
1158
1159
1160
1161

1162
1163
1164
1165
1166
1167
1168
1169


1170
1171
1172
1173
1174



1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197


1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209




1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222






1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233


1234
1235




1236

1237


1238
1239
1240
1241
1242
1243
1244
1245
1246

1247
1248
1249
1250




1251


1252

1253
1254
1255
1256
1257
1258
1259
1260



1261
1262
1263
1264
1265
1266
1267
1268
1269
1270







+
-
-
+
+
+
+

-
-
+
+






+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+








-
-
-
+
+
+
+
-
-
-
+
+
-
-
-
-
-
-
+
+
-
+




-
+

+

+
+
+
+
-
-
+
+



-
-
-
+
+
+
+
+
+
+
+


+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+








+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+

+
+
+
+
-
-
+
+
-
-
-
-

-
+
-
-
+
+

+
+
+
+
+
+
-
+
+
+

-
-
-
-
+
-
-
+
-

+






-
-
-
+
+
+







	if (Tcl_GetIndexFromObj(interp, objv[2], photoTransOptions, "option",
		0, &index) != TCL_OK) {
	    return TCL_ERROR;
	}

	switch ((enum transOptions) index) {
	case PHOTO_TRANS_GET: {
	    int boolMode;
	    XRectangle testBox;
	    TkRegion testRegion;

	    /*
	     * parse fixed args and option
	     */

	    if (objc != 5) {
		Tcl_WrongNumArgs(interp, 3, objv, "x y");
	    if (objc > 6 || objc < 5) {
		Tcl_WrongNumArgs(interp, 3, objv, "x y ?-option?");
		return TCL_ERROR;
	    }
	    if ((Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK)
		    || (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK)) {
		return TCL_ERROR;
	    }

	    index = 4;
	    memset(&options, 0, sizeof(options));
	    if (ParseSubcommandOptions(&options, interp,
		    OPT_ALPHA, &index, objc, objv) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if (index < objc) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"unknown option \"%s\": must be -alpha",
			Tcl_GetString(objv[index])));
		Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", "BAD_OPTION",
			NULL);
		return TCL_ERROR;
	    }
	    boolMode = 1;
	    if (options.options & OPT_ALPHA) {
		boolMode = 0;
	    }

	    if ((x < 0) || (x >= masterPtr->width)
		    || (y < 0) || (y >= masterPtr->height)) {
	    if ((x < 0) || (x >= modelPtr->width)
		    || (y < 0) || (y >= modelPtr->height)) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"%s transparency get: coordinates out of range",
			Tcl_GetString(objv[0])));
		Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", "COORDINATES",
			NULL);
		return TCL_ERROR;
	    }

	    testBox.x = x;
	    testBox.y = y;
	    testBox.width = 1;
	    /*
	     * Extract and return the desired value
	     */
	    pixelPtr = modelPtr->pix32 + (y * modelPtr->width + x) * 4;
	    testBox.height = 1;
	    /* What a way to do a test! */
	    testRegion = TkCreateRegion();
	    if (boolMode) {
		Tcl_SetObjResult(interp, Tcl_NewBooleanObj( ! pixelPtr[3]));
	    TkUnionRectWithRegion(&testBox, testRegion, testRegion);
	    TkIntersectRegion(testRegion, masterPtr->validRegion, testRegion);
	    TkClipBox(testRegion, &testBox);
	    TkDestroyRegion(testRegion);

	    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(
	    } else {
		Tcl_SetObjResult(interp, Tcl_NewWideIntObj(pixelPtr[3]));
		    testBox.width==0 && testBox.height==0));
	    }
	    return TCL_OK;
	}

	case PHOTO_TRANS_SET: {
	    int transFlag;
	    int newVal, boolMode;
	    XRectangle setBox;
	    TkRegion modRegion;

	    /*
	     * Parse args and option, check for valid values
	     */

	    if (objc != 6) {
		Tcl_WrongNumArgs(interp, 3, objv, "x y boolean");
	    if (objc < 6 || objc > 7) {
		Tcl_WrongNumArgs(interp, 3, objv, "x y newVal ?-option?");
		return TCL_ERROR;
	    }
	    if ((Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK)
		    || (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK)
		    || (Tcl_GetBooleanFromObj(interp, objv[5],
		    &transFlag) != TCL_OK)) {
		    || (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK)) {
		return TCL_ERROR;
	    }

	    index = 5;
	    memset(&options, 0, sizeof(options));
	    if (ParseSubcommandOptions(&options, interp,
		    OPT_ALPHA, &index, objc, objv) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if (index < objc) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"unknown option \"%s\": must be -alpha",
			Tcl_GetString(objv[index])));
		Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", "BAD_OPTION",
			NULL);
		return TCL_ERROR;
	    }
	    boolMode = 1;
	    if (options.options & OPT_ALPHA) {
		boolMode = 0;
	    }

	    if ((x < 0) || (x >= masterPtr->width)
		|| (y < 0) || (y >= masterPtr->height)) {
	    if ((x < 0) || (x >= modelPtr->width)
		|| (y < 0) || (y >= modelPtr->height)) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"%s transparency set: coordinates out of range",
			Tcl_GetString(objv[0])));
		Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", "COORDINATES",
			NULL);
		return TCL_ERROR;
	    }

	    if (boolMode) {
		if (Tcl_GetBooleanFromObj(interp, objv[5], &newVal) != TCL_OK) {
	    setBox.x = x;
	    setBox.y = y;
	    setBox.width = 1;
	    setBox.height = 1;
		    return TCL_ERROR;
		}
	    } else {
		if (Tcl_GetIntFromObj(interp, objv[5], &newVal) != TCL_OK) {
		    return TCL_ERROR;
		}
		if (newVal < 0 || newVal > 255) {
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			    "invalid alpha value \"%d\": "
			    "must be integer between 0 and 255", newVal));
		    Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO",
			    "BAD_VALUE", NULL);
		    return TCL_ERROR;
	    pixelPtr = masterPtr->pix32 + (y * masterPtr->width + x) * 4;

	    if (transFlag) {
		/*
		 * Make pixel transparent.
		 */
		}
	    }

	    /*
	     * Set new alpha value for the pixel
	     */

	    pixelPtr = modelPtr->pix32 + (y * modelPtr->width + x) * 4;
	    if (boolMode) {
		pixelPtr[3] = newVal ? 0 : 255;
	    } else {
		TkRegion clearRegion = TkCreateRegion();

		pixelPtr[3] = newVal;
	    }
		TkUnionRectWithRegion(&setBox, clearRegion, clearRegion);
		TkSubtractRegion(masterPtr->validRegion, clearRegion,
			masterPtr->validRegion);
		TkDestroyRegion(clearRegion);

		/*
	    /*
		 * Set the alpha value correctly.
		 */
	     * Update the validRegion of the image
	     */

	    setBox.x = x;
	    setBox.y = y;
	    setBox.width = 1;
	    setBox.height = 1;
	    modRegion = TkCreateRegion();
	    TkUnionRectWithRegion(&setBox, modRegion, modRegion);
		pixelPtr[3] = 0;
	    if (pixelPtr[3]) {
		TkUnionRectWithRegion(&setBox, modelPtr->validRegion,
			modelPtr->validRegion);
	    } else {
		/*
		 * Make pixel opaque.
		 */

		TkSubtractRegion(modelPtr->validRegion, modRegion,
		TkUnionRectWithRegion(&setBox, masterPtr->validRegion,
			masterPtr->validRegion);
			modelPtr->validRegion);
		pixelPtr[3] = 255;
	    }
	    TkDestroyRegion(modRegion);

	    /*
	     * Inform the generic image code that the image
	     * has (potentially) changed.
	     */

	    Tk_ImageChanged(masterPtr->tkMaster, x, y, 1, 1,
		    masterPtr->width, masterPtr->height);
	    masterPtr->flags &= ~IMAGE_CHANGED;
	    Tk_ImageChanged(modelPtr->tkModel, x, y, 1, 1,
		    modelPtr->width, modelPtr->height);
	    modelPtr->flags &= ~IMAGE_CHANGED;
	    return TCL_OK;
	}

	}
	Tcl_Panic("unexpected fallthrough");
    }

1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332




1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347


1348
1349
1350
1351
1352
1353
1354
1298
1299
1300
1301
1302
1303
1304




1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321


1322
1323
1324
1325
1326
1327
1328
1329
1330







-
-
-
-
+
+
+
+













-
-
+
+







		&index, objc, objv) != TCL_OK) {
	    return TCL_ERROR;
	}
	if ((options.name == NULL) || (index < objc)) {
	    Tcl_WrongNumArgs(interp, 2, objv, "fileName ?-option value ...?");
	    return TCL_ERROR;
	}
	if ((options.fromX > masterPtr->width)
		|| (options.fromY > masterPtr->height)
		|| (options.fromX2 > masterPtr->width)
		|| (options.fromY2 > masterPtr->height)) {
	if ((options.fromX > modelPtr->width)
		|| (options.fromY > modelPtr->height)
		|| (options.fromX2 > modelPtr->width)
		|| (options.fromY2 > modelPtr->height)) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "coordinates for -from option extend outside image", -1));
	    Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", "BAD_FROM", NULL);
	    return TCL_ERROR;
	}

	/*
	 * Fill in default values for unspecified parameters. Note that a
	 * missing -format flag results in us having a guess from the file
	 * extension. [Bug 2983824]
	 */

	if (!(options.options & OPT_FROM) || (options.fromX2 < 0)) {
	    options.fromX2 = masterPtr->width;
	    options.fromY2 = masterPtr->height;
	    options.fromX2 = modelPtr->width;
	    options.fromY2 = modelPtr->height;
	}
	if (options.format == NULL) {
	    fmtString = GetExtension(Tcl_GetString(options.name));
	    usedExt = (fmtString != NULL);
	} else {
	    fmtString = Tcl_GetString(options.format);
	    usedExt = 0;
1368
1369
1370
1371
1372
1373
1374

1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388

1389
1390
1391
1392
1393
1394
1395
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373







+














+







			    strlen(imageFormat->name)) == 0)) {
		matched = 1;
		if (imageFormat->fileWriteProc != NULL) {
		    break;
		}
	    }
	}
#if !defined(TK_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9
	if (imageFormat == NULL) {
	    oldformat = 1;
	    for (imageFormat = tsdPtr->oldFormatList; imageFormat != NULL;
		    imageFormat = imageFormat->nextPtr) {
		if ((fmtString == NULL)
			|| (strncasecmp(fmtString, imageFormat->name,
				strlen(imageFormat->name)) == 0)) {
		    matched = 1;
		    if (imageFormat->fileWriteProc != NULL) {
			break;
		    }
		}
	    }
	}
#endif
	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.
	     */

1415
1416
1417
1418
1419
1420
1421
1422

1423
1424
1425
1426
1427
1428
1429
1393
1394
1395
1396
1397
1398
1399

1400
1401
1402
1403
1404
1405
1406
1407







-
+







	    return TCL_ERROR;
	}

	/*
	 * Call the handler's file write function to write out the image.
	 */

	data = ImgGetPhoto(masterPtr, &block, &options);
	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 (options.background) {
1473
1474
1475
1476
1477
1478
1479
1480




1481
1482
1483
1484
1485
1486



1487
1488
1489
1490
1491
1492
1493
1451
1452
1453
1454
1455
1456
1457

1458
1459
1460
1461
1462
1463
1464
1465
1466

1467
1468
1469
1470
1471
1472
1473
1474
1475
1476







-
+
+
+
+





-
+
+
+







/*
 *----------------------------------------------------------------------
 *
 * 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, and -compositingrule.
 *	-subsample, -format, -shrink, -compositingrule, -alpha, -boolean and
 *	-withalpha.
 *	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.
 *
 * Side effects:
 *	Fields in *optPtr get filled in.
 *	Fields in *optPtr get filled in. The value of optIndexPtr is updated
 *	to contain the index of the first element in argv[] that was not
 *	parsed, or argc if the end of objv[] was reached.
 *
 *----------------------------------------------------------------------
 */

static int
ParseSubcommandOptions(
    struct SubcommandOptions *optPtr,
1503
1504
1505
1506
1507
1508
1509
1510

1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523

1524
1525
1526
1527
1528
1529
1530
1531
1486
1487
1488
1489
1490
1491
1492

1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505

1506

1507
1508
1509
1510
1511
1512
1513







-
+












-
+
-







    Tcl_Obj *const objv[])	/* Arguments to be parsed. */
{
    static const char *const compositingRules[] = {
	"overlay", "set",	/* Note that these must match the
				 * TK_PHOTO_COMPOSITE_* constants. */
	NULL
    };
    size_t length;
    TkSizeT length;
    int index, c, bit, currentBit;
    int values[4], numValues, maxValues, argIndex;
    const char *option, *expandedOption, *needed;
    const char *const *listPtr;
    Tcl_Obj *msgObj;

    for (index = *optIndexPtr; index < objc; *optIndexPtr = ++index) {
	/*
	 * We can have one value specified without an option; it goes into
	 * optPtr->name.
	 */

	expandedOption = option = Tcl_GetString(objv[index]);
	expandedOption = option = TkGetStringFromObj(objv[index], &length);
	length = objv[index]->length;
	if (option[0] != '-') {
	    if (optPtr->name == NULL) {
		optPtr->name = objv[index];
		continue;
	    }
	    break;
	}
1604
1605
1606
1607
1608
1609
1610
1611


1612
1613
1614
1615
1616
1617
1618
1586
1587
1588
1589
1590
1591
1592

1593
1594
1595
1596
1597
1598
1599
1600
1601







-
+
+







	    index++;
	    if (Tcl_GetIndexFromObj(interp, objv[index], compositingRules,
		    "compositing rule", 0, &optPtr->compositingRule)
		    != TCL_OK) {
		return TCL_ERROR;
	    }
	    *optIndexPtr = index;
	} else if ((bit != OPT_SHRINK) && (bit != OPT_GRAYSCALE)) {
	} else if (bit == OPT_TO || bit == OPT_FROM
		|| bit == OPT_SUBSAMPLE || bit == OPT_ZOOM) {
	    const char *val;

	    maxValues = ((bit == OPT_FROM) || (bit == OPT_TO)) ? 4 : 2;
	    argIndex = index + 1;
	    for (numValues = 0; numValues < maxValues; ++numValues) {
		if (argIndex >= objc) {
		    break;
1754
1755
1756
1757
1758
1759
1760
1761

1762
1763
1764
1765
1766
1767
1768
1769

1770
1771
1772
1773
1774
1775
1776
1777
1778
1779

1780
1781

1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792

1793
1794
1795
1796
1797
1798
1799

1800
1801

1802
1803
1804
1805
1806
1807
1808
1809
1737
1738
1739
1740
1741
1742
1743

1744
1745
1746
1747
1748
1749
1750
1751

1752
1753
1754
1755
1756
1757
1758
1759
1760
1761

1762
1763

1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774

1775
1776
1777
1778
1779
1780
1781

1782
1783

1784

1785
1786
1787
1788
1789
1790
1791







-
+







-
+









-
+

-
+










-
+






-
+

-
+
-







    Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", "BAD_OPTION", NULL);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * ImgPhotoConfigureMaster --
 * ImgPhotoConfigureModel --
 *
 *	This function is called when a photo image is created or reconfigured.
 *	It processes configuration options and resets any instances of the
 *	image.
 *
 * Results:
 *	A standard Tcl return value. If TCL_ERROR is returned then an error
 *	message is left in the masterPtr->interp's result.
 *	message is left in the modelPtr->interp's result.
 *
 * Side effects:
 *	Existing instances of the image will be redisplayed to match the new
 *	configuration options.
 *
 *----------------------------------------------------------------------
 */

static int
ImgPhotoConfigureMaster(
ImgPhotoConfigureModel(
    Tcl_Interp *interp,		/* Interpreter to use for reporting errors. */
    PhotoMaster *masterPtr,	/* Pointer to data structure describing
    PhotoModel *modelPtr,	/* Pointer to data structure describing
				 * overall photo image to (re)configure. */
    int objc,			/* Number of entries in objv. */
    Tcl_Obj *const objv[],	/* Pairs of configuration options for image. */
    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 *tempdata, *tempformat;
    size_t length;
    TkSizeT length;
    int i, j, result, imageWidth, imageHeight, oldformat;
    double oldGamma;
    Tcl_Channel chan;
    Tk_PhotoImageFormat *imageFormat;
    const char **args;

    args = ckalloc((objc + 1) * sizeof(char *));
    args = (const char **)ckalloc((objc + 1) * sizeof(char *));
    for (i = 0, j = 0; i < objc; i++,j++) {
	args[j] = Tcl_GetString(objv[i]);
	args[j] = TkGetStringFromObj(objv[i], &length);
	length = 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];
		    j--;
		} else {
1834
1835
1836
1837
1838
1839
1840
1841

1842
1843

1844
1845
1846
1847
1848
1849
1850

1851
1852
1853
1854
1855


1856
1857
1858
1859
1860
1861
1862

1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874



1875
1876
1877
1878
1879
1880
1881

1882
1883

1884
1885
1886
1887
1888
1889
1890


1891
1892

1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907


1908
1909

1910
1911
1912
1913
1914
1915
1916
1917


1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931



1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945

1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957


1958
1959
1960
1961
1962

1963
1964
1965
1966
1967
1968
1969
1970

1971
1972
1973
1974
1975

1976
1977
1978
1979
1980
1981
1982
1983

1984
1985
1986
1987
1988



1989
1990
1991


1992
1993
1994
1995

1996
1997
1998
1999
2000
2001
2002


2003
2004
2005
2006
2007
2008
2009
2010

2011
2012
2013
2014
2015
2016

2017
2018
2019
2020
2021
2022
2023
2024


2025
2026
2027
2028
2029



2030
2031
2032
2033
2034
2035
2036
2037
2038

2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049



2050
2051
2052
2053
2054
2055
2056
2057
2058

2059
2060
2061
2062
2063
2064
2065
1816
1817
1818
1819
1820
1821
1822

1823
1824

1825
1826
1827
1828
1829
1830
1831

1832
1833
1834
1835


1836
1837
1838
1839
1840
1841
1842
1843

1844
1845
1846
1847
1848
1849
1850
1851
1852
1853



1854
1855
1856
1857
1858
1859
1860
1861
1862

1863
1864

1865
1866
1867
1868
1869
1870


1871
1872
1873

1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887


1888
1889
1890

1891
1892
1893
1894
1895
1896
1897


1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910



1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926

1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937


1938
1939
1940
1941
1942
1943

1944
1945
1946
1947
1948
1949
1950
1951

1952
1953
1954
1955
1956

1957
1958
1959
1960
1961
1962
1963
1964

1965
1966
1967



1968
1969
1970
1971


1972
1973
1974
1975
1976

1977
1978
1979
1980
1981
1982


1983
1984
1985
1986
1987
1988
1989
1990
1991

1992
1993
1994
1995
1996
1997

1998
1999
2000
2001
2002
2003
2004


2005
2006
2007
2008



2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019

2020
2021
2022
2023
2024
2025
2026
2027
2028



2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039

2040
2041
2042
2043
2044
2045
2046
2047







-
+

-
+






-
+



-
-
+
+






-
+









-
-
-
+
+
+






-
+

-
+





-
-
+
+

-
+













-
-
+
+

-
+






-
-
+
+











-
-
-
+
+
+













-
+










-
-
+
+




-
+







-
+




-
+







-
+


-
-
-
+
+
+

-
-
+
+



-
+





-
-
+
+







-
+





-
+






-
-
+
+


-
-
-
+
+
+








-
+








-
-
-
+
+
+








-
+







    /*
     * Save the current values for fileString and dataString, so we can tell
     * if the user specifies them anew. IMPORTANT: if the format changes we
     * have to interpret "-file" and "-data" again as well! It might be that
     * the format string influences how "-data" or "-file" is interpreted.
     */

    oldFileString = masterPtr->fileString;
    oldFileString = modelPtr->fileString;
    if (oldFileString == NULL) {
	oldData = masterPtr->dataString;
	oldData = modelPtr->dataString;
	if (oldData != NULL) {
	    Tcl_IncrRefCount(oldData);
	}
    } else {
	oldData = NULL;
    }
    oldFormat = masterPtr->format;
    oldFormat = modelPtr->format;
    if (oldFormat != NULL) {
	Tcl_IncrRefCount(oldFormat);
    }
    oldPaletteString = masterPtr->palette;
    oldGamma = masterPtr->gamma;
    oldPaletteString = modelPtr->palette;
    oldGamma = modelPtr->gamma;

    /*
     * Process the configuration options specified.
     */

    if (Tk_ConfigureWidget(interp, Tk_MainWindow(interp), configSpecs,
	    j, args, (char *) masterPtr, flags) != TCL_OK) {
	    j, args, (char *) modelPtr, flags) != TCL_OK) {
	ckfree(args);
	goto errorExit;
    }
    ckfree(args);

    /*
     * Regard the empty string for -file, -data or -format as the null value.
     */

    if ((masterPtr->fileString != NULL) && (masterPtr->fileString[0] == 0)) {
	ckfree(masterPtr->fileString);
	masterPtr->fileString = NULL;
    if ((modelPtr->fileString != NULL) && (modelPtr->fileString[0] == 0)) {
	ckfree(modelPtr->fileString);
	modelPtr->fileString = NULL;
    }
    if (data) {
	/*
	 * Force into ByteArray format, which most (all) image handlers will
	 * use anyway. Empty length means ignore the -data option.
	 */
	int bytesize;
	TkSizeT bytesize;

	(void) Tcl_GetByteArrayFromObj(data, &bytesize);
	(void) TkGetByteArrayFromObj(data, &bytesize);
	if (bytesize) {
	    Tcl_IncrRefCount(data);
	} else {
	    data = NULL;
	}
	if (masterPtr->dataString) {
	    Tcl_DecrRefCount(masterPtr->dataString);
	if (modelPtr->dataString) {
	    Tcl_DecrRefCount(modelPtr->dataString);
	}
	masterPtr->dataString = data;
	modelPtr->dataString = data;
    }
    if (format) {
	/*
	 * Stringify to ignore -format "". It may come in as a list or other
	 * object.
	 */

	(void) Tcl_GetString(format);
	if (format->length) {
	    Tcl_IncrRefCount(format);
	} else {
	    format = NULL;
	}
	if (masterPtr->format) {
	    Tcl_DecrRefCount(masterPtr->format);
	if (modelPtr->format) {
	    Tcl_DecrRefCount(modelPtr->format);
	}
	masterPtr->format = format;
	modelPtr->format = format;
    }
    /*
     * Set the image to the user-requested size, if any, and make sure storage
     * is correctly allocated for this image.
     */

    if (ImgPhotoSetSize(masterPtr, masterPtr->width,
	    masterPtr->height) != TCL_OK) {
    if (ImgPhotoSetSize(modelPtr, modelPtr->width,
	    modelPtr->height) != TCL_OK) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		TK_PHOTO_ALLOC_FAILURE_MESSAGE, -1));
	Tcl_SetErrorCode(interp, "TK", "MALLOC", NULL);
	goto errorExit;
    }

    /*
     * Read in the image from the file or string if the user has specified the
     * -file or -data option.
     */

    if ((masterPtr->fileString != NULL)
	    && ((masterPtr->fileString != oldFileString)
	    || (masterPtr->format != oldFormat))) {
    if ((modelPtr->fileString != NULL)
	    && ((modelPtr->fileString != oldFileString)
	    || (modelPtr->format != oldFormat))) {
	/*
	 * Prevent file system access in a safe interpreter.
	 */

	if (Tcl_IsSafe(interp)) {
	    Tcl_ResetResult(interp);
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "can't get image from a file in a safe interpreter",
		    -1));
	    Tcl_SetErrorCode(interp, "TK", "SAFE", "PHOTO_FILE", NULL);
	    goto errorExit;
	}

	chan = Tcl_OpenFileChannel(interp, masterPtr->fileString, "r", 0);
	chan = Tcl_OpenFileChannel(interp, modelPtr->fileString, "r", 0);
	if (chan == NULL) {
	    goto errorExit;
	}

	/*
	 * -translation binary also sets -encoding binary
	 */

	if ((Tcl_SetChannelOption(interp, chan,
		"-translation", "binary") != TCL_OK) ||
		(MatchFileFormat(interp, chan, masterPtr->fileString,
			masterPtr->format, &imageFormat, &imageWidth,
		(MatchFileFormat(interp, chan, modelPtr->fileString,
			modelPtr->format, &imageFormat, &imageWidth,
			&imageHeight, &oldformat) != TCL_OK)) {
	    Tcl_Close(NULL, chan);
	    goto errorExit;
	}
	result = ImgPhotoSetSize(masterPtr, imageWidth, imageHeight);
	result = ImgPhotoSetSize(modelPtr, imageWidth, imageHeight);
	if (result != TCL_OK) {
	    Tcl_Close(NULL, chan);
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    TK_PHOTO_ALLOC_FAILURE_MESSAGE, -1));
	    Tcl_SetErrorCode(interp, "TK", "MALLOC", NULL);
	    goto errorExit;
	}
	tempformat = masterPtr->format;
	tempformat = modelPtr->format;
	if (oldformat && tempformat) {
	    tempformat = (Tcl_Obj *) Tcl_GetString(tempformat);
	}
	result = imageFormat->fileReadProc(interp, chan,
		masterPtr->fileString, tempformat, (Tk_PhotoHandle) masterPtr,
		modelPtr->fileString, tempformat, (Tk_PhotoHandle) modelPtr,
		0, 0, imageWidth, imageHeight, 0, 0);
	Tcl_Close(NULL, chan);
	if (result != TCL_OK) {
	    goto errorExit;
	}

	Tcl_ResetResult(interp);
	masterPtr->flags |= IMAGE_CHANGED;
	modelPtr->flags |= IMAGE_CHANGED;
    }

    if ((masterPtr->fileString == NULL) && (masterPtr->dataString != NULL)
	    && ((masterPtr->dataString != oldData)
		    || (masterPtr->format != oldFormat))) {
    if ((modelPtr->fileString == NULL) && (modelPtr->dataString != NULL)
	    && ((modelPtr->dataString != oldData)
		    || (modelPtr->format != oldFormat))) {

	if (MatchStringFormat(interp, masterPtr->dataString,
		masterPtr->format, &imageFormat, &imageWidth,
	if (MatchStringFormat(interp, modelPtr->dataString,
		modelPtr->format, &imageFormat, &imageWidth,
		&imageHeight, &oldformat) != TCL_OK) {
	    goto errorExit;
	}
	if (ImgPhotoSetSize(masterPtr, imageWidth, imageHeight) != TCL_OK) {
	if (ImgPhotoSetSize(modelPtr, imageWidth, imageHeight) != TCL_OK) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    TK_PHOTO_ALLOC_FAILURE_MESSAGE, -1));
	    Tcl_SetErrorCode(interp, "TK", "MALLOC", NULL);
	    goto errorExit;
	}
	tempformat = masterPtr->format;
	tempdata = masterPtr->dataString;
	tempformat = modelPtr->format;
	tempdata = modelPtr->dataString;
	if (oldformat) {
	    if (tempformat) {
		tempformat = (Tcl_Obj *) Tcl_GetString(tempformat);
	    }
	    tempdata = (Tcl_Obj *) Tcl_GetString(tempdata);
	}
	if (imageFormat->stringReadProc(interp, tempdata, tempformat,
		(Tk_PhotoHandle) masterPtr, 0, 0, imageWidth, imageHeight,
		(Tk_PhotoHandle) modelPtr, 0, 0, imageWidth, imageHeight,
		0, 0) != TCL_OK) {
	    goto errorExit;
	}

	Tcl_ResetResult(interp);
	masterPtr->flags |= IMAGE_CHANGED;
	modelPtr->flags |= IMAGE_CHANGED;
    }

    /*
     * Enforce a reasonable value for gamma.
     */

    if (masterPtr->gamma <= 0) {
	masterPtr->gamma = 1.0;
    if (modelPtr->gamma <= 0) {
	modelPtr->gamma = 1.0;
    }

    if ((masterPtr->gamma != oldGamma)
	    || (masterPtr->palette != oldPaletteString)) {
	masterPtr->flags |= IMAGE_CHANGED;
    if ((modelPtr->gamma != oldGamma)
	    || (modelPtr->palette != oldPaletteString)) {
	modelPtr->flags |= IMAGE_CHANGED;
    }

    /*
     * Cycle through all of the instances of this image, regenerating the
     * information for each instance. Then force the image to be redisplayed
     * everywhere that it is used.
     */

    for (instancePtr = masterPtr->instancePtr; instancePtr != NULL;
    for (instancePtr = modelPtr->instancePtr; instancePtr != NULL;
	    instancePtr = instancePtr->nextPtr) {
	TkImgPhotoConfigureInstance(instancePtr);
    }

    /*
     * Inform the generic image code that the image has (potentially) changed.
     */

    Tk_ImageChanged(masterPtr->tkMaster, 0, 0, masterPtr->width,
	    masterPtr->height, masterPtr->width, masterPtr->height);
    masterPtr->flags &= ~IMAGE_CHANGED;
    Tk_ImageChanged(modelPtr->tkModel, 0, 0, modelPtr->width,
	    modelPtr->height, modelPtr->width, modelPtr->height);
    modelPtr->flags &= ~IMAGE_CHANGED;

    if (oldData != NULL) {
	Tcl_DecrRefCount(oldData);
    }
    if (oldFormat != NULL) {
	Tcl_DecrRefCount(oldFormat);
    }

    ToggleComplexAlphaIfNeeded(masterPtr);
    ToggleComplexAlphaIfNeeded(modelPtr);

    return TCL_OK;

  errorExit:
    if (oldData != NULL) {
	Tcl_DecrRefCount(oldData);
    }
2078
2079
2080
2081
2082
2083
2084
2085

2086
2087
2088
2089
2090
2091
2092

2093
2094
2095
2096
2097
2098
2099
2060
2061
2062
2063
2064
2065
2066

2067
2068
2069
2070
2071
2072
2073

2074
2075
2076
2077
2078
2079
2080
2081







-
+






-
+







 *	partially transparent pixels exist, which requires blending instead of
 *	straight copy.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	(Re)sets COMPLEX_ALPHA flag of master.
 *	(Re)sets COMPLEX_ALPHA flag of model.
 *
 *----------------------------------------------------------------------
 */

static int
ToggleComplexAlphaIfNeeded(
    PhotoMaster *mPtr)
    PhotoModel *mPtr)
{
    size_t len = (size_t)MAX(mPtr->userWidth, mPtr->width) *
	    (size_t)MAX(mPtr->userHeight, mPtr->height) * 4;
    unsigned char *c = mPtr->pix32;
    unsigned char *end = c + len;

    /*
2116
2117
2118
2119
2120
2121
2122
2123

2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137

2138
2139
2140

2141
2142
2143

2144
2145
2146
2147
2148
2149
2150
2151
2152



2153
2154
2155


2156
2157
2158


2159
2160
2161


2162
2163
2164


2165
2166
2167


2168
2169
2170
2171
2172
2173
2174
2098
2099
2100
2101
2102
2103
2104

2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118

2119
2120
2121

2122
2123
2124

2125
2126
2127
2128
2129
2130
2131



2132
2133
2134
2135


2136
2137
2138


2139
2140
2141


2142
2143
2144


2145
2146
2147


2148
2149
2150
2151
2152
2153
2154
2155
2156







-
+













-
+


-
+


-
+






-
-
-
+
+
+

-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+







}

/*
 *----------------------------------------------------------------------
 *
 * ImgPhotoDelete --
 *
 *	This function is called by the image code to delete the master
 *	This function is called by the image code to delete the model
 *	structure for an image.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Resources associated with the image get freed.
 *
 *----------------------------------------------------------------------
 */

static void
ImgPhotoDelete(
    ClientData masterData)	/* Pointer to PhotoMaster structure for image.
    ClientData modelData)	/* Pointer to PhotoModel structure for image.
				 * Must not have any more instances. */
{
    PhotoMaster *masterPtr = masterData;
    PhotoModel *modelPtr = (PhotoModel *)modelData;
    PhotoInstance *instancePtr;

    while ((instancePtr = masterPtr->instancePtr) != NULL) {
    while ((instancePtr = modelPtr->instancePtr) != NULL) {
	if (instancePtr->refCount > 0) {
	    Tcl_Panic("tried to delete photo image when instances still exist");
	}
	Tcl_CancelIdleCall(TkImgDisposeInstance, instancePtr);
	TkImgDisposeInstance(instancePtr);
    }
    masterPtr->tkMaster = NULL;
    if (masterPtr->imageCmd != NULL) {
	Tcl_DeleteCommandFromToken(masterPtr->interp, masterPtr->imageCmd);
    modelPtr->tkModel = NULL;
    if (modelPtr->imageCmd != NULL) {
	Tcl_DeleteCommandFromToken(modelPtr->interp, modelPtr->imageCmd);
    }
    if (masterPtr->pix32 != NULL) {
	ckfree(masterPtr->pix32);
    if (modelPtr->pix32 != NULL) {
	ckfree(modelPtr->pix32);
    }
    if (masterPtr->validRegion != NULL) {
	TkDestroyRegion(masterPtr->validRegion);
    if (modelPtr->validRegion != NULL) {
	TkDestroyRegion(modelPtr->validRegion);
    }
    if (masterPtr->dataString != NULL) {
	Tcl_DecrRefCount(masterPtr->dataString);
    if (modelPtr->dataString != NULL) {
	Tcl_DecrRefCount(modelPtr->dataString);
    }
    if (masterPtr->format != NULL) {
	Tcl_DecrRefCount(masterPtr->format);
    if (modelPtr->format != NULL) {
	Tcl_DecrRefCount(modelPtr->format);
    }
    Tk_FreeOptions(configSpecs, (char *) masterPtr, NULL, 0);
    ckfree(masterPtr);
    Tk_FreeOptions(configSpecs, (char *) modelPtr, NULL, 0);
    ckfree(modelPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * ImgPhotoCmdDeletedProc --
 *
2182
2183
2184
2185
2186
2187
2188
2189

2190
2191
2192

2193
2194
2195
2196



2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214

2215
2216
2217
2218
2219
2220
2221

2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232


2233
2234
2235


2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250


2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265

2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277

2278
2279
2280
2281
2282
2283
2284
2285
2286
2287


2288
2289

2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306


2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318

2319
2320
2321
2322
2323
2324

2325
2326
2327
2328
2329
2330
2331

2332
2333
2334
2335
2336
2337
2338
2339
2340

2341
2342
2343
2344
2345

2346
2347
2348
2349

2350
2351
2352
2353
2354



2355
2356
2357
2358
2359
2360
2361
2362
2363


2364
2365
2366
2367



2368
2369
2370
2371
2372




2373
2374
2375
2376

2377
2378
2379
2380
2381
2382

2383
2384
2385
2386
2387
2388
2389
2164
2165
2166
2167
2168
2169
2170

2171
2172
2173

2174
2175



2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195

2196
2197
2198
2199
2200
2201
2202

2203
2204
2205
2206
2207
2208
2209
2210
2211
2212


2213
2214
2215


2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230


2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246

2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258

2259
2260
2261
2262
2263
2264
2265
2266
2267


2268
2269
2270

2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286


2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299

2300
2301
2302
2303
2304
2305

2306
2307
2308
2309
2310
2311
2312

2313
2314
2315
2316
2317
2318
2319
2320
2321

2322
2323
2324
2325
2326

2327
2328
2329
2330

2331
2332
2333



2334
2335
2336
2337
2338
2339
2340
2341
2342
2343


2344
2345
2346



2347
2348
2349
2350




2351
2352
2353
2354
2355
2356
2357

2358
2359
2360
2361
2362
2363

2364
2365
2366
2367
2368
2369
2370
2371







-
+


-
+

-
-
-
+
+
+

















-
+






-
+









-
-
+
+

-
-
+
+













-
-
+
+














-
+











-
+








-
-
+
+

-
+















-
-
+
+











-
+





-
+






-
+








-
+




-
+



-
+


-
-
-
+
+
+







-
-
+
+

-
-
-
+
+
+

-
-
-
-
+
+
+
+



-
+





-
+







 *	The image is deleted.
 *
 *----------------------------------------------------------------------
 */

static void
ImgPhotoCmdDeletedProc(
    ClientData clientData)	/* Pointer to PhotoMaster structure for
    ClientData clientData)	/* Pointer to PhotoModel structure for
				 * image. */
{
    PhotoMaster *masterPtr = clientData;
    PhotoModel *modelPtr = (PhotoModel *)clientData;

    masterPtr->imageCmd = NULL;
    if (masterPtr->tkMaster != NULL) {
	Tk_DeleteImage(masterPtr->interp, Tk_NameOfImage(masterPtr->tkMaster));
    modelPtr->imageCmd = NULL;
    if (modelPtr->tkModel != NULL) {
	Tk_DeleteImage(modelPtr->interp, Tk_NameOfImage(modelPtr->tkModel));
    }
}

/*
 *----------------------------------------------------------------------
 *
 * ImgPhotoSetSize --
 *
 *	This function reallocates the image storage and instance pixmaps for a
 *	photo image, as necessary, to change the image's size to `width' x
 *	`height' pixels.
 *
 * Results:
 *	TCL_OK if successful, TCL_ERROR if failure occurred (currently just
 *	with memory allocation.)
 *
 * Side effects:
 *	Storage gets reallocated, for the master and all its instances.
 *	Storage gets reallocated, for the model and all its instances.
 *
 *----------------------------------------------------------------------
 */

static int
ImgPhotoSetSize(
    PhotoMaster *masterPtr,
    PhotoModel *modelPtr,
    int width, int height)
{
    unsigned char *newPix32 = NULL;
    int h, offset, pitch;
    unsigned char *srcPtr, *destPtr;
    XRectangle validBox, clipBox;
    TkRegion clipRegion;
    PhotoInstance *instancePtr;

    if (masterPtr->userWidth > 0) {
	width = masterPtr->userWidth;
    if (modelPtr->userWidth > 0) {
	width = modelPtr->userWidth;
    }
    if (masterPtr->userHeight > 0) {
	height = masterPtr->userHeight;
    if (modelPtr->userHeight > 0) {
	height = modelPtr->userHeight;
    }

    if (width > INT_MAX / 4) {
	/* Pitch overflows int */
	return TCL_ERROR;
    }
    pitch = width * 4;

    /*
     * Test if we're going to (re)allocate the main buffer now, so that any
     * failures will leave the photo unchanged.
     */

    if ((width != masterPtr->width) || (height != masterPtr->height)
	    || (masterPtr->pix32 == NULL)) {
    if ((width != modelPtr->width) || (height != modelPtr->height)
	    || (modelPtr->pix32 == NULL)) {
	unsigned newPixSize;

	if (pitch && height > (int)(UINT_MAX / pitch)) {
	    return TCL_ERROR;
	}
	newPixSize = height * pitch;

	/*
	 * Some mallocs() really hate allocating zero bytes. [Bug 619544]
	 */

	if (newPixSize == 0) {
	    newPix32 = NULL;
	} else {
	    newPix32 = attemptckalloc(newPixSize);
	    newPix32 = (unsigned char *)attemptckalloc(newPixSize);
	    if (newPix32 == NULL) {
		return TCL_ERROR;
	    }
	}
    }

    /*
     * We have to trim the valid region if it is currently larger than the new
     * image size.
     */

    TkClipBox(masterPtr->validRegion, &validBox);
    TkClipBox(modelPtr->validRegion, &validBox);
    if ((validBox.x + validBox.width > width)
	    || (validBox.y + validBox.height > height)) {
	clipBox.x = 0;
	clipBox.y = 0;
	clipBox.width = width;
	clipBox.height = height;
	clipRegion = TkCreateRegion();
	TkUnionRectWithRegion(&clipBox, clipRegion, clipRegion);
	TkIntersectRegion(masterPtr->validRegion, clipRegion,
		masterPtr->validRegion);
	TkIntersectRegion(modelPtr->validRegion, clipRegion,
		modelPtr->validRegion);
	TkDestroyRegion(clipRegion);
	TkClipBox(masterPtr->validRegion, &validBox);
	TkClipBox(modelPtr->validRegion, &validBox);
    }

    /*
     * Use the reallocated storage (allocation above) for the 32-bit image and
     * copy over valid regions. Note that this test is true precisely when the
     * allocation has already been done.
     */

    if (newPix32 != NULL) {
	/*
	 * Zero the new array. The dithering code shouldn't read the areas
	 * outside validBox, but they might be copied to another photo image
	 * or written to a file.
	 */

	if ((masterPtr->pix32 != NULL)
	    && ((width == masterPtr->width) || (width == validBox.width))) {
	if ((modelPtr->pix32 != NULL)
	    && ((width == modelPtr->width) || (width == validBox.width))) {
	    if (validBox.y > 0) {
		memset(newPix32, 0, ((size_t) validBox.y * pitch));
	    }
	    h = validBox.y + validBox.height;
	    if (h < height) {
		memset(newPix32 + h*pitch, 0, ((size_t) (height - h) * pitch));
	    }
	} else {
	    memset(newPix32, 0, ((size_t)height * pitch));
	}

	if (masterPtr->pix32 != NULL) {
	if (modelPtr->pix32 != NULL) {
	    /*
	     * Copy the common area over to the new array array and free the
	     * old array.
	     */

	    if (width == masterPtr->width) {
	    if (width == modelPtr->width) {

		/*
		 * The region to be copied is contiguous.
		 */

		offset = validBox.y * pitch;
		memcpy(newPix32 + offset, masterPtr->pix32 + offset,
		memcpy(newPix32 + offset, modelPtr->pix32 + offset,
			((size_t)validBox.height * pitch));

	    } else if ((validBox.width > 0) && (validBox.height > 0)) {
		/*
		 * Area to be copied is not contiguous - copy line by line.
		 */

		destPtr = newPix32 + (validBox.y * width + validBox.x) * 4;
		srcPtr = masterPtr->pix32 + (validBox.y * masterPtr->width
		srcPtr = modelPtr->pix32 + (validBox.y * modelPtr->width
			+ validBox.x) * 4;
		for (h = validBox.height; h > 0; h--) {
		    memcpy(destPtr, srcPtr, ((size_t)validBox.width * 4));
		    destPtr += width * 4;
		    srcPtr += masterPtr->width * 4;
		    srcPtr += modelPtr->width * 4;
		}
	    }

	    ckfree(masterPtr->pix32);
	    ckfree(modelPtr->pix32);
	}

	masterPtr->pix32 = newPix32;
	masterPtr->width = width;
	masterPtr->height = height;
	modelPtr->pix32 = newPix32;
	modelPtr->width = width;
	modelPtr->height = height;

	/*
	 * Dithering will be correct up to the end of the last pre-existing
	 * complete scanline.
	 */

	if ((validBox.x > 0) || (validBox.y > 0)) {
	    masterPtr->ditherX = 0;
	    masterPtr->ditherY = 0;
	    modelPtr->ditherX = 0;
	    modelPtr->ditherY = 0;
	} else if (validBox.width == width) {
	    if ((int) validBox.height < masterPtr->ditherY) {
		masterPtr->ditherX = 0;
		masterPtr->ditherY = validBox.height;
	    if ((int) validBox.height < modelPtr->ditherY) {
		modelPtr->ditherX = 0;
		modelPtr->ditherY = validBox.height;
	    }
	} else if ((masterPtr->ditherY > 0)
		|| ((int) validBox.width < masterPtr->ditherX)) {
	    masterPtr->ditherX = validBox.width;
	    masterPtr->ditherY = 0;
	} else if ((modelPtr->ditherY > 0)
		|| ((int) validBox.width < modelPtr->ditherX)) {
	    modelPtr->ditherX = validBox.width;
	    modelPtr->ditherY = 0;
	}
    }

    ToggleComplexAlphaIfNeeded(masterPtr);
    ToggleComplexAlphaIfNeeded(modelPtr);

    /*
     * Now adjust the sizes of the pixmaps for all of the instances.
     */

    for (instancePtr = masterPtr->instancePtr; instancePtr != NULL;
    for (instancePtr = modelPtr->instancePtr; instancePtr != NULL;
	    instancePtr = instancePtr->nextPtr) {
	TkImgPhotoInstanceSetSize(instancePtr);
    }

    return TCL_OK;
}

2419
2420
2421
2422
2423
2424
2425
2426


2427
2428

2429
2430
2431
2432
2433
2434
2435
2401
2402
2403
2404
2405
2406
2407

2408
2409
2410

2411
2412
2413
2414
2415
2416
2417
2418







-
+
+

-
+







				/* A pointer to the photo image format record
				 * is returned here. */
    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;
    int matched = 0;
    int useoldformat = 0;
    Tk_PhotoImageFormat *formatPtr;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    const char *formatString = NULL;

    if (formatObj) {
	formatString = Tcl_GetString(formatObj);
    }

2466
2467
2468
2469
2470
2471
2472

2473

2474
2475
2476
2477
2478
2479
2480
2449
2450
2451
2452
2453
2454
2455
2456

2457
2458
2459
2460
2461
2462
2463
2464







+
-
+







		if (*heightPtr < 1) {
		    *heightPtr = 1;
		}
		break;
	    }
	}
    }
#if !defined(TK_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9
    if (formatPtr == NULL) {
if (formatPtr == NULL) {
	useoldformat = 1;
	for (formatPtr = tsdPtr->oldFormatList; formatPtr != NULL;
		formatPtr = formatPtr->nextPtr) {
	    if (formatString != NULL) {
		if (strncasecmp(formatString,
			formatPtr->name, strlen(formatPtr->name)) != 0) {
		    continue;
2500
2501
2502
2503
2504
2505
2506

2507
2508
2509
2510
2511
2512
2513
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498







+







			*heightPtr = 1;
		    }
		    break;
		}
	    }
	}
    }
#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",
2560
2561
2562
2563
2564
2565
2566
2567
2568


2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582










2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597










2598
2599
2600
2601
2602
2603
2604
2605

2606
2607
2608
2609
2610
2611
2612
2545
2546
2547
2548
2549
2550
2551


2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618







-
-
+
+














+
+
+
+
+
+
+
+
+
+















+
+
+
+
+
+
+
+
+
+








+







				 * is returned here. */
    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;
    ThreadSpecificData *tsdPtr =
    Tk_PhotoImageFormat *formatPtr, *defaultFormatPtr = NULL;
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    const char *formatString = NULL;

    if (formatObj) {
	formatString = Tcl_GetString(formatObj);
    }

    /*
     * Scan through the table of file format handlers to find one which can
     * handle the image.
     */

    for (formatPtr = tsdPtr->formatList; formatPtr != NULL;
	    formatPtr = formatPtr->nextPtr) {
	/*
	 * To keep the behaviour of older versions (Tk <= 8.6), the default
	 * list-of-lists string format is checked last. Remember its position.
	 */

	if (strncasecmp("default", formatPtr->name, strlen(formatPtr->name))
		== 0) {
	    defaultFormatPtr = formatPtr;
	}

	if (formatObj != NULL) {
	    if (strncasecmp(formatString,
		    formatPtr->name, strlen(formatPtr->name)) != 0) {
		continue;
	    }
	    matched = 1;
	    if (formatPtr->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 this is the default format, and it was not passed as -format
	 * option, skip the stringMatchProc test. It'll be done later
	 */

	if (formatObj == NULL && formatPtr == defaultFormatPtr) {
	    continue;
	}

	if ((formatPtr->stringMatchProc != NULL)
		&& (formatPtr->stringReadProc != NULL)
		&& formatPtr->stringMatchProc(data, formatObj,
			widthPtr, heightPtr, interp)) {
	    break;
	}
    }

#if !defined(TK_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9
    if (formatPtr == NULL) {
	useoldformat = 1;
	for (formatPtr = tsdPtr->oldFormatList; formatPtr != NULL;
		formatPtr = formatPtr->nextPtr) {
	    if (formatObj != NULL) {
		if (strncasecmp(formatString,
			formatPtr->name, strlen(formatPtr->name)) != 0) {
2628
2629
2630
2631
2632
2633
2634


2635















2636

2637
2638
2639
2640

2641








2642
2643
2644
2645
2646
2647







2648
2649
2650
2651






2652
2653
2654
2655
2656
2657
2658
2659
2660
2661

2662
2663
2664
2665
2666
2667
2668
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658

2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673






2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699

2700
2701
2702
2703
2704
2705
2706
2707







+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+




+

+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+




+
+
+
+
+
+









-
+







			    (Tcl_Obj *) Tcl_GetString(data),
			    (Tcl_Obj *) formatString,
			    widthPtr, heightPtr, interp)) {
		break;
	    }
	}
    }
#endif

    if (formatPtr == NULL) {
	/*
	 * Try the default format as last resort (only if no -format option
	 * was passed).
	 */

	if ( formatObj == NULL && defaultFormatPtr == NULL) {
	    Tcl_Panic("default image format handler not registered");
	}
	if ( formatObj == NULL
		&& defaultFormatPtr->stringMatchProc != NULL
		&& defaultFormatPtr->stringReadProc != NULL
		&& defaultFormatPtr->stringMatchProc(data, formatObj,
		widthPtr, heightPtr, interp) != 0) {
	    useoldformat = 0;
	    formatPtr = defaultFormatPtr;
	if ((formatObj != NULL) && !matched) {
	} else if ((formatObj != NULL) && !matched) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "image format \"%s\" is not supported", formatString));
	    Tcl_SetErrorCode(interp, "TK", "LOOKUP", "PHOTO_FORMAT",
		    formatString, NULL);
	    return TCL_ERROR;
	} else {

            /*
             * Some lower level routine (stringMatchProc) may have already set
             * a specific error message, so just return this. Otherwise return
             * a generic image data error.
             */

            if (Tcl_GetString(Tcl_GetObjResult(interp))[0] == '\0') {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "couldn't recognize image data", -1));
	    Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO",
		    "UNRECOGNIZED_DATA", NULL);
	}
	return TCL_ERROR;
                Tcl_SetObjResult(interp, Tcl_NewStringObj(
                        "couldn't recognize image data", -1));
	        Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO",
		        "UNRECOGNIZED_DATA", NULL);
            }
	    return TCL_ERROR;
	}
    }

    *imageFormatPtr = formatPtr;
    *oldformat = useoldformat;

    /*
     * Some stringMatchProc might have left error messages and error codes in
     * interp.	Clear them before return.
     */
    Tcl_ResetResult(interp);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Tk_FindPhoto --
 *
 *	This function is called to get an opaque handle (actually a
 *	PhotoMaster *) for a given image, which can be used in subsequent
 *	PhotoModel *) for a given image, which can be used in subsequent
 *	calls to Tk_PhotoPutBlock, etc. The `name' parameter is the name of
 *	the image.
 *
 * Results:
 *	The handle for the photo image, or NULL if there is no photo image
 *	with the name given.
 *
2676
2677
2678
2679
2680
2681
2682
2683

2684
2685
2686
2687
2688
2689
2690
2715
2716
2717
2718
2719
2720
2721

2722
2723
2724
2725
2726
2727
2728
2729







-
+







Tk_FindPhoto(
    Tcl_Interp *interp,		/* Interpreter (application) in which image
				 * exists. */
    const char *imageName)	/* Name of the desired photo image. */
{
    const Tk_ImageType *typePtr;
    ClientData clientData =
	    Tk_GetImageMasterData(interp, imageName, &typePtr);
	    Tk_GetImageModelData(interp, imageName, &typePtr);

    if ((typePtr == NULL) || (typePtr->name != tkPhotoImageType.name)) {
	return NULL;
    }
    return clientData;
}

2719
2720
2721
2722
2723
2724
2725
2726

2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746


2747
2748
2749
2750



2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775


















2776
2777
2778
2779
2780
2781
2782
2783
2784
2785

2786
2787
2788
2789
2790
2791
2792
2793
2794



2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805


2806
2807
2808
2809
2810
2811


2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829

2830
2831
2832
2833
2834
2835
2836
2837
2838


2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849

2850
2851
2852
2853
2854
2855
2856
2758
2759
2760
2761
2762
2763
2764

2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783


2784
2785
2786



2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809





2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836

2837

2838
2839
2840
2841
2842



2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854


2855
2856
2857
2858
2859
2860


2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879

2880
2881
2882
2883
2884
2885
2886
2887


2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899

2900
2901
2902
2903
2904
2905
2906
2907







-
+


















-
-
+
+

-
-
-
+
+
+




















-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+









-
+
-





-
-
-
+
+
+









-
-
+
+




-
-
+
+

















-
+







-
-
+
+










-
+







    int x, int y,		/* Coordinates of the top-left pixel to be
				 * updated in the image. */
    int width, int height,	/* Dimensions of the area of the image to be
				 * updated. */
    int compRule)		/* Compositing rule to use when processing
				 * transparent pixels. */
{
    register PhotoMaster *masterPtr = (PhotoMaster *) handle;
    PhotoModel *modelPtr = (PhotoModel *) handle;
    Tk_PhotoImageBlock sourceBlock;
    unsigned char *memToFree;
    int xEnd, yEnd, greenOffset, blueOffset, alphaOffset;
    int wLeft, hLeft, wCopy, hCopy, pitch;
    unsigned char *srcPtr, *srcLinePtr, *destPtr, *destLinePtr;
    int sourceIsSimplePhoto = compRule & SOURCE_IS_SIMPLE_ALPHA_PHOTO;
    XRectangle rect;

    /*
     * Zero-sized blocks never cause any changes. [Bug 3078902]
     */

    if (blockPtr->height == 0 || blockPtr->width == 0) {
	return TCL_OK;
    }

    compRule &= ~SOURCE_IS_SIMPLE_ALPHA_PHOTO;

    if ((masterPtr->userWidth != 0) && ((x + width) > masterPtr->userWidth)) {
	width = masterPtr->userWidth - x;
    if ((modelPtr->userWidth != 0) && ((x + width) > modelPtr->userWidth)) {
	width = modelPtr->userWidth - x;
    }
    if ((masterPtr->userHeight != 0)
	    && ((y + height) > masterPtr->userHeight)) {
	height = masterPtr->userHeight - y;
    if ((modelPtr->userHeight != 0)
	    && ((y + height) > modelPtr->userHeight)) {
	height = modelPtr->userHeight - y;
    }
    if ((width <= 0) || (height <= 0)) {
	return TCL_OK;
    }

    /*
     * Fix for bug e4336bef5d:
     *
     * Make a local copy of *blockPtr, as we might have to change some
     * of its fields and don't want to interfere with the caller's data.
     *
     * If source and destination are the same image, create a copy  of the
     * source data in our local sourceBlock.
     *
     * To find out, just comparing the pointers is not enough - they might have
     * different values and still point to the same block of memory. (e.g.
     * if the -from option was passed to [imageName copy])
     */
    sourceBlock = *blockPtr;
    memToFree = NULL;
    if (sourceBlock.pixelPtr >= masterPtr->pix32
	    && sourceBlock.pixelPtr <= masterPtr->pix32 + masterPtr->width
	    * masterPtr->height * 4) {
	sourceBlock.pixelPtr = attemptckalloc(sourceBlock.height
		* sourceBlock.pitch);
    if (sourceBlock.pixelPtr >= modelPtr->pix32
	    && sourceBlock.pixelPtr <= modelPtr->pix32 + modelPtr->width
	    * modelPtr->height * 4) {
	/*
	 * Fix 5c51be6411: avoid reading
	 *
	 *	(sourceBlock.pitch - sourceBlock.width * sourceBlock.pixelSize)
	 *
	 * bytes past the end of modelPtr->pix32[] when
	 *
	 *	blockPtr->pixelPtr > (modelPtr->pix32 +
	 *		4 * modelPtr->width * modelPtr->height -
	 *		sourceBlock.height * sourceBlock.pitch)
	 */
	unsigned int cpyLen = (sourceBlock.height - 1) * sourceBlock.pitch +
		sourceBlock.width * sourceBlock.pixelSize;

	sourceBlock.pixelPtr = (unsigned char *)attemptckalloc(cpyLen);
	if (sourceBlock.pixelPtr == NULL) {
	    if (interp != NULL) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			TK_PHOTO_ALLOC_FAILURE_MESSAGE, -1));
		Tcl_SetErrorCode(interp, "TK", "MALLOC", NULL);
	    }
	    return TCL_ERROR;
	}
	memToFree = sourceBlock.pixelPtr;
	memcpy(sourceBlock.pixelPtr, blockPtr->pixelPtr, sourceBlock.height
	memcpy(sourceBlock.pixelPtr, blockPtr->pixelPtr, cpyLen);
	    * sourceBlock.pitch);
    }


    xEnd = x + width;
    yEnd = y + height;
    if ((xEnd > masterPtr->width) || (yEnd > masterPtr->height)) {
	if (ImgPhotoSetSize(masterPtr, MAX(xEnd, masterPtr->width),
		MAX(yEnd, masterPtr->height)) == TCL_ERROR) {
    if ((xEnd > modelPtr->width) || (yEnd > modelPtr->height)) {
	if (ImgPhotoSetSize(modelPtr, MAX(xEnd, modelPtr->width),
		MAX(yEnd, modelPtr->height)) == TCL_ERROR) {
	    if (interp != NULL) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			TK_PHOTO_ALLOC_FAILURE_MESSAGE, -1));
		Tcl_SetErrorCode(interp, "TK", "MALLOC", NULL);
	    }
	    goto errorExit;
	}
    }

    if ((y < masterPtr->ditherY) || ((y == masterPtr->ditherY)
	    && (x < masterPtr->ditherX))) {
    if ((y < modelPtr->ditherY) || ((y == modelPtr->ditherY)
	    && (x < modelPtr->ditherX))) {
	/*
	 * The dithering isn't correct past the start of this block.
	 */

	masterPtr->ditherX = x;
	masterPtr->ditherY = y;
	modelPtr->ditherX = x;
	modelPtr->ditherY = y;
    }

    /*
     * If this image block could have different red, green and blue
     * components, mark it as a color image.
     */

    greenOffset = sourceBlock.offset[1] - sourceBlock.offset[0];
    blueOffset = sourceBlock.offset[2] - sourceBlock.offset[0];
    alphaOffset = sourceBlock.offset[3];
    if ((alphaOffset >= sourceBlock.pixelSize) || (alphaOffset < 0)) {
	alphaOffset = 0;
	sourceIsSimplePhoto = 1;
    } else {
	alphaOffset -= sourceBlock.offset[0];
    }
    if ((greenOffset != 0) || (blueOffset != 0)) {
	masterPtr->flags |= COLOR_IMAGE;
	modelPtr->flags |= COLOR_IMAGE;
    }

    /*
     * Copy the data into our local 32-bit/pixel array. If we can do it with a
     * single memmove, we do.
     */

    destLinePtr = masterPtr->pix32 + (y * masterPtr->width + x) * 4;
    pitch = masterPtr->width * 4;
    destLinePtr = modelPtr->pix32 + (y * modelPtr->width + x) * 4;
    pitch = modelPtr->width * 4;

    /*
     * Test to see if we can do the whole write in a single copy. This test is
     * probably too restrictive. We should also be able to do a memmove if
     * pixelSize == 3 and alphaOffset == 0. Maybe other cases too.
     */

    if ((sourceBlock.pixelSize == 4)
	    && (greenOffset == 1) && (blueOffset == 2) && (alphaOffset == 3)
	    && (width <= sourceBlock.width) && (height <= sourceBlock.height)
	    && ((height == 1) || ((x == 0) && (width == masterPtr->width)
	    && ((height == 1) || ((x == 0) && (width == modelPtr->width)
		&& (sourceBlock.pitch == pitch)))
	    && (compRule == TK_PHOTO_COMPOSITE_SET)) {
	memmove(destLinePtr, sourceBlock.pixelPtr + sourceBlock.offset[0],
		((size_t)height * width * 4));

	/*
	 * We know there's an alpha offset and we're setting the data, so skip
3024
3025
3026
3027
3028
3029
3030
3031
3032


3033
3034
3035
3036
3037
3038
3039
3040
3041

3042
3043
3044


3045
3046
3047
3048
3049
3050
3051


3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067


3068
3069
3070

3071
3072

3073
3074
3075

3076
3077
3078
3079
3080

3081
3082
3083
3084
3085
3086
3087
3088

3089
3090
3091
3092
3093
3094
3095

3096
3097
3098
3099
3100
3101
3102


3103
3104
3105
3106
3107
3108
3109
3075
3076
3077
3078
3079
3080
3081


3082
3083
3084
3085
3086
3087
3088
3089
3090
3091

3092
3093


3094
3095
3096
3097
3098
3099
3100


3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116


3117
3118
3119
3120

3121
3122

3123
3124
3125

3126
3127
3128
3129
3130

3131
3132
3133
3134
3135
3136
3137
3138

3139
3140
3141
3142
3143
3144
3145

3146
3147
3148
3149
3150
3151


3152
3153
3154
3155
3156
3157
3158
3159
3160







-
-
+
+








-
+

-
-
+
+





-
-
+
+














-
-
+
+


-
+

-
+


-
+




-
+







-
+






-
+





-
-
+
+







	recalculateValidRegion:
	    workRgn = TkCreateRegion();
	    rect.x = x;
	    rect.y = y;
	    rect.width = width;
	    rect.height = height;
	    TkUnionRectWithRegion(&rect, workRgn, workRgn);
	    TkSubtractRegion(masterPtr->validRegion, workRgn,
		    masterPtr->validRegion);
	    TkSubtractRegion(modelPtr->validRegion, workRgn,
		    modelPtr->validRegion);
	    TkDestroyRegion(workRgn);
	}

	/*
	 * Factorize out the main part of the building of the region data to
	 * allow for more efficient per-platform implementations. [Bug 919066]
	 */

	TkpBuildRegionFromAlphaData(masterPtr->validRegion, (unsigned) x,
	TkpBuildRegionFromAlphaData(modelPtr->validRegion, (unsigned) x,
		(unsigned) y, (unsigned) width, (unsigned) height,
		masterPtr->pix32 + (y * masterPtr->width + x) * 4 + 3,
		4, (unsigned) masterPtr->width * 4);
		modelPtr->pix32 + (y * modelPtr->width + x) * 4 + 3,
		4, (unsigned) modelPtr->width * 4);
    } else {
	rect.x = x;
	rect.y = y;
	rect.width = width;
	rect.height = height;
	TkUnionRectWithRegion(&rect, masterPtr->validRegion,
		masterPtr->validRegion);
	TkUnionRectWithRegion(&rect, modelPtr->validRegion,
		modelPtr->validRegion);
    }

    /*
     * Check if display code needs alpha blending...
     */

    if (!sourceIsSimplePhoto && (height == 1)) {
	/*
	 * Optimize the single span case if we can. This speeds up code that
	 * builds up large simple-alpha images by scan-lines or individual
	 * pixels. We don't negate COMPLEX_ALPHA in this case. [Bug 1409140]
	 * [Patch 1539990]
	 */

	if (!(masterPtr->flags & COMPLEX_ALPHA)) {
	    register int x1;
	if (!(modelPtr->flags & COMPLEX_ALPHA)) {
	    int x1;

	    for (x1=x ; x1<x+width ; x1++) {
		register unsigned char newAlpha;
		unsigned char newAlpha;

		destLinePtr = masterPtr->pix32 + (y*masterPtr->width + x1)*4;
		destLinePtr = modelPtr->pix32 + (y*modelPtr->width + x1)*4;
		newAlpha = destLinePtr[3];
		if (newAlpha && newAlpha != 255) {
		    masterPtr->flags |= COMPLEX_ALPHA;
		    modelPtr->flags |= COMPLEX_ALPHA;
		    break;
		}
	    }
	}
    } else if ((alphaOffset != 0) || (masterPtr->flags & COMPLEX_ALPHA)) {
    } else if ((alphaOffset != 0) || (modelPtr->flags & COMPLEX_ALPHA)) {
	/*
	 * Check for partial transparency if alpha pixels are specified, or
	 * rescan if we already knew such pixels existed. To restrict this
	 * Toggle to only checking the changed pixels requires knowing where
	 * the alpha pixels are.
	 */

	ToggleComplexAlphaIfNeeded(masterPtr);
	ToggleComplexAlphaIfNeeded(modelPtr);
    }

    /*
     * Update each instance.
     */

    Tk_DitherPhoto((Tk_PhotoHandle)masterPtr, x, y, width, height);
    Tk_DitherPhoto((Tk_PhotoHandle)modelPtr, x, y, width, height);

    /*
     * Tell the core image code that this image has changed.
     */

    Tk_ImageChanged(masterPtr->tkMaster, x, y, width, height,
	    masterPtr->width, masterPtr->height);
    Tk_ImageChanged(modelPtr->tkModel, x, y, width, height,
	    modelPtr->width, modelPtr->height);

    if (memToFree) ckfree(memToFree);

    return TCL_OK;

  errorExit:
    if (memToFree) ckfree(memToFree);
3145
3146
3147
3148
3149
3150
3151
3152
3153


3154
3155
3156
3157
3158
3159
3160
3196
3197
3198
3199
3200
3201
3202


3203
3204
3205
3206
3207
3208
3209
3210
3211







-
-
+
+







    int zoomX, int zoomY,	/* Zoom factors for the X and Y axes. */
    int subsampleX, int subsampleY,
				/* Subsampling factors for the X and Y
				 * axes. */
    int compRule)		/* Compositing rule to use when processing
				 * transparent pixels. */
{
    register PhotoMaster *masterPtr = (PhotoMaster *) handle;
    register Tk_PhotoImageBlock sourceBlock;
    PhotoModel *modelPtr = (PhotoModel *) handle;
    Tk_PhotoImageBlock sourceBlock;
    unsigned char *memToFree;
    int xEnd, yEnd, greenOffset, blueOffset, alphaOffset;
    int wLeft, hLeft, wCopy, hCopy, blockWid, blockHt;
    unsigned char *srcPtr, *srcLinePtr, *srcOrigPtr, *destPtr, *destLinePtr;
    int pitch, xRepeat, yRepeat, blockXSkip, blockYSkip, sourceIsSimplePhoto;
    XRectangle rect;

3173
3174
3175
3176
3177
3178
3179
3180
3181


3182
3183
3184
3185



3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209


















3210
3211
3212
3213
3214
3215
3216
3217
3218
3219

3220
3221
3222
3223
3224
3225
3226
3227



3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238


3239
3240
3241
3242
3243
3244


3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262

3263
3264
3265
3266
3267
3268
3269
3224
3225
3226
3227
3228
3229
3230


3231
3232
3233



3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255





3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282

3283

3284
3285
3286
3287



3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299


3300
3301
3302
3303
3304
3305


3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324

3325
3326
3327
3328
3329
3330
3331
3332







-
-
+
+

-
-
-
+
+
+



















-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+









-
+
-




-
-
-
+
+
+









-
-
+
+




-
-
+
+

















-
+








    sourceIsSimplePhoto = compRule & SOURCE_IS_SIMPLE_ALPHA_PHOTO;
    compRule &= ~SOURCE_IS_SIMPLE_ALPHA_PHOTO;

    if (zoomX <= 0 || zoomY <= 0) {
	return TCL_OK;
    }
    if ((masterPtr->userWidth != 0) && ((x + width) > masterPtr->userWidth)) {
	width = masterPtr->userWidth - x;
    if ((modelPtr->userWidth != 0) && ((x + width) > modelPtr->userWidth)) {
	width = modelPtr->userWidth - x;
    }
    if ((masterPtr->userHeight != 0)
	    && ((y + height) > masterPtr->userHeight)) {
	height = masterPtr->userHeight - y;
    if ((modelPtr->userHeight != 0)
	    && ((y + height) > modelPtr->userHeight)) {
	height = modelPtr->userHeight - y;
    }
    if (width <= 0 || height <= 0) {
	return TCL_OK;
    }

    /*
     * Fix for Bug e4336bef5d:
     * Make a local copy of *blockPtr, as we might have to change some
     * of its fields and don't want to interfere with the caller's data.
     *
     * If source and destination are the same image, create a copy  of the
     * source data in our local sourceBlock.
     *
     * To find out, just comparing the pointers is not enough - they might have
     * different values and still point to the same block of memory. (e.g.
     * if the -from option was passed to [imageName copy])
     */
    sourceBlock = *blockPtr;
    memToFree = NULL;
    if (sourceBlock.pixelPtr >= masterPtr->pix32
	    && sourceBlock.pixelPtr <= masterPtr->pix32 + masterPtr->width
	    * masterPtr->height * 4) {
	sourceBlock.pixelPtr = attemptckalloc(sourceBlock.height
		* sourceBlock.pitch);
    if (sourceBlock.pixelPtr >= modelPtr->pix32
	    && sourceBlock.pixelPtr <= modelPtr->pix32 + modelPtr->width
	    * modelPtr->height * 4) {
	/*
	 * Fix 5c51be6411: avoid reading
	 *
	 *	(sourceBlock.pitch - sourceBlock.width * sourceBlock.pixelSize)
	 *
	 * bytes past the end of modelPtr->pix32[] when
	 *
	 *	blockPtr->pixelPtr > (modelPtr->pix32 +
	 *		4 * modelPtr->width * modelPtr->height -
	 *		sourceBlock.height * sourceBlock.pitch)
	 */
	unsigned int cpyLen = (sourceBlock.height - 1) * sourceBlock.pitch +
		sourceBlock.width * sourceBlock.pixelSize;

	sourceBlock.pixelPtr = (unsigned char *)attemptckalloc(cpyLen);
	if (sourceBlock.pixelPtr == NULL) {
	    if (interp != NULL) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			TK_PHOTO_ALLOC_FAILURE_MESSAGE, -1));
		Tcl_SetErrorCode(interp, "TK", "MALLOC", NULL);
	    }
	    return TCL_ERROR;
	}
	memToFree = sourceBlock.pixelPtr;
	memcpy(sourceBlock.pixelPtr, blockPtr->pixelPtr, sourceBlock.height
	memcpy(sourceBlock.pixelPtr, blockPtr->pixelPtr, cpyLen);
	    * sourceBlock.pitch);
    }

    xEnd = x + width;
    yEnd = y + height;
    if ((xEnd > masterPtr->width) || (yEnd > masterPtr->height)) {
	if (ImgPhotoSetSize(masterPtr, MAX(xEnd, masterPtr->width),
		MAX(yEnd, masterPtr->height)) == TCL_ERROR) {
    if ((xEnd > modelPtr->width) || (yEnd > modelPtr->height)) {
	if (ImgPhotoSetSize(modelPtr, MAX(xEnd, modelPtr->width),
		MAX(yEnd, modelPtr->height)) == TCL_ERROR) {
	    if (interp != NULL) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			TK_PHOTO_ALLOC_FAILURE_MESSAGE, -1));
		Tcl_SetErrorCode(interp, "TK", "MALLOC", NULL);
	    }
	    goto errorExit;
	}
    }

    if ((y < masterPtr->ditherY) || ((y == masterPtr->ditherY)
	    && (x < masterPtr->ditherX))) {
    if ((y < modelPtr->ditherY) || ((y == modelPtr->ditherY)
	    && (x < modelPtr->ditherX))) {
	/*
	 * The dithering isn't correct past the start of this block.
	 */

	masterPtr->ditherX = x;
	masterPtr->ditherY = y;
	modelPtr->ditherX = x;
	modelPtr->ditherY = y;
    }

    /*
     * If this image block could have different red, green and blue
     * components, mark it as a color image.
     */

    greenOffset = sourceBlock.offset[1] - sourceBlock.offset[0];
    blueOffset = sourceBlock.offset[2] - sourceBlock.offset[0];
    alphaOffset = sourceBlock.offset[3];
    if ((alphaOffset >= sourceBlock.pixelSize) || (alphaOffset < 0)) {
	alphaOffset = 0;
	sourceIsSimplePhoto = 1;
    } else {
	alphaOffset -= sourceBlock.offset[0];
    }
    if ((greenOffset != 0) || (blueOffset != 0)) {
	masterPtr->flags |= COLOR_IMAGE;
	modelPtr->flags |= COLOR_IMAGE;
    }

    /*
     * Work out what area the pixel data in the block expands to after
     * subsampling and zooming.
     */

3284
3285
3286
3287
3288
3289
3290
3291

3292
3293
3294
3295
3296
3297
3298
3299
3300

3301
3302
3303
3304
3305
3306
3307
3347
3348
3349
3350
3351
3352
3353

3354
3355
3356
3357
3358
3359
3360
3361
3362

3363
3364
3365
3366
3367
3368
3369
3370







-
+








-
+







	blockHt = ((sourceBlock.height - subsampleY - 1) / -subsampleY) * zoomY;
    }

    /*
     * Copy the data into our local 32-bit/pixel array.
     */

    destLinePtr = masterPtr->pix32 + (y * masterPtr->width + x) * 4;
    destLinePtr = modelPtr->pix32 + (y * modelPtr->width + x) * 4;
    srcOrigPtr = sourceBlock.pixelPtr + sourceBlock.offset[0];
    if (subsampleX < 0) {
	srcOrigPtr += (sourceBlock.width - 1) * sourceBlock.pixelSize;
    }
    if (subsampleY < 0) {
	srcOrigPtr += (sourceBlock.height - 1) * sourceBlock.pitch;
    }

    pitch = masterPtr->width * 4;
    pitch = modelPtr->width * 4;
    for (hLeft = height; hLeft > 0; ) {
	hCopy = MIN(hLeft, blockHt);
	hLeft -= hCopy;
	yRepeat = zoomY;
	srcLinePtr = srcOrigPtr;
	for (; hCopy > 0; --hCopy) {
	    destPtr = destLinePtr;
3380
3381
3382
3383
3384
3385
3386
3387
3388


3389
3390
3391
3392

3393
3394
3395


3396
3397
3398
3399
3400
3401
3402


3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415

3416
3417
3418

3419
3420
3421
3422

3423
3424
3425

3426
3427
3428
3429
3430
3431
3432

3433
3434
3435
3436
3437
3438
3439

3440
3441
3442
3443
3444
3445
3446


3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464

3465
3466
3467
3468
3469
3470
3471

3472
3473
3474
3475
3476
3477
3478
3479

3480
3481
3482
3483
3484
3485

3486
3487
3488
3489
3490
3491
3492

3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504



3505
3506
3507
3508

3509
3510
3511

3512
3513
3514
3515
3516
3517
3518


3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530





3531
3532
3533
3534
3535
3536
3537
3443
3444
3445
3446
3447
3448
3449


3450
3451
3452
3453
3454

3455
3456


3457
3458
3459
3460
3461
3462
3463


3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477

3478
3479
3480

3481
3482
3483
3484

3485
3486
3487

3488
3489
3490
3491
3492
3493
3494

3495
3496
3497
3498
3499
3500
3501

3502
3503
3504
3505
3506
3507


3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526

3527
3528
3529
3530
3531
3532
3533

3534
3535
3536
3537
3538
3539
3540
3541

3542
3543
3544
3545
3546
3547

3548
3549
3550
3551
3552
3553
3554

3555
3556
3557
3558
3559
3560
3561
3562
3563
3564



3565
3566
3567
3568
3569
3570

3571
3572
3573

3574
3575
3576
3577
3578
3579


3580
3581
3582
3583
3584
3585
3586
3587
3588





3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600







-
-
+
+



-
+

-
-
+
+





-
-
+
+












-
+


-
+



-
+


-
+






-
+






-
+





-
-
+
+

















-
+






-
+







-
+





-
+






-
+









-
-
-
+
+
+



-
+


-
+





-
-
+
+







-
-
-
-
-
+
+
+
+
+







	    TkRegion workRgn = TkCreateRegion();

	    rect.x = x;
	    rect.y = y;
	    rect.width = width;
	    rect.height = 1;
	    TkUnionRectWithRegion(&rect, workRgn, workRgn);
	    TkSubtractRegion(masterPtr->validRegion, workRgn,
		    masterPtr->validRegion);
	    TkSubtractRegion(modelPtr->validRegion, workRgn,
		    modelPtr->validRegion);
	    TkDestroyRegion(workRgn);
	}

	TkpBuildRegionFromAlphaData(masterPtr->validRegion,
	TkpBuildRegionFromAlphaData(modelPtr->validRegion,
		(unsigned)x, (unsigned)y, (unsigned)width, (unsigned)height,
		&masterPtr->pix32[(y * masterPtr->width + x) * 4 + 3], 4,
		(unsigned) masterPtr->width * 4);
		&modelPtr->pix32[(y * modelPtr->width + x) * 4 + 3], 4,
		(unsigned) modelPtr->width * 4);
    } else {
	rect.x = x;
	rect.y = y;
	rect.width = width;
	rect.height = height;
	TkUnionRectWithRegion(&rect, masterPtr->validRegion,
		masterPtr->validRegion);
	TkUnionRectWithRegion(&rect, modelPtr->validRegion,
		modelPtr->validRegion);
    }

    /*
     * Check if display code needs alpha blending...
     */

    if (!sourceIsSimplePhoto && (width == 1) && (height == 1)) {
	/*
	 * Optimize the single pixel case if we can. This speeds up code that
	 * builds up large simple-alpha images by single pixels. We don't
	 * negate COMPLEX_ALPHA in this case. [Bug 1409140]
	 */
	if (!(masterPtr->flags & COMPLEX_ALPHA)) {
	if (!(modelPtr->flags & COMPLEX_ALPHA)) {
	    unsigned char newAlpha;

	    destLinePtr = masterPtr->pix32 + (y * masterPtr->width + x) * 4;
	    destLinePtr = modelPtr->pix32 + (y * modelPtr->width + x) * 4;
	    newAlpha = destLinePtr[3];

	    if (newAlpha && newAlpha != 255) {
		masterPtr->flags |= COMPLEX_ALPHA;
		modelPtr->flags |= COMPLEX_ALPHA;
	    }
	}
    } else if ((alphaOffset != 0) || (masterPtr->flags & COMPLEX_ALPHA)) {
    } else if ((alphaOffset != 0) || (modelPtr->flags & COMPLEX_ALPHA)) {
	/*
	 * Check for partial transparency if alpha pixels are specified, or
	 * rescan if we already knew such pixels existed. To restrict this
	 * Toggle to only checking the changed pixels requires knowing where
	 * the alpha pixels are.
	 */
	ToggleComplexAlphaIfNeeded(masterPtr);
	ToggleComplexAlphaIfNeeded(modelPtr);
    }

    /*
     * Update each instance.
     */

    Tk_DitherPhoto((Tk_PhotoHandle) masterPtr, x, y, width, height);
    Tk_DitherPhoto((Tk_PhotoHandle) modelPtr, x, y, width, height);

    /*
     * Tell the core image code that this image has changed.
     */

    Tk_ImageChanged(masterPtr->tkMaster, x, y, width, height, masterPtr->width,
	    masterPtr->height);
    Tk_ImageChanged(modelPtr->tkModel, x, y, width, height, modelPtr->width,
	    modelPtr->height);

    if (memToFree) ckfree(memToFree);

    return TCL_OK;

  errorExit:
    if (memToFree) ckfree(memToFree);

    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * Tk_DitherPhoto --
 *
 *	This function is called to update an area of each instance's pixmap by
 *	dithering the corresponding area of the image master.
 *	dithering the corresponding area of the image model.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The pixmap of each instance of this image gets updated. The fields in
 *	*masterPtr indicating which area of the image is correctly dithered
 *	*modelPtr indicating which area of the image is correctly dithered
 *	get updated.
 *
 *----------------------------------------------------------------------
 */

void
Tk_DitherPhoto(
    Tk_PhotoHandle photo,	/* Image master whose instances are to be
    Tk_PhotoHandle photo,	/* Image model whose instances are to be
				 * updated. */
    int x, int y,		/* Coordinates of the top-left pixel in the
				 * area to be dithered. */
    int width, int height)	/* Dimensions of the area to be dithered. */
{
    PhotoMaster *masterPtr = (PhotoMaster *) photo;
    PhotoModel *modelPtr = (PhotoModel *) photo;
    PhotoInstance *instancePtr;

    if ((width <= 0) || (height <= 0)) {
	return;
    }

    for (instancePtr = masterPtr->instancePtr; instancePtr != NULL;
    for (instancePtr = modelPtr->instancePtr; instancePtr != NULL;
	    instancePtr = instancePtr->nextPtr) {
	TkImgDitherInstance(instancePtr, x, y, width, height);
    }

    /*
     * Work out whether this block will be correctly dithered and whether it
     * will extend the correctly dithered region.
     */

    if (((y < masterPtr->ditherY)
	    || ((y == masterPtr->ditherY) && (x <= masterPtr->ditherX)))
	    && ((y + height) > (masterPtr->ditherY))) {
    if (((y < modelPtr->ditherY)
	    || ((y == modelPtr->ditherY) && (x <= modelPtr->ditherX)))
	    && ((y + height) > (modelPtr->ditherY))) {
	/*
	 * This block starts inside (or immediately after) the correctly
	 * dithered region, so the first scan line at least will be right.
	 * Furthermore this block extends into scanline masterPtr->ditherY.
	 * Furthermore this block extends into scanline modelPtr->ditherY.
	 */

	if ((x == 0) && (width == masterPtr->width)) {
	if ((x == 0) && (width == modelPtr->width)) {
	    /*
	     * We are doing the full width, therefore the dithering will be
	     * correct to the end.
	     */

	    masterPtr->ditherX = 0;
	    masterPtr->ditherY = y + height;
	    modelPtr->ditherX = 0;
	    modelPtr->ditherY = y + height;
	} else {
	    /*
	     * We are doing partial scanlines, therefore the
	     * correctly-dithered region will be extended by at most one scan
	     * line.
	     */

	    if (x <= masterPtr->ditherX) {
		masterPtr->ditherX = x + width;
		if (masterPtr->ditherX >= masterPtr->width) {
		    masterPtr->ditherX = 0;
		    masterPtr->ditherY++;
	    if (x <= modelPtr->ditherX) {
		modelPtr->ditherX = x + width;
		if (modelPtr->ditherX >= modelPtr->width) {
		    modelPtr->ditherX = 0;
		    modelPtr->ditherY++;
		}
	    }
	}
    }
}

/*
3551
3552
3553
3554
3555
3556
3557
3558

3559
3560
3561
3562


3563
3564
3565
3566
3567
3568
3569


3570
3571

3572
3573
3574
3575
3576
3577
3578
3579
3580



3581
3582
3583
3584
3585
3586
3587
3588
3589
3590


3591
3592
3593
3594
3595
3596
3597
3614
3615
3616
3617
3618
3619
3620

3621
3622
3623


3624
3625
3626
3627
3628
3629
3630


3631
3632
3633

3634
3635
3636
3637
3638
3639
3640



3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651


3652
3653
3654
3655
3656
3657
3658
3659
3660







-
+


-
-
+
+





-
-
+
+

-
+






-
-
-
+
+
+








-
-
+
+







 *----------------------------------------------------------------------
 */

void
Tk_PhotoBlank(
    Tk_PhotoHandle handle)	/* Handle for the image to be blanked. */
{
    PhotoMaster *masterPtr = (PhotoMaster *) handle;
    PhotoModel *modelPtr = (PhotoModel *) handle;
    PhotoInstance *instancePtr;

    masterPtr->ditherX = masterPtr->ditherY = 0;
    masterPtr->flags = 0;
    modelPtr->ditherX = modelPtr->ditherY = 0;
    modelPtr->flags = 0;

    /*
     * The image has valid data nowhere.
     */

    if (masterPtr->validRegion != NULL) {
	TkDestroyRegion(masterPtr->validRegion);
    if (modelPtr->validRegion != NULL) {
	TkDestroyRegion(modelPtr->validRegion);
    }
    masterPtr->validRegion = TkCreateRegion();
    modelPtr->validRegion = TkCreateRegion();

    /*
     * Clear out the 32-bit pixel storage array. Clear out the dithering error
     * arrays for each instance.
     */

    memset(masterPtr->pix32, 0,
	    ((size_t)masterPtr->width * masterPtr->height * 4));
    for (instancePtr = masterPtr->instancePtr; instancePtr != NULL;
    memset(modelPtr->pix32, 0,
	    ((size_t)modelPtr->width * modelPtr->height * 4));
    for (instancePtr = modelPtr->instancePtr; instancePtr != NULL;
	    instancePtr = instancePtr->nextPtr) {
	TkImgResetDither(instancePtr);
    }

    /*
     * Tell the core image code that this image has changed.
     */

    Tk_ImageChanged(masterPtr->tkMaster, 0, 0, masterPtr->width,
	    masterPtr->height, masterPtr->width, masterPtr->height);
    Tk_ImageChanged(modelPtr->tkModel, 0, 0, modelPtr->width,
	    modelPtr->height, modelPtr->width, modelPtr->height);
}

/*
 *----------------------------------------------------------------------
 *
 * Tk_PhotoExpand --
 *
3613
3614
3615
3616
3617
3618
3619
3620

3621
3622
3623


3624
3625
3626


3627
3628
3629
3630



3631
3632
3633
3634
3635
3636
3637
3638
3639


3640
3641
3642
3643
3644
3645
3646
3676
3677
3678
3679
3680
3681
3682

3683
3684


3685
3686
3687


3688
3689
3690



3691
3692
3693
3694
3695
3696
3697
3698
3699
3700


3701
3702
3703
3704
3705
3706
3707
3708
3709







-
+

-
-
+
+

-
-
+
+

-
-
-
+
+
+







-
-
+
+







int
Tk_PhotoExpand(
    Tcl_Interp *interp,		/* Interpreter for passing back error
				 * messages, or NULL. */
    Tk_PhotoHandle handle,	/* Handle for the image to be expanded. */
    int width, int height)	/* Desired minimum dimensions of the image. */
{
    PhotoMaster *masterPtr = (PhotoMaster *) handle;
    PhotoModel *modelPtr = (PhotoModel *) handle;

    if (width <= masterPtr->width) {
	width = masterPtr->width;
    if (width <= modelPtr->width) {
	width = modelPtr->width;
    }
    if (height <= masterPtr->height) {
	height = masterPtr->height;
    if (height <= modelPtr->height) {
	height = modelPtr->height;
    }
    if ((width != masterPtr->width) || (height != masterPtr->height)) {
	if (ImgPhotoSetSize(masterPtr, MAX(width, masterPtr->width),
		MAX(height, masterPtr->height)) == TCL_ERROR) {
    if ((width != modelPtr->width) || (height != modelPtr->height)) {
	if (ImgPhotoSetSize(modelPtr, MAX(width, modelPtr->width),
		MAX(height, modelPtr->height)) == TCL_ERROR) {
	    if (interp != NULL) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			TK_PHOTO_ALLOC_FAILURE_MESSAGE, -1));
		Tcl_SetErrorCode(interp, "TK", "MALLOC", NULL);
	    }
	    return TCL_ERROR;
	}
	Tk_ImageChanged(masterPtr->tkMaster, 0, 0, 0, 0, masterPtr->width,
		masterPtr->height);
	Tk_ImageChanged(modelPtr->tkModel, 0, 0, 0, 0, modelPtr->width,
		modelPtr->height);
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
3661
3662
3663
3664
3665
3666
3667
3668

3669
3670
3671


3672
3673
3674
3675
3676
3677
3678
3724
3725
3726
3727
3728
3729
3730

3731
3732


3733
3734
3735
3736
3737
3738
3739
3740
3741







-
+

-
-
+
+







Tk_PhotoGetSize(
    Tk_PhotoHandle handle,	/* Handle for the image whose dimensions are
				 * requested. */
    int *widthPtr, int *heightPtr)
				/* The dimensions of the image are returned
				 * here. */
{
    PhotoMaster *masterPtr = (PhotoMaster *) handle;
    PhotoModel *modelPtr = (PhotoModel *) handle;

    *widthPtr = masterPtr->width;
    *heightPtr = masterPtr->height;
    *widthPtr = modelPtr->width;
    *heightPtr = modelPtr->height;
}

/*
 *----------------------------------------------------------------------
 *
 * Tk_PhotoSetSize --
 *
3693
3694
3695
3696
3697
3698
3699
3700

3701
3702
3703
3704
3705




3706
3707
3708
3709
3710
3711
3712
3713
3714


3715
3716
3717
3718
3719
3720
3721
3756
3757
3758
3759
3760
3761
3762

3763
3764




3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775


3776
3777
3778
3779
3780
3781
3782
3783
3784







-
+

-
-
-
-
+
+
+
+







-
-
+
+







Tk_PhotoSetSize(
    Tcl_Interp *interp,		/* Interpreter for passing back error
				 * messages, or NULL. */
    Tk_PhotoHandle handle,	/* Handle for the image whose size is to be
				 * set. */
    int width, int height)	/* New dimensions for the image. */
{
    PhotoMaster *masterPtr = (PhotoMaster *) handle;
    PhotoModel *modelPtr = (PhotoModel *) handle;

    masterPtr->userWidth = width;
    masterPtr->userHeight = height;
    if (ImgPhotoSetSize(masterPtr, ((width > 0) ? width: masterPtr->width),
	    ((height > 0) ? height: masterPtr->height)) == TCL_ERROR) {
    modelPtr->userWidth = width;
    modelPtr->userHeight = height;
    if (ImgPhotoSetSize(modelPtr, ((width > 0) ? width: modelPtr->width),
	    ((height > 0) ? height: modelPtr->height)) == TCL_ERROR) {
	if (interp != NULL) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    TK_PHOTO_ALLOC_FAILURE_MESSAGE, -1));
	    Tcl_SetErrorCode(interp, "TK", "MALLOC", NULL);
	}
	return TCL_ERROR;
    }
    Tk_ImageChanged(masterPtr->tkMaster, 0, 0, 0, 0,
	    masterPtr->width, masterPtr->height);
    Tk_ImageChanged(modelPtr->tkModel, 0, 0, 0, 0,
	    modelPtr->width, modelPtr->height);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TkGetPhotoValidRegion --
3736
3737
3738
3739
3740
3741
3742
3743

3744
3745

3746
3747
3748
3749
3750
3751
3752
3799
3800
3801
3802
3803
3804
3805

3806
3807

3808
3809
3810
3811
3812
3813
3814
3815







-
+

-
+







 */

TkRegion
TkPhotoGetValidRegion(
    Tk_PhotoHandle handle)	/* Handle for the image whose valid region is
				 * to obtained. */
{
    PhotoMaster *masterPtr = (PhotoMaster *) handle;
    PhotoModel *modelPtr = (PhotoModel *) handle;

    return masterPtr->validRegion;
    return modelPtr->validRegion;
}

/*
 *----------------------------------------------------------------------
 *
 * ImgGetPhoto --
 *
3764
3765
3766
3767
3768
3769
3770
3771

3772
3773
3774
3775
3776
3777
3778
3779
3780
3781

3782
3783
3784
3785
3786
3787

3788
3789
3790
3791
3792
3793
3794
3827
3828
3829
3830
3831
3832
3833

3834
3835
3836
3837
3838
3839
3840
3841
3842
3843

3844
3845
3846
3847
3848
3849

3850
3851
3852
3853
3854
3855
3856
3857







-
+









-
+





-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static char *
ImgGetPhoto(
    PhotoMaster *masterPtr,	/* Handle for the photo image from which image
    PhotoModel *modelPtr,	/* Handle for the photo image from which image
				 * data is desired. */
    Tk_PhotoImageBlock *blockPtr,
				/* Information about the address and layout of
				 * the image data is returned here. */
    struct SubcommandOptions *optPtr)
{
    unsigned char *pixelPtr;
    int x, y, greenOffset, blueOffset, alphaOffset;

    Tk_PhotoGetImage((Tk_PhotoHandle) masterPtr, blockPtr);
    Tk_PhotoGetImage((Tk_PhotoHandle) modelPtr, blockPtr);
    blockPtr->pixelPtr += optPtr->fromY * blockPtr->pitch
	    + optPtr->fromX * blockPtr->pixelSize;
    blockPtr->width = optPtr->fromX2 - optPtr->fromX;
    blockPtr->height = optPtr->fromY2 - optPtr->fromY;

    if (!(masterPtr->flags & COLOR_IMAGE) &&
    if (!(modelPtr->flags & COLOR_IMAGE) &&
	    (!(optPtr->options & OPT_BACKGROUND)
	    || ((optPtr->background->red == optPtr->background->green)
	    && (optPtr->background->red == optPtr->background->blue)))) {
	blockPtr->offset[0] = blockPtr->offset[1] = blockPtr->offset[2];
    }
    alphaOffset = 0;
    for (y = 0; y < blockPtr->height; y++) {
3808
3809
3810
3811
3812
3813
3814
3815

3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828

3829
3830
3831
3832
3833
3834
3835
3871
3872
3873
3874
3875
3876
3877

3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890

3891
3892
3893
3894
3895
3896
3897
3898







-
+












-
+







    if (!alphaOffset) {
	blockPtr->offset[3]= -1; /* Tell caller alpha need not be read */
    }
    greenOffset = blockPtr->offset[1] - blockPtr->offset[0];
    blueOffset = blockPtr->offset[2] - blockPtr->offset[0];
    if (((optPtr->options & OPT_BACKGROUND) && alphaOffset) ||
	    ((optPtr->options & OPT_GRAYSCALE) && (greenOffset||blueOffset))) {
	int newPixelSize,x,y;
	int newPixelSize;
	unsigned char *srcPtr, *destPtr;
	char *data;

	newPixelSize = (!(optPtr->options & OPT_BACKGROUND) && alphaOffset)
		? 2 : 1;
	if ((greenOffset||blueOffset) && !(optPtr->options & OPT_GRAYSCALE)) {
	    newPixelSize += 2;
	}

	if (blockPtr->height > (int)((UINT_MAX/newPixelSize)/blockPtr->width)) {
	    return NULL;
	}
	data = attemptckalloc(newPixelSize*blockPtr->width*blockPtr->height);
	data = (char *)attemptckalloc(newPixelSize*blockPtr->width*blockPtr->height);
	if (data == NULL) {
	    return NULL;
	}
	srcPtr = blockPtr->pixelPtr + blockPtr->offset[0];
	destPtr = (unsigned char *) data;
	if (!greenOffset && !blueOffset) {
	    for (y = blockPtr->height; y > 0; y--) {
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
3999
4000
4001
4002
4003
4004
4005



















































4006
4007
4008
4009
4010
4011
4012







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







    }
    return NULL;
}

/*
 *----------------------------------------------------------------------
 *
 * ImgStringWrite --
 *
 *	Default string write function. The data is formatted in the default
 *	format as accepted by the "<img> put" command.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
ImgStringWrite(
    Tcl_Interp *interp,
    Tcl_Obj *formatString,
    Tk_PhotoImageBlock *blockPtr)
{
    int greenOffset, blueOffset;
    Tcl_Obj *data;

    greenOffset = blockPtr->offset[1] - blockPtr->offset[0];
    blueOffset = blockPtr->offset[2] - blockPtr->offset[0];

    data = Tcl_NewObj();
    if ((blockPtr->width > 0) && (blockPtr->height > 0)) {
	int row, col;

	for (row=0; row<blockPtr->height; row++) {
	    Tcl_Obj *line = Tcl_NewObj();
	    unsigned char *pixelPtr = blockPtr->pixelPtr + blockPtr->offset[0]
		    + row * blockPtr->pitch;

	    for (col=0; col<blockPtr->width; col++) {
		Tcl_AppendPrintfToObj(line, "%s#%02x%02x%02x",
			col ? " " : "", *pixelPtr,
			pixelPtr[greenOffset], pixelPtr[blueOffset]);
		pixelPtr += blockPtr->pixelSize;
	    }
	    Tcl_ListObjAppendElement(NULL, data, line);
	}
    }
    Tcl_SetObjResult(interp, data);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Tk_PhotoGetImage --
 *
 *	This function is called to obtain image data from a photo image. This
 *	function fills in the Tk_PhotoImageBlock structure pointed to by
 *	`blockPtr' with details of the address and layout of the image data in
 *	memory.
 *
4012
4013
4014
4015
4016
4017
4018
4019

4020
4021
4022
4023
4024




4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036

4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054

4055
4056
4057
4058

4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073

4074
4075
4076
4077
4078
4079
4080
4081

4082
4083
4084
4085
4086
4087
4088
4024
4025
4026
4027
4028
4029
4030

4031
4032




4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047

4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065

4066
4067
4068
4069

4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084

4085
4086
4087
4088
4089
4090
4091
4092

4093
4094
4095
4096
4097
4098
4099
4100







-
+

-
-
-
-
+
+
+
+











-
+

















-
+



-
+














-
+







-
+







Tk_PhotoGetImage(
    Tk_PhotoHandle handle,	/* Handle for the photo image from which image
				 * data is desired. */
    Tk_PhotoImageBlock *blockPtr)
				/* Information about the address and layout of
				 * the image data is returned here. */
{
    PhotoMaster *masterPtr = (PhotoMaster *) handle;
    PhotoModel *modelPtr = (PhotoModel *) handle;

    blockPtr->pixelPtr = masterPtr->pix32;
    blockPtr->width = masterPtr->width;
    blockPtr->height = masterPtr->height;
    blockPtr->pitch = masterPtr->width * 4;
    blockPtr->pixelPtr = modelPtr->pix32;
    blockPtr->width = modelPtr->width;
    blockPtr->height = modelPtr->height;
    blockPtr->pitch = modelPtr->width * 4;
    blockPtr->pixelSize = 4;
    blockPtr->offset[0] = 0;
    blockPtr->offset[1] = 1;
    blockPtr->offset[2] = 2;
    blockPtr->offset[3] = 3;
    return 1;
}

/*
 *--------------------------------------------------------------
 *
 * TkPostscriptPhoto --
 * ImgPostscriptPhoto --
 *
 *	This function is called to output the contents of a photo image in
 *	Postscript by calling the Tk_PostscriptPhoto function.
 *
 * Results:
 *	Returns a standard Tcl return value.
 *
 * Side effects:
 *	None.
 *
 *--------------------------------------------------------------
 */

static int
ImgPhotoPostscript(
    ClientData clientData,	/* Handle for the photo image. */
    Tcl_Interp *interp,		/* Interpreter. */
    Tk_Window tkwin,		/* (unused) */
    TCL_UNUSED(Tk_Window),		/* (unused) */
    Tk_PostscriptInfo psInfo,	/* Postscript info. */
    int x, int y,		/* First pixel to output. */
    int width, int height,	/* Width and height of area. */
    int prepass)		/* (unused) */
    TCL_UNUSED(int))		/* (unused) */
{
    Tk_PhotoImageBlock block;

    Tk_PhotoGetImage(clientData, &block);
    block.pixelPtr += y * block.pitch + x * block.pixelSize;

    return Tk_PostscriptPhoto(interp, &block, psInfo, width, height);
}

/*
 *----------------------------------------------------------------------
 *
 * 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.
 *
 *----------------------------------------------------------------------
 */

#if !defined(TK_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9
void
Tk_PhotoPutBlock_NoComposite(
    Tk_PhotoHandle handle,
    Tk_PhotoImageBlock *blockPtr,
    int x, int y, int width, int height)
{
    if (Tk_PhotoPutBlock(NULL, handle, blockPtr, x, y, width, height,
4107
4108
4109
4110
4111
4112
4113
4114

4115
4116
4117
4118
4119
4120
4121
4119
4120
4121
4122
4123
4124
4125

4126
4127
4128
4129
4130
4131
4132
4133







-
+








/*
 *----------------------------------------------------------------------
 *
 * 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.
 *
 *----------------------------------------------------------------------
 */
4160
4161
4162
4163
4164
4165
4166

4167
4168
4169
4170
4171
4172

4173
4174
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188







+






+


    Tk_PhotoHandle handle,
    int width, int height)
{
    if (Tk_PhotoSetSize(NULL, handle, width, height) != TCL_OK) {
	Tcl_Panic(TK_PHOTO_ALLOC_FAILURE_MESSAGE);
    }
}
#endif /* TK_NO_DEPRECATED */

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * tab-width: 8
 * End:
 */
Changes to generic/tkImgPhoto.h.
1
2
3
4
5
6
7
8
9




10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

30
31
32
33

34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
1
2
3
4
5




6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51







52
53
54
55
56
57
58





-
-
-
-
+
+
+
+




















+



-
+

















-
-
-
-
-
-
-







/*
 * 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 ([email protected]),
 *	   Department of Computer Science,
 *	   Australian National University.
 */

#include "tkInt.h"
#ifdef _WIN32
#include "tkWinInt.h"
#elif defined(__CYGWIN__)
#include "tkUnixInt.h"
#endif

/*
 * Forward declarations of the structures we define.
 */

#define PhotoMaster PhotoModel
typedef struct ColorTableId	ColorTableId;
typedef struct ColorTable	ColorTable;
typedef struct PhotoInstance	PhotoInstance;
typedef struct PhotoMaster	PhotoMaster;
typedef struct PhotoModel	PhotoModel;

/*
 * A signed 8-bit integral type. If chars are unsigned and the compiler isn't
 * an ANSI one, then we have to use short instead (which wastes space) to get
 * signed behavior.
 */

#if defined(__STDC__) || defined(_AIX)
    typedef signed char schar;
#else
#   ifndef __CHAR_UNSIGNED__
	typedef char schar;
#   else
	typedef short schar;
#   endif
#endif

/*
 * An unsigned 32-bit integral type, used for pixel values. We use int rather
 * than long here to accommodate those systems where longs are 64 bits.
 */

typedef unsigned int pixel;

/*
 * The maximum number of pixels to transmit to the server in a single
 * XPutImage call.
 */

#define MAX_PIXELS 65536

89
90
91
92
93
94
95




96


97
98


99

100
101
102
103
104
105

106
107
108


109
110
111
112
113
114
115
83
84
85
86
87
88
89
90
91
92
93
94
95
96


97
98
99
100
101
102
103
104
105

106
107


108
109
110
111
112
113
114
115
116







+
+
+
+

+
+
-
-
+
+

+





-
+

-
-
+
+







 * structure of the following type is used to store the allocated pixel values
 * and other information:
 */

struct ColorTable {
    ColorTableId id;		/* Information used in selecting this color
				 * table. */
#if TCL_MAJOR_VERSION > 8
    size_t	refCount;		/* Number of instances using this map. */
    size_t liveRefCount;		/* Number of instances which are actually in
				 * use, using this map. */
    int	flags;			/* See below. */
#else
    int	flags;			/* See below. */
    int	refCount;		/* Number of instances using this map. */
    int liveRefCount;		/* Number of instances which are actually in
    unsigned int	refCount;		/* Number of instances using this map. */
    unsigned int liveRefCount;		/* Number of instances which are actually in
				 * use, using this map. */
#endif
    int	numColors;		/* Number of colors allocated for this map. */

    XVisualInfo	visualInfo;	/* Information about the visual for windows
				 * using this color table. */

    pixel redValues[256];	/* Maps 8-bit values of red intensity to a
    unsigned redValues[256];	/* Maps 8-bit values of red intensity to a
				 * pixel value or index in pixelMap. */
    pixel greenValues[256];	/* Ditto for green intensity. */
    pixel blueValues[256];	/* Ditto for blue intensity. */
    unsigned greenValues[256];	/* Ditto for green intensity. */
    unsigned blueValues[256];	/* Ditto for blue intensity. */
    unsigned long *pixelMap;	/* Actual pixel values allocated. */

    unsigned char colorQuant[3][256];
				/* Maps 8-bit intensities to quantized
				 * intensities. The first index is 0 for red,
				 * 1 for green, 2 for blue. */
};
133
134
135
136
137
138
139
140

141
142
143
144


145
146
147
148
149
150
151
134
135
136
137
138
139
140

141
142
143


144
145
146
147
148
149
150
151
152







-
+


-
-
+
+








#define BLACK_AND_WHITE		1
#define COLOR_WINDOW		2
#define DISPOSE_PENDING		4
#define MAP_COLORS		8

/*
 * Definition of the data associated with each photo image master.
 * Definition of the data associated with each photo image model.
 */

struct PhotoMaster {
    Tk_ImageMaster tkMaster;	/* Tk's token for image master. NULL means the
struct PhotoModel {
    Tk_ImageModel tkModel;	/* Tk's token for image model. NULL means the
				 * image is being deleted. */
    Tcl_Interp *interp;		/* Interpreter associated with the application
				 * using this image. */
    Tcl_Command imageCmd;	/* Token for image command (used to delete it
				 * when the image goes away). NULL means the
				 * image command has already been deleted. */
    int	flags;			/* Sundry flags, defined below. */
160
161
162
163
164
165
166
167

168
169
170
171

172
173
174
175
176
177
178
161
162
163
164
165
166
167

168
169
170
171

172
173
174
175
176
177
178
179







-
+



-
+







				 * or string value. */
    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. */
    PhotoInstance *instancePtr;	/* First in the list of instances associated
				 * with this master. */
				 * with this model. */
};

/*
 * Bit definitions for the flags field of a PhotoMaster.
 * Bit definitions for the flags field of a PhotoModel.
 * COLOR_IMAGE:			1 means that the image has different color
 *				components.
 * IMAGE_CHANGED:		1 means that the instances of this image need
 *				to be redithered.
 * COMPLEX_ALPHA:		1 means that the instances of this image have
 *				alpha values that aren't 0 or 255, and so need
 *				the copy-merge-replace renderer .
191
192
193
194
195
196
197
198

199
200
201
202
203
204






205
206
207
208

209
210
211
212
213
214
215
192
193
194
195
196
197
198

199
200
201
202
203


204
205
206
207
208
209
210
211
212

213
214
215
216
217
218
219
220







-
+




-
-
+
+
+
+
+
+



-
+








/*
 * The following data structure represents all of the instances of a photo
 * image in windows on a given screen that are using the same colormap.
 */

struct PhotoInstance {
    PhotoMaster *masterPtr;	/* Pointer to master for image. */
    PhotoModel *modelPtr;	/* Pointer to model for image. */
    Display *display;		/* Display for windows using this instance. */
    Colormap colormap;		/* The image may only be used in windows with
				 * this particular colormap. */
    PhotoInstance *nextPtr;	/* Pointer to the next instance in the list of
				 * instances associated with this master. */
    int refCount;		/* Number of instances using this structure. */
				 * instances associated with this model. */
#if TCL_MAJOR_VERSION > 8
    size_t refCount;		/* Number of instances using this structure. */
#else
    unsigned int refCount;	/* Number of instances using this structure. */
#endif
    Tk_Uid palette;		/* Palette for these particular instances. */
    double gamma;		/* Gamma value for these instances. */
    Tk_Uid defaultPalette;	/* Default palette to use if a palette is not
				 * specified for the master. */
				 * specified for the model. */
    ColorTable *colorTablePtr;	/* Pointer to information about colors
				 * allocated for image display in windows like
				 * this one. */
    Pixmap pixels;		/* X pixmap containing dithered image. */
    int width, height;		/* Dimensions of the pixmap. */
    schar *error;		/* Error image, used in dithering. */
    XImage *imagePtr;		/* Image structure for converted pixels. */
Added generic/tkImgSVGnano.c.






































































































































































































































































































































































































































































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
 * tkImgSVGnano.c
 *
 *	A photo file handler for SVG files.
 *
 * Copyright © 2013-14 Mikko Mononen [email protected]
 * Copyright © 2018 Christian Gollwitzer [email protected]
 * Copyright © 2018 Christian Werner https://www.androwish.org/
 * Copyright © 2018 Rene Zaumseil [email protected]
 *
 * 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
 * https://github.com/memononen/nanosvg
 *
 */

#include "tkInt.h"
#define NANOSVG_malloc	ckalloc
#define NANOSVG_realloc	ckrealloc
#define NANOSVG_free	ckfree
#define NANOSVG_SCOPE MODULE_SCOPE
#define NANOSVG_ALL_COLOR_KEYWORDS
#define NANOSVG_IMPLEMENTATION
#include "nanosvg.h"
#define NANOSVGRAST_IMPLEMENTATION
#include "nanosvgrast.h"

/* Additional parameters to nsvgRasterize() */

typedef struct {
    double scale;
    int scaleToHeight;
    int scaleToWidth;
} RastOpts;

/*
 * Per interp cache of last NSVGimage which was matched to
 * be immediately rasterized after the match. This helps to
 * eliminate double parsing of the SVG file/string.
 */

typedef struct {
    /* A poiner to remember if it is the same svn image (data)
     * It is a Tcl_Channel if image created by -file option
     * or a Tcl_Obj, if image is created with the -data option
     */
    ClientData dataOrChan;
    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,
			    Tk_PhotoHandle imageHandle, int destX, int destY,
			    int width, int height, int srcX, int srcY);
static int		StringMatchSVG(Tcl_Obj *dataObj, Tcl_Obj *format,
			    int *widthPtr, int *heightPtr, Tcl_Interp *interp);
static int		StringReadSVG(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 NSVGimage *	ParseSVGWithOptions(Tcl_Interp *interp,
			    const char *input, TkSizeT length, Tcl_Obj *format,
			    RastOpts *ropts);
static int		RasterizeSVG(Tcl_Interp *interp,
			    Tk_PhotoHandle imageHandle, NSVGimage *nsvgImage,
			    int destX, int destY, int width, int height,
			    int srcX, int srcY, RastOpts *ropts);
static double		GetScaleFromParameters(NSVGimage *nsvgImage,
			    RastOpts *ropts, int *widthPtr, int *heightPtr);
static NSVGcache *	GetCachePtr(Tcl_Interp *interp);
static int		CacheSVG(Tcl_Interp *interp, ClientData dataOrChan,
			    Tcl_Obj *formatObj, NSVGimage *nsvgImage,
			    RastOpts *ropts);
static NSVGimage *	GetCachedSVG(Tcl_Interp *interp, ClientData dataOrChan,
			    Tcl_Obj *formatObj, RastOpts *ropts);
static void		CleanCache(Tcl_Interp *interp);
static void		FreeCache(ClientData clientData, Tcl_Interp *interp);

/*
 * The format record for the SVG nano file format:
 */

Tk_PhotoImageFormat tkImgFmtSVGnano = {
    "svg",			/* name */
    FileMatchSVG,		/* fileMatchProc */
    StringMatchSVG,		/* stringMatchProc */
    FileReadSVG,		/* fileReadProc */
    StringReadSVG,		/* stringReadProc */
    NULL,			/* fileWriteProc */
    NULL,			/* stringWriteProc */
    NULL
};

/*
 *----------------------------------------------------------------------
 *
 * 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.
 *
 * Results:
 *	The return value is >0 if the file can be successfully parsed,
 *	and 0 otherwise.
 *
 * Side effects:
 *	The file is saved in the internal cache for further use.
 *
 *----------------------------------------------------------------------
 */

static int
FileMatchSVG(
    Tcl_Channel chan,
    const char *fileName,
    Tcl_Obj *formatObj,
    int *widthPtr, int *heightPtr,
    Tcl_Interp *interp)
{
    TkSizeT length;
    Tcl_Obj *dataObj = Tcl_NewObj();
    const char *data;
    RastOpts ropts;
    NSVGimage *nsvgImage;
    (void)fileName;

    CleanCache(interp);
    if (Tcl_ReadChars(chan, dataObj, 4096, 0) == TCL_IO_FAILURE) {
	/* in case of an error reading the file */
	Tcl_DecrRefCount(dataObj);
	return 0;
    }
    data = TkGetStringFromObj(dataObj, &length);
    /* should have a '<svg' and a '>' in the first 4k */
    if ((memchr(data, '>', length) == NULL) ||
	(MemMem(data, length, "<svg", 4) == NULL)) {
	Tcl_DecrRefCount(dataObj);
	return 0;
    }
    if (!Tcl_Eof(chan) && (Tcl_ReadChars(chan, dataObj, -1, 1) == TCL_IO_FAILURE)) {
	/* in case of an error reading the file */
	Tcl_DecrRefCount(dataObj);
	return 0;
    }
    data = TkGetStringFromObj(dataObj, &length);
    nsvgImage = ParseSVGWithOptions(interp, data, length, formatObj, &ropts);
    Tcl_DecrRefCount(dataObj);
    if (nsvgImage != NULL) {
        GetScaleFromParameters(nsvgImage, &ropts, widthPtr, heightPtr);
        if ((*widthPtr <= 0.0) || (*heightPtr <= 0.0)) {
	    nsvgDelete(nsvgImage);
	    return 0;
        }
        if (!CacheSVG(interp, chan, formatObj, nsvgImage, &ropts)) {
	    nsvgDelete(nsvgImage);
        }
        return 1;
    }
    return 0;
}

/*
 *----------------------------------------------------------------------
 *
 * FileReadSVG --
 *
 *	This function is called by the photo image type to read SVG format
 *	data from a file and write it into a given photo image.
 *
 * Results:
 *	A standard TCL completion code. If TCL_ERROR is returned then an error
 *	message is left in the interp's result.
 *
 * Side effects:
 *	The access position in file f is changed, and new data is added to the
 *	image given by imageHandle.
 *
 *----------------------------------------------------------------------
 */

static int
FileReadSVG(
    Tcl_Interp *interp,
    Tcl_Channel chan,
    const char *fileName,
    Tcl_Obj *formatObj,
    Tk_PhotoHandle imageHandle,
    int destX, int destY,
    int width, int height,
    int srcX, int srcY)
{
    TkSizeT length;
    const char *data;
    RastOpts ropts;
    NSVGimage *nsvgImage = GetCachedSVG(interp, chan, formatObj, &ropts);
    (void)fileName;

    if (nsvgImage == NULL) {
        Tcl_Obj *dataObj = Tcl_NewObj();

	if (Tcl_ReadChars(chan, dataObj, -1, 0) == TCL_IO_FAILURE) {
	    /* in case of an error reading the file */
	    Tcl_DecrRefCount(dataObj);
	    Tcl_SetObjResult(interp, Tcl_NewStringObj("read error", -1));
	    Tcl_SetErrorCode(interp, "TK", "IMAGE", "SVG", "READ_ERROR", NULL);
	    return TCL_ERROR;
	}
	data = TkGetStringFromObj(dataObj, &length);
	nsvgImage = ParseSVGWithOptions(interp, data, length, formatObj,
			    &ropts);
	Tcl_DecrRefCount(dataObj);
	if (nsvgImage == NULL) {
	    return TCL_ERROR;
	}
    }
    return RasterizeSVG(interp, imageHandle, nsvgImage, destX, destY,
		width, height, srcX, srcY, &ropts);
}

/*
 *----------------------------------------------------------------------
 *
 * StringMatchSVG --
 *
 *	This function is invoked by the photo image type to see if a string
 *	contains image data in SVG format.
 *
 * Results:
 *	The return value is >0 if the file can be successfully parsed,
 *	and 0 otherwise.
 *
 * Side effects:
 *	The file is saved in the internal cache for further use.
 *
 *----------------------------------------------------------------------
 */

static int
StringMatchSVG(
    Tcl_Obj *dataObj,
    Tcl_Obj *formatObj,
    int *widthPtr, int *heightPtr,
    Tcl_Interp *interp)
{
    TkSizeT length, testLength;
    const char *data;
    RastOpts ropts;
    NSVGimage *nsvgImage;

    CleanCache(interp);
    data = TkGetStringFromObj(dataObj, &length);
    /* should have a '<svg' and a '>' in the first 4k */
    testLength = (length > 4096) ? 4096 : length;
    if ((memchr(data, '>', testLength) == NULL) ||
	(MemMem(data, testLength, "<svg", 4) == NULL)) {
	return 0;
    }
    nsvgImage = ParseSVGWithOptions(interp, data, length, formatObj, &ropts);
    if (nsvgImage != NULL) {
        GetScaleFromParameters(nsvgImage, &ropts, widthPtr, heightPtr);
        if ((*widthPtr <= 0.0) || (*heightPtr <= 0.0)) {
	    nsvgDelete(nsvgImage);
	    return 0;
        }
        if (!CacheSVG(interp, dataObj, formatObj, nsvgImage, &ropts)) {
	    nsvgDelete(nsvgImage);
        }
        return 1;
    }
    return 0;
}

/*
 *----------------------------------------------------------------------
 *
 * StringReadSVG --
 *
 *	This function is called by the photo image type to read SVG format
 *	data from a string and write it into a given photo image.
 *
 * Results:
 *	A standard TCL completion code. If TCL_ERROR is returned then an error
 *	message is left in the interp's result.
 *
 * Side effects:
 *	New data is added to the image given by imageHandle.
 *
 *----------------------------------------------------------------------
 */

static int
StringReadSVG(
    Tcl_Interp *interp,
    Tcl_Obj *dataObj,
    Tcl_Obj *formatObj,
    Tk_PhotoHandle imageHandle,
    int destX, int destY,
    int width, int height,
    int srcX, int srcY)
{
    TkSizeT length;
    const char *data;
    RastOpts ropts;
    NSVGimage *nsvgImage = GetCachedSVG(interp, dataObj, formatObj, &ropts);

    if (nsvgImage == NULL) {
        data = TkGetStringFromObj(dataObj, &length);
	nsvgImage = ParseSVGWithOptions(interp, data, length, formatObj,
			    &ropts);
    }
    if (nsvgImage == NULL) {
	return TCL_ERROR;
    }
    return RasterizeSVG(interp, imageHandle, nsvgImage, destX, destY,
		width, height, srcX, srcY, &ropts);
}

/*
 *----------------------------------------------------------------------
 *
 * ParseSVGWithOptions --
 *
 *	This function is called to parse the given input string as SVG.
 *
 * Results:
 *	Return a newly create NSVGimage on success, and NULL otherwise.
 *
 * Side effects:
 *
 *----------------------------------------------------------------------
 */

static NSVGimage *
ParseSVGWithOptions(
    Tcl_Interp *interp,
    const char *input,
    TkSizeT length,
    Tcl_Obj *formatObj,
    RastOpts *ropts)
{
    Tcl_Obj **objv = NULL;
    int objc = 0;
    double dpi = 96.0;
    char *inputCopy = NULL;
    NSVGimage *nsvgImage;
    int parameterScaleSeen = 0;
    static const char *const fmtOptions[] = {
        "-dpi", "-scale", "-scaletoheight", "-scaletowidth", NULL
    };
    enum fmtOptionsEnum {
	OPT_DPI, OPT_SCALE, OPT_SCALE_TO_HEIGHT, OPT_SCALE_TO_WIDTH
    };

    /*
     * The parser destroys the original input string,
     * therefore first duplicate.
     */

    inputCopy = (char *)attemptckalloc(length+1);
    if (inputCopy == NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("cannot alloc data buffer", -1));
	Tcl_SetErrorCode(interp, "TK", "IMAGE", "SVG", "OUT_OF_MEMORY", NULL);
	goto error;
    }
    memcpy(inputCopy, input, length);
    inputCopy[length] = '\0';

    /*
     * Process elements of format specification as a list.
     */

    ropts->scale = 1.0;
    ropts->scaleToHeight = 0;
    ropts->scaleToWidth = 0;
    if ((formatObj != NULL) &&
	    Tcl_ListObjGetElements(interp, formatObj, &objc, &objv) != TCL_OK) {
        goto error;
    }
    for (; objc > 0 ; objc--, objv++) {
	int optIndex;

	/*
	 * Ignore the "svg" part of the format specification.
	 */

	if (!strcasecmp(Tcl_GetString(objv[0]), "svg")) {
	    continue;
	}

	if (Tcl_GetIndexFromObjStruct(interp, objv[0], fmtOptions,
		sizeof(char *), "option", 0, &optIndex) == TCL_ERROR) {
	    goto error;
	}

	if (objc < 2) {
	    ckfree(inputCopy);
	    inputCopy = NULL;
	    Tcl_WrongNumArgs(interp, 1, objv, "value");
	    goto error;
	}

	objc--;
	objv++;

	/*
	 * check that only one scale option is given
	 */
	switch ((enum fmtOptionsEnum)optIndex) {
	case OPT_SCALE:
	case OPT_SCALE_TO_HEIGHT:
	case OPT_SCALE_TO_WIDTH:
	    if ( parameterScaleSeen ) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"only one of -scale, -scaletoheight, -scaletowidth may be given", -1));
		Tcl_SetErrorCode(interp, "TK", "IMAGE", "SVG", "BAD_SCALE",
			NULL);
		goto error;
	    }
	    parameterScaleSeen = 1;
	    break;
	default:
	    break;
	}

	/*
	 * Decode parameters
	 */
	switch ((enum fmtOptionsEnum) optIndex) {
	case OPT_DPI:
	    if (Tcl_GetDoubleFromObj(interp, objv[0], &dpi) == TCL_ERROR) {
	        goto error;
	    }
	    if (dpi < 0.0) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"-dpi value must be positive", -1));
		Tcl_SetErrorCode(interp, "TK", "IMAGE", "SVG", "BAD_DPI",
			NULL);
		goto error;
	    }
	    break;
	case OPT_SCALE:
	    if (Tcl_GetDoubleFromObj(interp, objv[0], &ropts->scale) ==
		TCL_ERROR) {
	        goto error;
	    }
	    if (ropts->scale <= 0.0) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"-scale value must be positive", -1));
		Tcl_SetErrorCode(interp, "TK", "IMAGE", "SVG", "BAD_SCALE",
			NULL);
		goto error;
	    }
	    break;
	case OPT_SCALE_TO_HEIGHT:
	    if (Tcl_GetIntFromObj(interp, objv[0], &ropts->scaleToHeight) ==
		TCL_ERROR) {
	        goto error;
	    }
	    if (ropts->scaleToHeight <= 0) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"-scaletoheight value must be positive", -1));
		Tcl_SetErrorCode(interp, "TK", "IMAGE", "SVG", "BAD_SCALE",
			NULL);
		goto error;
	    }
	    break;
	case OPT_SCALE_TO_WIDTH:
	    if (Tcl_GetIntFromObj(interp, objv[0], &ropts->scaleToWidth) ==
		TCL_ERROR) {
	        goto error;
	    }
	    if (ropts->scaleToWidth <= 0) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"-scaletowidth value must be positive", -1));
		Tcl_SetErrorCode(interp, "TK", "IMAGE", "SVG", "BAD_SCALE",
			NULL);
		goto error;
	    }
	    break;
	}
    }

    nsvgImage = nsvgParse(inputCopy, "px", (float) dpi);
    if (nsvgImage == NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("cannot parse SVG image", -1));
	Tcl_SetErrorCode(interp, "TK", "IMAGE", "SVG", "PARSE_ERROR", NULL);
	goto error;
    }
    ckfree(inputCopy);
    return nsvgImage;

error:
    if (inputCopy != NULL) {
        ckfree(inputCopy);
    }
    return NULL;
}

/*
 *----------------------------------------------------------------------
 *
 * RasterizeSVG --
 *
 *	This function is called to rasterize the given nsvgImage and
 *	fill the imageHandle with data.
 *
 * Results:
 *	A standard TCL completion code. If TCL_ERROR is returned then an error
 *	message is left in the interp's result.
 *
 *
 * Side effects:
 *	On error the given nsvgImage will be deleted.
 *
 *----------------------------------------------------------------------
 */

static int
RasterizeSVG(
    Tcl_Interp *interp,
    Tk_PhotoHandle imageHandle,
    NSVGimage *nsvgImage,
    int destX, int destY,
    int width, int height,
    int srcX, int srcY,
    RastOpts *ropts)
{
    int w, h, c;
    NSVGrasterizer *rast;
    unsigned char *imgData;
    Tk_PhotoImageBlock svgblock;
    double scale;
    (void)srcX;
    (void)srcY;

    scale = GetScaleFromParameters(nsvgImage, ropts, &w, &h);

    rast = nsvgCreateRasterizer();
    if (rast == NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("cannot initialize rasterizer", -1));
	Tcl_SetErrorCode(interp, "TK", "IMAGE", "SVG", "RASTERIZER_ERROR",
		NULL);
	goto cleanAST;
    }
    imgData = (unsigned char *)attemptckalloc(w * h *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;
    }
    nsvgRasterize(rast, nsvgImage, 0, 0,
	    (float) scale, imgData, w, h, w * 4);
    /* transfer the data to a photo block */
    svgblock.pixelPtr = imgData;
    svgblock.width = w;
    svgblock.height = h;
    svgblock.pitch = w * 4;
    svgblock.pixelSize = 4;
    for (c = 0; c <= 3; c++) {
	svgblock.offset[c] = c;
    }
    if (Tk_PhotoExpand(interp, imageHandle,
		destX + width, destY + height) != TCL_OK) {
	goto cleanRAST;
    }
    if (Tk_PhotoPutBlock(interp, imageHandle, &svgblock, destX, destY,
		width, height, TK_PHOTO_COMPOSITE_SET) != TCL_OK) {
	goto cleanimg;
    }
    ckfree(imgData);
    nsvgDeleteRasterizer(rast);
    nsvgDelete(nsvgImage);
    return TCL_OK;

cleanimg:
    ckfree(imgData);

cleanRAST:
    nsvgDeleteRasterizer(rast);

cleanAST:
    nsvgDelete(nsvgImage);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * GetScaleFromParameters --
 *
 *	Get the scale value from the already parsed parameters -scale,
 *	-scaletoheight and -scaletowidth.
 *
 *	The image width and height is also returned.
 *
 * Results:
 *	The evaluated or configured scale value, or 0.0 on failure
 *
 * Side effects:
 *	heightPtr and widthPtr are set to height and width of the image.
 *
 *----------------------------------------------------------------------
 */

static double
GetScaleFromParameters(
    NSVGimage *nsvgImage,
    RastOpts *ropts,
    int *widthPtr,
    int *heightPtr)
{
    double scale;
    int width, height;

    if ((nsvgImage->width == 0.0) || (nsvgImage->height == 0.0)) {
        width = height = 0;
        scale = 1.0;
    } else if (ropts->scaleToHeight > 0) {
	/*
	 * Fixed height
	 */
	height = ropts->scaleToHeight;
	scale = height / nsvgImage->height;
	width = (int) ceil(nsvgImage->width * scale);
    } else if (ropts->scaleToWidth > 0) {
	/*
	 * Fixed width
	 */
	width = ropts->scaleToWidth;
	scale = width / nsvgImage->width;
	height = (int) ceil(nsvgImage->height * scale);
    } else {
	/*
	 * Scale factor
	 */
	scale = ropts->scale;
	width = (int) ceil(nsvgImage->width * scale);
	height = (int) ceil(nsvgImage->height * scale);
    }

    *heightPtr = height;
    *widthPtr = width;
    return scale;
}

/*
 *----------------------------------------------------------------------
 *
 * GetCachePtr --
 *
 *	This function is called to get the per interpreter used
 *	svg image cache.
 *
 * Results:
 * 	Return a pointer to the used cache.
 *
 * Side effects:
 *	Initialize the cache on the first call.
 *
 *----------------------------------------------------------------------
 */

static NSVGcache *
GetCachePtr(
    Tcl_Interp *interp
) {
    NSVGcache *cachePtr = (NSVGcache *)Tcl_GetAssocData(interp, "tksvgnano", NULL);
    if (cachePtr == NULL) {
	cachePtr = (NSVGcache *)ckalloc(sizeof(NSVGcache));
	cachePtr->dataOrChan = NULL;
	Tcl_DStringInit(&cachePtr->formatString);
	cachePtr->nsvgImage = NULL;
	Tcl_SetAssocData(interp, "tksvgnano", FreeCache, cachePtr);
    }
    return cachePtr;
}

/*
 *----------------------------------------------------------------------
 *
 * CacheSVG --
 *
 *	Add the given svg image informations to the cache for further usage.
 *
 * Results:
 *	Return 1 on success, and 0 otherwise.
 *
 * Side effects:
 *
 *----------------------------------------------------------------------
 */

static int
CacheSVG(
    Tcl_Interp *interp,
    ClientData dataOrChan,
    Tcl_Obj *formatObj,
    NSVGimage *nsvgImage,
    RastOpts *ropts)
{
    TkSizeT length;
    const char *data;
    NSVGcache *cachePtr = GetCachePtr(interp);

    if (cachePtr != NULL) {
        cachePtr->dataOrChan = dataOrChan;
	if (formatObj != NULL) {
	    data = TkGetStringFromObj(formatObj, &length);
	    Tcl_DStringAppend(&cachePtr->formatString, data, length);
	}
	cachePtr->nsvgImage = nsvgImage;
	cachePtr->ropts = *ropts;
	return 1;
    }
    return 0;
}

/*
 *----------------------------------------------------------------------
 *
 * GetCachedSVG --
 *
 *	Try to get the NSVGimage from the internal cache.
 *
 * Results:
 *	Return the found NSVGimage on success, and NULL otherwise.
 *
 * Side effects:
 *	Calls the CleanCache() function.
 *
 *----------------------------------------------------------------------
 */

static NSVGimage *
GetCachedSVG(
    Tcl_Interp *interp,
    ClientData dataOrChan,
    Tcl_Obj *formatObj,
    RastOpts *ropts)
{
    TkSizeT length;
    const char *data;
    NSVGcache *cachePtr = GetCachePtr(interp);
    NSVGimage *nsvgImage = NULL;

    if ((cachePtr != NULL) && (cachePtr->nsvgImage != NULL) &&
	(cachePtr->dataOrChan == dataOrChan)) {
        if (formatObj != NULL) {
	    data = TkGetStringFromObj(formatObj, &length);
	    if (strcmp(data, Tcl_DStringValue(&cachePtr->formatString)) == 0) {
	        nsvgImage = cachePtr->nsvgImage;
		*ropts = cachePtr->ropts;
		cachePtr->nsvgImage = NULL;
	    }
	} else if (Tcl_DStringLength(&cachePtr->formatString) == 0) {
	    nsvgImage = cachePtr->nsvgImage;
	    *ropts = cachePtr->ropts;
	    cachePtr->nsvgImage = NULL;
	}
    }
    CleanCache(interp);
    return nsvgImage;
}

/*
 *----------------------------------------------------------------------
 *
 * CleanCache --
 *
 *	Reset the cache and delete the saved image in it.
 *
 * Results:
 *
 * Side effects:
 *
 *----------------------------------------------------------------------
 */

static void
CleanCache(Tcl_Interp *interp)
{
    NSVGcache *cachePtr = GetCachePtr(interp);

    if (cachePtr != NULL) {
        cachePtr->dataOrChan = NULL;
        Tcl_DStringSetLength(&cachePtr->formatString, 0);
	if (cachePtr->nsvgImage != NULL) {
	    nsvgDelete(cachePtr->nsvgImage);
	    cachePtr->nsvgImage = NULL;
	}
    }
}

/*
 *----------------------------------------------------------------------
 *
 * FreeCache --
 *
 *	This function is called to clean up the internal cache data.
 *
 * Results:
 *
 * Side effects:
 *	Existing image data in the cache and the cache will be deleted.
 *
 *----------------------------------------------------------------------
 */

static void
FreeCache(ClientData clientData, Tcl_Interp *interp)
{
    NSVGcache *cachePtr = (NSVGcache *)clientData;
    (void)interp;

    Tcl_DStringFree(&cachePtr->formatString);
    if (cachePtr->nsvgImage != NULL) {
        nsvgDelete(cachePtr->nsvgImage);
    }
    ckfree(cachePtr);
}

Changes to generic/tkImgUtil.c.
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







/*
 * 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.
 */

#include "tkInt.h"
#include "xbytes.h"
51
52
53
54
55
56
57
58

59
60
61
62
63
64
65
51
52
53
54
55
56
57

58
59
60
61
62
63
64
65







-
+







     */

    dataWidth = image->bytes_per_line;
    if (dataWidth % alignment) {
	dataWidth += (alignment - (dataWidth % alignment));
    }

    data = ckalloc(dataWidth * image->height);
    data = (char *)ckalloc(dataWidth * image->height);

    destPtr = data;
    for (i = 0; i < image->height; i++) {
	srcPtr = &image->data[i * image->bytes_per_line];
	for (j = 0; j < dataWidth; j++) {
	    if (j >= image->bytes_per_line) {
		*destPtr = 0;
Changes to generic/tkInt.decls.
1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15






-
-
+
+







# tkInt.decls --
#
#	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 <[email protected]>
# Copyright © 1998-1999 Scriptics Corporation.
# Copyright © 2007 Daniel A. Steffen <[email protected]>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

library tk

##############################################################################
95
96
97
98
99
100
101
102

103
104
105
106
107
108
109
95
96
97
98
99
100
101

102
103
104
105
106
107
108
109







-
+







	    Display *display, Drawable drawable, GC gc, GC outlineGC)
}
declare 21 {
    int TkFindStateNum(Tcl_Interp *interp, const char *option,
	    const TkStateMap *mapPtr, const char *strKey)
}
declare 22 {
    CONST86 char *TkFindStateString(const TkStateMap *mapPtr, int numKey)
    const char *TkFindStateString(const TkStateMap *mapPtr, int numKey)
}
declare 23 {
    void TkFocusDeadWindow(TkWindow *winPtr)
}
declare 24 {
    int TkFocusFilterEvent(TkWindow *winPtr, XEvent *eventPtr)
}
178
179
180
181
182
183
184
185

186
187
188
189
190
191
192
178
179
180
181
182
183
184

185
186
187
188
189
190
191
192







-
+







	    TkWindow *destPtr, int leaveType, int enterType,
	    Tcl_QueuePosition position)
}
declare 45 {
    void TkInstallFrameMenu(Tk_Window tkwin)
}
declare 46 {
    CONST86 char *TkKeysymToString(KeySym keysym)
    const char *TkKeysymToString(KeySym keysym)
}
declare 47 {
    int TkLineToArea(double end1Ptr[], double end2Ptr[], double rectPtr[])
}
declare 48 {
    double TkLineToPoint(double end1Ptr[], double end2Ptr[], double pointPtr[])
}
284
285
286
287
288
289
290
291

292
293
294
295
296
297
298
284
285
286
287
288
289
290

291
292
293
294
295
296
297
298







-
+







declare 78 {
    int TkReadBitmapFile(Display *display, Drawable d, const char *filename,
	    unsigned int *width_return, unsigned int *height_return,
	    Pixmap *bitmap_return, int *x_hot_return, int *y_hot_return)
}
declare 79 {
    int TkScrollWindow(Tk_Window tkwin, GC gc, int x, int y,
	    int width, int height, int dx, int dy, TkRegion damageRgn)
	    int width, int height, int dx, int dy, Region damageRgn)
}
declare 80 {
    void TkSelDeadWindow(TkWindow *winPtr)
}
declare 81 {
    void TkSelEventProc(Tk_Window tkwin, XEvent *eventPtr)
}
385
386
387
388
389
390
391
392

393
394
395
396
397
398
399
400
401
402
403
404
405

406
407
408

409
410
411

412
413
414

415
416
417

418
419
420
421

422
423
424
425


426
427
428
429
430
431
432
385
386
387
388
389
390
391

392
393
394
395
396
397
398
399
400
401
402
403
404

405
406
407

408
409
410

411
412
413

414
415
416

417
418
419
420

421
422
423


424
425
426
427
428
429
430
431
432







-
+












-
+


-
+


-
+


-
+


-
+



-
+


-
-
+
+







    TkMainInfo *TkGetMainInfoList(void)
}
declare 108 {
    int TkGetWindowFromObj(Tcl_Interp *interp, Tk_Window tkwin,
	    Tcl_Obj *objPtr, Tk_Window *windowPtr)
}
declare 109 {
    CONST86 char *TkpGetString(TkWindow *winPtr, XEvent *eventPtr, Tcl_DString *dsPtr)
    const char *TkpGetString(TkWindow *winPtr, XEvent *eventPtr, Tcl_DString *dsPtr)
}
declare 110 {
    void TkpGetSubFonts(Tcl_Interp *interp, Tk_Font tkfont)
}
declare 111 {
    Tcl_Obj *TkpGetSystemDefault(Tk_Window tkwin,
	    const char *dbName, const char *className)
}
declare 112 {
    void TkpMenuThreadInit(void)
}
declare 113 {
    int TkClipBox(TkRegion rgn, XRectangle *rect_return)
    int XClipBox(Region rgn, XRectangle *rect_return)
}
declare 114 {
    TkRegion TkCreateRegion(void)
    Region XCreateRegion(void)
}
declare 115 {
    int TkDestroyRegion(TkRegion rgn)
    int XDestroyRegion(Region rgn)
}
declare 116 {
    int TkIntersectRegion(TkRegion sra, TkRegion srcb, TkRegion dr_return)
    int XIntersectRegion(Region sra, Region srcb, Region dr_return)
}
declare 117 {
    int TkRectInRegion(TkRegion rgn, int x, int y, unsigned int width,
    int XRectInRegion(Region rgn, int x, int y, unsigned int width,
	    unsigned int height)
}
declare 118 {
    int TkSetRegion(Display *display, GC gc, TkRegion rgn)
    int XSetRegion(Display *display, GC gc, Region rgn)
}
declare 119 {
    int TkUnionRectWithRegion(XRectangle *rect,
	    TkRegion src, TkRegion dr_return)
    int XUnionRectWithRegion(XRectangle *rect,
	    Region src, Region dr_return)
}
declare 121 aqua {
    Pixmap TkpCreateNativeBitmap(Display *display, const void *source)
}
declare 122 aqua {
    void TkpDefineNativeBitmaps(void)
}
448
449
450
451
452
453
454
455

456
457
458
459
460
461
462
463
464
465
466
467
468
469
470

471
472
473
474
475
476
477
448
449
450
451
452
453
454

455
456
457
458
459
460
461
462
463
464
465
466
467
468
469

470
471
472
473
474
475
476
477







-
+














-
+







declare 138 {
    KeySym TkpGetKeySym(TkDisplay *dispPtr, XEvent *eventPtr)
}
declare 139 {
    void TkpInitKeymapInfo(TkDisplay *dispPtr)
}
declare 140 {
    TkRegion TkPhotoGetValidRegion(Tk_PhotoHandle handle)
    Region TkPhotoGetValidRegion(Tk_PhotoHandle handle)
}
declare 141 {
    TkWindow **TkWmStackorderToplevel(TkWindow *parentPtr)
}
declare 142 {
    void TkFocusFree(TkMainInfo *mainPtr)
}
declare 143 {
    void TkClipCleanup(TkDisplay *dispPtr)
}
declare 144 {
    void TkGCCleanup(TkDisplay *dispPtr)
}
declare 145 {
    int TkSubtractRegion(TkRegion sra, TkRegion srcb, TkRegion dr_return)
    int XSubtractRegion(Region sra, Region srcb, Region dr_return)
}
declare 146 {
    void TkStylePkgInit(TkMainInfo *mainPtr)
}
declare 147 {
    void TkStylePkgFree(TkMainInfo *mainPtr)
}
534
535
536
537
538
539
540
541

542
543
544
545
546
547
548
534
535
536
537
538
539
540

541
542
543
544
545
546
547
548







-
+







}
declare 162 {
    struct TkTextIndex *TkTextMakeByteIndex(TkTextBTree tree,
	    const struct TkText *textPtr, int lineIndex,
	    int byteIndex, struct TkTextIndex *indexPtr)
}
declare 163 {
    int TkTextPrintIndex(const struct TkText *textPtr,
    TkSizeT TkTextPrintIndex(const struct TkText *textPtr,
	    const struct TkTextIndex *indexPtr, char *string)
}
declare 164 {
    struct TkTextSegment *TkTextSetMark(struct TkText *textPtr,
	    const char *name, struct TkTextIndex *indexPtr)
}
declare 165 {
563
564
565
566
567
568
569
570

571
572
573
574


575
576
577
578

579
580
581
582


583
584
585
586

587
588
589
590


591
592
593
594

595
596
597
598


599
600
601
602

603
604
605
606


607
608
609
610

611
612
613
614


615
616
617
618
619
620
621
563
564
565
566
567
568
569

570
571
572


573
574
575
576
577

578
579
580


581
582
583
584
585

586
587
588


589
590
591
592
593

594
595
596


597
598
599
600
601

602
603
604


605
606
607
608
609

610
611
612


613
614
615
616
617
618
619
620
621







-
+


-
-
+
+



-
+


-
-
+
+



-
+


-
-
+
+



-
+


-
-
+
+



-
+


-
-
+
+



-
+


-
-
+
+







	    struct TkTextDispChunk *chunkPtr, int x, int y,
	    int height, int baseline, Display *display,
	    Drawable dst, int screenY)
}
# Next group of functions exposed due to [Bug 2768945].
declare 169 {
    int TkStateParseProc(ClientData clientData, Tcl_Interp *interp,
	    Tk_Window tkwin, const char *value, char *widgRec, int offset)
	    Tk_Window tkwin, const char *value, char *widgRec, TkSizeT offset)
}
declare 170 {
    CONST86 char *TkStatePrintProc(ClientData clientData, Tk_Window tkwin,
	    char *widgRec, int offset, Tcl_FreeProc **freeProcPtr)
    const char *TkStatePrintProc(ClientData clientData, Tk_Window tkwin,
	    char *widgRec, TkSizeT offset, Tcl_FreeProc **freeProcPtr)
}
declare 171 {
    int TkCanvasDashParseProc(ClientData clientData, Tcl_Interp *interp,
	    Tk_Window tkwin, const char *value, char *widgRec, int offset)
	    Tk_Window tkwin, const char *value, char *widgRec, TkSizeT offset)
}
declare 172 {
    CONST86 char *TkCanvasDashPrintProc(ClientData clientData, Tk_Window tkwin,
	    char *widgRec, int offset, Tcl_FreeProc **freeProcPtr)
    const char *TkCanvasDashPrintProc(ClientData clientData, Tk_Window tkwin,
	    char *widgRec, TkSizeT offset, Tcl_FreeProc **freeProcPtr)
}
declare 173 {
    int TkOffsetParseProc(ClientData clientData, Tcl_Interp *interp,
	    Tk_Window tkwin, const char *value, char *widgRec, int offset)
	    Tk_Window tkwin, const char *value, char *widgRec, TkSizeT offset)
}
declare 174 {
    CONST86 char *TkOffsetPrintProc(ClientData clientData, Tk_Window tkwin,
	    char *widgRec, int offset, Tcl_FreeProc **freeProcPtr)
    const char *TkOffsetPrintProc(ClientData clientData, Tk_Window tkwin,
	    char *widgRec, TkSizeT offset, Tcl_FreeProc **freeProcPtr)
}
declare 175 {
    int TkPixelParseProc(ClientData clientData, Tcl_Interp *interp,
	    Tk_Window tkwin, const char *value, char *widgRec, int offset)
	    Tk_Window tkwin, const char *value, char *widgRec, TkSizeT offset)
}
declare 176 {
    CONST86 char *TkPixelPrintProc(ClientData clientData, Tk_Window tkwin,
	    char *widgRec, int offset, Tcl_FreeProc **freeProcPtr)
    const char *TkPixelPrintProc(ClientData clientData, Tk_Window tkwin,
	    char *widgRec, TkSizeT offset, Tcl_FreeProc **freeProcPtr)
}
declare 177 {
    int TkOrientParseProc(ClientData clientData, Tcl_Interp *interp,
	    Tk_Window tkwin, const char *value, char *widgRec, int offset)
	    Tk_Window tkwin, const char *value, char *widgRec, TkSizeT offset)
}
declare 178 {
    CONST86 char *TkOrientPrintProc(ClientData clientData, Tk_Window tkwin,
	    char *widgRec, int offset, Tcl_FreeProc **freeProcPtr)
    const char *TkOrientPrintProc(ClientData clientData, Tk_Window tkwin,
	    char *widgRec, TkSizeT offset, Tcl_FreeProc **freeProcPtr)
}
declare 179 {
    int TkSmoothParseProc(ClientData clientData, Tcl_Interp *interp,
	    Tk_Window tkwin, const char *value, char *widgRec, int offset)
	    Tk_Window tkwin, const char *value, char *widgRec, TkSizeT offset)
}
declare 180 {
    CONST86 char *TkSmoothPrintProc(ClientData clientData, Tk_Window tkwin,
	    char *widgRec, int offset, Tcl_FreeProc **freeProcPtr)
    const char *TkSmoothPrintProc(ClientData clientData, Tk_Window tkwin,
	    char *widgRec, TkSizeT offset, Tcl_FreeProc **freeProcPtr)
}

# Angled text API, exposed for Emiliano Gavilán's RBC work.
declare 181 {
    void TkDrawAngledTextLayout(Display *display, Drawable drawable, GC gc,
	    Tk_TextLayout layout, int x, int y, double angle, int firstChar,
	    int lastChar)
630
631
632
633
634
635
636















637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653

654


655
656
657
658
659
660
661
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665



666

667
668
669
670
671
672
673
674
675







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+














-
-
-
+
-
+
+







	    int width, int height, double angle)
}
declare 184 {
    void TkDrawAngledChars(Display *display,Drawable drawable, GC gc,
	    Tk_Font tkfont, const char *source, int numBytes, double x,
	    double y, double angle)
}

# Support for aqua's inability to draw outside [NSView drawRect:]
declare 185 macosx {
    void TkpRedrawWidget(Tk_Window tkwin)
}
declare 186 macosx {
    int TkpWillDrawWidget(Tk_Window tkwin)
}

# Debugging / testing functions for photo images
declare 187 {
    int TkDebugPhotoStringMatchDef(Tcl_Interp *inter, Tcl_Obj *data,
            Tcl_Obj *formatString, int *widthPtr, int *heightPtr)
}


##############################################################################

# Define the platform specific internal Tcl interface. These functions are
# only available on the designated platform.

interface tkIntPlat

################################
# Unix specific functions

declare 0 x11 {
    void TkCreateXEventSource(void)
}
#
# Slot 1 unused (WAS: TkFreeWindowId)
# Slot 2 unused (WAS: TkInitXId)
declare 2 x11 {
#
    void TkGenerateActivateEvents(TkWindow *winPtr, int active)
}
declare 3 x11 {
    int TkpCmapStressed(Tk_Window tkwin, Colormap colormap)
}
declare 4 x11 {
    void TkpSync(Display *display)
}
declare 5 x11 {
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689


























690
691
692
693
694
695
696
686
687
688
689
690
691
692



693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733







-
-
-








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







}
declare 9 x11 {
    void TkWmCleanup(TkDisplay *dispPtr)
}
declare 10 x11 {
    void TkSendCleanup(TkDisplay *dispPtr)
}
#
# Slot 11 unused (WAS: TkFreeXId)
#
declare 12 x11 {
    int TkpWmSetState(TkWindow *winPtr, int state)
}
# only needed by tktest:
declare 13 x11 {
    int TkpTestsendCmd(ClientData clientData, Tcl_Interp *interp, int objc,
	    Tcl_Obj *const objv[])
}
declare 38 x11 {
    int TkpCmapStressed_(Tk_Window tkwin, Colormap colormap)
}
declare 39 x11 {
    void TkpSync_(Display *display)
}
declare 40 x11 {
    Window TkUnixContainerId_(TkWindow *winPtr)
}
declare 41 x11 {
    int TkUnixDoOneXEvent_(Tcl_Time *timePtr)
}
declare 42 x11 {
    void TkUnixSetMenubar_(Tk_Window tkwin, Tk_Window menubar)
}
declare 43 x11 {
    void TkWmCleanup_(TkDisplay *dispPtr)
}
declare 44 x11 {
    void TkSendCleanup_(TkDisplay *dispPtr)
}
# only needed by tktest:
declare 45 x11 {
    int TkpTestsendCmd_(ClientData clientData, Tcl_Interp *interp, int objc,
	    Tcl_Obj *const objv[])
}

################################
# Windows specific functions

declare 0 win {
    char *TkAlignImageData(XImage *image, int alignment, int bitOrder)
}
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864


865
866

867
868
869
870
871
872
873
887
888
889
890
891
892
893








894
895


896
897
898
899
900
901
902
903







-
-
-
-
-
-
-
-
+
+
-
-
+








################################
# Aqua specific functions

declare 0 aqua {
    void TkGenerateActivateEvents(TkWindow *winPtr, int active)
}

# removed duplicates from tkInt table
#declare 1 aqua {
#    Pixmap TkpCreateNativeBitmap(Display *display, const void *source)
#}
#
#declare 2 aqua {
#    void TkpDefineNativeBitmaps(void)
declare 2 aqua {
    void TkGenerateActivateEvents_(TkWindow *winPtr, int active)
#}

}
declare 3 aqua {
    void TkPointerDeadWindow(TkWindow *winPtr)
}
declare 4 aqua {
    void TkpSetCapture(TkWindow *winPtr)
}
declare 5 aqua {
884
885
886
887
888
889
890

891
892


893

894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
914
915
916
917
918
919
920
921


922
923

924
925
926
927






928
929
930






931
932
933
934
935
936
937







+
-
-
+
+
-
+



-
-
-
-
-
-



-
-
-
-
-
-







}
declare 9 aqua {
    void TkMacOSXClearMenubarActive(void)
}
declare 10 aqua {
    int TkMacOSXDispatchMenuEvent(int menuID, int index)
}
# Now a static function
declare 11 aqua {
    void TkMacOSXInstallCursor(int resizeOverride)
# declare 11 aqua {
#     void TkMacOSXInstallCursor(int resizeOverride)
}
# }
declare 12 aqua {
    void TkMacOSXHandleTearoffMenu(void)
}

# removed duplicate from tkPlat table(tk.decls)
#declare 13 aqua {
#    void TkMacOSXInvalClipRgns(TkWindow *winPtr)
#}

declare 14 aqua {
    int TkMacOSXDoHLEvent(void *theEvent)
}

# removed duplicate from tkPlat table(tk.decls)
#declare 15 aqua {
#    void *TkMacOSXGetDrawablePort(Drawable drawable)
#}

declare 16 aqua {
    Window TkMacOSXGetXWindow(void *macWinPtr)
}
declare 17 aqua {
    int TkMacOSXGrowToplevel(void *whichWindow, XPoint start)
}
declare 18 aqua {
940
941
942
943
944
945
946

947
948


949

950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967

968
969


970

971
972
973
974
975

976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012

1013
1014
1015

1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
959
960
961
962
963
964
965
966


967
968

969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988


989
990

991
992
993
994
995

996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009



1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029

1030
1031
1032

1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043







1044
1045
1046

1047
1048
1049
1050
1051
1052
1053







+
-
-
+
+
-
+


















+
-
-
+
+
-
+




-
+













-
-
-




















-
+


-
+










-
-
-
-
-
-
-



-







}
declare 24 aqua {
    void *TkMacOSXMakeStippleMap(Drawable d1, Drawable d2)
}
declare 25 aqua {
    void TkMacOSXMenuClick(void)
}
# The corresponding Unregister was not a stub, and this should be static.
declare 26 aqua {
    void TkMacOSXRegisterOffScreenWindow(Window window, void *portPtr)
#declare 26 aqua {
#    void TkMacOSXRegisterOffScreenWindow(Window window, void *portPtr)
}
#}
declare 27 aqua {
    int TkMacOSXResizable(TkWindow *winPtr)
}
declare 28 aqua {
    void TkMacOSXSetHelpMenuItemCount(void)
}
declare 29 aqua {
    void TkMacOSXSetScrollbarGrow(TkWindow *winPtr, int flag)
}
declare 30 aqua {
    void TkMacOSXSetUpClippingRgn(Drawable drawable)
}
declare 31 aqua {
    void TkMacOSXSetUpGraphicsPort(GC gc, void *destPort)
}
declare 32 aqua {
    void TkMacOSXUpdateClipRgn(TkWindow *winPtr)
}
# This was not implemented.  Perhaps meant to be OffScreen ?
declare 33 aqua {
    void TkMacOSXUnregisterMacWindow(void *portPtr)
#declare 33 aqua {
#    void TkMacOSXUnregisterMacWindow(void *portPtr)
}
#}
declare 34 aqua {
    int TkMacOSXUseMenuID(short macID)
}
declare 35 aqua {
    TkRegion TkMacOSXVisableClipRgn(TkWindow *winPtr)
    Region TkMacOSXVisableClipRgn(TkWindow *winPtr)
}
declare 36 aqua {
    void TkMacOSXWinBounds(TkWindow *winPtr, void *geometry)
}
declare 37 aqua {
    void TkMacOSXWindowOffset(void *wRef, int *xOffset, int *yOffset)
}
declare 38 aqua {
    int TkSetMacColor(unsigned long pixel, void *macColor)
}
declare 39 aqua {
    void TkSetWMName(TkWindow *winPtr, Tk_Uid titleUid)
}
#
# Slot 40 unused (WAS: TkSuspendClipboard)
#
declare 41 aqua {
    int TkMacOSXZoomToplevel(void *whichWindow, short zoomPart)
}
declare 42 aqua {
    Tk_Window Tk_TopCoordsToWindow(Tk_Window tkwin, int rootX, int rootY,
	    int *newX, int *newY)
}
declare 43 aqua {
    MacDrawable *TkMacOSXContainerId(TkWindow *winPtr)
}
declare 44 aqua {
    MacDrawable *TkMacOSXGetHostToplevel(TkWindow *winPtr)
}
declare 45 aqua {
    void TkMacOSXPreprocessMenu(void)
}
declare 46 aqua {
    int TkpIsWindowFloating(void *window)
}
declare 47 aqua {
    Tk_Window TkMacOSXGetCapture(void)
    Tk_Window TkpGetCapture(void)
}
declare 49 aqua {
    Tk_Window TkGetTransientMaster(TkWindow *winPtr)
    Tk_Window TkMacOSXGetContainer(TkWindow *winPtr)
}
declare 50 aqua {
    int TkGenerateButtonEvent(int x, int y, Window window, unsigned int state)
}
declare 51 aqua {
    void TkGenWMDestroyEvent(Tk_Window tkwin)
}
declare 52 aqua {
    void TkMacOSXSetDrawingEnabled(TkWindow *winPtr, int flag)
}

# removed duplicate from tkPlat table (tk.decls)
#declare 52 aqua {
#    void TkGenWMConfigureEvent(Tk_Window tkwin, int x, int y,
# 	    int width, int height, int flags)
#}

declare 53 aqua {
    unsigned long TkpGetMS(void)
}

# For Canvas3d, requested by Sean Woods
declare 54 aqua {
    void *TkMacOSXDrawable(Drawable drawable)
}
declare 55 aqua {
    int TkpScanWindowId(Tcl_Interp *interp, const char *string, Window *idPtr)
}
1492
1493
1494
1495
1496
1497
1498


1499



























































1500
1501

1502
1503

1504
1505
1506
1507

1508
1509
1510

1511
1512
1513
1514
1515

1516
1517
1518
1519

1520
1521
1522

1523
1524
1525

1526
1527
1528

1529
1530

1531
1532


1533
1534

1535
1536
1537

1538
1539
1540

1541
1542
1543

1544
1545
1546

1547
1548
1549

1550
1551
1552
1553

1554
1555
1556
1557

1558
1559
1560
1561

1562
1563
1564
1565

1566
1567
1568
1569
1570

1571
1572
1573
1574

1575
1576
1577

1578
1579
1580

1581
1582
1583
1584

1585
1586
1587

1588
1589
1590
1591

1592
1593
1594
1595

1596
1597
1598
1599

1600
1601
1602

1603
1604
1605

1606
1607
1608
1609

1610
1611
1612

1613
1614
1615
1616
1617

1618
1619
1620
1621
1622

1623
1624
1625

1626
1627
1628
1629

1630
1631
1632

1633
1634
1635

1636
1637
1638
1639

1640
1641
1642

1643
1644
1645
1646

1647
1648
1649

1650
1651
1652

1653
1654
1655
1656

1657
1658
1659

1660
1661
1662

1663
1664
1665

1666
1667
1668

1669
1670
1671

1672
1673
1674

1675
1676
1677

1678
1679
1680

1681
1682
1683

1684
1685
1686

1687
1688
1689

1690
1691
1692

1693
1694
1695

1696
1697
1698

1699
1700
1701
1702
1703

1704
1705
1706
1707

1708
1709
1710
1711

1712
1713
1714

1715
1716
1717
1718

1719
1720
1721

1722
1723
1724

1725
1726
1727

1728
1729
1730
1731

1732
1733
1734
1735

1736
1737
1738

1739
1740
1741

1742
1743
1744

1745
1746
1747

1748
1749
1750

1751
1752
1753

1754
1755
1756

1757
1758
1759
1760

1761
1762
1763

1764
1765
1766

1767
1768
1769
1770

1771
1772
1773
1774

1775
1776
1777
1778

1779
1780
1781
1782

1783
1784
1785

1786
1787
1788
1789

1790
1791
1792
1793

1794
1795
1796

1797
1798
1799

1800
1801
1802
1803

1804
1805
1806
1807
1808

1809
1810
1811

1812
1813
1814
1815

1816
1817
1818
1819

1820
1821
















































1822

1823
1824
1825

1826
1827
1828

1829
1830
1831

1832
1833
1834

1835
1836
1837

1838
1839




1840

1841
1842




























1843

1844
1845
1846
1847


1848






































































1849
1850
1851
1502
1503
1504
1505
1506
1507
1508
1509
1510

1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570

1571
1572

1573
1574
1575
1576

1577
1578
1579

1580
1581
1582
1583
1584

1585
1586
1587
1588

1589
1590
1591

1592
1593
1594

1595
1596
1597

1598
1599
1600
1601


1602
1603
1604

1605
1606
1607

1608
1609
1610

1611
1612
1613

1614
1615
1616

1617
1618
1619

1620
1621
1622
1623

1624
1625
1626
1627

1628
1629
1630
1631

1632
1633
1634
1635

1636
1637
1638
1639
1640

1641
1642
1643
1644

1645
1646
1647

1648
1649
1650

1651
1652
1653
1654

1655
1656
1657

1658
1659
1660
1661

1662
1663
1664
1665

1666
1667
1668
1669

1670
1671
1672

1673
1674
1675

1676
1677
1678
1679

1680
1681
1682

1683
1684
1685
1686
1687

1688
1689
1690
1691
1692

1693
1694
1695

1696
1697
1698
1699

1700
1701
1702

1703
1704
1705

1706
1707
1708
1709

1710
1711
1712

1713
1714
1715
1716

1717
1718
1719

1720
1721
1722

1723
1724
1725
1726

1727
1728
1729

1730
1731
1732

1733
1734
1735

1736
1737
1738

1739
1740
1741

1742
1743
1744

1745
1746
1747

1748
1749
1750

1751
1752
1753

1754
1755
1756

1757
1758
1759

1760
1761
1762

1763
1764
1765

1766
1767
1768

1769
1770
1771
1772
1773

1774
1775
1776
1777

1778
1779
1780
1781

1782
1783
1784

1785
1786
1787
1788

1789
1790
1791

1792
1793
1794

1795
1796
1797

1798
1799
1800
1801

1802
1803
1804
1805

1806
1807
1808

1809
1810
1811

1812
1813
1814

1815
1816
1817

1818
1819
1820

1821
1822
1823

1824
1825
1826

1827
1828
1829
1830

1831
1832
1833

1834
1835
1836

1837
1838
1839
1840

1841
1842
1843
1844

1845
1846
1847
1848

1849
1850
1851
1852

1853
1854
1855

1856
1857
1858
1859

1860
1861
1862
1863

1864
1865
1866

1867
1868
1869

1870
1871
1872
1873

1874
1875
1876
1877
1878

1879
1880
1881

1882
1883
1884
1885

1886
1887
1888
1889

1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940

1941
1942
1943

1944
1945
1946

1947
1948
1949

1950
1951
1952

1953
1954
1955

1956
1957
1958
1959
1960
1961
1962

1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993

1994
1995
1996
1997
1998
1999
2000

2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073







+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+

-
+



-
+


-
+




-
+



-
+


-
+


-
+


-
+


+
-
-
+
+

-
+


-
+


-
+


-
+


-
+


-
+



-
+



-
+



-
+



-
+




-
+



-
+


-
+


-
+



-
+


-
+



-
+



-
+



-
+


-
+


-
+



-
+


-
+




-
+




-
+


-
+



-
+


-
+


-
+



-
+


-
+



-
+


-
+


-
+



-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+




-
+



-
+



-
+


-
+



-
+


-
+


-
+


-
+



-
+



-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+



-
+


-
+


-
+



-
+



-
+



-
+



-
+


-
+



-
+



-
+


-
+


-
+



-
+




-
+


-
+



-
+



-
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+


-
+


-
+


-
+


-
+


-
+


+
+
+
+
-
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+




+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



    int XReparentWindow(Display *d, Window w, Window p, int x, int y)
}
declare 137 win {
    int XPutImage(Display *d, Drawable dr, GC gc, XImage *im,
	    int sx, int sy, int dx, int dy,
	    unsigned int w, unsigned int h)
}
declare 138 win {
    Region XPolygonRegion(XPoint *pts, int n, int rule)

}
declare 139 win {
    int XPointInRegion(Region rgn, int x, int y)
}
# For XIM
declare 140 win {
    XVaNestedList XVaCreateNestedList(int dummy, ...)
}
declare 141 win {
    char *XSetICValues(XIC xic, ...)
}
declare 142 win {
    char *XGetICValues(XIC xic, ...)
}
declare 143 win {
    void XSetICFocus(XIC xic)
}
declare 147 win {
    void XFreeFontSet(Display *display, XFontSet fontset)
}
declare 148 win {
    int XCloseIM(XIM im)
}
declare 149 win {
    Bool XRegisterIMInstantiateCallback(Display *dpy, struct _XrmHashBucketRec *rbd,
	    char *res_name, char *res_class, XIDProc callback, XPointer client_data)
}
declare 150 win {
    Bool XUnregisterIMInstantiateCallback(Display *dpy, struct _XrmHashBucketRec *rbd,
	    char *res_name, char *res_class, XIDProc callback, XPointer client_data)
}
declare 151 win {
    char *XSetLocaleModifiers(const char *modifier_list)
}
declare 152 win {
    XIM XOpenIM(Display *dpy, struct _XrmHashBucketRec *rdb, char *res_name,
	    char *res_class)
}
declare 153 win {
    char *XGetIMValues(XIM im, ...)
}
declare 154 win {
    char *XSetIMValues(XIM im, ...)
}
declare 155 win {
    XFontSet XCreateFontSet(Display *display, _Xconst char *base_font_name_list,
	    char ***missing_charset_list, int *missing_charset_count, char **def_string)
}
declare 156 win {
    void XFreeStringList(char **list)
}
declare 157 win {
    KeySym XkbKeycodeToKeysym(Display *d, unsigned int k, int g, int i)
}
declare 158 win {
    Display *XkbOpenDisplay(const char *name, int *ev_rtrn, int *err_rtrn,
	    int *major_rtrn, int *minor_rtrn, int *reason)
}

################################
# X functions for Aqua
# X functions for MacOSX

declare 0 aqua {
declare 0 macosx {
    int XSetDashes(Display *display, GC gc, int dash_offset,
	    _Xconst char *dash_list, int n)
}
declare 1 aqua {
declare 1 macosx {
    XModifierKeymap *XGetModifierMapping(Display *d)
}
declare 2 aqua {
declare 2 macosx {
    XImage *XCreateImage(Display *d, Visual *v, unsigned int ui1, int i1,
	    int i2, char *cp, unsigned int ui2, unsigned int ui3, int i3,
	    int i4)
}
declare 3 aqua {
declare 3 macosx {
    XImage *XGetImage(Display *d, Drawable dr, int i1, int i2,
	    unsigned int ui1, unsigned int ui2, unsigned long ul, int i3)
}
declare 4 aqua {
declare 4 macosx {
    char *XGetAtomName(Display *d, Atom a)
}
declare 5 aqua {
declare 5 macosx {
    char *XKeysymToString(KeySym k)
}
declare 6 aqua {
declare 6 macosx {
    Colormap XCreateColormap(Display *d, Window w, Visual *v, int i)
}
declare 7 aqua {
declare 7 macosx {
    GContext XGContextFromGC(GC g)
}
# second parameter was of type KeyCode
declare 8 aqua {
    KeySym XKeycodeToKeysym(Display *d, KeyCode k, int i)
declare 8 macosx {
    KeySym XKeycodeToKeysym(Display *d, unsigned int k, int i)
}
declare 9 aqua {
declare 9 macosx {
    KeySym XStringToKeysym(_Xconst char *c)
}
declare 10 aqua {
declare 10 macosx {
    Window XRootWindow(Display *d, int i)
}
declare 11 aqua {
declare 11 macosx {
    XErrorHandler XSetErrorHandler(XErrorHandler x)
}
declare 12 aqua {
declare 12 macosx {
    Status XAllocColor(Display *d, Colormap c, XColor *xp)
}
declare 13 aqua {
declare 13 macosx {
    int XBell(Display *d, int i)
}
declare 14 aqua {
declare 14 macosx {
    int XChangeProperty(Display *d, Window w, Atom a1, Atom a2, int i1,
	    int i2, _Xconst unsigned char *c, int i3)
}
declare 15 aqua {
declare 15 macosx {
    int XChangeWindowAttributes(Display *d, Window w, unsigned long ul,
	    XSetWindowAttributes *x)
}
declare 16 aqua {
declare 16 macosx {
    int XConfigureWindow(Display *d, Window w, unsigned int i,
	    XWindowChanges *x)
}
declare 17 aqua {
declare 17 macosx {
    int XCopyArea(Display *d, Drawable dr1, Drawable dr2, GC g, int i1,
	    int i2, unsigned int ui1, unsigned int ui2, int i3, int i4)
}
declare 18 aqua {
declare 18 macosx {
    int XCopyPlane(Display *d, Drawable dr1, Drawable dr2, GC g, int i1,
	    int i2, unsigned int ui1,
	    unsigned int ui2, int i3, int i4, unsigned long ul)
}
declare 19 aqua {
declare 19 macosx {
    Pixmap XCreateBitmapFromData(Display *display, Drawable d,
	    _Xconst char *data, unsigned int width, unsigned int height)
}
declare 20 aqua {
declare 20 macosx {
    int XDefineCursor(Display *d, Window w, Cursor c)
}
declare 21 aqua {
declare 21 macosx {
    int XDestroyWindow(Display *d, Window w)
}
declare 22 aqua {
declare 22 macosx {
    int XDrawArc(Display *d, Drawable dr, GC g, int i1, int i2,
	    unsigned int ui1, unsigned int ui2, int i3, int i4)
}
declare 23 aqua {
declare 23 macosx {
    int XDrawLines(Display *d, Drawable dr, GC g, XPoint *x, int i1, int i2)
}
declare 24 aqua {
declare 24 macosx {
    int XDrawRectangle(Display *d, Drawable dr, GC g, int i1, int i2,
	    unsigned int ui1, unsigned int ui2)
}
declare 25 aqua {
declare 25 macosx {
    int XFillArc(Display *d, Drawable dr, GC g, int i1, int i2,
	    unsigned int ui1, unsigned int ui2, int i3, int i4)
}
declare 26 aqua {
declare 26 macosx {
    int XFillPolygon(Display *d, Drawable dr, GC g, XPoint *x,
	    int i1, int i2, int i3)
}
declare 27 aqua {
declare 27 macosx {
    int XFillRectangles(Display *d, Drawable dr, GC g, XRectangle *x, int i)
}
declare 28 aqua {
declare 28 macosx {
    int XFreeColormap(Display *d, Colormap c)
}
declare 29 aqua {
declare 29 macosx {
    int XFreeColors(Display *d, Colormap c,
	    unsigned long *ulp, int i, unsigned long ul)
}
declare 30 aqua {
declare 30 macosx {
    int XFreeModifiermap(XModifierKeymap *x)
}
declare 31 aqua {
declare 31 macosx {
    Status XGetGeometry(Display *d, Drawable dr, Window *w, int *i1,
	    int *i2, unsigned int *ui1, unsigned int *ui2, unsigned int *ui3,
	    unsigned int *ui4)
}
declare 32 aqua {
declare 32 macosx {
    int XGetWindowProperty(Display *d, Window w, Atom a1, long l1, long l2,
	    Bool b, Atom a2, Atom *ap, int *ip, unsigned long *ulp1,
	    unsigned long *ulp2, unsigned char **cpp)
}
declare 33 aqua {
declare 33 macosx {
    int XGrabKeyboard(Display *d, Window w, Bool b, int i1, int i2, Time t)
}
declare 34 aqua {
declare 34 macosx {
    int XGrabPointer(Display *d, Window w1, Bool b, unsigned int ui,
	    int i1, int i2, Window w2, Cursor c, Time t)
}
declare 35 aqua {
declare 35 macosx {
    KeyCode XKeysymToKeycode(Display *d, KeySym k)
}
declare 36 aqua {
declare 36 macosx {
    int XMapWindow(Display *d, Window w)
}
declare 37 aqua {
declare 37 macosx {
    int XMoveResizeWindow(Display *d, Window w, int i1, int i2,
	    unsigned int ui1, unsigned int ui2)
}
declare 38 aqua {
declare 38 macosx {
    int XMoveWindow(Display *d, Window w, int i1, int i2)
}
declare 39 aqua {
declare 39 macosx {
    Bool XQueryPointer(Display *d, Window w1, Window *w2, Window *w3,
	    int *i1, int *i2, int *i3, int *i4, unsigned int *ui)
}
declare 40 aqua {
declare 40 macosx {
    int XRaiseWindow(Display *d, Window w)
}
declare 41 aqua {
declare 41 macosx {
    int XRefreshKeyboardMapping(XMappingEvent *x)
}
declare 42 aqua {
declare 42 macosx {
    int XResizeWindow(Display *d, Window w, unsigned int ui1,
	    unsigned int ui2)
}
declare 43 aqua {
declare 43 macosx {
    int XSelectInput(Display *d, Window w, long l)
}
declare 44 aqua {
declare 44 macosx {
    Status XSendEvent(Display *d, Window w, Bool b, long l, XEvent *x)
}
declare 45 aqua {
declare 45 macosx {
    int XSetIconName(Display *d, Window w, _Xconst char *c)
}
declare 46 aqua {
declare 46 macosx {
    int XSetInputFocus(Display *d, Window w, int i, Time t)
}
declare 47 aqua {
declare 47 macosx {
    int XSetSelectionOwner(Display *d, Atom a, Window w, Time t)
}
declare 48 aqua {
declare 48 macosx {
    int XSetWindowBackground(Display *d, Window w, unsigned long ul)
}
declare 49 aqua {
declare 49 macosx {
    int XSetWindowBackgroundPixmap(Display *d, Window w, Pixmap p)
}
declare 50 aqua {
declare 50 macosx {
    int XSetWindowBorder(Display *d, Window w, unsigned long ul)
}
declare 51 aqua {
declare 51 macosx {
    int XSetWindowBorderPixmap(Display *d, Window w, Pixmap p)
}
declare 52 aqua {
declare 52 macosx {
    int XSetWindowBorderWidth(Display *d, Window w, unsigned int ui)
}
declare 53 aqua {
declare 53 macosx {
    int XSetWindowColormap(Display *d, Window w, Colormap c)
}
declare 54 aqua {
declare 54 macosx {
    int XUngrabKeyboard(Display *d, Time t)
}
declare 55 aqua {
declare 55 macosx {
    int XUngrabPointer(Display *d, Time t)
}
declare 56 aqua {
declare 56 macosx {
    int XUnmapWindow(Display *d, Window w)
}
declare 57 aqua {
declare 57 macosx {
    int TkPutImage(unsigned long *colors, int ncolors, Display *display,
	    Drawable d, GC gc, XImage *image, int src_x, int src_y,
	    int dest_x, int dest_y, unsigned int width, unsigned int height)
}
declare 58 aqua {
declare 58 macosx {
    Status XParseColor(Display *display, Colormap map,
          _Xconst char *spec, XColor *colorPtr)
}
declare 59 aqua {
declare 59 macosx {
    GC XCreateGC(Display *display, Drawable d,
	    unsigned long valuemask, XGCValues *values)
}
declare 60 aqua {
declare 60 macosx {
    int XFreeGC(Display *display, GC gc)
}
declare 61 aqua {
declare 61 macosx {
    Atom XInternAtom(Display *display, _Xconst char *atom_name,
	    Bool only_if_exists)
}
declare 62 aqua {
declare 62 macosx {
    int XSetBackground(Display *display, GC gc, unsigned long foreground)
}
declare 63 aqua {
declare 63 macosx {
    int XSetForeground(Display *display, GC gc, unsigned long foreground)
}
declare 64 aqua {
declare 64 macosx {
    int XSetClipMask(Display *display, GC gc, Pixmap pixmap)
}
declare 65 aqua {
declare 65 macosx {
    int XSetClipOrigin(Display *display, GC gc,
	    int clip_x_origin, int clip_y_origin)
}
declare 66 aqua {
declare 66 macosx {
    int XSetTSOrigin(Display *display, GC gc,
	    int ts_x_origin, int ts_y_origin)
}
declare 67 aqua {
declare 67 macosx {
    int XChangeGC(Display *d, GC gc, unsigned long mask, XGCValues *values)
}
declare 68 aqua {
declare 68 macosx {
    int XSetFont(Display *display, GC gc, Font font)
}
declare 69 aqua {
declare 69 macosx {
    int XSetArcMode(Display *display, GC gc, int arc_mode)
}
declare 70 aqua {
declare 70 macosx {
    int XSetStipple(Display *display, GC gc, Pixmap stipple)
}
declare 71 aqua {
declare 71 macosx {
    int XSetFillRule(Display *display, GC gc, int fill_rule)
}
declare 72 aqua {
declare 72 macosx {
    int XSetFillStyle(Display *display, GC gc, int fill_style)
}
declare 73 aqua {
declare 73 macosx {
    int XSetFunction(Display *display, GC gc, int function)
}
declare 74 aqua {
declare 74 macosx {
    int XSetLineAttributes(Display *display, GC gc, unsigned int line_width,
	    int line_style, int cap_style, int join_style)
}
declare 75 aqua {
declare 75 macosx {
    int _XInitImageFuncPtrs(XImage *image)
}
declare 76 aqua {
declare 76 macosx {
    XIC XCreateIC(XIM xim, ...)
}
declare 77 aqua {
declare 77 macosx {
    XVisualInfo *XGetVisualInfo(Display *display, long vinfo_mask,
	    XVisualInfo *vinfo_template, int *nitems_return)
}
declare 78 aqua {
declare 78 macosx {
    void XSetWMClientMachine(Display *display, Window w,
	    XTextProperty *text_prop)
}
declare 79 aqua {
declare 79 macosx {
    Status XStringListToTextProperty(char **list, int count,
	    XTextProperty *text_prop_return)
}
declare 80 aqua {
declare 80 macosx {
    int XDrawSegments(Display *display, Drawable d, GC gc,
	    XSegment *segments, int nsegments)
}
declare 81 aqua {
declare 81 macosx {
    int XForceScreenSaver(Display *display, int mode)
}
declare 82 aqua {
declare 82 macosx {
    int XDrawLine(Display *d, Drawable dr, GC g, int x1, int y1,
	    int x2, int y2)
}
declare 83 aqua {
declare 83 macosx {
    int XFillRectangle(Display *display, Drawable d, GC gc,
	    int x, int y, unsigned int width, unsigned int height)
}
declare 84 aqua {
declare 84 macosx {
    int XClearWindow(Display *d, Window w)
}
declare 85 aqua {
declare 85 macosx {
    int XDrawPoint(Display *display, Drawable d, GC gc, int x, int y)
}
declare 86 aqua {
declare 86 macosx {
    int XDrawPoints(Display *display, Drawable d, GC gc, XPoint *points,
	    int npoints, int mode)
}
declare 87 aqua {
declare 87 macosx {
    int XWarpPointer(Display *display, Window src_w, Window dest_w,
	    int src_x, int src_y, unsigned int src_width,
	    unsigned int src_height, int dest_x, int dest_y)
}
declare 88 aqua {
declare 88 macosx {
    int XQueryColor(Display *display, Colormap colormap, XColor *def_in_out)
}
declare 89 aqua {
declare 89 macosx {
    int XQueryColors(Display *display, Colormap colormap,
	    XColor *defs_in_out, int ncolors)
}
declare 90 aqua {
declare 90 macosx {
    Status XQueryTree(Display *d, Window w1, Window *w2, Window *w3,
	    Window **w4, unsigned int *ui)
}
declare 91 aqua {
declare 91 macosx {
    int XSync(Display *display, Bool discard)
}
declare 92 macosx {
    Bool XTranslateCoordinates(Display *d, Window w1, Window w2, int i1,
	    int i2, int *i3, int *i4, Window *w3)
}
declare 93 macosx {
    int XDeleteProperty(Display *d, Window w, Atom a)
}
declare 94 macosx {
    int XFreeCursor(Display *d, Cursor c)
}
declare 95 macosx {
    int XGetInputFocus(Display *d, Window *w, int *i)
}
declare 96 macosx {
    int XmbLookupString(XIC xi, XKeyPressedEvent *xk, char *c, int i,
	    KeySym *k, Status *s)
}
declare 97 macosx {
    int XNextEvent(Display *d, XEvent *x)
}
declare 98 macosx {
    int XPutBackEvent(Display *d, XEvent *x)
}
declare 99 macosx {
    int XSetCommand(Display *d, Window w, char **c, int i)
}
declare 100 macosx {
    int XWindowEvent(Display *d, Window w, long l, XEvent *x)
}
declare 101 macosx {
    Status XGetWindowAttributes(Display *d, Window w, XWindowAttributes *x)
}
declare 102 macosx {
    Status XGetWMColormapWindows(Display *d, Window w, Window **wpp, int *ip)
}
declare 103 macosx {
    Status XIconifyWindow(Display *d, Window w, int i)
}
declare 104 macosx {
    Status XWithdrawWindow(Display *d, Window w, int i)
}
declare 105 macosx {
    XHostAddress *XListHosts(Display *d, int *i, Bool *b)
}
declare 106 macosx {
    int XSetClipRectangles(Display *display, GC gc, int clip_x_origin,
       int clip_y_origin, XRectangle rectangles[], int n, int ordering)
}
declare 107 aqua {
declare 107 macosx {
    int XFlush(Display *display)
}
declare 108 aqua {
declare 108 macosx {
    int XGrabServer(Display *display)
}
declare 109 aqua {
declare 109 macosx {
    int XUngrabServer(Display *display)
}
declare 110 aqua {
declare 110 macosx {
    int XFree(void *data)
}
declare 111 aqua {
declare 111 macosx {
    int XNoOp(Display *display)
}
declare 112 aqua {
declare 112 macosx {
    XAfterFunction XSynchronize(Display *display, Bool onoff)
}
declare 113 macosx {
    Status XLookupColor(Display *d, Colormap c1, _Xconst char *c2,
	    XColor *x1, XColor *x2)
}
declare 114 aqua {
declare 114 macosx {
    VisualID XVisualIDFromVisual(Visual *visual)
}
declare 120 macosx {
    int XOffsetRegion(Region rgn, int dx, int dy)
}
declare 121 macosx {
    int XUnionRegion(Region srca, Region srcb, Region dr_return)
}
declare 122 macosx {
    Window XCreateWindow(Display *display, Window parent, int x, int y,
	    unsigned int width, unsigned int height,
	    unsigned int border_width, int depth, unsigned int clazz,
	    Visual *visual, unsigned long value_mask,
	    XSetWindowAttributes *attributes)
}
declare 129 macosx {
    int XLowerWindow(Display *d, Window w)
}
declare 130 macosx {
    int XFillArcs(Display *d, Drawable dr, GC gc, XArc *a, int n)
}
declare 131 macosx {
    int XDrawArcs(Display *d, Drawable dr, GC gc, XArc *a, int n)
}
declare 132 macosx {
    int XDrawRectangles(Display *d, Drawable dr, GC gc, XRectangle *r, int n)
}
declare 136 macosx {
    int XReparentWindow(Display *d, Window w, Window p, int x, int y)
}
declare 137 aqua {
declare 137 macosx {
    int XPutImage(Display *d, Drawable dr, GC gc, XImage *im,
	    int sx, int sy, int dx, int dy,
	    unsigned int w, unsigned int h)
}
declare 138 macosx {
    Region XPolygonRegion(XPoint *pts, int n, int rule)

}
declare 139 macosx {
    int XPointInRegion(Region rgn, int x, int y)
}
declare 140 macosx {
    XVaNestedList XVaCreateNestedList(int dummy, ...)
}
declare 141 macosx {
    char *XSetICValues(XIC xic, ...)
}
declare 142 macosx {
    char *XGetICValues(XIC xic, ...)
}
declare 143 macosx {
    void XSetICFocus(XIC xic)
}
declare 144 macosx {
    void XDestroyIC(XIC xic)
}
declare 145 macosx {
    Cursor XCreatePixmapCursor(Display *d, Pixmap p1, Pixmap p2,
	    XColor *x1, XColor *x2, unsigned int ui1, unsigned int ui2)
}
declare 146 macosx {
    Cursor XCreateGlyphCursor(Display *d, Font f1, Font f2,
	    unsigned int ui1, unsigned int ui2, XColor _Xconst *x1,
	    XColor _Xconst *x2)
}
declare 147 macosx {
    void XFreeFontSet(Display *display, XFontSet fontset)
}
declare 148 macosx {
    int XCloseIM(XIM im)
}
declare 149 macosx {
    Bool XRegisterIMInstantiateCallback(Display *dpy, struct _XrmHashBucketRec *rbd,
	    char *res_name, char *res_class, XIDProc callback, XPointer client_data)
}
declare 150 macosx {
    Bool XUnregisterIMInstantiateCallback(Display *dpy, struct _XrmHashBucketRec *rbd,
	    char *res_name, char *res_class, XIDProc callback, XPointer client_data)
}
declare 151 macosx {
    char *XSetLocaleModifiers(const char *modifier_list)
}
declare 152 macosx {
    XIM XOpenIM(Display *dpy, struct _XrmHashBucketRec *rdb, char *res_name,
	    char *res_class)
}
declare 153 macosx {
    char *XGetIMValues(XIM im, ...)
}
declare 154 macosx {
    char *XSetIMValues(XIM im, ...)
}
declare 155 macosx {
    XFontSet XCreateFontSet(Display *display, _Xconst char *base_font_name_list,
	    char ***missing_charset_list, int *missing_charset_count, char **def_string)
}
declare 156 macosx {
    void XFreeStringList(char **list)
}
declare 157 macosx {
    KeySym XkbKeycodeToKeysym(Display *d, unsigned int k, int g, int i)
}
declare 158 macosx {
    Display *XkbOpenDisplay(const char *name, int *ev_rtrn, int *err_rtrn,
	    int *major_rtrn, int *minor_rtrn, int *reason)
}

# Local Variables:
# mode: tcl
# End:
Changes to generic/tkInt.h.
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

28
29
30
31
32
33
34








-
+


















-







/*
 * tkInt.h --
 *
 *	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.
 */

#ifndef _TKINT
#define _TKINT

#ifndef _TKPORT
#include "tkPort.h"
#endif

/*
 * Ensure WORDS_BIGENDIAN is defined correctly:
 * Needs to happen here in addition to configure to work with fat compiles on
 * Darwin (where configure runs only once for multiple architectures).
 */

#include <stdio.h>
#ifdef HAVE_SYS_TYPES_H
#    include <sys/types.h>
#endif
#ifdef HAVE_SYS_PARAM_H
#    include <sys/param.h>
#endif
#ifdef BYTE_ORDER
55
56
57
58
59
60
61








































62
63
64
65
66
67
68
69
70
71

72
73
74

75
76
77
78
79
80

81
82
83

84
85
86
87
88
89
90
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109

110
111
112

113
114
115
116
117
118

119
120
121

122
123
124
125
126
127
128
129







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+









-
+


-
+





-
+


-
+







#   ifdef __cplusplus
#	define MODULE_SCOPE extern "C"
#   else
#	define MODULE_SCOPE extern
#   endif
#endif

#ifndef JOIN
#  define JOIN(a,b) JOIN1(a,b)
#  define JOIN1(a,b) a##b
#endif

#ifndef TCL_UNUSED
#   if defined(__cplusplus)
#	define TCL_UNUSED(T) T
#   elif defined(__GNUC__) && (__GNUC__ > 2)
#	define TCL_UNUSED(T) T JOIN(dummy, __LINE__) __attribute__((unused))
#   else
#	define TCL_UNUSED(T) T JOIN(dummy, __LINE__)
#   endif
#endif

#ifndef TkSizeT
#   if TCL_MAJOR_VERSION > 8
#	define TkSizeT size_t
#   else
#	define TkSizeT int
#   endif
#endif

#if (TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION < 7)
# define Tcl_WCharToUtfDString ((char * (*)(const WCHAR *, int len, Tcl_DString *))Tcl_UniCharToUtfDString)
# define Tcl_UtfToWCharDString ((WCHAR * (*)(const char *, int len, Tcl_DString *))Tcl_UtfToUniCharDString)
# define Tcl_Char16ToUtfDString Tcl_UniCharToUtfDString
# define Tcl_UtfToChar16DString Tcl_UtfToUniCharDString
#endif

#if defined(__GNUC__) && (__GNUC__ > 2)
#   define TKFLEXARRAY 0
#else
#   define TKFLEXARRAY 1
#endif

#if !defined(Tcl_GetParent) && (TCL_MAJOR_VERSION < 9) && (TCL_MINOR_VERSION < 7)
#   define Tcl_GetParent Tcl_GetMaster
#endif

/*
 * Macros used to cast between pointers and integers (e.g. when storing an int
 * in ClientData), on 64-bit architectures they avoid gcc warning about "cast
 * to/from pointer from/to integer of different size".
 */

#if !defined(INT2PTR) && !defined(PTR2INT)
#   if defined(HAVE_INTPTR_T) || defined(intptr_t)
#	define INT2PTR(p) ((void*)(intptr_t)(p))
#	define PTR2INT(p) ((int)(intptr_t)(p))
#	define PTR2INT(p) ((intptr_t)(p))
#   else
#	define INT2PTR(p) ((void*)(p))
#	define PTR2INT(p) ((int)(p))
#	define PTR2INT(p) ((long)(p))
#   endif
#endif
#if !defined(UINT2PTR) && !defined(PTR2UINT)
#   if defined(HAVE_UINTPTR_T) || defined(uintptr_t)
#	define UINT2PTR(p) ((void*)(uintptr_t)(p))
#	define PTR2UINT(p) ((unsigned int)(uintptr_t)(p))
#	define PTR2UINT(p) ((uintptr_t)(p))
#   else
#	define UINT2PTR(p) ((void*)(p))
#	define PTR2UINT(p) ((unsigned int)(p))
#	define PTR2UINT(p) ((unsigned long)(p))
#   endif
#endif

#ifndef TCL_Z_MODIFIER
#   if defined(_WIN64)
#	define TCL_Z_MODIFIER	"I"
#   elif defined(__GNUC__) && !defined(_WIN32)
98
99
100
101
102
103
104
105

106
107
108
109
110
111
112
113
114
115
116
117
118
119
120

121
122
123
124
125
126
127
128
129

130
131
132
133
134
135
136
137
138
139
140
141
142
143

144
145
146
147
148
149
150
151
152
153
154
155
156
157
158

159
160
161
162
163
164
165
166
167

168
169
170
171
172
173
174
175







-
+














-
+








-
+







 * Opaque type declarations:
 */

typedef struct TkColormap TkColormap;
typedef struct TkFontAttributes TkFontAttributes;
typedef struct TkGrabEvent TkGrabEvent;
typedef struct TkpCursor_ *TkpCursor;
typedef struct TkRegion_ *TkRegion;
#define TkRegion Region
typedef struct TkStressedCmap TkStressedCmap;
typedef struct TkBindInfo_ *TkBindInfo;
typedef struct Busy *TkBusy;

/*
 * One of the following structures is maintained for each cursor in use in the
 * system. This structure is used by tkCursor.c and the various system-
 * specific cursor files.
 */

typedef struct TkCursor {
    Tk_Cursor cursor;		/* System specific identifier for cursor. */
    Display *display;		/* Display containing cursor. Needed for
				 * disposal and retrieval of cursors. */
    int resourceRefCount;	/* Number of active uses of this cursor (each
    TkSizeT resourceRefCount;	/* Number of active uses of this cursor (each
				 * active use corresponds to a call to
				 * Tk_AllocPreserveFromObj or Tk_Preserve). If
				 * this count is 0, then this structure is no
				 * longer valid and it isn't present in a hash
				 * table: it is being kept around only because
				 * there are objects referring to it. The
				 * structure is freed when resourceRefCount
				 * and objRefCount are both 0. */
    int objRefCount;		/* Number of Tcl objects that reference this
    TkSizeT objRefCount;		/* Number of Tcl objects that reference this
				 * structure.. */
    Tcl_HashTable *otherTable;	/* Second table (other than idTable) used to
				 * index this entry. */
    Tcl_HashEntry *hashPtr;	/* Entry in otherTable for this structure
				 * (needed when deleting). */
    Tcl_HashEntry *idHashPtr;	/* Entry in idTable for this structure (needed
				 * when deleting). */
156
157
158
159
160
161
162


163
164
165
166
167
168
169
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210







+
+







} TkCaret;

/*
 * One of the following structures is maintained for each display containing a
 * window managed by Tk. In part, the structure is used to store thread-
 * specific data, since each thread will have its own TkDisplay structure.
 */

typedef enum TkLockUsage {LU_IGNORE, LU_CAPS, LU_SHIFT} TkLockUsage;

typedef struct TkDisplay {
    Display *display;		/* Xlib's info about display. */
    struct TkDisplay *nextPtr;	/* Next in list of all displays. */
    char *name;			/* Name of display (with any screen identifier
				 * removed). Malloc-ed. */
    Time lastEventTime;		/* Time of last event received for this
198
199
200
201
202
203
204
205

206
207
208
209
210
211
212
239
240
241
242
243
244
245

246
247
248
249
250
251
252
253







-
+







				 * modifier, than this is zero. */
    unsigned int metaModMask;	/* Has one bit set to indicate the modifier
				 * corresponding to the "Meta" key. If no such
				 * modifier, then this is zero. */
    unsigned int altModMask;	/* Has one bit set to indicate the modifier
				 * corresponding to the "Meta" key. If no such
				 * modifier, then this is zero. */
    enum {LU_IGNORE, LU_CAPS, LU_SHIFT} lockUsage;
    TkLockUsage lockUsage;
				/* Indicates how to interpret lock
				 * modifier. */
    int numModKeyCodes;		/* Number of entries in modKeyCodes array
				 * below. */
    KeyCode *modKeyCodes;	/* Pointer to an array giving keycodes for all
				 * of the keys that have modifiers associated
				 * with them. Malloc'ed, but may be NULL. */
272
273
274
275
276
277
278
279

280
281
282
283
284
285
286
313
314
315
316
317
318
319

320
321
322
323
324
325
326
327







-
+







     * Information used by tkError.c only:
     */

    struct TkErrorHandler *errorPtr;
				/* First in list of error handlers for this
				 * display. NULL means no handlers exist at
				 * present. */
    int deleteCount;		/* Counts # of handlers deleted since last
    TkSizeT deleteCount;		/* Counts # of handlers deleted since last
				 * time inactive handlers were garbage-
				 * collected. When this number gets big,
				 * handlers get cleaned up. */

    /*
     * Used by tkEvent.c only:
     */
324
325
326
327
328
329
330
331
332
333



334
335
336

337
338
339
340
341
342
343
365
366
367
368
369
370
371



372
373
374
375
376

377
378
379
380
381
382
383
384







-
-
-
+
+
+


-
+







				 * initializing. */

    /*
     * Information used by tkGeometry.c only:
     */

    Tcl_HashTable maintainHashTable;
				/* Hash table that maps from a master's
				 * Tk_Window token to a list of slaves managed
				 * by that master. */
				/* Hash table that maps from a container's
				 * Tk_Window token to a list of windows managed
				 * by that container. */
    int geomInit;

#define TkGetGeomMaster(tkwin) (((TkWindow *)tkwin)->maintainerPtr != NULL ? \
#define TkGetContainer(tkwin) (((TkWindow *)tkwin)->maintainerPtr != NULL ? \
    ((TkWindow *)tkwin)->maintainerPtr : ((TkWindow *)tkwin)->parentPtr)

    /*
     * Information used by tkGet.c only:
     */

    Tcl_HashTable uidTable;	/* Stores all Tk_Uid used in a thread. */
407
408
409
410
411
412
413
414

415
416

417
418
419
420
421
422
423
448
449
450
451
452
453
454

455
456

457
458
459
460
461
462
463
464







-
+

-
+







				 * Packer structures. */

    /*
     * Information used by tkPlace.c only.
     */

    int placeInit;		/* 0 means tables below need initializing. */
    Tcl_HashTable masterTable;	/* Maps from Tk_Window toke to the Master
    Tcl_HashTable containerTable;	/* Maps from Tk_Window token to the Container
				 * structure for the window, if it exists. */
    Tcl_HashTable slaveTable;	/* Maps from Tk_Window toke to the Slave
    Tcl_HashTable contentTable;	/* Maps from Tk_Window token to the Content
				 * structure for the window, if it exists. */

    /*
     * Information used by tkSelect.c and tkClipboard.c only:
     */

    struct TkSelectionInfo *selectionInfoPtr;
481
482
483
484
485
486
487
488

489
490
491
492
493
494
495

496
497
498
499
500
501
502
503


504
505
506
507





508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526




527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
522
523
524
525
526
527
528

529
530
531
532
533
534
535

536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572

573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588


589
590
591
592
593


594
595
596
597
598
599
600







-
+






-
+








+
+




+
+
+
+
+

















-

+
+
+
+











-
-





-
-







    TkColormap *cmapPtr;	/* First in list of all non-default colormaps
				 * allocated for this display. */

    /*
     * Miscellaneous information:
     */

#ifdef TK_USE_INPUT_METHODS
#if defined(TK_USE_INPUT_METHODS) || (TCL_MAJOR_VERSION > 8)
    XIM inputMethod;		/* Input method for this display. */
    XIMStyle inputStyle;	/* Input style selected for this display. */
    XFontSet inputXfs;		/* XFontSet cached for over-the-spot XIM. */
#endif /* TK_USE_INPUT_METHODS */
    Tcl_HashTable winTable;	/* Maps from X window ids to TkWindow ptrs. */

    int refCount;		/* Reference count of how many Tk applications
    TkSizeT refCount;		/* Reference count of how many Tk applications
				 * are using this display. Used to clean up
				 * the display when we no longer have any Tk
				 * applications using it. */

    /*
     * The following field were all added for Tk8.3
     */

#if TCL_MAJOR_VERSION < 9
#if !defined(TK_NO_DEPRECATED)
    int mouseButtonState;	/* Current mouse button state for this
				 * display. NOT USED as of 8.6.10 */
    Window mouseButtonWindow;	/* Window the button state was set in, added
				 * in Tk 8.4. */
#else
    int notused1;
    XID notused2;
#endif /* !TK_NO_DEPRECATED */
#endif
    Tk_Window warpWindow;
    Tk_Window warpMainwin;	/* For finding the root window for warping
				 * purposes. */
    int warpX;
    int warpY;

    /*
     * The following field(s) were all added for Tk8.4
     */

    unsigned int flags;		/* Various flag values: these are all defined
				 * in below. */
    TkCaret caret;		/* Information about the caret for this
				 * display. This is not a pointer. */

    int iconDataSize;		/* Size of default iconphoto image data. */
    unsigned char *iconDataPtr;	/* Default iconphoto image data, if set. */
#ifdef TK_USE_INPUT_METHODS
    int ximGeneration;          /* Used to invalidate XIC */
#if !defined(TK_USE_INPUT_METHODS) && (TCL_MAJOR_VERSION < 9)
    XIM inputMethod;		/* Input method for this display. */
    XIMStyle inputStyle;	/* Input style selected for this display. */
    XFontSet inputXfs;		/* XFontSet cached for over-the-spot XIM. */
#endif /* TK_USE_INPUT_METHODS */
} TkDisplay;

/*
 * Flag values for TkDisplay flags.
 *  TK_DISPLAY_COLLAPSE_MOTION_EVENTS:	(default on)
 *	Indicates that we should collapse motion events on this display
 *  TK_DISPLAY_USE_IM:			(default on, set via tk.tcl)
 *	Whether to use input methods for this display
 *  TK_DISPLAY_WM_TRACING:		(default off)
 *	Whether we should do wm tracing on this display.
 *  TK_DISPLAY_IN_WARP:			(default off)
 *	Indicates that we are in a pointer warp
 */

#define TK_DISPLAY_COLLAPSE_MOTION_EVENTS	(1 << 0)
#define TK_DISPLAY_USE_IM			(1 << 1)
#define TK_DISPLAY_WM_TRACING			(1 << 3)
#define TK_DISPLAY_IN_WARP			(1 << 4)
#define TK_DISPLAY_USE_XKB			(1 << 5)

/*
 * One of the following structures exists for each error handler created by a
 * call to Tk_CreateErrorHandler. The structure is managed by tkError.c.
 */

typedef struct TkErrorHandler {
592
593
594
595
596
597
598
599

600
601
602
603
604
605
606
607
608
609

610




611
612
613
614
615
616
617
639
640
641
642
643
644
645

646
647
648
649
650
651
652
653
654
655
656
657

658
659
660
661
662
663
664
665
666
667
668







-
+










+
-
+
+
+
+







/*
 * Tk keeps one of the following data structures for each main window (created
 * by a call to TkCreateMainWindow). It stores information that is shared by
 * all of the windows associated with a particular main window.
 */

typedef struct TkMainInfo {
    int refCount;		/* Number of windows whose "mainPtr" fields
    TkSizeT refCount;		/* Number of windows whose "mainPtr" fields
				 * point here. When this becomes zero, can
				 * free up the structure (the reference count
				 * is zero because windows can get deleted in
				 * almost any order; the main window isn't
				 * necessarily the last one deleted). */
    struct TkWindow *winPtr;	/* Pointer to main window. */
    Tcl_Interp *interp;		/* Interpreter associated with application. */
    Tcl_HashTable nameTable;	/* Hash table mapping path names to TkWindow
				 * structs for all windows related to this
				 * main window. Managed by tkWindow.c. */
#if TCL_MAJOR_VERSION > 8
    long deletionEpoch;		/* Incremented by window deletions. */
    size_t deletionEpoch;		/* Incremented by window deletions. */
#else
    long deletionEpoch;
#endif
    Tk_BindingTable bindingTable;
				/* Used in conjunction with "bind" command to
				 * bind events to Tcl commands. */
    TkBindInfo bindInfo;	/* Information used by tkBind.c on a per
				 * application basis. */
    struct TkFontInfo *fontInfoPtr;
				/* Information used by tkFont.c on a per
631
632
633
634
635
636
637
638

639
640
641
642
643
644
645
682
683
684
685
686
687
688

689
690
691
692
693
694
695
696







-
+







				 * application has ever used. Used only by
				 * tkFocus.c. */

    struct ElArray *optionRootPtr;
				/* Top level of option hierarchy for this main
				 * window. NULL means uninitialized. Managed
				 * by tkOption.c. */
    Tcl_HashTable imageTable;	/* Maps from image names to Tk_ImageMaster
    Tcl_HashTable imageTable;	/* Maps from image names to Tk_ImageModel
				 * structures. Managed by tkImage.c. */
    int strictMotif;		/* This is linked to the tk_strictMotif global
				 * variable. */
    int alwaysShowSelection;	/* This is linked to the
				 * ::tk::AlwaysShowSelection variable. */
    struct TkMainInfo *nextPtr;	/* Next in list of all main windows managed by
				 * this process. */
678
679
680
681
682
683
684
685

686
687
688
689
690
691
692
729
730
731
732
733
734
735

736
737
738
739
740
741
742
743







-
+







    TkDisplay *dispPtr;		/* Tk's information about display for
				 * window. */
    int screenNum;		/* Index of screen for window, among all those
				 * for dispPtr. */
    Visual *visual;		/* Visual to use for window. If not default,
				 * MUST be set before X window is created. */
    int depth;			/* Number of bits/pixel. */
    Window window;		/* X's id for window. NULL means window hasn't
    Window window;		/* X's id for window. None means window hasn't
				 * actually been created yet, or it's been
				 * deleted. */
    struct TkWindow *childList;	/* First in list of child windows, or NULL if
				 * no children. List is in stacking order,
				 * lowest window first.*/
    struct TkWindow *lastChildPtr;
				/* Last in list of child windows (highest in
740
741
742
743
744
745
746
747

748
749
750
751
752
753
754
791
792
793
794
795
796
797

798
799
800
801
802
803
804
805







-
+








    /*
     * Information kept by the event manager (tkEvent.c):
     */

    TkEventHandler *handlerList;/* First in list of event handlers declared
				 * for this window, or NULL if none. */
#ifdef TK_USE_INPUT_METHODS
#if defined(TK_USE_INPUT_METHODS) || (TCL_MAJOR_VERSION > 8)
    XIC inputContext;		/* XIM input context. */
#endif /* TK_USE_INPUT_METHODS */

    /*
     * Information used for event bindings (see "bind" and "bindtags" commands
     * in tkCmds.c):
     */
821
822
823
824
825
826
827
828

829
830
831
832
833
834
835







836
837
838
839
840
841
842
843
844





845
846
847
848
849
850

851
852
853

854
855
856
857
858
859
860
861
862









863
864
865
866
867
868
869
872
873
874
875
876
877
878

879
880
881
882
883



884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909

910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939







-
+




-
-
-
+
+
+
+
+
+
+









+
+
+
+
+





-
+



+









+
+
+
+
+
+
+
+
+







    /* The remaining fields of internal border. */
    int internalBorderRight;
    int internalBorderTop;
    int internalBorderBottom;

    int minReqWidth;		/* Minimum requested width. */
    int minReqHeight;		/* Minimum requested height. */
#ifdef TK_USE_INPUT_METHODS
#if defined(TK_USE_INPUT_METHODS) || (TCL_MAJOR_VERSION > 8)
    int ximGeneration;          /* Used to invalidate XIC */
#endif /* TK_USE_INPUT_METHODS */
    char *geomMgrName;          /* Records the name of the geometry manager. */
    struct TkWindow *maintainerPtr;
				/* The geometry master for this window. The
				 * value is NULL if the window has no master or
				 * if its master is its parent. */
				/* The geometry container for this window. The
				 * value is NULL if the window has no container or
				 * if its container is its parent. */
#if !defined(TK_USE_INPUT_METHODS) && (TCL_MAJOR_VERSION < 9)
    XIC inputContext;		/* XIM input context. */
    int ximGeneration;          /* Used to invalidate XIC */
#endif /* TK_USE_INPUT_METHODS */
} TkWindow;

/*
 * Real definition of some events. Note that these events come from outside
 * but have internally generated pieces added to them.
 */

typedef struct {
    XKeyEvent keyEvent;		/* The real event from X11. */
#ifdef _WIN32
    char trans_chars[XMaxTransChars];
                            /* translated characters */
    unsigned char nbytes;
#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(). */
    int charValueLen;		/* Length of string in charValuePtr when that
    TkSizeT charValueLen;	/* Length of string in charValuePtr when that
				 * is non-NULL. */
    KeySym keysym;		/* Key symbol computed after input methods
				 * have been invoked */
#endif
} TkKeyEvent;

/*
 * Flags passed to TkpMakeMenuWindow's 'transient' argument.
 */

#define TK_MAKE_MENU_TEAROFF	0	/* Only non-transient case. */
#define TK_MAKE_MENU_POPUP	1
#define TK_MAKE_MENU_DROPDOWN	2

/* See TIP #494 */
#ifndef TCL_IO_FAILURE
#   define TCL_IO_FAILURE (-1)
#endif
/* See TIP #537 */
#ifndef TCL_INDEX_NONE
#   define TCL_INDEX_NONE (-1)
#endif

/*
 * The following structure is used with TkMakeEnsemble to create ensemble
 * commands and optionally to create sub-ensembles.
 */

typedef struct TkEnsemble {
888
889
890
891
892
893
894
895

896
897
898
899
900
901
902
958
959
960
961
962
963
964

965
966
967
968
969
970
971
972







-
+







 * representation of a clip_mask in a GC.
 */

typedef struct TkpClipMask {
    int type;			/* TKP_CLIP_PIXMAP or TKP_CLIP_REGION. */
    union {
	Pixmap pixmap;
	TkRegion region;
	Region region;
    } value;
} TkpClipMask;

#define TKP_CLIP_PIXMAP 0
#define TKP_CLIP_REGION 1

/*
937
938
939
940
941
942
943

























944
945
946
947
948
949
950
951


952
953
954
955
956
957
958
959
960
961
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044


1045
1046
1047

1048
1049
1050
1051
1052
1053
1054
1055







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






-
-
+
+

-








 * bits.
 */

#define META_MASK	(AnyModifier<<1)
#define ALT_MASK	(AnyModifier<<2)
#define EXTENDED_MASK	(AnyModifier<<3)

/*
 * Buttons 8 and 9 are the Xbuttons (left and right side-buttons). On Windows/Mac, those
 * are known as Buttons 4 and 5. At script level, they also get the numbers 4 and 5.
 */

#ifndef Button8
# define Button8 8
#endif
#ifndef Button9
# define Button9 9
#endif

#ifndef Button6Mask
# define Button6Mask (1<<13)
#endif
#ifndef Button7Mask
# define Button7Mask (1<<14)
#endif
#ifndef Button8Mask
# define Button8Mask (AnyModifier<<4)
#endif
#ifndef Button9Mask
# define Button9Mask (AnyModifier<<5)
#endif

/*
 * Mask that selects any of the state bits corresponding to buttons, plus
 * masks that select individual buttons' bits:
 */

#define ALL_BUTTONS \
	(Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask)

	(Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask \
		|Button6Mask|Button7Mask|Button8Mask|Button9Mask)

MODULE_SCOPE unsigned long TkGetButtonMask(unsigned int);

/*
 * Object types not declared in tkObj.c need to be mentioned here so they can
 * be properly registered with Tcl:
 */

MODULE_SCOPE const Tcl_ObjType tkBorderObjType;
MODULE_SCOPE const Tcl_ObjType tkBitmapObjType;
970
971
972
973
974
975
976

977
978

979
980
981
982
983
984
985
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081







+


+







 * outside world:
 */

MODULE_SCOPE const Tk_SmoothMethod tkBezierSmoothMethod;
MODULE_SCOPE Tk_ImageType	tkBitmapImageType;
MODULE_SCOPE Tk_PhotoImageFormat tkImgFmtGIF;
MODULE_SCOPE void		(*tkHandleEventProc) (XEvent* eventPtr);
MODULE_SCOPE Tk_PhotoImageFormat tkImgFmtDefault;
MODULE_SCOPE Tk_PhotoImageFormat 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;

MODULE_SCOPE const char *const tkWebColors[20];

/*
1020
1021
1022
1023
1024
1025
1026




1027
1028
1029
1030
1031
1032
1033
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133







+
+
+
+







#define GENERATED_FOCUS_EVENT_MAGIC	((Bool) 0x547321ac)

/*
 * Exported internals.
 */

#include "tkIntDecls.h"

#ifdef __cplusplus
extern "C" {
#endif

/*
 * Themed widget set init function:
 */

MODULE_SCOPE int	Ttk_Init(Tcl_Interp *interp);

1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186




1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199









1200
1201
1202
1203
1204
1205
1206
1207
1208

1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223




1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234



1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252



1253
1254
1255
1256
1257






1258
1259
1260
1261
1262
1263
1264
1265






















1266
1267

1268
1269
1270
1271
1272
1273
1274
1275
1276



1277
1278
1279














1280
1281
1282
1283
1284
1285
1286
1273
1274
1275
1276
1277
1278
1279







1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313

1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324

1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342

1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354


1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365

1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405

1406
1407
1408
1409
1410
1411
1412
1413


1414
1415
1416
1417


1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438







-
-
-
-
-
-
-
+
+
+
+













+
+
+
+
+
+
+
+
+








-
+










-




+
+
+
+










-
+
+
+









-
-







+
+
+

-



+
+
+
+
+
+








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+







-
-
+
+
+

-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+







			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tk_WinfoObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tk_WmObjCmd(ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);

MODULE_SCOPE int	Tk_GetDoublePixelsFromObj(Tcl_Interp *interp,
			    Tk_Window tkwin, Tcl_Obj *objPtr,
			    double *doublePtr);
MODULE_SCOPE int	TkSetGeometryMaster(Tcl_Interp *interp,
			    Tk_Window tkwin, const char *master);
MODULE_SCOPE void	TkFreeGeometryMaster(Tk_Window tkwin,
			    const char *master);
MODULE_SCOPE int	TkSetGeometryContainer(Tcl_Interp *interp,
			    Tk_Window tkwin, const char *name);
MODULE_SCOPE void	TkFreeGeometryContainer(Tk_Window tkwin,
			    const char *name);

MODULE_SCOPE void	TkEventInit(void);
MODULE_SCOPE void	TkRegisterObjTypes(void);
MODULE_SCOPE int	TkDeadAppObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc, Tcl_Obj *const argv[]);
MODULE_SCOPE int	TkCanvasGetCoordObj(Tcl_Interp *interp,
			    Tk_Canvas canvas, Tcl_Obj *obj,
			    double *doublePtr);
MODULE_SCOPE int	TkGetDoublePixels(Tcl_Interp *interp, Tk_Window tkwin,
			    const char *string, double *doublePtr);
MODULE_SCOPE int	TkPostscriptImage(Tcl_Interp *interp, Tk_Window tkwin,
			    Tk_PostscriptInfo psInfo, XImage *ximage,
			    int x, int y, int width, int height);
#if TCL_MAJOR_VERSION > 8
MODULE_SCOPE int TkCanvasTagsParseProc(ClientData clientData, Tcl_Interp *interp,
    Tk_Window tkwin, const char *value, char *widgRec, size_t offset);
MODULE_SCOPE const char *TkCanvasTagsPrintProc(ClientData clientData, Tk_Window tkwin,
    char *widgRec, size_t offset, Tcl_FreeProc **freeProcPtr);
#else
#define TkCanvasTagsParseProc Tk_CanvasTagsParseProc
#define TkCanvasTagsPrintProc Tk_CanvasTagsPrintProc
#endif
MODULE_SCOPE void       TkMapTopFrame(Tk_Window tkwin);
MODULE_SCOPE XEvent *	TkpGetBindingXEvent(Tcl_Interp *interp);
MODULE_SCOPE void	TkCreateExitHandler(Tcl_ExitProc *proc,
			    ClientData clientData);
MODULE_SCOPE void	TkDeleteExitHandler(Tcl_ExitProc *proc,
			    ClientData clientData);
MODULE_SCOPE Tcl_ExitProc	TkFinalize;
MODULE_SCOPE Tcl_ExitProc	TkFinalizeThread;
MODULE_SCOPE void	TkpBuildRegionFromAlphaData(TkRegion region,
MODULE_SCOPE void	TkpBuildRegionFromAlphaData(Region region,
			    unsigned x, unsigned y, unsigned width,
			    unsigned height, unsigned char *dataPtr,
			    unsigned pixelStride, unsigned lineStride);
MODULE_SCOPE void	TkAppendPadAmount(Tcl_Obj *bufferObj,
			    const char *buffer, int pad1, int pad2);
MODULE_SCOPE int	TkParsePadAmount(Tcl_Interp *interp,
			    Tk_Window tkwin, Tcl_Obj *objPtr,
			    int *pad1Ptr, int *pad2Ptr);
MODULE_SCOPE void       TkFocusSplit(TkWindow *winPtr);
MODULE_SCOPE void       TkFocusJoin(TkWindow *winPtr);
MODULE_SCOPE int	TkpAlwaysShowSelection(Tk_Window tkwin);
MODULE_SCOPE void	TkpDrawCharsInContext(Display * display,
			    Drawable drawable, GC gc, Tk_Font tkfont,
			    const char *source, int numBytes, int rangeStart,
			    int rangeLength, int x, int y);
MODULE_SCOPE void	TkpDrawAngledCharsInContext(Display * display,
			    Drawable drawable, GC gc, Tk_Font tkfont,
			    const char *source, int numBytes, int rangeStart,
			    int rangeLength, double x, double y, double angle);
MODULE_SCOPE int	TkpMeasureCharsInContext(Tk_Font tkfont,
			    const char *source, int numBytes, int rangeStart,
			    int rangeLength, int maxLength, int flags,
			    int *lengthPtr);
MODULE_SCOPE void	TkUnderlineCharsInContext(Display *display,
			    Drawable drawable, GC gc, Tk_Font tkfont,
			    const char *string, int numBytes, int x, int y,
			    int firstByte, int lastByte);
MODULE_SCOPE void	TkpGetFontAttrsForChar(Tk_Window tkwin, Tk_Font tkfont,
			    int c, struct TkFontAttributes *faPtr);
MODULE_SCOPE Tcl_Obj *	TkNewWindowObj(Tk_Window tkwin);
MODULE_SCOPE void	TkpDrawFrameEx(Tk_Window tkwin, Drawable drawable,
			    Tk_3DBorder border, int highlightWidth,
			    int borderWidth, int relief);
MODULE_SCOPE void	TkpShowBusyWindow(TkBusy busy);
MODULE_SCOPE void	TkpHideBusyWindow(TkBusy busy);
MODULE_SCOPE void	TkpMakeTransparentWindowExist(Tk_Window tkwin,
			    Window parent);
MODULE_SCOPE void	TkpCreateBusy(Tk_FakeWin *winPtr, Tk_Window tkRef,
			    Window *parentPtr, Tk_Window tkParent,
			    TkBusy busy);
MODULE_SCOPE int	TkBackgroundEvalObjv(Tcl_Interp *interp,
			    int objc, Tcl_Obj *const *objv, int flags);
MODULE_SCOPE void	TkSendVirtualEvent(Tk_Window tgtWin,
			    const char *eventName, Tcl_Obj *detail);
MODULE_SCOPE Tcl_Command TkMakeEnsemble(Tcl_Interp *interp,
			    const char *nsname, const char *name,
			    ClientData clientData, const TkEnsemble *map);
MODULE_SCOPE int	TkInitTkCmd(Tcl_Interp *interp,
			    ClientData clientData);
MODULE_SCOPE int	TkInitFontchooser(Tcl_Interp *interp,
			    ClientData clientData);
MODULE_SCOPE void	TkInitEmbeddedConfigurationInformation(
			    Tcl_Interp *interp);
MODULE_SCOPE void	TkDoWarpWrtWin(TkDisplay *dispPtr);
MODULE_SCOPE void	TkpWarpPointer(TkDisplay *dispPtr);
MODULE_SCOPE void	TkpCancelWarp(TkDisplay *dispPtr);
MODULE_SCOPE int	TkListCreateFrame(ClientData clientData,
			    Tcl_Interp *interp, Tcl_Obj *listObj,
			    int toplevel, Tcl_Obj *nameObj);
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)

#ifdef _WIN32
#define TkParseColor XParseColor
#else
MODULE_SCOPE Status TkParseColor (Display * display,
				Colormap map, const char* spec,
				XColor * colorPtr);
#endif
#if !defined(_WIN32) && !defined(__CYGWIN__) /* UNIX and MacOSX */
#undef TkPutImage
#define TkPutImage(colors, ncolors, display, pixels, gc, image, srcx, srcy, destx, desty, width, height) \
	XPutImage(display, pixels, gc, image, srcx, srcy, destx, desty, width, height);
#else
#undef XPutImage
#define XPutImage(display, pixels, gc, image, srcx, srcy, destx, desty, width, height) \
	TkPutImage(NULL, 0, display, pixels, gc, image, srcx, srcy, destx, desty, width, height);
#endif

/*
 * These macros are just wrappers for the equivalent X Region calls.
 */
#define TkClipBox XClipBox
#define TkCreateRegion XCreateRegion
#define TkDestroyRegion XDestroyRegion
#define TkIntersectRegion XIntersectRegion
#define TkRectInRegion XRectInRegion
#define TkSetRegion XSetRegion
#define TkSubtractRegion XSubtractRegion
#define TkUnionRectWithRegion XUnionRectWithRegion

#ifdef HAVE_XFT
MODULE_SCOPE void	TkUnixSetXftClipRegion(TkRegion clipRegion);
MODULE_SCOPE void	TkUnixSetXftClipRegion(Region clipRegion);
#endif

#if !defined(__cplusplus) && !defined(c_plusplus)
# define c_class class
#endif

#if TCL_UTF_MAX > 4
#   define TkUtfToUniChar Tcl_UtfToUniChar
#   define TkUniCharToUtf Tcl_UniCharToUtf
#   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 int TkUtfToUniChar(const char *, int *);
    MODULE_SCOPE int TkUniCharToUtf(int, char *);
    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
#endif

/*
 * Unsupported commands.
 */

MODULE_SCOPE int	TkUnsupported1ObjCmd(ClientData clientData,
1295
1296
1297
1298
1299
1300
1301




1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467







+
+
+
+










			    Tcl_Obj * const objv[]);
MODULE_SCOPE int	TkOldTestInit(Tcl_Interp *interp);
#if !(defined(_WIN32) || defined(MAC_OSX_TK))
#define TkplatformtestInit(x) TCL_OK
#else
MODULE_SCOPE int	TkplatformtestInit(Tcl_Interp *interp);
#endif

#ifdef __cplusplus
}
#endif

#endif /* _TKINT */

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Changes to generic/tkIntDecls.h.
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16


17
18
19
20
21
22
23
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25








-
+







+
+







/*
 * tkIntDecls.h --
 *
 *	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.
 */

#ifndef _TKINTDECLS
#define _TKINTDECLS

#include "X11/Xutil.h"

#ifdef BUILD_tk
#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLEXPORT
#endif

struct TkText;
100
101
102
103
104
105
106
107

108
109
110
111
112
113
114
102
103
104
105
106
107
108

109
110
111
112
113
114
115
116







-
+







				int numPoints, Display *display,
				Drawable drawable, GC gc, GC outlineGC);
/* 21 */
EXTERN int		TkFindStateNum(Tcl_Interp *interp,
				const char *option, const TkStateMap *mapPtr,
				const char *strKey);
/* 22 */
EXTERN CONST86 char *	TkFindStateString(const TkStateMap *mapPtr,
EXTERN const char *	TkFindStateString(const TkStateMap *mapPtr,
				int numKey);
/* 23 */
EXTERN void		TkFocusDeadWindow(TkWindow *winPtr);
/* 24 */
EXTERN int		TkFocusFilterEvent(TkWindow *winPtr,
				XEvent *eventPtr);
/* 25 */
163
164
165
166
167
168
169
170

171
172
173
174
175
176
177
165
166
167
168
169
170
171

172
173
174
175
176
177
178
179







-
+







/* 44 */
EXTERN void		TkInOutEvents(XEvent *eventPtr, TkWindow *sourcePtr,
				TkWindow *destPtr, int leaveType,
				int enterType, Tcl_QueuePosition position);
/* 45 */
EXTERN void		TkInstallFrameMenu(Tk_Window tkwin);
/* 46 */
EXTERN CONST86 char *	TkKeysymToString(KeySym keysym);
EXTERN const char *	TkKeysymToString(KeySym keysym);
/* 47 */
EXTERN int		TkLineToArea(double end1Ptr[], double end2Ptr[],
				double rectPtr[]);
/* 48 */
EXTERN double		TkLineToPoint(double end1Ptr[], double end2Ptr[],
				double pointPtr[]);
/* 49 */
250
251
252
253
254
255
256
257

258
259
260
261
262
263
264
252
253
254
255
256
257
258

259
260
261
262
263
264
265
266







-
+







				unsigned int *width_return,
				unsigned int *height_return,
				Pixmap *bitmap_return, int *x_hot_return,
				int *y_hot_return);
/* 79 */
EXTERN int		TkScrollWindow(Tk_Window tkwin, GC gc, int x, int y,
				int width, int height, int dx, int dy,
				TkRegion damageRgn);
				Region damageRgn);
/* 80 */
EXTERN void		TkSelDeadWindow(TkWindow *winPtr);
/* 81 */
EXTERN void		TkSelEventProc(Tk_Window tkwin, XEvent *eventPtr);
/* 82 */
EXTERN void		TkSelInit(Tk_Window tkwin);
/* 83 */
320
321
322
323
324
325
326
327

328
329
330
331
332
333
334
335
336
337

338
339

340
341

342
343
344


345
346

347
348
349

350
351
352


353
354
355
356
357
358
359
322
323
324
325
326
327
328

329
330
331
332
333
334
335
336
337
338

339
340

341
342

343
344


345
346
347

348
349
350

351
352


353
354
355
356
357
358
359
360
361







-
+









-
+

-
+

-
+

-
-
+
+

-
+


-
+

-
-
+
+







/* 107 */
EXTERN TkMainInfo *	TkGetMainInfoList(void);
/* 108 */
EXTERN int		TkGetWindowFromObj(Tcl_Interp *interp,
				Tk_Window tkwin, Tcl_Obj *objPtr,
				Tk_Window *windowPtr);
/* 109 */
EXTERN CONST86 char *	TkpGetString(TkWindow *winPtr, XEvent *eventPtr,
EXTERN const char *	TkpGetString(TkWindow *winPtr, XEvent *eventPtr,
				Tcl_DString *dsPtr);
/* 110 */
EXTERN void		TkpGetSubFonts(Tcl_Interp *interp, Tk_Font tkfont);
/* 111 */
EXTERN Tcl_Obj *	TkpGetSystemDefault(Tk_Window tkwin,
				const char *dbName, const char *className);
/* 112 */
EXTERN void		TkpMenuThreadInit(void);
/* 113 */
EXTERN int		TkClipBox(TkRegion rgn, XRectangle *rect_return);
EXTERN int		XClipBox(Region rgn, XRectangle *rect_return);
/* 114 */
EXTERN TkRegion		TkCreateRegion(void);
EXTERN Region		XCreateRegion(void);
/* 115 */
EXTERN int		TkDestroyRegion(TkRegion rgn);
EXTERN int		XDestroyRegion(Region rgn);
/* 116 */
EXTERN int		TkIntersectRegion(TkRegion sra, TkRegion srcb,
				TkRegion dr_return);
EXTERN int		XIntersectRegion(Region sra, Region srcb,
				Region dr_return);
/* 117 */
EXTERN int		TkRectInRegion(TkRegion rgn, int x, int y,
EXTERN int		XRectInRegion(Region rgn, int x, int y,
				unsigned int width, unsigned int height);
/* 118 */
EXTERN int		TkSetRegion(Display *display, GC gc, TkRegion rgn);
EXTERN int		XSetRegion(Display *display, GC gc, Region rgn);
/* 119 */
EXTERN int		TkUnionRectWithRegion(XRectangle *rect, TkRegion src,
				TkRegion dr_return);
EXTERN int		XUnionRectWithRegion(XRectangle *rect, Region src,
				Region dr_return);
/* Slot 120 is reserved */
#ifdef MAC_OSX_TK /* AQUA */
/* 121 */
EXTERN Pixmap		TkpCreateNativeBitmap(Display *display,
				const void *source);
#endif /* AQUA */
#ifdef MAC_OSX_TK /* AQUA */
386
387
388
389
390
391
392
393

394
395
396
397
398
399
400
401
402
403
404


405
406
407
408
409
410
411
388
389
390
391
392
393
394

395
396
397
398
399
400
401
402
403
404


405
406
407
408
409
410
411
412
413







-
+









-
-
+
+







EXTERN void		TkpSetKeycodeAndState(Tk_Window tkwin, KeySym keySym,
				XEvent *eventPtr);
/* 138 */
EXTERN KeySym		TkpGetKeySym(TkDisplay *dispPtr, XEvent *eventPtr);
/* 139 */
EXTERN void		TkpInitKeymapInfo(TkDisplay *dispPtr);
/* 140 */
EXTERN TkRegion		TkPhotoGetValidRegion(Tk_PhotoHandle handle);
EXTERN Region		TkPhotoGetValidRegion(Tk_PhotoHandle handle);
/* 141 */
EXTERN TkWindow **	TkWmStackorderToplevel(TkWindow *parentPtr);
/* 142 */
EXTERN void		TkFocusFree(TkMainInfo *mainPtr);
/* 143 */
EXTERN void		TkClipCleanup(TkDisplay *dispPtr);
/* 144 */
EXTERN void		TkGCCleanup(TkDisplay *dispPtr);
/* 145 */
EXTERN int		TkSubtractRegion(TkRegion sra, TkRegion srcb,
				TkRegion dr_return);
EXTERN int		XSubtractRegion(Region sra, Region srcb,
				Region dr_return);
/* 146 */
EXTERN void		TkStylePkgInit(TkMainInfo *mainPtr);
/* 147 */
EXTERN void		TkStylePkgFree(TkMainInfo *mainPtr);
/* 148 */
EXTERN Tk_Window	TkToplevelWindowForCommand(Tcl_Interp *interp,
				const char *cmdName);
455
456
457
458
459
460
461
462

463
464
465
466
467
468
469
457
458
459
460
461
462
463

464
465
466
467
468
469
470
471







-
+







				const struct TkTextIndex *srcPtr, int count,
				struct TkTextIndex *dstPtr);
/* 162 */
EXTERN struct TkTextIndex * TkTextMakeByteIndex(TkTextBTree tree,
				const struct TkText *textPtr, int lineIndex,
				int byteIndex, struct TkTextIndex *indexPtr);
/* 163 */
EXTERN int		TkTextPrintIndex(const struct TkText *textPtr,
EXTERN TkSizeT		TkTextPrintIndex(const struct TkText *textPtr,
				const struct TkTextIndex *indexPtr,
				char *string);
/* 164 */
EXTERN struct TkTextSegment * TkTextSetMark(struct TkText *textPtr,
				const char *name,
				struct TkTextIndex *indexPtr);
/* 165 */
482
483
484
485
486
487
488
489


490
491
492
493



494
495
496
497


498
499
500
501



502
503
504
505


506
507
508
509



510
511
512
513


514
515
516
517



518
519
520
521


522
523
524
525



526
527
528
529


530
531
532
533



534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552












553
554
555
556
557
558
559
484
485
486
487
488
489
490

491
492
493



494
495
496
497
498
499

500
501
502



503
504
505
506
507
508

509
510
511



512
513
514
515
516
517

518
519
520



521
522
523
524
525
526

527
528
529



530
531
532
533
534
535

536
537
538



539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579







-
+
+

-
-
-
+
+
+



-
+
+

-
-
-
+
+
+



-
+
+

-
-
-
+
+
+



-
+
+

-
-
-
+
+
+



-
+
+

-
-
-
+
+
+



-
+
+

-
-
-
+
+
+



















+
+
+
+
+
+
+
+
+
+
+
+







EXTERN void		TkTextInsertDisplayProc(struct TkText *textPtr,
				struct TkTextDispChunk *chunkPtr, int x,
				int y, int height, int baseline,
				Display *display, Drawable dst, int screenY);
/* 169 */
EXTERN int		TkStateParseProc(ClientData clientData,
				Tcl_Interp *interp, Tk_Window tkwin,
				const char *value, char *widgRec, int offset);
				const char *value, char *widgRec,
				TkSizeT offset);
/* 170 */
EXTERN CONST86 char *	TkStatePrintProc(ClientData clientData,
				Tk_Window tkwin, char *widgRec, int offset,
				Tcl_FreeProc **freeProcPtr);
EXTERN const char *	TkStatePrintProc(ClientData clientData,
				Tk_Window tkwin, char *widgRec,
				TkSizeT offset, Tcl_FreeProc **freeProcPtr);
/* 171 */
EXTERN int		TkCanvasDashParseProc(ClientData clientData,
				Tcl_Interp *interp, Tk_Window tkwin,
				const char *value, char *widgRec, int offset);
				const char *value, char *widgRec,
				TkSizeT offset);
/* 172 */
EXTERN CONST86 char *	TkCanvasDashPrintProc(ClientData clientData,
				Tk_Window tkwin, char *widgRec, int offset,
				Tcl_FreeProc **freeProcPtr);
EXTERN const char *	TkCanvasDashPrintProc(ClientData clientData,
				Tk_Window tkwin, char *widgRec,
				TkSizeT offset, Tcl_FreeProc **freeProcPtr);
/* 173 */
EXTERN int		TkOffsetParseProc(ClientData clientData,
				Tcl_Interp *interp, Tk_Window tkwin,
				const char *value, char *widgRec, int offset);
				const char *value, char *widgRec,
				TkSizeT offset);
/* 174 */
EXTERN CONST86 char *	TkOffsetPrintProc(ClientData clientData,
				Tk_Window tkwin, char *widgRec, int offset,
				Tcl_FreeProc **freeProcPtr);
EXTERN const char *	TkOffsetPrintProc(ClientData clientData,
				Tk_Window tkwin, char *widgRec,
				TkSizeT offset, Tcl_FreeProc **freeProcPtr);
/* 175 */
EXTERN int		TkPixelParseProc(ClientData clientData,
				Tcl_Interp *interp, Tk_Window tkwin,
				const char *value, char *widgRec, int offset);
				const char *value, char *widgRec,
				TkSizeT offset);
/* 176 */
EXTERN CONST86 char *	TkPixelPrintProc(ClientData clientData,
				Tk_Window tkwin, char *widgRec, int offset,
				Tcl_FreeProc **freeProcPtr);
EXTERN const char *	TkPixelPrintProc(ClientData clientData,
				Tk_Window tkwin, char *widgRec,
				TkSizeT offset, Tcl_FreeProc **freeProcPtr);
/* 177 */
EXTERN int		TkOrientParseProc(ClientData clientData,
				Tcl_Interp *interp, Tk_Window tkwin,
				const char *value, char *widgRec, int offset);
				const char *value, char *widgRec,
				TkSizeT offset);
/* 178 */
EXTERN CONST86 char *	TkOrientPrintProc(ClientData clientData,
				Tk_Window tkwin, char *widgRec, int offset,
				Tcl_FreeProc **freeProcPtr);
EXTERN const char *	TkOrientPrintProc(ClientData clientData,
				Tk_Window tkwin, char *widgRec,
				TkSizeT offset, Tcl_FreeProc **freeProcPtr);
/* 179 */
EXTERN int		TkSmoothParseProc(ClientData clientData,
				Tcl_Interp *interp, Tk_Window tkwin,
				const char *value, char *widgRec, int offset);
				const char *value, char *widgRec,
				TkSizeT offset);
/* 180 */
EXTERN CONST86 char *	TkSmoothPrintProc(ClientData clientData,
				Tk_Window tkwin, char *widgRec, int offset,
				Tcl_FreeProc **freeProcPtr);
EXTERN const char *	TkSmoothPrintProc(ClientData clientData,
				Tk_Window tkwin, char *widgRec,
				TkSizeT offset, Tcl_FreeProc **freeProcPtr);
/* 181 */
EXTERN void		TkDrawAngledTextLayout(Display *display,
				Drawable drawable, GC gc,
				Tk_TextLayout layout, int x, int y,
				double angle, int firstChar, int lastChar);
/* 182 */
EXTERN void		TkUnderlineAngledTextLayout(Display *display,
				Drawable drawable, GC gc,
				Tk_TextLayout layout, int x, int y,
				double angle, int underline);
/* 183 */
EXTERN int		TkIntersectAngledTextLayout(Tk_TextLayout layout,
				int x, int y, int width, int height,
				double angle);
/* 184 */
EXTERN void		TkDrawAngledChars(Display *display,
				Drawable drawable, GC gc, Tk_Font tkfont,
				const char *source, int numBytes, double x,
				double y, double angle);
#ifdef MAC_OSX_TCL /* MACOSX */
/* 185 */
EXTERN void		TkpRedrawWidget(Tk_Window tkwin);
#endif /* MACOSX */
#ifdef MAC_OSX_TCL /* MACOSX */
/* 186 */
EXTERN int		TkpWillDrawWidget(Tk_Window tkwin);
#endif /* MACOSX */
/* 187 */
EXTERN int		TkDebugPhotoStringMatchDef(Tcl_Interp *inter,
				Tcl_Obj *data, Tcl_Obj *formatString,
				int *widthPtr, int *heightPtr);

typedef struct TkIntStubs {
    int magic;
    void *hooks;

    TkWindow * (*tkAllocWindow) (TkDisplay *dispPtr, int screenNum, TkWindow *parentPtr); /* 0 */
    void (*tkBezierPoints) (double control[], int numSteps, double *coordPtr); /* 1 */
573
574
575
576
577
578
579
580

581
582
583
584
585
586
587
593
594
595
596
597
598
599

600
601
602
603
604
605
606
607







-
+







    Time (*tkCurrentTime) (TkDisplay *dispPtr); /* 15 */
    void (*tkDeleteAllImages) (TkMainInfo *mainPtr); /* 16 */
    void (*tkDoConfigureNotify) (TkWindow *winPtr); /* 17 */
    void (*tkDrawInsetFocusHighlight) (Tk_Window tkwin, GC gc, int width, Drawable drawable, int padding); /* 18 */
    void (*tkEventDeadWindow) (TkWindow *winPtr); /* 19 */
    void (*tkFillPolygon) (Tk_Canvas canvas, double *coordPtr, int numPoints, Display *display, Drawable drawable, GC gc, GC outlineGC); /* 20 */
    int (*tkFindStateNum) (Tcl_Interp *interp, const char *option, const TkStateMap *mapPtr, const char *strKey); /* 21 */
    CONST86 char * (*tkFindStateString) (const TkStateMap *mapPtr, int numKey); /* 22 */
    const char * (*tkFindStateString) (const TkStateMap *mapPtr, int numKey); /* 22 */
    void (*tkFocusDeadWindow) (TkWindow *winPtr); /* 23 */
    int (*tkFocusFilterEvent) (TkWindow *winPtr, XEvent *eventPtr); /* 24 */
    TkWindow * (*tkFocusKeyEvent) (TkWindow *winPtr, XEvent *eventPtr); /* 25 */
    void (*tkFontPkgInit) (TkMainInfo *mainPtr); /* 26 */
    void (*tkFontPkgFree) (TkMainInfo *mainPtr); /* 27 */
    void (*tkFreeBindingTags) (TkWindow *winPtr); /* 28 */
    void (*tkpFreeCursor) (TkCursor *cursorPtr); /* 29 */
597
598
599
600
601
602
603
604

605
606
607
608
609
610
611
617
618
619
620
621
622
623

624
625
626
627
628
629
630
631







-
+







    void (*tkGetPointerCoords) (Tk_Window tkwin, int *xPtr, int *yPtr); /* 39 */
    void (*tkGetServerInfo) (Tcl_Interp *interp, Tk_Window tkwin); /* 40 */
    void (*tkGrabDeadWindow) (TkWindow *winPtr); /* 41 */
    int (*tkGrabState) (TkWindow *winPtr); /* 42 */
    void (*tkIncludePoint) (Tk_Item *itemPtr, double *pointPtr); /* 43 */
    void (*tkInOutEvents) (XEvent *eventPtr, TkWindow *sourcePtr, TkWindow *destPtr, int leaveType, int enterType, Tcl_QueuePosition position); /* 44 */
    void (*tkInstallFrameMenu) (Tk_Window tkwin); /* 45 */
    CONST86 char * (*tkKeysymToString) (KeySym keysym); /* 46 */
    const char * (*tkKeysymToString) (KeySym keysym); /* 46 */
    int (*tkLineToArea) (double end1Ptr[], double end2Ptr[], double rectPtr[]); /* 47 */
    double (*tkLineToPoint) (double end1Ptr[], double end2Ptr[], double pointPtr[]); /* 48 */
    int (*tkMakeBezierCurve) (Tk_Canvas canvas, double *pointPtr, int numPoints, int numSteps, XPoint xPoints[], double dblPoints[]); /* 49 */
    void (*tkMakeBezierPostscript) (Tcl_Interp *interp, Tk_Canvas canvas, double *pointPtr, int numPoints); /* 50 */
    void (*tkOptionClassChanged) (TkWindow *winPtr); /* 51 */
    void (*tkOptionDeadWindow) (TkWindow *winPtr); /* 52 */
    int (*tkOvalToArea) (double *ovalPtr, double *rectPtr); /* 53 */
630
631
632
633
634
635
636
637

638
639
640
641
642
643
644
650
651
652
653
654
655
656

657
658
659
660
661
662
663
664







-
+







    int (*tkPositionInTree) (TkWindow *winPtr, TkWindow *treePtr); /* 72 */
    void (*tkpRedirectKeyEvent) (TkWindow *winPtr, XEvent *eventPtr); /* 73 */
    void (*tkpSetMainMenubar) (Tcl_Interp *interp, Tk_Window tkwin, const char *menuName); /* 74 */
    int (*tkpUseWindow) (Tcl_Interp *interp, Tk_Window tkwin, const char *string); /* 75 */
    void (*reserved76)(void);
    void (*tkQueueEventForAllChildren) (TkWindow *winPtr, XEvent *eventPtr); /* 77 */
    int (*tkReadBitmapFile) (Display *display, Drawable d, const char *filename, unsigned int *width_return, unsigned int *height_return, Pixmap *bitmap_return, int *x_hot_return, int *y_hot_return); /* 78 */
    int (*tkScrollWindow) (Tk_Window tkwin, GC gc, int x, int y, int width, int height, int dx, int dy, TkRegion damageRgn); /* 79 */
    int (*tkScrollWindow) (Tk_Window tkwin, GC gc, int x, int y, int width, int height, int dx, int dy, Region damageRgn); /* 79 */
    void (*tkSelDeadWindow) (TkWindow *winPtr); /* 80 */
    void (*tkSelEventProc) (Tk_Window tkwin, XEvent *eventPtr); /* 81 */
    void (*tkSelInit) (Tk_Window tkwin); /* 82 */
    void (*tkSelPropProc) (XEvent *eventPtr); /* 83 */
    void (*reserved84)(void);
    void (*tkSetWindowMenuBar) (Tcl_Interp *interp, Tk_Window tkwin, const char *oldMenuName, const char *menuName); /* 85 */
    KeySym (*tkStringToKeysym) (const char *name); /* 86 */
660
661
662
663
664
665
666
667

668
669
670
671
672
673
674
675
676
677







678
679
680
681
682
683
684
680
681
682
683
684
685
686

687
688
689
690







691
692
693
694
695
696
697
698
699
700
701
702
703
704







-
+



-
-
-
-
-
-
-
+
+
+
+
+
+
+







    Tcl_Obj * (*tkDebugConfig) (Tcl_Interp *interp, Tk_OptionTable table); /* 102 */
    Tcl_Obj * (*tkDebugFont) (Tk_Window tkwin, const char *name); /* 103 */
    int (*tkFindStateNumObj) (Tcl_Interp *interp, Tcl_Obj *optionPtr, const TkStateMap *mapPtr, Tcl_Obj *keyPtr); /* 104 */
    Tcl_HashTable * (*tkGetBitmapPredefTable) (void); /* 105 */
    TkDisplay * (*tkGetDisplayList) (void); /* 106 */
    TkMainInfo * (*tkGetMainInfoList) (void); /* 107 */
    int (*tkGetWindowFromObj) (Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr, Tk_Window *windowPtr); /* 108 */
    CONST86 char * (*tkpGetString) (TkWindow *winPtr, XEvent *eventPtr, Tcl_DString *dsPtr); /* 109 */
    const char * (*tkpGetString) (TkWindow *winPtr, XEvent *eventPtr, Tcl_DString *dsPtr); /* 109 */
    void (*tkpGetSubFonts) (Tcl_Interp *interp, Tk_Font tkfont); /* 110 */
    Tcl_Obj * (*tkpGetSystemDefault) (Tk_Window tkwin, const char *dbName, const char *className); /* 111 */
    void (*tkpMenuThreadInit) (void); /* 112 */
    int (*tkClipBox) (TkRegion rgn, XRectangle *rect_return); /* 113 */
    TkRegion (*tkCreateRegion) (void); /* 114 */
    int (*tkDestroyRegion) (TkRegion rgn); /* 115 */
    int (*tkIntersectRegion) (TkRegion sra, TkRegion srcb, TkRegion dr_return); /* 116 */
    int (*tkRectInRegion) (TkRegion rgn, int x, int y, unsigned int width, unsigned int height); /* 117 */
    int (*tkSetRegion) (Display *display, GC gc, TkRegion rgn); /* 118 */
    int (*tkUnionRectWithRegion) (XRectangle *rect, TkRegion src, TkRegion dr_return); /* 119 */
    int (*xClipBox) (Region rgn, XRectangle *rect_return); /* 113 */
    Region (*xCreateRegion) (void); /* 114 */
    int (*xDestroyRegion) (Region rgn); /* 115 */
    int (*xIntersectRegion) (Region sra, Region srcb, Region dr_return); /* 116 */
    int (*xRectInRegion) (Region rgn, int x, int y, unsigned int width, unsigned int height); /* 117 */
    int (*xSetRegion) (Display *display, GC gc, Region rgn); /* 118 */
    int (*xUnionRectWithRegion) (XRectangle *rect, Region src, Region dr_return); /* 119 */
    void (*reserved120)(void);
#if !(defined(_WIN32) || defined(MAC_OSX_TK)) /* X11 */
    void (*reserved121)(void);
#endif /* X11 */
#if defined(_WIN32) /* WIN */
    void (*reserved121)(void);
#endif /* WIN */
718
719
720
721
722
723
724
725

726
727
728
729
730

731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748

749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765












766
767
768
769



















770
771
772
773
774
775
776
738
739
740
741
742
743
744

745
746
747
748
749

750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767

768
769
770
771
772
773












774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815







-
+




-
+

















-
+





-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+




+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    void (*reserved133)(void);
    void (*reserved134)(void);
    void (*tkpDrawHighlightBorder) (Tk_Window tkwin, GC fgGC, GC bgGC, int highlightWidth, Drawable drawable); /* 135 */
    void (*tkSetFocusWin) (TkWindow *winPtr, int force); /* 136 */
    void (*tkpSetKeycodeAndState) (Tk_Window tkwin, KeySym keySym, XEvent *eventPtr); /* 137 */
    KeySym (*tkpGetKeySym) (TkDisplay *dispPtr, XEvent *eventPtr); /* 138 */
    void (*tkpInitKeymapInfo) (TkDisplay *dispPtr); /* 139 */
    TkRegion (*tkPhotoGetValidRegion) (Tk_PhotoHandle handle); /* 140 */
    Region (*tkPhotoGetValidRegion) (Tk_PhotoHandle handle); /* 140 */
    TkWindow ** (*tkWmStackorderToplevel) (TkWindow *parentPtr); /* 141 */
    void (*tkFocusFree) (TkMainInfo *mainPtr); /* 142 */
    void (*tkClipCleanup) (TkDisplay *dispPtr); /* 143 */
    void (*tkGCCleanup) (TkDisplay *dispPtr); /* 144 */
    int (*tkSubtractRegion) (TkRegion sra, TkRegion srcb, TkRegion dr_return); /* 145 */
    int (*xSubtractRegion) (Region sra, Region srcb, Region dr_return); /* 145 */
    void (*tkStylePkgInit) (TkMainInfo *mainPtr); /* 146 */
    void (*tkStylePkgFree) (TkMainInfo *mainPtr); /* 147 */
    Tk_Window (*tkToplevelWindowForCommand) (Tcl_Interp *interp, const char *cmdName); /* 148 */
    const Tk_OptionSpec * (*tkGetOptionSpec) (const char *name, Tk_OptionTable optionTable); /* 149 */
    int (*tkMakeRawCurve) (Tk_Canvas canvas, double *pointPtr, int numPoints, int numSteps, XPoint xPoints[], double dblPoints[]); /* 150 */
    void (*tkMakeRawCurvePostscript) (Tcl_Interp *interp, Tk_Canvas canvas, double *pointPtr, int numPoints); /* 151 */
    void (*tkpDrawFrame) (Tk_Window tkwin, Tk_3DBorder border, int highlightWidth, int borderWidth, int relief); /* 152 */
    void (*tkCreateThreadExitHandler) (Tcl_ExitProc *proc, ClientData clientData); /* 153 */
    void (*tkDeleteThreadExitHandler) (Tcl_ExitProc *proc, ClientData clientData); /* 154 */
    void (*reserved155)(void);
    int (*tkpTestembedCmd) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 156 */
    int (*tkpTesttextCmd) (ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 157 */
    int (*tkSelGetSelection) (Tcl_Interp *interp, Tk_Window tkwin, Atom selection, Atom target, Tk_GetSelProc *proc, ClientData clientData); /* 158 */
    int (*tkTextGetIndex) (Tcl_Interp *interp, struct TkText *textPtr, const char *string, struct TkTextIndex *indexPtr); /* 159 */
    int (*tkTextIndexBackBytes) (const struct TkText *textPtr, const struct TkTextIndex *srcPtr, int count, struct TkTextIndex *dstPtr); /* 160 */
    int (*tkTextIndexForwBytes) (const struct TkText *textPtr, const struct TkTextIndex *srcPtr, int count, struct TkTextIndex *dstPtr); /* 161 */
    struct TkTextIndex * (*tkTextMakeByteIndex) (TkTextBTree tree, const struct TkText *textPtr, int lineIndex, int byteIndex, struct TkTextIndex *indexPtr); /* 162 */
    int (*tkTextPrintIndex) (const struct TkText *textPtr, const struct TkTextIndex *indexPtr, char *string); /* 163 */
    TkSizeT (*tkTextPrintIndex) (const struct TkText *textPtr, const struct TkTextIndex *indexPtr, char *string); /* 163 */
    struct TkTextSegment * (*tkTextSetMark) (struct TkText *textPtr, const char *name, struct TkTextIndex *indexPtr); /* 164 */
    int (*tkTextXviewCmd) (struct TkText *textPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 165 */
    void (*tkTextChanged) (struct TkSharedText *sharedTextPtr, struct TkText *textPtr, const struct TkTextIndex *index1Ptr, const struct TkTextIndex *index2Ptr); /* 166 */
    int (*tkBTreeNumLines) (TkTextBTree tree, const struct TkText *textPtr); /* 167 */
    void (*tkTextInsertDisplayProc) (struct TkText *textPtr, struct TkTextDispChunk *chunkPtr, int x, int y, int height, int baseline, Display *display, Drawable dst, int screenY); /* 168 */
    int (*tkStateParseProc) (ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, int offset); /* 169 */
    CONST86 char * (*tkStatePrintProc) (ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr); /* 170 */
    int (*tkCanvasDashParseProc) (ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, int offset); /* 171 */
    CONST86 char * (*tkCanvasDashPrintProc) (ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr); /* 172 */
    int (*tkOffsetParseProc) (ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, int offset); /* 173 */
    CONST86 char * (*tkOffsetPrintProc) (ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr); /* 174 */
    int (*tkPixelParseProc) (ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, int offset); /* 175 */
    CONST86 char * (*tkPixelPrintProc) (ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr); /* 176 */
    int (*tkOrientParseProc) (ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, int offset); /* 177 */
    CONST86 char * (*tkOrientPrintProc) (ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr); /* 178 */
    int (*tkSmoothParseProc) (ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, int offset); /* 179 */
    CONST86 char * (*tkSmoothPrintProc) (ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr); /* 180 */
    int (*tkStateParseProc) (ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, TkSizeT offset); /* 169 */
    const char * (*tkStatePrintProc) (ClientData clientData, Tk_Window tkwin, char *widgRec, TkSizeT offset, Tcl_FreeProc **freeProcPtr); /* 170 */
    int (*tkCanvasDashParseProc) (ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, TkSizeT offset); /* 171 */
    const char * (*tkCanvasDashPrintProc) (ClientData clientData, Tk_Window tkwin, char *widgRec, TkSizeT offset, Tcl_FreeProc **freeProcPtr); /* 172 */
    int (*tkOffsetParseProc) (ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, TkSizeT offset); /* 173 */
    const char * (*tkOffsetPrintProc) (ClientData clientData, Tk_Window tkwin, char *widgRec, TkSizeT offset, Tcl_FreeProc **freeProcPtr); /* 174 */
    int (*tkPixelParseProc) (ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, TkSizeT offset); /* 175 */
    const char * (*tkPixelPrintProc) (ClientData clientData, Tk_Window tkwin, char *widgRec, TkSizeT offset, Tcl_FreeProc **freeProcPtr); /* 176 */
    int (*tkOrientParseProc) (ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, TkSizeT offset); /* 177 */
    const char * (*tkOrientPrintProc) (ClientData clientData, Tk_Window tkwin, char *widgRec, TkSizeT offset, Tcl_FreeProc **freeProcPtr); /* 178 */
    int (*tkSmoothParseProc) (ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, const char *value, char *widgRec, TkSizeT offset); /* 179 */
    const char * (*tkSmoothPrintProc) (ClientData clientData, Tk_Window tkwin, char *widgRec, TkSizeT offset, Tcl_FreeProc **freeProcPtr); /* 180 */
    void (*tkDrawAngledTextLayout) (Display *display, Drawable drawable, GC gc, Tk_TextLayout layout, int x, int y, double angle, int firstChar, int lastChar); /* 181 */
    void (*tkUnderlineAngledTextLayout) (Display *display, Drawable drawable, GC gc, Tk_TextLayout layout, int x, int y, double angle, int underline); /* 182 */
    int (*tkIntersectAngledTextLayout) (Tk_TextLayout layout, int x, int y, int width, int height, double angle); /* 183 */
    void (*tkDrawAngledChars) (Display *display, Drawable drawable, GC gc, Tk_Font tkfont, const char *source, int numBytes, double x, double y, double angle); /* 184 */
#if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */
    void (*reserved185)(void);
#endif /* UNIX */
#if defined(_WIN32) /* WIN */
    void (*reserved185)(void);
#endif /* WIN */
#ifdef MAC_OSX_TCL /* MACOSX */
    void (*tkpRedrawWidget) (Tk_Window tkwin); /* 185 */
#endif /* MACOSX */
#if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */
    void (*reserved186)(void);
#endif /* UNIX */
#if defined(_WIN32) /* WIN */
    void (*reserved186)(void);
#endif /* WIN */
#ifdef MAC_OSX_TCL /* MACOSX */
    int (*tkpWillDrawWidget) (Tk_Window tkwin); /* 186 */
#endif /* MACOSX */
    int (*tkDebugPhotoStringMatchDef) (Tcl_Interp *inter, Tcl_Obj *data, Tcl_Obj *formatString, int *widthPtr, int *heightPtr); /* 187 */
} TkIntStubs;

extern const TkIntStubs *tkIntStubsPtr;

#ifdef __cplusplus
}
#endif
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018














1019
1020
1021
1022
1023
1024
1025
1037
1038
1039
1040
1041
1042
1043














1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064







-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	(tkIntStubsPtr->tkpGetString) /* 109 */
#define TkpGetSubFonts \
	(tkIntStubsPtr->tkpGetSubFonts) /* 110 */
#define TkpGetSystemDefault \
	(tkIntStubsPtr->tkpGetSystemDefault) /* 111 */
#define TkpMenuThreadInit \
	(tkIntStubsPtr->tkpMenuThreadInit) /* 112 */
#define TkClipBox \
	(tkIntStubsPtr->tkClipBox) /* 113 */
#define TkCreateRegion \
	(tkIntStubsPtr->tkCreateRegion) /* 114 */
#define TkDestroyRegion \
	(tkIntStubsPtr->tkDestroyRegion) /* 115 */
#define TkIntersectRegion \
	(tkIntStubsPtr->tkIntersectRegion) /* 116 */
#define TkRectInRegion \
	(tkIntStubsPtr->tkRectInRegion) /* 117 */
#define TkSetRegion \
	(tkIntStubsPtr->tkSetRegion) /* 118 */
#define TkUnionRectWithRegion \
	(tkIntStubsPtr->tkUnionRectWithRegion) /* 119 */
#define XClipBox \
	(tkIntStubsPtr->xClipBox) /* 113 */
#define XCreateRegion \
	(tkIntStubsPtr->xCreateRegion) /* 114 */
#define XDestroyRegion \
	(tkIntStubsPtr->xDestroyRegion) /* 115 */
#define XIntersectRegion \
	(tkIntStubsPtr->xIntersectRegion) /* 116 */
#define XRectInRegion \
	(tkIntStubsPtr->xRectInRegion) /* 117 */
#define XSetRegion \
	(tkIntStubsPtr->xSetRegion) /* 118 */
#define XUnionRectWithRegion \
	(tkIntStubsPtr->xUnionRectWithRegion) /* 119 */
/* Slot 120 is reserved */
#ifdef MAC_OSX_TK /* AQUA */
#define TkpCreateNativeBitmap \
	(tkIntStubsPtr->tkpCreateNativeBitmap) /* 121 */
#endif /* AQUA */
#ifdef MAC_OSX_TK /* AQUA */
#define TkpDefineNativeBitmaps \
1056
1057
1058
1059
1060
1061
1062
1063
1064


1065
1066
1067
1068
1069
1070
1071
1095
1096
1097
1098
1099
1100
1101


1102
1103
1104
1105
1106
1107
1108
1109
1110







-
-
+
+







	(tkIntStubsPtr->tkWmStackorderToplevel) /* 141 */
#define TkFocusFree \
	(tkIntStubsPtr->tkFocusFree) /* 142 */
#define TkClipCleanup \
	(tkIntStubsPtr->tkClipCleanup) /* 143 */
#define TkGCCleanup \
	(tkIntStubsPtr->tkGCCleanup) /* 144 */
#define TkSubtractRegion \
	(tkIntStubsPtr->tkSubtractRegion) /* 145 */
#define XSubtractRegion \
	(tkIntStubsPtr->xSubtractRegion) /* 145 */
#define TkStylePkgInit \
	(tkIntStubsPtr->tkStylePkgInit) /* 146 */
#define TkStylePkgFree \
	(tkIntStubsPtr->tkStylePkgFree) /* 147 */
#define TkToplevelWindowForCommand \
	(tkIntStubsPtr->tkToplevelWindowForCommand) /* 148 */
#define TkGetOptionSpec \
1135
1136
1137
1138
1139
1140
1141










1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161








1162
1163
1164
1165




1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176


1177
1178
1179
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198












1199
1200
1201
1202
1203
1204
1205
1206

1207


1208
1209
1210
1211











1212
1213
1214
1215








+
+
+
+
+
+
+
+
+
+








-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-

-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+


-
	(tkIntStubsPtr->tkDrawAngledTextLayout) /* 181 */
#define TkUnderlineAngledTextLayout \
	(tkIntStubsPtr->tkUnderlineAngledTextLayout) /* 182 */
#define TkIntersectAngledTextLayout \
	(tkIntStubsPtr->tkIntersectAngledTextLayout) /* 183 */
#define TkDrawAngledChars \
	(tkIntStubsPtr->tkDrawAngledChars) /* 184 */
#ifdef MAC_OSX_TCL /* MACOSX */
#define TkpRedrawWidget \
	(tkIntStubsPtr->tkpRedrawWidget) /* 185 */
#endif /* MACOSX */
#ifdef MAC_OSX_TCL /* MACOSX */
#define TkpWillDrawWidget \
	(tkIntStubsPtr->tkpWillDrawWidget) /* 186 */
#endif /* MACOSX */
#define TkDebugPhotoStringMatchDef \
	(tkIntStubsPtr->tkDebugPhotoStringMatchDef) /* 187 */

#endif /* defined(USE_TK_STUBS) */

/* !END!: Do not edit above this line. */

#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLIMPORT

/*
 * On X11, these macros are just wrappers for the equivalent X Region calls.
 */
#if !(defined(_WIN32) || defined(__CYGWIN__) || defined(MAC_OSX_TK)) /* X11 */

#undef TkClipBox
#undef TkCreateRegion
#undef TkDestroyRegion
#undef TkIntersectRegion
#undef TkRectInRegion
#undef TkSetRegion
#undef TkSubtractRegion
#undef TkpCmapStressed_
#undef TkpSync_
#undef TkUnixContainerId_
#undef TkUnixDoOneXEvent_
#undef TkUnixSetMenubar_
#undef TkWmCleanup_
#undef TkSendCleanup_
#undef TkpTestsendCmd_
#undef TkUnionRectWithRegion

#define TkClipBox(rgn, rect) XClipBox((Region) rgn, rect)
#define TkCreateRegion() (TkRegion) XCreateRegion()
#if !defined(MAC_OSX_TK)
#   undef TkpWillDrawWidget
#   undef TkpRedrawWidget
#   define TkpWillDrawWidget(w) 0
#define TkDestroyRegion(rgn) XDestroyRegion((Region) rgn)
#define TkIntersectRegion(a, b, r) XIntersectRegion((Region) a, \
	(Region) b, (Region) r)
#define TkRectInRegion(r, x, y, w, h) XRectInRegion((Region) r, x, y, w, h)
#define TkSetRegion(d, gc, rgn) XSetRegion(d, gc, (Region) rgn)
#define TkSubtractRegion(a, b, r) XSubtractRegion((Region) a, \
	(Region) b, (Region) r)
#define TkUnionRectWithRegion(rect, src, ret) XUnionRectWithRegion(rect, \
	(Region) src, (Region) ret)

#endif /* UNIX */
#   define TkpRedrawWidget(w)
#endif

#endif /* _TKINTDECLS */

Changes to generic/tkIntPlatDecls.h.
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
16








-
+







/*
 * tkIntPlatDecls.h --
 *
 *	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

#ifdef BUILD_tk
147
148
149
150
151
152
153
154



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171

172
173
174
175
176
177
178
179
147
148
149
150
151
152
153

154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172

173

174
175
176
177
178
179
180







-
+
+
+
















-
+
-







EXTERN Tk_Window	TkpGetCapture(void);
#endif /* WIN */
#ifdef MAC_OSX_TK /* AQUA */
/* 0 */
EXTERN void		TkGenerateActivateEvents(TkWindow *winPtr,
				int active);
/* Slot 1 is reserved */
/* Slot 2 is reserved */
/* 2 */
EXTERN void		TkGenerateActivateEvents_(TkWindow *winPtr,
				int active);
/* 3 */
EXTERN void		TkPointerDeadWindow(TkWindow *winPtr);
/* 4 */
EXTERN void		TkpSetCapture(TkWindow *winPtr);
/* 5 */
EXTERN void		TkpSetCursor(TkpCursor cursor);
/* 6 */
EXTERN void		TkpWmSetState(TkWindow *winPtr, int state);
/* 7 */
EXTERN void		TkAboutDlg(void);
/* 8 */
EXTERN unsigned int	TkMacOSXButtonKeyState(void);
/* 9 */
EXTERN void		TkMacOSXClearMenubarActive(void);
/* 10 */
EXTERN int		TkMacOSXDispatchMenuEvent(int menuID, int index);
/* 11 */
/* Slot 11 is reserved */
EXTERN void		TkMacOSXInstallCursor(int resizeOverride);
/* 12 */
EXTERN void		TkMacOSXHandleTearoffMenu(void);
/* Slot 13 is reserved */
/* 14 */
EXTERN int		TkMacOSXDoHLEvent(void *theEvent);
/* Slot 15 is reserved */
/* 16 */
193
194
195
196
197
198
199
200

201
202
203
204
205
206
207
208
209
210
211
212
213
214
215

216
217
218
219
220

221
222
223
224
225
226
227
194
195
196
197
198
199
200

201


202
203
204
205
206
207
208
209
210
211
212
213

214

215
216
217

218
219
220
221
222
223
224
225







-
+
-
-












-
+
-



-
+







				unsigned int searchChar);
/* 23 */
EXTERN void		TkMacOSXMakeRealWindowExist(TkWindow *winPtr);
/* 24 */
EXTERN void *		TkMacOSXMakeStippleMap(Drawable d1, Drawable d2);
/* 25 */
EXTERN void		TkMacOSXMenuClick(void);
/* 26 */
/* Slot 26 is reserved */
EXTERN void		TkMacOSXRegisterOffScreenWindow(Window window,
				void *portPtr);
/* 27 */
EXTERN int		TkMacOSXResizable(TkWindow *winPtr);
/* 28 */
EXTERN void		TkMacOSXSetHelpMenuItemCount(void);
/* 29 */
EXTERN void		TkMacOSXSetScrollbarGrow(TkWindow *winPtr, int flag);
/* 30 */
EXTERN void		TkMacOSXSetUpClippingRgn(Drawable drawable);
/* 31 */
EXTERN void		TkMacOSXSetUpGraphicsPort(GC gc, void *destPort);
/* 32 */
EXTERN void		TkMacOSXUpdateClipRgn(TkWindow *winPtr);
/* 33 */
/* Slot 33 is reserved */
EXTERN void		TkMacOSXUnregisterMacWindow(void *portPtr);
/* 34 */
EXTERN int		TkMacOSXUseMenuID(short macID);
/* 35 */
EXTERN TkRegion		TkMacOSXVisableClipRgn(TkWindow *winPtr);
EXTERN Region		TkMacOSXVisableClipRgn(TkWindow *winPtr);
/* 36 */
EXTERN void		TkMacOSXWinBounds(TkWindow *winPtr, void *geometry);
/* 37 */
EXTERN void		TkMacOSXWindowOffset(void *wRef, int *xOffset,
				int *yOffset);
/* 38 */
EXTERN int		TkSetMacColor(unsigned long pixel, void *macColor);
239
240
241
242
243
244
245
246

247
248
249

250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269



270
271
272
273
274
275
276
237
238
239
240
241
242
243

244
245
246

247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266

267
268
269
270
271
272
273
274
275
276







-
+


-
+



















-
+
+
+







/* 44 */
EXTERN MacDrawable *	TkMacOSXGetHostToplevel(TkWindow *winPtr);
/* 45 */
EXTERN void		TkMacOSXPreprocessMenu(void);
/* 46 */
EXTERN int		TkpIsWindowFloating(void *window);
/* 47 */
EXTERN Tk_Window	TkMacOSXGetCapture(void);
EXTERN Tk_Window	TkpGetCapture(void);
/* Slot 48 is reserved */
/* 49 */
EXTERN Tk_Window	TkGetTransientMaster(TkWindow *winPtr);
EXTERN Tk_Window	TkMacOSXGetContainer(TkWindow *winPtr);
/* 50 */
EXTERN int		TkGenerateButtonEvent(int x, int y, Window window,
				unsigned int state);
/* 51 */
EXTERN void		TkGenWMDestroyEvent(Tk_Window tkwin);
/* 52 */
EXTERN void		TkMacOSXSetDrawingEnabled(TkWindow *winPtr, int flag);
/* 53 */
EXTERN unsigned long	TkpGetMS(void);
/* 54 */
EXTERN void *		TkMacOSXDrawable(Drawable drawable);
/* 55 */
EXTERN int		TkpScanWindowId(Tcl_Interp *interp,
				const char *string, Window *idPtr);
#endif /* AQUA */
#if !(defined(_WIN32) || defined(__CYGWIN__) || defined(MAC_OSX_TK)) /* X11 */
/* 0 */
EXTERN void		TkCreateXEventSource(void);
/* Slot 1 is reserved */
/* Slot 2 is reserved */
/* 2 */
EXTERN void		TkGenerateActivateEvents(TkWindow *winPtr,
				int active);
/* 3 */
EXTERN int		TkpCmapStressed(Tk_Window tkwin, Colormap colormap);
/* 4 */
EXTERN void		TkpSync(Display *display);
/* 5 */
EXTERN Window		TkUnixContainerId(TkWindow *winPtr);
/* 6 */
287
288
289
290
291
292
293










































294
295
296
297
298
299
300
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







/* Slot 11 is reserved */
/* 12 */
EXTERN int		TkpWmSetState(TkWindow *winPtr, int state);
/* 13 */
EXTERN int		TkpTestsendCmd(ClientData clientData,
				Tcl_Interp *interp, int objc,
				Tcl_Obj *const objv[]);
/* Slot 14 is reserved */
/* Slot 15 is reserved */
/* Slot 16 is reserved */
/* Slot 17 is reserved */
/* Slot 18 is reserved */
/* Slot 19 is reserved */
/* Slot 20 is reserved */
/* Slot 21 is reserved */
/* Slot 22 is reserved */
/* Slot 23 is reserved */
/* Slot 24 is reserved */
/* Slot 25 is reserved */
/* Slot 26 is reserved */
/* Slot 27 is reserved */
/* Slot 28 is reserved */
/* Slot 29 is reserved */
/* Slot 30 is reserved */
/* Slot 31 is reserved */
/* Slot 32 is reserved */
/* Slot 33 is reserved */
/* Slot 34 is reserved */
/* Slot 35 is reserved */
/* Slot 36 is reserved */
/* Slot 37 is reserved */
/* 38 */
EXTERN int		TkpCmapStressed_(Tk_Window tkwin, Colormap colormap);
/* 39 */
EXTERN void		TkpSync_(Display *display);
/* 40 */
EXTERN Window		TkUnixContainerId_(TkWindow *winPtr);
/* 41 */
EXTERN int		TkUnixDoOneXEvent_(Tcl_Time *timePtr);
/* 42 */
EXTERN void		TkUnixSetMenubar_(Tk_Window tkwin, Tk_Window menubar);
/* 43 */
EXTERN void		TkWmCleanup_(TkDisplay *dispPtr);
/* 44 */
EXTERN void		TkSendCleanup_(TkDisplay *dispPtr);
/* 45 */
EXTERN int		TkpTestsendCmd_(ClientData clientData,
				Tcl_Interp *interp, int objc,
				Tcl_Obj *const objv[]);
#endif /* X11 */

typedef struct TkIntPlatStubs {
    int magic;
    void *hooks;

#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
346
347
348
349
350
351
352
353

354
355
356
357
358
359
360
361
362

363
364
365
366
367
368
369
370
371
372
373
374
375
376
377

378
379
380
381
382
383
384

385
386

387
388
389
390
391
392
393
394
395
396
397
398

399
400

401
402
403
404
405
406
407
408
409
410
411

412
413
414
415
416
417
418
419
420
421
422
































423
424
425
426
427
428
429
388
389
390
391
392
393
394

395
396
397
398
399
400
401
402
403

404
405
406
407
408
409
410
411
412
413
414
415
416
417
418

419
420
421
422
423
424
425

426
427

428
429
430
431
432
433
434
435
436
437
438
439

440
441

442
443
444
445
446
447
448
449
450
451
452

453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503







-
+








-
+














-
+






-
+

-
+











-
+

-
+










-
+











+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    int (*tkpTestsendCmd) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 45 */
    void (*reserved46)(void);
    Tk_Window (*tkpGetCapture) (void); /* 47 */
#endif /* WIN */
#ifdef MAC_OSX_TK /* AQUA */
    void (*tkGenerateActivateEvents) (TkWindow *winPtr, int active); /* 0 */
    void (*reserved1)(void);
    void (*reserved2)(void);
    void (*tkGenerateActivateEvents_) (TkWindow *winPtr, int active); /* 2 */
    void (*tkPointerDeadWindow) (TkWindow *winPtr); /* 3 */
    void (*tkpSetCapture) (TkWindow *winPtr); /* 4 */
    void (*tkpSetCursor) (TkpCursor cursor); /* 5 */
    void (*tkpWmSetState) (TkWindow *winPtr, int state); /* 6 */
    void (*tkAboutDlg) (void); /* 7 */
    unsigned int (*tkMacOSXButtonKeyState) (void); /* 8 */
    void (*tkMacOSXClearMenubarActive) (void); /* 9 */
    int (*tkMacOSXDispatchMenuEvent) (int menuID, int index); /* 10 */
    void (*tkMacOSXInstallCursor) (int resizeOverride); /* 11 */
    void (*reserved11)(void);
    void (*tkMacOSXHandleTearoffMenu) (void); /* 12 */
    void (*reserved13)(void);
    int (*tkMacOSXDoHLEvent) (void *theEvent); /* 14 */
    void (*reserved15)(void);
    Window (*tkMacOSXGetXWindow) (void *macWinPtr); /* 16 */
    int (*tkMacOSXGrowToplevel) (void *whichWindow, XPoint start); /* 17 */
    void (*tkMacOSXHandleMenuSelect) (short theMenu, unsigned short theItem, int optionKeyPressed); /* 18 */
    void (*reserved19)(void);
    void (*reserved20)(void);
    void (*tkMacOSXInvalidateWindow) (MacDrawable *macWin, int flag); /* 21 */
    int (*tkMacOSXIsCharacterMissing) (Tk_Font tkfont, unsigned int searchChar); /* 22 */
    void (*tkMacOSXMakeRealWindowExist) (TkWindow *winPtr); /* 23 */
    void * (*tkMacOSXMakeStippleMap) (Drawable d1, Drawable d2); /* 24 */
    void (*tkMacOSXMenuClick) (void); /* 25 */
    void (*tkMacOSXRegisterOffScreenWindow) (Window window, void *portPtr); /* 26 */
    void (*reserved26)(void);
    int (*tkMacOSXResizable) (TkWindow *winPtr); /* 27 */
    void (*tkMacOSXSetHelpMenuItemCount) (void); /* 28 */
    void (*tkMacOSXSetScrollbarGrow) (TkWindow *winPtr, int flag); /* 29 */
    void (*tkMacOSXSetUpClippingRgn) (Drawable drawable); /* 30 */
    void (*tkMacOSXSetUpGraphicsPort) (GC gc, void *destPort); /* 31 */
    void (*tkMacOSXUpdateClipRgn) (TkWindow *winPtr); /* 32 */
    void (*tkMacOSXUnregisterMacWindow) (void *portPtr); /* 33 */
    void (*reserved33)(void);
    int (*tkMacOSXUseMenuID) (short macID); /* 34 */
    TkRegion (*tkMacOSXVisableClipRgn) (TkWindow *winPtr); /* 35 */
    Region (*tkMacOSXVisableClipRgn) (TkWindow *winPtr); /* 35 */
    void (*tkMacOSXWinBounds) (TkWindow *winPtr, void *geometry); /* 36 */
    void (*tkMacOSXWindowOffset) (void *wRef, int *xOffset, int *yOffset); /* 37 */
    int (*tkSetMacColor) (unsigned long pixel, void *macColor); /* 38 */
    void (*tkSetWMName) (TkWindow *winPtr, Tk_Uid titleUid); /* 39 */
    void (*reserved40)(void);
    int (*tkMacOSXZoomToplevel) (void *whichWindow, short zoomPart); /* 41 */
    Tk_Window (*tk_TopCoordsToWindow) (Tk_Window tkwin, int rootX, int rootY, int *newX, int *newY); /* 42 */
    MacDrawable * (*tkMacOSXContainerId) (TkWindow *winPtr); /* 43 */
    MacDrawable * (*tkMacOSXGetHostToplevel) (TkWindow *winPtr); /* 44 */
    void (*tkMacOSXPreprocessMenu) (void); /* 45 */
    int (*tkpIsWindowFloating) (void *window); /* 46 */
    Tk_Window (*tkMacOSXGetCapture) (void); /* 47 */
    Tk_Window (*tkpGetCapture) (void); /* 47 */
    void (*reserved48)(void);
    Tk_Window (*tkGetTransientMaster) (TkWindow *winPtr); /* 49 */
    Tk_Window (*tkMacOSXGetContainer) (TkWindow *winPtr); /* 49 */
    int (*tkGenerateButtonEvent) (int x, int y, Window window, unsigned int state); /* 50 */
    void (*tkGenWMDestroyEvent) (Tk_Window tkwin); /* 51 */
    void (*tkMacOSXSetDrawingEnabled) (TkWindow *winPtr, int flag); /* 52 */
    unsigned long (*tkpGetMS) (void); /* 53 */
    void * (*tkMacOSXDrawable) (Drawable drawable); /* 54 */
    int (*tkpScanWindowId) (Tcl_Interp *interp, const char *string, Window *idPtr); /* 55 */
#endif /* AQUA */
#if !(defined(_WIN32) || defined(__CYGWIN__) || defined(MAC_OSX_TK)) /* X11 */
    void (*tkCreateXEventSource) (void); /* 0 */
    void (*reserved1)(void);
    void (*reserved2)(void);
    void (*tkGenerateActivateEvents) (TkWindow *winPtr, int active); /* 2 */
    int (*tkpCmapStressed) (Tk_Window tkwin, Colormap colormap); /* 3 */
    void (*tkpSync) (Display *display); /* 4 */
    Window (*tkUnixContainerId) (TkWindow *winPtr); /* 5 */
    int (*tkUnixDoOneXEvent) (Tcl_Time *timePtr); /* 6 */
    void (*tkUnixSetMenubar) (Tk_Window tkwin, Tk_Window menubar); /* 7 */
    int (*tkpScanWindowId) (Tcl_Interp *interp, const char *string, Window *idPtr); /* 8 */
    void (*tkWmCleanup) (TkDisplay *dispPtr); /* 9 */
    void (*tkSendCleanup) (TkDisplay *dispPtr); /* 10 */
    void (*reserved11)(void);
    int (*tkpWmSetState) (TkWindow *winPtr, int state); /* 12 */
    int (*tkpTestsendCmd) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 13 */
    void (*reserved14)(void);
    void (*reserved15)(void);
    void (*reserved16)(void);
    void (*reserved17)(void);
    void (*reserved18)(void);
    void (*reserved19)(void);
    void (*reserved20)(void);
    void (*reserved21)(void);
    void (*reserved22)(void);
    void (*reserved23)(void);
    void (*reserved24)(void);
    void (*reserved25)(void);
    void (*reserved26)(void);
    void (*reserved27)(void);
    void (*reserved28)(void);
    void (*reserved29)(void);
    void (*reserved30)(void);
    void (*reserved31)(void);
    void (*reserved32)(void);
    void (*reserved33)(void);
    void (*reserved34)(void);
    void (*reserved35)(void);
    void (*reserved36)(void);
    void (*reserved37)(void);
    int (*tkpCmapStressed_) (Tk_Window tkwin, Colormap colormap); /* 38 */
    void (*tkpSync_) (Display *display); /* 39 */
    Window (*tkUnixContainerId_) (TkWindow *winPtr); /* 40 */
    int (*tkUnixDoOneXEvent_) (Tcl_Time *timePtr); /* 41 */
    void (*tkUnixSetMenubar_) (Tk_Window tkwin, Tk_Window menubar); /* 42 */
    void (*tkWmCleanup_) (TkDisplay *dispPtr); /* 43 */
    void (*tkSendCleanup_) (TkDisplay *dispPtr); /* 44 */
    int (*tkpTestsendCmd_) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 45 */
#endif /* X11 */
} TkIntPlatStubs;

extern const TkIntPlatStubs *tkIntPlatStubsPtr;

#ifdef __cplusplus
}
531
532
533
534
535
536
537
538


539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555

556
557
558
559
560
561
562
563
605
606
607
608
609
610
611

612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629

630

631
632
633
634
635
636
637







-
+
+
















-
+
-







#define TkpGetCapture \
	(tkIntPlatStubsPtr->tkpGetCapture) /* 47 */
#endif /* WIN */
#ifdef MAC_OSX_TK /* AQUA */
#define TkGenerateActivateEvents \
	(tkIntPlatStubsPtr->tkGenerateActivateEvents) /* 0 */
/* Slot 1 is reserved */
/* Slot 2 is reserved */
#define TkGenerateActivateEvents_ \
	(tkIntPlatStubsPtr->tkGenerateActivateEvents_) /* 2 */
#define TkPointerDeadWindow \
	(tkIntPlatStubsPtr->tkPointerDeadWindow) /* 3 */
#define TkpSetCapture \
	(tkIntPlatStubsPtr->tkpSetCapture) /* 4 */
#define TkpSetCursor \
	(tkIntPlatStubsPtr->tkpSetCursor) /* 5 */
#define TkpWmSetState \
	(tkIntPlatStubsPtr->tkpWmSetState) /* 6 */
#define TkAboutDlg \
	(tkIntPlatStubsPtr->tkAboutDlg) /* 7 */
#define TkMacOSXButtonKeyState \
	(tkIntPlatStubsPtr->tkMacOSXButtonKeyState) /* 8 */
#define TkMacOSXClearMenubarActive \
	(tkIntPlatStubsPtr->tkMacOSXClearMenubarActive) /* 9 */
#define TkMacOSXDispatchMenuEvent \
	(tkIntPlatStubsPtr->tkMacOSXDispatchMenuEvent) /* 10 */
#define TkMacOSXInstallCursor \
/* Slot 11 is reserved */
	(tkIntPlatStubsPtr->tkMacOSXInstallCursor) /* 11 */
#define TkMacOSXHandleTearoffMenu \
	(tkIntPlatStubsPtr->tkMacOSXHandleTearoffMenu) /* 12 */
/* Slot 13 is reserved */
#define TkMacOSXDoHLEvent \
	(tkIntPlatStubsPtr->tkMacOSXDoHLEvent) /* 14 */
/* Slot 15 is reserved */
#define TkMacOSXGetXWindow \
574
575
576
577
578
579
580
581

582
583
584
585
586
587
588
589
590
591
592
593
594
595

596
597
598
599
600
601
602
603
648
649
650
651
652
653
654

655

656
657
658
659
660
661
662
663
664
665
666
667

668

669
670
671
672
673
674
675







-
+
-












-
+
-







	(tkIntPlatStubsPtr->tkMacOSXIsCharacterMissing) /* 22 */
#define TkMacOSXMakeRealWindowExist \
	(tkIntPlatStubsPtr->tkMacOSXMakeRealWindowExist) /* 23 */
#define TkMacOSXMakeStippleMap \
	(tkIntPlatStubsPtr->tkMacOSXMakeStippleMap) /* 24 */
#define TkMacOSXMenuClick \
	(tkIntPlatStubsPtr->tkMacOSXMenuClick) /* 25 */
#define TkMacOSXRegisterOffScreenWindow \
/* Slot 26 is reserved */
	(tkIntPlatStubsPtr->tkMacOSXRegisterOffScreenWindow) /* 26 */
#define TkMacOSXResizable \
	(tkIntPlatStubsPtr->tkMacOSXResizable) /* 27 */
#define TkMacOSXSetHelpMenuItemCount \
	(tkIntPlatStubsPtr->tkMacOSXSetHelpMenuItemCount) /* 28 */
#define TkMacOSXSetScrollbarGrow \
	(tkIntPlatStubsPtr->tkMacOSXSetScrollbarGrow) /* 29 */
#define TkMacOSXSetUpClippingRgn \
	(tkIntPlatStubsPtr->tkMacOSXSetUpClippingRgn) /* 30 */
#define TkMacOSXSetUpGraphicsPort \
	(tkIntPlatStubsPtr->tkMacOSXSetUpGraphicsPort) /* 31 */
#define TkMacOSXUpdateClipRgn \
	(tkIntPlatStubsPtr->tkMacOSXUpdateClipRgn) /* 32 */
#define TkMacOSXUnregisterMacWindow \
/* Slot 33 is reserved */
	(tkIntPlatStubsPtr->tkMacOSXUnregisterMacWindow) /* 33 */
#define TkMacOSXUseMenuID \
	(tkIntPlatStubsPtr->tkMacOSXUseMenuID) /* 34 */
#define TkMacOSXVisableClipRgn \
	(tkIntPlatStubsPtr->tkMacOSXVisableClipRgn) /* 35 */
#define TkMacOSXWinBounds \
	(tkIntPlatStubsPtr->tkMacOSXWinBounds) /* 36 */
#define TkMacOSXWindowOffset \
615
616
617
618
619
620
621
622
623


624
625
626


627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644


645
646
647
648
649
650
651
687
688
689
690
691
692
693


694
695
696


697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715

716
717
718
719
720
721
722
723
724







-
-
+
+

-
-
+
+

















-
+
+







	(tkIntPlatStubsPtr->tkMacOSXContainerId) /* 43 */
#define TkMacOSXGetHostToplevel \
	(tkIntPlatStubsPtr->tkMacOSXGetHostToplevel) /* 44 */
#define TkMacOSXPreprocessMenu \
	(tkIntPlatStubsPtr->tkMacOSXPreprocessMenu) /* 45 */
#define TkpIsWindowFloating \
	(tkIntPlatStubsPtr->tkpIsWindowFloating) /* 46 */
#define TkMacOSXGetCapture \
	(tkIntPlatStubsPtr->tkMacOSXGetCapture) /* 47 */
#define TkpGetCapture \
	(tkIntPlatStubsPtr->tkpGetCapture) /* 47 */
/* Slot 48 is reserved */
#define TkGetTransientMaster \
	(tkIntPlatStubsPtr->tkGetTransientMaster) /* 49 */
#define TkMacOSXGetContainer \
	(tkIntPlatStubsPtr->tkMacOSXGetContainer) /* 49 */
#define TkGenerateButtonEvent \
	(tkIntPlatStubsPtr->tkGenerateButtonEvent) /* 50 */
#define TkGenWMDestroyEvent \
	(tkIntPlatStubsPtr->tkGenWMDestroyEvent) /* 51 */
#define TkMacOSXSetDrawingEnabled \
	(tkIntPlatStubsPtr->tkMacOSXSetDrawingEnabled) /* 52 */
#define TkpGetMS \
	(tkIntPlatStubsPtr->tkpGetMS) /* 53 */
#define TkMacOSXDrawable \
	(tkIntPlatStubsPtr->tkMacOSXDrawable) /* 54 */
#define TkpScanWindowId \
	(tkIntPlatStubsPtr->tkpScanWindowId) /* 55 */
#endif /* AQUA */
#if !(defined(_WIN32) || defined(__CYGWIN__) || defined(MAC_OSX_TK)) /* X11 */
#define TkCreateXEventSource \
	(tkIntPlatStubsPtr->tkCreateXEventSource) /* 0 */
/* Slot 1 is reserved */
/* Slot 2 is reserved */
#define TkGenerateActivateEvents \
	(tkIntPlatStubsPtr->tkGenerateActivateEvents) /* 2 */
#define TkpCmapStressed \
	(tkIntPlatStubsPtr->tkpCmapStressed) /* 3 */
#define TkpSync \
	(tkIntPlatStubsPtr->tkpSync) /* 4 */
#define TkUnixContainerId \
	(tkIntPlatStubsPtr->tkUnixContainerId) /* 5 */
#define TkUnixDoOneXEvent \
659
660
661
662
663
664
665








































666
667
668
669
670
671











672
673
674



675
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






+
+
+
+
+
+
+
+
+
+
+



+
+
+

#define TkSendCleanup \
	(tkIntPlatStubsPtr->tkSendCleanup) /* 10 */
/* Slot 11 is reserved */
#define TkpWmSetState \
	(tkIntPlatStubsPtr->tkpWmSetState) /* 12 */
#define TkpTestsendCmd \
	(tkIntPlatStubsPtr->tkpTestsendCmd) /* 13 */
/* Slot 14 is reserved */
/* Slot 15 is reserved */
/* Slot 16 is reserved */
/* Slot 17 is reserved */
/* Slot 18 is reserved */
/* Slot 19 is reserved */
/* Slot 20 is reserved */
/* Slot 21 is reserved */
/* Slot 22 is reserved */
/* Slot 23 is reserved */
/* Slot 24 is reserved */
/* Slot 25 is reserved */
/* Slot 26 is reserved */
/* Slot 27 is reserved */
/* Slot 28 is reserved */
/* Slot 29 is reserved */
/* Slot 30 is reserved */
/* Slot 31 is reserved */
/* Slot 32 is reserved */
/* Slot 33 is reserved */
/* Slot 34 is reserved */
/* Slot 35 is reserved */
/* Slot 36 is reserved */
/* Slot 37 is reserved */
#define TkpCmapStressed_ \
	(tkIntPlatStubsPtr->tkpCmapStressed_) /* 38 */
#define TkpSync_ \
	(tkIntPlatStubsPtr->tkpSync_) /* 39 */
#define TkUnixContainerId_ \
	(tkIntPlatStubsPtr->tkUnixContainerId_) /* 40 */
#define TkUnixDoOneXEvent_ \
	(tkIntPlatStubsPtr->tkUnixDoOneXEvent_) /* 41 */
#define TkUnixSetMenubar_ \
	(tkIntPlatStubsPtr->tkUnixSetMenubar_) /* 42 */
#define TkWmCleanup_ \
	(tkIntPlatStubsPtr->tkWmCleanup_) /* 43 */
#define TkSendCleanup_ \
	(tkIntPlatStubsPtr->tkSendCleanup_) /* 44 */
#define TkpTestsendCmd_ \
	(tkIntPlatStubsPtr->tkpTestsendCmd_) /* 45 */
#endif /* X11 */

#endif /* defined(USE_TK_STUBS) */

/* !END!: Do not edit above this line. */

#undef TkpCmapStressed_
#undef TkpSync_
#undef TkUnixContainerId_
#undef TkUnixDoOneXEvent_
#undef TkUnixSetMenubar_
#undef TkWmCleanup_
#undef TkSendCleanup_
#undef TkpTestsendCmd_
#undef TkGenerateActivateEvents_
#undef TkMacOSXSetUpClippingRgn

#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLIMPORT

#undef TkWinGetPlatformId
#define TkWinGetPlatformId() (2) /* VER_PLATFORM_WIN32_NT */

#endif /* _TKINTPLATDECLS */
Changes to generic/tkIntXlibDecls.h.
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

27
28
29



30
31
32
33
34
35
36










37
38
39
40
41
42
43
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

26



27
28
29
30


31
32


33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49








-
+
















-
+
-
-
-
+
+
+

-
-


-
-
+
+
+
+
+
+
+
+
+
+







/*
 * tkIntXlibDecls.h --
 *
 *	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

/*
 * WARNING: This file is automatically generated by the tools/genStubs.tcl
 * script.  Any modifications to the function declarations below should be made
 * in the generic/tkInt.decls script.
 */

#ifndef _TCL
#   include <tcl.h>
#endif

/* Some (older) versions of X11/Xutil.h have a wrong signature of those
#ifndef EXTERN
   two functions, so move them out of the way temporarly. */
#define XOffsetRegion _XOffsetRegion
#define XUnionRegion _XUnionRegion
#   define EXTERN extern TCL_STORAGE_CLASS
#endif

#include "X11/Xutil.h"
#undef XOffsetRegion
#undef XUnionRegion

#ifdef BUILD_tk
#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLEXPORT
#  undef TCL_STORAGE_CLASS
#  define TCL_STORAGE_CLASS DLLEXPORT
#else
#  ifndef TCL_STORAGE_CLASS
#    define TCL_STORAGE_CLASS DLLIMPORT
#  endif
#endif

#if defined(MAC_OSX_TK) && !defined(MAC_OSX_TCL)
#  define MAC_OSX_TCL 1
#endif

typedef int (*XAfterFunction) (	    /* WARNING, this type not in Xlib spec */
    Display*		/* display */
);

/* !BEGIN!: Do not edit below this line. */
409
410
411
412
413
414
415





















































416
417

418
419
420
421
422
423
424
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475

476
477
478
479
480
481
482
483







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+







/* 136 */
EXTERN int		XReparentWindow(Display *d, Window w, Window p,
				int x, int y);
/* 137 */
EXTERN int		XPutImage(Display *d, Drawable dr, GC gc, XImage *im,
				int sx, int sy, int dx, int dy,
				unsigned int w, unsigned int h);
/* 138 */
EXTERN Region		XPolygonRegion(XPoint *pts, int n, int rule);
/* 139 */
EXTERN int		XPointInRegion(Region rgn, int x, int y);
/* 140 */
EXTERN XVaNestedList	XVaCreateNestedList(int dummy, ...);
/* 141 */
EXTERN char *		XSetICValues(XIC xic, ...);
/* 142 */
EXTERN char *		XGetICValues(XIC xic, ...);
/* 143 */
EXTERN void		XSetICFocus(XIC xic);
/* Slot 144 is reserved */
/* Slot 145 is reserved */
/* Slot 146 is reserved */
/* 147 */
EXTERN void		XFreeFontSet(Display *display, XFontSet fontset);
/* 148 */
EXTERN int		XCloseIM(XIM im);
/* 149 */
EXTERN Bool		XRegisterIMInstantiateCallback(Display *dpy,
				struct _XrmHashBucketRec *rbd,
				char *res_name, char *res_class,
				XIDProc callback, XPointer client_data);
/* 150 */
EXTERN Bool		XUnregisterIMInstantiateCallback(Display *dpy,
				struct _XrmHashBucketRec *rbd,
				char *res_name, char *res_class,
				XIDProc callback, XPointer client_data);
/* 151 */
EXTERN char *		XSetLocaleModifiers(const char *modifier_list);
/* 152 */
EXTERN XIM		XOpenIM(Display *dpy, struct _XrmHashBucketRec *rdb,
				char *res_name, char *res_class);
/* 153 */
EXTERN char *		XGetIMValues(XIM im, ...);
/* 154 */
EXTERN char *		XSetIMValues(XIM im, ...);
/* 155 */
EXTERN XFontSet		XCreateFontSet(Display *display,
				_Xconst char *base_font_name_list,
				char ***missing_charset_list,
				int *missing_charset_count,
				char **def_string);
/* 156 */
EXTERN void		XFreeStringList(char **list);
/* 157 */
EXTERN KeySym		XkbKeycodeToKeysym(Display *d, unsigned int k, int g,
				int i);
/* 158 */
EXTERN Display *	XkbOpenDisplay(const char *name, int *ev_rtrn,
				int *err_rtrn, int *major_rtrn,
				int *minor_rtrn, int *reason);
#endif /* WIN */
#ifdef MAC_OSX_TK /* AQUA */
#ifdef MAC_OSX_TCL /* MACOSX */
/* 0 */
EXTERN int		XSetDashes(Display *display, GC gc, int dash_offset,
				_Xconst char *dash_list, int n);
/* 1 */
EXTERN XModifierKeymap * XGetModifierMapping(Display *d);
/* 2 */
EXTERN XImage *		XCreateImage(Display *d, Visual *v, unsigned int ui1,
434
435
436
437
438
439
440
441

442
443
444
445
446
447
448
493
494
495
496
497
498
499

500
501
502
503
504
505
506
507







-
+







EXTERN char *		XKeysymToString(KeySym k);
/* 6 */
EXTERN Colormap		XCreateColormap(Display *d, Window w, Visual *v,
				int i);
/* 7 */
EXTERN GContext		XGContextFromGC(GC g);
/* 8 */
EXTERN KeySym		XKeycodeToKeysym(Display *d, KeyCode k, int i);
EXTERN KeySym		XKeycodeToKeysym(Display *d, unsigned int k, int i);
/* 9 */
EXTERN KeySym		XStringToKeysym(_Xconst char *c);
/* 10 */
EXTERN Window		XRootWindow(Display *d, int i);
/* 11 */
EXTERN XErrorHandler	XSetErrorHandler(XErrorHandler x);
/* 12 */
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694





































695
696
697
698
699
700
701
702
703
704
705
706
707



708
709
710
711
712
713
714
715
716
717













718
719
720
721
722
723
724
725
726
727











728
729
730
731



732
733
734
735




























































736

737
738
739
740
741
742
743
732
733
734
735
736
737
738















739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787

788
789
790
791
792
793
794
795
796
797



798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816




817
818
819
820
821
822
823
824
825
826
827
828
829
830

831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897

898
899
900
901
902
903
904
905







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+












-
+
+
+







-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+






-
-
-
-
+
+
+
+
+
+
+
+
+
+
+



-
+
+
+




+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+







EXTERN int		XQueryColors(Display *display, Colormap colormap,
				XColor *defs_in_out, int ncolors);
/* 90 */
EXTERN Status		XQueryTree(Display *d, Window w1, Window *w2,
				Window *w3, Window **w4, unsigned int *ui);
/* 91 */
EXTERN int		XSync(Display *display, Bool discard);
/* Slot 92 is reserved */
/* Slot 93 is reserved */
/* Slot 94 is reserved */
/* Slot 95 is reserved */
/* Slot 96 is reserved */
/* Slot 97 is reserved */
/* Slot 98 is reserved */
/* Slot 99 is reserved */
/* Slot 100 is reserved */
/* Slot 101 is reserved */
/* Slot 102 is reserved */
/* Slot 103 is reserved */
/* Slot 104 is reserved */
/* Slot 105 is reserved */
/* Slot 106 is reserved */
/* 92 */
EXTERN Bool		XTranslateCoordinates(Display *d, Window w1,
				Window w2, int i1, int i2, int *i3, int *i4,
				Window *w3);
/* 93 */
EXTERN int		XDeleteProperty(Display *d, Window w, Atom a);
/* 94 */
EXTERN int		XFreeCursor(Display *d, Cursor c);
/* 95 */
EXTERN int		XGetInputFocus(Display *d, Window *w, int *i);
/* 96 */
EXTERN int		XmbLookupString(XIC xi, XKeyPressedEvent *xk,
				char *c, int i, KeySym *k, Status *s);
/* 97 */
EXTERN int		XNextEvent(Display *d, XEvent *x);
/* 98 */
EXTERN int		XPutBackEvent(Display *d, XEvent *x);
/* 99 */
EXTERN int		XSetCommand(Display *d, Window w, char **c, int i);
/* 100 */
EXTERN int		XWindowEvent(Display *d, Window w, long l, XEvent *x);
/* 101 */
EXTERN Status		XGetWindowAttributes(Display *d, Window w,
				XWindowAttributes *x);
/* 102 */
EXTERN Status		XGetWMColormapWindows(Display *d, Window w,
				Window **wpp, int *ip);
/* 103 */
EXTERN Status		XIconifyWindow(Display *d, Window w, int i);
/* 104 */
EXTERN Status		XWithdrawWindow(Display *d, Window w, int i);
/* 105 */
EXTERN XHostAddress *	XListHosts(Display *d, int *i, Bool *b);
/* 106 */
EXTERN int		XSetClipRectangles(Display *display, GC gc,
				int clip_x_origin, int clip_y_origin,
				XRectangle rectangles[], int n, int ordering);
/* 107 */
EXTERN int		XFlush(Display *display);
/* 108 */
EXTERN int		XGrabServer(Display *display);
/* 109 */
EXTERN int		XUngrabServer(Display *display);
/* 110 */
EXTERN int		XFree(void *data);
/* 111 */
EXTERN int		XNoOp(Display *display);
/* 112 */
EXTERN XAfterFunction	XSynchronize(Display *display, Bool onoff);
/* Slot 113 is reserved */
/* 113 */
EXTERN Status		XLookupColor(Display *d, Colormap c1,
				_Xconst char *c2, XColor *x1, XColor *x2);
/* 114 */
EXTERN VisualID		XVisualIDFromVisual(Visual *visual);
/* Slot 115 is reserved */
/* Slot 116 is reserved */
/* Slot 117 is reserved */
/* Slot 118 is reserved */
/* Slot 119 is reserved */
/* Slot 120 is reserved */
/* Slot 121 is reserved */
/* Slot 122 is reserved */
/* 120 */
EXTERN int		XOffsetRegion(Region rgn, int dx, int dy);
/* 121 */
EXTERN int		XUnionRegion(Region srca, Region srcb,
				Region dr_return);
/* 122 */
EXTERN Window		XCreateWindow(Display *display, Window parent, int x,
				int y, unsigned int width,
				unsigned int height,
				unsigned int border_width, int depth,
				unsigned int clazz, Visual *visual,
				unsigned long value_mask,
				XSetWindowAttributes *attributes);
/* Slot 123 is reserved */
/* Slot 124 is reserved */
/* Slot 125 is reserved */
/* Slot 126 is reserved */
/* Slot 127 is reserved */
/* Slot 128 is reserved */
/* Slot 129 is reserved */
/* Slot 130 is reserved */
/* Slot 131 is reserved */
/* Slot 132 is reserved */
/* 129 */
EXTERN int		XLowerWindow(Display *d, Window w);
/* 130 */
EXTERN int		XFillArcs(Display *d, Drawable dr, GC gc, XArc *a,
				int n);
/* 131 */
EXTERN int		XDrawArcs(Display *d, Drawable dr, GC gc, XArc *a,
				int n);
/* 132 */
EXTERN int		XDrawRectangles(Display *d, Drawable dr, GC gc,
				XRectangle *r, int n);
/* Slot 133 is reserved */
/* Slot 134 is reserved */
/* Slot 135 is reserved */
/* Slot 136 is reserved */
/* 136 */
EXTERN int		XReparentWindow(Display *d, Window w, Window p,
				int x, int y);
/* 137 */
EXTERN int		XPutImage(Display *d, Drawable dr, GC gc, XImage *im,
				int sx, int sy, int dx, int dy,
				unsigned int w, unsigned int h);
/* 138 */
EXTERN Region		XPolygonRegion(XPoint *pts, int n, int rule);
/* 139 */
EXTERN int		XPointInRegion(Region rgn, int x, int y);
/* 140 */
EXTERN XVaNestedList	XVaCreateNestedList(int dummy, ...);
/* 141 */
EXTERN char *		XSetICValues(XIC xic, ...);
/* 142 */
EXTERN char *		XGetICValues(XIC xic, ...);
/* 143 */
EXTERN void		XSetICFocus(XIC xic);
/* 144 */
EXTERN void		XDestroyIC(XIC xic);
/* 145 */
EXTERN Cursor		XCreatePixmapCursor(Display *d, Pixmap p1, Pixmap p2,
				XColor *x1, XColor *x2, unsigned int ui1,
				unsigned int ui2);
/* 146 */
EXTERN Cursor		XCreateGlyphCursor(Display *d, Font f1, Font f2,
				unsigned int ui1, unsigned int ui2,
				XColor _Xconst *x1, XColor _Xconst *x2);
/* 147 */
EXTERN void		XFreeFontSet(Display *display, XFontSet fontset);
/* 148 */
EXTERN int		XCloseIM(XIM im);
/* 149 */
EXTERN Bool		XRegisterIMInstantiateCallback(Display *dpy,
				struct _XrmHashBucketRec *rbd,
				char *res_name, char *res_class,
				XIDProc callback, XPointer client_data);
/* 150 */
EXTERN Bool		XUnregisterIMInstantiateCallback(Display *dpy,
				struct _XrmHashBucketRec *rbd,
				char *res_name, char *res_class,
				XIDProc callback, XPointer client_data);
/* 151 */
EXTERN char *		XSetLocaleModifiers(const char *modifier_list);
/* 152 */
EXTERN XIM		XOpenIM(Display *dpy, struct _XrmHashBucketRec *rdb,
				char *res_name, char *res_class);
/* 153 */
EXTERN char *		XGetIMValues(XIM im, ...);
/* 154 */
EXTERN char *		XSetIMValues(XIM im, ...);
/* 155 */
EXTERN XFontSet		XCreateFontSet(Display *display,
				_Xconst char *base_font_name_list,
				char ***missing_charset_list,
				int *missing_charset_count,
				char **def_string);
/* 156 */
EXTERN void		XFreeStringList(char **list);
/* 157 */
EXTERN KeySym		XkbKeycodeToKeysym(Display *d, unsigned int k, int g,
				int i);
/* 158 */
EXTERN Display *	XkbOpenDisplay(const char *name, int *ev_rtrn,
				int *err_rtrn, int *major_rtrn,
				int *minor_rtrn, int *reason);
#endif /* AQUA */
#endif /* MACOSX */

typedef struct TkIntXlibStubs {
    int magic;
    void *hooks;

#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
    int (*xSetDashes) (Display *display, GC gc, int dash_offset, _Xconst char *dash_list, int n); /* 0 */
874
875
876
877
878
879
880





















881
882

883
884
885
886
887
888
889
890
891

892
893
894
895
896
897
898
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064

1065
1066
1067
1068
1069
1070
1071
1072
1073

1074
1075
1076
1077
1078
1079
1080
1081







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+








-
+







    int (*xDrawArcs) (Display *d, Drawable dr, GC gc, XArc *a, int n); /* 131 */
    int (*xDrawRectangles) (Display *d, Drawable dr, GC gc, XRectangle *r, int n); /* 132 */
    int (*xDrawSegments) (Display *d, Drawable dr, GC gc, XSegment *s, int n); /* 133 */
    int (*xDrawPoint) (Display *d, Drawable dr, GC gc, int x, int y); /* 134 */
    int (*xDrawPoints) (Display *d, Drawable dr, GC gc, XPoint *p, int n, int m); /* 135 */
    int (*xReparentWindow) (Display *d, Window w, Window p, int x, int y); /* 136 */
    int (*xPutImage) (Display *d, Drawable dr, GC gc, XImage *im, int sx, int sy, int dx, int dy, unsigned int w, unsigned int h); /* 137 */
    Region (*xPolygonRegion) (XPoint *pts, int n, int rule); /* 138 */
    int (*xPointInRegion) (Region rgn, int x, int y); /* 139 */
    XVaNestedList (*xVaCreateNestedList) (int dummy, ...); /* 140 */
    char * (*xSetICValues) (XIC xic, ...); /* 141 */
    char * (*xGetICValues) (XIC xic, ...); /* 142 */
    void (*xSetICFocus) (XIC xic); /* 143 */
    void (*reserved144)(void);
    void (*reserved145)(void);
    void (*reserved146)(void);
    void (*xFreeFontSet) (Display *display, XFontSet fontset); /* 147 */
    int (*xCloseIM) (XIM im); /* 148 */
    Bool (*xRegisterIMInstantiateCallback) (Display *dpy, struct _XrmHashBucketRec *rbd, char *res_name, char *res_class, XIDProc callback, XPointer client_data); /* 149 */
    Bool (*xUnregisterIMInstantiateCallback) (Display *dpy, struct _XrmHashBucketRec *rbd, char *res_name, char *res_class, XIDProc callback, XPointer client_data); /* 150 */
    char * (*xSetLocaleModifiers) (const char *modifier_list); /* 151 */
    XIM (*xOpenIM) (Display *dpy, struct _XrmHashBucketRec *rdb, char *res_name, char *res_class); /* 152 */
    char * (*xGetIMValues) (XIM im, ...); /* 153 */
    char * (*xSetIMValues) (XIM im, ...); /* 154 */
    XFontSet (*xCreateFontSet) (Display *display, _Xconst char *base_font_name_list, char ***missing_charset_list, int *missing_charset_count, char **def_string); /* 155 */
    void (*xFreeStringList) (char **list); /* 156 */
    KeySym (*xkbKeycodeToKeysym) (Display *d, unsigned int k, int g, int i); /* 157 */
    Display * (*xkbOpenDisplay) (const char *name, int *ev_rtrn, int *err_rtrn, int *major_rtrn, int *minor_rtrn, int *reason); /* 158 */
#endif /* WIN */
#ifdef MAC_OSX_TK /* AQUA */
#ifdef MAC_OSX_TCL /* MACOSX */
    int (*xSetDashes) (Display *display, GC gc, int dash_offset, _Xconst char *dash_list, int n); /* 0 */
    XModifierKeymap * (*xGetModifierMapping) (Display *d); /* 1 */
    XImage * (*xCreateImage) (Display *d, Visual *v, unsigned int ui1, int i1, int i2, char *cp, unsigned int ui2, unsigned int ui3, int i3, int i4); /* 2 */
    XImage * (*xGetImage) (Display *d, Drawable dr, int i1, int i2, unsigned int ui1, unsigned int ui2, unsigned long ul, int i3); /* 3 */
    char * (*xGetAtomName) (Display *d, Atom a); /* 4 */
    char * (*xKeysymToString) (KeySym k); /* 5 */
    Colormap (*xCreateColormap) (Display *d, Window w, Visual *v, int i); /* 6 */
    GContext (*xGContextFromGC) (GC g); /* 7 */
    KeySym (*xKeycodeToKeysym) (Display *d, KeyCode k, int i); /* 8 */
    KeySym (*xKeycodeToKeysym) (Display *d, unsigned int k, int i); /* 8 */
    KeySym (*xStringToKeysym) (_Xconst char *c); /* 9 */
    Window (*xRootWindow) (Display *d, int i); /* 10 */
    XErrorHandler (*xSetErrorHandler) (XErrorHandler x); /* 11 */
    Status (*xAllocColor) (Display *d, Colormap c, XColor *xp); /* 12 */
    int (*xBell) (Display *d, int i); /* 13 */
    int (*xChangeProperty) (Display *d, Window w, Atom a1, Atom a2, int i1, int i2, _Xconst unsigned char *c, int i3); /* 14 */
    int (*xChangeWindowAttributes) (Display *d, Window w, unsigned long ul, XSetWindowAttributes *x); /* 15 */
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989















990
991
992
993
994
995
996

997
998
999
1000
1001
1002
1003
1004
1005



1006
1007
1008
1009
1010
1011
1012
1013
1014
1015




1016
1017
1018
1019

1020





















1021

1022
1023
1024
1025
1026
1027
1028
1151
1152
1153
1154
1155
1156
1157















1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178

1179
1180
1181
1182
1183
1184
1185



1186
1187
1188
1189
1190
1191
1192
1193
1194




1195
1196
1197
1198
1199
1200
1201

1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224

1225
1226
1227
1228
1229
1230
1231
1232







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






-
+






-
-
-
+
+
+






-
-
-
-
+
+
+
+



-
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+







    int (*xDrawPoint) (Display *display, Drawable d, GC gc, int x, int y); /* 85 */
    int (*xDrawPoints) (Display *display, Drawable d, GC gc, XPoint *points, int npoints, int mode); /* 86 */
    int (*xWarpPointer) (Display *display, Window src_w, Window dest_w, int src_x, int src_y, unsigned int src_width, unsigned int src_height, int dest_x, int dest_y); /* 87 */
    int (*xQueryColor) (Display *display, Colormap colormap, XColor *def_in_out); /* 88 */
    int (*xQueryColors) (Display *display, Colormap colormap, XColor *defs_in_out, int ncolors); /* 89 */
    Status (*xQueryTree) (Display *d, Window w1, Window *w2, Window *w3, Window **w4, unsigned int *ui); /* 90 */
    int (*xSync) (Display *display, Bool discard); /* 91 */
    void (*reserved92)(void);
    void (*reserved93)(void);
    void (*reserved94)(void);
    void (*reserved95)(void);
    void (*reserved96)(void);
    void (*reserved97)(void);
    void (*reserved98)(void);
    void (*reserved99)(void);
    void (*reserved100)(void);
    void (*reserved101)(void);
    void (*reserved102)(void);
    void (*reserved103)(void);
    void (*reserved104)(void);
    void (*reserved105)(void);
    void (*reserved106)(void);
    Bool (*xTranslateCoordinates) (Display *d, Window w1, Window w2, int i1, int i2, int *i3, int *i4, Window *w3); /* 92 */
    int (*xDeleteProperty) (Display *d, Window w, Atom a); /* 93 */
    int (*xFreeCursor) (Display *d, Cursor c); /* 94 */
    int (*xGetInputFocus) (Display *d, Window *w, int *i); /* 95 */
    int (*xmbLookupString) (XIC xi, XKeyPressedEvent *xk, char *c, int i, KeySym *k, Status *s); /* 96 */
    int (*xNextEvent) (Display *d, XEvent *x); /* 97 */
    int (*xPutBackEvent) (Display *d, XEvent *x); /* 98 */
    int (*xSetCommand) (Display *d, Window w, char **c, int i); /* 99 */
    int (*xWindowEvent) (Display *d, Window w, long l, XEvent *x); /* 100 */
    Status (*xGetWindowAttributes) (Display *d, Window w, XWindowAttributes *x); /* 101 */
    Status (*xGetWMColormapWindows) (Display *d, Window w, Window **wpp, int *ip); /* 102 */
    Status (*xIconifyWindow) (Display *d, Window w, int i); /* 103 */
    Status (*xWithdrawWindow) (Display *d, Window w, int i); /* 104 */
    XHostAddress * (*xListHosts) (Display *d, int *i, Bool *b); /* 105 */
    int (*xSetClipRectangles) (Display *display, GC gc, int clip_x_origin, int clip_y_origin, XRectangle rectangles[], int n, int ordering); /* 106 */
    int (*xFlush) (Display *display); /* 107 */
    int (*xGrabServer) (Display *display); /* 108 */
    int (*xUngrabServer) (Display *display); /* 109 */
    int (*xFree) (void *data); /* 110 */
    int (*xNoOp) (Display *display); /* 111 */
    XAfterFunction (*xSynchronize) (Display *display, Bool onoff); /* 112 */
    void (*reserved113)(void);
    Status (*xLookupColor) (Display *d, Colormap c1, _Xconst char *c2, XColor *x1, XColor *x2); /* 113 */
    VisualID (*xVisualIDFromVisual) (Visual *visual); /* 114 */
    void (*reserved115)(void);
    void (*reserved116)(void);
    void (*reserved117)(void);
    void (*reserved118)(void);
    void (*reserved119)(void);
    void (*reserved120)(void);
    void (*reserved121)(void);
    void (*reserved122)(void);
    int (*xOffsetRegion) (Region rgn, int dx, int dy); /* 120 */
    int (*xUnionRegion) (Region srca, Region srcb, Region dr_return); /* 121 */
    Window (*xCreateWindow) (Display *display, Window parent, int x, int y, unsigned int width, unsigned int height, unsigned int border_width, int depth, unsigned int clazz, Visual *visual, unsigned long value_mask, XSetWindowAttributes *attributes); /* 122 */
    void (*reserved123)(void);
    void (*reserved124)(void);
    void (*reserved125)(void);
    void (*reserved126)(void);
    void (*reserved127)(void);
    void (*reserved128)(void);
    void (*reserved129)(void);
    void (*reserved130)(void);
    void (*reserved131)(void);
    void (*reserved132)(void);
    int (*xLowerWindow) (Display *d, Window w); /* 129 */
    int (*xFillArcs) (Display *d, Drawable dr, GC gc, XArc *a, int n); /* 130 */
    int (*xDrawArcs) (Display *d, Drawable dr, GC gc, XArc *a, int n); /* 131 */
    int (*xDrawRectangles) (Display *d, Drawable dr, GC gc, XRectangle *r, int n); /* 132 */
    void (*reserved133)(void);
    void (*reserved134)(void);
    void (*reserved135)(void);
    void (*reserved136)(void);
    int (*xReparentWindow) (Display *d, Window w, Window p, int x, int y); /* 136 */
    int (*xPutImage) (Display *d, Drawable dr, GC gc, XImage *im, int sx, int sy, int dx, int dy, unsigned int w, unsigned int h); /* 137 */
    Region (*xPolygonRegion) (XPoint *pts, int n, int rule); /* 138 */
    int (*xPointInRegion) (Region rgn, int x, int y); /* 139 */
    XVaNestedList (*xVaCreateNestedList) (int dummy, ...); /* 140 */
    char * (*xSetICValues) (XIC xic, ...); /* 141 */
    char * (*xGetICValues) (XIC xic, ...); /* 142 */
    void (*xSetICFocus) (XIC xic); /* 143 */
    void (*xDestroyIC) (XIC xic); /* 144 */
    Cursor (*xCreatePixmapCursor) (Display *d, Pixmap p1, Pixmap p2, XColor *x1, XColor *x2, unsigned int ui1, unsigned int ui2); /* 145 */
    Cursor (*xCreateGlyphCursor) (Display *d, Font f1, Font f2, unsigned int ui1, unsigned int ui2, XColor _Xconst *x1, XColor _Xconst *x2); /* 146 */
    void (*xFreeFontSet) (Display *display, XFontSet fontset); /* 147 */
    int (*xCloseIM) (XIM im); /* 148 */
    Bool (*xRegisterIMInstantiateCallback) (Display *dpy, struct _XrmHashBucketRec *rbd, char *res_name, char *res_class, XIDProc callback, XPointer client_data); /* 149 */
    Bool (*xUnregisterIMInstantiateCallback) (Display *dpy, struct _XrmHashBucketRec *rbd, char *res_name, char *res_class, XIDProc callback, XPointer client_data); /* 150 */
    char * (*xSetLocaleModifiers) (const char *modifier_list); /* 151 */
    XIM (*xOpenIM) (Display *dpy, struct _XrmHashBucketRec *rdb, char *res_name, char *res_class); /* 152 */
    char * (*xGetIMValues) (XIM im, ...); /* 153 */
    char * (*xSetIMValues) (XIM im, ...); /* 154 */
    XFontSet (*xCreateFontSet) (Display *display, _Xconst char *base_font_name_list, char ***missing_charset_list, int *missing_charset_count, char **def_string); /* 155 */
    void (*xFreeStringList) (char **list); /* 156 */
    KeySym (*xkbKeycodeToKeysym) (Display *d, unsigned int k, int g, int i); /* 157 */
    Display * (*xkbOpenDisplay) (const char *name, int *ev_rtrn, int *err_rtrn, int *major_rtrn, int *minor_rtrn, int *reason); /* 158 */
#endif /* AQUA */
#endif /* MACOSX */
} TkIntXlibStubs;

extern const TkIntXlibStubs *tkIntXlibStubsPtr;

#ifdef __cplusplus
}
#endif
1294
1295
1296
1297
1298
1299
1300







































1301
1302

1303
1304
1305
1306
1307
1308
1309
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544

1545
1546
1547
1548
1549
1550
1551
1552







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+







	(tkIntXlibStubsPtr->xDrawPoint) /* 134 */
#define XDrawPoints \
	(tkIntXlibStubsPtr->xDrawPoints) /* 135 */
#define XReparentWindow \
	(tkIntXlibStubsPtr->xReparentWindow) /* 136 */
#define XPutImage \
	(tkIntXlibStubsPtr->xPutImage) /* 137 */
#define XPolygonRegion \
	(tkIntXlibStubsPtr->xPolygonRegion) /* 138 */
#define XPointInRegion \
	(tkIntXlibStubsPtr->xPointInRegion) /* 139 */
#define XVaCreateNestedList \
	(tkIntXlibStubsPtr->xVaCreateNestedList) /* 140 */
#define XSetICValues \
	(tkIntXlibStubsPtr->xSetICValues) /* 141 */
#define XGetICValues \
	(tkIntXlibStubsPtr->xGetICValues) /* 142 */
#define XSetICFocus \
	(tkIntXlibStubsPtr->xSetICFocus) /* 143 */
/* Slot 144 is reserved */
/* Slot 145 is reserved */
/* Slot 146 is reserved */
#define XFreeFontSet \
	(tkIntXlibStubsPtr->xFreeFontSet) /* 147 */
#define XCloseIM \
	(tkIntXlibStubsPtr->xCloseIM) /* 148 */
#define XRegisterIMInstantiateCallback \
	(tkIntXlibStubsPtr->xRegisterIMInstantiateCallback) /* 149 */
#define XUnregisterIMInstantiateCallback \
	(tkIntXlibStubsPtr->xUnregisterIMInstantiateCallback) /* 150 */
#define XSetLocaleModifiers \
	(tkIntXlibStubsPtr->xSetLocaleModifiers) /* 151 */
#define XOpenIM \
	(tkIntXlibStubsPtr->xOpenIM) /* 152 */
#define XGetIMValues \
	(tkIntXlibStubsPtr->xGetIMValues) /* 153 */
#define XSetIMValues \
	(tkIntXlibStubsPtr->xSetIMValues) /* 154 */
#define XCreateFontSet \
	(tkIntXlibStubsPtr->xCreateFontSet) /* 155 */
#define XFreeStringList \
	(tkIntXlibStubsPtr->xFreeStringList) /* 156 */
#define XkbKeycodeToKeysym \
	(tkIntXlibStubsPtr->xkbKeycodeToKeysym) /* 157 */
#define XkbOpenDisplay \
	(tkIntXlibStubsPtr->xkbOpenDisplay) /* 158 */
#endif /* WIN */
#ifdef MAC_OSX_TK /* AQUA */
#ifdef MAC_OSX_TCL /* MACOSX */
#define XSetDashes \
	(tkIntXlibStubsPtr->xSetDashes) /* 0 */
#define XGetModifierMapping \
	(tkIntXlibStubsPtr->xGetModifierMapping) /* 1 */
#define XCreateImage \
	(tkIntXlibStubsPtr->xCreateImage) /* 2 */
#define XGetImage \
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501






























1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513

1514

1515
1516
1517
1518
1519
1520
1521

1522
1523
1524





1525
1526
1527
1528
1529
1530

1531
1532
1533
1534







1535
1536
1537

1538

1539
1540










































1541

1542
1543
1544
1545




1546
1547
1548
1549
1550
1723
1724
1725
1726
1727
1728
1729















1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772

1773
1774
1775
1776
1777
1778
1779
1780
1781



1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793




1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804

1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849

1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+












+
-
+







+
-
-
-
+
+
+
+
+






+
-
-
-
-
+
+
+
+
+
+
+



+
-
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+




+
+
+
+





	(tkIntXlibStubsPtr->xQueryColor) /* 88 */
#define XQueryColors \
	(tkIntXlibStubsPtr->xQueryColors) /* 89 */
#define XQueryTree \
	(tkIntXlibStubsPtr->xQueryTree) /* 90 */
#define XSync \
	(tkIntXlibStubsPtr->xSync) /* 91 */
/* Slot 92 is reserved */
/* Slot 93 is reserved */
/* Slot 94 is reserved */
/* Slot 95 is reserved */
/* Slot 96 is reserved */
/* Slot 97 is reserved */
/* Slot 98 is reserved */
/* Slot 99 is reserved */
/* Slot 100 is reserved */
/* Slot 101 is reserved */
/* Slot 102 is reserved */
/* Slot 103 is reserved */
/* Slot 104 is reserved */
/* Slot 105 is reserved */
/* Slot 106 is reserved */
#define XTranslateCoordinates \
	(tkIntXlibStubsPtr->xTranslateCoordinates) /* 92 */
#define XDeleteProperty \
	(tkIntXlibStubsPtr->xDeleteProperty) /* 93 */
#define XFreeCursor \
	(tkIntXlibStubsPtr->xFreeCursor) /* 94 */
#define XGetInputFocus \
	(tkIntXlibStubsPtr->xGetInputFocus) /* 95 */
#define XmbLookupString \
	(tkIntXlibStubsPtr->xmbLookupString) /* 96 */
#define XNextEvent \
	(tkIntXlibStubsPtr->xNextEvent) /* 97 */
#define XPutBackEvent \
	(tkIntXlibStubsPtr->xPutBackEvent) /* 98 */
#define XSetCommand \
	(tkIntXlibStubsPtr->xSetCommand) /* 99 */
#define XWindowEvent \
	(tkIntXlibStubsPtr->xWindowEvent) /* 100 */
#define XGetWindowAttributes \
	(tkIntXlibStubsPtr->xGetWindowAttributes) /* 101 */
#define XGetWMColormapWindows \
	(tkIntXlibStubsPtr->xGetWMColormapWindows) /* 102 */
#define XIconifyWindow \
	(tkIntXlibStubsPtr->xIconifyWindow) /* 103 */
#define XWithdrawWindow \
	(tkIntXlibStubsPtr->xWithdrawWindow) /* 104 */
#define XListHosts \
	(tkIntXlibStubsPtr->xListHosts) /* 105 */
#define XSetClipRectangles \
	(tkIntXlibStubsPtr->xSetClipRectangles) /* 106 */
#define XFlush \
	(tkIntXlibStubsPtr->xFlush) /* 107 */
#define XGrabServer \
	(tkIntXlibStubsPtr->xGrabServer) /* 108 */
#define XUngrabServer \
	(tkIntXlibStubsPtr->xUngrabServer) /* 109 */
#define XFree \
	(tkIntXlibStubsPtr->xFree) /* 110 */
#define XNoOp \
	(tkIntXlibStubsPtr->xNoOp) /* 111 */
#define XSynchronize \
	(tkIntXlibStubsPtr->xSynchronize) /* 112 */
#define XLookupColor \
/* Slot 113 is reserved */
	(tkIntXlibStubsPtr->xLookupColor) /* 113 */
#define XVisualIDFromVisual \
	(tkIntXlibStubsPtr->xVisualIDFromVisual) /* 114 */
/* Slot 115 is reserved */
/* Slot 116 is reserved */
/* Slot 117 is reserved */
/* Slot 118 is reserved */
/* Slot 119 is reserved */
#define XOffsetRegion \
/* Slot 120 is reserved */
/* Slot 121 is reserved */
/* Slot 122 is reserved */
	(tkIntXlibStubsPtr->xOffsetRegion) /* 120 */
#define XUnionRegion \
	(tkIntXlibStubsPtr->xUnionRegion) /* 121 */
#define XCreateWindow \
	(tkIntXlibStubsPtr->xCreateWindow) /* 122 */
/* Slot 123 is reserved */
/* Slot 124 is reserved */
/* Slot 125 is reserved */
/* Slot 126 is reserved */
/* Slot 127 is reserved */
/* Slot 128 is reserved */
#define XLowerWindow \
/* Slot 129 is reserved */
/* Slot 130 is reserved */
/* Slot 131 is reserved */
/* Slot 132 is reserved */
	(tkIntXlibStubsPtr->xLowerWindow) /* 129 */
#define XFillArcs \
	(tkIntXlibStubsPtr->xFillArcs) /* 130 */
#define XDrawArcs \
	(tkIntXlibStubsPtr->xDrawArcs) /* 131 */
#define XDrawRectangles \
	(tkIntXlibStubsPtr->xDrawRectangles) /* 132 */
/* Slot 133 is reserved */
/* Slot 134 is reserved */
/* Slot 135 is reserved */
#define XReparentWindow \
/* Slot 136 is reserved */
	(tkIntXlibStubsPtr->xReparentWindow) /* 136 */
#define XPutImage \
	(tkIntXlibStubsPtr->xPutImage) /* 137 */
#define XPolygonRegion \
	(tkIntXlibStubsPtr->xPolygonRegion) /* 138 */
#define XPointInRegion \
	(tkIntXlibStubsPtr->xPointInRegion) /* 139 */
#define XVaCreateNestedList \
	(tkIntXlibStubsPtr->xVaCreateNestedList) /* 140 */
#define XSetICValues \
	(tkIntXlibStubsPtr->xSetICValues) /* 141 */
#define XGetICValues \
	(tkIntXlibStubsPtr->xGetICValues) /* 142 */
#define XSetICFocus \
	(tkIntXlibStubsPtr->xSetICFocus) /* 143 */
#define XDestroyIC \
	(tkIntXlibStubsPtr->xDestroyIC) /* 144 */
#define XCreatePixmapCursor \
	(tkIntXlibStubsPtr->xCreatePixmapCursor) /* 145 */
#define XCreateGlyphCursor \
	(tkIntXlibStubsPtr->xCreateGlyphCursor) /* 146 */
#define XFreeFontSet \
	(tkIntXlibStubsPtr->xFreeFontSet) /* 147 */
#define XCloseIM \
	(tkIntXlibStubsPtr->xCloseIM) /* 148 */
#define XRegisterIMInstantiateCallback \
	(tkIntXlibStubsPtr->xRegisterIMInstantiateCallback) /* 149 */
#define XUnregisterIMInstantiateCallback \
	(tkIntXlibStubsPtr->xUnregisterIMInstantiateCallback) /* 150 */
#define XSetLocaleModifiers \
	(tkIntXlibStubsPtr->xSetLocaleModifiers) /* 151 */
#define XOpenIM \
	(tkIntXlibStubsPtr->xOpenIM) /* 152 */
#define XGetIMValues \
	(tkIntXlibStubsPtr->xGetIMValues) /* 153 */
#define XSetIMValues \
	(tkIntXlibStubsPtr->xSetIMValues) /* 154 */
#define XCreateFontSet \
	(tkIntXlibStubsPtr->xCreateFontSet) /* 155 */
#define XFreeStringList \
	(tkIntXlibStubsPtr->xFreeStringList) /* 156 */
#define XkbKeycodeToKeysym \
	(tkIntXlibStubsPtr->xkbKeycodeToKeysym) /* 157 */
#define XkbOpenDisplay \
	(tkIntXlibStubsPtr->xkbOpenDisplay) /* 158 */
#endif /* AQUA */
#endif /* MACOSX */

#endif /* defined(USE_TK_STUBS) */

/* !END!: Do not edit above this line. */

#if !defined(_WIN32) && !defined(__CYGWIN__) && !defined(MAC_OSX_TCL) /* X11, Except MacOS/Cygwin */
EXTERN Display *XkbOpenDisplay(const char *, int *, int *, int *, int *, int *);
#endif

#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLIMPORT

#endif /* _TKINTXLIBDECLS */
Changes to generic/tkListbox.c.
1
2
3
4
5
6
7
8
9


10
11
12
13
14
15
16


17
18
19
20
21
22
23
1
2
3
4
5
6
7


8
9
10
11
12
13
14


15
16
17
18
19
20
21
22
23







-
-
+
+





-
-
+
+







/*
 * tkListbox.c --
 *
 *	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.
 */

#include "default.h"
#include "tkInt.h"
#include "tkInt.h"
#include "default.h"

#ifdef _WIN32
#include "tkWinInt.h"
#endif

typedef struct {
    Tk_OptionTable listboxOptionTable;
235
236
237
238
239
240
241
242

243
244
245

246
247
248

249
250

251
252

253
254
255

256
257
258
259


260
261
262


263
264

265
266

267
268

269
270

271
272
273


274
275

276
277
278
279


280
281

282
283

284
285

286
287
288
289


290
291

292
293
294

295
296
297

298
299

300
301
302

303
304
305

306
307

308
309
310

311
312
313

314
315

316
317
318
319
320
321
322
323
324
325

326
327
328
329

330
331

332
333

334
335
336

337
338
339
340

341
342
343

344
345
346
347
348
349
350
235
236
237
238
239
240
241

242
243
244

245
246
247

248
249

250
251

252
253
254

255
256
257


258
259
260


261
262
263

264
265

266
267

268
269

270
271


272
273
274

275
276
277


278
279
280

281
282

283
284

285
286
287


288
289
290

291
292
293

294
295
296

297
298

299
300
301

302
303
304

305
306

307
308
309

310
311
312

313
314

315
316
317
318
319
320
321
322
323
324

325
326
327
328

329
330

331
332

333
334
335

336
337
338
339

340
341
342

343
344
345
346
347
348
349
350







-
+


-
+


-
+

-
+

-
+


-
+


-
-
+
+

-
-
+
+

-
+

-
+

-
+

-
+

-
-
+
+

-
+


-
-
+
+

-
+

-
+

-
+


-
-
+
+

-
+


-
+


-
+

-
+


-
+


-
+

-
+


-
+


-
+

-
+









-
+



-
+

-
+

-
+


-
+



-
+


-
+







/*
 * The optionSpecs table defines the valid configuration options for the
 * listbox widget.
 */

static const Tk_OptionSpec optionSpecs[] = {
    {TK_OPTION_STRING_TABLE, "-activestyle", "activeStyle", "ActiveStyle",
	DEF_LISTBOX_ACTIVE_STYLE, -1, Tk_Offset(Listbox, activeStyle),
	DEF_LISTBOX_ACTIVE_STYLE, TCL_INDEX_NONE, offsetof(Listbox, activeStyle),
	0, activeStyleStrings, 0},
    {TK_OPTION_BORDER, "-background", "background", "Background",
	 DEF_LISTBOX_BG_COLOR, -1, Tk_Offset(Listbox, normalBorder),
	 DEF_LISTBOX_BG_COLOR, TCL_INDEX_NONE, offsetof(Listbox, normalBorder),
	 0, DEF_LISTBOX_BG_MONO, 0},
    {TK_OPTION_SYNONYM, "-bd", NULL, NULL,
	 NULL, 0, -1, 0, "-borderwidth", 0},
	 NULL, 0, TCL_INDEX_NONE, 0, "-borderwidth", 0},
    {TK_OPTION_SYNONYM, "-bg", NULL, NULL,
	 NULL, 0, -1, 0, "-background", 0},
	 NULL, 0, TCL_INDEX_NONE, 0, "-background", 0},
    {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
	 DEF_LISTBOX_BORDER_WIDTH, -1, Tk_Offset(Listbox, borderWidth),
	 DEF_LISTBOX_BORDER_WIDTH, TCL_INDEX_NONE, offsetof(Listbox, borderWidth),
	 0, 0, 0},
    {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
	 DEF_LISTBOX_CURSOR, -1, Tk_Offset(Listbox, cursor),
	 DEF_LISTBOX_CURSOR, TCL_INDEX_NONE, offsetof(Listbox, cursor),
	 TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground",
	 "DisabledForeground", DEF_LISTBOX_DISABLED_FG, -1,
	 Tk_Offset(Listbox, dfgColorPtr), TK_OPTION_NULL_OK, 0, 0},
	 "DisabledForeground", DEF_LISTBOX_DISABLED_FG, TCL_INDEX_NONE,
	 offsetof(Listbox, dfgColorPtr), TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_BOOLEAN, "-exportselection", "exportSelection",
	 "ExportSelection", DEF_LISTBOX_EXPORT_SELECTION, -1,
	 Tk_Offset(Listbox, exportSelection), 0, 0, 0},
	 "ExportSelection", DEF_LISTBOX_EXPORT_SELECTION, TCL_INDEX_NONE,
	 offsetof(Listbox, exportSelection), 0, 0, 0},
    {TK_OPTION_SYNONYM, "-fg", "foreground", NULL,
	 NULL, 0, -1, 0, "-foreground", 0},
	 NULL, 0, TCL_INDEX_NONE, 0, "-foreground", 0},
    {TK_OPTION_FONT, "-font", "font", "Font",
	 DEF_LISTBOX_FONT, -1, Tk_Offset(Listbox, tkfont), 0, 0, 0},
	 DEF_LISTBOX_FONT, TCL_INDEX_NONE, offsetof(Listbox, tkfont), 0, 0, 0},
    {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
	 DEF_LISTBOX_FG, -1, Tk_Offset(Listbox, fgColorPtr), 0, 0, 0},
	 DEF_LISTBOX_FG, TCL_INDEX_NONE, offsetof(Listbox, fgColorPtr), 0, 0, 0},
    {TK_OPTION_INT, "-height", "height", "Height",
	 DEF_LISTBOX_HEIGHT, -1, Tk_Offset(Listbox, height), 0, 0, 0},
	 DEF_LISTBOX_HEIGHT, TCL_INDEX_NONE, offsetof(Listbox, height), 0, 0, 0},
    {TK_OPTION_COLOR, "-highlightbackground", "highlightBackground",
	 "HighlightBackground", DEF_LISTBOX_HIGHLIGHT_BG, -1,
	 Tk_Offset(Listbox, highlightBgColorPtr), 0, 0, 0},
	 "HighlightBackground", DEF_LISTBOX_HIGHLIGHT_BG, TCL_INDEX_NONE,
	 offsetof(Listbox, highlightBgColorPtr), 0, 0, 0},
    {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
	 DEF_LISTBOX_HIGHLIGHT, -1, Tk_Offset(Listbox, highlightColorPtr),
	 DEF_LISTBOX_HIGHLIGHT, TCL_INDEX_NONE, offsetof(Listbox, highlightColorPtr),
	 0, 0, 0},
    {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
	 "HighlightThickness", DEF_LISTBOX_HIGHLIGHT_WIDTH, -1,
	 Tk_Offset(Listbox, highlightWidth), 0, 0, 0},
	 "HighlightThickness", DEF_LISTBOX_HIGHLIGHT_WIDTH, TCL_INDEX_NONE,
	 offsetof(Listbox, highlightWidth), 0, 0, 0},
    {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",
	DEF_LISTBOX_JUSTIFY, -1, Tk_Offset(Listbox, justify), 0, 0, 0},
	DEF_LISTBOX_JUSTIFY, TCL_INDEX_NONE, offsetof(Listbox, justify), 0, 0, 0},
    {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
	 DEF_LISTBOX_RELIEF, -1, Tk_Offset(Listbox, relief), 0, 0, 0},
	 DEF_LISTBOX_RELIEF, TCL_INDEX_NONE, offsetof(Listbox, relief), 0, 0, 0},
    {TK_OPTION_BORDER, "-selectbackground", "selectBackground", "Foreground",
	 DEF_LISTBOX_SELECT_COLOR, -1, Tk_Offset(Listbox, selBorder),
	 DEF_LISTBOX_SELECT_COLOR, TCL_INDEX_NONE, offsetof(Listbox, selBorder),
	 0, DEF_LISTBOX_SELECT_MONO, 0},
    {TK_OPTION_PIXELS, "-selectborderwidth", "selectBorderWidth",
	 "BorderWidth", DEF_LISTBOX_SELECT_BD, -1,
	 Tk_Offset(Listbox, selBorderWidth), 0, 0, 0},
	 "BorderWidth", DEF_LISTBOX_SELECT_BD, TCL_INDEX_NONE,
	 offsetof(Listbox, selBorderWidth), 0, 0, 0},
    {TK_OPTION_COLOR, "-selectforeground", "selectForeground", "Background",
	 DEF_LISTBOX_SELECT_FG_COLOR, -1, Tk_Offset(Listbox, selFgColorPtr),
	 DEF_LISTBOX_SELECT_FG_COLOR, TCL_INDEX_NONE, offsetof(Listbox, selFgColorPtr),
	 TK_OPTION_NULL_OK, DEF_LISTBOX_SELECT_FG_MONO, 0},
    {TK_OPTION_STRING, "-selectmode", "selectMode", "SelectMode",
	 DEF_LISTBOX_SELECT_MODE, -1, Tk_Offset(Listbox, selectMode),
	 DEF_LISTBOX_SELECT_MODE, TCL_INDEX_NONE, offsetof(Listbox, selectMode),
	 TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_BOOLEAN, "-setgrid", "setGrid", "SetGrid",
	 DEF_LISTBOX_SET_GRID, -1, Tk_Offset(Listbox, setGrid), 0, 0, 0},
	 DEF_LISTBOX_SET_GRID, TCL_INDEX_NONE, offsetof(Listbox, setGrid), 0, 0, 0},
    {TK_OPTION_STRING_TABLE, "-state", "state", "State",
	DEF_LISTBOX_STATE, -1, Tk_Offset(Listbox, state),
	DEF_LISTBOX_STATE, TCL_INDEX_NONE, offsetof(Listbox, state),
	0, stateStrings, 0},
    {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
	 DEF_LISTBOX_TAKE_FOCUS, -1, Tk_Offset(Listbox, takeFocus),
	 DEF_LISTBOX_TAKE_FOCUS, TCL_INDEX_NONE, offsetof(Listbox, takeFocus),
	 TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_INT, "-width", "width", "Width",
	 DEF_LISTBOX_WIDTH, -1, Tk_Offset(Listbox, width), 0, 0, 0},
	 DEF_LISTBOX_WIDTH, TCL_INDEX_NONE, offsetof(Listbox, width), 0, 0, 0},
    {TK_OPTION_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand",
	 DEF_LISTBOX_SCROLL_COMMAND, -1, Tk_Offset(Listbox, xScrollCmd),
	 DEF_LISTBOX_SCROLL_COMMAND, TCL_INDEX_NONE, offsetof(Listbox, xScrollCmd),
	 TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_STRING, "-yscrollcommand", "yScrollCommand", "ScrollCommand",
	 DEF_LISTBOX_SCROLL_COMMAND, -1, Tk_Offset(Listbox, yScrollCmd),
	 DEF_LISTBOX_SCROLL_COMMAND, TCL_INDEX_NONE, offsetof(Listbox, yScrollCmd),
	 TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_STRING, "-listvariable", "listVariable", "Variable",
	 DEF_LISTBOX_LIST_VARIABLE, -1, Tk_Offset(Listbox, listVarName),
	 DEF_LISTBOX_LIST_VARIABLE, TCL_INDEX_NONE, offsetof(Listbox, listVarName),
	 TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0, 0, 0}
    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, TCL_INDEX_NONE, 0, 0, 0}
};

/*
 * The itemAttrOptionSpecs table defines the valid configuration options for
 * listbox items.
 */

static const Tk_OptionSpec itemAttrOptionSpecs[] = {
    {TK_OPTION_BORDER, "-background", "background", "Background",
     NULL, -1, Tk_Offset(ItemAttr, border),
     NULL, TCL_INDEX_NONE, offsetof(ItemAttr, border),
     TK_OPTION_NULL_OK|TK_OPTION_DONT_SET_DEFAULT,
     DEF_LISTBOX_BG_MONO, 0},
    {TK_OPTION_SYNONYM, "-bg", NULL, NULL,
     NULL, 0, -1, 0, "-background", 0},
     NULL, 0, TCL_INDEX_NONE, 0, "-background", 0},
    {TK_OPTION_SYNONYM, "-fg", "foreground", NULL,
     NULL, 0, -1, 0, "-foreground", 0},
     NULL, 0, TCL_INDEX_NONE, 0, "-foreground", 0},
    {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
     NULL, -1, Tk_Offset(ItemAttr, fgColor),
     NULL, TCL_INDEX_NONE, offsetof(ItemAttr, fgColor),
     TK_OPTION_NULL_OK|TK_OPTION_DONT_SET_DEFAULT, 0, 0},
    {TK_OPTION_BORDER, "-selectbackground", "selectBackground", "Foreground",
     NULL, -1, Tk_Offset(ItemAttr, selBorder),
     NULL, TCL_INDEX_NONE, offsetof(ItemAttr, selBorder),
     TK_OPTION_NULL_OK|TK_OPTION_DONT_SET_DEFAULT,
     DEF_LISTBOX_SELECT_MONO, 0},
    {TK_OPTION_COLOR, "-selectforeground", "selectForeground", "Background",
     NULL, -1, Tk_Offset(ItemAttr, selFgColor),
     NULL, TCL_INDEX_NONE, offsetof(ItemAttr, selFgColor),
     TK_OPTION_NULL_OK|TK_OPTION_DONT_SET_DEFAULT,
     DEF_LISTBOX_SELECT_FG_MONO, 0},
    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0, 0, 0}
    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, TCL_INDEX_NONE, 0, 0, 0}
};

/*
 * The following tables define the listbox widget commands (and sub-commands)
 * and map the indexes into the string tables into enumerated types used to
 * dispatch the listbox widget command.
 */
373
374
375
376
377
378
379
380

381
382
383

384
385
386
387
388
389
390
373
374
375
376
377
378
379

380
381
382

383
384
385
386
387
388
389
390







-
+


-
+







    "mark", "dragto", NULL
};
enum scancommand {
    SCAN_MARK, SCAN_DRAGTO
};

static const char *const indexNames[] = {
    "active", "anchor", "end", NULL
    "active", "anchor", NULL
};
enum indices {
    INDEX_ACTIVE, INDEX_ANCHOR, INDEX_END
    INDEX_ACTIVE, INDEX_ANCHOR
};

/*
 * Declarations for procedures defined later in this file.
 */

static void		ChangeListboxOffset(Listbox *listPtr, int offset);
405
406
407
408
409
410
411
412
413


414
415
416
417
418
419
420
405
406
407
408
409
410
411


412
413
414
415
416
417
418
419
420







-
-
+
+







static int		ListboxInsertSubCmd(Listbox *listPtr,
			    int index, int objc, Tcl_Obj *const objv[]);
static void		ListboxCmdDeletedProc(ClientData clientData);
static void		ListboxComputeGeometry(Listbox *listPtr,
			    int fontChanged, int maxIsStale, int updateGrid);
static void		ListboxEventProc(ClientData clientData,
			    XEvent *eventPtr);
static int		ListboxFetchSelection(ClientData clientData,
			    int offset, char *buffer, int maxBytes);
static TkSizeT	ListboxFetchSelection(ClientData clientData,
			    TkSizeT offset, char *buffer, TkSizeT maxBytes);
static void		ListboxLostSelection(ClientData clientData);
static void		GenerateListboxSelectEvent(Listbox *listPtr);
static void		EventuallyRedrawRange(Listbox *listPtr,
			    int first, int last);
static void		ListboxScanTo(Listbox *listPtr, int x, int y);
static int		ListboxSelect(Listbox *listPtr,
			    int first, int last, int select);
469
470
471
472
473
474
475
476

477
478
479
480
481

482
483

484
485
486
487
488
489
490
491
492
493
494
495
496

497
498
499
500
501
502
503
504

505
506
507
508
509
510
511
469
470
471
472
473
474
475

476
477
478
479
480

481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496

497
498
499
500
501
502
503
504

505
506
507
508
509
510
511
512







-
+




-
+


+












-
+







-
+







 *	See the user documentation.
 *
 *--------------------------------------------------------------
 */

int
Tk_ListboxObjCmd(
    ClientData clientData,	/* NULL. */
    ClientData dummy,	/* NULL. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    register Listbox *listPtr;
    Listbox *listPtr;
    Tk_Window tkwin;
    ListboxOptionTables *optionTables;
    (void)dummy;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "pathName ?-option value ...?");
	return TCL_ERROR;
    }

    tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp),
	    Tcl_GetString(objv[1]), NULL);
    if (tkwin == NULL) {
	return TCL_ERROR;
    }

    optionTables = Tcl_GetAssocData(interp, "ListboxOptionTables", NULL);
    optionTables = (ListboxOptionTables *)Tcl_GetAssocData(interp, "ListboxOptionTables", NULL);
    if (optionTables == NULL) {
	/*
	 * We haven't created the option tables for this widget class yet. Do
	 * it now and save the a pointer to them as the ClientData for the
	 * command, so future invocations will have access to it.
	 */

	optionTables = ckalloc(sizeof(ListboxOptionTables));
	optionTables = (ListboxOptionTables *)ckalloc(sizeof(ListboxOptionTables));

	/*
	 * Set up an exit handler to free the optionTables struct.
	 */

	Tcl_SetAssocData(interp, "ListboxOptionTables",
		DestroyListboxOptionTables, optionTables);
522
523
524
525
526
527
528
529

530
531
532
533
534
535
536
537
538
539
540

541
542

543
544
545
546
547
548
549
523
524
525
526
527
528
529

530
531
532
533
534
535
536
537
538
539
540

541
542

543
544
545
546
547
548
549
550







-
+










-
+

-
+








    /*
     * Initialize the fields of the structure that won't be initialized by
     * ConfigureListbox, or that ConfigureListbox requires to be initialized
     * already (e.g. resource pointers).
     */

    listPtr			 = ckalloc(sizeof(Listbox));
    listPtr			 = (Listbox *)ckalloc(sizeof(Listbox));
    memset(listPtr, 0, sizeof(Listbox));

    listPtr->tkwin		 = tkwin;
    listPtr->display		 = Tk_Display(tkwin);
    listPtr->interp		 = interp;
    listPtr->widgetCmd		 = Tcl_CreateObjCommand(interp,
	    Tk_PathName(listPtr->tkwin), ListboxWidgetObjCmd, listPtr,
	    ListboxCmdDeletedProc);
    listPtr->optionTable	 = optionTables->listboxOptionTable;
    listPtr->itemAttrOptionTable = optionTables->itemAttrOptionTable;
    listPtr->selection		 = ckalloc(sizeof(Tcl_HashTable));
    listPtr->selection		 = (Tcl_HashTable *)ckalloc(sizeof(Tcl_HashTable));
    Tcl_InitHashTable(listPtr->selection, TCL_ONE_WORD_KEYS);
    listPtr->itemAttrTable	 = ckalloc(sizeof(Tcl_HashTable));
    listPtr->itemAttrTable	 = (Tcl_HashTable *)ckalloc(sizeof(Tcl_HashTable));
    Tcl_InitHashTable(listPtr->itemAttrTable, TCL_ONE_WORD_KEYS);
    listPtr->relief		 = TK_RELIEF_RAISED;
    listPtr->textGC		 = NULL;
    listPtr->selFgColorPtr	 = NULL;
    listPtr->selTextGC		 = NULL;
    listPtr->fullLines		 = 1;
    listPtr->xScrollUnit	 = 1;
563
564
565
566
567
568
569
570

571
572
573
574
575
576
577
578
579
580
581

582
583
584
585
586
587
588
564
565
566
567
568
569
570

571
572
573
574
575
576
577
578
579
580
581

582
583
584
585
586
587
588
589







-
+










-
+







    Tk_SetClass(listPtr->tkwin, "Listbox");
    Tk_SetClassProcs(listPtr->tkwin, &listboxClass, listPtr);
    Tk_CreateEventHandler(listPtr->tkwin,
	    ExposureMask|StructureNotifyMask|FocusChangeMask,
	    ListboxEventProc, listPtr);
    Tk_CreateSelHandler(listPtr->tkwin, XA_PRIMARY, XA_STRING,
	    ListboxFetchSelection, listPtr, XA_STRING);
    if (Tk_InitOptions(interp, (char *)listPtr,
    if (Tk_InitOptions(interp, listPtr,
	    optionTables->listboxOptionTable, tkwin) != TCL_OK) {
	Tk_DestroyWindow(listPtr->tkwin);
	return TCL_ERROR;
    }

    if (ConfigureListbox(interp, listPtr, objc-2, objv+2) != TCL_OK) {
	Tk_DestroyWindow(listPtr->tkwin);
	return TCL_ERROR;
    }

    Tcl_SetObjResult(interp, TkNewWindowObj(listPtr->tkwin));
    Tcl_SetObjResult(interp, Tk_NewWindowObj(listPtr->tkwin));
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * ListboxWidgetObjCmd --
603
604
605
606
607
608
609
610

611
612
613
614
615
616
617
604
605
606
607
608
609
610

611
612
613
614
615
616
617
618







-
+







static int
ListboxWidgetObjCmd(
    ClientData clientData,	/* Information about listbox widget. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Arguments as Tcl_Obj's. */
{
    register Listbox *listPtr = clientData;
    Listbox *listPtr = (Listbox *)clientData;
    int cmdIndex, index;
    int result = TCL_OK;
    Tcl_Obj *objPtr;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
	return TCL_ERROR;
678
679
680
681
682
683
684
685

686
687
688
689
690
691
692
693
694
695
696
697

698
699
700
701
702
703
704
679
680
681
682
683
684
685

686
687
688
689
690
691
692
693
694
695
696
697

698
699
700
701
702
703
704
705







-
+











-
+







    case COMMAND_CGET:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "option");
	    result = TCL_ERROR;
	    break;
	}

	objPtr = Tk_GetOptionValue(interp, (char *) listPtr,
	objPtr = Tk_GetOptionValue(interp, listPtr,
		listPtr->optionTable, objv[2], listPtr->tkwin);
	if (objPtr == NULL) {
	    result = TCL_ERROR;
	    break;
	}
	Tcl_SetObjResult(interp, objPtr);
	result = TCL_OK;
	break;

    case COMMAND_CONFIGURE:
	if (objc <= 3) {
	    objPtr = Tk_GetOptionInfo(interp, (char *) listPtr,
	    objPtr = Tk_GetOptionInfo(interp, listPtr,
		    listPtr->optionTable,
		    (objc == 3) ? objv[2] : NULL, listPtr->tkwin);
	    if (objPtr == NULL) {
		result = TCL_ERROR;
		break;
	    }
	    Tcl_SetObjResult(interp, objPtr);
724
725
726
727
728
729
730
731

732
733
734
735
736
737
738
725
726
727
728
729
730
731

732
733
734
735
736
737
738
739







-
+







	 * the indices in order, adding them to the result if they are
	 * selected.
	 */

	objPtr = Tcl_NewObj();
	for (i = 0; i < listPtr->nElements; i++) {
	    if (Tcl_FindHashEntry(listPtr->selection, KEY(i))) {
		Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewIntObj(i));
		Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewWideIntObj(i));
	    }
	}
	Tcl_SetObjResult(interp, objPtr);
	result = TCL_OK;
	break;
    }

837
838
839
840
841
842
843
844

845
846
847
848
849
850
851
838
839
840
841
842
843
844

845
846
847
848
849
850
851
852







-
+







	    result = TCL_ERROR;
	    break;
	}
	result = GetListboxIndex(interp, listPtr, objv[2], 1, &index);
	if (result != TCL_OK) {
	    break;
	}
	Tcl_SetObjResult(interp, Tcl_NewIntObj(index));
	Tcl_SetObjResult(interp, TkNewIndexObj(index));
	result = TCL_OK;
	break;

    case COMMAND_INSERT:
	if (objc < 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "index ?element ...?");
	    result = TCL_ERROR;
901
902
903
904
905
906
907
908

909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929

930
931
932
933
934
935
936
902
903
904
905
906
907
908

909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929

930
931
932
933
934
935
936
937







-
+




















-
+







    }

    case COMMAND_ITEMCONFIGURE: {
	ItemAttr *attrPtr;

	if (objc < 3) {
	    Tcl_WrongNumArgs(interp, 2, objv,
		    "index ?-option? ?value? ?-option value ...?");
		    "index ?-option value ...?");
	    result = TCL_ERROR;
	    break;
	}

	result = GetListboxIndex(interp, listPtr, objv[2], 0, &index);
	if (result != TCL_OK) {
	    break;
	}

	if (index < 0 || index >= listPtr->nElements) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "item number \"%s\" out of range",
		    Tcl_GetString(objv[2])));
	    Tcl_SetErrorCode(interp, "TK", "LISTBOX", "ITEM_INDEX", NULL);
	    result = TCL_ERROR;
	    break;
	}

	attrPtr = ListboxGetItemAttributes(interp, listPtr, index);
	if (objc <= 4) {
	    objPtr = Tk_GetOptionInfo(interp, (char *) attrPtr,
	    objPtr = Tk_GetOptionInfo(interp, attrPtr,
		    listPtr->itemAttrOptionTable,
		    (objc == 4) ? objv[3] : NULL, listPtr->tkwin);
	    if (objPtr == NULL) {
		result = TCL_ERROR;
		break;
	    }
	    Tcl_SetObjResult(interp, objPtr);
952
953
954
955
956
957
958
959

960
961
962
963
964
965
966
953
954
955
956
957
958
959

960
961
962
963
964
965
966
967







-
+







	}

	result = Tcl_GetIntFromObj(interp, objv[2], &y);
	if (result != TCL_OK) {
	    break;
	}
	index = NearestListboxElement(listPtr, y);
	Tcl_SetObjResult(interp, Tcl_NewIntObj(index));
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(index));
	result = TCL_OK;
	break;
    }

    case COMMAND_SCAN: {
	int x, y, scanCmdIndex;

1040
1041
1042
1043
1044
1045
1046
1047

1048
1049
1050
1051
1052
1053
1054
1041
1042
1043
1044
1045
1046
1047

1048
1049
1050
1051
1052
1053
1054
1055







-
+







	break;
    case COMMAND_SIZE:
	if (objc != 2) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    result = TCL_ERROR;
	    break;
	}
	Tcl_SetObjResult(interp, Tcl_NewIntObj(listPtr->nElements));
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(listPtr->nElements));
	result = TCL_OK;
	break;
    case COMMAND_XVIEW:
	result = ListboxXviewSubCmd(interp, listPtr, objc, objv);
	break;
    case COMMAND_YVIEW:
	result = ListboxYviewSubCmd(interp, listPtr, objc, objv);
1078
1079
1080
1081
1082
1083
1084
1085

1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105


1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117

1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135




1136
1137
1138
1139
1140
1141
1142
1079
1080
1081
1082
1083
1084
1085

1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105

1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118

1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133




1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144







-
+



















-
+
+











-
+














-
-
-
-
+
+
+
+








static int
ListboxBboxSubCmd(
    Tcl_Interp *interp,		/* Pointer to the calling Tcl interpreter */
    Listbox *listPtr,		/* Information about the listbox */
    int index)			/* Index of the element to get bbox info on */
{
    register Tk_Window tkwin = listPtr->tkwin;
    Tk_Window tkwin = listPtr->tkwin;
    int lastVisibleIndex;

    /*
     * Determine the index of the last visible item in the listbox.
     */

    lastVisibleIndex = listPtr->topIndex + listPtr->fullLines
	    + listPtr->partialLine;
    if (listPtr->nElements < lastVisibleIndex) {
	lastVisibleIndex = listPtr->nElements;
    }

    /*
     * Only allow bbox requests for indices that are visible.
     */

    if ((listPtr->topIndex <= index) && (index < lastVisibleIndex)) {
	Tcl_Obj *el, *results[4];
	const char *stringRep;
	int pixelWidth, stringLen, x, y, result;
	int pixelWidth, x, y, result;
	TkSizeT stringLen;
	Tk_FontMetrics fm;

	/*
	 * Compute the pixel width of the requested element.
	 */

	result = Tcl_ListObjIndex(interp, listPtr->listObj, index, &el);
	if (result != TCL_OK) {
	    return result;
	}

	stringRep = Tcl_GetStringFromObj(el, &stringLen);
	stringRep = TkGetStringFromObj(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;
        } else if (listPtr->justify == TK_JUSTIFY_RIGHT) {
            x = Tk_Width(tkwin) - (listPtr->inset + listPtr->selBorderWidth)
                    - pixelWidth - listPtr->xOffset + GetMaxOffset(listPtr);
        } else {
            x = (Tk_Width(tkwin) - pixelWidth)/2
                    - listPtr->xOffset + GetMaxOffset(listPtr)/2;
        }
	y = ((index - listPtr->topIndex)*listPtr->lineHeight)
		+ listPtr->inset + listPtr->selBorderWidth;
	results[0] = Tcl_NewIntObj(x);
	results[1] = Tcl_NewIntObj(y);
	results[2] = Tcl_NewIntObj(pixelWidth);
	results[3] = Tcl_NewIntObj(fm.linespace);
	results[0] = Tcl_NewWideIntObj(x);
	results[1] = Tcl_NewWideIntObj(y);
	results[2] = Tcl_NewWideIntObj(pixelWidth);
	results[3] = Tcl_NewWideIntObj(fm.linespace);
	Tcl_SetObjResult(interp, Tcl_NewListObj(4, results));
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
1406
1407
1408
1409
1410
1411
1412
1413

1414
1415
1416
1417
1418

1419
1420
1421
1422

1423
1424
1425
1426
1427
1428
1429
1408
1409
1410
1411
1412
1413
1414

1415
1416
1417
1418
1419

1420
1421
1422
1423

1424
1425
1426
1427
1428
1429
1430
1431







-
+




-
+



-
+







{
    int isNew;
    Tcl_HashEntry *entry;
    ItemAttr *attrs;

    entry = Tcl_CreateHashEntry(listPtr->itemAttrTable, KEY(index), &isNew);
    if (isNew) {
	attrs = ckalloc(sizeof(ItemAttr));
	attrs = (ItemAttr *)ckalloc(sizeof(ItemAttr));
	attrs->border = NULL;
	attrs->selBorder = NULL;
	attrs->fgColor = NULL;
	attrs->selFgColor = NULL;
	Tk_InitOptions(interp, (char *)attrs, listPtr->itemAttrOptionTable,
	Tk_InitOptions(interp, attrs, listPtr->itemAttrOptionTable,
		listPtr->tkwin);
	Tcl_SetHashValue(entry, attrs);
    } else {
	attrs = Tcl_GetHashValue(entry);
	attrs = (ItemAttr *)Tcl_GetHashValue(entry);
    }
    return attrs;
}

/*
 *----------------------------------------------------------------------
 *
1442
1443
1444
1445
1446
1447
1448
1449

1450
1451
1452
1453
1454
1455
1456
1444
1445
1446
1447
1448
1449
1450

1451
1452
1453
1454
1455
1456
1457
1458







-
+







 *----------------------------------------------------------------------
 */

static void
DestroyListbox(
    void *memPtr)		/* Info about listbox widget. */
{
    register Listbox *listPtr = memPtr;
    Listbox *listPtr = (Listbox *)memPtr;
    Tcl_HashEntry *entry;
    Tcl_HashSearch search;

    /*
     * If we have an internal list object, free it.
     */

1522
1523
1524
1525
1526
1527
1528
1529

1530


1531
1532
1533
1534
1535
1536
1537
1524
1525
1526
1527
1528
1529
1530

1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541







-
+

+
+







 *
 *----------------------------------------------------------------------
 */

static void
DestroyListboxOptionTables(
    ClientData clientData,	/* Pointer to the OptionTables struct */
    Tcl_Interp *interp)		/* Pointer to the calling interp */
    Tcl_Interp *dummy)		/* Pointer to the calling interp */
{
    (void)dummy;

    ckfree(clientData);
    return;
}

/*
 *----------------------------------------------------------------------
 *
1551
1552
1553
1554
1555
1556
1557
1558

1559
1560
1561
1562
1563
1564
1565
1555
1556
1557
1558
1559
1560
1561

1562
1563
1564
1565
1566
1567
1568
1569







-
+







 *
 *----------------------------------------------------------------------
 */

static int
ConfigureListbox(
    Tcl_Interp *interp,		/* Used for error reporting. */
    register Listbox *listPtr,	/* Information about widget; may or may not
    Listbox *listPtr,	/* Information about widget; may or may not
				 * already have values for some fields. */
    int objc,			/* Number of valid entries in argv. */
    Tcl_Obj *const objv[])	/* Arguments. */
{
    Tk_SavedOptions savedOptions;
    Tcl_Obj *oldListObj = NULL;
    Tcl_Obj *errorResult = NULL;
1574
1575
1576
1577
1578
1579
1580
1581

1582
1583
1584
1585
1586
1587
1588
1578
1579
1580
1581
1582
1583
1584

1585
1586
1587
1588
1589
1590
1591
1592







-
+








    for (error = 0; error <= 1; error++) {
	if (!error) {
	    /*
	     * First pass: set options to new values.
	     */

	    if (Tk_SetOptions(interp, (char *) listPtr,
	    if (Tk_SetOptions(interp, listPtr,
		    listPtr->optionTable, objc, objv,
		    listPtr->tkwin, &savedOptions, NULL) != TCL_OK) {
		continue;
	    }
	} else {
	    /*
	     * Second pass: restore options to old values.
1711
1712
1713
1714
1715
1716
1717
1718

1719
1720
1721
1722
1723
1724
1725
1726
1727

1728
1729
1730
1731
1732
1733
1734
1715
1716
1717
1718
1719
1720
1721

1722
1723
1724
1725
1726
1727
1728
1729
1730

1731
1732
1733
1734
1735
1736
1737
1738







-
+








-
+







 *
 *----------------------------------------------------------------------
 */

static int
ConfigureListboxItem(
    Tcl_Interp *interp,		/* Used for error reporting. */
    register Listbox *listPtr,	/* Information about widget; may or may not
    Listbox *listPtr,	/* Information about widget; may or may not
				 * already have values for some fields. */
    ItemAttr *attrs,		/* Information about the item to configure */
    int objc,			/* Number of valid entries in argv. */
    Tcl_Obj *const objv[],	/* Arguments. */
    int index)			/* Index of the listbox item being configure */
{
    Tk_SavedOptions savedOptions;

    if (Tk_SetOptions(interp, (char *)attrs,
    if (Tk_SetOptions(interp, attrs,
	    listPtr->itemAttrOptionTable, objc, objv, listPtr->tkwin,
	    &savedOptions, NULL) != TCL_OK) {
	Tk_RestoreSavedOptions(&savedOptions);
	return TCL_ERROR;
    }
    Tk_FreeSavedOptions(&savedOptions);

1762
1763
1764
1765
1766
1767
1768
1769

1770
1771
1772
1773
1774
1775
1776
1766
1767
1768
1769
1770
1771
1772

1773
1774
1775
1776
1777
1778
1779
1780







-
+







static void
ListboxWorldChanged(
    ClientData instanceData)	/* Information about widget. */
{
    XGCValues gcValues;
    GC gc;
    unsigned long mask;
    Listbox *listPtr = instanceData;
    Listbox *listPtr = (Listbox *)instanceData;

    if (listPtr->state & STATE_NORMAL) {
	gcValues.foreground = listPtr->fgColorPtr->pixel;
	gcValues.graphics_exposures = False;
	mask = GCForeground | GCFont | GCGraphicsExposures;
    } else if (listPtr->dfgColorPtr != NULL) {
	gcValues.foreground = listPtr->dfgColorPtr->pixel;
1833
1834
1835
1836
1837
1838
1839
1840
1841


1842
1843


1844
1845
1846
1847
1848
1849
1850
1837
1838
1839
1840
1841
1842
1843


1844
1845
1846

1847
1848
1849
1850
1851
1852
1853
1854
1855







-
-
+
+

-
+
+







 *--------------------------------------------------------------
 */

static void
DisplayListbox(
    ClientData clientData)	/* Information about window. */
{
    register Listbox *listPtr = clientData;
    register Tk_Window tkwin = listPtr->tkwin;
    Listbox *listPtr = (Listbox *)clientData;
    Tk_Window tkwin = listPtr->tkwin;
    GC gc;
    int i, limit, x, y, prevSelected, freeGC, stringLen;
    int i, limit, x, y, prevSelected, freeGC;
    TkSizeT stringLen;
    Tk_FontMetrics fm;
    Tcl_Obj *curElement;
    Tcl_HashEntry *entry;
    const char *stringRep;
    ItemAttr *attrs;
    Tk_3DBorder selectedBg;
    XGCValues gcValues;
1952
1953
1954
1955
1956
1957
1958
1959

1960
1961
1962
1963
1964
1965
1966
1957
1958
1959
1960
1961
1962
1963

1964
1965
1966
1967
1968
1969
1970
1971







-
+








		/*
		 * If there is attribute information for this item, adjust the
		 * drawing accordingly.
		 */

		if (entry != NULL) {
		    attrs = Tcl_GetHashValue(entry);
		    attrs = (ItemAttr *)Tcl_GetHashValue(entry);

		    /*
		     * Default GC has the values from the widget at large.
		     */

		    if (listPtr->selFgColorPtr) {
			gcValues.foreground = listPtr->selFgColorPtr->pixel;
2033
2034
2035
2036
2037
2038
2039
2040

2041
2042
2043
2044
2045
2046
2047
2038
2039
2040
2041
2042
2043
2044

2045
2046
2047
2048
2049
2050
2051
2052







-
+







	    } else {
		/*
		 * If there is an item attributes record for this item, draw
		 * the background box and set the foreground color accordingly.
		 */

		if (entry != NULL) {
		    attrs = Tcl_GetHashValue(entry);
		    attrs = (ItemAttr *)Tcl_GetHashValue(entry);
		    gcValues.foreground = listPtr->fgColorPtr->pixel;
		    gcValues.font = Tk_FontId(listPtr->tkfont);
		    gcValues.graphics_exposures = False;
		    mask = GCForeground | GCFont | GCGraphicsExposures;

		    /*
		     * If the item has its own background color, draw it now.
2070
2071
2072
2073
2074
2075
2076
2077

2078
2079
2080
2081
2082
2083
2084
2075
2076
2077
2078
2079
2080
2081

2082
2083
2084
2085
2086
2087
2088
2089







-
+







	}

	/*
	 * Draw the actual text of this item.
	 */

        Tcl_ListObjIndex(listPtr->interp, listPtr->listObj, i, &curElement);
        stringRep = Tcl_GetStringFromObj(curElement, &stringLen);
        stringRep = TkGetStringFromObj(curElement, &stringLen);
        textWidth = Tk_TextWidth(listPtr->tkfont, stringRep, stringLen);

	Tk_GetFontMetrics(listPtr->tkfont, &fm);
	y += fm.ascent + listPtr->selBorderWidth;

        if (listPtr->justify == TK_JUSTIFY_LEFT) {
            x = (listPtr->inset + listPtr->selBorderWidth) - listPtr->xOffset;
2232
2233
2234
2235
2236
2237
2238
2239


2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260

2261
2262
2263
2264
2265
2266
2267
2237
2238
2239
2240
2241
2242
2243

2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265

2266
2267
2268
2269
2270
2271
2272
2273







-
+
+




















-
+







				 * longer be up-to-date and must be
				 * recomputed. If fontChanged is 1 then this
				 * must be 1. */
    int updateGrid)		/* Non-zero means call Tk_SetGrid or
				 * Tk_UnsetGrid to update gridding for the
				 * window. */
{
    int width, height, pixelWidth, pixelHeight, textLength, i, result;
    int width, height, pixelWidth, pixelHeight, i, result;
    TkSizeT textLength;
    Tk_FontMetrics fm;
    Tcl_Obj *element;
    const char *text;

    if (fontChanged || maxIsStale) {
	listPtr->xScrollUnit = Tk_TextWidth(listPtr->tkfont, "0", 1);
	if (listPtr->xScrollUnit == 0) {
	    listPtr->xScrollUnit = 1;
	}
	listPtr->maxWidth = 0;
	for (i = 0; i < listPtr->nElements; i++) {
	    /*
	     * Compute the pixel width of the current element.
	     */

	    result = Tcl_ListObjIndex(listPtr->interp, listPtr->listObj, i,
		    &element);
	    if (result != TCL_OK) {
		continue;
	    }
	    text = Tcl_GetStringFromObj(element, &textLength);
	    text = TkGetStringFromObj(element, &textLength);
	    Tk_GetFontMetrics(listPtr->tkfont, &fm);
	    pixelWidth = Tk_TextWidth(listPtr->tkfont, text, textLength);
	    if (pixelWidth > listPtr->maxWidth) {
		listPtr->maxWidth = pixelWidth;
	    }
	}
    }
2313
2314
2315
2316
2317
2318
2319
2320

2321
2322
2323
2324
2325
2326


2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337

2338
2339
2340
2341
2342
2343
2344
2319
2320
2321
2322
2323
2324
2325

2326
2327
2328
2329
2330
2331

2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343

2344
2345
2346
2347
2348
2349
2350
2351







-
+





-
+
+










-
+







 *	callback is registered for the listbox.
 *
 *----------------------------------------------------------------------
 */

static int
ListboxInsertSubCmd(
    register Listbox *listPtr,	/* Listbox that is to get the new elements. */
    Listbox *listPtr,	/* Listbox that is to get the new elements. */
    int index,			/* Add the new elements before this
				 * element. */
    int objc,			/* Number of new elements to add. */
    Tcl_Obj *const objv[])	/* New elements (one per entry). */
{
    int i, oldMaxWidth, pixelWidth, result, length;
    int i, oldMaxWidth, pixelWidth, result;
    TkSizeT length;
    Tcl_Obj *newListObj;
    const char *stringRep;

    oldMaxWidth = listPtr->maxWidth;
    for (i = 0; i < objc; i++) {
	/*
	 * Check if any of the new elements are wider than the current widest;
	 * if so, update our notion of "widest."
	 */

	stringRep = Tcl_GetStringFromObj(objv[i], &length);
	stringRep = TkGetStringFromObj(objv[i], &length);
	pixelWidth = Tk_TextWidth(listPtr->tkfont, stringRep, length);
	if (pixelWidth > listPtr->maxWidth) {
	    listPtr->maxWidth = pixelWidth;
	}
    }

    /*
2429
2430
2431
2432
2433
2434
2435
2436

2437
2438
2439
2440


2441
2442
2443
2444
2445
2446
2447
2436
2437
2438
2439
2440
2441
2442

2443
2444
2445
2446

2447
2448
2449
2450
2451
2452
2453
2454
2455







-
+



-
+
+







 *	The listbox will be modified and (eventually) redisplayed.
 *
 *----------------------------------------------------------------------
 */

static int
ListboxDeleteSubCmd(
    register Listbox *listPtr,	/* Listbox widget to modify. */
    Listbox *listPtr,	/* Listbox widget to modify. */
    int first,			/* Index of first element to delete. */
    int last)			/* Index of last element to delete. */
{
    int count, i, widthChanged, length, result, pixelWidth;
    int count, i, widthChanged, result, pixelWidth;
    TkSizeT length;
    Tcl_Obj *newListObj, *element;
    const char *stringRep;
    Tcl_HashEntry *entry;

    /*
     * Adjust the range to fit within the existing elements of the listbox,
     * and make sure there's something to delete.
2488
2489
2490
2491
2492
2493
2494
2495

2496
2497
2498
2499
2500
2501
2502
2496
2497
2498
2499
2500
2501
2502

2503
2504
2505
2506
2507
2508
2509
2510







-
+







	 * Check width of the element. We only have to check if widthChanged
	 * has not already been set to 1, because we only need one maxWidth
	 * element to disappear for us to have to recompute the width.
	 */

	if (widthChanged == 0) {
	    Tcl_ListObjIndex(listPtr->interp, listPtr->listObj, i, &element);
	    stringRep = Tcl_GetStringFromObj(element, &length);
	    stringRep = TkGetStringFromObj(element, &length);
	    pixelWidth = Tk_TextWidth(listPtr->tkfont, stringRep, length);
	    if (pixelWidth == listPtr->maxWidth) {
		widthChanged = 1;
	    }
	}
    }

2606
2607
2608
2609
2610
2611
2612
2613

2614
2615
2616
2617
2618
2619
2620
2614
2615
2616
2617
2618
2619
2620

2621
2622
2623
2624
2625
2626
2627
2628







-
+







 */

static void
ListboxEventProc(
    ClientData clientData,	/* Information about window. */
    XEvent *eventPtr)		/* Information about event. */
{
    Listbox *listPtr = clientData;
    Listbox *listPtr = (Listbox *)clientData;

    if (eventPtr->type == Expose) {
	EventuallyRedrawRange(listPtr,
		NearestListboxElement(listPtr, eventPtr->xexpose.y),
		NearestListboxElement(listPtr, eventPtr->xexpose.y
		+ eventPtr->xexpose.height));
    } else if (eventPtr->type == DestroyNotify) {
2681
2682
2683
2684
2685
2686
2687
2688

2689
2690
2691
2692
2693
2694
2695
2689
2690
2691
2692
2693
2694
2695

2696
2697
2698
2699
2700
2701
2702
2703







-
+







 *----------------------------------------------------------------------
 */

static void
ListboxCmdDeletedProc(
    ClientData clientData)	/* Pointer to widget record for widget. */
{
    Listbox *listPtr = clientData;
    Listbox *listPtr = (Listbox *)clientData;

    /*
     * This procedure could be invoked either because the window was destroyed
     * and the command was then deleted (in which case tkwin is NULL) or
     * because the command was deleted, and then this procedure destroys the
     * widget.
     */
2719
2720
2721
2722
2723
2724
2725
2726

2727
2728
2729
2730
2731

2732









2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2727
2728
2729
2730
2731
2732
2733

2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765








2766
2767
2768
2769
2770
2771
2772







-
+





+

+
+
+
+
+
+
+
+
+















-
-
-
-
-
-
-
-








static int
GetListboxIndex(
    Tcl_Interp *interp,		/* For error messages. */
    Listbox *listPtr,		/* Listbox for which the index is being
				 * specified. */
    Tcl_Obj *indexObj,		/* Specifies an element in the listbox. */
    int endIsSize,		/* If 1, "end" refers to the number of entries
    int lastOK,		/* If 1, "end" refers to the number of entries
				 * in the listbox. If 0, "end" refers to 1
				 * less than the number of entries. */
    int *indexPtr)		/* Where to store converted index. */
{
    int result, index;
    TkSizeT idx;
    const char *stringRep;

    result = TkGetIntForIndex(indexObj, listPtr->nElements - 1, lastOK, &idx);
    if (result == TCL_OK) {
    	if ((idx != TCL_INDEX_NONE) && (idx > (TkSizeT)listPtr->nElements)) {
    	    idx = listPtr->nElements;
    	}
    	*indexPtr = (int)idx;
    	return TCL_OK;
    }

    /*
     * First see if the index is one of the named indices.
     */

    result = Tcl_GetIndexFromObj(NULL, indexObj, indexNames, "", 0, &index);
    if (result == TCL_OK) {
	switch (index) {
	case INDEX_ACTIVE:
	    /* "active" index */
	    *indexPtr = listPtr->active;
	    break;
	case INDEX_ANCHOR:
	    /* "anchor" index */
	    *indexPtr = listPtr->selectAnchor;
	    break;
	case INDEX_END:
	    /* "end" index */
	    if (endIsSize) {
		*indexPtr = listPtr->nElements;
	    } else {
		*indexPtr = listPtr->nElements - 1;
	    }
	    break;
	}
	return TCL_OK;
    }

    /*
     * The index didn't match any of the named indices; maybe it's an @x,y
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2793
2794
2795
2796
2797
2798
2799








2800
2801
2802
2803
2804
2805
2806







-
-
-
-
-
-
-
-







	if ((start == end) || (*end != '\0')) {
	    goto badIndex;
	}
	*indexPtr = NearestListboxElement(listPtr, y);
	return TCL_OK;
    }

    /*
     * Maybe the index is just an integer.
     */

    if (Tcl_GetIntFromObj(interp, indexObj, indexPtr) == TCL_OK) {
	return TCL_OK;
    }

    /*
     * Everything failed, nothing matched. Throw up an error message.
     */

  badIndex:
    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
	    "bad listbox index \"%s\": must be active, anchor, end, @x,y,"
2824
2825
2826
2827
2828
2829
2830
2831

2832
2833
2834
2835
2836
2837
2838
2826
2827
2828
2829
2830
2831
2832

2833
2834
2835
2836
2837
2838
2839
2840







-
+







 *	change its display too.
 *
 *----------------------------------------------------------------------
 */

static void
ChangeListboxView(
    register Listbox *listPtr,	/* Information about widget. */
    Listbox *listPtr,	/* Information about widget. */
    int index)			/* Index of element in listPtr that should now
				 * appear at the top of the listbox. */
{
    if (index >= (listPtr->nElements - listPtr->fullLines)) {
	index = listPtr->nElements - listPtr->fullLines;
    }
    if (index < 0) {
2859
2860
2861
2862
2863
2864
2865
2866

2867
2868
2869
2870
2871
2872
2873
2861
2862
2863
2864
2865
2866
2867

2868
2869
2870
2871
2872
2873
2874
2875







-
+







 *	The listbox may be redrawn to reflect its new horizontal offset.
 *
 *----------------------------------------------------------------------
 */

static void
ChangeListboxOffset(
    register Listbox *listPtr,	/* Information about widget. */
    Listbox *listPtr,	/* Information about widget. */
    int offset)			/* Desired new "xOffset" for listbox. */
{
    int maxOffset;

    /*
     * Make sure that the new offset is within the allowable range, and round
     * it off to an even multiple of xScrollUnit.
2907
2908
2909
2910
2911
2912
2913
2914

2915
2916
2917
2918
2919
2920
2921
2909
2910
2911
2912
2913
2914
2915

2916
2917
2918
2919
2920
2921
2922
2923







-
+







 *	The view in the window may change.
 *
 *----------------------------------------------------------------------
 */

static void
ListboxScanTo(
    register Listbox *listPtr,	/* Information about widget. */
    Listbox *listPtr,	/* Information about widget. */
    int x,			/* X-coordinate to use for scan operation. */
    int y)			/* Y-coordinate to use for scan operation. */
{
    int newTopIndex, newOffset, maxIndex, maxOffset;

    maxIndex = listPtr->nElements - listPtr->fullLines;
    maxOffset = GetMaxOffset(listPtr);
2974
2975
2976
2977
2978
2979
2980
2981

2982
2983
2984
2985
2986
2987
2988
2976
2977
2978
2979
2980
2981
2982

2983
2984
2985
2986
2987
2988
2989
2990







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
NearestListboxElement(
    register Listbox *listPtr,	/* Information about widget. */
    Listbox *listPtr,	/* Information about widget. */
    int y)			/* Y-coordinate in listPtr's window. */
{
    int index;

    index = (y - listPtr->inset) / listPtr->lineHeight;
    if (index >= (listPtr->fullLines + listPtr->partialLine)) {
	index = listPtr->fullLines + listPtr->partialLine - 1;
3015
3016
3017
3018
3019
3020
3021
3022

3023
3024
3025
3026
3027
3028
3029
3017
3018
3019
3020
3021
3022
3023

3024
3025
3026
3027
3028
3029
3030
3031







-
+







 *	non-zero.
 *
 *----------------------------------------------------------------------
 */

static int
ListboxSelect(
    register Listbox *listPtr,	/* Information about widget. */
    Listbox *listPtr,	/* Information about widget. */
    int first,			/* Index of first element to select or
				 * deselect. */
    int last,			/* Index of last element to select or
				 * deselect. */
    int select)			/* 1 means select items, 0 means deselect
				 * them. */
{
3106
3107
3108
3109
3110
3111
3112
3113

3114
3115
3116

3117
3118
3119

3120
3121
3122
3123

3124
3125


3126
3127
3128
3129
3130
3131
3132
3108
3109
3110
3111
3112
3113
3114

3115
3116
3117

3118
3119
3120

3121
3122
3123
3124

3125
3126

3127
3128
3129
3130
3131
3132
3133
3134
3135







-
+


-
+


-
+



-
+

-
+
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
static TkSizeT
ListboxFetchSelection(
    ClientData clientData,	/* Information about listbox widget. */
    int offset,			/* Offset within selection of first byte to be
    TkSizeT offset,			/* Offset within selection of first byte to be
				 * returned. */
    char *buffer,		/* Location in which to place selection. */
    int maxBytes)		/* Maximum number of bytes to place at buffer,
    TkSizeT maxBytes)		/* Maximum number of bytes to place at buffer,
				 * not including terminating NULL
				 * character. */
{
    register Listbox *listPtr = clientData;
    Listbox *listPtr = (Listbox *)clientData;
    Tcl_DString selection;
    int length, count, needNewline, stringLen, i;
    int count, needNewline, i;
    TkSizeT length, stringLen;
    Tcl_Obj *curElement;
    const char *stringRep;
    Tcl_HashEntry *entry;

    if ((!listPtr->exportSelection) || Tcl_IsSafe(listPtr->interp)) {
	return -1;
    }
3141
3142
3143
3144
3145
3146
3147
3148

3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163

3164
3165
3166

3167
3168


3169
3170

3171
3172
3173
3174
3175
3176
3177
3144
3145
3146
3147
3148
3149
3150

3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165

3166

3167
3168
3169


3170
3171
3172

3173
3174
3175
3176
3177
3178
3179
3180







-
+














-
+
-


+
-
-
+
+

-
+







	entry = Tcl_FindHashEntry(listPtr->selection, KEY(i));
	if (entry != NULL) {
	    if (needNewline) {
		Tcl_DStringAppend(&selection, "\n", 1);
	    }
	    Tcl_ListObjIndex(listPtr->interp, listPtr->listObj, i,
		    &curElement);
	    stringRep = Tcl_GetStringFromObj(curElement, &stringLen);
	    stringRep = TkGetStringFromObj(curElement, &stringLen);
	    Tcl_DStringAppend(&selection, stringRep, stringLen);
	    needNewline = 1;
	}
    }

    length = Tcl_DStringLength(&selection);
    if (length == 0) {
	return -1;
    }

    /*
     * Copy the requested portion of the selection to the buffer.
     */

    count = length - offset;
    if (length <= offset) {
    if (count <= 0) {
	count = 0;
    } else {
	count = length - offset;
	if (count > maxBytes) {
	    count = maxBytes;
	if (count > (int)maxBytes) {
	    count = (int)maxBytes;
	}
	memcpy(buffer, Tcl_DStringValue(&selection) + offset, (size_t) count);
	memcpy(buffer, Tcl_DStringValue(&selection) + offset, count);
    }
    buffer[count] = '\0';
    Tcl_DStringFree(&selection);
    return count;
}

/*
3192
3193
3194
3195
3196
3197
3198
3199

3200
3201
3202
3203
3204
3205
3206
3195
3196
3197
3198
3199
3200
3201

3202
3203
3204
3205
3206
3207
3208
3209







-
+







 *----------------------------------------------------------------------
 */

static void
ListboxLostSelection(
    ClientData clientData)	/* Information about listbox widget. */
{
    register Listbox *listPtr = clientData;
    Listbox *listPtr = (Listbox *)clientData;

    if ((listPtr->exportSelection) && (!Tcl_IsSafe(listPtr->interp))
	    && (listPtr->nElements > 0)) {
	ListboxSelect(listPtr, 0, listPtr->nElements-1, 0);
        GenerateListboxSelectEvent(listPtr);
    }
}
3222
3223
3224
3225
3226
3227
3228
3229

3230
3231
3232
3233
3234
3235
3236
3225
3226
3227
3228
3229
3230
3231

3232
3233
3234
3235
3236
3237
3238
3239







-
+







 *----------------------------------------------------------------------
 */

static void
GenerateListboxSelectEvent(
    Listbox *listPtr)		/* Information about widget. */
{
    TkSendVirtualEvent(listPtr->tkwin, "ListboxSelect", NULL);
    Tk_SendVirtualEvent(listPtr->tkwin, "ListboxSelect", NULL);
}

/*
 *----------------------------------------------------------------------
 *
 * EventuallyRedrawRange --
 *
3244
3245
3246
3247
3248
3249
3250
3251

3252
3253
3254
3255
3256
3257



3258
3259
3260
3261
3262
3263
3264
3247
3248
3249
3250
3251
3252
3253

3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270







-
+






+
+
+







 *	Information gets redisplayed.
 *
 *----------------------------------------------------------------------
 */

static void
EventuallyRedrawRange(
    register Listbox *listPtr,	/* Information about widget. */
    Listbox *listPtr,	/* Information about widget. */
    int first,			/* Index of first element in list that needs
				 * to be redrawn. */
    int last)			/* Index of last element in list that needs to
				 * be redrawn. May be less than first; these
				 * just bracket a range. */
{
    (void)first;
    (void)last;

    /*
     * We don't have to register a redraw callback if one is already pending,
     * or if the window doesn't exist, or if the window isn't mapped.
     */

    if ((listPtr->flags & REDRAW_PENDING)
	    || (listPtr->flags & LISTBOX_DELETED)
3287
3288
3289
3290
3291
3292
3293
3294

3295
3296
3297
3298
3299
3300
3301
3293
3294
3295
3296
3297
3298
3299

3300
3301
3302
3303
3304
3305
3306
3307







-
+







 *	process errors in the command.
 *
 *----------------------------------------------------------------------
 */

static void
ListboxUpdateVScrollbar(
    register Listbox *listPtr)	/* Information about widget. */
    Listbox *listPtr)	/* Information about widget. */
{
    char firstStr[TCL_DOUBLE_SPACE], lastStr[TCL_DOUBLE_SPACE];
    double first, last;
    int result;
    Tcl_Interp *interp;
    Tcl_DString buf;

3314
3315
3316
3317
3318
3319
3320
3321

3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332

3333
3334
3335
3336
3337
3338
3339
3320
3321
3322
3323
3324
3325
3326

3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337

3338
3339
3340
3341
3342
3343
3344
3345







-
+










-
+







	}
    }
    Tcl_PrintDouble(NULL, first, firstStr);
    Tcl_PrintDouble(NULL, last, lastStr);

    /*
     * We must hold onto the interpreter from the listPtr because the data at
     * listPtr might be freed as a result of the Tcl_VarEval.
     * listPtr might be freed as a result of the Tcl_EvalEx.
     */

    interp = listPtr->interp;
    Tcl_Preserve(interp);
    Tcl_DStringInit(&buf);
    Tcl_DStringAppend(&buf, listPtr->yScrollCmd, -1);
    Tcl_DStringAppend(&buf, " ", -1);
    Tcl_DStringAppend(&buf, firstStr, -1);
    Tcl_DStringAppend(&buf, " ", -1);
    Tcl_DStringAppend(&buf, lastStr, -1);
    result = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, 0);
    result = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, TCL_EVAL_GLOBAL);
    Tcl_DStringFree(&buf);
    if (result != TCL_OK) {
	Tcl_AddErrorInfo(interp,
		"\n    (vertical scrolling command executed by listbox)");
	Tcl_BackgroundException(interp, result);
    }
    Tcl_Release(interp);
3357
3358
3359
3360
3361
3362
3363
3364

3365
3366
3367
3368
3369
3370
3371
3363
3364
3365
3366
3367
3368
3369

3370
3371
3372
3373
3374
3375
3376
3377







-
+







 *	process errors in the command.
 *
 *----------------------------------------------------------------------
 */

static void
ListboxUpdateHScrollbar(
    register Listbox *listPtr)	/* Information about widget. */
    Listbox *listPtr)	/* Information about widget. */
{
    char firstStr[TCL_DOUBLE_SPACE], lastStr[TCL_DOUBLE_SPACE];
    int result, windowWidth;
    double first, last;
    Tcl_Interp *interp;
    Tcl_DString buf;

3386
3387
3388
3389
3390
3391
3392
3393

3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404

3405
3406
3407
3408
3409
3410
3411
3392
3393
3394
3395
3396
3397
3398

3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409

3410
3411
3412
3413
3414
3415
3416
3417







-
+










-
+







	}
    }
    Tcl_PrintDouble(NULL, first, firstStr);
    Tcl_PrintDouble(NULL, last, lastStr);

    /*
     * We must hold onto the interpreter because the data referred to at
     * listPtr might be freed as a result of the call to Tcl_VarEval.
     * listPtr might be freed as a result of the call to Tcl_EvalEx.
     */

    interp = listPtr->interp;
    Tcl_Preserve(interp);
    Tcl_DStringInit(&buf);
    Tcl_DStringAppend(&buf, listPtr->xScrollCmd, -1);
    Tcl_DStringAppend(&buf, " ", -1);
    Tcl_DStringAppend(&buf, firstStr, -1);
    Tcl_DStringAppend(&buf, " ", -1);
    Tcl_DStringAppend(&buf, lastStr, -1);
    result = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, 0);
    result = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, TCL_EVAL_GLOBAL);
    Tcl_DStringFree(&buf);
    if (result != TCL_OK) {
	Tcl_AddErrorInfo(interp,
		"\n    (horizontal scrolling command executed by listbox)");
	Tcl_BackgroundException(interp, result);
    }
    Tcl_Release(interp);
3431
3432
3433
3434
3435
3436
3437
3438

3439
3440
3441


3442
3443
3444
3445
3446
3447
3448
3437
3438
3439
3440
3441
3442
3443

3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456







-
+



+
+







ListboxListVarProc(
    ClientData clientData,	/* Information about button. */
    Tcl_Interp *interp,		/* Interpreter containing variable. */
    const char *name1,		/* Not used. */
    const char *name2,		/* Not used. */
    int flags)			/* Information about what happened. */
{
    Listbox *listPtr = clientData;
    Listbox *listPtr = (Listbox *)clientData;
    Tcl_Obj *oldListObj, *varListObj;
    int oldLength, i;
    Tcl_HashEntry *entry;
    (void)name1;
    (void)name2;

    /*
     * Bwah hahahaha! Puny mortal, you can't unset a -listvar'd variable!
     */

    if (flags & TCL_TRACE_UNSETS) {

3638
3639
3640
3641
3642
3643
3644
3645

3646
3647
3648
3649
3650
3651
3652
3646
3647
3648
3649
3650
3651
3652

3653
3654
3655
3656
3657
3658
3659
3660







-
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
*/
static int GetMaxOffset(
    register Listbox *listPtr)
    Listbox *listPtr)
{
    int maxOffset;

    maxOffset = listPtr->maxWidth -
            (Tk_Width(listPtr->tkwin) - 2*listPtr->inset -
            2*listPtr->selBorderWidth) + listPtr->xScrollUnit - 1;
    if (maxOffset < 0) {
Changes to generic/tkMacWinMenu.c.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







/*
 * 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.
 */

#include "tkInt.h"
#include "tkMenu.h"
39
40
41
42
43
44
45
46

47
48
49
50
51
52
53
39
40
41
42
43
44
45

46
47
48
49
50
51
52
53







-
+







 */

static int
PreprocessMenu(
    TkMenu *menuPtr)
{
    int index, result, finished;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    Tcl_Preserve(menuPtr);

    /*
     * First, let's process the post command on ourselves. If this command
     * destroys this menu, or if there was an error, we are done.
62
63
64
65
66
67
68
69
70


71
72
73
74
75
76
77
62
63
64
65
66
67
68


69
70
71
72
73
74
75
76
77







-
-
+
+







     * Now, we go through structure and process all of the commands. Since the
     * structure is changing, we stop after we do one command, and start over.
     * When we get through without doing any, we are done.
     */

    do {
	finished = 1;
	for (index = 0; index < menuPtr->numEntries; index++) {
	    register TkMenuEntry *entryPtr = menuPtr->entries[index];
	for (index = 0; index < (int)menuPtr->numEntries; index++) {
	    TkMenuEntry *entryPtr = menuPtr->entries[index];

	    if ((entryPtr->type == CASCADE_ENTRY)
		    && (entryPtr->namePtr != NULL)
		    && (entryPtr->childMenuRefPtr != NULL)
		    && (entryPtr->childMenuRefPtr->menuPtr != NULL)) {
		TkMenu *cascadeMenuPtr = entryPtr->childMenuRefPtr->menuPtr;

125
126
127
128
129
130
131
132

133
134
135
136
137
138
139
125
126
127
128
129
130
131

132
133
134
135
136
137
138
139







-
+







 *----------------------------------------------------------------------
 */

int
TkPreprocessMenu(
    TkMenu *menuPtr)
{
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    tsdPtr->postCommandGeneration++;
    menuPtr->postCommandGeneration = tsdPtr->postCommandGeneration;
    return PreprocessMenu(menuPtr);
}

Changes to generic/tkMain.c.
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42



43
44
45
46

47
48
49
50
51
52



53
54
55
56
57
58
59
11
12
13
14
15
16
17








18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57







-
-
-
-
-
-
-
-

















+
+
+



-
+






+
+
+







 * Copyright (c) 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.
 */

#include "tkInt.h"
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#ifdef NO_STDLIB_H
#   include "../compat/stdlib.h"
#else
#   include <stdlib.h>
#endif

extern int TkCygwinMainEx(int, char **, Tcl_AppInitProc *, Tcl_Interp *);

/*
 * The default prompt used when the user has not overridden it.
 */

static const char DEFAULT_PRIMARY_PROMPT[] = "% ";

/*
 * This file can be compiled on Windows in UNICODE mode, as well as
 * on all other platforms using the native encoding. This is done
 * by using the normal Windows functions like _tcscmp, but on
 * platforms which don't have <tchar.h> we have to translate that
 * to strcmp here.
 */
#ifdef _WIN32
#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 {
typedef struct TclIntPlatStubs {
    int magic;
    void *hooks;
    void (*dummy[16]) (void); /* dummy entries 0-15, not used */
    int (*tclpIsAtty) (int fd); /* 16 */
} TclIntPlatStubs;
extern const TclIntPlatStubs *tclIntPlatStubsPtr;
#ifdef __cplusplus
}
#endif
#   include "tkWinInt.h"
#else
#   define TCHAR char
#   define TEXT(arg) arg
#   define _tcscmp strcmp
#   define _tcslen strlen
#   define _tcsncmp strncmp
67
68
69
70
71
72
73

74

75
76
77
78
79
80
81
65
66
67
68
69
70
71
72

73
74
75
76
77
78
79
80







+
-
+







NewNativeObj(
    TCHAR *string)
{
    Tcl_Obj *obj;
    Tcl_DString ds;

#ifdef UNICODE
    Tcl_DStringInit(&ds);
    Tcl_WinTCharToUtf(string, -1, &ds);
    Tcl_WCharToUtfDString(string, wcslen(string), &ds);
#else
    Tcl_ExternalToUtfDString(NULL, (char *) string, -1, &ds);
#endif
    obj = Tcl_NewStringObj(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds));
    Tcl_DStringFree(&ds);
    return obj;
}
176
177
178
179
180
181
182
183

184
185
186
187
188
189
190
175
176
177
178
179
180
181

182
183
184
185
186
187
188
189







-
+







    Tcl_Channel chan;
    InteractiveState is;

    /*
     * Ensure that we are getting a compatible version of Tcl.
     */

    if (Tcl_InitStubs(interp, "8.6", 0) == NULL) {
    if (Tcl_InitStubs(interp, "8.6-", 0) == NULL) {
	if (Tcl_InitStubs(interp, "8.1", 0) == NULL) {
	    abort();
	} else {
	    Tcl_Panic("%s", Tcl_GetString(Tcl_GetObjResult(interp)));
	}
    }

277
278
279
280
281
282
283
284

285
286
287
288
289
290
291
276
277
278
279
280
281
282

283
284
285
286
287
288
289
290







-
+







    } else {
	appName = path;
    }
    Tcl_SetVar2Ex(interp, "argv0", NULL, appName, TCL_GLOBAL_ONLY);
    argc--;
    argv++;

    Tcl_SetVar2Ex(interp, "argc", NULL, Tcl_NewIntObj(argc), TCL_GLOBAL_ONLY);
    Tcl_SetVar2Ex(interp, "argc", NULL, Tcl_NewWideIntObj(argc), TCL_GLOBAL_ONLY);

    argvPtr = Tcl_NewListObj(0, NULL);
    while (argc--) {
	Tcl_ListObjAppendElement(NULL, argvPtr, NewNativeObj(*argv++));
    }
    Tcl_SetVar2Ex(interp, "argv", NULL, argvPtr, TCL_GLOBAL_ONLY);

304
305
306
307
308
309
310
311

312
313
314
315
316
317
318
303
304
305
306
307
308
309

310
311
312
313
314
315
316
317







-
+







    if (!is.tty) {
	struct stat st;

	nullStdin = fstat(0, &st) || (S_ISCHR(st.st_mode) && !st.st_blocks);
    }
#endif
    Tcl_SetVar2Ex(interp, "tcl_interactive", NULL,
	    Tcl_NewIntObj(!path && (is.tty || nullStdin)), TCL_GLOBAL_ONLY);
	    Tcl_NewWideIntObj(!path && (is.tty || nullStdin)), TCL_GLOBAL_ONLY);

    /*
     * Invoke application-specific initialization.
     */

    if (appInitProc(interp) != TCL_OK) {
	TkpDisplayWarning(Tcl_GetString(Tcl_GetObjResult(interp)),
397
398
399
400
401
402
403
404
405
406
407
408

409
410
411
412



413
414
415
416
417
418

419
420
421
422
423
424
425
396
397
398
399
400
401
402

403
404
405

406
407
408


409
410
411
412
413
414
415
416

417
418
419
420
421
422
423
424







-



-
+


-
-
+
+
+





-
+







 *
 * Side effects:
 *	Could be almost arbitrary, depending on the command that's typed.
 *
 *----------------------------------------------------------------------
 */

    /* ARGSUSED */
static void
StdinProc(
    ClientData clientData,	/* The state of interactive cmd line */
    int mask)			/* Not used. */
    TCL_UNUSED(int))
{
    char *cmd;
    int code, count;
    InteractiveState *isPtr = clientData;
    int code;
    TkSizeT count;
    InteractiveState *isPtr = (InteractiveState *)clientData;
    Tcl_Channel chan = isPtr->input;
    Tcl_Interp *interp = isPtr->interp;

    count = Tcl_Gets(chan, &isPtr->line);

    if (count == -1 && !isPtr->gotPartial) {
    if ((count == TCL_IO_FAILURE) && !isPtr->gotPartial) {
	if (isPtr->tty) {
	    Tcl_Exit(0);
	} else {
	    Tcl_DeleteChannelHandler(chan, StdinProc, isPtr);
	}
	return;
    }
Changes to generic/tkMenu.c.
1
2
3
4
5
6
7
8
9
10


11
12
13
14
15
16
17
1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
16
17








-
-
+
+







/*
 * tkMenu.c --
 *
 * 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.
 */

/*
 * Notes on implementation of menus:
34
35
36
37
38
39
40
41
42


43
44
45
46
47

48
49
50
51
52
53
54
34
35
36
37
38
39
40


41
42
43
44
45
46

47
48
49
50
51
52
53
54







-
-
+
+




-
+







 * the Macintosh, the platform specific menu handle for cascades attached to a
 * menu bar must have a title that matches the label for the cascade menu.
 *
 * To handle all of the constraints, Tk menubars and tearoff menus are
 * implemented using menu clones. Menu clones are full menus in their own
 * right; they have a Tk window and pathname associated with them; they have a
 * TkMenu structure and array of entries. However, they are linked with the
 * original menu that they were cloned from. The reflect the attributes of the
 * original, or "master", menu. So if an item is added to a menu, and that
 * original menu that they were cloned from. They reflect the attributes of the
 * original, or "main", menu. So if an item is added to a menu, and that
 * menu has clones, then the item must be added to all of its clones also.
 * Menus are cloned when a menu is torn-off or when a menu is assigned as a
 * menubar using the "-menu" option of the toplevel's pathname configure
 * subcommand. When a clone is destroyed, only the clone is destroyed, but
 * when the master menu is destroyed, all clones are also destroyed. This
 * when the main menu is destroyed, all clones are also destroyed. This
 * allows the developer to just deal with one set of menus when creating and
 * destroying.
 *
 * Clones are rather tricky when a menu with cascade entries is cloned (such
 * as a menubar). Not only does the menu have to be cloned, but each cascade
 * entry's corresponding menu must also be cloned. This maintains the pathname
 * parent-child hierarchy necessary for menubars and toplevels to work. This
114
115
116
117
118
119
120
121

122
123
124
125

126
127
128

129
130
131

132
133
134

135
136
137

138
139
140

141
142

143
144
145
146

147
148
149

150
151
152

153
154
155

156
157
158

159
160
161

162
163
164

165
166
167
168
169
170
171

172
173
174
175
176
177
178

179
180
181

182
183
184

185
186
187

188
189
190

191
192
193

194
195

196
197
198
199
200
201

202
203
204

205
206
207

208
209
210

211
212
213

214
215

216
217
218
219
220
221

222
223

224
225
226
227
228
229

230
231

232
233
234
235
236
237
238
114
115
116
117
118
119
120

121
122
123
124

125
126
127

128
129
130

131
132
133

134
135
136

137
138
139

140
141

142
143
144
145

146
147
148

149
150
151

152
153
154

155
156
157

158
159
160

161
162
163

164
165
166
167
168
169
170

171
172
173
174
175
176
177

178
179
180

181
182
183

184
185
186

187
188
189

190
191
192

193
194

195
196
197
198
199
200

201
202
203

204
205
206

207
208
209

210
211
212

213
214

215
216
217
218
219
220

221
222

223
224
225
226
227
228

229
230

231
232
233
234
235
236
237
238







-
+



-
+


-
+


-
+


-
+


-
+


-
+

-
+



-
+


-
+


-
+


-
+


-
+


-
+


-
+






-
+






-
+


-
+


-
+


-
+


-
+


-
+

-
+





-
+


-
+


-
+


-
+


-
+

-
+





-
+

-
+





-
+

-
+








static const char *const compoundStrings[] = {
    "bottom", "center", "left", "none", "right", "top", NULL
};

static const Tk_OptionSpec tkBasicMenuEntryConfigSpecs[] = {
    {TK_OPTION_BORDER, "-activebackground", NULL, NULL,
	DEF_MENU_ENTRY_ACTIVE_BG, Tk_Offset(TkMenuEntry, activeBorderPtr), -1,
	DEF_MENU_ENTRY_ACTIVE_BG, offsetof(TkMenuEntry, activeBorderPtr), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_COLOR, "-activeforeground", NULL, NULL,
	DEF_MENU_ENTRY_ACTIVE_FG,
	Tk_Offset(TkMenuEntry, activeFgPtr), -1, TK_OPTION_NULL_OK, NULL, 0},
	offsetof(TkMenuEntry, activeFgPtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_STRING, "-accelerator", NULL, NULL,
	DEF_MENU_ENTRY_ACCELERATOR,
	Tk_Offset(TkMenuEntry, accelPtr), -1, TK_OPTION_NULL_OK, NULL, 0},
	offsetof(TkMenuEntry, accelPtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_BORDER, "-background", NULL, NULL,
	DEF_MENU_ENTRY_BG,
	Tk_Offset(TkMenuEntry, borderPtr), -1, TK_OPTION_NULL_OK, NULL, 0},
	offsetof(TkMenuEntry, borderPtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_BITMAP, "-bitmap", NULL, NULL,
	DEF_MENU_ENTRY_BITMAP,
	Tk_Offset(TkMenuEntry, bitmapPtr), -1, TK_OPTION_NULL_OK, NULL, 0},
	offsetof(TkMenuEntry, bitmapPtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_BOOLEAN, "-columnbreak", NULL, NULL,
	DEF_MENU_ENTRY_COLUMN_BREAK,
	-1, Tk_Offset(TkMenuEntry, columnBreak), 0, NULL, 0},
	TCL_INDEX_NONE, offsetof(TkMenuEntry, columnBreak), 0, NULL, 0},
    {TK_OPTION_STRING, "-command", NULL, NULL,
	DEF_MENU_ENTRY_COMMAND,
	Tk_Offset(TkMenuEntry, commandPtr), -1, TK_OPTION_NULL_OK, NULL, 0},
	offsetof(TkMenuEntry, commandPtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_STRING_TABLE, "-compound", "compound", "Compound",
	DEF_MENU_ENTRY_COMPOUND, -1, Tk_Offset(TkMenuEntry, compound), 0,
	DEF_MENU_ENTRY_COMPOUND, TCL_INDEX_NONE, offsetof(TkMenuEntry, compound), 0,
	(ClientData) compoundStrings, 0},
    {TK_OPTION_FONT, "-font", NULL, NULL,
	DEF_MENU_ENTRY_FONT,
	Tk_Offset(TkMenuEntry, fontPtr), -1, TK_OPTION_NULL_OK, NULL, 0},
	offsetof(TkMenuEntry, fontPtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_COLOR, "-foreground", NULL, NULL,
	DEF_MENU_ENTRY_FG,
	Tk_Offset(TkMenuEntry, fgPtr), -1, TK_OPTION_NULL_OK, NULL, 0},
	offsetof(TkMenuEntry, fgPtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_BOOLEAN, "-hidemargin", NULL, NULL,
	DEF_MENU_ENTRY_HIDE_MARGIN,
	-1, Tk_Offset(TkMenuEntry, hideMargin), 0, NULL, 0},
	TCL_INDEX_NONE, offsetof(TkMenuEntry, hideMargin), 0, NULL, 0},
    {TK_OPTION_STRING, "-image", NULL, NULL,
	DEF_MENU_ENTRY_IMAGE,
	Tk_Offset(TkMenuEntry, imagePtr), -1, TK_OPTION_NULL_OK, NULL, 0},
	offsetof(TkMenuEntry, imagePtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_STRING, "-label", NULL, NULL,
	DEF_MENU_ENTRY_LABEL,
	Tk_Offset(TkMenuEntry, labelPtr), -1, 0, NULL, 0},
	offsetof(TkMenuEntry, labelPtr), TCL_INDEX_NONE, 0, NULL, 0},
    {TK_OPTION_STRING_TABLE, "-state", NULL, NULL,
	DEF_MENU_ENTRY_STATE,
	-1, Tk_Offset(TkMenuEntry, state), 0,
	TCL_INDEX_NONE, offsetof(TkMenuEntry, state), 0,
	(ClientData) menuStateStrings, 0},
    {TK_OPTION_INT, "-underline", NULL, NULL,
	DEF_MENU_ENTRY_UNDERLINE, -1, Tk_Offset(TkMenuEntry, underline), 0, NULL, 0},
	DEF_MENU_ENTRY_UNDERLINE, TCL_INDEX_NONE, offsetof(TkMenuEntry, underline), 0, NULL, 0},
    {TK_OPTION_END, NULL, NULL, NULL, 0, 0, 0, 0, NULL, 0}
};

static const Tk_OptionSpec tkSeparatorEntryConfigSpecs[] = {
    {TK_OPTION_BORDER, "-background", NULL, NULL,
	DEF_MENU_ENTRY_BG,
	Tk_Offset(TkMenuEntry, borderPtr), -1, TK_OPTION_NULL_OK, NULL, 0},
	offsetof(TkMenuEntry, borderPtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_END, NULL, NULL, NULL, 0, 0, 0, 0, NULL, 0}
};

static const Tk_OptionSpec tkCheckButtonEntryConfigSpecs[] = {
    {TK_OPTION_BOOLEAN, "-indicatoron", NULL, NULL,
	DEF_MENU_ENTRY_INDICATOR,
	-1, Tk_Offset(TkMenuEntry, indicatorOn), 0, NULL, 0},
	TCL_INDEX_NONE, offsetof(TkMenuEntry, indicatorOn), 0, NULL, 0},
    {TK_OPTION_STRING, "-offvalue", NULL, NULL,
	DEF_MENU_ENTRY_OFF_VALUE,
	Tk_Offset(TkMenuEntry, offValuePtr), -1, 0, NULL, 0},
	offsetof(TkMenuEntry, offValuePtr), TCL_INDEX_NONE, 0, NULL, 0},
    {TK_OPTION_STRING, "-onvalue", NULL, NULL,
	DEF_MENU_ENTRY_ON_VALUE,
	Tk_Offset(TkMenuEntry, onValuePtr), -1, 0, NULL, 0},
	offsetof(TkMenuEntry, onValuePtr), TCL_INDEX_NONE, 0, NULL, 0},
    {TK_OPTION_COLOR, "-selectcolor", NULL, NULL,
	DEF_MENU_ENTRY_SELECT,
	Tk_Offset(TkMenuEntry, indicatorFgPtr), -1, TK_OPTION_NULL_OK, NULL, 0},
	offsetof(TkMenuEntry, indicatorFgPtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_STRING, "-selectimage", NULL, NULL,
	DEF_MENU_ENTRY_SELECT_IMAGE,
	Tk_Offset(TkMenuEntry, selectImagePtr), -1, TK_OPTION_NULL_OK, NULL, 0},
	offsetof(TkMenuEntry, selectImagePtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_STRING, "-variable", NULL, NULL,
	DEF_MENU_ENTRY_CHECK_VARIABLE,
	Tk_Offset(TkMenuEntry, namePtr), -1, TK_OPTION_NULL_OK, NULL, 0},
	offsetof(TkMenuEntry, namePtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_END, NULL, NULL, NULL,
	NULL, 0, -1, 0, tkBasicMenuEntryConfigSpecs, 0}
	NULL, 0, TCL_INDEX_NONE, 0, tkBasicMenuEntryConfigSpecs, 0}
};

static const Tk_OptionSpec tkRadioButtonEntryConfigSpecs[] = {
    {TK_OPTION_BOOLEAN, "-indicatoron", NULL, NULL,
	DEF_MENU_ENTRY_INDICATOR,
	-1, Tk_Offset(TkMenuEntry, indicatorOn), 0, NULL, 0},
	TCL_INDEX_NONE, offsetof(TkMenuEntry, indicatorOn), 0, NULL, 0},
    {TK_OPTION_COLOR, "-selectcolor", NULL, NULL,
	DEF_MENU_ENTRY_SELECT,
	Tk_Offset(TkMenuEntry, indicatorFgPtr), -1, TK_OPTION_NULL_OK, NULL, 0},
	offsetof(TkMenuEntry, indicatorFgPtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_STRING, "-selectimage", NULL, NULL,
	DEF_MENU_ENTRY_SELECT_IMAGE,
	Tk_Offset(TkMenuEntry, selectImagePtr), -1, TK_OPTION_NULL_OK, NULL, 0},
	offsetof(TkMenuEntry, selectImagePtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_STRING, "-value", NULL, NULL,
	DEF_MENU_ENTRY_VALUE,
	Tk_Offset(TkMenuEntry, onValuePtr), -1, TK_OPTION_NULL_OK, NULL, 0},
	offsetof(TkMenuEntry, onValuePtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_STRING, "-variable", NULL, NULL,
	DEF_MENU_ENTRY_RADIO_VARIABLE,
	Tk_Offset(TkMenuEntry, namePtr), -1, 0, NULL, 0},
	offsetof(TkMenuEntry, namePtr), TCL_INDEX_NONE, 0, NULL, 0},
    {TK_OPTION_END, NULL, NULL, NULL,
	NULL, 0, -1, 0, tkBasicMenuEntryConfigSpecs, 0}
	NULL, 0, TCL_INDEX_NONE, 0, tkBasicMenuEntryConfigSpecs, 0}
};

static const Tk_OptionSpec tkCascadeEntryConfigSpecs[] = {
    {TK_OPTION_STRING, "-menu", NULL, NULL,
	DEF_MENU_ENTRY_MENU,
	Tk_Offset(TkMenuEntry, namePtr), -1, TK_OPTION_NULL_OK, NULL, 0},
	offsetof(TkMenuEntry, namePtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_END, NULL, NULL, NULL,
	NULL, 0, -1, 0, tkBasicMenuEntryConfigSpecs, 0}
	NULL, 0, TCL_INDEX_NONE, 0, tkBasicMenuEntryConfigSpecs, 0}
};

static const Tk_OptionSpec tkTearoffEntryConfigSpecs[] = {
    {TK_OPTION_BORDER, "-background", NULL, NULL,
	DEF_MENU_ENTRY_BG,
	Tk_Offset(TkMenuEntry, borderPtr), -1, TK_OPTION_NULL_OK, NULL, 0},
	offsetof(TkMenuEntry, borderPtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_STRING_TABLE, "-state", NULL, NULL,
	DEF_MENU_ENTRY_STATE, -1, Tk_Offset(TkMenuEntry, state), 0,
	DEF_MENU_ENTRY_STATE, TCL_INDEX_NONE, offsetof(TkMenuEntry, state), 0,
	(ClientData) menuStateStrings, 0},
    {TK_OPTION_END, NULL, NULL, NULL, 0, 0, 0, 0, NULL, 0}
};

static const Tk_OptionSpec *specsArray[] = {
    tkCascadeEntryConfigSpecs, tkCheckButtonEntryConfigSpecs,
    tkBasicMenuEntryConfigSpecs, tkRadioButtonEntryConfigSpecs,
246
247
248
249
250
251
252
253

254
255
256
257

258
259
260

261



262
263

264
265
266

267
268

269
270
271

272
273
274

275
276
277

278
279
280

281
282

283
284

285
286
287

288
289

290
291

292
293
294
295

296
297

298
299
300

301
302

303
304
305

306
307
308
309
310
311
312
246
247
248
249
250
251
252

253
254
255
256

257
258
259

260
261
262
263
264
265

266
267
268

269
270

271
272
273

274
275
276

277
278
279

280
281
282

283
284

285
286

287
288
289

290
291

292
293

294
295
296
297

298
299

300
301
302

303
304

305
306
307

308
309
310
311
312
313
314
315







-
+



-
+


-
+

+
+
+

-
+


-
+

-
+


-
+


-
+


-
+


-
+

-
+

-
+


-
+

-
+

-
+



-
+

-
+


-
+

-
+


-
+







static const char *const menuTypeStrings[] = {
    "normal", "tearoff", "menubar", NULL
};

static const Tk_OptionSpec tkMenuConfigSpecs[] = {
    {TK_OPTION_BORDER, "-activebackground", "activeBackground",
	"Foreground", DEF_MENU_ACTIVE_BG_COLOR,
	Tk_Offset(TkMenu, activeBorderPtr), -1, 0,
	offsetof(TkMenu, activeBorderPtr), TCL_INDEX_NONE, 0,
	(ClientData) DEF_MENU_ACTIVE_BG_MONO, 0},
    {TK_OPTION_PIXELS, "-activeborderwidth", "activeBorderWidth",
	"BorderWidth", DEF_MENU_ACTIVE_BORDER_WIDTH,
	Tk_Offset(TkMenu, activeBorderWidthPtr), -1, 0, NULL, 0},
	offsetof(TkMenu, activeBorderWidthPtr), TCL_INDEX_NONE, 0, NULL, 0},
    {TK_OPTION_COLOR, "-activeforeground", "activeForeground",
	"Background", DEF_MENU_ACTIVE_FG_COLOR,
	Tk_Offset(TkMenu, activeFgPtr), -1, 0,
	offsetof(TkMenu, activeFgPtr), TCL_INDEX_NONE, 0,
	(ClientData) DEF_MENU_ACTIVE_FG_MONO, 0},
    {TK_OPTION_RELIEF, "-activerelief", "activeRelief", "Relief",
	DEF_MENU_ACTIVE_RELIEF, offsetof(TkMenu, activeReliefPtr),
	TCL_INDEX_NONE, 0, NULL, 0},
    {TK_OPTION_BORDER, "-background", "background", "Background",
	DEF_MENU_BG_COLOR, Tk_Offset(TkMenu, borderPtr), -1, 0,
	DEF_MENU_BG_COLOR, offsetof(TkMenu, borderPtr), TCL_INDEX_NONE, 0,
	(ClientData) DEF_MENU_BG_MONO, 0},
    {TK_OPTION_SYNONYM, "-bd", NULL, NULL,
	NULL, 0, -1, 0, "-borderwidth", 0},
	NULL, 0, TCL_INDEX_NONE, 0, "-borderwidth", 0},
    {TK_OPTION_SYNONYM, "-bg", NULL, NULL,
	NULL, 0, -1, 0, "-background", 0},
	NULL, 0, TCL_INDEX_NONE, 0, "-background", 0},
    {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
	DEF_MENU_BORDER_WIDTH,
	Tk_Offset(TkMenu, borderWidthPtr), -1, 0, NULL, 0},
	offsetof(TkMenu, borderWidthPtr), TCL_INDEX_NONE, 0, NULL, 0},
    {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
	DEF_MENU_CURSOR,
	Tk_Offset(TkMenu, cursorPtr), -1, TK_OPTION_NULL_OK, NULL, 0},
	offsetof(TkMenu, cursorPtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground",
	"DisabledForeground", DEF_MENU_DISABLED_FG_COLOR,
	Tk_Offset(TkMenu, disabledFgPtr), -1, TK_OPTION_NULL_OK,
	offsetof(TkMenu, disabledFgPtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK,
	(ClientData) DEF_MENU_DISABLED_FG_MONO, 0},
    {TK_OPTION_SYNONYM, "-fg", NULL, NULL,
	NULL, 0, -1, 0, "-foreground", 0},
	NULL, 0, TCL_INDEX_NONE, 0, "-foreground", 0},
    {TK_OPTION_FONT, "-font", "font", "Font",
	DEF_MENU_FONT, Tk_Offset(TkMenu, fontPtr), -1, 0, NULL, 0},
	DEF_MENU_FONT, offsetof(TkMenu, fontPtr), TCL_INDEX_NONE, 0, NULL, 0},
    {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
	DEF_MENU_FG, Tk_Offset(TkMenu, fgPtr), -1, 0, NULL, 0},
	DEF_MENU_FG, offsetof(TkMenu, fgPtr), TCL_INDEX_NONE, 0, NULL, 0},
    {TK_OPTION_STRING, "-postcommand", "postCommand", "Command",
	DEF_MENU_POST_COMMAND,
	Tk_Offset(TkMenu, postCommandPtr), -1, TK_OPTION_NULL_OK, NULL, 0},
	offsetof(TkMenu, postCommandPtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
	DEF_MENU_RELIEF, Tk_Offset(TkMenu, reliefPtr), -1, 0, NULL, 0},
	DEF_MENU_RELIEF, offsetof(TkMenu, reliefPtr), TCL_INDEX_NONE, 0, NULL, 0},
    {TK_OPTION_COLOR, "-selectcolor", "selectColor", "Background",
	DEF_MENU_SELECT_COLOR, Tk_Offset(TkMenu, indicatorFgPtr), -1, 0,
	DEF_MENU_SELECT_COLOR, offsetof(TkMenu, indicatorFgPtr), TCL_INDEX_NONE, 0,
	(ClientData) DEF_MENU_SELECT_MONO, 0},
    {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
	DEF_MENU_TAKE_FOCUS,
	Tk_Offset(TkMenu, takeFocusPtr), -1, TK_OPTION_NULL_OK, NULL, 0},
	offsetof(TkMenu, takeFocusPtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_BOOLEAN, "-tearoff", "tearOff", "TearOff",
	DEF_MENU_TEAROFF, -1, Tk_Offset(TkMenu, tearoff), 0, NULL, 0},
	DEF_MENU_TEAROFF, TCL_INDEX_NONE, offsetof(TkMenu, tearoff), 0, NULL, 0},
    {TK_OPTION_STRING, "-tearoffcommand", "tearOffCommand",
	"TearOffCommand", DEF_MENU_TEAROFF_CMD,
	Tk_Offset(TkMenu, tearoffCommandPtr), -1, TK_OPTION_NULL_OK, NULL, 0},
	offsetof(TkMenu, tearoffCommandPtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_STRING, "-title", "title", "Title",
	DEF_MENU_TITLE,	 Tk_Offset(TkMenu, titlePtr), -1,
	DEF_MENU_TITLE,	 offsetof(TkMenu, titlePtr), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK, NULL, 0},
    {TK_OPTION_STRING_TABLE, "-type", "type", "Type",
	DEF_MENU_TYPE, Tk_Offset(TkMenu, menuTypePtr), -1, TK_OPTION_NULL_OK,
	DEF_MENU_TYPE, offsetof(TkMenu, menuTypePtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK,
	(ClientData) menuTypeStrings, 0},
    {TK_OPTION_END, NULL, NULL, NULL, 0, 0, 0, 0, NULL, 0}
};

/*
 * Command line options. Put here because MenuCmd has to look at them along
 * with MenuWidgetObjCmd.
339
340
341
342
343
344
345
346

347
348

349
350
351
352
353
354
355
356
357

358
359
360
361
362
363
364
365
366
367
368



369
370
371
372
373
374
375
342
343
344
345
346
347
348

349
350

351
352
353
354
355
356
357
358
359

360
361
362
363
364
365
366
367
368
369
370

371
372
373
374
375
376
377
378
379
380







-
+

-
+








-
+










-
+
+
+







			    int objc, Tcl_Obj *const objv[]);
static void		DeleteMenuCloneEntries(TkMenu *menuPtr,
			    int first, int last);
static void		DestroyMenuHashTable(ClientData clientData,
			    Tcl_Interp *interp);
static void		DestroyMenuInstance(TkMenu *menuPtr);
static void		DestroyMenuEntry(void *memPtr);
static int		GetIndexFromCoords(Tcl_Interp *interp,
static TkSizeT	GetIndexFromCoords(Tcl_Interp *interp,
			    TkMenu *menuPtr, const char *string,
			    int *indexPtr);
			    TkSizeT *indexPtr);
static int		MenuDoYPosition(Tcl_Interp *interp,
			    TkMenu *menuPtr, Tcl_Obj *objPtr);
static int		MenuDoXPosition(Tcl_Interp *interp,
			    TkMenu *menuPtr, Tcl_Obj *objPtr);
static int		MenuAddOrInsert(Tcl_Interp *interp,
			    TkMenu *menuPtr, Tcl_Obj *indexPtr, int objc,
			    Tcl_Obj *const objv[]);
static void		MenuCmdDeletedProc(ClientData clientData);
static TkMenuEntry *	MenuNewEntry(TkMenu *menuPtr, int index, int type);
static TkMenuEntry *	MenuNewEntry(TkMenu *menuPtr, TkSizeT index, int type);
static char *		MenuVarProc(ClientData clientData,
			    Tcl_Interp *interp, const char *name1,
			    const char *name2, int flags);
static int		MenuWidgetObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static void		MenuWorldChanged(ClientData instanceData);
static int		PostProcessEntry(TkMenuEntry *mePtr);
static void		RecursivelyDeleteMenu(TkMenu *menuPtr);
static void		UnhookCascadeEntry(TkMenuEntry *mePtr);
static void		TkMenuCleanup(ClientData unused);
static void		MenuCleanup(ClientData unused);
static int		GetMenuIndex(Tcl_Interp *interp, TkMenu *menuPtr,
			    Tcl_Obj *objPtr, int lastOK, TkSizeT *indexPtr);

/*
 * The structure below is a list of procs that respond to certain window
 * manager events. One of these includes a font change, which forces the
 * geometry proc to be called.
 */

400
401
402
403
404
405
406
407

408
409

410
411
412
413
414

415
416
417
418
419
420
421
405
406
407
408
409
410
411

412
413

414
415
416
417
418

419
420
421
422
423
424
425
426







-
+

-
+




-
+







int
Tk_MenuObjCmd(
    ClientData clientData,	/* Main window associated with interpreter. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument strings. */
{
    Tk_Window tkwin = clientData;
    Tk_Window tkwin = (Tk_Window)clientData;
    Tk_Window newWin;
    register TkMenu *menuPtr;
    TkMenu *menuPtr;
    TkMenuReferences *menuRefPtr;
    int i, index, toplevel;
    const char *windowName;
    static const char *const typeStringList[] = {"-type", NULL};
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "pathName ?-option value ...?");
	return TCL_ERROR;
    }

442
443
444
445
446
447
448
449

450
451
452
453
454
455
456
457

458
459

460
461
462
463
464
465
466
467
468

469
470
471
472
473
474
475
447
448
449
450
451
452
453

454
455
456
457
458
459
460
461

462
463

464
465
466
467
468
469
470
471
472

473
474
475
476
477
478
479
480







-
+







-
+

-
+








-
+








    /*
     * Initialize the data structure for the menu. Note that the menuPtr is
     * eventually freed in 'TkMenuEventProc' in tkMenuDraw.c, when
     * Tcl_EventuallyFree is called.
     */

    menuPtr = ckalloc(sizeof(TkMenu));
    menuPtr = (TkMenu *)ckalloc(sizeof(TkMenu));
    memset(menuPtr, 0, sizeof(TkMenu));
    menuPtr->tkwin = newWin;
    menuPtr->display = Tk_Display(newWin);
    menuPtr->interp = interp;
    menuPtr->widgetCmd = Tcl_CreateObjCommand(interp,
	    Tk_PathName(menuPtr->tkwin), MenuWidgetObjCmd, menuPtr,
	    MenuCmdDeletedProc);
    menuPtr->active = -1;
    menuPtr->active = TCL_INDEX_NONE;
    menuPtr->cursorPtr = NULL;
    menuPtr->masterMenuPtr = menuPtr;
    menuPtr->mainMenuPtr = menuPtr;
    menuPtr->menuType = UNKNOWN_TYPE;
    TkMenuInitializeDrawingFields(menuPtr);

    Tk_SetClass(menuPtr->tkwin, "Menu");
    Tk_SetClassProcs(menuPtr->tkwin, &menuClass, menuPtr);
    Tk_CreateEventHandler(newWin,
	    ExposureMask|StructureNotifyMask|ActivateMask,
	    TkMenuEventProc, menuPtr);
    if (Tk_InitOptions(interp, (char *) menuPtr,
    if (Tk_InitOptions(interp, menuPtr,
	    tsdPtr->menuOptionTable, menuPtr->tkwin)
	    != TCL_OK) {
    	Tk_DestroyWindow(menuPtr->tkwin);
    	return TCL_ERROR;
    }


509
510
511
512
513
514
515
516

517
518
519
520
521
522
523
524
525
526



527
528
529
530
531
532
533
514
515
516
517
518
519
520

521
522
523
524
525
526
527
528



529
530
531
532
533
534
535
536
537
538







-
+







-
-
-
+
+
+







	TkMenuEntry *nextCascadePtr;
	Tcl_Obj *newMenuName, *newObjv[2];

	while (cascadeListPtr != NULL) {
	    nextCascadePtr = cascadeListPtr->nextCascadePtr;

     	    /*
	     * If we have a new master menu, and an existing cloned menu
	     * If we have a new main menu, and an existing cloned menu
	     * points to this menu in a cascade entry, we have to clone the
	     * new menu and point the entry to the clone instead of the menu
	     * we are creating. Otherwise, ConfigureMenuEntry will hook up the
	     * platform-specific cascade linkages now that the menu we are
	     * creating exists.
     	     */

     	    if ((menuPtr->masterMenuPtr != menuPtr)
     	    	    || ((menuPtr->masterMenuPtr == menuPtr)
     	    	    && ((cascadeListPtr->menuPtr->masterMenuPtr
     	    if ((menuPtr->mainMenuPtr != menuPtr)
     	    	    || ((menuPtr->mainMenuPtr == menuPtr)
     	    	    && ((cascadeListPtr->menuPtr->mainMenuPtr
		    == cascadeListPtr->menuPtr)))) {
		newObjv[0] = Tcl_NewStringObj("-menu", -1);
		newObjv[1] = Tcl_NewStringObj(Tk_PathName(menuPtr->tkwin),-1);
		Tcl_IncrRefCount(newObjv[0]);
		Tcl_IncrRefCount(newObjv[1]);
     	    	ConfigureMenuEntry(cascadeListPtr, 2, newObjv);
		Tcl_DecrRefCount(newObjv[0]);
584
585
586
587
588
589
590
591

592
593
594
595
596
597
598
589
590
591
592
593
594
595

596
597
598
599
600
601
602
603







-
+







    	    listtkwin = topLevelListPtr->tkwin;
    	    TkSetWindowMenuBar(menuPtr->interp, listtkwin,
    	    	    Tk_PathName(menuPtr->tkwin), Tk_PathName(menuPtr->tkwin));
    	    topLevelListPtr = nextPtr;
    	}
    }

    Tcl_SetObjResult(interp, TkNewWindowObj(menuPtr->tkwin));
    Tcl_SetObjResult(interp, Tk_NewWindowObj(menuPtr->tkwin));
    return TCL_OK;
}

/*
 *--------------------------------------------------------------
 *
 * MenuWidgetObjCmd --
613
614
615
616
617
618
619
620
621


622
623
624

625
626
627
628
629
630
631
632
633
634
635
636
637
638
639

640
641
642
643
644
645

646
647
648
649
650
651

652
653

654
655
656
657
658
659
660
618
619
620
621
622
623
624


625
626
627
628

629
630
631
632
633
634
635
636
637
638
639
640
641
642
643

644
645
646
647
648
649

650
651
652
653
654
655

656
657

658
659
660
661
662
663
664
665







-
-
+
+


-
+














-
+





-
+





-
+

-
+







static int
MenuWidgetObjCmd(
    ClientData clientData,	/* Information about menu widget. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument strings. */
{
    register TkMenu *menuPtr = clientData;
    register TkMenuEntry *mePtr;
    TkMenu *menuPtr = (TkMenu *)clientData;
    TkMenuEntry *mePtr;
    int result = TCL_OK;
    int option;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
	return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObjStruct(interp, objv[1], menuOptions,
	    sizeof(char *), "option", 0, &option) != TCL_OK) {
	return TCL_ERROR;
    }
    Tcl_Preserve(menuPtr);

    switch ((enum options) option) {
    case MENU_ACTIVATE: {
	int index;
	TkSizeT index;

	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "index");
	    goto error;
	}
	if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) {
	if (GetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) {
	    goto error;
	}
	if (menuPtr->active == index) {
	    goto done;
	}
	if ((index >= 0) && ((menuPtr->entries[index]->type==SEPARATOR_ENTRY)
	if ((index != TCL_INDEX_NONE) && ((menuPtr->entries[index]->type==SEPARATOR_ENTRY)
		|| (menuPtr->entries[index]->state == ENTRY_DISABLED))) {
	    index = -1;
	    index = TCL_INDEX_NONE;
	}
	result = TkActivateMenuEntry(menuPtr, index);
	break;
    }
    case MENU_ADD:
	if (objc < 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "type ?-option value ...?");
668
669
670
671
672
673
674
675

676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695

696
697
698
699
700
701
702
703
704
705

706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723


724
725
726
727
728
729
730
731
732
733
734
735
736


737
738
739
740

741
742
743
744
745

746
747
748
749
750
751
752
753
754
755
756
757

758
759
760
761
762
763
764

765
766
767
768
769
770
771

772
773
774

775
776
777
778
779

780
781
782
783
784
785
786
787
788
789

790
791
792
793
794
795
796

797
798
799

800
801
802
803
804
805

806
807
808
809
810
811
812
813
814

815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830

831
832
833
834
835
836

837
838
839

840
841
842


843
844
845
846
847
848
849
850
851
852
853
854
855
856
857

858
859
860
861
862
863

864
865
866

867
868
869
870
871
872
873


874
875
876
877
878
879
880
881
882
883
884

885
886
887
888
889
890
891
673
674
675
676
677
678
679

680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699

700
701
702
703
704
705
706
707
708
709

710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727

728
729
730
731
732
733
734
735
736
737
738
739
740
741

742
743
744
745
746

747
748
749
750
751

752
753
754
755
756
757
758
759
760
761
762
763

764
765
766
767
768
769
770

771
772
773
774
775
776
777

778
779
780

781
782
783
784
785

786
787
788
789
790
791
792
793
794
795

796
797
798
799
800
801
802

803
804
805

806
807
808
809
810
811

812
813
814
815
816
817
818
819
820

821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836

837
838
839
840
841
842

843
844
845

846
847


848
849

850
851
852
853
854
855
856
857
858
859
860
861
862

863
864
865
866
867
868

869
870
871

872
873
874
875
876
877
878

879
880
881
882
883
884
885
886
887
888
889
890

891
892
893
894
895
896
897
898







-
+



















-
+









-
+

















-
+
+












-
+
+



-
+




-
+











-
+






-
+






-
+


-
+




-
+









-
+






-
+


-
+





-
+








-
+















-
+





-
+


-
+

-
-
+
+
-













-
+





-
+


-
+






-
+
+










-
+







    case MENU_CGET: {
	Tcl_Obj *resultPtr;

	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "option");
	    goto error;
	}
	resultPtr = Tk_GetOptionValue(interp, (char *) menuPtr,
	resultPtr = Tk_GetOptionValue(interp, menuPtr,
		tsdPtr->menuOptionTable, objv[2],
		menuPtr->tkwin);
	if (resultPtr == NULL) {
	    goto error;
	}
	Tcl_SetObjResult(interp, resultPtr);
	break;
    }
    case MENU_CLONE:
	if ((objc < 3) || (objc > 4)) {
	    Tcl_WrongNumArgs(interp, 2, objv, "newMenuName ?menuType?");
	    goto error;
	}
	result = CloneMenu(menuPtr, objv[2], (objc == 3) ? NULL : objv[3]);
	break;
    case MENU_CONFIGURE: {
	Tcl_Obj *resultPtr;

	if (objc == 2) {
	    resultPtr = Tk_GetOptionInfo(interp, (char *) menuPtr,
	    resultPtr = Tk_GetOptionInfo(interp, menuPtr,
		    tsdPtr->menuOptionTable, NULL,
		    menuPtr->tkwin);
	    if (resultPtr == NULL) {
		result = TCL_ERROR;
	    } else {
		result = TCL_OK;
		Tcl_SetObjResult(interp, resultPtr);
	    }
	} else if (objc == 3) {
	    resultPtr = Tk_GetOptionInfo(interp, (char *) menuPtr,
	    resultPtr = Tk_GetOptionInfo(interp, menuPtr,
		    tsdPtr->menuOptionTable, objv[2],
		    menuPtr->tkwin);
	    if (resultPtr == NULL) {
		result = TCL_ERROR;
	    } else {
		result = TCL_OK;
		Tcl_SetObjResult(interp, resultPtr);
	    }
	} else {
	    result = ConfigureMenu(interp, menuPtr, objc - 2, objv + 2);
	}
	if (result != TCL_OK) {
	    goto error;
	}
	break;
    }
    case MENU_DELETE: {
	int first, last;
	TkSizeT first, last;
	Tcl_WideInt w;

	if ((objc != 3) && (objc != 4)) {
	    Tcl_WrongNumArgs(interp, 2, objv, "first ?last?");
	    goto error;
	}

	/*
	 * If 'first' explicitly refers to past the end of the menu, we don't
	 * do anything. [Bug 220950]
	 */

	if (isdigit(UCHAR(Tcl_GetString(objv[2])[0]))
		&& Tcl_GetIntFromObj(NULL, objv[2], &first) == TCL_OK) {
		&& Tcl_GetWideIntFromObj(NULL, objv[2], &w) == TCL_OK) {
	    first = w;
	    if (first >= menuPtr->numEntries) {
		goto done;
	    }
	} else if (TkGetMenuIndex(interp,menuPtr,objv[2],0,&first) != TCL_OK){
	} else if (GetMenuIndex(interp,menuPtr,objv[2],0,&first) != TCL_OK){
	    goto error;
	}
	if (objc == 3) {
	    last = first;
	} else if (TkGetMenuIndex(interp,menuPtr,objv[3],0,&last) != TCL_OK) {
	} else if (GetMenuIndex(interp,menuPtr,objv[3],0,&last) != TCL_OK) {
	    goto error;
	}

	if (menuPtr->tearoff && (first == 0)) {
	    /*
	     * Sorry, can't delete the tearoff entry; must reconfigure the
	     * menu.
	     */

	    first = 1;
	}
	if ((first == -1) || (last < first)) {
	if ((first == TCL_INDEX_NONE) || (last < first)) {
	    goto done;
	}
	DeleteMenuCloneEntries(menuPtr, first, last);
	break;
    }
    case MENU_ENTRYCGET: {
	int index;
	TkSizeT index;
	Tcl_Obj *resultPtr;

	if (objc != 4) {
	    Tcl_WrongNumArgs(interp, 2, objv, "index option");
	    goto error;
	}
	if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) {
	if (GetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) {
	    goto error;
	}
	if (index < 0) {
	if (index == TCL_INDEX_NONE) {
	    goto done;
	}
	mePtr = menuPtr->entries[index];
	Tcl_Preserve(mePtr);
	resultPtr = Tk_GetOptionValue(interp, (char *) mePtr,
	resultPtr = Tk_GetOptionValue(interp, mePtr,
		mePtr->optionTable, objv[3], menuPtr->tkwin);
	Tcl_Release(mePtr);
	if (resultPtr == NULL) {
	    goto error;
	}
	Tcl_SetObjResult(interp, resultPtr);
	break;
    }
    case MENU_ENTRYCONFIGURE: {
	int index;
	TkSizeT index;
	Tcl_Obj *resultPtr;

	if (objc < 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "index ?-option value ...?");
	    goto error;
	}
	if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) {
	if (GetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) {
	    goto error;
	}
	if (index < 0) {
	if (index == TCL_INDEX_NONE) {
	    goto done;
	}
	mePtr = menuPtr->entries[index];
	Tcl_Preserve(mePtr);
	if (objc == 3) {
	    resultPtr = Tk_GetOptionInfo(interp, (char *) mePtr,
	    resultPtr = Tk_GetOptionInfo(interp, mePtr,
		    mePtr->optionTable, NULL, menuPtr->tkwin);
	    if (resultPtr == NULL) {
		result = TCL_ERROR;
	    } else {
		result = TCL_OK;
		Tcl_SetObjResult(interp, resultPtr);
	    }
	} else if (objc == 4) {
	    resultPtr = Tk_GetOptionInfo(interp, (char *) mePtr,
	    resultPtr = Tk_GetOptionInfo(interp, mePtr,
		    mePtr->optionTable, objv[3], menuPtr->tkwin);
	    if (resultPtr == NULL) {
		result = TCL_ERROR;
	    } else {
		result = TCL_OK;
		Tcl_SetObjResult(interp, resultPtr);
	    }
	} else {
	    result = ConfigureMenuCloneEntries(interp, menuPtr, index,
		    objc-3, objv+3);
	}
	Tcl_Release(mePtr);
	break;
    }
    case MENU_INDEX: {
	int index;
	TkSizeT index;

	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "string");
	    goto error;
	}
	if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) {
	if (GetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) {
	    goto error;
	}
	if (index < 0) {
	if (index == TCL_INDEX_NONE) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj("none", -1));
	} else {
	    Tcl_SetObjResult(interp, Tcl_NewIntObj(index));
	} else
	Tcl_SetObjResult(interp, TkNewIndexObj(index));
	}
	break;
    }
    case MENU_INSERT:
	if (objc < 4) {
	    Tcl_WrongNumArgs(interp, 2, objv,
		    "index type ?-option value ...?");
	    goto error;
	}
	if (MenuAddOrInsert(interp,menuPtr,objv[2],objc-3,objv+3) != TCL_OK) {
	    goto error;
	}
	break;
    case MENU_INVOKE: {
	int index;
	TkSizeT index;

	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "index");
	    goto error;
	}
	if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) {
	if (GetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) {
	    goto error;
	}
	if (index < 0) {
	if (index == TCL_INDEX_NONE) {
	    goto done;
	}
	result = TkInvokeMenu(interp, menuPtr, index);
	break;
    }
    case MENU_POST: {
	int x, y, index = -1;
	int x, y;
	TkSizeT index = TCL_INDEX_NONE;

	if (objc != 4 && objc != 5) {
	    Tcl_WrongNumArgs(interp, 2, objv, "x y ?index?");
	    goto error;
	}
	if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK)
		|| (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) {
	    goto error;
	}
	if (objc == 5) {
            if (TkGetMenuIndex(interp, menuPtr, objv[4], 0, &index) != TCL_OK) {
            if (GetMenuIndex(interp, menuPtr, objv[4], 0, &index) != TCL_OK) {
                goto error;
            }
	}

	/*
	 * Tearoff menus are the same as ordinary menus on the Mac and are
	 * posted differently on Windows than non-tearoffs. TkpPostMenu
901
902
903
904
905
906
907
908

909
910
911
912
913
914
915

916
917
918

919
920
921
922
923
924
925
926

927
928
929
930
931
932
933

934
935
936

937
938
939
940
941
942
943
908
909
910
911
912
913
914

915
916
917
918
919
920
921

922
923
924

925
926
927
928
929
930
931
932

933
934
935
936
937
938
939

940
941
942

943
944
945
946
947
948
949
950







-
+






-
+


-
+







-
+






-
+


-
+







	    result = TkpPostMenu(interp, menuPtr, x, y, index);
	} else {
	    result = TkpPostTearoffMenu(interp, menuPtr, x, y, index);
	}
	break;
    }
    case MENU_POSTCASCADE: {
	int index;
	TkSizeT index;

	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "index");
	    goto error;
	}

	if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) {
	if (GetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) {
	    goto error;
	}
	if ((index < 0) || (menuPtr->entries[index]->type != CASCADE_ENTRY)) {
	if ((index == TCL_INDEX_NONE) || (menuPtr->entries[index]->type != CASCADE_ENTRY)) {
	    result = TkPostSubmenu(interp, menuPtr, NULL);
	} else {
	    result = TkPostSubmenu(interp, menuPtr, menuPtr->entries[index]);
	}
	break;
    }
    case MENU_TYPE: {
	int index;
	TkSizeT index;
	const char *typeStr;

	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "index");
	    goto error;
	}
	if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) {
	if (GetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) {
	    goto error;
	}
	if (index < 0) {
	if (index == TCL_INDEX_NONE) {
	    goto done;
	}
	if (menuPtr->entries[index]->type == TEAROFF_ENTRY) {
	    typeStr = "tearoff";
	} else {
	    typeStr = menuEntryTypeStrings[menuPtr->entries[index]->type];
	}
994
995
996
997
998
999
1000
1001

1002
1003
1004
1005
1006
1007

1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022

1023
1024
1025
1026
1027
1028
1029
1001
1002
1003
1004
1005
1006
1007

1008
1009
1010
1011
1012
1013

1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028

1029
1030
1031
1032
1033
1034
1035
1036







-
+





-
+














-
+







 *----------------------------------------------------------------------
 */

int
TkInvokeMenu(
    Tcl_Interp *interp,		/* The interp that the menu lives in. */
    TkMenu *menuPtr,		/* The menu we are invoking. */
    int index)			/* The zero based index of the item we are
    TkSizeT index)			/* The zero based index of the item we are
    				 * invoking. */
{
    int result = TCL_OK;
    TkMenuEntry *mePtr;

    if (index < 0) {
    if (index == TCL_INDEX_NONE) {
    	goto done;
    }
    mePtr = menuPtr->entries[index];
    if (mePtr->state == ENTRY_DISABLED) {
	goto done;
    }

    Tcl_Preserve(mePtr);
    if (mePtr->type == TEAROFF_ENTRY) {
	Tcl_DString ds;

	Tcl_DStringInit(&ds);
	Tcl_DStringAppend(&ds, "tk::TearOffMenu ", -1);
	Tcl_DStringAppend(&ds, Tk_PathName(menuPtr->tkwin), -1);
	result = Tcl_EvalEx(interp, Tcl_DStringValue(&ds), -1, 0);
	result = Tcl_EvalEx(interp, Tcl_DStringValue(&ds), -1, TCL_EVAL_GLOBAL);
	Tcl_DStringFree(&ds);
    } else if ((mePtr->type == CHECK_BUTTON_ENTRY)
	    && (mePtr->namePtr != NULL)) {
	Tcl_Obj *valuePtr;

	if (mePtr->entryFlags & ENTRY_SELECTED) {
	    valuePtr = mePtr->offValuePtr;
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105



1106
1107
1108
1109
1110
1111
1112
1113
1114


1115
1116
1117

1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135

1136
1137
1138
1139
1140



1141
1142

1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162


1163
1164
1165
1166
1167
1168
1169
1170
1171
1172

1173
1174
1175
1176
1177
1178
1179
1103
1104
1105
1106
1107
1108
1109



1110
1111
1112
1113
1114
1115
1116
1117
1118
1119


1120
1121
1122
1123

1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141

1142
1143
1144



1145
1146
1147
1148

1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167


1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178

1179
1180
1181
1182
1183
1184
1185
1186







-
-
-
+
+
+







-
-
+
+


-
+

















-
+


-
-
-
+
+
+

-
+


















-
-
+
+









-
+







DestroyMenuInstance(
    TkMenu *menuPtr)		/* Info about menu widget. */
{
    int i;
    TkMenu *menuInstancePtr;
    TkMenuEntry *cascadePtr, *nextCascadePtr;
    Tcl_Obj *newObjv[2];
    TkMenu *parentMasterMenuPtr;
    TkMenuEntry *parentMasterEntryPtr;
    ThreadSpecificData *tsdPtr =
    TkMenu *parentMainMenuPtr;
    TkMenuEntry *parentMainEntryPtr;
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    /*
     * If the menu has any cascade menu entries pointing to it, the cascade
     * entries need to be told that the menu is going away. We need to clear
     * the menu ptr field in the menu reference at this point in the code so
     * that everything else can forget about this menu properly. We also need
     * to reset -menu field of all entries that are not master menus back to
     * this entry name if this is a master menu pointed to by another master
     * to reset -menu field of all entries that are not main menus back to
     * this entry name if this is a main menu pointed to by another main
     * menu. If there is a clone menu that points to this menu, then this menu
     * is itself a clone, so when this menu goes away, the -menu field of the
     * pointing entry must be set back to this menu's master menu name so that
     * pointing entry must be set back to this menu's main menu name so that
     * later if another menu is created the cascade hierarchy can be
     * maintained.
     */

    TkpDestroyMenu(menuPtr);
    if (menuPtr->menuRefPtr == NULL) {
	return;
    }
    cascadePtr = menuPtr->menuRefPtr->parentEntryPtr;
    menuPtr->menuRefPtr->menuPtr = NULL;
    if (TkFreeMenuReferences(menuPtr->menuRefPtr)) {
	menuPtr->menuRefPtr = NULL;
    }

    for (; cascadePtr != NULL; cascadePtr = nextCascadePtr) {
    	nextCascadePtr = cascadePtr->nextCascadePtr;

    	if (menuPtr->masterMenuPtr != menuPtr) {
    	if (menuPtr->mainMenuPtr != menuPtr) {
	    Tcl_Obj *menuNamePtr = Tcl_NewStringObj("-menu", -1);

	    parentMasterMenuPtr = cascadePtr->menuPtr->masterMenuPtr;
	    parentMasterEntryPtr =
		    parentMasterMenuPtr->entries[cascadePtr->index];
	    parentMainMenuPtr = cascadePtr->menuPtr->mainMenuPtr;
	    parentMainEntryPtr =
		    parentMainMenuPtr->entries[cascadePtr->index];
	    newObjv[0] = menuNamePtr;
	    newObjv[1] = parentMasterEntryPtr->namePtr;
	    newObjv[1] = parentMainEntryPtr->namePtr;

	    /*
	     * It is possible that the menu info is out of sync, and these
	     * things point to NULL, so verify existence [Bug: 3402]
	     */

	    if (newObjv[0] && newObjv[1]) {
		Tcl_IncrRefCount(newObjv[0]);
		Tcl_IncrRefCount(newObjv[1]);
		ConfigureMenuEntry(cascadePtr, 2, newObjv);
		Tcl_DecrRefCount(newObjv[0]);
		Tcl_DecrRefCount(newObjv[1]);
	    }
    	} else {
    	    ConfigureMenuEntry(cascadePtr, 0, NULL);
    	}
    }

    if (menuPtr->masterMenuPtr != menuPtr) {
	for (menuInstancePtr = menuPtr->masterMenuPtr;
    if (menuPtr->mainMenuPtr != menuPtr) {
	for (menuInstancePtr = menuPtr->mainMenuPtr;
		menuInstancePtr != NULL;
		menuInstancePtr = menuInstancePtr->nextInstancePtr) {
	    if (menuInstancePtr->nextInstancePtr == menuPtr) {
		menuInstancePtr->nextInstancePtr =
			menuInstancePtr->nextInstancePtr->nextInstancePtr;
		break;
	    }
	}
    } else if (menuPtr->nextInstancePtr != NULL) {
	Tcl_Panic("Attempting to delete master menu when there are still clones");
	Tcl_Panic("Attempting to delete main menu when there are still clones");
    }

    /*
     * Free up all the stuff that requires special handling, then let
     * Tk_FreeConfigOptions handle all the standard option-related stuff.
     */

1205
1206
1207
1208
1209
1210
1211
1212
1213


1214
1215
1216
1217
1218
1219
1220
1212
1213
1214
1215
1216
1217
1218


1219
1220
1221
1222
1223
1224
1225
1226
1227







-
-
+
+







/*
 *----------------------------------------------------------------------
 *
 * TkDestroyMenu --
 *
 *	This function is invoked by Tcl_EventuallyFree or Tcl_Release to clean
 *	up the internal structure of a menu at a safe time (when no-one is
 *	using it anymore). If called on a master instance, destroys all of the
 *	slave instances. If called on a non-master instance, just destroys
 *	using it anymore). If called on a main instance, destroys all of the
 *	instances. If called on a non-main instance, just destroys
 *	that instance.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Everything associated with the menu is freed up.
1252
1253
1254
1255
1256
1257
1258
1259

1260
1261
1262
1263
1264
1265
1266
1259
1260
1261
1262
1263
1264
1265

1266
1267
1268
1269
1270
1271
1272
1273







-
+







	topLevelListPtr = menuPtr->menuRefPtr->topLevelListPtr;
	while (topLevelListPtr != NULL) {
	    nextTopLevelPtr = topLevelListPtr->nextPtr;
	    TkpSetWindowMenuBar(topLevelListPtr->tkwin, NULL);
	    topLevelListPtr = nextTopLevelPtr;
	}
    }
    if (menuPtr->masterMenuPtr == menuPtr) {
    if (menuPtr->mainMenuPtr == menuPtr) {
	while (menuPtr->nextInstancePtr != NULL) {
	    menuInstancePtr = menuPtr->nextInstancePtr;
	    menuPtr->nextInstancePtr = menuInstancePtr->nextInstancePtr;
    	    if (menuInstancePtr->tkwin != NULL) {
		Tk_Window tkwin = menuInstancePtr->tkwin;

		/*
1381
1382
1383
1384
1385
1386
1387
1388

1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407

1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427

1428
1429
1430
1431
1432
1433
1434
1388
1389
1390
1391
1392
1393
1394

1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413

1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433

1434
1435
1436
1437
1438
1439
1440
1441







-
+


















-
+



















-
+







 *----------------------------------------------------------------------
 */

static void
DestroyMenuEntry(
    void *memPtr)		/* Pointer to entry to be freed. */
{
    register TkMenuEntry *mePtr = memPtr;
    TkMenuEntry *mePtr = (TkMenuEntry *)memPtr;
    TkMenu *menuPtr = mePtr->menuPtr;

    if (menuPtr->postedCascade == mePtr) {
    	/*
	 * Ignore errors while unposting the menu, since it's possible that
	 * the menu has already been deleted and the unpost will generate an
	 * error.
	 */

	TkPostSubmenu(menuPtr->interp, menuPtr, NULL);
    }

    /*
     * Free up all the stuff that requires special handling, then let
     * Tk_FreeConfigOptions handle all the standard option-related stuff.
     */

    if (mePtr->type == CASCADE_ENTRY) {
	if (menuPtr->masterMenuPtr != menuPtr) {
	if (menuPtr->mainMenuPtr != menuPtr) {
	    TkMenu *destroyThis = NULL;
	    TkMenuReferences *menuRefPtr = mePtr->childMenuRefPtr;

	    /*
	     * The menu as a whole is a clone. We must delete the clone of the
	     * cascaded menu for the particular entry we are destroying.
	     */

	    if (menuRefPtr != NULL) {
		destroyThis = menuRefPtr->menuPtr;

		/*
		 * But only if it is a clone. What can happen is that we are
		 * in the middle of deleting a menu and this menu pointer has
		 * already been reset to point to the original menu. In that
		 * case we have nothing special to do.
		 */

		if ((destroyThis != NULL)
			&& (destroyThis->masterMenuPtr == destroyThis)) {
			&& (destroyThis->mainMenuPtr == destroyThis)) {
		    destroyThis = NULL;
		}
	    }
	    UnhookCascadeEntry(mePtr);
	    menuRefPtr = mePtr->childMenuRefPtr;
	    if (menuRefPtr != NULL) {
		if (menuRefPtr->menuPtr == destroyThis) {
1481
1482
1483
1484
1485
1486
1487
1488
1489


1490
1491
1492
1493
1494
1495
1496
1488
1489
1490
1491
1492
1493
1494


1495
1496
1497
1498
1499
1500
1501
1502
1503







-
-
+
+







 *---------------------------------------------------------------------------
 */

static void
MenuWorldChanged(
    ClientData instanceData)	/* Information about widget. */
{
    TkMenu *menuPtr = instanceData;
    int i;
    TkMenu *menuPtr = (TkMenu *)instanceData;
    TkSizeT i;

    TkMenuConfigureDrawOptions(menuPtr);
    for (i = 0; i < menuPtr->numEntries; i++) {
    	TkMenuConfigureEntryDrawOptions(menuPtr->entries[i],
		menuPtr->entries[i]->index);
	TkpConfigureMenuEntry(menuPtr->entries[i]);
    }
1515
1516
1517
1518
1519
1520
1521
1522

1523
1524
1525
1526
1527
1528
1529
1530

1531
1532
1533

1534
1535
1536


1537
1538
1539
1540

1541
1542
1543
1544
1545
1546
1547
1522
1523
1524
1525
1526
1527
1528

1529
1530
1531
1532
1533
1534
1535
1536

1537
1538
1539

1540
1541


1542
1543
1544
1545
1546

1547
1548
1549
1550
1551
1552
1553
1554







-
+







-
+


-
+

-
-
+
+



-
+







 *
 *----------------------------------------------------------------------
 */

static int
ConfigureMenu(
    Tcl_Interp *interp,		/* Used for error reporting. */
    register TkMenu *menuPtr,	/* Information about widget; may or may not
    TkMenu *menuPtr,	/* Information about widget; may or may not
				 * already have values for some fields. */
    int objc,			/* Number of valid entries in argv. */
    Tcl_Obj *const objv[])	/* Arguments. */
{
    int i;
    TkMenu *menuListPtr, *cleanupPtr;
    int result;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    for (menuListPtr = menuPtr->masterMenuPtr; menuListPtr != NULL;
    for (menuListPtr = menuPtr->mainMenuPtr; menuListPtr != NULL;
	    menuListPtr = menuListPtr->nextInstancePtr) {
	menuListPtr->errorStructPtr = ckalloc(sizeof(Tk_SavedOptions));
	result = Tk_SetOptions(interp, (char *) menuListPtr,
	menuListPtr->errorStructPtr = (Tk_SavedOptions *)ckalloc(sizeof(Tk_SavedOptions));
	result = Tk_SetOptions(interp, menuListPtr,
		tsdPtr->menuOptionTable, objc, objv,
		menuListPtr->tkwin, menuListPtr->errorStructPtr, NULL);
	if (result != TCL_OK) {
	    for (cleanupPtr = menuPtr->masterMenuPtr;
	    for (cleanupPtr = menuPtr->mainMenuPtr;
		    cleanupPtr != menuListPtr;
		    cleanupPtr = cleanupPtr->nextInstancePtr) {
		Tk_RestoreSavedOptions(cleanupPtr->errorStructPtr);
		ckfree(cleanupPtr->errorStructPtr);
		cleanupPtr->errorStructPtr = NULL;
	    }
	    if (menuListPtr->errorStructPtr != NULL) {
1567
1568
1569
1570
1571
1572
1573
1574

1575
1576
1577
1578
1579
1580
1581
1574
1575
1576
1577
1578
1579
1580

1581
1582
1583
1584
1585
1586
1587
1588







-
+







	     * Configure the new window to be either a pop-up menu or a
	     * tear-off menu. We don't do this for menubars since they are not
	     * toplevel windows. Also, since this gets called before CloneMenu
	     * has a chance to set the menuType field, we have to look at the
	     * menuTypeName field to tell that this is a menu bar.
	     */

	    if (menuListPtr->menuType == MASTER_MENU) {
	    if (menuListPtr->menuType == MAIN_MENU) {
		int typeFlag = TK_MAKE_MENU_POPUP;
		Tk_Window tkwin = menuPtr->tkwin;

		/*
		 * Work out if we are the child of a menubar or a popup.
		 */

1602
1603
1604
1605
1606
1607
1608
1609

1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630

1631
1632
1633
1634
1635

1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650

1651
1652
1653
1654
1655
1656
1657
1658
1659
1660

1661
1662
1663
1664
1665
1666
1667
1609
1610
1611
1612
1613
1614
1615

1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632

1633
1634
1635

1636
1637
1638
1639


1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654

1655
1656
1657
1658
1659
1660
1661
1662
1663
1664

1665
1666
1667
1668
1669
1670
1671
1672







-
+
















-



-
+



-
-
+














-
+









-
+







	 * an initial tear-off entry at the beginning of the menu.
	 */

	if (menuListPtr->tearoff) {
	    if ((menuListPtr->numEntries == 0)
		    || (menuListPtr->entries[0]->type != TEAROFF_ENTRY)) {
		if (MenuNewEntry(menuListPtr, 0, TEAROFF_ENTRY) == NULL) {
		    for (cleanupPtr = menuPtr->masterMenuPtr;
		    for (cleanupPtr = menuPtr->mainMenuPtr;
			    cleanupPtr != menuListPtr;
			    cleanupPtr = cleanupPtr->nextInstancePtr) {
			Tk_RestoreSavedOptions(cleanupPtr->errorStructPtr);
			ckfree(cleanupPtr->errorStructPtr);
			cleanupPtr->errorStructPtr = NULL;
		    }
		    if (menuListPtr->errorStructPtr != NULL) {
			Tk_RestoreSavedOptions(menuListPtr->errorStructPtr);
			ckfree(menuListPtr->errorStructPtr);
			menuListPtr->errorStructPtr = NULL;
		    }
		    return TCL_ERROR;
		}
	    }
	} else if ((menuListPtr->numEntries > 0)
		&& (menuListPtr->entries[0]->type == TEAROFF_ENTRY)) {
	    int i;

	    Tcl_EventuallyFree(menuListPtr->entries[0], (Tcl_FreeProc *) DestroyMenuEntry);

	    for (i = 0; i < menuListPtr->numEntries - 1; i++) {
	    for (i = 0; i < (int)menuListPtr->numEntries - 1; i++) {
		menuListPtr->entries[i] = menuListPtr->entries[i + 1];
		menuListPtr->entries[i]->index = i;
	    }
	    menuListPtr->numEntries--;
	    if (menuListPtr->numEntries == 0) {
	    if (--menuListPtr->numEntries == 0) {
		ckfree(menuListPtr->entries);
		menuListPtr->entries = NULL;
	    }
	}

	TkMenuConfigureDrawOptions(menuListPtr);

	/*
	 * After reconfiguring a menu, we need to reconfigure all of the
	 * entries in the menu, since some of the things in the children (such
	 * as graphics contexts) may have to change to reflect changes in the
	 * parent.
	 */

	for (i = 0; i < menuListPtr->numEntries; i++) {
	for (i = 0; i < (int)menuListPtr->numEntries; i++) {
	    TkMenuEntry *mePtr;

	    mePtr = menuListPtr->entries[i];
	    ConfigureMenuEntry(mePtr, 0, NULL);
	}

	TkEventuallyRecomputeMenu(menuListPtr);
    }

    for (cleanupPtr = menuPtr->masterMenuPtr; cleanupPtr != NULL;
    for (cleanupPtr = menuPtr->mainMenuPtr; cleanupPtr != NULL;
	    cleanupPtr = cleanupPtr->nextInstancePtr) {
	Tk_FreeSavedOptions(cleanupPtr->errorStructPtr);
	ckfree(cleanupPtr->errorStructPtr);
	cleanupPtr->errorStructPtr = NULL;
    }

    return TCL_OK;
1701
1702
1703
1704
1705
1706
1707
1708

1709
1710
1711
1712
1713

1714
1715
1716
1717
1718
1719
1720
1706
1707
1708
1709
1710
1711
1712

1713
1714
1715
1716
1717

1718
1719
1720
1721
1722
1723
1724
1725







-
+




-
+







     * Tk_ConfigureWidget, such as special processing for defaults, sizing
     * strings, graphics contexts, etc.
     */

    if (mePtr->labelPtr == NULL) {
	mePtr->labelLength = 0;
    } else {
	Tcl_GetStringFromObj(mePtr->labelPtr, &mePtr->labelLength);
	(void)TkGetStringFromObj(mePtr->labelPtr, &mePtr->labelLength);
    }
    if (mePtr->accelPtr == NULL) {
	mePtr->accelLength = 0;
    } else {
	Tcl_GetStringFromObj(mePtr->accelPtr, &mePtr->accelLength);
	(void)TkGetStringFromObj(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
     * cascades have to be updated.
     */
1733
1734
1735
1736
1737
1738
1739
1740

1741
1742
1743
1744
1745
1746
1747
1738
1739
1740
1741
1742
1743
1744

1745
1746
1747
1748
1749
1750
1751
1752







-
+







	 * the list of entries pointing to the new menu.
	 *
	 * BUG: We are not recloning for special case #3 yet.
	 */

	name = Tcl_GetString(mePtr->namePtr);
	if (mePtr->childMenuRefPtr != NULL) {
	    oldHashKey = Tcl_GetHashKey(TkGetMenuHashTable(menuPtr->interp),
	    oldHashKey = (char *)Tcl_GetHashKey(TkGetMenuHashTable(menuPtr->interp),
		    mePtr->childMenuRefPtr->hashEntryPtr);
	    if (strcmp(oldHashKey, name) != 0) {
		UnhookCascadeEntry(mePtr);
	    }
	}

	if ((mePtr->childMenuRefPtr == NULL)
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1820
1821
1822
1823
1824
1825
1826

1827
1828
1829
1830
1831
1832
1833







-







	Tk_FreeImage(mePtr->selectImage);
    }
    mePtr->selectImage = image;

    if ((mePtr->type == CHECK_BUTTON_ENTRY)
	    || (mePtr->type == RADIO_BUTTON_ENTRY)) {
	Tcl_Obj *valuePtr;
	const char *name;

	if (mePtr->namePtr == NULL) {
	    if (mePtr->labelPtr == NULL) {
		mePtr->namePtr = NULL;
	    } else {
		mePtr->namePtr = Tcl_DuplicateObj(mePtr->labelPtr);
		Tcl_IncrRefCount(mePtr->namePtr);
1899
1900
1901
1902
1903
1904
1905
1906

1907
1908
1909
1910
1911
1912
1913
1903
1904
1905
1906
1907
1908
1909

1910
1911
1912
1913
1914
1915
1916
1917







-
+







 *	mePtr; old resources get freed, if there were any.
 *
 *----------------------------------------------------------------------
 */

static int
ConfigureMenuEntry(
    register TkMenuEntry *mePtr,/* Information about menu entry; may or may
    TkMenuEntry *mePtr,/* Information about menu entry; may or may
				 * not already have values for some fields. */
    int objc,			/* Number of valid entries in argv. */
    Tcl_Obj *const objv[])	/* Arguments. */
{
    TkMenu *menuPtr = mePtr->menuPtr;
    Tk_SavedOptions errorStruct;
    int result;
1925
1926
1927
1928
1929
1930
1931
1932

1933
1934
1935
1936
1937
1938
1939
1929
1930
1931
1932
1933
1934
1935

1936
1937
1938
1939
1940
1941
1942
1943







-
+







	Tcl_UntraceVar2(menuPtr->interp, name, NULL,
		TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
		MenuVarProc, mePtr);
    }

    result = TCL_OK;
    if (menuPtr->tkwin != NULL) {
	if (Tk_SetOptions(menuPtr->interp, (char *) mePtr,
	if (Tk_SetOptions(menuPtr->interp, mePtr,
		mePtr->optionTable, objc, objv, menuPtr->tkwin,
		&errorStruct, NULL) != TCL_OK) {
	    return TCL_ERROR;
	}
	result = PostProcessEntry(mePtr);
	if (result != TCL_OK) {
	    Tk_RestoreSavedOptions(&errorStruct);
1963
1964
1965
1966
1967
1968
1969
1970

1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981

1982
1983
1984
1985

1986
1987
1988
1989
1990
1991
1992

1993
1994
1995
1996
1997
1998
1999
1967
1968
1969
1970
1971
1972
1973

1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989

1990
1991
1992
1993
1994
1995
1996

1997
1998
1999
2000
2001
2002
2003
2004







-
+











+



-
+






-
+







 *	mePtr; old resources get freed, if there were any.
 *
 *----------------------------------------------------------------------
 */

static int
ConfigureMenuCloneEntries(
    Tcl_Interp *interp,		/* Used for error reporting. */
    Tcl_Interp *dummy,		/* Used for error reporting. */
    TkMenu *menuPtr,		/* Information about whole menu. */
    int index,			/* Index of mePtr within menuPtr's entries. */
    int objc,			/* Number of valid entries in argv. */
    Tcl_Obj *const objv[])	/* Arguments. */
{
    TkMenuEntry *mePtr;
    TkMenu *menuListPtr;
    int cascadeEntryChanged = 0;
    TkMenuReferences *oldCascadeMenuRefPtr, *cascadeMenuRefPtr = NULL;
    Tcl_Obj *oldCascadePtr = NULL;
    const char *newCascadeName;
    (void)dummy;

    /*
     * Cascades are kind of tricky here. This is special case #3 in the
     * comment at the top of this file. Basically, if a menu is the master
     * comment at the top of this file. Basically, if a menu is the main
     * menu of a clone chain, and has an entry with a cascade menu, the clones
     * of the menu will point to clones of the cascade menu. We have to
     * destroy the clones of the cascades, clone the new cascade menu, and
     * configure the entry to point to the new clone.
     */

    mePtr = menuPtr->masterMenuPtr->entries[index];
    mePtr = menuPtr->mainMenuPtr->entries[index];
    if (mePtr->type == CASCADE_ENTRY) {
	oldCascadePtr = mePtr->namePtr;
	if (oldCascadePtr != NULL) {
	    Tcl_IncrRefCount(oldCascadePtr);
	}
    }

2030
2031
2032
2033
2034
2035
2036
2037

2038
2039
2040
2041
2042
2043
2044
2035
2036
2037
2038
2039
2040
2041

2042
2043
2044
2045
2046
2047
2048
2049







-
+







	if (mePtr->namePtr != NULL) {
	    newCascadeName = Tcl_GetString(mePtr->namePtr);
	    cascadeMenuRefPtr = TkFindMenuReferences(menuPtr->interp,
		    newCascadeName);
	}
    }

    for (menuListPtr = menuPtr->masterMenuPtr->nextInstancePtr;
    for (menuListPtr = menuPtr->mainMenuPtr->nextInstancePtr;
    	    menuListPtr != NULL;
	    menuListPtr = menuListPtr->nextInstancePtr) {

    	mePtr = menuListPtr->entries[index];

	if (cascadeEntryChanged && (mePtr->namePtr != NULL)) {
	    oldCascadeMenuRefPtr = TkFindMenuReferencesObj(menuPtr->interp,
2085
2086
2087
2088
2089
2090
2091
2092

2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110

2111
2112
2113
2114
2115
2116
2117
2118

2119
2120
2121













2122
2123
2124
2125
2126
2127
2128

2129
2130
2131
2132
2133
2134
2135

2136
2137
2138
2139
2140

2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163

2164
2165
2166
2167
2168
2169
2170
2090
2091
2092
2093
2094
2095
2096

2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114

2115
2116
2117
2118
2119
2120
2121
2122

2123
2124
2125

2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144

2145

2146
2147
2148
2149
2150

2151
2152
2153
2154
2155

2156
2157
2158
2159
2160
2161


















2162
2163
2164
2165
2166
2167
2168
2169







-
+

















-
+







-
+


-
+
+
+
+
+
+
+
+
+
+
+
+
+






-
+
-





-
+




-
+





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+







    }
    return TCL_OK;
}

/*
 *--------------------------------------------------------------
 *
 * TkGetMenuIndex --
 * GetMenuIndex --
 *
 *	Parse a textual index into a menu and return the numerical index of
 *	the indicated entry.
 *
 * Results:
 *	A standard Tcl result. If all went well, then *indexPtr is filled in
 *	with the entry index corresponding to string (ranges from -1 to the
 *	number of entries in the menu minus one). Otherwise an error message
 *	is left in the interp's result.
 *
 * Side effects:
 *	None.
 *
 *--------------------------------------------------------------
 */

int
TkGetMenuIndex(
GetMenuIndex(
    Tcl_Interp *interp,		/* For error messages. */
    TkMenu *menuPtr,		/* Menu for which the index is being
				 * specified. */
    Tcl_Obj *objPtr,		/* Specification of an entry in menu. See
				 * manual entry for valid .*/
    int lastOK,			/* Non-zero means its OK to return index just
				 * *after* last entry. */
    int *indexPtr)		/* Where to store converted index. */
    TkSizeT *indexPtr)		/* Where to store converted index. */
{
    int i;
    const char *string = Tcl_GetString(objPtr);
    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) {
		*indexPtr = menuPtr->numEntries - ((lastOK) ? 0 : 1);
	    }
	    return TCL_OK;
	}
    }

    string = Tcl_GetString(objPtr);

    if ((string[0] == 'a') && (strcmp(string, "active") == 0)) {
	*indexPtr = menuPtr->active;
	goto success;
    }

    if (((string[0] == 'l') && (strcmp(string, "last") == 0))
    if ((string[0] == 'l') && (strcmp(string, "last") == 0)) {
	    || ((string[0] == 'e') && (strcmp(string, "end") == 0))) {
	*indexPtr = menuPtr->numEntries - ((lastOK) ? 0 : 1);
	goto success;
    }

    if ((string[0] == 'n') && (strcmp(string, "none") == 0)) {
	*indexPtr = -1;
	*indexPtr = TCL_INDEX_NONE;
	goto success;
    }

    if (string[0] == '@') {
	if (GetIndexFromCoords(interp, menuPtr, string, indexPtr)
	if (GetIndexFromCoords(NULL, menuPtr, string, indexPtr)
		== TCL_OK) {
	    goto success;
	}
    }

    if (isdigit(UCHAR(string[0]))) {
	if (Tcl_GetIntFromObj(interp, objPtr, &i) == TCL_OK) {
	    if (i >= menuPtr->numEntries) {
		if (lastOK) {
		    i = menuPtr->numEntries;
		} else {
		    i = menuPtr->numEntries-1;
		}
	    } else if (i < 0) {
		i = -1;
	    }
	    *indexPtr = i;
	    goto success;
	}
	Tcl_ResetResult(interp);
    }

    for (i = 0; i < menuPtr->numEntries; i++) {
    for (i = 0; i < (int)menuPtr->numEntries; i++) {
	Tcl_Obj *labelPtr = menuPtr->entries[i]->labelPtr;
	const char *label = (labelPtr == NULL) ? NULL : Tcl_GetString(labelPtr);

	if ((label != NULL) && (Tcl_StringCaseMatch(label, string, 0))) {
	    *indexPtr = i;
	    goto success;
	}
2197
2198
2199
2200
2201
2202
2203
2204

2205
2206
2207
2208
2209
2210
2211
2196
2197
2198
2199
2200
2201
2202

2203
2204
2205
2206
2207
2208
2209
2210







-
+







 *----------------------------------------------------------------------
 */

static void
MenuCmdDeletedProc(
    ClientData clientData)	/* Pointer to widget record for widget. */
{
    TkMenu *menuPtr = clientData;
    TkMenu *menuPtr = (TkMenu *)clientData;
    Tk_Window tkwin = menuPtr->tkwin;

    /*
     * This function could be invoked either because the window was destroyed
     * and the command was then deleted (in which case tkwin is NULL) or
     * because the command was deleted, and then this function destroys the
     * widget.
2239
2240
2241
2242
2243
2244
2245
2246

2247
2248
2249
2250
2251
2252
2253


2254
2255
2256
2257
2258
2259
2260

2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273

2274
2275
2276
2277
2278
2279
2280
2238
2239
2240
2241
2242
2243
2244

2245
2246
2247
2248
2249
2250


2251
2252
2253
2254
2255
2256
2257
2258

2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271

2272
2273
2274
2275
2276
2277
2278
2279







-
+





-
-
+
+






-
+












-
+







 *
 *----------------------------------------------------------------------
 */

static TkMenuEntry *
MenuNewEntry(
    TkMenu *menuPtr,		/* Menu that will hold the new entry. */
    int index,			/* Where in the menu the new entry is to
    TkSizeT index,			/* Where in the menu the new entry is to
				 * go. */
    int type)			/* The type of the new entry. */
{
    TkMenuEntry *mePtr;
    TkMenuEntry **newEntries;
    int i;
    ThreadSpecificData *tsdPtr =
    TkSizeT i;
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    /*
     * Create a new array of entries with an empty slot for the new entry.
     */

    newEntries = ckalloc((menuPtr->numEntries+1) * sizeof(TkMenuEntry *));
    newEntries = (TkMenuEntry **)ckalloc((menuPtr->numEntries+1) * sizeof(TkMenuEntry *));
    for (i = 0; i < index; i++) {
	newEntries[i] = menuPtr->entries[i];
    }
    for (; i < menuPtr->numEntries; i++) {
	newEntries[i+1] = menuPtr->entries[i];
	newEntries[i+1]->index = i + 1;
    }
    if (menuPtr->numEntries != 0) {
	ckfree(menuPtr->entries);
    }
    menuPtr->entries = newEntries;
    menuPtr->numEntries++;
    mePtr = ckalloc(sizeof(TkMenuEntry));
    mePtr = (TkMenuEntry *)ckalloc(sizeof(TkMenuEntry));
    menuPtr->entries[index] = mePtr;
    mePtr->type = type;
    mePtr->optionTable = tsdPtr->entryOptionTables[type];
    mePtr->menuPtr = menuPtr;
    mePtr->labelPtr = NULL;
    mePtr->labelLength = 0;
    mePtr->underline = -1;
2299
2300
2301
2302
2303
2304
2305
2306

2307
2308
2309
2310
2311
2312
2313
2298
2299
2300
2301
2302
2303
2304

2305
2306
2307
2308
2309
2310
2311
2312







-
+







    mePtr->namePtr = NULL;
    mePtr->childMenuRefPtr = NULL;
    mePtr->onValuePtr = NULL;
    mePtr->offValuePtr = NULL;
    mePtr->entryFlags = 0;
    mePtr->index = index;
    mePtr->nextCascadePtr = NULL;
    if (Tk_InitOptions(menuPtr->interp, (char *) mePtr,
    if (Tk_InitOptions(menuPtr->interp, mePtr,
	    mePtr->optionTable, menuPtr->tkwin) != TCL_OK) {
	ckfree(mePtr);
	return NULL;
    }
    TkMenuInitializeEntryDrawingFields(mePtr);
    if (TkpMenuNewEntry(mePtr) != TCL_OK) {
	Tk_FreeConfigOptions((char *) mePtr, mePtr->optionTable,
2342
2343
2344
2345
2346
2347
2348
2349


2350
2351
2352
2353
2354

2355
2356
2357
2358
2359
2360

2361
2362

2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383

2384
2385
2386
2387
2388
2389
2390
2391
2392

2393
2394

2395
2396
2397
2398
2399
2400
2401
2402
2403
2404

2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419

2420
2421
2422
2423
2424
2425
2426
2427
2428

2429
2430
2431
2432
2433
2434
2435
2341
2342
2343
2344
2345
2346
2347

2348
2349
2350
2351
2352
2353

2354
2355
2356
2357
2358
2359

2360
2361

2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382

2383
2384
2385
2386
2387
2388
2389
2390
2391

2392
2393

2394
2395
2396
2397
2398
2399
2400
2401
2402


2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417

2418
2419
2420
2421
2422
2423
2424
2425
2426

2427
2428
2429
2430
2431
2432
2433
2434







-
+
+




-
+





-
+

-
+




















-
+








-
+

-
+








-
-
+














-
+








-
+







    TkMenu *menuPtr,		/* Widget in which to create new entry. */
    Tcl_Obj *indexPtr,		/* Object describing index at which to insert.
				 * NULL means insert at end. */
    int objc,			/* Number of elements in objv. */
    Tcl_Obj *const objv[])	/* Arguments to command: first arg is type of
				 * entry, others are config options. */
{
    int type, index;
    int type;
    TkSizeT index;
    TkMenuEntry *mePtr;
    TkMenu *menuListPtr;

    if (indexPtr != NULL) {
	if (TkGetMenuIndex(interp, menuPtr, indexPtr, 1, &index) != TCL_OK) {
	if (GetMenuIndex(interp, menuPtr, indexPtr, 1, &index) != TCL_OK) {
	    return TCL_ERROR;
	}
    } else {
	index = menuPtr->numEntries;
    }
    if (index < 0) {
    if (index == TCL_INDEX_NONE) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"bad index \"%s\"", Tcl_GetString(indexPtr)));
		"bad menu entry index \"%s\"", Tcl_GetString(indexPtr)));
	Tcl_SetErrorCode(interp, "TK", "MENU", "INDEX", NULL);
	return TCL_ERROR;
    }
    if (menuPtr->tearoff && (index == 0)) {
	index = 1;
    }

    /*
     * Figure out the type of the new entry.
     */

    if (Tcl_GetIndexFromObjStruct(interp, objv[0], menuEntryTypeStrings,
	    sizeof(char *), "menu entry type", 0, &type) != TCL_OK) {
	return TCL_ERROR;
    }

    /*
     * Now we have to add an entry for every instance related to this menu.
     */

    for (menuListPtr = menuPtr->masterMenuPtr; menuListPtr != NULL;
    for (menuListPtr = menuPtr->mainMenuPtr; menuListPtr != NULL;
    	    menuListPtr = menuListPtr->nextInstancePtr) {

    	mePtr = MenuNewEntry(menuListPtr, index, type);
    	if (mePtr == NULL) {
    	    return TCL_ERROR;
    	}
    	if (ConfigureMenuEntry(mePtr, objc - 1, objv + 1) != TCL_OK) {
	    TkMenu *errorMenuPtr;
	    int i;
	    TkSizeT i;

	    for (errorMenuPtr = menuPtr->masterMenuPtr;
	    for (errorMenuPtr = menuPtr->mainMenuPtr;
		    errorMenuPtr != NULL;
		    errorMenuPtr = errorMenuPtr->nextInstancePtr) {
    		Tcl_EventuallyFree(errorMenuPtr->entries[index],
    	    		(Tcl_FreeProc *) DestroyMenuEntry);
		for (i = index; i < errorMenuPtr->numEntries - 1; i++) {
		    errorMenuPtr->entries[i] = errorMenuPtr->entries[i + 1];
		    errorMenuPtr->entries[i]->index = i;
		}
		errorMenuPtr->numEntries--;
		if (errorMenuPtr->numEntries == 0) {
		if (--errorMenuPtr->numEntries == 0) {
		    ckfree(errorMenuPtr->entries);
		    errorMenuPtr->entries = NULL;
		}
		if (errorMenuPtr == menuListPtr) {
		    break;
		}
	    }
    	    return TCL_ERROR;
    	}

    	/*
	 * If a menu has cascades, then every instance of the menu has to have
	 * its own parallel cascade structure. So adding an entry to a menu
	 * with clones means that the menu that the entry points to has to be
	 * cloned for every clone the master menu has. This is special case #2
	 * cloned for every clone the main menu has. This is special case #2
	 * in the comment at the top of this file.
    	 */

    	if ((menuPtr != menuListPtr) && (type == CASCADE_ENTRY)) {
    	    if ((mePtr->namePtr != NULL)
		    && (mePtr->childMenuRefPtr != NULL)
    	    	    && (mePtr->childMenuRefPtr->menuPtr != NULL)) {
		TkMenu *cascadeMenuPtr =
			mePtr->childMenuRefPtr->menuPtr->masterMenuPtr;
			mePtr->childMenuRefPtr->menuPtr->mainMenuPtr;
		Tcl_Obj *newCascadePtr, *newObjv[2];
		Tcl_Obj *menuNamePtr = Tcl_NewStringObj("-menu", -1);
		Tcl_Obj *windowNamePtr =
			Tcl_NewStringObj(Tk_PathName(menuListPtr->tkwin), -1);
		Tcl_Obj *normalPtr = Tcl_NewStringObj("normal", -1);
		TkMenuReferences *menuRefPtr;

2482
2483
2484
2485
2486
2487
2488
2489

2490
2491
2492


2493
2494
2495
2496
2497
2498
2499
2481
2482
2483
2484
2485
2486
2487

2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500







-
+



+
+







MenuVarProc(
    ClientData clientData,	/* Information about menu entry. */
    Tcl_Interp *interp,		/* Interpreter containing variable. */
    const char *name1,		/* First part of variable's name. */
    const char *name2,		/* Second part of variable's name. */
    int flags)			/* Describes what just happened. */
{
    TkMenuEntry *mePtr = clientData;
    TkMenuEntry *mePtr = (TkMenuEntry *)clientData;
    TkMenu *menuPtr;
    const char *value;
    const char *name, *onValue;
    (void)name1;
    (void)name2;

    if (Tcl_InterpDeleted(interp) || (mePtr->namePtr == NULL)) {
	/*
	 * Do nothing if the interpreter is going away or we have
	 * no variable name.
	 */

2587
2588
2589
2590
2591
2592
2593
2594
2595
2596



2597
2598

2599
2600
2601

2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615

2616
2617
2618
2619
2620
2621
2622
2588
2589
2590
2591
2592
2593
2594



2595
2596
2597
2598

2599
2600
2601

2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615

2616
2617
2618
2619
2620
2621
2622
2623







-
-
-
+
+
+

-
+


-
+













-
+







 *	may get posted and unposted.
 *
 *----------------------------------------------------------------------
 */

int
TkActivateMenuEntry(
    register TkMenu *menuPtr,	/* Menu in which to activate. */
    int index)			/* Index of entry to activate, or -1 to
				 * deactivate all entries. */
    TkMenu *menuPtr,	/* Menu in which to activate. */
    TkSizeT index)			/* Index of entry to activate, or
				 * TCL_INDEX_NONE to deactivate all entries. */
{
    register TkMenuEntry *mePtr;
    TkMenuEntry *mePtr;
    int result = TCL_OK;

    if (menuPtr->active >= 0) {
    if (menuPtr->active != TCL_INDEX_NONE) {
	mePtr = menuPtr->entries[menuPtr->active];

	/*
	 * Don't change the state unless it's currently active (state might
	 * already have been changed to disabled).
	 */

	if (mePtr->state == ENTRY_ACTIVE) {
	    mePtr->state = ENTRY_NORMAL;
	}
	TkEventuallyRedrawMenu(menuPtr, menuPtr->entries[menuPtr->active]);
    }
    menuPtr->active = index;
    if (index >= 0) {
    if (index != TCL_INDEX_NONE) {
	mePtr = menuPtr->entries[index];
	mePtr->state = ENTRY_ACTIVE;
	TkEventuallyRedrawMenu(menuPtr, mePtr);
    }
    return result;
}

2693
2694
2695
2696
2697
2698
2699
2700

2701
2702
2703
2704
2705
2706
2707
2694
2695
2696
2697
2698
2699
2700

2701
2702
2703
2704
2705
2706
2707
2708







-
+







{
    int returnResult;
    int menuType, i;
    TkMenuReferences *menuRefPtr;
    Tcl_Obj *menuDupCommandArray[4];

    if (newMenuTypePtr == NULL) {
	menuType = MASTER_MENU;
	menuType = MAIN_MENU;
    } else {
	if (Tcl_GetIndexFromObjStruct(menuPtr->interp, newMenuTypePtr,
		menuTypeStrings, sizeof(char *), "menu type", 0, &menuType) != TCL_OK) {
	    return TCL_ERROR;
	}
    }

2728
2729
2730
2731
2732
2733
2734
2735

2736
2737
2738
2739
2740
2741
2742
2743
2744

2745
2746

2747
2748
2749
2750
2751




2752
2753
2754
2755

2756
2757
2758
2759
2760
2761
2762
2729
2730
2731
2732
2733
2734
2735

2736
2737
2738
2739
2740
2741
2742
2743
2744

2745
2746

2747
2748




2749
2750
2751
2752
2753
2754
2755

2756
2757
2758
2759
2760
2761
2762
2763







-
+








-
+

-
+

-
-
-
-
+
+
+
+



-
+








    if ((returnResult == TCL_OK) &&
	    ((menuRefPtr = TkFindMenuReferencesObj(menuPtr->interp,
	    newMenuNamePtr)) != NULL)
	    && (menuPtr->numEntries == menuRefPtr->menuPtr->numEntries)) {
	TkMenu *newMenuPtr = menuRefPtr->menuPtr;
	Tcl_Obj *newObjv[3];
	int i, numElements;
	int numElements;

	/*
	 * Now put this newly created menu into the parent menu's instance
	 * chain.
	 */

	if (menuPtr->nextInstancePtr == NULL) {
	    menuPtr->nextInstancePtr = newMenuPtr;
	    newMenuPtr->masterMenuPtr = menuPtr->masterMenuPtr;
	    newMenuPtr->mainMenuPtr = menuPtr->mainMenuPtr;
	} else {
	    TkMenu *masterMenuPtr;
	    TkMenu *mainMenuPtr;

	    masterMenuPtr = menuPtr->masterMenuPtr;
	    newMenuPtr->nextInstancePtr = masterMenuPtr->nextInstancePtr;
	    masterMenuPtr->nextInstancePtr = newMenuPtr;
	    newMenuPtr->masterMenuPtr = masterMenuPtr;
	    mainMenuPtr = menuPtr->mainMenuPtr;
	    newMenuPtr->nextInstancePtr = mainMenuPtr->nextInstancePtr;
	    mainMenuPtr->nextInstancePtr = newMenuPtr;
	    newMenuPtr->mainMenuPtr = mainMenuPtr;
	}

	/*
	 * Add the master menu's window to the bind tags for this window after
	 * Add the main menu's window to the bind tags for this window after
	 * this window's tag. This is so the user can bind to either this
	 * clone (which may not be easy to do) or the entire menu clone
	 * structure.
	 */

	newObjv[0] = Tcl_NewStringObj("bindtags", -1);
	newObjv[1] = Tcl_NewStringObj(Tk_PathName(newMenuPtr->tkwin), -1);
2774
2775
2776
2777
2778
2779
2780
2781

2782
2783
2784
2785
2786
2787
2788
2775
2776
2777
2778
2779
2780
2781

2782
2783
2784
2785
2786
2787
2788
2789







-
+







	    for (i = 0; i < numElements; i++) {
		Tcl_ListObjIndex(newMenuPtr->interp, bindingsPtr, i,
			&elementPtr);
		windowName = Tcl_GetString(elementPtr);
		if (strcmp(windowName, Tk_PathName(newMenuPtr->tkwin))
			== 0) {
		    Tcl_Obj *newElementPtr = Tcl_NewStringObj(
			    Tk_PathName(newMenuPtr->masterMenuPtr->tkwin), -1);
			    Tk_PathName(newMenuPtr->mainMenuPtr->tkwin), -1);

		    /*
		     * The newElementPtr will have its refCount incremented
		     * here, so we don't need to worry about it any more.
		     */

		    Tcl_ListObjReplace(menuPtr->interp, bindingsPtr,
2799
2800
2801
2802
2803
2804
2805
2806

2807
2808
2809
2810
2811
2812
2813
2800
2801
2802
2803
2804
2805
2806

2807
2808
2809
2810
2811
2812
2813
2814







-
+







	Tcl_DecrRefCount(newObjv[1]);
	Tcl_ResetResult(menuPtr->interp);

	/*
	 * Clone all of the cascade menus that this menu points to.
	 */

	for (i = 0; i < menuPtr->numEntries; i++) {
	for (i = 0; i < (int)menuPtr->numEntries; i++) {
	    TkMenuReferences *cascadeRefPtr;
	    TkMenu *oldCascadePtr;

	    if ((menuPtr->entries[i]->type == CASCADE_ENTRY)
		&& (menuPtr->entries[i]->namePtr != NULL)) {
		cascadeRefPtr =
			TkFindMenuReferencesObj(menuPtr->interp,
2863
2864
2865
2866
2867
2868
2869
2870

2871
2872
2873

2874
2875
2876
2877
2878


2879
2880

2881
2882
2883
2884
2885
2886
2887
2864
2865
2866
2867
2868
2869
2870

2871
2872
2873

2874
2875
2876
2877


2878
2879
2880

2881
2882
2883
2884
2885
2886
2887
2888







-
+


-
+



-
-
+
+

-
+








static int
MenuDoXPosition(
    Tcl_Interp *interp,
    TkMenu *menuPtr,
    Tcl_Obj *objPtr)
{
    int index;
    TkSizeT index;

    TkRecomputeMenu(menuPtr);
    if (TkGetMenuIndex(interp, menuPtr, objPtr, 0, &index) != TCL_OK) {
    if (GetMenuIndex(interp, menuPtr, objPtr, 0, &index) != TCL_OK) {
	return TCL_ERROR;
    }
    Tcl_ResetResult(interp);
    if (index < 0) {
	Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
    if (index == TCL_INDEX_NONE) {
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(0));
    } else {
	Tcl_SetObjResult(interp, Tcl_NewIntObj(menuPtr->entries[index]->x));
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(menuPtr->entries[index]->x));
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
2900
2901
2902
2903
2904
2905
2906
2907

2908
2909
2910

2911
2912
2913
2914
2915


2916
2917

2918
2919
2920
2921
2922
2923
2924
2901
2902
2903
2904
2905
2906
2907

2908
2909
2910

2911
2912
2913
2914


2915
2916
2917

2918
2919
2920
2921
2922
2923
2924
2925







-
+


-
+



-
-
+
+

-
+








static int
MenuDoYPosition(
    Tcl_Interp *interp,
    TkMenu *menuPtr,
    Tcl_Obj *objPtr)
{
    int index;
    TkSizeT index;

    TkRecomputeMenu(menuPtr);
    if (TkGetMenuIndex(interp, menuPtr, objPtr, 0, &index) != TCL_OK) {
    if (GetMenuIndex(interp, menuPtr, objPtr, 0, &index) != TCL_OK) {
	goto error;
    }
    Tcl_ResetResult(interp);
    if (index < 0) {
	Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
    if (index == TCL_INDEX_NONE) {
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(0));
    } else {
	Tcl_SetObjResult(interp, Tcl_NewIntObj(menuPtr->entries[index]->y));
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(menuPtr->entries[index]->y));
    }

    return TCL_OK;

  error:
    return TCL_ERROR;
}
2938
2939
2940
2941
2942
2943
2944
2945

2946
2947
2948
2949
2950

2951
2952
2953
2954
2955
2956
2957
2939
2940
2941
2942
2943
2944
2945

2946
2947
2948
2949
2950

2951
2952
2953
2954
2955
2956
2957
2958







-
+




-
+







 *
 * Side effects:
 *	If int is invalid, interp's result will be set to NULL.
 *
 *----------------------------------------------------------------------
 */

static int
static TkSizeT
GetIndexFromCoords(
    Tcl_Interp *interp,		/* Interpreter of menu. */
    TkMenu *menuPtr,		/* The menu we are searching. */
    const char *string,		/* The @string we are parsing. */
    int *indexPtr)		/* The index of the item that matches. */
    TkSizeT *indexPtr)		/* The index of the item that matches. */
{
    int x, y, i;
    const char *p;
    char *end;
    int x2, borderwidth, max;

    TkRecomputeMenu(menuPtr);
2978
2979
2980
2981
2982
2983
2984
2985

2986
2987
2988
2989
2990
2991
2992
2979
2980
2981
2982
2983
2984
2985

2986
2987
2988
2989
2990
2991
2992
2993







-
+







    /* set the width of the final column to the remainder of the window
     * being aware of windows that may not be mapped yet.
     */
    max = Tk_IsMapped(menuPtr->tkwin)
      ? Tk_Width(menuPtr->tkwin) : Tk_ReqWidth(menuPtr->tkwin);
    max -= borderwidth;

    for (i = 0; i < menuPtr->numEntries; i++) {
    for (i = 0; i < (int)menuPtr->numEntries; i++) {
	if (menuPtr->entries[i]->entryFlags & ENTRY_LAST_COLUMN) {
	    x2 = max;
	} else {
	    x2 = menuPtr->entries[i]->x + menuPtr->entries[i]->width;
	}
	if ((x >= menuPtr->entries[i]->x) && (y >= menuPtr->entries[i]->y)
		&& (x < x2)
3021
3022
3023
3024
3025
3026
3027
3028

3029
3030
3031
3032
3033
3034
3035
3022
3023
3024
3025
3026
3027
3028

3029
3030
3031
3032
3033
3034
3035
3036







-
+







 *----------------------------------------------------------------------
 */

static void
RecursivelyDeleteMenu(
    TkMenu *menuPtr)		/* The menubar instance we are deleting. */
{
    int i;
    TkSizeT i;
    TkMenuEntry *mePtr;

    /*
     * It is not 100% clear that this preserve/release pair is required, but
     * we have added them for safety in this very complex code.
     */

3108
3109
3110
3111
3112
3113
3114
3115

3116
3117
3118
3119
3120
3121
3122
3109
3110
3111
3112
3113
3114
3115

3116
3117
3118
3119
3120
3121
3122
3123







-
+








	    Tcl_DecrRefCount(resultPtr);
	    resultPtr = Tcl_DuplicateObj(parentPtr);
	    if (doDot) {
		Tcl_AppendToObj(resultPtr, ".", -1);
	    }
	    Tcl_AppendObjToObj(resultPtr, childPtr);
	    intPtr = Tcl_NewIntObj(i);
	    intPtr = Tcl_NewWideIntObj(i);
	    Tcl_AppendObjToObj(resultPtr, intPtr);
	    Tcl_DecrRefCount(intPtr);
    	}
	destString = Tcl_GetString(resultPtr);
    	if ((Tcl_FindCommand(interp, destString, NULL, 0) == NULL)
		&& ((nameTablePtr == NULL)
		|| (Tcl_FindHashEntry(nameTablePtr, destString) == NULL))) {
3174
3175
3176
3177
3178
3179
3180
3181

3182
3183
3184
3185
3186
3187
3188
3175
3176
3177
3178
3179
3180
3181

3182
3183
3184
3185
3186
3187
3188
3189







-
+







	     */

	    if (menuRefPtr->menuPtr != NULL) {
		TkMenu *instancePtr;

		menuPtr = menuRefPtr->menuPtr;

		for (instancePtr = menuPtr->masterMenuPtr;
		for (instancePtr = menuPtr->mainMenuPtr;
			instancePtr != NULL;
			instancePtr = instancePtr->nextInstancePtr) {
		    if (instancePtr->menuType == MENUBAR
			    && instancePtr->parentTopLevelPtr == tkwin) {
			RecursivelyDeleteMenu(instancePtr);
			break;
		    }
3277
3278
3279
3280
3281
3282
3283
3284

3285
3286
3287
3288
3289
3290
3291
3278
3279
3280
3281
3282
3283
3284

3285
3286
3287
3288
3289
3290
3291
3292







-
+







	}

	/*
	 * Add this window to the menu's list of windows that refer to this
	 * menu.
	 */

	topLevelListPtr = ckalloc(sizeof(TkMenuTopLevelList));
	topLevelListPtr = (TkMenuTopLevelList *)ckalloc(sizeof(TkMenuTopLevelList));
	topLevelListPtr->tkwin = tkwin;
	topLevelListPtr->nextPtr = menuRefPtr->topLevelListPtr;
	menuRefPtr->topLevelListPtr = topLevelListPtr;
    } else {
	TkpSetWindowMenuBar(tkwin, NULL);
    }
    TkpSetMainMenubar(interp, tkwin, menuName);
3307
3308
3309
3310
3311
3312
3313
3314

3315


3316

3317
3318
3319
3320
3321
3322
3323
3308
3309
3310
3311
3312
3313
3314

3315
3316
3317
3318

3319
3320
3321
3322
3323
3324
3325
3326







-
+

+
+
-
+







 *
 *----------------------------------------------------------------------
 */

static void
DestroyMenuHashTable(
    ClientData clientData,	/* The menu hash table we are destroying. */
    Tcl_Interp *interp)		/* The interpreter we are destroying. */
    Tcl_Interp *dummy)		/* The interpreter we are destroying. */
{
    (void)dummy;

    Tcl_DeleteHashTable(clientData);
    Tcl_DeleteHashTable((Tcl_HashTable *)clientData);
    ckfree(clientData);
}

/*
 *----------------------------------------------------------------------
 *
 * TkGetMenuHashTable --
3335
3336
3337
3338
3339
3340
3341
3342

3343
3344
3345
3346

3347
3348
3349
3350
3351
3352
3353
3338
3339
3340
3341
3342
3343
3344

3345
3346
3347
3348

3349
3350
3351
3352
3353
3354
3355
3356







-
+



-
+







 *----------------------------------------------------------------------
 */

Tcl_HashTable *
TkGetMenuHashTable(
    Tcl_Interp *interp)		/* The interp we need the hash table in.*/
{
    Tcl_HashTable *menuTablePtr =
    Tcl_HashTable *menuTablePtr = (Tcl_HashTable *)
	    Tcl_GetAssocData(interp, MENU_HASH_KEY, NULL);

    if (menuTablePtr == NULL) {
	menuTablePtr = ckalloc(sizeof(Tcl_HashTable));
	menuTablePtr = (Tcl_HashTable *)ckalloc(sizeof(Tcl_HashTable));
	Tcl_InitHashTable(menuTablePtr, TCL_STRING_KEYS);
	Tcl_SetAssocData(interp, MENU_HASH_KEY, DestroyMenuHashTable,
		menuTablePtr);
    }
    return menuTablePtr;
}

3380
3381
3382
3383
3384
3385
3386
3387

3388
3389
3390
3391
3392
3393
3394

3395
3396
3397
3398
3399
3400
3401
3383
3384
3385
3386
3387
3388
3389

3390
3391
3392
3393
3394
3395
3396

3397
3398
3399
3400
3401
3402
3403
3404







-
+






-
+







    Tcl_HashEntry *hashEntryPtr;
    TkMenuReferences *menuRefPtr;
    int newEntry;
    Tcl_HashTable *menuTablePtr = TkGetMenuHashTable(interp);

    hashEntryPtr = Tcl_CreateHashEntry(menuTablePtr, pathName, &newEntry);
    if (newEntry) {
    	menuRefPtr = ckalloc(sizeof(TkMenuReferences));
    	menuRefPtr = (TkMenuReferences *)ckalloc(sizeof(TkMenuReferences));
    	menuRefPtr->menuPtr = NULL;
    	menuRefPtr->topLevelListPtr = NULL;
    	menuRefPtr->parentEntryPtr = NULL;
    	menuRefPtr->hashEntryPtr = hashEntryPtr;
    	Tcl_SetHashValue(hashEntryPtr, menuRefPtr);
    } else {
    	menuRefPtr = Tcl_GetHashValue(hashEntryPtr);
    	menuRefPtr = (TkMenuReferences *)Tcl_GetHashValue(hashEntryPtr);
    }
    return menuRefPtr;
}

/*
 *----------------------------------------------------------------------
 *
3424
3425
3426
3427
3428
3429
3430
3431

3432
3433
3434
3435
3436
3437
3438
3427
3428
3429
3430
3431
3432
3433

3434
3435
3436
3437
3438
3439
3440
3441







-
+







    Tcl_HashEntry *hashEntryPtr;
    TkMenuReferences *menuRefPtr = NULL;
    Tcl_HashTable *menuTablePtr;

    menuTablePtr = TkGetMenuHashTable(interp);
    hashEntryPtr = Tcl_FindHashEntry(menuTablePtr, pathName);
    if (hashEntryPtr != NULL) {
    	menuRefPtr = Tcl_GetHashValue(hashEntryPtr);
    	menuRefPtr = (TkMenuReferences *)Tcl_GetHashValue(hashEntryPtr);
    }
    return menuRefPtr;
}

/*
 *----------------------------------------------------------------------
 *
3520
3521
3522
3523
3524
3525
3526
3527

3528
3529
3530
3531
3532

3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543


3544
3545

3546
3547
3548
3549
3550
3551
3552
3553
3554
3555

3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571


3572


3573
3574
3575
3576
3577
3578
3579
3523
3524
3525
3526
3527
3528
3529

3530
3531
3532
3533
3534

3535
3536
3537
3538
3539
3540
3541
3542
3543
3544


3545
3546
3547

3548
3549
3550
3551
3552
3553
3554
3555
3556
3557

3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572


3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584







-
+




-
+









-
-
+
+

-
+









-
+














-
-
+
+

+
+







				 * entries to delete. */
    int last)			/* The zero-based last entry. */
{
    TkMenu *menuListPtr;
    int numDeleted, i, j;

    numDeleted = last + 1 - first;
    for (menuListPtr = menuPtr->masterMenuPtr; menuListPtr != NULL;
    for (menuListPtr = menuPtr->mainMenuPtr; menuListPtr != NULL;
	    menuListPtr = menuListPtr->nextInstancePtr) {
	for (i = last; i >= first; i--) {
	    Tcl_EventuallyFree(menuListPtr->entries[i], (Tcl_FreeProc *) DestroyMenuEntry);
	}
	for (i = last + 1; i < menuListPtr->numEntries; i++) {
	for (i = last + 1; i < (int)menuListPtr->numEntries; i++) {
	    j = i - numDeleted;
	    menuListPtr->entries[j] = menuListPtr->entries[i];
	    menuListPtr->entries[j]->index = j;
	}
	menuListPtr->numEntries -= numDeleted;
	if (menuListPtr->numEntries == 0) {
	    ckfree(menuListPtr->entries);
	    menuListPtr->entries = NULL;
	}
	if ((menuListPtr->active >= first)
		&& (menuListPtr->active <= last)) {
	if (((int)menuListPtr->active >= first)
		&& ((int)menuListPtr->active <= last)) {
	    menuListPtr->active = -1;
	} else if (menuListPtr->active > last) {
	} else if ((int)menuListPtr->active > last) {
	    menuListPtr->active -= numDeleted;
	}
	TkEventuallyRecomputeMenu(menuListPtr);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TkMenuCleanup --
 * MenuCleanup --
 *
 *	Resets menusInitialized to allow Tk to be finalized and reused without
 *	the DLL being unloaded.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
TkMenuCleanup(
    ClientData unused)
MenuCleanup(
    ClientData dummy)
{
    (void)dummy;

    menusInitialized = 0;
}

/*
 *----------------------------------------------------------------------
 *
 * TkMenuInit --
3589
3590
3591
3592
3593
3594
3595
3596

3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610

3611
3612
3613
3614
3615
3616
3617
3594
3595
3596
3597
3598
3599
3600

3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614

3615
3616
3617
3618
3619
3620
3621
3622







-
+













-
+







 *
 *----------------------------------------------------------------------
 */

void
TkMenuInit(void)
{
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (!menusInitialized) {
	Tcl_MutexLock(&menuMutex);
	if (!menusInitialized) {
	    TkpMenuInit();
	    menusInitialized = 1;
	}

	/*
	 * Make sure we cleanup on finalize.
	 */

	TkCreateExitHandler((Tcl_ExitProc *) TkMenuCleanup, NULL);
	TkCreateExitHandler((Tcl_ExitProc *) MenuCleanup, NULL);
	Tcl_MutexUnlock(&menuMutex);
    }
    if (!tsdPtr->menusInitialized) {
	TkpMenuThreadInit();
	tsdPtr->menuOptionTable =
		Tk_CreateOptionTable(NULL, tkMenuConfigSpecs);
	tsdPtr->entryOptionTables[TEAROFF_ENTRY] =
Changes to generic/tkMenu.h.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







/*
 * 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.
 */

#ifndef _TKMENU
#define _TKMENU
60
61
62
63
64
65
66
67

68
69
70
71

72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88

89
90
91
92
93
94
95
60
61
62
63
64
65
66

67
68
69
70

71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

88
89
90
91
92
93
94
95







-
+



-
+
















-
+







    int type;			/* Type of menu entry; see below for valid
				 * types. */
    struct TkMenu *menuPtr;	/* Menu with which this entry is
				 * associated. */
    Tk_OptionTable optionTable;	/* Option table for this menu entry. */
    Tcl_Obj *labelPtr;		/* Main text label displayed in entry (NULL if
				 * no label). */
    int labelLength;		/* Number of non-NULL characters in label. */
    TkSizeT labelLength;	/* Number of non-NULL characters in label. */
    int state;			/* State of button for display purposes:
				 * normal, active, or disabled. */
    int underline;		/* Value of -underline option: specifies index
				 * of character to underline (<0 means don't
				 * of character to underline (-1 means don't
				 * underline anything). */
    Tcl_Obj *underlinePtr;	/* Index of character to underline. */
    Tcl_Obj *bitmapPtr;		/* Bitmap to display in menu entry, or NULL.
				 * If not NULL then label is ignored. */
    Tcl_Obj *imagePtr;		/* Name of image to display, or NULL. If not
				 * NULL, bitmap, text, and textVarName are
				 * ignored. */
    Tk_Image image;		/* Image to display in menu entry, or NULL if
				 * none. */
    Tcl_Obj *selectImagePtr;	/* Name of image to display when selected, or
				 * NULL. */
    Tk_Image selectImage;	/* Image to display in entry when selected, or
				 * NULL if none. Ignored if image is NULL. */
    Tcl_Obj *accelPtr;		/* Accelerator string displayed at right of
				 * menu entry. NULL means no such accelerator.
				 * Malloc'ed. */
    int accelLength;		/* Number of non-NULL characters in
    TkSizeT accelLength;	/* Number of non-NULL characters in
				 * accelerator. */
    int indicatorOn;		/* True means draw indicator, false means
				 * don't draw it. This field is ignored unless
				 * the entry is a radio or check button. */
    /*
     * Display attributes
     */
181
182
183
184
185
186
187
188

189
190
191
192
193
194
195
181
182
183
184
185
186
187

188
189
190
191
192
193
194
195







-
+







    int entryFlags;		/* Various flags. See below for
				 * definitions. */
    int index;			/* Need to know which index we are. This is
    				 * zero-based. This is the top-left entry of
    				 * the menu. */

    /*
     * Bookeeping for master menus and cascade menus.
     * Bookeeping for main menus and cascade menus.
     */

    struct TkMenuReferences *childMenuRefPtr;
    				/* A pointer to the hash table entry for the
    				 * child menu. Stored here when the menu entry
    				 * is configured so that a hash lookup is not
    				 * necessary later.*/
259
260
261
262
263
264
265
266
267
268
269




270
271
272
273
274
275
276
259
260
261
262
263
264
265




266
267
268
269
270
271
272
273
274
275
276







-
-
-
-
+
+
+
+







    Display *display;		/* Display containing widget. Needed, among
				 * other things, so that resources can be
				 * freed up even after tkwin has gone away. */
    Tcl_Interp *interp;		/* Interpreter associated with menu. */
    Tcl_Command widgetCmd;	/* Token for menu's widget command. */
    TkMenuEntry **entries;	/* Array of pointers to all the entries in the
				 * menu. NULL means no entries. */
    int numEntries;		/* Number of elements in entries. */
    int active;			/* Index of active entry. -1 means nothing
				 * active. */
    int menuType;		/* MASTER_MENU, TEAROFF_MENU, or MENUBAR. See
    TkSizeT numEntries;		/* Number of elements in entries. */
    TkSizeT active;			/* Index of active entry. TCL_INDEX_NONE means
				 * nothing active. */
    int menuType;		/* MAIN_MENU, TEAROFF_MENU, or MENUBAR. See
    				 * below for definitions. */
    Tcl_Obj *menuTypePtr;	/* Used to control whether created tkwin is a
				 * toplevel or not. "normal", "menubar", or
				 * "toplevel" */

    /*
     * Information used when displaying widget:
347
348
349
350
351
352
353
354

355
356
357

358
359
360
361
362
363
364
347
348
349
350
351
352
353

354
355
356

357
358
359
360
361
362
363
364







-
+


-
+







				 * definition. */
    TkMenuEntry *postedCascade;	/* Points to menu entry for cascaded submenu
				 * that is currently posted or NULL if no
				 * submenu posted. */
    struct TkMenu *nextInstancePtr;
    				/* The next instance of this menu in the
    				 * chain. */
    struct TkMenu *masterMenuPtr;
    struct TkMenu *mainMenuPtr;
    				/* A pointer to the original menu for this
    				 * clone chain. Points back to this structure
    				 * if this menu is a master menu. */
    				 * if this menu is a main menu. */
    void *reserved1; /* not used any more. */
    Tk_Window parentTopLevelPtr;/* If this menu is a menubar, this is the
    				 * toplevel that owns the menu. Only
    				 * applicable for menubar clones. */
    struct TkMenuReferences *menuRefPtr;
    				/* Each menu is hashed into a table with the
    				 * name of the menu's window as the key. The
374
375
376
377
378
379
380

381
382
383
384
385
386
387
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388







+







				 * of options are in this structure. */
    Tk_OptionSpec *extensionPtr;/* Needed by the configuration package for
				 * this widget to be extended. */
    Tk_SavedOptions *errorStructPtr;
				/* We actually have to allocate these because
				 * multiple menus get changed during one
				 * ConfigureMenu call. */
    Tcl_Obj *activeReliefPtr;	/* 3-d effect for active element. */
} TkMenu;

/*
 * When the toplevel configure -menu command is executed, the menu may not
 * exist yet. We need to keep a linked list of windows that reference a
 * particular menu.
 */
429
430
431
432
433
434
435
436

437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454

455
456
457

458
459
460
461
462
463

464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480

481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498

499
500
501

502
503
504
505
506
507
508
430
431
432
433
434
435
436

437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454

455
456
457

458
459
460
461
462
463

464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480

481
482
483
484
485
486
487
488
489
490
491
492
493


494
495
496

497
498
499

500
501
502
503
504
505
506
507







-
+

















-
+


-
+





-
+
















-
+












-
-



-
+


-
+







 * REDRAW_PENDING:		Non-zero means a DoWhenIdle handler has
 *				already been queued to redraw this window.
 * RESIZE_PENDING:		Non-zero means a call to ComputeMenuGeometry
 *				has already been scheduled.
 * MENU_DELETION_PENDING	Non-zero means that we are currently
 *				destroying this menu's internal structures.
 *				This is useful when we are in the middle of
 *				cleaning this master menu's chain of menus up
 *				cleaning this main menu's chain of menus up
 *				when TkDestroyMenu was called again on this
 *				menu (via a destroy binding or somesuch).
 * MENU_WIN_DESTRUCTION_PENDING Non-zero means we are in the middle of
 *				destroying this menu's Tk_Window.
 * MENU_PLATFORM_FLAG1...	Reserved for use by the platform-specific menu
 *				code.
 */

#define REDRAW_PENDING			1
#define RESIZE_PENDING			2
#define MENU_DELETION_PENDING		4
#define MENU_WIN_DESTRUCTION_PENDING	8
#define MENU_PLATFORM_FLAG1	(1 << 30)
#define MENU_PLATFORM_FLAG2	(1 << 29)
#define MENU_PLATFORM_FLAG3	(1 << 28)

/*
 * Each menu created by the user is a MASTER_MENU. When a menu is torn off, a
 * Each menu created by the user is a MAIN_MENU. When a menu is torn off, a
 * TEAROFF_MENU instance is created. When a menu is assigned to a toplevel as
 * a menu bar, a MENUBAR instance is created. All instances have the same
 * configuration information. If the master instance is deleted, all instances
 * configuration information. If the main instance is deleted, all instances
 * are deleted. If one of the other instances is deleted, only that instance
 * is deleted.
 */

#define UNKNOWN_TYPE		-1
#define MASTER_MENU 		0
#define MAIN_MENU 		0
#define TEAROFF_MENU 		1
#define MENUBAR 		2

/*
 * Various geometry definitions:
 */

#define CASCADE_ARROW_HEIGHT	10
#define CASCADE_ARROW_WIDTH	8
#define DECORATION_BORDER_WIDTH	2

/*
 * Menu-related functions that are shared among Tk modules but not exported to
 * the outside world:
 */

MODULE_SCOPE int	TkActivateMenuEntry(TkMenu *menuPtr, int index);
MODULE_SCOPE int	TkActivateMenuEntry(TkMenu *menuPtr, TkSizeT index);
MODULE_SCOPE void	TkBindMenu(Tk_Window tkwin, TkMenu *menuPtr);
MODULE_SCOPE TkMenuReferences*TkCreateMenuReferences(Tcl_Interp *interp,
			    const char *name);
MODULE_SCOPE void	TkDestroyMenu(TkMenu *menuPtr);
MODULE_SCOPE void	TkEventuallyRecomputeMenu(TkMenu *menuPtr);
MODULE_SCOPE void	TkEventuallyRedrawMenu(TkMenu *menuPtr,
			    TkMenuEntry *mePtr);
MODULE_SCOPE TkMenuReferences*TkFindMenuReferences(Tcl_Interp *interp, const char *name);
MODULE_SCOPE TkMenuReferences*TkFindMenuReferencesObj(Tcl_Interp *interp,
			    Tcl_Obj *namePtr);
MODULE_SCOPE int	TkFreeMenuReferences(TkMenuReferences *menuRefPtr);
MODULE_SCOPE Tcl_HashTable *TkGetMenuHashTable(Tcl_Interp *interp);
MODULE_SCOPE int	TkGetMenuIndex(Tcl_Interp *interp, TkMenu *menuPtr,
			    Tcl_Obj *objPtr, int lastOK, int *indexPtr);
MODULE_SCOPE void	TkMenuInitializeDrawingFields(TkMenu *menuPtr);
MODULE_SCOPE void	TkMenuInitializeEntryDrawingFields(TkMenuEntry *mePtr);
MODULE_SCOPE int	TkInvokeMenu(Tcl_Interp *interp, TkMenu *menuPtr,
			    int index);
			    TkSizeT index);
MODULE_SCOPE void	TkMenuConfigureDrawOptions(TkMenu *menuPtr);
MODULE_SCOPE int	TkMenuConfigureEntryDrawOptions(
			    TkMenuEntry *mePtr, int index);
			    TkMenuEntry *mePtr, TkSizeT index);
MODULE_SCOPE void	TkMenuFreeDrawOptions(TkMenu *menuPtr);
MODULE_SCOPE void	TkMenuEntryFreeDrawOptions(TkMenuEntry *mePtr);
MODULE_SCOPE void	TkMenuEventProc(ClientData clientData,
    			    XEvent *eventPtr);
MODULE_SCOPE void	TkMenuImageProc(ClientData clientData, int x, int y,
			    int width, int height, int imgWidth,
			    int imgHeight);
Changes to generic/tkMenuDraw.c.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







/*
 * 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.
 */

#include "tkInt.h"
#include "tkMenu.h"
294
295
296
297
298
299
300
301

302
303
304
305
306
307
308
294
295
296
297
298
299
300

301
302
303
304
305
306
307
308







-
+







 *
 *----------------------------------------------------------------------
 */

int
TkMenuConfigureEntryDrawOptions(
    TkMenuEntry *mePtr,
    int index)
    TkSizeT index)
{
    XGCValues gcValues;
    GC newGC, newActiveGC, newDisabledGC, newIndicatorGC;
    unsigned long mask;
    Tk_Font tkfont;
    TkMenu *menuPtr = mePtr->menuPtr;

479
480
481
482
483
484
485
486
487


488
489
490

491
492
493
494
495
496
497
479
480
481
482
483
484
485


486
487
488
489

490
491
492
493
494
495
496
497







-
-
+
+


-
+







 *	one already scheduled.
 *
 *----------------------------------------------------------------------
 */

void
TkEventuallyRedrawMenu(
    register TkMenu *menuPtr,	/* Information about menu to redraw. */
    register TkMenuEntry *mePtr)/* Entry to redraw. NULL means redraw all the
    TkMenu *menuPtr,	/* Information about menu to redraw. */
    TkMenuEntry *mePtr)/* Entry to redraw. NULL means redraw all the
				 * entries in the menu. */
{
    int i;
    TkSizeT i;

    if (menuPtr->tkwin == NULL) {
	return;
    }
    if (mePtr != NULL) {
	mePtr->entryFlags |= ENTRY_NEEDS_REDISPLAY;
    } else {
526
527
528
529
530
531
532
533

534
535
536
537
538
539
540
526
527
528
529
530
531
532

533
534
535
536
537
538
539
540







-
+







 *--------------------------------------------------------------
 */

static void
ComputeMenuGeometry(
    ClientData clientData)	/* Structure describing menu. */
{
    TkMenu *menuPtr = clientData;
    TkMenu *menuPtr = (TkMenu *)clientData;

    if (menuPtr->tkwin == NULL) {
	return;
    }

    if (menuPtr->menuType == MENUBAR) {
	TkpComputeMenubarGeometry(menuPtr);
582
583
584
585
586
587
588
589







590
591
592
593
594
595
596
582
583
584
585
586
587
588

589
590
591
592
593
594
595
596
597
598
599
600
601
602







-
+
+
+
+
+
+
+







    ClientData clientData,	/* Pointer to widget record. */
    int x, int y,		/* Upper left pixel (within image) that must
				 * be redisplayed. */
    int width, int height,	/* Dimensions of area to redisplay (may be
				 * <=0). */
    int imgWidth, int imgHeight)/* New dimensions of image. */
{
    register TkMenuEntry *mePtr = clientData;
    TkMenuEntry *mePtr = (TkMenuEntry *)clientData;
    (void)x;
    (void)y;
    (void)width;
    (void)height;
    (void)imgWidth;
    (void)imgHeight;

    if ((mePtr->entryFlags & ENTRY_SELECTED)
	    && !(mePtr->menuPtr->menuFlags & REDRAW_PENDING)) {
	mePtr->menuPtr->menuFlags |= REDRAW_PENDING;
	Tcl_DoWhenIdle(DisplayMenu, mePtr->menuPtr);
    }
}
611
612
613
614
615
616
617
618
619
620
621





622
623
624
625
626
627
628
617
618
619
620
621
622
623




624
625
626
627
628
629
630
631
632
633
634
635







-
-
-
-
+
+
+
+
+







 *----------------------------------------------------------------------
 */

static void
DisplayMenu(
    ClientData clientData)	/* Information about widget. */
{
    register TkMenu *menuPtr = clientData;
    register TkMenuEntry *mePtr;
    register Tk_Window tkwin = menuPtr->tkwin;
    int index, strictMotif;
    TkMenu *menuPtr = (TkMenu *)clientData;
    TkMenuEntry *mePtr;
    Tk_Window tkwin = menuPtr->tkwin;
    TkSizeT index;
    int strictMotif;
    Tk_Font tkfont;
    Tk_FontMetrics menuMetrics;
    int width;
    int borderWidth;
    Tk_3DBorder border;
    int relief;

664
665
666
667
668
669
670














671
672





673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689





690
691
692
693
694
695
696
697
698






699
700
701
702
703
704
705
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742







+
+
+
+
+
+
+
+
+
+
+
+
+
+


+
+
+
+
+

















+
+
+
+
+









+
+
+
+
+
+







	    }
	}
	mePtr->entryFlags &= ~ENTRY_NEEDS_REDISPLAY;

	TkpDrawMenuEntry(mePtr, Tk_WindowId(menuPtr->tkwin), tkfont,
		&menuMetrics, mePtr->x, mePtr->y, mePtr->width,
		mePtr->height, strictMotif, 1);

        if (mePtr->entryFlags & ENTRY_LAST_COLUMN) {

            /*
             * Paint the area at the right of an entry in the last column.
             * This has zero width except after menu resizing.
             */

            Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), border,
                    mePtr->x + mePtr->width, mePtr->y,
                    Tk_Width(tkwin) - mePtr->x - mePtr->width - borderWidth,
                    mePtr->height, 0, TK_RELIEF_FLAT);
        }

	if ((index > 0) && (menuPtr->menuType != MENUBAR)
		&& mePtr->columnBreak) {

            /*
             * Paint the area under the last entry in a column.
             */

	    mePtr = menuPtr->entries[index - 1];
	    Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), border,
		mePtr->x, mePtr->y + mePtr->height, mePtr->width,
		Tk_Height(tkwin) - mePtr->y - mePtr->height - borderWidth,
		0, TK_RELIEF_FLAT);
	}
    }

    if (menuPtr->menuType != MENUBAR) {
	int x, y, height;

	if (menuPtr->numEntries == 0) {
	    x = y = borderWidth;
	    width = Tk_Width(tkwin) - 2 * borderWidth;
	    height = Tk_Height(tkwin) - 2 * borderWidth;
	} else {
	    mePtr = menuPtr->entries[menuPtr->numEntries - 1];

            /*
             * Paint the area under the last entry of the menu.
             */

	    Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin),
		border, mePtr->x, mePtr->y + mePtr->height, mePtr->width,
		Tk_Height(tkwin) - mePtr->y - mePtr->height - borderWidth,
		0, TK_RELIEF_FLAT);
	    x = mePtr->x + mePtr->width;
	    y = mePtr->y + mePtr->height;
	    width = Tk_Width(tkwin) - x - borderWidth;
	    height = Tk_Height(tkwin) - y - borderWidth;
	}

        /*
         * Paint the area at the bottom right of the last entry.
         * This has zero width except after menu resizing.
         */

	Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), border, x, y,
		width, height, 0, TK_RELIEF_FLAT);
    }

    Tk_GetReliefFromObj(NULL, menuPtr->reliefPtr, &relief);
    Tk_Draw3DRectangle(menuPtr->tkwin, Tk_WindowId(tkwin),
	    border, 0, 0, Tk_Width(tkwin), Tk_Height(tkwin), borderWidth,
725
726
727
728
729
730
731
732

733
734
735
736
737
738
739
762
763
764
765
766
767
768

769
770
771
772
773
774
775
776







-
+







 */

void
TkMenuEventProc(
    ClientData clientData,	/* Information about window. */
    XEvent *eventPtr)		/* Information about event. */
{
    TkMenu *menuPtr = clientData;
    TkMenu *menuPtr = (TkMenu *)clientData;

    if ((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0)) {
	TkEventuallyRedrawMenu(menuPtr, NULL);
    } else if (eventPtr->type == ConfigureNotify) {
	TkEventuallyRecomputeMenu(menuPtr);
	TkEventuallyRedrawMenu(menuPtr, NULL);
    } else if (eventPtr->type == ActivateNotify) {
790
791
792
793
794
795
796
797







798
799
800
801
802
803
804
827
828
829
830
831
832
833

834
835
836
837
838
839
840
841
842
843
844
845
846
847







-
+
+
+
+
+
+
+







    ClientData clientData,	/* Pointer to widget record. */
    int x, int y,		/* Upper left pixel (within image) that must
				 * be redisplayed. */
    int width, int height,	/* Dimensions of area to redisplay (may be
				 * <=0). */
    int imgWidth, int imgHeight)/* New dimensions of image. */
{
    register TkMenu *menuPtr = ((TkMenuEntry *) clientData)->menuPtr;
    TkMenu *menuPtr = (TkMenu *)((TkMenuEntry *) clientData)->menuPtr;
    (void)x;
    (void)y;
    (void)width;
    (void)height;
    (void)imgWidth;
    (void)imgHeight;

    if ((menuPtr->tkwin != NULL) && !(menuPtr->menuFlags & RESIZE_PENDING)) {
	menuPtr->menuFlags |= RESIZE_PENDING;
	Tcl_DoWhenIdle(ComputeMenuGeometry, menuPtr);
    }
}

848
849
850
851
852
853
854
855
856


857
858
859
860
861
862
863
891
892
893
894
895
896
897


898
899
900
901
902
903
904
905
906







-
-
+
+







 *--------------------------------------------------------------
 */

int
TkPostSubmenu(
    Tcl_Interp *interp,		/* Used for invoking sub-commands and
				 * reporting errors. */
    register TkMenu *menuPtr,	/* Information about menu as a whole. */
    register TkMenuEntry *mePtr)/* Info about submenu that is to be posted.
    TkMenu *menuPtr,	/* Information about menu as a whole. */
    TkMenuEntry *mePtr)/* Info about submenu that is to be posted.
				 * NULL means make sure that no submenu is
				 * posted. */
{
    int result, x, y;
    Tcl_Obj *subary[4];

    if (mePtr == menuPtr->postedCascade) {
907
908
909
910
911
912
913
914
915


916
917
918
919
920
921
922
950
951
952
953
954
955
956


957
958
959
960
961
962
963
964
965







-
-
+
+








	Tk_GetRootCoords(menuPtr->tkwin, &x, &y);
	AdjustMenuCoords(menuPtr, mePtr, &x, &y);

	menuPtr->postedCascade = mePtr;
	subary[0] = mePtr->namePtr;
	subary[1] = Tcl_NewStringObj("post", -1);
	subary[2] = Tcl_NewIntObj(x);
	subary[3] = Tcl_NewIntObj(y);
	subary[2] = Tcl_NewWideIntObj(x);
	subary[3] = Tcl_NewWideIntObj(y);
	Tcl_IncrRefCount(subary[1]);
	Tcl_IncrRefCount(subary[2]);
	Tcl_IncrRefCount(subary[3]);
	result = Tcl_EvalObjv(interp, 4, subary, 0);
	Tcl_DecrRefCount(subary[1]);
	Tcl_DecrRefCount(subary[2]);
	Tcl_DecrRefCount(subary[3]);
Changes to generic/tkMenubutton.c.
1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15

16
17
18
19
20
21
22






-
-
+
+







-







/*
 * 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.
 */

#include "tkInt.h"
#include "tkMenubutton.h"
#include "default.h"

/*
 * The structure below defines menubutton class behavior by means of
 * procedures that can be invoked from generic window code.
 */

static const Tk_ClassProcs menubuttonClass = {
56
57
58
59
60
61
62
63
64


65
66
67
68


69
70
71
72


73
74

75
76

77
78

79
80
81

82
83
84
85


86
87

88
89
90

91
92
93
94

95
96

97
98
99

100
101

102
103

104
105
106
107

108
109
110


111
112
113

114
115

116
117
118

119
120
121

122
123

124
125
126

127
128
129

130
131
132

133
134
135

136
137
138

139
140
141
142


143
144

145
146
147


148
149

150
151
152

153
154
155

156
157
158
159
160
161
162
55
56
57
58
59
60
61


62
63
64
65


66
67
68
69


70
71
72

73
74

75
76

77
78
79

80
81
82


83
84
85

86
87
88

89
90
91
92

93
94

95
96
97

98
99

100
101

102
103
104
105

106
107


108
109
110
111

112
113

114
115
116

117
118
119

120
121

122
123
124

125
126
127

128
129
130

131
132
133

134
135
136

137
138
139


140
141
142

143
144


145
146
147

148
149
150

151
152
153

154
155
156
157
158
159
160
161







-
-
+
+


-
-
+
+


-
-
+
+

-
+

-
+

-
+


-
+


-
-
+
+

-
+


-
+



-
+

-
+


-
+

-
+

-
+



-
+

-
-
+
+


-
+

-
+


-
+


-
+

-
+


-
+


-
+


-
+


-
+


-
+


-
-
+
+

-
+

-
-
+
+

-
+


-
+


-
+








/*
 * Information used for parsing configuration specs:
 */

static const Tk_OptionSpec optionSpecs[] = {
    {TK_OPTION_BORDER, "-activebackground", "activeBackground", "Foreground",
	DEF_MENUBUTTON_ACTIVE_BG_COLOR, -1,
	Tk_Offset(TkMenuButton, activeBorder), 0,
	DEF_MENUBUTTON_ACTIVE_BG_COLOR, TCL_INDEX_NONE,
	offsetof(TkMenuButton, activeBorder), 0,
	(ClientData) DEF_MENUBUTTON_ACTIVE_BG_MONO, 0},
    {TK_OPTION_COLOR, "-activeforeground", "activeForeground", "Background",
	DEF_MENUBUTTON_ACTIVE_FG_COLOR, -1,
	 Tk_Offset(TkMenuButton, activeFg),
	DEF_MENUBUTTON_ACTIVE_FG_COLOR, TCL_INDEX_NONE,
	 offsetof(TkMenuButton, activeFg),
	 0, DEF_MENUBUTTON_ACTIVE_FG_MONO, 0},
    {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",
	DEF_MENUBUTTON_ANCHOR, -1,
	Tk_Offset(TkMenuButton, anchor), 0, 0, 0},
	DEF_MENUBUTTON_ANCHOR, TCL_INDEX_NONE,
	offsetof(TkMenuButton, anchor), 0, 0, 0},
    {TK_OPTION_BORDER, "-background", "background", "Background",
	DEF_MENUBUTTON_BG_COLOR, -1, Tk_Offset(TkMenuButton, normalBorder),
	DEF_MENUBUTTON_BG_COLOR, TCL_INDEX_NONE, offsetof(TkMenuButton, normalBorder),
	0, DEF_MENUBUTTON_BG_MONO, 0},
    {TK_OPTION_SYNONYM, "-bd", NULL, NULL, NULL, 0, -1, 0,
    {TK_OPTION_SYNONYM, "-bd", NULL, NULL, NULL, 0, TCL_INDEX_NONE, 0,
	(ClientData) "-borderwidth", 0},
    {TK_OPTION_SYNONYM, "-bg", NULL, NULL, NULL, 0, -1, 0,
    {TK_OPTION_SYNONYM, "-bg", NULL, NULL, NULL, 0, TCL_INDEX_NONE, 0,
	(ClientData) "-background", 0},
    {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap",
	DEF_MENUBUTTON_BITMAP, -1, Tk_Offset(TkMenuButton, bitmap),
	DEF_MENUBUTTON_BITMAP, TCL_INDEX_NONE, offsetof(TkMenuButton, bitmap),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
	DEF_MENUBUTTON_BORDER_WIDTH, -1,
	Tk_Offset(TkMenuButton, borderWidth), 0, 0, 0},
	DEF_MENUBUTTON_BORDER_WIDTH, TCL_INDEX_NONE,
	offsetof(TkMenuButton, borderWidth), 0, 0, 0},
    {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
	DEF_MENUBUTTON_CURSOR, -1, Tk_Offset(TkMenuButton, cursor),
	DEF_MENUBUTTON_CURSOR, TCL_INDEX_NONE, offsetof(TkMenuButton, cursor),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_STRING_TABLE, "-direction", "direction", "Direction",
	DEF_MENUBUTTON_DIRECTION, -1, Tk_Offset(TkMenuButton, direction),
	DEF_MENUBUTTON_DIRECTION, TCL_INDEX_NONE, offsetof(TkMenuButton, direction),
	0, directionStrings, 0},
    {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground",
	"DisabledForeground", DEF_MENUBUTTON_DISABLED_FG_COLOR,
	-1, Tk_Offset(TkMenuButton, disabledFg), TK_OPTION_NULL_OK,
	TCL_INDEX_NONE, offsetof(TkMenuButton, disabledFg), TK_OPTION_NULL_OK,
	(ClientData) DEF_MENUBUTTON_DISABLED_FG_MONO, 0},
    {TK_OPTION_SYNONYM, "-fg", "foreground", NULL, NULL, 0, -1, 0,
    {TK_OPTION_SYNONYM, "-fg", "foreground", NULL, NULL, 0, TCL_INDEX_NONE, 0,
	(ClientData) "-foreground", 0},
    {TK_OPTION_FONT, "-font", "font", "Font",
	DEF_MENUBUTTON_FONT, -1, Tk_Offset(TkMenuButton, tkfont), 0, 0, 0},
	DEF_MENUBUTTON_FONT, TCL_INDEX_NONE, offsetof(TkMenuButton, tkfont), 0, 0, 0},
    {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
	DEF_MENUBUTTON_FG, -1, Tk_Offset(TkMenuButton, normalFg), 0, 0, 0},
	DEF_MENUBUTTON_FG, TCL_INDEX_NONE, offsetof(TkMenuButton, normalFg), 0, 0, 0},
    {TK_OPTION_STRING, "-height", "height", "Height",
	DEF_MENUBUTTON_HEIGHT, -1, Tk_Offset(TkMenuButton, heightString),
	DEF_MENUBUTTON_HEIGHT, TCL_INDEX_NONE, offsetof(TkMenuButton, heightString),
	0, 0, 0},
    {TK_OPTION_COLOR, "-highlightbackground", "highlightBackground",
	"HighlightBackground", DEF_MENUBUTTON_HIGHLIGHT_BG_COLOR,
	-1, Tk_Offset(TkMenuButton, highlightBgColorPtr), 0, 0, 0},
	TCL_INDEX_NONE, offsetof(TkMenuButton, highlightBgColorPtr), 0, 0, 0},
    {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
	DEF_MENUBUTTON_HIGHLIGHT, -1,
	Tk_Offset(TkMenuButton, highlightColorPtr),	0, 0, 0},
	DEF_MENUBUTTON_HIGHLIGHT, TCL_INDEX_NONE,
	offsetof(TkMenuButton, highlightColorPtr),	0, 0, 0},
    {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
	"HighlightThickness", DEF_MENUBUTTON_HIGHLIGHT_WIDTH,
	-1, Tk_Offset(TkMenuButton, highlightWidth), 0, 0, 0},
	TCL_INDEX_NONE, offsetof(TkMenuButton, highlightWidth), 0, 0, 0},
    {TK_OPTION_STRING, "-image", "image", "Image",
	DEF_MENUBUTTON_IMAGE, -1, Tk_Offset(TkMenuButton, imageString),
	DEF_MENUBUTTON_IMAGE, TCL_INDEX_NONE, offsetof(TkMenuButton, imageString),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_BOOLEAN, "-indicatoron", "indicatorOn", "IndicatorOn",
	DEF_MENUBUTTON_INDICATOR, -1, Tk_Offset(TkMenuButton, indicatorOn),
	DEF_MENUBUTTON_INDICATOR, TCL_INDEX_NONE, offsetof(TkMenuButton, indicatorOn),
	0, 0, 0},
    {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",
	DEF_MENUBUTTON_JUSTIFY, -1, Tk_Offset(TkMenuButton, justify), 0, 0, 0},
	DEF_MENUBUTTON_JUSTIFY, TCL_INDEX_NONE, offsetof(TkMenuButton, justify), 0, 0, 0},
    {TK_OPTION_STRING, "-menu", "menu", "Menu",
	DEF_MENUBUTTON_MENU, -1, Tk_Offset(TkMenuButton, menuName),
	DEF_MENUBUTTON_MENU, TCL_INDEX_NONE, offsetof(TkMenuButton, menuName),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_PIXELS, "-padx", "padX", "Pad",
	DEF_MENUBUTTON_PADX, -1, Tk_Offset(TkMenuButton, padX),
	DEF_MENUBUTTON_PADX, TCL_INDEX_NONE, offsetof(TkMenuButton, padX),
	0, 0, 0},
    {TK_OPTION_PIXELS, "-pady", "padY", "Pad",
	DEF_MENUBUTTON_PADY, -1, Tk_Offset(TkMenuButton, padY),
	DEF_MENUBUTTON_PADY, TCL_INDEX_NONE, offsetof(TkMenuButton, padY),
	0, 0, 0},
    {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
	DEF_MENUBUTTON_RELIEF, -1, Tk_Offset(TkMenuButton, relief),
	DEF_MENUBUTTON_RELIEF, TCL_INDEX_NONE, offsetof(TkMenuButton, relief),
	0, 0, 0},
    {TK_OPTION_STRING_TABLE, "-compound", "compound", "Compound",
	 DEF_BUTTON_COMPOUND, -1, Tk_Offset(TkMenuButton, compound), 0,
	 DEF_BUTTON_COMPOUND, TCL_INDEX_NONE, offsetof(TkMenuButton, compound), 0,
	 compoundStrings, 0},
    {TK_OPTION_STRING_TABLE, "-state", "state", "State",
	DEF_MENUBUTTON_STATE, -1, Tk_Offset(TkMenuButton, state),
	DEF_MENUBUTTON_STATE, TCL_INDEX_NONE, offsetof(TkMenuButton, state),
	0, stateStrings, 0},
    {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
	DEF_MENUBUTTON_TAKE_FOCUS, -1,
	Tk_Offset(TkMenuButton, takeFocus), TK_OPTION_NULL_OK, 0, 0},
	DEF_MENUBUTTON_TAKE_FOCUS, TCL_INDEX_NONE,
	offsetof(TkMenuButton, takeFocus), TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_STRING, "-text", "text", "Text",
	DEF_MENUBUTTON_TEXT, -1, Tk_Offset(TkMenuButton, text), 0, 0, 0},
	DEF_MENUBUTTON_TEXT, TCL_INDEX_NONE, offsetof(TkMenuButton, text), 0, 0, 0},
    {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable",
	DEF_MENUBUTTON_TEXT_VARIABLE, -1,
	Tk_Offset(TkMenuButton, textVarName), TK_OPTION_NULL_OK, 0, 0},
	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, -1, Tk_Offset(TkMenuButton, underline),
	DEF_MENUBUTTON_UNDERLINE, TCL_INDEX_NONE, offsetof(TkMenuButton, underline),
	 0, 0, 0},
    {TK_OPTION_STRING, "-width", "width", "Width",
	DEF_MENUBUTTON_WIDTH, -1, Tk_Offset(TkMenuButton, widthString),
	DEF_MENUBUTTON_WIDTH, TCL_INDEX_NONE, offsetof(TkMenuButton, widthString),
	0, 0, 0},
    {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength",
	DEF_MENUBUTTON_WRAP_LENGTH, -1, Tk_Offset(TkMenuButton, wrapLength),
	DEF_MENUBUTTON_WRAP_LENGTH, TCL_INDEX_NONE, offsetof(TkMenuButton, wrapLength),
	0, 0, 0},
    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0}
};

/*
 * The following tables define the menubutton widget commands and map the
 * indexes into the string tables into a single enumerated type used to
208
209
210
211
212
213
214
215

216
217
218
219
220

221
222

223
224
225
226
227
228
229
207
208
209
210
211
212
213

214
215
216
217
218

219
220
221
222
223
224
225
226
227
228
229







-
+




-
+


+







 *	See the user documentation.
 *
 *--------------------------------------------------------------
 */

int
Tk_MenubuttonObjCmd(
    ClientData clientData,	/* NULL. */
    ClientData dummy,	/* NULL. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    register TkMenuButton *mbPtr;
    TkMenuButton *mbPtr;
    Tk_OptionTable optionTable;
    Tk_Window tkwin;
    (void)dummy;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "pathName ?-option value ...?");
	return TCL_ERROR;
    }

    /*
304
305
306
307
308
309
310
311

312
313
314
315
316
317
318
319
320
321

322
323
324
325
326
327
328
304
305
306
307
308
309
310

311
312
313
314
315
316
317
318
319
320

321
322
323
324
325
326
327
328







-
+









-
+







    mbPtr->takeFocus = NULL;
    mbPtr->flags = 0;

    Tk_CreateEventHandler(mbPtr->tkwin,
	    ExposureMask|StructureNotifyMask|FocusChangeMask,
	    MenuButtonEventProc, mbPtr);

    if (Tk_InitOptions(interp, (char *) mbPtr, optionTable, tkwin) != TCL_OK) {
    if (Tk_InitOptions(interp, mbPtr, optionTable, tkwin) != TCL_OK) {
	Tk_DestroyWindow(mbPtr->tkwin);
	return TCL_ERROR;
    }

    if (ConfigureMenuButton(interp, mbPtr, objc-2, objv+2) != TCL_OK) {
	Tk_DestroyWindow(mbPtr->tkwin);
	return TCL_ERROR;
    }

    Tcl_SetObjResult(interp, TkNewWindowObj(mbPtr->tkwin));
    Tcl_SetObjResult(interp, Tk_NewWindowObj(mbPtr->tkwin));
    return TCL_OK;
}

/*
 *--------------------------------------------------------------
 *
 * MenuButtonWidgetObjCmd --
343
344
345
346
347
348
349
350

351
352
353
354
355
356
357
343
344
345
346
347
348
349

350
351
352
353
354
355
356
357







-
+







static int
MenuButtonWidgetObjCmd(
    ClientData clientData,	/* Information about button widget. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    register TkMenuButton *mbPtr = clientData;
    TkMenuButton *mbPtr = (TkMenuButton *)clientData;
    int result, index;
    Tcl_Obj *objPtr;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
	return TCL_ERROR;
    }
365
366
367
368
369
370
371
372

373
374
375
376
377
378
379
380
381
382

383
384
385
386
387
388
389
365
366
367
368
369
370
371

372
373
374
375
376
377
378
379
380
381

382
383
384
385
386
387
388
389







-
+









-
+







    switch (index) {
    case COMMAND_CGET:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 1, objv, "cget option");
	    goto error;
	}

	objPtr = Tk_GetOptionValue(interp, (char *) mbPtr,
	objPtr = Tk_GetOptionValue(interp, mbPtr,
		mbPtr->optionTable, objv[2], mbPtr->tkwin);
	if (objPtr == NULL) {
	    goto error;
	}
	Tcl_SetObjResult(interp, objPtr);
	break;

    case COMMAND_CONFIGURE:
	if (objc <= 3) {
	    objPtr = Tk_GetOptionInfo(interp, (char *) mbPtr,
	    objPtr = Tk_GetOptionInfo(interp, mbPtr,
		    mbPtr->optionTable, (objc == 3) ? objv[2] : NULL,
		    mbPtr->tkwin);
	    if (objPtr == NULL) {
		goto error;
	    }
	    Tcl_SetObjResult(interp, objPtr);
	} else {
418
419
420
421
422
423
424
425

426
427
428
429
430
431
432
418
419
420
421
422
423
424

425
426
427
428
429
430
431
432







-
+







 *----------------------------------------------------------------------
 */

static void
DestroyMenuButton(
    char *memPtr)		/* Info about button widget. */
{
    register TkMenuButton *mbPtr = (TkMenuButton *) memPtr;
    TkMenuButton *mbPtr = (TkMenuButton *) memPtr;
    TkpDestroyMenuButton(mbPtr);

    if (mbPtr->flags & REDRAW_PENDING) {
	Tcl_CancelIdleCall(TkpDisplayMenuButton, mbPtr);
    }

    /*
486
487
488
489
490
491
492
493

494
495
496
497
498
499
500
486
487
488
489
490
491
492

493
494
495
496
497
498
499
500







-
+







 *
 *----------------------------------------------------------------------
 */

static int
ConfigureMenuButton(
    Tcl_Interp *interp,		/* Used for error reporting. */
    register TkMenuButton *mbPtr,
    TkMenuButton *mbPtr,
				/* Information about widget; may or may not
				 * already have values for some fields. */
    int objc,			/* Number of valid entries in objv. */
    Tcl_Obj *const objv[])	/* Arguments. */
{
    Tk_SavedOptions savedOptions;
    Tcl_Obj *errorResult = NULL;
520
521
522
523
524
525
526
527

528
529
530
531
532
533
534
520
521
522
523
524
525
526

527
528
529
530
531
532
533
534







-
+








    for (error = 0; error <= 1; error++) {
	if (!error) {
	    /*
	     * First pass: set options to new values.
	     */

	    if (Tk_SetOptions(interp, (char *) mbPtr,
	    if (Tk_SetOptions(interp, mbPtr,
		    mbPtr->optionTable, objc, objv,
		    mbPtr->tkwin, &savedOptions, NULL) != TCL_OK) {
		continue;
	    }
	} else {
	    /*
	     * Second pass: restore options to old values.
629
630
631
632
633
634
635
636

637
638
639
640
641
642
643
629
630
631
632
633
634
635

636
637
638
639
640
641
642
643







-
+







	if (value == NULL) {
	    Tcl_SetVar2(interp, mbPtr->textVarName, NULL, mbPtr->text,
		    TCL_GLOBAL_ONLY);
	} else {
	    if (mbPtr->text != NULL) {
		ckfree(mbPtr->text);
	    }
	    mbPtr->text = ckalloc(strlen(value) + 1);
	    mbPtr->text = (char *)ckalloc(strlen(value) + 1);
	    strcpy(mbPtr->text, value);
	}
	Tcl_TraceVar2(interp, mbPtr->textVarName, NULL,
		TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
		MenuButtonTextVarProc, mbPtr);
    }

671
672
673
674
675
676
677
678

679
680
681
682
683
684
685
671
672
673
674
675
676
677

678
679
680
681
682
683
684
685







-
+







void
TkMenuButtonWorldChanged(
    ClientData instanceData)	/* Information about widget. */
{
    XGCValues gcValues;
    GC gc;
    unsigned long mask;
    TkMenuButton *mbPtr = instanceData;
    TkMenuButton *mbPtr = (TkMenuButton *)instanceData;

    gcValues.font = Tk_FontId(mbPtr->tkfont);
    gcValues.foreground = mbPtr->normalFg->pixel;
    gcValues.background = Tk_3DBorderColor(mbPtr->normalBorder)->pixel;

    /*
     * Note: GraphicsExpose events are disabled in GC's because they're used
772
773
774
775
776
777
778
779

780
781
782
783
784
785
786
772
773
774
775
776
777
778

779
780
781
782
783
784
785
786







-
+







 */

static void
MenuButtonEventProc(
    ClientData clientData,	/* Information about window. */
    XEvent *eventPtr)		/* Information about event. */
{
    TkMenuButton *mbPtr = clientData;
    TkMenuButton *mbPtr = (TkMenuButton *)clientData;

    if ((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0)) {
	goto redraw;
    } else if (eventPtr->type == ConfigureNotify) {
	/*
	 * Must redraw after size changes, since layout could have changed and
	 * borders will need to be redrawn.
831
832
833
834
835
836
837
838

839
840
841
842
843
844
845
831
832
833
834
835
836
837

838
839
840
841
842
843
844
845







-
+







 *----------------------------------------------------------------------
 */

static void
MenuButtonCmdDeletedProc(
    ClientData clientData)	/* Pointer to widget record for widget. */
{
    TkMenuButton *mbPtr = clientData;
    TkMenuButton *mbPtr = (TkMenuButton *)clientData;
    Tk_Window tkwin = mbPtr->tkwin;

    /*
     * This function could be invoked either because the window was destroyed
     * and the command was then deleted (in which case tkwin is NULL) or
     * because the command was deleted, and then this function destroys the
     * widget.
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880

881
882



883
884
885
886
887
888
889
864
865
866
867
868
869
870

871
872
873
874
875
876
877
878

879
880

881
882
883
884
885
886
887
888
889
890







-








-
+

-
+
+
+







 * Side effects:
 *	The text displayed in the menu button will change to match the
 *	variable.
 *
 *--------------------------------------------------------------
 */

	/* ARGSUSED */
static char *
MenuButtonTextVarProc(
    ClientData clientData,	/* Information about button. */
    Tcl_Interp *interp,		/* Interpreter containing variable. */
    const char *name1,		/* Name of variable. */
    const char *name2,		/* Second part of variable name. */
    int flags)			/* Information about what happened. */
{
    register TkMenuButton *mbPtr = clientData;
    TkMenuButton *mbPtr = (TkMenuButton *)clientData;
    const char *value;
    unsigned len;
    size_t len;
    (void)name1;
    (void)name2;

    /*
     * If the variable is unset, then immediately recreate it unless the whole
     * interpreter is going away.
     */

    if (flags & TCL_TRACE_UNSETS) {
920
921
922
923
924
925
926
927
928


929
930
931
932
933
934
935
921
922
923
924
925
926
927


928
929
930
931
932
933
934
935
936







-
-
+
+







    value = Tcl_GetVar2(interp, mbPtr->textVarName, NULL, TCL_GLOBAL_ONLY);
    if (value == NULL) {
	value = "";
    }
    if (mbPtr->text != NULL) {
	ckfree(mbPtr->text);
    }
    len = 1 + (unsigned) strlen(value);
    mbPtr->text = ckalloc(len);
    len = 1 + strlen(value);
    mbPtr->text = (char *)ckalloc(len);
    memcpy(mbPtr->text, value, len);
    TkpComputeMenuButtonGeometry(mbPtr);

    if ((mbPtr->tkwin != NULL) && Tk_IsMapped(mbPtr->tkwin)
	    && !(mbPtr->flags & REDRAW_PENDING)) {
	Tcl_DoWhenIdle(TkpDisplayMenuButton, mbPtr);
	mbPtr->flags |= REDRAW_PENDING;
960
961
962
963
964
965
966
967







968
969
970
971
972
973
974
961
962
963
964
965
966
967

968
969
970
971
972
973
974
975
976
977
978
979
980
981







-
+
+
+
+
+
+
+







    ClientData clientData,	/* Pointer to widget record. */
    int x, int y,		/* Upper left pixel (within image) that must
				 * be redisplayed. */
    int width, int height,	/* Dimensions of area to redisplay (may be <=
				 * 0). */
    int imgWidth, int imgHeight)/* New dimensions of image. */
{
    register TkMenuButton *mbPtr = clientData;
    TkMenuButton *mbPtr = (TkMenuButton *)clientData;
    (void)x;
    (void)y;
    (void)width;
    (void)height;
    (void)imgWidth;
    (void)imgHeight;

    if (mbPtr->tkwin != NULL) {
	TkpComputeMenuButtonGeometry(mbPtr);
	if (Tk_IsMapped(mbPtr->tkwin) && !(mbPtr->flags & REDRAW_PENDING)) {
	    Tcl_DoWhenIdle(TkpDisplayMenuButton, mbPtr);
	    mbPtr->flags |= REDRAW_PENDING;
	}
Changes to generic/tkMenubutton.h.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







/*
 * 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.
 */

#ifndef _TKMENUBUTTON
#define _TKMENUBUTTON
Changes to generic/tkMessage.c.
1
2
3
4
5
6
7
8
9
10



11
12
13
14
15
16
17


18
19
20
21
22
23
24
1
2
3
4
5
6
7



8
9
10
11
12
13
14
15


16
17
18
19
20
21
22
23
24







-
-
-
+
+
+





-
-
+
+







/*
 * tkMessage.c --
 *
 *	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.
 */

#include "default.h"
#include "tkInt.h"
#include "tkInt.h"
#include "default.h"

/*
 * A data structure of the following type is kept for each message widget
 * managed by this file:
 */

typedef struct {
105
106
107
108
109
110
111
112

113
114

115
116

117
118
119

120
121

122
123
124


125
126

127
128
129

130
131

132
133

134
135
136


137
138

139
140
141
142


143
144

145
146
147


148
149
150


151
152

153
154

155
156
157

158
159

160
161
162

163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183

184
185
186
187
188
189
190
105
106
107
108
109
110
111

112
113

114
115

116
117
118

119
120

121
122


123
124
125

126
127
128

129
130

131
132

133
134


135
136
137

138
139
140


141
142
143

144
145


146
147
148


149
150
151

152
153

154
155
156

157
158

159
160
161

162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182

183
184
185
186
187
188
189
190







-
+

-
+

-
+


-
+

-
+

-
-
+
+

-
+


-
+

-
+

-
+

-
-
+
+

-
+


-
-
+
+

-
+

-
-
+
+

-
-
+
+

-
+

-
+


-
+

-
+


-
+




















-
+








/*
 * Information used for argv parsing.
 */

static const Tk_OptionSpec optionSpecs[] = {
    {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor", DEF_MESSAGE_ANCHOR,
	 -1, Tk_Offset(Message, anchor), 0, 0, 0},
	 TCL_INDEX_NONE, offsetof(Message, anchor), 0, 0, 0},
    {TK_OPTION_INT, "-aspect", "aspect", "Aspect", DEF_MESSAGE_ASPECT,
	 -1, Tk_Offset(Message, aspect), 0, 0, 0},
	 TCL_INDEX_NONE, offsetof(Message, aspect), 0, 0, 0},
    {TK_OPTION_BORDER, "-background", "background", "Background",
	 DEF_MESSAGE_BG_COLOR, -1, Tk_Offset(Message, border), 0,
	 DEF_MESSAGE_BG_COLOR, TCL_INDEX_NONE, offsetof(Message, border), 0,
	 DEF_MESSAGE_BG_MONO, 0},
    {TK_OPTION_SYNONYM, "-bd", NULL, NULL, NULL,
	 0, -1, 0, "-borderwidth", 0},
	 0, TCL_INDEX_NONE, 0, "-borderwidth", 0},
    {TK_OPTION_SYNONYM, "-bg", NULL, NULL, NULL,
	 0, -1, 0, "-background", 0},
	 0, TCL_INDEX_NONE, 0, "-background", 0},
    {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
	 DEF_MESSAGE_BORDER_WIDTH, -1,
	 Tk_Offset(Message, borderWidth), 0, 0, 0},
	 DEF_MESSAGE_BORDER_WIDTH, TCL_INDEX_NONE,
	 offsetof(Message, borderWidth), 0, 0, 0},
    {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
	 DEF_MESSAGE_CURSOR, -1, Tk_Offset(Message, cursor),
	 DEF_MESSAGE_CURSOR, TCL_INDEX_NONE, offsetof(Message, cursor),
	 TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_SYNONYM, "-fg", NULL, NULL, NULL,
	 0, -1, 0, "-foreground", 0},
	 0, TCL_INDEX_NONE, 0, "-foreground", 0},
    {TK_OPTION_FONT, "-font", "font", "Font",
	DEF_MESSAGE_FONT, -1, Tk_Offset(Message, tkfont), 0, 0, 0},
	DEF_MESSAGE_FONT, TCL_INDEX_NONE, offsetof(Message, tkfont), 0, 0, 0},
    {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
	DEF_MESSAGE_FG, -1, Tk_Offset(Message, fgColorPtr), 0, 0, 0},
	DEF_MESSAGE_FG, TCL_INDEX_NONE, offsetof(Message, fgColorPtr), 0, 0, 0},
    {TK_OPTION_COLOR, "-highlightbackground", "highlightBackground",
	 "HighlightBackground", DEF_MESSAGE_HIGHLIGHT_BG, -1,
	 Tk_Offset(Message, highlightBgColorPtr), 0, 0, 0},
	 "HighlightBackground", DEF_MESSAGE_HIGHLIGHT_BG, TCL_INDEX_NONE,
	 offsetof(Message, highlightBgColorPtr), 0, 0, 0},
    {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
	 DEF_MESSAGE_HIGHLIGHT, -1, Tk_Offset(Message, highlightColorPtr),
	 DEF_MESSAGE_HIGHLIGHT, TCL_INDEX_NONE, offsetof(Message, highlightColorPtr),
	 0, 0, 0},
    {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
	"HighlightThickness", DEF_MESSAGE_HIGHLIGHT_WIDTH, -1,
	 Tk_Offset(Message, highlightWidth), 0, 0, 0},
	"HighlightThickness", DEF_MESSAGE_HIGHLIGHT_WIDTH, TCL_INDEX_NONE,
	 offsetof(Message, highlightWidth), 0, 0, 0},
    {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",
	DEF_MESSAGE_JUSTIFY, -1, Tk_Offset(Message, justify), 0, 0, 0},
	DEF_MESSAGE_JUSTIFY, TCL_INDEX_NONE, offsetof(Message, justify), 0, 0, 0},
    {TK_OPTION_PIXELS, "-padx", "padX", "Pad",
	 DEF_MESSAGE_PADX, Tk_Offset(Message, padXPtr),
	 Tk_Offset(Message, padX), 0, 0, 0},
	 DEF_MESSAGE_PADX, offsetof(Message, padXPtr),
	 offsetof(Message, padX), 0, 0, 0},
    {TK_OPTION_PIXELS, "-pady", "padY", "Pad",
	 DEF_MESSAGE_PADY, Tk_Offset(Message, padYPtr),
	 Tk_Offset(Message, padY), 0, 0, 0},
	 DEF_MESSAGE_PADY, offsetof(Message, padYPtr),
	 offsetof(Message, padY), 0, 0, 0},
    {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
	DEF_MESSAGE_RELIEF, -1, Tk_Offset(Message, relief), 0, 0, 0},
	DEF_MESSAGE_RELIEF, TCL_INDEX_NONE, offsetof(Message, relief), 0, 0, 0},
    {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
	DEF_MESSAGE_TAKE_FOCUS, -1, Tk_Offset(Message, takeFocus),
	DEF_MESSAGE_TAKE_FOCUS, TCL_INDEX_NONE, offsetof(Message, takeFocus),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_STRING, "-text", "text", "Text",
	DEF_MESSAGE_TEXT, -1, Tk_Offset(Message, string), 0, 0, 0},
	DEF_MESSAGE_TEXT, TCL_INDEX_NONE, offsetof(Message, string), 0, 0, 0},
    {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable",
	DEF_MESSAGE_TEXT_VARIABLE, -1, Tk_Offset(Message, textVarName),
	DEF_MESSAGE_TEXT_VARIABLE, TCL_INDEX_NONE, offsetof(Message, textVarName),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_PIXELS, "-width", "width", "Width",
	DEF_MESSAGE_WIDTH, -1, Tk_Offset(Message, width), 0, 0 ,0},
	DEF_MESSAGE_WIDTH, TCL_INDEX_NONE, offsetof(Message, width), 0, 0 ,0},
    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0}
};

/*
 * Forward declarations for functions defined later in this file:
 */

static void		MessageCmdDeletedProc(ClientData clientData);
static void		MessageEventProc(ClientData clientData,
			    XEvent *eventPtr);
static char *		MessageTextVarProc(ClientData clientData,
			    Tcl_Interp *interp, const char *name1,
			    const char *name2, int flags);
static int		MessageWidgetObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static void		MessageWorldChanged(ClientData instanceData);
static void		ComputeMessageGeometry(Message *msgPtr);
static int		ConfigureMessage(Tcl_Interp *interp, Message *msgPtr,
			    int objc, Tcl_Obj *const objv[], int flags);
static void		DestroyMessage(char *memPtr);
static void		DestroyMessage(void *memPtr);
static void		DisplayMessage(ClientData clientData);

/*
 * The structure below defines message class behavior by means of functions
 * that can be invoked from generic window code.
 */

210
211
212
213
214
215
216
217

218
219
220
221
222

223
224

225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245


246
247
248
249
250
251
252
210
211
212
213
214
215
216

217
218
219
220
221

222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244


245
246
247
248
249
250
251
252
253







-
+




-
+


+



















-
-
+
+







 *	See the user documentation.
 *
 *--------------------------------------------------------------
 */

int
Tk_MessageObjCmd(
    ClientData clientData,	/* NULL. */
    ClientData dummy,	/* NULL. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument strings. */
{
    register Message *msgPtr;
    Message *msgPtr;
    Tk_OptionTable optionTable;
    Tk_Window tkwin;
    (void)dummy;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "pathName ?-option value ...?");
	return TCL_ERROR;
    }

    tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp),
	    Tcl_GetString(objv[1]), NULL);
    if (tkwin == NULL) {
	return TCL_ERROR;
    }

    /*
     * Create the option table for this widget class. If it has already been
     * created, the cached pointer will be returned.
     */

    optionTable = Tk_CreateOptionTable(interp, optionSpecs);

    msgPtr = ckalloc(sizeof(Message));
    memset(msgPtr, 0, (size_t) sizeof(Message));
    msgPtr = (Message *)ckalloc(sizeof(Message));
    memset(msgPtr, 0, sizeof(Message));

    /*
     * Set values for those fields that don't take a 0 or NULL value.
     */

    msgPtr->tkwin = tkwin;
    msgPtr->display = Tk_Display(tkwin);
263
264
265
266
267
268
269
270

271
272
273
274
275
276
277
278
279
280

281
282
283
284
285
286
287
264
265
266
267
268
269
270

271
272
273
274
275
276
277
278
279
280

281
282
283
284
285
286
287
288







-
+









-
+







    msgPtr->cursor = NULL;

    Tk_SetClass(msgPtr->tkwin, "Message");
    Tk_SetClassProcs(msgPtr->tkwin, &messageClass, msgPtr);
    Tk_CreateEventHandler(msgPtr->tkwin,
	    ExposureMask|StructureNotifyMask|FocusChangeMask,
	    MessageEventProc, msgPtr);
    if (Tk_InitOptions(interp, (char *)msgPtr, optionTable, tkwin) != TCL_OK) {
    if (Tk_InitOptions(interp, msgPtr, optionTable, tkwin) != TCL_OK) {
	Tk_DestroyWindow(msgPtr->tkwin);
	return TCL_ERROR;
    }

    if (ConfigureMessage(interp, msgPtr, objc-2, objv+2, 0) != TCL_OK) {
	Tk_DestroyWindow(msgPtr->tkwin);
	return TCL_ERROR;
    }

    Tcl_SetObjResult(interp, TkNewWindowObj(msgPtr->tkwin));
    Tcl_SetObjResult(interp, Tk_NewWindowObj(msgPtr->tkwin));
    return TCL_OK;
}

/*
 *--------------------------------------------------------------
 *
 * MessageWidgetObjCmd --
302
303
304
305
306
307
308
309

310
311
312
313
314
315
316
303
304
305
306
307
308
309

310
311
312
313
314
315
316
317







-
+







static int
MessageWidgetObjCmd(
    ClientData clientData,	/* Information about message widget. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument strings. */
{
    register Message *msgPtr = clientData;
    Message *msgPtr = (Message *)clientData;
    static const char *const optionStrings[] = { "cget", "configure", NULL };
    enum options { MESSAGE_CGET, MESSAGE_CONFIGURE };
    int index;
    int result = TCL_OK;
    Tcl_Obj *objPtr;

    if (objc < 2) {
327
328
329
330
331
332
333
334

335
336
337
338
339
340
341
342
343
344
345
346

347
348
349
350
351
352
353
328
329
330
331
332
333
334

335
336
337
338
339
340
341
342
343
344
345
346

347
348
349
350
351
352
353
354







-
+











-
+








    switch ((enum options) index) {
    case MESSAGE_CGET:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "option");
	    result = TCL_ERROR;
	} else {
	    objPtr = Tk_GetOptionValue(interp, (char *) msgPtr,
	    objPtr = Tk_GetOptionValue(interp, msgPtr,
		    msgPtr->optionTable, objv[2], msgPtr->tkwin);
	    if (objPtr == NULL) {
		result = TCL_ERROR;
	    } else {
		Tcl_SetObjResult(interp, objPtr);
		result = TCL_OK;
	    }
	}
	break;
    case MESSAGE_CONFIGURE:
	if (objc <= 3) {
	    objPtr = Tk_GetOptionInfo(interp, (char *) msgPtr,
	    objPtr = Tk_GetOptionInfo(interp, msgPtr,
		    msgPtr->optionTable, (objc == 3) ? objv[2] : NULL,
		    msgPtr->tkwin);
	    if (objPtr == NULL) {
		result = TCL_ERROR;
	    } else {
		Tcl_SetObjResult(interp, objPtr);
		result = TCL_OK;
378
379
380
381
382
383
384
385

386
387

388
389
390
391
392
393
394
379
380
381
382
383
384
385

386
387

388
389
390
391
392
393
394
395







-
+

-
+







 *	Everything associated with the message is freed up.
 *
 *----------------------------------------------------------------------
 */

static void
DestroyMessage(
    char *memPtr)		/* Info about message widget. */
    void *memPtr)		/* Info about message widget. */
{
    register Message *msgPtr = (Message *) memPtr;
    Message *msgPtr = (Message *) memPtr;

    msgPtr->flags |= MESSAGE_DELETED;

    Tcl_DeleteCommandFromToken(msgPtr->interp, msgPtr->widgetCmd);
    if (msgPtr->flags & REDRAW_PENDING) {
	Tcl_CancelIdleCall(DisplayMessage, msgPtr);
    }
433
434
435
436
437
438
439
440

441
442
443
444
445
446

447
448
449
450
451
452
453
454
455
456
457
458

459
460
461
462
463
464
465
434
435
436
437
438
439
440

441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459

460
461
462
463
464
465
466
467







-
+






+











-
+







 *
 *----------------------------------------------------------------------
 */

static int
ConfigureMessage(
    Tcl_Interp *interp,		/* Used for error reporting. */
    register Message *msgPtr,	/* Information about widget; may or may not
    Message *msgPtr,	/* Information about widget; may or may not
				 * already have values for some fields. */
    int objc,			/* Number of valid entries in argv. */
    Tcl_Obj *const objv[],	/* Arguments. */
    int flags)			/* Flags to pass to Tk_ConfigureWidget. */
{
    Tk_SavedOptions savedOptions;
    (void)flags;

    /*
     * Eliminate any existing trace on a variable monitored by the message.
     */

    if (msgPtr->textVarName != NULL) {
	Tcl_UntraceVar2(interp, msgPtr->textVarName, NULL,
		TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
		MessageTextVarProc, msgPtr);
    }

    if (Tk_SetOptions(interp, (char *) msgPtr, msgPtr->optionTable, objc, objv,
    if (Tk_SetOptions(interp, msgPtr, msgPtr->optionTable, objc, objv,
	    msgPtr->tkwin, &savedOptions, NULL) != TCL_OK) {
	Tk_RestoreSavedOptions(&savedOptions);
	return TCL_ERROR;
    }

    /*
     * If the message is to display the value of a variable, then set up a
474
475
476
477
478
479
480
481

482
483
484
485
486
487
488
476
477
478
479
480
481
482

483
484
485
486
487
488
489
490







-
+







	if (value == NULL) {
	    Tcl_SetVar2(interp, msgPtr->textVarName, NULL, msgPtr->string,
		    TCL_GLOBAL_ONLY);
	} else {
	    if (msgPtr->string != NULL) {
		ckfree(msgPtr->string);
	    }
	    msgPtr->string = strcpy(ckalloc(strlen(value) + 1), value);
	    msgPtr->string = strcpy((char *)ckalloc(strlen(value) + 1), value);
	}
	Tcl_TraceVar2(interp, msgPtr->textVarName, NULL,
		TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
		MessageTextVarProc, msgPtr);
    }

    /*
523
524
525
526
527
528
529
530

531
532
533
534
535
536
537
525
526
527
528
529
530
531

532
533
534
535
536
537
538
539







-
+







static void
MessageWorldChanged(
    ClientData instanceData)	/* Information about widget. */
{
    XGCValues gcValues;
    GC gc = NULL;
    Tk_FontMetrics fm;
    Message *msgPtr = instanceData;
    Message *msgPtr = (Message *)instanceData;

    if (msgPtr->border != NULL) {
	Tk_SetBackgroundFromBorder(msgPtr->tkwin, msgPtr->border);
    }

    gcValues.font = Tk_FontId(msgPtr->tkfont);
    gcValues.foreground = msgPtr->fgColorPtr->pixel;
578
579
580
581
582
583
584
585

586
587
588
589
590
591
592
580
581
582
583
584
585
586

587
588
589
590
591
592
593
594







-
+







 *	desired geometry for this window.
 *
 *--------------------------------------------------------------
 */

static void
ComputeMessageGeometry(
    register Message *msgPtr)	/* Information about window. */
    Message *msgPtr)	/* Information about window. */
{
    int width, inc, height;
    int thisWidth, thisHeight, maxWidth;
    int aspect, lowerBound, upperBound, inset;

    Tk_FreeTextLayout(msgPtr->textLayout);

662
663
664
665
666
667
668
669
670


671
672
673
674
675
676
677
664
665
666
667
668
669
670


671
672
673
674
675
676
677
678
679







-
-
+
+







 *--------------------------------------------------------------
 */

static void
DisplayMessage(
    ClientData clientData)	/* Information about window. */
{
    register Message *msgPtr = clientData;
    register Tk_Window tkwin = msgPtr->tkwin;
    Message *msgPtr = (Message *)clientData;
    Tk_Window tkwin = msgPtr->tkwin;
    int x, y;
    int borderWidth = msgPtr->highlightWidth;

    msgPtr->flags &= ~REDRAW_PENDING;
    if ((msgPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {
	return;
    }
738
739
740
741
742
743
744
745

746
747
748
749
750
751
752
740
741
742
743
744
745
746

747
748
749
750
751
752
753
754







-
+







 */

static void
MessageEventProc(
    ClientData clientData,	/* Information about window. */
    XEvent *eventPtr)		/* Information about event. */
{
    Message *msgPtr = clientData;
    Message *msgPtr = (Message *)clientData;

    if (((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0))
	    || (eventPtr->type == ConfigureNotify)) {
	goto redraw;
    } else if (eventPtr->type == DestroyNotify) {
	DestroyMessage(clientData);
    } else if (eventPtr->type == FocusIn) {
791
792
793
794
795
796
797
798

799
800
801
802
803
804
805
793
794
795
796
797
798
799

800
801
802
803
804
805
806
807







-
+







 *----------------------------------------------------------------------
 */

static void
MessageCmdDeletedProc(
    ClientData clientData)	/* Pointer to widget record for widget. */
{
    Message *msgPtr = clientData;
    Message *msgPtr = (Message *)clientData;

    /*
     * This function could be invoked either because the window was destroyed
     * and the command was then deleted (in which case tkwin is NULL) or
     * because the command was deleted, and then this function destroys the
     * widget.
     */
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838

839


840
841
842
843
844
845
846
824
825
826
827
828
829
830

831
832
833
834
835
836
837
838

839
840
841
842
843
844
845
846
847
848
849







-








-
+

+
+







 *
 * Side effects:
 *	The text displayed in the message will change to match the variable.
 *
 *--------------------------------------------------------------
 */

	/* ARGSUSED */
static char *
MessageTextVarProc(
    ClientData clientData,	/* Information about message. */
    Tcl_Interp *interp,		/* Interpreter containing variable. */
    const char *name1,		/* Name of variable. */
    const char *name2,		/* Second part of variable name. */
    int flags)			/* Information about what happened. */
{
    register Message *msgPtr = clientData;
    Message *msgPtr = (Message *)clientData;
    const char *value;
    (void)name1;
    (void)name2;

    /*
     * If the variable is unset, then immediately recreate it unless the whole
     * interpreter is going away.
     */

    if (flags & TCL_TRACE_UNSETS) {
878
879
880
881
882
883
884
885

886
887
888
889
890
891
892
881
882
883
884
885
886
887

888
889
890
891
892
893
894
895







-
+







    if (value == NULL) {
	value = "";
    }
    if (msgPtr->string != NULL) {
	ckfree(msgPtr->string);
    }
    msgPtr->numChars = Tcl_NumUtfChars(value, -1);
    msgPtr->string = ckalloc(strlen(value) + 1);
    msgPtr->string = (char *)ckalloc(strlen(value) + 1);
    strcpy(msgPtr->string, value);
    ComputeMessageGeometry(msgPtr);

    if ((msgPtr->tkwin != NULL) && Tk_IsMapped(msgPtr->tkwin)
	    && !(msgPtr->flags & REDRAW_PENDING)) {
	Tcl_DoWhenIdle(DisplayMessage, msgPtr);
	msgPtr->flags |= REDRAW_PENDING;
Changes to generic/tkObj.c.
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







/*
 * 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.
 */

#include "tkInt.h"

46
47
48
49
50
51
52

53
54
55
56
57
58
59
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60







+







 * "dataKey" below is used to locate the ThreadSpecificData for the current
 * thread.
 */

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.
 */

69
70
71
72
73
74
75

76

77



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95





























96
97
98
99
100
101
102
103
104
105
106
107

108
109
110
111
112
113
114
115
116
117
118
119
120
121

122
123
124
125
126
127
128
129
130
131
132
133
134

135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152

153
154
155
156
157
158

159



160

161
162
163
164

165
166
167
168
169
170
171
172


















































173
174
175
176
177
178
179
70
71
72
73
74
75
76
77

78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140

141
142
143
144
145
146
147
148
149
150
151
152
153
154

155
156
157
158
159
160
161
162
163
164
165
166
167

168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185

186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202

203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268







+
-
+

+
+
+


















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+











-
+













-
+












-
+

















-
+






+

+
+
+

+



-
+








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







 * A WindowRep caches name-to-window lookups. The cache is invalid if tkwin is
 * NULL or if mainPtr->deletionEpoch does not match epoch.
 */

typedef struct WindowRep {
    Tk_Window tkwin;		/* Cached window; NULL if not found. */
    TkMainInfo *mainPtr;	/* MainWindow associated with tkwin. */
#if TCL_MAJOR_VERSION > 8
    long epoch;			/* Value of mainPtr->deletionEpoch at last
    size_t epoch;			/* Value of mainPtr->deletionEpoch at last
				 * successful lookup. */
#else
    long epoch;
#endif
} WindowRep;

/*
 * Prototypes for functions defined later in this file:
 */

static void		DupMMInternalRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr);
static void		DupPixelInternalRep(Tcl_Obj *srcPtr, Tcl_Obj*copyPtr);
static void		DupWindowInternalRep(Tcl_Obj *srcPtr,Tcl_Obj*copyPtr);
static void		FreeMMInternalRep(Tcl_Obj *objPtr);
static void		FreePixelInternalRep(Tcl_Obj *objPtr);
static void		FreeWindowInternalRep(Tcl_Obj *objPtr);
static ThreadSpecificData *GetTypeCache(void);
static void		UpdateStringOfMM(Tcl_Obj *objPtr);
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
#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 {
    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;

# 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
#ifdef __cplusplus
extern "C" {
#endif
extern int TclGetIntForIndex(Tcl_Interp*,  Tcl_Obj *, int, int*);
#ifdef __cplusplus
}
#endif
# define Tcl_GetIntForIndex(interp, obj, max, ptr) TclGetIntForIndex(interp, obj, max, ptr)
#endif
#endif

/*
 * The following structure defines the implementation of the "pixel" Tcl
 * object, used for measuring distances. The pixel object remembers its
 * initial display-independent settings.
 */

static const Tcl_ObjType pixelObjType = {
    "pixel",			/* name */
    FreePixelInternalRep,	/* freeIntRepProc */
    DupPixelInternalRep,	/* dupIntRepProc */
    NULL,			/* updateStringProc */
    SetPixelFromAny		/* setFromAnyProc */
    NULL			/* setFromAnyProc */
};

/*
 * The following structure defines the implementation of the "pixel" Tcl
 * object, used for measuring distances. The pixel object remembers its
 * initial display-independent settings.
 */

static const Tcl_ObjType mmObjType = {
    "mm",			/* name */
    FreeMMInternalRep,		/* freeIntRepProc */
    DupMMInternalRep,		/* dupIntRepProc */
    UpdateStringOfMM,		/* updateStringProc */
    SetMMFromAny		/* setFromAnyProc */
    NULL			/* setFromAnyProc */
};

/*
 * The following structure defines the implementation of the "window"
 * Tcl object.
 */

static const Tcl_ObjType windowObjType = {
    "window",			/* name */
    FreeWindowInternalRep,	/* freeIntRepProc */
    DupWindowInternalRep,	/* dupIntRepProc */
    NULL,			/* updateStringProc */
    SetWindowFromAny		/* setFromAnyProc */
    NULL			/* setFromAnyProc */
};

/*
 *----------------------------------------------------------------------
 *
 * GetTypeCache --
 *
 *	Get (and build if necessary) the cache of useful Tcl object types for
 *	comparisons in the conversion functions.  This allows optimized checks
 *	for standard cases.
 *
 *----------------------------------------------------------------------
 */

static ThreadSpecificData *
GetTypeCache(void)
{
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    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;
	obj.bytes += 2;
	obj.bytes = (char *)"0";
	obj.length = 1;
	obj.typePtr = NULL;
	Tcl_GetLongFromObj(NULL, &obj, &obj.internalRep.longValue);
	tsdPtr->intTypePtr = obj.typePtr;
    }
    return tsdPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * 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"
 *
 * Results:
 *	The return value is a standard Tcl object result.
 *
 * Side effects:
 *	None
 *
 *----------------------------------------------------------------------
 */

int
TkGetIntForIndex(
    Tcl_Obj *indexObj,
    TkSizeT end,
    int lastOK,
    TkSizeT *indexPtr)
{
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    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 "??+??" */
	return TCL_ERROR;
    }
#if TCL_MAJOR_VERSION < 9
    if ((*indexPtr < -1) || (end < -1)) {
	return TCL_ERROR;
    }
#endif
    if ((*indexPtr + 1) > (end + 1)) {
	*indexPtr = end + 1;
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * GetPixelsFromObjEx --
 *
 *	Attempt to return a pixel value from the Tcl object "objPtr". If the
 *	object is not already a pixel value, an attempt will be made to
404
405
406
407
408
409
410
411
412


413
414
415
416
417
418
419
420
421
422

423
424
425
426
427
428
429
493
494
495
496
497
498
499


500
501
502
503
504
505
506
507
508
509
510

511
512
513
514
515
516
517
518







-
-
+
+









-
+







 *	internal rep.
 *
 *----------------------------------------------------------------------
 */

static void
DupPixelInternalRep(
    register Tcl_Obj *srcPtr,	/* Object with internal rep to copy. */
    register Tcl_Obj *copyPtr)	/* Object with internal rep to set. */
    Tcl_Obj *srcPtr,	/* Object with internal rep to copy. */
    Tcl_Obj *copyPtr)	/* Object with internal rep to set. */
{
    copyPtr->typePtr = srcPtr->typePtr;

    if (SIMPLE_PIXELREP(srcPtr)) {
	SET_SIMPLEPIXEL(copyPtr, GET_SIMPLEPIXEL(srcPtr));
    } else {
	PixelRep *oldPtr, *newPtr;

	oldPtr = GET_COMPLEXPIXEL(srcPtr);
	newPtr = ckalloc(sizeof(PixelRep));
	newPtr = (PixelRep *)ckalloc(sizeof(PixelRep));
	newPtr->value = oldPtr->value;
	newPtr->units = oldPtr->units;
	newPtr->tkwin = oldPtr->tkwin;
	newPtr->returnValue = oldPtr->returnValue;
	SET_COMPLEXPIXEL(copyPtr, newPtr);
    }
}
499
500
501
502
503
504
505
506

507
508
509
510
511
512
513
588
589
590
591
592
593
594

595
596
597
598
599
600
601
602







-
+








    objPtr->typePtr = &pixelObjType;

    i = (int) d;
    if ((units < 0) && (i == d)) {
	SET_SIMPLEPIXEL(objPtr, i);
    } else {
	PixelRep *pixelPtr = ckalloc(sizeof(PixelRep));
	PixelRep *pixelPtr = (PixelRep *)ckalloc(sizeof(PixelRep));

	pixelPtr->value = d;
	pixelPtr->units = units;
	pixelPtr->tkwin = NULL;
	pixelPtr->returnValue = i;
	SET_COMPLEXPIXEL(objPtr, pixelPtr);
    }
560
561
562
563
564
565
566
567

568
569
570
571
572
573
574
649
650
651
652
653
654
655

656
657
658
659
660
661
662
663







-
+







    if (objPtr->typePtr != &mmObjType) {
	result = SetMMFromAny(interp, objPtr);
	if (result != TCL_OK) {
	    return result;
	}
    }

    mmPtr = objPtr->internalRep.twoPtrValue.ptr1;
    mmPtr = (MMRep *)objPtr->internalRep.twoPtrValue.ptr1;
    if (mmPtr->tkwin != tkwin) {
	d = mmPtr->value;
	if (mmPtr->units == -1) {
	    d /= WidthOfScreen(Tk_Screen(tkwin));
	    d *= WidthMMOfScreen(Tk_Screen(tkwin));
	} else {
	    d *= bias[mmPtr->units];
624
625
626
627
628
629
630
631
632


633
634
635
636
637
638


639
640
641
642
643
644
645
713
714
715
716
717
718
719


720
721
722
723
724
725


726
727
728
729
730
731
732
733
734







-
-
+
+




-
-
+
+







 *	internal rep.
 *
 *----------------------------------------------------------------------
 */

static void
DupMMInternalRep(
    register Tcl_Obj *srcPtr,	/* Object with internal rep to copy. */
    register Tcl_Obj *copyPtr)	/* Object with internal rep to set. */
    Tcl_Obj *srcPtr,	/* Object with internal rep to copy. */
    Tcl_Obj *copyPtr)	/* Object with internal rep to set. */
{
    MMRep *oldPtr, *newPtr;

    copyPtr->typePtr = srcPtr->typePtr;
    oldPtr = srcPtr->internalRep.twoPtrValue.ptr1;
    newPtr = ckalloc(sizeof(MMRep));
    oldPtr = (MMRep *)srcPtr->internalRep.twoPtrValue.ptr1;
    newPtr = (MMRep *)ckalloc(sizeof(MMRep));
    newPtr->value = oldPtr->value;
    newPtr->units = oldPtr->units;
    newPtr->tkwin = oldPtr->tkwin;
    newPtr->returnValue = oldPtr->returnValue;
    copyPtr->internalRep.twoPtrValue.ptr1 = newPtr;
}

660
661
662
663
664
665
666
667

668
669
670
671

672
673

674
675
676
677
678
679
680
681
682

683
684
685
686
687
688
689
749
750
751
752
753
754
755

756
757
758
759

760
761

762
763
764
765
766
767
768
769
770

771
772
773
774
775
776
777
778







-
+



-
+

-
+








-
+







 *	double-to-string conversion.
 *
 *----------------------------------------------------------------------
 */

static void
UpdateStringOfMM(
    register Tcl_Obj *objPtr)   /* pixel obj with string rep to update. */
    Tcl_Obj *objPtr)   /* pixel obj with string rep to update. */
{
    MMRep *mmPtr;
    char buffer[TCL_DOUBLE_SPACE];
    size_t len;
    TkSizeT len;

    mmPtr = objPtr->internalRep.twoPtrValue.ptr1;
    mmPtr = (MMRep *)objPtr->internalRep.twoPtrValue.ptr1;
    /* assert( mmPtr->units == -1 && objPtr->bytes == NULL ); */
    if ((mmPtr->units != -1) || (objPtr->bytes != NULL)) {
	Tcl_Panic("UpdateStringOfMM: false precondition");
    }

    Tcl_PrintDouble(NULL, mmPtr->value, buffer);
    len = strlen(buffer);

    objPtr->bytes = ckalloc(len + 1);
    objPtr->bytes = (char *)ckalloc(len + 1);
    strcpy(objPtr->bytes, buffer);
    objPtr->length = len;
}

/*
 *----------------------------------------------------------------------
 *
783
784
785
786
787
788
789
790

791
792
793
794
795
796
797
872
873
874
875
876
877
878

879
880
881
882
883
884
885
886







-
+







    typePtr = objPtr->typePtr;
    if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
	typePtr->freeIntRepProc(objPtr);
    }

    objPtr->typePtr = &mmObjType;

    mmPtr = ckalloc(sizeof(MMRep));
    mmPtr = (MMRep *)ckalloc(sizeof(MMRep));
    mmPtr->value = d;
    mmPtr->units = units;
    mmPtr->tkwin = NULL;
    mmPtr->returnValue	= d;

    objPtr->internalRep.twoPtrValue.ptr1 = mmPtr;

823
824
825
826
827
828
829
830

831
832
833
834
835
836
837
838
839

840
841
842
843
844
845
846
912
913
914
915
916
917
918

919
920
921
922
923
924
925
926
927

928
929
930
931
932
933
934
935







-
+








-
+







TkGetWindowFromObj(
    Tcl_Interp *interp, 	/* Used for error reporting if not NULL. */
    Tk_Window tkwin,		/* A token to get the main window from. */
    Tcl_Obj *objPtr,		/* The object from which to get window. */
    Tk_Window *windowPtr)	/* Place to store resulting window. */
{
    TkMainInfo *mainPtr = ((TkWindow *) tkwin)->mainPtr;
    register WindowRep *winPtr;
    WindowRep *winPtr;

    if (objPtr->typePtr != &windowObjType) {
	int result = SetWindowFromAny(interp, objPtr);
	if (result != TCL_OK) {
	    return result;
	}
    }

    winPtr = objPtr->internalRep.twoPtrValue.ptr1;
    winPtr = (WindowRep *)objPtr->internalRep.twoPtrValue.ptr1;
    if (winPtr->tkwin == NULL
	    || winPtr->mainPtr == NULL
	    || winPtr->mainPtr != mainPtr
	    || winPtr->epoch != mainPtr->deletionEpoch) {
	/*
	 * Cache is invalid.
	 */
878
879
880
881
882
883
884
885
886


887
888
889
890
891
892
893
894
895
896
897
898
899
900
901

902
903
904
905
906
907
908
967
968
969
970
971
972
973


974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989

990
991
992
993
994
995
996
997







-
-
+
+














-
+







 * 	TkGetWindowFromObj, which initializes the WindowRep cache.
 *
 *----------------------------------------------------------------------
 */

static int
SetWindowFromAny(
    Tcl_Interp *interp,		/* Used for error reporting if not NULL. */
    register Tcl_Obj *objPtr)	/* The object to convert. */
    TCL_UNUSED(Tcl_Interp *),
    Tcl_Obj *objPtr)	/* The object to convert. */
{
    const Tcl_ObjType *typePtr;
    WindowRep *winPtr;

    /*
     * Free the old internalRep before setting the new one.
     */

    Tcl_GetString(objPtr);
    typePtr = objPtr->typePtr;
    if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
	typePtr->freeIntRepProc(objPtr);
    }

    winPtr = ckalloc(sizeof(WindowRep));
    winPtr = (WindowRep *)ckalloc(sizeof(WindowRep));
    winPtr->tkwin = NULL;
    winPtr->mainPtr = NULL;
    winPtr->epoch = 0;

    objPtr->internalRep.twoPtrValue.ptr1 = winPtr;
    objPtr->typePtr = &windowObjType;

925
926
927
928
929
930
931
932
933


934
935

936
937
938


939
940
941
942
943
944
945
1014
1015
1016
1017
1018
1019
1020


1021
1022
1023

1024
1025


1026
1027
1028
1029
1030
1031
1032
1033
1034







-
-
+
+

-
+

-
-
+
+







 *	internal rep.
 *
 *----------------------------------------------------------------------
 */

static void
DupWindowInternalRep(
    register Tcl_Obj *srcPtr,
    register Tcl_Obj *copyPtr)
    Tcl_Obj *srcPtr,
    Tcl_Obj *copyPtr)
{
    register WindowRep *oldPtr, *newPtr;
    WindowRep *oldPtr, *newPtr;

    oldPtr = srcPtr->internalRep.twoPtrValue.ptr1;
    newPtr = ckalloc(sizeof(WindowRep));
    oldPtr = (WindowRep *)srcPtr->internalRep.twoPtrValue.ptr1;
    newPtr = (WindowRep *)ckalloc(sizeof(WindowRep));
    newPtr->tkwin = oldPtr->tkwin;
    newPtr->mainPtr = oldPtr->mainPtr;
    newPtr->epoch = oldPtr->epoch;
    copyPtr->internalRep.twoPtrValue.ptr1 = newPtr;
    copyPtr->typePtr = srcPtr->typePtr;
}

969
970
971
972
973
974
975
976

977
978
979
980
981
982
983
984
985
986
987
988
989
990
991

992
993
994
995
996

997
998
999
1000

1001
1002
1003
1004
1005
1006
1007
1058
1059
1060
1061
1062
1063
1064

1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079

1080
1081
1082
1083
1084

1085
1086
1087
1088

1089
1090
1091
1092
1093
1094
1095
1096







-
+














-
+




-
+



-
+







    objPtr->internalRep.twoPtrValue.ptr1 = NULL;
    objPtr->typePtr = NULL;
}

/*
 *----------------------------------------------------------------------
 *
 * TkNewWindowObj --
 * Tk_NewWindowObj --
 *
 *	This function allocates a new Tcl_Obj that refers to a particular to a
 *	particular Tk window.
 *
 * Results:
 *	A standard Tcl object reference, with refcount 0.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

Tcl_Obj *
TkNewWindowObj(
Tk_NewWindowObj(
    Tk_Window tkwin)
{
    Tcl_Obj *objPtr = Tcl_NewStringObj(Tk_PathName(tkwin), -1);
    TkMainInfo *mainPtr = ((TkWindow *) tkwin)->mainPtr;
    register WindowRep *winPtr;
    WindowRep *winPtr;

    SetWindowFromAny(NULL, objPtr);

    winPtr = objPtr->internalRep.twoPtrValue.ptr1;
    winPtr = (WindowRep *)objPtr->internalRep.twoPtrValue.ptr1;
    winPtr->tkwin = tkwin;
    winPtr->mainPtr = mainPtr;
    winPtr->epoch = mainPtr->deletionEpoch;
    return objPtr;
}

/*
Changes to generic/tkOldConfig.c.
1
2
3
4
5
6
7
8
9


10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27




28
29
30
31
32
33
34

35
36
37
38
39

40
41

42
43
44
45
46
47
48
1
2
3
4
5
6
7


8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

38
39
40
41
42

43
44

45
46
47
48
49
50
51
52







-
-
+
+


















+
+
+
+






-
+




-
+

-
+







/*
 * tkOldConfig.c --
 *
 *	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.
 */

#include "tkInt.h"

/*
 * Values for "flags" field of Tk_ConfigSpec structures. Be sure to coordinate
 * these values with those defined in tk.h (TK_CONFIG_COLOR_ONLY, etc.) There
 * must not be overlap!
 *
 * INIT -		Non-zero means (char *) things have been converted to
 *			Tk_Uid's.
 */

#define INIT		0x20

#ifndef TK_CONFIG_OPTION_SPECIFIED
#  define TK_CONFIG_OPTION_SPECIFIED      (1 << 4)
#endif

/*
 * Forward declarations for functions defined later in this file:
 */

static int		DoConfig(Tcl_Interp *interp, Tk_Window tkwin,
			    Tk_ConfigSpec *specPtr, Tk_Uid value,
			    int valueIsUid, char *widgRec);
			    int valueIsUid, void *widgRec);
static Tk_ConfigSpec *	FindConfigSpec(Tcl_Interp *interp,
			    Tk_ConfigSpec *specs, const char *argvName,
			    int needFlags, int hateFlags);
static char *		FormatConfigInfo(Tcl_Interp *interp, Tk_Window tkwin,
			    const Tk_ConfigSpec *specPtr, char *widgRec);
			    const Tk_ConfigSpec *specPtr, void *widgRec);
static const char *	FormatConfigValue(Tcl_Interp *interp, Tk_Window tkwin,
			    const Tk_ConfigSpec *specPtr, char *widgRec,
			    const Tk_ConfigSpec *specPtr, void *widgRec,
			    char *buffer, Tcl_FreeProc **freeProcPtr);
static Tk_ConfigSpec *	GetCachedSpecs(Tcl_Interp *interp,
			    const Tk_ConfigSpec *staticSpecs);
static void		DeleteSpecCacheTable(ClientData clientData,
			    Tcl_Interp *interp);

/*
78
79
80
81
82
83
84
85

86
87
88
89
90
91
92
82
83
84
85
86
87
88

89
90
91
92
93
94
95
96







-
+







    char *widgRec,		/* Record whose fields are to be modified.
				 * Values must be properly initialized. */
    int flags)			/* Used to specify additional flags that must
				 * be present in config specs for them to be
				 * considered. Also, may have
				 * TK_CONFIG_ARGV_ONLY set. */
{
    register Tk_ConfigSpec *specPtr, *staticSpecs;
    Tk_ConfigSpec *specPtr, *staticSpecs;
    Tk_Uid value;		/* Value of option from database. */
    int needFlags;		/* Specs must contain this set of flags or
				 * else they are not considered. */
    int hateFlags;		/* If a spec contains any bits here, it's not
				 * considered. */

    if (tkwin == NULL) {
241
242
243
244
245
246
247
248
249


250
251
252
253
254
255
256
245
246
247
248
249
250
251


252
253
254
255
256
257
258
259
260







-
-
+
+







    const char *argvName,	/* Name (suitable for use in a "config"
				 * command) identifying particular option. */
    int needFlags,		/* Flags that must be present in matching
				 * entry. */
    int hateFlags)		/* Flags that must NOT be present in matching
				 * entry. */
{
    register Tk_ConfigSpec *specPtr;
    register char c;		/* First character of current argument. */
    Tk_ConfigSpec *specPtr;
    char c;		/* First character of current argument. */
    Tk_ConfigSpec *matchPtr;	/* Matching spec, or NULL. */
    size_t length;

    c = argvName[1];
    length = strlen(argvName);
    matchPtr = NULL;
    for (specPtr = specs; specPtr->type != TK_CONFIG_END; specPtr++) {
336
337
338
339
340
341
342
343

344
345
346

347
348
349
350
351
352
353
354
355
356

357
358
359
360
361
362
363
340
341
342
343
344
345
346

347
348
349

350
351
352
353
354
355
356
357
358
359

360
361
362
363
364
365
366
367







-
+


-
+









-
+







    Tcl_Interp *interp,		/* Interpreter for error reporting. */
    Tk_Window tkwin,		/* Window containing widget (needed to set up
				 * X resources). */
    Tk_ConfigSpec *specPtr,	/* Specifier to apply. */
    Tk_Uid value,		/* Value to use to fill in widgRec. */
    int valueIsUid,		/* Non-zero means value is a Tk_Uid; zero
				 * means it's an ordinary string. */
    char *widgRec)		/* Record whose fields are to be modified.
    void *widgRec)		/* Record whose fields are to be modified.
				 * Values must be properly initialized. */
{
    char *ptr;
    void *ptr;
    Tk_Uid uid;
    int nullValue;

    nullValue = 0;
    if ((*value == 0) && (specPtr->specFlags & TK_CONFIG_NULL_OK)) {
	nullValue = 1;
    }

    do {
	ptr = widgRec + specPtr->offset;
	ptr = (char *)widgRec + specPtr->offset;
	switch (specPtr->type) {
	case TK_CONFIG_BOOLEAN:
	    if (Tcl_GetBoolean(interp, value, (int *) ptr) != TCL_OK) {
		return TCL_ERROR;
	    }
	    break;
	case TK_CONFIG_INT:
372
373
374
375
376
377
378
379

380
381
382
383
384
385
386
376
377
378
379
380
381
382

383
384
385
386
387
388
389
390







-
+







	    break;
	case TK_CONFIG_STRING: {
	    char *oldStr, *newStr;

	    if (nullValue) {
		newStr = NULL;
	    } else {
		newStr = ckalloc(strlen(value) + 1);
		newStr = (char *)ckalloc(strlen(value) + 1);
		strcpy(newStr, value);
	    }
	    oldStr = *((char **) ptr);
	    if (oldStr != NULL) {
		ckfree(oldStr);
	    }
	    *((char **) ptr) = newStr;
542
543
544
545
546
547
548
549

550
551
552
553
554
555
556
546
547
548
549
550
551
552

553
554
555
556
557
558
559
560







-
+







		}
	    }
	    *((Tk_Window *) ptr) = tkwin2;
	    break;
	}
	case TK_CONFIG_CUSTOM:
	    if (specPtr->customPtr->parseProc(specPtr->customPtr->clientData,
		    interp, tkwin, value, widgRec, specPtr->offset)!=TCL_OK) {
		    interp, tkwin, value, (char *)widgRec, specPtr->offset)!=TCL_OK) {
		return TCL_ERROR;
	    }
	    break;
	default:
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "bad config table: unknown type %d", specPtr->type));
	    Tcl_SetErrorCode(interp, "TK", "BAD_CONFIG", NULL);
599
600
601
602
603
604
605
606

607
608
609
610
611
612
613
603
604
605
606
607
608
609

610
611
612
613
614
615
616
617







-
+







    const char *argvName,	/* If non-NULL, indicates a single option
				 * whose info is to be returned. Otherwise
				 * info is returned for all options. */
    int flags)			/* Used to specify additional flags that must
				 * be present in config specs for them to be
				 * considered. */
{
    register Tk_ConfigSpec *specPtr, *staticSpecs;
    Tk_ConfigSpec *specPtr, *staticSpecs;
    int needFlags, hateFlags;
    char *list;
    const char *leader = "{";

    needFlags = flags & ~(TK_CONFIG_USER_BIT - 1);
    if (Tk_Depth(tkwin) <= 1) {
	hateFlags = TK_CONFIG_COLOR_ONLY;
682
683
684
685
686
687
688
689

690
691
692

693
694
695
696
697
698
699
686
687
688
689
690
691
692

693
694
695

696
697
698
699
700
701
702
703







-
+


-
+







 */

static char *
FormatConfigInfo(
    Tcl_Interp *interp,		/* Interpreter to use for things like
				 * floating-point precision. */
    Tk_Window tkwin,		/* Window corresponding to widget. */
    register const Tk_ConfigSpec *specPtr,
    const Tk_ConfigSpec *specPtr,
				/* Pointer to information describing
				 * option. */
    char *widgRec)		/* Pointer to record holding current values of
    void *widgRec)		/* Pointer to record holding current values of
				 * info for widget. */
{
    const char *argv[6];
    char *result;
    char buffer[200];
    Tcl_FreeProc *freeProc = NULL;

751
752
753
754
755
756
757
758

759
760
761
762
763
764
765

766

767
768
769

770
771
772
773

774
775
776
777
778
779
780

781
782
783
784

785
786
787
788

789
790
791
792
793
794

795
796
797
798
799
800
801
802

803
804
805
806
807
808
809
810

811
812
813
814
815
816
817
818

819
820
821
822
823
824
825
826

827
828
829
830
831
832
833
834

835
836
837
838

839
840
841
842
843
844
845
846

847
848
849

850
851
852

853
854
855

856
857
858

859
860
861
862

863
864
865
866
867
868

869
870
871
872
873
874
875
876

877
878
879
880
881
882
883
755
756
757
758
759
760
761

762
763
764
765
766
767
768
769
770

771
772
773

774
775
776
777

778
779
780
781
782
783
784

785
786
787
788

789
790
791
792

793
794
795
796
797
798

799
800
801
802
803
804
805
806

807
808
809
810
811
812
813
814

815
816
817
818
819
820
821
822

823
824
825
826
827
828
829
830

831
832
833
834
835
836
837
838

839
840
841
842

843
844
845
846
847
848
849
850

851
852
853

854
855
856

857
858
859

860
861
862

863
864
865
866

867
868
869
870



871
872
873
874
875
876
877
878

879
880
881
882
883
884
885
886







-
+







+
-
+


-
+



-
+






-
+



-
+



-
+





-
+







-
+







-
+







-
+







-
+







-
+



-
+







-
+


-
+


-
+


-
+


-
+



-
+



-
-
-
+







-
+








static const char *
FormatConfigValue(
    Tcl_Interp *interp,		/* Interpreter for use in real conversions. */
    Tk_Window tkwin,		/* Window corresponding to widget. */
    const Tk_ConfigSpec *specPtr, /* Pointer to information describing option.
				 * Must not point to a synonym option. */
    char *widgRec,		/* Pointer to record holding current values of
    void *widgRec,		/* Pointer to record holding current values of
				 * info for widget. */
    char *buffer,		/* Static buffer to use for small values.
				 * Must have at least 200 bytes of storage. */
    Tcl_FreeProc **freeProcPtr)	/* Pointer to word to fill in with address of
				 * function to free the result, or NULL if
				 * result is static. */
{
    void *ptr;
    const char *ptr, *result;
    const char *result;

    *freeProcPtr = NULL;
    ptr = widgRec + specPtr->offset;
    ptr = (char *)widgRec + specPtr->offset;
    result = "";
    switch (specPtr->type) {
    case TK_CONFIG_BOOLEAN:
	if (*((int *) ptr) == 0) {
	if (*((int *)ptr) == 0) {
	    result = "0";
	} else {
	    result = "1";
	}
	break;
    case TK_CONFIG_INT:
	sprintf(buffer, "%d", *((int *) ptr));
	sprintf(buffer, "%d", *((int *)ptr));
	result = buffer;
	break;
    case TK_CONFIG_DOUBLE:
	Tcl_PrintDouble(interp, *((double *) ptr), buffer);
	Tcl_PrintDouble(interp, *((double *)ptr), buffer);
	result = buffer;
	break;
    case TK_CONFIG_STRING:
	result = (*(char **) ptr);
	result = (*(char **)ptr);
	if (result == NULL) {
	    result = "";
	}
	break;
    case TK_CONFIG_UID: {
	Tk_Uid uid = *((Tk_Uid *) ptr);
	Tk_Uid uid = *((Tk_Uid *)ptr);

	if (uid != NULL) {
	    result = uid;
	}
	break;
    }
    case TK_CONFIG_COLOR: {
	XColor *colorPtr = *((XColor **) ptr);
	XColor *colorPtr = *((XColor **)ptr);

	if (colorPtr != NULL) {
	    result = Tk_NameOfColor(colorPtr);
	}
	break;
    }
    case TK_CONFIG_FONT: {
	Tk_Font tkfont = *((Tk_Font *) ptr);
	Tk_Font tkfont = *((Tk_Font *)ptr);

	if (tkfont != NULL) {
	    result = Tk_NameOfFont(tkfont);
	}
	break;
    }
    case TK_CONFIG_BITMAP: {
	Pixmap pixmap = *((Pixmap *) ptr);
	Pixmap pixmap = *((Pixmap *)ptr);

	if (pixmap != None) {
	    result = Tk_NameOfBitmap(Tk_Display(tkwin), pixmap);
	}
	break;
    }
    case TK_CONFIG_BORDER: {
	Tk_3DBorder border = *((Tk_3DBorder *) ptr);
	Tk_3DBorder border = *((Tk_3DBorder *)ptr);

	if (border != NULL) {
	    result = Tk_NameOf3DBorder(border);
	}
	break;
    }
    case TK_CONFIG_RELIEF:
	result = Tk_NameOfRelief(*((int *) ptr));
	result = Tk_NameOfRelief(*((int *)ptr));
	break;
    case TK_CONFIG_CURSOR:
    case TK_CONFIG_ACTIVE_CURSOR: {
	Tk_Cursor cursor = *((Tk_Cursor *) ptr);
	Tk_Cursor cursor = *((Tk_Cursor *)ptr);

	if (cursor != NULL) {
	    result = Tk_NameOfCursor(Tk_Display(tkwin), cursor);
	}
	break;
    }
    case TK_CONFIG_JUSTIFY:
	result = Tk_NameOfJustify(*((Tk_Justify *) ptr));
	result = Tk_NameOfJustify(*((Tk_Justify *)ptr));
	break;
    case TK_CONFIG_ANCHOR:
	result = Tk_NameOfAnchor(*((Tk_Anchor *) ptr));
	result = Tk_NameOfAnchor(*((Tk_Anchor *)ptr));
	break;
    case TK_CONFIG_CAP_STYLE:
	result = Tk_NameOfCapStyle(*((int *) ptr));
	result = Tk_NameOfCapStyle(*((int *)ptr));
	break;
    case TK_CONFIG_JOIN_STYLE:
	result = Tk_NameOfJoinStyle(*((int *) ptr));
	result = Tk_NameOfJoinStyle(*((int *)ptr));
	break;
    case TK_CONFIG_PIXELS:
	sprintf(buffer, "%d", *((int *) ptr));
	sprintf(buffer, "%d", *((int *)ptr));
	result = buffer;
	break;
    case TK_CONFIG_MM:
	Tcl_PrintDouble(interp, *((double *) ptr), buffer);
	Tcl_PrintDouble(interp, *((double *)ptr), buffer);
	result = buffer;
	break;
    case TK_CONFIG_WINDOW: {
	Tk_Window tkwin;

	tkwin = *((Tk_Window *) ptr);
	tkwin = *((Tk_Window *)ptr);
	if (tkwin != NULL) {
	    result = Tk_PathName(tkwin);
	}
	break;
    }
    case TK_CONFIG_CUSTOM:
	result = specPtr->customPtr->printProc(specPtr->customPtr->clientData,
		tkwin, widgRec, specPtr->offset, freeProcPtr);
		tkwin, (char *)widgRec, specPtr->offset, freeProcPtr);
	break;
    default:
	result = "?? unknown type ??";
    }
    return result;
}

967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986

987
988
989
990
991
992
993
970
971
972
973
974
975
976

977
978
979
980
981
982
983
984
985
986
987

988
989
990
991
992
993
994
995







-











-
+







 * Notes:
 *	Since this is not looking anything up, this uses the static version of
 *	the config specs.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
void
Tk_FreeOptions(
    const Tk_ConfigSpec *specs,	/* Describes legal options. */
    char *widgRec,		/* Record whose fields contain current values
				 * for options. */
    Display *display,		/* X display; needed for freeing some
				 * resources. */
    int needFlags)		/* Used to specify additional flags that must
				 * be present in config specs for them to be
				 * considered. */
{
    register const Tk_ConfigSpec *specPtr;
    const Tk_ConfigSpec *specPtr;
    char *ptr;

    for (specPtr = specs; specPtr->type != TK_CONFIG_END; specPtr++) {
	if ((specPtr->specFlags & needFlags) != needFlags) {
	    continue;
	}
	ptr = widgRec + specPtr->offset;
1067
1068
1069
1070
1071
1072
1073
1074

1075
1076
1077

1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091

1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107

1108
1109
1110

1111
1112
1113
1114
1115
1116
1117
1069
1070
1071
1072
1073
1074
1075

1076
1077
1078

1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092

1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108

1109
1110
1111

1112
1113
1114
1115
1116
1117
1118
1119







-
+


-
+













-
+















-
+


-
+








    /*
     * Get (or allocate if it doesn't exist) the hash table that the writable
     * copies of the widget specs are stored in. In effect, this is
     * self-initializing code.
     */

    specCacheTablePtr =
    specCacheTablePtr = (Tcl_HashTable *)
	    Tcl_GetAssocData(interp, "tkConfigSpec.threadTable", NULL);
    if (specCacheTablePtr == NULL) {
	specCacheTablePtr = ckalloc(sizeof(Tcl_HashTable));
	specCacheTablePtr = (Tcl_HashTable *)ckalloc(sizeof(Tcl_HashTable));
	Tcl_InitHashTable(specCacheTablePtr, TCL_ONE_WORD_KEYS);
	Tcl_SetAssocData(interp, "tkConfigSpec.threadTable",
		DeleteSpecCacheTable, specCacheTablePtr);
    }

    /*
     * Look up or create the hash entry that the constant specs are mapped to,
     * which will have the writable specs as its associated value.
     */

    entryPtr = Tcl_CreateHashEntry(specCacheTablePtr, (char *) staticSpecs,
	    &isNew);
    if (isNew) {
	unsigned int entrySpace = sizeof(Tk_ConfigSpec);
	size_t entrySpace = sizeof(Tk_ConfigSpec);
	const Tk_ConfigSpec *staticSpecPtr;
	Tk_ConfigSpec *specPtr;

	/*
	 * OK, no working copy in this interpreter so copy. Need to work out
	 * how much space to allocate first.
	 */

	for (staticSpecPtr=staticSpecs; staticSpecPtr->type!=TK_CONFIG_END;
		staticSpecPtr++) {
	    entrySpace += sizeof(Tk_ConfigSpec);
	}

	/*
	 * Now allocate our working copy's space and copy over the contents
	 * from the master copy.
	 * from the origin.
	 */

	cachedSpecs = ckalloc(entrySpace);
	cachedSpecs = (Tk_ConfigSpec *)ckalloc(entrySpace);
	memcpy(cachedSpecs, staticSpecs, entrySpace);
	Tcl_SetHashValue(entryPtr, cachedSpecs);

	/*
	 * Finally, go through and replace database names, database classes
	 * and default values with Tk_Uids. This is the bit that has to be
	 * per-thread.
1127
1128
1129
1130
1131
1132
1133
1134

1135
1136
1137
1138
1139
1140
1141
1129
1130
1131
1132
1133
1134
1135

1136
1137
1138
1139
1140
1141
1142
1143







-
+







		}
		if (specPtr->defValue != NULL) {
		    specPtr->defValue = Tk_GetUid(specPtr->defValue);
		}
	    }
	}
    } else {
	cachedSpecs = Tcl_GetHashValue(entryPtr);
	cachedSpecs = (Tk_ConfigSpec *)Tcl_GetHashValue(entryPtr);
    }

    return cachedSpecs;
}

/*
 *--------------------------------------------------------------
1153
1154
1155
1156
1157
1158
1159
1160

1161
1162

1163
1164
1165
1166
1167
1168
1169
1155
1156
1157
1158
1159
1160
1161

1162
1163

1164
1165
1166
1167
1168
1169
1170
1171







-
+

-
+







 *
 *--------------------------------------------------------------
 */

static void
DeleteSpecCacheTable(
    ClientData clientData,
    Tcl_Interp *interp)
    TCL_UNUSED(Tcl_Interp *))
{
    Tcl_HashTable *tablePtr = clientData;
    Tcl_HashTable *tablePtr = (Tcl_HashTable *)clientData;
    Tcl_HashEntry *entryPtr;
    Tcl_HashSearch search;

    for (entryPtr = Tcl_FirstHashEntry(tablePtr,&search); entryPtr != NULL;
	    entryPtr = Tcl_NextHashEntry(&search)) {
	/*
	 * Someone else deallocates the Tk_Uids themselves.
Changes to generic/tkOldTest.c.
1
2
3
4
5
6
7
8
9
10
11



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

27
28

29
30
31
32


33
34
35
36
37
38

39
40
41
42
43
44
45
46

47
48
49
50
51
52
53
54
55
56
57

58
59
60
61
62
63
64
1
2
3
4
5
6
7
8



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

29
30
31


32
33
34
35
36
37
38

39
40
41
42
43
44
45
46

47
48
49
50
51
52
53
54
55
56
57

58
59
60
61
62
63
64
65








-
-
-
+
+
+















+

-
+


-
-
+
+





-
+







-
+










-
+







/*
 * tkOldTest.c --
 *
 *	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.
 */

#define USE_OLD_IMAGE
#ifndef USE_TCL_STUBS
#   define USE_TCL_STUBS
#endif
#ifndef USE_TK_STUBS
#   define USE_TK_STUBS
#endif
#include "tkInt.h"

#if !defined(TK_NO_DEPRECATED) && (TCL_MAJOR_VERSION < 9)
/*
 * The following data structure represents the master for a test image:
 * The following data structure represents the model for a test image:
 */

typedef struct TImageMaster {
    Tk_ImageMaster master;      /* Tk's token for image master. */
typedef struct TImageModel {
    Tk_ImageModel model;        /* Tk's token for image model. */
    Tcl_Interp *interp;         /* Interpreter for application. */
    int width, height;          /* Dimensions of image. */
    char *imageName;            /* Name of image (malloc-ed). */
    char *varName;              /* Name of variable in which to log events for
                                 * image (malloc-ed). */
} TImageMaster;
} TImageModel;

/*
 * The following data structure represents a particular use of a particular
 * test image.
 */

typedef struct TImageInstance {
    TImageMaster *masterPtr;    /* Pointer to master for image. */
    TImageModel *modelPtr;    /* Pointer to model for image. */
    XColor *fg;                 /* Foreground color for drawing in image. */
    GC gc;                      /* Graphics context for drawing in image. */
} TImageInstance;

/*
 * The type record for test images:
 */

static int		ImageCreate(Tcl_Interp *interp,
			    char *name, int argc, char **argv,
			    Tk_ImageType *typePtr, Tk_ImageMaster master,
			    Tk_ImageType *typePtr, Tk_ImageModel model,
			    ClientData *clientDataPtr);
static ClientData	ImageGet(Tk_Window tkwin, ClientData clientData);
static void		ImageDisplay(ClientData clientData,
			    Display *display, Drawable drawable,
			    int imageX, int imageY, int width,
			    int height, int drawableX,
			    int drawableY);
80
81
82
83
84
85
86
87

88
89
90
91
92
93
94
81
82
83
84
85
86
87

88
89
90
91
92
93
94
95







-
+







/*
 * Forward declarations for functions defined later in this file:
 */

static int              ImageObjCmd(ClientData dummy,
                            Tcl_Interp *interp, int objc,
            			    Tcl_Obj * const objv[]);

#endif

/*
 *----------------------------------------------------------------------
 *
 * TkOldTestInit --
 *
 *	This function performs initialization for the Tk test suite
102
103
104
105
106
107
108
109

110
111

112
113
114

115

116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135

136
137
138
139
140
141
142
143
144
145
146

147
148
149
150
151

152
153

154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171


172
173
174
175

176
177

178
179
180
181

182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210

211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231

232
233
234
235
236
237
238
103
104
105
106
107
108
109

110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138

139

140
141
142
143
144
145
146
147
148

149
150
151
152
153

154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173


174
175
176
177
178

179
180

181
182
183
184

185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205

206
207
208
209
210
211
212

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233

234
235
236
237
238
239
240
241







-
+


+



+

+



















-
+
-









-
+




-
+


+
















-
-
+
+



-
+

-
+



-
+




















-







-
+




















-
+







 *	Creates several test commands.
 *
 *----------------------------------------------------------------------
 */

int
TkOldTestInit(
    Tcl_Interp *interp)
    Tcl_Interp *dummy)
{
    static int initialized = 0;
    (void)dummy;

    if (!initialized) {
	initialized = 1;
#if !defined(TK_NO_DEPRECATED) && (TCL_MAJOR_VERSION < 9)
	Tk_CreateImageType(&imageType);
#endif
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * ImageCreate --
 *
 *	This function is called by the Tk image code to create "oldtest" images.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	The data structure for a new image is allocated.
 *
 *----------------------------------------------------------------------
 */

#if !defined(TK_NO_DEPRECATED) && (TCL_MAJOR_VERSION < 9)
	/* ARGSUSED */
static int
ImageCreate(
    Tcl_Interp *interp,		/* Interpreter for application containing
				 * image. */
    char *name,			/* Name to use for image. */
    int argc,			/* Number of arguments. */
    char **argv,		/* Argument strings for options (doesn't
				 * include image name or type). */
    Tk_ImageType *typePtr,	/* Pointer to our type record (not used). */
    Tk_ImageMaster master,	/* Token for image, to be used by us in later
    Tk_ImageModel model,	/* Token for image, to be used by us in later
				 * callbacks. */
    ClientData *clientDataPtr)	/* Store manager's token for image here; it
				 * will be returned in later callbacks. */
{
    TImageMaster *timPtr;
    TImageModel *timPtr;
    const char *varName;
    int i;
    (void)typePtr;

    varName = "log";
    for (i = 0; i < argc; i += 2) {
	if (strcmp(argv[i], "-variable") != 0) {
	    Tcl_AppendResult(interp, "bad option name \"",
		    argv[i], "\"", NULL);
	    return TCL_ERROR;
	}
	if ((i+1) == argc) {
	    Tcl_AppendResult(interp, "no value given for \"",
		    argv[i], "\" option", NULL);
	    return TCL_ERROR;
	}
	varName = argv[i+1];
    }

    timPtr = ckalloc(sizeof(TImageMaster));
    timPtr->master = master;
    timPtr = (TImageModel *)ckalloc(sizeof(TImageModel));
    timPtr->model = model;
    timPtr->interp = interp;
    timPtr->width = 30;
    timPtr->height = 15;
    timPtr->imageName = ckalloc(strlen(name) + 1);
    timPtr->imageName = (char *)ckalloc(strlen(name) + 1);
    strcpy(timPtr->imageName, name);
    timPtr->varName = ckalloc(strlen(varName) + 1);
    timPtr->varName = (char *)ckalloc(strlen(varName) + 1);
    strcpy(timPtr->varName, varName);
    Tcl_CreateObjCommand(interp, name, ImageObjCmd, timPtr, NULL);
    *clientDataPtr = timPtr;
    Tk_ImageChanged(master, 0, 0, 30, 15, 30, 15);
    Tk_ImageChanged(model, 0, 0, 30, 15, 30, 15);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * ImageObjCmd --
 *
 *	This function implements the commands corresponding to individual
 *	images.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	Forces windows to be created.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
ImageObjCmd(
    ClientData clientData,	/* Main window for application. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])		/* Argument strings. */
{
    TImageMaster *timPtr = clientData;
    TImageModel *timPtr = (TImageModel *)clientData;
    int x, y, width, height;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
	return TCL_ERROR;
    }
    if (strcmp(Tcl_GetString(objv[1]), "changed") == 0) {
	if (objc != 8) {
	    Tcl_WrongNumArgs(interp, 1, objv, "changed x y width height"
		    " imageWidth imageHeight");
	    return TCL_ERROR;
	}
	if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK)
		|| (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)
		|| (Tcl_GetIntFromObj(interp, objv[4], &width) != TCL_OK)
		|| (Tcl_GetIntFromObj(interp, objv[5], &height) != TCL_OK)
		|| (Tcl_GetIntFromObj(interp, objv[6], &timPtr->width) != TCL_OK)
		|| (Tcl_GetIntFromObj(interp, objv[7], &timPtr->height) != TCL_OK)) {
	    return TCL_ERROR;
	}
	Tk_ImageChanged(timPtr->master, x, y, width, height, timPtr->width,
	Tk_ImageChanged(timPtr->model, x, y, width, height, timPtr->width,
		timPtr->height);
    } else {
	Tcl_AppendResult(interp, "bad option \"", Tcl_GetString(objv[1]),
		"\": must be changed", NULL);
	return TCL_ERROR;
    }
    return TCL_OK;
256
257
258
259
260
261
262
263

264
265

266
267
268
269
270
271
272
273
274
275


276
277
278
279
280
281
282
259
260
261
262
263
264
265

266
267

268
269
270
271
272
273
274
275
276


277
278
279
280
281
282
283
284
285







-
+

-
+








-
-
+
+







 *----------------------------------------------------------------------
 */

static ClientData
ImageGet(
    Tk_Window tkwin,		/* Token for window in which image will be
				 * used. */
    ClientData clientData)	/* Pointer to TImageMaster for image. */
    ClientData clientData)	/* Pointer to TImageModel for image. */
{
    TImageMaster *timPtr = clientData;
    TImageModel *timPtr = (TImageModel *)clientData;
    TImageInstance *instPtr;
    char buffer[100];
    XGCValues gcValues;

    sprintf(buffer, "%s get", timPtr->imageName);
    Tcl_SetVar2(timPtr->interp, timPtr->varName, NULL, buffer,
	    TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT);

    instPtr = ckalloc(sizeof(TImageInstance));
    instPtr->masterPtr = timPtr;
    instPtr = (TImageInstance *)ckalloc(sizeof(TImageInstance));
    instPtr->modelPtr = timPtr;
    instPtr->fg = Tk_GetColor(timPtr->interp, tkwin, "#ff0000");
    gcValues.foreground = instPtr->fg->pixel;
    instPtr->gc = Tk_GetGC(tkwin, GCForeground, &gcValues);
    return instPtr;
}

/*
305
306
307
308
309
310
311
312

313
314
315
316

317
318

319
320
321


322
323
324


325
326
327
328
329
330
331
308
309
310
311
312
313
314

315
316
317
318

319
320

321
322


323
324
325


326
327
328
329
330
331
332
333
334







-
+



-
+

-
+

-
-
+
+

-
-
+
+







    int imageX, int imageY,	/* Origin of area to redraw, relative to
				 * origin of image. */
    int width, int height,	/* Dimensions of area to redraw. */
    int drawableX, int drawableY)
				/* Coordinates in drawable corresponding to
				 * imageX and imageY. */
{
    TImageInstance *instPtr = clientData;
    TImageInstance *instPtr = (TImageInstance *)clientData;
    char buffer[200 + TCL_INTEGER_SPACE * 6];

    sprintf(buffer, "%s display %d %d %d %d %d %d",
	    instPtr->masterPtr->imageName, imageX, imageY, width, height,
	    instPtr->modelPtr->imageName, imageX, imageY, width, height,
	    drawableX, drawableY);
    Tcl_SetVar2(instPtr->masterPtr->interp, instPtr->masterPtr->varName, NULL,
    Tcl_SetVar2(instPtr->modelPtr->interp, instPtr->modelPtr->varName, NULL,
	    buffer, TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT);
    if (width > (instPtr->masterPtr->width - imageX)) {
	width = instPtr->masterPtr->width - imageX;
    if (width > (instPtr->modelPtr->width - imageX)) {
	width = instPtr->modelPtr->width - imageX;
    }
    if (height > (instPtr->masterPtr->height - imageY)) {
	height = instPtr->masterPtr->height - imageY;
    if (height > (instPtr->modelPtr->height - imageY)) {
	height = instPtr->modelPtr->height - imageY;
    }
    XDrawRectangle(display, drawable, instPtr->gc, drawableX, drawableY,
	    (unsigned) (width-1), (unsigned) (height-1));
    XDrawLine(display, drawable, instPtr->gc, drawableX, drawableY,
	    (int) (drawableX + width - 1), (int) (drawableY + height - 1));
    XDrawLine(display, drawable, instPtr->gc, drawableX,
	    (int) (drawableY + height - 1),
350
351
352
353
354
355
356
357

358
359
360
361


362
363
364
365
366
367
368
353
354
355
356
357
358
359

360
361
362


363
364
365
366
367
368
369
370
371







-
+


-
-
+
+







 */

static void
ImageFree(
    ClientData clientData,	/* Pointer to TImageInstance for instance. */
    Display *display)		/* Display where image was to be drawn. */
{
    TImageInstance *instPtr = clientData;
    TImageInstance *instPtr = (TImageInstance *)clientData;
    char buffer[200];

    sprintf(buffer, "%s free", instPtr->masterPtr->imageName);
    Tcl_SetVar2(instPtr->masterPtr->interp, instPtr->masterPtr->varName, NULL,
    sprintf(buffer, "%s free", instPtr->modelPtr->imageName);
    Tcl_SetVar2(instPtr->modelPtr->interp, instPtr->modelPtr->varName, NULL,
	    buffer, TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT);
    Tk_FreeColor(instPtr->fg);
    Tk_FreeGC(display, instPtr->gc);
    ckfree(instPtr);
}

/*
380
381
382
383
384
385
386
387

388
389
390
391

392
393
394
395
396
397
398
399
400
401
402

403
404
405
406
407
408
409
410
383
384
385
386
387
388
389

390
391
392
393

394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414







-
+



-
+











+








 *	Information about the image is deleted.
 *
 *----------------------------------------------------------------------
 */

static void
ImageDelete(
    ClientData clientData)	/* Pointer to TImageMaster for image. When
    ClientData clientData)	/* Pointer to TImageModel for image. When
				 * this function is called, no more instances
				 * exist. */
{
    TImageMaster *timPtr = clientData;
    TImageModel *timPtr = (TImageModel *)clientData;
    char buffer[100];

    sprintf(buffer, "%s delete", timPtr->imageName);
    Tcl_SetVar2(timPtr->interp, timPtr->varName, NULL, buffer,
	    TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT);

    Tcl_DeleteCommand(timPtr->interp, timPtr->imageName);
    ckfree(timPtr->imageName);
    ckfree(timPtr->varName);
    ckfree(timPtr);
}
#endif

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Changes to generic/tkOption.c.
1
2
3
4
5
6
7
8
9


10
11
12
13
14
15
16
1
2
3
4
5
6
7


8
9
10
11
12
13
14
15
16







-
-
+
+







/*
 * tkOption.c --
 *
 *	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.
 */

#include "tkInt.h"

250
251
252
253
254
255
256
257
258


259
260

261
262
263

264
265
266

267
268
269
270
271
272
273
250
251
252
253
254
255
256


257
258
259

260
261
262

263
264
265

266
267
268
269
270
271
272
273







-
-
+
+

-
+


-
+


-
+







    const char *value,		/* String value for option. */
    int priority)		/* Overall priority level to use for this
				 * option, such as TK_USER_DEFAULT_PRIO or
				 * TK_INTERACTIVE_PRIO. Must be between 0 and
				 * TK_MAX_PRIO. */
{
    TkWindow *winPtr = ((TkWindow *) tkwin)->mainPtr->winPtr;
    register ElArray **arrayPtrPtr;
    register Element *elPtr;
    ElArray **arrayPtrPtr;
    Element *elPtr;
    Element newEl;
    register const char *p;
    const char *p;
    const char *field;
    int count, firstField;
    ptrdiff_t length;
    size_t length;
#define TMP_SIZE 100
    char tmp[TMP_SIZE+1];
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (winPtr->mainPtr->optionRootPtr == NULL) {
	OptionInit(winPtr->mainPtr);
    }
    tsdPtr->cachedWindow = NULL;/* Invalidate the cache. */

307
308
309
310
311
312
313
314

315
316
317
318
319
320
321
307
308
309
310
311
312
313

314
315
316
317
318
319
320
321







-
+







	while ((*p != 0) && (*p != '.') && (*p != '*')) {
	    p++;
	}
	length = p - field;
	if (length > TMP_SIZE) {
	    length = TMP_SIZE;
	}
	strncpy(tmp, field, (size_t) length);
	strncpy(tmp, field, length);
	tmp[length] = 0;
	newEl.nameUid = Tk_GetUid(tmp);
	if (isupper(UCHAR(*field))) {
	    newEl.flags |= CLASS;
	}

	if (*p != 0) {
403
404
405
406
407
408
409
410
411


412
413
414

415
416
417
418
419
420
421
403
404
405
406
407
408
409


410
411
412
413

414
415
416
417
418
419
420
421







-
-
+
+


-
+







    const char *name,		/* Name of option. */
    const char *className)	/* Class of option. NULL means there is no
				 * class for this option: just check for
				 * name. */
{
    Tk_Uid nameId, classId = NULL;
    const char *masqName;
    register Element *elPtr, *bestPtr;
    register int count;
    Element *elPtr, *bestPtr;
    int count;
    StackLevel *levelPtr;
    int stackDepth[NUM_STACKS];
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    /*
     * Note: no need to call OptionInit here: it will be done by the
     * SetupStacks call below (squeeze out those nanoseconds).
     */

517
518
519
520
521
522
523
524
525


526
527
528
529
530
531
532
533
534
535
536
537
538


539
540
541
542
543
544
545
517
518
519
520
521
522
523


524
525
526
527
528
529
530
531
532
533
534
535
536


537
538
539
540
541
542
543
544
545







-
-
+
+











-
-
+
+







     * option database is densely populated, or if the widget has many
     * masquerading options.
     */

    if (masqName != NULL) {
	char *masqClass;
	Tk_Uid nodeId, winClassId, winNameId;
	unsigned int classNameLength;
	register Element *nodePtr, *leafPtr;
	TkSizeT classNameLength;
	Element *nodePtr, *leafPtr;
	static const int searchOrder[] = {
	    EXACT_NODE_NAME, WILDCARD_NODE_NAME, EXACT_NODE_CLASS,
	    WILDCARD_NODE_CLASS, -1
	};
	const int *currentPtr;
	int currentStack, leafCount;

	/*
	 * Extract the masquerade class name from the name field.
	 */

	classNameLength	= (unsigned) (masqName - name);
	masqClass = ckalloc(classNameLength + 1);
	classNameLength	= masqName - name;
	masqClass = (char *)ckalloc(classNameLength + 1);
	strncpy(masqClass, name, classNameLength);
	masqClass[classNameLength] = '\0';

	winClassId = Tk_GetUid(masqClass);
	ckfree(masqClass);
	winNameId = ((TkWindow *) tkwin)->nameUid;

611
612
613
614
615
616
617
618

619
620

621
622
623
624
625
626
627
611
612
613
614
615
616
617

618
619

620
621
622
623
624
625
626
627







-
+

-
+







int
Tk_OptionObjCmd(
    ClientData clientData,	/* Main window associated with interpreter. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of Tcl_Obj arguments. */
    Tcl_Obj *const objv[])	/* Tcl_Obj arguments. */
{
    Tk_Window tkwin = clientData;
    Tk_Window tkwin = (Tk_Window)clientData;
    int index, result;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    static const char *const optionCmds[] = {
	"add", "clear", "get", "readfile", NULL
    };
    enum optionVals {
	OPTION_ADD, OPTION_CLEAR, OPTION_GET, OPTION_READFILE
    };
734
735
736
737
738
739
740
741

742
743

744
745
746
747
748
749
750
734
735
736
737
738
739
740

741
742

743
744
745
746
747
748
749
750







-
+

-
+







 *	Option-related resources are freed. See code below for details.
 *
 *--------------------------------------------------------------
 */

void
TkOptionDeadWindow(
    register TkWindow *winPtr)	/* Window to be cleaned up. */
    TkWindow *winPtr)	/* Window to be cleaned up. */
{
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    /*
     * If this window is in the option stacks, then clear the stacks.
     *
     * XXX: OptionThreadExitProc will be invoked before DeleteWindowsExitProc
     * XXX: if it is thread-specific (which it should be), invalidating the
792
793
794
795
796
797
798
799

800
801
802
803
804
805
806
792
793
794
795
796
797
798

799
800
801
802
803
804
805
806







-
+








void
TkOptionClassChanged(
    TkWindow *winPtr)		/* Window whose class changed. */
{
    int i, j, *basePtr;
    ElArray *arrayPtr;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (winPtr->optionLevel == -1) {
	return;
    }

    /*
918
919
920
921
922
923
924
925

926
927
928
929
930
931
932
918
919
920
921
922
923
924

925
926
927
928
929
930
931
932







-
+







				 * this window's main window. */
    char *string,		/* String containing option specifiers. */
    int priority)		/* Priority level to use for options in this
				 * string, such as TK_USER_DEFAULT_PRIO or
				 * TK_INTERACTIVE_PRIO. Must be between 0 and
				 * TK_MAX_PRIO. */
{
    register char *src, *dst;
    char *src, *dst;
    char *name, *value;
    int lineNum;

    src = string;
    lineNum = 1;
    while (1) {
	/*
1080
1081
1082
1083
1084
1085
1086
1087


1088
1089
1090
1091
1092
1093
1094
1080
1081
1082
1083
1084
1085
1086

1087
1088
1089
1090
1091
1092
1093
1094
1095







-
+
+







    int priority)		/* Priority level to use for options in this
				 * file, such as TK_USER_DEFAULT_PRIO or
				 * TK_INTERACTIVE_PRIO. Must be between 0 and
				 * TK_MAX_PRIO. */
{
    const char *realName;
    Tcl_Obj *buffer;
    int result, bufferSize;
    int result;
    TkSizeT bufferSize;
    Tcl_Channel chan;
    Tcl_DString newName;

    /*
     * Prevent file system access in a safe interpreter.
     */

1111
1112
1113
1114
1115
1116
1117
1118

1119
1120
1121
1122
1123
1124
1125
1112
1113
1114
1115
1116
1117
1118

1119
1120
1121
1122
1123
1124
1125
1126







-
+







	return TCL_ERROR;
    }

    buffer = Tcl_NewObj();
    Tcl_IncrRefCount(buffer);
    Tcl_SetChannelOption(NULL, chan, "-encoding", "utf-8");
    bufferSize = Tcl_ReadChars(chan, buffer, -1, 0);
    if (bufferSize < 0) {
    if (bufferSize == TCL_IO_FAILURE) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"error reading file \"%s\": %s",
		fileName, Tcl_PosixError(interp)));
	Tcl_Close(NULL, chan);
	return TCL_ERROR;
    }
    Tcl_Close(NULL, chan);
1145
1146
1147
1148
1149
1150
1151
1152

1153
1154
1155
1156
1157
1158
1159
1146
1147
1148
1149
1150
1151
1152

1153
1154
1155
1156
1157
1158
1159
1160







-
+







 *--------------------------------------------------------------
 */

static ElArray *
NewArray(
    int numEls)			/* How many elements of space to allocate. */
{
    register ElArray *arrayPtr = ckalloc(EL_ARRAY_SIZE(numEls));
    ElArray *arrayPtr = (ElArray *)ckalloc(EL_ARRAY_SIZE(numEls));

    arrayPtr->arraySize = numEls;
    arrayPtr->numUsed = 0;
    arrayPtr->nextToUse = arrayPtr->els;
    return arrayPtr;
}

1172
1173
1174
1175
1176
1177
1178
1179
1180


1181
1182
1183
1184
1185
1186
1187

1188
1189

1190
1191
1192
1193
1194
1195
1196
1173
1174
1175
1176
1177
1178
1179


1180
1181
1182
1183
1184
1185
1186
1187

1188
1189

1190
1191
1192
1193
1194
1195
1196
1197







-
-
+
+






-
+

-
+







 *	Memory may be allocated or freed.
 *
 *--------------------------------------------------------------
 */

static ElArray *
ExtendArray(
    register ElArray *arrayPtr,	/* Array to be extended. */
    register Element *elPtr)	/* Element to be copied into array. */
    ElArray *arrayPtr,	/* Array to be extended. */
    Element *elPtr)	/* Element to be copied into array. */
{
    /*
     * If the current array has filled up, make it bigger.
     */

    if (arrayPtr->numUsed >= arrayPtr->arraySize) {
	register int newSize = 2*arrayPtr->arraySize;
	int newSize = 2*arrayPtr->arraySize;

	arrayPtr = ckrealloc(arrayPtr, EL_ARRAY_SIZE(newSize));
	arrayPtr = (ElArray *)ckrealloc(arrayPtr, EL_ARRAY_SIZE(newSize));
	arrayPtr->arraySize = newSize;
	arrayPtr->nextToUse = &arrayPtr->els[arrayPtr->numUsed];
    }

    *arrayPtr->nextToUse = *elPtr;
    arrayPtr->nextToUse++;
    arrayPtr->numUsed++;
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230



1231
1232
1233
1234
1235
1236
1237
1222
1223
1224
1225
1226
1227
1228



1229
1230
1231
1232
1233
1234
1235
1236
1237
1238







-
-
-
+
+
+







				 * cached. */
    int leaf)			/* Non-zero means this is the leaf window
				 * being probed. Zero means this is an
				 * ancestor of the desired leaf. */
{
    int level, i;
    const int *iPtr;
    register StackLevel *levelPtr;
    register ElArray *arrayPtr;
    ThreadSpecificData *tsdPtr =
    StackLevel *levelPtr;
    ElArray *arrayPtr;
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    /*
     * The following array defines the order in which the current stacks are
     * searched to find matching entries to add to the stacks. Given the
     * current priority-based scheme, the order below is no longer relevant;
     * all that matters is that an element is on the list *somewhere*. The
1300
1301
1302
1303
1304
1305
1306
1307

1308
1309
1310
1311
1312
1313
1314
1301
1302
1303
1304
1305
1306
1307

1308
1309
1310
1311
1312
1313
1314
1315







-
+







    /*
     * Step 4: create a new stack level; grow the level array if we've run out
     * of levels. Clear the stacks for EXACT_LEAF_NAME and EXACT_LEAF_CLASS
     * (anything that was there is of no use any more).
     */

    if (tsdPtr->curLevel >= tsdPtr->numLevels) {
	StackLevel *newLevels =
	StackLevel *newLevels = (StackLevel *)
		ckalloc(tsdPtr->numLevels * 2 * sizeof(StackLevel));

	memcpy(newLevels, tsdPtr->levels,
		tsdPtr->numLevels * sizeof(StackLevel));
	ckfree(tsdPtr->levels);
	tsdPtr->numLevels *= 2;
	tsdPtr->levels = newLevels;
1327
1328
1329
1330
1331
1332
1333
1334

1335
1336
1337
1338
1339
1340
1341
1328
1329
1330
1331
1332
1333
1334

1335
1336
1337
1338
1339
1340
1341
1342







-
+








    /*
     * Step 5: scan the current stack level looking for matches to this
     * window's name or class; where found, add new information to the stacks.
     */

    for (iPtr = searchOrder; *iPtr != -1; iPtr++) {
	register Element *elPtr;
	Element *elPtr;
	int count;
	Tk_Uid id;

	i = *iPtr;
	if (i & CLASS) {
	    id = winPtr->classUid;
	} else {
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391



1392
1393
1394
1395
1396
1397
1398
1383
1384
1385
1386
1387
1388
1389



1390
1391
1392
1393
1394
1395
1396
1397
1398
1399







-
-
-
+
+
+








static void
ExtendStacks(
    ElArray *arrayPtr,		/* Array of elements to copy onto stacks. */
    int leaf)			/* If zero, then don't copy exact leaf
				 * elements. */
{
    register int count;
    register Element *elPtr;
    ThreadSpecificData *tsdPtr =
    int count;
    Element *elPtr;
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    for (elPtr = arrayPtr->els, count = arrayPtr->numUsed;
	    count > 0; elPtr++, count--) {
	if (!(elPtr->flags & (NODE|WILDCARD)) && !leaf) {
	    continue;
	}
1415
1416
1417
1418
1419
1420
1421
1422

1423
1424

1425
1426
1427
1428
1429
1430
1431
1416
1417
1418
1419
1420
1421
1422

1423
1424

1425
1426
1427
1428
1429
1430
1431
1432







-
+

-
+







 *	Option-related data structures get freed.
 *
 *--------------------------------------------------------------
 */

static void
OptionThreadExitProc(
    ClientData clientData)	/* not used */
    TCL_UNUSED(void *))
{
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (tsdPtr->initialized) {
	int i;

	for (i = 0; i < NUM_STACKS; i++) {
	    ckfree(tsdPtr->stacks[i]);
1449
1450
1451
1452
1453
1454
1455
1456

1457
1458
1459
1460
1461
1462

1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477

1478
1479
1480
1481
1482
1483
1484
1450
1451
1452
1453
1454
1455
1456

1457
1458
1459
1460
1461
1462

1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477

1478
1479
1480
1481
1482
1483
1484
1485







-
+





-
+














-
+







 *	Option-related data structures get initialized.
 *
 *--------------------------------------------------------------
 */

static void
OptionInit(
    register TkMainInfo *mainPtr)
    TkMainInfo *mainPtr)
				/* Top-level information about window that
				 * isn't initialized yet. */
{
    int i;
    Tcl_Interp *interp;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    Element *defaultMatchPtr = &tsdPtr->defaultMatch;

    /*
     * First, once-only initialization.
     */

    if (tsdPtr->initialized == 0) {
	tsdPtr->initialized = 1;
	tsdPtr->cachedWindow = NULL;
	tsdPtr->numLevels = 5;
	tsdPtr->curLevel = -1;
	tsdPtr->serial = 0;

	tsdPtr->levels = ckalloc(5 * sizeof(StackLevel));
	tsdPtr->levels = (StackLevel *)ckalloc(5 * sizeof(StackLevel));
	for (i = 0; i < NUM_STACKS; i++) {
	    tsdPtr->stacks[i] = NewArray(10);
	    tsdPtr->levels[0].bases[i] = 0;
	}

	defaultMatchPtr->nameUid = NULL;
	defaultMatchPtr->child.valueUid = NULL;
1517
1518
1519
1520
1521
1522
1523
1524

1525
1526
1527
1528
1529
1530
1531
1518
1519
1520
1521
1522
1523
1524

1525
1526
1527
1528
1529
1530
1531
1532







-
+







 */

static void
ClearOptionTree(
    ElArray *arrayPtr)		/* Array of options; delete everything
				 * referred to recursively by this. */
{
    register Element *elPtr;
    Element *elPtr;
    int count;

    for (count = arrayPtr->numUsed, elPtr = arrayPtr->els;  count > 0;
	    count--, elPtr++) {
	if (elPtr->flags & NODE) {
	    ClearOptionTree(elPtr->child.arrayPtr);
	}
Changes to generic/tkPack.c.
1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

24
25
26
27
28
29
30
31
32

33
34
35

36
37
38
39
40



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58

59
60
61
62
63
64

65
66
67
68
69
70
71
72
73

74
75
76
77
78
79
80
81

82
83
84
85
86
87

88
89
90
91



92
93
94
95
96
97
98
99
100

101
102
103
104
105
106
107

108
109
110
111
112
113

114
115
116
117
118
119
120
121

122
123
124

125
126


127
128
129
130
131


132
133
134
135
136
137
138
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

23
24
25
26
27
28
29
30
31

32
33
34

35
36
37



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

58
59
60
61
62
63

64
65
66
67
68
69
70
71
72

73
74
75
76
77
78
79
80

81
82
83
84
85
86

87
88



89
90
91
92
93
94
95
96
97
98
99

100
101
102
103
104
105
106

107
108
109
110
111
112

113
114
115
116
117
118
119
120

121
122
123
124
125
126

127
128
129
130
131


132
133
134
135
136
137
138
139
140






-
-
+
+














-
+








-
+


-
+


-
-
-
+
+
+

















-
+





-
+








-
+







-
+





-
+

-
-
-
+
+
+








-
+






-
+





-
+







-
+



+

-
+
+



-
-
+
+







/*
 * 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.
 */

#include "tkInt.h"

typedef enum {TOP, BOTTOM, LEFT, RIGHT} Side;
static const char *const sideNames[] = {
    "top", "bottom", "left", "right", NULL
};

/*
 * For each window that the packer cares about (either because the window is
 * managed by the packer or because the window has slaves that are managed by
 * managed by the packer or because the window has content that are managed by
 * the packer), there is a structure of the following type:
 */

typedef struct Packer {
    Tk_Window tkwin;		/* Tk token for window. NULL means that the
				 * window has been deleted, but the packet
				 * hasn't had a chance to clean up yet because
				 * the structure is still in use. */
    struct Packer *masterPtr;	/* Master window within which this window is
    struct Packer *containerPtr;	/* Container window within which this window is
				 * packed (NULL means this window isn't
				 * managed by the packer). */
    struct Packer *nextPtr;	/* Next window packed within same master. List
    struct Packer *nextPtr;	/* Next window packed within same container. List
				 * is priority-ordered: first on list gets
				 * packed first. */
    struct Packer *slavePtr;	/* First in list of slaves packed inside this
				 * window (NULL means no packed slaves). */
    Side side;			/* Side of master against which this window is
    struct Packer *contentPtr;	/* First in list of content packed inside this
				 * window (NULL means no packed content). */
    Side side;			/* Side of container against which this window is
				 * packed. */
    Tk_Anchor anchor;		/* If frame allocated for window is larger
				 * than window needs, this indicates how where
				 * to position window in frame. */
    int padX, padY;		/* Total additional pixels to leave around the
				 * window. Some is of this space is on each
				 * side. This is space *outside* the window:
				 * we'll allocate extra space in frame but
				 * won't enlarge window). */
    int padLeft, padTop;	/* The part of padX or padY to use on the left
				 * or top of the widget, respectively. By
				 * default, this is half of padX or padY. */
    int iPadX, iPadY;		/* Total extra pixels to allocate inside the
				 * window (half of this amount will appear on
				 * each side). */
    int doubleBw;		/* Twice the window's last known border width.
				 * If this changes, the window must be
				 * repacked within its master. */
				 * repacked within its container. */
    int *abortPtr;		/* If non-NULL, it means that there is a
				 * nested call to ArrangePacking already
				 * working on this window. *abortPtr may be
				 * set to 1 to abort that nested call. This
				 * happens, for example, if tkwin or any of
				 * its slaves is deleted. */
				 * its content is deleted. */
    int flags;			/* Miscellaneous flags; see below for
				 * definitions. */
} Packer;

/*
 * Flag values for Packer structures:
 *
 * REQUESTED_REPACK:		1 means a Tcl_DoWhenIdle request has already
 *				been made to repack all the slaves of this
 *				been made to repack all the content of this
 *				window.
 * FILLX:			1 means if frame allocated for window is wider
 *				than window needs, expand window to fill
 *				frame. 0 means don't make window any larger
 *				than needed.
 * FILLY:			Same as FILLX, except for height.
 * EXPAND:			1 means this window's frame will absorb any
 *				extra space in the master window.
 *				extra space in the container window.
 * OLD_STYLE:			1 means this window is being managed with the
 *				old-style packer algorithms (before Tk version
 *				3.3). The main difference is that padding and
 *				filling are done differently.
 * DONT_PROPAGATE:		1 means don't set this window's requested
 *				size. 0 means if this window is a master then
 *				size. 0 means if this window is a container then
 *				Tk will set its requested size to fit the
 *				needs of its slaves.
 * ALLOCED_MASTER               1 means that Pack has allocated itself as
 *                              geometry master for this window.
 *				needs of its content.
 * ALLOCED_CONTAINER	1 means that Pack has allocated itself as
 *				geometry container for this window.
 */

#define REQUESTED_REPACK	1
#define FILLX			2
#define FILLY			4
#define EXPAND			8
#define OLD_STYLE		16
#define DONT_PROPAGATE		32
#define ALLOCED_MASTER		64
#define ALLOCED_CONTAINER	64

/*
 * The following structure is the official type record for the packer:
 */

static void		PackReqProc(ClientData clientData, Tk_Window tkwin);
static void		PackLostSlaveProc(ClientData clientData,
static void		PackLostContentProc(ClientData clientData,
			    Tk_Window tkwin);

static const Tk_GeomMgr packerType = {
    "pack",			/* name */
    PackReqProc,		/* requestProc */
    PackLostSlaveProc,		/* lostSlaveProc */
    PackLostContentProc,		/* lostContentProc */
};

/*
 * Forward declarations for functions defined later in this file:
 */

static void		ArrangePacking(ClientData clientData);
static int		ConfigureSlaves(Tcl_Interp *interp, Tk_Window tkwin,
static int		ConfigureContent(Tcl_Interp *interp, Tk_Window tkwin,
			    int objc, Tcl_Obj *const objv[]);
static void		DestroyPacker(void *memPtr);
static Packer *		GetPacker(Tk_Window tkwin);
#ifndef TK_NO_DEPRECATED
static int		PackAfter(Tcl_Interp *interp, Packer *prevPtr,
			    Packer *masterPtr, int objc,Tcl_Obj *const objv[]);
			    Packer *containerPtr, int objc,Tcl_Obj *const objv[]);
#endif /* !TK_NO_DEPRECATED */
static void		PackStructureProc(ClientData clientData,
			    XEvent *eventPtr);
static void		Unlink(Packer *packPtr);
static int		XExpansion(Packer *slavePtr, int cavityWidth);
static int		YExpansion(Packer *slavePtr, int cavityHeight);
static int		XExpansion(Packer *contentPtr, int cavityWidth);
static int		YExpansion(Packer *contentPtr, int cavityHeight);

/*
 *------------------------------------------------------------------------
 *
 * TkAppendPadAmount --
 *
 *	This function generates a text value that describes one of the -padx,
157
158
159
160
161
162
163
164

165
166
167


168
169
170
171
172
173
174
159
160
161
162
163
164
165

166
167


168
169
170
171
172
173
174
175
176







-
+

-
-
+
+







    int halfSpace,		/* The left or top padding amount */
    int allSpace)		/* The total amount of padding */
{
    Tcl_Obj *padding[2];

    if (halfSpace*2 == allSpace) {
	Tcl_DictObjPut(NULL, bufferObj, Tcl_NewStringObj(switchName, -1),
		Tcl_NewIntObj(halfSpace));
		Tcl_NewWideIntObj(halfSpace));
    } else {
	padding[0] = Tcl_NewIntObj(halfSpace);
	padding[1] = Tcl_NewIntObj(allSpace - halfSpace);
	padding[0] = Tcl_NewWideIntObj(halfSpace);
	padding[1] = Tcl_NewWideIntObj(allSpace - halfSpace);
	Tcl_DictObjPut(NULL, bufferObj, Tcl_NewStringObj(switchName, -1),
		Tcl_NewListObj(2, padding));
    }
}

/*
 *------------------------------------------------------------------------
190
191
192
193
194
195
196
197

198
199
200

201

202



203

204

205

206
207
208
209
210
211
212

213
214
215
216
217
218
219
220

221
222
223
224
225
226
227
228
229

230
231
232
233
234
235

236
237
238
239
240
241
242
243
244

245
246
247
248
249
250

251
252
253
254


255
256
257
258
259
260
261


262
263
264
265
266
267

268
269
270
271


272
273
274
275
276
277
278

279
280
281
282
283
284
285


286
287
288
289
290
291
292
293
294
295
296
297
298

299

300
301
302
303
304
305
306
307

308
309
310


311
312
313
314

315
316
317
318
319
320
321
322






323
324
325


326
327
328
329
330
331
332


333
334
335
336
337
338
339

340
341
342
343


344
345
346
347
348
349
350
351
352

353
354

355
356
357


358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378




379
380

381
382
383
384
385
386


387
388
389
390
391
392
393

394
395
396

397
398
399

400
401
402
403
404
405
406
407

408
409
410
411


412
413
414

415
416

417
418
419
420


421
422
423
424


425
426
427
428



429
430
431
432
433



434
435

436
437
438
439
440
441




442
443
444
445
446
447
448

449
450
451
452
453
454



455
456

457
458
459
460

461
462
463
464
465
466
467
468
469
470
471
472
473

474
475

476
477

478
479
480
481
482
483

484
485
486
487
488
489
490
192
193
194
195
196
197
198

199
200
201

202
203
204

205
206
207
208
209
210
211

212
213
214
215
216
217
218

219
220
221
222
223
224
225
226

227
228
229
230
231
232
233
234


235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250

251
252
253
254
255
256

257
258
259


260
261
262
263
264
265
266


267
268
269
270
271
272
273

274
275
276


277
278
279
280
281
282
283
284

285
286
287
288
289
290


291
292
293
294
295
296
297
298
299
300
301
302
303
304

305
306
307
308
309
310
311
312
313
314

315
316


317
318
319
320
321

322
323
324






325
326
327
328
329
330
331


332
333
334
335
336
337
338


339
340
341
342
343
344
345
346

347
348
349


350
351
352
353
354
355
356
357
358
359

360
361

362
363


364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382




383
384
385
386
387

388
389
390
391
392


393
394
395
396
397
398
399
400

401
402
403

404
405
406

407
408
409
410
411
412
413
414

415
416
417


418
419
420
421

422
423

424
425
426


427
428
429
430


431
432
433



434
435
436
437
438



439
440
441
442

443
444
445
446



447
448
449
450
451
452
453
454
455
456

457
458
459
460



461
462
463
464

465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482

483
484

485
486

487
488
489
490
491
492
493
494
495
496
497
498
499
500
501







-
+


-
+

+
-
+
+
+

+

+
-
+






-
+







-
+







-
-
+






+








-
+





-
+


-
-
+
+





-
-
+
+





-
+


-
-
+
+






-
+





-
-
+
+












-
+

+







-
+

-
-
+
+



-
+


-
-
-
-
-
-
+
+
+
+
+
+

-
-
+
+





-
-
+
+






-
+


-
-
+
+








-
+

-
+

-
-
+
+

















-
-
-
-
+
+
+
+

-
+




-
-
+
+






-
+


-
+


-
+







-
+


-
-
+
+


-
+

-
+


-
-
+
+


-
-
+
+

-
-
-
+
+
+


-
-
-
+
+
+

-
+



-
-
-
+
+
+
+






-
+



-
-
-
+
+
+

-
+




+












-
+

-
+

-
+






+







int
Tk_PackObjCmd(
    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;
    const char *argv2;
    static const char *const optionStrings[] = {
	/* after, append, before and unpack are deprecated */
#ifndef TK_NO_DEPRECATED
	"after", "append", "before", "unpack",
#endif /* !TK_NO_DEPRECATED */
	"configure", "forget", "info", "propagate", "slaves", NULL };
	"configure", "content", "forget", "info", "propagate", "slaves", NULL };
    static const char *const optionStringsNoDep[] = {
	"configure", "content", "forget", "info", "propagate", NULL };
    enum options {
#ifndef TK_NO_DEPRECATED
	PACK_AFTER, PACK_APPEND, PACK_BEFORE, PACK_UNPACK,
#endif /* !TK_NO_DEPRECATED */
	PACK_CONFIGURE, PACK_FORGET, PACK_INFO, PACK_PROPAGATE, PACK_SLAVES };
	PACK_CONFIGURE, PACK_CONTENT, PACK_FORGET, PACK_INFO, PACK_PROPAGATE, PACK_SLAVES };
    int index;

    if (objc >= 2) {
	const char *string = Tcl_GetString(objv[1]);

	if (string[0] == '.') {
	    return ConfigureSlaves(interp, tkwin, objc-1, objv+1);
	    return ConfigureContent(interp, tkwin, objc-1, objv+1);
	}
    }
    if (objc < 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?");
	return TCL_ERROR;
    }

    if (Tcl_GetIndexFromObjStruct(interp, objv[1], optionStrings,
    if (Tcl_GetIndexFromObjStruct(NULL, objv[1], optionStrings,
	    sizeof(char *), "option", 0, &index) != TCL_OK) {
	/*
	 * Call it again without the deprecated ones to get a proper error
	 * message. This works well since there can't be any ambiguity between
	 * deprecated and new options.
	 */

	Tcl_ResetResult(interp);
	Tcl_GetIndexFromObjStruct(interp, objv[1], &optionStrings[4],
	Tcl_GetIndexFromObjStruct(interp, objv[1], optionStringsNoDep,
		sizeof(char *), "option", 0, &index);
	return TCL_ERROR;
    }

    argv2 = Tcl_GetString(objv[2]);
    switch ((enum options) index) {
#ifndef TK_NO_DEPRECATED
    case PACK_AFTER: {
	Packer *prevPtr;
	Tk_Window tkwin2;

	if (TkGetWindowFromObj(interp, tkwin, objv[2], &tkwin2) != TCL_OK) {
	    return TCL_ERROR;
	}
	prevPtr = GetPacker(tkwin2);
	if (prevPtr->masterPtr == NULL) {
	if (prevPtr->containerPtr == NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "window \"%s\" isn't packed", argv2));
	    Tcl_SetErrorCode(interp, "TK", "PACK", "NOT_PACKED", NULL);
	    return TCL_ERROR;
	}
	return PackAfter(interp, prevPtr, prevPtr->masterPtr, objc-3, objv+3);
	return PackAfter(interp, prevPtr, prevPtr->containerPtr, objc-3, objv+3);
    }
    case PACK_APPEND: {
	Packer *masterPtr;
	register Packer *prevPtr;
	Packer *containerPtr;
	Packer *prevPtr;
	Tk_Window tkwin2;

	if (TkGetWindowFromObj(interp, tkwin, objv[2], &tkwin2) != TCL_OK) {
	    return TCL_ERROR;
	}
	masterPtr = GetPacker(tkwin2);
	prevPtr = masterPtr->slavePtr;
	containerPtr = GetPacker(tkwin2);
	prevPtr = containerPtr->contentPtr;
	if (prevPtr != NULL) {
	    while (prevPtr->nextPtr != NULL) {
		prevPtr = prevPtr->nextPtr;
	    }
	}
	return PackAfter(interp, prevPtr, masterPtr, objc-3, objv+3);
	return PackAfter(interp, prevPtr, containerPtr, objc-3, objv+3);
    }
    case PACK_BEFORE: {
	Packer *packPtr, *masterPtr;
	register Packer *prevPtr;
	Packer *packPtr, *containerPtr;
	Packer *prevPtr;
	Tk_Window tkwin2;

	if (TkGetWindowFromObj(interp, tkwin, objv[2], &tkwin2) != TCL_OK) {
	    return TCL_ERROR;
	}
	packPtr = GetPacker(tkwin2);
	if (packPtr->masterPtr == NULL) {
	if (packPtr->containerPtr == NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "window \"%s\" isn't packed", argv2));
	    Tcl_SetErrorCode(interp, "TK", "PACK", "NOT_PACKED", NULL);
	    return TCL_ERROR;
	}
	masterPtr = packPtr->masterPtr;
	prevPtr = masterPtr->slavePtr;
	containerPtr = packPtr->containerPtr;
	prevPtr = containerPtr->contentPtr;
	if (prevPtr == packPtr) {
	    prevPtr = NULL;
	} else {
	    for ( ; ; prevPtr = prevPtr->nextPtr) {
		if (prevPtr == NULL) {
		    Tcl_Panic("\"pack before\" couldn't find predecessor");
		}
		if (prevPtr->nextPtr == packPtr) {
		    break;
		}
	    }
	}
	return PackAfter(interp, prevPtr, masterPtr, objc-3, objv+3);
	return PackAfter(interp, prevPtr, containerPtr, objc-3, objv+3);
    }
#endif /* !TK_NO_DEPRECATED */
    case PACK_CONFIGURE:
	if (argv2[0] != '.') {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "bad argument \"%s\": must be name of window", argv2));
	    Tcl_SetErrorCode(interp, "TK", "VALUE", "WINDOW_PATH", NULL);
	    return TCL_ERROR;
	}
	return ConfigureSlaves(interp, tkwin, objc-2, objv+2);
	return ConfigureContent(interp, tkwin, objc-2, objv+2);
    case PACK_FORGET: {
	Tk_Window slave;
	Packer *slavePtr;
	Tk_Window content;
	Packer *contentPtr;
	int i;

	for (i = 2; i < objc; i++) {
	    if (TkGetWindowFromObj(interp, tkwin, objv[i], &slave) != TCL_OK) {
	    if (TkGetWindowFromObj(interp, tkwin, objv[i], &content) != TCL_OK) {
		continue;
	    }
	    slavePtr = GetPacker(slave);
	    if ((slavePtr != NULL) && (slavePtr->masterPtr != NULL)) {
		Tk_ManageGeometry(slave, NULL, NULL);
		if (slavePtr->masterPtr->tkwin != Tk_Parent(slavePtr->tkwin)) {
		    Tk_UnmaintainGeometry(slavePtr->tkwin,
			    slavePtr->masterPtr->tkwin);
	    contentPtr = GetPacker(content);
	    if ((contentPtr != NULL) && (contentPtr->containerPtr != NULL)) {
		Tk_ManageGeometry(content, NULL, NULL);
		if (contentPtr->containerPtr->tkwin != Tk_Parent(contentPtr->tkwin)) {
		    Tk_UnmaintainGeometry(contentPtr->tkwin,
			    contentPtr->containerPtr->tkwin);
		}
		Unlink(slavePtr);
		Tk_UnmapWindow(slavePtr->tkwin);
		Unlink(contentPtr);
		Tk_UnmapWindow(contentPtr->tkwin);
	    }
	}
	break;
    }
    case PACK_INFO: {
	register Packer *slavePtr;
	Tk_Window slave;
	Packer *contentPtr;
	Tk_Window content;
	Tcl_Obj *infoObj;

	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "window");
	    return TCL_ERROR;
	}
	if (TkGetWindowFromObj(interp, tkwin, objv[2], &slave) != TCL_OK) {
	if (TkGetWindowFromObj(interp, tkwin, objv[2], &content) != TCL_OK) {
	    return TCL_ERROR;
	}
	slavePtr = GetPacker(slave);
	if (slavePtr->masterPtr == NULL) {
	contentPtr = GetPacker(content);
	if (contentPtr->containerPtr == NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "window \"%s\" isn't packed", argv2));
	    Tcl_SetErrorCode(interp, "TK", "PACK", "NOT_PACKED", NULL);
	    return TCL_ERROR;
	}

	infoObj = Tcl_NewObj();
	Tcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj("-in", -1),
		TkNewWindowObj(slavePtr->masterPtr->tkwin));
		Tk_NewWindowObj(contentPtr->containerPtr->tkwin));
	Tcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj("-anchor", -1),
		Tcl_NewStringObj(Tk_NameOfAnchor(slavePtr->anchor), -1));
		Tcl_NewStringObj(Tk_NameOfAnchor(contentPtr->anchor), -1));
	Tcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj("-expand", -1),
		Tcl_NewBooleanObj(slavePtr->flags & EXPAND));
	switch (slavePtr->flags & (FILLX|FILLY)) {
		Tcl_NewBooleanObj(contentPtr->flags & EXPAND));
	switch (contentPtr->flags & (FILLX|FILLY)) {
	case 0:
	    Tcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj("-fill", -1),
		    Tcl_NewStringObj("none", -1));
	    break;
	case FILLX:
	    Tcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj("-fill", -1),
		    Tcl_NewStringObj("x", -1));
	    break;
	case FILLY:
	    Tcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj("-fill", -1),
		    Tcl_NewStringObj("y", -1));
	    break;
	case FILLX|FILLY:
	    Tcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj("-fill", -1),
		    Tcl_NewStringObj("both", -1));
	    break;
	}
	TkAppendPadAmount(infoObj, "-ipadx", slavePtr->iPadX/2, slavePtr->iPadX);
	TkAppendPadAmount(infoObj, "-ipady", slavePtr->iPadY/2, slavePtr->iPadY);
	TkAppendPadAmount(infoObj, "-padx", slavePtr->padLeft,slavePtr->padX);
	TkAppendPadAmount(infoObj, "-pady", slavePtr->padTop, slavePtr->padY);
	TkAppendPadAmount(infoObj, "-ipadx", contentPtr->iPadX/2, contentPtr->iPadX);
	TkAppendPadAmount(infoObj, "-ipady", contentPtr->iPadY/2, contentPtr->iPadY);
	TkAppendPadAmount(infoObj, "-padx", contentPtr->padLeft,contentPtr->padX);
	TkAppendPadAmount(infoObj, "-pady", contentPtr->padTop, contentPtr->padY);
	Tcl_DictObjPut(NULL, infoObj, Tcl_NewStringObj("-side", -1),
		Tcl_NewStringObj(sideNames[slavePtr->side], -1));
		Tcl_NewStringObj(sideNames[contentPtr->side], -1));
	Tcl_SetObjResult(interp, infoObj);
	break;
    }
    case PACK_PROPAGATE: {
	Tk_Window master;
	Packer *masterPtr;
	Tk_Window container;
	Packer *containerPtr;
	int propagate;

	if (objc > 4) {
	    Tcl_WrongNumArgs(interp, 2, objv, "window ?boolean?");
	    return TCL_ERROR;
	}
	if (TkGetWindowFromObj(interp, tkwin, objv[2], &master) != TCL_OK) {
	if (TkGetWindowFromObj(interp, tkwin, objv[2], &container) != TCL_OK) {
	    return TCL_ERROR;
	}
	masterPtr = GetPacker(master);
	containerPtr = GetPacker(container);
	if (objc == 3) {
	    Tcl_SetObjResult(interp,
		    Tcl_NewBooleanObj(!(masterPtr->flags & DONT_PROPAGATE)));
		    Tcl_NewBooleanObj(!(containerPtr->flags & DONT_PROPAGATE)));
	    return TCL_OK;
	}
	if (Tcl_GetBooleanFromObj(interp, objv[3], &propagate) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (propagate) {
	    /*
	     * If we have slaves, we need to register as geometry master.
	     * If we have content windows, we need to register as geometry container.
	     */

	    if (masterPtr->slavePtr != NULL) {
		if (TkSetGeometryMaster(interp, master, "pack") != TCL_OK) {
	    if (containerPtr->contentPtr != NULL) {
		if (TkSetGeometryContainer(interp, container, "pack") != TCL_OK) {
		    return TCL_ERROR;
		}
		masterPtr->flags |= ALLOCED_MASTER;
		containerPtr->flags |= ALLOCED_CONTAINER;
	    }
	    masterPtr->flags &= ~DONT_PROPAGATE;
	    containerPtr->flags &= ~DONT_PROPAGATE;

	    /*
	     * Repack the master to allow new geometry information to
	     * propagate upwards to the master's master.
	     * Repack the container to allow new geometry information to
	     * propagate upwards to the container's container.
	     */

	    if (masterPtr->abortPtr != NULL) {
		*masterPtr->abortPtr = 1;
	    if (containerPtr->abortPtr != NULL) {
		*containerPtr->abortPtr = 1;
	    }
	    if (!(masterPtr->flags & REQUESTED_REPACK)) {
		masterPtr->flags |= REQUESTED_REPACK;
		Tcl_DoWhenIdle(ArrangePacking, masterPtr);
	    if (!(containerPtr->flags & REQUESTED_REPACK)) {
		containerPtr->flags |= REQUESTED_REPACK;
		Tcl_DoWhenIdle(ArrangePacking, containerPtr);
	    }
	} else {
	    if (masterPtr->flags & ALLOCED_MASTER) {
		TkFreeGeometryMaster(master, "pack");
		masterPtr->flags &= ~ALLOCED_MASTER;
	    if (containerPtr->flags & ALLOCED_CONTAINER) {
		TkFreeGeometryContainer(container, "pack");
		containerPtr->flags &= ~ALLOCED_CONTAINER;
	    }
	    masterPtr->flags |= DONT_PROPAGATE;
	    containerPtr->flags |= DONT_PROPAGATE;
	}
	break;
    }
    case PACK_SLAVES: {
	Tk_Window master;
	Packer *masterPtr, *slavePtr;
    case PACK_SLAVES:
    case PACK_CONTENT: {
	Tk_Window container;
	Packer *containerPtr, *contentPtr;
	Tcl_Obj *resultObj;

	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "window");
	    return TCL_ERROR;
	}
	if (TkGetWindowFromObj(interp, tkwin, objv[2], &master) != TCL_OK) {
	if (TkGetWindowFromObj(interp, tkwin, objv[2], &container) != TCL_OK) {
	    return TCL_ERROR;
	}
	resultObj = Tcl_NewObj();
	masterPtr = GetPacker(master);
	for (slavePtr = masterPtr->slavePtr; slavePtr != NULL;
		slavePtr = slavePtr->nextPtr) {
	containerPtr = GetPacker(container);
	for (contentPtr = containerPtr->contentPtr; contentPtr != NULL;
		contentPtr = contentPtr->nextPtr) {
	    Tcl_ListObjAppendElement(NULL, resultObj,
		    TkNewWindowObj(slavePtr->tkwin));
		    Tk_NewWindowObj(contentPtr->tkwin));
	}
	Tcl_SetObjResult(interp, resultObj);
	break;
    }
#ifndef TK_NO_DEPRECATED
    case PACK_UNPACK: {
	Tk_Window tkwin2;
	Packer *packPtr;

	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "window");
	    return TCL_ERROR;
	}
	if (TkGetWindowFromObj(interp, tkwin, objv[2], &tkwin2) != TCL_OK) {
	    return TCL_ERROR;
	}
	packPtr = GetPacker(tkwin2);
	if ((packPtr != NULL) && (packPtr->masterPtr != NULL)) {
	if ((packPtr != NULL) && (packPtr->containerPtr != NULL)) {
	    Tk_ManageGeometry(tkwin2, NULL, NULL);
	    if (packPtr->masterPtr->tkwin != Tk_Parent(packPtr->tkwin)) {
	    if (packPtr->containerPtr->tkwin != Tk_Parent(packPtr->tkwin)) {
		Tk_UnmaintainGeometry(packPtr->tkwin,
			packPtr->masterPtr->tkwin);
			packPtr->containerPtr->tkwin);
	    }
	    Unlink(packPtr);
	    Tk_UnmapWindow(packPtr->tkwin);
	}
	break;
    }
#endif /* !TK_NO_DEPRECATED */
    }

    return TCL_OK;
}

/*
 *------------------------------------------------------------------------
500
501
502
503
504
505
506
507
508
509
510
511
512

513
514
515

516
517

518
519
520
521
522
523
524
525
526
527

528
529
530

531
532
533
534
535
536

537
538
539
540
541
542
543
544


545
546

547
548

549
550
551


552
553
554


555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571

572
573
574
575
576
577
578

579
580
581
582


583
584
585
586

587
588
589
590
591
592
593
594
595
596
597
598
599

600
601
602
603



604
605
606

607
608
609
610
611
612
613
614
615
616
617


618
619

620
621

622
623
624

625
626
627
628

629
630

631
632
633
634
635




636
637
638
639
640
641
642
643
644
645
646
647
648









649
650
651
652
653


654
655
656


657
658
659
660
661


662
663
664
665
666
667
668
669
670
671
672


673
674
675


676
677
678
679

680
681
682

683
684
685
686
687
688
689
690






691
692
693
694
695

696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713











714
715
716
717
718




719
720
721
722
723
724
725
726

727
728
729
730
731
732
733
734
735
736
737




738
739
740
741
742
743
744
745

746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762

763
764
765
766
767
768
769



770
771

772
773
774
775
776



777
778
779
780
781
782



783
784
785
786

787
788
789
790
791
792
793
511
512
513
514
515
516
517

518
519
520
521

522
523
524

525
526

527
528
529
530
531
532
533
534
535
536

537
538
539

540
541
542
543
544
545

546
547
548
549
550

551


552
553
554

555
556

557
558


559
560
561


562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579

580
581
582
583
584
585
586

587
588
589


590
591
592
593
594

595
596
597
598
599
600
601
602
603
604
605
606
607

608
609
610


611
612
613
614
615

616
617
618
619
620
621
622
623
624
625


626
627
628

629
630

631
632
633

634
635
636
637

638
639

640
641




642
643
644
645
646
647
648
649









650
651
652
653
654
655
656
657
658
659
660
661


662
663
664


665
666
667
668
669


670
671
672
673
674
675
676
677
678
679
680


681
682
683


684
685
686
687
688

689
690
691

692
693
694






695
696
697
698
699
700
701
702
703
704

705
706
707
708
709
710
711
712











713
714
715
716
717
718
719
720
721
722
723
724




725
726
727
728
729
730
731
732
733
734
735

736
737
738
739
740
741
742
743




744
745
746
747
748
749
750
751
752
753
754

755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771

772
773
774
775
776



777
778
779
780

781
782
783



784
785
786
787
788
789



790
791
792
793
794
795

796
797
798
799
800
801
802
803







-




-
+


-
+

-
+









-
+


-
+





-
+




-

-
-
+
+

-
+

-
+

-
-
+
+

-
-
+
+
















-
+






-
+


-
-
+
+



-
+












-
+


-
-
+
+
+


-
+









-
-
+
+

-
+

-
+


-
+



-
+

-
+

-
-
-
-
+
+
+
+




-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+



-
-
+
+

-
-
+
+



-
-
+
+









-
-
+
+

-
-
+
+



-
+


-
+


-
-
-
-
-
-
+
+
+
+
+
+




-
+







-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
+
+
+
+







-
+







-
-
-
-
+
+
+
+







-
+
















-
+




-
-
-
+
+
+

-
+


-
-
-
+
+
+



-
-
-
+
+
+



-
+







 * Side effects:
 *	Arranges for tkwin, and all its managed siblings, to be re-packed at
 *	the next idle point.
 *
 *------------------------------------------------------------------------
 */

	/* ARGSUSED */
static void
PackReqProc(
    ClientData clientData,	/* Packer's information about window that got
				 * new preferred geometry.  */
    Tk_Window tkwin)		/* Other Tk-related information about the
    TCL_UNUSED(Tk_Window))		/* Other Tk-related information about the
				 * window. */
{
    register Packer *packPtr = clientData;
    Packer *packPtr = (Packer *)clientData;

    packPtr = packPtr->masterPtr;
    packPtr = packPtr->containerPtr;
    if (!(packPtr->flags & REQUESTED_REPACK)) {
	packPtr->flags |= REQUESTED_REPACK;
	Tcl_DoWhenIdle(ArrangePacking, packPtr);
    }
}

/*
 *------------------------------------------------------------------------
 *
 * PackLostSlaveProc --
 * PackLostContentProc --
 *
 *	This function is invoked by Tk whenever some other geometry claims
 *	control over a slave that used to be managed by us.
 *	control over a content window that used to be managed by us.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Forgets all packer-related information about the slave.
 *	Forgets all packer-related information about the content.
 *
 *------------------------------------------------------------------------
 */

	/* ARGSUSED */
static void
PackLostSlaveProc(
    ClientData clientData,	/* Packer structure for slave window that was
PackLostContentProc(
    void *clientData,	/* Packer structure for content window that was
				 * stolen away. */
    Tk_Window tkwin)		/* Tk's handle for the slave window. */
    TCL_UNUSED(Tk_Window))		/* Tk's handle for the content window. */
{
    register Packer *slavePtr = clientData;
    Packer *contentPtr = (Packer *)clientData;

    if (slavePtr->masterPtr->tkwin != Tk_Parent(slavePtr->tkwin)) {
	Tk_UnmaintainGeometry(slavePtr->tkwin, slavePtr->masterPtr->tkwin);
    if (contentPtr->containerPtr->tkwin != Tk_Parent(contentPtr->tkwin)) {
	Tk_UnmaintainGeometry(contentPtr->tkwin, contentPtr->containerPtr->tkwin);
    }
    Unlink(slavePtr);
    Tk_UnmapWindow(slavePtr->tkwin);
    Unlink(contentPtr);
    Tk_UnmapWindow(contentPtr->tkwin);
}

/*
 *------------------------------------------------------------------------
 *
 * ArrangePacking --
 *
 *	This function is invoked (using the Tcl_DoWhenIdle mechanism) to
 *	re-layout a set of windows managed by the packer. It is invoked at
 *	idle time so that a series of packer requests can be merged into a
 *	single layout operation.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The packed slaves of masterPtr may get resized or moved.
 *	The packed content of containerPtr may get resized or moved.
 *
 *------------------------------------------------------------------------
 */

static void
ArrangePacking(
    ClientData clientData)	/* Structure describing master whose slaves
    ClientData clientData)	/* Structure describing container whose content
				 * are to be re-layed out. */
{
    register Packer *masterPtr = clientData;
    register Packer *slavePtr;
    Packer *containerPtr = (Packer *)clientData;
    Packer *contentPtr;
    int cavityX, cavityY, cavityWidth, cavityHeight;
				/* These variables keep track of the
				 * as-yet-unallocated space remaining in the
				 * middle of the master window. */
				 * middle of the container window. */
    int frameX, frameY, frameWidth, frameHeight;
				/* These variables keep track of the frame
				 * allocated to the current window. */
    int x, y, width, height;	/* These variables are used to hold the actual
				 * geometry of the current window. */
    int abort;			/* May get set to non-zero to abort this
				 * repacking operation. */
    int borderX, borderY;
    int borderTop, borderBtm;
    int borderLeft, borderRight;
    int maxWidth, maxHeight, tmp;

    masterPtr->flags &= ~REQUESTED_REPACK;
    containerPtr->flags &= ~REQUESTED_REPACK;

    /*
     * If the master has no slaves anymore, then don't do anything at all:
     * just leave the master's size as-is.
     * If the container has no content anymore, then leave the container's size as-is.
     * Otherwise there is no way to "relinquish" control over the container
     * so another geometry manager can take over.
     */

    if (masterPtr->slavePtr == NULL) {
    if (containerPtr->contentPtr == NULL) {
	return;
    }

    /*
     * Abort any nested call to ArrangePacking for this window, since we'll do
     * everything necessary here, and set up so this call can be aborted if
     * necessary.
     */

    if (masterPtr->abortPtr != NULL) {
	*masterPtr->abortPtr = 1;
    if (containerPtr->abortPtr != NULL) {
	*containerPtr->abortPtr = 1;
    }
    masterPtr->abortPtr = &abort;
    containerPtr->abortPtr = &abort;
    abort = 0;
    Tcl_Preserve(masterPtr);
    Tcl_Preserve(containerPtr);

    /*
     * Pass #1: scan all the slaves to figure out the total amount of space
     * Pass #1: scan all the content to figure out the total amount of space
     * needed. Two separate width and height values are computed:
     *
     * width -		Holds the sum of the widths (plus padding) of all the
     *			slaves seen so far that were packed LEFT or RIGHT.
     *			content seen so far that were packed LEFT or RIGHT.
     * height -		Holds the sum of the heights (plus padding) of all the
     *			slaves seen so far that were packed TOP or BOTTOM.
     *			content seen so far that were packed TOP or BOTTOM.
     *
     * maxWidth -	Gradually builds up the width needed by the master to
     *			just barely satisfy all the slave's needs. For each
     *			slave, the code computes the width needed for all the
     *			slaves so far and updates maxWidth if the new value is
     * maxWidth -	Gradually builds up the width needed by the container to
     *			just barely satisfy all the content's needs. For each
     *			content, the code computes the width needed for all the
     *			content so far and updates maxWidth if the new value is
     *			greater.
     * maxHeight -	Same as maxWidth, except keeps height info.
     */

    width = maxWidth = Tk_InternalBorderLeft(masterPtr->tkwin) +
	    Tk_InternalBorderRight(masterPtr->tkwin);
    height = maxHeight = Tk_InternalBorderTop(masterPtr->tkwin) +
	    Tk_InternalBorderBottom(masterPtr->tkwin);
    for (slavePtr = masterPtr->slavePtr; slavePtr != NULL;
	    slavePtr = slavePtr->nextPtr) {
	if ((slavePtr->side == TOP) || (slavePtr->side == BOTTOM)) {
	    tmp = Tk_ReqWidth(slavePtr->tkwin) + slavePtr->doubleBw
		    + slavePtr->padX + slavePtr->iPadX + width;
    width = maxWidth = Tk_InternalBorderLeft(containerPtr->tkwin) +
	    Tk_InternalBorderRight(containerPtr->tkwin);
    height = maxHeight = Tk_InternalBorderTop(containerPtr->tkwin) +
	    Tk_InternalBorderBottom(containerPtr->tkwin);
    for (contentPtr = containerPtr->contentPtr; contentPtr != NULL;
	    contentPtr = contentPtr->nextPtr) {
	if ((contentPtr->side == TOP) || (contentPtr->side == BOTTOM)) {
	    tmp = Tk_ReqWidth(contentPtr->tkwin) + contentPtr->doubleBw
		    + contentPtr->padX + contentPtr->iPadX + width;
	    if (tmp > maxWidth) {
		maxWidth = tmp;
	    }
	    height += Tk_ReqHeight(slavePtr->tkwin) + slavePtr->doubleBw
		    + slavePtr->padY + slavePtr->iPadY;
	    height += Tk_ReqHeight(contentPtr->tkwin) + contentPtr->doubleBw
		    + contentPtr->padY + contentPtr->iPadY;
	} else {
	    tmp = Tk_ReqHeight(slavePtr->tkwin) + slavePtr->doubleBw
		    + slavePtr->padY + slavePtr->iPadY + height;
	    tmp = Tk_ReqHeight(contentPtr->tkwin) + contentPtr->doubleBw
		    + contentPtr->padY + contentPtr->iPadY + height;
	    if (tmp > maxHeight) {
		maxHeight = tmp;
	    }
	    width += Tk_ReqWidth(slavePtr->tkwin) + slavePtr->doubleBw
		    + slavePtr->padX + slavePtr->iPadX;
	    width += Tk_ReqWidth(contentPtr->tkwin) + contentPtr->doubleBw
		    + contentPtr->padX + contentPtr->iPadX;
	}
    }
    if (width > maxWidth) {
	maxWidth = width;
    }
    if (height > maxHeight) {
	maxHeight = height;
    }

    if (maxWidth < Tk_MinReqWidth(masterPtr->tkwin)) {
	maxWidth = Tk_MinReqWidth(masterPtr->tkwin);
    if (maxWidth < Tk_MinReqWidth(containerPtr->tkwin)) {
	maxWidth = Tk_MinReqWidth(containerPtr->tkwin);
    }
    if (maxHeight < Tk_MinReqHeight(masterPtr->tkwin)) {
	maxHeight = Tk_MinReqHeight(masterPtr->tkwin);
    if (maxHeight < Tk_MinReqHeight(containerPtr->tkwin)) {
	maxHeight = Tk_MinReqHeight(containerPtr->tkwin);
    }

    /*
     * If the total amount of space needed in the master window has changed,
     * If the total amount of space needed in the container window has changed,
     * and if we're propagating geometry information, then notify the next
     * geometry manager up and requeue ourselves to start again after the
     * master has had a chance to resize us.
     * container has had a chance to resize us.
     */

    if (((maxWidth != Tk_ReqWidth(masterPtr->tkwin))
	    || (maxHeight != Tk_ReqHeight(masterPtr->tkwin)))
	    && !(masterPtr->flags & DONT_PROPAGATE)) {
	Tk_GeometryRequest(masterPtr->tkwin, maxWidth, maxHeight);
	masterPtr->flags |= REQUESTED_REPACK;
	Tcl_DoWhenIdle(ArrangePacking, masterPtr);
    if (((maxWidth != Tk_ReqWidth(containerPtr->tkwin))
	    || (maxHeight != Tk_ReqHeight(containerPtr->tkwin)))
	    && !(containerPtr->flags & DONT_PROPAGATE)) {
	Tk_GeometryRequest(containerPtr->tkwin, maxWidth, maxHeight);
	containerPtr->flags |= REQUESTED_REPACK;
	Tcl_DoWhenIdle(ArrangePacking, containerPtr);
	goto done;
    }

    /*
     * Pass #2: scan the slaves a second time assigning new sizes. The
     * Pass #2: scan the content a second time assigning new sizes. The
     * "cavity" variables keep track of the unclaimed space in the cavity of
     * the window; this shrinks inward as we allocate windows around the
     * edges. The "frame" variables keep track of the space allocated to the
     * current window and its frame. The current window is then placed
     * somewhere inside the frame, depending on anchor.
     */

    cavityX = x = Tk_InternalBorderLeft(masterPtr->tkwin);
    cavityY = y = Tk_InternalBorderTop(masterPtr->tkwin);
    cavityWidth = Tk_Width(masterPtr->tkwin) -
	    Tk_InternalBorderLeft(masterPtr->tkwin) -
	    Tk_InternalBorderRight(masterPtr->tkwin);
    cavityHeight = Tk_Height(masterPtr->tkwin) -
	    Tk_InternalBorderTop(masterPtr->tkwin) -
	    Tk_InternalBorderBottom(masterPtr->tkwin);
    for (slavePtr = masterPtr->slavePtr; slavePtr != NULL;
	    slavePtr = slavePtr->nextPtr) {
	if ((slavePtr->side == TOP) || (slavePtr->side == BOTTOM)) {
    cavityX = x = Tk_InternalBorderLeft(containerPtr->tkwin);
    cavityY = y = Tk_InternalBorderTop(containerPtr->tkwin);
    cavityWidth = Tk_Width(containerPtr->tkwin) -
	    Tk_InternalBorderLeft(containerPtr->tkwin) -
	    Tk_InternalBorderRight(containerPtr->tkwin);
    cavityHeight = Tk_Height(containerPtr->tkwin) -
	    Tk_InternalBorderTop(containerPtr->tkwin) -
	    Tk_InternalBorderBottom(containerPtr->tkwin);
    for (contentPtr = containerPtr->contentPtr; contentPtr != NULL;
	    contentPtr = contentPtr->nextPtr) {
	if ((contentPtr->side == TOP) || (contentPtr->side == BOTTOM)) {
	    frameWidth = cavityWidth;
	    frameHeight = Tk_ReqHeight(slavePtr->tkwin) + slavePtr->doubleBw
		    + slavePtr->padY + slavePtr->iPadY;
	    if (slavePtr->flags & EXPAND) {
		frameHeight += YExpansion(slavePtr, cavityHeight);
	    frameHeight = Tk_ReqHeight(contentPtr->tkwin) + contentPtr->doubleBw
		    + contentPtr->padY + contentPtr->iPadY;
	    if (contentPtr->flags & EXPAND) {
		frameHeight += YExpansion(contentPtr, cavityHeight);
	    }
	    cavityHeight -= frameHeight;
	    if (cavityHeight < 0) {
		frameHeight += cavityHeight;
		cavityHeight = 0;
	    }
	    frameX = cavityX;
	    if (slavePtr->side == TOP) {
	    if (contentPtr->side == TOP) {
		frameY = cavityY;
		cavityY += frameHeight;
	    } else {
		frameY = cavityY + cavityHeight;
	    }
	} else {
	    frameHeight = cavityHeight;
	    frameWidth = Tk_ReqWidth(slavePtr->tkwin) + slavePtr->doubleBw
		    + slavePtr->padX + slavePtr->iPadX;
	    if (slavePtr->flags & EXPAND) {
		frameWidth += XExpansion(slavePtr, cavityWidth);
	    frameWidth = Tk_ReqWidth(contentPtr->tkwin) + contentPtr->doubleBw
		    + contentPtr->padX + contentPtr->iPadX;
	    if (contentPtr->flags & EXPAND) {
		frameWidth += XExpansion(contentPtr, cavityWidth);
	    }
	    cavityWidth -= frameWidth;
	    if (cavityWidth < 0) {
		frameWidth += cavityWidth;
		cavityWidth = 0;
	    }
	    frameY = cavityY;
	    if (slavePtr->side == LEFT) {
	    if (contentPtr->side == LEFT) {
		frameX = cavityX;
		cavityX += frameWidth;
	    } else {
		frameX = cavityX + cavityWidth;
	    }
	}

	/*
	 * Now that we've got the size of the frame for the window, compute
	 * the window's actual size and location using the fill, padding, and
	 * frame factors. The variables "borderX" and "borderY" are used to
	 * handle the differences between old-style packing and the new style
	 * (in old-style, iPadX and iPadY are always zero and padding is
	 * completely ignored except when computing frame size).
	 */

	if (slavePtr->flags & OLD_STYLE) {
	if (contentPtr->flags & OLD_STYLE) {
	    borderX = borderY = 0;
	    borderTop = borderBtm = 0;
	    borderLeft = borderRight = 0;
	} else {
	    borderX = slavePtr->padX;
	    borderY = slavePtr->padY;
	    borderLeft = slavePtr->padLeft;
	    borderX = contentPtr->padX;
	    borderY = contentPtr->padY;
	    borderLeft = contentPtr->padLeft;
	    borderRight = borderX - borderLeft;
	    borderTop = slavePtr->padTop;
	    borderTop = contentPtr->padTop;
	    borderBtm = borderY - borderTop;
	}
	width = Tk_ReqWidth(slavePtr->tkwin) + slavePtr->doubleBw
		+ slavePtr->iPadX;
	if ((slavePtr->flags & FILLX)
	width = Tk_ReqWidth(contentPtr->tkwin) + contentPtr->doubleBw
		+ contentPtr->iPadX;
	if ((contentPtr->flags & FILLX)
		|| (width > (frameWidth - borderX))) {
	    width = frameWidth - borderX;
	}
	height = Tk_ReqHeight(slavePtr->tkwin) + slavePtr->doubleBw
		+ slavePtr->iPadY;
	if ((slavePtr->flags & FILLY)
	height = Tk_ReqHeight(contentPtr->tkwin) + contentPtr->doubleBw
		+ contentPtr->iPadY;
	if ((contentPtr->flags & FILLY)
		|| (height > (frameHeight - borderY))) {
	    height = frameHeight - borderY;
	}
	switch (slavePtr->anchor) {
	switch (contentPtr->anchor) {
	case TK_ANCHOR_N:
	    x = frameX + (borderLeft + frameWidth - width - borderRight)/2;
	    y = frameY + borderTop;
	    break;
	case TK_ANCHOR_NE:
	    x = frameX + frameWidth - width - borderRight;
	    y = frameY + borderTop;
819
820
821
822
823
824
825
826
827


828
829
830
831

832
833
834
835

836
837

838
839
840
841
842
843





844
845
846
847
848
849
850
851


852
853
854
855


856
857
858
859
860
861


862
863

864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881


882
883
884
885
886
887
888
889

890
891
892
893
894
895
896
897
898
899
900
901
902
903
904

905
906

907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927




928
929
930
931
932
933
934
935
936

937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955

956
957
958
959
960
961
962
963
964
965
966
967
968
969
970

971
972

973
974
975
976
977
978
979
980
981
982
983
984
985
986




987
988
989
990
991
992
993
994
995

996
997
998
999
1000
1001
1002
829
830
831
832
833
834
835


836
837
838
839
840

841
842
843
844

845
846

847
848





849
850
851
852
853
854
855
856
857
858
859


860
861
862
863


864
865
866
867
868
869


870
871
872

873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889


890
891
892
893
894
895
896
897
898

899
900
901
902
903
904
905
906
907
908
909
910
911
912
913

914
915

916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933




934
935
936
937
938
939
940
941
942
943
944
945

946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964

965
966
967
968
969
970
971
972
973
974
975
976
977
978
979

980
981

982
983
984
985
986
987
988
989
990
991
992




993
994
995
996
997
998
999
1000
1001
1002
1003
1004

1005
1006
1007
1008
1009
1010
1011
1012







-
-
+
+



-
+



-
+

-
+

-
-
-
-
-
+
+
+
+
+






-
-
+
+


-
-
+
+




-
-
+
+

-
+
















-
-
+
+







-
+














-
+

-
+

















-
-
-
-
+
+
+
+








-
+


















-
+














-
+

-
+










-
-
-
-
+
+
+
+








-
+







	case TK_ANCHOR_CENTER:
	    x = frameX + (borderLeft + frameWidth - width - borderRight)/2;
	    y = frameY + (borderTop + frameHeight - height - borderBtm)/2;
	    break;
	default:
	    Tcl_Panic("bad frame factor in ArrangePacking");
	}
	width -= slavePtr->doubleBw;
	height -= slavePtr->doubleBw;
	width -= contentPtr->doubleBw;
	height -= contentPtr->doubleBw;

	/*
	 * The final step is to set the position, size, and mapped/unmapped
	 * state of the slave. If the slave is a child of the master, then do
	 * state of the content. If the content is a child of the container, then do
	 * this here. Otherwise let Tk_MaintainGeometry do the work.
	 */

	if (masterPtr->tkwin == Tk_Parent(slavePtr->tkwin)) {
	if (containerPtr->tkwin == Tk_Parent(contentPtr->tkwin)) {
	    if ((width <= 0) || (height <= 0)) {
		Tk_UnmapWindow(slavePtr->tkwin);
		Tk_UnmapWindow(contentPtr->tkwin);
	    } else {
		if ((x != Tk_X(slavePtr->tkwin))
			|| (y != Tk_Y(slavePtr->tkwin))
			|| (width != Tk_Width(slavePtr->tkwin))
			|| (height != Tk_Height(slavePtr->tkwin))) {
		    Tk_MoveResizeWindow(slavePtr->tkwin, x, y, width, height);
		if ((x != Tk_X(contentPtr->tkwin))
			|| (y != Tk_Y(contentPtr->tkwin))
			|| (width != Tk_Width(contentPtr->tkwin))
			|| (height != Tk_Height(contentPtr->tkwin))) {
		    Tk_MoveResizeWindow(contentPtr->tkwin, x, y, width, height);
		}
		if (abort) {
		    goto done;
		}

		/*
		 * Don't map the slave if the master isn't mapped: wait until
		 * the master gets mapped later.
		 * Don't map the content if the container isn't mapped: wait until
		 * the container gets mapped later.
		 */

		if (Tk_IsMapped(masterPtr->tkwin)) {
		    Tk_MapWindow(slavePtr->tkwin);
		if (Tk_IsMapped(containerPtr->tkwin)) {
		    Tk_MapWindow(contentPtr->tkwin);
		}
	    }
	} else {
	    if ((width <= 0) || (height <= 0)) {
		Tk_UnmaintainGeometry(slavePtr->tkwin, masterPtr->tkwin);
		Tk_UnmapWindow(slavePtr->tkwin);
		Tk_UnmaintainGeometry(contentPtr->tkwin, containerPtr->tkwin);
		Tk_UnmapWindow(contentPtr->tkwin);
	    } else {
		Tk_MaintainGeometry(slavePtr->tkwin, masterPtr->tkwin,
		Tk_MaintainGeometry(contentPtr->tkwin, containerPtr->tkwin,
			x, y, width, height);
	    }
	}

	/*
	 * Changes to the window's structure could cause almost anything to
	 * happen, including deleting the parent or child. If this happens,
	 * we'll be told to abort.
	 */

	if (abort) {
	    goto done;
	}
    }

  done:
    masterPtr->abortPtr = NULL;
    Tcl_Release(masterPtr);
    containerPtr->abortPtr = NULL;
    Tcl_Release(containerPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * XExpansion --
 *
 *	Given a list of packed slaves, the first of which is packed on the
 *	Given a list of packed content, the first of which is packed on the
 *	left or right and is expandable, compute how much to expand the child.
 *
 * Results:
 *	The return value is the number of additional pixels to give to the
 *	child.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
XExpansion(
    register Packer *slavePtr,	/* First in list of remaining slaves. */
    Packer *contentPtr,	/* First in list of remaining content. */
    int cavityWidth)		/* Horizontal space left for all remaining
				 * slaves. */
				 * content. */
{
    int numExpand, minExpand, curExpand;
    int childWidth;

    /*
     * This function is tricky because windows packed top or bottom can be
     * interspersed among expandable windows packed left or right. Scan
     * through the list, keeping a running sum of the widths of all left and
     * right windows (actually, count the cavity space not allocated) and a
     * running count of all expandable left and right windows. At each top or
     * bottom window, and at the end of the list, compute the expansion factor
     * that seems reasonable at that point. Return the smallest factor seen at
     * any of these points.
     */

    minExpand = cavityWidth;
    numExpand = 0;
    for ( ; slavePtr != NULL; slavePtr = slavePtr->nextPtr) {
	childWidth = Tk_ReqWidth(slavePtr->tkwin) + slavePtr->doubleBw
		+ slavePtr->padX + slavePtr->iPadX;
	if ((slavePtr->side == TOP) || (slavePtr->side == BOTTOM)) {
    for ( ; contentPtr != NULL; contentPtr = contentPtr->nextPtr) {
	childWidth = Tk_ReqWidth(contentPtr->tkwin) + contentPtr->doubleBw
		+ contentPtr->padX + contentPtr->iPadX;
	if ((contentPtr->side == TOP) || (contentPtr->side == BOTTOM)) {
	    if (numExpand) {
		curExpand = (cavityWidth - childWidth)/numExpand;
		if (curExpand < minExpand) {
		    minExpand = curExpand;
		}
	    }
	} else {
	    cavityWidth -= childWidth;
	    if (slavePtr->flags & EXPAND) {
	    if (contentPtr->flags & EXPAND) {
		numExpand++;
	    }
	}
    }
    if (numExpand) {
	curExpand = cavityWidth/numExpand;
	if (curExpand < minExpand) {
	    minExpand = curExpand;
	}
    }
    return (minExpand < 0) ? 0 : minExpand;
}

/*
 *----------------------------------------------------------------------
 *
 * YExpansion --
 *
 *	Given a list of packed slaves, the first of which is packed on the top
 *	Given a list of packed content, the first of which is packed on the top
 *	or bottom and is expandable, compute how much to expand the child.
 *
 * Results:
 *	The return value is the number of additional pixels to give to the
 *	child.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
YExpansion(
    register Packer *slavePtr,	/* First in list of remaining slaves. */
    Packer *contentPtr,	/* First in list of remaining content. */
    int cavityHeight)		/* Vertical space left for all remaining
				 * slaves. */
				 * content. */
{
    int numExpand, minExpand, curExpand;
    int childHeight;

    /*
     * See comments for XExpansion.
     */

    minExpand = cavityHeight;
    numExpand = 0;
    for ( ; slavePtr != NULL; slavePtr = slavePtr->nextPtr) {
	childHeight = Tk_ReqHeight(slavePtr->tkwin) + slavePtr->doubleBw
		+ slavePtr->padY + slavePtr->iPadY;
	if ((slavePtr->side == LEFT) || (slavePtr->side == RIGHT)) {
    for ( ; contentPtr != NULL; contentPtr = contentPtr->nextPtr) {
	childHeight = Tk_ReqHeight(contentPtr->tkwin) + contentPtr->doubleBw
		+ contentPtr->padY + contentPtr->iPadY;
	if ((contentPtr->side == LEFT) || (contentPtr->side == RIGHT)) {
	    if (numExpand) {
		curExpand = (cavityHeight - childHeight)/numExpand;
		if (curExpand < minExpand) {
		    minExpand = curExpand;
		}
	    }
	} else {
	    cavityHeight -= childHeight;
	    if (slavePtr->flags & EXPAND) {
	    if (contentPtr->flags & EXPAND) {
		numExpand++;
	    }
	}
    }
    if (numExpand) {
	curExpand = cavityHeight/numExpand;
	if (curExpand < minExpand) {
1026
1027
1028
1029
1030
1031
1032
1033

1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051

1052
1053

1054
1055

1056
1057

1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078

1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089

1090
1091
1092
1093
1094
1095
1096


1097
1098
1099
1100
1101
1102

1103
1104
1105
1106
1107
1108
1109
1036
1037
1038
1039
1040
1041
1042

1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060

1061
1062

1063
1064

1065
1066

1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087

1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105


1106
1107
1108
1109
1110
1111
1112

1113
1114
1115
1116
1117
1118
1119
1120







-
+

















-
+

-
+

-
+

-
+




















-
+











+





-
-
+
+





-
+







 */

static Packer *
GetPacker(
    Tk_Window tkwin)		/* Token for window for which packer structure
				 * is desired. */
{
    register Packer *packPtr;
    Packer *packPtr;
    Tcl_HashEntry *hPtr;
    int isNew;
    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;

    if (!dispPtr->packInit) {
	dispPtr->packInit = 1;
	Tcl_InitHashTable(&dispPtr->packerHashTable, TCL_ONE_WORD_KEYS);
    }

    /*
     * See if there's already packer for this window. If not, then create a
     * new one.
     */

    hPtr = Tcl_CreateHashEntry(&dispPtr->packerHashTable, (char *) tkwin,
	    &isNew);
    if (!isNew) {
	return Tcl_GetHashValue(hPtr);
	return (Packer *)Tcl_GetHashValue(hPtr);
    }
    packPtr = ckalloc(sizeof(Packer));
    packPtr = (Packer *)ckalloc(sizeof(Packer));
    packPtr->tkwin = tkwin;
    packPtr->masterPtr = NULL;
    packPtr->containerPtr = NULL;
    packPtr->nextPtr = NULL;
    packPtr->slavePtr = NULL;
    packPtr->contentPtr = NULL;
    packPtr->side = TOP;
    packPtr->anchor = TK_ANCHOR_CENTER;
    packPtr->padX = packPtr->padY = 0;
    packPtr->padLeft = packPtr->padTop = 0;
    packPtr->iPadX = packPtr->iPadY = 0;
    packPtr->doubleBw = 2*Tk_Changes(tkwin)->border_width;
    packPtr->abortPtr = NULL;
    packPtr->flags = 0;
    Tcl_SetHashValue(hPtr, packPtr);
    Tk_CreateEventHandler(tkwin, StructureNotifyMask,
	    PackStructureProc, packPtr);
    return packPtr;
}

/*
 *------------------------------------------------------------------------
 *
 * PackAfter --
 *
 *	This function does most of the real work of adding one or more windows
 *	into the packing order for its master.
 *	into the packing order for its container.
 *
 * Results:
 *	A standard Tcl return value.
 *
 * Side effects:
 *	The geometry of the specified windows may change, both now and again
 *	in the future.
 *
 *------------------------------------------------------------------------
 */

#ifndef TK_NO_DEPRECATED
static int
PackAfter(
    Tcl_Interp *interp,		/* Interpreter for error reporting. */
    Packer *prevPtr,		/* Pack windows in argv just after this
				 * window; NULL means pack as first child of
				 * masterPtr. */
    Packer *masterPtr,		/* Master in which to pack windows. */
				 * containerPtr. */
    Packer *containerPtr,		/* Container in which to pack windows. */
    int objc,			/* Number of elements in objv. */
    Tcl_Obj *const objv[])	/* Array of lists, each containing 2 elements:
				 * window name and side against which to
				 * pack. */
{
    register Packer *packPtr;
    Packer *packPtr;
    Tk_Window tkwin, ancestor, parent;
    Tcl_Obj **options;
    int index, optionCount, c;

    /*
     * Iterate over all of the window specifiers, each consisting of two
     * arguments. The first argument contains the window name and the
1121
1122
1123
1124
1125
1126
1127
1128

1129
1130
1131
1132
1133
1134

1135
1136
1137
1138
1139
1140
1141
1142


1143
1144
1145
1146
1147
1148
1149
1150

1151
1152
1153
1154
1155
1156
1157
1132
1133
1134
1135
1136
1137
1138

1139
1140
1141
1142
1143
1144

1145
1146
1147
1148
1149
1150
1151


1152
1153
1154
1155
1156
1157
1158
1159
1160

1161
1162
1163
1164
1165
1166
1167
1168







-
+





-
+






-
-
+
+







-
+








	/*
	 * Find the packer for the window to be packed, and make sure that the
	 * window in which it will be packed is either its or a descendant of
	 * its parent.
	 */

	if (TkGetWindowFromObj(interp, masterPtr->tkwin, objv[0], &tkwin)
	if (TkGetWindowFromObj(interp, containerPtr->tkwin, objv[0], &tkwin)
		!= TCL_OK) {
	    return TCL_ERROR;
	}

	parent = Tk_Parent(tkwin);
	for (ancestor = masterPtr->tkwin; ; ancestor = Tk_Parent(ancestor)) {
	for (ancestor = containerPtr->tkwin; ; ancestor = Tk_Parent(ancestor)) {
	    if (ancestor == parent) {
		break;
	    }
	    if (((Tk_FakeWin *) (ancestor))->flags & TK_TOP_HIERARCHY) {
	    badWindow:
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"can't pack %s inside %s", Tcl_GetString(objv[0]),
			Tk_PathName(masterPtr->tkwin)));
			"can't pack \"%s\" inside \"%s\"", Tcl_GetString(objv[0]),
			Tk_PathName(containerPtr->tkwin)));
		Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "HIERARCHY", NULL);
		return TCL_ERROR;
	    }
	}
	if (((Tk_FakeWin *) (tkwin))->flags & TK_TOP_HIERARCHY) {
	    goto badWindow;
	}
	if (tkwin == masterPtr->tkwin) {
	if (tkwin == containerPtr->tkwin) {
	    goto badWindow;
	}
	packPtr = GetPacker(tkwin);

	/*
	 * Process options for this window.
	 */
1165
1166
1167
1168
1169
1170
1171

1172

1173
1174
1175
1176
1177
1178
1179
1180
1176
1177
1178
1179
1180
1181
1182
1183

1184

1185
1186
1187
1188
1189
1190
1191







+
-
+
-







	packPtr->padX = packPtr->padY = 0;
	packPtr->padLeft = packPtr->padTop = 0;
	packPtr->iPadX = packPtr->iPadY = 0;
	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 = Tcl_GetString(curOptPtr);
	    const char *curOpt = TkGetStringFromObj(curOptPtr, &length);
	    size_t length = curOptPtr->length;

	    c = curOpt[0];

	    if ((c == 't')
		    && (strncmp(curOpt, "top", length)) == 0) {
		packPtr->side = TOP;
	    } else if ((c == 'b')
1223
1224
1225
1226
1227
1228
1229
1230

1231
1232
1233
1234
1235
1236
1237
1234
1235
1236
1237
1238
1239
1240

1241
1242
1243
1244
1245
1246
1247
1248







-
+







		    return TCL_ERROR;
		}
		packPtr->padY /= 2;
		packPtr->padTop /= 2;
		packPtr->iPadY = 0;
		index++;
	    } else if ((c == 'f') && (length > 1)
		    && (strncmp(curOpt, "frame", (size_t) length) == 0)) {
		    && (strncmp(curOpt, "frame", length) == 0)) {
		if (optionCount < (index+2)) {
		    Tcl_SetObjResult(interp, Tcl_NewStringObj(
			    "wrong # args: \"frame\""
			    " option must be followed by anchor point", -1));
		    Tcl_SetErrorCode(interp, "TK", "OLDPACK", "BAD_PARAMETER",
			    NULL);
		    return TCL_ERROR;
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262



1263
1264
1265

1266
1267
1268
1269
1270
1271

1272
1273
1274
1275

1276
1277
1278


1279
1280
1281
1282
1283
1284
1285
1286


1287
1288
1289
1290
1291
1292

1293
1294
1295
1296
1297
1298

1299
1300
1301
1302


1303
1304
1305
1306



1307
1308
1309

1310
1311
1312
1313
1314
1315
1316

1317
1318
1319
1320
1321
1322

1323
1324
1325
1326
1327
1328
1329

1330
1331

1332
1333
1334


1335
1336
1337
1338


1339
1340

1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352



1353
1354
1355


1356
1357
1358

1359
1360
1361

1362



1363
1364
1365
1366
1367




1368
1369
1370
1371
1372
1373
1374
1264
1265
1266
1267
1268
1269
1270



1271
1272
1273
1274
1275

1276
1277
1278
1279
1280
1281

1282
1283
1284
1285

1286
1287


1288
1289
1290
1291
1292
1293
1294
1295


1296
1297
1298
1299
1300
1301
1302

1303
1304
1305
1306
1307
1308

1309
1310
1311


1312
1313
1314



1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327

1328
1329
1330
1331
1332
1333

1334
1335
1336
1337
1338
1339
1340

1341
1342

1343
1344


1345
1346
1347
1348


1349
1350
1351

1352
1353
1354
1355
1356
1357
1358
1359
1360
1361



1362
1363
1364
1365


1366
1367
1368
1369

1370
1371
1372

1373
1374
1375
1376
1377
1378
1379



1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390







-
-
-
+
+
+


-
+





-
+



-
+

-
-
+
+






-
-
+
+





-
+





-
+


-
-
+
+

-
-
-
+
+
+



+






-
+





-
+






-
+

-
+

-
-
+
+


-
-
+
+

-
+









-
-
-
+
+
+

-
-
+
+


-
+


-
+

+
+
+


-
-
-
+
+
+
+







	}

	if (packPtr != prevPtr) {
	    /*
	     * Unpack this window if it's currently packed.
	     */

	    if (packPtr->masterPtr != NULL) {
		if ((packPtr->masterPtr != masterPtr) &&
			(packPtr->masterPtr->tkwin
	    if (packPtr->containerPtr != NULL) {
		if ((packPtr->containerPtr != containerPtr) &&
			(packPtr->containerPtr->tkwin
			!= Tk_Parent(packPtr->tkwin))) {
		    Tk_UnmaintainGeometry(packPtr->tkwin,
			    packPtr->masterPtr->tkwin);
			    packPtr->containerPtr->tkwin);
		}
		Unlink(packPtr);
	    }

	    /*
	     * Add the window in the correct place in its master's packing
	     * Add the window in the correct place in its container's packing
	     * order, then make sure that the window is managed by us.
	     */

	    packPtr->masterPtr = masterPtr;
	    packPtr->containerPtr = containerPtr;
	    if (prevPtr == NULL) {
		packPtr->nextPtr = masterPtr->slavePtr;
		masterPtr->slavePtr = packPtr;
		packPtr->nextPtr = containerPtr->contentPtr;
		containerPtr->contentPtr = packPtr;
	    } else {
		packPtr->nextPtr = prevPtr->nextPtr;
		prevPtr->nextPtr = packPtr;
	    }
	    Tk_ManageGeometry(tkwin, &packerType, packPtr);

	    if (!(masterPtr->flags & DONT_PROPAGATE)) {
		if (TkSetGeometryMaster(interp, masterPtr->tkwin, "pack")
	    if (!(containerPtr->flags & DONT_PROPAGATE)) {
		if (TkSetGeometryContainer(interp, containerPtr->tkwin, "pack")
			!= TCL_OK) {
		    Tk_ManageGeometry(tkwin, NULL, NULL);
		    Unlink(packPtr);
		    return TCL_ERROR;
		}
		masterPtr->flags |= ALLOCED_MASTER;
		containerPtr->flags |= ALLOCED_CONTAINER;
	    }
	}
    }

    /*
     * Arrange for the master to be re-packed at the first idle moment.
     * Arrange for the container to be re-packed at the first idle moment.
     */

    if (masterPtr->abortPtr != NULL) {
	*masterPtr->abortPtr = 1;
    if (containerPtr->abortPtr != NULL) {
	*containerPtr->abortPtr = 1;
    }
    if (!(masterPtr->flags & REQUESTED_REPACK)) {
	masterPtr->flags |= REQUESTED_REPACK;
	Tcl_DoWhenIdle(ArrangePacking, masterPtr);
    if (!(containerPtr->flags & REQUESTED_REPACK)) {
	containerPtr->flags |= REQUESTED_REPACK;
	Tcl_DoWhenIdle(ArrangePacking, containerPtr);
    }
    return TCL_OK;
}
#endif /* !TK_NO_DEPRECATED */

/*
 *----------------------------------------------------------------------
 *
 * Unlink --
 *
 *	Remove a packer from its master's list of slaves.
 *	Remove a packer from its container's list of content.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The master will be scheduled for repacking.
 *	The container will be scheduled for repacking.
 *
 *----------------------------------------------------------------------
 */

static void
Unlink(
    register Packer *packPtr)	/* Window to unlink. */
    Packer *packPtr)	/* Window to unlink. */
{
    register Packer *masterPtr, *packPtr2;
    Packer *containerPtr, *packPtr2;

    masterPtr = packPtr->masterPtr;
    if (masterPtr == NULL) {
    containerPtr = packPtr->containerPtr;
    if (containerPtr == NULL) {
	return;
    }
    if (masterPtr->slavePtr == packPtr) {
	masterPtr->slavePtr = packPtr->nextPtr;
    if (containerPtr->contentPtr == packPtr) {
	containerPtr->contentPtr = packPtr->nextPtr;
    } else {
	for (packPtr2 = masterPtr->slavePtr; ; packPtr2 = packPtr2->nextPtr) {
	for (packPtr2 = containerPtr->contentPtr; ; packPtr2 = packPtr2->nextPtr) {
	    if (packPtr2 == NULL) {
		Tcl_Panic("Unlink couldn't find previous window");
	    }
	    if (packPtr2->nextPtr == packPtr) {
		packPtr2->nextPtr = packPtr->nextPtr;
		break;
	    }
	}
    }
    if (!(masterPtr->flags & REQUESTED_REPACK)) {
	masterPtr->flags |= REQUESTED_REPACK;
	Tcl_DoWhenIdle(ArrangePacking, masterPtr);
    if (!(containerPtr->flags & REQUESTED_REPACK)) {
	containerPtr->flags |= REQUESTED_REPACK;
	Tcl_DoWhenIdle(ArrangePacking, containerPtr);
    }
    if (masterPtr->abortPtr != NULL) {
	*masterPtr->abortPtr = 1;
    if (containerPtr->abortPtr != NULL) {
	*containerPtr->abortPtr = 1;
    }

    packPtr->masterPtr = NULL;
    packPtr->containerPtr = NULL;

    /*
     * If we have emptied this master from slaves it means we are no longer
     * If we have emptied this container from content it means we are no longer
     * handling it and should mark it as free.
     *
     * Send the event "NoManagedChild" to the container to inform it about there
     * being no managed children inside it.
     */

    if ((masterPtr->slavePtr == NULL) && (masterPtr->flags & ALLOCED_MASTER)) {
	TkFreeGeometryMaster(masterPtr->tkwin, "pack");
	masterPtr->flags &= ~ALLOCED_MASTER;
    if ((containerPtr->contentPtr == NULL) && (containerPtr->flags & ALLOCED_CONTAINER)) {
	TkFreeGeometryContainer(containerPtr->tkwin, "pack");
	containerPtr->flags &= ~ALLOCED_CONTAINER;
	Tk_SendVirtualEvent(containerPtr->tkwin, "NoManagedChild", NULL);
    }

}

/*
 *----------------------------------------------------------------------
 *
1388
1389
1390
1391
1392
1393
1394
1395

1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413

1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424

1425
1426
1427

1428
1429
1430
1431
1432

1433
1434

1435
1436
1437


1438
1439
1440
1441

1442
1443

1444
1445
1446
1447
1448
1449
1450
1451
1452
1453







1454
1455
1456
1457
1458
1459

1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470


1471
1472
1473

1474
1475
1476
1477
1478
1479

1480
1481
1482

1483
1484
1485
1486

1487
1488
1489
1490
1491
1492
1493
1494
1495
1496

1497
1498
1499
1500


1501
1502
1503
1504
1505
1506
1507

1508
1509
1510
1511
1512
1513

1514
1515
1516

1517
1518
1519
1520
1521
1522
1523
1524
1525



1526
1527
1528
1529
1530
1531
1532
1404
1405
1406
1407
1408
1409
1410

1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428

1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439

1440
1441
1442

1443
1444
1445
1446
1447

1448
1449

1450
1451


1452
1453
1454
1455
1456

1457
1458

1459
1460
1461
1462







1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474

1475
1476
1477
1478
1479
1480
1481
1482
1483
1484


1485
1486
1487
1488

1489
1490
1491
1492
1493
1494

1495
1496
1497

1498
1499
1500
1501

1502
1503
1504
1505
1506
1507
1508
1509
1510
1511

1512
1513
1514


1515
1516
1517
1518
1519
1520
1521
1522

1523
1524
1525
1526
1527
1528

1529
1530
1531

1532
1533
1534
1535
1536
1537
1538



1539
1540
1541
1542
1543
1544
1545
1546
1547
1548







-
+

















-
+










-
+


-
+




-
+

-
+

-
-
+
+



-
+

-
+



-
-
-
-
-
-
-
+
+
+
+
+
+
+





-
+









-
-
+
+


-
+





-
+


-
+



-
+









-
+


-
-
+
+






-
+





-
+


-
+






-
-
-
+
+
+







 */

static void
DestroyPacker(
    void *memPtr)		/* Info about packed window that is now
				 * dead. */
{
    register Packer *packPtr = memPtr;
    Packer *packPtr = (Packer *)memPtr;

    ckfree(packPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * PackStructureProc --
 *
 *	This function is invoked by the Tk event dispatcher in response to
 *	StructureNotify events.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	If a window was just deleted, clean up all its packer-related
 *	information. If it was just resized, repack its slaves, if any.
 *	information. If it was just resized, repack its content, if any.
 *
 *----------------------------------------------------------------------
 */

static void
PackStructureProc(
    ClientData clientData,	/* Our information about window referred to by
				 * eventPtr. */
    XEvent *eventPtr)		/* Describes what just happened. */
{
    register Packer *packPtr = clientData;
    Packer *packPtr = (Packer *)clientData;

    if (eventPtr->type == ConfigureNotify) {
	if ((packPtr->slavePtr != NULL)
	if ((packPtr->contentPtr != NULL)
		&& !(packPtr->flags & REQUESTED_REPACK)) {
	    packPtr->flags |= REQUESTED_REPACK;
	    Tcl_DoWhenIdle(ArrangePacking, packPtr);
	}
	if ((packPtr->masterPtr != NULL)
	if ((packPtr->containerPtr != NULL)
	        && (packPtr->doubleBw != 2*Tk_Changes(packPtr->tkwin)->border_width)) {
	    if (!(packPtr->masterPtr->flags & REQUESTED_REPACK)) {
	    if (!(packPtr->containerPtr->flags & REQUESTED_REPACK)) {
		packPtr->doubleBw = 2*Tk_Changes(packPtr->tkwin)->border_width;
		packPtr->masterPtr->flags |= REQUESTED_REPACK;
		Tcl_DoWhenIdle(ArrangePacking, packPtr->masterPtr);
		packPtr->containerPtr->flags |= REQUESTED_REPACK;
		Tcl_DoWhenIdle(ArrangePacking, packPtr->containerPtr);
	    }
	}
    } else if (eventPtr->type == DestroyNotify) {
	register Packer *slavePtr, *nextPtr;
	Packer *contentPtr, *nextPtr;

	if (packPtr->masterPtr != NULL) {
	if (packPtr->containerPtr != NULL) {
	    Unlink(packPtr);
	}

	for (slavePtr = packPtr->slavePtr; slavePtr != NULL;
		slavePtr = nextPtr) {
	    Tk_ManageGeometry(slavePtr->tkwin, NULL, NULL);
	    Tk_UnmapWindow(slavePtr->tkwin);
	    slavePtr->masterPtr = NULL;
	    nextPtr = slavePtr->nextPtr;
	    slavePtr->nextPtr = NULL;
	for (contentPtr = packPtr->contentPtr; contentPtr != NULL;
		contentPtr = nextPtr) {
	    Tk_ManageGeometry(contentPtr->tkwin, NULL, NULL);
	    Tk_UnmapWindow(contentPtr->tkwin);
	    contentPtr->containerPtr = NULL;
	    nextPtr = contentPtr->nextPtr;
	    contentPtr->nextPtr = NULL;
	}

	if (packPtr->tkwin != NULL) {
	    TkDisplay *dispPtr = ((TkWindow *) packPtr->tkwin)->dispPtr;
            Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->packerHashTable,
		    (char *) packPtr->tkwin));
		    packPtr->tkwin));
	}

	if (packPtr->flags & REQUESTED_REPACK) {
	    Tcl_CancelIdleCall(ArrangePacking, packPtr);
	}
	packPtr->tkwin = NULL;
	Tcl_EventuallyFree(packPtr, (Tcl_FreeProc *) DestroyPacker);
    } else if (eventPtr->type == MapNotify) {
	/*
	 * When a master gets mapped, must redo the geometry computation so
	 * that all of its slaves get remapped.
	 * When a container gets mapped, must redo the geometry computation so
	 * that all of its content get remapped.
	 */

	if ((packPtr->slavePtr != NULL)
	if ((packPtr->contentPtr != NULL)
		&& !(packPtr->flags & REQUESTED_REPACK)) {
	    packPtr->flags |= REQUESTED_REPACK;
	    Tcl_DoWhenIdle(ArrangePacking, packPtr);
	}
    } else if (eventPtr->type == UnmapNotify) {
	register Packer *packPtr2;
	Packer *packPtr2;

	/*
	 * Unmap all of the slaves when the master gets unmapped, so that they
	 * Unmap all of the content when the container gets unmapped, so that they
	 * don't bother to keep redisplaying themselves.
	 */

	for (packPtr2 = packPtr->slavePtr; packPtr2 != NULL;
	for (packPtr2 = packPtr->contentPtr; packPtr2 != NULL;
	     packPtr2 = packPtr2->nextPtr) {
	    Tk_UnmapWindow(packPtr2->tkwin);
	}
    }
}

/*
 *----------------------------------------------------------------------
 *
 * ConfigureSlaves --
 * ConfigureContent --
 *
 *	This implements the guts of the "pack configure" command. Given a list
 *	of slaves and configuration options, it arranges for the packer to
 *	manage the slaves and sets the specified options.
 *	of content and configuration options, it arranges for the packer to
 *	manage the content and sets the specified options.
 *
 * Results:
 *	TCL_OK is returned if all went well. Otherwise, TCL_ERROR is returned
 *	and the interp's result is set to contain an error message.
 *
 * Side effects:
 *	Slave windows get taken over by the packer.
 *	Content windows get taken over by the packer.
 *
 *----------------------------------------------------------------------
 */

static int
ConfigureSlaves(
ConfigureContent(
    Tcl_Interp *interp,		/* Interpreter for error reporting. */
    Tk_Window tkwin,		/* Any window in application containing
				 * slaves. Used to look up slave names. */
				 * content. Used to look up content names. */
    int objc,			/* Number of elements in argv. */
    Tcl_Obj *const objv[])	/* Argument objects: contains one or more
				 * window names followed by any number of
				 * "option value" pairs. Caller must make sure
				 * that there is at least one window name. */
{
    Packer *masterPtr, *slavePtr, *prevPtr, *otherPtr;
    Tk_Window other, slave, parent, ancestor;
    TkWindow *master;
    Packer *containerPtr, *contentPtr, *prevPtr, *otherPtr;
    Tk_Window other, content, parent, ancestor;
    TkWindow *container;
    int i, j, numWindows, tmp, positionGiven;
    const char *string;
    static const char *const optionStrings[] = {
	"-after", "-anchor", "-before", "-expand", "-fill",
	"-in", "-ipadx", "-ipady", "-padx", "-pady", "-side", NULL };
    enum options {
	CONF_AFTER, CONF_ANCHOR, CONF_BEFORE, CONF_EXPAND, CONF_FILL,
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551




1552
1553
1554
1555
1556
1557

1558
1559
1560
1561

1562
1563
1564

1565
1566
1567
1568
1569
1570
1571
1572


1573
1574
1575

1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586







1587
1588
1589
1590
1591
1592
1593
1557
1558
1559
1560
1561
1562
1563




1564
1565
1566
1567
1568
1569
1570
1571
1572

1573
1574
1575
1576

1577
1578
1579

1580
1581
1582
1583
1584
1585
1586


1587
1588
1589
1590

1591
1592
1593
1594
1595







1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609







-
-
-
-
+
+
+
+





-
+



-
+


-
+






-
-
+
+


-
+




-
-
-
-
-
-
-
+
+
+
+
+
+
+







	string = Tcl_GetString(objv[numWindows]);
	if (string[0] != '.') {
	    break;
	}
    }

    /*
     * Iterate over all of the slave windows, parsing the configuration
     * options for each slave. It's a bit wasteful to re-parse the options for
     * each slave, but things get too messy if we try to parse the arguments
     * just once at the beginning. For example, if a slave already is packed
     * Iterate over all of the content windows, parsing the configuration
     * options for each content. It's a bit wasteful to re-parse the options for
     * each content, but things get too messy if we try to parse the arguments
     * just once at the beginning. For example, if a content already is packed
     * we want to just change a few existing values without resetting
     * everything. If there are multiple windows, the -after, -before, and -in
     * options only get processed for the first window.
     */

    masterPtr = NULL;
    containerPtr = NULL;
    prevPtr = NULL;
    positionGiven = 0;
    for (j = 0; j < numWindows; j++) {
	if (TkGetWindowFromObj(interp, tkwin, objv[j], &slave) != TCL_OK) {
	if (TkGetWindowFromObj(interp, tkwin, objv[j], &content) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (Tk_TopWinHierarchy(slave)) {
	if (Tk_TopWinHierarchy(content)) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "can't pack \"%s\": it's a top-level window",
		    Tcl_GetString(objv[j])));
	    Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "TOPLEVEL", NULL);
	    return TCL_ERROR;
	}
	slavePtr = GetPacker(slave);
	slavePtr->flags &= ~OLD_STYLE;
	contentPtr = GetPacker(content);
	contentPtr->flags &= ~OLD_STYLE;

	/*
	 * If the slave isn't currently packed, reset all of its configuration
	 * If the content isn't currently packed, reset all of its configuration
	 * information to default values (there could be old values left from
	 * a previous packing).
	 */

	if (slavePtr->masterPtr == NULL) {
	    slavePtr->side = TOP;
	    slavePtr->anchor = TK_ANCHOR_CENTER;
	    slavePtr->padX = slavePtr->padY = 0;
	    slavePtr->padLeft = slavePtr->padTop = 0;
	    slavePtr->iPadX = slavePtr->iPadY = 0;
	    slavePtr->flags &= ~(FILLX|FILLY|EXPAND);
	if (contentPtr->containerPtr == NULL) {
	    contentPtr->side = TOP;
	    contentPtr->anchor = TK_ANCHOR_CENTER;
	    contentPtr->padX = contentPtr->padY = 0;
	    contentPtr->padLeft = contentPtr->padTop = 0;
	    contentPtr->iPadX = contentPtr->iPadY = 0;
	    contentPtr->flags &= ~(FILLX|FILLY|EXPAND);
	}

	for (i = numWindows; i < objc; i+=2) {
	    if ((i+2) > objc) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"extra option \"%s\" (option with no value?)",
			Tcl_GetString(objv[i])));
1603
1604
1605
1606
1607
1608
1609
1610

1611
1612
1613
1614
1615
1616
1617
1618
1619

1620
1621
1622
1623
1624

1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636

1637
1638
1639
1640


1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655

1656
1657

1658
1659
1660
1661
1662
1663

1664
1665

1666
1667

1668
1669

1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685


1686
1687
1688
1689
1690
1691
1692
1693
1694
1695

1696
1697
1698
1699
1700
1701
1702
1703

1704
1705
1706

1707
1708
1709
1710
1711
1712
1713
1714

1715
1716
1717
1718


1719
1720
1721
1722
1723
1724


1725
1726
1727
1728
1729
1730
1731
1732
1733

1734
1735
1736
1737
1738
1739

1740
1741
1742
1743
1744
1745


1746
1747
1748
1749
1750

1751
1752
1753
1754
1755
1756


1757
1758
1759
1760
1761
1762

1763
1764
1765
1766
1767
1768


1769
1770
1771
1772
1773
1774
1775
1776
1777
1778


1779
1780
1781
1782
1783


1784
1785
1786
1787
1788
1789
1790


1791
1792
1793
1794
1795

1796
1797

1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808



1809
1810
1811


1812
1813
1814
1815
1816
1817


1818
1819
1820
1821

1822
1823
1824
1825
1826
1827
1828
1829
1830






1831
1832

1833
1834
1835

1836
1837
1838


1839
1840
1841


1842
1843
1844


1845
1846
1847


1848
1849
1850


1851
1852
1853

1854
1855
1856
1857

1858
1859
1860
1861
1862


1863
1864
1865
1866



1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1619
1620
1621
1622
1623
1624
1625

1626
1627
1628
1629
1630
1631
1632
1633
1634

1635
1636
1637
1638
1639

1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651

1652
1653
1654


1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670

1671
1672

1673
1674
1675
1676
1677
1678

1679
1680

1681
1682

1683
1684

1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699


1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710

1711
1712
1713
1714
1715
1716
1717
1718

1719
1720
1721

1722
1723
1724
1725
1726
1727
1728
1729

1730
1731
1732


1733
1734
1735
1736
1737
1738


1739
1740
1741
1742
1743
1744
1745
1746
1747
1748

1749
1750
1751
1752
1753
1754

1755
1756
1757
1758
1759


1760
1761
1762
1763
1764
1765

1766
1767
1768
1769
1770


1771
1772
1773
1774
1775
1776
1777

1778
1779
1780
1781
1782


1783
1784
1785
1786
1787
1788
1789
1790
1791
1792


1793
1794
1795
1796
1797


1798
1799
1800
1801
1802
1803
1804


1805
1806
1807
1808
1809
1810

1811
1812

1813
1814
1815
1816
1817
1818
1819
1820
1821



1822
1823
1824
1825


1826
1827
1828
1829
1830
1831


1832
1833
1834
1835
1836

1837
1838
1839
1840






1841
1842
1843
1844
1845
1846
1847

1848
1849
1850

1851
1852


1853
1854
1855


1856
1857
1858


1859
1860
1861


1862
1863
1864


1865
1866
1867
1868

1869
1870
1871
1872

1873
1874
1875
1876


1877
1878
1879



1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894







-
+








-
+




-
+











-
+


-
-
+
+














-
+

-
+





-
+

-
+

-
+

-
+














-
-
+
+









-
+







-
+


-
+







-
+


-
-
+
+




-
-
+
+








-
+





-
+




-
-
+
+




-
+




-
-
+
+





-
+




-
-
+
+








-
-
+
+



-
-
+
+





-
-
+
+




-
+

-
+








-
-
-
+
+
+

-
-
+
+




-
-
+
+



-
+



-
-
-
-
-
-
+
+
+
+
+
+

-
+


-
+

-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+


-
+



-
+



-
-
+
+

-
-
-
+
+
+












	    case CONF_AFTER:
		if (j == 0) {
		    if (TkGetWindowFromObj(interp, tkwin, objv[i+1], &other)
			    != TCL_OK) {
			return TCL_ERROR;
		    }
		    prevPtr = GetPacker(other);
		    if (prevPtr->masterPtr == NULL) {
		    if (prevPtr->containerPtr == NULL) {
		    notPacked:
			Tcl_SetObjResult(interp, Tcl_ObjPrintf(
				"window \"%s\" isn't packed",
				Tcl_GetString(objv[i+1])));
			Tcl_SetErrorCode(interp, "TK", "PACK", "NOT_PACKED",
				NULL);
			return TCL_ERROR;
		    }
		    masterPtr = prevPtr->masterPtr;
		    containerPtr = prevPtr->containerPtr;
		    positionGiven = 1;
		}
		break;
	    case CONF_ANCHOR:
		if (Tk_GetAnchorFromObj(interp, objv[i+1], &slavePtr->anchor)
		if (Tk_GetAnchorFromObj(interp, objv[i+1], &contentPtr->anchor)
			!= TCL_OK) {
		    return TCL_ERROR;
		}
		break;
	    case CONF_BEFORE:
		if (j == 0) {
		    if (TkGetWindowFromObj(interp, tkwin, objv[i+1], &other)
			    != TCL_OK) {
			return TCL_ERROR;
		    }
		    otherPtr = GetPacker(other);
		    if (otherPtr->masterPtr == NULL) {
		    if (otherPtr->containerPtr == NULL) {
			goto notPacked;
		    }
		    masterPtr = otherPtr->masterPtr;
		    prevPtr = masterPtr->slavePtr;
		    containerPtr = otherPtr->containerPtr;
		    prevPtr = containerPtr->contentPtr;
		    if (prevPtr == otherPtr) {
			prevPtr = NULL;
		    } else {
			while (prevPtr->nextPtr != otherPtr) {
			    prevPtr = prevPtr->nextPtr;
			}
		    }
		    positionGiven = 1;
		}
		break;
	    case CONF_EXPAND:
		if (Tcl_GetBooleanFromObj(interp, objv[i+1], &tmp) != TCL_OK) {
		    return TCL_ERROR;
		}
		slavePtr->flags &= ~EXPAND;
		contentPtr->flags &= ~EXPAND;
		if (tmp) {
		    slavePtr->flags |= EXPAND;
		    contentPtr->flags |= EXPAND;
		}
		break;
	    case CONF_FILL:
		string = Tcl_GetString(objv[i+1]);
		if (strcmp(string, "none") == 0) {
		    slavePtr->flags &= ~(FILLX|FILLY);
		    contentPtr->flags &= ~(FILLX|FILLY);
		} else if (strcmp(string, "x") == 0) {
		    slavePtr->flags = (slavePtr->flags & ~FILLY) | FILLX;
		    contentPtr->flags = (contentPtr->flags & ~FILLY) | FILLX;
		} else if (strcmp(string, "y") == 0) {
		    slavePtr->flags = (slavePtr->flags & ~FILLX) | FILLY;
		    contentPtr->flags = (contentPtr->flags & ~FILLX) | FILLY;
		} else if (strcmp(string, "both") == 0) {
		    slavePtr->flags |= FILLX|FILLY;
		    contentPtr->flags |= FILLX|FILLY;
		} else {
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			    "bad fill style \"%s\": must be "
			    "none, x, y, or both", string));
		    Tcl_SetErrorCode(interp, "TK", "VALUE", "FILL", NULL);
		    return TCL_ERROR;
		}
		break;
	    case CONF_IN:
		if (j == 0) {
		    if (TkGetWindowFromObj(interp, tkwin, objv[i+1], &other)
			    != TCL_OK) {
			return TCL_ERROR;
		    }
		    masterPtr = GetPacker(other);
		    prevPtr = masterPtr->slavePtr;
		    containerPtr = GetPacker(other);
		    prevPtr = containerPtr->contentPtr;
		    if (prevPtr != NULL) {
			while (prevPtr->nextPtr != NULL) {
			    prevPtr = prevPtr->nextPtr;
			}
		    }
		    positionGiven = 1;
		}
		break;
	    case CONF_IPADX:
		if ((Tk_GetPixelsFromObj(interp, slave, objv[i+1], &tmp)
		if ((Tk_GetPixelsFromObj(interp, content, objv[i+1], &tmp)
			!= TCL_OK) || (tmp < 0)) {
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			    "bad ipadx value \"%s\": must be positive screen"
			    " distance", Tcl_GetString(objv[i+1])));
		    Tcl_SetErrorCode(interp, "TK", "VALUE", "INT_PAD", NULL);
		    return TCL_ERROR;
		}
		slavePtr->iPadX = tmp * 2;
		contentPtr->iPadX = tmp * 2;
		break;
	    case CONF_IPADY:
		if ((Tk_GetPixelsFromObj(interp, slave, objv[i+1], &tmp)
		if ((Tk_GetPixelsFromObj(interp, content, objv[i+1], &tmp)
			!= TCL_OK) || (tmp < 0)) {
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			    "bad ipady value \"%s\": must be positive screen"
			    " distance", Tcl_GetString(objv[i+1])));
		    Tcl_SetErrorCode(interp, "TK", "VALUE", "INT_PAD", NULL);
		    return TCL_ERROR;
		}
		slavePtr->iPadY = tmp * 2;
		contentPtr->iPadY = tmp * 2;
		break;
	    case CONF_PADX:
		if (TkParsePadAmount(interp, slave, objv[i+1],
			&slavePtr->padLeft, &slavePtr->padX) != TCL_OK) {
		if (TkParsePadAmount(interp, content, objv[i+1],
			&contentPtr->padLeft, &contentPtr->padX) != TCL_OK) {
		    return TCL_ERROR;
		}
		break;
	    case CONF_PADY:
		if (TkParsePadAmount(interp, slave, objv[i+1],
			&slavePtr->padTop, &slavePtr->padY) != TCL_OK) {
		if (TkParsePadAmount(interp, content, objv[i+1],
			&contentPtr->padTop, &contentPtr->padY) != TCL_OK) {
		    return TCL_ERROR;
		}
		break;
	    case CONF_SIDE:
		if (Tcl_GetIndexFromObjStruct(interp, objv[i+1], sideNames,
			sizeof(char *), "side", TCL_EXACT, &side) != TCL_OK) {
		    return TCL_ERROR;
		}
		slavePtr->side = (Side) side;
		contentPtr->side = (Side) side;
		break;
	    }
	}

	/*
	 * If no position in a packing list was specified and the slave is
	 * If no position in a packing list was specified and the content is
	 * already packed, then leave it in its current location in its
	 * current packing list.
	 */

	if (!positionGiven && (slavePtr->masterPtr != NULL)) {
	    masterPtr = slavePtr->masterPtr;
	if (!positionGiven && (contentPtr->containerPtr != NULL)) {
	    containerPtr = contentPtr->containerPtr;
	    goto scheduleLayout;
	}

	/*
	 * If the slave is going to be put back after itself or the same -in
	 * If the content is going to be put back after itself or the same -in
	 * window is passed in again, then just skip the whole operation,
	 * since it won't work anyway.
	 */

	if (prevPtr == slavePtr) {
	    masterPtr = slavePtr->masterPtr;
	if (prevPtr == contentPtr) {
	    containerPtr = contentPtr->containerPtr;
	    goto scheduleLayout;
	}

	/*
	 * If none of the "-in", "-before", or "-after" options has been
	 * specified, arrange for the slave to go at the end of the order for
	 * specified, arrange for the content to go at the end of the order for
	 * its parent.
	 */

	if (!positionGiven) {
	    masterPtr = GetPacker(Tk_Parent(slave));
	    prevPtr = masterPtr->slavePtr;
	    containerPtr = GetPacker(Tk_Parent(content));
	    prevPtr = containerPtr->contentPtr;
	    if (prevPtr != NULL) {
		while (prevPtr->nextPtr != NULL) {
		    prevPtr = prevPtr->nextPtr;
		}
	    }
	}

	/*
	 * Make sure that the slave's parent is either the master or an
	 * ancestor of the master, and that the master and slave aren't the
	 * Make sure that the content's parent is either the container or an
	 * ancestor of the container, and that the container and content aren't the
	 * same.
	 */

	parent = Tk_Parent(slave);
	for (ancestor = masterPtr->tkwin; ; ancestor = Tk_Parent(ancestor)) {
	parent = Tk_Parent(content);
	for (ancestor = containerPtr->tkwin; ; ancestor = Tk_Parent(ancestor)) {
	    if (ancestor == parent) {
		break;
	    }
	    if (Tk_TopWinHierarchy(ancestor)) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"can't pack %s inside %s", Tcl_GetString(objv[j]),
			Tk_PathName(masterPtr->tkwin)));
			"can't pack \"%s\" inside \"%s\"", Tcl_GetString(objv[j]),
			Tk_PathName(containerPtr->tkwin)));
		Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "HIERARCHY", NULL);
		return TCL_ERROR;
	    }
	}
	if (slave == masterPtr->tkwin) {
	if (content == containerPtr->tkwin) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "can't pack %s inside itself", Tcl_GetString(objv[j])));
		    "can't pack \"%s\" inside itself", Tcl_GetString(objv[j])));
	    Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "SELF", NULL);
	    return TCL_ERROR;
	}

	/*
	 * Check for management loops.
	 */

	for (master = (TkWindow *)masterPtr->tkwin; master != NULL;
	     master = (TkWindow *)TkGetGeomMaster(master)) {
	    if (master == (TkWindow *)slave) {
	for (container = (TkWindow *)containerPtr->tkwin; container != NULL;
	     container = (TkWindow *)TkGetContainer(container)) {
	    if (container == (TkWindow *)content) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "can't put %s inside %s, would cause management loop",
	            Tcl_GetString(objv[j]), Tk_PathName(masterPtr->tkwin)));
		    "can't put \"%s\" inside \"%s\": would cause management loop",
	            Tcl_GetString(objv[j]), Tk_PathName(containerPtr->tkwin)));
		Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "LOOP", NULL);
		return TCL_ERROR;
	    }
	}
	if (masterPtr->tkwin != Tk_Parent(slave)) {
	    ((TkWindow *)slave)->maintainerPtr = (TkWindow *)masterPtr->tkwin;
	if (containerPtr->tkwin != Tk_Parent(content)) {
	    ((TkWindow *)content)->maintainerPtr = (TkWindow *)containerPtr->tkwin;
	}

	/*
	 * Unpack the slave if it's currently packed, then position it after
	 * Unpack the content if it's currently packed, then position it after
	 * prevPtr.
	 */

	if (slavePtr->masterPtr != NULL) {
	    if ((slavePtr->masterPtr != masterPtr) &&
		    (slavePtr->masterPtr->tkwin
		    != Tk_Parent(slavePtr->tkwin))) {
		Tk_UnmaintainGeometry(slavePtr->tkwin,
			slavePtr->masterPtr->tkwin);
	if (contentPtr->containerPtr != NULL) {
	    if ((contentPtr->containerPtr != containerPtr) &&
		    (contentPtr->containerPtr->tkwin
		    != Tk_Parent(contentPtr->tkwin))) {
		Tk_UnmaintainGeometry(contentPtr->tkwin,
			contentPtr->containerPtr->tkwin);
	    }
	    Unlink(slavePtr);
	    Unlink(contentPtr);
	}

	slavePtr->masterPtr = masterPtr;
	contentPtr->containerPtr = containerPtr;
	if (prevPtr == NULL) {
	    slavePtr->nextPtr = masterPtr->slavePtr;
	    masterPtr->slavePtr = slavePtr;
	    contentPtr->nextPtr = containerPtr->contentPtr;
	    containerPtr->contentPtr = contentPtr;
	} else {
	    slavePtr->nextPtr = prevPtr->nextPtr;
	    prevPtr->nextPtr = slavePtr;
	    contentPtr->nextPtr = prevPtr->nextPtr;
	    prevPtr->nextPtr = contentPtr;
	}
	Tk_ManageGeometry(slave, &packerType, slavePtr);
	prevPtr = slavePtr;
	Tk_ManageGeometry(content, &packerType, contentPtr);
	prevPtr = contentPtr;

	if (!(masterPtr->flags & DONT_PROPAGATE)) {
	    if (TkSetGeometryMaster(interp, masterPtr->tkwin, "pack")
	if (!(containerPtr->flags & DONT_PROPAGATE)) {
	    if (TkSetGeometryContainer(interp, containerPtr->tkwin, "pack")
		    != TCL_OK) {
		Tk_ManageGeometry(slave, NULL, NULL);
		Unlink(slavePtr);
		Tk_ManageGeometry(content, NULL, NULL);
		Unlink(contentPtr);
		return TCL_ERROR;
	    }
	    masterPtr->flags |= ALLOCED_MASTER;
	    containerPtr->flags |= ALLOCED_CONTAINER;
	}

	/*
	 * Arrange for the master to be re-packed at the first idle moment.
	 * Arrange for the container to be re-packed at the first idle moment.
	 */

    scheduleLayout:
	if (masterPtr->abortPtr != NULL) {
	    *masterPtr->abortPtr = 1;
	if (containerPtr->abortPtr != NULL) {
	    *containerPtr->abortPtr = 1;
	}
	if (!(masterPtr->flags & REQUESTED_REPACK)) {
	    masterPtr->flags |= REQUESTED_REPACK;
	    Tcl_DoWhenIdle(ArrangePacking, masterPtr);
	if (!(containerPtr->flags & REQUESTED_REPACK)) {
	    containerPtr->flags |= REQUESTED_REPACK;
	    Tcl_DoWhenIdle(ArrangePacking, containerPtr);
	}
    }
    return TCL_OK;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Changes to generic/tkPanedWindow.c.
1
2
3
4
5
6
7
8
9
10


11
12
13
14
15
16
17


18
19
20
21
22
23
24
1
2
3
4
5
6
7
8


9
10
11
12
13
14
15


16
17
18
19
20
21
22
23
24








-
-
+
+





-
-
+
+







/*
 * tkPanedWindow.c --
 *
 *	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.
 */

#include "default.h"
#include "tkInt.h"
#include "tkInt.h"
#include "default.h"

/*
 * Flag values for "sticky"ness. The 16 combinations subsume the packer's
 * notion of anchor and fill.
 *
 * STICK_NORTH  	This window sticks to the top of its cavity.
 * STICK_EAST		This window sticks to the right edge of its cavity.
66
67
68
69
70
71
72
73

74
75
76
77
78
79
80
81

82
83
84
85

86
87

88
89
90

91
92
93


94
95
96
97

98
99
100
101
102
103

104
105

106
107
108
109

110
111
112
113
114
115
116
117
118
119
120
121
122
123
124

125
126
127
128
129
130
131
66
67
68
69
70
71
72

73
74
75
76
77
78
79
80

81
82
83
84

85
86

87
88
89

90
91


92
93
94
95
96

97
98
99
100
101
102

103
104

105
106
107
108

109
110
111
112
113
114
115
116
117
118
119
120
121
122
123

124
125
126
127
128
129
130
131







-
+







-
+



-
+

-
+


-
+

-
-
+
+



-
+





-
+

-
+



-
+














-
+







    (((stretch) == STRETCH_ALWAYS) ||				\
     ((stretch) == STRETCH_FIRST && (index) == (first)) ||	\
     ((stretch) == STRETCH_LAST && (index) == (last)) ||	\
     ((stretch) == STRETCH_MIDDLE && (index) != (first) && (index) != (last)))

typedef struct {
    Tk_OptionTable pwOptions;	/* Token for paned window option table. */
    Tk_OptionTable slaveOpts;	/* Token for slave cget option table. */
    Tk_OptionTable paneOpts;	/* Token for pane cget option table. */
} OptionTables;

/*
 * One structure of the following type is kept for each window
 * managed by a paned window widget.
 */

typedef struct Slave {
typedef struct Pane {
    Tk_Window tkwin;		/* Window being managed. */
    int minSize;		/* Minimum size of this pane, on the relevant
				 * axis, in pixels. */
    int padx;			/* Additional padding requested for slave, in
    int padx;			/* Additional padding requested for pane, in
				 * the x dimension. */
    int pady;			/* Additional padding requested for slave, in
    int pady;			/* Additional padding requested for pane, in
				 * the y dimension. */
    Tcl_Obj *widthPtr, *heightPtr;
				/* Tcl_Obj rep's of slave width/height, to
				/* Tcl_Obj rep's of pane width/height, to
				 * allow for null values. */
    int width;			/* Slave width. */
    int height;			/* Slave height. */
    int width;			/* Pane width. */
    int height;			/* Pane height. */
    int sticky;			/* Sticky string. */
    int x, y;			/* Coordinates of the widget. */
    int paneWidth, paneHeight;	/* Pane dimensions (may be different from
				 * slave width/height). */
				 * pane width/height). */
    int sashx, sashy;		/* Coordinates of the sash of the right or
				 * bottom of this pane. */
    int markx, marky;		/* Coordinates of the last mark set for the
				 * sash. */
    int handlex, handley;	/* Coordinates of the sash handle. */
    enum stretch stretch;	/* Controls how slave grows/shrinks */
    enum stretch stretch;	/* Controls how pane grows/shrinks */
    int hide;			/* Controls visibility of pane */
    struct PanedWindow *masterPtr;
    struct PanedWindow *containerPtr;
				/* Paned window managing the window. */
    Tk_Window after;		/* Placeholder for parsing options. */
    Tk_Window before;		/* Placeholder for parsing options. */
} Slave;
} Pane;

/*
 * A data structure of the following type is kept for each paned window widget
 * managed by this file:
 */

typedef struct PanedWindow {
    Tk_Window tkwin;		/* Window that embodies the paned window. */
    Tk_Window proxywin;		/* Window for the resizing proxy. */
    Display *display;		/* X's token for the window's display. */
    Tcl_Interp *interp;		/* Interpreter associated with widget. */
    Tcl_Command widgetCmd;	/* Token for square's widget command. */
    Tk_OptionTable optionTable;	/* Token representing the configuration
				 * specifications. */
    Tk_OptionTable slaveOpts;	/* Token for slave cget table. */
    Tk_OptionTable paneOpts;	/* Token for pane cget table. */
    Tk_3DBorder background;	/* Background color. */
    int borderWidth;		/* Value of -borderwidth option. */
    int relief;			/* 3D border effect (TK_RELIEF_RAISED, etc) */
    Tcl_Obj *widthPtr;		/* Tcl_Obj rep for width. */
    Tcl_Obj *heightPtr;		/* Tcl_Obj rep for height. */
    int width, height;		/* Width and height of the widget. */
    enum orient orient;		/* Orientation of the widget. */
147
148
149
150
151
152
153
154
155
156



157
158
159
160
161
162
163
147
148
149
150
151
152
153



154
155
156
157
158
159
160
161
162
163







-
-
-
+
+
+







    GC gc;			/* Graphics context for copying from
				 * off-screen pixmap onto screen. */
    int proxyx, proxyy;		/* Proxy x,y coordinates. */
    Tk_3DBorder proxyBackground;/* Background color used to draw proxy. If NULL, use background. */
    Tcl_Obj *proxyBorderWidthPtr; /* Tcl_Obj rep for proxyBorderWidth */
    int proxyBorderWidth;	/* Borderwidth used to draw proxy. */
    int proxyRelief;		/* Relief used to draw proxy, if TK_RELIEF_NULL then use relief. */
    Slave **slaves;		/* Pointer to array of Slaves. */
    int numSlaves;		/* Number of slaves. */
    int sizeofSlaves;		/* Number of elements in the slaves array. */
    Pane **panes;		/* Pointer to array of Panes. */
    int numPanes;		/* Number of panes. */
    int sizeofPanes;		/* Number of elements in the panes array. */
    int flags;			/* Flags for widget; see below. */
} PanedWindow;

/*
 * Flags used for paned windows:
 *
 * REDRAW_PENDING:		Non-zero means a DoWhenIdle handler has been
196
197
198
199
200
201
202
203

204
205
206
207
208
209


210
211
212

213
214
215
216
217
218
219
220
221

222
223
224
225
226
227
228

229
230
231

232
233
234
235
236

237
238
239

240
241
242
243
244

245
246
247
248

249
250
251
252
253

254
255
256
257
258
259
260
261
262
263
264

265
266
267
268
269
270
271
272
273
274
275
276
277
278

279
280
281

282
283

284
285

286
287
288

289
290
291

292
293
294
295


296
297
298


299
300
301


302
303

304
305
306

307
308
309
310


311
312

313
314
315

316
317

318
319
320

321
322
323

324
325
326
327


328
329

330
331
332
333


334
335
336
337

338
339

340
341
342

343
344
345
346


347
348

349
350

351
352

353
354

355
356

357
358
359

360
361
362
363


364
365
366
367
368
369
370
196
197
198
199
200
201
202

203
204
205
206
207


208
209
210
211

212
213
214
215
216
217
218
219
220

221
222
223
224
225
226
227

228
229
230

231
232
233
234
235

236
237
238

239
240
241
242
243

244
245
246
247

248
249
250
251
252

253
254
255
256
257
258
259
260
261
262
263

264
265
266
267
268
269
270
271
272
273
274
275
276
277

278
279
280

281
282

283
284

285
286
287

288
289
290

291
292
293


294
295
296


297
298
299


300
301
302

303
304
305

306
307
308


309
310
311

312
313
314

315
316

317
318
319

320
321
322

323
324
325


326
327
328

329
330
331


332
333
334
335
336

337
338

339
340
341

342
343
344


345
346
347

348
349

350
351

352
353

354
355

356
357
358

359
360
361


362
363
364
365
366
367
368
369
370







-
+




-
-
+
+


-
+








-
+






-
+


-
+




-
+


-
+




-
+



-
+




-
+










-
+













-
+


-
+

-
+

-
+


-
+


-
+


-
-
+
+

-
-
+
+

-
-
+
+

-
+


-
+


-
-
+
+

-
+


-
+

-
+


-
+


-
+


-
-
+
+

-
+


-
-
+
+



-
+

-
+


-
+


-
-
+
+

-
+

-
+

-
+

-
+

-
+


-
+


-
-
+
+







			    XEvent *eventPtr);
static void		ProxyWindowEventProc(ClientData clientData,
			    XEvent *eventPtr);
static void		DisplayProxyWindow(ClientData clientData);
static void		PanedWindowWorldChanged(ClientData instanceData);
static int		PanedWindowWidgetObjCmd(ClientData clientData,
			    Tcl_Interp *, int objc, Tcl_Obj * const objv[]);
static void		PanedWindowLostSlaveProc(ClientData clientData,
static void		PanedWindowLostPaneProc(ClientData clientData,
			    Tk_Window tkwin);
static void		PanedWindowReqProc(ClientData clientData,
			    Tk_Window tkwin);
static void		ArrangePanes(ClientData clientData);
static void		Unlink(Slave *slavePtr);
static Slave *		GetPane(PanedWindow *pwPtr, Tk_Window tkwin);
static void		Unlink(Pane *panePtr);
static Pane *		GetPane(PanedWindow *pwPtr, Tk_Window tkwin);
static void		GetFirstLastVisiblePane(PanedWindow *pwPtr,
			    int *firstPtr, int *lastPtr);
static void		SlaveStructureProc(ClientData clientData,
static void		PaneStructureProc(ClientData clientData,
			    XEvent *eventPtr);
static int		PanedWindowSashCommand(PanedWindow *pwPtr,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj * const objv[]);
static int		PanedWindowProxyCommand(PanedWindow *pwPtr,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj * const objv[]);
static void		ComputeGeometry(PanedWindow *pwPtr);
static int		ConfigureSlaves(PanedWindow *pwPtr,
static int		ConfigurePanes(PanedWindow *pwPtr,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj * const objv[]);
static void		DestroyOptionTables(ClientData clientData,
			    Tcl_Interp *interp);
static int		SetSticky(ClientData clientData, Tcl_Interp *interp,
			    Tk_Window tkwin, Tcl_Obj **value, char *recordPtr,
			    int internalOffset, char *oldInternalPtr,
			    TkSizeT internalOffset, char *oldInternalPtr,
			    int flags);
static Tcl_Obj *	GetSticky(ClientData clientData, Tk_Window tkwin,
			    char *recordPtr, int internalOffset);
			    char *recordPtr, TkSizeT internalOffset);
static void		RestoreSticky(ClientData clientData, Tk_Window tkwin,
			    char *internalPtr, char *oldInternalPtr);
static void		AdjustForSticky(int sticky, int cavityWidth,
			    int cavityHeight, int *xPtr, int *yPtr,
			    int *slaveWidthPtr, int *slaveHeightPtr);
			    int *paneWidthPtr, int *paneHeightPtr);
static void		MoveSash(PanedWindow *pwPtr, int sash, int diff);
static int		ObjectIsEmpty(Tcl_Obj *objPtr);
static char *		ComputeSlotAddress(char *recordPtr, int offset);
static void *	ComputeSlotAddress(void *recordPtr, TkSizeT offset);
static int		PanedWindowIdentifyCoords(PanedWindow *pwPtr,
			    Tcl_Interp *interp, int x, int y);

/*
 * Sashes are between panes only, so there is one less sash than slaves
 * Sashes are between panes only, so there is one less sash than panes
 */

#define ValidSashIndex(pwPtr, sash) \
	(((sash) >= 0) && ((sash) < ((pwPtr)->numSlaves-1)))
	(((sash) >= 0) && ((sash) < ((pwPtr)->numPanes-1)))

static const Tk_GeomMgr panedWindowMgrType = {
    "panedwindow",		/* name */
    PanedWindowReqProc,		/* requestProc */
    PanedWindowLostSlaveProc,	/* lostSlaveProc */
    PanedWindowLostPaneProc,	/* lostPaneProc */
};

/*
 * Information used for objv parsing.
 */

#define GEOMETRY		0x0001

/*
 * The following structure contains pointers to functions used for processing
 * the custom "-sticky" option for slave windows.
 * the custom "-sticky" option for panes.
 */

static const Tk_ObjCustomOption stickyOption = {
    "sticky",			/* name */
    SetSticky,			/* setProc */
    GetSticky,			/* getProc */
    RestoreSticky,		/* restoreProc */
    NULL,			/* freeProc */
    0
};

static const Tk_OptionSpec optionSpecs[] = {
    {TK_OPTION_BORDER, "-background", "background", "Background",
	 DEF_PANEDWINDOW_BG_COLOR, -1, Tk_Offset(PanedWindow, background), 0,
	 DEF_PANEDWINDOW_BG_COLOR, TCL_INDEX_NONE, offsetof(PanedWindow, background), 0,
	 DEF_PANEDWINDOW_BG_MONO, 0},
    {TK_OPTION_SYNONYM, "-bd", NULL, NULL,
	 NULL, 0, -1, 0, "-borderwidth", 0},
	 NULL, 0, TCL_INDEX_NONE, 0, "-borderwidth", 0},
    {TK_OPTION_SYNONYM, "-bg", NULL, NULL,
	 NULL, 0, -1, 0, "-background", 0},
	 NULL, 0, TCL_INDEX_NONE, 0, "-background", 0},
    {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
	 DEF_PANEDWINDOW_BORDERWIDTH, -1, Tk_Offset(PanedWindow, borderWidth),
	 DEF_PANEDWINDOW_BORDERWIDTH, TCL_INDEX_NONE, offsetof(PanedWindow, borderWidth),
	 0, 0, GEOMETRY},
    {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
	 DEF_PANEDWINDOW_CURSOR, -1, Tk_Offset(PanedWindow, cursor),
	 DEF_PANEDWINDOW_CURSOR, TCL_INDEX_NONE, offsetof(PanedWindow, cursor),
	 TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_PIXELS, "-handlepad", "handlePad", "HandlePad",
	 DEF_PANEDWINDOW_HANDLEPAD, -1, Tk_Offset(PanedWindow, handlePad),
	 DEF_PANEDWINDOW_HANDLEPAD, TCL_INDEX_NONE, offsetof(PanedWindow, handlePad),
	 0, 0, GEOMETRY},
    {TK_OPTION_PIXELS, "-handlesize", "handleSize", "HandleSize",
	 DEF_PANEDWINDOW_HANDLESIZE, Tk_Offset(PanedWindow, handleSizePtr),
	 Tk_Offset(PanedWindow, handleSize), 0, 0, GEOMETRY},
	 DEF_PANEDWINDOW_HANDLESIZE, offsetof(PanedWindow, handleSizePtr),
	 offsetof(PanedWindow, handleSize), 0, 0, GEOMETRY},
    {TK_OPTION_PIXELS, "-height", "height", "Height",
	 DEF_PANEDWINDOW_HEIGHT, Tk_Offset(PanedWindow, heightPtr),
	 Tk_Offset(PanedWindow, height), TK_OPTION_NULL_OK, 0, GEOMETRY},
	 DEF_PANEDWINDOW_HEIGHT, offsetof(PanedWindow, heightPtr),
	 offsetof(PanedWindow, height), TK_OPTION_NULL_OK, 0, GEOMETRY},
    {TK_OPTION_BOOLEAN, "-opaqueresize", "opaqueResize", "OpaqueResize",
	 DEF_PANEDWINDOW_OPAQUERESIZE, -1,
	 Tk_Offset(PanedWindow, resizeOpaque), 0, 0, 0},
	 DEF_PANEDWINDOW_OPAQUERESIZE, TCL_INDEX_NONE,
	 offsetof(PanedWindow, resizeOpaque), 0, 0, 0},
    {TK_OPTION_STRING_TABLE, "-orient", "orient", "Orient",
	 DEF_PANEDWINDOW_ORIENT, -1, Tk_Offset(PanedWindow, orient),
	 DEF_PANEDWINDOW_ORIENT, TCL_INDEX_NONE, offsetof(PanedWindow, orient),
	 0, orientStrings, GEOMETRY},
    {TK_OPTION_BORDER, "-proxybackground", "proxyBackground", "ProxyBackground",
	 0, -1, Tk_Offset(PanedWindow, proxyBackground), TK_OPTION_NULL_OK,
	 0, TCL_INDEX_NONE, offsetof(PanedWindow, proxyBackground), TK_OPTION_NULL_OK,
	 (ClientData) DEF_PANEDWINDOW_BG_MONO, 0},
    {TK_OPTION_PIXELS, "-proxyborderwidth", "proxyBorderWidth", "ProxyBorderWidth",
	 DEF_PANEDWINDOW_PROXYBORDER, Tk_Offset(PanedWindow, proxyBorderWidthPtr),
	 Tk_Offset(PanedWindow, proxyBorderWidth), 0, 0, GEOMETRY},
	 DEF_PANEDWINDOW_PROXYBORDER, offsetof(PanedWindow, proxyBorderWidthPtr),
	 offsetof(PanedWindow, proxyBorderWidth), 0, 0, GEOMETRY},
    {TK_OPTION_RELIEF, "-proxyrelief", "proxyRelief", "Relief",
	 0, -1, Tk_Offset(PanedWindow, proxyRelief),
	 0, TCL_INDEX_NONE, offsetof(PanedWindow, proxyRelief),
	 TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
	 DEF_PANEDWINDOW_RELIEF, -1, Tk_Offset(PanedWindow, relief), 0, 0, 0},
	 DEF_PANEDWINDOW_RELIEF, TCL_INDEX_NONE, offsetof(PanedWindow, relief), 0, 0, 0},
    {TK_OPTION_CURSOR, "-sashcursor", "sashCursor", "Cursor",
	 DEF_PANEDWINDOW_SASHCURSOR, -1, Tk_Offset(PanedWindow, sashCursor),
	 DEF_PANEDWINDOW_SASHCURSOR, TCL_INDEX_NONE, offsetof(PanedWindow, sashCursor),
	 TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_PIXELS, "-sashpad", "sashPad", "SashPad",
	 DEF_PANEDWINDOW_SASHPAD, -1, Tk_Offset(PanedWindow, sashPad),
	 DEF_PANEDWINDOW_SASHPAD, TCL_INDEX_NONE, offsetof(PanedWindow, sashPad),
	 0, 0, GEOMETRY},
    {TK_OPTION_RELIEF, "-sashrelief", "sashRelief", "Relief",
	 DEF_PANEDWINDOW_SASHRELIEF, -1, Tk_Offset(PanedWindow, sashRelief),
	 DEF_PANEDWINDOW_SASHRELIEF, TCL_INDEX_NONE, offsetof(PanedWindow, sashRelief),
	 0, 0, 0},
    {TK_OPTION_PIXELS, "-sashwidth", "sashWidth", "Width",
	 DEF_PANEDWINDOW_SASHWIDTH, Tk_Offset(PanedWindow, sashWidthPtr),
	 Tk_Offset(PanedWindow, sashWidth), 0, 0, GEOMETRY},
	 DEF_PANEDWINDOW_SASHWIDTH, offsetof(PanedWindow, sashWidthPtr),
	 offsetof(PanedWindow, sashWidth), 0, 0, GEOMETRY},
    {TK_OPTION_BOOLEAN, "-showhandle", "showHandle", "ShowHandle",
	 DEF_PANEDWINDOW_SHOWHANDLE, -1, Tk_Offset(PanedWindow, showHandle),
	 DEF_PANEDWINDOW_SHOWHANDLE, TCL_INDEX_NONE, offsetof(PanedWindow, showHandle),
	 0, 0, GEOMETRY},
    {TK_OPTION_PIXELS, "-width", "width", "Width",
	 DEF_PANEDWINDOW_WIDTH, Tk_Offset(PanedWindow, widthPtr),
	 Tk_Offset(PanedWindow, width), TK_OPTION_NULL_OK, 0, GEOMETRY},
	 DEF_PANEDWINDOW_WIDTH, offsetof(PanedWindow, widthPtr),
	 offsetof(PanedWindow, width), TK_OPTION_NULL_OK, 0, GEOMETRY},
    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0}
};

static const Tk_OptionSpec slaveOptionSpecs[] = {
static const Tk_OptionSpec paneOptionSpecs[] = {
    {TK_OPTION_WINDOW, "-after", NULL, NULL,
	 DEF_PANEDWINDOW_PANE_AFTER, -1, Tk_Offset(Slave, after),
	 DEF_PANEDWINDOW_PANE_AFTER, TCL_INDEX_NONE, offsetof(Pane, after),
	 TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_WINDOW, "-before", NULL, NULL,
	 DEF_PANEDWINDOW_PANE_BEFORE, -1, Tk_Offset(Slave, before),
	 DEF_PANEDWINDOW_PANE_BEFORE, TCL_INDEX_NONE, offsetof(Pane, before),
	 TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_PIXELS, "-height", NULL, NULL,
	 DEF_PANEDWINDOW_PANE_HEIGHT, Tk_Offset(Slave, heightPtr),
	 Tk_Offset(Slave, height), TK_OPTION_NULL_OK, 0, 0},
	 DEF_PANEDWINDOW_PANE_HEIGHT, offsetof(Pane, heightPtr),
	 offsetof(Pane, height), TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_BOOLEAN, "-hide", "hide", "Hide",
	 DEF_PANEDWINDOW_PANE_HIDE, -1, Tk_Offset(Slave, hide), 0,0,GEOMETRY},
	 DEF_PANEDWINDOW_PANE_HIDE, TCL_INDEX_NONE, offsetof(Pane, hide), 0,0,GEOMETRY},
    {TK_OPTION_PIXELS, "-minsize", NULL, NULL,
	 DEF_PANEDWINDOW_PANE_MINSIZE, -1, Tk_Offset(Slave, minSize), 0, 0, 0},
	 DEF_PANEDWINDOW_PANE_MINSIZE, TCL_INDEX_NONE, offsetof(Pane, minSize), 0, 0, 0},
    {TK_OPTION_PIXELS, "-padx", NULL, NULL,
	 DEF_PANEDWINDOW_PANE_PADX, -1, Tk_Offset(Slave, padx), 0, 0, 0},
	 DEF_PANEDWINDOW_PANE_PADX, TCL_INDEX_NONE, offsetof(Pane, padx), 0, 0, 0},
    {TK_OPTION_PIXELS, "-pady", NULL, NULL,
	 DEF_PANEDWINDOW_PANE_PADY, -1, Tk_Offset(Slave, pady), 0, 0, 0},
	 DEF_PANEDWINDOW_PANE_PADY, TCL_INDEX_NONE, offsetof(Pane, pady), 0, 0, 0},
    {TK_OPTION_CUSTOM, "-sticky", NULL, NULL,
	 DEF_PANEDWINDOW_PANE_STICKY, -1, Tk_Offset(Slave, sticky), 0,
	 DEF_PANEDWINDOW_PANE_STICKY, TCL_INDEX_NONE, offsetof(Pane, sticky), 0,
	 &stickyOption, 0},
    {TK_OPTION_STRING_TABLE, "-stretch", "stretch", "Stretch",
	DEF_PANEDWINDOW_PANE_STRETCH, -1, Tk_Offset(Slave, stretch), 0,
	DEF_PANEDWINDOW_PANE_STRETCH, TCL_INDEX_NONE, offsetof(Pane, stretch), 0,
	(ClientData) stretchStrings, 0},
    {TK_OPTION_PIXELS, "-width", NULL, NULL,
	 DEF_PANEDWINDOW_PANE_WIDTH, Tk_Offset(Slave, widthPtr),
	 Tk_Offset(Slave, width), TK_OPTION_NULL_OK, 0, 0},
	 DEF_PANEDWINDOW_PANE_WIDTH, offsetof(Pane, widthPtr),
	 offsetof(Pane, width), TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0}
};

/*
 *--------------------------------------------------------------
 *
 * Tk_PanedWindowObjCmd --
379
380
381
382
383
384
385
386

387
388
389
390
391
392
393
379
380
381
382
383
384
385

386
387
388
389
390
391
392
393







-
+







 *	A new widget is created and configured.
 *
 *--------------------------------------------------------------
 */

int
Tk_PanedWindowObjCmd(
    ClientData clientData,	/* NULL. */
    TCL_UNUSED(ClientData),	/* NULL. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj * const objv[])	/* Argument objects. */
{
    PanedWindow *pwPtr;
    Tk_Window tkwin, parent;
    OptionTables *pwOpts;
410
411
412
413
414
415
416
417

418
419
420
421
422
423
424
425
426
427
428
429
430
431

432
433
434
435
436
437
438
439
440

441
442
443
444
445
446
447
448
449

450
451
452
453
454
455
456
457
458
459
460
461
462

463
464
465
466
467
468
469
470
471
472
473
474

475
476
477
478
479
480
481
410
411
412
413
414
415
416

417
418
419
420
421
422
423
424
425
426
427
428
429
430

431
432
433
434
435
436
437
438
439

440
441
442
443
444
445
446
447
448

449
450
451
452
453
454
455
456
457
458
459
460
461

462
463
464
465
466
467
468
469
470
471
472
473

474
475
476
477
478
479
480
481







-
+













-
+








-
+








-
+












-
+











-
+







	/*
	 * The first time this function is invoked, the option tables will be
	 * NULL. We then create the option tables from the templates and store
	 * a pointer to the tables as the command's clinical so we'll have
	 * easy access to it in the future.
	 */

	pwOpts = ckalloc(sizeof(OptionTables));
	pwOpts = (OptionTables *)ckalloc(sizeof(OptionTables));

	/*
	 * Set up an exit handler to free the optionTables struct.
	 */

	Tcl_SetAssocData(interp, "PanedWindowOptionTables",
		DestroyOptionTables, pwOpts);

	/*
	 * Create the paned window option tables.
	 */

	pwOpts->pwOptions = Tk_CreateOptionTable(interp, optionSpecs);
	pwOpts->slaveOpts = Tk_CreateOptionTable(interp, slaveOptionSpecs);
	pwOpts->paneOpts = Tk_CreateOptionTable(interp, paneOptionSpecs);
    }

    Tk_SetClass(tkwin, "Panedwindow");

    /*
     * Allocate and initialize the widget record.
     */

    pwPtr = ckalloc(sizeof(PanedWindow));
    pwPtr = (PanedWindow *)ckalloc(sizeof(PanedWindow));
    memset((void *)pwPtr, 0, (sizeof(PanedWindow)));
    pwPtr->tkwin = tkwin;
    pwPtr->display = Tk_Display(tkwin);
    pwPtr->interp = interp;
    pwPtr->widgetCmd = Tcl_CreateObjCommand(interp,
	    Tk_PathName(pwPtr->tkwin), PanedWindowWidgetObjCmd, pwPtr,
	    PanedWindowCmdDeletedProc);
    pwPtr->optionTable = pwOpts->pwOptions;
    pwPtr->slaveOpts = pwOpts->slaveOpts;
    pwPtr->paneOpts = pwOpts->paneOpts;
    pwPtr->relief = TK_RELIEF_RAISED;
    pwPtr->gc = NULL;
    pwPtr->cursor = NULL;
    pwPtr->sashCursor = NULL;

    /*
     * Keep a hold of the associated tkwin until we destroy the widget,
     * otherwise Tk might free it while we still need it.
     */

    Tcl_Preserve(pwPtr->tkwin);

    if (Tk_InitOptions(interp, (char *) pwPtr, pwOpts->pwOptions,
    if (Tk_InitOptions(interp, pwPtr, pwOpts->pwOptions,
	    tkwin) != TCL_OK) {
	Tk_DestroyWindow(pwPtr->tkwin);
	return TCL_ERROR;
    }

    Tk_CreateEventHandler(pwPtr->tkwin, ExposureMask|StructureNotifyMask,
	    PanedWindowEventProc, pwPtr);

    /*
     * Find the toplevel ancestor of the panedwindow, and make a proxy win as
     * a child of that window; this way the proxy can always float above
     * slaves in the panedwindow.
     * panes in the panedwindow.
     */

    parent = Tk_Parent(pwPtr->tkwin);
    while (!(Tk_IsTopLevel(parent))) {
	parent = Tk_Parent(parent);
	if (parent == NULL) {
	    parent = pwPtr->tkwin;
502
503
504
505
506
507
508
509

510
511
512
513
514
515
516
502
503
504
505
506
507
508

509
510
511
512
513
514
515
516







-
+








    if (ConfigurePanedWindow(interp, pwPtr, objc - 2, objv + 2) != TCL_OK) {
	Tk_DestroyWindow(pwPtr->proxywin);
	Tk_DestroyWindow(pwPtr->tkwin);
	return TCL_ERROR;
    }

    Tcl_SetObjResult(interp, TkNewWindowObj(pwPtr->tkwin));
    Tcl_SetObjResult(interp, Tk_NewWindowObj(pwPtr->tkwin));
    return TCL_OK;
}

/*
 *--------------------------------------------------------------
 *
 * PanedWindowWidgetObjCmd --
531
532
533
534
535
536
537
538

539
540
541
542
543
544
545
546
547
548
549
550
551

552
553
554

555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572

573
574
575
576
577
578
579
580
581

582
583
584
585
586
587
588
589
590
591
592
593

594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619

620
621
622

623
624
625
626


627
628
629
630
631
632
633






634
635
636
637
638
639
640
531
532
533
534
535
536
537

538
539
540
541
542
543
544
545
546
547
548
549
550

551
552
553

554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571

572
573
574
575
576
577
578
579
580

581
582
583
584
585
586
587
588
589
590
591
592

593
594
595
596
597
598
599
600
601
602
603
604
605
606

607
608
609
610
611
612
613
614
615
616
617

618
619
620

621
622
623


624
625
626






627
628
629
630
631
632
633
634
635
636
637
638
639







-
+












-
+


-
+

















-
+








-
+











-
+













-











-
+


-
+


-
-
+
+

-
-
-
-
-
-
+
+
+
+
+
+







static int
PanedWindowWidgetObjCmd(
    ClientData clientData,	/* Information about square widget. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj * const objv[])	/* Argument objects. */
{
    PanedWindow *pwPtr = clientData;
    PanedWindow *pwPtr = (PanedWindow *)clientData;
    int result = TCL_OK;
    static const char *const optionStrings[] = {
	"add", "cget", "configure", "forget", "identify", "panecget",
	"paneconfigure", "panes", "proxy", "sash", NULL
    };
    enum options {
	PW_ADD, PW_CGET, PW_CONFIGURE, PW_FORGET, PW_IDENTIFY, PW_PANECGET,
	PW_PANECONFIGURE, PW_PANES, PW_PROXY, PW_SASH
    };
    Tcl_Obj *resultObj;
    int index, count, i, x, y;
    Tk_Window tkwin;
    Slave *slavePtr;
    Pane *panePtr;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg...?");
	Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
	return TCL_ERROR;
    }

    if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "command",
	    0, &index) != TCL_OK) {
	return TCL_ERROR;
    }

    Tcl_Preserve(pwPtr);

    switch ((enum options) index) {
    case PW_ADD:
	if (objc < 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "widget ?widget ...?");
	    result = TCL_ERROR;
	    break;
	}
	result = ConfigureSlaves(pwPtr, interp, objc, objv);
	result = ConfigurePanes(pwPtr, interp, objc, objv);
	break;

    case PW_CGET:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "option");
	    result = TCL_ERROR;
	    break;
	}
	resultObj = Tk_GetOptionValue(interp, (char *) pwPtr,
	resultObj = Tk_GetOptionValue(interp, pwPtr,
		pwPtr->optionTable, objv[2], pwPtr->tkwin);
	if (resultObj == NULL) {
	    result = TCL_ERROR;
	} else {
	    Tcl_SetObjResult(interp, resultObj);
	}
	break;

    case PW_CONFIGURE:
	resultObj = NULL;
	if (objc <= 3) {
	    resultObj = Tk_GetOptionInfo(interp, (char *) pwPtr,
	    resultObj = Tk_GetOptionInfo(interp, pwPtr,
		    pwPtr->optionTable,
		    (objc == 3) ? objv[2] : NULL, pwPtr->tkwin);
	    if (resultObj == NULL) {
		result = TCL_ERROR;
	    } else {
		Tcl_SetObjResult(interp, resultObj);
	    }
	} else {
	    result = ConfigurePanedWindow(interp, pwPtr, objc - 2, objv + 2);
	}
	break;

    case PW_FORGET: {
	int i;

	if (objc < 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "widget ?widget ...?");
	    result = TCL_ERROR;
	    break;
	}

	/*
	 * Clean up each window named in the arg list.
	 */
	for (count = 0, i = 2; i < objc; i++) {
	    Tk_Window slave = Tk_NameToWindow(interp, Tcl_GetString(objv[i]),
	    Tk_Window pane = Tk_NameToWindow(interp, Tcl_GetString(objv[i]),
		    pwPtr->tkwin);

	    if (slave == NULL) {
	    if (pane == NULL) {
		continue;
	    }
	    slavePtr = GetPane(pwPtr, slave);
	    if ((slavePtr != NULL) && (slavePtr->masterPtr != NULL)) {
	    panePtr = GetPane(pwPtr, pane);
	    if ((panePtr != NULL) && (panePtr->containerPtr != NULL)) {
		count++;
		Tk_ManageGeometry(slave, NULL, NULL);
		Tk_UnmaintainGeometry(slavePtr->tkwin, pwPtr->tkwin);
		Tk_DeleteEventHandler(slavePtr->tkwin, StructureNotifyMask,
			SlaveStructureProc, slavePtr);
		Tk_UnmapWindow(slavePtr->tkwin);
		Unlink(slavePtr);
		Tk_ManageGeometry(pane, NULL, NULL);
		Tk_UnmaintainGeometry(panePtr->tkwin, pwPtr->tkwin);
		Tk_DeleteEventHandler(panePtr->tkwin, StructureNotifyMask,
			PaneStructureProc, panePtr);
		Tk_UnmapWindow(panePtr->tkwin);
		Unlink(panePtr);
	    }
	    if (count != 0) {
		ComputeGeometry(pwPtr);
	    }
	}
	break;
    }
662
663
664
665
666
667
668
669
670


671
672

673
674
675
676
677

678
679
680
681
682
683
684
685
686
687
688
689
690
691
692

693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710


711
712

713
714
715
716
717
718
719
720
721
722
723
724

725
726
727
728
729
730

731
732

733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752

753
754

755
756
757
758
759
760
761


762
763
764
765
766
767

768
769
770
771
772
773

774
775
776
777


778
779
780
781
782

783
784
785
786
787
788
789
661
662
663
664
665
666
667


668
669
670

671
672
673
674
675

676
677
678
679
680
681
682
683
684
685
686
687
688
689
690

691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707


708
709
710

711
712
713
714
715
716
717
718
719
720
721
722

723
724
725
726
727
728

729
730

731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750

751
752

753
754
755
756
757
758


759
760
761
762
763
764
765

766
767
768
769
770
771

772
773
774


775
776
777
778
779
780

781
782
783
784
785
786
787
788







-
-
+
+

-
+




-
+














-
+
















-
-
+
+

-
+











-
+





-
+

-
+



















-
+

-
+





-
-
+
+





-
+





-
+


-
-
+
+




-
+







	}
	tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), pwPtr->tkwin);
	if (tkwin == NULL) {
	    result = TCL_ERROR;
	    break;
	}
	resultObj = NULL;
	for (i = 0; i < pwPtr->numSlaves; i++) {
	    if (pwPtr->slaves[i]->tkwin == tkwin) {
	for (i = 0; i < pwPtr->numPanes; i++) {
	    if (pwPtr->panes[i]->tkwin == tkwin) {
		resultObj = Tk_GetOptionValue(interp,
			(char *) pwPtr->slaves[i], pwPtr->slaveOpts,
			pwPtr->panes[i], pwPtr->paneOpts,
			objv[3], tkwin);
	    }
	}
	if (resultObj == NULL) {
	    if (i == pwPtr->numSlaves) {
	    if (i == pwPtr->numPanes) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"not managed by this window", -1));
		Tcl_SetErrorCode(interp, "TK", "PANEDWINDOW", "UNMANAGED",
			NULL);
	    }
	    result = TCL_ERROR;
	} else {
	    Tcl_SetObjResult(interp, resultObj);
	}
	break;

    case PW_PANECONFIGURE:
	if (objc < 3) {
	    Tcl_WrongNumArgs(interp, 2, objv,
		    "pane ?option? ?value option value ...?");
		    "pane ?-option value ...?");
	    result = TCL_ERROR;
	    break;
	}
	resultObj = NULL;
	if (objc <= 4) {
	    tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[2]),
		    pwPtr->tkwin);
            if (tkwin == NULL) {
                /*
                 * Just a plain old bad window; Tk_NameToWindow filled in an
                 * error message for us.
                 */

                result = TCL_ERROR;
                break;
            }
	    for (i = 0; i < pwPtr->numSlaves; i++) {
		if (pwPtr->slaves[i]->tkwin == tkwin) {
	    for (i = 0; i < pwPtr->numPanes; i++) {
		if (pwPtr->panes[i]->tkwin == tkwin) {
		    resultObj = Tk_GetOptionInfo(interp,
			    (char *) pwPtr->slaves[i], pwPtr->slaveOpts,
			    pwPtr->panes[i], pwPtr->paneOpts,
			    (objc == 4) ? objv[3] : NULL,
			    pwPtr->tkwin);
		    if (resultObj == NULL) {
			result = TCL_ERROR;
		    } else {
			Tcl_SetObjResult(interp, resultObj);
		    }
		    break;
		}
	    }
	} else {
	    result = ConfigureSlaves(pwPtr, interp, objc, objv);
	    result = ConfigurePanes(pwPtr, interp, objc, objv);
	}
	break;

    case PW_PANES:
	resultObj = Tcl_NewObj();
	for (i = 0; i < pwPtr->numSlaves; i++) {
	for (i = 0; i < pwPtr->numPanes; i++) {
	    Tcl_ListObjAppendElement(NULL, resultObj,
		    TkNewWindowObj(pwPtr->slaves[i]->tkwin));
		    Tk_NewWindowObj(pwPtr->panes[i]->tkwin));
	}
	Tcl_SetObjResult(interp, resultObj);
	break;

    case PW_PROXY:
	result = PanedWindowProxyCommand(pwPtr, interp, objc, objv);
	break;

    case PW_SASH:
	result = PanedWindowSashCommand(pwPtr, interp, objc, objv);
	break;
    }
    Tcl_Release(pwPtr);
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * ConfigureSlaves --
 * ConfigurePanes --
 *
 *	Add or alter the configuration options of a slave in a paned window.
 *	Add or alter the configuration options of a pane in a paned window.
 *
 * Results:
 *	Standard Tcl result.
 *
 * Side effects:
 *	Depends on options; may add a slave to the paned window, may alter the
 *	geometry management options of a slave.
 *	Depends on options; may add a pane to the paned window, may alter the
 *	geometry management options of a pane.
 *
 *----------------------------------------------------------------------
 */

static int
ConfigureSlaves(
ConfigurePanes(
    PanedWindow *pwPtr,		/* Information about paned window. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int i, firstOptionArg, j, found, doubleBw, index, numNewSlaves, haveLoc;
    int i, firstOptionArg, j, found, doubleBw, index, numNewPanes, haveLoc;
    int insertIndex;
    Tk_Window tkwin = NULL, ancestor, parent;
    Slave *slavePtr, **inserts, **newSlaves;
    Slave options;
    Pane *panePtr, **inserts, **newPanes;
    Pane options;
    const char *arg;

    /*
     * Find the non-window name arguments; these are the configure options for
     * the slaves. Also validate that the window names given are legitimate
     * the panes. Also validate that the window names given are legitimate
     * (ie, they are real windows, they are not the panedwindow itself, etc.).
     */

    for (i = 2; i < objc; i++) {
	arg = Tcl_GetString(objv[i]);
	if (arg[0] == '-') {
	    break;
813
814
815
816
817
818
819
820
821


822
823
824
825
826
827
828
812
813
814
815
816
817
818


819
820
821
822
823
824
825
826
827







-
-
+
+







		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"can't add toplevel %s to %s", arg,
			Tk_PathName(pwPtr->tkwin)));
		Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "TOPLEVEL", NULL);
		return TCL_ERROR;
	    } else {
		/*
		 * Make sure the panedwindow is the parent of the slave,
		 * or a descendant of the slave's parent.
		 * Make sure the panedwindow is the parent of the pane,
		 * or a descendant of the pane's parent.
		 */

		parent = Tk_Parent(tkwin);
		for (ancestor = pwPtr->tkwin;;ancestor = Tk_Parent(ancestor)) {
		    if (ancestor == parent) {
			break;
		    }
843
844
845
846
847
848
849
850
851


852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869


870
871
872
873
874
875
876
877
878


879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895

896
897
898
899
900
901

902
903
904
905
906

907
908
909
910

911
912
913


914
915
916

917
918
919
920
921
922
923
924
925
926
927
928
929




930
931
932


933
934
935
936
937

938
939
940
941
942
943


944
945
946
947
948
949
950
951
952
953
954

955
956
957
958
959
960
961
962
963
964
965
966
967
968
969

970
971
972
973
974
975



976
977

978
979
980
981
982
983
984





985
986

987
988
989


990
991

992
993
994


995
996
997
998

999
1000
1001
1002
1003
1004
1005





1006
1007
1008
1009

1010
1011
1012
1013
1014



1015
1016
1017

1018
1019
1020
1021
1022
1023




1024
1025
1026

1027
1028

1029
1030

1031
1032
1033
1034
1035
1036


1037
1038
1039
1040
1041

1042
1043
1044
1045
1046



1047
1048
1049
1050
1051
1052
1053

1054
1055
1056

1057
1058

1059
1060
1061

1062
1063
1064

1065
1066

1067
1068
1069
1070
1071
1072
1073
842
843
844
845
846
847
848


849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866


867
868
869
870
871
872
873
874
875


876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893

894
895
896
897
898
899

900
901
902
903
904

905
906
907
908

909
910


911
912
913
914

915
916
917
918
919
920
921
922
923
924




925
926
927
928
929


930
931
932
933
934
935

936
937
938
939
940


941
942
943
944
945
946
947
948
949
950
951
952

953
954
955
956
957
958
959
960
961
962
963
964
965
966
967

968
969
970
971



972
973
974
975

976
977
978





979
980
981
982
983
984

985
986


987
988
989

990
991


992
993
994
995
996

997
998
999





1000
1001
1002
1003
1004
1005
1006
1007

1008
1009
1010



1011
1012
1013
1014
1015

1016
1017
1018




1019
1020
1021
1022
1023
1024

1025
1026

1027
1028

1029
1030
1031
1032
1033


1034
1035
1036
1037
1038
1039

1040
1041
1042



1043
1044
1045
1046
1047
1048
1049
1050
1051

1052
1053
1054

1055
1056

1057
1058
1059

1060
1061
1062

1063
1064

1065
1066
1067
1068
1069
1070
1071
1072







-
-
+
+
















-
-
+
+







-
-
+
+
















-
+





-
+




-
+



-
+

-
-
+
+


-
+









-
-
-
-
+
+
+
+

-
-
+
+




-
+




-
-
+
+










-
+














-
+



-
-
-
+
+
+

-
+


-
-
-
-
-
+
+
+
+
+

-
+

-
-
+
+

-
+

-
-
+
+



-
+


-
-
-
-
-
+
+
+
+
+



-
+


-
-
-
+
+
+


-
+


-
-
-
-
+
+
+
+


-
+

-
+

-
+




-
-
+
+




-
+


-
-
-
+
+
+






-
+


-
+

-
+


-
+


-
+

-
+







    /*
     * Pre-parse the configuration options, to get the before/after specifiers
     * into an easy-to-find location (a local variable). Also, check the
     * return from Tk_SetOptions once, here, so we can save a little bit of
     * extra testing in the for loop below.
     */

    memset((void *)&options, 0, sizeof(Slave));
    if (Tk_SetOptions(interp, (char *) &options, pwPtr->slaveOpts,
    memset((void *)&options, 0, sizeof(Pane));
    if (Tk_SetOptions(interp, &options, pwPtr->paneOpts,
	    objc - firstOptionArg, objv + firstOptionArg,
	    pwPtr->tkwin, NULL, NULL) != TCL_OK) {
	return TCL_ERROR;
    }

    /*
     * If either -after or -before was given, find the numerical index that
     * corresponds to the given window. If both -after and -before are given,
     * the option precedence is: -after, then -before.
     */

    index = -1;
    haveLoc = 0;
    if (options.after != NULL) {
	tkwin = options.after;
	haveLoc = 1;
	for (i = 0; i < pwPtr->numSlaves; i++) {
	    if (options.after == pwPtr->slaves[i]->tkwin) {
	for (i = 0; i < pwPtr->numPanes; i++) {
	    if (options.after == pwPtr->panes[i]->tkwin) {
		index = i + 1;
		break;
	    }
	}
    } else if (options.before != NULL) {
	tkwin = options.before;
	haveLoc = 1;
	for (i = 0; i < pwPtr->numSlaves; i++) {
	    if (options.before == pwPtr->slaves[i]->tkwin) {
	for (i = 0; i < pwPtr->numPanes; i++) {
	    if (options.before == pwPtr->panes[i]->tkwin) {
		index = i;
		break;
	    }
	}
    }

    /*
     * If a window was given for -after/-before, but it's not a window managed
     * by the panedwindow, throw an error
     */

    if (haveLoc && index == -1) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"window \"%s\" is not managed by %s",
		Tk_PathName(tkwin), Tk_PathName(pwPtr->tkwin)));
	Tcl_SetErrorCode(interp, "TK", "PANEDWINDOW", "UNMANAGED", NULL);
	Tk_FreeConfigOptions((char *) &options, pwPtr->slaveOpts,
	Tk_FreeConfigOptions((char *) &options, pwPtr->paneOpts,
		pwPtr->tkwin);
	return TCL_ERROR;
    }

    /*
     * Allocate an array to hold, in order, the pointers to the slave
     * Allocate an array to hold, in order, the pointers to the pane
     * structures corresponding to the windows specified. Some of those
     * structures may already have existed, some may be new.
     */

    inserts = ckalloc(sizeof(Slave *) * (firstOptionArg - 2));
    inserts = (Pane **)ckalloc(sizeof(Pane *) * (firstOptionArg - 2));
    insertIndex = 0;

    /*
     * Populate the inserts array, creating new slave structures as necessary,
     * Populate the inserts array, creating new pane structures as necessary,
     * applying the options to each structure as we go, and, if necessary,
     * marking the spot in the original slaves array as empty (for
     * pre-existing slave structures).
     * marking the spot in the original panes array as empty (for
     * pre-existing pane structures).
     */

    for (i = 0, numNewSlaves = 0; i < firstOptionArg - 2; i++) {
    for (i = 0, numNewPanes = 0; i < firstOptionArg - 2; i++) {
	/*
	 * We don't check that tkwin is NULL here, because the pre-pass above
	 * guarantees that the input at this stage is good.
	 */

	tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[i + 2]),
		pwPtr->tkwin);

	found = 0;
	for (j = 0; j < pwPtr->numSlaves; j++) {
	    if (pwPtr->slaves[j] != NULL && pwPtr->slaves[j]->tkwin == tkwin) {
		Tk_SetOptions(interp, (char *) pwPtr->slaves[j],
			pwPtr->slaveOpts, objc - firstOptionArg,
	for (j = 0; j < pwPtr->numPanes; j++) {
	    if (pwPtr->panes[j] != NULL && pwPtr->panes[j]->tkwin == tkwin) {
		Tk_SetOptions(interp, pwPtr->panes[j],
			pwPtr->paneOpts, objc - firstOptionArg,
			objv + firstOptionArg, pwPtr->tkwin, NULL, NULL);
		if (pwPtr->slaves[j]->minSize < 0) {
		    pwPtr->slaves[j]->minSize = 0;
		if (pwPtr->panes[j]->minSize < 0) {
		    pwPtr->panes[j]->minSize = 0;
		}
		found = 1;

		/*
		 * If the slave is supposed to move, add it to the inserts
		 * If the pane is supposed to move, add it to the inserts
		 * array now; otherwise, leave it where it is.
		 */

		if (index != -1) {
		    inserts[insertIndex++] = pwPtr->slaves[j];
		    pwPtr->slaves[j] = NULL;
		    inserts[insertIndex++] = pwPtr->panes[j];
		    pwPtr->panes[j] = NULL;
		}
		break;
	    }
	}

	if (found) {
	    continue;
	}

	/*
	 * Make sure this slave wasn't already put into the inserts array,
	 * Make sure this pane wasn't already put into the inserts array,
	 * i.e., when the user specifies the same window multiple times in a
	 * single add commaned.
	 */
	for (j = 0; j < insertIndex; j++) {
	    if (inserts[j]->tkwin == tkwin) {
		found = 1;
		break;
	    }
	}
	if (found) {
	    continue;
	}

	/*
	 * Create a new slave structure and initialize it. All slaves start
	 * Create a new pane structure and initialize it. All panes start
	 * out with their "natural" dimensions.
	 */

	slavePtr = ckalloc(sizeof(Slave));
	memset(slavePtr, 0, sizeof(Slave));
	Tk_InitOptions(interp, (char *)slavePtr, pwPtr->slaveOpts,
	panePtr = (Pane *)ckalloc(sizeof(Pane));
	memset(panePtr, 0, sizeof(Pane));
	Tk_InitOptions(interp, panePtr, pwPtr->paneOpts,
		pwPtr->tkwin);
	Tk_SetOptions(interp, (char *)slavePtr, pwPtr->slaveOpts,
	Tk_SetOptions(interp, panePtr, pwPtr->paneOpts,
		objc - firstOptionArg, objv + firstOptionArg,
		pwPtr->tkwin, NULL, NULL);
	slavePtr->tkwin = tkwin;
	slavePtr->masterPtr = pwPtr;
	doubleBw = 2 * Tk_Changes(slavePtr->tkwin)->border_width;
	if (slavePtr->width > 0) {
	    slavePtr->paneWidth = slavePtr->width;
	panePtr->tkwin = tkwin;
	panePtr->containerPtr = pwPtr;
	doubleBw = 2 * Tk_Changes(panePtr->tkwin)->border_width;
	if (panePtr->width > 0) {
	    panePtr->paneWidth = panePtr->width;
	} else {
	    slavePtr->paneWidth = Tk_ReqWidth(tkwin) + doubleBw;
	    panePtr->paneWidth = Tk_ReqWidth(tkwin) + doubleBw;
	}
	if (slavePtr->height > 0) {
	    slavePtr->paneHeight = slavePtr->height;
	if (panePtr->height > 0) {
	    panePtr->paneHeight = panePtr->height;
	} else {
	    slavePtr->paneHeight = Tk_ReqHeight(tkwin) + doubleBw;
	    panePtr->paneHeight = Tk_ReqHeight(tkwin) + doubleBw;
	}
	if (slavePtr->minSize < 0) {
	    slavePtr->minSize = 0;
	if (panePtr->minSize < 0) {
	    panePtr->minSize = 0;
	}

	/*
	 * Set up the geometry management callbacks for this slave.
	 * Set up the geometry management callbacks for this pane.
	 */

	Tk_CreateEventHandler(slavePtr->tkwin, StructureNotifyMask,
		SlaveStructureProc, slavePtr);
	Tk_ManageGeometry(slavePtr->tkwin, &panedWindowMgrType, slavePtr);
	inserts[insertIndex++] = slavePtr;
	numNewSlaves++;
	Tk_CreateEventHandler(panePtr->tkwin, StructureNotifyMask,
		PaneStructureProc, panePtr);
	Tk_ManageGeometry(panePtr->tkwin, &panedWindowMgrType, panePtr);
	inserts[insertIndex++] = panePtr;
	numNewPanes++;
    }

    /*
     * Allocate the new slaves array, then copy the slaves into it, in order.
     * Allocate the new panes array, then copy the panes into it, in order.
     */

    i = sizeof(Slave *) * (pwPtr->numSlaves + numNewSlaves);
    newSlaves = ckalloc(i);
    memset(newSlaves, 0, (size_t) i);
    i = sizeof(Pane *) * (pwPtr->numPanes + numNewPanes);
    newPanes = (Pane **)ckalloc(i);
    memset(newPanes, 0, i);
    if (index == -1) {
	/*
	 * If none of the existing slaves have to be moved, just copy the old
	 * If none of the existing panes have to be moved, just copy the old
	 * and append the new.
	 */
	memcpy((void *)&(newSlaves[0]), pwPtr->slaves,
		sizeof(Slave *) * pwPtr->numSlaves);
	memcpy((void *)&(newSlaves[pwPtr->numSlaves]), inserts,
		sizeof(Slave *) * numNewSlaves);
	memcpy((void *)&(newPanes[0]), pwPtr->panes,
		sizeof(Pane *) * pwPtr->numPanes);
	memcpy((void *)&(newPanes[pwPtr->numPanes]), inserts,
		sizeof(Pane *) * numNewPanes);
    } else {
	/*
	 * If some of the existing slaves were moved, the old slaves array
	 * If some of the existing panes were moved, the old panes array
	 * will be partially populated, with some valid and some invalid
	 * entries. Walk through it, copying valid entries to the new slaves
	 * entries. Walk through it, copying valid entries to the new panes
	 * array as we go; when we get to the insert location for the new
	 * slaves, copy the inserts array over, then finish off the old slaves
	 * panes, copy the inserts array over, then finish off the old panes
	 * array.
	 */

	for (i = 0, j = 0; i < index; i++) {
	    if (pwPtr->slaves[i] != NULL) {
		newSlaves[j] = pwPtr->slaves[i];
	    if (pwPtr->panes[i] != NULL) {
		newPanes[j] = pwPtr->panes[i];
		j++;
	    }
	}

	memcpy((void *)&(newSlaves[j]), inserts, sizeof(Slave *)*insertIndex);
	memcpy((void *)&(newPanes[j]), inserts, sizeof(Pane *)*insertIndex);
	j += firstOptionArg - 2;

	for (i = index; i < pwPtr->numSlaves; i++) {
	    if (pwPtr->slaves[i] != NULL) {
		newSlaves[j] = pwPtr->slaves[i];
	for (i = index; i < pwPtr->numPanes; i++) {
	    if (pwPtr->panes[i] != NULL) {
		newPanes[j] = pwPtr->panes[i];
		j++;
	    }
	}
    }

    /*
     * Make the new slaves array the paned window's slave array, and clean up.
     * Make the new panes array the paned window's pane array, and clean up.
     */

    ckfree(pwPtr->slaves);
    ckfree(pwPtr->panes);
    ckfree(inserts);
    pwPtr->slaves = newSlaves;
    pwPtr->panes = newPanes;

    /*
     * Set the paned window's slave count to the new value.
     * Set the paned window's pane count to the new value.
     */

    pwPtr->numSlaves += numNewSlaves;
    pwPtr->numPanes += numNewPanes;

    Tk_FreeConfigOptions((char *) &options, pwPtr->slaveOpts, pwPtr->tkwin);
    Tk_FreeConfigOptions((char *) &options, pwPtr->paneOpts, pwPtr->tkwin);

    ComputeGeometry(pwPtr);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
1097
1098
1099
1100
1101
1102
1103
1104

1105
1106
1107
1108
1109
1110
1111
1096
1097
1098
1099
1100
1101
1102

1103
1104
1105
1106
1107
1108
1109
1110







-
+







	"coord", "dragto", "mark", "place", NULL
    };
    enum sashOptions {
	SASH_COORD, SASH_DRAGTO, SASH_MARK, SASH_PLACE
    };
    int index, sash, x, y, diff;
    Tcl_Obj *coords[2];
    Slave *slavePtr;
    Pane *panePtr;

    if (objc < 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "option ?arg ...?");
	return TCL_ERROR;
    }

    if (Tcl_GetIndexFromObj(interp, objv[2], sashOptionStrings, "option", 0,
1126
1127
1128
1129
1130
1131
1132
1133

1134
1135
1136


1137
1138
1139
1140
1141
1142
1143
1125
1126
1127
1128
1129
1130
1131

1132
1133


1134
1135
1136
1137
1138
1139
1140
1141
1142







-
+

-
-
+
+








	if (!ValidSashIndex(pwPtr, sash)) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "invalid sash index", -1));
	    Tcl_SetErrorCode(interp, "TK", "VALUE", "SASH_INDEX", NULL);
	    return TCL_ERROR;
	}
	slavePtr = pwPtr->slaves[sash];
	panePtr = pwPtr->panes[sash];

	coords[0] = Tcl_NewIntObj(slavePtr->sashx);
	coords[1] = Tcl_NewIntObj(slavePtr->sashy);
	coords[0] = Tcl_NewWideIntObj(panePtr->sashx);
	coords[1] = Tcl_NewWideIntObj(panePtr->sashy);
	Tcl_SetObjResult(interp, Tcl_NewListObj(2, coords));
	break;

    case SASH_MARK:
	if (objc != 6 && objc != 4) {
	    Tcl_WrongNumArgs(interp, 3, objv, "index ?x y?");
	    return TCL_ERROR;
1159
1160
1161
1162
1163
1164
1165
1166
1167


1168
1169
1170


1171
1172
1173
1174
1175
1176
1177
1158
1159
1160
1161
1162
1163
1164


1165
1166
1167


1168
1169
1170
1171
1172
1173
1174
1175
1176







-
-
+
+

-
-
+
+







		return TCL_ERROR;
	    }

	    if (Tcl_GetIntFromObj(interp, objv[5], &y) != TCL_OK) {
		return TCL_ERROR;
	    }

	    pwPtr->slaves[sash]->markx = x;
	    pwPtr->slaves[sash]->marky = y;
	    pwPtr->panes[sash]->markx = x;
	    pwPtr->panes[sash]->marky = y;
	} else {
	    coords[0] = Tcl_NewIntObj(pwPtr->slaves[sash]->markx);
	    coords[1] = Tcl_NewIntObj(pwPtr->slaves[sash]->marky);
	    coords[0] = Tcl_NewWideIntObj(pwPtr->panes[sash]->markx);
	    coords[1] = Tcl_NewWideIntObj(pwPtr->panes[sash]->marky);
	    Tcl_SetObjResult(interp, Tcl_NewListObj(2, coords));
	}
	break;

    case SASH_DRAGTO:
    case SASH_PLACE:
	if (objc != 6) {
1194
1195
1196
1197
1198
1199
1200
1201

1202
1203
1204

1205
1206

1207
1208
1209
1210

1211
1212

1213
1214
1215
1216
1217
1218
1219
1193
1194
1195
1196
1197
1198
1199

1200
1201
1202

1203
1204

1205
1206
1207
1208

1209
1210

1211
1212
1213
1214
1215
1216
1217
1218







-
+


-
+

-
+



-
+

-
+







	    return TCL_ERROR;
	}

	if (Tcl_GetIntFromObj(interp, objv[5], &y) != TCL_OK) {
	    return TCL_ERROR;
	}

	slavePtr = pwPtr->slaves[sash];
	panePtr = pwPtr->panes[sash];
	if (pwPtr->orient == ORIENT_HORIZONTAL) {
	    if (index == SASH_PLACE) {
		diff = x - pwPtr->slaves[sash]->sashx;
		diff = x - pwPtr->panes[sash]->sashx;
	    } else {
		diff = x - pwPtr->slaves[sash]->markx;
		diff = x - pwPtr->panes[sash]->markx;
	    }
	} else {
	    if (index == SASH_PLACE) {
		diff = y - pwPtr->slaves[sash]->sashy;
		diff = y - pwPtr->panes[sash]->sashy;
	    } else {
		diff = y - pwPtr->slaves[sash]->marky;
		diff = y - pwPtr->panes[sash]->marky;
	    }
	}

	MoveSash(pwPtr, sash, diff);
	ComputeGeometry(pwPtr);
    }
    return TCL_OK;
1245
1246
1247
1248
1249
1250
1251
1252

1253
1254
1255
1256
1257
1258
1259
1244
1245
1246
1247
1248
1249
1250

1251
1252
1253
1254
1255
1256
1257
1258







-
+







    PanedWindow *pwPtr,		/* Information about widget. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument values. */
{
    Tk_SavedOptions savedOptions;
    int typemask = 0;

    if (Tk_SetOptions(interp, (char *) pwPtr, pwPtr->optionTable, objc, objv,
    if (Tk_SetOptions(interp, pwPtr, pwPtr->optionTable, objc, objv,
	    pwPtr->tkwin, &savedOptions, &typemask) != TCL_OK) {
	Tk_RestoreSavedOptions(&savedOptions);
	return TCL_ERROR;
    }

    Tk_FreeSavedOptions(&savedOptions);

1291
1292
1293
1294
1295
1296
1297
1298

1299
1300
1301
1302
1303
1304
1305
1290
1291
1292
1293
1294
1295
1296

1297
1298
1299
1300
1301
1302
1303
1304







-
+








static void
PanedWindowWorldChanged(
    ClientData instanceData)	/* Information about the paned window. */
{
    XGCValues gcValues;
    GC newGC;
    PanedWindow *pwPtr = instanceData;
    PanedWindow *pwPtr = (PanedWindow *)instanceData;

    /*
     * Allocated a graphics context for drawing the paned window widget
     * elements (background, sashes, etc.) and set the window background.
     */

    gcValues.background = Tk_3DBorderColor(pwPtr->background)->pixel;
1348
1349
1350
1351
1352
1353
1354
1355

1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374



1375
1376
1377
1378
1379
1380



1381
1382
1383
1384
1385
1386
1387
1347
1348
1349
1350
1351
1352
1353

1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370



1371
1372
1373
1374
1375
1376



1377
1378
1379
1380
1381
1382
1383
1384
1385
1386







-
+
















-
-
-
+
+
+



-
-
-
+
+
+







 */

static void
PanedWindowEventProc(
    ClientData clientData,	/* Information about window. */
    XEvent *eventPtr)		/* Information about event. */
{
    PanedWindow *pwPtr = clientData;
    PanedWindow *pwPtr = (PanedWindow *)clientData;
    int i;

    if (eventPtr->type == Expose) {
	if (pwPtr->tkwin != NULL && !(pwPtr->flags & REDRAW_PENDING)) {
	    Tcl_DoWhenIdle(DisplayPanedWindow, pwPtr);
	    pwPtr->flags |= REDRAW_PENDING;
	}
    } else if (eventPtr->type == ConfigureNotify) {
	pwPtr->flags |= REQUESTED_RELAYOUT;
	if (pwPtr->tkwin != NULL && !(pwPtr->flags & REDRAW_PENDING)) {
	    Tcl_DoWhenIdle(DisplayPanedWindow, pwPtr);
	    pwPtr->flags |= REDRAW_PENDING;
	}
    } else if (eventPtr->type == DestroyNotify) {
	DestroyPanedWindow(pwPtr);
    } else if (eventPtr->type == UnmapNotify) {
        for (i = 0; i < pwPtr->numSlaves; i++) {
            if (!pwPtr->slaves[i]->hide) {
                Tk_UnmapWindow(pwPtr->slaves[i]->tkwin);
        for (i = 0; i < pwPtr->numPanes; i++) {
            if (!pwPtr->panes[i]->hide) {
                Tk_UnmapWindow(pwPtr->panes[i]->tkwin);
            }
        }
    } else if (eventPtr->type == MapNotify) {
        for (i = 0; i < pwPtr->numSlaves; i++) {
            if (!pwPtr->slaves[i]->hide) {
                Tk_MapWindow(pwPtr->slaves[i]->tkwin);
        for (i = 0; i < pwPtr->numPanes; i++) {
            if (!pwPtr->panes[i]->hide) {
                Tk_MapWindow(pwPtr->panes[i]->tkwin);
            }
        }
    }
}

/*
 *----------------------------------------------------------------------
1401
1402
1403
1404
1405
1406
1407
1408

1409
1410
1411
1412
1413
1414
1415
1400
1401
1402
1403
1404
1405
1406

1407
1408
1409
1410
1411
1412
1413
1414







-
+







 *----------------------------------------------------------------------
 */

static void
PanedWindowCmdDeletedProc(
    ClientData clientData)	/* Pointer to widget record for widget. */
{
    PanedWindow *pwPtr = clientData;
    PanedWindow *pwPtr = (PanedWindow *)clientData;

    /*
     * This function could be invoked either because the window was destroyed
     * and the command was then deleted or because the command was deleted,
     * and then this function destroys the widget. The WIDGET_DELETED flag
     * distinguishes these cases.
     */
1438
1439
1440
1441
1442
1443
1444
1445
1446


1447
1448
1449
1450
1451
1452
1453
1437
1438
1439
1440
1441
1442
1443


1444
1445
1446
1447
1448
1449
1450
1451
1452







-
-
+
+







 *--------------------------------------------------------------
 */

static void
DisplayPanedWindow(
    ClientData clientData)	/* Information about window. */
{
    PanedWindow *pwPtr = clientData;
    Slave *slavePtr;
    PanedWindow *pwPtr = (PanedWindow *)clientData;
    Pane *panePtr;
    Pixmap pixmap;
    Tk_Window tkwin = pwPtr->tkwin;
    int i, sashWidth, sashHeight;
    const int horizontal = (pwPtr->orient == ORIENT_HORIZONTAL);
    int first, last;

    pwPtr->flags &= ~REDRAW_PENDING;
1480
1481
1482
1483
1484
1485
1486
1487

1488
1489
1490

1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501



1502
1503
1504
1505
1506

1507
1508
1509
1510
1511

1512
1513
1514
1515
1516
1517
1518
1479
1480
1481
1482
1483
1484
1485

1486
1487
1488

1489
1490
1491
1492
1493
1494
1495
1496
1497



1498
1499
1500
1501
1502
1503
1504

1505
1506
1507
1508
1509

1510
1511
1512
1513
1514
1515
1516
1517







-
+


-
+








-
-
-
+
+
+




-
+




-
+








    /*
     * Set up boilerplate geometry values for sashes (width, height, common
     * coordinates).
     */

    if (horizontal) {
	sashHeight = Tk_Height(tkwin) - (2 * Tk_InternalBorderWidth(tkwin));
	sashHeight = Tk_Height(tkwin) - (2 * Tk_InternalBorderLeft(tkwin));
	sashWidth = pwPtr->sashWidth;
    } else {
	sashWidth = Tk_Width(tkwin) - (2 * Tk_InternalBorderWidth(tkwin));
	sashWidth = Tk_Width(tkwin) - (2 * Tk_InternalBorderLeft(tkwin));
	sashHeight = pwPtr->sashWidth;
    }

    /*
     * Draw the sashes.
     */

    GetFirstLastVisiblePane(pwPtr, &first, &last);
    for (i = 0; i < pwPtr->numSlaves - 1; i++) {
	slavePtr = pwPtr->slaves[i];
	if (slavePtr->hide || i == last) {
    for (i = 0; i < pwPtr->numPanes - 1; i++) {
	panePtr = pwPtr->panes[i];
	if (panePtr->hide || i == last) {
	    continue;
	}
	if (sashWidth > 0 && sashHeight > 0) {
	    Tk_Fill3DRectangle(tkwin, pixmap, pwPtr->background,
		    slavePtr->sashx, slavePtr->sashy, sashWidth, sashHeight,
		    panePtr->sashx, panePtr->sashy, sashWidth, sashHeight,
		    1, pwPtr->sashRelief);
	}
	if (pwPtr->showHandle) {
	    Tk_Fill3DRectangle(tkwin, pixmap, pwPtr->background,
		    slavePtr->handlex, slavePtr->handley,
		    panePtr->handlex, panePtr->handley,
		    pwPtr->handleSize, pwPtr->handleSize, 1,
		    TK_RELIEF_RAISED);
	}
    }

#ifndef TK_NO_DOUBLE_BUFFERING
    /*
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575




1576
1577
1578
1579
1580
1581
1582





1583
1584
1585


1586
1587
1588


1589
1590
1591
1592
1593
1594
1595
1564
1565
1566
1567
1568
1569
1570




1571
1572
1573
1574
1575
1576





1577
1578
1579
1580
1581
1582


1583
1584
1585


1586
1587
1588
1589
1590
1591
1592
1593
1594







-
-
-
-
+
+
+
+


-
-
-
-
-
+
+
+
+
+

-
-
+
+

-
-
+
+







	Tcl_CancelIdleCall(DisplayPanedWindow, pwPtr);
    }
    if (pwPtr->flags & RESIZE_PENDING) {
	Tcl_CancelIdleCall(ArrangePanes, pwPtr);
    }

    /*
     * Clean up the slave list; foreach slave:
     *  o  Cancel the slave's structure notification callback
     *  o  Cancel geometry management for the slave.
     *  o  Free memory for the slave
     * Clean up the pane list; foreach pane:
     *  o  Cancel the pane's structure notification callback
     *  o  Cancel geometry management for the pane.
     *  o  Free memory for the pane
     */

    for (i = 0; i < pwPtr->numSlaves; i++) {
	Tk_DeleteEventHandler(pwPtr->slaves[i]->tkwin, StructureNotifyMask,
		SlaveStructureProc, pwPtr->slaves[i]);
	Tk_ManageGeometry(pwPtr->slaves[i]->tkwin, NULL, NULL);
	Tk_FreeConfigOptions((char *) pwPtr->slaves[i], pwPtr->slaveOpts,
    for (i = 0; i < pwPtr->numPanes; i++) {
	Tk_DeleteEventHandler(pwPtr->panes[i]->tkwin, StructureNotifyMask,
		PaneStructureProc, pwPtr->panes[i]);
	Tk_ManageGeometry(pwPtr->panes[i]->tkwin, NULL, NULL);
	Tk_FreeConfigOptions((char *) pwPtr->panes[i], pwPtr->paneOpts,
		pwPtr->tkwin);
	ckfree(pwPtr->slaves[i]);
	pwPtr->slaves[i] = NULL;
	ckfree(pwPtr->panes[i]);
	pwPtr->panes[i] = NULL;
    }
    if (pwPtr->slaves) {
	ckfree(pwPtr->slaves);
    if (pwPtr->panes) {
	ckfree(pwPtr->panes);
    }

    /*
     * Remove the widget command from the interpreter.
     */

    Tcl_DeleteCommandFromToken(pwPtr->interp, pwPtr->widgetCmd);
1623
1624
1625
1626
1627
1628
1629
1630

1631
1632
1633
1634


1635
1636
1637
1638
1639
1640
1641
1642

1643
1644
1645


1646
1647
1648


1649
1650
1651
1652
1653
1654
1655
1656
1657

1658
1659
1660

1661
1662
1663
1664
1665
1666

1667
1668
1669
1670
1671
1672
1673
1674


1675
1676

1677
1678
1679


1680
1681
1682


1683
1684
1685
1686
1687
1688
1689






1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707

1708
1709
1710
1711
1712
1713
1714

1715
1716
1717
1718
1719



1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734

1735
1736
1737
1738
1739
1740

1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757

1758
1759
1760
1761
1762
1763
1764
1622
1623
1624
1625
1626
1627
1628

1629
1630
1631


1632
1633
1634
1635
1636
1637
1638
1639
1640

1641
1642


1643
1644
1645


1646
1647
1648
1649
1650
1651
1652
1653
1654
1655

1656
1657
1658

1659
1660
1661
1662
1663
1664

1665
1666
1667
1668
1669
1670
1671


1672
1673
1674

1675
1676


1677
1678
1679


1680
1681
1682






1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705

1706
1707
1708
1709
1710
1711
1712

1713
1714
1715



1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732

1733
1734
1735
1736
1737
1738

1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755

1756
1757
1758
1759
1760
1761
1762
1763







-
+


-
-
+
+







-
+

-
-
+
+

-
-
+
+








-
+


-
+





-
+






-
-
+
+

-
+

-
-
+
+

-
-
+
+

-
-
-
-
-
-
+
+
+
+
+
+

















-
+






-
+


-
-
-
+
+
+














-
+





-
+
















-
+







 *--------------------------------------------------------------
 */

static void
PanedWindowReqProc(
    ClientData clientData,	/* Paned window's information about window
				 * that got new preferred geometry. */
    Tk_Window tkwin)		/* Other Tk-related information about the
    TCL_UNUSED(Tk_Window))		/* Other Tk-related information about the
				 * window. */
{
    Slave *slavePtr = clientData;
    PanedWindow *pwPtr = (PanedWindow *) slavePtr->masterPtr;
    Pane *panePtr = (Pane *)clientData;
    PanedWindow *pwPtr = (PanedWindow *) panePtr->containerPtr;

    if (Tk_IsMapped(pwPtr->tkwin)) {
	if (!(pwPtr->flags & RESIZE_PENDING)) {
	    pwPtr->flags |= RESIZE_PENDING;
	    Tcl_DoWhenIdle(ArrangePanes, pwPtr);
	}
    } else {
	int doubleBw = 2 * Tk_Changes(slavePtr->tkwin)->border_width;
	int doubleBw = 2 * Tk_Changes(panePtr->tkwin)->border_width;

	if (slavePtr->width <= 0) {
	    slavePtr->paneWidth = Tk_ReqWidth(slavePtr->tkwin) + doubleBw;
	if (panePtr->width <= 0) {
	    panePtr->paneWidth = Tk_ReqWidth(panePtr->tkwin) + doubleBw;
	}
	if (slavePtr->height <= 0) {
	    slavePtr->paneHeight = Tk_ReqHeight(slavePtr->tkwin) + doubleBw;
	if (panePtr->height <= 0) {
	    panePtr->paneHeight = Tk_ReqHeight(panePtr->tkwin) + doubleBw;
	}
	ComputeGeometry(pwPtr);
    }
}

/*
 *--------------------------------------------------------------
 *
 * PanedWindowLostSlaveProc --
 * PanedWindowLostPaneProc --
 *
 *	This function is invoked by Tk whenever some other geometry claims
 *	control over a slave that used to be managed by us.
 *	control over a pane that used to be managed by us.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Forgets all information about the slave. Causes geometry to be
 *	Forgets all information about the pane. Causes geometry to be
 *	recomputed for the panedwindow.
 *
 *--------------------------------------------------------------
 */

static void
PanedWindowLostSlaveProc(
    ClientData clientData,	/* Grid structure for slave window that was
PanedWindowLostPaneProc(
    ClientData clientData,	/* Grid structure for the pane that was
				 * stolen away. */
    Tk_Window tkwin)		/* Tk's handle for the slave window. */
    TCL_UNUSED(Tk_Window))		/* Tk's handle for the pane. */
{
    register Slave *slavePtr = clientData;
    PanedWindow *pwPtr = (PanedWindow *) slavePtr->masterPtr;
    Pane *panePtr = (Pane *)clientData;
    PanedWindow *pwPtr = (PanedWindow *) panePtr->containerPtr;

    if (pwPtr->tkwin != Tk_Parent(slavePtr->tkwin)) {
	Tk_UnmaintainGeometry(slavePtr->tkwin, pwPtr->tkwin);
    if (pwPtr->tkwin != Tk_Parent(panePtr->tkwin)) {
	Tk_UnmaintainGeometry(panePtr->tkwin, pwPtr->tkwin);
    }
    Unlink(slavePtr);
    Tk_DeleteEventHandler(slavePtr->tkwin, StructureNotifyMask,
	    SlaveStructureProc, slavePtr);
    Tk_UnmapWindow(slavePtr->tkwin);
    slavePtr->tkwin = NULL;
    ckfree(slavePtr);
    Unlink(panePtr);
    Tk_DeleteEventHandler(panePtr->tkwin, StructureNotifyMask,
	    PaneStructureProc, panePtr);
    Tk_UnmapWindow(panePtr->tkwin);
    panePtr->tkwin = NULL;
    ckfree(panePtr);
    ComputeGeometry(pwPtr);
}

/*
 *--------------------------------------------------------------
 *
 * ArrangePanes --
 *
 *	This function is invoked (using the Tcl_DoWhenIdle mechanism) to
 *	re-layout a set of windows managed by a paned window. It is invoked at
 *	idle time so that a series of pane requests can be merged into a
 *	single layout operation.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The slaves of masterPtr may get resized or moved.
 *	The panes of containerPtr may get resized or moved.
 *
 *--------------------------------------------------------------
 */

static void
ArrangePanes(
    ClientData clientData)	/* Structure describing parent whose slaves
    ClientData clientData)	/* Structure describing parent whose panes
				 * are to be re-layed out. */
{
    register PanedWindow *pwPtr = clientData;
    register Slave *slavePtr;
    int i, slaveWidth, slaveHeight, slaveX, slaveY;
    PanedWindow *pwPtr = (PanedWindow *)clientData;
    Pane *panePtr;
    int i, newPaneWidth, newPaneHeight, paneX, paneY;
    int paneWidth, paneHeight, paneSize, paneMinSize;
    int doubleBw;
    int x, y;
    int sashWidth, sashOffset, sashCount, handleOffset;
    int sashReserve, sxReserve, syReserve;
    int internalBW;
    int paneDynSize, paneDynMinSize, pwHeight, pwWidth, pwSize;
    int first, last;
    int stretchReserve, stretchAmount;
    const int horizontal = (pwPtr->orient == ORIENT_HORIZONTAL);

    pwPtr->flags &= ~(REQUESTED_RELAYOUT|RESIZE_PENDING);

    /*
     * If the parent has no slaves anymore, then don't do anything at all:
     * If the parent has no panes anymore, then don't do anything at all:
     * just leave the parent's size as-is. Otherwise there is no way to
     * "relinquish" control over the parent so another geometry manager can
     * take over.
     */

    if (pwPtr->numSlaves == 0) {
    if (pwPtr->numPanes == 0) {
	return;
    }

    Tcl_Preserve(pwPtr);

    /*
     * Find index of first and last visible panes.
     */

    GetFirstLastVisiblePane(pwPtr, &first, &last);

    /*
     * First pass; compute sizes
     */

    paneDynSize = paneDynMinSize = 0;
    internalBW = Tk_InternalBorderWidth(pwPtr->tkwin);
    internalBW = Tk_InternalBorderLeft(pwPtr->tkwin);
    pwHeight = Tk_Height(pwPtr->tkwin) - (2 * internalBW);
    pwWidth = Tk_Width(pwPtr->tkwin) - (2 * internalBW);
    x = y = internalBW;
    stretchReserve = (horizontal ? pwWidth : pwHeight);

    /*
     * Calculate the sash width, including handle and padding, and the sash
1772
1773
1774
1775
1776
1777
1778
1779
1780


1781
1782

1783
1784
1785
1786
1787

1788
1789
1790
1791
1792
1793


1794
1795

1796
1797

1798
1799
1800


1801
1802

1803
1804

1805
1806

1807
1808
1809

1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822


1823
1824
1825
1826



1827
1828
1829
1830
1831

1832
1833
1834
1835

1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846






1847
1848
1849
1850
1851
1852
1853
1854


1855
1856

1857
1858
1859
1860
1861


1862
1863

1864
1865
1866
1867

1868
1869
1870
1871
1872
1873
1874
1875
1876
1877

1878
1879
1880
1881
1882
1883
1884
1771
1772
1773
1774
1775
1776
1777


1778
1779
1780

1781
1782
1783
1784
1785

1786
1787
1788
1789
1790


1791
1792
1793

1794
1795

1796
1797


1798
1799
1800

1801
1802

1803
1804

1805
1806
1807

1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819


1820
1821
1822



1823
1824
1825
1826
1827
1828
1829

1830
1831
1832
1833

1834
1835
1836
1837
1838
1839






1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851


1852
1853
1854

1855
1856
1857
1858


1859
1860
1861

1862
1863
1864
1865

1866
1867
1868
1869
1870
1871
1872
1873
1874
1875

1876
1877
1878
1879
1880
1881
1882
1883







-
-
+
+

-
+




-
+




-
-
+
+

-
+

-
+

-
-
+
+

-
+

-
+

-
+


-
+











-
-
+
+

-
-
-
+
+
+




-
+



-
+





-
-
-
-
-
-
+
+
+
+
+
+






-
-
+
+

-
+



-
-
+
+

-
+



-
+









-
+







		+ pwPtr->sashPad;
    } else {
	sashWidth = (2 * pwPtr->sashPad) + pwPtr->sashWidth;
	handleOffset = ((pwPtr->sashWidth - pwPtr->handleSize) / 2)
		+ pwPtr->sashPad;
    }

    for (i = sashCount = 0; i < pwPtr->numSlaves; i++) {
	slavePtr = pwPtr->slaves[i];
    for (i = sashCount = 0; i < pwPtr->numPanes; i++) {
	panePtr = pwPtr->panes[i];

	if (slavePtr->hide) {
	if (panePtr->hide) {
	    continue;
	}

	/*
	 * Compute the total size needed by all the slaves and the left-over,
	 * Compute the total size needed by all the panes and the left-over,
	 * or shortage of space available.
	 */

	if (horizontal) {
            if (slavePtr->width > 0) {
                paneSize = slavePtr->width;
            if (panePtr->width > 0) {
                paneSize = panePtr->width;
            } else {
                paneSize = slavePtr->paneWidth;
                paneSize = panePtr->paneWidth;
            }
	    stretchReserve -= paneSize + (2 * slavePtr->padx);
	    stretchReserve -= paneSize + (2 * panePtr->padx);
	} else {
            if (slavePtr->height > 0) {
                paneSize = slavePtr->height;
            if (panePtr->height > 0) {
                paneSize = panePtr->height;
            } else {
                paneSize = slavePtr->paneHeight;
                paneSize = panePtr->paneHeight;
            }
	    stretchReserve -= paneSize + (2 * slavePtr->pady);
	    stretchReserve -= paneSize + (2 * panePtr->pady);
	}
	if (IsStretchable(slavePtr->stretch,i,first,last)
	if (IsStretchable(panePtr->stretch,i,first,last)
		&& Tk_IsMapped(pwPtr->tkwin)) {
	    paneDynSize += paneSize;
	    paneDynMinSize += slavePtr->minSize;
	    paneDynMinSize += panePtr->minSize;
	}
	if (i != last) {
	    stretchReserve -= sashWidth;
	    sashCount++;
	}
    }

    /*
     * Second pass; adjust/arrange panes.
     */

    for (i = 0; i < pwPtr->numSlaves; i++) {
	slavePtr = pwPtr->slaves[i];
    for (i = 0; i < pwPtr->numPanes; i++) {
	panePtr = pwPtr->panes[i];

	if (slavePtr->hide) {
	    Tk_UnmaintainGeometry(slavePtr->tkwin, pwPtr->tkwin);
	    Tk_UnmapWindow(slavePtr->tkwin);
	if (panePtr->hide) {
	    Tk_UnmaintainGeometry(panePtr->tkwin, pwPtr->tkwin);
	    Tk_UnmapWindow(panePtr->tkwin);
	    continue;
	}

	/*
	 * Compute the size of this slave. The algorithm (assuming a
	 * Compute the size of this pane. The algorithm (assuming a
	 * horizontal paned window) is:
	 *
	 * 1.  Get "base" dimensions. If a width or height is specified for
	 *     this slave, use those values; else use the ReqWidth/ReqHeight.
	 *     this pane, use those values; else use the ReqWidth/ReqHeight.
	 * 2.  Using base dimensions, pane dimensions, and sticky values,
	 *     determine the x and y, and actual width and height of the
	 *     widget.
	 */

	doubleBw = 2 * Tk_Changes(slavePtr->tkwin)->border_width;
	slaveWidth = (slavePtr->width > 0 ? slavePtr->width :
		Tk_ReqWidth(slavePtr->tkwin) + doubleBw);
	slaveHeight = (slavePtr->height > 0 ? slavePtr->height :
		Tk_ReqHeight(slavePtr->tkwin) + doubleBw);
	paneMinSize = slavePtr->minSize;
	doubleBw = 2 * Tk_Changes(panePtr->tkwin)->border_width;
	newPaneWidth = (panePtr->width > 0 ? panePtr->width :
		Tk_ReqWidth(panePtr->tkwin) + doubleBw);
	newPaneHeight = (panePtr->height > 0 ? panePtr->height :
		Tk_ReqHeight(panePtr->tkwin) + doubleBw);
	paneMinSize = panePtr->minSize;

	/*
	 * Calculate pane width and height.
	 */

	if (horizontal) {
            if (slavePtr->width > 0) {
                paneSize = slavePtr->width;
            if (panePtr->width > 0) {
                paneSize = panePtr->width;
            } else {
                paneSize = slavePtr->paneWidth;
                paneSize = panePtr->paneWidth;
            }
	    pwSize = pwWidth;
	} else {
            if (slavePtr->height > 0) {
                paneSize = slavePtr->height;
            if (panePtr->height > 0) {
                paneSize = panePtr->height;
            } else {
                paneSize = slavePtr->paneHeight;
                paneSize = panePtr->paneHeight;
            }
	    pwSize = pwHeight;
	}
	if (IsStretchable(slavePtr->stretch, i, first, last)) {
	if (IsStretchable(panePtr->stretch, i, first, last)) {
	    double frac;

	    if (paneDynSize > 0) {
		frac = (double)paneSize / (double)paneDynSize;
	    } else {
		frac = (double)paneSize / (double)pwSize;
	    }

	    paneDynSize -= paneSize;
	    paneDynMinSize -= slavePtr->minSize;
	    paneDynMinSize -= panePtr->minSize;
	    stretchAmount = (int) (frac * stretchReserve);
	    if (paneSize + stretchAmount >= paneMinSize) {
		stretchReserve -= stretchAmount;
		paneSize += stretchAmount;
	    } else {
		stretchReserve += paneSize - paneMinSize;
		paneSize = paneMinSize;
1895
1896
1897
1898
1899
1900
1901
1902

1903
1904

1905
1906
1907
1908
1909
1910
1911
1894
1895
1896
1897
1898
1899
1900

1901
1902

1903
1904
1905
1906
1907
1908
1909
1910







-
+

-
+







	    } else {
		paneSize += paneDynSize - paneDynMinSize + stretchReserve;
		stretchReserve = paneDynMinSize - paneDynSize;
	    }
	}
	if (horizontal) {
	    paneWidth = paneSize;
	    paneHeight = pwHeight - (2 * slavePtr->pady);
	    paneHeight = pwHeight - (2 * panePtr->pady);
	} else {
	    paneWidth = pwWidth - (2 * slavePtr->padx);
	    paneWidth = pwWidth - (2 * panePtr->padx);
	    paneHeight = paneSize;
	}

	/*
	 * Adjust for area reserved for sashes.
	 */

1925
1926
1927
1928
1929
1930
1931
1932
1933


1934
1935
1936


1937
1938
1939
1940


1941
1942
1943
1944
1945
1946
1947
1948

1949
1950
1951
1952
1953
1954
1955




1956
1957
1958

1959
1960
1961
1962
1963
1964
1965




1966
1967
1968
1969
1970

1971
1972
1973
1974
1975
1976




1977
1978
1979


1980
1981
1982
1983
1984
1985
1986
1987
1988
1989





1990
1991
1992


1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004

2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017

2018
2019

2020
2021
2022
2023


2024
2025
2026
2027
2028

2029
2030
2031
2032
2033
2034
2035




2036
2037
2038
2039
2040
2041
2042

2043
2044
2045
2046
2047



2048
2049
2050


2051
2052
2053
2054
2055
2056
2057




2058
2059
2060
2061

2062
2063
2064
2065

2066
2067

2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079

2080
2081
2082
2083
2084
2085
2086
2087
2088

2089
2090
2091
2092
2093
2094
2095
2096
2097



2098
2099
2100
2101
2102
2103
2104
1924
1925
1926
1927
1928
1929
1930


1931
1932
1933


1934
1935
1936
1937


1938
1939
1940
1941
1942
1943
1944
1945
1946

1947
1948
1949
1950




1951
1952
1953
1954
1955
1956

1957
1958
1959
1960




1961
1962
1963
1964
1965
1966
1967
1968

1969
1970
1971




1972
1973
1974
1975
1976


1977
1978
1979
1980
1981
1982
1983





1984
1985
1986
1987
1988
1989


1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002

2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015

2016
2017

2018
2019
2020


2021
2022
2023
2024
2025
2026

2027
2028
2029
2030




2031
2032
2033
2034
2035
2036
2037
2038
2039
2040

2041
2042
2043



2044
2045
2046
2047


2048
2049
2050
2051
2052




2053
2054
2055
2056
2057
2058
2059

2060
2061
2062
2063

2064
2065

2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077

2078
2079
2080
2081
2082
2083
2084
2085
2086

2087
2088
2089
2090
2091
2092
2093



2094
2095
2096
2097
2098
2099
2100
2101
2102
2103







-
-
+
+

-
-
+
+


-
-
+
+







-
+



-
-
-
-
+
+
+
+


-
+



-
-
-
-
+
+
+
+




-
+


-
-
-
-
+
+
+
+

-
-
+
+





-
-
-
-
-
+
+
+
+
+

-
-
+
+











-
+












-
+

-
+


-
-
+
+




-
+



-
-
-
-
+
+
+
+






-
+


-
-
-
+
+
+

-
-
+
+



-
-
-
-
+
+
+
+



-
+



-
+

-
+











-
+








-
+






-
-
-
+
+
+







	if (pwWidth - sxReserve < x + paneWidth - internalBW) {
	    paneWidth = pwWidth - sxReserve - x + internalBW;
	}
	if (pwHeight - syReserve < y + paneHeight - internalBW) {
	    paneHeight = pwHeight - syReserve - y + internalBW;
	}

	if (slaveWidth > paneWidth) {
	    slaveWidth = paneWidth;
	if (newPaneWidth > paneWidth) {
	    newPaneWidth = paneWidth;
	}
	if (slaveHeight > paneHeight) {
	    slaveHeight = paneHeight;
	if (newPaneHeight > paneHeight) {
	    newPaneHeight = paneHeight;
	}

	slavePtr->x = x;
	slavePtr->y = y;
	panePtr->x = x;
	panePtr->y = y;

	/*
	 * Compute the location of the sash at the right or bottom of the
	 * parcel and the location of the next parcel.
	 */

	if (horizontal) {
	    x += paneWidth + (2 * slavePtr->padx);
	    x += paneWidth + (2 * panePtr->padx);
	    if (x < internalBW) {
		x = internalBW;
	    }
	    slavePtr->sashx = x + sashOffset;
	    slavePtr->sashy = y;
	    slavePtr->handlex = x + handleOffset;
	    slavePtr->handley = y + pwPtr->handlePad;
	    panePtr->sashx = x + sashOffset;
	    panePtr->sashy = y;
	    panePtr->handlex = x + handleOffset;
	    panePtr->handley = y + pwPtr->handlePad;
	    x += sashWidth;
	} else {
	    y += paneHeight + (2 * slavePtr->pady);
	    y += paneHeight + (2 * panePtr->pady);
	    if (y < internalBW) {
		y = internalBW;
	    }
	    slavePtr->sashx = x;
	    slavePtr->sashy = y + sashOffset;
	    slavePtr->handlex = x + pwPtr->handlePad;
	    slavePtr->handley = y + handleOffset;
	    panePtr->sashx = x;
	    panePtr->sashy = y + sashOffset;
	    panePtr->handlex = x + pwPtr->handlePad;
	    panePtr->handley = y + handleOffset;
	    y += sashWidth;
	}

	/*
	 * Compute the actual dimensions of the slave in the pane.
	 * Compute the actual dimensions of the pane in the pane.
	 */

	slaveX = slavePtr->x;
	slaveY = slavePtr->y;
	AdjustForSticky(slavePtr->sticky, paneWidth, paneHeight,
		&slaveX, &slaveY, &slaveWidth, &slaveHeight);
	paneX = panePtr->x;
	paneY = panePtr->y;
	AdjustForSticky(panePtr->sticky, paneWidth, paneHeight,
		&paneX, &paneY, &newPaneWidth, &newPaneHeight);

	slaveX += slavePtr->padx;
	slaveY += slavePtr->pady;
	paneX += panePtr->padx;
	paneY += panePtr->pady;

	/*
	 * Now put the window in the proper spot.
	 */

	if (slaveWidth <= 0 || slaveHeight <= 0 ||
		(horizontal ? slaveX - internalBW > pwWidth :
		slaveY - internalBW > pwHeight)) {
	    Tk_UnmaintainGeometry(slavePtr->tkwin, pwPtr->tkwin);
	    Tk_UnmapWindow(slavePtr->tkwin);
	if (newPaneWidth <= 0 || newPaneHeight <= 0 ||
		(horizontal ? paneX - internalBW > pwWidth :
		paneY - internalBW > pwHeight)) {
	    Tk_UnmaintainGeometry(panePtr->tkwin, pwPtr->tkwin);
	    Tk_UnmapWindow(panePtr->tkwin);
	} else {
	    Tk_MaintainGeometry(slavePtr->tkwin, pwPtr->tkwin,
		    slaveX, slaveY, slaveWidth, slaveHeight);
	    Tk_MaintainGeometry(panePtr->tkwin, pwPtr->tkwin,
		    paneX, paneY, newPaneWidth, newPaneHeight);
	}
	sashCount--;
    }
    Tcl_Release(pwPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * Unlink --
 *
 *	Remove a slave from a paned window.
 *	Remove a pane from a paned window.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The paned window will be scheduled for re-arranging and redrawing.
 *
 *----------------------------------------------------------------------
 */

static void
Unlink(
    register Slave *slavePtr)		/* Window to unlink. */
    Pane *panePtr)		/* Window to unlink. */
{
    register PanedWindow *masterPtr;
    PanedWindow *containerPtr;
    int i, j;

    masterPtr = slavePtr->masterPtr;
    if (masterPtr == NULL) {
    containerPtr = panePtr->containerPtr;
    if (containerPtr == NULL) {
	return;
    }

    /*
     * Find the specified slave in the panedwindow's list of slaves, then
     * Find the specified pane in the panedwindow's list of panes, then
     * remove it from that list.
     */

    for (i = 0; i < masterPtr->numSlaves; i++) {
	if (masterPtr->slaves[i] == slavePtr) {
	    for (j = i; j < masterPtr->numSlaves - 1; j++) {
		masterPtr->slaves[j] = masterPtr->slaves[j + 1];
    for (i = 0; i < containerPtr->numPanes; i++) {
	if (containerPtr->panes[i] == panePtr) {
	    for (j = i; j < containerPtr->numPanes - 1; j++) {
		containerPtr->panes[j] = containerPtr->panes[j + 1];
	    }
	    break;
	}
    }

    /*
     * Clean out any -after or -before references to this slave
     * Clean out any -after or -before references to this pane
     */

    for (i = 0; i < masterPtr->numSlaves; i++) {
	if (masterPtr->slaves[i]->before == slavePtr->tkwin) {
	    masterPtr->slaves[i]->before = NULL;
    for (i = 0; i < containerPtr->numPanes; i++) {
	if (containerPtr->panes[i]->before == panePtr->tkwin) {
	    containerPtr->panes[i]->before = NULL;
	}
	if (masterPtr->slaves[i]->after == slavePtr->tkwin) {
	    masterPtr->slaves[i]->after = NULL;
	if (containerPtr->panes[i]->after == panePtr->tkwin) {
	    containerPtr->panes[i]->after = NULL;
	}
    }

    masterPtr->flags |= REQUESTED_RELAYOUT;
    if (!(masterPtr->flags & REDRAW_PENDING)) {
	masterPtr->flags |= REDRAW_PENDING;
	Tcl_DoWhenIdle(DisplayPanedWindow, masterPtr);
    containerPtr->flags |= REQUESTED_RELAYOUT;
    if (!(containerPtr->flags & REDRAW_PENDING)) {
	containerPtr->flags |= REDRAW_PENDING;
	Tcl_DoWhenIdle(DisplayPanedWindow, containerPtr);
    }

    /*
     * Set the slave's masterPtr to NULL, so that we can tell that the slave
     * Set the pane's containerPtr to NULL, so that we can tell that the pane
     * is no longer attached to any panedwindow.
     */

    slavePtr->masterPtr = NULL;
    panePtr->containerPtr = NULL;

    masterPtr->numSlaves--;
    containerPtr->numPanes--;
}

/*
 *----------------------------------------------------------------------
 *
 * GetPane --
 *
 *	Given a token to a Tk window, find the pane that corresponds to that
 *	token in a given paned window.
 *
 * Results:
 *	Pointer to the slave structure, or NULL if the window is not managed
 *	Pointer to the pane structure, or NULL if the window is not managed
 *	by this paned window.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static Slave *
static Pane *
GetPane(
    PanedWindow *pwPtr,		/* Pointer to the paned window info. */
    Tk_Window tkwin)		/* Window to search for. */
{
    int i;

    for (i = 0; i < pwPtr->numSlaves; i++) {
	if (pwPtr->slaves[i]->tkwin == tkwin) {
	    return pwPtr->slaves[i];
    for (i = 0; i < pwPtr->numPanes; i++) {
	if (pwPtr->panes[i]->tkwin == tkwin) {
	    return pwPtr->panes[i];
	}
    }
    return NULL;
}

/*
 *----------------------------------------------------------------------
2121
2122
2123
2124
2125
2126
2127
2128
2129


2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141

2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152


2153
2154
2155
2156
2157
2158
2159

2160
2161
2162
2163
2164


2165
2166
2167
2168
2169



2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180

2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198

2199
2200
2201
2202
2203

2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225


2226
2227

2228
2229
2230
2231
2232

2233
2234
2235
2236
2237


2238
2239
2240
2241
2242
2243
2244
2245
2246
2247


2248
2249
2250
2251


2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265





2266
2267
2268
2269
2270
2271
2272





2273
2274
2275
2276
2277

2278
2279
2280
2281
2282
2283
2284


2285
2286
2287
2288


2289
2290
2291


2292
2293

2294
2295
2296
2297
2298
2299
2300


2301
2302
2303
2304


2305
2306
2307


2308
2309

2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327

2328
2329
2330
2331
2332
2333
2334
2120
2121
2122
2123
2124
2125
2126


2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139

2140
2141
2142
2143
2144
2145
2146
2147
2148
2149


2150
2151
2152
2153
2154
2155
2156
2157

2158
2159
2160
2161


2162
2163
2164
2165



2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178

2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196

2197
2198
2199
2200
2201

2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222


2223
2224
2225

2226
2227
2228
2229
2230

2231
2232
2233
2234


2235
2236
2237
2238
2239
2240
2241
2242
2243
2244


2245
2246
2247
2248


2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259





2260
2261
2262
2263
2264
2265
2266





2267
2268
2269
2270
2271
2272
2273
2274
2275

2276
2277
2278
2279
2280
2281


2282
2283
2284
2285


2286
2287
2288


2289
2290
2291

2292
2293
2294
2295
2296
2297


2298
2299
2300
2301


2302
2303
2304


2305
2306
2307

2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325

2326
2327
2328
2329
2330
2331
2332
2333







-
-
+
+











-
+









-
-
+
+






-
+



-
-
+
+


-
-
-
+
+
+










-
+

















-
+




-
+




















-
-
+
+

-
+




-
+



-
-
+
+








-
-
+
+


-
-
+
+









-
-
-
-
-
+
+
+
+
+


-
-
-
-
-
+
+
+
+
+




-
+





-
-
+
+


-
-
+
+

-
-
+
+

-
+





-
-
+
+


-
-
+
+

-
-
+
+

-
+

















-
+







GetFirstLastVisiblePane(
    PanedWindow *pwPtr,		/* Pointer to the paned window info. */
    int *firstPtr, 		/* Returned index for first. */
    int *lastPtr)  		/* Returned index for last. */
{
    int i;

    for (i = 0, *lastPtr = 0, *firstPtr = -1; i < pwPtr->numSlaves; i++) {
	if (pwPtr->slaves[i]->hide == 0) {
    for (i = 0, *lastPtr = 0, *firstPtr = -1; i < pwPtr->numPanes; i++) {
	if (pwPtr->panes[i]->hide == 0) {
	    if (*firstPtr < 0) {
		*firstPtr = i;
	    }
	    *lastPtr = i;
	}
    }
}

/*
 *--------------------------------------------------------------
 *
 * SlaveStructureProc --
 * PaneStructureProc --
 *
 *	This function is invoked whenever StructureNotify events occur for a
 *	window that's managed by a paned window. This function's only purpose
 *	is to clean up when windows are deleted.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The paned window slave structure associated with the window
 *	is freed, and the slave is disassociated from the paned
 *	The paned window pane structure associated with the window
 *	is freed, and the pane is disassociated from the paned
 *	window which managed it.
 *
 *--------------------------------------------------------------
 */

static void
SlaveStructureProc(
PaneStructureProc(
    ClientData clientData,	/* Pointer to record describing window item. */
    XEvent *eventPtr)		/* Describes what just happened. */
{
    Slave *slavePtr = clientData;
    PanedWindow *pwPtr = slavePtr->masterPtr;
    Pane *panePtr = (Pane *)clientData;
    PanedWindow *pwPtr = panePtr->containerPtr;

    if (eventPtr->type == DestroyNotify) {
	Unlink(slavePtr);
	slavePtr->tkwin = NULL;
	ckfree(slavePtr);
	Unlink(panePtr);
	panePtr->tkwin = NULL;
	ckfree(panePtr);
	ComputeGeometry(pwPtr);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * ComputeGeometry --
 *
 *	Compute geometry for the paned window, including coordinates of all
 *	slave windows and each sash.
 *	panes and each sash.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Recomputes geometry information for a paned window.
 *
 *----------------------------------------------------------------------
 */

static void
ComputeGeometry(
    PanedWindow *pwPtr)		/* Pointer to the Paned Window structure. */
{
    int i, x, y, doubleBw, internalBw;
    int sashWidth, sashOffset, handleOffset;
    int reqWidth, reqHeight, dim;
    Slave *slavePtr;
    Pane *panePtr;
    const int horizontal = (pwPtr->orient == ORIENT_HORIZONTAL);

    pwPtr->flags |= REQUESTED_RELAYOUT;

    x = y = internalBw = Tk_InternalBorderWidth(pwPtr->tkwin);
    x = y = internalBw = Tk_InternalBorderLeft(pwPtr->tkwin);
    reqWidth = reqHeight = 0;

    /*
     * Sashes and handles share space on the display. To simplify processing
     * below, precompute the x and y offsets of the handles and sashes within
     * the space occupied by their combination; later, just add those offsets
     * blindly (avoiding the extra showHandle, etc, checks).
     */

    sashOffset = handleOffset = pwPtr->sashPad;
    if (pwPtr->showHandle && pwPtr->handleSize > pwPtr->sashWidth) {
	sashWidth = (2 * pwPtr->sashPad) + pwPtr->handleSize;
	sashOffset = ((pwPtr->handleSize - pwPtr->sashWidth) / 2)
		+ pwPtr->sashPad;
    } else {
	sashWidth = (2 * pwPtr->sashPad) + pwPtr->sashWidth;
	handleOffset = ((pwPtr->sashWidth - pwPtr->handleSize) / 2)
		+ pwPtr->sashPad;
    }

    for (i = 0; i < pwPtr->numSlaves; i++) {
	slavePtr = pwPtr->slaves[i];
    for (i = 0; i < pwPtr->numPanes; i++) {
	panePtr = pwPtr->panes[i];

	if (slavePtr->hide) {
	if (panePtr->hide) {
	    continue;
	}

	/*
	 * First set the coordinates for the top left corner of the slave's
	 * First set the coordinates for the top left corner of the pane's
	 * parcel.
	 */

	slavePtr->x = x;
	slavePtr->y = y;
	panePtr->x = x;
	panePtr->y = y;

	/*
	 * Make sure the pane's paned dimension is at least minsize. This
	 * check may be redundant, since the only way to change a pane's size
	 * is by moving a sash, and that code checks the minsize.
	 */

	if (horizontal) {
	    if (slavePtr->paneWidth < slavePtr->minSize) {
		slavePtr->paneWidth = slavePtr->minSize;
	    if (panePtr->paneWidth < panePtr->minSize) {
		panePtr->paneWidth = panePtr->minSize;
	    }
	} else {
	    if (slavePtr->paneHeight < slavePtr->minSize) {
		slavePtr->paneHeight = slavePtr->minSize;
	    if (panePtr->paneHeight < panePtr->minSize) {
		panePtr->paneHeight = panePtr->minSize;
	    }
	}

	/*
	 * Compute the location of the sash at the right or bottom of the
	 * parcel.
	 */

	if (horizontal) {
	    x += slavePtr->paneWidth + (2 * slavePtr->padx);
	    slavePtr->sashx = x + sashOffset;
	    slavePtr->sashy = y;
	    slavePtr->handlex = x + handleOffset;
	    slavePtr->handley = y + pwPtr->handlePad;
	    x += panePtr->paneWidth + (2 * panePtr->padx);
	    panePtr->sashx = x + sashOffset;
	    panePtr->sashy = y;
	    panePtr->handlex = x + handleOffset;
	    panePtr->handley = y + pwPtr->handlePad;
	    x += sashWidth;
	} else {
	    y += slavePtr->paneHeight + (2 * slavePtr->pady);
	    slavePtr->sashx = x;
	    slavePtr->sashy = y + sashOffset;
	    slavePtr->handlex = x + pwPtr->handlePad;
	    slavePtr->handley = y + handleOffset;
	    y += panePtr->paneHeight + (2 * panePtr->pady);
	    panePtr->sashx = x;
	    panePtr->sashy = y + sashOffset;
	    panePtr->handlex = x + pwPtr->handlePad;
	    panePtr->handley = y + handleOffset;
	    y += sashWidth;
	}

	/*
	 * Find the maximum height/width of the slaves, for computing the
	 * Find the maximum height/width of the panes, for computing the
	 * requested height/width of the paned window.
	 */

	if (horizontal) {
	    /*
	     * If the slave has an explicit height set, use that; otherwise,
	     * use the slave's requested height.
	     * If the pane has an explicit height set, use that; otherwise,
	     * use the pane's requested height.
	     */

	    if (slavePtr->height > 0) {
		dim = slavePtr->height;
	    if (panePtr->height > 0) {
		dim = panePtr->height;
	    } else {
		doubleBw = 2 * Tk_Changes(slavePtr->tkwin)->border_width;
		dim = Tk_ReqHeight(slavePtr->tkwin) + doubleBw;
		doubleBw = 2 * Tk_Changes(panePtr->tkwin)->border_width;
		dim = Tk_ReqHeight(panePtr->tkwin) + doubleBw;
	    }
	    dim += 2 * slavePtr->pady;
	    dim += 2 * panePtr->pady;
	    if (dim > reqHeight) {
		reqHeight = dim;
	    }
	} else {
	    /*
	     * If the slave has an explicit width set use that; otherwise, use
	     * the slave's requested width.
	     * If the pane has an explicit width set use that; otherwise, use
	     * the pane's requested width.
	     */

	    if (slavePtr->width > 0) {
		dim = slavePtr->width;
	    if (panePtr->width > 0) {
		dim = panePtr->width;
	    } else {
		doubleBw = 2 * Tk_Changes(slavePtr->tkwin)->border_width;
		dim = Tk_ReqWidth(slavePtr->tkwin) + doubleBw;
		doubleBw = 2 * Tk_Changes(panePtr->tkwin)->border_width;
		dim = Tk_ReqWidth(panePtr->tkwin) + doubleBw;
	    }
	    dim += 2 * slavePtr->padx;
	    dim += 2 * panePtr->padx;
	    if (dim > reqWidth) {
		reqWidth = dim;
	    }
	}
    }

    /*
     * The loop above should have left x (or y) equal to the sum of the widths
     * (or heights) of the widgets, plus the size of one sash and the sash
     * padding for each widget, plus the width of the left (or top) border of
     * the paned window.
     *
     * The requested width (or height) is therefore x (or y) minus the size of
     * one sash and padding, plus the width of the right (or bottom) border of
     * the paned window.
     *
     * The height (or width) is equal to the maximum height (or width) of the
     * slaves, plus the width of the border of the top and bottom (or left and
     * panes, plus the width of the border of the top and bottom (or left and
     * right) of the paned window.
     *
     * If the panedwindow has an explicit width/height set use that;
     * otherwise, use the requested width/height.
     */

    if (horizontal) {
2366
2367
2368
2369
2370
2371
2372
2373

2374
2375
2376
2377
2378
2379
2380
2365
2366
2367
2368
2369
2370
2371

2372
2373
2374
2375
2376
2377
2378
2379







-
+







 *
 *----------------------------------------------------------------------
 */

static void
DestroyOptionTables(
    ClientData clientData,	/* Pointer to the OptionTables struct */
    Tcl_Interp *interp)		/* Pointer to the calling interp */
    TCL_UNUSED(Tcl_Interp *))		/* Pointer to the calling interp */
{
    ckfree(clientData);
}

/*
 *----------------------------------------------------------------------
 *
2390
2391
2392
2393
2394
2395
2396
2397
2398


2399
2400

2401
2402
2403
2404
2405
2406
2407
2389
2390
2391
2392
2393
2394
2395


2396
2397
2398

2399
2400
2401
2402
2403
2404
2405
2406







-
-
+
+

-
+







 *	Creates a new Tcl_Obj.
 *
 *----------------------------------------------------------------------
 */

static Tcl_Obj *
GetSticky(
    ClientData clientData,
    Tk_Window tkwin,
    TCL_UNUSED(void *),
    TCL_UNUSED(Tk_Window),
    char *recordPtr,		/* Pointer to widget record. */
    int internalOffset)		/* Offset within *recordPtr containing the
    TkSizeT internalOffset)		/* Offset within *recordPtr containing the
				 * sticky value. */
{
    int sticky = *(int *)(recordPtr + internalOffset);
    char buffer[5];
    char *p = &buffer[0];

    if (sticky & STICK_NORTH) {
2438
2439
2440
2441
2442
2443
2444
2445

2446
2447

2448
2449
2450
2451
2452

2453
2454
2455
2456
2457

2458

2459
2460
2461
2462
2463
2464
2465
2437
2438
2439
2440
2441
2442
2443

2444
2445

2446
2447
2448
2449
2450

2451
2452
2453
2454
2455
2456
2457

2458
2459
2460
2461
2462
2463
2464
2465







-
+

-
+




-
+





+
-
+







 *	specified string was empty and that is acceptable.
 *
 *----------------------------------------------------------------------
 */

static int
SetSticky(
    ClientData clientData,
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interp; may be used for errors. */
    Tk_Window tkwin,		/* Window for which option is being set. */
    TCL_UNUSED(Tk_Window),	/* Window for which option is being set. */
    Tcl_Obj **value,		/* Pointer to the pointer to the value object.
				 * We use a pointer to the pointer because we
				 * may need to return a value (NULL). */
    char *recordPtr,		/* Pointer to storage for the widget record. */
    int internalOffset,		/* Offset within *recordPtr at which the
    TkSizeT internalOffset,		/* Offset within *recordPtr at which the
				 * internal value is to be stored. */
    char *oldInternalPtr,	/* Pointer to storage for the old value. */
    int flags)			/* Flags for the option, set Tk_SetOptions. */
{
    int sticky = 0;
    char c;
    char c, *internalPtr;
    void *internalPtr;
    const char *string;

    internalPtr = ComputeSlotAddress(recordPtr, internalOffset);

    if (flags & TK_OPTION_NULL_OK && ObjectIsEmpty(*value)) {
	*value = NULL;
    } else {
2517
2518
2519
2520
2521
2522
2523
2524
2525


2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539


2540
2541
2542

2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561



2562
2563
2564


2565
2566
2567


2568
2569
2570
2571


2572
2573
2574
2575

2576
2577
2578

2579
2580
2581
2582
2583
2584
2585
2517
2518
2519
2520
2521
2522
2523


2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537


2538
2539
2540
2541

2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558



2559
2560
2561
2562


2563
2564
2565


2566
2567
2568
2569


2570
2571
2572
2573
2574

2575
2576
2577

2578
2579
2580
2581
2582
2583
2584
2585







-
-
+
+












-
-
+
+


-
+
















-
-
-
+
+
+

-
-
+
+

-
-
+
+


-
-
+
+



-
+


-
+







 *	Restores the old value.
 *
 *----------------------------------------------------------------------
 */

static void
RestoreSticky(
    ClientData clientData,
    Tk_Window tkwin,
    TCL_UNUSED(void *),
    TCL_UNUSED(Tk_Window),
    char *internalPtr,		/* Pointer to storage for value. */
    char *oldInternalPtr)	/* Pointer to old value. */
{
    *(int *)internalPtr = *(int *)oldInternalPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * AdjustForSticky --
 *
 *	Given the x,y coords of the top-left corner of a pane, the dimensions
 *	of that pane, and the dimensions of a slave, compute the x,y coords
 *	and actual dimensions of the slave based on the slave's sticky value.
 *	of that pane, and the dimensions of a pane, compute the x,y coords
 *	and actual dimensions of the pane based on the pane's sticky value.
 *
 * Results:
 *	No direct return; sets the x, y, slaveWidth and slaveHeight to correct
 *	No direct return; sets the x, y, paneWidth and paneHeight to correct
 *	values.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
AdjustForSticky(
    int sticky,			/* Sticky value; see top of file for
				 * definition. */
    int cavityWidth,		/* Width of the cavity. */
    int cavityHeight,		/* Height of the cavity. */
    int *xPtr, int *yPtr,	/* Initially, coordinates of the top-left
				 * corner of cavity; also return values for
				 * actual x, y coords of slave. */
    int *slaveWidthPtr,		/* Slave width. */
    int *slaveHeightPtr)	/* Slave height. */
				 * actual x, y coords of pane. */
    int *paneWidthPtr,		/* Pane width. */
    int *paneHeightPtr)	/* Pane height. */
{
    int diffx = 0;		/* Cavity width - slave width. */
    int diffy = 0;		/* Cavity hight - slave height. */
    int diffx = 0;		/* Cavity width - pane width. */
    int diffy = 0;		/* Cavity hight - pane height. */

    if (cavityWidth > *slaveWidthPtr) {
	diffx = cavityWidth - *slaveWidthPtr;
    if (cavityWidth > *paneWidthPtr) {
	diffx = cavityWidth - *paneWidthPtr;
    }

    if (cavityHeight > *slaveHeightPtr) {
	diffy = cavityHeight - *slaveHeightPtr;
    if (cavityHeight > *paneHeightPtr) {
	diffy = cavityHeight - *paneHeightPtr;
    }

    if ((sticky & STICK_EAST) && (sticky & STICK_WEST)) {
	*slaveWidthPtr += diffx;
	*paneWidthPtr += diffx;
    }
    if ((sticky & STICK_NORTH) && (sticky & STICK_SOUTH)) {
	*slaveHeightPtr += diffy;
	*paneHeightPtr += diffy;
    }
    if (!(sticky & STICK_WEST)) {
	*xPtr += (sticky & STICK_EAST) ? diffx : diffx/2;
    }
    if (!(sticky & STICK_NORTH)) {
	*yPtr += (sticky & STICK_SOUTH) ? diffy : diffy/2;
    }
2604
2605
2606
2607
2608
2609
2610
2611
2612


2613
2614
2615
2616
2617
2618
2619
2620
2621

2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632



2633
2634
2635
2636
2637


2638
2639
2640


2641
2642
2643
2644
2645
2646
2647
2648
2649
2650

2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661

2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678


2679
2680
2681
2682

2683
2684

2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698

2699
2700

2701
2702

2703
2704
2705
2706
2707
2708
2709
2710
2711


2712
2713
2714
2715

2716
2717

2718
2719
2720
2721



2722
2723

2724
2725
2726
2727

2728
2729

2730
2731
2732
2733
2734
2735
2736
2604
2605
2606
2607
2608
2609
2610


2611
2612
2613
2614
2615
2616
2617
2618
2619
2620

2621
2622
2623
2624
2625
2626
2627
2628
2629



2630
2631
2632
2633
2634
2635


2636
2637
2638


2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649

2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660

2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676


2677
2678
2679
2680
2681

2682
2683

2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697

2698
2699

2700
2701

2702
2703
2704
2705
2706
2707
2708
2709


2710
2711
2712
2713
2714

2715
2716

2717
2718



2719
2720
2721
2722

2723
2724
2725
2726

2727
2728

2729
2730
2731
2732
2733
2734
2735
2736







-
-
+
+








-
+








-
-
-
+
+
+



-
-
+
+

-
-
+
+









-
+










-
+















-
-
+
+



-
+

-
+













-
+

-
+

-
+







-
-
+
+



-
+

-
+

-
-
-
+
+
+

-
+



-
+

-
+







static void
MoveSash(
    PanedWindow *pwPtr,
    int sash,
    int diff)
{
    int i;
    int expandPane, reduceFirst, reduceLast, reduceIncr, slaveSize, sashOffset;
    Slave *slavePtr;
    int expandPane, reduceFirst, reduceLast, reduceIncr, paneSize, sashOffset;
    Pane *panePtr;
    int stretchReserve = 0;
    int nextSash = sash + 1;
    const int horizontal = (pwPtr->orient == ORIENT_HORIZONTAL);

    if (diff == 0)
	return;

    /*
     * Update the slave sizes with their real sizes.
     * Update the pane sizes with their real sizes.
     */

    if (pwPtr->showHandle && pwPtr->handleSize > pwPtr->sashWidth) {
	sashOffset = ((pwPtr->handleSize - pwPtr->sashWidth) / 2)
		+ pwPtr->sashPad;
    } else {
	sashOffset = pwPtr->sashPad;
    }
    for (i = 0; i < pwPtr->numSlaves; i++) {
	slavePtr = pwPtr->slaves[i];
	if (slavePtr->hide) {
    for (i = 0; i < pwPtr->numPanes; i++) {
	panePtr = pwPtr->panes[i];
	if (panePtr->hide) {
	    continue;
	}
	if (horizontal) {
	    slavePtr->paneWidth = slavePtr->width = slavePtr->sashx
		    - sashOffset - slavePtr->x - (2 * slavePtr->padx);
	    panePtr->paneWidth = panePtr->width = panePtr->sashx
		    - sashOffset - panePtr->x - (2 * panePtr->padx);
	} else {
	    slavePtr->paneHeight = slavePtr->height = slavePtr->sashy
		    - sashOffset - slavePtr->y - (2 * slavePtr->pady);
	    panePtr->paneHeight = panePtr->height = panePtr->sashy
		    - sashOffset - panePtr->y - (2 * panePtr->pady);
	}
    }

    /*
     * There must be a next sash since it is only possible to enter this
     * routine when moving an actual sash which implies there exists a visible
     * pane to either side of the sash.
     */

    while (nextSash < pwPtr->numSlaves-1 && pwPtr->slaves[nextSash]->hide) {
    while (nextSash < pwPtr->numPanes-1 && pwPtr->panes[nextSash]->hide) {
	nextSash++;
    }

    /*
     * Consolidate +/-diff variables to reduce duplicate code.
     */

    if (diff > 0) {
	expandPane = sash;
	reduceFirst = nextSash;
	reduceLast = pwPtr->numSlaves;
	reduceLast = pwPtr->numPanes;
	reduceIncr = 1;
    } else {
	diff = abs(diff);
	expandPane = nextSash;
	reduceFirst = sash;
	reduceLast = -1;
	reduceIncr = -1;
    }

    /*
     * Calculate how much room we have to stretch in and adjust diff value
     * accordingly.
     */

    for (i = reduceFirst; i != reduceLast; i += reduceIncr) {
	slavePtr = pwPtr->slaves[i];
	if (slavePtr->hide) {
	panePtr = pwPtr->panes[i];
	if (panePtr->hide) {
	    continue;
	}
	if (horizontal) {
	    stretchReserve += slavePtr->width - slavePtr->minSize;
	    stretchReserve += panePtr->width - panePtr->minSize;
	} else {
	    stretchReserve += slavePtr->height - slavePtr->minSize;
	    stretchReserve += panePtr->height - panePtr->minSize;
	}
    }
    if (stretchReserve <= 0) {
	return;
    }
    if (diff > stretchReserve) {
	diff = stretchReserve;
    }

    /*
     * Expand pane by diff amount.
     */

    slavePtr = pwPtr->slaves[expandPane];
    panePtr = pwPtr->panes[expandPane];
    if (horizontal) {
	slavePtr->paneWidth = slavePtr->width += diff;
	panePtr->paneWidth = panePtr->width += diff;
    } else {
	slavePtr->paneHeight = slavePtr->height += diff;
	panePtr->paneHeight = panePtr->height += diff;
    }

    /*
     * Reduce panes, respecting minsize, until diff amount has been used.
     */

    for (i = reduceFirst; i != reduceLast; i += reduceIncr) {
	slavePtr = pwPtr->slaves[i];
	if (slavePtr->hide) {
	panePtr = pwPtr->panes[i];
	if (panePtr->hide) {
	    continue;
	}
	if (horizontal) {
	    slaveSize = slavePtr->width;
	    paneSize = panePtr->width;
	} else {
	    slaveSize = slavePtr->height;
	    paneSize = panePtr->height;
	}
	if (diff > (slaveSize - slavePtr->minSize)) {
	    diff -= slaveSize - slavePtr->minSize;
	    slaveSize = slavePtr->minSize;
	if (diff > (paneSize - panePtr->minSize)) {
	    diff -= paneSize - panePtr->minSize;
	    paneSize = panePtr->minSize;
	} else {
	    slaveSize -= diff;
	    paneSize -= diff;
	    i = reduceLast - reduceIncr;
	}
	if (horizontal) {
	    slavePtr->paneWidth = slavePtr->width = slaveSize;
	    panePtr->paneWidth = panePtr->width = paneSize;
	} else {
	    slavePtr->paneHeight = slavePtr->height = slaveSize;
	    panePtr->paneHeight = panePtr->height = paneSize;
	}
    }
}

/*
 *----------------------------------------------------------------------
 *
2750
2751
2752
2753
2754
2755
2756
2757

2758
2759
2760
2761
2762
2763
2764
2750
2751
2752
2753
2754
2755
2756

2757
2758
2759
2760
2761
2762
2763
2764







-
+







 */

static void
ProxyWindowEventProc(
    ClientData clientData,	/* Information about window. */
    XEvent *eventPtr)		/* Information about event. */
{
    PanedWindow *pwPtr = clientData;
    PanedWindow *pwPtr = (PanedWindow *)clientData;

    if (eventPtr->type == Expose) {
	if (pwPtr->proxywin != NULL &&!(pwPtr->flags & PROXY_REDRAW_PENDING)) {
	    Tcl_DoWhenIdle(DisplayProxyWindow, pwPtr);
	    pwPtr->flags |= PROXY_REDRAW_PENDING;
	}
    }
2782
2783
2784
2785
2786
2787
2788
2789

2790
2791
2792
2793
2794
2795
2796
2782
2783
2784
2785
2786
2787
2788

2789
2790
2791
2792
2793
2794
2795
2796







-
+







 *--------------------------------------------------------------
 */

static void
DisplayProxyWindow(
    ClientData clientData)	/* Information about window. */
{
    PanedWindow *pwPtr = clientData;
    PanedWindow *pwPtr = (PanedWindow *)clientData;
    Pixmap pixmap;
    Tk_Window tkwin = pwPtr->proxywin;
    pwPtr->flags &= ~PROXY_REDRAW_PENDING;
    if ((tkwin == NULL) || !Tk_IsMapped(tkwin)) {
	return;
    }

2872
2873
2874
2875
2876
2877
2878
2879
2880


2881
2882
2883
2884
2885
2886
2887
2872
2873
2874
2875
2876
2877
2878


2879
2880
2881
2882
2883
2884
2885
2886
2887







-
-
+
+







    switch ((enum options) index) {
    case PROXY_COORD:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 3, objv, NULL);
	    return TCL_ERROR;
	}

	coords[0] = Tcl_NewIntObj(pwPtr->proxyx);
	coords[1] = Tcl_NewIntObj(pwPtr->proxyy);
	coords[0] = Tcl_NewWideIntObj(pwPtr->proxyx);
	coords[1] = Tcl_NewWideIntObj(pwPtr->proxyy);
	Tcl_SetObjResult(interp, Tcl_NewListObj(2, coords));
	break;

    case PROXY_FORGET:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 3, objv, NULL);
	    return TCL_ERROR;
2902
2903
2904
2905
2906
2907
2908
2909

2910
2911
2912
2913
2914
2915
2916
2917
2918

2919
2920
2921

2922
2923
2924
2925
2926
2927
2928
2929
2930

2931
2932
2933

2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952

2953
2954

2955
2956
2957
2958
2959
2960
2961
2902
2903
2904
2905
2906
2907
2908

2909
2910
2911
2912
2913
2914
2915
2916
2917

2918
2919
2920

2921
2922
2923
2924
2925
2926
2927
2928
2929

2930
2931
2932

2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951

2952
2953

2954
2955
2956
2957
2958
2959
2960
2961







-
+








-
+


-
+








-
+


-
+


















-
+

-
+







	    return TCL_ERROR;
	}

	if (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK) {
	    return TCL_ERROR;
	}

        internalBW = Tk_InternalBorderWidth(pwPtr->tkwin);
        internalBW = Tk_InternalBorderLeft(pwPtr->tkwin);
	if (pwPtr->orient == ORIENT_HORIZONTAL) {
	    if (x < 0) {
		x = 0;
	    }
            pwWidth = Tk_Width(pwPtr->tkwin) - (2 * internalBW);
            if (x > pwWidth) {
                x = pwWidth;
            }
            y = Tk_InternalBorderWidth(pwPtr->tkwin);
            y = Tk_InternalBorderLeft(pwPtr->tkwin);
	    sashWidth = pwPtr->sashWidth;
	    sashHeight = Tk_Height(pwPtr->tkwin) -
		    (2 * Tk_InternalBorderWidth(pwPtr->tkwin));
		    (2 * Tk_InternalBorderLeft(pwPtr->tkwin));
	} else {
	    if (y < 0) {
		y = 0;
	    }
            pwHeight = Tk_Height(pwPtr->tkwin) - (2 * internalBW);
            if (y > pwHeight) {
                y = pwHeight;
            }
	    x = Tk_InternalBorderWidth(pwPtr->tkwin);
	    x = Tk_InternalBorderLeft(pwPtr->tkwin);
	    sashHeight = pwPtr->sashWidth;
	    sashWidth = Tk_Width(pwPtr->tkwin) -
		    (2 * Tk_InternalBorderWidth(pwPtr->tkwin));
		    (2 * Tk_InternalBorderLeft(pwPtr->tkwin));
	}

	if (sashWidth < 1) {
	    sashWidth = 1;
	}
	if (sashHeight < 1) {
	    sashHeight = 1;
	}

	/*
	 * Stash the proxy coordinates for future "proxy coord" calls.
	 */

	pwPtr->proxyx = x;
	pwPtr->proxyy = y;

	/*
	 * Make sure the proxy window is higher in the stacking order than the
	 * slaves, so that it will be visible when drawn. It would be more
	 * panes, so that it will be visible when drawn. It would be more
	 * correct to push the proxy window just high enough to appear above
	 * the highest slave, but it's much easier to just force it all the
	 * the highest pane, but it's much easier to just force it all the
	 * way to the top of the stacking order.
	 */

	Tk_RestackWindow(pwPtr->proxywin, Above, NULL);

	/*
	 * Let Tk_MaintainGeometry take care of placing the window at the
3015
3016
3017
3018
3019
3020
3021
3022

3023
3024
3025


3026
3027
3028


3029
3030
3031
3032
3033
3034
3035
3015
3016
3017
3018
3019
3020
3021

3022
3023


3024
3025
3026


3027
3028
3029
3030
3031
3032
3033
3034
3035







-
+

-
-
+
+

-
-
+
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static char *
static void *
ComputeSlotAddress(
    char *recordPtr,	/* Pointer to the start of a record. */
    int offset)		/* Offset of a slot within that record; may be < 0. */
    void *recordPtr,	/* Pointer to the start of a record. */
    TkSizeT offset)		/* Offset of a slot within that record; may be TCL_INDEX_NONE. */
{
    if (offset >= 0) {
	return recordPtr + offset;
    if (offset != TCL_INDEX_NONE) {
	return (char *)recordPtr + offset;
    } else {
	return NULL;
    }
}

/*
 *----------------------------------------------------------------------
3062
3063
3064
3065
3066
3067
3068
3069

3070
3071
3072
3073
3074
3075
3076
3062
3063
3064
3065
3066
3067
3068

3069
3070
3071
3072
3073
3074
3075
3076







-
+








    if (pwPtr->orient == ORIENT_HORIZONTAL) {
	if (Tk_IsMapped(pwPtr->tkwin)) {
	    sashHeight = Tk_Height(pwPtr->tkwin);
	} else {
	    sashHeight = Tk_ReqHeight(pwPtr->tkwin);
	}
	sashHeight -= 2 * Tk_InternalBorderWidth(pwPtr->tkwin);
	sashHeight -= 2 * Tk_InternalBorderLeft(pwPtr->tkwin);
	if (pwPtr->showHandle && pwPtr->handleSize > pwPtr->sashWidth) {
	    sashWidth = pwPtr->handleSize;
	    lpad = (pwPtr->handleSize - pwPtr->sashWidth) / 2;
	    rpad = pwPtr->handleSize - lpad;
	    lpad += pwPtr->sashPad;
	    rpad += pwPtr->sashPad;
	} else {
3090
3091
3092
3093
3094
3095
3096
3097

3098
3099
3100
3101
3102
3103
3104
3105


3106
3107
3108
3109


3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121


3122
3123
3124
3125
3126
3127
3128
3090
3091
3092
3093
3094
3095
3096

3097
3098
3099
3100
3101
3102
3103


3104
3105
3106
3107


3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119


3120
3121
3122
3123
3124
3125
3126
3127
3128







-
+






-
-
+
+


-
-
+
+










-
-
+
+







	    tpad = bpad = pwPtr->sashPad;
	}
	if (Tk_IsMapped(pwPtr->tkwin)) {
	    sashWidth = Tk_Width(pwPtr->tkwin);
	} else {
	    sashWidth = Tk_ReqWidth(pwPtr->tkwin);
	}
	sashWidth -= 2 * Tk_InternalBorderWidth(pwPtr->tkwin);
	sashWidth -= 2 * Tk_InternalBorderLeft(pwPtr->tkwin);
	lpad = rpad = 0;
    }

    GetFirstLastVisiblePane(pwPtr, &first, &last);
    isHandle = 0;
    found = -1;
    for (i = 0; i < pwPtr->numSlaves - 1; i++) {
	if (pwPtr->slaves[i]->hide || i == last) {
    for (i = 0; i < pwPtr->numPanes - 1; i++) {
	if (pwPtr->panes[i]->hide || i == last) {
	    continue;
	}
	thisx = pwPtr->slaves[i]->sashx;
	thisy = pwPtr->slaves[i]->sashy;
	thisx = pwPtr->panes[i]->sashx;
	thisy = pwPtr->panes[i]->sashy;

	if (((thisx - lpad) <= x && x <= (thisx + rpad + sashWidth)) &&
		((thisy - tpad) <= y && y <= (thisy + bpad + sashHeight))) {
	    found = i;

	    /*
	     * Determine if the point is over the handle or the sash.
	     */

	    if (pwPtr->showHandle) {
		thisx = pwPtr->slaves[i]->handlex;
		thisy = pwPtr->slaves[i]->handley;
		thisx = pwPtr->panes[i]->handlex;
		thisy = pwPtr->panes[i]->handley;
		if (pwPtr->orient == ORIENT_HORIZONTAL) {
		    if (thisy <= y && y <= (thisy + pwPtr->handleSize)) {
			isHandle = 1;
		    }
		} else {
		    if (thisx <= x && x <= (thisx + pwPtr->handleSize)) {
			isHandle = 1;
3137
3138
3139
3140
3141
3142
3143
3144

3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3137
3138
3139
3140
3141
3142
3143

3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157







-
+













     * Set results. Note that the empty string is the default (this function
     * is called inside the implementation of a command).
     */

    if (found != -1) {
	Tcl_Obj *list[2];

	list[0] = Tcl_NewIntObj(found);
	list[0] = Tcl_NewWideIntObj(found);
	list[1] = Tcl_NewStringObj((isHandle ? "handle" : "sash"), -1);
	Tcl_SetObjResult(interp, Tcl_NewListObj(2, list));
    }
    return TCL_OK;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Added generic/tkPkgConfig.c.









































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
 * tkPkgConfig.c --
 *
 *	This file contains the configuration information to embed into the tcl
 *	binary library.
 *
 * Copyright © 2002 Andreas Kupries <[email protected]>
 * Copyright © 2017 Stuart Cassoff <[email protected]>
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

/* Note, the definitions in this module are influenced by the following C
 * preprocessor macros:
 *
 * OSCMa  = shortcut for "old style configuration macro activates"
 * NSCMdt = shortcut for "new style configuration macro declares that"
 *
 * - TCL_THREADS		OSCMa compilation as threaded.
 * - TCL_MEM_DEBUG		OSCMa memory debugging.
 *
 * - TCL_CFG_DO64BIT		NSCMdt tk is compiled for a 64bit system.
 * - NDEBUG			NSCMdt tk is compiled with symbol info off.
 * - TCL_CFG_OPTIMIZED		NSCMdt tk is compiled with cc optimizations on
 * - TCL_CFG_PROFILED		NSCMdt tk is compiled with profiling info.
 *
 * - _WIN32 || __CYGWIN__	The value for the fontsytem key will be
 *   MAC_OSX_TK			chosen based on these macros/defines.
 *   HAVE_XFT			NSCMdt xft font support was requested.
 *
 * - CFG_RUNTIME_*		Paths to various stuff at runtime.
 * - CFG_INSTALL_*		Paths to various stuff at installation time.
 *
 * - TCL_CFGVAL_ENCODING	string containing the encoding used for the
 *				configuration values.
 */

#include "tkInt.h"


#ifndef TCL_CFGVAL_ENCODING
#define TCL_CFGVAL_ENCODING "utf-8"
#endif

/*
 * Use C preprocessor statements to define the various values for the embedded
 * configuration information.
 */

#ifdef TCL_THREADS
#  define  CFG_THREADED		"1"
#else
#  define  CFG_THREADED		"0"
#endif

#ifdef TCL_MEM_DEBUG
#  define CFG_MEMDEBUG		"1"
#else
#  define CFG_MEMDEBUG		"0"
#endif

#ifdef TCL_CFG_DO64BIT
#  define CFG_64		"1"
#else
#  define CFG_64		"0"
#endif

#ifndef NDEBUG
#  define CFG_DEBUG		"1"
#else
#  define CFG_DEBUG		"0"
#endif

#ifdef TCL_CFG_OPTIMIZED
#  define CFG_OPTIMIZED		"1"
#else
#  define CFG_OPTIMIZED		"0"
#endif

#ifdef TCL_CFG_PROFILED
#  define CFG_PROFILED		"1"
#else
#  define CFG_PROFILED		"0"
#endif

#if defined(_WIN32)
#  define CFG_FONTSYSTEM	"gdi"
#elif defined(MAC_OSX_TK)
#  define CFG_FONTSYSTEM	"cocoa"
#elif defined(HAVE_XFT)
#  define CFG_FONTSYSTEM	"xft"
#else
#  define CFG_FONTSYSTEM	"x11"
#endif

static const Tcl_Config cfg[] = {
    {"debug",			CFG_DEBUG},
    {"threaded",		CFG_THREADED},
    {"profiled",		CFG_PROFILED},
    {"64bit",			CFG_64},
    {"optimized",		CFG_OPTIMIZED},
#ifdef TK_NO_DEPRECATED
    {"nodeprecated",	"1"},
#endif
    {"mem_debug",		CFG_MEMDEBUG},
    {"fontsystem",		CFG_FONTSYSTEM},

    /* Runtime paths to various stuff */

#ifdef CFG_RUNTIME_LIBDIR
    {"libdir,runtime",		CFG_RUNTIME_LIBDIR},
#endif
#ifdef CFG_RUNTIME_BINDIR
    {"bindir,runtime",		CFG_RUNTIME_BINDIR},
#endif
#ifdef CFG_RUNTIME_SCRDIR
    {"scriptdir,runtime",	CFG_RUNTIME_SCRDIR},
#endif
#ifdef CFG_RUNTIME_INCDIR
    {"includedir,runtime",	CFG_RUNTIME_INCDIR},
#endif
#ifdef CFG_RUNTIME_DOCDIR
    {"docdir,runtime",		CFG_RUNTIME_DOCDIR},
#endif
#ifdef CFG_RUNTIME_DEMODIR
    {"demodir,runtime",		CFG_RUNTIME_DEMODIR},
#endif

    /* Installation paths to various stuff */

#ifdef CFG_INSTALL_LIBDIR
    {"libdir,install",		CFG_INSTALL_LIBDIR},
#endif
#ifdef CFG_INSTALL_BINDIR
    {"bindir,install",		CFG_INSTALL_BINDIR},
#endif
#ifdef CFG_INSTALL_SCRDIR
    {"scriptdir,install",	CFG_INSTALL_SCRDIR},
#endif
#ifdef CFG_INSTALL_INCDIR
    {"includedir,install",	CFG_INSTALL_INCDIR},
#endif
#ifdef CFG_INSTALL_DOCDIR
    {"docdir,install",		CFG_INSTALL_DOCDIR},
#endif
#ifdef CFG_INSTALL_DEMODIR
    {"demodir,install",		CFG_INSTALL_DEMODIR},
#endif

    /* Last entry, closes the array */
    {NULL, NULL}
};

void
TkInitEmbeddedConfigurationInformation(
    Tcl_Interp *interp)		/* Interpreter the configuration command is
				 * registered in. */
{
    Tcl_RegisterConfig(interp, "tk", cfg, TCL_CFGVAL_ENCODING);
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Changes to generic/tkPlace.c.
1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
16
17
18
19
20

21
22
23


24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

39
40
41

42
43
44

45
46
47


48
49
50
51
52
53
54
55
56
57
58
59
60

61
62
63
64
65
66
67

68
69
70
71
72

73
74
75

76
77
78
79
80
81
82
83
84
85
86
87
88
89
90







91
92
93

94
95
96

97
98
99
100
101
102
103
104
105
106
107
108











109
110
111
112

113
114
115
116
117
118
119
120
121
122
123
124
125
126

127
128
129
130
131
132
133




134
135
136
137
138

139
140
141

142
143
144

145
146
147
148
149
150
151
152
153
154
155
156
157
158

159
160
161
162
163
164

165
166
167
168
169
170
171

172
173

174
175
176
177
178
179
180
181
182






183
184
185

186
187
188
189
190
191
192
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15
16
17
18
19

20
21


22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

38
39
40

41
42
43

44
45


46
47
48
49
50
51
52
53
54
55
56
57
58
59

60
61
62
63
64
65
66

67
68
69
70
71

72
73
74

75
76
77
78
79
80
81
82
83







84
85
86
87
88
89
90
91
92

93
94
95

96
97











98
99
100
101
102
103
104
105
106
107
108
109
110
111

112
113
114
115
116
117
118
119
120
121
122
123
124
125

126
127
128
129




130
131
132
133
134
135
136
137

138
139
140

141
142
143

144
145
146
147
148
149
150
151
152
153
154
155
156
157

158
159
160
161
162
163

164
165
166
167
168
169
170

171
172

173
174
175
176






177
178
179
180
181
182
183
184

185
186
187
188
189
190
191
192






-
-
+
+











-
+

-
-
+
+














-
+


-
+


-
+

-
-
+
+












-
+






-
+




-
+


-
+








-
-
-
-
-
-
-
+
+
+
+
+
+
+


-
+


-
+

-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+



-
+













-
+



-
-
-
-
+
+
+
+




-
+


-
+


-
+













-
+





-
+






-
+

-
+



-
-
-
-
-
-
+
+
+
+
+
+


-
+







/*
 * 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.
 */

#include "tkInt.h"

/*
 * Border modes for relative placement:
 *
 * BM_INSIDE:		relative distances computed using area inside all
 *			borders of master window.
 *			borders of container window.
 * BM_OUTSIDE:		relative distances computed using outside area that
 *			includes all borders of master.
 * BM_IGNORE:		border issues are ignored: place relative to master's
 *			includes all borders of container.
 * BM_IGNORE:		border issues are ignored: place relative to container's
 *			actual window size.
 */

static const char *const borderModeStrings[] = {
    "inside", "outside", "ignore", NULL
};

typedef enum {BM_INSIDE, BM_OUTSIDE, BM_IGNORE} BorderMode;

/*
 * For each window whose geometry is managed by the placer there is a
 * structure of the following type:
 */

typedef struct Slave {
typedef struct Content {
    Tk_Window tkwin;		/* Tk's token for window. */
    Tk_Window inTkwin;		/* Token for the -in window. */
    struct Master *masterPtr;	/* Pointer to information for window relative
    struct Container *containerPtr;	/* Pointer to information for window relative
				 * to which tkwin is placed. This isn't
				 * necessarily the logical parent of tkwin.
				 * NULL means the master was deleted or never
				 * NULL means the container was deleted or never
				 * assigned. */
    struct Slave *nextPtr;	/* Next in list of windows placed relative to
				 * same master (NULL for end of list). */
    struct Content *nextPtr;	/* Next in list of windows placed relative to
				 * same container (NULL for end of list). */
    Tk_OptionTable optionTable;	/* Table that defines configuration options
				 * available for this command. */
    /*
     * Geometry information for window; where there are both relative and
     * absolute values for the same attribute (e.g. x and relX) only one of
     * them is actually used, depending on flags.
     */

    int x, y;			/* X and Y pixel coordinates for tkwin. */
    Tcl_Obj *xPtr, *yPtr;	/* Tcl_Obj rep's of x, y coords, to keep pixel
				 * spec. information. */
    double relX, relY;		/* X and Y coordinates relative to size of
				 * master. */
				 * container. */
    int width, height;		/* Absolute dimensions for tkwin. */
    Tcl_Obj *widthPtr;		/* Tcl_Obj rep of width, to keep pixel
				 * spec. */
    Tcl_Obj *heightPtr;		/* Tcl_Obj rep of height, to keep pixel
				 * spec. */
    double relWidth, relHeight;	/* Dimensions for tkwin relative to size of
				 * master. */
				 * container. */
    Tcl_Obj *relWidthPtr;
    Tcl_Obj *relHeightPtr;
    Tk_Anchor anchor;		/* Which point on tkwin is placed at the given
				 * position. */
    BorderMode borderMode;	/* How to treat borders of master window. */
    BorderMode borderMode;	/* How to treat borders of container window. */
    int flags;			/* Various flags; see below for bit
				 * definitions. */
} Slave;
} Content;

/*
 * Type masks for options:
 */

#define IN_MASK		1

static const Tk_OptionSpec optionSpecs[] = {
    {TK_OPTION_ANCHOR, "-anchor", NULL, NULL, "nw", -1,
	 Tk_Offset(Slave, anchor), 0, 0, 0},
    {TK_OPTION_STRING_TABLE, "-bordermode", NULL, NULL, "inside", -1,
	 Tk_Offset(Slave, borderMode), 0, borderModeStrings, 0},
    {TK_OPTION_PIXELS, "-height", NULL, NULL, "", Tk_Offset(Slave, heightPtr),
	 Tk_Offset(Slave, height), TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_WINDOW, "-in", NULL, NULL, "", -1, Tk_Offset(Slave, inTkwin),
    {TK_OPTION_ANCHOR, "-anchor", NULL, NULL, "nw", TCL_INDEX_NONE,
	 offsetof(Content, anchor), 0, 0, 0},
    {TK_OPTION_STRING_TABLE, "-bordermode", NULL, NULL, "inside", TCL_INDEX_NONE,
	 offsetof(Content, borderMode), 0, borderModeStrings, 0},
    {TK_OPTION_PIXELS, "-height", NULL, NULL, "", offsetof(Content, heightPtr),
	 offsetof(Content, height), TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_WINDOW, "-in", NULL, NULL, "", TCL_INDEX_NONE, offsetof(Content, inTkwin),
	 0, 0, IN_MASK},
    {TK_OPTION_DOUBLE, "-relheight", NULL, NULL, "",
	 Tk_Offset(Slave, relHeightPtr), Tk_Offset(Slave, relHeight),
	 offsetof(Content, relHeightPtr), offsetof(Content, relHeight),
	 TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_DOUBLE, "-relwidth", NULL, NULL, "",
	 Tk_Offset(Slave, relWidthPtr), Tk_Offset(Slave, relWidth),
	 offsetof(Content, relWidthPtr), offsetof(Content, relWidth),
	 TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_DOUBLE, "-relx", NULL, NULL, "0", -1,
	 Tk_Offset(Slave, relX), 0, 0, 0},
    {TK_OPTION_DOUBLE, "-rely", NULL, NULL, "0", -1,
	 Tk_Offset(Slave, relY), 0, 0, 0},
    {TK_OPTION_PIXELS, "-width", NULL, NULL, "", Tk_Offset(Slave, widthPtr),
	 Tk_Offset(Slave, width), TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_PIXELS, "-x", NULL, NULL, "0", Tk_Offset(Slave, xPtr),
	 Tk_Offset(Slave, x), TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_PIXELS, "-y", NULL, NULL, "0", Tk_Offset(Slave, yPtr),
	 Tk_Offset(Slave, y), TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0, 0, 0}
    {TK_OPTION_DOUBLE, "-relx", NULL, NULL, "0", TCL_INDEX_NONE,
	 offsetof(Content, relX), 0, 0, 0},
    {TK_OPTION_DOUBLE, "-rely", NULL, NULL, "0", TCL_INDEX_NONE,
	 offsetof(Content, relY), 0, 0, 0},
    {TK_OPTION_PIXELS, "-width", NULL, NULL, "", offsetof(Content, widthPtr),
	 offsetof(Content, width), TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_PIXELS, "-x", NULL, NULL, "0", offsetof(Content, xPtr),
	 offsetof(Content, x), TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_PIXELS, "-y", NULL, NULL, "0", offsetof(Content, yPtr),
	 offsetof(Content, y), TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, TCL_INDEX_NONE, 0, 0, 0}
};

/*
 * Flag definitions for Slave structures:
 * Flag definitions for Content structures:
 *
 * CHILD_WIDTH -		1 means -width was specified;
 * CHILD_REL_WIDTH -		1 means -relwidth was specified.
 * CHILD_HEIGHT -		1 means -height was specified;
 * CHILD_REL_HEIGHT -		1 means -relheight was specified.
 */

#define CHILD_WIDTH		1
#define CHILD_REL_WIDTH		2
#define CHILD_HEIGHT		4
#define CHILD_REL_HEIGHT	8

/*
 * For each master window that has a slave managed by the placer there is a
 * For each container window that has a content managed by the placer there is a
 * structure of the following form:
 */

typedef struct Master {
    Tk_Window tkwin;		/* Tk's token for master window. */
    struct Slave *slavePtr;	/* First in linked list of slaves placed
				 * relative to this master. */
typedef struct Container {
    Tk_Window tkwin;		/* Tk's token for container window. */
    struct Content *contentPtr;	/* First in linked list of content windowslaced
				 * relative to this container. */
    int *abortPtr;		/* If non-NULL, it means that there is a nested
				 * call to RecomputePlacement already working on
				 * this window.  *abortPtr may be set to 1 to
				 * abort that nested call.  This happens, for
				 * example, if tkwin or any of its slaves
				 * example, if tkwin or any of its content
				 * is deleted. */
    int flags;			/* See below for bit definitions. */
} Master;
} Container;

/*
 * Flag definitions for masters:
 * Flag definitions for containers:
 *
 * PARENT_RECONFIG_PENDING -	1 means that a call to RecomputePlacement is
 *				already pending via a Do_When_Idle handler.
 */

#define PARENT_RECONFIG_PENDING	1

/*
 * The following structure is the official type record for the placer:
 */

static void		PlaceRequestProc(ClientData clientData,
			    Tk_Window tkwin);
static void		PlaceLostSlaveProc(ClientData clientData,
static void		PlaceLostContentProc(ClientData clientData,
			    Tk_Window tkwin);

static const Tk_GeomMgr placerType = {
    "place",			/* name */
    PlaceRequestProc,		/* requestProc */
    PlaceLostSlaveProc,		/* lostSlaveProc */
    PlaceLostContentProc,		/* lostContentProc */
};

/*
 * Forward declarations for functions defined later in this file:
 */

static void		SlaveStructureProc(ClientData clientData,
static void		ContentStructureProc(ClientData clientData,
			    XEvent *eventPtr);
static int		ConfigureSlave(Tcl_Interp *interp, Tk_Window tkwin,
static int		ConfigureContent(Tcl_Interp *interp, Tk_Window tkwin,
			    Tk_OptionTable table, int objc,
			    Tcl_Obj *const objv[]);
static int		PlaceInfoCommand(Tcl_Interp *interp, Tk_Window tkwin);
static Slave *		CreateSlave(Tk_Window tkwin, Tk_OptionTable table);
static void		FreeSlave(Slave *slavePtr);
static Slave *		FindSlave(Tk_Window tkwin);
static Master *		CreateMaster(Tk_Window tkwin);
static Master *		FindMaster(Tk_Window tkwin);
static void		MasterStructureProc(ClientData clientData,
static Content *		CreateContent(Tk_Window tkwin, Tk_OptionTable table);
static void		FreeContent(Content *contentPtr);
static Content *		FindContent(Tk_Window tkwin);
static Container *		CreateContainer(Tk_Window tkwin);
static Container *		FindContainer(Tk_Window tkwin);
static void		PlaceStructureProc(ClientData clientData,
			    XEvent *eventPtr);
static void		RecomputePlacement(ClientData clientData);
static void		UnlinkSlave(Slave *slavePtr);
static void		UnlinkContent(Content *contentPtr);

/*
 *--------------------------------------------------------------
 *
 * Tk_PlaceObjCmd --
 *
 *	This function is invoked to process the "place" Tcl commands. See the
204
205
206
207
208
209
210
211

212
213

214
215
216



217

218
219

220
221
222
223
224
225
226
204
205
206
207
208
209
210

211
212

213
214
215
216
217
218
219

220
221

222
223
224
225
226
227
228
229







-
+

-
+



+
+
+
-
+

-
+







int
Tk_PlaceObjCmd(
    ClientData clientData,	/* Interpreter main window. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tk_Window main_win = clientData;
    Tk_Window main_win = (Tk_Window)clientData;
    Tk_Window tkwin;
    Slave *slavePtr;
    Content *contentPtr;
    TkDisplay *dispPtr;
    Tk_OptionTable optionTable;
    static const char *const optionStrings[] = {
	"configure", "content", "forget", "info", "slaves", NULL
    };
    static const char *const optionStringsNoDep[] = {
	"configure", "forget", "info", "slaves", NULL
	"configure", "content", "forget", "info", NULL
    };
    enum options { PLACE_CONFIGURE, PLACE_FORGET, PLACE_INFO, PLACE_SLAVES };
    enum options { PLACE_CONFIGURE, PLACE_CONTENT, PLACE_FORGET, PLACE_INFO, PLACE_SLAVES };
    int index;

    if (objc < 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "option|pathName args");
	return TCL_ERROR;
    }

243
244
245
246
247
248
249
250
251


252
253
254
255

256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275


276
277
278
279
280








281
282
283
284
285
286
287
288
289
290


291
292
293

294
295
296
297
298
299
300
301

302
303
304
305
306
307
308
309


310
311
312
313
314



315
316
317
318
319
320





321
322
323

324
325
326
327
328
329
330
331
332
333
334



335
336
337
338
339
340
341


342
343
344
345


346
347

348
349
350
351
352
353
354
355
356
357
358
359
360
361

362
363

364
365
366
367

368
369
370

371
372
373
374
375
376
377



378
379
380
381

382
383
384
385

386
387

388
389
390
391

392
393
394
395
396
397
398
399
400
401
402
403
404
405











406
407
408
409
410
411

412
413

414
415
416
417
418
419
420
421
422
423
424
425
426


427
428
429
430



431
432
433
434
435
436

437
438

439
440
441
442
443

444
445
446
447
448
449
450
451
452
453



454
455

456
457
458

459
460
461
462

463
464
465
466
467
468

469
470
471


472
473
474
475
476
477

478
479
480
481
482
483
484


485
486
487


488
489
490


491
492
493
494


495
496

497
498

499
500
501


502
503
504
505
506
507
508


509
510

511
512
513
514
515
516

517
518

519
520
521
522

523
524
525

526
527
528
529
530
531
532



533
534
535

536
537
538
539

540
541
542
543
544
545
546
547
548








549
550

551
552

553
554
555
556
557
558

559
560

561
562
563
564
565

566
567
568
569
570
571
572
573
574
575
576



577
578

579
580
581

582
583
584
585

586
587
588
589
590
591

592
593
594
595
596
597
598
599
600
601

602
603
604
605
606
607
608

609
610
611
612
613
614
615

616
617
618
619
620



621
622
623
624
625
626
627
628
629
630

631
632
633


634
635
636
637
638

639
640
641
642
643



644
645
646
647


648
649
650
651


652
653
654
655


656
657
658

659
660

661
662
663
664

665
666
667
668

669
670
671

672
673
674
675


676
677
678
679
680


681
682
683
684
685
686


687
688
689
690
691

692
693
694


695
696
697
698
699
700
701
702
703
704
705



706
707
708


709
710
711
712
713
714


715
716
717
718


719
720

721
722
723

724
725
726
727
728



729
730
731


732
733
734
735

736
737
738
739
740



741
742
743
744

745
746
747
748
749
750
751





752
753
754

755
756
757
758
759
760
761
762



763
764
765
766
767
768
769
246
247
248
249
250
251
252


253
254
255
256
257

258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276


277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299


300
301
302
303

304
305
306
307
308
309
310
311

312
313
314
315
316
317
318


319
320
321
322



323
324
325
326





327
328
329
330
331
332
333

334
335
336
337
338
339
340
341
342
343


344
345
346
347
348
349
350
351


352
353
354
355


356
357
358

359
360
361
362
363
364
365
366
367
368
369
370
371
372

373
374

375
376
377
378

379
380
381

382
383
384
385
386



387
388
389
390
391
392

393
394
395
396

397
398

399
400
401
402

403
404
405
406











407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422

423
424

425
426
427
428
429
430
431
432
433
434
435
436


437
438
439



440
441
442
443
444
445
446
447

448
449

450
451
452
453
454

455
456
457
458
459
460
461
462



463
464
465
466

467
468
469

470
471
472
473

474
475
476
477
478
479

480
481


482
483
484
485
486
487
488

489
490
491
492
493
494


495
496
497


498
499
500


501
502
503
504


505
506
507

508
509

510
511


512
513
514
515
516
517
518


519
520
521

522
523
524
525
526
527

528
529

530
531
532
533

534
535
536

537
538
539
540
541



542
543
544
545
546

547
548
549
550

551
552








553
554
555
556
557
558
559
560
561

562
563

564
565
566
567
568
569

570
571

572
573
574
575
576

577
578
579
580
581
582
583
584
585



586
587
588
589

590
591
592

593
594
595
596

597
598
599
600
601
602

603
604
605
606
607
608
609
610
611
612

613
614
615
616
617
618
619

620
621
622
623
624
625
626

627
628
629



630
631
632
633
634
635
636
637
638
639
640
641

642
643


644
645
646
647
648
649

650
651
652



653
654
655
656
657


658
659
660
661


662
663
664
665


666
667
668
669

670
671

672
673
674
675

676
677
678
679

680
681
682

683
684
685


686
687
688
689
690


691
692
693
694
695
696


697
698
699
700
701
702

703
704


705
706
707
708
709
710
711
712
713
714



715
716
717
718


719
720
721
722
723
724


725
726
727
728


729
730
731

732
733
734

735
736
737



738
739
740
741


742
743
744
745
746

747
748
749



750
751
752
753
754
755

756
757
758





759
760
761
762
763
764
765

766
767
768
769
770
771



772
773
774
775
776
777
778
779
780
781







-
-
+
+



-
+


















-
-
+
+





+
+
+
+
+
+
+
+








-
-
+
+


-
+







-
+






-
-
+
+


-
-
-
+
+
+

-
-
-
-
-
+
+
+
+
+


-
+









-
-
+
+
+





-
-
+
+


-
-
+
+

-
+













-
+

-
+



-
+


-
+




-
-
-
+
+
+



-
+



-
+

-
+



-
+



-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+





-
+

-
+











-
-
+
+

-
-
-
+
+
+





-
+

-
+




-
+







-
-
-
+
+
+

-
+


-
+



-
+





-
+

-
-
+
+





-
+





-
-
+
+

-
-
+
+

-
-
+
+


-
-
+
+

-
+

-
+

-
-
+
+





-
-
+
+

-
+





-
+

-
+



-
+


-
+




-
-
-
+
+
+


-
+



-
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+

-
+

-
+





-
+

-
+




-
+








-
-
-
+
+
+

-
+


-
+



-
+





-
+









-
+






-
+






-
+


-
-
-
+
+
+









-
+

-
-
+
+




-
+


-
-
-
+
+
+


-
-
+
+


-
-
+
+


-
-
+
+


-
+

-
+



-
+



-
+


-
+


-
-
+
+



-
-
+
+




-
-
+
+




-
+

-
-
+
+








-
-
-
+
+
+

-
-
+
+




-
-
+
+


-
-
+
+

-
+


-
+


-
-
-
+
+
+

-
-
+
+



-
+


-
-
-
+
+
+



-
+


-
-
-
-
-
+
+
+
+
+


-
+





-
-
-
+
+
+








	/*
	 * Initialize, if that hasn't been done yet.
	 */

	dispPtr = ((TkWindow *) tkwin)->dispPtr;
	if (!dispPtr->placeInit) {
	    Tcl_InitHashTable(&dispPtr->masterTable, TCL_ONE_WORD_KEYS);
	    Tcl_InitHashTable(&dispPtr->slaveTable, TCL_ONE_WORD_KEYS);
	    Tcl_InitHashTable(&dispPtr->containerTable, TCL_ONE_WORD_KEYS);
	    Tcl_InitHashTable(&dispPtr->contentTable, TCL_ONE_WORD_KEYS);
	    dispPtr->placeInit = 1;
	}

	return ConfigureSlave(interp, tkwin, optionTable, objc-2, objv+2);
	return ConfigureContent(interp, tkwin, optionTable, objc-2, objv+2);
    }

    /*
     * Handle more general case of option followed by window name followed by
     * possible additional arguments.
     */

    if (TkGetWindowFromObj(interp, main_win, objv[2],
	    &tkwin) != TCL_OK) {
	return TCL_ERROR;
    }

    /*
     * Initialize, if that hasn't been done yet.
     */

    dispPtr = ((TkWindow *) tkwin)->dispPtr;
    if (!dispPtr->placeInit) {
	Tcl_InitHashTable(&dispPtr->masterTable, TCL_ONE_WORD_KEYS);
	Tcl_InitHashTable(&dispPtr->slaveTable, TCL_ONE_WORD_KEYS);
	Tcl_InitHashTable(&dispPtr->containerTable, TCL_ONE_WORD_KEYS);
	Tcl_InitHashTable(&dispPtr->contentTable, TCL_ONE_WORD_KEYS);
	dispPtr->placeInit = 1;
    }

    if (Tcl_GetIndexFromObjStruct(interp, objv[1], optionStrings,
	    sizeof(char *), "option", 0, &index) != TCL_OK) {
	/*
	 * Call it again without the deprecated ones to get a proper error
	 * message. This works well since there can't be any ambiguity between
	 * deprecated and new options.
	 */

	Tcl_GetIndexFromObjStruct(interp, objv[1], optionStringsNoDep,
		sizeof(char *), "option", 0, &index);
	return TCL_ERROR;
    }

    switch ((enum options) index) {
    case PLACE_CONFIGURE:
	if (objc == 3 || objc == 4) {
	    Tcl_Obj *objPtr;

	    slavePtr = FindSlave(tkwin);
	    if (slavePtr == NULL) {
	    contentPtr = FindContent(tkwin);
	    if (contentPtr == NULL) {
		return TCL_OK;
	    }
	    objPtr = Tk_GetOptionInfo(interp, (char *) slavePtr, optionTable,
	    objPtr = Tk_GetOptionInfo(interp, contentPtr, optionTable,
		    (objc == 4) ? objv[3] : NULL, tkwin);
	    if (objPtr == NULL) {
		return TCL_ERROR;
	    }
	    Tcl_SetObjResult(interp, objPtr);
	    return TCL_OK;
	}
	return ConfigureSlave(interp, tkwin, optionTable, objc-3, objv+3);
	return ConfigureContent(interp, tkwin, optionTable, objc-3, objv+3);

    case PLACE_FORGET:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "pathName");
	    return TCL_ERROR;
	}
	slavePtr = FindSlave(tkwin);
	if (slavePtr == NULL) {
	contentPtr = FindContent(tkwin);
	if (contentPtr == NULL) {
	    return TCL_OK;
	}
	if ((slavePtr->masterPtr != NULL) &&
		(slavePtr->masterPtr->tkwin != Tk_Parent(slavePtr->tkwin))) {
	    Tk_UnmaintainGeometry(slavePtr->tkwin, slavePtr->masterPtr->tkwin);
	if ((contentPtr->containerPtr != NULL) &&
		(contentPtr->containerPtr->tkwin != Tk_Parent(contentPtr->tkwin))) {
	    Tk_UnmaintainGeometry(contentPtr->tkwin, contentPtr->containerPtr->tkwin);
	}
	UnlinkSlave(slavePtr);
	Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->slaveTable,
		(char *) tkwin));
	Tk_DeleteEventHandler(tkwin, StructureNotifyMask, SlaveStructureProc,
		slavePtr);
	UnlinkContent(contentPtr);
	Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->contentTable,
		tkwin));
	Tk_DeleteEventHandler(tkwin, StructureNotifyMask, ContentStructureProc,
		contentPtr);
	Tk_ManageGeometry(tkwin, NULL, NULL);
	Tk_UnmapWindow(tkwin);
	FreeSlave(slavePtr);
	FreeContent(contentPtr);
	break;

    case PLACE_INFO:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "pathName");
	    return TCL_ERROR;
	}
	return PlaceInfoCommand(interp, tkwin);

    case PLACE_SLAVES: {
	Master *masterPtr;
    case PLACE_SLAVES:
    case PLACE_CONTENT: {
	Container *containerPtr;

	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "pathName");
	    return TCL_ERROR;
	}
	masterPtr = FindMaster(tkwin);
	if (masterPtr != NULL) {
	containerPtr = FindContainer(tkwin);
	if (containerPtr != NULL) {
	    Tcl_Obj *listPtr = Tcl_NewObj();

	    for (slavePtr = masterPtr->slavePtr; slavePtr != NULL;
		    slavePtr = slavePtr->nextPtr) {
	    for (contentPtr = containerPtr->contentPtr; contentPtr != NULL;
		    contentPtr = contentPtr->nextPtr) {
		Tcl_ListObjAppendElement(NULL, listPtr,
			TkNewWindowObj(slavePtr->tkwin));
			Tk_NewWindowObj(contentPtr->tkwin));
	    }
	    Tcl_SetObjResult(interp, listPtr);
	}
	break;
    }
    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * CreateSlave --
 * CreateContent --
 *
 *	Given a Tk_Window token, find the Slave structure corresponding to
 *	Given a Tk_Window token, find the Content structure corresponding to
 *	that token, creating a new one if necessary.
 *
 * Results:
 *	Pointer to the Slave structure.
 *	Pointer to the Content structure.
 *
 * Side effects:
 *	A new Slave structure may be created.
 *	A new Content structure may be created.
 *
 *----------------------------------------------------------------------
 */

static Slave *
CreateSlave(
    Tk_Window tkwin,		/* Token for desired slave. */
static Content *
CreateContent(
    Tk_Window tkwin,		/* Token for desired content. */
    Tk_OptionTable table)
{
    Tcl_HashEntry *hPtr;
    register Slave *slavePtr;
    Content *contentPtr;
    int isNew;
    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;

    hPtr = Tcl_CreateHashEntry(&dispPtr->slaveTable, (char *) tkwin, &isNew);
    hPtr = Tcl_CreateHashEntry(&dispPtr->contentTable, (char *) tkwin, &isNew);
    if (!isNew) {
	return Tcl_GetHashValue(hPtr);
	return (Content *)Tcl_GetHashValue(hPtr);
    }

    /*
     * No preexisting slave structure for that window, so make a new one and
     * No preexisting content structure for that window, so make a new one and
     * populate it with some default values.
     */

    slavePtr = ckalloc(sizeof(Slave));
    memset(slavePtr, 0, sizeof(Slave));
    slavePtr->tkwin = tkwin;
    slavePtr->inTkwin = NULL;
    slavePtr->anchor = TK_ANCHOR_NW;
    slavePtr->borderMode = BM_INSIDE;
    slavePtr->optionTable = table;
    Tcl_SetHashValue(hPtr, slavePtr);
    Tk_CreateEventHandler(tkwin, StructureNotifyMask, SlaveStructureProc,
	    slavePtr);
    return slavePtr;
    contentPtr = (Content *)ckalloc(sizeof(Content));
    memset(contentPtr, 0, sizeof(Content));
    contentPtr->tkwin = tkwin;
    contentPtr->inTkwin = NULL;
    contentPtr->anchor = TK_ANCHOR_NW;
    contentPtr->borderMode = BM_INSIDE;
    contentPtr->optionTable = table;
    Tcl_SetHashValue(hPtr, contentPtr);
    Tk_CreateEventHandler(tkwin, StructureNotifyMask, ContentStructureProc,
	    contentPtr);
    return contentPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * FreeSlave --
 * FreeContent --
 *
 *	Frees the resources held by a Slave structure.
 *	Frees the resources held by a Content structure.
 *
 * Results:
 *	None
 *
 * Side effects:
 *	Memory are freed.
 *
 *----------------------------------------------------------------------
 */

static void
FreeSlave(
    Slave *slavePtr)
FreeContent(
    Content *contentPtr)
{
    Tk_FreeConfigOptions((char *) slavePtr, slavePtr->optionTable,
	    slavePtr->tkwin);
    ckfree(slavePtr);
    Tk_FreeConfigOptions((char *) contentPtr, contentPtr->optionTable,
	    contentPtr->tkwin);
    ckfree(contentPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * FindSlave --
 * FindContent --
 *
 *	Given a Tk_Window token, find the Slave structure corresponding to
 *	Given a Tk_Window token, find the Content structure corresponding to
 *	that token. This is purely a lookup function; it will not create a
 *	record if one does not yet exist.
 *
 * Results:
 *	Pointer to Slave structure; NULL if none exists.
 *	Pointer to Content structure; NULL if none exists.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static Slave *
FindSlave(
    Tk_Window tkwin)		/* Token for desired slave. */
static Content *
FindContent(
    Tk_Window tkwin)		/* Token for desired content. */
{
    register Tcl_HashEntry *hPtr;
    Tcl_HashEntry *hPtr;
    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;

    hPtr = Tcl_FindHashEntry(&dispPtr->slaveTable, (char *) tkwin);
    hPtr = Tcl_FindHashEntry(&dispPtr->contentTable, tkwin);
    if (hPtr == NULL) {
	return NULL;
    }
    return Tcl_GetHashValue(hPtr);
    return (Content *)Tcl_GetHashValue(hPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * UnlinkSlave --
 * UnlinkContent --
 *
 *	This function removes a slave window from the chain of slaves in its
 *	master.
 *	This function removes a content window from the chain of content windows in its
 *	container.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The slave list of slavePtr's master changes.
 *	The content list of contentPtr's container changes.
 *
 *----------------------------------------------------------------------
 */

static void
UnlinkSlave(
    Slave *slavePtr)		/* Slave structure to be unlinked. */
UnlinkContent(
    Content *contentPtr)		/* Content structure to be unlinked. */
{
    register Master *masterPtr;
    register Slave *prevPtr;
    Container *containerPtr;
    Content *prevPtr;

    masterPtr = slavePtr->masterPtr;
    if (masterPtr == NULL) {
    containerPtr = contentPtr->containerPtr;
    if (containerPtr == NULL) {
	return;
    }
    if (masterPtr->slavePtr == slavePtr) {
	masterPtr->slavePtr = slavePtr->nextPtr;
    if (containerPtr->contentPtr == contentPtr) {
	containerPtr->contentPtr = contentPtr->nextPtr;
    } else {
	for (prevPtr = masterPtr->slavePtr; ; prevPtr = prevPtr->nextPtr) {
	for (prevPtr = containerPtr->contentPtr; ; prevPtr = prevPtr->nextPtr) {
	    if (prevPtr == NULL) {
		Tcl_Panic("UnlinkSlave couldn't find slave to unlink");
		Tcl_Panic("UnlinkContent couldn't find content to unlink");
	    }
	    if (prevPtr->nextPtr == slavePtr) {
		prevPtr->nextPtr = slavePtr->nextPtr;
	    if (prevPtr->nextPtr == contentPtr) {
		prevPtr->nextPtr = contentPtr->nextPtr;
		break;
	    }
	}
    }

    if (masterPtr->abortPtr != NULL) {
	*masterPtr->abortPtr = 1;
    if (containerPtr->abortPtr != NULL) {
	*containerPtr->abortPtr = 1;
    }
    slavePtr->masterPtr = NULL;
    contentPtr->containerPtr = NULL;
}

/*
 *----------------------------------------------------------------------
 *
 * CreateMaster --
 * CreateContainer --
 *
 *	Given a Tk_Window token, find the Master structure corresponding to
 *	Given a Tk_Window token, find the Container structure corresponding to
 *	that token, creating a new one if necessary.
 *
 * Results:
 *	Pointer to the Master structure.
 *	Pointer to the Container structure.
 *
 * Side effects:
 *	A new Master structure may be created.
 *	A new Container structure may be created.
 *
 *----------------------------------------------------------------------
 */

static Master *
CreateMaster(
    Tk_Window tkwin)		/* Token for desired master. */
static Container *
CreateContainer(
    Tk_Window tkwin)		/* Token for desired container. */
{
    Tcl_HashEntry *hPtr;
    register Master *masterPtr;
    Container *containerPtr;
    int isNew;
    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;

    hPtr = Tcl_CreateHashEntry(&dispPtr->masterTable, (char *) tkwin, &isNew);
    hPtr = Tcl_CreateHashEntry(&dispPtr->containerTable, (char *)tkwin, &isNew);
    if (isNew) {
	masterPtr = ckalloc(sizeof(Master));
	masterPtr->tkwin = tkwin;
	masterPtr->slavePtr = NULL;
	masterPtr->abortPtr = NULL;
	masterPtr->flags = 0;
	Tcl_SetHashValue(hPtr, masterPtr);
	Tk_CreateEventHandler(masterPtr->tkwin, StructureNotifyMask,
		MasterStructureProc, masterPtr);
	containerPtr = (Container *)ckalloc(sizeof(Container));
	containerPtr->tkwin = tkwin;
	containerPtr->contentPtr = NULL;
	containerPtr->abortPtr = NULL;
	containerPtr->flags = 0;
	Tcl_SetHashValue(hPtr, containerPtr);
	Tk_CreateEventHandler(containerPtr->tkwin, StructureNotifyMask,
		PlaceStructureProc, containerPtr);
    } else {
	masterPtr = Tcl_GetHashValue(hPtr);
	containerPtr = (Container *)Tcl_GetHashValue(hPtr);
    }
    return masterPtr;
    return containerPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * FindMaster --
 * FindContainer --
 *
 *	Given a Tk_Window token, find the Master structure corresponding to
 *	Given a Tk_Window token, find the Container structure corresponding to
 *	that token. This is simply a lookup function; a new record will not be
 *	created if one does not already exist.
 *
 * Results:
 *	Pointer to the Master structure; NULL if one does not exist for the
 *	Pointer to the Container structure; NULL if one does not exist for the
 *	given Tk_Window token.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static Master *
FindMaster(
    Tk_Window tkwin)		/* Token for desired master. */
static Container *
FindContainer(
    Tk_Window tkwin)		/* Token for desired container. */
{
    register Tcl_HashEntry *hPtr;
    Tcl_HashEntry *hPtr;
    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;

    hPtr = Tcl_FindHashEntry(&dispPtr->masterTable, (char *) tkwin);
    hPtr = Tcl_FindHashEntry(&dispPtr->containerTable, tkwin);
    if (hPtr == NULL) {
	return NULL;
    }
    return Tcl_GetHashValue(hPtr);
    return (Container *)Tcl_GetHashValue(hPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * ConfigureSlave --
 * ConfigureContent --
 *
 *	This function is called to process an argv/argc list to reconfigure
 *	the placement of a window.
 *
 * Results:
 *	A standard Tcl result. If an error occurs then a message is left in
 *	the interp's result.
 *
 * Side effects:
 *	Information in slavePtr may change, and slavePtr's master is scheduled
 *	Information in contentPtr may change, and contentPtr's container is scheduled
 *	for reconfiguration.
 *
 *----------------------------------------------------------------------
 */

static int
ConfigureSlave(
ConfigureContent(
    Tcl_Interp *interp,		/* Used for error reporting. */
    Tk_Window tkwin,		/* Token for the window to manipulate. */
    Tk_OptionTable table,	/* Token for option table. */
    int objc,			/* Number of config arguments. */
    Tcl_Obj *const objv[])	/* Object values for arguments. */
{
    register Master *masterPtr;
    Container *containerPtr;
    Tk_SavedOptions savedOptions;
    int mask;
    Slave *slavePtr;
    Tk_Window masterWin = NULL;
    TkWindow *master;
    Content *contentPtr;
    Tk_Window containerWin = NULL;
    TkWindow *container;

    if (Tk_TopWinHierarchy(tkwin)) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"can't use placer on top-level window \"%s\"; use "
		"wm command instead", Tk_PathName(tkwin)));
	Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "TOPLEVEL", NULL);
	return TCL_ERROR;
    }

    slavePtr = CreateSlave(tkwin, table);
    contentPtr = CreateContent(tkwin, table);

    if (Tk_SetOptions(interp, (char *) slavePtr, table, objc, objv,
	    slavePtr->tkwin, &savedOptions, &mask) != TCL_OK) {
    if (Tk_SetOptions(interp, contentPtr, table, objc, objv,
	    contentPtr->tkwin, &savedOptions, &mask) != TCL_OK) {
	goto error;
    }

    /*
     * Set slave flags. First clear the field, then add bits as needed.
     * Set content flags. First clear the field, then add bits as needed.
     */

    slavePtr->flags = 0;
    if (slavePtr->heightPtr) {
	slavePtr->flags |= CHILD_HEIGHT;
    contentPtr->flags = 0;
    if (contentPtr->heightPtr) {
	contentPtr->flags |= CHILD_HEIGHT;
    }

    if (slavePtr->relHeightPtr) {
	slavePtr->flags |= CHILD_REL_HEIGHT;
    if (contentPtr->relHeightPtr) {
	contentPtr->flags |= CHILD_REL_HEIGHT;
    }

    if (slavePtr->relWidthPtr) {
	slavePtr->flags |= CHILD_REL_WIDTH;
    if (contentPtr->relWidthPtr) {
	contentPtr->flags |= CHILD_REL_WIDTH;
    }

    if (slavePtr->widthPtr) {
	slavePtr->flags |= CHILD_WIDTH;
    if (contentPtr->widthPtr) {
	contentPtr->flags |= CHILD_WIDTH;
    }

    if (!(mask & IN_MASK) && (slavePtr->masterPtr != NULL)) {
    if (!(mask & IN_MASK) && (contentPtr->containerPtr != NULL)) {
	/*
	 * If no -in option was passed and the slave is already placed then
	 * If no -in option was passed and the content is already placed then
	 * just recompute the placement.
	 */

	masterPtr = slavePtr->masterPtr;
	containerPtr = contentPtr->containerPtr;
	goto scheduleLayout;
    } else if (mask & IN_MASK) {
	/* -in changed */
	Tk_Window tkwin;
	Tk_Window win;
	Tk_Window ancestor;

	tkwin = slavePtr->inTkwin;
	win = contentPtr->inTkwin;

	/*
	 * Make sure that the new master is either the logical parent of the
	 * slave or a descendant of that window, and that the master and slave
	 * Make sure that the new container is either the logical parent of the
	 * content window or a descendant of that window, and that the container and content
	 * aren't the same.
	 */

	for (ancestor = tkwin; ; ancestor = Tk_Parent(ancestor)) {
	    if (ancestor == Tk_Parent(slavePtr->tkwin)) {
	for (ancestor = win; ; ancestor = Tk_Parent(ancestor)) {
	    if (ancestor == Tk_Parent(contentPtr->tkwin)) {
		break;
	    }
	    if (Tk_TopWinHierarchy(ancestor)) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"can't place %s relative to %s",
			Tk_PathName(slavePtr->tkwin), Tk_PathName(tkwin)));
			"can't place \"%s\" relative to \"%s\"",
			Tk_PathName(contentPtr->tkwin), Tk_PathName(win)));
		Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "HIERARCHY", NULL);
		goto error;
	    }
	}
	if (slavePtr->tkwin == tkwin) {
	if (contentPtr->tkwin == win) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "can't place %s relative to itself",
		    Tk_PathName(slavePtr->tkwin)));
		    "can't place \"%s\" relative to itself",
		    Tk_PathName(contentPtr->tkwin)));
	    Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "LOOP", NULL);
	    goto error;
	}

	/*
	 * Check for management loops.
	 */

	for (master = (TkWindow *)tkwin; master != NULL;
	     master = (TkWindow *)TkGetGeomMaster(master)) {
	    if (master == (TkWindow *)slavePtr->tkwin) {
	for (container = (TkWindow *)win; container != NULL;
	     container = (TkWindow *)TkGetContainer(container)) {
	    if (container == (TkWindow *)contentPtr->tkwin) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "can't put %s inside %s, would cause management loop",
	            Tk_PathName(slavePtr->tkwin), Tk_PathName(tkwin)));
		    "can't put \"%s\" inside \"%s\": would cause management loop",
	            Tk_PathName(contentPtr->tkwin), Tk_PathName(win)));
		Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "LOOP", NULL);
		goto error;
	    }
	}
	if (tkwin != Tk_Parent(slavePtr->tkwin)) {
	    ((TkWindow *)slavePtr->tkwin)->maintainerPtr = (TkWindow *)tkwin;
	if (win != Tk_Parent(contentPtr->tkwin)) {
	    ((TkWindow *)contentPtr->tkwin)->maintainerPtr = (TkWindow *)win;
	}

	if ((slavePtr->masterPtr != NULL)
		&& (slavePtr->masterPtr->tkwin == tkwin)) {
	if ((contentPtr->containerPtr != NULL)
		&& (contentPtr->containerPtr->tkwin == win)) {
	    /*
	     * Re-using same old master. Nothing to do.
	     * Re-using same old container. Nothing to do.
	     */

	    masterPtr = slavePtr->masterPtr;
	    containerPtr = contentPtr->containerPtr;
	    goto scheduleLayout;
	}
	if ((slavePtr->masterPtr != NULL) &&
		(slavePtr->masterPtr->tkwin != Tk_Parent(slavePtr->tkwin))) {
	    Tk_UnmaintainGeometry(slavePtr->tkwin, slavePtr->masterPtr->tkwin);
	if ((contentPtr->containerPtr != NULL) &&
		(contentPtr->containerPtr->tkwin != Tk_Parent(contentPtr->tkwin))) {
	    Tk_UnmaintainGeometry(contentPtr->tkwin, contentPtr->containerPtr->tkwin);
	}
	UnlinkSlave(slavePtr);
	masterWin = tkwin;
	UnlinkContent(contentPtr);
	containerWin = win;
    }

    /*
     * If there's no master specified for this slave, use its Tk_Parent.
     * If there's no container specified for this content, use its Tk_Parent.
     */

    if (masterWin == NULL) {
	masterWin = Tk_Parent(slavePtr->tkwin);
	slavePtr->inTkwin = masterWin;
    if (containerWin == NULL) {
	containerWin = Tk_Parent(contentPtr->tkwin);
	contentPtr->inTkwin = containerWin;
    }

    /*
     * Manage the slave window in this master.
     * Manage the content window in this container.
     */

    masterPtr = CreateMaster(masterWin);
    slavePtr->masterPtr = masterPtr;
    slavePtr->nextPtr = masterPtr->slavePtr;
    masterPtr->slavePtr = slavePtr;
    Tk_ManageGeometry(slavePtr->tkwin, &placerType, slavePtr);
    containerPtr = CreateContainer(containerWin);
    contentPtr->containerPtr = containerPtr;
    contentPtr->nextPtr = containerPtr->contentPtr;
    containerPtr->contentPtr = contentPtr;
    Tk_ManageGeometry(contentPtr->tkwin, &placerType, contentPtr);

    /*
     * Arrange for the master to be re-arranged at the first idle moment.
     * Arrange for the container to be re-arranged at the first idle moment.
     */

  scheduleLayout:
    Tk_FreeSavedOptions(&savedOptions);

    if (!(masterPtr->flags & PARENT_RECONFIG_PENDING)) {
	masterPtr->flags |= PARENT_RECONFIG_PENDING;
	Tcl_DoWhenIdle(RecomputePlacement, masterPtr);
    if (!(containerPtr->flags & PARENT_RECONFIG_PENDING)) {
	containerPtr->flags |= PARENT_RECONFIG_PENDING;
	Tcl_DoWhenIdle(RecomputePlacement, containerPtr);
    }
    return TCL_OK;

    /*
     * Error while processing some option, cleanup and return.
     */

791
792
793
794
795
796
797
798

799
800
801
802


803
804
805
806

807
808
809

810
811
812
813
814
815
816



817
818
819
820

821
822

823
824
825
826
827


828
829
830
831

832
833

834
835
836
837
838
839
840


841
842
843
844
845
846
847
848
849
850
851

852
853
854
855
856
857
858
859
860
861
862
863
864

865
866
867


868
869

870
871
872
873
874

875
876
877
878
879
880
881
882
883


884
885

886
887

888
889
890
891


892
893
894
895
896
897


898
899

900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915













916
917
918
919
920


921
922
923

924
925

926
927

928
929
930


931
932

933
934
935
936
937
938
939
940
941

942
943
944
945
946
947


948
949

950
951
952


953
954

955
956
957
958
959

960
961
962
963
964
965


966
967
968
969
970
971


972
973
974

975
976
977
978
979
980
981
803
804
805
806
807
808
809

810
811
812


813
814
815
816
817

818
819
820

821
822
823
824
825



826
827
828
829
830
831

832
833

834
835
836
837


838
839
840
841
842

843
844

845
846
847
848
849
850


851
852
853
854
855
856
857
858
859
860
861
862

863
864
865
866
867
868
869
870
871
872
873
874
875

876
877


878
879
880

881
882
883
884
885

886
887
888
889
890
891
892
893


894
895
896

897
898

899
900
901


902
903
904
905
906
907


908
909
910

911
912
913
914













915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930


931
932
933
934

935
936

937
938

939
940


941
942
943

944
945
946
947
948
949
950
951
952

953
954
955
956
957


958
959
960

961
962


963
964
965

966
967
968
969
970

971
972
973
974
975


976
977
978
979
980
981


982
983
984
985

986
987
988
989
990
991
992
993







-
+


-
-
+
+



-
+


-
+




-
-
-
+
+
+



-
+

-
+



-
-
+
+



-
+

-
+





-
-
+
+










-
+












-
+

-
-
+
+

-
+




-
+







-
-
+
+

-
+

-
+


-
-
+
+




-
-
+
+

-
+



-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+



-
-
+
+


-
+

-
+

-
+

-
-
+
+

-
+








-
+




-
-
+
+

-
+

-
-
+
+

-
+




-
+




-
-
+
+




-
-
+
+


-
+







 */

static int
PlaceInfoCommand(
    Tcl_Interp *interp,		/* Interp into which to place result. */
    Tk_Window tkwin)		/* Token for the window to get info on. */
{
    Slave *slavePtr;
    Content *contentPtr;
    Tcl_Obj *infoObj;

    slavePtr = FindSlave(tkwin);
    if (slavePtr == NULL) {
    contentPtr = FindContent(tkwin);
    if (contentPtr == NULL) {
	return TCL_OK;
    }
    infoObj = Tcl_NewObj();
    if (slavePtr->masterPtr != NULL) {
    if (contentPtr->containerPtr != NULL) {
	Tcl_AppendToObj(infoObj, "-in", -1);
	Tcl_ListObjAppendElement(NULL, infoObj,
		TkNewWindowObj(slavePtr->masterPtr->tkwin));
		Tk_NewWindowObj(contentPtr->containerPtr->tkwin));
	Tcl_AppendToObj(infoObj, " ", -1);
    }
    Tcl_AppendPrintfToObj(infoObj,
	    "-x %d -relx %.4g -y %d -rely %.4g",
	    slavePtr->x, slavePtr->relX, slavePtr->y, slavePtr->relY);
    if (slavePtr->flags & CHILD_WIDTH) {
	Tcl_AppendPrintfToObj(infoObj, " -width %d", slavePtr->width);
	    contentPtr->x, contentPtr->relX, contentPtr->y, contentPtr->relY);
    if (contentPtr->flags & CHILD_WIDTH) {
	Tcl_AppendPrintfToObj(infoObj, " -width %d", contentPtr->width);
    } else {
	Tcl_AppendToObj(infoObj, " -width {}", -1);
    }
    if (slavePtr->flags & CHILD_REL_WIDTH) {
    if (contentPtr->flags & CHILD_REL_WIDTH) {
	Tcl_AppendPrintfToObj(infoObj,
		" -relwidth %.4g", slavePtr->relWidth);
		" -relwidth %.4g", contentPtr->relWidth);
    } else {
	Tcl_AppendToObj(infoObj, " -relwidth {}", -1);
    }
    if (slavePtr->flags & CHILD_HEIGHT) {
	Tcl_AppendPrintfToObj(infoObj, " -height %d", slavePtr->height);
    if (contentPtr->flags & CHILD_HEIGHT) {
	Tcl_AppendPrintfToObj(infoObj, " -height %d", contentPtr->height);
    } else {
	Tcl_AppendToObj(infoObj, " -height {}", -1);
    }
    if (slavePtr->flags & CHILD_REL_HEIGHT) {
    if (contentPtr->flags & CHILD_REL_HEIGHT) {
	Tcl_AppendPrintfToObj(infoObj,
		" -relheight %.4g", slavePtr->relHeight);
		" -relheight %.4g", contentPtr->relHeight);
    } else {
	Tcl_AppendToObj(infoObj, " -relheight {}", -1);
    }

    Tcl_AppendPrintfToObj(infoObj, " -anchor %s -bordermode %s",
	    Tk_NameOfAnchor(slavePtr->anchor),
	    borderModeStrings[slavePtr->borderMode]);
	    Tk_NameOfAnchor(contentPtr->anchor),
	    borderModeStrings[contentPtr->borderMode]);
    Tcl_SetObjResult(interp, infoObj);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * RecomputePlacement --
 *
 *	This function is called as a when-idle handler. It recomputes the
 *	geometries of all the slaves of a given master.
 *	geometries of all the content of a given container.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Windows may change size or shape.
 *
 *----------------------------------------------------------------------
 */

static void
RecomputePlacement(
    ClientData clientData)	/* Pointer to Master record. */
    ClientData clientData)	/* Pointer to Container record. */
{
    register Master *masterPtr = clientData;
    register Slave *slavePtr;
    Container *containerPtr = (Container *)clientData;
    Content *contentPtr;
    int x, y, width, height, tmp;
    int masterWidth, masterHeight, masterX, masterY;
    int containerWidth, containerHeight, containerX, containerY;
    double x1, y1, x2, y2;
    int abort;			/* May get set to non-zero to abort this
				 * placement operation. */

    masterPtr->flags &= ~PARENT_RECONFIG_PENDING;
    containerPtr->flags &= ~PARENT_RECONFIG_PENDING;

    /*
     * Abort any nested call to RecomputePlacement for this window, since
     * we'll do everything necessary here, and set up so this call can be
     * aborted if necessary.
     */

    if (masterPtr->abortPtr != NULL) {
	*masterPtr->abortPtr = 1;
    if (containerPtr->abortPtr != NULL) {
	*containerPtr->abortPtr = 1;
    }
    masterPtr->abortPtr = &abort;
    containerPtr->abortPtr = &abort;
    abort = 0;
    Tcl_Preserve(masterPtr);
    Tcl_Preserve(containerPtr);

    /*
     * Iterate over all the slaves for the master. Each slave's geometry can
     * be computed independently of the other slaves. Changes to the window's
     * Iterate over all the content windows for the container. Each content's geometry can
     * be computed independently of the other content. Changes to the window's
     * structure could cause almost anything to happen, including deleting the
     * parent or child. If this happens, we'll be told to abort.
     */

    for (slavePtr = masterPtr->slavePtr; slavePtr != NULL && !abort;
	    slavePtr = slavePtr->nextPtr) {
    for (contentPtr = containerPtr->contentPtr; contentPtr != NULL && !abort;
	    contentPtr = contentPtr->nextPtr) {
	/*
	 * Step 1: compute size and borderwidth of master, taking into account
	 * Step 1: compute size and borderwidth of container, taking into account
	 * desired border mode.
	 */

	masterX = masterY = 0;
	masterWidth = Tk_Width(masterPtr->tkwin);
	masterHeight = Tk_Height(masterPtr->tkwin);
	if (slavePtr->borderMode == BM_INSIDE) {
	    masterX = Tk_InternalBorderLeft(masterPtr->tkwin);
	    masterY = Tk_InternalBorderTop(masterPtr->tkwin);
	    masterWidth -= masterX + Tk_InternalBorderRight(masterPtr->tkwin);
	    masterHeight -= masterY +
		    Tk_InternalBorderBottom(masterPtr->tkwin);
	} else if (slavePtr->borderMode == BM_OUTSIDE) {
	    masterX = masterY = -Tk_Changes(masterPtr->tkwin)->border_width;
	    masterWidth -= 2 * masterX;
	    masterHeight -= 2 * masterY;
	containerX = containerY = 0;
	containerWidth = Tk_Width(containerPtr->tkwin);
	containerHeight = Tk_Height(containerPtr->tkwin);
	if (contentPtr->borderMode == BM_INSIDE) {
	    containerX = Tk_InternalBorderLeft(containerPtr->tkwin);
	    containerY = Tk_InternalBorderTop(containerPtr->tkwin);
	    containerWidth -= containerX + Tk_InternalBorderRight(containerPtr->tkwin);
	    containerHeight -= containerY +
		    Tk_InternalBorderBottom(containerPtr->tkwin);
	} else if (contentPtr->borderMode == BM_OUTSIDE) {
	    containerX = containerY = -Tk_Changes(containerPtr->tkwin)->border_width;
	    containerWidth -= 2 * containerX;
	    containerHeight -= 2 * containerY;
	}

	/*
	 * Step 2: compute size of slave (outside dimensions including border)
	 * and location of anchor point within master.
	 * Step 2: compute size of content (outside dimensions including border)
	 * and location of anchor point within container.
	 */

	x1 = slavePtr->x + masterX + (slavePtr->relX*masterWidth);
	x1 = contentPtr->x + containerX + (contentPtr->relX*containerWidth);
	x = (int) (x1 + ((x1 > 0) ? 0.5 : -0.5));
	y1 = slavePtr->y + masterY + (slavePtr->relY*masterHeight);
	y1 = contentPtr->y + containerY + (contentPtr->relY*containerHeight);
	y = (int) (y1 + ((y1 > 0) ? 0.5 : -0.5));
	if (slavePtr->flags & (CHILD_WIDTH|CHILD_REL_WIDTH)) {
	if (contentPtr->flags & (CHILD_WIDTH|CHILD_REL_WIDTH)) {
	    width = 0;
	    if (slavePtr->flags & CHILD_WIDTH) {
		width += slavePtr->width;
	    if (contentPtr->flags & CHILD_WIDTH) {
		width += contentPtr->width;
	    }
	    if (slavePtr->flags & CHILD_REL_WIDTH) {
	    if (contentPtr->flags & CHILD_REL_WIDTH) {
		/*
		 * The code below is a bit tricky. In order to round correctly
		 * when both relX and relWidth are specified, compute the
		 * location of the right edge and round that, then compute
		 * width. If we compute the width and round it, rounding
		 * errors in relX and relWidth accumulate.
		 */

		x2 = x1 + (slavePtr->relWidth*masterWidth);
		x2 = x1 + (contentPtr->relWidth*containerWidth);
		tmp = (int) (x2 + ((x2 > 0) ? 0.5 : -0.5));
		width += tmp - x;
	    }
	} else {
	    width = Tk_ReqWidth(slavePtr->tkwin)
		    + 2*Tk_Changes(slavePtr->tkwin)->border_width;
	    width = Tk_ReqWidth(contentPtr->tkwin)
		    + 2*Tk_Changes(contentPtr->tkwin)->border_width;
	}
	if (slavePtr->flags & (CHILD_HEIGHT|CHILD_REL_HEIGHT)) {
	if (contentPtr->flags & (CHILD_HEIGHT|CHILD_REL_HEIGHT)) {
	    height = 0;
	    if (slavePtr->flags & CHILD_HEIGHT) {
		height += slavePtr->height;
	    if (contentPtr->flags & CHILD_HEIGHT) {
		height += contentPtr->height;
	    }
	    if (slavePtr->flags & CHILD_REL_HEIGHT) {
	    if (contentPtr->flags & CHILD_REL_HEIGHT) {
		/*
		 * See note above for rounding errors in width computation.
		 */

		y2 = y1 + (slavePtr->relHeight*masterHeight);
		y2 = y1 + (contentPtr->relHeight*containerHeight);
		tmp = (int) (y2 + ((y2 > 0) ? 0.5 : -0.5));
		height += tmp - y;
	    }
	} else {
	    height = Tk_ReqHeight(slavePtr->tkwin)
		    + 2*Tk_Changes(slavePtr->tkwin)->border_width;
	    height = Tk_ReqHeight(contentPtr->tkwin)
		    + 2*Tk_Changes(contentPtr->tkwin)->border_width;
	}

	/*
	 * Step 3: adjust the x and y positions so that the desired anchor
	 * point on the slave appears at that position. Also adjust for the
	 * border mode and master's border.
	 * point on the content appears at that position. Also adjust for the
	 * border mode and container's border.
	 */

	switch (slavePtr->anchor) {
	switch (contentPtr->anchor) {
	case TK_ANCHOR_N:
	    x -= width/2;
	    break;
	case TK_ANCHOR_NE:
	    x -= width;
	    break;
	case TK_ANCHOR_E:
1006
1007
1008
1009
1010
1011
1012
1013
1014


1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025



1026
1027
1028
1029
1030
1031
1032
1033
1034






1035
1036
1037
1038
1039
1040
1041
1042


1043
1044
1045
1046


1047
1048
1049
1050
1051


1052
1053

1054
1055
1056
1057
1058
1059
1060


1061
1062
1063
1064
1065
1066

1067
1068
1069

1070
1071
1072
1073
1074
1075
1076

1077
1078
1079
1080
1081
1082
1083


1084
1085
1086
1087
1088
1089



1090
1091
1092
1093
1094
1095
1096




1097
1098
1099
1100
1101
1102
1103
1104





1105
1106
1107
1108
1109




1110
1111
1112
1113



1114
1115

1116
1117
1118
1119
1120


1121
1122
1123
1124
1125
1126




1127
1128
1129
1130
1131

1132
1133
1134
1135
1136
1137



1138
1139
1140
1141
1142
1143
1144
1145
1146

1147
1148
1149

1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162


1163
1164
1165
1166
1167


1168
1169
1170
1171


1172
1173
1174
1175



1176
1177
1178
1179
1180
1181
1182
1183
1184

1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201


1202
1203
1204


1205
1206
1207


1208
1209
1210
1211
1212
1213

1214
1215
1216
1217


1218
1219
1220
1221
1222



1223
1224
1225
1226
1227
1228
1229

1230
1231
1232

1233
1234
1235
1236
1237
1238

1239
1240
1241
1242
1243
1244
1245
1246


1247
1248

1249
1250
1251


1252
1253
1254


1255
1256
1257
1258
1259
1260
1261
1262






1263
1264
1265
1266
1267
1268
1269
1270
1271
1018
1019
1020
1021
1022
1023
1024


1025
1026
1027
1028
1029
1030
1031
1032
1033
1034



1035
1036
1037
1038
1039
1040






1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052


1053
1054
1055
1056


1057
1058
1059
1060
1061


1062
1063
1064

1065
1066
1067
1068
1069
1070


1071
1072
1073
1074
1075
1076
1077

1078
1079
1080

1081
1082
1083
1084
1085
1086
1087

1088
1089
1090
1091
1092
1093


1094
1095
1096
1097
1098



1099
1100
1101
1102
1103
1104




1105
1106
1107
1108
1109
1110
1111





1112
1113
1114
1115
1116
1117




1118
1119
1120
1121
1122



1123
1124
1125
1126

1127
1128
1129
1130


1131
1132
1133
1134




1135
1136
1137
1138
1139
1140
1141
1142

1143
1144
1145
1146



1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157

1158
1159
1160

1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172


1173
1174
1175
1176
1177


1178
1179
1180
1181


1182
1183
1184



1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195

1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208

1209
1210


1211
1212
1213


1214
1215
1216


1217
1218
1219
1220
1221
1222
1223

1224
1225
1226


1227
1228
1229
1230



1231
1232
1233
1234
1235
1236
1237
1238
1239

1240
1241
1242

1243
1244
1245
1246
1247
1248

1249
1250
1251
1252
1253

1254


1255
1256
1257

1258
1259


1260
1261
1262


1263
1264
1265
1266






1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281







-
-
+
+








-
-
-
+
+
+



-
-
-
-
-
-
+
+
+
+
+
+






-
-
+
+


-
-
+
+



-
-
+
+

-
+





-
-
+
+





-
+


-
+






-
+





-
-
+
+



-
-
-
+
+
+



-
-
-
-
+
+
+
+



-
-
-
-
-
+
+
+
+
+

-
-
-
-
+
+
+
+

-
-
-
+
+
+

-
+



-
-
+
+


-
-
-
-
+
+
+
+




-
+



-
-
-
+
+
+








-
+


-
+











-
-
+
+



-
-
+
+


-
-
+
+

-
-
-
+
+
+








-
+












-


-
-
+
+

-
-
+
+

-
-
+
+





-
+


-
-
+
+


-
-
-
+
+
+






-
+


-
+





-
+




-

-
-
+
+

-
+

-
-
+
+

-
-
+
+


-
-
-
-
-
-
+
+
+
+
+
+










	/*
	 * Step 4: adjust width and height again to reflect inside dimensions
	 * of window rather than outside. Also make sure that the width and
	 * height aren't zero.
	 */

	width -= 2*Tk_Changes(slavePtr->tkwin)->border_width;
	height -= 2*Tk_Changes(slavePtr->tkwin)->border_width;
	width -= 2*Tk_Changes(contentPtr->tkwin)->border_width;
	height -= 2*Tk_Changes(contentPtr->tkwin)->border_width;
	if (width <= 0) {
	    width = 1;
	}
	if (height <= 0) {
	    height = 1;
	}

	/*
	 * Step 5: reconfigure the window and map it if needed. If the slave
	 * is a child of the master, we do this ourselves. If the slave isn't
	 * a child of the master, let Tk_MaintainGeometry do the work (it will
	 * Step 5: reconfigure the window and map it if needed. If the content
	 * is a child of the container, we do this ourselves. If the content isn't
	 * a child of the container, let Tk_MaintainGeometry do the work (it will
	 * re-adjust things as relevant windows map, unmap, and move).
	 */

	if (masterPtr->tkwin == Tk_Parent(slavePtr->tkwin)) {
	    if ((x != Tk_X(slavePtr->tkwin))
		    || (y != Tk_Y(slavePtr->tkwin))
		    || (width != Tk_Width(slavePtr->tkwin))
		    || (height != Tk_Height(slavePtr->tkwin))) {
		Tk_MoveResizeWindow(slavePtr->tkwin, x, y, width, height);
	if (containerPtr->tkwin == Tk_Parent(contentPtr->tkwin)) {
	    if ((x != Tk_X(contentPtr->tkwin))
		    || (y != Tk_Y(contentPtr->tkwin))
		    || (width != Tk_Width(contentPtr->tkwin))
		    || (height != Tk_Height(contentPtr->tkwin))) {
		Tk_MoveResizeWindow(contentPtr->tkwin, x, y, width, height);
	    }
            if (abort) {
                break;
            }

	    /*
	     * Don't map the slave unless the master is mapped: the slave will
	     * get mapped later, when the master is mapped.
	     * Don't map the content unless the container is mapped: the content will
	     * get mapped later, when the container is mapped.
	     */

	    if (Tk_IsMapped(masterPtr->tkwin)) {
		Tk_MapWindow(slavePtr->tkwin);
	    if (Tk_IsMapped(containerPtr->tkwin)) {
		Tk_MapWindow(contentPtr->tkwin);
	    }
	} else {
	    if ((width <= 0) || (height <= 0)) {
		Tk_UnmaintainGeometry(slavePtr->tkwin, masterPtr->tkwin);
		Tk_UnmapWindow(slavePtr->tkwin);
		Tk_UnmaintainGeometry(contentPtr->tkwin, containerPtr->tkwin);
		Tk_UnmapWindow(contentPtr->tkwin);
	    } else {
		Tk_MaintainGeometry(slavePtr->tkwin, masterPtr->tkwin,
		Tk_MaintainGeometry(contentPtr->tkwin, containerPtr->tkwin,
			x, y, width, height);
	    }
	}
    }

    masterPtr->abortPtr = NULL;
    Tcl_Release(masterPtr);
    containerPtr->abortPtr = NULL;
    Tcl_Release(containerPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * MasterStructureProc --
 * PlaceStructureProc --
 *
 *	This function is invoked by the Tk event handler when StructureNotify
 *	events occur for a master window.
 *	events occur for a container window.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Structures get cleaned up if the window was deleted. If the window was
 *	resized then slave geometries get recomputed.
 *	resized then content geometries get recomputed.
 *
 *----------------------------------------------------------------------
 */

static void
MasterStructureProc(
    ClientData clientData,	/* Pointer to Master structure for window
PlaceStructureProc(
    ClientData clientData,	/* Pointer to Container structure for window
				 * referred to by eventPtr. */
    XEvent *eventPtr)		/* Describes what just happened. */
{
    register Master *masterPtr = clientData;
    register Slave *slavePtr, *nextPtr;
    TkDisplay *dispPtr = ((TkWindow *) masterPtr->tkwin)->dispPtr;
    Container *containerPtr = (Container *)clientData;
    Content *contentPtr, *nextPtr;
    TkDisplay *dispPtr = ((TkWindow *) containerPtr->tkwin)->dispPtr;

    switch (eventPtr->type) {
    case ConfigureNotify:
	if ((masterPtr->slavePtr != NULL)
		&& !(masterPtr->flags & PARENT_RECONFIG_PENDING)) {
	    masterPtr->flags |= PARENT_RECONFIG_PENDING;
	    Tcl_DoWhenIdle(RecomputePlacement, masterPtr);
	if ((containerPtr->contentPtr != NULL)
		&& !(containerPtr->flags & PARENT_RECONFIG_PENDING)) {
	    containerPtr->flags |= PARENT_RECONFIG_PENDING;
	    Tcl_DoWhenIdle(RecomputePlacement, containerPtr);
	}
	return;
    case DestroyNotify:
	for (slavePtr = masterPtr->slavePtr; slavePtr != NULL;
		slavePtr = nextPtr) {
	    slavePtr->masterPtr = NULL;
	    nextPtr = slavePtr->nextPtr;
	    slavePtr->nextPtr = NULL;
	for (contentPtr = containerPtr->contentPtr; contentPtr != NULL;
		contentPtr = nextPtr) {
	    contentPtr->containerPtr = NULL;
	    nextPtr = contentPtr->nextPtr;
	    contentPtr->nextPtr = NULL;
	}
	Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->masterTable,
		(char *) masterPtr->tkwin));
	if (masterPtr->flags & PARENT_RECONFIG_PENDING) {
	    Tcl_CancelIdleCall(RecomputePlacement, masterPtr);
	Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->containerTable,
		containerPtr->tkwin));
	if (containerPtr->flags & PARENT_RECONFIG_PENDING) {
	    Tcl_CancelIdleCall(RecomputePlacement, containerPtr);
	}
	masterPtr->tkwin = NULL;
	if (masterPtr->abortPtr != NULL) {
	    *masterPtr->abortPtr = 1;
	containerPtr->tkwin = NULL;
	if (containerPtr->abortPtr != NULL) {
	    *containerPtr->abortPtr = 1;
	}
	Tcl_EventuallyFree(masterPtr, TCL_DYNAMIC);
	Tcl_EventuallyFree(containerPtr, TCL_DYNAMIC);
	return;
    case MapNotify:
	/*
	 * When a master gets mapped, must redo the geometry computation so
	 * that all of its slaves get remapped.
	 * When a container gets mapped, must redo the geometry computation so
	 * that all of its content get remapped.
	 */

	if ((masterPtr->slavePtr != NULL)
		&& !(masterPtr->flags & PARENT_RECONFIG_PENDING)) {
	    masterPtr->flags |= PARENT_RECONFIG_PENDING;
	    Tcl_DoWhenIdle(RecomputePlacement, masterPtr);
	if ((containerPtr->contentPtr != NULL)
		&& !(containerPtr->flags & PARENT_RECONFIG_PENDING)) {
	    containerPtr->flags |= PARENT_RECONFIG_PENDING;
	    Tcl_DoWhenIdle(RecomputePlacement, containerPtr);
	}
	return;
    case UnmapNotify:
	/*
	 * Unmap all of the slaves when the master gets unmapped, so that they
	 * Unmap all of the content when the container gets unmapped, so that they
	 * don't keep redisplaying themselves.
	 */

	for (slavePtr = masterPtr->slavePtr; slavePtr != NULL;
		slavePtr = slavePtr->nextPtr) {
	    Tk_UnmapWindow(slavePtr->tkwin);
	for (contentPtr = containerPtr->contentPtr; contentPtr != NULL;
		contentPtr = contentPtr->nextPtr) {
	    Tk_UnmapWindow(contentPtr->tkwin);
	}
	return;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * SlaveStructureProc --
 * ContentStructureProc --
 *
 *	This function is invoked by the Tk event handler when StructureNotify
 *	events occur for a slave window.
 *	events occur for a content window.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Structures get cleaned up if the window was deleted.
 *
 *----------------------------------------------------------------------
 */

static void
SlaveStructureProc(
    ClientData clientData,	/* Pointer to Slave structure for window
ContentStructureProc(
    ClientData clientData,	/* Pointer to Content structure for window
				 * referred to by eventPtr. */
    XEvent *eventPtr)		/* Describes what just happened. */
{
    register Slave *slavePtr = clientData;
    TkDisplay *dispPtr = ((TkWindow *) slavePtr->tkwin)->dispPtr;
    Content *contentPtr = (Content *)clientData;
    TkDisplay *dispPtr = ((TkWindow *) contentPtr->tkwin)->dispPtr;

    if (eventPtr->type == DestroyNotify) {
	if (slavePtr->masterPtr != NULL) {
	    UnlinkSlave(slavePtr);
	if (contentPtr->containerPtr != NULL) {
	    UnlinkContent(contentPtr);
	}
	Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->slaveTable,
		(char *) slavePtr->tkwin));
	FreeSlave(slavePtr);
	Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->contentTable,
		contentPtr->tkwin));
	FreeContent(contentPtr);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * PlaceRequestProc --
 *
 *	This function is invoked by Tk whenever a slave managed by us changes
 *	This function is invoked by Tk whenever a content managed by us changes
 *	its requested geometry.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The window will get relayed out, if its requested size has anything to
 *	do with its actual size.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static void
PlaceRequestProc(
    ClientData clientData,	/* Pointer to our record for slave. */
    Tk_Window tkwin)		/* Window that changed its desired size. */
    ClientData clientData,	/* Pointer to our record for content. */
    TCL_UNUSED(Tk_Window))		/* Window that changed its desired size. */
{
    Slave *slavePtr = clientData;
    Master *masterPtr;
    Content *contentPtr = (Content *)clientData;
    Container *containerPtr;

    if ((slavePtr->flags & (CHILD_WIDTH|CHILD_REL_WIDTH))
	    && (slavePtr->flags & (CHILD_HEIGHT|CHILD_REL_HEIGHT))) {
    if ((contentPtr->flags & (CHILD_WIDTH|CHILD_REL_WIDTH))
	    && (contentPtr->flags & (CHILD_HEIGHT|CHILD_REL_HEIGHT))) {
        /*
         * Send a ConfigureNotify to indicate that the size change
         * request was rejected.
         */

        TkDoConfigureNotify((TkWindow *)(slavePtr->tkwin));
        TkDoConfigureNotify((TkWindow *)(contentPtr->tkwin));
	return;
    }
    masterPtr = slavePtr->masterPtr;
    if (masterPtr == NULL) {
    containerPtr = contentPtr->containerPtr;
    if (containerPtr == NULL) {
	return;
    }
    if (!(masterPtr->flags & PARENT_RECONFIG_PENDING)) {
	masterPtr->flags |= PARENT_RECONFIG_PENDING;
	Tcl_DoWhenIdle(RecomputePlacement, masterPtr);
    if (!(containerPtr->flags & PARENT_RECONFIG_PENDING)) {
	containerPtr->flags |= PARENT_RECONFIG_PENDING;
	Tcl_DoWhenIdle(RecomputePlacement, containerPtr);
    }
}

/*
 *--------------------------------------------------------------
 *
 * PlaceLostSlaveProc --
 * PlaceLostContentProc --
 *
 *	This function is invoked by Tk whenever some other geometry claims
 *	control over a slave that used to be managed by us.
 *	control over a content window that used to be managed by us.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Forgets all placer-related information about the slave.
 *	Forgets all placer-related information about the content window.
 *
 *--------------------------------------------------------------
 */

	/* ARGSUSED */
static void
PlaceLostSlaveProc(
    ClientData clientData,	/* Slave structure for slave window that was
PlaceLostContentProc(
    ClientData clientData,	/* Content structure for content window that was
				 * stolen away. */
    Tk_Window tkwin)		/* Tk's handle for the slave window. */
    Tk_Window tkwin)		/* Tk's handle for the content window. */
{
    register Slave *slavePtr = clientData;
    TkDisplay *dispPtr = ((TkWindow *) slavePtr->tkwin)->dispPtr;
    Content *contentPtr = (Content *)clientData;
    TkDisplay *dispPtr = ((TkWindow *) contentPtr->tkwin)->dispPtr;

    if (slavePtr->masterPtr->tkwin != Tk_Parent(slavePtr->tkwin)) {
	Tk_UnmaintainGeometry(slavePtr->tkwin, slavePtr->masterPtr->tkwin);
    if (contentPtr->containerPtr->tkwin != Tk_Parent(contentPtr->tkwin)) {
	Tk_UnmaintainGeometry(contentPtr->tkwin, contentPtr->containerPtr->tkwin);
    }
    Tk_UnmapWindow(tkwin);
    UnlinkSlave(slavePtr);
    Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->slaveTable,
	    (char *) tkwin));
    Tk_DeleteEventHandler(tkwin, StructureNotifyMask, SlaveStructureProc,
	    slavePtr);
    FreeSlave(slavePtr);
    UnlinkContent(contentPtr);
    Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->contentTable,
	    tkwin));
    Tk_DeleteEventHandler(tkwin, StructureNotifyMask, ContentStructureProc,
	    contentPtr);
    FreeContent(contentPtr);
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Changes to generic/tkPlatDecls.h.
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







/*
 * 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.
 */

#ifndef _TKPLATDECLS
#define _TKPLATDECLS
50
51
52
53
54
55
56
57

58
59
60
61
62
63
64

65
66

67
68

69
70
71
72
73

74
75
76
77

78
79
80
81
82
83
84











85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103




104
105

106
107

108
109
110






111
112
113
114
115
116
117
50
51
52
53
54
55
56

57







58


59


60

61
62
63

64
65
66
67

68

69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100




101
102
103
104
105

106
107

108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124







-
+
-
-
-
-
-
-
-
+
-
-
+
-
-
+
-



-
+



-
+
-






+
+
+
+
+
+
+
+
+
+
+















-
-
-
-
+
+
+
+

-
+

-
+



+
+
+
+
+
+







EXTERN void		Tk_PointerEvent(HWND hwnd, int x, int y);
/* 5 */
EXTERN int		Tk_TranslateWinEvent(HWND hwnd, UINT message,
				WPARAM wParam, LPARAM lParam,
				LRESULT *result);
#endif /* WIN */
#ifdef MAC_OSX_TK /* AQUA */
/* 0 */
/* Slot 0 is reserved */
EXTERN void		Tk_MacOSXSetEmbedHandler(
				Tk_MacOSXEmbedRegisterWinProc *registerWinProcPtr,
				Tk_MacOSXEmbedGetGrafPortProc *getPortProcPtr,
				Tk_MacOSXEmbedMakeContainerExistProc *containerExistProcPtr,
				Tk_MacOSXEmbedGetClipProc *getClipProc,
				Tk_MacOSXEmbedGetOffsetInParentProc *getOffsetProc);
/* 1 */
/* Slot 1 is reserved */
EXTERN void		Tk_MacOSXTurnOffMenus(void);
/* 2 */
/* Slot 2 is reserved */
EXTERN void		Tk_MacOSXTkOwnsCursor(int tkOwnsIt);
/* 3 */
/* Slot 3 is reserved */
EXTERN void		TkMacOSXInitMenus(Tcl_Interp *interp);
/* 4 */
EXTERN void		TkMacOSXInitAppleEvents(Tcl_Interp *interp);
/* 5 */
EXTERN void		TkGenWMConfigureEvent(Tk_Window tkwin, int x, int y,
EXTERN void		TkGenWMConfigureEvent_(Tk_Window tkwin, int x, int y,
				int width, int height, int flags);
/* 6 */
EXTERN void		TkMacOSXInvalClipRgns(Tk_Window tkwin);
/* 7 */
/* Slot 7 is reserved */
EXTERN void *		TkMacOSXGetDrawablePort(Drawable drawable);
/* 8 */
EXTERN void *		TkMacOSXGetRootControl(Drawable drawable);
/* 9 */
EXTERN void		Tk_MacOSXSetupTkNotifier(void);
/* 10 */
EXTERN int		Tk_MacOSXIsAppInFront(void);
/* 11 */
EXTERN Tk_Window	Tk_MacOSXGetTkWindow(void *w);
/* 12 */
EXTERN void *		Tk_MacOSXGetCGContextForDrawable(Drawable drawable);
/* 13 */
EXTERN void *		Tk_MacOSXGetNSWindowForDrawable(Drawable drawable);
/* Slot 14 is reserved */
/* Slot 15 is reserved */
/* 16 */
EXTERN void		TkGenWMConfigureEvent(Tk_Window tkwin, int x, int y,
				int width, int height, int flags);
#endif /* AQUA */

typedef struct TkPlatStubs {
    int magic;
    void *hooks;

#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
    Window (*tk_AttachHWND) (Tk_Window tkwin, HWND hwnd); /* 0 */
    HINSTANCE (*tk_GetHINSTANCE) (void); /* 1 */
    HWND (*tk_GetHWND) (Window window); /* 2 */
    Tk_Window (*tk_HWNDToWindow) (HWND hwnd); /* 3 */
    void (*tk_PointerEvent) (HWND hwnd, int x, int y); /* 4 */
    int (*tk_TranslateWinEvent) (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result); /* 5 */
#endif /* WIN */
#ifdef MAC_OSX_TK /* AQUA */
    void (*tk_MacOSXSetEmbedHandler) (Tk_MacOSXEmbedRegisterWinProc *registerWinProcPtr, Tk_MacOSXEmbedGetGrafPortProc *getPortProcPtr, Tk_MacOSXEmbedMakeContainerExistProc *containerExistProcPtr, Tk_MacOSXEmbedGetClipProc *getClipProc, Tk_MacOSXEmbedGetOffsetInParentProc *getOffsetProc); /* 0 */
    void (*tk_MacOSXTurnOffMenus) (void); /* 1 */
    void (*tk_MacOSXTkOwnsCursor) (int tkOwnsIt); /* 2 */
    void (*tkMacOSXInitMenus) (Tcl_Interp *interp); /* 3 */
    void (*reserved0)(void);
    void (*reserved1)(void);
    void (*reserved2)(void);
    void (*reserved3)(void);
    void (*tkMacOSXInitAppleEvents) (Tcl_Interp *interp); /* 4 */
    void (*tkGenWMConfigureEvent) (Tk_Window tkwin, int x, int y, int width, int height, int flags); /* 5 */
    void (*tkGenWMConfigureEvent_) (Tk_Window tkwin, int x, int y, int width, int height, int flags); /* 5 */
    void (*tkMacOSXInvalClipRgns) (Tk_Window tkwin); /* 6 */
    void * (*tkMacOSXGetDrawablePort) (Drawable drawable); /* 7 */
    void (*reserved7)(void);
    void * (*tkMacOSXGetRootControl) (Drawable drawable); /* 8 */
    void (*tk_MacOSXSetupTkNotifier) (void); /* 9 */
    int (*tk_MacOSXIsAppInFront) (void); /* 10 */
    Tk_Window (*tk_MacOSXGetTkWindow) (void *w); /* 11 */
    void * (*tk_MacOSXGetCGContextForDrawable) (Drawable drawable); /* 12 */
    void * (*tk_MacOSXGetNSWindowForDrawable) (Drawable drawable); /* 13 */
    void (*reserved14)(void);
    void (*reserved15)(void);
    void (*tkGenWMConfigureEvent) (Tk_Window tkwin, int x, int y, int width, int height, int flags); /* 16 */
#endif /* AQUA */
} TkPlatStubs;

extern const TkPlatStubs *tkPlatStubsPtr;

#ifdef __cplusplus
}
134
135
136
137
138
139
140
141
142
143
144




145
146
147
148
149
150
151
152


153
154
155
156

157
158
159
160
161
162










163
164
165
166
167
168
169
170
171
172
173
174
175



176
141
142
143
144
145
146
147




148
149
150
151




152
153


154
155
156
157


158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191







-
-
-
-
+
+
+
+
-
-
-
-


-
-
+
+


-
-
+






+
+
+
+
+
+
+
+
+
+













+
+
+

	(tkPlatStubsPtr->tk_HWNDToWindow) /* 3 */
#define Tk_PointerEvent \
	(tkPlatStubsPtr->tk_PointerEvent) /* 4 */
#define Tk_TranslateWinEvent \
	(tkPlatStubsPtr->tk_TranslateWinEvent) /* 5 */
#endif /* WIN */
#ifdef MAC_OSX_TK /* AQUA */
#define Tk_MacOSXSetEmbedHandler \
	(tkPlatStubsPtr->tk_MacOSXSetEmbedHandler) /* 0 */
#define Tk_MacOSXTurnOffMenus \
	(tkPlatStubsPtr->tk_MacOSXTurnOffMenus) /* 1 */
/* Slot 0 is reserved */
/* Slot 1 is reserved */
/* Slot 2 is reserved */
/* Slot 3 is reserved */
#define Tk_MacOSXTkOwnsCursor \
	(tkPlatStubsPtr->tk_MacOSXTkOwnsCursor) /* 2 */
#define TkMacOSXInitMenus \
	(tkPlatStubsPtr->tkMacOSXInitMenus) /* 3 */
#define TkMacOSXInitAppleEvents \
	(tkPlatStubsPtr->tkMacOSXInitAppleEvents) /* 4 */
#define TkGenWMConfigureEvent \
	(tkPlatStubsPtr->tkGenWMConfigureEvent) /* 5 */
#define TkGenWMConfigureEvent_ \
	(tkPlatStubsPtr->tkGenWMConfigureEvent_) /* 5 */
#define TkMacOSXInvalClipRgns \
	(tkPlatStubsPtr->tkMacOSXInvalClipRgns) /* 6 */
#define TkMacOSXGetDrawablePort \
	(tkPlatStubsPtr->tkMacOSXGetDrawablePort) /* 7 */
/* Slot 7 is reserved */
#define TkMacOSXGetRootControl \
	(tkPlatStubsPtr->tkMacOSXGetRootControl) /* 8 */
#define Tk_MacOSXSetupTkNotifier \
	(tkPlatStubsPtr->tk_MacOSXSetupTkNotifier) /* 9 */
#define Tk_MacOSXIsAppInFront \
	(tkPlatStubsPtr->tk_MacOSXIsAppInFront) /* 10 */
#define Tk_MacOSXGetTkWindow \
	(tkPlatStubsPtr->tk_MacOSXGetTkWindow) /* 11 */
#define Tk_MacOSXGetCGContextForDrawable \
	(tkPlatStubsPtr->tk_MacOSXGetCGContextForDrawable) /* 12 */
#define Tk_MacOSXGetNSWindowForDrawable \
	(tkPlatStubsPtr->tk_MacOSXGetNSWindowForDrawable) /* 13 */
/* Slot 14 is reserved */
/* Slot 15 is reserved */
#define TkGenWMConfigureEvent \
	(tkPlatStubsPtr->tkGenWMConfigureEvent) /* 16 */
#endif /* AQUA */

#endif /* defined(USE_TK_STUBS) */

/* !END!: Do not edit above this line. */

#ifdef __cplusplus
}
#endif

#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLIMPORT

#undef TkGenWMConfigureEvent_
#define Tk_MacOSXGetNSViewForDrawable TkMacOSXGetRootControl

#endif /* _TKPLATDECLS */
Changes to generic/tkPointer.c.
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

30
31
32
33
34
35
36
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
16
17
18
19
20
21
22

23
24
25
26
27

28
29
30
31
32
33
34
35








-
+













-





-
+







/*
 * tkPointer.c --
 *
 *	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.
 */

#include "tkInt.h"

#ifdef _WIN32
#include "tkWinInt.h"
#endif

#if defined(MAC_OSX_TK)
#include "tkMacOSXInt.h"
#define Cursor XCursor
#endif

typedef struct {
    TkWindow *grabWinPtr;	/* Window that defines the top of the grab
				 * tree in a global grab. */
    int lastState;		/* Last known state flags. */
    unsigned lastState;		/* Last known state flags. */
    XPoint lastPos;		/* Last reported mouse position. */
    TkWindow *lastWinPtr;	/* Last reported mouse window. */
    TkWindow *restrictWinPtr;	/* Window to which all mouse events will be
				 * reported. */
    TkWindow *cursorWinPtr;	/* Window that is currently controlling the
				 * global cursor. */
} ThreadSpecificData;
122
123
124
125
126
127
128
129

130
131
132
133
134
135
136
121
122
123
124
125
126
127

128
129
130
131
132
133
134
135







-
+







static int
GenerateEnterLeave(
    TkWindow *winPtr,		/* Current Tk window (or NULL). */
    int x, int y,		/* Current mouse position in root coords. */
    int state)			/* State flags. */
{
    int crossed = 0;		/* 1 if mouse crossed a window boundary */
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    TkWindow *restrictWinPtr = tsdPtr->restrictWinPtr;
    TkWindow *lastWinPtr = tsdPtr->lastWinPtr;

    if (winPtr != tsdPtr->lastWinPtr) {
	if (restrictWinPtr) {
	    int newPos, oldPos;
215
216
217
218
219
220
221
222

223
224
225
226
227
228
229



230
231
232
233
234
235
236
214
215
216
217
218
219
220

221
222
223
224
225
226


227
228
229
230
231
232
233
234
235
236







-
+





-
-
+
+
+







void
Tk_UpdatePointer(
    Tk_Window tkwin,		/* Window to which pointer event is reported.
				 * May be NULL. */
    int x, int y,		/* Pointer location in root coords. */
    int state)			/* Modifier state mask. */
{
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    TkWindow *winPtr = (TkWindow *)tkwin;
    TkWindow *targetWinPtr;
    XPoint pos;
    XEvent event;
    int changes = (state ^ tsdPtr->lastState) & ALL_BUTTONS;
    int type, b, mask;
    unsigned changes = (state ^ tsdPtr->lastState) & ALL_BUTTONS;
    int type, b;
    unsigned mask;

    pos.x = x;
    pos.y = y;

    /*
     * Use the current keyboard state, but the old mouse button state since we
     * haven't generated the button events yet.
250
251
252
253
254
255
256
257
258


259
260
261
262
263
264
265
250
251
252
253
254
255
256


257
258
259
260
261
262
263
264
265







-
-
+
+







    }

    /*
     * Generate ButtonPress/ButtonRelease events based on the differences
     * between the current button state and the last known button state.
     */

    for (b = Button1; b <= Button5; b++) {
	mask = TkGetButtonMask(b);
    for (b = Button1; b <= Button9; b++) {
	mask = Tk_GetButtonMask(b);
	if (changes & mask) {
	    if (state & mask) {
		type = ButtonPress;

		/*
		 * ButtonPress - Set restrict window if we aren't grabbed, or
		 * if this is the first button down.
420
421
422
423
424
425
426
427

428







429
430
431
432
433
434
435
420
421
422
423
424
425
426

427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442







-
+

+
+
+
+
+
+
+







    unsigned int event_mask,
    int pointer_mode,
    int keyboard_mode,
    Window confine_to,
    Cursor cursor,
    Time time)
{
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    (void)owner_events;
    (void)event_mask;
    (void)pointer_mode;
    (void)keyboard_mode;
    (void)confine_to;
    (void)cursor;
    (void)time;

    display->request++;
    tsdPtr->grabWinPtr = (TkWindow *) Tk_IdToWindow(display, grab_window);
    tsdPtr->restrictWinPtr = NULL;
    TkpSetCapture(tsdPtr->grabWinPtr);
    if (TkPositionInTree(tsdPtr->lastWinPtr, tsdPtr->grabWinPtr)
	    != TK_GRAB_IN_TREE) {
455
456
457
458
459
460
461
462

463

464
465
466
467
468
469
470
462
463
464
465
466
467
468

469
470
471
472
473
474
475
476
477
478







-
+

+







 */

int
XUngrabPointer(
    Display *display,
    Time time)
{
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    (void)time;

    display->request++;
    tsdPtr->grabWinPtr = NULL;
    tsdPtr->restrictWinPtr = NULL;
    TkpSetCapture(NULL);
    UpdateCursor(tsdPtr->lastWinPtr);
    return Success;
486
487
488
489
490
491
492
493

494
495
496
497
498
499
500
494
495
496
497
498
499
500

501
502
503
504
505
506
507
508







-
+







 *----------------------------------------------------------------------
 */

void
TkPointerDeadWindow(
    TkWindow *winPtr)
{
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (winPtr == tsdPtr->lastWinPtr) {
	tsdPtr->lastWinPtr = NULL;
    }
    if (winPtr == tsdPtr->grabWinPtr) {
	tsdPtr->grabWinPtr = NULL;
533
534
535
536
537
538
539
540

541
542
543
544
545
546
547
541
542
543
544
545
546
547

548
549
550
551
552
553
554
555







-
+







 */

static void
UpdateCursor(
    TkWindow *winPtr)
{
    Cursor cursor = None;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    /*
     * A window inherits its cursor from its parent if it doesn't have one of
     * its own. Top level windows inherit the default cursor.
     */

579
580
581
582
583
584
585
586

587

588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
587
588
589
590
591
592
593

594
595
596
597
598
599
600
601
602
603









































604
605
606
607
608
609
610
611







-
+

+







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-








int
XDefineCursor(
    Display *display,
    Window w,
    Cursor cursor)
{
    TkWindow *winPtr = (TkWindow *) Tk_IdToWindow(display, w);
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    (void)cursor;

    if (tsdPtr->cursorWinPtr == winPtr) {
	UpdateCursor(winPtr);
    }
    display->request++;
    return Success;
}

/*
 *----------------------------------------------------------------------
 *
 * TkGenerateActivateEvents --
 *
 *	This function is called by the Mac and Windows window manager routines
 *	when a toplevel window is activated or deactivated.
 *	Activate/Deactivate events will be sent to every subwindow of the
 *	toplevel followed by a FocusIn/FocusOut message.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Generates X events.
 *
 *----------------------------------------------------------------------
 */

void
TkGenerateActivateEvents(
    TkWindow *winPtr,		/* Toplevel to activate. */
    int active)			/* Non-zero if the window is being activated,
				 * else 0.*/
{
    XEvent event;

    /*
     * Generate Activate and Deactivate events. This event is sent to every
     * subwindow in a toplevel window.
     */

    event.xany.serial = winPtr->display->request++;
    event.xany.send_event = False;
    event.xany.display = winPtr->display;
    event.xany.window = winPtr->window;

    event.xany.type = active ? ActivateNotify : DeactivateNotify;
    TkQueueEventForAllChildren(winPtr, &event);
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Changes to generic/tkRectOval.c.
1
2
3
4
5
6
7


8
9
10
11
12
13
14
1
2
3
4
5


6
7
8
9
10
11
12
13
14





-
-
+
+







/*
 * 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.
 */

#include "tkInt.h"
#include "tkCanvas.h"
43
44
45
46
47
48
49
50

51
52
53
54
55
56
57
58
59
60
61
62
63
64

65
66
67

68
69

70
71

72
73
74

75
76

77
78
79

80
81
82

83
84
85

86
87
88

89
90

91
92
93

94
95
96

97
98

99
100
101

102
103

104
105
106

107
108

109
110
111

112
113

114
115

116
117
118
119

120
121
122
123
124
125
126
43
44
45
46
47
48
49

50
51
52
53
54
55
56
57
58
59
60
61
62
63

64
65
66

67
68

69
70

71
72
73

74
75

76
77
78

79
80
81

82
83
84

85
86
87

88
89

90
91
92

93
94
95

96
97

98
99
100

101
102

103
104
105

106
107

108
109
110

111
112

113
114

115
116
117
118

119
120
121
122
123
124
125
126







-
+













-
+


-
+

-
+

-
+


-
+

-
+


-
+


-
+


-
+


-
+

-
+


-
+


-
+

-
+


-
+

-
+


-
+

-
+


-
+

-
+

-
+



-
+







 * Information used for parsing configuration specs:
 */

static const Tk_CustomOption stateOption = {
    TkStateParseProc, TkStatePrintProc, INT2PTR(2)
};
static const Tk_CustomOption tagsOption = {
    Tk_CanvasTagsParseProc, Tk_CanvasTagsPrintProc, NULL
    TkCanvasTagsParseProc, TkCanvasTagsPrintProc, NULL
};
static const Tk_CustomOption dashOption = {
    TkCanvasDashParseProc, TkCanvasDashPrintProc, NULL
};
static const Tk_CustomOption offsetOption = {
    TkOffsetParseProc, TkOffsetPrintProc, INT2PTR(TK_OFFSET_RELATIVE)
};
static const Tk_CustomOption pixelOption = {
    TkPixelParseProc, TkPixelPrintProc, NULL
};

static const Tk_ConfigSpec configSpecs[] = {
    {TK_CONFIG_CUSTOM, "-activedash", NULL, NULL,
	NULL, Tk_Offset(RectOvalItem, outline.activeDash),
	NULL, offsetof(RectOvalItem, outline.activeDash),
	TK_CONFIG_NULL_OK, &dashOption},
    {TK_CONFIG_COLOR, "-activefill", NULL, NULL,
	NULL, Tk_Offset(RectOvalItem, activeFillColor), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(RectOvalItem, activeFillColor), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_COLOR, "-activeoutline", NULL, NULL,
	NULL, Tk_Offset(RectOvalItem, outline.activeColor), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(RectOvalItem, outline.activeColor), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_BITMAP, "-activeoutlinestipple", NULL, NULL,
	NULL, Tk_Offset(RectOvalItem, outline.activeStipple),
	NULL, offsetof(RectOvalItem, outline.activeStipple),
	TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_BITMAP, "-activestipple", NULL, NULL,
	NULL, Tk_Offset(RectOvalItem, activeFillStipple), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(RectOvalItem, activeFillStipple), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_CUSTOM, "-activewidth", NULL, NULL,
	"0.0", Tk_Offset(RectOvalItem, outline.activeWidth),
	"0.0", offsetof(RectOvalItem, outline.activeWidth),
	TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
    {TK_CONFIG_CUSTOM, "-dash", NULL, NULL,
	NULL, Tk_Offset(RectOvalItem, outline.dash),
	NULL, offsetof(RectOvalItem, outline.dash),
	TK_CONFIG_NULL_OK, &dashOption},
    {TK_CONFIG_PIXELS, "-dashoffset", NULL, NULL,
	"0", Tk_Offset(RectOvalItem, outline.offset),
	"0", offsetof(RectOvalItem, outline.offset),
	TK_CONFIG_DONT_SET_DEFAULT, NULL},
    {TK_CONFIG_CUSTOM, "-disableddash", NULL, NULL,
	NULL, Tk_Offset(RectOvalItem, outline.disabledDash),
	NULL, offsetof(RectOvalItem, outline.disabledDash),
	TK_CONFIG_NULL_OK, &dashOption},
    {TK_CONFIG_COLOR, "-disabledfill", NULL, NULL,
	NULL, Tk_Offset(RectOvalItem, disabledFillColor), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(RectOvalItem, disabledFillColor), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_COLOR, "-disabledoutline", NULL, NULL,
	NULL, Tk_Offset(RectOvalItem, outline.disabledColor),
	NULL, offsetof(RectOvalItem, outline.disabledColor),
	TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_BITMAP, "-disabledoutlinestipple", NULL, NULL,
	NULL, Tk_Offset(RectOvalItem, outline.disabledStipple),
	NULL, offsetof(RectOvalItem, outline.disabledStipple),
	TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_BITMAP, "-disabledstipple", NULL, NULL,
	NULL, Tk_Offset(RectOvalItem, disabledFillStipple), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(RectOvalItem, disabledFillStipple), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_PIXELS, "-disabledwidth", NULL, NULL,
	"0.0", Tk_Offset(RectOvalItem, outline.disabledWidth),
	"0.0", offsetof(RectOvalItem, outline.disabledWidth),
	TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
    {TK_CONFIG_COLOR, "-fill", NULL, NULL,
	NULL, Tk_Offset(RectOvalItem, fillColor), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(RectOvalItem, fillColor), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_CUSTOM, "-offset", NULL, NULL,
	"0,0", Tk_Offset(RectOvalItem, tsoffset),
	"0,0", offsetof(RectOvalItem, tsoffset),
	TK_CONFIG_DONT_SET_DEFAULT, &offsetOption},
    {TK_CONFIG_COLOR, "-outline", NULL, NULL,
	DEF_CANVITEM_OUTLINE, Tk_Offset(RectOvalItem, outline.color), TK_CONFIG_NULL_OK, NULL},
	DEF_CANVITEM_OUTLINE, offsetof(RectOvalItem, outline.color), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_CUSTOM, "-outlineoffset", NULL, NULL,
	"0,0", Tk_Offset(RectOvalItem, outline.tsoffset),
	"0,0", offsetof(RectOvalItem, outline.tsoffset),
	TK_CONFIG_DONT_SET_DEFAULT, &offsetOption},
    {TK_CONFIG_BITMAP, "-outlinestipple", NULL, NULL,
	NULL, Tk_Offset(RectOvalItem, outline.stipple), TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(RectOvalItem, outline.stipple), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_CUSTOM, "-state", NULL, NULL,
	NULL, Tk_Offset(Tk_Item, state),TK_CONFIG_NULL_OK, &stateOption},
	NULL, offsetof(Tk_Item, state),TK_CONFIG_NULL_OK, &stateOption},
    {TK_CONFIG_BITMAP, "-stipple", NULL, NULL,
	NULL, Tk_Offset(RectOvalItem, fillStipple),TK_CONFIG_NULL_OK, NULL},
	NULL, offsetof(RectOvalItem, fillStipple),TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_CUSTOM, "-tags", NULL, NULL,
	NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},
    {TK_CONFIG_CUSTOM, "-width", NULL, NULL,
	"1.0", Tk_Offset(RectOvalItem, outline.width),
	"1.0", offsetof(RectOvalItem, outline.width),
	TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
    {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL}
};

/*
 * Prototypes for functions defined in this file:
 */
145
146
147
148
149
150
151


152
153
154
155
156
157
158
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160







+
+







			    Tk_Item *itemPtr, int objc, Tcl_Obj *const objv[]);
static int		RectOvalToPostscript(Tcl_Interp *interp,
			    Tk_Canvas canvas, Tk_Item *itemPtr, int prepass);
static int		RectToArea(Tk_Canvas canvas, Tk_Item *itemPtr,
			    double *areaPtr);
static double		RectToPoint(Tk_Canvas canvas, Tk_Item *itemPtr,
			    double *pointPtr);
static void		RotateRectOval(Tk_Canvas canvas, Tk_Item *itemPtr,
			    double originX, double originY, double angleRad);
static void		ScaleRectOval(Tk_Canvas canvas, Tk_Item *itemPtr,
			    double originX, double originY,
			    double scaleX, double scaleY);
static void		TranslateRectOval(Tk_Canvas canvas, Tk_Item *itemPtr,
			    double deltaX, double deltaY);

/*
177
178
179
180
181
182
183

184

185
186
187
188
189
190
191
179
180
181
182
183
184
185
186

187
188
189
190
191
192
193
194







+
-
+







    TranslateRectOval,		/* translateProc */
    NULL,			/* indexProc */
    NULL,			/* icursorProc */
    NULL,			/* selectionProc */
    NULL,			/* insertProc */
    NULL,			/* dTextProc */
    NULL,			/* nextPtr */
    RotateRectOval,		/* rotateProc */
    NULL, 0, NULL, NULL
    0, NULL, NULL
};

Tk_ItemType tkOvalType = {
    "oval",			/* name */
    sizeof(RectOvalItem),	/* itemSize */
    CreateRectOval,		/* createProc */
    configSpecs,		/* configSpecs */
201
202
203
204
205
206
207

208

209
210
211
212
213
214
215
204
205
206
207
208
209
210
211

212
213
214
215
216
217
218
219







+
-
+







    TranslateRectOval,		/* translateProc */
    NULL,			/* indexProc */
    NULL,			/* cursorProc */
    NULL,			/* selectionProc */
    NULL,			/* insertProc */
    NULL,			/* dTextProc */
    NULL,			/* nextPtr */
    RotateRectOval,		/* rotateProc */
    NULL, 0, NULL, NULL
    0, NULL, NULL
};

/*
 *--------------------------------------------------------------
 *
 * CreateRectOval --
 *
571
572
573
574
575
576
577

578
579
580
581
582
583
584
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589







+







static void
DeleteRectOval(
    Tk_Canvas canvas,		/* Info about overall widget. */
    Tk_Item *itemPtr,		/* Item that is being deleted. */
    Display *display)		/* Display containing window for canvas. */
{
    RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
    (void)canvas;

    Tk_DeleteOutline(display, &(rectOvalPtr->outline));
    if (rectOvalPtr->fillColor != NULL) {
	Tk_FreeColor(rectOvalPtr->fillColor);
    }
    if (rectOvalPtr->activeFillColor != NULL) {
	Tk_FreeColor(rectOvalPtr->activeFillColor);
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
618
619
620
621
622
623
624

625
626
627
628
629
630
631







-







 *
 * Side effects:
 *	The fields x1, y1, x2, and y2 are updated in the header for itemPtr.
 *
 *--------------------------------------------------------------
 */

	/* ARGSUSED */
static void
ComputeRectOvalBbox(
    Tk_Canvas canvas,		/* Canvas that contains item. */
    RectOvalItem *rectOvalPtr)	/* Item whose bbox is to be recomputed. */
{
    int bloat, tmp;
    double dtmp, width;
744
745
746
747
748
749
750




751
752
753
754
755
756
757
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765







+
+
+
+







				/* Describes region of canvas that must be
				 * redisplayed (not used). */
{
    RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
    short x1, y1, x2, y2;
    Pixmap fillStipple;
    Tk_State state = itemPtr->state;
    (void)x;
    (void)y;
    (void)width;
    (void)height;

    /*
     * Compute the screen coordinates of the bounding box for the item. Make
     * sure that the bbox is at least one pixel large, since some X servers
     * will die if it isn't.
     */

953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
961
962
963
964
965
966
967

968
969
970
971
972
973
974







-







 *
 * Side effects:
 *	None.
 *
 *--------------------------------------------------------------
 */

	/* ARGSUSED */
static double
RectToPoint(
    Tk_Canvas canvas,		/* Canvas containing item. */
    Tk_Item *itemPtr,		/* Item to check against point. */
    double *pointPtr)		/* Pointer to x and y coordinates. */
{
    RectOvalItem *rectPtr = (RectOvalItem *) itemPtr;
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1080
1081
1082
1083
1084
1085
1086

1087
1088
1089
1090
1091
1092
1093







-







 *
 * Side effects:
 *	None.
 *
 *--------------------------------------------------------------
 */

	/* ARGSUSED */
static double
OvalToPoint(
    Tk_Canvas canvas,		/* Canvas containing item. */
    Tk_Item *itemPtr,		/* Item to check against point. */
    double *pointPtr)		/* Pointer to x and y coordinates. */
{
    RectOvalItem *ovalPtr = (RectOvalItem *) itemPtr;
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1134
1135
1136
1137
1138
1139
1140

1141
1142
1143
1144
1145
1146
1147







-







 *
 * Side effects:
 *	None.
 *
 *--------------------------------------------------------------
 */

	/* ARGSUSED */
static int
RectToArea(
    Tk_Canvas canvas,		/* Canvas containing item. */
    Tk_Item *itemPtr,		/* Item to check against rectangle. */
    double *areaPtr)		/* Pointer to array of four coordinates (x1,
				 * y1, x2, y2) describing rectangular area. */
{
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1207
1208
1209
1210
1211
1212
1213

1214
1215
1216
1217
1218
1219
1220







-







 *
 * Side effects:
 *	None.
 *
 *--------------------------------------------------------------
 */

	/* ARGSUSED */
static int
OvalToArea(
    Tk_Canvas canvas,		/* Canvas containing item. */
    Tk_Item *itemPtr,		/* Item to check against oval. */
    double *areaPtr)		/* Pointer to array of four coordinates (x1,
				 * y1, x2, y2) describing rectangular area. */
{
1278
1279
1280
1281
1282
1283
1284



















































1285
1286
1287
1288
1289
1290
1291
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







		&& ((xDelta2 + yDelta1) < 1.0)
		&& ((xDelta2 + yDelta2) < 1.0)) {
	    return -1;
	}
    }
    return result;
}

/*
 *--------------------------------------------------------------
 *
 * RotateRectOval --
 *
 *	This function is invoked to rotate a rectangle or oval item's
 *	coordinates. It works by rotating a computed point in the centre of
 *	the bounding box, NOT by rotating the corners of the bounding box.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The position of the rectangle or oval is rotated by angleRad about
 *	(originX, originY), and the bounding box is updated in the generic
 *	part of the item structure.
 *
 *--------------------------------------------------------------
 */

static void
RotateRectOval(
    Tk_Canvas canvas,		/* Canvas containing rectangle. */
    Tk_Item *itemPtr,		/* Rectangle to be scaled. */
    double originX, double originY,
				/* Origin about which to rotate rect. */
    double angleRad)		/* Amount to scale in X direction. */
{
    RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
    double newX, newY, oldX, oldY;

    /*
     * Compute the centre of the box, then rotate that about the origin.
     */

    newX = oldX = (rectOvalPtr->bbox[0] + rectOvalPtr->bbox[2]) / 2.0;
    newY = oldY = (rectOvalPtr->bbox[1] + rectOvalPtr->bbox[3]) / 2.0;
    TkRotatePoint(originX, originY, sin(angleRad), cos(angleRad),
	    &newX, &newY);

    /*
     * Apply the translation to the box.
     */

    rectOvalPtr->bbox[0] += newX - oldX;
    rectOvalPtr->bbox[1] += newY - oldY;
    rectOvalPtr->bbox[2] += newX - oldX;
    rectOvalPtr->bbox[3] += newY - oldY;
    ComputeRectOvalBbox(canvas, rectOvalPtr);
}

/*
 *--------------------------------------------------------------
 *
 * ScaleRectOval --
 *
 *	This function is invoked to rescale a rectangle or oval item.
1387
1388
1389
1390
1391
1392
1393

1394
1395
1396
1397
1398
1399
1400
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456







+







    RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
    double y1, y2;
    XColor *color;
    XColor *fillColor;
    Pixmap fillStipple;
    Tk_State state = itemPtr->state;
    Tcl_InterpState interpState;
    (void)prepass;

    y1 = Tk_CanvasPsY(canvas, rectOvalPtr->bbox[1]);
    y2 = Tk_CanvasPsY(canvas, rectOvalPtr->bbox[3]);

    /*
     * Generate a string that creates a path for the rectangle or oval. This
     * is the only part of the function's code that is type-specific.
1461
1462
1463
1464
1465
1466
1467
1468

1469
1470
1471
1472
1473
1474
1475
1476
1477

1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498

1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1517
1518
1519
1520
1521
1522
1523

1524


1525
1526
1527
1528
1529
1530

1531


1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549

1550



1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562






1563
1564
1565
1566
1567
1568
1569
1570
1571







-
+
-
-






-
+
-
-


















-
+
-
-
-












-
-
-
-
-
-









     * First draw the filled area of the rectangle.
     */

    if (fillColor != NULL) {
	Tcl_AppendObjToObj(psObj, pathObj);

	Tcl_ResetResult(interp);
	if (Tk_CanvasPsColor(interp, canvas, fillColor) != TCL_OK) {
	Tk_CanvasPsColor(interp, canvas, fillColor);
	    goto error;
	}
	Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));

	if (fillStipple != None) {
	    Tcl_AppendToObj(psObj, "clip ", -1);

	    Tcl_ResetResult(interp);
	    if (Tk_CanvasPsStipple(interp, canvas, fillStipple) != TCL_OK) {
	    Tk_CanvasPsStipple(interp, canvas, fillStipple);
		goto error;
	    }
	    Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
	    if (color != NULL) {
		Tcl_AppendToObj(psObj, "grestore gsave\n", -1);
	    }
	} else {
	    Tcl_AppendToObj(psObj, "fill\n", -1);
	}
    }

    /*
     * Now draw the outline, if there is one.
     */

    if (color != NULL) {
	Tcl_AppendObjToObj(psObj, pathObj);
	Tcl_AppendToObj(psObj, "0 setlinejoin 2 setlinecap\n", -1);

	Tcl_ResetResult(interp);
	if (Tk_CanvasPsOutline(canvas, itemPtr,
	Tk_CanvasPsOutline(canvas, itemPtr, &rectOvalPtr->outline);
		&rectOvalPtr->outline)!= TCL_OK) {
	    goto error;
	}
	Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
    }

    /*
     * Plug the accumulated postscript back into the result.
     */

    (void) Tcl_RestoreInterpState(interp, interpState);
    Tcl_AppendObjToObj(Tcl_GetObjResult(interp), psObj);
    Tcl_DecrRefCount(psObj);
    Tcl_DecrRefCount(pathObj);
    return TCL_OK;

  error:
    Tcl_DiscardInterpState(interpState);
    Tcl_DecrRefCount(psObj);
    Tcl_DecrRefCount(pathObj);
    return TCL_ERROR;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Changes to generic/tkScale.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14



15
16
17
18
19
20
21
22



23
24
25
26
27
28
29
1
2
3
4
5
6
7
8
9
10
11



12
13
14
15
16
17
18
19



20
21
22
23
24
25
26
27
28
29











-
-
-
+
+
+





-
-
-
+
+
+







/*
 * tkScale.c --
 *
 *	This module implements a scale widgets for the Tk toolkit. A scale
 *	displays a slider that can be adjusted to change a value; it also
 *	displays numeric labels and a textual label, if desired.
 *
 *	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.
 */

#include "default.h"
#include "tkInt.h"
#include "tkScale.h"
#include "tkInt.h"
#include "tkScale.h"
#include "default.h"

#if defined(_WIN32)
#define snprintf _snprintf
#endif

/*
 * The following table defines the legal values for the -orient option. It is
41
42
43
44
45
46
47
48

49
50
51

52
53
54

55
56
57

58
59

60
61

62
63
64

65
66
67

68
69
70

71
72
73

74
75

76
77

78
79
80


81
82
83

84
85
86

87
88
89
90


91
92

93
94
95

96
97

98
99
100

101
102

103
104
105

106
107
108

109
110
111

112
113
114

115
116
117

118
119
120

121
122
123

124
125
126

127
128
129

130
131

132
133
134

135
136
137
138


139
140
141
142
143
144
145
41
42
43
44
45
46
47

48
49
50

51
52
53

54
55
56

57
58

59
60

61
62
63

64
65
66

67
68
69

70
71
72

73
74

75
76

77
78


79
80
81
82

83
84
85

86
87
88


89
90
91

92
93
94

95
96

97
98
99

100
101

102
103
104

105
106
107

108
109
110

111
112
113

114
115
116

117
118
119

120
121
122

123
124
125

126
127
128

129
130

131
132
133

134
135
136


137
138
139
140
141
142
143
144
145







-
+


-
+


-
+


-
+

-
+

-
+


-
+


-
+


-
+


-
+

-
+

-
+

-
-
+
+


-
+


-
+


-
-
+
+

-
+


-
+

-
+


-
+

-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+

-
+


-
+


-
-
+
+








static const char *const stateStrings[] = {
    "active", "disabled", "normal", NULL
};

static const Tk_OptionSpec optionSpecs[] = {
    {TK_OPTION_BORDER, "-activebackground", "activeBackground", "Foreground",
	DEF_SCALE_ACTIVE_BG_COLOR, -1, Tk_Offset(TkScale, activeBorder),
	DEF_SCALE_ACTIVE_BG_COLOR, TCL_INDEX_NONE, offsetof(TkScale, activeBorder),
	0, DEF_SCALE_ACTIVE_BG_MONO, 0},
    {TK_OPTION_BORDER, "-background", "background", "Background",
	DEF_SCALE_BG_COLOR, -1, Tk_Offset(TkScale, bgBorder),
	DEF_SCALE_BG_COLOR, TCL_INDEX_NONE, offsetof(TkScale, bgBorder),
	0, DEF_SCALE_BG_MONO, 0},
    {TK_OPTION_DOUBLE, "-bigincrement", "bigIncrement", "BigIncrement",
	DEF_SCALE_BIG_INCREMENT, -1, Tk_Offset(TkScale, bigIncrement),
	DEF_SCALE_BIG_INCREMENT, TCL_INDEX_NONE, offsetof(TkScale, bigIncrement),
	0, 0, 0},
    {TK_OPTION_SYNONYM, "-bd", NULL, NULL,
	NULL, 0, -1, 0, "-borderwidth", 0},
	NULL, 0, TCL_INDEX_NONE, 0, "-borderwidth", 0},
    {TK_OPTION_SYNONYM, "-bg", NULL, NULL,
	NULL, 0, -1, 0, "-background", 0},
	NULL, 0, TCL_INDEX_NONE, 0, "-background", 0},
    {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
	DEF_SCALE_BORDER_WIDTH, -1, Tk_Offset(TkScale, borderWidth),
	DEF_SCALE_BORDER_WIDTH, TCL_INDEX_NONE, offsetof(TkScale, borderWidth),
	0, 0, 0},
    {TK_OPTION_STRING, "-command", "command", "Command",
	DEF_SCALE_COMMAND, -1, Tk_Offset(TkScale, command),
	DEF_SCALE_COMMAND, TCL_INDEX_NONE, offsetof(TkScale, command),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
	DEF_SCALE_CURSOR, -1, Tk_Offset(TkScale, cursor),
	DEF_SCALE_CURSOR, TCL_INDEX_NONE, offsetof(TkScale, cursor),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_INT, "-digits", "digits", "Digits",
	DEF_SCALE_DIGITS, -1, Tk_Offset(TkScale, digits),
	DEF_SCALE_DIGITS, TCL_INDEX_NONE, offsetof(TkScale, digits),
	0, 0, 0},
    {TK_OPTION_SYNONYM, "-fg", "foreground", NULL,
	NULL, 0, -1, 0, "-foreground", 0},
	NULL, 0, TCL_INDEX_NONE, 0, "-foreground", 0},
    {TK_OPTION_FONT, "-font", "font", "Font",
	DEF_SCALE_FONT, -1, Tk_Offset(TkScale, tkfont), 0, 0, 0},
	DEF_SCALE_FONT, TCL_INDEX_NONE, offsetof(TkScale, tkfont), 0, 0, 0},
    {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
	DEF_SCALE_FG_COLOR, -1, Tk_Offset(TkScale, textColorPtr), 0,
	DEF_SCALE_FG_COLOR, TCL_INDEX_NONE, offsetof(TkScale, textColorPtr), 0,
	(ClientData) DEF_SCALE_FG_MONO, 0},
    {TK_OPTION_DOUBLE, "-from", "from", "From", DEF_SCALE_FROM, -1,
	Tk_Offset(TkScale, fromValue), 0, 0, 0},
    {TK_OPTION_DOUBLE, "-from", "from", "From", DEF_SCALE_FROM, TCL_INDEX_NONE,
	offsetof(TkScale, fromValue), 0, 0, 0},
    {TK_OPTION_BORDER, "-highlightbackground", "highlightBackground",
	"HighlightBackground", DEF_SCALE_HIGHLIGHT_BG_COLOR,
	-1, Tk_Offset(TkScale, highlightBorder),
	TCL_INDEX_NONE, offsetof(TkScale, highlightBorder),
	0, DEF_SCALE_HIGHLIGHT_BG_MONO, 0},
    {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
	DEF_SCALE_HIGHLIGHT, -1, Tk_Offset(TkScale, highlightColorPtr),
	DEF_SCALE_HIGHLIGHT, TCL_INDEX_NONE, offsetof(TkScale, highlightColorPtr),
	0, 0, 0},
    {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
	"HighlightThickness", DEF_SCALE_HIGHLIGHT_WIDTH, -1,
	Tk_Offset(TkScale, highlightWidth), 0, 0, 0},
	"HighlightThickness", DEF_SCALE_HIGHLIGHT_WIDTH, TCL_INDEX_NONE,
	offsetof(TkScale, highlightWidth), 0, 0, 0},
    {TK_OPTION_STRING, "-label", "label", "Label",
	DEF_SCALE_LABEL, -1, Tk_Offset(TkScale, label),
	DEF_SCALE_LABEL, TCL_INDEX_NONE, offsetof(TkScale, label),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_PIXELS, "-length", "length", "Length",
	DEF_SCALE_LENGTH, -1, Tk_Offset(TkScale, length), 0, 0, 0},
	DEF_SCALE_LENGTH, TCL_INDEX_NONE, offsetof(TkScale, length), 0, 0, 0},
    {TK_OPTION_STRING_TABLE, "-orient", "orient", "Orient",
	DEF_SCALE_ORIENT, -1, Tk_Offset(TkScale, orient),
	DEF_SCALE_ORIENT, TCL_INDEX_NONE, offsetof(TkScale, orient),
	0, orientStrings, 0},
    {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
	DEF_SCALE_RELIEF, -1, Tk_Offset(TkScale, relief), 0, 0, 0},
	DEF_SCALE_RELIEF, TCL_INDEX_NONE, offsetof(TkScale, relief), 0, 0, 0},
    {TK_OPTION_INT, "-repeatdelay", "repeatDelay", "RepeatDelay",
	DEF_SCALE_REPEAT_DELAY, -1, Tk_Offset(TkScale, repeatDelay),
	DEF_SCALE_REPEAT_DELAY, TCL_INDEX_NONE, offsetof(TkScale, repeatDelay),
	0, 0, 0},
    {TK_OPTION_INT, "-repeatinterval", "repeatInterval", "RepeatInterval",
	DEF_SCALE_REPEAT_INTERVAL, -1, Tk_Offset(TkScale, repeatInterval),
	DEF_SCALE_REPEAT_INTERVAL, TCL_INDEX_NONE, offsetof(TkScale, repeatInterval),
	0, 0, 0},
    {TK_OPTION_DOUBLE, "-resolution", "resolution", "Resolution",
	DEF_SCALE_RESOLUTION, -1, Tk_Offset(TkScale, resolution),
	DEF_SCALE_RESOLUTION, TCL_INDEX_NONE, offsetof(TkScale, resolution),
	0, 0, 0},
    {TK_OPTION_BOOLEAN, "-showvalue", "showValue", "ShowValue",
	DEF_SCALE_SHOW_VALUE, -1, Tk_Offset(TkScale, showValue),
	DEF_SCALE_SHOW_VALUE, TCL_INDEX_NONE, offsetof(TkScale, showValue),
	0, 0, 0},
    {TK_OPTION_PIXELS, "-sliderlength", "sliderLength", "SliderLength",
	DEF_SCALE_SLIDER_LENGTH, -1, Tk_Offset(TkScale, sliderLength),
	DEF_SCALE_SLIDER_LENGTH, TCL_INDEX_NONE, offsetof(TkScale, sliderLength),
	0, 0, 0},
    {TK_OPTION_RELIEF, "-sliderrelief", "sliderRelief", "SliderRelief",
	DEF_SCALE_SLIDER_RELIEF, -1, Tk_Offset(TkScale, sliderRelief),
	DEF_SCALE_SLIDER_RELIEF, TCL_INDEX_NONE, offsetof(TkScale, sliderRelief),
	0, 0, 0},
    {TK_OPTION_STRING_TABLE, "-state", "state", "State",
	DEF_SCALE_STATE, -1, Tk_Offset(TkScale, state),
	DEF_SCALE_STATE, TCL_INDEX_NONE, offsetof(TkScale, state),
	0, stateStrings, 0},
    {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
	DEF_SCALE_TAKE_FOCUS, Tk_Offset(TkScale, takeFocusPtr), -1,
	DEF_SCALE_TAKE_FOCUS, offsetof(TkScale, takeFocusPtr), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_DOUBLE, "-tickinterval", "tickInterval", "TickInterval",
	DEF_SCALE_TICK_INTERVAL, -1, Tk_Offset(TkScale, tickInterval),
	DEF_SCALE_TICK_INTERVAL, TCL_INDEX_NONE, offsetof(TkScale, tickInterval),
	0, 0, 0},
    {TK_OPTION_DOUBLE, "-to", "to", "To",
	DEF_SCALE_TO, -1, Tk_Offset(TkScale, toValue), 0, 0, 0},
	DEF_SCALE_TO, TCL_INDEX_NONE, offsetof(TkScale, toValue), 0, 0, 0},
    {TK_OPTION_COLOR, "-troughcolor", "troughColor", "Background",
	DEF_SCALE_TROUGH_COLOR, -1, Tk_Offset(TkScale, troughColorPtr),
	DEF_SCALE_TROUGH_COLOR, TCL_INDEX_NONE, offsetof(TkScale, troughColorPtr),
	0, DEF_SCALE_TROUGH_MONO, 0},
    {TK_OPTION_STRING, "-variable", "variable", "Variable",
	DEF_SCALE_VARIABLE, Tk_Offset(TkScale, varNamePtr), -1,
	DEF_SCALE_VARIABLE, offsetof(TkScale, varNamePtr), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_PIXELS, "-width", "width", "Width",
	DEF_SCALE_WIDTH, -1, Tk_Offset(TkScale, width), 0, 0, 0},
    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0, 0, 0}
	DEF_SCALE_WIDTH, TCL_INDEX_NONE, offsetof(TkScale, width), 0, 0, 0},
    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, TCL_INDEX_NONE, 0, 0, 0}
};

/*
 * The following tables define the scale widget commands and map the indexes
 * into the string tables into a single enumerated type used to dispatch the
 * scale widget command.
 */
157
158
159
160
161
162
163
164

165
166
167
168
169
170
171
157
158
159
160
161
162
163

164
165
166
167
168
169
170
171







-
+







 * Forward declarations for procedures defined later in this file:
 */

static void		ComputeFormat(TkScale *scalePtr, int forTicks);
static void		ComputeScaleGeometry(TkScale *scalePtr);
static int		ConfigureScale(Tcl_Interp *interp, TkScale *scalePtr,
			    int objc, Tcl_Obj *const objv[]);
static void		DestroyScale(char *memPtr);
static void		DestroyScale(void *memPtr);
static double		MaxTickRoundingError(TkScale *scalePtr,
			    double tickResolution);
static void		ScaleCmdDeletedProc(ClientData clientData);
static void		ScaleEventProc(ClientData clientData,
			    XEvent *eventPtr);
static char *		ScaleVarProc(ClientData clientData,
			    Tcl_Interp *interp, const char *name1,
244
245
246
247
248
249
250
251

252
253
254
255
256

257
258

259
260
261
262
263
264
265
244
245
246
247
248
249
250

251
252
253
254
255

256
257
258
259
260
261
262
263
264
265
266







-
+




-
+


+







 *	See the user documentation.
 *
 *--------------------------------------------------------------
 */

int
Tk_ScaleObjCmd(
    ClientData clientData,	/* NULL. */
    ClientData dummy,	/* NULL. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument values. */
{
    register TkScale *scalePtr;
    TkScale *scalePtr;
    Tk_OptionTable optionTable;
    Tk_Window tkwin;
    (void)dummy;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "pathName ?-option value ...?");
	return TCL_ERROR;
    }

    tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp),
339
340
341
342
343
344
345
346

347
348
349
350
351
352
353
354
355
356
357
358
359

360
361
362
363
364
365
366
340
341
342
343
344
345
346

347
348
349
350
351
352
353
354
355
356
357
358
359

360
361
362
363
364
365
366
367







-
+












-
+







    scalePtr->flags		= NEVER_SET;

    Tk_SetClassProcs(scalePtr->tkwin, &scaleClass, scalePtr);
    Tk_CreateEventHandler(scalePtr->tkwin,
	    ExposureMask|StructureNotifyMask|FocusChangeMask,
	    ScaleEventProc, scalePtr);

    if ((Tk_InitOptions(interp, (char *) scalePtr, optionTable, tkwin)
    if ((Tk_InitOptions(interp, scalePtr, optionTable, tkwin)
	    != TCL_OK) ||
	    (ConfigureScale(interp, scalePtr, objc - 2, objv + 2) != TCL_OK)) {
	Tk_DestroyWindow(scalePtr->tkwin);
	return TCL_ERROR;
    }

    /*
     * The widget was just created, no command callback must be invoked.
     */

    scalePtr->flags &= ~INVOKE_COMMAND;

    Tcl_SetObjResult(interp, TkNewWindowObj(scalePtr->tkwin));
    Tcl_SetObjResult(interp, Tk_NewWindowObj(scalePtr->tkwin));
    return TCL_OK;
}

/*
 *--------------------------------------------------------------
 *
 * ScaleWidgetObjCmd --
381
382
383
384
385
386
387
388

389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409

410
411
412
413
414
415
416
417
418

419
420
421
422
423
424
425
382
383
384
385
386
387
388

389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409

410
411
412
413
414
415
416
417
418

419
420
421
422
423
424
425
426







-
+




















-
+








-
+







static int
ScaleWidgetObjCmd(
    ClientData clientData,	/* Information about scale widget. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument strings. */
{
    TkScale *scalePtr = clientData;
    TkScale *scalePtr = (TkScale *)clientData;
    Tcl_Obj *objPtr;
    int index, result;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
	return TCL_ERROR;
    }
    result = Tcl_GetIndexFromObjStruct(interp, objv[1], commandNames,
	    sizeof(char *), "option", 0, &index);
    if (result != TCL_OK) {
	return result;
    }
    Tcl_Preserve(scalePtr);

    switch (index) {
    case COMMAND_CGET:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 1, objv, "cget option");
	    goto error;
	}
	objPtr = Tk_GetOptionValue(interp, (char *) scalePtr,
	objPtr = Tk_GetOptionValue(interp, scalePtr,
		scalePtr->optionTable, objv[2], scalePtr->tkwin);
	if (objPtr == NULL) {
	    goto error;
	}
	Tcl_SetObjResult(interp, objPtr);
	break;
    case COMMAND_CONFIGURE:
	if (objc <= 3) {
	    objPtr = Tk_GetOptionInfo(interp, (char *) scalePtr,
	    objPtr = Tk_GetOptionInfo(interp, scalePtr,
		    scalePtr->optionTable,
		    (objc == 3) ? objv[2] : NULL, scalePtr->tkwin);
	    if (objPtr == NULL) {
		goto error;
	    }
	    Tcl_SetObjResult(interp, objPtr);
	} else {
447
448
449
450
451
452
453
454
455


456
457
458
459
460
461
462
448
449
450
451
452
453
454


455
456
457
458
459
460
461
462
463







-
-
+
+







		    + scalePtr->borderWidth;
	    y = TkScaleValueToPixel(scalePtr, value);
	} else {
	    x = TkScaleValueToPixel(scalePtr, value);
	    y = scalePtr->horizTroughY + scalePtr->width/2
		    + scalePtr->borderWidth;
	}
	coords[0] = Tcl_NewIntObj(x);
	coords[1] = Tcl_NewIntObj(y);
	coords[0] = Tcl_NewWideIntObj(x);
	coords[1] = Tcl_NewWideIntObj(y);
	Tcl_SetObjResult(interp, Tcl_NewListObj(2, coords));
	break;
    }
    case COMMAND_GET: {
	double value;
	int x, y;

536
537
538
539
540
541
542
543

544
545

546
547
548
549
550
551
552
537
538
539
540
541
542
543

544
545

546
547
548
549
550
551
552
553







-
+

-
+







 *	Everything associated with the scale is freed up.
 *
 *----------------------------------------------------------------------
 */

static void
DestroyScale(
    char *memPtr)	/* Info about scale widget. */
    void *memPtr)	/* Info about scale widget. */
{
    register TkScale *scalePtr = (TkScale *) memPtr;
    TkScale *scalePtr = (TkScale *) memPtr;

    scalePtr->flags |= SCALE_DELETED;

    Tcl_DeleteCommandFromToken(scalePtr->interp, scalePtr->widgetCmd);
    if (scalePtr->flags & REDRAW_PENDING) {
	Tcl_CancelIdleCall(TkpDisplayScale, scalePtr);
    }
595
596
597
598
599
600
601
602

603
604
605
606
607
608
609
596
597
598
599
600
601
602

603
604
605
606
607
608
609
610







-
+







 *
 *----------------------------------------------------------------------
 */

static int
ConfigureScale(
    Tcl_Interp *interp,		/* Used for error reporting. */
    register TkScale *scalePtr,	/* Information about widget; may or may not
    TkScale *scalePtr,	/* Information about widget; may or may not
				 * already have values for some fields. */
    int objc,			/* Number of valid entries in objv. */
    Tcl_Obj *const objv[])	/* Argument values. */
{
    Tk_SavedOptions savedOptions;
    Tcl_Obj *errorResult = NULL;
    int error;
621
622
623
624
625
626
627
628

629
630
631
632
633
634
635
622
623
624
625
626
627
628

629
630
631
632
633
634
635
636







-
+








    for (error = 0; error <= 1; error++) {
	if (!error) {
	    /*
	     * First pass: set options to new values.
	     */

	    if (Tk_SetOptions(interp, (char *) scalePtr,
	    if (Tk_SetOptions(interp, scalePtr,
		    scalePtr->optionTable, objc, objv, scalePtr->tkwin,
		    &savedOptions, NULL) != TCL_OK) {
		continue;
	    }
	} else {
	    /*
	     * Second pass: restore options to old values.
654
655
656
657
658
659
660
661
662
663
664




665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685

686
687
688
689
690
691
692
655
656
657
658
659
660
661




662
663
664
665
666


667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683

684
685
686
687
688
689
690
691







-
-
-
-
+
+
+
+

-
-

















-
+







		    TCL_GLOBAL_ONLY);
	    if ((valuePtr != NULL) &&
		    (Tcl_GetDoubleFromObj(NULL, valuePtr, &value) == TCL_OK)) {
		scalePtr->value = TkRoundValueToResolution(scalePtr, value);
	    }
	}

	/*
	 * Several options need special processing, such as parsing the
	 * orientation and creating GCs.
	 */
        /*
         * The fromValue shall not be rounded to the resolution, but the
         * toValue and tickInterval do.
         */

	scalePtr->fromValue = TkRoundValueToResolution(scalePtr,
		scalePtr->fromValue);
	scalePtr->toValue = TkRoundValueToResolution(scalePtr, scalePtr->toValue);
	scalePtr->tickInterval = TkRoundIntervalToResolution(scalePtr,
		scalePtr->tickInterval);

	/*
	 * Make sure that the tick interval has the right sign so that
	 * addition moves from fromValue to toValue.
	 */

	if ((scalePtr->tickInterval < 0)
		^ ((scalePtr->toValue - scalePtr->fromValue) < 0)) {
	    scalePtr->tickInterval = -scalePtr->tickInterval;
	}

	ComputeFormat(scalePtr, 0);
	ComputeFormat(scalePtr, 1);

	scalePtr->labelLength = scalePtr->label ? (int)strlen(scalePtr->label) : 0;
	scalePtr->labelLength = scalePtr->label ? strlen(scalePtr->label) : 0;

	Tk_SetBackgroundFromBorder(scalePtr->tkwin, scalePtr->bgBorder);

	if (scalePtr->highlightWidth < 0) {
	    scalePtr->highlightWidth = 0;
	}
	scalePtr->inset = scalePtr->highlightWidth + scalePtr->borderWidth;
765
766
767
768
769
770
771
772

773
774
775
776
777
778
779
764
765
766
767
768
769
770

771
772
773
774
775
776
777
778







-
+








static void
ScaleWorldChanged(
    ClientData instanceData)	/* Information about widget. */
{
    XGCValues gcValues;
    GC gc;
    TkScale *scalePtr = instanceData;
    TkScale *scalePtr = (TkScale *)instanceData;

    gcValues.foreground = scalePtr->troughColorPtr->pixel;
    gc = Tk_GetGC(scalePtr->tkwin, GCForeground, &gcValues);
    if (scalePtr->troughGC != NULL) {
	Tk_FreeGC(scalePtr->display, scalePtr->troughGC);
    }
    scalePtr->troughGC = gc;
1015
1016
1017
1018
1019
1020
1021
1022

1023
1024
1025
1026
1027
1028
1029
1014
1015
1016
1017
1018
1019
1020

1021
1022
1023
1024
1025
1026
1027
1028







-
+







 *	gets told about the window's preferred size.
 *
 *----------------------------------------------------------------------
 */

static void
ComputeScaleGeometry(
    register TkScale *scalePtr)	/* Information about widget. */
    TkScale *scalePtr)	/* Information about widget. */
{
    char valueString[TCL_DOUBLE_SPACE];
    int tmp, valuePixels, tickPixels, x, y, extraSpace;
    Tk_FontMetrics fm;

    Tk_GetFontMetrics(scalePtr->tkfont, &fm);
    scalePtr->fontHeight = fm.linespace + SPACING;
1159
1160
1161
1162
1163
1164
1165
1166

1167
1168
1169
1170
1171
1172
1173
1158
1159
1160
1161
1162
1163
1164

1165
1166
1167
1168
1169
1170
1171
1172







-
+







 */

static void
ScaleEventProc(
    ClientData clientData,	/* Information about window. */
    XEvent *eventPtr)		/* Information about event. */
{
    TkScale *scalePtr = clientData;
    TkScale *scalePtr = (TkScale *)clientData;

    if ((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0)) {
	TkEventuallyRedrawScale(scalePtr, REDRAW_ALL);
    } else if (eventPtr->type == DestroyNotify) {
	DestroyScale(clientData);
    } else if (eventPtr->type == ConfigureNotify) {
	ComputeScaleGeometry(scalePtr);
1207
1208
1209
1210
1211
1212
1213
1214

1215
1216
1217
1218
1219
1220
1221
1206
1207
1208
1209
1210
1211
1212

1213
1214
1215
1216
1217
1218
1219
1220







-
+







 *----------------------------------------------------------------------
 */

static void
ScaleCmdDeletedProc(
    ClientData clientData)	/* Pointer to widget record for widget. */
{
    TkScale *scalePtr = clientData;
    TkScale *scalePtr = (TkScale *)clientData;
    Tk_Window tkwin = scalePtr->tkwin;

    /*
     * This procedure could be invoked either because the window was destroyed
     * and the command was then deleted (in which case tkwin is NULL) or
     * because the command was deleted, and then this procedure destroys the
     * widget.
1244
1245
1246
1247
1248
1249
1250
1251

1252
1253
1254
1255
1256
1257
1258
1243
1244
1245
1246
1247
1248
1249

1250
1251
1252
1253
1254
1255
1256
1257







-
+







 *	be redrawn.
 *
 *--------------------------------------------------------------
 */

void
TkEventuallyRedrawScale(
    register TkScale *scalePtr,	/* Information about widget. */
    TkScale *scalePtr,	/* Information about widget. */
    int what)			/* What to redraw: REDRAW_SLIDER or
				 * REDRAW_ALL. */
{
    if ((what == 0) || (scalePtr->tkwin == NULL)
	    || !Tk_IsMapped(scalePtr->tkwin)) {
	return;
    }
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349

1350
1351
1352
1353


1354
1355
1356
1357
1358
1359
1360
1332
1333
1334
1335
1336
1337
1338

1339
1340
1341
1342
1343
1344
1345
1346

1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360







-








-
+




+
+







 *	The value displayed in the scale will change to match the variable's
 *	new value. If the variable has a bogus value then it is reset to the
 *	value of the scale.
 *
 *----------------------------------------------------------------------
 */

    /* ARGSUSED */
static char *
ScaleVarProc(
    ClientData clientData,	/* Information about button. */
    Tcl_Interp *interp,		/* Interpreter containing variable. */
    const char *name1,		/* Name of variable. */
    const char *name2,		/* Second part of variable name. */
    int flags)			/* Information about what happened. */
{
    register TkScale *scalePtr = clientData;
    TkScale *scalePtr = (TkScale *)clientData;
    const char *resultStr;
    double value;
    Tcl_Obj *valuePtr;
    int result;
    (void)name1;
    (void)name2;

    /*
     * If the variable is unset, then immediately recreate it unless the whole
     * interpreter is going away.
     */

    if (flags & TCL_TRACE_UNSETS) {
1437
1438
1439
1440
1441
1442
1443
1444

1445
1446
1447
1448
1449
1450
1451
1437
1438
1439
1440
1441
1442
1443

1444
1445
1446
1447
1448
1449
1450
1451







-
+







 *	may also be invoked. The scale's slider is redrawn.
 *
 *--------------------------------------------------------------
 */

void
TkScaleSetValue(
    register TkScale *scalePtr,	/* Info about widget. */
    TkScale *scalePtr,	/* Info about widget. */
    double value,		/* New value for scale. Gets adjusted if it's
				 * off the scale. */
    int setVar,			/* Non-zero means reflect new value through to
				 * associated variable, if any. */
    int invokeCommand)		/* Non-zero means invoked -command option to
				 * notify of new value, 0 means don't. */
{
1495
1496
1497
1498
1499
1500
1501
1502

1503
1504
1505
1506
1507
1508
1509
1495
1496
1497
1498
1499
1500
1501

1502
1503
1504
1505
1506
1507
1508
1509







-
+







 *	Other write traces on the variable will trigger.
 *
 *--------------------------------------------------------------
 */

static void
ScaleSetVariable(
    register TkScale *scalePtr)	/* Info about widget. */
    TkScale *scalePtr)	/* Info about widget. */
{
    if (scalePtr->varNamePtr != NULL) {
	char string[TCL_DOUBLE_SPACE];

        if (snprintf(string, TCL_DOUBLE_SPACE, scalePtr->valueFormat,
                scalePtr->value) < 0) {
            string[TCL_DOUBLE_SPACE - 1] = '\0';
1531
1532
1533
1534
1535
1536
1537
1538

1539
1540
1541
1542
1543
1544
1545
1531
1532
1533
1534
1535
1536
1537

1538
1539
1540
1541
1542
1543
1544
1545







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

double
TkScalePixelToValue(
    register TkScale *scalePtr,	/* Information about widget. */
    TkScale *scalePtr,	/* Information about widget. */
    int x, int y)		/* Coordinates of point within window. */
{
    double value, pixelRange;

    if (scalePtr->orient == ORIENT_VERTICAL) {
	pixelRange = Tk_Height(scalePtr->tkwin) - scalePtr->sliderLength
		- 2*scalePtr->inset - 2*scalePtr->borderWidth;
1589
1590
1591
1592
1593
1594
1595
1596

1597
1598
1599
1600
1601
1602
1603
1589
1590
1591
1592
1593
1594
1595

1596
1597
1598
1599
1600
1601
1602
1603







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TkScaleValueToPixel(
    register TkScale *scalePtr,	/* Information about widget. */
    TkScale *scalePtr,	/* Information about widget. */
    double value)		/* Reading of the widget. */
{
    int y, pixelRange;
    double valueRange;

    valueRange = scalePtr->toValue - scalePtr->fromValue;
    pixelRange = ((scalePtr->orient == ORIENT_VERTICAL)
Changes to generic/tkScale.h.
1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15






-
-
+
+







/*
 * 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.
 */

#ifndef _TKSCALE
#define _TKSCALE
83
84
85
86
87
88
89
90

91
92
93
94
95
96
97
83
84
85
86
87
88
89

90
91
92
93
94
95
96
97







-
+







				 * commands because the scale value changed.
				 * NULL means don't invoke commands. */
    int repeatDelay;		/* How long to wait before auto-repeating on
				 * scrolling actions (in ms). */
    int repeatInterval;		/* Interval between autorepeats (in ms). */
    char *label;		/* Label to display above or to right of
				 * scale; NULL means don't display a label. */
    int labelLength;		/* Number of non-NULL chars. in label. */
    TkSizeT labelLength;	/* Number of non-NULL chars. in label. */
    enum state state;		/* Values are active, normal, or disabled.
				 * Value of scale cannot be changed when
				 * disabled. */

    /*
     * Information used when displaying widget:
     */
Changes to generic/tkScrollbar.c.
1
2
3
4
5
6
7
8
9


10
11
12
13
14
15
16
1
2
3
4
5
6
7


8
9
10
11
12
13
14
15
16







-
-
+
+







/*
 * tkScrollbar.c --
 *
 *	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.
 */

#include "tkInt.h"
#include "tkScrollbar.h"
29
30
31
32
33
34
35
36

37
38
39

40
41
42

43
44

45
46
47

48
49
50
51
52

53
54

55
56
57

58
59
60

61
62
63

64
65
66

67
68
69

70
71

72
73

74
75
76

77
78

79
80

81
82

83
84
85

86
87
88

89
90
91

92
93
94
95
96
97
98
29
30
31
32
33
34
35

36
37
38

39
40
41

42
43

44
45
46

47
48
49
50
51

52
53

54
55
56

57
58
59

60
61
62

63
64
65

66
67
68

69
70

71
72

73
74
75

76
77

78
79

80
81

82
83
84

85
86
87

88
89
90

91
92
93
94
95
96
97
98







-
+


-
+


-
+

-
+


-
+




-
+

-
+


-
+


-
+


-
+


-
+


-
+

-
+

-
+


-
+

-
+

-
+

-
+


-
+


-
+


-
+








/*
 * Information used for argv parsing.
 */

static const Tk_ConfigSpec configSpecs[] = {
    {TK_CONFIG_BORDER, "-activebackground", "activeBackground", "Foreground",
	DEF_SCROLLBAR_ACTIVE_BG_COLOR, Tk_Offset(TkScrollbar, activeBorder),
	DEF_SCROLLBAR_ACTIVE_BG_COLOR, offsetof(TkScrollbar, activeBorder),
	TK_CONFIG_COLOR_ONLY, NULL},
    {TK_CONFIG_BORDER, "-activebackground", "activeBackground", "Foreground",
	DEF_SCROLLBAR_ACTIVE_BG_MONO, Tk_Offset(TkScrollbar, activeBorder),
	DEF_SCROLLBAR_ACTIVE_BG_MONO, offsetof(TkScrollbar, activeBorder),
	TK_CONFIG_MONO_ONLY, NULL},
    {TK_CONFIG_RELIEF, "-activerelief", "activeRelief", "Relief",
	DEF_SCROLLBAR_ACTIVE_RELIEF, Tk_Offset(TkScrollbar, activeRelief), 0, NULL},
	DEF_SCROLLBAR_ACTIVE_RELIEF, offsetof(TkScrollbar, activeRelief), 0, NULL},
    {TK_CONFIG_BORDER, "-background", "background", "Background",
	DEF_SCROLLBAR_BG_COLOR, Tk_Offset(TkScrollbar, bgBorder),
	DEF_SCROLLBAR_BG_COLOR, offsetof(TkScrollbar, bgBorder),
	TK_CONFIG_COLOR_ONLY, NULL},
    {TK_CONFIG_BORDER, "-background", "background", "Background",
	DEF_SCROLLBAR_BG_MONO, Tk_Offset(TkScrollbar, bgBorder),
	DEF_SCROLLBAR_BG_MONO, offsetof(TkScrollbar, bgBorder),
	TK_CONFIG_MONO_ONLY, NULL},
    {TK_CONFIG_SYNONYM, "-bd", "borderWidth", NULL, NULL, 0, 0, NULL},
    {TK_CONFIG_SYNONYM, "-bg", "background", NULL, NULL, 0, 0, NULL},
    {TK_CONFIG_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
	DEF_SCROLLBAR_BORDER_WIDTH, Tk_Offset(TkScrollbar, borderWidth), 0, NULL},
	DEF_SCROLLBAR_BORDER_WIDTH, offsetof(TkScrollbar, borderWidth), 0, NULL},
    {TK_CONFIG_STRING, "-command", "command", "Command",
	DEF_SCROLLBAR_COMMAND, Tk_Offset(TkScrollbar, command),
	DEF_SCROLLBAR_COMMAND, offsetof(TkScrollbar, command),
	TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_ACTIVE_CURSOR, "-cursor", "cursor", "Cursor",
	DEF_SCROLLBAR_CURSOR, Tk_Offset(TkScrollbar, cursor), TK_CONFIG_NULL_OK, NULL},
	DEF_SCROLLBAR_CURSOR, offsetof(TkScrollbar, cursor), TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_PIXELS, "-elementborderwidth", "elementBorderWidth",
	"BorderWidth", DEF_SCROLLBAR_EL_BORDER_WIDTH,
	Tk_Offset(TkScrollbar, elementBorderWidth), 0, NULL},
	offsetof(TkScrollbar, elementBorderWidth), 0, NULL},
    {TK_CONFIG_COLOR, "-highlightbackground", "highlightBackground",
	"HighlightBackground", DEF_SCROLLBAR_HIGHLIGHT_BG,
	Tk_Offset(TkScrollbar, highlightBgColorPtr), 0, NULL},
	offsetof(TkScrollbar, highlightBgColorPtr), 0, NULL},
    {TK_CONFIG_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
	DEF_SCROLLBAR_HIGHLIGHT,
	Tk_Offset(TkScrollbar, highlightColorPtr), 0, NULL},
	offsetof(TkScrollbar, highlightColorPtr), 0, NULL},
    {TK_CONFIG_PIXELS, "-highlightthickness", "highlightThickness",
	"HighlightThickness",
	DEF_SCROLLBAR_HIGHLIGHT_WIDTH, Tk_Offset(TkScrollbar, highlightWidth), 0, NULL},
	DEF_SCROLLBAR_HIGHLIGHT_WIDTH, offsetof(TkScrollbar, highlightWidth), 0, NULL},
    {TK_CONFIG_BOOLEAN, "-jump", "jump", "Jump",
	DEF_SCROLLBAR_JUMP, Tk_Offset(TkScrollbar, jump), 0, NULL},
	DEF_SCROLLBAR_JUMP, offsetof(TkScrollbar, jump), 0, NULL},
    {TK_CONFIG_CUSTOM, "-orient", "orient", "Orient",
	DEF_SCROLLBAR_ORIENT, Tk_Offset(TkScrollbar, vertical), 0,
	DEF_SCROLLBAR_ORIENT, offsetof(TkScrollbar, vertical), 0,
	&orientOption},
    {TK_CONFIG_RELIEF, "-relief", "relief", "Relief",
	DEF_SCROLLBAR_RELIEF, Tk_Offset(TkScrollbar, relief), 0, NULL},
	DEF_SCROLLBAR_RELIEF, offsetof(TkScrollbar, relief), 0, NULL},
    {TK_CONFIG_INT, "-repeatdelay", "repeatDelay", "RepeatDelay",
	DEF_SCROLLBAR_REPEAT_DELAY, Tk_Offset(TkScrollbar, repeatDelay), 0, NULL},
	DEF_SCROLLBAR_REPEAT_DELAY, offsetof(TkScrollbar, repeatDelay), 0, NULL},
    {TK_CONFIG_INT, "-repeatinterval", "repeatInterval", "RepeatInterval",
	DEF_SCROLLBAR_REPEAT_INTERVAL, Tk_Offset(TkScrollbar, repeatInterval), 0, NULL},
	DEF_SCROLLBAR_REPEAT_INTERVAL, offsetof(TkScrollbar, repeatInterval), 0, NULL},
    {TK_CONFIG_STRING, "-takefocus", "takeFocus", "TakeFocus",
	DEF_SCROLLBAR_TAKE_FOCUS, Tk_Offset(TkScrollbar, takeFocus),
	DEF_SCROLLBAR_TAKE_FOCUS, offsetof(TkScrollbar, takeFocus),
	TK_CONFIG_NULL_OK, NULL},
    {TK_CONFIG_COLOR, "-troughcolor", "troughColor", "Background",
	DEF_SCROLLBAR_TROUGH_COLOR, Tk_Offset(TkScrollbar, troughColorPtr),
	DEF_SCROLLBAR_TROUGH_COLOR, offsetof(TkScrollbar, troughColorPtr),
	TK_CONFIG_COLOR_ONLY, NULL},
    {TK_CONFIG_COLOR, "-troughcolor", "troughColor", "Background",
	DEF_SCROLLBAR_TROUGH_MONO, Tk_Offset(TkScrollbar, troughColorPtr),
	DEF_SCROLLBAR_TROUGH_MONO, offsetof(TkScrollbar, troughColorPtr),
	TK_CONFIG_MONO_ONLY, NULL},
    {TK_CONFIG_PIXELS, "-width", "width", "Width",
	tkDefScrollbarWidth, Tk_Offset(TkScrollbar, width), 0, NULL},
	tkDefScrollbarWidth, offsetof(TkScrollbar, width), 0, NULL},
    {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL}
};

/*
 * Forward declarations for functions defined later in this file:
 */

123
124
125
126
127
128
129
130
131


132
133
134
135
136
137
138
123
124
125
126
127
128
129


130
131
132
133
134
135
136
137
138







-
-
+
+







int
Tk_ScrollbarObjCmd(
    ClientData clientData,	/* Main window associated with interpreter. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])		/* Argument strings. */
{
    Tk_Window tkwin = clientData;
    register TkScrollbar *scrollPtr;
    Tk_Window tkwin = (Tk_Window)clientData;
    TkScrollbar *scrollPtr;
    Tk_Window newWin;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "pathName ?-option value ...?");
	return TCL_ERROR;
    }

175
176
177
178
179
180
181

182
183
184
185

186
187
188
189
190
191
192
193
194
195
196
197

198
199
200
201
202
203
204
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198

199
200
201
202
203
204
205
206







+




+











-
+







    scrollPtr->inset = 0;
    scrollPtr->elementBorderWidth = -1;
    scrollPtr->arrowLength = 0;
    scrollPtr->sliderFirst = 0;
    scrollPtr->sliderLast = 0;
    scrollPtr->activeField = 0;
    scrollPtr->activeRelief = TK_RELIEF_RAISED;
#ifndef TK_NO_DEPRECATED
    scrollPtr->totalUnits = 0;
    scrollPtr->windowUnits = 0;
    scrollPtr->firstUnit = 0;
    scrollPtr->lastUnit = 0;
#endif /* TK_NO_DEPRECATED */
    scrollPtr->firstFraction = 0.0;
    scrollPtr->lastFraction = 0.0;
    scrollPtr->cursor = NULL;
    scrollPtr->takeFocus = NULL;
    scrollPtr->flags = 0;

    if (ConfigureScrollbar(interp, scrollPtr, objc-2, objv+2, 0) != TCL_OK) {
	Tk_DestroyWindow(scrollPtr->tkwin);
	return TCL_ERROR;
    }

    Tcl_SetObjResult(interp, TkNewWindowObj(scrollPtr->tkwin));
    Tcl_SetObjResult(interp, Tk_NewWindowObj(scrollPtr->tkwin));
    return TCL_OK;
}

/*
 *--------------------------------------------------------------
 *
 * ScrollbarWidgetObjCmd --
219
220
221
222
223
224
225
226
227
228



229
230
231
232
233
234
235
221
222
223
224
225
226
227



228
229
230
231
232
233
234
235
236
237







-
-
-
+
+
+







static int
ScrollbarWidgetObjCmd(
    ClientData clientData,	/* Information about scrollbar widget. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])		/* Argument strings. */
{
    register TkScrollbar *scrollPtr = clientData;
    int result = TCL_OK;
    int length, cmdIndex;
    TkScrollbar *scrollPtr = (TkScrollbar *)clientData;
    int result = TCL_OK, cmdIndex, length;
    TkSizeT len;
    static const char *const commandNames[] = {
        "activate", "cget", "configure", "delta", "fraction",
        "get", "identify", "set", NULL
    };
    enum command {
        COMMAND_ACTIVATE, COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_DELTA,
        COMMAND_FRACTION, COMMAND_GET, COMMAND_IDENTIFY, COMMAND_SET
265
266
267
268
269
270
271
272

273
274
275
276
277
278

279
280
281
282
283
284
285
267
268
269
270
271
272
273

274
275
276
277
278
279

280
281
282
283
284
285
286
287







-
+





-
+







	    Tcl_SetObjResult(interp, Tcl_NewStringObj(zone, -1));
	    goto done;
	}
	if (objc != 3) {
		Tcl_WrongNumArgs(interp, 1, objv, "activate element");
	    goto error;
	}
	c = Tcl_GetStringFromObj(objv[2], &length)[0];
	c = TkGetStringFromObj(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;
	} else if ((c == 's') && (strncmp(Tcl_GetString(objv[2]), "slider", length) == 0)) {
	} else if ((c == 's') && (strncmp(Tcl_GetString(objv[2]), "slider", len) == 0)) {
	    scrollPtr->activeField = SLIDER;
	} else {
	    scrollPtr->activeField = OUTSIDE;
	}
	if (oldActiveField != scrollPtr->activeField) {
	    TkScrollbarEventuallyRedraw(scrollPtr);
	}
304
305
306
307
308
309
310
311

312
313
314
315
316
317
318
306
307
308
309
310
311
312

313
314
315
316
317
318
319
320







-
+







	} else {
	    result = ConfigureScrollbar(interp, scrollPtr, objc-2,
		    objv+2, TK_CONFIG_ARGV_ONLY);
	}
	break;
    }
    case COMMAND_DELTA: {
	int xDelta, yDelta, pixels, length;
	int xDelta, yDelta, pixels;
	double fraction;

	if (objc != 4) {
		Tcl_WrongNumArgs(interp, 1, objv, "delta xDelta yDelta");
	    goto error;
	}
	if ((Tcl_GetIntFromObj(interp, objv[2], &xDelta) != TCL_OK)
333
334
335
336
337
338
339
340

341
342
343
344
345
346
347
335
336
337
338
339
340
341

342
343
344
345
346
347
348
349







-
+







	} else {
	    fraction = ((double) pixels / (double) length);
	}
	Tcl_SetObjResult(interp, Tcl_NewDoubleObj(fraction));
	break;
    }
    case COMMAND_FRACTION: {
	int x, y, pos, length;
	int x, y, pos;
	double fraction;

	if (objc != 4) {
		Tcl_WrongNumArgs(interp, 1, objv, "fraction x y");
	    goto error;
	}
	if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK)
373
374
375
376
377
378
379

380

381
382
383
384
385
386
387
388




389

390




391
392
393
394
395
396
397
375
376
377
378
379
380
381
382

383








384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401







+
-
+
-
-
-
-
-
-
-
-
+
+
+
+

+

+
+
+
+







    case COMMAND_GET: {
	Tcl_Obj *resObjs[4];

	if (objc != 2) {
		Tcl_WrongNumArgs(interp, 1, objv, "get");
	    goto error;
	}
#ifndef TK_NO_DEPRECATED
	if (scrollPtr->flags & NEW_STYLE_COMMANDS) {
	if (scrollPtr->flags & OLD_STYLE_COMMANDS) {
	    resObjs[0] = Tcl_NewDoubleObj(scrollPtr->firstFraction);
	    resObjs[1] = Tcl_NewDoubleObj(scrollPtr->lastFraction);
	    Tcl_SetObjResult(interp, Tcl_NewListObj(2, resObjs));
	} else {
	    resObjs[0] = Tcl_NewIntObj(scrollPtr->totalUnits);
	    resObjs[1] = Tcl_NewIntObj(scrollPtr->windowUnits);
	    resObjs[2] = Tcl_NewIntObj(scrollPtr->firstUnit);
	    resObjs[3] = Tcl_NewIntObj(scrollPtr->lastUnit);
	    resObjs[0] = Tcl_NewWideIntObj(scrollPtr->totalUnits);
	    resObjs[1] = Tcl_NewWideIntObj(scrollPtr->windowUnits);
	    resObjs[2] = Tcl_NewWideIntObj(scrollPtr->firstUnit);
	    resObjs[3] = Tcl_NewWideIntObj(scrollPtr->lastUnit);
	    Tcl_SetObjResult(interp, Tcl_NewListObj(4, resObjs));
	    break;
	}
#endif /* TK_NO_DEPRECATED */
	resObjs[0] = Tcl_NewDoubleObj(scrollPtr->firstFraction);
	resObjs[1] = Tcl_NewDoubleObj(scrollPtr->lastFraction);
	Tcl_SetObjResult(interp, Tcl_NewListObj(2, resObjs));
	break;
    }
    case COMMAND_IDENTIFY: {
	int x, y;
	const char *zone = "";

	if (objc != 4) {
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
413
414
415
416
417
418
419


420
421
422
423
424
425
426







-
-







	case BOTTOM_GAP:	zone = "trough2"; break;
	case BOTTOM_ARROW:	zone = "arrow2";  break;
	}
	Tcl_SetObjResult(interp, Tcl_NewStringObj(zone, -1));
	break;
    }
    case COMMAND_SET: {
	int totalUnits, windowUnits, firstUnit, lastUnit;

	if (objc == 4) {
	    double first, last;

	    if (Tcl_GetDoubleFromObj(interp, objv[2], &first) != TCL_OK) {
		goto error;
	    }
	    if (Tcl_GetDoubleFromObj(interp, objv[3], &last) != TCL_OK) {
434
435
436
437
438
439
440

441

442

443
444
445
446
447
448
449
436
437
438
439
440
441
442
443

444
445
446
447
448
449
450
451
452
453







+
-
+

+







	    if (last < scrollPtr->firstFraction) {
		scrollPtr->lastFraction = scrollPtr->firstFraction;
	    } else if (last > 1.0) {
		scrollPtr->lastFraction = 1.0;
	    } else {
		scrollPtr->lastFraction = last;
	    }
#ifndef TK_NO_DEPRECATED
	    scrollPtr->flags |= NEW_STYLE_COMMANDS;
	    scrollPtr->flags &= ~OLD_STYLE_COMMANDS;
	} else if (objc == 6) {
	    int totalUnits, windowUnits, firstUnit, lastUnit;
	    if (Tcl_GetIntFromObj(interp, objv[2], &totalUnits) != TCL_OK) {
		goto error;
	    }
	    if (totalUnits < 0) {
		totalUnits = 0;
	    }
	    if (Tcl_GetIntFromObj(interp, objv[3], &windowUnits) != TCL_OK) {
472
473
474
475
476
477
478
479


480
481
482
483
484
485
486
487
488
489
490
476
477
478
479
480
481
482

483
484
485
486


487
488
489
490
491
492
493







-
+
+


-
-







	    if (scrollPtr->totalUnits == 0) {
		scrollPtr->firstFraction = 0.0;
		scrollPtr->lastFraction = 1.0;
	    } else {
		scrollPtr->firstFraction = ((double) firstUnit)/totalUnits;
		scrollPtr->lastFraction = ((double) (lastUnit+1))/totalUnits;
	    }
	    scrollPtr->flags &= ~NEW_STYLE_COMMANDS;
	    scrollPtr->flags |= OLD_STYLE_COMMANDS;
#endif /* !TK_NO_DEPRECATED */
	} else {
		Tcl_WrongNumArgs(interp, 1, objv, "set firstFraction lastFraction");
		Tcl_AppendResult(interp, " or \"", Tcl_GetString(objv[0]),
			" set totalUnits windowUnits firstUnit lastUnit\"", NULL);
	    goto error;
	}
	TkpComputeScrollbarGeometry(scrollPtr);
	TkScrollbarEventuallyRedraw(scrollPtr);
	break;
    }
    }
517
518
519
520
521
522
523
524

525
526
527
528
529
530
531
520
521
522
523
524
525
526

527
528
529
530
531
532
533
534







-
+







 *
 *----------------------------------------------------------------------
 */

static int
ConfigureScrollbar(
    Tcl_Interp *interp,		/* Used for error reporting. */
    register TkScrollbar *scrollPtr,
    TkScrollbar *scrollPtr,
				/* Information about widget; may or may not
				 * already have values for some fields. */
    int objc,			/* Number of valid entries in argv. */
    Tcl_Obj *const objv[],		/* Arguments. */
    int flags)			/* Flags to pass to Tk_ConfigureWidget. */
{
    if (Tk_ConfigureWidget(interp, scrollPtr->tkwin, configSpecs, objc,
580
581
582
583
584
585
586
587

588
589
590
591
592
593
594
583
584
585
586
587
588
589

590
591
592
593
594
595
596
597







-
+







 */

void
TkScrollbarEventProc(
    ClientData clientData,	/* Information about window. */
    XEvent *eventPtr)		/* Information about event. */
{
    TkScrollbar *scrollPtr = clientData;
    TkScrollbar *scrollPtr = (TkScrollbar *)clientData;

    if ((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0)) {
	TkScrollbarEventuallyRedraw(scrollPtr);
    } else if (eventPtr->type == DestroyNotify) {
	TkpDestroyScrollbar(scrollPtr);
	if (scrollPtr->tkwin != NULL) {
	    scrollPtr->tkwin = NULL;
645
646
647
648
649
650
651
652

653
654
655
656
657
658
659
648
649
650
651
652
653
654

655
656
657
658
659
660
661
662







-
+







 *----------------------------------------------------------------------
 */

static void
ScrollbarCmdDeletedProc(
    ClientData clientData)	/* Pointer to widget record for widget. */
{
    TkScrollbar *scrollPtr = clientData;
    TkScrollbar *scrollPtr = (TkScrollbar *)clientData;
    Tk_Window tkwin = scrollPtr->tkwin;

    /*
     * This function could be invoked either because the window was destroyed
     * and the command was then deleted (in which case tkwin is NULL) or
     * because the command was deleted, and then this function destroys the
     * widget.
Changes to generic/tkScrollbar.h.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







/*
 * 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.
 */

#ifndef _TKSCROLLBAR
#define _TKSCROLLBAR
89
90
91
92
93
94
95
96

97
98

99
100
101


102
103
104

105
106
107

108
109

110



111
112
113
114
115
116
117
89
90
91
92
93
94
95

96
97
98
99
100


101
102
103
104

105
106
107

108
109

110
111
112
113
114
115
116
117
118
119
120
121







-
+


+

-
-
+
+


-
+


-
+

-
+

+
+
+







    /*
     * Information describing the application related to the scrollbar. This
     * information is provided by the application by invoking the "set" widget
     * command. This information can now be provided in two ways: the "old"
     * form (totalUnits, windowUnits, firstUnit, and lastUnit), or the "new"
     * form (firstFraction and lastFraction). FirstFraction and lastFraction
     * will always be valid, but the old-style information is only valid if
     * the NEW_STYLE_COMMANDS flag is 0.
     * the OLD_STYLE_COMMANDS flag is 1.
     */

#ifndef TK_NO_DEPRECATED
    int totalUnits;		/* Total dimension of application, in units.
				 * Valid only if the NEW_STYLE_COMMANDS flag
				 * isn't set. */
				 * Valid only if the OLD_STYLE_COMMANDS flag
				 * is set. */
    int windowUnits;		/* Maximum number of units that can be
				 * displayed in the window at once. Valid only
				 * if the NEW_STYLE_COMMANDS flag isn't set. */
				 * if the OLD_STYLE_COMMANDS flag is set. */
    int firstUnit;		/* Number of last unit visible in
				 * application's window. Valid only if the
				 * NEW_STYLE_COMMANDS flag isn't set. */
				 * OLD_STYLE_COMMANDS flag is set. */
    int lastUnit;		/* Index of last unit visible in window.
				 * Valid only if the NEW_STYLE_COMMANDS flag
				 * Valid only if the OLD_STYLE_COMMANDS flag
				 * isn't set. */
#else
    int dummy1,dummy2,dummy3,dummy4; /* sizeof(TkScrollbar) should not depend on TK_NO_DEPRECATED */
#endif /* TK_NO_DEPRECATED */
    double firstFraction;	/* Position of first visible thing in window,
				 * specified as a fraction between 0 and
				 * 1.0. */
    double lastFraction;	/* Position of last visible thing in window,
				 * specified as a fraction between 0 and
				 * 1.0. */

140
141
142
143
144
145
146
147

148

149

150
151
152
153
154
155

156


157
158
159
160
161
162
163
144
145
146
147
148
149
150

151
152
153

154

155
156
157
158
159
160

161
162
163
164
165
166
167
168
169







-
+

+
-
+
-





+
-
+
+







#define BOTTOM_ARROW	5

/*
 * Flag bits for scrollbars:
 *
 * REDRAW_PENDING:		Non-zero means a DoWhenIdle handler has
 *				already been queued to redraw this window.
 * NEW_STYLE_COMMANDS:		Non-zero means the new style of commands
 * OLD_STYLE_COMMANDS:		Non-zero means the old style of commands
 *				should be used to communicate with the widget:
 *				".t yview 40", instead of
 *				".t yview scroll 2 lines", instead of
 *				".t yview scroll 2 lines", for example.
 *				".t yview 40", for example.
 * GOT_FOCUS:			Non-zero means this window has the input
 *				focus.
 */

#define REDRAW_PENDING		1
#ifndef TK_NO_DEPRECATED
#define NEW_STYLE_COMMANDS	2
#   define OLD_STYLE_COMMANDS	2
#endif /* TK_NO_DEPRECATED */
#define GOT_FOCUS		4

/*
 * Declaration of scrollbar class functions structure
 * and default scrollbar width, for use in configSpec.
 */

Changes to generic/tkSelect.c.
1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

30
31

32
33
34
35
36
37
38
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

29
30

31
32
33
34
35
36
37
38






-
-
+
+




















-
+

-
+







/*
 * 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.
 */

#include "tkInt.h"
#include "tkSelect.h"

/*
 * When a selection handler is set up by invoking "selection handle", one of
 * the following data structures is set up to hold information about the
 * command to invoke and its interpreter.
 */

typedef struct {
    Tcl_Interp *interp;		/* Interpreter in which to invoke command. */
    int cmdLength;		/* # of non-NULL bytes in command. */
    int charOffset;		/* The offset of the next char to retrieve. */
    int byteOffset;		/* The expected byte offset of the next
				 * chunk. */
    char buffer[4];	/* A buffer to hold part of a UTF character
    char buffer[4];		/* A buffer to hold part of a UTF character
				 * that is split across chunks. */
    char command[1];		/* Command to invoke. Actual space is
    char command[TKFLEXARRAY];		/* Command to invoke. Actual space is
				 * allocated as large as necessary. This must
				 * be the last entry in the structure. */
} CommandInfo;

/*
 * When selection ownership is claimed with the "selection own" Tcl command,
 * one of the following structures is created to record the Tcl command to be
55
56
57
58
59
60
61
62
63


64
65
66
67
68
69
70
55
56
57
58
59
60
61


62
63
64
65
66
67
68
69
70







-
-
+
+







} ThreadSpecificData;
static Tcl_ThreadDataKey dataKey;

/*
 * Forward declarations for functions defined in this file:
 */

static int		HandleTclCommand(ClientData clientData,
			    int offset, char *buffer, int maxBytes);
static TkSizeT	HandleTclCommand(ClientData clientData,
			    TkSizeT offset, char *buffer, TkSizeT maxBytes);
static void		LostSelection(ClientData clientData);
static int		SelGetProc(ClientData clientData,
			    Tcl_Interp *interp, const char *portion);

/*
 *--------------------------------------------------------------
 *
121
122
123
124
125
126
127
128

129
130
131
132
133
134
135
136
137
138
139
140
141
142

143
144
145
146
147
148
149
121
122
123
124
125
126
127

128
129
130
131
132
133
134
135
136
137
138
139
140
141

142
143
144
145
146
147
148
149







-
+













-
+







    ClientData clientData,	/* Value to pass to proc. */
    Atom format)		/* Format in which the selection information
				 * should be returned to the requestor.
				 * XA_STRING is best by far, but anything
				 * listed in the ICCCM will be tolerated
				 * (blech). */
{
    register TkSelHandler *selPtr;
    TkSelHandler *selPtr;
    TkWindow *winPtr = (TkWindow *) tkwin;

    if (winPtr->dispPtr->multipleAtom == None) {
	TkSelInit(tkwin);
    }

    /*
     * See if there's already a handler for this target and selection on this
     * window. If so, re-use it. If not, create a new one.
     */

    for (selPtr = winPtr->selHandlerList; ; selPtr = selPtr->nextPtr) {
	if (selPtr == NULL) {
	    selPtr = ckalloc(sizeof(TkSelHandler));
	    selPtr = (TkSelHandler *)ckalloc(sizeof(TkSelHandler));
	    selPtr->nextPtr = winPtr->selHandlerList;
	    winPtr->selHandlerList = selPtr;
	    break;
	}
	if ((selPtr->selection == selection) && (selPtr->target == target)) {
	    /*
	     * Special case: when replacing handler created by "selection
173
174
175
176
177
178
179
180

181
182
183
184
185
186
187
188
189
190
191
192
193

194
195
196
197
198
199
200
173
174
175
176
177
178
179

180
181
182
183
184
185
186
187
188
189
190
191
192

193
194
195
196
197
198
199
200







-
+












-
+







	 * If the user asked for a STRING handler and we understand
	 * UTF8_STRING, we implicitly create a UTF8_STRING handler for them.
	 */

	target = winPtr->dispPtr->utf8Atom;
	for (selPtr = winPtr->selHandlerList; ; selPtr = selPtr->nextPtr) {
	    if (selPtr == NULL) {
		selPtr = ckalloc(sizeof(TkSelHandler));
		selPtr = (TkSelHandler *)ckalloc(sizeof(TkSelHandler));
		selPtr->nextPtr = winPtr->selHandlerList;
		winPtr->selHandlerList = selPtr;
		selPtr->selection = selection;
		selPtr->target = target;
		selPtr->format = target; /* We want UTF8_STRING format */
		selPtr->proc = proc;
		if (selPtr->proc == HandleTclCommand) {
		    /*
		     * The clientData is selection controlled memory, so we
		     * should make a copy for this selPtr.
		     */

		    unsigned cmdInfoLen = Tk_Offset(CommandInfo, command) + 1 +
		    size_t cmdInfoLen = offsetof(CommandInfo, command) + 1 +
			    ((CommandInfo *)clientData)->cmdLength;

		    selPtr->clientData = ckalloc(cmdInfoLen);
		    memcpy(selPtr->clientData, clientData, cmdInfoLen);
		} else {
		    selPtr->clientData = clientData;
		}
235
236
237
238
239
240
241
242
243
244



245
246
247
248
249
250
251
235
236
237
238
239
240
241



242
243
244
245
246
247
248
249
250
251







-
-
-
+
+
+







    Tk_Window tkwin,		/* Token for window. */
    Atom selection,		/* The selection whose handler is to be
				 * removed. */
    Atom target)		/* The target whose selection handler is to be
				 * removed. */
{
    TkWindow *winPtr = (TkWindow *) tkwin;
    register TkSelHandler *selPtr, *prevPtr;
    register TkSelInProgress *ipPtr;
    ThreadSpecificData *tsdPtr =
    TkSelHandler *selPtr, *prevPtr;
    TkSelInProgress *ipPtr;
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    /*
     * Find the selection handler to be deleted, or return if it doesn't
     * exist.
     */

349
350
351
352
353
354
355
356

357
358
359
360

361
362
363
364
365
366
367
349
350
351
352
353
354
355

356
357
358
359

360
361
362
363
364
365
366
367







-
+



-
+







    Tk_Window tkwin,		/* Window to become new selection owner. */
    Atom selection,		/* Selection that window should own. */
    Tk_LostSelProc *proc,	/* Function to call when selection is taken
				 * away from tkwin. */
    ClientData clientData)	/* Arbitrary one-word argument to pass to
				 * proc. */
{
    register TkWindow *winPtr = (TkWindow *) tkwin;
    TkWindow *winPtr = (TkWindow *) tkwin;
    TkDisplay *dispPtr = winPtr->dispPtr;
    TkSelectionInfo *infoPtr;
    Tk_LostSelProc *clearProc = NULL;
    ClientData clearData = NULL;/* Initialization needed only to prevent
    void *clearData = NULL;/* Initialization needed only to prevent
				 * compiler warning. */

    if (dispPtr->multipleAtom == None) {
	TkSelInit(tkwin);
    }
    Tk_MakeWindowExist(tkwin);

378
379
380
381
382
383
384
385

386
387
388
389
390
391
392
378
379
380
381
382
383
384

385
386
387
388
389
390
391
392







-
+







    for (infoPtr = dispPtr->selectionInfoPtr; infoPtr != NULL;
	    infoPtr = infoPtr->nextPtr) {
	if (infoPtr->selection == selection) {
	    break;
	}
    }
    if (infoPtr == NULL) {
	infoPtr = ckalloc(sizeof(TkSelectionInfo));
	infoPtr = (TkSelectionInfo *)ckalloc(sizeof(TkSelectionInfo));
	infoPtr->selection = selection;
	infoPtr->nextPtr = dispPtr->selectionInfoPtr;
	dispPtr->selectionInfoPtr = infoPtr;
    } else if (infoPtr->clearProc != NULL) {
	if (infoPtr->owner != tkwin) {
	    clearProc = infoPtr->clearProc;
	    clearData = infoPtr->clearData;
456
457
458
459
460
461
462
463

464
465
466
467
468
469

470
471
472
473
474
475
476
456
457
458
459
460
461
462

463
464
465
466
467
468

469
470
471
472
473
474
475
476







-
+





-
+







 */

void
Tk_ClearSelection(
    Tk_Window tkwin,		/* Window that selects a display. */
    Atom selection)		/* Selection to be cancelled. */
{
    register TkWindow *winPtr = (TkWindow *) tkwin;
    TkWindow *winPtr = (TkWindow *) tkwin;
    TkDisplay *dispPtr = winPtr->dispPtr;
    TkSelectionInfo *infoPtr;
    TkSelectionInfo *prevPtr;
    TkSelectionInfo *nextPtr;
    Tk_LostSelProc *clearProc = NULL;
    ClientData clearData = NULL;/* Initialization needed only to prevent
    void *clearData = NULL;/* Initialization needed only to prevent
				 * compiler warning. */

    if (dispPtr->multipleAtom == None) {
	TkSelInit(tkwin);
    }

    for (infoPtr = dispPtr->selectionInfoPtr, prevPtr = NULL;
552
553
554
555
556
557
558
559

560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580

581
582
583
584
585
586
587
552
553
554
555
556
557
558

559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579

580
581
582
583
584
585
586
587







-
+




















-
+







    Tk_GetSelProc *proc,	/* Function to call to process the selection,
				 * once it has been retrieved. */
    ClientData clientData)	/* Arbitrary value to pass to proc. */
{
    TkWindow *winPtr = (TkWindow *) tkwin;
    TkDisplay *dispPtr = winPtr->dispPtr;
    TkSelectionInfo *infoPtr;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (dispPtr->multipleAtom == None) {
	TkSelInit(tkwin);
    }

    /*
     * If the selection is owned by a window managed by this process, then
     * call the retrieval function directly, rather than going through the X
     * server (it's dangerous to go through the X server in this case because
     * it could result in deadlock if an INCR-style selection results).
     */

    for (infoPtr = dispPtr->selectionInfoPtr; infoPtr != NULL;
	    infoPtr = infoPtr->nextPtr) {
	if (infoPtr->selection == selection) {
	    break;
	}
    }
    if (infoPtr != NULL) {
	register TkSelHandler *selPtr;
	TkSelHandler *selPtr;
	int offset, result, count;
	char buffer[TK_SEL_BYTES_AT_ONCE+1];
	TkSelInProgress ip;

	for (selPtr = ((TkWindow *) infoPtr->owner)->selHandlerList;
		selPtr != NULL; selPtr = selPtr->nextPtr) {
	    if (selPtr->target==target && selPtr->selection==selection) {
666
667
668
669
670
671
672
673

674
675
676
677
678
679
680
666
667
668
669
670
671
672

673
674
675
676
677
678
679
680







-
+







Tk_SelectionObjCmd(
    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;
    const char *path = NULL;
    Atom selection;
    const char *selName = NULL;
    const char *string;
    int count, index;
    Tcl_Obj **objs;
    static const char *const optionStrings[] = {
826
827
828
829
830
831
832
833
834


835
836
837
838
839
840
841
826
827
828
829
830
831
832


833
834
835
836
837
838
839
840
841







-
-
+
+







	return result;
    }

    case SELECTION_HANDLE: {
	Atom target, format;
	const char *targetName = NULL;
	const char *formatName = NULL;
	register CommandInfo *cmdInfoPtr;
	int cmdLength;
	CommandInfo *cmdInfoPtr;
	TkSizeT cmdLength;
	static const char *const handleOptionStrings[] = {
	    "-format", "-selection", "-type", NULL
	};
	enum handleOptions {
	    HANDLE_FORMAT, HANDLE_SELECTION, HANDLE_TYPE
	};
	int handleIndex;
896
897
898
899
900
901
902
903

904
905
906
907

908
909
910
911
912
913
914
915
916
917
918
919
920
921
922

923
924
925
926
927
928
929
896
897
898
899
900
901
902

903
904
905
906

907
908
909
910
911
912
913
914
915
916
917
918
919
920
921

922
923
924
925
926
927
928
929







-
+



-
+














-
+







	if (count > 3) {
	    format = Tk_InternAtom(tkwin, Tcl_GetString(objs[3]));
	} else if (formatName != NULL) {
	    format = Tk_InternAtom(tkwin, formatName);
	} else {
	    format = XA_STRING;
	}
	string = Tcl_GetStringFromObj(objs[1], &cmdLength);
	string = TkGetStringFromObj(objs[1], &cmdLength);
	if (cmdLength == 0) {
	    Tk_DeleteSelHandler(tkwin, selection, target);
	} else {
	    cmdInfoPtr = ckalloc(Tk_Offset(CommandInfo, command)
	    cmdInfoPtr = (CommandInfo *)ckalloc(offsetof(CommandInfo, command)
		    + 1 + cmdLength);
	    cmdInfoPtr->interp = interp;
	    cmdInfoPtr->charOffset = 0;
	    cmdInfoPtr->byteOffset = 0;
	    cmdInfoPtr->buffer[0] = '\0';
	    cmdInfoPtr->cmdLength = cmdLength;
	    memcpy(cmdInfoPtr->command, string, cmdLength + 1);
	    Tk_CreateSelHandler(tkwin, selection, target, HandleTclCommand,
		    cmdInfoPtr, format);
	}
	return TCL_OK;
    }

    case SELECTION_OWN: {
	register LostCommand *lostPtr;
	LostCommand *lostPtr;
	Tcl_Obj *commandObj = NULL;
	static const char *const ownOptionStrings[] = {
	    "-command", "-displayof", "-selection", NULL
	};
	enum ownOptions { OWN_COMMAND, OWN_DISPLAYOF, OWN_SELECTION };
	int ownIndex;

988
989
990
991
992
993
994
995

996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011

1012
1013
1014
1015
1016
1017
1018
988
989
990
991
992
993
994

995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010

1011
1012
1013
1014
1015
1016
1017
1018







-
+















-
+








	    /*
	     * Ignore the internal clipboard window.
	     */

	    if ((infoPtr != NULL)
		    && (infoPtr->owner != winPtr->dispPtr->clipWindow)) {
		Tcl_SetObjResult(interp, TkNewWindowObj(infoPtr->owner));
		Tcl_SetObjResult(interp, Tk_NewWindowObj(infoPtr->owner));
	    }
	    return TCL_OK;
	}

	tkwin = Tk_NameToWindow(interp, Tcl_GetString(objs[0]), tkwin);
	if (tkwin == NULL) {
	    return TCL_ERROR;
	}
	if (count == 2) {
	    commandObj = objs[1];
	}
	if (commandObj == NULL) {
	    Tk_OwnSelection(tkwin, selection, NULL, NULL);
	    return TCL_OK;
	}
	lostPtr = ckalloc(sizeof(LostCommand));
	lostPtr = (LostCommand *)ckalloc(sizeof(LostCommand));
	lostPtr->interp = interp;
	lostPtr->cmdObj = commandObj;
	Tcl_IncrRefCount(commandObj);
	Tk_OwnSelection(tkwin, selection, LostSelection, lostPtr);
	return TCL_OK;
    }
    }
1036
1037
1038
1039
1040
1041
1042
1043

1044
1045
1046
1047
1048
1049
1050
1036
1037
1038
1039
1040
1041
1042

1043
1044
1045
1046
1047
1048
1049
1050







-
+







 *
 *----------------------------------------------------------------------
 */

TkSelInProgress *
TkSelGetInProgress(void)
{
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    return tsdPtr->pendingPtr;
}

/*
 *----------------------------------------------------------------------
1063
1064
1065
1066
1067
1068
1069
1070

1071
1072
1073
1074
1075
1076
1077
1063
1064
1065
1066
1067
1068
1069

1070
1071
1072
1073
1074
1075
1076
1077







-
+







 *
 *----------------------------------------------------------------------
 */
void
TkSelSetInProgress(
    TkSelInProgress *pendingPtr)
{
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    tsdPtr->pendingPtr = pendingPtr;
}

/*
 *----------------------------------------------------------------------
1088
1089
1090
1091
1092
1093
1094
1095

1096
1097
1098


1099
1100

1101
1102
1103
1104
1105
1106
1107
1088
1089
1090
1091
1092
1093
1094

1095
1096


1097
1098
1099

1100
1101
1102
1103
1104
1105
1106
1107







-
+

-
-
+
+

-
+







 *	Frees up memory associated with the selection.
 *
 *----------------------------------------------------------------------
 */

void
TkSelDeadWindow(
    register TkWindow *winPtr)	/* Window that's being deleted. */
    TkWindow *winPtr)	/* Window that's being deleted. */
{
    register TkSelHandler *selPtr;
    register TkSelInProgress *ipPtr;
    TkSelHandler *selPtr;
    TkSelInProgress *ipPtr;
    TkSelectionInfo *infoPtr, *prevPtr, *nextPtr;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    /*
     * While deleting all the handlers, be careful to check whether
     * ConvertSelection or TkSelPropProc are about to process one of the
     * deleted handlers.
     */
1166
1167
1168
1169
1170
1171
1172
1173

1174
1175
1176
1177
1178
1179
1180
1166
1167
1168
1169
1170
1171
1172

1173
1174
1175
1176
1177
1178
1179
1180







-
+







 */

void
TkSelInit(
    Tk_Window tkwin)		/* Window token (used to find display to
				 * initialize). */
{
    register TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;

    /*
     * Fetch commonly-used atoms.
     */

    dispPtr->multipleAtom	= Tk_InternAtom(tkwin, "MULTIPLE");
    dispPtr->incrAtom		= Tk_InternAtom(tkwin, "INCR");
1217
1218
1219
1220
1221
1222
1223
1224

1225
1226

1227
1228
1229
1230
1231
1232
1233
1217
1218
1219
1220
1221
1222
1223

1224
1225

1226
1227
1228
1229
1230
1231
1232
1233







-
+

-
+







 *
 *----------------------------------------------------------------------
 */

void
TkSelClearSelection(
    Tk_Window tkwin,		/* Window for which event was targeted. */
    register XEvent *eventPtr)	/* X SelectionClear event. */
    XEvent *eventPtr)	/* X SelectionClear event. */
{
    register TkWindow *winPtr = (TkWindow *) tkwin;
    TkWindow *winPtr = (TkWindow *) tkwin;
    TkDisplay *dispPtr = winPtr->dispPtr;
    TkSelectionInfo *infoPtr;
    TkSelectionInfo *prevPtr;

    /*
     * Invoke clear function for window that just lost the selection. This
     * code is a bit tricky, because any callbacks due to selection changes
1242
1243
1244
1245
1246
1247
1248
1249

1250
1251
1252
1253
1254
1255
1256
1242
1243
1244
1245
1246
1247
1248

1249
1250
1251
1252
1253
1254
1255
1256







-
+







	if (infoPtr->selection == eventPtr->xselectionclear.selection) {
	    break;
	}
	prevPtr = infoPtr;
    }

    if (infoPtr != NULL && (infoPtr->owner == tkwin) &&
	    (eventPtr->xselectionclear.serial >= (unsigned) infoPtr->serial)) {
	    (eventPtr->xselectionclear.serial >= (unsigned long) infoPtr->serial)) {
	if (prevPtr == NULL) {
	    dispPtr->selectionInfoPtr = infoPtr->nextPtr;
	} else {
	    prevPtr->nextPtr = infoPtr->nextPtr;
	}

	/*
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293

1294
1295
1296
1297

1298
1299
1300
1301
1302
1303
1304
1281
1282
1283
1284
1285
1286
1287

1288
1289
1290
1291

1292
1293
1294
1295

1296
1297
1298
1299
1300
1301
1302
1303







-




-
+



-
+







 * Side effects:
 *	Bytes get appended to the dynamic string pointed to by the clientData
 *	argument.
 *
 *--------------------------------------------------------------
 */

	/* ARGSUSED */
static int
SelGetProc(
    ClientData clientData,	/* Dynamic string holding partially assembled
				 * selection. */
    Tcl_Interp *interp,		/* Interpreter used for error reporting (not
    TCL_UNUSED(Tcl_Interp *),	/* Interpreter used for error reporting (not
				 * used). */
    const char *portion)	/* New information to be appended. */
{
    Tcl_DStringAppend(clientData, portion, -1);
    Tcl_DStringAppend((Tcl_DString *)clientData, portion, -1);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * HandleTclCommand --
1314
1315
1316
1317
1318
1319
1320
1321

1322
1323
1324

1325
1326
1327

1328
1329

1330
1331
1332
1333
1334
1335
1336
1313
1314
1315
1316
1317
1318
1319

1320
1321
1322

1323
1324
1325

1326
1327

1328
1329
1330
1331
1332
1333
1334
1335







-
+


-
+


-
+

-
+







 *
 * Side effects:
 *	None except for things done by the Tcl command.
 *
 *----------------------------------------------------------------------
 */

static int
static TkSizeT
HandleTclCommand(
    ClientData clientData,	/* Information about command to execute. */
    int offset,			/* Return selection bytes starting at this
    TkSizeT offset,			/* Return selection bytes starting at this
				 * offset. */
    char *buffer,		/* Place to store converted selection. */
    int maxBytes)		/* Maximum # of bytes to store at buffer. */
    TkSizeT maxBytes)		/* Maximum # of bytes to store at buffer. */
{
    CommandInfo *cmdInfoPtr = clientData;
    CommandInfo *cmdInfoPtr = (CommandInfo *)clientData;
    int length;
    Tcl_Obj *command;
    const char *string;
    Tcl_Interp *interp = cmdInfoPtr->interp;
    Tcl_InterpState savedState;
    int extraBytes, charOffset, count, numChars, code;
    const char *p;
1344
1345
1346
1347
1348
1349
1350
1351

1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372

1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390


1391
1392
1393
1394
1395
1396
1397
1398
1399

1400
1401
1402

1403
1404
1405
1406
1407

1408
1409
1410
1411
1412
1413

1414
1415
1416
1417
1418
1419
1420
1343
1344
1345
1346
1347
1348
1349

1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370

1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387


1388
1389
1390
1391
1392
1393
1394
1395
1396
1397

1398
1399
1400
1401
1402
1403
1404
1405
1406

1407
1408
1409
1410
1411
1412

1413
1414
1415
1416
1417
1418
1419
1420







-
+




















-
+
















-
-
+
+








-
+



+




-
+





-
+







    Tcl_Preserve(interp);

    /*
     * Compute the proper byte offset in the case where the last chunk split a
     * character.
     */

    if (offset == cmdInfoPtr->byteOffset) {
    if ((int)offset == cmdInfoPtr->byteOffset) {
	charOffset = cmdInfoPtr->charOffset;
	extraBytes = strlen(cmdInfoPtr->buffer);
	if (extraBytes > 0) {
	    strcpy(buffer, cmdInfoPtr->buffer);
	    maxBytes -= extraBytes;
	    buffer += extraBytes;
	}
    } else {
	cmdInfoPtr->byteOffset = 0;
	cmdInfoPtr->charOffset = 0;
	extraBytes = 0;
	charOffset = 0;
    }

    /*
     * First, generate a command by taking the command string and appending
     * the offset and maximum # of bytes.
     */

    command = Tcl_ObjPrintf("%s %d %d",
	    cmdInfoPtr->command, charOffset, maxBytes);
	    cmdInfoPtr->command, charOffset, (int)maxBytes);
    Tcl_IncrRefCount(command);

    /*
     * Execute the command. Be sure to restore the state of the interpreter
     * after executing the command.
     */

    savedState = Tcl_SaveInterpState(interp, TCL_OK);
    code = Tcl_EvalObjEx(interp, command, TCL_EVAL_GLOBAL);
    Tcl_DecrRefCount(command);
    if (code == TCL_OK) {
	/*
	 * TODO: This assumes that bytes are characters; that's not true!
	 */

	string = Tcl_GetStringFromObj(Tcl_GetObjResult(interp), &length);
	count = (length > maxBytes) ? maxBytes : length;
	memcpy(buffer, string, (size_t) count);
	count = (length > (int)maxBytes) ? (int)maxBytes : length;
	memcpy(buffer, string, count);
	buffer[count] = '\0';

	/*
	 * Update the partial character information for the next retrieval if
	 * the command has not been deleted.
	 */

	if (cmdInfoPtr->interp != NULL) {
	    if (length <= maxBytes) {
	    if (length <= (int)maxBytes) {
		cmdInfoPtr->charOffset += Tcl_NumUtfChars(string, -1);
		cmdInfoPtr->buffer[0] = '\0';
	    } else {
		int ch;
		p = string;
		string += count;
		numChars = 0;
		while (p < string) {
		    p = Tcl_UtfNext(p);
		    p += TkUtfToUniChar(p, &ch);
		    numChars++;
		}
		cmdInfoPtr->charOffset += numChars;
		length = p - string;
		if (length > 0) {
		    strncpy(cmdInfoPtr->buffer, string, (size_t) length);
		    strncpy(cmdInfoPtr->buffer, string, length);
		}
		cmdInfoPtr->buffer[length] = '\0';
	    }
	    cmdInfoPtr->byteOffset += count + extraBytes;
	}
	count += extraBytes;
    } else {
1465
1466
1467
1468
1469
1470
1471
1472

1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485

1486
1487
1488
1489
1490
1491
1492
1465
1466
1467
1468
1469
1470
1471

1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484

1485
1486
1487
1488
1489
1490
1491
1492







-
+












-
+







    TkSelectionInfo *infoPtr,	/* Info about selection being retrieved. */
    Atom target,		/* Desired form of selection. */
    char *buffer,		/* Place to put selection characters. */
    int maxBytes,		/* Maximum # of bytes to store at buffer. */
    Atom *typePtr)		/* Store here the type of the selection, for
				 * use in converting to proper X format. */
{
    register TkWindow *winPtr = (TkWindow *) infoPtr->owner;
    TkWindow *winPtr = (TkWindow *) infoPtr->owner;
    TkDisplay *dispPtr = winPtr->dispPtr;

    if (target == dispPtr->timestampAtom) {
	if (maxBytes < 20) {
	    return -1;
	}
	sprintf(buffer, "0x%x", (unsigned int) infoPtr->time);
	*typePtr = XA_INTEGER;
	return strlen(buffer);
    }

    if (target == dispPtr->targetsAtom) {
	register TkSelHandler *selPtr;
	TkSelHandler *selPtr;
	int length;
	Tcl_DString ds;

	if (maxBytes < 50) {
	    return -1;
	}
	Tcl_DStringInit(&ds);
1504
1505
1506
1507
1508
1509
1510
1511

1512
1513
1514
1515
1516
1517
1518
1504
1505
1506
1507
1508
1509
1510

1511
1512
1513
1514
1515
1516
1517
1518







-
+







	    }
	}
	length = Tcl_DStringLength(&ds);
	if (length >= maxBytes) {
	    Tcl_DStringFree(&ds);
	    return -1;
	}
	memcpy(buffer, Tcl_DStringValue(&ds), (unsigned) (1+length));
	memcpy(buffer, Tcl_DStringValue(&ds), length + 1);
	Tcl_DStringFree(&ds);
	*typePtr = XA_ATOM;
	return length;
    }

    if (target == dispPtr->applicationAtom) {
	int length;
1561
1562
1563
1564
1565
1566
1567
1568

1569
1570
1571
1572
1573
1574
1575
1561
1562
1563
1564
1565
1566
1567

1568
1569
1570
1571
1572
1573
1574
1575







-
+







 *----------------------------------------------------------------------
 */

static void
LostSelection(
    ClientData clientData)	/* Pointer to LostCommand structure. */
{
    LostCommand *lostPtr = clientData;
    LostCommand *lostPtr = (LostCommand *)clientData;
    Tcl_Interp *interp = lostPtr->interp;
    Tcl_InterpState savedState;
    int code;

    Tcl_Preserve(interp);

    /*
Changes to generic/tkSelect.h.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

28

29
30
31



32
33
34
35

36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56


57
58
59
60
61
62
63
1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

29
30
31
32
33
34
35
36
37
38

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58


59
60
61
62
63
64
65
66
67






-
+




















+
-
+



+
+
+



-
+



















-
-
+
+







/*
 * 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.
 */

#ifndef _TKSELECT
#define _TKSELECT

/*
 * When a selection is owned by a window on a given display, one of the
 * following structures is present on a list of current selections in the
 * display structure. The structure is used to record the current owner of a
 * selection for use in later retrieval requests. There is a list of such
 * structures because a display can have multiple different selections active
 * at the same time.
 */

typedef struct TkSelectionInfo {
    Atom selection;		/* Selection name, e.g. XA_PRIMARY. */
    Tk_Window owner;		/* Current owner of this selection. */
#if TCL_MAJOR_VERSION > 8
    int serial;			/* Serial number of last XSelectionSetOwner
    unsigned long serial;	/* Serial number of last XSelectionSetOwner
				 * request made to server for this selection
				 * (used to filter out redundant
				 * SelectionClear events). */
#else
    int serial;
#endif
    Time time;			/* Timestamp used to acquire selection. */
    Tk_LostSelProc *clearProc;	/* Procedure to call when owner loses
				 * selection. */
    ClientData clearData;	/* Info to pass to clearProc. */
    void *clearData;	/* Info to pass to clearProc. */
    struct TkSelectionInfo *nextPtr;
				/* Next in list of current selections on this
				 * display. NULL means end of list. */
} TkSelectionInfo;

/*
 * One of the following structures exists for each selection handler created
 * for a window by calling Tk_CreateSelHandler. The handlers are linked in a
 * list rooted in the TkWindow structure.
 */

typedef struct TkSelHandler {
    Atom selection;		/* Selection name, e.g. XA_PRIMARY. */
    Atom target;		/* Target type for selection conversion, such
				 * as TARGETS or STRING. */
    Atom format;		/* Format in which selection info will be
				 * returned, such as STRING or ATOM. */
    Tk_SelectionProc *proc;	/* Procedure to generate selection in this
				 * format. */
    ClientData clientData;	/* Argument to pass to proc. */
    int size;			/* Size of units returned by proc (8 for
    void *clientData;	/* Argument to pass to proc. */
    TkSizeT size;			/* Size of units returned by proc (8 for
				 * STRING, 32 for almost anything else). */
    struct TkSelHandler *nextPtr;
				/* Next selection handler associated with same
				 * window (NULL for end of list). */
} TkSelHandler;

/*
99
100
101
102
103
104
105
106

107
108
109
110
111
112
113
103
104
105
106
107
108
109

110
111
112
113
114
115
116
117







-
+







 * CLIPBOARD selection is retrieved. All buffers of a given type on the same
 * clipboard must have the same format. The TkClipboardTarget structure is
 * used to record the information about a chain of buffers of the same type.
 */

typedef struct TkClipboardBuffer {
    char *buffer;		/* Null terminated data buffer. */
    long length;		/* Length of string in buffer. */
    TkSizeT length;		/* Length of string in buffer. */
    struct TkClipboardBuffer *nextPtr;
				/* Next in list of buffers. NULL means end of
				 * list . */
} TkClipboardBuffer;

typedef struct TkClipboardTarget {
    Atom type;			/* Type conversion supported. */
Changes to generic/tkSquare.c.
1
2
3
4
5
6
7
8
9
10

11
12
13
14
15
16
17
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17









-
+







/*
 * tkSquare.c --
 *
 *	This module implements "square" widgets that are object based. A
 *	"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.
 */

#if 0
#define __NO_OLD_CONFIG
62
63
64
65
66
67
68
69

70
71

72
73

74
75
76

77
78
79


80
81
82

83
84
85

86
87

88
89

90
91

92
93
94
95
96
97
98
62
63
64
65
66
67
68

69
70

71
72

73
74
75

76
77


78
79
80
81

82
83
84

85
86

87
88

89
90

91
92
93
94
95
96
97
98







-
+

-
+

-
+


-
+

-
-
+
+


-
+


-
+

-
+

-
+

-
+








/*
 * Information used for argv parsing.
 */

static const Tk_OptionSpec optionSpecs[] = {
    {TK_OPTION_BORDER, "-background", "background", "Background",
	    "#d9d9d9", Tk_Offset(Square, bgBorderPtr), -1, 0,
	    "#d9d9d9", offsetof(Square, bgBorderPtr), TCL_INDEX_NONE, 0,
	    "white", 0},
    {TK_OPTION_SYNONYM, "-bd", NULL, NULL, NULL, 0, -1, 0,
    {TK_OPTION_SYNONYM, "-bd", NULL, NULL, NULL, 0, TCL_INDEX_NONE, 0,
	    "-borderwidth", 0},
    {TK_OPTION_SYNONYM, "-bg", NULL, NULL, NULL, 0, -1, 0,
    {TK_OPTION_SYNONYM, "-bg", NULL, NULL, NULL, 0, TCL_INDEX_NONE, 0,
	    "-background", 0},
    {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
	    "2", Tk_Offset(Square, borderWidthPtr), -1, 0, NULL, 0},
	    "2", offsetof(Square, borderWidthPtr), TCL_INDEX_NONE, 0, NULL, 0},
    {TK_OPTION_BOOLEAN, "-dbl", "doubleBuffer", "DoubleBuffer",
	    "1", Tk_Offset(Square, doubleBufferPtr), -1, 0 , NULL, 0},
    {TK_OPTION_SYNONYM, "-fg", NULL, NULL, NULL, 0, -1, 0,
	    "1", offsetof(Square, doubleBufferPtr), TCL_INDEX_NONE, 0 , NULL, 0},
    {TK_OPTION_SYNONYM, "-fg", NULL, NULL, NULL, 0, TCL_INDEX_NONE, 0,
	    "-foreground", 0},
    {TK_OPTION_BORDER, "-foreground", "foreground", "Foreground",
	    "#b03060", Tk_Offset(Square, fgBorderPtr), -1, 0,
	    "#b03060", offsetof(Square, fgBorderPtr), TCL_INDEX_NONE, 0,
	    "black", 0},
    {TK_OPTION_PIXELS, "-posx", "posx", "PosX", "0",
	    Tk_Offset(Square, xPtr), -1, 0, NULL, 0},
	    offsetof(Square, xPtr), TCL_INDEX_NONE, 0, NULL, 0},
    {TK_OPTION_PIXELS, "-posy", "posy", "PosY", "0",
	    Tk_Offset(Square, yPtr), -1, 0, NULL, 0},
	    offsetof(Square, yPtr), TCL_INDEX_NONE, 0, NULL, 0},
    {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
	    "raised", Tk_Offset(Square, reliefPtr), -1, 0, NULL, 0},
	    "raised", offsetof(Square, reliefPtr), TCL_INDEX_NONE, 0, NULL, 0},
    {TK_OPTION_PIXELS, "-size", "size", "Size", "20",
	    Tk_Offset(Square, sizeObjPtr), -1, 0, NULL, 0},
	    offsetof(Square, sizeObjPtr), TCL_INDEX_NONE, 0, NULL, 0},
    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0}
};

/*
 * Forward declarations for procedures defined later in this file:
 */

121
122
123
124
125
126
127
128

129
130
131
132
133
134
135

136
137
138
139
140
141
142
121
122
123
124
125
126
127

128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143







-
+







+







 *	A new widget is created and configured.
 *
 *--------------------------------------------------------------
 */

int
SquareObjCmd(
    ClientData clientData,	/* NULL. */
    ClientData dummy,	/* NULL. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Square *squarePtr;
    Tk_Window tkwin;
    Tk_OptionTable optionTable;
    (void)dummy;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "pathName ?-option value ...?");
	return TCL_ERROR;
    }

    tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp),
156
157
158
159
160
161
162
163

164
165
166
167
168
169
170
171
172
173
174
175

176
177
178
179
180
181
182
183
184

185
186
187
188
189
190
191
157
158
159
160
161
162
163

164
165
166
167
168
169
170
171
172
173
174
175

176
177
178
179
180
181
182
183
184

185
186
187
188
189
190
191
192







-
+











-
+








-
+







    optionTable = Tk_CreateOptionTable(interp, optionSpecs);

    /*
     * Allocate and initialize the widget record. The memset allows us to set
     * just the non-NULL/0 items.
     */

    squarePtr = ckalloc(sizeof(Square));
    squarePtr = (Square *)ckalloc(sizeof(Square));
    memset(squarePtr, 0, sizeof(Square));

    squarePtr->tkwin = tkwin;
    squarePtr->display = Tk_Display(tkwin);
    squarePtr->interp = interp;
    squarePtr->widgetCmd = Tcl_CreateObjCommand(interp,
	    Tk_PathName(squarePtr->tkwin), SquareWidgetObjCmd, squarePtr,
	    SquareDeletedProc);
    squarePtr->gc = NULL;
    squarePtr->optionTable = optionTable;

    if (Tk_InitOptions(interp, (char *) squarePtr, optionTable, tkwin)
    if (Tk_InitOptions(interp, squarePtr, optionTable, tkwin)
	    != TCL_OK) {
	Tk_DestroyWindow(squarePtr->tkwin);
	ckfree(squarePtr);
	return TCL_ERROR;
    }

    Tk_CreateEventHandler(squarePtr->tkwin, ExposureMask|StructureNotifyMask,
	    SquareObjEventProc, squarePtr);
    if (Tk_SetOptions(interp, (char *) squarePtr, optionTable, objc - 2,
    if (Tk_SetOptions(interp, squarePtr, optionTable, objc - 2,
	    objv + 2, tkwin, NULL, NULL) != TCL_OK) {
	goto error;
    }
    if (SquareConfigure(interp, squarePtr) != TCL_OK) {
	goto error;
    }

219
220
221
222
223
224
225
226

227
228
229
230
231
232
233
234
235
236

237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253

254
255
256
257
258
259
260
261
262
263
264

265
266
267
268
269
270

271
272
273
274
275
276

277
278
279
280
281
282
283
220
221
222
223
224
225
226

227
228
229
230
231
232
233
234
235
236

237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253

254
255
256
257
258
259
260
261
262
263
264

265
266
267
268
269
270

271
272
273
274
275
276

277
278
279
280
281
282
283
284







-
+









-
+
















-
+










-
+





-
+





-
+







static int
SquareWidgetObjCmd(
    ClientData clientData,	/* Information about square widget. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj * const objv[])	/* Argument objects. */
{
    Square *squarePtr = clientData;
    Square *squarePtr = (Square *)clientData;
    int result = TCL_OK;
    static const char *const squareOptions[] = {"cget", "configure", NULL};
    enum {
	SQUARE_CGET, SQUARE_CONFIGURE
    };
    Tcl_Obj *resultObjPtr;
    int index;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg...?");
	Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
	return TCL_ERROR;
    }

    if (Tcl_GetIndexFromObjStruct(interp, objv[1], squareOptions,
	    sizeof(char *), "command", 0, &index) != TCL_OK) {
	return TCL_ERROR;
    }

    Tcl_Preserve(squarePtr);

    switch (index) {
    case SQUARE_CGET:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "option");
	    goto error;
	}
	resultObjPtr = Tk_GetOptionValue(interp, (char *) squarePtr,
	resultObjPtr = Tk_GetOptionValue(interp, squarePtr,
		squarePtr->optionTable, objv[2], squarePtr->tkwin);
	if (resultObjPtr == NULL) {
	    result = TCL_ERROR;
	} else {
	    Tcl_SetObjResult(interp, resultObjPtr);
	}
	break;
    case SQUARE_CONFIGURE:
	resultObjPtr = NULL;
	if (objc == 2) {
	    resultObjPtr = Tk_GetOptionInfo(interp, (char *) squarePtr,
	    resultObjPtr = Tk_GetOptionInfo(interp, squarePtr,
		    squarePtr->optionTable, NULL, squarePtr->tkwin);
	    if (resultObjPtr == NULL) {
		result = TCL_ERROR;
	    }
	} else if (objc == 3) {
	    resultObjPtr = Tk_GetOptionInfo(interp, (char *) squarePtr,
	    resultObjPtr = Tk_GetOptionInfo(interp, squarePtr,
		    squarePtr->optionTable, objv[2], squarePtr->tkwin);
	    if (resultObjPtr == NULL) {
		result = TCL_ERROR;
	    }
	} else {
	    result = Tk_SetOptions(interp, (char *) squarePtr,
	    result = Tk_SetOptions(interp, squarePtr,
		    squarePtr->optionTable, objc - 2, objv + 2,
		    squarePtr->tkwin, NULL, NULL);
	    if (result == TCL_OK) {
		result = SquareConfigure(interp, squarePtr);
	    }
	    if (!squarePtr->updatePending) {
		Tcl_DoWhenIdle(SquareDisplay, squarePtr);
314
315
316
317
318
319
320
321

322
323
324
325
326

327
328
329
330
331
332
333
315
316
317
318
319
320
321

322
323
324
325
326
327
328
329
330
331
332
333
334
335







-
+





+







 *	for squarePtr; old resources get freed, if there were any.
 *
 *----------------------------------------------------------------------
 */

static int
SquareConfigure(
    Tcl_Interp *interp,		/* Used for error reporting. */
    Tcl_Interp *dummy,		/* Used for error reporting. */
    Square *squarePtr)		/* Information about widget. */
{
    int borderWidth;
    Tk_3DBorder bgBorder;
    int doubleBuffer;
    (void)dummy;

    /*
     * Set the background for the window and create a graphics context for use
     * during redisplay.
     */

    bgBorder = Tk_Get3DBorderFromObj(squarePtr->tkwin,
379
380
381
382
383
384
385
386

387
388
389
390
391
392
393
381
382
383
384
385
386
387

388
389
390
391
392
393
394
395







-
+







 */

static void
SquareObjEventProc(
    ClientData clientData,	/* Information about window. */
    XEvent *eventPtr)		/* Information about event. */
{
    Square *squarePtr = clientData;
    Square *squarePtr = (Square *)clientData;

    if (eventPtr->type == Expose) {
	if (!squarePtr->updatePending) {
	    Tcl_DoWhenIdle(SquareDisplay, squarePtr);
	    squarePtr->updatePending = 1;
	}
    } else if (eventPtr->type == ConfigureNotify) {
432
433
434
435
436
437
438
439

440
441
442
443
444
445
446
434
435
436
437
438
439
440

441
442
443
444
445
446
447
448







-
+







 *----------------------------------------------------------------------
 */

static void
SquareDeletedProc(
    ClientData clientData)	/* Pointer to widget record for widget. */
{
    Square *squarePtr = clientData;
    Square *squarePtr = (Square *)clientData;
    Tk_Window tkwin = squarePtr->tkwin;

    /*
     * This procedure could be invoked either because the window was destroyed
     * and the command was then deleted (in which case tkwin is NULL) or
     * because the command was deleted, and then this procedure destroys the
     * widget.
469
470
471
472
473
474
475
476

477
478
479
480
481
482
483
471
472
473
474
475
476
477

478
479
480
481
482
483
484
485







-
+







 *--------------------------------------------------------------
 */

static void
SquareDisplay(
    ClientData clientData)	/* Information about window. */
{
    Square *squarePtr = clientData;
    Square *squarePtr = (Square *)clientData;
    Tk_Window tkwin = squarePtr->tkwin;
    Pixmap pm = None;
    Drawable d;
    int borderWidth, size, relief;
    Tk_3DBorder bgBorder, fgBorder;
    int doubleBuffer;

552
553
554
555
556
557
558
559

560
561
562
563
564
565
566
554
555
556
557
558
559
560

561
562
563
564
565
566
567
568







-
+







 *----------------------------------------------------------------------
 */

static void
SquareDestroy(
    void *memPtr)		/* Info about square widget. */
{
    Square *squarePtr = memPtr;
    Square *squarePtr = (Square *)memPtr;

    ckfree(squarePtr);
}

/*
 *----------------------------------------------------------------------
 *
577
578
579
580
581
582
583
584

585
586
587
588
589
590
591
579
580
581
582
583
584
585

586
587
588
589
590
591
592
593







-
+







 *	the square in the window.
 *
 *----------------------------------------------------------------------
 */

static void
KeepInWindow(
    register Square *squarePtr)	/* Pointer to widget record. */
    Square *squarePtr)	/* Pointer to widget record. */
{
    int i, bd, relief;
    int borderWidth, size;

    Tk_GetPixelsFromObj(NULL, squarePtr->tkwin, squarePtr->borderWidthPtr,
	    &borderWidth);
    Tk_GetPixelsFromObj(NULL, squarePtr->tkwin, squarePtr->xPtr,
Changes to generic/tkStubInit.c.
1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47







48




































































49
50
51
52
53



54
55
56
57
58
59

60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76


77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94



95
96

97
98
99
100
101


102
103
104
105
106
107
108
109
110


111
112
113
114
115
116
117
1
2
3
4
5

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

34
35
36
37
38
39
40







41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143





144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167

168





169
170



171
172
173
174
175
176
177
178
179
180
181
182
183
184
185





-
+




















+






-







-
-
-
-
-
-
-
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





+
+
+






+












-
-
-
-
-
+
+


















+
+
+

-
+
-
-
-
-
-
+
+
-
-
-






+
+







/*
 * 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.
 */

#include "tkInt.h"

#if !(defined(_WIN32) || defined(MAC_OSX_TK))
/* UNIX */
#define UNIX_TK
#include "tkUnixInt.h"
#endif

#ifdef _WIN32
#include "tkWinInt.h"
#endif

#if defined(MAC_OSX_TK)
/* we could have used _TKMACINT */
#include "tkMacOSXInt.h"
#include "tkMacOSXPrivate.h"
#endif

/* TODO: These ought to come in some other way */
#include "tkPlatDecls.h"
#include "tkIntXlibDecls.h"

static const TkIntStubs tkIntStubs;
MODULE_SCOPE const TkStubs tkStubs;

/*
 * Remove macro that might interfere with the definition below.
 */

#undef Tk_MainEx
#undef XVisualIDFromVisual
#undef XSynchronize
#undef XUngrabServer
#undef XNoOp
#undef XGrabServer
#undef XFree
#undef XFlush
#undef Tk_FreeXId
#undef Tk_FreeStyleFromObj
#undef Tk_GetStyleFromObj
#undef TkWinGetPlatformId
#undef TkPutImage
#undef XPutImage
#define TkMacOSXSetUpClippingRgn (void (*)(Drawable))(void *)doNothing

#if defined(_WIN32) && !defined(TK_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9
#   define Tk_TranslateWinEvent TkTranslateWinEvent
#   define Tk_PointerEvent TkWinPointerEvent
#define TkWinGetPlatformId winGetPlatformId
static int TkWinGetPlatformId(void) {
    return 2;
}
#else
#   define Tk_TranslateWinEvent 0
#   define Tk_PointerEvent 0
#   define TkWinGetPlatformId 0
#endif

static int
doNothing(void)
{
    /* dummy implementation, no need to do anything */
    return 0;
}

#if defined(TK_NO_DEPRECATED) || TCL_MAJOR_VERSION > 8
#define Tk_MainEx 0
#define Tk_FreeXId 0
#define Tk_FreeStyleFromObj 0
#define Tk_GetStyleFromObj 0
#define TkWinGetPlatformId 0
#define Tk_PhotoPutBlock_NoComposite 0
#define Tk_PhotoPutZoomedBlock_NoComposite 0
#define Tk_PhotoExpand_Panic 0
#define Tk_PhotoPutBlock_Panic 0
#define Tk_PhotoPutZoomedBlock_Panic 0
#define Tk_PhotoSetSize_Panic 0
#define Tk_CreateOldPhotoImageFormat 0
#else
#define Tk_FreeXId ((void (*)(Display *, XID))(void *)doNothing)
#define Tk_FreeStyleFromObj ((void (*)(Tcl_Obj *))(void *)doNothing)
#define Tk_GetStyleFromObj getStyleFromObj
static Tk_Style Tk_GetStyleFromObj(Tcl_Obj *obj)
{
	return Tk_AllocStyleFromObj(NULL, obj);
}
#endif /* !TK_NO_DEPRECATED */

#define TkpCmapStressed_ TkpCmapStressed
#define TkpSync_ TkpSync
#define TkUnixContainerId_ TkUnixContainerId
#define TkUnixDoOneXEvent_ TkUnixDoOneXEvent
#define TkUnixSetMenubar_ TkUnixSetMenubar
#define TkWmCleanup_ TkWmCleanup
#define TkSendCleanup_ TkSendCleanup
#define TkpTestsendCmd_ TkpTestsendCmd
#define TkGenWMConfigureEvent_ TkGenWMConfigureEvent
#define TkGenerateActivateEvents_ TkGenerateActivateEvents
#define TkMacOSXDrawable Tk_MacOSXGetNSWindowForDrawable
#define Tk_CanvasTagsParseProc \
		(int (*) (void *, Tcl_Interp *,Tk_Window, const char *, char *, \
		int offset))(void *)TkCanvasTagsParseProc
#define Tk_CanvasTagsPrintProc \
		(const char *(*) (void *,Tk_Window, char *, int, \
		Tcl_FreeProc **))(void *)TkCanvasTagsPrintProc

#if !defined(MAC_OSX_TK) && defined(MAC_OSX_TCL)
#   undef TkpWillDrawWidget
#   undef TkpRedrawWidget
#   define TkpWillDrawWidget ((int (*)(Tk_Window))(void *)doNothing)
#   define TkpRedrawWidget ((void (*)(Tk_Window))(void *)doNothing)
#endif

#ifdef _WIN32

int
TkpCmapStressed(Tk_Window tkwin, Colormap colormap)
{
    (void)tkwin;
    (void)colormap;

    /* dummy implementation, no need to do anything */
    return 0;
}
void
TkpSync(Display *display)
{
    (void)display;
    /* dummy implementation, no need to do anything */
}

void
TkCreateXEventSource(void)
{
    TkWinXInit(Tk_GetHINSTANCE());
}

#   define TkUnixContainerId 0
#   define TkUnixDoOneXEvent 0
#   define TkUnixSetMenubar 0
#   define XCreateWindow 0
#   define XOffsetRegion 0
#   define XUnionRegion 0
#   define TkWmCleanup (void (*)(TkDisplay *)) TkpSync
#   define TkSendCleanup (void (*)(TkDisplay *)) TkpSync
#   define TkWmCleanup (void (*)(TkDisplay *))(void *)TkpSync
#   define TkSendCleanup (void (*)(TkDisplay *))(void *)TkpSync
#   define TkpTestsendCmd 0

#else /* !_WIN32 */

/*
 * Make sure that extensions which call XParseColor through the stub
 * table, call TkParseColor instead. [Bug 3486474]
 */
#   define XParseColor	TkParseColor

#   ifdef __CYGWIN__

/*
 * Trick, so we don't have to include <windows.h> here, which in any
 * case lacks this function anyway.
 */

#define GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS	0x00000004
#ifdef __cplusplus
extern "C" {
#endif
int __stdcall GetModuleHandleExW(unsigned int, const char *, void *);

#ifdef __cplusplus
void *Tk_GetHINSTANCE()
{
    void *hInstance = NULL;

    GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
}
#endif
	    (const char *) &tkIntStubs, &hInstance);
    return hInstance;
}

void
TkSetPixmapColormap(
    Pixmap pixmap,
    Colormap colormap)
{
    (void)pixmap;
    (void)colormap;
}

void
TkpPrintWindowId(
    char *buf,			/* Pointer to string large enough to hold
				 * the hex representation of a pointer. */
    Window window)		/* Window to be printed into buffer. */
129
130
131
132
133
134
135
136
137
138

139
140
141
142
143

144
145

146
147
148

149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
197
198
199
200
201
202
203



204





205


206



207




























208
209
210
211
212
213


214

215
216
217
218
219
220
221







-
-
-
+
-
-
-
-
-
+
-
-
+
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-






-
-

-







    GC gc,
    XImage *image,		/* Source image. */
    int src_x, int src_y,	/* Offset of subimage. */
    int dest_x, int dest_y,	/* Position of subimage origin in drawable. */
    unsigned int width, unsigned int height)
				/* Dimensions of subimage. */
{
    return XPutImage(display, d, gc, image, src_x, src_y, dest_x, dest_y, width, height);
}

    (void)colors;
TkRegion TkCreateRegion()
{
    return (TkRegion) XCreateRegion();
}

    (void)ncolors;
int TkDestroyRegion(TkRegion r)
{

	return XDestroyRegion((Region)r);
}

    return XPutImage(display, d, gc, image, src_x, src_y, dest_x, dest_y, width, height);
int TkSetRegion(Display *d, GC g, TkRegion r)
{
	return XSetRegion(d, g, (Region)r);
}

int TkUnionRectWithRegion(XRectangle *a, TkRegion b, TkRegion c)
{
	return XUnionRectWithRegion(a, (Region) b, (Region) c);
}

int TkClipBox(TkRegion a, XRectangle *b)
{
	return XClipBox((Region) a, b);
}

int TkIntersectRegion(TkRegion a, TkRegion b, TkRegion c)
{
	return XIntersectRegion((Region) a, (Region) b, (Region) c);
}

int TkRectInRegion (TkRegion r, int a, int b, unsigned int c, unsigned int d)
{
    return XRectInRegion((Region) r, a, b, c, d);
}

int TkSubtractRegion (TkRegion a, TkRegion b, TkRegion c)
{
    return XSubtractRegion((Region) a, (Region) b, (Region) c);
}

	/* TODO: To be implemented for Cygwin */
#	define Tk_AttachHWND 0
#	define Tk_GetHWND 0
#	define Tk_HWNDToWindow 0
#	define Tk_PointerEvent 0
#	define Tk_TranslateWinEvent 0
#	define TkAlignImageData 0
#	define TkGenerateActivateEvents 0
#	define TkpGetMS 0
#	define TkpGetCapture 0
#	define TkPointerDeadWindow 0
#	define TkpSetCapture 0
#	define TkpSetCursor 0
#	define TkWinCancelMouseTimer 0
#	define TkWinClipboardRender 0
207
208
209
210
211
212
213
214
215
216
217
218
219


220
221
222


223
224
225
226
227
228
229
230

















231
232
233
234
235
236
237
238
239




240
241
242
243
244
245
246








247
248
249
250
251
252
253
235
236
237
238
239
240
241

242
243
244
245

246
247
248


249
250








251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267









268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293







-




-
+
+

-
-
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+







+
+
+
+
+
+
+
+







#	define TkWinSetWindowPos 0
#	define TkWinWmCleanup 0
#	define TkWinXCleanup 0
#	define TkWinXInit 0
#	define TkWinSetForegroundWindow 0
#	define TkWinDialogDebug 0
#	define TkWinGetMenuSystemDefault 0
#	define TkWinGetPlatformId 0
#	define TkWinSetHINSTANCE 0
#	define TkWinGetPlatformTheme 0
#	define TkWinChildProc 0

#   elif !defined(MAC_OSX_TK) /* UNIX */
#   endif
#endif /* !_WIN32 */

#	undef TkClipBox
#	undef TkCreateRegion
#if defined(MAC_OSX_TCL)

#	undef TkDestroyRegion
#	undef TkIntersectRegion
#	undef TkRectInRegion
#	undef TkSetRegion
#	undef TkUnionRectWithRegion
#	undef TkSubtractRegion

#	define TkClipBox (int (*) (TkRegion, XRectangle *)) XClipBox
int
TkPutImage(
    unsigned long *colors,	/* Array of pixel values used by this image.
				 * May be NULL. */
    int ncolors,		/* Number of colors used, or 0. */
    Display *display,
    Drawable d,			/* Destination drawable. */
    GC gc,
    XImage *image,		/* Source image. */
    int src_x, int src_y,	/* Offset of subimage. */
    int dest_x, int dest_y,	/* Position of subimage origin in drawable. */
    unsigned int width, unsigned int height)
				/* Dimensions of subimage. */
{
	(void)colors;
	(void)ncolors;

#	define TkCreateRegion (TkRegion (*) ()) XCreateRegion
#	define TkDestroyRegion (int (*) (TkRegion)) XDestroyRegion
#	define TkIntersectRegion (int (*) (TkRegion, TkRegion, TkRegion)) XIntersectRegion
#	define TkRectInRegion (int (*) (TkRegion, int, int, unsigned int, unsigned int)) XRectInRegion
#	define TkSetRegion (int (*) (Display *, GC, TkRegion)) XSetRegion
#	define TkUnionRectWithRegion (int (*) (XRectangle *, TkRegion, TkRegion)) XUnionRectWithRegion
#	define TkSubtractRegion (int (*) (TkRegion, TkRegion, TkRegion)) XSubtractRegion
#   endif
#endif /* !_WIN32 */
    return XPutImage(display, d, gc, image, src_x, src_y, dest_x, dest_y, width, height);
}
#endif /* MAC_OSX_TCL */


/*
 * WARNING: The contents of this file is automatically generated by the
 * tools/genStubs.tcl script. Any modifications to the function declarations
 * below should be made in the generic/tk.decls script.
 */

#ifdef __GNUC__
/*
 * The rest of this file shouldn't warn about deprecated functions; they're
 * there because we intend them to be so and know that this file is OK to
 * touch those fields.
 */
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
/* !BEGIN!: Do not edit below this line. */

static const TkIntStubs tkIntStubs = {
    TCL_STUB_MAGIC,
    0,
    TkAllocWindow, /* 0 */
    TkBezierPoints, /* 1 */
358
359
360
361
362
363
364
365
366
367
368
369
370
371







372
373
374
375
376
377
378
398
399
400
401
402
403
404







405
406
407
408
409
410
411
412
413
414
415
416
417
418







-
-
-
-
-
-
-
+
+
+
+
+
+
+







    TkGetDisplayList, /* 106 */
    TkGetMainInfoList, /* 107 */
    TkGetWindowFromObj, /* 108 */
    TkpGetString, /* 109 */
    TkpGetSubFonts, /* 110 */
    TkpGetSystemDefault, /* 111 */
    TkpMenuThreadInit, /* 112 */
    TkClipBox, /* 113 */
    TkCreateRegion, /* 114 */
    TkDestroyRegion, /* 115 */
    TkIntersectRegion, /* 116 */
    TkRectInRegion, /* 117 */
    TkSetRegion, /* 118 */
    TkUnionRectWithRegion, /* 119 */
    XClipBox, /* 113 */
    XCreateRegion, /* 114 */
    XDestroyRegion, /* 115 */
    XIntersectRegion, /* 116 */
    XRectInRegion, /* 117 */
    XSetRegion, /* 118 */
    XUnionRectWithRegion, /* 119 */
    0, /* 120 */
#if !(defined(_WIN32) || defined(MAC_OSX_TK)) /* X11 */
    0, /* 121 */
#endif /* X11 */
#if defined(_WIN32) /* WIN */
    0, /* 121 */
#endif /* WIN */
417
418
419
420
421
422
423
424

425
426
427
428
429
430
431
457
458
459
460
461
462
463

464
465
466
467
468
469
470
471







-
+







    TkpGetKeySym, /* 138 */
    TkpInitKeymapInfo, /* 139 */
    TkPhotoGetValidRegion, /* 140 */
    TkWmStackorderToplevel, /* 141 */
    TkFocusFree, /* 142 */
    TkClipCleanup, /* 143 */
    TkGCCleanup, /* 144 */
    TkSubtractRegion, /* 145 */
    XSubtractRegion, /* 145 */
    TkStylePkgInit, /* 146 */
    TkStylePkgFree, /* 147 */
    TkToplevelWindowForCommand, /* 148 */
    TkGetOptionSpec, /* 149 */
    TkMakeRawCurve, /* 150 */
    TkMakeRawCurvePostscript, /* 151 */
    TkpDrawFrame, /* 152 */
457
458
459
460
461
462
463



















464
465
466
467
468
469
470
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    TkOrientPrintProc, /* 178 */
    TkSmoothParseProc, /* 179 */
    TkSmoothPrintProc, /* 180 */
    TkDrawAngledTextLayout, /* 181 */
    TkUnderlineAngledTextLayout, /* 182 */
    TkIntersectAngledTextLayout, /* 183 */
    TkDrawAngledChars, /* 184 */
#if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */
    0, /* 185 */
#endif /* UNIX */
#if defined(_WIN32) /* WIN */
    0, /* 185 */
#endif /* WIN */
#ifdef MAC_OSX_TCL /* MACOSX */
    TkpRedrawWidget, /* 185 */
#endif /* MACOSX */
#if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */
    0, /* 186 */
#endif /* UNIX */
#if defined(_WIN32) /* WIN */
    0, /* 186 */
#endif /* WIN */
#ifdef MAC_OSX_TCL /* MACOSX */
    TkpWillDrawWidget, /* 186 */
#endif /* MACOSX */
    TkDebugPhotoStringMatchDef, /* 187 */
};

static const TkIntPlatStubs tkIntPlatStubs = {
    TCL_STUB_MAGIC,
    0,
#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
    TkAlignImageData, /* 0 */
515
516
517
518
519
520
521
522

523
524
525
526
527
528
529
530
531

532
533
534
535
536
537
538
539
540
541
542
543
544
545
546

547
548
549
550
551
552
553

554
555
556
557
558
559
560
561
562
563
564
565
566
567

568
569

570
571
572
573
574
575
576
577
578
579
580

581
582
583
584
585
586
587
588
589
590
591
































592
593
594
595
596
597
598
574
575
576
577
578
579
580

581
582
583
584
585
586
587
588
589

590
591
592
593
594
595
596
597
598
599
600
601
602
603
604

605
606
607
608
609
610
611

612
613
614
615
616
617
618
619
620
621
622
623
624
625

626
627

628
629
630
631
632
633
634
635
636
637
638

639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689







-
+








-
+














-
+






-
+













-
+

-
+










-
+











+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    TkpTestsendCmd, /* 45 */
    0, /* 46 */
    TkpGetCapture, /* 47 */
#endif /* WIN */
#ifdef MAC_OSX_TK /* AQUA */
    TkGenerateActivateEvents, /* 0 */
    0, /* 1 */
    0, /* 2 */
    TkGenerateActivateEvents_, /* 2 */
    TkPointerDeadWindow, /* 3 */
    TkpSetCapture, /* 4 */
    TkpSetCursor, /* 5 */
    TkpWmSetState, /* 6 */
    TkAboutDlg, /* 7 */
    TkMacOSXButtonKeyState, /* 8 */
    TkMacOSXClearMenubarActive, /* 9 */
    TkMacOSXDispatchMenuEvent, /* 10 */
    TkMacOSXInstallCursor, /* 11 */
    0, /* 11 */
    TkMacOSXHandleTearoffMenu, /* 12 */
    0, /* 13 */
    TkMacOSXDoHLEvent, /* 14 */
    0, /* 15 */
    TkMacOSXGetXWindow, /* 16 */
    TkMacOSXGrowToplevel, /* 17 */
    TkMacOSXHandleMenuSelect, /* 18 */
    0, /* 19 */
    0, /* 20 */
    TkMacOSXInvalidateWindow, /* 21 */
    TkMacOSXIsCharacterMissing, /* 22 */
    TkMacOSXMakeRealWindowExist, /* 23 */
    TkMacOSXMakeStippleMap, /* 24 */
    TkMacOSXMenuClick, /* 25 */
    TkMacOSXRegisterOffScreenWindow, /* 26 */
    0, /* 26 */
    TkMacOSXResizable, /* 27 */
    TkMacOSXSetHelpMenuItemCount, /* 28 */
    TkMacOSXSetScrollbarGrow, /* 29 */
    TkMacOSXSetUpClippingRgn, /* 30 */
    TkMacOSXSetUpGraphicsPort, /* 31 */
    TkMacOSXUpdateClipRgn, /* 32 */
    TkMacOSXUnregisterMacWindow, /* 33 */
    0, /* 33 */
    TkMacOSXUseMenuID, /* 34 */
    TkMacOSXVisableClipRgn, /* 35 */
    TkMacOSXWinBounds, /* 36 */
    TkMacOSXWindowOffset, /* 37 */
    TkSetMacColor, /* 38 */
    TkSetWMName, /* 39 */
    0, /* 40 */
    TkMacOSXZoomToplevel, /* 41 */
    Tk_TopCoordsToWindow, /* 42 */
    TkMacOSXContainerId, /* 43 */
    TkMacOSXGetHostToplevel, /* 44 */
    TkMacOSXPreprocessMenu, /* 45 */
    TkpIsWindowFloating, /* 46 */
    TkMacOSXGetCapture, /* 47 */
    TkpGetCapture, /* 47 */
    0, /* 48 */
    TkGetTransientMaster, /* 49 */
    TkMacOSXGetContainer, /* 49 */
    TkGenerateButtonEvent, /* 50 */
    TkGenWMDestroyEvent, /* 51 */
    TkMacOSXSetDrawingEnabled, /* 52 */
    TkpGetMS, /* 53 */
    TkMacOSXDrawable, /* 54 */
    TkpScanWindowId, /* 55 */
#endif /* AQUA */
#if !(defined(_WIN32) || defined(__CYGWIN__) || defined(MAC_OSX_TK)) /* X11 */
    TkCreateXEventSource, /* 0 */
    0, /* 1 */
    0, /* 2 */
    TkGenerateActivateEvents, /* 2 */
    TkpCmapStressed, /* 3 */
    TkpSync, /* 4 */
    TkUnixContainerId, /* 5 */
    TkUnixDoOneXEvent, /* 6 */
    TkUnixSetMenubar, /* 7 */
    TkpScanWindowId, /* 8 */
    TkWmCleanup, /* 9 */
    TkSendCleanup, /* 10 */
    0, /* 11 */
    TkpWmSetState, /* 12 */
    TkpTestsendCmd, /* 13 */
    0, /* 14 */
    0, /* 15 */
    0, /* 16 */
    0, /* 17 */
    0, /* 18 */
    0, /* 19 */
    0, /* 20 */
    0, /* 21 */
    0, /* 22 */
    0, /* 23 */
    0, /* 24 */
    0, /* 25 */
    0, /* 26 */
    0, /* 27 */
    0, /* 28 */
    0, /* 29 */
    0, /* 30 */
    0, /* 31 */
    0, /* 32 */
    0, /* 33 */
    0, /* 34 */
    0, /* 35 */
    0, /* 36 */
    0, /* 37 */
    TkpCmapStressed_, /* 38 */
    TkpSync_, /* 39 */
    TkUnixContainerId_, /* 40 */
    TkUnixDoOneXEvent_, /* 41 */
    TkUnixSetMenubar_, /* 42 */
    TkWmCleanup_, /* 43 */
    TkSendCleanup_, /* 44 */
    TkpTestsendCmd_, /* 45 */
#endif /* X11 */
};

static const TkIntXlibStubs tkIntXlibStubs = {
    TCL_STUB_MAGIC,
    0,
#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
730
731
732
733
734
735
736





















737
738

739
740
741
742
743
744
745
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849

850
851
852
853
854
855
856
857







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+







    XDrawArcs, /* 131 */
    XDrawRectangles, /* 132 */
    XDrawSegments, /* 133 */
    XDrawPoint, /* 134 */
    XDrawPoints, /* 135 */
    XReparentWindow, /* 136 */
    XPutImage, /* 137 */
    XPolygonRegion, /* 138 */
    XPointInRegion, /* 139 */
    XVaCreateNestedList, /* 140 */
    XSetICValues, /* 141 */
    XGetICValues, /* 142 */
    XSetICFocus, /* 143 */
    0, /* 144 */
    0, /* 145 */
    0, /* 146 */
    XFreeFontSet, /* 147 */
    XCloseIM, /* 148 */
    XRegisterIMInstantiateCallback, /* 149 */
    XUnregisterIMInstantiateCallback, /* 150 */
    XSetLocaleModifiers, /* 151 */
    XOpenIM, /* 152 */
    XGetIMValues, /* 153 */
    XSetIMValues, /* 154 */
    XCreateFontSet, /* 155 */
    XFreeStringList, /* 156 */
    XkbKeycodeToKeysym, /* 157 */
    XkbOpenDisplay, /* 158 */
#endif /* WIN */
#ifdef MAC_OSX_TK /* AQUA */
#ifdef MAC_OSX_TCL /* MACOSX */
    XSetDashes, /* 0 */
    XGetModifierMapping, /* 1 */
    XCreateImage, /* 2 */
    XGetImage, /* 3 */
    XGetAtomName, /* 4 */
    XKeysymToString, /* 5 */
    XCreateColormap, /* 6 */
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845















846
847
848
849
850
851
852

853
854
855
856
857
858
859
860
861



862
863
864
865
866
867
868
869
870
871




872
873
874
875

876





















877

878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895




896
897

898
899

900
901
902






903
904
905
906
907
908
909
936
937
938
939
940
941
942















943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963

964
965
966
967
968
969
970



971
972
973
974
975
976
977
978
979




980
981
982
983
984
985
986

987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009

1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024




1025
1026
1027
1028
1029

1030
1031

1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






-
+






-
-
-
+
+
+






-
-
-
-
+
+
+
+



-
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+














-
-
-
-
+
+
+
+

-
+

-
+



+
+
+
+
+
+







    XDrawPoint, /* 85 */
    XDrawPoints, /* 86 */
    XWarpPointer, /* 87 */
    XQueryColor, /* 88 */
    XQueryColors, /* 89 */
    XQueryTree, /* 90 */
    XSync, /* 91 */
    0, /* 92 */
    0, /* 93 */
    0, /* 94 */
    0, /* 95 */
    0, /* 96 */
    0, /* 97 */
    0, /* 98 */
    0, /* 99 */
    0, /* 100 */
    0, /* 101 */
    0, /* 102 */
    0, /* 103 */
    0, /* 104 */
    0, /* 105 */
    0, /* 106 */
    XTranslateCoordinates, /* 92 */
    XDeleteProperty, /* 93 */
    XFreeCursor, /* 94 */
    XGetInputFocus, /* 95 */
    XmbLookupString, /* 96 */
    XNextEvent, /* 97 */
    XPutBackEvent, /* 98 */
    XSetCommand, /* 99 */
    XWindowEvent, /* 100 */
    XGetWindowAttributes, /* 101 */
    XGetWMColormapWindows, /* 102 */
    XIconifyWindow, /* 103 */
    XWithdrawWindow, /* 104 */
    XListHosts, /* 105 */
    XSetClipRectangles, /* 106 */
    XFlush, /* 107 */
    XGrabServer, /* 108 */
    XUngrabServer, /* 109 */
    XFree, /* 110 */
    XNoOp, /* 111 */
    XSynchronize, /* 112 */
    0, /* 113 */
    XLookupColor, /* 113 */
    XVisualIDFromVisual, /* 114 */
    0, /* 115 */
    0, /* 116 */
    0, /* 117 */
    0, /* 118 */
    0, /* 119 */
    0, /* 120 */
    0, /* 121 */
    0, /* 122 */
    XOffsetRegion, /* 120 */
    XUnionRegion, /* 121 */
    XCreateWindow, /* 122 */
    0, /* 123 */
    0, /* 124 */
    0, /* 125 */
    0, /* 126 */
    0, /* 127 */
    0, /* 128 */
    0, /* 129 */
    0, /* 130 */
    0, /* 131 */
    0, /* 132 */
    XLowerWindow, /* 129 */
    XFillArcs, /* 130 */
    XDrawArcs, /* 131 */
    XDrawRectangles, /* 132 */
    0, /* 133 */
    0, /* 134 */
    0, /* 135 */
    0, /* 136 */
    XReparentWindow, /* 136 */
    XPutImage, /* 137 */
    XPolygonRegion, /* 138 */
    XPointInRegion, /* 139 */
    XVaCreateNestedList, /* 140 */
    XSetICValues, /* 141 */
    XGetICValues, /* 142 */
    XSetICFocus, /* 143 */
    XDestroyIC, /* 144 */
    XCreatePixmapCursor, /* 145 */
    XCreateGlyphCursor, /* 146 */
    XFreeFontSet, /* 147 */
    XCloseIM, /* 148 */
    XRegisterIMInstantiateCallback, /* 149 */
    XUnregisterIMInstantiateCallback, /* 150 */
    XSetLocaleModifiers, /* 151 */
    XOpenIM, /* 152 */
    XGetIMValues, /* 153 */
    XSetIMValues, /* 154 */
    XCreateFontSet, /* 155 */
    XFreeStringList, /* 156 */
    XkbKeycodeToKeysym, /* 157 */
    XkbOpenDisplay, /* 158 */
#endif /* AQUA */
#endif /* MACOSX */
};

static const TkPlatStubs tkPlatStubs = {
    TCL_STUB_MAGIC,
    0,
#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
    Tk_AttachHWND, /* 0 */
    Tk_GetHINSTANCE, /* 1 */
    Tk_GetHWND, /* 2 */
    Tk_HWNDToWindow, /* 3 */
    Tk_PointerEvent, /* 4 */
    Tk_TranslateWinEvent, /* 5 */
#endif /* WIN */
#ifdef MAC_OSX_TK /* AQUA */
    Tk_MacOSXSetEmbedHandler, /* 0 */
    Tk_MacOSXTurnOffMenus, /* 1 */
    Tk_MacOSXTkOwnsCursor, /* 2 */
    TkMacOSXInitMenus, /* 3 */
    0, /* 0 */
    0, /* 1 */
    0, /* 2 */
    0, /* 3 */
    TkMacOSXInitAppleEvents, /* 4 */
    TkGenWMConfigureEvent, /* 5 */
    TkGenWMConfigureEvent_, /* 5 */
    TkMacOSXInvalClipRgns, /* 6 */
    TkMacOSXGetDrawablePort, /* 7 */
    0, /* 7 */
    TkMacOSXGetRootControl, /* 8 */
    Tk_MacOSXSetupTkNotifier, /* 9 */
    Tk_MacOSXIsAppInFront, /* 10 */
    Tk_MacOSXGetTkWindow, /* 11 */
    Tk_MacOSXGetCGContextForDrawable, /* 12 */
    Tk_MacOSXGetNSWindowForDrawable, /* 13 */
    0, /* 14 */
    0, /* 15 */
    TkGenWMConfigureEvent, /* 16 */
#endif /* AQUA */
};

static const TkStubHooks tkStubHooks = {
    &tkPlatStubs,
    &tkIntStubs,
    &tkIntPlatStubs,
1007
1008
1009
1010
1011
1012
1013
1014

1015
1016
1017
1018
1019
1020
1021
1146
1147
1148
1149
1150
1151
1152

1153
1154
1155
1156
1157
1158
1159
1160







-
+







    Tk_GetCursor, /* 91 */
    Tk_GetCursorFromData, /* 92 */
    Tk_GetFont, /* 93 */
    Tk_GetFontFromObj, /* 94 */
    Tk_GetFontMetrics, /* 95 */
    Tk_GetGC, /* 96 */
    Tk_GetImage, /* 97 */
    Tk_GetImageMasterData, /* 98 */
    Tk_GetImageModelData, /* 98 */
    Tk_GetItemTypes, /* 99 */
    Tk_GetJoinStyle, /* 100 */
    Tk_GetJustify, /* 101 */
    Tk_GetNumMainWindows, /* 102 */
    Tk_GetOption, /* 103 */
    Tk_GetPixels, /* 104 */
    Tk_GetPixmap, /* 105 */
1183
1184
1185
1186
1187
1188
1189






1190
1191
1192













1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350







+
+
+
+
+
+



+
+
+
+
+
+
+
+
+
+
+
+
+
    Tk_PhotoPutZoomedBlock, /* 267 */
    Tk_PhotoSetSize, /* 268 */
    Tk_GetUserInactiveTime, /* 269 */
    Tk_ResetUserInactiveTime, /* 270 */
    Tk_Interp, /* 271 */
    Tk_CreateOldImageType, /* 272 */
    Tk_CreateOldPhotoImageFormat, /* 273 */
    Tk_AlwaysShowSelection, /* 274 */
    Tk_GetButtonMask, /* 275 */
    Tk_GetDoublePixelsFromObj, /* 276 */
    Tk_NewWindowObj, /* 277 */
    Tk_SendVirtualEvent, /* 278 */
    Tk_FontGetDescription, /* 279 */
};

/* !END!: Do not edit above this line. */


#ifdef __CYGWIN__
void *Tk_GetHINSTANCE(void)
{
    void *hInstance = NULL;

    GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
	    (const char *) &tkIntStubs, &hInstance);
    return hInstance;
}
#endif

Changes to generic/tkStubLib.c.
1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15






-
-
+
+







/*
 * 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.
 */

#include "tkInt.h"

71
72
73
74
75
76
77
78

79
80

81
82
83
84
85




86


87
88
89
90
91
92
93
71
72
73
74
75
76
77

78
79

80
81
82

83
84
85
86
87
88

89
90
91
92
93
94
95
96
97







-
+

-
+


-


+
+
+
+
-
+
+







#undef Tk_InitStubs
MODULE_SCOPE const char *
Tk_InitStubs(
    Tcl_Interp *interp,
    const char *version,
    int exact)
{
    const char *packageName = "Tk";
    const char *packageName = "tk";
    const char *errMsg = NULL;
    ClientData clientData = NULL;
    void *clientData = NULL;
    const char *actualVersion = tclStubsPtr->tcl_PkgRequireEx(interp,
	    packageName, version, 0, &clientData);
    const TkStubs *stubsPtr = clientData;

    if (actualVersion == NULL) {
	packageName = "Tk";
	actualVersion = tclStubsPtr->tcl_PkgRequireEx(interp,
    	    packageName, version, 0, &clientData);
	if (actualVersion == NULL) {
	return NULL;
	    return NULL;
	}
    }

    if (exact) {
	const char *p = version;
	int count = 0;

	while (*p) {
109
110
111
112
113
114
115
116

117
118
119
120
121
122
123
124






125
126
127
128
129
130
131
113
114
115
116
117
118
119

120
121
122






123
124
125
126
127
128
129
130
131
132
133
134
135







-
+


-
-
-
-
-
-
+
+
+
+
+
+







	    actualVersion = tclStubsPtr->tcl_PkgRequireEx(interp, packageName,
		    version, 1, NULL);
	    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;
	}
	return actualVersion;
Changes to generic/tkStyle.c.
1
2
3
4
5
6
7


8
9
10
11
12
13
14
1
2
3
4
5


6
7
8
9
10
11
12
13
14





-
-
+
+







/*
 * 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.
 */

#include "tkInt.h"

151
152
153
154
155
156
157
158

159
160
161
162
163
164
165
151
152
153
154
155
156
157

158
159
160
161
162
163
164
165







-
+







 */

static const Tcl_ObjType styleObjType = {
    "style",			/* name */
    FreeStyleObjProc,		/* freeIntRepProc */
    DupStyleObjProc,		/* dupIntRepProc */
    NULL,			/* updateStringProc */
    SetStyleFromAny		/* setFromAnyProc */
    NULL			/* setFromAnyProc */
};

/*
 *---------------------------------------------------------------------------
 *
 * TkStylePkgInit --
 *
174
175
176
177
178
179
180
181

182
183

184
185
186
187
188
189
190
174
175
176
177
178
179
180

181
182

183
184
185
186
187
188
189
190







-
+

-
+







 *	Memory allocated.
 *
 *---------------------------------------------------------------------------
 */

void
TkStylePkgInit(
    TkMainInfo *mainPtr)	/* The application being created. */
    TCL_UNUSED(TkMainInfo *))	/* The application being created. */
{
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (tsdPtr->nbInit != 0) {
	return;
    }

    /*
229
230
231
232
233
234
235
236

237
238

239
240
241
242
243
244
245
229
230
231
232
233
234
235

236
237

238
239
240
241
242
243
244
245







-
+

-
+







 *	Memory freed.
 *
 *---------------------------------------------------------------------------
 */

void
TkStylePkgFree(
    TkMainInfo *mainPtr)	/* The application being deleted. */
    TCL_UNUSED(TkMainInfo *))	/* The application being deleted. */
{
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    Tcl_HashSearch search;
    Tcl_HashEntry *entryPtr;
    StyleEngine *enginePtr;
    int i;

    tsdPtr->nbInit--;
260
261
262
263
264
265
266
267

268
269
270
271
272
273
274
260
261
262
263
264
265
266

267
268
269
270
271
272
273
274







-
+








    /*
     * Free engines.
     */

    entryPtr = Tcl_FirstHashEntry(&tsdPtr->engineTable, &search);
    while (entryPtr != NULL) {
	enginePtr = Tcl_GetHashValue(entryPtr);
	enginePtr = (StyleEngine *)Tcl_GetHashValue(entryPtr);
	FreeStyleEngine(enginePtr);
	ckfree(enginePtr);
	entryPtr = Tcl_NextHashEntry(&search);
    }
    Tcl_DeleteHashTable(&tsdPtr->engineTable);

    /*
303
304
305
306
307
308
309
310

311
312
313
314
315
316
317
303
304
305
306
307
308
309

310
311
312
313
314
315
316
317







-
+







Tk_StyleEngine
Tk_RegisterStyleEngine(
    const char *name,		/* Name of the engine to create. NULL or empty
				 * means the default system engine. */
    Tk_StyleEngine parent)	/* The engine's parent. NULL means the default
				 * system engine. */
{
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    Tcl_HashEntry *entryPtr;
    int newEntry;
    StyleEngine *enginePtr;

    /*
     * Attempt to create a new entry in the engine table.
327
328
329
330
331
332
333
334
335


336
337
338
339
340
341
342
327
328
329
330
331
332
333


334
335
336
337
338
339
340
341
342







-
-
+
+







	return NULL;
    }

    /*
     * Allocate and intitialize a new engine.
     */

    enginePtr = ckalloc(sizeof(StyleEngine));
    InitStyleEngine(enginePtr, Tcl_GetHashKey(&tsdPtr->engineTable, entryPtr),
    enginePtr = (StyleEngine *)ckalloc(sizeof(StyleEngine));
    InitStyleEngine(enginePtr, (const char *)Tcl_GetHashKey(&tsdPtr->engineTable, entryPtr),
	    (StyleEngine *) parent);
    Tcl_SetHashValue(entryPtr, enginePtr);

    return (Tk_StyleEngine) enginePtr;
}

/*
360
361
362
363
364
365
366
367

368
369
370
371
372
373
374
360
361
362
363
364
365
366

367
368
369
370
371
372
373
374







-
+







    StyleEngine *enginePtr,	/* Points to an uninitialized engine. */
    const char *name,		/* Name of the registered engine. NULL or empty
				 * means the default system engine. Usually
				 * points to the hash key. */
    StyleEngine *parentPtr)	/* The engine's parent. NULL means the default
				 * system engine. */
{
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    int elementId;

    if (name == NULL || *name == '\0') {
	/*
	 * This is the default style engine.
	 */
385
386
387
388
389
390
391
392

393
394
395
396
397
398
399
385
386
387
388
389
390
391

392
393
394
395
396
397
398
399







-
+







    }

    /*
     * Allocate and initialize elements array.
     */

    if (tsdPtr->nbElements > 0) {
	enginePtr->elements = ckalloc(
	enginePtr->elements = (StyledElement *)ckalloc(
		sizeof(StyledElement) * tsdPtr->nbElements);
	for (elementId = 0; elementId < tsdPtr->nbElements; elementId++) {
	    InitStyledElement(enginePtr->elements+elementId);
	}
    } else {
	enginePtr->elements = NULL;
    }
415
416
417
418
419
420
421
422

423
424
425
426
427
428
429
415
416
417
418
419
420
421

422
423
424
425
426
427
428
429







-
+







 *---------------------------------------------------------------------------
 */

static void
FreeStyleEngine(
    StyleEngine *enginePtr)	/* The style engine to free. */
{
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    int elementId;

    /*
     * Free allocated elements.
     */

450
451
452
453
454
455
456
457

458
459
460
461
462
463
464
465
466
467
468
469
470

471
472
473
474
475
476
477
450
451
452
453
454
455
456

457
458
459
460
461
462
463
464
465
466
467
468
469

470
471
472
473
474
475
476
477







-
+












-
+







 */

Tk_StyleEngine
Tk_GetStyleEngine(
    const char *name)		/* Name of the engine to retrieve. NULL or
				 * empty means the default system engine. */
{
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    Tcl_HashEntry *entryPtr;

    if (name == NULL) {
	return (Tk_StyleEngine) tsdPtr->defaultEnginePtr;
    }

    entryPtr = Tcl_FindHashEntry(&tsdPtr->engineTable, (name!=NULL?name:""));
    if (!entryPtr) {
	return NULL;
    }

    return Tcl_GetHashValue(entryPtr);
    return (Tk_StyleEngine)Tcl_GetHashValue(entryPtr);
}

/*
 *---------------------------------------------------------------------------
 *
 * InitElement --
 *
517
518
519
520
521
522
523
524

525
526
527
528
529
530
531
517
518
519
520
521
522
523

524
525
526
527
528
529
530
531







-
+







 *	Memory freed.
 *
 *---------------------------------------------------------------------------
 */

static void
FreeElement(
    Element *elementPtr)	/* The element to free. */
    TCL_UNUSED(Element *))	/* The element to free. */
{
    /* Nothing to do. */
}

/*
 *---------------------------------------------------------------------------
 *
600
601
602
603
604
605
606
607

608
609
610
611
612
613
614
600
601
602
603
604
605
606

607
608
609
610
611
612
613
614







-
+







static int
CreateElement(
    const char *name,		/* Name of the element. */
    int create)			/* Boolean, whether the element is being
				 * created explicitly (being registered) or
				 * implicitly (by a derived element). */
{
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    Tcl_HashEntry *entryPtr, *engineEntryPtr;
    Tcl_HashSearch search;
    int newEntry, elementId, genericId = -1;
    const char *dot;
    StyleEngine *enginePtr;

638
639
640
641
642
643
644
645

646
647
648

649
650
651
652
653
654
655
656
657

658
659

660
661
662
663
664
665
666
638
639
640
641
642
643
644

645
646
647

648
649
650
651
652
653
654
655
656

657
658

659
660
661
662
663
664
665
666







-
+


-
+








-
+

-
+







    elementId = tsdPtr->nbElements++;
    Tcl_SetHashValue(entryPtr, INT2PTR(elementId));

    /*
     * Reallocate element table.
     */

    tsdPtr->elements = ckrealloc(tsdPtr->elements,
    tsdPtr->elements = (Element *)ckrealloc(tsdPtr->elements,
	    sizeof(Element) * tsdPtr->nbElements);
    InitElement(tsdPtr->elements+elementId,
	    Tcl_GetHashKey(&tsdPtr->elementTable, entryPtr), elementId,
	    (const char *)Tcl_GetHashKey(&tsdPtr->elementTable, entryPtr), elementId,
	    genericId, create);

    /*
     * Reallocate style engines' element table.
     */

    engineEntryPtr = Tcl_FirstHashEntry(&tsdPtr->engineTable, &search);
    while (engineEntryPtr != NULL) {
	enginePtr = Tcl_GetHashValue(engineEntryPtr);
	enginePtr = (StyleEngine *)Tcl_GetHashValue(engineEntryPtr);

	enginePtr->elements = ckrealloc(enginePtr->elements,
	enginePtr->elements = (StyledElement *)ckrealloc(enginePtr->elements,
		sizeof(StyledElement) * tsdPtr->nbElements);
	InitStyledElement(enginePtr->elements+elementId);

	engineEntryPtr = Tcl_NextHashEntry(&search);
    }

    return elementId;
682
683
684
685
686
687
688
689

690
691
692
693
694
695
696
682
683
684
685
686
687
688

689
690
691
692
693
694
695
696







-
+







 *---------------------------------------------------------------------------
 */

int
Tk_GetElementId(
    const char *name)		/* Name of the element. */
{
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    Tcl_HashEntry *entryPtr;
    int genericId = -1;
    const char *dot;

    /*
     * Find the element Id.
755
756
757
758
759
760
761
762

763
764
765
766
767
768
769
755
756
757
758
759
760
761

762
763
764
765
766
767
768
769







-
+







    Tk_ElementSpec *templatePtr)/* Static template information about the
				 * element. */
{
    int elementId;
    StyledElement *elementPtr;
    Tk_ElementSpec *specPtr;
    int nbOptions;
    register Tk_ElementOptionSpec *srcOptions, *dstOptions;
    Tk_ElementOptionSpec *srcOptions, *dstOptions;

    if (templatePtr->version != TK_STYLE_VERSION_1) {
	/*
	 * Version mismatch. Do nothing.
	 */

	return -1;
782
783
784
785
786
787
788
789

790
791

792
793
794
795
796
797
798

799
800
801
802
803
804
805
806
807

808
809
810
811
812
813
814
782
783
784
785
786
787
788

789
790

791
792
793
794
795
796
797

798
799
800
801
802
803
804
805
806

807
808
809
810
811
812
813
814







-
+

-
+






-
+








-
+








    /*
     * Initialize the styled element.
     */

    elementPtr = ((StyleEngine *) engine)->elements+elementId;

    specPtr = ckalloc(sizeof(Tk_ElementSpec));
    specPtr = (Tk_ElementSpec *)ckalloc(sizeof(Tk_ElementSpec));
    specPtr->version = templatePtr->version;
    specPtr->name = ckalloc(strlen(templatePtr->name)+1);
    specPtr->name = (char *)ckalloc(strlen(templatePtr->name)+1);
    strcpy(specPtr->name, templatePtr->name);
    nbOptions = 0;
    for (nbOptions = 0, srcOptions = templatePtr->options;
	    srcOptions->name != NULL; nbOptions++, srcOptions++) {
	/* empty body */
    }
    specPtr->options =
    specPtr->options = (Tk_ElementOptionSpec *)
	    ckalloc(sizeof(Tk_ElementOptionSpec) * (nbOptions+1));
    for (srcOptions = templatePtr->options, dstOptions = specPtr->options;
	    /* End condition within loop */; srcOptions++, dstOptions++) {
	if (srcOptions->name == NULL) {
	    dstOptions->name = NULL;
	    break;
	}

	dstOptions->name = ckalloc(strlen(srcOptions->name)+1);
	dstOptions->name = (char *)ckalloc(strlen(srcOptions->name)+1);
	strcpy(dstOptions->name, srcOptions->name);
	dstOptions->type = srcOptions->type;
    }
    specPtr->getSize = templatePtr->getSize;
    specPtr->getBox = templatePtr->getBox;
    specPtr->getBorderWidth = templatePtr->getBorderWidth;
    specPtr->draw = templatePtr->draw;
840
841
842
843
844
845
846
847

848
849
850
851
852
853
854
840
841
842
843
844
845
846

847
848
849
850
851
852
853
854







-
+







static StyledElement *
GetStyledElement(
    StyleEngine *enginePtr,	/* Style engine providing the implementation.
				 * NULL means the default system engine. */
    int elementId)		/* Unique element ID */
{
    StyledElement *elementPtr;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    StyleEngine *enginePtr2;

    if (enginePtr == NULL) {
	enginePtr = tsdPtr->defaultEnginePtr;
    }

920
921
922
923
924
925
926
927

928
929
930
931
932
933
934
920
921
922
923
924
925
926

927
928
929
930
931
932
933
934







-
+







    }

    /*
     * Build the widget option list.
     */

    widgetSpecPtr->optionsPtr =
	    ckalloc(sizeof(Tk_OptionSpec *) * nbOptions);
	    (const Tk_OptionSpec **)ckalloc(sizeof(Tk_OptionSpec *) * nbOptions);
    for (i = 0, elementOptionPtr = elementPtr->specPtr->options;
	    i < nbOptions; i++, elementOptionPtr++) {
	widgetOptionPtr = TkGetOptionSpec(elementOptionPtr->name, optionTable);

	/*
	 * Check that the widget option type is compatible with one of the
	 * element's required types.
1004
1005
1006
1007
1008
1009
1010
1011

1012
1013
1014
1015
1016
1017
1018
1004
1005
1006
1007
1008
1009
1010

1011
1012
1013
1014
1015
1016
1017
1018







-
+







    }

    /*
     * Create and initialize a new widget spec.
     */

    i = elementPtr->nbWidgetSpecs++;
    elementPtr->widgetSpecs = ckrealloc(elementPtr->widgetSpecs,
    elementPtr->widgetSpecs = (StyledWidgetSpec *)ckrealloc(elementPtr->widgetSpecs,
	    sizeof(StyledWidgetSpec) * elementPtr->nbWidgetSpecs);
    widgetSpecPtr = elementPtr->widgetSpecs+i;
    InitWidgetSpec(widgetSpecPtr, elementPtr, optionTable);

    return widgetSpecPtr;
}

1072
1073
1074
1075
1076
1077
1078
1079

1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093

1094
1095
1096
1097
1098
1099
1100
1072
1073
1074
1075
1076
1077
1078

1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092

1093
1094
1095
1096
1097
1098
1099
1100







-
+













-
+







 */

void
Tk_GetElementSize(
    Tk_Style style,		/* The widget style. */
    Tk_StyledElement element,	/* The styled element, previously returned by
				 * Tk_GetStyledElement. */
    char *recordPtr,		/* The widget record. */
    void *recordPtr,		/* The widget record. */
    Tk_Window tkwin,		/* The widget window. */
    int width, int height,	/* Requested size. */
    int inner,			/* If TRUE, compute the outer size according
				 * to the requested minimum inner size. If
				 * FALSE, compute the inner size according to
				 * the requested maximum outer size. */
    int *widthPtr, int *heightPtr)
				/* Returned size. */
{
    Style *stylePtr = (Style *) style;
    StyledWidgetSpec *widgetSpecPtr = (StyledWidgetSpec *) element;

    widgetSpecPtr->elementPtr->specPtr->getSize(stylePtr->clientData,
	    recordPtr, widgetSpecPtr->optionsPtr, tkwin, width, height, inner,
	    (char *)recordPtr, widgetSpecPtr->optionsPtr, tkwin, width, height, inner,
	    widthPtr, heightPtr);
}

/*
 *---------------------------------------------------------------------------
 *
 * Tk_GetElementBox --
1113
1114
1115
1116
1117
1118
1119
1120

1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136

1137
1138
1139
1140
1141
1142
1143
1113
1114
1115
1116
1117
1118
1119

1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135

1136
1137
1138
1139
1140
1141
1142
1143







-
+















-
+







 */

void
Tk_GetElementBox(
    Tk_Style style,		/* The widget style. */
    Tk_StyledElement element,	/* The styled element, previously returned by
				 * Tk_GetStyledElement. */
    char *recordPtr,		/* The widget record. */
    void *recordPtr,		/* The widget record. */
    Tk_Window tkwin,		/* The widget window. */
    int x, int y,		/* Top left corner of available area. */
    int width, int height,	/* Size of available area. */
    int inner,			/* Boolean. If TRUE, compute the bounding box
				 * according to the requested inscribed box
				 * size. If FALSE, compute the inscribed box
				 * according to the requested bounding box. */
    int *xPtr, int *yPtr,	/* Returned top left corner. */
    int *widthPtr, int *heightPtr)
				/* Returned size. */
{
    Style *stylePtr = (Style *) style;
    StyledWidgetSpec *widgetSpecPtr = (StyledWidgetSpec *) element;

    widgetSpecPtr->elementPtr->specPtr->getBox(stylePtr->clientData,
	    recordPtr, widgetSpecPtr->optionsPtr, tkwin, x, y, width, height,
	    (char *)recordPtr, widgetSpecPtr->optionsPtr, tkwin, x, y, width, height,
	    inner, xPtr, yPtr, widthPtr, heightPtr);
}

/*
 *---------------------------------------------------------------------------
 *
 * Tk_GetElementBorderWidth --
1155
1156
1157
1158
1159
1160
1161
1162

1163
1164
1165
1166
1167
1168
1169

1170
1171
1172
1173
1174
1175
1176
1155
1156
1157
1158
1159
1160
1161

1162
1163
1164
1165
1166
1167
1168

1169
1170
1171
1172
1173
1174
1175
1176







-
+






-
+







 */

int
Tk_GetElementBorderWidth(
    Tk_Style style,		/* The widget style. */
    Tk_StyledElement element,	/* The styled element, previously returned by
				 * Tk_GetStyledElement. */
    char *recordPtr,		/* The widget record. */
    void *recordPtr,		/* The widget record. */
    Tk_Window tkwin)		/* The widget window. */
{
    Style *stylePtr = (Style *) style;
    StyledWidgetSpec *widgetSpecPtr = (StyledWidgetSpec *) element;

    return widgetSpecPtr->elementPtr->specPtr->getBorderWidth(
	    stylePtr->clientData, recordPtr, widgetSpecPtr->optionsPtr, tkwin);
	    stylePtr->clientData, (char *)recordPtr, widgetSpecPtr->optionsPtr, tkwin);
}

/*
 *---------------------------------------------------------------------------
 *
 * Tk_DrawElement --
 *
1186
1187
1188
1189
1190
1191
1192
1193

1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204

1205
1206
1207
1208
1209
1210
1211
1186
1187
1188
1189
1190
1191
1192

1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203

1204
1205
1206
1207
1208
1209
1210
1211







-
+










-
+







 */

void
Tk_DrawElement(
    Tk_Style style,		/* The widget style. */
    Tk_StyledElement element,	/* The styled element, previously returned by
				 * Tk_GetStyledElement. */
    char *recordPtr,		/* The widget record. */
    void *recordPtr,		/* The widget record. */
    Tk_Window tkwin,		/* The widget window. */
    Drawable d,			/* Where to draw element. */
    int x, int y,		/* Top left corner of element. */
    int width, int height,	/* Size of element. */
    int state)			/* Drawing state flags. */
{
    Style *stylePtr = (Style *) style;
    StyledWidgetSpec *widgetSpecPtr = (StyledWidgetSpec *) element;

    widgetSpecPtr->elementPtr->specPtr->draw(stylePtr->clientData,
	    recordPtr, widgetSpecPtr->optionsPtr, tkwin, d, x, y, width,
	    (char *)recordPtr, widgetSpecPtr->optionsPtr, tkwin, d, x, y, width,
	    height, state);
}

/*
 *---------------------------------------------------------------------------
 *
 * Tk_CreateStyle --
1225
1226
1227
1228
1229
1230
1231
1232

1233
1234
1235
1236
1237
1238
1239
1225
1226
1227
1228
1229
1230
1231

1232
1233
1234
1235
1236
1237
1238
1239







-
+







Tk_Style
Tk_CreateStyle(
    const char *name,		/* Name of the style to create. NULL or empty
				 * means the default system style. */
    Tk_StyleEngine engine,	/* The style engine. */
    ClientData clientData)	/* Private data passed as is to engine code. */
{
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    Tcl_HashEntry *entryPtr;
    int newEntry;
    Style *stylePtr;

    /*
     * Attempt to create a new entry in the style table.
1249
1250
1251
1252
1253
1254
1255
1256
1257


1258
1259
1260
1261
1262
1263
1264
1249
1250
1251
1252
1253
1254
1255


1256
1257
1258
1259
1260
1261
1262
1263
1264







-
-
+
+







	return NULL;
    }

    /*
     * Allocate and intitialize a new style.
     */

    stylePtr = ckalloc(sizeof(Style));
    InitStyle(stylePtr, Tcl_GetHashKey(&tsdPtr->styleTable, entryPtr),
    stylePtr = (Style *)ckalloc(sizeof(Style));
    InitStyle(stylePtr, (const char *)Tcl_GetHashKey(&tsdPtr->styleTable, entryPtr),
	    (engine!=NULL ? (StyleEngine*) engine : tsdPtr->defaultEnginePtr),
	    clientData);
    Tcl_SetHashValue(entryPtr, stylePtr);

    return (Tk_Style) stylePtr;
}

1340
1341
1342
1343
1344
1345
1346
1347

1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367

1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382

1383
1384
1385
1386
1387
1388
1389
1340
1341
1342
1343
1344
1345
1346

1347
1348
1349

1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363



1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378

1379
1380
1381
1382
1383
1384
1385
1386







-
+


-














-
-
-
+














-
+








Tk_Style
Tk_GetStyle(
    Tcl_Interp *interp,		/* Interp for error return. */
    const char *name)		/* Name of the style to retrieve. NULL or empty
				 * means the default system style. */
{
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    Tcl_HashEntry *entryPtr;
    Style *stylePtr;

    /*
     * Search for a corresponding entry in the style table.
     */

    entryPtr = Tcl_FindHashEntry(&tsdPtr->styleTable, (name!=NULL?name:""));
    if (entryPtr == NULL) {
	if (interp != NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "style \"%s\" doesn't exist", name));
	    Tcl_SetErrorCode(interp, "TK", "LOOKUP", "STYLE", name, NULL);
	}
	return NULL;
    }
    stylePtr = Tcl_GetHashValue(entryPtr);

    return (Tk_Style) stylePtr;
    return (Tk_Style)Tcl_GetHashValue(entryPtr);
}

/*
 *---------------------------------------------------------------------------
 *
 * Tk_FreeStyle --
 *
 *	No-op. Present only for stubs compatibility.
 *
 *---------------------------------------------------------------------------
 */

void
Tk_FreeStyle(
    Tk_Style style)
    TCL_UNUSED(Tk_Style))
{
}

/*
 *---------------------------------------------------------------------------
 *
 * Tk_AllocStyleFromObj --
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411

1412
1413
1414
1415
1416
1417



1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445

1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473


1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487

1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498




1499
1500

1501
1502
1503
1504
1505
1506
1507
1398
1399
1400
1401
1402
1403
1404


1405

1406






1407
1408
1409




























1410















1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421


1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454

1455
1456
1457
1458
1459
1460
1461
1462







-
-

-
+
-
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-











-
-
+
+














+











+
+
+
+

-
+








Tk_Style
Tk_AllocStyleFromObj(
    Tcl_Interp *interp,		/* Interp for error return. */
    Tcl_Obj *objPtr)		/* Object containing name of the style to
				 * retrieve. */
{
    Style *stylePtr;

    if (objPtr->typePtr != &styleObjType) {
	SetStyleFromAny(interp, objPtr);
	if (SetStyleFromAny(interp, objPtr) != TCL_OK) {
    }
    stylePtr = objPtr->internalRep.twoPtrValue.ptr1;

    return (Tk_Style) stylePtr;
}

	    return NULL;
	}
    }
/*
 *----------------------------------------------------------------------
 *
 * Tk_GetStyleFromObj --
 *
 *	Find the style that corresponds to a given object. The style must have
 *	already been created by Tk_CreateStyle.
 *
 * Results:
 *	The return value is a token for the style that matches objPtr, or NULL
 *	if none found.
 *
 * Side effects:
 *	If the object is not already a style ref, the conversion will free any
 *	old internal representation.
 *
 *----------------------------------------------------------------------
 */

Tk_Style
Tk_GetStyleFromObj(
    Tcl_Obj *objPtr)		/* The object from which to get the style. */
{
    if (objPtr->typePtr != &styleObjType) {
	SetStyleFromAny(NULL, objPtr);
    }

    return objPtr->internalRep.twoPtrValue.ptr1;
    return (Tk_Style)objPtr->internalRep.twoPtrValue.ptr1;
}

/*
 *---------------------------------------------------------------------------
 *
 * Tk_FreeStyleFromObj --
 *
 *	No-op. Present only for stubs compatibility.
 *
 *---------------------------------------------------------------------------
 */
void
Tk_FreeStyleFromObj(
    Tcl_Obj *objPtr)
{
}

/*
 *----------------------------------------------------------------------
 *
 * SetStyleFromAny --
 *
 *	Convert the internal representation of a Tcl object to the style
 *	internal form.
 *
 * Results:
 *	Always returns TCL_OK. If an error occurs is returned (e.g. the style
 *	doesn't exist), an error message will be left in interp's result.
 *	If an error occurs is returned (e.g. the style doesn't exist), an
 *	error message will be left in interp's result and TCL_ERROR is returned.
 *
 * Side effects:
 *	The object is left with its typePtr pointing to styleObjType.
 *
 *----------------------------------------------------------------------
 */

static int
SetStyleFromAny(
    Tcl_Interp *interp,		/* Used for error reporting if not NULL. */
    Tcl_Obj *objPtr)		/* The object to convert. */
{
    const Tcl_ObjType *typePtr;
    const char *name;
    Tk_Style style;

    /*
     * Free the old internalRep before setting the new one.
     */

    name = Tcl_GetString(objPtr);
    typePtr = objPtr->typePtr;
    if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
	typePtr->freeIntRepProc(objPtr);
    }

    style = Tk_GetStyle(interp, name);
    if (style == NULL) {
    	return TCL_ERROR;
    }
    objPtr->typePtr = &styleObjType;
    objPtr->internalRep.twoPtrValue.ptr1 = Tk_GetStyle(interp, name);
    objPtr->internalRep.twoPtrValue.ptr1 = style;

    return TCL_OK;
}

/*
 *---------------------------------------------------------------------------
 *
Changes to generic/tkTest.c.
1
2
3
4
5
6
7
8
9
10
11



12
13
14
15
16
17
18
1
2
3
4
5
6
7
8



9
10
11
12
13
14
15
16
17
18








-
-
-
+
+
+







/*
 * tkTest.c --
 *
 *	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.
 */

#undef STATIC_BUILD
#ifndef USE_TCL_STUBS
27
28
29
30
31
32
33
34

35
36

37
38
39
40
41
42
43
44
45
46
47
48
49
50



51




52
53

54
55
56
57


58
59
60
61
62
63

64
65
66
67
68
69
70
71

72
73


74
75
76
77
78
79
80
81
82

83
84
85
86
87
88
89
27
28
29
30
31
32
33

34
35

36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

60
61
62


63
64
65
66
67
68
69

70
71
72
73
74
75
76
77

78
79
80
81
82
83
84
85
86
87
88
89
90

91
92
93
94
95
96
97
98







-
+

-
+














+
+
+

+
+
+
+

-
+


-
-
+
+





-
+







-
+


+
+








-
+







#ifdef _WIN32
#include "tkWinInt.h"
#endif

#if defined(MAC_OSX_TK)
#include "tkMacOSXInt.h"
#include "tkScrollbar.h"
#define LOG_DISPLAY TkTestLogDisplay()
#define LOG_DISPLAY(drawable) TkTestLogDisplay(drawable)
#else
#define LOG_DISPLAY 1
#define LOG_DISPLAY(drawable) 1
#endif

#ifdef __UNIX__
#include "tkUnixInt.h"
#endif

/*
 * TCL_STORAGE_CLASS is set unconditionally to DLLEXPORT because the
 * Tcltest_Init declaration is in the source file itself, which is only
 * accessed when we are building a library.
 */

#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLEXPORT
#ifdef __cplusplus
extern "C" {
#endif
EXTERN int		Tktest_Init(Tcl_Interp *interp);
#ifdef __cplusplus
}
#endif

/*
 * The following data structure represents the master for a test image:
 * The following data structure represents the model for a test image:
 */

typedef struct TImageMaster {
    Tk_ImageMaster master;	/* Tk's token for image master. */
typedef struct TImageModel {
    Tk_ImageModel model;	/* Tk's token for image model. */
    Tcl_Interp *interp;		/* Interpreter for application. */
    int width, height;		/* Dimensions of image. */
    char *imageName;		/* Name of image (malloc-ed). */
    char *varName;		/* Name of variable in which to log events for
				 * image (malloc-ed). */
} TImageMaster;
} TImageModel;

/*
 * The following data structure represents a particular use of a particular
 * test image.
 */

typedef struct TImageInstance {
    TImageMaster *masterPtr;	/* Pointer to master for image. */
    TImageModel *modelPtr;	/* Pointer to model for image. */
    XColor *fg;			/* Foreground color for drawing in image. */
    GC gc;			/* Graphics context for drawing in image. */
    Bool displayFailed;         /* macOS display attempted out of drawRect. */
    char buffer[200 + TCL_INTEGER_SPACE * 6]; /* message to log on display. */
} TImageInstance;

/*
 * The type record for test images:
 */

static int		ImageCreate(Tcl_Interp *interp,
			    const char *name, int argc, Tcl_Obj *const objv[],
			    const Tk_ImageType *typePtr, Tk_ImageMaster master,
			    const Tk_ImageType *typePtr, Tk_ImageModel model,
			    ClientData *clientDataPtr);
static ClientData	ImageGet(Tk_Window tkwin, ClientData clientData);
static void		ImageDisplay(ClientData clientData,
			    Display *display, Drawable drawable,
			    int imageX, int imageY, int width,
			    int height, int drawableX,
			    int drawableY);
175
176
177
178
179
180
181
182

183
184
185
186
187

188
189
190

191
192
193

194
195
196



197
198
199
200
201
202
203
204
205
206
207
208



209
210
211
212
213
214
215
184
185
186
187
188
189
190

191





192



193



194

195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221







-
+
-
-
-
-
-
+
-
-
-
+
-
-
-
+
-


+
+
+












+
+
+







static int		TestmetricsObjCmd(ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj * const objv[]);
#endif
static int		TestobjconfigObjCmd(ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj * const objv[]);
static int		CustomOptionSet(ClientData clientData,
static Tk_CustomOptionSetProc CustomOptionSet;
			    Tcl_Interp *interp, Tk_Window tkwin,
			    Tcl_Obj **value, char *recordPtr,
			    int internalOffset, char *saveInternalPtr,
			    int flags);
static Tcl_Obj *	CustomOptionGet(ClientData clientData,
static Tk_CustomOptionGetProc CustomOptionGet;
			    Tk_Window tkwin, char *recordPtr,
			    int internalOffset);
static void		CustomOptionRestore(ClientData clientData,
static Tk_CustomOptionRestoreProc CustomOptionRestore;
			    Tk_Window tkwin, char *internalPtr,
			    char *saveInternalPtr);
static void		CustomOptionFree(ClientData clientData,
static Tk_CustomOptionFreeProc CustomOptionFree;
			    Tk_Window tkwin, char *internalPtr);
static int		TestpropObjCmd(ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj * const objv[]);
static int		TestprintfObjCmd(ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj * const objv[]);
#if !(defined(_WIN32) || defined(MAC_OSX_TK) || defined(__CYGWIN__))
static int		TestwrapperObjCmd(ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj * const objv[]);
#endif
static void		TrivialCmdDeletedProc(ClientData clientData);
static int		TrivialConfigObjCmd(ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj * const objv[]);
static void		TrivialEventProc(ClientData clientData,
			    XEvent *eventPtr);
static int              TestPhotoStringMatchCmd(ClientData dummy,
                            Tcl_Interp *interp, int objc,
                            Tcl_Obj * const objv[]);

/*
 *----------------------------------------------------------------------
 *
 * Tktest_Init --
 *
 *	This function performs initialization for the Tk test suite extensions.
226
227
228
229
230
231
232
233

234
235
236
237
238
239
240
241
242
243
244
245


246
247
248
249
250
251
252
232
233
234
235
236
237
238

239
240
241
242
243
244
245
246
247
248
249


250
251
252
253
254
255
256
257
258







-
+










-
-
+
+








int
Tktest_Init(
    Tcl_Interp *interp)		/* Interpreter for application. */
{
    static int initialized = 0;

    if (Tcl_InitStubs(interp, "8.1", 0) == NULL) {
    if (Tcl_InitStubs(interp, "8.6-", 0) == NULL) {
	return TCL_ERROR;
    }
    if (Tk_InitStubs(interp, TK_VERSION, 0) == NULL) {
	return TCL_ERROR;
    }

    /*
     * Create additional commands for testing Tk.
     */

    if (Tcl_PkgProvideEx(interp, "Tktest", TK_PATCH_LEVEL, NULL) == TCL_ERROR) {
        return 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,
	    (ClientData) Tk_MainWindow(interp), NULL);
    Tcl_CreateObjCommand(interp, "testborder", TestborderObjCmd,
	    (ClientData) Tk_MainWindow(interp), NULL);
262
263
264
265
266
267
268

269
270



271
272
273
274
275
276
277
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287







+


+
+
+







	    (ClientData) Tk_MainWindow(interp), NULL);
    Tcl_CreateObjCommand(interp, "testfont", TestfontObjCmd,
	    (ClientData) Tk_MainWindow(interp), NULL);
    Tcl_CreateObjCommand(interp, "testmakeexist", TestmakeexistObjCmd,
	    (ClientData) Tk_MainWindow(interp), NULL);
    Tcl_CreateObjCommand(interp, "testprop", TestpropObjCmd,
	    (ClientData) Tk_MainWindow(interp), NULL);
    Tcl_CreateObjCommand(interp, "testprintf", TestprintfObjCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "testtext", TkpTesttextCmd,
	    (ClientData) Tk_MainWindow(interp), NULL);
    Tcl_CreateObjCommand(interp, "testphotostringmatch",
            TestPhotoStringMatchCmd, (ClientData) Tk_MainWindow(interp),
            NULL);

#if defined(_WIN32)
    Tcl_CreateObjCommand(interp, "testmetrics", TestmetricsObjCmd,
	    (ClientData) Tk_MainWindow(interp), NULL);
#elif !defined(__CYGWIN__) && !defined(MAC_OSX_TK)
    Tcl_CreateObjCommand(interp, "testmenubar", TestmenubarObjCmd,
	    (ClientData) Tk_MainWindow(interp), NULL);
318
319
320
321
322
323
324
325
326
327
328

329
330
331
332
333
334
335
336
337
338
339
340
328
329
330
331
332
333
334

335
336

337
338
339
340
341

342
343
344
345
346
347
348







-


-
+




-







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
TestbitmapObjCmd(
    ClientData clientData,	/* Main window for application. */
    TCL_UNUSED(void *),	/* Main window for application. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "bitmap");
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, TkDebugBitmap(Tk_MainWindow(interp),
	    Tcl_GetString(objv[1])));
    return TCL_OK;
353
354
355
356
357
358
359
360
361
362
363

364
365
366
367
368
369
370
371
372
373
374
375
361
362
363
364
365
366
367

368
369

370
371
372
373
374

375
376
377
378
379
380
381







-


-
+




-







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
TestborderObjCmd(
    ClientData clientData,	/* Main window for application. */
    TCL_UNUSED(ClientData),	/* Main window for application. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "border");
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, TkDebugBorder(Tk_MainWindow(interp),
	    Tcl_GetString(objv[1])));
    return TCL_OK;
388
389
390
391
392
393
394
395
396
397
398

399
400
401
402
403
404
405
394
395
396
397
398
399
400

401
402

403
404
405
406
407
408
409
410







-


-
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
TestcolorObjCmd(
    ClientData clientData,	/* Main window for application. */
    TCL_UNUSED(void *),	/* Main window for application. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "color");
	return TCL_ERROR;
422
423
424
425
426
427
428
429
430
431
432

433
434
435
436
437
438
439
427
428
429
430
431
432
433

434
435

436
437
438
439
440
441
442
443







-


-
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
TestcursorObjCmd(
    ClientData clientData,	/* Main window for application. */
    TCL_UNUSED(void *),	/* Main window for application. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "cursor");
	return TCL_ERROR;
451
452
453
454
455
456
457
458

459
460
461
462
463
464
465
466
467
468
469
470




471
472
473
474
475
476
477
455
456
457
458
459
460
461

462
463
464
465
466
467

468
469




470
471
472
473
474
475
476
477
478
479
480







-
+





-


-
-
-
-
+
+
+
+







 *	This function implements the "testdeleteapps" command. It cleans up
 *	all the interpreters left behind by the "testnewapp" command.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	All the intepreters created by previous calls to "testnewapp" get
 *	All the interpreters created by previous calls to "testnewapp" get
 *	deleted.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
TestdeleteappsObjCmd(
    ClientData clientData,	/* Main window for application. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])		/* Argument strings. */
    TCL_UNUSED(void *),	/* Main window for application. */
    TCL_UNUSED(Tcl_Interp *),		/* Current interpreter. */
    TCL_UNUSED(int),			/* Number of arguments. */
    TCL_UNUSED(Tcl_Obj *const *))		/* Argument strings. */
{
    NewApp *nextPtr;

    while (newAppPtr != NULL) {
	nextPtr = newAppPtr->nextPtr;
	Tcl_DeleteInterp(newAppPtr->interp);
	ckfree(newAppPtr);
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
497
498
499
500
501
502
503

504
505
506
507
508
509
510







-







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
TestobjconfigObjCmd(
    ClientData clientData,	/* Main window for application. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
523
524
525
526
527
528
529
530

531
532
533
534
535
536
537
538
539

540
541
542
543
544
545
546
547
548
549

550
551

552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567

568
569
570
571
572
573
574
525
526
527
528
529
530
531

532
533
534
535
536
537
538
539
540

541
542
543
544
545
546
547
548
549
550

551
552

553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568

569
570
571
572
573
574
575
576







-
+








-
+









-
+

-
+















-
+







	"custom option",
	CustomOptionSet,
	CustomOptionGet,
	CustomOptionRestore,
	CustomOptionFree,
	INT2PTR(1)
    };
    Tk_Window mainWin = (Tk_Window) clientData;
    Tk_Window mainWin = (Tk_Window)clientData;
    Tk_Window tkwin;
    int index, result = TCL_OK;

    /*
     * Structures used by the "chain1" subcommand and also shared by the
     * "chain2" subcommand:
     */

    typedef struct ExtensionWidgetRecord {
    typedef struct {
	TrivialCommandHeader header;
	Tcl_Obj *base1ObjPtr;
	Tcl_Obj *base2ObjPtr;
	Tcl_Obj *extension3ObjPtr;
	Tcl_Obj *extension4ObjPtr;
	Tcl_Obj *extension5ObjPtr;
    } ExtensionWidgetRecord;
    static const Tk_OptionSpec baseSpecs[] = {
	{TK_OPTION_STRING, "-one", "one", "One", "one",
		Tk_Offset(ExtensionWidgetRecord, base1ObjPtr), -1, 0, NULL, 0},
		offsetof(ExtensionWidgetRecord, base1ObjPtr), TCL_INDEX_NONE, 0, NULL, 0},
	{TK_OPTION_STRING, "-two", "two", "Two", "two",
		Tk_Offset(ExtensionWidgetRecord, base2ObjPtr), -1, 0, NULL, 0},
		offsetof(ExtensionWidgetRecord, base2ObjPtr), TCL_INDEX_NONE, 0, NULL, 0},
	{TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0}
    };

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "command");
	return TCL_ERROR;
    }

    if (Tcl_GetIndexFromObjStruct(interp, objv[1], options,
	    sizeof(char *), "command", 0, &index)!= TCL_OK) {
	return TCL_ERROR;
    }

    switch (index) {
    case ALL_TYPES: {
	typedef struct TypesRecord {
	typedef struct {
	    TrivialCommandHeader header;
	    Tcl_Obj *booleanPtr;
	    Tcl_Obj *integerPtr;
	    Tcl_Obj *doublePtr;
	    Tcl_Obj *stringPtr;
	    Tcl_Obj *stringTablePtr;
	    Tcl_Obj *colorPtr;
586
587
588
589
590
591
592
593

594
595

596
597

598
599

600
601
602
603

604
605
606

607
608
609

610
611
612

613
614
615

616
617
618

619
620
621

622
623
624

625
626
627

628
629
630

631
632
633

634
635
636

637
638
639
640
641
642
643
644

645
646
647
648
649
650
651

652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671

672
673
674
675
676
677
678
679

680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699

700
701
702
703
704
705
706
707
708

709
710
711
712
713
714

715
716

717
718
719

720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738

739
740

741
742

743
744
745
746


747
748
749
750
751
752

753
754
755
756
757
758
759
760
761

762
763
764
765
766
767
768

769
770

771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788

789
790
791
792
793
794

795
796
797
798
799
800
801
802

803
804
805
806
807
808
809
588
589
590
591
592
593
594

595
596

597
598

599
600

601
602
603
604

605
606
607

608
609
610

611
612
613

614
615
616

617
618
619

620
621
622

623
624
625

626
627
628

629
630
631

632
633
634

635
636
637

638
639
640
641

642
643
644

645
646
647
648
649
650
651

652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671

672
673
674
675
676
677
678
679

680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696

697
698

699
700
701
702
703
704
705
706
707

708
709
710
711
712
713

714
715

716
717
718

719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737

738
739

740
741

742
743
744


745
746
747
748

749
750

751
752
753
754
755
756
757
758
759

760
761
762
763
764
765
766

767
768

769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786

787
788
789
790
791
792

793
794
795
796
797
798
799
800

801
802
803
804
805
806
807
808







-
+

-
+

-
+

-
+



-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+



-



-
+






-
+



















-
+







-
+
















-


-
+








-
+





-
+

-
+


-
+


















-
+

-
+

-
+


-
-
+
+


-


-
+








-
+






-
+

-
+

















-
+





-
+







-
+







	} TypesRecord;
	TypesRecord *recordPtr;
	static const char *const stringTable[] = {
	    "one", "two", "three", "four", NULL
	};
	static const Tk_OptionSpec typesSpecs[] = {
	    {TK_OPTION_BOOLEAN, "-boolean", "boolean", "Boolean", "1",
		Tk_Offset(TypesRecord, booleanPtr), -1, 0, 0, 0x1},
		offsetof(TypesRecord, booleanPtr), TCL_INDEX_NONE, 0, 0, 0x1},
	    {TK_OPTION_INT, "-integer", "integer", "Integer", "7",
		Tk_Offset(TypesRecord, integerPtr), -1, 0, 0, 0x2},
		offsetof(TypesRecord, integerPtr), TCL_INDEX_NONE, 0, 0, 0x2},
	    {TK_OPTION_DOUBLE, "-double", "double", "Double", "3.14159",
		Tk_Offset(TypesRecord, doublePtr), -1, 0, 0, 0x4},
		offsetof(TypesRecord, doublePtr), TCL_INDEX_NONE, 0, 0, 0x4},
	    {TK_OPTION_STRING, "-string", "string", "String",
		"foo", Tk_Offset(TypesRecord, stringPtr), -1,
		"foo", offsetof(TypesRecord, stringPtr), TCL_INDEX_NONE,
		TK_CONFIG_NULL_OK, 0, 0x8},
	    {TK_OPTION_STRING_TABLE,
		"-stringtable", "StringTable", "stringTable",
		"one", Tk_Offset(TypesRecord, stringTablePtr), -1,
		"one", offsetof(TypesRecord, stringTablePtr), TCL_INDEX_NONE,
		TK_CONFIG_NULL_OK, stringTable, 0x10},
	    {TK_OPTION_COLOR, "-color", "color", "Color",
		"red", Tk_Offset(TypesRecord, colorPtr), -1,
		"red", offsetof(TypesRecord, colorPtr), TCL_INDEX_NONE,
		TK_CONFIG_NULL_OK, "black", 0x20},
	    {TK_OPTION_FONT, "-font", "font", "Font", "Helvetica 12",
		Tk_Offset(TypesRecord, fontPtr), -1,
		offsetof(TypesRecord, fontPtr), TCL_INDEX_NONE,
		TK_CONFIG_NULL_OK, 0, 0x40},
	    {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap", "gray50",
		Tk_Offset(TypesRecord, bitmapPtr), -1,
		offsetof(TypesRecord, bitmapPtr), TCL_INDEX_NONE,
		TK_CONFIG_NULL_OK, 0, 0x80},
	    {TK_OPTION_BORDER, "-border", "border", "Border",
		"blue", Tk_Offset(TypesRecord, borderPtr), -1,
		"blue", offsetof(TypesRecord, borderPtr), TCL_INDEX_NONE,
		TK_CONFIG_NULL_OK, "white", 0x100},
	    {TK_OPTION_RELIEF, "-relief", "relief", "Relief", "raised",
		Tk_Offset(TypesRecord, reliefPtr), -1,
		offsetof(TypesRecord, reliefPtr), TCL_INDEX_NONE,
		TK_CONFIG_NULL_OK, 0, 0x200},
	    {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor", "xterm",
		Tk_Offset(TypesRecord, cursorPtr), -1,
		offsetof(TypesRecord, cursorPtr), TCL_INDEX_NONE,
		TK_CONFIG_NULL_OK, 0, 0x400},
	    {TK_OPTION_JUSTIFY, "-justify", NULL, NULL, "left",
		Tk_Offset(TypesRecord, justifyPtr), -1,
		offsetof(TypesRecord, justifyPtr), TCL_INDEX_NONE,
		TK_CONFIG_NULL_OK, 0, 0x800},
	    {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor", NULL,
		Tk_Offset(TypesRecord, anchorPtr), -1,
		offsetof(TypesRecord, anchorPtr), TCL_INDEX_NONE,
		TK_CONFIG_NULL_OK, 0, 0x1000},
	    {TK_OPTION_PIXELS, "-pixel", "pixel", "Pixel",
		"1", Tk_Offset(TypesRecord, pixelPtr), -1,
		"1", offsetof(TypesRecord, pixelPtr), TCL_INDEX_NONE,
		TK_CONFIG_NULL_OK, 0, 0x2000},
	    {TK_OPTION_CUSTOM, "-custom", NULL, NULL,
		"", Tk_Offset(TypesRecord, customPtr), -1,
		"", offsetof(TypesRecord, customPtr), TCL_INDEX_NONE,
		TK_CONFIG_NULL_OK, &CustomOption, 0x4000},
	    {TK_OPTION_SYNONYM, "-synonym", NULL, NULL,
		NULL, 0, -1, 0, "-color", 0x8000},
		NULL, 0, TCL_INDEX_NONE, 0, "-color", 0x8000},
	    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0}
	};
	Tk_OptionTable optionTable;
	Tk_Window tkwin;

	optionTable = Tk_CreateOptionTable(interp, typesSpecs);
	tables[index] = optionTable;
	tkwin = Tk_CreateWindowFromPath(interp, (Tk_Window) clientData,
	tkwin = Tk_CreateWindowFromPath(interp, (Tk_Window)clientData,
		Tcl_GetString(objv[2]), NULL);
	if (tkwin == NULL) {
	    return TCL_ERROR;
	}
	Tk_SetClass(tkwin, "Test");

	recordPtr = ckalloc(sizeof(TypesRecord));
	recordPtr = (TypesRecord *)ckalloc(sizeof(TypesRecord));
	recordPtr->header.interp = interp;
	recordPtr->header.optionTable = optionTable;
	recordPtr->header.tkwin = tkwin;
	recordPtr->booleanPtr = NULL;
	recordPtr->integerPtr = NULL;
	recordPtr->doublePtr = NULL;
	recordPtr->stringPtr = NULL;
	recordPtr->colorPtr = NULL;
	recordPtr->fontPtr = NULL;
	recordPtr->bitmapPtr = NULL;
	recordPtr->borderPtr = NULL;
	recordPtr->reliefPtr = NULL;
	recordPtr->cursorPtr = NULL;
	recordPtr->justifyPtr = NULL;
	recordPtr->anchorPtr = NULL;
	recordPtr->pixelPtr = NULL;
	recordPtr->mmPtr = NULL;
	recordPtr->stringTablePtr = NULL;
	recordPtr->customPtr = NULL;
	result = Tk_InitOptions(interp, (char *) recordPtr, optionTable,
	result = Tk_InitOptions(interp, recordPtr, optionTable,
		tkwin);
	if (result == TCL_OK) {
	    recordPtr->header.widgetCmd = Tcl_CreateObjCommand(interp,
		    Tcl_GetString(objv[2]), TrivialConfigObjCmd,
		    (ClientData) recordPtr, TrivialCmdDeletedProc);
	    Tk_CreateEventHandler(tkwin, StructureNotifyMask,
		    TrivialEventProc, (ClientData) recordPtr);
	    result = Tk_SetOptions(interp, (char *) recordPtr, optionTable,
	    result = Tk_SetOptions(interp, recordPtr, optionTable,
		    objc-3, objv+3, tkwin, NULL, NULL);
	    if (result != TCL_OK) {
		Tk_DestroyWindow(tkwin);
	    }
	} else {
	    Tk_DestroyWindow(tkwin);
	    ckfree(recordPtr);
	}
	if (result == TCL_OK) {
	    Tcl_SetObjResult(interp, objv[2]);
	}
	break;
    }

    case CHAIN1: {
	ExtensionWidgetRecord *recordPtr;
	Tk_Window tkwin;
	Tk_OptionTable optionTable;

	tkwin = Tk_CreateWindowFromPath(interp, (Tk_Window) clientData,
	tkwin = Tk_CreateWindowFromPath(interp, (Tk_Window)clientData,
		Tcl_GetString(objv[2]), NULL);
	if (tkwin == NULL) {
	    return TCL_ERROR;
	}
	Tk_SetClass(tkwin, "Test");
	optionTable = Tk_CreateOptionTable(interp, baseSpecs);
	tables[index] = optionTable;

	recordPtr = ckalloc(sizeof(ExtensionWidgetRecord));
	recordPtr = (ExtensionWidgetRecord *)ckalloc(sizeof(ExtensionWidgetRecord));
	recordPtr->header.interp = interp;
	recordPtr->header.optionTable = optionTable;
	recordPtr->header.tkwin = tkwin;
	recordPtr->base1ObjPtr = recordPtr->base2ObjPtr = NULL;
	recordPtr->extension3ObjPtr = recordPtr->extension4ObjPtr = NULL;
	result = Tk_InitOptions(interp, (char *)recordPtr, optionTable, tkwin);
	result = Tk_InitOptions(interp, recordPtr, optionTable, tkwin);
	if (result == TCL_OK) {
	    result = Tk_SetOptions(interp, (char *) recordPtr, optionTable,
	    result = Tk_SetOptions(interp, recordPtr, optionTable,
		    objc-3, objv+3, tkwin, NULL, NULL);
	    if (result != TCL_OK) {
		Tk_FreeConfigOptions((char *) recordPtr, optionTable, tkwin);
		Tk_FreeConfigOptions(recordPtr, optionTable, tkwin);
	    }
	}
	if (result == TCL_OK) {
	    recordPtr->header.widgetCmd = Tcl_CreateObjCommand(interp,
		    Tcl_GetString(objv[2]), TrivialConfigObjCmd,
		    (ClientData) recordPtr, TrivialCmdDeletedProc);
	    Tk_CreateEventHandler(tkwin, StructureNotifyMask,
		    TrivialEventProc, (ClientData) recordPtr);
	    Tcl_SetObjResult(interp, objv[2]);
	}
	break;
    }

    case CHAIN2:
    case CHAIN3: {
	ExtensionWidgetRecord *recordPtr;
	static const Tk_OptionSpec extensionSpecs[] = {
	    {TK_OPTION_STRING, "-three", "three", "Three", "three",
		Tk_Offset(ExtensionWidgetRecord, extension3ObjPtr), -1, 0, NULL, 0},
		offsetof(ExtensionWidgetRecord, extension3ObjPtr), TCL_INDEX_NONE, 0, NULL, 0},
	    {TK_OPTION_STRING, "-four", "four", "Four", "four",
		Tk_Offset(ExtensionWidgetRecord, extension4ObjPtr), -1, 0, NULL, 0},
		offsetof(ExtensionWidgetRecord, extension4ObjPtr), TCL_INDEX_NONE, 0, NULL, 0},
	    {TK_OPTION_STRING, "-two", "two", "Two", "two and a half",
		Tk_Offset(ExtensionWidgetRecord, base2ObjPtr), -1, 0, NULL, 0},
		offsetof(ExtensionWidgetRecord, base2ObjPtr), TCL_INDEX_NONE, 0, NULL, 0},
	    {TK_OPTION_STRING,
		"-oneAgain", "oneAgain", "OneAgain", "one again",
		Tk_Offset(ExtensionWidgetRecord, extension5ObjPtr), -1, 0, NULL, 0},
	    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0,
		offsetof(ExtensionWidgetRecord, extension5ObjPtr), TCL_INDEX_NONE, 0, NULL, 0},
	    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, TCL_INDEX_NONE, 0,
		(ClientData) baseSpecs, 0}
	};
	Tk_Window tkwin;
	Tk_OptionTable optionTable;

	tkwin = Tk_CreateWindowFromPath(interp, (Tk_Window) clientData,
	tkwin = Tk_CreateWindowFromPath(interp, (Tk_Window)clientData,
		Tcl_GetString(objv[2]), NULL);
	if (tkwin == NULL) {
	    return TCL_ERROR;
	}
	Tk_SetClass(tkwin, "Test");
	optionTable = Tk_CreateOptionTable(interp, extensionSpecs);
	tables[index] = optionTable;

	recordPtr = ckalloc(sizeof(ExtensionWidgetRecord));
	recordPtr = (ExtensionWidgetRecord *)ckalloc(sizeof(ExtensionWidgetRecord));
	recordPtr->header.interp = interp;
	recordPtr->header.optionTable = optionTable;
	recordPtr->header.tkwin = tkwin;
	recordPtr->base1ObjPtr = recordPtr->base2ObjPtr = NULL;
	recordPtr->extension3ObjPtr = recordPtr->extension4ObjPtr = NULL;
	recordPtr->extension5ObjPtr = NULL;
	result = Tk_InitOptions(interp, (char *)recordPtr, optionTable, tkwin);
	result = Tk_InitOptions(interp, recordPtr, optionTable, tkwin);
	if (result == TCL_OK) {
	    result = Tk_SetOptions(interp, (char *) recordPtr, optionTable,
	    result = Tk_SetOptions(interp, recordPtr, optionTable,
		    objc-3, objv+3, tkwin, NULL, NULL);
	    if (result != TCL_OK) {
		Tk_FreeConfigOptions((char *) recordPtr, optionTable, tkwin);
	    }
	}
	if (result == TCL_OK) {
	    recordPtr->header.widgetCmd = Tcl_CreateObjCommand(interp,
		    Tcl_GetString(objv[2]), TrivialConfigObjCmd,
		    (ClientData) recordPtr, TrivialCmdDeletedProc);
	    Tk_CreateEventHandler(tkwin, StructureNotifyMask,
		    TrivialEventProc, (ClientData) recordPtr);
	    Tcl_SetObjResult(interp, objv[2]);
	}
	break;
    }

    case CONFIG_ERROR: {
	typedef struct ErrorWidgetRecord {
	typedef struct {
	    Tcl_Obj *intPtr;
	} ErrorWidgetRecord;
	ErrorWidgetRecord widgetRecord;
	static const Tk_OptionSpec errorSpecs[] = {
	    {TK_OPTION_INT, "-int", "integer", "Integer", "bogus",
		Tk_Offset(ErrorWidgetRecord, intPtr), 0, 0, NULL, 0},
		offsetof(ErrorWidgetRecord, intPtr), 0, 0, NULL, 0},
	    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0}
	};
	Tk_OptionTable optionTable;

	widgetRecord.intPtr = NULL;
	optionTable = Tk_CreateOptionTable(interp, errorSpecs);
	tables[index] = optionTable;
	return Tk_InitOptions(interp, (char *) &widgetRecord, optionTable,
	return Tk_InitOptions(interp, &widgetRecord, optionTable,
		(Tk_Window) NULL);
    }

    case DEL:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "tableName");
	    return TCL_ERROR;
835
836
837
838
839
840
841
842

843
844
845
846
847
848
849
834
835
836
837
838
839
840

841
842
843
844
845
846
847
848







-
+







    case INTERNAL: {
	/*
	 * This command is similar to the "alltypes" command except that it
	 * stores all the configuration options as internal forms instead of
	 * objects.
	 */

	typedef struct InternalRecord {
	typedef struct {
	    TrivialCommandHeader header;
	    int boolean;
	    int integer;
	    double doubleValue;
	    char *string;
	    int index;
	    XColor *colorPtr;
861
862
863
864
865
866
867
868

869
870

871
872

873
874

875
876
877
878

879
880
881

882
883
884

885
886
887

888
889
890

891
892
893

894
895
896

897
898
899

900
901
902

903
904
905

906
907
908

909
910
911

912
913
914

915
916
917
918
919
920
921
922

923
924
925
926
927
928
929

930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950

951
952
953
954
955
956
957
958

959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974

975
976
977
978
979
980
981
982
983
984
985

986
987

988
989

990
991

992
993

994
995
996
997
998
999
1000
1001
1002

1003
1004
1005
1006
1007
1008
1009
1010
1011

1012
1013
1014

1015
1016
1017
1018
1019
1020
1021
1022

1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033

1034
1035
1036
1037
1038
1039

1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052


1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063

1064
1065
1066
1067
1068



1069
1070

1071
1072
1073
1074


1075
1076
1077
1078
1079
1080
1081

1082
1083
1084

1085
1086
1087
1088
1089

1090
1091
1092

1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103

1104
1105
1106
1107
1108
1109
1110
860
861
862
863
864
865
866

867
868

869
870

871
872

873
874
875
876

877
878
879

880
881
882

883
884
885

886
887
888

889
890
891

892
893
894

895
896
897

898
899
900

901
902
903

904
905
906

907
908
909

910
911
912

913
914
915
916

917
918
919

920
921
922
923
924
925
926

927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947

948
949
950
951
952
953
954
955

956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971

972
973
974
975
976
977
978
979
980
981
982

983
984

985
986

987
988

989
990

991
992
993
994
995
996
997
998
999

1000
1001
1002
1003
1004
1005
1006
1007
1008

1009
1010
1011

1012
1013
1014
1015
1016
1017
1018
1019

1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030

1031
1032
1033
1034
1035
1036

1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048


1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060

1061
1062
1063



1064
1065
1066
1067

1068
1069
1070


1071
1072
1073
1074
1075
1076
1077
1078

1079
1080
1081

1082
1083
1084
1085
1086

1087
1088
1089

1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100

1101
1102
1103
1104
1105
1106
1107
1108







-
+

-
+

-
+

-
+



-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+



-



-
+






-
+




















-
+







-
+















-
+










-
+

-
+

-
+

-
+

-
+








-
+








-
+


-
+







-
+










-
+





-
+











-
-
+
+










-
+


-
-
-
+
+
+

-
+


-
-
+
+






-
+


-
+




-
+


-
+










-
+







	} InternalRecord;
	InternalRecord *recordPtr;
	static const char *const internalStringTable[] = {
	    "one", "two", "three", "four", NULL
	};
	static const Tk_OptionSpec internalSpecs[] = {
	    {TK_OPTION_BOOLEAN, "-boolean", "boolean", "Boolean", "1",
		-1, Tk_Offset(InternalRecord, boolean), 0, 0, 0x1},
		TCL_INDEX_NONE, offsetof(InternalRecord, boolean), 0, 0, 0x1},
	    {TK_OPTION_INT, "-integer", "integer", "Integer", "148962237",
		-1, Tk_Offset(InternalRecord, integer), 0, 0, 0x2},
		TCL_INDEX_NONE, offsetof(InternalRecord, integer), 0, 0, 0x2},
	    {TK_OPTION_DOUBLE, "-double", "double", "Double", "3.14159",
		-1, Tk_Offset(InternalRecord, doubleValue), 0, 0, 0x4},
		TCL_INDEX_NONE, offsetof(InternalRecord, doubleValue), 0, 0, 0x4},
	    {TK_OPTION_STRING, "-string", "string", "String", "foo",
		-1, Tk_Offset(InternalRecord, string),
		TCL_INDEX_NONE, offsetof(InternalRecord, string),
		TK_CONFIG_NULL_OK, 0, 0x8},
	    {TK_OPTION_STRING_TABLE,
		"-stringtable", "StringTable", "stringTable", "one",
		-1, Tk_Offset(InternalRecord, index),
		TCL_INDEX_NONE, offsetof(InternalRecord, index),
		TK_CONFIG_NULL_OK, internalStringTable, 0x10},
	    {TK_OPTION_COLOR, "-color", "color", "Color", "red",
		-1, Tk_Offset(InternalRecord, colorPtr),
		TCL_INDEX_NONE, offsetof(InternalRecord, colorPtr),
		TK_CONFIG_NULL_OK, "black", 0x20},
	    {TK_OPTION_FONT, "-font", "font", "Font", "Helvetica 12",
		-1, Tk_Offset(InternalRecord, tkfont),
		TCL_INDEX_NONE, offsetof(InternalRecord, tkfont),
		TK_CONFIG_NULL_OK, 0, 0x40},
	    {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap", "gray50",
		-1, Tk_Offset(InternalRecord, bitmap),
		TCL_INDEX_NONE, offsetof(InternalRecord, bitmap),
		TK_CONFIG_NULL_OK, 0, 0x80},
	    {TK_OPTION_BORDER, "-border", "border", "Border", "blue",
		-1, Tk_Offset(InternalRecord, border),
		TCL_INDEX_NONE, offsetof(InternalRecord, border),
		TK_CONFIG_NULL_OK, "white", 0x100},
	    {TK_OPTION_RELIEF, "-relief", "relief", "Relief", "raised",
		-1, Tk_Offset(InternalRecord, relief),
		TCL_INDEX_NONE, offsetof(InternalRecord, relief),
		TK_CONFIG_NULL_OK, 0, 0x200},
	    {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor", "xterm",
		-1, Tk_Offset(InternalRecord, cursor),
		TCL_INDEX_NONE, offsetof(InternalRecord, cursor),
		TK_CONFIG_NULL_OK, 0, 0x400},
	    {TK_OPTION_JUSTIFY, "-justify", NULL, NULL, "left",
		-1, Tk_Offset(InternalRecord, justify),
		TCL_INDEX_NONE, offsetof(InternalRecord, justify),
		TK_CONFIG_NULL_OK, 0, 0x800},
	    {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor", NULL,
		-1, Tk_Offset(InternalRecord, anchor),
		TCL_INDEX_NONE, offsetof(InternalRecord, anchor),
		TK_CONFIG_NULL_OK, 0, 0x1000},
	    {TK_OPTION_PIXELS, "-pixel", "pixel", "Pixel", "1",
		-1, Tk_Offset(InternalRecord, pixels),
		TCL_INDEX_NONE, offsetof(InternalRecord, pixels),
		TK_CONFIG_NULL_OK, 0, 0x2000},
	    {TK_OPTION_WINDOW, "-window", "window", "Window", NULL,
		-1, Tk_Offset(InternalRecord, tkwin),
		TCL_INDEX_NONE, offsetof(InternalRecord, tkwin),
		TK_CONFIG_NULL_OK, 0, 0},
	    {TK_OPTION_CUSTOM, "-custom", NULL, NULL, "",
		-1, Tk_Offset(InternalRecord, custom),
		TCL_INDEX_NONE, offsetof(InternalRecord, custom),
		TK_CONFIG_NULL_OK, &CustomOption, 0x4000},
	    {TK_OPTION_SYNONYM, "-synonym", NULL, NULL,
		NULL, -1, -1, 0, "-color", 0x8000},
		NULL, TCL_INDEX_NONE, TCL_INDEX_NONE, 0, "-color", 0x8000},
	    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0}
	};
	Tk_OptionTable optionTable;
	Tk_Window tkwin;

	optionTable = Tk_CreateOptionTable(interp, internalSpecs);
	tables[index] = optionTable;
	tkwin = Tk_CreateWindowFromPath(interp, (Tk_Window) clientData,
	tkwin = Tk_CreateWindowFromPath(interp, (Tk_Window)clientData,
		Tcl_GetString(objv[2]), NULL);
	if (tkwin == NULL) {
	    return TCL_ERROR;
	}
	Tk_SetClass(tkwin, "Test");

	recordPtr = ckalloc(sizeof(InternalRecord));
	recordPtr = (InternalRecord *)ckalloc(sizeof(InternalRecord));
	recordPtr->header.interp = interp;
	recordPtr->header.optionTable = optionTable;
	recordPtr->header.tkwin = tkwin;
	recordPtr->boolean = 0;
	recordPtr->integer = 0;
	recordPtr->doubleValue = 0.0;
	recordPtr->string = NULL;
	recordPtr->index = 0;
	recordPtr->colorPtr = NULL;
	recordPtr->tkfont = NULL;
	recordPtr->bitmap = None;
	recordPtr->border = NULL;
	recordPtr->relief = TK_RELIEF_FLAT;
	recordPtr->cursor = NULL;
	recordPtr->justify = TK_JUSTIFY_LEFT;
	recordPtr->anchor = TK_ANCHOR_N;
	recordPtr->pixels = 0;
	recordPtr->mm = 0.0;
	recordPtr->tkwin = NULL;
	recordPtr->custom = NULL;
	result = Tk_InitOptions(interp, (char *) recordPtr, optionTable,
	result = Tk_InitOptions(interp, recordPtr, optionTable,
		tkwin);
	if (result == TCL_OK) {
	    recordPtr->header.widgetCmd = Tcl_CreateObjCommand(interp,
		    Tcl_GetString(objv[2]), TrivialConfigObjCmd,
		    recordPtr, TrivialCmdDeletedProc);
	    Tk_CreateEventHandler(tkwin, StructureNotifyMask,
		    TrivialEventProc, recordPtr);
	    result = Tk_SetOptions(interp, (char *) recordPtr, optionTable,
	    result = Tk_SetOptions(interp, recordPtr, optionTable,
		    objc - 3, objv + 3, tkwin, NULL, NULL);
	    if (result != TCL_OK) {
		Tk_DestroyWindow(tkwin);
	    }
	} else {
	    Tk_DestroyWindow(tkwin);
	    ckfree(recordPtr);
	}
	if (result == TCL_OK) {
	    Tcl_SetObjResult(interp, objv[2]);
	}
	break;
    }

    case NEW: {
	typedef struct FiveRecord {
	typedef struct {
	    TrivialCommandHeader header;
	    Tcl_Obj *one;
	    Tcl_Obj *two;
	    Tcl_Obj *three;
	    Tcl_Obj *four;
	    Tcl_Obj *five;
	} FiveRecord;
	FiveRecord *recordPtr;
	static const Tk_OptionSpec smallSpecs[] = {
	    {TK_OPTION_INT, "-one", "one", "One", "1",
		Tk_Offset(FiveRecord, one), -1, 0, NULL, 0},
		offsetof(FiveRecord, one), TCL_INDEX_NONE, 0, NULL, 0},
	    {TK_OPTION_INT, "-two", "two", "Two", "2",
		Tk_Offset(FiveRecord, two), -1, 0, NULL, 0},
		offsetof(FiveRecord, two), TCL_INDEX_NONE, 0, NULL, 0},
	    {TK_OPTION_INT, "-three", "three", "Three", "3",
		Tk_Offset(FiveRecord, three), -1, 0, NULL, 0},
		offsetof(FiveRecord, three), TCL_INDEX_NONE, 0, NULL, 0},
	    {TK_OPTION_INT, "-four", "four", "Four", "4",
		Tk_Offset(FiveRecord, four), -1, 0, NULL, 0},
		offsetof(FiveRecord, four), TCL_INDEX_NONE, 0, NULL, 0},
	    {TK_OPTION_STRING, "-five", NULL, NULL, NULL,
		Tk_Offset(FiveRecord, five), -1, 0, NULL, 0},
		offsetof(FiveRecord, five), TCL_INDEX_NONE, 0, NULL, 0},
	    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0}
	};

	if (objc < 3) {
	    Tcl_WrongNumArgs(interp, 1, objv, "new name ?-option value ...?");
	    return TCL_ERROR;
	}

	recordPtr = ckalloc(sizeof(FiveRecord));
	recordPtr = (FiveRecord *)ckalloc(sizeof(FiveRecord));
	recordPtr->header.interp = interp;
	recordPtr->header.optionTable = Tk_CreateOptionTable(interp,
		smallSpecs);
	tables[index] = recordPtr->header.optionTable;
	recordPtr->header.tkwin = NULL;
	recordPtr->one = recordPtr->two = recordPtr->three = NULL;
	recordPtr->four = recordPtr->five = NULL;
	Tcl_SetObjResult(interp, objv[2]);
	result = Tk_InitOptions(interp, (char *) recordPtr,
	result = Tk_InitOptions(interp, recordPtr,
		recordPtr->header.optionTable, (Tk_Window) NULL);
	if (result == TCL_OK) {
	    result = Tk_SetOptions(interp, (char *) recordPtr,
	    result = Tk_SetOptions(interp, recordPtr,
		    recordPtr->header.optionTable, objc - 3, objv + 3,
		    (Tk_Window) NULL, NULL, NULL);
	    if (result == TCL_OK) {
		recordPtr->header.widgetCmd = Tcl_CreateObjCommand(interp,
			Tcl_GetString(objv[2]), TrivialConfigObjCmd,
			(ClientData) recordPtr, TrivialCmdDeletedProc);
	    } else {
		Tk_FreeConfigOptions((char *) recordPtr,
		Tk_FreeConfigOptions(recordPtr,
			recordPtr->header.optionTable, (Tk_Window) NULL);
	    }
	}
	if (result != TCL_OK) {
	    ckfree(recordPtr);
	}

	break;
    }
    case NOT_ENOUGH_PARAMS: {
	typedef struct NotEnoughRecord {
	typedef struct {
	    Tcl_Obj *fooObjPtr;
	} NotEnoughRecord;
	NotEnoughRecord record;
	static const Tk_OptionSpec errorSpecs[] = {
	    {TK_OPTION_INT, "-foo", "foo", "Foo", "0",
		Tk_Offset(NotEnoughRecord, fooObjPtr), 0, 0, NULL, 0},
		offsetof(NotEnoughRecord, fooObjPtr), 0, 0, NULL, 0},
	    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0}
	};
	Tcl_Obj *newObjPtr = Tcl_NewStringObj("-foo", -1);
	Tk_OptionTable optionTable;

	record.fooObjPtr = NULL;

	tkwin = Tk_CreateWindowFromPath(interp, mainWin, ".config", NULL);
	Tk_SetClass(tkwin, "Config");
	optionTable = Tk_CreateOptionTable(interp, errorSpecs);
	tables[index] = optionTable;
	Tk_InitOptions(interp, (char *) &record, optionTable, tkwin);
	if (Tk_SetOptions(interp, (char *) &record, optionTable, 1,
	Tk_InitOptions(interp, &record, optionTable, tkwin);
	if (Tk_SetOptions(interp, &record, optionTable, 1,
		&newObjPtr, tkwin, NULL, NULL) != TCL_OK) {
	    result = TCL_ERROR;
	}
	Tcl_DecrRefCount(newObjPtr);
	Tk_FreeConfigOptions( (char *) &record, optionTable, tkwin);
	Tk_DestroyWindow(tkwin);
	return result;
    }

    case TWO_WINDOWS: {
	typedef struct SlaveRecord {
	typedef struct {
	    TrivialCommandHeader header;
	    Tcl_Obj *windowPtr;
	} SlaveRecord;
	SlaveRecord *recordPtr;
	static const Tk_OptionSpec slaveSpecs[] = {
	} ContentRecord;
	ContentRecord *recordPtr;
	static const Tk_OptionSpec contentSpecs[] = {
	    {TK_OPTION_WINDOW, "-window", "window", "Window", ".bar",
		Tk_Offset(SlaveRecord, windowPtr), -1, TK_CONFIG_NULL_OK, NULL, 0},
		offsetof(ContentRecord, windowPtr), TCL_INDEX_NONE, TK_CONFIG_NULL_OK, NULL, 0},
	    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0}
	};
	Tk_Window tkwin = Tk_CreateWindowFromPath(interp,
		(Tk_Window) clientData, Tcl_GetString(objv[2]), NULL);
	tkwin = Tk_CreateWindowFromPath(interp,
		(Tk_Window)clientData, Tcl_GetString(objv[2]), NULL);

	if (tkwin == NULL) {
	    return TCL_ERROR;
	}
	Tk_SetClass(tkwin, "Test");

	recordPtr = ckalloc(sizeof(SlaveRecord));
	recordPtr = (ContentRecord *)ckalloc(sizeof(ContentRecord));
	recordPtr->header.interp = interp;
	recordPtr->header.optionTable = Tk_CreateOptionTable(interp,
		slaveSpecs);
		contentSpecs);
	tables[index] = recordPtr->header.optionTable;
	recordPtr->header.tkwin = tkwin;
	recordPtr->windowPtr = NULL;

	result = Tk_InitOptions(interp,  (char *) recordPtr,
	result = Tk_InitOptions(interp, recordPtr,
		recordPtr->header.optionTable, tkwin);
	if (result == TCL_OK) {
	    result = Tk_SetOptions(interp, (char *) recordPtr,
	    result = Tk_SetOptions(interp, recordPtr,
		    recordPtr->header.optionTable, objc - 3, objv + 3,
		    tkwin, NULL, NULL);
	    if (result == TCL_OK) {
		recordPtr->header.widgetCmd = Tcl_CreateObjCommand(interp,
			Tcl_GetString(objv[2]), TrivialConfigObjCmd,
			recordPtr, TrivialCmdDeletedProc);
		Tk_CreateEventHandler(tkwin, StructureNotifyMask,
			TrivialEventProc, recordPtr);
		Tcl_SetObjResult(interp, objv[2]);
	    } else {
		Tk_FreeConfigOptions((char *) recordPtr,
		Tk_FreeConfigOptions(recordPtr,
			recordPtr->header.optionTable, tkwin);
	    }
	}
	if (result != TCL_OK) {
	    Tk_DestroyWindow(tkwin);
	    ckfree(recordPtr);
	}
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151

1152
1153
1154
1155
1156

1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174

1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185

1186
1187
1188
1189
1190
1191
1192
1193

1194
1195
1196
1197
1198
1199
1200
1201

1202
1203
1204
1205

1206
1207
1208
1209
1210

1211
1212
1213
1214
1215

1216
1217
1218
1219
1220
1221
1222
1125
1126
1127
1128
1129
1130
1131

1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147

1148
1149
1150
1151
1152

1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170

1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181

1182
1183
1184
1185
1186
1187
1188
1189

1190
1191
1192
1193
1194
1195
1196
1197

1198
1199
1200
1201

1202
1203
1204
1205
1206

1207
1208
1209
1210
1211

1212
1213
1214
1215
1216
1217
1218
1219







-
















-
+




-
+

















-
+










-
+







-
+







-
+



-
+




-
+




-
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
TrivialConfigObjCmd(
    ClientData clientData,	/* Main window for application. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int result = TCL_OK;
    static const char *const options[] = {
	"cget", "configure", "csave", NULL
    };
    enum {
	CGET, CONFIGURE, CSAVE
    };
    Tcl_Obj *resultObjPtr;
    int index, mask;
    TrivialCommandHeader *headerPtr = (TrivialCommandHeader *) clientData;
    TrivialCommandHeader *headerPtr = (TrivialCommandHeader *)clientData;
    Tk_Window tkwin = headerPtr->tkwin;
    Tk_SavedOptions saved;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg...?");
	Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
	return TCL_ERROR;
    }

    if (Tcl_GetIndexFromObjStruct(interp, objv[1], options,
	    sizeof(char *), "command", 0, &index) != TCL_OK) {
	return TCL_ERROR;
    }

    Tcl_Preserve(clientData);

    switch (index) {
    case CGET:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "option");
	    result = TCL_ERROR;
	    goto done;
	}
	resultObjPtr = Tk_GetOptionValue(interp, (char *) clientData,
	resultObjPtr = Tk_GetOptionValue(interp, clientData,
		headerPtr->optionTable, objv[2], tkwin);
	if (resultObjPtr != NULL) {
	    Tcl_SetObjResult(interp, resultObjPtr);
	    result = TCL_OK;
	} else {
	    result = TCL_ERROR;
	}
	break;
    case CONFIGURE:
	if (objc == 2) {
	    resultObjPtr = Tk_GetOptionInfo(interp, (char *) clientData,
	    resultObjPtr = Tk_GetOptionInfo(interp, clientData,
		    headerPtr->optionTable, NULL, tkwin);
	    if (resultObjPtr == NULL) {
		result = TCL_ERROR;
	    } else {
		Tcl_SetObjResult(interp, resultObjPtr);
	    }
	} else if (objc == 3) {
	    resultObjPtr = Tk_GetOptionInfo(interp, (char *) clientData,
	    resultObjPtr = Tk_GetOptionInfo(interp, clientData,
		    headerPtr->optionTable, objv[2], tkwin);
	    if (resultObjPtr == NULL) {
		result = TCL_ERROR;
	    } else {
		Tcl_SetObjResult(interp, resultObjPtr);
	    }
	} else {
	    result = Tk_SetOptions(interp, (char *) clientData,
	    result = Tk_SetOptions(interp, clientData,
		    headerPtr->optionTable, objc - 2, objv + 2,
		    tkwin, NULL, &mask);
	    if (result == TCL_OK) {
		Tcl_SetObjResult(interp, Tcl_NewIntObj(mask));
		Tcl_SetObjResult(interp, Tcl_NewWideIntObj(mask));
	    }
	}
	break;
    case CSAVE:
	result = Tk_SetOptions(interp, (char *) clientData,
	result = Tk_SetOptions(interp, clientData,
		headerPtr->optionTable, objc - 2, objv + 2,
		tkwin, &saved, &mask);
	Tk_FreeSavedOptions(&saved);
	if (result == TCL_OK) {
	    Tcl_SetObjResult(interp, Tcl_NewIntObj(mask));
	    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(mask));
	}
	break;
    }
  done:
    Tcl_Release(clientData);
    return result;
}
1239
1240
1241
1242
1243
1244
1245
1246

1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259


1260
1261
1262
1263
1264
1265
1266
1236
1237
1238
1239
1240
1241
1242

1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254


1255
1256
1257
1258
1259
1260
1261
1262
1263







-
+











-
-
+
+







 *----------------------------------------------------------------------
 */

static void
TrivialCmdDeletedProc(
    ClientData clientData)	/* Pointer to widget record for widget. */
{
    TrivialCommandHeader *headerPtr = (TrivialCommandHeader *) clientData;
    TrivialCommandHeader *headerPtr = (TrivialCommandHeader *)clientData;
    Tk_Window tkwin = headerPtr->tkwin;

    if (tkwin != NULL) {
	Tk_DestroyWindow(tkwin);
    } else if (headerPtr->optionTable != NULL) {
	/*
	 * This is a "new" object, which doesn't have a window, so we can't
	 * depend on cleaning up in the event function. Free its resources
	 * here.
	 */

	Tk_FreeConfigOptions((char *) clientData,
		headerPtr->optionTable, (Tk_Window) NULL);
	Tk_FreeConfigOptions(clientData,
		headerPtr->optionTable, NULL);
	Tcl_EventuallyFree(clientData, TCL_DYNAMIC);
    }
}

/*
 *--------------------------------------------------------------
 *
1278
1279
1280
1281
1282
1283
1284
1285

1286
1287
1288
1289

1290
1291
1292
1293
1294
1295
1296
1275
1276
1277
1278
1279
1280
1281

1282
1283
1284
1285

1286
1287
1288
1289
1290
1291
1292
1293







-
+



-
+







 */

static void
TrivialEventProc(
    ClientData clientData,	/* Information about window. */
    XEvent *eventPtr)		/* Information about event. */
{
    TrivialCommandHeader *headerPtr = (TrivialCommandHeader *) clientData;
    TrivialCommandHeader *headerPtr = (TrivialCommandHeader *)clientData;

    if (eventPtr->type == DestroyNotify) {
	if (headerPtr->tkwin != NULL) {
	    Tk_FreeConfigOptions((char *) clientData,
	    Tk_FreeConfigOptions(clientData,
		    headerPtr->optionTable, headerPtr->tkwin);
	    headerPtr->optionTable = NULL;
	    headerPtr->tkwin = NULL;
	    Tcl_DeleteCommandFromToken(headerPtr->interp,
		    headerPtr->widgetCmd);
	}
	Tcl_EventuallyFree(clientData, TCL_DYNAMIC);
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331

1332
1333
1334
1335
1336
1337
1338
1307
1308
1309
1310
1311
1312
1313

1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326

1327
1328
1329
1330
1331
1332
1333
1334







-













-
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
TestfontObjCmd(
    ClientData clientData,	/* Main window for application. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    static const char *const options[] = {"counts", "subfonts", NULL};
    enum option {COUNTS, SUBFONTS};
    int index;
    Tk_Window tkwin;
    Tk_Font tkfont;

    tkwin = (Tk_Window) clientData;
    tkwin = (Tk_Window)clientData;

    if (objc < 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "option fontName");
	return TCL_ERROR;
    }

    if (Tcl_GetIndexFromObjStruct(interp, objv[1], options,
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387


1388
1389
1390
1391
1392

1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412


1413
1414
1415
1416

1417
1418

1419
1420
1421
1422

1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451

1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472

1473
1474
1475
1476
1477
1478
1479
1366
1367
1368
1369
1370
1371
1372

1373
1374
1375
1376
1377
1378
1379
1380


1381
1382
1383
1384
1385
1386

1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405


1406
1407
1408
1409
1410

1411
1412

1413
1414
1415
1416

1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437

1438
1439
1440
1441
1442
1443
1444

1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465

1466
1467
1468
1469
1470
1471
1472
1473







-








-
-
+
+




-
+


















-
-
+
+



-
+

-
+



-
+




















-







-
+




















-
+







 *
 * Side effects:
 *	The data structure for a new image is allocated.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
ImageCreate(
    Tcl_Interp *interp,		/* Interpreter for application containing
				 * image. */
    const char *name,			/* Name to use for image. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[],	/* Argument strings for options (doesn't
				 * include image name or type). */
    const Tk_ImageType *typePtr,	/* Pointer to our type record (not used). */
    Tk_ImageMaster master,	/* Token for image, to be used by us in later
    TCL_UNUSED(const Tk_ImageType *),	/* Pointer to our type record (not used). */
	Tk_ImageModel model,	/* Token for image, to be used by us in later
				 * callbacks. */
    ClientData *clientDataPtr)	/* Store manager's token for image here; it
				 * will be returned in later callbacks. */
{
    TImageMaster *timPtr;
    TImageModel *timPtr;
    const char *varName;
    int i;

    varName = "log";
    for (i = 0; i < objc; i += 2) {
	if (strcmp(Tcl_GetString(objv[i]), "-variable") != 0) {
	    Tcl_AppendResult(interp, "bad option name \"",
		    Tcl_GetString(objv[i]), "\"", NULL);
	    return TCL_ERROR;
	}
	if ((i+1) == objc) {
	    Tcl_AppendResult(interp, "no value given for \"",
		    Tcl_GetString(objv[i]), "\" option", NULL);
	    return TCL_ERROR;
	}
	varName = Tcl_GetString(objv[i+1]);
    }

    timPtr = ckalloc(sizeof(TImageMaster));
    timPtr->master = master;
    timPtr = (TImageModel *)ckalloc(sizeof(TImageModel));
    timPtr->model = model;
    timPtr->interp = interp;
    timPtr->width = 30;
    timPtr->height = 15;
    timPtr->imageName = ckalloc(strlen(name) + 1);
    timPtr->imageName = (char *)ckalloc(strlen(name) + 1);
    strcpy(timPtr->imageName, name);
    timPtr->varName = ckalloc(strlen(varName) + 1);
    timPtr->varName = (char *)ckalloc(strlen(varName) + 1);
    strcpy(timPtr->varName, varName);
    Tcl_CreateObjCommand(interp, name, ImageObjCmd, timPtr, NULL);
    *clientDataPtr = timPtr;
    Tk_ImageChanged(master, 0, 0, 30, 15, 30, 15);
    Tk_ImageChanged(model, 0, 0, 30, 15, 30, 15);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * ImageObjCmd --
 *
 *	This function implements the commands corresponding to individual
 *	images.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	Forces windows to be created.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
ImageObjCmd(
    ClientData clientData,	/* Main window for application. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])		/* Argument strings. */
{
    TImageMaster *timPtr = (TImageMaster *) clientData;
    TImageModel *timPtr = (TImageModel *)clientData;
    int x, y, width, height;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
	return TCL_ERROR;
    }
    if (strcmp(Tcl_GetString(objv[1]), "changed") == 0) {
	if (objc != 8) {
		Tcl_WrongNumArgs(interp, 1, objv, "changed x y width height"
			" imageWidth imageHeight");
	    return TCL_ERROR;
	}
	if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK)
		|| (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)
		|| (Tcl_GetIntFromObj(interp, objv[4], &width) != TCL_OK)
		|| (Tcl_GetIntFromObj(interp, objv[5], &height) != TCL_OK)
		|| (Tcl_GetIntFromObj(interp, objv[6], &timPtr->width) != TCL_OK)
		|| (Tcl_GetIntFromObj(interp, objv[7], &timPtr->height) != TCL_OK)) {
	    return TCL_ERROR;
	}
	Tk_ImageChanged(timPtr->master, x, y, width, height, timPtr->width,
	Tk_ImageChanged(timPtr->model, x, y, width, height, timPtr->width,
		timPtr->height);
    } else {
	Tcl_AppendResult(interp, "bad option \"", Tcl_GetString(objv[1]),
		"\": must be changed", NULL);
	return TCL_ERROR;
    }
    return TCL_OK;
1497
1498
1499
1500
1501
1502
1503
1504

1505
1506

1507
1508
1509
1510
1511
1512
1513
1514
1515
1516


1517
1518
1519

1520
1521
1522
1523
1524
1525
1526
1491
1492
1493
1494
1495
1496
1497

1498
1499

1500
1501
1502
1503
1504
1505
1506
1507
1508


1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521







-
+

-
+








-
-
+
+



+







 *----------------------------------------------------------------------
 */

static ClientData
ImageGet(
    Tk_Window tkwin,		/* Token for window in which image will be
				 * used. */
    ClientData clientData)	/* Pointer to TImageMaster for image. */
    ClientData clientData)	/* Pointer to TImageModel for image. */
{
    TImageMaster *timPtr = (TImageMaster *) clientData;
    TImageModel *timPtr = (TImageModel *)clientData;
    TImageInstance *instPtr;
    char buffer[100];
    XGCValues gcValues;

    sprintf(buffer, "%s get", timPtr->imageName);
    Tcl_SetVar2(timPtr->interp, timPtr->varName, NULL, buffer,
	    TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT);

    instPtr = ckalloc(sizeof(TImageInstance));
    instPtr->masterPtr = timPtr;
    instPtr = (TImageInstance *)ckalloc(sizeof(TImageInstance));
    instPtr->modelPtr = timPtr;
    instPtr->fg = Tk_GetColor(timPtr->interp, tkwin, "#ff0000");
    gcValues.foreground = instPtr->fg->pixel;
    instPtr->gc = Tk_GetGC(tkwin, GCForeground, &gcValues);
    instPtr->displayFailed = False;
    return instPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * ImageDisplay --
1546
1547
1548
1549
1550
1551
1552
1553

1554
1555
1556
1557
1558
1559
1560



1561
1562

1563
1564
1565
1566
1567
1568
1569
1570
1571

1572
1573

1574
1575
1576

1577
1578
1579

1580
1581


1582
1583
1584
1585
1586
1587
1588
1589
1590
1591






























1592
1593
1594


1595
1596
1597
1598
1599
1600
1601
1541
1542
1543
1544
1545
1546
1547

1548

1549
1550
1551



1552
1553
1554
1555

1556


1557






1558


1559



1560



1561


1562
1563
1564
1565








1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596


1597
1598
1599
1600
1601
1602
1603
1604
1605







-
+
-



-
-
-
+
+
+

-
+
-
-

-
-
-
-
-
-
+
-
-
+
-
-
-
+
-
-
-
+
-
-
+
+


-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
+
+







    int imageX, int imageY,	/* Origin of area to redraw, relative to
				 * origin of image. */
    int width, int height,	/* Dimensions of area to redraw. */
    int drawableX, int drawableY)
				/* Coordinates in drawable corresponding to
				 * imageX and imageY. */
{
    TImageInstance *instPtr = (TImageInstance *) clientData;
    TImageInstance *instPtr = (TImageInstance *)clientData;
    char buffer[200 + TCL_INTEGER_SPACE * 6];

    /*
     * The purpose of the test image type is to track the calls to an image
     * display proc and record the parameters passed in each call.  On macOS
     * a display proc must be run inside of the drawRect method of an NSView
     * in order for the graphics operations to have any effect.  To deal with
     * display proc and record the parameters passed in each call.  On macOS a
     * display proc must be run inside of the drawRect method of an NSView in
     * order for the graphics operations to have any effect.  To deal with
     * this, whenever a display proc is called outside of any drawRect method
     * it schedules a redraw of the NSView by calling [view setNeedsDisplay:YES].
     * it schedules a redraw of the NSView.
     * This will trigger a later call to the view's drawRect method which will
     * run the display proc a second time.
     *
     * This complicates testing, since it can result in more calls to the display
     * proc than are expected by the test.  It can also result in an inconsistent
     * number of calls unless the test waits until the call to drawRect actually
     * occurs before validating its results.
     *
     * In an attempt to work around this, this display proc only logs those
     * In an attempt to work around this, each image instance maintains it own
     * calls which occur within a drawRect method.  This means that tests must
     * be written so as to ensure that the drawRect method is run before
     * copy of the log message which gets written on the first call to the
     * results are validated.  In practice it usually suffices to run update
     * idletasks (to run the display proc the first time) followed by update
     * (to run the display proc in drawRect).
     * display proc.  This usually means that the message created on macOS is
     *
     * This also has the consequence that the image changed command will log
     * different results on Aqua than on other systems, because when the image
     * the same as that created on other platforms.  However it is possible
     * is redisplayed in the drawRect method the entire image will be drawn,
     * not just the changed portion.  Tests must account for this.
     * for the messages to differ for other reasons, namely differences in
     * how damage regions are computed.
     */

    if (LOG_DISPLAY) {
	sprintf(buffer, "%s display %d %d %d %d",
		instPtr->masterPtr->imageName, imageX, imageY, width, height);
	Tcl_SetVar2(instPtr->masterPtr->interp, instPtr->masterPtr->varName,
		    NULL, buffer, TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT);
    }
    if (width > (instPtr->masterPtr->width - imageX)) {
	width = instPtr->masterPtr->width - imageX;
    if (LOG_DISPLAY(drawable)) {
	if (instPtr->displayFailed == False) {

	    /*
	     * Drawing is possible on the first call to DisplayImage.
	     * Log the message.
	     */

	    sprintf(instPtr->buffer, "%s display %d %d %d %d",
	    instPtr->modelPtr->imageName, imageX, imageY, width, height);
	}
	Tcl_SetVar2(instPtr->modelPtr->interp, instPtr->modelPtr->varName,
		    NULL, instPtr->buffer,
		    TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT);
	instPtr->displayFailed = False;
    } else {

	/*
         * Drawing is not possible on the first call to DisplayImage.
	 * Save the message, but do not log it until the actual display.
	 */

	if (instPtr->displayFailed == False) {
	    sprintf(instPtr->buffer, "%s display %d %d %d %d",
		    instPtr->modelPtr->imageName, imageX, imageY, width, height);
	}
	instPtr->displayFailed = True;
    }
    if (width > (instPtr->modelPtr->width - imageX)) {
	width = instPtr->modelPtr->width - imageX;
    }
    if (height > (instPtr->masterPtr->height - imageY)) {
	height = instPtr->masterPtr->height - imageY;
    if (height > (instPtr->modelPtr->height - imageY)) {
	height = instPtr->modelPtr->height - imageY;
    }

    XDrawRectangle(display, drawable, instPtr->gc, drawableX, drawableY,
	    (unsigned) (width-1), (unsigned) (height-1));
    XDrawLine(display, drawable, instPtr->gc, drawableX, drawableY,
	    (int) (drawableX + width - 1), (int) (drawableY + height - 1));
    XDrawLine(display, drawable, instPtr->gc, drawableX,
1621
1622
1623
1624
1625
1626
1627
1628

1629
1630
1631
1632


1633
1634
1635
1636
1637
1638
1639
1625
1626
1627
1628
1629
1630
1631

1632
1633
1634


1635
1636
1637
1638
1639
1640
1641
1642
1643







-
+


-
-
+
+







 */

static void
ImageFree(
    ClientData clientData,	/* Pointer to TImageInstance for instance. */
    Display *display)		/* Display where image was to be drawn. */
{
    TImageInstance *instPtr = (TImageInstance *) clientData;
    TImageInstance *instPtr = (TImageInstance *)clientData;
    char buffer[200];

    sprintf(buffer, "%s free", instPtr->masterPtr->imageName);
    Tcl_SetVar2(instPtr->masterPtr->interp, instPtr->masterPtr->varName, NULL,
    sprintf(buffer, "%s free", instPtr->modelPtr->imageName);
    Tcl_SetVar2(instPtr->modelPtr->interp, instPtr->modelPtr->varName, NULL,
	    buffer, TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT);
    Tk_FreeColor(instPtr->fg);
    Tk_FreeGC(display, instPtr->gc);
    ckfree(instPtr);
}

/*
1651
1652
1653
1654
1655
1656
1657
1658

1659
1660
1661
1662

1663
1664
1665
1666
1667
1668
1669
1655
1656
1657
1658
1659
1660
1661

1662
1663
1664
1665

1666
1667
1668
1669
1670
1671
1672
1673







-
+



-
+







 *	Information about the image is deleted.
 *
 *----------------------------------------------------------------------
 */

static void
ImageDelete(
    ClientData clientData)	/* Pointer to TImageMaster for image. When
    ClientData clientData)	/* Pointer to TImageModel for image. When
				 * this function is called, no more instances
				 * exist. */
{
    TImageMaster *timPtr = (TImageMaster *) clientData;
    TImageModel *timPtr = (TImageModel *)clientData;
    char buffer[100];

    sprintf(buffer, "%s delete", timPtr->imageName);
    Tcl_SetVar2(timPtr->interp, timPtr->varName, NULL, buffer,
	    TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT);

    Tcl_DeleteCommand(timPtr->interp, timPtr->imageName);
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701

1702
1703
1704
1705
1706
1707
1708
1690
1691
1692
1693
1694
1695
1696

1697
1698
1699
1700
1701
1702
1703

1704
1705
1706
1707
1708
1709
1710
1711







-







-
+







 *
 * Side effects:
 *	Forces windows to be created.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
TestmakeexistObjCmd(
    ClientData clientData,	/* Main window for application. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])		/* Argument strings. */
{
    Tk_Window mainWin = (Tk_Window) clientData;
    Tk_Window mainWin = (Tk_Window)clientData;
    int i;
    Tk_Window tkwin;

    for (i = 1; i < objc; i++) {
	tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[i]), mainWin);
	if (tkwin == NULL) {
	    return TCL_ERROR;
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744

1745
1746
1747
1748
1749
1750
1751
1730
1731
1732
1733
1734
1735
1736

1737
1738
1739
1740
1741
1742
1743
1744
1745

1746
1747
1748
1749
1750
1751
1752
1753







-









-
+







 *
 * Side effects:
 *	Changes menubar related stuff.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
#if !(defined(_WIN32) || defined(MAC_OSX_TK) || defined(__CYGWIN__))
static int
TestmenubarObjCmd(
    ClientData clientData,	/* Main window for application. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])		/* Argument strings. */
{
#ifdef __UNIX__
    Tk_Window mainWin = (Tk_Window) clientData;
    Tk_Window mainWin = (Tk_Window)clientData;
    Tk_Window tkwin, menubar;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
	return TCL_ERROR;
    }

1797
1798
1799
1800
1801
1802
1803
1804

1805
1806
1807
1808
1809
1810
1811
1799
1800
1801
1802
1803
1804
1805

1806
1807
1808
1809
1810
1811
1812
1813







-
+







 *
 *----------------------------------------------------------------------
 */

#if defined(_WIN32)
static int
TestmetricsObjCmd(
    ClientData clientData,	/* Main window for application. */
    TCL_UNUSED(void *),	/* Main window for application. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])		/* Argument strings. */
{
    char buf[TCL_INTEGER_SPACE];
    int val;

1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857

1858
1859
1860
1861
1862
1863
1864
1844
1845
1846
1847
1848
1849
1850

1851
1852
1853
1854
1855
1856
1857

1858
1859
1860
1861
1862
1863
1864
1865







-







-
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
TestpropObjCmd(
    ClientData clientData,	/* Main window for application. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])		/* Argument strings. */
{
    Tk_Window mainWin = (Tk_Window) clientData;
    Tk_Window mainWin = (Tk_Window)clientData;
    int result, actualFormat;
    unsigned long bytesAfter, length, value;
    Atom actualType, propName;
    unsigned char *property, *p;
    char *end;
    Window w;
    char buffer[30];
1901
1902
1903
1904
1905
1906
1907






















































1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944

1945
1946
1947
1948
1949
1950
1951
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982

1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997

1998
1999
2000
2001
2002
2003
2004
2005







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




















-















-
+







	}
    }
    if (property != NULL) {
	XFree(property);
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestpropObjCmd --
 *
 *	This function implements the "testprop" command. It fetches and prints
 *	the value of a property on a window.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TestprintfObjCmd(
    ClientData dummy,	/* Not used */
    Tcl_Interp *interp,		/* Current interpreter. */
    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;
    }
    if (Tcl_GetWideIntFromObj(interp, objv[1], &wideInt) != TCL_OK) {
	return TCL_ERROR;
    }
    longLongInt = wideInt;

    /* Just add a lot of arguments to sprintf. Reason: on AMD64, the first
     * 4 or 6 arguments (we assume 8, just in case) might be put in registers,
     * 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);
    Tcl_AppendResult(interp, buffer, NULL);
    return TCL_OK;
}

#if !(defined(_WIN32) || defined(MAC_OSX_TK) || defined(__CYGWIN__))
/*
 *----------------------------------------------------------------------
 *
 * TestwrapperObjCmd --
 *
 *	This function implements the "testwrapper" command. It provides a way
 *	from Tcl to determine the extra window Tk adds in between the toplevel
 *	window and the window decorations.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
TestwrapperObjCmd(
    ClientData clientData,	/* Main window for application. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])		/* Argument strings. */
{
    TkWindow *winPtr, *wrapperPtr;
    Tk_Window tkwin;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "window");
	return TCL_ERROR;
    }

    tkwin = (Tk_Window) clientData;
    tkwin = (Tk_Window)clientData;
    winPtr = (TkWindow *) Tk_NameToWindow(interp, Tcl_GetString(objv[1]), tkwin);
    if (winPtr == NULL) {
	return TCL_ERROR;
    }

    wrapperPtr = TkpGetWrapperWindow(winPtr);
    if (wrapperPtr != NULL) {
1974
1975
1976
1977
1978
1979
1980
1981

1982
1983
1984
1985
1986
1987
1988
1989

1990
1991

1992
1993
1994

1995
1996
1997
1998
1999
2000
2001
2002
2003

2004
2005
2006
2007
2008
2009
2010
2028
2029
2030
2031
2032
2033
2034

2035

2036
2037
2038
2039
2040
2041

2042
2043

2044
2045
2046

2047
2048
2049
2050
2051
2052
2053
2054
2055

2056
2057
2058
2059
2060
2061
2062
2063







-
+
-






-
+

-
+


-
+








-
+







 *		CustomOptionFree	None.
 *
 * Side effects:
 *	Depends on the function.
 *		CustomOptionSet		Sets option value to new setting.
 *		CustomOptionGet		Creates a new Tcl_Obj.
 *		CustomOptionRestore	Resets option value to original value.
 *		CustomOptionFree	Free storage for internal rep of
 *		CustomOptionFree	Free storage for internal rep of option.
 *					option.
 *
 *----------------------------------------------------------------------
 */

static int
CustomOptionSet(
    ClientData clientData,
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tk_Window tkwin,
    TCL_UNUSED(Tk_Window),
    Tcl_Obj **value,
    char *recordPtr,
    int internalOffset,
    TkSizeT internalOffset,
    char *saveInternalPtr,
    int flags)
{
    int objEmpty;
    char *newStr, *string, *internalPtr;

    objEmpty = 0;

    if (internalOffset >= 0) {
    if (internalOffset != TCL_INDEX_NONE) {
	internalPtr = recordPtr + internalOffset;
    } else {
	internalPtr = NULL;
    }

    /*
     * See if the object is empty.
2029
2030
2031
2032
2033
2034
2035
2036

2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051


2052
2053

2054
2055
2056
2057
2058
2059
2060

2061
2062
2063
2064



2065
2066
2067
2068
2069
2070
2071

2072
2073
2074



2075
2076
2077
2078
















































2079
2080
2081
2082
2083
2084
2085
2086
2082
2083
2084
2085
2086
2087
2088

2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102


2103
2104
2105

2106
2107
2108
2109
2110
2111
2112

2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126

2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193







-
+













-
-
+
+

-
+






-
+




+
+
+






-
+



+
+
+




+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








	    Tcl_SetObjResult(interp, Tcl_NewStringObj("expected good value, got \"BAD\"", -1));
	    return TCL_ERROR;
	}
    }
    if (internalPtr != NULL) {
	if (*value != NULL) {
	    string = Tcl_GetString(*value);
	    newStr = ckalloc((*value)->length + 1);
	    newStr = (char *)ckalloc((*value)->length + 1);
	    strcpy(newStr, string);
	} else {
	    newStr = NULL;
	}
	*((char **) saveInternalPtr) = *((char **) internalPtr);
	*((char **) internalPtr) = newStr;
    }

    return TCL_OK;
}

static Tcl_Obj *
CustomOptionGet(
    ClientData clientData,
    Tk_Window tkwin,
    TCL_UNUSED(void *),
    TCL_UNUSED(Tk_Window),
    char *recordPtr,
    int internalOffset)
    TkSizeT internalOffset)
{
    return (Tcl_NewStringObj(*(char **)(recordPtr + internalOffset), -1));
}

static void
CustomOptionRestore(
    ClientData clientData,
    ClientData dummy,
    Tk_Window tkwin,
    char *internalPtr,
    char *saveInternalPtr)
{
    (void)dummy;
    (void)tkwin;

    *(char **)internalPtr = *(char **)saveInternalPtr;
    return;
}

static void
CustomOptionFree(
    ClientData clientData,
    ClientData dummy,
    Tk_Window tkwin,
    char *internalPtr)
{
    (void)dummy;
    (void)tkwin;

    if (*(char **)internalPtr != NULL) {
	ckfree(*(char **)internalPtr);
    }
}
/*
 *----------------------------------------------------------------------
 *
 * TestPhotoStringMatchCmd --
 *
 *	This function implements the "testphotostringmatch" command. It
 *	provides a way from Tcl to call the string match function for the
 *	default image handler directly.
 *
 * Results:
 *	A standard Tcl result. If data is in the proper format, the result in
 *	interp will contain width and height as a list. If the data cannot be
 *	parsed as default image format, returns TCL_ERROR and leaves an
 *	appropriate error message in interp.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TestPhotoStringMatchCmd(
    ClientData clientData,	/* Main window for application. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])		/* Argument strings. */
{
    Tcl_Obj *dummy = NULL;
    Tcl_Obj *resultObj[2];
    int width, height;
    (void)clientData;

    if (objc != 2) {
        Tcl_WrongNumArgs(interp, 1, objv, "imageData");
        return TCL_ERROR;
    }
    if (TkDebugPhotoStringMatchDef(interp, objv[1], dummy, &width, &height)) {
        resultObj[0] = Tcl_NewWideIntObj(width);
        resultObj[1] = Tcl_NewWideIntObj(height);
        Tcl_SetObjResult(interp, Tcl_NewListObj(2, resultObj));
        return TCL_OK;
    } else {
        return TCL_ERROR;
    }
}



/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Changes to generic/tkText.c.
1
2
3
4
5
6
7
8
9
10
11



12
13
14
15
16
17
18
19



20
21
22
23
24
25
26
1
2
3
4
5
6
7
8



9
10
11
12
13
14
15
16



17
18
19
20
21
22
23
24
25
26








-
-
-
+
+
+





-
-
-
+
+
+







/*
 * tkText.c --
 *
 *	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.
 */

#include "default.h"
#include "tkInt.h"
#include "tkUndo.h"
#include "tkInt.h"
#include "tkUndo.h"
#include "default.h"

#if defined(MAC_OSX_TK)
#define Style TkStyle
#define DInfo TkDInfo
#endif

/*
92
93
94
95
96
97
98
99

100
101
102
103

104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125


126
127
128

129
130
131

132
133
134

135
136
137


138
139

140
141
142

143
144
145

146
147
148
149


150
151

152
153

154
155
156

157
158
159

160
161
162

163
164
165

166
167
168
169


170
171
172
173

174
175
176
177

178
179
180
181


182
183
184

185
186
187

188
189
190
191

192
193
194

195
196
197

198
199
200

201
202
203

204
205

206
207

208
209
210
211
212


213
214
215

216
217
218

219
220

221
222
223

224
225
226

227
228
229

230
231
232

233
234
235

236
237
238

239
240
241

242
243
244

245
246
247

248
249
250

251
252
253

254
255
256

257
258
259
260
261
262
263
92
93
94
95
96
97
98

99
100
101
102

103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123


124
125
126
127

128
129
130

131
132
133

134
135


136
137
138

139
140
141

142
143
144

145
146
147


148
149
150

151
152

153
154
155

156
157
158

159
160
161

162
163
164

165
166
167


168
169
170
171
172

173
174
175
176

177
178
179


180
181
182
183

184
185
186

187
188
189
190

191
192
193

194
195
196

197
198
199

200
201
202

203
204

205
206

207
208
209
210


211
212
213
214

215
216
217

218
219

220
221
222

223
224
225

226
227
228

229
230
231

232
233
234

235
236
237

238
239
240

241
242
243

244
245
246

247
248
249

250
251
252

253
254
255

256
257
258
259
260
261
262
263







-
+



-
+




















-
-
+
+


-
+


-
+


-
+

-
-
+
+

-
+


-
+


-
+


-
-
+
+

-
+

-
+


-
+


-
+


-
+


-
+


-
-
+
+



-
+



-
+


-
-
+
+


-
+


-
+



-
+


-
+


-
+


-
+


-
+

-
+

-
+



-
-
+
+


-
+


-
+

-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+







 * the internal storage is just a pointer, which therefore doesn't need
 * freeing.
 */

static int		SetLineStartEnd(ClientData clientData,
			    Tcl_Interp *interp, Tk_Window tkwin,
			    Tcl_Obj **value, char *recordPtr,
			    int internalOffset, char *oldInternalPtr,
			    TkSizeT internalOffset, char *oldInternalPtr,
			    int flags);
static Tcl_Obj *	GetLineStartEnd(ClientData clientData,
			    Tk_Window tkwin, char *recordPtr,
			    int internalOffset);
			    TkSizeT internalOffset);
static void		RestoreLineStartEnd(ClientData clientData,
			    Tk_Window tkwin, char *internalPtr,
			    char *oldInternalPtr);
static int		ObjectIsEmpty(Tcl_Obj *objPtr);

static const Tk_ObjCustomOption lineOption = {
    "line",			/* name */
    SetLineStartEnd,		/* setProc */
    GetLineStartEnd,		/* getProc */
    RestoreLineStartEnd,	/* restoreProc */
    NULL,			/* freeProc */
    0
};

/*
 * Information used to parse text configuration options:
 */

static const Tk_OptionSpec optionSpecs[] = {
    {TK_OPTION_BOOLEAN, "-autoseparators", "autoSeparators",
	"AutoSeparators", DEF_TEXT_AUTO_SEPARATORS, -1,
	Tk_Offset(TkText, autoSeparators),
	"AutoSeparators", DEF_TEXT_AUTO_SEPARATORS, TCL_INDEX_NONE,
	offsetof(TkText, autoSeparators),
	TK_OPTION_DONT_SET_DEFAULT, 0, 0},
    {TK_OPTION_BORDER, "-background", "background", "Background",
	DEF_TEXT_BG_COLOR, -1, Tk_Offset(TkText, border),
	DEF_TEXT_BG_COLOR, TCL_INDEX_NONE, offsetof(TkText, border),
	0, DEF_TEXT_BG_MONO, 0},
    {TK_OPTION_SYNONYM, "-bd", NULL, NULL,
	NULL, 0, -1, 0, "-borderwidth",
	NULL, 0, TCL_INDEX_NONE, 0, "-borderwidth",
	TK_TEXT_LINE_GEOMETRY},
    {TK_OPTION_SYNONYM, "-bg", NULL, NULL,
	NULL, 0, -1, 0, "-background", 0},
	NULL, 0, TCL_INDEX_NONE, 0, "-background", 0},
    {TK_OPTION_BOOLEAN, "-blockcursor", "blockCursor",
	"BlockCursor", DEF_TEXT_BLOCK_CURSOR, -1,
	Tk_Offset(TkText, insertCursorType), 0, 0, 0},
	"BlockCursor", DEF_TEXT_BLOCK_CURSOR, TCL_INDEX_NONE,
	offsetof(TkText, insertCursorType), 0, 0, 0},
    {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
	DEF_TEXT_BORDER_WIDTH, -1, Tk_Offset(TkText, borderWidth),
	DEF_TEXT_BORDER_WIDTH, TCL_INDEX_NONE, offsetof(TkText, borderWidth),
	0, 0, TK_TEXT_LINE_GEOMETRY},
    {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
	DEF_TEXT_CURSOR, -1, Tk_Offset(TkText, cursor),
	DEF_TEXT_CURSOR, TCL_INDEX_NONE, offsetof(TkText, cursor),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_CUSTOM, "-endline", NULL, NULL,
	 NULL, -1, Tk_Offset(TkText, end), TK_OPTION_NULL_OK,
	 NULL, TCL_INDEX_NONE, offsetof(TkText, end), TK_OPTION_NULL_OK,
	 &lineOption, TK_TEXT_LINE_RANGE},
    {TK_OPTION_BOOLEAN, "-exportselection", "exportSelection",
	"ExportSelection", DEF_TEXT_EXPORT_SELECTION, -1,
	Tk_Offset(TkText, exportSelection), 0, 0, 0},
	"ExportSelection", DEF_TEXT_EXPORT_SELECTION, TCL_INDEX_NONE,
	offsetof(TkText, exportSelection), 0, 0, 0},
    {TK_OPTION_SYNONYM, "-fg", "foreground", NULL,
	NULL, 0, -1, 0, "-foreground", 0},
	NULL, 0, TCL_INDEX_NONE, 0, "-foreground", 0},
    {TK_OPTION_FONT, "-font", "font", "Font",
	DEF_TEXT_FONT, -1, Tk_Offset(TkText, tkfont), 0, 0,
	DEF_TEXT_FONT, TCL_INDEX_NONE, offsetof(TkText, tkfont), 0, 0,
	TK_TEXT_LINE_GEOMETRY},
    {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
	DEF_TEXT_FG, -1, Tk_Offset(TkText, fgColor), 0,
	DEF_TEXT_FG, TCL_INDEX_NONE, offsetof(TkText, fgColor), 0,
	0, 0},
    {TK_OPTION_PIXELS, "-height", "height", "Height",
	DEF_TEXT_HEIGHT, -1, Tk_Offset(TkText, height), 0, 0, 0},
	DEF_TEXT_HEIGHT, TCL_INDEX_NONE, offsetof(TkText, height), 0, 0, 0},
    {TK_OPTION_COLOR, "-highlightbackground", "highlightBackground",
	"HighlightBackground", DEF_TEXT_HIGHLIGHT_BG,
	-1, Tk_Offset(TkText, highlightBgColorPtr),
	TCL_INDEX_NONE, offsetof(TkText, highlightBgColorPtr),
	0, 0, 0},
    {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
	DEF_TEXT_HIGHLIGHT, -1, Tk_Offset(TkText, highlightColorPtr),
	DEF_TEXT_HIGHLIGHT, TCL_INDEX_NONE, offsetof(TkText, highlightColorPtr),
	0, 0, 0},
    {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
	"HighlightThickness", DEF_TEXT_HIGHLIGHT_WIDTH, -1,
	Tk_Offset(TkText, highlightWidth), 0, 0, TK_TEXT_LINE_GEOMETRY},
	"HighlightThickness", DEF_TEXT_HIGHLIGHT_WIDTH, TCL_INDEX_NONE,
	offsetof(TkText, highlightWidth), 0, 0, TK_TEXT_LINE_GEOMETRY},
    {TK_OPTION_BORDER, "-inactiveselectbackground","inactiveSelectBackground",
	"Foreground",
	DEF_TEXT_INACTIVE_SELECT_COLOR,
	-1, Tk_Offset(TkText, inactiveSelBorder),
	TCL_INDEX_NONE, offsetof(TkText, inactiveSelBorder),
	TK_OPTION_NULL_OK, DEF_TEXT_SELECT_MONO, 0},
    {TK_OPTION_BORDER, "-insertbackground", "insertBackground", "Foreground",
	DEF_TEXT_INSERT_BG,
	-1, Tk_Offset(TkText, insertBorder),
	TCL_INDEX_NONE, offsetof(TkText, insertBorder),
	0, 0, 0},
    {TK_OPTION_PIXELS, "-insertborderwidth", "insertBorderWidth",
	"BorderWidth", DEF_TEXT_INSERT_BD_COLOR, -1,
	Tk_Offset(TkText, insertBorderWidth), 0,
	"BorderWidth", DEF_TEXT_INSERT_BD_COLOR, TCL_INDEX_NONE,
	offsetof(TkText, insertBorderWidth), 0,
	(ClientData) DEF_TEXT_INSERT_BD_MONO, 0},
    {TK_OPTION_INT, "-insertofftime", "insertOffTime", "OffTime",
	DEF_TEXT_INSERT_OFF_TIME, -1, Tk_Offset(TkText, insertOffTime),
	DEF_TEXT_INSERT_OFF_TIME, TCL_INDEX_NONE, offsetof(TkText, insertOffTime),
	0, 0, 0},
    {TK_OPTION_INT, "-insertontime", "insertOnTime", "OnTime",
	DEF_TEXT_INSERT_ON_TIME, -1, Tk_Offset(TkText, insertOnTime),
	DEF_TEXT_INSERT_ON_TIME, TCL_INDEX_NONE, offsetof(TkText, insertOnTime),
	0, 0, 0},
    {TK_OPTION_STRING_TABLE,
	"-insertunfocussed", "insertUnfocussed", "InsertUnfocussed",
	DEF_TEXT_INSERT_UNFOCUSSED, -1, Tk_Offset(TkText, insertUnfocussed),
	DEF_TEXT_INSERT_UNFOCUSSED, TCL_INDEX_NONE, offsetof(TkText, insertUnfocussed),
	0, insertUnfocussedStrings, 0},
    {TK_OPTION_PIXELS, "-insertwidth", "insertWidth", "InsertWidth",
	DEF_TEXT_INSERT_WIDTH, -1, Tk_Offset(TkText, insertWidth),
	DEF_TEXT_INSERT_WIDTH, TCL_INDEX_NONE, offsetof(TkText, insertWidth),
	0, 0, 0},
    {TK_OPTION_INT, "-maxundo", "maxUndo", "MaxUndo",
	DEF_TEXT_MAX_UNDO, -1, Tk_Offset(TkText, maxUndo),
	DEF_TEXT_MAX_UNDO, TCL_INDEX_NONE, offsetof(TkText, maxUndo),
	TK_OPTION_DONT_SET_DEFAULT, 0, 0},
    {TK_OPTION_PIXELS, "-padx", "padX", "Pad",
	DEF_TEXT_PADX, -1, Tk_Offset(TkText, padX), 0, 0,
	DEF_TEXT_PADX, TCL_INDEX_NONE, offsetof(TkText, padX), 0, 0,
	TK_TEXT_LINE_GEOMETRY},
    {TK_OPTION_PIXELS, "-pady", "padY", "Pad",
	DEF_TEXT_PADY, -1, Tk_Offset(TkText, padY), 0, 0, 0},
	DEF_TEXT_PADY, TCL_INDEX_NONE, offsetof(TkText, padY), 0, 0, 0},
    {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
	DEF_TEXT_RELIEF, -1, Tk_Offset(TkText, relief), 0, 0, 0},
	DEF_TEXT_RELIEF, TCL_INDEX_NONE, offsetof(TkText, relief), 0, 0, 0},
    {TK_OPTION_BORDER, "-selectbackground", "selectBackground", "Foreground",
	DEF_TEXT_SELECT_COLOR, -1, Tk_Offset(TkText, selBorder),
	DEF_TEXT_SELECT_COLOR, TCL_INDEX_NONE, offsetof(TkText, selBorder),
	0, DEF_TEXT_SELECT_MONO, 0},
    {TK_OPTION_PIXELS, "-selectborderwidth", "selectBorderWidth",
	"BorderWidth", DEF_TEXT_SELECT_BD_COLOR,
	Tk_Offset(TkText, selBorderWidthPtr),
	Tk_Offset(TkText, selBorderWidth),
	offsetof(TkText, selBorderWidthPtr),
	offsetof(TkText, selBorderWidth),
	TK_OPTION_NULL_OK, DEF_TEXT_SELECT_BD_MONO, 0},
    {TK_OPTION_COLOR, "-selectforeground", "selectForeground", "Background",
	DEF_TEXT_SELECT_FG_COLOR, -1, Tk_Offset(TkText, selFgColorPtr),
	DEF_TEXT_SELECT_FG_COLOR, TCL_INDEX_NONE, offsetof(TkText, selFgColorPtr),
	TK_OPTION_NULL_OK, DEF_TEXT_SELECT_FG_MONO, 0},
    {TK_OPTION_BOOLEAN, "-setgrid", "setGrid", "SetGrid",
	DEF_TEXT_SET_GRID, -1, Tk_Offset(TkText, setGrid), 0, 0, 0},
	DEF_TEXT_SET_GRID, TCL_INDEX_NONE, offsetof(TkText, setGrid), 0, 0, 0},
    {TK_OPTION_PIXELS, "-spacing1", "spacing1", "Spacing",
	DEF_TEXT_SPACING1, -1, Tk_Offset(TkText, spacing1),
	DEF_TEXT_SPACING1, TCL_INDEX_NONE, offsetof(TkText, spacing1),
	0, 0 , TK_TEXT_LINE_GEOMETRY },
    {TK_OPTION_PIXELS, "-spacing2", "spacing2", "Spacing",
	DEF_TEXT_SPACING2, -1, Tk_Offset(TkText, spacing2),
	DEF_TEXT_SPACING2, TCL_INDEX_NONE, offsetof(TkText, spacing2),
	0, 0 , TK_TEXT_LINE_GEOMETRY },
    {TK_OPTION_PIXELS, "-spacing3", "spacing3", "Spacing",
	DEF_TEXT_SPACING3, -1, Tk_Offset(TkText, spacing3),
	DEF_TEXT_SPACING3, TCL_INDEX_NONE, offsetof(TkText, spacing3),
	0, 0 , TK_TEXT_LINE_GEOMETRY },
    {TK_OPTION_CUSTOM, "-startline", NULL, NULL,
	 NULL, -1, Tk_Offset(TkText, start), TK_OPTION_NULL_OK,
	 NULL, TCL_INDEX_NONE, offsetof(TkText, start), TK_OPTION_NULL_OK,
	 &lineOption, TK_TEXT_LINE_RANGE},
    {TK_OPTION_STRING_TABLE, "-state", "state", "State",
	DEF_TEXT_STATE, -1, Tk_Offset(TkText, state),
	DEF_TEXT_STATE, TCL_INDEX_NONE, offsetof(TkText, state),
	0, stateStrings, 0},
    {TK_OPTION_STRING, "-tabs", "tabs", "Tabs",
	DEF_TEXT_TABS, Tk_Offset(TkText, tabOptionPtr), -1,
	DEF_TEXT_TABS, offsetof(TkText, tabOptionPtr), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK, 0, TK_TEXT_LINE_GEOMETRY},
    {TK_OPTION_STRING_TABLE, "-tabstyle", "tabStyle", "TabStyle",
	DEF_TEXT_TABSTYLE, -1, Tk_Offset(TkText, tabStyle),
	DEF_TEXT_TABSTYLE, TCL_INDEX_NONE, offsetof(TkText, tabStyle),
	0, tabStyleStrings, TK_TEXT_LINE_GEOMETRY},
    {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
	DEF_TEXT_TAKE_FOCUS, -1, Tk_Offset(TkText, takeFocus),
	DEF_TEXT_TAKE_FOCUS, TCL_INDEX_NONE, offsetof(TkText, takeFocus),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_BOOLEAN, "-undo", "undo", "Undo",
	DEF_TEXT_UNDO, -1, Tk_Offset(TkText, undo),
	DEF_TEXT_UNDO, TCL_INDEX_NONE, offsetof(TkText, undo),
	TK_OPTION_DONT_SET_DEFAULT, 0 , 0},
    {TK_OPTION_INT, "-width", "width", "Width",
	DEF_TEXT_WIDTH, -1, Tk_Offset(TkText, width), 0, 0,
	DEF_TEXT_WIDTH, TCL_INDEX_NONE, offsetof(TkText, width), 0, 0,
	TK_TEXT_LINE_GEOMETRY},
    {TK_OPTION_STRING_TABLE, "-wrap", "wrap", "Wrap",
	DEF_TEXT_WRAP, -1, Tk_Offset(TkText, wrapMode),
	DEF_TEXT_WRAP, TCL_INDEX_NONE, offsetof(TkText, wrapMode),
	0, wrapStrings, TK_TEXT_LINE_GEOMETRY},
    {TK_OPTION_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand",
	DEF_TEXT_XSCROLL_COMMAND, -1, Tk_Offset(TkText, xScrollCmd),
	DEF_TEXT_XSCROLL_COMMAND, TCL_INDEX_NONE, offsetof(TkText, xScrollCmd),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_STRING, "-yscrollcommand", "yScrollCommand", "ScrollCommand",
	DEF_TEXT_YSCROLL_COMMAND, -1, Tk_Offset(TkText, yScrollCmd),
	DEF_TEXT_YSCROLL_COMMAND, TCL_INDEX_NONE, offsetof(TkText, yScrollCmd),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_END, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0}
};

/*
 * These three typedefs, the structure and the SearchPerform, SearchCore
 * functions below are used for line-based searches of the text widget, and,
275
276
277
278
279
280
281
282

283
284
285

286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301

302
303
304

305
306
307
308
309
310
311
275
276
277
278
279
280
281

282
283
284

285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300

301
302
303

304
305
306
307
308
309
310
311







-
+


-
+















-
+


-
+







typedef ClientData	SearchAddLineProc(int lineNum,
			    struct SearchSpec *searchSpecPtr,
			    Tcl_Obj *theLine, int *lenPtr,
			    int *extraLinesPtr);
typedef int		SearchMatchProc(int lineNum,
			    struct SearchSpec *searchSpecPtr,
			    ClientData clientData, Tcl_Obj *theLine,
			    int matchOffset, int matchLength);
			    TkSizeT matchOffset, TkSizeT matchLength);
typedef int		SearchLineIndexProc(Tcl_Interp *interp,
			    Tcl_Obj *objPtr, struct SearchSpec *searchSpecPtr,
			    int *linePosPtr, int *offsetPosPtr);
			    int *linePosPtr, TkSizeT *offsetPosPtr);

typedef struct SearchSpec {
    int exact;			/* Whether search is exact or regexp. */
    int noCase;			/* Case-insenstivive? */
    int noLineStop;		/* If not set, a regexp search will use the
				 * TCL_REG_NLSTOP flag. */
    int overlap;		/* If set, results from multiple searches
				 * (-all) are allowed to overlap each
				 * other. */
    int strictLimits;		/* If set, matches must be completely inside
				 * the from,to range. Otherwise the limits
				 * only apply to the start of each match. */
    int all;			/* Whether all or the first match should be
				 * reported. */
    int startLine;		/* First line to examine. */
    int startOffset;		/* Index in first line to start at. */
    TkSizeT startOffset;		/* Index in first line to start at. */
    int stopLine;		/* Last line to examine, or -1 when we search
				 * all available text. */
    int stopOffset;		/* Index to stop at, provided stopLine is not
    TkSizeT stopOffset;		/* Index to stop at, provided stopLine is not
				 * -1. */
    int numLines;		/* Total lines which are available. */
    int backwards;		/* Searching forwards or backwards. */
    Tcl_Obj *varPtr;		/* If non-NULL, store length(s) of match(es)
				 * in this variable. */
    Tcl_Obj *countPtr;		/* Keeps track of currently found lengths. */
    Tcl_Obj *resPtr;		/* Keeps track of currently found locations */
361
362
363
364
365
366
367
368
369


370
371
372
373
374
375
376
361
362
363
364
365
366
367


368
369
370
371
372
373
374
375
376







-
-
+
+







static void		TextBlinkProc(ClientData clientData);
static void		TextCmdDeletedProc(ClientData clientData);
static int		CreateWidget(TkSharedText *sharedPtr, Tk_Window tkwin,
			    Tcl_Interp *interp, const TkText *parent,
			    int objc, Tcl_Obj *const objv[]);
static void		TextEventProc(ClientData clientData,
			    XEvent *eventPtr);
static int		TextFetchSelection(ClientData clientData, int offset,
			    char *buffer, int maxBytes);
static TkSizeT	TextFetchSelection(ClientData clientData, TkSizeT offset,
			    char *buffer, TkSizeT maxBytes);
static int		TextIndexSortProc(const void *first,
			    const void *second);
static int		TextInsertCmd(TkSharedText *sharedTextPtr,
			    TkText *textPtr, Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[],
			    const TkTextIndex *indexPtr, int viewUpdate);
static int		TextReplaceCmd(TkText *textPtr, Tcl_Interp *interp,
406
407
408
409
410
411
412
413
414


415
416
417
418
419
420
421
406
407
408
409
410
411
412


413
414
415
416
417
418
419
420
421







-
-
+
+







static void		GenerateModifiedEvent(TkText *textPtr);
static void		GenerateUndoStackEvent(TkText *textPtr);
static void		UpdateDirtyFlag(TkSharedText *sharedPtr);
static void		TextPushUndoAction(TkText *textPtr,
			    Tcl_Obj *undoString, int insert,
			    const TkTextIndex *index1Ptr,
			    const TkTextIndex *index2Ptr);
static int		TextSearchIndexInLine(const SearchSpec *searchSpecPtr,
			    TkTextLine *linePtr, int byteIndex);
static TkSizeT		TextSearchIndexInLine(const SearchSpec *searchSpecPtr,
			    TkTextLine *linePtr, TkSizeT byteIndex);
static int		TextPeerCmd(TkText *textPtr, Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
static TkUndoProc	TextUndoRedoCallback;

/*
 * Declarations of the three search procs required by the multi-line search
 * routines.
457
458
459
460
461
462
463
464

465
466
467
468
469
470
471
457
458
459
460
461
462
463

464
465
466
467
468
469
470
471







-
+







int
Tk_TextObjCmd(
    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;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "pathName ?-option value ...?");
	return TCL_ERROR;
    }

    return CreateWidget(NULL, tkwin, interp, NULL, objc, objv);
498
499
500
501
502
503
504
505

506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526

527
528
529
530
531
532
533
534
535
536
537

538
539
540
541
542
543
544
498
499
500
501
502
503
504

505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525

526
527
528
529
530
531
532
533
534
535
536

537
538
539
540
541
542
543
544







-
+




















-
+










-
+







    Tk_Window tkwin,		/* Main window associated with interpreter. */
    Tcl_Interp *interp,		/* Current interpreter. */
    const TkText *parent,	/* If non-NULL then take default start, end
				 * from this parent. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    register TkText *textPtr;
    TkText *textPtr;
    Tk_OptionTable optionTable;
    TkTextIndex startIndex;
    Tk_Window newWin;

    /*
     * Create the window.
     */

    newWin = Tk_CreateWindowFromPath(interp, tkwin, Tcl_GetString(objv[1]),
	    NULL);
    if (newWin == NULL) {
	return TCL_ERROR;
    }

    /*
     * Create the text widget and initialize everything to zero, then set the
     * necessary initial (non-NULL) values. It is important that the 'set' tag
     * and 'insert', 'current' mark pointers are all NULL to start.
     */

    textPtr = ckalloc(sizeof(TkText));
    textPtr = (TkText *)ckalloc(sizeof(TkText));
    memset(textPtr, 0, sizeof(TkText));

    textPtr->tkwin = newWin;
    textPtr->display = Tk_Display(newWin);
    textPtr->interp = interp;
    textPtr->widgetCmd = Tcl_CreateObjCommand(interp,
	    Tk_PathName(textPtr->tkwin), TextWidgetObjCmd,
	    textPtr, TextCmdDeletedProc);

    if (sharedPtr == NULL) {
	sharedPtr = ckalloc(sizeof(TkSharedText));
	sharedPtr = (TkSharedText *)ckalloc(sizeof(TkSharedText));
	memset(sharedPtr, 0, sizeof(TkSharedText));

	sharedPtr->refCount = 0;
	sharedPtr->peers = NULL;
	sharedPtr->tree = TkBTreeCreate(sharedPtr);

	Tcl_InitHashTable(&sharedPtr->tagTable, TCL_STRING_KEYS);
628
629
630
631
632
633
634
635

636
637
638
639
640
641
642
628
629
630
631
632
633
634

635
636
637
638
639
640
641
642







-
+








    /*
     * Note: it is important that textPtr->selTagPtr is NULL before this
     * initial call.
     */

    textPtr->selTagPtr = TkTextCreateTag(textPtr, "sel", NULL);
    textPtr->selTagPtr->reliefString =
    textPtr->selTagPtr->reliefString = (char *)
	    ckalloc(sizeof(DEF_TEXT_SELECT_RELIEF));
    strcpy(textPtr->selTagPtr->reliefString, DEF_TEXT_SELECT_RELIEF);
    Tk_GetRelief(interp, DEF_TEXT_SELECT_RELIEF, &textPtr->selTagPtr->relief);
    textPtr->currentMarkPtr = TkTextSetMark(textPtr, "current", &startIndex);
    textPtr->insertMarkPtr = TkTextSetMark(textPtr, "insert", &startIndex);

    /*
656
657
658
659
660
661
662
663

664
665
666
667
668
669
670
671
672
673

674
675
676
677
678
679
680
656
657
658
659
660
661
662

663
664
665
666
667
668
669
670
671
672

673
674
675
676
677
678
679
680







-
+









-
+







    Tk_CreateEventHandler(textPtr->tkwin, KeyPressMask|KeyReleaseMask
	    |ButtonPressMask|ButtonReleaseMask|EnterWindowMask
	    |LeaveWindowMask|PointerMotionMask|VirtualEventMask,
	    TkTextBindProc, textPtr);
    Tk_CreateSelHandler(textPtr->tkwin, XA_PRIMARY, XA_STRING,
	    TextFetchSelection, textPtr, XA_STRING);

    if (Tk_InitOptions(interp, (char *) textPtr, optionTable, textPtr->tkwin)
    if (Tk_InitOptions(interp, textPtr, optionTable, textPtr->tkwin)
	    != TCL_OK) {
	Tk_DestroyWindow(textPtr->tkwin);
	return TCL_ERROR;
    }
    if (ConfigureText(interp, textPtr, objc-2, objv+2) != TCL_OK) {
	Tk_DestroyWindow(textPtr->tkwin);
	return TCL_ERROR;
    }

    Tcl_SetObjResult(interp, TkNewWindowObj(textPtr->tkwin));
    Tcl_SetObjResult(interp, Tk_NewWindowObj(textPtr->tkwin));
    return TCL_OK;
}

/*
 *--------------------------------------------------------------
 *
 * TextWidgetObjCmd --
695
696
697
698
699
700
701
702

703
704

705
706
707
708
709
710
711
695
696
697
698
699
700
701

702
703

704
705
706
707
708
709
710
711







-
+

-
+







static int
TextWidgetObjCmd(
    ClientData clientData,	/* Information about text widget. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    register TkText *textPtr = clientData;
    TkText *textPtr = (TkText *)clientData;
    int result = TCL_OK;
    int index;
    int idx;

    static const char *const optionStrings[] = {
	"bbox", "cget", "compare", "configure", "count", "debug", "delete",
	"dlineinfo", "dump", "edit", "get", "image", "index", "insert",
	"mark", "peer", "pendingsync", "replace", "scan", "search",
	"see", "sync", "tag", "window", "xview", "yview", NULL
    };
720
721
722
723
724
725
726
727

728
729
730
731
732

733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754




755
756
757
758
759
760
761
762
763
764
765
766

767
768
769
770
771
772
773
720
721
722
723
724
725
726

727
728
729
730
731

732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750




751
752
753
754
755
756
757
758
759
760
761
762
763
764
765

766
767
768
769
770
771
772
773







-
+




-
+


















-
-
-
-
+
+
+
+











-
+








    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
	return TCL_ERROR;
    }

    if (Tcl_GetIndexFromObjStruct(interp, objv[1], optionStrings,
	    sizeof(char *), "option", 0, &index) != TCL_OK) {
	    sizeof(char *), "option", 0, &idx) != TCL_OK) {
	return TCL_ERROR;
    }
    textPtr->refCount++;

    switch ((enum options) index) {
    switch ((enum options) idx) {
    case TEXT_BBOX: {
	int x, y, width, height;
	const TkTextIndex *indexPtr;

	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "index");
	    result = TCL_ERROR;
	    goto done;
	}
	indexPtr = TkTextGetIndexFromObj(interp, textPtr, objv[2]);
	if (indexPtr == NULL) {
	    result = TCL_ERROR;
	    goto done;
	}
	if (TkTextIndexBbox(textPtr, indexPtr, &x, &y, &width, &height,
		NULL) == 0) {
	    Tcl_Obj *listObj = Tcl_NewListObj(0, NULL);

	    Tcl_ListObjAppendElement(interp, listObj, Tcl_NewIntObj(x));
	    Tcl_ListObjAppendElement(interp, listObj, Tcl_NewIntObj(y));
	    Tcl_ListObjAppendElement(interp, listObj, Tcl_NewIntObj(width));
	    Tcl_ListObjAppendElement(interp, listObj, Tcl_NewIntObj(height));
	    Tcl_ListObjAppendElement(interp, listObj, Tcl_NewWideIntObj(x));
	    Tcl_ListObjAppendElement(interp, listObj, Tcl_NewWideIntObj(y));
	    Tcl_ListObjAppendElement(interp, listObj, Tcl_NewWideIntObj(width));
	    Tcl_ListObjAppendElement(interp, listObj, Tcl_NewWideIntObj(height));

	    Tcl_SetObjResult(interp, listObj);
	}
	break;
    }
    case TEXT_CGET:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "option");
	    result = TCL_ERROR;
	    goto done;
	} else {
	    Tcl_Obj *objPtr = Tk_GetOptionValue(interp, (char *) textPtr,
	    Tcl_Obj *objPtr = Tk_GetOptionValue(interp, textPtr,
		    textPtr->optionTable, objv[2], textPtr->tkwin);

	    if (objPtr == NULL) {
		result = TCL_ERROR;
		goto done;
	    }
	    Tcl_SetObjResult(interp, objPtr);
822
823
824
825
826
827
828
829

830
831
832
833
834
835
836
822
823
824
825
826
827
828

829
830
831
832
833
834
835
836







-
+







		" <, <=, ==, >=, >, or !=", Tcl_GetString(objv[3])));
	Tcl_SetErrorCode(interp, "TK", "VALUE", "COMPARISON", NULL);
	result = TCL_ERROR;
	goto done;
    }
    case TEXT_CONFIGURE:
	if (objc <= 3) {
	    Tcl_Obj *objPtr = Tk_GetOptionInfo(interp, (char *) textPtr,
	    Tcl_Obj *objPtr = Tk_GetOptionInfo(interp, textPtr,
		    textPtr->optionTable, ((objc == 3) ? objv[2] : NULL),
		    textPtr->tkwin);

	    if (objPtr == NULL) {
		result = TCL_ERROR;
		goto done;
	    }
860
861
862
863
864
865
866
867
868


869
870
871
872
873
874
875
876
877
878
860
861
862
863
864
865
866


867
868
869
870

871
872
873
874
875
876
877







-
-
+
+


-







	if (indexToPtr == NULL) {
	    result = TCL_ERROR;
	    goto done;
	}

	for (i = 2; i < objc-2; i++) {
	    int value;
	    size_t length;
	    const char *option = Tcl_GetString(objv[i]);
	    TkSizeT length;
	    const char *option = TkGetStringFromObj(objv[i], &length);
	    char c;

	    length = objv[i]->length;
	    if (length < 2 || option[0] != '-') {
		goto badOption;
	    }
	    c = option[1];
	    if (c == 'c' && !strncmp("-chars", option, length)) {
		value = CountIndices(textPtr, indexFromPtr, indexToPtr,
			COUNT_CHARS);
1016
1017
1018
1019
1020
1021
1022
1023

1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035

1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047

1048
1049
1050
1051
1052
1053
1054
1055

1056
1057
1058
1059
1060
1061
1062
1015
1016
1017
1018
1019
1020
1021

1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033

1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045

1046
1047
1048
1049
1050
1051
1052
1053

1054
1055
1056
1057
1058
1059
1060
1061







-
+











-
+











-
+







-
+







	    } else {
		goto badOption;
	    }

	countDone:
	    found++;
	    if (found == 1) {
		Tcl_SetObjResult(interp, Tcl_NewIntObj(value));
		Tcl_SetObjResult(interp, Tcl_NewWideIntObj(value));
	    } else {
		if (found == 2) {
		    /*
		     * Move the first item we put into the result into the
		     * first element of the list object.
		     */

		    objPtr = Tcl_NewObj();
		    Tcl_ListObjAppendElement(NULL, objPtr,
			    Tcl_GetObjResult(interp));
		}
		Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewIntObj(value));
		Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewWideIntObj(value));
	    }
	}

	if (found == 0) {
	    /*
	     * Use the default '-indices'.
	     */

	    int value = CountIndices(textPtr, indexFromPtr, indexToPtr,
		    COUNT_INDICES);

	    Tcl_SetObjResult(interp, Tcl_NewIntObj(value));
	    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(value));
	} else if (found > 1) {
	    Tcl_SetObjResult(interp, objPtr);
	}
	break;

    badOption:
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"bad option \"%s\" must be -chars, -displaychars, "
		"bad option \"%s\": must be -chars, -displaychars, "
		"-displayindices, -displaylines, -indices, -lines, -update, "
		"-xpixels, or -ypixels", Tcl_GetString(objv[i])));
	Tcl_SetErrorCode(interp, "TK", "TEXT", "INDEX_OPTION", NULL);
	result = TCL_ERROR;
	goto done;
    }
    case TEXT_DEBUG:
1122
1123
1124
1125
1126
1127
1128
1129

1130
1131
1132
1133
1134
1135
1136
1121
1122
1123
1124
1125
1126
1127

1128
1129
1130
1131
1132
1133
1134
1135







-
+








		TkTextIndex *indices, *ixStart, *ixEnd, *lastStart;
		char *useIdx;
		int i;

		objc -= 2;
		objv += 2;
		indices = ckalloc((objc + 1) * sizeof(TkTextIndex));
		indices = (TkTextIndex *)ckalloc((objc + 1) * sizeof(TkTextIndex));

		/*
		 * First pass verifies that all indices are valid.
		 */

		for (i = 0; i < objc; i++) {
		    const TkTextIndex *indexPtr =
1150
1151
1152
1153
1154
1155
1156
1157
1158


1159
1160
1161
1162
1163
1164
1165
1149
1150
1151
1152
1153
1154
1155


1156
1157
1158
1159
1160
1161
1162
1163
1164







-
-
+
+








		if (objc & 1) {
		    indices[i] = indices[i-1];
		    TkTextIndexForwChars(NULL, &indices[i], 1, &indices[i],
			    COUNT_INDICES);
		    objc++;
		}
		useIdx = ckalloc(objc);
		memset(useIdx, 0, (size_t) objc);
		useIdx = (char *)ckalloc(objc);
		memset(useIdx, 0, objc);

		/*
		 * Do a decreasing order sort so that we delete the end ranges
		 * first to maintain index consistency.
		 */

		qsort(indices, (size_t) objc / 2,
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247





1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263

1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279

1280
1281
1282
1283
1284
1285

1286
1287
1288
1289
1290
1291
1292
1293
1235
1236
1237
1238
1239
1240
1241





1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261

1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277

1278

1279
1280
1281
1282

1283

1284
1285
1286
1287
1288
1289
1290







-
-
-
-
-
+
+
+
+
+















-
+















-
+
-




-
+
-







	    result = TCL_ERROR;
	    goto done;
	}
	if (TkTextDLineInfo(textPtr, indexPtr, &x, &y, &width, &height,
		&base) == 0) {
	    Tcl_Obj *listObj = Tcl_NewListObj(0, NULL);

	    Tcl_ListObjAppendElement(interp, listObj, Tcl_NewIntObj(x));
	    Tcl_ListObjAppendElement(interp, listObj, Tcl_NewIntObj(y));
	    Tcl_ListObjAppendElement(interp, listObj, Tcl_NewIntObj(width));
	    Tcl_ListObjAppendElement(interp, listObj, Tcl_NewIntObj(height));
	    Tcl_ListObjAppendElement(interp, listObj, Tcl_NewIntObj(base));
	    Tcl_ListObjAppendElement(interp, listObj, Tcl_NewWideIntObj(x));
	    Tcl_ListObjAppendElement(interp, listObj, Tcl_NewWideIntObj(y));
	    Tcl_ListObjAppendElement(interp, listObj, Tcl_NewWideIntObj(width));
	    Tcl_ListObjAppendElement(interp, listObj, Tcl_NewWideIntObj(height));
	    Tcl_ListObjAppendElement(interp, listObj, Tcl_NewWideIntObj(base));

	    Tcl_SetObjResult(interp, listObj);
	}
	break;
    }
    case TEXT_DUMP:
	result = TextDumpCmd(textPtr, interp, objc, objv);
	break;
    case TEXT_EDIT:
	result = TextEditCmd(textPtr, interp, objc, objv);
	break;
    case TEXT_GET: {
	Tcl_Obj *objPtr = NULL;
	int i, found = 0, visible = 0;
	const char *name;
	size_t length;
	TkSizeT length;

	if (objc < 3) {
	    Tcl_WrongNumArgs(interp, 2, objv,
		    "?-displaychars? ?--? index1 ?index2 ...?");
	    result = TCL_ERROR;
	    goto done;
	}

	/*
	 * Simple, restrictive argument parsing. The only options are -- and
	 * -displaychars (or any unique prefix).
	 */

	i = 2;
	if (objc > 3) {
	    name = Tcl_GetString(objv[i]);
	    name = TkGetStringFromObj(objv[i], &length);
	    length = objv[i]->length;
	    if (length > 1 && name[0] == '-') {
		if (strncmp("-displaychars", name, length) == 0) {
		    i++;
		    visible = 1;
		    name = Tcl_GetString(objv[i]);
		    name = TkGetStringFromObj(objv[i], &length);
		    length = objv[i]->length;
		}
		if ((i < objc-1) && (length == 2) && !strcmp("--", name)) {
		    i++;
		}
	    }
	}

1606
1607
1608
1609
1610
1611
1612
1613

1614
1615
1616
1617
1618
1619
1620
1603
1604
1605
1606
1607
1608
1609

1610
1611
1612
1613
1614
1615
1616
1617







-
+







static int
SharedTextObjCmd(
    ClientData clientData,	/* Information about shared test B-tree. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    register TkSharedText *sharedPtr = clientData;
    TkSharedText *sharedPtr = (TkSharedText *)clientData;
    int result = TCL_OK;
    int index;

    static const char *const optionStrings[] = {
	"delete", "insert", NULL
    };
    enum options {
1752
1753
1754
1755
1756
1757
1758
1759

1760
1761
1762
1763
1764
1765
1766
1749
1750
1751
1752
1753
1754
1755

1756
1757
1758
1759
1760
1761
1762
1763







-
+







	    Tcl_WrongNumArgs(interp, 3, objv, NULL);
	    return TCL_ERROR;
	}
	peersObj = Tcl_NewObj();
	while (tPtr != NULL) {
	    if (tPtr != textPtr) {
		Tcl_ListObjAppendElement(NULL, peersObj,
			TkNewWindowObj(tPtr->tkwin));
			Tk_NewWindowObj(tPtr->tkwin));
	    }
	    tPtr = tPtr->next;
	}
	Tcl_SetObjResult(interp, peersObj);
    }
    }

1976
1977
1978
1979
1980
1981
1982
1983

1984
1985
1986
1987
1988
1989
1990
1973
1974
1975
1976
1977
1978
1979

1980
1981
1982
1983
1984
1985
1986
1987







-
+







	/*
	 * Free up any embedded windows which belong to this widget.
	 */

	for (hPtr = Tcl_FirstHashEntry(&sharedTextPtr->windowTable, &search);
		hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
	    TkTextEmbWindowClient *loop;
	    TkTextSegment *ewPtr = Tcl_GetHashValue(hPtr);
	    TkTextSegment *ewPtr = (TkTextSegment *)Tcl_GetHashValue(hPtr);

	    loop = ewPtr->body.ew.clients;
	    if (loop->textPtr == textPtr) {
		ewPtr->body.ew.clients = loop->next;
		TkTextWinFreeClient(hPtr, loop);
	    } else {
		TkTextEmbWindowClient *client = ewPtr->body.ew.clients;
2008
2009
2010
2011
2012
2013
2014
2015

2016
2017
2018
2019
2020
2021
2022
2005
2006
2007
2008
2009
2010
2011

2012
2013
2014
2015
2016
2017
2018
2019







-
+







	 * everything in one go, more quickly.
	 */

	TkBTreeDestroy(sharedTextPtr->tree);

	for (hPtr = Tcl_FirstHashEntry(&sharedTextPtr->tagTable, &search);
		hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
	    tagPtr = Tcl_GetHashValue(hPtr);
	    tagPtr = (TkTextTag *)Tcl_GetHashValue(hPtr);

	    /*
	     * No need to use 'TkTextDeleteTag' since we've already removed
	     * the B-tree completely.
	     */

	    TkTextFreeTag(textPtr, tagPtr);
2074
2075
2076
2077
2078
2079
2080
2081

2082
2083
2084
2085
2086
2087
2088
2071
2072
2073
2074
2075
2076
2077

2078
2079
2080
2081
2082
2083
2084
2085







-
+







 *
 *----------------------------------------------------------------------
 */

static int
ConfigureText(
    Tcl_Interp *interp,		/* Used for error reporting. */
    register TkText *textPtr,	/* Information about widget; may or may not
    TkText *textPtr,	/* Information about widget; may or may not
				 * already have values for some fields. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tk_SavedOptions savedOptions;
    int oldExport = (textPtr->exportSelection) && (!Tcl_IsSafe(textPtr->interp));
    int mask = 0;
2377
2378
2379
2380
2381
2382
2383
2384

2385
2386
2387
2388
2389
2390
2391
2374
2375
2376
2377
2378
2379
2380

2381
2382
2383
2384
2385
2386
2387
2388







-
+







 *---------------------------------------------------------------------------
 */

static void
TextWorldChangedCallback(
    ClientData instanceData)	/* Information about widget. */
{
    TkText *textPtr = instanceData;
    TkText *textPtr = (TkText *)instanceData;

    TextWorldChanged(textPtr, TK_TEXT_LINE_GEOMETRY);
}

/*
 *---------------------------------------------------------------------------
 *
2466
2467
2468
2469
2470
2471
2472
2473

2474
2475

2476
2477
2478
2479
2480
2481
2482
2463
2464
2465
2466
2467
2468
2469

2470
2471

2472
2473
2474
2475
2476
2477
2478
2479







-
+

-
+







 *
 *--------------------------------------------------------------
 */

static void
TextEventProc(
    ClientData clientData,	/* Information about window. */
    register XEvent *eventPtr)	/* Information about event. */
    XEvent *eventPtr)	/* Information about event. */
{
    register TkText *textPtr = clientData;
    TkText *textPtr = (TkText *)clientData;
    TkTextIndex index, index2;

    if (eventPtr->type == Expose) {
	TkTextRedrawRegion(textPtr, eventPtr->xexpose.x,
		eventPtr->xexpose.y, eventPtr->xexpose.width,
		eventPtr->xexpose.height);
    } else if (eventPtr->type == ConfigureNotify) {
2577
2578
2579
2580
2581
2582
2583
2584

2585
2586
2587
2588
2589
2590
2591
2574
2575
2576
2577
2578
2579
2580

2581
2582
2583
2584
2585
2586
2587
2588







-
+







 *----------------------------------------------------------------------
 */

static void
TextCmdDeletedProc(
    ClientData clientData)	/* Pointer to widget record for widget. */
{
    TkText *textPtr = clientData;
    TkText *textPtr = (TkText *)clientData;
    Tk_Window tkwin = textPtr->tkwin;

    /*
     * This function could be invoked either because the window was destroyed
     * and the command was then deleted (in which this flag is already set) or
     * because the command was deleted, and then this function destroys the
     * widget.
2630
2631
2632
2633
2634
2635
2636
2637

2638
2639
2640
2641
2642

2643
2644
2645
2646
2647
2648
2649
2650
2651
2627
2628
2629
2630
2631
2632
2633

2634
2635
2636
2637
2638

2639
2640

2641
2642
2643
2644
2645
2646
2647







-
+




-
+

-







				 * modified if the index is not valid for
				 * insertion (e.g. if at "end"). */
    Tcl_Obj *stringPtr,		/* Null-terminated string containing new
				 * information to add to text. */
    int viewUpdate)		/* Update the view if set. */
{
    int lineIndex;
    size_t length;
    TkSizeT length;
    TkText *tPtr;
    int *lineAndByteIndex;
    int resetViewCount;
    int pixels[2*PIXEL_CLIENTS];
    const char *string = Tcl_GetString(stringPtr);
    const char *string = TkGetStringFromObj(stringPtr, &length);

    length = stringPtr->length;
    if (sharedTextPtr == NULL) {
	sharedTextPtr = textPtr->sharedTextPtr;
    }

    /*
     * Don't allow insertions on the last (dummy) line of the text. This is
     * the only place in this function where the indexPtr is modified.
2663
2664
2665
2666
2667
2668
2669
2670

2671
2672
2673
2674
2675
2676
2677
2659
2660
2661
2662
2663
2664
2665

2666
2667
2668
2669
2670
2671
2672
2673







-
+







     * insertion. If the insertion occurs on the top line of the widget
     * (textPtr->topIndex), then we have to recompute topIndex after the
     * insertion, since the insertion could invalidate it.
     */

    resetViewCount = 0;
    if (sharedTextPtr->refCount > PIXEL_CLIENTS) {
	lineAndByteIndex = ckalloc(sizeof(int) * 2 * sharedTextPtr->refCount);
	lineAndByteIndex = (int *)ckalloc(sizeof(int) * 2 * sharedTextPtr->refCount);
    } else {
	lineAndByteIndex = pixels;
    }
    for (tPtr = sharedTextPtr->peers; tPtr != NULL ; tPtr = tPtr->next) {
	lineAndByteIndex[resetViewCount] = -1;
	if (indexPtr->linePtr == tPtr->topIndex.linePtr) {
	    lineAndByteIndex[resetViewCount] =
2778
2779
2780
2781
2782
2783
2784



2785
2786
2787
2788
2789
2790
2791
2792
2793
2794




2795
2796
2797
2798
2799
2800
2801
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804







+
+
+










+
+
+
+







    const TkTextIndex *index1Ptr,
				/* Index describing first location. */
    const TkTextIndex *index2Ptr)
				/* Index describing second location. */
{
    TkUndoSubAtom *iAtom, *dAtom;
    int canUndo, canRedo;
    char lMarkName[20] = "tk::undoMarkL";
    char rMarkName[20] = "tk::undoMarkR";
    char stringUndoMarkId[16] = "";

    /*
     * Create the helpers.
     */

    Tcl_Obj *seeInsertObj = Tcl_NewObj();
    Tcl_Obj *markSet1InsertObj = Tcl_NewObj();
    Tcl_Obj *markSet2InsertObj = NULL;
    Tcl_Obj *insertCmdObj = Tcl_NewObj();
    Tcl_Obj *deleteCmdObj = Tcl_NewObj();
    Tcl_Obj *markSetLUndoMarkCmdObj = Tcl_NewObj();
    Tcl_Obj *markSetRUndoMarkCmdObj = NULL;
    Tcl_Obj *markGravityLUndoMarkCmdObj = Tcl_NewObj();
    Tcl_Obj *markGravityRUndoMarkCmdObj = NULL;

    /*
     * Get the index positions.
     */

    Tcl_Obj *index1Obj = TkTextNewIndexObj(NULL, index1Ptr);
    Tcl_Obj *index2Obj = TkTextNewIndexObj(NULL, index2Ptr);
2837
2838
2839
2840
2841
2842
2843


































2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860




2861
2862
2863
2864
2865




2866
2867
2868
2869
2870
2871
2872
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

















+
+
+
+





+
+
+
+







    Tcl_ListObjAppendElement(NULL, insertCmdObj, undoString);

    Tcl_ListObjAppendElement(NULL, deleteCmdObj,
	    Tcl_NewStringObj("delete", 6));
    Tcl_ListObjAppendElement(NULL, deleteCmdObj, index1Obj);
    Tcl_ListObjAppendElement(NULL, deleteCmdObj, index2Obj);

    Tcl_ListObjAppendElement(NULL, markSetLUndoMarkCmdObj,
	    Tcl_NewStringObj(Tk_PathName(textPtr->tkwin), -1));
    Tcl_ListObjAppendElement(NULL, markSetLUndoMarkCmdObj,
	    Tcl_NewStringObj("mark", 4));
    Tcl_ListObjAppendElement(NULL, markSetLUndoMarkCmdObj,
	    Tcl_NewStringObj("set", 3));
    markSetRUndoMarkCmdObj = Tcl_DuplicateObj(markSetLUndoMarkCmdObj);
    textPtr->sharedTextPtr->undoMarkId++;
    sprintf(stringUndoMarkId, "%d", textPtr->sharedTextPtr->undoMarkId);
    strcat(lMarkName, stringUndoMarkId);
    strcat(rMarkName, stringUndoMarkId);
    Tcl_ListObjAppendElement(NULL, markSetLUndoMarkCmdObj,
	    Tcl_NewStringObj(lMarkName, -1));
    Tcl_ListObjAppendElement(NULL, markSetRUndoMarkCmdObj,
	    Tcl_NewStringObj(rMarkName, -1));
    Tcl_ListObjAppendElement(NULL, markSetLUndoMarkCmdObj, index1Obj);
    Tcl_ListObjAppendElement(NULL, markSetRUndoMarkCmdObj, index2Obj);

    Tcl_ListObjAppendElement(NULL, markGravityLUndoMarkCmdObj,
	    Tcl_NewStringObj(Tk_PathName(textPtr->tkwin), -1));
    Tcl_ListObjAppendElement(NULL, markGravityLUndoMarkCmdObj,
	    Tcl_NewStringObj("mark", 4));
    Tcl_ListObjAppendElement(NULL, markGravityLUndoMarkCmdObj,
	    Tcl_NewStringObj("gravity", 7));
    markGravityRUndoMarkCmdObj = Tcl_DuplicateObj(markGravityLUndoMarkCmdObj);
    Tcl_ListObjAppendElement(NULL, markGravityLUndoMarkCmdObj,
	    Tcl_NewStringObj(lMarkName, -1));
    Tcl_ListObjAppendElement(NULL, markGravityRUndoMarkCmdObj,
	    Tcl_NewStringObj(rMarkName, -1));
    Tcl_ListObjAppendElement(NULL, markGravityLUndoMarkCmdObj,
            Tcl_NewStringObj("left", 4));
    Tcl_ListObjAppendElement(NULL, markGravityRUndoMarkCmdObj,
            Tcl_NewStringObj("right", 5));

    /*
     * Note: we don't wish to use textPtr->widgetCmd in these callbacks
     * because if we delete the textPtr, but peers still exist, we will then
     * have references to a non-existent Tcl_Command in the undo stack, which
     * will lead to crashes later. Also, the behaviour of the widget w.r.t.
     * bindings (%W substitutions) always uses the widget path name, so there
     * is no good reason the undo stack should do otherwise.
     *
     * For the 'insert' and 'delete' actions, we have to register a functional
     * callback, because these actions are defined to operate on the
     * underlying data shared by all peers.
     */

    iAtom = TkUndoMakeSubAtom(&TextUndoRedoCallback, textPtr->sharedTextPtr,
	    insertCmdObj, NULL);
    TkUndoMakeCmdSubAtom(NULL, markSet2InsertObj, iAtom);
    TkUndoMakeCmdSubAtom(NULL, seeInsertObj, iAtom);
    TkUndoMakeCmdSubAtom(NULL, markSetLUndoMarkCmdObj, iAtom);
    TkUndoMakeCmdSubAtom(NULL, markSetRUndoMarkCmdObj, iAtom);
    TkUndoMakeCmdSubAtom(NULL, markGravityLUndoMarkCmdObj, iAtom);
    TkUndoMakeCmdSubAtom(NULL, markGravityRUndoMarkCmdObj, iAtom);

    dAtom = TkUndoMakeSubAtom(&TextUndoRedoCallback, textPtr->sharedTextPtr,
	    deleteCmdObj, NULL);
    TkUndoMakeCmdSubAtom(NULL, markSet1InsertObj, dAtom);
    TkUndoMakeCmdSubAtom(NULL, seeInsertObj, dAtom);
    TkUndoMakeCmdSubAtom(NULL, markSetLUndoMarkCmdObj, dAtom);
    TkUndoMakeCmdSubAtom(NULL, markSetRUndoMarkCmdObj, dAtom);
    TkUndoMakeCmdSubAtom(NULL, markGravityLUndoMarkCmdObj, dAtom);
    TkUndoMakeCmdSubAtom(NULL, markGravityRUndoMarkCmdObj, dAtom);

    Tcl_DecrRefCount(seeInsertObj);
    Tcl_DecrRefCount(index1Obj);
    Tcl_DecrRefCount(index2Obj);

    canUndo = TkUndoCanUndo(textPtr->sharedTextPtr->undoStack);
    canRedo = TkUndoCanRedo(textPtr->sharedTextPtr->undoStack);
2912
2913
2914
2915
2916
2917
2918
2919

2920
2921
2922
2923
2924
2925
2926
2957
2958
2959
2960
2961
2962
2963

2964
2965
2966
2967
2968
2969
2970
2971







-
+







TextUndoRedoCallback(
    Tcl_Interp *interp,		/* Current interpreter. */
    ClientData clientData,	/* Passed from undo code, but contains our
				 * shared text data structure. */
    Tcl_Obj *objPtr)		/* Arguments of a command to be handled by the
				 * shared text data structure. */
{
    TkSharedText *sharedPtr = clientData;
    TkSharedText *sharedPtr = (TkSharedText *)clientData;
    int res, objc;
    Tcl_Obj **objv;
    TkText *textPtr;

    res = Tcl_ListObjGetElements(interp, objPtr, &objc, &objv);
    if (res != TCL_OK) {
	return res;
3124
3125
3126
3127
3128
3129
3130
3131

3132
3133
3134
3135
3136
3137
3138
3169
3170
3171
3172
3173
3174
3175

3176
3177
3178
3179
3180
3181
3182
3183







-
+







     * deleted but tags might be removed.
     */

    line1 = TkBTreeLinesTo(textPtr, index1.linePtr);
    line2 = TkBTreeLinesTo(textPtr, index2.linePtr);
    if (line2 == TkBTreeNumLines(sharedTextPtr->tree, textPtr)) {
	TkTextTag **arrayPtr;
	int arraySize, i;
	int arraySize;
	TkTextIndex oldIndex2;

	oldIndex2 = index2;
	TkTextIndexBackChars(NULL, &oldIndex2, 1, &index2, COUNT_INDICES);
	line2--;
	if ((index1.byteIndex == 0) && (line1 != 0)) {
	    TkTextIndexBackChars(NULL, &index1, 1, &index1, COUNT_INDICES);
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160

3161
3162
3163
3164
3165
3166
3167
3196
3197
3198
3199
3200
3201
3202



3203
3204
3205
3206
3207
3208
3209
3210







-
-
-
+







     * For speed, we remove all tags from the range first. If we don't
     * do this, the code below can (when there are many tags) grow
     * non-linearly in execution time.
     */

    for (i=0, hPtr=Tcl_FirstHashEntry(&sharedTextPtr->tagTable, &search);
	    hPtr != NULL; i++, hPtr = Tcl_NextHashEntry(&search)) {
        TkTextTag *tagPtr = Tcl_GetHashValue(hPtr);

        TkBTreeTag(&index1, &index2, tagPtr, 0);
        TkBTreeTag(&index1, &index2, (TkTextTag *)Tcl_GetHashValue(hPtr), 0);
    }

    /*
     * Special case for the sel tag which is not in the hash table. We
     * need to do this once for each peer text widget.
     */

3187
3188
3189
3190
3191
3192
3193
3194

3195
3196
3197
3198
3199
3200
3201
3230
3231
3232
3233
3234
3235
3236

3237
3238
3239
3240
3241
3242
3243
3244







-
+







     * first character will be, then do the deletion, then reset the view.
     */

    TkTextChanged(sharedTextPtr, NULL, &index1, &index2);

    resetViewCount = 0;
    if (sharedTextPtr->refCount > PIXEL_CLIENTS) {
	lineAndByteIndex = ckalloc(sizeof(int) * 2 * sharedTextPtr->refCount);
	lineAndByteIndex = (int *)ckalloc(sizeof(int) * 2 * sharedTextPtr->refCount);
    } else {
	lineAndByteIndex = pixels;
    }
    for (tPtr = sharedTextPtr->peers; tPtr != NULL ; tPtr = tPtr->next) {
	int line = 0;
	int byteIndex = 0;
	int resetView = 0;
3366
3367
3368
3369
3370
3371
3372
3373

3374
3375
3376

3377
3378
3379

3380
3381
3382
3383

3384
3385


3386
3387
3388
3389
3390
3391
3392
3409
3410
3411
3412
3413
3414
3415

3416
3417
3418

3419
3420
3421

3422
3423
3424
3425

3426
3427

3428
3429
3430
3431
3432
3433
3434
3435
3436







-
+


-
+


-
+



-
+

-
+
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
static TkSizeT
TextFetchSelection(
    ClientData clientData,	/* Information about text widget. */
    int offset,			/* Offset within selection of first character
    TkSizeT offset,			/* Offset within selection of first character
				 * to be returned. */
    char *buffer,		/* Location in which to place selection. */
    int maxBytes)		/* Maximum number of bytes to place at buffer,
    TkSizeT maxBytes)		/* Maximum number of bytes to place at buffer,
				 * not including terminating NULL
				 * character. */
{
    register TkText *textPtr = clientData;
    TkText *textPtr = (TkText *)clientData;
    TkTextIndex eof;
    int count, chunkSize, offsetInSeg;
    int count, chunkSize;
    TkSizeT offsetInSeg;
    TkTextSearch search;
    TkTextSegment *segPtr;

    if ((!textPtr->exportSelection) || Tcl_IsSafe(textPtr->interp)) {
	return -1;
    }

3442
3443
3444
3445
3446
3447
3448
3449
3450


3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467

3468
3469
3470
3471
3472
3473
3474
3486
3487
3488
3489
3490
3491
3492


3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510

3511
3512
3513
3514
3515
3516
3517
3518







-
-
+
+
















-
+








	while (1) {
	    if (maxBytes == 0) {
		goto fetchDone;
	    }
	    segPtr = TkTextIndexToSeg(&textPtr->selIndex, &offsetInSeg);
	    chunkSize = segPtr->size - offsetInSeg;
	    if (chunkSize > maxBytes) {
		chunkSize = maxBytes;
	    if (chunkSize > (int)maxBytes) {
		chunkSize = (int)maxBytes;
	    }
	    if (textPtr->selIndex.linePtr == search.curIndex.linePtr) {
		int leftInRange;

		leftInRange = search.curIndex.byteIndex
			- textPtr->selIndex.byteIndex;
		if (leftInRange < chunkSize) {
		    chunkSize = leftInRange;
		    if (chunkSize <= 0) {
			break;
		    }
		}
	    }
	    if ((segPtr->typePtr == &tkTextCharType)
		    && !TkTextIsElided(textPtr, &textPtr->selIndex, NULL)) {
		memcpy(buffer, segPtr->body.chars + offsetInSeg,
			(size_t) chunkSize);
			chunkSize);
		buffer += chunkSize;
		maxBytes -= chunkSize;
		count += chunkSize;
	    }
	    TkTextIndexForwBytes(textPtr, &textPtr->selIndex, chunkSize,
		    &textPtr->selIndex);
	}
3507
3508
3509
3510
3511
3512
3513
3514

3515
3516

3517
3518
3519
3520
3521
3522
3523
3551
3552
3553
3554
3555
3556
3557

3558
3559

3560
3561
3562
3563
3564
3565
3566
3567







-
+

-
+







 *----------------------------------------------------------------------
 */

void
TkTextLostSelection(
    ClientData clientData)	/* Information about text widget. */
{
    register TkText *textPtr = clientData;
    TkText *textPtr = (TkText *)clientData;

    if (TkpAlwaysShowSelection(textPtr->tkwin)) {
    if (Tk_AlwaysShowSelection(textPtr->tkwin)) {
	TkTextIndex start, end;

	if ((!textPtr->exportSelection) || Tcl_IsSafe(textPtr->interp)) {
	    return;
	}

	/*
3567
3568
3569
3570
3571
3572
3573
3574

3575
3576
3577
3578
3579
3580
3581
3611
3612
3613
3614
3615
3616
3617

3618
3619
3620
3621
3622
3623
3624
3625







-
+







    TkText *textPtr)
{
    /*
     * Send an event that the selection changed. This is equivalent to:
     *     event generate $textWidget <<Selection>>
     */

    TkSendVirtualEvent(textPtr->tkwin, "Selection", NULL);
    Tk_SendVirtualEvent(textPtr->tkwin, "Selection", NULL);
}

/*
 *----------------------------------------------------------------------
 *
 * TextBlinkProc --
 *
3592
3593
3594
3595
3596
3597
3598
3599

3600
3601
3602
3603
3604
3605
3606
3636
3637
3638
3639
3640
3641
3642

3643
3644
3645
3646
3647
3648
3649
3650







-
+







 *----------------------------------------------------------------------
 */

static void
TextBlinkProc(
    ClientData clientData)	/* Pointer to record describing text. */
{
    register TkText *textPtr = clientData;
    TkText *textPtr = (TkText *)clientData;
    TkTextIndex index;
    int x, y, w, h, charWidth;

    if ((textPtr->state == TK_TEXT_STATE_DISABLED) ||
	    !(textPtr->flags & GOT_FOCUS) || (textPtr->insertOffTime == 0)) {
	if (!(textPtr->flags & GOT_FOCUS) &&
		(textPtr->insertUnfocussed != TK_TEXT_INSERT_NOFOCUS_NONE)) {
3967
3968
3969
3970
3971
3972
3973
3974

3975
3976
3977
3978
3979

3980
3981
3982
3983
3984
3985
3986
4011
4012
4013
4014
4015
4016
4017

4018
4019
4020
4021
4022

4023
4024
4025
4026
4027
4028
4029
4030







-
+




-
+








static int
TextSearchGetLineIndex(
    Tcl_Interp *interp,		/* For error messages. */
    Tcl_Obj *objPtr,		/* Contains a textual index like "1.2" */
    SearchSpec *searchSpecPtr,	/* Contains other search parameters. */
    int *linePosPtr,		/* For returning the line number. */
    int *offsetPosPtr)		/* For returning the text offset in the
    TkSizeT *offsetPosPtr)		/* For returning the text offset in the
				 * line. */
{
    const TkTextIndex *indexPtr;
    int line;
    TkText *textPtr = searchSpecPtr->clientData;
    TkText *textPtr = (TkText *)searchSpecPtr->clientData;

    indexPtr = TkTextGetIndexFromObj(interp, textPtr, objPtr);
    if (indexPtr == NULL) {
	return TCL_ERROR;
    }

    line = TkBTreeLinesTo(textPtr, indexPtr->linePtr);
4027
4028
4029
4030
4031
4032
4033
4034

4035
4036
4037
4038
4039

4040
4041
4042

4043
4044


4045
4046
4047
4048
4049
4050

4051
4052
4053
4054
4055

4056
4057
4058
4059
4060
4061
4062
4071
4072
4073
4074
4075
4076
4077

4078
4079
4080
4081
4082

4083
4084
4085
4086
4087


4088
4089
4090
4091
4092
4093
4094

4095
4096
4097
4098
4099

4100
4101
4102
4103
4104
4105
4106
4107







-
+




-
+



+
-
-
+
+





-
+




-
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
static TkSizeT
TextSearchIndexInLine(
    const SearchSpec *searchSpecPtr,
				/* Search parameters. */
    TkTextLine *linePtr,	/* The line we're looking at. */
    int byteIndex)		/* Index into the line. */
    TkSizeT byteIndex)		/* Index into the line. */
{
    TkTextSegment *segPtr;
    TkTextIndex curIndex;
    TkSizeT index;
    int index, leftToScan;
    TkText *textPtr = searchSpecPtr->clientData;
    int leftToScan;
    TkText *textPtr = (TkText *)searchSpecPtr->clientData;

    index = 0;
    curIndex.tree = textPtr->sharedTextPtr->tree;
    curIndex.linePtr = linePtr; curIndex.byteIndex = 0;
    for (segPtr = linePtr->segPtr, leftToScan = byteIndex;
	    leftToScan > 0;
	    leftToScan + 1 > 1;
	    curIndex.byteIndex += segPtr->size, segPtr = segPtr->nextPtr) {
	if ((segPtr->typePtr == &tkTextCharType) &&
		(searchSpecPtr->searchElide
		|| !TkTextIsElided(textPtr, &curIndex, NULL))) {
	    if (leftToScan < segPtr->size) {
	    if (leftToScan + 1 < (int)segPtr->size + 1) {
		if (searchSpecPtr->exact) {
		    index += leftToScan;
		} else {
		    index += Tcl_NumUtfChars(segPtr->body.chars, leftToScan);
		}
	    } else if (searchSpecPtr->exact) {
		index += segPtr->size;
4107
4108
4109
4110
4111
4112
4113
4114

4115
4116
4117
4118
4119
4120
4121
4152
4153
4154
4155
4156
4157
4158

4159
4160
4161
4162
4163
4164
4165
4166







-
+







				 * incremented by the number of additional
				 * logical lines which are merged into this
				 * one by newlines being elided. */
{
    TkTextLine *linePtr, *thisLinePtr;
    TkTextIndex curIndex;
    TkTextSegment *segPtr;
    TkText *textPtr = searchSpecPtr->clientData;
    TkText *textPtr = (TkText *)searchSpecPtr->clientData;
    int nothingYet = 1;

    /*
     * Extract the text from the line.
     */

    linePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree, textPtr, lineNum);
4219
4220
4221
4222
4223
4224
4225
4226

4227
4228

4229
4230
4231

4232
4233
4234
4235
4236

4237
4238
4239
4240
4241
4242
4243
4244
4245
4246

4247
4248
4249
4250
4251
4252
4253
4264
4265
4266
4267
4268
4269
4270

4271
4272

4273
4274
4275

4276
4277
4278
4279
4280

4281
4282
4283
4284
4285
4286
4287
4288
4289
4290

4291
4292
4293
4294
4295
4296
4297
4298







-
+

-
+


-
+




-
+









-
+







    ClientData clientData,	/* Token returned by the 'addNextLineProc',
				 * TextSearchAddNextLine. May be NULL, in
				 * which we case we must generate it (from
				 * lineNum). */
    Tcl_Obj *theLine,		/* Text from current line, only accessed for
				 * exact searches, and is allowed to be NULL
				 * for regexp searches. */
    int matchOffset,		/* Offset of found item in utf-8 bytes for
    TkSizeT matchOffset,		/* Offset of found item in utf-8 bytes for
				 * exact search, Unicode chars for regexp. */
    int matchLength)		/* Length also in bytes/chars as per search
    TkSizeT matchLength)		/* Length also in bytes/chars as per search
				 * type. */
{
    int numChars;
    TkSizeT numChars;
    int leftToScan;
    TkTextIndex curIndex, foundIndex;
    TkTextSegment *segPtr;
    TkTextLine *linePtr;
    TkText *textPtr = searchSpecPtr->clientData;
    TkText *textPtr = (TkText *)searchSpecPtr->clientData;

    if (lineNum == searchSpecPtr->stopLine) {
	/*
	 * If the current index is on the wrong side of the stopIndex, then
	 * the item we just found is actually outside the acceptable range,
	 * and the search is over.
	 */

	if (searchSpecPtr->backwards ^
		(matchOffset >= searchSpecPtr->stopOffset)) {
		(matchOffset + 1 >= searchSpecPtr->stopOffset + 1)) {
	    return 0;
	}
    }

    /*
     * Calculate the character count, which may need augmenting if there are
     * embedded windows or elidden text.
4264
4265
4266
4267
4268
4269
4270
4271

4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287

4288
4289
4290
4291
4292
4293
4294
4309
4310
4311
4312
4313
4314
4315

4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331

4332
4333
4334
4335
4336
4337
4338
4339







-
+















-
+







    /*
     * If we're using strict limits checking, ensure that the match with its
     * full length fits inside the given range.
     */

    if (searchSpecPtr->strictLimits && lineNum == searchSpecPtr->stopLine) {
	if (searchSpecPtr->backwards ^
		((matchOffset + numChars) > searchSpecPtr->stopOffset)) {
		((matchOffset + numChars + 1) > searchSpecPtr->stopOffset + 1)) {
	    return 0;
	}
    }

    /*
     * The index information returned by the regular expression parser only
     * considers textual information: it doesn't account for embedded windows,
     * elided text (when we are not searching elided text) or any other
     * non-textual info. Scan through the line's segments again to adjust both
     * matchChar and matchCount.
     *
     * We will walk through the segments of this line until we have either
     * reached the end of the match or we have reached the end of the line.
     */

    linePtr = clientData;
    linePtr = (TkTextLine *)clientData;
    if (linePtr == NULL) {
	linePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree, textPtr,
		lineNum);
    }

    curIndex.tree = textPtr->sharedTextPtr->tree;

4315
4316
4317
4318
4319
4320
4321
4322

4323
4324
4325
4326
4327
4328
4329
4360
4361
4362
4363
4364
4365
4366

4367
4368
4369
4370
4371
4372
4373
4374







-
+







		if (searchSpecPtr->exact) {
		    matchOffset += segPtr->size;
		} else {
		    matchOffset += Tcl_NumUtfChars(segPtr->body.chars, -1);
		}
	    } else {
		if (searchSpecPtr->exact) {
		    leftToScan -= segPtr->size;
		    leftToScan -= (int)segPtr->size;
		} else {
		    leftToScan -= Tcl_NumUtfChars(segPtr->body.chars, -1);
		}
	    }
	    curIndex.byteIndex += segPtr->size;
	}
	if (segPtr == NULL && leftToScan >= 0) {
4417
4418
4419
4420
4421
4422
4423
4424

4425
4426
4427
4428
4429
4430
4431
4462
4463
4464
4465
4466
4467
4468

4469
4470
4471
4472
4473
4474
4475
4476







-
+







    }

    /*
     * Now store the count result, if it is wanted.
     */

    if (searchSpecPtr->varPtr != NULL) {
	Tcl_Obj *tmpPtr = Tcl_NewIntObj(numChars);
	Tcl_Obj *tmpPtr = Tcl_NewWideIntObj(numChars);
	if (searchSpecPtr->all) {
	    if (searchSpecPtr->countPtr == NULL) {
		searchSpecPtr->countPtr = Tcl_NewObj();
	    }
	    Tcl_ListObjAppendElement(NULL, searchSpecPtr->countPtr, tmpPtr);
	} else {
	    searchSpecPtr->countPtr = tmpPtr;
4490
4491
4492
4493
4494
4495
4496
4497
4498


4499
4500
4501
4502
4503
4504
4505
4535
4536
4537
4538
4539
4540
4541


4542
4543
4544
4545
4546
4547
4548
4549
4550







-
-
+
+







	}
    }

    /*
     * Parse the elements of the list one at a time to fill in the array.
     */

    tabArrayPtr = ckalloc(sizeof(TkTextTabArray)
	    + (count - 1) * sizeof(TkTextTab));
    tabArrayPtr = (TkTextTabArray *)ckalloc(offsetof(TkTextTabArray, tabs)
	    + count * sizeof(TkTextTab));
    tabArrayPtr->numTabs = 0;
    prevStop = 0.0;
    lastStop = 0.0;
    for (i = 0, tabPtr = &tabArrayPtr->tabs[0]; i < objc; i++, tabPtr++) {
	int index;

	/*
4617
4618
4619
4620
4621
4622
4623
4624

4625
4626
4627
4628
4629
4630
4631
4662
4663
4664
4665
4666
4667
4668

4669
4670
4671
4672
4673
4674
4675
4676







-
+







 *	side effects).
 *
 *----------------------------------------------------------------------
 */

static int
TextDumpCmd(
    register TkText *textPtr,	/* Information about text widget. */
    TkText *textPtr,	/* Information about text widget. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. Someone else has already
				 * parsed this command enough to know that
				 * objv[1] is "dump". */
{
    TkTextIndex index1, index2;
4704
4705
4706
4707
4708
4709
4710
4711

4712
4713
4714
4715
4716
4717

4718
4719
4720
4721
4722
4723
4724
4725
4749
4750
4751
4752
4753
4754
4755

4756
4757
4758
4759
4760
4761

4762

4763
4764
4765
4766
4767
4768
4769







-
+





-
+
-







	return TCL_ERROR;
    }
    arg++;
    atEnd = 0;
    if (objc == arg) {
	TkTextIndexForwChars(NULL, &index1, 1, &index2, COUNT_INDICES);
    } else {
	size_t length;
	TkSizeT length;
	const char *str;

	if (TkTextGetObjIndex(interp, textPtr, objv[arg], &index2) != TCL_OK) {
	    return TCL_ERROR;
	}
	str = Tcl_GetString(objv[arg]);
	str = TkGetStringFromObj(objv[arg], &length);
	length = objv[arg]->length;
	if (strncmp(str, "end", length) == 0) {
	    atEnd = 1;
	}
    }
    if (TkTextIndexCmp(&index1, &index2) >= 0) {
	return TCL_OK;
    }
4855
4856
4857
4858
4859
4860
4861
4862

4863
4864
4865
4866
4867
4868
4869
4899
4900
4901
4902
4903
4904
4905

4906
4907
4908
4909
4910
4911
4912
4913







-
+







		 * To avoid modifying the string in place we copy over just
		 * the segment that we want. Since DumpSegment can modify the
		 * text, we could not confidently revert the modification
		 * here.
		 */

		int length = last - first;
		char *range = ckalloc(length + 1);
		char *range = (char *)ckalloc(length + 1);

		memcpy(range, segPtr->body.chars + first, length);
		range[length] = '\0';

		TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr,
			lineno, offset + first, &index);
		lineChanged = DumpSegment(textPtr, interp, "text", range,
4886
4887
4888
4889
4890
4891
4892
4893

4894
4895
4896
4897
4898
4899
4900
4930
4931
4932
4933
4934
4935
4936

4937
4938
4939
4940
4941
4942
4943
4944







-
+







		    name = "insert";
		} else if (segPtr == textPtr->currentMarkPtr) {
		    name = "current";
		} else if (markPtr->hPtr == NULL) {
		    name = NULL;
		    lineChanged = 0;
		} else {
		    name = Tcl_GetHashKey(&textPtr->sharedTextPtr->markTable,
		    name = (const char *)Tcl_GetHashKey(&textPtr->sharedTextPtr->markTable,
			    markPtr->hPtr);
		}
		if (name != NULL) {
		    TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr,
			    lineno, offset, &index);
		    lineChanged = DumpSegment(textPtr, interp, "mark", name,
			    command, &index, what);
5012
5013
5014
5015
5016
5017
5018
5019

5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034

5035
5036
5037
5038
5039
5040
5041
5042

5043
5044
5045
5046
5047
5048
5049
5056
5057
5058
5059
5060
5061
5062

5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077

5078
5079
5080
5081
5082
5083
5084
5085

5086
5087
5088
5089
5090
5091
5092
5093







-
+














-
+







-
+







DumpSegment(
    TkText *textPtr,
    Tcl_Interp *interp,
    const char *key,		/* Segment type key. */
    const char *value,		/* Segment value. */
    Tcl_Obj *command,		/* Script callback. */
    const TkTextIndex *index,	/* index with line/byte position info. */
    int what)			/* Look for TK_DUMP_INDEX bit. */
    TCL_UNUSED(int))		/* Look for TK_DUMP_INDEX bit. */
{
    char buffer[TK_POS_CHARS];
    Tcl_Obj *values[3], *tuple;

    TkTextPrintIndex(textPtr, index, buffer);
    values[0] = Tcl_NewStringObj(key, -1);
    values[1] = Tcl_NewStringObj(value, -1);
    values[2] = Tcl_NewStringObj(buffer, -1);
    tuple = Tcl_NewListObj(3, values);
    if (command == NULL) {
	Tcl_ListObjAppendList(NULL, Tcl_GetObjResult(interp), tuple);
	Tcl_DecrRefCount(tuple);
	return 0;
    } else {
	int oldStateEpoch = TkBTreeEpoch(textPtr->sharedTextPtr->tree);
	TkSizeT oldStateEpoch = TkBTreeEpoch(textPtr->sharedTextPtr->tree);
	Tcl_DString buf;
	int code;

	Tcl_DStringInit(&buf);
	Tcl_DStringAppend(&buf, Tcl_GetString(command), -1);
	Tcl_DStringAppend(&buf, " ", -1);
	Tcl_DStringAppend(&buf, Tcl_GetString(tuple), -1);
	code = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, 0);
	code = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, TCL_EVAL_GLOBAL);
	Tcl_DStringFree(&buf);
	if (code != TCL_OK) {
	    Tcl_AddErrorInfo(interp,
		    "\n    (segment dumping command executed by text)");
	    Tcl_BackgroundException(interp, code);
	}
	Tcl_DecrRefCount(tuple);
5070
5071
5072
5073
5074
5075
5076


5077
5078
5079
5080
5081
5082
5083
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129







+
+







 */

static int
TextEditUndo(
    TkText *textPtr)		/* Overall information about text widget. */
{
    int status;
    Tcl_Obj *cmdObj;
    int code;

    if (!textPtr->sharedTextPtr->undo) {
	return TCL_OK;
    }

    /*
     * Turn off the undo feature while we revert a compound action, setting
5093
5094
5095
5096
5097
5098
5099
















5100
5101
5102
5103
5104
5105
5106
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    status = TkUndoRevert(textPtr->sharedTextPtr->undoStack);

    if (textPtr->sharedTextPtr->dirtyMode != TK_TEXT_DIRTY_FIXED) {
	textPtr->sharedTextPtr->dirtyMode = TK_TEXT_DIRTY_NORMAL;
    }
    textPtr->sharedTextPtr->undo = 1;

    /*
     * Convert undo/redo temporary marks set by TkUndoRevert() into
     * indices left in the interp result.
     */

    cmdObj = Tcl_ObjPrintf("::tk::TextUndoRedoProcessMarks %s",
            Tk_PathName(textPtr->tkwin));
    Tcl_IncrRefCount(cmdObj);
    code = Tcl_EvalObjEx(textPtr->interp, cmdObj, TCL_EVAL_GLOBAL);
    if (code != TCL_OK) {
        Tcl_AddErrorInfo(textPtr->interp,
                "\n    (on undoing)");
        Tcl_BackgroundException(textPtr->interp, code);
    }
    Tcl_DecrRefCount(cmdObj);

    return status;
}

/*
 *----------------------------------------------------------------------
 *
 * TextEditRedo --
5118
5119
5120
5121
5122
5123
5124


5125
5126
5127
5128
5129
5130
5131
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195







+
+







 */

static int
TextEditRedo(
    TkText *textPtr)		/* Overall information about text widget. */
{
    int status;
    Tcl_Obj *cmdObj;
    int code;

    if (!textPtr->sharedTextPtr->undo) {
	return TCL_OK;
    }

    /*
     * Turn off the undo feature temporarily while we revert a previously
5140
5141
5142
5143
5144
5145
5146

















5147
5148
5149
5150
5151
5152
5153
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








    status = TkUndoApply(textPtr->sharedTextPtr->undoStack);

    if (textPtr->sharedTextPtr->dirtyMode != TK_TEXT_DIRTY_FIXED) {
	textPtr->sharedTextPtr->dirtyMode = TK_TEXT_DIRTY_NORMAL;
    }
    textPtr->sharedTextPtr->undo = 1;

    /*
     * Convert undo/redo temporary marks set by TkUndoApply() into
     * indices left in the interp result.
     */

    cmdObj = Tcl_ObjPrintf("::tk::TextUndoRedoProcessMarks %s",
            Tk_PathName(textPtr->tkwin));
    Tcl_IncrRefCount(cmdObj);
    code = Tcl_EvalObjEx(textPtr->interp, cmdObj, TCL_EVAL_GLOBAL);
    if (code != TCL_OK) {
        Tcl_AddErrorInfo(textPtr->interp,
                "\n    (on undoing)");
        Tcl_BackgroundException(textPtr->interp, code);
    }
    Tcl_DecrRefCount(cmdObj);

    return status;
}

/*
 *----------------------------------------------------------------------
 *
 * TextEditCmd --
5349
5350
5351
5352
5353
5354
5355
5356

5357
5358
5359
5360
5361
5362
5363
5430
5431
5432
5433
5434
5435
5436

5437
5438
5439
5440
5441
5442
5443
5444







-
+








    TkTextMakeByteIndex(indexPtr1->tree, textPtr,
	    TkBTreeLinesTo(textPtr, indexPtr1->linePtr),
	    indexPtr1->byteIndex, &tmpIndex);

    if (TkTextIndexCmp(indexPtr1, indexPtr2) < 0) {
	while (1) {
	    int offset;
	    TkSizeT offset;
	    TkTextSegment *segPtr = TkTextIndexToSeg(&tmpIndex, &offset);
	    int last = segPtr->size, last2;

	    if (tmpIndex.linePtr == indexPtr2->linePtr) {
		/*
		 * The last line that was requested must be handled carefully,
		 * because we may need to break out of this loop in the middle
5404
5405
5406
5407
5408
5409
5410
5411

5412
5413
5414
5415
5416
5417
5418
5485
5486
5487
5488
5489
5490
5491

5492
5493
5494
5495
5496
5497
5498
5499







-
+







static void
GenerateModifiedEvent(
    TkText *textPtr)	/* Information about text widget. */
{
    for (textPtr = textPtr->sharedTextPtr->peers; textPtr != NULL;
	    textPtr = textPtr->next) {
	Tk_MakeWindowExist(textPtr->tkwin);
	TkSendVirtualEvent(textPtr->tkwin, "Modified", NULL);
	Tk_SendVirtualEvent(textPtr->tkwin, "Modified", NULL);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * GenerateUndoStackEvent --
5434
5435
5436
5437
5438
5439
5440
5441

5442
5443
5444
5445
5446
5447
5448
5515
5516
5517
5518
5519
5520
5521

5522
5523
5524
5525
5526
5527
5528
5529







-
+







static void
GenerateUndoStackEvent(
    TkText *textPtr)	/* Information about text widget. */
{
    for (textPtr = textPtr->sharedTextPtr->peers; textPtr != NULL;
	    textPtr = textPtr->next) {
	Tk_MakeWindowExist(textPtr->tkwin);
	TkSendVirtualEvent(textPtr->tkwin, "UndoStack", NULL);
	Tk_SendVirtualEvent(textPtr->tkwin, "UndoStack", NULL);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * UpdateDirtyFlag --
5514
5515
5516
5517
5518
5519
5520
5521

5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539

5540
5541
5542
5543
5544
5545
5546
5595
5596
5597
5598
5599
5600
5601

5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619

5620
5621
5622
5623
5624
5625
5626
5627







-
+

















-
+







 *----------------------------------------------------------------------
 */

void
TkTextRunAfterSyncCmd(
    ClientData clientData)		/* Information about text widget. */
{
    register TkText *textPtr = (TkText *) clientData;
    TkText *textPtr = (TkText *)clientData;
    int code;

    if ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)) {
	/*
	* The widget has been deleted. Don't do anything.
	*/

	if (textPtr->refCount-- <= 1) {
	    ckfree((char *) textPtr);
	}
	return;
    }

    Tcl_Preserve((ClientData) textPtr->interp);
    code = Tcl_EvalObjEx(textPtr->interp, textPtr->afterSyncCmd, TCL_EVAL_GLOBAL);
    if (code == TCL_ERROR) {
	Tcl_AddErrorInfo(textPtr->interp, "\n    (text sync)");
	Tcl_BackgroundError(textPtr->interp);
	Tcl_BackgroundException(textPtr->interp, TCL_ERROR);
    }
    Tcl_Release((ClientData) textPtr->interp);
    Tcl_DecrRefCount(textPtr->afterSyncCmd);
    textPtr->afterSyncCmd = NULL;
}

/*
5588
5589
5590
5591
5592
5593
5594
5595

5596
5597
5598
5599
5600
5601
5602
5669
5670
5671
5672
5673
5674
5675

5676
5677
5678
5679
5680
5681
5682
5683







-
+








    /*
     * Find the optional end location, similarly.
     */

    if (toPtr != NULL) {
	const TkTextIndex *indexToPtr, *indexFromPtr;
	TkText *textPtr = searchSpecPtr->clientData;
	TkText *textPtr = (TkText *)searchSpecPtr->clientData;

	indexToPtr = TkTextGetIndexFromObj(interp, textPtr, toPtr);
	if (indexToPtr == NULL) {
	    return TCL_ERROR;
	}
	indexFromPtr = TkTextGetIndexFromObj(interp, textPtr, fromPtr);

5669
5670
5671
5672
5673
5674
5675
5676


5677
5678
5679
5680
5681
5682
5683
5684
5685
5686
5687
5688
5689
5690
5691
5692
5693
5694
5695
5696
5697
5698
5699



5700
5701
5702
5703
5704
5705
5706
5750
5751
5752
5753
5754
5755
5756

5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777
5778



5779
5780
5781
5782
5783
5784
5785
5786
5787
5788







-
+
+




















-
-
-
+
+
+







				 * pattern. Must have a refCount > 0. */
{
    /*
     * For exact searches these are utf-8 char* offsets, for regexp searches
     * they are Unicode char offsets.
     */

    int firstOffset, lastOffset, matchOffset, matchLength;
    int firstOffset, lastOffset;
    TkSizeT matchOffset,  matchLength;
    int passes;
    int lineNum = searchSpecPtr->startLine;
    int code = TCL_OK;
    Tcl_Obj *theLine;
    int alreadySearchOffset = -1;

    const char *pattern = NULL;	/* For exact searches only. */
    int firstNewLine = -1; 	/* For exact searches only. */
    Tcl_RegExp regexp = NULL;	/* For regexp searches only. */

    /*
     * These items are for backward regexp searches only. They are for two
     * purposes: to allow us to report backwards matches in the correct order,
     * even though the implementation uses repeated forward searches; and to
     * provide for overlap checking between backwards matches on different
     * text lines.
     */

#define LOTS_OF_MATCHES 20
    int matchNum = LOTS_OF_MATCHES;
    int smArray[2 * LOTS_OF_MATCHES];
    int *storeMatch = smArray;
    int *storeLength = smArray + LOTS_OF_MATCHES;
    TkSizeT smArray[2 * LOTS_OF_MATCHES];
    TkSizeT *storeMatch = smArray;
    TkSizeT *storeLength = smArray + LOTS_OF_MATCHES;
    int lastBackwardsLineMatch = -1;
    int lastBackwardsMatchOffset = -1;

    if (searchSpecPtr->exact) {
	/*
	 * Convert the pattern to lower-case if we're supposed to ignore case.
	 */
5742
5743
5744
5745
5746
5747
5748
5749
5750

5751
5752
5753
5754
5755
5756
5757
5824
5825
5826
5827
5828
5829
5830


5831
5832
5833
5834
5835
5836
5837
5838







-
-
+








	/*
	 * 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 = Tcl_GetString(patObj);
	matchLength = patObj->length;
	pattern = TkGetStringFromObj(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
	 * will work fine.
	 */
5842
5843
5844
5845
5846
5847
5848
5849

5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860
5861

5862
5863
5864
5865
5866
5867
5868
5869
5870
5871
5872
5873
5874
5875

5876
5877
5878
5879
5880
5881
5882
5883
5884
5885

5886
5887
5888
5889

5890
5891
5892
5893
5894
5895
5896
5923
5924
5925
5926
5927
5928
5929

5930
5931
5932
5933
5934
5935
5936
5937
5938
5939
5940
5941

5942
5943
5944
5945
5946
5947
5948
5949
5950
5951
5952
5953
5954
5955

5956
5957
5958
5959
5960
5961
5962
5963
5964
5965

5966
5967
5968
5969

5970
5971
5972
5973
5974
5975
5976
5977







-
+











-
+













-
+









-
+



-
+







		/*
		 * Forward search and first pass, or backward search and
		 * second pass.
		 *
		 * Only use the last part of the line.
		 */

		if (searchSpecPtr->startOffset > firstOffset) {
		if (searchSpecPtr->startOffset + 1 > (TkSizeT)firstOffset + 1) {
		    firstOffset = searchSpecPtr->startOffset;
		}
		if ((firstOffset >= lastOffset)
		    && ((lastOffset != 0) || searchSpecPtr->exact)) {
		    goto nextLine;
		}
	    } else {
		/*
		 * Use only the first part of the line.
		 */

		if (searchSpecPtr->startOffset < lastOffset) {
		if (searchSpecPtr->startOffset + 1 < (TkSizeT)lastOffset + 1) {
		    lastOffset = searchSpecPtr->startOffset;
		}
	    }
	}

	/*
	 * Check for matches within the current line 'lineNum'. If so, and if
	 * we're searching backwards or for all matches, repeat the search
	 * until we find the last match in the line. The 'lastOffset' is one
	 * beyond the last position in the line at which a match is allowed to
	 * begin.
	 */

	matchOffset = -1;
	matchOffset = TCL_INDEX_NONE;

	if (searchSpecPtr->exact) {
	    int maxExtraLines = 0;
	    const char *startOfLine = Tcl_GetString(theLine);

	    CLANG_ASSERT(pattern);
	    do {
		int ch;
		const char *p;
		int lastFullLine = lastOffset;
		TkSizeT lastFullLine = lastOffset;

		if (firstNewLine == -1) {
		    if (searchSpecPtr->strictLimits
			    && (firstOffset + matchLength > lastOffset)) {
			    && (firstOffset + matchLength + 1 > (TkSizeT)lastOffset + 1)) {
			/*
			 * Not enough characters to match.
			 */

			break;
		    }

5912
5913
5914
5915
5916
5917
5918
5919

5920
5921
5922
5923
5924
5925
5926
5993
5994
5995
5996
5997
5998
5999

6000
6001
6002
6003
6004
6005
6006
6007







-
+







			    p = startOfLine + alreadySearchOffset;
			    alreadySearchOffset = -1;
			} else {
			    p = startOfLine + lastOffset -1;
			}
			while (p >= startOfLine + firstOffset) {
			    if (matchLength == 0 || (p[0] == c && !strncmp(
				     p, pattern, (size_t) matchLength))) {
				     p, pattern, matchLength))) {
				goto backwardsMatch;
			    }
			    p--;
			}
			break;
		    } else {
			p = strstr(startOfLine + firstOffset, pattern);
5941
5942
5943
5944
5945
5946
5947
5948

5949
5950
5951
5952
5953
5954
5955
6022
6023
6024
6025
6026
6027
6028

6029
6030
6031
6032
6033
6034
6035
6036







-
+







		} else {
		    /*
		     * Multi-line match has only one possible match position,
		     * because we know where the '\n' is.
		     */

		    p = startOfLine + lastOffset - firstNewLine - 1;
		    if (strncmp(p, pattern, (unsigned) firstNewLine + 1)) {
		    if (strncmp(p, pattern, firstNewLine + 1)) {
			/*
			 * No match.
			 */

			break;
		    } else {
			int extraLines = 1;
6000
6001
6002
6003
6004
6005
6006
6007

6008
6009
6010
6011
6012
6013
6014

6015
6016
6017
6018
6019
6020
6021
6081
6082
6083
6084
6085
6086
6087

6088
6089
6090
6091
6092
6093
6094

6095
6096
6097
6098
6099
6100
6101
6102







-
+






-
+







			    p = startOfLine + skipFirst;

			    /*
			     * Use the fact that 'matchLength = patLength' for
			     * exact searches.
			     */

			    if ((lastTotal - skipFirst) >= matchLength) {
			    if ((TkSizeT)lastTotal - skipFirst + 1 >= matchLength + 1) {
				/*
				 * We now have enough text to match, so we
				 * make a final test and break whatever the
				 * result.
				 */

				if (strncmp(p,pattern,(size_t)matchLength)) {
				if (strncmp(p, pattern, matchLength)) {
				    p = NULL;
				}
				break;
			    } else {
				/*
				 * Not enough text yet, but check the prefix.
				 */
6082
6083
6084
6085
6086
6087
6088
6089

6090
6091
6092
6093
6094
6095
6096
6163
6164
6165
6166
6167
6168
6169

6170
6171
6172
6173
6174
6175
6176
6177







-
+







			    alreadySearchOffset -= (matchLength ? matchLength : 1);
                            if (alreadySearchOffset < 0) {
                                break;
                            }
			}
		    } else {
                        firstOffset = matchLength ? p - startOfLine + matchLength
                                                  : p - startOfLine + 1;
                                                  : p - startOfLine + (TkSizeT)1;
			if (firstOffset >= lastOffset) {
			    /*
			     * Now, we have to be careful not to find
			     * overlapping matches either on the same or
			     * following lines. Assume that if we did find
			     * something, it goes until the last extra line we
			     * added.
6122
6123
6124
6125
6126
6127
6128
6129

6130
6131
6132
6133
6134
6135
6136
6137
6138
6139
6140
6141
6142
6143
6144
6145
6146
6147

6148
6149

6150
6151
6152
6153
6154
6155
6156
6157
6158
6159
6160
6161
6162
6163
6164
6165

6166
6167
6168
6169
6170
6171
6172
6203
6204
6205
6206
6207
6208
6209

6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225
6226
6227

6228
6229

6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245

6246
6247
6248
6249
6250
6251
6252
6253







-
+

















-
+

-
+















-
+







	    int maxExtraLines = 0;
	    int matches = 0;
	    int lastNonOverlap = -1;

	    do {
		Tcl_RegExpInfo info;
		int match;
		int lastFullLine = lastOffset;
		TkSizeT lastFullLine = lastOffset;

		match = Tcl_RegExpExecObj(interp, regexp, theLine,
			firstOffset, 1, (firstOffset>0 ? TCL_REG_NOTBOL : 0));
		if (match < 0) {
		    code = TCL_ERROR;
		    goto searchDone;
		}
		Tcl_RegExpGetInfo(regexp, &info);

		/*
		 * If we don't have a match, or if we do, but it extends to
		 * the end of the line, we must try to add more lines to get a
		 * full greedy match.
		 */

		if (!match ||
			((info.extendStart == info.matches[0].start)
			&& (info.matches[0].end == lastOffset-firstOffset))) {
			&& (info.matches[0].end == (TkSizeT) (lastOffset - firstOffset)))) {
		    int extraLines = 0;
		    int prevFullLine;
		    TkSizeT prevFullLine;

		    /*
		     * If we find a match that overlaps more than one line, we
		     * will use this value to determine the first allowed
		     * starting offset for the following search (to avoid
		     * overlapping results).
		     */

		    int lastTotal = lastOffset;

		    if ((lastBackwardsLineMatch != -1)
			    && (lastBackwardsLineMatch == (lineNum + 1))) {
			lastNonOverlap = lastTotal;
		    }

		    if (info.extendStart < 0) {
		    if (info.extendStart == TCL_INDEX_NONE) {
			/*
			 * No multi-line match is possible.
			 */

			break;
		    }

6255
6256
6257
6258
6259
6260
6261
6262
6263
6264



6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275

6276
6277
6278
6279
6280
6281
6282
6336
6337
6338
6339
6340
6341
6342



6343
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355

6356
6357
6358
6359
6360
6361
6362
6363







-
-
-
+
+
+










-
+







			 * This means we often add and search one more line
			 * than might be necessary if Tcl were able to give us
			 * a correct value of info.extendStart under all
			 * circumstances.
			 */

			if ((match &&
				firstOffset+info.matches[0].end != lastTotal &&
				firstOffset+info.matches[0].end < prevFullLine)
				|| info.extendStart < 0) {
				firstOffset + info.matches[0].end != (TkSizeT) lastTotal &&
				firstOffset + info.matches[0].end + 1 < prevFullLine + 1)
				|| info.extendStart == TCL_INDEX_NONE) {
			    break;
			}

			/*
			 * If there is a match, but that match starts after
			 * the end of the first line, then we'll handle that
			 * next time around, when we're actually looking at
			 * that line.
			 */

			if (match && (info.matches[0].start >= lastOffset)) {
			if (match && (info.matches[0].start + 1 >= (TkSizeT) lastOffset + 1)) {
			    break;
			}
			if (match && ((firstOffset + info.matches[0].end)
				>= prevFullLine)) {
			    if (extraLines > 0) {
				extraLinesSearched = extraLines - 1;
			    }
6325
6326
6327
6328
6329
6330
6331
6332
6333


6334
6335
6336
6337
6338
6339
6340
6406
6407
6408
6409
6410
6411
6412


6413
6414
6415
6416
6417
6418
6419
6420
6421







-
-
+
+







				    - info.matches[0].start;

			    if (lastNonOverlap != -1) {
				/*
				 * Possible overlap or enclosure.
				 */

				if (thisOffset-lastNonOverlap >=
					lastBackwardsMatchOffset+matchLength){
				if ((TkSizeT)thisOffset - lastNonOverlap >=
					lastBackwardsMatchOffset + matchLength + 1){
				    /*
				     * Totally encloses previous match, so
				     * forget the previous match.
				     */

				    lastBackwardsLineMatch = -1;
				} else if ((thisOffset - lastNonOverlap)
6407
6408
6409
6410
6411
6412
6413
6414

6415
6416

6417
6418
6419

6420
6421
6422
6423
6424
6425
6426
6427
6428
6429
6430
6431
6432
6433
6434
6435
6436
6437
6438
6439



6440
6441

6442
6443
6444
6445
6446
6447
6448
6488
6489
6490
6491
6492
6493
6494

6495
6496

6497
6498
6499

6500
6501
6502
6503
6504
6505
6506
6507
6508
6509
6510
6511
6512
6513
6514
6515
6516
6517



6518
6519
6520
6521

6522
6523
6524
6525
6526
6527
6528
6529







-
+

-
+


-
+

















-
-
-
+
+
+

-
+







		/*
		 * Update our local variables with the match, if we haven't
		 * yet found anything, or if we're doing '-all' or
		 * '-backwards' _and_ this match isn't fully enclosed in the
		 * previous match.
		 */

		if (matchOffset == -1 ||
		if (matchOffset == TCL_INDEX_NONE ||
			((searchSpecPtr->all || searchSpecPtr->backwards)
			&& ((firstOffset < matchOffset)
			&& (((TkSizeT)firstOffset + 1 < matchOffset + 1)
			|| ((firstOffset + info.matches[0].end
				- info.matches[0].start)
				> (matchOffset + matchLength))))) {
				> matchOffset + matchLength)))) {

		    matchOffset = firstOffset;
		    matchLength = info.matches[0].end - info.matches[0].start;

		    if (searchSpecPtr->backwards) {
			/*
			 * To get backwards searches in the correct order, we
			 * must store them away here.
			 */

			if (matches == matchNum) {
			    /*
			     * We've run out of space in our normal store, so
			     * we must allocate space for these backwards
			     * matches on the heap.
			     */

			    int *newArray =
				    ckalloc(4 * matchNum * sizeof(int));
			    memcpy(newArray, storeMatch, matchNum*sizeof(int));
			    TkSizeT *newArray = (TkSizeT *)
				    ckalloc(4 * matchNum * sizeof(TkSizeT));
			    memcpy(newArray, storeMatch, matchNum*sizeof(TkSizeT));
			    memcpy(newArray + 2*matchNum, storeLength,
				    matchNum * sizeof(int));
				    matchNum * sizeof(TkSizeT));
			    if (storeMatch != smArray) {
				ckfree(storeMatch);
			    }
			    matchNum *= 2;
			    storeMatch = newArray;
			    storeLength = newArray + matchNum;
			}
6469
6470
6471
6472
6473
6474
6475
6476

6477
6478
6479
6480
6481
6482
6483
6550
6551
6552
6553
6554
6555
6556

6557
6558
6559
6560
6561
6562
6563
6564







-
+








		    /*
		     * For forward matches, unless we allow overlaps, we move
		     * this on by the length of the current match so that we
		     * explicitly disallow overlapping matches.
		     */

		    if (matchLength > 0 && !searchSpecPtr->overlap
		    if (matchLength + 1 > 1 && !searchSpecPtr->overlap
			    && !searchSpecPtr->backwards) {
			firstOffset += matchLength;
			if (firstOffset >= lastOffset) {
			    /*
			     * Now, we have to be careful not to find
			     * overlapping matches either on the same or
			     * following lines. Assume that if we did find
6526
6527
6528
6529
6530
6531
6532
6533
6534


6535
6536
6537
6538
6539
6540
6541
6607
6608
6609
6610
6611
6612
6613


6614
6615
6616
6617
6618
6619
6620
6621
6622







-
-
+
+







			 * if (storeMatch[matches]<searchSpecPtr->stopOffset)
			 *	break;
			 *
			 * might be needed here, but no test case has been
			 * found which would exercise such a problem.
			 */
		    }
		    if (storeMatch[matches] + storeLength[matches]
			    >= matchOffset + matchLength) {
		    if (storeMatch[matches] + storeLength[matches] + 1
			    >= matchOffset + matchLength + 1) {
			/*
			 * The new match totally encloses the previous one, so
			 * we overwrite the previous one.
			 */

			matchOffset = storeMatch[matches];
			matchLength = storeLength[matches];
6575
6576
6577
6578
6579
6580
6581
6582

6583
6584
6585
6586
6587
6588
6589
6656
6657
6658
6659
6660
6661
6662

6663
6664
6665
6666
6667
6668
6669
6670







-
+







	 * If the 'all' flag is set, we will already have stored all matches,
	 * so we just proceed to the next line.
	 *
	 * If not, and there is a match we need to store that information and
	 * we are done.
	 */

	if ((lastBackwardsLineMatch == -1) && (matchOffset >= 0)
	if ((lastBackwardsLineMatch == -1) && (matchOffset != TCL_INDEX_NONE)
		&& !searchSpecPtr->all) {
	    searchSpecPtr->foundMatchProc(lineNum, searchSpecPtr, lineInfo,
		    theLine, matchOffset, matchLength);
	    goto searchDone;
	}

	/*
6691
6692
6693
6694
6695
6696
6697
6698
6699


6700
6701

6702
6703
6704
6705
6706
6707
6708
6709

6710
6711
6712
6713
6714
6715
6716
6772
6773
6774
6775
6776
6777
6778


6779
6780
6781

6782
6783
6784
6785
6786
6787
6788
6789

6790
6791
6792
6793
6794
6795
6796
6797







-
-
+
+

-
+







-
+







 *	Creates a new Tcl_Obj.
 *
 *----------------------------------------------------------------------
 */

static Tcl_Obj *
GetLineStartEnd(
    ClientData clientData,
    Tk_Window tkwin,
    TCL_UNUSED(void *),
    TCL_UNUSED(Tk_Window),
    char *recordPtr,		/* Pointer to widget record. */
    int internalOffset)		/* Offset within *recordPtr containing the
    TkSizeT internalOffset)		/* Offset within *recordPtr containing the
				 * line value. */
{
    TkTextLine *linePtr = *(TkTextLine **)(recordPtr + internalOffset);

    if (linePtr == NULL) {
	return Tcl_NewObj();
    }
    return Tcl_NewIntObj(1 + TkBTreeLinesTo(NULL, linePtr));
    return Tcl_NewWideIntObj(1 + TkBTreeLinesTo(NULL, linePtr));
}

/*
 *----------------------------------------------------------------------
 *
 * SetLineStartEnd --
 *
6726
6727
6728
6729
6730
6731
6732
6733

6734
6735

6736
6737
6738
6739
6740

6741
6742
6743
6744
6745
6746
6747
6748
6749
6750


6751
6752
6753
6754
6755
6756
6757
6807
6808
6809
6810
6811
6812
6813

6814
6815

6816
6817
6818
6819
6820

6821
6822
6823
6824
6825
6826
6827
6828
6829


6830
6831
6832
6833
6834
6835
6836
6837
6838







-
+

-
+




-
+








-
-
+
+







 *	that the specified string was empty and that is acceptable.
 *
 *----------------------------------------------------------------------
 */

static int
SetLineStartEnd(
    ClientData clientData,
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interp; may be used for errors. */
    Tk_Window tkwin,		/* Window for which option is being set. */
    TCL_UNUSED(Tk_Window),	/* Window for which option is being set. */
    Tcl_Obj **value,		/* Pointer to the pointer to the value object.
				 * We use a pointer to the pointer because we
				 * may need to return a value (NULL). */
    char *recordPtr,		/* Pointer to storage for the widget record. */
    int internalOffset,		/* Offset within *recordPtr at which the
    TkSizeT internalOffset,		/* Offset within *recordPtr at which the
				 * internal value is to be stored. */
    char *oldInternalPtr,	/* Pointer to storage for the old value. */
    int flags)			/* Flags for the option, set Tk_SetOptions. */
{
    TkTextLine *linePtr = NULL;
    char *internalPtr;
    TkText *textPtr = (TkText *) recordPtr;

    if (internalOffset >= 0) {
	internalPtr = recordPtr + internalOffset;
    if (internalOffset != TCL_INDEX_NONE) {
	internalPtr = (char *)recordPtr + internalOffset;
    } else {
	internalPtr = NULL;
    }

    if (flags & TK_OPTION_NULL_OK && ObjectIsEmpty(*value)) {
	*value = NULL;
    } else {
6785
6786
6787
6788
6789
6790
6791
6792
6793


6794
6795
6796
6797
6798
6799
6800
6866
6867
6868
6869
6870
6871
6872


6873
6874
6875
6876
6877
6878
6879
6880
6881







-
-
+
+







 *	Restores the old value.
 *
 *----------------------------------------------------------------------
 */

static void
RestoreLineStartEnd(
    ClientData clientData,
    Tk_Window tkwin,
    TCL_UNUSED(void *),
    TCL_UNUSED(Tk_Window),
    char *internalPtr,		/* Pointer to storage for value. */
    char *oldInternalPtr)	/* Pointer to old value. */
{
    *(TkTextLine **)internalPtr = *(TkTextLine **)oldInternalPtr;
}

/*
6844
6845
6846
6847
6848
6849
6850
6851

6852
6853
6854
6855
6856
6857
6858
6859
6860
6861
6862
6863
6864
6865
6866
6867
6868
6869
6870

6871
6872
6873
6874
6875
6876
6877
6925
6926
6927
6928
6929
6930
6931

6932
6933
6934
6935
6936
6937
6938
6939
6940
6941
6942
6943
6944
6945
6946
6947
6948
6949
6950

6951
6952
6953
6954
6955
6956
6957
6958







-
+


















-
+







 *	Depends on option; see below.
 *
 *----------------------------------------------------------------------
 */

int
TkpTesttextCmd(
    ClientData clientData,	/* Main window for application. */
    TCL_UNUSED(void *),	/* Main window for application. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])		/* Argument strings. */
{
    TkText *textPtr;
    size_t len;
    int lineIndex, byteIndex, byteOffset;
    TkTextIndex index;
    char buf[64];
    Tcl_CmdInfo info;

    if (objc < 3) {
	return TCL_ERROR;
    }

    if (Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &info) == 0) {
	return TCL_ERROR;
    }
    textPtr = info.objClientData;
    textPtr = (TkText *)info.objClientData;
    len = strlen(Tcl_GetString(objv[2]));
    if (strncmp(Tcl_GetString(objv[2]), "byteindex", len) == 0) {
	if (objc != 5) {
	    return TCL_ERROR;
	}
	lineIndex = atoi(Tcl_GetString(objv[3])) - 1;
	byteIndex = atoi(Tcl_GetString(objv[4]));
Changes to generic/tkText.h.
161
162
163
164
165
166
167
168

169
170
171

172
173
174
175
176
177
178
161
162
163
164
165
166
167

168
169
170

171
172
173
174
175
176
177
178







-
+


-
+







typedef struct TkTextSegment {
    const struct Tk_SegType *typePtr;
				/* Pointer to record describing segment's
				 * type. */
    struct TkTextSegment *nextPtr;
				/* Next in list of segments for this line, or
				 * NULL for end of list. */
    int size;			/* Size of this segment (# of bytes of index
    TkSizeT size;			/* Size of this segment (# of bytes of index
				 * space it occupies). */
    union {
	char chars[2];		/* Characters that make up character info.
	char chars[TKFLEXARRAY];		/* Characters that make up character info.
				 * Actual length varies to hold as many
				 * characters as needed.*/
	TkTextToggle toggle;	/* Information about tag toggle. */
	TkTextMark mark;	/* Information about mark. */
	TkTextEmbWindow ew;	/* Information about embedded window. */
	TkTextEmbImage ei;	/* Information about embedded image. */
    } body;
485
486
487
488
489
490
491
492

493
494
495
496
497
498
499
485
486
487
488
489
490
491

492
493
494
495
496
497
498
499







-
+







typedef struct TkTextTabArray {
    int numTabs;		/* Number of tab stops. */
    double lastTab;		/* The accurate fractional pixel position of
				 * the last tab. */
    double tabIncrement;	/* The accurate fractional pixel increment
				 * between interpolated tabs we have to create
				 * when we exceed numTabs. */
    TkTextTab tabs[1];		/* Array of tabs. The actual size will be
    TkTextTab tabs[TKFLEXARRAY];/* Array of tabs. The actual size will be
				 * numTabs. THIS FIELD MUST BE THE LAST IN THE
				 * STRUCTURE. */
} TkTextTabArray;

/*
 * Enumeration defining the edit modes of the widget.
 */
527
528
529
530
531
532
533
534








535
536

537
538
539
540
541
542
543
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543

544
545
546
547
548
549
550
551








+
+
+
+
+
+
+
+

-
+







    TK_TEXT_STATE_DISABLED, TK_TEXT_STATE_NORMAL
} TkTextState;

/*
 * A data structure of the following type is shared between each text widget
 * that are peers.
 */

#ifndef TkSizeT
#   if TCL_MAJOR_VERSION > 8
#	define TkSizeT size_t
#   else
#	define TkSizeT int
#   endif
#endif

typedef struct TkSharedText {
    int refCount;		/* Reference count this shared object. */
    TkSizeT refCount;		/* Reference count this shared object. */
    TkTextBTree tree;		/* B-tree representation of text and tags for
				 * widget. */
    Tcl_HashTable tagTable;	/* Hash table that maps from tag names to
				 * pointers to TkTextTag structures. The "sel"
				 * tag does not feature in this table, since
				 * there's one of those for each text peer. */
    int numTags;		/* Number of tags currently defined for
558
559
560
561
562
563
564
565

566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582


583
584
585
586
587
588
589
566
567
568
569
570
571
572

573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599







-
+

















+
+







				 * image, there is no entry for it here. */
    Tk_BindingTable bindingTable;
				/* Table of all bindings currently defined for
				 * this widget. NULL means that no bindings
				 * exist, so the table hasn't been created.
				 * Each "object" used for this table is the
				 * name of a tag. */
    int stateEpoch;		/* This is incremented each time the B-tree's
    TkSizeT stateEpoch;	/* This is incremented each time the B-tree's
				 * contents change structurally, or when the
				 * start/end limits change, and means that any
				 * cached TkTextIndex objects are no longer
				 * valid. */

    /*
     * Information related to the undo/redo functionality.
     */

    TkUndoRedoStack *undoStack;	/* The undo/redo stack. */
    int undo;			/* Non-zero means the undo/redo behaviour is
				 * enabled. */
    int maxUndo;		/* The maximum depth of the undo stack
				 * expressed as the maximum number of compound
				 * statements. */
    int autoSeparators;		/* Non-zero means the separators will be
				 * inserted automatically. */
    int undoMarkId;             /* Counts undo marks temporarily used during
                                   undo and redo operations. */
    int isDirty;		/* Flag indicating the 'dirtyness' of the
				 * text widget. If the flag is not zero,
				 * unsaved modifications have been applied to
				 * the text widget. */
    TkTextDirtyMode dirtyMode;	/* The nature of the dirtyness characterized
				 * by the isDirty flag. */
    TkTextEditMode lastEditMode;/* Keeps track of what the last edit mode
777
778
779
780
781
782
783
784

785
786
787
788
789
790
791
787
788
789
790
791
792
793

794
795
796
797
798
799
800
801







-
+







				 * horizontal scrollbar when view changes. */
    char *yScrollCmd;		/* Prefix of command to issue to update
				 * vertical scrollbar when view changes. */
    int flags;			/* Miscellaneous flags; see below for
				 * definitions. */
    Tk_OptionTable optionTable;	/* Token representing the configuration
				 * specifications. */
    int refCount;		/* Number of cached TkTextIndex objects
    TkSizeT refCount;		/* Number of cached TkTextIndex objects
				 * refering to us. */
    int insertCursorType;	/* 0 = standard insertion cursor, 1 = block
				 * cursor. */

    /*
     * Copies of information from the shared section relating to the undo/redo
     * functonality
833
834
835
836
837
838
839
840

841
842
843
844
845
846
847
848
849
850


851
852
853
854
855
856
857
843
844
845
846
847
848
849

850
851
852
853
854
855
856
857
858


859
860
861
862
863
864
865
866
867







-
+








-
-
+
+








/*
 * Records of the following type define segment types in terms of a collection
 * of procedures that may be called to manipulate segments of that type.
 */

typedef TkTextSegment *	Tk_SegSplitProc(struct TkTextSegment *segPtr,
			    int index);
			    TkSizeT index);
typedef int		Tk_SegDeleteProc(struct TkTextSegment *segPtr,
			    TkTextLine *linePtr, int treeGone);
typedef TkTextSegment *	Tk_SegCleanupProc(struct TkTextSegment *segPtr,
			    TkTextLine *linePtr);
typedef void		Tk_SegLineChangeProc(struct TkTextSegment *segPtr,
			    TkTextLine *linePtr);
typedef int		Tk_SegLayoutProc(struct TkText *textPtr,
			    struct TkTextIndex *indexPtr,
			    TkTextSegment *segPtr, int offset, int maxX,
			    int maxChars, int noCharsYet, TkWrapMode wrapMode,
			    TkTextSegment *segPtr, TkSizeT offset, int maxX,
			    TkSizeT maxChars, int noCharsYet, TkWrapMode wrapMode,
			    struct TkTextDispChunk *chunkPtr);
typedef void		Tk_SegCheckProc(TkTextSegment *segPtr,
			    TkTextLine *linePtr);

typedef struct Tk_SegType {
    const char *name;		/* Name of this kind of segment. */
    int leftGravity;		/* If a segment has zero size (e.g. a mark or
1003
1004
1005
1006
1007
1008
1009
1010

1011
1012
1013
1014
1015
1016
1017
1013
1014
1015
1016
1017
1018
1019

1020
1021
1022
1023
1024
1025
1026
1027







-
+







MODULE_SCOPE void	TkBTreeClientRangeChanged(TkText *textPtr,
			    int defaultHeight);
MODULE_SCOPE void	TkBTreeRemoveClient(TkTextBTree tree,
			    TkText *textPtr);
MODULE_SCOPE void	TkBTreeDestroy(TkTextBTree tree);
MODULE_SCOPE void	TkBTreeDeleteIndexRange(TkTextBTree tree,
			    TkTextIndex *index1Ptr, TkTextIndex *index2Ptr);
MODULE_SCOPE int	TkBTreeEpoch(TkTextBTree tree);
MODULE_SCOPE TkSizeT	TkBTreeEpoch(TkTextBTree tree);
MODULE_SCOPE TkTextLine *TkBTreeFindLine(TkTextBTree tree,
			    const TkText *textPtr, int line);
MODULE_SCOPE TkTextLine *TkBTreeFindPixelLine(TkTextBTree tree,
			    const TkText *textPtr, int pixels,
			    int *pixelOffset);
MODULE_SCOPE TkTextTag **TkBTreeGetTags(const TkTextIndex *indexPtr,
			    const TkText *textPtr, int *numTagsPtr);
1046
1047
1048
1049
1050
1051
1052
1053

1054
1055
1056
1057
1058
1059
1060
1056
1057
1058
1059
1060
1061
1062

1063
1064
1065
1066
1067
1068
1069
1070







-
+







			    XEvent *eventPtr);
MODULE_SCOPE void	TkTextSelectionEvent(TkText *textPtr);
MODULE_SCOPE int	TkTextIndexBbox(TkText *textPtr,
			    const TkTextIndex *indexPtr, int *xPtr, int *yPtr,
			    int *widthPtr, int *heightPtr, int *charWidthPtr);
MODULE_SCOPE int	TkTextCharLayoutProc(TkText *textPtr,
			    TkTextIndex *indexPtr, TkTextSegment *segPtr,
			    int offset, int maxX, int maxChars, int noBreakYet,
			    TkSizeT offset, int maxX, TkSizeT maxChars, int noBreakYet,
			    TkWrapMode wrapMode, TkTextDispChunk *chunkPtr);
MODULE_SCOPE void	TkTextCreateDInfo(TkText *textPtr);
MODULE_SCOPE int	TkTextDLineInfo(TkText *textPtr,
			    const TkTextIndex *indexPtr, int *xPtr, int *yPtr,
			    int *widthPtr, int *heightPtr, int *basePtr);
MODULE_SCOPE void	TkTextEmbWinDisplayProc(TkText *textPtr,
			    TkTextDispChunk *chunkPtr, int x, int y,
1092
1093
1094
1095
1096
1097
1098
1099

1100
1101
1102
1103
1104
1105
1106
1102
1103
1104
1105
1106
1107
1108

1109
1110
1111
1112
1113
1114
1115
1116







-
+







			    const TkTextIndex *srcPtr, int count,
			    TkTextIndex *dstPtr, TkTextCountType type);
MODULE_SCOPE void	TkTextIndexOfX(TkText *textPtr, int x,
			    TkTextIndex *indexPtr);
MODULE_SCOPE int	TkTextIndexYPixels(TkText *textPtr,
			    const TkTextIndex *indexPtr);
MODULE_SCOPE TkTextSegment *TkTextIndexToSeg(const TkTextIndex *indexPtr,
			    int *offsetPtr);
			    TkSizeT *offsetPtr);
MODULE_SCOPE void	TkTextLostSelection(ClientData clientData);
MODULE_SCOPE TkTextIndex *TkTextMakeCharIndex(TkTextBTree tree, TkText *textPtr,
			    int lineIndex, int charIndex,
			    TkTextIndex *indexPtr);
MODULE_SCOPE int	TkTextMeasureDown(TkText *textPtr,
			    TkTextIndex *srcPtr, int distance);
MODULE_SCOPE void	TkTextFreeElideInfo(TkTextElideInfo *infoPtr);
Changes to generic/tkTextBTree.c.
1
2
3
4
5
6
7
8
9


10
11
12
13
14
15
16
1
2
3
4
5
6
7


8
9
10
11
12
13
14
15
16







-
-
+
+







/*
 * tkTextBTree.c --
 *
 *	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.
 */

#include "tkInt.h"
#include "tkText.h"
101
102
103
104
105
106
107
108

109
110
111
112
113
114
115
101
102
103
104
105
106
107

108
109
110
111
112
113
114
115







-
+







 */

typedef struct BTree {
    Node *rootPtr;		/* Pointer to root of B-tree. */
    int clients;		/* Number of clients of this B-tree. */
    int pixelReferences;	/* Number of clients of this B-tree which care
				 * about pixel heights. */
    int stateEpoch;		/* Updated each time any aspect of the B-tree
    TkSizeT stateEpoch;	 /* Updated each time any aspect of the B-tree
				 * changes. */
    TkSharedText *sharedTextPtr;/* Used to find tagTable in consistency
				 * checking code, and to access list of all
				 * B-tree clients. */
    int startEndCount;
    TkTextLine **startEnd;
    TkText **startEndRef;
136
137
138
139
140
141
142
143
144
145
146




147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164

165
166
167
168
169
170
171
136
137
138
139
140
141
142




143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163

164
165
166
167
168
169
170
171







-
-
-
-
+
+
+
+

















-
+








int tkBTreeDebug = 0;

/*
 * Macros that determine how much space to allocate for new segments:
 */

#define CSEG_SIZE(chars) ((unsigned) (Tk_Offset(TkTextSegment, body) \
	+ 1 + (chars)))
#define TSEG_SIZE ((unsigned) (Tk_Offset(TkTextSegment, body) \
	+ sizeof(TkTextToggle)))
#define CSEG_SIZE(chars) (offsetof(TkTextSegment, body) \
	+ 1 + (chars))
#define TSEG_SIZE (offsetof(TkTextSegment, body) \
	+ sizeof(TkTextToggle))

/*
 * Forward declarations for functions defined in this file:
 */

static int		AdjustPixelClient(BTree *treePtr, int defaultHeight,
			    Node *nodePtr, TkTextLine *start, TkTextLine *end,
			    int useReference, int newPixelReferences,
			    int *counting);
static void		ChangeNodeToggleCount(Node *nodePtr,
			    TkTextTag *tagPtr, int delta);
static void		CharCheckProc(TkTextSegment *segPtr,
			    TkTextLine *linePtr);
static int		CharDeleteProc(TkTextSegment *segPtr,
			    TkTextLine *linePtr, int treeGone);
static TkTextSegment *	CharCleanupProc(TkTextSegment *segPtr,
			    TkTextLine *linePtr);
static TkTextSegment *	CharSplitProc(TkTextSegment *segPtr, int index);
static TkTextSegment *	CharSplitProc(TkTextSegment *segPtr, TkSizeT index);
static void		CheckNodeConsistency(Node *nodePtr, int references);
static void		CleanupLine(TkTextLine *linePtr);
static void		DeleteSummaries(Summary *tagPtr);
static void		DestroyNode(Node *nodePtr);
static TkTextSegment *	FindTagEnd(TkTextBTree tree, TkTextTag *tagPtr,
			    TkTextIndex *indexPtr);
static void		IncCount(TkTextTag *tagPtr, int inc,
257
258
259
260
261
262
263
264
265
266
267




268
269
270
271
272
273
274
275
276
277
278



279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299

300
301
302
303
304
305
306
307
308
309

310
311
312
313
314
315
316
317

318
319
320
321
322
323
324
257
258
259
260
261
262
263




264
265
266
267
268
269
270
271
272
273
274
275



276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298

299
300
301
302
303
304
305
306
307
308

309
310
311
312
313
314
315
316

317
318
319
320
321
322
323
324







-
-
-
-
+
+
+
+








-
-
-
+
+
+




















-
+









-
+







-
+







 *----------------------------------------------------------------------
 */

TkTextBTree
TkBTreeCreate(
    TkSharedText *sharedTextPtr)
{
    register BTree *treePtr;
    register Node *rootPtr;
    register TkTextLine *linePtr, *linePtr2;
    register TkTextSegment *segPtr;
    BTree *treePtr;
    Node *rootPtr;
    TkTextLine *linePtr, *linePtr2;
    TkTextSegment *segPtr;

    /*
     * The tree will initially have two empty lines. The second line isn't
     * actually part of the tree's contents, but its presence makes several
     * operations easier. The tree will have one node, which is also the root
     * of the tree.
     */

    rootPtr = ckalloc(sizeof(Node));
    linePtr = ckalloc(sizeof(TkTextLine));
    linePtr2 = ckalloc(sizeof(TkTextLine));
    rootPtr = (Node *)ckalloc(sizeof(Node));
    linePtr = (TkTextLine *)ckalloc(sizeof(TkTextLine));
    linePtr2 = (TkTextLine *)ckalloc(sizeof(TkTextLine));

    rootPtr->parentPtr = NULL;
    rootPtr->nextPtr = NULL;
    rootPtr->summaryPtr = NULL;
    rootPtr->level = 0;
    rootPtr->children.linePtr = linePtr;
    rootPtr->numChildren = 2;
    rootPtr->numLines = 2;

    /*
     * The tree currently has no registered clients, so all pixel count
     * pointers are simply NULL.
     */

    rootPtr->numPixels = NULL;
    linePtr->pixels = NULL;
    linePtr2->pixels = NULL;

    linePtr->parentPtr = rootPtr;
    linePtr->nextPtr = linePtr2;
    segPtr = ckalloc(CSEG_SIZE(1));
    segPtr = (TkTextSegment *)ckalloc(CSEG_SIZE(1));
    linePtr->segPtr = segPtr;
    segPtr->typePtr = &tkTextCharType;
    segPtr->nextPtr = NULL;
    segPtr->size = 1;
    segPtr->body.chars[0] = '\n';
    segPtr->body.chars[1] = 0;

    linePtr2->parentPtr = rootPtr;
    linePtr2->nextPtr = NULL;
    segPtr = ckalloc(CSEG_SIZE(1));
    segPtr = (TkTextSegment *)ckalloc(CSEG_SIZE(1));
    linePtr2->segPtr = segPtr;
    segPtr->typePtr = &tkTextCharType;
    segPtr->nextPtr = NULL;
    segPtr->size = 1;
    segPtr->body.chars[0] = '\n';
    segPtr->body.chars[1] = 0;

    treePtr = ckalloc(sizeof(BTree));
    treePtr = (BTree *)ckalloc(sizeof(BTree));
    treePtr->sharedTextPtr = sharedTextPtr;
    treePtr->rootPtr = rootPtr;
    treePtr->clients = 0;
    treePtr->stateEpoch = 0;
    treePtr->pixelReferences = 0;
    treePtr->startEndCount = 0;
    treePtr->startEnd = NULL;
362
363
364
365
366
367
368
369

370
371
372
373
374
375
376
362
363
364
365
366
367
368

369
370
371
372
373
374
375
376







-
+







void
TkBTreeAddClient(
    TkTextBTree tree,		/* B-tree to add a client to. */
    TkText *textPtr,		/* Client to add. */
    int defaultHeight)		/* Default line height for the new client, or
				 * -1 if no pixel heights are to be kept. */
{
    register BTree *treePtr = (BTree *) tree;
    BTree *treePtr = (BTree *) tree;

    if (treePtr == NULL) {
	Tcl_Panic("NULL treePtr in TkBTreeAddClient");
    }

    if (textPtr->start != NULL || textPtr->end != NULL) {
	AdjustStartEndRefs(treePtr, textPtr, TEXT_ADD_REFS);
497
498
499
500
501
502
503
504

505
506
507
508
509
510
511
497
498
499
500
501
502
503

504
505
506
507
508
509
510
511







-
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TkSizeT
TkBTreeEpoch(
    TkTextBTree tree)		/* Tree to get epoch for. */
{
    BTree *treePtr = (BTree *) tree;
    return treePtr->stateEpoch;
}

628
629
630
631
632
633
634
635

636
637

638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653

654
655

656
657
658
659
660
661
662
628
629
630
631
632
633
634

635
636

637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652

653
654

655
656
657
658
659
660
661
662







-
+

-
+















-
+

-
+







	    }
	    if (treePtr->startEndRef[i] != textPtr) {
		count++;
	    }
	    i++;
	}
	treePtr->startEndCount = count;
	treePtr->startEnd = ckrealloc(treePtr->startEnd,
	treePtr->startEnd = (TkTextLine **)ckrealloc(treePtr->startEnd,
		sizeof(TkTextLine *) * count);
	treePtr->startEndRef = ckrealloc(treePtr->startEndRef,
	treePtr->startEndRef = (TkText **)ckrealloc(treePtr->startEndRef,
		sizeof(TkText *) * count);
    }
    if ((action & TEXT_ADD_REFS)
	    && (textPtr->start != NULL || textPtr->end != NULL)) {
	int count;

	if (textPtr->start != NULL) {
	    treePtr->startEndCount++;
	}
	if (textPtr->end != NULL) {
	    treePtr->startEndCount++;
	}

	count = treePtr->startEndCount;

	treePtr->startEnd = ckrealloc(treePtr->startEnd,
	treePtr->startEnd = (TkTextLine **)ckrealloc(treePtr->startEnd,
		sizeof(TkTextLine *) * count);
	treePtr->startEndRef = ckrealloc(treePtr->startEndRef,
	treePtr->startEndRef = (TkText **)ckrealloc(treePtr->startEndRef,
		sizeof(TkText *) * count);

	if (textPtr->start != NULL) {
	    count--;
	    treePtr->startEnd[count] = textPtr->start;
	    treePtr->startEndRef[count] = textPtr;
	}
721
722
723
724
725
726
727
728

729
730
731
732
733
734
735
736
737
738

739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755

756
757
758
759
760
761
762
721
722
723
724
725
726
727

728
729
730
731
732
733
734
735
736
737

738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754

755
756
757
758
759
760
761
762







-
+









-
+
















-
+








	while (loopPtr != NULL) {
	    pixelCount += AdjustPixelClient(treePtr, defaultHeight, loopPtr,
		    start, end, useReference, newPixelReferences, counting);
	    loopPtr = loopPtr->nextPtr;
	}
    } else {
	register TkTextLine *linePtr = nodePtr->children.linePtr;
	TkTextLine *linePtr = nodePtr->children.linePtr;

	while (linePtr != NULL) {
	    if (!*counting && (linePtr == start)) {
		*counting = 1;
	    }
	    if (*counting && (linePtr == end)) {
		*counting = 0;
	    }
	    if (newPixelReferences != treePtr->pixelReferences) {
		linePtr->pixels = ckrealloc(linePtr->pixels,
		linePtr->pixels = (int *)ckrealloc(linePtr->pixels,
			sizeof(int) * 2 * newPixelReferences);
	    }

	    /*
	     * Notice that for the very last line, we are never counting and
	     * therefore this always has a height of 0 and an epoch of 1.
	     */

	    linePtr->pixels[2*useReference] = (*counting ? defaultHeight : 0);
	    linePtr->pixels[2*useReference+1] = (*counting ? 0 : 1);
	    pixelCount += linePtr->pixels[2*useReference];

	    linePtr = linePtr->nextPtr;
	}
    }
    if (newPixelReferences != treePtr->pixelReferences) {
	nodePtr->numPixels = ckrealloc(nodePtr->numPixels,
	nodePtr->numPixels = (int *)ckrealloc(nodePtr->numPixels,
		sizeof(int) * newPixelReferences);
    }
    nodePtr->numPixels[useReference] = pixelCount;
    return pixelCount;
}

/*
798
799
800
801
802
803
804
805

806
807
808
809
810
811
812
813
814
815

816
817
818
819
820
821
822
823
824
825
826

827
828
829
830
831
832
833
798
799
800
801
802
803
804

805
806
807
808
809
810
811
812
813
814

815
816
817
818
819
820
821
822
823
824
825

826
827
828
829
830
831
832
833







-
+









-
+










-
+







	nodePtr->numPixels[overwriteWithLast] =
		nodePtr->numPixels[treePtr->pixelReferences-1];
    }
    if (treePtr->pixelReferences == 1) {
	ckfree(nodePtr->numPixels);
	nodePtr->numPixels = NULL;
    } else {
	nodePtr->numPixels = ckrealloc(nodePtr->numPixels,
	nodePtr->numPixels = (int *)ckrealloc(nodePtr->numPixels,
		sizeof(int) * (treePtr->pixelReferences - 1));
    }
    if (nodePtr->level != 0) {
	nodePtr = nodePtr->children.nodePtr;
	while (nodePtr != NULL) {
	    RemovePixelClient(treePtr, nodePtr, overwriteWithLast);
	    nodePtr = nodePtr->nextPtr;
	}
    } else {
	register TkTextLine *linePtr = nodePtr->children.linePtr;
	TkTextLine *linePtr = nodePtr->children.linePtr;
	while (linePtr != NULL) {
	    if (overwriteWithLast != -1) {
		linePtr->pixels[2*overwriteWithLast] =
			linePtr->pixels[2*(treePtr->pixelReferences-1)];
		linePtr->pixels[1+2*overwriteWithLast] =
			linePtr->pixels[1+2*(treePtr->pixelReferences-1)];
	    }
	    if (treePtr->pixelReferences == 1) {
		linePtr->pixels = NULL;
	    } else {
		linePtr->pixels = ckrealloc(linePtr->pixels,
		linePtr->pixels = (int *)ckrealloc(linePtr->pixels,
			sizeof(int) * 2 * (treePtr->pixelReferences-1));
	    }
	    linePtr = linePtr->nextPtr;
	}
    }
}

846
847
848
849
850
851
852
853

854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871

872
873
874
875
876
877
878
846
847
848
849
850
851
852

853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870

871
872
873
874
875
876
877
878







-
+

















-
+







 *	All the storage for nodePtr and its descendants is freed.
 *
 *----------------------------------------------------------------------
 */

static void
DestroyNode(
    register Node *nodePtr)	/* Destroy from this node downwards. */
    Node *nodePtr)	/* Destroy from this node downwards. */
{
    if (nodePtr->level == 0) {
	TkTextLine *linePtr;
	TkTextSegment *segPtr;

	while (nodePtr->children.linePtr != NULL) {
	    linePtr = nodePtr->children.linePtr;
	    nodePtr->children.linePtr = linePtr->nextPtr;
	    while (linePtr->segPtr != NULL) {
		segPtr = linePtr->segPtr;
		linePtr->segPtr = segPtr->nextPtr;
		segPtr->typePtr->deleteProc(segPtr, linePtr, 1);
	    }
	    ckfree(linePtr->pixels);
	    ckfree(linePtr);
	}
    } else {
	register Node *childPtr;
	Node *childPtr;

	while (nodePtr->children.nodePtr != NULL) {
	    childPtr = nodePtr->children.nodePtr;
	    nodePtr->children.nodePtr = childPtr->nextPtr;
	    DestroyNode(childPtr);
	}
    }
896
897
898
899
900
901
902
903

904
905
906

907
908
909
910
911
912
913
896
897
898
899
900
901
902

903
904
905

906
907
908
909
910
911
912
913







-
+


-
+







 *	Storage is released.
 *
 *----------------------------------------------------------------------
 */

static void
DeleteSummaries(
    register Summary *summaryPtr)
    Summary *summaryPtr)
				/* First in list of node's tag summaries. */
{
    register Summary *nextPtr;
    Summary *nextPtr;

    while (summaryPtr != NULL) {
	nextPtr = summaryPtr->nextPtr;
	ckfree(summaryPtr);
	summaryPtr = nextPtr;
    }
}
928
929
930
931
932
933
934
935

936
937
938
939
940
941
942
943
944
945

946
947
948
949
950
951
952
928
929
930
931
932
933
934

935
936
937
938
939
940
941
942
943
944

945
946
947
948
949
950
951
952







-
+









-
+







 *
 *----------------------------------------------------------------------
 */

int
TkBTreeAdjustPixelHeight(
    const TkText *textPtr,	/* Client of the B-tree. */
    register TkTextLine *linePtr,
    TkTextLine *linePtr,
				/* The logical line to update. */
    int newPixelHeight,		/* The line's known height in pixels. */
    int mergedLogicalLines)	/* The number of extra logical lines which
				 * have been merged with this one (due to
				 * elided eols). They will have their pixel
				 * height set to zero, and the total pixel
				 * height associated with the given
				 * linePtr. */
{
    register Node *nodePtr;
    Node *nodePtr;
    int changeToPixelCount;	/* Counts change to total number of pixels in
				 * file. */
    int pixelReference = textPtr->pixelReference;

    changeToPixelCount = newPixelHeight - linePtr->pixels[2 * pixelReference];

    /*
997
998
999
1000
1001
1002
1003
1004

1005
1006
1007
1008
1009
1010
1011
1012
1013


1014
1015
1016
1017
1018
1019
1020
1021
1022

1023
1024
1025


1026
1027
1028
1029
1030
1031
1032
997
998
999
1000
1001
1002
1003

1004
1005
1006
1007
1008
1009
1010
1011


1012
1013
1014
1015
1016
1017
1018
1019
1020
1021

1022
1023


1024
1025
1026
1027
1028
1029
1030
1031
1032







-
+







-
-
+
+








-
+

-
-
+
+







 *
 *----------------------------------------------------------------------
 */

void
TkBTreeInsertChars(
    TkTextBTree tree,		/* Tree to insert into. */
    register TkTextIndex *indexPtr,
    TkTextIndex *indexPtr,
				/* Indicates where to insert text. When the
				 * function returns, this index is no longer
				 * valid because of changes to the segment
				 * structure. */
    const char *string)		/* Pointer to bytes to insert (may contain
				 * newlines, must be null-terminated). */
{
    register Node *nodePtr;
    register TkTextSegment *prevPtr;
    Node *nodePtr;
    TkTextSegment *prevPtr;
				/* The segment just before the first new
				 * segment (NULL means new segment is at
				 * beginning of line). */
    TkTextSegment *curPtr;	/* Current segment; new characters are
				 * inserted just after this one. NULL means
				 * insert at beginning of line. */
    TkTextLine *linePtr;	/* Current line (new segments are added to
				 * this line). */
    register TkTextSegment *segPtr;
    TkTextSegment *segPtr;
    TkTextLine *newLinePtr;
    int chunkSize;		/* # characters in current chunk. */
    register const char *eol;	/* Pointer to character just after last one in
    size_t chunkSize;		/* # characters in current chunk. */
    const char *eol;	/* Pointer to character just after last one in
				 * current chunk. */
    int changeToLineCount;	/* Counts change to total number of lines in
				 * file. */
    int *changeToPixelCount;	/* Counts change to total number of pixels in
				 * file. */
    int ref;
    int pixels[PIXEL_CLIENTS];
1040
1041
1042
1043
1044
1045
1046
1047

1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063

1064
1065
1066
1067
1068
1069
1070
1071
1072
1073

1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086


1087
1088
1089
1090
1091
1092
1093
1040
1041
1042
1043
1044
1045
1046

1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062

1063
1064
1065
1066
1067
1068
1069
1070
1071
1072

1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084


1085
1086
1087
1088
1089
1090
1091
1092
1093







-
+















-
+









-
+











-
-
+
+







    /*
     * Chop the string up into lines and create a new segment for each line,
     * plus a new line for the leftovers from the previous line.
     */

    changeToLineCount = 0;
    if (treePtr->pixelReferences > PIXEL_CLIENTS) {
	changeToPixelCount = ckalloc(sizeof(int) * treePtr->pixelReferences);
	changeToPixelCount = (int *)ckalloc(sizeof(int) * treePtr->pixelReferences);
    } else {
	changeToPixelCount = pixels;
    }
    for (ref = 0; ref < treePtr->pixelReferences; ref++) {
	changeToPixelCount[ref] = 0;
    }

    while (*string != 0) {
	for (eol = string; *eol != 0; eol++) {
	    if (*eol == '\n') {
		eol++;
		break;
	    }
	}
	chunkSize = eol-string;
	segPtr = ckalloc(CSEG_SIZE(chunkSize));
	segPtr = (TkTextSegment *)ckalloc(CSEG_SIZE(chunkSize));
	segPtr->typePtr = &tkTextCharType;
	if (curPtr == NULL) {
	    segPtr->nextPtr = linePtr->segPtr;
	    linePtr->segPtr = segPtr;
	} else {
	    segPtr->nextPtr = curPtr->nextPtr;
	    curPtr->nextPtr = segPtr;
	}
	segPtr->size = chunkSize;
	memcpy(segPtr->body.chars, string, (size_t) chunkSize);
	memcpy(segPtr->body.chars, string, chunkSize);
	segPtr->body.chars[chunkSize] = 0;

	if (eol[-1] != '\n') {
	    break;
	}

	/*
	 * The chunk ended with a newline, so create a new TkTextLine and move
	 * the remainder of the old line to it.
	 */

	newLinePtr = ckalloc(sizeof(TkTextLine));
	newLinePtr->pixels =
	newLinePtr = (TkTextLine *)ckalloc(sizeof(TkTextLine));
	newLinePtr->pixels = (int *)
		ckalloc(sizeof(int) * 2 * treePtr->pixelReferences);

	newLinePtr->parentPtr = linePtr->parentPtr;
	newLinePtr->nextPtr = linePtr->nextPtr;
	linePtr->nextPtr = newLinePtr;
	newLinePtr->segPtr = segPtr->nextPtr;

1186
1187
1188
1189
1190
1191
1192
1193

1194
1195
1196
1197
1198
1199
1200

1201
1202
1203
1204
1205
1206
1207
1186
1187
1188
1189
1190
1191
1192

1193
1194
1195
1196
1197
1198
1199

1200
1201
1202
1203
1204
1205
1206
1207







-
+






-
+







static TkTextSegment *
SplitSeg(
    TkTextIndex *indexPtr)	/* Index identifying position at which to
				 * split a segment. */
{
    TkTextSegment *prevPtr, *segPtr;
    TkTextLine *linePtr;
    int count = indexPtr->byteIndex;
    TkSizeT count = indexPtr->byteIndex;

    linePtr = indexPtr->linePtr;
    prevPtr = NULL;
    segPtr = linePtr->segPtr;

    while (segPtr != NULL) {
	if (segPtr->size > count) {
	if (segPtr->size + 1 > count + 1) {
	    if (count == 0) {
		return prevPtr;
	    }
	    segPtr = segPtr->typePtr->splitProc(segPtr, count);
	    if (prevPtr == NULL) {
		indexPtr->linePtr->segPtr = segPtr;
	    } else {
1308
1309
1310
1311
1312
1313
1314
1315

1316
1317
1318

1319
1320
1321
1322
1323
1324
1325
1308
1309
1310
1311
1312
1313
1314

1315
1316
1317

1318
1319
1320
1321
1322
1323
1324
1325







-
+


-
+







 *
 *----------------------------------------------------------------------
 */

void
TkBTreeDeleteIndexRange(
    TkTextBTree tree,		/* Tree to delete from. */
    register TkTextIndex *index1Ptr,
    TkTextIndex *index1Ptr,
				/* Indicates first character that is to be
				 * deleted. */
    register TkTextIndex *index2Ptr)
    TkTextIndex *index2Ptr)
				/* Indicates character just after the last one
				 * that is to be deleted. */
{
    TkTextSegment *prevPtr;	/* The segment just before the start of the
				 * deletion range. */
    TkTextSegment *lastPtr;	/* The segment just after the end of the
				 * deletion range. */
1592
1593
1594
1595
1596
1597
1598
1599
1600


1601
1602
1603
1604
1605
1606
1607
1592
1593
1594
1595
1596
1597
1598


1599
1600
1601
1602
1603
1604
1605
1606
1607







-
-
+
+







TkTextLine *
TkBTreeFindLine(
    TkTextBTree tree,		/* B-tree in which to find line. */
    const TkText *textPtr,	/* Relative to this client of the B-tree. */
    int line)			/* Index of desired line. */
{
    BTree *treePtr = (BTree *) tree;
    register Node *nodePtr;
    register TkTextLine *linePtr;
    Node *nodePtr;
    TkTextLine *linePtr;

    if (treePtr == NULL) {
	treePtr = (BTree *) textPtr->sharedTextPtr->tree;
    }

    nodePtr = treePtr->rootPtr;
    if ((line < 0) || (line >= nodePtr->numLines)) {
1682
1683
1684
1685
1686
1687
1688
1689
1690


1691
1692
1693
1694
1695
1696
1697
1682
1683
1684
1685
1686
1687
1688


1689
1690
1691
1692
1693
1694
1695
1696
1697







-
-
+
+







TkBTreeFindPixelLine(
    TkTextBTree tree,		/* B-tree to use. */
    const TkText *textPtr,	/* Relative to this client of the B-tree. */
    int pixels,			/* Pixel index of desired line. */
    int *pixelOffset)		/* Used to return offset. */
{
    BTree *treePtr = (BTree *) tree;
    register Node *nodePtr;
    register TkTextLine *linePtr;
    Node *nodePtr;
    TkTextLine *linePtr;
    int pixelReference = textPtr->pixelReference;

    nodePtr = treePtr->rootPtr;

    if ((pixels < 0) || (pixels > nodePtr->numPixels[pixelReference])) {
	return NULL;
    }
1751
1752
1753
1754
1755
1756
1757
1758

1759
1760
1761

1762
1763
1764
1765
1766
1767
1768
1751
1752
1753
1754
1755
1756
1757

1758
1759
1760

1761
1762
1763
1764
1765
1766
1767
1768







-
+


-
+







 *
 *----------------------------------------------------------------------
 */

TkTextLine *
TkBTreeNextLine(
    const TkText *textPtr,	/* Next line in the context of this client. */
    register TkTextLine *linePtr)
    TkTextLine *linePtr)
				/* Pointer to existing line in B-tree. */
{
    register Node *nodePtr;
    Node *nodePtr;

    if (linePtr->nextPtr != NULL) {
	if (textPtr != NULL && (linePtr == textPtr->end)) {
	    return NULL;
	} else {
	    return linePtr->nextPtr;
	}
1807
1808
1809
1810
1811
1812
1813
1814

1815
1816
1817
1818
1819



1820
1821
1822
1823
1824
1825
1826
1807
1808
1809
1810
1811
1812
1813

1814
1815
1816



1817
1818
1819
1820
1821
1822
1823
1824
1825
1826







-
+


-
-
-
+
+
+







 *
 *----------------------------------------------------------------------
 */

TkTextLine *
TkBTreePreviousLine(
    TkText *textPtr,		/* Relative to this client of the B-tree. */
    register TkTextLine *linePtr)
    TkTextLine *linePtr)
				/* Pointer to existing line in B-tree. */
{
    register Node *nodePtr;
    register Node *node2Ptr;
    register TkTextLine *prevPtr;
    Node *nodePtr;
    Node *node2Ptr;
    TkTextLine *prevPtr;

    if (textPtr != NULL && textPtr->start == linePtr) {
	return NULL;
    }

    /*
     * Find the line under this node just before the starting line.
1891
1892
1893
1894
1895
1896
1897
1898
1899


1900
1901
1902
1903
1904
1905
1906
1891
1892
1893
1894
1895
1896
1897


1898
1899
1900
1901
1902
1903
1904
1905
1906







-
-
+
+







 */

int
TkBTreePixelsTo(
    const TkText *textPtr,	/* Relative to this client of the B-tree. */
    TkTextLine *linePtr)	/* Pointer to existing line in B-tree. */
{
    register TkTextLine *linePtr2;
    register Node *nodePtr, *parentPtr;
    TkTextLine *linePtr2;
    Node *nodePtr, *parentPtr;
    int index;
    int pixelReference = textPtr->pixelReference;

    /*
     * First count how many pixels precede this line in its level-0 node.
     */

1917
1918
1919
1920
1921
1922
1923
1924

1925
1926
1927
1928
1929
1930
1931
1917
1918
1919
1920
1921
1922
1923

1924
1925
1926
1927
1928
1929
1930
1931







-
+







    /*
     * Now work up through the levels of the tree one at a time, counting how
     * many pixels are in nodes preceding the current node.
     */

    for (parentPtr = nodePtr->parentPtr ; parentPtr != NULL;
	    nodePtr = parentPtr, parentPtr = parentPtr->parentPtr) {
	register Node *nodePtr2;
	Node *nodePtr2;

	for (nodePtr2 = parentPtr->children.nodePtr; nodePtr2 != nodePtr;
		nodePtr2 = nodePtr2->nextPtr) {
	    if (nodePtr2 == NULL) {
		Tcl_Panic("TkBTreePixelsTo couldn't find node");
	    }
	    index += nodePtr2->numPixels[pixelReference];
1953
1954
1955
1956
1957
1958
1959
1960
1961


1962
1963
1964
1965
1966
1967
1968
1953
1954
1955
1956
1957
1958
1959


1960
1961
1962
1963
1964
1965
1966
1967
1968







-
-
+
+







 */

int
TkBTreeLinesTo(
    const TkText *textPtr,	/* Relative to this client of the B-tree. */
    TkTextLine *linePtr)	/* Pointer to existing line in B-tree. */
{
    register TkTextLine *linePtr2;
    register Node *nodePtr, *parentPtr, *nodePtr2;
    TkTextLine *linePtr2;
    Node *nodePtr, *parentPtr, *nodePtr2;
    int index;

    /*
     * First count how many lines precede this one in its level-0 node.
     */

    nodePtr = linePtr->parentPtr;
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049

2050
2051
2052
2053
2054
2055
2056
2033
2034
2035
2036
2037
2038
2039

2040
2041
2042
2043
2044
2045
2046
2047

2048
2049
2050
2051
2052
2053
2054
2055







-








-
+







 *
 * Side effects:
 *	SegPtr will be linked into its tree.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
void
TkBTreeLinkSegment(
    TkTextSegment *segPtr,	/* Pointer to new segment to be added to
				 * B-tree. Should be completely initialized by
				 * caller except for nextPtr field. */
    TkTextIndex *indexPtr)	/* Where to add segment: it gets linked in
				 * just before the segment indicated here. */
{
    register TkTextSegment *prevPtr;
    TkTextSegment *prevPtr;

    prevPtr = SplitSeg(indexPtr);
    if (prevPtr == NULL) {
	segPtr->nextPtr = indexPtr->linePtr->segPtr;
	indexPtr->linePtr->segPtr = segPtr;
    } else {
	segPtr->nextPtr = prevPtr->nextPtr;
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089

2090
2091
2092
2093
2094
2095
2096
2075
2076
2077
2078
2079
2080
2081

2082
2083
2084
2085
2086

2087
2088
2089
2090
2091
2092
2093
2094







-





-
+







 * Side effects:
 *	SegPtr will be unlinked from linePtr. The segment itself isn't
 *	modified by this function.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
void
TkBTreeUnlinkSegment(
    TkTextSegment *segPtr,	/* Segment to be unlinked. */
    TkTextLine *linePtr)	/* Line that currently contains segment. */
{
    register TkTextSegment *prevPtr;
    TkTextSegment *prevPtr;

    if (linePtr->segPtr == segPtr) {
	linePtr->segPtr = segPtr->nextPtr;
    } else {
	prevPtr = linePtr->segPtr;
	while (prevPtr->nextPtr != segPtr) {
	    prevPtr = prevPtr->nextPtr;
2131
2132
2133
2134
2135
2136
2137
2138

2139
2140

2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160

2161
2162
2163
2164
2165
2166
2167
2129
2130
2131
2132
2133
2134
2135

2136
2137

2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157

2158
2159
2160
2161
2162
2163
2164
2165







-
+

-
+



















-
+







 *	indexes may be modified by this function.
 *
 *----------------------------------------------------------------------
 */

int
TkBTreeTag(
    register TkTextIndex *index1Ptr,
    TkTextIndex *index1Ptr,
				/* Indicates first character in range. */
    register TkTextIndex *index2Ptr,
    TkTextIndex *index2Ptr,
				/* Indicates character just after the last one
				 * in range. */
    TkTextTag *tagPtr,		/* Tag to add or remove. */
    int add)			/* One means add tag to the given range of
				 * characters; zero means remove the tag from
				 * the range. */
{
    TkTextSegment *segPtr, *prevPtr;
    TkTextSearch search;
    TkTextLine *cleanupLinePtr;
    int oldState, changed, anyChanges = 0;

    /*
     * See whether the tag is present at the start of the range. If the state
     * doesn't already match what we want then add a toggle there.
     */

    oldState = TkBTreeCharTagged(index1Ptr, tagPtr);
    if ((add != 0) ^ oldState) {
	segPtr = ckalloc(TSEG_SIZE);
	segPtr = (TkTextSegment *)ckalloc(TSEG_SIZE);
	segPtr->typePtr = (add) ? &tkTextToggleOnType : &tkTextToggleOffType;
	prevPtr = SplitSeg(index1Ptr);
	if (prevPtr == NULL) {
	    segPtr->nextPtr = index1Ptr->linePtr->segPtr;
	    index1Ptr->linePtr->segPtr = segPtr;
	} else {
	    segPtr->nextPtr = prevPtr->nextPtr;
2224
2225
2226
2227
2228
2229
2230
2231

2232
2233
2234
2235
2236
2237
2238
2222
2223
2224
2225
2226
2227
2228

2229
2230
2231
2232
2233
2234
2235
2236







-
+







	 */

	if (changed) {
	    TkBTreeStartSearch(index1Ptr, index2Ptr, tagPtr, &search);
	}
    }
    if ((add != 0) ^ oldState) {
	segPtr = ckalloc(TSEG_SIZE);
	segPtr = (TkTextSegment *)ckalloc(TSEG_SIZE);
	segPtr->typePtr = (add) ? &tkTextToggleOffType : &tkTextToggleOnType;
	prevPtr = SplitSeg(index2Ptr);
	if (prevPtr == NULL) {
	    segPtr->nextPtr = index2Ptr->linePtr->segPtr;
	    index2Ptr->linePtr->segPtr = segPtr;
	} else {
	    segPtr->nextPtr = prevPtr->nextPtr;
2281
2282
2283
2284
2285
2286
2287
2288

2289
2290
2291
2292
2293
2294
2295


2296
2297
2298
2299
2300
2301
2302
2279
2280
2281
2282
2283
2284
2285

2286
2287
2288
2289
2290
2291


2292
2293
2294
2295
2296
2297
2298
2299
2300







-
+





-
-
+
+







 *	for the tag, moving it up or down the tree as needed.
 *
 *----------------------------------------------------------------------
 */

static void
ChangeNodeToggleCount(
    register Node *nodePtr,	/* Node whose toggle count for a tag must be
    Node *nodePtr,	/* Node whose toggle count for a tag must be
				 * changed. */
    TkTextTag *tagPtr,		/* Information about tag. */
    int delta)			/* Amount to add to current toggle count for
				 * tag (may be negative). */
{
    register Summary *summaryPtr, *prevPtr;
    register Node *node2Ptr;
    Summary *summaryPtr, *prevPtr;
    Node *node2Ptr;
    int rootLevel;		/* Level of original tag root. */

    tagPtr->toggleCount += delta;
    if (tagPtr->tagRootPtr == NULL) {
	tagPtr->tagRootPtr = nodePtr;
	return;
    }
2368
2369
2370
2371
2372
2373
2374
2375

2376
2377
2378
2379
2380
2381
2382
2383
2384

2385
2386
2387
2388
2389
2390
2391
2366
2367
2368
2369
2370
2371
2372

2373
2374
2375
2376
2377
2378
2379
2380
2381

2382
2383
2384
2385
2386
2387
2388
2389







-
+








-
+







		 * next time through the loop). To push it up one level we
		 * copy the original toggle count into the summary information
		 * at the old root and change the root to its parent node.
		 */

		Node *rootNodePtr = tagPtr->tagRootPtr;

		summaryPtr = ckalloc(sizeof(Summary));
		summaryPtr = (Summary *)ckalloc(sizeof(Summary));
		summaryPtr->tagPtr = tagPtr;
		summaryPtr->toggleCount = tagPtr->toggleCount - delta;
		summaryPtr->nextPtr = rootNodePtr->summaryPtr;
		rootNodePtr->summaryPtr = summaryPtr;
		rootNodePtr = rootNodePtr->parentPtr;
		rootLevel = rootNodePtr->level;
		tagPtr->tagRootPtr = rootNodePtr;
	    }
	    summaryPtr = ckalloc(sizeof(Summary));
	    summaryPtr = (Summary *)ckalloc(sizeof(Summary));
	    summaryPtr->tagPtr = tagPtr;
	    summaryPtr->toggleCount = delta;
	    summaryPtr->nextPtr = nodePtr->summaryPtr;
	    nodePtr->summaryPtr = summaryPtr;
	}
    }

2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477




2478
2479
2480
2481
2482
2483
2484
2465
2466
2467
2468
2469
2470
2471




2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482







-
-
-
-
+
+
+
+








static TkTextSegment *
FindTagStart(
    TkTextBTree tree,		/* Tree to search within. */
    TkTextTag *tagPtr,		/* Tag to search for. */
    TkTextIndex *indexPtr)	/* Return - index information. */
{
    register Node *nodePtr;
    register TkTextLine *linePtr;
    register TkTextSegment *segPtr;
    register Summary *summaryPtr;
    Node *nodePtr;
    TkTextLine *linePtr;
    TkTextSegment *segPtr;
    Summary *summaryPtr;
    int offset;

    nodePtr = tagPtr->tagRootPtr;
    if (nodePtr == NULL) {
	return NULL;
    }

2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562




2563
2564
2565
2566
2567
2568
2569
2550
2551
2552
2553
2554
2555
2556




2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567







-
-
-
-
+
+
+
+








static TkTextSegment *
FindTagEnd(
    TkTextBTree tree,		/* Tree to search within. */
    TkTextTag *tagPtr,		/* Tag to search for. */
    TkTextIndex *indexPtr)	/* Return - index information. */
{
    register Node *nodePtr, *lastNodePtr;
    register TkTextLine *linePtr ,*lastLinePtr;
    register TkTextSegment *segPtr, *lastSegPtr, *last2SegPtr;
    register Summary *summaryPtr;
    Node *nodePtr, *lastNodePtr;
    TkTextLine *linePtr ,*lastLinePtr;
    TkTextSegment *segPtr, *lastSegPtr, *last2SegPtr;
    Summary *summaryPtr;
    int lastoffset, lastoffset2, offset;

    nodePtr = tagPtr->tagRootPtr;
    if (nodePtr == NULL) {
	return NULL;
    }

2648
2649
2650
2651
2652
2653
2654
2655

2656
2657
2658
2659

2660
2661
2662
2663
2664
2665
2666
2646
2647
2648
2649
2650
2651
2652

2653
2654
2655
2656

2657
2658
2659
2660
2661
2662
2663
2664







-
+



-
+







TkBTreeStartSearch(
    TkTextIndex *index1Ptr,	/* Search starts here. Tag toggles at this
				 * position will not be returned. */
    TkTextIndex *index2Ptr,	/* Search stops here. Tag toggles at this
				 * position *will* be returned. */
    TkTextTag *tagPtr,		/* Tag to search for. NULL means search for
				 * any tag. */
    register TkTextSearch *searchPtr)
    TkTextSearch *searchPtr)
				/* Where to store information about search's
				 * progress. */
{
    int offset;
    TkSizeT offset;
    TkTextIndex index0;		/* First index of the tag. */
    TkTextSegment *seg0Ptr;	/* First segment of the tag. */

    /*
     * Find the segment that contains the first toggle for the tag. This may
     * become the starting point in the search.
     */
2744
2745
2746
2747
2748
2749
2750
2751

2752
2753
2754
2755

2756
2757
2758
2759
2760
2761
2762
2742
2743
2744
2745
2746
2747
2748

2749
2750
2751
2752

2753
2754
2755
2756
2757
2758
2759
2760







-
+



-
+







TkBTreeStartSearchBack(
    TkTextIndex *index1Ptr,	/* Search starts here. Tag toggles at this
				 * position will not be returned. */
    TkTextIndex *index2Ptr,	/* Search stops here. Tag toggles at this
				 * position *will* be returned. */
    TkTextTag *tagPtr,		/* Tag to search for. NULL means search for
				 * any tag. */
    register TkTextSearch *searchPtr)
    TkTextSearch *searchPtr)
				/* Where to store information about search's
				 * progress. */
{
    int offset;
    TkSizeT offset;
    TkTextIndex index0;		/* Last index of the tag. */
    TkTextIndex backOne;	/* One character before starting index. */
    TkTextSegment *seg0Ptr;	/* Last segment of the tag. */

    /*
     * Find the segment that contains the last toggle for the tag. This may
     * become the starting point in the search.
2845
2846
2847
2848
2849
2850
2851
2852

2853
2854
2855
2856
2857
2858
2859



2860
2861
2862
2863
2864
2865
2866
2843
2844
2845
2846
2847
2848
2849

2850
2851
2852
2853
2854



2855
2856
2857
2858
2859
2860
2861
2862
2863
2864







-
+




-
-
-
+
+
+







 *	search and indicate where the next tag toggle is located.
 *
 *----------------------------------------------------------------------
 */

int
TkBTreeNextTag(
    register TkTextSearch *searchPtr)
    TkTextSearch *searchPtr)
				/* Information about search in progress; must
				 * have been set up by call to
				 * TkBTreeStartSearch. */
{
    register TkTextSegment *segPtr;
    register Node *nodePtr;
    register Summary *summaryPtr;
    TkTextSegment *segPtr;
    Node *nodePtr;
    Summary *summaryPtr;

    if (searchPtr->linesLeft <= 0) {
	goto searchOver;
    }

    /*
     * The outermost loop iterates over lines that may potentially contain a
3010
3011
3012
3013
3014
3015
3016
3017

3018
3019
3020
3021
3022
3023
3024
3025




3026
3027
3028
3029
3030
3031
3032
3008
3009
3010
3011
3012
3013
3014

3015
3016
3017
3018
3019




3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030







-
+




-
-
-
-
+
+
+
+







 *	search and indicate where the next tag toggle is located.
 *
 *----------------------------------------------------------------------
 */

int
TkBTreePrevTag(
    register TkTextSearch *searchPtr)
    TkTextSearch *searchPtr)
				/* Information about search in progress; must
				 * have been set up by call to
				 * TkBTreeStartSearch. */
{
    register TkTextSegment *segPtr, *prevPtr;
    register TkTextLine *linePtr, *prevLinePtr;
    register Node *nodePtr, *node2Ptr, *prevNodePtr;
    register Summary *summaryPtr;
    TkTextSegment *segPtr, *prevPtr;
    TkTextLine *linePtr, *prevLinePtr;
    Node *nodePtr, *node2Ptr, *prevNodePtr;
    Summary *summaryPtr;
    int byteIndex, linesSkipped;
    int pastLast;		/* Saw last marker during scan. */

    if (searchPtr->linesLeft <= 0) {
	goto searchOver;
    }

3228
3229
3230
3231
3232
3233
3234
3235
3236
3237



3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249

3250
3251
3252
3253
3254
3255
3256
3226
3227
3228
3229
3230
3231
3232



3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246

3247
3248
3249
3250
3251
3252
3253
3254







-
-
-
+
+
+











-
+








int
TkBTreeCharTagged(
    const TkTextIndex *indexPtr,/* Indicates a character position at which to
				 * check for a tag. */
    TkTextTag *tagPtr)		/* Tag of interest. */
{
    register Node *nodePtr;
    register TkTextLine *siblingLinePtr;
    register TkTextSegment *segPtr;
    Node *nodePtr;
    TkTextLine *siblingLinePtr;
    TkTextSegment *segPtr;
    TkTextSegment *toggleSegPtr;
    int toggles, index;

    /*
     * Check for toggles for the tag in indexPtr's line but before indexPtr.
     * If there is one, its type indicates whether or not the character is
     * tagged.
     */

    toggleSegPtr = NULL;
    for (index = 0, segPtr = indexPtr->linePtr->segPtr;
	    (index + segPtr->size) <= indexPtr->byteIndex;
	    (index + (int)segPtr->size) <= indexPtr->byteIndex;
	    index += segPtr->size, segPtr = segPtr->nextPtr) {
	if (((segPtr->typePtr == &tkTextToggleOnType)
		|| (segPtr->typePtr == &tkTextToggleOffType))
		&& (segPtr->body.toggle.tagPtr == tagPtr)) {
	    toggleSegPtr = segPtr;
	}
    }
3284
3285
3286
3287
3288
3289
3290
3291
3292


3293
3294
3295
3296
3297
3298
3299
3282
3283
3284
3285
3286
3287
3288


3289
3290
3291
3292
3293
3294
3295
3296
3297







-
-
+
+







     * node, counting the number of toggles of the given tag in siblings that
     * precede that node.
     */

    toggles = 0;
    for (nodePtr = indexPtr->linePtr->parentPtr; nodePtr->parentPtr != NULL;
	    nodePtr = nodePtr->parentPtr) {
	register Node *siblingPtr;
	register Summary *summaryPtr;
	Node *siblingPtr;
	Summary *summaryPtr;

	for (siblingPtr = nodePtr->parentPtr->children.nodePtr;
		siblingPtr != nodePtr; siblingPtr = siblingPtr->nextPtr) {
	    for (summaryPtr = siblingPtr->summaryPtr; summaryPtr != NULL;
		    summaryPtr = summaryPtr->nextPtr) {
		if (summaryPtr->tagPtr == tagPtr) {
		    toggles += summaryPtr->toggleCount;
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352



3353
3354
3355
3356
3357
3358
3359
3360
3361


3362
3363
3364
3365
3366
3367
3368
3369
3370

3371
3372
3373
3374
3375
3376
3377
3330
3331
3332
3333
3334
3335
3336

3337
3338
3339
3340
3341
3342
3343
3344
3345
3346



3347
3348
3349
3350
3351
3352
3353
3354
3355
3356


3357
3358
3359
3360
3361
3362
3363
3364
3365
3366

3367
3368
3369
3370
3371
3372
3373
3374







-










-
-
-
+
+
+







-
-
+
+








-
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
TkTextTag **
TkBTreeGetTags(
    const TkTextIndex *indexPtr,/* Indicates a particular position in the
				 * B-tree. */
    const TkText *textPtr,	/* If non-NULL, then only return tags for this
				 * text widget (when there are peer
				 * widgets). */
    int *numTagsPtr)		/* Store number of tags found at this
				 * location. */
{
    register Node *nodePtr;
    register TkTextLine *siblingLinePtr;
    register TkTextSegment *segPtr;
    Node *nodePtr;
    TkTextLine *siblingLinePtr;
    TkTextSegment *segPtr;
    TkTextLine *linePtr;
    int src, dst, index;
    TagInfo tagInfo;
#define NUM_TAG_INFOS 10

    tagInfo.numTags = 0;
    tagInfo.arraySize = NUM_TAG_INFOS;
    tagInfo.tagPtrs = ckalloc(NUM_TAG_INFOS * sizeof(TkTextTag *));
    tagInfo.counts = ckalloc(NUM_TAG_INFOS * sizeof(int));
    tagInfo.tagPtrs = (TkTextTag **)ckalloc(NUM_TAG_INFOS * sizeof(TkTextTag *));
    tagInfo.counts = (int *)ckalloc(NUM_TAG_INFOS * sizeof(int));

    /*
     * Record tag toggles within the line of indexPtr but preceding indexPtr.
     */

    linePtr = indexPtr->linePtr;
    index = 0;
    segPtr = linePtr->segPtr;
    while ((index + segPtr->size) <= indexPtr->byteIndex) {
    while ((index + (int)segPtr->size) <= indexPtr->byteIndex) {
	if ((segPtr->typePtr == &tkTextToggleOnType)
		|| (segPtr->typePtr == &tkTextToggleOffType)) {
	    IncCount(segPtr->body.toggle.tagPtr, 1, &tagInfo);
	}
	index += segPtr->size;
	segPtr = segPtr->nextPtr;

3406
3407
3408
3409
3410
3411
3412
3413
3414


3415
3416
3417
3418
3419
3420
3421
3403
3404
3405
3406
3407
3408
3409


3410
3411
3412
3413
3414
3415
3416
3417
3418







-
-
+
+







    /*
     * For each node in the ancestry of this line, record tag toggles for all
     * siblings that precede that node.
     */

    for (nodePtr = indexPtr->linePtr->parentPtr; nodePtr->parentPtr != NULL;
	    nodePtr = nodePtr->parentPtr) {
	register Node *siblingPtr;
	register Summary *summaryPtr;
	Node *siblingPtr;
	Summary *summaryPtr;

	for (siblingPtr = nodePtr->parentPtr->children.nodePtr;
		siblingPtr != nodePtr; siblingPtr = siblingPtr->nextPtr) {
	    for (summaryPtr = siblingPtr->summaryPtr; summaryPtr != NULL;
		    summaryPtr = summaryPtr->nextPtr) {
		if (summaryPtr->toggleCount & 1) {
		    IncCount(summaryPtr->tagPtr, summaryPtr->toggleCount,
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500






3501
3502
3503
3504
3505

3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521


3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535

3536
3537
3538
3539
3540
3541
3542
3475
3476
3477
3478
3479
3480
3481

3482
3483
3484
3485
3486
3487
3488
3489
3490






3491
3492
3493
3494
3495
3496
3497
3498
3499
3500

3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515


3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530

3531
3532
3533
3534
3535
3536
3537
3538







-









-
-
-
-
-
-
+
+
+
+
+
+




-
+














-
-
+
+













-
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
int
TkTextIsElided(
    const TkText *textPtr,	/* Overall information about text widget. */
    const TkTextIndex *indexPtr,/* The character in the text for which display
				 * information is wanted. */
    TkTextElideInfo *elideInfo)	/* NULL or a pointer to a structure in which
				 * indexPtr's elide state will be stored and
				 * returned. */
{
    register Node *nodePtr;
    register TkTextLine *siblingLinePtr;
    register TkTextSegment *segPtr;
    register TkTextTag *tagPtr = NULL;
    register int i, index;
    register TkTextElideInfo *infoPtr;
    Node *nodePtr;
    TkTextLine *siblingLinePtr;
    TkTextSegment *segPtr;
    TkTextTag *tagPtr = NULL;
    int i, index;
    TkTextElideInfo *infoPtr;
    TkTextLine *linePtr;
    int elide;

    if (elideInfo == NULL) {
	infoPtr = ckalloc(sizeof(TkTextElideInfo));
	infoPtr = (TkTextElideInfo *)ckalloc(sizeof(TkTextElideInfo));
    } else {
	infoPtr = elideInfo;
    }

    infoPtr->elide = 0;		/* If nobody says otherwise, it's visible. */
    infoPtr->tagCnts = infoPtr->deftagCnts;
    infoPtr->tagPtrs = infoPtr->deftagPtrs;
    infoPtr->numTags = textPtr->sharedTextPtr->numTags;

    /*
     * Almost always avoid malloc, so stay out of system calls.
     */

    if (LOTSA_TAGS < infoPtr->numTags) {
	infoPtr->tagCnts = ckalloc(sizeof(int) * infoPtr->numTags);
	infoPtr->tagPtrs = ckalloc(sizeof(TkTextTag *) * infoPtr->numTags);
	infoPtr->tagCnts = (int *)ckalloc(sizeof(int) * infoPtr->numTags);
	infoPtr->tagPtrs = (TkTextTag **)ckalloc(sizeof(TkTextTag *) * infoPtr->numTags);
    }

    for (i=0; i<infoPtr->numTags; i++) {
	infoPtr->tagCnts[i] = 0;
    }

    /*
     * Record tag toggles within the line of indexPtr but preceding indexPtr.
     */

    index = 0;
    linePtr = indexPtr->linePtr;
    segPtr = linePtr->segPtr;
    while ((index + segPtr->size) <= indexPtr->byteIndex) {
    while ((index + (int)segPtr->size) <= indexPtr->byteIndex) {
	if ((segPtr->typePtr == &tkTextToggleOnType)
		|| (segPtr->typePtr == &tkTextToggleOffType)) {
	    tagPtr = segPtr->body.toggle.tagPtr;
	    if (tagPtr->elideString != NULL) {
		infoPtr->tagPtrs[tagPtr->priority] = tagPtr;
		infoPtr->tagCnts[tagPtr->priority]++;
	    }
3587
3588
3589
3590
3591
3592
3593
3594
3595


3596
3597
3598
3599
3600
3601
3602
3583
3584
3585
3586
3587
3588
3589


3590
3591
3592
3593
3594
3595
3596
3597
3598







-
-
+
+







    /*
     * For each node in the ancestry of this line, record tag toggles for all
     * siblings that precede that node.
     */

    for (nodePtr = indexPtr->linePtr->parentPtr; nodePtr->parentPtr != NULL;
	    nodePtr = nodePtr->parentPtr) {
	register Node *siblingPtr;
	register Summary *summaryPtr;
	Node *siblingPtr;
	Summary *summaryPtr;

	for (siblingPtr = nodePtr->parentPtr->children.nodePtr;
		siblingPtr != nodePtr; siblingPtr = siblingPtr->nextPtr) {
	    for (summaryPtr = siblingPtr->summaryPtr; summaryPtr != NULL;
		    summaryPtr = summaryPtr->nextPtr) {
		if (summaryPtr->toggleCount & 1) {
		    tagPtr = summaryPtr->tagPtr;
3693
3694
3695
3696
3697
3698
3699
3700

3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721

3722
3723
3724
3725
3726

3727
3728
3729
3730
3731
3732
3733
3689
3690
3691
3692
3693
3694
3695

3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716

3717
3718
3719
3720
3721

3722
3723
3724
3725
3726
3727
3728
3729







-
+




















-
+




-
+







static void
IncCount(
    TkTextTag *tagPtr,		/* Handle for tag. */
    int inc,			/* Amount by which to increment tag count. */
    TagInfo *tagInfoPtr)	/* Holds cumulative information about tags;
				 * increment count here. */
{
    register TkTextTag **tagPtrPtr;
    TkTextTag **tagPtrPtr;
    int count;

    for (tagPtrPtr = tagInfoPtr->tagPtrs, count = tagInfoPtr->numTags;
	    count > 0; tagPtrPtr++, count--) {
	if (*tagPtrPtr == tagPtr) {
	    tagInfoPtr->counts[tagInfoPtr->numTags-count] += inc;
	    return;
	}
    }

    /*
     * There isn't currently an entry for this tag, so we have to make a new
     * one. If the arrays are full, then enlarge the arrays first.
     */

    if (tagInfoPtr->numTags == tagInfoPtr->arraySize) {
	TkTextTag **newTags;
	int *newCounts, newSize;

	newSize = 2 * tagInfoPtr->arraySize;
	newTags = ckalloc(newSize * sizeof(TkTextTag *));
	newTags = (TkTextTag **)ckalloc(newSize * sizeof(TkTextTag *));
	memcpy(newTags, tagInfoPtr->tagPtrs,
		tagInfoPtr->arraySize * sizeof(TkTextTag *));
	ckfree(tagInfoPtr->tagPtrs);
	tagInfoPtr->tagPtrs = newTags;
	newCounts = ckalloc(newSize * sizeof(int));
	newCounts = (int *)ckalloc(newSize * sizeof(int));
	memcpy(newCounts, tagInfoPtr->counts,
		tagInfoPtr->arraySize * sizeof(int));
	ckfree(tagInfoPtr->counts);
	tagInfoPtr->counts = newCounts;
	tagInfoPtr->arraySize = newSize;
    }

3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766





3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777

3778
3779
3780
3781
3782
3783
3784
3751
3752
3753
3754
3755
3756
3757





3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772

3773
3774
3775
3776
3777
3778
3779
3780







-
-
-
-
-
+
+
+
+
+










-
+







 */

void
TkBTreeCheck(
    TkTextBTree tree)		/* Tree to check. */
{
    BTree *treePtr = (BTree *) tree;
    register Summary *summaryPtr;
    register Node *nodePtr;
    register TkTextLine *linePtr;
    register TkTextSegment *segPtr;
    register TkTextTag *tagPtr;
    Summary *summaryPtr;
    Node *nodePtr;
    TkTextLine *linePtr;
    TkTextSegment *segPtr;
    TkTextTag *tagPtr;
    Tcl_HashEntry *entryPtr;
    Tcl_HashSearch search;
    int count;

    /*
     * Make sure that the tag toggle counts and the tag root pointers are OK.
     */

    for (entryPtr=Tcl_FirstHashEntry(&treePtr->sharedTextPtr->tagTable,&search);
	    entryPtr != NULL ; entryPtr = Tcl_NextHashEntry(&search)) {
	tagPtr = Tcl_GetHashValue(entryPtr);
	tagPtr = (TkTextTag *)Tcl_GetHashValue(entryPtr);
	nodePtr = tagPtr->tagRootPtr;
	if (nodePtr == NULL) {
	    if (tagPtr->toggleCount != 0) {
		Tcl_Panic("TkBTreeCheck found \"%s\" with toggles (%d) but no root",
			tagPtr->name, tagPtr->toggleCount);
	    }
	    continue;		/* No ranges for the tag. */
3865
3866
3867
3868
3869
3870
3871
3872

3873
3874
3875
3876
3877
3878
3879
3861
3862
3863
3864
3865
3866
3867

3868
3869
3870
3871
3872
3873
3874
3875







-
+







	Tcl_Panic("TkBTreeCheck: last line has bogus segment type");
    }
    if (segPtr->nextPtr != NULL) {
	Tcl_Panic("TkBTreeCheck: last line has too many segments");
    }
    if (segPtr->size != 1) {
	Tcl_Panic("TkBTreeCheck: last line has wrong # characters: %d",
		segPtr->size);
		(int)segPtr->size);
    }
    if ((segPtr->body.chars[0] != '\n') || (segPtr->body.chars[1] != 0)) {
	Tcl_Panic("TkBTreeCheck: last line had bad value: %s",
		segPtr->body.chars);
    }
}

3894
3895
3896
3897
3898
3899
3900
3901

3902
3903
3904
3905
3906
3907
3908




3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929

3930
3931
3932
3933
3934
3935
3936
3890
3891
3892
3893
3894
3895
3896

3897
3898
3899
3900




3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924

3925
3926
3927
3928
3929
3930
3931
3932







-
+



-
-
-
-
+
+
+
+




















-
+







 *	panics.
 *
 *----------------------------------------------------------------------
 */

static void
CheckNodeConsistency(
    register Node *nodePtr,	/* Node whose subtree should be checked. */
    Node *nodePtr,	/* Node whose subtree should be checked. */
    int references)		/* Number of referring widgets which have
				 * pixel counts. */
{
    register Node *childNodePtr;
    register Summary *summaryPtr, *summaryPtr2;
    register TkTextLine *linePtr;
    register TkTextSegment *segPtr;
    Node *childNodePtr;
    Summary *summaryPtr, *summaryPtr2;
    TkTextLine *linePtr;
    TkTextSegment *segPtr;
    int numChildren, numLines, toggleCount, minChildren, i;
    int *numPixels;
    int pixels[PIXEL_CLIENTS];

    if (nodePtr->parentPtr != NULL) {
	minChildren = MIN_CHILDREN;
    } else if (nodePtr->level > 0) {
	minChildren = 2;
    } else {
	minChildren = 1;
    }
    if ((nodePtr->numChildren < minChildren)
	    || (nodePtr->numChildren > MAX_CHILDREN)) {
	Tcl_Panic("CheckNodeConsistency: bad child count (%d)",
		nodePtr->numChildren);
    }

    numChildren = 0;
    numLines = 0;
    if (references > PIXEL_CLIENTS) {
	numPixels = ckalloc(sizeof(int) * references);
	numPixels = (int *)ckalloc(sizeof(int) * references);
    } else {
	numPixels = pixels;
    }
    for (i = 0; i<references; i++) {
	numPixels[i] = 0;
    }

4083
4084
4085
4086
4087
4088
4089
4090

4091
4092
4093
4094
4095
4096
4097
4098
4099


4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117

4118
4119
4120
4121
4122
4123
4124
4125

4126
4127
4128
4129
4130
4131
4132
4133
4134


4135
4136
4137
4138
4139
4140
4141
4079
4080
4081
4082
4083
4084
4085

4086
4087
4088
4089
4090
4091
4092
4093


4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112

4113
4114
4115
4116
4117
4118
4119
4120

4121
4122
4123
4124
4125
4126
4127
4128


4129
4130
4131
4132
4133
4134
4135
4136
4137







-
+







-
-
+
+

















-
+







-
+







-
-
+
+







 *
 *----------------------------------------------------------------------
 */

static void
Rebalance(
    BTree *treePtr,		/* Tree that is being rebalanced. */
    register Node *nodePtr)	/* Node that may be out of balance. */
    Node *nodePtr)	/* Node that may be out of balance. */
{
    /*
     * Loop over the entire ancestral chain of the node, working up through
     * the tree one node at a time until the root node has been processed.
     */

    for ( ; nodePtr != NULL; nodePtr = nodePtr->parentPtr) {
	register Node *newPtr, *childPtr;
	register TkTextLine *linePtr;
	Node *newPtr, *childPtr;
	TkTextLine *linePtr;
	int i;

	/*
	 * Check to see if the node has too many children. If it does, then
	 * split off all but the first MIN_CHILDREN into a separate node
	 * following the original one. Then repeat until the node has a decent
	 * size.
	 */

	if (nodePtr->numChildren > MAX_CHILDREN) {
	    while (1) {
		/*
		 * If the node being split is the root node, then make a new
		 * root node above it first.
		 */

		if (nodePtr->parentPtr == NULL) {
		    newPtr = ckalloc(sizeof(Node));
		    newPtr = (Node *)ckalloc(sizeof(Node));
		    newPtr->parentPtr = NULL;
		    newPtr->nextPtr = NULL;
		    newPtr->summaryPtr = NULL;
		    newPtr->level = nodePtr->level + 1;
		    newPtr->children.nodePtr = nodePtr;
		    newPtr->numChildren = 1;
		    newPtr->numLines = nodePtr->numLines;
		    newPtr->numPixels =
		    newPtr->numPixels = (int *)
			    ckalloc(sizeof(int) * treePtr->pixelReferences);
		    for (i=0; i<treePtr->pixelReferences; i++) {
			newPtr->numPixels[i] = nodePtr->numPixels[i];
		    }
		    RecomputeNodeCounts(treePtr, newPtr);
		    treePtr->rootPtr = newPtr;
		}
		newPtr = ckalloc(sizeof(Node));
		newPtr->numPixels =
		newPtr = (Node *)ckalloc(sizeof(Node));
		newPtr->numPixels = (int *)
			ckalloc(sizeof(int) * treePtr->pixelReferences);
		for (i=0; i<treePtr->pixelReferences; i++) {
		    newPtr->numPixels[i] = 0;
		}
		newPtr->parentPtr = nodePtr->parentPtr;
		newPtr->nextPtr = nodePtr->nextPtr;
		nodePtr->nextPtr = newPtr;
4166
4167
4168
4169
4170
4171
4172
4173

4174
4175
4176

4177
4178
4179
4180
4181
4182
4183
4162
4163
4164
4165
4166
4167
4168

4169
4170
4171

4172
4173
4174
4175
4176
4177
4178
4179







-
+


-
+







		    RecomputeNodeCounts(treePtr, nodePtr);
		    break;
		}
	    }
	}

	while (nodePtr->numChildren < MIN_CHILDREN) {
	    register Node *otherPtr;
	    Node *otherPtr;
	    Node *halfwayNodePtr = NULL;       /* Initialization needed only */
	    TkTextLine *halfwayLinePtr = NULL; /* to prevent cc warnings. */
	    int totalChildren, firstChildren, i;
	    int totalChildren, firstChildren;

	    /*
	     * Too few children for this node. If this is the root then, it's
	     * OK for it to have less than MIN_CHILDREN children as long as
	     * it's got at least two. If it has only one (and isn't at level
	     * 0), then chop the root node out of the tree and use its child
	     * as the new root.
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4226
4227
4228
4229
4230
4231
4232


4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246


4247
4248
4249
4250
4251
4252
4253







-
-














-
-







	    firstChildren = totalChildren/2;
	    if (nodePtr->children.nodePtr == NULL) {
		nodePtr->children = otherPtr->children;
		otherPtr->children.nodePtr = NULL;
		otherPtr->children.linePtr = NULL;
	    }
	    if (nodePtr->level == 0) {
		register TkTextLine *linePtr;

		for (linePtr = nodePtr->children.linePtr, i = 1;
			linePtr->nextPtr != NULL;
			linePtr = linePtr->nextPtr, i++) {
		    if (i == firstChildren) {
			halfwayLinePtr = linePtr;
		    }
		}
		linePtr->nextPtr = otherPtr->children.linePtr;
		while (i <= firstChildren) {
		    halfwayLinePtr = linePtr;
		    linePtr = linePtr->nextPtr;
		    i++;
		}
	    } else {
		register Node *childPtr;

		for (childPtr = nodePtr->children.nodePtr, i = 1;
			childPtr->nextPtr != NULL;
			childPtr = childPtr->nextPtr, i++) {
		    if (i <= firstChildren) {
			if (i == firstChildren) {
			    halfwayNodePtr = childPtr;
			}
4322
4323
4324
4325
4326
4327
4328
4329
4330


4331
4332
4333
4334
4335
4336




4337
4338
4339
4340
4341
4342
4343
4314
4315
4316
4317
4318
4319
4320


4321
4322
4323
4324




4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335







-
-
+
+


-
-
-
-
+
+
+
+







 *	the childrens' parentPtr fields are made to point to nodePtr.
 *
 *----------------------------------------------------------------------
 */

static void
RecomputeNodeCounts(
    register BTree *treePtr,	/* The whole B-tree. */
    register Node *nodePtr)	/* Node whose tag summary information must be
    BTree *treePtr,	/* The whole B-tree. */
    Node *nodePtr)	/* Node whose tag summary information must be
				 * recomputed. */
{
    register Summary *summaryPtr, *summaryPtr2;
    register Node *childPtr;
    register TkTextLine *linePtr;
    register TkTextSegment *segPtr;
    Summary *summaryPtr, *summaryPtr2;
    Node *childPtr;
    TkTextLine *linePtr;
    TkTextSegment *segPtr;
    TkTextTag *tagPtr;
    int ref;

    /*
     * Zero out all the existing counts for the node, but don't delete the
     * existing Summary records (most of them will probably be reused).
     */
4373
4374
4375
4376
4377
4378
4379
4380

4381
4382
4383
4384
4385
4386
4387
4365
4366
4367
4368
4369
4370
4371

4372
4373
4374
4375
4376
4377
4378
4379







-
+







			|| !(segPtr->body.toggle.inNodeCounts)) {
		    continue;
		}
		tagPtr = segPtr->body.toggle.tagPtr;
		for (summaryPtr = nodePtr->summaryPtr; ;
			summaryPtr = summaryPtr->nextPtr) {
		    if (summaryPtr == NULL) {
			summaryPtr = ckalloc(sizeof(Summary));
			summaryPtr = (Summary *)ckalloc(sizeof(Summary));
			summaryPtr->tagPtr = tagPtr;
			summaryPtr->toggleCount = 1;
			summaryPtr->nextPtr = nodePtr->summaryPtr;
			nodePtr->summaryPtr = summaryPtr;
			break;
		    }
		    if (summaryPtr->tagPtr == tagPtr) {
4401
4402
4403
4404
4405
4406
4407
4408

4409
4410
4411
4412
4413
4414
4415
4393
4394
4395
4396
4397
4398
4399

4400
4401
4402
4403
4404
4405
4406
4407







-
+







	    }
	    childPtr->parentPtr = nodePtr;
	    for (summaryPtr2 = childPtr->summaryPtr; summaryPtr2 != NULL;
		    summaryPtr2 = summaryPtr2->nextPtr) {
		for (summaryPtr = nodePtr->summaryPtr; ;
			summaryPtr = summaryPtr->nextPtr) {
		    if (summaryPtr == NULL) {
			summaryPtr = ckalloc(sizeof(Summary));
			summaryPtr = (Summary *)ckalloc(sizeof(Summary));
			summaryPtr->tagPtr = summaryPtr2->tagPtr;
			summaryPtr->toggleCount = summaryPtr2->toggleCount;
			summaryPtr->nextPtr = nodePtr->summaryPtr;
			nodePtr->summaryPtr = summaryPtr;
			break;
		    }
		    if (summaryPtr->tagPtr == summaryPtr2->tagPtr) {
4549
4550
4551
4552
4553
4554
4555
4556

4557
4558
4559
4560
4561
4562


4563
4564
4565
4566

4567
4568
4569
4570
4571
4572
4573
4541
4542
4543
4544
4545
4546
4547

4548
4549
4550
4551
4552


4553
4554
4555
4556
4557

4558
4559
4560
4561
4562
4563
4564
4565







-
+




-
-
+
+



-
+







 *
 *--------------------------------------------------------------
 */

static TkTextSegment *
CharSplitProc(
    TkTextSegment *segPtr,	/* Pointer to segment to split. */
    int index)			/* Position within segment at which to
    TkSizeT index)			/* Position within segment at which to
				 * split. */
{
    TkTextSegment *newPtr1, *newPtr2;

    newPtr1 = ckalloc(CSEG_SIZE(index));
    newPtr2 = ckalloc(CSEG_SIZE(segPtr->size - index));
    newPtr1 = (TkTextSegment *)ckalloc(CSEG_SIZE(index));
    newPtr2 = (TkTextSegment *)ckalloc(CSEG_SIZE(segPtr->size - index));
    newPtr1->typePtr = &tkTextCharType;
    newPtr1->nextPtr = newPtr2;
    newPtr1->size = index;
    memcpy(newPtr1->body.chars, segPtr->body.chars, (size_t) index);
    memcpy(newPtr1->body.chars, segPtr->body.chars, index);
    newPtr1->body.chars[index] = 0;
    newPtr2->typePtr = &tkTextCharType;
    newPtr2->nextPtr = segPtr->nextPtr;
    newPtr2->size = segPtr->size - index;
    memcpy(newPtr2->body.chars, segPtr->body.chars + index, newPtr2->size);
    newPtr2->body.chars[newPtr2->size] = 0;
    ckfree(segPtr);
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600

4601
4602
4603
4604
4605
4606
4607
4608

4609
4610
4611
4612
4613
4614
4615
4580
4581
4582
4583
4584
4585
4586

4587
4588
4589
4590

4591
4592
4593
4594
4595
4596
4597
4598

4599
4600
4601
4602
4603
4604
4605
4606







-




-
+







-
+







 *
 * Side effects:
 *	Storage for the segments may be allocated and freed.
 *
 *--------------------------------------------------------------
 */

	/* ARGSUSED */
static TkTextSegment *
CharCleanupProc(
    TkTextSegment *segPtr,	/* Pointer to first of two adjacent segments
				 * to join. */
    TkTextLine *linePtr)	/* Line containing segments (not used). */
    TCL_UNUSED(TkTextLine *))	/* Line containing segments (not used). */
{
    TkTextSegment *segPtr2, *newPtr;

    segPtr2 = segPtr->nextPtr;
    if ((segPtr2 == NULL) || (segPtr2->typePtr != &tkTextCharType)) {
	return segPtr;
    }
    newPtr = ckalloc(CSEG_SIZE(segPtr->size + segPtr2->size));
    newPtr = (TkTextSegment *)ckalloc(CSEG_SIZE(segPtr->size + segPtr2->size));
    newPtr->typePtr = &tkTextCharType;
    newPtr->nextPtr = segPtr2->nextPtr;
    newPtr->size = segPtr->size + segPtr2->size;
    memcpy(newPtr->body.chars, segPtr->body.chars, segPtr->size);
    memcpy(newPtr->body.chars + segPtr->size, segPtr2->body.chars, segPtr2->size);
    newPtr->body.chars[newPtr->size] = 0;
    ckfree(segPtr);
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641


4642
4643
4644
4645
4646
4647
4648
4620
4621
4622
4623
4624
4625
4626

4627
4628
4629


4630
4631
4632
4633
4634
4635
4636
4637
4638







-



-
-
+
+







 *
 * Side effects:
 *	Storage for the segment is freed.
 *
 *--------------------------------------------------------------
 */

	/* ARGSUSED */
static int
CharDeleteProc(
    TkTextSegment *segPtr,	/* Segment to delete. */
    TkTextLine *linePtr,	/* Line containing segment. */
    int treeGone)		/* Non-zero means the entire tree is being
    TCL_UNUSED(TkTextLine *),	/* Line containing segment. */
    TCL_UNUSED(int))		/* Non-zero means the entire tree is being
				 * deleted, so everything must get cleaned
				 * up. */
{
    ckfree(segPtr);
    return 0;
}

4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670

4671
4672
4673
4674
4675
4676
4677
4678
4679

4680
4681
4682

4683
4684
4685
4686
4687
4688
4689
4649
4650
4651
4652
4653
4654
4655

4656
4657
4658

4659
4660
4661
4662
4663
4664
4665
4666
4667

4668
4669
4670

4671
4672
4673
4674
4675
4676
4677
4678







-



-
+








-
+


-
+







 *
 * Side effects:
 *	If the segment isn't inconsistent then the function panics.
 *
 *--------------------------------------------------------------
 */

	/* ARGSUSED */
static void
CharCheckProc(
    TkTextSegment *segPtr,	/* Segment to check. */
    TkTextLine *linePtr)	/* Line containing segment. */
    TCL_UNUSED(TkTextLine *))	/* Line containing segment. */
{
    /*
     * Make sure that the segment contains the number of characters indicated
     * by its header, and that the last segment in a line ends in a newline.
     * Also make sure that there aren't ever two character segments adjacent
     * to each other: they should be merged together.
     */

    if (segPtr->size <= 0) {
    if (segPtr->size + 1 <= 1) {
	Tcl_Panic("CharCheckProc: segment has size <= 0");
    }
    if (strlen(segPtr->body.chars) != (size_t) segPtr->size) {
    if (strlen(segPtr->body.chars) != (size_t)segPtr->size) {
	Tcl_Panic("CharCheckProc: segment has wrong size");
    }
    if (segPtr->nextPtr == NULL) {
	if (segPtr->body.chars[segPtr->size-1] != '\n') {
	    Tcl_Panic("CharCheckProc: line doesn't end with newline");
	}
    } else if (segPtr->nextPtr->typePtr == &tkTextCharType) {
4854
4855
4856
4857
4858
4859
4860
4861

4862
4863
4864
4865
4866
4867
4868
4843
4844
4845
4846
4847
4848
4849

4850
4851
4852
4853
4854
4855
4856
4857







-
+







 */

static void
ToggleCheckProc(
    TkTextSegment *segPtr,	/* Segment to check. */
    TkTextLine *linePtr)	/* Line containing segment. */
{
    register Summary *summaryPtr;
    Summary *summaryPtr;
    int needSummary;

    if (segPtr->size != 0) {
	Tcl_Panic("ToggleCheckProc: segment had non-zero size");
    }
    if (!segPtr->body.toggle.inNodeCounts) {
	Tcl_Panic("ToggleCheckProc: toggle counts not updated in nodes");
Changes to generic/tkTextDisp.c.
1
2
3
4
5
6
7
8
9
10


11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

26
27

28
29



30
31
32
33
34
35
36
37
38
1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
16
17
18
19
20
21
22



23
24

25


26
27
28
29

30
31
32
33
34
35
36








-
-
+
+












-
-
-
+

-
+
-
-
+
+
+

-







/*
 * tkTextDisp.c --
 *
 *	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.
 */

#include "tkInt.h"
#include "tkText.h"

#ifdef _WIN32
#include "tkWinInt.h"
#elif defined(__CYGWIN__)
#include "tkUnixInt.h"
#endif

#ifdef MAC_OSX_TK
#elif defined(MAC_OSX_TK)
#include "tkMacOSXInt.h"
#define OK_TO_LOG (!TkpAppIsDrawing())
#define OK_TO_LOG (!TkpWillDrawWidget(textPtr->tkwin))
#define FORCE_DISPLAY(winPtr) TkpDisplayWindow(winPtr)
#else
#endif

#if !defined(MAC_OSX_TK)
#define OK_TO_LOG 1
#define FORCE_DISPLAY(winPtr)
#endif

/*
 * "Calculations of line pixel heights and the size of the vertical
 * scrollbar."
 *
 * Given that tag, font and elide changes can happen to large numbers of
169
170
171
172
173
174
175
176

177
178
179
180
181
182
183
167
168
169
170
171
172
173

174
175
176
177
178
179
180
181







-
+







/*
 * The following structure extends the StyleValues structure above with
 * graphics contexts used to actually draw the characters. The entries in
 * dInfoPtr->styleTable point to structures of this type.
 */

typedef struct TextStyle {
    int refCount;		/* Number of times this structure is
    TkSizeT refCount;		/* Number of times this structure is
				 * referenced in Chunks. */
    GC bgGC;			/* Graphics context for background. None means
				 * use widget background. */
    GC fgGC;			/* Graphics context for foreground. */
    GC ulGC;			/* Graphics context for underline. */
    GC ovGC;			/* Graphics context for overstrike. */
    StyleValues *sValuePtr;	/* Raw information from which GCs were
416
417
418
419
420
421
422
423

424
425
426
427
428
429
430
414
415
416
417
418
419
420

421
422
423
424
425
426
427
428







-
+







				 * calculations, if they are out of date. */
    TkTextIndex metricIndex;	/* If the current metric update line wraps
				 * into very many display lines, then this is
				 * used to keep track of what index we've got
				 * to so far... */
    int metricPixelHeight;	/* ...and this is for the height calculation
				 * so far...*/
    int metricEpoch;		/* ...and this for the epoch of the partial
    TkSizeT metricEpoch;		/* ...and this for the epoch of the partial
				 * calculation so it can be cancelled if
				 * things change once more. This field will be
				 * -1 if there is no long-line calculation in
				 * progress, and take a non-negative value if
				 * there is such a calculation in progress. */
    int lastMetricUpdateLine;	/* When the current update line reaches this
				 * line, we are done and should stop the
438
439
440
441
442
443
444
445

446
447
448
449
450


451
452
453
454
455
456
457
436
437
438
439
440
441
442

443
444
445
446


447
448
449
450
451
452
453
454
455







-
+



-
-
+
+







} TextDInfo;

/*
 * In TkTextDispChunk structures for character segments, the clientData field
 * points to one of the following structures:
 */

#if !TK_LAYOUT_WITH_BASE_CHUNKS
#if !defined(TK_LAYOUT_WITH_BASE_CHUNKS)

typedef struct CharInfo {
    int numBytes;		/* Number of bytes to display. */
    char chars[1];		/* UTF characters to display. Actual size will
				 * be numBytes, not 1. THIS MUST BE THE LAST
    char chars[TKFLEXARRAY];		/* UTF characters to display.
				 * Allocated as large as necessary. THIS MUST BE THE LAST
				 * FIELD IN THE STRUCTURE. */
} CharInfo;

#else /* TK_LAYOUT_WITH_BASE_CHUNKS */

typedef struct CharInfo {
    TkTextDispChunk *baseChunkPtr;
550
551
552
553
554
555
556
557

558
559
560
561
562
563
564
548
549
550
551
552
553
554

555
556
557
558
559
560
561
562







-
+







static void		CharDisplayProc(TkText *textPtr,
			    TkTextDispChunk *chunkPtr, int x, int y,
			    int height, int baseline, Display *display,
			    Drawable dst, int screenY);
static int		CharMeasureProc(TkTextDispChunk *chunkPtr, int x);
static void		CharUndisplayProc(TkText *textPtr,
			    TkTextDispChunk *chunkPtr);
#if TK_LAYOUT_WITH_BASE_CHUNKS
#ifdef TK_LAYOUT_WITH_BASE_CHUNKS
static void		FinalizeBaseChunk(TkTextDispChunk *additionalChunkPtr);
static void		FreeBaseChunk(TkTextDispChunk *baseChunkPtr);
static int		IsSameFGStyle(TextStyle *style1, TextStyle *style2);
static void		RemoveFromBaseChunk(TkTextDispChunk *chunkPtr);
#endif
/*
 * Definitions of elided procs. Compiler can't inline these since we use
656
657
658
659
660
661
662
663

664
665
666

667
668
669
670
671
672
673
654
655
656
657
658
659
660

661
662
663

664
665
666
667
668
669
670
671







-
+


-
+







 *----------------------------------------------------------------------
 */

void
TkTextCreateDInfo(
    TkText *textPtr)		/* Overall information for text widget. */
{
    register TextDInfo *dInfoPtr;
    TextDInfo *dInfoPtr;
    XGCValues gcValues;

    dInfoPtr = ckalloc(sizeof(TextDInfo));
    dInfoPtr = (TextDInfo *)ckalloc(sizeof(TextDInfo));
    Tcl_InitHashTable(&dInfoPtr->styleTable, sizeof(StyleValues)/sizeof(int));
    dInfoPtr->dLinePtr = NULL;
    dInfoPtr->copyGC = NULL;
    gcValues.graphics_exposures = True;
    dInfoPtr->scrollGC = Tk_GetGC(textPtr->tkwin, GCGraphicsExposures,
	    &gcValues);
    dInfoPtr->topOfEof = 0;
715
716
717
718
719
720
721
722

723
724
725
726
727
728
729
713
714
715
716
717
718
719

720
721
722
723
724
725
726
727







-
+







 *----------------------------------------------------------------------
 */

void
TkTextFreeDInfo(
    TkText *textPtr)		/* Overall information for text widget. */
{
    register TextDInfo *dInfoPtr = textPtr->dInfoPtr;
    TextDInfo *dInfoPtr = textPtr->dInfoPtr;

    /*
     * Be careful to free up styleTable *after* freeing up all the DLines, so
     * that the hash table is still intact to free up the style-related
     * information from the lines. Once the lines are all free then styleTable
     * will be empty.
     */
771
772
773
774
775
776
777
778

779
780
781
782
783
784
785
769
770
771
772
773
774
775

776
777
778
779
780
781
782
783







-
+







static TextStyle *
GetStyle(
    TkText *textPtr,		/* Overall information about text widget. */
    const TkTextIndex *indexPtr)/* The character in the text for which display
				 * information is wanted. */
{
    TkTextTag **tagPtrs;
    register TkTextTag *tagPtr;
    TkTextTag *tagPtr;
    StyleValues styleValues;
    TextStyle *stylePtr;
    Tcl_HashEntry *hPtr;
    int numTags, isNew, i;
    int isSelected;
    XGCValues gcValues;
    unsigned long mask;
1000
1001
1002
1003
1004
1005
1006
1007

1008
1009
1010
1011
1012
1013
1014
1015
1016

1017
1018
1019
1020
1021
1022
1023
998
999
1000
1001
1002
1003
1004

1005
1006
1007
1008
1009
1010
1011
1012
1013

1014
1015
1016
1017
1018
1019
1020
1021







-
+








-
+







    /*
     * Use an existing style if there's one around that matches.
     */

    hPtr = Tcl_CreateHashEntry(&textPtr->dInfoPtr->styleTable,
	    (char *) &styleValues, &isNew);
    if (!isNew) {
	stylePtr = Tcl_GetHashValue(hPtr);
	stylePtr = (TextStyle *)Tcl_GetHashValue(hPtr);
	stylePtr->refCount++;
	return stylePtr;
    }

    /*
     * No existing style matched. Make a new one.
     */

    stylePtr = ckalloc(sizeof(TextStyle));
    stylePtr = (TextStyle *)ckalloc(sizeof(TextStyle));
    stylePtr->refCount = 1;
    if (styleValues.border != NULL) {
	gcValues.foreground = Tk_3DBorderColor(styleValues.border)->pixel;
	mask = GCForeground;
	if (styleValues.bgStipple != None) {
	    gcValues.stipple = styleValues.bgStipple;
	    gcValues.fill_style = FillStippled;
1067
1068
1069
1070
1071
1072
1073
1074

1075
1076
1077
1078

1079
1080
1081
1082
1083
1084
1085
1065
1066
1067
1068
1069
1070
1071

1072
1073
1074


1075
1076
1077
1078
1079
1080
1081
1082







-
+


-
-
+







 *
 *----------------------------------------------------------------------
 */

static void
FreeStyle(
    TkText *textPtr,		/* Information about overall widget. */
    register TextStyle *stylePtr)
    TextStyle *stylePtr)
				/* Information about style to free. */
{
    stylePtr->refCount--;
    if (stylePtr->refCount == 0) {
    if (stylePtr->refCount-- <= 1) {
	if (stylePtr->bgGC != NULL) {
	    Tk_FreeGC(textPtr->display, stylePtr->bgGC);
	}
	if (stylePtr->fgGC != NULL) {
	    Tk_FreeGC(textPtr->display, stylePtr->fgGC);
	}
	if (stylePtr->ulGC != NULL) {
1130
1131
1132
1133
1134
1135
1136
1137

1138
1139
1140
1141
1142
1143
1144
1127
1128
1129
1130
1131
1132
1133

1134
1135
1136
1137
1138
1139
1140
1141







-
+







static DLine *
LayoutDLine(
    TkText *textPtr,		/* Overall information about text widget. */
    const TkTextIndex *indexPtr)/* Beginning of display line. May not
				 * necessarily point to a character
				 * segment. */
{
    register DLine *dlPtr;	/* New display line. */
    DLine *dlPtr;	/* New display line. */
    TkTextSegment *segPtr;	/* Current segment in text. */
    TkTextDispChunk *lastChunkPtr;
				/* Last chunk allocated so far for line. */
    TkTextDispChunk *chunkPtr;	/* Current chunk. */
    TkTextIndex curIndex;
    TkTextDispChunk *breakChunkPtr;
				/* Chunk containing best word break point, if
1176
1177
1178
1179
1180
1181
1182

1183

1184
1185
1186
1187
1188
1189
1190
1191

1192
1193
1194
1195
1196
1197
1198
1173
1174
1175
1176
1177
1178
1179
1180

1181
1182
1183
1184
1185
1186
1187
1188

1189
1190
1191
1192
1193
1194
1195
1196







+
-
+







-
+







    int tabStyle;		/* One of TABULAR or WORDPROCESSOR. */
    int tabSize;		/* Number of pixels consumed by current tab
				 * stop. */
    TkTextDispChunk *lastCharChunkPtr;
				/* Pointer to last chunk in display lines with
				 * numBytes > 0. Used to drop 0-sized chunks
				 * from the end of the line. */
    TkSizeT byteOffset;
    int byteOffset, ascent, descent, code, elide, elidesize;
    int ascent, descent, code, elide, elidesize;
    StyleValues *sValuePtr;
    TkTextElideInfo info;	/* Keep track of elide state. */

    /*
     * Create and initialize a new DLine structure.
     */

    dlPtr = ckalloc(sizeof(DLine));
    dlPtr = (DLine *)ckalloc(sizeof(DLine));
    dlPtr->index = *indexPtr;
    dlPtr->byteCount = 0;
    dlPtr->y = 0;
    dlPtr->oldY = 0;		/* Only set to avoid compiler warnings. */
    dlPtr->height = 0;
    dlPtr->baseline = 0;
    dlPtr->chunkPtr = NULL;
1216
1217
1218
1219
1220
1221
1222
1223

1224
1225
1226
1227
1228
1229
1230
1214
1215
1216
1217
1218
1219
1220

1221
1222
1223
1224
1225
1226
1227
1228







-
+







     * Special case entirely elide line as there may be 1000s or more.
     */

    elide = TkTextIsElided(textPtr, indexPtr, &info);
    if (elide && indexPtr->byteIndex == 0) {
	maxBytes = 0;
	for (segPtr = info.segPtr; segPtr != NULL; segPtr = segPtr->nextPtr) {
	    if (segPtr->size > 0) {
	    if (segPtr->size + 1 > 1) {
		if (elide == 0) {
		    /*
		     * We toggled a tag and the elide state changed to
		     * visible, and we have something of non-zero size.
		     * Therefore we must bail out.
		     */

1337
1338
1339
1340
1341
1342
1343
1344

1345
1346
1347
1348
1349
1350
1351
1335
1336
1337
1338
1339
1340
1341

1342
1343
1344
1345
1346
1347
1348
1349







-
+







     * TkTextIndexToSeg for this because it won't return a segment with zero
     * size (such as the insertion cursor's mark).
     */

  connectNextLogicalLine:
    byteOffset = curIndex.byteIndex;
    segPtr = curIndex.linePtr->segPtr;
    while ((byteOffset > 0) && (byteOffset >= segPtr->size)) {
    while ((byteOffset + 1 > 1) && (byteOffset + 1 >= segPtr->size + 1)) {
	byteOffset -= segPtr->size;
	segPtr = segPtr->nextPtr;

	if (segPtr == NULL) {
	    /*
	     * Two logical lines merged into one display line through eliding
	     * of a newline.
1365
1366
1367
1368
1369
1370
1371
1372

1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384

1385
1386
1387
1388
1389
1390
1391
1363
1364
1365
1366
1367
1368
1369

1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381

1382
1383
1384
1385
1386
1387
1388
1389







-
+











-
+








    while (segPtr != NULL) {
	/*
	 * Every logical line still gets at least one chunk due to
	 * expectations in the rest of the code, but we are able to skip
	 * elided portions of the line quickly.
	 *
	 * If current chunk is elided and last chunk was too, coalese.
	 * If current chunk is elided and last chunk was too, coalesce.
	 *
	 * This also means that each logical line which is entirely elided
	 * still gets laid out into a DLine, but with zero height. This isn't
	 * particularly a problem, but it does seem somewhat unnecessary. We
	 * may wish to redesign the code to remove these zero height DLines in
	 * the future.
	 */

	if (elide && (lastChunkPtr != NULL)
		&& (lastChunkPtr->displayProc == NULL /*ElideDisplayProc*/)) {
	    elidesize = segPtr->size - byteOffset;
	    if (elidesize > 0) {
	    if (segPtr->size + 1 > byteOffset + 1) {
		curIndex.byteIndex += elidesize;
		lastChunkPtr->numBytes += elidesize;
		breakByteOffset = lastChunkPtr->breakIndex
			= lastChunkPtr->numBytes;

		/*
		 * If have we have a tag toggle, there is a chance that
1433
1434
1435
1436
1437
1438
1439
1440

1441
1442
1443
1444
1445
1446
1447
1431
1432
1433
1434
1435
1436
1437

1438
1439
1440
1441
1442
1443
1444
1445







-
+








	if (segPtr->typePtr->layoutProc == NULL) {
	    segPtr = segPtr->nextPtr;
	    byteOffset = 0;
	    continue;
	}
	if (chunkPtr == NULL) {
	    chunkPtr = ckalloc(sizeof(TkTextDispChunk));
	    chunkPtr = (TkTextDispChunk *)ckalloc(sizeof(TkTextDispChunk));
	    chunkPtr->nextPtr = NULL;
	    chunkPtr->clientData = NULL;
	}
	chunkPtr->stylePtr = GetStyle(textPtr, &curIndex);
	elide = chunkPtr->stylePtr->sValuePtr->elide;

	/*
1506
1507
1508
1509
1510
1511
1512
1513

1514
1515
1516
1517
1518
1519
1520
1504
1505
1506
1507
1508
1509
1510

1511
1512
1513
1514
1515
1516
1517
1518







-
+







			maxBytes = (p + 1 - segPtr->body.chars) - byteOffset;
			gotTab = 1;
			break;
		    }
		}
	    }

#if TK_LAYOUT_WITH_BASE_CHUNKS
#ifdef TK_LAYOUT_WITH_BASE_CHUNKS
	    if (baseCharChunkPtr != NULL) {
		int expectedX =
			((BaseCharInfo *) baseCharChunkPtr->clientData)->width
			+ baseCharChunkPtr->x;

		if ((expectedX != x) || !IsSameFGStyle(
			baseCharChunkPtr->stylePtr, chunkPtr->stylePtr)) {
1648
1649
1650
1651
1652
1653
1654
1655

1656
1657
1658
1659
1660
1661
1662
1646
1647
1648
1649
1650
1651
1652

1653
1654
1655
1656
1657
1658
1659
1660







-
+







		    goto connectNextLogicalLine;
		}
	    }
	}

	chunkPtr = NULL;
    }
#if TK_LAYOUT_WITH_BASE_CHUNKS
#ifdef TK_LAYOUT_WITH_BASE_CHUNKS
    FinalizeBaseChunk(NULL);
#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */
    if (noCharsYet) {
	dlPtr->spaceAbove = 0;
	dlPtr->spaceBelow = 0;
	dlPtr->length = 0;

1707
1708
1709
1710
1711
1712
1713
1714

1715
1716
1717
1718
1719
1720
1721
1705
1706
1707
1708
1709
1710
1711

1712
1713
1714
1715
1716
1717
1718
1719







-
+







	    if (breakChunkPtr->undisplayProc != NULL) {
		breakChunkPtr->undisplayProc(textPtr, breakChunkPtr);
	    }
	    segPtr = TkTextIndexToSeg(&breakIndex, &byteOffset);
	    segPtr->typePtr->layoutProc(textPtr, &breakIndex, segPtr,
		    byteOffset, maxX, breakByteOffset, 0, wrapMode,
		    breakChunkPtr);
#if TK_LAYOUT_WITH_BASE_CHUNKS
#ifdef TK_LAYOUT_WITH_BASE_CHUNKS
	    FinalizeBaseChunk(NULL);
#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */
	}
	lastChunkPtr = breakChunkPtr;
	wholeLine = 0;
    }

1831
1832
1833
1834
1835
1836
1837
1838
1839


1840
1841
1842
1843
1844
1845
1846
1829
1830
1831
1832
1833
1834
1835


1836
1837
1838
1839
1840
1841
1842
1843
1844







-
-
+
+







 *----------------------------------------------------------------------
 */

static void
UpdateDisplayInfo(
    TkText *textPtr)		/* Text widget to update. */
{
    register TextDInfo *dInfoPtr = textPtr->dInfoPtr;
    register DLine *dlPtr, *prevPtr;
    TextDInfo *dInfoPtr = textPtr->dInfoPtr;
    DLine *dlPtr, *prevPtr;
    TkTextIndex index;
    TkTextLine *lastLinePtr;
    int y, maxY, xPixelOffset, maxOffset, lineHeight;

    if (!(dInfoPtr->flags & DINFO_OUT_OF_DATE)) {
	return;
    }
1869
1870
1871
1872
1873
1874
1875
1876

1877
1878
1879
1880
1881
1882
1883
1867
1868
1869
1870
1871
1872
1873

1874
1875
1876
1877
1878
1879
1880
1881







-
+







    lastLinePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree, textPtr,
	    TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr));
    dlPtr = dInfoPtr->dLinePtr;
    prevPtr = NULL;
    y = dInfoPtr->y - dInfoPtr->newTopPixelOffset;
    maxY = dInfoPtr->maxY;
    while (1) {
	register DLine *newPtr;
	DLine *newPtr;

	if (index.linePtr == lastLinePtr) {
	    break;
	}

	/*
	 * There are three possibilities right now:
1980
1981
1982
1983
1984
1985
1986
1987

1988
1989
1990
1991
1992
1993
1994
1978
1979
1980
1981
1982
1983
1984

1985
1986
1987
1988
1989
1990
1991
1992







-
+








	/*
	 * If we switched text lines, delete any DLines left for the old text
	 * line.
	 */

	if (index.linePtr != prevPtr->index.linePtr) {
	    register DLine *nextPtr;
	    DLine *nextPtr;

	    nextPtr = dlPtr;
	    while ((nextPtr != NULL)
		    && (nextPtr->index.linePtr == prevPtr->index.linePtr)) {
		nextPtr = nextPtr->nextPtr;
	    }
	    if (nextPtr != dlPtr) {
2349
2350
2351
2352
2353
2354
2355
2356

2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370


2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389

2390
2391
2392
2393
2394
2395
2396
2347
2348
2349
2350
2351
2352
2353

2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366


2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386

2387
2388
2389
2390
2391
2392
2393
2394







-
+












-
-
+
+


















-
+







 *
 *----------------------------------------------------------------------
 */

static void
FreeDLines(
    TkText *textPtr,		/* Information about overall text widget. */
    register DLine *firstPtr,	/* Pointer to first DLine to free up. */
    DLine *firstPtr,	/* Pointer to first DLine to free up. */
    DLine *lastPtr,		/* Pointer to DLine just after last one to
				 * free (NULL means everything starting with
				 * firstPtr). */
    int action)			/* DLINE_UNLINK means DLines are currently
				 * linked into the list rooted at
				 * textPtr->dInfoPtr->dLinePtr and they have
				 * to be unlinked. DLINE_FREE means just free
				 * without unlinking. DLINE_FREE_TEMP means
				 * the DLine given is just a temporary one and
				 * we shouldn't invalidate anything for the
				 * overall widget. */
{
    register TkTextDispChunk *chunkPtr, *nextChunkPtr;
    register DLine *nextDLinePtr;
    TkTextDispChunk *chunkPtr, *nextChunkPtr;
    DLine *nextDLinePtr;

    if (action == DLINE_FREE_TEMP) {
	lineHeightsRecalculated++;
	if (tkTextDebug) {
	    char string[TK_POS_CHARS];

	    /*
	     * Debugging is enabled, so keep a log of all the lines whose
	     * height was recalculated. The test suite uses this information.
	     */

	    TkTextPrintIndex(textPtr, &firstPtr->index, string);
	    LOG("tk_textHeightCalc", string);
	}
    } else if (action == DLINE_UNLINK) {
	if (textPtr->dInfoPtr->dLinePtr == firstPtr) {
	    textPtr->dInfoPtr->dLinePtr = lastPtr;
	} else {
	    register DLine *prevPtr;
	    DLine *prevPtr;

	    for (prevPtr = textPtr->dInfoPtr->dLinePtr;
		    prevPtr->nextPtr != firstPtr; prevPtr = prevPtr->nextPtr) {
		/* Empty loop body. */
	    }
	    prevPtr->nextPtr = lastPtr;
	}
2430
2431
2432
2433
2434
2435
2436
2437

2438
2439
2440
2441
2442
2443
2444

2445
2446
2447
2448
2449
2450
2451
2428
2429
2430
2431
2432
2433
2434

2435
2436
2437
2438
2439
2440
2441

2442
2443
2444
2445
2446
2447
2448
2449







-
+






-
+







 *
 *----------------------------------------------------------------------
 */

static void
DisplayDLine(
    TkText *textPtr,		/* Text widget in which to draw line. */
    register DLine *dlPtr,	/* Information about line to draw. */
    DLine *dlPtr,	/* Information about line to draw. */
    DLine *prevPtr,		/* Line just before one to draw, or NULL if
				 * dlPtr is the top line. */
    Pixmap pixmap)		/* Pixmap to use for double-buffering. Caller
				 * must make sure it's large enough to hold
				 * line. */
{
    register TkTextDispChunk *chunkPtr;
    TkTextDispChunk *chunkPtr;
    TextDInfo *dInfoPtr = textPtr->dInfoPtr;
    Display *display;
    int height, y_off;
#ifndef TK_NO_DOUBLE_BUFFERING
    const int y = 0;
#else
    const int y = dlPtr->y;
2609
2610
2611
2612
2613
2614
2615
2616

2617
2618
2619
2620
2621
2622
2623
2607
2608
2609
2610
2611
2612
2613

2614
2615
2616
2617
2618
2619
2620
2621







-
+







 *
 *--------------------------------------------------------------
 */

static void
DisplayLineBackground(
    TkText *textPtr,		/* Text widget containing line. */
    register DLine *dlPtr,	/* Information about line to draw. */
    DLine *dlPtr,	/* Information about line to draw. */
    DLine *prevPtr,		/* Line just above dlPtr, or NULL if dlPtr is
				 * the top-most line in the window. */
    Pixmap pixmap)		/* Pixmap to use for double-buffering. Caller
				 * must make sure it's large enough to hold
				 * line. Caller must also have filled it with
				 * the background color for the widget. */
{
3005
3006
3007
3008
3009
3010
3011
3012

3013
3014
3015
3016
3017
3018
3019
3003
3004
3005
3006
3007
3008
3009

3010
3011
3012
3013
3014
3015
3016
3017







-
+







 *----------------------------------------------------------------------
 */

static void
AsyncUpdateLineMetrics(
    ClientData clientData)	/* Information about widget. */
{
    register TkText *textPtr = clientData;
    TkText *textPtr = (TkText *)clientData;
    TextDInfo *dInfoPtr = textPtr->dInfoPtr;
    int lineNum;

    dInfoPtr->lineUpdateTimer = NULL;

    if ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)
            || !Tk_IsMapped(textPtr->tkwin)) {
3062
3063
3064
3065
3066
3067
3068
3069

3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087

3088
3089
3090
3091
3092
3093
3094
3060
3061
3062
3063
3064
3065
3066

3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084

3085
3086
3087
3088
3089
3090
3091
3092







-
+

















-
+







    }

    /*
     * If we're not in the middle of a long-line calculation (metricEpoch==-1)
     * and we've reached the last line, then we're done.
     */

    if (dInfoPtr->metricEpoch == -1
    if (dInfoPtr->metricEpoch == TCL_INDEX_NONE
	    && lineNum == dInfoPtr->lastMetricUpdateLine) {
	/*
	 * We have looped over all lines, so we're done. We must release our
	 * refCount on the widget (the timer token was already set to NULL
	 * above). If there is a registered aftersync command, run that first.
	 * Cancel any pending idle task which would try to run the command
	 * after the afterSyncCmd pointer had been set to NULL.
	 */

        if (textPtr->afterSyncCmd) {
            int code;
	    Tcl_CancelIdleCall(TkTextRunAfterSyncCmd, textPtr);
            Tcl_Preserve((ClientData) textPtr->interp);
            code = Tcl_EvalObjEx(textPtr->interp, textPtr->afterSyncCmd,
                    TCL_EVAL_GLOBAL);
	    if (code == TCL_ERROR) {
                Tcl_AddErrorInfo(textPtr->interp, "\n    (text sync)");
                Tcl_BackgroundError(textPtr->interp);
                Tcl_BackgroundException(textPtr->interp, TCL_ERROR);
	    }
            Tcl_Release((ClientData) textPtr->interp);
            Tcl_DecrRefCount(textPtr->afterSyncCmd);
            textPtr->afterSyncCmd = NULL;
	}

        /*
3153
3154
3155
3156
3157
3158
3159
3160

3161
3162
3163
3164
3165
3166
3167
3168
3169
3170


3171
3172
3173
3174
3175
3176
3177
3151
3152
3153
3154
3155
3156
3157

3158
3159
3160
3161
3162
3163
3164
3165
3166


3167
3168
3169
3170
3171
3172
3173
3174
3175







-
+








-
-
+
+







     * is in sync.  (That is, to run DisplayText inside of the drawRect
     * method.)  Otherwise the screen might not get updated until an event
     * like a mouse click is received.  But that extra drawing corrupts the
     * data that the test suite is trying to collect.
     */

    if (!tkTextDebug) {
	FORCE_DISPLAY(textPtr->tkwin);
	TkpRedrawWidget(textPtr->tkwin);
    }

    if (NewSyncState != OldSyncState) {
	if (NewSyncState) {
	    textPtr->dInfoPtr->flags &= ~OUT_OF_SYNC;
	} else {
	    textPtr->dInfoPtr->flags |= OUT_OF_SYNC;
	}
        TkSendVirtualEvent(textPtr->tkwin, "WidgetViewSync",
                           Tcl_NewBooleanObj(NewSyncState));
	Tk_SendVirtualEvent(textPtr->tkwin, "WidgetViewSync",
		Tcl_NewBooleanObj(NewSyncState));
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TkTextUpdateLineMetrics --
3246
3247
3248
3249
3250
3251
3252
3253


3254
3255
3256
3257
3258
3259
3260
3244
3245
3246
3247
3248
3249
3250

3251
3252
3253
3254
3255
3256
3257
3258
3259







-
+
+







	    }

	    /*
	     * If we're in the middle of a partial-line height calculation,
	     * then we can't be done.
	     */

	    if (textPtr->dInfoPtr->metricEpoch == -1 && lineNum == endLine) {
	    if (textPtr->dInfoPtr->metricEpoch == TCL_INDEX_NONE && lineNum == endLine) {


		/*
		 * We have looped over all lines, so we're done.
		 */

		break;
	    }
4162
4163
4164
4165
4166
4167
4168
4169

4170
4171

4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
















4199
4200
4201
4202
4203
4204
4205
4161
4162
4163
4164
4165
4166
4167

4168
4169

4170
4171
4172
4173
4174
4175
4176
4177












4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208







-
+

-
+







-
-
-
-
-
-
-
-
-
-
-
-








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







 *----------------------------------------------------------------------
 */

static void
DisplayText(
    ClientData clientData)	/* Information about widget. */
{
    register TkText *textPtr = clientData;
    TkText *textPtr = (TkText *)clientData;
    TextDInfo *dInfoPtr = textPtr->dInfoPtr;
    register DLine *dlPtr;
    DLine *dlPtr;
    DLine *prevPtr;
    Pixmap pixmap;
    int maxHeight, borders;
    int bottomY = 0;		/* Initialization needed only to stop compiler
				 * warnings. */
    Tcl_Interp *interp;

#ifdef MAC_OSX_TK
    /*
     * If drawing is disabled, all we need to do is
     * clear the REDRAW_PENDING flag.
     */
    TkWindow *winPtr = (TkWindow *)(textPtr->tkwin);
    MacDrawable *macWin = winPtr->privatePtr;
    if (macWin && (macWin->flags & TK_DO_NOT_DRAW)){
	dInfoPtr->flags &= ~REDRAW_PENDING;
    	return;
     }
#endif

    if ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)) {
	/*
	 * The widget has been deleted.	 Don't do anything.
	 */

	return;
    }

#ifdef MAC_OSX_TK
    /*
     * If the toplevel is being resized it would be dangerous to try redrawing
     * the widget.  But we can just clear the REDRAW_PENDING flag and return.
     * This display proc will be called again after the widget has been
     * reconfigured.
     */

    TkWindow *winPtr = (TkWindow *)(textPtr->tkwin);
    MacDrawable *macWin = winPtr->privatePtr;
    if (macWin && (macWin->flags & TK_DO_NOT_DRAW)){
	dInfoPtr->flags &= ~REDRAW_PENDING;
    	return;
     }
#endif

    interp = textPtr->interp;
    Tcl_Preserve(interp);

    if (tkTextDebug) {
	CLEAR("tk_textRelayout");
    }
4248
4249
4250
4251
4252
4253
4254
4255

4256
4257
4258
4259
4260
4261
4262
4251
4252
4253
4254
4255
4256
4257

4258
4259
4260
4261
4262
4263
4264
4265







-
+







     * scrolling (copying from other parts of the screen). We have to be
     * particularly careful with the top and bottom lines of the display,
     * since these may only be partially visible and therefore not helpful for
     * some scrolling purposes.
     */

    for (dlPtr = dInfoPtr->dLinePtr; dlPtr != NULL; dlPtr = dlPtr->nextPtr) {
	register DLine *dlPtr2;
	DLine *dlPtr2;
	int offset, height, y, oldY;
	TkRegion damageRgn;

	/*
	 * These tests are, in order:
	 *
	 * 1. If the line is already marked as invalid
4546
4547
4548
4549
4550
4551
4552
4553

4554
4555
4556
4557
4558
4559
4560
4549
4550
4551
4552
4553
4554
4555

4556
4557
4558
4559
4560
4561
4562
4563







-
+







		 * Otherwise, everything else moves, but the embedded window
		 * doesn't!
		 *
		 * So, we loop through all the chunks, calling the display
		 * proc of embedded windows only.
		 */
#endif
		register TkTextDispChunk *chunkPtr;
		TkTextDispChunk *chunkPtr;

		for (chunkPtr = dlPtr->chunkPtr; (chunkPtr != NULL);
			chunkPtr = chunkPtr->nextPtr) {
		    int x;
		    if (chunkPtr->displayProc != TkTextEmbWinDisplayProc) {
			continue;
		    }
4748
4749
4750
4751
4752
4753
4754
4755

4756
4757
4758
4759
4760
4761
4762
4751
4752
4753
4754
4755
4756
4757

4758
4759
4760
4761
4762
4763
4764
4765







-
+







 */

static void
TextInvalidateRegion(
    TkText *textPtr,		/* Widget record for text widget. */
    TkRegion region)		/* Region of area to redraw. */
{
    register DLine *dlPtr;
    DLine *dlPtr;
    TextDInfo *dInfoPtr = textPtr->dInfoPtr;
    int maxY, inset;
    XRectangle rect;

    /*
     * Find all lines that overlap the given region and mark them for
     * redisplay.
5006
5007
5008
5009
5010
5011
5012
5013

5014
5015
5016
5017
5018
5019
5020
5009
5010
5011
5012
5013
5014
5015

5016
5017
5018
5019
5020
5021
5022
5023







-
+







    TkTextIndex *index2Ptr,	/* Character just after last one to consider
				 * for redisplay. NULL means process all the
				 * characters in the text. */
    TkTextTag *tagPtr,		/* Information about tag. */
    int withTag)		/* 1 means redraw characters that have the
				 * tag, 0 means redraw those without. */
{
    register DLine *dlPtr;
    DLine *dlPtr;
    DLine *endPtr;
    int tagOn;
    TkTextSearch search;
    TextDInfo *dInfoPtr = textPtr->dInfoPtr;
    TkTextIndex *curIndexPtr;
    TkTextIndex endOfText, *endIndexPtr;

5269
5270
5271
5272
5273
5274
5275
5276

5277
5278
5279
5280
5281
5282
5283
5272
5273
5274
5275
5276
5277
5278

5279
5280
5281
5282
5283
5284
5285
5286







-
+








    if (!IsStartOfNotMergedLine(textPtr, &textPtr->topIndex)) {
	TkTextFindDisplayLineEnd(textPtr, &textPtr->topIndex, 0, NULL);
    }

    /*
     * Invalidate cached scrollbar positions, so that scrollbars sliders will
     * be udpated.
     * be updated.
     */

    dInfoPtr->xScrollFirst = dInfoPtr->xScrollLast = -1;
    dInfoPtr->yScrollFirst = dInfoPtr->yScrollLast = -1;

    if (mask & TK_TEXT_LINE_GEOMETRY) {

5346
5347
5348
5349
5350
5351
5352
5353

5354
5355
5356
5357
5358
5359
5360
5349
5350
5351
5352
5353
5354
5355

5356
5357
5358
5359
5360
5361
5362
5363







-
+







				 * line, don't nudge it up or down by a few
				 * pixels just to make sure it is entirely
				 * displayed. Positive numbers indicate the
				 * number of pixels of the index's line which
				 * are to be off the top of the screen. */
{
    TextDInfo *dInfoPtr = textPtr->dInfoPtr;
    register DLine *dlPtr;
    DLine *dlPtr;
    int bottomY, close, lineIndex;
    TkTextIndex tmpIndex, rounded;
    int lineHeight;

    /*
     * If the specified position is the extra line at the end of the text,
     * round it back to the last real line.
6155
6156
6157
6158
6159
6160
6161
6162

6163
6164
6165
6166
6167
6168
6169
6170
6171
6172
6173
6174
6175
6176
6177
6178
6179
6180
6181
6182


6183
6184
6185
6186
6187
6188
6189
6158
6159
6160
6161
6162
6163
6164

6165
6166
6167
6168
6169
6170
6171
6172
6173
6174
6175
6176
6177
6178
6179
6180
6181
6182
6183


6184
6185
6186
6187
6188
6189
6190
6191
6192







-
+


















-
-
+
+







    Tcl_Obj *const objv[])	/* Argument objects. Someone else has already
				 * parsed this command enough to know that
				 * objv[1] is "yview". */
{
    TextDInfo *dInfoPtr = textPtr->dInfoPtr;
    int pickPlace, type;
    int pixels, count;
    int switchLength;
    TkSizeT switchLength;
    double fraction;
    TkTextIndex index;

    if (dInfoPtr->flags & DINFO_OUT_OF_DATE) {
	UpdateDisplayInfo(textPtr);
    }

    if (objc == 2) {
	GetYView(interp, textPtr, 0);
	return TCL_OK;
    }

    /*
     * Next, handle the old syntax: "pathName yview ?-pickplace? where"
     */

    pickPlace = 0;
    if (Tcl_GetString(objv[2])[0] == '-') {
	register const char *switchStr =
		Tcl_GetStringFromObj(objv[2], &switchLength);
	const char *switchStr =
		TkGetStringFromObj(objv[2], &switchLength);

	if ((switchLength >= 2) && (strncmp(switchStr, "-pickplace",
		(unsigned) switchLength) == 0)) {
	    pickPlace = 1;
	    if (objc != 4) {
		Tcl_WrongNumArgs(interp, 3, objv, "lineNum|index");
		return TCL_ERROR;
6352
6353
6354
6355
6356
6357
6358
6359

6360
6361
6362
6363
6364
6365
6366
6355
6356
6357
6358
6359
6360
6361

6362
6363
6364
6365
6366
6367
6368
6369







-
+







 *	See the user documentation.
 *
 *--------------------------------------------------------------
 */

int
TkTextScanCmd(
    register TkText *textPtr,	/* Information about text widget. */
    TkText *textPtr,	/* Information about text widget. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. Someone else has already
				 * parsed this command enough to know that
				 * objv[1] is "scan". */
{
    TextDInfo *dInfoPtr = textPtr->dInfoPtr;
6521
6522
6523
6524
6525
6526
6527
6528

6529
6530
6531
6532
6533
6534
6535
6524
6525
6526
6527
6528
6529
6530

6531
6532
6533
6534
6535
6536
6537
6538







-
+







	buf2[0] = ' ';
	Tcl_PrintDouble(NULL, first, buf1+1);
	Tcl_PrintDouble(NULL, last, buf2+1);
	Tcl_DStringInit(&buf);
	Tcl_DStringAppend(&buf, textPtr->xScrollCmd, -1);
	Tcl_DStringAppend(&buf, buf1, -1);
	Tcl_DStringAppend(&buf, buf2, -1);
	code = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, 0);
	code = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, TCL_EVAL_GLOBAL);
	Tcl_DStringFree(&buf);
	if (code != TCL_OK) {
	    Tcl_AddErrorInfo(interp,
		    "\n    (horizontal scrolling command executed by text)");
	    Tcl_BackgroundException(interp, code);
	}
    }
6806
6807
6808
6809
6810
6811
6812
6813

6814
6815
6816
6817
6818
6819
6820
6809
6810
6811
6812
6813
6814
6815

6816
6817
6818
6819
6820
6821
6822
6823







-
+







	buf2[0] = ' ';
	Tcl_PrintDouble(NULL, first, buf1+1);
	Tcl_PrintDouble(NULL, last, buf2+1);
	Tcl_DStringInit(&buf);
	Tcl_DStringAppend(&buf, textPtr->yScrollCmd, -1);
	Tcl_DStringAppend(&buf, buf1, -1);
	Tcl_DStringAppend(&buf, buf2, -1);
	code = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, 0);
	code = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, TCL_EVAL_GLOBAL);
	Tcl_DStringFree(&buf);
	if (code != TCL_OK) {
	    Tcl_AddErrorInfo(interp,
		    "\n    (vertical scrolling command executed by text)");
	    Tcl_BackgroundException(interp, code);
	}
    }
6838
6839
6840
6841
6842
6843
6844
6845

6846
6847
6848
6849
6850
6851
6852
6841
6842
6843
6844
6845
6846
6847

6848
6849
6850
6851
6852
6853
6854
6855







-
+







 *----------------------------------------------------------------------
 */

static void
AsyncUpdateYScrollbar(
    ClientData clientData)	/* Information about widget. */
{
    register TkText *textPtr = clientData;
    TkText *textPtr = (TkText *)clientData;

    textPtr->dInfoPtr->scrollbarTimer = NULL;

    if (!(textPtr->flags & DESTROYED)) {
	GetYView(textPtr->interp, textPtr, 1);
    }

6873
6874
6875
6876
6877
6878
6879
6880

6881
6882
6883
6884
6885
6886
6887
6876
6877
6878
6879
6880
6881
6882

6883
6884
6885
6886
6887
6888
6889
6890







-
+







 *
 *----------------------------------------------------------------------
 */

static DLine *
FindDLine(
    TkText *textPtr,		/* Widget record for text widget. */
    register DLine *dlPtr,	/* Pointer to first in list of DLines to
    DLine *dlPtr,	/* Pointer to first in list of DLines to
				 * search. */
    const TkTextIndex *indexPtr)/* Index of desired character. */
{
    DLine *dlPtrPrev;
    TkTextIndex indexPtr2;

    if (dlPtr == NULL) {
7043
7044
7045
7046
7047
7048
7049
7050

7051
7052
7053
7054
7055
7056
7057
7046
7047
7048
7049
7050
7051
7052

7053
7054
7055
7056
7057
7058
7059
7060







-
+







				 * the character nearest to (x,y). */
    int *nearest)		/* If non-NULL then gets set to 0 if (x,y) is
				 * actually over the returned index, and 1 if
				 * it is just nearby (e.g. if x,y is on the
				 * border of the widget). */
{
    TextDInfo *dInfoPtr = textPtr->dInfoPtr;
    register DLine *dlPtr, *validDlPtr;
    DLine *dlPtr, *validDlPtr;
    int nearby = 0;

    /*
     * Make sure that all of the layout information about what's displayed
     * where on the screen is up-to-date.
     */

7145
7146
7147
7148
7149
7150
7151
7152

7153
7154
7155
7156
7157
7158
7159
7148
7149
7150
7151
7152
7153
7154

7155
7156
7157
7158
7159
7160
7161
7162







-
+







				 * line. */
    int x,			/* Pixel x coordinate of point in widget's
				 * window. */
    TkTextIndex *indexPtr)	/* This index gets filled in with the index of
				 * the character nearest to x. */
{
    TextDInfo *dInfoPtr = textPtr->dInfoPtr;
    register TkTextDispChunk *chunkPtr;
    TkTextDispChunk *chunkPtr;

    /*
     * Scan through the line's chunks to find the one that contains the
     * desired x-coordinate. Before doing this, translate the x-coordinate
     * from the coordinate system of the window to the coordinate system of
     * the line (to take account of x-scrolling).
     */
7273
7274
7275
7276
7277
7278
7279
7280

7281
7282
7283
7284
7285
7286
7287
7276
7277
7278
7279
7280
7281
7282

7283
7284
7285
7286
7287
7288
7289
7290







-
+







DlineXOfIndex(
    TkText *textPtr,		/* Widget record for text widget. */
    DLine *dlPtr,		/* Display information for this display
				 * line. */
    int byteIndex)		/* The byte index for which we want the
				 * coordinate. */
{
    register TkTextDispChunk *chunkPtr = dlPtr->chunkPtr;
    TkTextDispChunk *chunkPtr = dlPtr->chunkPtr;
    int x = 0;

    if (byteIndex == 0 || chunkPtr == NULL) {
	return x;
    }

    /*
7343
7344
7345
7346
7347
7348
7349
7350

7351
7352
7353
7354
7355
7356
7357
7346
7347
7348
7349
7350
7351
7352

7353
7354
7355
7356
7357
7358
7359
7360







-
+







    int *charWidthPtr)		/* If the 'index' is at the end of a display
				 * line and therefore takes up a very large
				 * width, this is used to return the smaller
				 * width actually desired by the index. */
{
    TextDInfo *dInfoPtr = textPtr->dInfoPtr;
    DLine *dlPtr;
    register TkTextDispChunk *chunkPtr;
    TkTextDispChunk *chunkPtr;
    int byteCount;

    /*
     * Make sure that all of the screen layout information is up to date.
     */

    if (dInfoPtr->flags & DINFO_OUT_OF_DATE) {
7535
7536
7537
7538
7539
7540
7541
7542

7543
7544

7545
7546
7547
7548
7549


7550
7551
7552
7553
7554
7555
7556
7557
7558

7559
7560
7561
7562
7563
7564
7565
7566
7567
7568
7569
7570
7571


7572
7573
7574
7575
7576
7577
7578
7538
7539
7540
7541
7542
7543
7544

7545
7546

7547
7548
7549
7550


7551
7552
7553
7554
7555
7556
7557
7558
7559
7560
7561
7562
7563
7564
7565
7566
7567
7568
7569
7570
7571
7572
7573


7574
7575
7576
7577
7578
7579
7580
7581
7582







-
+

-
+



-
-
+
+









+











-
-
+
+








/*
 * Get bounding-box information about an elided chunk.
 */

static void
ElideBboxProc(
    TkText *textPtr,
    TCL_UNUSED(TkText *),
    TkTextDispChunk *chunkPtr,	/* Chunk containing desired char. */
    int index,			/* Index of desired character within the
    TCL_UNUSED(int),		/* Index of desired character within the
				 * chunk. */
    int y,			/* Topmost pixel in area allocated for this
				 * line. */
    int lineHeight,		/* Height of line, in pixels. */
    int baseline,		/* Location of line's baseline, in pixels
    TCL_UNUSED(int),	/* Height of line, in pixels. */
    TCL_UNUSED(int),	/* Location of line's baseline, in pixels
				 * measured down from y. */
    int *xPtr, int *yPtr,	/* Gets filled in with coords of character's
				 * upper-left pixel. X-coord is in same
				 * coordinate system as chunkPtr->x. */
    int *widthPtr,		/* Gets filled in with width of character, in
				 * pixels. */
    int *heightPtr)		/* Gets filled in with height of character, in
				 * pixels. */
{

    *xPtr = chunkPtr->x;
    *yPtr = y;
    *widthPtr = *heightPtr = 0;
}

/*
 * Measure an elided chunk.
 */

static int
ElideMeasureProc(
    TkTextDispChunk *chunkPtr,	/* Chunk containing desired coord. */
    int x)			/* X-coordinate, in same coordinate system as
    TCL_UNUSED(TkTextDispChunk *),	/* Chunk containing desired coord. */
    TCL_UNUSED(int))		/* X-coordinate, in same coordinate system as
				 * chunkPtr->x. */
{
    return 0 /*chunkPtr->numBytes - 1*/;
}

/*
 *--------------------------------------------------------------
7593
7594
7595
7596
7597
7598
7599
7600
7601


7602
7603
7604

7605
7606
7607
7608

7609
7610
7611
7612
7613
7614
7615

7616
7617
7618
7619
7620
7621


7622
7623
7624
7625
7626

7627
7628
7629
7630
7631
7632
7633
7597
7598
7599
7600
7601
7602
7603


7604
7605
7606
7607

7608
7609
7610
7611

7612
7613
7614
7615
7616
7617
7618

7619
7620
7621
7622
7623
7624

7625
7626
7627
7628
7629
7630

7631
7632
7633
7634
7635
7636
7637
7638







-
-
+
+


-
+



-
+






-
+





-
+
+




-
+







 *	Memory is allocated to hold additional information about the chunk.
 *
 *--------------------------------------------------------------
 */

int
TkTextCharLayoutProc(
    TkText *textPtr,		/* Text widget being layed out. */
    TkTextIndex *indexPtr,	/* Index of first character to lay out
    TCL_UNUSED(TkText *),	/* Text widget being layed out. */
    TCL_UNUSED(TkTextIndex *),	/* Index of first character to lay out
				 * (corresponds to segPtr and offset). */
    TkTextSegment *segPtr,	/* Segment being layed out. */
    int byteOffset,		/* Byte offset within segment of first
    TkSizeT byteOffset,		/* Byte offset within segment of first
				 * character to consider. */
    int maxX,			/* Chunk must not occupy pixels at this
				 * position or higher. */
    int maxBytes,		/* Chunk must not include more than this many
    TkSizeT maxBytes,		/* Chunk must not include more than this many
				 * characters. */
    int noCharsYet,		/* Non-zero means no characters have been
				 * assigned to this display line yet. */
    TkWrapMode wrapMode,	/* How to handle line wrapping:
				 * TEXT_WRAPMODE_CHAR, TEXT_WRAPMODE_NONE, or
				 * TEXT_WRAPMODE_WORD. */
    register TkTextDispChunk *chunkPtr)
    TkTextDispChunk *chunkPtr)
				/* Structure to fill in with information about
				 * this chunk. The x field has already been
				 * set by the caller. */
{
    Tk_Font tkfont;
    int nextX, bytesThatFit, count;
    int nextX, count;
    TkSizeT bytesThatFit;
    CharInfo *ciPtr;
    char *p;
    TkTextSegment *nextPtr;
    Tk_FontMetrics fm;
#if TK_LAYOUT_WITH_BASE_CHUNKS
#ifdef TK_LAYOUT_WITH_BASE_CHUNKS
    const char *line;
    int lineOffset;
    BaseCharInfo *bciPtr;
    Tcl_DString *baseString;
#endif

    /*
7644
7645
7646
7647
7648
7649
7650
7651

7652
7653
7654
7655
7656
7657
7658
7649
7650
7651
7652
7653
7654
7655

7656
7657
7658
7659
7660
7661
7662
7663







-
+







     * characters following the characters that fit in the space we've got,
     * even if no pixel of them is visible.
     */

    p = segPtr->body.chars + byteOffset;
    tkfont = chunkPtr->stylePtr->sValuePtr->tkfont;

#if TK_LAYOUT_WITH_BASE_CHUNKS
#ifdef TK_LAYOUT_WITH_BASE_CHUNKS
    if (baseCharChunkPtr == NULL) {
	baseCharChunkPtr = chunkPtr;
	bciPtr = ckalloc(sizeof(BaseCharInfo));
	baseString = &bciPtr->baseChars;
	Tcl_DStringInit(baseString);
	bciPtr->width = 0;

7676
7677
7678
7679
7680
7681
7682
7683

7684
7685
7686
7687
7688

7689
7690
7691
7692
7693
7694
7695
7681
7682
7683
7684
7685
7686
7687

7688
7689
7690
7691
7692

7693
7694
7695
7696
7697
7698
7699
7700







-
+




-
+







	    lineOffset + maxBytes, lineOffset, -1, chunkPtr->x, maxX,
	    TK_ISOLATE_END, &nextX);
#else /* !TK_LAYOUT_WITH_BASE_CHUNKS */
    bytesThatFit = CharChunkMeasureChars(chunkPtr, p, maxBytes, 0, -1,
	    chunkPtr->x, maxX, TK_ISOLATE_END, &nextX);
#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */

    if (bytesThatFit < maxBytes) {
    if (bytesThatFit + 1 <= maxBytes) {
	if ((bytesThatFit == 0) && noCharsYet) {
	    int ch;
	    int chLen = TkUtfToUniChar(p, &ch);

#if TK_LAYOUT_WITH_BASE_CHUNKS
#ifdef TK_LAYOUT_WITH_BASE_CHUNKS
	    bytesThatFit = CharChunkMeasureChars(chunkPtr, line,
		    lineOffset+chLen, lineOffset, -1, chunkPtr->x, -1, 0,
		    &nextX);
#else /* !TK_LAYOUT_WITH_BASE_CHUNKS */
	    bytesThatFit = CharChunkMeasureChars(chunkPtr, p, chLen, 0, -1,
		    chunkPtr->x, -1, 0, &nextX);
#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */
7725
7726
7727
7728
7729
7730
7731
7732

7733
7734
7735
7736
7737
7738
7739
7730
7731
7732
7733
7734
7735
7736

7737
7738
7739
7740
7741
7742
7743
7744







-
+







	     * A newline character takes up no space, so if the previous
	     * character fits then so does the newline.
	     */

	    bytesThatFit++;
	}
	if (bytesThatFit == 0) {
#if TK_LAYOUT_WITH_BASE_CHUNKS
#ifdef TK_LAYOUT_WITH_BASE_CHUNKS
	    chunkPtr->clientData = NULL;
	    if (chunkPtr == baseCharChunkPtr) {
		baseCharChunkPtr = NULL;
		Tcl_DStringFree(baseString);
	    } else {
		Tcl_DStringSetLength(baseString,lineOffset);
	    }
7758
7759
7760
7761
7762
7763
7764
7765
7766


7767
7768

7769
7770
7771
7772
7773
7774
7775
7776

7777
7778
7779
7780
7781
7782
7783
7763
7764
7765
7766
7767
7768
7769


7770
7771
7772

7773
7774
7775
7776
7777
7778
7779
7780

7781
7782
7783
7784
7785
7786
7787
7788







-
-
+
+

-
+







-
+







    chunkPtr->numBytes = bytesThatFit;
    chunkPtr->minAscent = fm.ascent + chunkPtr->stylePtr->sValuePtr->offset;
    chunkPtr->minDescent = fm.descent - chunkPtr->stylePtr->sValuePtr->offset;
    chunkPtr->minHeight = 0;
    chunkPtr->width = nextX - chunkPtr->x;
    chunkPtr->breakIndex = -1;

#if !TK_LAYOUT_WITH_BASE_CHUNKS
    ciPtr = ckalloc((Tk_Offset(CharInfo, chars) + 1) + bytesThatFit);
#if !defined(TK_LAYOUT_WITH_BASE_CHUNKS)
    ciPtr = (CharInfo *)ckalloc(offsetof(CharInfo, chars) + 1 + bytesThatFit);
    chunkPtr->clientData = ciPtr;
    memcpy(ciPtr->chars, p, (unsigned) bytesThatFit);
    memcpy(ciPtr->chars, p, bytesThatFit);
#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */

    ciPtr->numBytes = bytesThatFit;
    if (p[bytesThatFit - 1] == '\n') {
	ciPtr->numBytes--;
    }

#if TK_LAYOUT_WITH_BASE_CHUNKS
#ifdef TK_LAYOUT_WITH_BASE_CHUNKS
    /*
     * Final update for the current base chunk data.
     */

    Tcl_DStringSetLength(baseString,lineOffset+ciPtr->numBytes);
    bciPtr->width = nextX - baseCharChunkPtr->x;

7872
7873
7874
7875
7876
7877
7878
7879

7880
7881

7882
7883
7884
7885
7886
7887
7888
7877
7878
7879
7880
7881
7882
7883

7884
7885

7886
7887
7888
7889
7890
7891
7892
7893







-
+

-
+







				 * for unlimited. */
    int flags,			/* Flags to pass to MeasureChars. */
    int *nextXPtr)		/* The function puts the newly calculated
				 * right border x-position of the span
				 * here. */
{
    Tk_Font tkfont = chunkPtr->stylePtr->sValuePtr->tkfont;
    CharInfo *ciPtr = chunkPtr->clientData;
    CharInfo *ciPtr = (CharInfo *)chunkPtr->clientData;

#if !TK_LAYOUT_WITH_BASE_CHUNKS
#if !defined(TK_LAYOUT_WITH_BASE_CHUNKS)
    if (chars == NULL) {
	chars = ciPtr->chars;
	charsLen = ciPtr->numBytes;
    }
    if (end == -1) {
	end = charsLen;
    }
7947
7948
7949
7950
7951
7952
7953
7954

7955
7956
7957
7958
7959
7960
7961

7962
7963
7964
7965

7966
7967
7968

7969
7970
7971
7972
7973

7974
7975
7976
7977
7978
7979
7980
7981
7982
7983
7984
7985

7986
7987
7988
7989
7990

7991
7992
7993
7994
7995
7996
7997
7952
7953
7954
7955
7956
7957
7958

7959
7960
7961
7962
7963
7964
7965

7966
7967
7968
7969

7970
7971
7972

7973
7974
7975
7976
7977

7978
7979
7980
7981
7982
7983
7984
7985
7986
7987
7988
7989

7990
7991
7992
7993
7994

7995
7996
7997
7998
7999
8000
8001
8002







-
+






-
+



-
+


-
+




-
+











-
+




-
+







 *	Graphics are drawn.
 *
 *--------------------------------------------------------------
 */

static void
CharDisplayProc(
    TkText *textPtr,
    TCL_UNUSED(TkText *),
    TkTextDispChunk *chunkPtr,	/* Chunk that is to be drawn. */
    int x,			/* X-position in dst at which to draw this
				 * chunk (may differ from the x-position in
				 * the chunk because of scrolling). */
    int y,			/* Y-position at which to draw this chunk in
				 * dst. */
    int height,			/* Total height of line. */
    TCL_UNUSED(int),		/* Total height of line. */
    int baseline,		/* Offset of baseline from y. */
    Display *display,		/* Display to use for drawing. */
    Drawable dst,		/* Pixmap or window in which to draw chunk. */
    int screenY)		/* Y-coordinate in text window that
    TCL_UNUSED(int))	/* Y-coordinate in text window that
				 * corresponds to y. */
{
    CharInfo *ciPtr = chunkPtr->clientData;
    CharInfo *ciPtr = (CharInfo *)chunkPtr->clientData;
    const char *string;
    TextStyle *stylePtr;
    StyleValues *sValuePtr;
    int numBytes, offsetBytes, offsetX;
#if TK_DRAW_IN_CONTEXT
#ifdef TK_DRAW_IN_CONTEXT
    BaseCharInfo *bciPtr;
#endif /* TK_DRAW_IN_CONTEXT */

    if ((x + chunkPtr->width) <= 0) {
	/*
	 * The chunk is off-screen.
	 */

	return;
    }

#if TK_DRAW_IN_CONTEXT
#ifdef TK_DRAW_IN_CONTEXT
    bciPtr = ciPtr->baseChunkPtr->clientData;
    numBytes = Tcl_DStringLength(&bciPtr->baseChars);
    string = Tcl_DStringValue(&bciPtr->baseChars);

#elif TK_LAYOUT_WITH_BASE_CHUNKS
#elif defined(TK_LAYOUT_WITH_BASE_CHUNKS)
    if (ciPtr->baseChunkPtr != chunkPtr) {
	/*
	 * Without context drawing only base chunks display their foreground.
	 */

	return;
    }
8024
8025
8026
8027
8028
8029
8030
8031

8032
8033
8034
8035
8036
8037
8038
8029
8030
8031
8032
8033
8034
8035

8036
8037
8038
8039
8040
8041
8042
8043







-
+








    /*
     * Draw the text, underline, and overstrike for this chunk.
     */

    if (!sValuePtr->elide && (numBytes > offsetBytes)
	    && (stylePtr->fgGC != NULL)) {
#if TK_DRAW_IN_CONTEXT
#ifdef TK_DRAW_IN_CONTEXT
	int start = ciPtr->baseOffset + offsetBytes;
	int len = ciPtr->numBytes - offsetBytes;
	int xDisplacement = x - chunkPtr->x;

	if ((len > 0) && (string[start + len - 1] == '\t')) {
	    len--;
	}
8109
8110
8111
8112
8113
8114
8115
8116

8117
8118
8119

8120
8121
8122

8123
8124
8125
8126
8127
8128
8129
8114
8115
8116
8117
8118
8119
8120

8121
8122
8123

8124
8125
8126

8127
8128
8129
8130
8131
8132
8133
8134







-
+


-
+


-
+







 *	Memory and other resources get freed.
 *
 *--------------------------------------------------------------
 */

static void
CharUndisplayProc(
    TkText *textPtr,		/* Overall information about text widget. */
    TCL_UNUSED(TkText *),	/* Overall information about text widget. */
    TkTextDispChunk *chunkPtr)	/* Chunk that is about to be freed. */
{
    CharInfo *ciPtr = chunkPtr->clientData;
    CharInfo *ciPtr = (CharInfo *)chunkPtr->clientData;

    if (ciPtr) {
#if TK_LAYOUT_WITH_BASE_CHUNKS
#ifdef TK_LAYOUT_WITH_BASE_CHUNKS
	if (chunkPtr == ciPtr->baseChunkPtr) {
	    /*
	     * Basechunks are undisplayed first, when DLines are freed or
	     * partially freed, so this makes sure we don't access their data
	     * any more.
	     */

8198
8199
8200
8201
8202
8203
8204
8205

8206
8207
8208
8209
8210
8211

8212
8213
8214
8215
8216
8217
8218
8219
8220
8221
8222

8223
8224
8225
8226
8227
8228
8229
8203
8204
8205
8206
8207
8208
8209

8210
8211
8212
8213
8214
8215

8216
8217
8218
8219
8220
8221
8222
8223
8224
8225
8226

8227
8228
8229
8230
8231
8232
8233
8234







-
+





-
+










-
+







 *	None.
 *
 *--------------------------------------------------------------
 */

static void
CharBboxProc(
    TkText *textPtr,
    TCL_UNUSED(TkText *),
    TkTextDispChunk *chunkPtr,	/* Chunk containing desired char. */
    int byteIndex,		/* Byte offset of desired character within the
				 * chunk. */
    int y,			/* Topmost pixel in area allocated for this
				 * line. */
    int lineHeight,		/* Height of line, in pixels. */
    TCL_UNUSED(int),	/* Height of line, in pixels. */
    int baseline,		/* Location of line's baseline, in pixels
				 * measured down from y. */
    int *xPtr, int *yPtr,	/* Gets filled in with coords of character's
				 * upper-left pixel. X-coord is in same
				 * coordinate system as chunkPtr->x. */
    int *widthPtr,		/* Gets filled in with width of character, in
				 * pixels. */
    int *heightPtr)		/* Gets filled in with height of character, in
				 * pixels. */
{
    CharInfo *ciPtr = chunkPtr->clientData;
    CharInfo *ciPtr = (CharInfo *)chunkPtr->clientData;
    int maxX;

    maxX = chunkPtr->width + chunkPtr->x;
    CharChunkMeasureChars(chunkPtr, NULL, 0, 0, byteIndex,
	    chunkPtr->x, -1, 0, xPtr);

    if (byteIndex == ciPtr->numBytes) {
8378
8379
8380
8381
8382
8383
8384
8385

8386
8387
8388
8389
8390
8391
8392
8393
8394
8395
8396
8397
8398
8399
8400
8401
8402
8403
8404
8405
8406

8407
8408
8409
8410
8411
8412
8413
8383
8384
8385
8386
8387
8388
8389

8390
8391
8392
8393
8394
8395
8396
8397
8398
8399
8400
8401
8402
8403
8404
8405
8406
8407
8408
8409
8410

8411
8412
8413
8414
8415
8416
8417
8418







-
+




















-
+







    decimalChunkPtr = NULL;
    decimal = gotDigit = 0;
    for (chunkPtr2 = chunkPtr->nextPtr; chunkPtr2 != NULL;
	    chunkPtr2 = chunkPtr2->nextPtr) {
	if (chunkPtr2->displayProc != CharDisplayProc) {
	    continue;
	}
	ciPtr = chunkPtr2->clientData;
	ciPtr = (CharInfo *)chunkPtr2->clientData;
	for (p = ciPtr->chars, i = 0; i < ciPtr->numBytes; p++, i++) {
	    if (isdigit(UCHAR(*p))) {
		gotDigit = 1;
	    } else if ((*p == '.') || (*p == ',')) {
		decimal = p-ciPtr->chars;
		decimalChunkPtr = chunkPtr2;
	    } else if (gotDigit) {
		if (decimalChunkPtr == NULL) {
		    decimal = p-ciPtr->chars;
		    decimalChunkPtr = chunkPtr2;
		}
		goto endOfNumber;
	    }
	}
    }

  endOfNumber:
    if (decimalChunkPtr != NULL) {
	int curX;

	ciPtr = decimalChunkPtr->clientData;
	ciPtr = (CharInfo *)decimalChunkPtr->clientData;
	CharChunkMeasureChars(decimalChunkPtr, NULL, 0, 0, decimal,
		decimalChunkPtr->x, -1, 0, &curX);
	desired = tabX - (curX - x);
	goto update;
    }

    /*
8670
8671
8672
8673
8674
8675
8676
8677

8678
8679
8680
8681
8682
8683
8684
8675
8676
8677
8678
8679
8680
8681

8682
8683
8684
8685
8686
8687
8688
8689







-
+







    int flags,			/* Flags to pass to Tk_MeasureChars. */
    int *nextXPtr)		/* Return x-position of terminating character
				 * here. */
{
    int curX, width, ch;
    const char *special, *end, *start;

    ch = 0;			/* lint. */
    ch = 0;
    curX = startX;
    start = source + rangeStart;
    end = start + rangeLength;
    special = start;
    while (start < end) {
	if (start >= special) {
	    /*
8697
8698
8699
8700
8701
8702
8703
8704

8705
8706
8707
8708
8709
8710
8711
8702
8703
8704
8705
8706
8707
8708

8709
8710
8711
8712
8713
8714
8715
8716







-
+







	 * Special points at the next special character (or the end of the
	 * string). Process characters between start and special.
	 */

	if ((maxX >= 0) && (curX >= maxX)) {
	    break;
	}
#if TK_DRAW_IN_CONTEXT
#ifdef TK_DRAW_IN_CONTEXT
	start += TkpMeasureCharsInContext(tkfont, source, maxBytes,
		start - source, special - start,
		maxX >= 0 ? maxX - curX : -1, flags, &width);
#else
	(void) maxBytes;
	start += Tk_MeasureChars(tkfont, start, special - start,
		maxX >= 0 ? maxX - curX : -1, flags, &width);
8772
8773
8774
8775
8776
8777
8778
8779

8780
8781
8782

8783
8784

8785
8786
8787
8788
8789
8790
8791
8792
8793
8794
8795
8796
8797
8798
8799
8800
8801
8802
8803

8804
8805
8806
8807
8808
8809
8810
8811
8812

8813




8814
8815
8816
8817
8818
8819
8820



8821
8822
8823

8824




8825
8826
8827
8828
8829
8830
8831
8832
8833

8834
8835
8836
8837
8838
8839
8840
8777
8778
8779
8780
8781
8782
8783

8784
8785
8786

8787
8788
8789
8790
8791
8792
8793
8794
8795
8796
8797
8798
8799
8800
8801
8802
8803
8804
8805
8806
8807
8808

8809
8810
8811
8812
8813
8814
8815
8816
8817

8818
8819
8820
8821
8822
8823
8824
8825
8826
8827
8828
8829
8830
8831
8832
8833
8834
8835

8836
8837
8838
8839
8840
8841
8842
8843
8844
8845
8846
8847
8848
8849

8850
8851
8852
8853
8854
8855
8856
8857







-
+


-
+


+


















-
+








-
+

+
+
+
+







+
+
+


-
+

+
+
+
+








-
+







    static const char *const subcommands[] = {
	"moveto", "scroll", NULL
    };
    enum viewSubcmds {
	VIEW_MOVETO, VIEW_SCROLL
    };
    static const char *const units[] = {
	"units", "pages", "pixels", NULL
	"pages", "pixels", "units", NULL
    };
    enum viewUnits {
	VIEW_SCROLL_UNITS, VIEW_SCROLL_PAGES, VIEW_SCROLL_PIXELS
	VIEW_SCROLL_PAGES, VIEW_SCROLL_PIXELS, VIEW_SCROLL_UNITS
    };
    int index;
    double d;

    if (Tcl_GetIndexFromObjStruct(interp, objv[2], subcommands,
	    sizeof(char *), "option", 0, &index) != TCL_OK) {
	return TKTEXT_SCROLL_ERROR;
    }

    switch ((enum viewSubcmds) index) {
    case VIEW_MOVETO:
	if (objc != 4) {
	    Tcl_WrongNumArgs(interp, 3, objv, "fraction");
	    return TKTEXT_SCROLL_ERROR;
	}
	if (Tcl_GetDoubleFromObj(interp, objv[3], dblPtr) != TCL_OK) {
	    return TKTEXT_SCROLL_ERROR;
	}
	return TKTEXT_SCROLL_MOVETO;
    case VIEW_SCROLL:
	if (objc != 5) {
	    Tcl_WrongNumArgs(interp, 3, objv, "number units|pages|pixels");
	    Tcl_WrongNumArgs(interp, 3, objv, "number pages|pixels|units");
	    return TKTEXT_SCROLL_ERROR;
	}
	if (Tcl_GetIndexFromObjStruct(interp, objv[4], units,
		sizeof(char *), "argument", 0, &index) != TCL_OK) {
	    return TKTEXT_SCROLL_ERROR;
	}
	switch ((enum viewUnits) index) {
	case VIEW_SCROLL_PAGES:
	    if (Tcl_GetIntFromObj(interp, objv[3], intPtr) != TCL_OK) {
	    if (Tcl_GetDoubleFromObj(interp, objv[3], &d) != TCL_OK) {
		return TKTEXT_SCROLL_ERROR;
	    }
	    *intPtr = (d > 0) ? ceil(d) : floor(d);
	    if (dblPtr) {
		*dblPtr = d;
	    }
	    return TKTEXT_SCROLL_PAGES;
	case VIEW_SCROLL_PIXELS:
	    if (Tk_GetPixelsFromObj(interp, textPtr->tkwin, objv[3],
		    intPtr) != TCL_OK) {
		return TKTEXT_SCROLL_ERROR;
	    }
	    if (dblPtr) {
		*dblPtr = (double)*intPtr;
	    }
	    return TKTEXT_SCROLL_PIXELS;
	case VIEW_SCROLL_UNITS:
	    if (Tcl_GetIntFromObj(interp, objv[3], intPtr) != TCL_OK) {
	    if (Tcl_GetDoubleFromObj(interp, objv[3], &d) != TCL_OK) {
		return TKTEXT_SCROLL_ERROR;
	    }
	    *intPtr = (d > 0) ? ceil(d) : floor(d);
	    if (dblPtr) {
		*dblPtr = d;
	    }
	    return TKTEXT_SCROLL_UNITS;
	}
    }
    Tcl_Panic("unexpected switch fallthrough");
    return TKTEXT_SCROLL_ERROR;
}

#if TK_LAYOUT_WITH_BASE_CHUNKS
#ifdef TK_LAYOUT_WITH_BASE_CHUNKS
/*
 *----------------------------------------------------------------------
 *
 * FinalizeBaseChunk --
 *
 *	This procedure makes sure that all the chunks of the stretch are
 *	up-to-date. It is invoked when the LayoutProc has been called for all
8857
8858
8859
8860
8861
8862
8863
8864

8865
8866
8867
8868
8869
8870
8871
8872
8873
8874
8875
8876
8877
8878

8879
8880
8881
8882
8883
8884
8885
8886
8887
8888
8889
8890
8891

8892
8893
8894
8895
8896
8897
8898
8899
8900
8901
8902
8903
8904
8905

8906
8907
8908
8909
8910
8911
8912
8874
8875
8876
8877
8878
8879
8880

8881
8882
8883
8884
8885
8886
8887
8888
8889
8890
8891
8892
8893
8894

8895
8896
8897
8898
8899
8900
8901
8902
8903
8904
8905
8906
8907

8908
8909
8910
8911
8912
8913
8914
8915
8916
8917
8918
8919
8920
8921

8922
8923
8924
8925
8926
8927
8928
8929







-
+













-
+












-
+













-
+







				 * even though it may not be in the linked
				 * list yet. Used by the LayoutProc, otherwise
				 * NULL. */
{
    const char *baseChars;
    TkTextDispChunk *chunkPtr;
    CharInfo *ciPtr;
#if TK_DRAW_IN_CONTEXT
#ifdef TK_DRAW_IN_CONTEXT
    int widthAdjust = 0;
    int newwidth;
#endif /* TK_DRAW_IN_CONTEXT */

    if (baseCharChunkPtr == NULL) {
	return;
    }

    baseChars = Tcl_DStringValue(
	    &((BaseCharInfo *) baseCharChunkPtr->clientData)->baseChars);

    for (chunkPtr = baseCharChunkPtr; chunkPtr != NULL;
	    chunkPtr = chunkPtr->nextPtr) {
#if TK_DRAW_IN_CONTEXT
#ifdef TK_DRAW_IN_CONTEXT
	chunkPtr->x += widthAdjust;
#endif /* TK_DRAW_IN_CONTEXT */

	if (chunkPtr->displayProc != CharDisplayProc) {
	    continue;
	}
	ciPtr = chunkPtr->clientData;
	if (ciPtr->baseChunkPtr != baseCharChunkPtr) {
	    break;
	}
	ciPtr->chars = baseChars + ciPtr->baseOffset;

#if TK_DRAW_IN_CONTEXT
#ifdef TK_DRAW_IN_CONTEXT
	newwidth = 0;
	CharChunkMeasureChars(chunkPtr, NULL, 0, 0, -1, 0, -1, 0, &newwidth);
	if (newwidth < chunkPtr->width) {
	    widthAdjust += newwidth - chunkPtr->width;
	    chunkPtr->width = newwidth;
	}
#endif /* TK_DRAW_IN_CONTEXT */
    }

    if (addChunkPtr != NULL) {
	ciPtr = addChunkPtr->clientData;
	ciPtr->chars = baseChars + ciPtr->baseOffset;

#if TK_DRAW_IN_CONTEXT
#ifdef TK_DRAW_IN_CONTEXT
	addChunkPtr->x += widthAdjust;
	CharChunkMeasureChars(addChunkPtr, NULL, 0, 0, -1, 0, -1, 0,
		&addChunkPtr->width);
#endif /* TK_DRAW_IN_CONTEXT */
    }

    baseCharChunkPtr = NULL;
8996
8997
8998
8999
9000
9001
9002
9003

9004
9005
9006
9007
9008
9009
9010
9011
9012
9013
9014
9015
9016
9017
9018
9019

9020
9021
9022
9023
9024
9025
9026
9013
9014
9015
9016
9017
9018
9019

9020
9021
9022
9023
9024
9025
9026
9027
9028
9029
9030
9031
9032
9033
9034
9035

9036
9037
9038
9039
9040
9041
9042
9043







-
+















-
+







    StyleValues *sv1;
    StyleValues *sv2;

    if (style1 == style2) {
	return 1;
    }

#if !TK_DRAW_IN_CONTEXT
#if !defined(TK_DRAW_IN_CONTEXT)
    if (
#ifdef MAC_OSX_TK
	    !TkMacOSXCompareColors(style1->fgGC->foreground,
		    style2->fgGC->foreground)
#else
	    style1->fgGC->foreground != style2->fgGC->foreground
#endif
	    ) {
	return 0;
    }
#endif /* !TK_DRAW_IN_CONTEXT */

    sv1 = style1->sValuePtr;
    sv2 = style2->sValuePtr;

#if TK_DRAW_IN_CONTEXT
#ifdef TK_DRAW_IN_CONTEXT
    return sv1->tkfont == sv2->tkfont && sv1->offset == sv2->offset;
#else
    return sv1->tkfont == sv2->tkfont
	    && sv1->underline == sv2->underline
	    && sv1->overstrike == sv2->overstrike
	    && sv1->elide == sv2->elide
	    && sv1->offset == sv2->offset
Changes to generic/tkTextImage.c.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15
16
17
18
19
20
21

22
23
24
25
26
27
28
1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16
17
18
19
20

21
22
23
24
25
26
27
28






-
+













-
+







/*
 * 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.
 */

#include "tkPort.h"
#include "tkText.h"

/*
 * Macro that determines the size of an embedded image segment:
 */

#define EI_SEG_SIZE \
	((unsigned) (Tk_Offset(TkTextSegment, body) + sizeof(TkTextEmbImage)))
	(offsetof(TkTextSegment, body) + sizeof(TkTextEmbImage))

/*
 * Prototypes for functions defined in this file:
 */

static TkTextSegment *	EmbImageCleanupProc(TkTextSegment *segPtr,
			    TkTextLine *linePtr);
39
40
41
42
43
44
45
46

47
48
49
50
51
52
53
39
40
41
42
43
44
45

46
47
48
49
50
51
52
53







-
+







			    TkTextLine *linePtr, int treeGone);
static void		EmbImageDisplayProc(TkText *textPtr,
			    TkTextDispChunk *chunkPtr, int x, int y,
			    int lineHeight, int baseline, Display *display,
			    Drawable dst, int screenY);
static int		EmbImageLayoutProc(TkText *textPtr,
			    TkTextIndex *indexPtr, TkTextSegment *segPtr,
			    int offset, int maxX, int maxChars,
			    TkSizeT offset, int maxX, TkSizeT maxChars,
			    int noCharsYet, TkWrapMode wrapMode,
			    TkTextDispChunk *chunkPtr);
static void		EmbImageProc(ClientData clientData, int x, int y,
			    int width, int height, int imageWidth,
			    int imageHeight);

/*
79
80
81
82
83
84
85
86

87
88
89

90
91

92
93

94
95
96

97
98
99
100
101
102
103
79
80
81
82
83
84
85

86
87
88

89
90

91
92

93
94
95

96
97
98
99
100
101
102
103







-
+


-
+

-
+

-
+


-
+








/*
 * Information used for parsing image configuration options:
 */

static const Tk_OptionSpec optionSpecs[] = {
    {TK_OPTION_STRING_TABLE, "-align", NULL, NULL,
	"center", -1, Tk_Offset(TkTextEmbImage, align),
	"center", TCL_INDEX_NONE, offsetof(TkTextEmbImage, align),
	0, alignStrings, 0},
    {TK_OPTION_PIXELS, "-padx", NULL, NULL,
	"0", -1, Tk_Offset(TkTextEmbImage, padX), 0, 0, 0},
	"0", TCL_INDEX_NONE, offsetof(TkTextEmbImage, padX), 0, 0, 0},
    {TK_OPTION_PIXELS, "-pady", NULL, NULL,
	"0", -1, Tk_Offset(TkTextEmbImage, padY), 0, 0, 0},
	"0", TCL_INDEX_NONE, offsetof(TkTextEmbImage, padY), 0, 0, 0},
    {TK_OPTION_STRING, "-image", NULL, NULL,
	NULL, -1, Tk_Offset(TkTextEmbImage, imageString),
	NULL, TCL_INDEX_NONE, offsetof(TkTextEmbImage, imageString),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_STRING, "-name", NULL, NULL,
	NULL, -1, Tk_Offset(TkTextEmbImage, imageName),
	NULL, TCL_INDEX_NONE, offsetof(TkTextEmbImage, imageName),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0}
};

/*
 *--------------------------------------------------------------
 *
113
114
115
116
117
118
119
120

121
122
123
124
125
126
127
128

129
130
131
132
133
134
135
113
114
115
116
117
118
119

120
121
122
123
124
125
126
127

128
129
130
131
132
133
134
135







-
+







-
+







 *	See the user documentation.
 *
 *--------------------------------------------------------------
 */

int
TkTextImageCmd(
    register TkText *textPtr,	/* Information about text widget. */
    TkText *textPtr,	/* Information about text widget. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. Someone else has already
				 * parsed this command enough to know that
				 * objv[1] is "image". */
{
    int idx;
    register TkTextSegment *eiPtr;
    TkTextSegment *eiPtr;
    TkTextIndex index;
    static const char *const optionStrings[] = {
	"cget", "configure", "create", "names", NULL
    };
    enum opts {
	CMD_CGET, CMD_CONF, CMD_CREATE, CMD_NAMES
    };
157
158
159
160
161
162
163
164

165
166
167
168
169
170
171
157
158
159
160
161
162
163

164
165
166
167
168
169
170
171







-
+







	if (eiPtr->typePtr != &tkTextEmbImageType) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "no embedded image at index \"%s\"",
		    Tcl_GetString(objv[3])));
	    Tcl_SetErrorCode(interp, "TK", "TEXT", "NO_IMAGE", NULL);
	    return TCL_ERROR;
	}
	objPtr = Tk_GetOptionValue(interp, (char *) &eiPtr->body.ei,
	objPtr = Tk_GetOptionValue(interp, &eiPtr->body.ei,
		eiPtr->body.ei.optionTable, objv[4], textPtr->tkwin);
	if (objPtr == NULL) {
	    return TCL_ERROR;
	} else {
	    Tcl_SetObjResult(interp, objPtr);
	    return TCL_OK;
	}
184
185
186
187
188
189
190
191

192
193
194
195
196
197
198
184
185
186
187
188
189
190

191
192
193
194
195
196
197
198







-
+







		    "no embedded image at index \"%s\"",
		    Tcl_GetString(objv[3])));
	    Tcl_SetErrorCode(interp, "TK", "TEXT", "NO_IMAGE", NULL);
	    return TCL_ERROR;
	}
	if (objc <= 5) {
	    Tcl_Obj *objPtr = Tk_GetOptionInfo(interp,
		    (char *) &eiPtr->body.ei, eiPtr->body.ei.optionTable,
		    &eiPtr->body.ei, eiPtr->body.ei.optionTable,
		    (objc == 5) ? objv[4] : NULL, textPtr->tkwin);

	    if (objPtr == NULL) {
		return TCL_ERROR;
	    } else {
		Tcl_SetObjResult(interp, objPtr);
		return TCL_OK;
238
239
240
241
242
243
244
245

246
247
248
249
250
251
252
238
239
240
241
242
243
244

245
246
247
248
249
250
251
252







-
+







		    lineIndex, 1000000, &index);
	}

	/*
	 * Create the new image segment and initialize it.
	 */

	eiPtr = ckalloc(EI_SEG_SIZE);
	eiPtr = (TkTextSegment *)ckalloc(EI_SEG_SIZE);
	eiPtr->typePtr = &tkTextEmbImageType;
	eiPtr->size = 1;
	eiPtr->body.ei.sharedTextPtr = textPtr->sharedTextPtr;
	eiPtr->body.ei.linePtr = NULL;
	eiPtr->body.ei.imageName = NULL;
	eiPtr->body.ei.imageString = NULL;
	eiPtr->body.ei.name = NULL;
283
284
285
286
287
288
289
290

291
292



293
294



295
296
297
298
299
300
301
283
284
285
286
287
288
289

290
291
292
293
294
295


296
297
298
299
300
301
302
303
304
305







-
+


+
+
+
-
-
+
+
+







	    Tcl_WrongNumArgs(interp, 3, objv, NULL);
	    return TCL_ERROR;
	}
	resultObj = Tcl_NewObj();
	for (hPtr = Tcl_FirstHashEntry(&textPtr->sharedTextPtr->imageTable,
		&search); hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
	    Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewStringObj(
		    Tcl_GetHashKey(&textPtr->sharedTextPtr->markTable, hPtr),
		    (const char *)Tcl_GetHashKey(&textPtr->sharedTextPtr->markTable, hPtr),
		    -1));
	}
	if (resultObj == NULL) {
	    return TCL_ERROR;
	} else {
	Tcl_SetObjResult(interp, resultObj);
	return TCL_OK;
	    Tcl_SetObjResult(interp, resultObj);
	    return TCL_OK;
	}
    }
    default:
	Tcl_Panic("unexpected switch fallthrough");
    }
    return TCL_ERROR;
}

333
334
335
336
337
338
339
340

341
342
343
344
345
346
347
337
338
339
340
341
342
343

344
345
346
347
348
349
350
351







-
+







    Tcl_HashSearch search;
    char *name;
    int dummy;
    int count = 0;		/* The counter for picking a unique name */
    int conflict = 0;		/* True if we have a name conflict */
    size_t len;			/* length of image name */

    if (Tk_SetOptions(textPtr->interp, (char *) &eiPtr->body.ei,
    if (Tk_SetOptions(textPtr->interp, &eiPtr->body.ei,
	    eiPtr->body.ei.optionTable,
	    objc, objv, textPtr->tkwin, NULL, NULL) != TCL_OK) {
	return TCL_ERROR;
    }

    /*
     * Create the image. Save the old image around and don't free it until
385
386
387
388
389
390
391
392

393
394
395
396
397
398
399
389
390
391
392
393
394
395

396
397
398
399
400
401
402
403







-
+







	Tcl_SetErrorCode(textPtr->interp, "TK", "TEXT", "IMAGE_CREATE_USAGE",
		NULL);
	return TCL_ERROR;
    }
    len = strlen(name);
    for (hPtr = Tcl_FirstHashEntry(&textPtr->sharedTextPtr->imageTable,
	    &search); hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
	char *haveName =
	char *haveName = (char *)
		Tcl_GetHashKey(&textPtr->sharedTextPtr->imageTable, hPtr);

	if (strncmp(name, haveName, len) == 0) {
	    int newVal = 0;

	    sscanf(haveName+len, "#%d", &newVal);
	    if (newVal > count) {
415
416
417
418
419
420
421
422

423
424
425
426
427
428
429
419
420
421
422
423
424
425

426
427
428
429
430
431
432
433







-
+







	Tcl_DStringAppend(&newName, buf, -1);
    }
    name = Tcl_DStringValue(&newName);
    hPtr = Tcl_CreateHashEntry(&textPtr->sharedTextPtr->imageTable, name,
	    &dummy);
    Tcl_SetHashValue(hPtr, eiPtr);
    Tcl_SetObjResult(textPtr->interp, Tcl_NewStringObj(name, -1));
    eiPtr->body.ei.name = ckalloc(Tcl_DStringLength(&newName) + 1);
    eiPtr->body.ei.name = (char *)ckalloc(Tcl_DStringLength(&newName) + 1);
    strcpy(eiPtr->body.ei.name, name);
    Tcl_DStringFree(&newName);

    return TCL_OK;
}

/*
440
441
442
443
444
445
446
447
448
449
450
451
452


453
454
455
456
457
458
459
444
445
446
447
448
449
450

451
452
453


454
455
456
457
458
459
460
461
462







-



-
-
+
+







 * Side effects:
 *	The embedded image is deleted, if it exists, and any resources
 *	associated with it are released.
 *
 *--------------------------------------------------------------
 */

	/* ARGSUSED */
static int
EmbImageDeleteProc(
    TkTextSegment *eiPtr,	/* Segment being deleted. */
    TkTextLine *linePtr,	/* Line containing segment. */
    int treeGone)		/* Non-zero means the entire tree is being
    TCL_UNUSED(TkTextLine *),	/* Line containing segment. */
    TCL_UNUSED(int))		/* Non-zero means the entire tree is being
				 * deleted, so everything must get cleaned
				 * up. */
{
    Tcl_HashEntry *hPtr;

    if (eiPtr->body.ei.image != NULL) {
	hPtr = Tcl_FindHashEntry(&eiPtr->body.ei.sharedTextPtr->imageTable,
523
524
525
526
527
528
529
530
531
532
533
534

535
536

537
538
539
540

541
542
543
544

545
546
547

548
549
550
551
552
553
554
526
527
528
529
530
531
532

533
534
535

536
537

538
539
540
541

542
543
544
545

546
547
548

549
550
551
552
553
554
555
556







-



-
+

-
+



-
+



-
+


-
+







 *
 * Side effects:
 *	None, except for filling in chunkPtr.
 *
 *--------------------------------------------------------------
 */

	/*ARGSUSED*/
static int
EmbImageLayoutProc(
    TkText *textPtr,		/* Text widget being layed out. */
    TkTextIndex *indexPtr,	/* Identifies first character in chunk. */
    TCL_UNUSED(TkTextIndex *),	/* Identifies first character in chunk. */
    TkTextSegment *eiPtr,	/* Segment corresponding to indexPtr. */
    int offset,			/* Offset within segPtr corresponding to
    TkSizeT offset,			/* Offset within segPtr corresponding to
				 * indexPtr (always 0). */
    int maxX,			/* Chunk must not occupy pixels at this
				 * position or higher. */
    int maxChars,		/* Chunk must not include more than this many
    TCL_UNUSED(TkSizeT),	/* Chunk must not include more than this many
				 * characters. */
    int noCharsYet,		/* Non-zero means no characters have been
				 * assigned to this line yet. */
    TkWrapMode wrapMode,	/* Wrap mode to use for line:
    TCL_UNUSED(TkWrapMode),	/* Wrap mode to use for line:
				 * TEXT_WRAPMODE_CHAR, TEXT_WRAPMODE_NONE, or
				 * TEXT_WRAPMODE_WORD. */
    register TkTextDispChunk *chunkPtr)
    TkTextDispChunk *chunkPtr)
				/* Structure to fill in with information about
				 * this chunk. The x field has already been
				 * set by the caller. */
{
    int width, height;

    if (offset != 0) {
615
616
617
618
619
620
621
622

623
624
625
626
627
628
629

630
631
632
633
634
635
636
617
618
619
620
621
622
623

624
625
626
627
628
629
630

631
632
633
634
635
636
637
638







-
+






-
+







 *
 *--------------------------------------------------------------
 */

static void
EmbImageCheckProc(
    TkTextSegment *eiPtr,	/* Segment to check. */
    TkTextLine *linePtr)	/* Line containing segment. */
    TCL_UNUSED(TkTextLine *))	/* Line containing segment. */
{
    if (eiPtr->nextPtr == NULL) {
	Tcl_Panic("EmbImageCheckProc: embedded image is last segment in line");
    }
    if (eiPtr->size != 1) {
	Tcl_Panic("EmbImageCheckProc: embedded image has size %d",
		eiPtr->size);
		(int)eiPtr->size);
    }
}

/*
 *--------------------------------------------------------------
 *
 * EmbImageDisplayProc --
656
657
658
659
660
661
662
663

664
665

666
667
668

669
670
671
672
673
674
675
658
659
660
661
662
663
664

665
666

667
668
669

670
671
672
673
674
675
676
677







-
+

-
+


-
+







				 * chunk (differs from the x-position in the
				 * chunk because of scrolling). */
    int y,			/* Top of rectangular bounding box for line:
				 * tells where to draw this chunk in dst
				 * (x-position is in the chunk itself). */
    int lineHeight,		/* Total height of line. */
    int baseline,		/* Offset of baseline from y. */
    Display *display,		/* Display to use for drawing. */
    TCL_UNUSED(Display *),	/* Display to use for drawing. */
    Drawable dst,		/* Pixmap or window in which to draw */
    int screenY)		/* Y-coordinate in text window that
    TCL_UNUSED(int))	/* Y-coordinate in text window that
				 * corresponds to y. */
{
    TkTextSegment *eiPtr = chunkPtr->clientData;
    TkTextSegment *eiPtr = (TkTextSegment *)chunkPtr->clientData;
    int lineX, imageX, imageY, width, height;
    Tk_Image image;

    image = eiPtr->body.ei.image;
    if (image == NULL) {
	return;
    }
709
710
711
712
713
714
715
716

717
718

719
720
721
722
723
724
725
726
727
728
729
730
731
732

733
734
735
736
737
738
739
711
712
713
714
715
716
717

718
719

720
721
722
723
724
725
726
727
728
729
730
731
732
733

734
735
736
737
738
739
740
741







-
+

-
+













-
+







 *	None.
 *
 *--------------------------------------------------------------
 */

static void
EmbImageBboxProc(
    TkText *textPtr,
    TCL_UNUSED(TkText *),
    TkTextDispChunk *chunkPtr,	/* Chunk containing desired char. */
    int index,			/* Index of desired character within the
    TCL_UNUSED(int),			/* Index of desired character within the
				 * chunk. */
    int y,			/* Topmost pixel in area allocated for this
				 * line. */
    int lineHeight,		/* Total height of line. */
    int baseline,		/* Location of line's baseline, in pixels
				 * measured down from y. */
    int *xPtr, int *yPtr,	/* Gets filled in with coords of character's
				 * upper-left pixel. */
    int *widthPtr,		/* Gets filled in with width of image, in
				 * pixels. */
    int *heightPtr)		/* Gets filled in with height of image, in
				 * pixels. */
{
    TkTextSegment *eiPtr = chunkPtr->clientData;
    TkTextSegment *eiPtr = (TkTextSegment *)chunkPtr->clientData;
    Tk_Image image;

    image = eiPtr->body.ei.image;
    if (image != NULL) {
	Tk_SizeOfImage(image, widthPtr, heightPtr);
    } else {
	*widthPtr = 0;
790
791
792
793
794
795
796
797

798
799
800
801
802
803
804
792
793
794
795
796
797
798

799
800
801
802
803
804
805
806







-
+







	return 0;
    }

    hPtr = Tcl_FindHashEntry(&textPtr->sharedTextPtr->imageTable, name);
    if (hPtr == NULL) {
	return 0;
    }
    eiPtr = Tcl_GetHashValue(hPtr);
    eiPtr = (TkTextSegment *)Tcl_GetHashValue(hPtr);
    indexPtr->tree = textPtr->sharedTextPtr->tree;
    indexPtr->linePtr = eiPtr->body.ei.linePtr;
    indexPtr->byteIndex = TkTextSegToOffset(eiPtr, indexPtr->linePtr);
    return 1;
}

/*
817
818
819
820
821
822
823
824

825

826

827

828


829
830
831

832
833
834
835
836
837
838
819
820
821
822
823
824
825

826
827
828

829
830
831

832
833
834
835

836
837
838
839
840
841
842
843







-
+

+
-
+

+
-
+
+


-
+







 *
 *--------------------------------------------------------------
 */

static void
EmbImageProc(
    ClientData clientData,	/* Pointer to widget record. */
    int x, int y,		/* Upper left pixel (within image) that must
    TCL_UNUSED(int),		/* Upper left pixel (within image) that must
				 * be redisplayed. */
    TCL_UNUSED(int),
    int width, int height,	/* Dimensions of area to redisplay (may be
    TCL_UNUSED(int),	/* Dimensions of area to redisplay (may be
				 * <= 0). */
    TCL_UNUSED(int),
    int imgWidth, int imgHeight)/* New dimensions of image. */
    TCL_UNUSED(int),/* New dimensions of image. */
    TCL_UNUSED(int))

{
    TkTextSegment *eiPtr = clientData;
    TkTextSegment *eiPtr = (TkTextSegment *)clientData;
    TkTextIndex index;

    index.tree = eiPtr->body.ei.sharedTextPtr->tree;
    index.linePtr = eiPtr->body.ei.linePtr;
    index.byteIndex = TkTextSegToOffset(eiPtr, eiPtr->body.ei.linePtr);
    TkTextChanged(eiPtr->body.ei.sharedTextPtr, NULL, &index, &index);

Changes to generic/tkTextIndex.c.
1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
16



17
18
19
20
21
22
23
1
2
3
4
5
6


7
8
9
10
11
12
13



14
15
16
17
18
19
20
21
22
23






-
-
+
+





-
-
-
+
+
+







/*
 * 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.
 */

#include "default.h"
#include "tkInt.h"
#include "tkText.h"
#include "tkInt.h"
#include "tkText.h"
#include "default.h"

/*
 * Index to use to select last character in line (very large integer):
 */

#define LAST_CHAR 1000000

58
59
60
61
62
63
64
65

66
67

68
69
70
71
72
73
74
58
59
60
61
62
63
64

65
66

67
68
69
70
71
72
73
74







-
+

-
+







 */

#define GET_TEXTINDEX(objPtr) \
	((TkTextIndex *) (objPtr)->internalRep.twoPtrValue.ptr1)
#define GET_INDEXEPOCH(objPtr) \
	(PTR2INT((objPtr)->internalRep.twoPtrValue.ptr2))
#define SET_TEXTINDEX(objPtr, indexPtr) \
	((objPtr)->internalRep.twoPtrValue.ptr1 = (void *) (indexPtr))
	((objPtr)->internalRep.twoPtrValue.ptr1 = (void *)(indexPtr))
#define SET_INDEXEPOCH(objPtr, epoch) \
	((objPtr)->internalRep.twoPtrValue.ptr2 = INT2PTR(epoch))
	((objPtr)->internalRep.twoPtrValue.ptr2 = (void *) (size_t) (epoch))

/*
 * Define the 'textindex' object type, which Tk uses to represent indices in
 * text widgets internally.
 */

const Tcl_ObjType tkTextIndexType = {
100
101
102
103
104
105
106
107

108
109
110

111
112
113
114
115
116
117
100
101
102
103
104
105
106

107
108
109

110
111
112
113
114
115
116
117







-
+


-
+







}

static void
DupTextIndexInternalRep(
    Tcl_Obj *srcPtr,		/* TextIndex obj with internal rep to copy. */
    Tcl_Obj *copyPtr)		/* TextIndex obj with internal rep to set. */
{
    int epoch;
    TkSizeT epoch;
    TkTextIndex *dupIndexPtr, *indexPtr;

    dupIndexPtr = ckalloc(sizeof(TkTextIndex));
    dupIndexPtr = (TkTextIndex *)ckalloc(sizeof(TkTextIndex));
    indexPtr = GET_TEXTINDEX(srcPtr);
    epoch = GET_INDEXEPOCH(srcPtr);

    dupIndexPtr->tree = indexPtr->tree;
    dupIndexPtr->linePtr = indexPtr->linePtr;
    dupIndexPtr->byteIndex = indexPtr->byteIndex;
    dupIndexPtr->textPtr = indexPtr->textPtr;
135
136
137
138
139
140
141
142

143
144
145
146
147
148
149
135
136
137
138
139
140
141

142
143
144
145
146
147
148
149







-
+







{
    char buffer[TK_POS_CHARS];
    size_t len;
    const TkTextIndex *indexPtr = GET_TEXTINDEX(objPtr);

    len = TkTextPrintIndex(indexPtr->textPtr, indexPtr, buffer);

    objPtr->bytes = ckalloc(len + 1);
    objPtr->bytes = (char *)ckalloc(len + 1);
    strcpy(objPtr->bytes, buffer);
    objPtr->length = len;
}

/*
 *---------------------------------------------------------------------------
 *
172
173
174
175
176
177
178
179

180
181
182
183
184
185
186
172
173
174
175
176
177
178

179
180
181
182
183
184
185
186







-
+







static TkTextIndex *
MakeObjIndex(
    TkText *textPtr,		/* Information about text widget. */
    Tcl_Obj *objPtr,		/* Object containing description of
				 * position. */
    const TkTextIndex *origPtr)	/* Pointer to index. */
{
    TkTextIndex *indexPtr = ckalloc(sizeof(TkTextIndex));
    TkTextIndex *indexPtr = (TkTextIndex *)ckalloc(sizeof(TkTextIndex));

    indexPtr->tree = origPtr->tree;
    indexPtr->linePtr = origPtr->linePtr;
    indexPtr->byteIndex = origPtr->byteIndex;
    SET_TEXTINDEX(objPtr, indexPtr);
    objPtr->typePtr = &tkTextIndexType;
    indexPtr->textPtr = textPtr;
202
203
204
205
206
207
208
209

210
211
212
213
214
215
216
202
203
204
205
206
207
208

209
210
211
212
213
214
215
216







-
+







				 * position. */
{
    TkTextIndex index;
    TkTextIndex *indexPtr = NULL;
    int cache;

    if (objPtr->typePtr == &tkTextIndexType) {
	int epoch;
	TkSizeT epoch;

	indexPtr = GET_TEXTINDEX(objPtr);
	epoch = GET_INDEXEPOCH(objPtr);

	if (epoch == textPtr->sharedTextPtr->stateEpoch) {
	    if (indexPtr->textPtr == textPtr) {
		return indexPtr;
421
422
423
424
425
426
427
428

429
430
431
432
433
434
435
436
437
438
439

440
441
442
443
444
445
446
421
422
423
424
425
426
427

428
429
430
431
432
433
434
435
436
437
438

439
440
441
442
443
444
445
446







-
+










-
+







	     * character on the line is guaranteed to be a '\n', we can back
	     * up a constant sizeof(char) bytes.
	     */

	    indexPtr->byteIndex = index - sizeof(char);
	    break;
	}
	if (index + segPtr->size > byteIndex) {
	if (index + (int)segPtr->size > byteIndex) {
	    indexPtr->byteIndex = byteIndex;
	    if ((byteIndex > index) && (segPtr->typePtr == &tkTextCharType)) {
		/*
		 * Prevent UTF-8 character from being split up by ensuring
		 * that byteIndex falls on a character boundary. If the index
		 * 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 = Tcl_UtfPrev(start, segPtr->body.chars);
		p = TkUtfPrev(start, segPtr->body.chars);
		p += TkUtfToUniChar(p, &ch);
		indexPtr->byteIndex += p - start;
	    }
	    break;
	}
	index += segPtr->size;
    }
473
474
475
476
477
478
479
480

481
482
483
484
485
486
487
473
474
475
476
477
478
479

480
481
482
483
484
485
486
487







-
+







				 * to. */
    TkText *textPtr,
    int lineIndex,		/* Index of desired line (0 means first line
				 * of text). */
    int charIndex,		/* Index of desired character. */
    TkTextIndex *indexPtr)	/* Structure to fill in. */
{
    register TkTextSegment *segPtr;
    TkTextSegment *segPtr;
    char *p, *start, *end;
    int index, offset;
    int ch;

    indexPtr->tree = tree;
    if (lineIndex < 0) {
	lineIndex = 0;
527
528
529
530
531
532
533
534

535
536
537
538
539
540
541
527
528
529
530
531
532
533

534
535
536
537
538
539
540
541







-
+







		    return indexPtr;
		}
		charIndex--;
		offset = TkUtfToUniChar(p, &ch);
		index += offset;
	    }
	} else {
	    if (charIndex < segPtr->size) {
	    if (charIndex < (int)segPtr->size) {
		indexPtr->byteIndex = index;
		break;
	    }
	    charIndex -= segPtr->size;
	    index += segPtr->size;
	}
    }
561
562
563
564
565
566
567
568

569
570
571
572

573
574
575
576
577
578
579
561
562
563
564
565
566
567

568
569
570
571

572
573
574
575
576
577
578
579







-
+



-
+







 *
 *---------------------------------------------------------------------------
 */

TkTextSegment *
TkTextIndexToSeg(
    const TkTextIndex *indexPtr,/* Text index. */
    int *offsetPtr)		/* Where to store offset within segment, or
    TkSizeT *offsetPtr)		/* Where to store offset within segment, or
				 * NULL if offset isn't wanted. */
{
    TkTextSegment *segPtr;
    int offset;
    TkSizeT offset;

    for (offset = indexPtr->byteIndex, segPtr = indexPtr->linePtr->segPtr;
	    offset >= segPtr->size;
	    offset -= segPtr->size, segPtr = segPtr->nextPtr) {
	/* Empty loop body. */
    }
    if (offsetPtr != NULL) {
812
813
814
815
816
817
818
819

820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835

836
837
838
839
840
841
842
812
813
814
815
816
817
818

819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834

835
836
837
838
839
840
841
842







-
+















-
+








	    tagPtr = textPtr->selTagPtr;
	} else {
	    *p = 0;
	    hPtr = Tcl_FindHashEntry(&sharedPtr->tagTable, tagName);
	    *p = '.';
	    if (hPtr != NULL) {
		tagPtr = Tcl_GetHashValue(hPtr);
		tagPtr = (TkTextTag *)Tcl_GetHashValue(hPtr);
	    }
	}

	if (tagPtr == NULL) {
	    goto tryxy;
	}

	TkTextMakeByteIndex(sharedPtr->tree, textPtr, 0, 0, &first);
	TkTextMakeByteIndex(sharedPtr->tree, textPtr,
		TkBTreeNumLines(sharedPtr->tree, textPtr), 0, &last);
	TkBTreeStartSearch(&first, &last, tagPtr, &search);
	if (!TkBTreeCharTagged(&first, tagPtr) && !TkBTreeNextTag(&search)) {
	    if (tagPtr == textPtr->selTagPtr) {
		tagName = "sel";
	    } else if (hPtr != NULL) {
		tagName = Tcl_GetHashKey(&sharedPtr->tagTable, hPtr);
		tagName = (const char *)Tcl_GetHashKey(&sharedPtr->tagTable, hPtr);
	    }
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "text doesn't contain any characters tagged with \"%s\"",
		    tagName));
	    Tcl_SetErrorCode(interp, "TK", "LOOKUP", "TEXT_INDEX", tagName,
		    NULL);
	    Tcl_DStringFree(&copy);
919
920
921
922
923
924
925
926

927
928
929
930
931
932
933
919
920
921
922
923
924
925

926
927
928
929
930
931
932
933







-
+







	*endOfBase = c;
	if (result != 0) {
	    goto gotBase;
	}
    }
    if ((string[0] == 'e')
	    && (strncmp(string, "end",
	    (size_t) (endOfBase-Tcl_DStringValue(&copy))) == 0)) {
	    endOfBase-Tcl_DStringValue(&copy)) == 0)) {
	/*
	 * Base position is end of text.
	 */

	TkTextMakeByteIndex(sharedPtr->tree, textPtr,
		TkBTreeNumLines(sharedPtr->tree, textPtr), 0, indexPtr);
	canCache = 1;
1020
1021
1022
1023
1024
1025
1026
1027

1028
1029
1030
1031
1032
1033
1034
1020
1021
1022
1023
1024
1025
1026

1027
1028
1029
1030
1031
1032
1033
1034







-
+







 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

int
TkSizeT
TkTextPrintIndex(
    const TkText *textPtr,
    const TkTextIndex *indexPtr,/* Pointer to index. */
    char *string)		/* Place to store the position. Must have at
				 * least TK_POS_CHARS characters. */
{
    TkTextSegment *segPtr;
1045
1046
1047
1048
1049
1050
1051
1052

1053
1054
1055
1056
1057
1058
1059
1045
1046
1047
1048
1049
1050
1051

1052
1053
1054
1055
1056
1057
1058
1059







-
+







	     * Two logical lines merged into one display line through eliding
	     * of a newline.
	     */

	    linePtr = TkBTreeNextLine(NULL, linePtr);
	    segPtr = linePtr->segPtr;
	}
	if (numBytes <= segPtr->size) {
	if (numBytes <= (int)segPtr->size) {
	    break;
	}
	if (segPtr->typePtr == &tkTextCharType) {
	    charIndex += Tcl_NumUtfChars(segPtr->body.chars, segPtr->size);
	} else {
	    charIndex += segPtr->size;
	}
1147
1148
1149
1150
1151
1152
1153
1154

1155
1156
1157
1158
1159
1160
1161
1147
1148
1149
1150
1151
1152
1153

1154
1155
1156
1157
1158
1159
1160
1161







-
+







ForwBack(
    TkText *textPtr,		/* Information about text widget. */
    const char *string,		/* String to parse for additional info about
				 * modifier (count and units). Points to "+"
				 * or "-" that starts modifier. */
    TkTextIndex *indexPtr)	/* Index to update as specified in string. */
{
    register const char *p, *units;
    const char *p, *units;
    char *end;
    int count, lineIndex, modifier;
    size_t length;

    /*
     * Get the count (how many units forward or backward).
     */
1484
1485
1486
1487
1488
1489
1490
1491

1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502

1503
1504
1505
1506
1507
1508
1509
1484
1485
1486
1487
1488
1489
1490

1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501

1502
1503
1504
1505
1506
1507
1508
1509







-
+










-
+







				 * be negative. */
    TkTextIndex *dstPtr,	/* Destination index: gets modified. */
    TkTextCountType type)	/* The type of item to count */
{
    TkTextLine *linePtr;
    TkTextSegment *segPtr;
    TkTextElideInfo *infoPtr = NULL;
    int byteOffset;
    TkSizeT byteOffset;
    char *start, *end, *p;
    int ch;
    int elide = 0;
    int checkElided = (type & COUNT_DISPLAY);

    if (charCount < 0) {
	TkTextIndexBackChars(textPtr, srcPtr, -charCount, dstPtr, type);
	return;
    }
    if (checkElided) {
	infoPtr = ckalloc(sizeof(TkTextElideInfo));
	infoPtr = (TkTextElideInfo *)ckalloc(sizeof(TkTextElideInfo));
	elide = TkTextIsElided(textPtr, srcPtr, infoPtr);
    }

    *dstPtr = *srcPtr;

    /*
     * Find seg that contains src byteIndex. Move forward specified number of
1593
1594
1595
1596
1597
1598
1599
1600

1601
1602
1603
1604
1605
1606
1607
1593
1594
1595
1596
1597
1598
1599

1600
1601
1602
1603
1604
1605
1606
1607







-
+







			if (charCount == 0) {
			    dstPtr->byteIndex += (p - start);
			    goto forwardCharDone;
			}
			charCount--;
		    }
		} else if (type & COUNT_INDICES) {
		    if (charCount < segPtr->size - byteOffset) {
		    if (charCount + byteOffset < segPtr->size) {
			dstPtr->byteIndex += charCount;
			goto forwardCharDone;
		    }
		    charCount -= segPtr->size - byteOffset;
		}
	    }

1672
1673
1674
1675
1676
1677
1678
1679

1680
1681
1682
1683
1684
1685
1686
1672
1673
1674
1675
1676
1677
1678

1679
1680
1681
1682
1683
1684
1685
1686







-
+







    const TkTextIndex *indexPtr1,
				/* Index describing location of character from
				 * which to count. */
    const TkTextIndex *indexPtr2)
				/* Index describing location of last character
				 * at which to stop the count. */
{
    int byteCount, offset;
    TkSizeT byteCount, offset;
    TkTextSegment *segPtr, *segPtr1;
    TkTextLine *linePtr;

    if (indexPtr1->linePtr == indexPtr2->linePtr) {
        return indexPtr2->byteIndex - indexPtr1->byteIndex;
    }

1749
1750
1751
1752
1753
1754
1755
1756


1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770

1771
1772
1773
1774
1775
1776
1777
1749
1750
1751
1752
1753
1754
1755

1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770

1771
1772
1773
1774
1775
1776
1777
1778







-
+
+













-
+







				/* Index describing location of last character
				 * at which to stop the count. */
    TkTextCountType type)	/* The kind of indices to count. */
{
    TkTextLine *linePtr1;
    TkTextSegment *segPtr, *seg2Ptr = NULL;
    TkTextElideInfo *infoPtr = NULL;
    int byteOffset, maxBytes, count = 0, elide = 0;
    TkSizeT byteOffset, maxBytes, count = 0;
    int elide = 0;
    int checkElided = (type & COUNT_DISPLAY);

    /*
     * Find seg that contains src index, and remember how many bytes not to
     * count in the given segment.
     */

    segPtr = TkTextIndexToSeg(indexPtr1, &byteOffset);
    linePtr1 = indexPtr1->linePtr;

    seg2Ptr = TkTextIndexToSeg(indexPtr2, &maxBytes);

    if (checkElided) {
	infoPtr = ckalloc(sizeof(TkTextElideInfo));
	infoPtr = (TkTextElideInfo *)ckalloc(sizeof(TkTextElideInfo));
	elide = TkTextIsElided(textPtr, indexPtr1, infoPtr);
    }

    while (1) {
	/*
	 * Go through each segment in line adding up the number of characters.
	 */
1839
1840
1841
1842
1843
1844
1845
1846
1847


1848
1849

1850
1851
1852

1853
1854
1855
1856
1857
1858
1859
1840
1841
1842
1843
1844
1845
1846


1847
1848
1849

1850
1851
1852

1853
1854
1855
1856
1857
1858
1859
1860







-
-
+
+

-
+


-
+







		    }
		    byteOffset = 0;
		    continue;
		}
	    }

	    if (segPtr->typePtr == &tkTextCharType) {
		int byteLen = segPtr->size - byteOffset;
		register unsigned char *str = (unsigned char *)
		TkSizeT byteLen = segPtr->size - byteOffset;
		unsigned char *str = (unsigned char *)
			segPtr->body.chars + byteOffset;
		register int i;
		TkSizeT i;

		if (segPtr == seg2Ptr) {
		    if (byteLen > (maxBytes - byteOffset)) {
		    if (byteLen + byteOffset > maxBytes) {
			byteLen = maxBytes - byteOffset;
		    }
		}
		i = byteLen;

		/*
		 * This is a speed sensitive function, so run specially over
1872
1873
1874
1875
1876
1877
1878
1879

1880
1881
1882

1883
1884
1885
1886
1887
1888
1889
1873
1874
1875
1876
1877
1878
1879

1880
1881
1882

1883
1884
1885
1886
1887
1888
1889
1890







-
+


-
+







		count += byteLen - i;
		if (i) {
		    count += Tcl_NumUtfChars(segPtr->body.chars + byteOffset
			    + (byteLen - i), i);
		}
	    } else {
		if (type & COUNT_INDICES) {
		    int byteLen = segPtr->size - byteOffset;
		    TkSizeT byteLen = segPtr->size - byteOffset;

		    if (segPtr == seg2Ptr) {
			if (byteLen > (maxBytes - byteOffset)) {
			if (byteLen + byteOffset > maxBytes) {
			    byteLen = maxBytes - byteOffset;
			}
		    }
		    count += byteLen;
		}
	    }
	    if (segPtr == seg2Ptr) {
2021
2022
2023
2024
2025
2026
2027
2028

2029
2030
2031
2032
2033
2034
2035
2022
2023
2024
2025
2026
2027
2028

2029
2030
2031
2032
2033
2034
2035
2036







-
+







    int checkElided = (type & COUNT_DISPLAY);

    if (charCount < 0) {
	TkTextIndexForwChars(textPtr, srcPtr, -charCount, dstPtr, type);
	return;
    }
    if (checkElided) {
	infoPtr = ckalloc(sizeof(TkTextElideInfo));
	infoPtr = (TkTextElideInfo *)ckalloc(sizeof(TkTextElideInfo));
	elide = TkTextIsElided(textPtr, srcPtr, infoPtr);
    }

    *dstPtr = *srcPtr;

    /*
     * Find offset within seg that contains byteIndex. Move backward specified
2051
2052
2053
2054
2055
2056
2057
2058

2059
2060
2061
2062
2063
2064
2065
2052
2053
2054
2055
2056
2057
2058

2059
2060
2061
2062
2063
2064
2065
2066







-
+







		 * Two logical lines merged into one display line through
		 * eliding of a newline.
		 */

		linePtr = TkBTreeNextLine(NULL, linePtr);
		segPtr = linePtr->segPtr;
	    }
	    if (segSize <= segPtr->size) {
	    if (segSize <= (int)segPtr->size) {
		break;
	    }
	    segSize -= segPtr->size;
	}
    }

    /*
2121
2122
2123
2124
2125
2126
2127
2128

2129
2130
2131
2132
2133
2134
2135
2122
2123
2124
2125
2126
2127
2128

2129
2130
2131
2132
2133
2134
2135
2136







-
+







	    }
	}

	if (!elide) {
	    if (segPtr->typePtr == &tkTextCharType) {
		start = segPtr->body.chars;
		end = segPtr->body.chars + segSize;
		for (p = end; ; p = Tcl_UtfPrev(p, start)) {
		for (p = end; ; p = TkUtfPrev(p, start)) {
		    if (charCount == 0) {
			dstPtr->byteIndex -= (end - p);
			goto backwardCharDone;
		    }
		    if (p == start) {
			break;
		    }
2221
2222
2223
2224
2225
2226
2227
2228

2229
2230
2231
2232
2233
2234
2235
2222
2223
2224
2225
2226
2227
2228

2229
2230
2231
2232
2233
2234
2235
2236







-
+







    const char *string,		/* String to parse for additional info about
				 * modifier (count and units). Points to first
				 * character of modifier word. */
    TkTextIndex *indexPtr)	/* Index to modify based on string. */
{
    const char *p;
    size_t length;
    register TkTextSegment *segPtr;
    TkTextSegment *segPtr;
    int modifier;

    /*
     * Find the end of the modifier word.
     */

    for (p = string; isalnum(UCHAR(*p)); p++) {
2292
2293
2294
2295
2296
2297
2298
2299

2300
2301
2302
2303
2304
2305
2306
2293
2294
2295
2296
2297
2298
2299

2300
2301
2302
2303
2304
2305
2306
2307







-
+







	    TkTextFindDisplayLineEnd(textPtr, indexPtr, 0, NULL);
	} else {
	    indexPtr->byteIndex = 0;
	}
    } else if ((*string == 'w') && (strncmp(string, "wordend", length) == 0)
	    && (length >= 5)) {
	int firstChar = 1;
	int offset;
	TkSizeT offset;

	/*
	 * If the current character isn't part of a word then just move
	 * forward one character. Otherwise move forward until finding a
	 * character that isn't part of a word and stop there.
	 */

2335
2336
2337
2338
2339
2340
2341
2342

2343
2344
2345
2346
2347
2348
2349
2336
2337
2338
2339
2340
2341
2342

2343
2344
2345
2346
2347
2348
2349
2350







-
+







		TkTextIndexForwChars(NULL, indexPtr, 1, indexPtr,
			COUNT_INDICES);
	    }
	}
    } else if ((*string == 'w') && (strncmp(string, "wordstart", length) == 0)
	    && (length >= 5)) {
	int firstChar = 1;
	int offset;
	TkSizeT offset;

	if (modifier == TKINDEX_DISPLAY) {
	    TkTextIndexForwChars(textPtr, indexPtr, 0, indexPtr,
		    COUNT_DISPLAY_INDICES);
	}

	/*
2360
2361
2362
2363
2364
2365
2366
2367

2368
2369

2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386

2387
2388
2389
2390
2391
2392
2393
2361
2362
2363
2364
2365
2366
2367

2368
2369

2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386

2387
2388
2389
2390
2391
2392
2393
2394







-
+

-
+
















-
+







	    if (segPtr->typePtr == &tkTextCharType) {

		int ch;
		TkUtfToUniChar(segPtr->body.chars + offset, &ch);
		if (!Tcl_UniCharIsWordChar(ch)) {
		    break;
		}
		if (offset > 0) {
		if (offset + 1 > 1) {
		    chSize = (segPtr->body.chars + offset
			    - Tcl_UtfPrev(segPtr->body.chars + offset,
			    - TkUtfPrev(segPtr->body.chars + offset,
			    segPtr->body.chars));
		}
		firstChar = 0;
	    }
            if (offset == 0) {
                if (modifier == TKINDEX_DISPLAY) {
                    TkTextIndexBackChars(textPtr, indexPtr, 1, indexPtr,
                        COUNT_DISPLAY_INDICES);
                } else {
                    TkTextIndexBackChars(NULL, indexPtr, 1, indexPtr,
                        COUNT_INDICES);
                }
            } else {
                indexPtr->byteIndex -= chSize;
            }
            offset -= chSize;
	    if (offset < 0) {
	    if ((int)offset < 0) {
		if (indexPtr->byteIndex == 0) {
		    goto done;
		}
		segPtr = TkTextIndexToSeg(indexPtr, &offset);
	    }
	}

Changes to generic/tkTextMark.c.
1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
16
17
18
19
20
21
22
23


24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40


41
42
43
44
45
46
47
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15
16
17
18
19
20
21


22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38


39
40
41
42
43
44
45
46
47






-
-
+
+













-
-
+
+















-
-
+
+







/*
 * 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.
 */

#include "tkInt.h"
#include "tkText.h"
#include "tk3d.h"

/*
 * Macro that determines the size of a mark segment:
 */

#define MSEG_SIZE ((unsigned) (Tk_Offset(TkTextSegment, body) \
	+ sizeof(TkTextMark)))
#define MSEG_SIZE (offsetof(TkTextSegment, body) \
	+ sizeof(TkTextMark))

/*
 * Forward references for functions defined in this file:
 */

static Tcl_Obj *	GetMarkName(TkText *textPtr, TkTextSegment *segPtr);
static void		InsertUndisplayProc(TkText *textPtr,
			    TkTextDispChunk *chunkPtr);
static int		MarkDeleteProc(TkTextSegment *segPtr,
			    TkTextLine *linePtr, int treeGone);
static TkTextSegment *	MarkCleanupProc(TkTextSegment *segPtr,
			    TkTextLine *linePtr);
static void		MarkCheckProc(TkTextSegment *segPtr,
			    TkTextLine *linePtr);
static int		MarkLayoutProc(TkText *textPtr, TkTextIndex *indexPtr,
			    TkTextSegment *segPtr, int offset, int maxX,
			    int maxChars, int noCharsYet, TkWrapMode wrapMode,
			    TkTextSegment *segPtr, TkSizeT offset, int maxX,
			    TkSizeT maxChars, int noCharsYet, TkWrapMode wrapMode,
			    TkTextDispChunk *chunkPtr);
static int		MarkFindNext(Tcl_Interp *interp,
			    TkText *textPtr, Tcl_Obj *markName);
static int		MarkFindPrev(Tcl_Interp *interp,
			    TkText *textPtr, Tcl_Obj *markName);


89
90
91
92
93
94
95
96

97
98
99
100
101
102
103
89
90
91
92
93
94
95

96
97
98
99
100
101
102
103







-
+







 *	See the user documentation.
 *
 *--------------------------------------------------------------
 */

int
TkTextMarkCmd(
    register TkText *textPtr,	/* Information about text widget. */
    TkText *textPtr,	/* Information about text widget. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. Someone else has already
				 * parsed this command enough to know that
				 * objv[1] is "mark". */
{
    Tcl_HashEntry *hPtr;
122
123
124
125
126
127
128
129

130
131
132
133
134
135
136

137
138
139
140
141
142
143
144
145
146
147
148
149
150

151
152
153
154
155
156
157
158
159
160
161
162
163

164
165

166
167
168

169
170
171
172
173
174
175
122
123
124
125
126
127
128

129
130
131
132
133
134
135

136
137
138
139
140
141
142
143
144
145
146
147
148
149

150
151
152
153
154
155
156
157
158
159
160
161
162

163
164

165
166
167

168
169
170
171
172
173
174
175







-
+






-
+













-
+












-
+

-
+


-
+







	    sizeof(char *), "mark option", 0, &optionIndex) != TCL_OK) {
	return TCL_ERROR;
    }

    switch ((enum markOptions) optionIndex) {
    case MARK_GRAVITY: {
	char c;
	int length;
	TkSizeT length;
	const char *str;

	if (objc < 4 || objc > 5) {
	    Tcl_WrongNumArgs(interp, 3, objv, "markName ?gravity?");
	    return TCL_ERROR;
	}
	str = Tcl_GetStringFromObj(objv[3], &length);
	str = TkGetStringFromObj(objv[3], &length);
	if (length == 6 && !strcmp(str, "insert")) {
	    markPtr = textPtr->insertMarkPtr;
	} else if (length == 7 && !strcmp(str, "current")) {
	    markPtr = textPtr->currentMarkPtr;
	} else {
	    hPtr = Tcl_FindHashEntry(&textPtr->sharedTextPtr->markTable, str);
	    if (hPtr == NULL) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"there is no mark named \"%s\"", str));
		Tcl_SetErrorCode(interp, "TK", "LOOKUP", "TEXT_MARK", str,
			NULL);
		return TCL_ERROR;
	    }
	    markPtr = Tcl_GetHashValue(hPtr);
	    markPtr = (TkTextSegment *)Tcl_GetHashValue(hPtr);
	}
	if (objc == 4) {
	    const char *typeStr;

	    if (markPtr->typePtr == &tkTextRightMarkType) {
		typeStr = "right";
	    } else {
		typeStr = "left";
	    }
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(typeStr, -1));
	    return TCL_OK;
	}
	str = Tcl_GetStringFromObj(objv[4],&length);
	str = TkGetStringFromObj(objv[4],&length);
	c = str[0];
	if ((c == 'l') && (strncmp(str, "left", (unsigned) length) == 0)) {
	if ((c == 'l') && (strncmp(str, "left", length) == 0)) {
	    newTypePtr = &tkTextLeftMarkType;
	} else if ((c == 'r') &&
		(strncmp(str, "right", (unsigned) length) == 0)) {
		(strncmp(str, "right", length) == 0)) {
	    newTypePtr = &tkTextRightMarkType;
	} else {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "bad mark gravity \"%s\": must be left or right", str));
	    Tcl_SetErrorCode(interp, "TK", "VALUE", "MARK_GRAVITY", NULL);
	    return TCL_ERROR;
	}
190
191
192
193
194
195
196
197

198
199
200
201
202
203
204
190
191
192
193
194
195
196

197
198
199
200
201
202
203
204







-
+







	Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewStringObj(
		"insert", -1));
	Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewStringObj(
		"current", -1));
	for (hPtr = Tcl_FirstHashEntry(&textPtr->sharedTextPtr->markTable,
		&search); hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
	    Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewStringObj(
		    Tcl_GetHashKey(&textPtr->sharedTextPtr->markTable, hPtr),
		    (const char *)Tcl_GetHashKey(&textPtr->sharedTextPtr->markTable, hPtr),
		    -1));
	}
	Tcl_SetObjResult(interp, resultObj);
	break;
    }
    case MARK_NEXT:
	if (objc != 4) {
225
226
227
228
229
230
231
232

233
234
235
236
237
238
239
225
226
227
228
229
230
231

232
233
234
235
236
237
238
239







-
+







    case MARK_UNSET: {
	int i;

	for (i = 3; i < objc; i++) {
	    hPtr = Tcl_FindHashEntry(&textPtr->sharedTextPtr->markTable,
		    Tcl_GetString(objv[i]));
	    if (hPtr != NULL) {
		markPtr = Tcl_GetHashValue(hPtr);
		markPtr = (TkTextSegment *)Tcl_GetHashValue(hPtr);

		/*
		 * Special case not needed with peer widgets.
		 */

		if ((markPtr == textPtr->insertMarkPtr)
			|| (markPtr == textPtr->currentMarkPtr)) {
286
287
288
289
290
291
292
293

294
295
296
297
298
299
300
286
287
288
289
290
291
292

293
294
295
296
297
298
299
300







-
+







	widgetSpecific = 2;
	markPtr = textPtr->currentMarkPtr;
	isNew = (markPtr == NULL ? 1 : 0);
    } else {
	widgetSpecific = 0;
	hPtr = Tcl_CreateHashEntry(&textPtr->sharedTextPtr->markTable, name,
		&isNew);
	markPtr = Tcl_GetHashValue(hPtr);
	markPtr = (TkTextSegment *)Tcl_GetHashValue(hPtr);
    }
    if (!isNew) {
	/*
	 * If this is the insertion point that's being moved, be sure to force
	 * a display update at the old position. Also, don't let the insertion
	 * cursor be after the final newline of the file.
	 */
326
327
328
329
330
331
332
333

334
335
336
337
338
339
340
326
327
328
329
330
331
332

333
334
335
336
337
338
339
340







-
+







		TkTextIndexBackChars(NULL,indexPtr, 1, &insertIndex,
			COUNT_INDICES);
		indexPtr = &insertIndex;
	    }
	}
	TkBTreeUnlinkSegment(markPtr, markPtr->body.mark.linePtr);
    } else {
	markPtr = ckalloc(MSEG_SIZE);
	markPtr = (TkTextSegment *)ckalloc(MSEG_SIZE);
	markPtr->typePtr = &tkTextRightMarkType;
	markPtr->size = 0;
	markPtr->body.mark.textPtr = textPtr;
	markPtr->body.mark.linePtr = indexPtr->linePtr;
	markPtr->body.mark.hPtr = hPtr;
	if (widgetSpecific == 0) {
	    Tcl_SetHashValue(hPtr, markPtr);
448
449
450
451
452
453
454
455

456
457
458
459
460
461
462
448
449
450
451
452
453
454

455
456
457
458
459
460
461
462







-
+







    } else {
	Tcl_HashEntry *hPtr =
		Tcl_FindHashEntry(&textPtr->sharedTextPtr->markTable, name);

	if (hPtr == NULL) {
	    return TCL_ERROR;
	}
	segPtr = Tcl_GetHashValue(hPtr);
	segPtr = (TkTextSegment *)Tcl_GetHashValue(hPtr);
    }
    TkTextMarkSegToIndex(textPtr, segPtr, indexPtr);

    /* 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).
495
496
497
498
499
500
501
502
503
504
505
506
507



508
509
510
511
512
513
514
495
496
497
498
499
500
501

502
503



504
505
506
507
508
509
510
511
512
513







-


-
-
-
+
+
+







 * Side effects:
 *	None (even if the whole tree is being deleted we don't free up the
 *	mark; it will be done elsewhere).
 *
 *--------------------------------------------------------------
 */

	/* ARGSUSED */
static int
MarkDeleteProc(
    TkTextSegment *segPtr,	/* Segment being deleted. */
    TkTextLine *linePtr,	/* Line containing segment. */
    int treeGone)		/* Non-zero means the entire tree is being
    TCL_UNUSED(TkTextSegment *),	/* Segment being deleted. */
    TCL_UNUSED(TkTextLine *),	/* Line containing segment. */
    TCL_UNUSED(int))		/* Non-zero means the entire tree is being
				 * deleted, so everything must get cleaned
				 * up. */
{
    return 1;
}

/*
555
556
557
558
559
560
561
562

563
564

565
566

567
568

569
570

571
572
573


574
575
576
577
578
579
580
554
555
556
557
558
559
560

561
562

563
564

565
566

567
568

569
570


571
572
573
574
575
576
577
578
579







-
+

-
+

-
+

-
+

-
+

-
-
+
+







 *
 *--------------------------------------------------------------
 */

static int
MarkLayoutProc(
    TkText *textPtr,		/* Text widget being layed out. */
    TkTextIndex *indexPtr,	/* Identifies first character in chunk. */
    TCL_UNUSED(TkTextIndex *),	/* Identifies first character in chunk. */
    TkTextSegment *segPtr,	/* Segment corresponding to indexPtr. */
    int offset,			/* Offset within segPtr corresponding to
    TCL_UNUSED(TkSizeT),		/* Offset within segPtr corresponding to
				 * indexPtr (always 0). */
    int maxX,			/* Chunk must not occupy pixels at this
    TCL_UNUSED(int),			/* Chunk must not occupy pixels at this
				 * position or higher. */
    int maxChars,		/* Chunk must not include more than this many
    TCL_UNUSED(TkSizeT),		/* Chunk must not include more than this many
				 * characters. */
    int noCharsYet,		/* Non-zero means no characters have been
    TCL_UNUSED(int),		/* Non-zero means no characters have been
				 * assigned to this line yet. */
    TkWrapMode wrapMode,	/* Not used. */
    register TkTextDispChunk *chunkPtr)
    TCL_UNUSED(TkWrapMode),	/* Not used. */
    TkTextDispChunk *chunkPtr)
				/* Structure to fill in with information about
				 * this chunk. The x field has already been
				 * set by the caller. */
{
    if (segPtr != textPtr->insertMarkPtr) {
	return -1;
    }
611
612
613
614
615
616
617
618
619
620
621
622

623
624
625
626
627
628
629
630


631
632
633
634
635
636
637
610
611
612
613
614
615
616

617
618
619

620
621
622
623
624
625
626


627
628
629
630
631
632
633
634
635







-



-
+






-
-
+
+







 *
 * Side effects:
 *	Graphics are drawn.
 *
 *--------------------------------------------------------------
 */

	/* ARGSUSED */
void
TkTextInsertDisplayProc(
    TkText *textPtr,		/* The current text widget. */
    TkTextDispChunk *chunkPtr,	/* Chunk that is to be drawn. */
    TCL_UNUSED(TkTextDispChunk *),	/* Chunk that is to be drawn. */
    int x,			/* X-position in dst at which to draw this
				 * chunk (may differ from the x-position in
				 * the chunk because of scrolling). */
    int y,			/* Y-position at which to draw this chunk in
				 * dst (x-position is in the chunk itself). */
    int height,			/* Total height of line. */
    int baseline,		/* Offset of baseline from y. */
    Display *display,		/* Display to use for drawing. */
    TCL_UNUSED(int),		/* Offset of baseline from y. */
    TCL_UNUSED(Display *),		/* Display to use for drawing. */
    Drawable dst,		/* Pixmap or window in which to draw chunk. */
    int screenY)		/* Y-coordinate in text window that
				 * corresponds to y. */
{
    /*
     * We have no need for the clientData.
     */
717
718
719
720
721
722
723
724
725
726
727
728


729
730
731
732
733
734
735
715
716
717
718
719
720
721

722
723


724
725
726
727
728
729
730
731
732







-


-
-
+
+







 *
 * Side effects:
 *	None.
 *
 *--------------------------------------------------------------
 */

	/* ARGSUSED */
static void
InsertUndisplayProc(
    TkText *textPtr,		/* Overall information about text widget. */
    TkTextDispChunk *chunkPtr)	/* Chunk that is about to be freed. */
    TCL_UNUSED(TkText *),		/* Overall information about text widget. */
    TCL_UNUSED(TkTextDispChunk *))	/* Chunk that is about to be freed. */
{
    return;
}

/*
 *--------------------------------------------------------------
 *
805
806
807
808
809
810
811
812

813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833

834
835
836
837
838
839
840
802
803
804
805
806
807
808

809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829

830
831
832
833
834
835
836
837







-
+




















-
+







MarkFindNext(
    Tcl_Interp *interp,		/* For error reporting */
    TkText *textPtr,		/* The widget */
    Tcl_Obj *obj)			/* The starting index or mark name */
{
    TkTextIndex index;
    Tcl_HashEntry *hPtr;
    register TkTextSegment *segPtr;
    TkTextSegment *segPtr;
    int offset;
    const char *string = Tcl_GetString(obj);

    if (!strcmp(string, "insert")) {
	segPtr = textPtr->insertMarkPtr;
	TkTextMarkSegToIndex(textPtr, segPtr, &index);
	segPtr = segPtr->nextPtr;
    } else if (!strcmp(string, "current")) {
	segPtr = textPtr->currentMarkPtr;
	TkTextMarkSegToIndex(textPtr, segPtr, &index);
	segPtr = segPtr->nextPtr;
    } else {
	hPtr = Tcl_FindHashEntry(&textPtr->sharedTextPtr->markTable, string);
	if (hPtr != NULL) {
	    /*
	     * If given a mark name, return the next mark in the list of
	     * segments, even if it happens to be at the same character
	     * position.
	     */

	    segPtr = Tcl_GetHashValue(hPtr);
	    segPtr = (TkTextSegment *)Tcl_GetHashValue(hPtr);
	    TkTextMarkSegToIndex(textPtr, segPtr, &index);
	    segPtr = segPtr->nextPtr;
	} else {
	    /*
	     * For non-mark name indices we want to return any marks that are
	     * right at the index.
	     */
896
897
898
899
900
901
902
903

904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922

923
924
925
926
927
928
929
893
894
895
896
897
898
899

900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918

919
920
921
922
923
924
925
926







-
+


















-
+







MarkFindPrev(
    Tcl_Interp *interp,		/* For error reporting */
    TkText *textPtr,		/* The widget */
    Tcl_Obj *obj)			/* The starting index or mark name */
{
    TkTextIndex index;
    Tcl_HashEntry *hPtr;
    register TkTextSegment *segPtr, *seg2Ptr, *prevPtr;
    TkTextSegment *segPtr, *seg2Ptr, *prevPtr;
    int offset;
    const char *string = Tcl_GetString(obj);

    if (!strcmp(string, "insert")) {
	segPtr = textPtr->insertMarkPtr;
	TkTextMarkSegToIndex(textPtr, segPtr, &index);
    } else if (!strcmp(string, "current")) {
	segPtr = textPtr->currentMarkPtr;
	TkTextMarkSegToIndex(textPtr, segPtr, &index);
    } else {
	hPtr = Tcl_FindHashEntry(&textPtr->sharedTextPtr->markTable, string);
	if (hPtr != NULL) {
	    /*
	     * If given a mark name, return the previous mark in the list of
	     * segments, even if it happens to be at the same character
	     * position.
	     */

	    segPtr = Tcl_GetHashValue(hPtr);
	    segPtr = (TkTextSegment *)Tcl_GetHashValue(hPtr);
	    TkTextMarkSegToIndex(textPtr, segPtr, &index);
	} else {
	    /*
	     * For non-mark name indices we do not return any marks that are
	     * right at the index.
	     */

1008
1009
1010
1011
1012
1013
1014
1015

1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1005
1006
1007
1008
1009
1010
1011

1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024







-
+












	 * current marks for textPtr having already been tested above, the
	 * current segment is an insert or current mark from a peer of
	 * textPtr, which we don't want to return.
	 */

	return NULL;
    } else {
	markName = Tcl_GetHashKey(&textPtr->sharedTextPtr->markTable,
	markName = (const char *)Tcl_GetHashKey(&textPtr->sharedTextPtr->markTable,
		segPtr->body.mark.hPtr);
    }
    return Tcl_NewStringObj(markName, -1);
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Changes to generic/tkTextTag.c.
1
2
3
4
5
6
7
8
9


10
11
12
13
14
15
16
17



18
19
20
21
22
23
24
1
2
3
4
5
6
7


8
9
10
11
12
13
14



15
16
17
18
19
20
21
22
23
24







-
-
+
+





-
-
-
+
+
+







/*
 * tkTextTag.c --
 *
 *	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.
 */

#include "default.h"
#include "tkInt.h"
#include "tkText.h"
#include "tkInt.h"
#include "tkText.h"
#include "default.h"

/*
 * The 'TkWrapMode' enum in tkText.h is used to define a type for the -wrap
 * option of tags in a Text widget. These values are used as indices into the
 * string table below. Tags are allowed an empty wrap value, but the widget as
 * a whole is not.
 */
36
37
38
39
40
41
42
43

44
45

46
47

48
49
50

51
52
53

54
55

56
57

58
59

60
61

62
63

64
65

66
67

68
69

70
71
72

73
74
75

76
77

78
79

80
81

82
83

84
85

86
87

88
89

90
91

92
93

94
95
96

97
98
99

100
101
102

103
104
105
106
107
108
109
36
37
38
39
40
41
42

43
44

45
46

47
48
49

50
51
52

53
54

55
56

57
58

59
60

61
62

63
64

65
66

67
68

69
70
71

72
73
74

75
76

77
78

79
80

81
82

83
84

85
86

87
88

89
90

91
92

93
94
95

96
97
98

99
100
101

102
103
104
105
106
107
108
109







-
+

-
+

-
+


-
+


-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+


-
+


-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+


-
+


-
+


-
+








static const char *const tabStyleStrings[] = {
    "tabular", "wordprocessor", "", NULL
};

static const Tk_OptionSpec tagOptionSpecs[] = {
    {TK_OPTION_BORDER, "-background", NULL, NULL,
	NULL, -1, Tk_Offset(TkTextTag, border), TK_OPTION_NULL_OK, 0, 0},
	NULL, TCL_INDEX_NONE, offsetof(TkTextTag, border), TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_BITMAP, "-bgstipple", NULL, NULL,
	NULL, -1, Tk_Offset(TkTextTag, bgStipple), TK_OPTION_NULL_OK, 0, 0},
	NULL, TCL_INDEX_NONE, offsetof(TkTextTag, bgStipple), TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_PIXELS, "-borderwidth", NULL, NULL,
	NULL, Tk_Offset(TkTextTag, borderWidthPtr), Tk_Offset(TkTextTag, borderWidth),
	NULL, offsetof(TkTextTag, borderWidthPtr), offsetof(TkTextTag, borderWidth),
	TK_OPTION_NULL_OK|TK_OPTION_DONT_SET_DEFAULT, 0, 0},
    {TK_OPTION_STRING, "-elide", NULL, NULL,
	NULL, -1, Tk_Offset(TkTextTag, elideString),
	NULL, TCL_INDEX_NONE, offsetof(TkTextTag, elideString),
	TK_OPTION_NULL_OK|TK_OPTION_DONT_SET_DEFAULT, 0, 0},
    {TK_OPTION_BITMAP, "-fgstipple", NULL, NULL,
	NULL, -1, Tk_Offset(TkTextTag, fgStipple), TK_OPTION_NULL_OK, 0, 0},
	NULL, TCL_INDEX_NONE, offsetof(TkTextTag, fgStipple), TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_FONT, "-font", NULL, NULL,
	NULL, -1, Tk_Offset(TkTextTag, tkfont), TK_OPTION_NULL_OK, 0, 0},
	NULL, TCL_INDEX_NONE, offsetof(TkTextTag, tkfont), TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_COLOR, "-foreground", NULL, NULL,
	NULL, -1, Tk_Offset(TkTextTag, fgColor), TK_OPTION_NULL_OK, 0, 0},
	NULL, TCL_INDEX_NONE, offsetof(TkTextTag, fgColor), TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_STRING, "-justify", NULL, NULL,
	NULL, -1, Tk_Offset(TkTextTag, justifyString), TK_OPTION_NULL_OK, 0,0},
	NULL, TCL_INDEX_NONE, offsetof(TkTextTag, justifyString), TK_OPTION_NULL_OK, 0,0},
    {TK_OPTION_STRING, "-lmargin1", NULL, NULL,
	NULL, -1, Tk_Offset(TkTextTag, lMargin1String), TK_OPTION_NULL_OK,0,0},
	NULL, TCL_INDEX_NONE, offsetof(TkTextTag, lMargin1String), TK_OPTION_NULL_OK,0,0},
    {TK_OPTION_STRING, "-lmargin2", NULL, NULL,
	NULL, -1, Tk_Offset(TkTextTag, lMargin2String), TK_OPTION_NULL_OK,0,0},
	NULL, TCL_INDEX_NONE, offsetof(TkTextTag, lMargin2String), TK_OPTION_NULL_OK,0,0},
    {TK_OPTION_BORDER, "-lmargincolor", NULL, NULL,
	NULL, -1, Tk_Offset(TkTextTag, lMarginColor), TK_OPTION_NULL_OK, 0, 0},
	NULL, TCL_INDEX_NONE, offsetof(TkTextTag, lMarginColor), TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_STRING, "-offset", NULL, NULL,
	NULL, -1, Tk_Offset(TkTextTag, offsetString), TK_OPTION_NULL_OK, 0, 0},
	NULL, TCL_INDEX_NONE, offsetof(TkTextTag, offsetString), TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_STRING, "-overstrike", NULL, NULL,
	NULL, -1, Tk_Offset(TkTextTag, overstrikeString),
	NULL, TCL_INDEX_NONE, offsetof(TkTextTag, overstrikeString),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_COLOR, "-overstrikefg", NULL, NULL,
	NULL, -1, Tk_Offset(TkTextTag, overstrikeColor),
	NULL, TCL_INDEX_NONE, offsetof(TkTextTag, overstrikeColor),
        TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_STRING, "-relief", NULL, NULL,
	NULL, -1, Tk_Offset(TkTextTag, reliefString), TK_OPTION_NULL_OK, 0, 0},
	NULL, TCL_INDEX_NONE, offsetof(TkTextTag, reliefString), TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_STRING, "-rmargin", NULL, NULL,
	NULL, -1, Tk_Offset(TkTextTag, rMarginString), TK_OPTION_NULL_OK, 0,0},
	NULL, TCL_INDEX_NONE, offsetof(TkTextTag, rMarginString), TK_OPTION_NULL_OK, 0,0},
    {TK_OPTION_BORDER, "-rmargincolor", NULL, NULL,
	NULL, -1, Tk_Offset(TkTextTag, rMarginColor), TK_OPTION_NULL_OK, 0, 0},
	NULL, TCL_INDEX_NONE, offsetof(TkTextTag, rMarginColor), TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_BORDER, "-selectbackground", NULL, NULL,
	NULL, -1, Tk_Offset(TkTextTag, selBorder), TK_OPTION_NULL_OK, 0, 0},
	NULL, TCL_INDEX_NONE, offsetof(TkTextTag, selBorder), TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_COLOR, "-selectforeground", NULL, NULL,
	NULL, -1, Tk_Offset(TkTextTag, selFgColor), TK_OPTION_NULL_OK, 0, 0},
	NULL, TCL_INDEX_NONE, offsetof(TkTextTag, selFgColor), TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_STRING, "-spacing1", NULL, NULL,
	NULL, -1, Tk_Offset(TkTextTag, spacing1String), TK_OPTION_NULL_OK,0,0},
	NULL, TCL_INDEX_NONE, offsetof(TkTextTag, spacing1String), TK_OPTION_NULL_OK,0,0},
    {TK_OPTION_STRING, "-spacing2", NULL, NULL,
	NULL, -1, Tk_Offset(TkTextTag, spacing2String), TK_OPTION_NULL_OK,0,0},
	NULL, TCL_INDEX_NONE, offsetof(TkTextTag, spacing2String), TK_OPTION_NULL_OK,0,0},
    {TK_OPTION_STRING, "-spacing3", NULL, NULL,
	NULL, -1, Tk_Offset(TkTextTag, spacing3String), TK_OPTION_NULL_OK,0,0},
	NULL, TCL_INDEX_NONE, offsetof(TkTextTag, spacing3String), TK_OPTION_NULL_OK,0,0},
    {TK_OPTION_STRING, "-tabs", NULL, NULL,
	NULL, Tk_Offset(TkTextTag, tabStringPtr), -1, TK_OPTION_NULL_OK, 0, 0},
	NULL, offsetof(TkTextTag, tabStringPtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_STRING_TABLE, "-tabstyle", NULL, NULL,
	NULL, -1, Tk_Offset(TkTextTag, tabStyle),
	NULL, TCL_INDEX_NONE, offsetof(TkTextTag, tabStyle),
	TK_OPTION_NULL_OK, tabStyleStrings, 0},
    {TK_OPTION_STRING, "-underline", NULL, NULL,
	NULL, -1, Tk_Offset(TkTextTag, underlineString),
	NULL, TCL_INDEX_NONE, offsetof(TkTextTag, underlineString),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_COLOR, "-underlinefg", NULL, NULL,
	NULL, -1, Tk_Offset(TkTextTag, underlineColor),
	NULL, TCL_INDEX_NONE, offsetof(TkTextTag, underlineColor),
        TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_STRING_TABLE, "-wrap", NULL, NULL,
	NULL, -1, Tk_Offset(TkTextTag, wrapMode),
	NULL, TCL_INDEX_NONE, offsetof(TkTextTag, wrapMode),
	TK_OPTION_NULL_OK, wrapStrings, 0},
    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0}
};

/*
 * Forward declarations for functions defined later in this file:
 */
133
134
135
136
137
138
139
140

141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157

158
159
160
161
162
163
164
133
134
135
136
137
138
139

140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156

157
158
159
160
161
162
163
164







-
+
















-
+







 *	See the user documentation.
 *
 *--------------------------------------------------------------
 */

int
TkTextTagCmd(
    register TkText *textPtr,	/* Information about text widget. */
    TkText *textPtr,	/* Information about text widget. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. Someone else has already
				 * parsed this command enough to know that
				 * objv[1] is "tag". */
{
    static const char *const tagOptionStrings[] = {
	"add", "bind", "cget", "configure", "delete", "lower", "names",
	"nextrange", "prevrange", "raise", "ranges", "remove", NULL
    };
    enum tagOptions {
	TAG_ADD, TAG_BIND, TAG_CGET, TAG_CONFIGURE, TAG_DELETE, TAG_LOWER,
	TAG_NAMES, TAG_NEXTRANGE, TAG_PREVRANGE, TAG_RAISE, TAG_RANGES,
	TAG_REMOVE
    };
    int optionIndex, i;
    register TkTextTag *tagPtr;
    TkTextTag *tagPtr;
    TkTextIndex index1, index2;

    if (objc < 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "option ?arg ...?");
	return TCL_ERROR;
    }

339
340
341
342
343
344
345
346

347
348
349
350
351
352
353
354
355
356
357
358
359
360

361
362
363
364
365

366
367
368
369
370
371
372
373
374
375
376
377

378
379
380
381
382
383
384
339
340
341
342
343
344
345

346
347
348
349
350
351
352
353
354
355
356
357
358
359

360
361
362
363
364

365
366
367
368
369
370
371
372
373
374
375
376

377
378
379
380
381
382
383
384







-
+













-
+




-
+











-
+







	} else {
	    Tcl_Obj *objPtr;

	    tagPtr = FindTag(interp, textPtr, objv[3]);
	    if (tagPtr == NULL) {
		return TCL_ERROR;
	    }
	    objPtr = Tk_GetOptionValue(interp, (char *) tagPtr,
	    objPtr = Tk_GetOptionValue(interp, tagPtr,
		    tagPtr->optionTable, objv[4], textPtr->tkwin);
	    if (objPtr == NULL) {
		return TCL_ERROR;
	    }
	    Tcl_SetObjResult(interp, objPtr);
	    return TCL_OK;
	}
	break;
    case TAG_CONFIGURE: {
	int newTag;

	if (objc < 4) {
	    Tcl_WrongNumArgs(interp, 3, objv,
		    "tagName ?-option? ?value? ?-option value ...?");
		    "tagName ?-option value ...?");
	    return TCL_ERROR;
	}
	tagPtr = TkTextCreateTag(textPtr, Tcl_GetString(objv[3]), &newTag);
	if (objc <= 5) {
	    Tcl_Obj *objPtr = Tk_GetOptionInfo(interp, (char *) tagPtr,
	    Tcl_Obj *objPtr = Tk_GetOptionInfo(interp, tagPtr,
		    tagPtr->optionTable,
		    (objc == 5) ? objv[4] : NULL, textPtr->tkwin);

	    if (objPtr == NULL) {
		return TCL_ERROR;
	    }
	    Tcl_SetObjResult(interp, objPtr);
	    return TCL_OK;
	} else {
	    int result = TCL_OK;

	    if (Tk_SetOptions(interp, (char *) tagPtr, tagPtr->optionTable,
	    if (Tk_SetOptions(interp, tagPtr, tagPtr->optionTable,
		    objc-4, objv+4, textPtr->tkwin, NULL, NULL) != TCL_OK) {
		return TCL_ERROR;
	    }

	    /*
	     * Some of the configuration options, like -underline and
	     * -justify, require additional translation (this is needed
580
581
582
583
584
585
586
587

588
589
590
591
592
593
594
580
581
582
583
584
585
586

587
588
589
590
591
592
593
594







-
+







		 * Either this tag doesn't exist or it's the 'sel' tag (which
		 * is not in the hash table). Either way we don't want to
		 * delete it.
		 */

		continue;
	    }
	    tagPtr = Tcl_GetHashValue(hPtr);
	    tagPtr = (TkTextTag *)Tcl_GetHashValue(hPtr);
	    if (tagPtr == textPtr->selTagPtr) {
		continue;
	    }
	    if (tagPtr->affectsDisplay) {
		TkTextRedrawTag(textPtr->sharedTextPtr, NULL,
			NULL, NULL, tagPtr, 1);
	    }
641
642
643
644
645
646
647
648

649
650
651
652
653

654
655
656
657
658
659
660
641
642
643
644
645
646
647

648
649
650
651
652

653
654
655
656
657
658
659
660







-
+




-
+







	    Tcl_WrongNumArgs(interp, 3, objv, "?index?");
	    return TCL_ERROR;
	}
	if (objc == 3) {
	    Tcl_HashSearch search;
	    Tcl_HashEntry *hPtr;

	    arrayPtr = ckalloc(textPtr->sharedTextPtr->numTags
	    arrayPtr = (TkTextTag **)ckalloc(textPtr->sharedTextPtr->numTags
		    * sizeof(TkTextTag *));
	    for (i=0, hPtr = Tcl_FirstHashEntry(
		    &textPtr->sharedTextPtr->tagTable, &search);
		    hPtr != NULL; i++, hPtr = Tcl_NextHashEntry(&search)) {
		arrayPtr[i] = Tcl_GetHashValue(hPtr);
		arrayPtr[i] = (TkTextTag *)Tcl_GetHashValue(hPtr);
	    }

	    /*
	     * The 'sel' tag is not in the hash table.
	     */

	    arrayPtr[i] = textPtr->selTagPtr;
982
983
984
985
986
987
988
989

990
991
992
993
994
995
996
982
983
984
985
986
987
988

989
990
991
992
993
994
995
996







-
+







TkTextTag *
TkTextCreateTag(
    TkText *textPtr,		/* Widget in which tag is being used. */
    const char *tagName,	/* Name of desired tag. */
    int *newTag)		/* If non-NULL, then return 1 if new, or 0 if
				 * already exists. */
{
    register TkTextTag *tagPtr;
    TkTextTag *tagPtr;
    Tcl_HashEntry *hPtr = NULL;
    int isNew;
    const char *name;

    if (!strcmp(tagName, "sel")) {
	if (textPtr->selTagPtr != NULL) {
	    if (newTag != NULL) {
1005
1006
1007
1008
1009
1010
1011
1012

1013
1014

1015
1016
1017
1018
1019
1020
1021
1022

1023
1024
1025
1026
1027
1028
1029
1005
1006
1007
1008
1009
1010
1011

1012
1013

1014
1015
1016
1017
1018
1019
1020
1021

1022
1023
1024
1025
1026
1027
1028
1029







-
+

-
+







-
+







    } else {
	hPtr = Tcl_CreateHashEntry(&textPtr->sharedTextPtr->tagTable,
		tagName, &isNew);
	if (newTag != NULL) {
	    *newTag = isNew;
	}
	if (!isNew) {
	    return Tcl_GetHashValue(hPtr);
	    return (TkTextTag *)Tcl_GetHashValue(hPtr);
	}
	name = Tcl_GetHashKey(&textPtr->sharedTextPtr->tagTable, hPtr);
	name = (const char *)Tcl_GetHashKey(&textPtr->sharedTextPtr->tagTable, hPtr);
    }

    /*
     * No existing entry. Create a new one, initialize it, and add a pointer
     * to it to the hash table entry.
     */

    tagPtr = ckalloc(sizeof(TkTextTag));
    tagPtr = (TkTextTag *)ckalloc(sizeof(TkTextTag));
    tagPtr->name = name;
    tagPtr->textPtr = NULL;
    tagPtr->toggleCount = 0;
    tagPtr->tagRootPtr = NULL;
    tagPtr->priority = textPtr->sharedTextPtr->numTags;
    tagPtr->border = NULL;
    tagPtr->borderWidth = 0;
1104
1105
1106
1107
1108
1109
1110
1111

1112
1113
1114

1115
1116
1117
1118
1119
1120
1121

1122
1123
1124
1125
1126
1127
1128
1104
1105
1106
1107
1108
1109
1110

1111
1112
1113

1114
1115
1116
1117
1118
1119
1120

1121
1122
1123
1124
1125
1126
1127
1128







-
+


-
+






-
+







    Tcl_Interp *interp,		/* Interpreter to use for error message; if
				 * NULL, then don't record an error
				 * message. */
    TkText *textPtr,		/* Widget in which tag is being used. */
    Tcl_Obj *tagName)		/* Name of desired tag. */
{
    Tcl_HashEntry *hPtr;
    int len;
    TkSizeT len;
    const char *str;

    str = Tcl_GetStringFromObj(tagName, &len);
    str = TkGetStringFromObj(tagName, &len);
    if (len == 3 && !strcmp(str, "sel")) {
	return textPtr->selTagPtr;
    }
    hPtr = Tcl_FindHashEntry(&textPtr->sharedTextPtr->tagTable,
	    Tcl_GetString(tagName));
    if (hPtr != NULL) {
	return Tcl_GetHashValue(hPtr);
	return (TkTextTag *)Tcl_GetHashValue(hPtr);
    }
    if (interp != NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"tag \"%s\" isn't defined in text widget",
		Tcl_GetString(tagName)));
	Tcl_SetErrorCode(interp, "TK", "LOOKUP", "TEXT_TAG",
		Tcl_GetString(tagName), NULL);
1154
1155
1156
1157
1158
1159
1160
1161

1162
1163
1164
1165
1166
1167
1168
1154
1155
1156
1157
1158
1159
1160

1161
1162
1163
1164
1165
1166
1167
1168







-
+







 *
 *----------------------------------------------------------------------
 */

void
TkTextDeleteTag(
    TkText *textPtr,		/* Info about overall widget. */
    register TkTextTag *tagPtr)	/* Tag being deleted. */
    TkTextTag *tagPtr)	/* Tag being deleted. */
{
    TkTextIndex first, last;

    TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, 0, 0, &first);
    TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr,
	    TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr), 0, &last),
    TkBTreeTag(&first, &last, tagPtr, 0);
1212
1213
1214
1215
1216
1217
1218
1219

1220
1221
1222
1223
1224
1225
1226
1212
1213
1214
1215
1216
1217
1218

1219
1220
1221
1222
1223
1224
1225
1226







-
+







 *
 *----------------------------------------------------------------------
 */

void
TkTextFreeTag(
    TkText *textPtr,		/* Info about overall widget. */
    register TkTextTag *tagPtr)	/* Tag being deleted. */
    TkTextTag *tagPtr)	/* Tag being deleted. */
{
    int i;

    /*
     * Let Tk do most of the hard work for us.
     */

1291
1292
1293
1294
1295
1296
1297
1298

1299
1300
1301
1302
1303
1304
1305
1291
1292
1293
1294
1295
1296
1297

1298
1299
1300
1301
1302
1303
1304
1305







-
+








static void
SortTags(
    int numTags,		/* Number of tag pointers at *tagArrayPtr. */
    TkTextTag **tagArrayPtr)	/* Pointer to array of pointers. */
{
    int i, j, prio;
    register TkTextTag **tagPtrPtr;
    TkTextTag **tagPtrPtr;
    TkTextTag **maxPtrPtr, *tmp;

    if (numTags < 2) {
	return;
    }
    if (numTags < 20) {
	for (i = numTags-1; i > 0; i--, tagArrayPtr++) {
1375
1376
1377
1378
1379
1380
1381
1382

1383
1384
1385
1386
1387
1388
1389
1375
1376
1377
1378
1379
1380
1381

1382
1383
1384
1385
1386
1387
1388
1389







-
+







static void
ChangeTagPriority(
    TkText *textPtr,		/* Information about text widget. */
    TkTextTag *tagPtr,		/* Tag whose priority is to be changed. */
    int prio)			/* New priority for tag. */
{
    int low, high, delta;
    register TkTextTag *tagPtr2;
    TkTextTag *tagPtr2;
    Tcl_HashEntry *hPtr;
    Tcl_HashSearch search;

    if (prio < 0) {
	prio = 0;
    }
    if (prio >= textPtr->sharedTextPtr->numTags) {
1408
1409
1410
1411
1412
1413
1414
1415

1416
1417
1418
1419
1420
1421
1422
1408
1409
1410
1411
1412
1413
1414

1415
1416
1417
1418
1419
1420
1421
1422







-
+








    if ((textPtr->selTagPtr->priority >= low)
	    && (textPtr->selTagPtr->priority <= high)) {
	textPtr->selTagPtr->priority += delta;
    }
    for (hPtr = Tcl_FirstHashEntry(&textPtr->sharedTextPtr->tagTable, &search);
	    hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
	tagPtr2 = Tcl_GetHashValue(hPtr);
	tagPtr2 = (TkTextTag *)Tcl_GetHashValue(hPtr);
	if ((tagPtr2->priority >= low) && (tagPtr2->priority <= high)) {
	    tagPtr2->priority += delta;
	}
    }
    tagPtr->priority = prio;
}

1436
1437
1438
1439
1440
1441
1442
1443

1444
1445
1446

1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460

1461
1462

1463
1464
1465
1466
1467
1468
1469
1436
1437
1438
1439
1440
1441
1442

1443
1444
1445

1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459

1460
1461

1462
1463
1464
1465
1466
1467
1468
1469







-
+


-
+













-
+

-
+







 *	any).
 *
 *--------------------------------------------------------------
 */

void
TkTextBindProc(
    ClientData clientData,	/* Pointer to canvas structure. */
    ClientData clientData,	/* Pointer to text widget structure. */
    XEvent *eventPtr)		/* Pointer to X event that just happened. */
{
    TkText *textPtr = clientData;
    TkText *textPtr = (TkText *)clientData;
    int repick = 0;

    textPtr->refCount++;

    /*
     * This code simulates grabs for mouse buttons by keeping track of whether
     * a button is pressed and refusing to pick a new current character while
     * a button is pressed.
     */

    if (eventPtr->type == ButtonPress) {
	textPtr->flags |= BUTTON_DOWN;
    } else if (eventPtr->type == ButtonRelease) {
	unsigned int mask;
	unsigned long mask;

	mask = TkGetButtonMask(eventPtr->xbutton.button);
	mask = Tk_GetButtonMask(eventPtr->xbutton.button);
	if ((eventPtr->xbutton.state & ALL_BUTTONS) == mask) {
	    textPtr->flags &= ~BUTTON_DOWN;
	    repick = 1;
	}
    } else if ((eventPtr->type == EnterNotify)
	    || (eventPtr->type == LeaveNotify)) {
	if (eventPtr->xcrossing.state & ALL_BUTTONS) {
1525
1526
1527
1528
1529
1530
1531
1532

1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543


1544
1545
1546
1547
1548
1549
1550
1525
1526
1527
1528
1529
1530
1531

1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542

1543
1544
1545
1546
1547
1548
1549
1550
1551







-
+










-
+
+







 *	widget.
 *
 *--------------------------------------------------------------
 */

void
TkTextPickCurrent(
    register TkText *textPtr,	/* Text widget in which to select current
    TkText *textPtr,	/* Text widget in which to select current
				 * character. */
    XEvent *eventPtr)		/* Event describing location of mouse cursor.
				 * Must be EnterWindow, LeaveWindow,
				 * ButtonRelease, or MotionNotify. */
{
    TkTextIndex index;
    TkTextTag **oldArrayPtr, **newArrayPtr;
    TkTextTag **copyArrayPtr = NULL;
				/* Initialization needed to prevent compiler
				 * warning. */
    int numOldTags, numNewTags, i, j, size, nearby;
    int numOldTags, numNewTags, i, j, nearby;
    size_t size;
    XEvent event;

    /*
     * If a button is down, then don't do anything at all; we'll be called
     * again when all buttons are up, and we can repick then. This implements
     * a form of mouse grabbing.
     */
1628
1629
1630
1631
1632
1633
1634
1635
1636


1637
1638
1639
1640
1641
1642
1643
1629
1630
1631
1632
1633
1634
1635


1636
1637
1638
1639
1640
1641
1642
1643
1644







-
-
+
+







     * compare the old tags to the copy, nullifying any tags that are present
     * in both groups (i.e. the tags that haven't changed).
     */

    SortTags(textPtr->numCurTags, textPtr->curTagArrayPtr);
    if (numNewTags > 0) {
	size = numNewTags * sizeof(TkTextTag *);
	copyArrayPtr = ckalloc(size);
	memcpy(copyArrayPtr, newArrayPtr, (size_t) size);
	copyArrayPtr = (TkTextTag **)ckalloc(size);
	memcpy(copyArrayPtr, newArrayPtr, size);
	for (i = 0; i < textPtr->numCurTags; i++) {
	    for (j = 0; j < numNewTags; j++) {
		if (textPtr->curTagArrayPtr[i] == copyArrayPtr[j]) {
		    textPtr->curTagArrayPtr[i] = NULL;
		    copyArrayPtr[j] = NULL;
		    break;
		}
1732
1733
1734
1735
1736
1737
1738
1739

1740
1741
1742
1743
1744
1745
1746
1733
1734
1735
1736
1737
1738
1739

1740
1741
1742
1743
1744
1745
1746
1747







-
+







    int i;

    /*
     * Try to avoid allocation unless there are lots of tags.
     */

    if (numTags > NUM_BIND_TAGS) {
	nameArrPtr = ckalloc(numTags * sizeof(const char *));
	nameArrPtr = (const char **)ckalloc(numTags * sizeof(const char *));
    } else {
	nameArrPtr = nameArray;
    }

    /*
     * We use tag names as keys in the hash table. We do this instead of using
     * the actual tagPtr objects because we want one "sel" tag binding for all
Changes to generic/tkTextWind.c.
1
2
3
4
5
6
7
8
9


10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

26
27
28
29
30
31

32
33
34
35
36
37
38
39


40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

61
62
63
64
65
66
67
1
2
3
4
5
6
7


8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

25
26
27
28
29
30

31
32
33
34
35
36
37


38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

60
61
62
63
64
65
66
67







-
-
+
+















-
+





-
+






-
-
+
+




















-
+







/*
 * tkTextWind.c --
 *
 *	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.
 */

#include "tkPort.h"
#include "tkText.h"

/*
 * The following structure is the official type record for the embedded window
 * geometry manager:
 */

static void		EmbWinRequestProc(ClientData clientData,
			    Tk_Window tkwin);
static void		EmbWinLostSlaveProc(ClientData clientData,
static void		EmbWinLostContentProc(ClientData clientData,
			    Tk_Window tkwin);

static const Tk_GeomMgr textGeomType = {
    "text",			/* name */
    EmbWinRequestProc,		/* requestProc */
    EmbWinLostSlaveProc,	/* lostSlaveProc */
    EmbWinLostContentProc,	/* lostContentProc */
};

/*
 * Macro that determines the size of an embedded window segment:
 */

#define EW_SEG_SIZE ((unsigned) (Tk_Offset(TkTextSegment, body) \
	+ sizeof(TkTextEmbWindow)))
#define EW_SEG_SIZE (offsetof(TkTextSegment, body) \
	+ sizeof(TkTextEmbWindow))

/*
 * Prototypes for functions defined in this file:
 */

static TkTextSegment *	EmbWinCleanupProc(TkTextSegment *segPtr,
			    TkTextLine *linePtr);
static void		EmbWinCheckProc(TkTextSegment *segPtr,
			    TkTextLine *linePtr);
static void		EmbWinBboxProc(TkText *textPtr,
			    TkTextDispChunk *chunkPtr, int index, int y,
			    int lineHeight, int baseline, int *xPtr,int *yPtr,
			    int *widthPtr, int *heightPtr);
static int		EmbWinConfigure(TkText *textPtr, TkTextSegment *ewPtr,
			    int objc, Tcl_Obj *const objv[]);
static void		EmbWinDelayedUnmap(ClientData clientData);
static int		EmbWinDeleteProc(TkTextSegment *segPtr,
			    TkTextLine *linePtr, int treeGone);
static int		EmbWinLayoutProc(TkText *textPtr,
			    TkTextIndex *indexPtr, TkTextSegment *segPtr,
			    int offset, int maxX, int maxChars,int noCharsYet,
			    TkSizeT offset, int maxX, TkSizeT maxChars,int noCharsYet,
			    TkWrapMode wrapMode, TkTextDispChunk *chunkPtr);
static void		EmbWinStructureProc(ClientData clientData,
			    XEvent *eventPtr);
static void		EmbWinUndisplayProc(TkText *textPtr,
			    TkTextDispChunk *chunkPtr);
static TkTextEmbWindowClient *EmbWinGetClient(const TkText *textPtr,
			    TkTextSegment *ewPtr);
95
96
97
98
99
100
101
102

103
104
105

106
107

108
109

110
111

112
113

114
115
116
117
118
119
120
95
96
97
98
99
100
101

102
103
104

105
106

107
108

109
110

111
112

113
114
115
116
117
118
119
120







-
+


-
+

-
+

-
+

-
+

-
+








/*
 * Information used for parsing window configuration options:
 */

static const Tk_OptionSpec optionSpecs[] = {
    {TK_OPTION_STRING_TABLE, "-align", NULL, NULL,
	"center", -1, Tk_Offset(TkTextEmbWindow, align),
	"center", TCL_INDEX_NONE, offsetof(TkTextEmbWindow, align),
	0, alignStrings, 0},
    {TK_OPTION_STRING, "-create", NULL, NULL,
	NULL, -1, Tk_Offset(TkTextEmbWindow, create), TK_OPTION_NULL_OK, 0, 0},
	NULL, TCL_INDEX_NONE, offsetof(TkTextEmbWindow, create), TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_PIXELS, "-padx", NULL, NULL,
	"0", -1, Tk_Offset(TkTextEmbWindow, padX), 0, 0, 0},
	"0", TCL_INDEX_NONE, offsetof(TkTextEmbWindow, padX), 0, 0, 0},
    {TK_OPTION_PIXELS, "-pady", NULL, NULL,
	"0", -1, Tk_Offset(TkTextEmbWindow, padY), 0, 0, 0},
	"0", TCL_INDEX_NONE, offsetof(TkTextEmbWindow, padY), 0, 0, 0},
    {TK_OPTION_BOOLEAN, "-stretch", NULL, NULL,
	"0", -1, Tk_Offset(TkTextEmbWindow, stretch), 0, 0, 0},
	"0", TCL_INDEX_NONE, offsetof(TkTextEmbWindow, stretch), 0, 0, 0},
    {TK_OPTION_WINDOW, "-window", NULL, NULL,
	NULL, -1, Tk_Offset(TkTextEmbWindow, tkwin), TK_OPTION_NULL_OK, 0, 0},
	NULL, TCL_INDEX_NONE, offsetof(TkTextEmbWindow, tkwin), TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0}
};

/*
 *--------------------------------------------------------------
 *
 * TkTextWindowCmd --
129
130
131
132
133
134
135
136

137
138
139
140
141
142
143
144
145
146
147
148
149
150

151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
129
130
131
132
133
134
135

136
137
138
139
140
141
142
143
144
145
146
147
148
149

150
151
152
153
154
155
156
157
158
159
160
161
162

163
164
165
166
167
168
169







-
+













-
+












-







 *	See the user documentation.
 *
 *--------------------------------------------------------------
 */

int
TkTextWindowCmd(
    register TkText *textPtr,	/* Information about text widget. */
    TkText *textPtr,	/* Information about text widget. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. Someone else has already
				 * parsed this command enough to know that
				 * objv[1] is "window". */
{
    int optionIndex;
    static const char *const windOptionStrings[] = {
	"cget", "configure", "create", "names", NULL
    };
    enum windOptions {
	WIND_CGET, WIND_CONFIGURE, WIND_CREATE, WIND_NAMES
    };
    register TkTextSegment *ewPtr;
    TkTextSegment *ewPtr;

    if (objc < 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "option ?arg ...?");
	return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObjStruct(interp, objv[2], windOptionStrings,
	    sizeof(char *), "window option", 0, &optionIndex) != TCL_OK) {
	return TCL_ERROR;
    }
    switch ((enum windOptions) optionIndex) {
    case WIND_CGET: {
	TkTextIndex index;
	TkTextSegment *ewPtr;
	Tcl_Obj *objPtr;
	TkTextEmbWindowClient *client;

	if (objc != 5) {
	    Tcl_WrongNumArgs(interp, 3, objv, "index option");
	    return TCL_ERROR;
	}
187
188
189
190
191
192
193
194

195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
186
187
188
189
190
191
192

193
194
195
196
197
198
199
200
201
202

203
204
205
206
207
208
209







-
+









-







	client = EmbWinGetClient(textPtr, ewPtr);
	if (client != NULL) {
	    ewPtr->body.ew.tkwin = client->tkwin;
	} else {
	    ewPtr->body.ew.tkwin = NULL;
	}

	objPtr = Tk_GetOptionValue(interp, (char *) &ewPtr->body.ew,
	objPtr = Tk_GetOptionValue(interp, &ewPtr->body.ew,
		ewPtr->body.ew.optionTable, objv[4], textPtr->tkwin);
	if (objPtr == NULL) {
	    return TCL_ERROR;
	}
	Tcl_SetObjResult(interp, objPtr);
	return TCL_OK;
    }
    case WIND_CONFIGURE: {
	TkTextIndex index;
	TkTextSegment *ewPtr;

	if (objc < 4) {
	    Tcl_WrongNumArgs(interp, 3, objv, "index ?-option value ...?");
	    return TCL_ERROR;
	}
	if (TkTextGetObjIndex(interp, textPtr, objv[3], &index) != TCL_OK) {
	    return TCL_ERROR;
229
230
231
232
233
234
235
236

237
238
239
240
241
242
243
227
228
229
230
231
232
233

234
235
236
237
238
239
240
241







-
+







	    client = EmbWinGetClient(textPtr, ewPtr);
	    if (client != NULL) {
		ewPtr->body.ew.tkwin = client->tkwin;
	    } else {
		ewPtr->body.ew.tkwin = NULL;
	    }

	    objPtr = Tk_GetOptionInfo(interp, (char *) &ewPtr->body.ew,
	    objPtr = Tk_GetOptionInfo(interp, &ewPtr->body.ew,
		    ewPtr->body.ew.optionTable, (objc == 5) ? objv[4] : NULL,
		    textPtr->tkwin);
	    if (objPtr == NULL) {
		return TCL_ERROR;
	    }
	    Tcl_SetObjResult(interp, objPtr);
	    return TCL_OK;
286
287
288
289
290
291
292
293

294
295
296
297
298
299
300
301
302
303
304
305

306
307
308
309
310
311
312
284
285
286
287
288
289
290

291
292
293
294
295
296
297
298
299
300
301
302

303
304
305
306
307
308
309
310







-
+











-
+







		    lineIndex, 1000000, &index);
	}

	/*
	 * Create the new window segment and initialize it.
	 */

	ewPtr = ckalloc(EW_SEG_SIZE);
	ewPtr = (TkTextSegment *)ckalloc(EW_SEG_SIZE);
	ewPtr->typePtr = &tkTextEmbWindowType;
	ewPtr->size = 1;
	ewPtr->body.ew.sharedTextPtr = textPtr->sharedTextPtr;
	ewPtr->body.ew.linePtr = NULL;
	ewPtr->body.ew.tkwin = NULL;
	ewPtr->body.ew.create = NULL;
	ewPtr->body.ew.align = ALIGN_CENTER;
	ewPtr->body.ew.padX = ewPtr->body.ew.padY = 0;
	ewPtr->body.ew.stretch = 0;
	ewPtr->body.ew.optionTable = Tk_CreateOptionTable(interp, optionSpecs);

	client = ckalloc(sizeof(TkTextEmbWindowClient));
	client = (TkTextEmbWindowClient *)ckalloc(sizeof(TkTextEmbWindowClient));
	client->next = NULL;
	client->textPtr = textPtr;
	client->tkwin = NULL;
	client->chunkCount = 0;
	client->displayed = 0;
	client->parent = ewPtr;
	ewPtr->body.ew.clients = client;
341
342
343
344
345
346
347
348

349
350
351
352
353
354
355
339
340
341
342
343
344
345

346
347
348
349
350
351
352
353







-
+







	    Tcl_WrongNumArgs(interp, 3, objv, NULL);
	    return TCL_ERROR;
	}
	resultObj = Tcl_NewObj();
	for (hPtr = Tcl_FirstHashEntry(&textPtr->sharedTextPtr->windowTable,
		&search); hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
	    Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewStringObj(
		    Tcl_GetHashKey(&textPtr->sharedTextPtr->markTable, hPtr),
		    (const char *)Tcl_GetHashKey(&textPtr->sharedTextPtr->markTable, hPtr),
		    -1));
	}
	Tcl_SetObjResult(interp, resultObj);
	break;
    }
    }
    return TCL_OK;
399
400
401
402
403
404
405
406

407
408
409
410
411
412
413
397
398
399
400
401
402
403

404
405
406
407
408
409
410
411







-
+







    if (client != NULL) {
	ewPtr->body.ew.tkwin = client->tkwin;
    } else {
	ewPtr->body.ew.tkwin = NULL;
    }

    oldWindow = ewPtr->body.ew.tkwin;
    if (Tk_SetOptions(textPtr->interp, (char *) &ewPtr->body.ew,
    if (Tk_SetOptions(textPtr->interp, &ewPtr->body.ew,
	    ewPtr->body.ew.optionTable, objc, objv, textPtr->tkwin, NULL,
	    NULL) != TCL_OK) {
	return TCL_ERROR;
    }

    if (oldWindow != ewPtr->body.ew.tkwin) {
	if (oldWindow != NULL) {
439
440
441
442
443
444
445
446

447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462

463
464
465
466
467
468
469
470

471
472
473
474
475
476
477
437
438
439
440
441
442
443

444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459

460
461
462
463
464
465
466
467

468
469
470
471
472
473
474
475







-
+















-
+







-
+








	    parent = Tk_Parent(ewPtr->body.ew.tkwin);
	    for (ancestor = textPtr->tkwin; ; ancestor = Tk_Parent(ancestor)) {
		if (ancestor == parent) {
		    break;
		}
		if (Tk_TopWinHierarchy(ancestor)) {
		badMaster:
		badContainer:
		    Tcl_SetObjResult(textPtr->interp, Tcl_ObjPrintf(
			    "can't embed %s in %s",
			    Tk_PathName(ewPtr->body.ew.tkwin),
			    Tk_PathName(textPtr->tkwin)));
		    Tcl_SetErrorCode(textPtr->interp, "TK", "GEOMETRY",
			    "HIERARCHY", NULL);
		    ewPtr->body.ew.tkwin = NULL;
		    if (client != NULL) {
			client->tkwin = NULL;
		    }
		    return TCL_ERROR;
		}
	    }
	    if (Tk_TopWinHierarchy(ewPtr->body.ew.tkwin)
		    || (ewPtr->body.ew.tkwin == textPtr->tkwin)) {
		goto badMaster;
		goto badContainer;
	    }

	    if (client == NULL) {
		/*
		 * Have to make the new client.
		 */

		client = ckalloc(sizeof(TkTextEmbWindowClient));
		client = (TkTextEmbWindowClient *)ckalloc(sizeof(TkTextEmbWindowClient));
		client->next = ewPtr->body.ew.clients;
		client->textPtr = textPtr;
		client->tkwin = NULL;
		client->chunkCount = 0;
		client->displayed = 0;
		client->parent = ewPtr;
		ewPtr->body.ew.clients = client;
522
523
524
525
526
527
528
529

530
531
532
533
534
535
536
520
521
522
523
524
525
526

527
528
529
530
531
532
533
534







-
+







 */

static void
EmbWinStructureProc(
    ClientData clientData,	/* Pointer to record describing window item. */
    XEvent *eventPtr)		/* Describes what just happened. */
{
    TkTextEmbWindowClient *client = clientData;
    TkTextEmbWindowClient *client = (TkTextEmbWindowClient *)clientData;
    TkTextSegment *ewPtr = client->parent;
    TkTextIndex index;
    Tcl_HashEntry *hPtr;

    if (eventPtr->type != DestroyNotify) {
	return;
    }
569
570
571
572
573
574
575
576
577
578
579
580

581
582

583
584
585
586
587
588
589
590
591
592
593
594
595
596
597

598
599

600
601
602
603
604
605
606
607
608
609
610
611
612
613
614

615
616
617
618
619

620
621
622
623
624
625
626
567
568
569
570
571
572
573

574
575
576

577
578

579
580
581
582
583
584
585
586
587
588
589
590
591
592
593

594
595

596
597
598
599
600
601
602
603
604
605
606
607
608
609
610

611
612
613
614
615

616
617
618
619
620
621
622
623







-



-
+

-
+














-
+

-
+














-
+




-
+







 * Side effects:
 *	The size and location on the screen of the window may change,
 *	depending on the options specified for the window item.
 *
 *--------------------------------------------------------------
 */

	/* ARGSUSED */
static void
EmbWinRequestProc(
    ClientData clientData,	/* Pointer to record for window item. */
    Tk_Window tkwin)		/* Window that changed its desired size. */
    TCL_UNUSED(Tk_Window))		/* Window that changed its desired size. */
{
    TkTextEmbWindowClient *client = clientData;
    TkTextEmbWindowClient *client = (TkTextEmbWindowClient *)clientData;
    TkTextSegment *ewPtr = client->parent;
    TkTextIndex index;

    index.tree = ewPtr->body.ew.sharedTextPtr->tree;
    index.linePtr = ewPtr->body.ew.linePtr;
    index.byteIndex = TkTextSegToOffset(ewPtr, ewPtr->body.ew.linePtr);
    TkTextChanged(ewPtr->body.ew.sharedTextPtr, NULL, &index, &index);
    TkTextInvalidateLineMetrics(ewPtr->body.ew.sharedTextPtr, NULL,
	    index.linePtr, 0, TK_TEXT_INVALIDATE_ONLY);
}

/*
 *--------------------------------------------------------------
 *
 * EmbWinLostSlaveProc --
 * EmbWinLostContentProc --
 *
 *	This function is invoked by the Tk geometry manager when a slave
 *	This function is invoked by the Tk geometry manager when a content
 *	window managed by a text widget is claimed away by another geometry
 *	manager.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The window is disassociated from the window segment, and the portion
 *	of the text is redisplayed.
 *
 *--------------------------------------------------------------
 */

static void
EmbWinLostSlaveProc(
EmbWinLostContentProc(
    ClientData clientData,	/* Pointer to record describing window item. */
    Tk_Window tkwin)		/* Window that was claimed away by another
				 * geometry manager. */
{
    TkTextEmbWindowClient *client = clientData;
    TkTextEmbWindowClient *client = (TkTextEmbWindowClient *)clientData;
    TkTextSegment *ewPtr = client->parent;
    TkTextIndex index;
    Tcl_HashEntry *hPtr;
    TkTextEmbWindowClient *loop;

    Tk_DeleteEventHandler(client->tkwin, StructureNotifyMask,
	    EmbWinStructureProc, client);
732
733
734
735
736
737
738
739
740
741
742
743
744


745
746
747
748
749
750
751
729
730
731
732
733
734
735

736
737
738


739
740
741
742
743
744
745
746
747







-



-
-
+
+







 * Side effects:
 *	The embedded window is deleted, if it exists, and any resources
 *	associated with it are released.
 *
 *--------------------------------------------------------------
 */

	/* ARGSUSED */
static int
EmbWinDeleteProc(
    TkTextSegment *ewPtr,	/* Segment being deleted. */
    TkTextLine *linePtr,	/* Line containing segment. */
    int treeGone)		/* Non-zero means the entire tree is being
    TCL_UNUSED(TkTextLine *),	/* Line containing segment. */
    TCL_UNUSED(int))		/* Non-zero means the entire tree is being
				 * deleted, so everything must get cleaned
				 * up. */
{
    TkTextEmbWindowClient *client;
    client = ewPtr->body.ew.clients;

    while (client != NULL) {
812
813
814
815
816
817
818
819
820
821
822
823

824
825

826
827
828
829

830
831
832
833

834
835
836

837
838
839
840
841
842
843
808
809
810
811
812
813
814

815
816
817

818
819

820
821
822
823

824
825
826
827

828
829
830

831
832
833
834
835
836
837
838







-



-
+

-
+



-
+



-
+


-
+







 *
 * Side effects:
 *	None, except for filling in chunkPtr.
 *
 *--------------------------------------------------------------
 */

	/*ARGSUSED*/
static int
EmbWinLayoutProc(
    TkText *textPtr,		/* Text widget being layed out. */
    TkTextIndex *indexPtr,	/* Identifies first character in chunk. */
    TCL_UNUSED(TkTextIndex *),	/* Identifies first character in chunk. */
    TkTextSegment *ewPtr,	/* Segment corresponding to indexPtr. */
    int offset,			/* Offset within segPtr corresponding to
    TkSizeT offset,			/* Offset within segPtr corresponding to
				 * indexPtr (always 0). */
    int maxX,			/* Chunk must not occupy pixels at this
				 * position or higher. */
    int maxChars,		/* Chunk must not include more than this many
    TCL_UNUSED(TkSizeT),	/* Chunk must not include more than this many
				 * characters. */
    int noCharsYet,		/* Non-zero means no characters have been
				 * assigned to this line yet. */
    TkWrapMode wrapMode,	/* Wrap mode to use for line:
    TCL_UNUSED(TkWrapMode),	/* Wrap mode to use for line:
				 * TEXT_WRAPMODE_CHAR, TEXT_WRAPMODE_NONE, or
				 * TEXT_WRAPMODE_WORD. */
    register TkTextDispChunk *chunkPtr)
    TkTextDispChunk *chunkPtr)
				/* Structure to fill in with information about
				 * this chunk. The x field has already been
				 * set by the caller. */
{
    int width, height;
    TkTextEmbWindowClient *client;

932
933
934
935
936
937
938
939

940
941
942
943
944

945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962

963
964
965
966
967
968
969
927
928
929
930
931
932
933

934
935
936
937
938

939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956

957
958
959
960
961
962
963
964







-
+




-
+

















-
+







	}

	for (ancestor = textPtr->tkwin; ; ancestor = Tk_Parent(ancestor)) {
	    if (ancestor == Tk_Parent(ewPtr->body.ew.tkwin)) {
		break;
	    }
	    if (Tk_TopWinHierarchy(ancestor)) {
		goto badMaster;
		goto badContainer;
	    }
	}
	if (Tk_TopWinHierarchy(ewPtr->body.ew.tkwin)
		|| (textPtr->tkwin == ewPtr->body.ew.tkwin)) {
	badMaster:
	badContainer:
	    Tcl_SetObjResult(textPtr->interp, Tcl_ObjPrintf(
		    "can't embed %s relative to %s",
		    Tk_PathName(ewPtr->body.ew.tkwin),
		    Tk_PathName(textPtr->tkwin)));
	    Tcl_SetErrorCode(textPtr->interp, "TK", "GEOMETRY", "HIERARCHY",
		    NULL);
	    Tcl_BackgroundException(textPtr->interp, TCL_ERROR);
	    ewPtr->body.ew.tkwin = NULL;
	    goto gotWindow;
	}

	if (client == NULL) {
	    /*
	     * We just used a '-create' script to make a new window, which we
	     * now need to add to our client list.
	     */

	    client = ckalloc(sizeof(TkTextEmbWindowClient));
	    client = (TkTextEmbWindowClient *)ckalloc(sizeof(TkTextEmbWindowClient));
	    client->next = ewPtr->body.ew.clients;
	    client->textPtr = textPtr;
	    client->tkwin = NULL;
	    client->chunkCount = 0;
	    client->displayed = 0;
	    client->parent = ewPtr;
	    ewPtr->body.ew.clients = client;
1048
1049
1050
1051
1052
1053
1054
1055

1056
1057
1058
1059
1060
1061

1062
1063
1064
1065
1066
1067
1068
1043
1044
1045
1046
1047
1048
1049

1050
1051
1052
1053
1054
1055

1056
1057
1058
1059
1060
1061
1062
1063







-
+





-
+







 *
 *--------------------------------------------------------------
 */

static void
EmbWinCheckProc(
    TkTextSegment *ewPtr,	/* Segment to check. */
    TkTextLine *linePtr)	/* Line containing segment. */
    TCL_UNUSED(TkTextLine *))	/* Line containing segment. */
{
    if (ewPtr->nextPtr == NULL) {
	Tcl_Panic("EmbWinCheckProc: embedded window is last segment in line");
    }
    if (ewPtr->size != 1) {
	Tcl_Panic("EmbWinCheckProc: embedded window has size %d", ewPtr->size);
	Tcl_Panic("EmbWinCheckProc: embedded window has size %d", (int)ewPtr->size);
    }
}

/*
 *--------------------------------------------------------------
 *
 * TkTextEmbWinDisplayProc --
1083
1084
1085
1086
1087
1088
1089
1090

1091
1092
1093
1094
1095
1096


1097
1098
1099
1100
1101
1102
1103

1104
1105
1106
1107
1108
1109
1110
1078
1079
1080
1081
1082
1083
1084

1085
1086
1087
1088
1089


1090
1091
1092
1093
1094
1095
1096
1097

1098
1099
1100
1101
1102
1103
1104
1105







-
+




-
-
+
+






-
+







void
TkTextEmbWinDisplayProc(
    TkText *textPtr,		/* Information about text widget. */
    TkTextDispChunk *chunkPtr,	/* Chunk that is to be drawn. */
    int x,			/* X-position in dst at which to draw this
				 * chunk (differs from the x-position in the
				 * chunk because of scrolling). */
    int y,			/* Top of rectangular bounding box for line:
    TCL_UNUSED(int),	/* Top of rectangular bounding box for line:
				 * tells where to draw this chunk in dst
				 * (x-position is in the chunk itself). */
    int lineHeight,		/* Total height of line. */
    int baseline,		/* Offset of baseline from y. */
    Display *display,		/* Display to use for drawing (unused).  */
    Drawable dst,		/* Pixmap or window in which to draw
    TCL_UNUSED(Display *),	/* Display to use for drawing (unused).  */
    TCL_UNUSED(Drawable),	/* Pixmap or window in which to draw
				 * (unused).  */
    int screenY)		/* Y-coordinate in text window that
				 * corresponds to y. */
{
    int lineX, windowX, windowY, width, height;
    Tk_Window tkwin;
    TkTextSegment *ewPtr = chunkPtr->clientData;
    TkTextSegment *ewPtr = (TkTextSegment *)chunkPtr->clientData;
    TkTextEmbWindowClient *client = EmbWinGetClient(textPtr, ewPtr);

    if (client == NULL) {
	return;
    }

    tkwin = client->tkwin;
1176
1177
1178
1179
1180
1181
1182
1183

1184
1185
1186
1187
1188
1189
1190
1171
1172
1173
1174
1175
1176
1177

1178
1179
1180
1181
1182
1183
1184
1185







-
+







 */

static void
EmbWinUndisplayProc(
    TkText *textPtr,		/* Overall information about text widget. */
    TkTextDispChunk *chunkPtr)	/* Chunk that is about to be freed. */
{
    TkTextSegment *ewPtr = chunkPtr->clientData;
    TkTextSegment *ewPtr = (TkTextSegment *)chunkPtr->clientData;
    TkTextEmbWindowClient *client = EmbWinGetClient(textPtr, ewPtr);

    if (client == NULL) {
	return;
    }

    client->chunkCount--;
1224
1225
1226
1227
1228
1229
1230
1231

1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246

1247
1248
1249
1250
1251
1252
1253
1219
1220
1221
1222
1223
1224
1225

1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240

1241
1242
1243
1244
1245
1246
1247
1248







-
+














-
+







 *--------------------------------------------------------------
 */

static void
EmbWinBboxProc(
    TkText *textPtr,		/* Information about text widget. */
    TkTextDispChunk *chunkPtr,	/* Chunk containing desired char. */
    int index,			/* Index of desired character within the
    TCL_UNUSED(int),			/* Index of desired character within the
				 * chunk. */
    int y,			/* Topmost pixel in area allocated for this
				 * line. */
    int lineHeight,		/* Total height of line. */
    int baseline,		/* Location of line's baseline, in pixels
				 * measured down from y. */
    int *xPtr, int *yPtr,	/* Gets filled in with coords of character's
				 * upper-left pixel. */
    int *widthPtr,		/* Gets filled in with width of window, in
				 * pixels. */
    int *heightPtr)		/* Gets filled in with height of window, in
				 * pixels. */
{
    Tk_Window tkwin;
    TkTextSegment *ewPtr = chunkPtr->clientData;
    TkTextSegment *ewPtr = (TkTextSegment *)chunkPtr->clientData;
    TkTextEmbWindowClient *client = EmbWinGetClient(textPtr, ewPtr);

    if (client == NULL) {
	tkwin = NULL;
    } else {
	tkwin = client->tkwin;
    }
1301
1302
1303
1304
1305
1306
1307
1308

1309
1310
1311
1312
1313
1314
1315
1296
1297
1298
1299
1300
1301
1302

1303
1304
1305
1306
1307
1308
1309
1310







-
+







 *--------------------------------------------------------------
 */

static void
EmbWinDelayedUnmap(
    ClientData clientData)	/* Token for the window to be unmapped. */
{
    TkTextEmbWindowClient *client = clientData;
    TkTextEmbWindowClient *client = (TkTextEmbWindowClient *)clientData;

    if (!client->displayed && (client->tkwin != NULL)) {
	if (client->textPtr->tkwin != Tk_Parent(client->tkwin)) {
	    Tk_UnmaintainGeometry(client->tkwin, client->textPtr->tkwin);
	} else {
	    Tk_UnmapWindow(client->tkwin);
	}
1349
1350
1351
1352
1353
1354
1355
1356

1357
1358
1359
1360
1361
1362
1363
1344
1345
1346
1347
1348
1349
1350

1351
1352
1353
1354
1355
1356
1357
1358







-
+







    }

    hPtr = Tcl_FindHashEntry(&textPtr->sharedTextPtr->windowTable, name);
    if (hPtr == NULL) {
	return 0;
    }

    ewPtr = Tcl_GetHashValue(hPtr);
    ewPtr = (TkTextSegment *)Tcl_GetHashValue(hPtr);
    indexPtr->tree = textPtr->sharedTextPtr->tree;
    indexPtr->linePtr = ewPtr->body.ew.linePtr;
    indexPtr->byteIndex = TkTextSegToOffset(ewPtr, indexPtr->linePtr);
    return 1;
}

/*
Changes to generic/tkTrig.c.
1
2
3
4
5
6
7
8
9


10
11
12
13
14
15
16
1
2
3
4
5
6
7


8
9
10
11
12
13
14
15
16







-
-
+
+







/*
 * tkTrig.c --
 *
 *	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.
 */

#include "tkInt.h"
#include "tkCanvas.h"
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
278
279
280
281
282
283
284

285
286
287
288
289
290
291







-







 *
 * Side effects:
 *	None.
 *
 *--------------------------------------------------------------
 */

	/* ARGSUSED */
int
TkThickPolyLineToArea(
    double *coordPtr,		/* Points to an array of coordinates for the
				 * polyline: x0, y0, x1, y1, ... */
    int numPoints,		/* Total number of points at *coordPtr. */
    double width,		/* Width of each line segment. */
    int capStyle,		/* How are end-points of polyline drawn?
436
437
438
439
440
441
442
443

444
445
446
447
448
449
450
435
436
437
438
439
440
441

442
443
444
445
446
447
448
449







-
+







{
    double bestDist;		/* Closest distance between point and any edge
				 * in polygon. */
    int intersections;		/* Number of edges in the polygon that
				 * intersect a ray extending vertically
				 * upwards from the point to infinity. */
    int count;
    register double *pPtr;
    double *pPtr;

    /*
     * Iterate through all of the edges in the polygon, updating bestDist and
     * intersections.
     *
     * TRICKY POINT: when computing intersections, include left x-coordinate
     * of line within its range, but not y-coordinate. Otherwise if the point
584
585
586
587
588
589
590
591

592
593
594
595
596
597
598
599

600
601
602
603
604
605
606
583
584
585
586
587
588
589

590
591
592
593
594
595
596
597

598
599
600
601
602
603
604
605







-
+







-
+








int
TkPolygonToArea(
    double *polyPtr,		/* Points to an array coordinates for closed
				 * polygon: x0, y0, x1, y1, ... The polygon
				 * may be self-intersecting. */
    int numPoints,		/* Total number of points at *polyPtr. */
    register double *rectPtr)	/* Points to coords for rectangle, in the
    double *rectPtr)	/* Points to coords for rectangle, in the
				 * order x1, y1, x2, y2. X1 and y1 must be
				 * lower-left corner. */
{
    int state;			/* State of all edges seen so far (-1 means
				 * outside, 1 means inside, won't ever be
				 * 0). */
    int count;
    register double *pPtr;
    double *pPtr;

    /*
     * Iterate over all of the edges of the polygon and test them against the
     * rectangle. Can quit as soon as the state becomes "intersecting".
     */

    state = TkLineToArea(polyPtr, polyPtr+2, rectPtr);
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
647
648
649
650
651
652
653

654
655
656
657
658
659
660







-







 *
 * Side effects:
 *	None.
 *
 *--------------------------------------------------------------
 */

	/* ARGSUSED */
double
TkOvalToPoint(
    double ovalPtr[4],		/* 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
747
748
749
750
751
752
753
754

755
756
757
758

759
760
761
762
763
764
765
745
746
747
748
749
750
751

752
753
754
755

756
757
758
759
760
761
762
763







-
+



-
+







 *	None.
 *
 *--------------------------------------------------------------
 */

int
TkOvalToArea(
    register double *ovalPtr,	/* Points to coordinates defining the
    double *ovalPtr,	/* Points to coordinates defining the
				 * bounding rectangle for the oval: x1, y1,
				 * x2, y2. X1 must be less than x2 and y1 less
				 * than y2. */
    register double *rectPtr)	/* Points to coords for rectangle, in the
    double *rectPtr)	/* Points to coords for rectangle, in the
				 * order x1, y1, x2, y2. X1 and y1 must be
				 * lower-left corner. */
{
    double centerX, centerY, radX, radY, deltaX, deltaY;

    /*
     * First, see if oval is entirely inside rectangle or entirely outside
863
864
865
866
867
868
869
870
871
872
873

874
875
876
877
878
879
880
861
862
863
864
865
866
867

868
869

870
871
872
873
874
875
876
877







-


-
+







 *
 * Side effects:
 *	The boudn.
 *
 *--------------------------------------------------------------
 */

	/* ARGSUSED */
void
TkIncludePoint(
    register Tk_Item *itemPtr,	/* Item whose bounding box is being
    Tk_Item *itemPtr,	/* Item whose bounding box is being
				 * calculated. */
    double *pointPtr)		/* Address of two doubles giving x and y
				 * coordinates of point. */
{
    int tmp;

    tmp = (int) (pointPtr[0] + 0.5);
915
916
917
918
919
920
921
922

923
924
925
926
927
928
929
912
913
914
915
916
917
918

919
920
921
922
923
924
925
926







-
+








void
TkBezierScreenPoints(
    Tk_Canvas canvas,		/* Canvas in which curve is to be drawn. */
    double control[],		/* Array of coordinates for four control
				 * points: x0, y0, x1, y1, ... x3 y3. */
    int numSteps,		/* Number of curve points to generate. */
    register XPoint *xPointPtr)	/* Where to put new points. */
    XPoint *xPointPtr)	/* Where to put new points. */
{
    int i;
    double u, u2, u3, t, t2, t3;

    for (i = 1; i <= numSteps; i++, xPointPtr++) {
	t = ((double) i)/((double) numSteps);
	t2 = t*t;
961
962
963
964
965
966
967
968

969
970
971
972
973
974
975
958
959
960
961
962
963
964

965
966
967
968
969
970
971
972







-
+







 */

void
TkBezierPoints(
    double control[],		/* Array of coordinates for four control
				 * points: x0, y0, x1, y1, ... x3 y3. */
    int numSteps,		/* Number of curve points to generate. */
    register double *coordPtr)	/* Where to put new points. */
    double *coordPtr)	/* Where to put new points. */
{
    int i;
    double u, u2, u3, t, t2, t3;

    for (i = 1; i <= numSteps; i++, coordPtr += 2) {
	t = ((double) i)/((double) numSteps);
	t2 = t*t;
Changes to generic/tkUndo.c.
1
2
3
4
5
6
7


8
9
10
11
12
13
14
1
2
3
4
5


6
7
8
9
10
11
12
13
14





-
-
+
+







/*
 * 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.
 */

#include "tkInt.h"
#include "tkUndo.h"
90
91
92
93
94
95
96
97

98
99
100
101
102
103
104
90
91
92
93
94
95
96

97
98
99
100
101
102
103
104







-
+







int
TkUndoInsertSeparator(
    TkUndoAtom **stack)
{
    TkUndoAtom *separator;

    if (*stack!=NULL && (*stack)->type!=TK_UNDO_SEPARATOR) {
	separator = ckalloc(sizeof(TkUndoAtom));
	separator = (TkUndoAtom *)ckalloc(sizeof(TkUndoAtom));
	separator->type = TK_UNDO_SEPARATOR;
	TkUndoPushStack(stack,separator);
	return 1;
    }
    return 0;
}

177
178
179
180
181
182
183
184

185
186
187
188
189
190
191
177
178
179
180
181
182
183

184
185
186
187
188
189
190
191







-
+







TkUndoPushAction(
    TkUndoRedoStack *stack,	/* An Undo or Redo stack */
    TkUndoSubAtom *apply,
    TkUndoSubAtom *revert)
{
    TkUndoAtom *atom;

    atom = ckalloc(sizeof(TkUndoAtom));
    atom = (TkUndoAtom *)ckalloc(sizeof(TkUndoAtom));
    atom->type = TK_UNDO_ACTION;
    atom->apply = apply;
    atom->revert = revert;

    TkUndoPushStack(&stack->undoStack, atom);
    TkUndoClearStack(&stack->redoStack);
}
233
234
235
236
237
238
239
240

241
242
243
244
245
246
247
233
234
235
236
237
238
239

240
241
242
243
244
245
246
247







-
+







{
    TkUndoSubAtom *atom;

    if (command == NULL && actionScript == NULL) {
	Tcl_Panic("NULL command and actionScript in TkUndoMakeCmdSubAtom");
    }

    atom = ckalloc(sizeof(TkUndoSubAtom));
    atom = (TkUndoSubAtom *)ckalloc(sizeof(TkUndoSubAtom));
    atom->command = command;
    atom->funcPtr = NULL;
    atom->clientData = NULL;
    atom->next = NULL;
    atom->action = actionScript;
    if (atom->action != NULL) {
        Tcl_IncrRefCount(atom->action);
295
296
297
298
299
300
301
302

303
304
305
306
307
308
309
295
296
297
298
299
300
301

302
303
304
305
306
307
308
309







-
+







{
    TkUndoSubAtom *atom;

    if (funcPtr == NULL) {
	Tcl_Panic("NULL funcPtr in TkUndoMakeSubAtom");
    }

    atom = ckalloc(sizeof(TkUndoSubAtom));
    atom = (TkUndoSubAtom *)ckalloc(sizeof(TkUndoSubAtom));
    atom->command = NULL;
    atom->funcPtr = funcPtr;
    atom->clientData = clientData;
    atom->next = NULL;
    atom->action = actionScript;
    if (atom->action != NULL) {
        Tcl_IncrRefCount(atom->action);
337
338
339
340
341
342
343
344

345
346
347
348
349
350
351
337
338
339
340
341
342
343

344
345
346
347
348
349
350
351







-
+







TkUndoRedoStack *
TkUndoInitStack(
    Tcl_Interp *interp,		/* The interpreter */
    int maxdepth)		/* The maximum stack depth */
{
    TkUndoRedoStack *stack;	/* An Undo/Redo stack */

    stack = ckalloc(sizeof(TkUndoRedoStack));
    stack = (TkUndoRedoStack *)ckalloc(sizeof(TkUndoRedoStack));
    stack->undoStack = NULL;
    stack->redoStack = NULL;
    stack->interp = interp;
    stack->maxdepth = maxdepth;
    stack->depth = 0;
    return stack;
}
Changes to generic/tkUndo.h.
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







/*
 * 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.
 */

#ifndef _TKUNDO
#define _TKUNDO
Changes to generic/tkUtil.c.
1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15






-
-
+
+







/*
 * 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.
 */

#include "tkInt.h"

44
45
46
47
48
49
50
51

52
53
54

55
56
57
58
59
60
61

62
63
64
65
66
67
68
44
45
46
47
48
49
50

51
52
53

54
55
56
57
58
59


60
61
62
63
64
65
66
67







-
+


-
+





-
-
+







 *--------------------------------------------------------------
 */

int
TkStateParseProc(
    ClientData clientData,	/* some flags.*/
    Tcl_Interp *interp,		/* Used for reporting errors. */
    Tk_Window tkwin,		/* Window containing canvas widget. */
    TCL_UNUSED(Tk_Window),		/* Window containing canvas widget. */
    const char *value,		/* Value of option. */
    char *widgRec,		/* Pointer to record for item. */
    int offset)			/* Offset into item. */
    TkSizeT offset)			/* Offset into item. */
{
    int c;
    int flags = PTR2INT(clientData);
    size_t length;
    Tcl_Obj *msgObj;

    register Tk_State *statePtr = (Tk_State *) (widgRec + offset);
    Tk_State *statePtr = (Tk_State *) (widgRec + offset);

    if (value == NULL || *value == 0) {
	*statePtr = TK_STATE_NULL;
	return TCL_OK;
    }

    c = value[0];
122
123
124
125
126
127
128
129
130


131
132
133


134
135
136
137

138
139
140
141
142
143
144
121
122
123
124
125
126
127


128
129
130


131
132
133
134
135

136
137
138
139
140
141
142
143







-
-
+
+

-
-
+
+



-
+







 *	None.
 *
 *--------------------------------------------------------------
 */

const char *
TkStatePrintProc(
    ClientData clientData,	/* Ignored. */
    Tk_Window tkwin,		/* Window containing canvas widget. */
    TCL_UNUSED(void *),	/* Ignored. */
    TCL_UNUSED(Tk_Window),		/* Window containing canvas widget. */
    char *widgRec,		/* Pointer to record for item. */
    int offset,			/* Offset into item. */
    Tcl_FreeProc **freeProcPtr)	/* Pointer to variable to fill in with
    TkSizeT offset,			/* Offset into item. */
    TCL_UNUSED(Tcl_FreeProc **))	/* Pointer to variable to fill in with
				 * information about how to reclaim storage
				 * for return string. */
{
    register Tk_State *statePtr = (Tk_State *) (widgRec + offset);
    Tk_State *statePtr = (Tk_State *) (widgRec + offset);

    switch (*statePtr) {
    case TK_STATE_NORMAL:
	return "normal";
    case TK_STATE_DISABLED:
	return "disabled";
    case TK_STATE_HIDDEN:
166
167
168
169
170
171
172
173

174
175

176
177
178

179
180
181
182
183

184
185
186
187
188
189
190
165
166
167
168
169
170
171

172
173

174
175
176

177
178
179
180


181
182
183
184
185
186
187
188







-
+

-
+


-
+



-
-
+







 *	indicated in the value argument.
 *
 *--------------------------------------------------------------
 */

int
TkOrientParseProc(
    ClientData clientData,	/* some flags.*/
    TCL_UNUSED(void *),	/* some flags.*/
    Tcl_Interp *interp,		/* Used for reporting errors. */
    Tk_Window tkwin,		/* Window containing canvas widget. */
    TCL_UNUSED(Tk_Window),		/* Window containing canvas widget. */
    const char *value,		/* Value of option. */
    char *widgRec,		/* Pointer to record for item. */
    int offset)			/* Offset into item. */
    TkSizeT offset)			/* Offset into item. */
{
    int c;
    size_t length;

    register int *orientPtr = (int *) (widgRec + offset);
    int *orientPtr = (int *) (widgRec + offset);

    if (value == NULL || *value == 0) {
	*orientPtr = 0;
	return TCL_OK;
    }

    c = value[0];
225
226
227
228
229
230
231
232
233


234
235
236


237
238
239
240

241
242
243
244
245
246
247
223
224
225
226
227
228
229


230
231
232


233
234
235
236
237

238
239
240
241
242
243
244
245







-
-
+
+

-
-
+
+



-
+







 *	None.
 *
 *--------------------------------------------------------------
 */

const char *
TkOrientPrintProc(
    ClientData clientData,	/* Ignored. */
    Tk_Window tkwin,		/* Window containing canvas widget. */
    TCL_UNUSED(void *),	/* Ignored. */
    TCL_UNUSED(Tk_Window),		/* Window containing canvas widget. */
    char *widgRec,		/* Pointer to record for item. */
    int offset,			/* Offset into item. */
    Tcl_FreeProc **freeProcPtr)	/* Pointer to variable to fill in with
    TkSizeT offset,			/* Offset into item. */
    TCL_UNUSED(Tcl_FreeProc **))	/* Pointer to variable to fill in with
				 * information about how to reclaim storage
				 * for return string. */
{
    register int *statePtr = (int *) (widgRec + offset);
    int *statePtr = (int *) (widgRec + offset);

    if (*statePtr) {
	return "vertical";
    } else {
	return "horizontal";
    }
}
260
261
262
263
264
265
266
267

268
269
270
271
272
273
274
258
259
260
261
262
263
264

265
266
267
268
269
270
271
272







-
+







int
TkOffsetParseProc(
    ClientData clientData,	/* not used */
    Tcl_Interp *interp,		/* Interpreter to send results back to */
    Tk_Window tkwin,		/* Window on same display as tile */
    const char *value,		/* Name of image */
    char *widgRec,		/* Widget structure record */
    int offset)			/* Offset of tile in record */
    TkSizeT offset)			/* Offset of tile in record */
{
    Tk_TSOffset *offsetPtr = (Tk_TSOffset *) (widgRec + offset);
    Tk_TSOffset tsoffset;
    const char *q, *p;
    int result;
    Tcl_Obj *msgObj;

295
296
297
298
299
300
301

302
303
304
305
306
307
308
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307







+







	case 'n':
	    if (value[2]!='d' || value[3]!='\0') {
		goto badTSOffset;
	    }
	    tsoffset.flags = INT_MAX;
	    goto goodTSOffset;
	}
	break;
    case 'w':
	if (value[1] != '\0') {goto badTSOffset;}
	tsoffset.flags = TK_OFFSET_LEFT|TK_OFFSET_MIDDLE;
	goto goodTSOffset;
    case 'n':
	if ((value[1] != '\0') && (value[2] != '\0')) {
	    goto badTSOffset;
406
407
408
409
410
411
412
413
414


415
416

417
418
419
420
421
422
423
424
425
426

427
428
429
430
431
432
433
405
406
407
408
409
410
411


412
413
414

415
416
417
418
419
420
421
422
423
424

425
426
427
428
429
430
431
432







-
-
+
+

-
+









-
+







 *	The offset of the tile is returned.
 *
 *----------------------------------------------------------------------
 */

const char *
TkOffsetPrintProc(
    ClientData clientData,	/* not used */
    Tk_Window tkwin,		/* not used */
    TCL_UNUSED(void *),	/* not used */
    TCL_UNUSED(Tk_Window),		/* not used */
    char *widgRec,		/* Widget structure record */
    int offset,			/* Offset of tile in record */
    TkSizeT offset,			/* Offset of tile in record */
    Tcl_FreeProc **freeProcPtr)	/* not used */
{
    Tk_TSOffset *offsetPtr = (Tk_TSOffset *) (widgRec + offset);
    char *p, *q;

    if (offsetPtr->flags & TK_OFFSET_INDEX) {
	if (offsetPtr->flags >= INT_MAX) {
	    return "end";
	}
	p = ckalloc(32);
	p = (char *)ckalloc(32);
	sprintf(p, "%d", offsetPtr->flags & ~TK_OFFSET_INDEX);
	*freeProcPtr = TCL_DYNAMIC;
	return p;
    }
    if (offsetPtr->flags & TK_OFFSET_TOP) {
	if (offsetPtr->flags & TK_OFFSET_LEFT) {
	    return "nw";
449
450
451
452
453
454
455
456

457
458
459
460
461
462
463
448
449
450
451
452
453
454

455
456
457
458
459
460
461
462







-
+







	    return "sw";
	} else if (offsetPtr->flags & TK_OFFSET_CENTER) {
	    return "s";
	} else if (offsetPtr->flags & TK_OFFSET_RIGHT) {
	    return "se";
	}
    }
    q = p = ckalloc(32);
    q = p = (char *)ckalloc(32);
    if (offsetPtr->flags & TK_OFFSET_RELATIVE) {
	*q++ = '#';
    }
    sprintf(q, "%d,%d", offsetPtr->xoffset, offsetPtr->yoffset);
    *freeProcPtr = TCL_DYNAMIC;
    return p;
}
476
477
478
479
480
481
482
483

484
485
486
487
488
489
490
475
476
477
478
479
480
481

482
483
484
485
486
487
488
489







-
+







TkPixelParseProc(
    ClientData clientData,	/* If non-NULL, negative values are allowed as
				 * well. */
    Tcl_Interp *interp,		/* Interpreter to send results back to */
    Tk_Window tkwin,		/* Window on same display as tile */
    const char *value,		/* Name of image */
    char *widgRec,		/* Widget structure record */
    int offset)			/* Offset of tile in record */
    TkSizeT offset)			/* Offset of tile in record */
{
    double *doublePtr = (double *) (widgRec + offset);
    int result;

    result = TkGetDoublePixels(interp, tkwin, value, doublePtr);

    if ((result == TCL_OK) && (clientData == NULL) && (*doublePtr < 0.0)) {
507
508
509
510
511
512
513
514
515


516
517

518
519
520
521

522
523
524
525
526
527
528
506
507
508
509
510
511
512


513
514
515

516
517
518
519

520
521
522
523
524
525
526
527







-
-
+
+

-
+



-
+







 *	The name of the tile is returned.
 *
 *----------------------------------------------------------------------
 */

const char *
TkPixelPrintProc(
    ClientData clientData,	/* not used */
    Tk_Window tkwin,		/* not used */
    TCL_UNUSED(void *),	/* not used */
    TCL_UNUSED(Tk_Window),		/* not used */
    char *widgRec,		/* Widget structure record */
    int offset,			/* Offset of tile in record */
    TkSizeT offset,			/* Offset of tile in record */
    Tcl_FreeProc **freeProcPtr)	/* not used */
{
    double *doublePtr = (double *) (widgRec + offset);
    char *p = ckalloc(24);
    char *p = (char *)ckalloc(24);

    Tcl_PrintDouble(NULL, *doublePtr, p);
    *freeProcPtr = TCL_DYNAMIC;
    return p;
}

/*
661
662
663
664
665
666
667

668
669
670
671

672
673
674
675

676
677

678
679
680
681
682
683
684
685
686
687

688
689
690
691
692
693
694
660
661
662
663
664
665
666
667
668
669
670

671
672
673
674

675
676
677
678
679
680
681
682
683
684
685
686
687

688
689
690
691
692
693
694
695







+



-
+



-
+


+









-
+







	}
	if (Tcl_GetDouble(interp, argv[3], dblPtr) != TCL_OK) {
	    return TK_SCROLL_ERROR;
	}
	return TK_SCROLL_MOVETO;
    } else if ((c == 's')
	    && (strncmp(argv[2], "scroll", length) == 0)) {
	double d;
	if (argc != 5) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "wrong # args: should be \"%s %s %s\"",
		    argv[0], argv[1], "scroll number units|pages"));
		    argv[0], argv[1], "scroll number pages|units"));
	    Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", NULL);
	    return TK_SCROLL_ERROR;
	}
	if (Tcl_GetInt(interp, argv[3], intPtr) != TCL_OK) {
	if (Tcl_GetDouble(interp, argv[3], &d) != TCL_OK) {
	    return TK_SCROLL_ERROR;
	}
	*intPtr = (d > 0) ? ceil(d) : floor(d);
	length = strlen(argv[4]);
	c = argv[4][0];
	if ((c == 'p') && (strncmp(argv[4], "pages", length) == 0)) {
	    return TK_SCROLL_PAGES;
	} else if ((c == 'u') && (strncmp(argv[4], "units", length) == 0)) {
	    return TK_SCROLL_UNITS;
	}

	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"bad argument \"%s\": must be units or pages", argv[4]));
		"bad argument \"%s\": must be pages or units", argv[4]));
	Tcl_SetErrorCode(interp, "TK", "VALUE", "SCROLL_UNITS", NULL);
	return TK_SCROLL_ERROR;
    }
    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
	    "unknown option \"%s\": must be moveto or scroll", argv[2]));
    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "INDEX", "option", argv[2],
	    NULL);
725
726
727
728
729
730
731

732

733
734
735
736
737
738
739
740
741
742
743
744
745
746
747

748
749

750
751
752

753
754



755
756
757



758
759
760
761
762
763
764
765

766
767
768
769
770
771
772
726
727
728
729
730
731
732
733

734

735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750

751
752
753

754
755
756
757
758
759



760
761
762
763
764
765
766
767
768
769

770
771
772
773
774
775
776
777







+
-
+
-














+

-
+


-
+


+
+
+
-
-
-
+
+
+







-
+







    int objc,			/* # arguments for command. */
    Tcl_Obj *const objv[],	/* Arguments for command. */
    double *dblPtr,		/* Filled in with argument "moveto" option, if
				 * any. */
    int *intPtr)		/* Filled in with number of pages or lines to
				 * scroll, if any. */
{
    TkSizeT length;
    const char *arg = Tcl_GetString(objv[2]);
    const char *arg = TkGetStringFromObj(objv[2], &length);
    size_t length = objv[2]->length;

#define ArgPfxEq(str) \
	((arg[0] == str[0]) && !strncmp(arg, str, length))

    if (ArgPfxEq("moveto")) {
	if (objc != 4) {
	    Tcl_WrongNumArgs(interp, 2, objv, "moveto fraction");
	    return TK_SCROLL_ERROR;
	}
	if (Tcl_GetDoubleFromObj(interp, objv[3], dblPtr) != TCL_OK) {
	    return TK_SCROLL_ERROR;
	}
	return TK_SCROLL_MOVETO;
    } else if (ArgPfxEq("scroll")) {
	double d;
	if (objc != 5) {
	    Tcl_WrongNumArgs(interp, 2, objv, "scroll number units|pages");
	    Tcl_WrongNumArgs(interp, 2, objv, "scroll number pages|units");
	    return TK_SCROLL_ERROR;
	}
	if (Tcl_GetIntFromObj(interp, objv[3], intPtr) != TCL_OK) {
	if (Tcl_GetDoubleFromObj(interp, objv[3], &d) != TCL_OK) {
	    return TK_SCROLL_ERROR;
	}
	*intPtr = (d >= 0) ? ceil(d) : floor(d);
	if (dblPtr) {
	    *dblPtr = d;

	arg = Tcl_GetString(objv[4]);
	length = objv[4]->length;
	}

	arg = TkGetStringFromObj(objv[4], &length);
	if (ArgPfxEq("pages")) {
	    return TK_SCROLL_PAGES;
	} else if (ArgPfxEq("units")) {
	    return TK_SCROLL_UNITS;
	}

	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"bad argument \"%s\": must be units or pages", arg));
		"bad argument \"%s\": must be pages or units", arg));
	Tcl_SetErrorCode(interp, "TK", "VALUE", "SCROLL_UNITS", NULL);
	return TK_SCROLL_ERROR;
    }
    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
	    "unknown option \"%s\": must be moveto or scroll", arg));
    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "INDEX", "option", arg, NULL);
    return TK_SCROLL_ERROR;
1083
1084
1085
1086
1087
1088
1089
1090

1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107

1108
1109

1110
1111

1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128


1129
1130
1131
1132
1133
1134
1135

1136
1137
1138
1139
1140
1141
1142
1088
1089
1090
1091
1092
1093
1094

1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111

1112
1113

1114
1115

1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131


1132
1133
1134
1135
1136
1137
1138
1139

1140
1141
1142
1143
1144
1145
1146
1147







-
+
















-
+

-
+

-
+















-
-
+
+






-
+







 *
 *----------------------------------------------------------------------
 */

Tcl_Command
TkMakeEnsemble(
    Tcl_Interp *interp,
    const char *namespace,
    const char *namesp,
    const char *name,
    ClientData clientData,
    const TkEnsemble map[])
{
    Tcl_Namespace *namespacePtr = NULL;
    Tcl_Command ensemble = NULL;
    Tcl_Obj *dictObj = NULL, *nameObj;
    Tcl_DString ds;
    int i;

    if (map == NULL) {
	return NULL;
    }

    Tcl_DStringInit(&ds);

    namespacePtr = Tcl_FindNamespace(interp, namespace, NULL, 0);
    namespacePtr = Tcl_FindNamespace(interp, namesp, NULL, 0);
    if (namespacePtr == NULL) {
	namespacePtr = Tcl_CreateNamespace(interp, namespace, NULL, NULL);
	namespacePtr = Tcl_CreateNamespace(interp, namesp, NULL, NULL);
	if (namespacePtr == NULL) {
	    Tcl_Panic("failed to create namespace \"%s\"", namespace);
	    Tcl_Panic("failed to create namespace \"%s\"", namesp);
	}
    }

    nameObj = Tcl_NewStringObj(name, -1);
    ensemble = Tcl_FindEnsemble(interp, nameObj, 0);
    Tcl_DecrRefCount(nameObj);
    if (ensemble == NULL) {
	ensemble = Tcl_CreateEnsemble(interp, name, namespacePtr,
		TCL_ENSEMBLE_PREFIX);
	if (ensemble == NULL) {
	    Tcl_Panic("failed to create ensemble \"%s\"", name);
	}
    }

    Tcl_DStringSetLength(&ds, 0);
    Tcl_DStringAppend(&ds, namespace, -1);
    if (!(strlen(namespace) == 2 && namespace[1] == ':')) {
    Tcl_DStringAppend(&ds, namesp, -1);
    if (!(strlen(namesp) == 2 && namesp[1] == ':')) {
	Tcl_DStringAppend(&ds, "::", -1);
    }
    Tcl_DStringAppend(&ds, name, -1);

    dictObj = Tcl_NewObj();
    for (i = 0; map[i].name != NULL ; ++i) {
	Tcl_Obj *nameObj, *fqdnObj;
	Tcl_Obj *fqdnObj;

	nameObj = Tcl_NewStringObj(map[i].name, -1);
	fqdnObj = Tcl_NewStringObj(Tcl_DStringValue(&ds),
		Tcl_DStringLength(&ds));
	Tcl_AppendStringsToObj(fqdnObj, "::", map[i].name, NULL);
	Tcl_DictObjPut(NULL, dictObj, nameObj, fqdnObj);
	if (map[i].proc) {
1155
1156
1157
1158
1159
1160
1161
1162

1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175

1176
1177
1178
1179
1180
1181
1182
1160
1161
1162
1163
1164
1165
1166

1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179

1180
1181
1182
1183
1184
1185
1186
1187







-
+












-
+







    Tcl_DStringFree(&ds);
    return ensemble;
}

/*
 *----------------------------------------------------------------------
 *
 * TkSendVirtualEvent --
 * Tk_SendVirtualEvent --
 *
 * 	Send a virtual event notification to the specified target window.
 * 	Equivalent to:
 * 	    "event generate $target <<$eventName>> -data $detail"
 *
 * 	Note that we use Tk_QueueWindowEvent, not Tk_HandleEvent, so this
 * 	routine does not reenter the interpreter.
 *
 *----------------------------------------------------------------------
 */

void
TkSendVirtualEvent(
Tk_SendVirtualEvent(
    Tk_Window target,
    const char *eventName,
    Tcl_Obj *detail)
{
    union {XEvent general; XVirtualEvent virt;} event;

    memset(&event, 0, sizeof(event));
1207
1208
1209
1210
1211
1212
1213
1214

1215
1216
1217
1218
1219
1220
1221
1222
1223







1224
1225
1226
1227

1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243



1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255

1256
1257
1258
1259
1260
1261
1262
1263








































1264
1265
1266

1267
1268



1269
1270













1271
1272
1273
1274
1275
1276
1277
1212
1213
1214
1215
1216
1217
1218

1219
1220
1221
1222
1223
1224
1225
1226


1227
1228
1229
1230
1231
1232
1233
1234
1235
1236

1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251


1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265

1266
1267







1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307


1308
1309


1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334







-
+







-
-
+
+
+
+
+
+
+



-
+














-
-
+
+
+











-
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-

+
-
-
+
+
+


+
+
+
+
+
+
+
+
+
+
+
+
+







 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

int
size_t
TkUtfToUniChar(
    const char *src,	/* The UTF-8 string. */
    int *chPtr)		/* Filled with the Unicode value represented by
			 * the UTF-8 string. */
{
    Tcl_UniChar uniChar = 0;

    int len = Tcl_UtfToUniChar(src, &uniChar);
    if ((sizeof(Tcl_UniChar) == 2) && ((uniChar & 0xFC00) == 0xD800)) {
    size_t len = Tcl_UtfToUniChar(src, &uniChar);
    if ((sizeof(Tcl_UniChar) == 2)
	    && ((uniChar & 0xFC00) == 0xD800)
#if TCL_MAJOR_VERSION > 8
	    && (len == 1)
#endif
	) {
	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 */
	int len2 = Tcl_UtfToUniChar(src+len, &low);
	size_t len2 = Tcl_UtfToUniChar(src+len, &low);
	if ((low & 0xFC00) == 0xDC00) {
	    *chPtr = (((uniChar & 0x3FF) << 10) | (low & 0x3FF)) + 0x10000;
	    return len + len2;
	}
    }
    *chPtr = uniChar;
    return len;
}

/*
 *---------------------------------------------------------------------------
 *
 * TkUniCharToUtf --
 *
 *	Almost the same as Tcl_UniCharToUtf but producing 4-byte UTF-8
 *	sequences even when TCL_UTF_MAX==3. So, up to 4 bytes might be produced.
 *	Almost the same as Tcl_UniCharToUtf but producing 2 x 3-byte UTF-8
 *	sequences for out-of-bmp characters when TCL_UTF_MAX==3.
 *	So, up to 6 bytes might be produced.
 *
 * Results:
 *	*buf is filled with the UTF-8 string, and the return value is the
 *	number of bytes produced.
 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

int TkUniCharToUtf(int ch, char *buf)
size_t TkUniCharToUtf(int ch, char *buf)
{
    if (((unsigned)(ch - 0x10000) <= 0xFFFFF)) {
	/* Spit out a 4-byte UTF-8 character */
	*buf++ = (char) ((ch >> 18) | 0xF0);
	*buf++ = (char) (((ch >> 12) | 0x80) & 0xBF);
	*buf++ = (char) (((ch >> 6) | 0x80) & 0xBF);
	*buf = (char) ((ch | 0x80) & 0xBF);
	return 4;
    if ((sizeof(Tcl_UniChar) == 2) && (((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;
    } else {
	return Tcl_UniCharToUtf(ch, buf);
    }
#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 */

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Changes to generic/tkVisual.c.
1
2
3
4
5
6
7
8
9


10
11
12
13
14
15
16
17
18
19
20
21
22
23
24


25
26

27
28
29
30
31
32
33
34
35
36
37
38

39
40
41
42
43
44
45
46
47
48
49

50
51
52
53
54
55
56
1
2
3
4
5
6
7


8
9
10
11
12
13
14
15
16
17
18
19
20
21
22


23
24
25

26
27
28
29
30
31
32
33
34
35
36
37

38
39
40
41
42
43
44
45
46
47
48

49
50
51
52
53
54
55
56







-
-
+
+













-
-
+
+

-
+











-
+










-
+







/*
 * tkVisual.c --
 *
 *	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.
 */

#include "tkInt.h"

/*
 * The table below maps from symbolic names for visual classes to the
 * associated X class symbols.
 */

typedef struct VisualDictionary {
    const char *name;		/* Textual name of class. */
    int minLength;		/* Minimum # characters that must be specified
    char name[12];		/* Textual name of class. */
    unsigned short minLength;		/* Minimum # characters that must be specified
				 * for an unambiguous match. */
    int c_class;			/* X symbol for class. */
    short c_class;			/* X symbol for class. */
} VisualDictionary;
static const VisualDictionary visualNames[] = {
    {"best",		1,	0},
    {"directcolor",	2,	DirectColor},
    {"grayscale",	1,	GrayScale},
    {"greyscale",	1,	GrayScale},
    {"pseudocolor",	1,	PseudoColor},
    {"staticcolor",	7,	StaticColor},
    {"staticgray",	7,	StaticGray},
    {"staticgrey",	7,	StaticGray},
    {"truecolor",	1,	TrueColor},
    {NULL,		0,	0},
    {"",		0,	0},
};

/*
 * One of the following structures exists for each distinct non-default
 * colormap allocated for a display by Tk_GetColormap.
 */

struct TkColormap {
    Colormap colormap;		/* X's identifier for the colormap. */
    Visual *visual;		/* Visual for which colormap was allocated. */
    int refCount;		/* How many uses of the colormap are still
    size_t refCount;		/* How many uses of the colormap are still
				 * outstanding (calls to Tk_GetColormap minus
				 * calls to Tk_FreeColormap). */
    int shareable;		/* 0 means this colormap was allocated by a
				 * call to Tk_GetColormap with "new", implying
				 * that the window wants it all for itself.  1
				 * means that the colormap was allocated as a
				 * default for a particular visual, so it can
92
93
94
95
96
97
98
99

100
101
102

103
104
105
106
107
108
109
92
93
94
95
96
97
98

99
100
101

102
103
104
105
106
107
108
109







-
+


-
+







				 * here. */
    Colormap *colormapPtr)	/* If non-NULL, then a suitable colormap for
				 * visual is placed here. This colormap must
				 * eventually be freed by calling
				 * Tk_FreeColormap. */
{
    Tk_Window tkwin2;
    XVisualInfo template, *visInfoList, *bestPtr;
    XVisualInfo templ, *visInfoList, *bestPtr;
    long mask;
    Visual *visual;
    ptrdiff_t length;
    size_t length;
    int c, numVisuals, prio, bestPrio, i;
    const char *p;
    const VisualDictionary *dictPtr;
    TkColormap *cmapPtr;
    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;

    /*
133
134
135
136
137
138
139
140

141
142
143
144
145
146
147
148
149
150
151
152
153







154
155
156
157
158
159
160
133
134
135
136
137
138
139

140
141
142
143
144
145
146







147
148
149
150
151
152
153
154
155
156
157
158
159
160







-
+






-
-
-
-
-
-
-
+
+
+
+
+
+
+







		 * allocated here).
		 */

		*colormapPtr = Tk_Colormap(tkwin2);
		for (cmapPtr = dispPtr->cmapPtr; cmapPtr != NULL;
			cmapPtr = cmapPtr->nextPtr) {
		    if (cmapPtr->colormap == *colormapPtr) {
			cmapPtr->refCount += 1;
			cmapPtr->refCount++;
			break;
		    }
		}
	    }
	    return visual;
	}
	template.depth = Tk_Depth(tkwin2);
	template.c_class = visual->c_class;
	template.red_mask = visual->red_mask;
	template.green_mask = visual->green_mask;
	template.blue_mask = visual->blue_mask;
	template.colormap_size = visual->map_entries;
	template.bits_per_rgb = visual->bits_per_rgb;
	templ.depth = Tk_Depth(tkwin2);
	templ.c_class = visual->c_class;
	templ.red_mask = visual->red_mask;
	templ.green_mask = visual->green_mask;
	templ.blue_mask = visual->blue_mask;
	templ.colormap_size = visual->map_entries;
	templ.bits_per_rgb = visual->bits_per_rgb;
	mask = VisualDepthMask|VisualClassMask|VisualRedMaskMask
		|VisualGreenMaskMask|VisualBlueMaskMask|VisualColormapSizeMask
		|VisualBitsPerRGBMask;
    } else if ((c == 0) || ((c == 'd') && (string[1] != 0)
	    && (strncmp(string, "default", strlen(string)) == 0))) {
	/*
	 * Use the default visual for the window's screen.
174
175
176
177
178
179
180
181

182
183
184
185
186
187
188
189
190
191
192
193
194
195
196


197
198

199
200

201
202
203
204

205
206
207
208
209

210
211
212
213
214
215
216
217
218
219
220
221
222


223
224
225
226
227
228
229
230
231
232
233
234
235
236
237

238
239

240
241
242
243
244
245
246
174
175
176
177
178
179
180

181
182
183
184
185
186
187
188
189
190
191
192
193
194


195
196
197

198


199
200
201
202

203
204
205
206
207

208
209
210
211
212
213
214
215
216
217
218
219


220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235

236
237

238
239
240
241
242
243
244
245







-
+













-
-
+
+

-
+
-
-
+



-
+




-
+











-
-
+
+














-
+

-
+








	if (Tcl_GetInt(interp, string, &visualId) == TCL_ERROR) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "bad X identifier for visual: \"%s\"", string));
	    Tcl_SetErrorCode(interp, "TK", "VALUE", "VISUALID", NULL);
	    return NULL;
	}
	template.visualid = visualId;
	templ.visualid = visualId;
	mask = VisualIDMask;
    } else {
	/*
	 * Parse the string into a class name (or "best") optionally followed
	 * by whitespace and a depth.
	 */

	for (p = string; *p != 0; p++) {
	    if (isspace(UCHAR(*p)) || isdigit(UCHAR(*p))) {
		break;
	    }
	}
	length = p - string;
	template.c_class = -1;
	for (dictPtr = visualNames; dictPtr->name != NULL; dictPtr++) {
	templ.c_class = -1;
	for (dictPtr = visualNames; dictPtr->minLength; dictPtr++) {
	    if ((dictPtr->name[0] == c) && (length >= dictPtr->minLength)
		    && (strncmp(string, dictPtr->name,
		    && (strncmp(string, dictPtr->name, length) == 0)) {
		    (size_t) length) == 0)) {
		template.c_class = dictPtr->c_class;
		templ.c_class = dictPtr->c_class;
		break;
	    }
	}
	if (template.c_class == -1) {
	if (templ.c_class == -1) {
	    Tcl_Obj *msgObj = Tcl_ObjPrintf(
		    "unknown or ambiguous visual name \"%s\": class must be ",
		    string);

	    for (dictPtr = visualNames; dictPtr->name != NULL; dictPtr++) {
	    for (dictPtr = visualNames; dictPtr->minLength; dictPtr++) {
		Tcl_AppendPrintfToObj(msgObj, "%s, ", dictPtr->name);
	    }
	    Tcl_AppendToObj(msgObj, "or default", -1);
	    Tcl_SetObjResult(interp, msgObj);
	    Tcl_SetErrorCode(interp, "TK", "LOOKUP", "VISUAL", string, NULL);
	    return NULL;
	}
	while (isspace(UCHAR(*p))) {
	    p++;
	}
	if (*p == 0) {
	    template.depth = 10000;
	} else if (Tcl_GetInt(interp, p, &template.depth) != TCL_OK) {
	    templ.depth = 10000;
	} else if (Tcl_GetInt(interp, p, &templ.depth) != TCL_OK) {
	    return NULL;
	}
	if (c == 'b') {
	    mask = 0;
	} else {
	    mask = VisualClassMask;
	}
    }

    /*
     * Find all visuals that match the template we've just created, and return
     * an error if there are none that match.
     */

    template.screen = Tk_ScreenNumber(tkwin);
    templ.screen = Tk_ScreenNumber(tkwin);
    mask |= VisualScreenMask;
    visInfoList = XGetVisualInfo(Tk_Display(tkwin), mask, &template,
    visInfoList = XGetVisualInfo(Tk_Display(tkwin), mask, &templ,
	    &numVisuals);
    if (visInfoList == NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"couldn't find an appropriate visual", -1));
	Tcl_SetErrorCode(interp, "TK", "VISUAL", "INAPPROPRIATE", NULL);
	return NULL;
    }
282
283
284
285
286
287
288
289

290
291
292
293

294
295
296
297
298
299
300
281
282
283
284
285
286
287

288
289
290
291

292
293
294
295
296
297
298
299







-
+



-
+







		== DefaultVisualOfScreen(Tk_Screen(tkwin))) {
	    prio++;
	}
	if (bestPtr == NULL) {
	    goto newBest;
	}
	if (visInfoList[i].depth < bestPtr->depth) {
	    if (visInfoList[i].depth >= template.depth) {
	    if (visInfoList[i].depth >= templ.depth) {
		goto newBest;
	    }
	} else if (visInfoList[i].depth > bestPtr->depth) {
	    if (bestPtr->depth < template.depth) {
	    if (bestPtr->depth < templ.depth) {
		goto newBest;
	    }
	} else {
	    if (prio > bestPrio) {
		goto newBest;
	    }
	}
320
321
322
323
324
325
326
327

328
329
330
331

332
333
334
335
336
337
338
319
320
321
322
323
324
325

326
327
328
329

330
331
332
333
334
335
336
337







-
+



-
+







	if (visual == DefaultVisualOfScreen(Tk_Screen(tkwin))) {
	    *colormapPtr = DefaultColormapOfScreen(Tk_Screen(tkwin));
	} else {
	    for (cmapPtr = dispPtr->cmapPtr; cmapPtr != NULL;
		    cmapPtr = cmapPtr->nextPtr) {
		if (cmapPtr->shareable && (cmapPtr->visual == visual)) {
		    *colormapPtr = cmapPtr->colormap;
		    cmapPtr->refCount += 1;
		    cmapPtr->refCount++;
		    goto done;
		}
	    }
	    cmapPtr = ckalloc(sizeof(TkColormap));
	    cmapPtr = (TkColormap *)ckalloc(sizeof(TkColormap));
	    cmapPtr->colormap = XCreateColormap(Tk_Display(tkwin),
		    RootWindowOfScreen(Tk_Screen(tkwin)), visual,
		    AllocNone);
	    cmapPtr->visual = visual;
	    cmapPtr->refCount = 1;
	    cmapPtr->shareable = 1;
	    cmapPtr->nextPtr = dispPtr->cmapPtr;
379
380
381
382
383
384
385
386

387
388
389
390
391
392
393
378
379
380
381
382
383
384

385
386
387
388
389
390
391
392







-
+







    Tk_Window other;

    /*
     * Allocate a new colormap, if that's what is wanted.
     */

    if (strcmp(string, "new") == 0) {
	cmapPtr = ckalloc(sizeof(TkColormap));
	cmapPtr = (TkColormap *)ckalloc(sizeof(TkColormap));
	cmapPtr->colormap = XCreateColormap(Tk_Display(tkwin),
		RootWindowOfScreen(Tk_Screen(tkwin)), Tk_Visual(tkwin),
		AllocNone);
	cmapPtr->visual = Tk_Visual(tkwin);
	cmapPtr->refCount = 1;
	cmapPtr->shareable = 0;
	cmapPtr->nextPtr = dispPtr->cmapPtr;
423
424
425
426
427
428
429
430

431
432
433
434
435
436
437
422
423
424
425
426
427
428

429
430
431
432
433
434
435
436







-
+







     * If the colormap was a special one allocated by code in this file,
     * increment its reference count.
     */

    for (cmapPtr = dispPtr->cmapPtr; cmapPtr != NULL;
	    cmapPtr = cmapPtr->nextPtr) {
	if (cmapPtr->colormap == colormap) {
	    cmapPtr->refCount += 1;
	    cmapPtr->refCount++;
	}
    }
    return colormap;
}

/*
 *----------------------------------------------------------------------
472
473
474
475
476
477
478
479
480

481
482
483
484
485
486
487
471
472
473
474
475
476
477


478
479
480
481
482
483
484
485







-
-
+







    dispPtr = TkGetDisplay(display);
    if (dispPtr == NULL) {
	Tcl_Panic("unknown display passed to Tk_FreeColormap");
    }
    for (prevPtr = NULL, cmapPtr = dispPtr->cmapPtr; cmapPtr != NULL;
	    prevPtr = cmapPtr, cmapPtr = cmapPtr->nextPtr) {
	if (cmapPtr->colormap == colormap) {
	    cmapPtr->refCount -= 1;
	    if (cmapPtr->refCount == 0) {
	    if (cmapPtr->refCount-- <= 1) {
		XFreeColormap(display, colormap);
		if (prevPtr == NULL) {
		    dispPtr->cmapPtr = cmapPtr->nextPtr;
		} else {
		    prevPtr->nextPtr = cmapPtr->nextPtr;
		}
		ckfree(cmapPtr);
530
531
532
533
534
535
536
537

538
539
540
541
542
543
544
545
546
547
548
549
528
529
530
531
532
533
534

535
536
537
538
539
540
541
542
543
544
545
546
547







-
+












    dispPtr = TkGetDisplay(display);
    if (dispPtr == NULL) {
	Tcl_Panic("unknown display passed to Tk_PreserveColormap");
    }
    for (cmapPtr = dispPtr->cmapPtr; cmapPtr != NULL;
	    cmapPtr = cmapPtr->nextPtr) {
	if (cmapPtr->colormap == colormap) {
	    cmapPtr->refCount += 1;
	    cmapPtr->refCount++;
	    return;
	}
    }
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Changes to generic/tkWindow.c.
1
2
3
4
5
6
7
8
9


10
11
12
13
14
15
16

17
18
19
20
21
22
23
1
2
3
4
5
6
7


8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
23







-
-
+
+






-
+







/*
 * tkWindow.c --
 *
 *	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.
 */

#include "tkInt.h"

#include "tkPort.h"
#ifdef _WIN32
#include "tkWinInt.h"
#elif !defined(MAC_OSX_TK)
#include "tkUnixInt.h"
#endif

/*
120
121
122
123
124
125
126
127

128
129
130
131
132
133
134
120
121
122
123
124
125
126

127
128
129
130
131
132
133
134







-
+







    {"image",		Tk_ImageObjCmd,		PASSMAINWINDOW|ISSAFE},
    {"lower",		Tk_LowerObjCmd,		PASSMAINWINDOW|ISSAFE},
    {"option",		Tk_OptionObjCmd,	PASSMAINWINDOW|ISSAFE},
    {"pack",		Tk_PackObjCmd,		PASSMAINWINDOW|ISSAFE},
    {"place",		Tk_PlaceObjCmd,		PASSMAINWINDOW|ISSAFE},
    {"raise",		Tk_RaiseObjCmd,		PASSMAINWINDOW|ISSAFE},
    {"selection",	Tk_SelectionObjCmd,	PASSMAINWINDOW},
    {"tk",		(Tcl_ObjCmdProc *) TkInitTkCmd,  USEINITPROC|PASSMAINWINDOW|ISSAFE},
    {"tk",		(Tcl_ObjCmdProc *)(void *)TkInitTkCmd,  USEINITPROC|PASSMAINWINDOW|ISSAFE},
    {"tkwait",		Tk_TkwaitObjCmd,	PASSMAINWINDOW|ISSAFE},
    {"update",		Tk_UpdateObjCmd,	PASSMAINWINDOW|ISSAFE},
    {"winfo",		Tk_WinfoObjCmd,		PASSMAINWINDOW|ISSAFE},
    {"wm",		Tk_WmObjCmd,		PASSMAINWINDOW},

    /*
     * Default widget class commands.
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
235
236
237
238
239
240
241


242
243
244
245
246
247
248







-
-








static void
TkCloseDisplay(
    TkDisplay *dispPtr)
{
    TkClipCleanup(dispPtr);

    TkpCancelWarp(dispPtr);

    if (dispPtr->name != NULL) {
	ckfree(dispPtr->name);
    }

    if (dispPtr->atomInit) {
	Tcl_DeleteHashTable(&dispPtr->nameTable);
	Tcl_DeleteHashTable(&dispPtr->atomTable);
312
313
314
315
316
317
318
319
320


321
322

323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338

339
340
341

342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
310
311
312
313
314
315
316


317
318
319

320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359

360

361
362
363
364
365
366
367







-
-
+
+

-
+
















+



+


















-

-







    const char *screenName,	/* Name of screen on which to create window.
				 * NULL means use DISPLAY environment variable
				 * to determine. Empty string means use
				 * parent's screen, or DISPLAY if no
				 * parent. */
    unsigned int flags)		/* Additional flags to set on the window. */
{
    register TkWindow *winPtr;
    register TkDisplay *dispPtr;
    TkWindow *winPtr;
    TkDisplay *dispPtr;
    int screenId;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (!tsdPtr->initialized) {
	tsdPtr->initialized = 1;

	/*
	 * Create built-in image types.
	 */

	Tk_CreateImageType(&tkBitmapImageType);
	Tk_CreateImageType(&tkPhotoImageType);

	/*
	 * Create built-in photo image formats.
	 */

        Tk_CreatePhotoImageFormat(&tkImgFmtDefault);
	Tk_CreatePhotoImageFormat(&tkImgFmtGIF);
	Tk_CreatePhotoImageFormat(&tkImgFmtPNG);
	Tk_CreatePhotoImageFormat(&tkImgFmtPPM);
	Tk_CreatePhotoImageFormat(&tkImgFmtSVGnano);
    }

    if ((parent != NULL) && (screenName != NULL) && (screenName[0] == '\0')) {
	dispPtr = ((TkWindow *) parent)->dispPtr;
	screenId = Tk_ScreenNumber(parent);
    } else {
	dispPtr = GetScreen(interp, screenName, &screenId);
	if (dispPtr == NULL) {
	    return NULL;
	}
    }

    winPtr = TkAllocWindow(dispPtr, screenId, (TkWindow *) parent);

    /*
     * Set the flags specified in the call.
     */

#ifdef TK_USE_INPUT_METHODS
    winPtr->ximGeneration = 0;
#endif /*TK_USE_INPUT_METHODS*/
    winPtr->flags |= flags;

    /*
     * Force the window to use a border pixel instead of border pixmap. This
     * is needed for the case where the window doesn't use the default visual.
     * In this case, the default border is a pixmap inherited from the root
     * window, which won't work because it will have the wrong visual.
415
416
417
418
419
420
421
422

423
424
425
426

427
428
429
430
431
432
433
413
414
415
416
417
418
419

420
421
422
423

424
425
426
427
428
429
430
431







-
+



-
+







static TkDisplay *
GetScreen(
    Tcl_Interp *interp,		/* Place to leave error message. */
    const char *screenName,	/* Name for screen. NULL or empty means use
				 * DISPLAY envariable. */
    int *screenPtr)		/* Where to store screen number. */
{
    register TkDisplay *dispPtr;
    TkDisplay *dispPtr;
    const char *p;
    int screenId;
    size_t length;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    /*
     * Separate the screen number from the rest of the display name.
     * ScreenName is assumed to have the syntax <display>.<screen> with the
     * dot and the screen being optional.
     */
483
484
485
486
487
488
489
490

491
492
493
494
495
496
497
481
482
483
484
485
486
487

488
489
490
491
492
493
494
495







-
+







	     * Tk_QueueWindowEvent.
	     */

	    dispPtr->flags |= TK_DISPLAY_COLLAPSE_MOTION_EVENTS;

	    Tcl_InitHashTable(&dispPtr->winTable, TCL_ONE_WORD_KEYS);

	    dispPtr->name = ckalloc(length + 1);
	    dispPtr->name = (char *)ckalloc(length + 1);
	    strncpy(dispPtr->name, screenName, length);
	    dispPtr->name[length] = '\0';
	    break;
	}
	if ((strncmp(dispPtr->name, screenName, length) == 0)
		&& (dispPtr->name[length] == '\0')) {
	    break;
526
527
528
529
530
531
532
533

534
535
536
537
538
539
540
524
525
526
527
528
529
530

531
532
533
534
535
536
537
538







-
+







 */

TkDisplay *
TkGetDisplay(
    Display *display)		/* X's display pointer */
{
    TkDisplay *dispPtr;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    for (dispPtr = tsdPtr->displayList; dispPtr != NULL;
	    dispPtr = dispPtr->nextPtr) {
	if (dispPtr->display == display) {
	    break;
	}
559
560
561
562
563
564
565
566

567
568
569
570
571
572
573
557
558
559
560
561
562
563

564
565
566
567
568
569
570
571







-
+







 *
 *--------------------------------------------------------------
 */

TkDisplay *
TkGetDisplayList(void)
{
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    return tsdPtr->displayList;
}

/*
 *--------------------------------------------------------------
586
587
588
589
590
591
592
593

594
595
596
597
598
599
600
584
585
586
587
588
589
590

591
592
593
594
595
596
597
598







-
+







 *
 *--------------------------------------------------------------
 */

TkMainInfo *
TkGetMainInfoList(void)
{
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    return tsdPtr->mainWindowList;
}
/*
 *--------------------------------------------------------------
 *
616
617
618
619
620
621
622
623

624
625
626
627
628
629
630
614
615
616
617
618
619
620

621
622
623
624
625
626
627
628







-
+







TkAllocWindow(
    TkDisplay *dispPtr,		/* Display associated with new window. */
    int screenNum,		/* Index of screen for new window. */
    TkWindow *parentPtr)	/* Parent from which this window should
				 * inherit visual information. NULL means use
				 * screen defaults instead of inheriting. */
{
    register TkWindow *winPtr = ckalloc(sizeof(TkWindow));
    TkWindow *winPtr = (TkWindow *)ckalloc(sizeof(TkWindow));

    winPtr->display = dispPtr->display;
    winPtr->dispPtr = dispPtr;
    winPtr->screenNum = screenNum;
    if ((parentPtr != NULL) && (parentPtr->display == winPtr->display)
	    && (parentPtr->screenNum == winPtr->screenNum)) {
	winPtr->visual = parentPtr->visual;
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
648
649
650
651
652
653
654

655
656

657
658
659
660
661
662
663







-


-







	winPtr->atts.colormap = parentPtr->atts.colormap;
    } else {
	winPtr->atts.colormap = DefaultColormap(dispPtr->display, screenNum);
    }
    winPtr->dirtyAtts = CWEventMask|CWColormap|CWBitGravity;
    winPtr->flags = 0;
    winPtr->handlerList = NULL;
#ifdef TK_USE_INPUT_METHODS
    winPtr->ximGeneration = 0;
    winPtr->inputContext = NULL;
#endif /* TK_USE_INPUT_METHODS */
    winPtr->tagPtr = NULL;
    winPtr->numTags = 0;
    winPtr->optionLevel = -1;
    winPtr->selHandlerList = NULL;
    winPtr->geomMgrPtr = NULL;
    winPtr->geomData = NULL;
    winPtr->geomMgrName = NULL;
697
698
699
700
701
702
703
704

705
706
707
708
709
710
711
693
694
695
696
697
698
699

700
701
702
703
704
705
706
707







-
+







 *
 *----------------------------------------------------------------------
 */

static int
NameWindow(
    Tcl_Interp *interp,		/* Interpreter to use for error reporting. */
    register TkWindow *winPtr,	/* Window that is to be named and inserted. */
    TkWindow *winPtr,	/* Window that is to be named and inserted. */
    TkWindow *parentPtr,	/* Pointer to logical parent for winPtr (used
				 * for naming, options, etc.). */
    const char *name)		/* Name for winPtr; must be unique among
				 * parentPtr's children. */
{
#define FIXED_SIZE 200
    char staticSpace[FIXED_SIZE];
767
768
769
770
771
772
773
774

775
776
777
778
779
780
781
763
764
765
766
767
768
769

770
771
772
773
774
775
776
777







-
+







     */

    length1 = strlen(parentPtr->pathName);
    length2 = strlen(name);
    if ((length1 + length2 + 2) <= FIXED_SIZE) {
	pathName = staticSpace;
    } else {
	pathName = ckalloc(length1 + length2 + 2);
	pathName = (char *)ckalloc(length1 + length2 + 2);
    }
    if (length1 == 1) {
	pathName[0] = '.';
	strcpy(pathName+1, name);
    } else {
	strcpy(pathName, parentPtr->pathName);
	pathName[length1] = '.';
789
790
791
792
793
794
795
796

797
798
799
800
801
802
803
785
786
787
788
789
790
791

792
793
794
795
796
797
798
799







-
+







    if (!isNew) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"window name \"%s\" already exists in parent", name));
	Tcl_SetErrorCode(interp, "TK", "VALUE", "WINDOW", "EXISTS", NULL);
	return TCL_ERROR;
    }
    Tcl_SetHashValue(hPtr, winPtr);
    winPtr->pathName = Tcl_GetHashKey(&parentPtr->mainPtr->nameTable, hPtr);
    winPtr->pathName = (char *)Tcl_GetHashKey(&parentPtr->mainPtr->nameTable, hPtr);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TkCreateMainWindow --
828
829
830
831
832
833
834
835
836
837



838
839

840
841
842
843
844
845
846
824
825
826
827
828
829
830



831
832
833
834

835
836
837
838
839
840
841
842







-
-
-
+
+
+

-
+







				 * environment variable. */
    const char *baseName)	/* Base name for application; usually of the
				 * form "prog instance". */
{
    Tk_Window tkwin;
    int dummy, isSafe;
    Tcl_HashEntry *hPtr;
    register TkMainInfo *mainPtr;
    register TkWindow *winPtr;
    register const TkCmd *cmdPtr;
    TkMainInfo *mainPtr;
    TkWindow *winPtr;
    const TkCmd *cmdPtr;
    ClientData clientData;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    /*
     * Panic if someone updated the TkWindow structure without also updating
     * the Tk_FakeWin structure (or vice versa).
     */

860
861
862
863
864
865
866
867

868
869
870
871
872
873
874
856
857
858
859
860
861
862

863
864
865
866
867
868
869
870







-
+








    /*
     * Create the TkMainInfo structure for this application, and set up
     * name-related information for the new window.
     */

    winPtr = (TkWindow *) tkwin;
    mainPtr = ckalloc(sizeof(TkMainInfo));
    mainPtr = (TkMainInfo *)ckalloc(sizeof(TkMainInfo));
    mainPtr->winPtr = winPtr;
    mainPtr->refCount = 1;
    mainPtr->interp = interp;
    Tcl_InitHashTable(&mainPtr->nameTable, TCL_STRING_KEYS);
    mainPtr->deletionEpoch = 0l;
    TkEventInit();
    TkBindInit(mainPtr);
893
894
895
896
897
898
899
900

901
902
903
904
905
906
907
889
890
891
892
893
894
895

896
897
898
899
900
901
902
903







-
+







	Tcl_ResetResult(interp);
    }
    mainPtr->nextPtr = tsdPtr->mainWindowList;
    tsdPtr->mainWindowList = mainPtr;
    winPtr->mainPtr = mainPtr;
    hPtr = Tcl_CreateHashEntry(&mainPtr->nameTable, ".", &dummy);
    Tcl_SetHashValue(hPtr, winPtr);
    winPtr->pathName = Tcl_GetHashKey(&mainPtr->nameTable, hPtr);
    winPtr->pathName = (char *)Tcl_GetHashKey(&mainPtr->nameTable, hPtr);
    Tcl_InitHashTable(&mainPtr->busyTable, TCL_ONE_WORD_KEYS);

    /*
     * We have just created another Tk application; increment the refcount on
     * the display pointer.
     */

935
936
937
938
939
940
941
942

943
944
945
946
947
948
949
950
951
952
953

954
955
956
957
958
959
960
931
932
933
934
935
936
937

938
939
940
941
942
943
944
945
946
947
948

949
950
951
952
953
954
955
956







-
+










-
+








	if (cmdPtr->flags & PASSMAINWINDOW) {
	    clientData = tkwin;
	} else {
	    clientData = NULL;
	}
	if (cmdPtr->flags & USEINITPROC) {
	    ((TkInitProc *) cmdPtr->objProc)(interp, clientData);
	    ((TkInitProc *)(void *)cmdPtr->objProc)(interp, clientData);
	} else {
	    Tcl_CreateObjCommand(interp, cmdPtr->name, cmdPtr->objProc,
		    clientData, NULL);
	}
	if (isSafe && !(cmdPtr->flags & ISSAFE)) {
	    Tcl_HideCommand(interp, cmdPtr->name, cmdPtr->name);
	}
    }

    /*
     * Set variables for the intepreter.
     * Set variables for the interpreter.
     */

    Tcl_SetVar2(interp, "tk_patchLevel", NULL, TK_PATCH_LEVEL, TCL_GLOBAL_ONLY);
    Tcl_SetVar2(interp, "tk_version",    NULL, TK_VERSION,     TCL_GLOBAL_ONLY);

    tsdPtr->numMainWindows++;
    return tkwin;
1132
1133
1134
1135
1136
1137
1138
1139

1140
1141
1142
1143
1144
1145
1146
1147
1148
1149

1150
1151
1152
1153
1154
1155
1156

1157
1158

1159
1160
1161
1162
1163
1164
1165
1166

1167
1168
1169
1170
1171
1172
1173
1128
1129
1130
1131
1132
1133
1134

1135
1136
1137
1138
1139
1140
1141
1142
1143
1144

1145
1146
1147
1148
1149
1150
1151

1152
1153

1154
1155
1156
1157
1158
1159
1160
1161

1162
1163
1164
1165
1166
1167
1168
1169







-
+









-
+






-
+

-
+







-
+







				 * screen on which to create new window;
				 * window will be a top-level window. */
{
#define FIXED_SPACE 5
    char fixedSpace[FIXED_SPACE+1];
    char *p;
    Tk_Window parent;
    int numChars;
    size_t numChars;

    /*
     * Strip the parent's name out of pathName (it's everything up to the last
     * dot). There are two tricky parts: (a) must copy the parent's name
     * somewhere else to avoid modifying the pathName string (for large names,
     * space for the copy will have to be malloc'ed); (b) must special-case
     * the situation where the parent is ".".
     */

    p = strrchr(pathName, '.');
    p = (char *)strrchr(pathName, '.');
    if (p == NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"bad window path name \"%s\"", pathName));
	Tcl_SetErrorCode(interp, "TK", "VALUE", "WINDOW_PATH", NULL);
	return NULL;
    }
    numChars = (int) (p-pathName);
    numChars = p-pathName;
    if (numChars > FIXED_SPACE) {
	p = ckalloc(numChars + 1);
	p = (char *)ckalloc(numChars + 1);
    } else {
	p = fixedSpace;
    }
    if (numChars == 0) {
	*p = '.';
	p[1] = '\0';
    } else {
	strncpy(p, pathName, (size_t) numChars);
	strncpy(p, pathName, numChars);
	p[numChars] = '\0';
    }

    /*
     * Find the parent window.
     */

1236
1237
1238
1239
1240
1241
1242
1243

1244
1245
1246
1247
1248
1249
1250
1232
1233
1234
1235
1236
1237
1238

1239
1240
1241
1242
1243
1244
1245
1246







-
+







Tk_DestroyWindow(
    Tk_Window tkwin)		/* Window to destroy. */
{
    TkWindow *winPtr = (TkWindow *) tkwin;
    TkDisplay *dispPtr = winPtr->dispPtr;
    XEvent event;
    TkHalfdeadWindow *halfdeadPtr, *prev_halfdeadPtr;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (winPtr->flags & TK_ALREADY_DEAD) {
	/*
	 * A destroy event binding caused the window to be destroyed again.
	 * Ignore the request.
	 */
1259
1260
1261
1262
1263
1264
1265
1266

1267
1268
1269
1270
1271
1272
1273
1255
1256
1257
1258
1259
1260
1261

1262
1263
1264
1265
1266
1267
1268
1269







-
+







     */

    if (tsdPtr->halfdeadWindowList &&
	    (tsdPtr->halfdeadWindowList->flags & HD_CLEANUP) &&
	    (tsdPtr->halfdeadWindowList->winPtr == winPtr)) {
	halfdeadPtr = tsdPtr->halfdeadWindowList;
    } else {
	halfdeadPtr = ckalloc(sizeof(TkHalfdeadWindow));
	halfdeadPtr = (TkHalfdeadWindow *)ckalloc(sizeof(TkHalfdeadWindow));
	halfdeadPtr->flags = 0;
	halfdeadPtr->winPtr = winPtr;
	halfdeadPtr->nextPtr = tsdPtr->halfdeadWindowList;
	tsdPtr->halfdeadWindowList = halfdeadPtr;
    }

    /*
1439
1440
1441
1442
1443
1444
1445
1446

1447
1448
1449
1450
1451
1452
1453

1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1435
1436
1437
1438
1439
1440
1441

1442
1443
1444
1445
1446

1447

1448
1449
1450
1451

1452
1453
1454
1455
1456
1457
1458







-
+




-

-
+



-







	     * to do an explicit destroy of this X window.
	     */

	    XDestroyWindow(winPtr->display, winPtr->window);
	}
#endif
	Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->winTable,
		(char *) winPtr->window));
		winPtr->window));
	winPtr->window = None;
    }
    UnlinkWindow(winPtr);
    TkEventDeadWindow(winPtr);
#ifdef TK_USE_INPUT_METHODS
    if (winPtr->inputContext != NULL &&
	    winPtr->ximGeneration == winPtr->dispPtr->ximGeneration) {
	winPtr->ximGeneration == winPtr->dispPtr->ximGeneration) {
	XDestroyIC(winPtr->inputContext);
    }
    winPtr->inputContext = NULL;
#endif /* TK_USE_INPUT_METHODS */
    if (winPtr->tagPtr != NULL) {
	TkFreeBindingTags(winPtr);
    }
    TkOptionDeadWindow(winPtr);
    TkSelDeadWindow(winPtr);
    TkGrabDeadWindow(winPtr);
    if (winPtr->geomMgrName != NULL) {
1484
1485
1486
1487
1488
1489
1490
1491

1492
1493
1494
1495
1496
1497
1498
1478
1479
1480
1481
1482
1483
1484

1485
1486
1487
1488
1489
1490
1491
1492







-
+







	     * Invalidate all objects referring to windows with the same main
	     * window.
	     */

	    winPtr->mainPtr->deletionEpoch++;
	}
	if (winPtr->mainPtr->refCount-- <= 1) {
	    register const TkCmd *cmdPtr;
	    const TkCmd *cmdPtr;

	    /*
	     * We just deleted the last window in the application. Delete the
	     * TkMainInfo structure too and replace all of Tk's commands with
	     * dummy commands that return errors. Also delete the "send"
	     * command to unregister the interpreter.
	     *
1644
1645
1646
1647
1648
1649
1650
1651

1652
1653
1654
1655
1656
1657
1658
1638
1639
1640
1641
1642
1643
1644

1645
1646
1647
1648
1649
1650
1651
1652







-
+







    event.type = MapNotify;
    event.xmap.serial = LastKnownRequestProcessed(winPtr->display);
    event.xmap.send_event = False;
    event.xmap.display = winPtr->display;
    event.xmap.event = winPtr->window;
    event.xmap.window = winPtr->window;
    event.xmap.override_redirect = winPtr->atts.override_redirect;
    Tk_HandleEvent(&event);
    TkpHandleMapOrUnmap((Tk_Window)winPtr, &event);
}

/*
 *--------------------------------------------------------------
 *
 * Tk_MakeWindowExist --
 *
1671
1672
1673
1674
1675
1676
1677
1678

1679
1680
1681
1682
1683
1684
1685
1665
1666
1667
1668
1669
1670
1671

1672
1673
1674
1675
1676
1677
1678
1679







-
+







 *--------------------------------------------------------------
 */

void
Tk_MakeWindowExist(
    Tk_Window tkwin)		/* Token for window. */
{
    register TkWindow *winPtr = (TkWindow *) tkwin;
    TkWindow *winPtr = (TkWindow *) tkwin;
    TkWindow *winPtr2;
    Window parent;
    Tcl_HashEntry *hPtr;
    Tk_ClassCreateProc *createProc;
    int isNew;

    if (winPtr->window != None) {
1780
1781
1782
1783
1784
1785
1786
1787

1788
1789
1790
1791
1792
1793
1794
1774
1775
1776
1777
1778
1779
1780

1781
1782
1783
1784
1785
1786
1787
1788







-
+







 *--------------------------------------------------------------
 */

void
Tk_UnmapWindow(
    Tk_Window tkwin)		/* Token for window to unmap. */
{
    register TkWindow *winPtr = (TkWindow *) tkwin;
    TkWindow *winPtr = (TkWindow *) tkwin;

    if (!(winPtr->flags & TK_MAPPED) || (winPtr->flags & TK_ALREADY_DEAD)) {
	return;
    }
    if (winPtr->flags & TK_WIN_MANAGED) {
	/*
	 * Special processing has to be done for top-level windows. Let tkWm.c
1806
1807
1808
1809
1810
1811
1812
1813

1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824

1825
1826
1827
1828
1829
1830
1831
1800
1801
1802
1803
1804
1805
1806

1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817

1818
1819
1820
1821
1822
1823
1824
1825







-
+










-
+







	event.type = UnmapNotify;
	event.xunmap.serial = LastKnownRequestProcessed(winPtr->display);
	event.xunmap.send_event = False;
	event.xunmap.display = winPtr->display;
	event.xunmap.event = winPtr->window;
	event.xunmap.window = winPtr->window;
	event.xunmap.from_configure = False;
	Tk_HandleEvent(&event);
	TkpHandleMapOrUnmap((Tk_Window)winPtr, &event);
    }
}

void
Tk_ConfigureWindow(
    Tk_Window tkwin,		/* Window to re-configure. */
    unsigned int valueMask,	/* Mask indicating which parts of *valuePtr
				 * are to be used. */
    XWindowChanges *valuePtr)	/* New values. */
{
    register TkWindow *winPtr = (TkWindow *) tkwin;
    TkWindow *winPtr = (TkWindow *) tkwin;

    if (valueMask & CWX) {
	winPtr->changes.x = valuePtr->x;
    }
    if (valueMask & CWY) {
	winPtr->changes.y = valuePtr->y;
    }
1853
1854
1855
1856
1857
1858
1859
1860

1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878

1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898

1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919

1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937

1938
1939
1940

1941
1942
1943
1944
1945
1946
1947
1847
1848
1849
1850
1851
1852
1853

1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871

1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891

1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912

1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930

1931
1932
1933

1934
1935
1936
1937
1938
1939
1940
1941







-
+

















-
+



















-
+




















-
+

















-
+


-
+







}

void
Tk_MoveWindow(
    Tk_Window tkwin,		/* Window to move. */
    int x, int y)		/* New location for window (within parent). */
{
    register TkWindow *winPtr = (TkWindow *) tkwin;
    TkWindow *winPtr = (TkWindow *) tkwin;

    winPtr->changes.x = x;
    winPtr->changes.y = y;
    if (winPtr->window != None) {
	XMoveWindow(winPtr->display, winPtr->window, x, y);
	TkDoConfigureNotify(winPtr);
    } else {
	winPtr->dirtyChanges |= CWX|CWY;
	winPtr->flags |= TK_NEED_CONFIG_NOTIFY;
    }
}

void
Tk_ResizeWindow(
    Tk_Window tkwin,		/* Window to resize. */
    int width, int height)	/* New dimensions for window. */
{
    register TkWindow *winPtr = (TkWindow *) tkwin;
    TkWindow *winPtr = (TkWindow *) tkwin;

    winPtr->changes.width = (unsigned) width;
    winPtr->changes.height = (unsigned) height;
    if (winPtr->window != None) {
	XResizeWindow(winPtr->display, winPtr->window, (unsigned) width,
		(unsigned) height);
	TkDoConfigureNotify(winPtr);
    } else {
	winPtr->dirtyChanges |= CWWidth|CWHeight;
	winPtr->flags |= TK_NEED_CONFIG_NOTIFY;
    }
}

void
Tk_MoveResizeWindow(
    Tk_Window tkwin,		/* Window to move and resize. */
    int x, int y,		/* New location for window (within parent). */
    int width, int height)	/* New dimensions for window. */
{
    register TkWindow *winPtr = (TkWindow *) tkwin;
    TkWindow *winPtr = (TkWindow *) tkwin;

    winPtr->changes.x = x;
    winPtr->changes.y = y;
    winPtr->changes.width = (unsigned) width;
    winPtr->changes.height = (unsigned) height;
    if (winPtr->window != None) {
	XMoveResizeWindow(winPtr->display, winPtr->window, x, y,
		(unsigned) width, (unsigned) height);
	TkDoConfigureNotify(winPtr);
    } else {
	winPtr->dirtyChanges |= CWX|CWY|CWWidth|CWHeight;
	winPtr->flags |= TK_NEED_CONFIG_NOTIFY;
    }
}

void
Tk_SetWindowBorderWidth(
    Tk_Window tkwin,		/* Window to modify. */
    int width)			/* New border width for window. */
{
    register TkWindow *winPtr = (TkWindow *) tkwin;
    TkWindow *winPtr = (TkWindow *) tkwin;

    winPtr->changes.border_width = width;
    if (winPtr->window != None) {
	XSetWindowBorderWidth(winPtr->display, winPtr->window,
		(unsigned) width);
	TkDoConfigureNotify(winPtr);
    } else {
	winPtr->dirtyChanges |= CWBorderWidth;
	winPtr->flags |= TK_NEED_CONFIG_NOTIFY;
    }
}

void
Tk_ChangeWindowAttributes(
    Tk_Window tkwin,		/* Window to manipulate. */
    unsigned long valueMask,	/* OR'ed combination of bits, indicating which
				 * fields of *attsPtr are to be used. */
    register XSetWindowAttributes *attsPtr)
    XSetWindowAttributes *attsPtr)
				/* New values for some attributes. */
{
    register TkWindow *winPtr = (TkWindow *) tkwin;
    TkWindow *winPtr = (TkWindow *) tkwin;

    if (valueMask & CWBackPixmap) {
	winPtr->atts.background_pixmap = attsPtr->background_pixmap;
    }
    if (valueMask & CWBackPixel) {
	winPtr->atts.background_pixel = attsPtr->background_pixel;
    }
1996
1997
1998
1999
2000
2001
2002
2003

2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020

2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038

2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055

2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073

2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100

2101
2102
2103
2104
2105
2106
2107
1990
1991
1992
1993
1994
1995
1996

1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013

2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031

2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048

2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066

2067
2068



2069

2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089

2090
2091
2092
2093
2094
2095
2096
2097







-
+
















-
+

















-
+
















-
+

















-
+

-
-
-

-




















-
+








void
Tk_SetWindowBackground(
    Tk_Window tkwin,		/* Window to manipulate. */
    unsigned long pixel)	/* Pixel value to use for window's
				 * background. */
{
    register TkWindow *winPtr = (TkWindow *) tkwin;
    TkWindow *winPtr = (TkWindow *) tkwin;

    winPtr->atts.background_pixel = pixel;

    if (winPtr->window != None) {
	XSetWindowBackground(winPtr->display, winPtr->window, pixel);
    } else {
	winPtr->dirtyAtts = (winPtr->dirtyAtts & (unsigned) ~CWBackPixmap)
		| CWBackPixel;
    }
}

void
Tk_SetWindowBackgroundPixmap(
    Tk_Window tkwin,		/* Window to manipulate. */
    Pixmap pixmap)		/* Pixmap to use for window's background. */
{
    register TkWindow *winPtr = (TkWindow *) tkwin;
    TkWindow *winPtr = (TkWindow *) tkwin;

    winPtr->atts.background_pixmap = pixmap;

    if (winPtr->window != None) {
	XSetWindowBackgroundPixmap(winPtr->display,
		winPtr->window, pixmap);
    } else {
	winPtr->dirtyAtts = (winPtr->dirtyAtts & (unsigned) ~CWBackPixel)
		| CWBackPixmap;
    }
}

void
Tk_SetWindowBorder(
    Tk_Window tkwin,		/* Window to manipulate. */
    unsigned long pixel)	/* Pixel value to use for window's border. */
{
    register TkWindow *winPtr = (TkWindow *) tkwin;
    TkWindow *winPtr = (TkWindow *) tkwin;

    winPtr->atts.border_pixel = pixel;

    if (winPtr->window != None) {
	XSetWindowBorder(winPtr->display, winPtr->window, pixel);
    } else {
	winPtr->dirtyAtts = (winPtr->dirtyAtts & (unsigned) ~CWBorderPixmap)
		| CWBorderPixel;
    }
}

void
Tk_SetWindowBorderPixmap(
    Tk_Window tkwin,		/* Window to manipulate. */
    Pixmap pixmap)		/* Pixmap to use for window's border. */
{
    register TkWindow *winPtr = (TkWindow *) tkwin;
    TkWindow *winPtr = (TkWindow *) tkwin;

    winPtr->atts.border_pixmap = pixmap;

    if (winPtr->window != None) {
	XSetWindowBorderPixmap(winPtr->display,
		winPtr->window, pixmap);
    } else {
	winPtr->dirtyAtts = (winPtr->dirtyAtts & (unsigned) ~CWBorderPixel)
		| CWBorderPixmap;
    }
}

void
Tk_DefineCursor(
    Tk_Window tkwin,		/* Window to manipulate. */
    Tk_Cursor cursor)		/* Cursor to use for window (may be None). */
{
    register TkWindow *winPtr = (TkWindow *) tkwin;
    TkWindow *winPtr = (TkWindow *) tkwin;

#if defined(MAC_OSX_TK)
    winPtr->atts.cursor = (XCursor) cursor;
#else
    winPtr->atts.cursor = (Cursor) cursor;
#endif

    if (winPtr->window != None) {
	XDefineCursor(winPtr->display, winPtr->window, winPtr->atts.cursor);
    } else {
	winPtr->dirtyAtts = winPtr->dirtyAtts | CWCursor;
    }
}

void
Tk_UndefineCursor(
    Tk_Window tkwin)		/* Window to manipulate. */
{
    Tk_DefineCursor(tkwin, NULL);
}

void
Tk_SetWindowColormap(
    Tk_Window tkwin,		/* Window to manipulate. */
    Colormap colormap)		/* Colormap to use for window. */
{
    register TkWindow *winPtr = (TkWindow *) tkwin;
    TkWindow *winPtr = (TkWindow *) tkwin;

    winPtr->atts.colormap = colormap;

    if (winPtr->window != None) {
	XSetWindowColormap(winPtr->display, winPtr->window, colormap);
	if (!(winPtr->flags & TK_WIN_MANAGED)) {
	    TkWmAddToColormapWindows(winPtr);
2135
2136
2137
2138
2139
2140
2141
2142

2143
2144
2145
2146
2147
2148
2149
2125
2126
2127
2128
2129
2130
2131

2132
2133
2134
2135
2136
2137
2138
2139







-
+







int
Tk_SetWindowVisual(
    Tk_Window tkwin,		/* Window to manipulate. */
    Visual *visual,		/* New visual for window. */
    int depth,			/* New depth for window. */
    Colormap colormap)		/* An appropriate colormap for the visual. */
{
    register TkWindow *winPtr = (TkWindow *) tkwin;
    TkWindow *winPtr = (TkWindow *) tkwin;

    if (winPtr->window != None) {
	/* Too late! */
	return 0;
    }

    winPtr->visual = visual;
2178
2179
2180
2181
2182
2183
2184
2185

2186
2187
2188
2189
2190
2191
2192
2168
2169
2170
2171
2172
2173
2174

2175
2176
2177
2178
2179
2180
2181
2182







-
+







 *	An event is generated and processed by Tk_HandleEvent.
 *
 *----------------------------------------------------------------------
 */

void
TkDoConfigureNotify(
    register TkWindow *winPtr)	/* Window whose configuration was just
    TkWindow *winPtr)	/* Window whose configuration was just
				 * changed. */
{
    XEvent event;

    event.type = ConfigureNotify;
    event.xconfigure.serial = LastKnownRequestProcessed(winPtr->display);
    event.xconfigure.send_event = False;
2224
2225
2226
2227
2228
2229
2230
2231

2232
2233
2234
2235
2236
2237
2238
2214
2215
2216
2217
2218
2219
2220

2221
2222
2223
2224
2225
2226
2227
2228







-
+







 */

void
Tk_SetClass(
    Tk_Window tkwin,		/* Token for window to assign class. */
    const char *className)	/* New class for tkwin. */
{
    register TkWindow *winPtr = (TkWindow *) tkwin;
    TkWindow *winPtr = (TkWindow *) tkwin;

    winPtr->classUid = Tk_GetUid(className);
    if (winPtr->flags & TK_WIN_MANAGED) {
	TkWmSetClass(winPtr);
    }
    TkOptionClassChanged(winPtr);
}
2257
2258
2259
2260
2261
2262
2263
2264

2265
2266
2267
2268
2269
2270
2271
2247
2248
2249
2250
2251
2252
2253

2254
2255
2256
2257
2258
2259
2260
2261







-
+








void
Tk_SetClassProcs(
    Tk_Window tkwin,		/* Token for window to modify. */
    const Tk_ClassProcs *procs,	/* Class procs structure. */
    ClientData instanceData)	/* Data to be passed to class functions. */
{
    register TkWindow *winPtr = (TkWindow *) tkwin;
    TkWindow *winPtr = (TkWindow *) tkwin;

    winPtr->classProcsPtr = procs;
    winPtr->instanceData = instanceData;
}

/*
 *----------------------------------------------------------------------
2316
2317
2318
2319
2320
2321
2322
2323

2324
2325
2326
2327
2328
2329
2330
2306
2307
2308
2309
2310
2311
2312

2313
2314
2315
2316
2317
2318
2319
2320







-
+







	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "bad window path name \"%s\"", pathName));
	    Tcl_SetErrorCode(interp, "TK", "LOOKUP", "WINDOW", pathName,
		    NULL);
	}
	return NULL;
    }
    return Tcl_GetHashValue(hPtr);
    return (Tk_Window)Tcl_GetHashValue(hPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * Tk_IdToWindow --
 *
2358
2359
2360
2361
2362
2363
2364
2365

2366
2367
2368
2369

2370
2371
2372
2373
2374
2375
2376
2348
2349
2350
2351
2352
2353
2354

2355
2356
2357
2358

2359
2360
2361
2362
2363
2364
2365
2366







-
+



-
+







	    break;
	}
    }
    if (window == None) {
	return NULL;
    }

    hPtr = Tcl_FindHashEntry(&dispPtr->winTable, (char *) window);
    hPtr = Tcl_FindHashEntry(&dispPtr->winTable, window);
    if (hPtr == NULL) {
	return NULL;
    }
    return Tcl_GetHashValue(hPtr);
    return (Tk_Window)Tcl_GetHashValue(hPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * Tk_DisplayName --
 *
2620
2621
2622
2623
2624
2625
2626
2627

2628
2629
2630
2631
2632
2633
2634
2610
2611
2612
2613
2614
2615
2616

2617
2618
2619
2620
2621
2622
2623
2624







-
+







	return NULL;
    }
#ifdef USE_TCL_STUBS
    if (tclStubsPtr == NULL) {
	return NULL;
    }
#endif
    tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    tsdPtr = (ThreadSpecificData *)Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    for (mainPtr = tsdPtr->mainWindowList; mainPtr != NULL;
	    mainPtr = mainPtr->nextPtr) {
	if (mainPtr->interp == interp) {
	    return (Tk_Window) mainPtr->winPtr;
	}
    }
2690
2691
2692
2693
2694
2695
2696
2697

2698
2699
2700
2701
2702
2703
2704
2705

2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723

2724
2725
2726
2727
2728
2729
2730
2680
2681
2682
2683
2684
2685
2686

2687
2688
2689
2690
2691
2692
2693
2694

2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712

2713
2714
2715
2716
2717
2718
2719
2720







-
+







-
+

















-
+








#ifdef USE_TCL_STUBS
    if (tclStubsPtr == NULL) {
	return 0;
    }
#endif

    tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    tsdPtr = (ThreadSpecificData *)Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    return tsdPtr->numMainWindows;
}

/*
 *----------------------------------------------------------------------
 *
 * TkpAlwaysShowSelection --
 * Tk_AlwaysShowSelection --
 *
 *	Indicates whether text/entry widgets should always display
 *	their selection, regardless of window focus.
 *
 * Results:
 *	The return value is 1 if always showing the selection has been
 *	requested for tkwin's application by setting the
 *	::tk::AlwaysShowSelection variable in its interpreter to a true value.
 *	0 is returned if it has a false value.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TkpAlwaysShowSelection(
Tk_AlwaysShowSelection(
    Tk_Window tkwin)		/* Window whose application is to be
				 * checked. */
{
    return ((TkWindow *) tkwin)->mainPtr->alwaysShowSelection;
}

/*
2748
2749
2750
2751
2752
2753
2754
2755

2756
2757
2758
2759
2760
2761
2762
2738
2739
2740
2741
2742
2743
2744

2745
2746
2747
2748
2749
2750
2751
2752







-
+








static void
DeleteWindowsExitProc(
    ClientData clientData)	/* tsdPtr when handler was created. */
{
    TkDisplay *dispPtr, *nextPtr;
    Tcl_Interp *interp;
    ThreadSpecificData *tsdPtr = clientData;
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)clientData;

    if (tsdPtr == NULL) {
	return;
    }

    /*
     * Finish destroying any windows that are in a half-dead state. We must
2830
2831
2832
2833
2834
2835
2836
2837

2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853

2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869

2870
2871
2872
2873
2874
2875
2876
2820
2821
2822
2823
2824
2825
2826

2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842

2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858

2859
2860
2861
2862
2863
2864
2865
2866







-
+















-
+















-
+







#if defined(_WIN32)

static HMODULE tkcygwindll = NULL;

/*
 * Run Tk_MainEx from libtk8.?.dll
 *
 * This function is only ever called from wish8.4.exe, the cygwin port of Tcl.
 * This function is only ever called from wish8.?.exe, the cygwin port of Tcl.
 * This means that the system encoding is utf-8, so we don't have to do any
 * encoding conversions.
 */

int
TkCygwinMainEx(
    int argc,			/* Number of arguments. */
    char **argv,		/* Array of argument strings. */
    Tcl_AppInitProc *appInitProc,
				/* Application-specific initialization
				 * procedure to call after most initialization
				 * but before starting to execute commands. */
    Tcl_Interp *interp)
{
    WCHAR name[MAX_PATH];
    int len;
    size_t len;
    void (*tkmainex)(int, char **, Tcl_AppInitProc *, Tcl_Interp *);

    /* construct "<path>/libtk8.?.dll", from "<path>/tk8?.dll" */
    len = GetModuleFileNameW(Tk_GetHINSTANCE(), name, MAX_PATH);
    name[len-2] = '.';
    name[len-1] = name[len-5];
    wcscpy(name+len, L".dll");
    memcpy(name+len-8, L"libtk8", 6 * sizeof(WCHAR));

    tkcygwindll = LoadLibraryW(name);
    if (!tkcygwindll) {
	/* dll is not present */
	return 0;
    }
    tkmainex = (void (*)(int, char **, Tcl_AppInitProc *, Tcl_Interp *))
	    GetProcAddress(tkcygwindll, "Tk_MainEx");
	    (void *)GetProcAddress(tkcygwindll, "Tk_MainEx");
    if (!tkmainex) {
	return 0;
    }
    tkmainex(argc, argv, appInitProc, interp);
    return 1;
}
#endif /* _WIN32 */
2902
2903
2904
2905
2906
2907
2908
2909

2910
2911
2912
2913
2914
2915
2916
2892
2893
2894
2895
2896
2897
2898

2899
2900
2901
2902
2903
2904
2905
2906







-
+







Tk_Init(
    Tcl_Interp *interp)		/* Interpreter to initialize. */
{
#if defined(_WIN32)
    if (tkcygwindll) {
	int (*tkinit)(Tcl_Interp *);

	tkinit = (int(*)(Tcl_Interp *)) GetProcAddress(tkcygwindll,"Tk_Init");
	tkinit = (int(*)(Tcl_Interp *))(void *)GetProcAddress(tkcygwindll,"Tk_Init");
	if (tkinit) {
	    return tkinit(interp);
	}
    }
#endif /* _WIN32 */
    return Initialize(interp);
}
2965
2966
2967
2968
2969
2970
2971
2972

2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983

2984
2985
2986
2987
2988
2989
2990
2955
2956
2957
2958
2959
2960
2961

2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972

2973
2974
2975
2976
2977
2978
2979
2980







-
+










-
+







     * - Wm is unsafe because (if toplevels are allowed, in the future) it can
     *   be used to remove decorations, move windows around, cover the entire
     *   screen etc etc.
     *
     * Current risks:
     *
     * - No CPU time limit, no memory allocation limits, no color limits.
     *   CPU time limits can be imposed by an unsafe master interpreter.
     *   CPU time limits can be imposed by an unsafe parent interpreter.
     *
     * The actual code called is the same as Tk_Init but Tcl_IsSafe() is
     * checked at several places to differentiate the two initialisations.
     */

#if defined(_WIN32)
    if (tkcygwindll) {
	int (*tksafeinit)(Tcl_Interp *);

	tksafeinit = (int (*)(Tcl_Interp *))
		GetProcAddress(tkcygwindll, "Tk_SafeInit");
		(void *)GetProcAddress(tkcygwindll, "Tk_SafeInit");
	if (tksafeinit) {
	    return tksafeinit(interp);
	}
    }
#endif /* _WIN32 */
    return Initialize(interp);
}
3011
3012
3013
3014
3015
3016
3017


3018
3019
3020
3021
3022
3023
3024
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016







+
+








static int
CopyValue(
    ClientData dummy,
    Tcl_Obj *objPtr,
    void *dstPtr)
{
    (void)dummy;

    *(Tcl_Obj **)dstPtr = objPtr;
    return 1;
}

static int
Initialize(
    Tcl_Interp *interp)		/* Interpreter to initialize. */
3037
3038
3039
3040
3041
3042
3043
3044

3045
3046

3047
3048

3049
3050

3051
3052

3053
3054

3055
3056
3057
3058
3059
3060
3061
3062
3063

3064
3065
3066






3067
3068
3069
3070
3071
3072
3073

3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084

3085
3086
3087
3088

3089
3090
3091
3092
3093
3094

3095
3096
3097
3098



3099
3100
3101


3102
3103
3104
3105
3106
3107
3108
3109
3110

3111
3112
3113
3114
3115
3116

3117
3118
3119
3120
3121
3122

3123
3124
3125
3126


3127
3128
3129
3130

3131
3132

3133
3134
3135
3136
3137
3138

3139
3140
3141
3142
3143
3144
3145
3029
3030
3031
3032
3033
3034
3035

3036
3037

3038
3039

3040
3041

3042
3043

3044
3045

3046
3047
3048
3049
3050
3051
3052
3053
3054

3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070

3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081

3082
3083
3084
3085

3086
3087
3088
3089
3090
3091

3092
3093



3094
3095
3096
3097


3098
3099
3100
3101
3102
3103
3104
3105
3106
3107

3108
3109
3110
3111
3112
3113

3114
3115
3116
3117
3118
3119

3120
3121
3122


3123
3124
3125
3126
3127

3128
3129

3130
3131
3132
3133
3134
3135

3136
3137
3138
3139
3140
3141
3142
3143







-
+

-
+

-
+

-
+

-
+

-
+








-
+



+
+
+
+
+
+






-
+










-
+



-
+





-
+

-
-
-
+
+
+

-
-
+
+








-
+





-
+





-
+


-
-
+
+



-
+

-
+





-
+







    Tcl_Obj *geometryObj = NULL;

    int sync = 0;

    const Tcl_ArgvInfo table[] = {
	{TCL_ARGV_CONSTANT, "-sync", INT2PTR(1), &sync,
		"Use synchronous mode for display server", NULL},
	{TCL_ARGV_FUNC, "-colormap", CopyValue, &colorMapObj,
	{TCL_ARGV_FUNC, "-colormap", (void *)CopyValue, &colorMapObj,
		"Colormap for main window", NULL},
	{TCL_ARGV_FUNC, "-display", CopyValue, &displayObj,
	{TCL_ARGV_FUNC, "-display", (void *)CopyValue, &displayObj,
		"Display to use", NULL},
	{TCL_ARGV_FUNC, "-geometry", CopyValue, &geometryObj,
	{TCL_ARGV_FUNC, "-geometry", (void *)CopyValue, &geometryObj,
		"Initial geometry for window", NULL},
	{TCL_ARGV_FUNC, "-name", CopyValue, &nameObj,
	{TCL_ARGV_FUNC, "-name", (void *)CopyValue, &nameObj,
		"Name to use for application", NULL},
	{TCL_ARGV_FUNC, "-visual", CopyValue, &visualObj,
	{TCL_ARGV_FUNC, "-visual", (void *)CopyValue, &visualObj,
		"Visual for main window", NULL},
	{TCL_ARGV_FUNC, "-use", CopyValue, &useObj,
	{TCL_ARGV_FUNC, "-use", (void *)CopyValue, &useObj,
		"Id of window in which to embed application", NULL},
	TCL_ARGV_AUTO_REST, TCL_ARGV_AUTO_HELP, TCL_ARGV_TABLE_END
    };

    /*
     * Ensure that we are getting a compatible version of Tcl.
     */

    if (Tcl_InitStubs(interp, "8.6", 0) == NULL) {
    if (Tcl_InitStubs(interp, "8.6-", 0) == NULL) {
	return TCL_ERROR;
    }

    /*
     * TIP #59: Make embedded configuration information available.
     */

    TkInitEmbeddedConfigurationInformation(interp);

    /*
     * Ensure that our obj-types are registered with the Tcl runtime.
     */

    TkRegisterObjTypes();

    tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    tsdPtr = (ThreadSpecificData *)Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    /*
     * We start by resetting the result because it might not be clean.
     */

    Tcl_ResetResult(interp);

    if (Tcl_IsSafe(interp)) {
	/*
	 * Get the clearance to start Tk and the "argv" parameters from the
	 * master.
	 * parent.
	 */

	/*
	 * Step 1 : find the master and construct the interp name (could be a
	 * Step 1 : find the parent and construct the interp name (could be a
	 * function if new APIs were ok). We could also construct the path
	 * while walking, but there is no API to get the name of an interp
	 * either.
	 */

	Tcl_Interp *master = interp;
	Tcl_Interp *parent = interp;

	while (Tcl_IsSafe(master)) {
	    master = Tcl_GetMaster(master);
	    if (master == NULL) {
	while (Tcl_IsSafe(parent)) {
	    parent = Tcl_GetParent(parent);
	    if (parent == NULL) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"no controlling master interpreter", -1));
		Tcl_SetErrorCode(interp, "TK", "SAFE", "NO_MASTER", NULL);
			"no controlling parent interpreter", -1));
		Tcl_SetErrorCode(interp, "TK", "SAFE", "NO_PARENT", NULL);
		return TCL_ERROR;
	    }
	}

	/*
	 * Construct the name (rewalk...)
	 */

	code = Tcl_GetInterpPath(master, interp);
	code = Tcl_GetInterpPath(parent, interp);
	if (code != TCL_OK) {
	    Tcl_Panic("Tcl_GetInterpPath broken!");
	}

	/*
	 * Build the command to eval in trusted master.
	 * Build the command to eval in trusted parent.
	 */

	cmd = Tcl_NewListObj(2, NULL);
	Tcl_ListObjAppendElement(NULL, cmd,
		Tcl_NewStringObj("::safe::TkInit", -1));
	Tcl_ListObjAppendElement(NULL, cmd, Tcl_GetObjResult(master));
	Tcl_ListObjAppendElement(NULL, cmd, Tcl_GetObjResult(parent));

	/*
	 * Step 2 : Eval in the master. The argument is the *reversed* interp
	 * path of the slave.
	 * Step 2 : Eval in the parent. The argument is the *reversed* interp
	 * path of the child.
	 */

	Tcl_IncrRefCount(cmd);
	code = Tcl_EvalObjEx(master, cmd, 0);
	code = Tcl_EvalObjEx(parent, cmd, 0);
	Tcl_DecrRefCount(cmd);
	Tcl_TransferResult(master, code, interp);
	Tcl_TransferResult(parent, code, interp);
	if (code != TCL_OK) {
	    return code;
	}

	/*
	 * Use the master's result as argv. Note: We don't use the Obj
	 * Use the parent's result as argv. Note: We don't use the Obj
	 * interfaces to avoid dealing with cross interp refcounting and
	 * changing the code below.
	 */

	value = Tcl_GetObjResult(interp);
    } else {
	/*
3166
3167
3168
3169
3170
3171
3172
3173

3174
3175
3176
3177
3178
3179
3180
3164
3165
3166
3167
3168
3169
3170

3171
3172
3173
3174
3175
3176
3177
3178







-
+







		    "\n    (processing arguments in argv variable)");
	    code = TCL_ERROR;
	}
	if (code == TCL_OK) {
	    Tcl_SetVar2Ex(interp, "argv", NULL,
		    Tcl_NewListObj(objc-1, rest+1), TCL_GLOBAL_ONLY);
	    Tcl_SetVar2Ex(interp, "argc", NULL,
		    Tcl_NewIntObj(objc-1), TCL_GLOBAL_ONLY);
		    Tcl_NewWideIntObj(objc-1), TCL_GLOBAL_ONLY);
	    ckfree(rest);
	}
	Tcl_DecrRefCount(parseList);
	if (code != TCL_OK) {
	    goto done;
	}
    }
3198
3199
3200
3201
3202
3203
3204
3205
3206


3207
3208
3209
3210
3211
3212
3213
3196
3197
3198
3199
3200
3201
3202


3203
3204
3205
3206
3207
3208
3209
3210
3211







-
-
+
+







    }

    /*
     * The -class argument is always the ToTitle of the -name
     */

    {
	int numBytes;
	const char *bytes = Tcl_GetStringFromObj(nameObj, &numBytes);
	TkSizeT numBytes;
	const char *bytes = TkGetStringFromObj(nameObj, &numBytes);

	classObj = Tcl_NewStringObj(bytes, numBytes);

	numBytes = Tcl_UtfToTitle(Tcl_GetString(classObj));
	Tcl_SetObjLength(classObj, numBytes);
    }

3281
3282
3283
3284
3285
3286
3287
3288

3289
3290

3291




3292
3293
3294
3295
3296
3297
3298
3279
3280
3281
3282
3283
3284
3285

3286
3287
3288
3289

3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300







-
+


+
-
+
+
+
+







	geometryObj = NULL;
	if (code != TCL_OK) {
	    goto done;
	}
    }

    /*
     * Provide Tk and its stub table.
     * Provide "tk" and its stub table.
     */

#ifndef TK_NO_DEPRECATED
    code = Tcl_PkgProvideEx(interp, "Tk", TK_PATCH_LEVEL,
    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;
    }

    /*
     * If we were able to provide ourselves as a package, then set the main
3335
3336
3337
3338
3339
3340
3341
3342

3343
3344
3345
3346
3347
3348
3349
3337
3338
3339
3340
3341
3342
3343

3344
3345
3346
3347
3348
3349
3350
3351







-
+







"if {[namespace which -command tkInit] eq \"\"} {\n\
  proc tkInit {} {\n\
    global tk_library tk_version tk_patchLevel\n\
      rename tkInit {}\n\
    tcl_findLibrary tk $tk_version $tk_patchLevel tk.tcl TK_LIBRARY tk_library\n\
  }\n\
}\n\
tkInit", -1, 0);
tkInit", -1, TCL_EVAL_GLOBAL);
    }
    if (code == TCL_OK) {
	/*
	 * Create exit handlers to delete all windows when the application or
	 * thread exits. The handler need to be invoked before other platform
	 * specific cleanups take place to avoid panics in finalization.
	 */
3379
3380
3381
3382
3383
3384
3385
3386

3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398

3399
3400
3401
3402

3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3381
3382
3383
3384
3385
3386
3387

3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399

3400
3401
3402
3403

3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416







-
+











-
+



-
+













const char *
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;

	while (*p) {
	    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;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Changes to generic/ttk/ttk.decls.
21
22
23
24
25
26
27
28

29
30
31
32
33
34
35
36
37

38
39
40
41
42
43
44
21
22
23
24
25
26
27

28
29
30
31
32
33
34
35
36

37
38
39
40
41
42
43
44







-
+








-
+







	Tcl_Interp *interp, void *deleteData, Ttk_CleanupProc *cleanupProc)
}

declare 5 {
    int Ttk_RegisterElementSpec(
	Ttk_Theme theme,
	const char *elementName,
	Ttk_ElementSpec *elementSpec,
	const Ttk_ElementSpec *elementSpec,
	void *clientData)
}

declare 6 {
    Ttk_ElementClass *Ttk_RegisterElement(
	Tcl_Interp *interp,
	Ttk_Theme theme,
	const char *elementName,
	Ttk_ElementSpec *elementSpec,
	const Ttk_ElementSpec *elementSpec,
	void *clientData)
}

declare 7 {
    int Ttk_RegisterElementFactory(
	Tcl_Interp *interp,
	const char *name,
68
69
70
71
72
73
74
75

76
77
78
79
80
81
82
68
69
70
71
72
73
74

75
76
77
78
79
80
81
82







-
+







}
declare 13 {
    Tcl_Obj *Ttk_StateMapLookup(
	Tcl_Interp *interp, Ttk_StateMap map, Ttk_State state)
}
declare 14 {
    int Ttk_StateTableLookup(
    	Ttk_StateTable map[], Ttk_State state)
    	const Ttk_StateTable *map, Ttk_State state)
}


#
# Low-level geometry utilities.
#
declare 20 {
139
140
141
142
143
144
145
146

147
148
149
150
139
140
141
142
143
144
145

146
147
148
149
150







-
+




declare 35 {
    Tcl_Obj *Ttk_NewBoxObj(Ttk_Box box)
}

#
# Utilities.
#
declare 40 {
declare 40 {deprecated {}} {
    int Ttk_GetOrientFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int *orient)
}


Changes to generic/ttk/ttkBlink.c.
10
11
12
13
14
15
16
17

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

38
39


40
41
42
43
44
45
46
47
48
49
50
51
52

53
54
55

56
57
58
59
60

61
62
63
64
65
66
67
68
69
70
71

72
73
74
75
76
77
78
10
11
12
13
14
15
16

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

54
55
56

57
58
59
60
61

62
63
64
65
66
67
68
69
70
71
72

73
74
75
76
77
78
79
80







-
+



















-
+


+
+












-
+


-
+




-
+










-
+







 * 	to display the cursor or not (e.g., readonly or disabled states);
 * 	TtkBlinkCursor() does not account for this.
 *
 * TODO:
 * 	Add script-level access to configure application-wide blink rate.
 */

#include <tk.h>
#include "tkInt.h"
#include "ttkTheme.h"
#include "ttkWidget.h"

#define DEF_CURSOR_ON_TIME	600		/* milliseconds */
#define DEF_CURSOR_OFF_TIME	300		/* milliseconds */

/* Interp-specific data for tracking cursors:
 */
typedef struct
{
    WidgetCore		*owner; 	/* Widget that currently has cursor */
    Tcl_TimerToken	timer;		/* Blink timer */
    int 		onTime;		/* #milliseconds to blink cursor on */
    int 		offTime;	/* #milliseconds to blink cursor off */
} CursorManager;

/* CursorManagerDeleteProc --
 * 	InterpDeleteProc for cursor manager.
 */
static void CursorManagerDeleteProc(ClientData clientData, Tcl_Interp *interp)
static void CursorManagerDeleteProc(ClientData clientData, Tcl_Interp *dummy)
{
    CursorManager *cm = (CursorManager*)clientData;
    (void)dummy;

    if (cm->timer) {
	Tcl_DeleteTimerHandler(cm->timer);
    }
    ckfree(clientData);
}

/* GetCursorManager --
 * 	Look up and create if necessary the interp's cursor manager.
 */
static CursorManager *GetCursorManager(Tcl_Interp *interp)
{
    static const char *cm_key = "ttk::CursorManager";
    CursorManager *cm = Tcl_GetAssocData(interp, cm_key,0);
    CursorManager *cm = (CursorManager *)Tcl_GetAssocData(interp, cm_key,0);

    if (!cm) {
	cm = ckalloc(sizeof(*cm));
	cm = (CursorManager *)ckalloc(sizeof(*cm));
	cm->timer = 0;
	cm->owner = 0;
	cm->onTime = DEF_CURSOR_ON_TIME;
	cm->offTime = DEF_CURSOR_OFF_TIME;
	Tcl_SetAssocData(interp,cm_key,CursorManagerDeleteProc,(ClientData)cm);
	Tcl_SetAssocData(interp, cm_key, CursorManagerDeleteProc, cm);
    }
    return cm;
}

/* CursorBlinkProc --
 *	Timer handler to blink the insert cursor on and off.
 */
static void
CursorBlinkProc(ClientData clientData)
{
    CursorManager *cm = (CursorManager*)clientData;
    CursorManager *cm = (CursorManager *)clientData;
    int blinkTime;

    if (cm->owner->flags & CURSOR_ON) {
	cm->owner->flags &= ~CURSOR_ON;
	blinkTime = cm->offTime;
    } else {
	cm->owner->flags |= CURSOR_ON;
Changes to generic/ttk/ttkButton.c.
1
2

3
4
5
6
7
8

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

26
27
28
29
30
31
32
1

2
3
4
5
6


7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

-
+




-
-
+

















+







/*
 * Copyright (c) 2003, Joe English
 * Copyright © 2003, Joe English
 *
 * label, button, checkbutton, radiobutton, and menubutton widgets.
 */

#include <string.h>
#include <tk.h>
#include "tkInt.h"
#include "ttkTheme.h"
#include "ttkWidget.h"

/* Bit fields for OptionSpec mask field:
 */
#define STATE_CHANGED	 	(0x100)		/* -state option changed */
#define DEFAULTSTATE_CHANGED	(0x200)		/* -default option changed */

/*------------------------------------------------------------------------
 * +++ Base resources for labels, buttons, checkbuttons, etc:
 */
typedef struct
{
    /*
     * Text element resources:
     */
    Tcl_Obj *textObj;
    Tcl_Obj *justifyObj;
    Tcl_Obj *textVariableObj;
    Tcl_Obj *underlineObj;
    Tcl_Obj *widthObj;

    Ttk_TraceHandle	*textVariableTrace;
    Ttk_ImageSpec	*imageSpec;

50
51
52
53
54
55
56
57

58



59
60

61
62
63

64
65
66

67
68
69
70

71
72
73
74
75
76
77

78
79
80
81
82
83
84
85


86
87
88

89
90
91
92
93
94
95

96
97
98
99
100
101
102
103
104
105
106

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123

124
125



126
127
128
129
130
131
132
133

134
135
136
137
138
139
140
141
142
143
144
145







146
147
148
149
150
151

152
153
154
155
156
157
158
50
51
52
53
54
55
56

57
58
59
60
61
62

63
64
65

66
67
68

69
70
71
72

73
74
75
76
77
78
79

80
81
82
83
84
85
86


87
88
89
90

91
92
93
94
95
96
97

98
99
100
101
102
103
104
105
106
107
108

109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125

126
127

128
129
130
131
132
133
134
135
136
137

138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162

163
164
165
166
167
168
169
170







-
+

+
+
+

-
+


-
+


-
+



-
+






-
+






-
-
+
+


-
+






-
+










-
+
















-
+

-
+
+
+







-
+












+
+
+
+
+
+
+





-
+








typedef struct
{
    WidgetCore	core;
    BasePart	base;
} Base;

static Tk_OptionSpec BaseOptionSpecs[] =
static const Tk_OptionSpec BaseOptionSpecs[] =
{
    {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",
        "left", offsetof(Base,base.justifyObj), TCL_INDEX_NONE,
        TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },
    {TK_OPTION_STRING, "-text", "text", "Text", "",
	Tk_Offset(Base,base.textObj), -1,
	offsetof(Base,base.textObj), TCL_INDEX_NONE,
	0,0,GEOMETRY_CHANGED },
    {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable", "",
	Tk_Offset(Base,base.textVariableObj), -1,
	offsetof(Base,base.textVariableObj), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },
    {TK_OPTION_INT, "-underline", "underline", "Underline",
	"-1", Tk_Offset(Base,base.underlineObj), -1,
	"-1", offsetof(Base,base.underlineObj), TCL_INDEX_NONE,
	0,0,0 },
    /* SB: OPTION_INT, see <<NOTE-NULLOPTIONS>> */
    {TK_OPTION_STRING, "-width", "width", "Width",
	NULL, Tk_Offset(Base,base.widthObj), -1,
	NULL, offsetof(Base,base.widthObj), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },

    /*
     * Image options
     */
    {TK_OPTION_STRING, "-image", "image", "Image", NULL/*default*/,
	Tk_Offset(Base,base.imageObj), -1,
	offsetof(Base,base.imageObj), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },

    /*
     * Compound base/image options
     */
    {TK_OPTION_STRING_TABLE, "-compound", "compound", "Compound",
	 NULL, Tk_Offset(Base,base.compoundObj), -1,
	 TK_OPTION_NULL_OK,(ClientData)ttkCompoundStrings,
	 NULL, offsetof(Base,base.compoundObj), TCL_INDEX_NONE,
	 TK_OPTION_NULL_OK, (void *)ttkCompoundStrings,
         GEOMETRY_CHANGED },
    {TK_OPTION_STRING, "-padding", "padding", "Pad",
	NULL, Tk_Offset(Base,base.paddingObj), -1,
	NULL, offsetof(Base,base.paddingObj), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED},

    /*
     * Compatibility/legacy options
     */
    {TK_OPTION_STRING, "-state", "state", "State",
	 "normal", Tk_Offset(Base,base.stateObj), -1,
	 "normal", offsetof(Base,base.stateObj), TCL_INDEX_NONE,
	 0,0,STATE_CHANGED },

    WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs)
};

/*
 * Variable trace procedure for -textvariable option:
 */
static void TextVariableChanged(void *clientData, const char *value)
{
    Base *basePtr = clientData;
    Base *basePtr = (Base *)clientData;
    Tcl_Obj *newText;

    if (WidgetDestroyed(&basePtr->core)) {
	return;
    }

    newText = value ? Tcl_NewStringObj(value, -1) : Tcl_NewStringObj("", 0);

    Tcl_IncrRefCount(newText);
    Tcl_DecrRefCount(basePtr->base.textObj);
    basePtr->base.textObj = newText;

    TtkResizeWidget(&basePtr->core);
}

static void
BaseInitialize(Tcl_Interp *interp, void *recordPtr)
BaseInitialize(Tcl_Interp *dummy, void *recordPtr)
{
    Base *basePtr = recordPtr;
    Base *basePtr = (Base *)recordPtr;
    (void)dummy;

    basePtr->base.textVariableTrace = 0;
    basePtr->base.imageSpec = NULL;
}

static void
BaseCleanup(void *recordPtr)
{
    Base *basePtr = recordPtr;
    Base *basePtr = (Base *)recordPtr;
    if (basePtr->base.textVariableTrace)
	Ttk_UntraceVariable(basePtr->base.textVariableTrace);
    if (basePtr->base.imageSpec)
    	TtkFreeImageSpec(basePtr->base.imageSpec);
}

static void
BaseImageChanged(
	ClientData clientData, int x, int y, int width, int height,
	int imageWidth, int imageHeight)
{
    Base *basePtr = (Base *)clientData;
    (void)x;
    (void)y;
    (void)width;
    (void)height;
    (void)imageWidth;
    (void)imageHeight;

    TtkResizeWidget(&basePtr->core);
}

static int BaseConfigure(Tcl_Interp *interp, void *recordPtr, int mask)
{
    Base *basePtr = recordPtr;
    Base *basePtr = (Base *)recordPtr;
    Tcl_Obj *textVarName = basePtr->base.textVariableObj;
    Ttk_TraceHandle *vt = 0;
    Ttk_ImageSpec *imageSpec = NULL;

    if (textVarName != NULL && *Tcl_GetString(textVarName) != '\0') {
	vt = Ttk_TraceVariable(interp,textVarName,TextVariableChanged,basePtr);
	if (!vt) return TCL_ERROR;
187
188
189
190
191
192
193
194

195
196

197


198
199
200
201
202
203
204
199
200
201
202
203
204
205

206
207

208
209
210
211
212
213
214
215
216
217
218







-
+

-
+

+
+







	TtkCheckStateOption(&basePtr->core, basePtr->base.stateObj);
    }

    return TCL_OK;
}

static int
BasePostConfigure(Tcl_Interp *interp, void *recordPtr, int mask)
BasePostConfigure(Tcl_Interp *dummy, void *recordPtr, int mask)
{
    Base *basePtr = recordPtr;
    Base *basePtr = (Base *)recordPtr;
    int status = TCL_OK;
    (void)dummy;
    (void)mask;

    if (basePtr->base.textVariableTrace) {
	status = Ttk_FireTrace(basePtr->base.textVariableTrace);
    }

    return status;
}
223
224
225
226
227
228
229
230

231
232
233

234
235
236

237
238
239

240
241
242

243
244
245

246
247
248

249
250
251

252
253
254

255
256
257
258
259
260
261

262
263

264
265
266

267
268
269
270

271
272
273
274
275
276
277
237
238
239
240
241
242
243

244
245
246

247
248
249

250
251
252

253
254
255

256
257
258

259
260
261

262
263
264

265
266
267

268
269
270
271
272
273
274
275
276
277

278
279
280

281
282
283
284

285
286
287
288
289
290
291
292







-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+







+

-
+


-
+



-
+







typedef struct
{
    WidgetCore	core;
    BasePart	base;
    LabelPart	label;
} Label;

static Tk_OptionSpec LabelOptionSpecs[] =
static const Tk_OptionSpec LabelOptionSpecs[] =
{
    {TK_OPTION_BORDER, "-background", "frameColor", "FrameColor",
	NULL, Tk_Offset(Label,label.backgroundObj), -1,
	NULL, offsetof(Label,label.backgroundObj), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK,0,0 },
    {TK_OPTION_COLOR, "-foreground", "textColor", "TextColor",
	NULL, Tk_Offset(Label,label.foregroundObj), -1,
	NULL, offsetof(Label,label.foregroundObj), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK,0,0 },
    {TK_OPTION_FONT, "-font", "font", "Font",
	NULL, Tk_Offset(Label,label.fontObj), -1,
	NULL, offsetof(Label,label.fontObj), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },
    {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
	NULL, Tk_Offset(Label,label.borderWidthObj), -1,
	NULL, offsetof(Label,label.borderWidthObj), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },
    {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
	NULL, Tk_Offset(Label,label.reliefObj), -1,
	NULL, offsetof(Label,label.reliefObj), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },
    {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",
	NULL, Tk_Offset(Label,label.anchorObj), -1,
	NULL, offsetof(Label,label.anchorObj), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK, 0, GEOMETRY_CHANGED},
    {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",
	NULL, Tk_Offset(Label, label.justifyObj), -1,
	NULL, offsetof(Label, label.justifyObj), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },
    {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength",
	NULL, Tk_Offset(Label, label.wrapLengthObj), -1,
	NULL, offsetof(Label, label.wrapLengthObj), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED /*SB: SIZE_CHANGED*/ },

    WIDGET_TAKEFOCUS_FALSE,
    WIDGET_INHERIT_OPTIONS(BaseOptionSpecs)
};

static const Ttk_Ensemble LabelCommands[] = {
    { "cget",		TtkWidgetCgetCommand,0 },
    { "configure",	TtkWidgetConfigureCommand,0 },
    { "cget",		TtkWidgetCgetCommand,0 },
    { "identify",	TtkWidgetIdentifyCommand,0 },
    { "instate",	TtkWidgetInstateCommand,0 },
    { "state",  	TtkWidgetStateCommand,0 },
    { "identify",	TtkWidgetIdentifyCommand,0 },
    { "style",		TtkWidgetStyleCommand,0 },
    { 0,0,0 }
};

static WidgetSpec LabelWidgetSpec =
static const WidgetSpec LabelWidgetSpec =
{
    "TLabel",			/* className */
    sizeof(Label),		/* recordSize */
    LabelOptionSpecs,		/* optionSpecs */
    LabelCommands,		/* subcommands */
    BaseInitialize,		/* initializeProc */
    BaseCleanup,		/* cleanupProc */
306
307
308
309
310
311
312
313

314
315
316

317
318
319


320
321
322
323
324
325
326
327

328
329
330
331
332
333
334
335
336

337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355

356
357
358
359
360
361
362
363
364
365
366

367
368

369
370

371
372

373
374
375
376

377
378
379
380
381
382
383
321
322
323
324
325
326
327

328
329
330

331
332


333
334
335
336
337
338
339
340
341

342
343
344
345
346
347
348
349
350

351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369

370
371
372
373
374
375
376
377
378
379
380
381
382
383

384

385
386
387

388
389
390
391

392
393
394
395
396
397
398
399







-
+


-
+

-
-
+
+







-
+








-
+


















-
+











+

-
+
-

+

-
+



-
+







    BasePart	base;
    ButtonPart	button;
} Button;

/*
 * Option specifications:
 */
static Tk_OptionSpec ButtonOptionSpecs[] =
static const Tk_OptionSpec ButtonOptionSpecs[] =
{
    {TK_OPTION_STRING, "-command", "command", "Command",
	"", Tk_Offset(Button, button.commandObj), -1, 0,0,0},
	"", offsetof(Button, button.commandObj), TCL_INDEX_NONE, 0,0,0},
    {TK_OPTION_STRING_TABLE, "-default", "default", "Default",
	"normal", Tk_Offset(Button, button.defaultStateObj), -1,
	0, (ClientData) ttkDefaultStrings, DEFAULTSTATE_CHANGED},
	"normal", offsetof(Button, button.defaultStateObj), TCL_INDEX_NONE,
	0, (void *)ttkDefaultStrings, DEFAULTSTATE_CHANGED},

    WIDGET_TAKEFOCUS_TRUE,
    WIDGET_INHERIT_OPTIONS(BaseOptionSpecs)
};

static int ButtonConfigure(Tcl_Interp *interp, void *recordPtr, int mask)
{
    Button *buttonPtr = recordPtr;
    Button *buttonPtr = (Button *)recordPtr;

    if (BaseConfigure(interp, recordPtr, mask) != TCL_OK) {
	return TCL_ERROR;
    }

    /* Handle "-default" option:
     */
    if (mask & DEFAULTSTATE_CHANGED) {
	int defaultState = TTK_BUTTON_DEFAULT_DISABLED;
	Ttk_ButtonDefaultState defaultState = TTK_BUTTON_DEFAULT_DISABLED;
	Ttk_GetButtonDefaultStateFromObj(
	    NULL, buttonPtr->button.defaultStateObj, &defaultState);
	if (defaultState == TTK_BUTTON_DEFAULT_ACTIVE) {
	    TtkWidgetChangeState(&buttonPtr->core, TTK_STATE_ALTERNATE, 0);
	} else {
	    TtkWidgetChangeState(&buttonPtr->core, 0, TTK_STATE_ALTERNATE);
	}
    }
    return TCL_OK;
}

/* $button invoke --
 * 	Evaluate the button's -command.
 */
static int
ButtonInvokeCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Button *buttonPtr = recordPtr;
    Button *buttonPtr = (Button *)recordPtr;
    if (objc > 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "invoke");
	return TCL_ERROR;
    }
    if (buttonPtr->core.state & TTK_STATE_DISABLED) {
	return TCL_OK;
    }
    return Tcl_EvalObjEx(interp, buttonPtr->button.commandObj, TCL_EVAL_GLOBAL);
}

static const Ttk_Ensemble ButtonCommands[] = {
    { "cget",		TtkWidgetCgetCommand,0 },
    { "configure",	TtkWidgetConfigureCommand,0 },
    { "cget",		TtkWidgetCgetCommand,0 },
    { "identify",	TtkWidgetIdentifyCommand,0 },
    { "invoke",		ButtonInvokeCommand,0 },
    { "instate",	TtkWidgetInstateCommand,0 },
    { "invoke",		ButtonInvokeCommand,0 },
    { "state",  	TtkWidgetStateCommand,0 },
    { "identify",	TtkWidgetIdentifyCommand,0 },
    { "style",		TtkWidgetStyleCommand,0 },
    { 0,0,0 }
};

static WidgetSpec ButtonWidgetSpec =
static const WidgetSpec ButtonWidgetSpec =
{
    "TButton",			/* className */
    sizeof(Button),		/* recordSize */
    ButtonOptionSpecs,		/* optionSpecs */
    ButtonCommands,		/* subcommands */
    BaseInitialize,		/* initializeProc */
    BaseCleanup,		/* cleanupProc */
416
417
418
419
420
421
422
423

424
425
426

427
428
429

430
431
432

433
434
435

436
437
438
439
440
441
442
443
444
445
446
447

448
449
450
451
452
453
454
432
433
434
435
436
437
438

439
440
441

442
443
444

445
446
447

448
449
450

451
452
453
454
455
456
457
458
459
460
461
462

463
464
465
466
467
468
469
470







-
+


-
+


-
+


-
+


-
+











-
+







    BasePart base;
    CheckbuttonPart checkbutton;
} Checkbutton;

/*
 * Option specifications:
 */
static Tk_OptionSpec CheckbuttonOptionSpecs[] =
static const Tk_OptionSpec CheckbuttonOptionSpecs[] =
{
    {TK_OPTION_STRING, "-variable", "variable", "Variable",
	NULL, Tk_Offset(Checkbutton, checkbutton.variableObj), -1,
	NULL, offsetof(Checkbutton, checkbutton.variableObj), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK,0,0},
    {TK_OPTION_STRING, "-onvalue", "onValue", "OnValue",
	"1", Tk_Offset(Checkbutton, checkbutton.onValueObj), -1,
	"1", offsetof(Checkbutton, checkbutton.onValueObj), TCL_INDEX_NONE,
	0,0,0},
    {TK_OPTION_STRING, "-offvalue", "offValue", "OffValue",
	"0", Tk_Offset(Checkbutton, checkbutton.offValueObj), -1,
	"0", offsetof(Checkbutton, checkbutton.offValueObj), TCL_INDEX_NONE,
	0,0,0},
    {TK_OPTION_STRING, "-command", "command", "Command",
	"", Tk_Offset(Checkbutton, checkbutton.commandObj), -1,
	"", offsetof(Checkbutton, checkbutton.commandObj), TCL_INDEX_NONE,
	0,0,0},

    WIDGET_TAKEFOCUS_TRUE,
    WIDGET_INHERIT_OPTIONS(BaseOptionSpecs)
};

/*
 * Variable trace procedure for checkbutton -variable option
 */
static void CheckbuttonVariableChanged(void *clientData, const char *value)
{
    Checkbutton *checkPtr = clientData;
    Checkbutton *checkPtr = (Checkbutton *)clientData;

    if (WidgetDestroyed(&checkPtr->core)) {
	return;
    }

    if (!value) {
	TtkWidgetChangeState(&checkPtr->core, TTK_STATE_ALTERNATE, 0);
462
463
464
465
466
467
468
469

470
471
472
473
474
475
476
477
478
479
480
481
482
483

484
485
486
487
488
489
490
491
492

493
494
495

496
497
498
499
500
501
502
478
479
480
481
482
483
484

485
486
487
488
489
490
491
492
493
494
495
496
497
498

499
500
501
502
503
504
505
506
507

508
509
510

511
512
513
514
515
516
517
518







-
+













-
+








-
+


-
+







	TtkWidgetChangeState(&checkPtr->core, 0, TTK_STATE_SELECTED);
    }
}

static void
CheckbuttonInitialize(Tcl_Interp *interp, void *recordPtr)
{
    Checkbutton *checkPtr = recordPtr;
    Checkbutton *checkPtr = (Checkbutton *)recordPtr;
    Tcl_Obj *variableObj;

    /* default -variable is the widget name:
     */
    variableObj = Tcl_NewStringObj(Tk_PathName(checkPtr->core.tkwin), -1);
    Tcl_IncrRefCount(variableObj);
    checkPtr->checkbutton.variableObj = variableObj;
    BaseInitialize(interp, recordPtr);
}

static void
CheckbuttonCleanup(void *recordPtr)
{
    Checkbutton *checkPtr = recordPtr;
    Checkbutton *checkPtr = (Checkbutton *)recordPtr;
    Ttk_UntraceVariable(checkPtr->checkbutton.variableTrace);
    checkPtr->checkbutton.variableTrace = 0;
    BaseCleanup(recordPtr);
}

static int
CheckbuttonConfigure(Tcl_Interp *interp, void *recordPtr, int mask)
{
    Checkbutton *checkPtr = recordPtr;
    Checkbutton *checkPtr = (Checkbutton *)recordPtr;
    Tcl_Obj *varName = checkPtr->checkbutton.variableObj;
    Ttk_TraceHandle *vt = NULL;
        

    if (varName != NULL && *Tcl_GetString(varName) != '\0') {
        vt = Ttk_TraceVariable(interp, varName,
	    CheckbuttonVariableChanged, checkPtr);
        if (!vt) {
	    return TCL_ERROR;
        }
    }
513
514
515
516
517
518
519
520

521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538

539
540
541
542
543
544
545
529
530
531
532
533
534
535

536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553

554
555
556
557
558
559
560
561







-
+

















-
+








    return TCL_OK;
}

static int
CheckbuttonPostConfigure(Tcl_Interp *interp, void *recordPtr, int mask)
{
    Checkbutton *checkPtr = recordPtr;
    Checkbutton *checkPtr = (Checkbutton *)recordPtr;
    int status = TCL_OK;

    if (checkPtr->checkbutton.variableTrace)
	status = Ttk_FireTrace(checkPtr->checkbutton.variableTrace);
    if (status == TCL_OK && !WidgetDestroyed(&checkPtr->core))
	status = BasePostConfigure(interp, recordPtr, mask);
    return status;
}

/*
 * Checkbutton 'invoke' subcommand:
 * 	Toggles the checkbutton state.
 */
static int
CheckbuttonInvokeCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Checkbutton *checkPtr = recordPtr;
    Checkbutton *checkPtr = (Checkbutton *)recordPtr;
    WidgetCore *corePtr = &checkPtr->core;
    Tcl_Obj *newValue;

    if (objc > 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "invoke");
	return TCL_ERROR;
    }
567
568
569
570
571
572
573

574
575

576
577

578
579

580
581
582
583
584

585
586
587
588
589
590
591
583
584
585
586
587
588
589
590
591

592

593
594
595

596
597
598
599
600

601
602
603
604
605
606
607
608







+

-
+
-

+

-
+




-
+







	return TCL_ERROR;

    return Tcl_EvalObjEx(interp,
	checkPtr->checkbutton.commandObj, TCL_EVAL_GLOBAL);
}

static const Ttk_Ensemble CheckbuttonCommands[] = {
    { "cget",		TtkWidgetCgetCommand,0 },
    { "configure",	TtkWidgetConfigureCommand,0 },
    { "cget",		TtkWidgetCgetCommand,0 },
    { "identify",	TtkWidgetIdentifyCommand,0 },
    { "invoke",		CheckbuttonInvokeCommand,0 },
    { "instate",	TtkWidgetInstateCommand,0 },
    { "invoke",		CheckbuttonInvokeCommand,0 },
    { "state",  	TtkWidgetStateCommand,0 },
    { "identify",	TtkWidgetIdentifyCommand,0 },
    { "style",		TtkWidgetStyleCommand,0 },
    /* MISSING: select, deselect, toggle */
    { 0,0,0 }
};

static WidgetSpec CheckbuttonWidgetSpec =
static const WidgetSpec CheckbuttonWidgetSpec =
{
    "TCheckbutton",		/* className */
    sizeof(Checkbutton),	/* recordSize */
    CheckbuttonOptionSpecs,	/* optionSpecs */
    CheckbuttonCommands,	/* subcommands */
    CheckbuttonInitialize,	/* initializeProc */
    CheckbuttonCleanup,		/* cleanupProc */
624
625
626
627
628
629
630
631

632
633
634

635
636
637

638
639
640

641
642
643
644
645
646
647
648
649
650
651
652
653

654
655
656
657
658
659
660
641
642
643
644
645
646
647

648
649
650

651
652
653

654
655
656

657
658
659
660
661
662
663
664
665
666
667
668
669

670
671
672
673
674
675
676
677







-
+


-
+


-
+


-
+












-
+







    BasePart base;
    RadiobuttonPart radiobutton;
} Radiobutton;

/*
 * Option specifications:
 */
static Tk_OptionSpec RadiobuttonOptionSpecs[] =
static const Tk_OptionSpec RadiobuttonOptionSpecs[] =
{
    {TK_OPTION_STRING, "-variable", "variable", "Variable",
	"::selectedButton", Tk_Offset(Radiobutton, radiobutton.variableObj),-1,
	"::selectedButton", offsetof(Radiobutton, radiobutton.variableObj),TCL_INDEX_NONE,
	0,0,0},
    {TK_OPTION_STRING, "-value", "Value", "Value",
	"1", Tk_Offset(Radiobutton, radiobutton.valueObj), -1,
	"1", offsetof(Radiobutton, radiobutton.valueObj), TCL_INDEX_NONE,
	0,0,0},
    {TK_OPTION_STRING, "-command", "command", "Command",
	"", Tk_Offset(Radiobutton, radiobutton.commandObj), -1,
	"", offsetof(Radiobutton, radiobutton.commandObj), TCL_INDEX_NONE,
	0,0,0},

    WIDGET_TAKEFOCUS_TRUE,
    WIDGET_INHERIT_OPTIONS(BaseOptionSpecs)
};

/*
 * Variable trace procedure for radiobuttons.
 */
static void
RadiobuttonVariableChanged(void *clientData, const char *value)
{
    Radiobutton *radioPtr = clientData;
    Radiobutton *radioPtr = (Radiobutton *)clientData;

    if (WidgetDestroyed(&radioPtr->core)) {
	return;
    }

    if (!value) {
	TtkWidgetChangeState(&radioPtr->core, TTK_STATE_ALTERNATE, 0);
668
669
670
671
672
673
674
675

676
677
678
679
680
681
682
683
684

685
686
687
688
689
690
691
685
686
687
688
689
690
691

692
693
694
695
696
697
698
699
700

701
702
703
704
705
706
707
708







-
+








-
+







	TtkWidgetChangeState(&radioPtr->core, 0, TTK_STATE_SELECTED);
    }
}

static void
RadiobuttonCleanup(void *recordPtr)
{
    Radiobutton *radioPtr = recordPtr;
    Radiobutton *radioPtr = (Radiobutton *)recordPtr;
    Ttk_UntraceVariable(radioPtr->radiobutton.variableTrace);
    radioPtr->radiobutton.variableTrace = 0;
    BaseCleanup(recordPtr);
}

static int
RadiobuttonConfigure(Tcl_Interp *interp, void *recordPtr, int mask)
{
    Radiobutton *radioPtr = recordPtr;
    Radiobutton *radioPtr = (Radiobutton *)recordPtr;
    Ttk_TraceHandle *vt = Ttk_TraceVariable(
	interp, radioPtr->radiobutton.variableObj,
	RadiobuttonVariableChanged, radioPtr);

    if (!vt) {
	return TCL_ERROR;
    }
700
701
702
703
704
705
706
707

708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725

726
727
728
729
730
731
732
717
718
719
720
721
722
723

724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741

742
743
744
745
746
747
748
749







-
+

















-
+








    return TCL_OK;
}

static int
RadiobuttonPostConfigure(Tcl_Interp *interp, void *recordPtr, int mask)
{
    Radiobutton *radioPtr = recordPtr;
    Radiobutton *radioPtr = (Radiobutton *)recordPtr;
    int status = TCL_OK;

    if (radioPtr->radiobutton.variableTrace)
	status = Ttk_FireTrace(radioPtr->radiobutton.variableTrace);
    if (status == TCL_OK && !WidgetDestroyed(&radioPtr->core))
	status = BasePostConfigure(interp, recordPtr, mask);
    return status;
}

/*
 * Radiobutton 'invoke' subcommand:
 * 	Sets the radiobutton -variable to the -value, evaluates the -command.
 */
static int
RadiobuttonInvokeCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Radiobutton *radioPtr = recordPtr;
    Radiobutton *radioPtr = (Radiobutton *)recordPtr;
    WidgetCore *corePtr = &radioPtr->core;

    if (objc > 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "invoke");
	return TCL_ERROR;
    }
    if (corePtr->state & TTK_STATE_DISABLED)
743
744
745
746
747
748
749

750
751

752
753

754
755

756
757
758
759
760

761
762
763
764
765
766
767
760
761
762
763
764
765
766
767
768

769

770
771
772

773
774
775
776
777

778
779
780
781
782
783
784
785







+

-
+
-

+

-
+




-
+







	return TCL_ERROR;

    return Tcl_EvalObjEx(interp,
	radioPtr->radiobutton.commandObj, TCL_EVAL_GLOBAL);
}

static const Ttk_Ensemble RadiobuttonCommands[] = {
    { "cget",		TtkWidgetCgetCommand,0 },
    { "configure",	TtkWidgetConfigureCommand,0 },
    { "cget",		TtkWidgetCgetCommand,0 },
    { "identify",	TtkWidgetIdentifyCommand,0 },
    { "invoke",		RadiobuttonInvokeCommand,0 },
    { "instate",	TtkWidgetInstateCommand,0 },
    { "invoke",		RadiobuttonInvokeCommand,0 },
    { "state",  	TtkWidgetStateCommand,0 },
    { "identify",	TtkWidgetIdentifyCommand,0 },
    { "style",		TtkWidgetStyleCommand,0 },
    /* MISSING: select, deselect */
    { 0,0,0 }
};

static WidgetSpec RadiobuttonWidgetSpec =
static const WidgetSpec RadiobuttonWidgetSpec =
{
    "TRadiobutton",		/* className */
    sizeof(Radiobutton),	/* recordSize */
    RadiobuttonOptionSpecs,	/* optionSpecs */
    RadiobuttonCommands,	/* subcommands */
    BaseInitialize,		/* initializeProc */
    RadiobuttonCleanup,		/* cleanupProc */
799
800
801
802
803
804
805
806

807
808
809

810
811
812


813
814
815
816
817
818
819
820
821
822
823

824
825
826
827

828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847

848
849
850
851
852
853
854
817
818
819
820
821
822
823

824
825
826

827
828


829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845

846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865

866
867
868
869
870
871
872
873







-
+


-
+

-
-
+
+











+



-
+



















-
+








/*
 * Option specifications:
 */
static const char *const directionStrings[] = {
    "above", "below", "left", "right", "flush", NULL
};
static Tk_OptionSpec MenubuttonOptionSpecs[] =
static const Tk_OptionSpec MenubuttonOptionSpecs[] =
{
    {TK_OPTION_STRING, "-menu", "menu", "Menu",
	"", Tk_Offset(Menubutton, menubutton.menuObj), -1, 0,0,0},
	"", offsetof(Menubutton, menubutton.menuObj), TCL_INDEX_NONE, 0,0,0},
    {TK_OPTION_STRING_TABLE, "-direction", "direction", "Direction",
	"below", Tk_Offset(Menubutton, menubutton.directionObj), -1,
	0,(ClientData)directionStrings,GEOMETRY_CHANGED},
	"below", offsetof(Menubutton, menubutton.directionObj), TCL_INDEX_NONE,
	0, (void *)directionStrings, GEOMETRY_CHANGED},

    WIDGET_TAKEFOCUS_TRUE,
    WIDGET_INHERIT_OPTIONS(BaseOptionSpecs)
};

static const Ttk_Ensemble MenubuttonCommands[] = {
    { "configure",	TtkWidgetConfigureCommand,0 },
    { "cget",		TtkWidgetCgetCommand,0 },
    { "instate",	TtkWidgetInstateCommand,0 },
    { "state",  	TtkWidgetStateCommand,0 },
    { "identify",	TtkWidgetIdentifyCommand,0 },
    { "style",		TtkWidgetStyleCommand,0 },
    { 0,0,0 }
};

static WidgetSpec MenubuttonWidgetSpec =
static const WidgetSpec MenubuttonWidgetSpec =
{
    "TMenubutton",		/* className */
    sizeof(Menubutton), 	/* recordSize */
    MenubuttonOptionSpecs, 	/* optionSpecs */
    MenubuttonCommands,  	/* subcommands */
    BaseInitialize,     	/* initializeProc */
    BaseCleanup,		/* cleanupProc */
    BaseConfigure,		/* configureProc */
    BasePostConfigure,  	/* postConfigureProc */
    TtkWidgetGetLayout, 	/* getLayoutProc */
    TtkWidgetSize, 		/* sizeProc */
    TtkWidgetDoLayout,		/* layoutProc */
    TtkWidgetDisplay		/* displayProc */
};

TTK_BEGIN_LAYOUT(MenubuttonLayout)
    TTK_GROUP("Menubutton.border", TTK_FILL_BOTH,
	TTK_GROUP("Menubutton.focus", TTK_FILL_BOTH,
	    TTK_NODE("Menubutton.indicator", TTK_PACK_RIGHT)
	    TTK_GROUP("Menubutton.padding", TTK_PACK_LEFT|TTK_EXPAND|TTK_FILL_X,
	    TTK_GROUP("Menubutton.padding", TTK_FILL_X,
	        TTK_NODE("Menubutton.label", TTK_PACK_LEFT))))
TTK_END_LAYOUT

/*------------------------------------------------------------------------
 * +++ Initialization.
 */

Changes to generic/ttk/ttkCache.c.
1
2
3
4

5
6
7
8
9
10
11
1
2
3

4
5
6
7
8
9
10
11



-
+







/*
 *      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.
 * With the theme engine, resources are allocated right before
 * drawing an element and released immediately after.
24
25
26
27
28
29
30
31
32

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

53
54
55
56
57
58
59
24
25
26
27
28
29
30


31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

51
52
53
54
55
56
57
58







-
-
+



















-
+







 * @@@ BUGS/TODO: Need distinct caches for each combination
 * of display, visual, and colormap.
 *
 * @@@ Colormap flashing on PseudoColor visuals is still possible,
 * but this will be a transient effect.
 */

#include <stdio.h>	/* for sprintf */
#include <tk.h>
#include "tkInt.h"
#include "ttkTheme.h"

struct Ttk_ResourceCache_ {
    Tcl_Interp	  *interp;	/* Interpreter for error reporting */
    Tk_Window	  tkwin;	/* Cache window. */
    Tcl_HashTable fontTable;	/* Entries: Tcl_Obj* holding FontObjs */
    Tcl_HashTable colorTable;	/* Entries: Tcl_Obj* holding ColorObjs */
    Tcl_HashTable borderTable;	/* Entries: Tcl_Obj* holding BorderObjs */
    Tcl_HashTable imageTable;	/* Entries: Tk_Images */

    Tcl_HashTable namedColors;	/* Entries: RGB values as Tcl_StringObjs */
};

/*
 * Ttk_CreateResourceCache --
 * 	Initialize a new resource cache.
 */
Ttk_ResourceCache Ttk_CreateResourceCache(Tcl_Interp *interp)
{
    Ttk_ResourceCache cache = ckalloc(sizeof(*cache));
    Ttk_ResourceCache cache = (Ttk_ResourceCache)ckalloc(sizeof(*cache));

    cache->tkwin = NULL;	/* initialized later */
    cache->interp = interp;
    Tcl_InitHashTable(&cache->fontTable, TCL_STRING_KEYS);
    Tcl_InitHashTable(&cache->colorTable, TCL_STRING_KEYS);
    Tcl_InitHashTable(&cache->borderTable, TCL_STRING_KEYS);
    Tcl_InitHashTable(&cache->imageTable, TCL_STRING_KEYS);
72
73
74
75
76
77
78
79

80
81
82
83
84
85
86
87
88
89
90
91
92
93
94

95
96
97
98
99
100
101
102
103
104
105
106
107
108
109

110
111
112
113
114
115
116
117
118
119
120
121
122
123
124

125
126
127
128
129
130
131
71
72
73
74
75
76
77

78
79
80
81
82
83
84
85
86
87
88
89
90
91
92

93
94
95
96
97
98
99
100
101
102
103
104
105
106
107

108
109
110
111
112
113
114
115
116
117
118
119
120
121
122

123
124
125
126
127
128
129
130







-
+














-
+














-
+














-
+







    Tcl_HashEntry *entryPtr;

    /*
     * Free fonts:
     */
    entryPtr = Tcl_FirstHashEntry(&cache->fontTable, &search);
    while (entryPtr != NULL) {
	Tcl_Obj *fontObj = Tcl_GetHashValue(entryPtr);
	Tcl_Obj *fontObj = (Tcl_Obj *)Tcl_GetHashValue(entryPtr);
	if (fontObj) {
	    Tk_FreeFontFromObj(cache->tkwin, fontObj);
	    Tcl_DecrRefCount(fontObj);
	}
	entryPtr = Tcl_NextHashEntry(&search);
    }
    Tcl_DeleteHashTable(&cache->fontTable);
    Tcl_InitHashTable(&cache->fontTable, TCL_STRING_KEYS);

    /*
     * Free colors:
     */
    entryPtr = Tcl_FirstHashEntry(&cache->colorTable, &search);
    while (entryPtr != NULL) {
	Tcl_Obj *colorObj = Tcl_GetHashValue(entryPtr);
	Tcl_Obj *colorObj = (Tcl_Obj *)Tcl_GetHashValue(entryPtr);
	if (colorObj) {
	    Tk_FreeColorFromObj(cache->tkwin, colorObj);
	    Tcl_DecrRefCount(colorObj);
	}
	entryPtr = Tcl_NextHashEntry(&search);
    }
    Tcl_DeleteHashTable(&cache->colorTable);
    Tcl_InitHashTable(&cache->colorTable, TCL_STRING_KEYS);

    /*
     * Free borders:
     */
    entryPtr = Tcl_FirstHashEntry(&cache->borderTable, &search);
    while (entryPtr != NULL) {
	Tcl_Obj *borderObj = Tcl_GetHashValue(entryPtr);
	Tcl_Obj *borderObj = (Tcl_Obj *)Tcl_GetHashValue(entryPtr);
	if (borderObj) {
	    Tk_Free3DBorderFromObj(cache->tkwin, borderObj);
	    Tcl_DecrRefCount(borderObj);
	}
	entryPtr = Tcl_NextHashEntry(&search);
    }
    Tcl_DeleteHashTable(&cache->borderTable);
    Tcl_InitHashTable(&cache->borderTable, TCL_STRING_KEYS);

    /*
     * Free images:
     */
    entryPtr = Tcl_FirstHashEntry(&cache->imageTable, &search);
    while (entryPtr != NULL) {
	Tk_Image image = Tcl_GetHashValue(entryPtr);
	Tk_Image image = (Tk_Image)Tcl_GetHashValue(entryPtr);
	if (image) {
	    Tk_FreeImage(image);
	}
	entryPtr = Tcl_NextHashEntry(&search);
    }
    Tcl_DeleteHashTable(&cache->imageTable);
    Tcl_InitHashTable(&cache->imageTable, TCL_STRING_KEYS);
150
151
152
153
154
155
156
157

158
159
160
161
162
163
164
165
166
167
168
169
170
171
172

173
174
175
176
177
178
179
149
150
151
152
153
154
155

156
157
158
159
160
161
162
163
164
165
166
167
168
169
170

171
172
173
174
175
176
177
178







-
+














-
+







    Tcl_DeleteHashTable(&cache->imageTable);

    /*
     * Free named colors:
     */
    entryPtr = Tcl_FirstHashEntry(&cache->namedColors, &search);
    while (entryPtr != NULL) {
	Tcl_Obj *colorNameObj = Tcl_GetHashValue(entryPtr);
	Tcl_Obj *colorNameObj = (Tcl_Obj *)Tcl_GetHashValue(entryPtr);
	Tcl_DecrRefCount(colorNameObj);
	entryPtr = Tcl_NextHashEntry(&search);
    }
    Tcl_DeleteHashTable(&cache->namedColors);

    ckfree(cache);
}

/*
 * CacheWinEventHandler --
 * 	Detect when the cache window is destroyed, clear cache.
 */
static void CacheWinEventHandler(ClientData clientData, XEvent *eventPtr)
{
    Ttk_ResourceCache cache = clientData;
    Ttk_ResourceCache cache = (Ttk_ResourceCache)clientData;

    if (eventPtr->type != DestroyNotify) {
	return;
    }
    Tk_DeleteEventHandler(cache->tkwin, StructureNotifyMask,
	    CacheWinEventHandler, clientData);
    Ttk_ClearCache(cache);
213
214
215
216
217
218
219
220

221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238

239
240
241
242
243
244
245
212
213
214
215
216
217
218

219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236

237
238
239
240
241
242
243
244







-
+

















-
+







    sprintf(nameBuf, "#%04X%04X%04X",
    	colorPtr->red, colorPtr->green, colorPtr->blue);
    colorNameObj = Tcl_NewStringObj(nameBuf, -1);
    Tcl_IncrRefCount(colorNameObj);

    entryPtr = Tcl_CreateHashEntry(&cache->namedColors, colorName, &newEntry);
    if (!newEntry) {
    	Tcl_Obj *oldColor = Tcl_GetHashValue(entryPtr);
    	Tcl_Obj *oldColor = (Tcl_Obj *)Tcl_GetHashValue(entryPtr);
	Tcl_DecrRefCount(oldColor);
    }

    Tcl_SetHashValue(entryPtr, colorNameObj);
}

/*
 * CheckNamedColor(objPtr) --
 *	If objPtr is a registered color name, return a Tcl_Obj *
 *	containing the registered color value specification.
 *	Otherwise, return the input argument.
 */
static Tcl_Obj *CheckNamedColor(Ttk_ResourceCache cache, Tcl_Obj *objPtr)
{
    Tcl_HashEntry *entryPtr =
    	Tcl_FindHashEntry(&cache->namedColors, Tcl_GetString(objPtr));
    if (entryPtr) {	/* Use named color instead */
    	objPtr = Tcl_GetHashValue(entryPtr);
    	objPtr = (Tcl_Obj *)Tcl_GetHashValue(entryPtr);
    }
    return objPtr;
}

/*
 * Template for allocation routines:
 */
254
255
256
257
258
259
260
261

262
263
264
265
266
267
268
253
254
255
256
257
258
259

260
261
262
263
264
265
266
267







-
+







{
    int newEntry;
    Tcl_HashEntry *entryPtr =
	Tcl_CreateHashEntry(table,Tcl_GetString(objPtr),&newEntry);
    Tcl_Obj *cacheObj;

    if (!newEntry) {
	return Tcl_GetHashValue(entryPtr);
	return (Tcl_Obj *)Tcl_GetHashValue(entryPtr);
    }

    cacheObj = Tcl_DuplicateObj(objPtr);
    Tcl_IncrRefCount(cacheObj);

    if (allocate(interp, tkwin, cacheObj)) {
	Tcl_SetHashValue(entryPtr, cacheObj);
311
312
313
314
315
316
317
318

319
320









321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337

338
339
340
341
342
343
344
345
346
347
348
349
350
310
311
312
313
314
315
316

317
318

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343

344
345
346
347
348
349
350
351
352
353
354
355
356
357







-
+

-
+
+
+
+
+
+
+
+
+
















-
+













	&cache->borderTable,(Allocator)Tk_Alloc3DBorderFromObj, tkwin, objPtr);
}

/* NullImageChanged --
 * 	Tk_ImageChangedProc for Ttk_UseImage
 */

static void NullImageChanged(ClientData clientData,
static void NullImageChanged(ClientData dummy,
    int x, int y, int width, int height, int imageWidth, int imageHeight)
{ /* No-op */ }
{ /* No-op */
    (void)dummy;
    (void)x;
    (void)y;
    (void)width;
    (void)height;
    (void)imageWidth;
    (void)imageHeight;
}

/*
 * Ttk_UseImage --
 * 	Acquire a Tk_Image from the cache.
 */
Tk_Image Ttk_UseImage(Ttk_ResourceCache cache, Tk_Window tkwin, Tcl_Obj *objPtr)
{
    const char *imageName = Tcl_GetString(objPtr);
    int newEntry;
    Tcl_HashEntry *entryPtr =
	Tcl_CreateHashEntry(&cache->imageTable,imageName,&newEntry);
    Tk_Image image;

    InitCacheWindow(cache, tkwin);

    if (!newEntry) {
	return Tcl_GetHashValue(entryPtr);
	return (Tk_Image)Tcl_GetHashValue(entryPtr);
    }

    image = Tk_GetImage(cache->interp, tkwin, imageName, NullImageChanged,0);
    Tcl_SetHashValue(entryPtr, image);

    if (!image) {
	Tcl_BackgroundException(cache->interp, TCL_ERROR);
    }

    return image;
}

/*EOF*/
Changes to generic/ttk/ttkClamTheme.c.
1
2

3
4
5
6
7

8
9
10
11


12
13
14
15
16
17
18
1

2
3
4
5
6

7
8
9


10
11
12
13
14
15
16
17
18

-
+




-
+


-
-
+
+







/*
 * Copyright (C) 2004 Joe English
 * Copyright © 2004 Joe English
 *
 * "clam" theme; inspired by the XFCE family of Gnome themes.
 */

#include <tk.h>
#include "tkInt.h"
#include "ttkTheme.h"

/* 
 * Under windows, the Tk-provided XDrawLine and XDrawArc have an 
/*
 * Under windows, the Tk-provided XDrawLine and XDrawArc have an
 * off-by-one error in the end point. This is especially apparent with this
 * theme. Defining this macro as true handles this case.
 */
#if defined(_WIN32) && !defined(WIN32_XDRAWLINE_HACK)
#	define WIN32_XDRAWLINE_HACK 1
#else
#	define WIN32_XDRAWLINE_HACK 0
102
103
104
105
106
107
108
109

110
111

112
113

114
115

116
117

118
119
120


121
122
123
124
125
126
127


128
129
130
131
132

133
134
135
136




137
138
139
140
141
142
143

144
145
146

147
148
149


150
151
152
153
154
155
156
102
103
104
105
106
107
108

109
110

111
112

113
114

115
116

117
118


119
120
121
122
123
124
125


126
127
128
129
130
131

132
133
134
135
136
137
138
139
140
141
142
143
144
145
146

147
148
149

150
151
152
153
154
155
156
157
158
159
160
161
162







-
+

-
+

-
+

-
+

-
+

-
-
+
+





-
-
+
+




-
+




+
+
+
+






-
+


-
+



+
+







    Tcl_Obj 	*borderColorObj;
    Tcl_Obj 	*lightColorObj;
    Tcl_Obj 	*darkColorObj;
    Tcl_Obj 	*reliefObj;
    Tcl_Obj 	*borderWidthObj;	/* See <<NOTE-BORDERWIDTH>> */
} BorderElement;

static Ttk_ElementOptionSpec BorderElementOptions[] = {
static const Ttk_ElementOptionSpec BorderElementOptions[] = {
    { "-bordercolor", TK_OPTION_COLOR,
	Tk_Offset(BorderElement,borderColorObj), DARKEST_COLOR },
	offsetof(BorderElement,borderColorObj), DARKEST_COLOR },
    { "-lightcolor", TK_OPTION_COLOR,
	Tk_Offset(BorderElement,lightColorObj), LIGHT_COLOR },
	offsetof(BorderElement,lightColorObj), LIGHT_COLOR },
    { "-darkcolor", TK_OPTION_COLOR,
	Tk_Offset(BorderElement,darkColorObj), DARK_COLOR },
	offsetof(BorderElement,darkColorObj), DARK_COLOR },
    { "-relief", TK_OPTION_RELIEF,
	Tk_Offset(BorderElement,reliefObj), "flat" },
	offsetof(BorderElement,reliefObj), "flat" },
    { "-borderwidth", TK_OPTION_PIXELS,
	Tk_Offset(BorderElement,borderWidthObj), "2" },
    { NULL, 0, 0, NULL }
	offsetof(BorderElement,borderWidthObj), "2" },
    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
};

/*
 * <<NOTE-BORDERWIDTH>>: -borderwidth is only partially supported:
 * in this theme, borders are always exactly 2 pixels thick.
 * With -borderwidth 0, border is not drawn at all; 
 * otherwise a 2-pixel border is used.  For -borderwidth > 2, 
 * With -borderwidth 0, border is not drawn at all;
 * otherwise a 2-pixel border is used.  For -borderwidth > 2,
 * the excess is used as padding.
 */

static void BorderElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    BorderElement *border = (BorderElement*)elementRecord;
    int borderWidth = 2;
    (void)dummy;
    (void)widthPtr;
    (void)heightPtr;

    Tk_GetPixelsFromObj(NULL, tkwin, border->borderWidthObj, &borderWidth);
    if (borderWidth == 1) ++borderWidth;
    *paddingPtr = Ttk_UniformPadding((short)borderWidth);
}

static void BorderElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned state)
{
    BorderElement *border = elementRecord;
    BorderElement *border = (BorderElement *)elementRecord;
    int relief = TK_RELIEF_FLAT;
    int borderWidth = 2;
    Tcl_Obj *outer = 0, *upper = 0, *lower = 0;
    (void)dummy;
    (void)state;

    Tk_GetReliefFromObj(NULL, border->reliefObj, &relief);
    Tk_GetPixelsFromObj(NULL, tkwin, border->borderWidthObj, &borderWidth);

    if (borderWidth == 0) return;

    switch (relief) {
173
174
175
176
177
178
179
180

181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199

200
201

202
203

204
205

206
207
208


209
210
211
212

213
214






215
216
217
218
219

220
221
222

223
224
225
226


227
228
229
230
231
232
233

234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249

250
251
252
253
254
255
256
257
258
259
260

261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281

282
283

284
285

286
287

288
289

290
291

292
293
294


295
296
297
298

299
300
301

302
303



304
305
306
307
308
309
310
311

312
313
314

315
316
317
318
319

320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339

340
341
342
343


344
345
346
347
348
349

350
351
352
353
354
355
356
179
180
181
182
183
184
185

186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204

205
206

207
208

209
210

211
212


213
214
215
216
217

218
219
220
221
222
223
224
225
226
227
228
229
230

231
232
233

234
235
236
237
238
239
240
241
242
243
244
245
246

247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262

263
264
265
266
267
268
269
270
271
272
273

274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294

295
296

297
298

299
300

301
302

303
304

305
306


307
308
309
310
311

312
313
314

315
316
317
318
319
320
321
322
323
324
325
326
327

328
329
330

331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356

357
358
359
360

361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376







-
+


















-
+

-
+

-
+

-
+

-
-
+
+



-
+


+
+
+
+
+
+




-
+


-
+




+
+






-
+















-
+










-
+




















-
+

-
+

-
+

-
+

-
+

-
+

-
-
+
+



-
+


-
+


+
+
+







-
+


-
+





+



















-
+



-
+
+






+







	    outer = upper = lower = border->borderColorObj;
	    break;
    }

    DrawSmoothBorder(tkwin, d, b, outer, upper, lower);
}

static Ttk_ElementSpec BorderElementSpec = {
static const Ttk_ElementSpec BorderElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(BorderElement),
    BorderElementOptions,
    BorderElementSize,
    BorderElementDraw
};

/*------------------------------------------------------------------------
 * +++ Field element.
 */

typedef struct {
    Tcl_Obj 	*borderColorObj;
    Tcl_Obj 	*lightColorObj;
    Tcl_Obj 	*darkColorObj;
    Tcl_Obj 	*backgroundObj;
} FieldElement;

static Ttk_ElementOptionSpec FieldElementOptions[] = {
static const Ttk_ElementOptionSpec FieldElementOptions[] = {
    { "-bordercolor", TK_OPTION_COLOR,
	Tk_Offset(FieldElement,borderColorObj), DARKEST_COLOR },
	offsetof(FieldElement,borderColorObj), DARKEST_COLOR },
    { "-lightcolor", TK_OPTION_COLOR,
	Tk_Offset(FieldElement,lightColorObj), LIGHT_COLOR },
	offsetof(FieldElement,lightColorObj), LIGHT_COLOR },
    { "-darkcolor", TK_OPTION_COLOR,
	Tk_Offset(FieldElement,darkColorObj), DARK_COLOR },
	offsetof(FieldElement,darkColorObj), DARK_COLOR },
    { "-fieldbackground", TK_OPTION_BORDER,
	Tk_Offset(FieldElement,backgroundObj), "white" },
    { NULL, 0, 0, NULL }
	offsetof(FieldElement,backgroundObj), "white" },
    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
};

static void FieldElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    (void)dummy;
    (void)elementRecord;
    (void)tkwin;
    (void)widthPtr;
    (void)heightPtr;

    *paddingPtr = Ttk_UniformPadding(2);
}

static void FieldElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned state)
{
    FieldElement *field = elementRecord;
    FieldElement *field = (FieldElement *)elementRecord;
    Tk_3DBorder bg = Tk_Get3DBorderFromObj(tkwin, field->backgroundObj);
    Ttk_Box f = Ttk_PadBox(b, Ttk_UniformPadding(2));
    Tcl_Obj *outer = field->borderColorObj,
	    *inner = field->lightColorObj;
    (void)dummy;
    (void)state;

    DrawSmoothBorder(tkwin, d, b, outer, inner, inner);
    Tk_Fill3DRectangle(
	tkwin, d, bg, f.x, f.y, f.width, f.height, 0, TK_RELIEF_SUNKEN);
}

static Ttk_ElementSpec FieldElementSpec = {
static const Ttk_ElementSpec FieldElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(FieldElement),
    FieldElementOptions,
    FieldElementSize,
    FieldElementDraw
};

/*
 * Modified field element for comboboxes:
 * 	Right edge is expanded to overlap the dropdown button.
 */
static void ComboboxFieldElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned state)
{
    FieldElement *field = elementRecord;
    FieldElement *field = (FieldElement *)elementRecord;
    GC gc = Ttk_GCForColor(tkwin,field->borderColorObj,d);

    ++b.width;
    FieldElementDraw(clientData, elementRecord, tkwin, d, b, state);

    XDrawLine(Tk_Display(tkwin), d, gc,
	    b.x + b.width - 1, b.y,
	    b.x + b.width - 1, b.y + b.height - 1 + WIN32_XDRAWLINE_HACK);
}

static Ttk_ElementSpec ComboboxFieldElementSpec = {
static const Ttk_ElementSpec ComboboxFieldElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(FieldElement),
    FieldElementOptions,
    FieldElementSize,
    ComboboxFieldElementDraw
};

/*------------------------------------------------------------------------
 * +++ Indicator elements for check and radio buttons.
 */

typedef struct {
    Tcl_Obj *sizeObj;
    Tcl_Obj *marginObj;
    Tcl_Obj *backgroundObj;
    Tcl_Obj *foregroundObj;
    Tcl_Obj *upperColorObj;
    Tcl_Obj *lowerColorObj;
} IndicatorElement;

static Ttk_ElementOptionSpec IndicatorElementOptions[] = {
static const Ttk_ElementOptionSpec IndicatorElementOptions[] = {
    { "-indicatorsize", TK_OPTION_PIXELS,
	Tk_Offset(IndicatorElement,sizeObj), "10" },
	offsetof(IndicatorElement,sizeObj), "10" },
    { "-indicatormargin", TK_OPTION_STRING,
	Tk_Offset(IndicatorElement,marginObj), "1" },
	offsetof(IndicatorElement,marginObj), "1" },
    { "-indicatorbackground", TK_OPTION_COLOR,
	Tk_Offset(IndicatorElement,backgroundObj), "white" },
	offsetof(IndicatorElement,backgroundObj), "white" },
    { "-indicatorforeground", TK_OPTION_COLOR,
	Tk_Offset(IndicatorElement,foregroundObj), "black" },
	offsetof(IndicatorElement,foregroundObj), "black" },
    { "-upperbordercolor", TK_OPTION_COLOR,
	Tk_Offset(IndicatorElement,upperColorObj), DARKEST_COLOR },
	offsetof(IndicatorElement,upperColorObj), DARKEST_COLOR },
    { "-lowerbordercolor", TK_OPTION_COLOR,
	Tk_Offset(IndicatorElement,lowerColorObj), DARK_COLOR },
    { NULL, 0, 0, NULL }
	offsetof(IndicatorElement,lowerColorObj), DARK_COLOR },
    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
};

static void IndicatorElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    IndicatorElement *indicator = elementRecord;
    IndicatorElement *indicator = (IndicatorElement *)elementRecord;
    Ttk_Padding margins;
    int size = 10;
    (void)dummy;
    (void)paddingPtr;

    Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &margins);
    Tk_GetPixelsFromObj(NULL, tkwin, indicator->sizeObj, &size);
    *widthPtr = size + Ttk_PaddingWidth(margins);
    *heightPtr = size + Ttk_PaddingHeight(margins);
}

static void RadioIndicatorElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned state)
{
    IndicatorElement *indicator = elementRecord;
    IndicatorElement *indicator = (IndicatorElement *)elementRecord;
    GC gcb=Ttk_GCForColor(tkwin,indicator->backgroundObj,d);
    GC gcf=Ttk_GCForColor(tkwin,indicator->foregroundObj,d);
    GC gcu=Ttk_GCForColor(tkwin,indicator->upperColorObj,d);
    GC gcl=Ttk_GCForColor(tkwin,indicator->lowerColorObj,d);
    Ttk_Padding padding;
    (void)dummy;

    Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &padding);
    b = Ttk_PadBox(b, padding);

    XFillArc(Tk_Display(tkwin),d,gcb, b.x,b.y,b.width,b.height, 0,360*64);
    XDrawArc(Tk_Display(tkwin),d,gcl, b.x,b.y,b.width,b.height, 225*64,180*64);
    XDrawArc(Tk_Display(tkwin),d,gcu, b.x,b.y,b.width,b.height, 45*64,180*64);

    if (state & TTK_STATE_SELECTED) {
	b = Ttk_PadBox(b,Ttk_UniformPadding(3));
	XFillArc(Tk_Display(tkwin),d,gcf, b.x,b.y,b.width,b.height, 0,360*64);
	XDrawArc(Tk_Display(tkwin),d,gcf, b.x,b.y,b.width,b.height, 0,360*64);
#if WIN32_XDRAWLINE_HACK
	XDrawArc(Tk_Display(tkwin),d,gcf, b.x,b.y,b.width,b.height, 300*64,360*64);
#endif
    }
}

static void CheckIndicatorElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned state)
{
    Display *display = Tk_Display(tkwin);
    IndicatorElement *indicator = elementRecord;
    IndicatorElement *indicator = (IndicatorElement *)elementRecord;

    GC gcb=Ttk_GCForColor(tkwin,indicator->backgroundObj,d);
    GC gcf=Ttk_GCForColor(tkwin,indicator->foregroundObj,d);
    GC gcu=Ttk_GCForColor(tkwin,indicator->upperColorObj,d);
    GC gcl=Ttk_GCForColor(tkwin,indicator->lowerColorObj,d);
    Ttk_Padding padding;
    const int w = WIN32_XDRAWLINE_HACK;
    (void)dummy;

    Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &padding);
    b = Ttk_PadBox(b, padding);

    XFillRectangle(display,d,gcb, b.x,b.y,b.width,b.height);
    XDrawLine(display,d,gcl,b.x,b.y+b.height,b.x+b.width+w,b.y+b.height);/*S*/
    XDrawLine(display,d,gcl,b.x+b.width,b.y,b.x+b.width,b.y+b.height+w); /*E*/
371
372
373
374
375
376
377
378

379
380
381
382
383
384
385
386

387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402

403
404
405

406
407
408

409
410
411

412
413

414
415
416
417

418
419
420

421
422



423
424
425
426
427
428
429
430
431

432
433
434

435
436
437
438


439
440
441
442
443
444
445
446
447

448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472

473
474

475
476

477
478
479


480
481
482
483
484
485
486
487


488


489
490
491

492
493
494
495
496
497
498
499
500
501
502
503
504


505
506
507
508

509
510
511
512

513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529

530
531
532
533
534
535
536
391
392
393
394
395
396
397

398
399
400
401
402
403
404
405

406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421

422
423
424

425
426
427

428
429
430

431
432

433
434
435
436

437
438
439

440
441
442
443
444
445
446
447
448
449
450
451
452
453

454
455
456

457
458
459
460
461
462
463
464
465
466
467
468
469
470
471

472
473
474
475
476
477
478
479
480
481
482
483
484
485
486




487
488
489
490
491
492

493
494

495
496

497
498


499
500
501
502
503
504
505
506


507
508
509
510
511
512
513

514
515
516
517
518
519
520
521
522
523
524
525


526
527
528
529
530
531
532
533
534
535

536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552

553
554
555
556
557
558
559
560







-
+







-
+















-
+


-
+


-
+


-
+

-
+



-
+


-
+


+
+
+








-
+


-
+




+
+








-
+














-
-
-
-






-
+

-
+

-
+

-
-
+
+






-
-
+
+

+
+


-
+











-
-
+
+




+



-
+
















-
+







	s-=w, q-=w;
	XDrawLine(display, d, gcf, p,   s,   r,   q);
	XDrawLine(display, d, gcf, p+1, s,   r,   q+1);
	XDrawLine(display, d, gcf, p,   s-1, r-1, q);
    }
}

static Ttk_ElementSpec RadioIndicatorElementSpec = {
static const Ttk_ElementSpec RadioIndicatorElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(IndicatorElement),
    IndicatorElementOptions,
    IndicatorElementSize,
    RadioIndicatorElementDraw
};

static Ttk_ElementSpec CheckIndicatorElementSpec = {
static const Ttk_ElementSpec CheckIndicatorElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(IndicatorElement),
    IndicatorElementOptions,
    IndicatorElementSize,
    CheckIndicatorElementDraw
};

#define MENUBUTTON_ARROW_SIZE 5

typedef struct {
    Tcl_Obj *sizeObj;
    Tcl_Obj *colorObj;
    Tcl_Obj *paddingObj;
} MenuIndicatorElement;

static Ttk_ElementOptionSpec MenuIndicatorElementOptions[] =
static const Ttk_ElementOptionSpec MenuIndicatorElementOptions[] =
{
    { "-arrowsize", TK_OPTION_PIXELS,
	Tk_Offset(MenuIndicatorElement,sizeObj), 
	offsetof(MenuIndicatorElement,sizeObj),
	STR(MENUBUTTON_ARROW_SIZE)},
    { "-arrowcolor",TK_OPTION_COLOR,
	Tk_Offset(MenuIndicatorElement,colorObj),
	offsetof(MenuIndicatorElement,colorObj),
	"black" },
    { "-arrowpadding",TK_OPTION_STRING,
	Tk_Offset(MenuIndicatorElement,paddingObj),
	offsetof(MenuIndicatorElement,paddingObj),
	"3" },
    { NULL, 0, 0, NULL }
    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
};

static void MenuIndicatorElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    MenuIndicatorElement *indicator = elementRecord;
    MenuIndicatorElement *indicator = (MenuIndicatorElement *)elementRecord;
    Ttk_Padding margins;
    int size = MENUBUTTON_ARROW_SIZE;
    (void)dummy;
    (void)paddingPtr;

    Tk_GetPixelsFromObj(NULL, tkwin, indicator->sizeObj, &size);
    Ttk_GetPaddingFromObj(NULL, tkwin, indicator->paddingObj, &margins);
    TtkArrowSize(size, ARROW_DOWN, widthPtr, heightPtr);
    *widthPtr += Ttk_PaddingWidth(margins);
    *heightPtr += Ttk_PaddingHeight(margins);
}

static void MenuIndicatorElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    MenuIndicatorElement *indicator = elementRecord;
    MenuIndicatorElement *indicator = (MenuIndicatorElement *)elementRecord;
    XColor *arrowColor = Tk_GetColorFromObj(tkwin, indicator->colorObj);
    GC gc = Tk_GCForColor(arrowColor, d);
    int size = MENUBUTTON_ARROW_SIZE;
    int width, height;
    (void)dummy;
    (void)state;

    Tk_GetPixelsFromObj(NULL, tkwin, indicator->sizeObj, &size);

    TtkArrowSize(size, ARROW_DOWN, &width, &height);
    b = Ttk_StickBox(b, width, height, 0);
    TtkFillArrow(Tk_Display(tkwin), d, gc, b, ARROW_DOWN);
}

static Ttk_ElementSpec MenuIndicatorElementSpec =
static const Ttk_ElementSpec MenuIndicatorElementSpec =
{
    TK_STYLE_VERSION_2,
    sizeof(MenuIndicatorElement),
    MenuIndicatorElementOptions,
    MenuIndicatorElementSize,
    MenuIndicatorElementDraw
};

/*------------------------------------------------------------------------
 * +++ Grips.
 *
 * TODO: factor this with ThumbElementDraw
 */

static Ttk_Orient GripClientData[] = {
    TTK_ORIENT_HORIZONTAL, TTK_ORIENT_VERTICAL
};

typedef struct {
    Tcl_Obj 	*lightColorObj;
    Tcl_Obj 	*borderColorObj;
    Tcl_Obj 	*gripCountObj;
} GripElement;

static Ttk_ElementOptionSpec GripElementOptions[] = {
static const Ttk_ElementOptionSpec GripElementOptions[] = {
    { "-lightcolor", TK_OPTION_COLOR,
	Tk_Offset(GripElement,lightColorObj), LIGHT_COLOR },
	offsetof(GripElement,lightColorObj), LIGHT_COLOR },
    { "-bordercolor", TK_OPTION_COLOR,
	Tk_Offset(GripElement,borderColorObj), DARKEST_COLOR },
	offsetof(GripElement,borderColorObj), DARKEST_COLOR },
    { "-gripcount", TK_OPTION_INT,
	Tk_Offset(GripElement,gripCountObj), "5" },
    { NULL, 0, 0, NULL }
	offsetof(GripElement,gripCountObj), "5" },
    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
};

static void GripElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    int horizontal = *((Ttk_Orient*)clientData) == TTK_ORIENT_HORIZONTAL;
    GripElement *grip = elementRecord;
    Ttk_Orient orient = (Ttk_Orient)PTR2INT(clientData);
    GripElement *grip = (GripElement *)elementRecord;
    int gripCount = 0;
    (void)tkwin;
    (void)paddingPtr;

    Tcl_GetIntFromObj(NULL, grip->gripCountObj, &gripCount);
    if (horizontal) {
    if (orient == TTK_ORIENT_HORIZONTAL) {
	*widthPtr = 2*gripCount;
    } else {
	*heightPtr = 2*gripCount;
    }
}

static void GripElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned state)
{
    const int w = WIN32_XDRAWLINE_HACK;
    int horizontal = *((Ttk_Orient*)clientData) == TTK_ORIENT_HORIZONTAL;
    GripElement *grip = elementRecord;
    Ttk_Orient orient = (Ttk_Orient)PTR2INT(clientData);
    GripElement *grip = (GripElement *)elementRecord;
    GC lightGC = Ttk_GCForColor(tkwin,grip->lightColorObj,d);
    GC darkGC = Ttk_GCForColor(tkwin,grip->borderColorObj,d);
    int gripPad = 1, gripCount = 0;
    int i;
    (void)state;

    Tcl_GetIntFromObj(NULL, grip->gripCountObj, &gripCount);

    if (horizontal) {
    if (orient == TTK_ORIENT_HORIZONTAL) {
	int x = b.x + b.width / 2 - gripCount;
	int y1 = b.y + gripPad, y2 = b.y + b.height - gripPad - 1 + w;
	for (i=0; i<gripCount; ++i) {
	    XDrawLine(Tk_Display(tkwin), d, darkGC,  x,y1, x,y2); ++x;
	    XDrawLine(Tk_Display(tkwin), d, lightGC, x,y1, x,y2); ++x;
	}
    } else {
	int y = b.y + b.height / 2 - gripCount;
	int x1 = b.x + gripPad, x2 = b.x + b.width - gripPad - 1 + w;
	for (i=0; i<gripCount; ++i) {
	    XDrawLine(Tk_Display(tkwin), d, darkGC,  x1,y, x2,y); ++y;
	    XDrawLine(Tk_Display(tkwin), d, lightGC, x1,y, x2,y); ++y;
	}
    }
}

static Ttk_ElementSpec GripElementSpec = {
static const Ttk_ElementSpec GripElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(GripElement),
    GripElementOptions,
    GripElementSize,
    GripElementDraw
};

550
551
552
553
554
555
556
557

558
559

560
561

562
563

564
565

566
567

568
569

570
571

572
573

574
575

576
577
578


579
580
581
582

583
584
585

586
587



588
589
590
591
592

593
594
595
596
597
598
599
600
601

602
603
604

605




606
607
608
609
610
611

612
613
614
615



616
617
618


619
620
621
622
623
624
625
626
627
628
629

630
631
632
633

634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654

655
656
657
658
659
660
661
662
663
664
665
666

667
668
669
670





671
672
673

674
675
676
677
678
679
680
681
682
683
684
685
686

687
688
689
690
691
692
693
574
575
576
577
578
579
580

581
582

583
584

585
586

587
588

589
590

591
592

593
594

595
596

597
598

599
600


601
602
603
604
605

606
607
608

609
610
611
612
613
614
615
616
617
618

619
620
621
622
623
624
625
626
627

628
629
630

631
632
633
634
635
636
637
638
639
640
641

642
643
644


645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662

663
664
665
666

667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687

688
689
690
691
692
693
694
695
696
697
698
699

700
701
702


703
704
705
706
707
708
709

710
711
712
713
714
715
716
717
718
719
720
721
722

723
724
725
726
727
728
729
730







-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
-
+
+



-
+


-
+


+
+
+




-
+








-
+


-
+

+
+
+
+





-
+


-
-
+
+
+



+
+










-
+



-
+




















-
+











-
+


-
-
+
+
+
+
+


-
+












-
+







    Tcl_Obj 	*darkColorObj;
    Tcl_Obj 	*arrowColorObj;
    Tcl_Obj 	*arrowSizeObj;
    Tcl_Obj 	*gripCountObj;
    Tcl_Obj 	*sliderlengthObj;
} ScrollbarElement;

static Ttk_ElementOptionSpec ScrollbarElementOptions[] = {
static const Ttk_ElementOptionSpec ScrollbarElementOptions[] = {
    { "-orient", TK_OPTION_ANY,
	Tk_Offset(ScrollbarElement, orientObj), "horizontal" },
	offsetof(ScrollbarElement, orientObj), "horizontal" },
    { "-background", TK_OPTION_BORDER,
	Tk_Offset(ScrollbarElement,backgroundObj), FRAME_COLOR },
	offsetof(ScrollbarElement,backgroundObj), FRAME_COLOR },
    { "-bordercolor", TK_OPTION_COLOR,
	Tk_Offset(ScrollbarElement,borderColorObj), DARKEST_COLOR },
	offsetof(ScrollbarElement,borderColorObj), DARKEST_COLOR },
    { "-troughcolor", TK_OPTION_COLOR,
	Tk_Offset(ScrollbarElement,troughColorObj), DARKER_COLOR },
	offsetof(ScrollbarElement,troughColorObj), DARKER_COLOR },
    { "-lightcolor", TK_OPTION_COLOR,
	Tk_Offset(ScrollbarElement,lightColorObj), LIGHT_COLOR },
	offsetof(ScrollbarElement,lightColorObj), LIGHT_COLOR },
    { "-darkcolor", TK_OPTION_COLOR,
	Tk_Offset(ScrollbarElement,darkColorObj), DARK_COLOR },
	offsetof(ScrollbarElement,darkColorObj), DARK_COLOR },
    { "-arrowcolor", TK_OPTION_COLOR,
	Tk_Offset(ScrollbarElement,arrowColorObj), "#000000" },
	offsetof(ScrollbarElement,arrowColorObj), "#000000" },
    { "-arrowsize", TK_OPTION_PIXELS,
	Tk_Offset(ScrollbarElement,arrowSizeObj), STR(SCROLLBAR_THICKNESS) },
	offsetof(ScrollbarElement,arrowSizeObj), STR(SCROLLBAR_THICKNESS) },
    { "-gripcount", TK_OPTION_INT,
	Tk_Offset(ScrollbarElement,gripCountObj), "5" },
	offsetof(ScrollbarElement,gripCountObj), "5" },
    { "-sliderlength", TK_OPTION_INT,
	Tk_Offset(ScrollbarElement,sliderlengthObj), "30" },
    { NULL, 0, 0, NULL }
	offsetof(ScrollbarElement,sliderlengthObj), "30" },
    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
};

static void TroughElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned state)
{
    ScrollbarElement *sb = elementRecord;
    ScrollbarElement *sb = (ScrollbarElement *)elementRecord;
    GC gcb = Ttk_GCForColor(tkwin,sb->borderColorObj,d);
    GC gct = Ttk_GCForColor(tkwin,sb->troughColorObj,d);
    (void)dummy;
    (void)state;

    XFillRectangle(Tk_Display(tkwin), d, gct, b.x, b.y, b.width-1, b.height-1);
    XDrawRectangle(Tk_Display(tkwin), d, gcb, b.x, b.y, b.width-1, b.height-1);
}

static Ttk_ElementSpec TroughElementSpec = {
static const Ttk_ElementSpec TroughElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(ScrollbarElement),
    ScrollbarElementOptions,
    TtkNullElementSize,
    TroughElementDraw
};

static void ThumbElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    ScrollbarElement *sb = elementRecord;
    ScrollbarElement *sb = (ScrollbarElement *)elementRecord;
    int size = SCROLLBAR_THICKNESS;
    (void)dummy;
    (void)tkwin;
    (void)paddingPtr;

    Tcl_GetIntFromObj(NULL, sb->arrowSizeObj, &size);
    *widthPtr = *heightPtr = size;
}

static void ThumbElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned state)
{
    ScrollbarElement *sb = elementRecord;
    int gripCount = 0, orient = TTK_ORIENT_HORIZONTAL;
    ScrollbarElement *sb = (ScrollbarElement *)elementRecord;
    int gripCount = 0;
    Ttk_Orient orient = TTK_ORIENT_HORIZONTAL;
    GC lightGC, darkGC;
    int x1, y1, x2, y2, dx, dy, i;
    const int w = WIN32_XDRAWLINE_HACK;
    (void)dummy;
    (void)state;

    DrawSmoothBorder(tkwin, d, b,
	sb->borderColorObj, sb->lightColorObj, sb->darkColorObj);
    XFillRectangle(
	Tk_Display(tkwin), d, BackgroundGC(tkwin, sb->backgroundObj),
	b.x+2, b.y+2, b.width-4, b.height-4);

    /*
     * Draw grip:
     */
    Ttk_GetOrientFromObj(NULL, sb->orientObj, &orient);
    TtkGetOrientFromObj(NULL, sb->orientObj, &orient);
    Tcl_GetIntFromObj(NULL, sb->gripCountObj, &gripCount);
    lightGC = Ttk_GCForColor(tkwin,sb->lightColorObj,d);
    darkGC = Ttk_GCForColor(tkwin,sb->borderColorObj,d);
    

    if (orient == TTK_ORIENT_HORIZONTAL) {
	dx = 1; dy = 0;
	x1 = x2 = b.x + b.width / 2 - gripCount;
	y1 = b.y + 2;
	y2 = b.y + b.height - 3 + w;
    } else {
	dx = 0; dy = 1;
	y1 = y2 = b.y + b.height / 2 - gripCount;
	x1 = b.x + 2;
	x2 = b.x + b.width - 3 + w;
    }

    for (i=0; i<gripCount; ++i) {
	XDrawLine(Tk_Display(tkwin), d, darkGC, x1,y1, x2,y2);
	x1 += dx; x2 += dx; y1 += dy; y2 += dy;
	XDrawLine(Tk_Display(tkwin), d, lightGC, x1,y1, x2,y2);
	x1 += dx; x2 += dx; y1 += dy; y2 += dy;
    }
}

static Ttk_ElementSpec ThumbElementSpec = {
static const Ttk_ElementSpec ThumbElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(ScrollbarElement),
    ScrollbarElementOptions,
    ThumbElementSize,
    ThumbElementDraw
};

/*------------------------------------------------------------------------
 * +++ Slider element.
 */
static void SliderElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    ScrollbarElement *sb = elementRecord;
    int length, thickness, orient;
    ScrollbarElement *sb = (ScrollbarElement *)elementRecord;
    int length, thickness;
    Ttk_Orient orient;
    (void)dummy;
    (void)paddingPtr;

    length = thickness = SCROLLBAR_THICKNESS;
    Ttk_GetOrientFromObj(NULL, sb->orientObj, &orient);
    TtkGetOrientFromObj(NULL, sb->orientObj, &orient);
    Tcl_GetIntFromObj(NULL, sb->arrowSizeObj, &thickness);
    Tk_GetPixelsFromObj(NULL, tkwin, sb->sliderlengthObj, &length);
    if (orient == TTK_ORIENT_VERTICAL) {
	*heightPtr = length;
	*widthPtr = thickness;
    } else {
	*heightPtr = thickness;
	*widthPtr = length;
    }

}

static Ttk_ElementSpec SliderElementSpec = {
static const Ttk_ElementSpec SliderElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(ScrollbarElement),
    ScrollbarElementOptions,
    SliderElementSize,
    ThumbElementDraw
};

702
703
704
705
706
707
708
709

710
711
712
713




714
715
716
717
718

719
720
721
722
723
724

725
726
727
728
729
730
731
732
733
734
735
736
737
738
739

740
741
742

743




744
745
746
747
748
749
750
751
752
753


754
755

756
757
758
759
760
761
762
763
764
765
766

767
768
769

770
771
772

773
774
775
776
777
778
779
780
781
782
783
784


785
786
787
788
789
790
791
792
793
794
795

796
797

798
799

800
801

802
803
804


805
806
807
808

809
810
811






812
813
814
815
816
817

818
819
820

821
822
823
824
825
826

827
828
829
830
831
832
833
739
740
741
742
743
744
745

746
747
748


749
750
751
752
753
754
755
756

757
758
759
760
761
762

763
764
765
766
767
768
769
770
771
772
773
774


775

776
777
778

779
780
781
782
783
784
785
786
787
788
789
790
791
792


793
794
795
796
797
798
799
800
801
802
803
804
805
806
807

808
809
810

811
812
813

814
815
816
817
818
819
820
821
822
823
824


825
826
827
828
829
830
831
832
833
834
835
836

837
838

839
840

841
842

843
844


845
846
847
848
849

850
851
852
853
854
855
856
857
858
859
860
861
862
863
864

865
866
867

868
869
870
871
872
873
874
875
876
877
878
879
880
881
882







-
+


-
-
+
+
+
+




-
+





-
+











-
-

-
+


-
+

+
+
+
+








-
-
+
+


+










-
+


-
+


-
+










-
-
+
+










-
+

-
+

-
+

-
+

-
-
+
+



-
+



+
+
+
+
+
+





-
+


-
+






+







	    widthPtr, heightPtr, paddingPtr);
    *paddingPtr = Ttk_UniformPadding(2);
    *widthPtr += 4;
    *heightPtr += 4;
}

static void PbarElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned state)
{
    ScrollbarElement *sb = elementRecord;
    
    ScrollbarElement *sb = (ScrollbarElement *)elementRecord;
    (void)dummy;
    (void)state;

    b = Ttk_PadBox(b, Ttk_UniformPadding(2));
    if (b.width > 4 && b.height > 4) {
	DrawSmoothBorder(tkwin, d, b,
	    sb->borderColorObj, sb->lightColorObj, sb->darkColorObj);
	XFillRectangle(Tk_Display(tkwin), d, 
	XFillRectangle(Tk_Display(tkwin), d,
	    BackgroundGC(tkwin, sb->backgroundObj),
	    b.x+2, b.y+2, b.width-4, b.height-4);
    }
}

static Ttk_ElementSpec PbarElementSpec = {
static const Ttk_ElementSpec PbarElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(ScrollbarElement),
    ScrollbarElementOptions,
    PbarElementSize,
    PbarElementDraw
};


/*------------------------------------------------------------------------
 * +++ Scrollbar arrows.
 */
static int ArrowElements[] = { ARROW_UP, ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT };

static void ArrowElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    ScrollbarElement *sb = elementRecord;
    ScrollbarElement *sb = (ScrollbarElement *)elementRecord;
    int size = SCROLLBAR_THICKNESS;
    (void)dummy;
    (void)tkwin;
    (void)paddingPtr;

    Tcl_GetIntFromObj(NULL, sb->arrowSizeObj, &size);
    *widthPtr = *heightPtr = size;
}

static void ArrowElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned state)
{
    ArrowDirection dir = *(ArrowDirection*)clientData;
    ScrollbarElement *sb = elementRecord;
    ArrowDirection direction = (ArrowDirection)PTR2INT(clientData);
    ScrollbarElement *sb = (ScrollbarElement *)elementRecord;
    GC gc = Ttk_GCForColor(tkwin,sb->arrowColorObj, d);
    int h, cx, cy;
    (void)state;

    DrawSmoothBorder(tkwin, d, b,
	sb->borderColorObj, sb->lightColorObj, sb->darkColorObj);

    XFillRectangle(
	Tk_Display(tkwin), d, BackgroundGC(tkwin, sb->backgroundObj),
	b.x+2, b.y+2, b.width-4, b.height-4);

    b = Ttk_PadBox(b, Ttk_UniformPadding(3));
    h = b.width < b.height ? b.width : b.height;
    TtkArrowSize(h/2, dir, &cx, &cy);
    TtkArrowSize(h/2, direction, &cx, &cy);
    b = Ttk_AnchorBox(b, cx, cy, TK_ANCHOR_CENTER);

    TtkFillArrow(Tk_Display(tkwin), d, gc, b, dir);
    TtkFillArrow(Tk_Display(tkwin), d, gc, b, direction);
}

static Ttk_ElementSpec ArrowElementSpec = {
static const Ttk_ElementSpec ArrowElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(ScrollbarElement),
    ScrollbarElementOptions,
    ArrowElementSize,
    ArrowElementDraw
};


/*------------------------------------------------------------------------
 * +++ Notebook elements.
 * 	
 * Note: Tabs, except for the rightmost, overlap the neighbor to 
 *
 * Note: Tabs, except for the rightmost, overlap the neighbor to
 * their right by one pixel.
 */

typedef struct {
    Tcl_Obj *backgroundObj;
    Tcl_Obj *borderColorObj;
    Tcl_Obj *lightColorObj;
    Tcl_Obj *darkColorObj;
} NotebookElement;

static Ttk_ElementOptionSpec NotebookElementOptions[] = {
static const Ttk_ElementOptionSpec NotebookElementOptions[] = {
    { "-background", TK_OPTION_BORDER,
	Tk_Offset(NotebookElement,backgroundObj), FRAME_COLOR },
	offsetof(NotebookElement,backgroundObj), FRAME_COLOR },
    { "-bordercolor", TK_OPTION_COLOR,
	Tk_Offset(NotebookElement,borderColorObj), DARKEST_COLOR },
	offsetof(NotebookElement,borderColorObj), DARKEST_COLOR },
    { "-lightcolor", TK_OPTION_COLOR,
	Tk_Offset(NotebookElement,lightColorObj), LIGHT_COLOR },
	offsetof(NotebookElement,lightColorObj), LIGHT_COLOR },
    { "-darkcolor", TK_OPTION_COLOR,
	Tk_Offset(NotebookElement,darkColorObj), DARK_COLOR },
    { NULL, 0, 0, NULL }
	offsetof(NotebookElement,darkColorObj), DARK_COLOR },
    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
};

static void TabElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    int borderWidth = 2;
    (void)dummy;
    (void)elementRecord;
    (void)tkwin;
    (void)widthPtr;
    (void)heightPtr;

    paddingPtr->top = paddingPtr->left = paddingPtr->right = borderWidth;
    paddingPtr->bottom = 0;
}

static void TabElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    NotebookElement *tab = elementRecord;
    NotebookElement *tab = (NotebookElement *)elementRecord;
    Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, tab->backgroundObj);
    Display *display = Tk_Display(tkwin);
    int borderWidth = 2, dh = 0;
    int x1,y1,x2,y2;
    GC gc;
    const int w = WIN32_XDRAWLINE_HACK;
    (void)dummy;

    if (state & TTK_STATE_SELECTED) {
	dh = borderWidth;
    }

    if (state & TTK_STATE_USER2) {	/* Rightmost tab */
	--b.width;
846
847
848
849
850
851
852
853

854
855
856
857
858
859
860
861
862
863

864
865
866






867
868
869
870
871

872
873
874

875
876


877
878
879
880
881
882
883
884

885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901

902
903
904
905
906
907
908
895
896
897
898
899
900
901

902
903
904
905
906
907
908
909
910
911

912
913
914
915
916
917
918
919
920
921
922
923
924
925

926
927
928

929
930
931
932
933
934
935
936
937
938
939
940

941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957

958
959
960
961
962
963
964
965







-
+









-
+



+
+
+
+
+
+




-
+


-
+


+
+







-
+
















-
+







    XDrawLine(display,d,gc, x1+1,y1, x2-1+w,y1);

    gc=Ttk_GCForColor(tkwin,tab->lightColorObj,d);
    XDrawLine(display,d,gc, x1+1,y1+1, x1+1,y2-1+dh+w);
    XDrawLine(display,d,gc, x1+1,y1+1, x2-1+w,y1+1);
}

static Ttk_ElementSpec TabElementSpec =
static const Ttk_ElementSpec TabElementSpec =
{
    TK_STYLE_VERSION_2,
    sizeof(NotebookElement),
    NotebookElementOptions,
    TabElementSize,
    TabElementDraw
};

static void ClientElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    int borderWidth = 2;
    (void)dummy;
    (void)elementRecord;
    (void)tkwin;
    (void)widthPtr;
    (void)heightPtr;

    *paddingPtr = Ttk_UniformPadding((short)borderWidth);
}

static void ClientElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    NotebookElement *ce = elementRecord;
    NotebookElement *ce = (NotebookElement *)elementRecord;
    Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, ce->backgroundObj);
    int borderWidth = 2;
    (void)dummy;
    (void)state;

    Tk_Fill3DRectangle(tkwin, d, border,
	b.x, b.y, b.width, b.height, borderWidth,TK_RELIEF_FLAT);
    DrawSmoothBorder(tkwin, d, b,
    	ce->borderColorObj, ce->lightColorObj, ce->darkColorObj);
}

static Ttk_ElementSpec ClientElementSpec =
static const Ttk_ElementSpec ClientElementSpec =
{
    TK_STYLE_VERSION_2,
    sizeof(NotebookElement),
    NotebookElementOptions,
    ClientElementSize,
    ClientElementDraw
};

/*------------------------------------------------------------------------
 * +++ Modified widget layouts.
 */

TTK_BEGIN_LAYOUT_TABLE(LayoutTable)

TTK_LAYOUT("TCombobox",
    TTK_NODE("Combobox.downarrow", TTK_PACK_RIGHT|TTK_FILL_Y)
    TTK_GROUP("Combobox.field", TTK_PACK_LEFT|TTK_FILL_BOTH|TTK_EXPAND,
    TTK_GROUP("Combobox.field", TTK_FILL_BOTH,
	TTK_GROUP("Combobox.padding", TTK_FILL_BOTH,
	    TTK_NODE("Combobox.textarea", TTK_FILL_BOTH))))

TTK_LAYOUT("Horizontal.Sash",
    TTK_GROUP("Sash.hsash", TTK_FILL_BOTH,
	TTK_NODE("Sash.hgrip", TTK_FILL_BOTH)))

932
933
934
935
936
937
938
939

940
941

942
943

944
945

946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962

963
964

965
966
967
968
969
970
971
989
990
991
992
993
994
995

996
997

998
999

1000
1001

1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018

1019
1020

1021
1022
1023
1024
1025
1026
1027
1028







-
+

-
+

-
+

-
+
















-
+

-
+







    Ttk_RegisterElement(interp,
	theme, "Combobox.field", &ComboboxFieldElementSpec, NULL);
    Ttk_RegisterElement(interp,
	theme, "trough", &TroughElementSpec, NULL);
    Ttk_RegisterElement(interp,
	theme, "thumb", &ThumbElementSpec, NULL);
    Ttk_RegisterElement(interp,
	theme, "uparrow", &ArrowElementSpec, &ArrowElements[0]);
	theme, "uparrow", &ArrowElementSpec, INT2PTR(ARROW_UP));
    Ttk_RegisterElement(interp,
	theme, "downarrow", &ArrowElementSpec, &ArrowElements[1]);
	theme, "downarrow", &ArrowElementSpec, INT2PTR(ARROW_DOWN));
    Ttk_RegisterElement(interp,
	theme, "leftarrow", &ArrowElementSpec, &ArrowElements[2]);
	theme, "leftarrow", &ArrowElementSpec, INT2PTR(ARROW_LEFT));
    Ttk_RegisterElement(interp,
	theme, "rightarrow", &ArrowElementSpec, &ArrowElements[3]);
	theme, "rightarrow", &ArrowElementSpec, INT2PTR(ARROW_RIGHT));

    Ttk_RegisterElement(interp,
	theme, "Radiobutton.indicator", &RadioIndicatorElementSpec, NULL);
    Ttk_RegisterElement(interp,
	theme, "Checkbutton.indicator", &CheckIndicatorElementSpec, NULL);
    Ttk_RegisterElement(interp,
	theme, "Menubutton.indicator", &MenuIndicatorElementSpec, NULL);

    Ttk_RegisterElement(interp, theme, "tab", &TabElementSpec, NULL);
    Ttk_RegisterElement(interp, theme, "client", &ClientElementSpec, NULL);

    Ttk_RegisterElement(interp, theme, "slider", &SliderElementSpec, NULL);
    Ttk_RegisterElement(interp, theme, "bar", &PbarElementSpec, NULL);
    Ttk_RegisterElement(interp, theme, "pbar", &PbarElementSpec, NULL);

    Ttk_RegisterElement(interp, theme, "hgrip",
	    &GripElementSpec,  &GripClientData[0]);
	    &GripElementSpec,  INT2PTR(TTK_ORIENT_HORIZONTAL));
    Ttk_RegisterElement(interp, theme, "vgrip",
	    &GripElementSpec,  &GripClientData[1]);
	    &GripElementSpec,  INT2PTR(TTK_ORIENT_VERTICAL));

    Ttk_RegisterLayouts(theme, LayoutTable);

    Tcl_PkgProvide(interp, "ttk::theme::clam", TTK_VERSION);

    return TCL_OK;
}
Changes to generic/ttk/ttkClassicTheme.c.
1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2004, Joe English
 * Copyright © 2004, Joe English
 *
 * "classic" theme; implements the classic Motif-like Tk look.
 *
 */

#include "tkInt.h"
#include "ttkTheme.h"
17
18
19
20
21
22
23
24

25
26

27
28
29


30
31
32
33

34
35
36

37




38
39
40
41
42
43
44

45
46
47

48
49



50
51
52
53
54
55
56
57
58

59
60
61
62
63
64
65
66
67
68
69

70
71
72
73
74
75
76
77
78
79
80
81
82
83
84

85
86
87
88
89
90
91
92
93
94









95
96
97
98

99
100
101
102


103




104
105
106
107
108
109
110
111
112
113
114
115
116

117
118
119
120

121
122
123

124
125
126

127


128
129
130
131
132
133
134
17
18
19
20
21
22
23

24
25

26
27


28
29
30
31
32

33
34
35

36
37
38
39
40
41
42
43
44
45
46
47

48
49
50

51
52
53
54
55
56
57
58
59
60
61
62
63
64

65
66
67
68
69
70
71
72
73
74
75

76
77
78
79
80
81
82
83
84
85
86
87
88
89
90

91
92









93
94
95
96
97
98
99
100
101
102
103
104

105
106
107


108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126

127
128
129
130

131
132
133

134
135
136

137
138
139
140
141
142
143
144
145
146
147







-
+

-
+

-
-
+
+



-
+


-
+

+
+
+
+






-
+


-
+


+
+
+








-
+










-
+














-
+

-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+



-
+


-
-
+
+

+
+
+
+












-
+



-
+


-
+


-
+

+
+







 */

typedef struct {
    Tcl_Obj	*highlightColorObj;
    Tcl_Obj	*highlightThicknessObj;
} HighlightElement;

static Ttk_ElementOptionSpec HighlightElementOptions[] = {
static const Ttk_ElementOptionSpec HighlightElementOptions[] = {
    { "-highlightcolor",TK_OPTION_COLOR,
	Tk_Offset(HighlightElement,highlightColorObj), DEFAULT_BACKGROUND },
	offsetof(HighlightElement,highlightColorObj), DEFAULT_BACKGROUND },
    { "-highlightthickness",TK_OPTION_PIXELS,
	Tk_Offset(HighlightElement,highlightThicknessObj), "0" },
    { NULL, 0, 0, NULL }
	offsetof(HighlightElement,highlightThicknessObj), "0" },
    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
};

static void HighlightElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    HighlightElement *hl = elementRecord;
    HighlightElement *hl = (HighlightElement *)elementRecord;
    int highlightThickness = 0;
    (void)dummy;
    (void)tkwin;
    (void)widthPtr;
    (void)heightPtr;

    Tcl_GetIntFromObj(NULL,hl->highlightThicknessObj,&highlightThickness);
    *paddingPtr = Ttk_UniformPadding((short)highlightThickness);
}

static void HighlightElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    HighlightElement *hl = elementRecord;
    HighlightElement *hl = (HighlightElement *)elementRecord;
    int highlightThickness = 0;
    XColor *highlightColor = Tk_GetColorFromObj(tkwin, hl->highlightColorObj);
    (void)dummy;
    (void)b;
    (void)state;

    Tcl_GetIntFromObj(NULL,hl->highlightThicknessObj,&highlightThickness);
    if (highlightColor && highlightThickness > 0) {
	GC gc = Tk_GCForColor(highlightColor, d);
	Tk_DrawFocusHighlight(tkwin, gc, highlightThickness, d);
    }
}

static Ttk_ElementSpec HighlightElementSpec =
static const Ttk_ElementSpec HighlightElementSpec =
{
    TK_STYLE_VERSION_2,
    sizeof(HighlightElement),
    HighlightElementOptions,
    HighlightElementSize,
    HighlightElementDraw
};

/*------------------------------------------------------------------------
 * +++ Button Border element:
 * 
 *
 * The Motif-style button border on X11 consists of (from outside-in):
 *
 * + focus indicator (controlled by -highlightcolor and -highlightthickness),
 * + default ring (if -default active; blank if -default normal)
 * + shaded border (controlled by -background, -borderwidth, and -relief)
 */

typedef struct {
    Tcl_Obj	*borderObj;
    Tcl_Obj	*borderWidthObj;
    Tcl_Obj	*reliefObj;
    Tcl_Obj	*defaultStateObj;
} ButtonBorderElement;

static Ttk_ElementOptionSpec ButtonBorderElementOptions[] =
static const Ttk_ElementOptionSpec ButtonBorderElementOptions[] =
{
    { "-background", TK_OPTION_BORDER, 
	Tk_Offset(ButtonBorderElement,borderObj), DEFAULT_BACKGROUND },
    { "-borderwidth", TK_OPTION_PIXELS, 
	Tk_Offset(ButtonBorderElement,borderWidthObj), DEFAULT_BORDERWIDTH },
    { "-relief", TK_OPTION_RELIEF, 
	Tk_Offset(ButtonBorderElement,reliefObj), "flat" },
    { "-default", TK_OPTION_ANY, 
	Tk_Offset(ButtonBorderElement,defaultStateObj), "disabled" },
    { NULL, 0, 0, NULL }
    { "-background", TK_OPTION_BORDER,
	offsetof(ButtonBorderElement,borderObj), DEFAULT_BACKGROUND },
    { "-borderwidth", TK_OPTION_PIXELS,
	offsetof(ButtonBorderElement,borderWidthObj), DEFAULT_BORDERWIDTH },
    { "-relief", TK_OPTION_RELIEF,
	offsetof(ButtonBorderElement,reliefObj), "flat" },
    { "-default", TK_OPTION_ANY,
	offsetof(ButtonBorderElement,defaultStateObj), "disabled" },
    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
};

static void ButtonBorderElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    ButtonBorderElement *bd = elementRecord;
    int defaultState = TTK_BUTTON_DEFAULT_DISABLED;
    ButtonBorderElement *bd = (ButtonBorderElement *)elementRecord;
    Ttk_ButtonDefaultState defaultState = TTK_BUTTON_DEFAULT_DISABLED;
    int borderWidth = 0;
    (void)dummy;
    (void)tkwin;
    (void)widthPtr;
    (void)heightPtr;

    Tcl_GetIntFromObj(NULL, bd->borderWidthObj, &borderWidth);
    Ttk_GetButtonDefaultStateFromObj(NULL, bd->defaultStateObj, &defaultState);

    if (defaultState != TTK_BUTTON_DEFAULT_DISABLED) {
	borderWidth += 5;
    }
    *paddingPtr = Ttk_UniformPadding((short)borderWidth);
}

/*
 * (@@@ Note: ButtonBorderElement still still still buggy:
 * padding for default ring is drawn in the wrong color 
 * padding for default ring is drawn in the wrong color
 * when the button is active.)
 */
static void ButtonBorderElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    ButtonBorderElement *bd = elementRecord;
    ButtonBorderElement *bd = (ButtonBorderElement *)elementRecord;
    Tk_3DBorder border = NULL;
    int borderWidth = 1, relief = TK_RELIEF_FLAT;
    int defaultState = TTK_BUTTON_DEFAULT_DISABLED;
    Ttk_ButtonDefaultState defaultState = TTK_BUTTON_DEFAULT_DISABLED;
    int inset = 0;
    (void)dummy;
    (void)state;

    /*
     * Get option values.
     */
    border = Tk_Get3DBorderFromObj(tkwin, bd->borderObj);
    Tcl_GetIntFromObj(NULL, bd->borderWidthObj, &borderWidth);
    Tk_GetReliefFromObj(NULL, bd->reliefObj, &relief);
166
167
168
169
170
171
172
173

174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198

199
200

201
202

203
204

205
206
207


208
209
210
211

212
213
214

215


216
217
218
219
220
221
222
223
224
225
226


227
228
229
230
231

232
233
234
235
236
237
238
179
180
181
182
183
184
185

186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201

202
203
204
205
206
207
208
209

210
211

212
213

214
215

216
217


218
219
220
221
222

223
224
225

226
227
228
229
230
231
232
233
234
235
236
237
238


239
240
241
242
243
244
245
246
247
248
249
250
251
252
253







-
+















-








-
+

-
+

-
+

-
+

-
-
+
+



-
+


-
+

+
+









-
-
+
+





+







    if (border && borderWidth > 0) {
	Tk_Draw3DRectangle(tkwin, d, border,
	    b.x+inset, b.y+inset, b.width - 2*inset, b.height - 2*inset,
	    borderWidth,relief);
    }
}

static Ttk_ElementSpec ButtonBorderElementSpec =
static const Ttk_ElementSpec ButtonBorderElementSpec =
{
    TK_STYLE_VERSION_2,
    sizeof(ButtonBorderElement),
    ButtonBorderElementOptions,
    ButtonBorderElementSize,
    ButtonBorderElementDraw
};

/*----------------------------------------------------------------------
 * +++ Arrow element(s).
 *
 * Draws a 3-D shaded triangle.
 * clientData is an enum ArrowDirection pointer.
 */

static int ArrowElements[] = { ARROW_UP, ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT };
typedef struct
{
    Tcl_Obj *sizeObj;
    Tcl_Obj *borderObj;
    Tcl_Obj *borderWidthObj;
    Tcl_Obj *reliefObj;
} ArrowElement;

static Ttk_ElementOptionSpec ArrowElementOptions[] =
static const Ttk_ElementOptionSpec ArrowElementOptions[] =
{
    { "-arrowsize", TK_OPTION_PIXELS, Tk_Offset(ArrowElement,sizeObj),
    { "-arrowsize", TK_OPTION_PIXELS, offsetof(ArrowElement,sizeObj),
	DEFAULT_ARROW_SIZE },
    { "-background", TK_OPTION_BORDER, Tk_Offset(ArrowElement,borderObj),
    { "-background", TK_OPTION_BORDER, offsetof(ArrowElement,borderObj),
    	DEFAULT_BACKGROUND },
    { "-borderwidth", TK_OPTION_PIXELS, Tk_Offset(ArrowElement,borderWidthObj),
    { "-borderwidth", TK_OPTION_PIXELS, offsetof(ArrowElement,borderWidthObj),
    	DEFAULT_BORDERWIDTH },
    { "-relief", TK_OPTION_RELIEF, Tk_Offset(ArrowElement,reliefObj),"raised" },
    { NULL, 0, 0, NULL }
    { "-relief", TK_OPTION_RELIEF, offsetof(ArrowElement,reliefObj),"raised" },
    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
};

static void ArrowElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    ArrowElement *arrow = elementRecord;
    ArrowElement *arrow = (ArrowElement *)elementRecord;
    int size = 12;
    (void)dummy;
    (void)paddingPtr;

    Tk_GetPixelsFromObj(NULL, tkwin, arrow->sizeObj, &size);
    *widthPtr = *heightPtr = size;
}

static void ArrowElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    int direction = *(int *)clientData;
    ArrowElement *arrow = elementRecord;
	ArrowDirection direction = (ArrowDirection)PTR2INT(clientData);
    ArrowElement *arrow = (ArrowElement *)elementRecord;
    Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, arrow->borderObj);
    int borderWidth = 2;
    int relief = TK_RELIEF_RAISED;
    int size = b.width < b.height ? b.width : b.height;
    XPoint points[3];
    (void)state;

    Tk_GetPixelsFromObj(NULL, tkwin, arrow->borderWidthObj, &borderWidth);
    Tk_GetReliefFromObj(NULL, arrow->reliefObj, &relief);


    /*
     * @@@ There are off-by-one pixel errors in the way these are drawn;
262
263
264
265
266
267
268
269

270
271
272
273
274
275
276
277
278
279
280
281
282

283
284
285
286
287
288
289

290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310





311
312
313
314



315
316

317
318
319


320
321
322
323
324
325
326

327
328



329
330
331
332
333
334
335
336
337

338
339
340
341
342
343
344
345
346
347

348
349
350
351
352

353

354
355
356
357
358
359
360
361
362
363
364
365
366
367
368

369
370
371

372
373
374
375
376
377
378
379

380
381
382
383
384
385
386
387
388
389
390
391
392

393
394
395
396
397
398
399

400
401
402
403
404

405
406
407
408
409
410
411
277
278
279
280
281
282
283

284
285
286
287
288
289
290
291
292
293
294
295
296

297
298
299
300
301
302
303

304
305
306
307




308
309
310
311
312
313
314
315
316





317
318
319
320
321
322



323
324
325
326

327
328


329
330
331
332
333
334
335
336

337
338

339
340
341
342
343
344
345
346
347
348
349

350
351
352
353
354
355
356
357
358
359

360
361
362
363
364

365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381

382
383
384

385
386
387
388
389
390
391
392

393
394
395
396
397
398
399
400
401
402
403
404
405

406
407
408
409
410
411
412

413
414
415
416
417

418
419
420
421
422
423
424
425







-
+












-
+






-
+



-
-
-
-









-
-
-
-
-
+
+
+
+
+

-
-
-
+
+
+

-
+

-
-
+
+






-
+

-
+
+
+








-
+









-
+




-
+

+














-
+


-
+







-
+












-
+






-
+




-
+







	    points[2].x = b.x;		points[2].y = b.y + size;
	    break;
    }

    Tk_Fill3DPolygon(tkwin, d, border, points, 3, borderWidth, relief);
}

static Ttk_ElementSpec ArrowElementSpec =
static const Ttk_ElementSpec ArrowElementSpec =
{
    TK_STYLE_VERSION_2,
    sizeof(ArrowElement),
    ArrowElementOptions,
    ArrowElementSize,
    ArrowElementDraw
};


/*------------------------------------------------------------------------
 * +++ Sash element (for ttk::panedwindow)
 *
 * NOTES: 
 * NOTES:
 *
 * panedwindows with -orient horizontal use vertical sashes, and vice versa.
 *
 * Interpretation of -sashrelief 'groove' and 'ridge' are
 * swapped wrt. the core panedwindow, which (I think) has them backwards.
 *
 * Default -sashrelief is sunken; the core panedwindow has default 
 * Default -sashrelief is sunken; the core panedwindow has default
 * -sashrelief raised, but that looks wrong to me.
 */

static Ttk_Orient SashClientData[] = {
    TTK_ORIENT_HORIZONTAL, TTK_ORIENT_VERTICAL 
};

typedef struct {
    Tcl_Obj *borderObj; 	/* background color */
    Tcl_Obj *sashReliefObj;	/* sash relief */
    Tcl_Obj *sashThicknessObj;	/* overall thickness of sash */
    Tcl_Obj *sashPadObj;	/* padding on either side of handle */
    Tcl_Obj *handleSizeObj;	/* handle width and height */
    Tcl_Obj *handlePadObj;	/* handle's distance from edge */
} SashElement;

static Ttk_ElementOptionSpec SashOptions[] = {
    { "-background", TK_OPTION_BORDER, 
	Tk_Offset(SashElement,borderObj), DEFAULT_BACKGROUND },
    { "-sashrelief", TK_OPTION_RELIEF, 
	Tk_Offset(SashElement,sashReliefObj), "sunken" },
static const Ttk_ElementOptionSpec SashOptions[] = {
    { "-background", TK_OPTION_BORDER,
	offsetof(SashElement,borderObj), DEFAULT_BACKGROUND },
    { "-sashrelief", TK_OPTION_RELIEF,
	offsetof(SashElement,sashReliefObj), "sunken" },
    { "-sashthickness", TK_OPTION_PIXELS,
	Tk_Offset(SashElement,sashThicknessObj), "6" },
    { "-sashpad", TK_OPTION_PIXELS, 
	Tk_Offset(SashElement,sashPadObj), "2" },
	offsetof(SashElement,sashThicknessObj), "6" },
    { "-sashpad", TK_OPTION_PIXELS,
	offsetof(SashElement,sashPadObj), "2" },
    { "-handlesize", TK_OPTION_PIXELS,
	Tk_Offset(SashElement,handleSizeObj), "8" },
	offsetof(SashElement,handleSizeObj), "8" },
    { "-handlepad", TK_OPTION_PIXELS,
	Tk_Offset(SashElement,handlePadObj), "8" },
    { NULL, 0, 0, NULL }
	offsetof(SashElement,handlePadObj), "8" },
    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
};

static void SashElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    SashElement *sash = elementRecord;
    SashElement *sash = (SashElement *)elementRecord;
    int sashPad = 2, sashThickness = 6, handleSize = 8;
    int horizontal = *((Ttk_Orient*)clientData) == TTK_ORIENT_HORIZONTAL;
    Ttk_Orient orient = (Ttk_Orient)PTR2INT(clientData);
    (void)paddingPtr;
    (void)paddingPtr;

    Tk_GetPixelsFromObj(NULL, tkwin, sash->sashThicknessObj, &sashThickness);
    Tk_GetPixelsFromObj(NULL, tkwin, sash->handleSizeObj, &handleSize);
    Tk_GetPixelsFromObj(NULL, tkwin, sash->sashPadObj, &sashPad);

    if (sashThickness < handleSize + 2*sashPad)
	sashThickness = handleSize + 2*sashPad;

    if (horizontal)
    if (orient == TTK_ORIENT_HORIZONTAL)
	*heightPtr = sashThickness;
    else
	*widthPtr = sashThickness;
}

static void SashElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, Ttk_State state)
{
    SashElement *sash = elementRecord;
    SashElement *sash = (SashElement *)elementRecord;
    Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, sash->borderObj);
    GC gc1,gc2;
    int relief = TK_RELIEF_RAISED;
    int handleSize = 8, handlePad = 8;
    int horizontal = *((Ttk_Orient*)clientData) == TTK_ORIENT_HORIZONTAL;
    Ttk_Orient orient = (Ttk_Orient)PTR2INT(clientData);
    Ttk_Box hb;
    (void)state;

    Tk_GetPixelsFromObj(NULL, tkwin, sash->handleSizeObj, &handleSize);
    Tk_GetPixelsFromObj(NULL, tkwin, sash->handlePadObj, &handlePad);
    Tk_GetReliefFromObj(NULL, sash->sashReliefObj, &relief);

    switch (relief) {
	case TK_RELIEF_RAISED: case TK_RELIEF_RIDGE:
	    gc1 = Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC);
	    gc2 = Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC);
	    break;
	case TK_RELIEF_SUNKEN: case TK_RELIEF_GROOVE:
	    gc1 = Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC);
	    gc2 = Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC);
	    break;
	case TK_RELIEF_SOLID: 
	case TK_RELIEF_SOLID:
	    gc1 = gc2 = Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC);
	    break;
	case TK_RELIEF_FLAT: 
	case TK_RELIEF_FLAT:
	default:
	    gc1 = gc2 = Tk_3DBorderGC(tkwin, border, TK_3D_FLAT_GC);
	    break;
    }

    /* Draw sash line:
     */
    if (horizontal) {
    if (orient == TTK_ORIENT_HORIZONTAL) {
	int y = b.y + b.height/2 - 1;
	XDrawLine(Tk_Display(tkwin), d, gc1, b.x, y, b.x+b.width, y); ++y;
	XDrawLine(Tk_Display(tkwin), d, gc2, b.x, y, b.x+b.width, y);
    } else {
	int x = b.x + b.width/2 - 1;
	XDrawLine(Tk_Display(tkwin), d, gc1, x, b.y, x, b.y+b.height); ++x;
	XDrawLine(Tk_Display(tkwin), d, gc2, x, b.y, x, b.y+b.height);
    }

    /* Draw handle:
     */
    if (handleSize >= 0) {
	if (horizontal) {
	if (orient == TTK_ORIENT_HORIZONTAL) {
	    hb = Ttk_StickBox(b, handleSize, handleSize, TTK_STICK_W);
	    hb.x += handlePad;
	} else {
	    hb = Ttk_StickBox(b, handleSize, handleSize, TTK_STICK_N);
	    hb.y += handlePad;
	}
	Tk_Fill3DRectangle(tkwin, d, border, 
	Tk_Fill3DRectangle(tkwin, d, border,
	    hb.x, hb.y, hb.width, hb.height, 1, TK_RELIEF_RAISED);
    }
}

static Ttk_ElementSpec SashElementSpec = {
static const Ttk_ElementSpec SashElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(SashElement),
    SashOptions,
    SashElementSize,
    SashElementDraw
};

435
436
437
438
439
440
441
442

443
444
445
446
447
448
449
449
450
451
452
453
454
455

456
457
458
459
460
461
462
463







-
+







	        TTK_NODE("Radiobutton.indicator", TTK_PACK_LEFT)
	        TTK_NODE("Radiobutton.label", TTK_PACK_LEFT|TTK_FILL_BOTH)))))

TTK_LAYOUT("TMenubutton",
    TTK_GROUP("Menubutton.highlight", TTK_FILL_BOTH,
        TTK_GROUP("Menubutton.border", TTK_FILL_BOTH,
	    TTK_NODE("Menubutton.indicator", TTK_PACK_RIGHT)
	    TTK_GROUP("Menubutton.padding", TTK_PACK_LEFT|TTK_EXPAND|TTK_FILL_X,
	    TTK_GROUP("Menubutton.padding", TTK_FILL_X,
	        TTK_NODE("Menubutton.label", 0)))))

/* "classic" entry, includes highlight border */
TTK_LAYOUT("TEntry",
    TTK_GROUP("Entry.highlight", TTK_FILL_BOTH,
        TTK_GROUP("Entry.field", TTK_FILL_BOTH|TTK_BORDER,
	    TTK_GROUP("Entry.padding", TTK_FILL_BOTH,
479
480
481
482
483
484
485
486

487
488

489
490

491
492

493
494

495
496
497


498
499

500
501
502
503
504
505
506
507
508
509
510
511
493
494
495
496
497
498
499

500
501

502
503

504
505

506
507

508
509


510
511
512

513
514
515
516
517
518
519
520
521
522
523
524
525







-
+

-
+

-
+

-
+

-
+

-
-
+
+

-
+












    Ttk_RegisterElement(interp, theme, "highlight",
	    &HighlightElementSpec, NULL);

    Ttk_RegisterElement(interp, theme, "Button.border",
	    &ButtonBorderElementSpec, NULL);

    Ttk_RegisterElement(interp, theme, "uparrow",
	    &ArrowElementSpec, &ArrowElements[0]);
	    &ArrowElementSpec, INT2PTR(ARROW_UP));
    Ttk_RegisterElement(interp, theme, "downarrow",
	    &ArrowElementSpec, &ArrowElements[1]);
	    &ArrowElementSpec, INT2PTR(ARROW_DOWN));
    Ttk_RegisterElement(interp, theme, "leftarrow",
	    &ArrowElementSpec, &ArrowElements[2]);
	    &ArrowElementSpec, INT2PTR(ARROW_LEFT));
    Ttk_RegisterElement(interp, theme, "rightarrow",
	    &ArrowElementSpec, &ArrowElements[3]);
	    &ArrowElementSpec, INT2PTR(ARROW_RIGHT));
    Ttk_RegisterElement(interp, theme, "arrow",
	    &ArrowElementSpec, &ArrowElements[0]);
	    &ArrowElementSpec, INT2PTR(ARROW_UP));

    Ttk_RegisterElement(interp, theme, "hsash", 
	    &SashElementSpec, &SashClientData[0]);
    Ttk_RegisterElement(interp, theme, "hsash",
	    &SashElementSpec, INT2PTR(TTK_ORIENT_HORIZONTAL));
    Ttk_RegisterElement(interp, theme, "vsash",
	    &SashElementSpec, &SashClientData[1]);
	    &SashElementSpec, INT2PTR(TTK_ORIENT_VERTICAL));

    /*
     * Register layouts:
     */
    Ttk_RegisterLayouts(theme, LayoutTable);

    Tcl_PkgProvide(interp, "ttk::theme::classic", TTK_VERSION);

    return TCL_OK;
}

/*EOF*/
Changes to generic/ttk/ttkDecls.h.
9
10
11
12
13
14
15

16




17
18









19
20
21
22
23
24
25
9
10
11
12
13
14
15
16

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38







+
-
+
+
+
+


+
+
+
+
+
+
+
+
+








extern const char *TtkInitializeStubs(
	Tcl_Interp *, const char *version, int epoch, int revision);
#define Ttk_InitStubs(interp) TtkInitializeStubs( \
	interp, TTK_VERSION, TTK_STUBS_EPOCH, TTK_STUBS_REVISION)
#else

#if !defined(TK_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9
#define Ttk_InitStubs(interp) Tcl_PkgRequireEx(interp, "Ttk", TTK_VERSION, 0, NULL)
#   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)
#elif defined(TK_NO_DEPRECATED)
# define TTK_DEPRECATED(msg) MODULE_SCOPE
#else
# define TTK_DEPRECATED(msg) TTKAPI
#endif



/* !BEGIN!: Do not edit below this line. */

#define TTK_STUBS_EPOCH 0
#define TTK_STUBS_REVISION 31

43
44
45
46
47
48
49
50

51
52
53
54
55

56
57
58
59
60
61
62
56
57
58
59
60
61
62

63
64
65
66
67

68
69
70
71
72
73
74
75







-
+




-
+







/* 4 */
TTKAPI void		Ttk_RegisterCleanup(Tcl_Interp *interp,
				void *deleteData,
				Ttk_CleanupProc *cleanupProc);
/* 5 */
TTKAPI int		Ttk_RegisterElementSpec(Ttk_Theme theme,
				const char *elementName,
				Ttk_ElementSpec *elementSpec,
				const Ttk_ElementSpec *elementSpec,
				void *clientData);
/* 6 */
TTKAPI Ttk_ElementClass * Ttk_RegisterElement(Tcl_Interp *interp,
				Ttk_Theme theme, const char *elementName,
				Ttk_ElementSpec *elementSpec,
				const Ttk_ElementSpec *elementSpec,
				void *clientData);
/* 7 */
TTKAPI int		Ttk_RegisterElementFactory(Tcl_Interp *interp,
				const char *name,
				Ttk_ElementFactory factoryProc,
				void *clientData);
/* 8 */
73
74
75
76
77
78
79
80

81
82
83
84
85
86
87
86
87
88
89
90
91
92

93
94
95
96
97
98
99
100







-
+







/* 12 */
TTKAPI Ttk_StateMap	Ttk_GetStateMapFromObj(Tcl_Interp *interp,
				Tcl_Obj *objPtr);
/* 13 */
TTKAPI Tcl_Obj *	Ttk_StateMapLookup(Tcl_Interp *interp,
				Ttk_StateMap map, Ttk_State state);
/* 14 */
TTKAPI int		Ttk_StateTableLookup(Ttk_StateTable map[],
TTKAPI int		Ttk_StateTableLookup(const Ttk_StateTable *map,
				Ttk_State state);
/* Slot 15 is reserved */
/* Slot 16 is reserved */
/* Slot 17 is reserved */
/* Slot 18 is reserved */
/* Slot 19 is reserved */
/* 20 */
126
127
128
129
130
131
132

133

134
135
136
137
138
139
140
141
142
143
144
145
146
147
148


149
150
151
152
153
154
155
156

157
158
159
160
161
162
163
139
140
141
142
143
144
145
146

147
148
149
150
151
152
153
154
155
156
157
158
159
160


161
162
163
164
165
166
167
168
169

170
171
172
173
174
175
176
177







+
-
+













-
-
+
+







-
+







/* 35 */
TTKAPI Tcl_Obj *	Ttk_NewBoxObj(Ttk_Box box);
/* Slot 36 is reserved */
/* Slot 37 is reserved */
/* Slot 38 is reserved */
/* Slot 39 is reserved */
/* 40 */
TTK_DEPRECATED("")
TTKAPI int		Ttk_GetOrientFromObj(Tcl_Interp *interp,
int			Ttk_GetOrientFromObj(Tcl_Interp *interp,
				Tcl_Obj *objPtr, int *orient);

typedef struct TtkStubs {
    int magic;
    int epoch;
    int revision;
    void *hooks;

    Ttk_Theme (*ttk_GetTheme) (Tcl_Interp *interp, const char *name); /* 0 */
    Ttk_Theme (*ttk_GetDefaultTheme) (Tcl_Interp *interp); /* 1 */
    Ttk_Theme (*ttk_GetCurrentTheme) (Tcl_Interp *interp); /* 2 */
    Ttk_Theme (*ttk_CreateTheme) (Tcl_Interp *interp, const char *name, Ttk_Theme parent); /* 3 */
    void (*ttk_RegisterCleanup) (Tcl_Interp *interp, void *deleteData, Ttk_CleanupProc *cleanupProc); /* 4 */
    int (*ttk_RegisterElementSpec) (Ttk_Theme theme, const char *elementName, Ttk_ElementSpec *elementSpec, void *clientData); /* 5 */
    Ttk_ElementClass * (*ttk_RegisterElement) (Tcl_Interp *interp, Ttk_Theme theme, const char *elementName, Ttk_ElementSpec *elementSpec, void *clientData); /* 6 */
    int (*ttk_RegisterElementSpec) (Ttk_Theme theme, const char *elementName, const Ttk_ElementSpec *elementSpec, void *clientData); /* 5 */
    Ttk_ElementClass * (*ttk_RegisterElement) (Tcl_Interp *interp, Ttk_Theme theme, const char *elementName, const Ttk_ElementSpec *elementSpec, void *clientData); /* 6 */
    int (*ttk_RegisterElementFactory) (Tcl_Interp *interp, const char *name, Ttk_ElementFactory factoryProc, void *clientData); /* 7 */
    void (*ttk_RegisterLayout) (Ttk_Theme theme, const char *className, Ttk_LayoutSpec layoutSpec); /* 8 */
    void (*reserved9)(void);
    int (*ttk_GetStateSpecFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Ttk_StateSpec *spec_rtn); /* 10 */
    Tcl_Obj * (*ttk_NewStateSpecObj) (unsigned int onbits, unsigned int offbits); /* 11 */
    Ttk_StateMap (*ttk_GetStateMapFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr); /* 12 */
    Tcl_Obj * (*ttk_StateMapLookup) (Tcl_Interp *interp, Ttk_StateMap map, Ttk_State state); /* 13 */
    int (*ttk_StateTableLookup) (Ttk_StateTable map[], Ttk_State state); /* 14 */
    int (*ttk_StateTableLookup) (const Ttk_StateTable *map, Ttk_State state); /* 14 */
    void (*reserved15)(void);
    void (*reserved16)(void);
    void (*reserved17)(void);
    void (*reserved18)(void);
    void (*reserved19)(void);
    int (*ttk_GetPaddingFromObj) (Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr, Ttk_Padding *pad_rtn); /* 20 */
    int (*ttk_GetBorderFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Ttk_Padding *pad_rtn); /* 21 */
175
176
177
178
179
180
181
182

183
184
185
186
187
188
189
189
190
191
192
193
194
195

196
197
198
199
200
201
202
203







-
+







    Ttk_Box (*ttk_ExpandBox) (Ttk_Box b, Ttk_Padding p); /* 33 */
    Ttk_Box (*ttk_PlaceBox) (Ttk_Box *cavity, int w, int h, Ttk_Side side, Ttk_Sticky sticky); /* 34 */
    Tcl_Obj * (*ttk_NewBoxObj) (Ttk_Box box); /* 35 */
    void (*reserved36)(void);
    void (*reserved37)(void);
    void (*reserved38)(void);
    void (*reserved39)(void);
    int (*ttk_GetOrientFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int *orient); /* 40 */
    TCL_DEPRECATED_API("") int (*ttk_GetOrientFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int *orient); /* 40 */
} TtkStubs;

extern const TtkStubs *ttkStubsPtr;

#ifdef __cplusplus
}
#endif
Changes to generic/ttk/ttkDefaultTheme.c.
1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * 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"
#include "ttkTheme.h"

33
34
35
36
37
38
39
40

41
42
43
44
45
46
47
48
49
50

51
52
53
54
55
56
57
33
34
35
36
37
38
39

40
41
42
43
44
45
46
47
48
49

50
51
52
53
54
55
56
57







-
+









-
+







 * Please excuse the gross misspelling "LITE" for "LIGHT",
 * but it makes things line up nicer.
 */

enum BorderColor { FLAT = 1, LITE = 2, DARK = 3, BRDR = 4 };

/* top-left outer, top-left inner, bottom-right inner, bottom-right outer */
static int const shadowColors[6][4] = {
static const enum BorderColor shadowColors[6][4] = {
    { FLAT, FLAT, FLAT, FLAT },	/* TK_RELIEF_FLAT   = 0*/
    { DARK, LITE, DARK, LITE },	/* TK_RELIEF_GROOVE = 1*/
    { LITE, FLAT, DARK, BRDR },	/* TK_RELIEF_RAISED = 2*/
    { LITE, DARK, LITE, DARK },	/* TK_RELIEF_RIDGE  = 3*/
    { BRDR, BRDR, BRDR, BRDR },	/* TK_RELIEF_SOLID  = 4*/
    { BRDR, DARK, FLAT, LITE }	/* TK_RELIEF_SUNKEN = 5*/
};

/* top-left, bottom-right */
static int const thinShadowColors[6][4] = {
static const enum BorderColor thinShadowColors[6][4] = {
    { FLAT, FLAT },	/* TK_RELIEF_FLAT   = 0*/
    { DARK, LITE },	/* TK_RELIEF_GROOVE = 1*/
    { LITE, DARK },	/* TK_RELIEF_RAISED = 2*/
    { LITE, DARK },	/* TK_RELIEF_RIDGE  = 3*/
    { BRDR, BRDR },	/* TK_RELIEF_SOLID  = 4*/
    { DARK, LITE }	/* TK_RELIEF_SUNKEN = 5*/
};
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127

128
129

130
131

132
133

134
135
136
137
138
139
140
141

142
143
144
145

146
147
148
149
150
151
152
112
113
114
115
116
117
118


119
120
121
122
123
124

125
126

127
128

129
130

131
132
133
134
135
136
137
138

139
140
141
142

143
144
145
146
147
148
149
150







-
-






-
+

-
+

-
+

-
+







-
+



-
+







	    break;
    }
}

/* Alternate shadow colors for entry fields:
 * NOTE: FLAT color is normally white, and the LITE color is a darker shade.
 */
static int fieldShadowColors[4] = { DARK, BRDR, LITE, FLAT };

static void DrawFieldBorder(
    Tk_Window tkwin, Drawable d, Tk_3DBorder border, XColor *borderColor,
    Ttk_Box b)
{
    GC borderGC = Tk_GCForColor(borderColor, d);
    DrawCorner(tkwin, d, border, borderGC,
	b.x, b.y, b.width, b.height, 0,fieldShadowColors[0]);
	b.x, b.y, b.width, b.height, 0, DARK);
    DrawCorner(tkwin, d, border, borderGC,
	b.x+1, b.y+1, b.width-2, b.height-2, 0,fieldShadowColors[1]);
	b.x+1, b.y+1, b.width-2, b.height-2, 0, BRDR);
    DrawCorner(tkwin, d, border, borderGC,
	b.x+1, b.y+1, b.width-2, b.height-2, 1,fieldShadowColors[2]);
	b.x+1, b.y+1, b.width-2, b.height-2, 1, LITE);
    DrawCorner(tkwin, d, border, borderGC,
	b.x, b.y, b.width, b.height, 1,fieldShadowColors[3]);
	b.x, b.y, b.width, b.height, 1, FLAT);
    return;
}

/*
 * ArrowPoints --
 * 	Compute points of arrow polygon.
 */
static void ArrowPoints(Ttk_Box b, ArrowDirection dir, XPoint points[4])
static void ArrowPoints(Ttk_Box b, ArrowDirection direction, XPoint points[4])
{
    int cx, cy, h;

    switch (dir) {
    switch (direction) {
	case ARROW_UP:
	    h = (b.width - 1)/2;
	    cx = b.x + h;
	    cy = b.y;
	    if (b.height <= h) h = b.height - 1;
	    points[0].x = cx;		points[0].y = cy;
	    points[1].x = cx - h;  	points[1].y = cy + h;
182
183
184
185
186
187
188
189

190
191

192
193
194
195
196
197
198
199
200
201
202
203
204
205

206
207
208

209
210
211
212
213
214
215
216
217
218

219
220
221

222
223
224
225
226
227
228
180
181
182
183
184
185
186

187
188

189
190
191
192
193
194
195
196
197
198
199
200
201
202

203
204
205

206
207
208
209
210
211
212
213
214
215

216
217
218

219
220
221
222
223
224
225
226







-
+

-
+













-
+


-
+









-
+


-
+







    }

    points[3].x = points[0].x;
    points[3].y = points[0].y;
}

/*public*/
void TtkArrowSize(int h, ArrowDirection dir, int *widthPtr, int *heightPtr)
void TtkArrowSize(int h, ArrowDirection direction, int *widthPtr, int *heightPtr)
{
    switch (dir) {
    switch (direction) {
	case ARROW_UP:
	case ARROW_DOWN:	*widthPtr = 2*h+1; *heightPtr = h+1; break;
	case ARROW_LEFT:
	case ARROW_RIGHT:	*widthPtr = h+1; *heightPtr = 2*h+1;
    }
}

/*
 * TtkDrawArrow, TtkFillArrow --
 * 	Draw an arrow in the indicated direction inside the specified box.
 */
/*public*/
void TtkFillArrow(
    Display *display, Drawable d, GC gc, Ttk_Box b, ArrowDirection dir)
    Display *display, Drawable d, GC gc, Ttk_Box b, ArrowDirection direction)
{
    XPoint points[4];
    ArrowPoints(b, dir, points);
    ArrowPoints(b, direction, points);
    XFillPolygon(display, d, gc, points, 3, Convex, CoordModeOrigin);
    XDrawLines(display, d, gc, points, 4, CoordModeOrigin);

    /* Work around bug [77527326e5] - ttk artifacts on Ubuntu */
    XDrawPoint(display, d, gc, points[2].x, points[2].y);
}

/*public*/
void TtkDrawArrow(
    Display *display, Drawable d, GC gc, Ttk_Box b, ArrowDirection dir)
    Display *display, Drawable d, GC gc, Ttk_Box b, ArrowDirection direction)
{
    XPoint points[4];
    ArrowPoints(b, dir, points);
    ArrowPoints(b, direction, points);
    XDrawLines(display, d, gc, points, 4, CoordModeOrigin);

    /* Work around bug [77527326e5] - ttk artifacts on Ubuntu */
    XDrawPoint(display, d, gc, points[2].x, points[2].y);
}

/*
240
241
242
243
244
245
246
247
248


249
250
251
252


253
254

255
256

257
258

259
260
261
262

263
264
265

266
267





268
269
270
271
272
273
274
275
276
277
278
279
280

281
282
283

284
285
286
287
288



289
290
291
292
293
294
295
238
239
240
241
242
243
244


245
246
247
248


249
250
251

252
253

254
255

256
257
258
259

260
261
262

263
264

265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281

282
283
284

285
286
287
288
289

290
291
292
293
294
295
296
297
298
299







-
-
+
+


-
-
+
+

-
+

-
+

-
+



-
+


-
+

-
+
+
+
+
+












-
+


-
+




-
+
+
+







    Tcl_Obj	*borderObj;
    Tcl_Obj	*borderColorObj;	/* Extra border color */
    Tcl_Obj	*borderWidthObj;
    Tcl_Obj	*reliefObj;
    Tcl_Obj	*defaultStateObj;	/* for buttons */
} BorderElement;

static Ttk_ElementOptionSpec BorderElementOptions[] = {
    { "-background", TK_OPTION_BORDER, Tk_Offset(BorderElement,borderObj),
static const Ttk_ElementOptionSpec BorderElementOptions[] = {
    { "-background", TK_OPTION_BORDER, offsetof(BorderElement,borderObj),
    	DEFAULT_BACKGROUND },
    { "-bordercolor",TK_OPTION_COLOR,
	Tk_Offset(BorderElement,borderColorObj), "black" },
    { "-default", TK_OPTION_ANY, Tk_Offset(BorderElement,defaultStateObj),
	offsetof(BorderElement,borderColorObj), "black" },
    { "-default", TK_OPTION_ANY, offsetof(BorderElement,defaultStateObj),
    	"disabled" },
    { "-borderwidth",TK_OPTION_PIXELS,Tk_Offset(BorderElement,borderWidthObj),
    { "-borderwidth",TK_OPTION_PIXELS, offsetof(BorderElement,borderWidthObj),
    	STRINGIFY(BORDERWIDTH) },
    { "-relief", TK_OPTION_RELIEF, Tk_Offset(BorderElement,reliefObj),
    { "-relief", TK_OPTION_RELIEF, offsetof(BorderElement,reliefObj),
    	"flat" },
        { NULL, 0, 0, NULL }
        { NULL, TK_OPTION_BOOLEAN, 0, NULL }
};

static void BorderElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    BorderElement *bd = elementRecord;
    BorderElement *bd = (BorderElement *)elementRecord;
    int borderWidth = 0;
    int defaultState = TTK_BUTTON_DEFAULT_DISABLED;
    Ttk_ButtonDefaultState defaultState = TTK_BUTTON_DEFAULT_DISABLED;
    (void)dummy;
    (void)tkwin;
    (void)widthPtr;
    (void)heightPtr;

    Tcl_GetIntFromObj(NULL, bd->borderWidthObj, &borderWidth);
    Ttk_GetButtonDefaultStateFromObj(NULL, bd->defaultStateObj, &defaultState);

    if (defaultState != TTK_BUTTON_DEFAULT_DISABLED) {
	++borderWidth;
    }

    *paddingPtr = Ttk_UniformPadding((short)borderWidth);
}

static void BorderElementDraw(
    void *clientData, void *elementRecord,
    void *dummy, void *elementRecord,
    Tk_Window tkwin, Drawable d, Ttk_Box b, unsigned int state)
{
    BorderElement *bd = elementRecord;
    BorderElement *bd = (BorderElement *)elementRecord;
    Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, bd->borderObj);
    XColor *borderColor = Tk_GetColorFromObj(tkwin, bd->borderColorObj);
    int borderWidth = 2;
    int relief = TK_RELIEF_FLAT;
    int defaultState = TTK_BUTTON_DEFAULT_DISABLED;
    Ttk_ButtonDefaultState defaultState = TTK_BUTTON_DEFAULT_DISABLED;
    (void)dummy;
    (void)state;

    /*
     * Get option values.
     */
    Tcl_GetIntFromObj(NULL, bd->borderWidthObj, &borderWidth);
    Tk_GetReliefFromObj(NULL, bd->reliefObj, &relief);
    Ttk_GetButtonDefaultStateFromObj(NULL, bd->defaultStateObj, &defaultState);
303
304
305
306
307
308
309
310

311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328


329
330

331
332

333
334
335
336

337
338






339
340
341
342
343

344
345
346

347
348


349
350
351
352
353
354
355

356
357
358
359
360
361
362
307
308
309
310
311
312
313

314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330


331
332
333

334
335

336
337
338
339

340
341
342
343
344
345
346
347
348
349
350
351
352

353
354
355

356
357
358
359
360
361
362
363
364
365
366

367
368
369
370
371
372
373
374







-
+
















-
-
+
+

-
+

-
+



-
+


+
+
+
+
+
+




-
+


-
+


+
+






-
+







	/* Space for default ring: */
	b = Ttk_PadBox(b, Ttk_UniformPadding(1));
    }

    DrawBorder(tkwin, d, border, borderColor, b, borderWidth, relief);
}

static Ttk_ElementSpec BorderElementSpec = {
static const Ttk_ElementSpec BorderElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(BorderElement),
    BorderElementOptions,
    BorderElementSize,
    BorderElementDraw
};

/*----------------------------------------------------------------------
 * +++ Field element:
 * 	Used for editable fields.
 */
typedef struct {
    Tcl_Obj	*borderObj;
    Tcl_Obj	*borderColorObj;	/* Extra border color */
} FieldElement;

static Ttk_ElementOptionSpec FieldElementOptions[] = {
    { "-fieldbackground", TK_OPTION_BORDER, Tk_Offset(FieldElement,borderObj),
static const Ttk_ElementOptionSpec FieldElementOptions[] = {
    { "-fieldbackground", TK_OPTION_BORDER, offsetof(FieldElement,borderObj),
    	"white" },
    { "-bordercolor",TK_OPTION_COLOR, Tk_Offset(FieldElement,borderColorObj),
    { "-bordercolor",TK_OPTION_COLOR, offsetof(FieldElement,borderColorObj),
	"black" },
    { NULL, 0, 0, NULL }
    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
};

static void FieldElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    (void)dummy;
    (void)elementRecord;
    (void)tkwin;
    (void)widthPtr;
    (void)heightPtr;

    *paddingPtr = Ttk_UniformPadding(2);
}

static void FieldElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    FieldElement *field = elementRecord;
    FieldElement *field = (FieldElement *)elementRecord;
    Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, field->borderObj);
    XColor *borderColor = Tk_GetColorFromObj(tkwin, field->borderColorObj);
    (void)dummy;
    (void)state;

    Tk_Fill3DRectangle(
	tkwin, d, border, b.x, b.y, b.width, b.height, 0, TK_RELIEF_SUNKEN);
    DrawFieldBorder(tkwin, d, border, borderColor, b);
}

static Ttk_ElementSpec FieldElementSpec = {
static const Ttk_ElementSpec FieldElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(FieldElement),
    FieldElementOptions,
    FieldElementSize,
    FieldElementDraw
};

371
372
373
374
375
376
377
378

379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398

399
400
401
402
403
404
405
383
384
385
386
387
388
389

390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409

410
411
412
413
414
415
416
417







-
+



















-
+







 * Indicator bitmap descriptor:
 */
typedef struct {
    int width;		/* Width of each image */
    int height;		/* Height of each image */
    int nimages;	/* #images / row */
    const char *const *pixels;	/* array[height] of char[width*nimage] */
    Ttk_StateTable *map;/* used to look up image index by state */
    const Ttk_StateTable *map;/* used to look up image index by state */
} IndicatorSpec;

#if 0
/*XPM*/
static const char *const button_images[] = {
    /* width height ncolors chars_per_pixel */
    "52 13 8 1",
    /* colors */
    "A c #808000000000 s shadow",
    "B c #000080800000 s highlight",
    "C c #808080800000 s 3dlight",
    "D c #000000008080 s window",
    "E c #808000008080 s 3ddark",
    "F c #000080808080 s frame",
    "G c #000000000000 s foreground",
    "H c #000080800000 s disabledfg",
};
#endif

static Ttk_StateTable checkbutton_states[] = {
static const Ttk_StateTable checkbutton_states[] = {
    { 0, 0, TTK_STATE_SELECTED|TTK_STATE_DISABLED },
    { 1, TTK_STATE_SELECTED, TTK_STATE_DISABLED },
    { 2, TTK_STATE_DISABLED, TTK_STATE_SELECTED },
    { 3, TTK_STATE_SELECTED|TTK_STATE_DISABLED, 0 },
    { 0, 0, 0 }
};

421
422
423
424
425
426
427
428

429
430
431
432
433
434
435
433
434
435
436
437
438
439

440
441
442
443
444
445
446
447







-
+








static IndicatorSpec checkbutton_spec = {
    13, 13, 4,		/* width, height, nimages */
    checkbutton_pixels,
    checkbutton_states
};

static Ttk_StateTable radiobutton_states[] = {
static const Ttk_StateTable radiobutton_states[] = {
    { 0, 0, TTK_STATE_SELECTED|TTK_STATE_DISABLED },
    { 1, TTK_STATE_SELECTED, TTK_STATE_DISABLED },
    { 2, TTK_STATE_DISABLED, TTK_STATE_SELECTED },
    { 3, TTK_STATE_SELECTED|TTK_STATE_DISABLED, 0 },
    { 0, 0, 0 }
};

461
462
463
464
465
466
467
468

469
470

471
472

473
474

475
476

477
478

479
480

481
482
483


484
485
486
487
488
489
490
491


492


493
494
495
496
497
498
499
500
501
502
503


504
505
506
507
508
509
510
473
474
475
476
477
478
479

480
481

482
483

484
485

486
487

488
489

490
491

492
493


494
495
496
497
498
499
500
501


502
503
504
505
506
507
508
509
510
511
512
513
514
515


516
517
518
519
520
521
522
523
524







-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
-
+
+






-
-
+
+

+
+









-
-
+
+







    Tcl_Obj *colorObj;
    Tcl_Obj *lightColorObj;
    Tcl_Obj *shadeColorObj;
    Tcl_Obj *borderColorObj;
    Tcl_Obj *marginObj;
} IndicatorElement;

static Ttk_ElementOptionSpec IndicatorElementOptions[] = {
static const Ttk_ElementOptionSpec IndicatorElementOptions[] = {
    { "-background", TK_OPTION_COLOR,
	    Tk_Offset(IndicatorElement,backgroundObj), DEFAULT_BACKGROUND },
	    offsetof(IndicatorElement,backgroundObj), DEFAULT_BACKGROUND },
    { "-foreground", TK_OPTION_COLOR,
	    Tk_Offset(IndicatorElement,foregroundObj), DEFAULT_FOREGROUND },
	    offsetof(IndicatorElement,foregroundObj), DEFAULT_FOREGROUND },
    { "-indicatorcolor", TK_OPTION_COLOR,
	    Tk_Offset(IndicatorElement,colorObj), "#FFFFFF" },
	    offsetof(IndicatorElement,colorObj), "#FFFFFF" },
    { "-lightcolor", TK_OPTION_COLOR,
	    Tk_Offset(IndicatorElement,lightColorObj), "#DDDDDD" },
	    offsetof(IndicatorElement,lightColorObj), "#DDDDDD" },
    { "-shadecolor", TK_OPTION_COLOR,
	    Tk_Offset(IndicatorElement,shadeColorObj), "#888888" },
	    offsetof(IndicatorElement,shadeColorObj), "#888888" },
    { "-bordercolor", TK_OPTION_COLOR,
	    Tk_Offset(IndicatorElement,borderColorObj), "black" },
	    offsetof(IndicatorElement,borderColorObj), "black" },
    { "-indicatormargin", TK_OPTION_STRING,
	    Tk_Offset(IndicatorElement,marginObj), "0 2 4 2" },
	    { NULL, 0, 0, NULL }
	    offsetof(IndicatorElement,marginObj), "0 2 4 2" },
	    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
};

static void IndicatorElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    IndicatorSpec *spec = clientData;
    IndicatorElement *indicator = elementRecord;
    IndicatorSpec *spec = (IndicatorSpec *)clientData;
    IndicatorElement *indicator = (IndicatorElement *)elementRecord;
    Ttk_Padding margins;
    (void)paddingPtr;

    Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &margins);
    *widthPtr = spec->width + Ttk_PaddingWidth(margins);
    *heightPtr = spec->height + Ttk_PaddingHeight(margins);
}

static void IndicatorElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    IndicatorSpec *spec = clientData;
    IndicatorElement *indicator = elementRecord;
    IndicatorSpec *spec = (IndicatorSpec *)clientData;
    IndicatorElement *indicator = (IndicatorElement *)elementRecord;
    Display *display = Tk_Display(tkwin);
    Ttk_Padding padding;
    XColor *fgColor, *frameColor, *shadeColor, *indicatorColor, *borderColor;

    int index, ix, iy;
    XGCValues gcValues;
    GC copyGC;
575
576
577
578
579
580
581
582

583
584
585
586
587
588
589
589
590
591
592
593
594
595

596
597
598
599
600
601
602
603







-
+








    if (img == NULL) {
        return;
    }

#if defined(IGNORES_VISUAL)

    img->data = ckalloc(img->bytes_per_line * img->height);
    img->data = (char *)ckalloc(img->bytes_per_line * img->height);
    if (img->data == NULL) {
        XDestroyImage(img);
	return;
    }

#endif

624
625
626
627
628
629
630
631

632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655

656
657

658
659

660
661

662
663

664
665
666


667
668
669
670
671
672
673
674

675
676
677
678
679
680
681


682

683
684
685
686
687
688
689
690
691
692
693
694
695
696


697
698
699
700
701

702
703
704
705
706
707
708
709
710
711
712
713

714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734

735
736
737
738
739

740
741

742
743

744
745
746


747
748
749

750
751
752

753
754
755

756



757
758
759
760
761
762
763
764

765
766
767

768
769
770
771
772
773


774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794

795
796
797
798
799
800
801
638
639
640
641
642
643
644

645
646
647
648
649
650
651
652
653
654
655
656
657
658
659

660
661
662
663
664
665
666
667

668
669

670
671

672
673

674
675

676
677


678
679
680
681
682
683
684
685
686

687
688
689
690
691
692


693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708


709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727

728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748

749
750
751
752
753

754
755

756
757

758
759


760
761
762
763

764
765
766

767
768
769

770
771
772
773
774
775
776
777
778
779
780
781

782
783
784

785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813

814
815
816
817
818
819
820
821







-
+














-








-
+

-
+

-
+

-
+

-
+

-
-
+
+







-
+





-
-
+
+

+












-
-
+
+





+











-
+




















-
+




-
+

-
+

-
+

-
-
+
+


-
+


-
+


-
+

+
+
+







-
+


-
+






+
+




















-
+







    ckfree(img->data);
    img->data = NULL;
#endif

    XDestroyImage(img);
}

static Ttk_ElementSpec IndicatorElementSpec = {
static const Ttk_ElementSpec IndicatorElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(IndicatorElement),
    IndicatorElementOptions,
    IndicatorElementSize,
    IndicatorElementDraw
};

/*----------------------------------------------------------------------
 * +++ Arrow element(s).
 *
 * 	Draws a solid triangle, inside a box.
 * 	clientData is an enum ArrowDirection pointer.
 */

static int ArrowElements[] = { ARROW_UP, ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT };
typedef struct {
    Tcl_Obj *sizeObj;
    Tcl_Obj *borderObj;
    Tcl_Obj *borderColorObj;	/* Extra color for borders */
    Tcl_Obj *reliefObj;
    Tcl_Obj *colorObj;		/* Arrow color */
} ArrowElement;

static Ttk_ElementOptionSpec ArrowElementOptions[] = {
static const Ttk_ElementOptionSpec ArrowElementOptions[] = {
    { "-arrowsize", TK_OPTION_PIXELS,
	Tk_Offset(ArrowElement,sizeObj), STRINGIFY(SCROLLBAR_WIDTH) },
	offsetof(ArrowElement,sizeObj), STRINGIFY(SCROLLBAR_WIDTH) },
    { "-background", TK_OPTION_BORDER,
	Tk_Offset(ArrowElement,borderObj), DEFAULT_BACKGROUND },
	offsetof(ArrowElement,borderObj), DEFAULT_BACKGROUND },
    { "-bordercolor", TK_OPTION_COLOR,
	Tk_Offset(ArrowElement,borderColorObj), "black" },
	offsetof(ArrowElement,borderColorObj), "black" },
    { "-relief", TK_OPTION_RELIEF,
	Tk_Offset(ArrowElement,reliefObj),"raised"},
	offsetof(ArrowElement,reliefObj),"raised"},
    { "-arrowcolor", TK_OPTION_COLOR,
	Tk_Offset(ArrowElement,colorObj),"black"},
    { NULL, 0, 0, NULL }
	offsetof(ArrowElement,colorObj),"black"},
    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
};

/*
 * Note asymmetric padding:
 * top/left padding is 1 less than bottom/right,
 * since in this theme 2-pixel borders are asymmetric.
 */
static Ttk_Padding ArrowPadding = { 3,3,4,4 };
static const Ttk_Padding ArrowPadding = { 3,3,4,4 };

static void ArrowElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    ArrowElement *arrow = elementRecord;
    int direction = *(int *)clientData;
    ArrowElement *arrow = (ArrowElement *)elementRecord;
	ArrowDirection direction = (ArrowDirection)PTR2INT(clientData);
    int width = SCROLLBAR_WIDTH;
    (void)paddingPtr;

    Tk_GetPixelsFromObj(NULL, tkwin, arrow->sizeObj, &width);
    width -= Ttk_PaddingWidth(ArrowPadding);
    TtkArrowSize(width/2, direction, widthPtr, heightPtr);
    *widthPtr += Ttk_PaddingWidth(ArrowPadding);
    *heightPtr += Ttk_PaddingHeight(ArrowPadding);
}

static void ArrowElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    int direction = *(int *)clientData;
    ArrowElement *arrow = elementRecord;
	ArrowDirection direction = (ArrowDirection)PTR2INT(clientData);
    ArrowElement *arrow = (ArrowElement *)elementRecord;
    Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, arrow->borderObj);
    XColor *borderColor = Tk_GetColorFromObj(tkwin, arrow->borderColorObj);
    XColor *arrowColor = Tk_GetColorFromObj(tkwin, arrow->colorObj);
    int relief = TK_RELIEF_RAISED;
    int borderWidth = 2;
    (void)state;

    Tk_GetReliefFromObj(NULL, arrow->reliefObj, &relief);

    Tk_Fill3DRectangle(
	tkwin, d, border, b.x, b.y, b.width, b.height, 0, TK_RELIEF_FLAT);
    DrawBorder(tkwin,d,border,borderColor,b,borderWidth,relief);

    TtkFillArrow(Tk_Display(tkwin), d, Tk_GCForColor(arrowColor, d),
	Ttk_PadBox(b, ArrowPadding), direction);
}

static Ttk_ElementSpec ArrowElementSpec = {
static const Ttk_ElementSpec ArrowElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(ArrowElement),
    ArrowElementOptions,
    ArrowElementSize,
    ArrowElementDraw
};

/*----------------------------------------------------------------------
 * +++ Menubutton indicator:
 * 	Draw an arrow in the direction where the menu will be posted.
 */

#define MENUBUTTON_ARROW_SIZE 5

typedef struct {
    Tcl_Obj *directionObj;
    Tcl_Obj *sizeObj;
    Tcl_Obj *colorObj;
} MenubuttonArrowElement;

static const char *directionStrings[] = {	/* See also: button.c */
static const char *const directionStrings[] = {	/* See also: button.c */
    "above", "below", "left", "right", "flush", NULL
};
enum { POST_ABOVE, POST_BELOW, POST_LEFT, POST_RIGHT, POST_FLUSH };

static Ttk_ElementOptionSpec MenubuttonArrowElementOptions[] = {
static const Ttk_ElementOptionSpec MenubuttonArrowElementOptions[] = {
    { "-direction", TK_OPTION_STRING,
	Tk_Offset(MenubuttonArrowElement,directionObj), "below" },
	offsetof(MenubuttonArrowElement,directionObj), "below" },
    { "-arrowsize", TK_OPTION_PIXELS,
	Tk_Offset(MenubuttonArrowElement,sizeObj), STRINGIFY(MENUBUTTON_ARROW_SIZE)},
	offsetof(MenubuttonArrowElement,sizeObj), STRINGIFY(MENUBUTTON_ARROW_SIZE)},
    { "-arrowcolor",TK_OPTION_COLOR,
	Tk_Offset(MenubuttonArrowElement,colorObj), "black"},
    { NULL, 0, 0, NULL }
	offsetof(MenubuttonArrowElement,colorObj), "black"},
    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
};

static Ttk_Padding MenubuttonArrowPadding = { 3, 0, 3, 0 };
static const Ttk_Padding MenubuttonArrowPadding = { 3, 0, 3, 0 };

static void MenubuttonArrowElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    MenubuttonArrowElement *arrow = elementRecord;
    MenubuttonArrowElement *arrow = (MenubuttonArrowElement *)elementRecord;
    int size = MENUBUTTON_ARROW_SIZE;
    (void)dummy;
    (void)paddingPtr;

    Tk_GetPixelsFromObj(NULL, tkwin, arrow->sizeObj, &size);
    *widthPtr = *heightPtr = 2 * size + 1;
    *widthPtr += Ttk_PaddingWidth(MenubuttonArrowPadding);
    *heightPtr += Ttk_PaddingHeight(MenubuttonArrowPadding);
}

static void MenubuttonArrowElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    MenubuttonArrowElement *arrow = elementRecord;
    MenubuttonArrowElement *arrow = (MenubuttonArrowElement *)elementRecord;
    XColor *arrowColor = Tk_GetColorFromObj(tkwin, arrow->colorObj);
    GC gc = Tk_GCForColor(arrowColor, d);
    int size = MENUBUTTON_ARROW_SIZE;
    int postDirection = POST_BELOW;
    ArrowDirection arrowDirection = ARROW_DOWN;
    int width = 0, height = 0;
    (void)dummy;
    (void)state;

    Tk_GetPixelsFromObj(NULL, tkwin, arrow->sizeObj, &size);
    Tcl_GetIndexFromObjStruct(NULL, arrow->directionObj, directionStrings,
	   sizeof(char *), ""/*message*/, 0/*flags*/, &postDirection);

    /* ... this might not be such a great idea ... */
    switch (postDirection) {
	case POST_ABOVE:	arrowDirection = ARROW_UP; break;
	case POST_BELOW:	arrowDirection = ARROW_DOWN; break;
	case POST_LEFT:		arrowDirection = ARROW_LEFT; break;
	case POST_RIGHT:	arrowDirection = ARROW_RIGHT; break;
	case POST_FLUSH:	arrowDirection = ARROW_DOWN; break;
    }

    TtkArrowSize(size, arrowDirection, &width, &height);
    b = Ttk_PadBox(b, MenubuttonArrowPadding);
    b = Ttk_AnchorBox(b, width, height, TK_ANCHOR_CENTER);
    TtkFillArrow(Tk_Display(tkwin), d, gc, b, arrowDirection);
}

static Ttk_ElementSpec MenubuttonArrowElementSpec = {
static const Ttk_ElementSpec MenubuttonArrowElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(MenubuttonArrowElement),
    MenubuttonArrowElementOptions,
    MenubuttonArrowElementSize,
    MenubuttonArrowElementDraw
};

816
817
818
819
820
821
822
823

824
825

826
827

828
829

830
831

832
833
834


835
836
837
838

839
840
841

842



843
844
845
846
847
848
849
850
851
852
853

854
855
856

857
858




859
860
861

862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880

881
882
883
884
885
886
887
836
837
838
839
840
841
842

843
844

845
846

847
848

849
850

851
852


853
854
855
856
857

858
859
860

861
862
863
864
865
866
867
868
869
870
871
872
873
874
875

876
877
878

879
880

881
882
883
884
885
886

887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905

906
907
908
909
910
911
912
913







-
+

-
+

-
+

-
+

-
+

-
-
+
+



-
+


-
+

+
+
+










-
+


-
+

-
+
+
+
+


-
+


















-
+







    Tcl_Obj *colorObj;
    Tcl_Obj *borderWidthObj;
    Tcl_Obj *reliefObj;
    Tcl_Obj *grooveWidthObj;
    Tcl_Obj *orientObj;
} TroughElement;

static Ttk_ElementOptionSpec TroughElementOptions[] = {
static const Ttk_ElementOptionSpec TroughElementOptions[] = {
    { "-orient", TK_OPTION_ANY,
	Tk_Offset(TroughElement, orientObj), "horizontal" },
	offsetof(TroughElement, orientObj), "horizontal" },
    { "-troughborderwidth", TK_OPTION_PIXELS,
	Tk_Offset(TroughElement,borderWidthObj), "1" },
	offsetof(TroughElement,borderWidthObj), "1" },
    { "-troughcolor", TK_OPTION_BORDER,
	Tk_Offset(TroughElement,colorObj), DEFAULT_BACKGROUND },
	offsetof(TroughElement,colorObj), DEFAULT_BACKGROUND },
    { "-troughrelief",TK_OPTION_RELIEF,
	Tk_Offset(TroughElement,reliefObj), "sunken" },
	offsetof(TroughElement,reliefObj), "sunken" },
    { "-groovewidth", TK_OPTION_PIXELS,
	Tk_Offset(TroughElement,grooveWidthObj), "-1" },
    { NULL, 0, 0, NULL }
	offsetof(TroughElement,grooveWidthObj), "-1" },
    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
};

static void TroughElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    TroughElement *troughPtr = elementRecord;
    TroughElement *troughPtr = (TroughElement *)elementRecord;
    int borderWidth = 2, grooveWidth = 0;
    (void)dummy;
    (void)widthPtr;
    (void)heightPtr;

    Tk_GetPixelsFromObj(NULL, tkwin, troughPtr->borderWidthObj, &borderWidth);
    Tk_GetPixelsFromObj(NULL, tkwin, troughPtr->grooveWidthObj, &grooveWidth);

    if (grooveWidth <= 0) {
	*paddingPtr = Ttk_UniformPadding((short)borderWidth);
    }
}

static void TroughElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    TroughElement *troughPtr = elementRecord;
    TroughElement *troughPtr = (TroughElement *)elementRecord;
    Tk_3DBorder border = NULL;
    int borderWidth = 2, relief = TK_RELIEF_SUNKEN, groove = -1, orient;
    int borderWidth = 2, relief = TK_RELIEF_SUNKEN, groove = -1;
    Ttk_Orient orient;
    (void)dummy;
    (void)state;

    border = Tk_Get3DBorderFromObj(tkwin, troughPtr->colorObj);
    Ttk_GetOrientFromObj(NULL, troughPtr->orientObj, &orient);
    TtkGetOrientFromObj(NULL, troughPtr->orientObj, &orient);
    Tk_GetReliefFromObj(NULL, troughPtr->reliefObj, &relief);
    Tk_GetPixelsFromObj(NULL, tkwin, troughPtr->borderWidthObj, &borderWidth);
    Tk_GetPixelsFromObj(NULL, tkwin, troughPtr->grooveWidthObj, &groove);

    if (groove != -1 && groove < b.height && groove < b.width) {
	if (orient == TTK_ORIENT_HORIZONTAL) {
	    b.y = b.y + b.height/2 - groove/2;
	    b.height = groove;
	} else {
	    b.x = b.x + b.width/2 - groove/2;
	    b.width = groove;
	}
    }

    Tk_Fill3DRectangle(tkwin, d, border, b.x, b.y, b.width, b.height,
	    borderWidth, relief);
}

static Ttk_ElementSpec TroughElementSpec = {
static const Ttk_ElementSpec TroughElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(TroughElement),
    TroughElementOptions,
    TroughElementSize,
    TroughElementDraw
};

896
897
898
899
900
901
902
903
904


905
906

907
908

909
910
911
912



913
914
915
916

917
918
919
920






921
922

923
924
925
926
927
928
929
930
931
932
933
934

935
936
937

938
939
940
941


942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957

958
959
960
961
962
963
964
922
923
924
925
926
927
928


929
930
931

932
933

934
935



936
937
938
939
940
941

942
943
944


945
946
947
948
949
950
951

952
953
954
955
956
957
958
959
960
961
962
963

964
965
966

967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988

989
990
991
992
993
994
995
996







-
-
+
+

-
+

-
+

-
-
-
+
+
+



-
+


-
-
+
+
+
+
+
+

-
+











-
+


-
+




+
+















-
+







    Tcl_Obj *lastObj;
    Tcl_Obj *borderObj;
    Tcl_Obj *borderColorObj;
    Tcl_Obj *reliefObj;
    Tcl_Obj *orientObj;
} ThumbElement;

static Ttk_ElementOptionSpec ThumbElementOptions[] = {
    { "-width", TK_OPTION_PIXELS, Tk_Offset(ThumbElement,sizeObj),
static const Ttk_ElementOptionSpec ThumbElementOptions[] = {
    { "-width", TK_OPTION_PIXELS, offsetof(ThumbElement,sizeObj),
        STRINGIFY(SCROLLBAR_WIDTH) },
    { "-background", TK_OPTION_BORDER, Tk_Offset(ThumbElement,borderObj),
    { "-background", TK_OPTION_BORDER, offsetof(ThumbElement,borderObj),
	DEFAULT_BACKGROUND },
    { "-bordercolor", TK_OPTION_COLOR, Tk_Offset(ThumbElement,borderColorObj),
    { "-bordercolor", TK_OPTION_COLOR, offsetof(ThumbElement,borderColorObj),
	"black" },
    { "-relief", TK_OPTION_RELIEF,Tk_Offset(ThumbElement,reliefObj),"raised" },
    { "-orient", TK_OPTION_ANY,Tk_Offset(ThumbElement,orientObj),"horizontal"},
    { NULL, 0, 0, NULL }
    { "-relief", TK_OPTION_RELIEF, offsetof(ThumbElement,reliefObj),"raised" },
    { "-orient", TK_OPTION_ANY, offsetof(ThumbElement,orientObj),"horizontal"},
    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
};

static void ThumbElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    ThumbElement *thumb = elementRecord;
    int orient, size;
    ThumbElement *thumb = (ThumbElement *)elementRecord;
    Ttk_Orient orient;
    int size;
    (void)dummy;
    (void)paddingPtr;

    Tk_GetPixelsFromObj(NULL, tkwin, thumb->sizeObj, &size);
    Ttk_GetOrientFromObj(NULL, thumb->orientObj, &orient);
    TtkGetOrientFromObj(NULL, thumb->orientObj, &orient);

    if (orient == TTK_ORIENT_VERTICAL) {
	*widthPtr = size;
	*heightPtr = MIN_THUMB_SIZE;
    } else {
	*widthPtr = MIN_THUMB_SIZE;
	*heightPtr = size;
    }
}

static void ThumbElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    ThumbElement *thumb = elementRecord;
    ThumbElement *thumb = (ThumbElement *)elementRecord;
    Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, thumb->borderObj);
    XColor *borderColor = Tk_GetColorFromObj(tkwin, thumb->borderColorObj);
    int relief = TK_RELIEF_RAISED;
    int borderWidth = 2;
    (void)dummy;
    (void)state;

    /*
     * Don't draw the thumb if we are disabled.
     * This makes it behave like Windows ... if that's what we want.
    if (state & TTK_STATE_DISABLED)
	return;
     */

    Tk_GetReliefFromObj(NULL, thumb->reliefObj, &relief);

    Tk_Fill3DRectangle(
	tkwin, d, border, b.x,b.y,b.width,b.height, 0, TK_RELIEF_FLAT);
    DrawBorder(tkwin, d, border, borderColor, b, borderWidth, relief);
}

static Ttk_ElementSpec ThumbElementSpec = {
static const Ttk_ElementSpec ThumbElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(ThumbElement),
    ThumbElementOptions,
    ThumbElementSize,
    ThumbElementDraw
};

979
980
981
982
983
984
985
986
987


988
989

990
991

992
993

994
995

996
997

998
999

1000
1001

1002
1003
1004
1005

1006
1007
1008
1009





1010
1011

1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030

1031
1032
1033

1034
1035
1036


1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047

1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068

1069
1070

1071
1072

1073
1074
1075


1076
1077
1078
1079

1080
1081
1082

1083
1084


1085
1086
1087
1088
1089
1090
1091
1092
1093

1094
1095
1096

1097
1098
1099
1100
1101

1102
1103
1104
1105
1106
1107
1108
1011
1012
1013
1014
1015
1016
1017


1018
1019
1020

1021
1022

1023
1024

1025
1026

1027
1028

1029
1030

1031
1032

1033
1034
1035
1036

1037
1038
1039


1040
1041
1042
1043
1044
1045

1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064

1065
1066
1067

1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083

1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104

1105
1106

1107
1108

1109
1110


1111
1112
1113
1114
1115

1116
1117
1118

1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131

1132
1133
1134

1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148







-
-
+
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+



-
+


-
-
+
+
+
+
+

-
+


















-
+


-
+



+
+










-
+




















-
+

-
+

-
+

-
-
+
+



-
+


-
+


+
+








-
+


-
+





+







    Tcl_Obj *reliefObj;		/* Relief for this object */
    Tcl_Obj *borderObj;		/* Border / background color */
    Tcl_Obj *borderColorObj;	/* Additional border color */
    Tcl_Obj *borderWidthObj;
    Tcl_Obj *orientObj;		/* Orientation of overall slider */
} SliderElement;

static Ttk_ElementOptionSpec SliderElementOptions[] = {
    { "-sliderlength", TK_OPTION_PIXELS, Tk_Offset(SliderElement,lengthObj),
static const Ttk_ElementOptionSpec SliderElementOptions[] = {
    { "-sliderlength", TK_OPTION_PIXELS, offsetof(SliderElement,lengthObj),
	"15" },
    { "-sliderthickness",TK_OPTION_PIXELS,Tk_Offset(SliderElement,thicknessObj),
    { "-sliderthickness",TK_OPTION_PIXELS, offsetof(SliderElement,thicknessObj),
	"15" },
    { "-sliderrelief", TK_OPTION_RELIEF, Tk_Offset(SliderElement,reliefObj),
    { "-sliderrelief", TK_OPTION_RELIEF, offsetof(SliderElement,reliefObj),
	"raised" },
    { "-borderwidth", TK_OPTION_PIXELS, Tk_Offset(SliderElement,borderWidthObj),
    { "-borderwidth", TK_OPTION_PIXELS, offsetof(SliderElement,borderWidthObj),
	STRINGIFY(BORDERWIDTH) },
    { "-background", TK_OPTION_BORDER, Tk_Offset(SliderElement,borderObj),
    { "-background", TK_OPTION_BORDER, offsetof(SliderElement,borderObj),
	DEFAULT_BACKGROUND },
    { "-bordercolor", TK_OPTION_COLOR, Tk_Offset(ThumbElement,borderColorObj),
    { "-bordercolor", TK_OPTION_COLOR, offsetof(ThumbElement,borderColorObj),
	"black" },
    { "-orient", TK_OPTION_ANY, Tk_Offset(SliderElement,orientObj),
    { "-orient", TK_OPTION_ANY, offsetof(SliderElement,orientObj),
	"horizontal" },
    { NULL, 0, 0, NULL }
    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
};

static void SliderElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    SliderElement *slider = elementRecord;
    int orient, length, thickness, borderWidth;
    SliderElement *slider = (SliderElement *)elementRecord;
    Ttk_Orient orient;
    int length, thickness, borderWidth;
    (void)dummy;
    (void)paddingPtr;

    Ttk_GetOrientFromObj(NULL, slider->orientObj, &orient);
    TtkGetOrientFromObj(NULL, slider->orientObj, &orient);
    Tk_GetPixelsFromObj(NULL, tkwin, slider->borderWidthObj, &borderWidth);
    Tk_GetPixelsFromObj(NULL, tkwin, slider->lengthObj, &length);
    Tk_GetPixelsFromObj(NULL, tkwin, slider->thicknessObj, &thickness);

    switch (orient) {
	case TTK_ORIENT_VERTICAL:
	    *widthPtr = thickness + (borderWidth *2);
	    *heightPtr = *widthPtr/2;
	    break;

	case TTK_ORIENT_HORIZONTAL:
	    *heightPtr = thickness + (borderWidth *2);
	    *widthPtr = *heightPtr/2;
	    break;
    }
}

static void SliderElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    SliderElement *slider = elementRecord;
    SliderElement *slider = (SliderElement *)elementRecord;
    Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, slider->borderObj);
    XColor *borderColor = Tk_GetColorFromObj(tkwin, slider->borderColorObj);
    int relief = TK_RELIEF_RAISED, borderWidth = 2;
    (void)dummy;
    (void)state;

    Tk_GetPixelsFromObj(NULL, tkwin, slider->borderWidthObj, &borderWidth);
    Tk_GetReliefFromObj(NULL, slider->reliefObj, &relief);

    Tk_Fill3DRectangle(tkwin, d, border,
	b.x, b.y, b.width, b.height,
	borderWidth, TK_RELIEF_FLAT);
    DrawBorder(tkwin, d, border, borderColor, b, borderWidth, relief);
}

static Ttk_ElementSpec SliderElementSpec = {
static const Ttk_ElementSpec SliderElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(SliderElement),
    SliderElementOptions,
    SliderElementSize,
    SliderElementDraw
};

/*------------------------------------------------------------------------
 * +++ Tree indicator element.
 */

#define TTK_STATE_OPEN TTK_STATE_USER1		/* XREF: treeview.c */
#define TTK_STATE_LEAF TTK_STATE_USER2

typedef struct {
    Tcl_Obj *colorObj;
    Tcl_Obj *marginObj;
    Tcl_Obj *diameterObj;
} TreeitemIndicator;

static Ttk_ElementOptionSpec TreeitemIndicatorOptions[] = {
static const Ttk_ElementOptionSpec TreeitemIndicatorOptions[] = {
    { "-foreground", TK_OPTION_COLOR,
	Tk_Offset(TreeitemIndicator,colorObj), DEFAULT_FOREGROUND },
	offsetof(TreeitemIndicator,colorObj), DEFAULT_FOREGROUND },
    { "-diameter", TK_OPTION_PIXELS,
	Tk_Offset(TreeitemIndicator,diameterObj), "9" },
	offsetof(TreeitemIndicator,diameterObj), "9" },
    { "-indicatormargins", TK_OPTION_STRING,
	Tk_Offset(TreeitemIndicator,marginObj), "2 2 4 2" },
    { NULL, 0, 0, NULL }
	offsetof(TreeitemIndicator,marginObj), "2 2 4 2" },
    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
};

static void TreeitemIndicatorSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    TreeitemIndicator *indicator = elementRecord;
    TreeitemIndicator *indicator = (TreeitemIndicator *)elementRecord;
    int diameter = 0;
    Ttk_Padding margins;
    (void)dummy;
    (void)paddingPtr;

    Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &margins);
    Tk_GetPixelsFromObj(NULL, tkwin, indicator->diameterObj, &diameter);
    *widthPtr = diameter + Ttk_PaddingWidth(margins);
    *heightPtr = diameter + Ttk_PaddingHeight(margins);
}

static void TreeitemIndicatorDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, Ttk_State state)
{
    TreeitemIndicator *indicator = elementRecord;
    TreeitemIndicator *indicator = (TreeitemIndicator *)elementRecord;
    XColor *color = Tk_GetColorFromObj(tkwin, indicator->colorObj);
    GC gc = Tk_GCForColor(color, d);
    Ttk_Padding padding = Ttk_UniformPadding(0);
    int w = WIN32_XDRAWLINE_HACK;
    int cx, cy;
    (void)dummy;

    if (state & TTK_STATE_LEAF) {
	/* don't draw anything ... */
	return;
    }

    Ttk_GetPaddingFromObj(NULL,tkwin,indicator->marginObj,&padding);
1117
1118
1119
1120
1121
1122
1123
1124

1125
1126
1127
1128
1129
1130
1131
1157
1158
1159
1160
1161
1162
1163

1164
1165
1166
1167
1168
1169
1170
1171







-
+








    if (!(state & TTK_STATE_OPEN)) {
	/* turn '-' into a '+' */
	XDrawLine(Tk_Display(tkwin), d, gc, cx, b.y+2, cx, b.y+b.height-3+w);
    }
}

static Ttk_ElementSpec TreeitemIndicatorElementSpec = {
static const Ttk_ElementSpec TreeitemIndicatorElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(TreeitemIndicator),
    TreeitemIndicatorOptions,
    TreeitemIndicatorSize,
    TreeitemIndicatorDraw
};

1153
1154
1155
1156
1157
1158
1159
1160

1161
1162

1163
1164

1165
1166

1167
1168

1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1193
1194
1195
1196
1197
1198
1199

1200
1201

1202
1203

1204
1205

1206
1207

1208



1209
1210
1211
1212
1213
1214
1215
1216
1217
1218







-
+

-
+

-
+

-
+

-
+
-
-
-










    Ttk_RegisterElement(interp, theme, "field", &FieldElementSpec, NULL);

    Ttk_RegisterElement(interp, theme, "trough", &TroughElementSpec, NULL);
    Ttk_RegisterElement(interp, theme, "thumb", &ThumbElementSpec, NULL);
    Ttk_RegisterElement(interp, theme, "slider", &SliderElementSpec, NULL);

    Ttk_RegisterElement(interp, theme, "uparrow",
	    &ArrowElementSpec, &ArrowElements[0]);
	    &ArrowElementSpec, INT2PTR(ARROW_UP));
    Ttk_RegisterElement(interp, theme, "downarrow",
	    &ArrowElementSpec, &ArrowElements[1]);
	    &ArrowElementSpec, INT2PTR(ARROW_DOWN));
    Ttk_RegisterElement(interp, theme, "leftarrow",
	    &ArrowElementSpec, &ArrowElements[2]);
	    &ArrowElementSpec, INT2PTR(ARROW_LEFT));
    Ttk_RegisterElement(interp, theme, "rightarrow",
	    &ArrowElementSpec, &ArrowElements[3]);
	    &ArrowElementSpec, INT2PTR(ARROW_RIGHT));
    Ttk_RegisterElement(interp, theme, "arrow",
	    &ArrowElementSpec, &ArrowElements[0]);
	    &ArrowElementSpec, INT2PTR(ARROW_UP));

    Ttk_RegisterElement(interp, theme, "arrow",
	    &ArrowElementSpec, &ArrowElements[0]);

    Ttk_RegisterElement(interp, theme, "Treeitem.indicator",
	    &TreeitemIndicatorElementSpec, 0);

    Tcl_PkgProvide(interp, "ttk::theme::alt", TTK_VERSION);

    return TCL_OK;
}

/*EOF*/
Changes to generic/ttk/ttkElements.c.
1
2

3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

25
26
27
28

29
30






31
32
33
34
35

36
37






38
39
40
41
42
43
44
1

2
3
4
5
6
7


8

9
10
11
12
13
14
15
16
17
18
19
20
21

22
23
24
25

26
27
28
29
30
31
32
33
34
35
36
37
38

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

-
+





-
-
+
-













-
+



-
+


+
+
+
+
+
+




-
+


+
+
+
+
+
+







/*
 * Copyright (c) 2003, Joe English
 * Copyright © 2003 Joe English
 *
 * Default implementation for themed elements.
 *
 */

#include <tcl.h>
#include <tk.h>
#include "tkInt.h"
#include <string.h>
#include "ttkTheme.h"
#include "ttkWidget.h"

#define DEFAULT_BORDERWIDTH "2"
#define DEFAULT_ARROW_SIZE "15"
#define MIN_THUMB_SIZE 10

/*----------------------------------------------------------------------
 * +++ Null element.  Does nothing; used as a stub.
 * Null element methods, option table and element spec are public,
 * and may be used in other engines.
 */

/* public */ Ttk_ElementOptionSpec TtkNullElementOptions[] = { { NULL, 0, 0, NULL } };
/* public */ const Ttk_ElementOptionSpec TtkNullElementOptions[] = { { NULL, TK_OPTION_BOOLEAN, 0, NULL } };

/* public */ void
TtkNullElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    (void)dummy;
    (void)elementRecord;
    (void)tkwin;
    (void)widthPtr;
    (void)heightPtr;
    (void)paddingPtr;
}

/* public */ void
TtkNullElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    (void)dummy;
    (void)elementRecord;
    (void)tkwin;
    (void)d;
    (void)b;
    (void)state;
}

/* public */ Ttk_ElementSpec ttkNullElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(NullElement),
    TtkNullElementOptions,
    TtkNullElementSize,
54
55
56
57
58
59
60
61

62
63
64


65
66
67
68

69
70
71

72


73
74
75
76
77
78
79
80
81
82


83
84
85
86
87
88

89
90
91
92
93
94
95
96

97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114

115
116

117
118

119
120
121


122
123
124
125

126
127
128

129





130
131
132
133
134
135

136
137
138

139
140


141
142
143
144
145
146
147
148
149
150
151
152

153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169

170
171

172
173
174


175
176
177
178

179
180
181

182




183
184
185
186
187
188

189
190
191

192
193


194
195
196
197
198
199
200

201
202
203
204
205
206
207
64
65
66
67
68
69
70

71
72


73
74
75
76
77

78
79
80

81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101

102
103
104
105
106
107
108
109

110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127

128
129

130
131

132
133


134
135
136
137
138

139
140
141

142
143
144
145
146
147
148
149
150
151
152
153

154
155
156

157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172

173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189

190
191

192
193


194
195
196
197
198

199
200
201

202
203
204
205
206
207
208
209
210
211
212

213
214
215

216
217
218
219
220
221
222
223
224
225
226

227
228
229
230
231
232
233
234







-
+

-
-
+
+



-
+


-
+

+
+










+
+





-
+







-
+

















-
+

-
+

-
+

-
-
+
+



-
+


-
+

+
+
+
+
+





-
+


-
+


+
+











-
+
















-
+

-
+

-
-
+
+



-
+


-
+

+
+
+
+





-
+


-
+


+
+






-
+







 * Ttk_GetLayout() automatically includes a background element.
 */

typedef struct {
    Tcl_Obj	*backgroundObj;
} BackgroundElement;

static Ttk_ElementOptionSpec BackgroundElementOptions[] = {
static const Ttk_ElementOptionSpec BackgroundElementOptions[] = {
    { "-background", TK_OPTION_BORDER,
	    Tk_Offset(BackgroundElement,backgroundObj), DEFAULT_BACKGROUND },
    { NULL, 0, 0, NULL }
	    offsetof(BackgroundElement,backgroundObj), DEFAULT_BACKGROUND },
    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
};

static void FillElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    BackgroundElement *bg = elementRecord;
    BackgroundElement *bg = (BackgroundElement *)elementRecord;
    Tk_3DBorder backgroundPtr = Tk_Get3DBorderFromObj(tkwin,bg->backgroundObj);
    (void)dummy;
    (void)state;

    XFillRectangle(Tk_Display(tkwin), d,
	Tk_3DBorderGC(tkwin, backgroundPtr, TK_3D_FLAT_GC),
	b.x, b.y, b.width, b.height);
}

static void BackgroundElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    (void)b;

    FillElementDraw(
	clientData, elementRecord, tkwin,
	d, Ttk_WinBox(tkwin), state);
}

static Ttk_ElementSpec FillElementSpec = {
static const Ttk_ElementSpec FillElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(BackgroundElement),
    BackgroundElementOptions,
    TtkNullElementSize,
    FillElementDraw
};

static Ttk_ElementSpec BackgroundElementSpec = {
static const Ttk_ElementSpec BackgroundElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(BackgroundElement),
    BackgroundElementOptions,
    TtkNullElementSize,
    BackgroundElementDraw
};

/*----------------------------------------------------------------------
 * +++ Border element.
 */

typedef struct {
    Tcl_Obj	*borderObj;
    Tcl_Obj	*borderWidthObj;
    Tcl_Obj	*reliefObj;
} BorderElement;

static Ttk_ElementOptionSpec BorderElementOptions[] = {
static const Ttk_ElementOptionSpec BorderElementOptions[] = {
    { "-background", TK_OPTION_BORDER,
	Tk_Offset(BorderElement,borderObj), DEFAULT_BACKGROUND },
	offsetof(BorderElement,borderObj), DEFAULT_BACKGROUND },
    { "-borderwidth", TK_OPTION_PIXELS,
	Tk_Offset(BorderElement,borderWidthObj), DEFAULT_BORDERWIDTH },
	offsetof(BorderElement,borderWidthObj), DEFAULT_BORDERWIDTH },
    { "-relief", TK_OPTION_RELIEF,
	Tk_Offset(BorderElement,reliefObj), "flat" },
    { NULL, 0, 0, NULL }
	offsetof(BorderElement,reliefObj), "flat" },
    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
};

static void BorderElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    BorderElement *bd = elementRecord;
    BorderElement *bd = (BorderElement *)elementRecord;
    int borderWidth = 0;
    (void)dummy;
    (void)tkwin;
    (void)widthPtr;
    (void)heightPtr;

    Tcl_GetIntFromObj(NULL, bd->borderWidthObj, &borderWidth);
    *paddingPtr = Ttk_UniformPadding((short)borderWidth);
}

static void BorderElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    BorderElement *bd = elementRecord;
    BorderElement *bd = (BorderElement *)elementRecord;
    Tk_3DBorder border = NULL;
    int borderWidth = 1, relief = TK_RELIEF_FLAT;
    (void)dummy;
    (void)state;

    border = Tk_Get3DBorderFromObj(tkwin, bd->borderObj);
    Tcl_GetIntFromObj(NULL, bd->borderWidthObj, &borderWidth);
    Tk_GetReliefFromObj(NULL, bd->reliefObj, &relief);

    if (border && borderWidth > 0 && relief != TK_RELIEF_FLAT) {
	Tk_Draw3DRectangle(tkwin, d, border,
	    b.x, b.y, b.width, b.height, borderWidth,relief);
    }
}

static Ttk_ElementSpec BorderElementSpec = {
static const Ttk_ElementSpec BorderElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(BorderElement),
    BorderElementOptions,
    BorderElementSize,
    BorderElementDraw
};

/*----------------------------------------------------------------------
 * +++ Field element.
 * 	Used for editable fields.
 */
typedef struct {
    Tcl_Obj	*borderObj;
    Tcl_Obj	*borderWidthObj;
} FieldElement;

static Ttk_ElementOptionSpec FieldElementOptions[] = {
static const Ttk_ElementOptionSpec FieldElementOptions[] = {
    { "-fieldbackground", TK_OPTION_BORDER,
	Tk_Offset(FieldElement,borderObj), "white" },
	offsetof(FieldElement,borderObj), "white" },
    { "-borderwidth", TK_OPTION_PIXELS,
	Tk_Offset(FieldElement,borderWidthObj), "2" },
    { NULL, 0, 0, NULL }
	offsetof(FieldElement,borderWidthObj), "2" },
    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
};

static void FieldElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    FieldElement *field = elementRecord;
    FieldElement *field = (FieldElement *)elementRecord;
    int borderWidth = 2;
    (void)dummy;
    (void)widthPtr;
    (void)heightPtr;

    Tk_GetPixelsFromObj(NULL, tkwin, field->borderWidthObj, &borderWidth);
    *paddingPtr = Ttk_UniformPadding((short)borderWidth);
}

static void FieldElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    FieldElement *field = elementRecord;
    FieldElement *field = (FieldElement *)elementRecord;
    Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, field->borderObj);
    int borderWidth = 2;
    (void)dummy;
    (void)state;

    Tk_GetPixelsFromObj(NULL, tkwin, field->borderWidthObj, &borderWidth);
    Tk_Fill3DRectangle(tkwin, d, border,
	    b.x, b.y, b.width, b.height, borderWidth, TK_RELIEF_SUNKEN);
}

static Ttk_ElementSpec FieldElementSpec = {
static const Ttk_ElementSpec FieldElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(FieldElement),
    FieldElementOptions,
    FieldElementSize,
    FieldElementDraw
};

218
219
220
221
222
223
224
225

226
227

228
229

230
231
232


233
234
235
236

237
238
239

240
241
242



243
244
245
246
247
248
249
250

251
252
253
254
255
256
257
245
246
247
248
249
250
251

252
253

254
255

256
257


258
259
260
261
262

263
264
265

266
267
268
269
270
271
272
273
274
275
276
277
278
279

280
281
282
283
284
285
286
287







-
+

-
+

-
+

-
-
+
+



-
+


-
+



+
+
+







-
+








typedef struct {
    Tcl_Obj	*paddingObj;
    Tcl_Obj	*reliefObj;
    Tcl_Obj	*shiftreliefObj;
} PaddingElement;

static Ttk_ElementOptionSpec PaddingElementOptions[] = {
static const Ttk_ElementOptionSpec PaddingElementOptions[] = {
    { "-padding", TK_OPTION_STRING,
	Tk_Offset(PaddingElement,paddingObj), "0" },
	offsetof(PaddingElement,paddingObj), "0" },
    { "-relief", TK_OPTION_RELIEF,
	Tk_Offset(PaddingElement,reliefObj), "flat" },
	offsetof(PaddingElement,reliefObj), "flat" },
    { "-shiftrelief", TK_OPTION_INT,
	Tk_Offset(PaddingElement,shiftreliefObj), "0" },
    { NULL, 0, 0, NULL }
	offsetof(PaddingElement,shiftreliefObj), "0" },
    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
};

static void PaddingElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    PaddingElement *padding = elementRecord;
    PaddingElement *padding = (PaddingElement *)elementRecord;
    int shiftRelief = 0;
    int relief = TK_RELIEF_FLAT;
    Ttk_Padding pad;
    (void)dummy;
    (void)widthPtr;
    (void)heightPtr;

    Tk_GetReliefFromObj(NULL, padding->reliefObj, &relief);
    Tcl_GetIntFromObj(NULL, padding->shiftreliefObj, &shiftRelief);
    Ttk_GetPaddingFromObj(NULL,tkwin,padding->paddingObj,&pad);
    *paddingPtr = Ttk_RelievePadding(pad, relief, shiftRelief);
}

static Ttk_ElementSpec PaddingElementSpec = {
static const Ttk_ElementSpec PaddingElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(PaddingElement),
    PaddingElementOptions,
    PaddingElementSize,
    TtkNullElementDraw
};

284
285
286
287
288
289
290
291

292
293

294
295
296


297
298
299
300

301
302
303

304




305
306
307
308
309
310
311

312
313
314

315

316
317
318
319
320
321
322
323

324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343

344
345

346
347
348


349
350
351
352

353
354





355
356
357
358
359

360
361
362

363
364
365


366
367
368
369
370
371
372

373
374
375

376
377
378


379
380
381
382
383
384
385
386
387
388
389
390




391
392
393
394
395
396
397
398
399
400
401
402
403

404
405
406
407
408
409
410
411

412
413
414
415
416
417
418
419

420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435

436
437
438


439
440
441
442

443
444
445





446
447
448
449
450

451
452
453

454
455
456
457
458


459
460
461
462
463
464
465
466
467
468

469
470
471
472
473
474
475
314
315
316
317
318
319
320

321
322

323
324


325
326
327
328
329

330
331
332

333
334
335
336
337
338
339
340
341
342
343
344

345
346
347

348
349
350
351
352
353
354
355
356
357

358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377

378
379

380
381


382
383
384
385
386

387
388
389
390
391
392
393
394
395
396
397
398

399
400
401

402
403
404
405
406
407
408
409
410
411
412
413

414
415
416

417
418
419
420
421
422
423
424
425
426
427
428
429
430
431



432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447

448
449
450
451
452
453
454
455

456
457
458
459
460
461
462
463

464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479

480
481


482
483
484
485
486

487
488
489
490
491
492
493
494
495
496
497
498
499

500
501
502

503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519

520
521
522
523
524
525
526
527







-
+

-
+

-
-
+
+



-
+


-
+

+
+
+
+






-
+


-
+

+







-
+



















-
+

-
+

-
-
+
+



-
+


+
+
+
+
+




-
+


-
+



+
+






-
+


-
+



+
+









-
-
-
+
+
+
+












-
+







-
+







-
+















-
+

-
-
+
+



-
+



+
+
+
+
+




-
+


-
+





+
+









-
+







    mask = GCForeground | GCLineStyle | GCDashList | GCDashOffset | GCLineWidth;

    gc = Tk_GetGC(tkwin, mask, &gcvalues);
    XDrawRectangle(Tk_Display(tkwin), d, gc, b.x, b.y, b.width-1, b.height-1);
    Tk_FreeGC(Tk_Display(tkwin), gc);
}

static Ttk_ElementOptionSpec FocusElementOptions[] = {
static const Ttk_ElementOptionSpec FocusElementOptions[] = {
    { "-focuscolor",TK_OPTION_COLOR,
	Tk_Offset(FocusElement,focusColorObj), "black" },
	offsetof(FocusElement,focusColorObj), "black" },
    { "-focusthickness",TK_OPTION_PIXELS,
	Tk_Offset(FocusElement,focusThicknessObj), "1" },
    { NULL, 0, 0, NULL }
	offsetof(FocusElement,focusThicknessObj), "1" },
    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
};

static void FocusElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    FocusElement *focus = elementRecord;
    FocusElement *focus = (FocusElement *)elementRecord;
    int focusThickness = 0;
    (void)dummy;
    (void)tkwin;
    (void)widthPtr;
    (void)heightPtr;

    Tcl_GetIntFromObj(NULL, focus->focusThicknessObj, &focusThickness);
    *paddingPtr = Ttk_UniformPadding((short)focusThickness);
}

static void FocusElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    FocusElement *focus = elementRecord;
    FocusElement *focus = (FocusElement *)elementRecord;
    int focusThickness = 0;
    (void)dummy;

    if (state & TTK_STATE_FOCUS) {
	Tcl_GetIntFromObj(NULL,focus->focusThicknessObj,&focusThickness);
	DrawFocusRing(tkwin, d, focus->focusColorObj, b);
    }
}

static Ttk_ElementSpec FocusElementSpec = {
static const Ttk_ElementSpec FocusElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(FocusElement),
    FocusElementOptions,
    FocusElementSize,
    FocusElementDraw
};

/*----------------------------------------------------------------------
 * +++ Separator element.
 * 	Just draws a horizontal or vertical bar.
 * 	Three elements are defined: horizontal, vertical, and general;
 *	the general separator checks the "-orient" option.
 */

typedef struct {
    Tcl_Obj	*orientObj;
    Tcl_Obj	*borderObj;
} SeparatorElement;

static Ttk_ElementOptionSpec SeparatorElementOptions[] = {
static const Ttk_ElementOptionSpec SeparatorElementOptions[] = {
    { "-orient", TK_OPTION_ANY,
	Tk_Offset(SeparatorElement, orientObj), "horizontal" },
	offsetof(SeparatorElement, orientObj), "horizontal" },
    { "-background", TK_OPTION_BORDER,
	Tk_Offset(SeparatorElement,borderObj), DEFAULT_BACKGROUND },
    { NULL, 0, 0, NULL }
	offsetof(SeparatorElement,borderObj), DEFAULT_BACKGROUND },
    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
};

static void SeparatorElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    (void)dummy;
    (void)elementRecord;
    (void)tkwin;
    (void)paddingPtr;

    *widthPtr = *heightPtr = 2;
}

static void HorizontalSeparatorElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    SeparatorElement *separator = elementRecord;
    SeparatorElement *separator = (SeparatorElement *)elementRecord;
    Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, separator->borderObj);
    GC lightGC = Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC);
    GC darkGC = Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC);
    (void)dummy;
    (void)state;

    XDrawLine(Tk_Display(tkwin), d, darkGC, b.x, b.y, b.x + b.width, b.y);
    XDrawLine(Tk_Display(tkwin), d, lightGC, b.x, b.y+1, b.x + b.width, b.y+1);
}

static void VerticalSeparatorElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    SeparatorElement *separator = elementRecord;
    SeparatorElement *separator = (SeparatorElement *)elementRecord;
    Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, separator->borderObj);
    GC lightGC = Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC);
    GC darkGC = Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC);
    (void)dummy;
    (void)state;

    XDrawLine(Tk_Display(tkwin), d, darkGC, b.x, b.y, b.x, b.y + b.height);
    XDrawLine(Tk_Display(tkwin), d, lightGC, b.x+1, b.y, b.x+1, b.y+b.height);
}

static void GeneralSeparatorElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    SeparatorElement *separator = elementRecord;
    int orient;
    Ttk_GetOrientFromObj(NULL, separator->orientObj, &orient);
    SeparatorElement *separator = (SeparatorElement *)elementRecord;
    Ttk_Orient orient;

    TtkGetOrientFromObj(NULL, separator->orientObj, &orient);
    switch (orient) {
	case TTK_ORIENT_HORIZONTAL:
	    HorizontalSeparatorElementDraw(
		clientData, elementRecord, tkwin, d, b, state);
	    break;
	case TTK_ORIENT_VERTICAL:
	    VerticalSeparatorElementDraw(
		clientData, elementRecord, tkwin, d, b, state);
	    break;
    }
}

static Ttk_ElementSpec HorizontalSeparatorElementSpec = {
static const Ttk_ElementSpec HorizontalSeparatorElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(SeparatorElement),
    SeparatorElementOptions,
    SeparatorElementSize,
    HorizontalSeparatorElementDraw
};

static Ttk_ElementSpec VerticalSeparatorElementSpec = {
static const Ttk_ElementSpec VerticalSeparatorElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(SeparatorElement),
    SeparatorElementOptions,
    SeparatorElementSize,
    HorizontalSeparatorElementDraw
};

static Ttk_ElementSpec SeparatorElementSpec = {
static const Ttk_ElementSpec SeparatorElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(SeparatorElement),
    SeparatorElementOptions,
    SeparatorElementSize,
    GeneralSeparatorElementDraw
};

/*----------------------------------------------------------------------
 * +++ Sizegrip: lower-right corner grip handle for resizing window.
 */

typedef struct {
    Tcl_Obj	*backgroundObj;
} SizegripElement;

static Ttk_ElementOptionSpec SizegripOptions[] = {
static const Ttk_ElementOptionSpec SizegripOptions[] = {
    { "-background", TK_OPTION_BORDER,
	Tk_Offset(SizegripElement,backgroundObj), DEFAULT_BACKGROUND },
    {0,0,0,0}
	offsetof(SizegripElement,backgroundObj), DEFAULT_BACKGROUND },
    {0,TK_OPTION_BOOLEAN,0,0}
};

static void SizegripSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    int gripCount = 3, gripSpace = 2, gripThickness = 3;
    (void)dummy;
    (void)elementRecord;
    (void)tkwin;
    (void)paddingPtr;

    *widthPtr = *heightPtr = gripCount * (gripSpace + gripThickness);
}

static void SizegripDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, Ttk_State state)
{
    SizegripElement *grip = elementRecord;
    SizegripElement *grip = (SizegripElement *)elementRecord;
    int gripCount = 3, gripSpace = 2;
    Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, grip->backgroundObj);
    GC lightGC = Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC);
    GC darkGC = Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC);
    int x1 = b.x + b.width-1, y1 = b.y + b.height-1, x2 = x1, y2 = y1;
    (void)dummy;
    (void)state;

    while (gripCount--) {
	x1 -= gripSpace; y2 -= gripSpace;
	XDrawLine(Tk_Display(tkwin), d, darkGC,  x1,y1, x2,y2); --x1; --y2;
	XDrawLine(Tk_Display(tkwin), d, darkGC,  x1,y1, x2,y2); --x1; --y2;
	XDrawLine(Tk_Display(tkwin), d, lightGC, x1,y1, x2,y2); --x1; --y2;
    }
}

static Ttk_ElementSpec SizegripElementSpec = {
static const Ttk_ElementSpec SizegripElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(SizegripElement),
    SizegripOptions,
    SizegripSize,
    SizegripDraw
};

489
490
491
492
493
494
495
496

497
498

499
500

501
502

503
504

505
506

507
508
509


510
511
512
513
514
515
516

517
518
519

520
521



522
523
524
525
526
527
528
529

530
531
532

533
534
535
536
537


538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558

559
560
561

562
563



564
565
566
567
568
569
570
571

572
573
574

575
576
577
578
579
580


581
582
583
584
585
586
587
541
542
543
544
545
546
547

548
549

550
551

552
553

554
555

556
557

558
559


560
561
562
563
564
565
566
567

568
569
570

571
572
573
574
575
576
577
578
579
580
581
582
583

584
585
586

587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614

615
616
617

618
619
620
621
622
623
624
625
626
627
628
629
630

631
632
633

634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649







-
+

-
+

-
+

-
+

-
+

-
+

-
-
+
+






-
+


-
+


+
+
+







-
+


-
+





+
+




















-
+


-
+


+
+
+







-
+


-
+






+
+







    Tcl_Obj *reliefObj;
    Tcl_Obj *colorObj;
    Tcl_Obj *diameterObj;
    Tcl_Obj *marginObj;
    Tcl_Obj *borderWidthObj;
} IndicatorElement;

static Ttk_ElementOptionSpec IndicatorElementOptions[] = {
static const Ttk_ElementOptionSpec IndicatorElementOptions[] = {
    { "-background", TK_OPTION_BORDER,
	Tk_Offset(IndicatorElement,backgroundObj), DEFAULT_BACKGROUND },
	offsetof(IndicatorElement,backgroundObj), DEFAULT_BACKGROUND },
    { "-indicatorcolor", TK_OPTION_BORDER,
	Tk_Offset(IndicatorElement,colorObj), DEFAULT_BACKGROUND },
	offsetof(IndicatorElement,colorObj), DEFAULT_BACKGROUND },
    { "-indicatorrelief", TK_OPTION_RELIEF,
	Tk_Offset(IndicatorElement,reliefObj), "raised" },
	offsetof(IndicatorElement,reliefObj), "raised" },
    { "-indicatordiameter", TK_OPTION_PIXELS,
	Tk_Offset(IndicatorElement,diameterObj), "12" },
	offsetof(IndicatorElement,diameterObj), "12" },
    { "-indicatormargin", TK_OPTION_STRING,
	Tk_Offset(IndicatorElement,marginObj), "0 2 4 2" },
	offsetof(IndicatorElement,marginObj), "0 2 4 2" },
    { "-borderwidth", TK_OPTION_PIXELS,
	Tk_Offset(IndicatorElement,borderWidthObj), DEFAULT_BORDERWIDTH },
    { NULL, 0, 0, NULL }
	offsetof(IndicatorElement,borderWidthObj), DEFAULT_BORDERWIDTH },
    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
};

/*
 * Checkbutton indicators (default): 3-D square.
 */
static void SquareIndicatorElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    IndicatorElement *indicator = elementRecord;
    IndicatorElement *indicator = (IndicatorElement *)elementRecord;
    Ttk_Padding margins;
    int diameter = 0;
    (void)dummy;
    (void)paddingPtr;

    Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &margins);
    Tk_GetPixelsFromObj(NULL, tkwin, indicator->diameterObj, &diameter);
    *widthPtr = diameter + Ttk_PaddingWidth(margins);
    *heightPtr = diameter + Ttk_PaddingHeight(margins);
}

static void SquareIndicatorElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    IndicatorElement *indicator = elementRecord;
    IndicatorElement *indicator = (IndicatorElement *)elementRecord;
    Tk_3DBorder border = 0, interior = 0;
    int relief = TK_RELIEF_RAISED;
    Ttk_Padding padding;
    int borderWidth = 2;
    int diameter;
    (void)dummy;
    (void)state;

    interior = Tk_Get3DBorderFromObj(tkwin, indicator->colorObj);
    border = Tk_Get3DBorderFromObj(tkwin, indicator->backgroundObj);
    Tcl_GetIntFromObj(NULL,indicator->borderWidthObj,&borderWidth);
    Tk_GetReliefFromObj(NULL,indicator->reliefObj,&relief);
    Ttk_GetPaddingFromObj(NULL,tkwin,indicator->marginObj,&padding);

    b = Ttk_PadBox(b, padding);

    diameter = b.width < b.height ? b.width : b.height;
    Tk_Fill3DRectangle(tkwin, d, interior, b.x, b.y,
	    diameter, diameter,borderWidth, TK_RELIEF_FLAT);
    Tk_Draw3DRectangle(tkwin, d, border, b.x, b.y,
	    diameter, diameter, borderWidth, relief);
}

/*
 * Radiobutton indicators:  3-D diamond.
 */
static void DiamondIndicatorElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    IndicatorElement *indicator = elementRecord;
    IndicatorElement *indicator = (IndicatorElement *)elementRecord;
    Ttk_Padding margins;
    int diameter = 0;
    (void)dummy;
    (void)paddingPtr;

    Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &margins);
    Tk_GetPixelsFromObj(NULL, tkwin, indicator->diameterObj, &diameter);
    *widthPtr = diameter + 3 + Ttk_PaddingWidth(margins);
    *heightPtr = diameter + 3 + Ttk_PaddingHeight(margins);
}

static void DiamondIndicatorElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    IndicatorElement *indicator = elementRecord;
    IndicatorElement *indicator = (IndicatorElement *)elementRecord;
    Tk_3DBorder border = 0, interior = 0;
    int borderWidth = 2;
    int relief = TK_RELIEF_RAISED;
    int diameter, radius;
    XPoint points[4];
    Ttk_Padding padding;
    (void)dummy;
    (void)state;

    interior = Tk_Get3DBorderFromObj(tkwin, indicator->colorObj);
    border = Tk_Get3DBorderFromObj(tkwin, indicator->backgroundObj);
    Tcl_GetIntFromObj(NULL,indicator->borderWidthObj,&borderWidth);
    Tk_GetReliefFromObj(NULL,indicator->reliefObj,&relief);
    Ttk_GetPaddingFromObj(NULL,tkwin,indicator->marginObj,&padding);

599
600
601
602
603
604
605
606

607
608
609
610
611
612
613
614

615
616
617
618
619
620
621
661
662
663
664
665
666
667

668
669
670
671
672
673
674
675

676
677
678
679
680
681
682
683







-
+







-
+







    points[3].x = b.x + radius;
    points[3].y = b.y;

    Tk_Fill3DPolygon(tkwin,d,interior,points,4,borderWidth,TK_RELIEF_FLAT);
    Tk_Draw3DPolygon(tkwin,d,border,points,4,borderWidth,relief);
}

static Ttk_ElementSpec CheckbuttonIndicatorElementSpec = {
static const Ttk_ElementSpec CheckbuttonIndicatorElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(IndicatorElement),
    IndicatorElementOptions,
    SquareIndicatorElementSize,
    SquareIndicatorElementDraw
};

static Ttk_ElementSpec RadiobuttonIndicatorElementSpec = {
static const Ttk_ElementSpec RadiobuttonIndicatorElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(IndicatorElement),
    IndicatorElementOptions,
    DiamondIndicatorElementSize,
    DiamondIndicatorElementDraw
};

635
636
637
638
639
640
641
642

643
644

645
646

647
648

649
650

651
652

653
654
655


656
657
658
659

660
661
662

663



664
665
666
667
668
669
670
671
672

673
674
675

676
677
678


679
680
681
682
683
684
685
686
687

688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711

712
713

714
715

716
717

718
719

720
721
722


723
724
725

726
727
728
729
730
731
732


733

734
735
736
737
738
739
740
741
742
743
744
745
746
747


748
749
750
751

752
753
754
755
756


757
758
759

760
761
762

763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782

783
784

785
786

787
788
789


790
791
792
793

794
795
796

797



798
799
800
801
802
803
804

805
806
807

808
809


810
811
812
813
814
815
816
817
818
819

820
821
822
823
824
825
826
697
698
699
700
701
702
703

704
705

706
707

708
709

710
711

712
713

714
715


716
717
718
719
720

721
722
723

724
725
726
727
728
729
730
731
732
733
734
735
736

737
738
739

740
741
742
743
744
745
746
747
748
749
750
751
752
753

754
755
756
757
758
759
760
761
762
763
764
765
766
767
768

769
770
771
772
773
774
775
776

777
778

779
780

781
782

783
784

785
786


787
788
789
790

791
792
793
794
795
796


797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812


813
814
815
816
817
818
819
820
821
822


823
824
825
826

827
828
829

830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849

850
851

852
853

854
855


856
857
858
859
860

861
862
863

864
865
866
867
868
869
870
871
872
873
874

875
876
877

878
879
880
881
882
883
884
885
886
887
888
889
890
891

892
893
894
895
896
897
898
899







-
+

-
+

-
+

-
+

-
+

-
+

-
-
+
+



-
+


-
+

+
+
+








-
+


-
+



+
+








-
+














-








-
+

-
+

-
+

-
+

-
+

-
-
+
+


-
+





-
-
+
+

+












-
-
+
+




+



-
-
+
+


-
+


-
+



















-
+

-
+

-
+

-
-
+
+



-
+


-
+

+
+
+






-
+


-
+


+
+









-
+







    Tcl_Obj *widthObj;
    Tcl_Obj *heightObj;
    Tcl_Obj *borderWidthObj;
    Tcl_Obj *reliefObj;
    Tcl_Obj *marginObj;
} MenuIndicatorElement;

static Ttk_ElementOptionSpec MenuIndicatorElementOptions[] = {
static const Ttk_ElementOptionSpec MenuIndicatorElementOptions[] = {
    { "-background", TK_OPTION_BORDER,
	Tk_Offset(MenuIndicatorElement,backgroundObj), DEFAULT_BACKGROUND },
	offsetof(MenuIndicatorElement,backgroundObj), DEFAULT_BACKGROUND },
    { "-indicatorwidth", TK_OPTION_PIXELS,
	Tk_Offset(MenuIndicatorElement,widthObj), "4.0m" },
	offsetof(MenuIndicatorElement,widthObj), "4.0m" },
    { "-indicatorheight", TK_OPTION_PIXELS,
	Tk_Offset(MenuIndicatorElement,heightObj), "1.7m" },
	offsetof(MenuIndicatorElement,heightObj), "1.7m" },
    { "-borderwidth", TK_OPTION_PIXELS,
	Tk_Offset(MenuIndicatorElement,borderWidthObj), DEFAULT_BORDERWIDTH },
	offsetof(MenuIndicatorElement,borderWidthObj), DEFAULT_BORDERWIDTH },
    { "-indicatorrelief", TK_OPTION_RELIEF,
	Tk_Offset(MenuIndicatorElement,reliefObj),"raised" },
	offsetof(MenuIndicatorElement,reliefObj),"raised" },
    { "-indicatormargin", TK_OPTION_STRING,
	    Tk_Offset(MenuIndicatorElement,marginObj), "5 0" },
    { NULL, 0, 0, NULL }
	    offsetof(MenuIndicatorElement,marginObj), "5 0" },
    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
};

static void MenuIndicatorElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    MenuIndicatorElement *mi = elementRecord;
    MenuIndicatorElement *mi = (MenuIndicatorElement *)elementRecord;
    Ttk_Padding margins;
    (void)dummy;
    (void)paddingPtr;

    Tk_GetPixelsFromObj(NULL, tkwin, mi->widthObj, widthPtr);
    Tk_GetPixelsFromObj(NULL, tkwin, mi->heightObj, heightPtr);
    Ttk_GetPaddingFromObj(NULL,tkwin,mi->marginObj, &margins);
    *widthPtr += Ttk_PaddingWidth(margins);
    *heightPtr += Ttk_PaddingHeight(margins);
}

static void MenuIndicatorElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    MenuIndicatorElement *mi = elementRecord;
    MenuIndicatorElement *mi = (MenuIndicatorElement *)elementRecord;
    Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, mi->backgroundObj);
    Ttk_Padding margins;
    int borderWidth = 2;
    (void)dummy;
    (void)state;

    Ttk_GetPaddingFromObj(NULL,tkwin,mi->marginObj,&margins);
    b = Ttk_PadBox(b, margins);
    Tk_GetPixelsFromObj(NULL, tkwin, mi->borderWidthObj, &borderWidth);
    Tk_Fill3DRectangle(tkwin, d, border, b.x, b.y, b.width, b.height,
	    borderWidth, TK_RELIEF_RAISED);
}

static Ttk_ElementSpec MenuIndicatorElementSpec = {
static const Ttk_ElementSpec MenuIndicatorElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(MenuIndicatorElement),
    MenuIndicatorElementOptions,
    MenuIndicatorElementSize,
    MenuIndicatorElementDraw
};

/*----------------------------------------------------------------------
 * +++ Arrow elements.
 *
 * 	Draws a solid triangle inside a box.
 * 	clientData is an enum ArrowDirection pointer.
 */

static int ArrowElements[] = { ARROW_UP, ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT };
typedef struct {
    Tcl_Obj *borderObj;
    Tcl_Obj *borderWidthObj;
    Tcl_Obj *reliefObj;
    Tcl_Obj *sizeObj;
    Tcl_Obj *colorObj;
} ArrowElement;

static Ttk_ElementOptionSpec ArrowElementOptions[] = {
static const Ttk_ElementOptionSpec ArrowElementOptions[] = {
    { "-background", TK_OPTION_BORDER,
	Tk_Offset(ArrowElement,borderObj), DEFAULT_BACKGROUND },
	offsetof(ArrowElement,borderObj), DEFAULT_BACKGROUND },
    { "-relief",TK_OPTION_RELIEF,
	Tk_Offset(ArrowElement,reliefObj),"raised"},
	offsetof(ArrowElement,reliefObj),"raised"},
    { "-borderwidth", TK_OPTION_PIXELS,
	Tk_Offset(ArrowElement,borderWidthObj), "1" },
	offsetof(ArrowElement,borderWidthObj), "1" },
    { "-arrowcolor",TK_OPTION_COLOR,
	Tk_Offset(ArrowElement,colorObj),"black"},
	offsetof(ArrowElement,colorObj),"black"},
    { "-arrowsize", TK_OPTION_PIXELS,
	Tk_Offset(ArrowElement,sizeObj), "14" },
    { NULL, 0, 0, NULL }
	offsetof(ArrowElement,sizeObj), "14" },
    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
};

static Ttk_Padding ArrowMargins = { 3,3,3,3 };
static const Ttk_Padding ArrowMargins = { 3,3,3,3 };

static void ArrowElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    ArrowElement *arrow = elementRecord;
    int direction = *(int *)clientData;
    ArrowElement *arrow = (ArrowElement *)elementRecord;
    ArrowDirection direction = (ArrowDirection)PTR2INT(clientData);
    int width = 14;
    (void)paddingPtr;

    Tk_GetPixelsFromObj(NULL, tkwin, arrow->sizeObj, &width);
    width -= Ttk_PaddingWidth(ArrowMargins);
    TtkArrowSize(width/2, direction, widthPtr, heightPtr);
    *widthPtr += Ttk_PaddingWidth(ArrowMargins);
    *heightPtr += Ttk_PaddingWidth(ArrowMargins);
}

static void ArrowElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    int direction = *(int *)clientData;
    ArrowElement *arrow = elementRecord;
    ArrowDirection direction = (ArrowDirection)PTR2INT(clientData);
    ArrowElement *arrow = (ArrowElement *)elementRecord;
    Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, arrow->borderObj);
    XColor *arrowColor = Tk_GetColorFromObj(tkwin, arrow->colorObj);
    int relief = TK_RELIEF_RAISED;
    int borderWidth = 1;
    (void)state;

    Tk_GetReliefFromObj(NULL, arrow->reliefObj, &relief);

    Tk_Fill3DRectangle(
	tkwin, d, border, b.x, b.y, b.width, b.height, borderWidth, relief);
    Tk_Fill3DRectangle( tkwin, d, border, b.x, b.y, b.width, b.height,
	    borderWidth, relief);

    TtkFillArrow(Tk_Display(tkwin), d, Tk_GCForColor(arrowColor, d),
	Ttk_PadBox(b, ArrowMargins), direction);
	    Ttk_PadBox(b, ArrowMargins), direction);
}

static Ttk_ElementSpec ArrowElementSpec = {
static const Ttk_ElementSpec ArrowElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(ArrowElement),
    ArrowElementOptions,
    ArrowElementSize,
    ArrowElementDraw
};

/*----------------------------------------------------------------------
 * +++ Trough element.
 *
 * Used in scrollbars and scales in place of "border".
 */

typedef struct {
    Tcl_Obj *colorObj;
    Tcl_Obj *borderWidthObj;
    Tcl_Obj *reliefObj;
} TroughElement;

static Ttk_ElementOptionSpec TroughElementOptions[] = {
static const Ttk_ElementOptionSpec TroughElementOptions[] = {
    { "-borderwidth", TK_OPTION_PIXELS,
	Tk_Offset(TroughElement,borderWidthObj), DEFAULT_BORDERWIDTH },
	offsetof(TroughElement,borderWidthObj), DEFAULT_BORDERWIDTH },
    { "-troughcolor", TK_OPTION_BORDER,
	Tk_Offset(TroughElement,colorObj), DEFAULT_BACKGROUND },
	offsetof(TroughElement,colorObj), DEFAULT_BACKGROUND },
    { "-troughrelief",TK_OPTION_RELIEF,
	Tk_Offset(TroughElement,reliefObj), "sunken" },
    { NULL, 0, 0, NULL }
	offsetof(TroughElement,reliefObj), "sunken" },
    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
};

static void TroughElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    TroughElement *troughPtr = elementRecord;
    TroughElement *troughPtr = (TroughElement *)elementRecord;
    int borderWidth = 2;
    (void)dummy;
    (void)widthPtr;
    (void)heightPtr;

    Tk_GetPixelsFromObj(NULL, tkwin, troughPtr->borderWidthObj, &borderWidth);
    *paddingPtr = Ttk_UniformPadding((short)borderWidth);
}

static void TroughElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    TroughElement *troughPtr = elementRecord;
    TroughElement *troughPtr = (TroughElement *)elementRecord;
    Tk_3DBorder border = NULL;
    int borderWidth = 2, relief = TK_RELIEF_SUNKEN;
    (void)dummy;
    (void)state;

    border = Tk_Get3DBorderFromObj(tkwin, troughPtr->colorObj);
    Tk_GetReliefFromObj(NULL, troughPtr->reliefObj, &relief);
    Tk_GetPixelsFromObj(NULL, tkwin, troughPtr->borderWidthObj, &borderWidth);

    Tk_Fill3DRectangle(tkwin, d, border, b.x, b.y, b.width, b.height,
	    borderWidth, relief);
}

static Ttk_ElementSpec TroughElementSpec = {
static const Ttk_ElementSpec TroughElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(TroughElement),
    TroughElementOptions,
    TroughElementSize,
    TroughElementDraw
};

835
836
837
838
839
840
841
842

843
844

845
846

847
848

849
850

851
852
853


854
855
856
857

858
859
860
861





862
863
864

865
866
867
868
869
870
871
872
873
874
875
876

877
878
879

880
881


882
883
884
885
886
887
888
889

890
891
892
893
894
895
896
908
909
910
911
912
913
914

915
916

917
918

919
920

921
922

923
924


925
926
927
928
929

930
931
932


933
934
935
936
937
938
939

940
941
942
943
944
945
946
947
948
949
950
951

952
953
954

955
956
957
958
959
960
961
962
963
964
965
966

967
968
969
970
971
972
973
974







-
+

-
+

-
+

-
+

-
+

-
-
+
+



-
+


-
-
+
+
+
+
+


-
+











-
+


-
+


+
+







-
+







    Tcl_Obj *orientObj;
    Tcl_Obj *thicknessObj;
    Tcl_Obj *reliefObj;
    Tcl_Obj *borderObj;
    Tcl_Obj *borderWidthObj;
} ThumbElement;

static Ttk_ElementOptionSpec ThumbElementOptions[] = {
static const Ttk_ElementOptionSpec ThumbElementOptions[] = {
    { "-orient", TK_OPTION_ANY,
	Tk_Offset(ThumbElement, orientObj), "horizontal" },
	offsetof(ThumbElement, orientObj), "horizontal" },
    { "-width", TK_OPTION_PIXELS,
	Tk_Offset(ThumbElement,thicknessObj), DEFAULT_ARROW_SIZE },
	offsetof(ThumbElement,thicknessObj), DEFAULT_ARROW_SIZE },
    { "-relief", TK_OPTION_RELIEF,
	Tk_Offset(ThumbElement,reliefObj), "raised" },
	offsetof(ThumbElement,reliefObj), "raised" },
    { "-background", TK_OPTION_BORDER,
	Tk_Offset(ThumbElement,borderObj), DEFAULT_BACKGROUND },
	offsetof(ThumbElement,borderObj), DEFAULT_BACKGROUND },
    { "-borderwidth", TK_OPTION_PIXELS,
	Tk_Offset(ThumbElement,borderWidthObj), DEFAULT_BORDERWIDTH },
    { NULL, 0, 0, NULL }
	offsetof(ThumbElement,borderWidthObj), DEFAULT_BORDERWIDTH },
    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
};

static void ThumbElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    ThumbElement *thumb = elementRecord;
    int orient, thickness;
    ThumbElement *thumb = (ThumbElement *)elementRecord;
    Ttk_Orient orient;
    int thickness;
    (void)dummy;
    (void)paddingPtr;

    Tk_GetPixelsFromObj(NULL, tkwin, thumb->thicknessObj, &thickness);
    Ttk_GetOrientFromObj(NULL, thumb->orientObj, &orient);
    TtkGetOrientFromObj(NULL, thumb->orientObj, &orient);

    if (orient == TTK_ORIENT_VERTICAL) {
	*widthPtr = thickness;
	*heightPtr = MIN_THUMB_SIZE;
    } else {
	*widthPtr = MIN_THUMB_SIZE;
	*heightPtr = thickness;
    }
}

static void ThumbElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    ThumbElement *thumb = elementRecord;
    ThumbElement *thumb = (ThumbElement *)elementRecord;
    Tk_3DBorder  border = Tk_Get3DBorderFromObj(tkwin, thumb->borderObj);
    int borderWidth = 2, relief = TK_RELIEF_RAISED;
    (void)dummy;
    (void)state;

    Tk_GetPixelsFromObj(NULL, tkwin, thumb->borderWidthObj, &borderWidth);
    Tk_GetReliefFromObj(NULL, thumb->reliefObj, &relief);
    Tk_Fill3DRectangle(tkwin, d, border, b.x, b.y, b.width, b.height,
	    borderWidth, relief);
}

static Ttk_ElementSpec ThumbElementSpec = {
static const Ttk_ElementSpec ThumbElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(ThumbElement),
    ThumbElementOptions,
    ThumbElementSize,
    ThumbElementDraw
};

906
907
908
909
910
911
912
913
914


915
916

917
918

919
920

921
922

923
924

925
926

927
928
929
930

931
932
933
934





935
936

937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954

955
956
957

958
959




960
961
962

963
964
965
966
967
968
969
984
985
986
987
988
989
990


991
992
993

994
995

996
997

998
999

1000
1001

1002
1003

1004
1005
1006
1007

1008
1009
1010


1011
1012
1013
1014
1015
1016

1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034

1035
1036
1037

1038
1039

1040
1041
1042
1043
1044
1045

1046
1047
1048
1049
1050
1051
1052
1053







-
-
+
+

-
+

-
+

-
+

-
+

-
+

-
+



-
+


-
-
+
+
+
+
+

-
+

















-
+


-
+

-
+
+
+
+


-
+







    Tcl_Obj *lengthObj;      /* slider length */
    Tcl_Obj *thicknessObj;   /* slider thickness */
    Tcl_Obj *reliefObj;      /* the relief for this object */
    Tcl_Obj *borderObj;      /* the background color */
    Tcl_Obj *borderWidthObj; /* the size of the border */
} SliderElement;

static Ttk_ElementOptionSpec SliderElementOptions[] = {
    { "-sliderlength", TK_OPTION_PIXELS, Tk_Offset(SliderElement,lengthObj),
static const Ttk_ElementOptionSpec SliderElementOptions[] = {
    { "-sliderlength", TK_OPTION_PIXELS, offsetof(SliderElement,lengthObj),
	"30" },
    { "-sliderthickness",TK_OPTION_PIXELS,Tk_Offset(SliderElement,thicknessObj),
    { "-sliderthickness",TK_OPTION_PIXELS, offsetof(SliderElement,thicknessObj),
	"15" },
    { "-sliderrelief", TK_OPTION_RELIEF, Tk_Offset(SliderElement,reliefObj),
    { "-sliderrelief", TK_OPTION_RELIEF, offsetof(SliderElement,reliefObj),
	"raised" },
    { "-borderwidth", TK_OPTION_PIXELS, Tk_Offset(SliderElement,borderWidthObj),
    { "-borderwidth", TK_OPTION_PIXELS, offsetof(SliderElement,borderWidthObj),
	DEFAULT_BORDERWIDTH },
    { "-background", TK_OPTION_BORDER, Tk_Offset(SliderElement,borderObj),
    { "-background", TK_OPTION_BORDER, offsetof(SliderElement,borderObj),
	DEFAULT_BACKGROUND },
    { "-orient", TK_OPTION_ANY, Tk_Offset(SliderElement,orientObj),
    { "-orient", TK_OPTION_ANY, offsetof(SliderElement,orientObj),
	"horizontal" },
    { NULL, 0, 0, NULL }
    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
};

static void SliderElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    SliderElement *slider = elementRecord;
    int orient, length, thickness;
    SliderElement *slider = (SliderElement *)elementRecord;
    Ttk_Orient orient;
    int length, thickness;
    (void)dummy;
    (void)paddingPtr;

    Ttk_GetOrientFromObj(NULL, slider->orientObj, &orient);
    TtkGetOrientFromObj(NULL, slider->orientObj, &orient);
    Tk_GetPixelsFromObj(NULL, tkwin, slider->lengthObj, &length);
    Tk_GetPixelsFromObj(NULL, tkwin, slider->thicknessObj, &thickness);

    switch (orient) {
	case TTK_ORIENT_VERTICAL:
	    *widthPtr = thickness;
	    *heightPtr = length;
	    break;

	case TTK_ORIENT_HORIZONTAL:
	    *widthPtr = length;
	    *heightPtr = thickness;
	    break;
    }
}

static void SliderElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    SliderElement *slider = elementRecord;
    SliderElement *slider = (SliderElement *)elementRecord;
    Tk_3DBorder border = NULL;
    int relief = TK_RELIEF_RAISED, borderWidth = 2, orient;
    int relief = TK_RELIEF_RAISED, borderWidth = 2;
    Ttk_Orient orient;
    (void)dummy;
    (void)state;

    border = Tk_Get3DBorderFromObj(tkwin, slider->borderObj);
    Ttk_GetOrientFromObj(NULL, slider->orientObj, &orient);
    TtkGetOrientFromObj(NULL, slider->orientObj, &orient);
    Tk_GetPixelsFromObj(NULL, tkwin, slider->borderWidthObj, &borderWidth);
    Tk_GetReliefFromObj(NULL, slider->reliefObj, &relief);

    Tk_Fill3DRectangle(tkwin, d, border,
	b.x, b.y, b.width, b.height,
	borderWidth, relief);

988
989
990
991
992
993
994
995

996
997
998
999
1000
1001
1002
1072
1073
1074
1075
1076
1077
1078

1079
1080
1081
1082
1083
1084
1085
1086







-
+







		    Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC),
		    b.x+borderWidth, b.y, b.x+b.width-borderWidth, b.y);
	    }
	}
    }
}

static Ttk_ElementSpec SliderElementSpec = {
static const Ttk_ElementSpec SliderElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(SliderElement),
    SliderElementOptions,
    SliderElementSize,
    SliderElementDraw
};

1017
1018
1019
1020
1021
1022
1023
1024
1025


1026
1027

1028
1029

1030
1031

1032
1033

1034
1035

1036
1037

1038
1039
1040
1041

1042
1043
1044
1045





1046
1047

1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065

1066
1067
1068

1069
1070


1071
1072
1073
1074
1075
1076
1077
1078
1079
1080

1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097

1098
1099

1100
1101
1102


1103
1104
1105
1106

1107
1108
1109

1110




1111
1112
1113
1114
1115
1116
1117

1118
1119
1120

1121
1122
1123
1124
1125

1126
1127
1128
1129
1130
1131
1132
1101
1102
1103
1104
1105
1106
1107


1108
1109
1110

1111
1112

1113
1114

1115
1116

1117
1118

1119
1120

1121
1122
1123
1124

1125
1126
1127


1128
1129
1130
1131
1132
1133

1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151

1152
1153
1154

1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168

1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185

1186
1187

1188
1189


1190
1191
1192
1193
1194

1195
1196
1197

1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209

1210
1211
1212

1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226







-
-
+
+

-
+

-
+

-
+

-
+

-
+

-
+



-
+


-
-
+
+
+
+
+

-
+

















-
+


-
+


+
+









-
+
















-
+

-
+

-
-
+
+



-
+


-
+

+
+
+
+






-
+


-
+





+







    Tcl_Obj *thicknessObj;	/* the height/width of the bar */
    Tcl_Obj *lengthObj;		/* default width/height of the bar */
    Tcl_Obj *reliefObj; 	/* border relief for this object */
    Tcl_Obj *borderObj; 	/* background color */
    Tcl_Obj *borderWidthObj; 	/* thickness of the border */
} PbarElement;

static Ttk_ElementOptionSpec PbarElementOptions[] = {
    { "-orient", TK_OPTION_ANY, Tk_Offset(PbarElement,orientObj),
static const Ttk_ElementOptionSpec PbarElementOptions[] = {
    { "-orient", TK_OPTION_ANY, offsetof(PbarElement,orientObj),
	"horizontal" },
    { "-thickness", TK_OPTION_PIXELS, Tk_Offset(PbarElement,thicknessObj),
    { "-thickness", TK_OPTION_PIXELS, offsetof(PbarElement,thicknessObj),
	DEFAULT_PBAR_THICKNESS },
    { "-barsize", TK_OPTION_PIXELS, Tk_Offset(PbarElement,lengthObj),
    { "-barsize", TK_OPTION_PIXELS, offsetof(PbarElement,lengthObj),
	DEFAULT_PBAR_LENGTH },
    { "-pbarrelief", TK_OPTION_RELIEF, Tk_Offset(PbarElement,reliefObj),
    { "-pbarrelief", TK_OPTION_RELIEF, offsetof(PbarElement,reliefObj),
	"raised" },
    { "-borderwidth", TK_OPTION_PIXELS, Tk_Offset(PbarElement,borderWidthObj),
    { "-borderwidth", TK_OPTION_PIXELS, offsetof(PbarElement,borderWidthObj),
	DEFAULT_BORDERWIDTH },
    { "-background", TK_OPTION_BORDER, Tk_Offset(PbarElement,borderObj),
    { "-background", TK_OPTION_BORDER, offsetof(PbarElement,borderObj),
	DEFAULT_BACKGROUND },
    { NULL, 0, 0, NULL }
    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
};

static void PbarElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    PbarElement *pbar = elementRecord;
    int orient, thickness = 15, length = 30, borderWidth = 2;
    PbarElement *pbar = (PbarElement *)elementRecord;
    Ttk_Orient orient;
    int thickness = 15, length = 30, borderWidth = 2;
    (void)dummy;
    (void)paddingPtr;

    Ttk_GetOrientFromObj(NULL, pbar->orientObj, &orient);
    TtkGetOrientFromObj(NULL, pbar->orientObj, &orient);
    Tk_GetPixelsFromObj(NULL, tkwin, pbar->thicknessObj, &thickness);
    Tk_GetPixelsFromObj(NULL, tkwin, pbar->lengthObj, &length);
    Tk_GetPixelsFromObj(NULL, tkwin, pbar->borderWidthObj, &borderWidth);

    switch (orient) {
	case TTK_ORIENT_HORIZONTAL:
	    *widthPtr	= length + 2 * borderWidth;
	    *heightPtr	= thickness + 2 * borderWidth;
	    break;
	case TTK_ORIENT_VERTICAL:
	    *widthPtr	= thickness + 2 * borderWidth;
	    *heightPtr	= length + 2 * borderWidth;
	    break;
    }
}

static void PbarElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, Ttk_State state)
{
    PbarElement *pbar = elementRecord;
    PbarElement *pbar = (PbarElement *)elementRecord;
    Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, pbar->borderObj);
    int relief = TK_RELIEF_RAISED, borderWidth = 2;
    (void)dummy;
    (void)state;

    Tk_GetPixelsFromObj(NULL, tkwin, pbar->borderWidthObj, &borderWidth);
    Tk_GetReliefFromObj(NULL, pbar->reliefObj, &relief);

    Tk_Fill3DRectangle(tkwin, d, border,
	b.x, b.y, b.width, b.height,
	borderWidth, relief);
}

static Ttk_ElementSpec PbarElementSpec = {
static const Ttk_ElementSpec PbarElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(PbarElement),
    PbarElementOptions,
    PbarElementSize,
    PbarElementDraw
};

/*------------------------------------------------------------------------
 * +++ Notebook tabs and client area.
 */

typedef struct {
    Tcl_Obj *borderWidthObj;
    Tcl_Obj *backgroundObj;
} TabElement;

static Ttk_ElementOptionSpec TabElementOptions[] = {
static const Ttk_ElementOptionSpec TabElementOptions[] = {
    { "-borderwidth", TK_OPTION_PIXELS,
	Tk_Offset(TabElement,borderWidthObj),"1" },
	offsetof(TabElement,borderWidthObj),"1" },
    { "-background", TK_OPTION_BORDER,
	Tk_Offset(TabElement,backgroundObj), DEFAULT_BACKGROUND },
    {0,0,0,0}
	offsetof(TabElement,backgroundObj), DEFAULT_BACKGROUND },
    {0,TK_OPTION_BOOLEAN,0,0}
};

static void TabElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    TabElement *tab = elementRecord;
    TabElement *tab = (TabElement *)elementRecord;
    int borderWidth = 1;
    (void)dummy;
    (void)widthPtr;
    (void)heightPtr;

    Tk_GetPixelsFromObj(0, tkwin, tab->borderWidthObj, &borderWidth);
    paddingPtr->top = paddingPtr->left = paddingPtr->right = borderWidth;
    paddingPtr->bottom = 0;
}

static void TabElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    TabElement *tab = elementRecord;
    TabElement *tab = (TabElement *)elementRecord;
    Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, tab->backgroundObj);
    int borderWidth = 1;
    int cut = 2;
    XPoint pts[6];
    int n = 0;
    (void)dummy;

    Tcl_GetIntFromObj(NULL, tab->borderWidthObj, &borderWidth);

    if (state & TTK_STATE_SELECTED) {
	/*
	 * Draw slightly outside of the allocated parcel,
	 * to overwrite the client area border.
1161
1162
1163
1164
1165
1166
1167
1168

1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184

1185
1186
1187

1188
1189


1190
1191
1192
1193
1194
1195
1196
1197
1198

1199
1200
1201

1202




1203
1204
1205
1206
1207

1208
1209
1210
1211
1212
1213
1214
1255
1256
1257
1258
1259
1260
1261

1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277

1278
1279
1280

1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293

1294
1295
1296

1297
1298
1299
1300
1301
1302
1303
1304
1305
1306

1307
1308
1309
1310
1311
1312
1313
1314







-
+















-
+


-
+


+
+








-
+


-
+

+
+
+
+




-
+







		pts+3, 3, CoordModeOrigin);
	++pts[0].x; ++pts[1].x; ++pts[2].x;             --pts[4].x; --pts[5].x;
	                        ++pts[2].y; ++pts[3].y;
    }

}

static Ttk_ElementSpec TabElementSpec = {
static const Ttk_ElementSpec TabElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(TabElement),
    TabElementOptions,
    TabElementSize,
    TabElementDraw
};

/*
 * Client area element:
 * Uses same resources as tab element.
 */
typedef TabElement ClientElement;
#define ClientElementOptions TabElementOptions

static void ClientElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    ClientElement *ce = elementRecord;
    ClientElement *ce = (ClientElement *)elementRecord;
    Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, ce->backgroundObj);
    int borderWidth = 1;
    (void)dummy;
    (void)state;

    Tcl_GetIntFromObj(NULL, ce->borderWidthObj, &borderWidth);

    Tk_Fill3DRectangle(tkwin, d, border,
	b.x, b.y, b.width, b.height, borderWidth,TK_RELIEF_RAISED);
}

static void ClientElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    ClientElement *ce = elementRecord;
    ClientElement *ce = (ClientElement *)elementRecord;
    int borderWidth = 1;
    (void)dummy;
    (void)widthPtr;
    (void)heightPtr;

    Tk_GetPixelsFromObj(0, tkwin, ce->borderWidthObj, &borderWidth);
    *paddingPtr = Ttk_UniformPadding((short)borderWidth);
}

static Ttk_ElementSpec ClientElementSpec = {
static const Ttk_ElementSpec ClientElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(ClientElement),
    ClientElementOptions,
    ClientElementSize,
    ClientElementDraw
};

1241
1242
1243
1244
1245
1246
1247
1248

1249
1250

1251
1252

1253
1254

1255
1256

1257
1258
1259
1260
1261
1262
1263
1341
1342
1343
1344
1345
1346
1347

1348
1349

1350
1351

1352
1353

1354
1355

1356
1357
1358
1359
1360
1361
1362
1363







-
+

-
+

-
+

-
+

-
+







	    &RadiobuttonIndicatorElementSpec, NULL);
    Ttk_RegisterElement(interp, theme, "Menubutton.indicator",
	    &MenuIndicatorElementSpec, NULL);

    Ttk_RegisterElement(interp, theme, "indicator", &ttkNullElementSpec,NULL);

    Ttk_RegisterElement(interp, theme, "uparrow",
	    &ArrowElementSpec, &ArrowElements[0]);
	    &ArrowElementSpec, INT2PTR(ARROW_UP));
    Ttk_RegisterElement(interp, theme, "downarrow",
	    &ArrowElementSpec, &ArrowElements[1]);
	    &ArrowElementSpec, INT2PTR(ARROW_DOWN));
    Ttk_RegisterElement(interp, theme, "leftarrow",
	    &ArrowElementSpec, &ArrowElements[2]);
	    &ArrowElementSpec, INT2PTR(ARROW_LEFT));
    Ttk_RegisterElement(interp, theme, "rightarrow",
	    &ArrowElementSpec, &ArrowElements[3]);
	    &ArrowElementSpec, INT2PTR(ARROW_RIGHT));
    Ttk_RegisterElement(interp, theme, "arrow",
	    &ArrowElementSpec, &ArrowElements[0]);
	    &ArrowElementSpec, INT2PTR(ARROW_UP));

    Ttk_RegisterElement(interp, theme, "trough", &TroughElementSpec, NULL);
    Ttk_RegisterElement(interp, theme, "thumb", &ThumbElementSpec, NULL);
    Ttk_RegisterElement(interp, theme, "slider", &SliderElementSpec, NULL);
    Ttk_RegisterElement(interp, theme, "pbar", &PbarElementSpec, NULL);

    Ttk_RegisterElement(interp, theme, "separator",
Changes to generic/ttk/ttkEntry.c.
1
2
3
4
5
6
7
8





9
10
11
12
13
14
15
1
2
3





4
5
6
7
8
9
10
11
12
13
14
15



-
-
-
-
-
+
+
+
+
+







/*
 * 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"

/*
65
66
67
68
69
70
71

72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87


88
89
90
91



92
93
94
95
96
97
98
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86


87
88
89



90
91
92
93
94
95
96
97
98
99







+














-
-
+
+

-
-
-
+
+
+







 * displayString points to string if showChar == NULL,
 * or to malloc'ed storage if showChar != NULL.
 */

/* Style parameters:
 */
typedef struct {
    Tcl_Obj *placeholderForegroundObj;/* Foreground color for placeholder text */
    Tcl_Obj *foregroundObj;	/* Foreground color for normal text */
    Tcl_Obj *backgroundObj;	/* Entry widget background color */
    Tcl_Obj *selBorderObj;	/* Border and background for selection */
    Tcl_Obj *selBorderWidthObj;	/* Width of selection border */
    Tcl_Obj *selForegroundObj;	/* Foreground color for selected text */
    Tcl_Obj *insertColorObj;	/* Color of insertion cursor */
    Tcl_Obj *insertWidthObj;	/* Insert cursor width */
} EntryStyleData;

typedef struct {
    /*
     * Internal state:
     */
    char *string;		/* Storage for string (malloced) */
    int numBytes;		/* Length of string in bytes. */
    int numChars;		/* Length of string in characters. */
    TkSizeT numBytes;		/* Length of string in bytes. */
    TkSizeT numChars;		/* Length of string in characters. */

    int insertPos;		/* Insert index */
    int selectFirst;		/* Index of start of selection, or -1 */
    int selectLast;		/* Index of end of selection, or -1 */
    TkSizeT insertPos;		/* Insert index */
    TkSizeT selectFirst;		/* Index of start of selection, or TCL_INDEX_NONE */
    TkSizeT selectLast;		/* Index of end of selection, or TCL_INDEX_NONE */

    Scrollable xscroll;		/* Current scroll position */
    ScrollHandle xscrollHandle;

    /*
     * Options managed by Tk_SetOptions:
     */
109
110
111
112
113
114
115


116
117
118
119
120
121
122
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125







+
+







    Tcl_Obj *widthObj;		/* Desired width of window (in avgchars) */
    Tk_Justify justify;		/* Text justification */

    EntryStyleData styleData;	/* Display style data (widget options) */
    EntryStyleData styleDefaults;/* Style defaults (fallback values) */

    Tcl_Obj *stateObj;		/* Compatibility option -- see CheckStateObj */

    Tcl_Obj *placeholderObj;	/* Text to display for placeholder text */

    /*
     * Derived resources:
     */
    Ttk_TraceHandle *textVariableTrace;

    char *displayString;	/* String to use when displaying */
139
140
141
142
143
144
145
146
147
148
149
150
151







152
153

154
155

156
157
158

159
160
161

162
163
164

165



166
167

168
169
170

171
172
173

174
175
176
177


178
179

180
181
182

183
184
185

186
187
188
189



190
191

192
193
194



195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214

215
216
217
218
219
220
221
222
223
224
225

226
227
228
229
230
231
232
142
143
144
145
146
147
148






149
150
151
152
153
154
155
156

157
158

159
160
161

162
163
164

165
166
167

168
169
170
171
172
173

174
175
176

177
178
179

180
181
182


183
184
185

186
187
188

189
190
191

192
193
194
195
196
197
198
199
200

201
202


203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245







-
-
-
-
-
-
+
+
+
+
+
+
+

-
+

-
+


-
+


-
+


-
+

+
+
+

-
+


-
+


-
+


-
-
+
+

-
+


-
+


-
+




+
+
+

-
+

-
-
+
+
+




















+











+







#define STATE_CHANGED	 	(0x100)	/* -state option changed */
#define TEXTVAR_CHANGED	 	(0x200)	/* -textvariable option changed */
#define SCROLLCMD_CHANGED	(0x400)	/* -xscrollcommand option changed */

/*
 * Default option values:
 */
#define DEF_SELECT_BG	"#000000"
#define DEF_SELECT_FG	"#ffffff"
#define DEF_INSERT_BG	"black"
#define DEF_ENTRY_WIDTH	"20"
#define DEF_ENTRY_FONT	"TkTextFont"
#define DEF_LIST_HEIGHT	"10"
#define DEF_SELECT_BG		"#000000"
#define DEF_SELECT_FG		"#ffffff"
#define DEF_PLACEHOLDER_FG	"#b3b3b3"
#define DEF_INSERT_BG		"black"
#define DEF_ENTRY_WIDTH		"20"
#define DEF_ENTRY_FONT		"TkTextFont"
#define DEF_LIST_HEIGHT		"10"

static Tk_OptionSpec EntryOptionSpecs[] = {
static const Tk_OptionSpec EntryOptionSpecs[] = {
    {TK_OPTION_BOOLEAN, "-exportselection", "exportSelection",
        "ExportSelection", "1", -1, Tk_Offset(Entry, entry.exportSelection),
        "ExportSelection", "1", TCL_INDEX_NONE, offsetof(Entry, entry.exportSelection),
	0,0,0 },
    {TK_OPTION_FONT, "-font", "font", "Font",
	DEF_ENTRY_FONT, Tk_Offset(Entry, entry.fontObj),-1,
	DEF_ENTRY_FONT, offsetof(Entry, entry.fontObj),TCL_INDEX_NONE,
	0,0,GEOMETRY_CHANGED},
    {TK_OPTION_STRING, "-invalidcommand", "invalidCommand", "InvalidCommand",
	NULL, -1, Tk_Offset(Entry, entry.invalidCmd),
	NULL, TCL_INDEX_NONE, offsetof(Entry, entry.invalidCmd),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",
	"left", -1, Tk_Offset(Entry, entry.justify),
	"left", TCL_INDEX_NONE, offsetof(Entry, entry.justify),
	0, 0, GEOMETRY_CHANGED},
    {TK_OPTION_STRING, "-placeholder", "placeHolder", "PlaceHolder",
	NULL, offsetof(Entry, entry.placeholderObj), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_STRING, "-show", "show", "Show",
        NULL, -1, Tk_Offset(Entry, entry.showChar),
        NULL, TCL_INDEX_NONE, offsetof(Entry, entry.showChar),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_STRING, "-state", "state", "State",
	"normal", Tk_Offset(Entry, entry.stateObj), -1,
	"normal", offsetof(Entry, entry.stateObj), TCL_INDEX_NONE,
        0,0,STATE_CHANGED},
    {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable",
	NULL, Tk_Offset(Entry, entry.textVariableObj), -1,
	NULL, offsetof(Entry, entry.textVariableObj), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK,0,TEXTVAR_CHANGED},
    {TK_OPTION_STRING_TABLE, "-validate", "validate", "Validate",
	"none", -1, Tk_Offset(Entry, entry.validate),
	0, (ClientData) validateStrings, 0},
	"none", TCL_INDEX_NONE, offsetof(Entry, entry.validate),
	0, (void *) validateStrings, 0},
    {TK_OPTION_STRING, "-validatecommand", "validateCommand", "ValidateCommand",
	NULL, -1, Tk_Offset(Entry, entry.validateCmd),
	NULL, TCL_INDEX_NONE, offsetof(Entry, entry.validateCmd),
	TK_OPTION_NULL_OK, 0, 0},
    {TK_OPTION_INT, "-width", "width", "Width",
	DEF_ENTRY_WIDTH, Tk_Offset(Entry, entry.widthObj), -1,
	DEF_ENTRY_WIDTH, offsetof(Entry, entry.widthObj), TCL_INDEX_NONE,
	0,0,GEOMETRY_CHANGED},
    {TK_OPTION_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand",
	NULL, -1, Tk_Offset(Entry, entry.xscroll.scrollCmd),
	NULL, TCL_INDEX_NONE, offsetof(Entry, entry.xscroll.scrollCmd),
	TK_OPTION_NULL_OK, 0, SCROLLCMD_CHANGED},

    /* EntryStyleData options:
     */
    {TK_OPTION_COLOR, "-background", "windowColor", "WindowColor",
	NULL, offsetof(Entry, entry.styleData.backgroundObj), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK,0,0},
    {TK_OPTION_COLOR, "-foreground", "textColor", "TextColor",
	NULL, Tk_Offset(Entry, entry.styleData.foregroundObj), -1,
	NULL, offsetof(Entry, entry.styleData.foregroundObj), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK,0,0},
    {TK_OPTION_COLOR, "-background", "windowColor", "WindowColor",
	NULL, Tk_Offset(Entry, entry.styleData.backgroundObj), -1,
    {TK_OPTION_COLOR, "-placeholderforeground", "placeholderForeground",
        "PlaceholderForeground", NULL,
        offsetof(Entry, entry.styleData.placeholderForegroundObj), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK,0,0},

    WIDGET_TAKEFOCUS_TRUE,
    WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs)
};

/*------------------------------------------------------------------------
 * +++ EntryStyleData management.
 * 	This is still more awkward than it should be;
 * 	it should be able to use the Element API instead.
 */

/* EntryInitStyleDefaults --
 * 	Initialize EntryStyleData record to fallback values.
 */
static void EntryInitStyleDefaults(EntryStyleData *es)
{
#define INIT(member, value) \
	es->member = Tcl_NewStringObj(value, -1); \
	Tcl_IncrRefCount(es->member);
    INIT(placeholderForegroundObj, DEF_PLACEHOLDER_FG)
    INIT(foregroundObj, DEFAULT_FOREGROUND)
    INIT(selBorderObj, DEF_SELECT_BG)
    INIT(selForegroundObj, DEF_SELECT_FG)
    INIT(insertColorObj, DEFAULT_FOREGROUND)
    INIT(selBorderWidthObj, "0")
    INIT(insertWidthObj, "1")
#undef INIT
}

static void EntryFreeStyleDefaults(EntryStyleData *es)
{
    Tcl_DecrRefCount(es->placeholderForegroundObj);
    Tcl_DecrRefCount(es->foregroundObj);
    Tcl_DecrRefCount(es->selBorderObj);
    Tcl_DecrRefCount(es->selForegroundObj);
    Tcl_DecrRefCount(es->insertColorObj);
    Tcl_DecrRefCount(es->selBorderWidthObj);
    Tcl_DecrRefCount(es->insertWidthObj);
}
245
246
247
248
249
250
251

252
253
254
255
256
257
258
259
260
261

262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282

283
284
285
286

287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302


303

304

305
306
307
308








309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327

328
329

330
331
332


333
334
335
336

337
338

339
340
341
342
343
344



345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364

365
366

367
368
369
370
371
372
373
374
375
376
377
378
379
380

381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398



399
400
401
402
403
404
405
406
407
408
409
410

411
412
413
414

415
416
417
418
419

420
421
422
423
424



425
426
427
428
429
430
431



432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450

451
452
453
454

455
456
457
458
459
460
461

462
463
464
465
466
467
468
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296

297
298
299
300

301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321

322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352

353
354

355
356


357
358
359
360
361

362
363

364
365
366
367
368
369
370
371
372
373
374
375
376
377
378



379
380
381
382
383
384
385
386
387
388
389

390
391

392
393
394
395
396
397
398
399
400
401
402
403
404
405

406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421



422
423
424
425
426
427
428
429
430
431
432
433
434
435

436
437
438
439

440
441
442
443
444

445
446
447



448
449
450
451
452
453
454



455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475

476
477
478
479

480
481
482
483
484
485
486

487
488
489
490
491
492
493
494







+










+




















-
+



-
+
















+
+

+
-
+




+
+
+
+
+
+
+
+


















-
+

-
+

-
-
+
+



-
+

-
+






+
+
+





-
-
-











-
+

-
+













-
+















-
-
-
+
+
+











-
+



-
+




-
+


-
-
-
+
+
+




-
-
-
+
+
+


















-
+



-
+






-
+







    /* Initialize to fallback values:
     */
    *es = entryPtr->entry.styleDefaults;

#   define INIT(member, name) \
    if ((tmp=Ttk_QueryOption(entryPtr->core.layout,name,state))) \
    	es->member=tmp;
    INIT(placeholderForegroundObj, "-placeholderforeground");
    INIT(foregroundObj, "-foreground");
    INIT(selBorderObj, "-selectbackground")
    INIT(selBorderWidthObj, "-selectborderwidth")
    INIT(selForegroundObj, "-selectforeground")
    INIT(insertColorObj, "-insertcolor")
    INIT(insertWidthObj, "-insertwidth")
#undef INIT

    /* Reacquire color & border resources from resource cache.
     */
    es->placeholderForegroundObj = Ttk_UseColor(cache, tkwin, es->placeholderForegroundObj);
    es->foregroundObj = Ttk_UseColor(cache, tkwin, es->foregroundObj);
    es->selForegroundObj = Ttk_UseColor(cache, tkwin, es->selForegroundObj);
    es->insertColorObj = Ttk_UseColor(cache, tkwin, es->insertColorObj);
    es->selBorderObj = Ttk_UseBorder(cache, tkwin, es->selBorderObj);
}

/*------------------------------------------------------------------------
 * +++ Resource management.
 */

/* EntryDisplayString --
 * 	Return a malloc'ed string consisting of 'numChars' copies
 * 	of (the first character in the string) 'showChar'.
 * 	Used to compute the displayString if -show is non-NULL.
 */
static char *EntryDisplayString(const char *showChar, int numChars)
{
    char *displayString, *p;
    int size;
    int ch;
    char buf[4];
    char buf[6];

    TkUtfToUniChar(showChar, &ch);
    size = TkUniCharToUtf(ch, buf);
    p = displayString = ckalloc(numChars * size + 1);
    p = displayString = (char *)ckalloc(numChars * size + 1);

    while (numChars--) {
	memcpy(p, buf, size);
	p += size;
    }
    *p = '\0';

    return displayString;
}

/* EntryUpdateTextLayout --
 * 	Recompute textLayout, layoutWidth, and layoutHeight
 * 	from displayString and fontObj.
 */
static void EntryUpdateTextLayout(Entry *entryPtr)
{
    TkSizeT length;
    char *text;
    Tk_FreeTextLayout(entryPtr->entry.textLayout);
    if ((entryPtr->entry.numChars != 0) || (entryPtr->entry.placeholderObj == NULL)) {
    entryPtr->entry.textLayout = Tk_ComputeTextLayout(
        entryPtr->entry.textLayout = Tk_ComputeTextLayout(
	    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);
        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);
    }
}

/* EntryEditable --
 * 	Returns 1 if the entry widget accepts user changes, 0 otherwise
 */
static int
EntryEditable(Entry *entryPtr)
{
    return !(entryPtr->core.state & (TTK_STATE_DISABLED|TTK_STATE_READONLY));
}

/*------------------------------------------------------------------------
 * +++ Selection management.
 */

/* EntryFetchSelection --
 *	Selection handler for entry widgets.
 */
static int
static TkSizeT
EntryFetchSelection(
    ClientData clientData, int offset, char *buffer, int maxBytes)
    ClientData clientData, TkSizeT offset, char *buffer, TkSizeT maxBytes)
{
    Entry *entryPtr = (Entry *) clientData;
    int byteCount;
    Entry *entryPtr = (Entry *)clientData;
    TkSizeT byteCount;
    const char *string;
    const char *selStart, *selEnd;

    if (entryPtr->entry.selectFirst < 0 || (!entryPtr->entry.exportSelection)
    if (entryPtr->entry.selectFirst == TCL_INDEX_NONE || (!entryPtr->entry.exportSelection)
	    || Tcl_IsSafe(entryPtr->core.interp)) {
	return -1;
	return TCL_INDEX_NONE;
    }
    string = entryPtr->entry.displayString;

    selStart = Tcl_UtfAtIndex(string, entryPtr->entry.selectFirst);
    selEnd = Tcl_UtfAtIndex(selStart,
	    entryPtr->entry.selectLast - entryPtr->entry.selectFirst);
    if (selEnd  <= selStart + offset) {
	return 0;
    }
    byteCount = selEnd - selStart - offset;
    if (byteCount > maxBytes) {
    /* @@@POSSIBLE BUG: Can transfer partial UTF-8 sequences.  Is this OK? */
	byteCount = maxBytes;
    }
    if (byteCount <= 0) {
	return 0;
    }
    memcpy(buffer, selStart + offset, byteCount);
    buffer[byteCount] = '\0';
    return byteCount;
}

/* EntryLostSelection --
 *	Tk_LostSelProc for Entry widgets; called when an entry
 *	loses ownership of the selection.
 */
static void EntryLostSelection(ClientData clientData)
{
    Entry *entryPtr = (Entry *) clientData;
    Entry *entryPtr = (Entry *)clientData;
    entryPtr->core.flags &= ~GOT_SELECTION;
    entryPtr->entry.selectFirst = entryPtr->entry.selectLast = -1;
    entryPtr->entry.selectFirst = entryPtr->entry.selectLast = TCL_INDEX_NONE;
    TtkRedisplayWidget(&entryPtr->core);
}

/* EntryOwnSelection --
 * 	Assert ownership of the PRIMARY selection,
 * 	if -exportselection set and selection is present and interp is unsafe.
 */
static void EntryOwnSelection(Entry *entryPtr)
{
    if (entryPtr->entry.exportSelection
	&& (!Tcl_IsSafe(entryPtr->core.interp))
	&& !(entryPtr->core.flags & GOT_SELECTION)) {
	Tk_OwnSelection(entryPtr->core.tkwin, XA_PRIMARY, EntryLostSelection,
		(ClientData) entryPtr);
		entryPtr);
	entryPtr->core.flags |= GOT_SELECTION;
    }
}

/*------------------------------------------------------------------------
 * +++ Validation.
 */

/* ExpandPercents --
 *	Expand an entry validation script template (-validatecommand
 *	or -invalidcommand).
 */
static void
ExpandPercents(
     Entry *entryPtr,		/* Entry that needs validation. */
     const char *template, 	/* Script template */
     const char *new,		/* Potential new value of entry string */
     int index,			/* index of insert/delete */
     const char *templ, 	/* Script template */
     const char *newValue,		/* Potential new value of entry string */
     TkSizeT index,			/* index of insert/delete */
     int count,			/* #changed characters */
     VREASON reason,		/* Reason for change */
     Tcl_DString *dsPtr)	/* Result of %-substitutions */
{
    int spaceNeeded, cvtFlags;
    int number, length;
    const char *string;
    int stringLength;
    int ch;
    char numStorage[2*TCL_INTEGER_SPACE];

    while (*template) {
    while (*templ) {
	/* Find everything up to the next % character and append it
	 * to the result string.
	 */
	string = Tcl_UtfFindFirst(template, '%');
	string = Tcl_UtfFindFirst(templ, '%');
	if (string == NULL) {
	    /* No more %-sequences to expand.
	     * Copy the rest of the template.
	     */
	    Tcl_DStringAppend(dsPtr, template, -1);
	    Tcl_DStringAppend(dsPtr, templ, -1);
	    return;
	}
	if (string != template) {
	    Tcl_DStringAppend(dsPtr, template, string - template);
	    template = string;
	if (string != templ) {
	    Tcl_DStringAppend(dsPtr, templ, string - templ);
	    templ = string;
	}

	/* There's a percent sequence here.  Process it.
	 */
	++template; /* skip over % */
	if (*template != '\0') {
	    template += TkUtfToUniChar(template, &ch);
	++templ; /* skip over % */
	if (*templ != '\0') {
	    templ += TkUtfToUniChar(templ, &ch);
	} else {
	    ch = '%';
	}

	stringLength = -1;
	switch (ch) {
	    case 'd': /* Type of call that caused validation */
		if (reason == VALIDATE_INSERT) {
		    number = 1;
		} else if (reason == VALIDATE_DELETE) {
		    number = 0;
		} else {
		    number = -1;
		}
		sprintf(numStorage, "%d", number);
		string = numStorage;
		break;
	    case 'i': /* index of insert/delete */
		sprintf(numStorage, "%d", index);
		sprintf(numStorage, "%d", (int)index);
		string = numStorage;
		break;
	    case 'P': /* 'Peeked' new value of the string */
		string = new;
		string = newValue;
		break;
	    case 's': /* Current string value */
		string = entryPtr->entry.string;
		break;
	    case 'S': /* string to be inserted/deleted, if any */
		if (reason == VALIDATE_INSERT) {
		    string = Tcl_UtfAtIndex(new, index);
		    string = Tcl_UtfAtIndex(newValue, index);
		    stringLength = Tcl_UtfAtIndex(string, count) - string;
		} else if (reason == VALIDATE_DELETE) {
		    string = Tcl_UtfAtIndex(entryPtr->entry.string, index);
		    stringLength = Tcl_UtfAtIndex(string, count) - string;
		} else {
		    string = "";
		    stringLength = 0;
498
499
500
501
502
503
504
505

506
507
508
509



510
511
512
513
514
515
516

517
518
519
520
521
522
523
524
525
526
527
528
529
530

531
532



533
534
535
536
537
538
539
540
541

542
543
544
545
546
547
548
549







-
+

-
-
-
+
+
+






-
+







 * 	Build and evaluate an entry validation script.
 * 	If the script raises an error, disable validation
 * 	by setting '-validate none'
 */
static int RunValidationScript(
    Tcl_Interp *interp, 	/* Interpreter to use */
    Entry *entryPtr,		/* Entry being validated */
    const char *template,	/* Script template */
    const char *templ,	/* Script template */
    const char *optionName,	/* "-validatecommand", "-invalidcommand" */
    const char *new,		/* Potential new value of entry string */
    int index,			/* index of insert/delete */
    int count,			/* #changed characters */
    const char *newValue,	/* Potential new value of entry string */
    TkSizeT index,			/* index of insert/delete */
    TkSizeT count,			/* #changed characters */
    VREASON reason)		/* Reason for change */
{
    Tcl_DString script;
    int code;

    Tcl_DStringInit(&script);
    ExpandPercents(entryPtr, template, new, index, count, reason, &script);
    ExpandPercents(entryPtr, templ, newValue, index, count, reason, &script);
    code = Tcl_EvalEx(interp,
		Tcl_DStringValue(&script), Tcl_DStringLength(&script),
		TCL_EVAL_GLOBAL);
    Tcl_DStringFree(&script);
    if (WidgetDestroyed(&entryPtr->core))
	return TCL_ERROR;

553
554
555
556
557
558
559
560

561
562
563
564
565
566
567
568
569
570


571
572
573
574
575
576
577

578
579

580
581
582
583
584
585
586
579
580
581
582
583
584
585

586
587
588
589
590
591
592
593
594


595
596
597
598
599
600
601
602

603
604

605
606
607
608
609
610
611
612







-
+








-
-
+
+






-
+

-
+







/* EntryValidateChange --
 *	Validate a proposed change to the entry widget's value if required.
 *	Call the -invalidcommand if validation fails.
 *
 * Returns:
 *	TCL_OK if the change is accepted
 *	TCL_BREAK if the change is rejected
 *      TCL_ERROR if any errors occured
 *      TCL_ERROR if any errors occurred
 *
 * The change will be rejected if -validatecommand returns 0,
 * or if -validatecommand or -invalidcommand modifies the value.
 */
static int
EntryValidateChange(
    Entry *entryPtr,		/* Entry that needs validation. */
    const char *newValue,	/* Potential new value of entry string */
    int index,			/* index of insert/delete, -1 otherwise */
    int count,			/* #changed characters */
    TkSizeT index,			/* index of insert/delete, TCL_INDEX_NONE otherwise */
    TkSizeT count,			/* #changed characters */
    VREASON reason)		/* Reason for change */
{
    Tcl_Interp *interp = entryPtr->core.interp;
    VMODE vmode = entryPtr->entry.validate;
    int code, change_ok;

    if (   (entryPtr->entry.validateCmd == NULL)
    if ((entryPtr->entry.validateCmd == NULL)
	|| (entryPtr->core.flags & VALIDATING)
	|| !EntryNeedsValidation(vmode, reason) )
	|| !EntryNeedsValidation(vmode, reason))
    {
	return TCL_OK;
    }

    entryPtr->core.flags |= VALIDATING;

    /* Run -validatecommand and check return value:
626
627
628
629
630
631
632
633

634
635
636

637
638
639
640
641
642
643
652
653
654
655
656
657
658

659
660
661
662
663
664
665
666
667
668
669
670







-
+



+







/* EntryRevalidate --
 * 	Revalidate the current value of an entry widget,
 * 	update the TTK_STATE_INVALID bit.
 *
 * Returns:
 * 	TCL_OK if valid, TCL_BREAK if invalid, TCL_ERROR on error.
 */
static int EntryRevalidate(Tcl_Interp *interp, Entry *entryPtr, VREASON reason)
static int EntryRevalidate(Tcl_Interp *dummy, Entry *entryPtr, VREASON reason)
{
    int code = EntryValidateChange(
		    entryPtr, entryPtr->entry.string, -1,0, reason);
    (void)dummy;

    if (code == TCL_BREAK) {
	TtkWidgetChangeState(&entryPtr->core, TTK_STATE_INVALID, 0);
    } else if (code == TCL_OK) {
	TtkWidgetChangeState(&entryPtr->core, 0, TTK_STATE_INVALID);
    }

689
690
691
692
693
694
695
696
697


698
699
700
701
702
703
704
705
706
707
708
709
710

711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728

729
730
731
732
733
734
735
716
717
718
719
720
721
722


723
724
725
726
727
728
729
730
731
732
733
734
735
736

737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754

755
756
757
758
759
760
761
762







-
-
+
+












-
+

















-
+







    int g = nChars > 0;		/* left gravity adjustment */

    e->insertPos    = AdjustIndex(e->insertPos, index, nChars);
    e->selectFirst  = AdjustIndex(e->selectFirst, index, nChars);
    e->selectLast   = AdjustIndex(e->selectLast, index+g, nChars);
    e->xscroll.first= AdjustIndex(e->xscroll.first, index+g, nChars);

    if (e->selectLast <= e->selectFirst)
	e->selectFirst = e->selectLast = -1;
    if (e->selectLast + 1 <= e->selectFirst + 1)
	e->selectFirst = e->selectLast = TCL_INDEX_NONE;
}

/* EntryStoreValue --
 *	Replace the contents of a text entry with a given value,
 *	recompute dependent resources, and schedule a redisplay.
 *
 *	See also: EntrySetValue().
 */
static void
EntryStoreValue(Entry *entryPtr, const char *value)
{
    size_t numBytes = strlen(value);
    int numChars = Tcl_NumUtfChars(value, numBytes);
    TkSizeT numChars = Tcl_NumUtfChars(value, numBytes);

    if (entryPtr->core.flags & VALIDATING)
	entryPtr->core.flags |= VALIDATION_SET_VALUE;

    /* Make sure all indices remain in bounds:
     */
    if (numChars < entryPtr->entry.numChars)
	AdjustIndices(entryPtr, numChars, numChars - entryPtr->entry.numChars);

    /* Free old value:
     */
    if (entryPtr->entry.displayString != entryPtr->entry.string)
	ckfree(entryPtr->entry.displayString);
    ckfree(entryPtr->entry.string);

    /* Store new value:
     */
    entryPtr->entry.string = ckalloc(numBytes + 1);
    entryPtr->entry.string = (char *)ckalloc(numBytes + 1);
    strcpy(entryPtr->entry.string, value);
    entryPtr->entry.numBytes = numBytes;
    entryPtr->entry.numChars = numChars;

    entryPtr->entry.displayString
	= entryPtr->entry.showChar
	? EntryDisplayString(entryPtr->entry.showChar, numChars)
778
779
780
781
782
783
784
785

786
787
788
789
790
791
792
805
806
807
808
809
810
811

812
813
814
815
816
817
818
819







-
+







}

/* EntryTextVariableTrace --
 *	Variable trace procedure for entry -textvariable
 */
static void EntryTextVariableTrace(void *recordPtr, const char *value)
{
    Entry *entryPtr = recordPtr;
    Entry *entryPtr = (Entry *)recordPtr;

    if (WidgetDestroyed(&entryPtr->core)) {
	return;
    }

    if (entryPtr->core.flags & SYNCING_VARIABLE) {
	/* Trace was fired due to Tcl_SetVar2 call in EntrySetValue.
804
805
806
807
808
809
810
811

812
813
814
815
816
817
818
819

820
821
822
823
824
825
826
827
828
829




830
831
832

833
834
835
836

837
838
839
840
841

842
843
844
845
846
847
848
849
850
851
852


853
854
855
856

857
858
859

860
861
862

863
864
865

866
867
868
869
870
871
872
873
874
875



876
877
878

879
880
881
882

883
884
885
886

887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903

904
905
906
907
908
909
910
831
832
833
834
835
836
837

838
839
840
841
842
843
844
845

846
847
848
849
850
851
852




853
854
855
856
857
858

859
860
861
862

863
864
865
866
867

868
869
870
871
872
873
874
875
876
877


878
879
880
881
882

883
884
885

886
887
888

889
890
891

892
893
894
895
896
897
898
899



900
901
902
903
904

905
906
907
908

909
910
911
912

913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929

930
931
932
933
934
935
936
937







-
+







-
+






-
-
-
-
+
+
+
+


-
+



-
+




-
+









-
-
+
+



-
+


-
+


-
+


-
+







-
-
-
+
+
+


-
+



-
+



-
+
















-
+








/* InsertChars --
 *	Add new characters to an entry widget.
 */
static int
InsertChars(
    Entry *entryPtr,		/* Entry that is to get the new elements. */
    int index,			/* Insert before this index */
    TkSizeT index,			/* Insert before this index */
    const char *value)		/* New characters to add */
{
    char *string = entryPtr->entry.string;
    size_t byteIndex = Tcl_UtfAtIndex(string, index) - string;
    size_t byteCount = strlen(value);
    int charsAdded = Tcl_NumUtfChars(value, byteCount);
    size_t newByteCount = entryPtr->entry.numBytes + byteCount + 1;
    char *new;
    char *newBytes;
    int code;

    if (byteCount == 0) {
	return TCL_OK;
    }

    new =  ckalloc(newByteCount);
    memcpy(new, string, byteIndex);
    strcpy(new + byteIndex, value);
    strcpy(new + byteIndex + byteCount, string + byteIndex);
    newBytes =  (char *)ckalloc(newByteCount);
    memcpy(newBytes, string, byteIndex);
    strcpy(newBytes + byteIndex, value);
    strcpy(newBytes + byteIndex + byteCount, string + byteIndex);

    code = EntryValidateChange(
	    entryPtr, new, index, charsAdded, VALIDATE_INSERT);
	    entryPtr, newBytes, index, charsAdded, VALIDATE_INSERT);

    if (code == TCL_OK) {
	AdjustIndices(entryPtr, index, charsAdded);
	code = EntrySetValue(entryPtr, new);
	code = EntrySetValue(entryPtr, newBytes);
    } else if (code == TCL_BREAK) {
	code = TCL_OK;
    }

    ckfree(new);
    ckfree(newBytes);
    return code;
}

/* DeleteChars --
 *	Remove one or more characters from an entry widget.
 */
static int
DeleteChars(
    Entry *entryPtr,		/* Entry widget to modify. */
    int index,			/* Index of first character to delete. */
    int count)			/* How many characters to delete. */
    TkSizeT index,			/* Index of first character to delete. */
    TkSizeT count)			/* How many characters to delete. */
{
    char *string = entryPtr->entry.string;
    size_t byteIndex, byteCount, newByteCount;
    char *new;
    char *newBytes;
    int code;

    if (index < 0) {
    if (index == TCL_INDEX_NONE) {
	index = 0;
    }
    if (count > entryPtr->entry.numChars - index) {
    if (count + index + 1 > entryPtr->entry.numChars + 1) {
	count = entryPtr->entry.numChars - index;
    }
    if (count <= 0) {
    if (count + 1 <= 1) {
	return TCL_OK;
    }

    byteIndex = Tcl_UtfAtIndex(string, index) - string;
    byteCount = Tcl_UtfAtIndex(string+byteIndex, count) - (string+byteIndex);

    newByteCount = entryPtr->entry.numBytes + 1 - byteCount;
    new =  ckalloc(newByteCount);
    memcpy(new, string, byteIndex);
    strcpy(new + byteIndex, string + byteIndex + byteCount);
    newBytes =  (char *)ckalloc(newByteCount);
    memcpy(newBytes, string, byteIndex);
    strcpy(newBytes + byteIndex, string + byteIndex + byteCount);

    code = EntryValidateChange(
	    entryPtr, new, index, count, VALIDATE_DELETE);
	    entryPtr, newBytes, index, count, VALIDATE_DELETE);

    if (code == TCL_OK) {
	AdjustIndices(entryPtr, index, -count);
	code = EntrySetValue(entryPtr, new);
	code = EntrySetValue(entryPtr, newBytes);
    } else if (code == TCL_BREAK) {
	code = TCL_OK;
    }
    ckfree(new);
    ckfree(newBytes);

    return code;
}

/*------------------------------------------------------------------------
 * +++ Event handler.
 */

/* EntryEventProc --
 *	Extra event handling for entry widgets:
 *	Triggers validation on FocusIn and FocusOut events.
 */
#define EntryEventMask (FocusChangeMask)
static void
EntryEventProc(ClientData clientData, XEvent *eventPtr)
{
    Entry *entryPtr = (Entry *) clientData;
    Entry *entryPtr = (Entry *)clientData;

    Tcl_Preserve(clientData);
    switch (eventPtr->type) {
	case DestroyNotify:
	    Tk_DeleteEventHandler(entryPtr->core.tkwin,
		    EntryEventMask, EntryEventProc, clientData);
	    break;
919
920
921
922
923
924
925
926

927
928


929
930
931
932
933

934
935
936

937
938
939
940
941
942
943
944
945
946
947
948
949


950
951
952
953
954
955

956
957
958
959
960
961
962
946
947
948
949
950
951
952

953
954

955
956
957
958
959
960

961
962
963

964
965
966
967
968
969
970
971
972
973
974
975


976
977
978
979
980
981
982

983
984
985
986
987
988
989
990







-
+

-
+
+




-
+


-
+











-
-
+
+





-
+







}

/*------------------------------------------------------------------------
 * +++ Initialization and cleanup.
 */

static void
EntryInitialize(Tcl_Interp *interp, void *recordPtr)
EntryInitialize(Tcl_Interp *dummy, void *recordPtr)
{
    Entry *entryPtr = recordPtr;
    Entry *entryPtr = (Entry *)recordPtr;
    (void)dummy;

    Tk_CreateEventHandler(
	entryPtr->core.tkwin, EntryEventMask, EntryEventProc, entryPtr);
    Tk_CreateSelHandler(entryPtr->core.tkwin, XA_PRIMARY, XA_STRING,
	EntryFetchSelection, (ClientData) entryPtr, XA_STRING);
	EntryFetchSelection, entryPtr, XA_STRING);
    TtkBlinkCursor(&entryPtr->core);

    entryPtr->entry.string		= ckalloc(1);
    entryPtr->entry.string		= (char *)ckalloc(1);
    *entryPtr->entry.string 		= '\0';
    entryPtr->entry.displayString	= entryPtr->entry.string;
    entryPtr->entry.textVariableTrace 	= 0;
    entryPtr->entry.numBytes = entryPtr->entry.numChars = 0;

    EntryInitStyleDefaults(&entryPtr->entry.styleDefaults);

    entryPtr->entry.xscrollHandle =
	TtkCreateScrollHandle(&entryPtr->core, &entryPtr->entry.xscroll);

    entryPtr->entry.insertPos		= 0;
    entryPtr->entry.selectFirst 	= -1;
    entryPtr->entry.selectLast		= -1;
    entryPtr->entry.selectFirst 	= TCL_INDEX_NONE;
    entryPtr->entry.selectLast		= TCL_INDEX_NONE;
}

static void
EntryCleanup(void *recordPtr)
{
    Entry *entryPtr = recordPtr;
    Entry *entryPtr = (Entry *)recordPtr;

    if (entryPtr->entry.textVariableTrace)
	Ttk_UntraceVariable(entryPtr->entry.textVariableTrace);

    TtkFreeScrollHandle(entryPtr->entry.xscrollHandle);

    EntryFreeStyleDefaults(&entryPtr->entry.styleDefaults);
970
971
972
973
974
975
976
977

978
979
980
981
982
983
984
998
999
1000
1001
1002
1003
1004

1005
1006
1007
1008
1009
1010
1011
1012







-
+







}

/* EntryConfigure --
 * 	Configure hook for Entry widgets.
 */
static int EntryConfigure(Tcl_Interp *interp, void *recordPtr, int mask)
{
    Entry *entryPtr = recordPtr;
    Entry *entryPtr = (Entry *)recordPtr;
    Tcl_Obj *textVarName = entryPtr->entry.textVariableObj;
    Ttk_TraceHandle *vt = 0;

    if (mask & TEXTVAR_CHANGED) {
	if (textVarName && *Tcl_GetString(textVarName) != '\0') {
	    vt = Ttk_TraceVariable(interp,
		    textVarName,EntryTextVariableTrace,entryPtr);
997
998
999
1000
1001
1002
1003
1004

1005
1006
1007
1008
1009
1010
1011
1025
1026
1027
1028
1029
1030
1031

1032
1033
1034
1035
1036
1037
1038
1039







-
+







	if (entryPtr->entry.textVariableTrace)
	    Ttk_UntraceVariable(entryPtr->entry.textVariableTrace);
	entryPtr->entry.textVariableTrace = vt;
    }

    /* Claim the selection, in case we've suddenly started exporting it.
     */
    if (entryPtr->entry.exportSelection && (entryPtr->entry.selectFirst != -1)
    if (entryPtr->entry.exportSelection && (entryPtr->entry.selectFirst != TCL_INDEX_NONE)
	    && (!Tcl_IsSafe(entryPtr->core.interp))) {
	EntryOwnSelection(entryPtr);
    }

    /* Handle -state compatibility option:
     */
    if (mask & STATE_CHANGED) {
1034
1035
1036
1037
1038
1039
1040
1041

1042
1043

1044

1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062

1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082

1083
1084
1085
1086
1087
1088
1089
1062
1063
1064
1065
1066
1067
1068

1069
1070

1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090

1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110

1111
1112
1113
1114
1115
1116
1117
1118







-
+

-
+

+

















-
+



















-
+







    EntryUpdateTextLayout(entryPtr);
    return TCL_OK;
}

/* EntryPostConfigure --
 * 	Post-configuration hook for entry widgets.
 */
static int EntryPostConfigure(Tcl_Interp *interp, void *recordPtr, int mask)
static int EntryPostConfigure(Tcl_Interp *dummy, void *recordPtr, int mask)
{
    Entry *entryPtr = recordPtr;
    Entry *entryPtr = (Entry *)recordPtr;
    int status = TCL_OK;
    (void)dummy;

    if ((mask & TEXTVAR_CHANGED) && entryPtr->entry.textVariableTrace != NULL) {
	status = Ttk_FireTrace(entryPtr->entry.textVariableTrace);
    }

    return status;
}

/*------------------------------------------------------------------------
 * +++ Layout and display.
 */

/* EntryCharPosition --
 * 	Return the X coordinate of the specified character index.
 * 	Precondition: textLayout and layoutX up-to-date.
 */
static int
EntryCharPosition(Entry *entryPtr, int index)
EntryCharPosition(Entry *entryPtr, TkSizeT index)
{
    int xPos;
    Tk_CharBbox(entryPtr->entry.textLayout, index, &xPos, NULL, NULL, NULL);
    return xPos + entryPtr->entry.layoutX;
}

/* EntryDoLayout --
 * 	Layout hook for entry widgets.
 *
 * 	Determine position of textLayout based on xscroll.first, justify,
 * 	and display area.
 *
 * 	Recalculates layoutX, layoutY, and rightIndex,
 * 	and updates xscroll accordingly.
 * 	May adjust xscroll.first to ensure the maximum #characters are onscreen.
 */
static void
EntryDoLayout(void *recordPtr)
{
    Entry *entryPtr = recordPtr;
    Entry *entryPtr = (Entry *)recordPtr;
    WidgetCore *corePtr = &entryPtr->core;
    Tk_TextLayout textLayout = entryPtr->entry.textLayout;
    int leftIndex = entryPtr->entry.xscroll.first;
    int rightIndex;
    Ttk_Box textarea;

    Ttk_PlaceLayout(corePtr->layout,corePtr->state,Ttk_WinBox(corePtr->tkwin));
1162
1163
1164
1165
1166
1167
1168
1169

1170
1171

1172
1173
1174
1175
1176
1177
1178
1179
1180

1181
1182
1183
1184
1185
1186
1187
1188
1189


1190
1191
1192
1193
1194
1195



1196
1197
1198
1199
1200
1201

1202
1203

1204
1205
1206
1207
1208
1209
1210
1191
1192
1193
1194
1195
1196
1197

1198
1199

1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217


1218
1219
1220
1221
1222



1223
1224
1225

1226
1227
1228
1229

1230
1231

1232
1233
1234
1235
1236
1237
1238
1239







-
+

-
+









+







-
-
+
+



-
-
-
+
+
+
-




-
+

-
+







}

/* EntryDisplay --
 *	Redraws the contents of an entry window.
 */
static void EntryDisplay(void *clientData, Drawable d)
{
    Entry *entryPtr = clientData;
    Entry *entryPtr = (Entry *)clientData;
    Tk_Window tkwin = entryPtr->core.tkwin;
    int leftIndex = entryPtr->entry.xscroll.first,
    TkSizeT leftIndex = entryPtr->entry.xscroll.first,
	rightIndex = entryPtr->entry.xscroll.last + 1,
	selFirst = entryPtr->entry.selectFirst,
	selLast = entryPtr->entry.selectLast;
    EntryStyleData es;
    GC gc;
    int showSelection, showCursor;
    Ttk_Box textarea;
    TkRegion clipRegion;
    XRectangle rect;
    Tcl_Obj *foregroundObj;

    EntryInitStyleData(entryPtr, &es);

    textarea = Ttk_ClientRegion(entryPtr->core.layout, "textarea");
    showCursor =
	   (entryPtr->core.flags & CURSOR_ON)
	&& EntryEditable(entryPtr)
	&& entryPtr->entry.insertPos >= leftIndex
	&& entryPtr->entry.insertPos <= rightIndex
	&& entryPtr->entry.insertPos + 1 >= leftIndex + 1
	&& entryPtr->entry.insertPos + 1 <= rightIndex + 1
	;
    showSelection =
	   !(entryPtr->core.state & TTK_STATE_DISABLED)
	&& selFirst > -1
	&& selLast > leftIndex
	&& selFirst <= rightIndex
	&& selFirst != TCL_INDEX_NONE
	&& selLast + 1 > leftIndex + 1
	&& selFirst + 1 <= rightIndex + 1;
	;

    /* Adjust selection range to keep in display bounds.
     */
    if (showSelection) {
	if (selFirst < leftIndex)
	if (selFirst + 1 < leftIndex + 1)
	    selFirst = leftIndex;
	if (selLast > rightIndex)
	if (selLast + 1 > rightIndex + 1)
	    selLast = rightIndex;
    }

    /* Draw widget background & border
     */
    Ttk_DrawLayout(entryPtr->core.layout, entryPtr->core.state, d);

1269
1270
1271
1272
1273
1274
1275














1276
1277
1278
1279
1280
1281
1282



















1283
1284
1285


1286
1287
1288
1289
1290
1291










1292
1293
1294
1295
1296
1297
1298
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318







1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338


1339
1340

1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362







+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
+
+
-





+
+
+
+
+
+
+
+
+
+







	XFillRectangle(Tk_Display(tkwin), d, gc,
	    cursorX, cursorY, cursorWidth, cursorHeight);
	Tk_FreeGC(Tk_Display(tkwin), gc);
    }

    /* Draw the text:
     */
    if ((*(entryPtr->entry.displayString) == '\0')
		&& (entryPtr->entry.placeholderObj != NULL)) {
	/* No text displayed, but -placeholder is given */
	if (Tcl_GetCharLength(es.placeholderForegroundObj) > 0) {
	    foregroundObj = es.placeholderForegroundObj;
	} else {
            foregroundObj = es.foregroundObj;
	}
	/* Use placeholder text width */
	leftIndex = 0;
	(void)TkGetStringFromObj(entryPtr->entry.placeholderObj, &rightIndex);
    } else {
	foregroundObj = es.foregroundObj;
    }
    gc = EntryGetGC(entryPtr, es.foregroundObj, clipRegion);
    Tk_DrawTextLayout(
	Tk_Display(tkwin), d, gc, entryPtr->entry.textLayout,
	entryPtr->entry.layoutX, entryPtr->entry.layoutY,
	leftIndex, rightIndex);
    XSetClipMask(Tk_Display(tkwin), gc, None);
    Tk_FreeGC(Tk_Display(tkwin), gc);
    gc = EntryGetGC(entryPtr, foregroundObj, clipRegion);
    if (showSelection) {

        /* Draw the selected and unselected portions separately.
	 */
	if (leftIndex < selFirst) {
	    Tk_DrawTextLayout(
		Tk_Display(tkwin), d, gc, entryPtr->entry.textLayout,
		entryPtr->entry.layoutX, entryPtr->entry.layoutY,
		leftIndex, selFirst);
	}
	if (selLast < rightIndex) {
	    Tk_DrawTextLayout(
		Tk_Display(tkwin), d, gc, entryPtr->entry.textLayout,
		entryPtr->entry.layoutX, entryPtr->entry.layoutY,
		selLast, rightIndex);
	}
	XSetClipMask(Tk_Display(tkwin), gc, None);
	Tk_FreeGC(Tk_Display(tkwin), gc);

    /* Overwrite the selected portion (if any) in the -selectforeground color:
     */
	/* Draw the selected portion in the -selectforeground color:
	 */
    if (showSelection) {
	gc = EntryGetGC(entryPtr, es.selForegroundObj, clipRegion);
	Tk_DrawTextLayout(
	    Tk_Display(tkwin), d, gc, entryPtr->entry.textLayout,
	    entryPtr->entry.layoutX, entryPtr->entry.layoutY,
	    selFirst, selLast);
	XSetClipMask(Tk_Display(tkwin), gc, None);
	Tk_FreeGC(Tk_Display(tkwin), gc);
    } else {

        /* Draw the entire visible text
         */
	Tk_DrawTextLayout(
	    Tk_Display(tkwin), d, gc, entryPtr->entry.textLayout,
	    entryPtr->entry.layoutX, entryPtr->entry.layoutY,
	    leftIndex, rightIndex);
	XSetClipMask(Tk_Display(tkwin), gc, None);
	Tk_FreeGC(Tk_Display(tkwin), gc);
    }

    /* Drop the region. Note that we have to manually remove the reference to
     * it from the Xft guts (if they're being used).
     */
1318
1319
1320
1321
1322
1323
1324
1325

1326
1327

1328
1329
1330






1331
1332
1333







1334
1335
1336
1337
1338
1339
1340

1341
1342
1343
1344
1345
1346
1347
1382
1383
1384
1385
1386
1387
1388

1389
1390
1391
1392



1393
1394
1395
1396
1397
1398



1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411

1412
1413
1414
1415
1416
1417
1418
1419







-
+


+
-
-
-
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+






-
+







 *	error occurs then an error message is left in the interp's result.
 */
static int
EntryIndex(
    Tcl_Interp *interp,		/* For error messages. */
    Entry *entryPtr,		/* Entry widget to query */
    Tcl_Obj *indexObj,		/* Symbolic index name */
    int *indexPtr)		/* Return value */
    TkSizeT *indexPtr)		/* Return value */
{
#   define EntryWidth(e) (Tk_Width(entryPtr->core.tkwin)) /* Not Right */
    TkSizeT length, idx;
    const char *string = Tcl_GetString(indexObj);
    size_t length = indexObj->length;

    const char *string;

    if (TCL_OK == TkGetIntForIndex(indexObj, entryPtr->entry.numChars - 1, 1, &idx)) {
    	if ((idx != TCL_INDEX_NONE) && (idx > entryPtr->entry.numChars)) {
    	    idx = entryPtr->entry.numChars;
    	}
    if (strncmp(string, "end", length) == 0) {
	*indexPtr = entryPtr->entry.numChars;
    } else if (strncmp(string, "insert", length) == 0) {
    	*indexPtr = idx;
    	return TCL_OK;
    }

    string = TkGetStringFromObj(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;
    } else if (strncmp(string, "right", length) == 0) {	/* for debugging */
	*indexPtr = entryPtr->entry.xscroll.last;
    } else if (strncmp(string, "sel.", 4) == 0) {
	if (entryPtr->entry.selectFirst < 0) {
	if (entryPtr->entry.selectFirst == TCL_INDEX_NONE) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "selection isn't in widget %s",
		    Tk_PathName(entryPtr->core.tkwin)));
	    Tcl_SetErrorCode(interp, "TTK", "ENTRY", "NO_SELECTION", NULL);
	    return TCL_ERROR;
	}
	if (strncmp(string, "sel.first", length) == 0) {
1363
1364
1365
1366
1367
1368
1369
1370

1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381

1382
1383
1384
1385
1386

1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410

1411
1412

1413
1414
1415
1416
1417
1418
1419
1420
1421

1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441


1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456

1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469

1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485

1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506


1507
1508
1509
1510
1511
1512
1513
1514
1515

1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528


1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549

1550
1551
1552
1553
1554
1555

1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566

1567
1568
1569
1570
1571
1572

1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583


1584
1585
1586
1587
1588

1589
1590
1591
1592
1593
1594
1595
1596
1597


1598
1599
1600
1601
1602
1603
1604
1435
1436
1437
1438
1439
1440
1441

1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452

1453
1454
1455
1456


1457






1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474

1475
1476

1477
1478
1479
1480
1481
1482
1483
1484
1485

1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504


1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520

1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533

1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549

1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569


1570
1571
1572
1573
1574
1575
1576
1577
1578
1579

1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591


1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613

1614
1615
1616
1617
1618
1619

1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630

1631
1632
1633
1634
1635
1636

1637
1638
1639
1640
1641
1642
1643
1644
1645
1646


1647
1648
1649
1650
1651
1652

1653
1654
1655
1656
1657
1658
1659
1660


1661
1662
1663
1664
1665
1666
1667
1668
1669







-
+










-
+



-
-
+
-
-
-
-
-
-

















-
+

-
+








-
+


















-
-
+
+














-
+












-
+















-
+



















-
-
+
+








-
+











-
-
+
+




















-
+





-
+










-
+





-
+









-
-
+
+




-
+







-
-
+
+







	    x = maxWidth;
	    roundUp = 1;
	}
	*indexPtr = Tk_PointToChar(entryPtr->entry.textLayout,
		x - entryPtr->entry.layoutX, 0);

        TtkUpdateScrollInfo(entryPtr->entry.xscrollHandle);
	if (*indexPtr < entryPtr->entry.xscroll.first) {
	if (*indexPtr + 1 < (TkSizeT)entryPtr->entry.xscroll.first + 1) {
	    *indexPtr = entryPtr->entry.xscroll.first;
	}

	/*
	 * Special trick:  if the x-position was off-screen to the right,
	 * round the index up to refer to the character just after the
	 * last visible one on the screen.  This is needed to enable the
	 * last character to be selected, for example.
	 */

	if (roundUp && (*indexPtr < entryPtr->entry.numChars)) {
	if (roundUp && ((TkSizeT)*indexPtr + 1 < entryPtr->entry.numChars + 1 )) {
	    *indexPtr += 1;
	}
    } else {
	if (Tcl_GetIntFromObj(interp, indexObj, indexPtr) != TCL_OK) {
	    goto badIndex;
	goto badIndex;
	}
	if (*indexPtr < 0) {
	    *indexPtr = 0;
	} else if (*indexPtr > entryPtr->entry.numChars) {
	    *indexPtr = entryPtr->entry.numChars;
	}
    }
    return TCL_OK;

badIndex:
    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
	    "bad entry index \"%s\"", string));
    Tcl_SetErrorCode(interp, "TTK", "ENTRY", "INDEX", NULL);
    return TCL_ERROR;
}

/* $entry bbox $index --
 * 	Return the bounding box of the character at the specified index.
 */
static int
EntryBBoxCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Entry *entryPtr = recordPtr;
    Entry *entryPtr = (Entry *)recordPtr;
    Ttk_Box b;
    int index;
    TkSizeT index;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "index");
	return TCL_ERROR;
    }
    if (EntryIndex(interp, entryPtr, objv[2], &index) != TCL_OK) {
	return TCL_ERROR;
    }
    if ((index == entryPtr->entry.numChars) && (index > 0)) {
    if ((index == entryPtr->entry.numChars) && (index + 1 > 1)) {
	index--;
    }
    Tk_CharBbox(entryPtr->entry.textLayout, index,
	    &b.x, &b.y, &b.width, &b.height);
    b.x += entryPtr->entry.layoutX;
    b.y += entryPtr->entry.layoutY;
    Tcl_SetObjResult(interp, Ttk_NewBoxObj(b));
    return TCL_OK;
}

/* $entry delete $from ?$to? --
 *	Delete the characters in the range [$from,$to).
 *	$to defaults to $from+1 if not specified.
 */
static int
EntryDeleteCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Entry *entryPtr = recordPtr;
    int first, last;
    Entry *entryPtr = (Entry *)recordPtr;
    TkSizeT first, last;

    if ((objc < 3) || (objc > 4)) {
	Tcl_WrongNumArgs(interp, 2, objv, "firstIndex ?lastIndex?");
	return TCL_ERROR;
    }
    if (EntryIndex(interp, entryPtr, objv[2], &first) != TCL_OK) {
	return TCL_ERROR;
    }
    if (objc == 3) {
	last = first + 1;
    } else if (EntryIndex(interp, entryPtr, objv[3], &last) != TCL_OK) {
	return TCL_ERROR;
    }

    if (last >= first && EntryEditable(entryPtr)) {
    if (last + 1 >= first + 1 && EntryEditable(entryPtr)) {
	return DeleteChars(entryPtr, first, last - first);
    }
    return TCL_OK;
}

/* $entry get --
 * 	Return the current value of the entry widget.
 */
static int
EntryGetCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Entry *entryPtr = recordPtr;
    Entry *entryPtr = (Entry *)recordPtr;
    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 2, objv, NULL);
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, Tcl_NewStringObj(entryPtr->entry.string, -1));
    return TCL_OK;
}

/* $entry icursor $index --
 * 	Set the insert cursor position.
 */
static int
EntryICursorCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Entry *entryPtr = recordPtr;
    Entry *entryPtr = (Entry *)recordPtr;
    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "pos");
	return TCL_ERROR;
    }
    if (EntryIndex(interp, entryPtr, objv[2],
	    &entryPtr->entry.insertPos) != TCL_OK) {
	return TCL_ERROR;
    }
    TtkRedisplayWidget(&entryPtr->core);
    return TCL_OK;
}

/* $entry index $index --
 * 	Return numeric value (0..numChars) of the specified index.
 */
static int
EntryIndexCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Entry *entryPtr = recordPtr;
    int index;
    Entry *entryPtr = (Entry *)recordPtr;
    TkSizeT index;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "string");
	return TCL_ERROR;
    }
    if (EntryIndex(interp, entryPtr, objv[2], &index) != TCL_OK) {
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, Tcl_NewIntObj(index));
    Tcl_SetObjResult(interp, TkNewIndexObj(index));
    return TCL_OK;
}

/* $entry insert $index $text --
 * 	Insert $text after position $index.
 * 	Silent no-op if the entry is disabled or read-only.
 */
static int
EntryInsertCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Entry *entryPtr = recordPtr;
    int index;
    Entry *entryPtr = (Entry *)recordPtr;
    TkSizeT index;

    if (objc != 4) {
	Tcl_WrongNumArgs(interp, 2, objv, "index text");
	return TCL_ERROR;
    }
    if (EntryIndex(interp, entryPtr, objv[2], &index) != TCL_OK) {
	return TCL_ERROR;
    }
    if (EntryEditable(entryPtr)) {
	return InsertChars(entryPtr, index, Tcl_GetString(objv[3]));
    }
    return TCL_OK;
}

/* $entry selection clear --
 * 	Clear selection.
 */
static int EntrySelectionClearCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Entry *entryPtr = recordPtr;
    Entry *entryPtr = (Entry *)recordPtr;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 3, objv, NULL);
	return TCL_ERROR;
    }
    entryPtr->entry.selectFirst = entryPtr->entry.selectLast = -1;
    entryPtr->entry.selectFirst = entryPtr->entry.selectLast = TCL_INDEX_NONE;
    TtkRedisplayWidget(&entryPtr->core);
    return TCL_OK;
}

/* $entry selection present --
 * 	Returns 1 if any characters are selected, 0 otherwise.
 */
static int EntrySelectionPresentCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Entry *entryPtr = recordPtr;
    Entry *entryPtr = (Entry *)recordPtr;
    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 3, objv, NULL);
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp,
	    Tcl_NewBooleanObj(entryPtr->entry.selectFirst >= 0));
	    Tcl_NewWideIntObj(entryPtr->entry.selectFirst != TCL_INDEX_NONE));
    return TCL_OK;
}

/* $entry selection range $start $end --
 * 	Explicitly set the selection range.
 */
static int EntrySelectionRangeCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Entry *entryPtr = recordPtr;
    int start, end;
    Entry *entryPtr = (Entry *)recordPtr;
    TkSizeT start, end;
    if (objc != 5) {
	Tcl_WrongNumArgs(interp, 3, objv, "start end");
	return TCL_ERROR;
    }
    if (    EntryIndex(interp, entryPtr, objv[3], &start) != TCL_OK
    if (EntryIndex(interp, entryPtr, objv[3], &start) != TCL_OK
         || EntryIndex(interp, entryPtr, objv[4], &end) != TCL_OK) {
	return TCL_ERROR;
    }
    if (entryPtr->core.state & TTK_STATE_DISABLED) {
	return TCL_OK;
    }

    if (start >= end) {
	entryPtr->entry.selectFirst = entryPtr->entry.selectLast = -1;
    if (start + 1 >= end + 1 ) {
	entryPtr->entry.selectFirst = entryPtr->entry.selectLast = TCL_INDEX_NONE;
    } else {
	entryPtr->entry.selectFirst = start;
	entryPtr->entry.selectLast = end;
	EntryOwnSelection(entryPtr);
    }
    TtkRedisplayWidget(&entryPtr->core);
    return TCL_OK;
1613
1614
1615
1616
1617
1618
1619
1620

1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636

1637
1638
1639
1640
1641
1642
1643
1678
1679
1680
1681
1682
1683
1684

1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700

1701
1702
1703
1704
1705
1706
1707
1708







-
+















-
+








/* $entry set $value
 * 	Sets the value of an entry widget.
 */
static int EntrySetCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Entry *entryPtr = recordPtr;
    Entry *entryPtr = (Entry *)recordPtr;
    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "value");
	return TCL_ERROR;
    }
    EntrySetValue(entryPtr, Tcl_GetString(objv[2]));
    return TCL_OK;
}

/* $entry validate --
 * 	Trigger forced validation.  Returns 1/0 if validation succeeds/fails
 * 	or error status from -validatecommand / -invalidcommand.
 */
static int EntryValidateCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Entry *entryPtr = recordPtr;
    Entry *entryPtr = (Entry *)recordPtr;
    int code;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 2, objv, NULL);
	return TCL_ERROR;
    }

1651
1652
1653
1654
1655
1656
1657
1658

1659
1660

1661
1662
1663
1664
1665
1666
1667
1716
1717
1718
1719
1720
1721
1722

1723
1724

1725
1726
1727
1728
1729
1730
1731
1732







-
+

-
+







}

/* $entry xview	-- horizontal scrolling interface
 */
static int EntryXViewCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Entry *entryPtr = recordPtr;
    Entry *entryPtr = (Entry *)recordPtr;
    if (objc == 3) {
	int newFirst;
	TkSizeT newFirst;
	if (EntryIndex(interp, entryPtr, objv[2], &newFirst) != TCL_OK) {
	    return TCL_ERROR;
	}
	TtkScrollTo(entryPtr->entry.xscrollHandle, newFirst, 1);
	return TCL_OK;
    }
    return TtkScrollviewCommand(interp, objc, objv, entryPtr->entry.xscrollHandle);
1676
1677
1678
1679
1680
1681
1682

1683
1684
1685
1686
1687
1688
1689
1690
1691
1692

1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725

1726
1727
1728
1729
1730
1731
1732
1733
1734

1735
1736

1737
1738
1739

1740
1741
1742

1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753

1754
1755

1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766

1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787


1788
1789
1790
1791
1792

1793
1794
1795
1796
1797
1798


1799
1800
1801
1802
1803
1804

1805
1806
1807
1808
1809

1810
1811

1812
1813
1814
1815

1816
1817
1818

1819
1820
1821
1822
1823



1824
1825

1826
1827



1828
1829
1830
1831

1832
1833
1834

1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845





1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857

1858
1859
1860
1861
1862
1863
1864
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757

1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772










1773
1774
1775
1776
1777
1778
1779
1780

1781
1782
1783
1784
1785
1786
1787
1788
1789

1790
1791

1792
1793
1794

1795
1796
1797

1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808

1809
1810

1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821

1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841


1842
1843
1844
1845
1846
1847

1848
1849
1850
1851
1852


1853
1854
1855
1856
1857
1858
1859

1860
1861
1862
1863
1864

1865
1866

1867
1868
1869
1870

1871
1872
1873

1874
1875




1876
1877
1878


1879


1880
1881
1882




1883



1884











1885
1886
1887
1888
1889
1890








1891
1892

1893
1894
1895
1896
1897
1898
1899
1900







+









-
+














-
-
-
-
-
-
-
-
-
-








-
+








-
+

-
+


-
+


-
+










-
+

-
+










-
+



















-
-
+
+




-
+




-
-
+
+





-
+




-
+

-
+



-
+


-
+

-
-
-
-
+
+
+
-
-
+
-
-
+
+
+
-
-
-
-
+
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+

-
-
-
-
-
-
-
-


-
+







    { "icursor", 	EntryICursorCommand,0 },
    { "identify",	TtkWidgetIdentifyCommand,0 },
    { "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 }
};

/*------------------------------------------------------------------------
 * +++ Entry widget definition.
 */

static WidgetSpec EntryWidgetSpec = {
static const WidgetSpec EntryWidgetSpec = {
    "TEntry",			/* className */
    sizeof(Entry), 		/* recordSize */
    EntryOptionSpecs, 		/* optionSpecs */
    EntryCommands,  		/* subcommands */
    EntryInitialize,     	/* initializeProc */
    EntryCleanup,		/* cleanupProc */
    EntryConfigure,		/* configureProc */
    EntryPostConfigure,  	/* postConfigureProc */
    TtkWidgetGetLayout, 	/* getLayoutProc */
    TtkWidgetSize, 		/* sizeProc */
    EntryDoLayout,		/* layoutProc */
    EntryDisplay		/* displayProc */
};

/*------------------------------------------------------------------------
 * Named indices for the combobox "current" command
 */
static const char *const comboboxCurrentIndexNames[] = {
    "end", NULL
};
enum comboboxCurrentIndices {
    INDEX_END
};

/*------------------------------------------------------------------------
 * +++ Combobox widget record.
 */

typedef struct {
    Tcl_Obj	*postCommandObj;
    Tcl_Obj	*valuesObj;
    Tcl_Obj	*heightObj;
    int 	currentIndex;
    TkSizeT	currentIndex;
} ComboboxPart;

typedef struct {
    WidgetCore core;
    EntryPart entry;
    ComboboxPart combobox;
} Combobox;

static Tk_OptionSpec ComboboxOptionSpecs[] = {
static const Tk_OptionSpec ComboboxOptionSpecs[] = {
    {TK_OPTION_STRING, "-height", "height", "Height",
        DEF_LIST_HEIGHT, Tk_Offset(Combobox, combobox.heightObj), -1,
        DEF_LIST_HEIGHT, offsetof(Combobox, combobox.heightObj), TCL_INDEX_NONE,
	0,0,0 },
    {TK_OPTION_STRING, "-postcommand", "postCommand", "PostCommand",
        "", Tk_Offset(Combobox, combobox.postCommandObj), -1,
        "", offsetof(Combobox, combobox.postCommandObj), TCL_INDEX_NONE,
	0,0,0 },
    {TK_OPTION_STRING, "-values", "values", "Values",
        "", Tk_Offset(Combobox, combobox.valuesObj), -1,
        "", offsetof(Combobox, combobox.valuesObj), TCL_INDEX_NONE,
	0,0,0 },
    WIDGET_INHERIT_OPTIONS(EntryOptionSpecs)
};

/* ComboboxInitialize --
 * 	Initialization hook for combobox widgets.
 */
static void
ComboboxInitialize(Tcl_Interp *interp, void *recordPtr)
{
    Combobox *cb = recordPtr;
    Combobox *cb = (Combobox *)recordPtr;

    cb->combobox.currentIndex = -1;
    cb->combobox.currentIndex = TCL_INDEX_NONE;
    TtkTrackElementState(&cb->core);
    EntryInitialize(interp, recordPtr);
}

/* ComboboxConfigure --
 * 	Configuration hook for combobox widgets.
 */
static int
ComboboxConfigure(Tcl_Interp *interp, void *recordPtr, int mask)
{
    Combobox *cbPtr = recordPtr;
    Combobox *cbPtr = (Combobox *)recordPtr;
    int unused;

    /* Make sure -values is a valid list:
     */
    if (Tcl_ListObjLength(interp,cbPtr->combobox.valuesObj,&unused) != TCL_OK)
	return TCL_ERROR;

    return EntryConfigure(interp, recordPtr, mask);
}

/* $cb current ?newIndex? -- get or set current index.
 * 	Setting the current index updates the combobox value,
 * 	but the value and -values may be changed independently
 * 	of the index.  Instead of trying to keep currentIndex
 * 	in sync at all times, [$cb current] double-checks
 */
static int ComboboxCurrentCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Combobox *cbPtr = recordPtr;
    int currentIndex = cbPtr->combobox.currentIndex;
    Combobox *cbPtr = (Combobox *)recordPtr;
    TkSizeT currentIndex = cbPtr->combobox.currentIndex;
    const char *currentValue = cbPtr->entry.string;
    int nValues;
    Tcl_Obj **values;

    Tcl_ListObjGetElements(interp,cbPtr->combobox.valuesObj,&nValues,&values);
    Tcl_ListObjGetElements(interp, cbPtr->combobox.valuesObj, &nValues, &values);

    if (objc == 2) {
	/* Check if currentIndex still valid:
	 */
	if (    currentIndex < 0
	     || currentIndex >= nValues
	if (currentIndex == TCL_INDEX_NONE
	     || currentIndex >= (TkSizeT)nValues
	     || strcmp(currentValue,Tcl_GetString(values[currentIndex]))
	   )
	{
	    /* Not valid.  Check current value against each element in -values:
	     */
	    for (currentIndex = 0; currentIndex < nValues; ++currentIndex) {
	    for (currentIndex = 0; currentIndex < (TkSizeT)nValues; ++currentIndex) {
		if (!strcmp(currentValue,Tcl_GetString(values[currentIndex]))) {
		    break;
		}
	    }
	    if (currentIndex >= nValues) {
	    if (currentIndex >= (TkSizeT)nValues) {
		/* Not found */
		currentIndex = -1;
		currentIndex = TCL_INDEX_NONE;
	    }
	}
	cbPtr->combobox.currentIndex = currentIndex;
	Tcl_SetObjResult(interp, Tcl_NewIntObj(currentIndex));
	Tcl_SetObjResult(interp, TkNewIndexObj(currentIndex));
	return TCL_OK;
    } else if (objc == 3) {
        int result, index;
	TkSizeT idx;

        result = Tcl_GetIndexFromObj(NULL, objv[2], comboboxCurrentIndexNames,
                "", 0, &index);
        if (result == TCL_OK) {

	if (TCL_OK == TkGetIntForIndex(objv[2], nValues - 1, 0, &idx)) {
	    if (idx == TCL_INDEX_NONE || idx > (TkSizeT)nValues) {
	        Tcl_SetObjResult(interp, Tcl_ObjPrintf(
            /*
             * The index is one of the named indices.
		        "index \"%s\" out of range", Tcl_GetString(objv[2])));
             */

	        Tcl_SetErrorCode(interp, "TTK", "COMBOBOX", "IDX_RANGE", NULL);
	        return TCL_ERROR;
	    }
	    switch (index) {
	    case INDEX_END:
	        /* "end" index */
                currentIndex = nValues - 1;
	    currentIndex = idx;
                break;
	    }
        } else {
	} else {

            /*
             * The index should be just an integer.
             */

	    if (Tcl_GetIntFromObj(NULL, objv[2], &currentIndex) != TCL_OK) {
	        Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		        "Incorrect index %s", Tcl_GetString(objv[2])));
	        Tcl_SetErrorCode(interp, "TTK", "COMBOBOX", "IDX_VALUE", NULL);
	        return TCL_ERROR;
	    }
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "Incorrect index %s", Tcl_GetString(objv[2])));
	    Tcl_SetErrorCode(interp, "TTK", "COMBOBOX", "IDX_VALUE", NULL);
	    return TCL_ERROR;
	}

	    if (currentIndex < 0 || currentIndex >= nValues) {
	        Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		        "Index %s out of range", Tcl_GetString(objv[2])));
	        Tcl_SetErrorCode(interp, "TTK", "COMBOBOX", "IDX_RANGE", NULL);
	        return TCL_ERROR;
	    }
        }

	cbPtr->combobox.currentIndex = currentIndex;

	return EntrySetValue(recordPtr, Tcl_GetString(values[currentIndex]));
	return EntrySetValue((Entry *)recordPtr, Tcl_GetString(values[currentIndex]));
    } else {
	Tcl_WrongNumArgs(interp, 2, objv, "?newIndex?");
	return TCL_ERROR;
    }
    return TCL_OK;
}

1874
1875
1876
1877
1878
1879
1880

1881
1882

1883
1884
1885
1886
1887
1888

1889
1890
1891
1892
1893
1894
1895
1910
1911
1912
1913
1914
1915
1916
1917
1918

1919
1920
1921
1922
1923
1924

1925
1926
1927
1928
1929
1930
1931
1932







+

-
+





-
+







    { "get", 		EntryGetCommand,0 },
    { "icursor", 	EntryICursorCommand,0 },
    { "identify",	TtkWidgetIdentifyCommand,0 },
    { "index", 		EntryIndexCommand,0 },
    { "insert", 	EntryInsertCommand,0 },
    { "instate",	TtkWidgetInstateCommand,0 },
    { "selection", 	0,EntrySelectionCommands },
    { "set", 		EntrySetCommand,0 },
    { "state",  	TtkWidgetStateCommand,0 },
    { "set", 		EntrySetCommand,0 },
    { "style",		TtkWidgetStyleCommand,0 },
    { "validate",	EntryValidateCommand,0 },
    { "xview", 		EntryXViewCommand,0 },
    { 0,0,0 }
};

static WidgetSpec ComboboxWidgetSpec = {
static const WidgetSpec ComboboxWidgetSpec = {
    "TCombobox",		/* className */
    sizeof(Combobox), 		/* recordSize */
    ComboboxOptionSpecs,	/* optionSpecs */
    ComboboxCommands,  		/* subcommands */
    ComboboxInitialize,     	/* initializeProc */
    EntryCleanup,		/* cleanupProc */
    ComboboxConfigure,		/* configureProc */
1918
1919
1920
1921
1922
1923
1924
1925

1926
1927

1928
1929
1930
1931

1932
1933
1934

1935
1936
1937

1938
1939
1940

1941
1942
1943
1944

1945
1946
1947

1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959

1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970

1971
1972
1973
1974
1975
1976
1977
1955
1956
1957
1958
1959
1960
1961

1962
1963

1964
1965
1966
1967

1968
1969
1970

1971
1972
1973

1974
1975
1976

1977
1978
1979
1980

1981
1982
1983

1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995

1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006

2007
2008
2009
2010
2011
2012
2013
2014







-
+

-
+



-
+


-
+


-
+


-
+



-
+


-
+











-
+










-
+








typedef struct {
    WidgetCore core;
    EntryPart entry;
    SpinboxPart spinbox;
} Spinbox;

static Tk_OptionSpec SpinboxOptionSpecs[] = {
static const Tk_OptionSpec SpinboxOptionSpecs[] = {
    {TK_OPTION_STRING, "-values", "values", "Values",
        "", Tk_Offset(Spinbox, spinbox.valuesObj), -1,
        "", offsetof(Spinbox, spinbox.valuesObj), TCL_INDEX_NONE,
	0,0,0 },

    {TK_OPTION_DOUBLE, "-from", "from", "From",
	"0", Tk_Offset(Spinbox,spinbox.fromObj), -1,
	"0", offsetof(Spinbox,spinbox.fromObj), TCL_INDEX_NONE,
	0,0,0 },
    {TK_OPTION_DOUBLE, "-to", "to", "To",
	"0", Tk_Offset(Spinbox,spinbox.toObj), -1,
	"0", offsetof(Spinbox,spinbox.toObj), TCL_INDEX_NONE,
	0,0,0 },
    {TK_OPTION_DOUBLE, "-increment", "increment", "Increment",
	"1", Tk_Offset(Spinbox,spinbox.incrementObj), -1,
	"1", offsetof(Spinbox,spinbox.incrementObj), TCL_INDEX_NONE,
	0,0,0 },
    {TK_OPTION_STRING, "-format", "format", "Format",
	"", Tk_Offset(Spinbox, spinbox.formatObj), -1,
	"", offsetof(Spinbox, spinbox.formatObj), TCL_INDEX_NONE,
	0,0,0 },

    {TK_OPTION_STRING, "-command", "command", "Command",
	"", Tk_Offset(Spinbox, spinbox.commandObj), -1,
	"", offsetof(Spinbox, spinbox.commandObj), TCL_INDEX_NONE,
	0,0,0 },
    {TK_OPTION_BOOLEAN, "-wrap", "wrap", "Wrap",
	"0", Tk_Offset(Spinbox,spinbox.wrapObj), -1,
	"0", offsetof(Spinbox,spinbox.wrapObj), TCL_INDEX_NONE,
	0,0,0 },

    WIDGET_INHERIT_OPTIONS(EntryOptionSpecs)
};

/* SpinboxInitialize --
 * 	Initialization hook for spinbox widgets.
 */
static void
SpinboxInitialize(Tcl_Interp *interp, void *recordPtr)
{
    Spinbox *sb = recordPtr;
    Spinbox *sb = (Spinbox *)recordPtr;
    TtkTrackElementState(&sb->core);
    EntryInitialize(interp, recordPtr);
}

/* SpinboxConfigure --
 * 	Configuration hook for spinbox widgets.
 */
static int
SpinboxConfigure(Tcl_Interp *interp, void *recordPtr, int mask)
{
    Spinbox *sb = recordPtr;
    Spinbox *sb = (Spinbox *)recordPtr;
    int unused;

    /* Make sure -values is a valid list:
     */
    if (Tcl_ListObjLength(interp,sb->spinbox.valuesObj,&unused) != TCL_OK)
	return TCL_ERROR;

1986
1987
1988
1989
1990
1991
1992

1993
1994

1995
1996
1997
1998
1999
2000

2001
2002
2003
2004
2005
2006
2007
2023
2024
2025
2026
2027
2028
2029
2030
2031

2032
2033
2034
2035
2036
2037

2038
2039
2040
2041
2042
2043
2044
2045







+

-
+





-
+







    { "get", 		EntryGetCommand,0 },
    { "icursor", 	EntryICursorCommand,0 },
    { "identify",	TtkWidgetIdentifyCommand,0 },
    { "index", 		EntryIndexCommand,0 },
    { "insert", 	EntryInsertCommand,0 },
    { "instate",	TtkWidgetInstateCommand,0 },
    { "selection", 	0,EntrySelectionCommands },
    { "set", 		EntrySetCommand,0 },
    { "state",  	TtkWidgetStateCommand,0 },
    { "set", 		EntrySetCommand,0 },
    { "style",		TtkWidgetStyleCommand,0 },
    { "validate",	EntryValidateCommand,0 },
    { "xview", 		EntryXViewCommand,0 },
    { 0,0,0 }
};

static WidgetSpec SpinboxWidgetSpec = {
static const WidgetSpec SpinboxWidgetSpec = {
    "TSpinbox",			/* className */
    sizeof(Spinbox), 		/* recordSize */
    SpinboxOptionSpecs,		/* optionSpecs */
    SpinboxCommands,  		/* subcommands */
    SpinboxInitialize,     	/* initializeProc */
    EntryCleanup,		/* cleanupProc */
    SpinboxConfigure,		/* configureProc */
2020
2021
2022
2023
2024
2025
2026
2027

2028
2029

2030
2031
2032


2033
2034
2035
2036

2037
2038
2039

2040
2041
2042
2043


2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054

2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075

2076
2077
2078
2079
2080
2081
2082
2058
2059
2060
2061
2062
2063
2064

2065
2066

2067
2068


2069
2070
2071
2072
2073

2074
2075
2076

2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093

2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114

2115
2116
2117
2118
2119
2120
2121
2122







-
+

-
+

-
-
+
+



-
+


-
+




+
+










-
+




















-
+







 */

typedef struct {
    Tcl_Obj	*fontObj;
    Tcl_Obj	*widthObj;
} TextareaElement;

static Ttk_ElementOptionSpec TextareaElementOptions[] = {
static const Ttk_ElementOptionSpec TextareaElementOptions[] = {
    { "-font", TK_OPTION_FONT,
	Tk_Offset(TextareaElement,fontObj), DEF_ENTRY_FONT },
	offsetof(TextareaElement,fontObj), DEF_ENTRY_FONT },
    { "-width", TK_OPTION_INT,
	Tk_Offset(TextareaElement,widthObj), "20" },
    { NULL, 0, 0, NULL }
	offsetof(TextareaElement,widthObj), "20" },
    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
};

static void TextareaElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    TextareaElement *textarea = elementRecord;
    TextareaElement *textarea = (TextareaElement *)elementRecord;
    Tk_Font font = Tk_GetFontFromObj(tkwin, textarea->fontObj);
    int avgWidth = Tk_TextWidth(font, "0", 1);
    Tk_FontMetrics fm;
    int prefWidth = 1;
    (void)dummy;
    (void)paddingPtr;

    Tk_GetFontMetrics(font, &fm);
    Tcl_GetIntFromObj(NULL, textarea->widthObj, &prefWidth);
    if (prefWidth <= 0)
	prefWidth = 1;

    *heightPtr = fm.linespace;
    *widthPtr = prefWidth * avgWidth;
}

static Ttk_ElementSpec TextareaElementSpec = {
static const Ttk_ElementSpec TextareaElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(TextareaElement),
    TextareaElementOptions,
    TextareaElementSize,
    TtkNullElementDraw
};

/*------------------------------------------------------------------------
 * +++ Widget layouts.
 */

TTK_BEGIN_LAYOUT(EntryLayout)
    TTK_GROUP("Entry.field", TTK_FILL_BOTH|TTK_BORDER,
	TTK_GROUP("Entry.padding", TTK_FILL_BOTH,
	    TTK_NODE("Entry.textarea", TTK_FILL_BOTH)))
TTK_END_LAYOUT

TTK_BEGIN_LAYOUT(ComboboxLayout)
    TTK_GROUP("Combobox.field", TTK_FILL_BOTH,
	TTK_NODE("Combobox.downarrow", TTK_PACK_RIGHT|TTK_FILL_Y)
	TTK_GROUP("Combobox.padding", TTK_FILL_BOTH|TTK_PACK_LEFT|TTK_EXPAND,
	TTK_GROUP("Combobox.padding", TTK_FILL_BOTH,
	    TTK_NODE("Combobox.textarea", TTK_FILL_BOTH)))
TTK_END_LAYOUT

TTK_BEGIN_LAYOUT(SpinboxLayout)
     TTK_GROUP("Spinbox.field", TTK_PACK_TOP|TTK_FILL_X,
	 TTK_GROUP("null", TTK_PACK_RIGHT,
	     TTK_NODE("Spinbox.uparrow", TTK_PACK_TOP|TTK_STICK_E)
Changes to generic/ttk/ttkFrame.c.
1
2

3
4
5
6
7

8
9
10
11
12
13
14
15
1

2
3
4
5
6

7

8
9
10
11
12
13
14

-
+




-
+
-







/*
 * Copyright (c) 2004, Joe English
 * Copyright © 2004 Joe English
 *
 * ttk::frame and ttk::labelframe widgets.
 */

#include <tk.h>
#include "tkInt.h"

#include "ttkTheme.h"
#include "ttkWidget.h"
#include "ttkManager.h"

/* ======================================================================
 * +++ Frame widget:
 */
23
24
25
26
27
28
29
30

31
32

33
34
35

36
37
38

39
40
41

42
43
44

45
46
47
48
49
50
51

52
53

54
55
56

57
58
59
60
61
62
63
22
23
24
25
26
27
28

29
30

31
32
33

34
35
36

37
38
39

40
41
42

43
44
45
46
47
48
49
50
51
52

53
54
55

56
57
58
59
60
61
62
63







-
+

-
+


-
+


-
+


-
+


-
+







+

-
+


-
+







} FramePart;

typedef struct {
    WidgetCore	core;
    FramePart	frame;
} Frame;

static Tk_OptionSpec FrameOptionSpecs[] = {
static const Tk_OptionSpec FrameOptionSpecs[] = {
    {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", NULL,
	Tk_Offset(Frame,frame.borderWidthObj), -1,
	offsetof(Frame,frame.borderWidthObj), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },
    {TK_OPTION_STRING, "-padding", "padding", "Pad", NULL,
	Tk_Offset(Frame,frame.paddingObj), -1,
	offsetof(Frame,frame.paddingObj), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },
    {TK_OPTION_RELIEF, "-relief", "relief", "Relief", NULL,
	Tk_Offset(Frame,frame.reliefObj), -1,
	offsetof(Frame,frame.reliefObj), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK,0,0 },
    {TK_OPTION_PIXELS, "-width", "width", "Width", "0",
	Tk_Offset(Frame,frame.widthObj), -1,
	offsetof(Frame,frame.widthObj), TCL_INDEX_NONE,
	0,0,GEOMETRY_CHANGED },
    {TK_OPTION_PIXELS, "-height", "height", "Height", "0",
	Tk_Offset(Frame,frame.heightObj), -1,
	offsetof(Frame,frame.heightObj), TCL_INDEX_NONE,
	0,0,GEOMETRY_CHANGED },

    WIDGET_TAKEFOCUS_FALSE,
    WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs)
};

static const Ttk_Ensemble FrameCommands[] = {
    { "cget",   	TtkWidgetCgetCommand,0 },
    { "configure",	TtkWidgetConfigureCommand,0 },
    { "cget",   	TtkWidgetCgetCommand,0 },
    { "identify",	TtkWidgetIdentifyCommand,0 },
    { "instate",	TtkWidgetInstateCommand,0 },
    { "state",  	TtkWidgetStateCommand,0 },
    { "identify",	TtkWidgetIdentifyCommand,0 },
    { "style",		TtkWidgetStyleCommand,0 },
    { 0,0,0 }
};

/*
 * FrameMargins --
 * 	Compute internal margins for a frame widget.
 * 	This includes the -borderWidth, plus any additional -padding.
85
86
87
88
89
90
91
92




93
94

95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115

116
117
118
119
120
121
122
85
86
87
88
89
90
91

92
93
94
95
96

97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117

118
119
120
121
122
123
124
125







-
+
+
+
+

-
+




















-
+







    return margins;
}

/* FrameSize procedure --
 * 	The frame doesn't request a size of its own by default,
 * 	but it does have an internal border.  See also <<NOTE-SIZE>>
 */
static int FrameSize(void *recordPtr, int *widthPtr, int *heightPtr)
static int FrameSize(
    void *recordPtr,
    TCL_UNUSED(int *),
    TCL_UNUSED(int *))
{
    Frame *framePtr = recordPtr;
    Frame *framePtr = (Frame *)recordPtr;
    Ttk_SetMargins(framePtr->core.tkwin, FrameMargins(framePtr));
    return 0;
}

/*
 * FrameConfigure -- configure hook.
 *	<<NOTE-SIZE>> Usually the size of a frame is controlled by
 *	a geometry manager (pack, grid); the -width and -height
 *	options are only effective if geometry propagation is turned
 *	off or if the [place] GM is used for child widgets.
 *
 *	To avoid geometry blinking, we issue a geometry request
 *	in the Configure hook instead of the Size hook, and only
 *	if -width and/or -height is nonzero and one of them
 *	or the other size-related options (-borderwidth, -padding)
 *	has been changed.
 */

static int FrameConfigure(Tcl_Interp *interp, void *recordPtr, int mask)
{
    Frame *framePtr = recordPtr;
    Frame *framePtr = (Frame *)recordPtr;
    int width, height;

    /*
     * Make sure -padding resource, if present, is correct:
     */
    if (framePtr->frame.paddingObj) {
	Ttk_Padding unused;
142
143
144
145
146
147
148
149

150
151
152
153
154
155
156
145
146
147
148
149
150
151

152
153
154
155
156
157
158
159







-
+







    if ((width > 0 || height > 0) && (mask & GEOMETRY_CHANGED)) {
	Tk_GeometryRequest(framePtr->core.tkwin, width, height);
    }

    return TtkCoreConfigure(interp, recordPtr, mask);
}

static WidgetSpec FrameWidgetSpec = {
static const WidgetSpec FrameWidgetSpec = {
    "TFrame",			/* className */
    sizeof(Frame),		/* recordSize */
    FrameOptionSpecs,		/* optionSpecs */
    FrameCommands,		/* subcommands */
    TtkNullInitialize,		/* initializeProc */
    TtkNullCleanup,		/* cleanupProc */
    FrameConfigure,		/* configureProc */
244
245
246
247
248
249
250
251

252
253

254
255
256

257
258
259

260
261
262

263
264
265
266
267
268
269
247
248
249
250
251
252
253

254
255

256
257
258

259
260
261

262
263
264

265
266
267
268
269
270
271
272







-
+

-
+


-
+


-
+


-
+







    WidgetCore  	core;
    FramePart   	frame;
    LabelframePart	label;
} Labelframe;

#define LABELWIDGET_CHANGED 0x100

static Tk_OptionSpec LabelframeOptionSpecs[] = {
static const Tk_OptionSpec LabelframeOptionSpecs[] = {
    {TK_OPTION_STRING, "-labelanchor", "labelAnchor", "LabelAnchor",
	"nw", Tk_Offset(Labelframe, label.labelAnchorObj),-1,
	"nw", offsetof(Labelframe, label.labelAnchorObj),TCL_INDEX_NONE,
        0,0,GEOMETRY_CHANGED},
    {TK_OPTION_STRING, "-text", "text", "Text", "",
	Tk_Offset(Labelframe,label.textObj), -1,
	offsetof(Labelframe,label.textObj), TCL_INDEX_NONE,
	0,0,GEOMETRY_CHANGED },
    {TK_OPTION_INT, "-underline", "underline", "Underline",
	"-1", Tk_Offset(Labelframe,label.underlineObj), -1,
	"-1", offsetof(Labelframe,label.underlineObj), TCL_INDEX_NONE,
	0,0,0 },
    {TK_OPTION_WINDOW, "-labelwidget", "labelWidget", "LabelWidget", NULL,
	-1, Tk_Offset(Labelframe,label.labelWidget),
	TCL_INDEX_NONE, offsetof(Labelframe,label.labelWidget),
	TK_OPTION_NULL_OK,0,LABELWIDGET_CHANGED|GEOMETRY_CHANGED },

    WIDGET_INHERIT_OPTIONS(FrameOptionSpecs)
};

/*
 * Labelframe style parameters:
334
335
336
337
338
339
340
341




342
343

344
345
346
347
348
349
350
337
338
339
340
341
342
343

344
345
346
347
348

349
350
351
352
353
354
355
356







-
+
+
+
+

-
+







}

/*
 * LabelframeSize --
 * 	Like the frame, this doesn't request a size of its own
 * 	but it does have internal padding and a minimum size.
 */
static int LabelframeSize(void *recordPtr, int *widthPtr, int *heightPtr)
static int LabelframeSize(
    void *recordPtr,
    TCL_UNUSED(int *),
    TCL_UNUSED(int *))
{
    Labelframe *lframePtr = recordPtr;
    Labelframe *lframePtr = (Labelframe *)recordPtr;
    WidgetCore *corePtr = &lframePtr->core;
    Ttk_Padding margins;
    LabelframeStyle style;
    int labelWidth, labelHeight;

    LabelframeStyleOptions(lframePtr, &style);

381
382
383
384
385
386
387
388

389
390
391
392
393
394
395
387
388
389
390
391
392
393

394
395
396
397
398
399
400
401







-
+







 * LabelframeGetLayout --
 * 	Getlayout widget hook.
 */

static Ttk_Layout LabelframeGetLayout(
    Tcl_Interp *interp, Ttk_Theme theme, void *recordPtr)
{
    Labelframe *lf = recordPtr;
    Labelframe *lf = (Labelframe *)recordPtr;
    Ttk_Layout frameLayout = TtkWidgetGetLayout(interp, theme, recordPtr);
    Ttk_Layout labelLayout;

    if (!frameLayout) {
	return NULL;
    }

412
413
414
415
416
417
418
419

420
421
422
423
424
425
426
418
419
420
421
422
423
424

425
426
427
428
429
430
431
432







-
+







 * 	Labelframe layout hook.
 *
 * Side effects: Computes labelParcel.
 */

static void LabelframeDoLayout(void *recordPtr)
{
    Labelframe *lframePtr = recordPtr;
    Labelframe *lframePtr = (Labelframe *)recordPtr;
    WidgetCore *corePtr = &lframePtr->core;
    int lw, lh;			/* Label width and height */
    LabelframeStyle style;
    Ttk_Box borderParcel = Ttk_WinBox(lframePtr->core.tkwin);
    Ttk_Box labelParcel;

    /*
452
453
454
455
456
457
458
459

460
461
462
463
464
465

466
467
468
469
470
471
472
473
474
475

476
477
478

479
480

481
482

483
484
485
486
487


488
489
490
491





492
493
494
495
496
497
498
499
500
501

502
503



504
505


506
507
508
509
510

511
512

513
514
515
516
517
518
519
520



521
522

523
524
525
526
527
528
529
530
531
532
533
534
535
536

537
538
539
540
541
542
543
458
459
460
461
462
463
464

465
466
467
468
469
470

471
472
473
474
475
476
477
478
479
480

481
482
483

484
485

486
487

488
489
490
491


492
493
494
495
496

497
498
499
500
501
502
503
504
505
506
507
508
509
510

511
512

513
514
515
516

517
518
519
520
521
522

523
524

525
526
527
528
529
530
531
532

533
534
535
536

537
538
539
540
541
542
543
544
545
546
547
548
549
550

551
552
553
554
555
556
557
558







-
+





-
+









-
+


-
+

-
+

-
+



-
-
+
+



-
+
+
+
+
+









-
+

-
+
+
+

-
+
+




-
+

-
+







-
+
+
+

-
+













-
+







     * Place border and label:
     */
    Ttk_PlaceLayout(corePtr->layout, corePtr->state, borderParcel);
    if (lframePtr->label.labelLayout) {
	Ttk_PlaceLayout(
	    lframePtr->label.labelLayout, corePtr->state, labelParcel);
    }
    /* labelWidget placed in LabelframePlaceSlaves GM hook */
    /* labelWidget placed in LabelframePlaceContent GM hook */
    lframePtr->label.labelParcel = labelParcel;
}

static void LabelframeDisplay(void *recordPtr, Drawable d)
{
    Labelframe *lframePtr = recordPtr;
    Labelframe *lframePtr = (Labelframe *)recordPtr;
    Ttk_DrawLayout(lframePtr->core.layout, lframePtr->core.state, d);
    if (lframePtr->label.labelLayout) {
	Ttk_DrawLayout(lframePtr->label.labelLayout, lframePtr->core.state, d);
    }
}

/* +++ Labelframe geometry manager hooks.
 */

/* LabelframePlaceSlaves --
/* LabelframePlaceContent --
 * 	Sets the position and size of the labelwidget.
 */
static void LabelframePlaceSlaves(void *recordPtr)
static void LabelframePlaceContent(void *recordPtr)
{
    Labelframe *lframe = recordPtr;
    Labelframe *lframe = (Labelframe *)recordPtr;

    if (Ttk_NumberSlaves(lframe->label.mgr) == 1) {
    if (Ttk_NumberContent(lframe->label.mgr) == 1) {
	Ttk_Box b;
	LabelframeDoLayout(recordPtr);
	b = lframe->label.labelParcel;
	/* ASSERT: slave #0 is lframe->label.labelWidget */
	Ttk_PlaceSlave(lframe->label.mgr, 0, b.x,b.y,b.width,b.height);
	/* ASSERT: content #0 is lframe->label.labelWidget */
	Ttk_PlaceContent(lframe->label.mgr, 0, b.x,b.y,b.width,b.height);
    }
}

static int LabelRequest(void *managerData, int index, int width, int height)
static int LabelRequest(
    TCL_UNUSED(void *),
    TCL_UNUSED(TkSizeT),
    TCL_UNUSED(int),
    TCL_UNUSED(int))
{
    return 1;
}

/* LabelRemoved --
 * 	Unset the -labelwidget option.
 *
 * <<NOTE-LABELREMOVED>>:
 * 	This routine is also called when the widget voluntarily forgets
 * 	the slave in LabelframeConfigure.
 * 	the window in LabelframeConfigure.
 */
static void LabelRemoved(void *managerData, int slaveIndex)
static void LabelRemoved(
    void *managerData,
    TCL_UNUSED(TkSizeT))
{
    Labelframe *lframe = managerData;
    Labelframe *lframe = (Labelframe *)managerData;

    lframe->label.labelWidget = 0;
}

static Ttk_ManagerSpec LabelframeManagerSpec = {
    { "labelframe", Ttk_GeometryRequestProc, Ttk_LostSlaveProc },
    { "labelframe", Ttk_GeometryRequestProc, Ttk_LostContentProc },
    LabelframeSize,
    LabelframePlaceSlaves,
    LabelframePlaceContent,
    LabelRequest,
    LabelRemoved
};

/* LabelframeInitialize --
 * 	Initialization hook.
 */
static void LabelframeInitialize(Tcl_Interp *interp, void *recordPtr)
static void LabelframeInitialize(
    TCL_UNUSED(Tcl_Interp *),
    void *recordPtr)
{
    Labelframe *lframe = recordPtr;
    Labelframe *lframe = (Labelframe *)recordPtr;

    lframe->label.mgr = Ttk_CreateManager(
	&LabelframeManagerSpec, lframe, lframe->core.tkwin);
    lframe->label.labelWidget = 0;
    lframe->label.labelLayout = 0;
    lframe->label.labelParcel = Ttk_MakeBox(-1,-1,-1,-1);
}

/* LabelframeCleanup --
 * 	Cleanup hook.
 */
static void LabelframeCleanup(void *recordPtr)
{
    Labelframe *lframe = recordPtr;
    Labelframe *lframe = (Labelframe *)recordPtr;
    Ttk_DeleteManager(lframe->label.mgr);
    if (lframe->label.labelLayout) {
	Ttk_FreeLayout(lframe->label.labelLayout);
    }
}

/* RaiseLabelWidget --
560
561
562
563
564
565
566
567

568
569
570
571
572
573
574
575
576
577
578
579
580
581

582
583
584
585
586
587
588
589







-
+







}

/* LabelframeConfigure --
 * 	Configuration hook.
 */
static int LabelframeConfigure(Tcl_Interp *interp,void *recordPtr,int mask)
{
    Labelframe *lframePtr = recordPtr;
    Labelframe *lframePtr = (Labelframe *)recordPtr;
    Tk_Window labelWidget = lframePtr->label.labelWidget;
    Ttk_PositionSpec unused;

    /* Validate options:
     */
    if (mask & LABELWIDGET_CHANGED && labelWidget != NULL) {
	if (!Ttk_Maintainable(interp, labelWidget, lframePtr->core.tkwin)) {
587
588
589
590
591
592
593
594
595


596
597
598
599
600
601
602

603
604
605
606
607
608
609
610
611
612
613
614
615

616
617
618
619
620
621
622
602
603
604
605
606
607
608


609
610
611
612
613
614
615
616

617
618
619
620
621
622
623
624
625
626
627
628
629

630
631
632
633
634
635
636
637







-
-
+
+






-
+












-
+







    if (FrameConfigure(interp, recordPtr, mask) != TCL_OK) {
	return TCL_ERROR;
    }

    /* Update -labelwidget changes, if any:
     */
    if (mask & LABELWIDGET_CHANGED) {
	if (Ttk_NumberSlaves(lframePtr->label.mgr) == 1) {
	    Ttk_ForgetSlave(lframePtr->label.mgr, 0);
	if (Ttk_NumberContent(lframePtr->label.mgr) == 1) {
	    Ttk_ForgetContent(lframePtr->label.mgr, 0);
	    /* Restore labelWidget field (see <<NOTE-LABELREMOVED>>)
	     */
	    lframePtr->label.labelWidget = labelWidget;
	}

	if (labelWidget) {
	    Ttk_InsertSlave(lframePtr->label.mgr, 0, labelWidget, NULL);
		Ttk_InsertContent(lframePtr->label.mgr, 0, labelWidget, NULL);
	    RaiseLabelWidget(lframePtr);
	}
    }

    if (mask & GEOMETRY_CHANGED) {
	Ttk_ManagerSizeChanged(lframePtr->label.mgr);
	Ttk_ManagerLayoutChanged(lframePtr->label.mgr);
    }

    return TCL_OK;
}

static WidgetSpec LabelframeWidgetSpec = {
static const WidgetSpec LabelframeWidgetSpec = {
    "TLabelframe",		/* className */
    sizeof(Labelframe),		/* recordSize */
    LabelframeOptionSpecs, 	/* optionSpecs */
    FrameCommands,		/* subcommands */
    LabelframeInitialize,	/* initializeProc */
    LabelframeCleanup,		/* cleanupProc */
    LabelframeConfigure,	/* configureProc */
Deleted generic/ttk/ttkGenStubs.tcl.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963



































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
# ttkGenStubs.tcl --
#
#	This script generates a set of stub files for a given
#	interface.
#
#
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright (c) 2007 Daniel A. Steffen <[email protected]>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# SOURCE: tcl/tools/genStubs.tcl, revision 1.44
#
# CHANGES:
#	+ Second argument to "declare" is used as a status guard
#	  instead of a platform guard.
#	+ Allow trailing semicolon in function declarations
#

namespace eval genStubs {
    # libraryName --
    #
    #	The name of the entire library.  This value is used to compute
    #	the USE_*_STUBS macro and the name of the init file.

    variable libraryName "UNKNOWN"

    # interfaces --
    #
    #	An array indexed by interface name that is used to maintain
    #   the set of valid interfaces.  The value is empty.

    array set interfaces {}

    # curName --
    #
    #	The name of the interface currently being defined.

    variable curName "UNKNOWN"

    # scspec --
    #
    #	Storage class specifier for external function declarations.
    #	Normally "EXTERN", may be set to something like XYZAPI
    #
    variable scspec "EXTERN"

    # epoch, revision --
    #
    #	The epoch and revision numbers of the interface currently being defined.
    #   (@@@TODO: should be an array mapping interface names -> numbers)
    #

    variable epoch {}
    variable revision 0

    # hooks --
    #
    #	An array indexed by interface name that contains the set of
    #	subinterfaces that should be defined for a given interface.

    array set hooks {}

    # stubs --
    #
    #	This three dimensional array is indexed first by interface name,
    #	second by field name, and third by a numeric offset or the
    #	constant "lastNum".  The lastNum entry contains the largest
    #	numeric offset used for a given interface.
    #
    #	Field "decl,$i" contains the C function specification that
    #	should be used for the given entry in the stub table.  The spec
    #	consists of a list in the form returned by parseDecl.
    #   Other fields TBD later.

    array set stubs {}

    # outDir --
    #
    #	The directory where the generated files should be placed.

    variable outDir .
}

# genStubs::library --
#
#	This function is used in the declarations file to set the name
#	of the library that the interfaces are associated with (e.g. "tcl").
#	This value will be used to define the inline conditional macro.
#
# Arguments:
#	name	The library name.
#
# Results:
#	None.

proc genStubs::library {name} {
    variable libraryName $name
}

# genStubs::interface --
#
#	This function is used in the declarations file to set the name
#	of the interface currently being defined.
#
# Arguments:
#	name	The name of the interface.
#
# Results:
#	None.

proc genStubs::interface {name} {
    variable curName $name
    variable interfaces
    variable stubs

    set interfaces($name) {}
    set stubs($name,lastNum) 0
    return
}

# genStubs::scspec --
#
#	Define the storage class macro used for external function declarations.
#	Typically, this will be a macro like XYZAPI or EXTERN that
#	expands to either DLLIMPORT or DLLEXPORT, depending on whether
#	-DBUILD_XYZ has been set.
#
proc genStubs::scspec {value} {
    variable scspec $value
}

# genStubs::epoch --
#
#	Define the epoch number for this library.  The epoch
#	should be incrememented when a release is made that
#	contains incompatible changes to the public API.
#
proc genStubs::epoch {value} {
    variable epoch $value
}

# genStubs::hooks --
#
#	This function defines the subinterface hooks for the current
#	interface.
#
# Arguments:
#	names	The ordered list of interfaces that are reachable through the
#		hook vector.
#
# Results:
#	None.

proc genStubs::hooks {names} {
    variable curName
    variable hooks

    set hooks($curName) $names
    return
}

# genStubs::declare --
#
#	This function is used in the declarations file to declare a new
#	interface entry.
#
# Arguments:
#	index		The index number of the interface.
#	status  	Status of the interface: one of "current",
#		  	"deprecated", or "obsolete".
#	decl		The C function declaration, or {} for an undefined
#			entry.
#
# Results:
#	None.

proc genStubs::declare {args} {
    variable stubs
    variable curName
    variable revision

    incr revision
    if {[llength $args] == 2} {
	lassign $args index decl
	set status current
    } elseif {[llength $args] == 3} {
	lassign $args index status decl
    } else {
	puts stderr "wrong # args: declare $args"
	return
    }

    # Check for duplicate declarations, then add the declaration and
    # bump the lastNum counter if necessary.

    if {[info exists stubs($curName,decl,$index)]} {
	puts stderr "Duplicate entry: $index"
    }
    regsub -all "\[ \t\n\]+" [string trim $decl] " " decl
    set decl [parseDecl $decl]

    set stubs($curName,status,$index) $status
    set stubs($curName,decl,$index) $decl

    if {$index > $stubs($curName,lastNum)} {
	set stubs($curName,lastNum) $index
    }
    return
}

# genStubs::export --
#
#	This function is used in the declarations file to declare a symbol
#	that is exported from the library but is not in the stubs table.
#
# Arguments:
#	decl		The C function declaration, or {} for an undefined
#			entry.
#
# Results:
#	None.

proc genStubs::export {args} {
    if {[llength $args] != 1} {
	puts stderr "wrong # args: export $args"
    }
    return
}

# genStubs::rewriteFile --
#
#	This function replaces the machine generated portion of the
#	specified file with new contents.  It looks for the !BEGIN! and
#	!END! comments to determine where to place the new text.
#
# Arguments:
#	file	The name of the file to modify.
#	text	The new text to place in the file.
#
# Results:
#	None.

proc genStubs::rewriteFile {file text} {
    if {![file exists $file]} {
	puts stderr "Cannot find file: $file"
	return
    }
    set in [open ${file} r]
    set out [open ${file}.new w]
    fconfigure $out -translation lf

    while {![eof $in]} {
	set line [gets $in]
	if {[string match "*!BEGIN!*" $line]} {
	    break
	}
	puts $out $line
    }
    puts $out "/* !BEGIN!: Do not edit below this line. */"
    puts $out $text
    while {![eof $in]} {
	set line [gets $in]
	if {[string match "*!END!*" $line]} {
	    break
	}
    }
    puts $out "/* !END!: Do not edit above this line. */"
    puts -nonewline $out [read $in]
    close $in
    close $out
    file rename -force ${file}.new ${file}
    return
}

# genStubs::addPlatformGuard --
#
#	Wrap a string inside a platform #ifdef.
#
# Arguments:
#	plat	Platform to test.
#
# Results:
#	Returns the original text inside an appropriate #ifdef.

proc genStubs::addPlatformGuard {plat iftxt {eltxt {}}} {
    set text ""
    switch $plat {
	win {
	    append text "#ifdef _WIN32 /* WIN */\n${iftxt}"
	    if {$eltxt ne ""} {
		append text "#else /* WIN */\n${eltxt}"
	    }
	    append text "#endif /* WIN */\n"
	}
	unix {
	    append text "#if !defined(_WIN32) && !defined(MAC_OSX_TCL)\
		    /* UNIX */\n${iftxt}"
	    if {$eltxt ne ""} {
		append text "#else /* UNIX */\n${eltxt}"
	    }
	    append text "#endif /* UNIX */\n"
	}
	macosx {
	    append text "#ifdef MAC_OSX_TCL /* MACOSX */\n${iftxt}"
	    if {$eltxt ne ""} {
		append text "#else /* MACOSX */\n${eltxt}"
	    }
	    append text "#endif /* MACOSX */\n"
	}
	aqua {
	    append text "#ifdef MAC_OSX_TK /* AQUA */\n${iftxt}"
	    if {$eltxt ne ""} {
		append text "#else /* AQUA */\n${eltxt}"
	    }
	    append text "#endif /* AQUA */\n"
	}
	x11 {
	    append text "#if !(defined(_WIN32) || defined(MAC_OSX_TK))\
		    /* X11 */\n${iftxt}"
	    if {$eltxt ne ""} {
		append text "#else /* X11 */\n${eltxt}"
	    }
	    append text "#endif /* X11 */\n"
	}
	default {
	    append text "${iftxt}${eltxt}"
	}
    }
    return $text
}

# genStubs::emitSlots --
#
#	Generate the stub table slots for the given interface.  If there
#	are no generic slots, then one table is generated for each
#	platform, otherwise one table is generated for all platforms.
#
# Arguments:
#	name	The name of the interface being emitted.
#	textVar	The variable to use for output.
#
# Results:
#	None.

proc genStubs::emitSlots {name textVar} {
    upvar $textVar text

    forAllStubs $name makeSlot noGuard text {"    void (*reserved$i)(void);\n"}
    return
}

# genStubs::parseDecl --
#
#	Parse a C function declaration into its component parts.
#
# Arguments:
#	decl	The function declaration.
#
# Results:
#	Returns a list of the form {returnType name args}.  The args
#	element consists of a list of type/name pairs, or a single
#	element "void".  If the function declaration is malformed
#	then an error is displayed and the return value is {}.

proc genStubs::parseDecl {decl} {
    if {![regexp {^(.*)\((.*)\);?$} $decl all prefix args]} {
	set prefix $decl
	set args {}
    }
    set prefix [string trim $prefix]
    if {![regexp {^(.+[ ][*]*)([^ *]+)$} $prefix all rtype fname]} {
	puts stderr "Bad return type: $decl"
	return
    }
    set rtype [string trim $rtype]
    if {$args eq ""} {
	return [list $rtype $fname {}]
    }
    foreach arg [split $args ,] {
	lappend argList [string trim $arg]
    }
    if {![string compare [lindex $argList end] "..."]} {
	set args TCL_VARARGS
	foreach arg [lrange $argList 0 end-1] {
	    set argInfo [parseArg $arg]
	    if {[llength $argInfo] == 2 || [llength $argInfo] == 3} {
		lappend args $argInfo
	    } else {
		puts stderr "Bad argument: '$arg' in '$decl'"
		return
	    }
	}
    } else {
	set args {}
	foreach arg $argList {
	    set argInfo [parseArg $arg]
	    if {![string compare $argInfo "void"]} {
		lappend args "void"
		break
	    } elseif {[llength $argInfo] == 2 || [llength $argInfo] == 3} {
		lappend args $argInfo
	    } else {
		puts stderr "Bad argument: '$arg' in '$decl'"
		return
	    }
	}
    }
    return [list $rtype $fname $args]
}

# genStubs::parseArg --
#
#	This function parses a function argument into a type and name.
#
# Arguments:
#	arg	The argument to parse.
#
# Results:
#	Returns a list of type and name with an optional third array
#	indicator.  If the argument is malformed, returns "".

proc genStubs::parseArg {arg} {
    if {![regexp {^(.+[ ][*]*)([^][ *]+)(\[\])?$} $arg all type name array]} {
	if {$arg eq "void"} {
	    return $arg
	} else {
	    return
	}
    }
    set result [list [string trim $type] $name]
    if {$array ne ""} {
	lappend result $array
    }
    return $result
}

# genStubs::makeDecl --
#
#	Generate the prototype for a function.
#
# Arguments:
#	name	The interface name.
#	decl	The function declaration.
#	index	The slot index for this function.
#
# Results:
#	Returns the formatted declaration string.

proc genStubs::makeDecl {name decl index} {
    variable scspec
    lassign $decl rtype fname args

    append text "/* $index */\n"
    set line "$scspec $rtype"
    set count [expr {2 - ([string length $line] / 8)}]
    append line [string range "\t\t\t" 0 $count]
    set pad [expr {24 - [string length $line]}]
    if {$pad <= 0} {
	append line " "
	set pad 0
    }
    if {$args eq ""} {
	append line $fname
	append text $line
	append text ";\n"
	return $text
    }
    append line $fname

    set arg1 [lindex $args 0]
    switch -exact $arg1 {
	void {
	    append line "(void)"
	}
	TCL_VARARGS {
	    set sep "("
	    foreach arg [lrange $args 1 end] {
		append line $sep
		set next {}
		append next [lindex $arg 0]
		if {[string index $next end] ne "*"} {
		    append next " "
		}
		append next [lindex $arg 1] [lindex $arg 2]
		if {[string length $line] + [string length $next] \
			+ $pad > 76} {
		    append text [string trimright $line] \n
		    set line "\t\t\t\t"
		    set pad 28
		}
		append line $next
		set sep ", "
	    }
	    append line ", ...)"
	}
	default {
	    set sep "("
	    foreach arg $args {
		append line $sep
		set next {}
		append next [lindex $arg 0]
		if {[string index $next end] ne "*"} {
		    append next " "
		}
		append next [lindex $arg 1] [lindex $arg 2]
		if {[string length $line] + [string length $next] \
			+ $pad > 76} {
		    append text [string trimright $line] \n
		    set line "\t\t\t\t"
		    set pad 28
		}
		append line $next
		set sep ", "
	    }
	    append line ")"
	}
    }
    return "$text$line;\n"
}

# genStubs::makeMacro --
#
#	Generate the inline macro for a function.
#
# Arguments:
#	name	The interface name.
#	decl	The function declaration.
#	index	The slot index for this function.
#
# Results:
#	Returns the formatted macro definition.

proc genStubs::makeMacro {name decl index} {
    lassign $decl rtype fname args

    set lfname [string tolower [string index $fname 0]]
    append lfname [string range $fname 1 end]

    set text "#define $fname \\\n\t("
    if {$args eq ""} {
	append text "*"
    }
    append text "${name}StubsPtr->$lfname)"
    append text " /* $index */\n"
    return $text
}

# genStubs::makeSlot --
#
#	Generate the stub table entry for a function.
#
# Arguments:
#	name	The interface name.
#	decl	The function declaration.
#	index	The slot index for this function.
#
# Results:
#	Returns the formatted table entry.

proc genStubs::makeSlot {name decl index} {
    lassign $decl rtype fname args

    set lfname [string tolower [string index $fname 0]]
    append lfname [string range $fname 1 end]

    set text "    "
    if {$args eq ""} {
	append text $rtype " *" $lfname "; /* $index */\n"
	return $text
    }
    if {[string range $rtype end-8 end] eq "__stdcall"} {
	append text [string trim [string range $rtype 0 end-9]] " (__stdcall *" $lfname ") "
    } else {
	append text $rtype " (*" $lfname ") "
    }
    set arg1 [lindex $args 0]
    switch -exact $arg1 {
	void {
	    append text "(void)"
	}
	TCL_VARARGS {
	    set sep "("
	    foreach arg [lrange $args 1 end] {
		append text $sep [lindex $arg 0]
		if {[string index $text end] ne "*"} {
		    append text " "
		}
		append text [lindex $arg 1] [lindex $arg 2]
		set sep ", "
	    }
	    append text ", ...)"
	}
	default {
	    set sep "("
	    foreach arg $args {
		append text $sep [lindex $arg 0]
		if {[string index $text end] ne "*"} {
		    append text " "
		}
		append text [lindex $arg 1] [lindex $arg 2]
		set sep ", "
	    }
	    append text ")"
	}
    }

    append text "; /* $index */\n"
    return $text
}

# genStubs::makeInit --
#
#	Generate the prototype for a function.
#
# Arguments:
#	name	The interface name.
#	decl	The function declaration.
#	index	The slot index for this function.
#
# Results:
#	Returns the formatted declaration string.

proc genStubs::makeInit {name decl index} {
    if {[lindex $decl 2] eq ""} {
	append text "    &" [lindex $decl 1] ", /* " $index " */\n"
    } else {
	append text "    " [lindex $decl 1] ", /* " $index " */\n"
    }
    return $text
}

# genStubs::forAllStubs --
#
#	This function iterates over all of the slots and invokes
#	a callback for each slot.  The result of the callback is then
#	placed inside appropriate guards.
#
# Arguments:
#	name		The interface name.
#	slotProc	The proc to invoke to handle the slot.  It will
#			have the interface name, the declaration,  and
#			the index appended.
#	guardProc	The proc to invoke to add guards.  It will have
#		        the slot status and text appended.
#	textVar		The variable to use for output.
#	skipString	The string to emit if a slot is skipped.  This
#			string will be subst'ed in the loop so "$i" can
#			be used to substitute the index value.
#
# Results:
#	None.

proc genStubs::forAllStubs {name slotProc guardProc textVar
	{skipString {"/* Slot $i is reserved */\n"}}} {
    variable stubs
    upvar $textVar text

    set lastNum $stubs($name,lastNum)

    for {set i 0} {$i <= $lastNum} {incr i} {
	if {[info exists stubs($name,decl,$i)]} {
	    append text [$guardProc $stubs($name,status,$i) \
	    			[$slotProc $name $stubs($name,decl,$i) $i]]
	} else {
	    eval {append text} $skipString
	}
    }
}

proc genStubs::noGuard  {status text} { return $text }

proc genStubs::addGuard {status text} {
    variable libraryName
    set upName [string toupper $libraryName]

    switch -- $status {
	current	{
	    # No change
	}
	deprecated {
	    set text [ifdeffed "${upName}_DEPRECATED" $text]
	}
	obsolete {
	    set text ""
	}
	default {
	    puts stderr "Unrecognized status code $status"
	}
    }
    return $text
}

proc genStubs::ifdeffed {macro text} {
    join [list "#ifdef $macro" $text "#endif" ""] \n
}

# genStubs::emitDeclarations --
#
#	This function emits the function declarations for this interface.
#
# Arguments:
#	name	The interface name.
#	textVar	The variable to use for output.
#
# Results:
#	None.

proc genStubs::emitDeclarations {name textVar} {
    upvar $textVar text

    append text "\n/*\n * Exported function declarations:\n */\n\n"
    forAllStubs $name makeDecl noGuard text
    return
}

# genStubs::emitMacros --
#
#	This function emits the inline macros for an interface.
#
# Arguments:
#	name	The name of the interface being emitted.
#	textVar	The variable to use for output.
#
# Results:
#	None.

proc genStubs::emitMacros {name textVar} {
    variable libraryName
    upvar $textVar text

    set upName [string toupper $libraryName]
    append text "\n#if defined(USE_${upName}_STUBS)\n"
    append text "\n/*\n * Inline function declarations:\n */\n\n"

    forAllStubs $name makeMacro addGuard text

    append text "\n#endif /* defined(USE_${upName}_STUBS) */\n"
    return
}

# genStubs::emitHeader --
#
#	This function emits the body of the <name>Decls.h file for
#	the specified interface.
#
# Arguments:
#	name	The name of the interface being emitted.
#
# Results:
#	None.

proc genStubs::emitHeader {name} {
    variable outDir
    variable hooks
    variable epoch
    variable revision

    set capName [string toupper [string index $name 0]]
    append capName [string range $name 1 end]

    if {$epoch ne ""} {
	set CAPName [string toupper $name]
	append text "\n"
	append text "#define ${CAPName}_STUBS_EPOCH $epoch\n"
	append text "#define ${CAPName}_STUBS_REVISION $revision\n"
    }

    append text "\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n"

    emitDeclarations $name text

    if {[info exists hooks($name)]} {
	append text "\ntypedef struct {\n"
	foreach hook $hooks($name) {
	    set capHook [string toupper [string index $hook 0]]
	    append capHook [string range $hook 1 end]
	    append text "    const struct ${capHook}Stubs *${hook}Stubs;\n"
	}
	append text "} ${capName}StubHooks;\n"
    }
    append text "\ntypedef struct ${capName}Stubs {\n"
    append text "    int magic;\n"
    if {$epoch ne ""} {
	append text "    int epoch;\n"
	append text "    int revision;\n"
    }
    if {[info exists hooks($name)]} {
	append text "    const ${capName}StubHooks *hooks;\n\n"
    } else {
	append text "    void *hooks;\n\n"
    }

    emitSlots $name text

    append text "} ${capName}Stubs;\n\n"

    append text "extern const ${capName}Stubs *${name}StubsPtr;\n\n"
    append text "#ifdef __cplusplus\n}\n#endif\n"

    emitMacros $name text

    rewriteFile [file join $outDir ${name}Decls.h] $text
    return
}

# genStubs::emitInit --
#
#	Generate the table initializers for an interface.
#
# Arguments:
#	name		The name of the interface to initialize.
#	textVar		The variable to use for output.
#
# Results:
#	Returns the formatted output.

proc genStubs::emitInit {name textVar} {
    variable hooks
    variable interfaces
    variable epoch
    upvar $textVar text
    set root 1

    set capName [string toupper [string index $name 0]]
    append capName [string range $name 1 end]

    if {[info exists hooks($name)]} {
	append text "\nstatic const ${capName}StubHooks ${name}StubHooks = \{\n"
	set sep "    "
	foreach sub $hooks($name) {
	    append text $sep "&${sub}Stubs"
	    set sep ",\n    "
	}
	append text "\n\};\n"
    }
    foreach intf [array names interfaces] {
	if {[info exists hooks($intf)]} {
	    if {[lsearch -exact $hooks($intf) $name] >= 0} {
		set root 0
		break
	    }
	}
    }

    append text "\n"
    if {!$root} {
	append text "static "
    }
    append text "const ${capName}Stubs ${name}Stubs = \{\n    TCL_STUB_MAGIC,\n"
    if {$epoch ne ""} {
	set CAPName [string toupper $name]
	append text "    ${CAPName}_STUBS_EPOCH,\n"
	append text "    ${CAPName}_STUBS_REVISION,\n"
    }
    if {[info exists hooks($name)]} {
	append text "    &${name}StubHooks,\n"
    } else {
	append text "    0,\n"
    }

    forAllStubs $name makeInit noGuard text {"    0, /* $i */\n"}

    append text "\};\n"
    return
}

# genStubs::emitInits --
#
#	This function emits the body of the <name>StubInit.c file for
#	the specified interface.
#
# Arguments:
#	name	The name of the interface being emitted.
#
# Results:
#	None.

proc genStubs::emitInits {} {
    variable hooks
    variable outDir
    variable libraryName
    variable interfaces

    # Assuming that dependencies only go one level deep, we need to emit
    # all of the leaves first to avoid needing forward declarations.

    set leaves {}
    set roots {}
    foreach name [lsort [array names interfaces]] {
	if {[info exists hooks($name)]} {
	    lappend roots $name
	} else {
	    lappend leaves $name
	}
    }
    foreach name $leaves {
	emitInit $name text
    }
    foreach name $roots {
	emitInit $name text
    }

    rewriteFile [file join $outDir ${libraryName}StubInit.c] $text
}

# genStubs::init --
#
#	This is the main entry point.
#
# Arguments:
#	None.
#
# Results:
#	None.

proc genStubs::init {} {
    global argv argv0
    variable outDir
    variable interfaces

    if {[llength $argv] < 2} {
	puts stderr "usage: $argv0 outDir declFile ?declFile...?"
	exit 1
    }

    set outDir [lindex $argv 0]

    foreach file [lrange $argv 1 end] {
	source $file
    }

    foreach name [lsort [array names interfaces]] {
	puts "Emitting $name"
	emitHeader $name
    }

    emitInits
}

# lassign --
#
#	This function emulates the TclX lassign command.
#
# Arguments:
#	valueList	A list containing the values to be assigned.
#	args		The list of variables to be assigned.
#
# Results:
#	Returns any values that were not assigned to variables.

if {[string length [namespace which lassign]] == 0} {
    proc lassign {valueList args} {
	if {[llength $args] == 0} {
	    error "wrong # args: should be \"lassign list varName ?varName ...?\""
	}
	uplevel [list foreach $args $valueList {break}]
	return [lrange $valueList [llength $args] end]
    }
}

genStubs::init
Changes to generic/ttk/ttkImage.c.
1
2
3
4
5


6
7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

36
37









38
39
40
41
42
43
44
1
2
3


4
5
6
7
8
9
10
11
12


13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

34
35

36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51



-
-
+
+







-
-
+




















-
+

-
+
+
+
+
+
+
+
+
+







/*
 *	Image specifications and image element factory.
 *
 * Copyright (C) 2004 Pat Thoyts <[email protected]>
 * Copyright (C) 2004 Joe English
 * Copyright © 2004 Pat Thoyts <[email protected]>
 * 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].
 */

#include <string.h>
#include <tk.h>
#include "tkInt.h"
#include "ttkTheme.h"

#define MIN(a,b) ((a) < (b) ? (a) : (b))

/*------------------------------------------------------------------------
 * +++ ImageSpec management.
 */

struct TtkImageSpec {
    Tk_Image 		baseImage;	/* Base image to use */
    int 		mapCount;	/* #state-specific overrides */
    Ttk_StateSpec	*states;	/* array[mapCount] of states ... */
    Tk_Image		*images;	/* ... per-state images to use */
    Tk_ImageChangedProc *imageChanged;
    ClientData		imageChangedClientData;
};

/* NullImageChanged --
 * 	Do-nothing Tk_ImageChangedProc.
 */
static void NullImageChanged(ClientData clientData,
static void NullImageChanged(ClientData dummy,
    int x, int y, int width, int height, int imageWidth, int imageHeight)
{ /* No-op */ }
{ /* No-op */
    (void)dummy;
    (void)x;
    (void)y;
    (void)width;
    (void)height;
    (void)imageWidth;
    (void)imageHeight;
}

/* ImageSpecImageChanged --
 *     Image changes should trigger a repaint.
 */
static void ImageSpecImageChanged(ClientData clientData,
    int x, int y, int width, int height, int imageWidth, int imageHeight)
{
71
72
73
74
75
76
77
78

79
80
81
82
83
84
85
78
79
80
81
82
83
84

85
86
87
88
89
90
91
92







-
+







TtkGetImageSpecEx(Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr,
    Tk_ImageChangedProc *imageChangedProc, ClientData imageChangedClientData)
{
    Ttk_ImageSpec *imageSpec = 0;
    int i = 0, n = 0, objc;
    Tcl_Obj **objv;

    imageSpec = ckalloc(sizeof(*imageSpec));
    imageSpec = (Ttk_ImageSpec *)ckalloc(sizeof(*imageSpec));
    imageSpec->baseImage = 0;
    imageSpec->mapCount = 0;
    imageSpec->states = 0;
    imageSpec->images = 0;
    imageSpec->imageChanged = imageChangedProc;
    imageSpec->imageChangedClientData = imageChangedClientData;

94
95
96
97
98
99
100
101
102


103
104
105
106
107
108
109
101
102
103
104
105
106
107


108
109
110
111
112
113
114
115
116







-
-
+
+







		-1));
	    Tcl_SetErrorCode(interp, "TTK", "IMAGE", "SPEC", NULL);
	}
	goto error;
    }

    n = (objc - 1) / 2;
    imageSpec->states = ckalloc(n * sizeof(Ttk_StateSpec));
    imageSpec->images = ckalloc(n * sizeof(Tk_Image *));
    imageSpec->states = (Ttk_StateSpec *)ckalloc(n * sizeof(Ttk_StateSpec));
    imageSpec->images = (Tk_Image *)ckalloc(n * sizeof(Tk_Image));

    /* Get base image:
    */
    imageSpec->baseImage = Tk_GetImage(
	    interp, tkwin, Tcl_GetString(objv[0]), ImageSpecImageChanged, imageSpec);
    if (!imageSpec->baseImage) {
    	goto error;
202
203
204
205
206
207
208

209
210
211
212
213
214
215
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223







+







 */
static void Ttk_Fill(
    Tk_Window tkwin, Drawable d, Tk_Image image, Ttk_Box src, Ttk_Box dst)
{
    int dr = dst.x + dst.width;
    int db = dst.y + dst.height;
    int x,y;
    (void)tkwin;

    if (!(src.width && src.height && dst.width && dst.height))
	return;

    for (x = dst.x; x < dr; x += src.width) {
	int cw = MIN(src.width, dr - x);
	for (y = dst.y; y <= db; y += src.height) {
251
252
253
254
255
256
257
258

259
260
261
262
263
264
265
266

267
268

269
270
271
272
273
274
275
276
277
278

279


280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298

299
300
301

302
303

304
305
306
307
308
309
310
259
260
261
262
263
264
265

266
267
268
269
270
271
272
273

274
275

276
277
278
279
280
281
282
283
284
285

286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307

308
309
310
311
312
313

314
315
316
317
318
319
320
321







-
+







-
+

-
+









-
+

+
+


















-
+



+

-
+







    Ttk_ImageSpec *imageSpec;	/* Image(s) to use */
    int minWidth;		/* Minimum width; overrides image width */
    int minHeight;		/* Minimum width; overrides image width */
    Ttk_Sticky sticky;		/* -stickiness specification */
    Ttk_Padding border;		/* Fixed border region */
    Ttk_Padding padding;	/* Internal padding */

#if TILE_07_COMPAT
#ifdef TILE_07_COMPAT
    Ttk_ResourceCache cache;	/* Resource cache for images */
    Ttk_StateMap imageMap;	/* State-based lookup table for images */
#endif
} ImageData;

static void FreeImageData(void *clientData)
{
    ImageData *imageData = clientData;
    ImageData *imageData = (ImageData *)clientData;
    if (imageData->imageSpec)	{ TtkFreeImageSpec(imageData->imageSpec); }
#if TILE_07_COMPAT
#ifdef TILE_07_COMPAT
    if (imageData->imageMap)	{ Tcl_DecrRefCount(imageData->imageMap); }
#endif
    ckfree(clientData);
}

static void ImageElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    ImageData *imageData = clientData;
    ImageData *imageData = (ImageData *)clientData;
    Tk_Image image = imageData->imageSpec->baseImage;
    (void)elementRecord;
    (void)tkwin;

    if (image) {
	Tk_SizeOfImage(image, widthPtr, heightPtr);
    }
    if (imageData->minWidth >= 0) {
	*widthPtr = imageData->minWidth;
    }
    if (imageData->minHeight >= 0) {
	*heightPtr = imageData->minHeight;
    }

    *paddingPtr = imageData->padding;
}

static void ImageElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    ImageData *imageData = clientData;
    ImageData *imageData = (ImageData *)clientData;
    Tk_Image image = 0;
    int imgWidth, imgHeight;
    Ttk_Box src, dst;
    (void)elementRecord;

#if TILE_07_COMPAT
#ifdef TILE_07_COMPAT
    if (imageData->imageMap) {
	Tcl_Obj *imageObj = Ttk_StateMapLookup(NULL,imageData->imageMap,state);
	if (imageObj) {
	    image = Ttk_UseImage(imageData->cache, tkwin, imageObj);
	}
    }
    if (!image) {
321
322
323
324
325
326
327
328

329
330
331
332
333
334
335
336
337
338
339
340
341
342
343

344
345
346
347
348

349
350
351
352
353
354
355

356
357
358
359
360
361
362
363
364
365
366
367
368
369

370
371
372
373
374

375
376
377
378
379
380
381
382
383
384
385
386
387
388
389

390
391
392
393
394
395
396
332
333
334
335
336
337
338

339
340
341
342
343
344
345
346
347
348
349
350
351
352
353

354
355
356
357
358

359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380

381
382
383
384
385

386
387
388
389
390
391
392
393
394
395
396
397
398
399
400

401
402
403
404
405
406
407
408







-
+














-
+




-
+







+













-
+




-
+














-
+







    Tk_SizeOfImage(image, &imgWidth, &imgHeight);
    src = Ttk_MakeBox(0, 0, imgWidth, imgHeight);
    dst = Ttk_StickBox(b, imgWidth, imgHeight, imageData->sticky);

    Ttk_Tile(tkwin, d, image, src, dst, imageData->border);
}

static Ttk_ElementSpec ImageElementSpec =
static const Ttk_ElementSpec ImageElementSpec =
{
    TK_STYLE_VERSION_2,
    sizeof(NullElement),
    TtkNullElementOptions,
    ImageElementSize,
    ImageElementDraw
};

/*------------------------------------------------------------------------
 * +++ Image element factory.
 */
static int
Ttk_CreateImageElement(
    Tcl_Interp *interp,
    void *clientData,
    void *dummy,
    Ttk_Theme theme,
    const char *elementName,
    int objc, Tcl_Obj *const objv[])
{
    static const char *optionStrings[] =
    static const char *const optionStrings[] =
	 { "-border","-height","-padding","-sticky","-width",NULL };
    enum { O_BORDER, O_HEIGHT, O_PADDING, O_STICKY, O_WIDTH };

    Ttk_ImageSpec *imageSpec = 0;
    ImageData *imageData = 0;
    int padding_specified = 0;
    int i;
    (void)dummy;

    if (objc <= 0) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"Must supply a base image", -1));
	Tcl_SetErrorCode(interp, "TTK", "IMAGE", "BASE", NULL);
	return TCL_ERROR;
    }

    imageSpec = TtkGetImageSpec(interp, Tk_MainWindow(interp), objv[0]);
    if (!imageSpec) {
	return TCL_ERROR;
    }

    imageData = ckalloc(sizeof(*imageData));
    imageData = (ImageData *)ckalloc(sizeof(*imageData));
    imageData->imageSpec = imageSpec;
    imageData->minWidth = imageData->minHeight = -1;
    imageData->sticky = TTK_FILL_BOTH;
    imageData->border = imageData->padding = Ttk_UniformPadding(0);
#if TILE_07_COMPAT
#ifdef TILE_07_COMPAT
    imageData->cache = Ttk_GetResourceCache(interp);
    imageData->imageMap = 0;
#endif

    for (i = 1; i < objc; i += 2) {
	int option;

	if (i == objc - 1) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "Value for %s missing", Tcl_GetString(objv[i])));
	    Tcl_SetErrorCode(interp, "TTK", "IMAGE", "VALUE", NULL);
	    goto error;
	}

#if TILE_07_COMPAT
#ifdef TILE_07_COMPAT
	if (!strcmp("-map", Tcl_GetString(objv[i]))) {
	    imageData->imageMap = objv[i+1];
	    Tcl_IncrRefCount(imageData->imageMap);
	    continue;
	}
#endif

Changes to generic/ttk/ttkInit.c.
1
2

3
4
5
6
7
8

9
10
11
12
13
14
15
16

17
18
19
20
21

22
23
24
25






26
27
28
29
30
31
32

33
34
35
36
37
38

39
40
41
42






43
44
45
46
47
48
49

50
51
52

53
54
55
56
57
58
59












60
61
62
63
64
65

66
67
68
69
70
71
72
1

2
3
4
5
6


7
8
9
10
11
12
13
14

15
16
17
18
19

20
21



22
23
24
25
26
27
28
29
30
31
32
33

34
35
36
37
38
39

40
41



42
43
44
45
46
47
48
49
50
51
52
53

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82

83
84
85
86
87
88
89
90

-
+




-
-
+







-
+




-
+

-
-
-
+
+
+
+
+
+






-
+





-
+

-
-
-
+
+
+
+
+
+






-
+



+







+
+
+
+
+
+
+
+
+
+
+
+





-
+







/*
 * Copyright (c) 2003, Joe English
 * Copyright © 2003 Joe English
 *
 * Ttk package: initialization routine and miscellaneous utilities.
 */

#include <string.h>
#include <tk.h>
#include "tkInt.h"
#include "ttkTheme.h"
#include "ttkWidget.h"

/*
 * Legal values for the button -default option.
 * See also: enum Ttk_ButtonDefaultState.
 */
const char *ttkDefaultStrings[] = {
const char *const ttkDefaultStrings[] = {
    "normal", "active", "disabled", NULL
};

int Ttk_GetButtonDefaultStateFromObj(
    Tcl_Interp *interp, Tcl_Obj *objPtr, int *statePtr)
    Tcl_Interp *interp, Tcl_Obj *objPtr, Ttk_ButtonDefaultState *statePtr)
{
    *statePtr = TTK_BUTTON_DEFAULT_DISABLED;
    return Tcl_GetIndexFromObjStruct(interp, objPtr, ttkDefaultStrings,
	    sizeof(char *), "default state", 0, statePtr);
    int state = (int)TTK_BUTTON_DEFAULT_DISABLED;
    int result = Tcl_GetIndexFromObjStruct(interp, objPtr, ttkDefaultStrings,
	    sizeof(char *), "default state", 0, &state);

    *statePtr = (Ttk_ButtonDefaultState)state;
    return result;
}

/*
 * Legal values for the -compound option.
 * See also: enum Ttk_Compound.
 */
const char *ttkCompoundStrings[] = {
const char *const ttkCompoundStrings[] = {
    "none", "text", "image", "center",
    "top", "bottom", "left", "right", NULL
};

int Ttk_GetCompoundFromObj(
    Tcl_Interp *interp, Tcl_Obj *objPtr, int *statePtr)
    Tcl_Interp *interp, Tcl_Obj *objPtr, Ttk_Compound *compoundPtr)
{
    *statePtr = TTK_COMPOUND_NONE;
    return Tcl_GetIndexFromObjStruct(interp, objPtr, ttkCompoundStrings,
	    sizeof(char *), "compound layout", 0, statePtr);
    int compound = (int)TTK_COMPOUND_NONE;
    int result = Tcl_GetIndexFromObjStruct(interp, objPtr, ttkCompoundStrings,
	    sizeof(char *), "compound layout", 0, &compound);

    *compoundPtr = (Ttk_Compound)compound;
    return result;
}

/*
 * Legal values for the -orient option.
 * See also: enum Ttk_Orient.
 */
const char *ttkOrientStrings[] = {
const char *const ttkOrientStrings[] = {
    "horizontal", "vertical", NULL
};

#if !defined(TK_NO_DEPRECATED) && TK_MAJOR_VERSION < 9
int Ttk_GetOrientFromObj(
    Tcl_Interp *interp, Tcl_Obj *objPtr, int *resultPtr)
{
    *resultPtr = TTK_ORIENT_HORIZONTAL;
    return Tcl_GetIndexFromObjStruct(interp, objPtr, ttkOrientStrings,
	    sizeof(char *), "orientation", 0, resultPtr);
}
#endif

int TtkGetOrientFromObj(
    Tcl_Interp *interp, Tcl_Obj *objPtr, Ttk_Orient *resultPtr)
{
    int orient = (int)TTK_ORIENT_HORIZONTAL;
    int result = Tcl_GetIndexFromObjStruct(interp, objPtr, ttkOrientStrings,
    	    sizeof(char *), "orientation", 0, &orient);

    *resultPtr = (Ttk_Orient)orient;
    return result;
}

/*
 * Recognized values for the -state compatibility option.
 * Other options are accepted and interpreted as synonyms for "normal".
 */
static const char *ttkStateStrings[] = {
static const char *const ttkStateStrings[] = {
    "normal", "readonly", "disabled", "active", NULL
};
enum {
    TTK_COMPAT_STATE_NORMAL,
    TTK_COMPAT_STATE_READONLY,
    TTK_COMPAT_STATE_DISABLED,
    TTK_COMPAT_STATE_ACTIVE
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
120
121
122
123
124
125
126






















127
128
129
130
131
132
133







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







	case TTK_COMPAT_STATE_ACTIVE:
	    SETFLAGS(TTK_STATE_ACTIVE);
	    break;
    }
#   undef SETFLAGS
}

/* TtkSendVirtualEvent --
 * 	Send a virtual event notification to the specified target window.
 * 	Equivalent to "event generate $tgtWindow <<$eventName>>"
 *
 * 	Note that we use Tk_QueueWindowEvent, not Tk_HandleEvent,
 * 	so this routine does not reenter the interpreter.
 */
void TtkSendVirtualEvent(Tk_Window tgtWin, const char *eventName)
{
    union {XEvent general; XVirtualEvent virt;} event;

    memset(&event, 0, sizeof(event));
    event.general.xany.type = VirtualEvent;
    event.general.xany.serial = NextRequest(Tk_Display(tgtWin));
    event.general.xany.send_event = False;
    event.general.xany.window = Tk_WindowId(tgtWin);
    event.general.xany.display = Tk_Display(tgtWin);
    event.virt.name = Tk_GetUid(eventName);

    Tk_QueueWindowEvent(&event.general, TCL_QUEUE_TAIL);
}

/* TtkEnumerateOptions, TtkGetOptionValue --
 *	Common factors for data accessor commands.
 */
int TtkEnumerateOptions(
    Tcl_Interp *interp, void *recordPtr, const Tk_OptionSpec *specPtr,
    Tk_OptionTable optionTable, Tk_Window tkwin)
{
145
146
147
148
149
150
151
152

153
154
155
156
157
158
159
141
142
143
144
145
146
147

148
149
150
151
152
153
154
155







-
+







	    Tcl_ListObjAppendElement(interp, result, optionName);
	    Tcl_ListObjAppendElement(interp, result, optionValue);
	}
	++specPtr;

	if (specPtr->type == TK_OPTION_END && specPtr->clientData != NULL) {
	    /* Chain to next option spec array: */
	    specPtr = specPtr->clientData;
	    specPtr = (const Tk_OptionSpec *)specPtr->clientData;
	}
    }
    Tcl_SetObjResult(interp, result);
    return TCL_OK;
}

int TtkGetOptionValue(
172
173
174
175
176
177
178
179

180
181
182

183
184

185
186

187
188
189
190
191
192
193
168
169
170
171
172
173
174

175
176
177

178
179

180
181

182
183
184
185
186
187
188
189







-
+


-
+

-
+

-
+








/*------------------------------------------------------------------------
 * Core Option specifications:
 * type name dbName dbClass default objOffset intOffset flags clientData mask
 */

/* public */
Tk_OptionSpec ttkCoreOptionSpecs[] =
const Tk_OptionSpec ttkCoreOptionSpecs[] =
{
    {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor", NULL,
	Tk_Offset(WidgetCore, cursorObj), -1, TK_OPTION_NULL_OK,0,0 },
	offsetof(WidgetCore, cursorObj), TCL_INDEX_NONE, TK_OPTION_NULL_OK,0,0 },
    {TK_OPTION_STRING, "-style", "style", "Style", "",
	Tk_Offset(WidgetCore,styleObj), -1, 0,0,STYLE_CHANGED},
	offsetof(WidgetCore,styleObj), TCL_INDEX_NONE, 0,0,STYLE_CHANGED},
    {TK_OPTION_STRING, "-class", "", "", NULL,
	Tk_Offset(WidgetCore,classObj), -1, 0,0,READONLY_OPTION},
	offsetof(WidgetCore,classObj), TCL_INDEX_NONE, 0,0,READONLY_OPTION},
    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0}
};

/*------------------------------------------------------------------------
 * +++ Initialization: elements and element factories.
 */

271
272
273
274
275
276
277

278



279
280
281
282
283
267
268
269
270
271
272
273
274

275
276
277
278
279
280
281
282







+
-
+
+
+






    RegisterElements(interp);
    RegisterWidgets(interp);
    RegisterThemes(interp);

    Ttk_PlatformInit(interp);

#ifndef TK_NO_DEPRECATED
    Tcl_PkgProvideEx(interp, "Ttk", TTK_PATCH_LEVEL, (ClientData)&ttkStubs);
    Tcl_PkgProvideEx(interp, "Ttk", TTK_PATCH_LEVEL, (void *)&ttkStubs);
#endif
    Tcl_PkgProvideEx(interp, "ttk", TTK_PATCH_LEVEL, (void *)&ttkStubs);

    return TCL_OK;
}

/*EOF*/
Changes to generic/ttk/ttkLabel.c.
42
43
44
45
46
47
48
49

50
51

52
53

54
55

56
57

58
59

60
61

62
63

64
65

66
67
68


69
70
71
72
73
74
75
42
43
44
45
46
47
48

49
50

51
52

53
54

55
56

57
58

59
60

61
62

63
64

65
66


67
68
69
70
71
72
73
74
75







-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
-
+
+







    int			embossed;

} TextElement;

/* Text element options table.
 * NB: Keep in sync with label element option table.
 */
static Ttk_ElementOptionSpec TextElementOptions[] = {
static const Ttk_ElementOptionSpec TextElementOptions[] = {
    { "-text", TK_OPTION_STRING,
	Tk_Offset(TextElement,textObj), "" },
	offsetof(TextElement,textObj), "" },
    { "-font", TK_OPTION_FONT,
	Tk_Offset(TextElement,fontObj), DEFAULT_FONT },
	offsetof(TextElement,fontObj), DEFAULT_FONT },
    { "-foreground", TK_OPTION_COLOR,
	Tk_Offset(TextElement,foregroundObj), "black" },
	offsetof(TextElement,foregroundObj), "black" },
    { "-underline", TK_OPTION_INT,
	Tk_Offset(TextElement,underlineObj), "-1"},
	offsetof(TextElement,underlineObj), "-1"},
    { "-width", TK_OPTION_INT,
	Tk_Offset(TextElement,widthObj), "-1"},
	offsetof(TextElement,widthObj), "-1"},
    { "-anchor", TK_OPTION_ANCHOR,
	Tk_Offset(TextElement,anchorObj), "w"},
	offsetof(TextElement,anchorObj), "w"},
    { "-justify", TK_OPTION_JUSTIFY,
	Tk_Offset(TextElement,justifyObj), "left" },
	offsetof(TextElement,justifyObj), "left" },
    { "-wraplength", TK_OPTION_PIXELS,
	Tk_Offset(TextElement,wrapLengthObj), "0" },
	offsetof(TextElement,wrapLengthObj), "0" },
    { "-embossed", TK_OPTION_INT,
	Tk_Offset(TextElement,embossedObj), "0"},
    { NULL, 0, 0, NULL }
	offsetof(TextElement,embossedObj), "0"},
    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
};

static int TextSetup(TextElement *text, Tk_Window tkwin)
{
    const char *string = Tcl_GetString(text->textObj);
    Tk_Justify justify = TK_JUSTIFY_LEFT;
    int wrapLength = 0;
134
135
136
137
138
139
140
141

142
143
144
145
146
147
148
134
135
136
137
138
139
140

141
142
143
144
145
146
147
148







-
+








    gcValues.font = Tk_FontId(text->tkfont);
    gcValues.foreground = color->pixel;
    gc1 = Tk_GetGC(tkwin, GCFont | GCForeground, &gcValues);
    gcValues.foreground = WhitePixelOfScreen(Tk_Screen(tkwin));
    gc2 = Tk_GetGC(tkwin, GCFont | GCForeground, &gcValues);

    /* 
    /*
     * Place text according to -anchor:
     */
    Tk_GetAnchorFromObj(NULL, text->anchorObj, &anchor);
    b = Ttk_AnchorBox(b, text->width, text->height, anchor);

    /*
     * Clip text if it's too wide:
189
190
191
192
193
194
195
196

197
198
199



200
201
202
203
204
205
206
207
208
209
210
211
212
213

214
215
216




217
218
219
220
221
222
223

224
225
226
227
228
229
230
189
190
191
192
193
194
195

196
197
198

199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214

215
216
217

218
219
220
221
222
223
224
225
226
227

228
229
230
231
232
233
234
235







-
+


-
+
+
+













-
+


-
+
+
+
+






-
+







	TkDestroyRegion(clipRegion);
    }
    Tk_FreeGC(Tk_Display(tkwin), gc1);
    Tk_FreeGC(Tk_Display(tkwin), gc2);
}

static void TextElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    TextElement *text = elementRecord;
    TextElement *text = (TextElement *)elementRecord;
    (void)dummy;
    (void)paddingPtr;

    if (!TextSetup(text, tkwin))
	return;

    *heightPtr = text->height;
    *widthPtr = TextReqWidth(text);

    TextCleanup(text);

    return;
}

static void TextElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, Ttk_State state)
{
    TextElement *text = elementRecord;
    TextElement *text = (TextElement *)elementRecord;
    (void)dummy;
    (void)state;

    if (TextSetup(text, tkwin)) {
	TextDraw(text, tkwin, d, b);
	TextCleanup(text);
    }
}

static Ttk_ElementSpec TextElementSpec = {
static const Ttk_ElementSpec TextElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(TextElement),
    TextElementOptions,
    TextElementSize,
    TextElementDraw
};

242
243
244
245
246
247
248
249

250
251

252
253

254
255
256


257
258
259
260
261
262
263
247
248
249
250
251
252
253

254
255

256
257

258
259


260
261
262
263
264
265
266
267
268







-
+

-
+

-
+

-
-
+
+







    Tk_Image	tkimg;
    int 	width;
    int		height;
} ImageElement;

/* ===> NB: Keep in sync with label element option table.  <===
 */
static Ttk_ElementOptionSpec ImageElementOptions[] = {
static const Ttk_ElementOptionSpec ImageElementOptions[] = {
    { "-image", TK_OPTION_STRING,
	Tk_Offset(ImageElement,imageObj), "" },
	offsetof(ImageElement,imageObj), "" },
    { "-stipple", TK_OPTION_STRING, 	/* Really: TK_OPTION_BITMAP */
	Tk_Offset(ImageElement,stippleObj), "gray50" },
	offsetof(ImageElement,stippleObj), "gray50" },
    { "-background", TK_OPTION_COLOR,
	Tk_Offset(ImageElement,backgroundObj), DEFAULT_BACKGROUND },
    { NULL, 0, 0, NULL }
	offsetof(ImageElement,backgroundObj), DEFAULT_BACKGROUND },
    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
};

/*
 * ImageSetup() --
 * 	Look up the Tk_Image from the image element's imageObj resource.
 * 	Caller must release the image with ImageCleanup().
 *
337
338
339
340
341
342
343
344

345
346
347
348

349
350
351
352

353
354
355
356
357
358
359
360
361
362
363

364
365
366



367
368
369
370
371
372
373
374
375
376

377
378
379


380
381
382
383
384
385
386
387

388
389
390
391
392
393
394
342
343
344
345
346
347
348

349
350
351
352

353
354
355
356

357
358
359
360
361
362
363
364
365
366
367

368
369
370

371
372
373
374
375
376
377
378
379
380
381
382

383
384
385

386
387
388
389
390
391
392
393
394

395
396
397
398
399
400
401
402







-
+



-
+



-
+










-
+


-
+
+
+









-
+


-
+
+







-
+







	/* Completely clipped - bail out.
	 */
	return;
    }

    Tk_RedrawImage(image->tkimg, 0,0, width, height, d, b.x, b.y);

    /* If we're disabled there's no state-specific 'disabled' image, 
    /* If we're disabled there's no state-specific 'disabled' image,
     * stipple the image.
     * @@@ Possibly: Don't do disabled-stippling at all;
     * @@@ it's ugly and out of fashion.
     * Do not stipple at all under Aqua, just draw the image: it shows up 
     * Do not stipple at all under Aqua, just draw the image: it shows up
     * as a white rectangle otherwise.
     */

    

    if (state & TTK_STATE_DISABLED) {
	if (TtkSelectImage(image->imageSpec, 0ul) == image->tkimg) {
#ifndef MAC_OSX_TK
	    StippleOver(image, tkwin, d, b.x,b.y);
#endif
	}
    }
}

static void ImageElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    ImageElement *image = elementRecord;
    ImageElement *image = (ImageElement *)elementRecord;
    (void)dummy;
    (void)paddingPtr;

    if (ImageSetup(image, tkwin, 0)) {
	*widthPtr = image->width;
	*heightPtr = image->height;
	ImageCleanup(image);
    }
}

static void ImageElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, Ttk_State state)
{
    ImageElement *image = elementRecord;
    ImageElement *image = (ImageElement *)elementRecord;
    (void)dummy;

    if (ImageSetup(image, tkwin, state)) {
	ImageDraw(image, tkwin, d, b, state);
	ImageCleanup(image);
    }
}

static Ttk_ElementSpec ImageElementSpec = {
static const Ttk_ElementSpec ImageElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(ImageElement),
    ImageElementOptions,
    ImageElementSize,
    ImageElementDraw
};

436
437
438
439
440
441
442
443

444
445

446
447

448
449
450
451
452
453

454
455

456
457

458
459

460
461

462
463

464
465

466
467

468
469

470
471
472
473
474
475

476
477

478
479
480


481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498


499
500
501
502
503
504
505
444
445
446
447
448
449
450

451
452

453
454

455
456
457
458
459
460

461
462

463
464

465
466

467
468

469
470

471
472

473
474

475
476

477
478
479
480
481
482

483
484

485
486


487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504


505
506
507
508
509
510
511
512
513







-
+

-
+

-
+





-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+





-
+

-
+

-
-
+
+
















-
-
+
+







     * Computed values (see LabelSetup)
     */
    Ttk_Compound	compound;
    int  		space;
    int 		totalWidth, totalHeight;
} LabelElement;

static Ttk_ElementOptionSpec LabelElementOptions[] = {
static const Ttk_ElementOptionSpec LabelElementOptions[] = {
    { "-compound", TK_OPTION_ANY,
	Tk_Offset(LabelElement,compoundObj), "none" },
	offsetof(LabelElement,compoundObj), "none" },
    { "-space", TK_OPTION_PIXELS,
	Tk_Offset(LabelElement,spaceObj), "4" },
	offsetof(LabelElement,spaceObj), "4" },

    /* Text element part:
     * NB: Keep in sync with TextElementOptions.
     */
    { "-text", TK_OPTION_STRING,
	Tk_Offset(LabelElement,text.textObj), "" },
	offsetof(LabelElement,text.textObj), "" },
    { "-font", TK_OPTION_FONT,
	Tk_Offset(LabelElement,text.fontObj), DEFAULT_FONT },
	offsetof(LabelElement,text.fontObj), DEFAULT_FONT },
    { "-foreground", TK_OPTION_COLOR,
	Tk_Offset(LabelElement,text.foregroundObj), "black" },
	offsetof(LabelElement,text.foregroundObj), "black" },
    { "-underline", TK_OPTION_INT,
	Tk_Offset(LabelElement,text.underlineObj), "-1"},
	offsetof(LabelElement,text.underlineObj), "-1"},
    { "-width", TK_OPTION_INT,
	Tk_Offset(LabelElement,text.widthObj), ""},
	offsetof(LabelElement,text.widthObj), ""},
    { "-anchor", TK_OPTION_ANCHOR,
	Tk_Offset(LabelElement,text.anchorObj), "w"},
	offsetof(LabelElement,text.anchorObj), "w"},
    { "-justify", TK_OPTION_JUSTIFY,
	Tk_Offset(LabelElement,text.justifyObj), "left" },
	offsetof(LabelElement,text.justifyObj), "left" },
    { "-wraplength", TK_OPTION_PIXELS,
	Tk_Offset(LabelElement,text.wrapLengthObj), "0" },
	offsetof(LabelElement,text.wrapLengthObj), "0" },
    { "-embossed", TK_OPTION_INT,
	Tk_Offset(LabelElement,text.embossedObj), "0"},
	offsetof(LabelElement,text.embossedObj), "0"},

    /* Image element part:
     * NB: Keep in sync with ImageElementOptions.
     */
    { "-image", TK_OPTION_STRING,
	Tk_Offset(LabelElement,image.imageObj), "" },
	offsetof(LabelElement,image.imageObj), "" },
    { "-stipple", TK_OPTION_STRING, 	/* Really: TK_OPTION_BITMAP */
	Tk_Offset(LabelElement,image.stippleObj), "gray50" },
	offsetof(LabelElement,image.stippleObj), "gray50" },
    { "-background", TK_OPTION_COLOR,
	Tk_Offset(LabelElement,image.backgroundObj), DEFAULT_BACKGROUND },
    { NULL, 0, 0, NULL }
	offsetof(LabelElement,image.backgroundObj), DEFAULT_BACKGROUND },
    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
};

/*
 * LabelSetup --
 * 	Fills in computed fields of the label element.
 *
 * 	Calculate the text, image, and total width and height.
 */

#undef  MAX
#define MAX(a,b) ((a) > (b) ? a : b);
static void LabelSetup(
    LabelElement *c, Tk_Window tkwin, Ttk_State state)
{
    Ttk_Compound *compoundPtr = &c->compound;

    Tk_GetPixelsFromObj(NULL,tkwin,c->spaceObj,&c->space);
    Ttk_GetCompoundFromObj(NULL,c->compoundObj,(int*)compoundPtr);
    Tk_GetPixelsFromObj(NULL, tkwin, c->spaceObj, &c->space);
    Ttk_GetCompoundFromObj(NULL, c->compoundObj, compoundPtr);

    /*
     * Deal with TTK_COMPOUND_NONE.
     */
    if (c->compound == TTK_COMPOUND_NONE) {
	if (ImageSetup(&c->image, tkwin, state)) {
	    c->compound = TTK_COMPOUND_IMAGE;
557
558
559
560
561
562
563

564
565





566
567

568
569
570
571
572
573
574
575
576
577
578
579

580
581
582
583
584
585
586
587
588
589
590

591
592
593
594

595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610

611
612
613
614
615
616
617
618
619
620

621
622





623
624

625
626
627
628
629
630
631
565
566
567
568
569
570
571
572


573
574
575
576
577
578

579
580
581
582
583
584
585
586
587
588
589
590

591
592
593
594
595
596
597
598
599
600
601

602
603
604
605

606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621

622
623
624
625
626
627
628
629
630
631
632
633


634
635
636
637
638
639

640
641
642
643
644
645
646
647







+
-
-
+
+
+
+
+

-
+











-
+










-
+



-
+















-
+










+
-
-
+
+
+
+
+

-
+







    if (c->compound != TTK_COMPOUND_TEXT)
	ImageCleanup(&c->image);
    if (c->compound != TTK_COMPOUND_IMAGE)
	TextCleanup(&c->text);
}

static void LabelElementSize(
    TCL_UNUSED(void *),
    void *clientData, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
    void *elementRecord,
    Tk_Window tkwin,
    int *widthPtr,
    int *heightPtr,
    TCL_UNUSED(Ttk_Padding *))
{
    LabelElement *label = elementRecord;
    LabelElement *label = (LabelElement *)elementRecord;
    int textReqWidth = 0;

    LabelSetup(label, tkwin, 0);

    *heightPtr = label->totalHeight;

    /* Requested width based on -width option, not actual text width:
     */
    if (label->compound != TTK_COMPOUND_IMAGE)
	textReqWidth = TextReqWidth(&label->text);

    switch (label->compound) 
    switch (label->compound)
    {
	case TTK_COMPOUND_TEXT:
	    *widthPtr = textReqWidth;
	    break;
	case TTK_COMPOUND_IMAGE:
	    *widthPtr = label->image.width;
	    break;
	case TTK_COMPOUND_TOP:
	case TTK_COMPOUND_BOTTOM:
	case TTK_COMPOUND_CENTER:
	    *widthPtr = MAX(label->image.width, textReqWidth); 
	    *widthPtr = MAX(label->image.width, textReqWidth);
	    break;
	case TTK_COMPOUND_LEFT:
	case TTK_COMPOUND_RIGHT:
	    *widthPtr = label->image.width + textReqWidth + label->space; 
	    *widthPtr = label->image.width + textReqWidth + label->space;
	    break;
	case TTK_COMPOUND_NONE:
	    break; /* Can't happen */
    }

    LabelCleanup(label);
}

/*
 * DrawCompound --
 * 	Helper routine for LabelElementDraw;
 * 	Handles layout for -compound {left,right,top,bottom}
 */
static void DrawCompound(
    LabelElement *l, Ttk_Box b, Tk_Window tkwin, Drawable d, Ttk_State state,
    int imageSide, int textSide)
	Ttk_Side imageSide, Ttk_Side textSide)
{
    Ttk_Box imageBox =
	Ttk_PlaceBox(&b, l->image.width, l->image.height, imageSide, 0);
    Ttk_Box textBox =
	Ttk_PlaceBox(&b, l->text.width, l->text.height, textSide, 0);
    ImageDraw(&l->image,tkwin,d,imageBox,state);
    TextDraw(&l->text,tkwin,d,textBox);
}

static void LabelElementDraw(
    TCL_UNUSED(void *),
    void *clientData, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, Ttk_State state)
    void *elementRecord,
    Tk_Window tkwin,
    Drawable d,
    Ttk_Box b,
    Ttk_State state)
{
    LabelElement *l = elementRecord;
    LabelElement *l = (LabelElement *)elementRecord;
    Tk_Anchor anchor = TK_ANCHOR_CENTER;

    LabelSetup(l, tkwin, state);

    /*
     * Adjust overall parcel based on -anchor:
     */
669
670
671
672
673
674
675
676

677
678
679
680
681
682
683
685
686
687
688
689
690
691

692
693
694
695
696
697
698
699







-
+







	    DrawCompound(l, b, tkwin, d, state, TTK_SIDE_RIGHT, TTK_SIDE_LEFT);
	    break;
    }

    LabelCleanup(l);
}

static Ttk_ElementSpec LabelElementSpec = {
static const Ttk_ElementSpec LabelElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(LabelElement),
    LabelElementOptions,
    LabelElementSize,
    LabelElementDraw
};

Changes to generic/ttk/ttkLayout.c.
1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16
1
2
3
4
5

6
7
8

9
10
11
12
13
14
15





-
+


-







/*
 * ttkLayout.c --
 *
 * Generic layout processing.
 *
 * Copyright (c) 2003 Joe English.  Freely redistributable.
 * Copyright © 2003 Joe English.  Freely redistributable.
 */

#include <string.h>
#include "tkInt.h"
#include "ttkThemeInt.h"

#define MAX(a,b) (a > b ? a : b)
#define MIN(a,b) (a < b ? a : b)

/*------------------------------------------------------------------------
33
34
35
36
37
38
39
40
41
42
43




44
45
46
47
48
49
50
32
33
34
35
36
37
38




39
40
41
42
43
44
45
46
47
48
49







-
-
-
-
+
+
+
+







}

Tcl_Obj *
Ttk_NewBoxObj(Ttk_Box box)
{
    Tcl_Obj *result[4];

    result[0] = Tcl_NewIntObj(box.x);
    result[1] = Tcl_NewIntObj(box.y);
    result[2] = Tcl_NewIntObj(box.width);
    result[3] = Tcl_NewIntObj(box.height);
    result[0] = Tcl_NewWideIntObj(box.x);
    result[1] = Tcl_NewWideIntObj(box.y);
    result[2] = Tcl_NewWideIntObj(box.width);
    result[3] = Tcl_NewWideIntObj(box.height);

    return Tcl_NewListObj(4, result);
}

/*
 * packTop, packBottom, packLeft, packRight --
 * 	Carve out a parcel of the specified height (resp width)
521
522
523
524
525
526
527
528

529
530
531
532
533
534
535
520
521
522
523
524
525
526

527
528
529
530
531
532
533
534







-
+







    Ttk_Box 		parcel;		/* allocated parcel */
    Ttk_LayoutNode	*next, *child;
};

static Ttk_LayoutNode *Ttk_NewLayoutNode(
    unsigned flags, Ttk_ElementClass *elementClass)
{
    Ttk_LayoutNode *node = ckalloc(sizeof(*node));
    Ttk_LayoutNode *node = (Ttk_LayoutNode *)ckalloc(sizeof(*node));

    node->flags = flags;
    node->eclass = elementClass;
    node->state = 0u;
    node->next = node->child = 0;
    node->parcel = Ttk_MakeBox(0,0,0,0);

554
555
556
557
558
559
560
561
562


563
564
565
566
567
568
569
553
554
555
556
557
558
559


560
561
562
563
564
565
566
567
568







-
-
+
+







    char *name;
    unsigned flags;
    struct Ttk_TemplateNode_ *next, *child;
};

static Ttk_TemplateNode *Ttk_NewTemplateNode(const char *name, unsigned flags)
{
    Ttk_TemplateNode *op = ckalloc(sizeof(*op));
    op->name = ckalloc(strlen(name) + 1); strcpy(op->name, name);
    Ttk_TemplateNode *op = (Ttk_TemplateNode *)ckalloc(sizeof(*op));
    op->name = (char *)ckalloc(strlen(name) + 1); strcpy(op->name, name);
    op->flags = flags;
    op->next = op->child = 0;
    return op;
}

void Ttk_FreeLayoutTemplate(Ttk_LayoutTemplate op)
{
600
601
602
603
604
605
606
607

608
609
610
611
612
613

614
615
616
617
618
619
620
599
600
601
602
603
604
605

606
607
608
609
610
611

612
613
614
615
616
617
618
619







-
+





-
+







 *	Convert a Tcl list into a layout template.
 *
 * Syntax:
 * 	layoutSpec ::= { elementName ?-option value ...? }+
 */

/* NB: This must match bit definitions TTK_PACK_LEFT etc. */
static const char *packSideStrings[] =
static const char *const packSideStrings[] =
    { "left", "right", "top", "bottom", NULL };

Ttk_LayoutTemplate Ttk_ParseLayoutTemplate(Tcl_Interp *interp, Tcl_Obj *objPtr)
{
    enum {  OP_SIDE, OP_STICKY, OP_EXPAND, OP_BORDER, OP_UNIT, OP_CHILDREN };
    static const char *optStrings[] = {
    static const char *const optStrings[] = {
	"-side", "-sticky", "-expand", "-border", "-unit", "-children", 0 };

    int i = 0, objc;
    Tcl_Obj **objv;
    Ttk_TemplateNode *head = 0, *tail = 0;

    if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK)
806
807
808
809
810
811
812
813

814
815
816
817
818
819
820
805
806
807
808
809
810
811

812
813
814
815
816
817
818
819







-
+







	 * In Ttk_ParseLayoutTemplate, default -sticky is "nsew", so always
	 * include this even if no sticky bits are set.
	 */

	APPENDSTR("-sticky");
	APPENDOBJ(Ttk_NewStickyObj(flags & _TTK_MASK_STICK));

	/* @@@ Check again: are these necessary? */
	/* @@@ Check again: are these necessary? Can't see any effect! */
	if (flags & TTK_BORDER)	{ APPENDSTR("-border"); APPENDSTR("1"); }
	if (flags & TTK_UNIT) 	{ APPENDSTR("-unit"); APPENDSTR("1"); }

	if (node->child) {
	    APPENDSTR("-children");
	    APPENDOBJ(Ttk_UnparseLayoutTemplate(node->child));
	}
840
841
842
843
844
845
846
847

848
849
850
851
852
853
854
839
840
841
842
843
844
845

846
847
848
849
850
851
852
853







-
+







};

static Ttk_Layout TTKNewLayout(
    Ttk_Style style,
    void *recordPtr,Tk_OptionTable optionTable, Tk_Window tkwin,
    Ttk_LayoutNode *root)
{
    Ttk_Layout layout = ckalloc(sizeof(*layout));
    Ttk_Layout layout = (Ttk_Layout)ckalloc(sizeof(*layout));
    layout->style = style;
    layout->recordPtr = recordPtr;
    layout->optionTable = optionTable;
    layout->tkwin = tkwin;
    layout->root = root;
    return layout;
}
Changes to generic/ttk/ttkManager.c.
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15


16
17
18
19
20


21
22

23
24

25
26
27
28
29
30

31
32

33
34
35
36

37
38
39
40



41
42

43
44
45
46
47
48
49

50
51

52
53

54
55

56
57

58
59
60
61
62
63

64
65
66


67
68
69
70
71
72
73
1
2
3
4
5
6


7
8
9
10
11
12


13
14
15
16
17


18
19
20

21
22

23
24
25
26
27
28

29
30

31
32
33
34

35
36



37
38
39
40

41
42
43
44
45
46
47

48
49

50
51

52
53

54
55

56
57
58
59
60
61

62
63


64
65
66
67
68
69
70
71
72






-
-
+





-
-
+
+



-
-
+
+

-
+

-
+





-
+

-
+



-
+

-
-
-
+
+
+

-
+






-
+

-
+

-
+

-
+

-
+





-
+

-
-
+
+







/*
 * Copyright 2005, Joe English.  Freely redistributable.
 *
 * Support routines for geometry managers.
 */

#include <string.h>
#include <tk.h>
#include "tkInt.h"
#include "ttkManager.h"

/*------------------------------------------------------------------------
 * +++ The Geometry Propagation Dance.
 *
 * When a slave window requests a new size or some other parameter changes,
 * the manager recomputes the required size for the master window and calls
 * When a content window requests a new size or some other parameter changes,
 * the manager recomputes the required size for the container window and calls
 * Tk_GeometryRequest().  This is scheduled as an idle handler so multiple
 * updates can be processed as a single batch.
 *
 * If all goes well, the master's manager will process the request
 * (and so on up the chain to the toplevel window), and the master
 * If all goes well, the container's manager will process the request
 * (and so on up the chain to the toplevel window), and the container
 * window will eventually receive a <Configure> event.  At this point
 * it recomputes the size and position of all slaves and places them.
 * it recomputes the size and position of all content windows and places them.
 *
 * If all does not go well, however, the master's request may be ignored
 * If all does not go well, however, the container's request may be ignored
 * (typically because the top-level window has a fixed, user-specified size).
 * Tk doesn't provide any notification when this happens; to account for this,
 * we also schedule an idle handler to call the layout procedure
 * after making a geometry request.
 *
 * +++ Slave removal <<NOTE-LOSTSLAVE>>.
 * +++ Content window removal <<NOTE-LOSTCONTENT>>.
 *
 * There are three conditions under which a slave is removed:
 * There are three conditions under which a content window is removed:
 *
 * (1) Another GM claims control
 * (2) Manager voluntarily relinquishes control
 * (3) Slave is destroyed
 * (3) Content window is destroyed
 *
 * In case (1), Tk calls the manager's lostSlaveProc.
 * Case (2) is performed by calling Tk_ManageGeometry(slave,NULL,0);
 * in this case Tk does _not_ call the LostSlaveProc (documented behavior).
 * In case (1), Tk calls the manager's lostContentProc.
 * Case (2) is performed by calling Tk_ManageGeometry(window,NULL,0);
 * in this case Tk does _not_ call the lostContentProc (documented behavior).
 * Tk doesn't handle case (3) either; to account for that we
 * register an event handler on the slave widget to track <Destroy> events.
 * register an event handler on the content window to track <Destroy> events.
 */

/* ++ Data structures.
 */
typedef struct
{
    Tk_Window 		slaveWindow;
    Tk_Window 		window;
    Ttk_Manager 	*manager;
    void 		*slaveData;
    void 		*data;
    unsigned		flags;
} Ttk_Slave;
} Ttk_Content;

/* slave->flags bits:
/* content->flags bits:
 */
#define SLAVE_MAPPED 		0x1	/* slave to be mapped when master is */
#define CONTENT_MAPPED 	0x1	/* content windows to be mapped when container is */

struct TtkManager_
{
    Ttk_ManagerSpec	*managerSpec;
    void 		*managerData;
    Tk_Window   	masterWindow;
    Tk_Window   	window;
    unsigned		flags;
    int 	 	nSlaves;
    Ttk_Slave 		**slaves;
    TkSizeT 	 	nContent;
    Ttk_Content 		**content;
};

/* manager->flags bits:
 */
#define MGR_UPDATE_PENDING	0x1
#define MGR_RESIZE_REQUIRED	0x2
#define MGR_RELAYOUT_REQUIRED	0x4
84
85
86
87
88
89
90
91

92
93
94
95
96
97
98
99

100
101
102
103
104
105
106

107
108
109
110

111
112
113
114
115
116
117
118
119

120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140


141
142
143
144
145
146


147
148
149
150
151
152
153
154
155
156
157




158
159
160
161
162
163
164



165
166
167
168
169
170
171
172



173
174
175

176
177

178
179
180


181
182
183
184
185

186
187
188
189


190
191

192
193
194
195
196




197
198

199
200
201

202
203

204
205
206
207
208
209
210
211

212
213

214
215
216
217
218
219



220
221
222
223

224
225
226
227
228
229
230
231

232
233
234


235
236
237


238
239
240
241
242
243
244
245
246

247
248
249
250


251
252

253
254
255


256
257
258

259
260
261
262

263
264
265


266
267
268


269
270
271
272
273
274


275
276
277
278
279

280
281

282
283
284


285
286
287
288

289
290
291
292
293
294



295
296
297
298
299
300

301
302
303
304


305
306

307
308
309
310
311
312
313
314
315

316
317
318
319
320




321
322
323


324
325
326
327
328
329

330
331
332


333
334
335

336
337
338
339
340
341
342
343


344
345
346


347
348
349


350
351
352
353


354
355

356
357
358
359



360
361
362
363


364
365
366
367

368
369
370


371
372
373
374
375
376





377
378
379
380
381


382
383

384
385
386
387



388
389

390
391

392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409

410
411

412
413

414
415

416
417

418
419

420
421
422
423
424
425
426
427


428
429

430
431
432
433



434
435

436
437
438
439
440



441
442
443
444
445
446
447
448


449
450
451

452
453
454
455
456
457


458
459
460


461
462
463

464
465
466
467

468
469
470
471
472



473
474
475
476


477
478
479

480
481
482
483
484
485


486
487
488
489
490


491
492

493
494

495
496
497
498

499
500
501
502
503

504
505
506
507

508
509

510
511
512
513
514
515
516
517



518
519
520
521
522




523
524
525
526

527
528

529
530

531
532
533
534
535
536
537
538
539
540
541
542
543
544
545


546
547
548
549
83
84
85
86
87
88
89

90
91
92
93
94
95
96
97

98
99
100
101
102
103
104

105
106
107
108

109
110
111
112
113
114
115
116
117

118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137


138
139
140
141
142
143


144
145
146
147
148
149
150
151
152




153
154
155
156
157
158
159
160



161
162
163
164
165
166
167
168



169
170
171
172


173
174

175
176


177
178
179
180
181
182

183
184
185


186
187
188

189
190




191
192
193
194
195

196
197
198

199
200

201
202
203
204
205
206
207
208

209
210

211
212
213
214



215
216
217
218
219
220

221
222
223
224
225
226
227
228

229
230


231
232
233


234
235
236
237
238
239
240
241
242
243

244
245
246


247
248
249

250
251


252
253
254
255

256
257
258
259

260
261


262
263
264


265
266
267
268
269
270


271
272
273
274
275
276

277
278

279
280


281
282
283
284
285

286
287
288
289



290
291
292
293
294
295
296
297

298
299
300


301
302
303

304
305
306
307
308
309
310
311
312

313
314




315
316
317
318
319


320
321
322
323
324
325
326

327
328


329
330
331
332

333
334
335
336
337
338
339


340
341
342


343
344
345


346
347
348
349


350
351
352

353
354



355
356
357
358
359


360
361
362
363
364

365
366


367
368
369





370
371
372
373
374
375
376
377


378
379
380

381
382



383
384
385
386

387
388

389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406

407
408

409
410

411
412

413
414

415
416

417
418
419
420
421
422
423


424
425
426

427
428



429
430
431
432

433
434
435



436
437
438
439
440
441
442
443
444


445
446
447
448

449
450
451
452
453


454
455
456


457
458
459
460

461
462
463
464

465
466
467



468
469
470
471
472


473
474
475
476

477
478
479
480
481


482
483
484
485
486


487
488
489

490
491

492
493
494
495

496
497
498
499
500

501
502
503
504

505
506

507
508
509
510
511
512



513
514
515
516




517
518
519
520
521
522
523

524
525

526
527

528
529
530
531
532
533
534
535
536
537
538
539
540
541


542
543
544
545
546
547







-
+







-
+






-
+



-
+








-
+



















-
-
+
+




-
-
+
+







-
-
-
-
+
+
+
+




-
-
-
+
+
+





-
-
-
+
+
+

-
-
+

-
+

-
-
+
+




-
+


-
-
+
+

-
+

-
-
-
-
+
+
+
+

-
+


-
+

-
+







-
+

-
+



-
-
-
+
+
+



-
+







-
+

-
-
+
+

-
-
+
+








-
+


-
-
+
+

-
+

-
-
+
+


-
+



-
+

-
-
+
+

-
-
+
+




-
-
+
+




-
+

-
+

-
-
+
+



-
+



-
-
-
+
+
+





-
+


-
-
+
+

-
+








-
+

-
-
-
-
+
+
+
+

-
-
+
+





-
+

-
-
+
+


-
+






-
-
+
+

-
-
+
+

-
-
+
+


-
-
+
+

-
+

-
-
-
+
+
+


-
-
+
+



-
+

-
-
+
+

-
-
-
-
-
+
+
+
+
+



-
-
+
+

-
+

-
-
-
+
+
+

-
+

-
+

















-
+

-
+

-
+

-
+

-
+

-
+






-
-
+
+

-
+

-
-
-
+
+
+

-
+


-
-
-
+
+
+






-
-
+
+


-
+




-
-
+
+

-
-
+
+


-
+



-
+


-
-
-
+
+
+


-
-
+
+


-
+




-
-
+
+



-
-
+
+

-
+

-
+



-
+




-
+



-
+

-
+





-
-
-
+
+
+

-
-
-
-
+
+
+
+



-
+

-
+

-
+













-
-
+
+




	Tcl_DoWhenIdle(ManagerIdleProc, mgr);
	mgr->flags |= MGR_UPDATE_PENDING;
    }
    mgr->flags |= flags;
}

/* ++ RecomputeSize --
 * 	Recomputes the required size of the master window,
 * 	Recomputes the required size of the container window,
 * 	makes geometry request.
 */
static void RecomputeSize(Ttk_Manager *mgr)
{
    int width = 1, height = 1;

    if (mgr->managerSpec->RequestedSize(mgr->managerData, &width, &height)) {
	Tk_GeometryRequest(mgr->masterWindow, width, height);
	Tk_GeometryRequest(mgr->window, width, height);
	ScheduleUpdate(mgr, MGR_RELAYOUT_REQUIRED);
    }
    mgr->flags &= ~MGR_RESIZE_REQUIRED;
}

/* ++ RecomputeLayout --
 * 	Recompute geometry of all slaves.
 * 	Recompute geometry of all content windows.
 */
static void RecomputeLayout(Ttk_Manager *mgr)
{
    mgr->managerSpec->PlaceSlaves(mgr->managerData);
    mgr->managerSpec->PlaceContent(mgr->managerData);
    mgr->flags &= ~MGR_RELAYOUT_REQUIRED;
}

/* ++ ManagerIdleProc --
 * 	DoWhenIdle procedure for deferred updates.
 */
static void ManagerIdleProc(ClientData clientData)
{
    Ttk_Manager *mgr = clientData;
    Ttk_Manager *mgr = (Ttk_Manager *)clientData;
    mgr->flags &= ~MGR_UPDATE_PENDING;

    if (mgr->flags & MGR_RESIZE_REQUIRED) {
	RecomputeSize(mgr);
    }
    if (mgr->flags & MGR_RELAYOUT_REQUIRED) {
	if (mgr->flags & MGR_UPDATE_PENDING) {
	    /* RecomputeSize has scheduled another update; relayout later */
	    return;
	}
	RecomputeLayout(mgr);
    }
}

/*------------------------------------------------------------------------
 * +++ Event handlers.
 */

/* ++ ManagerEventHandler --
 * 	Recompute slave layout when master widget is resized.
 * 	Keep the slave's map state in sync with the master's.
 * 	Recompute content layout when container widget is resized.
 * 	Keep the content's map state in sync with the container's.
 */
static const int ManagerEventMask = StructureNotifyMask;
static void ManagerEventHandler(ClientData clientData, XEvent *eventPtr)
{
    Ttk_Manager *mgr = clientData;
    int i;
    Ttk_Manager *mgr = (Ttk_Manager *)clientData;
    TkSizeT i;

    switch (eventPtr->type)
    {
	case ConfigureNotify:
	    RecomputeLayout(mgr);
	    break;
	case MapNotify:
	    for (i = 0; i < mgr->nSlaves; ++i) {
		Ttk_Slave *slave = mgr->slaves[i];
		if (slave->flags & SLAVE_MAPPED) {
		    Tk_MapWindow(slave->slaveWindow);
	    for (i = 0; i < mgr->nContent; ++i) {
		Ttk_Content *content = mgr->content[i];
		if (content->flags & CONTENT_MAPPED) {
		    Tk_MapWindow(content->window);
		}
	    }
	    break;
	case UnmapNotify:
	    for (i = 0; i < mgr->nSlaves; ++i) {
		Ttk_Slave *slave = mgr->slaves[i];
		Tk_UnmapWindow(slave->slaveWindow);
	    for (i = 0; i < mgr->nContent; ++i) {
		Ttk_Content *content = mgr->content[i];
		Tk_UnmapWindow(content->window);
	    }
	    break;
    }
}

/* ++ SlaveEventHandler --
 * 	Notifies manager when a slave is destroyed
 * 	(see <<NOTE-LOSTSLAVE>>).
/* ++ ContentLostEventHandler --
 * 	Notifies manager when a content window is destroyed
 * 	(see <<NOTE-LOSTCONTENT>>).
 */
static const unsigned SlaveEventMask = StructureNotifyMask;
static void SlaveEventHandler(ClientData clientData, XEvent *eventPtr)
static void ContentLostEventHandler(void *clientData, XEvent *eventPtr)
{
    Ttk_Slave *slave = clientData;
    Ttk_Content *content = (Ttk_Content *)clientData;
    if (eventPtr->type == DestroyNotify) {
	slave->manager->managerSpec->tkGeomMgr.lostSlaveProc(
	    slave->manager, slave->slaveWindow);
	content->manager->managerSpec->tkGeomMgr.lostContentProc(
	    content->manager, content->window);
    }
}

/*------------------------------------------------------------------------
 * +++ Slave initialization and cleanup.
 * +++ Content initialization and cleanup.
 */

static Ttk_Slave *NewSlave(
    Ttk_Manager *mgr, Tk_Window slaveWindow, void *slaveData)
static Ttk_Content *NewContent(
    Ttk_Manager *mgr, Tk_Window window, void *data)
{
    Ttk_Slave *slave = ckalloc(sizeof(*slave));
    Ttk_Content *content = (Ttk_Content *)ckalloc(sizeof(Ttk_Content));

    slave->slaveWindow = slaveWindow;
    slave->manager = mgr;
    slave->flags = 0;
    slave->slaveData = slaveData;
    content->window = window;
    content->manager = mgr;
    content->flags = 0;
    content->data = data;

    return slave;
    return content;
}

static void DeleteSlave(Ttk_Slave *slave)
static void DeleteContent(Ttk_Content *content)
{
    ckfree(slave);
    ckfree(content);
}

/*------------------------------------------------------------------------
 * +++ Manager initialization and cleanup.
 */

Ttk_Manager *Ttk_CreateManager(
    Ttk_ManagerSpec *managerSpec, void *managerData, Tk_Window masterWindow)
    Ttk_ManagerSpec *managerSpec, void *managerData, Tk_Window window)
{
    Ttk_Manager *mgr = ckalloc(sizeof(*mgr));
    Ttk_Manager *mgr = (Ttk_Manager *)ckalloc(sizeof(*mgr));

    mgr->managerSpec 	= managerSpec;
    mgr->managerData	= managerData;
    mgr->masterWindow	= masterWindow;
    mgr->nSlaves 	= 0;
    mgr->slaves 	= NULL;
    mgr->window	= window;
    mgr->nContent 	= 0;
    mgr->content 	= NULL;
    mgr->flags  	= 0;

    Tk_CreateEventHandler(
	mgr->masterWindow, ManagerEventMask, ManagerEventHandler, mgr);
	mgr->window, ManagerEventMask, ManagerEventHandler, mgr);

    return mgr;
}

void Ttk_DeleteManager(Ttk_Manager *mgr)
{
    Tk_DeleteEventHandler(
	mgr->masterWindow, ManagerEventMask, ManagerEventHandler, mgr);
	mgr->window, ManagerEventMask, ManagerEventHandler, mgr);

    while (mgr->nSlaves > 0) {
	Ttk_ForgetSlave(mgr, mgr->nSlaves - 1);
    while (mgr->nContent > 0) {
	Ttk_ForgetContent(mgr, mgr->nContent - 1);
    }
    if (mgr->slaves) {
	ckfree(mgr->slaves);
    if (mgr->content) {
	ckfree(mgr->content);
    }

    Tcl_CancelIdleCall(ManagerIdleProc, mgr);

    ckfree(mgr);
}

/*------------------------------------------------------------------------
 * +++ Slave management.
 * +++ Content window management.
 */

/* ++ InsertSlave --
 * 	Adds slave to the list of managed windows.
/* ++ InsertContent --
 * 	Adds content to the list of managed windows.
 */
static void InsertSlave(Ttk_Manager *mgr, Ttk_Slave *slave, int index)
static void InsertContent(Ttk_Manager *mgr, Ttk_Content *content, TkSizeT index)
{
    int endIndex = mgr->nSlaves++;
    mgr->slaves = ckrealloc(mgr->slaves, mgr->nSlaves * sizeof(Ttk_Slave *));
    TkSizeT endIndex = mgr->nContent++;
    mgr->content = (Ttk_Content **)ckrealloc(mgr->content, mgr->nContent * sizeof(Ttk_Content *));

    while (endIndex > index) {
	mgr->slaves[endIndex] = mgr->slaves[endIndex - 1];
	mgr->content[endIndex] = mgr->content[endIndex - 1];
	--endIndex;
    }

    mgr->slaves[index] = slave;
    mgr->content[index] = content;

    Tk_ManageGeometry(slave->slaveWindow,
	&mgr->managerSpec->tkGeomMgr, (ClientData)mgr);
    Tk_ManageGeometry(content->window,
	&mgr->managerSpec->tkGeomMgr, mgr);

    Tk_CreateEventHandler(slave->slaveWindow,
	SlaveEventMask, SlaveEventHandler, (ClientData)slave);
    Tk_CreateEventHandler(content->window,
	StructureNotifyMask, ContentLostEventHandler, content);

    ScheduleUpdate(mgr, MGR_RESIZE_REQUIRED);
}

/* RemoveSlave --
 * 	Unmanage and delete the slave.
/* RemoveContent --
 * 	Unmanage and delete the content window.
 *
 * NOTES/ASSUMPTIONS:
 *
 * [1] It's safe to call Tk_UnmapWindow / Tk_UnmaintainGeometry even if this
 * routine is called from the slave's DestroyNotify event handler.
 * routine is called from the content window's DestroyNotify event handler.
 */
static void RemoveSlave(Ttk_Manager *mgr, int index)
static void RemoveContent(Ttk_Manager *mgr, TkSizeT index)
{
    Ttk_Slave *slave = mgr->slaves[index];
    int i;
    Ttk_Content *content = mgr->content[index];
    TkSizeT i;

    /* Notify manager:
     */
    mgr->managerSpec->SlaveRemoved(mgr->managerData, index);
    mgr->managerSpec->ContentRemoved(mgr->managerData, index);

    /* Remove from array:
     */
    --mgr->nSlaves;
    for (i = index ; i < mgr->nSlaves; ++i) {
	mgr->slaves[i] = mgr->slaves[i+1];
    --mgr->nContent;
    for (i = index ; i < mgr->nContent; ++i) {
	mgr->content[i] = mgr->content[i+1];
    }

    /* Clean up:
     */
    Tk_DeleteEventHandler(
	slave->slaveWindow, SlaveEventMask, SlaveEventHandler, slave);
	content->window, StructureNotifyMask, ContentLostEventHandler, content);

    /* Note [1] */
    Tk_UnmaintainGeometry(slave->slaveWindow, mgr->masterWindow);
    Tk_UnmapWindow(slave->slaveWindow);
    Tk_UnmaintainGeometry(content->window, mgr->window);
    Tk_UnmapWindow(content->window);

    DeleteSlave(slave);
    DeleteContent(content);

    ScheduleUpdate(mgr, MGR_RESIZE_REQUIRED);
}

/*------------------------------------------------------------------------
 * +++ Tk_GeomMgr hooks.
 */

void Ttk_GeometryRequestProc(ClientData clientData, Tk_Window slaveWindow)
void Ttk_GeometryRequestProc(ClientData clientData, Tk_Window window)
{
    Ttk_Manager *mgr = clientData;
    int slaveIndex = Ttk_SlaveIndex(mgr, slaveWindow);
    int reqWidth = Tk_ReqWidth(slaveWindow);
    int reqHeight= Tk_ReqHeight(slaveWindow);
    Ttk_Manager *mgr = (Ttk_Manager *)clientData;
    TkSizeT index = Ttk_ContentIndex(mgr, window);
    int reqWidth = Tk_ReqWidth(window);
    int reqHeight= Tk_ReqHeight(window);

    if (mgr->managerSpec->SlaveRequest(
		mgr->managerData, slaveIndex, reqWidth, reqHeight)) 
    if (mgr->managerSpec->ContentRequest(
		mgr->managerData, index, reqWidth, reqHeight))
    {
	ScheduleUpdate(mgr, MGR_RESIZE_REQUIRED);
    }
}

void Ttk_LostSlaveProc(ClientData clientData, Tk_Window slaveWindow)
void Ttk_LostContentProc(ClientData clientData, Tk_Window window)
{
    Ttk_Manager *mgr = clientData;
    int index = Ttk_SlaveIndex(mgr, slaveWindow);
    Ttk_Manager *mgr = (Ttk_Manager *)clientData;
    TkSizeT index = Ttk_ContentIndex(mgr, window);

    /* ASSERT: index >= 0 */
    RemoveSlave(mgr, index);
    RemoveContent(mgr, index);
}

/*------------------------------------------------------------------------
 * +++ Public API.
 */

/* ++ Ttk_InsertSlave --
 * 	Add a new slave window at the specified index.
/* ++ Ttk_InsertContent --
 * 	Add a new content window at the specified index.
 */
void Ttk_InsertSlave(
    Ttk_Manager *mgr, int index, Tk_Window tkwin, void *slaveData)
void Ttk_InsertContent(
    Ttk_Manager *mgr, TkSizeT index, Tk_Window tkwin, void *data)
{
    Ttk_Slave *slave = NewSlave(mgr, tkwin, slaveData);
    InsertSlave(mgr, slave, index);
    Ttk_Content *content = NewContent(mgr, tkwin, data);
    InsertContent(mgr, content, index);
}

/* ++ Ttk_ForgetSlave --
 * 	Unmanage the specified slave.
/* ++ Ttk_ForgetContent --
 * 	Unmanage the specified content window.
 */
void Ttk_ForgetSlave(Ttk_Manager *mgr, int slaveIndex)
void Ttk_ForgetContent(Ttk_Manager *mgr, TkSizeT index)
{
    Tk_Window slaveWindow = mgr->slaves[slaveIndex]->slaveWindow;
    RemoveSlave(mgr, slaveIndex);
    Tk_ManageGeometry(slaveWindow, NULL, 0);
    Tk_Window window = mgr->content[index]->window;
    RemoveContent(mgr, index);
    Tk_ManageGeometry(window, NULL, 0);
}

/* ++ Ttk_PlaceSlave --
 * 	Set the position and size of the specified slave window.
/* ++ Ttk_PlaceContent --
 * 	Set the position and size of the specified content window.
 *
 * NOTES:
 * 	Contrary to documentation, Tk_MaintainGeometry doesn't always
 * 	map the slave.
 * 	map the content window.
 */
void Ttk_PlaceSlave(
    Ttk_Manager *mgr, int slaveIndex, int x, int y, int width, int height)
void Ttk_PlaceContent(
    Ttk_Manager *mgr, TkSizeT index, int x, int y, int width, int height)
{
    Ttk_Slave *slave = mgr->slaves[slaveIndex];
    Tk_MaintainGeometry(slave->slaveWindow,mgr->masterWindow,x,y,width,height);
    slave->flags |= SLAVE_MAPPED;
    if (Tk_IsMapped(mgr->masterWindow)) {
	Tk_MapWindow(slave->slaveWindow);
    Ttk_Content *content = mgr->content[index];
    Tk_MaintainGeometry(content->window,mgr->window,x,y,width,height);
    content->flags |= CONTENT_MAPPED;
    if (Tk_IsMapped(mgr->window)) {
	Tk_MapWindow(content->window);
    }
}

/* ++ Ttk_UnmapSlave --
 * 	Unmap the specified slave, but leave it managed.
/* ++ Ttk_UnmapContent --
 * 	Unmap the specified content window, but leave it managed.
 */
void Ttk_UnmapSlave(Ttk_Manager *mgr, int slaveIndex)
void Ttk_UnmapContent(Ttk_Manager *mgr, TkSizeT index)
{
    Ttk_Slave *slave = mgr->slaves[slaveIndex];
    Tk_UnmaintainGeometry(slave->slaveWindow, mgr->masterWindow);
    slave->flags &= ~SLAVE_MAPPED;
    Ttk_Content *content = mgr->content[index];
    Tk_UnmaintainGeometry(content->window, mgr->window);
    content->flags &= ~CONTENT_MAPPED;
    /* Contrary to documentation, Tk_UnmaintainGeometry doesn't always
     * unmap the slave:
     * unmap the content window:
     */
    Tk_UnmapWindow(slave->slaveWindow);
    Tk_UnmapWindow(content->window);
}

/* LayoutChanged, SizeChanged --
 * 	Schedule a relayout, resp. resize request.
 */
void Ttk_ManagerLayoutChanged(Ttk_Manager *mgr)
{
    ScheduleUpdate(mgr, MGR_RELAYOUT_REQUIRED);
}

void Ttk_ManagerSizeChanged(Ttk_Manager *mgr)
{
    ScheduleUpdate(mgr, MGR_RESIZE_REQUIRED);
}

/* +++ Accessors.
 */
int Ttk_NumberSlaves(Ttk_Manager *mgr)
TkSizeT Ttk_NumberContent(Ttk_Manager *mgr)
{
    return mgr->nSlaves;
    return mgr->nContent;
}
void *Ttk_SlaveData(Ttk_Manager *mgr, int slaveIndex)
void *Ttk_ContentData(Ttk_Manager *mgr, TkSizeT index)
{
    return mgr->slaves[slaveIndex]->slaveData;
    return mgr->content[index]->data;
}
Tk_Window Ttk_SlaveWindow(Ttk_Manager *mgr, int slaveIndex)
Tk_Window Ttk_ContentWindow(Ttk_Manager *mgr, TkSizeT index)
{
    return mgr->slaves[slaveIndex]->slaveWindow;
    return mgr->content[index]->window;
}

/*------------------------------------------------------------------------
 * +++ Utility routines.
 */

/* ++ Ttk_SlaveIndex --
 * 	Returns the index of specified slave window, -1 if not found.
/* ++ Ttk_ContentIndex --
 * 	Returns the index of specified content window, -1 if not found.
 */
int Ttk_SlaveIndex(Ttk_Manager *mgr, Tk_Window slaveWindow)
TkSizeT Ttk_ContentIndex(Ttk_Manager *mgr, Tk_Window window)
{
    int index;
    for (index = 0; index < mgr->nSlaves; ++index)
	if (mgr->slaves[index]->slaveWindow == slaveWindow)
    TkSizeT index;
    for (index = 0; index < mgr->nContent; ++index)
	if (mgr->content[index]->window == window)
	    return index;
    return -1;
    return TCL_INDEX_NONE;
}

/* ++ Ttk_GetSlaveIndexFromObj(interp, mgr, objPtr, indexPtr) --
 * 	Return the index of the slave specified by objPtr.
 * 	Slaves may be specified as an integer index or
/* ++ Ttk_GetContentIndexFromObj(interp, mgr, objPtr, indexPtr) --
 * 	Return the index of the content window specified by objPtr.
 * 	Content windows may be specified as an integer index or
 * 	as the name of the managed window.
 *
 * Returns:
 * 	Standard Tcl completion code.  Leaves an error message in case of error.
 */

int Ttk_GetSlaveIndexFromObj(
    Tcl_Interp *interp, Ttk_Manager *mgr, Tcl_Obj *objPtr, int *indexPtr)
int Ttk_GetContentIndexFromObj(
    Tcl_Interp *interp, Ttk_Manager *mgr, Tcl_Obj *objPtr, TkSizeT *indexPtr)
{
    const char *string = Tcl_GetString(objPtr);
    int slaveIndex = 0;
    TkSizeT index = 0;
    Tk_Window tkwin;

    /* Try interpreting as an integer first:
     */
    if (Tcl_GetIntFromObj(NULL, objPtr, &slaveIndex) == TCL_OK) {
	if (slaveIndex < 0 || slaveIndex >= mgr->nSlaves) {
    if (TkGetIntForIndex(objPtr, mgr->nContent - 1, 1, &index) == TCL_OK) {
	if (index + 1 > mgr->nContent + 1) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"Slave index %d out of bounds", slaveIndex));
	    Tcl_SetErrorCode(interp, "TTK", "SLAVE", "INDEX", NULL);
		"Managed window index %d out of bounds", (int)index));
	    Tcl_SetErrorCode(interp, "TTK", "MANAGED", "INDEX", NULL);
	    return TCL_ERROR;
	}
	*indexPtr = slaveIndex;
	*indexPtr = index;
	return TCL_OK;
    }

    /* Try interpreting as a slave window name;
    /* Try interpreting as a window name;
     */
    if ((*string == '.') &&
	    (tkwin = Tk_NameToWindow(interp, string, mgr->masterWindow))) {
	slaveIndex = Ttk_SlaveIndex(mgr, tkwin);
	if (slaveIndex < 0) {
	    (tkwin = Tk_NameToWindow(interp, string, mgr->window))) {
	index = Ttk_ContentIndex(mgr, tkwin);
	if (index == TCL_INDEX_NONE) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "%s is not managed by %s", string,
		    Tk_PathName(mgr->masterWindow)));
	    Tcl_SetErrorCode(interp, "TTK", "SLAVE", "MANAGER", NULL);
		    Tk_PathName(mgr->window)));
	    Tcl_SetErrorCode(interp, "TTK", "MANAGED", "MANAGER", NULL);
	    return TCL_ERROR;
	}
	*indexPtr = slaveIndex;
	*indexPtr = index;
	return TCL_OK;
    }

    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
	    "Invalid slave specification %s", string));
    Tcl_SetErrorCode(interp, "TTK", "SLAVE", "SPEC", NULL);
	    "Invalid managed window specification %s", string));
    Tcl_SetErrorCode(interp, "TTK", "MANAGED", "SPEC", NULL);
    return TCL_ERROR;
}

/* ++ Ttk_ReorderSlave(mgr, fromIndex, toIndex) --
 * 	Change slave order.
/* ++ Ttk_ReorderContent(mgr, fromIndex, toIndex) --
 * 	Change content window order.
 */
void Ttk_ReorderSlave(Ttk_Manager *mgr, int fromIndex, int toIndex)
void Ttk_ReorderContent(Ttk_Manager *mgr, TkSizeT fromIndex, TkSizeT toIndex)
{
    Ttk_Slave *moved = mgr->slaves[fromIndex];
    Ttk_Content *moved = mgr->content[fromIndex];

    /* Shuffle down: */
    while (fromIndex > toIndex) {
	mgr->slaves[fromIndex] = mgr->slaves[fromIndex - 1];
	mgr->content[fromIndex] = mgr->content[fromIndex - 1];
	--fromIndex;
    }
    /* Or, shuffle up: */
    while (fromIndex < toIndex) {
	mgr->slaves[fromIndex] = mgr->slaves[fromIndex + 1];
	mgr->content[fromIndex] = mgr->content[fromIndex + 1];
	++fromIndex;
    }
    /* ASSERT: fromIndex == toIndex */
    mgr->slaves[fromIndex] = moved;
    mgr->content[fromIndex] = moved;

    /* Schedule a relayout.  In general, rearranging slaves
    /* Schedule a relayout.  In general, rearranging content
     * may also change the size:
     */
    ScheduleUpdate(mgr, MGR_RESIZE_REQUIRED);
}

/* ++ Ttk_Maintainable(interp, slave, master) --
 * 	Utility routine.  Verifies that 'master' may be used to maintain
 *	the geometry of 'slave' via Tk_MaintainGeometry:
/* ++ Ttk_Maintainable(interp, window, container) --
 * 	Utility routine.  Verifies that 'container' may be used to maintain
 *	the geometry of 'window' via Tk_MaintainGeometry:
 *
 * 	+ 'master' is either 'slave's parent -OR-
 * 	+ 'master is a descendant of 'slave's parent.
 * 	+ 'slave' is not a toplevel window
 * 	+ 'slave' belongs to the same toplevel as 'master'
 * 	+ 'container' is either 'window's parent -OR-
 * 	+ 'container is a descendant of 'window's parent.
 * 	+ 'window' is not a toplevel window
 * 	+ 'window' belongs to the same toplevel as 'container'
 *
 * Returns: 1 if OK; otherwise 0, leaving an error message in 'interp'.
 */
int Ttk_Maintainable(Tcl_Interp *interp, Tk_Window slave, Tk_Window master)
int Ttk_Maintainable(Tcl_Interp *interp, Tk_Window window, Tk_Window container)
{
    Tk_Window ancestor = master, parent = Tk_Parent(slave);
    Tk_Window ancestor = container, parent = Tk_Parent(window);

    if (Tk_IsTopLevel(slave) || slave == master) {
    if (Tk_IsTopLevel(window) || window == container) {
	goto badWindow;
    }

    while (ancestor != parent) {
	if (Tk_IsTopLevel(ancestor)) {
	    goto badWindow;
	}
	ancestor = Tk_Parent(ancestor);
    }

    return 1;

badWindow:
    Tcl_SetObjResult(interp, Tcl_ObjPrintf("can't add %s as slave of %s",
	    Tk_PathName(slave), Tk_PathName(master)));
    Tcl_SetObjResult(interp, Tcl_ObjPrintf("can't add %s as content of %s",
	    Tk_PathName(window), Tk_PathName(container)));
    Tcl_SetErrorCode(interp, "TTK", "GEOMETRY", "MAINTAINABLE", NULL);
    return 0;
}

Changes to generic/ttk/ttkManager.h.
1
2

3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

18
19
20


21
22
23


24
25
26


27
28
29
30
31
32
33
34
35



36
37
38
39
40

41
42


43
44
45
46
47
48

49
50

51
52


53

54

55

56
57


58

59
60
61



62

63
64


65
66
67
68
69
70
71

72
73


74

75
76


77
78
79
80
81



82

83
84


85

86
87


88
89
90


91
92
1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

17
18


19
20
21


22
23
24


25
26
27
28
29
30
31
32



33
34
35
36
37
38
39
40
41


42
43
44
45
46
47
48

49
50
51
52


53
54
55
56

57
58
59


60
61
62
63



64
65
66
67
68


69
70
71
72
73
74
75
76
77
78


79
80
81
82


83
84
85
86
87


88
89
90
91
92


93
94
95
96


97
98
99


100
101
102
103

-
+














-
+

-
-
+
+

-
-
+
+

-
-
+
+






-
-
-
+
+
+





+
-
-
+
+





-
+


+
-
-
+
+

+
-
+

+
-
-
+
+

+
-
-
-
+
+
+

+
-
-
+
+







+
-
-
+
+

+
-
-
+
+



-
-
+
+
+

+
-
-
+
+

+
-
-
+
+

-
-
+
+


/*
 * Copyright (c) 2005, Joe English.  Freely redistributable.
 * Copyright © 2005 Joe English.  Freely redistributable.
 *
 * Geometry manager utilities.
 */

#ifndef _TTKMANAGER
#define _TTKMANAGER

#include "ttkTheme.h"

typedef struct TtkManager_ Ttk_Manager;

/*
 * Geometry manager specification record:
 *
 * RequestedSize computes the requested size of the master window.
 * RequestedSize computes the requested size of the container window.
 *
 * PlaceSlaves sets the position and size of all managed slaves
 * by calling Ttk_PlaceSlave().
 * PlaceContent sets the position and size of all managed content windows
 * by calling Ttk_PlaceContent().
 *
 * SlaveRemoved() is called immediately before a slave is removed.
 * NB: the associated slave window may have been destroyed when this
 * ContentRemoved() is called immediately before a content window is removed.
 * NB: the associated content window may have been destroyed when this
 * routine is called.
 * 
 * SlaveRequest() is called when a slave requests a size change.
 *
 * ContentRequest() is called when a content window requests a size change.
 * It should return 1 if the request should propagate, 0 otherwise.
 */
typedef struct {			/* Manager hooks */
    Tk_GeomMgr tkGeomMgr;		/* "real" Tk Geometry Manager */

    int  (*RequestedSize)(void *managerData, int *widthPtr, int *heightPtr);
    void (*PlaceSlaves)(void *managerData);
    int  (*SlaveRequest)(void *managerData, int slaveIndex, int w, int h);
    void (*SlaveRemoved)(void *managerData, int slaveIndex);
    void (*PlaceContent)(void *managerData);
    int  (*ContentRequest)(void *managerData, TkSizeT index, int w, int h);
    void (*ContentRemoved)(void *managerData, TkSizeT index);
} Ttk_ManagerSpec;

/*
 * Default implementations for Tk_GeomMgr hooks:
 */
#define Ttk_LostSlaveProc Ttk_LostContentProc
MODULE_SCOPE void Ttk_GeometryRequestProc(ClientData, Tk_Window slave);
MODULE_SCOPE void Ttk_LostSlaveProc(ClientData, Tk_Window slave);
MODULE_SCOPE void Ttk_GeometryRequestProc(ClientData, Tk_Window window);
MODULE_SCOPE void Ttk_LostContentProc(ClientData, Tk_Window window);

/*
 * Public API:
 */
MODULE_SCOPE Ttk_Manager *Ttk_CreateManager(
	Ttk_ManagerSpec *, void *managerData, Tk_Window masterWindow);
	Ttk_ManagerSpec *, void *managerData, Tk_Window window);
MODULE_SCOPE void Ttk_DeleteManager(Ttk_Manager *);

#define  Ttk_InsertSlave Ttk_InsertContent
MODULE_SCOPE void Ttk_InsertSlave(
    Ttk_Manager *, int position, Tk_Window, void *slaveData);
MODULE_SCOPE void Ttk_InsertContent(
    Ttk_Manager *, TkSizeT position, Tk_Window, void *clientData);

#define Ttk_ForgetSlave Ttk_ForgetContent
MODULE_SCOPE void Ttk_ForgetSlave(Ttk_Manager *, int slaveIndex);
MODULE_SCOPE void Ttk_ForgetContent(Ttk_Manager *, TkSizeT index);

#define Ttk_ReorderSlave Ttk_ReorderContent
MODULE_SCOPE void Ttk_ReorderSlave(Ttk_Manager *, int fromIndex, int toIndex);
    /* Rearrange slave positions */
MODULE_SCOPE void Ttk_ReorderContent(Ttk_Manager *, TkSizeT fromIndex, TkSizeT toIndex);
    /* Rearrange content window positions */

#define Ttk_PlaceSlave Ttk_PlaceContent
MODULE_SCOPE void Ttk_PlaceSlave(
    Ttk_Manager *, int slaveIndex, int x, int y, int width, int height);
    /* Position and map the slave */
MODULE_SCOPE void Ttk_PlaceContent(
    Ttk_Manager *, TkSizeT index, int x, int y, int width, int height);
    /* Position and map the content window */

#define Ttk_UnmapSlave Ttk_UnmapContent
MODULE_SCOPE void Ttk_UnmapSlave(Ttk_Manager *, int slaveIndex);
    /* Unmap the slave */
MODULE_SCOPE void Ttk_UnmapContent(Ttk_Manager *, TkSizeT index);
    /* Unmap the content window */

MODULE_SCOPE void Ttk_ManagerSizeChanged(Ttk_Manager *);
MODULE_SCOPE void Ttk_ManagerLayoutChanged(Ttk_Manager *);
    /* Notify manager that size (resp. layout) needs to be recomputed */

/* Utilities:
 */
#define Ttk_SlaveIndex Ttk_ContentIndex
MODULE_SCOPE int Ttk_SlaveIndex(Ttk_Manager *, Tk_Window);
    /* Returns: index in slave array of specified window, -1 if not found */
MODULE_SCOPE TkSizeT Ttk_ContentIndex(Ttk_Manager *, Tk_Window);
    /* Returns: index in content array of specified window, TCL_INDEX_NONE if not found */

#define Ttk_GetSlaveIndexFromObj Ttk_GetContentIndexFromObj
MODULE_SCOPE int Ttk_GetSlaveIndexFromObj(
    Tcl_Interp *, Ttk_Manager *, Tcl_Obj *, int *indexPtr);
MODULE_SCOPE int Ttk_GetContentIndexFromObj(
    Tcl_Interp *, Ttk_Manager *, Tcl_Obj *, TkSizeT *indexPtr);

/* Accessor functions:
 */
MODULE_SCOPE int Ttk_NumberSlaves(Ttk_Manager *);
    /* Returns: number of managed slaves */
#define Ttk_NumberSlaves Ttk_NumberContent
MODULE_SCOPE TkSizeT Ttk_NumberContent(Ttk_Manager *);
    /* Returns: number of managed content windows */

#define Ttk_SlaveData Ttk_ContentData
MODULE_SCOPE void *Ttk_SlaveData(Ttk_Manager *, int slaveIndex);
    /* Returns: client data associated with slave */
MODULE_SCOPE void *Ttk_ContentData(Ttk_Manager *, TkSizeT index);
    /* Returns: client data associated with content window */

#define Ttk_SlaveWindow Ttk_ContentWindow
MODULE_SCOPE Tk_Window Ttk_SlaveWindow(Ttk_Manager *, int slaveIndex);
    /* Returns: slave window */
MODULE_SCOPE Tk_Window Ttk_ContentWindow(Ttk_Manager *, TkSizeT index);
    /* Returns: content window */

MODULE_SCOPE int Ttk_Maintainable(Tcl_Interp *, Tk_Window slave, Tk_Window master);
    /* Returns: 1 if master can manage slave; 0 otherwise leaving error msg */
MODULE_SCOPE int Ttk_Maintainable(Tcl_Interp *, Tk_Window content, Tk_Window container);
    /* Returns: 1 if container can manage content; 0 otherwise leaving error msg */

#endif /* _TTKMANAGER */
Changes to generic/ttk/ttkNotebook.c.
1
2

3
4
5
6
7
8

9
10
11
12
13
14
15
16
1

2
3
4




5

6
7
8
9
10
11
12

-
+


-
-
-
-
+
-







/*
 * Copyright (c) 2004, Joe English
 * Copyright © 2004 Joe English
 */

#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <tk.h>
#include "tkInt.h"

#include "ttkTheme.h"
#include "ttkWidget.h"
#include "ttkManager.h"

#define MIN(a,b) ((a) < (b) ? (a) : (b))
#define MAX(a,b) ((a) > (b) ? (a) : (b))

53
54
55
56
57
58
59
60

61
62

63
64
65
66


67
68

69
70

71
72
73


74
75

76
77
78
79

80
81
82

83
84

85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102


103
104
105

106
107
108
109
110
111
112
113
114

115
116
117

118
119
120

121
122
123

124
125
126
127
128
129
130
49
50
51
52
53
54
55

56
57

58
59
60


61
62
63

64
65

66
67


68
69
70

71
72
73
74

75
76
77

78
79

80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96


97
98
99
100

101
102
103
104
105
106
107
108
109

110
111
112

113
114
115

116
117
118

119
120
121
122
123
124
125
126







-
+

-
+


-
-
+
+

-
+

-
+

-
-
+
+

-
+



-
+


-
+

-
+
















-
-
+
+


-
+








-
+


-
+


-
+


-
+







} Tab;

/* Two different option tables are used for tabs:
 * TabOptionSpecs is used to draw the tab, and only includes resources
 * relevant to the tab.
 *
 * PaneOptionSpecs includes additional options for child window placement
 * and is used to configure the slave.
 * and is used to configure the pane.
 */
static Tk_OptionSpec TabOptionSpecs[] =
static const Tk_OptionSpec TabOptionSpecs[] =
{
    {TK_OPTION_STRING_TABLE, "-state", "", "",
	"normal", -1,Tk_Offset(Tab,state),
	0,(ClientData)TabStateStrings,0 },
	"normal", TCL_INDEX_NONE, offsetof(Tab,state),
	0, (void *)TabStateStrings, 0 },
    {TK_OPTION_STRING, "-text", "text", "Text", "",
	Tk_Offset(Tab,textObj), -1, 0,0,GEOMETRY_CHANGED },
	offsetof(Tab,textObj), TCL_INDEX_NONE, 0, 0, GEOMETRY_CHANGED },
    {TK_OPTION_STRING, "-image", "image", "Image", NULL/*default*/,
	Tk_Offset(Tab,imageObj), -1, TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },
	offsetof(Tab,imageObj), TCL_INDEX_NONE, TK_OPTION_NULL_OK, 0, GEOMETRY_CHANGED },
    {TK_OPTION_STRING_TABLE, "-compound", "compound", "Compound",
	NULL, Tk_Offset(Tab,compoundObj), -1,
	TK_OPTION_NULL_OK,(ClientData)ttkCompoundStrings,GEOMETRY_CHANGED },
	NULL, offsetof(Tab,compoundObj), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK,(void *)ttkCompoundStrings,GEOMETRY_CHANGED },
    {TK_OPTION_INT, "-underline", "underline", "Underline", "-1",
	Tk_Offset(Tab,underlineObj), -1, 0,0,GEOMETRY_CHANGED },
	offsetof(Tab,underlineObj), TCL_INDEX_NONE, 0, 0, GEOMETRY_CHANGED },
    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0 }
};

static Tk_OptionSpec PaneOptionSpecs[] =
static const Tk_OptionSpec PaneOptionSpecs[] =
{
    {TK_OPTION_STRING, "-padding", "padding", "Padding", "0",
	Tk_Offset(Tab,paddingObj), -1, 0,0,GEOMETRY_CHANGED },
	offsetof(Tab,paddingObj), TCL_INDEX_NONE, 0, 0, GEOMETRY_CHANGED },
    {TK_OPTION_STRING, "-sticky", "sticky", "Sticky", "nsew",
	Tk_Offset(Tab,stickyObj), -1, 0,0,GEOMETRY_CHANGED },
	offsetof(Tab,stickyObj), TCL_INDEX_NONE, 0, 0, GEOMETRY_CHANGED },

    WIDGET_INHERIT_OPTIONS(TabOptionSpecs)
};

/*------------------------------------------------------------------------
 * +++ Notebook resources.
 */
typedef struct
{
    Tcl_Obj *widthObj;		/* Default width */
    Tcl_Obj *heightObj;		/* Default height */
    Tcl_Obj *paddingObj;	/* Padding around notebook */

    Ttk_Manager *mgr;		/* Geometry manager */
    Tk_OptionTable tabOptionTable;	/* Tab options */
    Tk_OptionTable paneOptionTable;	/* Tab+pane options */
    int currentIndex;		/* index of currently selected tab */
    int activeIndex;		/* index of currently active tab */
    TkSizeT currentIndex;		/* index of currently selected tab */
    TkSizeT activeIndex;		/* index of currently active tab */
    Ttk_Layout tabLayout;	/* Sublayout for tabs */

    Ttk_Box clientArea;		/* Where to pack slave widgets */
    Ttk_Box clientArea;		/* Where to pack content windows */
} NotebookPart;

typedef struct
{
    WidgetCore core;
    NotebookPart notebook;
} Notebook;

static Tk_OptionSpec NotebookOptionSpecs[] =
static const Tk_OptionSpec NotebookOptionSpecs[] =
{
    {TK_OPTION_INT, "-width", "width", "Width", "0",
	Tk_Offset(Notebook,notebook.widthObj),-1,
	offsetof(Notebook,notebook.widthObj),TCL_INDEX_NONE,
	0,0,GEOMETRY_CHANGED },
    {TK_OPTION_INT, "-height", "height", "Height", "0",
	Tk_Offset(Notebook,notebook.heightObj),-1,
	offsetof(Notebook,notebook.heightObj),TCL_INDEX_NONE,
	0,0,GEOMETRY_CHANGED },
    {TK_OPTION_STRING, "-padding", "padding", "Padding", NULL,
	Tk_Offset(Notebook,notebook.paddingObj),-1,
	offsetof(Notebook,notebook.paddingObj),TCL_INDEX_NONE,
	TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },

    WIDGET_TAKEFOCUS_TRUE,
    WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs)
};

/* Notebook style options:
187
188
189
190
191
192
193
194

195
196
197

198
199
200

201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216

217
218
219
220
221
222
223
224
225


226
227
228
229
230
231
232
233
234
235
236
237

238
239
240
241
242
243
244
183
184
185
186
187
188
189

190
191
192

193
194
195

196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211

212
213
214
215
216
217
218
219


220
221
222
223
224
225
226
227
228
229
230
231
232

233
234
235
236
237
238
239
240







-
+


-
+


-
+















-
+







-
-
+
+











-
+







    }
}

/*------------------------------------------------------------------------
 * +++ Tab management.
 */

static Tab *CreateTab(Tcl_Interp *interp, Notebook *nb, Tk_Window slaveWindow)
static Tab *CreateTab(Tcl_Interp *interp, Notebook *nb, Tk_Window window)
{
    Tk_OptionTable optionTable = nb->notebook.paneOptionTable;
    void *record = ckalloc(sizeof(Tab));
    Tab *record = (Tab *)ckalloc(sizeof(Tab));
    memset(record, 0, sizeof(Tab));

    if (Tk_InitOptions(interp, record, optionTable, slaveWindow) != TCL_OK) {
    if (Tk_InitOptions(interp, record, optionTable, window) != TCL_OK) {
	ckfree(record);
	return NULL;
    }

    return record;
}

static void DestroyTab(Notebook *nb, Tab *tab)
{
    void *record = tab;
    Tk_FreeConfigOptions(record, nb->notebook.paneOptionTable, nb->core.tkwin);
    ckfree(record);
}

static int ConfigureTab(
    Tcl_Interp *interp, Notebook *nb, Tab *tab, Tk_Window slaveWindow,
    Tcl_Interp *interp, Notebook *nb, Tab *tab, Tk_Window window,
    int objc, Tcl_Obj *const objv[])
{
    Ttk_Sticky sticky = tab->sticky;
    Ttk_Padding padding = tab->padding;
    Tk_SavedOptions savedOptions;
    int mask = 0;

    if (Tk_SetOptions(interp, (ClientData)tab, nb->notebook.paneOptionTable,
	    objc, objv, slaveWindow, &savedOptions, &mask) != TCL_OK)
    if (Tk_SetOptions(interp, tab, nb->notebook.paneOptionTable,
	    objc, objv, window, &savedOptions, &mask) != TCL_OK)
    {
	return TCL_ERROR;
    }

    /* Check options:
     * @@@ TODO: validate -image option.
     */
    if (Ttk_GetStickyFromObj(interp, tab->stickyObj, &sticky) != TCL_OK)
    {
	goto error;
    }
    if (Ttk_GetPaddingFromObj(interp, slaveWindow, tab->paddingObj, &padding)
    if (Ttk_GetPaddingFromObj(interp, window, tab->paddingObj, &padding)
	    != TCL_OK)
    {
	goto error;
    }

    tab->sticky = sticky;
    tab->padding = padding;
254
255
256
257
258
259
260
261

262
263
264
265



266
267
268
269
270
271
272

273
274
275
276
277
278
279

280
281
282
283
284
285
286
287
288
289
290
291
292
293
294

295
296
297
298


299
300
301
302
303
304
305
306
307
308
309
310


311
312
313
314
315
316
317
318
319
320


321
322
323
324
325
326
327
328
329

330
331
332
333
334
335
336
250
251
252
253
254
255
256

257
258



259
260
261
262
263
264
265
266
267

268
269
270
271
272
273
274

275
276
277
278
279
280
281
282
283
284
285
286
287
288
289

290
291
292


293
294
295
296
297
298
299
300
301
302
303
304


305
306
307
308
309
310
311
312
313
314


315
316
317
318
319
320
321
322
323
324

325
326
327
328
329
330
331
332







-
+

-
-
-
+
+
+






-
+






-
+














-
+


-
-
+
+










-
-
+
+








-
-
+
+








-
+







}

/*
 * IdentifyTab --
 * 	Return the index of the tab at point x,y,
 * 	or -1 if no tab at that point.
 */
static int IdentifyTab(Notebook *nb, int x, int y)
static TkSizeT IdentifyTab(Notebook *nb, int x, int y)
{
    int index;
    for (index = 0; index < Ttk_NumberSlaves(nb->notebook.mgr); ++index) {
	Tab *tab = Ttk_SlaveData(nb->notebook.mgr,index);
    TkSizeT index;
    for (index = 0; index < Ttk_NumberContent(nb->notebook.mgr); ++index) {
	Tab *tab = (Tab *)Ttk_ContentData(nb->notebook.mgr,index);
	if (	tab->state != TAB_STATE_HIDDEN
	     && Ttk_BoxContains(tab->parcel, x,y))
	{
	    return index;
	}
    }
    return -1;
    return TCL_INDEX_NONE;
}

/*
 * ActivateTab --
 * 	Set the active tab index, redisplay if necessary.
 */
static void ActivateTab(Notebook *nb, int index)
static void ActivateTab(Notebook *nb, TkSizeT index)
{
    if (index != nb->notebook.activeIndex) {
	nb->notebook.activeIndex = index;
	TtkRedisplayWidget(&nb->core);
    }
}

/*
 * TabState --
 * 	Return the state of the specified tab, based on
 * 	notebook state, currentIndex, activeIndex, and user-specified tab state.
 *	The USER1 bit is set for the leftmost visible tab, and USER2
 * 	is set for the rightmost visible tab.
 */
static Ttk_State TabState(Notebook *nb, int index)
static Ttk_State TabState(Notebook *nb, TkSizeT index)
{
    Ttk_State state = nb->core.state;
    Tab *tab = Ttk_SlaveData(nb->notebook.mgr, index);
    int i = 0;
    Tab *itab = (Tab *)Ttk_ContentData(nb->notebook.mgr, index);
    TkSizeT i = 0;

    if (index == nb->notebook.currentIndex) {
	state |= TTK_STATE_SELECTED;
    } else {
	state &= ~TTK_STATE_FOCUS;
    }

    if (index == nb->notebook.activeIndex) {
	state |= TTK_STATE_ACTIVE;
    }
    for (i = 0; i < Ttk_NumberSlaves(nb->notebook.mgr); ++i) {
	Tab *tab = Ttk_SlaveData(nb->notebook.mgr, i);
    for (i = 0; i < Ttk_NumberContent(nb->notebook.mgr); ++i) {
	Tab *tab = (Tab *)Ttk_ContentData(nb->notebook.mgr, i);
	if (tab->state == TAB_STATE_HIDDEN) {
	    continue;
	}
	if (index == i) {
	    state |= TTK_STATE_USER1;
	}
	break;
    }
    for (i = Ttk_NumberSlaves(nb->notebook.mgr) - 1; i >= 0; --i) {
	Tab *tab = Ttk_SlaveData(nb->notebook.mgr, i);
    for (i = Ttk_NumberContent(nb->notebook.mgr) - 1; i != TCL_INDEX_NONE; --i) {
	Tab *tab = (Tab *)Ttk_ContentData(nb->notebook.mgr, i);
	if (tab->state == TAB_STATE_HIDDEN) {
	    continue;
	}
	if (index == i) {
	    state |= TTK_STATE_USER2;
	}
	break;
    }
    if (tab->state == TAB_STATE_DISABLED) {
    if (itab->state == TAB_STATE_DISABLED) {
	state |= TTK_STATE_DISABLED;
    }

    return state;
}

/*------------------------------------------------------------------------
351
352
353
354
355
356
357
358

359
360
361


362
363
364
365
366
367
368
347
348
349
350
351
352
353

354
355


356
357
358
359
360
361
362
363
364







-
+

-
-
+
+







 * 	(max height/width) but not parallel (total width/height).
 */
static void TabrowSize(
    Notebook *nb, Ttk_Orient orient, int minTabWidth, int *widthPtr, int *heightPtr)
{
    Ttk_Layout tabLayout = nb->notebook.tabLayout;
    int tabrowWidth = 0, tabrowHeight = 0;
    int i;
    TkSizeT i;

    for (i = 0; i < Ttk_NumberSlaves(nb->notebook.mgr); ++i) {
	Tab *tab = Ttk_SlaveData(nb->notebook.mgr, i);
    for (i = 0; i < Ttk_NumberContent(nb->notebook.mgr); ++i) {
	Tab *tab = (Tab *)Ttk_ContentData(nb->notebook.mgr, i);
	Ttk_State tabState = TabState(nb,i);

	Ttk_RebindSublayout(tabLayout, tab);
	Ttk_LayoutSize(tabLayout,tabState,&tab->width,&tab->height);
        tab->width = MAX(tab->width, minTabWidth);

	if (orient == TTK_ORIENT_HORIZONTAL) {
378
379
380
381
382
383
384
385

386
387
388
389
390
391

392
393
394
395
396
397
398

399
400
401
402

403
404
405
406
407
408
409
410







411
412
413


414
415
416
417
418
419
420
374
375
376
377
378
379
380

381
382
383
384
385
386

387
388
389
390
391
392
393

394
395
396
397

398
399







400
401
402
403
404
405
406
407


408
409
410
411
412
413
414
415
416







-
+





-
+






-
+



-
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
+
+







    *heightPtr = tabrowHeight;
}

/* NotebookSize -- GM and widget size hook.
 *
 * Total height is tab height + client area height + pane internal padding
 * Total width is max(client width, tab width) + pane internal padding
 * Client area size determined by max size of slaves,
 * Client area size determined by max size of content windows,
 * overridden by -width and/or -height if nonzero.
 */

static int NotebookSize(void *clientData, int *widthPtr, int *heightPtr)
{
    Notebook *nb = clientData;
    Notebook *nb = (Notebook *)clientData;
    NotebookStyle nbstyle;
    Ttk_Padding padding;
    Ttk_Element clientNode = Ttk_FindElement(nb->core.layout, "client");
    int clientWidth = 0, clientHeight = 0,
    	reqWidth = 0, reqHeight = 0,
	tabrowWidth = 0, tabrowHeight = 0;
    int i;
    TkSizeT i;

    NotebookStyleOptions(nb, &nbstyle);

    /* Compute max requested size of all slaves:
    /* Compute max requested size of all content windows:
     */
    for (i = 0; i < Ttk_NumberSlaves(nb->notebook.mgr); ++i) {
	Tk_Window slaveWindow = Ttk_SlaveWindow(nb->notebook.mgr, i);
	Tab *tab = Ttk_SlaveData(nb->notebook.mgr, i);
	int slaveWidth
	    = Tk_ReqWidth(slaveWindow) + Ttk_PaddingWidth(tab->padding);
	int slaveHeight
	    = Tk_ReqHeight(slaveWindow) + Ttk_PaddingHeight(tab->padding);
    for (i = 0; i < Ttk_NumberContent(nb->notebook.mgr); ++i) {
	Tk_Window window = Ttk_ContentWindow(nb->notebook.mgr, i);
	Tab *tab = (Tab *)Ttk_ContentData(nb->notebook.mgr, i);
	int width
	    = Tk_ReqWidth(window) + Ttk_PaddingWidth(tab->padding);
	int height
	    = Tk_ReqHeight(window) + Ttk_PaddingHeight(tab->padding);

	clientWidth = MAX(clientWidth, slaveWidth);
	clientHeight = MAX(clientHeight, slaveHeight);
	clientWidth = MAX(clientWidth, width);
	clientHeight = MAX(clientHeight, height);
    }

    /* Client width/height overridable by widget options:
     */
    Tcl_GetIntFromObj(NULL, nb->notebook.widthObj,&reqWidth);
    Tcl_GetIntFromObj(NULL, nb->notebook.heightObj,&reqHeight);
    if (reqWidth > 0)
461
462
463
464
465
466
467
468

469
470
471
472
473
474
475
476
477

478
479
480
481
482
483
484
485
486
487
488
489
490
491
492

493
494
495
496

497
498
499
500
501
502
503
457
458
459
460
461
462
463

464
465
466
467
468
469
470
471
472

473
474
475
476
477
478
479
480
481
482
483
484
485
486
487

488
489
490
491

492
493
494
495
496
497
498
499







-
+








-
+














-
+



-
+







 * @@@ <<NOTE-TABPOSITION>> bug: only works for horizontal orientations
 * @@@ <<NOTE-SQUEEZE-HIDDEN>> does not account for hidden tabs.
 */

static void SqueezeTabs(
    Notebook *nb, int needed, int available)
{
    int nTabs = Ttk_NumberSlaves(nb->notebook.mgr);
    int nTabs = Ttk_NumberContent(nb->notebook.mgr);

    if (nTabs > 0) {
	int difference = available - needed;
	double delta = (double)difference / needed;
	double slack = 0;
	int i;

	for (i = 0; i < nTabs; ++i) {
	    Tab *tab = Ttk_SlaveData(nb->notebook.mgr,i);
	    Tab *tab = (Tab *)Ttk_ContentData(nb->notebook.mgr,i);
	    double ad = slack + tab->width * delta;
	    tab->width += (int)ad;
	    slack = ad - (int)ad;
	}
    }
}

/* PlaceTabs --
 * 	Compute all tab parcels.
 */
static void PlaceTabs(
    Notebook *nb, Ttk_Box tabrowBox, Ttk_PositionSpec tabPlacement)
{
    Ttk_Layout tabLayout = nb->notebook.tabLayout;
    int nTabs = Ttk_NumberSlaves(nb->notebook.mgr);
    int nTabs = Ttk_NumberContent(nb->notebook.mgr);
    int i;

    for (i = 0; i < nTabs; ++i) {
	Tab *tab = Ttk_SlaveData(nb->notebook.mgr, i);
	Tab *tab = (Tab *)Ttk_ContentData(nb->notebook.mgr, i);
	Ttk_State tabState = TabState(nb, i);

	if (tab->state != TAB_STATE_HIDDEN) {
	    Ttk_Padding expand = Ttk_UniformPadding(0);
	    Tcl_Obj *expandObj = Ttk_QueryOption(tabLayout,"-expand",tabState);

	    if (expandObj) {
513
514
515
516
517
518
519
520

521
522
523
524

525
526
527
528
529
530
531
509
510
511
512
513
514
515

516
517
518
519

520
521
522
523
524
525
526
527







-
+



-
+







    }
}

/* NotebookDoLayout --
 *	Computes notebook layout and places tabs.
 *
 * Side effects:
 * 	Sets clientArea, used to place slave panes.
 * 	Sets clientArea, used to place panes.
 */
static void NotebookDoLayout(void *recordPtr)
{
    Notebook *nb = recordPtr;
    Notebook *nb = (Notebook *)recordPtr;
    Tk_Window nbwin = nb->core.tkwin;
    Ttk_Box cavity = Ttk_WinBox(nbwin);
    int tabrowWidth = 0, tabrowHeight = 0;
    Ttk_Element clientNode = Ttk_FindElement(nb->core.layout, "client");
    Ttk_Box tabrowBox;
    NotebookStyle nbstyle;

567
568
569
570
571
572
573
574

575
576

577
578

579
580
581
582



583
584

585
586
587


588
589
590

591
592
593

594
595
596
597



598
599

600
601
602
603
604
605
606
607

608
609
610


611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627


628
629
630
631


632
633
634
635

636
637
638

639
640
641
642
643
644
645
646
647
648
649


650
651
652
653
654


655
656
657
658
659
660
661
662
663


664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684


685
686
687


688
689
690

691
692
693
694
695
696
697
698

699
700

701
702

703
704
705


706
707
708
709
710
711

712
713
714
715
716
717
718
719
720





721
722
723
724
725
726
727
728
729
730

731
732
733
734

735
736
737
738

739
740

741
742
743
744
745
746
747
748

749
750
751
752

753
754
755
756
757

758
759
760
761

762
763

764
765
766
767
768
769
770
771

772
773

774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792

793
794
795
796
797
798

799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816

817
818
819
820
821
822
823
824
825
826

827
828
829
830
831

832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847

848
849

850
851
852
853





854
855



856
857
858
859
860
861
862
863
864
865
866

867
868





869
870



871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888

889
890
891


892
893
894
895
896
897
898
899
900


901
902
903

904
905
906


907
908
909

910
911
912
913

914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931




932
933
934

935
936
937
938
939
940

941
942
943
944
945
946

947
948

949
950
951

952
953
954
955
956
957



958
959

960
961
962


963
964
965

966
967
968
969


970
971
972
973
974
975
976


977
978

979
980
981
982

983
984
985

986
987

988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003


1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014

1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027


1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039

1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056

1057
1058
1059

1060
1061


1062
1063
1064
1065
1066
1067
1068

1069
1070
1071
1072
1073
1074
1075
1076
1077
1078


1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098


1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114



1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132



1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145

1146
1147
1148
1149


1150
1151
1152
1153
1154

1155

1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171

1172
1173
1174

1175
1176
1177
1178
1179
1180
1181
1182
1183


1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196

1197
1198
1199


1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212


1213
1214
1215
1216

1217
1218
1219

1220
1221
1222

1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241

1242
1243
1244
1245
1246
1247
1248
1249

1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261

1262
1263
1264
1265
1266
1267
1268
1269
1270


1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281

1282
1283
1284
1285
1286
1287
1288
1289
1290

1291
1292
1293
1294
1295
1296
1297
563
564
565
566
567
568
569

570
571

572
573

574
575



576
577
578
579

580
581


582
583
584
585

586
587
588

589
590



591
592
593
594

595
596
597
598
599
600
601
602

603
604


605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621


622
623
624
625


626
627
628
629
630

631
632
633

634
635
636
637
638
639
640
641
642
643


644
645
646
647
648


649
650
651
652
653
654
655
656
657


658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678


679
680
681


682
683
684
685

686
687
688
689
690
691
692
693

694
695

696
697

698
699


700
701
702
703
704
705
706

707
708
709
710
711
712
713
714
715

716
717
718
719
720
721
722
723
724
725
726
727
728
729

730
731
732
733

734
735
736
737

738
739

740
741
742
743
744
745
746
747

748
749
750
751

752
753
754
755
756

757
758
759
760

761
762

763
764
765
766
767
768
769
770

771
772

773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791

792
793
794
795
796
797

798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815

816
817
818
819
820
821
822
823
824
825

826
827
828
829
830

831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846

847
848

849
850
851
852
853
854
855
856
857
858


859
860
861
862
863
864
865
866
867
868
869
870
871

872
873
874
875
876
877
878
879


880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899

900



901
902
903
904
905
906
907
908
909


910
911
912
913

914
915


916
917
918
919

920
921
922
923

924
925
926
927
928
929
930
931
932
933
934
935
936
937
938




939
940
941
942
943
944

945
946
947
948



949
950
951
952
953
954

955
956

957
958
959

960
961
962
963



964
965
966
967

968
969
970
971
972
973
974
975

976
977
978


979
980
981
982
983
984
985


986
987
988

989
990
991
992

993
994
995

996
997

998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012


1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024

1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036


1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049

1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066

1067
1068
1069

1070
1071

1072
1073
1074
1075
1076
1077
1078
1079

1080
1081
1082
1083
1084
1085
1086
1087
1088


1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108


1109
1110

1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123


1124
1125
1126
1127
1128
1129
1130
1131
1132









1133


1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148

1149
1150
1151


1152
1153
1154
1155
1156
1157
1158
1159

1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175

1176
1177
1178

1179
1180
1181
1182
1183
1184
1185
1186


1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200

1201
1202


1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215


1216
1217
1218
1219
1220

1221
1222
1223

1224
1225
1226

1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244

1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266

1267
1268
1269
1270
1271
1272
1273
1274


1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286

1287
1288
1289
1290
1291
1292
1293
1294
1295

1296
1297
1298
1299
1300
1301
1302
1303







-
+

-
+

-
+

-
-
-
+
+
+

-
+

-
-
+
+


-
+


-
+

-
-
-
+
+
+

-
+







-
+

-
-
+
+















-
-
+
+


-
-
+
+



-
+


-
+









-
-
+
+



-
-
+
+







-
-
+
+



















-
-
+
+

-
-
+
+


-
+







-
+

-
+

-
+

-
-
+
+





-
+








-
+
+
+
+
+









-
+



-
+



-
+

-
+







-
+



-
+




-
+



-
+

-
+







-
+

-
+


















-
+





-
+

















-
+









-
+




-
+















-
+

-
+




+
+
+
+
+
-
-
+
+
+










-
+


+
+
+
+
+
-
-
+
+
+

















-
+
-
-
-
+
+







-
-
+
+


-
+

-
-
+
+


-
+



-
+














-
-
-
-
+
+
+
+


-
+



-
-
-
+





-
+

-
+


-
+



-
-
-
+
+
+

-
+



+
+


-
+


-
-
+
+





-
-
+
+

-
+



-
+


-
+

-
+














-
-
+
+










-
+











-
-
+
+











-
+
















-
+


-
+

-
+
+






-
+








-
-
+
+


















-
-
+
+
-













-
-
+
+
+






-
-
-
-
-
-
-
-
-

-
-
+
+
+












-
+


-
-
+
+





+
-
+















-
+


-
+







-
-
+
+












-
+

-
-
+
+











-
-
+
+



-
+


-
+


-
+

















-

+








+











-
+







-
-
+
+










-
+








-
+







    if (cavity.height <= 0) cavity.height = 1;
    if (cavity.width <= 0) cavity.width = 1;

    nb->notebook.clientArea = cavity;
}

/*
 * NotebookPlaceSlave --
 * NotebookPlaceContent --
 * 	Set the position and size of a child widget
 * 	based on the current client area and slave options:
 * 	based on the current client area and content window options:
 */
static void NotebookPlaceSlave(Notebook *nb, int slaveIndex)
static void NotebookPlaceContent(Notebook *nb, TkSizeT index)
{
    Tab *tab = Ttk_SlaveData(nb->notebook.mgr, slaveIndex);
    Tk_Window slaveWindow = Ttk_SlaveWindow(nb->notebook.mgr, slaveIndex);
    Ttk_Box slaveBox =
    Tab *tab = (Tab *)Ttk_ContentData(nb->notebook.mgr, index);
    Tk_Window window = Ttk_ContentWindow(nb->notebook.mgr, index);
    Ttk_Box box =
	Ttk_StickBox(Ttk_PadBox(nb->notebook.clientArea, tab->padding),
	    Tk_ReqWidth(slaveWindow), Tk_ReqHeight(slaveWindow),tab->sticky);
	    Tk_ReqWidth(window), Tk_ReqHeight(window),tab->sticky);

    Ttk_PlaceSlave(nb->notebook.mgr, slaveIndex,
	slaveBox.x, slaveBox.y, slaveBox.width, slaveBox.height);
    Ttk_PlaceContent(nb->notebook.mgr, index,
	box.x, box.y, box.width, box.height);
}

/* NotebookPlaceSlaves --
/* NotebookPlaceContents --
 * 	Geometry manager hook.
 */
static void NotebookPlaceSlaves(void *recordPtr)
static void NotebookPlaceContents(void *recordPtr)
{
    Notebook *nb = recordPtr;
    int currentIndex = nb->notebook.currentIndex;
    if (currentIndex >= 0) {
    Notebook *nb = (Notebook *)recordPtr;
    TkSizeT currentIndex = nb->notebook.currentIndex;
    if (currentIndex != TCL_INDEX_NONE) {
	NotebookDoLayout(nb);
	NotebookPlaceSlave(nb, currentIndex);
	NotebookPlaceContent(nb, currentIndex);
    }
}

/*
 * SelectTab(nb, index) --
 * 	Change the currently-selected tab.
 */
static void SelectTab(Notebook *nb, int index)
static void SelectTab(Notebook *nb, TkSizeT index)
{
    Tab *tab = Ttk_SlaveData(nb->notebook.mgr,index);
    int currentIndex = nb->notebook.currentIndex;
    Tab *tab = (Tab *)Ttk_ContentData(nb->notebook.mgr, index);
    TkSizeT currentIndex = nb->notebook.currentIndex;

    if (index == currentIndex) {
	return;
    }

    if (TabState(nb, index) & TTK_STATE_DISABLED) {
	return;
    }

    /* Unhide the tab if it is currently hidden and being selected.
     */
    if (tab->state == TAB_STATE_HIDDEN) {
	tab->state = TAB_STATE_NORMAL;
    }

    if (currentIndex >= 0) {
	Ttk_UnmapSlave(nb->notebook.mgr, currentIndex);
    if (currentIndex != TCL_INDEX_NONE) {
	Ttk_UnmapContent(nb->notebook.mgr, currentIndex);
    }

    /* Must be set before calling NotebookPlaceSlave(), otherwise it may
     * happen that NotebookPlaceSlaves(), triggered by an interveaning
    /* Must be set before calling NotebookPlaceContent(), otherwise it may
     * happen that NotebookPlaceContents(), triggered by an interveaning
     * geometry request, will swap to old index. */
    nb->notebook.currentIndex = index;

    NotebookPlaceSlave(nb, index);
    NotebookPlaceContent(nb, index);
    TtkRedisplayWidget(&nb->core);

    TtkSendVirtualEvent(nb->core.tkwin, "NotebookTabChanged");
    Tk_SendVirtualEvent(nb->core.tkwin, "NotebookTabChanged", NULL);
}

/* NextTab --
 * 	Returns the index of the next tab after the specified tab
 * 	in the normal state (e.g., not hidden or disabled),
 * 	or -1 if all tabs are disabled or hidden.
 */
static int NextTab(Notebook *nb, int index)
{
    int nTabs = Ttk_NumberSlaves(nb->notebook.mgr);
    int nextIndex;
    TkSizeT nTabs = Ttk_NumberContent(nb->notebook.mgr);
    TkSizeT nextIndex;

    /* Scan forward for following usable tab:
     */
    for (nextIndex = index + 1; nextIndex < nTabs; ++nextIndex) {
	Tab *tab = Ttk_SlaveData(nb->notebook.mgr, nextIndex);
    for (nextIndex = index + 1; nextIndex + 1 < nTabs + 1; ++nextIndex) {
	Tab *tab = (Tab *)Ttk_ContentData(nb->notebook.mgr, nextIndex);
	if (tab->state == TAB_STATE_NORMAL) {
	    return nextIndex;
	}
    }

    /* Not found -- scan backwards.
     */
    for (nextIndex = index - 1; nextIndex >= 0; --nextIndex) {
	Tab *tab = Ttk_SlaveData(nb->notebook.mgr, nextIndex);
    for (nextIndex = index - 1; nextIndex != TCL_INDEX_NONE; --nextIndex) {
	Tab *tab = (Tab *)Ttk_ContentData(nb->notebook.mgr, nextIndex);
	if (tab->state == TAB_STATE_NORMAL) {
	    return nextIndex;
	}
    }

    /* Still nothing.  Give up.
     */
    return -1;
}

/* SelectNearestTab --
 * 	Handles the case where the current tab is forgotten, hidden,
 * 	or destroyed.
 *
 * 	Unmap the current tab and schedule the next available one
 * 	to be mapped at the next GM update.
 */
static void SelectNearestTab(Notebook *nb)
{
    int currentIndex = nb->notebook.currentIndex;
    int nextIndex = NextTab(nb, currentIndex);
    TkSizeT currentIndex = nb->notebook.currentIndex;
    TkSizeT nextIndex = NextTab(nb, currentIndex);

    if (currentIndex >= 0) {
	Ttk_UnmapSlave(nb->notebook.mgr, currentIndex);
    if (currentIndex != TCL_INDEX_NONE) {
	Ttk_UnmapContent(nb->notebook.mgr, currentIndex);
    }
    if (currentIndex != nextIndex) {
	TtkSendVirtualEvent(nb->core.tkwin, "NotebookTabChanged");
	Tk_SendVirtualEvent(nb->core.tkwin, "NotebookTabChanged", NULL);
    }

    nb->notebook.currentIndex = nextIndex;
    Ttk_ManagerLayoutChanged(nb->notebook.mgr);
    TtkRedisplayWidget(&nb->core);
}

/* TabRemoved -- GM SlaveRemoved hook.
/* TabRemoved -- GM TabRemoved hook.
 * 	Select the next tab if the current one is being removed.
 * 	Adjust currentIndex to account for removed slave.
 * 	Adjust currentIndex to account for removed content window.
 */
static void TabRemoved(void *managerData, int index)
static void TabRemoved(void *managerData, TkSizeT index)
{
    Notebook *nb = managerData;
    Tab *tab = Ttk_SlaveData(nb->notebook.mgr, index);
    Notebook *nb = (Notebook *)managerData;
    Tab *tab = (Tab *)Ttk_ContentData(nb->notebook.mgr, index);

    if (index == nb->notebook.currentIndex) {
	SelectNearestTab(nb);
    }

    if (index < nb->notebook.currentIndex) {
    if (index + 1 < nb->notebook.currentIndex + 1) {
	--nb->notebook.currentIndex;
    }

    DestroyTab(nb, tab);

    TtkRedisplayWidget(&nb->core);
}

static int TabRequest(void *managerData, int index, int width, int height)
static int TabRequest(
    TCL_UNUSED(void *),
    TCL_UNUSED(TkSizeT),
    TCL_UNUSED(int),
    TCL_UNUSED(int))
{
    return 1;
}

/* AddTab --
 * 	Add new tab at specified index.
 */
static int AddTab(
    Tcl_Interp *interp, Notebook *nb,
    int destIndex, Tk_Window slaveWindow,
    TkSizeT destIndex, Tk_Window window,
    int objc, Tcl_Obj *const objv[])
{
    Tab *tab;
    if (!Ttk_Maintainable(interp, slaveWindow, nb->core.tkwin)) {
    if (!Ttk_Maintainable(interp, window, nb->core.tkwin)) {
	return TCL_ERROR;
    }
#if 0 /* can't happen */
    if (Ttk_SlaveIndex(nb->notebook.mgr, slaveWindow) >= 0) {
    if (Ttk_ContentIndex(nb->notebook.mgr, window) != TCL_INDEX_NONE) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf("%s already added",
	    Tk_PathName(slaveWindow)));
	    Tk_PathName(window)));
	Tcl_SetErrorCode(interp, "TTK", "NOTEBOOK", "PRESENT", NULL);
	return TCL_ERROR;
    }
#endif

    /* Create and insert tab.
     */
    tab = CreateTab(interp, nb, slaveWindow);
    tab = CreateTab(interp, nb, window);
    if (!tab) {
	return TCL_ERROR;
    }
    if (ConfigureTab(interp, nb, tab, slaveWindow, objc, objv) != TCL_OK) {
    if (ConfigureTab(interp, nb, tab, window, objc, objv) != TCL_OK) {
	DestroyTab(nb, tab);
	return TCL_ERROR;
    }

    Ttk_InsertSlave(nb->notebook.mgr, destIndex, slaveWindow, tab);
    Ttk_InsertContent(nb->notebook.mgr, destIndex, window, tab);

    /* Adjust indices and/or autoselect first tab:
     */
    if (nb->notebook.currentIndex < 0) {
    if (nb->notebook.currentIndex == TCL_INDEX_NONE) {
	SelectTab(nb, destIndex);
    } else if (nb->notebook.currentIndex >= destIndex) {
    } else if (nb->notebook.currentIndex + 1 >= destIndex + 1) {
	++nb->notebook.currentIndex;
    }

    return TCL_OK;
}

static Ttk_ManagerSpec NotebookManagerSpec = {
    { "notebook", Ttk_GeometryRequestProc, Ttk_LostSlaveProc },
    { "notebook", Ttk_GeometryRequestProc, Ttk_LostContentProc },
    NotebookSize,
    NotebookPlaceSlaves,
    NotebookPlaceContents,
    TabRequest,
    TabRemoved
};

/*------------------------------------------------------------------------
 * +++ Event handlers.
 */

/* NotebookEventHandler --
 * 	Tracks the active tab.
 */
static const int NotebookEventMask
    = StructureNotifyMask
    | PointerMotionMask
    | LeaveWindowMask
    ;
static void NotebookEventHandler(ClientData clientData, XEvent *eventPtr)
{
    Notebook *nb = clientData;
    Notebook *nb = (Notebook *)clientData;

    if (eventPtr->type == DestroyNotify) { /* Remove self */
	Tk_DeleteEventHandler(nb->core.tkwin,
	    NotebookEventMask, NotebookEventHandler, clientData);
    } else if (eventPtr->type == MotionNotify) {
	int index = IdentifyTab(nb, eventPtr->xmotion.x, eventPtr->xmotion.y);
	TkSizeT index = IdentifyTab(nb, eventPtr->xmotion.x, eventPtr->xmotion.y);
	ActivateTab(nb, index);
    } else if (eventPtr->type == LeaveNotify) {
	ActivateTab(nb, -1);
    }
}

/*------------------------------------------------------------------------
 * +++ Utilities.
 */

/* FindTabIndex --
 *	Find the index of the specified tab.
 *	Tab identifiers are one of:
 *
 *	+ positional specifications @x,y,
 *	+ "current",
 *	+ numeric indices [0..nTabs],
 *	+ slave window names
 *	+ content window names
 *
 *	Stores index of specified tab in *index_rtn, -1 if not found.
 *
 *	Returns TCL_ERROR and leaves an error message in interp->result
 *	if the tab identifier was incorrect.
 *
 *	See also: GetTabIndex.
 */
static int FindTabIndex(
    Tcl_Interp *interp, Notebook *nb, Tcl_Obj *objPtr, int *index_rtn)
    Tcl_Interp *interp, Notebook *nb, Tcl_Obj *objPtr, TkSizeT *index_rtn)
{
    const char *string = Tcl_GetString(objPtr);
    int x, y;

    *index_rtn = -1;
    *index_rtn = TCL_INDEX_NONE;

    /* Check for @x,y ...
     */
    if (string[0] == '@' && sscanf(string, "@%d,%d",&x,&y) == 2) {
	*index_rtn = IdentifyTab(nb, x, y);
	return TCL_OK;
    }

    /* ... or "current" ...
     */
    if (!strcmp(string, "current")) {
	*index_rtn = nb->notebook.currentIndex;
	return TCL_OK;
    }

    /* ... or integer index or slave window name:
    /* ... or integer index or content window name:
     */
    if (Ttk_GetSlaveIndexFromObj(
    if (Ttk_GetContentIndexFromObj(
	    interp, nb->notebook.mgr, objPtr, index_rtn) == TCL_OK)
    {
	return TCL_OK;
    }
    if (*index_rtn == Ttk_NumberContent(nb->notebook.mgr)) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"Invalid tab specification %s", string));
	Tcl_SetErrorCode(interp, "TTK", "NOTEBOOK", "SPEC", NULL);
	return TCL_ERROR;

    /* Nothing matched; Ttk_GetSlaveIndexFromObj will have left error message.
    }

    /* Nothing matched; Ttk_GetContentIndexFromObj will have left error message.
     */
    return TCL_ERROR;
}

/* GetTabIndex --
 * 	Get the index of an existing tab.
 * 	Tab identifiers are as per FindTabIndex.
 * 	Returns TCL_ERROR if the tab does not exist.
 */
static int GetTabIndex(
    Tcl_Interp *interp, Notebook *nb, Tcl_Obj *objPtr, int *index_rtn)
    Tcl_Interp *interp, Notebook *nb, Tcl_Obj *objPtr, TkSizeT *index_rtn)
{
    int status = FindTabIndex(interp, nb, objPtr, index_rtn);
	if (status == TCL_OK && *index_rtn + 1 >= Ttk_NumberContent(nb->notebook.mgr) + 1) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"tab index %s out of bounds", Tcl_GetString(objPtr)));
	    Tcl_SetErrorCode(interp, "TTK", "NOTEBOOK", "INDEX", NULL);
	    return TCL_ERROR;

    if (status == TCL_OK && *index_rtn < 0) {
	}

    if (status == TCL_OK && *index_rtn == TCL_INDEX_NONE) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
	    "tab '%s' not found", Tcl_GetString(objPtr)));
	Tcl_SetErrorCode(interp, "TTK", "NOTEBOOK", "TAB", NULL);
	status = TCL_ERROR;
    }
    return status;
}

/*------------------------------------------------------------------------
 * +++ Widget command routines.
 */

/* $nb add window ?options ... ?
 */
static int NotebookAddCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Notebook *nb = recordPtr;
    Notebook *nb = (Notebook *)recordPtr;
    int index = Ttk_NumberSlaves(nb->notebook.mgr);
    Tk_Window slaveWindow;
    int slaveIndex;
    Tk_Window window;
    int index;
    Tab *tab;

    if (objc <= 2 || objc % 2 != 1) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?-option value ...?");
	return TCL_ERROR;
    }

    slaveWindow = Tk_NameToWindow(interp,Tcl_GetString(objv[2]),nb->core.tkwin);
    if (!slaveWindow) {
    window = Tk_NameToWindow(interp,Tcl_GetString(objv[2]),nb->core.tkwin);
    if (!window) {
	return TCL_ERROR;
    }
    slaveIndex = Ttk_SlaveIndex(nb->notebook.mgr, slaveWindow);
    index = Ttk_ContentIndex(nb->notebook.mgr, window);

    if (slaveIndex < 0) { /* New tab */
	return AddTab(interp, nb, index, slaveWindow, objc-3,objv+3);
    if (index < 0) { /* New tab */
	return AddTab(interp, nb, Ttk_NumberContent(nb->notebook.mgr), window, objc-3,objv+3);
    }

    tab = Ttk_SlaveData(nb->notebook.mgr, slaveIndex);
    tab = (Tab *)Ttk_ContentData(nb->notebook.mgr, index);
    if (tab->state == TAB_STATE_HIDDEN) {
	tab->state = TAB_STATE_NORMAL;
    }
    if (ConfigureTab(interp, nb, tab, slaveWindow, objc-3,objv+3) != TCL_OK) {
    if (ConfigureTab(interp, nb, tab, window, objc-3,objv+3) != TCL_OK) {
	return TCL_ERROR;
    }

    TtkRedisplayWidget(&nb->core);

    return TCL_OK;
}

/* $nb insert $index $tab ?-option value ...?
 * 	Insert new tab, or move existing one.
 */
static int NotebookInsertCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Notebook *nb = recordPtr;
    int current = nb->notebook.currentIndex;
    int nSlaves = Ttk_NumberSlaves(nb->notebook.mgr);
    int srcIndex, destIndex;
    Notebook *nb = (Notebook *)recordPtr;
    TkSizeT current = nb->notebook.currentIndex;
    TkSizeT nContent = Ttk_NumberContent(nb->notebook.mgr);
    TkSizeT srcIndex, destIndex;

    if (objc < 4) {
	Tcl_WrongNumArgs(interp, 2,objv, "index slave ?-option value ...?");
	Tcl_WrongNumArgs(interp, 2,objv, "index window ?-option value ...?");
	return TCL_ERROR;
    }

    if (!strcmp(Tcl_GetString(objv[2]), "end")) {
	destIndex = Ttk_NumberSlaves(nb->notebook.mgr);
    } else if (TCL_OK != Ttk_GetSlaveIndexFromObj(
    if (TCL_OK != Ttk_GetContentIndexFromObj(
		interp, nb->notebook.mgr, objv[2], &destIndex)) {
	return TCL_ERROR;
    }

    if (Tcl_GetString(objv[3])[0] == '.') {
	/* Window name -- could be new or existing slave.
	/* Window name -- could be new or existing content window.
	 */
	Tk_Window slaveWindow =
	Tk_Window window =
	    Tk_NameToWindow(interp,Tcl_GetString(objv[3]),nb->core.tkwin);

	if (!slaveWindow) {
	if (!window) {
	    return TCL_ERROR;
	}

	srcIndex = Ttk_SlaveIndex(nb->notebook.mgr, slaveWindow);
	if (srcIndex < 0) {	/* New slave */
	    return AddTab(interp, nb, destIndex, slaveWindow, objc-4,objv+4);
	srcIndex = Ttk_ContentIndex(nb->notebook.mgr, window);
	if (srcIndex == TCL_INDEX_NONE) {	/* New content window */
	    return AddTab(interp, nb, destIndex, window, objc-4,objv+4);
	}
    } else if (Ttk_GetSlaveIndexFromObj(
    } else if (Ttk_GetContentIndexFromObj(
		interp, nb->notebook.mgr, objv[3], &srcIndex) != TCL_OK)
    {
	return TCL_ERROR;
    } else if (srcIndex + 1 >= Ttk_NumberContent(nb->notebook.mgr) + 1) {
	srcIndex = Ttk_NumberContent(nb->notebook.mgr) - 1;
    }

    /* Move existing slave:
    /* Move existing content window:
     */
    if (ConfigureTab(interp, nb,
	     Ttk_SlaveData(nb->notebook.mgr,srcIndex),
	     Ttk_SlaveWindow(nb->notebook.mgr,srcIndex),
	     (Tab *)Ttk_ContentData(nb->notebook.mgr, srcIndex),
		 Ttk_ContentWindow(nb->notebook.mgr, srcIndex),
	     objc-4,objv+4) != TCL_OK)
    {
	return TCL_ERROR;
    }

    if (destIndex >= nSlaves) {
	destIndex  = nSlaves - 1;
    if (destIndex + 1 >= nContent + 1) {
	destIndex  = nContent - 1;
    }
    Ttk_ReorderSlave(nb->notebook.mgr, srcIndex, destIndex);
    Ttk_ReorderContent(nb->notebook.mgr, srcIndex, destIndex);

    /* Adjust internal indexes:
     */
    nb->notebook.activeIndex = -1;
    nb->notebook.activeIndex = TCL_INDEX_NONE;
    if (current == srcIndex) {
	nb->notebook.currentIndex = destIndex;
    } else if (destIndex <= current && current < srcIndex) {
    } else if (destIndex + 1 <= current + 1 && current + 1 < srcIndex + 1) {
	++nb->notebook.currentIndex;
    } else if (srcIndex < current && current <= destIndex) {
    } else if (srcIndex + 1 < current + 1 && current + 1 <= destIndex + 1) {
	--nb->notebook.currentIndex;
    }

    TtkRedisplayWidget(&nb->core);

    return TCL_OK;
}

/* $nb forget $tab --
 * 	Removes the specified tab.
 */
static int NotebookForgetCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Notebook *nb = recordPtr;
    int index;
    Notebook *nb = (Notebook *)recordPtr;
    TkSizeT index;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "tab");
	return TCL_ERROR;
    }

    if (GetTabIndex(interp, nb, objv[2], &index) != TCL_OK) {
	return TCL_ERROR;
    }

    Ttk_ForgetSlave(nb->notebook.mgr, index);
    Ttk_ForgetContent(nb->notebook.mgr, index);
    TtkRedisplayWidget(&nb->core);

    return TCL_OK;
}

/* $nb hide $tab --
 * 	Hides the specified tab.
 */
static int NotebookHideCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Notebook *nb = recordPtr;
    int index;
    Notebook *nb = (Notebook *)recordPtr;
    TkSizeT index;
    Tab *tab;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "tab");
	return TCL_ERROR;
    }

    if (GetTabIndex(interp, nb, objv[2], &index) != TCL_OK) {
	return TCL_ERROR;
    }

    tab = Ttk_SlaveData(nb->notebook.mgr, index);
    tab = (Tab *)Ttk_ContentData(nb->notebook.mgr, index);
    tab->state = TAB_STATE_HIDDEN;
    if (index == nb->notebook.currentIndex) {
	SelectNearestTab(nb);
    }

    TtkRedisplayWidget(&nb->core);

    return TCL_OK;
}

/* $nb identify $x $y --
 * 	Returns name of tab element at $x,$y; empty string if none.
 */
static int NotebookIdentifyCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    static const char *whatTable[] = { "element", "tab", NULL };
    static const char *const whatTable[] = { "element", "tab", NULL };
    enum { IDENTIFY_ELEMENT, IDENTIFY_TAB };
    int what = IDENTIFY_ELEMENT;
    Notebook *nb = recordPtr;
    Notebook *nb = (Notebook *)recordPtr;
    Ttk_Element element = NULL;
    int x, y, tabIndex;
    int x, y;
    TkSizeT tabIndex;

    if (objc < 4 || objc > 5) {
	Tcl_WrongNumArgs(interp, 2,objv, "?what? x y");
	return TCL_ERROR;
    }

    if (   Tcl_GetIntFromObj(interp, objv[objc-2], &x) != TCL_OK
    if (Tcl_GetIntFromObj(interp, objv[objc-2], &x) != TCL_OK
	|| Tcl_GetIntFromObj(interp, objv[objc-1], &y) != TCL_OK
	|| (objc == 5 && Tcl_GetIndexFromObjStruct(interp, objv[2], whatTable,
		sizeof(char *), "option", 0, &what) != TCL_OK)
    ) {
	return TCL_ERROR;
    }

    tabIndex = IdentifyTab(nb, x, y);
    if (tabIndex >= 0) {
	Tab *tab = Ttk_SlaveData(nb->notebook.mgr, tabIndex);
    if (tabIndex != TCL_INDEX_NONE) {
	Tab *tab = (Tab *)Ttk_ContentData(nb->notebook.mgr, tabIndex);
	Ttk_State state = TabState(nb, tabIndex);
	Ttk_Layout tabLayout = nb->notebook.tabLayout;

	Ttk_RebindSublayout(tabLayout, tab);
	Ttk_PlaceLayout(tabLayout, state, tab->parcel);

	element = Ttk_IdentifyElement(tabLayout, x, y);
    }

    switch (what) {
	case IDENTIFY_ELEMENT:
	    if (element) {
		const char *elementName = Ttk_ElementName(element);

		Tcl_SetObjResult(interp, Tcl_NewStringObj(elementName, -1));
	    }
	    break;
	case IDENTIFY_TAB:
	    if (tabIndex >= 0) {
		Tcl_SetObjResult(interp, Tcl_NewIntObj(tabIndex));
	    if (tabIndex != TCL_INDEX_NONE)
	    Tcl_SetObjResult(interp, TkNewIndexObj(tabIndex));
	    }
	    break;
    }
    return TCL_OK;
}

/* $nb index $item --
 * 	Returns the integer index of the tab specified by $item,
 * 	the empty string if $item does not identify a tab.
 *	See above for valid item formats.
 */
static int NotebookIndexCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Notebook *nb = recordPtr;
    int index, status;
    Notebook *nb = (Notebook *)recordPtr;
    TkSizeT index;
    int status;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "tab");
	return TCL_ERROR;
    }

    /*
     * Special-case for "end":
     */
    if (!strcmp("end", Tcl_GetString(objv[2]))) {
	int nSlaves = Ttk_NumberSlaves(nb->notebook.mgr);
	Tcl_SetObjResult(interp, Tcl_NewIntObj(nSlaves));
	return TCL_OK;
    }

    status = FindTabIndex(interp, nb, objv[2], &index);
    if (status == TCL_OK && index >= 0) {
	Tcl_SetObjResult(interp, Tcl_NewIntObj(index));
	if (status == TCL_OK) {
	if (index != TCL_INDEX_NONE)
	Tcl_SetObjResult(interp, TkNewIndexObj(index));
    }

    return status;
}

/* $nb select ?$item? --
 * 	Select the specified tab, or return the widget path of
 * 	the currently-selected pane.
 */
static int NotebookSelectCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Notebook *nb = recordPtr;
    Notebook *nb = (Notebook *)recordPtr;

    if (objc == 2) {
	if (nb->notebook.currentIndex >= 0) {
	    Tk_Window pane = Ttk_SlaveWindow(
	if (nb->notebook.currentIndex != TCL_INDEX_NONE) {
	    Tk_Window pane = Ttk_ContentWindow(
		nb->notebook.mgr, nb->notebook.currentIndex);
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(Tk_PathName(pane), -1));
	}
	return TCL_OK;
    } else if (objc == 3) {
	TkSizeT index;
	int index, status = GetTabIndex(interp, nb, objv[2], &index);
	int status = GetTabIndex(interp, nb, objv[2], &index);
	if (status == TCL_OK) {
	    SelectTab(nb, index);
	}
	return status;
    } /*else*/
    Tcl_WrongNumArgs(interp, 2, objv, "?tab?");
    return TCL_ERROR;
}

/* $nb tabs --
 * 	Return list of tabs.
 */
static int NotebookTabsCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Notebook *nb = recordPtr;
    Notebook *nb = (Notebook *)recordPtr;
    Ttk_Manager *mgr = nb->notebook.mgr;
    Tcl_Obj *result;
    int i;
    TkSizeT i;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 2, objv, "");
	return TCL_ERROR;
    }

    result = Tcl_NewListObj(0, NULL);
    for (i = 0; i < Ttk_NumberSlaves(mgr); ++i) {
	const char *pathName = Tk_PathName(Ttk_SlaveWindow(mgr,i));
    for (i = 0; i < Ttk_NumberContent(mgr); ++i) {
	const char *pathName = Tk_PathName(Ttk_ContentWindow(mgr,i));

	Tcl_ListObjAppendElement(NULL, result, Tcl_NewStringObj(pathName,-1));
    }
    Tcl_SetObjResult(interp, result);
    return TCL_OK;
}

/* $nb tab $tab ?-option ?value -option value...??
 */
static int NotebookTabCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Notebook *nb = recordPtr;
    Notebook *nb = (Notebook *)recordPtr;
    Ttk_Manager *mgr = nb->notebook.mgr;
    int index;
    Tk_Window slaveWindow;
    TkSizeT index;
    Tk_Window window;
    Tab *tab;

    if (objc < 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "tab ?-option ?value??...");
	return TCL_ERROR;
    }

    if (GetTabIndex(interp, nb, objv[2], &index) != TCL_OK) {
	return TCL_ERROR;
    }

    tab = Ttk_SlaveData(mgr, index);
    slaveWindow = Ttk_SlaveWindow(mgr, index);
    tab = (Tab *)Ttk_ContentData(mgr, index);
    window = Ttk_ContentWindow(mgr, index);

    if (objc == 3) {
	return TtkEnumerateOptions(interp, tab,
	    PaneOptionSpecs, nb->notebook.paneOptionTable, slaveWindow);
	    PaneOptionSpecs, nb->notebook.paneOptionTable, window);
    } else if (objc == 4) {
	return TtkGetOptionValue(interp, tab, objv[3],
	    nb->notebook.paneOptionTable, slaveWindow);
	    nb->notebook.paneOptionTable, window);
    } /* else */

    if (ConfigureTab(interp, nb, tab, slaveWindow, objc-3,objv+3) != TCL_OK) {
    if (ConfigureTab(interp, nb, tab, window, objc-3,objv+3) != TCL_OK) {
	return TCL_ERROR;
    }

    /* If the current tab has become disabled or hidden,
     * select the next nondisabled, unhidden one:
     */
    if (index == nb->notebook.currentIndex && tab->state != TAB_STATE_NORMAL) {
	SelectNearestTab(nb);
    }

    return TCL_OK;
}

/* 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 }
};

/*------------------------------------------------------------------------
 * +++ Widget class hooks.
 */

static void NotebookInitialize(Tcl_Interp *interp, void *recordPtr)
{
    Notebook *nb = recordPtr;
    Notebook *nb = (Notebook *)recordPtr;

    nb->notebook.mgr = Ttk_CreateManager(
	    &NotebookManagerSpec, recordPtr, nb->core.tkwin);

    nb->notebook.tabOptionTable = Tk_CreateOptionTable(interp,TabOptionSpecs);
    nb->notebook.paneOptionTable = Tk_CreateOptionTable(interp,PaneOptionSpecs);

    nb->notebook.currentIndex = -1;
    nb->notebook.activeIndex = -1;
    nb->notebook.currentIndex = TCL_INDEX_NONE;
    nb->notebook.activeIndex = TCL_INDEX_NONE;
    nb->notebook.tabLayout = 0;

    nb->notebook.clientArea = Ttk_MakeBox(0,0,1,1);

    Tk_CreateEventHandler(
	nb->core.tkwin, NotebookEventMask, NotebookEventHandler, recordPtr);
}

static void NotebookCleanup(void *recordPtr)
{
    Notebook *nb = recordPtr;
    Notebook *nb = (Notebook *)recordPtr;

    Ttk_DeleteManager(nb->notebook.mgr);
    if (nb->notebook.tabLayout)
	Ttk_FreeLayout(nb->notebook.tabLayout);
}

static int NotebookConfigure(Tcl_Interp *interp, void *clientData, int mask)
{
    Notebook *nb = clientData;
    Notebook *nb = (Notebook *)clientData;

    /*
     * Error-checks:
     */
    if (nb->notebook.paddingObj) {
	/* Check for valid -padding: */
	Ttk_Padding unused;
1307
1308
1309
1310
1311
1312
1313
1314

1315
1316
1317
1318
1319
1320
1321
1313
1314
1315
1316
1317
1318
1319

1320
1321
1322
1323
1324
1325
1326
1327







-
+








/* NotebookGetLayout  --
 * 	GetLayout widget hook.
 */
static Ttk_Layout NotebookGetLayout(
    Tcl_Interp *interp, Ttk_Theme theme, void *recordPtr)
{
    Notebook *nb = recordPtr;
    Notebook *nb = (Notebook *)recordPtr;
    Ttk_Layout notebookLayout = TtkWidgetGetLayout(interp, theme, recordPtr);
    Ttk_Layout tabLayout;

    if (!notebookLayout) {
	return NULL;
    }

1335
1336
1337
1338
1339
1340
1341
1342

1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356



1357
1358
1359
1360
1361
1362
1363
1364
1365

1366
1367
1368
1369
1370

1371
1372
1373
1374
1375
1376
1377
1378
1379

1380
1381
1382
1383
1384
1385
1386
1341
1342
1343
1344
1345
1346
1347

1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359



1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370

1371
1372
1373
1374
1375

1376
1377
1378
1379
1380
1381
1382
1383
1384

1385
1386
1387
1388
1389
1390
1391
1392







-
+











-
-
-
+
+
+








-
+




-
+








-
+







/*------------------------------------------------------------------------
 * +++ Display routines.
 */

static void DisplayTab(Notebook *nb, int index, Drawable d)
{
    Ttk_Layout tabLayout = nb->notebook.tabLayout;
    Tab *tab = Ttk_SlaveData(nb->notebook.mgr, index);
    Tab *tab = (Tab *)Ttk_ContentData(nb->notebook.mgr, index);
    Ttk_State state = TabState(nb, index);

    if (tab->state != TAB_STATE_HIDDEN) {
	Ttk_RebindSublayout(tabLayout, tab);
	Ttk_PlaceLayout(tabLayout, state, tab->parcel);
	Ttk_DrawLayout(tabLayout, state, d);
    }
}

static void NotebookDisplay(void *clientData, Drawable d)
{
    Notebook *nb = clientData;
    int nSlaves = Ttk_NumberSlaves(nb->notebook.mgr);
    int index;
    Notebook *nb = (Notebook *)clientData;
    TkSizeT nContent = Ttk_NumberContent(nb->notebook.mgr);
    TkSizeT index;

    /* Draw notebook background (base layout):
     */
    Ttk_DrawLayout(nb->core.layout, nb->core.state, d);

    /* Draw tabs from left to right, but draw the current tab last
     * so it will overwrite its neighbors.
     */
    for (index = 0; index < nSlaves; ++index) {
    for (index = 0; index < nContent; ++index) {
	if (index != nb->notebook.currentIndex) {
	    DisplayTab(nb, index, d);
	}
    }
    if (nb->notebook.currentIndex >= 0) {
    if (nb->notebook.currentIndex != TCL_INDEX_NONE) {
	DisplayTab(nb, nb->notebook.currentIndex, d);
    }
}

/*------------------------------------------------------------------------
 * +++ Widget specification and layout definitions.
 */

static WidgetSpec NotebookWidgetSpec =
static const WidgetSpec NotebookWidgetSpec =
{
    "TNotebook",		/* className */
    sizeof(Notebook),		/* recordSize */
    NotebookOptionSpecs,	/* optionSpecs */
    NotebookCommands,		/* subcommands */
    NotebookInitialize,		/* initializeProc */
    NotebookCleanup,		/* cleanupProc */
Changes to generic/ttk/ttkPanedwindow.c.
1
2

3
4
5
6
7
8
9
10

11
12
13
14
15
16
17
1

2
3
4
5
6
7
8


9
10
11
12
13
14
15
16

-
+






-
-
+







/*
 * Copyright (c) 2005, Joe English.  Freely redistributable.
 * Copyright © 2005 Joe English.  Freely redistributable.
 *
 * ttk::panedwindow widget implementation.
 *
 * TODO: track active/pressed sash.
 */

#include <string.h>
#include <tk.h>
#include "tkInt.h"
#include "ttkManager.h"
#include "ttkTheme.h"
#include "ttkWidget.h"

/*------------------------------------------------------------------------
 * +++ Layout algorithm.
 *
25
26
27
28
29
30
31
32

33
34
35
36
37
38
39
24
25
26
27
28
29
30

31
32
33
34
35
36
37
38







-
+







 * When resizing, sash positions are computed from the request sizes,
 * the available space, and pane weights (see PlaceSashes()).
 * This ensures continuous resize behavior (that is: changing
 * the size by X pixels then changing the size by Y pixels
 * gives the same result as changing the size by X+Y pixels
 * in one step).
 *
 * The request size is initially set to the slave window's requested size.
 * The request size is initially set to the content window's requested size.
 * When the user drags a sash, each pane's request size is set to its
 * actual size.  This ensures that panes "stay put" on the next resize.
 *
 * If reqSize == 0, use 0 for the weight as well.  This ensures that
 * "collapsed" panes stay collapsed during a resize, regardless of
 * their nominal -weight.
 *
71
72
73
74
75
76
77
78

79
80
81


82
83
84


85
86
87


88
89
90
91
92
93
94

95
96
97
98
99
100
101
102

103
104
105


106
107
108
109
110
111

112
113
114
115

116
117
118

119
120
121
122
123
124
125

126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144

145
146
147
148
149
150
151
152


153
154
155
156
157
158
159
70
71
72
73
74
75
76

77
78


79
80
81


82
83
84


85
86
87
88
89
90
91
92

93
94
95
96
97
98
99
100

101
102


103
104
105
106
107
108
109

110
111
112
113

114
115
116

117
118
119
120
121
122
123

124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142

143
144
145
146
147
148
149


150
151
152
153
154
155
156
157
158







-
+

-
-
+
+

-
-
+
+

-
-
+
+






-
+







-
+

-
-
+
+





-
+



-
+


-
+






-
+


















-
+






-
-
+
+







typedef struct {
    WidgetCore	core;
    PanedPart	paned;
} Paned;

/* @@@ NOTE: -orient is readonly 'cause dynamic oriention changes NYI
 */
static Tk_OptionSpec PanedOptionSpecs[] = {
static const Tk_OptionSpec PanedOptionSpecs[] = {
    {TK_OPTION_STRING_TABLE, "-orient", "orient", "Orient", "vertical",
	Tk_Offset(Paned,paned.orientObj), Tk_Offset(Paned,paned.orient),
	0,(ClientData)ttkOrientStrings,READONLY_OPTION|STYLE_CHANGED },
	offsetof(Paned,paned.orientObj), offsetof(Paned,paned.orient),
	0, (void *)ttkOrientStrings, READONLY_OPTION|STYLE_CHANGED },
    {TK_OPTION_INT, "-width", "width", "Width", "0",
	-1,Tk_Offset(Paned,paned.width),
	0,0,GEOMETRY_CHANGED },
	TCL_INDEX_NONE, offsetof(Paned, paned.width),
	0, 0, GEOMETRY_CHANGED },
    {TK_OPTION_INT, "-height", "height", "Height", "0",
	-1,Tk_Offset(Paned,paned.height),
	0,0,GEOMETRY_CHANGED },
	TCL_INDEX_NONE, offsetof(Paned, paned.height),
	0, 0, GEOMETRY_CHANGED },

    WIDGET_TAKEFOCUS_FALSE,
    WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs)
};

/*------------------------------------------------------------------------
 * +++ Slave pane record.
 * +++ Pane record.
 */
typedef struct {
    int 	reqSize;		/* Pane request size */
    int 	sashPos;		/* Folowing sash position */
    int 	weight; 		/* Pane -weight, for resizing */
} Pane;

static Tk_OptionSpec PaneOptionSpecs[] = {
static const Tk_OptionSpec PaneOptionSpecs[] = {
    {TK_OPTION_INT, "-weight", "weight", "Weight", "0",
	-1,Tk_Offset(Pane,weight), 0,0,GEOMETRY_CHANGED },
    {TK_OPTION_END, 0,0,0, NULL, -1,-1, 0,0,0}
	TCL_INDEX_NONE, offsetof(Pane,weight), 0,0,GEOMETRY_CHANGED },
    {TK_OPTION_END, 0,0,0, NULL, TCL_INDEX_NONE,TCL_INDEX_NONE, 0,0,0}
};

/* CreatePane --
 * 	Create a new pane record.
 */
static Pane *CreatePane(Tcl_Interp *interp, Paned *pw, Tk_Window slaveWindow)
static Pane *CreatePane(Tcl_Interp *interp, Paned *pw, Tk_Window window)
{
    Tk_OptionTable optionTable = pw->paned.paneOptionTable;
    void *record = ckalloc(sizeof(Pane));
    Pane *pane = record;
    Pane *pane = (Pane *)record;

    memset(record, 0, sizeof(Pane));
    if (Tk_InitOptions(interp, record, optionTable, slaveWindow) != TCL_OK) {
    if (Tk_InitOptions(interp, record, optionTable, window) != TCL_OK) {
	ckfree(record);
	return NULL;
    }

    pane->reqSize
	= pw->paned.orient == TTK_ORIENT_HORIZONTAL
	? Tk_ReqWidth(slaveWindow) : Tk_ReqHeight(slaveWindow);
	? Tk_ReqWidth(window) : Tk_ReqHeight(window);

    return pane;
}

/* DestroyPane --
 * 	Free pane record.
 */
static void DestroyPane(Paned *pw, Pane *pane)
{
    void *record = pane;
    Tk_FreeConfigOptions(record, pw->paned.paneOptionTable, pw->core.tkwin);
    ckfree(record);
}

/* ConfigurePane --
 * 	Set pane options.
 */
static int ConfigurePane(
    Tcl_Interp *interp, Paned *pw, Pane *pane, Tk_Window slaveWindow,
    Tcl_Interp *interp, Paned *pw, Pane *pane, Tk_Window window,
    int objc, Tcl_Obj *const objv[])
{
    Ttk_Manager *mgr = pw->paned.mgr;
    Tk_SavedOptions savedOptions;
    int mask = 0;

    if (Tk_SetOptions(interp, (void*)pane, pw->paned.paneOptionTable,
	    objc, objv, slaveWindow, &savedOptions, &mask) != TCL_OK)
    if (Tk_SetOptions(interp, pane, pw->paned.paneOptionTable,
	    objc, objv, window, &savedOptions, &mask) != TCL_OK)
    {
	return TCL_ERROR;
    }

    /* Sanity-check:
     */
    if (pane->weight < 0) {
185
186
187
188
189
190
191
192

193
194
195
196
197
198
199

200
201
202
203
204
205
206
207
208
209
210

211
212

213
214
215
216


217
218

219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234


235
236
237
238
239
240
241
242
243


244
245
246


247
248
249
250
251
252
253


254
255
256


257
258
259
260
261
262
263
184
185
186
187
188
189
190

191
192
193
194
195
196
197

198
199
200
201
202
203
204
205
206
207
208

209
210

211
212
213


214
215
216

217
218
219
220
221
222
223
224
225
226
227
228
229
230
231


232
233
234
235
236
237
238
239
240


241
242
243


244
245
246
247
248
249
250


251
252
253


254
255
256
257
258
259
260
261
262







-
+






-
+










-
+

-
+


-
-
+
+

-
+














-
-
+
+







-
-
+
+

-
-
+
+





-
-
+
+

-
-
+
+







 * 	of the window.  If that happens, shove back down.
 *
 * 	Returns: final position of sash i.
 */

static int ShoveUp(Paned *pw, int i, int pos)
{
    Pane *pane = Ttk_SlaveData(pw->paned.mgr, i);
    Pane *pane = (Pane *)Ttk_ContentData(pw->paned.mgr, i);
    int sashThickness = pw->paned.sashThickness;

    if (i == 0) {
	if (pos < 0)
	    pos = 0;
    } else {
	Pane *prevPane = Ttk_SlaveData(pw->paned.mgr, i-1);
	Pane *prevPane = (Pane *)Ttk_ContentData(pw->paned.mgr, i-1);
	if (pos < prevPane->sashPos + sashThickness)
	    pos = ShoveUp(pw, i-1, pos - sashThickness) + sashThickness;
    }
    return pane->sashPos = pos;
}

/* ShoveDown --
 * 	Same as ShoveUp, but going in the opposite direction
 * 	and stopping at the sentinel sash.
 */
static int ShoveDown(Paned *pw, int i, int pos)
static int ShoveDown(Paned *pw, TkSizeT i, int pos)
{
    Pane *pane = Ttk_SlaveData(pw->paned.mgr,i);
    Pane *pane = (Pane *)Ttk_ContentData(pw->paned.mgr,i);
    int sashThickness = pw->paned.sashThickness;

    if (i == Ttk_NumberSlaves(pw->paned.mgr) - 1) {
	pos = pane->sashPos; /* Sentinel value == master window size */
    if (i == Ttk_NumberContent(pw->paned.mgr) - 1) {
	pos = pane->sashPos; /* Sentinel value == container window size */
    } else {
	Pane *nextPane = Ttk_SlaveData(pw->paned.mgr,i+1);
	Pane *nextPane = (Pane *)Ttk_ContentData(pw->paned.mgr,i+1);
	if (pos + sashThickness > nextPane->sashPos)
	    pos = ShoveDown(pw, i+1, pos + sashThickness) - sashThickness;
    }
    return pane->sashPos = pos;
}

/* PanedSize --
 * 	Compute the requested size of the paned widget
 * 	from the individual pane request sizes.
 *
 * 	Used as the WidgetSpec sizeProc and the ManagerSpec sizeProc.
 */
static int PanedSize(void *recordPtr, int *widthPtr, int *heightPtr)
{
    Paned *pw = recordPtr;
    int nPanes = Ttk_NumberSlaves(pw->paned.mgr);
    Paned *pw = (Paned *)recordPtr;
    int nPanes = Ttk_NumberContent(pw->paned.mgr);
    int nSashes = nPanes - 1;
    int sashThickness = pw->paned.sashThickness;
    int width = 0, height = 0;
    int index;

    if (pw->paned.orient == TTK_ORIENT_HORIZONTAL) {
	for (index = 0; index < nPanes; ++index) {
	    Pane *pane = Ttk_SlaveData(pw->paned.mgr, index);
	    Tk_Window slaveWindow = Ttk_SlaveWindow(pw->paned.mgr, index);
	    Pane *pane = (Pane *)Ttk_ContentData(pw->paned.mgr, index);
	    Tk_Window window = Ttk_ContentWindow(pw->paned.mgr, index);

	    if (height < Tk_ReqHeight(slaveWindow))
		height = Tk_ReqHeight(slaveWindow);
	    if (height < Tk_ReqHeight(window))
		height = Tk_ReqHeight(window);
	    width += pane->reqSize;
	}
	width += nSashes * sashThickness;
    } else {
	for (index = 0; index < nPanes; ++index) {
	    Pane *pane = Ttk_SlaveData(pw->paned.mgr, index);
	    Tk_Window slaveWindow = Ttk_SlaveWindow(pw->paned.mgr, index);
	    Pane *pane = (Pane *)Ttk_ContentData(pw->paned.mgr, index);
	    Tk_Window window = Ttk_ContentWindow(pw->paned.mgr, index);

	    if (width < Tk_ReqWidth(slaveWindow))
		width = Tk_ReqWidth(slaveWindow);
	    if (width < Tk_ReqWidth(window))
		width = Tk_ReqWidth(window);
	    height += pane->reqSize;
	}
	height += nSashes * sashThickness;
    }

    *widthPtr = pw->paned.width > 0 ? pw->paned.width : width;
    *heightPtr = pw->paned.height > 0 ? pw->paned.height : height;
272
273
274
275
276
277
278
279

280
281
282


283
284
285
286
287
288
289
271
272
273
274
275
276
277

278
279


280
281
282
283
284
285
286
287
288







-
+

-
-
+
+







 * 	will leave the sashes in the same place, as long as available size
 * 	remains contant.
 */
static void AdjustPanes(Paned *pw)
{
    int sashThickness = pw->paned.sashThickness;
    int pos = 0;
    int index;
    TkSizeT index;

    for (index = 0; index < Ttk_NumberSlaves(pw->paned.mgr); ++index) {
	Pane *pane = Ttk_SlaveData(pw->paned.mgr, index);
    for (index = 0; index < Ttk_NumberContent(pw->paned.mgr); ++index) {
	Pane *pane = (Pane *)Ttk_ContentData(pw->paned.mgr, index);
	int size = pane->sashPos - pos;
	pane->reqSize = size >= 0 ? size : 0;
	pos = pane->sashPos + sashThickness;
    }
}

/* PlaceSashes --
301
302
303
304
305
306
307
308

309
310
311
312
313
314
315
316
317
318
319
320

321
322
323
324
325
326
327
300
301
302
303
304
305
306

307
308
309
310
311
312
313
314
315
316
317
318

319
320
321
322
323
324
325
326







-
+











-
+







 * Notes:
 * 	This doesn't distribute the remainder pixels as evenly as it could
 * 	when more than one pane has weight > 1.
 */
static void PlaceSashes(Paned *pw, int width, int height)
{
    Ttk_Manager *mgr = pw->paned.mgr;
    int nPanes = Ttk_NumberSlaves(mgr);
    int nPanes = Ttk_NumberContent(mgr);
    int sashThickness = pw->paned.sashThickness;
    int available = pw->paned.orient == TTK_ORIENT_HORIZONTAL ? width : height;
    int reqSize = 0, totalWeight = 0;
    int difference, delta, remainder, pos, i;

    if (nPanes == 0)
	return;

    /* Compute total required size and total available weight:
     */
    for (i = 0; i < nPanes; ++i) {
	Pane *pane = Ttk_SlaveData(mgr, i);
	Pane *pane = (Pane *)Ttk_ContentData(mgr, i);
	reqSize += pane->reqSize;
	totalWeight += pane->weight * (pane->reqSize != 0);
    }

    /* Compute difference to be redistributed:
     */
    difference = available - reqSize - sashThickness*(nPanes-1);
337
338
339
340
341
342
343
344

345
346
347
348
349
350
351
336
337
338
339
340
341
342

343
344
345
346
347
348
349
350







-
+







    }
    /* ASSERT: 0 <= remainder < totalWeight */

    /* Place sashes:
     */
    pos = 0;
    for (i = 0; i < nPanes; ++i) {
	Pane *pane = Ttk_SlaveData(mgr, i);
	Pane *pane = (Pane *)Ttk_ContentData(mgr, i);
	int weight = pane->weight * (pane->reqSize != 0);
	int size = pane->reqSize + delta * weight;

	if (weight > remainder)
	    weight = remainder;
	remainder -= weight;
	size += weight;
361
362
363
364
365
366
367
368

369
370
371
372
373
374
375
376

377
378
379


380
381
382
383
384

385
386

387
388
389

390
391
392
393
394
395
396
397
398
399
400

401
402

403
404
405
406
407

408
409
410


411
412
413
414
415
416

417
418
419
420

421
422
423

424
425

426
427
428
429
430

431
432
433
434

435
436
437
438
439

440
441
442
443
444
445


446
447
448
449

450
451
452
453



454
455
456

457
458
459
460
461
462
463

464
465

466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486

487
488
489
490

491
492
493
494
495
496
497
498
499
500

501
502
503
504
505
506
507
508
509
510
511
512

513
514
515
516
517
518
519
520
521
522
523




524
525

526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546

547
548
549
550
551
552
553
360
361
362
363
364
365
366

367
368
369
370
371
372
373
374

375
376


377
378
379
380
381
382

383
384

385
386
387

388
389
390
391
392
393
394
395
396
397
398

399
400

401
402
403
404
405

406
407


408
409
410
411
412
413
414

415
416
417
418

419
420
421

422
423

424
425
426
427
428

429
430
431
432

433
434
435
436
437

438
439
440
441
442


443
444
445
446
447

448
449



450
451
452
453
454

455
456
457
458
459
460
461

462
463

464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484

485
486
487
488

489
490
491
492
493
494
495
496
497
498

499
500
501
502
503
504
505
506
507
508
509
510

511
512
513
514
515
516
517
518
519
520
521

522
523
524
525
526

527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547

548
549
550
551
552
553
554
555







-
+







-
+

-
-
+
+




-
+

-
+


-
+










-
+

-
+




-
+

-
-
+
+





-
+



-
+


-
+

-
+




-
+



-
+




-
+




-
-
+
+



-
+

-
-
-
+
+
+


-
+






-
+

-
+




















-
+



-
+









-
+











-
+










-
+
+
+
+

-
+




















-
+







     * Set sentinel sash position to end of widget,
     * shove preceding sashes up.
     */
    ShoveUp(pw, nPanes - 1, available);
}

/* PlacePanes --
 *	Places slave panes based on sash positions.
 *	Places panes based on sash positions.
 */
static void PlacePanes(Paned *pw)
{
    int horizontal = pw->paned.orient == TTK_ORIENT_HORIZONTAL;
    int width = Tk_Width(pw->core.tkwin), height = Tk_Height(pw->core.tkwin);
    int sashThickness = pw->paned.sashThickness;
    int pos = 0;
    int index;
    TkSizeT index;

    for (index = 0; index < Ttk_NumberSlaves(pw->paned.mgr); ++index) {
	Pane *pane = Ttk_SlaveData(pw->paned.mgr, index);
    for (index = 0; index < Ttk_NumberContent(pw->paned.mgr); ++index) {
	Pane *pane = (Pane *)Ttk_ContentData(pw->paned.mgr, index);
	int size = pane->sashPos - pos;

	if (size > 0) {
	    if (horizontal) {
		Ttk_PlaceSlave(pw->paned.mgr, index, pos, 0, size, height);
		Ttk_PlaceContent(pw->paned.mgr, index, pos, 0, size, height);
	    } else {
		Ttk_PlaceSlave(pw->paned.mgr, index, 0, pos, width, size);
		Ttk_PlaceContent(pw->paned.mgr, index, 0, pos, width, size);
	    }
	} else {
	    Ttk_UnmapSlave(pw->paned.mgr, index);
	    Ttk_UnmapContent(pw->paned.mgr, index);
	}

	pos = pane->sashPos + sashThickness;
    }
}

/*------------------------------------------------------------------------
 * +++ Manager specification.
 */

static void PanedPlaceSlaves(void *managerData)
static void PanedPlaceContent(void *managerData)
{
    Paned *pw = managerData;
    Paned *pw = (Paned *)managerData;
    PlaceSashes(pw, Tk_Width(pw->core.tkwin), Tk_Height(pw->core.tkwin));
    PlacePanes(pw);
}

static void PaneRemoved(void *managerData, int index)
static void PaneRemoved(void *managerData, TkSizeT index)
{
    Paned *pw = managerData;
    Pane *pane = Ttk_SlaveData(pw->paned.mgr, index);
    Paned *pw = (Paned *)managerData;
    Pane *pane = (Pane *)Ttk_ContentData(pw->paned.mgr, index);
    DestroyPane(pw, pane);
}

static int AddPane(
    Tcl_Interp *interp, Paned *pw,
    int destIndex, Tk_Window slaveWindow,
    int destIndex, Tk_Window window,
    int objc, Tcl_Obj *const objv[])
{
    Pane *pane;
    if (!Ttk_Maintainable(interp, slaveWindow, pw->core.tkwin)) {
    if (!Ttk_Maintainable(interp, window, pw->core.tkwin)) {
	return TCL_ERROR;
    }
    if (Ttk_SlaveIndex(pw->paned.mgr, slaveWindow) >= 0) {
    if (Ttk_ContentIndex(pw->paned.mgr, window) != TCL_INDEX_NONE) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"%s already added", Tk_PathName(slaveWindow)));
		"%s already added", Tk_PathName(window)));
	Tcl_SetErrorCode(interp, "TTK", "PANE", "PRESENT", NULL);
	return TCL_ERROR;
    }

    pane = CreatePane(interp, pw, slaveWindow);
    pane = CreatePane(interp, pw, window);
    if (!pane) {
	return TCL_ERROR;
    }
    if (ConfigurePane(interp, pw, pane, slaveWindow, objc, objv) != TCL_OK) {
    if (ConfigurePane(interp, pw, pane, window, objc, objv) != TCL_OK) {
	DestroyPane(pw, pane);
	return TCL_ERROR;
    }

    Ttk_InsertSlave(pw->paned.mgr, destIndex, slaveWindow, pane);
    Ttk_InsertContent(pw->paned.mgr, destIndex, window, pane);
    return TCL_OK;
}

/* PaneRequest --
 * 	Only update pane request size if slave is currently unmapped.
 * 	Geometry requests from mapped slaves are not directly honored
 * 	Only update pane request size if pane is currently unmapped.
 * 	Geometry requests from mapped panes are not directly honored
 * 	in order to avoid unexpected pane resizes (esp. while the
 * 	user is dragging a sash [#1325286]).
 */
static int PaneRequest(void *managerData, int index, int width, int height)
static int PaneRequest(void *managerData, TkSizeT index, int width, int height)
{
    Paned *pw = managerData;
    Pane *pane = Ttk_SlaveData(pw->paned.mgr, index);
    Tk_Window slaveWindow = Ttk_SlaveWindow(pw->paned.mgr, index);
    Paned *pw = (Paned *)managerData;
    Pane *pane = (Pane *)Ttk_ContentData(pw->paned.mgr, index);
    Tk_Window window = Ttk_ContentWindow(pw->paned.mgr, index);
    int horizontal = pw->paned.orient == TTK_ORIENT_HORIZONTAL;

    if (!Tk_IsMapped(slaveWindow)) {
    if (!Tk_IsMapped(window)) {
	pane->reqSize = horizontal ? width : height;
    }
    return 1;
}

static Ttk_ManagerSpec PanedManagerSpec = {
    { "panedwindow", Ttk_GeometryRequestProc, Ttk_LostSlaveProc },
    { "panedwindow", Ttk_GeometryRequestProc, Ttk_LostContentProc },
    PanedSize,
    PanedPlaceSlaves,
    PanedPlaceContent,
    PaneRequest,
    PaneRemoved
};

/*------------------------------------------------------------------------
 * +++ Event handler.
 *
 * <<NOTE-PW-LEAVE-NOTIFYINFERIOR>>
 * Tk does not execute binding scripts for <Leave> events when
 * the pointer crosses from a parent to a child.  This widget
 * needs to know when that happens, though, so it can reset
 * the cursor.
 *
 * This event handler generates an <<EnteredChild>> virtual event
 * on LeaveNotify/NotifyInferior.
 */

static const unsigned PanedEventMask = LeaveWindowMask;
static void PanedEventProc(ClientData clientData, XEvent *eventPtr)
{
    WidgetCore *corePtr = clientData;
    WidgetCore *corePtr = (WidgetCore *)clientData;
    if (   eventPtr->type == LeaveNotify
	&& eventPtr->xcrossing.detail == NotifyInferior)
    {
	TtkSendVirtualEvent(corePtr->tkwin, "EnteredChild");
	Tk_SendVirtualEvent(corePtr->tkwin, "EnteredChild", NULL);
    }
}

/*------------------------------------------------------------------------
 * +++ Initialization and cleanup hooks.
 */

static void PanedInitialize(Tcl_Interp *interp, void *recordPtr)
{
    Paned *pw = recordPtr;
    Paned *pw = (Paned *)recordPtr;

    Tk_CreateEventHandler(pw->core.tkwin,
	PanedEventMask, PanedEventProc, recordPtr);
    pw->paned.mgr = Ttk_CreateManager(&PanedManagerSpec, pw, pw->core.tkwin);
    pw->paned.paneOptionTable = Tk_CreateOptionTable(interp,PaneOptionSpecs);
    pw->paned.sashLayout = 0;
    pw->paned.sashThickness = 1;
}

static void PanedCleanup(void *recordPtr)
{
    Paned *pw = recordPtr;
    Paned *pw = (Paned *)recordPtr;

    if (pw->paned.sashLayout)
	Ttk_FreeLayout(pw->paned.sashLayout);
    Tk_DeleteEventHandler(pw->core.tkwin,
	PanedEventMask, PanedEventProc, recordPtr);
    Ttk_DeleteManager(pw->paned.mgr);
}

/* Post-configuration hook.
 */
static int PanedPostConfigure(Tcl_Interp *interp, void *clientData, int mask)
static int PanedPostConfigure(
    TCL_UNUSED(Tcl_Interp *),
    void *clientData,
    int mask)
{
    Paned *pw = clientData;
    Paned *pw = (Paned *)clientData;

    if (mask & GEOMETRY_CHANGED) {
	/* User has changed -width or -height.
	 * Recalculate sash positions based on requested size.
	 */
	Tk_Window tkwin = pw->core.tkwin;
	PlaceSashes(pw,
	    pw->paned.width > 0 ? pw->paned.width : Tk_Width(tkwin),
	    pw->paned.height > 0 ? pw->paned.height : Tk_Height(tkwin));
    }

    return TCL_OK;
}

/*------------------------------------------------------------------------
 * +++ Layout management hooks.
 */
static Ttk_Layout PanedGetLayout(
    Tcl_Interp *interp, Ttk_Theme themePtr, void *recordPtr)
{
    Paned *pw = recordPtr;
    Paned *pw = (Paned *)recordPtr;
    Ttk_Layout panedLayout = TtkWidgetGetLayout(interp, themePtr, recordPtr);

    if (panedLayout) {
	int horizontal = pw->paned.orient == TTK_ORIENT_HORIZONTAL;
	const char *layoutName =
	    horizontal ? ".Vertical.Sash" : ".Horizontal.Sash";
	Ttk_Layout sashLayout = Ttk_CreateSublayout(
577
578
579
580
581
582
583
584

585
586
587
588
589
590
591
579
580
581
582
583
584
585

586
587
588
589
590
591
592
593







-
+








/* SashLayout --
 * 	Place the sash sublayout after the specified pane,
 * 	in preparation for drawing.
 */
static Ttk_Layout SashLayout(Paned *pw, int index)
{
    Pane *pane = Ttk_SlaveData(pw->paned.mgr, index);
    Pane *pane = (Pane *)Ttk_ContentData(pw->paned.mgr, index);
    int thickness = pw->paned.sashThickness,
	height = Tk_Height(pw->core.tkwin),
	width = Tk_Width(pw->core.tkwin),
	sashPos = pane->sashPos;

    Ttk_PlaceLayout(
	pw->paned.sashLayout, pw->core.state,
599
600
601
602
603
604
605
606
607


608
609
610
611


612
613
614
615
616
617
618
619
620
621
622
623
624
625


626
627
628
629
630
631
632

633
634
635

636
637
638
639

640
641
642
643
644


645
646
647
648
649
650
651
652




653
654
655

656
657
658
659

660
661

662
663
664
665
666
667
668


669
670
671
672
673
674
675
676




677
678
679
680



681
682
683
684
685
686



687
688
689
690
691
692
693
694
695


696
697
698
699
700
701
702

703
704
705


706
707

708
709
710
711
712
713
714
715
716
717
718

719
720
721

722
723

724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742

743
744
745
746
747

748
749
750
751
752
753
754
601
602
603
604
605
606
607


608
609
610
611


612
613
614
615
616
617
618
619
620
621
622
623
624
625


626
627
628
629
630
631
632
633

634
635
636

637
638
639
640

641
642
643
644


645
646
647
648
649
650




651
652
653
654
655
656

657
658
659
660

661
662

663
664
665
666




667
668
669
670
671
672




673
674
675
676
677



678
679
680
681
682
683



684
685
686
687
688
689
690
691
692
693


694
695
696
697
698
699
700
701

702
703
704
705
706
707
708

709
710
711
712
713
714
715
716
717
718
719

720
721
722

723
724

725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743

744
745
746
747
748

749
750
751
752
753
754
755
756







-
-
+
+


-
-
+
+












-
-
+
+






-
+


-
+



-
+



-
-
+
+




-
-
-
-
+
+
+
+


-
+



-
+

-
+



-
-
-
-
+
+




-
-
-
-
+
+
+
+

-
-
-
+
+
+



-
-
-
+
+
+







-
-
+
+






-
+



+
+

-
+










-
+


-
+

-
+


















-
+




-
+







static void DrawSash(Paned *pw, int index, Drawable d)
{
    Ttk_DrawLayout(SashLayout(pw, index), pw->core.state, d);
}

static void PanedDisplay(void *recordPtr, Drawable d)
{
    Paned *pw = recordPtr;
    int i, nSashes = Ttk_NumberSlaves(pw->paned.mgr) - 1;
    Paned *pw = (Paned *)recordPtr;
    TkSizeT i, nContent = Ttk_NumberContent(pw->paned.mgr);

    TtkWidgetDisplay(recordPtr, d);
    for (i = 0; i < nSashes; ++i) {
	DrawSash(pw, i, d);
    for (i = 1; i < nContent; ++i) {
	DrawSash(pw, i - 1, d);
    }
}

/*------------------------------------------------------------------------
 * +++ Widget commands.
 */

/* $pw add window [ options ... ]
 */
static int PanedAddCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Paned *pw = recordPtr;
    Tk_Window slaveWindow;
    Paned *pw = (Paned *)recordPtr;
    Tk_Window window;

    if (objc < 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "window");
	return TCL_ERROR;
    }

    slaveWindow = Tk_NameToWindow(
    window = Tk_NameToWindow(
	interp, Tcl_GetString(objv[2]), pw->core.tkwin);

    if (!slaveWindow) {
    if (!window) {
	return TCL_ERROR;
    }

    return AddPane(interp, pw, Ttk_NumberSlaves(pw->paned.mgr), slaveWindow,
    return AddPane(interp, pw, Ttk_NumberContent(pw->paned.mgr), window,
	    objc - 3, objv + 3);
}

/* $pw insert $index $slave ?-option value ...?
 * 	Insert new slave, or move existing one.
/* $pw insert $index $window ?-option value ...?
 * 	Insert new content window, or move existing one.
 */
static int PanedInsertCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Paned *pw = recordPtr;
    int nSlaves = Ttk_NumberSlaves(pw->paned.mgr);
    int srcIndex, destIndex;
    Tk_Window slaveWindow;
    Paned *pw = (Paned *)recordPtr;
    TkSizeT nContent = Ttk_NumberContent(pw->paned.mgr);
    TkSizeT srcIndex, destIndex;
    Tk_Window window;

    if (objc < 4) {
	Tcl_WrongNumArgs(interp, 2,objv, "index slave ?-option value ...?");
	Tcl_WrongNumArgs(interp, 2,objv, "index window ?-option value ...?");
	return TCL_ERROR;
    }

    slaveWindow = Tk_NameToWindow(
    window = Tk_NameToWindow(
	interp, Tcl_GetString(objv[3]), pw->core.tkwin);
    if (!slaveWindow) {
    if (!window) {
	return TCL_ERROR;
    }

    if (!strcmp(Tcl_GetString(objv[2]), "end")) {
	destIndex = Ttk_NumberSlaves(pw->paned.mgr);
    } else if (TCL_OK != Ttk_GetSlaveIndexFromObj(
		interp,pw->paned.mgr,objv[2],&destIndex))
    if (TCL_OK != Ttk_GetContentIndexFromObj(
		interp,pw->paned.mgr, objv[2], &destIndex))
    {
	return TCL_ERROR;
    }

    srcIndex = Ttk_SlaveIndex(pw->paned.mgr, slaveWindow);
    if (srcIndex < 0) { /* New slave: */
	return AddPane(interp, pw, destIndex, slaveWindow, objc-4, objv+4);
    } /* else -- move existing slave: */
    srcIndex = Ttk_ContentIndex(pw->paned.mgr, window);
    if (srcIndex == TCL_INDEX_NONE) { /* New content: */
	return AddPane(interp, pw, destIndex, window, objc-4, objv+4);
    } /* else -- move existing content: */

    if (destIndex >= nSlaves)
	destIndex  = nSlaves - 1;
    Ttk_ReorderSlave(pw->paned.mgr, srcIndex, destIndex);
    if (destIndex + 1 >= nContent + 1)
	destIndex  = nContent - 1;
    Ttk_ReorderContent(pw->paned.mgr, srcIndex, destIndex);

    return objc == 4 ? TCL_OK :
	ConfigurePane(interp, pw,
		Ttk_SlaveData(pw->paned.mgr, destIndex),
		Ttk_SlaveWindow(pw->paned.mgr, destIndex),
		objc-4,objv+4);
		(Pane *)Ttk_ContentData(pw->paned.mgr, destIndex),
		Ttk_ContentWindow(pw->paned.mgr, destIndex),
		objc-4, objv+4);
}

/* $pw forget $pane
 */
static int PanedForgetCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Paned *pw = recordPtr;
    int paneIndex;
    Paned *pw = (Paned *)recordPtr;
    TkSizeT paneIndex;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 2,objv, "pane");
	return TCL_ERROR;
    }

    if (TCL_OK != Ttk_GetSlaveIndexFromObj(
    if (TCL_OK != Ttk_GetContentIndexFromObj(
		    interp, pw->paned.mgr, objv[2], &paneIndex))
    {
	return TCL_ERROR;
    } else if (paneIndex + 1 >= Ttk_NumberContent(pw->paned.mgr) + 1) {
	paneIndex = Ttk_NumberContent(pw->paned.mgr) - 1;
    }
    Ttk_ForgetSlave(pw->paned.mgr, paneIndex);
    Ttk_ForgetContent(pw->paned.mgr, paneIndex);

    return TCL_OK;
}

/* $pw identify ?what? $x $y --
 * 	Return index of sash at $x,$y
 */
static int PanedIdentifyCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    static const char *whatTable[] = { "element", "sash", NULL };
    static const char *const whatTable[] = { "element", "sash", NULL };
    enum { IDENTIFY_ELEMENT, IDENTIFY_SASH };
    int what = IDENTIFY_SASH;
    Paned *pw = recordPtr;
    Paned *pw = (Paned *)recordPtr;
    int sashThickness = pw->paned.sashThickness;
    int nSashes = Ttk_NumberSlaves(pw->paned.mgr) - 1;
    int nSashes = Ttk_NumberContent(pw->paned.mgr) - 1;
    int x, y, pos;
    int index;

    if (objc < 4 || objc > 5) {
	Tcl_WrongNumArgs(interp, 2,objv, "?what? x y");
	return TCL_ERROR;
    }

    if (   Tcl_GetIntFromObj(interp, objv[objc-2], &x) != TCL_OK
	|| Tcl_GetIntFromObj(interp, objv[objc-1], &y) != TCL_OK
	|| (objc == 5 && Tcl_GetIndexFromObjStruct(interp, objv[2], whatTable,
	    sizeof(char *), "option", 0, &what) != TCL_OK)
    ) {
	return TCL_ERROR;
    }

    pos = pw->paned.orient == TTK_ORIENT_HORIZONTAL ? x : y;
    for (index = 0; index < nSashes; ++index) {
	Pane *pane = Ttk_SlaveData(pw->paned.mgr, index);
	Pane *pane = (Pane *)Ttk_ContentData(pw->paned.mgr, index);
	if (pane->sashPos <= pos && pos <= pane->sashPos + sashThickness) {
	    /* Found it. */
	    switch (what) {
		case IDENTIFY_SASH:
		    Tcl_SetObjResult(interp, Tcl_NewIntObj(index));
		    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(index));
		    return TCL_OK;
		case IDENTIFY_ELEMENT:
		{
		    Ttk_Element element =
			Ttk_IdentifyElement(SashLayout(pw, index), x, y);
		    if (element) {
			Tcl_SetObjResult(interp,
765
766
767
768
769
770
771
772
773
774



775
776
777
778
779
780
781
782
783


784
785


786
787
788
789


790
791
792
793
794

795
796
797

798
799

800
801
802
803
804
805
806
807
808
809

810
811
812

813
814
815
816
817
818
819
820
821


822
823
824
825
826
827
828
829
830
831
832
833
834
835
836

837
838
839
840
841
842
843
844
845
846
847

848
849
850
851
852
853
854

855
856
857

858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875

876
877
878
879
880
881
882

883
884
885
886
887
888
889
890

891
892
893
894
895
896
897
898

899
900
901
902
903
904
905
767
768
769
770
771
772
773



774
775
776
777
778
779
780
781
782
783


784
785
786
787
788
789
790
791


792
793
794
795
796
797

798
799
800

801
802

803
804
805
806
807
808
809
810
811
812

813
814
815

816
817
818
819
820
821
822
823


824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839

840
841
842
843
844
845
846
847
848
849
850

851
852
853
854
855
856
857

858
859
860

861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878

879
880
881
882
883
884

885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902

903
904
905
906
907
908
909
910







-
-
-
+
+
+







-
-
+
+


+
+


-
-
+
+




-
+


-
+

-
+









-
+


-
+







-
-
+
+














-
+










-
+






-
+


-
+

















-
+





-

+








+







-
+








/* $pw pane $pane ?-option ?value -option value ...??
 * 	Query/modify pane options.
 */
static int PanedPaneCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Paned *pw = recordPtr;
    int paneIndex;
    Tk_Window slaveWindow;
    Paned *pw = (Paned *)recordPtr;
    TkSizeT paneIndex;
    Tk_Window window;
    Pane *pane;

    if (objc < 3) {
	Tcl_WrongNumArgs(interp, 2,objv, "pane ?-option value ...?");
	return TCL_ERROR;
    }

    if (TCL_OK != Ttk_GetSlaveIndexFromObj(
		    interp,pw->paned.mgr,objv[2],&paneIndex))
    if (TCL_OK != Ttk_GetContentIndexFromObj(
		    interp,pw->paned.mgr, objv[2], &paneIndex))
    {
	return TCL_ERROR;
    } else if (paneIndex + 1 >= Ttk_NumberContent(pw->paned.mgr) + 1) {
	paneIndex = Ttk_NumberContent(pw->paned.mgr) - 1;
    }

    pane = Ttk_SlaveData(pw->paned.mgr, paneIndex);
    slaveWindow = Ttk_SlaveWindow(pw->paned.mgr, paneIndex);
    pane = (Pane *)Ttk_ContentData(pw->paned.mgr, paneIndex);
    window = Ttk_ContentWindow(pw->paned.mgr, paneIndex);

    switch (objc) {
	case 3:
	    return TtkEnumerateOptions(interp, pane, PaneOptionSpecs,
			pw->paned.paneOptionTable, slaveWindow);
			pw->paned.paneOptionTable, window);
	case 4:
	    return TtkGetOptionValue(interp, pane, objv[3],
			pw->paned.paneOptionTable, slaveWindow);
			pw->paned.paneOptionTable, window);
	default:
	    return ConfigurePane(interp, pw, pane, slaveWindow, objc-3,objv+3);
	    return ConfigurePane(interp, pw, pane, window, objc-3,objv+3);
    }
}

/* $pw panes --
 * 	Return list of managed panes.
 */
static int PanedPanesCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Paned *pw = recordPtr;
    Paned *pw = (Paned *)recordPtr;
    Ttk_Manager *mgr = pw->paned.mgr;
    Tcl_Obj *panes;
    int i;
    TkSizeT i;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 2, objv, "");
	return TCL_ERROR;
    }

    panes = Tcl_NewListObj(0, NULL);
    for (i = 0; i < Ttk_NumberSlaves(mgr); ++i) {
	const char *pathName = Tk_PathName(Ttk_SlaveWindow(mgr,i));
    for (i = 0; i < Ttk_NumberContent(mgr); ++i) {
	const char *pathName = Tk_PathName(Ttk_ContentWindow(mgr,i));
	Tcl_ListObjAppendElement(interp, panes, Tcl_NewStringObj(pathName,-1));
    }
    Tcl_SetObjResult(interp, panes);

    return TCL_OK;
}


/* $pw sashpos $index ?$newpos?
 * 	Query or modify sash position.
 */
static int PanedSashposCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Paned *pw = recordPtr;
    Paned *pw = (Paned *)recordPtr;
    int sashIndex, position = -1;
    Pane *pane;

    if (objc < 3 || objc > 4) {
	Tcl_WrongNumArgs(interp, 2,objv, "index ?newpos?");
	return TCL_ERROR;
    }
    if (Tcl_GetIntFromObj(interp, objv[2], &sashIndex) != TCL_OK) {
	return TCL_ERROR;
    }
    if (sashIndex < 0 || sashIndex >= Ttk_NumberSlaves(pw->paned.mgr) - 1) {
    if (sashIndex < 0 || (TkSizeT)sashIndex + 1 >= Ttk_NumberContent(pw->paned.mgr)) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
	    "sash index %d out of range", sashIndex));
	Tcl_SetErrorCode(interp, "TTK", "PANE", "SASH_INDEX", NULL);
	return TCL_ERROR;
    }

    pane = Ttk_SlaveData(pw->paned.mgr, sashIndex);
    pane = (Pane *)Ttk_ContentData(pw->paned.mgr, sashIndex);

    if (objc == 3) {
	Tcl_SetObjResult(interp, Tcl_NewIntObj(pane->sashPos));
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(pane->sashPos));
	return TCL_OK;
    }
    /* else -- set new sash position */

    if (Tcl_GetIntFromObj(interp, objv[3], &position) != TCL_OK) {
	return TCL_ERROR;
    }

    if (position < pane->sashPos) {
	ShoveUp(pw, sashIndex, position);
    } else {
	ShoveDown(pw, sashIndex, position);
    }

    AdjustPanes(pw);
    Ttk_ManagerLayoutChanged(pw->paned.mgr);

    Tcl_SetObjResult(interp, Tcl_NewIntObj(pane->sashPos));
    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(pane->sashPos));
    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.
 */

static WidgetSpec PanedWidgetSpec =
static const WidgetSpec PanedWidgetSpec =
{
    "TPanedwindow",		/* className */
    sizeof(Paned),		/* recordSize */
    PanedOptionSpecs,		/* optionSpecs */
    PanedCommands,		/* subcommands */
    PanedInitialize,		/* initializeProc */
    PanedCleanup,		/* cleanupProc */
917
918
919
920
921
922
923
924

925
926
927


928
929
930

931
932





933
934

935

936
937
938
939
940

941
942
943
944
945
946
947
922
923
924
925
926
927
928

929
930


931
932
933
934
935
936


937
938
939
940
941
942

943
944
945
946
947
948
949

950
951
952
953
954
955
956
957







-
+

-
-
+
+



+
-
-
+
+
+
+
+

-
+

+




-
+








static const int DEFAULT_SASH_THICKNESS = 5;

typedef struct {
    Tcl_Obj *thicknessObj;
} SashElement;

static Ttk_ElementOptionSpec SashElementOptions[] = {
static const Ttk_ElementOptionSpec SashElementOptions[] = {
    { "-sashthickness", TK_OPTION_INT,
	    Tk_Offset(SashElement,thicknessObj), "5" },
    { NULL, 0, 0, NULL }
	    offsetof(SashElement,thicknessObj), "5" },
    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
};

static void SashElementSize(
    TCL_UNUSED(void *),
    void *clientData, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
    void *elementRecord,
    TCL_UNUSED(Tk_Window),
    int *widthPtr,
    int *heightPtr,
    TCL_UNUSED(Ttk_Padding *))
{
    SashElement *sash = elementRecord;
    SashElement *sash = (SashElement *)elementRecord;
    int thickness = DEFAULT_SASH_THICKNESS;

    Tcl_GetIntFromObj(NULL, sash->thicknessObj, &thickness);
    *widthPtr = *heightPtr = thickness;
}

static Ttk_ElementSpec SashElementSpec = {
static const Ttk_ElementSpec SashElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(SashElement),
    SashElementOptions,
    SashElementSize,
    TtkNullElementDraw
};

Changes to generic/ttk/ttkProgress.c.
1
2

3
4
5
6
7
8

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

26



27

28

29
30


31
32


33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

48








49
50
51




52
53

54



55
56
57
58
59
60








61
62
63


64

65
66

67
68
69
70






71
72
73
74
75
76
77
1

2
3
4
5
6


7

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

25
26
27
28
29
30
31


32
33
34

35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

51
52
53
54
55
56
57
58
59
60



61
62
63
64
65

66
67
68
69
70
71





72
73
74
75
76
77
78
79
80


81
82

83
84

85
86



87
88
89
90
91
92
93
94
95
96
97
98
99

-
+




-
-
+
-
















+
-
+
+
+

+

+
-
-
+
+

-
+
+














-
+

+
+
+
+
+
+
+
+
-
-
-
+
+
+
+

-
+

+
+
+

-
-
-
-
-
+
+
+
+
+
+
+
+

-
-
+
+
-
+

-
+

-
-
-
+
+
+
+
+
+







/*
 * Copyright (c) Joe English, Pat Thoyts, Michael Kirkham
 * Copyright © Joe English, Pat Thoyts, Michael Kirkham
 *
 * ttk::progressbar widget.
 */

#include <math.h>
#include <tk.h>
#include "tkInt.h"

#include "ttkTheme.h"
#include "ttkWidget.h"

/*------------------------------------------------------------------------
 * +++ Widget record:
 */

#define DEF_PROGRESSBAR_LENGTH "100"
enum {
    TTK_PROGRESSBAR_DETERMINATE, TTK_PROGRESSBAR_INDETERMINATE
};
static const char *const ProgressbarModeStrings[] = {
    "determinate", "indeterminate", NULL
};

typedef struct {
    Tcl_Obj 	*anchorObj;
    Tcl_Obj 	*orientObj;
    Tcl_Obj 	*fontObj;
    Tcl_Obj 	*foregroundObj;
    Tcl_Obj 	*justifyObj;
    Tcl_Obj 	*lengthObj;
    Tcl_Obj 	*maximumObj;
    Tcl_Obj 	*modeObj;
    Tcl_Obj 	*orientObj;
    Tcl_Obj 	*variableObj;
    Tcl_Obj 	*maximumObj;
    Tcl_Obj 	*phaseObj;
    Tcl_Obj 	*textObj;
    Tcl_Obj 	*valueObj;
    Tcl_Obj 	*phaseObj;
    Tcl_Obj 	*variableObj;
    Tcl_Obj 	*wrapLengthObj;

    int 	mode;
    Ttk_TraceHandle *variableTrace;	/* Trace handle for -variable option */
    int 	period;			/* Animation period */
    int 	maxPhase;		/* Max animation phase */
    Tcl_TimerToken timer;		/* Animation timer */

} ProgressbarPart;

typedef struct {
    WidgetCore 		core;
    ProgressbarPart	progress;
} Progressbar;

static Tk_OptionSpec ProgressbarOptionSpecs[] =
static const Tk_OptionSpec ProgressbarOptionSpecs[] =
{
    {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",
	"w", offsetof(Progressbar,progress.anchorObj), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK, 0, GEOMETRY_CHANGED},
    {TK_OPTION_FONT, "-font", "font", "Font",
	DEFAULT_FONT, offsetof(Progressbar,progress.fontObj), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },
    {TK_OPTION_COLOR, "-foreground", "textColor", "TextColor",
	"black", offsetof(Progressbar,progress.foregroundObj), TCL_INDEX_NONE,
    {TK_OPTION_STRING_TABLE, "-orient", "orient", "Orient",
	"horizontal", Tk_Offset(Progressbar,progress.orientObj), -1,
	0, (ClientData)ttkOrientStrings, STYLE_CHANGED },
	TK_OPTION_NULL_OK,0,0 },
    {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",
	"left", offsetof(Progressbar,progress.justifyObj), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },
    {TK_OPTION_PIXELS, "-length", "length", "Length",
        DEF_PROGRESSBAR_LENGTH, Tk_Offset(Progressbar,progress.lengthObj), -1,
        DEF_PROGRESSBAR_LENGTH, offsetof(Progressbar,progress.lengthObj), TCL_INDEX_NONE,
	0, 0, GEOMETRY_CHANGED },
    {TK_OPTION_DOUBLE, "-maximum", "maximum", "Maximum",
	"100", offsetof(Progressbar,progress.maximumObj), TCL_INDEX_NONE,
	0, 0, 0 },
    {TK_OPTION_STRING_TABLE, "-mode", "mode", "ProgressMode", "determinate",
	Tk_Offset(Progressbar,progress.modeObj),
	Tk_Offset(Progressbar,progress.mode),
	0, (ClientData)ProgressbarModeStrings, 0 },
    {TK_OPTION_DOUBLE, "-maximum", "maximum", "Maximum",
	"100", Tk_Offset(Progressbar,progress.maximumObj), -1,
	offsetof(Progressbar,progress.modeObj),
	offsetof(Progressbar,progress.mode),
	0, (void *)ProgressbarModeStrings, 0 },
    {TK_OPTION_STRING_TABLE, "-orient", "orient", "Orient",
	"horizontal", offsetof(Progressbar,progress.orientObj), TCL_INDEX_NONE,
	0, (void *)ttkOrientStrings, STYLE_CHANGED },
    {TK_OPTION_INT, "-phase", "phase", "Phase",
	"0", offsetof(Progressbar,progress.phaseObj), TCL_INDEX_NONE,
	0, 0, 0 },
    {TK_OPTION_STRING, "-variable", "variable", "Variable",
	NULL, Tk_Offset(Progressbar,progress.variableObj), -1,
    {TK_OPTION_STRING, "-text", "text", "Text", "",
	offsetof(Progressbar,progress.textObj), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK, 0, 0 },
	0,0,GEOMETRY_CHANGED },
    {TK_OPTION_DOUBLE, "-value", "value", "Value",
	"0.0", Tk_Offset(Progressbar,progress.valueObj), -1,
	"0.0", offsetof(Progressbar,progress.valueObj), TCL_INDEX_NONE,
	0, 0, 0 },
    {TK_OPTION_INT, "-phase", "phase", "Phase",
	"0", Tk_Offset(Progressbar,progress.phaseObj), -1,
	0, 0, 0 },
    {TK_OPTION_STRING, "-variable", "variable", "Variable",
	NULL, offsetof(Progressbar,progress.variableObj), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK, 0, 0 },
    {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength",
	"0", offsetof(Progressbar, progress.wrapLengthObj), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED},

    WIDGET_TAKEFOCUS_FALSE,
    WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs)
};

/*------------------------------------------------------------------------
 * +++ Animation procedures:
96
97
98
99
100
101
102
103

104
105
106
107
108
109
110
111
112
113

114
115
116



117
118

119
120
121
122
123

124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140

141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156

157
158
159
160
161
162
163
118
119
120
121
122
123
124

125
126
127

128
129
130
131
132
133
134
135
136


137
138
139
140

141
142
143
144
145
146
147
148
149

150
151
152
153
154
155
156
157
158
159
160
161
162

163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178

179
180
181
182
183
184
185
186







-
+


-







+

-
-
+
+
+

-
+





+


-













-
+















-
+







/* AnimateProgressProc --
 * 	Timer callback for progress bar animation.
 * 	Increments the -phase option, redisplays the widget,
 * 	and reschedules itself if animation still enabled.
 */
static void AnimateProgressProc(ClientData clientData)
{
    Progressbar *pb = 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_NewIntObj(phase);
	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 --
 * 	If animation is enabled and not scheduled, schedule it.
 * 	If animation is disabled but scheduled, cancel it.
 */
static void CheckAnimation(Progressbar *pb)
{
    if (AnimationEnabled(pb)) {
	if (pb->progress.timer == 0) {
	    pb->progress.timer = Tcl_CreateTimerHandler(
		pb->progress.period, AnimateProgressProc, (ClientData)pb);
		pb->progress.period, AnimateProgressProc, pb);
	}
    } else {
	if (pb->progress.timer != 0) {
	    Tcl_DeleteTimerHandler(pb->progress.timer);
	    pb->progress.timer = 0;
	}
    }
}

/*------------------------------------------------------------------------
 * +++ Trace hook for progressbar -variable option:
 */

static void VariableChanged(void *recordPtr, const char *value)
{
    Progressbar *pb = recordPtr;
    Progressbar *pb = (Progressbar *)recordPtr;
    Tcl_Obj *newValue;
    double scratch;

    if (WidgetDestroyed(&pb->core)) {
	return;
    }

182
183
184
185
186
187
188
189



190
191


192
193
194
195
196
197
198

199
200
201
202
203
204
205
206
207
208
209
210
211
212

213
214
215
216
217
218
219
205
206
207
208
209
210
211

212
213
214
215

216
217
218
219
220
221
222
223

224
225
226
227
228
229
230
231
232
233
234
235
236
237

238
239
240
241
242
243
244
245







-
+
+
+

-
+
+






-
+













-
+







    TtkRedisplayWidget(&pb->core);
}

/*------------------------------------------------------------------------
 * +++ Widget class methods:
 */

static void ProgressbarInitialize(Tcl_Interp *interp, void *recordPtr)
static void ProgressbarInitialize(
    TCL_UNUSED(Tcl_Interp *),
    void *recordPtr)
{
    Progressbar *pb = recordPtr;
    Progressbar *pb = (Progressbar *)recordPtr;

    pb->progress.variableTrace = 0;
    pb->progress.timer = 0;
}

static void ProgressbarCleanup(void *recordPtr)
{
    Progressbar *pb = recordPtr;
    Progressbar *pb = (Progressbar *)recordPtr;
    if (pb->progress.variableTrace)
	Ttk_UntraceVariable(pb->progress.variableTrace);
    if (pb->progress.timer)
	Tcl_DeleteTimerHandler(pb->progress.timer);
}

/*
 * Configure hook:
 *
 * @@@ TODO: deal with [$pb configure -value ... -variable ...]
 */
static int ProgressbarConfigure(Tcl_Interp *interp, void *recordPtr, int mask)
{
    Progressbar *pb = recordPtr;
    Progressbar *pb = (Progressbar *)recordPtr;
    Tcl_Obj *varName = pb->progress.variableObj;
    Ttk_TraceHandle *vt = 0;

    if (varName != NULL && *Tcl_GetString(varName) != '\0') {
	vt = Ttk_TraceVariable(interp, varName, VariableChanged, recordPtr);
	if (!vt) return TCL_ERROR;
    }
231
232
233
234
235
236
237

238


239
240

241
242
243
244
245
246
247
257
258
259
260
261
262
263
264

265
266
267

268
269
270
271
272
273
274
275







+
-
+
+

-
+







    return TCL_OK;
}

/*
 * Post-configuration hook:
 */
static int ProgressbarPostConfigure(
    TCL_UNUSED(Tcl_Interp *),
    Tcl_Interp *interp, void *recordPtr, int mask)
    void *recordPtr,
    TCL_UNUSED(int))
{
    Progressbar *pb = recordPtr;
    Progressbar *pb = (Progressbar *)recordPtr;
    int status = TCL_OK;

    if (pb->progress.variableTrace) {
	status = Ttk_FireTrace(pb->progress.variableTrace);
	if (WidgetDestroyed(&pb->core)) {
	    return TCL_ERROR;
	}
262
263
264
265
266
267
268
269
270



271
272
273
274
275
276
277

278
279
280
281
282
283
284
290
291
292
293
294
295
296


297
298
299
300
301
302
303
304
305

306
307
308
309
310
311
312
313







-
-
+
+
+






-
+








/*
 * Size hook:
 * 	Compute base layout size, overrid
 */
static int ProgressbarSize(void *recordPtr, int *widthPtr, int *heightPtr)
{
    Progressbar *pb = recordPtr;
    int length = 100, orient = TTK_ORIENT_HORIZONTAL;
    Progressbar *pb = (Progressbar *)recordPtr;
    int length = 100;
    Ttk_Orient orient = TTK_ORIENT_HORIZONTAL;

    TtkWidgetSize(recordPtr, widthPtr, heightPtr);

    /* Override requested width (height) based on -length and -orient
     */
    Tk_GetPixelsFromObj(NULL, pb->core.tkwin, pb->progress.lengthObj, &length);
    Ttk_GetOrientFromObj(NULL, pb->progress.orientObj, &orient);
    TtkGetOrientFromObj(NULL, pb->progress.orientObj, &orient);

    if (orient == TTK_ORIENT_HORIZONTAL) {
	*widthPtr = length;
    } else {
	*heightPtr = length;
    }

330
331
332
333
334
335
336
337

338
339
340
341

342
343
344
345
346
347
348
349
350

351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369

370
371
372
373
374
375
376
359
360
361
362
363
364
365

366
367
368
369

370
371
372
373
374
375
376
377
378

379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397

398
399
400
401
402
403
404
405







-
+



-
+








-
+


















-
+







	pbarBox.y = parcel.y + (int)(fraction * (parcel.height-pbarBox.height));
    }
    Ttk_PlaceElement(pb->core.layout, pbar, pbarBox);
}

static void ProgressbarDoLayout(void *recordPtr)
{
    Progressbar *pb = recordPtr;
    Progressbar *pb = (Progressbar *)recordPtr;
    WidgetCore *corePtr = &pb->core;
    Ttk_Element pbar = Ttk_FindElement(corePtr->layout, "pbar");
    double value = 0.0, maximum = 100.0;
    int orient = TTK_ORIENT_HORIZONTAL;
    Ttk_Orient orient = TTK_ORIENT_HORIZONTAL;

    Ttk_PlaceLayout(corePtr->layout,corePtr->state,Ttk_WinBox(corePtr->tkwin));

    /* Adjust the bar size:
     */

    Tcl_GetDoubleFromObj(NULL, pb->progress.valueObj, &value);
    Tcl_GetDoubleFromObj(NULL, pb->progress.maximumObj, &maximum);
    Ttk_GetOrientFromObj(NULL, pb->progress.orientObj, &orient);
    TtkGetOrientFromObj(NULL, pb->progress.orientObj, &orient);

    if (pbar) {
	double fraction = value / maximum;
	Ttk_Box parcel = Ttk_ClientRegion(corePtr->layout, "trough");

	if (pb->progress.mode == TTK_PROGRESSBAR_DETERMINATE) {
	    ProgressbarDeterminateLayout(
		pb, pbar, parcel, fraction, orient);
	} else {
	    ProgressbarIndeterminateLayout(
		pb, pbar, parcel, fraction, orient);
	}
    }
}

static Ttk_Layout ProgressbarGetLayout(
    Tcl_Interp *interp, Ttk_Theme theme, void *recordPtr)
{
    Progressbar *pb = recordPtr;
    Progressbar *pb = (Progressbar *)recordPtr;
    Ttk_Layout layout = TtkWidgetGetOrientedLayout(
	interp, theme, recordPtr, pb->progress.orientObj);

    /*
     * Check if the style supports animation:
     */
    pb->progress.period = 0;
392
393
394
395
396
397
398
399

400
401

402
403
404
405
406
407
408
421
422
423
424
425
426
427

428
429

430
431
432
433
434
435
436
437







-
+

-
+







 */

/* $sb step ?amount?
 */
static int ProgressbarStepCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Progressbar *pb = recordPtr;
    Progressbar *pb = (Progressbar *)recordPtr;
    double value = 0.0, stepAmount = 1.0;
    Tcl_Obj *newValueObj; 
    Tcl_Obj *newValueObj;

    if (objc == 3) {
	if (Tcl_GetDoubleFromObj(interp, objv[2], &stepAmount) != TCL_OK) {
	    return TCL_ERROR;
	}
    } else if (objc != 2) {
	Tcl_WrongNumArgs(interp, 2,objv, "?stepAmount?");
421
422
423
424
425
426
427
428

429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449

450
451
452
453
454
455
456
450
451
452
453
454
455
456

457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477

478
479
480
481
482
483
484
485







-
+




















-
+







    }

    newValueObj = Tcl_NewDoubleObj(value);
    Tcl_IncrRefCount(newValueObj);

    TtkRedisplayWidget(&pb->core);

    /* Update value by setting the linked -variable, if there is one: 
    /* Update value by setting the linked -variable, if there is one:
     */
    if (pb->progress.variableTrace) {
	int result = Tcl_ObjSetVar2(
		        interp, pb->progress.variableObj, 0, newValueObj,
		        TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG)
	        ? TCL_OK : TCL_ERROR;
        Tcl_DecrRefCount(newValueObj);
        return result;
    }

    /* Otherwise, change the -value directly:
     */
    Tcl_DecrRefCount(pb->progress.valueObj);
    pb->progress.valueObj = newValueObj;
    CheckAnimation(pb);

    return TCL_OK;
}

/* $sb start|stop ?args? --
 * Change [$sb $cmd ...] to [ttk::progressbar::$cmd ...] 
 * Change [$sb $cmd ...] to [ttk::progressbar::$cmd ...]
 * and pass to interpreter.
 */
static int ProgressbarStartStopCommand(
    Tcl_Interp *interp, const char *cmdName, int objc, Tcl_Obj *const objv[])
{
    Tcl_Obj *cmd = Tcl_NewListObj(objc, objv);
    Tcl_Obj *prefix[2];
466
467
468
469
470
471
472



473

474
475
476

477
478
479



480

481
482
483

484
485
486
487
488

489
490
491
492
493
494

495
496
497
498
499
500
501

502
503
504
505
506
507
508
495
496
497
498
499
500
501
502
503
504

505
506
507

508
509
510
511
512
513
514

515
516
517

518
519
520
521

522
523
524
525
526
527
528
529
530
531
532
533
534
535
536

537
538
539
540
541
542
543
544







+
+
+
-
+


-
+



+
+
+
-
+


-
+



-

+






+






-
+







    status = Tcl_EvalObjEx(interp, cmd, 0);
    Tcl_DecrRefCount(cmd);

    return status;
}

static int ProgressbarStartCommand(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
    Tcl_Obj *const objv[])
{
    return ProgressbarStartStopCommand(
	interp, "::ttk::progressbar::start", objc, objv);
	    interp, "::ttk::progressbar::start", objc, objv);
}

static int ProgressbarStopCommand(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
    Tcl_Obj *const objv[])
{
    return ProgressbarStartStopCommand(
	interp, "::ttk::progressbar::stop", objc, objv);
	    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:
 */
static WidgetSpec ProgressbarWidgetSpec =
static const WidgetSpec ProgressbarWidgetSpec =
{
    "TProgressbar",		/* className */
    sizeof(Progressbar),	/* recordSize */
    ProgressbarOptionSpecs,	/* optionSpecs */
    ProgressbarCommands,	/* subcommands */
    ProgressbarInitialize,	/* initializeProc */
    ProgressbarCleanup,		/* cleanupProc */
520
521
522
523
524
525
526
527


528
529
530
531
532
533
534
556
557
558
559
560
561
562

563
564
565
566
567
568
569
570
571







-
+
+







TTK_BEGIN_LAYOUT(VerticalProgressbarLayout)
    TTK_GROUP("Vertical.Progressbar.trough", TTK_FILL_BOTH,
	TTK_NODE("Vertical.Progressbar.pbar", TTK_PACK_BOTTOM|TTK_FILL_X))
TTK_END_LAYOUT

TTK_BEGIN_LAYOUT(HorizontalProgressbarLayout)
    TTK_GROUP("Horizontal.Progressbar.trough", TTK_FILL_BOTH,
	TTK_NODE("Horizontal.Progressbar.pbar", TTK_PACK_LEFT|TTK_FILL_Y))
	TTK_NODE("Horizontal.Progressbar.pbar", TTK_PACK_LEFT|TTK_FILL_Y)
	TTK_NODE("Horizontal.Progressbar.text", TTK_PACK_LEFT))
TTK_END_LAYOUT

/*
 * Initialization:
 */

MODULE_SCOPE
Changes to generic/ttk/ttkScale.c.
1
2

3
4
5
6
7

8
9
10
11
12
13
14
15
16
1

2
3
4
5
6

7


8
9
10
11
12
13
14

-
+




-
+
-
-







/*
 * Copyright (C) 2004 Pat Thoyts <[email protected]>
 * Copyright © 2004 Pat Thoyts <[email protected]>
 *
 * ttk::scale widget.
 */

#include <tk.h>
#include "tkInt.h"
#include <string.h>
#include <stdio.h>
#include "ttkTheme.h"
#include "ttkWidget.h"

#define DEF_SCALE_LENGTH "100"

#define MAX(a,b) ((a) > (b) ? (a) : (b))
#define MIN(a,b) ((a) < (b) ? (a) : (b))
48
49
50
51
52
53
54
55

56
57
58

59
60
61
62


63
64
65
66



67
68
69

70
71

72
73

74
75

76
77
78
79
80


81
82
83
84
85
86
87
88
89
90
91
92

93
94
95
96
97

98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115



116
117


118
119
120
121
122
123

124
125
126
127
128
129
130
131
132
133
134
135
136

137
138
139
140
141
142
143
46
47
48
49
50
51
52

53
54
55

56
57
58


59
60
61



62
63
64
65
66

67
68

69
70

71
72

73
74
75
76


77
78
79
80
81
82
83
84
85
86
87
88
89

90
91
92
93
94

95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112

113
114
115
116

117
118
119
120
121
122
123

124
125
126
127
128
129
130
131
132
133
134
135
136

137
138
139
140
141
142
143
144







-
+


-
+


-
-
+
+

-
-
-
+
+
+


-
+

-
+

-
+

-
+



-
-
+
+











-
+




-
+

















-
+
+
+

-
+
+





-
+












-
+








typedef struct
{
    WidgetCore core;
    ScalePart  scale;
} Scale;

static Tk_OptionSpec ScaleOptionSpecs[] =
static const Tk_OptionSpec ScaleOptionSpecs[] =
{
    {TK_OPTION_STRING, "-command", "command", "Command", "",
	Tk_Offset(Scale,scale.commandObj), -1, 
	offsetof(Scale,scale.commandObj), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK,0,0},
    {TK_OPTION_STRING, "-variable", "variable", "Variable", "",
	Tk_Offset(Scale,scale.variableObj), -1, 
	0,0,0},
	offsetof(Scale,scale.variableObj), TCL_INDEX_NONE,
	0, 0, 0},
    {TK_OPTION_STRING_TABLE, "-orient", "orient", "Orient", "horizontal",
	Tk_Offset(Scale,scale.orientObj),
	Tk_Offset(Scale,scale.orient), 0, 
	(ClientData)ttkOrientStrings, STYLE_CHANGED },
	offsetof(Scale,scale.orientObj),
	offsetof(Scale,scale.orient), 0,
	(void *)ttkOrientStrings, STYLE_CHANGED },

    {TK_OPTION_DOUBLE, "-from", "from", "From", "0",
	Tk_Offset(Scale,scale.fromObj), -1, 0, 0, 0},
	offsetof(Scale,scale.fromObj), TCL_INDEX_NONE, 0, 0, 0},
    {TK_OPTION_DOUBLE, "-to", "to", "To", "1.0",
	Tk_Offset(Scale,scale.toObj), -1, 0, 0, 0},
	offsetof(Scale,scale.toObj), TCL_INDEX_NONE, 0, 0, 0},
    {TK_OPTION_DOUBLE, "-value", "value", "Value", "0",
	Tk_Offset(Scale,scale.valueObj), -1, 0, 0, 0},
	offsetof(Scale,scale.valueObj), TCL_INDEX_NONE, 0, 0, 0},
    {TK_OPTION_PIXELS, "-length", "length", "Length",
	DEF_SCALE_LENGTH, Tk_Offset(Scale,scale.lengthObj), -1, 0, 0, 
	DEF_SCALE_LENGTH, offsetof(Scale,scale.lengthObj), TCL_INDEX_NONE, 0, 0,
    	GEOMETRY_CHANGED},

    {TK_OPTION_STRING, "-state", "state", "State",
	"normal", Tk_Offset(Scale,scale.stateObj), -1,
        0,0,STATE_CHANGED},
	"normal", offsetof(Scale,scale.stateObj), TCL_INDEX_NONE,
        0, 0, STATE_CHANGED},

    WIDGET_TAKEFOCUS_TRUE,
    WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs)
};

static XPoint ValueToPoint(Scale *scalePtr, double value);
static double PointToValue(Scale *scalePtr, int x, int y);

/* ScaleVariableChanged --
 * 	Variable trace procedure for scale -variable;
 * 	Updates the scale's value.
 * 	If the linked variable is not a valid double, 
 * 	If the linked variable is not a valid double,
 * 	sets the 'invalid' state.
 */
static void ScaleVariableChanged(void *recordPtr, const char *value)
{
    Scale *scale = recordPtr;
    Scale *scale = (Scale *)recordPtr;
    double v;

    if (value == NULL || Tcl_GetDouble(0, value, &v) != TCL_OK) {
	TtkWidgetChangeState(&scale->core, TTK_STATE_INVALID, 0);
    } else {
	Tcl_Obj *valueObj = Tcl_NewDoubleObj(v);
	Tcl_IncrRefCount(valueObj);
	Tcl_DecrRefCount(scale->scale.valueObj);
	scale->scale.valueObj = valueObj;
	TtkWidgetChangeState(&scale->core, 0, TTK_STATE_INVALID);
    }
    TtkRedisplayWidget(&scale->core);
}

/* ScaleInitialize --
 * 	Scale widget initialization hook.
 */
static void ScaleInitialize(Tcl_Interp *interp, void *recordPtr)
static void ScaleInitialize(
    TCL_UNUSED(Tcl_Interp *),
    void *recordPtr)
{
    Scale *scalePtr = recordPtr;
    Scale *scalePtr = (Scale *)recordPtr;

    TtkTrackElementState(&scalePtr->core);
}

static void ScaleCleanup(void *recordPtr)
{
    Scale *scale = recordPtr;
    Scale *scale = (Scale *)recordPtr;

    if (scale->scale.variableTrace) {
	Ttk_UntraceVariable(scale->scale.variableTrace);
	scale->scale.variableTrace = 0;
    }
}

/* ScaleConfigure --
 * 	Configuration hook.
 */
static int ScaleConfigure(Tcl_Interp *interp, void *recordPtr, int mask)
{
    Scale *scale = recordPtr;
    Scale *scale = (Scale *)recordPtr;
    Tcl_Obj *varName = scale->scale.variableObj;
    Ttk_TraceHandle *vt = 0;

    if (varName != NULL && *Tcl_GetString(varName) != '\0') {
	vt = Ttk_TraceVariable(interp,varName, ScaleVariableChanged,recordPtr);
	if (!vt) return TCL_ERROR;
    }
159
160
161
162
163
164
165

166


167
168

169
170
171
172
173
174
175
160
161
162
163
164
165
166
167

168
169
170

171
172
173
174
175
176
177
178







+
-
+
+

-
+







    return TCL_OK;
}

/* ScalePostConfigure --
 * 	Post-configuration hook.
 */
static int ScalePostConfigure(
    TCL_UNUSED(Tcl_Interp *),
    Tcl_Interp *interp, void *recordPtr, int mask)
    void *recordPtr,
    TCL_UNUSED(int))
{
    Scale *scale = recordPtr;
    Scale *scale = (Scale *)recordPtr;
    int status = TCL_OK;

    if (scale->scale.variableTrace) {
	status = Ttk_FireTrace(scale->scale.variableTrace);
	if (WidgetDestroyed(&scale->core)) {
	    return TCL_ERROR;
	}
185
186
187
188
189
190
191
192

193
194
195

196
197
198
199
200
201
202
188
189
190
191
192
193
194

195
196
197

198
199
200
201
202
203
204
205







-
+


-
+








    return status;
}

/* ScaleGetLayout --
 *	getLayout hook.
 */
static Ttk_Layout 
static Ttk_Layout
ScaleGetLayout(Tcl_Interp *interp, Ttk_Theme theme, void *recordPtr)
{
    Scale *scalePtr = recordPtr;
    Scale *scalePtr = (Scale *)recordPtr;
    return TtkWidgetGetOrientedLayout(
	interp, theme, recordPtr, scalePtr->scale.orientObj);
}

/*
 * TroughBox --
 * 	Returns the inner area of the trough element.
249
250
251
252
253
254
255
256

257
258
259
260
261
262
263

264
265
266
267
268
269
270
252
253
254
255
256
257
258

259
260
261
262
263
264
265

266
267
268
269
270
271
272
273







-
+






-
+








    fraction = (value - from) / (to - from);

    return fraction < 0 ? 0 : fraction > 1 ? 1 : fraction;
}

/* $scale get ?x y? --
 * 	Returns the current value of the scale widget, or if $x and 
 * 	Returns the current value of the scale widget, or if $x and
 * 	$y are specified, the value represented by point @x,y.
 */
static int
ScaleGetCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Scale *scalePtr = recordPtr;
    Scale *scalePtr = (Scale *)recordPtr;
    int x, y, r = TCL_OK;
    double value = 0;

    if ((objc != 2) && (objc != 4)) {
	Tcl_WrongNumArgs(interp, 1, objv, "get ?x y?");
	return TCL_ERROR;
    }
284
285
286
287
288
289
290
291

292
293
294
295
296
297
298
287
288
289
290
291
292
293

294
295
296
297
298
299
300
301







-
+








/* $scale set $newValue
 */
static int
ScaleSetCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Scale *scalePtr = recordPtr;
    Scale *scalePtr = (Scale *)recordPtr;
    double from = 0.0, to = 1.0, value;
    int result = TCL_OK;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "set value");
	return TCL_ERROR;
    }
352
353
354
355
356
357
358
359

360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378


379
380
381
382
383
384
385
386

387
388
389
390
391
392
393
394

395
396
397
398
399
400
401
355
356
357
358
359
360
361

362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379


380
381
382
383
384
385
386
387
388

389
390
391
392
393
394
395
396

397
398
399
400
401
402
403
404







-
+

















-
-
+
+







-
+







-
+







    return result;
}

static int
ScaleCoordsCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Scale *scalePtr = recordPtr;
    Scale *scalePtr = (Scale *)recordPtr;
    double value;
    int r = TCL_OK;

    if (objc < 2 || objc > 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "coords ?value?");
	return TCL_ERROR;
    }

    if (objc == 3) {
	r = Tcl_GetDoubleFromObj(interp, objv[2], &value);
    } else {
	r = Tcl_GetDoubleFromObj(interp, scalePtr->scale.valueObj, &value);
    }

    if (r == TCL_OK) {
	Tcl_Obj *point[2];
	XPoint pt = ValueToPoint(scalePtr, value);
	point[0] = Tcl_NewIntObj(pt.x);
	point[1] = Tcl_NewIntObj(pt.y);
	point[0] = Tcl_NewWideIntObj(pt.x);
	point[1] = Tcl_NewWideIntObj(pt.y);
	Tcl_SetObjResult(interp, Tcl_NewListObj(2, point));
    }
    return r;
}

static void ScaleDoLayout(void *clientData)
{
    WidgetCore *corePtr = clientData;
    WidgetCore *corePtr = (WidgetCore *)clientData;
    Ttk_Element slider = Ttk_FindElement(corePtr->layout, "slider");

    Ttk_PlaceLayout(corePtr->layout,corePtr->state,Ttk_WinBox(corePtr->tkwin));

    /* Adjust the slider position:
     */
    if (slider) {
	Scale *scalePtr = clientData;
	Scale *scalePtr = (Scale *)clientData;
	Ttk_Box troughBox = TroughBox(scalePtr);
	Ttk_Box sliderBox = Ttk_ElementParcel(slider);
	double value = 0.0;
	double fraction;
	int range;

	Tcl_GetDoubleFromObj(NULL, scalePtr->scale.valueObj, &value);
414
415
416
417
418
419
420
421
422


423
424
425
426
427
428
429
417
418
419
420
421
422
423


424
425
426
427
428
429
430
431
432







-
-
+
+








/*
 * ScaleSize --
 * 	Compute requested size of scale.
 */
static int ScaleSize(void *clientData, int *widthPtr, int *heightPtr)
{
    WidgetCore *corePtr = clientData;
    Scale *scalePtr = clientData;
    WidgetCore *corePtr = (WidgetCore *)clientData;
    Scale *scalePtr = (Scale *)clientData;
    int length;

    Ttk_LayoutSize(corePtr->layout, corePtr->state, widthPtr, heightPtr);

    /* Assert the -length configuration option */
    Tk_GetPixelsFromObj(NULL, corePtr->tkwin,
	    scalePtr->scale.lengthObj, &length);
475
476
477
478
479
480
481

482

483
484


485
486
487
488
489


490
491
492
493

494
495
496
497
498
499
500
478
479
480
481
482
483
484
485
486
487


488
489
490

491


492
493
494
495
496

497
498
499
500
501
502
503
504







+

+
-
-
+
+

-

-
-
+
+



-
+







	pt.x = troughBox.x + troughBox.width / 2;
	pt.y = troughBox.y + (int)(fraction * troughBox.height);
    }
    return pt;
}

static const Ttk_Ensemble ScaleCommands[] = {
    { "cget",        TtkWidgetCgetCommand,0 },
    { "configure",   TtkWidgetConfigureCommand,0 },
    { "coords",      ScaleCoordsCommand,0 },
    { "cget",        TtkWidgetCgetCommand,0 },
    { "state",       TtkWidgetStateCommand,0 },
    { "get",         ScaleGetCommand,0 },
    { "identify",    TtkWidgetIdentifyCommand,0 },
    { "instate",     TtkWidgetInstateCommand,0 },
    { "identify",    TtkWidgetIdentifyCommand,0 },
    { "set",         ScaleSetCommand,0 },
    { "get",         ScaleGetCommand,0 },
    { "coords",      ScaleCoordsCommand,0 },
    { "state",       TtkWidgetStateCommand,0 },
    { "style",		TtkWidgetStyleCommand,0 },
    { 0,0,0 }
};

static WidgetSpec ScaleWidgetSpec =
static const WidgetSpec ScaleWidgetSpec =
{
    "TScale",			/* Class name */
    sizeof(Scale),		/* record size */
    ScaleOptionSpecs,		/* option specs */
    ScaleCommands,		/* widget commands */
    ScaleInitialize,		/* initialization proc */
    ScaleCleanup,		/* cleanup proc */
Changes to generic/ttk/ttkScroll.c.
51
52
53
54
55
56
57
58

59
60
61
62
63
64
65
51
52
53
54
55
56
57

58
59
60
61
62
63
64
65







-
+







};

/* TtkCreateScrollHandle --
 * 	Initialize scroll handle.
 */
ScrollHandle TtkCreateScrollHandle(WidgetCore *corePtr, Scrollable *scrollPtr)
{
    ScrollHandle h = ckalloc(sizeof(*h));
    ScrollHandle h = (ScrollHandle)ckalloc(sizeof(*h));

    h->flags = 0;
    h->corePtr = corePtr;
    h->scrollPtr = scrollPtr;

    scrollPtr->first = 0;
    scrollPtr->last = 1;
100
101
102
103
104
105
106
107





108
109
110
111
112
113
114
115

116
117
118
119
120
121
122
123
124
125
126
127
128
129
130

131
132
133
134
135

136
137
138
139
140
141
142
100
101
102
103
104
105
106

107
108
109
110
111
112


113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132

133
134
135
136
137

138
139
140
141
142
143
144
145







-
+
+
+
+
+

-
-





+














-
+




-
+







    if (WidgetDestroyed(corePtr)) {
	Tcl_Release(corePtr);
	return TCL_ERROR;
    }
    Tcl_Release(corePtr);

    if (code != TCL_OK && !Tcl_InterpDeleted(interp)) {
	/* Disable the -scrollcommand, add to stack trace:
	/* Add error to stack trace.
         * Also set the SCROLL_UPDATE_REQUIRED flag so that a later call to
         * TtkScrolled has an effect. Indeed, the error in the -scrollcommand
         * callback may later be gone, for instance the callback proc got
         * defined in the meantime.
	 */
	ckfree(s->scrollCmd);
	s->scrollCmd = 0;

	Tcl_AddErrorInfo(interp, /* @@@ "horizontal" / "vertical" */
		"\n    (scrolling command executed by ");
	Tcl_AddErrorInfo(interp, Tk_PathName(h->corePtr->tkwin));
	Tcl_AddErrorInfo(interp, ")");
        TtkScrollbarUpdateRequired(h);
    }
    return code;
}

/* UpdateScrollbarBG --
 * 	Idle handler to update the scrollbar.
 */
static void UpdateScrollbarBG(ClientData clientData)
{
    ScrollHandle h = (ScrollHandle)clientData;
    Tcl_Interp *interp = h->corePtr->interp;
    int code;

    h->flags &= ~SCROLL_UPDATE_PENDING;
    Tcl_Preserve((ClientData) interp);
    Tcl_Preserve(interp);
    code = UpdateScrollbar(interp, h);
    if (code == TCL_ERROR && !Tcl_InterpDeleted(interp)) {
	Tcl_BackgroundException(interp, code);
    }
    Tcl_Release((ClientData) interp);
    Tcl_Release(interp);
}

/* TtkScrolled --
 * 	Update scroll info, schedule scrollbar update.
 */
void TtkScrolled(ScrollHandle h, int first, int last, int total)
{
160
161
162
163
164
165
166
167

168
169
170
171
172
173
174
163
164
165
166
167
168
169

170
171
172
173
174
175
176
177







-
+







	    || (h->flags & SCROLL_UPDATE_REQUIRED))
    {
	s->first = first;
	s->last = last;
	s->total = total;

	if (!(h->flags & SCROLL_UPDATE_PENDING)) {
	    Tcl_DoWhenIdle(UpdateScrollbarBG, (ClientData)h);
	    Tcl_DoWhenIdle(UpdateScrollbarBG, h);
	    h->flags |= SCROLL_UPDATE_PENDING;
	}
    }
}

/* TtkScrollbarUpdateRequired --
 * 	Force a scrollbar update at the next call to TtkScrolled(),
267
268
269
270
271
272
273
274

275
276
277
278
270
271
272
273
274
275
276

277
278
279
280
281







-
+




	TtkRedisplayWidget(h->corePtr);
    }
}

void TtkFreeScrollHandle(ScrollHandle h)
{
    if (h->flags & SCROLL_UPDATE_PENDING) {
	Tcl_CancelIdleCall(UpdateScrollbarBG, (ClientData)h);
	Tcl_CancelIdleCall(UpdateScrollbarBG, h);
    }
    ckfree(h);
}

Changes to generic/ttk/ttkScrollbar.c.
1
2

3
4
5
6
7

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

26
27
28
29
30
31
32
33
34
35

36
37
38

39
40
41
42
43



44
45
46
47
48
49
50
51
52
53
54




55
56


57
58
59
60
61
62
63
64
65
66

67
68
69
70
71
72
73
74
75
76
77
78
79
80

81
82
83
84
85
86
87
1

2
3
4
5
6

7

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

24
25
26
27
28
29
30
31
32
33

34
35
36

37
38
39



40
41
42
43
44
45
46
47
48
49
50
51


52
53
54
55
56

57
58
59
60
61
62
63
64
65
66
67

68
69
70
71
72
73
74
75
76
77
78
79
80
81

82
83
84
85
86
87
88
89

-
+




-
+
-
















-
+









-
+


-
+


-
-
-
+
+
+









-
-
+
+
+
+

-
+
+









-
+













-
+







/*
 * Copyright (c) 2003, Joe English
 * Copyright © 2003 Joe English
 *
 * ttk::scrollbar widget.
 */

#include <tk.h>
#include "tkInt.h"

#include "ttkTheme.h"
#include "ttkWidget.h"

/*------------------------------------------------------------------------
 * +++ Scrollbar widget record.
 */
typedef struct
{
    Tcl_Obj	*commandObj;

    int 	orient;
    Tcl_Obj	*orientObj;

    double	first;			/* top fraction */
    double	last;			/* bottom fraction */

    Ttk_Box	troughBox;		/* trough parcel */ 
    Ttk_Box	troughBox;		/* trough parcel */
    int 	minSize;		/* minimum size of thumb */
} ScrollbarPart;

typedef struct
{
    WidgetCore core;
    ScrollbarPart scrollbar;
} Scrollbar;

static Tk_OptionSpec ScrollbarOptionSpecs[] =
static const Tk_OptionSpec ScrollbarOptionSpecs[] =
{
    {TK_OPTION_STRING, "-command", "command", "Command", "",
	Tk_Offset(Scrollbar,scrollbar.commandObj), -1, 0,0,0},
	offsetof(Scrollbar, scrollbar.commandObj), TCL_INDEX_NONE, 0, 0, 0},

    {TK_OPTION_STRING_TABLE, "-orient", "orient", "Orient", "vertical",
	Tk_Offset(Scrollbar,scrollbar.orientObj),
	Tk_Offset(Scrollbar,scrollbar.orient),
	0,(ClientData)ttkOrientStrings,STYLE_CHANGED },
	offsetof(Scrollbar, scrollbar.orientObj),
	offsetof(Scrollbar, scrollbar.orient),
	0, (void *)ttkOrientStrings, STYLE_CHANGED },

    WIDGET_TAKEFOCUS_FALSE,
    WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs)
};

/*------------------------------------------------------------------------
 * +++ Widget hooks.
 */

static void 
ScrollbarInitialize(Tcl_Interp *interp, void *recordPtr)
static void
ScrollbarInitialize(
    TCL_UNUSED(Tcl_Interp *),
    void *recordPtr)
{
    Scrollbar *sb = recordPtr;
    Scrollbar *sb = (Scrollbar *)recordPtr;

    sb->scrollbar.first = 0.0;
    sb->scrollbar.last = 1.0;

    TtkTrackElementState(&sb->core);
}

static Ttk_Layout ScrollbarGetLayout(
    Tcl_Interp *interp, Ttk_Theme theme, void *recordPtr)
{
    Scrollbar *sb = recordPtr;
    Scrollbar *sb = (Scrollbar *)recordPtr;
    return TtkWidgetGetOrientedLayout(
	interp, theme, recordPtr, sb->scrollbar.orientObj);
}

/*
 * ScrollbarDoLayout --
 * 	Layout hook.  Adjusts the position of the scrollbar thumb.
 *
 * Side effects:
 * 	Sets sb->troughBox and sb->minSize.
 */
static void ScrollbarDoLayout(void *recordPtr)
{
    Scrollbar *sb = recordPtr;
    Scrollbar *sb = (Scrollbar *)recordPtr;
    WidgetCore *corePtr = &sb->core;
    Ttk_Element thumb;
    Ttk_Box thumbBox;
    int thumbWidth, thumbHeight;
    double first, last, size;
    int minSize;

129
130
131
132
133
134
135
136

137
138
139
140
141
142
143
131
132
133
134
135
136
137

138
139
140
141
142
143
144
145







-
+







/* $sb set $first $last --
 * 	Set the position of the scrollbar.
 */
static int
ScrollbarSetCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Scrollbar *scrollbar = recordPtr;
    Scrollbar *scrollbar = (Scrollbar *)recordPtr;
    Tcl_Obj *firstObj, *lastObj;
    double first, last;

    if (objc != 4) {
	Tcl_WrongNumArgs(interp, 2, objv, "first last");
	return TCL_ERROR;
    }
180
181
182
183
184
185
186
187

188
189
190
191
192
193
194
182
183
184
185
186
187
188

189
190
191
192
193
194
195
196







-
+







/* $sb get --
 * 	Returns the last thing passed to 'set'.
 */
static int
ScrollbarGetCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Scrollbar *scrollbar = recordPtr;
    Scrollbar *scrollbar = (Scrollbar *)recordPtr;
    Tcl_Obj *result[2];

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 2, objv, "");
	return TCL_ERROR;
    }

203
204
205
206
207
208
209
210

211
212
213
214
215
216
217
205
206
207
208
209
210
211

212
213
214
215
216
217
218
219







-
+







 * 	Returns the percentage change corresponding to a mouse movement
 * 	of $dx, $dy.
 */
static int
ScrollbarDeltaCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Scrollbar *sb = recordPtr;
    Scrollbar *sb = (Scrollbar *)recordPtr;
    double dx, dy;
    double delta = 0.0;

    if (objc != 4) {
	Tcl_WrongNumArgs(interp, 2, objv, "dx dy");
	return TCL_ERROR;
    }
237
238
239
240
241
242
243
244

245
246
247
248
249
250

251
252
253
254
255
256
257
239
240
241
242
243
244
245

246
247
248
249
250
251

252
253
254
255
256
257
258
259







-
+





-
+








    Tcl_SetObjResult(interp, Tcl_NewDoubleObj(delta));
    return TCL_OK;
}

/* $sb fraction $x $y --
 * 	Returns a real number between 0 and 1 indicating  where  the
 * 	point given by x and y lies in the trough area of the scrollbar. 
 * 	point given by x and y lies in the trough area of the scrollbar.
 */
static int
ScrollbarFractionCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Scrollbar *sb = recordPtr;
    Scrollbar *sb = (Scrollbar *)recordPtr;
    Ttk_Box b = sb->scrollbar.troughBox;
    int minSize = sb->scrollbar.minSize;
    double x, y;
    double fraction = 0.0;

    if (objc != 4) {
	Tcl_WrongNumArgs(interp, 2, objv, "x y");
276
277
278
279
280
281
282
283
284

285
286
287
288
289
290
291

292
293
294
295
296
297
298

299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319

320
321
322
323
324
325
326
327

328
329
330
331
332
333
334
278
279
280
281
282
283
284

285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300

301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320


321
322
323
324
325
326
327


328
329
330
331
332
333
334
335







-

+







+






-
+



















-
-
+






-
-
+







    }

    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.
 */
static WidgetSpec ScrollbarWidgetSpec =
static const WidgetSpec ScrollbarWidgetSpec =
{
    "TScrollbar",		/* className */
    sizeof(Scrollbar),		/* recordSize */
    ScrollbarOptionSpecs,	/* optionSpecs */
    ScrollbarCommands,		/* subcommands */
    ScrollbarInitialize,	/* initializeProc */
    TtkNullCleanup,		/* cleanupProc */
    TtkCoreConfigure,		/* configureProc */
    TtkNullPostConfigure,	/* postConfigureProc */
    ScrollbarGetLayout,		/* getLayoutProc */
    TtkWidgetSize, 		/* sizeProc */
    ScrollbarDoLayout,		/* layoutProc */
    TtkWidgetDisplay		/* displayProc */
};

TTK_BEGIN_LAYOUT(VerticalScrollbarLayout)
    TTK_GROUP("Vertical.Scrollbar.trough", TTK_FILL_Y,
	TTK_NODE("Vertical.Scrollbar.uparrow", TTK_PACK_TOP)
	TTK_NODE("Vertical.Scrollbar.downarrow", TTK_PACK_BOTTOM)
	TTK_NODE(
	    "Vertical.Scrollbar.thumb", TTK_PACK_TOP|TTK_EXPAND|TTK_FILL_BOTH))
	TTK_NODE("Vertical.Scrollbar.thumb", TTK_FILL_BOTH))
TTK_END_LAYOUT

TTK_BEGIN_LAYOUT(HorizontalScrollbarLayout)
    TTK_GROUP("Horizontal.Scrollbar.trough", TTK_FILL_X,
	TTK_NODE("Horizontal.Scrollbar.leftarrow", TTK_PACK_LEFT)
	TTK_NODE("Horizontal.Scrollbar.rightarrow", TTK_PACK_RIGHT)
	TTK_NODE(
	"Horizontal.Scrollbar.thumb", TTK_PACK_LEFT|TTK_EXPAND|TTK_FILL_BOTH))
	TTK_NODE("Horizontal.Scrollbar.thumb", TTK_FILL_BOTH))
TTK_END_LAYOUT

/*------------------------------------------------------------------------
 * +++ Initialization.
 */

MODULE_SCOPE
Changes to generic/ttk/ttkSeparator.c.
1
2

3
4
5
6
7

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

27
28
29
30



31
32
33
34
35
36
37
38
39
40
41
42
43

44
45
46
47
48
49
50
51
52
53

54
55
56

57
58
59
60
61
62
63

64
65
66
67
68
69
70
1

2
3
4
5
6

7

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

25
26



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

42
43
44
45
46
47
48
49
50

51
52
53
54
55
56
57
58
59
60
61
62

63
64
65
66
67
68
69
70

-
+




-
+
-

















-
+

-
-
-
+
+
+












-
+








-

+



+






-
+







/*
 * Copyright (c) 2004, Joe English
 * Copyright © 2004 Joe English
 *
 * ttk::separator and ttk::sizegrip widgets.
 */

#include <tk.h>
#include "tkInt.h"

#include "ttkTheme.h"
#include "ttkWidget.h"

/* +++ Separator widget record:
 */
typedef struct
{
    Tcl_Obj	*orientObj;
    int 	orient;
} SeparatorPart;

typedef struct
{
    WidgetCore core;
    SeparatorPart separator;
} Separator;

static Tk_OptionSpec SeparatorOptionSpecs[] = {
static const Tk_OptionSpec SeparatorOptionSpecs[] = {
    {TK_OPTION_STRING_TABLE, "-orient", "orient", "Orient", "horizontal",
	Tk_Offset(Separator,separator.orientObj),
	Tk_Offset(Separator,separator.orient),
	0,(ClientData)ttkOrientStrings,STYLE_CHANGED },
	offsetof(Separator,separator.orientObj),
	offsetof(Separator,separator.orient),
	0, (void *)ttkOrientStrings, STYLE_CHANGED },

    WIDGET_TAKEFOCUS_FALSE,
    WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs)
};

/*
 * GetLayout hook --
 * 	Choose layout based on -orient option.
 */
static Ttk_Layout SeparatorGetLayout(
    Tcl_Interp *interp, Ttk_Theme theme, void *recordPtr)
{
    Separator *sep = recordPtr;
    Separator *sep = (Separator *)recordPtr;
    return TtkWidgetGetOrientedLayout(
	interp, theme, recordPtr, sep->separator.orientObj);
}

/*
 * 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:
 */
static WidgetSpec SeparatorWidgetSpec =
static const WidgetSpec SeparatorWidgetSpec =
{
    "TSeparator",		/* className */
    sizeof(Separator),		/* recordSize */
    SeparatorOptionSpecs,	/* optionSpecs */
    SeparatorCommands,		/* subcommands */
    TtkNullInitialize,		/* initializeProc */
    TtkNullCleanup,		/* cleanupProc */
80
81
82
83
84
85
86
87

88
89
90
91
92
93
94

95
96
97

98
99
100
101

102
103
104
105
106
107
108
80
81
82
83
84
85
86

87
88
89
90
91
92

93
94
95
96
97
98
99
100
101

102
103
104
105
106
107
108
109







-
+





-

+



+



-
+







    TTK_NODE("Separator.separator", TTK_FILL_BOTH)
TTK_END_LAYOUT

/* +++ Sizegrip widget:
 * 	Has no options or methods other than the standard ones.
 */

static Tk_OptionSpec SizegripOptionSpecs[] = {
static const Tk_OptionSpec SizegripOptionSpecs[] = {
    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 WidgetSpec SizegripWidgetSpec =
static const WidgetSpec SizegripWidgetSpec =
{
    "TSizegrip",		/* className */
    sizeof(WidgetCore),		/* recordSize */
    SizegripOptionSpecs, 	/* optionSpecs */
    SizegripCommands,		/* subcommands */
    TtkNullInitialize,		/* initializeProc */
    TtkNullCleanup,		/* cleanupProc */
Changes to generic/ttk/ttkSquare.c.
1

2
3
4
5
6

7
8
9
10
11
12
13

1
2
3
4
5

6
7
8
9
10
11
12
13
-
+




-
+







/* square.c - Copyright (C) 2004 Pat Thoyts <[email protected]>
/* square.c - Copyright © 2004 Pat Thoyts <[email protected]>
 *
 * Minimal sample ttk widget.
 */

#include <tk.h>
#include "tkInt.h"
#include "ttkTheme.h"
#include "ttkWidget.h"

#if defined(TTK_SQUARE_WIDGET) || 1

#ifndef DEFAULT_BORDERWIDTH
#define DEFAULT_BORDERWIDTH "2"
44
45
46
47
48
49
50
51

52
53
54

55
56
57
58
59



60
61

62
63
64

65
66

67
68

69
70

71
72
73


74
75
76


77
78
79
80
81
82
83
44
45
46
47
48
49
50

51
52
53

54
55
56



57
58
59
60

61
62
63

64
65

66
67

68
69

70
71


72
73
74


75
76
77
78
79
80
81
82
83







-
+


-
+


-
-
-
+
+
+

-
+


-
+

-
+

-
+

-
+

-
-
+
+

-
-
+
+







 * This structure is the same as the option specification structure used
 * for Tk widgets. For each option we provide the type, name and options
 * database name and class name and the position in the structure and
 * default values. At the bottom we bring in the standard widget option
 * defined for all widgets.
 */

static Tk_OptionSpec SquareOptionSpecs[] =
static const Tk_OptionSpec SquareOptionSpecs[] =
{
    {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
     DEFAULT_BORDERWIDTH, Tk_Offset(Square,square.borderWidthObj), -1,
     DEFAULT_BORDERWIDTH, offsetof(Square,square.borderWidthObj), TCL_INDEX_NONE,
     0,0,GEOMETRY_CHANGED },
    {TK_OPTION_BORDER, "-foreground", "foreground", "Foreground",
     DEFAULT_BACKGROUND, Tk_Offset(Square,square.foregroundObj),
     -1, 0, 0, 0},
    
     DEFAULT_BACKGROUND, offsetof(Square,square.foregroundObj),
     TCL_INDEX_NONE, 0, 0, 0},

    {TK_OPTION_PIXELS, "-width", "width", "Width",
     "50", Tk_Offset(Square,square.widthObj), -1, 0, 0,
     "50", offsetof(Square,square.widthObj), TCL_INDEX_NONE, 0, 0,
     GEOMETRY_CHANGED},
    {TK_OPTION_PIXELS, "-height", "height", "Height",
     "50", Tk_Offset(Square,square.heightObj), -1, 0, 0,
     "50", offsetof(Square,square.heightObj), TCL_INDEX_NONE, 0, 0,
     GEOMETRY_CHANGED},
    

    {TK_OPTION_STRING, "-padding", "padding", "Pad", NULL,
     Tk_Offset(Square,square.paddingObj), -1, 
     offsetof(Square,square.paddingObj), TCL_INDEX_NONE,
     TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },
    

    {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
     NULL, Tk_Offset(Square,square.reliefObj), -1, TK_OPTION_NULL_OK, 0, 0},
    
     NULL, offsetof(Square,square.reliefObj), TCL_INDEX_NONE, TK_OPTION_NULL_OK, 0, 0},

    {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",
     NULL, Tk_Offset(Square,square.anchorObj), -1, TK_OPTION_NULL_OK, 0, 0},
    
     NULL, offsetof(Square,square.anchorObj), TCL_INDEX_NONE, TK_OPTION_NULL_OK, 0, 0},

    WIDGET_TAKEFOCUS_TRUE,
    WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs)
};

/*
 * Almost all of the widget functionality is handled by the default Ttk
 * widget code and the contained element. The one thing that we must handle
105
106
107
108
109
110
111
112

113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133

134
135
136

137
138
139
140
141

142
143
144
145
146

147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162

163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179

180
181

182
183

184
185

186
187

188
189
190
191



192
193
194
195
196
197
198
199
200

201
202





203
204

205
206
207
208
209
210
211
212
213
214
215
216
217

218
219





220
221

222
223
224
225
226
227
228
229
230
231
232
233

234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251

252
253
254
255
256
257
258
259
260

261
262
263
264
265

266
267
268
269
270
271
272
105
106
107
108
109
110
111

112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131

132
133
134
135
136
137
138
139
140
141

142
143
144
145
146

147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162

163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179

180
181

182
183

184
185

186
187

188
189



190
191
192
193
194
195
196
197
198
199
200
201
202


203
204
205
206
207
208

209
210
211
212
213
214
215
216
217
218
219
220
221
222
223


224
225
226
227
228
229

230
231
232
233
234
235
236
237
238
239
240
241

242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259

260
261
262
263
264
265
266
267
268

269
270
271
272
273

274
275
276
277
278
279
280
281







-
+



















-

+



+




-
+




-
+















-
+
















-
+

-
+

-
+

-
+

-
+

-
-
-
+
+
+









+
-
-
+
+
+
+
+

-
+













+
-
-
+
+
+
+
+

-
+











-
+

















-
+








-
+




-
+








    /*
     * Adjust the position of the square element within the widget according
     * to the -anchor option.
     */

    if (squareNode) {
	Square *squarePtr = clientData;
	Square *squarePtr = (Square *)clientData;
	Tk_Anchor anchor = TK_ANCHOR_CENTER;
	Ttk_Box b;

	b = Ttk_ElementParcel(squareNode);
	if (squarePtr->square.anchorObj != NULL)
	    Tk_GetAnchorFromObj(NULL, squarePtr->square.anchorObj, &anchor);
	b = Ttk_AnchorBox(winBox, b.width, b.height, anchor);

	Ttk_PlaceElement(corePtr->layout, squareNode, b);
    }
}

/*
 * Widget commands. A widget is impelemented as an ensemble and the
 * 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 
 * The Widget specification structure holds all the implementation
 * information about this widget and this is what must be registered
 * with Tk in the package initialization code (see bottom).
 */

static WidgetSpec SquareWidgetSpec =
static const WidgetSpec SquareWidgetSpec =
{
    "TSquare",			/* className */
    sizeof(Square),		/* recordSize */
    SquareOptionSpecs,		/* optionSpecs */
    SquareCommands,		/* subcommands */
    TtkNullInitialize,		/* initializeProc */
    TtkNullCleanup,		/* cleanupProc */
    TtkCoreConfigure,		/* configureProc */
    TtkNullPostConfigure,		/* postConfigureProc */
    TtkWidgetGetLayout,		/* getLayoutProc */
    TtkWidgetSize, 		/* sizeProc */
    SquareDoLayout,		/* layoutProc */
    TtkWidgetDisplay		/* displayProc */
};

/* ---------------------------------------------------------------------- 
/* ----------------------------------------------------------------------
 * Square element
 *
 * In this section we demonstrate what is required to create a new themed
 * element.
 */

typedef struct
{
    Tcl_Obj *borderObj;
    Tcl_Obj *foregroundObj;
    Tcl_Obj *borderWidthObj;
    Tcl_Obj *reliefObj;
    Tcl_Obj *widthObj;
    Tcl_Obj *heightObj;
} SquareElement;

static Ttk_ElementOptionSpec SquareElementOptions[] = 
static const Ttk_ElementOptionSpec SquareElementOptions[] =
{
    { "-background", TK_OPTION_BORDER, Tk_Offset(SquareElement,borderObj),
    { "-background", TK_OPTION_BORDER, offsetof(SquareElement,borderObj),
    	DEFAULT_BACKGROUND },
    { "-foreground", TK_OPTION_BORDER, Tk_Offset(SquareElement,foregroundObj),
    { "-foreground", TK_OPTION_BORDER, offsetof(SquareElement,foregroundObj),
    	DEFAULT_BACKGROUND },
    { "-borderwidth", TK_OPTION_PIXELS, Tk_Offset(SquareElement,borderWidthObj),
    { "-borderwidth", TK_OPTION_PIXELS, offsetof(SquareElement,borderWidthObj),
    	DEFAULT_BORDERWIDTH },
    { "-relief", TK_OPTION_RELIEF, Tk_Offset(SquareElement,reliefObj),
    { "-relief", TK_OPTION_RELIEF, offsetof(SquareElement,reliefObj),
    	"raised" },
    { "-width",  TK_OPTION_PIXELS, Tk_Offset(SquareElement,widthObj), "20"},
    { "-height", TK_OPTION_PIXELS, Tk_Offset(SquareElement,heightObj), "20"},
    { NULL, 0, 0, NULL }
    { "-width",  TK_OPTION_PIXELS, offsetof(SquareElement,widthObj), "20"},
    { "-height", TK_OPTION_PIXELS, offsetof(SquareElement,heightObj), "20"},
    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
};

/*
 * The element geometry function is called when the layout code wishes to
 * find out how big this element wants to be. We must return our preferred
 * size and padding information
 */

static void SquareElementSize(
    TCL_UNUSED(void *),
    void *clientData, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
    void *elementRecord,
    Tk_Window tkwin,
    int *widthPtr,
    int *heightPtr,
    Ttk_Padding *paddingPtr)
{
    SquareElement *square = elementRecord;
    SquareElement *square = (SquareElement *)elementRecord;
    int borderWidth = 0;

    Tcl_GetIntFromObj(NULL, square->borderWidthObj, &borderWidth);
    *paddingPtr = Ttk_UniformPadding((short)borderWidth);
    Tk_GetPixelsFromObj(NULL, tkwin, square->widthObj, widthPtr);
    Tk_GetPixelsFromObj(NULL, tkwin, square->heightObj, heightPtr);
}

/*
 * Draw the element in the box provided.
 */

static void SquareElementDraw(
    TCL_UNUSED(void *),
    void *clientData, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
    void *elementRecord,
    Tk_Window tkwin,
    Drawable d,
    Ttk_Box b,
    TCL_UNUSED(unsigned int))
{
    SquareElement *square = elementRecord;
    SquareElement *square = (SquareElement *)elementRecord;
    Tk_3DBorder foreground = NULL;
    int borderWidth = 1, relief = TK_RELIEF_FLAT;

    foreground = Tk_Get3DBorderFromObj(tkwin, square->foregroundObj);
    Tcl_GetIntFromObj(NULL, square->borderWidthObj, &borderWidth);
    Tk_GetReliefFromObj(NULL, square->reliefObj, &relief);

    Tk_Fill3DRectangle(tkwin, d, foreground,
	b.x, b.y, b.width, b.height, borderWidth, relief);
}

static Ttk_ElementSpec SquareElementSpec =
static const Ttk_ElementSpec SquareElementSpec =
{
    TK_STYLE_VERSION_2,
    sizeof(SquareElement),
    SquareElementOptions,
    SquareElementSize,
    SquareElementDraw
};

/* ----------------------------------------------------------------------
 *
 * Layout section.
 *
 * Every widget class needs a layout style that specifies which elements
 * are part of the widget and how they should be placed. The element layout
 * engine is similar to the Tk pack geometry manager. Read the documentation
 * for the details. In this example we just need to have the square element
 * that has been defined for this widget placed on a background. We will
 * also need some padding to keep it away from the edges. 
 * also need some padding to keep it away from the edges.
 */

TTK_BEGIN_LAYOUT(SquareLayout)
     TTK_NODE("Square.background", TTK_FILL_BOTH)
     TTK_GROUP("Square.padding", TTK_FILL_BOTH,
	 TTK_NODE("Square.square", 0))
TTK_END_LAYOUT

/* ---------------------------------------------------------------------- 
/* ----------------------------------------------------------------------
 *
 * Widget initialization.
 *
 * This file defines a new element and a new widget. We need to register
 * the element with the themes that will need it. In this case we will 
 * the element with the themes that will need it. In this case we will
 * register with the default theme that is the root of the theme inheritance
 * tree. This means all themes will find this element.
 * We then need to register the widget class style. This is the layout
 * specification. If a different theme requires an alternative layout, we
 * could register that here. For instance, in some themes the scrollbars have
 * one uparrow, in other themes there are two uparrow elements.
 * Finally we register the widget itself. This step creates a tcl command so
283
284
285
286
287
288
289
290

291
292
293

294
295
296
297
298
299
300
301
292
293
294
295
296
297
298

299
300
301

302
303
304
305
306
307
308
309
310







-
+


-
+








/* public */ MODULE_SCOPE int
TtkSquareWidget_Init(Tcl_Interp *interp)
{
    Ttk_Theme theme = Ttk_GetDefaultTheme(interp);

    /* register the new elements for this theme engine */
    Ttk_RegisterElement(interp, theme, "square", &SquareElementSpec, NULL);
    

    /* register the layout for this theme */
    Ttk_RegisterLayout(theme, "TSquare", SquareLayout);
    

    /* register the widget */
    RegisterWidget(interp, "ttk::square", &SquareWidgetSpec);

    return TCL_OK;
}

#endif /* TTK_SQUARE_WIDGET */

Changes to generic/ttk/ttkState.c.
1
2
3
4

5
6
7
8
9
10

11
12
13
14
15
16
17
1
2
3

4
5
6
7



8
9
10
11
12
13
14
15



-
+



-
-
-
+







/*
 * Tk widget state utilities.
 *
 * Copyright (c) 2003 Joe English.  Freely redistributable.
 * Copyright © 2003 Joe English.  Freely redistributable.
 *
 */

#include <string.h>

#include <tk.h>
#include "tkInt.h"
#include "ttkTheme.h"

/*
 * Table of state names.  Must be kept in sync with TTK_STATE_*
 * #defines in ttkTheme.h.
 */
static const char *const stateNames[] =
143
144
145
146
147
148
149
150

151
152
153
154
155
156
157

158
159
160
161
162
163
164
141
142
143
144
145
146
147

148
149
150
151
152
153
154

155
156
157
158
159
160
161
162







-
+






-
+







	    Tcl_DStringAppend(&result, " ", 1);
	}
    }

    len = Tcl_DStringLength(&result);
    if (len) {
	/* 'len' includes extra trailing ' ' */
	objPtr->bytes = ckalloc(len);
	objPtr->bytes = (char *)ckalloc(len);
	objPtr->length = len-1;
	strncpy(objPtr->bytes, Tcl_DStringValue(&result), len-1);
	objPtr->bytes[len-1] = '\0';
    } else {
	/* empty string */
	objPtr->length = 0;
	objPtr->bytes = ckalloc(1);
	objPtr->bytes = (char *)ckalloc(1);
	*objPtr->bytes = '\0';
    }

    Tcl_DStringFree(&result);
}

Tcl_Obj *Ttk_NewStateSpecObj(unsigned int onbits, unsigned int offbits)
259
260
261
262
263
264
265
266

267
268
269
270
271
272
273
274
275
276
257
258
259
260
261
262
263

264
265
266
267
268
269
270
271
272
273
274







-
+










    return mapObj;
}

/*
 * Ttk_StateTableLooup --
 * 	Look up an index from a statically allocated state table.
 */
int Ttk_StateTableLookup(Ttk_StateTable *map, unsigned int state)
int Ttk_StateTableLookup(const Ttk_StateTable *map, unsigned int state)
{
    while ((state & map->onBits) != map->onBits
	    || (~state & map->offBits) != map->offBits)
    {
	++map;
    }
    return map->index;
}

/*EOF*/
Changes to generic/ttk/ttkStubInit.c.
1
2
3
4
5
6

7
8
9
10












11
12
13
14
15
16
17
1
2
3
4
5

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29





-
+




+
+
+
+
+
+
+
+
+
+
+
+







/*
 * This file is (mostly) automatically generated from ttk.decls.
 * It is compiled and linked in with the ttk package proper.
 */

#include "tk.h"
#include "tkInt.h"
#include "ttkTheme.h"

MODULE_SCOPE const TtkStubs ttkStubs;

#if defined(TK_NO_DEPRECATED) || TCL_MAJOR_VERSION > 8
#define Ttk_GetOrientFromObj 0
#endif

#ifdef __GNUC__
/*
 * The rest of this file shouldn't warn about deprecated functions; they're
 * there because we intend them to be so and know that this file is OK to
 * touch those fields.
 */
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
/* !BEGIN!: Do not edit below this line. */

const TtkStubs ttkStubs = {
    TCL_STUB_MAGIC,
    TTK_STUBS_EPOCH,
    TTK_STUBS_REVISION,
    0,
Changes to generic/ttk/ttkStubLib.c.
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
16








-
+







/*
 * We need to ensure that we use the tcl stub macros so that this file
 * contains no references to any of the tcl stub functions.
 */

#undef USE_TCL_STUBS
#define USE_TCL_STUBS

#include "tk.h"
#include "tkInt.h"

#define USE_TTK_STUBS 1
#include "ttkTheme.h"

MODULE_SCOPE const TtkStubs *ttkStubsPtr;
const TtkStubs *ttkStubsPtr = NULL;

30
31
32
33
34
35
36
37

38
39

40
41
42

43
44




45
46
47





48
49
50
51
52
53
54
30
31
32
33
34
35
36

37
38

39
40
41

42
43
44
45
46
47
48



49
50
51
52
53
54
55
56
57
58
59
60







-
+

-
+


-
+


+
+
+
+
-
-
-
+
+
+
+
+







 *
 */
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;
    ClientData pkgClientData = NULL;
    void *pkgClientData = NULL;
    const char *actualVersion = Tcl_PkgRequireEx(
	interp, packageName, version, exact, &pkgClientData);
    const TtkStubs *stubsPtr = pkgClientData;
    const TtkStubs *stubsPtr;

    if (!actualVersion) {
	packageName = "Ttk";
	actualVersion = Tcl_PkgRequireEx(
		interp, packageName, version, exact, &pkgClientData);
	if (!actualVersion) {
	return NULL;
    }

	    return NULL;
	}
    }

    stubsPtr = (const TtkStubs *)pkgClientData;
    if (!stubsPtr) {
	errMsg = "missing stub table pointer";
	goto error;
    }
    if (stubsPtr->epoch != epoch) {
	errMsg = "epoch number mismatch";
	goto error;
63
64
65
66
67
68
69
70

71
72
73
74
69
70
71
72
73
74
75

76
77
78
79
80







-
+





error:
    Tcl_ResetResult(interp);
    Tcl_AppendResult(interp,
	"Error loading ", packageName, " package",
	" (requested version '", version,
	"', loaded version '", actualVersion, "'): ",
	errMsg, 
	errMsg,
	NULL);
    return NULL;
}

Changes to generic/ttk/ttkTagSet.c.
1
2
3
4

5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

26
27
28
29
30
31
32
33
34
35
36
37

38
39
40
41
42
43
44
1
2
3

4
5
6



7

8
9
10
11
12
13
14
15
16
17
18
19
20
21

22
23
24
25
26
27
28
29
30
31
32
33

34
35
36
37
38
39
40
41



-
+


-
-
-
+
-














-
+











-
+







/*
 * Tag tables.  3/4-baked, work in progress.
 *
 * Copyright (C) 2005, Joe English.  Freely redistributable.
 * Copyright © 2005, Joe English.  Freely redistributable.
 */

#include <string.h>	/* for memset() */
#include <tcl.h>
#include <tk.h>
#include "tkInt.h"

#include "ttkTheme.h"
#include "ttkWidget.h"

/*------------------------------------------------------------------------
 * +++ Internal data structures.
 */
struct TtkTag {
    int 	priority;		/* 1=>highest */
    const char	*tagName;		/* Back-pointer to hash table entry */
    void	*tagRecord;		/* User data */
};

struct TtkTagTable {
    Tk_Window		tkwin;		/* owner window */
    Tk_OptionSpec	*optionSpecs;	/* ... */
    const Tk_OptionSpec	*optionSpecs;	/* ... */
    Tk_OptionTable	optionTable;	/* ... */
    int         	recordSize;	/* size of tag record */
    int 		nTags;		/* #tags defined so far */
    Tcl_HashTable	tags;		/* defined tags */
};

/*------------------------------------------------------------------------
 * +++ Tags.
 */
static Ttk_Tag NewTag(Ttk_TagTable tagTable, const char *tagName)
{
    Ttk_Tag tag = ckalloc(sizeof(*tag));
    Ttk_Tag tag = (Ttk_Tag)ckalloc(sizeof(*tag));
    tag->tagRecord = ckalloc(tagTable->recordSize);
    memset(tag->tagRecord, 0, tagTable->recordSize);
    /* Don't need Tk_InitOptions() here, all defaults should be NULL. */
    tag->priority = ++tagTable->nTags;
    tag->tagName = tagName;
    return tag;
}
52
53
54
55
56
57
58
59

60
61

62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78

79
80
81
82
83
84











85
86
87
88
89
90
91
92
93

94
95
96

97
98
99
100
101
102
103
49
50
51
52
53
54
55

56
57

58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74

75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100

101
102
103

104
105
106
107
108
109
110
111







-
+

-
+
















-
+






+
+
+
+
+
+
+
+
+
+
+








-
+


-
+








/*------------------------------------------------------------------------
 * +++ Tag tables.
 */

Ttk_TagTable Ttk_CreateTagTable(
    Tcl_Interp *interp, Tk_Window tkwin,
    Tk_OptionSpec optionSpecs[], int recordSize)
    const Tk_OptionSpec *optionSpecs, int recordSize)
{
    Ttk_TagTable tagTable = ckalloc(sizeof(*tagTable));
    Ttk_TagTable tagTable = (Ttk_TagTable)ckalloc(sizeof(*tagTable));
    tagTable->tkwin = tkwin;
    tagTable->optionSpecs = optionSpecs;
    tagTable->optionTable = Tk_CreateOptionTable(interp, optionSpecs);
    tagTable->recordSize = recordSize;
    tagTable->nTags = 0;
    Tcl_InitHashTable(&tagTable->tags, TCL_STRING_KEYS);
    return tagTable;
}

void Ttk_DeleteTagTable(Ttk_TagTable tagTable)
{
    Tcl_HashSearch search;
    Tcl_HashEntry *entryPtr;

    entryPtr = Tcl_FirstHashEntry(&tagTable->tags, &search);
    while (entryPtr != NULL) {
	DeleteTag(tagTable, Tcl_GetHashValue(entryPtr));
	DeleteTag(tagTable, (Ttk_Tag)Tcl_GetHashValue(entryPtr));
	entryPtr = Tcl_NextHashEntry(&search);
    }

    Tcl_DeleteHashTable(&tagTable->tags);
    ckfree(tagTable);
}

void Ttk_DeleteTagFromTable(Ttk_TagTable tagTable, Ttk_Tag tag)
{
    Tcl_HashEntry *entryPtr;

    entryPtr = Tcl_FindHashEntry(&tagTable->tags, tag->tagName);
    if (entryPtr != NULL) {
        DeleteTag(tagTable, tag);
        Tcl_DeleteHashEntry(entryPtr);
    }
}

Ttk_Tag Ttk_GetTag(Ttk_TagTable tagTable, const char *tagName)
{
    int isNew = 0;
    Tcl_HashEntry *entryPtr = Tcl_CreateHashEntry(
	&tagTable->tags, tagName, &isNew);

    if (isNew) {
	tagName = Tcl_GetHashKey(&tagTable->tags, entryPtr);
	tagName = (char *)Tcl_GetHashKey(&tagTable->tags, entryPtr);
	Tcl_SetHashValue(entryPtr, NewTag(tagTable,tagName));
    }
    return Tcl_GetHashValue(entryPtr);
    return (Ttk_Tag)Tcl_GetHashValue(entryPtr);
}

Ttk_Tag Ttk_GetTagFromObj(Ttk_TagTable tagTable, Tcl_Obj *objPtr)
{
    return Ttk_GetTag(tagTable, Tcl_GetString(objPtr));
}

112
113
114
115
116
117
118
119

120
121
122
123
124
125
126
127
128
129
130
131
132
133
134

135
136
137
138
139
140
141
120
121
122
123
124
125
126

127
128
129
130
131
132
133
134
135
136
137
138
139
140
141

142
143
144
145
146
147
148
149







-
+














-
+







 * Returns NULL and leaves an error message in interp->result on error.
 *
 * Non-NULL results must be passed to Ttk_FreeTagSet().
 */
Ttk_TagSet Ttk_GetTagSetFromObj(
    Tcl_Interp *interp, Ttk_TagTable tagTable, Tcl_Obj *objPtr)
{
    Ttk_TagSet tagset = ckalloc(sizeof(*tagset));
    Ttk_TagSet tagset = (Ttk_TagSet)ckalloc(sizeof(*tagset));
    Tcl_Obj **objv;
    int i, objc;

    if (objPtr == NULL) {
	tagset->tags = NULL;
	tagset->nTags = 0;
	return tagset;
    }

    if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) {
	ckfree(tagset);
    	return NULL;
    }

    tagset->tags = ckalloc((objc+1) * sizeof(Ttk_Tag));
    tagset->tags = (Ttk_Tag *)ckalloc((objc+1) * sizeof(Ttk_Tag));
    for (i=0; i<objc; ++i) {
	tagset->tags[i] = Ttk_GetTagFromObj(tagTable, objv[i]);
    }
    tagset->tags[i] = NULL;
    tagset->nTags = objc;

    return tagset;
184
185
186
187
188
189
190
191

192
193
194
195
196
197
198
192
193
194
195
196
197
198

199
200
201
202
203
204
205
206







-
+







{
    int i;
    for (i = 0; i < tagset->nTags; ++i) {
	if (tagset->tags[i] == tag) {
	    return 0;
	}
    }
    tagset->tags = ckrealloc(tagset->tags, 
    tagset->tags = (Ttk_Tag *)ckrealloc(tagset->tags,
	    (tagset->nTags+1)*sizeof(tagset->tags[0]));
    tagset->tags[tagset->nTags++] = tag;
    return 1;
}

/* Ttk_TagSetRemove -- remove a tag from a tag set.
 *
268
269
270
271
272
273
274
275
276


277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292

293
294
295

296
297
298
299
300
301
302
303
304
305
306
276
277
278
279
280
281
282


283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299

300
301
302

303
304
305
306
307
308
309
310
311
312
313
314







-
-
+
+















-
+


-
+











{
    const int LOWEST_PRIORITY = 0x7FFFFFFF;
    int i, j;

    memset(record, 0, tagTable->recordSize);

    for (i = 0; tagTable->optionSpecs[i].type != TK_OPTION_END; ++i) {
	Tk_OptionSpec *optionSpec = tagTable->optionSpecs + i;
	int offset = optionSpec->objOffset;
	const Tk_OptionSpec *optionSpec = tagTable->optionSpecs + i;
	TkSizeT offset = optionSpec->objOffset;
	int prio = LOWEST_PRIORITY;

	for (j = 0; j < tagSet->nTags; ++j) {
	    Ttk_Tag tag = tagSet->tags[j];
	    if (OBJ_AT(tag->tagRecord, offset) != 0 && tag->priority < prio) {
		OBJ_AT(record, offset) = OBJ_AT(tag->tagRecord, offset);
		prio = tag->priority;
	    }
	}
    }
}

void Ttk_TagSetApplyStyle(
    Ttk_TagTable tagTable, Ttk_Style style, Ttk_State state, void *record)
{
    Tk_OptionSpec *optionSpec = tagTable->optionSpecs;
    const Tk_OptionSpec *optionSpec = tagTable->optionSpecs;

    while (optionSpec->type != TK_OPTION_END) {
	int offset = optionSpec->objOffset;
	TkSizeT offset = optionSpec->objOffset;
	const char *optionName = optionSpec->optionName;
	Tcl_Obj *val = Ttk_StyleMap(style, optionName, state);
	if (val) {
	    OBJ_AT(record, offset) = val;
	} else if (OBJ_AT(record, offset) == 0) {
	    OBJ_AT(record, offset) = Ttk_StyleDefault(style, optionName);
	}
	++optionSpec;
    }
}

Changes to generic/ttk/ttkTheme.c.
1
2
3
4
5
6
7


8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

46
47

48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

67
68
69
70
71
72
73
74

75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95

96
97
98
99
100
101
102
103
104
105

106
107
108
109
110
111
112
113

114
115
116
117
118
119
120
121
122
123
124
125
126
127

128
129
130
131
132
133
134
1
2
3
4
5


6
7
8
9
10
11
12
13
14
15
16
17







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

38
39

40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58

59
60
61
62
63
64
65
66

67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

88
89
90
91
92
93
94
95
96
97

98
99
100
101
102
103
104
105

106
107
108
109
110
111
112
113
114
115
116
117
118
119

120
121
122
123
124
125
126
127





-
-
+
+










-
-
-
-
-
-
-




















-
+

-
+


















-
+







-
+




















-
+









-
+







-
+













-
+







/*
 * 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.
 */

#include "tkInt.h"
#include "ttkThemeInt.h"

#define PKG_ASSOC_KEY "Ttk"

#ifdef MAC_OSX_TK
    extern void TkMacOSXFlushWindows(void);
    #define UPDATE_WINDOWS() TkMacOSXFlushWindows()
#else
    #define UPDATE_WINDOWS()
#endif

/*------------------------------------------------------------------------
 * +++ Styles.
 *
 * Invariants:
 * 	If styleName contains a dot, parentStyle->styleName is everything
 * 	after the first dot; otherwise, parentStyle is the theme's root
 * 	style ".".  The root style's parentStyle is NULL.
 *
 */

typedef struct Ttk_Style_
{
    const char		*styleName;	/* points to hash table key */
    Tcl_HashTable	settingsTable;	/* KEY: string; VALUE: StateMap */
    Tcl_HashTable	defaultsTable;	/* KEY: string; VALUE: resource */
    Ttk_LayoutTemplate	layoutTemplate;	/* Layout template for style, or NULL */
    Ttk_Style		parentStyle;	/* Previous style in chain */
    Ttk_ResourceCache	cache;		/* Back-pointer to resource cache */
} Style;

static Style *NewStyle()
static Style *NewStyle(void)
{
    Style *stylePtr = ckalloc(sizeof(Style));
    Style *stylePtr = (Style *)ckalloc(sizeof(Style));

    stylePtr->styleName = NULL;
    stylePtr->parentStyle = NULL;
    stylePtr->layoutTemplate = NULL;
    stylePtr->cache = NULL;
    Tcl_InitHashTable(&stylePtr->settingsTable, TCL_STRING_KEYS);
    Tcl_InitHashTable(&stylePtr->defaultsTable, TCL_STRING_KEYS);

    return stylePtr;
}

static void FreeStyle(Style *stylePtr)
{
    Tcl_HashSearch search;
    Tcl_HashEntry *entryPtr;

    entryPtr = Tcl_FirstHashEntry(&stylePtr->settingsTable, &search);
    while (entryPtr != NULL) {
	Ttk_StateMap stateMap = Tcl_GetHashValue(entryPtr);
	Ttk_StateMap stateMap = (Ttk_StateMap)Tcl_GetHashValue(entryPtr);
	Tcl_DecrRefCount(stateMap);
	entryPtr = Tcl_NextHashEntry(&search);
    }
    Tcl_DeleteHashTable(&stylePtr->settingsTable);

    entryPtr = Tcl_FirstHashEntry(&stylePtr->defaultsTable, &search);
    while (entryPtr != NULL) {
	Tcl_Obj *defaultValue = Tcl_GetHashValue(entryPtr);
	Tcl_Obj *defaultValue = (Tcl_Obj *)Tcl_GetHashValue(entryPtr);
	Tcl_DecrRefCount(defaultValue);
	entryPtr = Tcl_NextHashEntry(&search);
    }
    Tcl_DeleteHashTable(&stylePtr->defaultsTable);

    Ttk_FreeLayoutTemplate(stylePtr->layoutTemplate);

    ckfree(stylePtr);
}

/*
 * Ttk_StyleMap --
 * 	Look up state-specific option value from specified style.
 */
Tcl_Obj *Ttk_StyleMap(Ttk_Style style, const char *optionName, Ttk_State state)
{
    while (style) {
	Tcl_HashEntry *entryPtr =
	    Tcl_FindHashEntry(&style->settingsTable, optionName);
	if (entryPtr) {
	    Ttk_StateMap stateMap = Tcl_GetHashValue(entryPtr);
	    Ttk_StateMap stateMap = (Ttk_StateMap)Tcl_GetHashValue(entryPtr);
	    return Ttk_StateMapLookup(NULL, stateMap, state);
	}
	style = style->parentStyle;
    }
    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 =
	    Tcl_FindHashEntry(&style->defaultsTable, optionName);
	if (entryPtr)
	    return Tcl_GetHashValue(entryPtr);
	    return (Tcl_Obj *)Tcl_GetHashValue(entryPtr);
	style= style->parentStyle;
    }
    return 0;
}

/*------------------------------------------------------------------------
 * +++ Elements.
 */
typedef const Tk_OptionSpec **OptionMap;
    /* array of Tk_OptionSpecs mapping widget options to element options */

struct Ttk_ElementClass_ {
    const char *name;		/* Points to hash table key */
    Ttk_ElementSpec *specPtr;	/* Template provided during registration. */
    const Ttk_ElementSpec *specPtr;	/* Template provided during registration. */
    void *clientData;		/* Client data passed in at registration time */
    void *elementRecord;	/* Scratch buffer for element record storage */
    int nResources;		/* #Element options */
    Tcl_Obj **defaultValues;	/* Array of option default values */
    Tcl_HashTable optMapCache;	/* Map: Tk_OptionTable * -> OptionMap */
};

145
146
147
148
149
150
151
152

153
154
155
156
157
158
159
138
139
140
141
142
143
144

145
146
147
148
149
150
151
152







-
+







    const Tk_OptionSpec *optionSpec = TkGetOptionSpec(optionName, optionTable);

    if (!optionSpec)
	return 0;

    /* Make sure widget option has a Tcl_Obj* entry:
     */
    if (optionSpec->objOffset < 0) {
    if (optionSpec->objOffset == TCL_INDEX_NONE) {
	return 0;
    }

    /* Grrr.  Ignore accidental mismatches caused by prefix-matching:
     */
    if (strcmp(optionSpec->optionName, optionName)) {
	return 0;
179
180
181
182
183
184
185
186

187
188
189
190
191

192
193
194
195
196
197
198
172
173
174
175
176
177
178

179
180
181
182
183

184
185
186
187
188
189
190
191







-
+




-
+








/* BuildOptionMap --
 * 	Construct the mapping from element options to widget options.
 */
static OptionMap
BuildOptionMap(Ttk_ElementClass *elementClass, Tk_OptionTable optionTable)
{
    OptionMap optionMap = ckalloc(
    OptionMap optionMap = (OptionMap)ckalloc(
	    sizeof(const Tk_OptionSpec) * elementClass->nResources + 1);
    int i;

    for (i = 0; i < elementClass->nResources; ++i) {
	Ttk_ElementOptionSpec *e = elementClass->specPtr->options+i;
	const Ttk_ElementOptionSpec *e = elementClass->specPtr->options+i;
	optionMap[i] = TTKGetOptionSpec(e->optionName, optionTable, e->type);
    }

    return optionMap;
}

/* GetOptionMap --
207
208
209
210
211
212
213
214

215
216
217
218
219
220
221
222
223
224
225
226

227
228

229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244

245
246
247
248
249
250
251
200
201
202
203
204
205
206

207
208
209
210
211
212
213
214
215
216
217
218

219
220

221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236

237
238
239
240
241
242
243
244







-
+











-
+

-
+















-
+







    Tcl_HashEntry *entryPtr = Tcl_CreateHashEntry(
	&elementClass->optMapCache, (void*)optionTable, &isNew);

    if (isNew) {
	optionMap = BuildOptionMap(elementClass, optionTable);
	Tcl_SetHashValue(entryPtr, optionMap);
    } else {
	optionMap = Tcl_GetHashValue(entryPtr);
	optionMap = (OptionMap)Tcl_GetHashValue(entryPtr);
    }

    return optionMap;
}

/*
 * NewElementClass --
 * 	Allocate and initialize an element class record
 * 	from the specified element specification.
 */
static Ttk_ElementClass *
NewElementClass(const char *name, Ttk_ElementSpec *specPtr,void *clientData)
NewElementClass(const char *name, const Ttk_ElementSpec *specPtr, void *clientData)
{
    Ttk_ElementClass *elementClass = ckalloc(sizeof(Ttk_ElementClass));
    Ttk_ElementClass *elementClass = (Ttk_ElementClass *)ckalloc(sizeof(Ttk_ElementClass));
    int i;

    elementClass->name = name;
    elementClass->specPtr = specPtr;
    elementClass->clientData = clientData;
    elementClass->elementRecord = ckalloc(specPtr->elementSize);

    /* Count #element resources:
     */
    for (i = 0; specPtr->options[i].optionName != 0; ++i)
	continue;
    elementClass->nResources = i;

    /* Initialize default values:
     */
    elementClass->defaultValues =
    elementClass->defaultValues = (Tcl_Obj **)
	ckalloc(elementClass->nResources * sizeof(Tcl_Obj *) + 1);
    for (i=0; i < elementClass->nResources; ++i) {
        const char *defaultValue = specPtr->options[i].defaultValue;
	if (defaultValue) {
	    elementClass->defaultValues[i] = Tcl_NewStringObj(defaultValue,-1);
	    Tcl_IncrRefCount(elementClass->defaultValues[i]);
	} else {
294
295
296
297
298
299
300
301




302


303
304
305
306
307
308
309
310
311
312
313
314
315
316
317

318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334

335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351

352
353
354
355
356
357
358
359
360
361
362

363
364
365
366
367
368
369
287
288
289
290
291
292
293

294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314

315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331

332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348

349
350
351
352
353
354
355
356
357
358
359

360
361
362
363
364
365
366
367







-
+
+
+
+

+
+














-
+
















-
+
















-
+










-
+







    ckfree(elementClass);
}

/*------------------------------------------------------------------------
 * +++ Themes.
 */

static int ThemeEnabled(Ttk_Theme theme, void *clientData) { return 1; }
static int ThemeEnabled(
    TCL_UNUSED(Ttk_Theme),
    TCL_UNUSED(void *))
{
    /* Default ThemeEnabledProc -- always return true */
    return 1;
}

typedef struct Ttk_Theme_
{
    Ttk_Theme parentPtr;             	/* Parent theme. */
    Tcl_HashTable elementTable;	     	/* Map element names to class records */
    Tcl_HashTable styleTable;	     	/* Map style names to Styles */
    Ttk_Style rootStyle;		/* "." style, root of chain */
    Ttk_ThemeEnabledProc *enabledProc;	/* Function called by SetTheme */
    void *enabledData;              	/* ClientData for enabledProc */
    Ttk_ResourceCache cache;		/* Back-pointer to resource cache */
} Theme;

static Theme *NewTheme(Ttk_ResourceCache cache, Ttk_Theme parent)
{
    Theme *themePtr = ckalloc(sizeof(Theme));
    Theme *themePtr = (Theme *)ckalloc(sizeof(Theme));
    Tcl_HashEntry *entryPtr;
    int unused;

    themePtr->parentPtr = parent;
    themePtr->enabledProc = ThemeEnabled;
    themePtr->enabledData = NULL;
    themePtr->cache = cache;
    Tcl_InitHashTable(&themePtr->elementTable, TCL_STRING_KEYS);
    Tcl_InitHashTable(&themePtr->styleTable, TCL_STRING_KEYS);

    /*
     * Create root style "."
     */
    entryPtr = Tcl_CreateHashEntry(&themePtr->styleTable, ".", &unused);
    themePtr->rootStyle = NewStyle();
    themePtr->rootStyle->styleName =
	Tcl_GetHashKey(&themePtr->styleTable, entryPtr);
	(const char *)Tcl_GetHashKey(&themePtr->styleTable, entryPtr);
    themePtr->rootStyle->cache = themePtr->cache;
    Tcl_SetHashValue(entryPtr, themePtr->rootStyle);

    return themePtr;
}

static void FreeTheme(Theme *themePtr)
{
    Tcl_HashSearch search;
    Tcl_HashEntry *entryPtr;

    /*
     * Free element table:
     */
    entryPtr = Tcl_FirstHashEntry(&themePtr->elementTable, &search);
    while (entryPtr != NULL) {
	Ttk_ElementClass *elementClass = Tcl_GetHashValue(entryPtr);
	Ttk_ElementClass *elementClass = (Ttk_ElementClass *)Tcl_GetHashValue(entryPtr);
	FreeElementClass(elementClass);
	entryPtr = Tcl_NextHashEntry(&search);
    }
    Tcl_DeleteHashTable(&themePtr->elementTable);

    /*
     * Free style table:
     */
    entryPtr = Tcl_FirstHashEntry(&themePtr->styleTable, &search);
    while (entryPtr != NULL) {
	Style *stylePtr = Tcl_GetHashValue(entryPtr);
	Style *stylePtr = (Style *)Tcl_GetHashValue(entryPtr);
	FreeStyle(stylePtr);
	entryPtr = Tcl_NextHashEntry(&search);
    }
    Tcl_DeleteHashTable(&themePtr->styleTable);

    /*
     * Free theme record:
387
388
389
390
391
392
393
394

395
396
397
398
399
400
401
402
403
404
405
406
407
408

409
410
411
412
413



414
415

416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432

433
434
435
436
437
438
439
385
386
387
388
389
390
391

392
393
394
395
396
397
398
399
400
401
402
403
404
405

406
407
408
409
410

411
412
413
414

415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431

432
433
434
435
436
437
438
439







-
+













-
+




-
+
+
+

-
+
















-
+







typedef struct CleanupStruct {
    void *clientData;
    Ttk_CleanupProc *cleanupProc;
    struct CleanupStruct *next;
} Cleanup;

/*------------------------------------------------------------------------
 * +++ Master style package data structure.
 * +++ Style package data structure.
 */
typedef struct
{
    Tcl_Interp *interp;			/* Owner interp */
    Tcl_HashTable themeTable;		/* KEY: name; VALUE: Theme pointer */
    Tcl_HashTable factoryTable; 	/* KEY: name; VALUE: FactoryRec ptr */
    Theme *defaultTheme;		/* Default theme; global fallback*/
    Theme *currentTheme;		/* Currently-selected theme */
    Cleanup *cleanupList;		/* Cleanup records */
    Ttk_ResourceCache cache;		/* Resource cache */
    int themeChangePending;		/* scheduled ThemeChangedProc call? */
} StylePackageData;

static void ThemeChangedProc(ClientData);	/* Forward */
static void ThemeChangedProc(void *);	/* Forward */

/* Ttk_StylePkgFree --
 *	Cleanup procedure for StylePackageData.
 */
static void Ttk_StylePkgFree(ClientData clientData, Tcl_Interp *interp)
static void Ttk_StylePkgFree(
    ClientData clientData,
    TCL_UNUSED(Tcl_Interp *))
{
    StylePackageData *pkgPtr = clientData;
    StylePackageData *pkgPtr = (StylePackageData *)clientData;
    Tcl_HashSearch search;
    Tcl_HashEntry *entryPtr;
    Cleanup *cleanup;

    /*
     * Cancel any pending ThemeChanged calls:
     */
    if (pkgPtr->themeChangePending) {
	Tcl_CancelIdleCall(ThemeChangedProc, pkgPtr);
    }

    /*
     * Free themes.
     */
    entryPtr = Tcl_FirstHashEntry(&pkgPtr->themeTable, &search);
    while (entryPtr != NULL) {
	Theme *themePtr = Tcl_GetHashValue(entryPtr);
	Theme *themePtr = (Theme *)Tcl_GetHashValue(entryPtr);
	FreeTheme(themePtr);
	entryPtr = Tcl_NextHashEntry(&search);
    }
    Tcl_DeleteHashTable(&pkgPtr->themeTable);

    /*
     * Free element constructor table:
467
468
469
470
471
472
473
474

475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490


491
492
493
494
495
496
497
467
468
469
470
471
472
473

474
475
476
477
478
479
480
481
482
483
484
485
486
487
488


489
490
491
492
493
494
495
496
497







-
+














-
-
+
+







/*
 * GetStylePackageData --
 * 	Look up the package data registered with the interp.
 */

static StylePackageData *GetStylePackageData(Tcl_Interp *interp)
{
    return Tcl_GetAssocData(interp, PKG_ASSOC_KEY, NULL);
    return (StylePackageData *)Tcl_GetAssocData(interp, PKG_ASSOC_KEY, NULL);
}

/*
 * Ttk_RegisterCleanup --
 *
 *	Register a function to be called when a theme engine is deleted.
 *	(This only happens when the main interp is destroyed). The cleanup
 *	function is called with the current Tcl interpreter and the client
 *	data provided here.
 *
 */
void Ttk_RegisterCleanup(
    Tcl_Interp *interp, ClientData clientData, Ttk_CleanupProc *cleanupProc)
{
    StylePackageData *pkgPtr = GetStylePackageData(interp);
    Cleanup *cleanup = ckalloc(sizeof(*cleanup));
    StylePackageData *pkgPtr = (StylePackageData *)GetStylePackageData(interp);
    Cleanup *cleanup = (Cleanup *)ckalloc(sizeof(*cleanup));

    cleanup->clientData = clientData;
    cleanup->cleanupProc = cleanupProc;
    cleanup->next = pkgPtr->cleanupList;
    pkgPtr->cleanupList = cleanup;
}

506
507
508
509
510
511
512
513

514
515
516
517
518
519
520
521
522
523
524
525
526
527
506
507
508
509
510
511
512

513
514
515
516
517
518
519

520
521
522
523
524
525
526







-
+






-







 * 	The Tk C API doesn't doesn't provide an easy way to traverse
 * 	the widget hierarchy, so this is done by evaluating a Tcl script.
 */

static void ThemeChangedProc(ClientData clientData)
{
    static char ThemeChangedScript[] = "ttk::ThemeChanged";
    StylePackageData *pkgPtr = clientData;
    StylePackageData *pkgPtr = (StylePackageData *)clientData;

    int code = Tcl_EvalEx(pkgPtr->interp, ThemeChangedScript, -1, TCL_EVAL_GLOBAL);
    if (code != TCL_OK) {
	Tcl_BackgroundException(pkgPtr->interp, code);
    }
    pkgPtr->themeChangePending = 0;
    UPDATE_WINDOWS();
}

/*
 * ThemeChanged --
 * 	Schedule a call to ThemeChanged if one is not already pending.
 */
static void ThemeChanged(StylePackageData *pkgPtr)
587
588
589
590
591
592
593
594

595
596
597
598
599
600
601
602
603
604
605
606
607

608
609
610
611
612
613
614
586
587
588
589
590
591
592

593
594
595
596
597
598
599
600
601
602
603
604
605

606
607
608
609
610
611
612
613







-
+












-
+







 * LookupTheme --
 *	Retrieve a registered theme by name.  If not found,
 *	returns NULL and leaves an error message in interp's result.
 */

static Ttk_Theme LookupTheme(
    Tcl_Interp *interp,		/* where to leave error messages */
    StylePackageData *pkgPtr,	/* style package master record */
    StylePackageData *pkgPtr,	/* style package record */
    const char *name)		/* theme name */
{
    Tcl_HashEntry *entryPtr;

    entryPtr = Tcl_FindHashEntry(&pkgPtr->themeTable, name);
    if (!entryPtr) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"theme \"%s\" doesn't exist", name));
	Tcl_SetErrorCode(interp, "TTK", "LOOKUP", "THEME", name, NULL);
	return NULL;
    }

    return Tcl_GetHashValue(entryPtr);
    return (Ttk_Theme)Tcl_GetHashValue(entryPtr);
}

/*
 * Ttk_GetTheme --
 *	Public interface to LookupTheme.
 */
Ttk_Theme Ttk_GetTheme(Tcl_Interp *interp, const char *themeName)
708
709
710
711
712
713
714
715

716
717
718
719
720

721
722
723
724
725
726
727
707
708
709
710
711
712
713

714
715
716
717
718

719
720
721
722
723
724
725
726







-
+




-
+








	if (dot) {
	    stylePtr->parentStyle = Ttk_GetStyle(themePtr, dot + 1);
	} else {
	    stylePtr->parentStyle = themePtr->rootStyle;
	}

	stylePtr->styleName = Tcl_GetHashKey(&themePtr->styleTable, entryPtr);
	stylePtr->styleName = (const char *)Tcl_GetHashKey(&themePtr->styleTable, entryPtr);
	stylePtr->cache = stylePtr->parentStyle->cache;
	Tcl_SetHashValue(entryPtr, stylePtr);
	return stylePtr;
    }
    return Tcl_GetHashValue(entryPtr);
    return (Ttk_Style)Tcl_GetHashValue(entryPtr);
}

/* FindLayoutTemplate --
 * 	Locate a layout template in the layout table, checking
 * 	generic names to specific names first, then looking for
 * 	the full name in the parent theme.
 */
759
760
761
762
763
764
765
766

767
768
769
770
771
772
773
774
775
776
777

778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793

794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810

811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831

832
833
834
835
836
837
838
758
759
760
761
762
763
764

765
766
767
768
769
770
771
772
773
774
775

776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791

792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808

809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829

830
831
832
833
834
835
836
837







-
+










-
+















-
+
















-
+




















-
+







    const char *dot = elementName;

    /*
     * Check if element has already been registered:
     */
    entryPtr = Tcl_FindHashEntry(&themePtr->elementTable, elementName);
    if (entryPtr) {
	return Tcl_GetHashValue(entryPtr);
	return (Ttk_ElementClass *)Tcl_GetHashValue(entryPtr);
    }

    /*
     * Check generic names:
     */
    while (!entryPtr && ((dot = strchr(dot, '.')) != NULL)) {
	dot++;
	entryPtr = Tcl_FindHashEntry(&themePtr->elementTable, dot);
    }
    if (entryPtr) {
	return Tcl_GetHashValue(entryPtr);
	return (Ttk_ElementClass *)Tcl_GetHashValue(entryPtr);
    }

    /*
     * Check parent theme:
     */
    if (themePtr->parentPtr) {
	return Ttk_GetElement(themePtr->parentPtr, elementName);
    }

    /*
     * Not found, and this is the root theme; return null element, "".
     * (@@@ SHOULD: signal a background error)
     */
    entryPtr = Tcl_FindHashEntry(&themePtr->elementTable, "");
    /* ASSERT: entryPtr != 0 */
    return Tcl_GetHashValue(entryPtr);
    return (Ttk_ElementClass *)Tcl_GetHashValue(entryPtr);
}

const char *Ttk_ElementClassName(Ttk_ElementClass *elementClass)
{
    return elementClass->name;
}

/*
 * Ttk_RegisterElementFactory --
 *	Register a new element factory.
 */
int Ttk_RegisterElementFactory(
    Tcl_Interp *interp,	const char *name,
    Ttk_ElementFactory factory, void *clientData)
{
    StylePackageData *pkgPtr = GetStylePackageData(interp);
    FactoryRec *recPtr = ckalloc(sizeof(*recPtr));
    FactoryRec *recPtr = (FactoryRec *)ckalloc(sizeof(*recPtr));
    Tcl_HashEntry *entryPtr;
    int newEntry;

    recPtr->factory = factory;
    recPtr->clientData = clientData;

    entryPtr = Tcl_CreateHashEntry(&pkgPtr->factoryTable, name, &newEntry);
    if (!newEntry) {
    	/* Free old factory: */
	ckfree(Tcl_GetHashValue(entryPtr));
    }
    Tcl_SetHashValue(entryPtr, recPtr);

    return TCL_OK;
}

/* Ttk_CloneElement -- element factory procedure.
 * 	(style element create $name) "from" $theme ?$element?
 */
static int Ttk_CloneElement(
    Tcl_Interp *interp, void *clientData,
    Tcl_Interp *interp, TCL_UNUSED(void *),
    Ttk_Theme theme, const char *elementName,
    int objc, Tcl_Obj *const objv[])
{
    Ttk_Theme fromTheme;
    Ttk_ElementClass *fromElement;

    if (objc <= 0 || objc > 2) {
869
870
871
872
873
874
875
876

877
878
879
880
881
882
883
868
869
870
871
872
873
874

875
876
877
878
879
880
881
882







-
+







 *	if interp is non-NULL.
 */

Ttk_ElementClass *Ttk_RegisterElement(
    Tcl_Interp *interp,		/* Where to leave error messages */
    Ttk_Theme theme,		/* Style engine providing the implementation. */
    const char *name,		/* Name of new element */
    Ttk_ElementSpec *specPtr, 	/* Static template information */
    const Ttk_ElementSpec *specPtr, 	/* Static template information */
    void *clientData)		/* application-specific data */
{
    Ttk_ElementClass *elementClass;
    Tcl_HashEntry *entryPtr;
    int newEntry;

    if (specPtr->version != TK_STYLE_VERSION_2) {
899
900
901
902
903
904
905
906

907
908
909
910
911
912
913
914
915
916
917

918
919
920
921
922
923
924
898
899
900
901
902
903
904

905
906
907
908
909
910
911
912
913
914
915

916
917
918
919
920
921
922
923







-
+










-
+







	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"Duplicate element %s", name));
	    Tcl_SetErrorCode(interp, "TTK", "REGISTER_ELEMENT", "DUPE", NULL);
	}
	return 0;
    }

    name = Tcl_GetHashKey(&theme->elementTable, entryPtr);
    name = (char *)Tcl_GetHashKey(&theme->elementTable, entryPtr);
    elementClass = NewElementClass(name, specPtr, clientData);
    Tcl_SetHashValue(entryPtr, elementClass);

    return elementClass;
}

/* Ttk_RegisterElementSpec (deprecated) --
 * 	Register a new element.
 */
int Ttk_RegisterElementSpec(Ttk_Theme theme,
    const char *name, Ttk_ElementSpec *specPtr, void *clientData)
    const char *name, const Ttk_ElementSpec *specPtr, void *clientData)
{
    return Ttk_RegisterElement(NULL, theme, name, specPtr, clientData)
	   ? TCL_OK : TCL_ERROR;
}

/*------------------------------------------------------------------------
 * +++ Element record initialization.
974
975
976
977
978
979
980
981

982
983
984
985
986

987
988
989
990

991
992
993
994
995

996
997
998
999
1000
1001
1002
1003

1004
1005
1006
1007
1008
1009
1010
973
974
975
976
977
978
979

980
981
982
983
984

985
986
987
988

989
990
991
992
993

994
995
996
997
998
999
1000
1001

1002
1003
1004
1005
1006
1007
1008
1009







-
+




-
+



-
+




-
+







-
+







 * 	Tcl_Obj * reference counts are _NOT_ adjusted.
 */

static
int InitializeElementRecord(
    Ttk_ElementClass *eclass,	/* Element instance to initialize */
    Ttk_Style style,		/* Style table */
    char *widgetRecord,		/* Source of widget option values */
    void *widgetRecord,		/* Source of widget option values */
    Tk_OptionTable optionTable,	/* Option table describing widget record */
    Tk_Window tkwin,		/* Corresponding window */
    Ttk_State state)	/* Widget or element state */
{
    char *elementRecord = eclass->elementRecord;
    void *elementRecord = eclass->elementRecord;
    OptionMap optionMap = GetOptionMap(eclass,optionTable);
    int nResources = eclass->nResources;
    Ttk_ResourceCache cache = style->cache;
    Ttk_ElementOptionSpec *elementOption = eclass->specPtr->options;
    const Ttk_ElementOptionSpec *elementOption = eclass->specPtr->options;

    int i;
    for (i=0; i<nResources; ++i, ++elementOption) {
	Tcl_Obj **dest = (Tcl_Obj **)
	    (elementRecord + elementOption->offset);
	    ((char *)elementRecord + elementOption->offset);
	const char *optionName = elementOption->optionName;
	Tcl_Obj *dynamicSetting = Ttk_StyleMap(style, optionName, state);
	Tcl_Obj *widgetValue = 0;
	Tcl_Obj *elementDefault = eclass->defaultValues[i];

	if (optionMap[i]) {
	    widgetValue = *(Tcl_Obj **)
		(widgetRecord + optionMap[i]->objOffset);
		((char *)widgetRecord + optionMap[i]->objOffset);
	}

	if (widgetValue) {
	    *dest = widgetValue;
	} else if (dynamicSetting) {
	    *dest = dynamicSetting;
	} else {
1068
1069
1070
1071
1072
1073
1074
1075

1076
1077
1078
1079
1080
1081
1082
1067
1068
1069
1070
1071
1072
1073

1074
1075
1076
1077
1078
1079
1080
1081







-
+







 *	Compute the requested size of the given element.
 */

void
Ttk_ElementSize(
    Ttk_ElementClass *eclass,		/* Element to query */
    Ttk_Style style,			/* Style settings */
    char *recordPtr,			/* The widget record. */
    void *recordPtr,			/* The widget record. */
    Tk_OptionTable optionTable,		/* Description of widget record */
    Tk_Window tkwin,			/* The widget window. */
    Ttk_State state,			/* Current widget state */
    int *widthPtr, 			/* Requested width */
    int *heightPtr,			/* Reqested height */
    Ttk_Padding *paddingPtr)		/* Requested inner border */
{
1098
1099
1100
1101
1102
1103
1104
1105

1106
1107
1108
1109
1110
1111
1112
1097
1098
1099
1100
1101
1102
1103

1104
1105
1106
1107
1108
1109
1110
1111







-
+







 *	Draw the given widget element in a given drawable area.
 */

void
Ttk_DrawElement(
    Ttk_ElementClass *eclass,		/* Element instance */
    Ttk_Style style,			/* Style settings */
    char *recordPtr,			/* The widget record. */
    void *recordPtr,			/* The widget record. */
    Tk_OptionTable optionTable,		/* Description of option table */
    Tk_Window tkwin,			/* The widget window. */
    Drawable d,				/* Where to draw element. */
    Ttk_Box b,				/* Element area */
    Ttk_State state)			/* Widget or element state flags. */
{
    if (b.width <= 0 || b.height <= 0)
1138
1139
1140
1141
1142
1143
1144
1145

1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166


1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182

1183
1184
1185
1186
1187

1188
1189
1190
1191
1192
1193
1194
1137
1138
1139
1140
1141
1142
1143

1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163


1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180

1181
1182
1183
1184
1185

1186
1187
1188
1189
1190
1191
1192
1193







-
+



















-
-
+
+















-
+




-
+







int TtkEnumerateHashTable(Tcl_Interp *interp, Tcl_HashTable *ht)
{
    Tcl_HashSearch search;
    Tcl_Obj *result = Tcl_NewListObj(0, NULL);
    Tcl_HashEntry *entryPtr = Tcl_FirstHashEntry(ht, &search);

    while (entryPtr != NULL) {
	Tcl_Obj *nameObj = Tcl_NewStringObj(Tcl_GetHashKey(ht, entryPtr),-1);
	Tcl_Obj *nameObj = Tcl_NewStringObj((const char *)Tcl_GetHashKey(ht, entryPtr),-1);
	Tcl_ListObjAppendElement(interp, result, nameObj);
	entryPtr = Tcl_NextHashEntry(&search);
    }

    Tcl_SetObjResult(interp, result);
    return TCL_OK;
}

/* HashTableToDict --
 * 	Helper routine.  Converts a TCL_STRING_KEYS Tcl_HashTable
 * 	with Tcl_Obj * entries into a dictionary.
 */
static Tcl_Obj* HashTableToDict(Tcl_HashTable *ht)
{
    Tcl_HashSearch search;
    Tcl_Obj *result = Tcl_NewListObj(0, NULL);
    Tcl_HashEntry *entryPtr = Tcl_FirstHashEntry(ht, &search);

    while (entryPtr != NULL) {
	Tcl_Obj *nameObj = Tcl_NewStringObj(Tcl_GetHashKey(ht, entryPtr),-1);
	Tcl_Obj *valueObj = Tcl_GetHashValue(entryPtr);
	Tcl_Obj *nameObj = Tcl_NewStringObj((const char *)Tcl_GetHashKey(ht, entryPtr),-1);
	Tcl_Obj *valueObj = (Tcl_Obj *)Tcl_GetHashValue(entryPtr);
	Tcl_ListObjAppendElement(NULL, result, nameObj);
	Tcl_ListObjAppendElement(NULL, result, valueObj);
	entryPtr = Tcl_NextHashEntry(&search);
    }

    return result;
}

/* + style map $style ? -resource statemap ... ?
 *
 * 	Note that resource names are unconstrained; the Style
 * 	doesn't know what resources individual elements may use.
 */
static int
StyleMapCmd(
    ClientData clientData,		/* Master StylePackageData pointer */
    ClientData clientData,		/* StylePackageData pointer */
    Tcl_Interp *interp,			/* Current interpreter */
    int objc,				/* Number of arguments */
    Tcl_Obj *const objv[])		/* Argument objects */
{
    StylePackageData *pkgPtr = clientData;
    StylePackageData *pkgPtr = (StylePackageData *)clientData;
    Ttk_Theme theme = pkgPtr->currentTheme;
    const char *styleName;
    Style *stylePtr;
    int i;

    if (objc < 3) {
usage:
1244
1245
1246
1247
1248
1249
1250
1251

1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266

1267
1268
1269

1270
1271
1272
1273
1274
1275
1276
1243
1244
1245
1246
1247
1248
1249

1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264

1265
1266
1267

1268
1269
1270
1271
1272
1273
1274
1275







-
+














-
+


-
+







}

/* + style configure $style -option ?value...
 */
static int StyleConfigureCmd(
    ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    StylePackageData *pkgPtr = clientData;
    StylePackageData *pkgPtr = (StylePackageData *)clientData;
    Ttk_Theme theme = pkgPtr->currentTheme;
    const char *styleName;
    Style *stylePtr;
    int i;

    if (objc < 3) {
usage:
	Tcl_WrongNumArgs(interp,2,objv,"style ?-option ?value...??");
	return TCL_ERROR;
    }

    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));
	}
	return TCL_OK;
1299
1300
1301
1302
1303
1304
1305
1306

1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321

1322
1323
1324
1325
1326
1327
1328
1298
1299
1300
1301
1302
1303
1304

1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317



1318
1319
1320
1321
1322
1323
1324
1325







-
+












-
-
-
+







}

/* + style lookup $style -option ?statespec? ?defaultValue?
 */
static int StyleLookupCmd(
    ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    StylePackageData *pkgPtr = clientData;
    StylePackageData *pkgPtr = (StylePackageData *)clientData;
    Ttk_Theme theme = pkgPtr->currentTheme;
    Ttk_Style style = NULL;
    const char *optionName;
    Ttk_State state = 0ul;
    Tcl_Obj *result;

    if (objc < 4 || objc > 6) {
	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 */
	if (Ttk_GetStateSpecFromObj(interp, objv[4], &stateSpec) != TCL_OK) {
	    return TCL_ERROR;
1341
1342
1343
1344
1345
1346
1347
1348

1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360

1361
1362

1363
1364
1365
1366
1367
1368
1369
1338
1339
1340
1341
1342
1343
1344

1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356

1357
1358

1359
1360
1361
1362
1363
1364
1365
1366







-
+











-
+

-
+








    return TCL_OK;
}

static int StyleThemeCurrentCmd(
    ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj * const objv[])
{
    StylePackageData *pkgPtr = clientData;
    StylePackageData *pkgPtr = (StylePackageData *)clientData;
    Tcl_HashSearch search;
    Tcl_HashEntry *entryPtr = NULL;
    const char *name = NULL;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 3, objv, "");
	return TCL_ERROR;
    }

    entryPtr = Tcl_FirstHashEntry(&pkgPtr->themeTable, &search);
    while (entryPtr != NULL) {
	Theme *ptr = Tcl_GetHashValue(entryPtr);
	Theme *ptr = (Theme *)Tcl_GetHashValue(entryPtr);
	if (ptr == pkgPtr->currentTheme) {
	    name = Tcl_GetHashKey(&pkgPtr->themeTable, entryPtr);
	    name = (char *)Tcl_GetHashKey(&pkgPtr->themeTable, entryPtr);
	    break;
	}
	entryPtr = Tcl_NextHashEntry(&search);
    }

    if (name == NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
1377
1378
1379
1380
1381
1382
1383
1384
1385


1386
1387
1388
1389
1390
1391
1392
1374
1375
1376
1377
1378
1379
1380


1381
1382
1383
1384
1385
1386
1387
1388
1389







-
-
+
+







}

/* + style theme create name ?-parent $theme? ?-settings { script }?
 */
static int StyleThemeCreateCmd(
    ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    StylePackageData *pkgPtr = clientData;
    static const char *optStrings[] =
    StylePackageData *pkgPtr = (StylePackageData *)clientData;
    static const char *const optStrings[] =
    	 { "-parent", "-settings", NULL };
    enum { OP_PARENT, OP_SETTINGS };
    Ttk_Theme parentTheme = pkgPtr->defaultTheme, newTheme;
    Tcl_Obj *settingsScript = NULL;
    const char *themeName;
    int i;

1439
1440
1441
1442
1443
1444
1445
1446




1447
1448


1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459

1460
1461
1462
1463
1464

1465
1466
1467
1468
1469
1470
1471
1436
1437
1438
1439
1440
1441
1442

1443
1444
1445
1446
1447

1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459

1460
1461
1462
1463
1464

1465
1466
1467
1468
1469
1470
1471
1472







-
+
+
+
+

-
+
+










-
+




-
+







    }
}

/* + style theme names --
 * 	Return list of registered themes.
 */
static int StyleThemeNamesCmd(
    ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
    ClientData clientData,
    Tcl_Interp *interp,
    TCL_UNUSED(int),
    TCL_UNUSED(Tcl_Obj *const *))
{
    StylePackageData *pkgPtr = clientData;
    StylePackageData *pkgPtr = (StylePackageData *)clientData;

    return TtkEnumerateHashTable(interp, &pkgPtr->themeTable);
}

/* + style theme settings $theme $script
 *
 * 	Temporarily sets the current theme to $themeName,
 * 	evaluates $script, then restores the old theme.
 */
static int
StyleThemeSettingsCmd(
    ClientData clientData,		/* Master StylePackageData pointer */
    ClientData clientData,		/* StylePackageData pointer */
    Tcl_Interp *interp,			/* Current interpreter */
    int objc,				/* Number of arguments */
    Tcl_Obj *const objv[])		/* Argument objects */
{
    StylePackageData *pkgPtr = clientData;
    StylePackageData *pkgPtr = (StylePackageData *)clientData;
    Ttk_Theme oldTheme = pkgPtr->currentTheme;
    Ttk_Theme newTheme;
    int status;

    if (objc != 5) {
	Tcl_WrongNumArgs(interp, 3, objv, "theme script");
	return TCL_ERROR;
1483
1484
1485
1486
1487
1488
1489
1490

1491
1492
1493
1494
1495
1496
1497
1484
1485
1486
1487
1488
1489
1490

1491
1492
1493
1494
1495
1496
1497
1498







-
+







}

/* + style element create name type ? ...args ?
 */
static int StyleElementCreateCmd(
    ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    StylePackageData *pkgPtr = clientData;
    StylePackageData *pkgPtr = (StylePackageData *)clientData;
    Ttk_Theme theme = pkgPtr->currentTheme;
    const char *elementName, *factoryName;
    Tcl_HashEntry *entryPtr;
    FactoryRec *recPtr;

    if (objc < 5) {
	Tcl_WrongNumArgs(interp, 3, objv, "name type ?-option value ...?");
1506
1507
1508
1509
1510
1511
1512
1513

1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525

1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541

1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555


1556
1557
1558
1559
1560
1561
1562
1507
1508
1509
1510
1511
1512
1513

1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525

1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541

1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554


1555
1556
1557
1558
1559
1560
1561
1562
1563







-
+











-
+















-
+












-
-
+
+







	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"No such element type %s", factoryName));
	Tcl_SetErrorCode(interp, "TTK", "LOOKUP", "ELEMENT_TYPE", factoryName,
		NULL);
	return TCL_ERROR;
    }

    recPtr = Tcl_GetHashValue(entryPtr);
    recPtr = (FactoryRec *)Tcl_GetHashValue(entryPtr);

    return recPtr->factory(interp, recPtr->clientData,
	    theme, elementName, objc - 5, objv + 5);
}

/* + style element names --
 * 	Return a list of elements defined in the current theme.
 */
static int StyleElementNamesCmd(
    ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    StylePackageData *pkgPtr = clientData;
    StylePackageData *pkgPtr = (StylePackageData *)clientData;
    Ttk_Theme theme = pkgPtr->currentTheme;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 3, objv, NULL);
	return TCL_ERROR;
    }
    return TtkEnumerateHashTable(interp, &theme->elementTable);
}

/* + style element options $element --
 * 	Return list of element options for specified element
 */
static int StyleElementOptionsCmd(
    ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    StylePackageData *pkgPtr = clientData;
    StylePackageData *pkgPtr = (StylePackageData *)clientData;
    Ttk_Theme theme = pkgPtr->currentTheme;
    const char *elementName;
    Ttk_ElementClass *elementClass;

    if (objc != 4) {
	Tcl_WrongNumArgs(interp, 3, objv, "element");
	return TCL_ERROR;
    }

    elementName = Tcl_GetString(objv[3]);
    elementClass = Ttk_GetElement(theme, elementName);
    if (elementClass) {
	Ttk_ElementSpec *specPtr = elementClass->specPtr;
	Ttk_ElementOptionSpec *option = specPtr->options;
	const Ttk_ElementSpec *specPtr = elementClass->specPtr;
	const Ttk_ElementOptionSpec *option = specPtr->options;
	Tcl_Obj *result = Tcl_NewListObj(0,0);

	while (option->optionName) {
	    Tcl_ListObjAppendElement(
		interp, result, Tcl_NewStringObj(option->optionName,-1));
	    ++option;
	}
1572
1573
1574
1575
1576
1577
1578
1579

1580
1581
1582
1583
1584
1585
1586
1573
1574
1575
1576
1577
1578
1579

1580
1581
1582
1583
1584
1585
1586
1587







-
+







}

/* + style layout name ?spec?
 */
static int StyleLayoutCmd(
    ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    StylePackageData *pkgPtr = clientData;
    StylePackageData *pkgPtr = (StylePackageData *)clientData;
    Ttk_Theme theme = pkgPtr->currentTheme;
    const char *layoutName;
    Ttk_LayoutTemplate layoutTemplate;

    if (objc < 3 || objc > 4) {
	Tcl_WrongNumArgs(interp, 2, objv, "name ?spec?");
	return TCL_ERROR;
1604
1605
1606
1607
1608
1609
1610

























1611
1612
1613
1614
1615
1616
1617

1618
1619
1620
1621
1622

1623
1624
1625
1626
1627
1628
1629
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642

1643
1644
1645
1646
1647

1648
1649
1650
1651
1652
1653
1654
1655







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






-
+




-
+







	    return TCL_ERROR;
	}
	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
StyleThemeUseCmd(
    ClientData clientData,		/* Master StylePackageData pointer */
    ClientData clientData,		/* StylePackageData pointer */
    Tcl_Interp *interp,			/* Current interpreter */
    int objc,				/* Number of arguments */
    Tcl_Obj *const objv[])		/* Argument objects */
{
    StylePackageData *pkgPtr = clientData;
    StylePackageData *pkgPtr = (StylePackageData *)clientData;
    Ttk_Theme theme;

    if (objc < 3 || objc > 4) {
	Tcl_WrongNumArgs(interp, 3, objv, "?theme?");
	return TCL_ERROR;
    }

1644
1645
1646
1647
1648
1649
1650

1651
1652
1653
1654
1655
1656
1657
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684







+







 *	Implementation of the [style] command.
 */

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[] = {
    { "create", StyleElementCreateCmd, 0 },
    { "names", StyleElementNamesCmd, 0 },
1667
1668
1669
1670
1671
1672
1673
1674

1675
1676
1677
1678
1679
1680
1681
1694
1695
1696
1697
1698
1699
1700

1701
1702
1703
1704
1705
1706
1707
1708







-
+







    { "theme", 0, StyleThemeEnsemble },
    { "element", 0, StyleElementEnsemble },
    { NULL, 0, 0 }
};

static int
StyleObjCmd(
    ClientData clientData,		/* Master StylePackageData pointer */
    ClientData clientData,		/* StylePackageData pointer */
    Tcl_Interp *interp,			/* Current interpreter */
    int objc,				/* Number of arguments */
    Tcl_Obj *const objv[])		/* Argument objects */
{
    return Ttk_InvokeEnsemble(StyleEnsemble, 1, clientData,interp,objc,objv);
}

1710
1711
1712
1713
1714
1715
1716
1717

1718
1719
1720
1721
1722
1723
1724
1737
1738
1739
1740
1741
1742
1743

1744
1745
1746
1747
1748
1749
1750
1751







-
+







 *	package on a per-interp basis.
 */

void Ttk_StylePkgInit(Tcl_Interp *interp)
{
    Tcl_Namespace *nsPtr;

    StylePackageData *pkgPtr = ckalloc(sizeof(StylePackageData));
    StylePackageData *pkgPtr = (StylePackageData *)ckalloc(sizeof(StylePackageData));

    pkgPtr->interp = interp;
    Tcl_InitHashTable(&pkgPtr->themeTable, TCL_STRING_KEYS);
    Tcl_InitHashTable(&pkgPtr->factoryTable, TCL_STRING_KEYS);
    pkgPtr->cleanupList = NULL;
    pkgPtr->cache = Ttk_CreateResourceCache(interp);
    pkgPtr->themeChangePending = 0;
Changes to generic/ttk/ttkTheme.h.
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
71
72
73
74
75
76
77



78
79
80
81
82



83
84
85
86
87
88
89
90
91
92


93
94
95
96
97
98
99
100
101
102
103
104








105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122



123
124
125
126
127
128
129







-
-
-





-
-
-










-
-












-
-
-
-
-
-
-
-


















-
-
-








#define Ttk_StateMatches(state, spec) \
    (((state) & ((spec)->onbits|(spec)->offbits)) == (spec)->onbits)

#define Ttk_ModifyState(state, spec) \
    (((state) & ~(spec)->offbits) | (spec)->onbits)

TTKAPI int Ttk_GetStateSpecFromObj(Tcl_Interp *, Tcl_Obj *, Ttk_StateSpec *);
TTKAPI Tcl_Obj *Ttk_NewStateSpecObj(unsigned int onbits,unsigned int offbits);

/*------------------------------------------------------------------------
 * +++ State maps and state tables.
 */
typedef Tcl_Obj *Ttk_StateMap;

TTKAPI Ttk_StateMap Ttk_GetStateMapFromObj(Tcl_Interp *, Tcl_Obj *);
TTKAPI Tcl_Obj *Ttk_StateMapLookup(Tcl_Interp*, Ttk_StateMap, Ttk_State);

/*
 * Table for looking up an integer index based on widget state:
 */
typedef struct
{
    int index;			/* Value to return if this entry matches */
    unsigned int onBits;	/* Bits which must be set */
    unsigned int offBits;	/* Bits which must be cleared */
} Ttk_StateTable;

TTKAPI int Ttk_StateTableLookup(Ttk_StateTable map[], Ttk_State);

/*------------------------------------------------------------------------
 * +++ Padding.
 * 	Used to represent internal padding and borders.
 */
typedef struct
{
    short left;
    short top;
    short right;
    short bottom;
} Ttk_Padding;

TTKAPI int Ttk_GetPaddingFromObj(Tcl_Interp*,Tk_Window,Tcl_Obj*,Ttk_Padding*);
TTKAPI int Ttk_GetBorderFromObj(Tcl_Interp*,Tcl_Obj*,Ttk_Padding*);

TTKAPI Ttk_Padding Ttk_MakePadding(short l, short t, short r, short b);
TTKAPI Ttk_Padding Ttk_UniformPadding(short borderWidth);
TTKAPI Ttk_Padding Ttk_AddPadding(Ttk_Padding, Ttk_Padding);
TTKAPI Ttk_Padding Ttk_RelievePadding(Ttk_Padding, int relief, int n);

#define Ttk_PaddingWidth(p) ((p).left + (p).right)
#define Ttk_PaddingHeight(p) ((p).top + (p).bottom)

#define Ttk_SetMargins(tkwin, pad) \
    Tk_SetInternalBorderEx(tkwin, pad.left, pad.right, pad.top, pad.bottom)

/*------------------------------------------------------------------------
 * +++ Boxes.
 * 	Used to represent rectangular regions
 */
typedef struct 	/* Hey, this is an XRectangle! */
{
    int x;
    int y;
    int width;
    int height;
} Ttk_Box;

TTKAPI Ttk_Box Ttk_MakeBox(int x, int y, int width, int height);
TTKAPI int Ttk_BoxContains(Ttk_Box, int x, int y);

#define Ttk_WinBox(tkwin) Ttk_MakeBox(0,0,Tk_Width(tkwin),Tk_Height(tkwin))

/*------------------------------------------------------------------------
 * +++ Layout utilities.
 */
typedef enum {
    TTK_SIDE_LEFT, TTK_SIDE_TOP, TTK_SIDE_RIGHT, TTK_SIDE_BOTTOM
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
142
143
144
145
146
147
148

149
150
151
152
153
154
155







-







/*
 * Aliases and useful combinations:
 */
#define TTK_FILL_X	(0x3)	/* -sticky ew */
#define TTK_FILL_Y	(0xC)	/* -sticky ns */
#define TTK_FILL_BOTH	(0xF)	/* -sticky nswe */

TTKAPI int Ttk_GetStickyFromObj(Tcl_Interp *, Tcl_Obj *, Ttk_Sticky *);
TTKAPI Tcl_Obj *Ttk_NewStickyObj(Ttk_Sticky);

/*
 * Extra bits for position specifications (combine -side and -sticky)
 */

typedef unsigned int Ttk_PositionSpec;	/* See below */
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239








240
241
242
243
244
245

246
247
248
249
250
251
252
253
254

255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283

284
285
286
287
288
289
290
168
169
170
171
172
173
174






175
176
177
178
179
180
181
182
183
184
185
186
187







188
189
190
191
192
193


194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217

218
219
220
221
222
223
224
225
226

227
228
229
230
231




232
233
234
235



236
237
238
239
240
241
242
243
244
245
246
247
248

249
250
251
252
253
254
255
256







-
-
-
-
-
-













-
-
-
-
-
-
-






-
-











+
+
+
+
+
+
+
+





-
+








-
+




-
-
-
-




-
-
-













-
+







#define _TTK_CHILDREN	(0x1000)/* for LayoutSpecs -- children follow */
#define _TTK_LAYOUT_END	(0x2000)/* for LayoutSpecs -- end of child list */
#define _TTK_LAYOUT	(0x4000)/* for LayoutSpec tables -- define layout */

#define _TTK_MASK_STICK (0x0F)	/* See Ttk_UnparseLayout() */
#define _TTK_MASK_PACK	(0xF0)	/* See Ttk_UnparseLayout(), packStrings */

TTKAPI Ttk_Box Ttk_PackBox(Ttk_Box *cavity, int w, int h, Ttk_Side side);
TTKAPI Ttk_Box Ttk_StickBox(Ttk_Box parcel, int w, int h, Ttk_Sticky sticky);
TTKAPI Ttk_Box Ttk_AnchorBox(Ttk_Box parcel, int w, int h, Tk_Anchor anchor);
TTKAPI Ttk_Box Ttk_PadBox(Ttk_Box b, Ttk_Padding p);
TTKAPI Ttk_Box Ttk_ExpandBox(Ttk_Box b, Ttk_Padding p);
TTKAPI Ttk_Box Ttk_PlaceBox(Ttk_Box *cavity, int w,int h, Ttk_Side,Ttk_Sticky);
TTKAPI Ttk_Box Ttk_PositionBox(Ttk_Box *cavity, int w, int h, Ttk_PositionSpec);

/*------------------------------------------------------------------------
 * +++ Themes.
 */
MODULE_SCOPE void Ttk_StylePkgInit(Tcl_Interp *);

typedef struct Ttk_Theme_ *Ttk_Theme;
typedef struct Ttk_ElementClass_ Ttk_ElementClass;
typedef struct Ttk_Layout_ *Ttk_Layout;
typedef struct Ttk_LayoutNode_ *Ttk_Element;
typedef struct Ttk_Style_ *Ttk_Style;

TTKAPI Ttk_Theme Ttk_GetTheme(Tcl_Interp *interp, const char *name);
TTKAPI Ttk_Theme Ttk_GetDefaultTheme(Tcl_Interp *interp);
TTKAPI Ttk_Theme Ttk_GetCurrentTheme(Tcl_Interp *interp);

TTKAPI Ttk_Theme Ttk_CreateTheme(
    Tcl_Interp *interp, const char *name, Ttk_Theme parent);

typedef int (Ttk_ThemeEnabledProc)(Ttk_Theme theme, void *clientData);
MODULE_SCOPE void Ttk_SetThemeEnabledProc(Ttk_Theme, Ttk_ThemeEnabledProc, void *);

MODULE_SCOPE int Ttk_UseTheme(Tcl_Interp *, Ttk_Theme);

typedef void (Ttk_CleanupProc)(void *clientData);
TTKAPI void Ttk_RegisterCleanup(
    Tcl_Interp *interp, void *deleteData, Ttk_CleanupProc *cleanupProc);

/*------------------------------------------------------------------------
 * +++ Elements.
 */

enum TTKStyleVersion2 { TK_STYLE_VERSION_2 = 2 };

typedef void (Ttk_ElementSizeProc)(void *clientData, void *elementRecord,
        Tk_Window tkwin, int *widthPtr, int *heightPtr, Ttk_Padding*);
typedef void (Ttk_ElementDrawProc)(void *clientData, void *elementRecord,
        Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state);

#ifndef TkSizeT
#   if TCL_MAJOR_VERSION > 8
#	define TkSizeT size_t
#   else
#	define TkSizeT int
#   endif
#endif

typedef struct Ttk_ElementOptionSpec
{
    const char *optionName;		/* Command-line name of the widget option */
    Tk_OptionType type; 	/* Accepted option types */
    int offset;			/* Offset of Tcl_Obj* field in element record */
    TkSizeT offset;			/* Offset of Tcl_Obj* field in element record */
    const char *defaultValue;		/* Default value to used if resource missing */
} Ttk_ElementOptionSpec;

#define TK_OPTION_ANY TK_OPTION_STRING

typedef struct Ttk_ElementSpec {
    enum TTKStyleVersion2 version;	/* Version of the style support. */
    size_t elementSize;			/* Size of element record */
    Ttk_ElementOptionSpec *options;	/* List of options, NULL-terminated */
    const Ttk_ElementOptionSpec *options;	/* List of options, NULL-terminated */
    Ttk_ElementSizeProc *size;		/* Compute min size and padding */
    Ttk_ElementDrawProc *draw;  	/* Draw the element */
} Ttk_ElementSpec;

TTKAPI Ttk_ElementClass *Ttk_RegisterElement(
	Tcl_Interp *interp, Ttk_Theme theme, const char *elementName,
	Ttk_ElementSpec *, void *clientData);

typedef int (*Ttk_ElementFactory)
	(Tcl_Interp *, void *clientData,
	 Ttk_Theme, const char *elementName, int objc, Tcl_Obj *const objv[]);

TTKAPI int Ttk_RegisterElementFactory(
	Tcl_Interp *, const char *name, Ttk_ElementFactory, void *clientData);

/*
 * Null element implementation:
 * has no geometry or layout; may be used as a stub or placeholder.
 */

typedef struct {
    Tcl_Obj	*unused;
} NullElement;

MODULE_SCOPE void TtkNullElementSize
	(void *, void *, Tk_Window, int *, int *, Ttk_Padding *);
MODULE_SCOPE void TtkNullElementDraw
	(void *, void *, Tk_Window, Drawable, Ttk_Box, Ttk_State);
MODULE_SCOPE Ttk_ElementOptionSpec TtkNullElementOptions[];
MODULE_SCOPE const Ttk_ElementOptionSpec TtkNullElementOptions[];
MODULE_SCOPE Ttk_ElementSpec ttkNullElementSpec;

/*------------------------------------------------------------------------
 * +++ Layout templates.
 */
typedef struct {
    const char *	elementName;
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
269
270
271
272
273
274
275



276
277
278
279
280
281
282







-
-
-







				{ 0, _TTK_LAYOUT_END },
#define TTK_NODE(name, flags)	{ name, flags },
#define TTK_END_LAYOUT_TABLE	{ 0, _TTK_LAYOUT | _TTK_LAYOUT_END } };

#define TTK_BEGIN_LAYOUT(name)	static TTKLayoutInstruction name[] = {
#define TTK_END_LAYOUT 		{ 0, _TTK_LAYOUT_END } };

TTKAPI void Ttk_RegisterLayout(
    Ttk_Theme theme, const char *className, Ttk_LayoutSpec layoutSpec);

TTKAPI void Ttk_RegisterLayouts(
    Ttk_Theme theme, Ttk_LayoutSpec layoutTable);

/*------------------------------------------------------------------------
 * +++ Layout instances.
 */

388
389
390
391
392
393
394
395

396
397
398
399
400
401
402
403
404
405
406
407
408
409

410
411
412
413
414



415
416
417
418
419
420
421
351
352
353
354
355
356
357

358
359
360
361
362
363
364
365
366
367
368
369
370
371

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387







-
+













-
+





+
+
+







typedef enum 			/* -default option values */
{
    TTK_BUTTON_DEFAULT_NORMAL,	/* widget defaultable */
    TTK_BUTTON_DEFAULT_ACTIVE,	/* currently the default widget */
    TTK_BUTTON_DEFAULT_DISABLED	/* not defaultable */
} Ttk_ButtonDefaultState;

TTKAPI int Ttk_GetButtonDefaultStateFromObj(Tcl_Interp *, Tcl_Obj *, int *);
TTKAPI int Ttk_GetButtonDefaultStateFromObj(Tcl_Interp *, Tcl_Obj *, Ttk_ButtonDefaultState *);

typedef enum 			/* -compound option values */
{
    TTK_COMPOUND_NONE,  	/* image if specified, otherwise text */
    TTK_COMPOUND_TEXT,  	/* text only */
    TTK_COMPOUND_IMAGE,  	/* image only */
    TTK_COMPOUND_CENTER,	/* text overlays image */
    TTK_COMPOUND_TOP,   	/* image above text */
    TTK_COMPOUND_BOTTOM,	/* image below text */
    TTK_COMPOUND_LEFT,   	/* image to left of text */
    TTK_COMPOUND_RIGHT  	/* image to right of text */
} Ttk_Compound;

TTKAPI int Ttk_GetCompoundFromObj(Tcl_Interp *, Tcl_Obj *, int *);
TTKAPI int Ttk_GetCompoundFromObj(Tcl_Interp *, Tcl_Obj *, Ttk_Compound *);

typedef enum { 		/* -orient option values */
    TTK_ORIENT_HORIZONTAL,
    TTK_ORIENT_VERTICAL
} Ttk_Orient;

MODULE_SCOPE int		TtkGetOrientFromObj(Tcl_Interp *interp,
				Tcl_Obj *objPtr, Ttk_Orient *orient);

/*------------------------------------------------------------------------
 * +++ Utilities.
 */

typedef struct TtkEnsemble {
    const char *name;			/* subcommand name */
Changes to generic/ttk/ttkThemeInt.h.
11
12
13
14
15
16
17
18

19
20
21
22

23
24
25
26
27
28
29
11
12
13
14
15
16
17

18
19
20
21

22
23
24
25
26
27
28
29







-
+



-
+








typedef struct Ttk_TemplateNode_ Ttk_TemplateNode, *Ttk_LayoutTemplate;

MODULE_SCOPE Ttk_ElementClass *Ttk_GetElement(Ttk_Theme, const char *name);
MODULE_SCOPE const char *Ttk_ElementClassName(Ttk_ElementClass *);

MODULE_SCOPE void Ttk_ElementSize(
	Ttk_ElementClass *, Ttk_Style, char *recordPtr, Tk_OptionTable,
	Ttk_ElementClass *, Ttk_Style, void *recordPtr, Tk_OptionTable,
	Tk_Window tkwin, Ttk_State state,
	int *widthPtr, int *heightPtr, Ttk_Padding*);
MODULE_SCOPE void Ttk_DrawElement(
	Ttk_ElementClass *, Ttk_Style, char *recordPtr, Tk_OptionTable,
	Ttk_ElementClass *, Ttk_Style, void *recordPtr, Tk_OptionTable,
	Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state);

MODULE_SCOPE Tcl_Obj *Ttk_QueryStyle(
    Ttk_Style, void *, Tk_OptionTable, const char *, Ttk_State state);

MODULE_SCOPE Ttk_LayoutTemplate Ttk_ParseLayoutTemplate(
	Tcl_Interp *, Tcl_Obj *);
Changes to generic/ttk/ttkTrace.c.
1
2
3
4
5
6

7
8
9
10

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30


31
32
33

34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

55
56
57
58
59
60
61
1
2
3
4
5

6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28


29
30
31
32

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

54
55
56
57
58
59
60
61





-
+



-
+


















-
-
+
+


-
+




















-
+







/*
 * Copyright 2003, Joe English
 *
 * Simplified interface to Tcl_TraceVariable.
 *
 * PROBLEM: Can't distinguish "variable does not exist" (which is OK) 
 * PROBLEM: Can't distinguish "variable does not exist" (which is OK)
 * from other errors (which are not).
 */

#include <tk.h>
#include "tkInt.h"
#include "ttkTheme.h"
#include "ttkWidget.h"

struct TtkTraceHandle_
{
    Tcl_Interp		*interp;	/* Containing interpreter */
    Tcl_Obj 		*varnameObj;	/* Name of variable being traced */
    Ttk_TraceProc	callback;	/* Callback procedure */
    void		*clientData;	/* Data to pass to callback */
};

/*
 * Tcl_VarTraceProc for trace handles.
 */
static char *
VarTraceProc(
    ClientData clientData,	/* Widget record pointer */
    Tcl_Interp *interp, 	/* Interpreter containing variable. */
    const char *name1,		/* (unused) */
    const char *name2,		/* (unused) */
    TCL_UNUSED(const char *),	/* name1 */
    TCL_UNUSED(const char *),	/* name2 */
    int flags)			/* Information about what happened. */
{
    Ttk_TraceHandle *tracePtr = clientData;
    Ttk_TraceHandle *tracePtr = (Ttk_TraceHandle *)clientData;
    const char *name, *value;
    Tcl_Obj *valuePtr;

    if (Tcl_InterpDeleted(interp)) {
	return NULL;
    }

    name = Tcl_GetString(tracePtr->varnameObj);

    /*
     * If the variable is being unset, then re-establish the trace:
     */
    if (flags & TCL_TRACE_DESTROYED) {
	/*
	 * If a prior call to Ttk_UntraceVariable() left behind an
	 * indicator that we wanted this handler to be deleted (see below),
	 * cleanup the ClientData bits and exit.
	 */
	if (tracePtr->interp == NULL) {
	    Tcl_DecrRefCount(tracePtr->varnameObj);
	    ckfree((ClientData)tracePtr);
	    ckfree(tracePtr);
	    return NULL;
	}
	Tcl_TraceVar2(interp, name, NULL,
		TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
		VarTraceProc, clientData);
	tracePtr->callback(tracePtr->clientData, NULL);
	return NULL;
81
82
83
84
85
86
87
88

89
90
91
92
93
94
95
96
97
98
99

100
101
102
103
104
105
106
81
82
83
84
85
86
87

88
89
90
91
92
93
94
95
96
97
98

99
100
101
102
103
104
105
106







-
+










-
+







 */
Ttk_TraceHandle *Ttk_TraceVariable(
    Tcl_Interp *interp,
    Tcl_Obj *varnameObj,
    Ttk_TraceProc callback,
    void *clientData)
{
    Ttk_TraceHandle *h = ckalloc(sizeof(*h));
    Ttk_TraceHandle *h = (Ttk_TraceHandle *)ckalloc(sizeof(*h));
    int status;

    h->interp = interp;
    h->varnameObj = Tcl_DuplicateObj(varnameObj);
    Tcl_IncrRefCount(h->varnameObj);
    h->clientData = clientData;
    h->callback = callback;

    status = Tcl_TraceVar2(interp, Tcl_GetString(varnameObj),
	    NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
	    VarTraceProc, (ClientData)h);
	    VarTraceProc, h);

    if (status != TCL_OK) {
	Tcl_DecrRefCount(h->varnameObj);
	ckfree(h);
	return NULL;
    }

133
134
135
136
137
138
139
140

141
142
143
144
145
146
147
148
149
150
151
152
153
154
155

156
157
158
159
160
161
162
133
134
135
136
137
138
139

140
141
142
143
144
145
146
147
148
149
150
151
152
153
154

155
156
157
158
159
160
161
162







-
+














-
+








	/*
	 * Search the traces on the variable to see if the one we are tasked
	 * with removing is present.
	 */
	while ((cd = Tcl_VarTraceInfo(h->interp, Tcl_GetString(h->varnameObj),
		TCL_GLOBAL_ONLY, VarTraceProc, cd)) != NULL) {
	    if (cd == (ClientData) h) {
	    if (cd == h) {
		break;
	    }
	}
	/*
	 * If the trace we wish to delete is not visible, Tcl_UntraceVar
	 * will do nothing, so don't try to call it.  Instead set an
	 * indicator in the Ttk_TraceHandle that we need to cleanup later.
	 */
	if (cd == NULL) {
	    h->interp = NULL;
	    return;
	}
	Tcl_UntraceVar2(h->interp, Tcl_GetString(h->varnameObj),
		NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
		VarTraceProc, (ClientData)h);
		VarTraceProc, h);
	Tcl_DecrRefCount(h->varnameObj);
	ckfree(h);
    }
}

/*
 * Ttk_FireTrace --
Changes to generic/ttk/ttkTrack.c.
1
2

3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

20
21
22
23

24
25
26

27
28
29
30
31
32
33
1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

19
20
21
22

23
24
25

26
27
28
29
30
31
32
33

-
+
















-
+



-
+


-
+







/*
 * 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.
 *
 * Usage:
 * 	TtkTrackElementState(&recordPtr->core);
 *
 * Registers an event handler on the widget that tracks pointer
 * events and updates the state of the element under the
 * mouse cursor.
 *
 * The "active" element is the one under the mouse cursor,
 * and is normally set to the ACTIVE state unless another element
 * is currently being pressed.
 *
 * The active element becomes "pressed" on <ButtonPress> events,
 * The active element becomes "pressed" on <Button> events,
 * and remains "active" and "pressed" until the corresponding
 * <ButtonRelease> event.
 *
 * TODO: Handle "chords" properly (e.g., <B1-ButtonPress-2>)
 * TODO: Handle "chords" properly (e.g., <B1-Button-2>)
 */

#include <tk.h>
#include "tkInt.h"
#include "ttkTheme.h"
#include "ttkWidget.h"

typedef struct {
    WidgetCore		*corePtr;	/* widget to track */
    Ttk_Layout		tracking;	/* current layout being tracked */
    Ttk_Element 	activeElement;	/* element under the mouse cursor */
114
115
116
117
118
119
120
121

122
123
124
125
126
127
128
114
115
116
117
118
119
120

121
122
123
124
125
126
127
128







-
+







    | EnterWindowMask
    | StructureNotifyMask
    ;

static void
ElementStateEventProc(ClientData clientData, XEvent *ev)
{
    ElementStateTracker *es = clientData;
    ElementStateTracker *es = (ElementStateTracker *)clientData;
    Ttk_Layout layout = es->corePtr->layout;
    Ttk_Element element;

    /* Guard against dangling pointers [#2431428]
     */
    if (es->tracking != layout) {
	es->pressedElement = es->activeElement = 0;
169
170
171
172
173
174
175
176

177
178
179
180
181
182
183
169
170
171
172
173
174
175

176
177
178
179
180
181
182
183







-
+







 * TtkTrackElementState --
 * 	Register an event handler to manage the 'pressed'
 * 	and 'active' states of individual widget elements.
 */

void TtkTrackElementState(WidgetCore *corePtr)
{
    ElementStateTracker *es = ckalloc(sizeof(*es));
    ElementStateTracker *es = (ElementStateTracker *)ckalloc(sizeof(*es));
    es->corePtr = corePtr;
    es->tracking = 0;
    es->activeElement = es->pressedElement = 0;
    Tk_CreateEventHandler(corePtr->tkwin,
	    ElementStateMask,ElementStateEventProc,es);
}

Changes to generic/ttk/ttkTreeview.c.
1
2

3
4
5
6
7
8
9
10
11
12
13
14
15
1

2
3
4
5
6


7
8
9
10
11
12
13

-
+




-
-







/*
 * Copyright (c) 2004, Joe English
 * Copyright © 2004, Joe English
 *
 * ttk::treeview widget implementation.
 */

#include <string.h>
#include <stdio.h>
#include "tkInt.h"
#include "ttkTheme.h"
#include "ttkWidget.h"

#define DEF_TREE_ROWS		"10"
#define DEF_COLWIDTH		"200"
#define DEF_MINWIDTH		"20"
57
58
59
60
61
62
63
64

65
66

67
68
69

70
71
72

73
74
75

76
77
78

79
80
81

82
83



84
85
86
87
88
89

90
91
92
93
94
95
96
55
56
57
58
59
60
61

62
63

64
65
66

67
68
69

70
71
72

73
74
75

76
77
78

79
80
81
82
83
84
85
86
87
88
89

90
91
92
93
94
95
96
97







-
+

-
+


-
+


-
+


-
+


-
+


-
+


+
+
+





-
+







    Ttk_TagSet	tagset;
    Ttk_ImageSpec *imagespec;
};

#define ITEM_OPTION_TAGS_CHANGED	0x100
#define ITEM_OPTION_IMAGE_CHANGED	0x200

static Tk_OptionSpec ItemOptionSpecs[] = {
static const Tk_OptionSpec ItemOptionSpecs[] = {
    {TK_OPTION_STRING, "-text", "text", "Text",
	"", Tk_Offset(TreeItem,textObj), -1,
	"", offsetof(TreeItem,textObj), TCL_INDEX_NONE,
	0,0,0 },
    {TK_OPTION_STRING, "-image", "image", "Image",
	NULL, Tk_Offset(TreeItem,imageObj), -1,
	NULL, offsetof(TreeItem,imageObj), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK,0,ITEM_OPTION_IMAGE_CHANGED },
    {TK_OPTION_STRING, "-values", "values", "Values",
	NULL, Tk_Offset(TreeItem,valuesObj), -1,
	NULL, offsetof(TreeItem,valuesObj), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK,0,0 },
    {TK_OPTION_BOOLEAN, "-open", "open", "Open",
	"0", Tk_Offset(TreeItem,openObj), -1,
	"0", offsetof(TreeItem,openObj), TCL_INDEX_NONE,
	0,0,0 },
    {TK_OPTION_STRING, "-tags", "tags", "Tags",
	NULL, Tk_Offset(TreeItem,tagsObj), -1,
	NULL, offsetof(TreeItem,tagsObj), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK,0,ITEM_OPTION_TAGS_CHANGED },

    {TK_OPTION_END, 0,0,0, NULL, -1,-1, 0,0,0}
    {TK_OPTION_END, 0,0,0, NULL, TCL_INDEX_NONE,TCL_INDEX_NONE, 0,0,0}
};

/* Forward declaration */
static void RemoveTag(TreeItem *, Ttk_Tag);

/* + NewItem --
 * 	Allocate a new, uninitialized, unlinked item
 */
static TreeItem *NewItem(void)
{
    TreeItem *item = ckalloc(sizeof(*item));
    TreeItem *item = (TreeItem *)ckalloc(sizeof(*item));

    item->entryPtr = 0;
    item->parent = item->children = item->next = item->prev = NULL;

    item->state = 0ul;
    item->textObj = NULL;
    item->imageObj = NULL;
117
118
119
120
121
122
123
124

125
126
127
128
129
130
131
118
119
120
121
122
123
124

125
126
127
128
129
130
131
132







-
+








    if (item->tagset)	{ Ttk_FreeTagSet(item->tagset); }
    if (item->imagespec) { TtkFreeImageSpec(item->imagespec); }

    ckfree(item);
}

static void FreeItemCB(void *clientData) { FreeItem(clientData); }
static void FreeItemCB(void *clientData) { FreeItem((TreeItem *)clientData); }

/* + DetachItem --
 * 	Unlink an item from the tree.
 */
static void DetachItem(TreeItem *item)
{
    if (item->parent && item->parent->children == item)
185
186
187
188
189
190
191
192

193
194

195
196
197

198
199
200

201
202
203

204
205
206

207
208
209

210
211
212

213
214
215
216
217
218
219
186
187
188
189
190
191
192

193
194

195
196
197

198
199
200

201
202
203

204
205
206

207
208
209

210
211
212

213
214
215
216
217
218
219
220







-
+

-
+


-
+


-
+


-
+


-
+


-
+


-
+







    Tcl_Obj *imageObj;		/* taken from item */
    Tcl_Obj *anchorObj;		/* from column <<NOTE-ANCHOR>> */
    Tcl_Obj *backgroundObj;	/* remainder from tag */
    Tcl_Obj *foregroundObj;
    Tcl_Obj *fontObj;
} DisplayItem;

static Tk_OptionSpec TagOptionSpecs[] = {
static const Tk_OptionSpec TagOptionSpecs[] = {
    {TK_OPTION_STRING, "-text", "text", "Text",
	NULL, Tk_Offset(DisplayItem,textObj), -1,
	NULL, offsetof(DisplayItem,textObj), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK,0,0 },
    {TK_OPTION_STRING, "-image", "image", "Image",
	NULL, Tk_Offset(DisplayItem,imageObj), -1,
	NULL, offsetof(DisplayItem,imageObj), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK,0,0 },
    {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",
	NULL, Tk_Offset(DisplayItem,anchorObj), -1,
	NULL, offsetof(DisplayItem,anchorObj), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK, 0, GEOMETRY_CHANGED},	/* <<NOTE-ANCHOR>> */
    {TK_OPTION_COLOR, "-background", "windowColor", "WindowColor",
	NULL, Tk_Offset(DisplayItem,backgroundObj), -1,
	NULL, offsetof(DisplayItem,backgroundObj), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK,0,0 },
    {TK_OPTION_COLOR, "-foreground", "textColor", "TextColor",
	NULL, Tk_Offset(DisplayItem,foregroundObj), -1,
	NULL, offsetof(DisplayItem,foregroundObj), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK,0,0 },
    {TK_OPTION_FONT, "-font", "font", "Font",
	NULL, Tk_Offset(DisplayItem,fontObj), -1,
	NULL, offsetof(DisplayItem,fontObj), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },

    {TK_OPTION_END, 0,0,0, NULL, -1,-1, 0,0,0}
    {TK_OPTION_END, 0,0,0, NULL, TCL_INDEX_NONE,TCL_INDEX_NONE, 0,0,0}
};

/*------------------------------------------------------------------------
 * +++ Columns.
 *
 * There are separate option tables associated with the column record:
 * ColumnOptionSpecs is for configuring the column,
269
270
271
272
273
274
275
276

277
278

279
280
281

282
283
284

285
286
287

288
289
290

291
292

293
294
295

296
297

298
299
300

301
302
303

304
305
306

307
308
309

310
311

312
313
314
315
316
317
318
319
320
321
322
323
324

325
326
327
328
329
330
331

332
333
334
335
336
337
338
270
271
272
273
274
275
276

277
278

279
280
281

282
283
284

285
286
287

288
289
290

291
292

293
294
295

296
297

298
299
300

301
302
303

304
305
306

307
308
309

310
311

312
313
314
315
316
317
318
319
320
321
322
323
324

325
326
327
328
329
330
331

332
333
334
335
336
337
338
339







-
+

-
+


-
+


-
+


-
+


-
+

-
+


-
+

-
+


-
+


-
+


-
+


-
+

-
+












-
+






-
+







    if (column->headingAnchorObj) { Tcl_DecrRefCount(column->headingAnchorObj); }
    if (column->headingStateObj) { Tcl_DecrRefCount(column->headingStateObj); }
    if (column->headingCommandObj) { Tcl_DecrRefCount(column->headingCommandObj); }

    /* Don't touch column->data, it's scratch storage */
}

static Tk_OptionSpec ColumnOptionSpecs[] = {
static const Tk_OptionSpec ColumnOptionSpecs[] = {
    {TK_OPTION_INT, "-width", "width", "Width",
	DEF_COLWIDTH, -1, Tk_Offset(TreeColumn,width),
	DEF_COLWIDTH, TCL_INDEX_NONE, offsetof(TreeColumn,width),
	0,0,GEOMETRY_CHANGED },
    {TK_OPTION_INT, "-minwidth", "minWidth", "MinWidth",
	DEF_MINWIDTH, -1, Tk_Offset(TreeColumn,minWidth),
	DEF_MINWIDTH, TCL_INDEX_NONE, offsetof(TreeColumn,minWidth),
	0,0,0 },
    {TK_OPTION_BOOLEAN, "-stretch", "stretch", "Stretch",
	"1", -1, Tk_Offset(TreeColumn,stretch),
	"1", TCL_INDEX_NONE, offsetof(TreeColumn,stretch),
	0,0,GEOMETRY_CHANGED },
    {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",
	"w", Tk_Offset(TreeColumn,anchorObj), -1,	/* <<NOTE-ANCHOR>> */
	"w", offsetof(TreeColumn,anchorObj), TCL_INDEX_NONE,	/* <<NOTE-ANCHOR>> */
	0,0,0 },
    {TK_OPTION_STRING, "-id", "id", "ID",
	NULL, Tk_Offset(TreeColumn,idObj), -1,
	NULL, offsetof(TreeColumn,idObj), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK,0,READONLY_OPTION },
    {TK_OPTION_END, 0,0,0, NULL, -1,-1, 0,0,0}
    {TK_OPTION_END, 0,0,0, NULL, TCL_INDEX_NONE,TCL_INDEX_NONE, 0,0,0}
};

static Tk_OptionSpec HeadingOptionSpecs[] = {
static const Tk_OptionSpec HeadingOptionSpecs[] = {
    {TK_OPTION_STRING, "-text", "text", "Text",
	"", Tk_Offset(TreeColumn,headingObj), -1,
	"", offsetof(TreeColumn,headingObj), TCL_INDEX_NONE,
	0,0,0 },
    {TK_OPTION_STRING, "-image", "image", "Image",
	"", Tk_Offset(TreeColumn,headingImageObj), -1,
	"", offsetof(TreeColumn,headingImageObj), TCL_INDEX_NONE,
	0,0,0 },
    {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",
	"center", Tk_Offset(TreeColumn,headingAnchorObj), -1,
	"center", offsetof(TreeColumn,headingAnchorObj), TCL_INDEX_NONE,
	0,0,0 },
    {TK_OPTION_STRING, "-command", "", "",
	"", Tk_Offset(TreeColumn,headingCommandObj), -1,
	"", offsetof(TreeColumn,headingCommandObj), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK,0,0 },
    {TK_OPTION_STRING, "state", "", "",
	"", Tk_Offset(TreeColumn,headingStateObj), -1,
	"", offsetof(TreeColumn,headingStateObj), TCL_INDEX_NONE,
	0,0,STATE_CHANGED },
    {TK_OPTION_END, 0,0,0, NULL, -1,-1, 0,0,0}
    {TK_OPTION_END, 0,0,0, NULL, TCL_INDEX_NONE,TCL_INDEX_NONE, 0,0,0}
};

/*------------------------------------------------------------------------
 * +++ -show option:
 * TODO: Implement SHOW_BRANCHES.
 */

#define SHOW_TREE 	(0x1) 	/* Show tree column? */
#define SHOW_HEADINGS	(0x2)	/* Show heading row? */

#define DEFAULT_SHOW	"tree headings"

static const char *showStrings[] = {
static const char *const showStrings[] = {
    "tree", "headings", NULL
};

static int GetEnumSetFromObj(
    Tcl_Interp *interp,
    Tcl_Obj *objPtr,
    const char *table[],
    const char *const table[],
    unsigned *resultPtr)
{
    unsigned result = 0;
    int i, objc;
    Tcl_Obj **objv;

    if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK)
431
432
433
434
435
436
437
438

439
440

441
442
443


444
445
446


447
448
449


450
451
452
453


454
455
456
457


458
459

460
461
462
463

464
465
466

467
468
469
470
471
472
473
432
433
434
435
436
437
438

439
440

441
442


443
444
445


446
447
448


449
450
451
452


453
454
455
456


457
458
459

460
461
462
463

464
465
466

467
468
469
470
471
472
473
474







-
+

-
+

-
-
+
+

-
-
+
+

-
-
+
+


-
-
+
+


-
-
+
+

-
+



-
+


-
+








#define USER_MASK 		0x0100
#define COLUMNS_CHANGED 	(USER_MASK)
#define DCOLUMNS_CHANGED	(USER_MASK<<1)
#define SCROLLCMD_CHANGED	(USER_MASK<<2)
#define SHOW_CHANGED 		(USER_MASK<<3)

static const char *SelectModeStrings[] = { "none", "browse", "extended", NULL };
static const char *const SelectModeStrings[] = { "none", "browse", "extended", NULL };

static Tk_OptionSpec TreeviewOptionSpecs[] = {
static const Tk_OptionSpec TreeviewOptionSpecs[] = {
    {TK_OPTION_STRING, "-columns", "columns", "Columns",
	"", Tk_Offset(Treeview,tree.columnsObj), -1,
	0,0,COLUMNS_CHANGED | GEOMETRY_CHANGED /*| READONLY_OPTION*/ },
	"", offsetof(Treeview,tree.columnsObj), TCL_INDEX_NONE,
	0, 0,COLUMNS_CHANGED | GEOMETRY_CHANGED /*| READONLY_OPTION*/ },
    {TK_OPTION_STRING, "-displaycolumns","displayColumns","DisplayColumns",
	"#all", Tk_Offset(Treeview,tree.displayColumnsObj), -1,
	0,0,DCOLUMNS_CHANGED | GEOMETRY_CHANGED },
	"#all", offsetof(Treeview,tree.displayColumnsObj), TCL_INDEX_NONE,
	0, 0,DCOLUMNS_CHANGED | GEOMETRY_CHANGED },
    {TK_OPTION_STRING, "-show", "show", "Show",
	DEFAULT_SHOW, Tk_Offset(Treeview,tree.showObj), -1,
	0,0,SHOW_CHANGED | GEOMETRY_CHANGED },
	DEFAULT_SHOW, offsetof(Treeview,tree.showObj), TCL_INDEX_NONE,
	0, 0,SHOW_CHANGED | GEOMETRY_CHANGED },

    {TK_OPTION_STRING_TABLE, "-selectmode", "selectMode", "SelectMode",
	"extended", Tk_Offset(Treeview,tree.selectModeObj), -1,
	0,(ClientData)SelectModeStrings,0 },
	"extended", offsetof(Treeview,tree.selectModeObj), TCL_INDEX_NONE,
	0, (void *)SelectModeStrings, 0 },

    {TK_OPTION_PIXELS, "-height", "height", "Height",
	DEF_TREE_ROWS, Tk_Offset(Treeview,tree.heightObj), -1,
	0,0,GEOMETRY_CHANGED},
	DEF_TREE_ROWS, offsetof(Treeview,tree.heightObj), TCL_INDEX_NONE,
	0, 0,GEOMETRY_CHANGED},
    {TK_OPTION_STRING, "-padding", "padding", "Pad",
	NULL, Tk_Offset(Treeview,tree.paddingObj), -1,
	NULL, offsetof(Treeview,tree.paddingObj), TCL_INDEX_NONE,
	TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },

    {TK_OPTION_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand",
	NULL, -1, Tk_Offset(Treeview, tree.xscroll.scrollCmd),
	NULL, TCL_INDEX_NONE, offsetof(Treeview, tree.xscroll.scrollCmd),
	TK_OPTION_NULL_OK, 0, SCROLLCMD_CHANGED},
    {TK_OPTION_STRING, "-yscrollcommand", "yScrollCommand", "ScrollCommand",
	NULL, -1, Tk_Offset(Treeview, tree.yscroll.scrollCmd),
	NULL, TCL_INDEX_NONE, offsetof(Treeview, tree.yscroll.scrollCmd),
	TK_OPTION_NULL_OK, 0, SCROLLCMD_CHANGED},

    WIDGET_TAKEFOCUS_TRUE,
    WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs)
};

/*------------------------------------------------------------------------
523
524
525
526
527
528
529
530

531
532
533
534
535
536
537
524
525
526
527
528
529
530

531
532
533
534
535
536
537
538







-
+







    int columnIndex;

    /* Check for named column:
     */
    entryPtr = Tcl_FindHashEntry(
	    &tv->tree.columnNames, Tcl_GetString(columnIDObj));
    if (entryPtr) {
	return Tcl_GetHashValue(entryPtr);
	return (TreeColumn *)Tcl_GetHashValue(entryPtr);
    }

    /* Check for number:
     */
    if (Tcl_GetIntFromObj(NULL, columnIDObj, &columnIndex) == TCL_OK) {
	if (columnIndex < 0 || columnIndex >= tv->tree.nColumns) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
584
585
586
587
588
589
590
591

592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612

613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629

630
631
632
633
634
635
636
585
586
587
588
589
590
591

592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612

613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629

630
631
632
633
634
635
636
637







-
+




















-
+
















-
+








    if (!entryPtr) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"Item %s not found", itemName));
	Tcl_SetErrorCode(interp, "TTK", "TREE", "ITEM", NULL);
	return 0;
    }
    return Tcl_GetHashValue(entryPtr);
    return (TreeItem *)Tcl_GetHashValue(entryPtr);
}

/* + GetItemListFromObj --
 * 	Parse a Tcl_Obj * as a list of items.
 * 	Returns a NULL-terminated array of items; result must
 * 	be ckfree()d. On error, returns NULL and leaves an error
 * 	message in interp.
 */

static TreeItem **GetItemListFromObj(
    Tcl_Interp *interp, Treeview *tv, Tcl_Obj *objPtr)
{
    TreeItem **items;
    Tcl_Obj **elements;
    int i, nElements;

    if (Tcl_ListObjGetElements(interp,objPtr,&nElements,&elements) != TCL_OK) {
	return NULL;
    }

    items = ckalloc((nElements + 1)*sizeof(TreeItem*));
    items = (TreeItem **)ckalloc((nElements + 1)*sizeof(TreeItem*));
    for (i = 0; i < nElements; ++i) {
	items[i] = FindItem(interp, tv, elements[i]);
	if (!items[i]) {
	    ckfree(items);
	    return NULL;
	}
    }
    items[i] = NULL;
    return items;
}

/* + ItemName --
 * 	Returns the item's ID.
 */
static const char *ItemName(Treeview *tv, TreeItem *item)
{
    return Tcl_GetHashKey(&tv->tree.items, item->entryPtr);
    return (const char *)Tcl_GetHashKey(&tv->tree.items, item->entryPtr);
}

/* + ItemID --
 * 	Returns a fresh Tcl_Obj * (refcount 0) holding the
 * 	item identifier of the specified item.
 */
static Tcl_Obj *ItemID(Treeview *tv, TreeItem *item)
680
681
682
683
684
685
686
687

688
689
690
691
692
693
694
681
682
683
684
685
686
687

688
689
690
691
692
693
694
695







-
+







     */
    TreeviewFreeColumns(tv);

    /*
     * Initialize columns array and columnNames hash table:
     */
    tv->tree.nColumns = ncols;
    tv->tree.columns = ckalloc(tv->tree.nColumns * sizeof(TreeColumn));
    tv->tree.columns = (TreeColumn *)ckalloc(tv->tree.nColumns * sizeof(TreeColumn));

    for (i = 0; i < ncols; ++i) {
	int isNew;
	Tcl_Obj *columnName = Tcl_DuplicateObj(columns[i]);

	Tcl_HashEntry *entryPtr = Tcl_CreateHashEntry(
	    &tv->tree.columnNames, Tcl_GetString(columnName), &isNew);
725
726
727
728
729
730
731
732

733
734
735
736
737

738
739
740
741
742
743
744
726
727
728
729
730
731
732

733
734
735
736
737

738
739
740
741
742
743
744
745







-
+




-
+







    if (Tcl_ListObjGetElements(interp,
	    tv->tree.displayColumnsObj, &ndcols, &dcolumns) != TCL_OK) {
	return TCL_ERROR;
    }

    if (!strcmp(Tcl_GetString(tv->tree.displayColumnsObj), "#all")) {
	ndcols = tv->tree.nColumns;
	displayColumns = ckalloc((ndcols+1) * sizeof(TreeColumn*));
	displayColumns = (TreeColumn **)ckalloc((ndcols+1) * sizeof(TreeColumn*));
	for (index = 0; index < ndcols; ++index) {
	    displayColumns[index+1] = tv->tree.columns + index;
	}
    } else {
	displayColumns = ckalloc((ndcols+1) * sizeof(TreeColumn*));
	displayColumns = (TreeColumn **)ckalloc((ndcols+1) * sizeof(TreeColumn*));
	for (index = 0; index < ndcols; ++index) {
	    displayColumns[index+1] = GetColumn(interp, tv, dcolumns[index]);
	    if (!displayColumns[index+1]) {
		ckfree(displayColumns);
		return TCL_ERROR;
	    }
	}
787
788
789
790
791
792
793
794
795


796
797
798
799
800
801
802
803
788
789
790
791
792
793
794


795
796

797
798
799
800
801
802
803







-
-
+
+
-







 * 	That is, don't bother changing column widths if the tree
 * 	is already scrolled or short.
 */
static int PickupSlack(Treeview *tv, int extra)
{
    int newSlack = tv->tree.slack + extra;

    if (   (newSlack < 0 && 0 <= tv->tree.slack)
	|| (newSlack > 0 && 0 >= tv->tree.slack))
    if ((newSlack < 0 && 0 <= tv->tree.slack)
	    || (newSlack > 0 && 0 >= tv->tree.slack)) {
    {
	tv->tree.slack = 0;
	return newSlack;
    } else {
	tv->tree.slack = newSlack;
	return 0;
    }
}
928
929
930
931
932
933
934
935

936
937
938
939
940
941
942
928
929
930
931
932
933
934

935
936
937
938
939
940
941
942







-
+







    | ButtonPressMask|ButtonReleaseMask
    | PointerMotionMask|ButtonMotionMask
    | VirtualEventMask
    ;

static void TreeviewBindEventProc(void *clientData, XEvent *event)
{
    Treeview *tv = clientData;
    Treeview *tv = (Treeview *)clientData;
    TreeItem *item = NULL;
    Ttk_TagSet tagset;

    /*
     * Figure out where to deliver the event.
     */
    switch (event->type)
980
981
982
983
984
985
986
987

988
989
990
991
992
993
994
980
981
982
983
984
985
986

987
988
989
990
991
992
993
994







-
+








/*------------------------------------------------------------------------
 * +++ Initialization and cleanup.
 */

static void TreeviewInitialize(Tcl_Interp *interp, void *recordPtr)
{
    Treeview *tv = recordPtr;
    Treeview *tv = (Treeview *)recordPtr;
    int unused;

    tv->tree.itemOptionTable =
	Tk_CreateOptionTable(interp, ItemOptionSpecs);
    tv->tree.columnOptionTable =
	Tk_CreateOptionTable(interp, ColumnOptionSpecs);
    tv->tree.headingOptionTable =
1047
1048
1049
1050
1051
1052
1053
1054

1055
1056
1057
1058
1059
1060
1061
1047
1048
1049
1050
1051
1052
1053

1054
1055
1056
1057
1058
1059
1060
1061







-
+







     */
    tv->tree.treeArea = tv->tree.headingArea = Ttk_MakeBox(0,0,0,0);
    tv->tree.slack = 0;
}

static void TreeviewCleanup(void *recordPtr)
{
    Treeview *tv = recordPtr;
    Treeview *tv = (Treeview *)recordPtr;

    Tk_DeleteEventHandler(tv->core.tkwin,
	    TreeviewBindEventMask,  TreeviewBindEventProc, tv);
    Tk_DeleteBindingTable(tv->tree.bindingTable);
    Ttk_DeleteTagTable(tv->tree.tagTable);

    if (tv->tree.itemLayout) Ttk_FreeLayout(tv->tree.itemLayout);
1080
1081
1082
1083
1084
1085
1086
1087

1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105



1106
1107
1108
1109
1110
1111
1112
1113
1080
1081
1082
1083
1084
1085
1086

1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102



1103
1104
1105

1106
1107
1108
1109
1110
1111
1112







-
+















-
-
-
+
+
+
-







 *
 * 	BUG: If user sets -columns and -displaycolumns, but -displaycolumns
 * 	has an error, the widget is left in an inconsistent state.
 */
static int
TreeviewConfigure(Tcl_Interp *interp, void *recordPtr, int mask)
{
    Treeview *tv = recordPtr;
    Treeview *tv = (Treeview *)recordPtr;
    unsigned showFlags = tv->tree.showFlags;

    if (mask & COLUMNS_CHANGED) {
	if (TreeviewInitColumns(interp, tv) != TCL_OK)
	    return TCL_ERROR;
	mask |= DCOLUMNS_CHANGED;
    }
    if (mask & DCOLUMNS_CHANGED) {
	if (TreeviewInitDisplayColumns(interp, tv) != TCL_OK)
	    return TCL_ERROR;
    }
    if (mask & SCROLLCMD_CHANGED) {
	TtkScrollbarUpdateRequired(tv->tree.xscrollHandle);
	TtkScrollbarUpdateRequired(tv->tree.yscrollHandle);
    }
    if (  (mask & SHOW_CHANGED)
	&& GetEnumSetFromObj(
		    interp,tv->tree.showObj,showStrings,&showFlags) != TCL_OK)
    if ((mask & SHOW_CHANGED)
	    && GetEnumSetFromObj(
		    interp,tv->tree.showObj,showStrings,&showFlags) != TCL_OK) {
    {
	return TCL_ERROR;
    }

    if (TtkCoreConfigure(interp, recordPtr, mask) != TCL_OK) {
	return TCL_ERROR;
    }

1127
1128
1129
1130
1131
1132
1133
1134

1135
1136
1137
1138
1139
1140
1141
1126
1127
1128
1129
1130
1131
1132

1133
1134
1135
1136
1137
1138
1139
1140







-
+







    int objc, Tcl_Obj *const objv[])
{
    Tk_SavedOptions savedOptions;
    int mask;
    Ttk_ImageSpec *newImageSpec = NULL;
    Ttk_TagSet newTagSet = NULL;

    if (Tk_SetOptions(interp, (ClientData)item, tv->tree.itemOptionTable,
    if (Tk_SetOptions(interp, item, tv->tree.itemOptionTable,
		objc, objv, tv->core.tkwin, &savedOptions, &mask)
		!= TCL_OK)
    {
	return TCL_ERROR;
    }

    /* Make sure that -values is a valid list:
1207
1208
1209
1210
1211
1212
1213
1214

1215
1216
1217
1218
1219
1220
1221
1206
1207
1208
1209
1210
1211
1212

1213
1214
1215
1216
1217
1218
1219
1220







-
+







static int ConfigureColumn(
    Tcl_Interp *interp, Treeview *tv, TreeColumn *column,
    int objc, Tcl_Obj *const objv[])
{
    Tk_SavedOptions savedOptions;
    int mask;

    if (Tk_SetOptions(interp, (ClientData)column,
    if (Tk_SetOptions(interp, column,
	    tv->tree.columnOptionTable, objc, objv, tv->core.tkwin,
	    &savedOptions,&mask) != TCL_OK)
    {
	return TCL_ERROR;
    }

    if (mask & READONLY_OPTION) {
1253
1254
1255
1256
1257
1258
1259
1260

1261
1262
1263
1264
1265
1266
1267
1252
1253
1254
1255
1256
1257
1258

1259
1260
1261
1262
1263
1264
1265
1266







-
+







static int ConfigureHeading(
    Tcl_Interp *interp, Treeview *tv, TreeColumn *column,
    int objc, Tcl_Obj *const objv[])
{
    Tk_SavedOptions savedOptions;
    int mask;

    if (Tk_SetOptions(interp, (ClientData)column,
    if (Tk_SetOptions(interp, column,
	    tv->tree.headingOptionTable, objc, objv, tv->core.tkwin,
	    &savedOptions,&mask) != TCL_OK)
    {
	return TCL_ERROR;
    }

    /* @@@ testing ... */
1499
1500
1501
1502
1503
1504
1505
1506

1507
1508
1509
1510
1511
1512
1513
1498
1499
1500
1501
1502
1503
1504

1505
1506
1507
1508
1509
1510
1511
1512







-
+







    REGION_NOTHING = 0,
    REGION_HEADING,
    REGION_SEPARATOR,
    REGION_TREE,
    REGION_CELL
} TreeRegion;

static const char *regionStrings[] = {
static const char *const regionStrings[] = {
    "nothing", "heading", "separator", "tree", "cell", 0
};

static TreeRegion IdentifyRegion(Treeview *tv, int x, int y)
{
    int x1 = 0, colno;

1559
1560
1561
1562
1563
1564
1565
1566

1567
1568
1569
1570
1571
1572
1573
1558
1559
1560
1561
1562
1563
1564

1565
1566
1567
1568
1569
1570
1571
1572







-
+








/* + TreeviewGetLayout --
 * 	GetLayout() widget hook.
 */
static Ttk_Layout TreeviewGetLayout(
    Tcl_Interp *interp, Ttk_Theme themePtr, void *recordPtr)
{
    Treeview *tv = recordPtr;
    Treeview *tv = (Treeview *)recordPtr;
    Ttk_Layout treeLayout = TtkWidgetGetLayout(interp, themePtr, recordPtr);
    Tcl_Obj *objPtr;
    int unused;

    if (!(
	treeLayout
     && GetSublayout(interp, themePtr, treeLayout, ".Item",
1608
1609
1610
1611
1612
1613
1614
1615

1616
1617
1618
1619
1620
1621
1622
1607
1608
1609
1610
1611
1612
1613

1614
1615
1616
1617
1618
1619
1620
1621







-
+







 * Side effects:
 * 	Computes headingArea and treeArea.
 * 	Computes subtree height.
 * 	Invokes scroll callbacks.
 */
static void TreeviewDoLayout(void *clientData)
{
    Treeview *tv = clientData;
    Treeview *tv = (Treeview *)clientData;
    int visibleRows;

    Ttk_PlaceLayout(tv->core.layout,tv->core.state,Ttk_WinBox(tv->core.tkwin));
    tv->tree.treeArea = Ttk_ClientRegion(tv->core.layout, "treearea");

    ResizeColumns(tv, tv->tree.treeArea.width);

1642
1643
1644
1645
1646
1647
1648
1649

1650
1651
1652
1653
1654
1655
1656
1641
1642
1643
1644
1645
1646
1647

1648
1649
1650
1651
1652
1653
1654
1655







-
+








/* + TreeviewSize --
 * 	SizeProc() widget hook.  Size is determined by
 * 	-height option and column widths.
 */
static int TreeviewSize(void *clientData, int *widthPtr, int *heightPtr)
{
    Treeview *tv = clientData;
    Treeview *tv = (Treeview *)clientData;
    int nRows, padHeight, padWidth;

    Ttk_LayoutSize(tv->core.layout, tv->core.state, &padWidth, &padHeight);
    Tcl_GetIntFromObj(NULL, tv->tree.heightObj, &nRows);

    *widthPtr = padWidth + TreeWidth(tv);
    *heightPtr = padHeight + tv->tree.rowHeight * nRows;
1775
1776
1777
1778
1779
1780
1781
1782

1783
1784
1785
1786
1787
1788
1789
1774
1775
1776
1777
1778
1779
1780

1781
1782
1783
1784
1785
1786
1787
1788







-
+







    if (tv->tree.showFlags & SHOW_TREE) {
	int indent = depth * tv->tree.indent;
	int colwidth = tv->tree.column0.width;
	Ttk_Box parcel = Ttk_MakeBox(
		x+indent, y, colwidth-indent, rowHeight);
	if (item->textObj) { displayItem.textObj = item->textObj; }
	if (item->imageObj) { displayItem.imageObj = item->imageObj; }
	/* ??? displayItem.anchorObj = 0; <<NOTE-ANCHOR>> */
        displayItem.anchorObj = tv->tree.column0.anchorObj;
	DisplayLayout(tv->tree.itemLayout, &displayItem, state, parcel, d);
	x += colwidth;
    }

    /* Draw data cells:
     */
    DrawCells(tv, item, &displayItem, d, x, y);
1830
1831
1832
1833
1834
1835
1836
1837

1838
1839
1840
1841
1842
1843
1844
1829
1830
1831
1832
1833
1834
1835

1836
1837
1838
1839
1840
1841
1842
1843







-
+







}

/* + TreeviewDisplay --
 * 	Display() widget hook.  Draw the widget contents.
 */
static void TreeviewDisplay(void *clientData, Drawable d)
{
    Treeview *tv = clientData;
    Treeview *tv = (Treeview *)clientData;

    Ttk_DrawLayout(tv->core.layout, tv->core.state, d);
    if (tv->tree.showFlags & SHOW_HEADINGS) {
	DrawHeadings(tv, d);
    }
    DrawForest(tv, tv->tree.root->children, d, 0,0);
}
1944
1945
1946
1947
1948
1949
1950
1951

1952
1953
1954
1955
1956
1957
1958
1943
1944
1945
1946
1947
1948
1949

1950
1951
1952
1953
1954
1955
1956
1957







-
+








/* + $tv children $item ?newchildren? --
 * 	Return the list of children associated with $item
 */
static int TreeviewChildrenCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Treeview *tv = recordPtr;
    Treeview *tv = (Treeview *)recordPtr;
    TreeItem *item;
    Tcl_Obj *result;

    if (objc < 3 || objc > 4) {
	Tcl_WrongNumArgs(interp, 2, objv, "item ?newchildren?");
	return TCL_ERROR;
    }
2024
2025
2026
2027
2028
2029
2030
2031

2032
2033
2034
2035
2036
2037
2038
2023
2024
2025
2026
2027
2028
2029

2030
2031
2032
2033
2034
2035
2036
2037







-
+








/* + $tv parent $item --
 * 	Return the item ID of $item's parent.
 */
static int TreeviewParentCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Treeview *tv = recordPtr;
    Treeview *tv = (Treeview *)recordPtr;
    TreeItem *item;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "item");
	return TCL_ERROR;
    }
    item = FindItem(interp, tv, objv[2]);
2052
2053
2054
2055
2056
2057
2058
2059

2060
2061
2062
2063
2064
2065
2066
2051
2052
2053
2054
2055
2056
2057

2058
2059
2060
2061
2062
2063
2064
2065







-
+








/* + $tv next $item
 * 	Return the ID of $item's next sibling.
 */
static int TreeviewNextCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Treeview *tv = recordPtr;
    Treeview *tv = (Treeview *)recordPtr;
    TreeItem *item;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "item");
	return TCL_ERROR;
    }
    item = FindItem(interp, tv, objv[2]);
2077
2078
2079
2080
2081
2082
2083
2084

2085
2086
2087
2088
2089
2090
2091
2076
2077
2078
2079
2080
2081
2082

2083
2084
2085
2086
2087
2088
2089
2090







-
+








/* + $tv prev $item
 * 	Return the ID of $item's previous sibling.
 */
static int TreeviewPrevCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Treeview *tv = recordPtr;
    Treeview *tv = (Treeview *)recordPtr;
    TreeItem *item;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "item");
	return TCL_ERROR;
    }
    item = FindItem(interp, tv, objv[2]);
2102
2103
2104
2105
2106
2107
2108
2109

2110
2111

2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127

2128
2129
2130
2131
2132
2133
2134
2135
2136
2137

2138
2139
2140
2141
2142
2143
2144
2145
2146

2147
2148
2149
2150
2151
2152
2153
2154
2155
2156

2157
2158
2159
2160
2161
2162
2163
2101
2102
2103
2104
2105
2106
2107

2108
2109

2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125

2126
2127
2128
2129
2130
2131
2132
2133
2134
2135

2136
2137
2138
2139
2140
2141
2142
2143
2144

2145
2146
2147
2148
2149
2150
2151
2152
2153
2154

2155
2156
2157
2158
2159
2160
2161
2162







-
+

-
+















-
+









-
+








-
+









-
+








/* + $tv index $item --
 * 	Return the index of $item within its parent.
 */
static int TreeviewIndexCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Treeview *tv = recordPtr;
    Treeview *tv = (Treeview *)recordPtr;
    TreeItem *item;
    int index = 0;
    TkSizeT index = 0;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "item");
	return TCL_ERROR;
    }
    item = FindItem(interp, tv, objv[2]);
    if (!item) {
	return TCL_ERROR;
    }

    while (item->prev) {
	++index;
	item = item->prev;
    }

    Tcl_SetObjResult(interp, Tcl_NewIntObj(index));
    Tcl_SetObjResult(interp, TkNewIndexObj(index));
    return TCL_OK;
}

/* + $tv exists $itemid --
 * 	Test if the specified item id is present in the tree.
 */
static int TreeviewExistsCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Treeview *tv = recordPtr;
    Treeview *tv = (Treeview *)recordPtr;
    Tcl_HashEntry *entryPtr;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "itemid");
	return TCL_ERROR;
    }

    entryPtr = Tcl_FindHashEntry(&tv->tree.items, Tcl_GetString(objv[2]));
    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(entryPtr != 0));
    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(entryPtr != 0));
    return TCL_OK;
}

/* + $tv bbox $itemid ?$column? --
 * 	Return bounding box [x y width height] of specified item.
 */
static int TreeviewBBoxCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Treeview *tv = recordPtr;
    Treeview *tv = (Treeview *)recordPtr;
    TreeItem *item = 0;
    TreeColumn *column = 0;
    Ttk_Box bbox;

    if (objc < 3 || objc > 4) {
	Tcl_WrongNumArgs(interp, 2, objv, "itemid ?column");
	return TCL_ERROR;
2192
2193
2194
2195
2196
2197
2198

2199
2200
2201
2202
2203


2204
2205
2206
2207
2208
2209
2210
2211
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201


2202
2203

2204
2205
2206
2207
2208
2209
2210







+



-
-
+
+
-







{
    const char *what = "nothing", *detail = NULL;
    TreeItem *item = 0;
    Tcl_Obj *result;
    int dColumnNumber;
    char dcolbuf[16];
    int x, y, x1;
    (void)objc;

    /* ASSERT: objc == 4 */

    if (   Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK
	|| Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK
    if (Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK
	    || Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK) {
    ) {
	return TCL_ERROR;
    }

    dColumnNumber = IdentifyDisplayColumn(tv, x, &x1);
    if (dColumnNumber < 0) {
	goto done;
    }
2261
2262
2263
2264
2265
2266
2267
2268

2269
2270
2271
2272

2273
2274
2275
2276
2277
2278
2279
2260
2261
2262
2263
2264
2265
2266

2267
2268
2269
2270

2271
2272
2273
2274
2275
2276
2277
2278







-
+



-
+







/* + $tv identify $component $x $y --
 * 	Identify the component at position x,y.
 */

static int TreeviewIdentifyCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    static const char *submethodStrings[] =
    static const char *const submethodStrings[] =
	 { "region", "item", "column", "row", "element", NULL };
    enum { I_REGION, I_ITEM, I_COLUMN, I_ROW, I_ELEMENT };

    Treeview *tv = recordPtr;
    Treeview *tv = (Treeview *)recordPtr;
    int submethod;
    int x, y;

    TreeRegion region;
    Ttk_Box bbox;
    TreeItem *item;
    TreeColumn *column = 0;
2367
2368
2369
2370
2371
2372
2373
2374

2375
2376
2377
2378

2379
2380
2381
2382
2383
2384
2385
2366
2367
2368
2369
2370
2371
2372

2373
2374
2375
2376

2377
2378
2379
2380
2381
2382
2383
2384







-
+



-
+








/* + $tv item $item ?options ....?
 * 	Query or configure item options.
 */
static int TreeviewItemCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Treeview *tv = recordPtr;
    Treeview *tv = (Treeview *)recordPtr;
    TreeItem *item;

    if (objc < 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "item ?option ?value??...");
	Tcl_WrongNumArgs(interp, 2, objv, "item ?-option ?value??...");
	return TCL_ERROR;
    }
    if (!(item = FindItem(interp, tv, objv[2]))) {
	return TCL_ERROR;
    }

    if (objc == 3) {
2395
2396
2397
2398
2399
2400
2401
2402

2403
2404
2405
2406
2407
2408
2409
2394
2395
2396
2397
2398
2399
2400

2401
2402
2403
2404
2405
2406
2407
2408







-
+








/* + $tv column column ?options ....?
 * 	Column data accessor
 */
static int TreeviewColumnCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Treeview *tv = recordPtr;
    Treeview *tv = (Treeview *)recordPtr;
    TreeColumn *column;

    if (objc < 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "column -option value...");
	return TCL_ERROR;
    }
    if (!(column = FindColumn(interp, tv, objv[2]))) {
2423
2424
2425
2426
2427
2428
2429
2430

2431
2432
2433
2434
2435
2436
2437
2422
2423
2424
2425
2426
2427
2428

2429
2430
2431
2432
2433
2434
2435
2436







-
+








/* + $tv heading column ?options ....?
 * 	Heading data accessor
 */
static int TreeviewHeadingCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Treeview *tv = recordPtr;
    Treeview *tv = (Treeview *)recordPtr;
    Tk_OptionTable optionTable = tv->tree.headingOptionTable;
    Tk_Window tkwin = tv->core.tkwin;
    TreeColumn *column;

    if (objc < 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "column -option value...");
	return TCL_ERROR;
2453
2454
2455
2456
2457
2458
2459
2460

2461
2462
2463
2464
2465
2466
2467
2452
2453
2454
2455
2456
2457
2458

2459
2460
2461
2462
2463
2464
2465
2466







-
+








/* + $tv set $item ?$column ?value??
 * 	Query or configure cell values
 */
static int TreeviewSetCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Treeview *tv = recordPtr;
    Treeview *tv = (Treeview *)recordPtr;
    TreeItem *item;
    TreeColumn *column;
    int columnNumber;

    if (objc < 3 || objc > 5) {
	Tcl_WrongNumArgs(interp, 2, objv, "item ?column ?value??");
	return TCL_ERROR;
2547
2548
2549
2550
2551
2552
2553
2554

2555
2556
2557
2558
2559
2560
2561
2546
2547
2548
2549
2550
2551
2552

2553
2554
2555
2556
2557
2558
2559
2560







-
+








/* + $tv insert $parent $index ?-id id? ?-option value ...?
 * 	Insert a new item.
 */
static int TreeviewInsertCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Treeview *tv = recordPtr;
    Treeview *tv = (Treeview *)recordPtr;
    TreeItem *parent, *sibling, *newItem;
    Tcl_HashEntry *entryPtr;
    int isNew;

    if (objc < 4) {
	Tcl_WrongNumArgs(interp, 2, objv, "parent index ?-id id? -options...");
	return TCL_ERROR;
2628
2629
2630
2631
2632
2633
2634
2635

2636
2637
2638
2639
2640
2641
2642
2627
2628
2629
2630
2631
2632
2633

2634
2635
2636
2637
2638
2639
2640
2641







-
+








/* + $tv detach $item --
 * 	Unlink $item from the tree.
 */
static int TreeviewDetachCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Treeview *tv = recordPtr;
    Treeview *tv = (Treeview *)recordPtr;
    TreeItem **items;
    int i;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "item");
	return TCL_ERROR;
    }
2675
2676
2677
2678
2679
2680
2681
2682

2683
2684
2685
2686
2687
2688
2689
2674
2675
2676
2677
2678
2679
2680

2681
2682
2683
2684
2685
2686
2687
2688







-
+







 *	in the list of items to delete (either directly or as a descendant
 *	of a previously deleted item.)
 */

static int TreeviewDeleteCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Treeview *tv = recordPtr;
    Treeview *tv = (Treeview *)recordPtr;
    TreeItem **items, *delq;
    int i, selItemDeleted = 0;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "items");
	return TCL_ERROR;
    }
2724
2725
2726
2727
2728
2729
2730
2731

2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743

2744
2745
2746
2747
2748
2749
2750
2751
2752


2753
2754
2755
2756
2757
2758
2759
2760
2723
2724
2725
2726
2727
2728
2729

2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741

2742
2743
2744
2745
2746
2747
2748
2749


2750
2751

2752
2753
2754
2755
2756
2757
2758







-
+











-
+







-
-
+
+
-







	    tv->tree.endPtr = 0;
	FreeItem(delq);
	delq = next;
    }

    ckfree(items);
    if (selItemDeleted) {
        TtkSendVirtualEvent(tv->core.tkwin, "TreeviewSelect");
        Tk_SendVirtualEvent(tv->core.tkwin, "TreeviewSelect", NULL);
    }
    TtkRedisplayWidget(&tv->core);
    return TCL_OK;
}

/* + $tv move $item $parent $index
 * 	Move $item to the specified $index in $parent's child list.
 */
static int TreeviewMoveCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Treeview *tv = recordPtr;
    Treeview *tv = (Treeview *)recordPtr;
    TreeItem *item, *parent;
    TreeItem *sibling;

    if (objc != 5) {
	Tcl_WrongNumArgs(interp, 2, objv, "item parent index");
	return TCL_ERROR;
    }
    if (   (item = FindItem(interp, tv, objv[2])) == 0
	|| (parent = FindItem(interp, tv, objv[3])) == 0)
    if ((item = FindItem(interp, tv, objv[2])) == 0
	    || (parent = FindItem(interp, tv, objv[3])) == 0) {
    {
	return TCL_ERROR;
    }

    /* Locate previous sibling based on $index:
     */
    if (!strcmp(Tcl_GetString(objv[4]), "end")) {
	sibling = EndPosition(tv, parent);
2799
2800
2801
2802
2803
2804
2805
2806

2807
2808
2809
2810
2811
2812
2813

2814
2815
2816
2817
2818
2819
2820
2821
2822
2823

2824
2825
2826
2827
2828
2829
2830
2797
2798
2799
2800
2801
2802
2803

2804
2805
2806
2807
2808
2809
2810

2811
2812
2813
2814
2815
2816
2817
2818
2819
2820

2821
2822
2823
2824
2825
2826
2827
2828







-
+






-
+









-
+







/*------------------------------------------------------------------------
 * +++ Widget commands -- scrolling
 */

static int TreeviewXViewCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Treeview *tv = recordPtr;
    Treeview *tv = (Treeview *)recordPtr;
    return TtkScrollviewCommand(interp, objc, objv, tv->tree.xscrollHandle);
}

static int TreeviewYViewCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Treeview *tv = recordPtr;
    Treeview *tv = (Treeview *)recordPtr;
    return TtkScrollviewCommand(interp, objc, objv, tv->tree.yscrollHandle);
}

/* $tree see $item --
 * 	Ensure that $item is visible.
 */
static int TreeviewSeeCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Treeview *tv = recordPtr;
    Treeview *tv = (Treeview *)recordPtr;
    TreeItem *item, *parent;
    int rowNumber;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "item");
	return TCL_ERROR;
    }
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2836
2837
2838
2839
2840
2841
2842

2843
2844
2845
2846
2847
2848
2849







-







	if (!(parent->state & TTK_STATE_OPEN)) {
	    parent->openObj = unshareObj(parent->openObj);
	    Tcl_SetBooleanObj(parent->openObj, 1);
	    parent->state |= TTK_STATE_OPEN;
	    TtkRedisplayWidget(&tv->core);
	}
    }
    tv->tree.yscroll.total = CountRows(tv->tree.root) - 1;

    /* Make sure item is visible:
     */
    rowNumber = RowNumber(tv, item);
    if (rowNumber < tv->tree.yscroll.first) {
	TtkScrollTo(tv->tree.yscrollHandle, rowNumber, 1);
    } else if (rowNumber >= tv->tree.yscroll.last) {
2863
2864
2865
2866
2867
2868
2869
2870

2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882


2883
2884
2885
2886
2887
2888
2889
2890
2860
2861
2862
2863
2864
2865
2866

2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877


2878
2879

2880
2881
2882
2883
2884
2885
2886







-
+










-
-
+
+
-








/* + $tree drag $column $newX --
 * 	Set right edge of display column $column to x position $X
 */
static int TreeviewDragCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Treeview *tv = recordPtr;
    Treeview *tv = (Treeview *)recordPtr;
    int left = tv->tree.treeArea.x - tv->tree.xscroll.first;
    int i = FirstColumn(tv);
    TreeColumn *column;
    int newx;

    if (objc != 4) {
	Tcl_WrongNumArgs(interp, 2, objv, "column xposition");
	return TCL_ERROR;
    }

    if (  (column = FindColumn(interp, tv, objv[2])) == 0
        || Tcl_GetIntFromObj(interp, objv[3], &newx) != TCL_OK)
    if ((column = FindColumn(interp, tv, objv[2])) == 0
	    || Tcl_GetIntFromObj(interp, objv[3], &newx) != TCL_OK) {
    {
	return TCL_ERROR;
    }

    for (;i < tv->tree.nDisplayColumns; ++i) {
	TreeColumn *c = tv->tree.displayColumns[i];
	int right = left + c->width;
	if (c == column) {
2900
2901
2902
2903
2904
2905
2906
2907

2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927

2928
2929
2930
2931
2932
2933
2934
2896
2897
2898
2899
2900
2901
2902

2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922

2923
2924
2925
2926
2927
2928
2929
2930







-
+



















-
+







    Tcl_SetErrorCode(interp, "TTK", "TREE", "COLUMN_INVISIBLE", NULL);
    return TCL_ERROR;
}

static int TreeviewDropCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Treeview *tv = recordPtr;
    Treeview *tv = (Treeview *)recordPtr;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "drop");
	return TCL_ERROR;
    }
    ResizeColumns(tv, TreeWidth(tv));
    TtkRedisplayWidget(&tv->core);
    return TCL_OK;
}

/*------------------------------------------------------------------------
 * +++ Widget commands -- focus and selection
 */

/* + $tree focus ?item?
 */
static int TreeviewFocusCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Treeview *tv = recordPtr;
    Treeview *tv = (Treeview *)recordPtr;

    if (objc == 2) {
	if (tv->tree.focus) {
	    Tcl_SetObjResult(interp, ItemID(tv, tv->tree.focus));
	}
	return TCL_OK;
    } else if (objc == 3) {
2948
2949
2950
2951
2952
2953
2954
2955

2956
2957
2958
2959

2960
2961
2962
2963
2964
2965

2966
2967
2968
2969
2970
2971
2972
2944
2945
2946
2947
2948
2949
2950

2951
2952
2953
2954

2955
2956
2957
2958
2959
2960

2961
2962
2963
2964
2965
2966
2967
2968







-
+



-
+





-
+







 */
static int TreeviewSelectionCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    enum {
	SELECTION_SET, SELECTION_ADD, SELECTION_REMOVE, SELECTION_TOGGLE
    };
    static const char *selopStrings[] = {
    static const char *const selopStrings[] = {
	"set", "add", "remove", "toggle", NULL
    };

    Treeview *tv = recordPtr;
    Treeview *tv = (Treeview *)recordPtr;
    int selop, i;
    TreeItem *item, **items;

    if (objc == 2) {
	Tcl_Obj *result = Tcl_NewListObj(0,0);
	for (item = tv->tree.root->children; item; item=NextPreorder(item)) {
	for (item = tv->tree.root->children; item; item = NextPreorder(item)) {
	    if (item->state & TTK_STATE_SELECTED)
		Tcl_ListObjAppendElement(NULL, result, ItemID(tv, item));
	}
	Tcl_SetObjResult(interp, result);
	return TCL_OK;
    }

2984
2985
2986
2987
2988
2989
2990
2991

2992
2993
2994
2995
2996
2997
2998
2980
2981
2982
2983
2984
2985
2986

2987
2988
2989
2990
2991
2992
2993
2994







-
+







    if (!items) {
	return TCL_ERROR;
    }

    switch (selop)
    {
	case SELECTION_SET:
	    for (item=tv->tree.root; item; item=NextPreorder(item)) {
	    for (item=tv->tree.root; item; item = NextPreorder(item)) {
		item->state &= ~TTK_STATE_SELECTED;
	    }
	    /*FALLTHRU*/
	case SELECTION_ADD:
	    for (i=0; items[i]; ++i) {
		items[i]->state |= TTK_STATE_SELECTED;
	    }
3006
3007
3008
3009
3010
3011
3012
3013

3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028

3029
3030
3031
3032
3033
3034
3035
3002
3003
3004
3005
3006
3007
3008

3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023

3024
3025
3026
3027
3028
3029
3030
3031







-
+














-
+







	    for (i=0; items[i]; ++i) {
		items[i]->state ^= TTK_STATE_SELECTED;
	    }
	    break;
    }

    ckfree(items);
    TtkSendVirtualEvent(tv->core.tkwin, "TreeviewSelect");
    Tk_SendVirtualEvent(tv->core.tkwin, "TreeviewSelect", NULL);
    TtkRedisplayWidget(&tv->core);

    return TCL_OK;
}

/*------------------------------------------------------------------------
 * +++ Widget commands -- tags and bindings.
 */

/* + $tv tag bind $tag ?$sequence ?$script??
 */
static int TreeviewTagBindCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Treeview *tv = recordPtr;
    Treeview *tv = (Treeview *)recordPtr;
    Ttk_TagTable tagTable = tv->tree.tagTable;
    Tk_BindingTable bindingTable = tv->tree.bindingTable;
    Ttk_Tag tag;

    if (objc < 4 || objc > 6) {
    	Tcl_WrongNumArgs(interp, 3, objv, "tagName ?sequence? ?script?");
	return TCL_ERROR;
3074
3075
3076
3077
3078
3079
3080
3081

3082
3083
3084
3085
3086
3087
3088
3070
3071
3072
3073
3074
3075
3076

3077
3078
3079
3080
3081
3082
3083
3084







-
+







}

/* + $tv tag configure $tag ?-option ?value -option value...??
 */
static int TreeviewTagConfigureCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Treeview *tv = recordPtr;
    Treeview *tv = (Treeview *)recordPtr;
    Ttk_TagTable tagTable = tv->tree.tagTable;
    Ttk_Tag tag;

    if (objc < 4) {
    	Tcl_WrongNumArgs(interp, 3, objv, "tagName ?-option ?value ...??");
	return TCL_ERROR;
    }
3099
3100
3101
3102
3103
3104
3105




























3106
3107
3108
3109
3110
3111
3112

3113
3114
3115
3116
3117
3118
3119
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135

3136
3137
3138
3139
3140
3141
3142
3143







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






-
+







	} /* else */
	return TCL_ERROR;
    }
    /* else */
    TtkRedisplayWidget(&tv->core);
    return Ttk_ConfigureTag(interp, tagTable, tag, objc - 4, objv + 4);
}

/* + $tv tag delete $tag
 */
static int TreeviewTagDeleteCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Treeview *tv = (Treeview *)recordPtr;
    Ttk_TagTable tagTable = tv->tree.tagTable;
    TreeItem *item = tv->tree.root;
    Ttk_Tag tag;

    if (objc != 4) {
	Tcl_WrongNumArgs(interp, 3, objv, "tagName");
	return TCL_ERROR;
    }

    tag = Ttk_GetTagFromObj(tagTable, objv[3]);
    /* remove the tag from all items */
    while (item) {
	RemoveTag(item, tag);
	item = NextPreorder(item);
    }
    /* then remove the tag from the tag table */
    Ttk_DeleteTagFromTable(tagTable, tag);
    TtkRedisplayWidget(&tv->core);

    return TCL_OK;
}

/* + $tv tag has $tag ?$item?
 */
static int TreeviewTagHasCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Treeview *tv = recordPtr;
    Treeview *tv = (Treeview *)recordPtr;

    if (objc == 4) {	/* Return list of all items with tag */
	Ttk_Tag tag = Ttk_GetTagFromObj(tv->tree.tagTable, objv[3]);
	TreeItem *item = tv->tree.root;
	Tcl_Obj *result = Tcl_NewListObj(0,0);

	while (item) {
3128
3129
3130
3131
3132
3133
3134
3135

3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148

3149
3150
3151
3152
3153
3154
3155
3152
3153
3154
3155
3156
3157
3158

3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171

3172
3173
3174
3175
3176
3177
3178
3179







-
+












-
+







    } else if (objc == 5) {	/* Test if item has specified tag */
	Ttk_Tag tag = Ttk_GetTagFromObj(tv->tree.tagTable, objv[3]);
	TreeItem *item = FindItem(interp, tv, objv[4]);
	if (!item) {
	    return TCL_ERROR;
	}
	Tcl_SetObjResult(interp,
	    Tcl_NewBooleanObj(Ttk_TagSetContains(item->tagset, tag)));
	    Tcl_NewWideIntObj(Ttk_TagSetContains(item->tagset, tag)));
	return TCL_OK;
    } else {
    	Tcl_WrongNumArgs(interp, 3, objv, "tagName ?item?");
	return TCL_ERROR;
    }
}

/* + $tv tag names $tag
 */
static int TreeviewTagNamesCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Treeview *tv = recordPtr;
    Treeview *tv = (Treeview *)recordPtr;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 3, objv, "");
	return TCL_ERROR;
    }

    return Ttk_EnumerateTags(interp, tv->tree.tagTable);
3165
3166
3167
3168
3169
3170
3171
3172

3173
3174
3175
3176
3177
3178
3179
3189
3190
3191
3192
3193
3194
3195

3196
3197
3198
3199
3200
3201
3202
3203







-
+







	Tcl_IncrRefCount(item->tagsObj);
    }
}

static int TreeviewTagAddCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Treeview *tv = recordPtr;
    Treeview *tv = (Treeview *)recordPtr;
    Ttk_Tag tag;
    TreeItem **items;
    int i;

    if (objc != 5) {
	Tcl_WrongNumArgs(interp, 3, objv, "tagName items");
	return TCL_ERROR;
3205
3206
3207
3208
3209
3210
3211
3212

3213
3214
3215
3216
3217
3218
3219
3229
3230
3231
3232
3233
3234
3235

3236
3237
3238
3239
3240
3241
3242
3243







-
+







	Tcl_IncrRefCount(item->tagsObj);
    }
}

static int TreeviewTagRemoveCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    Treeview *tv = recordPtr;
    Treeview *tv = (Treeview *)recordPtr;
    Ttk_Tag tag;

    if (objc < 4) {
	Tcl_WrongNumArgs(interp, 3, objv, "tagName items");
	return TCL_ERROR;
    }

3229
3230
3231
3232
3233
3234
3235
3236

3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248

3249
3250
3251
3252
3253
3254
3255
3253
3254
3255
3256
3257
3258
3259

3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280







-
+












+







	for (i=0; items[i]; ++i) {
	    RemoveTag(items[i], tag);
	}
    } else if (objc == 4) {
	TreeItem *item = tv->tree.root;
	while (item) {
	    RemoveTag(item, tag);
	    item=NextPreorder(item);
	    item = NextPreorder(item);
	}
    }

    TtkRedisplayWidget(&tv->core);

    return TCL_OK;
}

static const Ttk_Ensemble TreeviewTagCommands[] = {
    { "add",		TreeviewTagAddCommand,0 },
    { "bind",		TreeviewTagBindCommand,0 },
    { "configure",	TreeviewTagConfigureCommand,0 },
    { "delete",		TreeviewTagDeleteCommand,0 },
    { "has",		TreeviewTagHasCommand,0 },
    { "names",		TreeviewTagNamesCommand,0 },
    { "remove",		TreeviewTagRemoveCommand,0 },
    { 0,0,0 }
};

/*------------------------------------------------------------------------
3266
3267
3268
3269
3270
3271
3272
3273
3274

3275
3276
3277
3278
3279
3280
3281
3282
3283

3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294

3295
3296
3297
3298
3299
3300
3301
3291
3292
3293
3294
3295
3296
3297

3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319

3320
3321
3322
3323
3324
3325
3326
3327







-

+









+










-
+







    { "drag",   	TreeviewDragCommand,0 },
    { "drop",   	TreeviewDropCommand,0 },
    { "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 }
};

/*------------------------------------------------------------------------
 * +++ Widget definition.
 */

static WidgetSpec TreeviewWidgetSpec = {
static const WidgetSpec TreeviewWidgetSpec = {
    "Treeview",			/* className */
    sizeof(Treeview),   	/* recordSize */
    TreeviewOptionSpecs,	/* optionSpecs */
    TreeviewCommands,   	/* subcommands */
    TreeviewInitialize,   	/* initializeProc */
    TreeviewCleanup,		/* cleanupProc */
    TreeviewConfigure,    	/* configureProc */
3317
3318
3319
3320
3321
3322
3323
3324
3325

3326
3327
3328
3329
3330
3331
3332
3343
3344
3345
3346
3347
3348
3349


3350
3351
3352
3353
3354
3355
3356
3357







-
-
+







	TTK_GROUP("Treeview.padding", TTK_FILL_BOTH,
	    TTK_NODE("Treeview.treearea", TTK_FILL_BOTH))))

TTK_LAYOUT("Item",
    TTK_GROUP("Treeitem.padding", TTK_FILL_BOTH,
	TTK_NODE("Treeitem.indicator", TTK_PACK_LEFT)
	TTK_NODE("Treeitem.image", TTK_PACK_LEFT)
	TTK_GROUP("Treeitem.focus", TTK_PACK_LEFT,
	    TTK_NODE("Treeitem.text", TTK_PACK_LEFT))))
	TTK_NODE("Treeitem.text", TTK_FILL_BOTH)))

TTK_LAYOUT("Cell",
    TTK_GROUP("Treedata.padding", TTK_FILL_BOTH,
	TTK_NODE("Treeitem.text", TTK_FILL_BOTH)))

TTK_LAYOUT("Heading",
    TTK_NODE("Treeheading.cell", TTK_FILL_BOTH)
3346
3347
3348
3349
3350
3351
3352
3353

3354
3355

3356
3357

3358
3359
3360


3361
3362
3363
3364

3365
3366
3367

3368
3369


3370
3371
3372
3373
3374
3375
3376
3377
3378
3379

3380
3381
3382

3383
3384
3385
3386
3387

3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405

3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422

3423
3424

3425
3426
3427


3428
3429
3430
3431

3432
3433
3434

3435
3436



3437
3438
3439
3440
3441

3442
3443
3444
3445
3446
3447
3448
3371
3372
3373
3374
3375
3376
3377

3378
3379

3380
3381

3382
3383


3384
3385
3386
3387
3388

3389
3390
3391

3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405

3406
3407
3408

3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432

3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449

3450
3451

3452
3453


3454
3455
3456
3457
3458

3459
3460
3461

3462
3463
3464
3465
3466
3467
3468
3469
3470
3471

3472
3473
3474
3475
3476
3477
3478
3479







-
+

-
+

-
+

-
-
+
+



-
+


-
+


+
+









-
+


-
+





+

















-
+
















-
+

-
+

-
-
+
+



-
+


-
+


+
+
+




-
+








typedef struct {
    Tcl_Obj *colorObj;
    Tcl_Obj *sizeObj;
    Tcl_Obj *marginsObj;
} TreeitemIndicator;

static Ttk_ElementOptionSpec TreeitemIndicatorOptions[] = {
static const Ttk_ElementOptionSpec TreeitemIndicatorOptions[] = {
    { "-foreground", TK_OPTION_COLOR,
	Tk_Offset(TreeitemIndicator,colorObj), DEFAULT_FOREGROUND },
	offsetof(TreeitemIndicator,colorObj), DEFAULT_FOREGROUND },
    { "-indicatorsize", TK_OPTION_PIXELS,
	Tk_Offset(TreeitemIndicator,sizeObj), "12" },
	offsetof(TreeitemIndicator,sizeObj), "12" },
    { "-indicatormargins", TK_OPTION_STRING,
	Tk_Offset(TreeitemIndicator,marginsObj), "2 2 4 2" },
    { NULL, 0, 0, NULL }
	offsetof(TreeitemIndicator,marginsObj), "2 2 4 2" },
    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
};

static void TreeitemIndicatorSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    TreeitemIndicator *indicator = elementRecord;
    TreeitemIndicator *indicator = (TreeitemIndicator *)elementRecord;
    Ttk_Padding margins;
    int size = 0;
    (void)dummy;
    (void)paddingPtr;

    Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginsObj, &margins);
    Tk_GetPixelsFromObj(NULL, tkwin, indicator->sizeObj, &size);

    *widthPtr = size + Ttk_PaddingWidth(margins);
    *heightPtr = size + Ttk_PaddingHeight(margins);
}

static void TreeitemIndicatorDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, Ttk_State state)
{
    TreeitemIndicator *indicator = elementRecord;
    TreeitemIndicator *indicator = (TreeitemIndicator *)elementRecord;
    ArrowDirection direction =
	(state & TTK_STATE_OPEN) ? ARROW_DOWN : ARROW_RIGHT;
    Ttk_Padding margins;
    XColor *borderColor = Tk_GetColorFromObj(tkwin, indicator->colorObj);
    XGCValues gcvalues; GC gc; unsigned mask;
    (void)dummy;

    if (state & TTK_STATE_LEAF) /* don't draw anything */
	return;

    Ttk_GetPaddingFromObj(NULL,tkwin,indicator->marginsObj,&margins);
    b = Ttk_PadBox(b, margins);

    gcvalues.foreground = borderColor->pixel;
    gcvalues.line_width = 1;
    mask = GCForeground | GCLineWidth;
    gc = Tk_GetGC(tkwin, mask, &gcvalues);

    TtkDrawArrow(Tk_Display(tkwin), d, gc, b, direction);

    Tk_FreeGC(Tk_Display(tkwin), gc);
}

static Ttk_ElementSpec TreeitemIndicatorElementSpec = {
static const Ttk_ElementSpec TreeitemIndicatorElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(TreeitemIndicator),
    TreeitemIndicatorOptions,
    TreeitemIndicatorSize,
    TreeitemIndicatorDraw
};

/*------------------------------------------------------------------------
 * +++ Row element.
 */

typedef struct {
    Tcl_Obj *backgroundObj;
    Tcl_Obj *rowNumberObj;
} RowElement;

static Ttk_ElementOptionSpec RowElementOptions[] = {
static const Ttk_ElementOptionSpec RowElementOptions[] = {
    { "-background", TK_OPTION_COLOR,
	Tk_Offset(RowElement,backgroundObj), DEFAULT_BACKGROUND },
	offsetof(RowElement,backgroundObj), DEFAULT_BACKGROUND },
    { "-rownumber", TK_OPTION_INT,
	Tk_Offset(RowElement,rowNumberObj), "0" },
    { NULL, 0, 0, NULL }
	offsetof(RowElement,rowNumberObj), "0" },
    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
};

static void RowElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, Ttk_State state)
{
    RowElement *row = elementRecord;
    RowElement *row = (RowElement *)elementRecord;
    XColor *color = Tk_GetColorFromObj(tkwin, row->backgroundObj);
    GC gc = Tk_GCForColor(color, d);
    (void)dummy;
    (void)state;

    XFillRectangle(Tk_Display(tkwin), d, gc,
	    b.x, b.y, b.width, b.height);
}

static Ttk_ElementSpec RowElementSpec = {
static const Ttk_ElementSpec RowElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(RowElement),
    RowElementOptions,
    TtkNullElementSize,
    RowElementDraw
};

Changes to generic/ttk/ttkWidget.c.
1
2

3
4
5
6
7
8
9

10
11
12
13
14
15
16
1

2
3
4
5
6

7

8
9
10
11
12
13
14
15

-
+




-

-
+







/*
 * Copyright (c) 2003, Joe English
 * Copyright © 2003, Joe English
 *
 * Core widget utilities.
 */

#include <string.h>
#include "tkInt.h"
#include "ttkTheme.h"
#include "ttkThemeInt.h"
#include "ttkWidget.h"

#ifdef MAC_OSX_TK
#define TK_NO_DOUBLE_BUFFERING 1
#endif

/*------------------------------------------------------------------------
82
83
84
85
86
87
88
89

90
91
92
93
94
95
96
97

98
99
100
101
102
103
104
81
82
83
84
85
86
87

88
89
90
91
92
93
94
95

96
97
98
99
100
101
102
103







-
+







-
+








    Tk_FreePixmap(Tk_Display(tkwin), d);
    Tk_FreeGC(Tk_Display(tkwin), gc);
}
#else
/* No double-buffering: draw directly into the window. */
static Drawable BeginDrawing(Tk_Window tkwin) { return Tk_WindowId(tkwin); }
static void EndDrawing(Tk_Window tkwin, Drawable d) { }
static void EndDrawing(Tk_Window tkwin, Drawable d) { (void)tkwin; (void)d;}
#endif

/* DrawWidget --
 *	Redraw a widget.  Called as an idle handler.
 */
static void DrawWidget(ClientData recordPtr)
{
    WidgetCore *corePtr = recordPtr;
    WidgetCore *corePtr = (WidgetCore *)recordPtr;

    corePtr->flags &= ~REDISPLAY_PENDING;
    if (Tk_IsMapped(corePtr->tkwin)) {
	Drawable d = BeginDrawing(corePtr->tkwin);
	corePtr->widgetSpec->layoutProc(recordPtr);
	corePtr->widgetSpec->displayProc(recordPtr, d);
	EndDrawing(corePtr->tkwin, d);
149
150
151
152
153
154
155
156

157
158
159
160
161
162
163
148
149
150
151
152
153
154

155
156
157
158
159
160
161
162







-
+







/* WidgetInstanceObjCmd --
 *	Widget instance command implementation.
 */
static int
WidgetInstanceObjCmd(
    ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    WidgetCore *corePtr = clientData;
    WidgetCore *corePtr = (WidgetCore *)clientData;
    const Ttk_Ensemble *commands = corePtr->widgetSpec->commands;
    int status;

    Tcl_Preserve(clientData);
    status = Ttk_InvokeEnsemble(commands,1, clientData,interp,objc,objv);
    Tcl_Release(clientData);

184
185
186
187
188
189
190
191

192
193
194
195
196
197
198
183
184
185
186
187
188
189

190
191
192
193
194
195
196
197







-
+








/* WidgetInstanceObjCmdDeleted --
 * 	Widget instance command	deletion callback.
 */
static void
WidgetInstanceObjCmdDeleted(ClientData clientData)
{
    WidgetCore *corePtr = clientData;
    WidgetCore *corePtr = (WidgetCore *)clientData;
    corePtr->widgetCmd = NULL;
    if (corePtr->tkwin != NULL)
	Tk_DestroyWindow(corePtr->tkwin);
}

/* FreeWidget --
 *	 Final cleanup for widget; called via Tcl_EventuallyFree().
210
211
212
213
214
215
216
217

218
219
220
221
222
223
224
209
210
211
212
213
214
215

216
217
218
219
220
221
222
223







-
+







DestroyWidget(WidgetCore *corePtr)
{
    corePtr->flags |= WIDGET_DESTROYED;

    corePtr->widgetSpec->cleanupProc(corePtr);

    Tk_FreeConfigOptions(
	(ClientData)corePtr, corePtr->optionTable, corePtr->tkwin);
	    corePtr, corePtr->optionTable, corePtr->tkwin);

    if (corePtr->layout) {
	Ttk_FreeLayout(corePtr->layout);
    }

    if (corePtr->flags & REDISPLAY_PENDING) {
	Tcl_CancelIdleCall(DrawWidget, corePtr);
329
330
331
332
333
334
335
336

337
338
339
340
341

342
343
344
345
346
347
348
349
350
351
352
353
354
355
356

357
358
359
360
361
362
363
328
329
330
331
332
333
334

335
336
337
338
339

340
341
342
343
344
345
346
347
348
349
350
351
352
353
354

355
356
357
358
359
360
361
362







-
+




-
+














-
+







 * WidgetWorldChanged --
 * 	Default Tk_ClassWorldChangedProc() for widgets.
 * 	Invoked whenever fonts or other system resources are changed;
 * 	recomputes geometry.
 */
static void WidgetWorldChanged(ClientData clientData)
{
    WidgetCore *corePtr = clientData;
    WidgetCore *corePtr = (WidgetCore *)clientData;
    SizeChanged(corePtr);
    TtkRedisplayWidget(corePtr);
}

static Tk_ClassProcs widgetClassProcs = {
static const Tk_ClassProcs widgetClassProcs = {
    sizeof(Tk_ClassProcs),	/* size */
    WidgetWorldChanged,	/* worldChangedProc */
    NULL,					/* createProc */
    NULL					/* modalProc */
};

/*
 * TtkWidgetConstructorObjCmd --
 *	General-purpose widget constructor command implementation.
 *	ClientData is a WidgetSpec *.
 */
int TtkWidgetConstructorObjCmd(
    ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    WidgetSpec *widgetSpec = clientData;
    WidgetSpec *widgetSpec = (WidgetSpec *)clientData;
    const char *className = widgetSpec->className;
    Tk_OptionTable optionTable =
	Tk_CreateOptionTable(interp, widgetSpec->optionSpecs);
    Tk_Window tkwin;
    void *recordPtr;
    WidgetCore *corePtr;
    Tk_SavedOptions savedOptions;
385
386
387
388
389
390
391
392

393
394
395
396
397
398
399
384
385
386
387
388
389
390

391
392
393
394
395
396
397
398







-
+







	return TCL_ERROR;

    /*
     * Allocate and initialize the widget record.
     */
    recordPtr = ckalloc(widgetSpec->recordSize);
    memset(recordPtr, 0, widgetSpec->recordSize);
    corePtr = recordPtr;
    corePtr = (WidgetCore *)recordPtr;

    corePtr->tkwin	= tkwin;
    corePtr->interp 	= interp;
    corePtr->widgetSpec	= widgetSpec;
    corePtr->widgetCmd	= Tcl_CreateObjCommand(interp, Tk_PathName(tkwin),
	WidgetInstanceObjCmd, recordPtr, WidgetInstanceObjCmdDeleted);
    corePtr->optionTable = optionTable;
460
461
462
463
464
465
466
467

468
469
470
471
472
473
474
459
460
461
462
463
464
465

466
467
468
469
470
471
472
473







-
+







 * 	Default getLayoutProc.
 *	Looks up the layout based on the -style resource (if specified),
 *	otherwise use the widget class.
 */
Ttk_Layout TtkWidgetGetLayout(
    Tcl_Interp *interp, Ttk_Theme themePtr, void *recordPtr)
{
    WidgetCore *corePtr = recordPtr;
    WidgetCore *corePtr = (WidgetCore *)recordPtr;
    const char *styleName = 0;

    if (corePtr->styleObj)
    	styleName = Tcl_GetString(corePtr->styleObj);

    if (!styleName || *styleName == '\0')
    	styleName = corePtr->widgetSpec->className;
482
483
484
485
486
487
488
489

490
491
492

493
494
495
496
497
498
499

500
501
502
503
504
505
506
481
482
483
484
485
486
487

488
489
490

491
492
493
494
495
496
497

498
499
500
501
502
503
504
505







-
+


-
+






-
+







 * 	Helper routine.  Same as TtkWidgetGetLayout, but prefixes
 * 	"Horizontal." or "Vertical." to the style name, depending
 * 	on the value of the 'orient' option.
 */
Ttk_Layout TtkWidgetGetOrientedLayout(
    Tcl_Interp *interp, Ttk_Theme themePtr, void *recordPtr, Tcl_Obj *orientObj)
{
    WidgetCore *corePtr = recordPtr;
    WidgetCore *corePtr = (WidgetCore *)recordPtr;
    const char *baseStyleName = 0;
    Tcl_DString styleName;
    int orient = TTK_ORIENT_HORIZONTAL;
    Ttk_Orient orient = TTK_ORIENT_HORIZONTAL;
    Ttk_Layout layout;

    Tcl_DStringInit(&styleName);

    /* Prefix:
     */
    Ttk_GetOrientFromObj(NULL, orientObj, &orient);
    TtkGetOrientFromObj(NULL, orientObj, &orient);
    if (orient == TTK_ORIENT_HORIZONTAL)
	Tcl_DStringAppend(&styleName, "Horizontal.", -1);
    else
	Tcl_DStringAppend(&styleName, "Vertical.", -1);

    /* Add base style name:
     */
522
523
524
525
526
527
528


529
530
531
532
533
534
535




536
537
538
539
540
541
542
543
544
545

546
547
548
549
550
551
552
553
554
555
556
557
558
559

560
561
562
563
564
565
566
567
568

569
570
571
572
573
574
575
576
577

578
579
580
581
582
583
584
585
586

587
588
589
590
591
592
593
594
595
596
597
598
599
600

601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620

621
622
623
624
625
626
627
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549

550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573

574
575
576
577
578
579
580
581
582

583
584
585
586
587
588
589
590
591

592
593
594
595
596
597
598
599
600
601
602
603
604
605

606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625

626
627
628
629
630
631
632
633







+
+







+
+
+
+









-
+














+








-
+








-
+








-
+













-
+



















-
+







}

/* TtkNullInitialize --
 * 	Default widget initializeProc (no-op)
 */
void TtkNullInitialize(Tcl_Interp *interp, void *recordPtr)
{
    (void)interp;
    (void)recordPtr;
}

/* TtkNullPostConfigure --
 * 	Default widget postConfigureProc (no-op)
 */
int TtkNullPostConfigure(Tcl_Interp *interp, void *clientData, int mask)
{
    (void)interp;
    (void)clientData;
    (void)mask;

    return TCL_OK;
}

/* TtkCoreConfigure --
 * 	Default widget configureProc.
 * 	Handles -style option.
 */
int TtkCoreConfigure(Tcl_Interp *interp, void *clientData, int mask)
{
    WidgetCore *corePtr = clientData;
    WidgetCore *corePtr = (WidgetCore *)clientData;
    int status = TCL_OK;

    if (mask & STYLE_CHANGED) {
	status = UpdateLayout(interp, corePtr);
    }

    return status;
}

/* TtkNullCleanup --
 * 	Default widget cleanupProc (no-op)
 */
void TtkNullCleanup(void *recordPtr)
{
    (void)recordPtr;
    return;
}

/* TtkWidgetDoLayout --
 * 	Default widget layoutProc.
 */
void TtkWidgetDoLayout(void *clientData)
{
    WidgetCore *corePtr = clientData;
    WidgetCore *corePtr = (WidgetCore *)clientData;
    Ttk_PlaceLayout(corePtr->layout,corePtr->state,Ttk_WinBox(corePtr->tkwin));
}

/* TtkWidgetDisplay --
 * 	Default widget displayProc.
 */
void TtkWidgetDisplay(void *recordPtr, Drawable d)
{
    WidgetCore *corePtr = recordPtr;
    WidgetCore *corePtr = (WidgetCore *)recordPtr;
    Ttk_DrawLayout(corePtr->layout, corePtr->state, d);
}

/* TtkWidgetSize --
 * 	Default widget sizeProc()
 */
int TtkWidgetSize(void *recordPtr, int *widthPtr, int *heightPtr)
{
    WidgetCore *corePtr = recordPtr;
    WidgetCore *corePtr = (WidgetCore *)recordPtr;
    Ttk_LayoutSize(corePtr->layout, corePtr->state, widthPtr, heightPtr);
    return 1;
}

/*------------------------------------------------------------------------
 * +++ Default implementations for widget subcommands.
 */

/* $w cget -option
 */
int TtkWidgetCgetCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    WidgetCore *corePtr = recordPtr;
    WidgetCore *corePtr = (WidgetCore *)recordPtr;
    Tcl_Obj *result;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "option");
	return TCL_ERROR;
    }
    result = Tk_GetOptionValue(interp, recordPtr,
		corePtr->optionTable, objv[2], corePtr->tkwin);
    if (result == NULL)
	return TCL_ERROR;
    Tcl_SetObjResult(interp, result);
    return TCL_OK;
}

/* $w configure ?-option ?value ....??
 */
int TtkWidgetConfigureCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    WidgetCore *corePtr = recordPtr;
    WidgetCore *corePtr = (WidgetCore *)recordPtr;
    Tcl_Obj *result;

    if (objc == 2) {
	result = Tk_GetOptionInfo(interp, recordPtr,
		corePtr->optionTable, NULL, corePtr->tkwin);
    } else if (objc == 3) {
	result = Tk_GetOptionInfo(interp, recordPtr,
683
684
685
686
687
688
689
690

691
692
693
694
695
696
697
689
690
691
692
693
694
695

696
697
698
699
700
701
702
703







-
+







 *
 * 	Otherwise, return a statespec matching all the currently-set bits.
 */

int TtkWidgetStateCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    WidgetCore *corePtr = recordPtr;
    WidgetCore *corePtr = (WidgetCore *)recordPtr;
    Ttk_StateSpec spec;
    int status;
    Ttk_State oldState, changed;

    if (objc == 2) {
	Tcl_SetObjResult(interp,
	    Ttk_NewStateSpecObj(corePtr->state, 0ul));
723
724
725
726
727
728
729
730

731
732
733
734
735
736
737
738
739
740
741
742
743
744
745

746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761

762
763

764
765
766
767
768
769
770
729
730
731
732
733
734
735

736
737
738
739
740
741
742
743
744
745
746
747
748
749
750

751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766

767
768

769
770
771
772
773
774
775
776







-
+














-
+















-
+

-
+







 *	If $script is specified, execute script if state matches.
 *	Otherwise, return true/false
 */

int TtkWidgetInstateCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    WidgetCore *corePtr = recordPtr;
    WidgetCore *corePtr = (WidgetCore *)recordPtr;
    Ttk_State state = corePtr->state;
    Ttk_StateSpec spec;
    int status = TCL_OK;

    if (objc < 3 || objc > 4) {
	Tcl_WrongNumArgs(interp, 2, objv, "state-spec ?script?");
	return TCL_ERROR;
    }
    status = Ttk_GetStateSpecFromObj(interp, objv[2], &spec);
    if (status != TCL_OK)
	return status;

    if (objc == 3) {
	Tcl_SetObjResult(interp,
	    Tcl_NewBooleanObj(Ttk_StateMatches(state,&spec)));
	    Tcl_NewWideIntObj(Ttk_StateMatches(state,&spec)));
    } else if (objc == 4) {
	if (Ttk_StateMatches(state,&spec)) {
	    status = Tcl_EvalObjEx(interp, objv[3], 0);
	}
    }
    return status;
}

/* $w identify $x $y
 * $w identify element $x $y
 * 	Returns: name of element at $x, $y
 */
int TtkWidgetIdentifyCommand(
    void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
    WidgetCore *corePtr = recordPtr;
    WidgetCore *corePtr = (WidgetCore *)recordPtr;
    Ttk_Element element;
    static const char *whatTable[] = { "element", NULL };
    static const char *const whatTable[] = { "element", NULL };
    int x, y, what;

    if (objc < 4 || objc > 5) {
	Tcl_WrongNumArgs(interp, 2, objv, "?what? x y");
	return TCL_ERROR;
    }
    if (objc == 5) {
784
785
786
787
788
789
790




















791
792
793
794
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





    element = Ttk_IdentifyElement(corePtr->layout, x, y);
    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*/
Changes to generic/ttk/ttkWidget.h.
85
86
87
88
89
90
91


92
93
94

95
96
97
98
99
100

101
102
103
104
105
106
107
108
109
110
111
112
113
114
115


116
117
118
119
120

121
122
123

124
125
126
127
128
129
130

131
132
133
134

135
136
137
138
139
140
141
85
86
87
88
89
90
91
92
93
94
95

96
97
98
99
100
101

102
103
104
105
106
107
108
109
110
111
112
113
114
115


116
117
118
119
120
121

122
123
124

125
126
127
128
129
130
131

132
133
134
135

136
137
138
139
140
141
142
143







+
+


-
+





-
+













-
-
+
+




-
+


-
+






-
+



-
+







MODULE_SCOPE void TtkWidgetDoLayout(void *recordPtr);
MODULE_SCOPE void TtkWidgetDisplay(void *recordPtr, Drawable);

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(
	ClientData, Tcl_Interp*, int, Tcl_Obj*const[]);

#define RegisterWidget(interp, name, specPtr) \
    Tcl_CreateObjCommand(interp, name, \
	TtkWidgetConstructorObjCmd, (ClientData)specPtr,NULL)

/* WIDGET_TAKEFOCUS_TRUE --
 * WIDGET_TAKEFOCUS_FALSE --
 *	Add one or the other of these to each OptionSpecs table 
 *	to indicate whether the widget should take focus 
 *	Add one or the other of these to each OptionSpecs table
 *	to indicate whether the widget should take focus
 *	during keyboard traversal.
 */
#define WIDGET_TAKEFOCUS_TRUE \
    {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus", \
	"ttk::takefocus", Tk_Offset(WidgetCore, takeFocusPtr), -1, 0,0,0 }
	"ttk::takefocus", offsetof(WidgetCore, takeFocusPtr), TCL_INDEX_NONE, 0,0,0 }
#define WIDGET_TAKEFOCUS_FALSE \
    {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus", \
	"", Tk_Offset(WidgetCore, takeFocusPtr), -1, 0,0,0 }
	"", offsetof(WidgetCore, takeFocusPtr), TCL_INDEX_NONE, 0,0,0 }

/* WIDGET_INHERIT_OPTIONS(baseOptionSpecs) --
 * Add this at the end of an OptionSpecs table to inherit
 * the options from 'baseOptionSpecs'.
 */
#define WIDGET_INHERIT_OPTIONS(baseOptionSpecs) \
    {TK_OPTION_END, 0,0,0, NULL, -1,-1, 0, (ClientData)baseOptionSpecs, 0}
    {TK_OPTION_END, 0,0,0, NULL, TCL_INDEX_NONE,TCL_INDEX_NONE, 0, baseOptionSpecs, 0}

/* All widgets should inherit from ttkCoreOptionSpecs[].
 */
MODULE_SCOPE Tk_OptionSpec ttkCoreOptionSpecs[];
MODULE_SCOPE const Tk_OptionSpec ttkCoreOptionSpecs[];

/*
 * Useful routines for use inside widget implementations:
 */
/* extern int WidgetDestroyed(WidgetCore *); */
#define WidgetDestroyed(corePtr) ((corePtr)->flags & WIDGET_DESTROYED)

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
162
163
164
165
166
167
168





169
170
171
172
173
174
175







-
-
-
-
-







typedef struct TtkTraceHandle_ Ttk_TraceHandle;

MODULE_SCOPE Ttk_TraceHandle *Ttk_TraceVariable(
    Tcl_Interp*, Tcl_Obj *varnameObj, Ttk_TraceProc callback, void *clientData);
MODULE_SCOPE void Ttk_UntraceVariable(Ttk_TraceHandle *);
MODULE_SCOPE int Ttk_FireTrace(Ttk_TraceHandle *);

/*
 * Virtual events:
 */
MODULE_SCOPE void TtkSendVirtualEvent(Tk_Window tgtWin, const char *eventName);

/*
 * Helper routines for data accessor commands:
 */
MODULE_SCOPE int TtkEnumerateOptions(
    Tcl_Interp *, void *, const Tk_OptionSpec *, Tk_OptionTable, Tk_Window);
MODULE_SCOPE int TtkGetOptionValue(
    Tcl_Interp *, void *, Tcl_Obj *optName, Tk_OptionTable, Tk_Window);
208
209
210
211
212
213
214
215

216
217
218
219
220
221
222
223
224
225
226
227


228
229
230
231
232
233
234
205
206
207
208
209
210
211

212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233







-
+












+
+







typedef struct TtkTagTable *Ttk_TagTable;
typedef struct TtkTagSet {	/* TODO: make opaque */
    Ttk_Tag	*tags;
    int 	nTags;
} *Ttk_TagSet;

MODULE_SCOPE Ttk_TagTable Ttk_CreateTagTable(
	Tcl_Interp *, Tk_Window tkwin, Tk_OptionSpec[], int recordSize);
	Tcl_Interp *, Tk_Window tkwin, const Tk_OptionSpec *, int recordSize);
MODULE_SCOPE void Ttk_DeleteTagTable(Ttk_TagTable);

MODULE_SCOPE Ttk_Tag Ttk_GetTag(Ttk_TagTable, const char *tagName);
MODULE_SCOPE Ttk_Tag Ttk_GetTagFromObj(Ttk_TagTable, Tcl_Obj *);

MODULE_SCOPE Tcl_Obj *Ttk_TagOptionValue(
    Tcl_Interp *, Ttk_TagTable, Ttk_Tag, Tcl_Obj *optionName);

MODULE_SCOPE int Ttk_EnumerateTagOptions(
    Tcl_Interp *, Ttk_TagTable, Ttk_Tag);

MODULE_SCOPE int Ttk_EnumerateTags(Tcl_Interp *, Ttk_TagTable);

MODULE_SCOPE void Ttk_DeleteTagFromTable(Ttk_TagTable, Ttk_Tag);

MODULE_SCOPE int Ttk_ConfigureTag(
    Tcl_Interp *interp, Ttk_TagTable tagTable, Ttk_Tag tag,
    int objc, Tcl_Obj *const objv[]);

MODULE_SCOPE Ttk_TagSet Ttk_GetTagSetFromObj(
    Tcl_Interp *interp, Ttk_TagTable, Tcl_Obj *objPtr);
243
244
245
246
247
248
249
250
251
252



253
254
255
256
257
258
259
242
243
244
245
246
247
248



249
250
251
252
253
254
255
256
257
258







-
-
-
+
+
+







MODULE_SCOPE void Ttk_TagSetValues(Ttk_TagTable, Ttk_TagSet, void *record);
MODULE_SCOPE void Ttk_TagSetApplyStyle(Ttk_TagTable,Ttk_Style,Ttk_State,void*);

/*
 * String tables for widget resource specifications:
 */

MODULE_SCOPE const char *ttkOrientStrings[];
MODULE_SCOPE const char *ttkCompoundStrings[];
MODULE_SCOPE const char *ttkDefaultStrings[];
MODULE_SCOPE const char *const ttkOrientStrings[];
MODULE_SCOPE const char *const ttkCompoundStrings[];
MODULE_SCOPE const char *const ttkDefaultStrings[];

/*
 * ... other option types...
 */
MODULE_SCOPE int TtkGetLabelAnchorFromObj(
	Tcl_Interp*, Tcl_Obj*, Ttk_PositionSpec *);

Changes to library/bgerror.tcl.
1
2
3
4
5
6
7
8
9
10
11
12




13
14
15
16
17
18
19
1
2
3
4
5
6
7
8




9
10
11
12
13
14
15
16
17
18
19








-
-
-
-
+
+
+
+







# bgerror.tcl --
#
#	Implementation of the bgerror procedure.  It posts a dialog box with
#	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 (c) 1998-2000 by Ajuba Solutions.
# Copyright (c) 2007 by ActiveState Software Inc.
# Copyright (c) 2007 Daniel A. Steffen <[email protected]>
# Copyright (c) 2009 Pat Thoyts <[email protected]>
# Copyright © 1998-2000 Ajuba Solutions.
# Copyright © 2007 ActiveState Software Inc.
# Copyright © 2007 Daniel A. Steffen <[email protected]>
# Copyright © 2009 Pat Thoyts <[email protected]>

namespace eval ::tk::dialog::error {
    namespace import -force ::tk::msgcat::*
    namespace export bgerror
    option add *ErrorDialog.function.text [mc "Save To Log"] \
	widgetDefault
    option add *ErrorDialog.function.command [namespace code SaveToLog]
37
38
39
40
41
42
43
44

45
46
47
48
49
50
51
52
53

54
55
56
57
58
59
60
37
38
39
40
41
42
43

44
45
46
47
48
49
50
51
52

53
54
55
56
57
58
59
60







-
+








-
+







    set button $code
}

proc ::tk::dialog::error::Details {} {
    set w .bgerrorDialog
    set caption [option get $w.function text {}]
    set command [option get $w.function command {}]
    if { ($caption eq "") || ($command eq "") } {
    if {($caption eq "") || ($command eq "")} {
	grid forget $w.function
    }
    lappend command [$w.top.info.text get 1.0 end-1c]
    $w.function configure -text $caption -command $command
    grid $w.top.info - -sticky nsew -padx 3m -pady 3m
}

proc ::tk::dialog::error::SaveToLog {text} {
    if { $::tcl_platform(platform) eq "windows" } {
    if {$::tcl_platform(platform) eq "windows"} {
	set allFiles *.*
    } else {
	set allFiles *
    }
    set types [list \
	    [list [mc "Log Files"] .log]      \
	    [list [mc "Text Files"] .txt]     \
125
126
127
128
129
130
131
132
133


134
135
136

137
138
139
140
141
142
143
125
126
127
128
129
130
131


132
133
134
135

136
137
138
139
140
141
142
143







-
-
+
+


-
+







    # Truncate the message if it is too wide (>maxLine characters) or
    # too tall (>4 lines).  Truncation occurs at the first point at
    # which one of those conditions is met.
    set displayedErr ""
    set lines 0
    set maxLine 45
    foreach line [split $err \n] {
	if { [string length $line] > $maxLine } {
	    append displayedErr "[string range $line 0 [expr {$maxLine-3}]]..."
	if {[string length $line] > $maxLine} {
	    append displayedErr "[string range $line 0 $maxLine-3]..."
	    break
	}
	if { $lines > 4 } {
	if {$lines > 4} {
	    append displayedErr "..."
	    break
	} else {
	    append displayedErr "${line}\n"
	}
	incr lines
    }
178
179
180
181
182
183
184
185

186
187
188
189
190
191
192
178
179
180
181
182
183
184

185
186
187
188
189
190
191
192







-
+







    }

    ttk::scrollbar $W.scroll -command [list $W.text yview]
    pack $W.scroll -side right -fill y
    pack $W.text -side left -expand yes -fill both
    $W.text insert 0.0 "$err\n$info"
    $W.text mark set insert 0.0
    bind $W.text <ButtonPress-1> { focus %W }
    bind $W.text <Button-1> {focus %W}
    $W.text configure -state disabled

    # 2. Fill the top part with bitmap and message

    # Max-width of message is the width of the screen...
    set wrapwidth [winfo screenwidth $dlg]
    # ...minus the width of the icon, padding and a fudge factor for
Changes to library/button.tcl.
1
2
3
4
5
6
7
8
9



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

25
26
27
28
29
30
31
32
33

34
35
36
37
38
39
40
41
42
43
44

45
46
47

48
49
50
51
52
53

54
55
56
57
58
59
60
61
62
63
64
65
66

67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

88
89
90

91
92
93
94
95
96
97
1
2
3
4
5
6



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

24
25
26
27
28
29
30
31
32

33
34
35
36
37
38
39
40
41
42
43

44
45
46

47
48
49
50
51
52

53
54
55
56
57
58
59
60
61
62
63
64
65

66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86

87
88
89

90
91
92
93
94
95
96
97






-
-
-
+
+
+














-
+








-
+










-
+


-
+





-
+












-
+




















-
+


-
+







# button.tcl --
#
# This file defines the default bindings for Tk label, button,
# checkbutton, and radiobutton widgets and provides procedures
# that help in implementing those bindings.
#
# Copyright (c) 1992-1994 The Regents of the University of California.
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright (c) 2002 ActiveState Corporation.
# Copyright © 1992-1994 The Regents of the University of California.
# Copyright © 1994-1996 Sun Microsystems, Inc.
# 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.
#

#-------------------------------------------------------------------------
# The code below creates the default class bindings for buttons.
#-------------------------------------------------------------------------

if {[tk windowingsystem] eq "aqua"} {

    bind Radiobutton <Enter> {
	tk::ButtonEnter %W
    }
    bind Radiobutton <1> {
    bind Radiobutton <Button-1> {
	tk::ButtonDown %W
    }
    bind Radiobutton <ButtonRelease-1> {
	tk::ButtonUp %W
    }
    bind Checkbutton <Enter> {
	tk::ButtonEnter %W
    }
    bind Checkbutton <1> {
    bind Checkbutton <Button-1> {
	tk::ButtonDown %W
    }
    bind Checkbutton <ButtonRelease-1> {
	tk::ButtonUp %W
    }
    bind Checkbutton <Leave> {
	tk::ButtonLeave %W
    }
}
if {"win32" eq [tk windowingsystem]} {
    bind Checkbutton <equal> {
    bind Checkbutton <=> {
	tk::CheckRadioInvoke %W select
    }
    bind Checkbutton <plus> {
    bind Checkbutton <+> {
	tk::CheckRadioInvoke %W select
    }
    bind Checkbutton <minus> {
	tk::CheckRadioInvoke %W deselect
    }
    bind Checkbutton <1> {
    bind Checkbutton <Button-1> {
	tk::CheckRadioDown %W
    }
    bind Checkbutton <ButtonRelease-1> {
	tk::ButtonUp %W
    }
    bind Checkbutton <Enter> {
	tk::CheckRadioEnter %W
    }
    bind Checkbutton <Leave> {
	tk::ButtonLeave %W
    }

    bind Radiobutton <1> {
    bind Radiobutton <Button-1> {
	tk::CheckRadioDown %W
    }
    bind Radiobutton <ButtonRelease-1> {
	tk::ButtonUp %W
    }
    bind Radiobutton <Enter> {
	tk::CheckRadioEnter %W
    }
}
if {"x11" eq [tk windowingsystem]} {
    bind Checkbutton <Return> {
	if {!$tk_strictMotif} {
	    tk::CheckInvoke %W
	}
    }
    bind Radiobutton <Return> {
	if {!$tk_strictMotif} {
	    tk::CheckRadioInvoke %W
	}
    }
    bind Checkbutton <1> {
    bind Checkbutton <Button-1> {
	tk::CheckInvoke %W
    }
    bind Radiobutton <1> {
    bind Radiobutton <Button-1> {
	tk::CheckRadioInvoke %W
    }
    bind Checkbutton <Enter> {
	tk::CheckEnter %W
    }
    bind Radiobutton <Enter> {
	tk::ButtonEnter %W
123
124
125
126
127
128
129
130

131
132
133
134
135
136
137
123
124
125
126
127
128
129

130
131
132
133
134
135
136
137







-
+







bind Button <FocusIn> {}
bind Button <Enter> {
    tk::ButtonEnter %W
}
bind Button <Leave> {
    tk::ButtonLeave %W
}
bind Button <1> {
bind Button <Button-1> {
    tk::ButtonDown %W
}
bind Button <ButtonRelease-1> {
    tk::ButtonUp %W
}

bind Checkbutton <FocusIn> {}
Changes to library/choosedir.tcl.
1
2
3
4
5

6
7
8
9
10
11
12
1
2
3
4

5
6
7
8
9
10
11
12




-
+







# choosedir.tcl --
#
#	Choose directory dialog implementation for Unix/Mac.
#
# Copyright (c) 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 {}

# Make the chooseDir namespace inside the dialog namespace
Changes to library/clrpick.tcl.
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







# clrpick.tcl --
#
#	Color selection dialog for platforms that do not support a
#	standard color selection dialog.
#
# 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.
#
# ToDo:
#
#	(1): Find out how many free colors are left in the colormap and
312
313
314
315
316
317
318
319

320
321
322
323
324
325
326
312
313
314
315
316
317
318

319
320
321
322
323
324
325
326







-
+







    grid columnconfigure $botFrame {0 4} -weight 1 -uniform space
    grid columnconfigure $botFrame {1 3} -weight 1 -uniform button
    grid columnconfigure $botFrame 2 -weight 2 -uniform space
    pack $botFrame -side bottom -fill x

    # Accelerator bindings
    bind $lab <<AltUnderlined>> [list focus $ent]
    bind $w <KeyPress-Escape> [list tk::ButtonInvoke $data(cancelBtn)]
    bind $w <Escape> [list tk::ButtonInvoke $data(cancelBtn)]
    bind $w <Alt-Key> [list tk::AltKeyInDialog $w %A]

    wm protocol $w WM_DELETE_WINDOW [list tk::dialog::color::CancelCmd $w]
    bind $lab <Destroy> [list tk::dialog::color::CancelCmd $w]
}

# ::tk::dialog::color::SetRGBValue --
392
393
394
395
396
397
398
399

400
401
402
403
404
405
406
407
408
409
410
411
412

413
414
415
416
417
418
419

420
421
422
423
424
425
426
392
393
394
395
396
397
398

399
400
401
402
403
404
405
406
407
408
409
410
411

412
413
414
415
416
417
418

419
420
421
422
423
424
425
426







-
+












-
+






-
+







	# Delete the selector if it exists
	if {[info exists data($c,index)]} {
	    $sel delete $data($c,index)
	}

	# Draw the selection polygons
	CreateSelector $w $sel $c
	$sel bind $data($c,index) <ButtonPress-1> \
	$sel bind $data($c,index) <Button-1> \
		[list tk::dialog::color::StartMove $w $sel $c %x $data(selPad) 1]
	$sel bind $data($c,index) <B1-Motion> \
		[list tk::dialog::color::MoveSelector $w $sel $c %x $data(selPad)]
	$sel bind $data($c,index) <ButtonRelease-1> \
		[list tk::dialog::color::ReleaseMouse $w $sel $c %x $data(selPad)]

	set height [winfo height $col]
	# Create an invisible region under the colorstrip to catch mouse clicks
	# that aren't on the selector.
	set data($c,clickRegion) [$sel create rectangle 0 0 \
		$data(canvasWidth) $height -fill {} -outline {}]

	bind $col <ButtonPress-1> \
	bind $col <Button-1> \
		[list tk::dialog::color::StartMove $w $sel $c %x $data(colorPad)]
	bind $col <B1-Motion> \
		[list tk::dialog::color::MoveSelector $w $sel $c %x $data(colorPad)]
	bind $col <ButtonRelease-1> \
		[list tk::dialog::color::ReleaseMouse $w $sel $c %x $data(colorPad)]

	$sel bind $data($c,clickRegion) <ButtonPress-1> \
	$sel bind $data($c,clickRegion) <Button-1> \
		[list tk::dialog::color::StartMove $w $sel $c %x $data(selPad)]
	$sel bind $data($c,clickRegion) <B1-Motion> \
		[list tk::dialog::color::MoveSelector $w $sel $c %x $data(selPad)]
	$sel bind $data($c,clickRegion) <ButtonRelease-1> \
		[list tk::dialog::color::ReleaseMouse $w $sel $c %x $data(selPad)]
    } else {
	# l is the canvas index of the first colorbar.
Changes to library/comdlg.tcl.
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







# comdlg.tcl --
#
#	Some functions needed for the common dialog boxes. Probably need to go
#	in a different file.
#
# 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.
#

# tclParseConfigSpec --
#
25
26
27
28
29
30
31
32


33
34
35
36
37
38
39
25
26
27
28
29
30
31

32
33
34
35
36
37
38
39
40







-
+
+







# w = widget record to modify. Must be the pathname of a widget.
#
# 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

    # 1: Put the specs in associative arrays for faster access
59
60
61
62
63
64
65

66
67



68
69
70
71
72
73
74
60
61
62
63
64
65
66
67


68
69
70
71
72
73
74
75
76
77







+
-
-
+
+
+







	}
	return -code error -errorcode {TK VALUE_MISSING} \
	    "value for \"$cmdsw\" missing"
    }

    # 2: set the default values
    #
    if {"DONTSETDEFAULTS" ni $flags} {
    foreach cmdsw [array names cmd] {
	set data($cmdsw) $def($cmdsw)
        foreach cmdsw [array names cmd] {
	    set data($cmdsw) $def($cmdsw)
        }
    }

    # 3: parse the argument list
    #
    foreach {cmdsw value} $argList {
	if {![info exists cmd($cmdsw)]} {
	    return -code error -errorcode [list TK LOOKUP OPTION $cmdsw] \
Changes to library/console.tcl.
1
2
3
4
5
6
7
8
9



10
11
12
13
14
15
16
1
2
3
4
5
6



7
8
9
10
11
12
13
14
15
16






-
-
-
+
+
+







# console.tcl --
#
# This code constructs the console window for an application.  It
# can be used by non-unix systems that do not have built-in support
# for shells.
#
# Copyright (c) 1995-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-2000 Ajuba Solutions.
# Copyright (c) 2007-2008 Daniel A. Steffen <[email protected]>
# Copyright © 1995-1997 Sun Microsystems, Inc.
# Copyright © 1998-2000 Ajuba Solutions.
# Copyright © 2007-2008 Daniel A. Steffen <[email protected]>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#

# TODO: history - remember partially written command

127
128
129
130
131
132
133
134

135
136
137
138
139
140
141
127
128
129
130
131
132
133

134
135
136
137
138
139
140
141







-
+







    set families [font families]
    switch -exact -- [tk windowingsystem] {
        aqua { set preferred {Monaco 10} }
        win32 { set preferred {ProFontWindows 8 Consolas 8} }
        default { set preferred {} }
    }
    foreach {family size} $preferred {
        if {[lsearch -exact $families $family] != -1} {
        if {$family in $families} {
            font configure TkConsoleFont -family $family -size $size
            break
        }
    }

    # Provide the right border for the text widget (platform dependent).
    ::ttk::style layout ConsoleFrame {
211
212
213
214
215
216
217
218

219
220
221
222
223
224
225
211
212
213
214
215
216
217

218
219
220
221
222
223
224
225







-
+







proc ::tk::ConsoleSource {} {
    set filename [tk_getOpenFile -defaultextension .tcl -parent . \
	    -title [mc "Select a file to source"] \
	    -filetypes [list \
	    [list [mc "Tcl Scripts"] .tcl] \
	    [list [mc "All Files"] *]]]
    if {$filename ne ""} {
    	set cmd [list source $filename]
    	set cmd [list source -encoding utf-8 $filename]
	if {[catch {consoleinterp eval $cmd} result]} {
	    ConsoleOutput stderr "$result\n"
	}
    }
}

# ::tk::ConsoleInvoke --
412
413
414
415
416
417
418
419

420
421

422
423
424
425

426
427
428
429
430
431
432
433
434



435
436
437
438
439
440




441
442
443
444
445
446
447
448
449
450









451
452
453
454
455
456
457
458







459
460
461
462
463
464
465
466
467
468
469
470
471
472








473
474
475
476
477
478
479
480
412
413
414
415
416
417
418

419
420

421
422
423
424

425
426
427
428
429
430
431



432
433
434
435
436




437
438
439
440
441









442
443
444
445
446
447
448
449
450
451







452
453
454
455
456
457
458














459
460
461
462
463
464
465
466

467
468
469
470
471
472
473







-
+

-
+



-
+






-
-
-
+
+
+


-
-
-
-
+
+
+
+

-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-







    bindtags $w [list $w Console PostConsole [winfo toplevel $w] all]

    ## Get all Text bindings into Console
    foreach ev [bind Text] {
	bind Console $ev [bind Text $ev]
    }
    ## We really didn't want the newline insertion...
    bind Console <Control-Key-o> {}
    bind Console <Control-o> {}
    ## ...or any Control-v binding (would block <<Paste>>)
    bind Console <Control-Key-v> {}
    bind Console <Control-v> {}

    # For the moment, transpose isn't enabled until the console
    # gets and overhaul of how it handles input -- hobbs
    bind Console <Control-Key-t> {}
    bind Console <Control-t> {}

    # Ignore all Alt, Meta, and Control keypresses unless explicitly bound.
    # Otherwise, if a widget binding for one of these is defined, the
    # <Keypress> class binding will also fire and insert the character
    # which is wrong.

    bind Console <Alt-KeyPress> {# nothing }
    bind Console <Meta-KeyPress> {# nothing}
    bind Console <Control-KeyPress> {# nothing}
    bind Console <Alt-Key> {# nothing }
    bind Console <Meta-Key> {# nothing}
    bind Console <Control-Key> {# nothing}

    foreach {ev key} {
	<<Console_NextImmediate>>	<Control-Key-n>
	<<Console_PrevImmediate>>	<Control-Key-p>
	<<Console_PrevSearch>>		<Control-Key-r>
	<<Console_NextSearch>>		<Control-Key-s>
	<<Console_NextImmediate>>	<Control-n>
	<<Console_PrevImmediate>>	<Control-p>
	<<Console_PrevSearch>>		<Control-r>
	<<Console_NextSearch>>		<Control-s>

	<<Console_Expand>>		<Key-Tab>
	<<Console_Expand>>		<Key-Escape>
	<<Console_ExpandFile>>		<Control-Shift-Key-F>
	<<Console_ExpandProc>>		<Control-Shift-Key-P>
	<<Console_ExpandVar>>		<Control-Shift-Key-V>
	<<Console_Tab>>			<Control-Key-i>
	<<Console_Tab>>			<Meta-Key-i>
	<<Console_Eval>>		<Key-Return>
	<<Console_Eval>>		<Key-KP_Enter>
	<<Console_Expand>>		<Tab>
	<<Console_Expand>>		<Escape>
	<<Console_ExpandFile>>		<Control-Shift-F>
	<<Console_ExpandProc>>		<Control-Shift-P>
	<<Console_ExpandVar>>		<Control-Shift-V>
	<<Console_Tab>>			<Control-i>
	<<Console_Tab>>			<Meta-i>
	<<Console_Eval>>		<Return>
	<<Console_Eval>>		<KP_Enter>

	<<Console_Clear>>		<Control-Key-l>
	<<Console_KillLine>>		<Control-Key-k>
	<<Console_Transpose>>		<Control-Key-t>
	<<Console_ClearLine>>		<Control-Key-u>
	<<Console_SaveCommand>>		<Control-Key-z>
        <<Console_FontSizeIncr>>	<Control-Key-plus>
        <<Console_FontSizeDecr>>	<Control-Key-minus>
	<<Console_Clear>>		<Control-l>
	<<Console_KillLine>>		<Control-k>
	<<Console_Transpose>>		<Control-t>
	<<Console_ClearLine>>		<Control-u>
	<<Console_SaveCommand>>		<Control-z>
	<<Console_FontSizeIncr>>	<Control-+>
	<<Console_FontSizeDecr>>	<Control-minus>
    } {
	event add $ev $key
	bind Console $key {}
    }
    if {[tk windowingsystem] eq "aqua"} {
	foreach {ev key} {
	    <<Console_FontSizeIncr>>	<Command-Key-plus>
	    <<Console_FontSizeDecr>>	<Command-Key-minus>
	} {
	    event add $ev $key
	    bind Console $key {}
	}
	if {$::tk::console::useFontchooser} {
	    bind Console <Command-Key-t> [list ::tk::console::FontchooserToggle]
	<<Console_FontSizeIncr>>	<Command-+>
	<<Console_FontSizeDecr>>	<Command-minus>
    } {
	event add $ev $key
	bind Console $key {}
    }
    if {$::tk::console::useFontchooser} {
	bind Console <Command-t> [list ::tk::console::FontchooserToggle]
	}
    }
    bind Console <<Console_Expand>> {
	if {[%W compare insert > promptEnd]} {
	    ::tk::console::Expand %W
	}
    }
    bind Console <<Console_ExpandFile>> {
583
584
585
586
587
588
589
590

591
592
593
594
595

596
597
598
599


600
601
602
603
604
605
606
607
576
577
578
579
580
581
582

583
584
585
586
587

588
589



590
591

592
593
594
595
596
597
598







-
+




-
+

-
-
-
+
+
-







    }
    bind Console <<NextLine>> {
	tk::ConsoleHistory next
    }
    bind Console <Insert> {
	catch {tk::ConsoleInsert %W [::tk::GetSelection %W PRIMARY]}
    }
    bind Console <KeyPress> {
    bind Console <Key> {
	tk::ConsoleInsert %W %A
    }
    bind Console <F9> {
	eval destroy [winfo child .]
	source [file join $tk_library console.tcl]
	source -encoding utf-8 [file join $tk_library console.tcl]
    }
    if {[tk windowingsystem] eq "aqua"} {
	bind Console <Command-q> {
	    exit
    bind Console <Command-q> {
	exit
	}
    }
    bind Console <<Cut>> { ::tk::console::Cut %W }
    bind Console <<Copy>> { ::tk::console::Copy %W }
    bind Console <<Paste>> { ::tk::console::Paste %W }

    bind Console <<Console_FontSizeIncr>> {
        set size [font configure TkConsoleFont -size]
625
626
627
628
629
630
631
632

633
634
635
636
637

638
639
640
641
642

643
644
645
646
647

648
649
650
651
652
653

654
655
656
657
658
659
660
616
617
618
619
620
621
622

623
624
625
626
627

628
629
630
631
632

633
634
635
636
637

638
639
640
641
642
643

644
645
646
647
648
649
650
651







-
+




-
+




-
+




-
+





-
+







    bind Console <<Console_FitScreenWidth>> {
	::tk::console::FitScreenWidth %W
    }

    ##
    ## Bindings for doing special things based on certain keys
    ##
    bind PostConsole <Key-parenright> {
    bind PostConsole <parenright> {
	if {"\\" ne [%W get insert-2c]} {
	    ::tk::console::MatchPair %W \( \) promptEnd
	}
    }
    bind PostConsole <Key-bracketright> {
    bind PostConsole <bracketright> {
	if {"\\" ne [%W get insert-2c]} {
	    ::tk::console::MatchPair %W \[ \] promptEnd
	}
    }
    bind PostConsole <Key-braceright> {
    bind PostConsole <braceright> {
	if {"\\" ne [%W get insert-2c]} {
	    ::tk::console::MatchPair %W \{ \} promptEnd
	}
    }
    bind PostConsole <Key-quotedbl> {
    bind PostConsole <quotedbl> {
	if {"\\" ne [%W get insert-2c]} {
	    ::tk::console::MatchQuote %W promptEnd
	}
    }

    bind PostConsole <KeyPress> {
    bind PostConsole <Key> {
	if {"%A" ne ""} {
	    ::tk::console::TagProc %W
	}
    }
}

# ::tk::ConsoleInsert --
736
737
738
739
740
741
742
743

744
745

746
747
748
749
750
751
752
727
728
729
730
731
732
733

734
735

736
737
738
739
740
741
742
743







-
+

-
+







	tk fontchooser hide
    } else {
	tk fontchooser show
    }
}
proc ::tk::console::FontchooserVisibility {index} {
    if {[tk fontchooser configure -visible]} {
	.menubar.edit entryconfigure $index -label [msgcat::mc "Hide Fonts"]
	.menubar.edit entryconfigure $index -label [::tk::msgcat::mc "Hide Fonts"]
    } else {
	.menubar.edit entryconfigure $index -label [msgcat::mc "Show Fonts"]
	.menubar.edit entryconfigure $index -label [::tk::msgcat::mc "Show Fonts"]
    }
}
proc ::tk::console::FontchooserFocus {w isFocusIn} {
    if {$isFocusIn} {
	tk fontchooser configure -parent $w -font TkConsoleFont \
		-command [namespace code [list FontchooserApply]]
    } else {
Changes to library/demos/arrow.tcl.
150
151
152
153
154
155
156
157
158
159



160
161

162
163
164
165
166
167
168
150
151
152
153
154
155
156



157
158
159
160

161
162
163
164
165
166
167
168







-
-
-
+
+
+

-
+







    set demo_arrowInfo(activeStyle) "-fill black -outline black -width 1"
}
arrowSetup $c
$c bind box <Enter> "$c itemconfigure current $demo_arrowInfo(activeStyle)"
$c bind box <Leave> "$c itemconfigure current $demo_arrowInfo(boxStyle)"
$c bind box <B1-Enter> " "
$c bind box <B1-Leave> " "
$c bind box1 <1> {set demo_arrowInfo(motionProc) arrowMove1}
$c bind box2 <1> {set demo_arrowInfo(motionProc) arrowMove2}
$c bind box3 <1> {set demo_arrowInfo(motionProc) arrowMove3}
$c bind box1 <Button-1> {set demo_arrowInfo(motionProc) arrowMove1}
$c bind box2 <Button-1> {set demo_arrowInfo(motionProc) arrowMove2}
$c bind box3 <Button-1> {set demo_arrowInfo(motionProc) arrowMove3}
$c bind box <B1-Motion> "\$demo_arrowInfo(motionProc) $c %x %y"
bind $c <Any-ButtonRelease-1> "arrowSetup $c"
bind $c <ButtonRelease-1> "arrowSetup $c"

# arrowMove1 --
# This procedure is called for each mouse motion event on box1 (the
# one at the vertex of the arrow).  It updates the controlling parameters
# for the line and arrowhead.
#
# Arguments:
Changes to library/demos/bind.tcl.
59
60
61
62
63
64
65
66
67


68
69
70
71
72
73
74
75






76
77
78
59
60
61
62
63
64
65


66
67
68
69






70
71
72
73
74
75
76
77
78







-
-
+
+


-
-
-
-
-
-
+
+
+
+
+
+



$w.text insert end \n\n
$w.text insert end \
{6. A grid that demonstrates how canvases can be scrolled.} d6

# Create bindings for tags.

foreach tag {d1 d2 d3 d4 d5 d6} {
    $w.text tag bind $tag <Any-Enter> "$w.text tag configure $tag $bold"
    $w.text tag bind $tag <Any-Leave> "$w.text tag configure $tag $normal"
    $w.text tag bind $tag <Enter> "$w.text tag configure $tag $bold"
    $w.text tag bind $tag <Leave> "$w.text tag configure $tag $normal"
}
# Main widget program sets variable tk_demoDirectory
$w.text tag bind d1 <1> {source [file join $tk_demoDirectory items.tcl]}
$w.text tag bind d2 <1> {source [file join $tk_demoDirectory plot.tcl]}
$w.text tag bind d3 <1> {source [file join $tk_demoDirectory ctext.tcl]}
$w.text tag bind d4 <1> {source [file join $tk_demoDirectory arrow.tcl]}
$w.text tag bind d5 <1> {source [file join $tk_demoDirectory ruler.tcl]}
$w.text tag bind d6 <1> {source [file join $tk_demoDirectory cscroll.tcl]}
$w.text tag bind d1 <Button-1> {source -encoding utf-8 [file join $tk_demoDirectory items.tcl]}
$w.text tag bind d2 <Button-1> {source -encoding utf-8 [file join $tk_demoDirectory plot.tcl]}
$w.text tag bind d3 <Button-1> {source -encoding utf-8 [file join $tk_demoDirectory ctext.tcl]}
$w.text tag bind d4 <Button-1> {source -encoding utf-8 [file join $tk_demoDirectory arrow.tcl]}
$w.text tag bind d5 <Button-1> {source -encoding utf-8 [file join $tk_demoDirectory ruler.tcl]}
$w.text tag bind d6 <Button-1> {source -encoding utf-8 [file join $tk_demoDirectory cscroll.tcl]}

$w.text mark set insert 0.0
$w.text configure -state disabled
Changes to library/demos/colors.tcl.
28
29
30
31
32
33
34
35

36
37
38
39
40
41
42
28
29
30
31
32
33
34

35
36
37
38
39
40
41
42







-
+







pack $w.frame -side top -expand yes -fill y

scrollbar $w.frame.scroll -command "$w.frame.list yview"
listbox $w.frame.list -yscroll "$w.frame.scroll set" \
	-width 20 -height 16 -setgrid 1
pack $w.frame.list $w.frame.scroll -side left -fill y -expand 1

bind $w.frame.list <Double-1> {
bind $w.frame.list <Double-Button-1> {
    tk_setPalette [selection get]
}
$w.frame.list insert 0 gray60 gray70 gray80 gray85 gray90 gray95 \
    snow1 snow2 snow3 snow4 seashell1 seashell2 \
    seashell3 seashell4 AntiqueWhite1 AntiqueWhite2 AntiqueWhite3 \
    AntiqueWhite4 bisque1 bisque2 bisque3 bisque4 PeachPuff1 \
    PeachPuff2 PeachPuff3 PeachPuff4 NavajoWhite1 NavajoWhite2 \
Changes to library/demos/combo.tcl.
39
40
41
42
43
44
45
46


47
48
49
50
51
52
53
39
40
41
42
43
44
45

46
47
48
49
50
51
52
53
54







-
+
+







    Canberra Sydney Melbourne Perth Adelaide Brisbane
    Hobart Darwin "Alice Springs"
}
set secondValue unchangable
set ozCity Sydney

ttk::labelframe $w.c1 -text "Fully Editable"
ttk::combobox $w.c1.c -textvariable firstValue
ttk::combobox $w.c1.c -textvariable firstValue -placeholder {Enter text here}
ttk::style configure TEntry -placeholderforeground gray50
ttk::labelframe $w.c2 -text Disabled
ttk::combobox $w.c2.c -textvariable secondValue -state disabled
ttk::labelframe $w.c3 -text "Defined List Only"
ttk::combobox $w.c3.c -textvariable ozCity -state readonly \
	-values $australianCities
bind $w.c1.c <Return> {
    if {[%W get] ni [%W cget -values]} {
Changes to library/demos/cscroll.tcl.
49
50
51
52
53
54
55
56
57
58
59
60
61



























62

63
64





65

66
67





68

69
70





71

72

73
74

75
76
77


78
79
80
81
82
83

84
85
86
87
88

89
90
91
92
93

94
95
96
97
98

99
100
101
102
103

104
105
106
107
108
109
110
49
50
51
52
53
54
55






56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84


85
86
87
88
89
90
91


92
93
94
95
96
97
98


99
100
101
102
103
104
105

106


107



108
109


110
111
112

113
114
115
116
117

118
119
120
121
122

123
124
125
126
127

128
129
130
131
132

133
134
135
136
137
138
139
140







-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
-
-
+
+
+
+
+

+
-
-
+
+
+
+
+

+
-
-
+
+
+
+
+

+
-
+
-
-
+
-
-
-
+
+
-
-



-
+




-
+




-
+




-
+




-
+







	$c create rect ${x}c ${y}c [expr {$x+2}]c [expr {$y+2}]c \
		-fill $bg -tags rect
	$c create text [expr {$x+1}]c [expr {$y+1}]c -text "$i,$j" \
	    -anchor center -tags text
    }
}

$c bind all <Any-Enter> "scrollEnter $c"
$c bind all <Any-Leave> "scrollLeave $c"
$c bind all <1> "scrollButton $c"
bind $c <2> "$c scan mark %x %y"
bind $c <B2-Motion> "$c scan dragto %x %y"
if {[tk windowingsystem] eq "aqua"} {
$c bind all <Enter> "scrollEnter $c"
$c bind all <Leave> "scrollLeave $c"
$c bind all <Button-1> "scrollButton $c"
if {([tk windowingsystem] eq "aqua") && ![package vsatisfies [package provide Tk] 8.7-]} {
    bind $c <Button-3> "$c scan mark %x %y"
    bind $c <B3-Motion> "$c scan dragto %x %y"
    bind $c <MouseWheel> {
	%W yview scroll [expr {-%D}] units
    }
    bind $c <Option-MouseWheel> {
	%W yview scroll [expr {-10*%D}] units
    }
    bind $c <Shift-MouseWheel> {
	%W xview scroll [expr {-%D}] units
    }
    bind $c <Shift-Option-MouseWheel> {
	%W xview scroll [expr {-10*%D}] units
    }
} else {
    bind $c <Button-2> "$c scan mark %x %y"
    bind $c <B2-Motion> "$c scan dragto %x %y"
    # We must make sure that positive and negative movements are rounded
    # equally to integers, avoiding the problem that
    #     (int)1/-30 = -1,
    # but
    #     (int)-1/-30 = 0
    # The following code ensure equal +/- behaviour.
    bind $c <MouseWheel> {
	if {%D >= 0} {
	%W yview scroll [expr {-(%D)}] units
    }
	    %W yview scroll [expr {%D/-30}] units
	} else {
	    %W yview scroll [expr {(%D-29)/-30}] units
	}
    }
    bind $c <Option-MouseWheel> {
	if {%D >= 0} {
	%W yview scroll [expr {-10 * (%D)}] units
    }
	    %W yview scroll [expr {%D/-3}] units
	} else {
	    %W yview scroll [expr {(%D-2)/-3}] units
	}
    }
    bind $c <Shift-MouseWheel> {
	if {%D >= 0} {
	%W xview scroll [expr {-(%D)}] units
    }
	    %W xview scroll [expr {%D/-30}] units
	} else {
	    %W xview scroll [expr {(%D-29)/-30}] units
	}
    }
    bind $c <Shift-Option-MouseWheel> {
	if {%D >= 0} {
	%W xview scroll [expr {-10 * (%D)}] units
	    %W xview scroll [expr {%D/-3}] units
    }
} else {
	} else {
    bind $c <MouseWheel> {
	%W yview scroll [expr {-(%D / 30)}] units
    }
	    %W xview scroll [expr {(%D-2)/-3}] units
	}
    bind $c <Shift-MouseWheel> {
	%W xview scroll [expr {-(%D / 30)}] units
    }
}

if {[tk windowingsystem] eq "x11"} {
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/
    bind $c <4> {
    bind $c <Button-4> {
	if {!$tk_strictMotif} {
	    %W yview scroll -5 units
	}
    }
    bind $c <Shift-4> {
    bind $c <Shift-Button-4> {
	if {!$tk_strictMotif} {
	    %W xview scroll -5 units
	}
    }
    bind $c <5> {
    bind $c <Button-5> {
	if {!$tk_strictMotif} {
	    %W yview scroll 5 units
	}
    }
    bind $c <Shift-5> {
    bind $c <Shift-Button-5> {
	if {!$tk_strictMotif} {
	    %W xview scroll 5 units
	}
    }
}


Changes to library/demos/ctext.tcl.
37
38
39
40
41
42
43
44

45
46

47
48

49
50
51
52



53


54
55
56
57
58
59
60
61

62
63
64
65
66
67
68

69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

88
89
90
91
92
93
94
37
38
39
40
41
42
43

44
45

46
47

48
49
50
51
52
53
54
55

56
57
58
59
60
61
62
63
64

65
66
67
68
69
70
71

72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90

91
92
93
94
95
96
97
98







-
+

-
+

-
+




+
+
+
-
+
+







-
+






-
+


















-
+







set textFont {Helvetica 24}

$c create rectangle 245 195 255 205 -outline black -fill red

# First, create the text item and give it bindings so it can be edited.

$c addtag text withtag [$c create text 250 200 -text "This is just a string of text to demonstrate the text facilities of canvas widgets. Bindings have been defined to support editing (see above)." -width 440 -anchor n -font $textFont -justify left]
$c bind text <1> "textB1Press $c %x %y"
$c bind text <Button-1> "textB1Press $c %x %y"
$c bind text <B1-Motion> "textB1Move $c %x %y"
$c bind text <Shift-1> "$c select adjust current @%x,%y"
$c bind text <Shift-Button-1> "$c select adjust current @%x,%y"
$c bind text <Shift-B1-Motion> "textB1Move $c %x %y"
$c bind text <KeyPress> "textInsert $c %A"
$c bind text <Key> "textInsert $c %A"
$c bind text <Return> "textInsert $c \\n"
$c bind text <Control-h> "textBs $c"
$c bind text <BackSpace> "textBs $c"
$c bind text <Delete> "textDel $c"
if {[tk windowingsystem] eq "aqua" && ![package vsatisfies [package provide Tk] 8.7-]} {
    $c bind text <Button-3> "textPaste $c @%x,%y"
} else {
$c bind text <2> "textPaste $c @%x,%y"
    $c bind text <Button-2> "textPaste $c @%x,%y"
}

# Next, create some items that allow the text's anchor position
# to be edited.

proc mkTextConfigBox {w x y option value color} {
    set item [$w create rect $x $y [expr {$x+30}] [expr {$y+30}] \
	    -outline black -fill $color -width 1]
    $w bind $item <1> "$w itemconf text $option $value"
    $w bind $item <Button-1> "$w itemconf text $option $value"
    $w addtag config withtag $item
}
proc mkTextConfigPie {w x y a option value color} {
    set item [$w create arc $x $y [expr {$x+90}] [expr {$y+90}] \
	    -start [expr {$a-15}] -extent 30 -outline black -fill $color \
	    -width 1]
    $w bind $item <1> "$w itemconf text $option $value"
    $w bind $item <Button-1> "$w itemconf text $option $value"
    $w addtag config withtag $item
}

set x 50
set y 50
set color LightSkyBlue1
mkTextConfigBox $c $x $y -anchor se $color
mkTextConfigBox $c [expr {$x+30}] [expr {$y   }] -anchor s      $color
mkTextConfigBox $c [expr {$x+60}] [expr {$y   }] -anchor sw     $color
mkTextConfigBox $c [expr {$x   }] [expr {$y+30}] -anchor e      $color
mkTextConfigBox $c [expr {$x+30}] [expr {$y+30}] -anchor center $color
mkTextConfigBox $c [expr {$x+60}] [expr {$y+30}] -anchor w      $color
mkTextConfigBox $c [expr {$x   }] [expr {$y+60}] -anchor ne     $color
mkTextConfigBox $c [expr {$x+30}] [expr {$y+60}] -anchor n      $color
mkTextConfigBox $c [expr {$x+60}] [expr {$y+60}] -anchor nw     $color
set item [$c create rect \
	[expr {$x+40}] [expr {$y+40}] [expr {$x+50}] [expr {$y+50}] \
	-outline black -fill red]
$c bind $item <1> "$c itemconf text -anchor center"
$c bind $item <Button-1> "$c itemconf text -anchor center"
$c create text [expr {$x+45}] [expr {$y-5}] \
	-text {Text Position}  -anchor s  -font {Times 20}  -fill brown

# Now create some items that allow the text's angle to be changed.

set x 205
set y 50
Changes to library/demos/dialog1.tcl.
1
2
3
4
5
6
7
8




9
10
11
12
13
14

15
16
17
18
19
20
21
22
23
24


25
1
2
3
4




5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21
22


23
24
25




-
-
-
-
+
+
+
+





-
+








-
-
+
+

# dialog1.tcl --
#
# This demonstration script creates a dialog box with a local grab.

interp create slave
load {} Tk slave
slave eval {
    wm title . slave
interp create child
load {} Tk child
child eval {
    wm title . child
    wm geometry . +700+30
    pack [text .t -width 30 -height 10]
}

after idle {.dialog1.msg configure -wraplength 4i}
set i [tk_dialog .dialog1 "Dialog with local grab" {This is a modal dialog box.  It uses Tk's "grab" command to create a "local grab" on the dialog box.  The grab prevents any mouse or keyboard events from getting to any other windows in the application until you have answered the dialog by invoking one of the buttons below.  However, you can still interact with other applications.  For example, you should be able to edit text in the window named "slave" which was created by a slave interpreter.} \
set i [tk_dialog .dialog1 "Dialog with local grab" {This is a modal dialog box.  It uses Tk's "grab" command to create a "local grab" on the dialog box.  The grab prevents any mouse or keyboard events from getting to any other windows in the application until you have answered the dialog by invoking one of the buttons below.  However, you can still interact with other applications.  For example, you should be able to edit text in the window named "child" which was created by a child interpreter.} \
info 0 OK Cancel {Show Code}]

switch $i {
    0 {puts "You pressed OK"}
    1 {puts "You pressed Cancel"}
    2 {showCode .dialog1}
}

if {[interp exists slave]} {
    interp delete slave
if {[interp exists child]} {
    interp delete child
}
Changes to library/demos/entry1.tcl.
12
13
14
15
16
17
18
19

20
21
22
23
24
25
26
27
28

29
30
31
32
33
34
12
13
14
15
16
17
18

19
20
21
22
23
24
25
26
27

28
29
30
31
32
33
34







-
+








-
+






set w .entry1
catch {destroy $w}
toplevel $w
wm title $w "Entry Demonstration (no scrollbars)"
wm iconname $w "entry1"
positionWindow $w

label $w.msg -font $font -wraplength 5i -justify left -text "Three different entries are displayed below.  You can add characters by pointing, clicking and typing.  The normal Motif editing characters are supported, along with many Emacs bindings.  For example, Backspace and Control-h delete the character to the left of the insertion cursor and Delete and Control-d delete the chararacter to the right of the insertion cursor.  For entries that are too large to fit in the window all at once, you can scan through the entries by dragging with mouse button2 pressed."
label $w.msg -font $font -wraplength 5i -justify left -text "Three different entries are displayed below.  You can add characters by pointing, clicking and typing.  The normal Motif editing characters are supported, along with many Emacs bindings.  For example, Backspace and Control-h delete the character to the left of the insertion cursor and Delete and Control-d delete the chararacter to the right of the insertion cursor.  For entries that are too large to fit in the window all at once, you can scan through the entries by dragging with mouse the middle mouse button pressed."
pack $w.msg -side top

## See Code / Dismiss buttons
set btns [addSeeDismiss $w.buttons $w]
pack $btns -side bottom -fill x

entry $w.e1
entry $w.e2
entry $w.e3
entry $w.e3 -placeholder {Enter text here} -placeholderforeground gray75
pack $w.e1 $w.e2 $w.e3 -side top -pady 5 -padx 10 -fill x

$w.e1 insert 0 "Initial value"
$w.e2 insert end "This entry contains a long value, much too long "
$w.e2 insert end "to fit in the window at one time, so long in fact "
$w.e2 insert end "that you'll have to scan or scroll to see the end."
Changes to library/demos/entry2.tcl.
12
13
14
15
16
17
18
19

20
21
22
23
24
25
26
12
13
14
15
16
17
18

19
20
21
22
23
24
25
26







-
+







set w .entry2
catch {destroy $w}
toplevel $w
wm title $w "Entry Demonstration (with scrollbars)"
wm iconname $w "entry2"
positionWindow $w

label $w.msg -font $font -wraplength 5i -justify left -text "Three different entries are displayed below, with a scrollbar for each entry.  You can add characters by pointing, clicking and typing.  The normal Motif editing characters are supported, along with many Emacs bindings.  For example, Backspace and Control-h delete the character to the left of the insertion cursor and Delete and Control-d delete the chararacter to the right of the insertion cursor.  For entries that are too large to fit in the window all at once, you can scan through the entries with the scrollbars, or by dragging with mouse button2 pressed."
label $w.msg -font $font -wraplength 5i -justify left -text "Three different entries are displayed below, with a scrollbar for each entry.  You can add characters by pointing, clicking and typing.  The normal Motif editing characters are supported, along with many Emacs bindings.  For example, Backspace and Control-h delete the character to the left of the insertion cursor and Delete and Control-d delete the chararacter to the right of the insertion cursor.  For entries that are too large to fit in the window all at once, you can scan through the entries with the scrollbars, or by dragging with the middle mouse button pressed."
pack $w.msg -side top

## See Code / Dismiss buttons
set btns [addSeeDismiss $w.buttons $w]
pack $btns -side bottom -fill x

frame $w.frame -borderwidth 10
40
41
42
43
44
45
46

40
41
42
43
44
45
46
47







+
pack $w.frame.e1 $w.frame.s1 $w.frame.spacer1 $w.frame.e2 $w.frame.s2 \
	$w.frame.spacer2 $w.frame.e3 $w.frame.s3 -side top -fill x

$w.frame.e1 insert 0 "Initial value"
$w.frame.e2 insert end "This entry contains a long value, much too long "
$w.frame.e2 insert end "to fit in the window at one time, so long in fact "
$w.frame.e2 insert end "that you'll have to scan or scroll to see the end."
$w.frame.e3 configure -placeholder {Enter text here} -placeholderforeground gray75
Changes to library/demos/entry3.tcl.
60
61
62
63
64
65
66
67

68
69
70
71
72
73

74
75
76
77
78
79
80
60
61
62
63
64
65
66

67
68
69
70
71
72

73
74
75
76
77
78
79
80







-
+





-
+







	after 200 [list focusAndFlash $W $fg $bg [expr {$count-1}]]
    }
}

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.

# Initial content for the third entry widget
98
99
100
101
102
103
104
105

106
107
108
109
110
111
112
98
99
100
101
102
103
104

105
106
107
108
109
110
111
112







-
+







# vmode - The widget's validation mode
# idx -	  The index where replacement is to occur
# char -  The character (or string, though that will always be
#	  refused) to be overwritten at that point.

proc validatePhoneChange {W vmode idx char} {
    global phoneNumberMap entry3content
    if {$idx == -1} {return 1}
    if {$idx < 0} {return 1}
    after idle [list $W configure -validate $vmode -invcmd bell]
    if {
	!($idx<3 || $idx==6 || $idx==7 || $idx==11 || $idx>15) &&
	[string match {[0-9A-Za-z]} $char]
    } then {
	$W delete $idx
	$W insert $idx [string map $phoneNumberMap $char]
157
158
159
160
161
162
163
164

165
166
167
168
169
170
171
172
173
174
175
176
177

178
179
180
181
182
183
184
185
157
158
159
160
161
162
163

164
165
166
167
168
169
170
171
172
173
174
175
176

177
178
179
180
181
182
183
184
185







-
+












-
+








	bell
	return -code break
    }
}

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 <FocusIn> {
    if {"%d" ne "NotifyAncestor"} {
	%W icursor 3
	after idle {%W selection clear}
    }
}
bind $w.l3.e <<PrevChar>> {phoneSkipLeft  %W}
bind $w.l3.e <<NextChar>> {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
Changes to library/demos/floor.tcl.
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359



1360
1361




1362
1363



1364
1365
1366
1350
1351
1352
1353
1354
1355
1356



1357
1358
1359
1360
1361
1362
1363
1364
1365


1366
1367
1368
1369
1370
1371







-
-
-
+
+
+


+
+
+
+
-
-
+
+
+



    set colors(active) black
}
set activeFloor ""
floorDisplay $c 3

# Set up event bindings for canvas:

$c bind floor1 <1> "floorDisplay $c 1"
$c bind floor2 <1> "floorDisplay $c 2"
$c bind floor3 <1> "floorDisplay $c 3"
$c bind floor1 <Button-1> "floorDisplay $c 1"
$c bind floor2 <Button-1> "floorDisplay $c 2"
$c bind floor3 <Button-1> "floorDisplay $c 3"
$c bind room <Enter> "newRoom $c"
$c bind room <Leave> {set currentRoom ""}
if {[tk windowingsystem] eq "aqua" && ![package vsatisfies [package provide Tk] 8.7-]} {
    bind $c <Button-3> "$c scan mark %x %y"
    bind $c <B3-Motion> "$c scan dragto %x %y"
} else {
bind $c <2> "$c scan mark %x %y"
bind $c <B2-Motion> "$c scan dragto %x %y"
    bind $c <Button-2> "$c scan mark %x %y"
    bind $c <B2-Motion> "$c scan dragto %x %y"
}
bind $c <Destroy> "unset currentRoom"
set currentRoom ""
trace variable currentRoom w "roomChanged $c"
Changes to library/demos/fontchoose.tcl.
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69


51
52
53
54
55
56
57




58
59
60
61
62
63
64
65
66
67







-
-
-
-








+
+

ttk::button $f.font -text "Set font ..." -command [list SelectFont $w]

grid $f.msg $f.vs -sticky news
grid $f.font -    -sticky e
grid columnconfigure $f 0 -weight 1
grid rowconfigure $f 0 -weight 1
bind $w <Visibility> {
    bind %W <Visibility> {}
    grid propagate %W.f 0
}

## See Code / Dismiss buttons
set btns [addSeeDismiss $w.buttons $w]

grid $f -sticky news
grid $btns -sticky ew
grid columnconfigure $w 0 -weight 1
grid rowconfigure $w 0 -weight 1
update idletasks
grid propagate $f 0
Changes to library/demos/goldberg.tcl.
101
102
103
104
105
106
107
108

109
110
111
112
113
114
115
116

117
118

119
120
121
122
123
124
125
101
102
103
104
105
106
107

108
109
110
111
112
113
114
115

116
117

118
119
120
121
122
123
124
125







-
+







-
+

-
+







	    -side left -fill both -expand 1

    canvas $w.c -width 860 -height 730 -bg $C(bg) -highlightthickness 0
    $w.c config -scrollregion {0 0 1000 1000}	;# Kludge: move everything up
    $w.c yview moveto .05
    pack $w.c -in $w.screen -side top -fill both -expand 1

    bind $w.c <3> [list $w.pause invoke]
    bind $w.c <Button-3> [list $w.pause invoke]
    bind $w.c <Destroy> {
	after cancel $animationCallbacks(goldberg)
	unset animationCallbacks(goldberg)
    }
    DoCtrlFrame $w
    DoDetailFrame $w
    if {[tk windowingsystem] ne "aqua"} {
	ttk::button $w.show -text "\u00bb" -command [list ShowCtrl $w] -width 2
	ttk::button $w.show -text "»" -command [list ShowCtrl $w] -width 2
    } else {
	button $w.show -text "\u00bb" -command [list ShowCtrl $w] -width 2 -highlightbackground $C(bg)
	button $w.show -text "»" -command [list ShowCtrl $w] -width 2 -highlightbackground $C(bg)
    }
    place $w.show -in $w.c -relx 1 -rely 0 -anchor ne
    update
}

proc DoCtrlFrame {w} {
    global S
158
159
160
161
162
163
164
165

166
167
168
169
170
171
172
158
159
160
161
162
163
164

165
166
167
168
169
170
171
172







-
+







    trace variable ::S(speed) w	  [list ActiveGUI $w]

    grid $w.message -in $w.ctrl -row 98 -sticky ew -pady 5
    grid $w.message.e -sticky nsew
    grid $w.speed -in $w.ctrl -row 99 -sticky ew -pady {0 5}
    pack $w.speed.scale -fill both -expand 1
    grid $w.about -in $w.ctrl -row 100 -sticky ew
    bind $w.reset <3> {set S(mode) -1}		;# Debugging
    bind $w.reset <Button-3> {set S(mode) -1}		;# Debugging

    ## See Code / Dismiss buttons hack!
    set btns [addSeeDismiss $w.ctrl.buttons $w]
    grid [ttk::separator $w.ctrl.sep] -sticky ew -pady 4
    set i 0
    foreach b [winfo children $btns] {
	if {[winfo class $b] eq "TButton"} {
200
201
202
203
204
205
206
207

208
209
210

211
212
213
214
215
216
217
200
201
202
203
204
205
206

207
208
209

210
211
212
213
214
215
216
217







-
+


-
+







    grid columnconfigure $w2 1 -weight 1
}

# Map or unmap the ctrl window
proc ShowCtrl {w} {
    if {[winfo ismapped $w.ctrl]} {
	pack forget $w.ctrl
	$w.show config -text "\u00bb"
	$w.show config -text "»"
    } else {
	pack $w.ctrl -side right -fill both -ipady 5
	$w.show config -text "\u00ab"
	$w.show config -text "»"
    }
}

proc DrawAll {w} {
    ResetStep
    $w.c delete all
    for {set i 0} {1} {incr i} {
338
339
340
341
342
343
344
345

346
347
348
349
350
351
352
338
339
340
341
342
343
344

345
346
347
348
349
350
351
352







-
+







    set color $::C(0)
    set xy {579 119}
    $w.c create text $xy -text "START HERE!" -fill $color -anchor w \
	    -tag I0 -font {{Times Roman} 12 italic bold}
    set xy {719 119 763 119}
    $w.c create line $xy -tag I0 -fill $color -width 5 -arrow last \
	    -arrowshape {18 18 5}
    $w.c bind I0 <1> Start
    $w.c bind I0 <Button-1> Start
}
proc Move0 {w {step {}}} {
    set step [GetStep 0 $step]

    if {$::S(mode) > $::MSTART} {		;# Start the ball rolling
	MoveAbs $w I0 {-100 -100}		;# Hide the banner
	return 2
368
369
370
371
372
373
374
375

376
377
378
379
380
381
382
368
369
370
371
372
373
374

375
376
377
378
379
380
381
382







-
+







    set xy {844 133 800 133 800 346 820 346 820 168 844 168 844 133}
    $w.c create poly $xy -width 3 -fill $color -outline {}
    set xy {771 133 685 133 685 168 751 168 751 346 771 346 771 133}
    $w.c create poly $xy -width 3 -fill $color -outline {}

    set xy [box 812 122 9]
    $w.c create oval $xy -tag I1 -fill $color2 -outline {}
    $w.c bind I1 <1> Start
    $w.c bind I1 <Button-1> Start
}
proc Move1 {w {step {}}} {
    set step [GetStep 1 $step]
    set pos {
	{807 122} {802 122} {797 123} {793 124} {789 129} {785 153}
	{785 203} {785 278 x} {785 367} {810 392} {816 438} {821 503}
	{824 585 y} {838 587} {848 593} {857 601} {-100 -100}
1616
1617
1618
1619
1620
1621
1622
1623

1624
1625
1626
1627
1628
1629
1630
1616
1617
1618
1619
1620
1621
1622

1623
1624
1625
1626
1627
1628
1629
1630







-
+







    global S
    set step [GetStep 26 $step]

    if {$step >= 3} {
	$w.c delete I24 I26
	$w.c create text 430 755 -anchor s -tag I26 \
		-text "click to continue" -font {{Times Roman} 24 bold}
	bind $w.c <1> [list Reset $w]
	bind $w.c <Button-1> [list Reset $w]
	return 4
    }

    $w.c scale I24 {*}[Centroid $w I24] .8 .8
    $w.c move I24 0 60
    $w.c itemconfig I24t -font [list {Times Roman} [expr {30 - 6*$step}] bold]
    return 1
1671
1672
1673
1674
1675
1676
1677
1678

1679
1680
1681
1682
1683
1684
1685
1671
1672
1673
1674
1675
1676
1677

1678
1679
1680
1681
1682
1683
1684
1685







-
+








    return [list $xx $yy]
}

proc Reset {w} {
    global S
    DrawAll $w
    bind $w.c <1> {}
    bind $w.c <Button-1> {}
    set S(mode) $::MSTART
    set S(active) 0
}

# Each Move## keeps its state info in STEP, this retrieves and increments it
proc GetStep {who step} {
    global STEP
Changes to library/demos/image2.tcl.
91
92
93
94
95
96
97
98

99
100
101
102
103
104
105
91
92
93
94
95
96
97

98
99
100
101
102
103
104
105







-
+







pack $w.dir.b -side left -fill y    -padx {0 2m} -pady 2m
labelframe $w.f -text "File:" -padx 2m -pady 2m

listbox $w.f.list -width 20 -height 10 -yscrollcommand "$w.f.scroll set"
ttk::scrollbar $w.f.scroll -command "$w.f.list yview"
pack $w.f.list $w.f.scroll -side left -fill y -expand 1
$w.f.list insert 0 earth.gif earthris.gif teapot.ppm
bind $w.f.list <Double-1> "loadImage $w %x %y"
bind $w.f.list <Double-Button-1> "loadImage $w %x %y"

catch {image delete image2a}
image create photo image2a
labelframe $w.image -text "Image:"
label $w.image.image -image image2a
pack $w.image.image -padx 2m -pady 2m

Changes to library/demos/items.tcl.
13
14
15
16
17
18
19
20

21
22
23
24
25
26
27
13
14
15
16
17
18
19

20
21
22
23
24
25
26
27







-
+







catch {destroy $w}
toplevel $w
wm title $w "Canvas Item Demonstration"
wm iconname $w "Items"
positionWindow $w
set c $w.frame.c

label $w.msg -font $font -wraplength 5i -justify left -text "This window contains a canvas widget with examples of the various kinds of items supported by canvases.  The following operations are supported:\n  Button-1 drag:\tmoves item under pointer.\n  Button-2 drag:\trepositions view.\n  Button-3 drag:\tstrokes out area.\n  Ctrl+f:\t\tprints items under area."
label $w.msg -font $font -wraplength 5i -justify left -text "This window contains a canvas widget with examples of the various kinds of items supported by canvases.  The following operations are supported:\n  Left-Button drag:\tmoves item under pointer.\n  Middle-Button drag:\trepositions view.\n  Right-Button drag:\tstrokes out area.\n  Ctrl+f:\t\tprints items under area."
pack $w.msg -side top

## See Code / Dismiss buttons
set btns [addSeeDismiss $w.buttons $w]
pack $btns -side bottom -fill x

frame $w.frame
167
168
169
170
171
172
173
174
175
176
177
178
179













180
181

182
183
184
185
186
187
188
167
168
169
170
171
172
173






174
175
176
177
178
179
180
181
182
183
184
185
186
187

188
189
190
191
192
193
194
195







-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+







$c create window 28.5c 17.5c -window $c.scale -anchor n -tags item
$c create text 21c 17.9c -text Button: -anchor sw
$c create text 21c 20.9c -text Entry: -anchor sw
$c create text 28.5c 17.4c -text Scale: -anchor s

# Set up event bindings for canvas:

$c bind item <Any-Enter> "itemEnter $c"
$c bind item <Any-Leave> "itemLeave $c"
bind $c <2> "$c scan mark %x %y"
bind $c <B2-Motion> "$c scan dragto %x %y"
bind $c <3> "itemMark $c %x %y"
bind $c <B3-Motion> "itemStroke $c %x %y"
$c bind item <Enter> "itemEnter $c"
$c bind item <Leave> "itemLeave $c"
if {[tk windowingsystem] eq "aqua" && ![package vsatisfies [package provide Tk] 8.7-]} {
    bind $c <Button-2> "itemMark $c %x %y"
    bind $c <B2-Motion> "itemStroke $c %x %y"
    bind $c <Button-3> "$c scan mark %x %y"
    bind $c <B3-Motion> "$c scan dragto %x %y"
} else {
    bind $c <Button-2> "$c scan mark %x %y"
    bind $c <B2-Motion> "$c scan dragto %x %y"
    bind $c <Button-3> "itemMark $c %x %y"
    bind $c <B3-Motion> "itemStroke $c %x %y"
}
bind $c <<NextChar>> "itemsUnderArea $c"
bind $c <1> "itemStartDrag $c %x %y"
bind $c <Button-1> "itemStartDrag $c %x %y"
bind $c <B1-Motion> "itemDrag $c %x %y"

# Utility procedures for highlighting the item under the pointer:

proc itemEnter {c} {
    global restoreCmd

246
247
248
249
250
251
252
253

254
255
256
257
258
259
260

261
262
263
264
265
266
267
253
254
255
256
257
258
259

260
261
262
263
264
265
266

267
268
269
270
271
272
273
274







-
+






-
+







}

proc itemsUnderArea {c} {
    global areaX1 areaY1 areaX2 areaY2
    set area [$c find withtag area]
    set items ""
    foreach i [$c find enclosed $areaX1 $areaY1 $areaX2 $areaY2] {
	if {[lsearch [$c gettags $i] item] != -1} {
	if {[lsearch [$c gettags $i] item] >= 0} {
	    lappend items $i
	}
    }
    puts stdout "Items enclosed by area: $items"
    set items ""
    foreach i [$c find overlapping $areaX1 $areaY1 $areaX2 $areaY2] {
	if {[lsearch [$c gettags $i] item] != -1} {
	if {[lsearch [$c gettags $i] item] >= 0} {
	    lappend items $i
	}
    }
    puts stdout "Items overlapping area: $items"
}

set areaX1 0
Changes to library/demos/ixset.
50
51
52
53
54
55
56
57

58
59
60
61
62
63
64
50
51
52
53
54
55
56

57
58
59
60
61
62
63
64







-
+







    global mouseacc ;	set mouseacc	"3/1"
    global mousethr ;	set mousethr	4
    global screenbla ;	set screenbla	"blank"
    global screentim ;	set screentim	600
    global screencyc ;	set screencyc	600

    set xfd [open "|xset q" r]
    while {[gets $xfd line] > -1} {
    while {[gets $xfd line] >= 0} {
	switch -- [lindex $line 0] {
	    auto {
		set rpt [lindex $line 1]
		if {$rpt eq "repeat:"} {
		    set kbdrep [lindex $line 2]
		    set kbdcli [lindex $line 6]
		}
193
194
195
196
197
198
199
200

201
202
203
204
205
206
207
193
194
195
196
197
198
199

200
201
202
203
204
205
206
207







-
+







    button .buttons.quit   -default normal -command quit   -text "Quit"

    pack .buttons.ok .buttons.apply .buttons.cancel .buttons.quit \
	    -side left -expand yes -pady 5

    bind . <Return> {.buttons.ok   flash; .buttons.ok   invoke}
    bind . <Escape> {.buttons.quit flash; .buttons.quit invoke}
    bind . <1> {
    bind . <Button-1> {
	if {![string match .buttons* %W]} {
	    .buttons.apply  configure -state normal
	    .buttons.cancel configure -state normal
	}
    }
    bind . <Key> {
	if {![string match .buttons* %W]} {
Changes to library/demos/knightstour.tcl.
1

2
3
4
5
6
7
8

1
2
3
4
5
6
7
8
-
+







# Copyright (C) 2008 Pat Thoyts <[email protected]>
# Copyright © 2008 Pat Thoyts <[email protected]>
#
#	Calculate a Knight's tour of a chessboard.
#
#	This uses Warnsdorff's rule to calculate the next square each
#	time. This specifies that the next square should be the one that
#	has the least number of available moves.
#
17
18
19
20
21
22
23
24

25
26
27
28
29
30
31
32

33
34
35
36
37
38
39
40
41
42
43
44

45
46
47
48
49
50
51
52
53
54
55
56
57
58

59
60
61
62
63
64
65
17
18
19
20
21
22
23

24
25
26
27
28
29
30
31

32
33
34
35
36
37
38
39
40
41
42
43

44
45
46
47
48
49
50
51
52
53
54
55
56
57

58
59
60
61
62
63
64
65







-
+







-
+











-
+













-
+







#	If the call to the Edgemost function is commented out you can see
#	this occur.
#
#	You can drag the knight to a specific square to start if you wish.
#	If you let it repeat then it will choose random start positions
#	for each new tour.

package require Tk 8.5
package require Tk

# Return a list of accessible squares from a given square
proc ValidMoves {square} {
    set moves {}
    foreach pair {{-1 -2} {-2 -1} {-2 1} {-1 2} {1 2} {2 1} {2 -1} {1 -2}} {
        set col [expr {($square % 8) + [lindex $pair 0]}]
        set row [expr {($square / 8) + [lindex $pair 1]}]
        if {$row > -1 && $row < 8 && $col > -1 && $col < 8} {
        if {$row >= 0 && $row < 8 && $col >= 0 && $col < 8} {
            lappend moves [expr {$row * 8 + $col}]
        }
    }
    return $moves
}

# Return the number of available moves for this square
proc CheckSquare {square} {
    variable visited
    set moves 0
    foreach test [ValidMoves $square] {
        if {[lsearch -exact -integer $visited $test] == -1} {
        if {[lsearch -exact -integer $visited $test] < 0} {
            incr moves
        }
    }
    return $moves
}

# Select the next square to move to. Returns -1 if there are no available
# squares remaining that we can move to.
proc Next {square} {
    variable visited
    set minimum 9
    set nextSquare -1
    foreach testSquare [ValidMoves $square] {
        if {[lsearch -exact -integer $visited $testSquare] == -1} {
        if {[lsearch -exact -integer $visited $testSquare] < 0} {
            set count [CheckSquare $testSquare]
            if {$count < $minimum} {
                set minimum $count
                set nextSquare $testSquare
            } elseif {$count == $minimum} {
                # to remove the enhancement to Warnsdorff's rule
                # remove the next line:
186
187
188
189
190
191
192
193

194
195
196
197
198
199
200
201
202
203
204
205
206
207
208

209
210
211

212
213
214
215
216
217
218
219
220
221

222
223
224
225
226
227
228
186
187
188
189
190
191
192

193
194
195
196
197
198
199
200
201
202
203
204
205
206
207

208
209
210

211
212
213
214
215
216
217
218
219
220

221
222
223
224
225
226
227
228







-
+














-
+


-
+









-
+







    ttk::scale $dlg.tf.sc  -from 8 -to 2000 -command [list SetDelay] \
        -variable [namespace which -variable delay]
    ttk::checkbutton $dlg.tf.cc -text Repeat \
        -variable [namespace which -variable continuous]
    ttk::button $dlg.tf.b1 -text Start -command [list Tour $dlg]
    ttk::button $dlg.tf.b2 -text Exit -command [list Exit $dlg]
    set square 0
    for {set row 7} {$row != -1} {incr row -1} {
    for {set row 7} {$row >= 0} {incr row -1} {
        for {set col 0} {$col < 8} {incr col} {
            if {(($col & 1) ^ ($row & 1))} {
                set fill tan3 ; set dfill tan4
            } else {
                set fill bisque ; set dfill bisque3
            }
            set coords [list [expr {$col * 30 + 4}] [expr {$row * 30 + 4}] \
                            [expr {$col * 30 + 30}] [expr {$row * 30 + 30}]]
            $c create rectangle $coords -fill $fill -disabledfill $dfill \
                -width 2 -state disabled -outline black
        }
    }
    if {[tk windowingsystem] ne "x11"} {
        catch {eval font create KnightFont -size -24}
        $c create text 0 0 -font KnightFont -text "\u265e" \
        $c create text 0 0 -font KnightFont -text "" \
            -anchor nw -tags knight -fill black -activefill "#600000"
    } else {
        # On X11 we cannot reliably tell if the \u265e glyph is available
        # On X11 we cannot reliably tell if the  glyph is available
        # so just use a polygon
        set pts {
            2 25   24 25  21 19   20 8   14 0   10 0   0 13   0 16
            2 17    4 14   5 15    3 17   5 17   9 14  10 15  5 21
        }
        $c create polygon $pts -tag knight -offset 8 \
            -fill black -activefill "#600000"
    }
    $c moveto knight {*}[lrange [$c coords [expr {1 + int(rand() * 64)}]] 0 1]
    $c bind knight <ButtonPress-1> [namespace code [list DragStart %W %x %y]]
    $c bind knight <Button-1> [namespace code [list DragStart %W %x %y]]
    $c bind knight <Motion> [namespace code [list DragMotion %W %x %y]]
    $c bind knight <ButtonRelease-1> [namespace code [list DragEnd %W %x %y]]

    grid $c $f.txt $f.vs  -sticky news
    grid rowconfigure    $f 0 -weight 1
    grid columnconfigure $f 1 -weight 1

Changes to library/demos/menu.tcl.
59
60
61
62
63
64
65
66

67
68
69
70
71
72
73
59
60
61
62
63
64
65

66
67
68
69
70
71
72
73







-
+







} elseif {[tk windowingsystem] == "win32"} {
    set modifier Control
} 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
menu $m -tearoff 0
$m add command -label "Print hello" \
127
128
129
130
131
132
133
134

135
136
137
138
139
140
141
142
143







144
145
146



147
148
149















150
151
152
153
154
155
156
127
128
129
130
131
132
133

134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156



157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178







-
+









+
+
+
+
+
+
+



+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	    puts "You invoked the $i bitmap" ]
}
$m entryconfigure 2 -columnbreak 1

set m $w.menu.more
$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} {Make life meaningful}} {
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\""]
}
$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\
		menu entry." {} 0 OK ]

$m entryconfigure "Does almost nothing also" -image lilearth -compound left \
	-command [list \
	tk_dialog $w.compound {Compound Menu Entry} \
		"The menu entry you invoked displays both a image and a\
		text string.  Other than this, it is just like any other\
		menu entry." {} 0 OK ]

set m $w.menu.colors
$w.menu add cascade -label "Colors" -menu $m -underline 1
menu $m -tearoff 1
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} {
    $m add command -label $i -background $i -command [list \
	    puts "You invoked \"$i\"" ]
    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 <<MenuSelect>> {
    global $menustatus
    if {[catch {%W entrycget active -label} label]} {
Changes to library/demos/pendulum.tcl.
46
47
48
49
50
51
52
53
54


55
56
57
58
59
60
61
46
47
48
49
50
51
52


53
54
55
56
57
58
59
60
61







-
-
+
+







$w.k create line 160 200 160 0 -fill grey75 -arrow last -tags y_axis
$w.k create line 0 100 320 100 -fill grey75 -arrow last -tags x_axis
for {set i 90} {$i>=0} {incr i -10} {
    # Coordinates of these items don't matter; they will be set properly below
    $w.k create line 0 0 1 1 -smooth true -tags graph$i -fill grey$i
}

$w.k create text 0 0 -anchor ne -text "\u03b8" -tags label_theta
$w.k create text 0 0 -anchor ne -text "\u03b4\u03b8" -tags label_dtheta
$w.k create text 0 0 -anchor ne -text "θ" -tags label_theta
$w.k create text 0 0 -anchor ne -text "δθ" -tags label_dtheta
pack $w.k -in $w.p.l2 -fill both -expand true

# Initialize some variables
set points {}
set Theta   45.0
set dTheta   0.0
set pi       3.1415926535897933
109
110
111
112
113
114
115
116

117
118
119
120
121
122
123
109
110
111
112
113
114
115

116
117
118
119
120
121
122
123







-
+







# button. Also note that both canvases are sensitive to <Configure>
# events, which allows them to find out when they have been resized by
# the user.
bind $w.c <Destroy> {
    after cancel $animationCallbacks(pendulum)
    unset animationCallbacks(pendulum)
}
bind $w.c <1> {
bind $w.c <Button-1> {
    after cancel $animationCallbacks(pendulum)
    showPendulum %W at %x %y
}
bind $w.c <B1-Motion> {
    showPendulum %W at %x %y
}
bind $w.c <ButtonRelease-1> {
Changes to library/demos/plot.tcl.
51
52
53
54
55
56
57
58
59
60



61
62
63
64
65
66
67
51
52
53
54
55
56
57



58
59
60
61
62
63
64
65
66
67







-
-
-
+
+
+







    set y [expr {250 - (4*[lindex $point 1])/5}]
    set item [$c create oval [expr {$x-6}] [expr {$y-6}] \
	    [expr {$x+6}] [expr {$y+6}] -width 1 -outline black \
	    -fill SkyBlue2]
    $c addtag point withtag $item
}

$c bind point <Any-Enter> "$c itemconfig current -fill red"
$c bind point <Any-Leave> "$c itemconfig current -fill SkyBlue2"
$c bind point <1> "plotDown $c %x %y"
$c bind point <Enter> "$c itemconfig current -fill red"
$c bind point <Leave> "$c itemconfig current -fill SkyBlue2"
$c bind point <Button-1> "plotDown $c %x %y"
$c bind point <ButtonRelease-1> "$c dtag selected"
bind $c <B1-Motion> "plotMove $c %x %y"

set plot(lastX) 0
set plot(lastY) 0

# plotDown --
Changes to library/demos/ruler.tcl.
73
74
75
76
77
78
79
80
81


82
83

84
85
86
87
88
89
90
73
74
75
76
77
78
79


80
81
82

83
84
85
86
87
88
89
90







-
-
+
+

-
+







    $c create text $x.15c .75c -text $i -anchor sw
}
$c addtag well withtag [$c create rect 13.2c 1c 13.8c 0.5c \
	-fill [lindex [$c config -bg] 4]]
$c addtag well withtag [rulerMkTab $c [winfo pixels $c 13.5c] \
	[winfo pixels $c .65c]]

$c bind well <1> "rulerNewTab $c %x %y"
$c bind tab <1> "rulerSelectTab $c %x %y"
$c bind well <Button-1> "rulerNewTab $c %x %y"
$c bind tab <Button-1> "rulerSelectTab $c %x %y"
bind $c <B1-Motion> "rulerMoveTab $c %x %y"
bind $c <Any-ButtonRelease-1> "rulerReleaseTab $c"
bind $c <ButtonRelease-1> "rulerReleaseTab $c"

# rulerNewTab --
# Does all the work of creating a tab stop, including creating the
# triangle object and adding tags to it to give it tab behavior.
#
# Arguments:
# c -		The canvas window.
Changes to library/demos/spin.tcl.
34
35
36
37
38
39
40
41

42
43
44
45
46
47
48
34
35
36
37
38
39
40

41
42
43
44
45
46
47
48







-
+








set australianCities {
    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
#entry $w.e3
pack $w.s1 $w.s2 $w.s3 -side top -pady 5 -padx 10 ;#-fill x
Changes to library/demos/square.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15


16
17
18
19
20
21

22
23
24
25
26
27
28
1
2
3
4
5
6
7
8
9
10
11
12
13


14
15
16
17
18
19
20

21
22
23
24
25
26
27
28













-
-
+
+





-
+







#!/bin/sh
# the next line restarts using wish \
exec wish "$0" ${1+"$@"}

# square --
# This script generates a demo application containing only a "square"
# widget.  It's only usable in the "tktest" application or if Tk has
# been compiled with tkSquare.c. This demo arranges the following
# 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

bind .s <1> {center %x %y}
bind .s <Button-1> {center %x %y}
bind .s <B1-Motion> {center %x %y}
bind .s a animate
focus .s

# The procedure below centers the square on a given position.

proc center {x y} {
Added library/demos/systray.tcl.

























































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 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
Changes to library/demos/tclIndex.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67





























































1
2
3
4
5
6
7
8



























































9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69








-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# Tcl autoload index file, version 2.0
# This file is generated by the "auto_mkindex" command
# and sourced to set up indexing information for one or
# more commands.  Typically each line is a command that
# sets an element in the auto_index array, where the
# element name is the name of a command and the value is
# a script that loads the command.

set auto_index(arrowSetup) [list source [file join $dir arrow.tcl]]
set auto_index(arrowMove1) [list source [file join $dir arrow.tcl]]
set auto_index(arrowMove2) [list source [file join $dir arrow.tcl]]
set auto_index(arrowMove3) [list source [file join $dir arrow.tcl]]
set auto_index(textLoadFile) [list source [file join $dir search.tcl]]
set auto_index(textSearch) [list source [file join $dir search.tcl]]
set auto_index(textToggle) [list source [file join $dir search.tcl]]
set auto_index(itemEnter) [list source [file join $dir items.tcl]]
set auto_index(itemLeave) [list source [file join $dir items.tcl]]
set auto_index(itemMark) [list source [file join $dir items.tcl]]
set auto_index(itemStroke) [list source [file join $dir items.tcl]]
set auto_index(itemsUnderArea) [list source [file join $dir items.tcl]]
set auto_index(itemStartDrag) [list source [file join $dir items.tcl]]
set auto_index(itemDrag) [list source [file join $dir items.tcl]]
set auto_index(butPress) [list source [file join $dir items.tcl]]
set auto_index(loadDir) [list source [file join $dir image2.tcl]]
set auto_index(loadImage) [list source [file join $dir image2.tcl]]
set auto_index(rulerMkTab) [list source [file join $dir ruler.tcl]]
set auto_index(rulerNewTab) [list source [file join $dir ruler.tcl]]
set auto_index(rulerSelectTab) [list source [file join $dir ruler.tcl]]
set auto_index(rulerMoveTab) [list source [file join $dir ruler.tcl]]
set auto_index(rulerReleaseTab) [list source [file join $dir ruler.tcl]]
set auto_index(mkTextConfig) [list source [file join $dir ctext.tcl]]
set auto_index(textEnter) [list source [file join $dir ctext.tcl]]
set auto_index(textInsert) [list source [file join $dir ctext.tcl]]
set auto_index(textPaste) [list source [file join $dir ctext.tcl]]
set auto_index(textB1Press) [list source [file join $dir ctext.tcl]]
set auto_index(textB1Move) [list source [file join $dir ctext.tcl]]
set auto_index(textBs) [list source [file join $dir ctext.tcl]]
set auto_index(textDel) [list source [file join $dir ctext.tcl]]
set auto_index(bitmapRow) [list source [file join $dir bitmap.tcl]]
set auto_index(scrollEnter) [list source [file join $dir cscroll.tcl]]
set auto_index(scrollLeave) [list source [file join $dir cscroll.tcl]]
set auto_index(scrollButton) [list source [file join $dir cscroll.tcl]]
set auto_index(textWindOn) [list source [file join $dir twind.tcl]]
set auto_index(textWindOff) [list source [file join $dir twind.tcl]]
set auto_index(textWindPlot) [list source [file join $dir twind.tcl]]
set auto_index(embPlotDown) [list source [file join $dir twind.tcl]]
set auto_index(embPlotMove) [list source [file join $dir twind.tcl]]
set auto_index(textWindDel) [list source [file join $dir twind.tcl]]
set auto_index(embDefBg) [list source [file join $dir twind.tcl]]
set auto_index(floorDisplay) [list source [file join $dir floor.tcl]]
set auto_index(newRoom) [list source [file join $dir floor.tcl]]
set auto_index(roomChanged) [list source [file join $dir floor.tcl]]
set auto_index(bg1) [list source [file join $dir floor.tcl]]
set auto_index(bg2) [list source [file join $dir floor.tcl]]
set auto_index(bg3) [list source [file join $dir floor.tcl]]
set auto_index(fg1) [list source [file join $dir floor.tcl]]
set auto_index(fg2) [list source [file join $dir floor.tcl]]
set auto_index(fg3) [list source [file join $dir floor.tcl]]
set auto_index(setWidth) [list source [file join $dir hscale.tcl]]
set auto_index(plotDown) [list source [file join $dir plot.tcl]]
set auto_index(plotMove) [list source [file join $dir plot.tcl]]
set auto_index(puzzleSwitch) [list source [file join $dir puzzle.tcl]]
set auto_index(setHeight) [list source [file join $dir vscale.tcl]]
set auto_index(showMessageBox) [list source [file join $dir msgbox.tcl]]
set auto_index(setColor) [list source [file join $dir clrpick.tcl]]
set auto_index(setColor_helper) [list source [file join $dir clrpick.tcl]]
set auto_index(fileDialog) [list source [file join $dir filebox.tcl]]
set auto_index(arrowSetup) [list source -encoding utf-8 [file join $dir arrow.tcl]]
set auto_index(arrowMove1) [list source -encoding utf-8 [file join $dir arrow.tcl]]
set auto_index(arrowMove2) [list source -encoding utf-8 [file join $dir arrow.tcl]]
set auto_index(arrowMove3) [list source -encoding utf-8 [file join $dir arrow.tcl]]
set auto_index(textLoadFile) [list source -encoding utf-8 [file join $dir search.tcl]]
set auto_index(textSearch) [list source -encoding utf-8 [file join $dir search.tcl]]
set auto_index(textToggle) [list source -encoding utf-8 [file join $dir search.tcl]]
set auto_index(itemEnter) [list source -encoding utf-8 [file join $dir items.tcl]]
set auto_index(itemLeave) [list source -encoding utf-8 [file join $dir items.tcl]]
set auto_index(itemMark) [list source -encoding utf-8 [file join $dir items.tcl]]
set auto_index(itemStroke) [list source -encoding utf-8 [file join $dir items.tcl]]
set auto_index(itemsUnderArea) [list source -encoding utf-8 [file join $dir items.tcl]]
set auto_index(itemStartDrag) [list source -encoding utf-8 [file join $dir items.tcl]]
set auto_index(itemDrag) [list source -encoding utf-8 [file join $dir items.tcl]]
set auto_index(butPress) [list source -encoding utf-8 [file join $dir items.tcl]]
set auto_index(loadDir) [list source -encoding utf-8 [file join $dir image2.tcl]]
set auto_index(loadImage) [list source -encoding utf-8 [file join $dir image2.tcl]]
set auto_index(rulerMkTab) [list source -encoding utf-8 [file join $dir ruler.tcl]]
set auto_index(rulerNewTab) [list source -encoding utf-8 [file join $dir ruler.tcl]]
set auto_index(rulerSelectTab) [list source -encoding utf-8 [file join $dir ruler.tcl]]
set auto_index(rulerMoveTab) [list source -encoding utf-8 [file join $dir ruler.tcl]]
set auto_index(rulerReleaseTab) [list source -encoding utf-8 [file join $dir ruler.tcl]]
set auto_index(mkTextConfig) [list source -encoding utf-8 [file join $dir ctext.tcl]]
set auto_index(textEnter) [list source -encoding utf-8 [file join $dir ctext.tcl]]
set auto_index(textInsert) [list source -encoding utf-8 [file join $dir ctext.tcl]]
set auto_index(textPaste) [list source -encoding utf-8 [file join $dir ctext.tcl]]
set auto_index(textB1Press) [list source -encoding utf-8 [file join $dir ctext.tcl]]
set auto_index(textB1Move) [list source -encoding utf-8 [file join $dir ctext.tcl]]
set auto_index(textBs) [list source -encoding utf-8 [file join $dir ctext.tcl]]
set auto_index(textDel) [list source -encoding utf-8 [file join $dir ctext.tcl]]
set auto_index(bitmapRow) [list source -encoding utf-8 [file join $dir bitmap.tcl]]
set auto_index(scrollEnter) [list source -encoding utf-8 [file join $dir cscroll.tcl]]
set auto_index(scrollLeave) [list source -encoding utf-8 [file join $dir cscroll.tcl]]
set auto_index(scrollButton) [list source -encoding utf-8 [file join $dir cscroll.tcl]]
set auto_index(textWindOn) [list source -encoding utf-8 [file join $dir twind.tcl]]
set auto_index(textWindOff) [list source -encoding utf-8 [file join $dir twind.tcl]]
set auto_index(textWindPlot) [list source -encoding utf-8 [file join $dir twind.tcl]]
set auto_index(embPlotDown) [list source -encoding utf-8 [file join $dir twind.tcl]]
set auto_index(embPlotMove) [list source -encoding utf-8 [file join $dir twind.tcl]]
set auto_index(textWindDel) [list source -encoding utf-8 [file join $dir twind.tcl]]
set auto_index(embDefBg) [list source -encoding utf-8 [file join $dir twind.tcl]]
set auto_index(floorDisplay) [list source -encoding utf-8 [file join $dir floor.tcl]]
set auto_index(newRoom) [list source -encoding utf-8 [file join $dir floor.tcl]]
set auto_index(roomChanged) [list source -encoding utf-8 [file join $dir floor.tcl]]
set auto_index(bg1) [list source -encoding utf-8 [file join $dir floor.tcl]]
set auto_index(bg2) [list source -encoding utf-8 [file join $dir floor.tcl]]
set auto_index(bg3) [list source -encoding utf-8 [file join $dir floor.tcl]]
set auto_index(fg1) [list source -encoding utf-8 [file join $dir floor.tcl]]
set auto_index(fg2) [list source -encoding utf-8 [file join $dir floor.tcl]]
set auto_index(fg3) [list source -encoding utf-8 [file join $dir floor.tcl]]
set auto_index(setWidth) [list source -encoding utf-8 [file join $dir hscale.tcl]]
set auto_index(plotDown) [list source -encoding utf-8 [file join $dir plot.tcl]]
set auto_index(plotMove) [list source -encoding utf-8 [file join $dir plot.tcl]]
set auto_index(puzzleSwitch) [list source -encoding utf-8 [file join $dir puzzle.tcl]]
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]]

Changes to library/demos/tcolor.
1
2
3
4
5
6
7
8
9
10

11
12
13
14
15
16
17
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17









-
+







#!/bin/sh
# the next line restarts using wish \
exec wish "$0" ${1+"$@"}

# tcolor --
# This script implements a simple color editor, where you can
# create colors using either the RGB, HSB, or CYM color spaces
# and apply the color to existing applications.

package require Tk 8.4
package require Tk
wm title . "Color Editor"

# Global variables that control the program:
#
# colorSpace -			Color space currently being used for
#				editing.  Must be "rgb", "cmy", or "hsb".
# label1, label2, label3 -	Labels for the scales.
86
87
88
89
90
91
92
93

94
95
96
97
98
99
100
86
87
88
89
90
91
92

93
94
95
96
97
98
99
100







-
+







    }
    set f [open $i]
    labelframe .names -text "Select:" -padx .1c -pady .1c
    grid .names -row 0 -column 0 -sticky nsew -padx .15c -pady .15c -rowspan 2
    grid columnconfigure . 0 -weight 1
    listbox .names.lb -width 20 -height 12 -yscrollcommand ".names.s set" \
	-exportselection false
    bind .names.lb <Double-1> {
    bind .names.lb <Double-Button-1> {
	    tc_loadNamedColor [.names.lb get [.names.lb curselection]]
    }
    scrollbar .names.s -orient vertical -command ".names.lb yview"
    pack .names.lb .names.s -side left -fill y -expand 1
    while {[gets $f line] >= 0} {
	if {[regexp {^\s*\d+\s+\d+\s+\d+\s+(\S+)$} $line -> col]} {
	    .names.lb insert end $col
Changes to library/demos/text.tcl.
53
54
55
56
57
58
59
60
61



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80


81
82
83
84
85
86
87
53
54
55
56
57
58
59


60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80

81
82
83
84
85
86
87
88
89







-
-
+
+
+


















-
+
+







$w.text insert 0.0 \
{This window is a text widget.  It displays one or more lines of text
and allows you to edit the text.  Here is a summary of the things you
can do to a text widget:

1. Scrolling. Use the scrollbar to adjust the view in the text window.

2. Scanning. Press mouse button 2 in the text window and drag up or down.
This will drag the text at high speed to allow you to scan its contents.
2. Scanning. Press the middle mouse button in the text window and drag up
or down. This will drag the text at high speed to allow you to scan its
contents.

3. Insert text. Press mouse button 1 to set the insertion cursor, then
type text.  What you type will be added to the widget.

4. Select. Press mouse button 1 and drag to select a range of characters.
Once you've released the button, you can adjust the selection by pressing
button 1 with the shift key down.  This will reset the end of the
selection nearest the mouse cursor and you can drag that end of the
selection by dragging the mouse before releasing the mouse button.
You can double-click to select whole words or triple-click to select
whole lines.

5. Delete and replace. To delete text, select the characters you'd like
to delete and type Backspace or Delete.  Alternatively, you can type new
text, in which case it will replace the selected text.

6. Copy the selection. To copy the selection into this window, select
what you want to copy (either here or in another application), then
click button 2 to copy the selection to the point of the mouse cursor.
click the middle mouse button to copy the selection to the point of the
mouse cursor.

7. Edit.  Text widgets support the standard Motif editing characters
plus many Emacs editing characters.  Backspace and Control-h erase the
character to the left of the insertion cursor.  Delete and Control-d
erase the character to the right of the insertion cursor.  Meta-backspace
deletes the word to the left of the insertion cursor, and Meta-d deletes
the word to the right of the insertion cursor.  Control-k deletes from
Changes to library/demos/toolbar.tcl.
13
14
15
16
17
18
19
20

21
22
23
24
25
26
27
13
14
15
16
17
18
19

20
21
22
23
24
25
26
27







-
+







toplevel $w
wm title $w "Toolbar Demonstration"
wm iconname $w "toolbar"
positionWindow $w

ttk::label $w.msg -wraplength 4i -text "This is a demonstration of how to do\
	a toolbar that is styled correctly and which can be torn off. The\
	buttons are configured to be \u201Ctoolbar style\u201D buttons by\
	buttons are configured to be toolbar style buttons by\
	telling them that they are to use the Toolbutton style. At the left\
	end of the toolbar is a simple marker that the cursor changes to a\
	movement icon over; drag that away from the toolbar to tear off the\
	whole toolbar into a separate toplevel widget. When the dragged-off\
	toolbar is no longer needed, just close it like any normal toplevel\
	and it will reattach to the window it was torn off from."

Changes to library/demos/tree.tcl.
35
36
37
38
39
40
41

42
43
44
45
46
47
48
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49







+







proc populateTree {tree node} {
    if {[$tree set $node type] ne "directory"} {
	return
    }
    set path [$tree set $node fullpath]
    $tree delete [$tree children $node]
    foreach f [lsort -dictionary [glob -nocomplain -dir $path *]] {
	set f [file normalize $f]
	set type [file type $f]
	set id [$tree insert $node end -text [file tail $f] \
		-values [list $f $type]]

	if {$type eq "directory"} {
	    ## Make it so that this node is openable
	    $tree insert $id 0 -text dummy ;# a dummy
Changes to library/demos/ttkbut.tcl.
13
14
15
16
17
18
19
20

21
22
23
24
25
26
27
13
14
15
16
17
18
19

20
21
22
23
24
25
26
27







-
+







set w .ttkbut
catch {destroy $w}
toplevel $w
wm title $w "Simple Ttk Widgets"
wm iconname $w "ttkbut"
positionWindow $w

ttk::label $w.msg -font $font -wraplength 4i -justify left -text "Ttk is the new Tk themed widget set. This is a Ttk themed label, and below are three groups of Ttk widgets in Ttk labelframes. The first group are all buttons that set the current application theme when pressed. The second group contains three sets of checkbuttons, with a separator widget between the sets. Note that the \u201cEnabled\u201d button controls whether all the other themed widgets in this toplevel are in the disabled state. The third group has a collection of linked radiobuttons."
ttk::label $w.msg -font $font -wraplength 4i -justify left -text "Ttk is the new Tk themed widget set. This is a Ttk themed label, and below are three groups of Ttk widgets in Ttk labelframes. The first group are all buttons that set the current application theme when pressed. The second group contains three sets of checkbuttons, with a separator widget between the sets. Note that the Enabled button controls whether all the other themed widgets in this toplevel are in the disabled state. The third group has a collection of linked radiobuttons."
pack $w.msg -side top -fill x

## See Code / Dismiss
pack [addSeeDismiss $w.seeDismiss $w {enabled cheese tomato basil oregano happiness}]\
	-side bottom -fill x

## Add buttons for setting the theme
Changes to library/demos/ttkprogress.tcl.
11
12
13
14
15
16
17
18

19
20
21
22
23
24
25
11
12
13
14
15
16
17

18
19
20
21
22
23
24
25







-
+







set w .ttkprogress
catch {destroy $w}
toplevel $w
wm title $w "Progress Bar Demonstration"
wm iconname $w "ttkprogress"
positionWindow $w

ttk::label $w.msg -font $font -wraplength 4i -justify left -text "Below are two progress bars. The top one is a \u201Cdeterminate\u201D progress bar, which is used for showing how far through a defined task the program has got. The bottom one is an \u201Cindeterminate\u201D progress bar, which is used to show that the program is busy but does not know how long for. Both are run here in self-animated mode, which can be turned on and off using the buttons underneath."
ttk::label $w.msg -font $font -wraplength 4i -justify left -text "Below are two progress bars. The top one is a determinate progress bar, which is used for showing how far through a defined task the program has got. The bottom one is an indeterminate progress bar, which is used to show that the program is busy but does not know how long for. Both are run here in self-animated mode, which can be turned on and off using the buttons underneath."
pack $w.msg -side top -fill x

## See Code / Dismiss buttons
set btns [addSeeDismiss $w.buttons $w]
pack $btns -side bottom -fill x

ttk::frame $w.f
Changes to library/demos/twind.tcl.
261
262
263
264
265
266
267
268
269
270



271
272
273
274
275
276
277
261
262
263
264
265
266
267



268
269
270
271
272
273
274
275
276
277







-
-
-
+
+
+







	set y [expr {250 - (4*[lindex $point 1])/5}]
	set item [$c create oval [expr {$x-6}] [expr {$y-6}] \
		[expr {$x+6}] [expr {$y+6}] -width 1 -outline black \
		-fill SkyBlue2]
	$c addtag point withtag $item
    }

    $c bind point <Any-Enter> "$c itemconfig current -fill red"
    $c bind point <Any-Leave> "$c itemconfig current -fill SkyBlue2"
    $c bind point <1> "embPlotDown $c %x %y"
    $c bind point <Enter> "$c itemconfig current -fill red"
    $c bind point <Leave> "$c itemconfig current -fill SkyBlue2"
    $c bind point <Button-1> "embPlotDown $c %x %y"
    $c bind point <ButtonRelease-1> "$c dtag selected"
    bind $c <B1-Motion> "embPlotMove $c %x %y"
    return $c
}

set embPlot(lastX) 0
set embPlot(lastY) 0
Changes to library/demos/unicodeout.tcl.
17
18
19
20
21
22
23
24

25
26
27
28
29
30
31
32
33
17
18
19
20
21
22
23

24


25
26
27
28
29
30
31







-
+
-
-







positionWindow $w

label $w.msg -font $font -wraplength 4i -anchor w -justify left \
	-text "This is a sample of Tk's support for languages that use\
	non-Western character sets.  However, what you will actually see\
	below depends largely on what character sets you have installed,\
	and what you see for characters that are not present varies greatly\
	between platforms as well.  The strings are written in Tcl using\
	between platforms as well."
	UNICODE characters using the \\uXXXX escape so as to do so in a\
	portable fashion."
pack $w.msg -side top

## See Code / Dismiss buttons
set btns [addSeeDismiss $w.buttons $w]
pack $btns -side bottom -fill x

## The frame that will contain the sample texts.
94
95
96
97
98
99
100
101

102
103
104
105
106

107
108
109
110
111
112
113




114
115
116
117
118

119
120
121
122

123
124
125

126
127
128


129
130
131
132


133
134
135
136

137
138
139
140
141
142
143
144
145
146
92
93
94
95
96
97
98

99


100
101

102


103




104
105
106
107


108
109

110

111
112

113

114

115



116
117




118
119

120


121





122
123
124
125
126







-
+
-
-


-
+
-
-

-
-
-
-
+
+
+
+
-
-


-
+
-


-
+
-

-
+
-
-
-
+
+
-
-
-
-
+
+
-

-
-
+
-
-
-
-
-





set oldCursor [$w cget -cursor]
$w conf -cursor watch
update

## Add the samples...
if {[usePresentationFormsFor Arabic]} {
    # Using presentation forms (pre-layouted)
    addSample $w Arabic \
    addSample $w Arabic "ﺔﻴﺑﺮﻌﻟﺍ ﺔﻤﻠﻜﻟﺍ"
	    "\uFE94\uFEF4\uFE91\uFEAE\uFECC\uFEDF\uFE8D " \
	    "\uFE94\uFEE4\uFEE0\uFEDC\uFEDF\uFE8D"
} else {
    # Using standard text characters
    addSample $w Arabic \
    addSample $w Arabic "الكلمة العربية"
	    "\u0627\u0644\u0643\u0644\u0645\u0629 " \
	    "\u0627\u0644\u0639\u0631\u0628\u064A\u0629"
}
addSample $w "Trad. Chinese"  "\u4E2D\u570B\u7684\u6F22\u5B57"
addSample $w "Simpl. Chinese" "\u6C49\u8BED"
addSample $w French "Langue fran\xE7aise"
addSample $w Greek \
addSample $w "Trad. Chinese"  "中國的漢字"
addSample $w "Simpl. Chinese" "汉语"
addSample $w French "Langue française"
addSample $w Greek "Ελληνική γλώσσα"
	"\u0395\u03BB\u03BB\u03B7\u03BD\u03B9\u03BA\u03AE " \
	"\u03B3\u03BB\u03CE\u03C3\u03C3\u03B1"
if {[usePresentationFormsFor Hebrew]} {
    # Visual order (pre-layouted)
    addSample $w Hebrew \
    addSample $w Hebrew "תירבע בתכ"
	    "\u05EA\u05D9\u05E8\u05D1\u05E2 \u05D1\u05EA\u05DB"
} else {
    # Standard logical order
    addSample $w Hebrew \
    addSample $w Hebrew "כתב עברית"
	    "\u05DB\u05EA\u05D1 \u05E2\u05D1\u05E8\u05D9\u05EA"
}
addSample $w Hindi \
addSample $w Hindi "हिन्दी भाषा"
    "\u0939\u093F\u0928\u094D\u0926\u0940 \u092D\u093E\u0937\u093E"
addSample $w Icelandic "\xCDslenska"
addSample $w Japanese \
addSample $w Icelandic "Íslenska"
addSample $w Japanese "日本語のひらがな, 漢字とカタカナ"
	"\u65E5\u672C\u8A9E\u306E\u3072\u3089\u304C\u306A, " \
	"\u6F22\u5B57\u3068\u30AB\u30BF\u30AB\u30CA"
addSample $w Korean "\uB300\uD55C\uBBFC\uAD6D\uC758 \uD55C\uAE00"
addSample $w Russian \
addSample $w Korean "대한민국의 한글"
addSample $w Russian "Русский язык"
	"\u0420\u0443\u0441\u0441\u043A\u0438\u0439 \u044F\u0437\u044B\u043A"
if {([tk windowingsystem] ne "x11") || (![catch {tk::pkgconfig get fontsystem} fs] && ($fs eq "xft"))} {
    if {[package vsatisfies [package provide Tcl] 8.7-]} {
	addSample $w Emoji \
    addSample $w Emoji "😀💩👍🇳🇱"
		"\U1F600\U1F4A9\U1F44D\U1F1F3\U1F1F1"
    } else {
	addSample $w Emoji \
		"\uD83D\uDE00\uD83D\uDCA9\uD83D\uDC4D\uD83C\uDDF3\uD83C\uDDF1"
    }
}

## We're done processing, so change things back to normal running...
destroy $w.wait
$w conf -cursor $oldCursor
Changes to library/demos/widget.
79
80
81
82
83
84
85
86
87
88
89
90
91














92
93
94
95
96
97
98
79
80
81
82
83
84
85






86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106







-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    AAAAAAAAAAAAAAAAACH5BAEAAAoALAAAAAAQABAAAARGUMlJKwU4AztB+ODGeUiJ
    fGLlgeEYmGWQXmx7aXgmAUTv/74N4EAsGhOJg1DAbDqbwoJ0Sp0KB9isNis0eL/g
    ryhH5pgnEQA7
}

# Note that this is run through the message catalog! This is because this is
# actually an image of a word.
image create photo ::img::new -format GIF -data [mc {
    R0lGODlhHgAOALMPALMAANyIiOu7u8dEROaqqvru7sxVVeGZmbgREfXd3b0iItZ3
    d8IzM9FmZvDMzP///yH5BAEAAA8ALAAAAAAeAA4AAASa8MlJq7046827WVOCHEkw
    nANhUgJlEBIABJIwL3K+4IcUALCHjfbItYZDSgJgkBiYPmBMAUAkkLPKs/BAyLgM
    wAQwOAAY2ByCaw4QAFQSoDEePJ6DmU1xInYZTw5nOEFFdgVUelkVDTIMd3AKFGQ1
    MgI2AwEmQW8APZ0gdRONAks5nhIFVVxdAAkUAS2pAVwFl7ITB4UqHb0XEQA7
image create photo ::img::new -format PNG -data [mc {
    iVBORw0KGgoAAAANSUhEUgAAAB4AAAAOCAYAAAA45qw5AAACMElEQVR4AeVTAwxd
    QRCc2tZHGtQ2w9q2bdsOa9u2bUW1bdt2Z372JZe6DapJLqtb3h7+T8yKi5j4CsYD
    EUQXxETclT7kWOlH2VV+tFkdQHPSwksSISF+BauCqL0qgOcMWgGfgEkaMsHxqUBk
    3plE/sOnh/qDPAPJH/CKFBivGHWzFwBRnHhlqbu1Mh6CoFNnC/JshQ9p4YC2lrKt
    DCAV+THiVejyhMjAbrNSrroiEfKR9g7ZfCgOog8QfnUQV62wAk68ndQ9ZbyoWO1H
    Y6eDY1LCQL6a9ApOp9Hi1T0+gQq2JKMlky/oTKQliKWxEZvyG575kpW4pl1aZnQK
    CLOVt45Lkp8uXp2SL8KO6uitNTZLdpK6s+I/eZbhpmsmWeOGOVQNKYLITzpKPAO3
    tY7LSNZ7ccSLxX9y3uuOxRkg3dKESMoCHvL+GRVCutXsB3guLgDCeXOv4iWWkvwG
    BaS+PmlpK6SI9ApI2oC2UtrwZQEkhkH+NtolVlQXJl1I+QltuU3XEc721bIRFpa8
    IA5iqTo6vNNWmkNBLQbPeXwF2g17Q94nTQAfY3YzeY+WSu8MDzQ2kpELUhSGJUHE
    0zeR3rY1L+Xl5G/re+jbiK6KhThwwInsts1fbMUUcpZszKeVtggZEiGdZDe5AtHh
    7vL4CGiRvvKPS8FAvq9Nr4ZkFadR2y6kggu1z4vlyIbBp6BugQ8JLEg4bTkD9eMZ
    QZ8hpJ3VvTtuvbWrY/ElvP/9R+Aj3603+iE3fkEAAAAASUVORK5CYII=
}]

#----------------------------------------------------------------
# The code below creates the main window, consisting of a menu bar and a text
# widget that explains how to use the program, plus lists all of the demos as
# hypertext items.
#----------------------------------------------------------------
182
183
184
185
186
187
188




189
190
191
192
193
194
195
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207







+
+
+
+







	-underline 1
    .t tag configure hot -background black -foreground white
} else {
    .t tag configure demo -lmargin1 1c -lmargin2 1c \
	-foreground blue -underline 1
    .t tag configure visited -lmargin1 1c -lmargin2 1c \
	-foreground #303080 -underline 1
    if {[tk windowingsystem] eq "aqua"} {
	.t tag configure demo -foreground systemLinkColor
	.t tag configure visited -foreground purple
    }
    .t tag configure hot -foreground red -underline 1
}
.t tag bind demo <ButtonRelease-1> {
    invoke [.t index {@%x,%y}]
}
set lastLine ""
.t tag bind demo <Enter> {
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377


378
379
380
381
382
383
384
362
363
364
365
366
367
368

369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397







-




















+
+







    @@demo floor	A building floor plan
    @@demo cscroll	A simple scrollable canvas
    @@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
    @@demo paned2	Vertical paned window
    @@demo ttkpane	Themed nested panes
    @@demo ttknote	Notebook widget

    @@subtitle	Menus and Toolbars
    @@demo menu		Menus and cascades (sub-menus)
    @@demo menubu	Menu-buttons
    @@demo ttkmenu	Themed menu buttons
    @@demo toolbar	Themed toolbar

    @@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

    @@subtitle	Animation
    @@demo anilabel	Animated labels
    @@demo aniwave	Animated wave
    @@demo pendulum	Pendulum simulation
    @@demo goldberg	A celebration of Rube Goldberg

500
501
502
503
504
505
506
507

508
509
510
511
512
513
514
513
514
515
516
517
518
519

520
521
522
523
524
525
526
527







-
+







    if {$i < 0} {
	return
    }
    set cursor [.t cget -cursor]
    .t configure -cursor [::ttk::cursor busy]
    update
    set demo [string range [lindex $tags $i] 5 end]
    uplevel 1 [list source [file join $tk_demoDirectory $demo.tcl]]
    uplevel 1 [list source -encoding utf-8 [file join $tk_demoDirectory $demo.tcl]]
    update
    .t configure -cursor $cursor

    .t tag add visited "$index linestart +1 chars" "$index lineend -1 chars"
}

# showStatus --
608
609
610
611
612
613
614

615
616
617
618
619
620
621
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635







+







    } else {
	wm deiconify $top
	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
    $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
}

# printCode --
706
707
708
709
710
711
712
713
714
715
716




717
718
719
720
721
720
721
722
723
724
725
726




727
728
729
730
731
732
733
734
735







-
-
-
-
+
+
+
+





# tkAboutDialog --
#
#	Pops up a message box with an "about" message
#
proc tkAboutDialog {} {
    tk_messageBox -icon info -type ok -title [mc "About Widget Demo"] \
	    -message [mc "Tk widget demonstration application"] -detail \
"[mc "Copyright \u00a9 %s" {1996-1997 Sun Microsystems, Inc.}]
[mc "Copyright \u00a9 %s" {1997-2000 Ajuba Solutions, Inc.}]
[mc "Copyright \u00a9 %s" {2001-2009 Donal K. Fellows}]
[mc "Copyright \u00a9 %s" {2002-2007 Daniel A. Steffen}]"
"[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}]"
}

# Local Variables:
# mode: tcl
# End:
Changes to library/dialog.tcl.
1
2
3
4
5
6
7


8
9
10
11
12
13
14
1
2
3
4
5


6
7
8
9
10
11
12
13
14





-
-
+
+







# dialog.tcl --
#
# This file defines the procedure tk_dialog, which creates a dialog
# box containing a bitmap, a message, and one or more buttons.
#
# Copyright (c) 1992-1993 The Regents of the University of California.
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright © 1992-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.
#

#
# ::tk_dialog:
Changes to library/entry.tcl.
1
2
3
4
5
6
7


8
9
10
11
12
13
14
1
2
3
4
5


6
7
8
9
10
11
12
13
14





-
-
+
+







# entry.tcl --
#
# This file defines the default bindings for Tk entry widgets and provides
# procedures that help in implementing those bindings.
#
# 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.
#

#-------------------------------------------------------------------------
# Elements of tk::Priv that are used in this file:
54
55
56
57
58
59
60
61

62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77

78
79
80
81
82
83
84
85

86
87
88
89
90

91
92
93
94
95

96
97
98
99

100
101
102
103

104
105
106
107
108
109
110
111
112
113
114
115
116
117

118
119
120
121
122

123
124
125

126
127
128

129
130
131
132

133
134
135
136
137
138
139
54
55
56
57
58
59
60

61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76

77
78
79
80
81
82
83
84

85
86
87
88
89

90
91
92
93
94

95
96
97
98

99
100
101
102

103
104
105
106
107
108
109
110
111
112
113
114
115
116

117
118
119
120
121

122
123
124

125
126
127

128
129
130
131

132
133
134
135
136
137
138
139







-
+















-
+







-
+




-
+




-
+



-
+



-
+













-
+




-
+


-
+


-
+



-
+







	}
	%W insert insert [::tk::GetSelection %W CLIPBOARD]
	tk::EntrySeeInsert %W
    }
}
bind Entry <<Clear>> {
    # ignore if there is no selection
    catch { %W delete sel.first sel.last }
    catch {%W delete sel.first sel.last}
}
bind Entry <<PasteSelection>> {
    if {$tk_strictMotif || ![info exists tk::Priv(mouseMoved)]
	|| !$tk::Priv(mouseMoved)} {
	tk::EntryPaste %W %x
    }
}

bind Entry <<TraverseIn>> {
    %W selection range 0 end
    %W icursor end
}

# Standard Motif bindings:

bind Entry <1> {
bind Entry <Button-1> {
    tk::EntryButton1 %W %x
    %W selection clear
}
bind Entry <B1-Motion> {
    set tk::Priv(x) %x
    tk::EntryMouseSelect %W %x
}
bind Entry <Double-1> {
bind Entry <Double-Button-1> {
    set tk::Priv(selectMode) word
    tk::EntryMouseSelect %W %x
    catch {%W icursor sel.last}
}
bind Entry <Triple-1> {
bind Entry <Triple-Button-1> {
    set tk::Priv(selectMode) line
    tk::EntryMouseSelect %W %x
    catch {%W icursor sel.last}
}
bind Entry <Shift-1> {
bind Entry <Shift-Button-1> {
    set tk::Priv(selectMode) char
    %W selection adjust @%x
}
bind Entry <Double-Shift-1>	{
bind Entry <Double-Shift-Button-1>	{
    set tk::Priv(selectMode) word
    tk::EntryMouseSelect %W %x
}
bind Entry <Triple-Shift-1>	{
bind Entry <Triple-Shift-Button-1>	{
    set tk::Priv(selectMode) line
    tk::EntryMouseSelect %W %x
}
bind Entry <B1-Leave> {
    set tk::Priv(x) %x
    tk::EntryAutoScan %W
}
bind Entry <B1-Enter> {
    tk::CancelRepeat
}
bind Entry <ButtonRelease-1> {
    tk::CancelRepeat
}
bind Entry <Control-1> {
bind Entry <Control-Button-1> {
    %W icursor @%x
}

bind Entry <<PrevChar>> {
    tk::EntrySetCursor %W [expr {[%W index insert] - 1}]
    tk::EntrySetCursor %W [expr {[%W index insert]-1}]
}
bind Entry <<NextChar>> {
    tk::EntrySetCursor %W [expr {[%W index insert] + 1}]
    tk::EntrySetCursor %W [expr {[%W index insert]+1}]
}
bind Entry <<SelectPrevChar>> {
    tk::EntryKeySelect %W [expr {[%W index insert] - 1}]
    tk::EntryKeySelect %W [expr {[%W index insert]-1}]
    tk::EntrySeeInsert %W
}
bind Entry <<SelectNextChar>> {
    tk::EntryKeySelect %W [expr {[%W index insert] + 1}]
    tk::EntryKeySelect %W [expr {[%W index insert]+1}]
    tk::EntrySeeInsert %W
}
bind Entry <<PrevWord>> {
    tk::EntrySetCursor %W [tk::EntryPreviousWord %W insert]
}
bind Entry <<NextWord>> {
    tk::EntrySetCursor %W [tk::EntryNextWord %W insert]
186
187
188
189
190
191
192
193

194
195
196
197
198
199
200

201
202
203
204
205



206
207
208
209
210
211
212
213

214
215
216
217
218
219
220
221
186
187
188
189
190
191
192

193
194
195
196
197
198
199

200
201
202



203
204
205
206
207
208
209
210
211


212

213
214
215
216
217
218
219







-
+






-
+


-
-
-
+
+
+






-
-
+
-







}
bind Entry <<SelectAll>> {
    %W selection range 0 end
}
bind Entry <<SelectNone>> {
    %W selection clear
}
bind Entry <KeyPress> {
bind Entry <Key> {
    tk::CancelRepeat
    tk::EntryInsert %W %A
}

# Ignore all Alt, Meta, and Control keypresses unless explicitly bound.
# Otherwise, if a widget binding for one of these is defined, the
# <KeyPress> class binding will also fire and insert the character,
# <Key> class binding will also fire and insert the character,
# which is wrong.  Ditto for Escape, Return, and Tab.

bind Entry <Alt-KeyPress> {# nothing}
bind Entry <Meta-KeyPress> {# nothing}
bind Entry <Control-KeyPress> {# nothing}
bind Entry <Alt-Key> {# nothing}
bind Entry <Meta-Key> {# nothing}
bind Entry <Control-Key> {# nothing}
bind Entry <Escape> {# nothing}
bind Entry <Return> {# nothing}
bind Entry <KP_Enter> {# nothing}
bind Entry <Tab> {# nothing}
bind Entry <Prior> {# nothing}
bind Entry <Next> {# nothing}
if {[tk windowingsystem] eq "aqua"} {
    bind Entry <Command-KeyPress> {# nothing}
bind Entry <Command-Key> {# nothing}
}
# Tk-on-Cocoa generates characters for these two keys. [Bug 2971663]
bind Entry <<NextLine>> {# nothing}
bind Entry <<PrevLine>> {# nothing}

# On Windows, paste is done using Shift-Insert.  Shift-Insert already
# generates the <<Paste>> event, so we don't need to do anything here.
if {[tk windowingsystem] ne "win32"} {
274
275
276
277
278
279
280
281

282
283
284
285
286
287
288
289
290
291
292
293
294
295
296

297
298

299
300
301
302
303
304


305
306
307
308
309
310
311
272
273
274
275
276
277
278

279
280
281
282
283
284
285
286
287
288
289
290
291
292
293

294
295

296
297
298
299
300


301
302
303
304
305
306
307
308
309







-
+














-
+

-
+




-
-
+
+








# Bindings for IME text input and accents.

bind Entry <<TkStartIMEMarkedText>> {
    dict set ::tk::Priv(IMETextMark) "%W" [%W index insert]
}
bind Entry <<TkEndIMEMarkedText>> {
    if { [catch {dict get $::tk::Priv(IMETextMark) "%W"} mark] } {
    if {[catch {dict get $::tk::Priv(IMETextMark) "%W"} mark]} {
	bell
    } else {
	%W selection range $mark insert
    }
}
bind Entry <<TkClearIMEMarkedText>> {
    %W delete [dict get $::tk::Priv(IMETextMark) "%W"] [%W index insert]
}
bind Entry <<TkAccentBackspace>> {
    tk::EntryBackspace %W
}

# A few additional bindings of my own.

bind Entry <2> {
bind Entry <Button-2> {
    if {!$tk_strictMotif} {
	::tk::EntryScanMark %W %x
        ::tk::EntryScanMark %W %x
    }
}
bind Entry <B2-Motion> {
    if {!$tk_strictMotif} {
	::tk::EntryScanDrag %W %x
    }
        ::tk::EntryScanDrag %W %x
     }
}

# ::tk::EntryClosestGap --
# Given x and y coordinates, this procedure finds the closest boundary
# between characters to the given coordinates and returns the index
# of the character just after the boundary.
#
374
375
376
377
378
379
380
381

382
383
384

385
386
387
388
389
390
391
372
373
374
375
376
377
378

379
380
381

382
383
384
385
386
387
388
389







-
+


-
+







		    $w selection clear
		}
	    }
	}
	word {
	    if {$cur < $anchor} {
		set before [tcl_wordBreakBefore [$w get] $cur]
		set after [tcl_wordBreakAfter [$w get] [expr {$anchor-1}]]
		set after [tcl_wordBreakAfter [$w get] $anchor-1]
	    } elseif {$cur > $anchor} {
		set before [tcl_wordBreakBefore [$w get] $anchor]
		set after [tcl_wordBreakAfter [$w get] [expr {$cur - 1}]]
		set after [tcl_wordBreakAfter [$w get] $cur-1]
	    } else {
		if {[$w index @$Priv(pressX)] < $anchor} {
		      incr anchor -1
		}
		set before [tcl_wordBreakBefore [$w get] $anchor]
		set after [tcl_wordBreakAfter [$w get] $anchor]
	    }
501
502
503
504
505
506
507
508
509
510



511
512
513
514
515
516
517
499
500
501
502
503
504
505



506
507
508
509
510
511
512
513
514
515







-
-
-
+
+
+







# Arguments:
# w -		The entry window in which to backspace.

proc ::tk::EntryBackspace w {
    if {[$w selection present]} {
	$w delete sel.first sel.last
    } else {
	set x [expr {[$w index insert] - 1}]
	if {$x >= 0} {
	    $w delete $x
	set x [$w index insert]
	if {$x > 0} {
	    $w delete [expr {$x-1}]
	}
	if {[$w index @0] >= [$w index insert]} {
	    set range [$w xview]
	    set left [lindex $range 0]
	    set right [lindex $range 1]
	    $w xview moveto [expr {$left - ($right - $left)/2.0}]
	}
558
559
560
561
562
563
564
565
566

567
568

569
570

571
572
573
574
575
576
577
556
557
558
559
560
561
562


563
564
565
566
567

568
569
570
571
572
573
574
575







-
-
+


+

-
+







# w -		The entry window.

proc ::tk::EntryTranspose w {
    set i [$w index insert]
    if {$i < [$w index end]} {
	incr i
    }
    set first [expr {$i-2}]
    if {$first < 0} {
    if {$i < 2} {
	return
    }
    set first [expr {$i-2}]
    set data [$w get]
    set new [string index $data [expr {$i-1}]][string index $data $first]
    set new [string index $data $i-1][string index $data $first]
    $w delete $first $i
    $w insert insert $new
    EntrySeeInsert $w
}

# ::tk::EntryNextWord --
# Returns the index of the next word position after a given position in the
643
644
645
646
647
648
649
650

651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667

668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
641
642
643
644
645
646
647

648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664

665
666
667
668
669
670
671
















-
+
















-
+






-
-
-
-
-
-
-
-
-
# Arguments:
# w -	The entry window from which the text to get
# x -	x location on screen

proc ::tk::EntryScanDrag {w x} {
    # Make sure these exist, as some weird situations can trigger the
    # motion binding without the initial press.  [Bug #220269]
    if {![info exists ::tk::Priv(x)]} { set ::tk::Priv(x) $x }
    if {![info exists ::tk::Priv(x)]} {set ::tk::Priv(x) $x}
    # allow for a delta
    if {abs($x-$::tk::Priv(x)) > 2} {
	set ::tk::Priv(mouseMoved) 1
    }
    $w scan dragto $x
}

# ::tk::EntryGetSelection --
#
# Returns the selected text of the entry with respect to the -show option.
#
# Arguments:
# w -         The entry window from which the text to get

proc ::tk::EntryGetSelection {w} {
    set entryString [string range [$w get] [$w index sel.first] \
	    [expr {[$w index sel.last] - 1}]]
	    [$w index sel.last]-1]
    if {[$w cget -show] ne ""} {
	return [string repeat [string index [$w cget -show] 0] \
		[string length $entryString]]
    }
    return $entryString
}









Changes to library/focus.tcl.
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







# focus.tcl --
#
# This file defines several procedures for managing the input
# focus.
#
# Copyright (c) 1994-1995 Sun Microsystems, Inc.
# 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.
#

# ::tk_focusNext --
# This procedure returns the name of the next window after "w" in
Changes to library/fontchooser.tcl.
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15
16
17
18
19
20
21





22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

40
41

42
43
44
45
46
47
48
1
2
3
4


5
6
7
8
9
10
11
12
13
14
15
16





17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

39
40

41
42
43
44
45
46
47
48




-
-
+
+










-
-
-
-
-
+
+
+
+
+

















-
+

-
+







# fontchooser.tcl -
#
#	A themeable Tk font selection dialog. See TIP #324.
#
# Copyright (C) 2008 Keith Vetter
# Copyright (C) 2008 Pat Thoyts <[email protected]>
# Copyright © 2008 Keith Vetter
# Copyright © 2008 Pat Thoyts <[email protected]>
#
# 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 {
    variable S

    set S(W) .__tk__fontchooser
    set S(fonts) [lsort -dictionary [font families]]
    set S(styles) [list \
                       [::msgcat::mc "Regular"] \
                       [::msgcat::mc "Italic"] \
                       [::msgcat::mc "Bold"] \
                       [::msgcat::mc "Bold Italic"] \
                      ]
	[::msgcat::mc "Regular"] \
	[::msgcat::mc "Italic"] \
	[::msgcat::mc "Bold"] \
	[::msgcat::mc "Bold Italic"] \
    ]

    set S(sizes) {8 9 10 11 12 14 16 18 20 22 24 26 28 36 48 72}
    set S(strike) 0
    set S(under) 0
    set S(first) 1
    set S(sampletext) [::msgcat::mc "AaBbYyZz01"]
    set S(-parent) .
    set S(-title) [::msgcat::mc "Font"]
    set S(-command) ""
    set S(-font) TkDefaultFont
}

proc ::tk::fontchooser::Setup {} {
    variable S

    # Canonical versions of font families, styles, etc. for easier searching
    set S(fonts,lcase) {}
    foreach font $S(fonts) { lappend S(fonts,lcase) [string tolower $font]}
    foreach font $S(fonts) {lappend S(fonts,lcase) [string tolower $font]}
    set S(styles,lcase) {}
    foreach style $S(styles) { lappend S(styles,lcase) [string tolower $style]}
    foreach style $S(styles) {lappend S(styles,lcase) [string tolower $style]}
    set S(sizes,lcase) $S(sizes)

    ::ttk::style layout FontchooserFrame {
        Entry.field -sticky news -border true -children {
            FontchooserFrame.padding -sticky news
        }
    }
107
108
109
110
111
112
113
114

115
116
117
118
119
120
121
122
123
124

125
126
127
128
129
130
131
107
108
109
110
111
112
113

114
115
116
117
118
119
120
121
122
123

124
125
126
127
128
129
130
131







-
+









-
+







        return -code error -errorcode [list TK LOOKUP OPTION $option] \
	    "bad option \"$option\": must be\
            -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
    }
    if {[string trim $S(-title)] eq ""} {
        set S(-title) [::msgcat::mc "Font"]
    }
    if {[winfo exists $S(W)] && [lsearch $args -font] != -1} {
    if {[winfo exists $S(W)] && ("-font" in $args)} {
	Init $S(-font)
	event generate $S(-parent) <<TkFontchooserFontChanged>>
    }
    return $r
}

proc ::tk::fontchooser::Create {} {
141
142
143
144
145
146
147



148
149
150
151

152
153
154
155
156
157
158
141
142
143
144
145
146
147
148
149
150
151
152
153

154
155
156
157
158
159
160
161







+
+
+



-
+







    if {![winfo exists $S(W)]} {
        toplevel $S(W) -class TkFontDialog
        if {[package provide tcltest] ne {}} {set ::tk_dialog $S(W)}
        wm withdraw $S(W)
        wm title $S(W) $S(-title)
        wm transient $S(W) [winfo toplevel $S(-parent)]

        set scaling [tk scaling]
        set sizeWidth [expr {int([string length [::msgcat::mc "&Size:"]] * $scaling)}]

        set outer [::ttk::frame $S(W).outer -padding {10 10}]
        ::tk::AmpWidget ::ttk::label $S(W).font -text [::msgcat::mc "&Font:"]
        ::tk::AmpWidget ::ttk::label $S(W).style -text [::msgcat::mc "Font st&yle:"]
        ::tk::AmpWidget ::ttk::label $S(W).size -text [::msgcat::mc "&Size:"]
        ::tk::AmpWidget ::ttk::label $S(W).size -text [::msgcat::mc "&Size:"] -width $sizeWidth
        ttk::entry $S(W).efont -width 18 \
            -textvariable [namespace which -variable S](font)
        ttk::entry $S(W).estyle -width 10 \
            -textvariable [namespace which -variable S](style)
        ttk::entry $S(W).esize -textvariable [namespace which -variable S](size) \
            -width 3 -validate key -validatecommand {string is double %P}

195
196
197
198
199
200
201
202

203
204
205
206
207
208
209
198
199
200
201
202
203
204

205
206
207
208
209
210
211
212







-
+







        set minsize(fonts) \
            [expr {[font measure TkDefaultFont "Helvetica"] + $scroll_width}]
        set minsize(styles) \
            [expr {[font measure TkDefaultFont "Bold Italic"] + $scroll_width}]
        set minsize(sizes) \
            [expr {[font measure TkDefaultFont "-99"] + $scroll_width}]
        set min [expr {$minsize(gap) * 4}]
        foreach {what width} [array get minsize] { incr min $width }
        foreach {what width} [array get minsize] {incr min $width}
        wm minsize $S(W) $min 260

        bind $S(W) <Return> [namespace code [list Done 1]]
        bind $S(W) <Escape> [namespace code [list Done 0]]
        bind $S(W) <Map> [namespace code [list Visibility %W 1]]
        bind $S(W) <Unmap> [namespace code [list Visibility %W 0]]
        bind $S(W) <Destroy> [namespace code [list Visibility %W 0]]
273
274
275
276
277
278
279
280

281
282
283
284
285
286
287
276
277
278
279
280
281
282

283
284
285
286
287
288
289
290







-
+







# ::tk::fontchooser::Done --
#
#       Handles teardown of the dialog, calling -command if needed
#
# Arguments:
#       ok              true if user pressed OK
#
proc ::tk::::fontchooser::Done {ok} {
proc ::tk::fontchooser::Done {ok} {
    variable S

    if {! $ok} {
        set S(result) ""
    }
    trace vdelete S(size) w [namespace code [list Tracer]]
    trace vdelete S(style) w [namespace code [list Tracer]]
323
324
325
326
327
328
329
330

331
332

333
334

335
336

337
338
339
340
341
342
343
326
327
328
329
330
331
332

333
334

335
336

337
338

339
340
341
342
343
344
345
346







-
+

-
+

-
+

-
+







            destroy .___e
        }
        array set F [font actual $defaultFont]
        set S(font) $F(-family)
        set S(size) $F(-size)
        set S(strike) $F(-overstrike)
        set S(under) $F(-underline)
        set S(style) "Regular"
        set S(style) [::msgcat::mc "Regular"]
        if {$F(-weight) eq "bold" && $F(-slant) eq "italic"} {
            set S(style) "Bold Italic"
            set S(style) [::msgcat::mc "Bold Italic"]
        } elseif {$F(-weight) eq "bold"} {
            set S(style) "Bold"
            set S(style) [::msgcat::mc "Bold"]
        } elseif {$F(-slant) eq "italic"} {
            set S(style) "Italic"
            set S(style) [::msgcat::mc "Italic"]
        }

        set S(first) 0
    }

    Tracer a b c
    Update
377
378
379
380
381
382
383
384

385
386
387
388
389
390
391
392
393
394
395
396
397
398
399

400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415





416
417
418
419
420
421
422
380
381
382
383
384
385
386

387
388
389
390
391
392
393
394
395
396
397
398
399
400
401

402
403
404
405
406
407
408
409
410
411
412
413





414
415
416
417
418
419
420
421
422
423
424
425







-
+














-
+











-
-
-
-
-
+
+
+
+
+







    set nstate normal
    # Make selection in each listbox
    foreach var {font style size} {
        set value [string tolower $S($var)]
        $S(W).l${var}s selection clear 0 end
        set n [lsearch -exact $S(${var}s,lcase) $value]
        $S(W).l${var}s selection set $n
        if {$n != -1} {
        if {$n >= 0} {
            set S($var) [lindex $S(${var}s) $n]
            $S(W).e$var icursor end
            $S(W).e$var selection clear
        } else {                                ;# No match, try prefix
            # Size is weird: valid numbers are legal but don't display
            # unless in the font size list
            set n [lsearch -glob $S(${var}s,lcase) "$value*"]
            set bad 1
            if {$var ne "size" || ! [string is double -strict $value]} {
                set nstate disabled
            }
        }
        $S(W).l${var}s see $n
    }
    if {!$bad} { Update }
    if {!$bad} {Update}
    $S(W).ok configure -state $nstate
}

# ::tk::fontchooser::Update --
#
#       Shows a sample of the currently selected font
#
proc ::tk::fontchooser::Update {} {
    variable S

    set S(result) [list $S(font) $S(size)]
    if {$S(style) eq "Bold"} { lappend S(result) bold }
    if {$S(style) eq "Italic"} { lappend S(result) italic }
    if {$S(style) eq "Bold Italic"} { lappend S(result) bold italic}
    if {$S(strike)} { lappend S(result) overstrike}
    if {$S(under)} { lappend S(result) underline}
    if {$S(style) eq [::msgcat::mc "Bold"]} {lappend S(result) bold}
    if {$S(style) eq [::msgcat::mc "Italic"]} {lappend S(result) italic}
    if {$S(style) eq [::msgcat::mc "Bold Italic"]} {lappend S(result) bold italic}
    if {$S(strike)} {lappend S(result) overstrike}
    if {$S(under)} {lappend S(result) underline}

    $S(sample) configure -font $S(result)
}

# ::tk::fontchooser::Visibility --
#
#	Notify the parent when the dialog visibility changes
Changes to library/iconlist.tcl.
1
2
3
4
5
6
7


8
9
10
11
12
13
14
1
2
3
4
5


6
7
8
9
10
11
12
13
14





-
-
+
+







# iconlist.tcl
#
#	Implements the icon-list megawidget used in the "Tk" standard file
#	selection dialog boxes.
#
# Copyright (c) 1994-1998 Sun Microsystems, Inc.
# Copyright (c) 2009 Donal K. Fellows
# Copyright © 1994-1998 Sun Microsystems, Inc.
# Copyright © 2009 Donal K. Fellows
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# API Summary:
#	tk::IconList <path> ?<option> <value>? ...
#	<path> add <imageName> <itemList>
22
23
24
25
26
27
28
29

30
31
32
33
34
35
36
22
23
24
25
26
27
28

29
30
31
32
33
34
35
36







-
+







#	<path> see <index>
#	<path> selection anchor ?<int>?
#	<path> selection clear <first> ?<last>?
#	<path> selection get
#	<path> selection includes <item>
#	<path> selection set <first> ?<last>?

package require Tk 8.6
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
    constructor args {
	next {*}$args
429
430
431
432
433
434
435
436

437
438
439
440


441
442
443
444
445
446
447
448
449
450
451


452
453
454

455
456
457
458
459
460
461
462
463
464
465
466
467



468
469
470
471
472
473
474
429
430
431
432
433
434
435

436
437
438


439
440
441
442
443
444
445
446
447
448



449
450



451




452
453
454
455
456
457



458
459
460
461
462
463
464
465
466
467







-
+


-
-
+
+








-
-
-
+
+
-
-
-
+
-
-
-
-






-
-
-
+
+
+







	    set fill $fg
	}

	# Creates the event bindings.
	#
	bind $canvas <Configure>	[namespace code {my WhenIdle Arrange}]

	bind $canvas <1>		[namespace code {my Btn1 %x %y}]
	bind $canvas <Button-1>		[namespace code {my Btn1 %x %y}]
	bind $canvas <B1-Motion>	[namespace code {my Motion1 %x %y}]
	bind $canvas <B1-Leave>		[namespace code {my Leave1 %x %y}]
	bind $canvas <Control-1>	[namespace code {my CtrlBtn1 %x %y}]
	bind $canvas <Shift-1>		[namespace code {my ShiftBtn1 %x %y}]
	bind $canvas <Control-Button-1>	[namespace code {my CtrlBtn1 %x %y}]
	bind $canvas <Shift-Button-1>	[namespace code {my ShiftBtn1 %x %y}]
	bind $canvas <B1-Enter>		[list tk::CancelRepeat]
	bind $canvas <ButtonRelease-1>	[list tk::CancelRepeat]
	bind $canvas <Double-ButtonRelease-1> \
	    [namespace code {my Double1 %x %y}]

	bind $canvas <Control-B1-Motion> {;}
	bind $canvas <Shift-B1-Motion>	[namespace code {my ShiftMotion1 %x %y}]

	if {[tk windowingsystem] eq "aqua"} {
	    bind $canvas <Shift-MouseWheel>	[namespace code {my MouseWheel [expr {40 * (%D)}]}]
	    bind $canvas <Option-Shift-MouseWheel>	[namespace code {my MouseWheel [expr {400 * (%D)}]}]
	bind $canvas <Shift-MouseWheel>	[namespace code {my MouseWheel %D}]
	bind $canvas <Option-Shift-MouseWheel>	[namespace code {my MouseWheel %D -12}]
	} else {
	    bind $canvas <Shift-MouseWheel>	[namespace code {my MouseWheel %D}]
	}

	if {[tk windowingsystem] eq "x11"} {
	    bind $canvas <Shift-4>	[namespace code {my MouseWheel 120}]
	    bind $canvas <Shift-5>	[namespace code {my MouseWheel -120}]
	}

	bind $canvas <<PrevLine>>	[namespace code {my UpDown -1}]
	bind $canvas <<NextLine>>	[namespace code {my UpDown  1}]
	bind $canvas <<PrevChar>>	[namespace code {my LeftRight -1}]
	bind $canvas <<NextChar>>	[namespace code {my LeftRight  1}]
	bind $canvas <Return>		[namespace code {my ReturnKey}]
	bind $canvas <KeyPress>		[namespace code {my KeyPress %A}]
	bind $canvas <Control-KeyPress> ";"
	bind $canvas <Alt-KeyPress>	";"
	bind $canvas <Key>		[namespace code {my KeyPress %A}]
	bind $canvas <Control-Key> ";"
	bind $canvas <Alt-Key>	";"

	bind $canvas <FocusIn>		[namespace code {my FocusIn}]
	bind $canvas <FocusOut>		[namespace code {my FocusOut}]

	return $w
    }

499
500
501
502
503
504
505
506

507
508
509
510
511
512
513

514
515
516
517
518
519
520
521
492
493
494
495
496
497
498

499
500
501
502




503

504
505
506
507
508
509
510







-
+



-
-
-
-
+
-







	my Motion1 $x $y
	set ::tk::Priv(afterId) [after 50 [namespace code {my AutoScan}]]
    }

    # ----------------------------------------------------------------------

    # Event handlers
    method MouseWheel {amount} {
    method MouseWheel {amount {factor -120.0}} {
	if {$noScroll || $::tk_strictMotif} {
	    return
	}
	if {$amount > 0} {
	    $canvas xview scroll [expr {(-119-$amount) / 120}] units
	} else {
	    $canvas xview scroll [expr {-($amount / 120)}] units
	$canvas xview scroll [expr {$amount/$factor}] units
	}
    }
    method Btn1 {x y} {
	focus $canvas
	set i [$w index @$x,$y]
	if {$i eq ""} {
	    return
	}
693
694
695
696
697
698
699
700

701
702
703
704
705
706
707
682
683
684
685
686
687
688

689
690
691
692
693
694
695
696







-
+







		set i 0
	    }
	    if {$i == $start} {
		break
	    }
	}

	if {$theIndex > -1} {
	if {$theIndex >= 0} {
	    $w selection clear 0 end
	    $w selection set $theIndex
	    $w selection anchor $theIndex
	    $w see $theIndex
	}
    }
    method Reset {} {
Changes to library/icons.tcl.
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
1
2
3
4
5
6
7
8
9
10

11
12
13
14
15
16
17
18










-
+







# icons.tcl --
#
#	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/)
#
#	See http://tango.freedesktop.org/Tango_Desktop_Project
#
# Copyright (c) 2009 Pat Thoyts <[email protected]>
# Copyright © 2009 Pat Thoyts <[email protected]>

namespace eval ::tk::icons {}

image create photo ::tk::icons::warning -data {
    iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQICAgIfAhkiAAABSZJREFU
    WIXll1toVEcYgL+Zc87u2Yu7MYmrWRuTJuvdiMuqiJd4yYKXgMQKVkSjFR80kFIVJfWCWlvpg4h9
    8sXGWGof8iKNICYSo6JgkCBEJRG8ImYThNrNxmaTeM7pQ5IlJkabi0/9YZhhZv7///4z/8zPgf+7
Changes to library/images/logo.eps.
24
25
26
27
28
29
30
31

32
33
34
35
36
37
38
24
25
26
27
28
29
30

31
32
33
34
35
36
37
38







-
+







%AI5_NumLayers: 1
%AI5_OpenToView: 90 576 2 938 673 18 1 1 2 40
%AI5_OpenViewLayers: 7
%%EndComments
%%BeginProlog
%%BeginResource: procset Adobe_level2_AI5 1.0 0
%%Title: (Adobe Illustrator (R) Version 5.0 Level 2 Emulation)
%%Version: 1.0 
%%Version: 1.0
%%CreationDate: (04/10/93) ()
%%Copyright: ((C) 1987-1993 Adobe Systems Incorporated All Rights Reserved)
userdict /Adobe_level2_AI5 21 dict dup begin
	put
	/packedarray where not
	{
		userdict begin
73
74
75
76
77
78
79
80

81
82
83
84
85
86
87
73
74
75
76
77
78
79

80
81
82
83
84
85
86
87







-
+







				4 index mul 4 1 roll
			} repeat
			5 -1 roll pop
			setcmykcolor
		}
		def
	} if
	

	/gt38? mark {version cvx exec} stopped {cleartomark true} {38 gt exch pop} ifelse def
	userdict /deviceDPI 72 0 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt put
	userdict /level2?
	systemdict /languagelevel known dup
	{
		pop systemdict /languagelevel get 2 ge
	} if
174
175
176
177
178
179
180
181

182
183
184
185
186
187
188
174
175
176
177
178
179
180

181
182
183
184
185
186
187
188







-
+







		/customColor? isCMYKSep? not def
	 end
	} if
 end defaultpacking setpacking
%%EndResource
%%BeginResource: procset Adobe_IllustratorA_AI5 1.1 0
%%Title: (Adobe Illustrator (R) Version 5.0 Abbreviated Prolog)
%%Version: 1.1 
%%Version: 1.1
%%CreationDate: (3/7/1994) ()
%%Copyright: ((C) 1987-1994 Adobe Systems Incorporated All Rights Reserved)
currentpacking true setpacking
userdict /Adobe_IllustratorA_AI5_vars 70 dict dup begin
put
/_lp /none def
/_pf
1058
1059
1060
1061
1062
1063
1064
1065

1066
1067
1068
1069
1070
1071
1072
1058
1059
1060
1061
1062
1063
1064

1065
1066
1067
1068
1069
1070
1071
1072







-
+







	{
		0 eq
		{
			(%AI5_BeginLayer) 1 (%AI5_EndLayer--) discard
		}
		{
			/clipForward? true def
			

			/Tx /pop load def
			/Tj /pop load def
			currentdict end clipRenderOff begin begin
		} ifelse
	}
	{
		0 eq
1085
1086
1087
1088
1089
1090
1091
1092

1093
1094
1095
1096
1097
1098
1099
1085
1086
1087
1088
1089
1090
1091

1092
1093
1094
1095
1096
1097
1098
1099







-
+







		pop
		clipForward?
		{
			currentdict
		 end
		 end
		 begin
			

			/clipForward? false ddef
		} if
	} ifelse
} bind def
/Pb
{
	pop pop
Changes to library/images/pwrdLogo.eps.
24
25
26
27
28
29
30
31

32
33
34
35
36
37
38
24
25
26
27
28
29
30

31
32
33
34
35
36
37
38







-
+







%AI5_NumLayers: 1
%AI5_OpenToView: 102 564 2 938 673 18 1 1 2 40
%AI5_OpenViewLayers: 7
%%EndComments
%%BeginProlog
%%BeginResource: procset Adobe_level2_AI5 1.0 0
%%Title: (Adobe Illustrator (R) Version 5.0 Level 2 Emulation)
%%Version: 1.0 
%%Version: 1.0
%%CreationDate: (04/10/93) ()
%%Copyright: ((C) 1987-1993 Adobe Systems Incorporated All Rights Reserved)
userdict /Adobe_level2_AI5 21 dict dup begin
	put
	/packedarray where not
	{
		userdict begin
73
74
75
76
77
78
79
80

81
82
83
84
85
86
87
73
74
75
76
77
78
79

80
81
82
83
84
85
86
87







-
+







				4 index mul 4 1 roll
			} repeat
			5 -1 roll pop
			setcmykcolor
		}
		def
	} if
	

	/gt38? mark {version cvx exec} stopped {cleartomark true} {38 gt exch pop} ifelse def
	userdict /deviceDPI 72 0 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt put
	userdict /level2?
	systemdict /languagelevel known dup
	{
		pop systemdict /languagelevel get 2 ge
	} if
174
175
176
177
178
179
180
181

182
183
184
185
186
187
188
174
175
176
177
178
179
180

181
182
183
184
185
186
187
188







-
+







		/customColor? isCMYKSep? not def
	 end
	} if
 end defaultpacking setpacking
%%EndResource
%%BeginResource: procset Adobe_IllustratorA_AI5 1.1 0
%%Title: (Adobe Illustrator (R) Version 5.0 Abbreviated Prolog)
%%Version: 1.1 
%%Version: 1.1
%%CreationDate: (3/7/1994) ()
%%Copyright: ((C) 1987-1994 Adobe Systems Incorporated All Rights Reserved)
currentpacking true setpacking
userdict /Adobe_IllustratorA_AI5_vars 70 dict dup begin
put
/_lp /none def
/_pf
1058
1059
1060
1061
1062
1063
1064
1065

1066
1067
1068
1069
1070
1071
1072
1058
1059
1060
1061
1062
1063
1064

1065
1066
1067
1068
1069
1070
1071
1072







-
+







	{
		0 eq
		{
			(%AI5_BeginLayer) 1 (%AI5_EndLayer--) discard
		}
		{
			/clipForward? true def
			

			/Tx /pop load def
			/Tj /pop load def
			currentdict end clipRenderOff begin begin
		} ifelse
	}
	{
		0 eq
1085
1086
1087
1088
1089
1090
1091
1092

1093
1094
1095
1096
1097
1098
1099
1085
1086
1087
1088
1089
1090
1091

1092
1093
1094
1095
1096
1097
1098
1099







-
+







		pop
		clipForward?
		{
			currentdict
		 end
		 end
		 begin
			

			/clipForward? false ddef
		} if
	} ifelse
} bind def
/Pb
{
	pop pop
Changes to library/listbox.tcl.
1
2
3
4
5
6
7
8



9
10
11
12
13
14
15
1
2
3
4
5



6
7
8
9
10
11
12
13
14
15





-
-
-
+
+
+







# listbox.tcl --
#
# This file defines the default bindings for Tk listbox widgets
# and provides procedures that help in implementing those bindings.
#
# Copyright (c) 1994 The Regents of the University of California.
# Copyright (c) 1994-1995 Sun Microsystems, Inc.
# Copyright (c) 1998 by Scriptics Corporation.
# Copyright © 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.

#--------------------------------------------------------------------------
# tk::Priv elements used in this file:
#
27
28
29
30
31
32
33
34

35
36
37
38
39
40
41
42
43
44

45
46
47
48
49
50
51
52
53
54
55
56
57

58
59
60

61
62
63
64
65
66
67
27
28
29
30
31
32
33

34
35
36
37
38
39
40
41
42
43

44
45
46
47
48
49
50
51
52
53
54
55
56

57
58
59

60
61
62
63
64
65
66
67







-
+









-
+












-
+


-
+








# Note: the check for existence of %W below is because this binding
# is sometimes invoked after a window has been deleted (e.g. because
# there is a double-click binding on the widget that deletes it).  Users
# can put "break"s in their bindings to avoid the error, but this check
# makes that unnecessary.

bind Listbox <1> {
bind Listbox <Button-1> {
    if {[winfo exists %W]} {
	tk::ListboxBeginSelect %W [%W index @%x,%y] 1
    }
}

# Ignore double clicks so that users can define their own behaviors.
# Among other things, this prevents errors if the user deletes the
# listbox on a double click.

bind Listbox <Double-1> {
bind Listbox <Double-Button-1> {
    # Empty script
}

bind Listbox <B1-Motion> {
    set tk::Priv(x) %x
    set tk::Priv(y) %y
    tk::ListboxMotion %W [%W index @%x,%y]
}
bind Listbox <ButtonRelease-1> {
    tk::CancelRepeat
    %W activate @%x,%y
}
bind Listbox <Shift-1> {
bind Listbox <Shift-Button-1> {
    tk::ListboxBeginExtend %W [%W index @%x,%y]
}
bind Listbox <Control-1> {
bind Listbox <Control-Button-1> {
    tk::ListboxBeginToggle %W [%W index @%x,%y]
}
bind Listbox <B1-Leave> {
    set tk::Priv(x) %x
    set tk::Priv(y) %y
    tk::ListboxAutoScan %W
}
165
166
167
168
169
170
171
172

173
174
175
176
177
178
179
180
181
182
183
184
185
186
187




188
189
190
191
192
193
194
195
196
197

198
199
200
201
202

203
204

205
206
207
208
209
210
211
212

213
214
215
216
217
218
219
220
221

222
223

224
225

226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
165
166
167
168
169
170
171

172
173
174
175
176
177
178









179
180
181
182










183





184


185








186









187


188


189












190
191
192
193
194
195
196







-
+






-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
+
-
-
+
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
+
-
-
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-







	%W selection clear 0 end
        tk::FireListboxSelectEvent %W
    }
}

# Additional Tk bindings that aren't part of the Motif look and feel:

bind Listbox <2> {
bind Listbox <Button-2> {
    %W scan mark %x %y
}
bind Listbox <B2-Motion> {
    %W scan dragto %x %y
}

# The MouseWheel will typically only fire on Windows and Mac OS X.
# However, someone could use the "event generate" command to produce
# one on other platforms.

if {[tk windowingsystem] eq "aqua"} {
    bind Listbox <MouseWheel> {
        %W yview scroll [expr {-(%D)}] units
    }
    bind Listbox <Option-MouseWheel> {
bind Listbox <MouseWheel> {
    tk::MouseWheel %W y %D -30.0
}
bind Listbox <Option-MouseWheel> {
        %W yview scroll [expr {-10 * (%D)}] units
    }
    bind Listbox <Shift-MouseWheel> {
        %W xview scroll [expr {-(%D)}] units
    }
    bind Listbox <Shift-Option-MouseWheel> {
        %W xview scroll [expr {-10 * (%D)}] units
    }
} else {
    bind Listbox <MouseWheel> {
    tk::MouseWheel %W y %D -3.0
	if {%D >= 0} {
	    %W yview scroll [expr {-%D/30}] units
	} else {
	    %W yview scroll [expr {(29-%D)/30}] units
	}
}
    }
    bind Listbox <Shift-MouseWheel> {
bind Listbox <Shift-MouseWheel> {
	if {%D >= 0} {
	    %W xview scroll [expr {-%D/30}] units
	} else {
	    %W xview scroll [expr {(29-%D)/30}] units
	}
    }
}

    tk::MouseWheel %W x %D -30.0
if {[tk windowingsystem] eq "x11"} {
    # 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/
    bind Listbox <4> {
	if {!$tk_strictMotif} {
	    %W yview scroll -5 units
	}
}
    }
    bind Listbox <Shift-4> {
bind Listbox <Shift-Option-MouseWheel> {
	if {!$tk_strictMotif} {
	    %W xview scroll -5 units
    tk::MouseWheel %W x %D -3.0
	}
    }
    bind Listbox <5> {
	if {!$tk_strictMotif} {
	    %W yview scroll 5 units
	}
    }
    bind Listbox <Shift-5> {
	if {!$tk_strictMotif} {
	    %W xview scroll 5 units
	}
    }
}

# ::tk::ListboxBeginSelect --
#
# This procedure is typically invoked on button-1 presses.  It begins
# the process of making a selection in the listbox.  Its exact behavior
# depends on the selection mode currently in effect for the listbox;
307
308
309
310
311
312
313
314

315
316
317
318
319
320

321
322
323
324
325
326
327
259
260
261
262
263
264
265

266
267
268
269
270
271

272
273
274
275
276
277
278
279







-
+





-
+







		$w selection clear $i $el
		$w selection clear anchor $el
	    }
	    if {![info exists Priv(listboxSelection)]} {
		set Priv(listboxSelection) [$w curselection]
	    }
	    while {($i < $el) && ($i < $anchor)} {
		if {[lsearch $Priv(listboxSelection) $i] >= 0} {
		if {$i in $Priv(listboxSelection)} {
		    $w selection set $i
		}
		incr i
	    }
	    while {($i > $el) && ($i > $anchor)} {
		if {[lsearch $Priv(listboxSelection) $i] >= 0} {
		if {$i in $Priv(listboxSelection)} {
		    $w selection set $i
		}
		incr i -1
	    }
	    set Priv(listboxPrev) $el
	    tk::FireListboxSelectEvent $w
	}
513
514
515
516
517
518
519
520

521
522
523
524
525
526
527
465
466
467
468
469
470
471

472
473
474
475
476
477
478
479







-
+







    if {$first > $last} {
	set tmp $first
	set first $last
	set last $tmp
    }
    $w selection clear $first $last
    while {$first <= $last} {
	if {[lsearch $Priv(listboxSelection) $first] >= 0} {
	if {$first in $Priv(listboxSelection)} {
	    $w selection set $first
	}
	incr first
    }
    tk::FireListboxSelectEvent $w
}

Changes to library/megawidget.tcl.
1
2
3
4
5
6
7

8
9
10
11
12
13

14
15
16
17
18
19
20
1
2
3
4
5
6

7
8
9
10
11
12

13
14
15
16
17
18
19
20






-
+





-
+







# megawidget.tcl
#
#	Basic megawidget support classes. Experimental for any use other than
#	the ::tk::IconList megawdget, which is itself only designed for use in
#	the Unix file dialogs.
#
# Copyright (c) 2009-2010 Donal K. Fellows
# Copyright © 2009-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.
#

package require Tk 8.6
package require tk

::oo::class create ::tk::Megawidget {
    superclass ::oo::class
    method unknown {w args} {
	if {[string match .* $w]} {
	    [self] create $w {*}$args
	    return $w
Changes to library/menu.tcl.
1
2
3
4
5
6
7
8
9
10




11
12
13
14
15
16
17
1
2
3
4
5
6




7
8
9
10
11
12
13
14
15
16
17






-
-
-
-
+
+
+
+







# menu.tcl --
#
# This file defines the default bindings for Tk menus and menubuttons.
# It also implements keyboard traversal of menus and implements a few
# other utility procedures related to menus.
#
# Copyright (c) 1992-1994 The Regents of the University of California.
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright (c) 2007 Daniel A. Steffen <[email protected]>
# Copyright © 1992-1994 The Regents of the University of California.
# Copyright © 1994-1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# Copyright © 2007 Daniel A. Steffen <[email protected]>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#

#-------------------------------------------------------------------------
# Elements of tk::Priv that are used in this file:
84
85
86
87
88
89
90
91

92
93
94
95
96
97
98
84
85
86
87
88
89
90

91
92
93
94
95
96
97
98







-
+







bind Menubutton <FocusIn> {}
bind Menubutton <Enter> {
    tk::MbEnter %W
}
bind Menubutton <Leave> {
    tk::MbLeave %W
}
bind Menubutton <1> {
bind Menubutton <Button-1> {
    if {$tk::Priv(inMenubutton) ne ""} {
	tk::MbPost $tk::Priv(inMenubutton) %X %Y
    }
}
bind Menubutton <Motion> {
    tk::MbMotion %W up %X %Y
}
134
135
136
137
138
139
140
141

142
143
144
145
146
147
148
134
135
136
137
138
139
140

141
142
143
144
145
146
147
148







-
+








bind Menu <Leave> {
    tk::MenuLeave %W %X %Y %s
}
bind Menu <Motion> {
    tk::MenuMotion %W %x %y %s
}
bind Menu <ButtonPress> {
bind Menu <Button> {
    tk::MenuButtonDown %W
}
bind Menu <ButtonRelease> {
   tk::MenuInvoke %W 1
}
bind Menu <space> {
    tk::MenuInvoke %W 0
164
165
166
167
168
169
170
171

172
173
174
175
176
177
178
179
180

181
182
183
184
185
186
187
188

189
190
191
192
193
194
195
164
165
166
167
168
169
170

171
172
173
174
175
176
177
178
179

180
181
182
183
184
185
186
187

188
189
190
191
192
193
194
195







-
+








-
+







-
+







}
bind Menu <<PrevLine>> {
    tk::MenuUpArrow %W
}
bind Menu <<NextLine>> {
    tk::MenuDownArrow %W
}
bind Menu <KeyPress> {
bind Menu <Key> {
    tk::TraverseWithinMenu %W %A
    break
}

# The following bindings apply to all windows, and are used to
# implement keyboard menu traversal.

if {[tk windowingsystem] eq "x11"} {
    bind all <Alt-KeyPress> {
    bind all <Alt-Key> {
	tk::TraverseToMenu %W %A
    }

    bind all <F10> {
	tk::FirstMenu %W
    }
} else {
    bind Menubutton <Alt-KeyPress> {
    bind Menubutton <Alt-Key> {
	tk::TraverseToMenu %W %A
    }

    bind Menubutton <F10> {
	tk::FirstMenu %W
    }
}
Changes to library/msgbox.tcl.
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







# msgbox.tcl --
#
#	Implements messageboxes for platforms that do not have native
#	messagebox support.
#
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# 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.
#

# Ensure existence of ::tk::dialog namespace
#
Changes to library/msgs/cs.msg.
1
2

3
4

5
6
7
8
9
10
11





12
13
14
15
16
17


18
19
20
21
22



23
24
25
26
27


28
29
30
31



32
33
34
35
36
37


38
39
40
41

42
43
44
45
46
47
48
49
50
51
52
53







54
55
56
57



58
59
60
61



62
63
64
65
66
67
68
69
70
71







72
73
74

75
76
77
1

2
3

4
5
6





7
8
9
10
11
12
13
14
15


16
17
18
19



20
21
22
23
24
25


26
27
28



29
30
31
32
33
34
35


36
37
38
39
40

41
42
43
44
45
46







47
48
49
50
51
52
53
54



55
56
57
58



59
60
61
62
63
64







65
66
67
68
69
70
71
72
73

74
75
76
77

-
+

-
+


-
-
-
-
-
+
+
+
+
+




-
-
+
+


-
-
-
+
+
+



-
-
+
+

-
-
-
+
+
+




-
-
+
+



-
+





-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
+
+
+

-
-
-
+
+
+



-
-
-
-
-
-
-
+
+
+
+
+
+
+


-
+



namespace eval ::tk {
    ::msgcat::mcset cs "&Abort" "&P\u0159eru\u0161it"
    ::msgcat::mcset cs "&Abort" "&Přerušit"
    ::msgcat::mcset cs "&About..." "&O programu..."
    ::msgcat::mcset cs "All Files" "V\u0161echny soubory"
    ::msgcat::mcset cs "All Files" "Všechny soubory"
    ::msgcat::mcset cs "Application Error" "Chyba programu"
    ::msgcat::mcset cs "Bold Italic"
    ::msgcat::mcset cs "&Blue" "&Modr\341"
    ::msgcat::mcset cs "Cancel" "Zru\u0161it"
    ::msgcat::mcset cs "&Cancel" "&Zru\u0161it"
    ::msgcat::mcset cs "Cannot change to the directory \"%1\$s\".\nPermission denied." "Nemohu zm\u011bnit atku\341ln\355 adres\341\u0159 na \"%1\$s\".\nP\u0159\355stup odm\355tnut."
    ::msgcat::mcset cs "Choose Directory" "V\375b\u011br adres\341\u0159e"
    ::msgcat::mcset cs "&Blue" "&Modá"
    ::msgcat::mcset cs "Cancel" "Zrušit"
    ::msgcat::mcset cs "&Cancel" "&Zrušit"
    ::msgcat::mcset cs "Cannot change to the directory \"%1\$s\".\nPermission denied." "Nemohu změnit atkálí adreář na \"%1\$s\".\nPístup odítnut."
    ::msgcat::mcset cs "Choose Directory" "ýběr adreáře"
    ::msgcat::mcset cs "Cl&ear" "Sma&zat"
    ::msgcat::mcset cs "&Clear Console" "&Smazat konzolu"
    ::msgcat::mcset cs "Color" "Barva"
    ::msgcat::mcset cs "Console" "Konzole"
    ::msgcat::mcset cs "&Copy" "&Kop\355rovat"
    ::msgcat::mcset cs "Cu&t" "V&y\u0159\355znout"
    ::msgcat::mcset cs "&Copy" "&Koírovat"
    ::msgcat::mcset cs "Cu&t" "V&yíznout"
    ::msgcat::mcset cs "&Delete" "&Smazat"
    ::msgcat::mcset cs "Details >>" "Detaily >>"
    ::msgcat::mcset cs "Directory \"%1\$s\" does not exist." "Adres\341\u0159 \"%1\$s\" neexistuje."
    ::msgcat::mcset cs "&Directory:" "&Adres\341\u0159:"
    ::msgcat::mcset cs "&Edit" "&\332pravy"
    ::msgcat::mcset cs "Directory \"%1\$s\" does not exist." "Adreář \"%1\$s\" neexistuje."
    ::msgcat::mcset cs "&Directory:" "&Adreář:"
    ::msgcat::mcset cs "&Edit" "Úpravy"
    ::msgcat::mcset cs "Error: %1\$s" "Chyba: %1\$s"
    ::msgcat::mcset cs "E&xit" "&Konec"
    ::msgcat::mcset cs "&File" "&Soubor"
    ::msgcat::mcset cs "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "Soubor \"%1\$s\" ji\u017e existuje.\nChcete jej p\u0159epsat?"
    ::msgcat::mcset cs "File \"%1\$s\" already exists.\n\n" "Soubor \"%1\$s\" ji\u017e existuje.\n\n"
    ::msgcat::mcset cs "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "Soubor \"%1\$s\" již existuje.\nChcete jej přepsat?"
    ::msgcat::mcset cs "File \"%1\$s\" already exists.\n\n" "Soubor \"%1\$s\" již existuje.\n\n"
    ::msgcat::mcset cs "File \"%1\$s\" does not exist." "Soubor \"%1\$s\" neexistuje."
    ::msgcat::mcset cs "File &name:" "&Jm\351no souboru:"
    ::msgcat::mcset cs "File &names:" "&Jm\351na soubor\u016f:"
    ::msgcat::mcset cs "Files of &type:" "&Typy soubor\u016f:"
    ::msgcat::mcset cs "File &name:" "&Jéno souboru:"
    ::msgcat::mcset cs "File &names:" "&Jéna souborů:"
    ::msgcat::mcset cs "Files of &type:" "&Typy souborů:"
    ::msgcat::mcset cs "Fi&les:" "Sou&bory:"
    ::msgcat::mcset cs "&Filter" "&Filtr"
    ::msgcat::mcset cs "Fil&ter:" "Fil&tr:"
    ::msgcat::mcset cs "Font st&yle:"
    ::msgcat::mcset cs "&Green" "Ze&len\341"
    ::msgcat::mcset cs "&Help" "&N\341pov\u011bda"
    ::msgcat::mcset cs "&Green" "Ze&leá"
    ::msgcat::mcset cs "&Help" "&ápověda"
    ::msgcat::mcset cs "Hi" "Ahoj"
    ::msgcat::mcset cs "&Hide Console" "&Schovat Konzolu"
    ::msgcat::mcset cs "&Ignore" "&Ignorovat"
    ::msgcat::mcset cs "Invalid file name \"%1\$s\"." "\u0160patn\351 jm\351no souboru \"%1\$s\"."
    ::msgcat::mcset cs "Invalid file name \"%1\$s\"." "Špaté jéno souboru \"%1\$s\"."
    ::msgcat::mcset cs "Log Files" "Log soubory"
    ::msgcat::mcset cs "&No" "&Ne"
    ::msgcat::mcset cs "&OK"
    ::msgcat::mcset cs "OK"
    ::msgcat::mcset cs "Ok"
    ::msgcat::mcset cs "Open" "Otev\u0159\355t"
    ::msgcat::mcset cs "&Open" "&Otev\u0159\355t"
    ::msgcat::mcset cs "Open Multiple Files" "Otev\u0159\355t v\355ce soubor\u016f"
    ::msgcat::mcset cs "P&aste" "&Vlo\u017eit"
    ::msgcat::mcset cs "&Quit" "&Ukon\u010dit"
    ::msgcat::mcset cs "&Red" "\u010ce&rven\341"
    ::msgcat::mcset cs "Replace existing file?" "Nahradit st\341vaj\355c\355 soubor?"
    ::msgcat::mcset cs "Open" "Otevít"
    ::msgcat::mcset cs "&Open" "&Otevít"
    ::msgcat::mcset cs "Open Multiple Files" "Otevít íce souborů"
    ::msgcat::mcset cs "P&aste" "&Vložit"
    ::msgcat::mcset cs "&Quit" "&Ukončit"
    ::msgcat::mcset cs "&Red" "Če&rveá"
    ::msgcat::mcset cs "Replace existing file?" "Nahradit sávaíí soubor?"
    ::msgcat::mcset cs "&Retry" "Z&novu"
    ::msgcat::mcset cs "&Save" "&Ulo\u017eit"
    ::msgcat::mcset cs "Save As" "Ulo\u017eit jako"
    ::msgcat::mcset cs "Save To Log" "Ulo\u017eit do logu"
    ::msgcat::mcset cs "&Save" "&Uložit"
    ::msgcat::mcset cs "Save As" "Uložit jako"
    ::msgcat::mcset cs "Save To Log" "Uložit do logu"
    ::msgcat::mcset cs "Select Log File" "Vybrat log soubor"
    ::msgcat::mcset cs "Select a file to source" "Vybrat soubor k nahr\341n\355"
    ::msgcat::mcset cs "&Selection:" "&V\375b\u011br:"
    ::msgcat::mcset cs "Skip Messages" "P\u0159esko\u010dit zpr\341vy"
    ::msgcat::mcset cs "Select a file to source" "Vybrat soubor k naháí"
    ::msgcat::mcset cs "&Selection:" "&ýběr:"
    ::msgcat::mcset cs "Skip Messages" "Přeskočit zpávy"
    ::msgcat::mcset cs "&Source..." "&Zdroj..."
    ::msgcat::mcset cs "Tcl Scripts" "Tcl skripty"
    ::msgcat::mcset cs "Tcl for Windows" "Tcl pro Windows"
    ::msgcat::mcset cs "Text Files" "Textov\351 soubory"
    ::msgcat::mcset cs "abort" "p\u0159eru\u0161it"
    ::msgcat::mcset cs "blue" "modr\341"
    ::msgcat::mcset cs "cancel" "zru\u0161it"
    ::msgcat::mcset cs "extension" "p\u0159\355pona"
    ::msgcat::mcset cs "extensions" "p\u0159\355pony"
    ::msgcat::mcset cs "green" "zelen\341"
    ::msgcat::mcset cs "Text Files" "Textoé soubory"
    ::msgcat::mcset cs "abort" "přerušit"
    ::msgcat::mcset cs "blue" "modá"
    ::msgcat::mcset cs "cancel" "zrušit"
    ::msgcat::mcset cs "extension" "pípona"
    ::msgcat::mcset cs "extensions" "pípony"
    ::msgcat::mcset cs "green" "zeleá"
    ::msgcat::mcset cs "ignore" "ignorovat"
    ::msgcat::mcset cs "ok"
    ::msgcat::mcset cs "red" "\u010derven\341"
    ::msgcat::mcset cs "red" "červeá"
    ::msgcat::mcset cs "retry" "znovu"
    ::msgcat::mcset cs "yes" "ano"
}
Changes to library/msgs/da.msg.
1
2
3
4
5
6

7
8
9
10

11
12
13
14
15
16
17
1
2
3
4
5

6
7
8
9

10
11
12
13
14
15
16
17





-
+



-
+







namespace eval ::tk {
    ::msgcat::mcset da "&Abort" "&Afbryd"
    ::msgcat::mcset da "&About..." "&Om..."
    ::msgcat::mcset da "All Files" "Alle filer"
    ::msgcat::mcset da "Application Error" "Programfejl"
    ::msgcat::mcset da "&Blue" "&Bl\u00E5"
    ::msgcat::mcset da "&Blue" "&Blå"
    ::msgcat::mcset da "Cancel" "Annuller"
    ::msgcat::mcset da "&Cancel" "&Annuller"
    ::msgcat::mcset da "Cannot change to the directory \"%1\$s\".\nPermission denied." "Kan ikke skifte til katalog \"%1\$s\".\nIngen rettigheder."
    ::msgcat::mcset da "Choose Directory" "V\u00E6lg katalog"
    ::msgcat::mcset da "Choose Directory" "Vælg katalog"
    ::msgcat::mcset da "Cl&ear" "&Ryd"
    ::msgcat::mcset da "&Clear Console" "&Ryd konsolen"
    ::msgcat::mcset da "Color" "Farve"
    ::msgcat::mcset da "Console" "Konsol"
    ::msgcat::mcset da "&Copy" "&Kopier"
    ::msgcat::mcset da "Cu&t" "Kli&p"
    ::msgcat::mcset da "&Delete" "&Slet"
27
28
29
30
31
32
33
34
35


36
37
38
39
40
41
42
43
44
45
46
47
48




49
50

51
52
53
54
55
56
57


58
59
60
61
62

63
64
65
66
67
68

69
70
71
72

73
74
75

76
77
78
27
28
29
30
31
32
33


34
35
36
37
38
39
40
41
42
43
44




45
46
47
48
49

50
51
52
53
54
55


56
57
58
59
60
61

62
63
64
65
66
67

68
69
70
71

72
73
74

75
76
77
78







-
-
+
+









-
-
-
-
+
+
+
+

-
+





-
-
+
+




-
+





-
+



-
+


-
+



    ::msgcat::mcset da "File \"%1\$s\" does not exist." "Filen \"%1\$s\" findes ikke."
    ::msgcat::mcset da "File &name:" "Fil&navn:"
    ::msgcat::mcset da "File &names:" "Fil&navne:"
    ::msgcat::mcset da "Files of &type:" "Fil&typer:"
    ::msgcat::mcset da "Fi&les:" "Fi&ler:"
    ::msgcat::mcset da "&Filter"
    ::msgcat::mcset da "Fil&ter:"
    ::msgcat::mcset da "&Green" "&Gr\u00F8n"
    ::msgcat::mcset da "&Help" "&Hj\u00E6lp"
    ::msgcat::mcset da "&Green" "&Grøn"
    ::msgcat::mcset da "&Help" "&Hjælp"
    ::msgcat::mcset da "Hi" "Hej"
    ::msgcat::mcset da "&Hide Console" "Skjul &konsol"
    ::msgcat::mcset da "&Ignore" "&Ignorer"
    ::msgcat::mcset da "Invalid file name \"%1\$s\"." "Ugyldig fil navn \"%1\$s\"."
    ::msgcat::mcset da "Log Files" "Logfiler"
    ::msgcat::mcset da "&No" "&Nej"
    ::msgcat::mcset da "&OK" "&O.K."
    ::msgcat::mcset da "OK" "O.K."
    ::msgcat::mcset da "Ok"
    ::msgcat::mcset da "Open" "\u00C5bn"
    ::msgcat::mcset da "&Open" "&\u00C5bn"
    ::msgcat::mcset da "Open Multiple Files" "\u00C5bn flere filer"
    ::msgcat::mcset da "P&aste" "&Inds\u00E6t"
    ::msgcat::mcset da "Open" "Åbn"
    ::msgcat::mcset da "&Open" "&Åbn"
    ::msgcat::mcset da "Open Multiple Files" "Åbn flere filer"
    ::msgcat::mcset da "P&aste" "&Indsæt"
    ::msgcat::mcset da "&Quit" "&Afslut"
    ::msgcat::mcset da "&Red" "&R\u00F8d"
    ::msgcat::mcset da "&Red" "&Rød"
    ::msgcat::mcset da "Replace existing file?" "Erstat eksisterende fil?"
    ::msgcat::mcset da "&Retry" "&Gentag"
    ::msgcat::mcset da "&Save" "&Gem"
    ::msgcat::mcset da "Save As" "Gem som"
    ::msgcat::mcset da "Save To Log" "Gem i log"
    ::msgcat::mcset da "Select Log File" "V\u00E6lg logfil"
    ::msgcat::mcset da "Select a file to source" "V\u00E6lg k\u00F8rbar fil"
    ::msgcat::mcset da "Select Log File" "Vælg logfil"
    ::msgcat::mcset da "Select a file to source" "Vælg kørbar fil"
    ::msgcat::mcset da "&Selection:" "&Udvalg:"
    ::msgcat::mcset da "Show &Hidden Directories" "Vis &skjulte kataloger"
    ::msgcat::mcset da "Show &Hidden Files and Directories" "Vis &skjulte filer og kataloger"
    ::msgcat::mcset da "Skip Messages" "Overspring beskeder"
    ::msgcat::mcset da "&Source..." "&K\u00F8r..."
    ::msgcat::mcset da "&Source..." "&Kør..."
    ::msgcat::mcset da "Tcl Scripts" "Tcl-Skripter"
    ::msgcat::mcset da "Tcl for Windows" "Tcl for Windows"
    ::msgcat::mcset da "Text Files" "Tekstfiler"
    ::msgcat::mcset da "&Yes" "&Ja"
    ::msgcat::mcset da "abort" "afbryd"
    ::msgcat::mcset da "blue" "bl\u00E5"
    ::msgcat::mcset da "blue" "blå"
    ::msgcat::mcset da "cancel" "afbryd"
    ::msgcat::mcset da "extension"
    ::msgcat::mcset da "extensions"
    ::msgcat::mcset da "green" "gr\u00F8n"
    ::msgcat::mcset da "green" "grøn"
    ::msgcat::mcset da "ignore" "ignorer"
    ::msgcat::mcset da "ok"
    ::msgcat::mcset da "red" "r\u00F8d"
    ::msgcat::mcset da "red" "rød"
    ::msgcat::mcset da "retry" "gentag"
    ::msgcat::mcset da "yes" "ja"
}
Changes to library/msgs/de.msg.
1
2
3

4
5
6
7
8
9
10
11
12
13
14
15



16
17
18
19
20

21
22
23
24
25
26
27
28
29

30
31
32
33
34
35
36
37
38
39
40
41

42
43
44
45
46

47
48
49
50
51
52
53
54
55
56




57
58
59
60
61
62
63
64
65
66
67


68
69
70
71
72
73


74
75
76

77
78
79
80
81
82
83
84
85

86
87
88
89
90
91
1
2

3
4
5
6
7
8
9
10
11
12



13
14
15
16
17
18
19

20
21
22
23
24
25
26
27
28

29
30
31
32
33
34
35
36
37
38
39
40

41
42
43
44
45

46
47
48
49
50
51
52




53
54
55
56
57
58
59
60
61
62
63
64
65


66
67
68
69
70
71


72
73
74
75

76
77
78
79
80
81
82
83
84

85
86
87
88
89
90
91


-
+









-
-
-
+
+
+




-
+








-
+











-
+




-
+






-
-
-
-
+
+
+
+









-
-
+
+




-
-
+
+


-
+








-
+






namespace eval ::tk {
    ::msgcat::mcset de "&Abort" "&Abbruch"
    ::msgcat::mcset de "&About..." "&\u00dcber..."
    ::msgcat::mcset de "&About..." "&Über..."
    ::msgcat::mcset de "All Files" "Alle Dateien"
    ::msgcat::mcset de "Application Error" "Applikationsfehler"
    ::msgcat::mcset de "&Apply" "&Anwenden"
    ::msgcat::mcset de "Bold" "Fett"
    ::msgcat::mcset de "Bold Italic" "Fett kursiv"
    ::msgcat::mcset de "&Blue" "&Blau"
    ::msgcat::mcset de "Cancel" "Abbruch"
    ::msgcat::mcset de "&Cancel" "&Abbruch"
    ::msgcat::mcset de "Cannot change to the directory \"%1\$s\".\nPermission denied." "Kann nicht in das Verzeichnis \"%1\$s\" wechseln.\nKeine Rechte vorhanden."
    ::msgcat::mcset de "Choose Directory" "W\u00e4hle Verzeichnis"
    ::msgcat::mcset de "Cl&ear" "&R\u00fccksetzen"
    ::msgcat::mcset de "&Clear Console" "&Konsole l\u00f6schen"
    ::msgcat::mcset de "Choose Directory" "Wähle Verzeichnis"
    ::msgcat::mcset de "Cl&ear" "&Rücksetzen"
    ::msgcat::mcset de "&Clear Console" "&Konsole löschen"
    ::msgcat::mcset de "Color" "Farbe"
    ::msgcat::mcset de "Console" "Konsole"
    ::msgcat::mcset de "&Copy" "&Kopieren"
    ::msgcat::mcset de "Cu&t" "Aus&schneiden"
    ::msgcat::mcset de "&Delete" "&L\u00f6schen"
    ::msgcat::mcset de "&Delete" "&Löschen"
    ::msgcat::mcset de "Details >>"
    ::msgcat::mcset de "Directory \"%1\$s\" does not exist." "Das Verzeichnis \"%1\$s\" existiert nicht."
    ::msgcat::mcset de "&Directory:" "&Verzeichnis:"
    ::msgcat::mcset de "&Edit" "&Bearbeiten"
    ::msgcat::mcset de "Effects" "Effekte"
    ::msgcat::mcset de "Error: %1\$s" "Fehler: %1\$s"
    ::msgcat::mcset de "E&xit" "&Ende"
    ::msgcat::mcset de "&File" "&Datei"
    ::msgcat::mcset de "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "Die Datei \"%1\$s\" ist bereits vorhanden.\nWollen sie diese Datei \u00fcberschreiben ?"
    ::msgcat::mcset de "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "Die Datei \"%1\$s\" ist bereits vorhanden.\nWollen sie diese Datei überschreiben ?"
    ::msgcat::mcset de "File \"%1\$s\" already exists.\n\n" "Die Datei \"%1\$s\" ist bereits vorhanden.\n\n"
    ::msgcat::mcset de "File \"%1\$s\" does not exist." "Die Datei \"%1\$s\" existiert nicht."
    ::msgcat::mcset de "File &name:" "Datei&name:"
    ::msgcat::mcset de "File &names:" "Datei&namen:"
    ::msgcat::mcset de "Files of &type:" "Dateien des &Typs:"
    ::msgcat::mcset de "Fi&les:" "Dat&eien:"
    ::msgcat::mcset de "&Filter"
    ::msgcat::mcset de "Fil&ter:"
    ::msgcat::mcset de "Font" "Schriftart"
    ::msgcat::mcset de "&Font:" "Schriftart:"
    ::msgcat::mcset de "Font st&yle:" "Schriftschnitt:"
    ::msgcat::mcset de "&Green" "&Gr\u00fcn"
    ::msgcat::mcset de "&Green" "&Grün"
    ::msgcat::mcset de "&Help" "&Hilfe"
    ::msgcat::mcset de "Hi" "Hallo"
    ::msgcat::mcset de "&Hide Console" "&Konsole unsichtbar machen"
    ::msgcat::mcset de "&Ignore" "&Ignorieren"
    ::msgcat::mcset de "Invalid file name \"%1\$s\"." "Ung\u00fcltiger Dateiname \"%1\$s\"."
    ::msgcat::mcset de "Invalid file name \"%1\$s\"." "Ungültiger Dateiname \"%1\$s\"."
    ::msgcat::mcset de "Italic" "Kursiv"
    ::msgcat::mcset de "Log Files" "Protokolldatei"
    ::msgcat::mcset de "&No" "&Nein"
    ::msgcat::mcset de "&OK"
    ::msgcat::mcset de "OK"
    ::msgcat::mcset de "Ok"
    ::msgcat::mcset de "Open" "\u00d6ffnen"
    ::msgcat::mcset de "&Open" "\u00d6&ffnen"
    ::msgcat::mcset de "Open Multiple Files" "Mehrere Dateien \u00F6ffnen"
    ::msgcat::mcset de "P&aste" "E&inf\u00fcgen"
    ::msgcat::mcset de "Open" "Öffnen"
    ::msgcat::mcset de "&Open" "Ö&ffnen"
    ::msgcat::mcset de "Open Multiple Files" "Mehrere Dateien Öffnen"
    ::msgcat::mcset de "P&aste" "E&infügen"
    ::msgcat::mcset de "&Quit" "&Beenden"
    ::msgcat::mcset de "&Red" "&Rot"
    ::msgcat::mcset de "Regular" "Standard"
    ::msgcat::mcset de "Replace existing file?" "Existierende Datei ersetzen?"
    ::msgcat::mcset de "&Retry" "&Wiederholen"
    ::msgcat::mcset de "Sample" "Beispiel"
    ::msgcat::mcset de "&Save" "&Speichern"
    ::msgcat::mcset de "Save As" "Speichern unter"
    ::msgcat::mcset de "Save To Log" "In Protokoll speichern"
    ::msgcat::mcset de "Select Log File" "Protokolldatei ausw\u00e4hlen"
    ::msgcat::mcset de "Select a file to source" "Auszuf\u00fchrende Datei ausw\u00e4hlen"
    ::msgcat::mcset de "Select Log File" "Protokolldatei auswählen"
    ::msgcat::mcset de "Select a file to source" "Auszuführende Datei auswählen"
    ::msgcat::mcset de "&Selection:" "Auswah&l:"
    ::msgcat::mcset de "&Size:" "Schriftgrad:"
    ::msgcat::mcset de "Show &Hidden Directories" "Zeige versteckte Dateien"
    ::msgcat::mcset de "Show &Hidden Files and Directories" "Zeige versteckte Dateien und Verzeichnisse"
    ::msgcat::mcset de "Skip Messages" "Weitere Nachrichten \u00fcberspringen"
    ::msgcat::mcset de "&Source..." "&Ausf\u00fchren..."
    ::msgcat::mcset de "Skip Messages" "Weitere Nachrichten überspringen"
    ::msgcat::mcset de "&Source..." "&Ausführen..."
    ::msgcat::mcset de "Stri&keout" "&Durchgestrichen"
    ::msgcat::mcset de "Tcl Scripts" "Tcl-Skripte"
    ::msgcat::mcset de "Tcl for Windows" "Tcl f\u00fcr Windows"
    ::msgcat::mcset de "Tcl for Windows" "Tcl für Windows"
    ::msgcat::mcset de "Text Files" "Textdateien"
    ::msgcat::mcset de "&Underline" "&Unterstrichen"
    ::msgcat::mcset de "&Yes" "&Ja"
    ::msgcat::mcset de "abort" "abbrechen"
    ::msgcat::mcset de "blue" "blau"
    ::msgcat::mcset de "cancel" "abbrechen"
    ::msgcat::mcset de "extension" "Erweiterung"
    ::msgcat::mcset de "extensions" "Erweiterungen"
    ::msgcat::mcset de "green" "gr\u00fcn"
    ::msgcat::mcset de "green" "grün"
    ::msgcat::mcset de "ignore" "ignorieren"
    ::msgcat::mcset de "ok"
    ::msgcat::mcset de "red" "rot"
    ::msgcat::mcset de "retry" "wiederholen"
    ::msgcat::mcset de "yes" "ja"
}
Changes to library/msgs/el.msg.
1
2
3
4
5
6
7
8
9
10
11






12
13
14
15
16
17
18
19
20
21
22









23
24
25
26
27




28
29
30

31
32

33
34
35
36
37
38
39
40
41
42
43
44











45
46
47
48
49
50
51
52
53








54
55
56
57
58




59
60
61
62
63
64
65






66
67
68
69
70




71
72
73
74
75
76
77
78
79
80
81
82
83
84
85














86
1
2
3
4
5






6
7
8
9
10
11
12
13









14
15
16
17
18
19
20
21
22
23




24
25
26
27
28
29

30
31

32
33











34
35
36
37
38
39
40
41
42
43
44
45








46
47
48
49
50
51
52
53
54




55
56
57
58
59






60
61
62
63
64
65
66




67
68
69
70
71














72
73
74
75
76
77
78
79
80
81
82
83
84
85
86





-
-
-
-
-
-
+
+
+
+
+
+


-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+

-
-
-
-
+
+
+
+


-
+

-
+

-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+

-
-
-
-
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+

-
-
-
-
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+

## Messages for the Greek (Hellenic - "el") language.
## Please report any changes/suggestions to:
##    [email protected]

namespace eval ::tk {
    ::msgcat::mcset el "&Abort"              "\u03a4\u03b5\u03c1\u03bc\u03b1\u03c4\u03b9\u03c3\u03bc\u03cc\u03c2"
    ::msgcat::mcset el "About..."           "\u03a3\u03c7\u03b5\u03c4\u03b9\u03ba\u03ac..."
    ::msgcat::mcset el "All Files"          "\u038c\u03bb\u03b1 \u03c4\u03b1 \u0391\u03c1\u03c7\u03b5\u03af\u03b1"
    ::msgcat::mcset el "Application Error"  "\u039b\u03ac\u03b8\u03bf\u03c2 \u0395\u03c6\u03b1\u03c1\u03bc\u03bf\u03b3\u03ae\u03c2"
    ::msgcat::mcset el "&Blue"               "\u039c\u03c0\u03bb\u03b5"
    ::msgcat::mcset el "&Cancel"             "\u0391\u03ba\u03cd\u03c1\u03c9\u03c3\u03b7"
    ::msgcat::mcset el "&Abort"              "Τερματισμός"
    ::msgcat::mcset el "About..."           "Σχετικά..."
    ::msgcat::mcset el "All Files"          "Όλα τα Αρχεία"
    ::msgcat::mcset el "Application Error"  "Λάθος Εφαρμογής"
    ::msgcat::mcset el "&Blue"               "Μπλε"
    ::msgcat::mcset el "&Cancel"             "Ακύρωση"
    ::msgcat::mcset el \
"Cannot change to the directory \"%1\$s\".\nPermission denied." \
"\u0394\u03b5\u03bd \u03b5\u03af\u03bd\u03b1\u03b9 \u03b4\u03c5\u03bd\u03b1\u03c4\u03ae \u03b7 \u03b1\u03bb\u03bb\u03b1\u03b3\u03ae \u03ba\u03b1\u03c4\u03b1\u03bb\u03cc\u03b3\u03bf\u03c5 \u03c3\u03b5 \"%1\$s\".\n\u0397 \u03c0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7 \u03b4\u03b5\u03bd \u03b5\u03c0\u03b9\u03c4\u03c1\u03ad\u03c0\u03b5\u03c4\u03b1\u03b9."
    ::msgcat::mcset el "Choose Directory"   "\u0395\u03c0\u03b9\u03bb\u03bf\u03b3\u03ae \u039a\u03b1\u03c4\u03b1\u03bb\u03cc\u03b3\u03bf\u03c5"
    ::msgcat::mcset el "Clear"              "\u039a\u03b1\u03b8\u03b1\u03c1\u03b9\u03c3\u03bc\u03cc\u03c2"
    ::msgcat::mcset el "Color"              "\u03a7\u03c1\u03ce\u03bc\u03b1"
    ::msgcat::mcset el "Console"            "\u039a\u03bf\u03bd\u03c3\u03cc\u03bb\u03b1"
    ::msgcat::mcset el "Copy"               "\u0391\u03bd\u03c4\u03b9\u03b3\u03c1\u03b1\u03c6\u03ae"
    ::msgcat::mcset el "Cut"                "\u0391\u03c0\u03bf\u03ba\u03bf\u03c0\u03ae"
    ::msgcat::mcset el "Delete"             "\u0394\u03b9\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae"
    ::msgcat::mcset el "Details >>"         "\u039b\u03b5\u03c0\u03c4\u03bf\u03bc\u03ad\u03c1\u03b5\u03b9\u03b5\u03c2 >>"
"Δεν είναι δυνατή η αλλαγή καταλόγου σε \"%1\$s\".\nΗ πρόσβαση δεν επιτρέπεται."
    ::msgcat::mcset el "Choose Directory"   "Επιλογή Καταλόγου"
    ::msgcat::mcset el "Clear"              "Καθαρισμός"
    ::msgcat::mcset el "Color"              "Χρώμα"
    ::msgcat::mcset el "Console"            "Κονσόλα"
    ::msgcat::mcset el "Copy"               "Αντιγραφή"
    ::msgcat::mcset el "Cut"                "Αποκοπή"
    ::msgcat::mcset el "Delete"             "Διαγραφή"
    ::msgcat::mcset el "Details >>"         "Λεπτομέρειες >>"
    ::msgcat::mcset el "Directory \"%1\$s\" does not exist." \
                                        "\u039f \u03ba\u03b1\u03c4\u03ac\u03bb\u03bf\u03b3\u03bf\u03c2 \"%1\$s\" \u03b4\u03b5\u03bd \u03c5\u03c0\u03ac\u03c1\u03c7\u03b5\u03b9."
    ::msgcat::mcset el "&Directory:"         "&\u039a\u03b1\u03c4\u03ac\u03bb\u03bf\u03b3\u03bf\u03c2:"
    ::msgcat::mcset el "Error: %1\$s"       "\u039b\u03ac\u03b8\u03bf\u03c2: %1\$s"
    ::msgcat::mcset el "Exit"               "\u0388\u03be\u03bf\u03b4\u03bf\u03c2"
                                        "Ο κατάλογος \"%1\$s\" δεν υπάρχει."
    ::msgcat::mcset el "&Directory:"         "&Κατάλογος:"
    ::msgcat::mcset el "Error: %1\$s"       "Λάθος: %1\$s"
    ::msgcat::mcset el "Exit"               "Έξοδος"
    ::msgcat::mcset el \
               "File \"%1\$s\" already exists.\nDo you want to overwrite it?" \
               "\u03a4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \"%1\$s\" \u03ae\u03b4\u03b7 \u03c5\u03c0\u03ac\u03c1\u03c7\u03b5\u03b9.\n\u0398\u03ad\u03bb\u03b5\u03c4\u03b5 \u03bd\u03b1 \u03b5\u03c0\u03b9\u03ba\u03b1\u03bb\u03c5\u03c6\u03b8\u03b5\u03af;"
               "Το αρχείο \"%1\$s\" ήδη υπάρχει.\nΘέλετε να επικαλυφθεί;"
    ::msgcat::mcset el "File \"%1\$s\" already exists.\n\n" \
                   "\u03a4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \"%1\$s\" \u03ae\u03b4\u03b7 \u03c5\u03c0\u03ac\u03c1\u03c7\u03b5\u03b9.\n\n"
                   "Το αρχείο \"%1\$s\" ήδη υπάρχει.\n\n"
    ::msgcat::mcset el "File \"%1\$s\" does not exist." \
                   "\u03a4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \"%1\$s\" \u03b4\u03b5\u03bd \u03c5\u03c0\u03ac\u03c1\u03c7\u03b5\u03b9."
    ::msgcat::mcset el "File &name:"         "\u038c&\u03bd\u03bf\u03bc\u03b1 \u03b1\u03c1\u03c7\u03b5\u03af\u03bf\u03c5:"
    ::msgcat::mcset el "File &names:"        "\u038c&\u03bd\u03bf\u03bc\u03b1 \u03b1\u03c1\u03c7\u03b5\u03af\u03c9\u03bd:"
    ::msgcat::mcset el "Files of &type:"     "\u0391\u03c1\u03c7\u03b5\u03af\u03b1 \u03c4\u03bf\u03c5 &\u03c4\u03cd\u03c0\u03bf\u03c5:"
    ::msgcat::mcset el "Fi&les:"             "\u0391\u03c1\u03c7\u03b5\u03af\u03b1:"
    ::msgcat::mcset el "&Filter"             "\u03a6\u03af\u03bb\u03c4\u03c1\u03bf"
    ::msgcat::mcset el "Fil&ter:"            "\u03a6\u03af\u03bb\u03c4\u03c1\u03bf:"
    ::msgcat::mcset el "&Green"              "\u03a0\u03c1\u03ac\u03c3\u03b9\u03bd\u03bf"
    ::msgcat::mcset el "Hi"                 "\u0393\u03b5\u03b9\u03b1"
    ::msgcat::mcset el "Hide Console"       "\u0391\u03c0\u03cc\u03ba\u03c1\u03c5\u03c8\u03b7 \u03ba\u03bf\u03bd\u03c3\u03cc\u03bb\u03b1\u03c2"
    ::msgcat::mcset el "&Ignore"             "\u0391\u03b3\u03bd\u03cc\u03b7\u03c3\u03b7"
                   "Το αρχείο \"%1\$s\" δεν υπάρχει."
    ::msgcat::mcset el "File &name:"         "Ό&νομα αρχείου:"
    ::msgcat::mcset el "File &names:"        "Ό&νομα αρχείων:"
    ::msgcat::mcset el "Files of &type:"     "Αρχεία του &τύπου:"
    ::msgcat::mcset el "Fi&les:"             "Αρχεία:"
    ::msgcat::mcset el "&Filter"             "Φίλτρο"
    ::msgcat::mcset el "Fil&ter:"            "Φίλτρο:"
    ::msgcat::mcset el "&Green"              "Πράσινο"
    ::msgcat::mcset el "Hi"                 "Γεια"
    ::msgcat::mcset el "Hide Console"       "Απόκρυψη κονσόλας"
    ::msgcat::mcset el "&Ignore"             "Αγνόηση"
    ::msgcat::mcset el "Invalid file name \"%1\$s\"." \
                   "\u0386\u03ba\u03c5\u03c1\u03bf \u03cc\u03bd\u03bf\u03bc\u03b1 \u03b1\u03c1\u03c7\u03b5\u03af\u03bf\u03c5 \"%1\$s\"."
    ::msgcat::mcset el "Log Files"          "\u0391\u03c1\u03c7\u03b5\u03af\u03b1 \u039a\u03b1\u03c4\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae\u03c2"
    ::msgcat::mcset el "&No"                 "\u038c\u03c7\u03b9"
    ::msgcat::mcset el "&OK"                 "\u0395\u03bd\u03c4\u03ac\u03be\u03b5\u03b9"
    ::msgcat::mcset el "OK"                 "\u0395\u03bd\u03c4\u03ac\u03be\u03b5\u03b9"
    ::msgcat::mcset el "Ok"                 "\u0395\u03bd\u03c4\u03ac\u03be\u03b5\u03b9"
    ::msgcat::mcset el "Open"               "\u0386\u03bd\u03bf\u03b9\u03b3\u03bc\u03b1"
    ::msgcat::mcset el "&Open"               "\u0386\u03bd\u03bf\u03b9\u03b3\u03bc\u03b1"
                   "Άκυρο όνομα αρχείου \"%1\$s\"."
    ::msgcat::mcset el "Log Files"          "Αρχεία Καταγραφής"
    ::msgcat::mcset el "&No"                 "Όχι"
    ::msgcat::mcset el "&OK"                 "Εντάξει"
    ::msgcat::mcset el "OK"                 "Εντάξει"
    ::msgcat::mcset el "Ok"                 "Εντάξει"
    ::msgcat::mcset el "Open"               "Άνοιγμα"
    ::msgcat::mcset el "&Open"               "Άνοιγμα"
    ::msgcat::mcset el "Open Multiple Files" \
                                        "\u0386\u03bd\u03bf\u03b9\u03b3\u03bc\u03b1 \u03c0\u03bf\u03bb\u03bb\u03b1\u03c0\u03bb\u03ce\u03bd \u03b1\u03c1\u03c7\u03b5\u03af\u03c9\u03bd"
    ::msgcat::mcset el "P&aste"              "\u0395\u03c0\u03b9\u03ba\u03cc\u03bb\u03bb\u03b7\u03c3\u03b7"
    ::msgcat::mcset el "Quit"               "\u0388\u03be\u03bf\u03b4\u03bf\u03c2"
    ::msgcat::mcset el "&Red"                "\u039a\u03cc\u03ba\u03ba\u03b9\u03bd\u03bf"
                                        "Άνοιγμα πολλαπλών αρχείων"
    ::msgcat::mcset el "P&aste"              "Επικόλληση"
    ::msgcat::mcset el "Quit"               "Έξοδος"
    ::msgcat::mcset el "&Red"                "Κόκκινο"
    ::msgcat::mcset el "Replace existing file?" \
                                        "\u0395\u03c0\u03b9\u03ba\u03ac\u03bb\u03c5\u03c8\u03b7 \u03c5\u03c0\u03ac\u03c1\u03c7\u03bf\u03bd\u03c4\u03bf\u03c2 \u03b1\u03c1\u03c7\u03b5\u03af\u03bf\u03c5;"
    ::msgcat::mcset el "&Retry"              "\u03a0\u03c1\u03bf\u03c3\u03c0\u03ac\u03b8\u03b7\u03c3\u03b5 \u03be\u03b1\u03bd\u03ac"
    ::msgcat::mcset el "&Save"               "\u0391\u03c0\u03bf\u03b8\u03ae\u03ba\u03b5\u03c5\u03c3\u03b7"
    ::msgcat::mcset el "Save As"            "\u0391\u03c0\u03bf\u03b8\u03ae\u03ba\u03b5\u03c5\u03c3\u03b7 \u03c3\u03b1\u03bd"
    ::msgcat::mcset el "Save To Log"        "\u0391\u03c0\u03bf\u03b8\u03ae\u03ba\u03b5\u03c5\u03c3\u03b7 \u03c3\u03c4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \u03ba\u03b1\u03c4\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae\u03c2"
    ::msgcat::mcset el "Select Log File"    "\u0395\u03c0\u03b9\u03bb\u03bf\u03b3\u03ae \u03b1\u03c1\u03c7\u03b5\u03af\u03bf\u03c5 \u03ba\u03b1\u03c4\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae\u03c2"
                                        "Επικάλυψη υπάρχοντος αρχείου;"
    ::msgcat::mcset el "&Retry"              "Προσπάθησε ξανά"
    ::msgcat::mcset el "&Save"               "Αποθήκευση"
    ::msgcat::mcset el "Save As"            "Αποθήκευση σαν"
    ::msgcat::mcset el "Save To Log"        "Αποθήκευση στο αρχείο καταγραφής"
    ::msgcat::mcset el "Select Log File"    "Επιλογή αρχείου καταγραφής"
    ::msgcat::mcset el "Select a file to source" \
                                        "\u0395\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \u03b3\u03b9\u03b1 \u03b5\u03ba\u03c4\u03ad\u03bb\u03b5\u03c3\u03b7"
    ::msgcat::mcset el "&Selection:"         "\u0395\u03c0\u03b9\u03bb\u03bf\u03b3\u03ae:"
    ::msgcat::mcset el "Skip Messages"      "\u0391\u03c0\u03bf\u03c6\u03c5\u03b3\u03ae\u03bc\u03b7\u03bd\u03c5\u03bc\u03ac\u03c4\u03c9\u03bd"
    ::msgcat::mcset el "&Source..."          "\u0395\u03ba\u03c4\u03ad\u03bb\u03b5\u03c3\u03b7..."
                                        "Επιλέξτε αρχείο για εκτέλεση"
    ::msgcat::mcset el "&Selection:"         "Επιλογή:"
    ::msgcat::mcset el "Skip Messages"      "Αποφυγήμηνυμάτων"
    ::msgcat::mcset el "&Source..."          "Εκτέλεση..."
    ::msgcat::mcset el "Tcl Scripts"        "Tcl Scripts"
    ::msgcat::mcset el "Tcl for Windows"    "Tcl \u03b3\u03b9\u03b1 Windows"
    ::msgcat::mcset el "Text Files"         "\u0391\u03c1\u03c7\u03b5\u03af\u03b1 \u039a\u03b5\u03b9\u03bc\u03ad\u03bd\u03bf\u03c5"
    ::msgcat::mcset el "&Yes"                "\u039d\u03b1\u03b9"
    ::msgcat::mcset el "abort"              "\u03c4\u03b5\u03c1\u03bc\u03b1\u03c4\u03b9\u03c3\u03bc\u03cc\u03c2"
    ::msgcat::mcset el "blue"               "\u03bc\u03c0\u03bb\u03b5"
    ::msgcat::mcset el "cancel"             "\u03b1\u03ba\u03cd\u03c1\u03c9\u03c3\u03b7"
    ::msgcat::mcset el "extension"          "\u03b5\u03c0\u03ad\u03ba\u03c4\u03b1\u03c3\u03b7"
    ::msgcat::mcset el "extensions"         "\u03b5\u03c0\u03b5\u03ba\u03c4\u03ac\u03c3\u03b5\u03b9\u03c2"
    ::msgcat::mcset el "green"              "\u03c0\u03c1\u03ac\u03c3\u03b9\u03bd\u03bf"
    ::msgcat::mcset el "ignore"             "\u03b1\u03b3\u03bd\u03cc\u03b7\u03c3\u03b7"
    ::msgcat::mcset el "ok"                 "\u03b5\u03bd\u03c4\u03ac\u03be\u03b5\u03b9"
    ::msgcat::mcset el "red"                "\u03ba\u03cc\u03ba\u03ba\u03b9\u03bd\u03bf"
    ::msgcat::mcset el "retry"              "\u03c0\u03c1\u03bf\u03c3\u03c0\u03ac\u03b8\u03b7\u03c3\u03b5 \u03be\u03b1\u03bd\u03ac"
    ::msgcat::mcset el "yes"                "\u03bd\u03b1\u03b9"
    ::msgcat::mcset el "Tcl for Windows"    "Tcl για Windows"
    ::msgcat::mcset el "Text Files"         "Αρχεία Κειμένου"
    ::msgcat::mcset el "&Yes"                "Ναι"
    ::msgcat::mcset el "abort"              "τερματισμός"
    ::msgcat::mcset el "blue"               "μπλε"
    ::msgcat::mcset el "cancel"             "ακύρωση"
    ::msgcat::mcset el "extension"          "επέκταση"
    ::msgcat::mcset el "extensions"         "επεκτάσεις"
    ::msgcat::mcset el "green"              "πράσινο"
    ::msgcat::mcset el "ignore"             "αγνόηση"
    ::msgcat::mcset el "ok"                 "εντάξει"
    ::msgcat::mcset el "red"                "κόκκινο"
    ::msgcat::mcset el "retry"              "προσπάθησε ξανά"
    ::msgcat::mcset el "yes"                "ναι"
}
Changes to library/msgs/eo.msg.
1
2

3
4

5
6
7
8
9

10
11
12
13
14
15
16

17
18
19
20
21
22
23
24
25

26
27
28
29
30
31
32
33
34
35
36
37

38
39
40
41
42
43
44
45
46
47
48

49
50
51

52
53
54
55
56
57
58
59

60
61
62
63
64
65

66
67
68
69
70
71
72

73
74
75
1

2
3

4
5
6
7
8

9
10
11
12
13
14
15

16
17
18
19
20
21
22
23
24

25
26
27
28
29
30
31
32
33
34
35
36

37
38
39
40
41
42
43
44
45
46
47

48
49
50

51
52
53
54
55
56
57
58

59
60
61
62
63
64

65
66
67
68
69
70
71

72
73
74
75

-
+

-
+




-
+






-
+








-
+











-
+










-
+


-
+







-
+





-
+






-
+



namespace eval ::tk {
    ::msgcat::mcset eo "&Abort" "&\u0108esigo"
    ::msgcat::mcset eo "&Abort" "&Ĉesigo"
    ::msgcat::mcset eo "&About..." "Pri..."
    ::msgcat::mcset eo "All Files" "\u0108ioj dosieroj"
    ::msgcat::mcset eo "All Files" "Ĉioj dosieroj"
    ::msgcat::mcset eo "Application Error" "Aplikoerraro"
    ::msgcat::mcset eo "&Blue" "&Blua"
    ::msgcat::mcset eo "Cancel" "Rezignu"
    ::msgcat::mcset eo "&Cancel" "&Rezignu"
    ::msgcat::mcset eo "Cannot change to the directory \"%1\$s\".\nPermission denied." "Neeble \u0109angi al dosierulon \"%1\$s\".\nVi ne rajtas tion."
    ::msgcat::mcset eo "Cannot change to the directory \"%1\$s\".\nPermission denied." "Neeble ĉangi al dosierulon \"%1\$s\".\nVi ne rajtas tion."
    ::msgcat::mcset eo "Choose Directory" "Elektu Dosierujo"
    ::msgcat::mcset eo "Cl&ear" "&Klaru"
    ::msgcat::mcset eo "&Clear Console" "&Klaru konzolon"
    ::msgcat::mcset eo "Color" "Farbo"
    ::msgcat::mcset eo "Console" "Konzolo"
    ::msgcat::mcset eo "&Copy" "&Kopiu"
    ::msgcat::mcset eo "Cu&t" "&Enpo\u015digu"
    ::msgcat::mcset eo "Cu&t" "&Enpoŝigu"
    ::msgcat::mcset eo "&Delete" "&Forprenu"
    ::msgcat::mcset eo "Details >>" "Detaloj >>"
    ::msgcat::mcset eo "Directory \"%1\$s\" does not exist." "La dosierujo \"%1\$s\" ne ekzistas."
    ::msgcat::mcset eo "&Directory:" "&Dosierujo:"
    ::msgcat::mcset eo "&Edit" "&Redaktu"
    ::msgcat::mcset eo "Error: %1\$s" "Eraro: %1\$s"
    ::msgcat::mcset eo "E&xit" "&Eliru"
    ::msgcat::mcset eo "&File" "&Dosiero"
    ::msgcat::mcset eo "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "La dosiero \"%1\$s\" jam ekzistas.\n\u0108u vi volas anstata\u00fbigi la dosieron?"
    ::msgcat::mcset eo "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "La dosiero \"%1\$s\" jam ekzistas.\nĈu vi volas anstataûigi la dosieron?"
    ::msgcat::mcset eo "File \"%1\$s\" already exists.\n\n" "La dosiero \"%1\$s\" jam egzistas. \n\n"
    ::msgcat::mcset eo "File \"%1\$s\" does not exist." "La dosierp \"%1\$s\" ne estas."
    ::msgcat::mcset eo "File &name:" "Dosiero&nomo:"
    ::msgcat::mcset eo "File &names:" "Dosiero&nomoj:"
    ::msgcat::mcset eo "Files of &type:" "Dosieroj de &Typo:"
    ::msgcat::mcset eo "Fi&les:" "Do&sieroj:"
    ::msgcat::mcset eo "&Filter" "&Filtrilo"
    ::msgcat::mcset eo "Fil&ter:" "&Filtrilo:"
    ::msgcat::mcset eo "&Green" "&Verda"
    ::msgcat::mcset eo "&Help" "&Helpu"
    ::msgcat::mcset eo "Hi" "Saluton"
    ::msgcat::mcset eo "&Hide Console" "&Ka\u015du konzolon"
    ::msgcat::mcset eo "&Hide Console" "&Kaŝu konzolon"
    ::msgcat::mcset eo "&Ignore" "&Ignoru"
    ::msgcat::mcset eo "Invalid file name \"%1\$s\"." "Malvalida dosieronomo \"%1\$s\"."
    ::msgcat::mcset eo "Log Files" "Protokolo"
    ::msgcat::mcset eo "&No" "&Ne"
    ::msgcat::mcset eo "&OK"
    ::msgcat::mcset eo "OK"
    ::msgcat::mcset eo "Ok"
    ::msgcat::mcset eo "Open" "Malfermu"
    ::msgcat::mcset eo "&Open" "&Malfermu"
    ::msgcat::mcset eo "Open Multiple Files" "Melfermu multan dosierojn"
    ::msgcat::mcset eo "P&aste" "&Elpo\u015digi"
    ::msgcat::mcset eo "P&aste" "&Elpoŝigi"
    ::msgcat::mcset eo "&Quit" "&Finigu"
    ::msgcat::mcset eo "&Red" "&Rosa"
    ::msgcat::mcset eo "Replace existing file?" "\u0108u anstata\u00fbu ekzistantan dosieron?"
    ::msgcat::mcset eo "Replace existing file?" "Ĉu anstataûu ekzistantan dosieron?"
    ::msgcat::mcset eo "&Retry" "&Ripetu"
    ::msgcat::mcset eo "&Save" "&Savu"
    ::msgcat::mcset eo "Save As" "Savu kiel"
    ::msgcat::mcset eo "Save To Log" "Savu en protokolon"
    ::msgcat::mcset eo "Select Log File" "Elektu prokolodosieron"
    ::msgcat::mcset eo "Select a file to source" "Elektu dosieron por interpreti"
    ::msgcat::mcset eo "&Selection:" "&Elekto:"
    ::msgcat::mcset eo "Skip Messages" "transsaltu pluajn mesa\u011dojn"
    ::msgcat::mcset eo "Skip Messages" "transsaltu pluajn mesaĝojn"
    ::msgcat::mcset eo "&Source..." "&Fontoprogramo..."
    ::msgcat::mcset eo "Tcl Scripts" "Tcl-skriptoj"
    ::msgcat::mcset eo "Tcl for Windows" "Tcl por vindoso"
    ::msgcat::mcset eo "Text Files" "Tekstodosierojn"
    ::msgcat::mcset eo "&Yes" "&Jes"
    ::msgcat::mcset eo "abort" "\u0109esigo"
    ::msgcat::mcset eo "abort" "ĉesigo"
    ::msgcat::mcset eo "blue" "blua"
    ::msgcat::mcset eo "cancel" "rezignu"
    ::msgcat::mcset eo "extension" "ekspansio"
    ::msgcat::mcset eo "extensions" "ekspansioj"
    ::msgcat::mcset eo "green" "verda"
    ::msgcat::mcset eo "ignore" "ignorieren"
    ::msgcat::mcset eo "red" "ru\u011da"
    ::msgcat::mcset eo "red" "ruĝa"
    ::msgcat::mcset eo "retry" "ripetu"
    ::msgcat::mcset eo "yes" "jes"
}
Changes to library/msgs/es.msg.
1
2
3
4
5

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

26
27
28
29
30
31
32
33
34
35
36
37
38
39

40
41
42
43
44
45
46
47

48
49
50
51

52
53
54
55
56
57
58

59
60
61
62
63
64

65
66
67
68

69
70
71
72
73
74
75

76
1
2
3
4

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

25
26
27
28
29
30
31
32
33
34
35
36
37
38

39
40
41
42
43
44
45
46

47
48
49
50

51
52
53
54
55
56
57

58
59
60
61
62
63

64
65
66
67

68
69
70
71
72
73
74

75
76




-
+



















-
+













-
+







-
+



-
+






-
+





-
+



-
+






-
+

namespace eval ::tk {
    ::msgcat::mcset es "&Abort" "&Abortar"
    ::msgcat::mcset es "&About..." "&Acerca de ..."
    ::msgcat::mcset es "All Files" "Todos los archivos"
    ::msgcat::mcset es "Application Error" "Error de la aplicaci\u00f3n"
    ::msgcat::mcset es "Application Error" "Error de la aplicación"
    ::msgcat::mcset es "&Blue" "&Azul"
    ::msgcat::mcset es "Cancel" "Cancelar"
    ::msgcat::mcset es "&Cancel" "&Cancelar"
    ::msgcat::mcset es "Cannot change to the directory \"%1\$s\".\nPermission denied." "No es posible acceder al directorio \"%1\$s\".\nPermiso denegado."
    ::msgcat::mcset es "Choose Directory" "Elegir directorio"
    ::msgcat::mcset es "Cl&ear" "&Borrar"
    ::msgcat::mcset es "&Clear Console" "&Borrar consola"
    ::msgcat::mcset es "Color"
    ::msgcat::mcset es "Console" "Consola"
    ::msgcat::mcset es "&Copy" "&Copiar"
    ::msgcat::mcset es "Cu&t" "Cor&tar"
    ::msgcat::mcset es "&Delete" "&Borrar"
    ::msgcat::mcset es "Details >>" "Detalles >>"
    ::msgcat::mcset es "Directory \"%1\$s\" does not exist." "El directorio \"%1\$s\" no existe."
    ::msgcat::mcset es "&Directory:" "&Directorio:"
    ::msgcat::mcset es "&Edit" "&Editar"
    ::msgcat::mcset es "Error: %1\$s"
    ::msgcat::mcset es "E&xit" "Salir"
    ::msgcat::mcset es "&File" "&Archivo"
    ::msgcat::mcset es "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "El archivo \"%1\$s\" ya existe.\n\u00bfDesea sobreescribirlo?"
    ::msgcat::mcset es "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "El archivo \"%1\$s\" ya existe.\n¿Desea sobreescribirlo?"
    ::msgcat::mcset es "File \"%1\$s\" already exists.\n\n" "El archivo \"%1\$s\" ya existe.\n\n"
    ::msgcat::mcset es "File \"%1\$s\" does not exist." "El archivo \"%1\$s\" no existe."
    ::msgcat::mcset es "File &name:" "&Nombre de archivo:"
    ::msgcat::mcset es "File &names:" "&Nombres de archivo:"
    ::msgcat::mcset es "Files of &type:" "Archivos de &tipo:"
    ::msgcat::mcset es "Fi&les:" "&Archivos:"
    ::msgcat::mcset es "&Filter" "&Filtro"
    ::msgcat::mcset es "Fil&ter:" "Fil&tro:"
    ::msgcat::mcset es "&Green" "&Verde"
    ::msgcat::mcset es "&Help" "&Ayuda"
    ::msgcat::mcset es "Hi"  "Hola"
    ::msgcat::mcset es "&Hide Console" "&Esconder la consola"
    ::msgcat::mcset es "&Ignore" "&Ignorar"
    ::msgcat::mcset es "Invalid file name \"%1\$s\"." "Nombre de archivo inv\u00e1lido \"%1\$s\"."
    ::msgcat::mcset es "Invalid file name \"%1\$s\"." "Nombre de archivo inválido \"%1\$s\"."
    ::msgcat::mcset es "Log Files"  "Ficheros de traza"
    ::msgcat::mcset es "&No"
    ::msgcat::mcset es "&OK"
    ::msgcat::mcset es "OK"
    ::msgcat::mcset es "Ok"
    ::msgcat::mcset es "Open" "Abrir"
    ::msgcat::mcset es "&Open" "&Abrir"
    ::msgcat::mcset es "Open Multiple Files" "Abrir m\u00faltiples archivos"
    ::msgcat::mcset es "Open Multiple Files" "Abrir múltiples archivos"
    ::msgcat::mcset es "P&aste" "Peg&ar"
    ::msgcat::mcset es "&Quit" "&Abandonar"
    ::msgcat::mcset es "&Red" "&Rojo"
    ::msgcat::mcset es "Replace existing file?" "\u00bfReemplazar el archivo existente?"
    ::msgcat::mcset es "Replace existing file?" "¿Reemplazar el archivo existente?"
    ::msgcat::mcset es "&Retry" "&Reintentar"
    ::msgcat::mcset es "&Save" "&Guardar"
    ::msgcat::mcset es "Save As" "Guardar como"
    ::msgcat::mcset es "Save To Log" "Guardar al archivo de traza"
    ::msgcat::mcset es "Select Log File"  "Elegir un archivo de traza"
    ::msgcat::mcset es "Select a file to source" "Seleccionar un archivo a evaluar"
    ::msgcat::mcset es "&Selection:" "&Selecci\u00f3n:"
    ::msgcat::mcset es "&Selection:" "&Selección:"
    ::msgcat::mcset es "Skip Messages" "Omitir los mensajes"
    ::msgcat::mcset es "&Source..." "E&valuar..."
    ::msgcat::mcset es "Tcl Scripts" "Scripts Tcl"
    ::msgcat::mcset es "Tcl for Windows" "Tcl para Windows"
    ::msgcat::mcset es "Text Files" "Archivos de texto"
    ::msgcat::mcset es "&Yes" "&S\u00ed"
    ::msgcat::mcset es "&Yes" "&Sí"
    ::msgcat::mcset es "abort" "abortar"
    ::msgcat::mcset es "blue" "azul"
    ::msgcat::mcset es "cancel" "cancelar"
    ::msgcat::mcset es "extension"  "extensi\u00f3n"
    ::msgcat::mcset es "extension"  "extensión"
    ::msgcat::mcset es "extensions" "extensiones"
    ::msgcat::mcset es "green" "verde"
    ::msgcat::mcset es "ignore" "ignorar"
    ::msgcat::mcset es "ok"
    ::msgcat::mcset es "red" "rojo"
    ::msgcat::mcset es "retry" "reintentar"
    ::msgcat::mcset es "yes" "s\u00ed"
    ::msgcat::mcset es "yes" "sí"
}
Changes to library/msgs/fr.msg.
1
2
3

4
5
6
7
8
9
10


11
12
13
14
15
16
17
18
19



20
21
22
23


24
25
26
27
28
29
30
1
2

3
4
5
6
7
8


9
10
11
12
13
14
15
16



17
18
19
20
21


22
23
24
25
26
27
28
29
30


-
+





-
-
+
+






-
-
-
+
+
+


-
-
+
+







namespace eval ::tk {
    ::msgcat::mcset fr "&Abort" "&Annuler"
    ::msgcat::mcset fr "About..." "\u00c0 propos..."
    ::msgcat::mcset fr "About..." "À propos..."
    ::msgcat::mcset fr "All Files" "Tous les fichiers"
    ::msgcat::mcset fr "Application Error" "Erreur d'application"
    ::msgcat::mcset fr "&Blue" "&Bleu"
    ::msgcat::mcset fr "Cancel" "Annuler"
    ::msgcat::mcset fr "&Cancel" "&Annuler"
    ::msgcat::mcset fr "Cannot change to the directory \"%1\$s\".\nPermission denied." "Impossible d'acc\u00e9der au r\u00e9pertoire \"%1\$s\".\nPermission refus\u00e9e."
    ::msgcat::mcset fr "Choose Directory" "Choisir r\u00e9pertoire"
    ::msgcat::mcset fr "Cannot change to the directory \"%1\$s\".\nPermission denied." "Impossible d'accéder au répertoire \"%1\$s\".\nPermission refusée."
    ::msgcat::mcset fr "Choose Directory" "Choisir répertoire"
    ::msgcat::mcset fr "Cl&ear" "Effacer"
    ::msgcat::mcset fr "Color" "Couleur"
    ::msgcat::mcset fr "Console"
    ::msgcat::mcset fr "Copy" "Copier"
    ::msgcat::mcset fr "Cu&t" "Couper"
    ::msgcat::mcset fr "Delete" "Effacer"
    ::msgcat::mcset fr "Details >>" "D\u00e9tails >>"
    ::msgcat::mcset fr "Directory \"%1\$s\" does not exist." "Le r\u00e9pertoire \"%1\$s\" n'existe pas."
    ::msgcat::mcset fr "&Directory:" "&R\u00e9pertoire:"
    ::msgcat::mcset fr "Details >>" "Détails >>"
    ::msgcat::mcset fr "Directory \"%1\$s\" does not exist." "Le répertoire \"%1\$s\" n'existe pas."
    ::msgcat::mcset fr "&Directory:" "&Répertoire:"
    ::msgcat::mcset fr "Error: %1\$s" "Erreur: %1\$s"
    ::msgcat::mcset fr "E&xit" "Quitter"
    ::msgcat::mcset fr "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "Le fichier \"%1\$s\" existe d\u00e9j\u00e0.\nVoulez-vous l'\u00e9craser?"
    ::msgcat::mcset fr "File \"%1\$s\" already exists.\n\n" "Le fichier \"%1\$s\" existe d\u00e9j\u00e0.\n\n"
    ::msgcat::mcset fr "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "Le fichier \"%1\$s\" existe déjà.\nVoulez-vous l'écraser?"
    ::msgcat::mcset fr "File \"%1\$s\" already exists.\n\n" "Le fichier \"%1\$s\" existe déjà.\n\n"
    ::msgcat::mcset fr "File \"%1\$s\" does not exist." "Le fichier \"%1\$s\" n'existe pas."
    ::msgcat::mcset fr "File &name:" "&Nom de fichier:"
    ::msgcat::mcset fr "File &names:" "&Noms de fichiers:"
    ::msgcat::mcset fr "Files of &type:" "&Type de fichiers:"
    ::msgcat::mcset fr "Fi&les:" "Fich&iers:"
    ::msgcat::mcset fr "&Filter" "&Filtre"
    ::msgcat::mcset fr "Fil&ter:" "Fil&tre:"
41
42
43
44
45
46
47
48

49
50
51
52
53
54


55
56

57
58
59
60
61
62
63
64
65
66
67
68
69
70

71
72
41
42
43
44
45
46
47

48
49
50
51
52


53
54
55

56
57
58
59
60
61
62
63
64
65
66
67
68
69

70
71
72







-
+




-
-
+
+

-
+













-
+


    ::msgcat::mcset fr "Open" "Ouvrir"
    ::msgcat::mcset fr "&Open" "&Ouvrir"
    ::msgcat::mcset fr "Open Multiple Files" "Ouvrir plusieurs fichiers"
    ::msgcat::mcset fr "P&aste" "Coller"
    ::msgcat::mcset fr "&Quit" "&Quitter"
    ::msgcat::mcset fr "&Red" "&Rouge"
    ::msgcat::mcset fr "Replace existing file?" "Remplacer le fichier existant?"
    ::msgcat::mcset fr "&Retry" "&R\u00e9-essayer"
    ::msgcat::mcset fr "&Retry" "&Ré-essayer"
    ::msgcat::mcset fr "&Save" "&Sauvegarder"
    ::msgcat::mcset fr "Save As" "Sauvegarder sous"
    ::msgcat::mcset fr "Save To Log" "Sauvegarde au fichier de trace"
    ::msgcat::mcset fr "Select Log File" "Choisir un fichier de trace"
    ::msgcat::mcset fr "Select a file to source" "Choisir un fichier \u00e0 \u00e9valuer"
    ::msgcat::mcset fr "&Selection:" "&S\u00e9lection:"
    ::msgcat::mcset fr "Select a file to source" "Choisir un fichier à évaluer"
    ::msgcat::mcset fr "&Selection:" "&Sélection:"
    ::msgcat::mcset fr "Skip Messages" "Omettre les messages"
    ::msgcat::mcset fr "&Source..." "\u00c9valuer..."
    ::msgcat::mcset fr "&Source..." "Évaluer..."
    ::msgcat::mcset fr "Tcl Scripts" "Scripts Tcl"
    ::msgcat::mcset fr "Tcl for Windows" "Tcl pour Windows"
    ::msgcat::mcset fr "Text Files" "Fichiers texte"
    ::msgcat::mcset fr "&Yes" "&Oui"
    ::msgcat::mcset fr "abort" "abandonner"
    ::msgcat::mcset fr "blue" "bleu"
    ::msgcat::mcset fr "cancel" "annuler"
    ::msgcat::mcset fr "extension"
    ::msgcat::mcset fr "extensions"
    ::msgcat::mcset fr "green" "vert"
    ::msgcat::mcset fr "ignore" "ignorer"
    ::msgcat::mcset fr "ok"
    ::msgcat::mcset fr "red" "rouge"
    ::msgcat::mcset fr "retry" "r\u00e9essayer"
    ::msgcat::mcset fr "retry" "réessayer"
    ::msgcat::mcset fr "yes" "oui"
}
Changes to library/msgs/hu.msg.
1
2
3
4
5
6
7
8
9
10
11
12
13












14
15
16
17
18
19
20






21
22
23
24
25
26
27
28
29
30
31
32
33
34












35
36
37
38
39
40





41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62


















63
64
65

66
67
68
69
70
71
72






73
74
75
76


77
78
1












2
3
4
5
6
7
8
9
10
11
12
13
14






15
16
17
18
19
20
21
22












23
24
25
26
27
28
29
30
31
32
33
34
35





36
37
38
39
40
41
42
43
44


















45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

65
66






67
68
69
70
71
72
73
74


75
76
77
78

-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+


-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
+
+
+
+
+




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
+

-
-
-
-
-
-
+
+
+
+
+
+


-
-
+
+


namespace eval ::tk {
    ::msgcat::mcset hu "&Abort" "&Megszak\u00edt\u00e1s"
    ::msgcat::mcset hu "&About..." "N\u00e9vjegy..."
    ::msgcat::mcset hu "All Files" "Minden f\u00e1jl"
    ::msgcat::mcset hu "Application Error" "Alkalmaz\u00e1s hiba"
    ::msgcat::mcset hu "&Blue" "&K\u00e9k"
    ::msgcat::mcset hu "Cancel" "M\u00e9gsem"
    ::msgcat::mcset hu "&Cancel" "M\u00e9g&sem"
    ::msgcat::mcset hu "Cannot change to the directory \"%1\$s\".\nPermission denied." "A k\u00f6nyvt\u00e1rv\u00e1lt\u00e1s nem siker\u00fclt: \"%1\$s\".\nHozz\u00e1f\u00e9r\u00e9s megtagadva."
    ::msgcat::mcset hu "Choose Directory" "K\u00f6nyvt\u00e1r kiv\u00e1laszt\u00e1sa"
    ::msgcat::mcset hu "Cl&ear" "T\u00f6rl\u00e9s"
    ::msgcat::mcset hu "&Clear Console" "&T\u00f6rl\u00e9s Konzol"
    ::msgcat::mcset hu "Color" "Sz\u00edn"
    ::msgcat::mcset hu "&Abort" "&Megszakítás"
    ::msgcat::mcset hu "&About..." "Névjegy..."
    ::msgcat::mcset hu "All Files" "Minden fájl"
    ::msgcat::mcset hu "Application Error" "Alkalmazás hiba"
    ::msgcat::mcset hu "&Blue" "&Kék"
    ::msgcat::mcset hu "Cancel" "Mégsem"
    ::msgcat::mcset hu "&Cancel" "Még&sem"
    ::msgcat::mcset hu "Cannot change to the directory \"%1\$s\".\nPermission denied." "A könyvtárváltás nem sikerült: \"%1\$s\".\nHozzáférés megtagadva."
    ::msgcat::mcset hu "Choose Directory" "Könyvtár kiválasztása"
    ::msgcat::mcset hu "Cl&ear" "Törlés"
    ::msgcat::mcset hu "&Clear Console" "&Törlés Konzol"
    ::msgcat::mcset hu "Color" "Szín"
    ::msgcat::mcset hu "Console" "Konzol"
    ::msgcat::mcset hu "&Copy" "&M\u00e1sol\u00e1s"
    ::msgcat::mcset hu "Cu&t" "&Kiv\u00e1g\u00e1s"
    ::msgcat::mcset hu "&Delete" "&T\u00f6rl\u00e9s"
    ::msgcat::mcset hu "Details >>" "R\u00e9szletek >>"
    ::msgcat::mcset hu "Directory \"%1\$s\" does not exist." "\"%1\$s\" k\u00f6nyvt\u00e1r nem l\u00e9tezik."
    ::msgcat::mcset hu "&Directory:" "&K\u00f6nyvt\u00e1r:"
    ::msgcat::mcset hu "&Copy" "&Másolás"
    ::msgcat::mcset hu "Cu&t" "&Kivágás"
    ::msgcat::mcset hu "&Delete" "&Törlés"
    ::msgcat::mcset hu "Details >>" "Részletek >>"
    ::msgcat::mcset hu "Directory \"%1\$s\" does not exist." "\"%1\$s\" könyvtár nem létezik."
    ::msgcat::mcset hu "&Directory:" "&Könyvtár:"
    #::msgcat::mcset hu "&Edit"
    ::msgcat::mcset hu "Error: %1\$s" "Hiba: %1\$s"
    ::msgcat::mcset hu "E&xit" "Kil\u00e9p\u00e9s"
    ::msgcat::mcset hu "&File" "&F\u00e1jl"
    ::msgcat::mcset hu "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "\"%1\$s\" f\u00e1jl m\u00e1r l\u00e9tezik.\nFel\u00fcl\u00edrjam?"
    ::msgcat::mcset hu "File \"%1\$s\" already exists.\n\n" "\"%1\$s\" f\u00e1jl m\u00e1r l\u00e9tezik.\n\n"
    ::msgcat::mcset hu "File \"%1\$s\" does not exist." "\"%1\$s\" f\u00e1jl nem l\u00e9tezik."
    ::msgcat::mcset hu "File &name:" "F\u00e1jl &neve:"
    ::msgcat::mcset hu "File &names:" "F\u00e1jlok &nevei:"
    ::msgcat::mcset hu "Files of &type:" "F\u00e1jlok &t\u00edpusa:"
    ::msgcat::mcset hu "Fi&les:" "F\u00e1j&lok:"
    ::msgcat::mcset hu "&Filter" "&Sz\u0171r\u0151"
    ::msgcat::mcset hu "Fil&ter:" "S&z\u0171r\u0151:"
    ::msgcat::mcset hu "&Green" "&Z\u00f6ld"
    ::msgcat::mcset hu "E&xit" "Kilépés"
    ::msgcat::mcset hu "&File" "&Fájl"
    ::msgcat::mcset hu "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "\"%1\$s\" fájl már létezik.\nFelülírjam?"
    ::msgcat::mcset hu "File \"%1\$s\" already exists.\n\n" "\"%1\$s\" fájl már létezik.\n\n"
    ::msgcat::mcset hu "File \"%1\$s\" does not exist." "\"%1\$s\" fájl nem létezik."
    ::msgcat::mcset hu "File &name:" "Fájl &neve:"
    ::msgcat::mcset hu "File &names:" "Fájlok &nevei:"
    ::msgcat::mcset hu "Files of &type:" "Fájlok &típusa:"
    ::msgcat::mcset hu "Fi&les:" "Fáj&lok:"
    ::msgcat::mcset hu "&Filter" "&Szűrő"
    ::msgcat::mcset hu "Fil&ter:" "S&zűrő:"
    ::msgcat::mcset hu "&Green" "&Zöld"
    #::msgcat::mcset hu "&Help"
    ::msgcat::mcset hu "Hi" "\u00dcdv"
    ::msgcat::mcset hu "&Hide Console" "Konzol &elrejt\u00e9se"
    ::msgcat::mcset hu "&Ignore" "K&ihagy\u00e1s"
    ::msgcat::mcset hu "Invalid file name \"%1\$s\"." "\u00c9rv\u00e9nytelen f\u00e1jln\u00e9v: \"%1\$s\"."
    ::msgcat::mcset hu "Log Files" "Log f\u00e1jlok"
    ::msgcat::mcset hu "Hi" "Üdv"
    ::msgcat::mcset hu "&Hide Console" "Konzol &elrejtése"
    ::msgcat::mcset hu "&Ignore" "K&ihagyás"
    ::msgcat::mcset hu "Invalid file name \"%1\$s\"." "Érvénytelen fájlnév: \"%1\$s\"."
    ::msgcat::mcset hu "Log Files" "Log fájlok"
    ::msgcat::mcset hu "&No" "&Nem"
    ::msgcat::mcset hu "&OK"
    ::msgcat::mcset hu "OK"
    ::msgcat::mcset hu "Ok"
    ::msgcat::mcset hu "Open" "Megnyit\u00e1s"
    ::msgcat::mcset hu "&Open" "&Megnyit\u00e1s"
    ::msgcat::mcset hu "Open Multiple Files" "T\u00f6bb f\u00e1jl megnyit\u00e1sa"
    ::msgcat::mcset hu "P&aste" "&Beilleszt\u00e9s"
    ::msgcat::mcset hu "&Quit" "&Kil\u00e9p\u00e9s"
    ::msgcat::mcset hu "&Red" "&V\u00f6r\u00f6s"
    ::msgcat::mcset hu "Replace existing file?" "Megl\u00e9v\u0151 f\u00e1jl cser\u00e9je?"
    ::msgcat::mcset hu "&Retry" "\u00daj&ra"
    ::msgcat::mcset hu "&Save" "&Ment\u00e9s"
    ::msgcat::mcset hu "Save As" "Ment\u00e9s m\u00e1sk\u00e9nt"
    ::msgcat::mcset hu "Save To Log" "Ment\u00e9s log f\u00e1jlba"
    ::msgcat::mcset hu "Select Log File" "Log f\u00e1jl kiv\u00e1laszt\u00e1sa"
    ::msgcat::mcset hu "Select a file to source" "Forr\u00e1sf\u00e1jl kiv\u00e1laszt\u00e1sa"
    ::msgcat::mcset hu "&Selection:" "&Kijel\u00f6l\u00e9s:"
    ::msgcat::mcset hu "Show &Hidden Directories" "&Rejtett k\u00f6nyvt\u00e1rak megjelen\u00edt\u00e9se"
    ::msgcat::mcset hu "Show &Hidden Files and Directories" "&Rejtett f\u00e1jlok \u00e9s k\u00f6nyvt\u00e1rak megjelen\u00edt\u00e9se"
    ::msgcat::mcset hu "Skip Messages" "\u00dczenetek kihagy\u00e1sa"
    ::msgcat::mcset hu "&Source..." "&Forr\u00e1s..."
    ::msgcat::mcset hu "Open" "Megnyitás"
    ::msgcat::mcset hu "&Open" "&Megnyitás"
    ::msgcat::mcset hu "Open Multiple Files" "Több fájl megnyitása"
    ::msgcat::mcset hu "P&aste" "&Beillesztés"
    ::msgcat::mcset hu "&Quit" "&Kilépés"
    ::msgcat::mcset hu "&Red" "&Vörös"
    ::msgcat::mcset hu "Replace existing file?" "Meglévő fájl cseréje?"
    ::msgcat::mcset hu "&Retry" "Új&ra"
    ::msgcat::mcset hu "&Save" "&Mentés"
    ::msgcat::mcset hu "Save As" "Mentés másként"
    ::msgcat::mcset hu "Save To Log" "Mentés log fájlba"
    ::msgcat::mcset hu "Select Log File" "Log fájl kiválasztása"
    ::msgcat::mcset hu "Select a file to source" "Forrásfájl kiválasztása"
    ::msgcat::mcset hu "&Selection:" "&Kijelölés:"
    ::msgcat::mcset hu "Show &Hidden Directories" "&Rejtett könyvtárak megjelenítése"
    ::msgcat::mcset hu "Show &Hidden Files and Directories" "&Rejtett fájlok és könyvtárak megjelenítése"
    ::msgcat::mcset hu "Skip Messages" "Üzenetek kihagyása"
    ::msgcat::mcset hu "&Source..." "&Forrás..."
    ::msgcat::mcset hu "Tcl Scripts" "Tcl scriptek"
    ::msgcat::mcset hu "Tcl for Windows" "Tcl Windows-hoz"
    ::msgcat::mcset hu "Text Files" "Sz\u00f6vegf\u00e1jlok"
    ::msgcat::mcset hu "Text Files" "Szövegfájlok"
    ::msgcat::mcset hu "&Yes" "&Igen"
    ::msgcat::mcset hu "abort" "megszak\u00edt\u00e1s"
    ::msgcat::mcset hu "blue" "k\u00e9k"
    ::msgcat::mcset hu "cancel" "m\u00e9gsem"
    ::msgcat::mcset hu "extension" "kiterjeszt\u00e9s"
    ::msgcat::mcset hu "extensions" "kiterjeszt\u00e9sek"
    ::msgcat::mcset hu "green" "z\u00f6ld"
    ::msgcat::mcset hu "abort" "megszakítás"
    ::msgcat::mcset hu "blue" "kék"
    ::msgcat::mcset hu "cancel" "mégsem"
    ::msgcat::mcset hu "extension" "kiterjesztés"
    ::msgcat::mcset hu "extensions" "kiterjesztések"
    ::msgcat::mcset hu "green" "zöld"
    ::msgcat::mcset hu "ignore" "ignorer"
    ::msgcat::mcset hu "ok"
    ::msgcat::mcset hu "red" "v\u00f6r\u00f6s"
    ::msgcat::mcset hu "retry" "\u00fajra"
    ::msgcat::mcset hu "red" "vörös"
    ::msgcat::mcset hu "retry" "újra"
    ::msgcat::mcset hu "yes" "igen"
}
Changes to library/msgs/it.msg.
16
17
18
19
20
21
22
23
24


25
26
27
28
29
30
31
16
17
18
19
20
21
22


23
24
25
26
27
28
29
30
31







-
-
+
+







    ::msgcat::mcset it "Cu&t" "Taglia"
    ::msgcat::mcset it "Delete" "Cancella"
    ::msgcat::mcset it "Details >>" "Dettagli >>"
    ::msgcat::mcset it "Directory \"%1\$s\" does not exist." "La directory \"%1\$s\" non esiste."
    ::msgcat::mcset it "&Directory:"
    ::msgcat::mcset it "Error: %1\$s" "Errore: %1\$s"
    ::msgcat::mcset it "E&xit" "Esci"
    ::msgcat::mcset it "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "Il file \"%1\$s\" esiste gi\u00e0.\nVuoi sovrascriverlo?"
    ::msgcat::mcset it "File \"%1\$s\" already exists.\n\n" "Il file \"%1\$s\" esiste gi\u00e0.\n\n"
    ::msgcat::mcset it "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "Il file \"%1\$s\" esiste già.\nVuoi sovrascriverlo?"
    ::msgcat::mcset it "File \"%1\$s\" already exists.\n\n" "Il file \"%1\$s\" esiste già.\n\n"
    ::msgcat::mcset it "File \"%1\$s\" does not exist." "Il file \"%1\$s\" non esiste."
    ::msgcat::mcset it "File &name:" "&Nome del file:"
    ::msgcat::mcset it "File &names:" "&Nomi dei file:"
    ::msgcat::mcset it "Files of &type:" "File di &tipo:"
    ::msgcat::mcset it "Fi&les:" "Fi&le:"
    ::msgcat::mcset it "&Filter" "&Filtro"
    ::msgcat::mcset it "Fil&ter:" "Fil&tro:"
54
55
56
57
58
59
60
61

62
63
64
65
66
67
68
69
70
71
72

73
54
55
56
57
58
59
60

61
62
63
64
65
66
67
68
69
70
71

72
73







-
+










-
+

    ::msgcat::mcset it "Select a file to source" "Scegli un file da eseguire"
    ::msgcat::mcset it "&Selection:" "&Selezione:"
    ::msgcat::mcset it "Skip Messages" "Salta i messaggi"
    ::msgcat::mcset it "Source..." "Esegui..."
    ::msgcat::mcset it "Tcl Scripts" "Script Tcl"
    ::msgcat::mcset it "Tcl for Windows" "Tcl per Windows"
    ::msgcat::mcset it "Text Files" "File di testo"
    ::msgcat::mcset it "&Yes" "&S\u00ec"
    ::msgcat::mcset it "&Yes" "&Sì"
    ::msgcat::mcset it "abort" "interrompi"
    ::msgcat::mcset it "blue" "blu"
    ::msgcat::mcset it "cancel" "annulla"
    ::msgcat::mcset it "extension" "estensione"
    ::msgcat::mcset it "extensions" "estensioni"
    ::msgcat::mcset it "green" "verde"
    ::msgcat::mcset it "ignore" "ignora"
    ::msgcat::mcset it "ok"
    ::msgcat::mcset it "red" "rosso"
    ::msgcat::mcset it "retry" "riprova"
    ::msgcat::mcset it "yes" "s\u00ec"
    ::msgcat::mcset it "yes" "sì"
}
Changes to library/msgs/nl.msg.
11
12
13
14
15
16
17
18

19
20
21
22
23
24
25
26
27

28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

44
45
46
47
48
49
50
11
12
13
14
15
16
17

18
19
20
21
22
23
24
25
26

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

43
44
45
46
47
48
49
50







-
+








-
+















-
+







    ::msgcat::mcset nl "&Cancel" "&Annuleren"
    ::msgcat::mcset nl "Cannot change to the directory \"%1\$s\".\nPermission denied." "Kan niet naar map \"%1\$s\" gaan.\nU heeft hiervoor geen toestemming."
    ::msgcat::mcset nl "Choose Directory" "Kies map"
    ::msgcat::mcset nl "Cl&ear" "Wissen"
    ::msgcat::mcset nl "&Clear Console" "&Wis Console"
    ::msgcat::mcset nl "Color" "Kleur"
    ::msgcat::mcset nl "Console"
    ::msgcat::mcset nl "&Copy" "Kopi\u00ebren"
    ::msgcat::mcset nl "&Copy" "Kopiëren"
    ::msgcat::mcset nl "Cu&t" "Knippen"
    ::msgcat::mcset nl "&Delete" "Wissen"
    ::msgcat::mcset nl "Details >>"
    ::msgcat::mcset nl "Directory \"%1\$s\" does not exist." "Map \"%1\$s\" bestaat niet."
    ::msgcat::mcset nl "&Directory:" "&Map:"
    ::msgcat::mcset nl "&Edit" "Bewerken"
    ::msgcat::mcset nl "Effects" "Effecten"
    ::msgcat::mcset nl "Error: %1\$s" "Fout: %1\$s"
    ::msgcat::mcset nl "E&xit" "Be\u00ebindigen"
    ::msgcat::mcset nl "E&xit" "Beëindigen"
    ::msgcat::mcset nl "&File" "Bestand"
    ::msgcat::mcset nl "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "Bestand \"%1\$s\" bestaat al.\nWilt u het overschrijven?"
    ::msgcat::mcset nl "File \"%1\$s\" already exists.\n\n" "Bestand \"%1\$s\" bestaat al.\n\n"
    ::msgcat::mcset nl "File \"%1\$s\" does not exist." "Bestand \"%1\$s\" bestaat niet."
    ::msgcat::mcset nl "File &name:" "Bestands&naam:"
    ::msgcat::mcset nl "File &names:" "Bestands&namen:"
    ::msgcat::mcset nl "Files of &type:" "Bestanden van het &type:"
    ::msgcat::mcset nl "Fi&les:" "&Bestanden:"
    ::msgcat::mcset nl "&Filter"
    ::msgcat::mcset nl "Fil&ter:"
    ::msgcat::mcset nl "Font"
    ::msgcat::mcset nl "&Font:"
    ::msgcat::mcset nl "Font st&yle:" "Font stijl:"
    ::msgcat::mcset nl "&Green" "&Groen"
    ::msgcat::mcset nl "&Help"
    ::msgcat::mcset nl "Hi" "H\u00e9"
    ::msgcat::mcset nl "Hi" "Hé"
    ::msgcat::mcset nl "&Hide Console" "Verberg Console"
    ::msgcat::mcset nl "&Ignore" "&Negeren"
    ::msgcat::mcset nl "Invalid file name \"%1\$s\"." "Ongeldige bestandsnaam \"%1\$s\"."
    ::msgcat::mcset nl "Italic" "Cursief"
    ::msgcat::mcset nl "Log Files" "Log Bestanden"
    ::msgcat::mcset nl "&No" "&Nee"
    ::msgcat::mcset nl "&OK"
Changes to library/msgs/pl.msg.
1
2
3
4
5

6
7
8
9
10
11
12

13
14
15


16
17
18
19
20
21


22
23
24
25
26
27


28
29
30


31
32
33

34
35
36
37
38
39
40
41
42
43
44

45
46

47
48
49
50
51
52
53
54
55



56
57

58
59
60
61
62



63
64
65
66
67
68

69
70
71
72
73
74





75
76
77
78

79
80
81
82
83
84
85
86
87
88
89

90
91
1
2
3
4

5
6
7
8
9
10
11

12
13


14
15
16
17
18
19


20
21
22
23
24
25


26
27
28


29
30
31
32

33
34
35
36
37
38
39
40
41
42
43

44
45

46
47
48
49
50
51
52



53
54
55
56

57
58
59



60
61
62
63
64
65
66
67

68
69





70
71
72
73
74
75
76
77

78
79
80
81
82
83
84
85
86
87
88

89
90
91




-
+






-
+

-
-
+
+




-
-
+
+




-
-
+
+

-
-
+
+


-
+










-
+

-
+






-
-
-
+
+
+

-
+


-
-
-
+
+
+





-
+

-
-
-
-
-
+
+
+
+
+



-
+










-
+


namespace eval ::tk {
    ::msgcat::mcset pl "&Abort" "&Przerwij"
    ::msgcat::mcset pl "&About..." "O programie..."
    ::msgcat::mcset pl "All Files" "Wszystkie pliki"
    ::msgcat::mcset pl "Application Error" "B\u0142\u0105d w programie"
    ::msgcat::mcset pl "Application Error" "Błąd w programie"
    ::msgcat::mcset pl "&Apply" "Zastosuj"
    ::msgcat::mcset pl "Bold" "Pogrubienie"
    ::msgcat::mcset pl "Bold Italic" "Pogrubiona kursywa"
    ::msgcat::mcset pl "&Blue" "&Niebieski"
    ::msgcat::mcset pl "Cancel" "Anuluj"
    ::msgcat::mcset pl "&Cancel" "&Anuluj"
    ::msgcat::mcset pl "Cannot change to the directory \"%1\$s\".\nPermission denied." "Nie mo\u017cna otworzy\u0107 katalogu \"%1\$s\".\nOdmowa dost\u0119pu."
    ::msgcat::mcset pl "Cannot change to the directory \"%1\$s\".\nPermission denied." "Nie można otworzyć katalogu \"%1\$s\".\nOdmowa dostępu."
    ::msgcat::mcset pl "Choose Directory" "Wybierz katalog"
    ::msgcat::mcset pl "Cl&ear" "&Wyczy\u015b\u0107"
    ::msgcat::mcset pl "&Clear Console" "&Wyczy\u015b\u0107 konsol\u0119"
    ::msgcat::mcset pl "Cl&ear" "&Wyczyść"
    ::msgcat::mcset pl "&Clear Console" "&Wyczyść konsolę"
    ::msgcat::mcset pl "Color" "Kolor"
    ::msgcat::mcset pl "Console" "Konsola"
    ::msgcat::mcset pl "&Copy" "&Kopiuj"
    ::msgcat::mcset pl "Cu&t" "&Wytnij"
    ::msgcat::mcset pl "&Delete" "&Usu\u0144"
    ::msgcat::mcset pl "Details >>" "Szczeg\u00f3\u0142y >>"
    ::msgcat::mcset pl "&Delete" "&Usuń"
    ::msgcat::mcset pl "Details >>" "Szczegóły >>"
    ::msgcat::mcset pl "Directory \"%1\$s\" does not exist." "Katalog \"%1\$s\" nie istnieje."
    ::msgcat::mcset pl "&Directory:" "&Katalog:"
    ::msgcat::mcset pl "&Edit" "&Edytuj"
    ::msgcat::mcset pl "Effects" "Efekty"
    ::msgcat::mcset pl "Error: %1\$s" "B\u0142\u0105d: %1\$s"
    ::msgcat::mcset pl "E&xit" "&Wyjd\u017a"
    ::msgcat::mcset pl "Error: %1\$s" "Błąd: %1\$s"
    ::msgcat::mcset pl "E&xit" "&Wyjdź"
    ::msgcat::mcset pl "&File" "&Plik"
    ::msgcat::mcset pl "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "Plik \"%1\$s\" ju\u017c istnieje.\nCzy chcesz go nadpisa\u0107?"
    ::msgcat::mcset pl "File \"%1\$s\" already exists.\n\n" "Plik \"%1\$s\" ju\u017c istnieje.\n\n"
    ::msgcat::mcset pl "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "Plik \"%1\$s\" już istnieje.\nCzy chcesz go nadpisać?"
    ::msgcat::mcset pl "File \"%1\$s\" already exists.\n\n" "Plik \"%1\$s\" już istnieje.\n\n"
    ::msgcat::mcset pl "File \"%1\$s\" does not exist." "Plik \"%1\$s\" nie istnieje."
    ::msgcat::mcset pl "File &name:" "Nazwa &pliku:"
    ::msgcat::mcset pl "File &names:" "Nazwy &plik\u00f3w:"
    ::msgcat::mcset pl "File &names:" "Nazwy &plików:"
    ::msgcat::mcset pl "Files of &type:" "Pliki &typu:"
    ::msgcat::mcset pl "Fi&les:" "Pli&ki:"
    ::msgcat::mcset pl "&Filter" "&Filtr"
    ::msgcat::mcset pl "Fil&ter:" "&Filtr:"
    ::msgcat::mcset pl "Font" "Czcionka"
    ::msgcat::mcset pl "&Font:" "Czcio&nka:"
    ::msgcat::mcset pl "Font st&yle:" "&Styl czcionki:"
    ::msgcat::mcset pl "&Green" "&Zielony"
    ::msgcat::mcset pl "&Help" "&Pomoc"
    ::msgcat::mcset pl "Hi" "Witaj"
    ::msgcat::mcset pl "&Hide Console" "&Ukryj konsol\u0119"
    ::msgcat::mcset pl "&Hide Console" "&Ukryj konsolę"
    ::msgcat::mcset pl "&Ignore" "&Ignoruj"
    ::msgcat::mcset pl "Invalid file name \"%1\$s\"." "Niew\u0142a\u015bciwa nazwa pliku \"%1\$s\"."
    ::msgcat::mcset pl "Invalid file name \"%1\$s\"." "Niewłaściwa nazwa pliku \"%1\$s\"."
    ::msgcat::mcset pl "Italic" "Kursywa"
    ::msgcat::mcset pl "Log Files" "Pliki dziennika"
    ::msgcat::mcset pl "&No" "&Nie"
    ::msgcat::mcset pl "&OK"
    ::msgcat::mcset pl "OK"
    ::msgcat::mcset pl "Ok"
    ::msgcat::mcset pl "Open" "Otw\u00f3rz"
    ::msgcat::mcset pl "&Open" "&Otw\u00f3rz"
    ::msgcat::mcset pl "Open Multiple Files" "Otw\u00f3rz wiele plik\u00f3w"
    ::msgcat::mcset pl "Open" "Otwórz"
    ::msgcat::mcset pl "&Open" "&Otwórz"
    ::msgcat::mcset pl "Open Multiple Files" "Otwórz wiele plików"
    ::msgcat::mcset pl "P&aste" "&Wklej"
    ::msgcat::mcset pl "&Quit" "&Zako\u0144cz"
    ::msgcat::mcset pl "&Quit" "&Zakończ"
    ::msgcat::mcset pl "&Red" "&Czerwony"
    ::msgcat::mcset pl "Regular" "Regularne"
    ::msgcat::mcset pl "Replace existing file?" "Czy zast\u0105pi\u0107 istniej\u0105cy plik?"
    ::msgcat::mcset pl "&Retry" "&Pon\u00f3w"
    ::msgcat::mcset pl "Sample" "Przyk\u0142ad"
    ::msgcat::mcset pl "Replace existing file?" "Czy zastąpić istniejący plik?"
    ::msgcat::mcset pl "&Retry" "&Ponów"
    ::msgcat::mcset pl "Sample" "Przykład"
    ::msgcat::mcset pl "&Save" "&Zapisz"
    ::msgcat::mcset pl "Save As" "Zapisz jako"
    ::msgcat::mcset pl "Save To Log" "Wpisz do dziennika"
    ::msgcat::mcset pl "Select Log File" "Wybierz plik dziennika"
    ::msgcat::mcset pl "Select a file to source" "Wybierz plik do wykonania"
    ::msgcat::mcset pl "&Selection:" "&Wyb\u00f3r:"
    ::msgcat::mcset pl "&Selection:" "&Wybór:"
    ::msgcat::mcset pl "&Size:" "&Rozmiar:"
    ::msgcat::mcset pl "Show &Hidden Directories" "Poka\u017c &ukryte katalogi"
    ::msgcat::mcset pl "Show &Hidden Files and Directories" "Poka\u017c &ukryte pliki i katalogi"
    ::msgcat::mcset pl "Skip Messages" "Pomi\u0144 pozosta\u0142e komunikaty"
    ::msgcat::mcset pl "&Source..." "&Kod \u017ar\u00f3d\u0142owy..."
    ::msgcat::mcset pl "Stri&keout" "&Przekre\u015blenie"
    ::msgcat::mcset pl "Show &Hidden Directories" "Pokaż &ukryte katalogi"
    ::msgcat::mcset pl "Show &Hidden Files and Directories" "Pokaż &ukryte pliki i katalogi"
    ::msgcat::mcset pl "Skip Messages" "Pomiń pozostałe komunikaty"
    ::msgcat::mcset pl "&Source..." "&Kod źródłowy..."
    ::msgcat::mcset pl "Stri&keout" "&Przekreślenie"
    ::msgcat::mcset pl "Tcl Scripts" "Skrypty Tcl"
    ::msgcat::mcset pl "Tcl for Windows" "Tcl dla Windows"
    ::msgcat::mcset pl "Text Files" "Pliki tekstowe"
    ::msgcat::mcset pl "&Underline" "Po&dkre\u015blenie"
    ::msgcat::mcset pl "&Underline" "Po&dkreślenie"
    ::msgcat::mcset pl "&Yes" "&Tak"
    ::msgcat::mcset pl "abort" "przerwij"
    ::msgcat::mcset pl "blue" "niebieski"
    ::msgcat::mcset pl "cancel" "anuluj"
    ::msgcat::mcset pl "extension" "rozszerzenie"
    ::msgcat::mcset pl "extensions" "rozszerzenia"
    ::msgcat::mcset pl "green" "zielony"
    ::msgcat::mcset pl "ignore" "ignoruj"
    ::msgcat::mcset pl "ok"
    ::msgcat::mcset pl "red" "czerwony"
    ::msgcat::mcset pl "retry" "pon\u00f3w"
    ::msgcat::mcset pl "retry" "ponów"
    ::msgcat::mcset pl "yes" "tak"
}
Changes to library/msgs/pt.msg.
1
2
3
4
5

6
7
8
9
10


11
12
13
14
15
16
17
18
19
20


21
22
23
24
25
26



27
28
29
30
31
32
33
34
35
36
37

38
39

40
41
42
43
44
45

46
47
48
49
50
51
52
53
54
55
56

57
58
59
60
61
62
63
64
65
66
67


68
69
70
71
72
73
74
1
2
3
4

5
6
7
8


9
10
11
12
13
14
15
16
17
18


19
20
21
22
23



24
25
26
27
28
29
30
31
32
33
34
35
36

37
38

39
40
41
42
43
44

45
46
47
48
49
50
51
52
53
54
55

56
57
58
59
60
61
62
63
64
65


66
67
68
69
70
71
72
73
74




-
+



-
-
+
+








-
-
+
+



-
-
-
+
+
+










-
+

-
+





-
+










-
+









-
-
+
+







namespace eval ::tk {
    ::msgcat::mcset pt "&Abort" "&Abortar"
    ::msgcat::mcset pt "About..." "Sobre ..."
    ::msgcat::mcset pt "All Files" "Todos os arquivos"
    ::msgcat::mcset pt "Application Error" "Erro de aplica\u00e7\u00e3o"
    ::msgcat::mcset pt "Application Error" "Erro de aplicação"
    ::msgcat::mcset pt "&Blue" "&Azul"
    ::msgcat::mcset pt "Cancel" "Cancelar"
    ::msgcat::mcset pt "&Cancel" "&Cancelar"
    ::msgcat::mcset pt "Cannot change to the directory \"%1\$s\".\nPermission denied." "N\u00e3o foi poss\u00edvel mudar para o diret\u00f3rio \"%1\$s\".\nPermiss\u00e3o negada."
    ::msgcat::mcset pt "Choose Directory" "Escolha um diret\u00f3rio"
    ::msgcat::mcset pt "Cannot change to the directory \"%1\$s\".\nPermission denied." "Não foi possível mudar para o diretório \"%1\$s\".\nPermissão negada."
    ::msgcat::mcset pt "Choose Directory" "Escolha um diretório"
    ::msgcat::mcset pt "Cl&ear" "Apagar"
    ::msgcat::mcset pt "&Clear Console" "Apagar Console"
    ::msgcat::mcset pt "Color" "Cor"
    ::msgcat::mcset pt "Console"
    ::msgcat::mcset pt "&Copy" "Copiar"
    ::msgcat::mcset pt "Cu&t" "Recortar"
    ::msgcat::mcset pt "&Delete" "Excluir"
    ::msgcat::mcset pt "Details >>" "Detalhes >>"
    ::msgcat::mcset pt "Directory \"%1\$s\" does not exist." "O diret\u00f3rio \"%1\$s\" n\u00e3o existe."
    ::msgcat::mcset pt "&Directory:" "&Diret\u00f3rio:"
    ::msgcat::mcset pt "Directory \"%1\$s\" does not exist." "O diretório \"%1\$s\" não existe."
    ::msgcat::mcset pt "&Directory:" "&Diretório:"
    ::msgcat::mcset pt "Error: %1\$s" "Erro: %1\$s"
    ::msgcat::mcset pt "E&xit" "Sair"
    ::msgcat::mcset pt "&File" "Arquivo"
    ::msgcat::mcset pt "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "O arquivo \"%1\$s\" j\u00e1 existe.\nDeseja sobrescreve-lo?"
    ::msgcat::mcset pt "File \"%1\$s\" already exists.\n\n" "O arquivo \"%1\$s\" j\u00e1 existe.\n\n"
    ::msgcat::mcset pt "File \"%1\$s\" does not exist." "Arquivo \"%1\$s\" n\u00e3o existe."
    ::msgcat::mcset pt "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "O arquivo \"%1\$s\" já existe.\nDeseja sobrescreve-lo?"
    ::msgcat::mcset pt "File \"%1\$s\" already exists.\n\n" "O arquivo \"%1\$s\" já existe.\n\n"
    ::msgcat::mcset pt "File \"%1\$s\" does not exist." "Arquivo \"%1\$s\" não existe."
    ::msgcat::mcset pt "File &name:" "&Nome do arquivo:"
    ::msgcat::mcset pt "File &names:" "&Nomes dos arquivos:"
    ::msgcat::mcset pt "Files of &type:" "Arquivos do &tipo:"
    ::msgcat::mcset pt "Fi&les:" "&Arquivos:"
    ::msgcat::mcset pt "&Filter" "&Filtro"
    ::msgcat::mcset pt "Fil&ter:" "Fil&tro:"
    ::msgcat::mcset pt "&Green" "&Verde"
    ::msgcat::mcset pt "Hi" "Oi"
    ::msgcat::mcset pt "&Hide Console" "Ocultar console"
    ::msgcat::mcset pt "&Ignore" "&Ignorar"
    ::msgcat::mcset pt "Invalid file name \"%1\$s\"." "O nome do arquivo \u00e9 inv\u00e1lido \"%1\$s\"."
    ::msgcat::mcset pt "Invalid file name \"%1\$s\"." "O nome do arquivo é inválido \"%1\$s\"."
    ::msgcat::mcset pt "Log Files" "Arquivos de log"
    ::msgcat::mcset pt "&No" "&N\u00e3o"
    ::msgcat::mcset pt "&No" "&Não"
    ::msgcat::mcset pt "&OK"
    ::msgcat::mcset pt "OK"
    ::msgcat::mcset pt "Ok"
    ::msgcat::mcset pt "Open" "Abrir"
    ::msgcat::mcset pt "&Open" "&Abrir"
    ::msgcat::mcset pt "Open Multiple Files" "Abrir m\u00faltiplos arquivos"
    ::msgcat::mcset pt "Open Multiple Files" "Abrir múltiplos arquivos"
    ::msgcat::mcset pt "P&aste" "Col&ar"
    ::msgcat::mcset pt "Quit" "Encerrar"
    ::msgcat::mcset pt "&Red" "&Vermelho"
    ::msgcat::mcset pt "Replace existing file?" "Substituir arquivo existente?"
    ::msgcat::mcset pt "&Retry" "Tenta&r novamente"
    ::msgcat::mcset pt "&Save" "&Salvar"
    ::msgcat::mcset pt "Save As" "Salvar como"
    ::msgcat::mcset pt "Save To Log" "Salvar arquivo de log"
    ::msgcat::mcset pt "Select Log File" "Selecionar arquivo de log"
    ::msgcat::mcset pt "Select a file to source" "Selecione um arquivo como fonte"
    ::msgcat::mcset pt "&Selection:" "&Sele\u00e7\u00e3o:"
    ::msgcat::mcset pt "&Selection:" "&Seleção:"
    ::msgcat::mcset pt "Skip Messages" "Omitir as mensagens"
    ::msgcat::mcset pt "&Source..." "&Fonte..."
    ::msgcat::mcset pt "Tcl Scripts" "Scripts Tcl"
    ::msgcat::mcset pt "Tcl for Windows" "Tcl para Windows"
    ::msgcat::mcset pt "Text Files" "Arquivos de texto"
    ::msgcat::mcset pt "&Yes" "&Sim"
    ::msgcat::mcset pt "abort" "abortar"
    ::msgcat::mcset pt "blue" "azul"
    ::msgcat::mcset pt "cancel" "cancelar"
    ::msgcat::mcset pt "extension" "extens\u00e3o"
    ::msgcat::mcset pt "extensions" "extens\u00f5es"
    ::msgcat::mcset pt "extension" "extensão"
    ::msgcat::mcset pt "extensions" "extensões"
    ::msgcat::mcset pt "green" "verde"
    ::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"
}
Changes to library/msgs/ru.msg.
1
2
3
4
5
6
7
8







9
10
11
12
13
14
15
16
17
18
19
20
21
22













23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
































56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73

















74
75
1







2
3
4
5
6
7
8
9













10
11
12
13
14
15
16
17
18
19
20
21
22
23
































24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

















57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75

-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


namespace eval ::tk {
    ::msgcat::mcset ru "&Abort" "&\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c"
    ::msgcat::mcset ru "&About..." "\u041f\u0440\u043e..."
    ::msgcat::mcset ru "All Files" "\u0412\u0441\u0435 \u0444\u0430\u0439\u043b\u044b"
    ::msgcat::mcset ru "Application Error" "\u041e\u0448\u0438\u0431\u043a\u0430 \u0432 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0435"
    ::msgcat::mcset ru "&Blue" " &\u0413\u043e\u043b\u0443\u0431\u043e\u0439"
    ::msgcat::mcset ru "Cancel" "\u041e\u0442&\u043c\u0435\u043d\u0430"
    ::msgcat::mcset ru "&Cancel" "\u041e\u0442&\u043c\u0435\u043d\u0430"
    ::msgcat::mcset ru "&Abort" "&Отменить"
    ::msgcat::mcset ru "&About..." "Про..."
    ::msgcat::mcset ru "All Files" "Все файлы"
    ::msgcat::mcset ru "Application Error" "Ошибка в программе"
    ::msgcat::mcset ru "&Blue" " &Голубой"
    ::msgcat::mcset ru "Cancel" "От&мена"
    ::msgcat::mcset ru "&Cancel" "От&мена"
    ::msgcat::mcset ru "Cannot change to the directory \"%1\$s\".\nPermission denied." \
			"\u041d\u0435 \u043c\u043e\u0433\u0443 \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u0432 \u043a\u0430\u0442\u0430\u043b\u043e\u0433 \"%1\$s\".\n\u041d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u0430\u0432 \u0434\u043e\u0441\u0442\u0443\u043f\u0430"
    ::msgcat::mcset ru "Choose Directory" "\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043a\u0430\u0442\u0430\u043b\u043e\u0433"
    ::msgcat::mcset ru "Cl&ear" "\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u044c"
    ::msgcat::mcset ru "Color" "\u0426\u0432\u0435\u0442"
    ::msgcat::mcset ru "Console" "\u041a\u043e\u043d\u0441\u043e\u043b\u044c"
    ::msgcat::mcset ru "&Copy" "\u041a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c"
    ::msgcat::mcset ru "Cu&t" "\u0412\u044b\u0440\u0435\u0437\u0430\u0442\u044c"
    ::msgcat::mcset ru "&Delete" "\u0423\u0434\u0430\u043b\u0438\u0442\u044c"
    ::msgcat::mcset ru "Details >>" "\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 >>"
    ::msgcat::mcset ru "Directory \"%1\$s\" does not exist." "\u041a\u0430\u0442\u0430\u043b\u043e\u0433\u0430 \"%1\$s\" \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442."
    ::msgcat::mcset ru "&Directory:" "&\u041a\u0430\u0442\u0430\u043b\u043e\u0433:"
    ::msgcat::mcset ru "Error: %1\$s" "\u041e\u0448\u0438\u0431\u043a\u0430: %1\$s"
    ::msgcat::mcset ru "E&xit" "\u0412\u044b\u0445\u043e\u0434"
			"Не могу перейти в каталог \"%1\$s\".\nНедостаточно прав доступа"
    ::msgcat::mcset ru "Choose Directory" "Выберите каталог"
    ::msgcat::mcset ru "Cl&ear" "Очистить"
    ::msgcat::mcset ru "Color" "Цвет"
    ::msgcat::mcset ru "Console" "Консоль"
    ::msgcat::mcset ru "&Copy" "Копировать"
    ::msgcat::mcset ru "Cu&t" "Вырезать"
    ::msgcat::mcset ru "&Delete" "Удалить"
    ::msgcat::mcset ru "Details >>" "Подробнее >>"
    ::msgcat::mcset ru "Directory \"%1\$s\" does not exist." "Каталога \"%1\$s\" не существует."
    ::msgcat::mcset ru "&Directory:" "&Каталог:"
    ::msgcat::mcset ru "Error: %1\$s" "Ошибка: %1\$s"
    ::msgcat::mcset ru "E&xit" "Выход"
    ::msgcat::mcset ru "File \"%1\$s\" already exists.\nDo you want to overwrite it?" \
			    "\u0424\u0430\u0439\u043b \"%1\$s\" \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442.\n\u0417\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u0435\u0433\u043e?"
    ::msgcat::mcset ru "File \"%1\$s\" already exists.\n\n" "\u0424\u0430\u0439\u043b \"%1\$s\" \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442.\n\n"
    ::msgcat::mcset ru "File \"%1\$s\" does not exist." "\u0424\u0430\u0439\u043b \"%1\$s\" \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d."
    ::msgcat::mcset ru "File &name:" "&\u0418\u043c\u044f \u0444\u0430\u0439\u043b\u0430:"
    ::msgcat::mcset ru "File &names:" "&\u0418\u043c\u0435\u043d\u0430 \u0444\u0430\u0439\u043b\u043e\u0432:"
    ::msgcat::mcset ru "Files of &type:" "&\u0422\u0438\u043f \u0444\u0430\u0439\u043b\u043e\u0432:"
    ::msgcat::mcset ru "Fi&les:" "\u0424\u0430\u0439&\u043b\u044b:"
    ::msgcat::mcset ru "&Filter" "&\u0424\u0438\u043b\u044c\u0442\u0440"
    ::msgcat::mcset ru "Fil&ter:" "\u0424\u0438\u043b\u044c&\u0442\u0440:"
    ::msgcat::mcset ru "&Green" " &\u0417\u0435\u043b\u0435\u043d\u044b\u0439"
    ::msgcat::mcset ru "Hi" "\u041f\u0440\u0438\u0432\u0435\u0442"
    ::msgcat::mcset ru "&Hide Console" "\u0421\u043f\u0440\u044f\u0442\u0430\u0442\u044c \u043a\u043e\u043d\u0441\u043e\u043b\u044c"
    ::msgcat::mcset ru "&Ignore" "&\u0418\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c"
    ::msgcat::mcset ru "Invalid file name \"%1\$s\"." "\u041d\u0435\u0432\u0435\u0440\u043d\u043e\u0435 \u0438\u043c\u044f \u0444\u0430\u0439\u043b\u0430 \"%1\$s\"."
    ::msgcat::mcset ru "Log Files" "\u0424\u0430\u0439\u043b\u044b \u0436\u0443\u0440\u043d\u0430\u043b\u0430"
    ::msgcat::mcset ru "&No" "&\u041d\u0435\u0442"
    ::msgcat::mcset ru "&OK" "&\u041e\u041a"
    ::msgcat::mcset ru "OK" "\u041e\u041a"
    ::msgcat::mcset ru "Ok" "\u0414\u0430"
    ::msgcat::mcset ru "Open" "\u041e\u0442\u043a\u0440\u044b\u0442\u044c"
    ::msgcat::mcset ru "&Open" "&\u041e\u0442\u043a\u0440\u044b\u0442\u044c"
    ::msgcat::mcset ru "Open Multiple Files" "\u041e\u0442\u043a\u0440\u044b\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0444\u0430\u0439\u043b\u043e\u0432"
    ::msgcat::mcset ru "P&aste" "\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c"
    ::msgcat::mcset ru "&Quit" "\u0412\u044b\u0445\u043e\u0434"
    ::msgcat::mcset ru "&Red" " &\u041a\u0440\u0430\u0441\u043d\u044b\u0439"
    ::msgcat::mcset ru "Replace existing file?" "\u0417\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u0444\u0430\u0439\u043b?"
    ::msgcat::mcset ru "&Retry" "&\u041f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u044c"
    ::msgcat::mcset ru "&Save" "&\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c"
    ::msgcat::mcset ru "Save As" "\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043a\u0430\u043a"
    ::msgcat::mcset ru "Save To Log" "\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 \u0436\u0443\u0440\u043d\u0430\u043b"
    ::msgcat::mcset ru "Select Log File" "\u0412\u044b\u0431\u0440\u0430\u0442\u044c \u0436\u0443\u0440\u043d\u0430\u043b"
    ::msgcat::mcset ru "Select a file to source" "\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0444\u0430\u0439\u043b \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0446\u0438\u0438"
			    "Файл \"%1\$s\" уже существует.\nЗаменить его?"
    ::msgcat::mcset ru "File \"%1\$s\" already exists.\n\n" "Файл \"%1\$s\" уже существует.\n\n"
    ::msgcat::mcset ru "File \"%1\$s\" does not exist." "Файл \"%1\$s\" не найден."
    ::msgcat::mcset ru "File &name:" "&Имя файла:"
    ::msgcat::mcset ru "File &names:" "&Имена файлов:"
    ::msgcat::mcset ru "Files of &type:" "&Тип файлов:"
    ::msgcat::mcset ru "Fi&les:" "Фай&лы:"
    ::msgcat::mcset ru "&Filter" "&Фильтр"
    ::msgcat::mcset ru "Fil&ter:" "Филь&тр:"
    ::msgcat::mcset ru "&Green" " &Зеленый"
    ::msgcat::mcset ru "Hi" "Привет"
    ::msgcat::mcset ru "&Hide Console" "Спрятать консоль"
    ::msgcat::mcset ru "&Ignore" "&Игнорировать"
    ::msgcat::mcset ru "Invalid file name \"%1\$s\"." "Неверное имя файла \"%1\$s\"."
    ::msgcat::mcset ru "Log Files" "Файлы журнала"
    ::msgcat::mcset ru "&No" "&Нет"
    ::msgcat::mcset ru "&OK" "&ОК"
    ::msgcat::mcset ru "OK" "ОК"
    ::msgcat::mcset ru "Ok" "Да"
    ::msgcat::mcset ru "Open" "Открыть"
    ::msgcat::mcset ru "&Open" "&Открыть"
    ::msgcat::mcset ru "Open Multiple Files" "Открыть несколько файлов"
    ::msgcat::mcset ru "P&aste" "Вставить"
    ::msgcat::mcset ru "&Quit" "Выход"
    ::msgcat::mcset ru "&Red" " &Красный"
    ::msgcat::mcset ru "Replace existing file?" "Заменить существующий файл?"
    ::msgcat::mcset ru "&Retry" "&Повторить"
    ::msgcat::mcset ru "&Save" "&Сохранить"
    ::msgcat::mcset ru "Save As" "Сохранить как"
    ::msgcat::mcset ru "Save To Log" "Сохранить в журнал"
    ::msgcat::mcset ru "Select Log File" "Выбрать журнал"
    ::msgcat::mcset ru "Select a file to source" "Выберите файл для интерпретации"
    ::msgcat::mcset ru "&Selection:"
    ::msgcat::mcset ru "Skip Messages" "\u041f\u0440\u043e\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f"
    ::msgcat::mcset ru "&Source..." "\u0418\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0444\u0430\u0439\u043b..."
    ::msgcat::mcset ru "Tcl Scripts" "\u041f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430 \u043d\u0430 \u044f\u0437\u044b\u043a\u0435 TCL"
    ::msgcat::mcset ru "Tcl for Windows" "TCL \u0434\u043b\u044f Windows"
    ::msgcat::mcset ru "Text Files" "\u0422\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0435 \u0444\u0430\u0439\u043b\u044b"
    ::msgcat::mcset ru "&Yes" "&\u0414\u0430"
    ::msgcat::mcset ru "abort" "\u043e\u0442\u043c\u0435\u043d\u0430"
    ::msgcat::mcset ru "blue" " \u0433\u043e\u043b\u0443\u0431\u043e\u0439"
    ::msgcat::mcset ru "cancel" "\u043e\u0442\u043c\u0435\u043d\u0430"
    ::msgcat::mcset ru "extension" "\u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435"
    ::msgcat::mcset ru "extensions" "\u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f"
    ::msgcat::mcset ru "green" " \u0437\u0435\u043b\u0435\u043d\u044b\u0439"
    ::msgcat::mcset ru "ignore" "\u043f\u0440\u043e\u043f\u0443\u0441\u0442\u0438\u0442\u044c"
    ::msgcat::mcset ru "ok" "\u043e\u043a"
    ::msgcat::mcset ru "red" " \u043a\u0440\u0430\u0441\u043d\u044b\u0439"
    ::msgcat::mcset ru "retry" "\u043f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u044c"
    ::msgcat::mcset ru "yes" "\u0434\u0430"
    ::msgcat::mcset ru "Skip Messages" "Пропустить сообщения"
    ::msgcat::mcset ru "&Source..." "Интерпретировать файл..."
    ::msgcat::mcset ru "Tcl Scripts" "Программа на языке TCL"
    ::msgcat::mcset ru "Tcl for Windows" "TCL для Windows"
    ::msgcat::mcset ru "Text Files" "Текстовые файлы"
    ::msgcat::mcset ru "&Yes" "&Да"
    ::msgcat::mcset ru "abort" "отмена"
    ::msgcat::mcset ru "blue" " голубой"
    ::msgcat::mcset ru "cancel" "отмена"
    ::msgcat::mcset ru "extension" "расширение"
    ::msgcat::mcset ru "extensions" "расширения"
    ::msgcat::mcset ru "green" " зеленый"
    ::msgcat::mcset ru "ignore" "пропустить"
    ::msgcat::mcset ru "ok" "ок"
    ::msgcat::mcset ru "red" " красный"
    ::msgcat::mcset ru "retry" "повторить"
    ::msgcat::mcset ru "yes" "да"
}

Changes to library/msgs/sv.msg.
1
2
3
4
5
6

7
8
9
10


11
12
13

14
15
16
17
18
19
20
21
22
23
24
25

26
27
28
29
30
31
32
33
34
35


36
37

38
39
40
41
42
43
44
45
46
47



48
49
50
51
52



53
54
55
56
57


58
59
60


61
62

63
64
65
66

67
68
69
70

71
72
73
74


75
76
1
2
3
4
5

6
7
8


9
10
11
12

13
14
15
16
17
18
19
20
21
22
23
24

25
26
27
28
29
30
31
32
33


34
35
36

37
38
39
40
41
42
43
44



45
46
47
48
49



50
51
52
53
54
55


56
57
58


59
60
61

62
63
64
65

66
67
68
69

70
71
72


73
74
75
76





-
+


-
-
+
+


-
+











-
+








-
-
+
+

-
+







-
-
-
+
+
+


-
-
-
+
+
+



-
-
+
+

-
-
+
+

-
+



-
+



-
+


-
-
+
+


namespace eval ::tk {
    ::msgcat::mcset sv "&Abort" "&Avsluta"
    ::msgcat::mcset sv "&About..." "&Om..."
    ::msgcat::mcset sv "All Files" "Samtliga filer"
    ::msgcat::mcset sv "Application Error" "Programfel"
    ::msgcat::mcset sv "&Blue" "&Bl\u00e5"
    ::msgcat::mcset sv "&Blue" "&Blå"
    ::msgcat::mcset sv "Cancel" "Avbryt"
    ::msgcat::mcset sv "&Cancel" "&Avbryt"
    ::msgcat::mcset sv "Cannot change to the directory \"%1\$s\".\nPermission denied." "Kan ej n\u00e5 mappen \"%1\$s\".\nSaknar r\u00e4ttigheter."
    ::msgcat::mcset sv "Choose Directory" "V\u00e4lj mapp"
    ::msgcat::mcset sv "Cannot change to the directory \"%1\$s\".\nPermission denied." "Kan ej nå mappen \"%1\$s\".\nSaknar rättigheter."
    ::msgcat::mcset sv "Choose Directory" "Välj mapp"
    ::msgcat::mcset sv "Cl&ear" "&Radera"
    ::msgcat::mcset sv "&Clear Console" "&Radera konsollen"
    ::msgcat::mcset sv "Color" "F\u00e4rg"
    ::msgcat::mcset sv "Color" "Färg"
    ::msgcat::mcset sv "Console" "Konsoll"
    ::msgcat::mcset sv "&Copy" "&Kopiera"
    ::msgcat::mcset sv "Cu&t" "Klipp u&t"
    ::msgcat::mcset sv "&Delete" "&Radera"
    ::msgcat::mcset sv "Details >>" "Detaljer >>"
    ::msgcat::mcset sv "Directory \"%1\$s\" does not exist." "Mappen \"%1\$s\" finns ej."
    ::msgcat::mcset sv "&Directory:" "&Mapp:"
    ::msgcat::mcset sv "&Edit" "R&edigera"
    ::msgcat::mcset sv "Error: %1\$s" "Fel: %1\$s"
    ::msgcat::mcset sv "E&xit" "&Avsluta"
    ::msgcat::mcset sv "&File" "&Fil"
    ::msgcat::mcset sv "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "Filen \"%1\$s\" finns redan.\nVill du skriva \u00f6ver den?"
    ::msgcat::mcset sv "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "Filen \"%1\$s\" finns redan.\nVill du skriva över den?"
    ::msgcat::mcset sv "File \"%1\$s\" already exists.\n\n" "Filen \"%1\$s\" finns redan.\n\n"
    ::msgcat::mcset sv "File \"%1\$s\" does not exist." "Filen \"%1\$s\" finns ej."
    ::msgcat::mcset sv "File &name:" "Fil&namn:"
    ::msgcat::mcset sv "File &names:" "Fil&namn:"
    ::msgcat::mcset sv "Files of &type:" "Filer av &typ:"
    ::msgcat::mcset sv "Fi&les:" "Fi&ler:"
    ::msgcat::mcset sv "&Filter"
    ::msgcat::mcset sv "Fil&ter:"
    ::msgcat::mcset sv "&Green" "&Gr\u00f6n"
    ::msgcat::mcset sv "&Help" "&Hj\u00e4lp"
    ::msgcat::mcset sv "&Green" "&Grön"
    ::msgcat::mcset sv "&Help" "&Hjälp"
    ::msgcat::mcset sv "Hi" "Hej"
    ::msgcat::mcset sv "&Hide Console" "&G\u00f6m konsollen"
    ::msgcat::mcset sv "&Hide Console" "&Göm konsollen"
    ::msgcat::mcset sv "&Ignore" "&Ignorera"
    ::msgcat::mcset sv "Invalid file name \"%1\$s\"." "Ogiltigt filnamn \"%1\$s\"."
    ::msgcat::mcset sv "Log Files" "Loggfiler"
    ::msgcat::mcset sv "&No" "&Nej"
    ::msgcat::mcset sv "&OK"
    ::msgcat::mcset sv "OK"
    ::msgcat::mcset sv "Ok"
    ::msgcat::mcset sv "Open" "\u00d6ppna"
    ::msgcat::mcset sv "&Open" "&\u00d6ppna"
    ::msgcat::mcset sv "Open Multiple Files" "\u00d6ppna flera filer"
    ::msgcat::mcset sv "Open" "Öppna"
    ::msgcat::mcset sv "&Open" "&Öppna"
    ::msgcat::mcset sv "Open Multiple Files" "Öppna flera filer"
    ::msgcat::mcset sv "P&aste" "&Klistra in"
    ::msgcat::mcset sv "&Quit" "&Avsluta"
    ::msgcat::mcset sv "&Red" "&R\u00f6d"
    ::msgcat::mcset sv "Replace existing file?" "Ers\u00e4tt existerande fil?"
    ::msgcat::mcset sv "&Retry" "&F\u00f6rs\u00f6k igen"
    ::msgcat::mcset sv "&Red" "&Röd"
    ::msgcat::mcset sv "Replace existing file?" "Ersätt existerande fil?"
    ::msgcat::mcset sv "&Retry" "&Försök igen"
    ::msgcat::mcset sv "&Save" "&Spara"
    ::msgcat::mcset sv "Save As" "Spara som"
    ::msgcat::mcset sv "Save To Log" "Spara till logg"
    ::msgcat::mcset sv "Select Log File" "V\u00e4lj loggfil"
    ::msgcat::mcset sv "Select a file to source" "V\u00e4lj k\u00e4llfil"
    ::msgcat::mcset sv "Select Log File" "Välj loggfil"
    ::msgcat::mcset sv "Select a file to source" "Välj källfil"
    ::msgcat::mcset sv "&Selection:" "&Val:"
    ::msgcat::mcset sv "Skip Messages" "Hoppa \u00f6ver meddelanden"
    ::msgcat::mcset sv "&Source..." "&K\u00e4lla..."
    ::msgcat::mcset sv "Skip Messages" "Hoppa över meddelanden"
    ::msgcat::mcset sv "&Source..." "&Källa..."
    ::msgcat::mcset sv "Tcl Scripts" "Tcl skript"
    ::msgcat::mcset sv "Tcl for Windows" "Tcl f\u00f6r Windows"
    ::msgcat::mcset sv "Tcl for Windows" "Tcl för Windows"
    ::msgcat::mcset sv "Text Files" "Textfiler"
    ::msgcat::mcset sv "&Yes" "&Ja"
    ::msgcat::mcset sv "abort" "avbryt"
    ::msgcat::mcset sv "blue" "bl\u00e5"
    ::msgcat::mcset sv "blue" "blå"
    ::msgcat::mcset sv "cancel" "avbryt"
    ::msgcat::mcset sv "extension" "utvidgning"
    ::msgcat::mcset sv "extensions" "utvidgningar"
    ::msgcat::mcset sv "green" "gr\u00f6n"
    ::msgcat::mcset sv "green" "grön"
    ::msgcat::mcset sv "ignore" "ignorera"
    ::msgcat::mcset sv "ok"
    ::msgcat::mcset sv "red" "r\u00f6d"
    ::msgcat::mcset sv "retry" "f\u00f6rs\u00f6k igen"
    ::msgcat::mcset sv "red" "röd"
    ::msgcat::mcset sv "retry" "försök igen"
    ::msgcat::mcset sv "yes" "ja"
}
Changes to library/obsolete.tcl.
1
2
3
4
5
6
7


8
9
10
11
12
13
14
1
2
3
4
5


6
7
8
9
10
11
12
13
14





-
-
+
+







# obsolete.tcl --
#
# This file contains obsolete procedures that people really shouldn't
# be using anymore, but which are kept around for backward compatibility.
#
# Copyright (c) 1994 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright © 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.
#

# The procedures below are here strictly for backward compatibility with
# Tk version 3.6 and earlier.  The procedures are no longer needed, so
99
100
101
102
103
104
105
106

107
108
109
110
111
112
113
99
100
101
102
103
104
105

106
107
108
109
110
111
112
113







-
+







    if {[tk windowingsystem] ne "aqua"} {
	option add *Listbox.borderWidth		2 $prio; # 1
    }
    if {[tk windowingsystem] eq "x11"} {
	option add *Listbox.selectBorderWidth	1 $prio; # 0
    }
    # Remove focus into Listbox added for 8.5
    bind Listbox <1> {
    bind Listbox <Button-1> {
	if {[winfo exists %W]} {
	    tk::ListboxBeginSelect %W [%W index @%x,%y]
	}
    }
}

proc ::tk::classic::restore_menu {args} {
Changes to library/optMenu.tcl.
1
2
3
4
5
6
7


8
9
10
11
12
13
14
1
2
3
4
5


6
7
8
9
10
11
12
13
14





-
-
+
+







# optMenu.tcl --
#
# This file defines the procedure tk_optionMenu, which creates
# an option button and its associated menu.
#
# Copyright (c) 1994 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright © 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.
#

# ::tk_optionMenu --
# This procedure creates an option button named $w and an associated
Changes to library/palette.tcl.
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







# palette.tcl --
#
# This file contains procedures that change the color palette used
# by Tk.
#
# Copyright (c) 1995-1997 Sun Microsystems, Inc.
# Copyright © 1995-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.
#

# ::tk_setPalette --
# Changes the default color scheme for a Tk application by setting
Changes to library/safetk.tcl.
1
2
3
4
5

6
7
8
9
10
11
12
13
14
15
16
17

18
19

20
21
22
23
24
25
26
27
28
29
30
31
32

33
34

35
36

37
38
39
40
41
42
43

44
45
46

47
48

49
50

51
52
53
54
55
56

57
58
59
60
61
62
63
64
65

66
67
68
69
70
71
72

73
74
75
76
77

78
79
80
81
82
83
84

85
86
87
88

89
90
91


92
93
94
95


96
97
98
99
100
101
102
1
2
3
4

5
6
7
8
9
10
11
12
13
14
15
16

17
18

19
20
21
22
23
24
25
26
27
28
29
30
31

32
33

34
35

36
37
38
39
40
41
42

43
44
45

46
47

48
49

50
51
52
53
54
55

56
57
58
59
60
61
62
63
64

65
66
67
68
69
70
71

72
73
74
75
76

77
78
79
80
81
82
83

84
85
86
87

88
89


90
91
92
93


94
95
96
97
98
99
100
101
102




-
+











-
+

-
+












-
+

-
+

-
+






-
+


-
+

-
+

-
+





-
+








-
+






-
+




-
+






-
+



-
+

-
-
+
+


-
-
+
+







# safetk.tcl --
#
# Support procs to use Tk in safe interpreters.
#
# 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.

# see safetk.n for documentation

#
#
# Note: It is now ok to let untrusted code being executed
#       between the creation of the interp and the actual loading
#       of Tk in that interp because the C side Tk_Init will
#       now look up the master interp and ask its safe::TkInit
#       now look up the parent interp and ask its safe::TkInit
#       for the actual parameters to use for it's initialization (if allowed),
#       not relying on the slave state.
#       not relying on the child state.
#

# We use opt (optional arguments parsing)
package require opt 0.4.1;

namespace eval ::safe {

    # counter for safe toplevels
    variable tkSafeId 0
}

#
# tkInterpInit : prepare the slave interpreter for tk loading
# tkInterpInit : prepare the child interpreter for tk loading
#                most of the real job is done by loadTk
# returns the slave name (tkInterpInit does)
# returns the child name (tkInterpInit does)
#
proc ::safe::tkInterpInit {slave argv} {
proc ::safe::tkInterpInit {child argv} {
    global env tk_library

    # We have to make sure that the tk_library variable is normalized.
    set tk_library [file normalize $tk_library]

    # Clear Tk's access for that interp (path).
    allowTk $slave $argv
    allowTk $child $argv

    # Ensure tk_library and subdirs (eg, ttk) are on the access path
    ::interp eval $slave [list set tk_library [::safe::interpAddToAccessPath $slave $tk_library]]
    ::interp eval $child [list set tk_library [::safe::interpAddToAccessPath $child $tk_library]]
    foreach subdir [::safe::AddSubDirs [list $tk_library]] {
	::safe::interpAddToAccessPath $slave $subdir
	::safe::interpAddToAccessPath $child $subdir
    }
    return $slave
    return $child
}


# tkInterpLoadTk:
# Do additional configuration as needed (calling tkInterpInit)
# and actually load Tk into the slave.
# and actually load Tk into the child.
#
# Either contained in the specified windowId (-use) or
# creating a decorated toplevel for it.

# empty definition for auto_mkIndex
proc ::safe::loadTk {} {}

::tcl::OptProc ::safe::loadTk {
    {slave -interp "name of the slave interpreter"}
    {child -interp "name of the child interpreter"}
    {-use  -windowId {} "window Id to use (new toplevel otherwise)"}
    {-display -displayName {} "display name to use (current one otherwise)"}
} {
    set displayGiven [::tcl::OptProcArgGiven "-display"]
    if {!$displayGiven} {
	# Try to get the current display from "."
	# (which might not exist if the master is tk-less)
	# (which might not exist if the parent is tk-less)
	if {[catch {set display [winfo screen .]}]} {
	    if {[info exists ::env(DISPLAY)]} {
		set display $::env(DISPLAY)
	    } else {
		Log $slave "no winfo screen . nor env(DISPLAY)" WARNING
		Log $child "no winfo screen . nor env(DISPLAY)" WARNING
		set display ":0.0"
	    }
	}
    }

    # Get state for access to the cleanupHook.
    namespace upvar ::safe S$slave state
    namespace upvar ::safe S$child state

    if {![::tcl::OptProcArgGiven "-use"]} {
	# create a decorated toplevel
	lassign [tkTopLevel $slave $display] w use
	lassign [tkTopLevel $child $display] w use

	# set our delete hook (slave arg is added by interpDelete)
	# to clean up both window related code and tkInit(slave)
	# set our delete hook (child arg is added by interpDelete)
	# to clean up both window related code and tkInit(child)
	set state(cleanupHook) [list tkDelete {} $w]
    } else {
	# set our delete hook (slave arg is added by interpDelete)
	# to clean up tkInit(slave)
	# set our delete hook (child arg is added by interpDelete)
	# to clean up tkInit(child)
	set state(cleanupHook) [list disallowTk]

	# Let's be nice and also accept tk window names instead of ids
	if {[string match ".*" $use]} {
	    set windowName $use
	    set use [winfo id $windowName]
	    set nDisplay [winfo screen $windowName]
118
119
120
121
122
123
124
125
126


127
128

129
130

131
132
133
134
135
136
137
118
119
120
121
122
123
124


125
126
127

128
129

130
131
132
133
134
135
136
137







-
-
+
+

-
+

-
+







		    "conflicting -display $display and -use $use -> $nDisplay"
	    } else {
		set display $nDisplay
	    }
	}
    }

    # Prepares the slave for tk with those parameters
    tkInterpInit $slave [list "-use" $use "-display" $display]
    # Prepares the child for tk with those parameters
    tkInterpInit $child [list "-use" $use "-display" $display]

    load {} Tk $slave
    load {} Tk $child

    return $slave
    return $child
}

proc ::safe::TkInit {interpPath} {
    variable tkInit
    if {[info exists tkInit($interpPath)]} {
	set value $tkInit($interpPath)
	Log $interpPath "TkInit called, returning \"$value\"" NOTICE
145
146
147
148
149
150
151
152

153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171

172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191

192
193
194
195
196

197
198
199
200
201
202
203
204




205
206
207
208

209
210
211
212
213


214
215
216
217

218
219
220
221
222
223

224
225

226
227

228
229
230
231
232
233
234
235
236
237
238
239

240
241
242
243
244
245
246
247
248
249
250

251
252
253
254
255
256
257
258
259
260
261
262
145
146
147
148
149
150
151

152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170

171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190

191
192
193
194
195

196
197
198
199
200




201
202
203
204
205
206
207

208
209
210
211


212
213
214
215
216

217
218
219
220
221
222

223
224

225
226

227
228
229
230
231
232
233
234
235
236
237
238

239
240
241
242
243
244
245
246
247
248
249

250
251
252
253
254
255
256
257
258
259
260
261
262







-
+


















-
+



















-
+




-
+




-
-
-
-
+
+
+
+



-
+



-
-
+
+



-
+





-
+

-
+

-
+











-
+










-
+













# safe::allowTk --
#
#	Set tkInit(interpPath) to allow Tk to be initialized in
#	safe::TkInit.
#
# Arguments:
#	interpPath	slave interpreter handle
#	interpPath	child interpreter handle
#	argv		arguments passed to safe::TkInterpInit
#
# Results:
#	none.

proc ::safe::allowTk {interpPath argv} {
    variable tkInit
    set tkInit($interpPath) $argv
    return
}


# safe::disallowTk --
#
#	Unset tkInit(interpPath) to disallow Tk from getting initialized
#	in safe::TkInit.
#
# Arguments:
#	interpPath	slave interpreter handle
#	interpPath	child interpreter handle
#
# Results:
#	none.

proc ::safe::disallowTk {interpPath} {
    variable tkInit
    # This can already be deleted by the DeleteHook of the interp
    if {[info exists tkInit($interpPath)]} {
	unset tkInit($interpPath)
    }
    return
}


# safe::tkDelete --
#
#	Clean up the window associated with the interp being deleted.
#
# Arguments:
#	interpPath	slave interpreter handle
#	interpPath	child interpreter handle
#
# Results:
#	none.

proc ::safe::tkDelete {W window slave} {
proc ::safe::tkDelete {W window child} {

    # we are going to be called for each widget... skip untill it's
    # top level

    Log $slave "Called tkDelete $W $window" NOTICE
    if {[::interp exists $slave]} {
	if {[catch {::safe::interpDelete $slave} msg]} {
	    Log $slave "Deletion error : $msg"
    Log $child "Called tkDelete $W $window" NOTICE
    if {[::interp exists $child]} {
	if {[catch {::safe::interpDelete $child} msg]} {
	    Log $child "Deletion error : $msg"
	}
    }
    if {[winfo exists $window]} {
	Log $slave "Destroy toplevel $window" NOTICE
	Log $child "Destroy toplevel $window" NOTICE
	destroy $window
    }

    # clean up tkInit(slave)
    disallowTk $slave
    # clean up tkInit(child)
    disallowTk $child
    return
}

proc ::safe::tkTopLevel {slave display} {
proc ::safe::tkTopLevel {child display} {
    variable tkSafeId
    incr tkSafeId
    set w ".safe$tkSafeId"
    if {[catch {toplevel $w -screen $display -class SafeTk} msg]} {
	return -code error -errorcode {TK TOPLEVEL SAFE} \
	    "Unable to create toplevel for safe slave \"$slave\" ($msg)"
	    "Unable to create toplevel for \"$child\" ($msg)"
    }
    Log $slave "New toplevel $w" NOTICE
    Log $child "New toplevel $w" NOTICE

    set msg "Untrusted Tcl applet ($slave)"
    set msg "Untrusted Tcl applet ($child)"
    wm title $w $msg

    # Control frame (we must create a style for it)
    ttk::style layout TWarningFrame {WarningFrame.border -sticky nswe}
    ttk::style configure TWarningFrame -background red

    set wc $w.fc
    ttk::frame $wc -relief ridge -borderwidth 4 -style TWarningFrame

    # We will destroy the interp when the window is destroyed
    bindtags $wc [concat Safe$wc [bindtags $wc]]
    bind Safe$wc <Destroy> [list ::safe::tkDelete %W $w $slave]
    bind Safe$wc <Destroy> [list ::safe::tkDelete %W $w $child]

    ttk::label $wc.l -text $msg -anchor w

    # We want the button to be the last visible item
    # (so be packed first) and at the right and not resizing horizontally

    # frame the button so it does not expand horizontally
    # but still have the default background instead of red one from the parent
    ttk::frame  $wc.fb -borderwidth 0
    ttk::button $wc.fb.b -text "Delete" \
	    -command [list ::safe::tkDelete $w $w $slave]
	    -command [list ::safe::tkDelete $w $w $child]
    pack $wc.fb.b -side right -fill both
    pack $wc.fb -side right -fill both -expand 1
    pack $wc.l -side left -fill both -expand 1 -ipady 2
    pack $wc -side bottom -fill x

    # Container frame
    frame $w.c -container 1
    pack $w.c -fill both -expand 1

    # return both the toplevel window name and the id to use for embedding
    list $w [winfo id $w.c]
}
Changes to library/scale.tcl.
1
2
3
4
5
6
7


8
9
10
11
12
13
14
1
2
3
4
5


6
7
8
9
10
11
12
13
14





-
-
+
+







# scale.tcl --
#
# This file defines the default bindings for Tk scale widgets and provides
# procedures that help in implementing the bindings.
#
# Copyright (c) 1994 The Regents of the University of California.
# Copyright (c) 1994-1995 Sun Microsystems, Inc.
# Copyright © 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.
#

#-------------------------------------------------------------------------
# The code below creates the default class bindings for entries.
30
31
32
33
34
35
36
37

38
39
40
41
42
43
44
45
46
47
48
49
50

51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71

72
73
74
75
76
77
78
30
31
32
33
34
35
36

37
38
39
40
41
42
43
44
45
46
47
48
49

50
51
52
53
54
55
56
57
58
59
60
61
62









63
64
65
66
67
68
69
70







-
+












-
+












-
-
-
-
-
-
-
-
-
+







    if {$tk_strictMotif} {
	%W configure -activebackground $tk::Priv(activeBg)
    }
    if {[%W cget -state] eq "active"} {
	%W configure -state normal
    }
}
bind Scale <1> {
bind Scale <Button-1> {
    tk::ScaleButtonDown %W %x %y
}
bind Scale <B1-Motion> {
    tk::ScaleDrag %W %x %y
}
bind Scale <B1-Leave> { }
bind Scale <B1-Enter> { }
bind Scale <ButtonRelease-1> {
    tk::CancelRepeat
    tk::ScaleEndDrag %W
    tk::ScaleActivate %W %x %y
}
bind Scale <2> {
bind Scale <Button-2> {
    tk::ScaleButton2Down %W %x %y
}
bind Scale <B2-Motion> {
    tk::ScaleDrag %W %x %y
}
bind Scale <B2-Leave> { }
bind Scale <B2-Enter> { }
bind Scale <ButtonRelease-2> {
    tk::CancelRepeat
    tk::ScaleEndDrag %W
    tk::ScaleActivate %W %x %y
}
if {[tk windowingsystem] eq "win32"} {
    # On Windows do the same with button 3, as that is the right mouse button
    bind Scale <3>		[bind Scale <2>]
    bind Scale <B3-Motion>	[bind Scale <B2-Motion>]
    bind Scale <B3-Leave>	[bind Scale <B2-Leave>]
    bind Scale <B3-Enter>	[bind Scale <B2-Enter>]
    bind Scale <ButtonRelease-3> [bind Scale <ButtonRelease-2>]
}
bind Scale <Control-1> {
bind Scale <Control-Button-1> {
    tk::ScaleControlPress %W %x %y
}
bind Scale <<PrevLine>> {
    tk::ScaleIncrement %W up little noRepeat
}
bind Scale <<NextLine>> {
    tk::ScaleIncrement %W down little noRepeat
Changes to library/scrlbar.tcl.
1
2
3
4
5
6
7


8
9
10
11
12
13
14
1
2
3
4
5


6
7
8
9
10
11
12
13
14





-
-
+
+







# scrlbar.tcl --
#
# This file defines the default bindings for Tk scrollbar widgets.
# It also provides procedures that help in implementing the bindings.
#
# Copyright (c) 1994 The Regents of the University of California.
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright © 1994 The Regents of the University of California.
# Copyright © 1994-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.
#

#-------------------------------------------------------------------------
# The code below creates the default class bindings for scrollbars.
35
36
37
38
39
40
41
42

43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

61
62
63

64
65
66

67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

88
89
90

91
92
93
94
95
96
97
35
36
37
38
39
40
41

42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

60
61
62

63
64
65

66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86

87
88
89

90
91
92
93
94
95
96
97







-
+

















-
+


-
+


-
+




















-
+


-
+








bind Scrollbar <Leave> {
    if {$tk_strictMotif && [info exists tk::Priv(activeBg)]} {
	%W configure -activebackground $tk::Priv(activeBg)
    }
    %W activate {}
}
bind Scrollbar <1> {
bind Scrollbar <Button-1> {
    tk::ScrollButtonDown %W %x %y
}
bind Scrollbar <B1-Motion> {
    tk::ScrollDrag %W %x %y
}
bind Scrollbar <B1-B2-Motion> {
    tk::ScrollDrag %W %x %y
}
bind Scrollbar <ButtonRelease-1> {
    tk::ScrollButtonUp %W %x %y
}
bind Scrollbar <B1-Leave> {
    # Prevents <Leave> binding from being invoked.
}
bind Scrollbar <B1-Enter> {
    # Prevents <Enter> binding from being invoked.
}
bind Scrollbar <2> {
bind Scrollbar <Button-2> {
    tk::ScrollButton2Down %W %x %y
}
bind Scrollbar <B1-2> {
bind Scrollbar <B1-Button-2> {
    # Do nothing, since button 1 is already down.
}
bind Scrollbar <B2-1> {
bind Scrollbar <B2-Button-1> {
    # Do nothing, since button 2 is already down.
}
bind Scrollbar <B2-Motion> {
    tk::ScrollDrag %W %x %y
}
bind Scrollbar <ButtonRelease-2> {
    tk::ScrollButtonUp %W %x %y
}
bind Scrollbar <B1-ButtonRelease-2> {
    # Do nothing:  B1 release will handle it.
}
bind Scrollbar <B2-ButtonRelease-1> {
    # Do nothing:  B2 release will handle it.
}
bind Scrollbar <B2-Leave> {
    # Prevents <Leave> binding from being invoked.
}
bind Scrollbar <B2-Enter> {
    # Prevents <Enter> binding from being invoked.
}
bind Scrollbar <Control-1> {
bind Scrollbar <Control-Button-1> {
    tk::ScrollTopBottom %W %x %y
}
bind Scrollbar <Control-2> {
bind Scrollbar <Control-Button-2> {
    tk::ScrollTopBottom %W %x %y
}

bind Scrollbar <<PrevLine>> {
    tk::ScrollByUnits %W v -1
}
bind Scrollbar <<NextLine>> {
125
126
127
128
129
130
131
132
133
134
135
136




137
138
139
140

141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
125
126
127
128
129
130
131





132
133
134
135




136


























137
138
139
140
141
142
143







-
-
-
-
-
+
+
+
+
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







    tk::ScrollToPos %W 0
}
bind Scrollbar <<LineEnd>> {
    tk::ScrollToPos %W 1
}
}

if {[tk windowingsystem] eq "aqua"} {
    bind Scrollbar <MouseWheel> {
	tk::ScrollByUnits %W v [expr {-(%D)}]
    }
    bind Scrollbar <Option-MouseWheel> {
bind Scrollbar <MouseWheel> {
    tk::ScrollByUnits %W hv %D -30.0
}
bind Scrollbar <Option-MouseWheel> {
	tk::ScrollByUnits %W v [expr {-10 * (%D)}]
    }
    bind Scrollbar <Shift-MouseWheel> {
	tk::ScrollByUnits %W h [expr {-(%D)}]
    tk::ScrollByUnits %W hv %D -3.0
    }
    bind Scrollbar <Shift-Option-MouseWheel> {
	tk::ScrollByUnits %W h [expr {-10 * (%D)}]
    }
} else {
    bind Scrollbar <MouseWheel> {
	if {%D >= 0} {
	    tk::ScrollByUnits %W v [expr {-%D/30}]
	} else {
	    tk::ScrollByUnits %W v [expr {(29-%D)/30}]
	}
    }
    bind Scrollbar <Shift-MouseWheel> {
	if {%D >= 0} {
	    tk::ScrollByUnits %W h [expr {-%D/30}]
	} else {
	    tk::ScrollByUnits %W h [expr {(29-%D)/30}]
	}
    }
}

if {[tk windowingsystem] eq "x11"} {
    bind Scrollbar <4> {tk::ScrollByUnits %W v -5}
    bind Scrollbar <5> {tk::ScrollByUnits %W v 5}
    bind Scrollbar <Shift-4> {tk::ScrollByUnits %W h -5}
    bind Scrollbar <Shift-5> {tk::ScrollByUnits %W h 5}
}

# 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
# depending on where the mouse is.
#
332
333
334
335
336
337
338
339

340
341
342
343
344
345
346
347

348
349

350
351
352
353
354
355
356
302
303
304
305
306
307
308

309
310
311
312
313
314
315
316

317
318

319
320
321
322
323
324
325
326







-
+







-
+

-
+







#
# Arguments:
# w -		The scrollbar widget.
# orient -	Which kinds of scrollbars this applies to:  "h" for
#		horizontal, "v" for vertical, "hv" for both.
# amount -	How many units to scroll:  typically 1 or -1.

proc ::tk::ScrollByUnits {w orient amount} {
proc ::tk::ScrollByUnits {w orient amount {factor 1.0}} {
    set cmd [$w cget -command]
    if {$cmd eq "" || ([string first \
	    [string index [$w cget -orient] 0] $orient] < 0)} {
	return
    }
    set info [$w get]
    if {[llength $info] == 2} {
	uplevel #0 $cmd scroll $amount units
	uplevel #0 $cmd scroll [expr {$amount/$factor}] units
    } else {
	uplevel #0 $cmd [expr {[lindex $info 2] + $amount}]
	uplevel #0 $cmd [expr {[lindex $info 2] + [expr {$amount/$factor}]}]
    }
}

# ::tk::ScrollByPages --
# This procedure tells the scrollbar's associated widget to scroll up
# or down by a given number of screenfuls.  It notifies the associated
# widget in different ways for old and new command syntaxes.
Changes to library/spinbox.tcl.
1
2
3
4
5
6
7
8
9
10




11
12
13
14
15
16
17
1
2
3
4
5
6




7
8
9
10
11
12
13
14
15
16
17






-
-
-
-
+
+
+
+







# spinbox.tcl --
#
# This file defines the default bindings for Tk spinbox widgets and provides
# procedures that help in implementing those bindings.  The spinbox builds
# off the entry widget, so it can reuse Entry bindings and procedures.
#
# Copyright (c) 1992-1994 The Regents of the University of California.
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright (c) 1999-2000 Jeffrey Hobbs
# Copyright (c) 2000 Ajuba Solutions
# Copyright © 1992-1994 The Regents of the University of California.
# Copyright © 1994-1997 Sun Microsystems, Inc.
# Copyright © 1999-2000 Jeffrey Hobbs
# 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.
#

#-------------------------------------------------------------------------
# Elements of tk::Priv that are used in this file:
75
76
77
78
79
80
81
82

83
84
85
86
87
88

89
90
91
92
93

94
95
96
97
98

99
100
101
102

103
104
105
106

107
108
109
110
111
112
113
114
115
116
117
118
119
120

121
122
123
124
125
126
127
75
76
77
78
79
80
81

82
83
84
85
86
87

88
89
90
91
92

93
94
95
96
97

98
99
100
101

102
103
104
105

106
107
108
109
110
111
112
113
114
115
116
117
118
119

120
121
122
123
124
125
126
127







-
+





-
+




-
+




-
+



-
+



-
+













-
+







bind Spinbox <<TraverseIn>> {
    %W selection range 0 end
    %W icursor end
}

# Standard Motif bindings:

bind Spinbox <1> {
bind Spinbox <Button-1> {
    ::tk::spinbox::ButtonDown %W %x %y
}
bind Spinbox <B1-Motion> {
    ::tk::spinbox::Motion %W %x %y
}
bind Spinbox <Double-1> {
bind Spinbox <Double-Button-1> {
    ::tk::spinbox::ArrowPress %W %x %y
    set tk::Priv(selectMode) word
    ::tk::spinbox::MouseSelect %W %x sel.first
}
bind Spinbox <Triple-1> {
bind Spinbox <Triple-Button-1> {
    ::tk::spinbox::ArrowPress %W %x %y
    set tk::Priv(selectMode) line
    ::tk::spinbox::MouseSelect %W %x 0
}
bind Spinbox <Shift-1> {
bind Spinbox <Shift-Button-1> {
    set tk::Priv(selectMode) char
    %W selection adjust @%x
}
bind Spinbox <Double-Shift-1> {
bind Spinbox <Double-Shift-Button-1> {
    set tk::Priv(selectMode) word
    ::tk::spinbox::MouseSelect %W %x
}
bind Spinbox <Triple-Shift-1> {
bind Spinbox <Triple-Shift-Button-1> {
    set tk::Priv(selectMode) line
    ::tk::spinbox::MouseSelect %W %x
}
bind Spinbox <B1-Leave> {
    set tk::Priv(x) %x
    ::tk::spinbox::AutoScan %W
}
bind Spinbox <B1-Enter> {
    tk::CancelRepeat
}
bind Spinbox <ButtonRelease-1> {
    ::tk::spinbox::ButtonUp %W %x %y
}
bind Spinbox <Control-1> {
bind Spinbox <Control-Button-1> {
    %W icursor @%x
}

bind Spinbox <<PrevLine>> {
    %W invoke buttonup
}
bind Spinbox <<NextLine>> {
196
197
198
199
200
201
202
203

204
205
206
207
208
209

210
211
212
213
214



215
216
217
218
219
220
221
222

223
224
225
226
227
228
229
230
196
197
198
199
200
201
202

203
204
205
206
207
208

209
210
211



212
213
214
215
216
217
218
219
220


221

222
223
224
225
226
227
228







-
+





-
+


-
-
-
+
+
+






-
-
+
-







}
bind Spinbox <<SelectAll>> {
    %W selection range 0 end
}
bind Spinbox <<SelectNone>> {
    %W selection clear
}
bind Spinbox <KeyPress> {
bind Spinbox <Key> {
    ::tk::EntryInsert %W %A
}

# Ignore all Alt, Meta, and Control keypresses unless explicitly bound.
# Otherwise, if a widget binding for one of these is defined, the
# <KeyPress> class binding will also fire and insert the character,
# <Key> class binding will also fire and insert the character,
# which is wrong.  Ditto for Escape, Return, and Tab.

bind Spinbox <Alt-KeyPress> {# nothing}
bind Spinbox <Meta-KeyPress> {# nothing}
bind Spinbox <Control-KeyPress> {# nothing}
bind Spinbox <Alt-Key> {# nothing}
bind Spinbox <Meta-Key> {# nothing}
bind Spinbox <Control-Key> {# nothing}
bind Spinbox <Escape> {# nothing}
bind Spinbox <Return> {# nothing}
bind Spinbox <KP_Enter> {# nothing}
bind Spinbox <Tab> {# nothing}
bind Spinbox <Prior> {# nothing}
bind Spinbox <Next> {# nothing}
if {[tk windowingsystem] eq "aqua"} {
    bind Spinbox <Command-KeyPress> {# nothing}
bind Spinbox <Command-Key> {# nothing}
}

# On Windows, paste is done using Shift-Insert.  Shift-Insert already
# generates the <<Paste>> event, so we don't need to do anything here.
if {[tk windowingsystem] ne "win32"} {
    bind Spinbox <Insert> {
	catch {::tk::EntryInsert %W [::tk::GetSelection %W PRIMARY]}
    }
276
277
278
279
280
281
282
283

284
285
286
287
288
289
290
274
275
276
277
278
279
280

281
282
283
284
285
286
287
288







-
+







    if {!$tk_strictMotif} {
	%W delete [::tk::EntryPreviousWord %W insert] insert
    }
}

# A few additional bindings of my own.

bind Spinbox <2> {
bind Spinbox <Button-2> {
    if {!$tk_strictMotif} {
	::tk::EntryScanMark %W %x
    }
}
bind Spinbox <B2-Motion> {
    if {!$tk_strictMotif} {
	::tk::EntryScanDrag %W %x
466
467
468
469
470
471
472
473

474
475
476

477
478
479
480
481
482
483
464
465
466
467
468
469
470

471
472
473

474
475
476
477
478
479
480
481







-
+


-
+







		    $w selection clear
		}
	    }
	}
	word {
	    if {$cur < [$w index anchor]} {
		set before [tcl_wordBreakBefore [$w get] $cur]
		set after [tcl_wordBreakAfter [$w get] [expr {$anchor-1}]]
		set after [tcl_wordBreakAfter [$w get] $anchor-1]
	    } else {
		set before [tcl_wordBreakBefore [$w get] $anchor]
		set after [tcl_wordBreakAfter [$w get] [expr {$cur - 1}]]
		set after [tcl_wordBreakAfter [$w get] $cur-1]
	    }
	    if {$before < 0} {
		set before 0
	    }
	    if {$after < 0} {
		set after end
	    }
572
573
574
575
576
577
578
579

580
570
571
572
573
574
575
576

577
578







-
+

# a spinbox has no -show option to obscure contents.
#
# Arguments:
# w -         The spinbox window from which the text to get

proc ::tk::spinbox::GetSelection {w} {
    return [string range [$w get] [$w index sel.first] \
	    [expr {[$w index sel.last] - 1}]]
	    [$w index sel.last]-1]
}
Added library/systray.tcl.









































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 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 <Any-Enter> "after 1000 [list ::tk::systray::_balloon_show %W [list $help]]"
	bind $w <Any-Leave> "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 <Button-1> event.
#             -button3 - Tcl proc to invoke on <Button-3> 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 <Button-1> event.
#             -button3  - Tcl proc to change for <Button-3> 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 <Button-1> [dict get $values -button1]
		bind ._tray <Button-3> [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 <Button-1> [dict get $args -button1]
		}
		if {[dict exists $args -button3]} {
		    bind ._tray <Button-3> [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
set map [namespace ensemble configure tk -map]
dict set map systray ::tk::systray
dict set map sysnotify ::tk::sysnotify::sysnotify
namespace ensemble configure tk -map $map
Changes to library/tclIndex.
195
196
197
198
199
200
201

202
203
204
205
206
207
208
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209







+







set auto_index(::tk::TextPrevPos) [list source [file join $dir text.tcl]]
set auto_index(::tk::PlaceWindow) [list source [file join $dir tk.tcl]]
set auto_index(::tk::SetFocusGrab) [list source [file join $dir tk.tcl]]
set auto_index(::tk::RestoreFocusGrab) [list source [file join $dir tk.tcl]]
set auto_index(::tk::ScreenChanged) [list source [file join $dir tk.tcl]]
set auto_index(::tk::EventMotifBindings) [list source [file join $dir tk.tcl]]
set auto_index(::tk::CancelRepeat) [list source [file join $dir tk.tcl]]
set auto_index(::tk::MouseWheel) [list source [file join $dir tk.tcl]]
set auto_index(::tk::TabToWindow) [list source [file join $dir tk.tcl]]
set auto_index(::tk::dialog::file::) [list source [file join $dir tkfbox.tcl]]
set auto_index(::tk::dialog::file::Config) [list source [file join $dir tkfbox.tcl]]
set auto_index(::tk::dialog::file::Create) [list source [file join $dir tkfbox.tcl]]
set auto_index(::tk::dialog::file::SetSelectMode) [list source [file join $dir tkfbox.tcl]]
set auto_index(::tk::dialog::file::UpdateWhenIdle) [list source [file join $dir tkfbox.tcl]]
set auto_index(::tk::dialog::file::Update) [list source [file join $dir tkfbox.tcl]]
243
244
245
246
247
248
249
250
251
252
253
244
245
246
247
248
249
250

251
252
253







-



set auto_index(::tk::MotifFDialog_FilterCmd) [list source [file join $dir xmfbox.tcl]]
set auto_index(::tk::MotifFDialog_CancelCmd) [list source [file join $dir xmfbox.tcl]]
set auto_index(::tk::ListBoxKeyAccel_Set) [list source [file join $dir xmfbox.tcl]]
set auto_index(::tk::ListBoxKeyAccel_Unset) [list source [file join $dir xmfbox.tcl]]
set auto_index(::tk::ListBoxKeyAccel_Key) [list source [file join $dir xmfbox.tcl]]
set auto_index(::tk::ListBoxKeyAccel_Goto) [list source [file join $dir xmfbox.tcl]]
set auto_index(::tk::ListBoxKeyAccel_Reset) [list source [file join $dir xmfbox.tcl]]
set auto_index(tk_getFileType) [list source [file join $dir xmfbox.tcl]]
set auto_index(::tk::unsupported::ExposePrivateCommand) [list source [file join $dir unsupported.tcl]]
set auto_index(::tk::unsupported::ExposePrivateVariable) [list source [file join $dir unsupported.tcl]]
set auto_index(::tk::fontchooser) [list source [file join $dir fontchooser.tcl]]
Changes to library/tearoff.tcl.
1
2
3
4
5
6


7
8
9
10
11
12
13
1
2
3
4


5
6
7
8
9
10
11
12
13




-
-
+
+







# tearoff.tcl --
#
# This file contains procedures that implement tear-off menus.
#
# 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.
#

# ::tk::TearoffMenu --
# Given the name of a menu, this procedure creates a torn-off menu
35
36
37
38
39
40
41
42

43
44
45
46
47
48
49
35
36
37
38
39
40
41

42
43
44
45
46
47
48
49







-
+







    }
    if {$y == 0} {
    	set y [winfo rooty $w]
	if {[tk windowingsystem] eq "aqua"} {
	    # Shift by height of tearoff entry minus height of window titlebar
	    catch {incr y [expr {[$w yposition 1] - 16}]}
	    # Avoid the native menu bar which sits on top of everything.
	    if {$y < 22} { set y 22 }
	    if {$y < 22} {set y 22}
	}
    }

    set parent [winfo parent $w]
    while {[winfo toplevel $parent] ne $parent \
	    || [winfo class $parent] eq "Menu"} {
	set parent [winfo parent $parent]
149
150
151
152
153
154
155
156
157
158





159
160
161
162
163
164
165
166
167
168
169
170
171
172




173
174

175
176
177
178
179
180
149
150
151
152
153
154
155



156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172


173
174
175
176
177

178
179
180
181
182
183
184







-
-
-
+
+
+
+
+












-
-
+
+
+
+

-
+






    # Duplicate the binding tags and bindings from the source menu.

    set tags [bindtags $src]
    set srcLen [string length $src]

    # Copy tags to x, replacing each substring of src with dst.

    while {[set index [string first $src $tags]] != -1} {
	append x [string range $tags 0 [expr {$index - 1}]]$dst
	set tags [string range $tags [expr {$index + $srcLen}] end]
    while {[set index [string first $src $tags]] >= 0} {
	if {$index > 0} {
	    append x [string range $tags 0 $index-1]$dst
	}
	set tags [string range $tags $index+$srcLen end]
    }
    append x $tags

    bindtags $dst $x

    foreach event [bind $src] {
	unset x
	set script [bind $src $event]
	set eventLen [string length $event]

	# Copy script to x, replacing each substring of event with dst.

	while {[set index [string first $event $script]] != -1} {
	    append x [string range $script 0 [expr {$index - 1}]]
	while {[set index [string first $event $script]] >= 0} {
	    if {$index > 0} {
		append x [string range $script 0 $index-1]
	    }
	    append x $dst
	    set script [string range $script [expr {$index + $eventLen}] end]
	    set script [string range $script $index+$eventLen end]
	}
	append x $script

	bind $dst $event $x
    }
}
Changes to library/text.tcl.
1
2
3
4
5
6
7
8



9
10
11
12
13
14
15
1
2
3
4
5



6
7
8
9
10
11
12
13
14
15





-
-
-
+
+
+







# text.tcl --
#
# This file defines the default bindings for Tk text widgets and provides
# procedures that help in implementing the bindings.
#
# Copyright (c) 1992-1994 The Regents of the University of California.
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright (c) 1998 by Scriptics Corporation.
# Copyright © 1992-1994 The Regents of the University of California.
# Copyright © 1994-1997 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.
#

#-------------------------------------------------------------------------
# Elements of ::tk::Priv that are used in this file:
38
39
40
41
42
43
44
45

46
47
48
49
50
51
52
53
54

55
56
57
58
59

60
61
62
63
64

65
66
67
68
69

70
71
72
73

74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89

90
91
92
93
94
95
96
97
98

99
100
101
102
103
104
105
38
39
40
41
42
43
44

45
46
47
48
49
50
51
52
53

54
55
56
57
58

59
60
61
62
63

64
65
66
67
68

69
70
71
72

73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88

89
90
91
92
93
94
95
96
97

98
99
100
101
102
103
104
105







-
+








-
+




-
+




-
+




-
+



-
+















-
+








-
+







# The code below creates the default class bindings for text widgets.
#-------------------------------------------------------------------------



# Standard Motif bindings:

bind Text <1> {
bind Text <Button-1> {
    tk::TextButton1 %W %x %y
    %W tag remove sel 0.0 end
}
bind Text <B1-Motion> {
    set tk::Priv(x) %x
    set tk::Priv(y) %y
    tk::TextSelectTo %W %x %y
}
bind Text <Double-1> {
bind Text <Double-Button-1> {
    set tk::Priv(selectMode) word
    tk::TextSelectTo %W %x %y
    catch {%W mark set insert sel.first}
}
bind Text <Triple-1> {
bind Text <Triple-Button-1> {
    set tk::Priv(selectMode) line
    tk::TextSelectTo %W %x %y
    catch {%W mark set insert sel.first}
}
bind Text <Shift-1> {
bind Text <Shift-Button-1> {
    tk::TextResetAnchor %W @%x,%y
    set tk::Priv(selectMode) char
    tk::TextSelectTo %W %x %y
}
bind Text <Double-Shift-1>	{
bind Text <Double-Shift-Button-1>	{
    set tk::Priv(selectMode) word
    tk::TextSelectTo %W %x %y 1
}
bind Text <Triple-Shift-1>	{
bind Text <Triple-Shift-Button-1>	{
    set tk::Priv(selectMode) line
    tk::TextSelectTo %W %x %y
}
bind Text <B1-Leave> {
    set tk::Priv(x) %x
    set tk::Priv(y) %y
    tk::TextAutoScan %W
}
bind Text <B1-Enter> {
    tk::CancelRepeat
}
bind Text <ButtonRelease-1> {
    tk::CancelRepeat
}

bind Text <Control-1> {
bind Text <Control-Button-1> {
    %W mark set insert @%x,%y
    # An operation that moves the insert mark without making it
    # one end of the selection must insert an autoseparator
    if {[%W cget -autoseparators]} {
	%W edit separator
    }
}
# stop an accidental double click triggering <Double-Button-1>
bind Text <Double-Control-1> { # nothing }
bind Text <Double-Control-Button-1> { # nothing }
# stop an accidental movement triggering <B1-Motion>
bind Text <Control-B1-Motion> { # nothing }
bind Text <<PrevChar>> {
    tk::TextSetCursor %W insert-1displayindices
}
bind Text <<NextChar>> {
    tk::TextSetCursor %W insert+1displayindices
288
289
290
291
292
293
294
295

296
297
298
299
300
301

302
303
304
305
306



307
308
309
310

311
312
313
314
315
316
317
318
288
289
290
291
292
293
294

295
296
297
298
299
300

301
302
303



304
305
306
307
308


309

310
311
312
313
314
315
316







-
+





-
+


-
-
-
+
+
+


-
-
+
-







	    || !$tk::Priv(mouseMoved)} {
	tk::TextPasteSelection %W %x %y
    }
}
bind Text <Insert> {
    catch {tk::TextInsert %W [::tk::GetSelection %W PRIMARY]}
}
bind Text <KeyPress> {
bind Text <Key> {
    tk::TextInsert %W %A
}

# Ignore all Alt, Meta, and Control keypresses unless explicitly bound.
# Otherwise, if a widget binding for one of these is defined, the
# <KeyPress> class binding will also fire and insert the character,
# <Key> class binding will also fire and insert the character,
# which is wrong.  Ditto for <Escape>.

bind Text <Alt-KeyPress> {# nothing }
bind Text <Meta-KeyPress> {# nothing}
bind Text <Control-KeyPress> {# nothing}
bind Text <Alt-Key> {# nothing }
bind Text <Meta-Key> {# nothing}
bind Text <Control-Key> {# nothing}
bind Text <Escape> {# nothing}
bind Text <KP_Enter> {# nothing}
if {[tk windowingsystem] eq "aqua"} {
    bind Text <Command-KeyPress> {# nothing}
bind Text <Command-Key> {# nothing}
}

# Additional emacs-like bindings:

bind Text <Control-d> {
    if {!$tk_strictMotif && [%W compare end != insert+1c]} {
	%W delete insert
    }
425
426
427
428
429
430
431
432

433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453




454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469

470
471
472
473
474

475
476

477
478
479
480
481
482
483
484

485
486
487
488
489
490
491
492
493

494
495
496
497
498
499
500

501
502
503
504
505
506
507

508
509
510
511
512
513
514
515
516
423
424
425
426
427
428
429

430
431
432
433
434
435
436
437
438
439
440
441










442
443
444
445
















446





447


448








449









450







451







452


453
454
455
456
457
458
459







-
+











-
-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
+
-
-
+
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
+
-
-








bind Text <Control-h> {
    if {!$tk_strictMotif && [%W compare insert != 1.0]} {
	%W delete insert-1c
	%W see insert
    }
}
bind Text <2> {
bind Text <Button-2> {
    if {!$tk_strictMotif} {
	tk::TextScanMark %W %x %y
    }
}
bind Text <B2-Motion> {
    if {!$tk_strictMotif} {
	tk::TextScanDrag %W %x %y
    }
}
set ::tk::Priv(prevPos) {}

# The MouseWheel will typically only fire on Windows and MacOS X.
# However, someone could use the "event generate" command to produce one
# on other platforms.  We must be careful not to round -ve values of %D
# down to zero.

if {[tk windowingsystem] eq "aqua"} {
    bind Text <MouseWheel> {
        %W yview scroll [expr {-15 * (%D)}] pixels
    }
    bind Text <Option-MouseWheel> {
bind Text <MouseWheel> {
    tk::MouseWheel %W y %D -3.0 pixels
}
bind Text <Option-MouseWheel> {
        %W yview scroll [expr {-150 * (%D)}] pixels
    }
    bind Text <Shift-MouseWheel> {
        %W xview scroll [expr {-15 * (%D)}] pixels
    }
    bind Text <Shift-Option-MouseWheel> {
        %W xview scroll [expr {-150 * (%D)}] pixels
    }
} else {
    # We must make sure that positive and negative movements are rounded
    # equally to integers, avoiding the problem that
    #     (int)1/3 = 0,
    # but
    #     (int)-1/3 = -1
    # The following code ensure equal +/- behaviour.
    bind Text <MouseWheel> {
    tk::MouseWheel %W y %D -0.3 pixels
	if {%D >= 0} {
	    %W yview scroll [expr {-%D/3}] pixels
	} else {
	    %W yview scroll [expr {(2-%D)/3}] pixels
	}
}
    }
    bind Text <Shift-MouseWheel> {
bind Text <Shift-MouseWheel> {
	if {%D >= 0} {
	    %W xview scroll [expr {-%D/3}] pixels
	} else {
	    %W xview scroll [expr {(2-%D)/3}] pixels
	}
    }
}

    tk::MouseWheel %W x %D -3.0 pixels
if {[tk windowingsystem] eq "x11"} {
    # 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/
    bind Text <4> {
	if {!$tk_strictMotif} {
	    %W yview scroll -50 pixels
	}
}
    }
    bind Text <5> {
	if {!$tk_strictMotif} {
	    %W yview scroll 50 pixels
	}
    }
    bind Text <Shift-4> {
bind Text <Shift-Option-MouseWheel> {
	if {!$tk_strictMotif} {
	    %W xview scroll -50 pixels
	}
    }
    bind Text <Shift-5> {
	if {!$tk_strictMotif} {
	    %W xview scroll 50 pixels
    tk::MouseWheel %W x %D -0.3 pixels
	}
    }
}

# ::tk::TextClosestGap --
# Given x and y coordinates, this procedure finds the closest boundary
# between characters to the given coordinates and returns the index
# of the character just after the boundary.
#
554
555
556
557
558
559
560
561
562
563
564
565

566
567
568
569
570
571
572
573
497
498
499
500
501
502
503





504

505
506
507
508
509
510
511







-
-
-
-
-
+
-







    # relative to the gap
    set bbox [$w bbox [$w index $anchorname]]
    if {$x > [lindex $bbox 0]} {
	$w mark gravity $anchorname right
    } else {
	$w mark gravity $anchorname left
    }
    # Allow focus in any case on Windows, because that will let the
    # selection be displayed even for state disabled text widgets.
    if {[tk windowingsystem] eq "win32" \
	    || [$w cget -state] eq "normal"} {
	focus $w
    focus $w
    }
    if {[$w cget -autoseparators]} {
	$w edit separator
    }
}

# ::tk::TextSelectTo --
# This procedure is invoked to extend the selection, typically when
1222
1223
1224
1225
1226
1227
1228
1229





























































































1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
    }
    if {($x != $Priv(x)) || ($y != $Priv(y))} {
	set Priv(mouseMoved) 1
    }
    if {[info exists Priv(mouseMoved)] && $Priv(mouseMoved)} {
	$w scan dragto $x $y
    }
}
# ::tk::TextUndoRedoProcessMarks --
#
# This proc is executed after an undo or redo action.
# It processes the list of undo/redo marks temporarily set in the
# text widget to positions delimiting where changes happened, and
# returns a flat list of ranges. The temporary marks are removed
# from the text widget.
#
# Arguments:
# w -	The text widget

proc ::tk::TextUndoRedoProcessMarks {w} {
    set indices {}
    set undoMarks {}

    # only consider the temporary marks set by an undo/redo action
    foreach mark [$w mark names] {
        if {[string range $mark 0 11] eq "tk::undoMark"} {
            lappend undoMarks $mark
        }
    }

    # transform marks into indices
    # the number of undo/redo marks is always even, each right mark
    # completes a left mark to give a range
    # this is true because:
    #   - undo/redo only deals with insertions and deletions of text
    #   - insertions may move marks but not delete them
    #   - when deleting text, marks located inside the deleted range
    #     are not erased but moved to the start of the deletion range
    #         . this is done in TkBTreeDeleteIndexRange ("This segment
    #           refuses to die...")
    #         . because MarkDeleteProc does nothing else than returning
    #           a value indicating that marks are not deleted by this
    #           deleteProc
    #         . mark deletion rather happen through [.text mark unset xxx]
    #           which was not used _up to this point of the code_ (it
    #           is a bit later just before exiting the present proc)
    set nUndoMarks [llength $undoMarks]
    set n [expr {$nUndoMarks / 2}]
    set undoMarks [lsort -dictionary $undoMarks]
    if {$n > 0} {
	set Lmarks [lrange $undoMarks 0 [expr {$n - 1}]]
    } else {
	set Lmarks {}
    }
    set Rmarks [lrange $undoMarks $n [llength $undoMarks]]
    foreach Lmark $Lmarks Rmark $Rmarks {
        lappend indices [$w index $Lmark] [$w index $Rmark]
        $w mark unset $Lmark $Rmark
    }

    # process ranges to:
    #   - remove those already fully included in another range
    #   - merge overlapping ranges
    set ind [lsort -dictionary -stride 2 $indices]
    set indices {}

    for {set i 0} {$i < $nUndoMarks} {incr i 2} {
        set il1 [lindex $ind $i]
        set ir1 [lindex $ind [expr {$i + 1}]]
        lappend indices $il1 $ir1

        for {set j [expr {$i + 2}]} {$j < $nUndoMarks} {incr j 2} {
            set il2 [lindex $ind $j]
            set ir2 [lindex $ind [expr {$j + 1}]]

            if {[$w compare $il2 > $ir1]} {
                # second range starts after the end of first range
                # -> further second ranges do not need to be considered
                #    because ranges were sorted by increasing first index
                set j $nUndoMarks
            } else {
                if {[$w compare $ir2 > $ir1]} {
                    # second range overlaps first range
                    # -> merge them into a single range
                    set indices [lreplace $indices end-1 end]
                    lappend indices $il1 $ir2
                } else {
                    # second range is fully included in first range
                    # -> ignore it
                }
                # in both cases above, the second range shall be
                # trimmed out from the list of ranges
                set ind [lreplace $ind $j [expr {$j + 1}]]
                incr j -2
                incr nUndoMarks -2
            }
        }
    }

    return $indices
}
Changes to library/tk.tcl.
1
2
3
4
5
6
7
8



9
10
11
12
13
14

15
16
17
18
19
20
21
1
2
3
4
5



6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21





-
-
-
+
+
+





-
+







# tk.tcl --
#
# Initialization script normally executed in the interpreter for each Tk-based
# application.  Arranges class bindings for widgets.
#
# Copyright (c) 1992-1994 The Regents of the University of California.
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-2000 Ajuba Solutions.
# Copyright © 1992-1994 The Regents of the University of California.
# Copyright © 1994-1996 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.

# Verify that we have Tk binary and script components from the same release
package require -exact Tk  8.6.10
package require -exact tk  8.7a4

# Create a ::tk namespace
namespace eval ::tk {
    # Set up the msgcat commands
    namespace eval msgcat {
	namespace export mc mcmax
        if {[interp issafe] || [catch {package require msgcat}]} {
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323















324
325
326
327
328
329
330
302
303
304
305
306
307
308















309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








    if {$name} {
	set op delete
    } else {
	set op add
    }

    event $op <<Cut>> <Control-Key-w> <Control-Lock-Key-W> <Shift-Key-Delete>
    event $op <<Copy>> <Meta-Key-w> <Meta-Lock-Key-W> <Control-Key-Insert>
    event $op <<Paste>> <Control-Key-y> <Control-Lock-Key-Y> <Shift-Key-Insert>
    event $op <<PrevChar>> <Control-Key-b> <Control-Lock-Key-B>
    event $op <<NextChar>> <Control-Key-f> <Control-Lock-Key-F>
    event $op <<PrevLine>> <Control-Key-p> <Control-Lock-Key-P>
    event $op <<NextLine>> <Control-Key-n> <Control-Lock-Key-N>
    event $op <<LineStart>> <Control-Key-a> <Control-Lock-Key-A>
    event $op <<LineEnd>> <Control-Key-e> <Control-Lock-Key-E>
    event $op <<SelectPrevChar>> <Control-Key-B> <Control-Lock-Key-b>
    event $op <<SelectNextChar>> <Control-Key-F> <Control-Lock-Key-f>
    event $op <<SelectPrevLine>> <Control-Key-P> <Control-Lock-Key-p>
    event $op <<SelectNextLine>> <Control-Key-N> <Control-Lock-Key-n>
    event $op <<SelectLineStart>> <Control-Key-A> <Control-Lock-Key-a>
    event $op <<SelectLineEnd>> <Control-Key-E> <Control-Lock-Key-e>
    event $op <<Cut>> <Control-w> <Control-Lock-W> <Shift-Delete>
    event $op <<Copy>> <Meta-w> <Meta-Lock-W> <Control-Insert>
    event $op <<Paste>> <Control-y> <Control-Lock-Y> <Shift-Insert>
    event $op <<PrevChar>> <Control-b> <Control-Lock-B>
    event $op <<NextChar>> <Control-f> <Control-Lock-F>
    event $op <<PrevLine>> <Control-p> <Control-Lock-P>
    event $op <<NextLine>> <Control-n> <Control-Lock-N>
    event $op <<LineStart>> <Control-a> <Control-Lock-A>
    event $op <<LineEnd>> <Control-e> <Control-Lock-E>
    event $op <<SelectPrevChar>> <Control-B> <Control-Lock-b>
    event $op <<SelectNextChar>> <Control-F> <Control-Lock-f>
    event $op <<SelectPrevLine>> <Control-P> <Control-Lock-p>
    event $op <<SelectNextLine>> <Control-N> <Control-Lock-n>
    event $op <<SelectLineStart>> <Control-A> <Control-Lock-a>
    event $op <<SelectLineEnd>> <Control-E> <Control-Lock-e>
}

#----------------------------------------------------------------------
# Define common dialogs on platforms where they are not implemented
# using compiled code.
#----------------------------------------------------------------------

362
363
364
365
366
367
368



369
370
371
372
373



374
375
376


377
378
379
380
381
382


383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403

404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424



425
426
427


428
429
430
431


432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452

453
454
455
456
457



458
459
460
461
462
463
464

465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484








485
486
487
488
489
490
491

492
493
494
495
496
497
498
499
500
501

502
503
504
505
506
507
508
509
510
511
512

513
514
515
516
517
518
519
362
363
364
365
366
367
368
369
370
371
372
373



374
375
376



377
378

379
380
381


382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403

404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422



423
424
425



426
427

428


429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450

451
452
453



454
455
456

457

458
459
460

461


462
463
464
465
466
467
468
469
470
471








472
473
474
475
476
477
478
479
480
481
482
483
484
485

486
487
488
489
490
491
492
493
494
495

496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515







+
+
+


-
-
-
+
+
+
-
-
-
+
+
-



-
-
+
+




















-
+


















-
-
-
+
+
+
-
-
-
+
+
-

-
-
+
+




















-
+


-
-
-
+
+
+
-

-



-
+
-
-










-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+






-
+









-
+











+







    }
}

#----------------------------------------------------------------------
# Define the set of common virtual events.
#----------------------------------------------------------------------

event add <<ContextMenu>>	<Button-3>
event add <<PasteSelection>>	<ButtonRelease-2>

switch -exact -- [tk windowingsystem] {
    "x11" {
	event add <<Cut>>		<Control-Key-x> <Key-F20> <Control-Lock-Key-X>
	event add <<Copy>>		<Control-Key-c> <Key-F16> <Control-Lock-Key-C>
	event add <<Paste>>		<Control-Key-v> <Key-F18> <Control-Lock-Key-V>
	event add <<Cut>>		<Control-x> <F20> <Control-Lock-X>
	event add <<Copy>>		<Control-c> <F16> <Control-Lock-C>
	event add <<Paste>>		<Control-v> <F18> <Control-Lock-V>
	event add <<PasteSelection>>	<ButtonRelease-2>
	event add <<Undo>>		<Control-Key-z> <Control-Lock-Key-Z>
	event add <<Redo>>		<Control-Key-Z> <Control-Lock-Key-z>
	event add <<Undo>>		<Control-z> <Control-Lock-Z>
	event add <<Redo>>		<Control-Z> <Control-Lock-z>
	event add <<ContextMenu>>	<Button-3>
	# 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 <<SelectAll>>		<Control-Key-slash>
	event add <<SelectNone>>	<Control-Key-backslash>
	event add <<SelectAll>>		<Control-/>
	event add <<SelectNone>>	<Control-backslash>
	event add <<NextChar>>		<Right>
	event add <<SelectNextChar>>	<Shift-Right>
	event add <<PrevChar>>		<Left>
	event add <<SelectPrevChar>>	<Shift-Left>
	event add <<NextWord>>		<Control-Right>
	event add <<SelectNextWord>>	<Control-Shift-Right>
	event add <<PrevWord>>		<Control-Left>
	event add <<SelectPrevWord>>	<Control-Shift-Left>
	event add <<LineStart>>		<Home>
	event add <<SelectLineStart>>	<Shift-Home>
	event add <<LineEnd>>		<End>
	event add <<SelectLineEnd>>	<Shift-End>
	event add <<PrevLine>>		<Up>
	event add <<NextLine>>		<Down>
	event add <<SelectPrevLine>>	<Shift-Up>
	event add <<SelectNextLine>>	<Shift-Down>
	event add <<PrevPara>>		<Control-Up>
	event add <<NextPara>>		<Control-Down>
	event add <<SelectPrevPara>>	<Control-Shift-Up>
	event add <<SelectNextPara>>	<Control-Shift-Down>
	event add <<ToggleSelection>>	<Control-ButtonPress-1>
	event add <<ToggleSelection>>	<Control-Button-1>

	# Some OS's define a goofy (as in, not <Shift-Tab>) keysym that is
	# returned when the user presses <Shift-Tab>. In order for tab
	# traversal to work, we have to add these keysyms to the PrevWindow
	# event. We use catch just in case the keysym isn't recognized.

	# This is needed for XFree86 systems
	catch { event add <<PrevWindow>> <ISO_Left_Tab> }
	# This seems to be correct on *some* HP systems.
	catch { event add <<PrevWindow>> <hpBackTab> }

	trace add variable ::tk_strictMotif write ::tk::EventMotifBindings
	set ::tk_strictMotif $::tk_strictMotif
	# On unix, we want to always display entry/text selection,
	# regardless of which window has focus
	set ::tk::AlwaysShowSelection 1
    }
    "win32" {
	event add <<Cut>>		<Control-Key-x> <Shift-Key-Delete> <Control-Lock-Key-X>
	event add <<Copy>>		<Control-Key-c> <Control-Key-Insert> <Control-Lock-Key-C>
	event add <<Paste>>		<Control-Key-v> <Shift-Key-Insert> <Control-Lock-Key-V>
	event add <<Cut>>		<Control-x> <Shift-Delete> <Control-Lock-X>
	event add <<Copy>>		<Control-c> <Control-Insert> <Control-Lock-C>
	event add <<Paste>>		<Control-v> <Shift-Insert> <Control-Lock-V>
	event add <<PasteSelection>>	<ButtonRelease-2>
  	event add <<Undo>>		<Control-Key-z> <Control-Lock-Key-Z>
	event add <<Redo>>		<Control-Key-y> <Control-Lock-Key-Y>
  	event add <<Undo>>		<Control-z> <Control-Lock-Z>
	event add <<Redo>>		<Control-y> <Control-Lock-Y>
	event add <<ContextMenu>>	<Button-3>

	event add <<SelectAll>>		<Control-Key-slash> <Control-Key-a> <Control-Lock-Key-A>
	event add <<SelectNone>>	<Control-Key-backslash>
	event add <<SelectAll>>		<Control-/> <Control-a> <Control-Lock-A>
	event add <<SelectNone>>	<Control-backslash>
	event add <<NextChar>>		<Right>
	event add <<SelectNextChar>>	<Shift-Right>
	event add <<PrevChar>>		<Left>
	event add <<SelectPrevChar>>	<Shift-Left>
	event add <<NextWord>>		<Control-Right>
	event add <<SelectNextWord>>	<Control-Shift-Right>
	event add <<PrevWord>>		<Control-Left>
	event add <<SelectPrevWord>>	<Control-Shift-Left>
	event add <<LineStart>>		<Home>
	event add <<SelectLineStart>>	<Shift-Home>
	event add <<LineEnd>>		<End>
	event add <<SelectLineEnd>>	<Shift-End>
	event add <<PrevLine>>		<Up>
	event add <<NextLine>>		<Down>
	event add <<SelectPrevLine>>	<Shift-Up>
	event add <<SelectNextLine>>	<Shift-Down>
	event add <<PrevPara>>		<Control-Up>
	event add <<NextPara>>		<Control-Down>
	event add <<SelectPrevPara>>	<Control-Shift-Up>
	event add <<SelectNextPara>>	<Control-Shift-Down>
	event add <<ToggleSelection>>	<Control-ButtonPress-1>
	event add <<ToggleSelection>>	<Control-Button-1>
    }
    "aqua" {
	event add <<Cut>>		<Command-Key-x> <Key-F2> <Command-Lock-Key-X>
	event add <<Copy>>		<Command-Key-c> <Key-F3> <Command-Lock-Key-C>
	event add <<Paste>>		<Command-Key-v> <Key-F4> <Command-Lock-Key-V>
	event add <<Cut>>		<Command-x> <F2> <Command-Lock-X>
	event add <<Copy>>		<Command-c> <F3> <Command-Lock-C>
	event add <<Paste>>		<Command-v> <F4> <Command-Lock-V>
	event add <<PasteSelection>>	<ButtonRelease-3>
	event add <<Clear>>		<Clear>
	event add <<ContextMenu>>	<Button-2>

	# Official bindings
	# See http://support.apple.com/kb/HT1343
	event add <<SelectAll>>		<Command-Key-a>
	event add <<SelectAll>>		<Command-a>
	#Attach function keys not otherwise assigned to this event so they no-op - workaround for bug 0e6930dfe7
	event add <<SelectNone>>	<Option-Command-Key-a> <Key-F5> <Key-F1> <Key-F5> <Key-F6> <Key-F7> <Key-F8> <Key-F9> <Key-F10> <Key-F11> <Key-F12>
	event add <<Undo>>		<Command-Key-z> <Command-Lock-Key-Z>
	event add <<Redo>>		<Shift-Command-Key-z> <Shift-Command-Lock-Key-z>
	event add <<NextChar>>		<Right> <Control-Key-f> <Control-Lock-Key-F>
	event add <<SelectNextChar>>	<Shift-Right> <Shift-Control-Key-F> <Shift-Control-Lock-Key-F>
	event add <<PrevChar>>		<Left> <Control-Key-b> <Control-Lock-Key-B>
	event add <<SelectPrevChar>>	<Shift-Left> <Shift-Control-Key-B> <Shift-Control-Lock-Key-B>
	event add <<NextWord>>		<Option-Right>
	event add <<SelectNextWord>>	<Shift-Option-Right>
	event add <<PrevWord>>		<Option-Left>
	event add <<SelectPrevWord>>	<Shift-Option-Left>
	event add <<LineStart>>		<Home> <Command-Left> <Control-Key-a> <Control-Lock-Key-A>
	event add <<SelectLineStart>>	<Shift-Home> <Shift-Command-Left> <Shift-Control-Key-A> <Shift-Control-Lock-Key-A>
	event add <<LineEnd>>		<End> <Command-Right> <Control-Key-e> <Control-Lock-Key-E>
	event add <<SelectLineEnd>>	<Shift-End> <Shift-Command-Right> <Shift-Control-Key-E> <Shift-Control-Lock-Key-E>
	event add <<PrevLine>>		<Up> <Control-Key-p> <Control-Lock-Key-P>
	event add <<SelectPrevLine>>	<Shift-Up> <Shift-Control-Key-P> <Shift-Control-Lock-Key-P>
	event add <<NextLine>>		<Down> <Control-Key-n> <Control-Lock-Key-N>
	event add <<SelectNextLine>>	<Shift-Down> <Shift-Control-Key-N> <Shift-Control-Lock-Key-N>
	event add <<LineStart>>		<Home> <Command-Left> <Control-a> <Control-Lock-A>
	event add <<SelectLineStart>>	<Shift-Home> <Shift-Command-Left> <Shift-Control-A> <Shift-Control-Lock-A>
	event add <<LineEnd>>		<End> <Command-Right> <Control-e> <Control-Lock-E>
	event add <<SelectLineEnd>>	<Shift-End> <Shift-Command-Right> <Shift-Control-E> <Shift-Control-Lock-E>
	event add <<PrevLine>>		<Up> <Control-p> <Control-Lock-P>
	event add <<SelectPrevLine>>	<Shift-Up> <Shift-Control-P> <Shift-Control-Lock-P>
	event add <<NextLine>>		<Down> <Control-n> <Control-Lock-N>
	event add <<SelectNextLine>>	<Shift-Down> <Shift-Control-N> <Shift-Control-Lock-N>
	# Not official, but logical extensions of above. Also derived from
	# bindings present in MS Word on OSX.
	event add <<PrevPara>>		<Option-Up>
	event add <<NextPara>>		<Option-Down>
	event add <<SelectPrevPara>>	<Shift-Option-Up>
	event add <<SelectNextPara>>	<Shift-Option-Down>
	event add <<ToggleSelection>>	<Command-ButtonPress-1>
	event add <<ToggleSelection>>	<Command-Button-1>
    }
}

# ----------------------------------------------------------------------
# Read in files that define all of the class bindings.
# ----------------------------------------------------------------------

if {$::tk_library ne ""} {
    proc ::tk::SourceLibFile {file} {
        namespace eval :: [list source [file join $::tk_library $file.tcl]]
        namespace eval :: [list source -encoding utf-8 [file join $::tk_library $file.tcl]]
    }
    namespace eval ::tk {
	SourceLibFile icons
	SourceLibFile button
	SourceLibFile entry
	SourceLibFile listbox
	SourceLibFile menu
	SourceLibFile panedwindow
	SourceLibFile scale
	SourceLibFile scrlbar
	SourceLibFile spinbox
	SourceLibFile systray
	SourceLibFile text
    }
}

# ----------------------------------------------------------------------
# Default bindings for keyboard traversal.
# ----------------------------------------------------------------------
534
535
536
537
538
539
540







541
542
543
544
545
546
547
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550







+
+
+
+
+
+
+








proc ::tk::CancelRepeat {} {
    variable ::tk::Priv
    after cancel $Priv(afterId)
    set Priv(afterId) {}
}

## ::tk::MouseWheel $w $dir $amount $factor $units

proc ::tk::MouseWheel {w dir amount {factor -120.0} {units units}} {
    $w ${dir}view scroll [expr {$amount/$factor}] $units
}


# ::tk::TabToWindow --
# This procedure moves the focus to the given widget.
# It sends a <<TraverseOut>> virtual event to the previous focus window,
# if any, before changing the focus, and a <<TraverseIn>> event
# to the new focus window afterwards.
#
# Arguments:
625
626
627
628
629
630
631
632
633


634
635
636
637
638
639
640
628
629
630
631
632
633
634


635
636
637
638
639
640
641
642
643







-
-
+
+







    if {$class in {
	Button Checkbutton Label Radiobutton
	TButton TCheckbutton TLabel TRadiobutton
    } && [string equal -nocase $char \
	    [string index [$path cget -text] [$path cget -underline]]]} {
	return $path
    }
    set subwins [concat [grid slaves $path] [pack slaves $path] \
	    [place slaves $path]]
    set subwins [concat [grid content $path] [pack content $path] \
	    [place content $path]]
    if {$class eq "Canvas"} {
	foreach item [$path find all] {
	    if {[$path type $item] eq "window"} {
		set w [$path itemcget $item -window]
		if {$w ne ""} {lappend subwins $w}
	    }
	}
685
686
687
688
689
690
691

692

693
694

695
696
697
698
699
700
701
702
703
704
705
706

707
708
709
710
711
712
688
689
690
691
692
693
694
695

696
697
698
699
700
701
702
703
704
705
706
707
708
709
710

711
712
713
714
715
716
717







+
-
+


+











-
+






    }
}


if {[tk windowingsystem] eq "aqua"} {
    #stub procedures to respond to "do script" Apple Events
    proc ::tk::mac::DoScriptFile {file} {
	uplevel #0 $file
    	source $file
    	source -encoding utf-8 $file
    }
    proc ::tk::mac::DoScriptText {script} {
	uplevel #0 $script
    	eval $script
    }
}

# Create a dictionary to store the starting index of the IME marked
# text in an Entry or Text widget.

set ::tk::Priv(IMETextMark) [dict create]

# Run the Ttk themed widget set initialization
if {$::ttk::library ne ""} {
    uplevel \#0 [list source $::ttk::library/ttk.tcl]
    uplevel \#0 [list source -encoding utf-8 $::ttk::library/ttk.tcl]
}

# Local Variables:
# mode: tcl
# fill-column: 78
# End:
Changes to library/tkfbox.tcl.
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
20












-
+







# tkfbox.tcl --
#
#	Implements the "TK" standard file selection dialog box.  This dialog
#	box is used on the Unix platforms whenever the tk_strictMotif flag is
#	not set.
#
#	The "TK" standard file selection dialog box is similar to the file
#	selection dialog box on Win95(TM).  The user can navigate the
#	directories by clicking on the folder icons or by selecting the
#	"Directory" option menu.  The user can select files by clicking on the
#	file icons or by entering a filename in the "Filename:" entry.
#
# Copyright (c) 1994-1998 Sun Microsystems, Inc.
# 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.
#

namespace eval ::tk::dialog {}
namespace eval ::tk::dialog::file {
459
460
461
462
463
464
465
466

467
468
469
470
471
472
473
459
460
461
462
463
464
465

466
467
468
469
470
471
472
473







-
+








    # Set up the event handlers that are common to Directory and File Dialogs
    #

    wm protocol $w WM_DELETE_WINDOW [list ::tk::dialog::file::CancelCmd $w]
    $data(upBtn)     configure -command [list ::tk::dialog::file::UpDirCmd $w]
    $data(cancelBtn) configure -command [list ::tk::dialog::file::CancelCmd $w]
    bind $w <KeyPress-Escape> [list $data(cancelBtn) invoke]
    bind $w <Escape> [list $data(cancelBtn) invoke]
    bind $w <Alt-Key> [list tk::AltKeyInDialog $w %A]

    # Set up event handlers specific to File or Directory Dialogs
    #
    if {$class eq "TkFDialog"} {
	bind $data(ent) <Return> [list ::tk::dialog::file::ActivateEnt $w]
	$data(okBtn)     configure -command [list ::tk::dialog::file::OkCmd $w]
Changes to library/ttk/aquaTheme.tcl.
11
12
13
14
15
16
17
18

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37






38
39
40
41
42
43
44
45






46
47


48
49
50

51
52









53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119

120
121
122
123
124
125
126
127
128
129
130
11
12
13
14
15
16
17

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44



45
46
47
48
49
50
51
52
53
54


55
56
57
58

59
60

61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86


































87
88
89
90
91
92
93
94
95
96
97
98
99
100
101

102
103
104
105
106
107
108
109
110
111
112
113







-
+



















+
+
+
+
+
+

-
-
-




+
+
+
+
+
+
-
-
+
+


-
+

-
+
+
+
+
+
+
+
+
+

















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-















-
+











	    -foreground systemLabelColor \
	    -selectbackground systemSelectedTextBackgroundColor \
	    -selectforeground systemSelectedTextColor \
	    -selectborderwidth 0 \
	    -insertwidth 1

	ttk::style map . \
	    -foreground { 
	    -foreground {
		disabled systemDisabledControlTextColor
		background systemLabelColor} \
	    -selectbackground {
		background systemSelectedTextBackgroundColor
		!focus systemSelectedTextBackgroundColor} \
	    -selectforeground {
		background systemSelectedTextColor
		!focus systemSelectedTextColor}

	# Button
	ttk::style configure TButton -anchor center -width -6 \
	    -foreground systemControlTextColor
	ttk::style map TButton \
	    -foreground {
		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
	    } \
	    -selectbackground {
		!focus systemUnemphasizedSelectedTextBackgroundColor
	    }

	# Combobox:
	ttk::style map TCombobox \
	    -selectforeground {
		background systemTextColor
	    -foreground {
		disabled systemDisabledControlTextColor
	    } \
	    -selectbackground {
		background systemTextBackgroundColor
		!focus systemUnemphasizedSelectedTextBackgroundColor
	    }
	    

	# Spinbox
	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 {}

	# Notebook
	ttk::style configure TNotebook -tabmargins {10 0} -tabposition n
	ttk::style configure TNotebook -padding {18 8 18 17}
	ttk::style configure TNotebook.Tab -padding {12 3 12 2}
	ttk::style configure TNotebook.Tab -foreground systemControlTextColor
	ttk::style map TNotebook.Tab \
	    -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
	ttk::style configure Treeview -rowheight 18 \
	    -background systemTextBackgroundColor \
	    -foreground systemTextColor \
	    -fieldbackground systemTextBackgroundColor
	ttk::style map Treeview \
	    -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)
	#
	ttk::style configure TLabelframe \
		-labeloutside true -labelmargins {14 0 14 4}

	# TODO: panedwindow sashes should be 9 pixels (HIG:Controls:Split Views)
    }
}
Changes to library/ttk/button.tcl.
1
2
3
4
5
6
7
8
9
10
11
12


13
14
15
16
17
18
19
20
21
22
23

24
25
26

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43


44
45
46


47
48
49
50
51
52
53
1
2
3
4
5
6
7
8
9
10


11
12
13
14
15
16
17
18
19
20
21
22

23
24
25

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41


42
43
44


45
46
47
48
49
50
51
52
53










-
-
+
+










-
+


-
+















-
-
+
+

-
-
+
+







#
# Bindings for Buttons, Checkbuttons, and Radiobuttons.
#
# Notes: <Button1-Leave>, <Button1-Enter> only control the "pressed"
# state; widgets remain "active" if the pointer is dragged out.
# This doesn't seem to be conventional, but it's a nice way
# to provide extra feedback while the grab is active.
# (If the button is released off the widget, the grab deactivates and
# we get a <Leave> event then, which turns off the "active" state)
#
# Normally, <ButtonRelease> and <ButtonN-Enter/Leave> events are 
# delivered to the widget which received the initial <ButtonPress>
# Normally, <ButtonRelease> and <ButtonN-Enter/Leave> events are
# delivered to the widget which received the initial <Button>
# event.  However, Tk [grab]s (#1223103) and menu interactions
# (#1222605) can interfere with this.  To guard against spurious
# <Button1-Enter> events, the <Button1-Enter> binding only sets
# the pressed state if the button is currently active.
#

namespace eval ttk::button {}

bind TButton <Enter> 		{ %W instate !disabled {%W state active} }
bind TButton <Leave>		{ %W state !active }
bind TButton <Key-space>	{ ttk::button::activate %W }
bind TButton <space>		{ ttk::button::activate %W }
bind TButton <<Invoke>> 	{ ttk::button::activate %W }

bind TButton <ButtonPress-1> \
bind TButton <Button-1> \
    { %W instate !disabled { ttk::clickToFocus %W; %W state pressed } }
bind TButton <ButtonRelease-1> \
    { %W instate pressed { %W state !pressed; %W instate !disabled { %W invoke } } }
bind TButton <Button1-Leave> \
    { %W state !pressed }
bind TButton <Button1-Enter> \
    { %W instate {active !disabled} { %W state pressed } }

# Checkbuttons and Radiobuttons have the same bindings as Buttons:
#
ttk::copyBindings TButton TCheckbutton
ttk::copyBindings TButton TRadiobutton

# ...plus a few more:

bind TRadiobutton <KeyPress-Up> 	{ ttk::button::RadioTraverse %W -1 }
bind TRadiobutton <KeyPress-Down> 	{ ttk::button::RadioTraverse %W +1 }
bind TRadiobutton <Up>  		{ ttk::button::RadioTraverse %W -1 }
bind TRadiobutton <Down> 		{ ttk::button::RadioTraverse %W +1 }

# bind TCheckbutton <KeyPress-plus> { %W select }
# bind TCheckbutton <KeyPress-minus> { %W deselect }
# bind TCheckbutton <+> { %W select }
# bind TCheckbutton <minus> { %W deselect }

# activate --
#	Simulate a button press: temporarily set the state to 'pressed',
#	then invoke the button.
#
proc ttk::button::activate {w} {
    $w instate disabled { return }
Changes to library/ttk/clamTheme.tcl.
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







#
# "Clam" theme.
#
# Inspired by the XFCE family of Gnome themes.
#

namespace eval ttk::theme::clam {
    variable colors 
    variable colors
    array set colors {
	-disabledfg		"#999999"
	-frame  		"#dcdad5"
	-window  		"#ffffff"
	-dark			"#cfcdc8"
	-darker 		"#bab5ab"
	-darkest		"#9e9a91"
Changes to library/ttk/combobox.tcl.
41
42
43
44
45
46
47
48
49


50
51
52
53
54




55
56
57
58
59
60
61
62
63
64
65
66
67



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85

86
87
88
89
90
91
92
41
42
43
44
45
46
47


48
49
50




51
52
53
54
55
56
57
58
59
60
61
62
63
64



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84

85
86
87
88
89
90
91
92







-
-
+
+

-
-
-
-
+
+
+
+










-
-
-
+
+
+

















-
+







### Combobox bindings.
#
# Duplicate the Entry bindings, override if needed:
#

ttk::copyBindings TEntry TCombobox

bind TCombobox <KeyPress-Down> 		{ ttk::combobox::Post %W }
bind TCombobox <KeyPress-Escape> 	{ ttk::combobox::Unpost %W }
bind TCombobox <Down> 			{ ttk::combobox::Post %W }
bind TCombobox <Escape> 		{ ttk::combobox::Unpost %W }

bind TCombobox <ButtonPress-1> 		{ ttk::combobox::Press "" %W %x %y }
bind TCombobox <Shift-ButtonPress-1>	{ ttk::combobox::Press "s" %W %x %y }
bind TCombobox <Double-ButtonPress-1> 	{ ttk::combobox::Press "2" %W %x %y }
bind TCombobox <Triple-ButtonPress-1> 	{ ttk::combobox::Press "3" %W %x %y }
bind TCombobox <Button-1> 		{ ttk::combobox::Press "" %W %x %y }
bind TCombobox <Shift-Button-1>		{ ttk::combobox::Press "s" %W %x %y }
bind TCombobox <Double-Button-1> 	{ ttk::combobox::Press "2" %W %x %y }
bind TCombobox <Triple-Button-1> 	{ ttk::combobox::Press "3" %W %x %y }
bind TCombobox <B1-Motion>		{ ttk::combobox::Drag %W %x }
bind TCombobox <Motion>			{ ttk::combobox::Motion %W %x %y }

ttk::bindMouseWheel TCombobox [list ttk::combobox::Scroll %W]

bind TCombobox <<TraverseIn>> 		{ ttk::combobox::TraverseIn %W }

### Combobox listbox bindings.
#
bind ComboboxListbox <ButtonRelease-1>	{ ttk::combobox::LBSelected %W }
bind ComboboxListbox <KeyPress-Return>	{ ttk::combobox::LBSelected %W }
bind ComboboxListbox <KeyPress-Escape>  { ttk::combobox::LBCancel %W }
bind ComboboxListbox <KeyPress-Tab>	{ ttk::combobox::LBTab %W next }
bind ComboboxListbox <Return>		{ ttk::combobox::LBSelected %W }
bind ComboboxListbox <Escape>		{ ttk::combobox::LBCancel %W }
bind ComboboxListbox <Tab>		{ ttk::combobox::LBTab %W next }
bind ComboboxListbox <<PrevWindow>>	{ ttk::combobox::LBTab %W prev }
bind ComboboxListbox <Destroy>		{ ttk::combobox::LBCleanup %W }
bind ComboboxListbox <Motion>		{ ttk::combobox::LBHover %W %x %y }
bind ComboboxListbox <Map>		{ focus -force %W }

switch -- [tk windowingsystem] {
    win32 {
	# Dismiss listbox when user switches to a different application.
	# NB: *only* do this on Windows (see #1814778)
	bind ComboboxListbox <FocusOut>		{ ttk::combobox::LBCancel %W }
    }
}

### Combobox popdown window bindings.
#
bind ComboboxPopdown	<Map>		{ ttk::combobox::MapPopdown %W }
bind ComboboxPopdown	<Unmap>		{ ttk::combobox::UnmapPopdown %W }
bind ComboboxPopdown	<ButtonPress> \
bind ComboboxPopdown	<Button> \
			{ ttk::combobox::Unpost [winfo parent %W] }

### Option database settings.
#

option add *TCombobox*Listbox.font TkTextFont widgetDefault
option add *TCombobox*Listbox.relief flat widgetDefault
102
103
104
105
106
107
108
109

110
111
112
113
114
115
116
102
103
104
105
106
107
108

109
110
111
112
113
114
115
116







-
+







	option add *TCombobox*Listbox.borderWidth 0 widgetDefault
    }
}

### Binding procedures.
#

## Press $mode $x $y -- ButtonPress binding for comboboxes.
## Press $mode $x $y -- Button binding for comboboxes.
#	Either post/unpost the listbox, or perform Entry widget binding,
#	depending on widget state and location of button press.
#
proc ttk::combobox::Press {mode w x y} {
    variable State

    $w instate disabled { return }
131
132
133
134
135
136
137
138

139
140
141
142
143
144
145
131
132
133
134
135
136
137

138
139
140
141
142
143
144
145







-
+







	}
    } else {
	Post $w
    }
}

## Drag -- B1-Motion binding for comboboxes.
#	If the initial ButtonPress event was handled by Entry binding,
#	If the initial Button event was handled by Entry binding,
#	perform Entry widget drag binding; otherwise nothing.
#
proc ttk::combobox::Drag {w x}  {
    variable State
    if {$State(entryPress)} {
	ttk::entry::Drag $w $x
    }
178
179
180
181
182
183
184
185

186
187
188
189
190
191










192
193
194
195
196
197
198
199
200

201
202
203
204
205
206
207
208
209
210

211
212
213
214
215
216
217

218
219
220
221
222
223
224
178
179
180
181
182
183
184

185
186
187
188



189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206

207
208
209
210
211
212
213
214
215
216

217
218
219
220
221
222
223

224
225
226
227
228
229
230
231







-
+



-
-
-
+
+
+
+
+
+
+
+
+
+








-
+









-
+






-
+







    $cb selection range 0 end
    $cb icursor end
    event generate $cb <<ComboboxSelected>> -when mark
}

## Scroll -- Mousewheel binding
#
proc ttk::combobox::Scroll {cb dir} {
proc ttk::combobox::Scroll {cb dir {factor 1.0}} {
    $cb instate disabled { return }
    set max [llength [$cb cget -values]]
    set current [$cb current]
    incr current $dir
    if {$max != 0 && $current == $current % $max} {
	SelectEntry $cb $current
    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}
    }
    if {$max != 0 && $index != $current} {
	SelectEntry $cb $index
    }
}

## LBSelected $lb -- Activation binding for listbox
#	Set the combobox value to the currently-selected listbox value
#	and unpost the listbox.
#
proc ttk::combobox::LBSelected {lb} {
    set cb [LBMaster $lb]
    set cb [LBMain $lb]
    LBSelect $lb
    Unpost $cb
    focus $cb
}

## LBCancel --
#	Unpost the listbox.
#
proc ttk::combobox::LBCancel {lb} {
    Unpost [LBMaster $lb]
    Unpost [LBMain $lb]
}

## LBTab -- Tab key binding for combobox listbox.
#	Set the selection, and navigate to next/prev widget.
#
proc ttk::combobox::LBTab {lb dir} {
    set cb [LBMaster $lb]
    set cb [LBMain $lb]
    switch -- $dir {
	next	{ set newFocus [tk_focusNext $cb] }
	prev	{ set newFocus [tk_focusPrev $cb] }
    }

    if {$newFocus ne ""} {
	LBSelect $lb
353
354
355
356
357
358
359



360
361
362
363
364
365
366
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376







+
+
+







#
proc ttk::combobox::PlacePopdown {cb popdown} {
    set x [winfo rootx $cb]
    set y [winfo rooty $cb]
    set w [winfo width $cb]
    set h [winfo height $cb]
    set style [$cb cget -style]
    if { $style eq {} } {
      set style TCombobox
    }
    set postoffset [ttk::style lookup $style -postoffset {} {0 0 0 0}]
    foreach var {x y w h} delta $postoffset {
    	incr $var $delta
    }

    set H [winfo reqheight $popdown]
    if {$y + $h + $H > [winfo screenheight $popdown]} {
407
408
409
410
411
412
413
414

415
416
417

418
419
420
421
422
423
424
425

426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442

443
444
445
417
418
419
420
421
422
423

424
425
426

427
428
429
430
431
432
433
434

435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451

452
453
454
455







-
+


-
+







-
+
















-
+



proc ttk::combobox::Unpost {cb} {
    if {[winfo exists $cb.popdown]} {
	wm withdraw $cb.popdown
    }
    grab release $cb.popdown ;# in case of stuck or unexpected grab [#1239190]
}

## LBMaster $lb --
## LBMain $lb --
#	Return the combobox main widget that owns the listbox.
#
proc ttk::combobox::LBMaster {lb} {
proc ttk::combobox::LBMain {lb} {
    winfo parent [winfo parent [winfo parent $lb]]
}

## LBSelect $lb --
#	Transfer listbox selection to combobox value.
#
proc ttk::combobox::LBSelect {lb} {
    set cb [LBMaster $lb]
    set cb [LBMain $lb]
    set selection [$lb curselection]
    if {[llength $selection] == 1} {
	SelectEntry $cb [lindex $selection 0]
    }
}

## LBCleanup $lb --
#	<Destroy> binding for combobox listboxes.
#	Cleans up by unsetting the linked textvariable.
#
#	Note: we can't just use { unset [%W cget -listvariable] }
#	because the widget command is already gone when this binding fires).
#	[winfo parent] still works, fortunately.
#
proc ttk::combobox::LBCleanup {lb} {
    variable Values
    unset Values([LBMaster $lb])
    unset Values([LBMain $lb])
}

#*EOF*
Changes to library/ttk/cursors.tcl.
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110







111
112
113
114
115
116
117






118
119
120
121
122
123
124
125
95
96
97
98
99
100
101









102
103
104
105
106
107
108
109






110
111
112
113
114
115

116
117
118
119
120
121
122







-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+
-








		neresize	size_ne_sw
		seresize	size_nw_se
	    }
	}

	"aqua" {
	    if {[package vsatisfies [package provide Tk] 8.5]} {
		# appeared 2007-04-23, Tk 8.5a6
		array set Cursors {
		    standard	arrow
		    text 	ibeam
		    link	pointinghand
		    crosshair	crosshair
		    busy	watch
		    forbidden	notallowed
	    array set Cursors {
		standard	arrow
		text 	ibeam
		link	pointinghand
		crosshair	crosshair
		busy	watch
		forbidden	notallowed

		    hresize 	resizeleftright
		    vresize 	resizeupdown
		    nresize	resizeup
		    sresize	resizedown
		    wresize	resizeleft
		    eresize	resizeright
		hresize 	resizeleftright
		vresize 	resizeupdown
		nresize	resizeup
		sresize	resizedown
		wresize	resizeleft
		eresize	resizeright
		}
	    }
	}
    }
}

## ttk::cursor $cursor --
#	Return platform-specific cursor for specified symbolic cursor.
197
198
199
200
201
202
203
204

205
206
207
208
194
195
196
197
198
199
200

201
202
203
204
205







-
+





    return $f
}

if {[info exists argv0] && $argv0 eq [info script]} {
    wm title . "[array size ::ttk::Cursors] cursors"
    pack [ttk::CursorSampler .f] -expand true -fill both
    bind . <KeyPress-Escape> [list destroy .]
    bind . <Escape> [list destroy .]
    focus .f
}

#*EOF*
Changes to library/ttk/defaults.tcl.
39
40
41
42
43
44
45
46

47
48
49
50
51
52
53
39
40
41
42
43
44
45

46
47
48
49
50
51
52
53







-
+







	    [list disabled $colors(-frame)  active $colors(-activebg)]
	ttk::style map "." -foreground \
	    [list disabled $colors(-disabledfg)]

	ttk::style configure TButton \
	    -anchor center -padding "3 3" -width -9 \
	    -relief raised -shiftrelief 1
	ttk::style map TButton -relief [list {!disabled pressed} sunken] 
	ttk::style map TButton -relief [list {!disabled pressed} sunken]

	ttk::style configure TCheckbutton \
	    -indicatorcolor "#ffffff" -indicatorrelief sunken -padding 1
	ttk::style map TCheckbutton -indicatorcolor \
	    [list pressed $colors(-activebg)  \
			{!disabled alternate} $colors(-altindicator) \
			{disabled alternate} $colors(-disabledaltindicator) \
Changes to library/ttk/entry.tcl.
1
2
3
4
5
6



7
8
9
10
11
12
13
1
2
3



4
5
6
7
8
9
10
11
12
13



-
-
-
+
+
+







#
# DERIVED FROM: tk/library/entry.tcl r1.22
#
# Copyright (c) 1992-1994 The Regents of the University of California.
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright (c) 2004, Joe English
# Copyright © 1992-1994 The Regents of the University of California.
# Copyright © 1994-1997 Sun Microsystems, Inc.
# Copyright © 2004, Joe English
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#

namespace eval ttk {
    namespace eval entry {
36
37
38
39
40
41
42
43
44


45
46

47
48
49

50
51
52


53
54
55
56

57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74




75
76
77
78
79



80
81
82
83
84
85
86
87


88
89

90
91
92
93
94
95
96
36
37
38
39
40
41
42


43
44
45

46
47
48

49
50


51
52
53
54
55

56
57
58
59
60
61
62
63
64
65
66
67
68
69
70




71
72
73
74
75
76



77
78
79
80
81
82
83
84
85
86

87
88
89

90
91
92
93
94
95
96
97







-
-
+
+

-
+


-
+

-
-
+
+



-
+














-
-
-
-
+
+
+
+


-
-
-
+
+
+







-
+
+

-
+







#
option add *TEntry.cursor [ttk::cursor text] widgetDefault

### Bindings.
#
# Removed the following standard Tk bindings:
#
# <Control-Key-space>, <Control-Shift-Key-space>,
# <Key-Select>,  <Shift-Key-Select>:
# <Control-space>, <Control-Shift-space>,
# <Select>,  <Shift-Select>:
#	Ttk entry widget doesn't use selection anchor.
# <Key-Insert>:
# <Insert>:
#	Inserts PRIMARY selection (on non-Windows platforms).
#	This is inconsistent with typical platform bindings.
# <Double-Shift-ButtonPress-1>, <Triple-Shift-ButtonPress-1>:
# <Double-Shift-Button-1>, <Triple-Shift-Button-1>:
#	These don't do the right thing to start with.
# <Meta-Key-b>, <Meta-Key-d>, <Meta-Key-f>,
# <Meta-Key-BackSpace>, <Meta-Key-Delete>:
# <Meta-b>, <Meta-d>, <Meta-f>,
# <Meta-BackSpace>, <Meta-Delete>:
#	Judgment call.  If <Meta> happens to be assigned to the Alt key,
#	these could conflict with application accelerators.
#	(Plus, who has a Meta key these days?)
# <Control-Key-t>:
# <Control-t>:
#	Another judgment call.  If anyone misses this, let me know
#	and I'll put it back.
#

## Clipboard events:
#
bind TEntry <<Cut>> 			{ ttk::entry::Cut %W }
bind TEntry <<Copy>> 			{ ttk::entry::Copy %W }
bind TEntry <<Paste>> 			{ ttk::entry::Paste %W }
bind TEntry <<Clear>> 			{ ttk::entry::Clear %W }

## Button1 bindings:
#	Used for selection and navigation.
#
bind TEntry <ButtonPress-1> 		{ ttk::entry::Press %W %x }
bind TEntry <Shift-ButtonPress-1>	{ ttk::entry::Shift-Press %W %x }
bind TEntry <Double-ButtonPress-1> 	{ ttk::entry::Select %W %x word }
bind TEntry <Triple-ButtonPress-1> 	{ ttk::entry::Select %W %x line }
bind TEntry <Button-1> 			{ ttk::entry::Press %W %x }
bind TEntry <Shift-Button-1>		{ ttk::entry::Shift-Press %W %x }
bind TEntry <Double-Button-1> 		{ ttk::entry::Select %W %x word }
bind TEntry <Triple-Button-1> 		{ ttk::entry::Select %W %x line }
bind TEntry <B1-Motion>			{ ttk::entry::Drag %W %x }

bind TEntry <B1-Leave> 		{ ttk::entry::DragOut %W %m }
bind TEntry <B1-Enter>		{ ttk::entry::DragIn %W }
bind TEntry <ButtonRelease-1>	{ ttk::entry::Release %W }
bind TEntry <B1-Leave> 			{ ttk::entry::DragOut %W %m }
bind TEntry <B1-Enter>			{ ttk::entry::DragIn %W }
bind TEntry <ButtonRelease-1>		{ ttk::entry::Release %W }

bind TEntry <<ToggleSelection>> {
    %W instate {!readonly !disabled} { %W icursor @%x ; focus %W }
}

## Button2 bindings:
#	Used for scanning and primary transfer.
#	Note: ButtonRelease-2 is mapped to <<PasteSelection>> in tk.tcl.
#	Note: ButtonRelease-2
#	is mapped to <<PasteSelection>> in tk.tcl.
#
bind TEntry <ButtonPress-2> 		{ ttk::entry::ScanMark %W %x }
bind TEntry <Button-2> 			{ ttk::entry::ScanMark %W %x }
bind TEntry <B2-Motion> 		{ ttk::entry::ScanDrag %W %x }
bind TEntry <ButtonRelease-2>		{ ttk::entry::ScanRelease %W %x }
bind TEntry <<PasteSelection>>		{ ttk::entry::ScanRelease %W %x }

## Keyboard navigation bindings:
#
bind TEntry <<PrevChar>>		{ ttk::entry::Move %W prevchar }
110
111
112
113
114
115
116
117
118
119



120
121
122

123
124
125
126
127
128
129
130
131







132
133
134
135
136
137


138
139
140
141
142
143
144
145
146



147
148
149
150
151
152
153
111
112
113
114
115
116
117



118
119
120
121
122

123
124
125







126
127
128
129
130
131
132






133
134
135
136
137
138
139
140



141
142
143
144
145
146
147
148
149
150







-
-
-
+
+
+


-
+


-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+






-
-
-
+
+
+







bind TEntry <<SelectAll>> 		{ %W selection range 0 end }
bind TEntry <<SelectNone>> 		{ %W selection clear }

bind TEntry <<TraverseIn>> 	{ %W selection range 0 end; %W icursor end }

## Edit bindings:
#
bind TEntry <KeyPress> 			{ ttk::entry::Insert %W %A }
bind TEntry <Key-Delete>		{ ttk::entry::Delete %W }
bind TEntry <Key-BackSpace> 		{ ttk::entry::Backspace %W }
bind TEntry <Key> 			{ ttk::entry::Insert %W %A }
bind TEntry <Delete>			{ ttk::entry::Delete %W }
bind TEntry <BackSpace> 		{ ttk::entry::Backspace %W }

# Ignore all Alt, Meta, and Control keypresses unless explicitly bound.
# Otherwise, the <KeyPress> class binding will fire and insert the character.
# Otherwise, the <Key> class binding will fire and insert the character.
# Ditto for Escape, Return, and Tab.
#
bind TEntry <Alt-KeyPress>		{# nothing}
bind TEntry <Meta-KeyPress>		{# nothing}
bind TEntry <Control-KeyPress> 		{# nothing}
bind TEntry <Key-Escape> 		{# nothing}
bind TEntry <Key-Return> 		{# nothing}
bind TEntry <Key-KP_Enter> 		{# nothing}
bind TEntry <Key-Tab> 			{# nothing}
bind TEntry <Alt-Key>			{# nothing}
bind TEntry <Meta-Key>			{# nothing}
bind TEntry <Control-Key> 		{# nothing}
bind TEntry <Escape> 			{# nothing}
bind TEntry <Return> 			{# nothing}
bind TEntry <KP_Enter> 			{# nothing}
bind TEntry <Tab> 			{# nothing}

# Argh.  Apparently on Windows, the NumLock modifier is interpreted
# as a Command modifier.
if {[tk windowingsystem] eq "aqua"} {
    bind TEntry <Command-KeyPress>	{# nothing}
}
bind TEntry <Command-Key>		{# nothing}

# Tk-on-Cocoa generates characters for these two keys. [Bug 2971663]
bind TEntry <<PrevLine>>		{# nothing}
bind TEntry <<NextLine>>		{# nothing}

## Additional emacs-like bindings:
#
bind TEntry <Control-Key-d>		{ ttk::entry::Delete %W }
bind TEntry <Control-Key-h>		{ ttk::entry::Backspace %W }
bind TEntry <Control-Key-k>		{ %W delete insert end }
bind TEntry <Control-d>			{ ttk::entry::Delete %W }
bind TEntry <Control-h>			{ ttk::entry::Backspace %W }
bind TEntry <Control-k>			{ %W delete insert end }

# Bindings for IME text input.

bind TEntry <<TkStartIMEMarkedText>> {
    dict set ::tk::Priv(IMETextMark) "%W" [%W index insert]
}
bind TEntry <<TkEndIMEMarkedText>> {
168
169
170
171
172
173
174
175

176
177
178
179
180
181
182
165
166
167
168
169
170
171

172
173
174
175
176
177
178
179







-
+







#

## EntrySelection -- Return the selected text of the entry.
#	Raises an error if there is no selection.
#
proc ttk::entry::EntrySelection {w} {
    set entryString [string range [$w get] [$w index sel.first] \
	    [expr {[$w index sel.last] - 1}]]
	    [$w index sel.last]-1]
    if {[$w cget -show] ne ""} {
	return [string repeat [string index [$w cget -show] 0] \
		[string length $entryString]]
    }
    return $entryString
}

347
348
349
350
351
352
353
354

355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

372
373
374
375
376
377
378
344
345
346
347
348
349
350

351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367

368
369
370
371
372
373
374
375







-
+
















-
+








### Button 1 binding procedures.
#
# Double-clicking followed by a drag enters "word-select" mode.
# Triple-clicking enters "line-select" mode.
#

## Press -- ButtonPress-1 binding.
## Press -- Button-1 binding.
#	Set the insertion cursor, claim the input focus, set up for
#	future drag operations.
#
proc ttk::entry::Press {w x} {
    variable State

    $w icursor [ClosestGap $w $x]
    $w selection clear
    $w instate !disabled { focus $w }

    # Set up for future drag, double-click, or triple-click.
    set State(x) $x
    set State(selectMode) char
    set State(anchor) [$w index insert]
}

## Shift-Press -- Shift-ButtonPress-1 binding.
## Shift-Press -- Shift-Button-1 binding.
#	Extends the selection, sets anchor for future drag operations.
#
proc ttk::entry::Shift-Press {w x} {
    variable State

    focus $w
    set anchor [ExtendTo $w @$x]
513
514
515
516
517
518
519
520

521
522
523
524
525
526
527
510
511
512
513
514
515
516

517
518
519
520
521
522
523
524







-
+







    $w selection range 0 end
    $w icursor end
}

### Button 2 binding procedures.
#

## ScanMark -- ButtonPress-2 binding.
## ScanMark -- Button-2 binding.
#	Marks the start of a scan or primary transfer operation.
#
proc ttk::entry::ScanMark {w x} {
    variable State
    set State(scanX) $x
    set State(scanIndex) [$w index @0]
    set State(scanMoved) 0
Changes to library/ttk/fonts.tcl.
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
49
50
51
52
53
54
55




56
57
58
59
60
61
62







-
-
-
-







#	For now, assume patch #971980 applied.
#
#	"Classic" look used Helvetica bold for everything except
#	for entry widgets, which use Helvetica medium.
#	Most other toolkits use medium weight for all UI elements,
#	which is what we do now.
#
#	Font size specified in pixels on X11, not points.
#	This is Theoretically Wrong, but in practice works better; using
#	points leads to huge inconsistencies across different servers.
#

namespace eval ttk {

variable tip145 [catch {font create TkDefaultFont}]
catch {font create TkTextFont}
catch {font create TkHeadingFont}
catch {font create TkCaptionFont}
78
79
80
81
82
83
84
85

86
87
88
89
90
91
92
74
75
76
77
78
79
80

81
82
83
84
85
86
87
88







-
+







	if {[info exists tcl_platform(osVersion)]} {
            if {$tcl_platform(osVersion) >= 5.0} {
                set F(family) "Tahoma"
            } else {
                set F(family) "MS Sans Serif"
            }
        } else {
            if {[lsearch -exact [font families] Tahoma] != -1} {
            if {[lsearch -exact [font families] Tahoma] >= 0} {
                set F(family) "Tahoma"
            } else {
                set F(family) "MS Sans Serif"
            }
        }
	set F(size) 8

127
128
129
130
131
132
133
134
135
136
137




138
139
140
141
142
143
144
123
124
125
126
127
128
129




130
131
132
133
134
135
136
137
138
139
140







-
-
-
-
+
+
+
+







	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) -12
	set F(ttsize) -10
	set F(capsize) -14
	set F(fixedsize) -12
	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
Changes to library/ttk/menubutton.tcl.
1
2
3
4
5
6
7
8

9
10
11
12
13

14
15
16
17
18
19
20
21
22

23
24
25

26
27
28

29
30
31

32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

50
51
52
53

54
55
56
57

58
59
60
61
62
63
64
1
2
3
4
5
6
7

8
9
10
11
12

13
14
15
16
17
18
19
20
21

22
23
24

25
26
27

28
29
30

31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

49
50
51
52

53
54
55
56

57
58
59
60
61
62
63
64







-
+




-
+








-
+


-
+


-
+


-
+

















-
+



-
+



-
+







#
# Bindings for Menubuttons.
#
# Menubuttons have three interaction modes:
#
# Pulldown: Press menubutton, drag over menu, release to activate menu entry
# Popdown: Click menubutton to post menu
# Keyboard: <Key-space> or accelerator key to post menu
# Keyboard: <space> or accelerator key to post menu
#
# (In addition, when menu system is active, "dropdown" -- menu posts
# on mouse-over.  Ttk menubuttons don't implement this).
#
# For keyboard and popdown mode, we hand off to tk_popup and let 
# For keyboard and popdown mode, we hand off to tk_popup and let
# the built-in Tk bindings handle the rest of the interaction.
#
# ON X11:
#
# Standard Tk menubuttons use a global grab on the menubutton.
# This won't work for Ttk menubuttons in pulldown mode,
# since we need to process the final <ButtonRelease> event,
# and this might be delivered to the menu.  So instead we
# rely on the passive grab that occurs on <ButtonPress> events,
# rely on the passive grab that occurs on <Button> events,
# and transition to popdown mode when the mouse is released
# or dragged outside the menubutton.
# 
#
# ON WINDOWS:
#
# I'm not sure what the hell is going on here.  [$menu post] apparently 
# I'm not sure what the hell is going on here.  [$menu post] apparently
# sets up some kind of internal grab for native menus.
# On this platform, just use [tk_popup] for all menu actions.
# 
#
# ON MACOS:
#
# Same probably applies here.
#

namespace eval ttk {
    namespace eval menubutton {
	variable State
	array set State {
	    pulldown	0
	    oldcursor	{}
	}
    }
}

bind TMenubutton <Enter>	{ %W instate !disabled {%W state active } }
bind TMenubutton <Leave>	{ %W state !active }
bind TMenubutton <Key-space> 	{ ttk::menubutton::Popdown %W }
bind TMenubutton <space>	{ ttk::menubutton::Popdown %W }
bind TMenubutton <<Invoke>> 	{ ttk::menubutton::Popdown %W }

if {[tk windowingsystem] eq "x11"} {
    bind TMenubutton <ButtonPress-1>  	{ ttk::menubutton::Pulldown %W }
    bind TMenubutton <Button-1>  	{ ttk::menubutton::Pulldown %W }
    bind TMenubutton <ButtonRelease-1>	{ ttk::menubutton::TransferGrab %W }
    bind TMenubutton <B1-Leave> 	{ ttk::menubutton::TransferGrab %W }
} else {
    bind TMenubutton <ButtonPress-1>  \
    bind TMenubutton <Button-1>  \
	{ %W state pressed ; ttk::menubutton::Popdown %W }
    bind TMenubutton <ButtonRelease-1>  \
	{ if {[winfo exists %W]} { %W state !pressed } }
}

# PostPosition --
#	Returns x and y coordinates and a menu item index.
93
94
95
96
97
98
99
100

101
102
103
104
105
106
107
108

109
110
111
112
113
114
115
93
94
95
96
97
98
99

100
101
102
103
104
105
106
107

108
109
110
111
112
113
114
115







-
+







-
+







	switch [$mb cget -direction] {
	    above {
		set entry ""
		incr y [expr {-$mh + 2 * $menuPad}]
	    }
	    below {
		set entry ""
		incr y $bh 
		incr y $bh
	    }
	    left {
		incr y $menuPad
		incr x -$mw
	    }
	    right {
		incr y $menuPad
		incr x $bw 
		incr x $bw
	    }
	    default {
		incr y $bbh
	    }
	}
	return [list $x $y $entry]
    }
178
179
180
181
182
183
184
185

186
187
188
189
190
191
192
178
179
180
181
182
183
184

185
186
187
188
189
190
191
192







-
+







    }
    foreach {x y entry} [PostPosition $mb $menu] { break }
    tk_popup $menu $x $y $entry
}

# Pulldown (X11 only) --
#	Called when Button1 is pressed on a menubutton.
#	Posts the menu; a subsequent ButtonRelease 
#	Posts the menu; a subsequent ButtonRelease
#	or Leave event will set a grab on the menu.
#
proc ttk::menubutton::Pulldown {mb} {
    variable State
    if {[$mb instate disabled] || [set menu [$mb cget -menu]] eq ""} {
	return
    }
220
221
222
223
224
225
226
227

228
229
230
231

232
233
234
235
236
237
238
239
240
241
242
243
220
221
222
223
224
225
226

227
228
229
230

231
232
233
234
235
236
237
238
239
240
241
242
243







-
+



-
+












    	tk_popup $menu [winfo rootx $menu] [winfo rooty $menu]
    }
}

# FindMenuEntry --
#	Hack to support tk_optionMenus.
#	Returns the index of the menu entry with a matching -label,
#	-1 if not found.
#	"" if not found.
#
proc ttk::menubutton::FindMenuEntry {menu s} {
    set last [$menu index last]
    if {$last eq "none"} {
    if {$last eq "none" || $last eq ""} {
	return ""
    }
    for {set i 0} {$i <= $last} {incr i} {
	if {![catch {$menu entrycget $i -label} label]
	    && ($label eq $s)} {
	    return $i
	}
    }
    return ""
}

#*EOF*
Changes to library/ttk/notebook.tcl.
1
2
3
4
5
6
7
8
9
10
11
12
13





14
15
16
17


18
19
20
21
22
23
24
1
2
3
4
5
6
7
8





9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26








-
-
-
-
-
+
+
+
+
+




+
+







#
# Bindings for TNotebook widget
#

namespace eval ttk::notebook {
    variable TLNotebooks ;# See enableTraversal
}

bind TNotebook <ButtonPress-1>		{ ttk::notebook::Press %W %x %y }
bind TNotebook <Key-Right>		{ ttk::notebook::CycleTab %W  1; break }
bind TNotebook <Key-Left>		{ ttk::notebook::CycleTab %W -1; break }
bind TNotebook <Control-Key-Tab>	{ ttk::notebook::CycleTab %W  1; break }
bind TNotebook <Control-Shift-Key-Tab>	{ ttk::notebook::CycleTab %W -1; break }
bind TNotebook <Button-1>		{ ttk::notebook::Press %W %x %y }
bind TNotebook <Right>			{ ttk::notebook::CycleTab %W  1; break }
bind TNotebook <Left>			{ ttk::notebook::CycleTab %W -1; break }
bind TNotebook <Control-Tab>		{ ttk::notebook::CycleTab %W  1; break }
bind TNotebook <Control-Shift-Tab>	{ ttk::notebook::CycleTab %W -1; break }
catch {
bind TNotebook <Control-ISO_Left_Tab>	{ ttk::notebook::CycleTab %W -1; break }
}
bind TNotebook <Destroy>		{ 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;
#	+ keep focus if the notebook already has it;
39
40
41
42
43
44
45
46

47
48
49
50
51
52
53
54
55
56
57
58
59

60
61



62
63
64




65
66
67
68
69
70
71
72
73

74
75
76
77
78
79
80
41
42
43
44
45
46
47

48
49
50
51
52
53
54
55
56
57
58
59
60

61
62
63
64
65
66



67
68
69
70
71
72
73
74
75
76
77
78

79
80
81
82
83
84
85
86







-
+












-
+


+
+
+
-
-
-
+
+
+
+








-
+







	ttk::traverseTo $f
    } else {
	focus $w
    }
}

# Press $nb $x $y --
#	ButtonPress-1 binding for notebook widgets.
#	Button-1 binding for notebook widgets.
#	Activate the tab under the mouse cursor, if any.
#
proc ttk::notebook::Press {w x y} {
    set index [$w index @$x,$y]
    if {$index ne ""} {
	ActivateTab $w $index
    }
}

# CycleTab --
#	Select the next/previous tab in the list.
#
proc ttk::notebook::CycleTab {w dir} {
proc ttk::notebook::CycleTab {w dir {factor 1.0}} {
    if {[$w index end] != 0} {
	set current [$w index current]
	set d [expr {$dir/$factor}]
	set d [expr {int($d > 0 ? ceil($d) : floor($d))}]
	set tabCount [$w index end]
	set select [expr {($current + $dir) % [$w index end]}]
	while {[$w tab $select -state] != "normal" && ($select != $current)} {
	    set select [expr {($select + $dir) % [$w index end]}]
	set select [expr {($current + $d) % $tabCount}]
	set step [expr {$dir > 0 ? 1 : -1}]
	while {[$w tab $select -state] ne "normal" && ($select != $current)} {
	    set select [expr {($select + $step) % $tabCount}]
	}
	if {$select != $current} {
	    ActivateTab $w $select
	}
    }
}

# MnemonicTab $nb $key --
#	Scan all tabs in the specified notebook for one with the 
#	Scan all tabs in the specified notebook for one with the
#	specified mnemonic. If found, returns path name of tab;
#	otherwise returns ""
#
proc ttk::notebook::MnemonicTab {nb key} {
    set key [string toupper $key]
    foreach tab [$nb tabs] {
	set label [$nb tab $tab -text]
90
91
92
93
94
95
96
97
98


99
100
101
102
103
104
105
106
107
108
109
110
111




112
113

114
115
116
117


118
119
120
121
122
123
124
125
126
127
128
96
97
98
99
100
101
102


103
104
105
106
107
108
109
110
111
112
113




114
115
116
117
118

119
120



121
122




123
124
125
126
127
128
129







-
-
+
+









-
-
-
-
+
+
+
+

-
+

-
-
-
+
+
-
-
-
-







# +++ Toplevel keyboard traversal.
#

# enableTraversal --
#	Enable keyboard traversal for a notebook widget
#	by adding bindings to the containing toplevel window.
#
#	TLNotebooks($top) keeps track of the list of all traversal-enabled 
#	notebooks contained in the toplevel 
#	TLNotebooks($top) keeps track of the list of all traversal-enabled
#	notebooks contained in the toplevel
#
proc ttk::notebook::enableTraversal {nb} {
    variable TLNotebooks

    set top [winfo toplevel $nb]

    if {![info exists TLNotebooks($top)]} {
	# Augment $top bindings:
	#
	bind $top <Control-Key-Next>         {+ttk::notebook::TLCycleTab %W  1}
	bind $top <Control-Key-Prior>        {+ttk::notebook::TLCycleTab %W -1}
	bind $top <Control-Key-Tab> 	     {+ttk::notebook::TLCycleTab %W  1}
	bind $top <Control-Shift-Key-Tab>    {+ttk::notebook::TLCycleTab %W -1}
	bind $top <Control-Next>             {+ttk::notebook::TLCycleTab %W  1}
	bind $top <Control-Prior>            {+ttk::notebook::TLCycleTab %W -1}
	bind $top <Control-Tab> 	     {+ttk::notebook::TLCycleTab %W  1}
	bind $top <Control-Shift-Tab>        {+ttk::notebook::TLCycleTab %W -1}
	catch {
	bind $top <Control-Key-ISO_Left_Tab> {+ttk::notebook::TLCycleTab %W -1}
	bind $top <Control-ISO_Left_Tab>     {+ttk::notebook::TLCycleTab %W -1}
	}
	if {[tk windowingsystem] eq "aqua"} {
	    bind $top <Option-KeyPress> \
		+[list ttk::notebook::MnemonicActivation $top %K]
	bind $top <Option-Key> \
	    +[list ttk::notebook::MnemonicActivation $top %K]
	} else {
	    bind $top <Alt-KeyPress> \
		+[list ttk::notebook::MnemonicActivation $top %K]
	}
	bind $top <Destroy> {+ttk::notebook::TLCleanup %W}
    }

    lappend TLNotebooks($top) $nb
}

# TLCleanup -- <Destroy> binding for traversal-enabled toplevels
141
142
143
144
145
146
147
148

149
150
151
152
153
154
155
142
143
144
145
146
147
148

149
150
151
152
153
154
155
156







-
+







    set top [winfo toplevel $nb]
    if {[info exists TLNotebooks($top)]} {
	set index [lsearch -exact $TLNotebooks($top) $nb]
        set TLNotebooks($top) [lreplace $TLNotebooks($top) $index $index]
    }
}

# EnclosingNotebook $w -- 
# EnclosingNotebook $w --
#	Return the nearest traversal-enabled notebook widget
#	that contains $w.
#
# BUGS: this only works properly for tabs that are direct children
#	of the notebook widget.  This routine should follow the
#	geometry manager hierarchy, not window ancestry, but that
#	information is not available in Tk.
167
168
169
170
171
172
173
174

175
176
177
178
179
180
181
182
183
184
185

186
187
188
189
190
191
192
193
194
195
196
197
168
169
170
171
172
173
174

175
176
177
178
179
180
181
182
183
184
185

186
187
188
189
190
191
192
193
194
195
196
197
198







-
+










-
+












	set w [winfo parent $w]
    }
    return ""
}

# TLCycleTab --
#	toplevel binding procedure for Control-Tab / Control-Shift-Tab
#	Select the next/previous tab in the nearest ancestor notebook. 
#	Select the next/previous tab in the nearest ancestor notebook.
#
proc ttk::notebook::TLCycleTab {w dir} {
    set nb [EnclosingNotebook $w]
    if {$nb ne ""} {
	CycleTab $nb $dir
	return -code break
    }
}

# MnemonicActivation $nb $key --
#	Alt-KeyPress binding procedure for mnemonic activation.
#	Alt-Key binding procedure for mnemonic activation.
#	Scan all notebooks in specified toplevel for a tab with the
#	the specified mnemonic.  If found, activate it and return TCL_BREAK.
#
proc ttk::notebook::MnemonicActivation {top key} {
    variable TLNotebooks
    foreach nb $TLNotebooks($top) {
	if {[set tab [MnemonicTab $nb $key]] ne ""} {
	    ActivateTab $nb [$nb index $tab]
	    return -code break
	}
    }
}
Changes to library/ttk/panedwindow.tcl.
11
12
13
14
15
16
17
18

19
20
21
22
23
24
25
11
12
13
14
15
16
17

18
19
20
21
22
23
24
25







-
+







	sash 	-
	sashPos -
    }
}

## Bindings:
#
bind TPanedwindow <ButtonPress-1> 	{ ttk::panedwindow::Press %W %x %y }
bind TPanedwindow <Button-1> 		{ ttk::panedwindow::Press %W %x %y }
bind TPanedwindow <B1-Motion>		{ ttk::panedwindow::Drag %W %x %y }
bind TPanedwindow <ButtonRelease-1> 	{ ttk::panedwindow::Release %W %x %y }

bind TPanedwindow <Motion> 		{ ttk::panedwindow::SetCursor %W %x %y }
bind TPanedwindow <Enter> 		{ ttk::panedwindow::SetCursor %W %x %y }
bind TPanedwindow <Leave> 		{ ttk::panedwindow::ResetCursor %W }
# See <<NOTE-PW-LEAVE-NOTIFYINFERIOR>>
Changes to library/ttk/scale.tcl.
1

2
3
4
5
6
7
8
9
10
11
12

13
14
15
16

17
18
19
20

21
22
23
24
25
26
27

1
2
3
4
5
6
7
8
9
10
11

12
13
14
15

16
17
18
19

20
21
22
23
24
25
26
27
-
+










-
+



-
+



-
+







# scale.tcl - Copyright (C) 2004 Pat Thoyts <[email protected]>
# scale.tcl - Copyright © 2004 Pat Thoyts <[email protected]>
#
# Bindings for the TScale widget

namespace eval ttk::scale {
    variable State
    array set State  {
	dragging 0
    }
}

bind TScale <ButtonPress-1>   { ttk::scale::Press %W %x %y }
bind TScale <Button-1>        { ttk::scale::Press %W %x %y }
bind TScale <B1-Motion>       { ttk::scale::Drag %W %x %y }
bind TScale <ButtonRelease-1> { ttk::scale::Release %W %x %y }

bind TScale <ButtonPress-2>   { ttk::scale::Jump %W %x %y }
bind TScale <Button-2>        { ttk::scale::Jump %W %x %y }
bind TScale <B2-Motion>       { ttk::scale::Drag %W %x %y }
bind TScale <ButtonRelease-2> { ttk::scale::Release %W %x %y }

bind TScale <ButtonPress-3>   { ttk::scale::Jump %W %x %y }
bind TScale <Button-3>        { ttk::scale::Jump %W %x %y }
bind TScale <B3-Motion>       { ttk::scale::Drag %W %x %y }
bind TScale <ButtonRelease-3> { ttk::scale::Release %W %x %y }

## Keyboard navigation bindings:
#
bind TScale <<LineStart>>     { %W set [%W cget -from] }
bind TScale <<LineEnd>>       { %W set [%W cget -to] }
48
49
50
51
52
53
54
55

56
57
58
59
60
61
62
48
49
50
51
52
53
54

55
56
57
58
59
60
61
62







-
+







        *slider {
            set State(dragging) 1
            set State(initial) [$w get]
        }
    }
}

# scale::Jump -- ButtonPress-2/3 binding for scale acts like
# scale::Jump -- Button-2/3 binding for scale acts like
#	Press except that clicking in the trough jumps to the
#	clicked position.
proc ttk::scale::Jump {w x y} {
    variable State
    set State(dragging) 0

    switch -glob -- [$w identify $x $y] {
Changes to library/ttk/scrollbar.tcl.
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16

17
18
19
20
21
22
23
24

25
26
27

28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15

16
17
18
19
20
21



22



23












24
25
26
27
28
29
30











-
+



-
+





-
-
-
+
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-







#
# Bindings for TScrollbar widget
#

namespace eval ttk::scrollbar {
    variable State
    # State(xPress)	--
    # State(yPress)	-- initial position of mouse at start of drag.
    # State(first)	-- value of -first at start of drag.
}

bind TScrollbar <ButtonPress-1> 	{ ttk::scrollbar::Press %W %x %y }
bind TScrollbar <Button-1> 		{ ttk::scrollbar::Press %W %x %y }
bind TScrollbar <B1-Motion>		{ ttk::scrollbar::Drag %W %x %y }
bind TScrollbar <ButtonRelease-1>	{ ttk::scrollbar::Release %W %x %y }

bind TScrollbar <ButtonPress-2> 	{ ttk::scrollbar::Jump %W %x %y }
bind TScrollbar <Button-2> 		{ ttk::scrollbar::Jump %W %x %y }
bind TScrollbar <B2-Motion>		{ ttk::scrollbar::Drag %W %x %y }
bind TScrollbar <ButtonRelease-2>	{ ttk::scrollbar::Release %W %x %y }

# Redirect scrollwheel bindings to the scrollbar widget
#
# The shift-bindings scroll left/right (not up/down)
# if a widget has both possibilities
set eventList [list <MouseWheel> <Shift-MouseWheel>]
bind TScrollbar <MouseWheel> [bind Scrollbar <MouseWheel>]
switch [tk windowingsystem] {
    aqua {
        lappend eventList <Option-MouseWheel> <Shift-Option-MouseWheel>
bind TScrollbar <Option-MouseWheel> [bind Scrollbar <Option-MouseWheel>]
    }
    x11 {
        lappend eventList <Button-4> <Button-5> \
                <Shift-Button-4> <Shift-Button-5>
        # For tk 8.7, the event list should be extended by
        # <Button-6> <Button-7>
    }
}
foreach event $eventList {
    bind TScrollbar $event [bind Scrollbar $event]
}
unset eventList event

proc ttk::scrollbar::Scroll {w n units} {
    set cmd [$w cget -command]
    if {$cmd ne ""} {
	uplevel #0 $cmd scroll $n $units
    }
}
55
56
57
58
59
60
61
62

63
64
65
66
67
68
69

70
71
72
73
74
75
76
39
40
41
42
43
44
45

46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61







-
+







+







proc ttk::scrollbar::Press {w x y} {
    variable State

    set State(xPress) $x
    set State(yPress) $y

    switch -glob -- [$w identify $x $y] {
    	*uparrow -
	*uparrow -
	*leftarrow {
	    ttk::Repeatedly Scroll $w -1 units
	}
	*downarrow -
	*rightarrow {
	    ttk::Repeatedly Scroll $w  1 units
	}
	*grip -
	*thumb {
	    set State(first) [lindex [$w get] 0]
	}
	*trough {
	    set f [$w fraction $x $y]
	    if {$f < [lindex [$w get] 0]} {
		# Clicked in upper/left trough
85
86
87
88
89
90
91
92

93
94
95
96
97
98
99
100
101
102
103
104
105
106
107

108
109
110
111
112
113
114

115
116
117
118
119
120
121
122
123
124
125
126
70
71
72
73
74
75
76

77
78
79
80
81
82
83
84
85
86
87
88
89
90
91

92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112







-
+














-
+







+












	}
    }
}

proc ttk::scrollbar::Drag {w x y} {
    variable State
    if {![info exists State(first)]} {
    	# Initial buttonpress was not on the thumb, 
    	# Initial buttonpress was not on the thumb,
	# or something screwy has happened.  In either case, ignore:
	return;
    }
    set xDelta [expr {$x - $State(xPress)}]
    set yDelta [expr {$y - $State(yPress)}]
    Moveto $w [expr {$State(first) + [$w delta $xDelta $yDelta]}]
}

proc ttk::scrollbar::Release {w x y} {
    variable State
    unset -nocomplain State(xPress) State(yPress) State(first)
    ttk::CancelRepeat
}

# scrollbar::Jump -- ButtonPress-2 binding for scrollbars.
# scrollbar::Jump -- Button-2 binding for scrollbars.
# 	Behaves exactly like scrollbar::Press, except that
#	clicking in the trough jumps to the the selected position.
#
proc ttk::scrollbar::Jump {w x y} {
    variable State

    switch -glob -- [$w identify $x $y] {
	*grip -
	*thumb -
	*trough {
	    set State(first) [$w fraction $x $y]
	    Moveto $w $State(first)
	    set State(xPress) $x
	    set State(yPress) $y
	}
	default {
	    Press $w $x $y
	}
    }
}
Changes to library/ttk/sizegrip.tcl.
28
29
30
31
32
33
34
35

36
37
38
39
40
41
42
28
29
30
31
32
33
34

35
36
37
38
39
40
41
42







-
+







	heightInc	1
        resizeX         1
        resizeY         1
	toplevel 	{}
    }
}

bind TSizegrip <ButtonPress-1> 		{ ttk::sizegrip::Press	%W %X %Y }
bind TSizegrip <Button-1> 		{ ttk::sizegrip::Press	%W %X %Y }
bind TSizegrip <B1-Motion> 		{ ttk::sizegrip::Drag 	%W %X %Y }
bind TSizegrip <ButtonRelease-1> 	{ ttk::sizegrip::Release %W %X %Y }

proc ttk::sizegrip::Press {W X Y} {
    variable State

    if {[$W instate disabled]} { return }
Changes to library/ttk/spinbox.tcl.
8
9
10
11
12
13
14
15

16
17
18
19
20
21


22
23
24
25
26

27
28
29
30
31
32
33
34
35

36
37
38
39
40
41
42
43
44
45
46
47
48
49

50
51

52
53

54
55
56

57
58

59
60
61
62
63
64
65
66
67
68
69
70
71
72

73
74
75
76
77
78
79
80
81
82
83

84
85

86
87

88
89

90
91
92
93
94
95
96
8
9
10
11
12
13
14

15
16
17
18
19


20
21
22
23
24
25

26
27
28
29
30
31
32
33
34

35
36
37
38
39
40
41
42
43
44
45
46
47
48

49
50

51
52

53
54
55

56
57

58
59
60
61
62
63
64
65
66
67
68
69
70
71

72
73
74
75
76
77
78
79
80
81
82

83
84

85
86

87
88

89
90
91
92
93
94
95
96







-
+




-
-
+
+




-
+








-
+













-
+

-
+

-
+


-
+

-
+













-
+










-
+

-
+

-
+

-
+







#
# Duplicate the Entry bindings, override if needed:
#

ttk::copyBindings TEntry TSpinbox

bind TSpinbox <Motion>			{ ttk::spinbox::Motion %W %x %y }
bind TSpinbox <ButtonPress-1> 		{ ttk::spinbox::Press %W %x %y }
bind TSpinbox <Button-1> 		{ ttk::spinbox::Press %W %x %y }
bind TSpinbox <ButtonRelease-1> 	{ ttk::spinbox::Release %W }
bind TSpinbox <Double-Button-1> 	{ ttk::spinbox::DoubleClick %W %x %y }
bind TSpinbox <Triple-Button-1> 	{} ;# disable TEntry triple-click

bind TSpinbox <KeyPress-Up>		{ event generate %W <<Increment>> }
bind TSpinbox <KeyPress-Down> 		{ event generate %W <<Decrement>> }
bind TSpinbox <Up>			{ event generate %W <<Increment>> }
bind TSpinbox <Down> 			{ event generate %W <<Decrement>> }

bind TSpinbox <<Increment>>		{ ttk::spinbox::Spin %W +1 }
bind TSpinbox <<Decrement>> 		{ 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} {
    variable State
    ttk::saveCursor $w State(userConfCursor) [ttk::cursor text]
    if {   [$w identify $x $y] eq "textarea"
        && [$w instate {!readonly !disabled}]
	&& [$w instate {!readonly !disabled}]
    } {
	ttk::setCursor $w text
    } else {
	ttk::setCursor $w $State(userConfCursor)
    }
}

## Press --
#
proc ttk::spinbox::Press {w x y} {
    if {[$w instate disabled]} { return }
    focus $w
    switch -glob -- [$w identify $x $y] {
        *textarea	{ ttk::entry::Press $w $x }
	*textarea	{ ttk::entry::Press $w $x }
	*rightarrow	-
        *uparrow 	{ ttk::Repeatedly event generate $w <<Increment>> }
	*uparrow 	{ ttk::Repeatedly event generate $w <<Increment>> }
	*leftarrow	-
        *downarrow	{ ttk::Repeatedly event generate $w <<Decrement>> }
	*downarrow	{ ttk::Repeatedly event generate $w <<Decrement>> }
	*spinbutton {
	    if {$y * 2 >= [winfo height $w]} {
	    	set event <<Decrement>>
		set event <<Decrement>>
	    } else {
	    	set event <<Increment>>
		set event <<Increment>>
	    }
	    ttk::Repeatedly event generate $w $event
	}
    }
}

## DoubleClick --
#	Select all if over the text area; otherwise same as Press.
#
proc ttk::spinbox::DoubleClick {w x y} {
    if {[$w instate disabled]} { return }

    switch -glob -- [$w identify $x $y] {
        *textarea	{ SelectAll $w }
	*textarea	{ SelectAll $w }
	*		{ Press $w $x $y }
    }
}

proc ttk::spinbox::Release {w} {
    ttk::CancelRepeat
}

## MouseWheel --
#	Mousewheel callback.  Turn these into <<Increment>> (-1, up)
# 	or <<Decrement> (+1, down) events.
# 	or <<Decrement> (+1, down) events. Not used any more.
#
proc ttk::spinbox::MouseWheel {w dir} {
proc ttk::spinbox::MouseWheel {w dir {factor 1.0}} {
    if {[$w instate disabled]} { return }
    if {$dir < 0} {
    if {($dir < 0) ^ ($factor < 0)} {
	event generate $w <<Increment>>
    } else {
    } elseif {$dir != 0} {
	event generate $w <<Decrement>>
    }
}

## SelectAll --
#	Select widget contents.
#
130
131
132
133
134
135
136
137



138





139
140
141
142
143
144
















145
146
147


148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165

166
167
168
169
170
171
172
173
174
175
176
177
130
131
132
133
134
135
136

137
138
139
140
141
142
143
144
145






146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162


163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181

182
183
184
185
186
187
188
189
190
191
192
193
194







-
+
+
+

+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
+
+

















-
+













## Spin --
#	Handle <<Increment>> and <<Decrement>> 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)]} {
	set State($w,values.index) -1
	set State($w,values.last) {}
    }
    set nvalues [llength [set values [$w cget -values]]]
    set value [$w get]
    if {$nvalues} {
	set current [lsearch -exact $values $value]
	set index [Adjust $w [expr {$current + $dir}] 0 [expr {$nvalues - 1}]]
	$w set [lindex $values $index]
    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 + $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]}]
	if {[catch {
	    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]]]
    }
    SelectAll $w
    uplevel #0 [$w cget -command]
}

## FormatValue --
#	Reformat numeric value based on -format.
#
proc ttk::spinbox::FormatValue {w val} {
    set fmt [$w cget -format]
    if {$fmt eq ""} {
	# Try to guess a suitable -format based on -increment.
	set delta [expr {abs([$w cget -increment])}]
        if {0 < $delta && $delta < 1} {
	if {0 < $delta && $delta < 1} {
	    # NB: This guesses wrong if -increment has more than 1
	    # significant digit itself, e.g., -increment 0.25
	    set nsd [expr {int(ceil(-log10($delta)))}]
	    set fmt "%.${nsd}f"
	} else {
	    set fmt "%.0f"
	}
    }
    return [format $fmt $val]
}

#*EOF*
Changes to library/ttk/treeview.tcl.
24
25
26
27
28
29
30
31
32


33
34
35
36
37
38
39
40
41
42








43
44

45
46
47
48
49

50
51
52
53
54
55
56
24
25
26
27
28
29
30


31
32
33
34








35
36
37
38
39
40
41
42
43

44
45
46
47
48

49
50
51
52
53
54
55
56







-
-
+
+


-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+

-
+




-
+








### Widget bindings.
#

bind Treeview	<Motion> 		{ ttk::treeview::Motion %W %x %y }
bind Treeview	<B1-Leave>		{ #nothing }
bind Treeview	<Leave>			{ ttk::treeview::ActivateHeading {} {}}
bind Treeview	<ButtonPress-1> 	{ ttk::treeview::Press %W %x %y }
bind Treeview	<Double-ButtonPress-1> 	{ ttk::treeview::DoubleClick %W %x %y }
bind Treeview	<Button-1> 		{ ttk::treeview::Press %W %x %y }
bind Treeview	<Double-Button-1> 	{ ttk::treeview::DoubleClick %W %x %y }
bind Treeview	<ButtonRelease-1> 	{ ttk::treeview::Release %W %x %y }
bind Treeview	<B1-Motion> 		{ ttk::treeview::Drag %W %x %y }
bind Treeview 	<KeyPress-Up>    	{ ttk::treeview::Keynav %W up }
bind Treeview 	<KeyPress-Down>  	{ ttk::treeview::Keynav %W down }
bind Treeview 	<KeyPress-Right> 	{ ttk::treeview::Keynav %W right }
bind Treeview 	<KeyPress-Left>  	{ ttk::treeview::Keynav %W left }
bind Treeview	<KeyPress-Prior>	{ %W yview scroll -1 pages }
bind Treeview	<KeyPress-Next> 	{ %W yview scroll  1 pages }
bind Treeview	<KeyPress-Return>	{ ttk::treeview::ToggleFocus %W }
bind Treeview	<KeyPress-space>	{ ttk::treeview::ToggleFocus %W }
bind Treeview 	<Up>    		{ ttk::treeview::Keynav %W up }
bind Treeview 	<Down>  		{ ttk::treeview::Keynav %W down }
bind Treeview 	<Right> 		{ ttk::treeview::Keynav %W right }
bind Treeview 	<Left>  		{ ttk::treeview::Keynav %W left }
bind Treeview	<Prior>			{ %W yview scroll -1 pages }
bind Treeview	<Next> 			{ %W yview scroll  1 pages }
bind Treeview	<Return>		{ ttk::treeview::ToggleFocus %W }
bind Treeview	<space>			{ ttk::treeview::ToggleFocus %W }

bind Treeview	<Shift-ButtonPress-1> \
bind Treeview	<Shift-Button-1> \
		{ ttk::treeview::Select %W %x %y extend }
bind Treeview	<<ToggleSelection>> \
		{ ttk::treeview::Select %W %x %y toggle }

ttk::copyBindings TtkScrollable Treeview 
ttk::copyBindings TtkScrollable Treeview

### Binding procedures.
#

## Keynav -- Keyboard navigation
#
# @@@ TODO: verify/rewrite up and down code.
127
128
129
130
131
132
133
134

135
136
137
138
139
140
141
127
128
129
130
131
132
133

134
135
136
137
138
139
140
141







-
+







	if {[winfo exists $State(activeWidget)] && $State(activeHeading) != {}} {
	    # It may happen that $State(activeHeading) no longer corresponds
	    # to an existing display column. This happens for instance when
	    # changing -displaycolumns in a bound script when this change
	    # triggers a <Leave> event. A proc checking if the display column
	    # $State(activeHeading) is really still present or not could be
	    # written but it would need to check several special cases:
	    #   a. -displaycolumns "#all" or being an explicit columns list 
	    #   a. -displaycolumns "#all" or being an explicit columns list
	    #   b. column #0 display is not governed by the -displaycolumn
	    #      list but by the value of the -show option
	    # --> Let's rather catch the following line.
	    catch {$State(activeWidget) heading $State(activeHeading) state !active}
	}
	if {$heading != {}} {
	    $w heading $heading state active
151
152
153
154
155
156
157
158

159
160
161
162
163
164
165
166
167
168

169
170
171
172
173
174
175
151
152
153
154
155
156
157

158
159
160
161
162
163
164
165
166
167

168
169
170
171
172
173
174
175







-
+









-
+







#
proc ttk::treeview::Select {w x y op} {
    if {[set item [$w identify row $x $y]] ne "" } {
	SelectOp $w $item $op
    }
}

## DoubleClick -- Double-ButtonPress-1 binding.
## DoubleClick -- Double-Button-1 binding.
#
proc ttk::treeview::DoubleClick {w x y} {
    if {[set row [$w identify row $x $y]] ne ""} {
	Toggle $w $row
    } else {
	Press $w $x $y ;# perform single-click action
    }
}

## Press -- ButtonPress binding.
## Press -- Button binding.
#
proc ttk::treeview::Press {w x y} {
    focus $w
    switch -- [$w identify region $x $y] {
	nothing { }
	heading { heading.press $w $x $y }
	separator { resize.press $w $x $y }
261
262
263
264
265
266
267
268
269
270



271
272
273
274
275
276
277
261
262
263
264
265
266
267



268
269
270
271
272
273
274
275
276
277







-
-
-
+
+
+







#
proc ttk::treeview::SelectOp {w item op} {
    select.$op.[$w cget -selectmode] $w $item
}

## -selectmode none:
#
proc ttk::treeview::select.choose.none {w item} { $w focus $item }
proc ttk::treeview::select.toggle.none {w item} { $w focus $item }
proc ttk::treeview::select.extend.none {w item} { $w focus $item }
proc ttk::treeview::select.choose.none {w item} { $w focus $item; $w see $item }
proc ttk::treeview::select.toggle.none {w item} { $w focus $item; $w see $item }
proc ttk::treeview::select.extend.none {w item} { $w focus $item; $w see $item }

## -selectmode browse:
#
proc ttk::treeview::select.choose.browse {w item} { BrowseTo $w $item }
proc ttk::treeview::select.toggle.browse {w item} { BrowseTo $w $item }
proc ttk::treeview::select.extend.browse {w item} { BrowseTo $w $item }

Changes to library/ttk/ttk.tcl.
8
9
10
11
12
13
14
15
16
17



18
19
20
21
22
23
24
8
9
10
11
12
13
14



15
16
17
18
19
20
21
22
23
24







-
-
-
+
+
+







namespace eval ::ttk {
    variable library
    if {![info exists library]} {
	set library [file dirname [info script]]
    }
}

source [file join $::ttk::library fonts.tcl]
source [file join $::ttk::library cursors.tcl]
source [file join $::ttk::library utils.tcl]
source -encoding utf-8 [file join $::ttk::library fonts.tcl]
source -encoding utf-8 [file join $::ttk::library cursors.tcl]
source -encoding utf-8 [file join $::ttk::library utils.tcl]

## ttk::deprecated $old $new --
#	Define $old command as a deprecated alias for $new command
#	$old and $new must be fully namespace-qualified.
#
proc ttk::deprecated {old new} {
    interp alias {} $old {} ttk::do'deprecate $old $new
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111












112
113
114
115
116
117
118
119
120
121
122
123
124
125

126
127
128
129
130
131
132
133
134
135
136
137
138

139
140
141
142
143
144
145
93
94
95
96
97
98
99












100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124

125
126
127
128
129
130
131
132
133
134
135
136
137

138
139
140
141
142
143
144
145







-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+













-
+












-
+







    }
    ::ttk::style theme use $theme
    set currentTheme $theme
}

### Load widget bindings.
#
source [file join $::ttk::library button.tcl]
source [file join $::ttk::library menubutton.tcl]
source [file join $::ttk::library scrollbar.tcl]
source [file join $::ttk::library scale.tcl]
source [file join $::ttk::library progress.tcl]
source [file join $::ttk::library notebook.tcl]
source [file join $::ttk::library panedwindow.tcl]
source [file join $::ttk::library entry.tcl]
source [file join $::ttk::library combobox.tcl]	;# dependency: entry.tcl
source [file join $::ttk::library spinbox.tcl]  ;# dependency: entry.tcl
source [file join $::ttk::library treeview.tcl]
source [file join $::ttk::library sizegrip.tcl]
source -encoding utf-8 [file join $::ttk::library button.tcl]
source -encoding utf-8 [file join $::ttk::library menubutton.tcl]
source -encoding utf-8 [file join $::ttk::library scrollbar.tcl]
source -encoding utf-8 [file join $::ttk::library scale.tcl]
source -encoding utf-8 [file join $::ttk::library progress.tcl]
source -encoding utf-8 [file join $::ttk::library notebook.tcl]
source -encoding utf-8 [file join $::ttk::library panedwindow.tcl]
source -encoding utf-8 [file join $::ttk::library entry.tcl]
source -encoding utf-8 [file join $::ttk::library combobox.tcl]	;# dependency: entry.tcl
source -encoding utf-8 [file join $::ttk::library spinbox.tcl]  ;# dependency: entry.tcl
source -encoding utf-8 [file join $::ttk::library treeview.tcl]
source -encoding utf-8 [file join $::ttk::library sizegrip.tcl]

## Label and Labelframe bindings:
#  (not enough to justify their own file...)
#
bind TLabelframe <<Invoke>>	{ tk::TabToWindow [tk_focusNext %W] }
bind TLabel <<Invoke>>		{ tk::TabToWindow [tk_focusNext %W] }

### Load settings for built-in themes:
#
proc ttk::LoadThemes {} {
    variable library

    # "default" always present:
    uplevel #0 [list source [file join $library defaults.tcl]] 
    uplevel #0 [list source -encoding utf-8 [file join $library defaults.tcl]]

    set builtinThemes [style theme names]
    foreach {theme scripts} {
	classic 	classicTheme.tcl
	alt 		altTheme.tcl
	clam 		clamTheme.tcl
	winnative	winTheme.tcl
	xpnative	{xpTheme.tcl vistaTheme.tcl}
	aqua 		aquaTheme.tcl
    } {
	if {[lsearch -exact $builtinThemes $theme] >= 0} {
            foreach script $scripts {
                uplevel #0 [list source [file join $library $script]]
                uplevel #0 [list source -encoding utf-8 [file join $library $script]]
            }
	}
    }
}

ttk::LoadThemes; rename ::ttk::LoadThemes {}

Changes to library/ttk/utils.tcl.
54
55
56
57
58
59
60
61

62
63
64
65
66
67
68
54
55
56
57
58
59
60

61
62
63
64
65
66
67
68







-
+







	event generate $focus <<TraverseOut>>
    }
    focus $w
    event generate $w <<TraverseIn>>
}

## ttk::clickToFocus $w --
#	Utility routine, used in <ButtonPress-1> bindings --
#	Utility routine, used in <Button-1> bindings --
#	Assign keyboard focus to the specified widget if -takefocus is enabled.
#
proc ttk::clickToFocus {w} {
    if {[ttk::takesFocus $w]} { focus $w }
}

## ttk::takesFocus w --
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299


300
301
302
303
304
305
306
307
308
309


310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330

331
332

333
334
335
336



337
338
339

340
341
342
343



344
345
269
270
271
272
273
274
275















276
277
278
279
280
281
282


283
284
285
286
287







288
289



290
291
292
293
294
295
296
297
298
299








300


301




302
303
304



305




306
307
308

309







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







-
-
+
+



-
-
-
-
-
-
-
+
+
-
-
-










-
-
-
-
-
-
-
-
+
-
-
+
-
-
-
-
+
+
+
-
-
-
+
-
-
-
-
+
+
+
-

    }
}

### Mousewheel bindings.
#
# Platform inconsistencies:
#
# On X11, the server typically maps the mouse wheel to Button4 and Button5.
#
# On OSX, Tk generates sensible values for the %D field in <MouseWheel> events.
#
# On Windows, %D must be scaled by a factor of 120.
# In addition, Tk redirects mousewheel events to the window with
# keyboard focus instead of sending them to the window under the pointer.
# We do not attempt to fix that here, see also TIP#171.
#
# OSX conventionally uses Shift+MouseWheel for horizontal scrolling,
# and Option+MouseWheel for accelerated scrolling.
#
# The Shift+MouseWheel behavior is not conventional on Windows or most
# X11 toolkits, but it's useful.
#
# MouseWheel scrolling is accelerated on X11, which is conventional
# for Tk and appears to be conventional for other toolkits (although
# 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} {
    if {[tk windowingsystem] eq "x11"} {
	bind $bindtag <ButtonPress-4> "$callback -1"
	bind $bindtag <ButtonPress-5> "$callback +1"
    }
    if {[tk windowingsystem] eq "aqua"} {
	bind $bindtag <MouseWheel> [append callback { [expr {-(%D)}]} ]
	bind $bindtag <Option-MouseWheel> [append callback { [expr {-10 *(%D)}]} ]
    bind $bindtag <MouseWheel> "$callback %D -120.0"
    bind $bindtag <Option-MouseWheel> "$callback %D -12.0"
    } else {
	bind $bindtag <MouseWheel> [append callback { [expr {-(%D / 120)}]}]
    }
}

## Mousewheel bindings for standard scrollable widgets.
#
# Usage: [ttk::copyBindings TtkScrollable $bindtag]
#
# $bindtag should be for a widget that supports the
# standard scrollbar protocol.
#

if {[tk windowingsystem] eq "x11"} {
    bind TtkScrollable <ButtonPress-4>       { %W yview scroll -5 units }
    bind TtkScrollable <ButtonPress-5>       { %W yview scroll  5 units }
    bind TtkScrollable <Shift-ButtonPress-4> { %W xview scroll -5 units }
    bind TtkScrollable <Shift-ButtonPress-5> { %W xview scroll  5 units }
}
if {[tk windowingsystem] eq "aqua"} {
    bind TtkScrollable <MouseWheel> \
bind TtkScrollable <MouseWheel> \
	    { %W yview scroll [expr {-(%D)}] units }
    bind TtkScrollable <Shift-MouseWheel> \
	{ tk::MouseWheel %W y %D -30.0 }
	    { %W xview scroll [expr {-(%D)}] units }
    bind TtkScrollable <Option-MouseWheel> \
	    { %W yview scroll  [expr {-10 * (%D)}] units }
    bind TtkScrollable <Shift-Option-MouseWheel> \
bind TtkScrollable <Option-MouseWheel> \
	{ tk::MouseWheel %W y %D -3.0 }
bind TtkScrollable <Shift-MouseWheel> \
	    { %W xview scroll [expr {-10 * (%D)}] units }
} else {
    bind TtkScrollable <MouseWheel> \
	{ tk::MouseWheel %W x %D -30.0 }
	    { %W yview scroll [expr {-(%D / 120)}] units }
    bind TtkScrollable <Shift-MouseWheel> \
	    { %W xview scroll [expr {-(%D / 120)}] units }
}
bind TtkScrollable <Shift-Option-MouseWheel> \
	{ tk::MouseWheel %W x %D -3.0 }


#*EOF*
Changes to library/ttk/vistaTheme.tcl.
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







#
# Settings for Microsoft Windows Vista and Server 2008
#

# The Vista theme can only be defined on Windows Vista and above. The theme
# is created in C due to the need to assign a theme-enabled function for 
# is created in C due to the need to assign a theme-enabled function for
# detecting when themeing is disabled. On systems that cannot support the
# Vista theme, there will be no such theme created and we must not
# evaluate this script.

if {"vista" ni [ttk::style theme names]} {
    return
}
65
66
67
68
69
70
71
72

73
74

75
76
77
78
79
80
81
65
66
67
68
69
70
71

72
73

74
75
76
77
78
79
80
81







-
+

-
+







            EDIT 3 {disabled 3 readonly 5 focus 4 hover 2 {} 1}
        ttk::style element create Combobox.rightdownarrow vsapi \
            COMBOBOX 6 {disabled 4 pressed 3 active 2 {} 1} \
            -syssize {SM_CXVSCROLL SM_CYVSCROLL}
        ttk::style layout TCombobox {
            Combobox.border -sticky nswe -border 0 -children {
                Combobox.rightdownarrow -side right -sticky ns
                Combobox.padding -expand 1 -sticky nswe -children {
                Combobox.padding -sticky nswe -children {
                    Combobox.background -sticky nswe -children {
                        Combobox.focus -expand 1 -sticky nswe -children {
                        Combobox.focus -sticky nswe -children {
                            Combobox.textarea -sticky nswe
                        }
                    }
                }
            }
        }
        # Vista.Combobox droplist frame
134
135
136
137
138
139
140
141

142
143
144
145
146
147
148
149
150
151
152
153
154

155
156
157
158
159
160
161
134
135
136
137
138
139
140

141
142
143
144
145
146
147
148
149
150
151
152
153

154
155
156
157
158
159
160
161







-
+












-
+







            -padding 1 -halfheight 1 \
            -syssize { SM_CXVSCROLL SM_CYVSCROLL }
        ttk::style layout TSpinbox {
            Spinbox.field -sticky nswe -children {
                Spinbox.background -sticky news -children {
                    Spinbox.padding -sticky news -children {
                        Spinbox.innerbg -sticky news -children {
                            Spinbox.textarea -expand 1
                            Spinbox.textarea
                        }
                    }
                    Spinbox.uparrow -side top -sticky ens
                    Spinbox.downarrow -side bottom -sticky ens
                }
            }
        }
	ttk::style map TSpinbox \
	    -selectbackground [list !focus SystemWindow] \
	    -selectforeground [list !focus SystemWindowText] \
	    ;

        

        # SCROLLBAR elements (Vista includes a state for 'hover')
        ttk::style element create Vertical.Scrollbar.uparrow vsapi \
            SCROLLBAR 1 {disabled 4 pressed 3 active 2 hover 17 {} 1} \
            -syssize {SM_CXVSCROLL SM_CYVSCROLL}
        ttk::style element create Vertical.Scrollbar.downarrow vsapi \
            SCROLLBAR 1 {disabled 8 pressed 7 active 6 hover 18 {} 5} \
            -syssize {SM_CXVSCROLL SM_CYVSCROLL}
183
184
185
186
187
188
189

190
191
192
193
194
195
196
197
198
199

200
201
202
203
204
205
206


207
208
209
210
211
212
213
214
215
216
217


218
219
220
221
222
223

224
225
226

227
228
229
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199

200
201
202
203
204
205


206
207
208
209
210
211
212
213
214
215
216


217
218
219
220
221
222
223

224
225
226

227
228
229
230







+









-
+





-
-
+
+









-
-
+
+





-
+


-
+




        # Progressbar
        ttk::style element create Horizontal.Progressbar.pbar vsapi \
            PROGRESS 3 {{} 1} -padding 8
        ttk::style layout Horizontal.TProgressbar {
            Horizontal.Progressbar.trough -sticky nswe -children {
                Horizontal.Progressbar.pbar -side left -sticky ns
                Horizontal.Progressbar.text -sticky nesw
            }
        }
        ttk::style element create Vertical.Progressbar.pbar vsapi \
            PROGRESS 3 {{} 1} -padding 8
        ttk::style layout Vertical.TProgressbar {
            Vertical.Progressbar.trough -sticky nswe -children {
                Vertical.Progressbar.pbar -side bottom -sticky we
            }
        }
        

        # Scale
        ttk::style element create Horizontal.Scale.slider vsapi \
            TRACKBAR 3 {disabled 5 focus 4 pressed 3 active 2 {} 1} \
            -width 6 -height 12
        ttk::style layout Horizontal.TScale {
            Scale.focus -expand 1 -sticky nswe -children {
                Horizontal.Scale.trough -expand 1 -sticky nswe -children {
            Scale.focus -sticky nswe -children {
                Horizontal.Scale.trough -sticky nswe -children {
                    Horizontal.Scale.track -sticky we
                    Horizontal.Scale.slider -side left -sticky {}
                }
            }
        }
        ttk::style element create Vertical.Scale.slider vsapi \
            TRACKBAR 6 {disabled 5 focus 4 pressed 3 active 2 {} 1} \
            -width 12 -height 6
        ttk::style layout Vertical.TScale {
            Scale.focus -expand 1 -sticky nswe -children {
                Vertical.Scale.trough -expand 1 -sticky nswe -children {
            Scale.focus -sticky nswe -children {
                Vertical.Scale.trough -sticky nswe -children {
                    Vertical.Scale.track -sticky ns
                    Vertical.Scale.slider -side top -sticky {}
                }
            }
        }
        

        # Treeview
        ttk::style configure Item -padding {4 0 0 0}
        

        package provide ttk::theme::vista 1.0
    }
}
Changes to library/xmfbox.tcl.
1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15






-
-
+
+







# xmfbox.tcl --
#
#	Implements the "Motif" style file selection dialog for the
#	Unix platform. This implementation is used only if the
#	"::tk_strictMotif" flag is set.
#
# Copyright (c) 1996 Sun Microsystems, Inc.
# Copyright (c) 1998-2000 Scriptics Corporation
# Copyright © 1996 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.

namespace eval ::tk::dialog {}
namespace eval ::tk::dialog::file {}

206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
206
207
208
209
210
211
212

213
214
215
216
217
218
219







-







# This proc gets called whenever data(filter) is set
#
proc ::tk::MotifFDialog_SetFilter {w type} {
    upvar ::tk::dialog::file::[winfo name $w] data
    variable ::tk::Priv

    set data(filter) [lindex $type 1]
    set Priv(selectFileType) [lindex [lindex $type 0] 0]

    MotifFDialog_Update $w
}

# ::tk::MotifFDialog_Config --
#
#	Iterates over the optional arguments to determine the option
903
904
905
906
907
908
909
910

911
912

913
914
915
916
917
918
919
902
903
904
905
906
907
908

909
910

911
912
913
914
915
916
917
918







-
+

-
+








    set Priv(selectFilePath) ""
    set Priv(selectFile)     ""
    set Priv(selectPath)     ""
}

proc ::tk::ListBoxKeyAccel_Set {w} {
    bind Listbox <Any-KeyPress> ""
    bind Listbox <Key> ""
    bind $w <Destroy> [list tk::ListBoxKeyAccel_Unset $w]
    bind $w <Any-KeyPress> [list tk::ListBoxKeyAccel_Key $w %A]
    bind $w <Key> [list tk::ListBoxKeyAccel_Key $w %A]
}

proc ::tk::ListBoxKeyAccel_Unset {w} {
    variable ::tk::Priv

    catch {after cancel $Priv(lbAccel,$w,afterId)}
    unset -nocomplain Priv(lbAccel,$w) Priv(lbAccel,$w,afterId)
977
978
979
980
981
982
983
984
985
986
987
988
989
976
977
978
979
980
981
982













-
-
-
-
-
-

proc ::tk::ListBoxKeyAccel_Reset {w} {
    variable ::tk::Priv

    unset -nocomplain Priv(lbAccel,$w)
}

proc ::tk_getFileType {} {
    variable ::tk::Priv

    return $Priv(selectFileType)
}

Added macosx/Credits.html.in.
























1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
<!doctype htmL>
<html>
<head>
</head>
<body style="font-size:120%;font-family:Arial,sans-serif;">
<p>
Tcl and Tk are distributed under a modified BSD license:<br>
<a href="https:www.tcl.tk/software/tcltk/license.html">
  https:www.tcl.tk/software/tcltk/license.html
</a>
</p>
<ul style="list-style-type:none;">
<li>&copy; 1987-@TK_YEAR@ Tcl Core Team and Contributers.</li>
<li>&copy; 2011-@TK_YEAR@ Kevin Walzer/WordTech Communications LLC.</li>
<li>&copy; 2014-@TK_YEAR@ Marc Culler.</li>
<li>&copy; 2002-2012 Daniel A. Steffen.</li>
<li>&copy; 2001-2009 Apple Inc.</li>
<li>&copy; 2001-2002 Jim Ingham &amp; Ian Reid.</li>
<li>&copy; 1998-2000 Jim Ingham &amp; Ray Johnson.</li>
<li>&copy; 1998-2000 Scriptics Inc.</li>
<li>&copy; 1996-1997 Sun Microsystems Inc.</li>
</ul>
</body>
</html>
Changes to macosx/GNUmakefile.
21
22
23
24
25
26
27

28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44












45
46
47
48
49
50
51
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64







+

















+
+
+
+
+
+
+
+
+
+
+
+







SYMROOT			?= ${BUILD_DIR}/${PROJECT}
OBJROOT			?= ${SYMROOT}

EXTRA_CONFIGURE_ARGS	?=
EXTRA_MAKE_ARGS		?=

INSTALL_PATH		?= /Library/Frameworks
TCL_INSTALL_PATH	?= ${INSTALL_PATH}/Tcl.framework
APPLICATION_INSTALL_PATH ?= /Applications/Utilities
PREFIX			?= /usr/local
BINDIR			?= ${PREFIX}/bin
LIBDIR			?= ${INSTALL_PATH}
MANDIR			?= ${PREFIX}/man

# tcl build directory (containing tclConfig.sh and Makefile)
TCL_BUILD_DIR		?= ${BUILD_DIR}/tcl/${BUILD_STYLE}
# location of installed tcl, only used if tcl in TCL_BUILD_DIR can't be found
TCL_FRAMEWORK_DIR	?= /Library/Frameworks
TCLSH_DIR		?= ${PREFIX}/bin

# set to non-empty value to install manpages in addition to html help:
INSTALL_MANPAGES	?=

# 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

#-------------------------------------------------------------------------------------------------------
# meta targets

meta			:= all install embedded install-embedded clean distclean test

styles			:= develop deploy
83
84
85
86
87
88
89
90

91
92
93
94
95
96
97
98
99
100
101
102
103
104
105

106
107
108
109
110

111
112
113
114
115
116
117
118

119
120
121
122
123
124
125
96
97
98
99
100
101
102

103
104
105
106
107
108
109
110
111
112
113
114
115
116
117

118
119
120
121
122

123
124
125
126
127
128
129
130

131
132
133
134
135
136
137
138







-
+














-
+




-
+







-
+







OBJ_DIR			= ${OBJROOT}/${BUILD_STYLE}

empty			:=
space			:= ${empty} ${empty}
objdir			= $(subst ${space},\ ,${OBJ_DIR})

develop_make_args	:= BUILD_STYLE=Development CONFIGURE_ARGS=--enable-symbols
deploy_make_args	:= BUILD_STYLE=Deployment INSTALL_TARGET=install-strip
deploy_make_args	:= BUILD_STYLE=Deployment INSTALL_TARGET=install
embedded_make_args	:= EMBEDDED_BUILD=1
install_make_args	:= INSTALL_BUILD=1

${targets}:
	${MAKE} ${action}${PROJECT} \
	$(foreach s,${styles} embedded install,$(if $(findstring $s,$@),${${s}_make_args}))

#-------------------------------------------------------------------------------------------------------
# project specific settings

PROJECT			:= tk
PRODUCT_NAME		:= Tk

UNIX_DIR		:= ${CURDIR}/../unix
VERSION			:= $(shell awk -F= '/^TK_VERSION/ {print $$2; nextfile}' ${UNIX_DIR}/configure.in)
VERSION			:= $(shell awk -F= '/^TK_VERSION/ {print $$2; nextfile}' ${UNIX_DIR}/configure.ac)
TCL_VERSION		:= ${VERSION}
wish			:= wish
WISH			= wish${VERSION}

BUILD_TARGET		:= all tktest
BUILD_TARGET		:= binaries libraries tktest
INSTALL_TARGET		:= install

ifneq ($(wildcard $(subst ${space},\ ,${TCL_BUILD_DIR})/tclConfig.sh),)
TCL_DIR			:= ${TCL_BUILD_DIR}
TCL_FRAMEWORK_DIR	:= ${TCL_BUILD_DIR}/..
MAKE_VARS		:=
else
TCL_DIR			:= ${TCL_FRAMEWORK_DIR}/Tcl.framework
TCL_DIR			:= ${TCL_INSTALL_PATH}
TCL_EXE			:= ${TCLSH_DIR}/tclsh${TCL_VERSION}
MAKE_VARS		:= TCL_EXE
export DYLD_FRAMEWORK_PATH := ${TCL_FRAMEWORK_DIR}
endif

export CPPROG		:= cp -p

176
177
178
179
180
181
182
183

184
185
186
187
188
189
190
189
190
191
192
193
194
195

196
197
198
199
200
201
202
203







-
+







	${MAKE} install-${PROJECT} INSTALL_ROOT="${OBJ_DIR}/"

${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-threads --enable-framework \
	--mandir="${MANDIR}" --enable-framework \
	--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
endif

206
207
208
209
210
211
212



213
214
215



216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231


232
233
234
235
236
237
238
239

240

241
242
243
244
245
246
247
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248


249
250
251
252
253
254
255
256
257

258
259
260
261
262
263
264
265
266
267







+
+
+



+
+
+














-
-
+
+







-
+

+







	rm -f Tcl.framework && ln -s "${TCL_FRAMEWORK_DIR}/Tcl.framework" . ; fi
endif

install-${PROJECT}: build-${PROJECT}
ifeq (${EMBEDDED_BUILD}_${INSTALL_ROOT},1_)
	@echo "Cannot install-embedded with empty INSTALL_ROOT !" && false
endif
ifeq (${SUBFRAMEWORK}_${DYLIB_INSTALL_DIR},1_)
	@echo "Cannot install subframework with empty DYLIB_INSTALL_DIR !" && false
endif
ifeq (${EMBEDDED_BUILD},1)
	@rm -rf "${INSTALL_ROOT}/${LIBDIR}/Tk.framework"
endif
ifeq (${SUBFRAMEWORK},1)
	@rm -rf "${INSTALL_ROOT}/Frameworks/Tk.framework"
endif
	${DO_MAKE}
ifeq (${EMBEDDED_BUILD}_${TK_X11},1_)
# workaround bug with 'cp -pRH' on Darwin 6 and earlier
	@if [ "`uname -r | awk -F. '{print $$1}'`" -lt 7 ]; then \
	mkdir -p "${TOP_DIR}"/{"${TCL_FMWK_DIR}","${TK_FMWK_DIR}"}/PrivateHeaders; fi
endif
ifeq (${INSTALL_BUILD},1)
ifeq (${EMBEDDED_BUILD},1)
# if we are embedding frameworks, don't install wish
	@rm -f "${INSTALL_ROOT}${BINDIR}/${WISH}" && \
	rmdir -p "${INSTALL_ROOT}${BINDIR}" 2>&- || true
else
# install wish symbolic link
	@ln -fs ${WISH} "${INSTALL_ROOT}${BINDIR}/${wish}"
endif
endif
endif # embedded
endif # install
ifeq (${BUILD_STYLE}_${EMBEDDED_BUILD},Development_)
# keep copy of debug library around, so that
# Deployment build can be installed on top
# of Development build without overwriting
# the debug library
	@cd "${INSTALL_ROOT}${LIBDIR}/${PRODUCT_NAME}.framework/Versions/${VERSION}" && \
	ln -f "${PRODUCT_NAME}" "${PRODUCT_NAME}_debug"
endif
endif # Development, not embedded
ifeq (${TK_X11},)
ifeq (${SUBFRAMEWORK},)
ifeq (${EMBEDDED_BUILD},)
# install Wish.app link in APPLICATION_INSTALL_PATH and setup 'Wish Shell' compatibility links
	@cd "${TOP_DIR}" && if [ -n "${APP_DIR}" ]; then mkdir -p "./${APP_DIR}" && rm -rf "./${APP_DIR}/Wish.app" && \
	ln -fsh "./$$(echo "${APP_DIR}" | sed -e 's#/[^/][^/]*#/..#g')/${FMWK_DIR}/${PRODUCT_NAME}.framework/Resources/Wish.app" "./${APP_DIR}" && \
	ln -fsh Wish.app "./${APP_DIR}/Wish Shell.app"; fi && \
	ln -fsh Wish.app "./${TK_FMWK_DIR}/Resources/Wish Shell.app" && \
	ln -fsh Wish "./${TK_FMWK_DIR}/Resources/Wish.app/Contents/MacOS/Wish Shell"
267
268
269
270
271
272
273

274
275
276



277
278
279
280
281
282
283
287
288
289
290
291
292
293
294



295
296
297
298
299
300
301
302
303
304







+
-
-
-
+
+
+







	    install_name_tool -change $$(otool -L "$$1" | awk "/$$2\.framework.*[^:]\$$/ {print \$$1; sub(\"^.*/Frameworks\",\"@executable_path/../Frameworks\",\$$1); print \$$1}") "$$1"; \
	    chmod -RH a-w "$$1"; \
	} && \
	fix_install_id Frameworks/Tcl.framework/Tcl Tcl && fix_install_id Frameworks/Tk.framework/Tk Tk && \
	fix_install_name MacOS/Wish Tcl && fix_install_name MacOS/Wish Tk
ifeq (${INSTALL_BUILD},1)
	@cd "${TOP_DIR}" && rm -rf "./${FMWK_DIR}"/T{cl,k}.framework && rmdir -p "./${FMWK_DIR}" 2>&- || true
endif # install not subframework
endif
endif
endif
endif # embedded
endif # not subframework
endif # not X11

clean-${PROJECT}: %-${PROJECT}:
	${DO_MAKE}
	rm -rf "${SYMROOT}"/{${PRODUCT_NAME}.framework,${WISH},tktest}
	rm -f "${OBJ_DIR}"{"${LIBDIR}","${BINDIR}"} && \
	rmdir -p "${OBJ_DIR}"$(dir $(subst ${space},\ ,${LIBDIR})) 2>&- || true && \
	rmdir -p "${OBJ_DIR}"$(dir $(subst ${space},\ ,${BINDIR})) 2>&- || true
Changes to macosx/README.
165
166
167
168
169
170
171
172

173
174
175
176
177

178
179
180
181
182
183
184
165
166
167
168
169
170
171

172
173
174
175
176

177
178
179
180
181
182
183
184







-
+




-
+







is available when Tk is built and run on macOS 10.14 (Mojave) or later.  In
that case the Ttk widgets all support the "Dark Mode" appearance which was
introduced in 10.14. The command accepts the following values for the optional
newAppearance option: "aqua", "darkaqua", or "auto".  If the appearance is set
to aqua or darkaqua then the window will be displayed with the corresponding
appearance independent of any preferences settings.  If it is set to "auto"
the appearance will be determined by the preferences.  This command can be
used to opt out of Dark Mode on a per-window basis. It may be best to run the "update" command before setting the appearance property, to allow the event loop to run.
used to opt out of Dark Mode on a per-window basis.  It may be best to run the "update" command before setting the appearance property, to allow the event loop to run.


- To determine the current appearance of a window in macOS 10.14 (Mojave) and
higher, one can use the command:
  tk::unsupported::MacWindowStyle isdark window?
  tk::unsupported::MacWindowStyle isdark
The boolean return value is true if the window is currently displayed with the
dark appearance.

- If you want to use Remote Debugging with Xcode, you need to set the
environment variable XCNOSTDIN to 1 in the Executable editor for Wish. That will
cause us to force closing stdin & stdout.  Otherwise, given how Xcode launches
Wish remotely, they will be left open and then Wish & gdb will fight for stdin.
268
269
270
271
272
273
274

275
276
277
278












279
280

281
282
283
284
285
286
287
288




289
290
291
292
293
294
295
268
269
270
271
272
273
274
275




276
277
278
279
280
281
282
283
284
285
286
287


288








289
290
291
292
293
294
295
296
297
298
299







+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
-
-
-
-
-
-
-
-
+
+
+
+







---------------------------------------

With the release of OSX 10.14 (Mojave), Apple introduced the DarkAqua
appearance.  Part of the implementation of the Dark Mode was to make
some of the named NSColors have dynamic values.  Apple calls these
"semantic colors" because the name does not specify a specific color,
but rather refers to the context in which the color should be used.
In particular, when a user selects Dark Mode in the system preferences
Tk now provides the following semantic colors as system colors:
systemTextColor, systemTextBackgroundColor, systemSelectedTextColor,
systemSelectedTextBackgroundColor, systemControlTextColor,
systemDisabledControlTextColor, systemLabelColor, and
these colors change appearance.  For example systemTextColor is dark in
Aqua and light in DarkAqua.

Tk now provides colors corresponding to all of the NSColors in Apple's System
ColorList.  The convention for naming these colors is that the Tk name is
generated by capitalizing the macOS name and adding the prefix "system". The
System ColorList differs between releases of macOS and some colors, such as
systemLinkColor and systemControlAccentColor, are simulated on older systems
which did not provide them.  The following colors are available on all
supported macOS releases, although newer systems will support additional
colors: systemControlAccentColor, systemControlTextColor,
systemDisabledControlTextColor, systemLabelColor, systemLinkColor,
systemControlAccentColor.  All of these except the last two were
present in OSX 10.0 (and those two are simulated in systems where they
systemPlaceholderTextColor, systemSelectedTextBackgroundColor,
do not exist).  The change in 10.14 was that the RGB color value of
these colors became dynamic, meaning that the color value can change
when the application appearance changes.  In particular, when a user
selects Dark Mode in the system preferences these colors change
appearance.  For example systemTextColor is dark in Aqua and light in
DarkAqua.  One additional color, systemSelectedTabTextColor, does not
exist in macOS but is used by Tk to match the different colors used
for Notebook tab text in different OS versions.
systemSelectedTextColor, systemSeparatorColor, systemTextBackgroundColor, and
systemTextColor.  One additional color, systemSelectedTabTextColor, does not
exist in macOS but is used by Tk to match the different colors used for
Notebook tab titles in different OS versions.

The default background and foreground colors of most of the Tk widgets
have been set to semantic colors, which means that the widgets will change
appearance, and remain usable, when Dark Mode is selected in the system
preferences.  However, to get a close match to the native Dark Mode style it
is recommended to use Ttk widgets when possible.

450
451
452
453
454
455
456














457
458
459
460
461
462
463
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481







+
+
+
+
+
+
+
+
+
+
+
+
+
+







If you used non-default install locations for Tcl.framework, specify them as
make overrides to the tk/macosx GNUmakefile, e.g.
	make -C tk${ver}/macosx \
	    TCL_FRAMEWORK_DIR=$HOME/Library/Frameworks TCLSH_DIR=$HOME/usr/bin
	sudo make -C tk${ver}/macosx install \
	    TCL_FRAMEWORK_DIR=$HOME/Library/Frameworks TCLSH_DIR=$HOME/usr/bin
The Makefile variables TCL_FRAMEWORK_DIR and TCLSH_DIR were added with Tk 8.4.3.

- To build a Tcl.framework and Tk.framework for use as subframeworks in another
framework, use the install-embedded target and set SUBFRAMEWORK=1.  Set the
DYLIB_INSTALL_DIR variable to the path which should be the install_name path of
the shared library and set the DESTDIR variable to the pathname of a staging
directory where the frameworks will be written.  The Tcl framework must be
built first.
For example, running the commands:
	make -C ../tcl8.6/macosx install-embedded SUBFRAMEWORK=1 DESTDIR=/tmp/tcltk \
	DYLIB_INSTALL_DIR=/Library/Frameworks/Some.framework/Versions/X.Y/Frameworks/Tcl.framework
	make -C macosx install-embedded SUBFRAMEWORK=1 DESTDIR=/tmp/tcltk \
	DYLIB_INSTALL_DIR=/Library/Frameworks/Some.framework/Versions/X.Y/Frameworks/Tk.framework
will produce a Tcl.framework and a Tk.framework usable as subframeworks of
Some.framework.  The frameworks will be found in /tmp/tcltk/Frameworks/

5. Details regarding the macOS port of Tk.
-------------------------------------------

5.1 About the event loop
~~~~~~~~~~~~~~~~~~~~~~~~

658
659
660
661
662
663
664
665
666


667
668
669
670
671
672
673


























674
675
676
677
678
679
680
676
677
678
679
680
681
682


683
684
685






686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718







-
-
+
+

-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







inefficient to iterate through all embedded windows in a Text widget,
looking for those which meet the scrolling area, the damage region
constructed by TkScrollWindow contains only the difference between the
source and destination rectangles for the scrolling.  The embedded
windows are redrawn within the DisplayText function by some
conditional code which is only used for macOS.

6.0 Virtual events on 10.14
~~~~~~~~~~~~~~~~~~~~~~~~~~~
6.0 Virtual events on macOS 10.14 and later
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

10.14 supports system appearance changes, and has added a "Dark Mode"
that casts all window frames and menus as black. Tk 8.6.9 has added two
virtual events, <<LightAqua>> and <<DarkAqua>>, to allow you to update
your Tk app's appearance when the system appearance changes. Just bind
your appearance-updating code to these virtual events and you will see
it triggered when the system appearance toggles between dark and light.
The 10.14 release added support for system appearance changes,
including a "Dark Mode" that renders all window frames and menus in
dark colors. Tk 8.6.11 provides three virtual events <<LightAqua>>,
<<DarkAqua>> and <<AppearanceChanged>>, to allow you to update your Tk
app's appearance when the system appearance changes.  These events are
generated in [NSView effectiveAppearanceChanged], which is called by
the Apple window manager when the General Preferences is changed
either by switching between Light Mode and Dark Mode or by changing
the Accent Color or Highlight Color.

The <<AppearanceChanged>> virtual event has a data string which can be
accessed with the %d substitution.  The format of the data string is
that it consists of 6 words:
  "Appearance XXXX Accent YYYY Highlight ZZZZ"
For example, the following code will print the current appearance
name, accent color and highlight color when the <<AppearanceChanged>>
virtual event fires:

bind . <<AppearanceChanged>> {
    array set data [split %d]
    puts "  Appearance: $data(Appearance)"
    puts "  Accent: $data(Accent)"
    puts "  Highlight: $data(Highlight)\n"
}



7.0 Mac Services
~~~~~~~~~~~~~~~~~~~~~~~~~~~

With 8.6.10, Tk supports the Mac's NSServices API, documented at
https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/SysServices/introduction.html#//apple_ref/doc/uid/10000101-SW1
and in TIP 536 and Tk's man page. Tk presents a simple,
Changes to macosx/Tk-Common.xcconfig.
19
20
21
22
23
24
25
26

27
28
29
30
31
32
33
34
35
36
37
38
39

40
41
42
43
44
45
46


19
20
21
22
23
24
25

26
27
28
29
30
31
32
33
34
35
36
37
38

39
40
41
42
43
44


45
46







-
+












-
+





-
-
+
+
GCC_PREFIX_HEADER = $(DERIVED_FILE_DIR)/tk/tkConfig.h
OTHER_CFLAGS = -imacros "$(DERIVED_FILE_DIR)/tcl/tclConfig.h" $(OTHER_CFLAGS)
GCC_GENERATE_DEBUGGING_SYMBOLS = YES
GCC_NO_COMMON_BLOCKS = YES
GCC_DYNAMIC_NO_PIC = YES
GCC_VERSION = 4.2
GCC = gcc-$(GCC_VERSION)
WARNING_CFLAGS = -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unused-value -Winit-self -Wpointer-arith -Wcast-align -Wdisabled-optimization -Winline $(WARNING_CFLAGS)
WARNING_CFLAGS = -Wall -Wextra -Wshadow -Wundef -Wwrite-strings -Wpointer-arith -Winit-self -Wcast-align -Wdisabled-optimization -Winline $(WARNING_CFLAGS)
REZ_RESOURCE_MAP_READ_ONLY = YES
APPLICATION_INSTALL_PATH = /Applications/Utilities
BINDIR = $(PREFIX)/bin
CFLAGS = $(CFLAGS)
CPPFLAGS = -mmacosx-version-min=$(MACOSX_DEPLOYMENT_TARGET) $(CPPFLAGS)
FRAMEWORK_INSTALL_PATH = /Library/Frameworks
INCLUDEDIR = $(PREFIX)/include
LIBDIR = $(PREFIX)/lib
MANDIR = $(PREFIX)/man
PER_ARCH_CFLAGS_ppc = -mcpu=G3 -mtune=G4 $(PER_ARCH_CFLAGS_ppc)
PREFIX = /usr/local
TCL_BUILD_DIR = $(OBJROOT)/../tcl/Tcl.build/$(CONFIGURATION)/Tcl.build/Objects
TCL_CONFIGURE_ARGS = --enable-threads --enable-dtrace
TCL_CONFIGURE_ARGS = --enable-dtrace
TCL_FRAMEWORK_DIR = $(SYMROOT)/../tcl/$(CONFIGURATION)
TCL_LIBRARY = $(LIBDIR)/tcl$(VERSION)
TCL_PACKAGE_PATH = "$(LIBDIR)"
TCL_DEFS = HAVE_TCL_CONFIG_H
TK_LIBRARY = $(LIBDIR)/tk$(VERSION)
TK_DEFS = HAVE_TK_CONFIG_H
VERSION = 8.6
TK_DEFS = HAVE_TK_CONFIG_H TCL_NO_DEPRECATED
VERSION = 8.7
Changes to macosx/Tk.xcode/project.pbxproj.
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1039
1040
1041
1042
1043
1044
1045

1046
1047
1048
1049
1050
1051
1052







-







		F966BBCE08F27A3B005CB29B /* tkMacOSXDebug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkMacOSXDebug.h; sourceTree = "<group>"; };
		F966BBCF08F27A3B005CB29B /* tkMacOSXDefault.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkMacOSXDefault.h; sourceTree = "<group>"; };
		F966BBD008F27A3B005CB29B /* tkMacOSXDialog.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXDialog.c; sourceTree = "<group>"; };
		F966BBD108F27A3B005CB29B /* tkMacOSXDraw.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXDraw.c; sourceTree = "<group>"; };
		F966BBD208F27A3B005CB29B /* tkMacOSXEmbed.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXEmbed.c; sourceTree = "<group>"; };
		F966BBD308F27A3B005CB29B /* tkMacOSXEntry.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXEntry.c; sourceTree = "<group>"; };
		F966BBD408F27A3B005CB29B /* tkMacOSXEvent.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXEvent.c; sourceTree = "<group>"; };
		F966BBD508F27A3B005CB29B /* tkMacOSXEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkMacOSXEvent.h; sourceTree = "<group>"; };
		F966BBD608F27A3B005CB29B /* tkMacOSXFont.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXFont.c; sourceTree = "<group>"; };
		F966BBD708F27A3B005CB29B /* tkMacOSXHLEvents.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXHLEvents.c; sourceTree = "<group>"; };
		F966BBD808F27A3B005CB29B /* tkMacOSXInit.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXInit.c; sourceTree = "<group>"; };
		F966BBDA08F27A3B005CB29B /* tkMacOSXInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkMacOSXInt.h; sourceTree = "<group>"; };
		F966BBDB08F27A3B005CB29B /* tkMacOSXKeyboard.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXKeyboard.c; sourceTree = "<group>"; };
		F966BBDC08F27A3B005CB29B /* tkMacOSXKeyEvent.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXKeyEvent.c; sourceTree = "<group>"; };
		F966BBDD08F27A3B005CB29B /* tkMacOSXMenu.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXMenu.c; sourceTree = "<group>"; };
1168
1169
1170
1171
1172
1173
1174
1175

1176
1177
1178
1179
1180
1181
1182
1167
1168
1169
1170
1171
1172
1173

1174
1175
1176
1177
1178
1179
1180
1181







-
+







		F966BC6608F27A3D005CB29B /* winMenu.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winMenu.test; sourceTree = "<group>"; };
		F966BC6708F27A3D005CB29B /* winSend.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winSend.test; sourceTree = "<group>"; };
		F966BC6808F27A3D005CB29B /* winWm.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winWm.test; sourceTree = "<group>"; };
		F966BC6908F27A3D005CB29B /* wm.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = wm.test; sourceTree = "<group>"; };
		F966BC6A08F27A3D005CB29B /* xmfbox.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = xmfbox.test; sourceTree = "<group>"; };
		F966BC6C08F27A3D005CB29B /* aclocal.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = aclocal.m4; sourceTree = "<group>"; };
		F966BC6D08F27A3D005CB29B /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = "<group>"; };
		F966BC6E08F27A3D005CB29B /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = "<group>"; };
		F966BC6E08F27A3D005CB29B /* configure.ac */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.ac; sourceTree = "<group>"; };
		F966BC6F08F27A3D005CB29B /* install-sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = "install-sh"; sourceTree = "<group>"; };
		F966BC7008F27A3D005CB29B /* installManPage */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = installManPage; sourceTree = "<group>"; };
		F966BC7108F27A3D005CB29B /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = "<group>"; };
		F966BC7208F27A3D005CB29B /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
		F966BC7308F27A3D005CB29B /* tcl.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tcl.m4; sourceTree = "<group>"; };
		F966BC7408F27A3D005CB29B /* tk.spec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tk.spec; sourceTree = "<group>"; };
		F966BC7508F27A3D005CB29B /* tkAppInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkAppInit.c; sourceTree = "<group>"; };
1207
1208
1209
1210
1211
1212
1213
1214

1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1206
1207
1208
1209
1210
1211
1212

1213
1214
1215

1216
1217
1218
1219
1220

1221
1222
1223
1224
1225
1226
1227







-
+


-





-







		F966BC8E08F27A3D005CB29B /* tkUnixSelect.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixSelect.c; sourceTree = "<group>"; };
		F966BC8F08F27A3D005CB29B /* tkUnixSend.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixSend.c; sourceTree = "<group>"; };
		F966BC9008F27A3D005CB29B /* tkUnixWm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixWm.c; sourceTree = "<group>"; };
		F966BC9108F27A3D005CB29B /* tkUnixXId.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixXId.c; sourceTree = "<group>"; };
		F966BC9408F27A3D005CB29B /* aclocal.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = aclocal.m4; sourceTree = "<group>"; };
		F966BC9508F27A3D005CB29B /* buildall.vc.bat */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = buildall.vc.bat; sourceTree = "<group>"; };
		F966BC9608F27A3E005CB29B /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = "<group>"; };
		F966BC9708F27A3E005CB29B /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = "<group>"; };
		F966BC9708F27A3E005CB29B /* configure.ac */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.ac; sourceTree = "<group>"; };
		F966BC9908F27A3E005CB29B /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = "<group>"; };
		F966BC9A08F27A3E005CB29B /* makefile.vc */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = makefile.vc; sourceTree = "<group>"; };
		F966BC9B08F27A3E005CB29B /* mkd.bat */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = mkd.bat; sourceTree = "<group>"; };
		F966BC9C08F27A3E005CB29B /* nmakehlp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nmakehlp.c; sourceTree = "<group>"; };
		F966BCEE08F27A3E005CB29B /* tk.rc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tk.rc; sourceTree = "<group>"; };
		F966BCEF08F27A3E005CB29B /* tk_base.rc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tk_base.rc; sourceTree = "<group>"; };
		F966BCF208F27A3E005CB29B /* wish.rc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = wish.rc; sourceTree = "<group>"; };
		F966BCF308F27A3E005CB29B /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
		F966BCF408F27A3E005CB29B /* rmd.bat */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = rmd.bat; sourceTree = "<group>"; };
		F966BCF508F27A3F005CB29B /* rules.vc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = rules.vc; sourceTree = "<group>"; };
		F966BCF608F27A3F005CB29B /* stubs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = stubs.c; sourceTree = "<group>"; };
		F966BCF708F27A3F005CB29B /* tcl.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tcl.m4; sourceTree = "<group>"; };
		F966BCF808F27A3F005CB29B /* tkConfig.sh.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tkConfig.sh.in; sourceTree = "<group>"; };
		F966BCF908F27A3F005CB29B /* tkWin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkWin.h; sourceTree = "<group>"; };
		F966BCFA08F27A3F005CB29B /* tkWin32Dll.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWin32Dll.c; sourceTree = "<group>"; };
		F966BCFB08F27A3F005CB29B /* tkWin3d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWin3d.c; sourceTree = "<group>"; };
1407
1408
1409
1410
1411
1412
1413
1414

1415
1416
1417
1418
1419
1420
1421
1404
1405
1406
1407
1408
1409
1410

1411
1412
1413
1414
1415
1416
1417
1418







-
+







		F96D3E1B08F272A5004A47F5 /* CrtChnlHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtChnlHdlr.3; sourceTree = "<group>"; };
		F96D3E1C08F272A5004A47F5 /* CrtCloseHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtCloseHdlr.3; sourceTree = "<group>"; };
		F96D3E1D08F272A5004A47F5 /* CrtCommand.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtCommand.3; sourceTree = "<group>"; };
		F96D3E1E08F272A5004A47F5 /* CrtFileHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtFileHdlr.3; sourceTree = "<group>"; };
		F96D3E1F08F272A5004A47F5 /* CrtInterp.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtInterp.3; sourceTree = "<group>"; };
		F96D3E2008F272A5004A47F5 /* CrtMathFnc.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtMathFnc.3; sourceTree = "<group>"; };
		F96D3E2108F272A5004A47F5 /* CrtObjCmd.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtObjCmd.3; sourceTree = "<group>"; };
		F96D3E2208F272A5004A47F5 /* CrtSlave.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtSlave.3; sourceTree = "<group>"; };
		F96D3E2208F272A5004A47F5 /* CrtAlias.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtAlias.3; sourceTree = "<group>"; };
		F96D3E2308F272A5004A47F5 /* CrtTimerHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtTimerHdlr.3; sourceTree = "<group>"; };
		F96D3E2408F272A5004A47F5 /* CrtTrace.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtTrace.3; sourceTree = "<group>"; };
		F96D3E2508F272A5004A47F5 /* dde.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = dde.n; sourceTree = "<group>"; };
		F96D3E2608F272A5004A47F5 /* DetachPids.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DetachPids.3; sourceTree = "<group>"; };
		F96D3E2708F272A5004A47F5 /* dict.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = dict.n; sourceTree = "<group>"; };
		F96D3E2808F272A5004A47F5 /* DictObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DictObj.3; sourceTree = "<group>"; };
		F96D3E2908F272A5004A47F5 /* DoOneEvent.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DoOneEvent.3; sourceTree = "<group>"; };
1911
1912
1913
1914
1915
1916
1917
1918

1919
1920
1921
1922
1923
1924
1925
1908
1909
1910
1911
1912
1913
1914

1915
1916
1917
1918
1919
1920
1921
1922







-
+







		F96D43CB08F272B7004A47F5 /* winFCmd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winFCmd.test; sourceTree = "<group>"; };
		F96D43CC08F272B7004A47F5 /* winFile.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winFile.test; sourceTree = "<group>"; };
		F96D43CD08F272B7004A47F5 /* winNotify.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winNotify.test; sourceTree = "<group>"; };
		F96D43CE08F272B7004A47F5 /* winPipe.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winPipe.test; sourceTree = "<group>"; };
		F96D43CF08F272B7004A47F5 /* winTime.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winTime.test; sourceTree = "<group>"; };
		F96D43D108F272B8004A47F5 /* checkLibraryDoc.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = checkLibraryDoc.tcl; sourceTree = "<group>"; };
		F96D43D208F272B8004A47F5 /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = "<group>"; };
		F96D43D308F272B8004A47F5 /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = "<group>"; };
		F96D43D308F272B8004A47F5 /* configure.ac */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.ac; sourceTree = "<group>"; };
		F96D442208F272B8004A47F5 /* eolFix.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = eolFix.tcl; sourceTree = "<group>"; };
		F96D442408F272B8004A47F5 /* fix_tommath_h.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = fix_tommath_h.tcl; sourceTree = "<group>"; };
		F96D442508F272B8004A47F5 /* genStubs.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = genStubs.tcl; sourceTree = "<group>"; };
		F96D442708F272B8004A47F5 /* index.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = index.tcl; sourceTree = "<group>"; };
		F96D442808F272B8004A47F5 /* installData.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = installData.tcl; sourceTree = "<group>"; };
		F96D442908F272B8004A47F5 /* loadICU.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = loadICU.tcl; sourceTree = "<group>"; };
		F96D442A08F272B8004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = "<group>"; };
1936
1937
1938
1939
1940
1941
1942
1943

1944
1945
1946
1947
1948
1949
1950
1933
1934
1935
1936
1937
1938
1939

1940
1941
1942
1943
1944
1945
1946
1947







-
+







		F96D443608F272B8004A47F5 /* tcl.wse.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.wse.in; sourceTree = "<group>"; };
		F96D443908F272B9004A47F5 /* tcltk-man2html.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "tcltk-man2html.tcl"; sourceTree = "<group>"; };
		F96D443A08F272B9004A47F5 /* tclZIC.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclZIC.tcl; sourceTree = "<group>"; };
		F96D443B08F272B9004A47F5 /* uniClass.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = uniClass.tcl; sourceTree = "<group>"; };
		F96D443C08F272B9004A47F5 /* uniParse.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = uniParse.tcl; sourceTree = "<group>"; };
		F96D444008F272B9004A47F5 /* aclocal.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = aclocal.m4; sourceTree = "<group>"; };
		F96D444108F272B9004A47F5 /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = "<group>"; };
		F96D444208F272B9004A47F5 /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = "<group>"; };
		F96D444208F272B9004A47F5 /* configure.ac */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.ac; sourceTree = "<group>"; };
		F96D444408F272B9004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = "<group>"; };
		F96D444508F272B9004A47F5 /* pkga.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkga.c; sourceTree = "<group>"; };
		F96D444608F272B9004A47F5 /* pkgb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgb.c; sourceTree = "<group>"; };
		F96D444708F272B9004A47F5 /* pkgc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgc.c; sourceTree = "<group>"; };
		F96D444808F272B9004A47F5 /* pkgd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgd.c; sourceTree = "<group>"; };
		F96D444908F272B9004A47F5 /* pkge.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkge.c; sourceTree = "<group>"; };
		F96D444B08F272B9004A47F5 /* pkgua.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgua.c; sourceTree = "<group>"; };
1980
1981
1982
1983
1984
1985
1986
1987

1988
1989
1990
1991
1992
1993
1994
1977
1978
1979
1980
1981
1982
1983

1984
1985
1986
1987
1988
1989
1990
1991







-
+







		F96D446B08F272B9004A47F5 /* tclUnixTime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixTime.c; sourceTree = "<group>"; };
		F96D446C08F272B9004A47F5 /* tclXtNotify.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclXtNotify.c; sourceTree = "<group>"; };
		F96D446D08F272B9004A47F5 /* tclXtTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclXtTest.c; sourceTree = "<group>"; };
		F96D447008F272BA004A47F5 /* aclocal.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = aclocal.m4; sourceTree = "<group>"; };
		F96D447108F272BA004A47F5 /* buildall.vc.bat */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = buildall.vc.bat; sourceTree = "<group>"; };
		F96D447208F272BA004A47F5 /* cat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cat.c; sourceTree = "<group>"; };
		F96D447408F272BA004A47F5 /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = "<group>"; };
		F96D447508F272BA004A47F5 /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = "<group>"; };
		F96D447508F272BA004A47F5 /* configure.ac */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.ac; sourceTree = "<group>"; };
		F96D447708F272BA004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = "<group>"; };
		F96D447808F272BA004A47F5 /* makefile.vc */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = makefile.vc; sourceTree = "<group>"; };
		F96D447908F272BA004A47F5 /* nmakehlp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nmakehlp.c; sourceTree = "<group>"; };
		F96D447A08F272BA004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
		F96D447C08F272BA004A47F5 /* rules.vc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = rules.vc; sourceTree = "<group>"; };
		F96D447D08F272BA004A47F5 /* stub16.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = stub16.c; sourceTree = "<group>"; };
		F96D447E08F272BA004A47F5 /* tcl.dsp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.dsp; sourceTree = "<group>"; };
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2579
2580
2581
2582
2583
2584
2585

2586
2587
2588
2589
2590
2591
2592







-







				F966BBCE08F27A3B005CB29B /* tkMacOSXDebug.h */,
				F966BBCF08F27A3B005CB29B /* tkMacOSXDefault.h */,
				F966BBD008F27A3B005CB29B /* tkMacOSXDialog.c */,
				F966BBD108F27A3B005CB29B /* tkMacOSXDraw.c */,
				F966BBD208F27A3B005CB29B /* tkMacOSXEmbed.c */,
				F966BBD308F27A3B005CB29B /* tkMacOSXEntry.c */,
				F966BBD408F27A3B005CB29B /* tkMacOSXEvent.c */,
				F966BBD508F27A3B005CB29B /* tkMacOSXEvent.h */,
				F966BBD608F27A3B005CB29B /* tkMacOSXFont.c */,
				F93E5EFD09CF8711008FA367 /* tkMacOSXFont.h */,
				F966BBD708F27A3B005CB29B /* tkMacOSXHLEvents.c */,
				F966BBD808F27A3B005CB29B /* tkMacOSXInit.c */,
				F966BBDA08F27A3B005CB29B /* tkMacOSXInt.h */,
				F966BBDB08F27A3B005CB29B /* tkMacOSXKeyboard.c */,
				F966BBDC08F27A3B005CB29B /* tkMacOSXKeyEvent.c */,
2736
2737
2738
2739
2740
2741
2742
2743

2744
2745
2746
2747
2748
2749
2750
2732
2733
2734
2735
2736
2737
2738

2739
2740
2741
2742
2743
2744
2745
2746







-
+







			sourceTree = "<group>";
		};
		F966BC6B08F27A3D005CB29B /* unix */ = {
			isa = PBXGroup;
			children = (
				F966BC6C08F27A3D005CB29B /* aclocal.m4 */,
				F966BC6D08F27A3D005CB29B /* configure */,
				F966BC6E08F27A3D005CB29B /* configure.in */,
				F966BC6E08F27A3D005CB29B /* configure.ac */,
				F966BC6F08F27A3D005CB29B /* install-sh */,
				F966BC7008F27A3D005CB29B /* installManPage */,
				F966BC7108F27A3D005CB29B /* Makefile.in */,
				F966BC7208F27A3D005CB29B /* README */,
				F966BC7308F27A3D005CB29B /* tcl.m4 */,
				F974D57B0FBE7EC000BF728B /* tk.pc.in */,
				F966BC7408F27A3D005CB29B /* tk.spec */,
2783
2784
2785
2786
2787
2788
2789
2790

2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2779
2780
2781
2782
2783
2784
2785

2786
2787
2788

2789
2790
2791
2792
2793
2794
2795







-
+


-







		};
		F966BC9208F27A3D005CB29B /* win */ = {
			isa = PBXGroup;
			children = (
				F966BC9408F27A3D005CB29B /* aclocal.m4 */,
				F966BC9508F27A3D005CB29B /* buildall.vc.bat */,
				F966BC9608F27A3E005CB29B /* configure */,
				F966BC9708F27A3E005CB29B /* configure.in */,
				F966BC9708F27A3E005CB29B /* configure.ac */,
				F966BC9908F27A3E005CB29B /* Makefile.in */,
				F966BC9A08F27A3E005CB29B /* makefile.vc */,
				F966BC9B08F27A3E005CB29B /* mkd.bat */,
				F966BC9C08F27A3E005CB29B /* nmakehlp.c */,
				F966BC9D08F27A3E005CB29B /* rc */,
				F966BCF308F27A3E005CB29B /* README */,
				F966BCF408F27A3E005CB29B /* rmd.bat */,
				F966BCF508F27A3F005CB29B /* rules.vc */,
				F966BCF608F27A3F005CB29B /* stubs.c */,
				F966BCF708F27A3F005CB29B /* tcl.m4 */,
3074
3075
3076
3077
3078
3079
3080
3081

3082
3083
3084
3085
3086
3087
3088
3069
3070
3071
3072
3073
3074
3075

3076
3077
3078
3079
3080
3081
3082
3083







-
+







				F96D3E1B08F272A5004A47F5 /* CrtChnlHdlr.3 */,
				F96D3E1C08F272A5004A47F5 /* CrtCloseHdlr.3 */,
				F96D3E1D08F272A5004A47F5 /* CrtCommand.3 */,
				F96D3E1E08F272A5004A47F5 /* CrtFileHdlr.3 */,
				F96D3E1F08F272A5004A47F5 /* CrtInterp.3 */,
				F96D3E2008F272A5004A47F5 /* CrtMathFnc.3 */,
				F96D3E2108F272A5004A47F5 /* CrtObjCmd.3 */,
				F96D3E2208F272A5004A47F5 /* CrtSlave.3 */,
				F96D3E2208F272A5004A47F5 /* CrtAlias.3 */,
				F96D3E2308F272A5004A47F5 /* CrtTimerHdlr.3 */,
				F96D3E2408F272A5004A47F5 /* CrtTrace.3 */,
				F96D3E2508F272A5004A47F5 /* dde.n */,
				F93599D30DF1F8F500E04F67 /* define.n */,
				F96D3E2608F272A5004A47F5 /* DetachPids.3 */,
				F96D3E2708F272A5004A47F5 /* dict.n */,
				F96D3E2808F272A5004A47F5 /* DictObj.3 */,
3718
3719
3720
3721
3722
3723
3724
3725

3726
3727
3728
3729
3730
3731
3732
3713
3714
3715
3716
3717
3718
3719

3720
3721
3722
3723
3724
3725
3726
3727







-
+







			sourceTree = "<group>";
		};
		F96D43D008F272B8004A47F5 /* tools */ = {
			isa = PBXGroup;
			children = (
				F96D43D108F272B8004A47F5 /* checkLibraryDoc.tcl */,
				F96D43D208F272B8004A47F5 /* configure */,
				F96D43D308F272B8004A47F5 /* configure.in */,
				F96D43D308F272B8004A47F5 /* configure.ac */,
				F96D442208F272B8004A47F5 /* eolFix.tcl */,
				F96D442408F272B8004A47F5 /* fix_tommath_h.tcl */,
				F96D442508F272B8004A47F5 /* genStubs.tcl */,
				F96D442708F272B8004A47F5 /* index.tcl */,
				F96D442808F272B8004A47F5 /* installData.tcl */,
				F96D442908F272B8004A47F5 /* loadICU.tcl */,
				F96D442A08F272B8004A47F5 /* Makefile.in */,
3751
3752
3753
3754
3755
3756
3757
3758

3759
3760
3761
3762
3763
3764
3765
3746
3747
3748
3749
3750
3751
3752

3753
3754
3755
3756
3757
3758
3759
3760







-
+







			sourceTree = "<group>";
		};
		F96D443E08F272B9004A47F5 /* unix */ = {
			isa = PBXGroup;
			children = (
				F96D444008F272B9004A47F5 /* aclocal.m4 */,
				F96D444108F272B9004A47F5 /* configure */,
				F96D444208F272B9004A47F5 /* configure.in */,
				F96D444208F272B9004A47F5 /* configure.ac */,
				F96D444308F272B9004A47F5 /* dltest */,
				F96D444D08F272B9004A47F5 /* install-sh */,
				F96D444E08F272B9004A47F5 /* installManPage */,
				F96D444F08F272B9004A47F5 /* ldAix */,
				F96D445008F272B9004A47F5 /* Makefile.in */,
				F96D445208F272B9004A47F5 /* README */,
				F96D445308F272B9004A47F5 /* tcl.m4 */,
3812
3813
3814
3815
3816
3817
3818
3819

3820
3821
3822
3823
3824
3825
3826
3807
3808
3809
3810
3811
3812
3813

3814
3815
3816
3817
3818
3819
3820
3821







-
+







		F96D446E08F272B9004A47F5 /* win */ = {
			isa = PBXGroup;
			children = (
				F96D447008F272BA004A47F5 /* aclocal.m4 */,
				F96D447108F272BA004A47F5 /* buildall.vc.bat */,
				F96D447208F272BA004A47F5 /* cat.c */,
				F96D447408F272BA004A47F5 /* configure */,
				F96D447508F272BA004A47F5 /* configure.in */,
				F96D447508F272BA004A47F5 /* configure.ac */,
				F96D447708F272BA004A47F5 /* Makefile.in */,
				F96D447808F272BA004A47F5 /* makefile.vc */,
				F96D447908F272BA004A47F5 /* nmakehlp.c */,
				F96D447A08F272BA004A47F5 /* README */,
				F96D447C08F272BA004A47F5 /* rules.vc */,
				F96D447D08F272BA004A47F5 /* stub16.c */,
				F96D447E08F272BA004A47F5 /* tcl.dsp */,
3964
3965
3966
3967
3968
3969
3970
3971

3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984

3985
3986
3987
3988
3989
3990
3991
3992
3993
3994

3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005

4006
4007
4008
4009
4010
4011
4012
4013
4014
4015

4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028

4029
4030
4031
4032
4033
4034
4035
4036
4037
4038

4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049

4050
4051
4052
4053
4054
4055
4056
3959
3960
3961
3962
3963
3964
3965

3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978

3979
3980
3981
3982
3983
3984
3985
3986
3987
3988

3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999

4000
4001
4002
4003
4004
4005
4006
4007
4008
4009

4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022

4023
4024
4025
4026
4027
4028
4029
4030
4031
4032

4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043

4044
4045
4046
4047
4048
4049
4050
4051







-
+












-
+









-
+










-
+









-
+












-
+









-
+










-
+







		F9A5C5F508F651A2008AE941 /* Configure Tcl */ = {
			isa = PBXShellScriptBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			inputPaths = (
				"$(TCL_SRCROOT)/macosx/configure.ac",
				"$(TCL_SRCROOT)/unix/configure.in",
				"$(TCL_SRCROOT)/unix/configure.ac",
				"$(TCL_SRCROOT)/unix/tcl.m4",
				"$(TCL_SRCROOT)/unix/aclocal.m4",
				"$(TCL_SRCROOT)/unix/tclConfig.sh.in",
				"$(TCL_SRCROOT)/unix/Makefile.in",
				"$(TCL_SRCROOT)/unix/dltest/Makefile.in",
			);
			name = "Configure Tcl";
			outputPaths = (
				"$(DERIVED_FILE_DIR)/tcl/tclConfig.sh",
			);
			runOnlyForDeploymentPostprocessing = 0;
			shellPath = /bin/bash;
			shellScript = "## tcl configure shell script phase\n\ncd \"${TCL_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.in -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n    echo \"Running autoconf & autoheader in tcl/macosx\"\n    rm -rf autom4te.cache\n    ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n    rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tcl && cd tcl &&\nif [ \"${TCL_SRCROOT}\"/macosx/configure -nt config.status ]; then\n    echo \"Configuring Tcl\"\n    CC=$(xcrun -find ${GCC} || echo ${GCC})\n    \"${TCL_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared CC=${CC} LD=${CC} ${CONFIGURE_ARGS}\nelse\n    ./config.status\nfi\n";
			shellScript = "## tcl configure shell script phase\n\ncd \"${TCL_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.ac -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n    echo \"Running autoconf & autoheader in tcl/macosx\"\n    rm -rf autom4te.cache\n    ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n    rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tcl && cd tcl &&\nif [ \"${TCL_SRCROOT}\"/macosx/configure -nt config.status ]; then\n    echo \"Configuring Tcl\"\n    CC=$(xcrun -find ${GCC} || echo ${GCC})\n    \"${TCL_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared CC=${CC} LD=${CC} ${CONFIGURE_ARGS}\nelse\n    ./config.status\nfi\n";
			showEnvVarsInLog = 0;
		};
		F9A5C5F608F651AB008AE941 /* Configure Tk */ = {
			isa = PBXShellScriptBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			inputPaths = (
				"$(TK_SRCROOT)/macosx/configure.ac",
				"$(TK_SRCROOT)/unix/configure.in",
				"$(TK_SRCROOT)/unix/configure.ac",
				"$(TK_SRCROOT)/unix/tcl.m4",
				"$(TK_SRCROOT)/unix/aclocal.m4",
				"$(TK_SRCROOT)/unix/tkConfig.sh.in",
			);
			name = "Configure Tk";
			outputPaths = (
				"$(DERIVED_FILE_DIR)/tk/tkConfig.sh",
			);
			runOnlyForDeploymentPostprocessing = 0;
			shellPath = /bin/bash;
			shellScript = "## tk configure shell script phase\n\ncd \"${TK_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.in -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n    echo \"Running autoconf & autoheader in tk/macosx\"\n    rm -rf autom4te.cache\n    ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n    rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tk && cd tk &&\nif [ \"${TK_SRCROOT}\"/macosx/configure -nt config.status ]; then\n    echo \"Configuring Tk\"\n    CC=$(xcrun -find ${GCC} || echo ${GCC})\n    \"${TK_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared --enable-aqua --with-tcl=../tcl CC=${CC} LD=${CC} ${CONFIGURE_ARGS}\nelse\n    ./config.status\nfi\n";
			shellScript = "## tk configure shell script phase\n\ncd \"${TK_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.ac -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n    echo \"Running autoconf & autoheader in tk/macosx\"\n    rm -rf autom4te.cache\n    ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n    rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tk && cd tk &&\nif [ \"${TK_SRCROOT}\"/macosx/configure -nt config.status ]; then\n    echo \"Configuring Tk\"\n    CC=$(xcrun -find ${GCC} || echo ${GCC})\n    \"${TK_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared --enable-aqua --with-tcl=../tcl CC=${CC} LD=${CC} ${CONFIGURE_ARGS}\nelse\n    ./config.status\nfi\n";
			showEnvVarsInLog = 0;
		};
		F9FD30B40CC1AD070073837D /* Configure Tcl */ = {
			isa = PBXShellScriptBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			inputPaths = (
				"$(TCL_SRCROOT)/macosx/configure.ac",
				"$(TCL_SRCROOT)/unix/configure.in",
				"$(TCL_SRCROOT)/unix/configure.ac",
				"$(TCL_SRCROOT)/unix/tcl.m4",
				"$(TCL_SRCROOT)/unix/aclocal.m4",
				"$(TCL_SRCROOT)/unix/tclConfig.sh.in",
				"$(TCL_SRCROOT)/unix/Makefile.in",
				"$(TCL_SRCROOT)/unix/dltest/Makefile.in",
			);
			name = "Configure Tcl";
			outputPaths = (
				"$(DERIVED_FILE_DIR)/tcl/tclConfig.sh",
			);
			runOnlyForDeploymentPostprocessing = 0;
			shellPath = /bin/bash;
			shellScript = "## tcl configure shell script phase\n\ncd \"${TCL_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.in -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n    echo \"Running autoconf & autoheader in tcl/macosx\"\n    rm -rf autom4te.cache\n    ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n    rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tcl && cd tcl &&\nif [ \"${TCL_SRCROOT}\"/macosx/configure -nt config.status ]; then\n    echo \"Configuring Tcl\"\n    CC=$(xcrun -find ${GCC} || echo ${GCC})\n    \"${TCL_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared CC=${CC} LD=${CC} ${CONFIGURE_ARGS}\nelse\n    ./config.status\nfi\n";
			shellScript = "## tcl configure shell script phase\n\ncd \"${TCL_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.ac -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n    echo \"Running autoconf & autoheader in tcl/macosx\"\n    rm -rf autom4te.cache\n    ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n    rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tcl && cd tcl &&\nif [ \"${TCL_SRCROOT}\"/macosx/configure -nt config.status ]; then\n    echo \"Configuring Tcl\"\n    CC=$(xcrun -find ${GCC} || echo ${GCC})\n    \"${TCL_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared CC=${CC} LD=${CC} ${CONFIGURE_ARGS}\nelse\n    ./config.status\nfi\n";
			showEnvVarsInLog = 0;
		};
		F9FD30B50CC1AD070073837D /* Configure Tk */ = {
			isa = PBXShellScriptBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			inputPaths = (
				"$(TK_SRCROOT)/macosx/configure.ac",
				"$(TK_SRCROOT)/unix/configure.in",
				"$(TK_SRCROOT)/unix/configure.ac",
				"$(TK_SRCROOT)/unix/tcl.m4",
				"$(TK_SRCROOT)/unix/aclocal.m4",
				"$(TK_SRCROOT)/unix/tkConfig.sh.in",
			);
			name = "Configure Tk";
			outputPaths = (
				"$(DERIVED_FILE_DIR)/tk/tkConfig.sh",
			);
			runOnlyForDeploymentPostprocessing = 0;
			shellPath = /bin/bash;
			shellScript = "## tk configure shell script phase\n\ncd \"${TK_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.in -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n    echo \"Running autoconf & autoheader in tk/macosx\"\n    rm -rf autom4te.cache\n    ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n    rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tk && cd tk &&\nif [ \"${TK_SRCROOT}\"/macosx/configure -nt config.status ]; then\n    echo \"Configuring Tk\"\n    CC=$(xcrun -find ${GCC} || echo ${GCC})\n    PATH=\"${PATH}:/usr/X11R6/bin\" \"${TK_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared --enable-xft --with-tcl=../tcl CC=${CC} LD=${CC} ${CONFIGURE_ARGS}\nelse\n    ./config.status\nfi";
			shellScript = "## tk configure shell script phase\n\ncd \"${TK_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.ac -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n    echo \"Running autoconf & autoheader in tk/macosx\"\n    rm -rf autom4te.cache\n    ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n    rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tk && cd tk &&\nif [ \"${TK_SRCROOT}\"/macosx/configure -nt config.status ]; then\n    echo \"Configuring Tk\"\n    CC=$(xcrun -find ${GCC} || echo ${GCC})\n    PATH=\"${PATH}:/usr/X11R6/bin\" \"${TK_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared --enable-xft --with-tcl=../tcl CC=${CC} LD=${CC} ${CONFIGURE_ARGS}\nelse\n    ./config.status\nfi";
			showEnvVarsInLog = 0;
		};
/* End PBXShellScriptBuildPhase section */

/* Begin PBXSourcesBuildPhase section */
		8DD76FAB0486AB0100D96B5E /* Sources */ = {
			isa = PBXSourcesBuildPhase;
Changes to macosx/Tk.xcodeproj/project.pbxproj.
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1039
1040
1041
1042
1043
1044
1045

1046
1047
1048
1049
1050
1051
1052







-







		F966BBCE08F27A3B005CB29B /* tkMacOSXDebug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkMacOSXDebug.h; sourceTree = "<group>"; };
		F966BBCF08F27A3B005CB29B /* tkMacOSXDefault.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkMacOSXDefault.h; sourceTree = "<group>"; };
		F966BBD008F27A3B005CB29B /* tkMacOSXDialog.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXDialog.c; sourceTree = "<group>"; };
		F966BBD108F27A3B005CB29B /* tkMacOSXDraw.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXDraw.c; sourceTree = "<group>"; };
		F966BBD208F27A3B005CB29B /* tkMacOSXEmbed.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXEmbed.c; sourceTree = "<group>"; };
		F966BBD308F27A3B005CB29B /* tkMacOSXEntry.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXEntry.c; sourceTree = "<group>"; };
		F966BBD408F27A3B005CB29B /* tkMacOSXEvent.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXEvent.c; sourceTree = "<group>"; };
		F966BBD508F27A3B005CB29B /* tkMacOSXEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkMacOSXEvent.h; sourceTree = "<group>"; };
		F966BBD608F27A3B005CB29B /* tkMacOSXFont.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXFont.c; sourceTree = "<group>"; };
		F966BBD708F27A3B005CB29B /* tkMacOSXHLEvents.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXHLEvents.c; sourceTree = "<group>"; };
		F966BBD808F27A3B005CB29B /* tkMacOSXInit.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXInit.c; sourceTree = "<group>"; };
		F966BBDA08F27A3B005CB29B /* tkMacOSXInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkMacOSXInt.h; sourceTree = "<group>"; };
		F966BBDB08F27A3B005CB29B /* tkMacOSXKeyboard.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXKeyboard.c; sourceTree = "<group>"; };
		F966BBDC08F27A3B005CB29B /* tkMacOSXKeyEvent.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXKeyEvent.c; sourceTree = "<group>"; };
		F966BBDD08F27A3B005CB29B /* tkMacOSXMenu.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = tkMacOSXMenu.c; sourceTree = "<group>"; };
1168
1169
1170
1171
1172
1173
1174
1175

1176
1177
1178
1179
1180
1181
1182
1167
1168
1169
1170
1171
1172
1173

1174
1175
1176
1177
1178
1179
1180
1181







-
+







		F966BC6608F27A3D005CB29B /* winMenu.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winMenu.test; sourceTree = "<group>"; };
		F966BC6708F27A3D005CB29B /* winSend.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winSend.test; sourceTree = "<group>"; };
		F966BC6808F27A3D005CB29B /* winWm.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winWm.test; sourceTree = "<group>"; };
		F966BC6908F27A3D005CB29B /* wm.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = wm.test; sourceTree = "<group>"; };
		F966BC6A08F27A3D005CB29B /* xmfbox.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = xmfbox.test; sourceTree = "<group>"; };
		F966BC6C08F27A3D005CB29B /* aclocal.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = aclocal.m4; sourceTree = "<group>"; };
		F966BC6D08F27A3D005CB29B /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = "<group>"; };
		F966BC6E08F27A3D005CB29B /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = "<group>"; };
		F966BC6E08F27A3D005CB29B /* configure.ac */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.ac; sourceTree = "<group>"; };
		F966BC6F08F27A3D005CB29B /* install-sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = "install-sh"; sourceTree = "<group>"; };
		F966BC7008F27A3D005CB29B /* installManPage */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = installManPage; sourceTree = "<group>"; };
		F966BC7108F27A3D005CB29B /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = "<group>"; };
		F966BC7208F27A3D005CB29B /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
		F966BC7308F27A3D005CB29B /* tcl.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tcl.m4; sourceTree = "<group>"; };
		F966BC7408F27A3D005CB29B /* tk.spec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tk.spec; sourceTree = "<group>"; };
		F966BC7508F27A3D005CB29B /* tkAppInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkAppInit.c; sourceTree = "<group>"; };
1207
1208
1209
1210
1211
1212
1213
1214

1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1206
1207
1208
1209
1210
1211
1212

1213
1214
1215

1216
1217
1218
1219
1220

1221
1222
1223
1224
1225
1226
1227







-
+


-





-







		F966BC8E08F27A3D005CB29B /* tkUnixSelect.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixSelect.c; sourceTree = "<group>"; };
		F966BC8F08F27A3D005CB29B /* tkUnixSend.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixSend.c; sourceTree = "<group>"; };
		F966BC9008F27A3D005CB29B /* tkUnixWm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixWm.c; sourceTree = "<group>"; };
		F966BC9108F27A3D005CB29B /* tkUnixXId.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkUnixXId.c; sourceTree = "<group>"; };
		F966BC9408F27A3D005CB29B /* aclocal.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = aclocal.m4; sourceTree = "<group>"; };
		F966BC9508F27A3D005CB29B /* buildall.vc.bat */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = buildall.vc.bat; sourceTree = "<group>"; };
		F966BC9608F27A3E005CB29B /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = "<group>"; };
		F966BC9708F27A3E005CB29B /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = "<group>"; };
		F966BC9708F27A3E005CB29B /* configure.ac */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.ac; sourceTree = "<group>"; };
		F966BC9908F27A3E005CB29B /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = "<group>"; };
		F966BC9A08F27A3E005CB29B /* makefile.vc */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = makefile.vc; sourceTree = "<group>"; };
		F966BC9B08F27A3E005CB29B /* mkd.bat */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = mkd.bat; sourceTree = "<group>"; };
		F966BC9C08F27A3E005CB29B /* nmakehlp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nmakehlp.c; sourceTree = "<group>"; };
		F966BCEE08F27A3E005CB29B /* tk.rc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tk.rc; sourceTree = "<group>"; };
		F966BCEF08F27A3E005CB29B /* tk_base.rc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tk_base.rc; sourceTree = "<group>"; };
		F966BCF208F27A3E005CB29B /* wish.rc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = wish.rc; sourceTree = "<group>"; };
		F966BCF308F27A3E005CB29B /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
		F966BCF408F27A3E005CB29B /* rmd.bat */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = rmd.bat; sourceTree = "<group>"; };
		F966BCF508F27A3F005CB29B /* rules.vc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = rules.vc; sourceTree = "<group>"; };
		F966BCF608F27A3F005CB29B /* stubs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = stubs.c; sourceTree = "<group>"; };
		F966BCF708F27A3F005CB29B /* tcl.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tcl.m4; sourceTree = "<group>"; };
		F966BCF808F27A3F005CB29B /* tkConfig.sh.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tkConfig.sh.in; sourceTree = "<group>"; };
		F966BCF908F27A3F005CB29B /* tkWin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tkWin.h; sourceTree = "<group>"; };
		F966BCFA08F27A3F005CB29B /* tkWin32Dll.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWin32Dll.c; sourceTree = "<group>"; };
		F966BCFB08F27A3F005CB29B /* tkWin3d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkWin3d.c; sourceTree = "<group>"; };
1407
1408
1409
1410
1411
1412
1413
1414

1415
1416
1417
1418
1419
1420
1421
1404
1405
1406
1407
1408
1409
1410

1411
1412
1413
1414
1415
1416
1417
1418







-
+







		F96D3E1B08F272A5004A47F5 /* CrtChnlHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtChnlHdlr.3; sourceTree = "<group>"; };
		F96D3E1C08F272A5004A47F5 /* CrtCloseHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtCloseHdlr.3; sourceTree = "<group>"; };
		F96D3E1D08F272A5004A47F5 /* CrtCommand.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtCommand.3; sourceTree = "<group>"; };
		F96D3E1E08F272A5004A47F5 /* CrtFileHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtFileHdlr.3; sourceTree = "<group>"; };
		F96D3E1F08F272A5004A47F5 /* CrtInterp.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtInterp.3; sourceTree = "<group>"; };
		F96D3E2008F272A5004A47F5 /* CrtMathFnc.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtMathFnc.3; sourceTree = "<group>"; };
		F96D3E2108F272A5004A47F5 /* CrtObjCmd.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtObjCmd.3; sourceTree = "<group>"; };
		F96D3E2208F272A5004A47F5 /* CrtSlave.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtSlave.3; sourceTree = "<group>"; };
		F96D3E2208F272A5004A47F5 /* CrtAlias.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtAlias.3; sourceTree = "<group>"; };
		F96D3E2308F272A5004A47F5 /* CrtTimerHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtTimerHdlr.3; sourceTree = "<group>"; };
		F96D3E2408F272A5004A47F5 /* CrtTrace.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtTrace.3; sourceTree = "<group>"; };
		F96D3E2508F272A5004A47F5 /* dde.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = dde.n; sourceTree = "<group>"; };
		F96D3E2608F272A5004A47F5 /* DetachPids.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DetachPids.3; sourceTree = "<group>"; };
		F96D3E2708F272A5004A47F5 /* dict.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = dict.n; sourceTree = "<group>"; };
		F96D3E2808F272A5004A47F5 /* DictObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DictObj.3; sourceTree = "<group>"; };
		F96D3E2908F272A5004A47F5 /* DoOneEvent.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DoOneEvent.3; sourceTree = "<group>"; };
1911
1912
1913
1914
1915
1916
1917
1918

1919
1920
1921
1922
1923
1924
1925
1908
1909
1910
1911
1912
1913
1914

1915
1916
1917
1918
1919
1920
1921
1922







-
+







		F96D43CB08F272B7004A47F5 /* winFCmd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winFCmd.test; sourceTree = "<group>"; };
		F96D43CC08F272B7004A47F5 /* winFile.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winFile.test; sourceTree = "<group>"; };
		F96D43CD08F272B7004A47F5 /* winNotify.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winNotify.test; sourceTree = "<group>"; };
		F96D43CE08F272B7004A47F5 /* winPipe.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winPipe.test; sourceTree = "<group>"; };
		F96D43CF08F272B7004A47F5 /* winTime.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winTime.test; sourceTree = "<group>"; };
		F96D43D108F272B8004A47F5 /* checkLibraryDoc.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = checkLibraryDoc.tcl; sourceTree = "<group>"; };
		F96D43D208F272B8004A47F5 /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = "<group>"; };
		F96D43D308F272B8004A47F5 /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = "<group>"; };
		F96D43D308F272B8004A47F5 /* configure.ac */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.ac; sourceTree = "<group>"; };
		F96D442208F272B8004A47F5 /* eolFix.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = eolFix.tcl; sourceTree = "<group>"; };
		F96D442408F272B8004A47F5 /* fix_tommath_h.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = fix_tommath_h.tcl; sourceTree = "<group>"; };
		F96D442508F272B8004A47F5 /* genStubs.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = genStubs.tcl; sourceTree = "<group>"; };
		F96D442708F272B8004A47F5 /* index.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = index.tcl; sourceTree = "<group>"; };
		F96D442808F272B8004A47F5 /* installData.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = installData.tcl; sourceTree = "<group>"; };
		F96D442908F272B8004A47F5 /* loadICU.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = loadICU.tcl; sourceTree = "<group>"; };
		F96D442A08F272B8004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = "<group>"; };
1936
1937
1938
1939
1940
1941
1942
1943

1944
1945
1946
1947
1948
1949
1950
1933
1934
1935
1936
1937
1938
1939

1940
1941
1942
1943
1944
1945
1946
1947







-
+







		F96D443608F272B8004A47F5 /* tcl.wse.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.wse.in; sourceTree = "<group>"; };
		F96D443908F272B9004A47F5 /* tcltk-man2html.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "tcltk-man2html.tcl"; sourceTree = "<group>"; };
		F96D443A08F272B9004A47F5 /* tclZIC.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclZIC.tcl; sourceTree = "<group>"; };
		F96D443B08F272B9004A47F5 /* uniClass.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = uniClass.tcl; sourceTree = "<group>"; };
		F96D443C08F272B9004A47F5 /* uniParse.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = uniParse.tcl; sourceTree = "<group>"; };
		F96D444008F272B9004A47F5 /* aclocal.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = aclocal.m4; sourceTree = "<group>"; };
		F96D444108F272B9004A47F5 /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = "<group>"; };
		F96D444208F272B9004A47F5 /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = "<group>"; };
		F96D444208F272B9004A47F5 /* configure.ac */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.ac; sourceTree = "<group>"; };
		F96D444408F272B9004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = "<group>"; };
		F96D444508F272B9004A47F5 /* pkga.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkga.c; sourceTree = "<group>"; };
		F96D444608F272B9004A47F5 /* pkgb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgb.c; sourceTree = "<group>"; };
		F96D444708F272B9004A47F5 /* pkgc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgc.c; sourceTree = "<group>"; };
		F96D444808F272B9004A47F5 /* pkgd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgd.c; sourceTree = "<group>"; };
		F96D444908F272B9004A47F5 /* pkge.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkge.c; sourceTree = "<group>"; };
		F96D444B08F272B9004A47F5 /* pkgua.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgua.c; sourceTree = "<group>"; };
1980
1981
1982
1983
1984
1985
1986
1987

1988
1989
1990
1991
1992
1993
1994
1977
1978
1979
1980
1981
1982
1983

1984
1985
1986
1987
1988
1989
1990
1991







-
+







		F96D446B08F272B9004A47F5 /* tclUnixTime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixTime.c; sourceTree = "<group>"; };
		F96D446C08F272B9004A47F5 /* tclXtNotify.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclXtNotify.c; sourceTree = "<group>"; };
		F96D446D08F272B9004A47F5 /* tclXtTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclXtTest.c; sourceTree = "<group>"; };
		F96D447008F272BA004A47F5 /* aclocal.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = aclocal.m4; sourceTree = "<group>"; };
		F96D447108F272BA004A47F5 /* buildall.vc.bat */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = buildall.vc.bat; sourceTree = "<group>"; };
		F96D447208F272BA004A47F5 /* cat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cat.c; sourceTree = "<group>"; };
		F96D447408F272BA004A47F5 /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = "<group>"; };
		F96D447508F272BA004A47F5 /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = "<group>"; };
		F96D447508F272BA004A47F5 /* configure.ac */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.ac; sourceTree = "<group>"; };
		F96D447708F272BA004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = "<group>"; };
		F96D447808F272BA004A47F5 /* makefile.vc */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = makefile.vc; sourceTree = "<group>"; };
		F96D447908F272BA004A47F5 /* nmakehlp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nmakehlp.c; sourceTree = "<group>"; };
		F96D447A08F272BA004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
		F96D447C08F272BA004A47F5 /* rules.vc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = rules.vc; sourceTree = "<group>"; };
		F96D447D08F272BA004A47F5 /* stub16.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = stub16.c; sourceTree = "<group>"; };
		F96D447E08F272BA004A47F5 /* tcl.dsp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.dsp; sourceTree = "<group>"; };
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2579
2580
2581
2582
2583
2584
2585

2586
2587
2588
2589
2590
2591
2592







-







				F966BBCE08F27A3B005CB29B /* tkMacOSXDebug.h */,
				F966BBCF08F27A3B005CB29B /* tkMacOSXDefault.h */,
				F966BBD008F27A3B005CB29B /* tkMacOSXDialog.c */,
				F966BBD108F27A3B005CB29B /* tkMacOSXDraw.c */,
				F966BBD208F27A3B005CB29B /* tkMacOSXEmbed.c */,
				F966BBD308F27A3B005CB29B /* tkMacOSXEntry.c */,
				F966BBD408F27A3B005CB29B /* tkMacOSXEvent.c */,
				F966BBD508F27A3B005CB29B /* tkMacOSXEvent.h */,
				F966BBD608F27A3B005CB29B /* tkMacOSXFont.c */,
				F93E5EFD09CF8711008FA367 /* tkMacOSXFont.h */,
				F966BBD708F27A3B005CB29B /* tkMacOSXHLEvents.c */,
				F966BBD808F27A3B005CB29B /* tkMacOSXInit.c */,
				F966BBDA08F27A3B005CB29B /* tkMacOSXInt.h */,
				F966BBDB08F27A3B005CB29B /* tkMacOSXKeyboard.c */,
				F966BBDC08F27A3B005CB29B /* tkMacOSXKeyEvent.c */,
2736
2737
2738
2739
2740
2741
2742
2743

2744
2745
2746
2747
2748
2749
2750
2732
2733
2734
2735
2736
2737
2738

2739
2740
2741
2742
2743
2744
2745
2746







-
+







			sourceTree = "<group>";
		};
		F966BC6B08F27A3D005CB29B /* unix */ = {
			isa = PBXGroup;
			children = (
				F966BC6C08F27A3D005CB29B /* aclocal.m4 */,
				F966BC6D08F27A3D005CB29B /* configure */,
				F966BC6E08F27A3D005CB29B /* configure.in */,
				F966BC6E08F27A3D005CB29B /* configure.ac */,
				F966BC6F08F27A3D005CB29B /* install-sh */,
				F966BC7008F27A3D005CB29B /* installManPage */,
				F966BC7108F27A3D005CB29B /* Makefile.in */,
				F966BC7208F27A3D005CB29B /* README */,
				F966BC7308F27A3D005CB29B /* tcl.m4 */,
				F974D57B0FBE7EC000BF728B /* tk.pc.in */,
				F966BC7408F27A3D005CB29B /* tk.spec */,
2783
2784
2785
2786
2787
2788
2789
2790

2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2779
2780
2781
2782
2783
2784
2785

2786
2787
2788

2789
2790
2791

2792
2793
2794
2795
2796
2797
2798







-
+


-



-







		};
		F966BC9208F27A3D005CB29B /* win */ = {
			isa = PBXGroup;
			children = (
				F966BC9408F27A3D005CB29B /* aclocal.m4 */,
				F966BC9508F27A3D005CB29B /* buildall.vc.bat */,
				F966BC9608F27A3E005CB29B /* configure */,
				F966BC9708F27A3E005CB29B /* configure.in */,
				F966BC9708F27A3E005CB29B /* configure.ac */,
				F966BC9908F27A3E005CB29B /* Makefile.in */,
				F966BC9A08F27A3E005CB29B /* makefile.vc */,
				F966BC9B08F27A3E005CB29B /* mkd.bat */,
				F966BC9C08F27A3E005CB29B /* nmakehlp.c */,
				F966BC9D08F27A3E005CB29B /* rc */,
				F966BCF308F27A3E005CB29B /* README */,
				F966BCF408F27A3E005CB29B /* rmd.bat */,
				F966BCF508F27A3F005CB29B /* rules.vc */,
				F966BCF608F27A3F005CB29B /* stubs.c */,
				F966BCF708F27A3F005CB29B /* tcl.m4 */,
				F966BCF808F27A3F005CB29B /* tkConfig.sh.in */,
				F966BCF908F27A3F005CB29B /* tkWin.h */,
				F966BCFA08F27A3F005CB29B /* tkWin32Dll.c */,
				F966BCFB08F27A3F005CB29B /* tkWin3d.c */,
3074
3075
3076
3077
3078
3079
3080
3081

3082
3083
3084
3085
3086
3087
3088
3068
3069
3070
3071
3072
3073
3074

3075
3076
3077
3078
3079
3080
3081
3082







-
+







				F96D3E1B08F272A5004A47F5 /* CrtChnlHdlr.3 */,
				F96D3E1C08F272A5004A47F5 /* CrtCloseHdlr.3 */,
				F96D3E1D08F272A5004A47F5 /* CrtCommand.3 */,
				F96D3E1E08F272A5004A47F5 /* CrtFileHdlr.3 */,
				F96D3E1F08F272A5004A47F5 /* CrtInterp.3 */,
				F96D3E2008F272A5004A47F5 /* CrtMathFnc.3 */,
				F96D3E2108F272A5004A47F5 /* CrtObjCmd.3 */,
				F96D3E2208F272A5004A47F5 /* CrtSlave.3 */,
				F96D3E2208F272A5004A47F5 /* CrtAlias.3 */,
				F96D3E2308F272A5004A47F5 /* CrtTimerHdlr.3 */,
				F96D3E2408F272A5004A47F5 /* CrtTrace.3 */,
				F96D3E2508F272A5004A47F5 /* dde.n */,
				F93599D30DF1F8F500E04F67 /* define.n */,
				F96D3E2608F272A5004A47F5 /* DetachPids.3 */,
				F96D3E2708F272A5004A47F5 /* dict.n */,
				F96D3E2808F272A5004A47F5 /* DictObj.3 */,
3718
3719
3720
3721
3722
3723
3724
3725

3726
3727
3728
3729
3730
3731
3732
3712
3713
3714
3715
3716
3717
3718

3719
3720
3721
3722
3723
3724
3725
3726







-
+







			sourceTree = "<group>";
		};
		F96D43D008F272B8004A47F5 /* tools */ = {
			isa = PBXGroup;
			children = (
				F96D43D108F272B8004A47F5 /* checkLibraryDoc.tcl */,
				F96D43D208F272B8004A47F5 /* configure */,
				F96D43D308F272B8004A47F5 /* configure.in */,
				F96D43D308F272B8004A47F5 /* configure.ac */,
				F96D442208F272B8004A47F5 /* eolFix.tcl */,
				F96D442408F272B8004A47F5 /* fix_tommath_h.tcl */,
				F96D442508F272B8004A47F5 /* genStubs.tcl */,
				F96D442708F272B8004A47F5 /* index.tcl */,
				F96D442808F272B8004A47F5 /* installData.tcl */,
				F96D442908F272B8004A47F5 /* loadICU.tcl */,
				F96D442A08F272B8004A47F5 /* Makefile.in */,
3751
3752
3753
3754
3755
3756
3757
3758

3759
3760
3761
3762
3763
3764
3765
3745
3746
3747
3748
3749
3750
3751

3752
3753
3754
3755
3756
3757
3758
3759







-
+







			sourceTree = "<group>";
		};
		F96D443E08F272B9004A47F5 /* unix */ = {
			isa = PBXGroup;
			children = (
				F96D444008F272B9004A47F5 /* aclocal.m4 */,
				F96D444108F272B9004A47F5 /* configure */,
				F96D444208F272B9004A47F5 /* configure.in */,
				F96D444208F272B9004A47F5 /* configure.ac */,
				F96D444308F272B9004A47F5 /* dltest */,
				F96D444D08F272B9004A47F5 /* install-sh */,
				F96D444E08F272B9004A47F5 /* installManPage */,
				F96D444F08F272B9004A47F5 /* ldAix */,
				F96D445008F272B9004A47F5 /* Makefile.in */,
				F96D445208F272B9004A47F5 /* README */,
				F96D445308F272B9004A47F5 /* tcl.m4 */,
3812
3813
3814
3815
3816
3817
3818
3819

3820
3821
3822
3823
3824
3825
3826
3806
3807
3808
3809
3810
3811
3812

3813
3814
3815
3816
3817
3818
3819
3820







-
+







		F96D446E08F272B9004A47F5 /* win */ = {
			isa = PBXGroup;
			children = (
				F96D447008F272BA004A47F5 /* aclocal.m4 */,
				F96D447108F272BA004A47F5 /* buildall.vc.bat */,
				F96D447208F272BA004A47F5 /* cat.c */,
				F96D447408F272BA004A47F5 /* configure */,
				F96D447508F272BA004A47F5 /* configure.in */,
				F96D447508F272BA004A47F5 /* configure.ac */,
				F96D447708F272BA004A47F5 /* Makefile.in */,
				F96D447808F272BA004A47F5 /* makefile.vc */,
				F96D447908F272BA004A47F5 /* nmakehlp.c */,
				F96D447A08F272BA004A47F5 /* README */,
				F96D447C08F272BA004A47F5 /* rules.vc */,
				F96D447D08F272BA004A47F5 /* stub16.c */,
				F96D447E08F272BA004A47F5 /* tcl.dsp */,
3967
3968
3969
3970
3971
3972
3973
3974

3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987

3988
3989
3990
3991
3992
3993
3994
3995
3996
3997

3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008

4009
4010
4011
4012
4013
4014
4015
4016
4017
4018

4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031

4032
4033
4034
4035
4036
4037
4038
4039
4040
4041

4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052

4053
4054
4055
4056
4057
4058
4059
3961
3962
3963
3964
3965
3966
3967

3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980

3981
3982
3983
3984
3985
3986
3987
3988
3989
3990

3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001

4002
4003
4004
4005
4006
4007
4008
4009
4010
4011

4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024

4025
4026
4027
4028
4029
4030
4031
4032
4033
4034

4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045

4046
4047
4048
4049
4050
4051
4052
4053







-
+












-
+









-
+










-
+









-
+












-
+









-
+










-
+







		F9A5C5F508F651A2008AE941 /* Configure Tcl */ = {
			isa = PBXShellScriptBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			inputPaths = (
				"$(TCL_SRCROOT)/macosx/configure.ac",
				"$(TCL_SRCROOT)/unix/configure.in",
				"$(TCL_SRCROOT)/unix/configure.ac",
				"$(TCL_SRCROOT)/unix/tcl.m4",
				"$(TCL_SRCROOT)/unix/aclocal.m4",
				"$(TCL_SRCROOT)/unix/tclConfig.sh.in",
				"$(TCL_SRCROOT)/unix/Makefile.in",
				"$(TCL_SRCROOT)/unix/dltest/Makefile.in",
			);
			name = "Configure Tcl";
			outputPaths = (
				"$(DERIVED_FILE_DIR)/tcl/tclConfig.sh",
			);
			runOnlyForDeploymentPostprocessing = 0;
			shellPath = /bin/bash;
			shellScript = "## tcl configure shell script phase\n\ncd \"${TCL_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.in -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n    echo \"Running autoconf & autoheader in tcl/macosx\"\n    rm -rf autom4te.cache\n    ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n    rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tcl && cd tcl &&\nif [ \"${TCL_SRCROOT}\"/macosx/configure -nt config.status ]; then\n    echo \"Configuring Tcl\"\n    CC=$(xcrun -find ${GCC} || echo ${GCC})\n    \"${TCL_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared CC=${CC} LD=${CC} ${CONFIGURE_ARGS}\nelse\n    ./config.status\nfi\n";
			shellScript = "## tcl configure shell script phase\n\ncd \"${TCL_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.ac -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n    echo \"Running autoconf & autoheader in tcl/macosx\"\n    rm -rf autom4te.cache\n    ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n    rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tcl && cd tcl &&\nif [ \"${TCL_SRCROOT}\"/macosx/configure -nt config.status ]; then\n    echo \"Configuring Tcl\"\n    CC=$(xcrun -find ${GCC} || echo ${GCC})\n    \"${TCL_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared CC=${CC} LD=${CC} ${CONFIGURE_ARGS}\nelse\n    ./config.status\nfi\n";
			showEnvVarsInLog = 0;
		};
		F9A5C5F608F651AB008AE941 /* Configure Tk */ = {
			isa = PBXShellScriptBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			inputPaths = (
				"$(TK_SRCROOT)/macosx/configure.ac",
				"$(TK_SRCROOT)/unix/configure.in",
				"$(TK_SRCROOT)/unix/configure.ac",
				"$(TK_SRCROOT)/unix/tcl.m4",
				"$(TK_SRCROOT)/unix/aclocal.m4",
				"$(TK_SRCROOT)/unix/tkConfig.sh.in",
			);
			name = "Configure Tk";
			outputPaths = (
				"$(DERIVED_FILE_DIR)/tk/tkConfig.sh",
			);
			runOnlyForDeploymentPostprocessing = 0;
			shellPath = /bin/bash;
			shellScript = "## tk configure shell script phase\n\ncd \"${TK_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.in -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n    echo \"Running autoconf & autoheader in tk/macosx\"\n    rm -rf autom4te.cache\n    ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n    rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tk && cd tk &&\nif [ \"${TK_SRCROOT}\"/macosx/configure -nt config.status ]; then\n    echo \"Configuring Tk\"\n    CC=$(xcrun -find ${GCC} || echo ${GCC})\n    \"${TK_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared --enable-aqua --with-tcl=../tcl CC=${CC} LD=${CC} ${CONFIGURE_ARGS}\nelse\n    ./config.status\nfi\n";
			shellScript = "## tk configure shell script phase\n\ncd \"${TK_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.ac -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n    echo \"Running autoconf & autoheader in tk/macosx\"\n    rm -rf autom4te.cache\n    ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n    rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tk && cd tk &&\nif [ \"${TK_SRCROOT}\"/macosx/configure -nt config.status ]; then\n    echo \"Configuring Tk\"\n    CC=$(xcrun -find ${GCC} || echo ${GCC})\n    \"${TK_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared --enable-aqua --with-tcl=../tcl CC=${CC} LD=${CC} ${CONFIGURE_ARGS}\nelse\n    ./config.status\nfi\n";
			showEnvVarsInLog = 0;
		};
		F9FD30B40CC1AD070073837D /* Configure Tcl */ = {
			isa = PBXShellScriptBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			inputPaths = (
				"$(TCL_SRCROOT)/macosx/configure.ac",
				"$(TCL_SRCROOT)/unix/configure.in",
				"$(TCL_SRCROOT)/unix/configure.ac",
				"$(TCL_SRCROOT)/unix/tcl.m4",
				"$(TCL_SRCROOT)/unix/aclocal.m4",
				"$(TCL_SRCROOT)/unix/tclConfig.sh.in",
				"$(TCL_SRCROOT)/unix/Makefile.in",
				"$(TCL_SRCROOT)/unix/dltest/Makefile.in",
			);
			name = "Configure Tcl";
			outputPaths = (
				"$(DERIVED_FILE_DIR)/tcl/tclConfig.sh",
			);
			runOnlyForDeploymentPostprocessing = 0;
			shellPath = /bin/bash;
			shellScript = "## tcl configure shell script phase\n\ncd \"${TCL_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.in -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n    echo \"Running autoconf & autoheader in tcl/macosx\"\n    rm -rf autom4te.cache\n    ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n    rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tcl && cd tcl &&\nif [ \"${TCL_SRCROOT}\"/macosx/configure -nt config.status ]; then\n    echo \"Configuring Tcl\"\n    CC=$(xcrun -find ${GCC} || echo ${GCC})\n    \"${TCL_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared CC=${CC} LD=${CC} ${CONFIGURE_ARGS}\nelse\n    ./config.status\nfi\n";
			shellScript = "## tcl configure shell script phase\n\ncd \"${TCL_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.ac -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n    echo \"Running autoconf & autoheader in tcl/macosx\"\n    rm -rf autom4te.cache\n    ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n    rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tcl && cd tcl &&\nif [ \"${TCL_SRCROOT}\"/macosx/configure -nt config.status ]; then\n    echo \"Configuring Tcl\"\n    CC=$(xcrun -find ${GCC} || echo ${GCC})\n    \"${TCL_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared CC=${CC} LD=${CC} ${CONFIGURE_ARGS}\nelse\n    ./config.status\nfi\n";
			showEnvVarsInLog = 0;
		};
		F9FD30B50CC1AD070073837D /* Configure Tk */ = {
			isa = PBXShellScriptBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			inputPaths = (
				"$(TK_SRCROOT)/macosx/configure.ac",
				"$(TK_SRCROOT)/unix/configure.in",
				"$(TK_SRCROOT)/unix/configure.ac",
				"$(TK_SRCROOT)/unix/tcl.m4",
				"$(TK_SRCROOT)/unix/aclocal.m4",
				"$(TK_SRCROOT)/unix/tkConfig.sh.in",
			);
			name = "Configure Tk";
			outputPaths = (
				"$(DERIVED_FILE_DIR)/tk/tkConfig.sh",
			);
			runOnlyForDeploymentPostprocessing = 0;
			shellPath = /bin/bash;
			shellScript = "## tk configure shell script phase\n\ncd \"${TK_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.in -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n    echo \"Running autoconf & autoheader in tk/macosx\"\n    rm -rf autom4te.cache\n    ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n    rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tk && cd tk &&\nif [ \"${TK_SRCROOT}\"/macosx/configure -nt config.status ]; then\n    echo \"Configuring Tk\"\n    CC=$(xcrun -find ${GCC} || echo ${GCC})\n    PATH=\"${PATH}:/usr/X11R6/bin\" \"${TK_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared --enable-xft --with-tcl=../tcl CC=${CC} LD=${CC} ${CONFIGURE_ARGS}\nelse\n    ./config.status\nfi";
			shellScript = "## tk configure shell script phase\n\ncd \"${TK_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.ac -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n    echo \"Running autoconf & autoheader in tk/macosx\"\n    rm -rf autom4te.cache\n    ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n    rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tk && cd tk &&\nif [ \"${TK_SRCROOT}\"/macosx/configure -nt config.status ]; then\n    echo \"Configuring Tk\"\n    CC=$(xcrun -find ${GCC} || echo ${GCC})\n    PATH=\"${PATH}:/usr/X11R6/bin\" \"${TK_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared --enable-xft --with-tcl=../tcl CC=${CC} LD=${CC} ${CONFIGURE_ARGS}\nelse\n    ./config.status\nfi";
			showEnvVarsInLog = 0;
		};
/* End PBXShellScriptBuildPhase section */

/* Begin PBXSourcesBuildPhase section */
		8DD76FAB0486AB0100D96B5E /* Sources */ = {
			isa = PBXSourcesBuildPhase;
Changes to macosx/configure.ac.
1
2
3
4
5
6
7
8
9
10
11

1
2
3
4
5
6
7
8
9
10

11










-
+
#! /bin/bash -norc
dnl	This file is an input file used by the GNU "autoconf" program to
dnl	generate the file "configure", which is run during Tk installation
dnl	to configure the system for the local environment.

dnl	Ensure that the config (auto)headers support is used, then just
dnl	include the configure sources from ../unix:

m4_include(../unix/aclocal.m4)
m4_define(SC_USE_CONFIG_HEADERS)
m4_include(../unix/configure.in)
m4_include(../unix/configure.ac)
Changes to macosx/tkMacOSX.h.
22
23
24
25
26
27
28
29

30
31
32
33
34
22
23
24
25
26
27
28

29
30
31
32
33
34







-
+





 * Structures and function types for handling Netscape-type in process
 * embedding where Tk does not control the top-level
 */

typedef int (Tk_MacOSXEmbedRegisterWinProc) (long winID, Tk_Window window);
typedef void* (Tk_MacOSXEmbedGetGrafPortProc) (Tk_Window window);
typedef int (Tk_MacOSXEmbedMakeContainerExistProc) (Tk_Window window);
typedef void (Tk_MacOSXEmbedGetClipProc) (Tk_Window window, TkRegion rgn);
typedef void (Tk_MacOSXEmbedGetClipProc) (Tk_Window window, void *rgn);
typedef void (Tk_MacOSXEmbedGetOffsetInParentProc) (Tk_Window window, void *ulCorner);

#include "tkPlatDecls.h"

#endif /* _TKMAC */
Changes to macosx/tkMacOSXBitmap.c.
1
2
3
4
5
6
7
8



9
10
11
12
13
14
15
1
2
3
4
5



6
7
8
9
10
11
12
13
14
15





-
-
-
+
+
+







/*
 * 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 <[email protected]>
 * Copyright © 1996-1997 Sun Microsystems, Inc.
 * Copyright © 2001-2009 Apple Inc.
 * Copyright © 2006-2009 Daniel A. Steffen <[email protected]>
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tkMacOSXPrivate.h"
#include "tkMacOSXConstants.h"
40
41
42
43
44
45
46
47

48
49
50
51
52
53
54
40
41
42
43
44
45
46

47
48
49
50
51
52
53
54







-
+







    {"ramdisk",		kGenericRAMDiskIcon},
    {"cdrom",		kGenericCDROMIcon},
    {"preferences",	kGenericPreferencesIcon},
    {"querydoc",	kGenericQueryDocumentIcon},
    {"stop",		kAlertStopIcon},
    {"note",		kAlertNoteIcon},
    {"caution",		kAlertCautionIcon},
    {NULL}
    {NULL,			0}
};

#define builtInIconSize 32

#define OSTYPE_TO_UTI(x) (NSString *)UTTypeCreatePreferredIdentifierForTag( \
     kUTTagClassOSType, UTCreateStringForOSType(x), nil)

96
97
98
99
100
101
102
103

104
105
106
107
108
109
110
96
97
98
99
100
101
102

103
104
105
106
107
108
109
110







-
+







	Tcl_HashEntry *predefHashPtr;
	Tk_Uid name;
	int isNew;

	name = Tk_GetUid(builtInPtr->name);
	predefHashPtr = Tcl_CreateHashEntry(tablePtr, name, &isNew);
	if (isNew) {
	    TkPredefBitmap *predefPtr = ckalloc(sizeof(TkPredefBitmap));
	    TkPredefBitmap *predefPtr = (TkPredefBitmap *)ckalloc(sizeof(TkPredefBitmap));

	    predefPtr->source = UINT2PTR(builtInPtr->iconType);
	    predefPtr->width = builtInIconSize;
	    predefPtr->height = builtInIconSize;
	    predefPtr->native = 1;
	    Tcl_SetHashValue(predefHashPtr, predefPtr);
	}
132
133
134
135
136
137
138
139

140
141
142
143
144
145

146
147
148
149
150
151
152
153
154
132
133
134
135
136
137
138

139
140
141
142
143
144

145


146
147
148
149
150
151
152







-
+





-
+
-
-







    NSImage* image,
    CGSize size)
{
    TkMacOSXDrawingContext dc;
    Pixmap pixmap;

    pixmap = Tk_GetPixmap(display, None, size.width, size.height, 0);
    if (TkMacOSXSetupDrawingContext(pixmap, NULL, 1, &dc)) {
    if (TkMacOSXSetupDrawingContext(pixmap, NULL, &dc)) {
	if (dc.context) {
	    CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1,
				    .tx = 0, .ty = size.height};
	    CGContextConcatCTM(dc.context, t);
	    [NSGraphicsContext saveGraphicsState];
	    [NSGraphicsContext setCurrentContext:[NSGraphicsContext
	    [NSGraphicsContext setCurrentContext:GET_NSCONTEXT(dc.context, NO)];
		graphicsContextWithGraphicsPort:dc.context
		flipped:NO]];
	    [image drawAtPoint:NSZeroPoint fromRect:NSZeroRect
		operation:NSCompositeCopy fraction:1.0];
	    [NSGraphicsContext restoreGraphicsState];
	}
	TkMacOSXRestoreDrawingContext(&dc);
    }
    return pixmap;
176
177
178
179
180
181
182
183

184
185
186
187
188
189
190
174
175
176
177
178
179
180

181
182
183
184
185
186
187
188







-
+







    Display *display,
    const void *source)		/* Info about the icon to build. */
{
    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;
}


/*
 *----------------------------------------------------------------------
 *
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
311
312
313
314
315
316
317

318
319
320
321
322
323
324







-







	*width = size.width;
	*height = size.height;
	pixmap = PixmapFromImage(display, image, NSSizeToCGSize(size));
    } else if (name) {
	OSType iconType;
	if (OSTypeFromString(name, &iconType) == TCL_OK) {
	    NSString *iconUTI = OSTYPE_TO_UTI(iconType);
	    printf("Found image for UTI %s\n", iconUTI.UTF8String);
	    NSImage *iconImage = [[NSWorkspace sharedWorkspace]
				     iconForFileType: iconUTI];
	    pixmap = PixmapFromImage(display, iconImage, NSSizeToCGSize(size));
	}
    }
    return pixmap;
}
340
341
342
343
344
345
346
347

348
349
350
351
352
353
354
337
338
339
340
341
342
343

344
345
346
347
348
349
350
351







-
+







 *	none
 *
 *----------------------------------------------------------------------
 */

int
TkMacOSXIconBitmapObjCmd(
    ClientData clientData,	/* Unused. */
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_HashEntry *hPtr;
    int i = 1, len, isNew, result = TCL_ERROR;
    const char *name, *value;
395
396
397
398
399
400
401
402

403
404
405
406
407
408
409
410
411
412

413
414
415
416
417
418
419
392
393
394
395
396
397
398

399
400
401
402
403
404
405
406
407
408

409
410
411
412
413
414
415
416







-
+









-
+







	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "invalid bitmap value", -1));
	    Tcl_SetErrorCode(interp, "TK", "MACBITMAP", "INVALID", NULL);
	    goto end;
	}
    }
#endif
    ib.value = ckalloc(len + 1);
    ib.value = (char *)ckalloc(len + 1);
    strcpy(ib.value, value);
    if (!iconBitmapTable.buckets) {
	Tcl_InitHashTable(&iconBitmapTable, TCL_STRING_KEYS);
    }
    hPtr = Tcl_CreateHashEntry(&iconBitmapTable, name, &isNew);
    if (!isNew) {
	iconBitmap = Tcl_GetHashValue(hPtr);
	ckfree(iconBitmap->value);
    } else {
	iconBitmap = ckalloc(sizeof(IconBitmap));
	iconBitmap = (IconBitmap *)ckalloc(sizeof(IconBitmap));
	Tcl_SetHashValue(hPtr, iconBitmap);
    }
    *iconBitmap = ib;
    result = TCL_OK;
  end:
    return result;
}
Changes to macosx/tkMacOSXButton.c.
1
2
3
4
5
6
7
8
9
10
11
12






13
14
15
16
17
18
19
1
2
3
4
5
6






7
8
9
10
11
12
13
14
15
16
17
18
19






-
-
-
-
-
-
+
+
+
+
+
+







/*
 * 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 <[email protected]>
 * 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 <[email protected]>
 * 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.
 *
 */

#include "tkMacOSXPrivate.h"
91
92
93
94
95
96
97


98
99
100
101
102
103
104
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106







+
+







/*
 * The class procedure table for the button widgets.
 */

const Tk_ClassProcs tkpButtonProcs = {
    sizeof(Tk_ClassProcs),	/* size */
    TkButtonWorldChanged,	/* worldChangedProc */
    NULL,
	NULL
};

static int bCount;

/*
 *----------------------------------------------------------------------
 *
139
140
141
142
143
144
145
146

147
148
149
150
151
152
153
141
142
143
144
145
146
147

148
149
150
151
152
153
154
155







-
+







 *----------------------------------------------------------------------
 */

TkButton *
TkpCreateButton(
    Tk_Window tkwin)
{
    MacButton *macButtonPtr = ckalloc(sizeof(MacButton));
    MacButton *macButtonPtr = (MacButton *)ckalloc(sizeof(MacButton));

    Tk_CreateEventHandler(tkwin, ActivateMask,
	    ButtonEventProc, macButtonPtr);
    macButtonPtr->id = bCount++;
    macButtonPtr->flags = FIRST_DRAW;
    macButtonPtr->btnkind = kThemePushButton;
    macButtonPtr->defaultPulseHandler = NULL;
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
184
185
186
187
188
189
190



191
192
193
194
195
196







197
198
199
200
201
202
203







-
-
-






-
-
-
-
-
-
-







    MacButton *macButtonPtr = clientData;
    TkButton *butPtr = clientData;
    Tk_Window tkwin = butPtr->tkwin;
    Pixmap pixmap;
    DrawParams* dpPtr = &macButtonPtr->drawParams;
    int needhighlight = 0;

    if (butPtr->flags & BUTTON_DELETED) {
	return;
    }
    butPtr->flags &= ~REDRAW_PENDING;
    if ((butPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {
	return;
    }
    pixmap = (Pixmap) Tk_WindowId(tkwin);

    /*
     * Set up clipping region. Make sure the we are using the port
     * for this button, or we will set the wrong window's clip.
     */

    TkMacOSXSetUpClippingRgn(Tk_WindowId(tkwin));

    if (TkMacOSXComputeButtonDrawParams(butPtr, dpPtr)) {
	macButtonPtr->useTkText = 0;
    } else {
	macButtonPtr->useTkText = 1;
    }
    if (macButtonPtr->useTkText) {
	if (butPtr->type == TYPE_BUTTON) {
328
329
330
331
332
333
334

335
336
337
338
339
340
341







342
343
344
345
346
347
348
349
350








351
352
353
354
355
356
357
358







359
360
361
362
363
364
365






366
367


368
369
370
371
372
373
374
320
321
322
323
324
325
326
327







328
329
330
331
332
333
334
335








336
337
338
339
340
341
342
343
344







345
346
347
348
349
350
351
352






353
354
355
356
357
358


359
360
361
362
363
364
365
366
367







+
-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+
-
-
+
+







		&butPtr->textWidth, &butPtr->textHeight);

	txtWidth = butPtr->textWidth + 2*butPtr->padX;
	txtHeight = butPtr->textHeight + 2*butPtr->padY;
	haveText = 1;
    }

    if (haveImage) {
    if (haveImage && haveText) { /* Image and Text */
	switch ((enum compound) butPtr->compound) {
	case COMPOUND_TOP:
	case COMPOUND_BOTTOM:
	    /*
	     * Image is above or below text.
	     */
	if (haveText) { /* Image and Text */
	    switch ((enum compound) butPtr->compound) {
	    case COMPOUND_TOP:
	    case COMPOUND_BOTTOM:
		/*
		* Image is above or below text.
		*/

	    height += txtHeight + butPtr->padY;
	    width = (width > txtWidth ? width : txtWidth);
	    break;
	case COMPOUND_LEFT:
	case COMPOUND_RIGHT:
	    /*
	     * Image is left or right of text.
	     */
		height += txtHeight + butPtr->padY;
		width = (width > txtWidth ? width : txtWidth);
		break;
	    case COMPOUND_LEFT:
	    case COMPOUND_RIGHT:
		/*
		* Image is left or right of text.
		*/

	    width += txtWidth + 2*butPtr->padX;
	    height = (height > txtHeight ? height : txtHeight);
	    break;
	case COMPOUND_CENTER:
	    /*
	     * Image and text are superimposed.
	     */
		width += txtWidth + 2*butPtr->padX;
		height = (height > txtHeight ? height : txtHeight);
		break;
	    case COMPOUND_CENTER:
		/*
		* Image and text are superimposed.
		*/

	    width = (width > txtWidth ? width : txtWidth);
	    height = (height > txtHeight ? height : txtHeight);
	    break;
	default:
	    break;
	}
		width = (width > txtWidth ? width : txtWidth);
		height = (height > txtHeight ? height : txtHeight);
		break;
	    default:
		break;
	    }
	width += butPtr->indicatorSpace;
    } else if (haveImage) { /* Image only */
	}
	/* Image with or without text */
	width = butPtr->width > 0 ? butPtr->width : width + butPtr->indicatorSpace;
	height = butPtr->height > 0 ? butPtr->height : height;
	if (butPtr->type == TYPE_BUTTON) {
	    /*
	     * Allow room to shift the image.
	     */
	    width += 2;
395
396
397
398
399
400
401
402

403
404
405
406
407
408
409
388
389
390
391
392
393
394

395
396
397
398
399
400
401
402







-
+







	butPtr->highlightWidth = 0;
    }

    butPtr->inset = butPtr->borderWidth + butPtr->highlightWidth;

    width += butPtr->inset*2;
    height += butPtr->inset*2;
    if ([NSApp macMinorVersion] == 6) {
    if ([NSApp macOSVersion] == 100600) {
	width += 12;
    }
    if (mbPtr->btnkind == kThemePushButton) {
        HIRect tmpRect;
    	HIRect contBounds;

	/*
461
462
463
464
465
466
467
468

469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484

485
486
487
488
489
490
491
454
455
456
457
458
459
460

461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476

477
478
479
480
481
482
483
484







-
+















-
+








    if (tkwin == NULL || !Tk_IsMapped(tkwin)) {
        return;
    }

    pixmap = (Pixmap) Tk_WindowId(tkwin);

    if (butPtr->image != None) {
    if (butPtr->image != NULL) {
        Tk_SizeOfImage(butPtr->image, &width, &height);
        haveImage = 1;
    } else if (butPtr->bitmap != None) {
        Tk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height);
        haveImage = 1;
    }

    imageWidth = width;
    imageHeight = height;

    if (mbPtr->drawinfo.state == kThemeStatePressed) {
        pressed = 1;
    }

    haveText = (butPtr->textWidth != 0 && butPtr->textHeight != 0);
    if (haveImage && haveText) { /* Image and Text */
    if (butPtr->compound != COMPOUND_NONE && haveImage && haveText) { /* Image and Text */
        int x, y;

        switch ((enum compound) butPtr->compound) {
	case COMPOUND_TOP:
	case COMPOUND_BOTTOM:
	    /* Image is above or below text */
	    if (butPtr->compound == COMPOUND_TOP) {
722
723
724
725
726
727
728
729

730
731
732
733
734
735
736
715
716
717
718
719
720
721

722
723
724
725
726
727
728
729







-
+







 *
 *--------------------------------------------------------------
 */

static void
TkMacOSXDrawButton(
    MacButton *mbPtr,    /* Mac button. */
    GC gc,               /* The GC we are drawing into - needed for
    TCL_UNUSED(GC),      /* The GC we are drawing into - needed for
                          * the bevel button */
    Pixmap pixmap)       /* The pixmap we are drawing into - needed
                          * for the bevel button */
{
    TkButton *butPtr = (TkButton *) mbPtr;
    TkWindow *winPtr = (TkWindow *) butPtr->tkwin;
    HIRect cntrRect;
747
748
749
750
751
752
753
754

755
756
757
758
759
760
761
740
741
742
743
744
745
746

747
748
749
750
751
752
753
754







-
+








    if (useNewerHITools == 1) {
        HIRect contHIRec;
        static HIThemeButtonDrawInfo hiinfo;

        ButtonBackgroundDrawCB(&cntrRect, mbPtr, 32, true);

	if (!TkMacOSXSetupDrawingContext(pixmap, dpPtr->gc, 1, &dc)) {
	if (!TkMacOSXSetupDrawingContext(pixmap, dpPtr->gc, &dc)) {
	    return;
	}

        hiinfo.version = 0;
        hiinfo.state = mbPtr->drawinfo.state;
        hiinfo.kind = mbPtr->btnkind;
        hiinfo.value = mbPtr->drawinfo.value;
780
781
782
783
784
785
786
787

788
789
790
791
792
793
794
773
774
775
776
777
778
779

780
781
782
783
784
785
786
787







-
+







	HIThemeDrawButton(&cntrRect, &hiinfo, dc.context,
		kHIThemeOrientationNormal, &contHIRec);

	TkMacOSXRestoreDrawingContext(&dc);
        ButtonContentDrawCB(&contHIRec, mbPtr->btnkind, &mbPtr->drawinfo,
		(MacButton *) mbPtr, 32, true);
    } else {
	if (!TkMacOSXSetupDrawingContext(pixmap, dpPtr->gc, 1, &dc)) {
	if (!TkMacOSXSetupDrawingContext(pixmap, dpPtr->gc, &dc)) {
	    return;
	}

	TkMacOSXRestoreDrawingContext(&dc);
    }
    mbPtr->lastdrawinfo = mbPtr->drawinfo;
}
808
809
810
811
812
813
814
815

816
817
818


819
820
821
822
823
824
825
801
802
803
804
805
806
807

808
809


810
811
812
813
814
815
816
817
818







-
+

-
-
+
+







 *        The background gets updated to the current color.
 *
 *--------------------------------------------------------------
 */

static void
ButtonBackgroundDrawCB(
    const HIRect *btnbounds,
    TCL_UNUSED(const HIRect *),
    MacButton *ptr,
    SInt16 depth,
    Boolean isColorDev)
    TCL_UNUSED(SInt16),
    TCL_UNUSED(Boolean))
{
    MacButton *mbPtr = (MacButton *) ptr;
    TkButton *butPtr = (TkButton *) mbPtr;
    Tk_Window tkwin = butPtr->tkwin;
    Pixmap pixmap;
    int usehlborder = 0;

860
861
862
863
864
865
866
867
868
869



870
871
872


873
874
875
876
877
878
879
853
854
855
856
857
858
859



860
861
862
863


864
865
866
867
868
869
870
871
872







-
-
-
+
+
+

-
-
+
+







 * Side effects:
 *        The content of the button gets updated.
 *
 *--------------------------------------------------------------
 */
static void
ButtonContentDrawCB (
    const HIRect * btnbounds,
    ThemeButtonKind kind,
    const HIThemeButtonDrawInfo *drawinfo,
    TCL_UNUSED(const HIRect *),
    TCL_UNUSED(ThemeButtonKind),
    TCL_UNUSED(const HIThemeButtonDrawInfo *),
    MacButton *ptr,
    SInt16 depth,
    Boolean isColorDev)
    TCL_UNUSED(SInt16),
    TCL_UNUSED(Boolean))
{
    TkButton *butPtr = (TkButton *) ptr;
    Tk_Window tkwin = butPtr->tkwin;

    if (tkwin == NULL || !Tk_IsMapped(tkwin)) {
        return;
    }
1043
1044
1045
1046
1047
1048
1049







1050

1051
1052
1053
1054
1055
1056
1057
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049

1050
1051
1052
1053
1054
1055
1056
1057







+
+
+
+
+
+
+
-
+







    }

    drawinfo->adornment = kThemeAdornmentNone;
    if (butPtr->defaultState == DEFAULT_ACTIVE) {
	if (drawinfo->state != kThemeStatePressed) {
	    drawinfo->adornment |= kThemeAdornmentDefault;
	}

	/*
	 * Older macOS systems (10.9 and earlier) use an animation to
	 * indicate the active button.  This is simulated by redrawing
	 * the button periodically.
	 */

        if (!mbPtr->defaultPulseHandler) {
        if (!mbPtr->defaultPulseHandler && ([NSApp macOSVersion] <= 100900)) {
            mbPtr->defaultPulseHandler = Tcl_CreateTimerHandler(
                    PULSE_TIMER_MSECS, PulseDefaultButtonProc, butPtr);
        }
    } else if (mbPtr->defaultPulseHandler) {
        Tcl_DeleteTimerHandler(mbPtr->defaultPulseHandler);
    }
    if (butPtr->highlightWidth >= 3) {
1173
1174
1175
1176
1177
1178
1179







1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198







+
+
+
+
+
+
+













static void
PulseDefaultButtonProc(ClientData clientData)
{
    MacButton *mbPtr = 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
     * event is handled (DestroyButton only cancels calls when REDRAW_PENDING
     * is set, which is not the case after calling TkpDisplayButton directly).
     */
    Tcl_CancelIdleCall(TkpDisplayButton, clientData);
    mbPtr->defaultPulseHandler = Tcl_CreateTimerHandler(
            PULSE_TIMER_MSECS, PulseDefaultButtonProc, clientData);
}

/*
 * Local Variables:
 * mode: objc
 * c-basic-offset: 4
 * fill-column: 79
 * coding: utf-8
 * End:
 */
Changes to macosx/tkMacOSXClipboard.c.
1
2
3
4
5
6
7
8



9
10
11
12
13
14
15
1
2
3
4
5



6
7
8
9
10
11
12
13
14
15





-
-
-
+
+
+







/*
 * 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 <[email protected]>
 * Copyright © 1995-1997 Sun Microsystems, Inc.
 * Copyright © 2001-2009 Apple Inc.
 * Copyright © 2006-2009 Daniel A. Steffen <[email protected]>
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tkMacOSXPrivate.h"
#include "tkMacOSXConstants.h"
31
32
33
34
35
36
37


38

39
40
41
42
43
44
45
31
32
33
34
35
36
37
38
39

40
41
42
43
44
45
46
47







+
+
-
+







	    [type isEqualToString:NSStringPboardType]) {
	for (TkClipboardTarget *targetPtr = dispPtr->clipTargetPtr; targetPtr;
		targetPtr = targetPtr->nextPtr) {
	    if (targetPtr->type == XA_STRING ||
		    targetPtr->type == dispPtr->utf8Atom) {
		for (TkClipboardBuffer *cbPtr = targetPtr->firstBufferPtr;
			cbPtr; cbPtr = cbPtr->nextPtr) {
		    NSString *s = [[TKNSString alloc]
				      initWithTclUtfBytes:cbPtr->buffer
		    NSString *s = TkUtfToNSString(cbPtr->buffer, cbPtr->length);
						   length:cbPtr->length];
		    [string appendString:s];
		    [s release];
		}
		break;
	    }
	}
    }
131
132
133
134
135
136
137
138

139
140

141
142
143
144
145
146
147
148




149
150
151
152
153
154
155
156
157



158
159
160
161
162
163
164
133
134
135
136
137
138
139

140


141








142
143
144
145


146
147
148
149



150
151
152
153
154
155
156
157
158
159







-
+
-
-
+
-
-
-
-
-
-
-
-
+
+
+
+
-
-




-
-
-
+
+
+







	NSString *type = [pb availableTypeFromArray:[NSArray arrayWithObject:
		NSStringPboardType]];

	if (type) {
	    string = [pb stringForType:type];
	}
	if (string) {

	    if (target == dispPtr->utf8Atom) {
	    /*
	     * Encode the string using the encoding which is used in Tcl
		result = proc(clientData, interp, string.UTF8String);
	     * when TCL_UTF_MAX = 3.  This replaces each UTF-16 surrogate with
	     * a 3-byte sequence generated using the UTF-8 algorithm. (Even
	     * though UTF-8 does not allow encoding surrogates, the algorithm
	     * does produce a 3-byte sequence.)
	     */

	    char *bytes = TkNSStringToUtf(string, NULL);
	    result = proc(clientData, interp, bytes);
	    } else if (target == XA_STRING) {
		const char *latin1 = [string
		    cStringUsingEncoding:NSISOLatin1StringEncoding];
		result = proc(clientData, interp, latin1);
	    if (bytes) {
		ckfree(bytes);
	    }
	}
    } else {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"%s selection doesn't exist or form \"%s\" not defined",
		Tk_GetAtomName(tkwin, selection),
		Tk_GetAtomName(tkwin, target)));
	     "%s selection doesn't exist or form \"%s\" not defined",
	     Tk_GetAtomName(tkwin, selection),
	     Tk_GetAtomName(tkwin, target)));
	Tcl_SetErrorCode(interp, "TK", "SELECTION", "EXISTS", NULL);
    }
    return result;
}

/*
 *----------------------------------------------------------------------
178
179
180
181
182
183
184
185

186
187

188
189
190
191
192
193
194
173
174
175
176
177
178
179

180
181
182
183
184
185
186
187
188
189
190







-
+


+







 */

int
XSetSelectionOwner(
    Display *display,		/* X Display. */
    Atom selection,		/* What selection to own. */
    Window owner,		/* Window to be the owner. */
    Time time)			/* The current time? */
    TCL_UNUSED(Time))			/* The current time? */
{
    TkDisplay *dispPtr = TkGetDisplayList();
    (void)time;

    if (dispPtr && selection == dispPtr->clipboardAtom) {
	clipboardOwner = owner ? Tk_IdToWindow(display, owner) : NULL;
	if (!dispPtr->clipboardActive) {
	    NSPasteboard *pb = [NSPasteboard generalPasteboard];

	    changeCount = [pb declareTypes:[NSArray array] owner:NSApp];
238
239
240
241
242
243
244
245
246


247
248
249
250
251
252
253
234
235
236
237
238
239
240


241
242
243
244
245
246
247
248
249







-
-
+
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

void
TkSelUpdateClipboard(
    TkWindow *winPtr,		/* Window associated with clipboard. */
    TkClipboardTarget *targetPtr)
    TCL_UNUSED(TkWindow *),		/* Window associated with clipboard. */
    TCL_UNUSED(TkClipboardTarget *))
				/* Info about the content. */
{
    NSPasteboard *pb = [NSPasteboard generalPasteboard];

    changeCount = [pb addTypes:[NSArray arrayWithObject:NSStringPboardType]
	    owner:NSApp];
}
267
268
269
270
271
272
273
274

275
276
277
278
279
280
281
263
264
265
266
267
268
269

270
271
272
273
274
275
276
277







-
+







 *
 *--------------------------------------------------------------
 */

void
TkSelEventProc(
    Tk_Window tkwin,		/* Window for which event was targeted. */
    register XEvent *eventPtr)	/* X event: either SelectionClear,
    XEvent *eventPtr)	/* X event: either SelectionClear,
				 * SelectionRequest, or SelectionNotify. */
{
    if (eventPtr->type == SelectionClear) {
	clipboardOwner = NULL;
	TkSelClearSelection(tkwin, eventPtr);
    }
}
295
296
297
298
299
300
301
302

303
304
305
306
307
308
309
310
311
312
313
291
292
293
294
295
296
297

298
299
300
301
302
303
304
305
306
307
308
309







-
+











 *	None.
 *
 *----------------------------------------------------------------------
 */

void
TkSelPropProc(
    register XEvent *eventPtr)	/* X PropertyChange event. */
    TCL_UNUSED(XEvent *))	/* X PropertyChange event. */
{
}

/*
 * Local Variables:
 * mode: objc
 * c-basic-offset: 4
 * fill-column: 79
 * coding: utf-8
 * End:
 */
Changes to macosx/tkMacOSXColor.c.
1
2

3
4
5
6
7
8
9
10
11





12
13
14
15
16
17
18

19
20
21
22
23
24




25
26
27
28
29
30
31
32
33
34










35
36
37
38
39

40
41
42
43
44
45
46
47















48
49
50
51
52

53
54
55



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
















74
75
76



77
78
79
80
81
82
83







84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
















99
100
101
102
103
104
105







106
107
108
109
110
111
112
113
114
115
116











117
118
119
120
121
122
123
124
125
126
127
128
129
130















131
132
133




134
135
136
137
138
139
140
141
142
143
144
145
146
147
148














149
150
151
152
153
154
155




156
157


158
159
160
161
162





163
164
165



166
167
168



169
170
171
172
173
174
175
176
177
178
179











180
181
182
183
184
185








186
187
188
189
190
191
192
193
194
195
196























197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213






214
215
216
217
218
219
220
221
222
223
224

225
226


227
228
229


230
231
232

233
234
235
236
237
238
239



240
241


242
243
244







245
246

247
248
249
250
251
252
253
254
255
256











257
258

259
260
261

262
263
264

265
266
267
268
269
270
271
272
273
274
275



276
277

278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299

300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317



318
319
320
321
322
323
324
325

326
327
328
329

330
331
332
333
334
335



336
337
338


339
340
341
342
343


344
345
346
347
348
349
350
351
352
353
354

355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373





374
375

376
377
378

379
380
381
382
383
384
385
386
387
388
389
390



391
392
393
394
395
396

397
















398
399
400
401
402


















403
404

405
406


407
408


409

410
411
412

413
414
415
416
417
418
419
1

2
3
4
5
6
7




8
9
10
11
12
13
14
15
16
17
18
19
20
21





22
23
24
25










26
27
28
29
30
31
32
33
34
35


36


37








38
39
40
41
42
43
44
45
46
47
48
49
50
51
52





53
54


55
56
57


















58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73



74
75
76







77
78
79
80
81
82
83















84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99







100
101
102
103
104
105
106











107
108
109
110
111
112
113
114
115
116
117














118
119
120
121
122
123
124
125
126
127
128
129
130
131
132



133
134
135
136















137
138
139
140
141
142
143
144
145
146
147
148
149
150







151
152
153
154


155
156





157
158
159
160
161



162
163
164



165
166
167











168
169
170
171
172
173
174
175
176
177
178






179
180
181
182
183
184
185
186











187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209

















210
211
212
213
214
215






216
217
218
219

220
221

222
223
224
225

226
227
228
229

230
231
232
233
234



235
236
237

238
239
240



241
242
243
244
245
246
247
248

249
250
251








252
253
254
255
256
257
258
259
260
261
262


263
264
265

266
267
268

269
270
271
272
273







274
275
276
277

278
279

280






281
282
283
284
285








286



287
288
289
290
291
292
293
294
295
296
297
298



299
300
301
302
303
304
305
306
307
308

309
310
311
312

313
314
315
316



317
318
319



320
321





322
323











324



















325
326
327
328
329


330

331

332


333









334
335
336


337
338


339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356





357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377


378
379


380
381
382
383
384
385

386
387
388
389
390
391
392
393

-
+





-
-
-
-
+
+
+
+
+







+

-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-

-
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+

-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
-
-
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-




-
+

-
+
+


-
+
+


-
+




-
-
-
+
+
+
-

+
+
-
-
-
+
+
+
+
+
+
+

-
+


-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
+


-
+


-
+




-
-
-
-
-
-
-
+
+
+

-
+

-

-
-
-
-
-
-





-
-
-
-
-
-
-
-
+
-
-
-












-
-
-
+
+
+







-
+



-
+



-
-
-
+
+
+
-
-
-
+
+
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
-
-
+
-

-
+
-
-

-
-
-
-
-
-
-
-
-
+
+
+
-
-


-
-
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


+
-
-
+
+
-
-
+
+

+


-
+







/*
 * tkMacOSXColor.c --
 * TkMacOSXColor.c --
 *
 *	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 <[email protected]>
 * 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 <[email protected]>
 * 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 "tkMacOSXPrivate.h"
#include "tkColor.h"
#include "tkMacOSXColor.h"

/*
 * The colorType specifies how the color value should be interpreted.  For the
 * unique rgbColor entry, the RGB values are generated from the pixel value of
 * an XColor.  The ttkBackground and semantic types are dynamic, meaning
 * that they change when dark mode is enabled on OSX 10.13 and later.
static Tcl_HashTable systemColors;
static int numSystemColors;
static int rgbColorIndex;
static int controlAccentIndex;
 */

enum colorType {
    clearColor,    /* There should be only one of these. */
    rgbColor,      /* There should be only one of these. */
    appearance,    /* There should be only one of these. */
    HIBrush,       /* The value is a HITheme brush color table index. */
    HIText,        /* The value is a HITheme text color table index. */
    HIBackground,  /* The value is a HITheme background color table index. */
    ttkBackground, /* The value can be used as a parameter.*/
static int selectedTabTextIndex;
static Bool useFakeAccentColor = NO;
static SystemColorDatum **systemColorIndex;
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400
static NSAppearance *lightAqua = nil;
static NSAppearance *darkAqua = nil;
#endif
static NSColorSpace* sRGB = NULL;
static const CGFloat WINDOWBACKGROUND[4] =
    {236.0 / 255, 236.0 / 255, 236.0 / 255, 1.0};
    semantic, /* The value can be used as a parameter.*/
};

/*

void initColorTable()
 */

struct SystemColorMapEntry {
    const char *name;
    enum colorType type;
    long value;
};  /* unsigned char pixelCode; */

{
    NSAutoreleasePool *pool = [NSAutoreleasePool new];
    Tcl_InitHashTable(&systemColors, TCL_STRING_KEYS);
    SystemColorDatum *entry, *oldEntry;
    Tcl_HashSearch search;
    Tcl_HashEntry *hPtr;
    int newPtr, index = 0;
    NSColorList *systemColorList = [NSColorList colorListNamed:@"System"];
    NSString *key;

#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400
    if (@available(macOS 10.14, *)) {
	darkAqua = [NSAppearance appearanceNamed:NSAppearanceNameDarkAqua];
        lightAqua = [NSAppearance appearanceNamed:NSAppearanceNameAqua];
    }
/*
 * Array of system color definitions: the array index is required to equal the
 * color's (pixelCode - MIN_PIXELCODE), i.e. the array order needs to be kept
 * in sync with the public pixel code values in tkMacOSXPort.h !
 */
#endif

#define MIN_PIXELCODE  30
static const struct SystemColorMapEntry systemColorMap[] = {
    /*
     * Build a hash table for looking up a color by its name.
     * First add all of the static entries from tkMacOSXColor.h
    { "Transparent",			    clearColor,   0 },						    /*  30: TRANSPARENT_PIXEL */
    { "Highlight",			    HIBrush,      kThemeBrushPrimaryHighlightColor },		    /*  31 */
    { "HighlightSecondary",		    HIBrush,      kThemeBrushSecondaryHighlightColor },		    /*  32 */
    { "HighlightText",			    HIBrush,      kThemeBrushBlack },				    /*  33 */
    { "HighlightAlternate",		    HIBrush,      kThemeBrushAlternatePrimaryHighlightColor },	    /*  34 */
    { "ButtonText",			    HIText,       kThemeTextColorPushButtonActive },	       	    /*  35 */
    { "PrimaryHighlightColor",		    HIBrush,      kThemeBrushPrimaryHighlightColor },		    /*  36 */
    { "ButtonFace",			    HIBrush,      kThemeBrushButtonFaceActive },	       	    /*  37 */
    { "SecondaryHighlightColor",	    HIBrush,      kThemeBrushSecondaryHighlightColor },		    /*  38 */
    { "ButtonFrame",			    HIBrush,      kThemeBrushButtonFrameActive },	       	    /*  39 */
    { "AlternatePrimaryHighlightColor",	    HIBrush,      kThemeBrushAlternatePrimaryHighlightColor },	    /*  40 */
    { "WindowBody",			    HIBrush,      kThemeBrushDocumentWindowBackground },       	    /*  41 */
    { "SheetBackground",		    HIBrush,      kThemeBrushSheetBackground },			    /*  42 */
    { "MenuActive",			    HIBrush,      kThemeBrushMenuBackgroundSelected },		    /*  43 */
    { "Black",				    HIBrush,      kThemeBrushBlack },				    /*  44 */
    { "MenuActiveText",			    HIText,       kThemeTextColorMenuItemSelected },	       	    /*  45 */
    { "White",				    HIBrush,      kThemeBrushWhite },				    /*  46 */
    { "Menu",				    HIBrush,      kThemeBrushMenuBackground },			    /*  47 */
     */

    for (entry = systemColorData; entry->name != NULL; entry++) {
	hPtr = Tcl_CreateHashEntry(&systemColors, entry->name, &newPtr);
	if (entry->type == semantic) {
	    NSString *colorName = [[NSString alloc]
				   initWithCString:entry->macName
					  encoding:NSUTF8StringEncoding];
	    SEL colorSelector = NSSelectorFromString(colorName);
	    if (![NSColor respondsToSelector:colorSelector]) {
		if ([colorName isEqualToString:@"controlAccentColor"]) {
		    useFakeAccentColor = YES;
		} else if (![colorName isEqualToString:@"selectedTabTextColor"]) {
		    /* Uncomment to print all unsupported colors:              */
		    /* printf("Unsupported color %s\n", colorName.UTF8String); */
		    continue;
    { "DialogBackgroundActive",		    HIBrush,      kThemeBrushDialogBackgroundActive },		    /*  48 */
    { "MenuDisabled",			    HIText,       kThemeTextColorMenuItemDisabled },	       	    /*  49 */
    { "DialogBackgroundInactive",	    HIBrush,      kThemeBrushDialogBackgroundInactive },       	    /*  50 */
		}
	    }
	    entry->selector = [colorName retain];
    { "MenuText",			    HIText,       kThemeTextColorMenuItemActive },	       	    /*  51 */
    { "AppearanceColor",		    appearance,   0 },						    /*  52: APPEARANCE_PIXEL */
    { "AlertBackgroundActive",		    HIBrush,      kThemeBrushAlertBackgroundActive },		    /*  53 */
    { "AlertBackgroundInactive",	    HIBrush,      kThemeBrushAlertBackgroundInactive },		    /*  54 */
    { "ModelessDialogBackgroundActive",	    HIBrush,      kThemeBrushModelessDialogBackgroundActive },	    /*  55 */
    { "ModelessDialogBackgroundInactive",   HIBrush,      kThemeBrushModelessDialogBackgroundInactive },    /*  56 */
    { "UtilityWindowBackgroundActive",	    HIBrush,      kThemeBrushUtilityWindowBackgroundActive },	    /*  57 */
	}
	if (newPtr == 0) {
	    oldEntry = (SystemColorDatum *) Tcl_GetHashValue(hPtr);
	    entry->index = oldEntry->index;
	    [oldEntry->selector release];
	} else {
	    entry->index = index++;
    { "UtilityWindowBackgroundInactive",    HIBrush,      kThemeBrushUtilityWindowBackgroundInactive },	    /*  58 */
    { "ListViewSortColumnBackground",	    HIBrush,      kThemeBrushListViewSortColumnBackground },	    /*  59 */
    { "ListViewBackground",		    HIBrush,      kThemeBrushListViewBackground },	       	    /*  60 */
    { "IconLabelBackground",		    HIBrush,      kThemeBrushIconLabelBackground },    		    /*  61 */
    { "ListViewSeparator",		    HIBrush,      kThemeBrushListViewSeparator },      		    /*  62 */
    { "ChasingArrows",			    HIBrush,      kThemeBrushChasingArrows },			    /*  63 */
    { "DragHilite",			    HIBrush,      kThemeBrushDragHilite },	       		    /*  64 */
    { "DocumentWindowBackground",	    HIBrush,      kThemeBrushDocumentWindowBackground },       	    /*  65 */
    { "FinderWindowBackground",		    HIBrush,      kThemeBrushFinderWindowBackground },		    /*  66 */
    { "ScrollBarDelimiterActive",	    HIBrush,      kThemeBrushScrollBarDelimiterActive },       	    /*  67 */
    { "ScrollBarDelimiterInactive",	    HIBrush,      kThemeBrushScrollBarDelimiterInactive },     	    /*  68 */
    { "FocusHighlight",			    HIBrush,      kThemeBrushFocusHighlight },			    /*  69 */
    { "PopupArrowActive",		    HIBrush,      kThemeBrushPopupArrowActive },	       	    /*  70 */
    { "PopupArrowPressed",		    HIBrush,      kThemeBrushPopupArrowPressed },	       	    /*  71 */
    { "PopupArrowInactive",		    HIBrush,      kThemeBrushPopupArrowInactive },	       	    /*  72 */
	}
	Tcl_SetHashValue(hPtr, entry);
    }

    /*
     * Add all of the colors in the System ColorList.
     */

    for (key in [systemColorList allKeys]) {
	int length = [key lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
	char *name;
	entry = (SystemColorDatum *)ckalloc(sizeof(SystemColorDatum));
	bzero(entry, sizeof(SystemColorDatum));
	name = (char *)ckalloc(length + 1);
	strcpy(name, key.UTF8String);
	name[0] = toupper(name[0]);
    { "AppleGuideCoachmark",		    HIBrush,      kThemeBrushAppleGuideCoachmark },	       	    /*  73 */
    { "IconLabelBackgroundSelected",	    HIBrush,      kThemeBrushIconLabelBackgroundSelected },    	    /*  74 */
    { "StaticAreaFill",			    HIBrush,      kThemeBrushStaticAreaFill },			    /*  75 */
    { "ActiveAreaFill",			    HIBrush,      kThemeBrushActiveAreaFill },			    /*  76 */
    { "ButtonFrameActive",		    HIBrush,      kThemeBrushButtonFrameActive },		    /*  77 */
    { "ButtonFrameInactive",		    HIBrush,      kThemeBrushButtonFrameInactive },	       	    /*  78 */
    { "ButtonFaceActive",		    HIBrush,      kThemeBrushButtonFaceActive },       		    /*  79 */
        if (!strcmp(name, "WindowBackgroundColor")) {

	    /*
	     * Avoid black windows on old systems.
	     */

	    continue;
    { "ButtonFaceInactive",		    HIBrush,      kThemeBrushButtonFaceInactive },	       	    /*  80 */
    { "ButtonFacePressed",		    HIBrush,      kThemeBrushButtonFacePressed },	       	    /*  81 */
    { "ButtonActiveDarkShadow",		    HIBrush,      kThemeBrushButtonActiveDarkShadow },		    /*  82 */
    { "ButtonActiveDarkHighlight",	    HIBrush,      kThemeBrushButtonActiveDarkHighlight },	    /*  83 */
    { "ButtonActiveLightShadow",	    HIBrush,      kThemeBrushButtonActiveLightShadow },		    /*  84 */
    { "ButtonActiveLightHighlight",	    HIBrush,      kThemeBrushButtonActiveLightHighlight },	    /*  85 */
    { "ButtonInactiveDarkShadow",	    HIBrush,      kThemeBrushButtonInactiveDarkShadow },	    /*  86 */
    { "ButtonInactiveDarkHighlight",	    HIBrush,      kThemeBrushButtonInactiveDarkHighlight },	    /*  87 */
    { "ButtonInactiveLightShadow",	    HIBrush,      kThemeBrushButtonInactiveLightShadow },	    /*  88 */
    { "ButtonInactiveLightHighlight",	    HIBrush,      kThemeBrushButtonInactiveLightHighlight },	    /*  89 */
    { "ButtonPressedDarkShadow",	    HIBrush,      kThemeBrushButtonPressedDarkShadow },		    /*  90 */
	}
	entry->type=semantic;
	entry->name = name;
	entry->selector = [key retain];
	hPtr = Tcl_CreateHashEntry(&systemColors, entry->name, &newPtr);
	if (newPtr == 0) {
	    oldEntry = (SystemColorDatum *) Tcl_GetHashValue(hPtr);
	    entry->index = oldEntry->index;
	    [oldEntry->selector release];
	} else {
	    entry->index = index++;
    { "ButtonPressedDarkHighlight",	    HIBrush,      kThemeBrushButtonPressedDarkHighlight },	    /*  91 */
    { "ButtonPressedLightShadow",	    HIBrush,      kThemeBrushButtonPressedLightShadow },	    /*  92 */
    { "ButtonPressedLightHighlight",	    HIBrush,      kThemeBrushButtonPressedLightHighlight },	    /*  93 */
    { "BevelActiveLight",		    HIBrush,      kThemeBrushBevelActiveLight },		    /*  94 */
    { "BevelActiveDark",		    HIBrush,      kThemeBrushBevelActiveDark },			    /*  95 */
    { "BevelInactiveLight",		    HIBrush,      kThemeBrushBevelInactiveLight },		    /*  96 */
    { "BevelInactiveDark",		    HIBrush,      kThemeBrushBevelInactiveDark },		    /*  97 */
    { "NotificationWindowBackground",	    HIBrush,      kThemeBrushNotificationWindowBackground },	    /*  98 */
    { "MovableModalBackground",		    HIBrush,      kThemeBrushMovableModalBackground },		    /*  99 */
    { "SheetBackgroundOpaque",		    HIBrush,      kThemeBrushSheetBackgroundOpaque },		    /* 100 */
    { "DrawerBackground",		    HIBrush,      kThemeBrushDrawerBackground },		    /* 101 */
    { "ToolbarBackground",		    HIBrush,      kThemeBrushToolbarBackground },		    /* 102 */
    { "SheetBackgroundTransparent",	    HIBrush,      kThemeBrushSheetBackgroundTransparent },	    /* 103 */
    { "MenuBackground",			    HIBrush,      kThemeBrushMenuBackground },			    /* 104 */
	}
	Tcl_SetHashValue(hPtr, entry);
    }

    /*
     * Build an array for looking up a color by its index.
     */

    numSystemColors = index;
    systemColorIndex = (SystemColorDatum **)ckalloc(numSystemColors * sizeof(SystemColorDatum *));
    for (hPtr = Tcl_FirstHashEntry(&systemColors, &search); hPtr != NULL;
	 hPtr = Tcl_NextHashEntry(&search)) {
	entry = (SystemColorDatum *) Tcl_GetHashValue(hPtr);
	if (entry == NULL) {
	    Tcl_Panic("Unsupported semantic color with no supported backup!");
    { "Pixel",				    rgbColor,     0 },						    /* 105: PIXEL_MAGIC */
    { "MenuBackgroundSelected",		    HIBrush,      kThemeBrushMenuBackgroundSelected },		    /* 106 */
    { "ListViewOddRowBackground",	    HIBrush,      kThemeBrushListViewOddRowBackground },	    /* 107 */
	}
	systemColorIndex[entry->index] = entry;
    }

    { "ListViewEvenRowBackground",	    HIBrush,      kThemeBrushListViewEvenRowBackground },	    /* 108 */
    { "ListViewColumnDivider",		    HIBrush,      kThemeBrushListViewColumnDivider },		    /* 109 */
    { "BlackText",			    HIText,       kThemeTextColorBlack },			    /* 110 */
    { "DialogActiveText",		    HIText,       kThemeTextColorDialogActive },		    /* 111 */
    { "DialogInactiveText",		    HIText,       kThemeTextColorDialogInactive },		    /* 112 */
    { "AlertActiveText",		    HIText,       kThemeTextColorAlertActive },			    /* 113 */
    { "AlertInactiveText",		    HIText,       kThemeTextColorAlertInactive },		    /* 114 */
    { "ModelessDialogActiveText",	    HIText,       kThemeTextColorModelessDialogActive },	    /* 115 */
    { "ModelessDialogInactiveText",	    HIText,       kThemeTextColorModelessDialogInactive },	    /* 116 */
    { "WindowHeaderActiveText",		    HIText,       kThemeTextColorWindowHeaderActive },		    /* 117 */
    { "WindowHeaderInactiveText",	    HIText,       kThemeTextColorWindowHeaderInactive },	    /* 118 */
    { "PlacardActiveText",		    HIText,       kThemeTextColorPlacardActive },		    /* 119 */
    { "PlacardInactiveText",		    HIText,       kThemeTextColorPlacardInactive },		    /* 120 */
    { "PlacardPressedText",		    HIText,       kThemeTextColorPlacardPressed },		    /* 121 */
    { "PushButtonActiveText",		    HIText,       kThemeTextColorPushButtonActive },		    /* 122 */
    /*
     * Remember the indexes of some special entries.
     */

    hPtr = Tcl_FindHashEntry(&systemColors, "Pixel");
    entry = (SystemColorDatum *) Tcl_GetHashValue(hPtr);
    rgbColorIndex = entry->index;
    hPtr = Tcl_FindHashEntry(&systemColors, "ControlAccentColor");
    entry = (SystemColorDatum *) Tcl_GetHashValue(hPtr);
    controlAccentIndex = entry->index;
    hPtr = Tcl_FindHashEntry(&systemColors, "SelectedTabTextColor");
    entry = (SystemColorDatum *) Tcl_GetHashValue(hPtr);
    selectedTabTextIndex = entry->index;
    [pool drain];
    { "PushButtonInactiveText",		    HIText,       kThemeTextColorPushButtonInactive },		    /* 123 */
    { "PushButtonPressedText",		    HIText,       kThemeTextColorPushButtonPressed },		    /* 124 */
    { "BevelButtonActiveText",		    HIText,       kThemeTextColorBevelButtonActive },		    /* 125 */
    { "BevelButtonInactiveText",	    HIText,       kThemeTextColorBevelButtonInactive },		    /* 126 */
    { "BevelButtonPressedText",		    HIText,       kThemeTextColorBevelButtonPressed },		    /* 127 */
    { "PopupButtonActiveText",		    HIText,       kThemeTextColorPopupButtonActive },		    /* 128 */
    { "PopupButtonInactiveText",	    HIText,       kThemeTextColorPopupButtonInactive },		    /* 129 */
}

/*
 *----------------------------------------------------------------------
    { "PopupButtonPressedText",		    HIText,       kThemeTextColorPopupButtonPressed },		    /* 130 */
    { "IconLabelText",			    HIText,       kThemeTextColorIconLabel },			    /* 131 */
 *
 * TkMacOSXRGBPixel --
    { "ListViewText",			    HIText,       kThemeTextColorListView },			    /* 132 */
    { "DocumentWindowTitleActiveText",	    HIText,       kThemeTextColorDocumentWindowTitleActive },	    /* 133 */
    { "DocumentWindowTitleInactiveText",    HIText,       kThemeTextColorDocumentWindowTitleInactive },	    /* 134 */
    { "MovableModalWindowTitleActiveText",  HIText,       kThemeTextColorMovableModalWindowTitleActive },   /* 135 */
    { "MovableModalWindowTitleInactiveText",HIText,       kThemeTextColorMovableModalWindowTitleInactive }, /* 136 */
 *
 *	Return an unsigned long value suitable for use in the pixel
 *	field of an XColor with the specified red, green and blue
 *	intensities.  The inputs are cast as unsigned longs but are
 *      expected to have values representable by an unsigned char.
    { "UtilityWindowTitleActiveText",	    HIText,       kThemeTextColorUtilityWindowTitleActive },	    /* 137 */
    { "UtilityWindowTitleInactiveText",	    HIText,       kThemeTextColorUtilityWindowTitleInactive },	    /* 138 */
    { "PopupWindowTitleActiveText",	    HIText,       kThemeTextColorPopupWindowTitleActive },	    /* 139 */
 *
 *      This is called in the TkpGetPixel macro, used in xcolor.c,
 *      and in ImageGetPixel.
    { "PopupWindowTitleInactiveText",	    HIText,       kThemeTextColorPopupWindowTitleInactive },	    /* 140 */
    { "RootMenuActiveText",		    HIText,       kThemeTextColorRootMenuActive },		    /* 141 */
    { "RootMenuSelectedText",		    HIText,       kThemeTextColorRootMenuSelected },		    /* 142 */
 *
 * Results:
 *	An unsigned long that can be used as the pixel field of an XColor.
    { "RootMenuDisabledText",		    HIText,       kThemeTextColorRootMenuDisabled },		    /* 143 */
    { "MenuItemActiveText",		    HIText,       kThemeTextColorMenuItemActive },		    /* 144 */
    { "MenuItemSelectedText",		    HIText,       kThemeTextColorMenuItemSelected },		    /* 145 */
    { "MenuItemDisabledText",		    HIText,       kThemeTextColorMenuItemDisabled },		    /* 146 */
    { "PopupLabelActiveText",		    HIText,       kThemeTextColorPopupLabelActive },		    /* 147 */
    { "PopupLabelInactiveText",		    HIText,       kThemeTextColorPopupLabelInactive },		    /* 148 */
    { "TabFrontActiveText",		    HIText,       kThemeTextColorTabFrontActive },		    /* 149 */
    { "TabNonFrontActiveText",		    HIText,       kThemeTextColorTabNonFrontActive },		    /* 150 */
    { "TabNonFrontPressedText",		    HIText,       kThemeTextColorTabNonFrontPressed },		    /* 151 */
    { "TabFrontInactiveText",		    HIText,       kThemeTextColorTabFrontInactive },		    /* 152 */
    { "TabNonFrontInactiveText",	    HIText,       kThemeTextColorTabNonFrontInactive },		    /* 153 */
 *
 * Side effects:
 *	None.
 *----------------------------------------------------------------------
 */
MODULE_SCOPE
unsigned long
TkMacOSXRGBPixel(
    unsigned long red,
    unsigned long green,
    unsigned long blue)
    { "IconLabelSelectedText",		    HIText,       kThemeTextColorIconLabelSelected },		    /* 154 */
    { "BevelButtonStickyActiveText",	    HIText,       kThemeTextColorBevelButtonStickyActive },	    /* 155 */
    { "BevelButtonStickyInactiveText",	    HIText,       kThemeTextColorBevelButtonStickyInactive },	    /* 156 */
    { "NotificationText",		    HIText,       kThemeTextColorNotification },		    /* 157 */
    { "SystemDetailText",		    HIText,       kThemeTextColorSystemDetail },		    /* 158 */
    { "WhiteText",			    HIText,       kThemeTextColorWhite },			    /* 159 */
{
    MacPixel p = {0};
    p.pixel.colortype = rgbColor;
    p.pixel.value = ((red & 0xff) << 16)  |
	            ((green & 0xff) << 8) |
	            (blue & 0xff);
    return p.ulong;
}
    { "TabPaneBackground",		    HIBackground, kThemeBackgroundTabPane },			    /* 160 */
    { "PlacardBackground",		    HIBackground, kThemeBackgroundPlacard },			    /* 161 */
    { "WindowHeaderBackground",		    HIBackground, kThemeBackgroundWindowHeader },		    /* 162 */
    { "ListViewWindowHeaderBackground",	    HIBackground, kThemeBackgroundListViewWindowHeader },	    /* 163 */
    { "SecondaryGroupBoxBackground",	    HIBackground, kThemeBackgroundSecondaryGroupBox },		    /* 164 */
    { "MetalBackground",		    HIBackground, kThemeBackgroundMetal },			    /* 165 */

    /*
     * Colors based on "semantic" NSColors.
     */


/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXClearPixel --
 *
 *	Return the unsigned long value that appears in the pixel
 *	field of the XColor for systemTransparentColor.
 *
 *      This is used in tkMacOSXImage.c.
 *
 * Results:
 *	The unsigned long that appears in the pixel field of the XColor
 *      for systemTransparentPixel.
 *
 * Side effects:
 *	None.
 *----------------------------------------------------------------------
 */
MODULE_SCOPE
unsigned long TkMacOSXClearPixel(
    void)
{
    { "WindowBackgroundColor",		    ttkBackground, 0 },	    					    /* 166 */
    { "WindowBackgroundColor1",		    ttkBackground, 1 },						    /* 167 */
    { "WindowBackgroundColor2",		    ttkBackground, 2 },						    /* 168 */
    { "WindowBackgroundColor3",		    ttkBackground, 3 },						    /* 169 */
    { "WindowBackgroundColor4",		    ttkBackground, 4 },						    /* 170 */
    { "WindowBackgroundColor5",		    ttkBackground, 5 },						    /* 171 */
    { "WindowBackgroundColor6",		    ttkBackground, 6 },						    /* 172 */
    { "WindowBackgroundColor7",		    ttkBackground, 7 },						    /* 173 */
    { "TextColor",			    semantic, 0 },						    /* 174 */
    { "SelectedTextColor",		    semantic, 1 },						    /* 175 */
    { "LabelColor",			    semantic, 2 },						    /* 176 */
    { "ControlTextColor",      		    semantic, 3 },						    /* 177 */
    { "DisabledControlTextColor",	    semantic, 4 },						    /* 178 */
    { "SelectedTabTextColor",		    semantic, 5 },						    /* 179 */
    { "TextBackgroundColor",		    semantic, 6 },						    /* 180 */
    { "SelectedTextBackgroundColor",	    semantic, 7 },						    /* 181 */
    { "ControlAccentColor",		    semantic, 8 },						    /* 182 */
    MacPixel p = {0};
    p.pixel.value = 0;
    p.pixel.colortype = clearColor;
    return p.ulong;
}

    /* Apple's SecondaryLabelColor is the same as their LabelColor so we roll our own. */
    { "SecondaryLabelColor",		    ttkBackground, 14 },					    /* 183 */
    { NULL,				    0, 0 }
};
#define FIRST_SEMANTIC_COLOR 166
#define MAX_PIXELCODE 183

/*
 *----------------------------------------------------------------------
 *
 * GetEntryFromPixelCode --
 * GetEntryFromPixel --
 *
 *	Extract a SystemColorMapEntry from the table.
 *	Look up a SystemColorDatum which describes the XColor with
 *      the specified value as its pixel field.
 *
 * Results:
 *	Returns false if the code is out of bounds.
 *	A pointer to a SystemColorDatum, or NULL if the pixel value is
 *	invalid.
 *
 * Side effects:
 *	None.
 *	None
 *
 *----------------------------------------------------------------------
 */

static bool
GetEntryFromPixelCode(
    unsigned char code,
SystemColorDatum*
GetEntryFromPixel(
    unsigned long pixel)
    struct SystemColorMapEntry *entry)
{
    MacPixel p = {0};
    int index = rgbColorIndex;
    if (code >= MIN_PIXELCODE && code <= MAX_PIXELCODE) {
	*entry = systemColorMap[code - MIN_PIXELCODE];
	return true;

    p.ulong = pixel;
    if (p.pixel.colortype != rgbColor) {
	index = p.pixel.value;
    }
    if (index < numSystemColors) {
	return systemColorIndex[index];
    } else {
	return false;
	return NULL;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * SetCGColorComponents --
 *
 *	Set the components of a CGColorRef from an XColor pixel value and a
 *      system color map entry.  The pixel value is only used in the case where


/*
 *----------------------------------------------------------------------
 *
 * GetRGBA --
 *
 *	Given a SystemColorDatum and a pointer to an array of 4 CGFloats, store
 *      the associated RGBA color values in the array.  In the case of the
 *      RGBColor datum, the unsigned long pixel value containing the RGB values
 *      must also be provided as the pixel parameter.  Otherwise the pixel
 *      the color is of type rgbColor.  In that case the normalized XColor RGB
 *      values are copied into the CGColorRef.
 *      parameter is ignored.
 *
 * Results:
 *	OSStatus
 *	None
 *
 * Side effects:
 *	None.
 *	The array rgba is filled in.
 *
 *----------------------------------------------------------------------
 */

static NSColorSpace* sRGB = NULL;
static CGFloat windowBackground[4] =
    {236.0 / 255, 236.0 / 255, 236.0 / 255, 1.0};

static OSStatus
SetCGColorComponents(
    struct SystemColorMapEntry entry,
static void
GetRGBA(
    SystemColorDatum *entry,
    unsigned long pixel,
    CGColorRef *c)
    CGFloat *rgba)
{
    OSStatus err = noErr;
    NSColor *bgColor, *color = nil;
    CGFloat rgba[4] = {0, 0, 0, 1};
#if MAC_OS_X_VERSION_MAX_ALLOWED < 101400
    NSInteger colorVariant;
    static CGFloat graphiteAccentRGBA[4] =
	{152.0 / 255, 152.0 / 255, 152.0 / 255, 1.0};
#endif

    if (!sRGB) {
	sRGB = [NSColorSpace sRGBColorSpace];
    }

    /*
     * This function is called before our autorelease pool is set up,
     * so it needs its own pool.
     */

    NSAutoreleasePool *pool = [NSAutoreleasePool new];

    switch (entry.type) {
    switch (entry->type) {
    case HIBrush:
	err = ChkErr(HIThemeBrushCreateCGColor, entry.value, c);
	return err;
    case rgbColor:
	rgba[0] = ((pixel >> 16) & 0xff) / 255.0;
	rgba[1] = ((pixel >>  8) & 0xff) / 255.0;
	rgba[2] = ((pixel      ) & 0xff) / 255.0;
	break;
    case ttkBackground:

	/*
	 * Prior to OSX 10.14, getComponents returns black when applied to
	 * windowBackGroundColor.
	 */

	if ([NSApp macMinorVersion] < 14) {
	    for (int i=0; i<3; i++) {
		rgba[i] = windowBackground[i];
	if ([NSApp macOSVersion] < 101400) {
	    for (int i = 0; i < 3; i++) {
		rgba[i] = WINDOWBACKGROUND[i];
	    }
	} else {
	    bgColor = [[NSColor windowBackgroundColor] colorUsingColorSpace:sRGB];
	    [bgColor getComponents: rgba];
	}
	if (rgba[0] + rgba[1] + rgba[2] < 1.5) {
	    for (int i=0; i<3; i++) {
		rgba[i] += entry.value*8.0 / 255.0;
		rgba[i] += entry->value*8.0 / 255.0;
	    }
	} else {
	    for (int i=0; i<3; i++) {
		rgba[i] -= entry.value*8.0 / 255.0;
		rgba[i] -= entry->value*8.0 / 255.0;
	    }
	}
	break;
    case semantic:
	switch (entry.value) {
	case 0:
    case clearColor:
	rgba[0] = rgba[1] = rgba[2] = 1.0;
	rgba[3] = 0;
	    color = [[NSColor textColor] colorUsingColorSpace:sRGB];
	    break;
	case 1:
	break;
    case semantic:
	    color = [[NSColor selectedTextColor] colorUsingColorSpace:sRGB];
	    break;
	case 2:
	    if ([NSApp macMinorVersion] > 9) {
#if MAC_OS_X_VERSION_MAX_ALLOWED > 1090
	if (entry->index == controlAccentIndex && useFakeAccentColor) {
#if MAC_OS_X_VERSION_MIN_REQUIRED < 101400
		color = [[NSColor labelColor] colorUsingColorSpace:sRGB];
#endif
	    } else {
		color = [[NSColor textColor] colorUsingColorSpace:sRGB];
	    }
	    break;
	case 3:
	    color = [[NSColor controlTextColor] colorUsingColorSpace:sRGB];
	    break;
	case 4:
	    color = [[NSColor disabledControlTextColor]
	    color = [[NSColor colorForControlTint: [NSColor currentControlTint]]
			colorUsingColorSpace:sRGB];
	    break;
	case 5:
	    if ([NSApp macMinorVersion] > 6) {
		color = [[NSColor whiteColor] colorUsingColorSpace:sRGB];
	    } else {
		color = [[NSColor blackColor] colorUsingColorSpace:sRGB];
	    }
	    break;
	case 6:
	    color = [[NSColor textBackgroundColor] colorUsingColorSpace:sRGB];
	    break;
	case 7:
	    color = [[NSColor selectedTextBackgroundColor]
			colorUsingColorSpace:sRGB];
	    break;
	case 8:
	    if ([NSApp macMinorVersion] >= 14) {
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400
			      colorUsingColorSpace:sRGB];
#endif
	} else if (entry->index == selectedTabTextIndex) {
	    int OSVersion = [NSApp macOSVersion];
	    if (OSVersion > 100600 && OSVersion < 110000) {
		color = [[NSColor controlAccentColor]
			    colorUsingColorSpace:sRGB];
		color = [[NSColor whiteColor] colorUsingColorSpace:sRGB];
#endif
	    } else {
		color = [[NSColor
		color = [[NSColor textColor] colorUsingColorSpace:sRGB];
			    colorForControlTint:[NSColor currentControlTint]]
			        colorUsingColorSpace: sRGB];
	    }
	    break;
	default:
	    if ([NSApp macMinorVersion] >= 10) {
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000
		color = [[NSColor labelColor] colorUsingColorSpace:sRGB];
#endif
	    } else {
		color = [[NSColor textColor] colorUsingColorSpace:sRGB];
	    }
	} else {
	    color = [[NSColor valueForKey:entry->selector] colorUsingColorSpace:sRGB];
	}
	    break;
	}
	[color getComponents: rgba];
	break;
    case clearColor:
	rgba[3]	= 0.0;
    default:
	break;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * SetCGColorComponents --
 *
 *	Set the components of a CGColorRef from an XColor pixel value and a
 *      SystemColorDatum.  The pixel value is only used in the case where
 *      the color is of type rgbColor.  In that case the normalized XColor RGB
 *      values are copied into the CGColorRef.  Otherwise the components are
 *      computed from the SystemColorDatum.
 *
 * Results:
 *	True if the function succeeds, false otherwise.

    /*
     * There are no HITheme functions which convert Text or background colors
     * to CGColors.  (GetThemeTextColor has been removed, and it was never
     * possible with backgrounds.)  If we get one of these we return black.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static Bool
SetCGColorComponents(
    SystemColorDatum *entry,
    unsigned long pixel,
    CGColorRef *c)
{
    CGFloat rgba[4] = {0, 0, 0, 1};

    /*
     * This function is called before our autorelease pool is set up,
     * so it needs its own pool.
     */

    NSAutoreleasePool *pool = [NSAutoreleasePool new];
    case HIText:
    case HIBackground:

    if (entry->type == HIBrush) {
    default:
	break;
     	OSStatus err = ChkErr(HIThemeBrushCreateCGColor, entry->value, c);
     	return err == noErr;
    }
    GetRGBA(entry, pixel, rgba);
    *c = CGColorCreate(sRGB.CGColorSpace, rgba);
    [pool drain];
    return err;
    return true;
}

/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXInDarkMode --
 *
427
428
429
430
431
432
433
434
435
436
437
438

439
440

441
442
443

444
445
446

447
448

449
450

451


452
453
454

455
456
457
458
459
460
461
462
463
464
465




466
467
468

469
470
471
472

473
474
475
476
477
478
479
480
481


482
483
484
485
486

487
488
489

490
491
492

493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508

509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541

542
543
544
545
546
547
548
549


550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610

611
612
613

614
615
616
617
618
619
620
621
622
623

624
625
626

627
628
629

630
631
632
633
634
635



636
637
638
639
640
641
642
643
644
645
646
647

648
649

650

651
652
653
654
655
656
657
658
659
660
661
662
663

664
665
666
667
668
669
670
671
672
673

674
675
676
677
678



679
680

681
682
683

684
685
686
687
688
689
690
691
692
693
694
695
696
697
698

699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720







721
722
723
724
725
726
727
728


729
730
731
732
733
734
735
736
737
738
739

740
741
742




743











744
745

746
747
748
749
750
751


752
753
754


755
756
757
758
759
760
761
762
































763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797



798
799
800
801
802
803
804
805

806
807



808


809
810
811

812
813
814
815
816
817
818

819
820
821
822
823
824
825

826
827
828
829

830
831
832
833
834

835
836
837
838
839
840
841
401
402
403
404
405
406
407

408
409


410

411
412
413
414

415
416
417

418
419

420

421
422
423
424
425
426


427
428
429
430
431
432
433
434




435
436
437
438
439
440

441

442
443

444

445
446
447
448
449
450


451
452
453
454



455



456



457
















458

































459








460
461





















































462
463
464
465
466
467
468
469
470
471
472

473
474
475
476
477
478
479
480
481
482

483
484
485

486
487
488

489






490
491
492



493
494
495
496
497
498
499
500

501


502

503
504
505
506
507
508
509
510
511
512
513
514
515

516
517
518
519
520
521





522





523
524
525
526

527
528
529

530
531
532
533










534

535



536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553

554
555
556
557
558
559
560
561
562
563
564
565



566
567
568
569
570
571
572
573
574
575
576
577

578

579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597

598

599
600
601


602
603
604


605
606



607




608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639

640
641
642
643
644
645
646
647
648
649
650
651
652
653
654




655
656
657

658
659

660
661
662
663
664



665
666
667
668
669
670
671
672
673
674
675
676


677
678
679

680
681
682
683

684



685
686
687

688
689
690
691
692
693
694

695
696
697
698

699
700
701
702
703

704
705
706
707
708
709
710
711







-


-
-
+
-

+


-
+


-
+

-
+
-

+

+
+

-
-
+







-
-
-
-
+
+
+
+


-
+
-


-
+
-






-
-
+
+


-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-








+


-
+









-
+


-
+


-
+
-
-
-
-
-
-
+
+
+
-
-
-








-
+
-
-
+
-
+












-
+





-
-
-
-
-
+
-
-
-
-
-
+
+
+

-
+


-
+



-
-
-
-
-
-
-
-
-
-

-
+
-
-
-


















-
+
+
+
+
+
+
+





-
-
-
+
+










-
+
-


+
+
+
+

+
+
+
+
+
+
+
+
+
+
+

-
+
-



-
-
+
+

-
-
+
+
-
-
-

-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-















-
-
-
-



-


-





-
-
-
+
+
+








+
-
-
+
+
+
-
+
+


-
+
-
-
-



-
+






-
+



-
+




-
+







 *
 *----------------------------------------------------------------------
 */

MODULE_SCOPE Bool
TkMacOSXInDarkMode(Tk_Window tkwin)
{
    int result = false;

#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400
    static NSAppearanceName darkAqua = @"NSAppearanceNameDarkAqua";

    if (@available(macOS 10.14, *)) {
    if ([NSApp macMinorVersion] >= 14) {
        TkWindow *winPtr = (TkWindow*) tkwin;
	NSAppearanceName name;
	NSView *view = nil;
	if (winPtr && winPtr->privatePtr) {
	    view = TkMacOSXDrawableView(winPtr->privatePtr);
	    view = TkMacOSXGetNSViewForDrawable((Drawable)winPtr->privatePtr);
	}
	if (view) {
	    result = [view.effectiveAppearance.name isEqualToString:darkAqua];
	    name = [[view effectiveAppearance] name];
	} else {
	    result = [[NSAppearance currentAppearance].name
	    name = [[NSAppearance currentAppearance] name];
			 isEqualToString:darkAqua];
	}
	return (name == NSAppearanceNameDarkAqua);
    }
#else
    (void) tkwin;
#endif

    return result;
    return false;
}

/*
 *----------------------------------------------------------------------
 *
 * TkSetMacColor --
 *
 *	Sets the components of a CGColorRef from an XColor pixel value.
 *      The high order byte of the pixel value is used as an index into
 *      the system color table, and then SetCGColorComponents is called
 *      with the table entry and the pixel value.
 *	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.  The parameter macColor should be a pointer to a CGColorRef.
 *
 * Results:
 *      Returns false if the high order byte is not a valid index, true
 *      Returns false if the color is not found, true otherwise.
 *	otherwise.
 *
 * Side effects:
 *	The variable macColor is set to a new CGColorRef, the caller is
 *	The CGColorRef referenced by the variable macColor may be modified.
 *	responsible for releasing it!
 *
 *----------------------------------------------------------------------
 */

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;
    OSStatus err = -1;
    struct SystemColorMapEntry entry;

    SystemColorDatum *entry = GetEntryFromPixel(pixel);
    if (GetEntryFromPixelCode((pixel >> 24) & 0xff, &entry)) {
	err = ChkErr(SetCGColorComponents, entry, pixel, color);
    }

    return (err == noErr);
}

    if (entry) {
/*
 *----------------------------------------------------------------------
 *
 * TkpInitGCCache, TkpFreeGCCache, CopyCachedColor, SetCachedColor --
 *
 *	Maintain a per-GC cache of previously converted CGColorRefs
 *
 * Results:
 *	None resp. retained CGColorRef for CopyCachedColor()
 *
 * Side effects:M
 *	None.
 *
 *----------------------------------------------------------------------
 */

	return SetCGColorComponents(entry, pixel, color);
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) {
    } else {
	    cgColor = gcCache->cachedBackgroundColor;
	}
	if (cgColor) {
	    CFRetain(cgColor);
	}
    }
    return cgColor;
}
	return false;
    }

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 --
 *
 *	Creates an autoreleased NSColor from a X style pixel value.
 *      The return value is nil if the pixel value is invalid.
 *
 * Results:
 *	Returns nil if not a real pixel, NSColor* otherwise.
 *	A possibly nil pointer to an NSColor.
 *
 * Side effects:
 *	None
 *
 *----------------------------------------------------------------------
 */

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) {
    TkSetMacColor(pixel, &cgColor);
	NSColorSpace *colorSpace = [[NSColorSpace alloc]
		initWithCGColorSpace:CGColorGetColorSpace(cgColor)];

	nsColor = [NSColor colorWithColorSpace:colorSpace
		components:CGColorGetComponents(cgColor)
		count:CGColorGetNumberOfComponents(cgColor)];
    nsColor = [NSColor colorWithColorSpace:sRGB
		   components:CGColorGetComponents(cgColor)
		   count:CGColorGetNumberOfComponents(cgColor)];
	[colorSpace release];
	CFRelease(cgColor);
    }
    return nsColor;
}

/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXSetColorInContext --
 *
 *	Sets fill and stroke color in the given CG context from an X
 *	Sets the fill and stroke colors in the given CGContext to the CGColor
 *	pixel value, or if the pixel code indicates a system color,
 *	sets the corresponding brush, textColor or background via
 *	which corresponds to the XColor having the specified value for its pixel
 *	HITheme APIs if available or Appearance mgr APIs.
 *	field.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void
TkMacOSXSetColorInContext(
    GC gc,
    TCL_UNUSED(GC),
    unsigned long pixel,
    CGContextRef context)
{
    OSStatus err = noErr;
    CGColorRef cgColor = nil;
    struct SystemColorMapEntry entry;
    CGRect rect;
    int code = (pixel >> 24) & 0xff;
    HIThemeBackgroundDrawInfo info = {0, kThemeStateActive, 0};;

    SystemColorDatum *entry = GetEntryFromPixel(pixel);
    if (code < FIRST_SEMANTIC_COLOR) {
	cgColor = CopyCachedColor(gc, pixel);
    }
    if (!cgColor && GetEntryFromPixelCode(code, &entry)) {
	switch (entry.type) {

    if (entry) {
	switch (entry->type) {
	case HIBrush:
	    err = ChkErr(HIThemeSetFill, entry.value, NULL, context,
	    err = ChkErr(HIThemeSetFill, entry->value, NULL, context,
		    kHIThemeOrientationNormal);
	    if (err == noErr) {
		err = ChkErr(HIThemeSetStroke, entry.value, NULL, context,
		err = ChkErr(HIThemeSetStroke, entry->value, NULL, context,
			kHIThemeOrientationNormal);
	    }
	    break;
	case HIText:
	    err = ChkErr(HIThemeSetTextFill, entry.value, NULL, context,
		    kHIThemeOrientationNormal);
	    break;
	case HIBackground:
	    info.kind = entry.value;
	    rect = CGContextGetClipBoundingBox(context);
	    err = ChkErr(HIThemeApplyBackground, &rect, &info,
		    context, kHIThemeOrientationNormal);
	    break;
	default:
	    err = ChkErr(SetCGColorComponents, entry, pixel, &cgColor);
	    SetCGColorComponents(entry, pixel, &cgColor);
	    if (err == noErr) {
		SetCachedColor(gc, pixel, cgColor);
	    }
	    break;
	}
    }
    if (cgColor) {
	CGContextSetFillColorWithColor(context, cgColor);
	CGContextSetStrokeColorWithColor(context, cgColor);
	CGColorRelease(cgColor);
    }
    if (err != noErr) {
	TkMacOSXDbgMsg("Ignored unknown pixel value 0x%lx", pixel);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TkpGetColor --
 *
 *	Allocate a new TkColor for the color with the given name.
 *	Create a new TkColor for the color with the given name, for use in the
 *      specified window. The colormap field is set to lightColormap if the
 *      window has a LightAqua appearance, or darkColormap if the window has a
 *      DarkAqua appearance.  TkColors with different colormaps are managed
 *      separately in the per-display table of TkColors maintained by Tk.
 *
 *      This function is called by Tk_GetColor.
 *
 * Results:
 *	Returns a newly allocated TkColor, or NULL on failure.
 *
 * Side effects:
 *	May invalidate the colormap cache associated with tkwin upon
 *	allocating a new colormap entry. Allocates a new TkColor
 *	structure.
 *
 *	Allocates memory for the TkColor structure.
 *
 *----------------------------------------------------------------------
 */

TkColor *
TkpGetColor(
    Tk_Window tkwin,		/* Window in which color will be used. */
    Tk_Uid name)		/* Name of color to be allocated (in form
				 * suitable for passing to XParseColor). */
{
    Display *display = tkwin != None ? Tk_Display(tkwin) : NULL;
    Display *display = NULL;
    Colormap colormap = tkwin!= None ? Tk_Colormap(tkwin) : None;
    TkColor *tkColPtr;
    XColor color;
    Colormap colormap = tkwin ? Tk_Colormap(tkwin) : noColormap;
    NSView *view = nil;
    static Bool initialized = NO;
    static NSColorSpace* sRGB = nil;

    if (!initialized) {
	initialized = YES;
	sRGB = [NSColorSpace sRGBColorSpace];
	initColorTable();
    }
    if (tkwin) {
	display = Tk_Display(tkwin);
	Drawable d = Tk_WindowId(tkwin);
	view = TkMacOSXGetNSViewForDrawable(d);
    }

    /*
     * Check to see if this is a system color. Otherwise, XParseColor
     * Check to see if this is a system color. If not, just call XParseColor.
     * will do all the work.
     */

    if (strncasecmp(name, "system", 6) == 0) {
	Tcl_Obj *strPtr = Tcl_NewStringObj(name+6, -1);
	int idx, result;
	Tcl_HashEntry *hPtr = Tcl_FindHashEntry(&systemColors, name + 6);
	MacPixel p = {0};

	result = Tcl_GetIndexFromObjStruct(NULL, strPtr, systemColorMap,
		sizeof(struct SystemColorMapEntry), NULL, TCL_EXACT, &idx);
	if (hPtr != NULL) {
	    SystemColorDatum *entry = (SystemColorDatum *)Tcl_GetHashValue(hPtr);
	Tcl_DecrRefCount(strPtr);
	if (result == TCL_OK) {
	    OSStatus err;
	    CGColorRef c;
	    unsigned char pixelCode = idx + MIN_PIXELCODE;
	    struct SystemColorMapEntry entry = systemColorMap[idx];

	    err = ChkErr(SetCGColorComponents, entry, 0, &c);

	    p.pixel.colortype = entry->type;
	    p.pixel.value = entry->index;
	    color.pixel = p.ulong;
	    if (entry->type == semantic) {
		CGFloat rgba[4];
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400
		if (@available(macOS 10.14, *)) {
		    NSAppearance *savedAppearance = [NSAppearance currentAppearance];
		    NSAppearance *windowAppearance = savedAppearance;
		    if (view) {
			windowAppearance = [view effectiveAppearance];
		    }
		    if ([windowAppearance name] == NSAppearanceNameDarkAqua) {
			colormap = darkColormap;
		    } else {
			colormap = lightColormap;
		    }
		    [NSAppearance setCurrentAppearance:windowAppearance];
		    GetRGBA(entry, p.ulong, rgba);
		    [NSAppearance setCurrentAppearance:savedAppearance];
		} else {
		    GetRGBA(entry, p.ulong, rgba);
		}
#else
		GetRGBA(entry, p.ulong, rgba);
#endif
		color.red   = rgba[0] * 65535.0;
		color.green = rgba[1] * 65535.0;
		color.blue  = rgba[2] * 65535.0;
		goto validXColor;
	    } else if (SetCGColorComponents(entry, 0, &c)) {
	    if (err == noErr) {
		const size_t n = CGColorGetNumberOfComponents(c);
		const CGFloat *rgba = CGColorGetComponents(c);

		switch (n) {
		case 4:
		    color.red   = rgba[0] * 65535.0;
		    color.green = rgba[1] * 65535.0;
		    color.blue  = rgba[2] * 65535.0;
		    break;
		case 2:
		    color.red = color.green = color.blue = rgba[0] * 65535.0;
		    break;
		default:
		    Tcl_Panic("CGColor with %d components", (int) n);
		}
		color.pixel = ((((((pixelCode << 8)
			| ((color.red   >> 8) & 0xff)) << 8)
			| ((color.green >> 8) & 0xff)) << 8)
			| ((color.blue  >> 8) & 0xff));
		CGColorRelease(c);
		goto validXColor;
	    }
	    CGColorRelease(c);
	}
    }

    if (TkParseColor(display, colormap, name, &color) == 0) {
	return NULL;
    }

validXColor:
    tkColPtr = ckalloc(sizeof(TkColor));
    tkColPtr->color = color;

    tkColPtr = (TkColor *)ckalloc(sizeof(TkColor));
    tkColPtr->colormap = colormap;
    tkColPtr->color = color;
    return tkColPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * TkpGetColorByValue --
 *
 *	Given an pointer to an XColor, construct a TkColor whose red, green and
 *	Given a desired set of red-green-blue intensities for a color,
 *	locate a pixel value to use to draw that color in a given
 *	blue intensities match those of the XColor as closely as possible.  For
 *	the Macintosh, this means that the colortype bitfield of the pixel
 *	value will be RGBColor and that the color intensities stored in its
 *	window.
 *	24-bit value bitfield are computed from the 16-bit red green and blue
 *	values in the XColor by dividing by 256.
 *
 * Results:
 *	The return value is a pointer to an TkColor structure that
 *	A pointer to a newly allocated TkColor structure.
 *	indicates the closest red, blue, and green intensities available
 *	to those specified in colorPtr, and also specifies a pixel
 *	value to use to draw in that color.
 *
 * Side effects:
 *	May invalidate the colormap cache for the specified window.
 *	Allocates a new TkColor structure.
 *	Allocates memory for a TkColor structure.
 *
 *----------------------------------------------------------------------
 */

TkColor *
TkpGetColorByValue(
    Tk_Window tkwin,		/* Window in which color will be used. */
    TCL_UNUSED(Tk_Window),		/* Window in which color will be used. */
    XColor *colorPtr)		/* Red, green, and blue fields indicate
				 * desired color. */
{
    TkColor *tkColPtr = ckalloc(sizeof(TkColor));
    TkColor *tkColPtr = (TkColor *)ckalloc(sizeof(TkColor));

    tkColPtr->color.red = colorPtr->red;
    tkColPtr->color.green = colorPtr->green;
    tkColPtr->color.blue = colorPtr->blue;
    tkColPtr->color.pixel = TkpGetPixel(&tkColPtr->color);
    tkColPtr->color.pixel = TkpGetPixel(colorPtr);
    return tkColPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * Stub functions --
851
852
853
854
855
856
857
858

859
860
861
862
863
864
865
866
867
868
869
870
871




872
873

874
875
876


877
878
879
880
881
882
883
884


885
886
887
888
889
890
891
892
893
894
895





896
897
898
899
900


901
902
903
904
905
906
907
908
909
910
911
912
721
722
723
724
725
726
727

728
729
730
731
732
733
734
735
736
737




738
739
740
741
742

743
744
745

746
747
748
749
750
751
752
753


754
755
756
757
758
759
760
761





762
763
764
765
766
767
768



769
770
771
772
773
774
775
776
777
778
779
780
781
782







-
+









-
-
-
-
+
+
+
+

-
+


-
+
+






-
-
+
+






-
-
-
-
-
+
+
+
+
+


-
-
-
+
+












 *
 *----------------------------------------------------------------------
 */

Status
XAllocColor(
    Display *display,		/* Display. */
    Colormap map,		/* Not used. */
    TCL_UNUSED(Colormap),		/* Not used. */
    XColor *colorPtr)		/* XColor struct to modify. */
{
    display->request++;
    colorPtr->pixel = TkpGetPixel(colorPtr);
    return 1;
}

Colormap
XCreateColormap(
    Display *display,		/* Display. */
    Window window,		/* X window. */
    Visual *visual,		/* Not used. */
    int alloc)			/* Not used. */
    TCL_UNUSED(Display *),		/* Display. */
    TCL_UNUSED(Window),		/* X window. */
    TCL_UNUSED(Visual *),		/* Not used. */
    TCL_UNUSED(int))			/* Not used. */
{
    static Colormap index = 1;
    static Colormap index = 16;

    /*
     * Just return a new value each time.
     * Just return a new value each time, large enough that it will not
     * conflict with any value of the macColormap enum.
     */
    return index++;
}

int
XFreeColormap(
    Display* display,		/* Display. */
    Colormap colormap)		/* Colormap. */
    TCL_UNUSED(Display *),		/* Display. */
    TCL_UNUSED(Colormap))		/* Colormap. */
{
    return Success;
}

int
XFreeColors(
    Display* display,		/* Display. */
    Colormap colormap,		/* Colormap. */
    unsigned long* pixels,	/* Array of pixels. */
    int npixels,		/* Number of pixels. */
    unsigned long planes)	/* Number of pixel planes. */
    TCL_UNUSED(Display *),		/* Display. */
    TCL_UNUSED(Colormap),		/* Colormap. */
    TCL_UNUSED(unsigned long *),	/* Array of pixels. */
    TCL_UNUSED(int),		/* Number of pixels. */
    TCL_UNUSED(unsigned long))	/* Number of pixel planes. */
{
    /*
     * The Macintosh version of Tk uses TrueColor. Nothing
     * needs to be done to release colors as there really is
     * no colormap in the Tk sense.
     * Nothing needs to be done to release colors as there really is no
     * colormap in the Tk sense.
     */
    return Success;
}

/*
 * Local Variables:
 * mode: objc
 * c-basic-offset: 4
 * fill-column: 79
 * coding: utf-8
 * End:
 */
Added macosx/tkMacOSXColor.h.







































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
#ifndef MACOSXCOLOR_H
#define MACOSXCOLOR_H
/*
 * The generic Tk code uses the X11 GC type to describe a graphics context.
 * (A GC is a pointer to a struct XGCValues).  The foreground and background
 * colors in a GC are unsigned longs.  These are meant to be used as indexes
 * into a table of XColors, where an XColor is declared in Xlib.h as:
 * typedef struct {
 *       unsigned long pixel;
 *       unsigned short red, green, blue;
 *       char flags;
 *       char pad;
 * } XColor;
 *
 * The xlib function XParseColor creates XColors from strings.  It recognizes
 * literal hexadecimal color specifications such as "#RRGGBB" as well as the
 * standard X11 color names.  When XParseColor creates an XColor it fills in
 * all of the fields except for the pixel field, and then passes the XColor
 * to TkpGetPixel to get a value to use for the pixel field. Since TkpGetPixel
 * is platform specific, each platform is free to choose a value which can
 * be used to set the foreground or background color in the platform's graphics
 * context.
 *
 * Tk represents a color by a struct TkColor, which extends the XColor struct.
 * Tk provides a mapping from color names to TkColors which extends the mapping
 * provided by XParseColor but also allows for platform specific color names.
 * By convention, these platform specific color names begin with the string
 * "system".  The mapping from names to TkColors is implemented by the function
 * TkpGetColor defined for the Macintosh in this file.  The pixel field in the
 * XColor contained in a TkColor will be stored in the X11 graphics context.
 * In X11 the pixel field is used as an index into a colormap.  On the Mac
 * the high order byte of the pixel is used to indicate a color type and
 * the low 24 bits are either used as an rgb value (if the type is rgbColor)
 * or as an index into a table of color descriptions.
 */

enum colorType {
    rgbColor,      /* The 24 bit value is an rgb color. */
    clearColor,    /* The unique rgba color with all channels 0. */
    HIBrush,       /* A HITheme brush color.*/
    ttkBackground, /* A background color which indicates nesting level.*/
    semantic,      /* A semantic NSColor.*/
};

typedef struct xpixel_t {
    unsigned value: 24;     /* Either RGB or an index into systemColorData. */
    unsigned colortype: 8;
} xpixel;

typedef union MacPixel_t {
    unsigned long ulong;
    xpixel pixel;
} MacPixel;

/*
 * We maintain two colormaps, one for the LightAqua appearance and one for the
 * DarkAqua appearance.
 */

enum macColormap {
    noColormap,
    lightColormap,
    darkColormap,
};

/*
 * In TkMacOSXColor.c a Tk hash table is constructed from the static data
 * below to map system color names to CGColors.
 */

typedef struct {
    const char *name;
    enum colorType type;
    int value;
    const char *macName;
    /* Fields below are filled in after or during construction of the hash table. */
    int index;
    NSString *selector;
} SystemColorDatum;

/*
 * WARNING: Semantic colors which are not supported on all systems must be
 * preceded by a backup color with the same name which *is* supported.  Systems
 * which do support the color will replace the backup value when the table is
 * 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 },

{"Highlight",				HIBrush,  kThemeBrushPrimaryHighlightColor, NULL, 0, NULL },
{"HighlightSecondary",		    	HIBrush,  kThemeBrushSecondaryHighlightColor, NULL, 0, NULL },
{"HighlightText",			HIBrush,  kThemeBrushBlack, NULL, 0, NULL },
{"HighlightAlternate",			HIBrush,  kThemeBrushAlternatePrimaryHighlightColor, NULL, 0, NULL },
{"PrimaryHighlightColor",		HIBrush,  kThemeBrushPrimaryHighlightColor, NULL, 0, NULL },
{"ButtonFace",				HIBrush,  kThemeBrushButtonFaceActive, NULL, 0, NULL },
{"SecondaryHighlightColor",		HIBrush,  kThemeBrushSecondaryHighlightColor, NULL, 0, NULL },
{"ButtonFrame",				HIBrush,  kThemeBrushButtonFrameActive, NULL, 0, NULL },
{"AlternatePrimaryHighlightColor",      HIBrush,  kThemeBrushAlternatePrimaryHighlightColor, NULL, 0, NULL },
{"WindowBody",				HIBrush,  kThemeBrushDocumentWindowBackground, NULL, 0, NULL },
{"SheetBackground",			HIBrush,  kThemeBrushSheetBackground, NULL, 0, NULL },
{"MenuActive",				HIBrush,  kThemeBrushMenuBackgroundSelected, NULL, 0, NULL },
{"Menu",				HIBrush,  kThemeBrushMenuBackground, NULL, 0, NULL },
{"DialogBackgroundInactive",		HIBrush,  kThemeBrushDialogBackgroundInactive, NULL, 0, NULL },
{"DialogBackgroundActive",		HIBrush,  kThemeBrushDialogBackgroundActive, NULL, 0, NULL },
{"AlertBackgroundActive",		HIBrush,  kThemeBrushAlertBackgroundActive, NULL, 0, NULL },
{"AlertBackgroundInactive",		HIBrush,  kThemeBrushAlertBackgroundInactive, NULL, 0, NULL },
{"ModelessDialogBackgroundActive",	HIBrush,  kThemeBrushModelessDialogBackgroundActive, NULL, 0, NULL },
{"ModelessDialogBackgroundInactive",	HIBrush,  kThemeBrushModelessDialogBackgroundInactive, NULL, 0, NULL },
{"UtilityWindowBackgroundActive",	HIBrush,  kThemeBrushUtilityWindowBackgroundActive, NULL, 0, NULL },
{"UtilityWindowBackgroundInactive",	HIBrush,  kThemeBrushUtilityWindowBackgroundInactive, NULL, 0, NULL },
{"ListViewSortColumnBackground",	HIBrush,  kThemeBrushListViewSortColumnBackground, NULL, 0, NULL },
{"ListViewBackground",			HIBrush,  kThemeBrushListViewBackground, NULL, 0, NULL },
{"IconLabelBackground",			HIBrush,  kThemeBrushIconLabelBackground, NULL, 0, NULL },
{"ListViewSeparator",			HIBrush,  kThemeBrushListViewSeparator, NULL, 0, NULL },
{"ChasingArrows",			HIBrush,  kThemeBrushChasingArrows, NULL, 0, NULL },
{"DragHilite",				HIBrush,  kThemeBrushDragHilite, NULL, 0, NULL },
{"DocumentWindowBackground",		HIBrush,  kThemeBrushDocumentWindowBackground, NULL, 0, NULL },
{"FinderWindowBackground",		HIBrush,  kThemeBrushFinderWindowBackground, NULL, 0, NULL },
{"ScrollBarDelimiterActive",		HIBrush,  kThemeBrushScrollBarDelimiterActive, NULL, 0, NULL },
{"ScrollBarDelimiterInactive",		HIBrush,  kThemeBrushScrollBarDelimiterInactive, NULL, 0, NULL },
{"FocusHighlight",			HIBrush,  kThemeBrushFocusHighlight, NULL, 0, NULL },
{"PopupArrowActive",			HIBrush,  kThemeBrushPopupArrowActive, NULL, 0, NULL },
{"PopupArrowPressed",			HIBrush,  kThemeBrushPopupArrowPressed, NULL, 0, NULL },
{"PopupArrowInactive",			HIBrush,  kThemeBrushPopupArrowInactive, NULL, 0, NULL },
{"AppleGuideCoachmark",			HIBrush,  kThemeBrushAppleGuideCoachmark, NULL, 0, NULL },
{"IconLabelBackgroundSelected",		HIBrush,  kThemeBrushIconLabelBackgroundSelected, NULL, 0, NULL },
{"StaticAreaFill",			HIBrush,  kThemeBrushStaticAreaFill, NULL, 0, NULL },
{"ActiveAreaFill",			HIBrush,  kThemeBrushActiveAreaFill, NULL, 0, NULL },
{"ButtonFrameActive",			HIBrush,  kThemeBrushButtonFrameActive, NULL, 0, NULL },
{"ButtonFrameInactive",			HIBrush,  kThemeBrushButtonFrameInactive, NULL, 0, NULL },
{"ButtonFaceActive",			HIBrush,  kThemeBrushButtonFaceActive, NULL, 0, NULL },
{"ButtonFaceInactive",			HIBrush,  kThemeBrushButtonFaceInactive, NULL, 0, NULL },
{"ButtonFacePressed",			HIBrush,  kThemeBrushButtonFacePressed, NULL, 0, NULL },
{"ButtonActiveDarkShadow",		HIBrush,  kThemeBrushButtonActiveDarkShadow, NULL, 0, NULL },
{"ButtonActiveDarkHighlight",		HIBrush,  kThemeBrushButtonActiveDarkHighlight, NULL, 0, NULL },
{"ButtonActiveLightShadow",		HIBrush,  kThemeBrushButtonActiveLightShadow, NULL, 0, NULL },
{"ButtonActiveLightHighlight",		HIBrush,  kThemeBrushButtonActiveLightHighlight, NULL, 0, NULL },
{"ButtonInactiveDarkShadow",		HIBrush,  kThemeBrushButtonInactiveDarkShadow, NULL, 0, NULL },
{"ButtonInactiveDarkHighlight",		HIBrush,  kThemeBrushButtonInactiveDarkHighlight, NULL, 0, NULL },
{"ButtonInactiveLightShadow",		HIBrush,  kThemeBrushButtonInactiveLightShadow, NULL, 0, NULL },
{"ButtonInactiveLightHighlight",	HIBrush,  kThemeBrushButtonInactiveLightHighlight, NULL, 0, NULL },
{"ButtonPressedDarkShadow",		HIBrush,  kThemeBrushButtonPressedDarkShadow, NULL, 0, NULL },
{"ButtonPressedDarkHighlight",		HIBrush,  kThemeBrushButtonPressedDarkHighlight, NULL, 0, NULL },
{"ButtonPressedLightShadow",		HIBrush,  kThemeBrushButtonPressedLightShadow, NULL, 0, NULL },
{"ButtonPressedLightHighlight",		HIBrush,  kThemeBrushButtonPressedLightHighlight, NULL, 0, NULL },
{"BevelActiveLight",			HIBrush,  kThemeBrushBevelActiveLight, NULL, 0, NULL },
{"BevelActiveDark",			HIBrush,  kThemeBrushBevelActiveDark, NULL, 0, NULL },
{"BevelInactiveLight",			HIBrush,  kThemeBrushBevelInactiveLight, NULL, 0, NULL },
{"BevelInactiveDark",			HIBrush,  kThemeBrushBevelInactiveDark, NULL, 0, NULL },
{"NotificationWindowBackground",	HIBrush,  kThemeBrushNotificationWindowBackground, NULL, 0, NULL },
{"MovableModalBackground",		HIBrush,  kThemeBrushMovableModalBackground, NULL, 0, NULL },
{"SheetBackgroundOpaque",		HIBrush,  kThemeBrushSheetBackgroundOpaque, NULL, 0, NULL },
{"DrawerBackground",			HIBrush,  kThemeBrushDrawerBackground, NULL, 0, NULL },
{"ToolbarBackground",			HIBrush,  kThemeBrushToolbarBackground, NULL, 0, NULL },
{"SheetBackgroundTransparent",		HIBrush,  kThemeBrushSheetBackgroundTransparent, NULL, 0, NULL },
{"MenuBackground",			HIBrush,  kThemeBrushMenuBackground, NULL, 0, NULL },
{"MenuBackgroundSelected",		HIBrush,  kThemeBrushMenuBackgroundSelected, NULL, 0, NULL },
{"ListViewOddRowBackground",		HIBrush,  kThemeBrushListViewOddRowBackground, NULL, 0, NULL },
{"ListViewEvenRowBackground",		HIBrush,  kThemeBrushListViewEvenRowBackground, NULL, 0, NULL },
{"ListViewColumnDivider",		HIBrush,  kThemeBrushListViewColumnDivider, NULL, 0, NULL },

    /*
     * Dynamic Colors
     */

{"WindowBackgroundColor",	    ttkBackground, 0, NULL, 0, NULL },
{"WindowBackgroundColor1",	    ttkBackground, 1, NULL, 0, NULL },
{"WindowBackgroundColor2",	    ttkBackground, 2, NULL, 0, NULL },
{"WindowBackgroundColor3",	    ttkBackground, 3, NULL, 0, NULL },
{"WindowBackgroundColor4",	    ttkBackground, 4, NULL, 0, NULL },
{"WindowBackgroundColor5",	    ttkBackground, 5, NULL, 0, NULL },
{"WindowBackgroundColor6",	    ttkBackground, 6, NULL, 0, NULL },
{"WindowBackgroundColor7",	    ttkBackground, 7, NULL, 0, NULL },
/* Apple's SecondaryLabelColor is the same as their LabelColor so we roll our own. */
{"SecondaryLabelColor",		    ttkBackground, 14, NULL, 0, NULL },
/* Color to use for notebook tab labels -- depends on OS version. */
{"SelectedTabTextColor",	    semantic, 0, "textColor", 0, NULL },
/* Semantic colors that we simulate on older systems which don't supoort them. */
{"SelectedMenuItemTextColor",       semantic, 0, "selectedMenuItemTextColor", 0, NULL },
{"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 },
{"UnemphasizedSelectedTextBackgroundColor", semantic, 0, "grayColor", 0, NULL },
{NULL,				    0, 0, NULL, 0, NULL }
};

#endif
/*
 * Local Variables:
 * mode: objc
 * c-basic-offset: 4
 * fill-column: 79
 * coding: utf-8
 * End:
 */
Changes to macosx/tkMacOSXConfig.c.
1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15






-
-
+
+







/*
 * 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.
 */

#include "tkInt.h"

35
36
37
38
39
40
41




42
43
44
45
46
47
48
49
50
51
52
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56







+
+
+
+












Tcl_Obj *
TkpGetSystemDefault(
    Tk_Window tkwin,			/* A window to use. */
    const char *dbName,			/* The option database name. */
    const char *className)		/* The name of the option class. */
{
    (void)tkwin;
    (void)dbName;
    (void)className;

    return NULL;
}

/*
 * Local Variables:
 * mode: objc
 * c-basic-offset: 4
 * fill-column: 79
 * coding: utf-8
 * End:
 */
Changes to macosx/tkMacOSXConstants.h.
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20




21
22
23
24
25
26
27
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31








-
+











+
+
+
+







/*
 * tkMacOSXConstants.h --
 *
 *	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.
 */

#ifndef _TKMACCONSTANTS
#define _TKMACCONSTANTS

#if MAC_OS_X_VERSION_MAX_ALLOWED < 1070
#define NSFullScreenWindowMask (1 << 14)
#endif

#if MAC_OS_X_VERSION_MAX_ALLOWED < 1090
typedef NSInteger NSModalResponse;
#endif

/*
 * Let's raise a glass for the project manager who improves our lives by
 * generating deprecation warnings about pointless changes of the names
 * of constants.
 */

94
95
96
97
98
99
100
101
102
103
104



105






106
107

98
99
100
101
102
103
104


105
106
107
108
109
110
111
112
113
114
115
116
117
118
119







-
-


+
+
+

+
+
+
+
+
+


+
#define NSFullScreenWindowMask NSWindowStyleMaskFullScreen
#endif

#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
#define NSStringPboardType NSPasteboardTypeString
#define NSOnState NSControlStateValueOn
#define NSOffState NSControlStateValueOff
// Now we are also changing names of methods!
#define graphicsContextWithGraphicsPort graphicsContextWithCGContext
#endif

#if MAC_OS_X_VERSION_MIN_REQUIRED >= 110000
#define NSWindowStyleMaskTexturedBackground 0
#endif

#if MAC_OS_X_VERSION_MIN_REQUIRED < 101000
#define GET_NSCONTEXT(context, flip) [NSGraphicsContext		\
	    graphicsContextWithGraphicsPort:context flipped:flip]
#else
#define GET_NSCONTEXT(context, flip) [NSGraphicsContext		\
	    graphicsContextWithCGContext:context flipped:NO]
#endif

#endif
Changes to macosx/tkMacOSXCursor.c.
1
2
3
4
5
6
7
8



9
10
11
12
13
14
15
1
2
3
4
5



6
7
8
9
10
11
12
13
14
15





-
-
-
+
+
+







/*
 * 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 <[email protected]>
 * Copyright © 1995-1997 Sun Microsystems, Inc.
 * Copyright © 2001-2009 Apple Inc.
 * Copyright © 2006-2009 Daniel A. Steffen <[email protected]>
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tkMacOSXPrivate.h"
#include "tkMacOSXCursors.h"
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94






































95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181






















































































182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
50
51
52
53
54
55
56






































57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95






















































































96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189









190
191
192
193
194
195
196







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








-
-
-
-
-
-
-
-
-







    NSPoint hotspot;
};

#define MacCursorData(n)	((id)tkMacOSXCursors[TK_MAC_CURSOR_##n])
#define MacXCursorData(n)	((id)tkMacOSXXCursors[TK_MAC_XCURSOR_##n])

static const struct CursorName cursorNames[] = {
    {"none",			NONE,	    nil},
    {"arrow",			SELECTOR,    @"arrowCursor"},
    {"top_left_arrow",		SELECTOR,    @"arrowCursor"},
    {"left_ptr",		SELECTOR,    @"arrowCursor"},
    {"copyarrow",		SELECTOR,    @"dragCopyCursor", @"_copyDragCursor"},
    {"aliasarrow",		SELECTOR,    @"dragLinkCursor", @"_linkDragCursor"},
    {"contextualmenuarrow",	SELECTOR,    @"contextualMenuCursor"},
    {"movearrow",		SELECTOR,    @"_moveCursor"},
    {"ibeam",			SELECTOR,    @"IBeamCursor"},
    {"text",			SELECTOR,    @"IBeamCursor"},
    {"xterm",			SELECTOR,    @"IBeamCursor"},
    {"cross",			SELECTOR,    @"crosshairCursor"},
    {"crosshair",		SELECTOR,    @"crosshairCursor"},
    {"cross-hair",		SELECTOR,    @"crosshairCursor"},
    {"tcross",			SELECTOR,    @"crosshairCursor"},
    {"hand",			SELECTOR,    @"openHandCursor"},
    {"openhand",		SELECTOR,    @"openHandCursor"},
    {"closedhand",		SELECTOR,    @"closedHandCursor"},
    {"fist",			SELECTOR,    @"closedHandCursor"},
    {"pointinghand",		SELECTOR,    @"pointingHandCursor"},
    {"resize",			SELECTOR,    @"arrowCursor"},
    {"resizeleft",		SELECTOR,    @"resizeLeftCursor"},
    {"resizeright",		SELECTOR,    @"resizeRightCursor"},
    {"resizeleftright",		SELECTOR,    @"resizeLeftRightCursor"},
    {"resizeup",		SELECTOR,    @"resizeUpCursor"},
    {"resizedown",		SELECTOR,    @"resizeDownCursor"},
    {"resizeupdown",		SELECTOR,    @"resizeUpDownCursor"},
    {"resizebottomleft",	SELECTOR,    @"_bottomLeftResizeCursor"},
    {"resizetopleft",		SELECTOR,    @"_topLeftResizeCursor"},
    {"resizebottomright",	SELECTOR,    @"_bottomRightResizeCursor"},
    {"resizetopright",		SELECTOR,    @"_topRightResizeCursor"},
    {"notallowed",		SELECTOR,    @"operationNotAllowedCursor"},
    {"poof",			SELECTOR,    @"disappearingItemCursor"},
    {"wait",			SELECTOR,    @"busyButClickableCursor"},
    {"spinning",		SELECTOR,    @"busyButClickableCursor"},
    {"countinguphand",		SELECTOR,    @"busyButClickableCursor"},
    {"countingdownhand",	SELECTOR,    @"busyButClickableCursor"},
    {"countingupanddownhand",	SELECTOR,    @"busyButClickableCursor"},
    {"none",			NONE,	    nil, nil, {0, 0}},
    {"arrow",			SELECTOR,    @"arrowCursor", nil, {0, 0}},
    {"top_left_arrow",		SELECTOR,    @"arrowCursor", nil, {0, 0}},
    {"left_ptr",		SELECTOR,    @"arrowCursor", nil, {0, 0}},
    {"copyarrow",		SELECTOR,    @"dragCopyCursor", @"_copyDragCursor", {0, 0}},
    {"aliasarrow",		SELECTOR,    @"dragLinkCursor", @"_linkDragCursor", {0, 0}},
    {"contextualmenuarrow",	SELECTOR,    @"contextualMenuCursor", nil, {0, 0}},
    {"movearrow",		SELECTOR,    @"_moveCursor", nil, {0, 0}},
    {"ibeam",			SELECTOR,    @"IBeamCursor", nil, {0, 0}},
    {"text",			SELECTOR,    @"IBeamCursor", nil, {0, 0}},
    {"xterm",			SELECTOR,    @"IBeamCursor", nil, {0, 0}},
    {"cross",			SELECTOR,    @"crosshairCursor", nil, {0, 0}},
    {"crosshair",		SELECTOR,    @"crosshairCursor", nil, {0, 0}},
    {"cross-hair",		SELECTOR,    @"crosshairCursor", nil, {0, 0}},
    {"tcross",			SELECTOR,    @"crosshairCursor", nil, {0, 0}},
    {"hand",			SELECTOR,    @"openHandCursor", nil, {0, 0}},
    {"openhand",		SELECTOR,    @"openHandCursor", nil, {0, 0}},
    {"closedhand",		SELECTOR,    @"closedHandCursor", nil, {0, 0}},
    {"fist",			SELECTOR,    @"closedHandCursor", nil, {0, 0}},
    {"pointinghand",		SELECTOR,    @"pointingHandCursor", nil, {0, 0}},
    {"resize",			SELECTOR,    @"arrowCursor", nil, {0, 0}},
    {"resizeleft",		SELECTOR,    @"resizeLeftCursor", nil, {0, 0}},
    {"resizeright",		SELECTOR,    @"resizeRightCursor", nil, {0, 0}},
    {"resizeleftright",		SELECTOR,    @"resizeLeftRightCursor", nil, {0, 0}},
    {"resizeup",		SELECTOR,    @"resizeUpCursor", nil, {0, 0}},
    {"resizedown",		SELECTOR,    @"resizeDownCursor", nil, {0, 0}},
    {"resizeupdown",		SELECTOR,    @"resizeUpDownCursor", nil, {0, 0}},
    {"resizebottomleft",	SELECTOR,    @"_bottomLeftResizeCursor", nil, {0, 0}},
    {"resizetopleft",		SELECTOR,    @"_topLeftResizeCursor", nil, {0, 0}},
    {"resizebottomright",	SELECTOR,    @"_bottomRightResizeCursor", nil, {0, 0}},
    {"resizetopright",		SELECTOR,    @"_topRightResizeCursor", nil, {0, 0}},
    {"notallowed",		SELECTOR,    @"operationNotAllowedCursor", nil, {0, 0}},
    {"poof",			SELECTOR,    @"disappearingItemCursor", nil, {0, 0}},
    {"wait",			SELECTOR,    @"busyButClickableCursor", nil, {0, 0}},
    {"spinning",		SELECTOR,    @"busyButClickableCursor", nil, {0, 0}},
    {"countinguphand",		SELECTOR,    @"busyButClickableCursor", nil, {0, 0}},
    {"countingdownhand",	SELECTOR,    @"busyButClickableCursor", nil, {0, 0}},
    {"countingupanddownhand",	SELECTOR,    @"busyButClickableCursor", nil, {0, 0}},
    {"help",			IMAGENAMED,  @"NSHelpCursor", nil, {8, 8}},
//  {"hand",			IMAGEBITMAP, MacCursorData(hand)},
    {"bucket",			IMAGEBITMAP, MacCursorData(bucket)},
    {"cancel",			IMAGEBITMAP, MacCursorData(cancel)},
//  {"resize",			IMAGEBITMAP, MacCursorData(resize)},
    {"eyedrop",			IMAGEBITMAP, MacCursorData(eyedrop)},
    {"eyedrop-full",		IMAGEBITMAP, MacCursorData(eyedrop_full)},
    {"zoom-in",			IMAGEBITMAP, MacCursorData(zoom_in)},
    {"zoom-out",		IMAGEBITMAP, MacCursorData(zoom_out)},
    {"X_cursor",		IMAGEBITMAP, MacXCursorData(X_cursor)},
//  {"arrow",			IMAGEBITMAP, MacXCursorData(arrow)},
    {"based_arrow_down",	IMAGEBITMAP, MacXCursorData(based_arrow_down)},
    {"based_arrow_up",		IMAGEBITMAP, MacXCursorData(based_arrow_up)},
    {"boat",			IMAGEBITMAP, MacXCursorData(boat)},
    {"bogosity",		IMAGEBITMAP, MacXCursorData(bogosity)},
    {"bottom_left_corner",	IMAGEBITMAP, MacXCursorData(bottom_left_corner)},
    {"bottom_right_corner",	IMAGEBITMAP, MacXCursorData(bottom_right_corner)},
    {"bottom_side",		IMAGEBITMAP, MacXCursorData(bottom_side)},
    {"bottom_tee",		IMAGEBITMAP, MacXCursorData(bottom_tee)},
    {"box_spiral",		IMAGEBITMAP, MacXCursorData(box_spiral)},
    {"center_ptr",		IMAGEBITMAP, MacXCursorData(center_ptr)},
    {"circle",			IMAGEBITMAP, MacXCursorData(circle)},
    {"clock",			IMAGEBITMAP, MacXCursorData(clock)},
    {"coffee_mug",		IMAGEBITMAP, MacXCursorData(coffee_mug)},
//  {"cross",			IMAGEBITMAP, MacXCursorData(cross)},
    {"cross_reverse",		IMAGEBITMAP, MacXCursorData(cross_reverse)},
//  {"crosshair",		IMAGEBITMAP, MacXCursorData(crosshair)},
    {"diamond_cross",		IMAGEBITMAP, MacXCursorData(diamond_cross)},
    {"dot",			IMAGEBITMAP, MacXCursorData(dot)},
    {"dotbox",			IMAGEBITMAP, MacXCursorData(dotbox)},
    {"double_arrow",		IMAGEBITMAP, MacXCursorData(double_arrow)},
    {"draft_large",		IMAGEBITMAP, MacXCursorData(draft_large)},
    {"draft_small",		IMAGEBITMAP, MacXCursorData(draft_small)},
    {"draped_box",		IMAGEBITMAP, MacXCursorData(draped_box)},
    {"exchange",		IMAGEBITMAP, MacXCursorData(exchange)},
    {"fleur",			IMAGEBITMAP, MacXCursorData(fleur)},
    {"gobbler",			IMAGEBITMAP, MacXCursorData(gobbler)},
    {"gumby",			IMAGEBITMAP, MacXCursorData(gumby)},
    {"hand1",			IMAGEBITMAP, MacXCursorData(hand1)},
    {"hand2",			IMAGEBITMAP, MacXCursorData(hand2)},
    {"heart",			IMAGEBITMAP, MacXCursorData(heart)},
    {"icon",			IMAGEBITMAP, MacXCursorData(icon)},
    {"iron_cross",		IMAGEBITMAP, MacXCursorData(iron_cross)},
//  {"left_ptr",		IMAGEBITMAP, MacXCursorData(left_ptr)},
    {"left_side",		IMAGEBITMAP, MacXCursorData(left_side)},
    {"left_tee",		IMAGEBITMAP, MacXCursorData(left_tee)},
    {"leftbutton",		IMAGEBITMAP, MacXCursorData(leftbutton)},
    {"ll_angle",		IMAGEBITMAP, MacXCursorData(ll_angle)},
    {"lr_angle",		IMAGEBITMAP, MacXCursorData(lr_angle)},
    {"man",			IMAGEBITMAP, MacXCursorData(man)},
    {"middlebutton",		IMAGEBITMAP, MacXCursorData(middlebutton)},
    {"mouse",			IMAGEBITMAP, MacXCursorData(mouse)},
    {"pencil",			IMAGEBITMAP, MacXCursorData(pencil)},
    {"pirate",			IMAGEBITMAP, MacXCursorData(pirate)},
    {"plus",			IMAGEBITMAP, MacXCursorData(plus)},
    {"question_arrow",		IMAGEBITMAP, MacXCursorData(question_arrow)},
    {"right_ptr",		IMAGEBITMAP, MacXCursorData(right_ptr)},
    {"right_side",		IMAGEBITMAP, MacXCursorData(right_side)},
    {"right_tee",		IMAGEBITMAP, MacXCursorData(right_tee)},
    {"rightbutton",		IMAGEBITMAP, MacXCursorData(rightbutton)},
    {"rtl_logo",		IMAGEBITMAP, MacXCursorData(rtl_logo)},
    {"sailboat",		IMAGEBITMAP, MacXCursorData(sailboat)},
    {"sb_down_arrow",		IMAGEBITMAP, MacXCursorData(sb_down_arrow)},
    {"sb_h_double_arrow",	IMAGEBITMAP, MacXCursorData(sb_h_double_arrow)},
    {"sb_left_arrow",		IMAGEBITMAP, MacXCursorData(sb_left_arrow)},
    {"sb_right_arrow",		IMAGEBITMAP, MacXCursorData(sb_right_arrow)},
    {"sb_up_arrow",		IMAGEBITMAP, MacXCursorData(sb_up_arrow)},
    {"sb_v_double_arrow",	IMAGEBITMAP, MacXCursorData(sb_v_double_arrow)},
    {"shuttle",			IMAGEBITMAP, MacXCursorData(shuttle)},
    {"sizing",			IMAGEBITMAP, MacXCursorData(sizing)},
    {"spider",			IMAGEBITMAP, MacXCursorData(spider)},
    {"spraycan",		IMAGEBITMAP, MacXCursorData(spraycan)},
    {"star",			IMAGEBITMAP, MacXCursorData(star)},
    {"target",			IMAGEBITMAP, MacXCursorData(target)},
//  {"tcross",			IMAGEBITMAP, MacXCursorData(tcross)},
//  {"top_left_arrow",		IMAGEBITMAP, MacXCursorData(top_left_arrow)},
    {"top_left_corner",		IMAGEBITMAP, MacXCursorData(top_left_corner)},
    {"top_right_corner",	IMAGEBITMAP, MacXCursorData(top_right_corner)},
    {"top_side",		IMAGEBITMAP, MacXCursorData(top_side)},
    {"top_tee",			IMAGEBITMAP, MacXCursorData(top_tee)},
    {"trek",			IMAGEBITMAP, MacXCursorData(trek)},
    {"ul_angle",		IMAGEBITMAP, MacXCursorData(ul_angle)},
    {"umbrella",		IMAGEBITMAP, MacXCursorData(umbrella)},
    {"ur_angle",		IMAGEBITMAP, MacXCursorData(ur_angle)},
    {"watch",			IMAGEBITMAP, MacXCursorData(watch)},
//  {"xterm",			IMAGEBITMAP, MacXCursorData(xterm)},
    {NULL}
//  {"hand",			IMAGEBITMAP, MacCursorData(hand), nil, {0, 0}},
    {"bucket",			IMAGEBITMAP, MacCursorData(bucket), nil, {0, 0}},
    {"cancel",			IMAGEBITMAP, MacCursorData(cancel), nil, {0, 0}},
//  {"resize",			IMAGEBITMAP, MacCursorData(resize), nil, {0, 0}},
    {"eyedrop",			IMAGEBITMAP, MacCursorData(eyedrop), nil, {0, 0}},
    {"eyedrop-full",		IMAGEBITMAP, MacCursorData(eyedrop_full), nil, {0, 0}},
    {"zoom-in",			IMAGEBITMAP, MacCursorData(zoom_in), nil, {0, 0}},
    {"zoom-out",		IMAGEBITMAP, MacCursorData(zoom_out), nil, {0, 0}},
    {"X_cursor",		IMAGEBITMAP, MacXCursorData(X_cursor), nil, {0, 0}},
//  {"arrow",			IMAGEBITMAP, MacXCursorData(arrow), nil, {0, 0}},
    {"based_arrow_down",	IMAGEBITMAP, MacXCursorData(based_arrow_down), nil, {0, 0}},
    {"based_arrow_up",		IMAGEBITMAP, MacXCursorData(based_arrow_up), nil, {0, 0}},
    {"boat",			IMAGEBITMAP, MacXCursorData(boat), nil, {0, 0}},
    {"bogosity",		IMAGEBITMAP, MacXCursorData(bogosity), nil, {0, 0}},
    {"bottom_left_corner",	IMAGEBITMAP, MacXCursorData(bottom_left_corner), nil, {0, 0}},
    {"bottom_right_corner",	IMAGEBITMAP, MacXCursorData(bottom_right_corner), nil, {0, 0}},
    {"bottom_side",		IMAGEBITMAP, MacXCursorData(bottom_side), nil, {0, 0}},
    {"bottom_tee",		IMAGEBITMAP, MacXCursorData(bottom_tee), nil, {0, 0}},
    {"box_spiral",		IMAGEBITMAP, MacXCursorData(box_spiral), nil, {0, 0}},
    {"center_ptr",		IMAGEBITMAP, MacXCursorData(center_ptr), nil, {0, 0}},
    {"circle",			IMAGEBITMAP, MacXCursorData(circle), nil, {0, 0}},
    {"clock",			IMAGEBITMAP, MacXCursorData(clock), nil, {0, 0}},
    {"coffee_mug",		IMAGEBITMAP, MacXCursorData(coffee_mug), nil, {0, 0}},
//  {"cross",			IMAGEBITMAP, MacXCursorData(cross), nil, {0, 0}},
    {"cross_reverse",		IMAGEBITMAP, MacXCursorData(cross_reverse), nil, {0, 0}},
//  {"crosshair",		IMAGEBITMAP, MacXCursorData(crosshair), nil, {0, 0}},
    {"diamond_cross",		IMAGEBITMAP, MacXCursorData(diamond_cross), nil, {0, 0}},
    {"dot",			IMAGEBITMAP, MacXCursorData(dot), nil, {0, 0}},
    {"dotbox",			IMAGEBITMAP, MacXCursorData(dotbox), nil, {0, 0}},
    {"double_arrow",		IMAGEBITMAP, MacXCursorData(double_arrow), nil, {0, 0}},
    {"draft_large",		IMAGEBITMAP, MacXCursorData(draft_large), nil, {0, 0}},
    {"draft_small",		IMAGEBITMAP, MacXCursorData(draft_small), nil, {0, 0}},
    {"draped_box",		IMAGEBITMAP, MacXCursorData(draped_box), nil, {0, 0}},
    {"exchange",		IMAGEBITMAP, MacXCursorData(exchange), nil, {0, 0}},
    {"fleur",			IMAGEBITMAP, MacXCursorData(fleur), nil, {0, 0}},
    {"gobbler",			IMAGEBITMAP, MacXCursorData(gobbler), nil, {0, 0}},
    {"gumby",			IMAGEBITMAP, MacXCursorData(gumby), nil, {0, 0}},
    {"hand1",			IMAGEBITMAP, MacXCursorData(hand1), nil, {0, 0}},
    {"hand2",			IMAGEBITMAP, MacXCursorData(hand2), nil, {0, 0}},
    {"heart",			IMAGEBITMAP, MacXCursorData(heart), nil, {0, 0}},
    {"icon",			IMAGEBITMAP, MacXCursorData(icon), nil, {0, 0}},
    {"iron_cross",		IMAGEBITMAP, MacXCursorData(iron_cross), nil, {0, 0}},
//  {"left_ptr",		IMAGEBITMAP, MacXCursorData(left_ptr), nil, {0, 0}},
    {"left_side",		IMAGEBITMAP, MacXCursorData(left_side), nil, {0, 0}},
    {"left_tee",		IMAGEBITMAP, MacXCursorData(left_tee), nil, {0, 0}},
    {"leftbutton",		IMAGEBITMAP, MacXCursorData(leftbutton), nil, {0, 0}},
    {"ll_angle",		IMAGEBITMAP, MacXCursorData(ll_angle), nil, {0, 0}},
    {"lr_angle",		IMAGEBITMAP, MacXCursorData(lr_angle), nil, {0, 0}},
    {"man",			IMAGEBITMAP, MacXCursorData(man), nil, {0, 0}},
    {"middlebutton",		IMAGEBITMAP, MacXCursorData(middlebutton), nil, {0, 0}},
    {"mouse",			IMAGEBITMAP, MacXCursorData(mouse), nil, {0, 0}},
    {"pencil",			IMAGEBITMAP, MacXCursorData(pencil), nil, {0, 0}},
    {"pirate",			IMAGEBITMAP, MacXCursorData(pirate), nil, {0, 0}},
    {"plus",			IMAGEBITMAP, MacXCursorData(plus), nil, {0, 0}},
    {"question_arrow",		IMAGEBITMAP, MacXCursorData(question_arrow), nil, {0, 0}},
    {"right_ptr",		IMAGEBITMAP, MacXCursorData(right_ptr), nil, {0, 0}},
    {"right_side",		IMAGEBITMAP, MacXCursorData(right_side), nil, {0, 0}},
    {"right_tee",		IMAGEBITMAP, MacXCursorData(right_tee), nil, {0, 0}},
    {"rightbutton",		IMAGEBITMAP, MacXCursorData(rightbutton), nil, {0, 0}},
    {"rtl_logo",		IMAGEBITMAP, MacXCursorData(rtl_logo), nil, {0, 0}},
    {"sailboat",		IMAGEBITMAP, MacXCursorData(sailboat), nil, {0, 0}},
    {"sb_down_arrow",		IMAGEBITMAP, MacXCursorData(sb_down_arrow), nil, {0, 0}},
    {"sb_h_double_arrow",	IMAGEBITMAP, MacXCursorData(sb_h_double_arrow), nil, {0, 0}},
    {"sb_left_arrow",		IMAGEBITMAP, MacXCursorData(sb_left_arrow), nil, {0, 0}},
    {"sb_right_arrow",		IMAGEBITMAP, MacXCursorData(sb_right_arrow), nil, {0, 0}},
    {"sb_up_arrow",		IMAGEBITMAP, MacXCursorData(sb_up_arrow), nil, {0, 0}},
    {"sb_v_double_arrow",	IMAGEBITMAP, MacXCursorData(sb_v_double_arrow), nil, {0, 0}},
    {"shuttle",			IMAGEBITMAP, MacXCursorData(shuttle), nil, {0, 0}},
    {"sizing",			IMAGEBITMAP, MacXCursorData(sizing), nil, {0, 0}},
    {"spider",			IMAGEBITMAP, MacXCursorData(spider), nil, {0, 0}},
    {"spraycan",		IMAGEBITMAP, MacXCursorData(spraycan), nil, {0, 0}},
    {"star",			IMAGEBITMAP, MacXCursorData(star), nil, {0, 0}},
    {"target",			IMAGEBITMAP, MacXCursorData(target), nil, {0, 0}},
//  {"tcross",			IMAGEBITMAP, MacXCursorData(tcross), nil, {0, 0}},
//  {"top_left_arrow",		IMAGEBITMAP, MacXCursorData(top_left_arrow), nil, {0, 0}},
    {"top_left_corner",		IMAGEBITMAP, MacXCursorData(top_left_corner), nil, {0, 0}},
    {"top_right_corner",	IMAGEBITMAP, MacXCursorData(top_right_corner), nil, {0, 0}},
    {"top_side",		IMAGEBITMAP, MacXCursorData(top_side), nil, {0, 0}},
    {"top_tee",			IMAGEBITMAP, MacXCursorData(top_tee), nil, {0, 0}},
    {"trek",			IMAGEBITMAP, MacXCursorData(trek), nil, {0, 0}},
    {"ul_angle",		IMAGEBITMAP, MacXCursorData(ul_angle), nil, {0, 0}},
    {"umbrella",		IMAGEBITMAP, MacXCursorData(umbrella), nil, {0, 0}},
    {"ur_angle",		IMAGEBITMAP, MacXCursorData(ur_angle), nil, {0, 0}},
    {"watch",			IMAGEBITMAP, MacXCursorData(watch), nil, {0, 0}},
//  {"xterm",			IMAGEBITMAP, MacXCursorData(xterm), nil, {0, 0}},
    {NULL, 0, nil, nil, {0, 0}}
};

/*
 * Declarations of static variables used in this file.
 */

static TkMacOSXCursor *gCurrentCursor = NULL;
				/* A pointer to the current cursor. */
static int gResizeOverride = false;
				/* A boolean indicating whether we should use
				 * the resize cursor during installations. */
static int gTkOwnsCursor = true;/* A boolean indicating whether Tk owns the
				 * cursor. If not (for instance, in the case
				 * where a Tk window is embedded in another
				 * app's window, and the cursor is out of the
				 * Tk window, we will not attempt to adjust
				 * the cursor. */

/*
 * Declarations of procedures local to this file
 */

static void FindCursorByName(TkMacOSXCursor *macCursorPtr, const char *string);

267
268
269
270
271
272
273
274

275
276
277
278
279
280
281
258
259
260
261
262
263
264

265
266
267
268
269
270
271
272







-
+







		haveHotSpot = 1;
		break;
	    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,
			bitmap, pix*pix/8, NULL);

371
372
373
374
375
376
377
378

379
380
381
382
383
384
385
386
387
388
389
390
391
392
393

394
395
396
397
398
399
400
362
363
364
365
366
367
368

369
370
371
372
373
374
375
376
377
378
379
380
381
382
383

384
385
386
387
388
389
390
391







-
+














-
+







 *
 *----------------------------------------------------------------------
 */

TkCursor *
TkGetCursorByName(
    Tcl_Interp *interp,		/* Interpreter to use for error reporting. */
    Tk_Window tkwin,		/* Window in which cursor will be used. */
    TCL_UNUSED(Tk_Window),		/* Window in which cursor will be used. */
    Tk_Uid string)		/* Description of cursor. See manual entry
				 * for details on legal syntax. */
{
    TkMacOSXCursor *macCursorPtr = NULL;
    const char **argv = NULL;
    int argc;

    /*
     * All cursor names are valid lists of one element (for
     * TkX11-compatibility), even unadorned system cursor names.
     */

    if (Tcl_SplitList(interp, string, &argc, &argv) == TCL_OK) {
	if (argc) {
	    macCursorPtr = ckalloc(sizeof(TkMacOSXCursor));
	    macCursorPtr = (TkMacOSXCursor *)ckalloc(sizeof(TkMacOSXCursor));
	    macCursorPtr->info.cursor = (Tk_Cursor) macCursorPtr;
	    macCursorPtr->macCursor = nil;
	    macCursorPtr->type = 0;
	    FindCursorByName(macCursorPtr, argv[0]);
	}
	ckfree(argv);
    }
425
426
427
428
429
430
431
432
433
434
435
436
437
438









439
440
441
442
443
444
445
416
417
418
419
420
421
422







423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438







-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+







 *	Allocates a new cursor.
 *
 *----------------------------------------------------------------------
 */

TkCursor *
TkCreateCursorFromData(
    Tk_Window tkwin,		/* Window in which cursor will be used. */
    const char *source,		/* Bitmap data for cursor shape. */
    const char *mask,		/* Bitmap data for cursor mask. */
    int width, int height,	/* Dimensions of cursor. */
    int xHot, int yHot,		/* Location of hot-spot in cursor. */
    XColor fgColor,		/* Foreground color for cursor. */
    XColor bgColor)		/* Background color for cursor. */
    TCL_UNUSED(Tk_Window),		/* Window in which cursor will be used. */
    TCL_UNUSED(const char *),		/* Bitmap data for cursor shape. */
    TCL_UNUSED(const char *),		/* Bitmap data for cursor mask. */
    TCL_UNUSED(int),	/* Dimensions of cursor. */
    TCL_UNUSED(int),
    TCL_UNUSED(int),		/* Location of hot-spot in cursor. */
    TCL_UNUSED(int),
    TCL_UNUSED(XColor),		/* Foreground color for cursor. */
    TCL_UNUSED(XColor))		/* Background color for cursor. */
{
    return NULL;
}

/*
 *----------------------------------------------------------------------
 *
460
461
462
463
464
465
466
467

468
469
470
471
472
473
474
453
454
455
456
457
458
459

460
461
462
463
464
465
466
467







-
+







void
TkpFreeCursor(
    TkCursor *cursorPtr)
{
    TkMacOSXCursor *macCursorPtr = (TkMacOSXCursor *) cursorPtr;

    [macCursorPtr->macCursor release];
    macCursorPtr->macCursor = NULL;
    macCursorPtr->macCursor = nil;
    if (macCursorPtr == gCurrentCursor) {
	gCurrentCursor = NULL;
    }
}

/*
 *----------------------------------------------------------------------
483
484
485
486
487
488
489
490

491
492

493
494
495
496
497
498
499
500

501
502
503
504
505
506
507
476
477
478
479
480
481
482

483
484

485
486
487
488
489
490



491
492
493
494
495
496
497
498







-
+

-
+





-
-
-
+







 *
 * Side effects:
 *	Changes the Macintosh mouse cursor.
 *
 *----------------------------------------------------------------------
 */

void
static void
TkMacOSXInstallCursor(
    int resizeOverride)
    void)
{
    TkMacOSXCursor *macCursorPtr = gCurrentCursor;
    static int cursorHidden = 0;
    int cursorNone = 0;

    gResizeOverride = resizeOverride;

    if (resizeOverride || !macCursorPtr) {
    if (!macCursorPtr) {
	[[NSCursor arrowCursor] set];
    } else {
	switch (macCursorPtr->type) {
	case NONE:
	    if (!cursorHidden) {
		cursorHidden = 1;
		[NSCursor hide];
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570

571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
532
533
534
535
536
537
538




539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556

557
558























559
560
561
562
563
564
565
566
567
568







-
-
-
-


















-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-











void
TkpSetCursor(
    TkpCursor cursor)
{
    int cursorChanged = 1;

    if (!gTkOwnsCursor) {
	return;
    }

    if (cursor == None) {
	/*
	 * 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
	 * logic.
	 */

	gCurrentCursor = NULL;
    } else {
	if (gCurrentCursor == (TkMacOSXCursor *) cursor) {
	    cursorChanged = 0;
	}
	gCurrentCursor = (TkMacOSXCursor *) cursor;
    }

    if (Tk_MacOSXIsAppInFront() && cursorChanged) {
	TkMacOSXInstallCursor(gResizeOverride);
	TkMacOSXInstallCursor();
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tk_MacOSXTkOwnsCursor --
 *
 *	Sets whether Tk has the right to adjust the cursor.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	May keep Tk from changing the cursor.
 *
 *----------------------------------------------------------------------
 */

void
Tk_MacOSXTkOwnsCursor(
    int tkOwnsIt)
{
    gTkOwnsCursor = tkOwnsIt;
}

/*
 * Local Variables:
 * mode: objc
 * c-basic-offset: 4
 * fill-column: 79
 * coding: utf-8
 * End:
 */
Changes to macosx/tkMacOSXCursors.h.
1
2
3
4
5
6
7
8
9



10
11
12
13
14
15
16
1
2
3
4
5
6



7
8
9
10
11
12
13
14
15
16






-
-
-
+
+
+







/*
 * 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 <[email protected]>
 * Copyright © 1995-1996 Sun Microsystems, Inc.
 * Copyright © 2008-2009 Apple Inc.
 * Copyright © 2008-2009 Daniel A. Steffen <[email protected]>
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

static const unsigned char tkMacOSXCursors[][68] = {

Changes to macosx/tkMacOSXDebug.c.
1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15






-
-
+
+







/*
 * 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 <[email protected]>
 * Copyright © 2001-2009, Apple Inc.
 * Copyright © 2006-2009 Daniel A. Steffen <[email protected]>
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tkMacOSXPrivate.h"
#include "tkMacOSXDebug.h"
Changes to macosx/tkMacOSXDebug.h.
1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15






-
-
+
+







/*
 * 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 <[email protected]>
 * Copyright © 2001-2009, Apple Inc.
 * Copyright © 2005-2009 Daniel A. Steffen <[email protected]>
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#ifndef _TKMACDEBUG
#define _TKMACDEBUG
Changes to macosx/tkMacOSXDefault.h.
38
39
40
41
42
43
44
45

46
47
48


49
50
51
52
53
54
55
38
39
40
41
42
43
44

45
46
47

48
49
50
51
52
53
54
55
56







-
+


-
+
+







#define NORMAL_BG		"systemWindowBackgroundColor"
#define TEXT_BG                 "systemTextBackgroundColor"
#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		"#a3a3a3"
#define DISABLED		"systemDisabledControlTextColor"
#define IGNORED                 "#abcdef"

/*
 * Defaults for labels, buttons, checkbuttons, and radiobuttons:
 */

#define DEF_BUTTON_ANCHOR		"center"
#define DEF_BUTTON_ACTIVE_BG_COLOR	ACTIVE_BG
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
85
86
87
88
89
90
91




92

93




94

95
96
97
98
99
100
101







-
-
-
-

-

-
-
-
-

-







#define DEF_BUTTON_IMAGE		NULL
#define DEF_BUTTON_INDICATOR		"1"
#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"
#define DEF_BUTTON_SELECT_COLOR		INDICATOR
#define DEF_BUTTON_SELECT_MONO		BLACK
188
189
190
191
192
193
194


195
196
197
198
199
200
201
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194







+
+







#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"
#define DEF_ENTRY_INSERT_ON_TIME	"600"
#define DEF_ENTRY_INSERT_WIDTH		"1"
#define DEF_ENTRY_JUSTIFY		"left"
#define DEF_ENTRY_PLACEHOLDER		""
#define DEF_ENTRY_PLACEHOLDERFG		"systemPlaceholderTextColor"
#define DEF_ENTRY_READONLY_BG_COLOR	NORMAL_BG
#define DEF_ENTRY_READONLY_BG_MONO	WHITE
#define DEF_ENTRY_RELIEF		"sunken"
#define DEF_ENTRY_SCROLL_COMMAND	""
#define DEF_ENTRY_SELECT_COLOR		SELECT_BG
#define DEF_ENTRY_SELECT_MONO		BLACK
#define DEF_ENTRY_SELECT_BD_COLOR	"1"
209
210
211
212
213
214
215

216

217
218
219
220
221
222
223
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218







+

+







#define DEF_ENTRY_WIDTH			"20"

/*
 * Defaults for frames:
 */

#define DEF_FRAME_BG_COLOR		NORMAL_BG
#define DEF_FRAME_BG_IMAGE		NULL
#define DEF_FRAME_BG_MONO		WHITE
#define DEF_FRAME_BG_TILE		"0"
#define DEF_FRAME_BORDER_WIDTH		"0"
#define DEF_FRAME_CLASS			"Frame"
#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
303
304
305
306
307
308
309
310
311


312
313
314
315
316





317
318
319

320
321
322

323
324
325
326


327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343






344
345
346
347
348
349
350
351
352
353
354
355

356
357
358
359
360
361
362
298
299
300
301
302
303
304


305
306
307




308
309
310
311
312
313
314

315
316
317

318
319
320


321
322
323
324
325
326
327
328
329
330
331
332
333






334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350

351
352
353
354
355
356
357
358







-
-
+
+

-
-
-
-
+
+
+
+
+


-
+


-
+


-
-
+
+











-
-
-
-
-
-
+
+
+
+
+
+











-
+







#define DEF_MENU_ENTRY_SELECT		NULL
#define DEF_MENU_ENTRY_UNDERLINE	"-1"

/*
 * Defaults for menus overall:
 */

#define DEF_MENU_ACTIVE_BG_COLOR	"systemMenuActive"
#define DEF_MENU_ACTIVE_BG_MONO		BLACK
#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	"systemMenuActiveText"
#define DEF_MENU_ACTIVE_FG_MONO		WHITE
#define DEF_MENU_BG_COLOR		"systemMenu"
#define DEF_MENU_BG_MONO		WHITE
#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		"#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	"systemMenuDisabled"
#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			"systemMenuText"
#define DEF_MENU_FG			"#010000"  /* Detects custom fg. */
#define DEF_MENU_POST_COMMAND		""
#define DEF_MENU_RELIEF			"flat"
#define DEF_MENU_SELECT_COLOR		"systemMenuActive"
#define DEF_MENU_SELECT_MONO		BLACK
#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"

/*
 * Defaults for menubuttons:
 */

#define DEF_MENUBUTTON_ANCHOR		"w"
#define DEF_MENUBUTTON_ACTIVE_BG_COLOR	ACTIVE_BG
#define DEF_MENUBUTTON_ACTIVE_BG_MONO	WHITE
#define DEF_MENUBUTTON_ACTIVE_FG_COLOR	ACTIVE_FG
#define DEF_MENUBUTTON_ACTIVE_FG_MONO	BLACK
#define DEF_MENUBUTTON_BG_COLOR		NORMAL_BG
#define DEF_MENUBUTTON_BG_MONO		WHITE
#define DEF_MENUBUTTON_ACTIVE_BG_COLOR	NORMAL_BG /*ignored*/
#define DEF_MENUBUTTON_ACTIVE_BG_MONO	NORMAL_BG /*ignored*/
#define DEF_MENUBUTTON_ACTIVE_FG_COLOR	"systemTextColor"
#define DEF_MENUBUTTON_ACTIVE_FG_MONO	"systemTextColor"
#define DEF_MENUBUTTON_BG_COLOR		NORMAL_BG /*ignored*/
#define DEF_MENUBUTTON_BG_MONO		NORMAL_BG /*ignored*/
#define DEF_MENUBUTTON_BITMAP		""
#define DEF_MENUBUTTON_BORDER_WIDTH	"0"
#define DEF_MENUBUTTON_CURSOR		""
#define DEF_MENUBUTTON_DIRECTION	"below"
#define DEF_MENUBUTTON_DISABLED_FG_COLOR DISABLED
#define DEF_MENUBUTTON_DISABLED_FG_MONO	""
#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	BLACK
#define DEF_MENUBUTTON_HIGHLIGHT	NORMAL_BG
#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		""
#define DEF_MENUBUTTON_PADX		"0"
#define DEF_MENUBUTTON_PADY		"0"
Changes to macosx/tkMacOSXDialog.c.
1
2
3
4
5
6
7
8
9




10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

27
28
29
30
31
32
33
1
2
3
4
5




6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

26
27
28
29
30
31
32
33





-
-
-
-
+
+
+
+
















-
+







/*
 * 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 <[email protected]>
 * Copyright (c) 2017 Christian Gollwitzer.
 * Copyright © 1996-1997 Sun Microsystems, Inc.
 * Copyright © 2001-2009 Apple Inc.
 * Copyright © 2006-2009 Daniel A. Steffen <[email protected]>
 * 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.
 */

#include "tkMacOSXPrivate.h"
#include "tkFileFilter.h"
#include "tkMacOSXConstants.h"

#if MAC_OS_X_VERSION_MIN_REQUIRED < 1090
#define modalOK     NSOKButton
#define modalCancel NSCancelButton
#else
#define modalOK     NSModalResponseOK
#define modalCancel NSModalResponseCancel
#endif // MAC_OS_X_VERSION_MIN_REQUIRED < 1090
#define modalOther  -1
#define modalOther  -1 // indicates that the -command option was used.
#define modalError  -2

/*
 * Vars for filtering in "open file" and "save file" dialogs.
 */

typedef struct {
48
49
50
51
52
53
54




55
56
57
58
59
60
61
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65







+
+
+
+







    NSMutableArray *allowedExtensions;	/* Set of all allowed extensions. */
    bool allowedExtensionsAllowAll;	/* Set of all allowed extensions
					 * includes *.* */
    NSUInteger fileTypeIndex;		/* Index of currently selected
					 * filter. */
} filepanelFilterInfo;

/*
 * Only one of these is needed for the application, so they can be static.
 */

static filepanelFilterInfo filterInfo;
static NSOpenPanel *openpanel;
static NSSavePanel *savepanel;

static const char *const colorOptionStrings[] = {
    "-initialcolor", "-parent", "-title", NULL
};
194
195
196
197
198
199
200


201
202
203
204

205
206
207

208
209
210
211
212

213

214
215
216
217
218
219
220
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221

222
223
224
225
226
227
228
229







+
+




+



+





+
-
+







}

#pragma mark TKApplication(TKDialog)

@implementation TKApplication(TKDialog)

- (BOOL)panel:(id)sender shouldEnableURL:(NSURL *)url {
	(void)sender;
	(void)url;
    return YES;
}

- (void)panel:(id)sender didChangeToDirectoryURL:(NSURL *)url {
    (void)sender; (void)url;
}

- (BOOL)panel:(id)sender validateURL:(NSURL *)url error:(NSError **)outError {
    (void)sender; (void)url;
    *outError = nil;
    return YES;
}

- (void) tkFilePanelDidEnd: (NSSavePanel *) panel
		returnCode: (NSModalResponse) returnCode
	returnCode: (NSInteger) returnCode contextInfo: (void *) contextInfo
	       contextInfo: (void *) contextInfo
{
    FilePanelCallbackInfo *callbackInfo = contextInfo;

    if (returnCode == modalOK) {
	Tcl_Obj *resultObj;

	if (callbackInfo->multiple) {
228
229
230
231
232
233
234
235

236
237
238
239
240
241
242
243
244
245
246
247
248
249


250
251

252
253
254

255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273

274
275
276
277
278
279
280
237
238
239
240
241
242
243

244
245
246
247
248
249
250
251
252
253
254
255
256


257
258
259

260

261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281

282
283
284
285
286
287
288
289







-
+












-
-
+
+

-
+
-


+


















-
+







	}
	if (callbackInfo->cmdObj) {
	    Tcl_Obj **objv, **tmpv;
	    int objc, result = Tcl_ListObjGetElements(callbackInfo->interp,
		    callbackInfo->cmdObj, &objc, &objv);

	    if (result == TCL_OK && objc) {
		tmpv = ckalloc(sizeof(Tcl_Obj *) * (objc + 2));
		tmpv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj *) * (objc + 2));
		memcpy(tmpv, objv, sizeof(Tcl_Obj *) * objc);
		tmpv[objc] = resultObj;
		TkBackgroundEvalObjv(callbackInfo->interp, objc + 1, tmpv,
			TCL_EVAL_GLOBAL);
		ckfree(tmpv);
	    }
	} else {
	    Tcl_SetObjResult(callbackInfo->interp, resultObj);
	}
    } else if (returnCode == modalCancel) {
	Tcl_ResetResult(callbackInfo->interp);
    }
    if (panel == [NSApp modalWindow]) {
	[NSApp stopModalWithCode:returnCode];
    if (callbackInfo->cmdObj) {
	Tcl_DecrRefCount(callbackInfo->cmdObj);
    }
    if (callbackInfo->cmdObj) {
    if (callbackInfo) {
	Tcl_DecrRefCount(callbackInfo->cmdObj);
	ckfree(callbackInfo);
    }
    [NSApp stopModalWithCode:returnCode];
}

- (void) tkAlertDidEnd: (NSAlert *) alert returnCode: (NSInteger) returnCode
	contextInfo: (void *) contextInfo
{
    AlertCallbackInfo *callbackInfo = contextInfo;

    if (returnCode >= NSAlertFirstButtonReturn) {
	Tcl_Obj *resultObj = Tcl_NewStringObj(alertButtonStrings[
		alertNativeButtonIndexAndTypeToButtonIndex[callbackInfo->
		typeIndex][returnCode - NSAlertFirstButtonReturn]], -1);

	if (callbackInfo->cmdObj) {
	    Tcl_Obj **objv, **tmpv;
	    int objc, result = Tcl_ListObjGetElements(callbackInfo->interp,
		    callbackInfo->cmdObj, &objc, &objv);

	    if (result == TCL_OK && objc) {
		tmpv = ckalloc(sizeof(Tcl_Obj *) * (objc + 2));
		tmpv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj *) * (objc + 2));
		memcpy(tmpv, objv, sizeof(Tcl_Obj *) * objc);
		tmpv[objc] = resultObj;
		TkBackgroundEvalObjv(callbackInfo->interp, objc + 1, tmpv,
			TCL_EVAL_GLOBAL);
		ckfree(tmpv);
	    }
	} else {
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
298
299
300
301
302
303
304

305
306
307
308
309
310
311







-







	ckfree(callbackInfo);
    }
}

- (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
	 * the NSSavePanel, where it has the effect that it does not append an
	 * extension. Setting the allowed file types to nil allows selecting
339
340
341
342
343
344
345
346

347
348

349
350
351
352










353
354




355












356
357
358
359
360










361
362
363
364
365
366
367
347
348
349
350
351
352
353

354
355

356
357
358
359
360
361
362
363
364
365
366
367
368
369
370


371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387





388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404







-
+

-
+




+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+







static NSInteger showOpenSavePanel(
    NSSavePanel *panel,
    NSWindow *parent,
    FilePanelCallbackInfo *callbackInfo)
{
    NSInteger modalReturnCode;

    if (parent && ![parent attachedSheet] && [NSApp macMinorVersion] < 15) {
    if (parent && ![parent attachedSheet]) {
	[panel beginSheetModalForWindow:parent
	       completionHandler:^(NSInteger returnCode) {
	       completionHandler:^(NSModalResponse returnCode) {
	    [NSApp tkFilePanelDidEnd:panel
		       returnCode:returnCode
		       contextInfo:callbackInfo ];
	    }];

	/*
	 * 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.
	 */

	if ([NSApp macOSVersion] > 101400) {
	modalReturnCode = callbackInfo->cmdObj ? modalOther :
	    [NSApp runModalForWindow:panel];
	    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) {
	    [panel beginWithCompletionHandler:^(NSModalResponse returnCode) {
		    [NSApp tkFilePanelDidEnd:panel
			          returnCode:returnCode
			         contextInfo:callbackInfo ];
	    }];
	modalReturnCode = [panel runModal];
	[NSApp tkFilePanelDidEnd:panel returnCode:modalReturnCode
		     contextInfo:callbackInfo];
    }
    return modalReturnCode;
	    modalReturnCode = [panel runModal];
	} else {
	    modalReturnCode = [panel runModal];
	    [NSApp tkFilePanelDidEnd:panel
		   	  returnCode:modalReturnCode
		         contextInfo:callbackInfo ];
	    [panel close];
	}
    }
    return callbackInfo->cmdObj ? modalOther : modalReturnCode;
}

/*
 *----------------------------------------------------------------------
 *
 * Tk_ChooseColorObjCmd --
 *
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
687
688
689
690
691
692
693


694
695
696
697
698
699
700







-
-







    NSString *directory = nil, *filename = nil;
    NSString *message = nil, *title = nil;
    NSWindow *parent;
    openpanel =  [NSOpenPanel openPanel];
    NSInteger modalReturnCode = modalError;
    BOOL parentIsKey = NO;

    [openpanel setDelegate:NSApp];

    for (i = 1; i < objc; i += 2) {
	if (Tcl_GetIndexFromObjStruct(interp, objv[i], openOptionStrings,
		sizeof(char *), "option", TCL_EXACT, &index) != TCL_OK) {
	    goto end;
	}
	if (i + 1 == objc) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
721
722
723
724
725
726
727
728

729
730
731
732
733
734
735
756
757
758
759
760
761
762

763
764
765
766
767
768
769
770







-
+







	[openpanel setTitle:title];

	/*
	 * From OSX 10.11, the title string is silently ignored in the open
	 * panel.  Prepend the title to the message in this case.
	 */

	if ([NSApp macMinorVersion] > 10) {
	if ([NSApp macOSVersion] > 101000) {
	    if (message) {
		NSString *fullmessage =
		    [[NSString alloc] initWithFormat:@"%@\n%@", title, message];
		[message release];
		[title release];
		message = fullmessage;
	    } else {
759
760
761
762
763
764
765

766
767
768
769
770
771
772
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808







+








	[label setEditable:NO];
	[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) {

	    /*
	     * A specific filter was selected from the typevariable. Select it
800
801
802
803
804
805
806
807

808
809
810
811
812
813
814
815
816
817

818
819
820
821
822
823
824
836
837
838
839
840
841
842

843
844
845
846
847
848
849
850
851
852

853
854
855
856
857
858
859
860







-
+









-
+







    }
    if (cmdObj) {
	if (Tcl_IsShared(cmdObj)) {
	    cmdObj = Tcl_DuplicateObj(cmdObj);
	}
	Tcl_IncrRefCount(cmdObj);
    }
    callbackInfo = ckalloc(sizeof(FilePanelCallbackInfo));
    callbackInfo = (FilePanelCallbackInfo *)ckalloc(sizeof(FilePanelCallbackInfo));
    callbackInfo->cmdObj = cmdObj;
    callbackInfo->interp = interp;
    callbackInfo->multiple = multiple;
    if (directory || filename) {
	NSURL *fileURL = getFileURL(directory, filename);

	[openpanel setDirectoryURL:fileURL];
    }
    if (haveParentOption) {
	parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window);
	parent = TkMacOSXGetNSWindowForDrawable(((TkWindow *)tkwin)->window);
	parentIsKey = parent && [parent isKeyWindow];
    } else {
	parent = nil;
	parentIsKey = False;
    }
    modalReturnCode = showOpenSavePanel(openpanel, parent, callbackInfo);
    result = (modalReturnCode != modalError) ? TCL_OK : TCL_ERROR;
862
863
864
865
866
867
868
869

870
871
872
873



874
875
876
877

878
879
880
881
882
883
884
898
899
900
901
902
903
904

905
906



907
908
909
910
911
912

913
914
915
916
917
918
919
920







-
+

-
-
-
+
+
+



-
+







	    extension = [selectedFile pathExtension];

	    if (filterInfo.preselectFilter &&
		    filterCompatible(extension, filterInfo.fileTypeIndex)) {
		selectedFilterIndex = filterInfo.fileTypeIndex;  // The preselection from the typevariable
		selectedFilter = [filterInfo.fileTypeNames objectAtIndex:selectedFilterIndex];
	    } else {
		NSUInteger i;
		NSUInteger j;

		for (i = 0; i < [filterInfo.fileTypeNames count]; i++) {
		    if (filterCompatible(extension, i)) {
			selectedFilterIndex = i;
		for (j = 0; j < [filterInfo.fileTypeNames count]; j++) {
		    if (filterCompatible(extension, j)) {
			selectedFilterIndex = j;
			break;
		    }
		}
		if (i == selectedFilterIndex) {
		if (j == selectedFilterIndex) {
		    selectedFilter = [filterInfo.fileTypeNames objectAtIndex:selectedFilterIndex];
		} else {
		    selectedFilter = @"";
		}
	    }
	}
	Tcl_ObjSetVar2(interp, typeVariablePtr, NULL,
909
910
911
912
913
914
915
916

917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
945
946
947
948
949
950
951

952
953
954
955
956
957
958
959
960
961
962
963
964
965
966


967
968
969
970
971
972
973







-
+














-
-







int
Tk_GetSaveFileObjCmd(
    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 confirmOverwrite = 1;
    int index, len;
    Tcl_Obj *cmdObj = NULL, *typeVariablePtr = NULL, *fileTypesPtr = NULL;
    FilePanelCallbackInfo callbackInfoStruct;
    FilePanelCallbackInfo *callbackInfo = &callbackInfoStruct;
    NSString *directory = nil, *filename = nil, *defaultType = nil;
    NSString *message = nil, *title = nil;
    NSWindow *parent;
    savepanel = [NSSavePanel savePanel];
    NSInteger modalReturnCode = modalError;
    BOOL parentIsKey = NO;

    [savepanel setDelegate:NSApp];

    for (i = 1; i < objc; i += 2) {
	if (Tcl_GetIndexFromObjStruct(interp, objv[i], saveOptionStrings,
		sizeof(char *), "option", TCL_EXACT, &index) != TCL_OK) {
	    goto end;
	}
	if (i + 1 == objc) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
1046
1047
1048
1049
1050
1051
1052

1053
1054
1055
1056
1057
1058
1059
1060
1061
1080
1081
1082
1083
1084
1085
1086
1087
1088

1089
1090
1091
1092
1093
1094
1095







+

-







	[label setDrawsBackground:NO];

	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];

	[savepanel setAllowedFileTypes:[filterInfo.fileTypeExtensions objectAtIndex:filterInfo.fileTypeIndex]];
	[savepanel setAllowsOtherFileTypes:filterInfo.allowedExtensionsAllowAll];
1078
1079
1080
1081
1082
1083
1084
1085

1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105

1106
1107
1108
1109
1110
1111
1112
1112
1113
1114
1115
1116
1117
1118

1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138

1139
1140
1141
1142
1143
1144
1145
1146







-
+



















-
+








    if (cmdObj) {
	if (Tcl_IsShared(cmdObj)) {
	    cmdObj = Tcl_DuplicateObj(cmdObj);
	}
	Tcl_IncrRefCount(cmdObj);
    }
    callbackInfo = ckalloc(sizeof(FilePanelCallbackInfo));
    callbackInfo = (FilePanelCallbackInfo *)ckalloc(sizeof(FilePanelCallbackInfo));
    callbackInfo->cmdObj = cmdObj;
    callbackInfo->interp = interp;
    callbackInfo->multiple = 0;

    if (directory) {
	[savepanel setDirectoryURL:[NSURL fileURLWithPath:directory isDirectory:YES]];
    }

    /*
     * Check for file name and set to the empty string if nil. This prevents a crash
     * with an uncaught exception.
     */

    if (filename) {
	[savepanel setNameFieldStringValue:filename];
    } else {
	[savepanel setNameFieldStringValue:@""];
    }
    if (haveParentOption) {
	parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window);
	parent = TkMacOSXGetNSWindowForDrawable(((TkWindow *)tkwin)->window);
	parentIsKey = parent && [parent isKeyWindow];
    } else {
	parent = nil;
	parentIsKey = False;
    }
    modalReturnCode = showOpenSavePanel(savepanel, parent, callbackInfo);
    result = (modalReturnCode != modalError) ? TCL_OK : TCL_ERROR;
1153
1154
1155
1156
1157
1158
1159
1160

1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1187
1188
1189
1190
1191
1192
1193

1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207


1208
1209
1210
1211
1212
1213
1214







-
+













-
-







int
Tk_ChooseDirectoryObjCmd(
    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, mustexist = 0;
    Tcl_Obj *cmdObj = NULL;
    FilePanelCallbackInfo callbackInfoStruct;
    FilePanelCallbackInfo *callbackInfo = &callbackInfoStruct;
    NSString *directory = nil;
    NSString *message, *title;
    NSWindow *parent;
    NSOpenPanel *panel = [NSOpenPanel openPanel];
    NSInteger modalReturnCode = modalError;
    BOOL parentIsKey = NO;

    [panel setDelegate:NSApp];

    for (i = 1; i < objc; i += 2) {
	if (Tcl_GetIndexFromObjStruct(interp, objv[i], chooseOptionStrings,
		sizeof(char *), "option", TCL_EXACT, &index) != TCL_OK) {
	    goto end;
	}
	if (i + 1 == objc) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
1229
1230
1231
1232
1233
1234
1235
1236

1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249

1250
1251
1252

1253
1254
1255
1256
1257
1258
1259
1261
1262
1263
1264
1265
1266
1267

1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280

1281
1282
1283

1284
1285
1286
1287
1288
1289
1290
1291







-
+












-
+


-
+







    [panel setCanCreateDirectories:!mustexist];
    if (cmdObj) {
	if (Tcl_IsShared(cmdObj)) {
	    cmdObj = Tcl_DuplicateObj(cmdObj);
	}
	Tcl_IncrRefCount(cmdObj);
    }
    callbackInfo = ckalloc(sizeof(FilePanelCallbackInfo));
    callbackInfo = (FilePanelCallbackInfo *)ckalloc(sizeof(FilePanelCallbackInfo));
    callbackInfo->cmdObj = cmdObj;
    callbackInfo->interp = interp;
    callbackInfo->multiple = 0;

    /*
     * Check for directory value, set to root if not specified; otherwise
     * crashes with exception because of nil string parameter.
     */

    if (!directory) {
	directory = @"/";
    }
    parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window);
    parent = TkMacOSXGetNSWindowForDrawable(((TkWindow *)tkwin)->window);
    [panel setDirectoryURL:[NSURL fileURLWithPath:directory isDirectory:YES]];
    if (haveParentOption) {
	parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window);
	parent = TkMacOSXGetNSWindowForDrawable(((TkWindow *)tkwin)->window);
	parentIsKey = parent && [parent isKeyWindow];
    } else {
	parent = nil;
	parentIsKey = False;
    }
    modalReturnCode = showOpenSavePanel(panel, parent, callbackInfo);
    result = (modalReturnCode != modalError) ? TCL_OK : TCL_ERROR;
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288

1289
1290
1291
1292
1293

1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362

1363
1364
1365
1366
1367
1368
1369
1370
1371

1372
1373
1374
1375
1376
1377
1378
1311
1312
1313
1314
1315
1316
1317



1318





1319
1320

















































1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338

1339
1340
1341
1342
1343
1344
1345
1346
1347

1348
1349
1350
1351
1352
1353
1354
1355







-
-
-
+
-
-
-
-
-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-


















-
+








-
+







 *
 *----------------------------------------------------------------------
 */

void
TkAboutDlg(void)
{
    NSImage *image;
    NSString *path = [NSApp tkFrameworkImagePath: @"Tk.tiff"];

    [NSApp orderFrontStandardAboutPanel:nil];
    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];
}

/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXStandardAboutPanelObjCmd --
 *
 *	Implements the ::tk::mac::standardAboutPanel command.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	none
 *
 *----------------------------------------------------------------------
 */

int
TkMacOSXStandardAboutPanelObjCmd(
    ClientData clientData,	/* Unused. */
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    if (objc > 1) {
	Tcl_WrongNumArgs(interp, 1, objv, NULL);
	return TCL_ERROR;
    }
    TkAboutDlg();
    [NSApp orderFrontStandardAboutPanel:nil];
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Tk_MessageBoxObjCmd --
1391
1392
1393
1394
1395
1396
1397
1398

1399
1400
1401
1402
1403
1404
1405
1368
1369
1370
1371
1372
1373
1374

1375
1376
1377
1378
1379
1380
1381
1382







-
+







int
Tk_MessageBoxObjCmd(
    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, typeIndex, iconIndex, indexDefaultOption = 0;
    int defaultNativeButtonIndex = 1; /* 1, 2, 3: right to left */
    Tcl_Obj *cmdObj = NULL;
    AlertCallbackInfo callbackInfoStruct, *callbackInfo = &callbackInfoStruct;
    NSString *message, *title;
1525
1526
1527
1528
1529
1530
1531
1532

1533
1534
1535
1536

1537
1538
1539
1540
1541
1542
1543
1502
1503
1504
1505
1506
1507
1508

1509
1510
1511
1512

1513
1514
1515
1516
1517
1518
1519
1520







-
+



-
+







	    setKeyEquivalent: @"\r"];
    if (cmdObj) {
	if (Tcl_IsShared(cmdObj)) {
	    cmdObj = Tcl_DuplicateObj(cmdObj);
	}
	Tcl_IncrRefCount(cmdObj);
    }
    callbackInfo = ckalloc(sizeof(AlertCallbackInfo));
    callbackInfo = (AlertCallbackInfo *)ckalloc(sizeof(AlertCallbackInfo));
    callbackInfo->cmdObj = cmdObj;
    callbackInfo->interp = interp;
    callbackInfo->typeIndex = typeIndex;
    parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window);
    parent = TkMacOSXGetNSWindowForDrawable(((TkWindow *)tkwin)->window);
    if (haveParentOption && parent && ![parent attachedSheet]) {
	parentIsKey = [parent isKeyWindow];
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
 	[alert beginSheetModalForWindow:parent
	       completionHandler:^(NSModalResponse returnCode) {
	    [NSApp tkAlertDidEnd:alert
		    returnCode:returnCode
1569
1570
1571
1572
1573
1574
1575
1576

1577
1578
1579
1580
1581
1582
1583
1546
1547
1548
1549
1550
1551
1552

1553
1554
1555
1556
1557
1558
1559
1560







-
+







 *----------------------------------------------------------------------
 */
#pragma mark [tk fontchooser] implementation (TIP 324)
/*
 *----------------------------------------------------------------------
 */

#include "tkMacOSXEvent.h"
#include "tkMacOSXInt.h"
#include "tkMacOSXFont.h"

typedef struct FontchooserData {
    Tcl_Obj *titleObj;
    Tcl_Obj *cmdObj;
    Tk_Window parent;
} FontchooserData;
1626
1627
1628
1629
1630
1631
1632

1633
1634
1635
1636
1637
1638
1639
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617







+







};

@implementation TKApplication(TKFontPanel)

- (void) changeFont: (id) sender
{
    NSFontManager *fm = [NSFontManager sharedFontManager];
    (void)sender;

    if ([fm currentFontAction] == NSViaPanelFontAction) {
	NSFont *font = [fm convertFont:fontPanelFont];

	if (![fontPanelFont isEqual:font]) {
	    [fontPanelFont release];
	    fontPanelFont = [font retain];
1649
1650
1651
1652
1653
1654
1655
1656

1657


1658
1659
1660
1661
1662
1663

1664
1665
1666
1667
1668
1669
1670
1627
1628
1629
1630
1631
1632
1633

1634
1635
1636
1637
1638
1639
1640
1641
1642

1643
1644
1645
1646
1647
1648
1649
1650







-
+

+
+





-
+








    if (![fontPanelFontAttributes isEqual:attributes]) {
	[fontPanelFontAttributes setDictionary:attributes];
	FontchooserEvent(FontchooserSelection);
    }
}

- (NSUInteger) validModesForFontPanel: (NSFontPanel *) fontPanel
- (NSUInteger) validModesForFontPanel: (NSFontPanel *)fontPanel
{
    (void)fontPanel;

    return (NSFontPanelStandardModesMask & ~NSFontPanelAllEffectsModeMask) |
	    NSFontPanelUnderlineEffectModeMask |
	    NSFontPanelStrikethroughEffectModeMask;
}

- (void) windowDidOrderOffScreen: (NSNotification *) notification
- (void) windowDidOrderOffScreen: (NSNotification *)notification
{
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
    TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
#endif
    if ([[notification object] isEqual:[[NSFontManager sharedFontManager]
	    fontPanel:NO]]) {
	FontchooserEvent(FontchooserClosed);
1680
1681
1682
1683
1684
1685
1686
1687

1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706

1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721

1722
1723
1724
1725
1726
1727
1728
1729

1730
1731
1732
1733
1734
1735
1736
1660
1661
1662
1663
1664
1665
1666

1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685

1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700

1701
1702
1703
1704
1705
1706
1707
1708

1709
1710
1711
1712
1713
1714
1715
1716







-
+


















-
+














-
+







-
+







 *	This processes events generated by user interaction with the font
 *	panel.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Additional events may be place on the Tk event queue.
 *	Additional events may be placed on the Tk event queue.
 *
 *----------------------------------------------------------------------
 */

static void
FontchooserEvent(
    int kind)
{
    FontchooserData *fcdPtr;
    Tcl_Obj *fontObj;

    if (!fontchooserInterp) {
	return;
    }
    fcdPtr = Tcl_GetAssocData(fontchooserInterp, "::tk::fontchooser", NULL);
    switch (kind) {
    case FontchooserClosed:
	if (fcdPtr->parent != None) {
	    TkSendVirtualEvent(fcdPtr->parent, "TkFontchooserVisibility", NULL);
	    Tk_SendVirtualEvent(fcdPtr->parent, "TkFontchooserVisibility", NULL);
	    fontchooserInterp = NULL;
	}
	break;
    case FontchooserSelection:
	fontObj = TkMacOSXFontDescriptionForNSFontAndNSFontAttributes(
		fontPanelFont, fontPanelFontAttributes);
	if (fontObj) {
	    if (fcdPtr->cmdObj) {
		int objc, result;
		Tcl_Obj **objv, **tmpv;

		result = Tcl_ListObjGetElements(fontchooserInterp,
			fcdPtr->cmdObj, &objc, &objv);
		if (result == TCL_OK) {
		    tmpv = ckalloc(sizeof(Tcl_Obj *) * (objc + 2));
		    tmpv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj *) * (objc + 2));
		    memcpy(tmpv, objv, sizeof(Tcl_Obj *) * objc);
		    tmpv[objc] = fontObj;
		    TkBackgroundEvalObjv(fontchooserInterp, objc + 1, tmpv,
			    TCL_EVAL_GLOBAL);
		    ckfree(tmpv);
		}
	    }
	    TkSendVirtualEvent(fcdPtr->parent, "TkFontchooserFontChanged", NULL);
	    Tk_SendVirtualEvent(fcdPtr->parent, "TkFontchooserFontChanged", NULL);
	}
	break;
    }
}

/*
 *----------------------------------------------------------------------
1756
1757
1758
1759
1760
1761
1762
1763

1764
1765
1766
1767
1768
1769
1770
1736
1737
1738
1739
1740
1741
1742

1743
1744
1745
1746
1747
1748
1749
1750







-
+







{
    Tcl_Obj *resObj = NULL;

    switch(optionIndex) {
    case FontchooserParent:
	if (fcdPtr->parent != None) {
	    resObj = Tcl_NewStringObj(
		    ((TkWindow *) fcdPtr->parent)->pathName, -1);
		    ((TkWindow *)fcdPtr->parent)->pathName, -1);
	} else {
	    resObj = Tcl_NewStringObj(".", 1);
	}
	break;
    case FontchooserTitle:
	if (fcdPtr->titleObj) {
	    resObj = fcdPtr->titleObj;
1783
1784
1785
1786
1787
1788
1789
1790
1791


1792
1793
1794
1795
1796
1797
1798
1763
1764
1765
1766
1767
1768
1769


1770
1771
1772
1773
1774
1775
1776
1777
1778







-
-
+
+







	if (fcdPtr->cmdObj) {
	    resObj = fcdPtr->cmdObj;
	} else {
	    resObj = Tcl_NewObj();
	}
	break;
    case FontchooserVisible:
	resObj = Tcl_NewBooleanObj([[[NSFontManager sharedFontManager]
		fontPanel:NO] isVisible]);
	resObj = Tcl_NewWideIntObj([[[NSFontManager sharedFontManager]
		fontPanel:NO] isVisible] != 0);
	break;
    default:
	resObj = Tcl_NewObj();
    }
    return resObj;
}

1931
1932
1933
1934
1935
1936
1937
1938

1939
1940
1941
1942
1943
1944
1945
1911
1912
1913
1914
1915
1916
1917

1918
1919
1920
1921
1922
1923
1924
1925







-
+







	    NSFontPanel *fp = [fm fontPanel:NO];

	    [fp setPanelFont:fontPanelFont isMultiple:NO];
	    [fm setSelectedFont:fontPanelFont isMultiple:NO];
	    [fm setSelectedAttributes:fontPanelFontAttributes
		    isMultiple:NO];
	    if ([fp isVisible]) {
		TkSendVirtualEvent(fcdPtr->parent,
		Tk_SendVirtualEvent(fcdPtr->parent,
			"TkFontchooserFontChanged", NULL);
	    }
	    break;
	case FontchooserCmd:
	    if (fcdPtr->cmdObj) {
		Tcl_DecrRefCount(fcdPtr->cmdObj);
	    }
1977
1978
1979
1980
1981
1982
1983
1984
1985


1986
1987
1988
1989
1990
1991

1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004

2005
2006
2007
2008
2009
2010
2011
1957
1958
1959
1960
1961
1962
1963


1964
1965
1966
1967
1968
1969
1970

1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983

1984
1985
1986
1987
1988
1989
1990
1991







-
-
+
+





-
+












-
+







 * ----------------------------------------------------------------------
 */

static int
FontchooserShowCmd(
    ClientData clientData,	/* Main window */
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
    TCL_UNUSED(int),
    TCL_UNUSED(Tcl_Obj *const *))
{
    FontchooserData *fcdPtr = Tcl_GetAssocData(interp, "::tk::fontchooser",
	    NULL);

    if (fcdPtr->parent == None) {
	fcdPtr->parent = (Tk_Window) clientData;
	fcdPtr->parent = (Tk_Window)clientData;
	Tk_CreateEventHandler(fcdPtr->parent, StructureNotifyMask,
		FontchooserParentEventHandler, fcdPtr);
    }

    NSFontManager *fm = [NSFontManager sharedFontManager];
    NSFontPanel *fp = [fm fontPanel:YES];

    if ([fp delegate] != NSApp) {
	[fp setDelegate:NSApp];
    }
    if (![fp isVisible]) {
	[fm orderFrontFontPanel:NSApp];
	TkSendVirtualEvent(fcdPtr->parent, "TkFontchooserVisibility", NULL);
	Tk_SendVirtualEvent(fcdPtr->parent, "TkFontchooserVisibility", NULL);
    }
    fontchooserInterp = interp;

    return TCL_OK;
}

/*
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033




2034
2035
2036
2037
2038
2039
2040
2003
2004
2005
2006
2007
2008
2009




2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020







-
-
-
-
+
+
+
+







 *	Font Panel may be hidden.
 *
 * ----------------------------------------------------------------------
 */

static int
FontchooserHideCmd(
    ClientData clientData,	/* Main window */
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
    TCL_UNUSED(void *),	/* Main window */
    TCL_UNUSED(Tcl_Interp *),
    TCL_UNUSED(int),
    TCL_UNUSED(Tcl_Obj *const *))
{
    NSFontPanel *fp = [[NSFontManager sharedFontManager] fontPanel:NO];

    if ([fp isVisible]) {
	[fp orderOut:NSApp];
    }
    return TCL_OK;
2125
2126
2127
2128
2129
2130
2131
2132

2133
2134

2135
2136
2137
2138
2139
2140
2141
2105
2106
2107
2108
2109
2110
2111

2112
2113

2114
2115
2116
2117
2118
2119
2120
2121







-
+

-
+







 *
 * ----------------------------------------------------------------------
 */

MODULE_SCOPE int
TkInitFontchooser(
    Tcl_Interp *interp,
    ClientData clientData)
    TCL_UNUSED(void *))
{
    FontchooserData *fcdPtr = ckalloc(sizeof(FontchooserData));
    FontchooserData *fcdPtr = (FontchooserData *)ckalloc(sizeof(FontchooserData));

    bzero(fcdPtr, sizeof(FontchooserData));
    Tcl_SetAssocData(interp, "::tk::fontchooser", DeleteFontchooserData,
	    fcdPtr);
    if (!fontPanelFontAttributes) {
	fontPanelFontAttributes = [NSMutableDictionary new];
    }
Changes to macosx/tkMacOSXDraw.c.
1
2
3
4
5


6
7
8
9
10




11
12
13
14
15
16
17
18
19
20

21
22
23
24
25
26
27
1
2
3


4
5
6




7
8
9
10
11
12
13
14
15
16
17
18
19

20
21
22
23
24
25
26
27



-
-
+
+

-
-
-
-
+
+
+
+









-
+







/*
 * tkMacOSXDraw.c --
 *
 *	This file contains functions that perform drawing to Xlib windows. Most
 *	of the functions simply emulate Xlib functions.
 *	This file contains functions that draw to windows. Many of thees
 *	functions emulate Xlib functions.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright 2001-2009, Apple Inc.
 * Copyright (c) 2006-2009 Daniel A. Steffen <[email protected]>
 * Copyright 2014 Marc Culler.
 * Copyright © 1995-1997 Sun Microsystems, Inc.
 * Copyright © 2001-2009 Apple Inc.
 * Copyright © 2006-2009 Daniel A. Steffen <[email protected]>
 * 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.
 */

#include "tkMacOSXPrivate.h"
#include "tkMacOSXDebug.h"
#include "tkButton.h"

#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
#define GET_CGCONTEXT [[NSGraphicsContext currentContext] CGContext]
#else
#define GET_CGCONTEXT [[NSGraphicsContext currentContext] graphicsPort]
#endif

/*
#ifdef TK_MAC_DEBUG
39
40
41
42
43
44
45

46
47
48
49
50
51


52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72

73
74
75
76
77
78
79
80
81
82
83
84
85

86
87
88
89
90
91
92
93
94
95

96
97
98
99

100
101

102
103
104
105
106
107
108
109

110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129

130
131
132
133
134
135
136

137
138
139
140
141
142

143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167


168
169
170
171
172
173
174


175
176
177
178
179
180
181

182
183
184
185
186


187
188
189
190
191
192
193

194
195
196
197
198

199
200
201
202



203
204
205
206






207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334

335
336

337
338
339

340
341
342
343

344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424

425
426
427
428
429
430
431
432
433
434







435

436
437



438
439
440
441
442








443
444
445
446
447
448

449
450
451
452
453
454
455
456
457
458
459
460
461
462

463
464
465
466
467
468
469

470

471




472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559

560
561
562
563
564
565
566
567
568
569
570
571
572
573


574
575
576

577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594

595
596
597
598
599
600
601
602
603

604
605
606
607
608
609
610
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74

75
76
77
78
79
80
81
82
83
84
85
86
87

88
89
90
91
92
93
94
95
96
97

98
99
100
101

102
103
104
105
106
107
108
109
110
111
112

113
114



















115

116
117




118



119
120

121
122
123
124


















125



126
127







128
129







130





131
132







133





134




135
136
137




138
139
140
141
142
143
144
145
146
147
148



























































































































149


150



151




152















































































153

154
155
156
157
158
159
160
161



162
163
164
165
166
167
168
169
170


171
172
173
174




175
176
177
178
179
180
181
182
183
184
185
186
187

188
189
190
191
192
193
194
195
196
197
198
199
200
201

202
203
204
205
206
207
208
209
210
211
212

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228












































































229
230
231
232
233
234
235
236
237
238
239
240
241


242
243
244
245

246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263

264
265
266
267
268
269
270
271
272

273
274
275
276
277
278
279
280







+






+
+




















-
+












-
+









-
+



-
+


+







-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-


-
-
-
-
+
-
-
-


-
+



-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
-
+
+
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
+
-
-
-
-
-
+
+
-
-
-
-
-
-
-
+
-
-
-
-
-
+
-
-
-
-
+
+
+
-
-
-
-
+
+
+
+
+
+





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
-
-
-
+
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
+







-
-
-
+
+
+
+
+
+
+

+
-
-
+
+
+

-
-
-
-
+
+
+
+
+
+
+
+





-
+













-
+







+

+
-
+
+
+
+












-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+












-
-
+
+


-
+

















-
+








-
+







#define NON_AA_CG_OFFSET .999

static int cgAntiAliasLimit = 0;
#define notAA(w)	((w) < cgAntiAliasLimit)

static int useThemedToplevel = 0;
static int useThemedFrame = 0;
static unsigned long transparentColor;

/*
 * Prototypes for functions used only in this file.
 */

static void ClipToGC(Drawable d, GC gc, HIShapeRef *clipRgnPtr);
static NSImage *CreateNSImageFromPixmap(Pixmap pixmap, int width, int height);


/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXInitCGDrawing --
 *
 *	Initializes link vars that control CG drawing.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

MODULE_SCOPE int
TkMacOSXInitCGDrawing(
    Tcl_Interp *interp,
    int enable,
    TCL_UNUSED(int),
    int limit)
{
    static Boolean initialized = FALSE;

    if (!initialized) {
	initialized = TRUE;

	if (Tcl_CreateNamespace(interp, "::tk::mac", NULL, NULL) == NULL) {
	    Tcl_ResetResult(interp);
	}

	if (Tcl_LinkVar(interp, "::tk::mac::CGAntialiasLimit",
		(char *) &cgAntiAliasLimit, TCL_LINK_INT) != TCL_OK) {
		(char *)&cgAntiAliasLimit, TCL_LINK_INT) != TCL_OK) {
	    Tcl_ResetResult(interp);
	}
	cgAntiAliasLimit = limit;

	/*
	 * Piggy-back the themed drawing var init here.
	 */

	if (Tcl_LinkVar(interp, "::tk::mac::useThemedToplevel",
		(char *) &useThemedToplevel, TCL_LINK_BOOLEAN) != TCL_OK) {
		(char *)&useThemedToplevel, TCL_LINK_BOOLEAN) != TCL_OK) {
	    Tcl_ResetResult(interp);
	}
	if (Tcl_LinkVar(interp, "::tk::mac::useThemedFrame",
		(char *) &useThemedFrame, TCL_LINK_BOOLEAN) != TCL_OK) {
		(char *)&useThemedFrame, TCL_LINK_BOOLEAN) != TCL_OK) {
	    Tcl_ResetResult(interp);
	}
	transparentColor = TkMacOSXClearPixel();
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXBitmapRepFromDrawableRect
 * TkMacOSXGetNSImageFromTkImage --
 *
 *	Extract bitmap data from a MacOSX drawable as an NSBitmapImageRep.
 *
 *      This is only used by XGetImage, which is never called.  And this
 *      implementation does not work correctly.  Originally it 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 into 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
 *	Get autoreleased NSImage for Tk_Image.
 *      will include some more helpful ways of doing this.
 *
 * 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.
 *
 *	NSImage.
 *      NOTE: The x,y coordinates should be relative to a coordinate system
 *      with origin at the top left, as used by XImage and CGImage, not bottom
 *      left as used by NSView.
 *
 * Side effects:
 *     None
 *	None.
 *
 *----------------------------------------------------------------------
 */

NSBitmapImageRep *
TkMacOSXBitmapRepFromDrawableRect(
    Drawable drawable,
    int x,
    int y,
    unsigned int width,
    unsigned int height)
{
    MacDrawable *mac_drawable = (MacDrawable *) drawable;
    CGContextRef cg_context = NULL;
    CGImageRef cg_image = NULL, sub_cg_image = NULL;
    NSBitmapImageRep *bitmap_rep = NULL;
    NSView *view = 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);
NSImage *
TkMacOSXGetNSImageFromTkImage(
	cg_image = CGBitmapContextCreateImage((CGContextRef) cg_context);
	sub_cg_image = CGImageCreateWithImageInRect(cg_image, image_rect);
	if (sub_cg_image) {
	    bitmap_rep = [NSBitmapImageRep alloc];
	    [bitmap_rep initWithCGImage:sub_cg_image];
	}
	if (cg_image) {
    Display *display,
    Tk_Image image,
	    CGImageRelease(cg_image);
	}
    } else if ((view = TkMacOSXDrawableView(mac_drawable)) != NULL) {
	/*
	 * Convert Tk top-left to NSView bottom-left coordinates.
	 */

    int width,
	int view_height = [view bounds].size.height;
	NSRect view_rect = NSMakeRect(x + mac_drawable->xOff,
		view_height - height - y - mac_drawable->yOff,
		width, height);

    int 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 mark the view as needing
	 * display and return NULL.
	 */

    Pixmap pixmap;
	if (view == [NSView focusView]) {
	    bitmap_rep = [view bitmapImageRepForCachingDisplayInRect: view_rect];
	    [bitmap_rep retain];
	    [view cacheDisplayInRect:view_rect toBitmapImageRep:bitmap_rep];
	} else {
    NSImage *nsImage;
	    TkMacOSXDbgMsg("No CGContext - cannot copy from screen to bitmap.");
	    [view setNeedsDisplay:YES];
	    return NULL;
	}
    if (width == 0 || height == 0) {
	return nsImage = [[NSImage alloc] initWithSize:NSMakeSize(0,0)];
    }
    } else {
	TkMacOSXDbgMsg("Invalid source drawable");
    }
    return bitmap_rep;
    pixmap = Tk_GetPixmap(display, None, width, height, 0);
    Tk_RedrawImage(image, 0, 0, width, height, pixmap, 0, 0);
    nsImage = CreateNSImageFromPixmap(pixmap, width, height);
    Tk_FreePixmap(display, pixmap);

    return [nsImage autorelease];
}

/*
 *----------------------------------------------------------------------
 *
 * XCopyArea --
 *
 *	Copies data from one drawable to another.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Data is moved from a window or bitmap to a second window or bitmap.
 *
 *----------------------------------------------------------------------
 */

int
XCopyArea(
    Display *display,		/* Display. */
    Drawable src,		/* Source drawable. */
    Drawable dst,		/* Destination drawable. */
    GC gc,			/* GC to use. */
    int src_x,			/* X & Y, width & height */
    int src_y,			/* define the source rectangle */
    unsigned int width,		/* that will be copied. */
    unsigned int height,
    int dest_x,			/* Dest X & Y on dest rect. */
    int dest_y)
{
    TkMacOSXDrawingContext dc;
    MacDrawable *srcDraw = (MacDrawable *) src;
    NSBitmapImageRep *bitmap_rep = NULL;
    CGImageRef img = NULL;
    CGRect bounds, srcRect, dstRect;

    display->request++;
    if (!width || !height) {
	return BadDrawable;
    }

    if (!TkMacOSXSetupDrawingContext(dst, gc, 1, &dc)) {
	TkMacOSXDbgMsg("Failed to setup drawing context.");
	return BadDrawable;
    }

    if (!dc.context) {
	TkMacOSXDbgMsg("Invalid destination drawable - no context.");
	return BadDrawable;
    }

    if (srcDraw->flags & TK_IS_PIXMAP) {
	img = TkMacOSXCreateCGImageWithDrawable(src);
    } else if (TkMacOSXDrawableWindow(src)) {
	bitmap_rep = TkMacOSXBitmapRepFromDrawableRect(src,
		src_x, src_y, width, height);
	if (bitmap_rep) {
	    img = [bitmap_rep CGImage];
	}
    } else {
	TkMacOSXDbgMsg("Invalid source drawable - neither window nor pixmap.");
    }

    if (img) {
	bounds = CGRectMake(0, 0, srcDraw->size.width, srcDraw->size.height);
	srcRect = CGRectMake(src_x, src_y, width, height);
	dstRect = CGRectMake(dest_x, dest_y, width, height);
	TkMacOSXDrawCGImage(dst, gc, dc.context, img,
		gc->foreground, gc->background, bounds, srcRect, dstRect);
	CFRelease(img);
    } else {
	TkMacOSXDbgMsg("Failed to construct CGImage.");
    }

    TkMacOSXRestoreDrawingContext(&dc);
    return Success;
}

/*
 *----------------------------------------------------------------------
 *
 * XCopyPlane --
 *
 *	Copies a bitmap from a source drawable to a destination drawable. The
 *	plane argument specifies which bit plane of the source contains the
 *	bitmap. Note that this implementation ignores the gc->function.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Changes the destination drawable.
 *
 *----------------------------------------------------------------------
 */

int
XCopyPlane(
    Display *display,		/* Display. */
    Drawable src,		/* Source drawable. */
    Drawable dst,		/* Destination drawable. */
    GC gc,				/* GC to use. */
    int src_x,			/* X & Y, width & height */
    int src_y,			/* define the source rectangle */
    unsigned int width,	/* that will be copied. */
    unsigned int height,
    int dest_x,			/* Dest X & Y on dest rect. */
    int dest_y,
    unsigned long plane)	/* Which plane to copy. */
{
    TkMacOSXDrawingContext dc;
    MacDrawable *srcDraw = (MacDrawable *) src;
    MacDrawable *dstDraw = (MacDrawable *) dst;
    CGRect bounds, srcRect, dstRect;
    display->request++;
    if (!width || !height) {
	/* TkMacOSXDbgMsg("Drawing of empty area requested"); */
	return BadDrawable;
    }
    if (plane != 1) {
	Tcl_Panic("Unexpected plane specified for XCopyPlane");
    }
    if (srcDraw->flags & TK_IS_PIXMAP) {
	if (!TkMacOSXSetupDrawingContext(dst, gc, 1, &dc)) {
	    return BadDrawable;
	}

 * TkMacOSXGetNSImageFromBitmap --
	CGContextRef context = dc.context;

 *
	if (context) {
	    CGImageRef img = TkMacOSXCreateCGImageWithDrawable(src);

 *	Get autoreleased NSImage for Bitmap.
	    if (img) {
		TkpClipMask *clipPtr = (TkpClipMask *) gc->clip_mask;
		unsigned long imageBackground  = gc->background;

 *
                if (clipPtr && clipPtr->type == TKP_CLIP_PIXMAP) {
		    srcRect = CGRectMake(src_x, src_y, width, height);
		    CGImageRef mask = TkMacOSXCreateCGImageWithDrawable(
			    clipPtr->value.pixmap);
		    CGImageRef submask = CGImageCreateWithImageInRect(
			    img, srcRect);
		    CGRect rect = CGRectMake(dest_x, dest_y, width, height);

		    rect = CGRectOffset(rect, dstDraw->xOff, dstDraw->yOff);
		    CGContextSaveGState(context);

		    /*
		     * Move the origin of the destination to top left.
		     */

		    CGContextTranslateCTM(context,
			    0, rect.origin.y + CGRectGetMaxY(rect));
		    CGContextScaleCTM(context, 1, -1);

		    /*
		     * Fill with the background color, clipping to the mask.
		     */

		    CGContextClipToMask(context, rect, submask);
		    TkMacOSXSetColorInContext(gc, gc->background, dc.context);
		    CGContextFillRect(context, rect);

		    /*
		     * Fill with the foreground color, clipping to the
		     * intersection of img and mask.
		     */

		    CGImageRef subimage = CGImageCreateWithImageInRect(
			    img, srcRect);
		    CGContextClipToMask(context, rect, subimage);
		    TkMacOSXSetColorInContext(gc, gc->foreground, context);
		    CGContextFillRect(context, rect);
		    CGContextRestoreGState(context);
		    CGImageRelease(img);
		    CGImageRelease(mask);
		    CGImageRelease(submask);
		    CGImageRelease(subimage);
		} else {
		    bounds = CGRectMake(0, 0,
			    srcDraw->size.width, srcDraw->size.height);
		    srcRect = CGRectMake(src_x, src_y, width, height);
		    dstRect = CGRectMake(dest_x, dest_y, width, height);
		    TkMacOSXDrawCGImage(dst, gc, dc.context, img,
			    gc->foreground, imageBackground, bounds,
			    srcRect, dstRect);
		    CGImageRelease(img);
		}
	    } else {
		/* no image */
		TkMacOSXDbgMsg("Invalid source drawable");
	    }
	} else {
	    TkMacOSXDbgMsg("Invalid destination drawable - "
		    "could not get a bitmap context.");
	}
	TkMacOSXRestoreDrawingContext(&dc);
	return Success;
    } else {
	/*
	 * Source drawable is a Window, not a Pixmap.
	 */

	return XCopyArea(display, src, dst, gc, src_x, src_y, width, height,
		dest_x, dest_y);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXCreateCGImageWithDrawable --
 *
 *	Create a CGImage from the given Drawable.
 *
 * Results:
 *	CGImage, release after use.
 *	NSImage.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

CGImageRef
TkMacOSXCreateCGImageWithDrawable(
    Drawable drawable)
NSImage *
TkMacOSXGetNSImageFromBitmap(
    Display *display,
    Pixmap bitmap,
    GC gc,
    int width,
    int height)
{
    Pixmap pixmap = Tk_GetPixmap(display, None, width, height, 0);
    CGImageRef img = NULL;
    CGContextRef context = TkMacOSXGetCGContextForDrawable(drawable);
    NSImage *nsImage;

    unsigned long origBackground = gc->background;

    if (context) {
	img = CGBitmapContextCreateImage(context);
    }
    return img;
    gc->background = transparentColor;
    XSetClipOrigin(display, gc, 0, 0);
    XCopyPlane(display, bitmap, pixmap, gc, 0, 0, width, height, 0, 0, 1);
    gc->background = origBackground;
    nsImage = CreateNSImageFromPixmap(pixmap, width, height);
    Tk_FreePixmap(display, pixmap);

    return [nsImage autorelease];
}

/*
 *----------------------------------------------------------------------
 *
 * CreateNSImageWithPixmap --
 * CreateNSImageFromPixmap --
 *
 *	Create NSImage for Pixmap.
 *
 * Results:
 *	NSImage.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static NSImage *
CreateNSImageWithPixmap(
CreateNSImageFromPixmap(
    Pixmap pixmap,
    int width,
    int height)
{
    CGImageRef cgImage;
    NSImage *nsImage;
    NSBitmapImageRep *bitmapImageRep;
    CGContextRef context = TkMacOSXGetCGContextForDrawable(pixmap);

    if (context) {
    cgImage = TkMacOSXCreateCGImageWithDrawable(pixmap);
	cgImage = CGBitmapContextCreateImage(context);
    } else {
	return NULL;
    }
    nsImage = [[NSImage alloc] initWithSize:NSMakeSize(width, height)];
    bitmapImageRep = [[NSBitmapImageRep alloc] initWithCGImage:cgImage];
    [nsImage addRepresentation:bitmapImageRep];
    [bitmapImageRep release];
    CFRelease(cgImage);

    return nsImage;
}

/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXGetNSImageWithTkImage --
 *
 *	Get autoreleased NSImage for Tk_Image.
 *
 * Results:
 *	NSImage.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

NSImage *
TkMacOSXGetNSImageWithTkImage(
    Display *display,
    Tk_Image image,
    int width,
    int height)
{
    Pixmap pixmap;
    NSImage *nsImage;
    if (width == 0 || height == 0) {
	return nsImage = [[NSImage alloc] initWithSize:NSMakeSize(0,0)];
    }
    pixmap = Tk_GetPixmap(display, None, width, height, 0);
    Tk_RedrawImage(image, 0, 0, width, height, pixmap, 0, 0);
    nsImage = CreateNSImageWithPixmap(pixmap, width, height);
    Tk_FreePixmap(display, pixmap);

    return [nsImage autorelease];
}

/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXGetNSImageWithBitmap --
 *
 *	Get autoreleased NSImage for Bitmap.
 *
 * Results:
 *	NSImage.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

NSImage *
TkMacOSXGetNSImageWithBitmap(
    Display *display,
    Pixmap bitmap,
    GC gc,
    int width,
    int height)
{
    Pixmap pixmap = Tk_GetPixmap(display, None, width, height, 0);
    NSImage *nsImage;

    unsigned long origBackground = gc->background;

    gc->background = TRANSPARENT_PIXEL << 24;
    XSetClipOrigin(display, gc, 0, 0);
    XCopyPlane(display, bitmap, pixmap, gc, 0, 0, width, height, 0, 0, 1);
    gc->background = origBackground;
    nsImage = CreateNSImageWithPixmap(pixmap, width, height);
    Tk_FreePixmap(display, pixmap);

    return [nsImage autorelease];
}

/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXGetCGContextForDrawable --
 * Tk_MacOSXGetCGContextForDrawable --
 *
 *	Get CGContext for given Drawable, creating one if necessary.
 *
 * Results:
 *	CGContext.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

CGContextRef
TkMacOSXGetCGContextForDrawable(
void *
Tk_MacOSXGetCGContextForDrawable(
    Drawable drawable)
{
    MacDrawable *macDraw = (MacDrawable *) drawable;
    MacDrawable *macDraw = (MacDrawable *)drawable;

    if (macDraw && (macDraw->flags & TK_IS_PIXMAP) && !macDraw->context) {
	const size_t bitsPerComponent = 8;
	size_t bitsPerPixel, bytesPerRow, len;
	CGColorSpaceRef colorspace = NULL;
	CGBitmapInfo bitmapInfo =
#ifdef __LITTLE_ENDIAN__
		kCGBitmapByteOrder32Host;
#else
		kCGBitmapByteOrderDefault;
#endif
	char *data;
	CGRect bounds = CGRectMake(0, 0,
		macDraw->size.width, macDraw->size.height);

	if (macDraw->flags & TK_IS_BW_PIXMAP) {
	    bitsPerPixel = 8;
	    bitmapInfo = (CGBitmapInfo) kCGImageAlphaOnly;
	    bitmapInfo = (CGBitmapInfo)kCGImageAlphaOnly;
	} else {
	    colorspace = CGColorSpaceCreateDeviceRGB();
	    bitsPerPixel = 32;
	    bitmapInfo |= kCGImageAlphaPremultipliedFirst;
	}
	bytesPerRow = ((size_t)
		macDraw->size.width * bitsPerPixel + 127) >> 3 & ~15;
	len = macDraw->size.height * bytesPerRow;
	data = ckalloc(len);
	data = (char *)ckalloc(len);
	bzero(data, len);
	macDraw->context = CGBitmapContextCreate(data, macDraw->size.width,
		macDraw->size.height, bitsPerComponent, bytesPerRow,
		colorspace, bitmapInfo);
	if (macDraw->context) {
	    CGContextClearRect(macDraw->context, bounds);
	}
640
641
642
643
644
645
646
647

648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664

665
666
667
668
669
670

671
672
673
674
675

676
677
678
679
680
681
682
310
311
312
313
314
315
316

317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340

341
342
343
344
345

346
347
348
349
350
351
352
353







-
+

















+





-
+




-
+







    CGImageRef image,
    unsigned long imageForeground,
    unsigned long imageBackground,
    CGRect imageBounds,
    CGRect srcBounds,
    CGRect dstBounds)
{
    MacDrawable *macDraw = (MacDrawable *) d;
    MacDrawable *macDraw = (MacDrawable *)d;

    if (macDraw && context && image) {
	CGImageRef subImage = NULL;

	if (!CGRectEqualToRect(imageBounds, srcBounds)) {
	    if (!CGRectContainsRect(imageBounds, srcBounds)) {
		TkMacOSXDbgMsg("Mismatch of sub CGImage bounds");
	    }
	    subImage = CGImageCreateWithImageInRect(image, CGRectOffset(
		    srcBounds, -imageBounds.origin.x, -imageBounds.origin.y));
	    if (subImage) {
		image = subImage;
	    }
	}
	dstBounds = CGRectOffset(dstBounds, macDraw->xOff, macDraw->yOff);
	if (CGImageIsMask(image)) {
	    if (macDraw->flags & TK_IS_BW_PIXMAP) {

		/*
		 * Set fill color to black; background comes from the context,
		 * or is transparent.
		 */

		if (imageBackground != TRANSPARENT_PIXEL << 24) {
		if (imageBackground != transparentColor) {
		    CGContextClearRect(context, dstBounds);
		}
		CGContextSetRGBFillColor(context, 0.0, 0.0, 0.0, 1.0);
	    } else {
		if (imageBackground != TRANSPARENT_PIXEL << 24) {
		if (imageBackground != transparentColor) {
		    TkMacOSXSetColorInContext(gc, imageBackground, context);
		    CGContextFillRect(context, dstBounds);
		}
		TkMacOSXSetColorInContext(gc, imageForeground, context);
	    }
	}

735
736
737
738
739
740
741
742

743
744
745
746
747
748
749
750
751

752
753
754
755
756
757
758
406
407
408
409
410
411
412

413
414
415
416
417
418
419
420
421

422
423
424
425
426
427
428
429







-
+








-
+







    Display *display,		/* Display. */
    Drawable d,			/* Draw on this. */
    GC gc,			/* Use this GC. */
    XPoint *points,		/* Array of points. */
    int npoints,		/* Number of points. */
    int mode)			/* Line drawing mode. */
{
    MacDrawable *macWin = (MacDrawable *) d;
    MacDrawable *macWin = (MacDrawable *)d;
    TkMacOSXDrawingContext dc;
    int i, lw = gc->line_width;

    if (npoints < 2) {
	return BadValue;
    }

    display->request++;
    if (!TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) {
    if (!TkMacOSXSetupDrawingContext(d, gc, &dc)) {
	return BadDrawable;
    }
    if (dc.context) {
	double prevx, prevy;
	double o = (lw % 2) ? .5 : 0;

	CGContextBeginPath(dc.context);
807
808
809
810
811
812
813
814

815
816
817
818
819

820
821
822
823
824
825
826
478
479
480
481
482
483
484

485
486
487
488
489

490
491
492
493
494
495
496
497







-
+




-
+







XDrawSegments(
    Display *display,
    Drawable d,
    GC gc,
    XSegment *segments,
    int nsegments)
{
    MacDrawable *macWin = (MacDrawable *) d;
    MacDrawable *macWin = (MacDrawable *)d;
    TkMacOSXDrawingContext dc;
    int i, lw = gc->line_width;

    display->request++;
    if (!TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) {
    if (!TkMacOSXSetupDrawingContext(d, gc, &dc)) {
	return BadDrawable;
    }
    if (dc.context) {
	double o = (lw % 2) ? .5 : 0;

	for (i = 0; i < nsegments; i++) {
	    CGContextBeginPath(dc.context);
856
857
858
859
860
861
862
863

864
865
866

867
868
869
870
871

872
873
874
875
876
877
878
527
528
529
530
531
532
533

534
535
536

537
538
539
540
541

542
543
544
545
546
547
548
549







-
+


-
+




-
+







int
XFillPolygon(
    Display *display,		/* Display. */
    Drawable d,			/* Draw on this. */
    GC gc,			/* Use this GC. */
    XPoint *points,		/* Array of points. */
    int npoints,		/* Number of points. */
    int shape,			/* Shape to draw. */
    TCL_UNUSED(int),	/* Shape to draw. */
    int mode)			/* Drawing mode. */
{
    MacDrawable *macWin = (MacDrawable *) d;
    MacDrawable *macWin = (MacDrawable *)d;
    TkMacOSXDrawingContext dc;
    int i;

    display->request++;
    if (!TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) {
    if (!TkMacOSXSetupDrawingContext(d, gc, &dc)) {
	return BadDrawable;
    }
    if (dc.context) {
	double prevx, prevy;
	double o = (gc->line_width % 2) ? .5 : 0;

	CGContextBeginPath(dc.context);
917
918
919
920
921
922
923
924

925
926
927
928
929
930
931
932
933

934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
588
589
590
591
592
593
594

595
596
597
598
599
600
601
602
603

604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619

620
621
622
623
624
625
626







-
+








-
+















-







    Display *display,		/* Display. */
    Drawable d,			/* Draw on this. */
    GC gc,			/* Use this GC. */
    int x, int y,		/* Upper left corner. */
    unsigned int width,		/* Width & height of rect. */
    unsigned int height)
{
    MacDrawable *macWin = (MacDrawable *) d;
    MacDrawable *macWin = (MacDrawable *)d;
    TkMacOSXDrawingContext dc;
    int lw = gc->line_width;

    if (width == 0 || height == 0) {
	return BadDrawable;
    }

    display->request++;
    if (!TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) {
    if (!TkMacOSXSetupDrawingContext(d, gc, &dc)) {
	return BadDrawable;
    }
    if (dc.context) {
	CGRect rect;
	double o = (lw % 2) ? .5 : 0;

	rect = CGRectMake(
		macWin->xOff + x + o, macWin->yOff + y + o,
		width, height);
	CGContextStrokeRect(dc.context, rect);
    }
    TkMacOSXRestoreDrawingContext(&dc);
    return Success;
}

#ifdef TK_MACOSXDRAW_UNUSED
/*
 *----------------------------------------------------------------------
 *
 * XDrawRectangles --
 *
 *	Draws the outlines of the specified rectangles as if a five-point
 *	PolyLine protocol request were specified for each rectangle:
967
968
969
970
971
972
973
974

975
976
977

978
979
980
981
982

983
984
985
986
987
988
989


990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006

1007
1008
1009
1010
1011
1012
1013
1014
1015
637
638
639
640
641
642
643

644
645
646

647
648
649
650
651

652
653
654
655
656
657


658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678

679
680
681
682
683
684
685







-
+


-
+




-
+





-
-
+
+

















+

-







 *
 * Side effects:
 *	Draws rectangles on the specified drawable.
 *
 *----------------------------------------------------------------------
 */

void
int
XDrawRectangles(
    Display *display,
    Drawable drawable,
    Drawable d,
    GC gc,
    XRectangle *rectArr,
    int nRects)
{
    MacDrawable *macWin = (MacDrawable *) drawable;
    MacDrawable *macWin = (MacDrawable *)d;
    TkMacOSXDrawingContext dc;
    XRectangle * rectPtr;
    int i, lw = gc->line_width;

    display->request++;
    if (!TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) {
	return;
    if (!TkMacOSXSetupDrawingContext(d, gc, &dc)) {
	return BadDrawable;
    }
    if (dc.context) {
	CGRect rect;
	double o = (lw % 2) ? .5 : 0;

	for (i = 0, rectPtr = rectArr; i < nRects; i++, rectPtr++) {
	    if (rectPtr->width == 0 || rectPtr->height == 0) {
		continue;
	    }
	    rect = CGRectMake(
		    macWin->xOff + rectPtr->x + o,
		    macWin->yOff + rectPtr->y + o,
		    rectPtr->width, rectPtr->height);
	    CGContextStrokeRect(dc.context, rect);
	}
    }
    TkMacOSXRestoreDrawingContext(&dc);
    return Success;
}
#endif

/*
 *----------------------------------------------------------------------
 *
 * XFillRectangles --
 *
 *	Fill multiple rectangular areas in the given drawable.
1027
1028
1029
1030
1031
1032
1033
1034

1035
1036
1037
1038
1039
1040

1041
1042
1043
1044
1045
1046
1047
697
698
699
700
701
702
703

704
705
706
707
708
709

710
711
712
713
714
715
716
717







-
+





-
+







XFillRectangles(
    Display *display,		/* Display. */
    Drawable d,			/* Draw on this. */
    GC gc,			/* Use this GC. */
    XRectangle *rectangles,	/* Rectangle array. */
    int n_rectangles)		/* Number of rectangles. */
{
    MacDrawable *macWin = (MacDrawable *) d;
    MacDrawable *macWin = (MacDrawable *)d;
    TkMacOSXDrawingContext dc;
    XRectangle * rectPtr;
    int i;

    display->request++;
    if (!TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) {
    if (!TkMacOSXSetupDrawingContext(d, gc, &dc)) {
	return BadDrawable;
    }
    if (dc.context) {
	CGRect rect;

	for (i = 0, rectPtr = rectangles; i < n_rectangles; i++, rectPtr++) {
	    if (rectPtr->width == 0 || rectPtr->height == 0) {
1086
1087
1088
1089
1090
1091
1092
1093

1094
1095
1096
1097
1098
1099
1100
756
757
758
759
760
761
762

763
764
765
766
767
768
769
770







-
+







    int inset,
    int thickness)
{
    Drawable d = Tk_WindowId(tkwin);
    TkMacOSXDrawingContext dc;
    CGRect outerRect, innerRect;

    if (!TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) {
    if (!TkMacOSXSetupDrawingContext(d, gc, &dc)) {
	return;
    }
    if (dc.context) {
	outerRect = CGRectMake(Tk_X(tkwin), Tk_Y(tkwin),
			       Tk_Width(tkwin), Tk_Height(tkwin));
	outerRect = CGRectInset(outerRect, inset, inset);
	innerRect = CGRectInset(outerRect, thickness, thickness);
1129
1130
1131
1132
1133
1134
1135
1136

1137
1138
1139
1140
1141
1142
1143
1144
1145

1146
1147
1148
1149
1150
1151
1152
799
800
801
802
803
804
805

806
807
808
809
810
811
812
813
814

815
816
817
818
819
820
821
822







-
+








-
+







    GC gc,			/* Use this GC. */
    int x, int y,		/* Upper left of bounding rect. */
    unsigned int width,		/* Width & height. */
    unsigned int height,
    int angle1,			/* Staring angle of arc. */
    int angle2)			/* Extent of arc. */
{
    MacDrawable *macWin = (MacDrawable *) d;
    MacDrawable *macWin = (MacDrawable *)d;
    TkMacOSXDrawingContext dc;
    int lw = gc->line_width;

    if (width == 0 || height == 0 || angle2 == 0) {
	return BadDrawable;
    }

    display->request++;
    if (!TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) {
    if (!TkMacOSXSetupDrawingContext(d, gc, &dc)) {
	return BadDrawable;
    }
    if (dc.context) {
	CGRect rect;
	double o = (lw % 2) ? .5 : 0;

	rect = CGRectMake(
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
842
843
844
845
846
847
848

849
850
851
852
853
854
855







-







	    CGContextStrokePath(dc.context);
	}
    }
    TkMacOSXRestoreDrawingContext(&dc);
    return Success;
}

#ifdef TK_MACOSXDRAW_UNUSED
/*
 *----------------------------------------------------------------------
 *
 * XDrawArcs --
 *
 *	Draws multiple circular or elliptical arcs. Each arc is specified by a
 *	rectangle and two angles. The center of the circle or ellipse is the
1203
1204
1205
1206
1207
1208
1209
1210

1211
1212
1213
1214
1215
1216

1217
1218
1219
1220
1221
1222
1223
872
873
874
875
876
877
878

879
880
881
882
883
884

885
886
887
888
889
890
891
892







-
+





-
+







XDrawArcs(
    Display *display,
    Drawable d,
    GC gc,
    XArc *arcArr,
    int nArcs)
{
    MacDrawable *macWin = (MacDrawable *) d;
    MacDrawable *macWin = (MacDrawable *)d;
    TkMacOSXDrawingContext dc;
    XArc *arcPtr;
    int i, lw = gc->line_width;

    display->request++;
    if (!TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) {
    if (!TkMacOSXSetupDrawingContext(d, gc, &dc)) {
	return BadDrawable;
    }
    if (dc.context) {
	CGRect rect;
	double o = (lw % 2) ? .5 : 0;

	for (i=0, arcPtr = arcArr; i < nArcs; i++, arcPtr++) {
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
922
923
924
925
926
927
928

929
930
931
932
933
934
935







-







		CGContextStrokePath(dc.context);
	    }
	}
    }
    TkMacOSXRestoreDrawingContext(&dc);
    return Success;
}
#endif

/*
 *----------------------------------------------------------------------
 *
 * XFillArc --
 *
 *	Draw a filled arc.
1282
1283
1284
1285
1286
1287
1288
1289

1290
1291
1292
1293
1294
1295
1296
1297
1298

1299
1300
1301
1302
1303
1304
1305
950
951
952
953
954
955
956

957
958
959
960
961
962
963
964
965

966
967
968
969
970
971
972
973







-
+








-
+







    GC gc,			/* Use this GC. */
    int x, int y,		/* Upper left of bounding rect. */
    unsigned int width,		/* Width & height. */
    unsigned int height,
    int angle1,			/* Staring angle of arc. */
    int angle2)			/* Extent of arc. */
{
    MacDrawable *macWin = (MacDrawable *) d;
    MacDrawable *macWin = (MacDrawable *)d;
    TkMacOSXDrawingContext dc;
    int lw = gc->line_width;

    if (width == 0 || height == 0 || angle2 == 0) {
	return BadDrawable;
    }

    display->request++;
    if (!TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) {
    if (!TkMacOSXSetupDrawingContext(d, gc, &dc)) {
	return BadDrawable;
    }
    if (dc.context) {
	CGRect rect;
	double o = (lw % 2) ? .5 : 0, u = 0;

	if (notAA(lw)) {
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358

1359
1360
1361
1362
1363
1364
1365
1366

1367
1368
1369
1370
1371
1372
1373


1374
1375
1376
1377
1378
1379
1380
1002
1003
1004
1005
1006
1007
1008

1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024

1025
1026
1027
1028
1029
1030
1031
1032

1033
1034
1035
1036
1037
1038


1039
1040
1041
1042
1043
1044
1045
1046
1047







-
















-
+







-
+





-
-
+
+







	    CGContextFillPath(dc.context);
	}
    }
    TkMacOSXRestoreDrawingContext(&dc);
    return Success;
}

#ifdef TK_MACOSXDRAW_UNUSED
/*
 *----------------------------------------------------------------------
 *
 * XFillArcs --
 *
 *	Draw a filled arc.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Draws a filled arc for each array element on the specified drawable.
 *
 *----------------------------------------------------------------------
 */

void
int
XFillArcs(
    Display *display,
    Drawable d,
    GC gc,
    XArc *arcArr,
    int nArcs)
{
    MacDrawable *macWin = (MacDrawable *) d;
    MacDrawable *macWin = (MacDrawable *)d;
    TkMacOSXDrawingContext dc;
    XArc * arcPtr;
    int i, lw = gc->line_width;

    display->request++;
    if (!TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) {
	return;
    if (!TkMacOSXSetupDrawingContext(d, gc, &dc)) {
	return BadDrawable;
    }
    if (dc.context) {
	CGRect rect;
	double o = (lw % 2) ? .5 : 0, u = 0;

	if (notAA(lw)) {
	    o += NON_AA_CG_OFFSET/2;
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437

1438
1439
1440
1441
1442
1443
1444
1445
1446
1081
1082
1083
1084
1085
1086
1087

















1088
1089

1090
1091
1092
1093
1094
1095
1096







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+

-







		CGContextAddPath(dc.context, p);
		CGPathRelease(p);
		CGContextFillPath(dc.context);
	    }
	}
    }
    TkMacOSXRestoreDrawingContext(&dc);
}
#endif

#ifdef TK_MACOSXDRAW_UNUSED
/*
 *----------------------------------------------------------------------
 *
 * XMaxRequestSize --
 *
 *----------------------------------------------------------------------
 */

long
XMaxRequestSize(
    Display *display)
{
    return (SHRT_MAX / 4);
    return Success;
}
#endif

/*
 *----------------------------------------------------------------------
 *
 * TkScrollWindow --
 *
 *	Scroll a rectangle of the specified window and accumulate a damage
1455
1456
1457
1458
1459
1460
1461
1462

1463
1464
1465
1466

1467
1468
1469
1470


1471
1472
1473
1474
1475
1476
1477
1105
1106
1107
1108
1109
1110
1111

1112
1113
1114
1115

1116
1117
1118


1119
1120
1121
1122
1123
1124
1125
1126
1127







-
+



-
+


-
-
+
+







 *
 *----------------------------------------------------------------------
 */

int
TkScrollWindow(
    Tk_Window tkwin,		/* The window to be scrolled. */
    GC gc,			/* GC for window to be scrolled. */
    TCL_UNUSED(GC),			/* GC for window to be scrolled. */
    int x, int y,		/* Position rectangle to be scrolled. */
    int width, int height,
    int dx, int dy,		/* Distance rectangle should be moved. */
    TkRegion damageRgn)		/* Region to accumulate damage in. */
    Region damageRgn)		/* Region to accumulate damage in. */
{
    Drawable drawable = Tk_WindowId(tkwin);
    MacDrawable *macDraw = (MacDrawable *) drawable;
    TKContentView *view = (TKContentView *) TkMacOSXDrawableView(macDraw);
    MacDrawable *macDraw = (MacDrawable *)drawable;
    TKContentView *view = (TKContentView *)TkMacOSXGetNSViewForDrawable(macDraw);
    CGRect srcRect, dstRect;
    HIShapeRef dmgRgn = NULL, extraRgn = NULL;
    NSRect bounds, visRect, scrollSrc, scrollDst;
    int result = 0;

    if (view) {
  	/*
1551
1552
1553
1554
1555
1556
1557
1558
1559


1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570

1571
1572
1573
1574


1575
1576
1577
1578



1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590

1591
1592

1593
1594
1595
1596
1597

1598
1599
1600
1601
1602





1603
1604
1605
1606


1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618


1619
1620
1621
1622
1623

1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654

1655
1656
1657
1658
1659

1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672








1673
1674
1675
1676
1677
1678





































1679
1680

1681
1682
1683
1684
1685
1686
1687
1688
1689






1690
1691
1692
1693
1694
1695
1696







1697
1698
1699
1700
1701
1702





1703

1704
1705
1706
1707





1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726


















1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737










1738
1739
1740
1741
1742
1743
1744
1745
1746



1747
1748
1749
1750
1751
1752
1753
1754
1755
1756










1757
1758
1759
1760
1761
1762
1763
1764
1765








1766
1767
1768
1769



1770
1771
1772
1773
1774
1775

1776
1777
1778
1779
1780
1781
1782
1783
1784
1785

1786
1787
1788
1789
1790
1791
1792
1201
1202
1203
1204
1205
1206
1207


1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219

1220
1221
1222


1223
1224
1225
1226
1227

1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238

1239
1240

1241
1242

1243
1244

1245
1246

1247

1248
1249
1250

1251
1252
1253
1254
1255
1256
1257
1258

1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270


1271
1272
1273
1274
1275
1276

1277































1278





1279







1280
1281
1282
1283
1284

1285
1286
1287
1288
1289
1290
1291
1292
1293





1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331

1332
1333
1334







1335
1336
1337
1338
1339
1340
1341






1342
1343
1344
1345
1346
1347
1348
1349





1350
1351
1352
1353
1354
1355
1356




1357
1358
1359
1360
1361



















1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380










1381
1382
1383
1384
1385
1386
1387
1388
1389
1390



1391





1392
1393
1394
1395









1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406








1407
1408
1409
1410
1411
1412
1413
1414




1415
1416
1417


1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440







-
-
+
+










-
+


-
-
+
+



-
+
+
+








-


-
+

-
+

-


-
+
-



-
+
+
+
+
+



-
+
+










-
-
+
+




-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
+
-
-
-
-
-
-
-





-
+
+
+
+
+
+
+
+

-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+


-
-
-
-
-
-
-
+
+
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
-
+
+
+
+
+

+
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-

-
-
-
-
-
+
+
+

-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
-
-




+










+







 *	None.
 *
 *----------------------------------------------------------------------
 */

void
TkMacOSXSetUpGraphicsPort(
    GC gc,			/* GC to apply to current port. */
    void *destPort)
    TCL_UNUSED(GC),			/* GC to apply to current port. */
    TCL_UNUSED(void *))
{
    Tcl_Panic("TkMacOSXSetUpGraphicsPort: Obsolete, no more QD!");
}


/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXSetUpDrawingContext --
 *
 *	Set up a drawing context for the given drawable and GC.
 *	Set up a drawing context for the given drawable from an X GC.
 *
 * Results:
 *	Boolean indicating whether it is ok to draw; if false, drawing context
 *	was not setup, so do not attempt to draw and do not call
 *	Boolean indicating whether it is ok to draw; if false, the drawing
 *	context was not setup, so do not attempt to draw and do not call
 *	TkMacOSXRestoreDrawingContext().
 *
 * Side effects:
 *	None.
 *	May modify or create the drawable's graphics context.  May expand the
 *      drawable's dirty rectangle.  When the result is true The dcPtr
 *      parameter is set to reference the new or updated drawing context.
 *
 *----------------------------------------------------------------------
 */

Bool
TkMacOSXSetupDrawingContext(
    Drawable d,
    GC gc,
    int useCG,			/* advisory only ! */
    TkMacOSXDrawingContext *dcPtr)
{
    MacDrawable *macDraw = (MacDrawable *) d;
    MacDrawable *macDraw = (MacDrawable *)d;
    Bool canDraw = true;
    NSWindow *win = NULL;
    TKContentView *view = nil;
    TkMacOSXDrawingContext dc = {};
    CGRect clipBounds;

    /*
     * If the drawable is not a pixmap and it has an associated NSWindow then
     * If the drawable is not a pixmap, get the associated NSView.
     * we know we are drawing to a window.
     */

    if (!(macDraw->flags & TK_IS_PIXMAP)) {
	win = TkMacOSXDrawableWindow(d);
	view = (TKContentView *)TkMacOSXGetNSViewForDrawable(d);
	if (!view) {
	    Tcl_Panic("TkMacOSXSetupDrawingContext(): "
		    "no NSView to draw into !");
	}
    }

    /*
     * Check that we have a non-empty clipping region.
     * Intersect the drawable's clipping region with the region stored in the
     * X GC.  If the resulting region is empty, don't do any drawing.
     */

    dc.clipRgn = TkMacOSXGetClipRgn(d);
    ClipToGC(d, gc, &dc.clipRgn);
    if (dc.clipRgn && HIShapeIsEmpty(dc.clipRgn)) {
	canDraw = false;
	goto end;
    }

    /*
     * If we already have a CGContext, use it.  Otherwise, if we are drawing to
     * a window then we can get one from the window.
     * 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 = clipBounds = CGContextGetClipBoundingBox(dc.context);
	dc.portBounds = CGContextGetClipBoundingBox(dc.context);
    } else if (win) {
	NSView *view = TkMacOSXDrawableView(macDraw);

	if (!view) {
	    Tcl_Panic("TkMacOSXSetupDrawingContext(): "
		    "no NSView to draw into !");
	}

	/*
	 * We can only draw into the view when the current CGContext is valid
	 * and belongs to the view.  Validity can only be guaranteed inside of
	 * a view's drawRect or setFrame methods.  The isDrawing attribute
	 * tells us whether we are being called from one of those methods.
	 *
	 * If the CGContext is not valid then we mark our view as needing
	 * display in the bounding rectangle of the clipping region and
	 * return failure.  That rectangle should get drawn in a later call
	 * to drawRect.
	 *
	 * As an exception to the above, if mouse buttons are pressed at the
	 * moment when we fail to obtain a valid context we schedule the entire
	 * view for a redraw rather than just the clipping region.  The purpose
	 * of this is to make sure that scrollbars get updated correctly.
	 */

	if (![NSApp isDrawing] || view != [NSView focusView]) {
	    NSRect bounds = [view bounds];
	    NSRect dirtyNS = bounds;
	    if ([NSEvent pressedMouseButtons]) {
		[view setNeedsDisplay:YES];
	    } else {
    } else {
		CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1, .tx = 0,
					.ty = dirtyNS.size.height};
		if (dc.clipRgn) {
		    CGRect dirtyCG = NSRectToCGRect(dirtyNS);
		    HIShapeGetBounds(dc.clipRgn, &dirtyCG);
	NSRect drawingBounds, currentBounds;
		    dirtyNS = NSRectToCGRect(CGRectApplyAffineTransform(dirtyCG, t));
		}
		[view setNeedsDisplayInRect:dirtyNS];
	    }
	    canDraw = false;
	    goto end;
	}

	dc.view = view;
	dc.context = GET_CGCONTEXT;
	dc.portBounds = NSRectToCGRect([view bounds]);
	if (dc.clipRgn) {
	    clipBounds = CGContextGetClipBoundingBox(dc.context);
	    CGRect clipBounds;
	    CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1, .tx = 0,
				    .ty = [view bounds].size.height};
	    HIShapeGetBounds(dc.clipRgn, &clipBounds);
	    clipBounds = CGRectApplyAffineTransform(clipBounds, t);
	    drawingBounds = NSRectFromCGRect(clipBounds);
	} else {
	    drawingBounds = [view bounds];
	}
    } else {
	Tcl_Panic("TkMacOSXSetupDrawingContext(): "
		"no context to draw into !");
    }


	/*
	 * We can only draw into the NSView which is the current focusView.
	 * When the current [NSView focusView] is nil, the CGContext for
	 * [NSGraphicsContext currentContext] is nil.  Otherwise the current
	 * CGContext draws into the current focusView.  An NSView is guaranteed
	 * to be the focusView when its drawRect or setFrame methods are
	 * running.  Prior to OSX 10.14 it was also possible to call the
	 * lockFocus method to force an NSView to become the current focusView.
	 * But that method was deprecated in 10.14 and so is no longer used by
	 * Tk.  Instead, if the view is not the current focusView then we add
	 * the drawing bounds to its dirty rectangle and return false.  The
	 * part of the view inside the drawing bounds will get redrawn during
	 * the next call to its drawRect method.
	 */

	if (view != [NSView focusView]) {
	    [view addTkDirtyRect:drawingBounds];
	    canDraw = false;
	    goto end;
	}

	/*
	 * Drawing will also fail when the view is the current focusView but
	 * the clipping rectangle set by drawRect does not contain the clipping
	 * region of our drawing context.  (See bug [2a61eca3a8].)  If part of
	 * 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 = NSRectFromCGRect(CGContextGetClipBoundingBox(dc.context));
	if (!NSContainsRect(currentBounds, drawingBounds)) {
	    [view addTkDirtyRect:drawingBounds];
	}
    }

    /*
     * Configure the drawing context.
     * Finish configuring the drawing context.
     */

    if (dc.context) {
	CGAffineTransform t = {
	    .a = 1, .b = 0,
	    .c = 0, .d = -1,
	    .tx = 0,
	    .ty = dc.portBounds.size.height
	};
    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;
	CGContextSaveGState(dc.context);
	CGContextSetTextDrawingMode(dc.context, kCGTextFill);
	CGContextConcatCTM(dc.context, t);
	if (dc.clipRgn) {
    dc.portBounds.origin.x += macDraw->xOff;
    dc.portBounds.origin.y += macDraw->yOff;
    CGContextSaveGState(dc.context);
    CGContextSetTextDrawingMode(dc.context, kCGTextFill);
    CGContextConcatCTM(dc.context, t);
    if (dc.clipRgn) {

#ifdef TK_MAC_DEBUG_DRAWING
	    CGContextSaveGState(dc.context);
	    ChkErr(HIShapeReplacePathInCGContext, dc.clipRgn, dc.context);
	    CGContextSetRGBFillColor(dc.context, 1.0, 0.0, 0.0, 0.1);
	    CGContextEOFillPath(dc.context);
	    CGContextRestoreGState(dc.context);
	CGContextSaveGState(dc.context);
	ChkErr(HIShapeReplacePathInCGContext, dc.clipRgn, dc.context);
	CGContextSetRGBFillColor(dc.context, 1.0, 0.0, 0.0, 0.1);
	CGContextEOFillPath(dc.context);
	CGContextRestoreGState(dc.context);
#endif /* TK_MAC_DEBUG_DRAWING */

	    CGRect r;

	    if (!HIShapeIsRectangular(dc.clipRgn) || !CGRectContainsRect(
		    *HIShapeGetBounds(dc.clipRgn, &r),
	CGRect r;
	CGRect b = CGRectApplyAffineTransform(
	    CGContextGetClipBoundingBox(dc.context), t);
	if (!HIShapeIsRectangular(dc.clipRgn) ||
	    !CGRectContainsRect(*HIShapeGetBounds(dc.clipRgn, &r), b)) {
		    CGRectApplyAffineTransform(clipBounds, t))) {
		ChkErr(HIShapeReplacePathInCGContext, dc.clipRgn, dc.context);
		CGContextEOClip(dc.context);
	    }
	}
	if (gc) {
	    static const CGLineCap cgCap[] = {
		[CapNotLast] = kCGLineCapButt,
		[CapButt] = kCGLineCapButt,
		[CapRound] = kCGLineCapRound,
		[CapProjecting] = kCGLineCapSquare,
	    };
	    static const CGLineJoin cgJoin[] = {
		[JoinMiter] = kCGLineJoinMiter,
		[JoinRound] = kCGLineJoinRound,
		[JoinBevel] = kCGLineJoinBevel,
	    };
	    bool shouldAntialias;
	    double w = gc->line_width;
	    ChkErr(HIShapeReplacePathInCGContext, dc.clipRgn, dc.context);
	    CGContextEOClip(dc.context);
	}
    }
    if (gc) {
	static const CGLineCap cgCap[] = {
	    [CapNotLast] = kCGLineCapButt,
	    [CapButt] = kCGLineCapButt,
	    [CapRound] = kCGLineCapRound,
	    [CapProjecting] = kCGLineCapSquare,
	};
	static const CGLineJoin cgJoin[] = {
	    [JoinMiter] = kCGLineJoinMiter,
	    [JoinRound] = kCGLineJoinRound,
	    [JoinBevel] = kCGLineJoinBevel,
	};
	bool shouldAntialias = !notAA(gc->line_width);
	double w = gc->line_width;

	    TkMacOSXSetColorInContext(gc, gc->foreground, dc.context);
	    if (win) {
		CGContextSetPatternPhase(dc.context, CGSizeMake(
			dc.portBounds.size.width, dc.portBounds.size.height));
	    }
	    if (gc->function != GXcopy) {
		TkMacOSXDbgMsg("Logical functions other than GXcopy are "
			"not supported for CG drawing!");
	    }

	TkMacOSXSetColorInContext(gc, gc->foreground, dc.context);
	if (view) {
	    CGContextSetPatternPhase(dc.context, CGSizeMake(
	        dc.portBounds.size.width, dc.portBounds.size.height));
	}
	if (gc->function != GXcopy) {
	    TkMacOSXDbgMsg("Logical functions other than GXcopy are "
			   "not supported for CG drawing!");
	}
	if (!shouldAntialias) {
	    /*
	     * When should we antialias?
	     */

	    shouldAntialias = !notAA(gc->line_width);
	    if (!shouldAntialias) {
		/*
		 * Make non-antialiased CG drawing look more like X11.
		 */
	    /*
	     * Make non-antialiased CG drawing look more like X11.
	     */

		w -= (gc->line_width ? NON_AA_CG_OFFSET : 0);
	    }
	    CGContextSetShouldAntialias(dc.context, shouldAntialias);
	    CGContextSetLineWidth(dc.context, w);
	    if (gc->line_style != LineSolid) {
		int num = 0;
		char *p = &gc->dashes;
		CGFloat dashOffset = gc->dash_offset;
		CGFloat lengths[10];
	    w -= (gc->line_width ? NON_AA_CG_OFFSET : 0);
	}
	CGContextSetShouldAntialias(dc.context, shouldAntialias);
	CGContextSetLineWidth(dc.context, w);
	if (gc->line_style != LineSolid) {
	    int num = 0;
	    char *p = &gc->dashes;
	    CGFloat dashOffset = gc->dash_offset;
	    dashOffset -= (gc->line_width % 2) ? 0.5 : 0.0;
	    CGFloat lengths[10];

		while (p[num] != '\0' && num < 10) {
		    lengths[num] = p[num];
		    num++;
		}
		CGContextSetLineDash(dc.context, dashOffset, lengths, num);
	    }
	    if ((unsigned) gc->cap_style < sizeof(cgCap)/sizeof(CGLineCap)) {
		CGContextSetLineCap(dc.context,
	    while (p[num] != '\0' && num < 10) {
		lengths[num] = p[num];
		num++;
	    }
	    CGContextSetLineDash(dc.context, dashOffset, lengths, num);
	}
	if ((unsigned) gc->cap_style < sizeof(cgCap)/sizeof(CGLineCap)) {
	    CGContextSetLineCap(dc.context, cgCap[(unsigned) gc->cap_style]);
			cgCap[(unsigned) gc->cap_style]);
	    }
	    if ((unsigned)gc->join_style < sizeof(cgJoin)/sizeof(CGLineJoin)) {
		CGContextSetLineJoin(dc.context,
	}
	if ((unsigned)gc->join_style < sizeof(cgJoin)/sizeof(CGLineJoin)) {
	    CGContextSetLineJoin(dc.context, cgJoin[(unsigned) gc->join_style]);
			cgJoin[(unsigned) gc->join_style]);
	    }
	}
    }

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));
	}
    }
#endif

    if (!canDraw && dc.clipRgn) {
	CFRelease(dc.clipRgn);
	dc.clipRgn = NULL;
    }
    *dcPtr = dc;
    return canDraw;
}
1840
1841
1842
1843
1844
1845
1846
1847

1848
1849
1850
1851
1852
1853
1854
1855


1856
1857
1858
1859
1860
1861
1862
1488
1489
1490
1491
1492
1493
1494

1495
1496
1497
1498
1499
1500
1501
1502

1503
1504
1505
1506
1507
1508
1509
1510
1511







-
+







-
+
+







 *----------------------------------------------------------------------
 */

HIShapeRef
TkMacOSXGetClipRgn(
    Drawable drawable)		/* Drawable. */
{
    MacDrawable *macDraw = (MacDrawable *) drawable;
    MacDrawable *macDraw = (MacDrawable *)drawable;
    HIShapeRef clipRgn = NULL;

    if (macDraw->winPtr && macDraw->flags & TK_CLIP_INVALID) {
	TkMacOSXUpdateClipRgn(macDraw->winPtr);
#ifdef TK_MAC_DEBUG_DRAWING
	TkMacOSXDbgMsg("%s", macDraw->winPtr->pathName);

	NSView *view = TkMacOSXDrawableView(macDraw);
	NSView *view = TkMacOSXGetNSViewForDrawable(macDraw);
	CGContextRef context = GET_CGCONTEXT;

	CGContextSaveGState(context);
	CGContextConcatCTM(context, CGAffineTransformMake(1.0, 0.0, 0.0,
	      -1.0, 0.0, [view bounds].size.height));
	ChkErr(HIShapeReplacePathInCGContext, macDraw->visRgn, context);
	CGContextSetRGBFillColor(context, 0.0, 1.0, 0.0, 0.1);
	CGContextEOFillPath(context);
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917

1918
1919
1920
1921
1922

1923
1924
1925
1926
1927
1928
1929
1520
1521
1522
1523
1524
1525
1526























1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542

1543
1544
1545
1546
1547

1548
1549
1550
1551
1552
1553
1554
1555







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
















-
+




-
+







    }
    return clipRgn;
}

/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXSetUpClippingRgn --
 *
 *	Set up the clipping region so that drawing only occurs on the specified
 *	X subwindow.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void
TkMacOSXSetUpClippingRgn(
    Drawable drawable)		/* Drawable to update. */
{
}

/*
 *----------------------------------------------------------------------
 *
 * TkpClipDrawableToRect --
 *
 *	Clip all drawing into the drawable d to the given rectangle. If width
 *	or height are negative, reset to no clipping.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Subsequent drawing into d is offset and clipped as specified.
 *
 *----------------------------------------------------------------------
 */

void
TkpClipDrawableToRect(
    Display *display,
    TCL_UNUSED(Display *),
    Drawable d,
    int x, int y,
    int width, int height)
{
    MacDrawable *macDraw = (MacDrawable *) d;
    MacDrawable *macDraw = (MacDrawable *)d;

    if (macDraw->drawRgn) {
	CFRelease(macDraw->drawRgn);
	macDraw->drawRgn = NULL;
    }
    if (width >= 0 && height >= 0) {
	CGRect clipRect = CGRectMake(x + macDraw->xOff, y + macDraw->yOff,
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972




1973
1974
1975

1976
1977
1978
1979
1980
1981
1982
1983
1984

1985
1986
1987
1988
1989
1990
1991
1588
1589
1590
1591
1592
1593
1594




1595
1596
1597
1598
1599
1600

1601
1602
1603
1604
1605
1606
1607
1608
1609

1610
1611
1612
1613
1614
1615
1616
1617







-
-
-
-
+
+
+
+


-
+








-
+







static void
ClipToGC(
    Drawable d,
    GC gc,
    HIShapeRef *clipRgnPtr) /* must point to initialized variable */
{
    if (gc && gc->clip_mask &&
	    ((TkpClipMask *) gc->clip_mask)->type == TKP_CLIP_REGION) {
	TkRegion gcClip = ((TkpClipMask *) gc->clip_mask)->value.region;
	int xOffset = ((MacDrawable *) d)->xOff + gc->clip_x_origin;
	int yOffset = ((MacDrawable *) d)->yOff + gc->clip_y_origin;
	    ((TkpClipMask *)gc->clip_mask)->type == TKP_CLIP_REGION) {
	Region gcClip = ((TkpClipMask *)gc->clip_mask)->value.region;
	int xOffset = ((MacDrawable *)d)->xOff + gc->clip_x_origin;
	int yOffset = ((MacDrawable *)d)->yOff + gc->clip_y_origin;
	HIShapeRef clipRgn = *clipRgnPtr, gcClipRgn;

	TkMacOSXOffsetRegion(gcClip, xOffset, yOffset);
	XOffsetRegion(gcClip, xOffset, yOffset);
	gcClipRgn = TkMacOSXGetNativeRegion(gcClip);
	if (clipRgn) {
	    *clipRgnPtr = HIShapeCreateIntersection(gcClipRgn, clipRgn);
	    CFRelease(clipRgn);
	} else {
	    *clipRgnPtr = HIShapeCreateCopy(gcClipRgn);
	}
	CFRelease(gcClipRgn);
	TkMacOSXOffsetRegion(gcClip, -xOffset, -yOffset);
	XOffsetRegion(gcClip, -xOffset, -yOffset);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXMakeStippleMap --
2001
2002
2003
2004
2005
2006
2007
2008
2009


2010
2011
2012
2013
2014
2015
2016
1627
1628
1629
1630
1631
1632
1633


1634
1635
1636
1637
1638
1639
1640
1641
1642







-
-
+
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

void *
TkMacOSXMakeStippleMap(
    Drawable drawable,		/* Window to apply stipple. */
    Drawable stipple)		/* The stipple pattern. */
    TCL_UNUSED(Drawable),	/* Window to apply stipple. */
    TCL_UNUSED(Drawable))	/* The stipple pattern. */
{
    return NULL;
}

/*
 *----------------------------------------------------------------------
 *
2053
2054
2055
2056
2057
2058
2059
2060

2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075

2076

2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094

2095
2096
2097


2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
1679
1680
1681
1682
1683
1684
1685

1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700

1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720

1721



1722
1723

1724
1725
1726
1727
1728
1729
1730
1731
1732
1733







-
+














-
+

+

















-
+
-
-
-
+
+
-










	}
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TkpDrawFrame --
 * TkpDrawFrameEx --
 *
 *	This procedure draws the rectangular frame area. If the user has
 *	requested themeing, it draws with the background theme.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Draws inside the tkwin area.
 *
 *----------------------------------------------------------------------
 */

void
TkpDrawFrame(
TkpDrawFrameEx(
    Tk_Window tkwin,
    Drawable drawable,
    Tk_3DBorder border,
    int highlightWidth,
    int borderWidth,
    int relief)
{
    if (useThemedToplevel && Tk_IsTopLevel(tkwin)) {
	static Tk_3DBorder themedBorder = NULL;

	if (!themedBorder) {
	    themedBorder = Tk_Get3DBorder(NULL, tkwin,
		    "systemWindowHeaderBackground");
	}
	if (themedBorder) {
	    border = themedBorder;
	}
    }

    Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin),
    Tk_Fill3DRectangle(tkwin, drawable, border, highlightWidth,
	    border, highlightWidth, highlightWidth,
	    Tk_Width(tkwin) - 2 * highlightWidth,
	    Tk_Height(tkwin) - 2 * highlightWidth,
	    highlightWidth, Tk_Width(tkwin) - 2 * highlightWidth,
	    Tk_Height(tkwin) - 2 * highlightWidth, borderWidth, relief);
	    borderWidth, relief);
}

/*
 * Local Variables:
 * mode: objc
 * c-basic-offset: 4
 * fill-column: 79
 * coding: utf-8
 * End:
 */
Changes to macosx/tkMacOSXEmbed.c.
1
2
3
4
5
6
7
8
9
10
11
12



13
14
15
16
17
18
19
1
2
3
4
5
6
7
8
9



10
11
12
13
14
15
16
17
18
19









-
-
-
+
+
+







/*
 * tkMacOSXEmbed.c --
 *
 *	This file contains platform-specific procedures for theMac to provide
 *	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 <[email protected]>
 * Copyright © 1996-1997 Sun Microsystems, Inc.
 * Copyright © 2001-2009 Apple Inc.
 * Copyright © 2006-2009 Daniel A. Steffen <[email protected]>
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tkMacOSXPrivate.h"
#include "tkBusy.h"
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
39
40
41
42
43
44
45





46
47
48
49
50
51
52
53
54
55
56
57
58
59




































60
61
62
63
64
65
66







-
-
-
-
-














-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







    struct Container *nextPtr;	/* Next in list of all containers in this
				 * process. */
} Container;

static Container *firstContainerPtr = NULL;
				/* First in list of all containers managed by
				 * this process. */
/*
 * Globals defined in this file:
 */

TkMacOSXEmbedHandler *tkMacOSXEmbedHandler = NULL;

/*
 * Prototypes for static procedures defined in this file:
 */

static void	ContainerEventProc(ClientData clientData, XEvent *eventPtr);
static void	EmbeddedEventProc(ClientData clientData, XEvent *eventPtr);
static void	EmbedActivateProc(ClientData clientData, XEvent *eventPtr);
static void	EmbedFocusProc(ClientData clientData, XEvent *eventPtr);
static void	EmbedGeometryRequest(Container *containerPtr, int width,
		    int height);
static void	EmbedSendConfigure(Container *containerPtr);
static void	EmbedStructureProc(ClientData clientData, XEvent *eventPtr);
static void	EmbedWindowDeleted(TkWindow *winPtr);

/*
 *----------------------------------------------------------------------
 *
 * Tk_MacOSXSetEmbedHandler --
 *
 *	Registers a handler for an in process form of embedding, like Netscape
 *	plugins, where Tk is loaded into the process, but does not control the
 *	main window
 *
 * Results:
 *	None
 *
 * Side effects:
 *	The embed handler is set.
 *
 *----------------------------------------------------------------------
 */

void
Tk_MacOSXSetEmbedHandler(
    Tk_MacOSXEmbedRegisterWinProc *registerWinProc,
    Tk_MacOSXEmbedGetGrafPortProc *getPortProc,
    Tk_MacOSXEmbedMakeContainerExistProc *containerExistProc,
    Tk_MacOSXEmbedGetClipProc *getClipProc,
    Tk_MacOSXEmbedGetOffsetInParentProc *getOffsetProc)
{
    if (tkMacOSXEmbedHandler == NULL) {
	tkMacOSXEmbedHandler = ckalloc(sizeof(TkMacOSXEmbedHandler));
    }
    tkMacOSXEmbedHandler->registerWinProc = registerWinProc;
    tkMacOSXEmbedHandler->getPortProc = getPortProc;
    tkMacOSXEmbedHandler->containerExistProc = containerExistProc;
    tkMacOSXEmbedHandler->getClipProc = getClipProc;
    tkMacOSXEmbedHandler->getOffsetProc = getOffsetProc;
}

/*
 *----------------------------------------------------------------------
 *
 * TkpMakeWindow --
 *
 *	Creates an X Window (Mac subwindow).
117
118
119
120
121
122
123

124
125
126
127
128
129
130
131
132
133
134
135
136
137

138
139
140
141
142
143
144
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96

97
98
99
100
101
102
103
104







+













-
+








Window
TkpMakeWindow(
    TkWindow *winPtr,
    Window parent)
{
    MacDrawable *macWin;
    (void)parent;

    /*
     * If this window is marked as embedded then the window structure should
     * have already been created in the TkpUseWindow function.
     */

    if (Tk_IsEmbedded(winPtr)) {
	macWin = winPtr->privatePtr;
    } else {
	/*
	 * Allocate sub window
	 */

	macWin = ckalloc(sizeof(MacDrawable));
	macWin = (MacDrawable *)ckalloc(sizeof(MacDrawable));
	if (macWin == NULL) {
	    winPtr->privatePtr = NULL;
	    return None;
	}
	macWin->winPtr = winPtr;
	winPtr->privatePtr = macWin;
	macWin->visRgn = NULL;
302
303
304
305
306
307
308
309

310
311
312
313
314
315
316
262
263
264
265
266
267
268

269
270
271
272
273
274
275
276







-
+







	}
    }

    /*
     * Make the embedded window.
     */

    macWin = ckalloc(sizeof(MacDrawable));
    macWin = (MacDrawable *)ckalloc(sizeof(MacDrawable));
    if (macWin == NULL) {
	winPtr->privatePtr = NULL;
	return TCL_ERROR;
    }

    macWin->winPtr = winPtr;
    macWin->view = nil;
388
389
390
391
392
393
394
395

396
397
398
399
400
401
402
348
349
350
351
352
353
354

355
356
357
358
359
360
361
362







-
+








    /*
     * Register the window as a container so that, for example, we can make
     * sure the argument to -use is valid.
     */

    Tk_MakeWindowExist(tkwin);
    containerPtr = ckalloc(sizeof(Container));
    containerPtr = (Container *)ckalloc(sizeof(Container));
    containerPtr->parent = Tk_WindowId(tkwin);
    containerPtr->parentPtr = winPtr;
    containerPtr->embedded = None;
    containerPtr->embeddedPtr = NULL;
    containerPtr->nextPtr = firstContainerPtr;
    firstContainerPtr = containerPtr;
    winPtr->flags |= TK_CONTAINER;
442
443
444
445
446
447
448
449

450
451
452
453
454
455
456
402
403
404
405
406
407
408

409
410
411
412
413
414
415
416







-
+







    TkWindow *winPtr)		/* Tk's structure for an embedded window. */
{
    Container *containerPtr;

    for (containerPtr = firstContainerPtr; containerPtr != NULL;
	    containerPtr = containerPtr->nextPtr) {
	if (containerPtr->embeddedPtr == winPtr) {
	    return (MacDrawable *) containerPtr->parent;
	    return (MacDrawable *)containerPtr->parent;
	}
    }
    Tcl_Panic("TkMacOSXContainerId couldn't find window");
    return NULL;
}

/*
555
556
557
558
559
560
561
562

563
564
565
566
567
568
569
570
571

572
573
574
575
576
577
578
515
516
517
518
519
520
521

522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539







-
+









+







 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TkpTestembedCmd(
    ClientData clientData,	/* Main window for application. */
    ClientData dummy,	/* Main window for application. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])		/* Argument strings. */
{
    int all;
    Container *containerPtr;
    Tcl_DString dString;
    char buffer[50];
    Tcl_Interp *embeddedInterp = NULL, *parentInterp = NULL;
    (void)dummy;

    if ((objc > 1) && (strcmp(Tcl_GetString(objv[1]), "all") == 0)) {
	all = 1;
    } else {
	all = 0;
    }
    Tcl_DStringInit(&dString);
592
593
594
595
596
597
598

599

600
601
602
603
604
605
606
553
554
555
556
557
558
559
560

561
562
563
564
565
566
567
568







+
-
+







	/*
	 * Parent id
	 */

	if (containerPtr->parent == None) {
	    Tcl_DStringAppendElement(&dString, "");
	} else if (all) {
	    sprintf(buffer, "0x%" TCL_Z_MODIFIER "x",
	    sprintf(buffer, "0x%lx", containerPtr->parent);
		    (size_t) containerPtr->parent);
	    Tcl_DStringAppendElement(&dString, buffer);
	} else {
	    Tcl_DStringAppendElement(&dString, "XXX");
	}

	/*
	 * Parent pathName
662
663
664
665
666
667
668



669
670
671
672
673
674
675
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640







+
+
+







void
TkpRedirectKeyEvent(
    TkWindow *winPtr,		/* Window to which the event was originally
				 * reported. */
    XEvent *eventPtr)		/* X event to redirect (should be KeyPress or
				 * KeyRelease). */
{
    (void)winPtr;
    (void)eventPtr;

    /* TODO: Implement this or decide it definitely needs no implementation */
}

/*
 *----------------------------------------------------------------------
 *
 * TkpGetOtherWindow --
849
850
851
852
853
854
855
856

857
858
859
860
861
862
863
814
815
816
817
818
819
820

821
822
823
824
825
826
827
828







-
+







    } else if (eventPtr->type == DestroyNotify) {
	/*
	 * It is not clear whether the container should be destroyed
	 * when an embedded window is destroyed.  See ticket [67384bce7d].
	 * Here we are following unix, by destroying the container.
	 */

	Tk_DestroyWindow((Tk_Window) winPtr);
	Tk_DestroyWindow((Tk_Window)winPtr);
    }
    Tk_DeleteErrorHandler(errHandler);
}

/*
 *----------------------------------------------------------------------
 *
898
899
900
901
902
903
904
905
906


907
908
909
910
911
912
913
863
864
865
866
867
868
869


870
871
872
873
874
875
876
877
878







-
-
+
+







	    /*
	     * Ignore errors, since the embedded application could have
	     * deleted its window.
	     */

	    errHandler = Tk_CreateErrorHandler(eventPtr->xfocus.display, -1,
		    -1, -1, NULL, NULL);
	    Tk_MoveResizeWindow((Tk_Window) containerPtr->embeddedPtr, 0, 0,
		    (unsigned) Tk_Width((Tk_Window) containerPtr->parentPtr),
	    Tk_MoveResizeWindow((Tk_Window)containerPtr->embeddedPtr, 0, 0,
		    (unsigned) Tk_Width((Tk_Window)containerPtr->parentPtr),
		    (unsigned) Tk_Height((Tk_Window)containerPtr->parentPtr));
	    Tk_DeleteErrorHandler(errHandler);
	}
    } else if (eventPtr->type == DestroyNotify) {
	EmbedWindowDeleted(containerPtr->parentPtr);
    }
}
1044
1045
1046
1047
1048
1049
1050
1051
1052


1053
1054
1055
1056
1057
1058
1059
1060
1061
1009
1010
1011
1012
1013
1014
1015


1016
1017


1018
1019
1020
1021
1022
1023
1024







-
-
+
+
-
-







     * the container window. We need to send a Configure event back to the
     * embedded application if we decide not to honor its request; to make this
     * happen, process all idle event handlers synchronously here (so that the
     * geometry managers have had a chance to do whatever they want to do), and
     * if the window's size didn't change then generate a configure event.
     */

    Tk_GeometryRequest((Tk_Window) winPtr, width, height);
    while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {
    Tk_GeometryRequest((Tk_Window)winPtr, width, height);
    while (Tcl_DoOneEvent(TCL_IDLE_EVENTS|TCL_TIMER_EVENTS|TCL_DONT_WAIT)) {}
	/* Empty loop body. */
    }
    if ((winPtr->changes.width != width)
	    || (winPtr->changes.height != height)) {
	EmbedSendConfigure(containerPtr);
    }
}

/*
1079
1080
1081
1082
1083
1084
1085

1086
1087
1088
1089
1090
1091
1092
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056







+







 *----------------------------------------------------------------------
 */

static void
EmbedSendConfigure(
    Container *containerPtr)	/* Information about the embedding. */
{
    (void)containerPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * EmbedWindowDeleted --
 *
1186
1187
1188
1189
1190
1191
1192

1193
1194
1195
1196
1197
1198

1199
1200
1201
1202
1203
1204
1205


1206
1207
1208
1209
1210
1211
1212
1213
1214
1215





1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198







+






+







+
+










+
+
+
+
+










 *----------------------------------------------------------------------
 */

void
TkpShowBusyWindow(
    TkBusy busy)
{
    (void)busy;
}

void
TkpHideBusyWindow(
    TkBusy busy)
{
    (void)busy;
}

void
TkpMakeTransparentWindowExist(
    Tk_Window tkwin,		/* Token for window. */
    Window parent)		/* Parent window. */
{
    (void)tkwin;
    (void)parent;
}

void
TkpCreateBusy(
    Tk_FakeWin *winPtr,
    Tk_Window tkRef,
    Window* parentPtr,
    Tk_Window tkParent,
    TkBusy busy)
{
    (void)winPtr;
    (void)tkRef;
    (void)parentPtr;
    (void)tkParent;
    (void)busy;
}

/*
 * Local Variables:
 * mode: objc
 * c-basic-offset: 4
 * fill-column: 79
 * coding: utf-8
 * End:
 */
Changes to macosx/tkMacOSXEntry.c.
1
2
3
4
5
6
7
8



9
10
11
12
13
14
15
1
2
3
4
5



6
7
8
9
10
11
12
13
14
15





-
-
-
+
+
+







/*
 * tkMacOSXEntry.c --
 *
 *	This file implements the native aqua entry widget.
 *
 * Copyright 2001, Apple Computer, Inc.
 * Copyright (c) 2006-2009 Daniel A. Steffen <[email protected]>
 * Copyright 2008-2009, Apple Inc.
 * Copyright © 2001 Apple Computer, Inc.
 * Copyright © 2006-2009 Daniel A. Steffen <[email protected]>
 * 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.
 */

#include "tkMacOSXPrivate.h"
#include "tkEntry.h"
88
89
90
91
92
93
94
95

96
97
98
99
100
101
102
88
89
90
91
92
93
94

95
96
97
98
99
100
101
102







-
+







    int isSpinbox)
{
    CGRect bounds;
    TkMacOSXDrawingContext dc;
    GC bgGC;
    Tk_Window tkwin = entryPtr->tkwin;
    int oldWidth = 0;
    MacDrawable *macDraw = (MacDrawable *) d;
    MacDrawable *macDraw = (MacDrawable *)d;
    const HIThemeFrameDrawInfo info = {
	.version = 0,
	.kind = kHIThemeFrameTextFieldSquare,
	.state = (entryPtr->state == STATE_DISABLED ? kThemeStateInactive :
		kThemeStateActive),
	.isFocused = (entryPtr->flags & GOT_FOCUS ? 1 : 0),
    };
151
152
153
154
155
156
157
158

159
160
161
162
163
164
165
151
152
153
154
155
156
157

158
159
160
161
162
163
164
165







-
+







     * 3 according to the Carbon docs.
     */

    bounds.origin.x = macDraw->xOff + MAC_OSX_FOCUS_WIDTH;
    bounds.origin.y = macDraw->yOff + MAC_OSX_FOCUS_WIDTH;
    bounds.size.width = Tk_Width(tkwin) - 2*MAC_OSX_FOCUS_WIDTH;
    bounds.size.height = Tk_Height(tkwin) - 2*MAC_OSX_FOCUS_WIDTH;
    if (!TkMacOSXSetupDrawingContext(d, NULL, 1, &dc)) {
    if (!TkMacOSXSetupDrawingContext(d, NULL, &dc)) {

	/*
	 * No graphics context is available.  If the widget is a Spinbox, we
	 * must restore its width before returning 0. (Ticket [273b6a4996].)
	 */

	if (isSpinbox) {
204
205
206
207
208
209
210
211

212
213
214
215
216
217
218
204
205
206
207
208
209
210

211
212
213
214
215
216
217
218







-
+







    Tk_Window tkwin = sbPtr->entry.tkwin;
    int height = Tk_Height(tkwin);
    int buttonHeight = height - 2 * MAC_OSX_FOCUS_WIDTH;
    int incDecWidth;
    TkMacOSXDrawingContext dc;
    XRectangle rects[1];
    GC bgGC;
    MacDrawable *macDraw = (MacDrawable *) d;
    MacDrawable *macDraw = (MacDrawable *)d;
    HIThemeButtonDrawInfo info = {
	.version = 0,
	.adornment = kThemeAdornmentNone,
    };

    /*
     * FIXME: RAISED really makes more sense
261
262
263
264
265
266
267
268

269
270
271
272
273
274
275
261
262
263
264
265
266
267

268
269
270
271
272
273
274
275







-
+







    bgGC = Tk_GCForColor(sbPtr->entry.highlightBgColorPtr, d);
    rects[0].x = Tk_Width(tkwin) - incDecWidth - 1;
    rects[0].y = 0;
    rects[0].width = incDecWidth + 1;
    rects[0].height = Tk_Height(tkwin);
    XFillRectangles(Tk_Display(tkwin), d, bgGC, rects, 1);

    if (!TkMacOSXSetupDrawingContext(d, NULL, 1, &dc)) {
    if (!TkMacOSXSetupDrawingContext(d, NULL, &dc)) {
	return 0;
    }
    ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL);
    TkMacOSXRestoreDrawingContext(&dc);
    return 1;
}

Changes to macosx/tkMacOSXEvent.c.
1
2
3
4
5
6
7
8



9
10
11
12
13
14
15

16
17
18
19
20
21
22
1
2
3
4
5



6
7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
22





-
-
-
+
+
+






-
+







/*
 * 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 <[email protected]>
 * Copyright © 1995-1997 Sun Microsystems, Inc.
 * Copyright © 2001-2009, Apple Inc.
 * Copyright © 2005-2009 Daniel A. Steffen <[email protected]>
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tkMacOSXPrivate.h"
#include "tkMacOSXEvent.h"
#include "tkMacOSXInt.h"
#include "tkMacOSXDebug.h"
#include "tkMacOSXConstants.h"

#pragma mark TKApplication(TKEvent)

enum {
    NSWindowWillMoveEventType = 20
100
101
102
103
104
105
106
107
108




109
110


111
112
113
114
115
116
117







118
119
120
121
122
123

124
125
126
127
128
129

130
131
132
133
134
135
136
137

138
139
140



141
142
143
144
145
146
147
148
149
150
151
100
101
102
103
104
105
106

107
108
109
110
111


112
113







114
115
116
117
118
119
120






121






122
123







124



125
126
127


128
129
130
131
132
133
134
135
136







-

+
+
+
+
-
-
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
+
-
-
-
-
-
-
+

-
-
-
-
-
-
-
+
-
-
-
+
+
+
-
-










    default:
	break; /* return theEvent */
    }
    return processedEvent;
}
@end

#pragma mark -
int
XSync(
    Display *display,
    TCL_UNUSED(Bool))

/*
{
    /*
 *----------------------------------------------------------------------
 *
 * TkMacOSXFlushWindows --
 *
 *	This routine is a stub called by XSync, which is called during the Tk
 *      update command.  The language specification does not require that the
 *      update command be synchronous but many of the tests implicitly assume
     *  The main use of XSync is by the update command, which alternates
     *  between running an event loop to process all events without waiting and
     *  calling XSync on all displays until no events are left.  There is
     *  nothing for the mac to do with respect to syncing its one display but
     *  it can (and, during regression testing, frequently does) happen that
     *  timer events fire during the event loop. Processing those here seems
     *  to make the update command work in a way that is more consistent with
 *      that it is.  It is definitely asynchronous on macOS since many idle
 *      tasks are run inside of the drawRect method of a window's contentView,
 *      which will not be called until after this function returns.
 *
 * Results:
 *	None.
     *  its behavior on other platforms.
 *
 * Side effects: Processes all pending idle events then calls the display
 *	method of each visible window.
 *
 *----------------------------------------------------------------------
 */
     */

MODULE_SCOPE void
TkMacOSXFlushWindows(void)
{
    if (Tk_GetNumMainWindows() == 0) {
	return;
    }
    while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)){}
    while (Tcl_DoOneEvent(TCL_TIMER_EVENTS|TCL_DONT_WAIT)){}
    for (NSWindow *w in [NSApp orderedWindows]) {
	[w display];
    }
    display->request++;
    return 0;
}
}


/*
 * Local Variables:
 * mode: objc
 * c-basic-offset: 4
 * fill-column: 79
 * coding: utf-8
 * End:
 */
Deleted macosx/tkMacOSXEvent.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23























-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*
 * tkMacOSXEvent.h --
 *
 *	Declarations of Macintosh specific functions for implementing the
 *	Mac OS X Notifier.
 *
 * Copyright 2001-2009, Apple Inc.
 * Copyright (c) 2005-2009 Daniel A. Steffen <[email protected]>
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#ifndef _TKMACEVENT
#define _TKMACEVENT

#ifndef _TKMACINT
#include "tkMacOSXInt.h"
#endif

MODULE_SCOPE void TkMacOSXFlushWindows(void);

#endif
Changes to macosx/tkMacOSXFont.c.
1
2
3
4
5
6
7
8
9



10
11
12
13
14
15
16
1
2
3
4
5
6



7
8
9
10
11
12
13
14
15
16






-
-
-
+
+
+







/*
 * tkMacOSXFont.c --
 *
 *	Contains the Macintosh implementation of the platform-independent font
 *	package interface.
 *
 * Copyright 2002-2004 Benjamin Riefenstahl, [email protected]
 * Copyright (c) 2006-2009 Daniel A. Steffen <[email protected]>
 * Copyright 2008-2009, Apple Inc.
 * Copyright © 2002-2004 Benjamin Riefenstahl, [email protected]
 * Copyright © 2006-2009 Daniel A. Steffen <[email protected]>
 * 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.
 */

#include "tkMacOSXPrivate.h"
#include "tkMacOSXFont.h"
52
53
54
55
56
57
58
59

60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77

















78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107

108
109
110
111
112




113
114
115
116
117
118
119
120

121
122
123


124
125
126
127
128

129
130

131
132
133
134
135
136










137
138
139








140
141
142
143
144




145
146
147

148
149
150
151
152
153
154
155
156
157
158

159
160
161
162
163
164
165


166
167
168


169
170
171


172
173
174
175
176
177
178
179
180
181
182
183
184
185

186
187
188
189
190






191
192
193
194
195
196









197
198

199
200
201
202
203



204
205
206
207

208
209
210
211
212
213

214
215
216


217
218
219
220
221
222


223
224
225
226
227
228
229
230



231
232


233
234
235
236






237
238
239
240
241
242
243
244
52
53
54
55
56
57
58

59
60

















61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95




96
97
98
99
100



101





102
103
104
105








106



107
108





109


110


111



112
113
114
115
116
117
118
119
120
121



122
123
124
125
126
127
128
129





130
131
132
133



134











135







136
137



138
139



140
141














142





143
144
145
146
147
148






149
150
151
152
153
154
155
156
157


158





159
160
161




162






163



164
165






166
167








168
169
170


171
172




173
174
175
176
177
178

179
180
181
182
183
184
185







-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


















-
-
-
-





-
-
-
+
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
+
-
-
-
+
+
-
-
-
-
-
+
-
-
+
-
-

-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
+
+
-
-
-
+
+
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
+
-
-
-
-
-
+
+
+
-
-
-
-
+
-
-
-
-
-
-
+
-
-
-
+
+
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
+
+
+
-
-
+
+
-
-
-
-
+
+
+
+
+
+
-







    const char *tkName;
    const char *tkName1;
};

#define ThemeFont(n, ...) { kTheme##n##Font, "system" #n "Font", ##__VA_ARGS__ }
static const struct SystemFontMapEntry systemFontMap[] = {
    ThemeFont(System, 			"TkDefaultFont", "TkIconFont"),
    ThemeFont(EmphasizedSystem,		"TkCaptionFont"),
    ThemeFont(EmphasizedSystem,		"TkCaptionFont", NULL),
    ThemeFont(SmallSystem,		"TkHeadingFont", "TkTooltipFont"),
    ThemeFont(SmallEmphasizedSystem),
    ThemeFont(Application,		"TkTextFont"),
    ThemeFont(Label,			"TkSmallCaptionFont"),
    ThemeFont(Views),
    ThemeFont(MenuTitle),
    ThemeFont(MenuItem,			"TkMenuFont"),
    ThemeFont(MenuItemMark),
    ThemeFont(MenuItemCmdKey),
    ThemeFont(WindowTitle),
    ThemeFont(PushButton),
    ThemeFont(UtilityWindowTitle),
    ThemeFont(AlertHeader),
    ThemeFont(Toolbar),
    ThemeFont(MiniSystem),
    { kThemeSystemFontDetail,		"systemDetailSystemFont" },
    { kThemeSystemFontDetailEmphasized,	"systemDetailEmphasizedSystemFont" },
    { -1, NULL }
    ThemeFont(SmallEmphasizedSystem, NULL, NULL),
    ThemeFont(Application,		"TkTextFont", NULL),
    ThemeFont(Label,			"TkSmallCaptionFont", NULL),
    ThemeFont(Views, NULL, NULL),
    ThemeFont(MenuTitle, NULL, NULL),
    ThemeFont(MenuItem,			"TkMenuFont", NULL),
    ThemeFont(MenuItemMark, NULL, NULL),
    ThemeFont(MenuItemCmdKey, NULL, NULL),
    ThemeFont(WindowTitle, NULL, NULL),
    ThemeFont(PushButton, NULL, NULL),
    ThemeFont(UtilityWindowTitle, NULL, NULL),
    ThemeFont(AlertHeader, NULL, NULL),
    ThemeFont(Toolbar, NULL, NULL),
    ThemeFont(MiniSystem, NULL, NULL),
    { kThemeSystemFontDetail,		"systemDetailSystemFont", NULL, NULL },
    { kThemeSystemFontDetailEmphasized,	"systemDetailEmphasizedSystemFont", NULL, NULL },
    { -1, NULL, NULL, NULL }
};
#undef ThemeFont

static int antialiasedTextEnabled = -1;
static NSCharacterSet *whitespaceCharacterSet = nil;
static NSCharacterSet *lineendingCharacterSet = nil;

static void		GetTkFontAttributesForNSFont(NSFont *nsFont,
			    TkFontAttributes *faPtr);
static NSFont *		FindNSFont(const char *familyName,
			    NSFontTraitMask traits, NSInteger weight,
			    CGFloat size, int fallbackToDefault);
static void		InitFont(NSFont *nsFont,
			    const TkFontAttributes *reqFaPtr,
			    MacFont *fontPtr);
static int		CreateNamedSystemFont(Tcl_Interp *interp,
			    Tk_Window tkwin, const char *name,
			    TkFontAttributes *faPtr);
static void		DrawCharsInContext(Display *display, Drawable drawable,
			    GC gc, Tk_Font tkfont, const char *source,
			    int numBytes, int rangeStart, int rangeLength,
			    int x, int y, double angle);

#pragma mark -
#pragma mark Font Helpers:

/*
 *---------------------------------------------------------------------------
 *
 * TkUtfToNSString --
 * To avoid an extra copy, a TKNSString object wraps a Tcl_DString with an
 *
 * When Tcl is compiled with TCL_UTF_MAX = 3 (the default for 8.6) it cannot
 * deal directly with UTF-8 encoded non-BMP characters, since their UTF-8
 * encoding requires 4 bytes.
 *
 * NSString that uses the DString's buffer as its character buffer.  It can be
 * constructed from a Tcl_DString and it has a DString property that handles
 * converting from an NSString to a Tcl_DString.
 */
 * As a workaround, these versions of Tcl encode non-BMP characters as a string
 * of length 6 in which the high and low UTF-16 surrogates have been encoded
 * using the UTF-8 algorithm.  The UTF-8 encoding does not allow encoding
 * surrogates, so these 6-byte strings are not valid UTF-8, and hence Apple's
 * NString class will refuse to instantiate an NSString from the 6-byte
 * encoding.  This function allows creating an NSString from a C-string which
 * has been encoded using this scheme.
 *

 * Results:
 *	An NSString, which may be nil.
 *
@implementation TKNSString

 * Side effects:
 *	None.
 *---------------------------------------------------------------------------
 */

- (instancetype)initWithTclUtfBytes:(const void *)bytes
MODULE_SCOPE NSString*
TkUtfToNSString(
		       length:(NSUInteger)len
   const char *source,
   size_t numBytes)
{
    NSString *string;
    Tcl_DString ds;

    self = [self init];
    if (self) {
	Tcl_DStringInit(&_ds);
	Tcl_UtfToChar16DString(bytes, len, &_ds);
	_string = [[NSString alloc]
	     initWithCharactersNoCopy:(unichar *)Tcl_DStringValue(&_ds)
			       length:Tcl_DStringLength(&_ds)>>1
			 freeWhenDone:NO];
	self.UTF8String = _string.UTF8String;
    }
    Tcl_DStringInit(&ds);
    Tcl_UtfToUniCharDString(source, numBytes, &ds);
    string = [[NSString alloc] initWithCharacters:(const unichar *)Tcl_DStringValue(&ds)
    return self;
}

- (instancetype)initWithString:(NSString *)aString
{
    self = [self init];
    if (self) {
	_string = [[NSString alloc] initWithString:aString];
	    length:(Tcl_DStringLength(&ds)>>1)];
    Tcl_DStringFree(&ds);
    return string;
}

	_UTF8String = _string.UTF8String;
    }
    return self;
}
/*
 *---------------------------------------------------------------------------
 *

 * TkUtfAtIndex --
 *
 *  Write a sequence of bytes up to length 6 which is an encoding of a UTF-16
 *  character in an NSString.  Also record the unicode code point of the character.
 *  this may be a non-BMP character constructed by reading two surrogates from
 *  the NSString.
 *
 * Results:
 *	Returns the number of bytes written.
 *
 * Side effects:
- (void)dealloc
 *	Bytes are written to the char array referenced by the pointer uni and
 *      the unicode code point is written to the integer referenced by the
 *      pointer code.
 *
 */

MODULE_SCOPE int
{
    Tcl_DStringFree(&_ds);
TkUtfAtIndex(
    NSString *string,
    int index,
    [_string release];
    [super dealloc];
    char *uni,
    unsigned int *code)
{
}

    char *ptr = uni;
    UniChar uniChar = [string characterAtIndex: index];
    if (CFStringIsSurrogateHighCharacter(uniChar)) {
	UniChar lowChar = [string characterAtIndex: ++index];
	*code = CFStringGetLongCharacterForSurrogatePair(
	    uniChar, lowChar);
	ptr += Tcl_UniCharToUtf(uniChar, ptr);
        ptr += Tcl_UniCharToUtf(lowChar, ptr);
	return ptr - uni;
    } else {
	*code = (int) uniChar;
	[[string substringWithRange: NSMakeRange(index, 1)]
     	        getCString: uni
		 maxLength: XMaxTransChars
- (NSUInteger)length
		  encoding: NSUTF8StringEncoding];
	return strlen(uni);
    }
}

{
    return _string.length;
}

- (unichar)characterAtIndex:(NSUInteger)index
{
/*
 *---------------------------------------------------------------------------
 *
 * TkNSStringToUtf --
 *
 * Encodes the unicode string represented by an NSString object with the
    return [_string characterAtIndex:index];
}

- (Tcl_DString)DString
{
    if ( _ds.string == NULL) {

	/*
	 * The DString has not been initialized. Construct it from
 * internal encoding that Tcl uses when TCL_UTF_MAX = 3.  This encoding
 * is similar to UTF-8 except that non-BMP characters are encoded as two
	 * our string's unicode characters.
 * successive 3-byte sequences which are constructed from UTF-16 surrogates
 * by applying the UTF-8 algorithm.  Even though the UTF-8 encoding does not
 * allow encoding surrogates, the algorithm does produce a well-defined
 * 3-byte sequence.
 *
	 */
	char *p;
	NSUInteger index;
 * Results:
 *	Returns a pointer to a null-terminated byte array which encodes the
 *	NSString.
 *

 * Side effects:
 *      Memory is allocated to hold the byte array, which must be freed with
 *      ckalloc.  If the pointer numBytes is not NULL the number of non-null
 *      bytes written to the array is stored in the integer it references.
 */

	Tcl_DStringInit(&_ds);
MODULE_SCOPE char*
TkNSStringToUtf(
   NSString *string,
	Tcl_DStringSetLength(&_ds, 3 * [_string length]);
	p = Tcl_DStringValue(&_ds);
   int *numBytes)
{
    unsigned int code;
    int i;
    char *ptr, *bytes = ckalloc(6*[string length] + 1);

	for (index = 0; index < [_string length]; index++) {
	    p += Tcl_UniCharToUtf([_string characterAtIndex: index], p);
    ptr = bytes;
    if (ptr) {
	for (i = 0; i < [string length]; i++) {
	    ptr += TkUtfAtIndex(string, i, ptr, &code);
	    if (code > 0xffff){
		i++;
	    }
	}
	}
	Tcl_DStringSetLength(&_ds, p - Tcl_DStringValue(&_ds));
    }
	*ptr = '\0';
    }
    return _ds;
}
    if (numBytes) {
	*numBytes = ptr - bytes;
    }
    return bytes;

#ifndef __clang__
@synthesize UTF8String = _UTF8String;
@synthesize DString = _ds;
#endif
@end
}

#define GetNSFontTraitsFromTkFontAttributes(faPtr) \
	((faPtr)->weight == TK_FW_BOLD ? NSBoldFontMask : NSUnboldFontMask) | \
	((faPtr)->slant == TK_FS_ITALIC ? NSItalicFontMask : NSUnitalicFontMask)

/*
 *---------------------------------------------------------------------------
503
504
505
506
507
508
509
510

511
512
513
514
515
516
517
444
445
446
447
448
449
450

451
452
453
454
455
456
457
458







-
+







 */

void
TkpFontPkgInit(
    TkMainInfo *mainPtr)	/* The application being created. */
{
    Tcl_Interp *interp = mainPtr->interp;
    Tk_Window tkwin = (Tk_Window) mainPtr->winPtr;
    Tk_Window tkwin = (Tk_Window)mainPtr->winPtr;
    const struct SystemFontMapEntry *systemFont = systemFontMap;
    NSFont *nsFont;
    TkFontAttributes fa;
    NSMutableCharacterSet *cs;
    /*
     * Since we called before TkpInit, we need our own autorelease pool.
     */
602
603
604
605
606
607
608
609

610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628

629
630
631
632
633
634
635
543
544
545
546
547
548
549

550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568

569
570
571
572
573
574
575
576







-
+


















-
+







 *	None.
 *
 *---------------------------------------------------------------------------
 */

TkFont *
TkpGetNativeFont(
    Tk_Window tkwin,		/* For display where font will be used. */
    TCL_UNUSED(Tk_Window),		/* For display where font will be used. */
    const char *name)		/* Platform-specific font name. */
{
    MacFont *fontPtr = NULL;
    ThemeFontID themeFontId;
    CTFontRef ctFont;

    if (strcmp(name, SYSTEMFONT_NAME) == 0) {
	themeFontId = kThemeSystemFont;
    } else if (strcmp(name, APPLFONT_NAME) == 0) {
	themeFontId = kThemeApplicationFont;
    } else if (strcmp(name, MENUITEMFONT_NAME) == 0) {
	themeFontId = kThemeMenuItemFont;
    } else {
	return NULL;
    }
    ctFont = CTFontCreateUIFontForLanguage(
	    HIThemeGetUIFontType(themeFontId), 0, NULL);
    if (ctFont) {
	fontPtr = ckalloc(sizeof(MacFont));
	fontPtr = (MacFont *)ckalloc(sizeof(MacFont));
	InitFont((NSFont*) ctFont, NULL, fontPtr);
    }

    return (TkFont *) fontPtr;
}

/*
689
690
691
692
693
694
695
696

697
698
699
700
701
702
703
630
631
632
633
634
635
636

637
638
639
640
641
642
643
644







-
+







    if (!nsFont) {
	nsFont = FindNSFont(faPtr->family, traits, weight, points, 1);
    }
    if (!nsFont) {
	Tcl_Panic("Could not determine NSFont from TkFontAttributes");
    }
    if (tkFontPtr == NULL) {
	fontPtr = ckalloc(sizeof(MacFont));
	fontPtr = (MacFont *)ckalloc(sizeof(MacFont));
    } else {
	fontPtr = (MacFont *) tkFontPtr;
	TkpDeleteFont(tkFontPtr);
    }
    CFRetain(nsFont); /* Always needed to allow unconditional CFRelease below */
    InitFont(nsFont, faPtr, fontPtr);

751
752
753
754
755
756
757
758

759
760
761
762
763
764
765
692
693
694
695
696
697
698

699
700
701
702
703
704
705
706







-
+







 *
 *---------------------------------------------------------------------------
 */

void
TkpGetFontFamilies(
    Tcl_Interp *interp,		/* Interp to hold result. */
    Tk_Window tkwin)		/* For display to query. */
    TCL_UNUSED(Tk_Window))		/* For display to query. */
{
    Tcl_Obj *resultPtr = Tcl_NewListObj(0, NULL);
    NSArray *list = [[NSFontManager sharedFontManager] availableFontFamilies];

    for (NSString *family in list) {
	Tcl_ListObjAppendElement(NULL, resultPtr,
		Tcl_NewStringObj([family UTF8String], -1));
824
825
826
827
828
829
830
831

832
833
834
835
836
837
838
765
766
767
768
769
770
771

772
773
774
775
776
777
778
779







-
+







 *	The font attributes are stored in *faPtr.
 *
 *----------------------------------------------------------------------
 */

void
TkpGetFontAttrsForChar(
    Tk_Window tkwin,		/* Window on the font's display */
    TCL_UNUSED(Tk_Window),		/* Window on the font's display */
    Tk_Font tkfont,		/* Font to query */
    int c,         		/* Character of interest */
    TkFontAttributes* faPtr)	/* Output: Font attributes */
{
    MacFont *fontPtr = (MacFont *) tkfont;
    NSFont *nsFont = fontPtr->nsFont;
    *faPtr = fontPtr->font.fa;
975
976
977
978
979
980
981
982

983
984
985
986
987
988
989
916
917
918
919
920
921
922

923
924
925
926
927
928
929
930







-
+







	    (maxLength == 0 && !(flags & TK_AT_LEAST_ONE))) {
	*lengthPtr = 0;
	return 0;
    }
    if (maxLength > 32767) {
	maxLength = 32767;
    }
    string = TkUtfToNSString((const char *)source, numBytes);
    string = [[TKNSString alloc] initWithTclUtfBytes:source length:numBytes];
    if (!string) {
	length = 0;
	fit = rangeLength;
	goto done;
    }
    attributedString = [[NSAttributedString alloc] initWithString:string
	    attributes:fontPtr->nsAttributes];
1111
1112
1113
1114
1115
1116
1117
1118

1119
1120
1121
1122
1123
1124
1125
1052
1053
1054
1055
1056
1057
1058

1059
1060
1061
1062
1063
1064
1065
1066







-
+







 *---------------------------------------------------------------------------
 *
 * Tk_DrawChars --
 *
 *	Draw a string of characters on the screen.
 *
 *	With ATSUI we need the line context to do this right, so we have the
 *	actual implementation in TkpDrawCharsInContext().
 *	actual implementation in TkpDrawAngledCharsInContext().
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Information gets drawn on the screen.
 *
1140
1141
1142
1143
1144
1145
1146
1147

1148
1149
1150
1151
1152
1153
1154
1081
1082
1083
1084
1085
1086
1087

1088
1089
1090
1091
1092
1093
1094
1095







-
+







				 * passed to this function. If they are not
				 * stripped out, they will be displayed as
				 * regular printing characters. */
    int numBytes,		/* Number of bytes in string. */
    int x, int y)		/* Coordinates at which to place origin of the
				 * string when drawing. */
{
    DrawCharsInContext(display, drawable, gc, tkfont, source, numBytes,
    TkpDrawAngledCharsInContext(display, drawable, gc, tkfont, source, numBytes,
	    0, numBytes, x, y, 0.0);
}

void
TkDrawAngledChars(
    Display *display,		/* Display on which to draw. */
    Drawable drawable,		/* Window or pixmap in which to draw. */
1163
1164
1165
1166
1167
1168
1169
1170

1171
1172
1173
1174
1175
1176
1177
1104
1105
1106
1107
1108
1109
1110

1111
1112
1113
1114
1115
1116
1117
1118







-
+







				 * stripped out, they will be displayed as
				 * regular printing characters. */
    int numBytes,		/* Number of bytes in string. */
    double x, double y,		/* Coordinates at which to place origin of
				 * string when drawing. */
    double angle)		/* What angle to put text at, in degrees. */
{
    DrawCharsInContext(display, drawable, gc, tkfont, source, numBytes,
    TkpDrawAngledCharsInContext(display, drawable, gc, tkfont, source, numBytes,
	    0, numBytes, x, y, angle);
}

/*
 *---------------------------------------------------------------------------
 *
 * TkpDrawCharsInContext --
1208
1209
1210
1211
1212
1213
1214

1215

1216
1217
1218
1219
1220
1221



1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236

1237
1238
1239

1240
1241
1242
1243
1244
1245
1246
1247
1248



1249
1250
1251
1252
1253
1254

1255
1256
1257
1258



1259
1260
1261

1262
1263
1264

1265
1266

1267
1268
1269
1270
1271

1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282





1283
1284
1285




1286
1287
1288
1289
1290


1291
1292







1293
1294
1295
1296



1297
1298

1299
1300

1301
1302
1303
1304
1305
1306
1307
1149
1150
1151
1152
1153
1154
1155
1156

1157
1158
1159
1160



1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177

1178
1179
1180

1181
1182
1183
1184
1185
1186
1187



1188
1189
1190
1191
1192
1193
1194
1195

1196
1197



1198
1199
1200
1201
1202

1203
1204
1205
1206
1207
1208

1209
1210
1211

1212

1213

1214
1215
1216
1217
1218





1219
1220
1221
1222
1223
1224


1225
1226
1227
1228
1229
1230

1231

1232
1233
1234

1235
1236
1237
1238
1239
1240
1241
1242



1243
1244
1245


1246
1247

1248
1249
1250
1251
1252
1253
1254
1255







+
-
+



-
-
-
+
+
+














-
+


-
+






-
-
-
+
+
+





-
+

-
-
-
+
+
+


-
+



+

-
+


-

-
+
-





-
-
-
-
-
+
+
+
+
+

-
-
+
+
+
+


-

-
+
+

-
+
+
+
+
+
+
+

-
-
-
+
+
+
-
-
+

-
+







    int numBytes,		/* Number of bytes in string. */
    int rangeStart,		/* Index of first byte to draw. */
    int rangeLength,		/* Length of range to draw in bytes. */
    int x, int y)		/* Coordinates at which to place origin of the
				 * whole (not just the range) string when
				 * drawing. */
{
    (void)display;
    DrawCharsInContext(display, drawable, gc, tkfont, source, numBytes,
    TkpDrawAngledCharsInContext(display, drawable, gc, tkfont, source, numBytes,
	    rangeStart, rangeLength, x, y, 0.0);
}

static void
DrawCharsInContext(
    Display *display,		/* Display on which to draw. */
void
TkpDrawAngledCharsInContext(
    TCL_UNUSED(Display *),		/* Display on which to draw. */
    Drawable drawable,		/* Window or pixmap in which to draw. */
    GC gc,			/* Graphics context for drawing characters. */
    Tk_Font tkfont,		/* Font in which characters will be drawn; must
				 * be the same as font used in GC. */
    const char * source,	/* UTF-8 string to be displayed. Need not be
				 * '\0' terminated. All Tk meta-characters
				 * (tabs, control characters, and newlines)
				 * should be stripped out of the string that is
				 * passed to this function. If they are not
				 * stripped out, they will be displayed as
				 * regular printing characters. */
    int numBytes,		/* Number of bytes in string. */
    int rangeStart,		/* Index of first byte to draw. */
    int rangeLength,		/* Length of range to draw in bytes. */
    int x, int y,		/* Coordinates at which to place origin of the
    double x, double y,		/* Coordinates at which to place origin of the
				 * whole (not just the range) string when
				 * drawing. */
    double angle)
    double angle)		/* What angle to put text at, in degrees. */
{
    const MacFont *fontPtr = (const MacFont *) tkfont;
    NSString *string;
    NSMutableDictionary *attributes;
    NSAttributedString *attributedString;
    CTTypesetterRef typesetter;
    CFIndex start, len;
    CTLineRef line;
    MacDrawable *macWin = (MacDrawable *) drawable;
    CFIndex start, length;
    CTLineRef line, full=nil;
    MacDrawable *macWin = (MacDrawable *)drawable;
    TkMacOSXDrawingContext drawingContext;
    CGContextRef context;
    CGColorRef fg;
    NSFont *nsFont;
    CGAffineTransform t;
    int h;
    CGFloat width, height, textX = (CGFloat) x, textY = (CGFloat) y;

    if (rangeStart < 0 || rangeLength <= 0 ||
	    rangeStart + rangeLength > numBytes ||
	    !TkMacOSXSetupDrawingContext(drawable, gc, 1, &drawingContext)) {
    if (rangeStart < 0 || rangeLength <= 0  ||
	rangeStart + rangeLength > numBytes ||
	!TkMacOSXSetupDrawingContext(drawable, gc, &drawingContext)) {
	return;
    }
    string = TkUtfToNSString((const char *)source, numBytes);
    string = [[TKNSString alloc] initWithTclUtfBytes:source length:numBytes];
    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:[NSGraphicsContext graphicsContextWithGraphicsPort:
    [nsFont setInContext:GET_NSCONTEXT(context, NO)];
	    context flipped:NO]];
    CGContextSetTextMatrix(context, CGAffineTransformIdentity);
    attributedString = [[NSAttributedString alloc] initWithString:string
	    attributes:attributes];
    typesetter = CTTypesetterCreateWithAttributedString(
	    (CFAttributedStringRef)attributedString);
    x += macWin->xOff;
    y += macWin->yOff;
    h = drawingContext.portBounds.size.height;
    y = h - y;
    t = CGAffineTransformMake(1.0, 0.0, 0.0, -1.0, 0.0, h);
    textX += (CGFloat) macWin->xOff;
    textY += (CGFloat) macWin->yOff;
    height = drawingContext.portBounds.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(
		CGAffineTransformTranslate(t, x, y), angle*PI/180.0), -x, -y);
	t = CGAffineTransformTranslate(
             CGAffineTransformRotate(
                 CGAffineTransformTranslate(t, textX, textY), angle*PI/180.0),
             -textX, -textY);
    }
    CGContextConcatCTM(context, t);
    CGContextSetTextPosition(context, x, y);
    start = Tcl_NumUtfChars(source, rangeStart);
    len = Tcl_NumUtfChars(source, rangeStart + rangeLength);
    length = Tcl_NumUtfChars(source, rangeStart + rangeLength) - start;
    line = CTTypesetterCreateLine(typesetter, CFRangeMake(start, length));
    if (start > 0) {
	CGRect clipRect = CGRectInfinite, startBounds;

	/*
	 * We are only drawing part of the string.  To compute the x coordinate
	 * of the part we are drawing we subtract its typographical length from
	 * the typographical length of the full string.  This accounts for the
	 * kerning after the initial part of the string.
	 */

	line = CTTypesetterCreateLine(typesetter, CFRangeMake(0, start));
	startBounds = CTLineGetImageBounds(line, context);
	CFRelease(line);
	full = CTTypesetterCreateLine(typesetter, CFRangeMake(0, start + length));
	width = CTLineGetTypographicBounds(full, NULL, NULL, NULL);
	CFRelease(full);
	clipRect.origin.x = startBounds.origin.x + startBounds.size.width;
	CGContextClipToRect(context, clipRect);
	textX += (width - CTLineGetTypographicBounds(line, NULL, NULL, NULL));
    }
    line = CTTypesetterCreateLine(typesetter, CFRangeMake(0, len));
    CGContextSetTextPosition(context, textX, textY);
    CTLineDraw(line, context);
    CFRelease(line);
    CFRelease(typesetter);
    [attributedString release];
    [string release];
    [attributes release];
    TkMacOSXRestoreDrawingContext(&drawingContext);
1371
1372
1373
1374
1375
1376
1377
1378
1379


1380
1381
1382
1383
1384
1385
1386
1319
1320
1321
1322
1323
1324
1325


1326
1327
1328
1329
1330
1331
1332
1333
1334







-
-
+
+







 *	None.
 *
 *---------------------------------------------------------------------------
 */

int
TkMacOSXIsCharacterMissing(
    Tk_Font tkfont,		/* The font we are looking in. */
    unsigned int searchChar)	/* The character we are looking for. */
    TCL_UNUSED(Tk_Font),		/* The font we are looking in. */
    TCL_UNUSED(unsigned int))	/* The character we are looking for. */
{
    return 0;
}

/*
 *----------------------------------------------------------------------
 *
1411
1412
1413
1414
1415
1416
1417
1418
1419


1420
1421
1422
1423
1424
1425
1426
1359
1360
1361
1362
1363
1364
1365


1366
1367
1368
1369
1370
1371
1372
1373
1374







-
-
+
+







		traitsOfFont:nsFont];
	id underline = [nsAttributes objectForKey:
		NSUnderlineStyleAttributeName];
	id strikethrough = [nsAttributes objectForKey:
		NSStrikethroughStyleAttributeName];

	objv[i++] = Tcl_NewStringObj(familyName, -1);
	objv[i++] = Tcl_NewIntObj([nsFont pointSize]);
#define S(s)    Tcl_NewStringObj(STRINGIFY(s),(int)(sizeof(STRINGIFY(s))-1))
	objv[i++] = Tcl_NewWideIntObj([nsFont pointSize]);
#define S(s)    Tcl_NewStringObj(STRINGIFY(s), (sizeof(STRINGIFY(s))-1))
	objv[i++] = (traits & NSBoldFontMask)	? S(bold)   : S(normal);
	objv[i++] = (traits & NSItalicFontMask)	? S(italic) : S(roman);
	if ([underline respondsToSelector:@selector(intValue)] &&
		([underline intValue] & (NSUnderlineStyleSingle |
		NSUnderlineStyleThick | NSUnderlineStyleDouble))) {
	    objv[i++] = S(underline);
	}
Changes to macosx/tkMacOSXFont.h.
1
2
3
4
5
6
7
8
9
10




11
12
13
14
15
16
17
1
2
3
4
5
6




7
8
9
10
11
12
13
14
15
16
17






-
-
-
-
+
+
+
+







/*
 * 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 <[email protected]>
 * 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 <[email protected]>
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#ifndef TKMACOSXFONT_H
#define TKMACOSXFONT_H 1
Changes to macosx/tkMacOSXHLEvents.c.
1
2
3
4
5
6
7
8
9
10





11
12
13
14
15
16
17
1
2
3
4
5





6
7
8
9
10
11
12
13
14
15
16
17





-
-
-
-
-
+
+
+
+
+







/*
 * 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 <[email protected]>
 * 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 <[email protected]>
 * 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.
 */

#include "tkMacOSXPrivate.h"
#include <sys/param.h>
35
36
37
38
39
40
41

42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60





61
62
63
64
65
66

67
68






69
70
71

72
73
74
75
76
77
78


79
80
81
82
83
84
85
86
87
88
89

90
91
92
93
94
95
96
97
98
99



100
101
102
103
104
105
106
107
108
109
110
111
112



113
114
115
116
117
118
119
120
121
122
123
124
125
126



127
128
129
130
131
132
133
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56





57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99

100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153







+














-
-
-
-
-
+
+
+
+
+






+


+
+
+
+
+
+



+







+
+










-
+










+
+
+













+
+
+














+
+
+







 */

typedef struct AppleEventInfo {
    Tcl_Interp *interp;
    const char *procedure;
    Tcl_DString command;
    NSAppleEventDescriptor *replyEvent; /* Only used for DoScriptText. */
    int retryCount;
} AppleEventInfo;

/*
 * Static functions used only in this file.
 */

static int  MissedAnyParameters(const AppleEvent *theEvent);
static int  ReallyKillMe(Tcl_Event *eventPtr, int flags);
static void ProcessAppleEvent(ClientData clientData);

/*
 * Names of the procedures which can be used to process AppleEvents.
 */

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 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";

#pragma mark TKApplication(TKHLEvents)

@implementation TKApplication(TKHLEvents)
- (void) terminate: (id) sender
{
    (void)sender;
    [self handleQuitApplicationEvent:Nil withReplyEvent:Nil];
}

- (void) superTerminate: (id) sender
{
    (void) sender;
    [super terminate:nil];
}

- (void) preferences: (id) sender
{
    (void)sender;
    [self handleShowPreferencesEvent:Nil withReplyEvent:Nil];
}

- (void) handleQuitApplicationEvent: (NSAppleEventDescriptor *)event
    withReplyEvent: (NSAppleEventDescriptor *)replyEvent
{
    KillEvent *eventPtr;
    (void)event;
    (void)replyEvent;

    if (_eventInterp) {
	/*
	 * Call the exit command from the event loop, since you are not
	 * supposed to call ExitToShell in an Apple Event Handler. We put this
	 * at the head of Tcl's event queue because this message usually comes
	 * when the Mac is shutting down, and we want to kill the shell as
	 * quickly as possible.
	 */

	eventPtr = ckalloc(sizeof(KillEvent));
	eventPtr = (KillEvent *)ckalloc(sizeof(KillEvent));
	eventPtr->header.proc = ReallyKillMe;
	eventPtr->interp = _eventInterp;

	Tcl_QueueEvent((Tcl_Event *) eventPtr, TCL_QUEUE_HEAD);
    }
}

- (void) handleOpenApplicationEvent: (NSAppleEventDescriptor *)event
    withReplyEvent: (NSAppleEventDescriptor *)replyEvent
{
    (void)event;
    (void)replyEvent;

    if (_eventInterp &&
	Tcl_FindCommand(_eventInterp, "::tk::mac::OpenApplication", NULL, 0)){
	int code = Tcl_EvalEx(_eventInterp, "::tk::mac::OpenApplication",
			      -1, TCL_EVAL_GLOBAL);
	if (code != TCL_OK) {
	    Tcl_BackgroundException(_eventInterp, code);
	}
    }
}

- (void) handleReopenApplicationEvent: (NSAppleEventDescriptor *)event
    withReplyEvent: (NSAppleEventDescriptor *)replyEvent
{
    (void)event;
    (void)replyEvent;

    [NSApp activateIgnoringOtherApps: YES];
    if (_eventInterp && Tcl_FindCommand(_eventInterp,
	    "::tk::mac::ReopenApplication", NULL, 0)) {
	int code = Tcl_EvalEx(_eventInterp, "::tk::mac::ReopenApplication",
			      -1, TCL_EVAL_GLOBAL);
	if (code != TCL_OK){
	    Tcl_BackgroundException(_eventInterp, code);
	}
    }
}

- (void) handleShowPreferencesEvent: (NSAppleEventDescriptor *)event
    withReplyEvent: (NSAppleEventDescriptor *)replyEvent
{
    (void)event;
    (void)replyEvent;

    if (_eventInterp &&
	    Tcl_FindCommand(_eventInterp, "::tk::mac::ShowPreferences", NULL, 0)){
	int code = Tcl_EvalEx(_eventInterp, "::tk::mac::ShowPreferences",
			      -1, TCL_EVAL_GLOBAL);
	if (code != TCL_OK) {
	    Tcl_BackgroundException(_eventInterp, code);
	}
143
144
145
146
147
148
149

150
151
152
153
154
155
156
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177







+







    char URLString[1 + URL_MAX_LENGTH];
    NSURL *fileURL;
    DescType type;
    Size actual;
    long count, index;
    AEKeyword keyword;
    Tcl_DString pathName;
    (void)replyEvent;

    /*
     * Do nothing if we don't have an interpreter.
     */

    if (!_eventInterp) {
	return;
182
183
184
185
186
187
188
189

190
191
192
193
194
195
196
203
204
205
206
207
208
209

210
211
212
213
214
215
216
217







-
+







    }

    /*
     * Construct a Tcl expression which calls the ::tk::mac::OpenDocument
     * procedure, passing the paths contained in the AppleEvent as arguments.
     */

    AppleEventInfo *AEInfo = ckalloc(sizeof(AppleEventInfo));
    AppleEventInfo *AEInfo = (AppleEventInfo *)ckalloc(sizeof(AppleEventInfo));
    Tcl_DString *openCommand = &AEInfo->command;
    Tcl_DStringInit(openCommand);
    Tcl_DStringAppend(openCommand, openDocumentProc, -1);
    utf8 = Tcl_GetEncoding(NULL, "utf-8");

    for (index = 1; index <= count; index++) {
	if (noErr != AEGetNthPtr(fileSpecDesc, index, typeFileURL, &keyword,
212
213
214
215
216
217
218







219
220
221
222
223
224
225
226
227

228


229
230
231
232
233
234
235


236
237
238
239
240
241
242
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254

255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274







+
+
+
+
+
+
+








-
+

+
+







+
+








    Tcl_FreeEncoding(utf8);
    AEDisposeDesc(&contents);
    AEInfo->interp = _eventInterp;
    AEInfo->procedure = openDocumentProc;
    AEInfo->replyEvent = nil;
    Tcl_DoWhenIdle(ProcessAppleEvent, (ClientData)AEInfo);
    AEInfo->retryCount = 0;

    if (Tcl_FindCommand(_eventInterp, "::tk::mac::OpenDocuments", NULL, 0)){
	ProcessAppleEvent((ClientData)AEInfo);
    } else {
	Tcl_CreateTimerHandler(500, ProcessAppleEvent, (ClientData)AEInfo);
    }
}

- (void) handlePrintDocumentsEvent: (NSAppleEventDescriptor *)event
		    withReplyEvent: (NSAppleEventDescriptor *)replyEvent
{
    NSString* file = [[event paramDescriptorForKeyword:keyDirectObject]
			 stringValue];
    const char *printFile = [file UTF8String];
    AppleEventInfo *AEInfo = ckalloc(sizeof(AppleEventInfo));
    AppleEventInfo *AEInfo = (AppleEventInfo *)ckalloc(sizeof(AppleEventInfo));
    Tcl_DString *printCommand = &AEInfo->command;
    (void)replyEvent;

    Tcl_DStringInit(printCommand);
    Tcl_DStringAppend(printCommand, printDocProc, -1);
    Tcl_DStringAppendElement(printCommand, printFile);
    AEInfo->interp = _eventInterp;
    AEInfo->procedure = printDocProc;
    AEInfo->replyEvent = nil;
    Tcl_DoWhenIdle(ProcessAppleEvent, (ClientData)AEInfo);
    AEInfo->retryCount = 0;
    ProcessAppleEvent((ClientData)AEInfo);
}

- (void) handleDoScriptEvent: (NSAppleEventDescriptor *)event
	      withReplyEvent: (NSAppleEventDescriptor *)replyEvent
{
    OSStatus err;
    const AEDesc *theDesc = nil;
281
282
283
284
285
286
287
288

289
290
291
292
293
294
295
296


297
298
299
300
301
302
303
304
305
306
307
308

309
310
311

312
313
314
315




316
317
318

319
320
321

322
323
324


325
326
327
328
329
330
331
332
333
334
335
336
337

338


339
340
341
342
343
344
345


346
347
348
349
350
351
352
313
314
315
316
317
318
319

320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341

342
343
344
345
346




347
348
349
350
351
352
353
354
355
356

357
358
359

360
361
362
363
364
365
366
367
368
369
370
371
372
373

374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393







-
+








+
+











-
+



+
-
-
-
-
+
+
+
+



+


-
+


-
+
+












-
+

+
+







+
+








	if (noErr == AEGetParamPtr(theDesc, keyDirectObject, typeFileURL, &type,
                                  (Ptr) URLBuffer, URL_MAX_LENGTH, &actual)) {
            if (actual > 0) {
                URLBuffer[actual] = '\0';
                NSString *urlString = [NSString stringWithUTF8String:(char*)URLBuffer];
                NSURL *fileURL = [NSURL URLWithString:urlString];
                AppleEventInfo *AEInfo = ckalloc(sizeof(AppleEventInfo));
                AppleEventInfo *AEInfo = (AppleEventInfo *)ckalloc(sizeof(AppleEventInfo));
                Tcl_DString *scriptFileCommand = &AEInfo->command;
                Tcl_DStringInit(scriptFileCommand);
                Tcl_DStringAppend(scriptFileCommand, scriptFileProc, -1);
                Tcl_DStringAppendElement(scriptFileCommand, [[fileURL path] UTF8String]);
                AEInfo->interp = _eventInterp;
                AEInfo->procedure = scriptFileProc;
                AEInfo->replyEvent = nil;
                Tcl_DoWhenIdle(ProcessAppleEvent, (ClientData)AEInfo);
		AEInfo->retryCount = 0;
                ProcessAppleEvent((ClientData)AEInfo);
            }
        }
    } else if (noErr == AEGetParamPtr(theDesc, keyDirectObject, typeUTF8Text, &type,
			       NULL, 0, &actual)) {
        /*
         * The descriptor cannot be coerced to a file URL but can be coerced to
         * text.  Construct a Tcl expression which passes the text as a string
         * argument to ::tk::mac::DoScriptText.
         */

	if (actual > 0) {
	    char *data = ckalloc(actual + 1);
	    char *data = (char *)ckalloc(actual + 1);
	    if (noErr == AEGetParamPtr(theDesc, keyDirectObject,
				       typeUTF8Text, &type,
				       data, actual, NULL)) {
		data[actual] = '\0';
                AppleEventInfo *AEInfo = ckalloc(sizeof(AppleEventInfo));
                Tcl_DString *scriptTextCommand = &AEInfo->command;
                Tcl_DStringInit(scriptTextCommand);
                Tcl_DStringAppend(scriptTextCommand, scriptTextProc, -1);
		AppleEventInfo *AEInfo = (AppleEventInfo *)ckalloc(sizeof(AppleEventInfo));
		Tcl_DString *scriptTextCommand = &AEInfo->command;
		Tcl_DStringInit(scriptTextCommand);
		Tcl_DStringAppend(scriptTextCommand, scriptTextProc, -1);
		Tcl_DStringAppendElement(scriptTextCommand, data);
		AEInfo->interp = _eventInterp;
		AEInfo->procedure = scriptTextProc;
		AEInfo->retryCount = 0;
                if (Tcl_FindCommand(AEInfo->interp, AEInfo->procedure, NULL, 0)) {
                    AEInfo->replyEvent = replyEvent;
                    ProcessAppleEvent((ClientData)AEInfo);
                    ProcessAppleEvent(AEInfo);
                } else {
                    AEInfo->replyEvent = nil;
                    Tcl_DoWhenIdle(ProcessAppleEvent, (ClientData)AEInfo);
                    Tcl_DoWhenIdle(ProcessAppleEvent, AEInfo);
                    ProcessAppleEvent(AEInfo);
                }
	    }
	}
    }
}

- (void)handleURLEvent:(NSAppleEventDescriptor*)event
        withReplyEvent:(NSAppleEventDescriptor*)replyEvent
{
    NSString* url = [[event paramDescriptorForKeyword:keyDirectObject]
                        stringValue];
    const char *cURL=[url UTF8String];
    AppleEventInfo *AEInfo = ckalloc(sizeof(AppleEventInfo));
    AppleEventInfo *AEInfo = (AppleEventInfo *)ckalloc(sizeof(AppleEventInfo));
    Tcl_DString *launchCommand = &AEInfo->command;
    (void)replyEvent;

    Tcl_DStringInit(launchCommand);
    Tcl_DStringAppend(launchCommand, launchURLProc, -1);
    Tcl_DStringAppendElement(launchCommand, cURL);
    AEInfo->interp = _eventInterp;
    AEInfo->procedure = launchURLProc;
    AEInfo->replyEvent = nil;
    Tcl_DoWhenIdle(ProcessAppleEvent, (ClientData)AEInfo);
    AEInfo->retryCount = 0;
    ProcessAppleEvent((ClientData)AEInfo);
}

@end

#pragma mark -

/*
373
374
375
376
377
378
379

380
381



















382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402


403

404
405
406
407
408
409
410
414
415
416
417
418
419
420
421


422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444



445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469







+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




-
-
-














+
+

+







 */

static void ProcessAppleEvent(
    ClientData clientData)
{
    int code;
    AppleEventInfo *AEInfo = (AppleEventInfo*) clientData;

    if (!AEInfo->interp ||
        !Tcl_FindCommand(AEInfo->interp, AEInfo->procedure, NULL, 0)) {
    if (!AEInfo->interp) {
	return;
    }

    /*
     * Apple events that are delivered during the app startup can arrive
     * before the Tcl procedure for handling the events has been defined.
     * If the command is not found we create a timer handler to process
     * the event later, hopefully after the command has been created.
     * We retry up to 2 times before giving up.
     */

    if (!Tcl_FindCommand(AEInfo->interp, AEInfo->procedure, NULL, 0)) {
	if (AEInfo->retryCount < 2) {
	    AEInfo->retryCount++;
	    Tcl_CreateTimerHandler(200, ProcessAppleEvent, clientData);
	} else {
	    ckfree(clientData);
	}
	return;
    }
    code = Tcl_EvalEx(AEInfo->interp, Tcl_DStringValue(&AEInfo->command),
	    Tcl_DStringLength(&AEInfo->command), TCL_EVAL_GLOBAL);
    if (code != TCL_OK) {
	Tcl_BackgroundException(AEInfo->interp, code);
    }

    if (AEInfo->replyEvent && code >= 0) {
        int reslen;
        const char *result = Tcl_GetStringFromObj(Tcl_GetObjResult(AEInfo->interp),
                                                  &reslen);
        if (code == TCL_OK) {
            AEPutParamPtr((AppleEvent*)[AEInfo->replyEvent aeDesc],
                          keyDirectObject, typeChar, result, reslen);
        } else {
            AEPutParamPtr((AppleEvent*)[AEInfo->replyEvent aeDesc],
                          keyErrorString, typeChar, result, reslen);
            AEPutParamPtr((AppleEvent*)[AEInfo->replyEvent aeDesc],
                          keyErrorNumber, typeSInt32, (Ptr) &code, sizeof(int));
        }
    } else if (code != TCL_OK) {
	Tcl_BackgroundException(AEInfo->interp, code);
    }

    Tcl_DStringFree(&AEInfo->command);
    ckfree(clientData);
}

/*
 *----------------------------------------------------------------------
 *
420
421
422
423
424
425
426
427

428
429
430
431
432
433
434
479
480
481
482
483
484
485

486
487
488
489
490
491
492
493







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

void
TkMacOSXInitAppleEvents(
    Tcl_Interp *interp)   /* not used */
    TCL_UNUSED(Tcl_Interp *))
{
    NSAppleEventManager *aeManager = [NSAppleEventManager sharedAppleEventManager];
    static Boolean initialized = FALSE;

    if (!initialized) {
	initialized = TRUE;

530
531
532
533
534
535
536
537

538
539
540
541
542






543

544
545
546
547
548
549
550
589
590
591
592
593
594
595

596
597
598
599


600
601
602
603
604
605
606
607
608
609
610
611
612
613
614







-
+



-
-
+
+
+
+
+
+

+







 *
 *----------------------------------------------------------------------
 */

static int
ReallyKillMe(
    Tcl_Event *eventPtr,
    int flags)
    TCL_UNUSED(int))
{
    Tcl_Interp *interp = ((KillEvent *) eventPtr)->interp;
    int quit = Tcl_FindCommand(interp, "::tk::mac::Quit", NULL, 0)!=NULL;
    int code = Tcl_EvalEx(interp, quit ? "::tk::mac::Quit" : "exit", -1, TCL_EVAL_GLOBAL);


    if (!quit) {
	Tcl_Exit(0);
    }

    int code = Tcl_EvalEx(interp, "::tk::mac::Quit", -1, TCL_EVAL_GLOBAL);
    if (code != TCL_OK) {

	/*
	 * Should be never reached...
	 */

	Tcl_BackgroundException(interp, code);
    }
    return 1;
574
575
576
577
578
579
580
581

582
583
584
585
586
587
588
589
590
591
638
639
640
641
642
643
644

645

646
647
648
649
650
651
652
653
654







-
+
-









   Size actualSize;
   OSStatus err;

   err = AEGetAttributePtr(theEvent, keyMissedKeywordAttr,
	    typeWildCard, &returnedType, NULL, 0, &actualSize);

   return (err != errAEDescNotFound);
}
}


/*
 * Local Variables:
 * mode: objc
 * c-basic-offset: 4
 * fill-column: 79
 * coding: utf-8
 * End:
 */
Changes to macosx/tkMacOSXImage.c.
1
2
3
4
5
6
7
8
9




10
11
12
13
14
15
16
17




18
19
20
21
22

23
24
25
26
27
28
29
1
2
3
4
5




6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

26
27
28
29
30
31
32
33





-
-
-
-
+
+
+
+








+
+
+
+




-
+







/*
 * 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) 2005-2009 Daniel A. Steffen <[email protected]>
 * Copyright 2017-2018 Marc Culler.
 * Copyright © 1995-1997 Sun Microsystems, Inc.
 * Copyright © 2001-2009, Apple Inc.
 * Copyright © 2005-2009 Daniel A. Steffen <[email protected]>
 * Copyright © 2017-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 "tkMacOSXPrivate.h"
#include "xbytes.h"

static CGImageRef CreateCGImageFromPixmap(Drawable pixmap);
static CGImageRef CreateCGImageFromDrawableRect( Drawable drawable,
	   int x, int y, unsigned int width, unsigned int height);

#pragma mark XImage handling

int
_XInitImageFuncPtrs(
    XImage *image)
    TCL_UNUSED(XImage *)) /* image */
{
    return 0;
}

/*
 *----------------------------------------------------------------------
 *
37
38
39
40
41
42
43
44





45
46
47
48
49
50
51
41
42
43
44
45
46
47

48
49
50
51
52
53
54
55
56
57
58
59







-
+
+
+
+
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void ReleaseData(void *info, const void *data, size_t size) {
static void ReleaseData(
    void *info,
    TCL_UNUSED(const void *), /* data */
    TCL_UNUSED(size_t))       /* size */
{
    ckfree(info);
}

CGImageRef
TkMacOSXCreateCGImageWithXImage(
    XImage *image)
{
68
69
70
71
72
73
74
75

76
77
78
79
80
81
82
76
77
78
79
80
81
82

83
84
85
86
87
88
89
90







-
+







	decode = decodeWB;

	bitsPerComponent = 1;
	bitsPerPixel = 1;
	if (image->bitmap_bit_order != MSBFirst) {
	    char *srcPtr = image->data + image->xoffset;
	    char *endPtr = srcPtr + len;
	    char *destPtr = (data = ckalloc(len));
	    char *destPtr = (data = (char *)ckalloc(len));

	    while (srcPtr < endPtr) {
		*destPtr++ = xBitReverseTable[(unsigned char)(*(srcPtr++))];
	    }
	} else {
	    data = memcpy(ckalloc(len), image->data + image->xoffset, len);
	}
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
135
136
137
138
139
140
141







































































































































142
143
144
145
146
147
148







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







    }
    return img;
}

/*
 *----------------------------------------------------------------------
 *
 * XGetImage --
 *
 *	This function copies data from a pixmap or window into an XImage.  It
 *      is essentially never used. At one time it was called by
 *      pTkImgPhotoDisplay, but that is no longer the case. Currently it is
 *      called two places, one of which is requesting an XY image which we do
 *      not support.  It probably does not work correctly -- see the comments
 *      for TkMacOSXBitmapRepFromDrawableRect.
 *
 * Results:
 *	Returns a newly allocated XImage containing the data from the given
 *	rectangle of the given drawable, or NULL if the XImage could not be
 *	constructed.  NOTE: If we are copying from a window on a Retina
 *	display, the dimensions of the XImage will be 2*width x 2*height.
 *
 * 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,
    int x,
    int y,
    unsigned int width,
    unsigned int height,
    unsigned long plane_mask,
    int format)
{
    NSBitmapImageRep* bitmap_rep = NULL;
    NSUInteger bitmap_fmt = 0;
    XImage* imagePtr = NULL;
    char* bitmap = NULL;
    char R, G, B, A;
    int depth = 32, offset = 0, bitmap_pad = 0;
    unsigned int bytes_per_row, size, row, n, m;
    unsigned int scalefactor=1, scaled_height=height, scaled_width=width;
    NSWindow *win = TkMacOSXDrawableWindow(drawable);
    static enum {unknown, no, yes} has_retina = unknown;

    if (win && has_retina == unknown) {
#ifdef __clang__
	has_retina = [win respondsToSelector:@selector(backingScaleFactor)] ?
		yes : no;
#else
	has_retina = no;
#endif
    }

    if (has_retina == yes) {
	/*
	 * We only allow scale factors 1 or 2, as Apple currently does.
	 */

#ifdef __clang__
	scalefactor = [win backingScaleFactor] == 2.0 ? 2 : 1;
#endif
	scaled_height *= scalefactor;
	scaled_width *= scalefactor;
    }

    if (format == ZPixmap) {
	if (width == 0 || height == 0) {
	    return NULL;
	}

	bitmap_rep = TkMacOSXBitmapRepFromDrawableRect(drawable,
		x, y, width, height);
	if (!bitmap_rep) {
	    TkMacOSXDbgMsg("XGetImage: Failed to construct NSBitmapRep");
	    return NULL;
	}
	bitmap_fmt = [bitmap_rep bitmapFormat];
	size = [bitmap_rep bytesPerPlane];
	bytes_per_row = [bitmap_rep bytesPerRow];
	bitmap = ckalloc(size);
	if (!bitmap
		|| (bitmap_fmt != 0 && bitmap_fmt != 1)
		|| [bitmap_rep samplesPerPixel] != 4
		|| [bitmap_rep isPlanar] != 0
		|| bytes_per_row < 4 * scaled_width
		|| size != bytes_per_row * scaled_height) {
	    TkMacOSXDbgMsg("XGetImage: Unrecognized bitmap format");
	    CFRelease(bitmap_rep);
	    return NULL;
	}
	memcpy(bitmap, (char *)[bitmap_rep bitmapData], size);
	CFRelease(bitmap_rep);

	/*
	 * 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;

	for (row = 0, n = 0; row < scaled_height; row++, n += bytes_per_row) {
	    for (m = n; m < n + 4*scaled_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;
	    }
	}
	imagePtr = XCreateImage(display, NULL, depth, format, offset,
		(char*) bitmap, scaled_width, scaled_height,
		bitmap_pad, bytes_per_row);
	if (scalefactor == 2) {
	    imagePtr->pixelpower = 1;
	}
    } 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;
}

/*
 *----------------------------------------------------------------------
 *
 * DestroyImage --
 *
 *	Destroys storage associated with an image.
 *
 * Results:
 *	None.
 *
296
297
298
299
300
301
302

303




304
305
306
307
308
309
310
311
312
313
314
315
316
317
318





319
320
321
322
323
324
325

326
327
328
329
330
331
332
333
334
335

336
337
338
339
340

341
342
343
344
345
346
347
348

349
350
351
352
353
354
355
356

357
358
359
360
361


362
363
364
365
366
367
368
169
170
171
172
173
174
175
176

177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206

207
208
209
210
211
212
213
214
215
216

217
218
219
220
221

222
223
224
225
226
227
228
229

230
231
232
233
234
235
236
237

238
239
240
241
242

243
244
245
246
247
248
249
250
251







+
-
+
+
+
+















+
+
+
+
+






-
+









-
+




-
+







-
+







-
+




-
+
+







 *----------------------------------------------------------------------
 *
 * ImageGetPixel --
 *
 *	Get a single pixel from an image.
 *
 * Results:
 *      The XColor structure contains an unsigned long field named pixel which
 *	Returns the 32 bit pixel value.
 *      identifies the color.  This function returns the unsigned long that
 *      would be used as the pixel value of an XColor that has the same red
 *      green and blue components as the XImage pixel at the specified
 *      location.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static unsigned long
ImageGetPixel(
    XImage *image,
    int x,
    int y)
{
    unsigned char r = 0, g = 0, b = 0;

    /*
     * Compute 8 bit red green and blue values, which are passed as inputs to
     * TkMacOSXRGBPixel to produce the pixel value.
     */

    if (image && image->data) {
	unsigned char *srcPtr = ((unsigned char*) image->data)
		+ (y * image->bytes_per_line)
		+ (((image->xoffset + x) * image->bits_per_pixel) / NBBY);

	switch (image->bits_per_pixel) {
	case 32:
	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];
	    }*/
	    break;
	case 16:
	case 16: /* 5 bits per channel */
	    r = (*((unsigned short*) srcPtr) >> 7) & 0xf8;
	    g = (*((unsigned short*) srcPtr) >> 2) & 0xf8;
	    b = (*((unsigned short*) srcPtr) << 3) & 0xf8;
	    break;
	case 8:
	case 8: /* 2 bits per channel */
	    r = (*srcPtr << 2) & 0xc0;
	    g = (*srcPtr << 4) & 0xc0;
	    b = (*srcPtr << 6) & 0xc0;
	    r |= r >> 2 | r >> 4 | r >> 6;
	    g |= g >> 2 | g >> 4 | g >> 6;
	    b |= b >> 2 | b >> 4 | b >> 6;
	    break;
	case 4: {
	case 4: { /* 1 bit per channel */
	    unsigned char c = (x % 2) ? *srcPtr : (*srcPtr >> 4);

	    r = (c & 0x04) ? 0xff : 0;
	    g = (c & 0x02) ? 0xff : 0;
	    b = (c & 0x01) ? 0xff : 0;
	    break;
	}
	case 1:
	case 1: /* Black-white bitmap. */
	    r = g = b = ((*srcPtr) & (0x80 >> (x % 8))) ? 0xff : 0;
	    break;
	}
    }
    return (PIXEL_MAGIC << 24) | (r << 16) | (g << 8) | b;

    return TkMacOSXRGBPixel(r, g, b);
}

/*
 *----------------------------------------------------------------------
 *
 * ImagePutPixel --
 *
436
437
438
439
440
441
442
443

444
445
446
447
448
449
450
319
320
321
322
323
324
325

326
327
328
329
330
331
332
333







-
+







 *
 *----------------------------------------------------------------------
 */

XImage *
XCreateImage(
    Display* display,
    Visual* visual,
    TCL_UNUSED(Visual*),  /* visual */
    unsigned int depth,
    int format,
    int offset,
    char* data,
    unsigned int width,
    unsigned int height,
    int bitmap_pad,
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
342
343
344
345
346
347
348







349
350
351
352
353
354
355







-
-
-
-
-
-
-







    ximage->width = width;
    ximage->depth = depth;
    ximage->xoffset = offset;
    ximage->format = format;
    ximage->data = data;
    ximage->obdata = NULL;

    /*
     * The default pixelpower is 0.  This must be explicitly set to 1 in the
     * case of an XImage extracted from a Retina display.
     */

    ximage->pixelpower = 0;

    if (format == ZPixmap) {
	ximage->bits_per_pixel = 32;
	ximage->bitmap_unit = 32;
    } else {
	ximage->bits_per_pixel = 1;
	ximage->bitmap_unit = 8;
    }
512
513
514
515
516
517
518
519

520
521
522
523
524
525
526
388
389
390
391
392
393
394

395
396
397
398
399
400
401
402







-
+








    return ximage;
}

/*
 *----------------------------------------------------------------------
 *
 * TkPutImage, XPutImage --
 * XPutImage --
 *
 *	Copies a rectangular subimage of an XImage into a drawable.  Currently
 *      this is only called by TkImgPhotoDisplay, using a Window as the
 *      drawable.
 *
 * Results:
 *	None.
538
539
540
541
542
543
544
545

546
547
548

549
550
551

552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577

578
579
580
581
582
583
584
585
586
587
588
589
590
591
















































































































































































































































































































































592
593





























594
595
596
597
598
599
600
601
602
603
604
605
606
607
















































































608
609
610
611
612
613
614
615
616
617
414
415
416
417
418
419
420

421
422
423

424
425
426

427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442









443

444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825














826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915







-
+


-
+


-
+















-
-
-
-
-
-
-
-
-

-
+














+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+










    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;
    MacDrawable *macDraw = (MacDrawable *)drawable;

    display->request++;
    if (!TkMacOSXSetupDrawingContext(drawable, gc, 1, &dc)) {
    if (!TkMacOSXSetupDrawingContext(drawable, gc, &dc)) {
	return BadDrawable;
    }
    if (dc.context) {
	CGRect bounds, srcRect, dstRect;
	CGImageRef img = TkMacOSXCreateCGImageWithXImage(image);

	/*
	 * The CGContext for a pixmap is RGB only, with A = 0.
	 */

	if (!(macDraw->flags & TK_IS_PIXMAP)) {
	    CGContextSetBlendMode(dc.context, kCGBlendModeSourceAtop);
	}
	if (img) {

	    /*
	     * If the XImage has big pixels, the source is rescaled to reflect
	     * the actual pixel dimensions.  This is not currently used, but
	     * could arise if the image were copied from a retina monitor and
	     * redrawn on an ordinary monitor.
	     */

	    int pp = image->pixelpower;

	    bounds = CGRectMake(0, 0, image->width, image->height);
	    srcRect = CGRectMake(src_x<<pp, src_y<<pp, width<<pp, height<<pp);
	    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");
	}
    } else {
	TkMacOSXDbgMsg("Invalid destination drawable");
    }
    TkMacOSXRestoreDrawingContext(&dc);
    return Success;
}

/*
 *----------------------------------------------------------------------
 *
 * 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
 *      [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.
 *
 * 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.
 *
 *      NOTE: The x,y coordinates should be relative to a coordinate system
 *      with origin at the top left, as used by XImage and CGImage, not bottom
 *      left as used by NSView.
 *
 * Side effects:
 *     None
 *
 *----------------------------------------------------------------------
 */

static CGImageRef
CreateCGImageFromDrawableRect(
    Drawable drawable,
    int x,
    int y,
    unsigned int width,
    unsigned int height)
{
    MacDrawable *mac_drawable = (MacDrawable *)drawable;
    CGContextRef cg_context = NULL;
    CGImageRef cg_image = NULL, result = NULL;
    NSBitmapImageRep *bitmapRep = nil;
    NSView *view = nil;
    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) != nil) {

	/*
	 * 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");
    }
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * CreateCGImageFromPixmap --
 *
 *	Create a CGImage from an X Pixmap.
 *
 * Results:
 *	CGImage, release after use.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static CGImageRef
CreateCGImageFromPixmap(
    Drawable pixmap)
{
    CGImageRef img = NULL;
    CGContextRef context = TkMacOSXGetCGContextForDrawable(pixmap);

    if (context) {
	img = CGBitmapContextCreateImage(context);
    }
    return img;
}

/*
 *----------------------------------------------------------------------
 *
 * XGetImage --
 *
 *	This function copies data from a pixmap or window into an XImage.  It
 *      is essentially never used. At one time it was called by
 *      pTkImgPhotoDisplay, but that is no longer the case. Currently it is
 *      called two places, one of which is requesting an XY image which we do
 *      not support.  It probably does not work correctly -- see the comments
 *      for CGImageFromDrawableRect.
 *
 * Results:
 *	Returns a newly allocated XImage containing the data from the given
 *	rectangle of the given drawable, or NULL if the XImage could not be
 *	constructed.
 *
 * 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,
    int x,
    int y,
    unsigned int width,
    unsigned int height,
    TCL_UNUSED(unsigned long), /* plane_mask */
    int format)
{
    NSBitmapImageRep* bitmapRep = nil;
    NSUInteger bitmap_fmt = 0;
    XImage* imagePtr = NULL;
    char* bitmap = NULL;
    char R, G, B, A;
    int depth = 32, offset = 0, bitmap_pad = 0;
    unsigned int bytes_per_row, size, row, n, m;

    if (format == ZPixmap) {
	CGImageRef cgImage;
	if (width == 0 || height == 0) {
	    return NULL;
	}

	cgImage = CreateCGImageFromDrawableRect(drawable, x, y, width, height);
	if (cgImage) {
	    bitmapRep = [NSBitmapImageRep alloc];
	    [bitmapRep initWithCGImage:cgImage];
	    CFRelease(cgImage);
	} else {
	    TkMacOSXDbgMsg("XGetImage: Failed to construct CGImage");
	    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) {
	    TkMacOSXDbgMsg("XGetImage: Unrecognized bitmap format");
	    CFRelease(bitmapRep);
	    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;

	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;
	    }
	}
	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;
}

/*
 *----------------------------------------------------------------------
 *
 * XCopyArea --
 *
 *	Copies image data from one drawable to another.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Image data is moved from a window or bitmap to a second window or bitmap.
 *
 *----------------------------------------------------------------------
 */

int
XCopyArea(
    Display *display,		/* Display. */
    Drawable src,		/* Source drawable. */
    Drawable dst,		/* Destination drawable. */
    GC gc,			/* GC to use. */
    int src_x,			/* X & Y, width & height */
    int src_y,			/* define the source rectangle */
    unsigned int width,		/* that will be copied. */
    unsigned int height,
    int dest_x,			/* Dest X & Y on dest rect. */
    int dest_y)
{
    TkMacOSXDrawingContext dc;
    MacDrawable *srcDraw = (MacDrawable *)src;
    CGImageRef img = NULL;
    CGRect bounds, srcRect, dstRect;

    display->request++;
    if (!width || !height) {
	return BadDrawable;
    }

    if (!TkMacOSXSetupDrawingContext(dst, gc, &dc)) {
	TkMacOSXDbgMsg("Failed to setup drawing context.");
	return BadDrawable;
    }

    if (!dc.context) {
	TkMacOSXDbgMsg("Invalid destination drawable - no context.");
	return BadDrawable;
    }

    if (srcDraw->flags & TK_IS_PIXMAP) {
	img = CreateCGImageFromPixmap(src);
    } else if (TkMacOSXGetNSWindowForDrawable(src)) {
	img = CreateCGImageFromDrawableRect(src, src_x, src_y, width, height);
    } else {
	TkMacOSXDbgMsg("Invalid source drawable - neither window nor pixmap.");
    }

    if (img) {
	bounds = CGRectMake(0, 0, srcDraw->size.width, srcDraw->size.height);
	srcRect = CGRectMake(src_x, src_y, width, height);
	dstRect = CGRectMake(dest_x, dest_y, width, height);
	TkMacOSXDrawCGImage(dst, gc, dc.context, img,
		gc->foreground, gc->background, bounds, srcRect, dstRect);
	CFRelease(img);
    } else {
	TkMacOSXDbgMsg("Failed to construct CGImage.");
    }

    TkMacOSXRestoreDrawingContext(&dc);
    return Success;
}

/*
 *----------------------------------------------------------------------
 *
 * XCopyPlane --
 *
 *	Copies a bitmap from a source drawable to a destination drawable. The
 *	plane argument specifies which bit plane of the source contains the
 *	bitmap. Note that this implementation ignores the gc->function.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Changes the destination drawable.
 *
 *----------------------------------------------------------------------
 */

int
XCopyPlane(
    Display *display,		/* Display. */
    Drawable src,		/* Source drawable. */
    Drawable dst,		/* Destination drawable. */
    GC gc,				/* GC to use. */
    int src_x,			/* X & Y, width & height */
    int src_y,			/* define the source rectangle */
    unsigned int width,	/* that will be copied. */
    unsigned int height,
    int dest_x,			/* Dest X & Y on dest rect. */
    int dest_y,
    unsigned long plane)	/* Which plane to copy. */
{
    TkMacOSXDrawingContext dc;
    MacDrawable *srcDraw = (MacDrawable *)src;
    MacDrawable *dstDraw = (MacDrawable *)dst;
    CGRect bounds, srcRect, dstRect;
    display->request++;
    if (!width || !height) {
	/* TkMacOSXDbgMsg("Drawing of empty area requested"); */
	return BadDrawable;
    }
    if (plane != 1) {
	Tcl_Panic("Unexpected plane specified for XCopyPlane");
    }
    if (srcDraw->flags & TK_IS_PIXMAP) {
	if (!TkMacOSXSetupDrawingContext(dst, gc, &dc)) {
	    return BadDrawable;
	}
TkPutImage(
    unsigned long *colors,	/* Array of pixel values used by this image.
				 * May be NULL. */
    int ncolors,		/* Number of colors used, or 0. */
    Display *display,
    Drawable d,			/* Destination drawable. */
    GC gc,
    XImage *image,		/* Source image. */
    int src_x, int src_y,	/* Offset of subimage. */
    int dest_x, int dest_y,	/* Position of subimage origin in drawable. */
    unsigned int width, unsigned int height)
				/* Dimensions of subimage. */
{
    return XPutImage(display, d, gc, image, src_x, src_y, dest_x, dest_y, width, height);

	CGContextRef context = dc.context;

	if (context) {
	    CGImageRef img = CreateCGImageFromPixmap(src);

	    if (img) {
		TkpClipMask *clipPtr = (TkpClipMask *) gc->clip_mask;
		unsigned long imageBackground  = gc->background;

                if (clipPtr && clipPtr->type == TKP_CLIP_PIXMAP) {
		    srcRect = CGRectMake(src_x, src_y, width, height);
		    CGImageRef mask = CreateCGImageFromPixmap(
			    clipPtr->value.pixmap);
		    CGImageRef submask = CGImageCreateWithImageInRect(
			    img, srcRect);
		    CGRect rect = CGRectMake(dest_x, dest_y, width, height);

		    rect = CGRectOffset(rect, dstDraw->xOff, dstDraw->yOff);
		    CGContextSaveGState(context);

		    /*
		     * Move the origin of the destination to top left.
		     */

		    CGContextTranslateCTM(context,
			    0, rect.origin.y + CGRectGetMaxY(rect));
		    CGContextScaleCTM(context, 1, -1);

		    /*
		     * Fill with the background color, clipping to the mask.
		     */

		    CGContextClipToMask(context, rect, submask);
		    TkMacOSXSetColorInContext(gc, gc->background, dc.context);
		    CGContextFillRect(context, rect);

		    /*
		     * Fill with the foreground color, clipping to the
		     * intersection of img and mask.
		     */

		    CGImageRef subimage = CGImageCreateWithImageInRect(
			    img, srcRect);
		    CGContextClipToMask(context, rect, subimage);
		    TkMacOSXSetColorInContext(gc, gc->foreground, context);
		    CGContextFillRect(context, rect);
		    CGContextRestoreGState(context);
		    CGImageRelease(img);
		    CGImageRelease(mask);
		    CGImageRelease(submask);
		    CGImageRelease(subimage);
		} else {
		    bounds = CGRectMake(0, 0,
			    srcDraw->size.width, srcDraw->size.height);
		    srcRect = CGRectMake(src_x, src_y, width, height);
		    dstRect = CGRectMake(dest_x, dest_y, width, height);
		    TkMacOSXDrawCGImage(dst, gc, dc.context, img,
			    gc->foreground, imageBackground, bounds,
			    srcRect, dstRect);
		    CGImageRelease(img);
		}
	    } else {
		/* no image */
		TkMacOSXDbgMsg("Invalid source drawable");
	    }
	} else {
	    TkMacOSXDbgMsg("Invalid destination drawable - "
		    "could not get a bitmap context.");
	}
	TkMacOSXRestoreDrawingContext(&dc);
	return Success;
    } else {
	/*
	 * Source drawable is a Window, not a Pixmap.
	 */

	return XCopyArea(display, src, dst, gc, src_x, src_y, width, height,
		dest_x, dest_y);
    }
}

/*
 * Local Variables:
 * mode: objc
 * c-basic-offset: 4
 * fill-column: 79
 * coding: utf-8
 * End:
 */
Changes to macosx/tkMacOSXInit.c.
1
2
3
4
5
6
7
8
9
10




11
12
13
14
15
16
17
18
19
20

21
22
23
24
25
26
27
28
29
30







31
32
33
34
35

36


37
38
39
40
41
42
43
1
2
3
4
5
6




7
8
9
10
11
12
13
14
15
16


17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

41
42
43
44
45
46
47
48
49
50
51






-
-
-
-
+
+
+
+






-
-


+










+
+
+
+
+
+
+




-
+

+
+







/*
 * 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 <[email protected]>
 * Copyright (c) 2017 Marc Culler
 * Copyright © 1995-1997 Sun Microsystems, Inc.
 * Copyright © 2001-2009 Apple Inc.
 * Copyright © 2005-2009 Daniel A. Steffen <[email protected]>
 * 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.
 */

#include "tkMacOSXPrivate.h"

#include <sys/stat.h>
#include <dlfcn.h>
#include <objc/objc-auto.h>
#include <sys/stat.h>

static char tkLibPath[PATH_MAX + 1] = "";

/*
 * If the App is in an App package, then we want to add the Scripts directory
 * to the auto_path.
 */

static char scriptPath[PATH_MAX + 1] = "";

/*
 * Forward declarations...
 */

static int		TkMacOSXGetAppPathCmd(ClientData cd, Tcl_Interp *ip,
			    int objc, Tcl_Obj *const objv[]);

#pragma mark TKApplication(TKInit)

@implementation TKApplication
@synthesize poolLock = _poolLock;
@synthesize macMinorVersion = _macMinorVersion;
@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.
 */
#undef DEBUG_LOCK
71
72
73
74
75
76
77
78

79
80
81
82
83
84
85
86
87

88
89
90
91
92
93
94
95
96
97
98
99
100



101
102


103
104
105
106
107




108
109
110
111
112
113
114
115




116
117
118



119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137

138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156

157

158
159

160
161
162

163
164
165

166
167
168
169
170
171
172
79
80
81
82
83
84
85

86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106



107
108
109


110
111

112



113
114
115
116
117
118
119
120
121
122
123

124
125
126
127
128


129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149

150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170

171
172
173
174
175
176
177
178
179
180

181
182
183
184
185
186
187
188







-
+









+










-
-
-
+
+
+
-
-
+
+
-

-
-
-
+
+
+
+







-
+
+
+
+

-
-
+
+
+


















-
+



















+
-
+


+



+


-
+








- (void) _setupApplicationNotifications
{
    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
#define observe(n, s) \
	[nc addObserver:self selector:@selector(s) name:(n) object:nil]
    observe(NSApplicationDidBecomeActiveNotification, applicationActivate:);
    observe(NSApplicationDidResignActiveNotification, applicationDeactivate:);
    observe(NSApplicationWillResignActiveNotification, applicationDeactivate:);
    observe(NSApplicationDidUnhideNotification, applicationShowHide:);
    observe(NSApplicationDidHideNotification, applicationShowHide:);
    observe(NSApplicationDidChangeScreenParametersNotification, displayChanged:);
    observe(NSTextInputContextKeyboardSelectionDidChangeNotification, keyboardChanged:);
#undef observe
}

-(void)applicationWillFinishLaunching:(NSNotification *)aNotification
{
    (void)aNotification;

    /*
     * Initialize notifications.
     */
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
    [[NSNotificationCenter defaultCenter] addObserver:self
	    selector:@selector(_postedNotification:) name:nil object:nil];
#endif
    [self _setupWindowNotifications];
    [self _setupApplicationNotifications];

    /*
     * Construct the menu bar.
}

-(void)applicationDidFinishLaunching:(NSNotification *)notification
     */
    _defaultMainMenu = nil;
{
    (void)notification;
    [self _setupMenus];

    /*
     * Initialize event processing.
     */
   /*
    * Initialize event processing.
    */

    TkMacOSXInitAppleEvents(_eventInterp);

    /*
     * Initialize the graphics context.
     */
    TkMacOSXUseAntialiasedText(_eventInterp, -1);
    TkMacOSXInitCGDrawing(_eventInterp, TRUE, 0);
}

    /*
     * Construct the menu bar.
     */

-(void)applicationDidFinishLaunching:(NSNotification *)notification
{
    _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.
     * However, with the release of macOS 10.15 (Catalina) that was no longer
     * sufficient.  (See ticket bf93d098d7.)  The call to setActivationPolicy
     * needed to be moved into this function as well.
     */

    [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
    [NSApp activateIgnoringOtherApps: YES];

    /*
     * Process events to ensure that the root window is fully initialized. See
     * ticket 56a1823c73.
     */

    [NSApp _lockAutoreleasePool];
    while (Tcl_DoOneEvent(TCL_WINDOW_EVENTS| TCL_DONT_WAIT)) {}
    while (Tcl_DoOneEvent(TCL_WINDOW_EVENTS|TCL_DONT_WAIT)) {}
    [NSApp _unlockAutoreleasePool];
}

- (void) _setup: (Tcl_Interp *) interp
{
    /*
     * Remember our interpreter.
     */
    _eventInterp = interp;

    /*
     * Install the global autoreleasePool.
     */
    _mainPool = [NSAutoreleasePool new];
    [NSApp setPoolLock:0];

    /*
     * Record the OS version we are running on.
     */

    int minorVersion;
    int minorVersion, majorVersion;
#if MAC_OS_X_VERSION_MAX_ALLOWED < 101000
    Gestalt(gestaltSystemVersionMinor, (SInt32*)&minorVersion);
    majorVersion = 10;
#else
    NSOperatingSystemVersion systemVersion;
    systemVersion = [[NSProcessInfo processInfo] operatingSystemVersion];
    majorVersion = systemVersion.majorVersion;
    minorVersion = systemVersion.minorVersion;
#endif
    [NSApp setMacMinorVersion: minorVersion];
    [NSApp setMacOSVersion: 10000*majorVersion + 100*minorVersion];

    /*
     * We are not drawing right now.
     */

    [NSApp setIsDrawing:NO];

252
253
254
255
256
257
258
259










































































260
261
262
263
264
265
266
267
268


269
270
271
272
273
274
275



276
277
278
279
280
281
282
283
284


285

286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329

330
331
332
333
334
335
336
337








338
339

340
341
342
343
344
345
346
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356


357
358

359
360
361
362


363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393










394
395
396
397
398
399
400
401
402
403
404
405
406
407
408

409
410

411








412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







-
-
+
+
-




-
-
+
+
+









+
+

+















-
-
-
-
-
-
-
-
-
-















-


-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+


+







 *	the interp's result.
 *
 * Side effects:
 *	Sets "tk_library" Tcl variable, runs "tk.tcl" script.
 *
 *----------------------------------------------------------------------
 */

/*
 * Helper function which closes the shared NSFontPanel and NSColorPanel.
 */

static void closePanels(
    void)
{
    if ([NSFontPanel sharedFontPanelExists]) {
	[[NSFontPanel sharedFontPanel] orderOut:nil];
    }
    if ([NSColorPanel sharedColorPanelExists]) {
        [[NSColorPanel sharedColorPanel] orderOut:nil];
    }
}

/*
 * This custom exit procedure is called by Tcl_Exit in place of the exit
 * function from the C runtime.  It calls the terminate method of the
 * NSApplication class (superTerminate for a TKApplication).  The purpose of
 * doing this is to ensure that the NSFontPanel and the NSColorPanel are closed
 * before the process exits, and that the application state is recorded
 * correctly for all termination scenarios.
 *
 * TkpWantsExitProc tells Tcl_AppInit whether to install our custom exit proc,
 * which terminates the process by calling [NSApplication terminate].  This
 * does not work correctly if the process is part of an exec pipeline, so it is
 * only done if the process was launched by the launcher or if both stdin and
 * stdout are ttys.  To disable using the custom exit proc altogether, undefine
 * USE_CUSTOM_EXIT_PROC.
 */

#if defined(USE_CUSTOM_EXIT_PROC)
static Bool doCleanupFromExit = NO;

int TkpWantsExitProc(void) {
    return doCleanupFromExit == YES;
}

TCL_NORETURN void TkpExitProc(
    void *clientdata)
{
    Bool doCleanup = doCleanupFromExit;
    if (doCleanupFromExit) {
	doCleanupFromExit = NO; /* prevent possible recursive call. */
	closePanels();
    }

    /*
     * Tcl_Exit does not call Tcl_Finalize if there is an exit proc installed.
     */

    Tcl_Finalize();
    if (doCleanup == YES) {
	[(TKApplication *)NSApp superTerminate:nil]; /* Should not return. */
    }
    exit((long)clientdata); /* Convince the compiler that we don't return. */
}
#endif

/*
 * This signal handler is installed for the SIGINT, SIGHUP and SIGTERM signals
 * so that normal finalization occurs when a Tk app is killed by one of these
 * signals (e.g when ^C is pressed while running Wish in the shell).  It calls
 * Tcl_Exit instead of the C runtime exit function called by the default handler.
 * This is consistent with the Tcl_Exit manual page, which says that Tcl_Exit
 * should always be called instead of exit.  When Tk is killed by a signal we
 * return exit status 1.
 */

static void TkMacOSXSignalHandler(TCL_UNUSED(int)) {

    Tcl_Exit(1);
}

int
TkpInit(
    Tcl_Interp *interp)
{
    static int initialized = 0;

    /*
     * Since it is possible for TkInit to be called multiple times and we
     * don't want to do the following initialization multiple times we protect
     * TkpInit can be called multiple times with different interpreters. But
     * The application initialization should only be done onece.
     * against doing it more than once.
     */

    if (!initialized) {
	struct stat st;

	initialized = 1;
	Bool shouldOpenConsole = NO;
        Bool stdinIsNullish = (!isatty(0) &&
	    (fstat(0, &st) || (S_ISCHR(st.st_mode) && st.st_blocks == 0)));

	/*
	 * Initialize/check OS version variable for runtime checks.
	 */

#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
#   error Mac OS X 10.6 required
#endif

	initialized = 1;

#ifdef TK_FRAMEWORK

	/*
	 * When Tk is in a framework, force tcl_findLibrary to look in the
	 * framework scripts directory.
	 * FIXME: Should we come up with a more generic way of doing this?
	 */

	if (Tcl_MacOSXOpenVersionedBundleResources(interp,
		"com.tcltk.tklibrary", TK_FRAMEWORK_VERSION, 0, PATH_MAX,
		tkLibPath) != TCL_OK) {
            # if 0 /* This is not really an error.  Wish still runs fine. */
	    TkMacOSXDbgMsg("Tcl_MacOSXOpenVersionedBundleResources failed");
	    # endif
	}
#endif

	/*
	 * FIXME: Close stdin & stdout for remote debugging otherwise we will
	 * fight with gdb for stdin & stdout
	 */

	if (getenv("XCNOSTDIN") != NULL) {
	    close(0);
	    close(1);
	}

	/*
	 * Instantiate our NSApplication object. This needs to be done before
	 * we check whether to open a console window.
	 */

	NSAutoreleasePool *pool = [NSAutoreleasePool new];
	[[NSUserDefaults standardUserDefaults] registerDefaults:
		[NSDictionary dictionaryWithObjectsAndKeys:
				  [NSNumber numberWithBool:YES],
			      @"_NSCanWrapButtonTitles",
				   [NSNumber numberWithInt:-1],
			      @"NSStringDrawingTypesetterBehavior",
			      nil]];
	[TKApplication sharedApplication];
	[pool drain];
	[NSApp _setup:interp];

        /*
         * WARNING: The finishLaunching method runs asynchronously, apparently
         * WARNING: The finishLaunching method runs asynchronously. This
         * in a separate thread.  This creates a race between the
         * initialization of the NSApplication and the initialization of Tk.
         * If Tk wins the race bad things happen with the root window (see
         * below).  If the NSApplication wins then an AppleEvent created during
         * launch, e.g. by dropping a file icon on the application icon, will
         * be delivered before the procedure meant to to handle the AppleEvent
         * has been defined.  This is now handled by processing the AppleEvent
         * as an idle task.  See tkMacOSXHLEvents.c.
         * creates a race between the initialization of the NSApplication and
         * the initialization of Tk.  If Tk wins the race bad things happen
         * with the root window (see below).  If the NSApplication wins then an
         * AppleEvent created during launch, e.g. by dropping a file icon on
         * the application icon, will be delivered before the procedure meant
         * to to handle the AppleEvent has been defined.  This is handled in
         * tkMacOSXHLEvents.c by scheduling a timer event to handle the
         * ApplEvent later, after the required procedure has been defined.
         */

	[NSApp _setup:interp];
	[NSApp finishLaunching];

        /*
         * Create a Tk event source based on the Appkit event queue.
         */

	Tk_MacOSXSetupTkNotifier();
359
360
361
362
363
364
365
366

367
368


369
370
371

372
373
374
375
376
377
378

379
380
381
382
383
384
385
386



387
388
389


390
391
392













393
394
395

























396
397
398
399
400
401
402
403
404
405







406
































407
408
409
410
411
412
413
414
415
416
417
418
419
420




421
422
423
424
425
426
427
442
443
444
445
446
447
448

449


450
451
452
453

454







455








456
457
458



459
460
461


462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511

512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564

565
566
567
568
569
570
571
572
573
574
575







-
+
-
-
+
+


-
+
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
+
+
+
-
-
-
+
+

-
-
+
+
+
+
+
+
+
+
+
+
+
+
+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+









-
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+













-
+
+
+
+







         * NSApplication initialization wins the race, avoiding these bad
         * window behaviors.
	 */

	Tcl_DoOneEvent(TCL_WINDOW_EVENTS | TCL_DONT_WAIT);

	/*
	 * If we don't have a TTY and stdin is a special character file of
	 * Decide whether to open a console window.  If the TK_CONSOLE
	 * length 0, (e.g. /dev/null, which is what Finder sets when double
	 * clicking Wish) then use the Tk based console interpreter.
	 * environment variable is not defined we only show the console if
	 * stdin is not a tty and there is no startup script.
	 */

	if (getenv("TK_CONSOLE") ||
	if (getenv("TK_CONSOLE")) {
		(!isatty(0) && (fstat(0, &st) ||
		(S_ISCHR(st.st_mode) && st.st_blocks == 0)))) {
	    Tk_InitConsoleChannels(interp);
	    Tcl_RegisterChannel(interp, Tcl_GetStdChannel(TCL_STDIN));
	    Tcl_RegisterChannel(interp, Tcl_GetStdChannel(TCL_STDOUT));
	    Tcl_RegisterChannel(interp, Tcl_GetStdChannel(TCL_STDERR));

	    shouldOpenConsole = YES;
	    /*
	     * Only show the console if we don't have a startup script and
	     * tcl_interactive hasn't been set already.
	     */

	    if (Tcl_GetStartupScript(NULL) == NULL) {
		const char *intvar = Tcl_GetVar2(interp,
			"tcl_interactive", NULL, TCL_GLOBAL_ONLY);
	} else if (stdinIsNullish && Tcl_GetStartupScript(NULL) == NULL) {
	    const char *intvar = Tcl_GetVar2(interp, "tcl_interactive",
					     NULL, TCL_GLOBAL_ONLY);

		if (intvar == NULL) {
		    Tcl_SetVar2(interp, "tcl_interactive", NULL, "1",
	    if (intvar == NULL) {
		Tcl_SetVar2(interp, "tcl_interactive", NULL, "1",
			    TCL_GLOBAL_ONLY);
		}
	    }
	    }

#if defined(USE_CUSTOM_EXIT_PROC)
	    doCleanupFromExit = YES;
#endif

	    shouldOpenConsole = YES;
	}
	if (shouldOpenConsole) {
	    Tk_InitConsoleChannels(interp);
	    Tcl_RegisterChannel(interp, Tcl_GetStdChannel(TCL_STDIN));
	    Tcl_RegisterChannel(interp, Tcl_GetStdChannel(TCL_STDOUT));
	    Tcl_RegisterChannel(interp, Tcl_GetStdChannel(TCL_STDERR));
	    if (Tk_CreateConsoleWindow(interp) == TCL_ERROR) {
		return TCL_ERROR;
	    }
	} else if (stdinIsNullish) {

	    /*
	     * When launched as a macOS application with no console,
	     * redirect stderr and stdout to /dev/null. This avoids waiting
	     * forever for those files to become writable if the underlying
	     * Tcl program tries to write to them with a puts command.
	     */

	    FILE *null = fopen("/dev/null", "w");
	    dup2(fileno(null), STDOUT_FILENO);
	    dup2(fileno(null), STDERR_FILENO);
#if defined(USE_CUSTOM_EXIT_PROC)
	    doCleanupFromExit = YES;
#endif
	}

	/*
	 * FIXME: Close stdin & stdout for remote debugging if XCNOSTDIN is
	 * set.  Otherwise we will fight with gdb for stdin & stdout
	 */

	if (getenv("XCNOSTDIN") != NULL) {
	    close(0);
	    close(1);
	}

	/*
	 * Initialize the NSServices object here. Apple's docs say to do this
	 * in applicationDidFinishLaunching, but the Tcl interpreter is not
	 * initialized until this function call.
	 */

	TkMacOSXServices_Init(interp);
    }

	/*
	 * The root window has been created and mapped, but XMapWindow deferred its
	 * call to makeKeyAndOrderFront because the first call to XMapWindow
	 * occurs too early in the initialization process for that.  Process idle
	 * tasks now, so the root window is configured, then order it front.
	 */

	while(Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {};
	for (NSWindow *window in [NSApp windows]) {
	    TkWindow *winPtr = TkMacOSXGetTkWindow(window);
	    if (winPtr && Tk_IsMapped(winPtr)) {
		[window makeKeyAndOrderFront:NSApp];
		break;
	    }
	}

# if defined(USE_CUSTOM_EXIT_PROC)

	if ((isatty(0) && isatty(1))) {
	    doCleanupFromExit = YES;
	}

# endif

	/*
	 * Install a signal handler for SIGINT, SIGHUP and SIGTERM which uses
	 * Tcl_Exit instead of exit so that normal cleanup takes place if a TK
	 * application is killed with one of these signals.
	 */

	signal(SIGINT, TkMacOSXSignalHandler);
	signal(SIGHUP, TkMacOSXSignalHandler);
	signal(SIGTERM, TkMacOSXSignalHandler);
    }

    /*
     * Initialization steps that are needed for all interpreters.
     */

    if (tkLibPath[0] != '\0') {
	Tcl_SetVar2(interp, "tk_library", NULL, tkLibPath, TCL_GLOBAL_ONLY);
    }

    if (scriptPath[0] != '\0') {
	Tcl_SetVar2(interp, "auto_path", NULL, scriptPath,
		TCL_GLOBAL_ONLY|TCL_LIST_ELEMENT|TCL_APPEND_VALUE);
    }

    Tcl_CreateObjCommand(interp, "::tk::mac::standardAboutPanel",
	    TkMacOSXStandardAboutPanelObjCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "::tk::mac::iconBitmap",
	    TkMacOSXIconBitmapObjCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "::tk::mac::GetAppPath", TkMacOSXGetAppPath, NULL, NULL);
    Tcl_CreateObjCommand(interp, "::tk::mac::GetAppPath",
	    TkMacOSXGetAppPathCmd, NULL, NULL);
    MacSystrayInit(interp);

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TkpGetAppName --
453
454
455
456
457
458
459
460

461
462
463
464

465
466
467
468
469
470
471
472
473
474
475


476

477
478
479
480




481
482

483
484
485


486
487
488
489

490
491
492
493
494



495

496


497
498
499
500



501

502

503
504
505
506
507
508
509
510





511
512
513
514
515
516
517
518
601
602
603
604
605
606
607

608
609
610
611

612
613
614
615
616
617
618
619
620
621
622
623
624
625

626




627
628
629
630
631

632



633
634




635

636



637
638
639
640
641

642
643
644



645
646
647
648
649

650
651







652
653
654
655
656

657
658
659
660
661
662
663







-
+



-
+











+
+
-
+
-
-
-
-
+
+
+
+

-
+
-
-
-
+
+
-
-
-
-
+
-

-
-
-
+
+
+

+
-
+
+

-
-
-
+
+
+

+
-
+

-
-
-
-
-
-
-
+
+
+
+
+
-







	p = strrchr(name, '/');
	if (p != NULL) {
	    name = p+1;
	}
    }
    Tcl_DStringAppend(namePtr, name, -1);
}


/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXGetAppPath --
 * TkMacOSXGetAppPathCmd --
 *
 *	Returns the path of the Wish application bundle.
 *
 * Results:
 *	Returns the application path.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
int TkMacOSXGetAppPath(
TkMacOSXGetAppPathCmd(
		       ClientData cd,
		       Tcl_Interp *ip,
		       int objc,
		       Tcl_Obj *const objv[])
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{

    if (objc != 1) {
  CFURLRef mainBundleURL = CFBundleCopyBundleURL(CFBundleGetMainBundle());


	Tcl_WrongNumArgs(interp, 1, objv, NULL);
	return TCL_ERROR;
  /*
   * Convert the URL reference into a string reference.
   */

    }
  CFStringRef appPath = CFURLCopyFileSystemPath(mainBundleURL, kCFURLPOSIXPathStyle);

  /*
   * Get the system encoding method.
   */
    /*
     * Get the application path URL and convert it to a string path reference.
     */

    CFURLRef mainBundleURL = CFBundleCopyBundleURL(CFBundleGetMainBundle());
  CFStringEncoding encodingMethod = CFStringGetSystemEncoding();
    CFStringRef appPath =
	    CFURLCopyFileSystemPath(mainBundleURL, kCFURLPOSIXPathStyle);

  /*
   * Convert the string reference into a C string.
   */
    /*
     * Convert (and copy) the string reference into a Tcl result.
     */

    Tcl_SetObjResult(interp, Tcl_NewStringObj(
  char *path = (char *) CFStringGetCStringPtr(appPath, encodingMethod);
	    CFStringGetCStringPtr(appPath, CFStringGetSystemEncoding()), -1));

  Tcl_SetResult(ip, path, NULL);

  CFRelease(mainBundleURL);
  CFRelease(appPath);
  return TCL_OK;

}
    CFRelease(mainBundleURL);
    CFRelease(appPath);
    return TCL_OK;
}


/*
 *----------------------------------------------------------------------
 *
 * TkpDisplayWarning --
 *
 *	This routines is called from Tk_Main to display warning messages that
 *	occur during startup.
571
572
573
574
575
576
577
578

579
580
581
582
583
584
585
716
717
718
719
720
721
722

723
724
725
726
727
728
729
730







-
+







	CFURLRef appMainURL = CFBundleCopyResourceURL(bundleRef,
		CFSTR("AppMain"), CFSTR("tcl"), CFSTR("Scripts"));

	if (appMainURL != NULL) {
	    CFURLRef scriptFldrURL;
	    char startupScript[PATH_MAX + 1];

	    if (CFURLGetFileSystemRepresentation (appMainURL, true,
	    if (CFURLGetFileSystemRepresentation(appMainURL, true,
		    (unsigned char *) startupScript, PATH_MAX)) {
		Tcl_SetStartupScript(Tcl_NewStringObj(startupScript,-1), NULL);
		scriptFldrURL = CFURLCreateCopyDeletingLastPathComponent(NULL,
			appMainURL);
		if (scriptFldrURL != NULL) {
		    CFURLGetFileSystemRepresentation(scriptFldrURL, true,
			    (unsigned char *) scriptPath, PATH_MAX);
608
609
610
611
612
613
614
615
616


617
618

619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
753
754
755
756
757
758
759


760
761
762
763
764
765
766
767
768
769








































770
771
772
773
774
775
776
777
778







-
-
+
+


+





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-









 *	None.
 *
 *----------------------------------------------------------------------
 */

MODULE_SCOPE void*
TkMacOSXGetNamedSymbol(
    const char* module,
    const char* symbol)
    TCL_UNUSED(const char *),
    const char *symbol)
{
    void *addr = dlsym(RTLD_NEXT, symbol);

    if (!addr) {
	(void) dlerror(); /* Clear dlfcn error state */
    }
    return addr;
}

/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXGetStringObjFromCFString --
 *
 *	Get a string object from a CFString as efficiently as possible.
 *
 * Results:
 *	New string object or NULL if conversion failed.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

MODULE_SCOPE Tcl_Obj*
TkMacOSXGetStringObjFromCFString(
    CFStringRef str)
{
    Tcl_Obj *obj = NULL;
    const char *c = CFStringGetCStringPtr(str, kCFStringEncodingUTF8);

    if (c) {
	obj = Tcl_NewStringObj(c, -1);
    } else {
	CFRange all = CFRangeMake(0, CFStringGetLength(str));
	CFIndex len;

	if (CFStringGetBytes(str, all, kCFStringEncodingUTF8, 0, false, NULL,
		0, &len) > 0 && len < INT_MAX) {
	    obj = Tcl_NewObj();
	    Tcl_SetObjLength(obj, len);
	    CFStringGetBytes(str, all, kCFStringEncodingUTF8, 0, false,
		    (UInt8*) obj->bytes, len, NULL);
	}
    }
    return obj;
}

/*
 * Local Variables:
 * mode: objc
 * c-basic-offset: 4
 * fill-column: 79
 * coding: utf-8
 * End:
 */
Changes to macosx/tkMacOSXInt.h.
20
21
22
23
24
25
26

27

28
29
30
31
32
33
34
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36







+

+








/*
 * Include platform specific public interfaces.
 */

#ifndef _TKMAC
#include "tkMacOSX.h"
#define Cursor QDCursor
#import <Cocoa/Cocoa.h>
#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.
 */

94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
96
97
98
99
100
101
102

































103
104
105
106
107
108
109







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







 * This is defined in tk.h. We need to duplicate the TK_EMBEDDED flag in the
 * TkWindow structure for the window, but in the MacWin. This way we can
 * 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.
 */

/*
 * This structure is for handling Netscape-type in process
 * embedding where Tk does not control the top-level. It contains
 * various functions that are needed by Mac specific routines, like
 * TkMacOSXGetDrawablePort. The definitions of the function types
 * are in tkMacOSX.h.
 */

typedef struct {
    Tk_MacOSXEmbedRegisterWinProc *registerWinProc;
    Tk_MacOSXEmbedGetGrafPortProc *getPortProc;
    Tk_MacOSXEmbedMakeContainerExistProc *containerExistProc;
    Tk_MacOSXEmbedGetClipProc *getClipProc;
    Tk_MacOSXEmbedGetOffsetInParentProc *getOffsetProc;
} TkMacOSXEmbedHandler;

MODULE_SCOPE TkMacOSXEmbedHandler *tkMacOSXEmbedHandler;

/*
 * 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
#   ifndef CGGEOMETRY_H_
#	ifndef CGFLOAT_DEFINED
176
177
178
179
180
181
182
183

184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201


202
203
204
205

206
207
208
209
210
211
212
213
145
146
147
148
149
150
151

152
153
154
155
156
157
158
159
160
161
162




163
164


165
166
167



168

169
170
171
172
173
174
175







-
+










-
-
-
-


-
-
+
+

-
-
-
+
-








#define TK_LOCATION_CHANGED	1
#define TK_SIZE_CHANGED		2
#define TK_BOTH_CHANGED		3
#define TK_MACOSX_HANDLE_EVENT_IMMEDIATELY 1024

/*
 * Defines for tkTextDisp.c
 * Defines for tkTextDisp.c and tkFont.c
 */

#define TK_LAYOUT_WITH_BASE_CHUNKS	1
#define TK_DRAW_IN_CONTEXT		1

/*
 * Prototypes of internal procs not in the stubs table.
 */

MODULE_SCOPE void TkMacOSXDefaultStartupScript(void);
#if 0
MODULE_SCOPE int XSetClipRectangles(Display *d, GC gc, int clip_x_origin,
	int clip_y_origin, XRectangle* rectangles, int n, int ordering);
#endif
MODULE_SCOPE void TkpClipDrawableToRect(Display *display, Drawable d, int x,
	int y, int width, int height);
MODULE_SCOPE void TkpRetainRegion(TkRegion r);
MODULE_SCOPE void TkpReleaseRegion(TkRegion r);
MODULE_SCOPE void TkpRetainRegion(Region r);
MODULE_SCOPE void TkpReleaseRegion(Region r);
MODULE_SCOPE void TkpShiftButton(NSButton *button, NSPoint delta);
MODULE_SCOPE Bool TkpAppIsDrawing(void);
MODULE_SCOPE void TkpDisplayWindow(Tk_Window tkwin);
MODULE_SCOPE Bool TkTestLogDisplay(void);
MODULE_SCOPE Bool TkTestLogDisplay(Drawable drawable);
MODULE_SCOPE Bool TkMacOSXInDarkMode(Tk_Window tkwin);

/*
 * Include the stubbed internal platform-specific API.
 */

#include "tkIntPlatDecls.h"

Changes to macosx/tkMacOSXKeyEvent.c.
1
2
3
4
5
6
7
8
9
10




11
12
13
14
15
16
17
18





19
20
21
22
23
24

25
26
27


28
29

30
31
32
33
34
35
36
37
38
39
40



41
42
43
44
45
46
47
48
49
50
51



52

53
54
55
56



57
58

59
60

61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155





156

157
158
159
160
161
162







163
164
165

166
167
168
169







170
171
172
173











174
175
176



177
178
179
180
181

182
183
184
185
186
187

188
189

190
191

192
193
194
195


196



197







198


199
200
201











202





203
204



205
206
207
208
209




210
211

212
213
214
215
216

217
218
219
220
221
222













223
224
225
226
227
228


229
230
231
232
233
234



235
236
237

238
239






240
241
242
243

244
245
246
247
248
249
250






251
252
253
254







255
256
257

258
259
260
261
262
263
























































264
265
266
267
268
269
270

271
272
273
274

275
276
277
278
279
280
281
282
283
284
285

286
287
288
289
290
291

292
293




294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309

310
311
312
313
314
315
316
317


318
319
320
321
322
323
324
325
326
327
328
329
330


331
332
333
334


335
336
337
338


339
340

341
342
343
344

345
346
347
348

349


350
351
352





















353

354

355
356

357
358
359
360
361
362
363
364
365
366
367



368
369
370
371
372
373
374
375
376
377
378
379
380
381
382

383
384

385
386
387
388
389
390
391
392
393
394
395
1
2
3
4
5
6




7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31


32
33


34


35
36
37
38





39
40
41
42
43
44
45
46
47
48
49
50
51

52
53
54
55
56
57
58


59
60
61


62
63

64
65
66
67
68
69






70
71
72
73
74















































































75
76
77
78
79
80
81






82
83
84
85
86
87
88



89




90
91
92
93
94
95
96
97



98
99
100
101
102
103
104
105
106
107
108



109
110
111





112
113





114


115
116

117




118
119
120
121
122
123

124
125
126
127
128
129
130
131
132
133



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150


151
152
153





154
155
156
157
158

159





160






161
162
163
164
165
166
167
168
169
170
171
172
173






174
175






176
177
178



179


180
181
182
183
184
185
186
187


188







189
190
191
192
193
194
195
196


197
198
199
200
201
202
203
204
205
206
207






208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269

270




271



272
273
274
275
276
277
278

279
280
281
282
283
284

285
286

287
288
289
290
291
292
293
294
295
296
297
298
299


300
301
302
303
304
305
306
307
308
309
310
311
312

313
314
315
316
317
318
319
320
321
322
323
324



325
326
327
328
329
330
331
332
333
334


335
336


337




338


339
340
341
342
343
344



345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365

366
367
368
369
370
371
372

373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398

399
400
401
402
403
404
405

406
407
408
409
410
411
412






-
-
-
-
+
+
+
+








+
+
+
+
+






+

-
-
+
+
-
-
+
-
-




-
-
-
-
-
+
+
+










-
+
+
+

+


-
-
+
+
+
-
-
+

-
+





-
-
-
-
-
-





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+

+
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
+
-
-
-
-
+
+
+
+
+
+
+

-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
-
-
-
-
-
+

-
-
-
-
-
+
-
-
+

-
+
-
-
-
-
+
+

+
+
+
-
+
+
+
+
+
+
+

+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
-
-
+
+
+
-
-
-
-
-
+
+
+
+

-
+
-
-
-
-
-
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
-
-
-
-
-
-
+
+
+
-
-
-
+
-
-
+
+
+
+
+
+


-
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+


-
-
+
+
+
+
+
+
+



+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






-
+
-
-
-
-
+
-
-
-







-
+





-
+

-
+
+
+
+









-
-





+







-
+
+










-
-
-
+
+




+
+


-
-
+
+
-
-
+
-
-
-
-
+
-
-


+

+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+

+


+

-









+
+
+














-
+


+



-







/*
 * 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 <[email protected]>
 * Copyright (c) 2012 Adrian Robert.
 * Copyright 2015-2019 Marc Culler.
 * Copyright © 2001-2009, Apple Inc.
 * Copyright © 2006-2009 Daniel A. Steffen <[email protected]>
 * 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.
 */

#include "tkMacOSXPrivate.h"
#include "tkMacOSXInt.h"
#include "tkMacOSXConstants.h"
#include "tkMacOSXWm.h"

/*
 * See tkMacOSXPrivate.h for macros related to key event processing.
 */

/*
#ifdef TK_MAC_DEBUG
#define TK_MAC_DEBUG_KEYBOARD
#endif
*/

#define NS_KEYLOG 0

static Tk_Window keyboardGrabWinPtr = NULL;
#define XEVENT_MOD_MASK (ControlMask | Mod1Mask | Mod3Mask | Mod4Mask)
static Tk_Window keyboardGrabWinPtr = NULL; /* Current keyboard grab window. */
				/* Current keyboard grab window. */
static NSWindow *keyboardGrabNSWindow = nil;
static NSWindow *keyboardGrabNSWindow = nil; /* Its underlying NSWindow.*/
				/* NSWindow for the current keyboard grab
				 * window. */
static NSModalSession modalSession = nil;
static BOOL processingCompose = NO;
static Tk_Window composeWin = NULL;
static int caret_x = 0, caret_y = 0, caret_height = 0;
static unsigned short releaseCode;

static void setupXEvent(XEvent *xEvent, NSWindow *w, unsigned int state);
static unsigned	isFunctionKey(unsigned int code);

static void setupXEvent(XEvent *xEvent, Tk_Window tkwin, NSUInteger modifiers);
static void setXEventPoint(XEvent *xEvent, Tk_Window tkwin, NSWindow *w);
static NSUInteger textInputModifiers;

#pragma mark TKApplication(TKKeyEvent)

@implementation TKApplication(TKKeyEvent)

- (NSEvent *) tkProcessKeyEvent: (NSEvent *) theEvent
{
#ifdef TK_MAC_DEBUG_EVENTS
    TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, theEvent);
#endif
    NSWindow *w;
    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 modifiers = ([theEvent modifierFlags] &
			    NSDeviceIndependentModifierFlagsMask);
    NSUInteger len = 0;
    BOOL repeat = NO;
    XEvent xEvent;
    MacKeycode macKC;
    UniChar keychar = 0;
    unsigned short keyCode = [theEvent keyCode];
    NSString *characters = nil, *charactersIgnoringModifiers = nil;
    Bool can_input_text, has_modifiers = NO, use_text_input = NO;
    static NSUInteger savedModifiers = 0;
    static NSMutableArray *nsEvArray;
    static NSMutableArray *nsEvArray = nil;

    if (nsEvArray == nil) {
        nsEvArray = [[NSMutableArray alloc] initWithCapacity: 1];
        processingCompose = NO;
    }

    w = [theEvent window];
    TkWindow *winPtr = TkMacOSXGetTkWindow(w);
    Tk_Window tkwin = (Tk_Window) winPtr;
    XEvent xEvent;

    if (!winPtr) {
	return theEvent;
    }

    /*
     * Control-Tab and Control-Shift-Tab are used to switch tabs in a tabbed
     * window.  We do not want to generate an Xevent for these since that might
     * cause the deselected tab to be reactivated.
     */

    if (keyCode == 48 && (modifiers & NSControlKeyMask) == NSControlKeyMask) {
	return theEvent;
    }

    switch (type) {
    case NSKeyUp:
	/*Fix for bug #1ba71a86bb: key release firing on key press.*/
	setupXEvent(&xEvent, w, 0);
	xEvent.xany.type = KeyRelease;
	xEvent.xkey.keycode = releaseCode;
	xEvent.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
    case NSKeyDown:
	repeat = [theEvent isARepeat];
	characters = [theEvent characters];
	charactersIgnoringModifiers = [theEvent charactersIgnoringModifiers];
        len = [charactersIgnoringModifiers length];
    case NSFlagsChanged:

#if defined(TK_MAC_DEBUG_EVENTS) || NS_KEYLOG == 1
	TKLog(@"-[%@(%p) %s] r=%d mods=%u '%@' '%@' code=%u c=%d %@ %d", [self class], self, _cmd, repeat, modifiers, characters, charactersIgnoringModifiers, keyCode,([charactersIgnoringModifiers length] == 0) ? 0 : [charactersIgnoringModifiers characterAtIndex: 0], w, type);
#endif
	break;

    default:
	return theEvent; /* Unrecognized key event. */
    }

    /*
     * Create an Xevent to add to the Tk queue.
     */

    if (!processingCompose) {
        unsigned int state = 0;

        if (modifiers & NSAlphaShiftKeyMask) {
	    state |= LockMask;
        }
        if (modifiers & NSShiftKeyMask) {
	    state |= ShiftMask;
        }
        if (modifiers & NSControlKeyMask) {
	    state |= ControlMask;
        }
        if (modifiers & NSCommandKeyMask) {
	    state |= Mod1Mask;		/* command key */
        }
        if (modifiers & NSAlternateKeyMask) {
	    state |= Mod2Mask;		/* option key */
        }
        if (modifiers & NSNumericPadKeyMask) {
	    state |= Mod3Mask;
        }
        if (modifiers & NSFunctionKeyMask) {
	    state |= Mod4Mask;
        }

        /*
         * Key events are only received for the front Window on the Macintosh. So
	 * to build an XEvent we look up the Tk window associated to the Front
	 * window.
         */

        TkWindow *winPtr = TkMacOSXGetTkWindow(w);
        Tk_Window tkwin = (Tk_Window) winPtr;

	if (tkwin) {
	    TkWindow *grabWinPtr = winPtr->dispPtr->grabWinPtr;

	    /*
	     * 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
	     * grab is in effect all key events are redirected to the grabber.
	     */
     * 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
     * grab is in effect all key events are redirected to the grabber.
     */

    grabWinPtr = winPtr->dispPtr->grabWinPtr;
	    if (grabWinPtr) {
		if (winPtr->dispPtr->grabFlags ||  /* global grab */
		    grabWinPtr->mainPtr == winPtr->mainPtr){ /* same appl. */
			tkwin = (Tk_Window) winPtr->dispPtr->focusPtr;
		    }
	    }
    if (grabWinPtr) {
	if (winPtr->dispPtr->grabFlags ||  /* global grab */
	    grabWinPtr->mainPtr == winPtr->mainPtr){ /* same application */
	    winPtr =winPtr->dispPtr->focusPtr;
	    tkwin = (Tk_Window)winPtr;
	}
    }
	} else {
	    tkwin = (Tk_Window) winPtr->dispPtr->focusPtr;
	}

        if (!tkwin) {
	    TkMacOSXDbgMsg("tkwin == NULL");
	    return theEvent;  /* Give up. No window for this event. */
        }
    /*
     * Extract the unicode character from KeyUp and KeyDown events.
     */

    if (type == NSKeyUp || type == NSKeyDown) {
	if ([[theEvent characters] length] > 0) {
	    keychar = [[theEvent characters] characterAtIndex:0];

        /*
         * If it's a function key, or we have modifiers other than Shift or
         * Alt, pass it straight to Tk.  Otherwise we'll send for input
	    /*
	     * Currently, real keys always send BMP characters, but who knows?
	     */

	    if (CFStringIsSurrogateHighCharacter(keychar)) {
		UniChar lowChar = [[theEvent characters] characterAtIndex:1];
		keychar = CFStringGetLongCharacterForSurrogatePair(
		    keychar, lowChar);
	    }
	} else {

         * processing.
         */

	    /*
	     * This is a dead key, such as Option-e, so it should go to the
	     * TextInputClient.
        int code = (len == 0) ? 0 :
		[charactersIgnoringModifiers characterAtIndex: 0];
        if (type != NSKeyDown || isFunctionKey(code)
		|| (len > 0 && state & (ControlMask | Mod1Mask | Mod3Mask | Mod4Mask))) {
            XEvent xEvent;
	     */

            setupXEvent(&xEvent, w, state);
            if (type == NSFlagsChanged) {
		if (savedModifiers > modifiers) {
		    xEvent.xany.type = KeyRelease;
		} else {
	    use_text_input = YES;
		    xEvent.xany.type = KeyPress;
		}
	}

		/*
	/*
		 * Use special '-1' to signify a special keycode to our
		 * platform specific code in tkMacOSXKeyboard.c. This is rather
		 * like what happens on Windows.
		 */
	 * Apple uses 0x10 for unrecognized keys.
	 */

	if (keychar == 0x10) {
	    keychar = UNKNOWN_KEYCHAR;
	}
		xEvent.xany.send_event = -1;

#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);
#endif

    }

		/*
		 * Set keycode (which was zero) to the changed modifier
		 */
    /*
     * Build a skeleton XEvent.  We need to build it here, even if we will not
     * send it, so we can pass it to TkFocusKeyEvent to determine whether the
     * target widget can input text.
     */

    setupXEvent(&xEvent, tkwin, modifiers);
    has_modifiers = xEvent.xkey.state & XEVENT_MOD_MASK;
    focusWinPtr = TkFocusKeyEvent(winPtr, &xEvent);
    if (focusWinPtr == NULL) {
	TKContentView *contentView = [w contentView];

	/*
	 * This NSEvent is being sent to a window which does not have focus.
	 * This could mean, for example, that the user deactivated the Tk app
	 * while the NSTextInputClient's popup character selection window was
	 * still open.  We attempt to abandon any ongoing composition operation
		xEvent.xkey.keycode = (modifiers ^ savedModifiers);
            } else {
	 * and discard the event.
	 */

		if (type == NSKeyUp || repeat) {
		    xEvent.xany.type = KeyRelease;
		} else {
		    xEvent.xany.type = KeyPress;
		}
	[contentView cancelComposingText];
	return theEvent;
    }
    can_input_text = ((focusWinPtr->flags & TK_CAN_INPUT_TEXT) != 0);

		if ([characters length] > 0) {
#if (NS_KEYLOG)
		    xEvent.xkey.keycode = (keyCode << 16) |
			    (UInt16) [characters characterAtIndex:0];
		    if (![characters getCString:xEvent.xkey.trans_chars
			    maxLength:XMaxTransChars encoding:NSUTF8StringEncoding]) {
			/* prevent SF bug 2907388 (crash on some composite chars) */
    TKLog(@"keyDown: %s compose sequence.\n",
			//PENDING: we might not need this anymore
			TkMacOSXDbgMsg("characters too long");
			return theEvent;
		    }
		}

	  processingCompose == YES ? "Continue" : "Begin");
#endif

    /*
     * Decide whether this event should be processed with the NSTextInputClient
     * protocol.
     */

    if (processingCompose ||
	(type == NSKeyDown && can_input_text && !has_modifiers &&
	 IS_PRINTABLE(keychar))
	) {
	use_text_input = YES;
		if (repeat) {
		    Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL);
		    xEvent.xany.type = KeyPress;
		    xEvent.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
		}
            }
    }

            Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL);
            savedModifiers = modifiers;
            return theEvent;
	}  /* if this is a function key or has modifiers */
    }  /* if not processing compose */

    /*
     * If we are processing this KeyDown event as an NSTextInputClient we do
     * not queue an XEvent.  We pass the NSEvent to our interpretKeyEvents
    if (type == NSKeyDown) {
        if (NS_KEYLOG) {
	    TKLog(@"keyDown: %s compose sequence.\n",
     * method.  When the composition sequence is complete, the callback method
		    processingCompose == YES ? "Continue" : "Begin");
	}
     * insertText: replacementRange will be called.  That method generates a
     * keyPress XEvent with the selected character.
     */

    if (use_text_input) {
	textInputModifiers = modifiers;

	/*
	 * Call the interpretKeyEvents method to interpret composition key
	 * strokes.  When it detects a complete composition sequence it will
	 * In IME the Enter key is used to terminate a composition sequence.
	 * call our implementation of insertText: replacementRange, which
	 * generates a key down XEvent with the appropriate character.  In IME
	 * when multiple characters have the same composition sequence and the
	 * chosen character is not the default it may be necessary to hit the
	 * enter key multiple times before the character is accepted and
	 * rendered. We send enter key events until inputText has cleared
	 * the processingCompose flag.
	 * When there are multiple choices of input text available, and the
	 * user's selected choice is not the default, it may be necessary to
	 * hit the Enter key multiple times before the text is accepted and
	 * rendered (See ticket 39de9677aa]). So when sending an Enter key
	 * during composition, we continue sending Enter keys until the
	 * inputText method has cleared the processingCompose flag.
	 */

	processingCompose = YES;
	while(processingCompose) {
	if (processingCompose && [theEvent keyCode] == 36) {
	    [nsEvArray addObject: theEvent];
	    while(processingCompose) {
		[[w contentView] interpretKeyEvents: nsEvArray];
	    }
	    [nsEvArray removeObject: theEvent];
	} else {
	    [nsEvArray addObject: theEvent];
	    [[w contentView] interpretKeyEvents: nsEvArray];
	    [nsEvArray removeObject: theEvent];
	}
	    if ([theEvent keyCode] != 36) {
		break;
	    }
	}
    }
    savedModifiers = modifiers;
	return theEvent;
    }

    /*
     * We are not handling this event as an NSTextInputClient, so we need to
     * 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;
    switch (type) {
    case NSFlagsChanged:

	/*
	 * This XEvent is a simulated KeyPress or KeyRelease event for a
	 * modifier key.  To determine the type, note that the highest bit
	 * where the flags differ is 1 if and only if it is a KeyPress. The
	 * modifiers are saved so we can detect the next flag change.
	 */

	xEvent.xany.type = modifiers > savedModifiers ? KeyPress : KeyRelease;
	savedModifiers = modifiers;

	/*
	 * Set the keychar to MOD_KEYCHAR as a signal to TkpGetKeySym (see
	 * tkMacOSXKeyboard.c) that this is a modifier key event.
	 */

	keychar = MOD_KEYCHAR;
	break;
    case NSKeyUp:
	xEvent.xany.type = KeyRelease;
	break;
    case NSKeyDown:
	xEvent.xany.type = KeyPress;
	break;
    default:
	return theEvent; /* Unrecognized key event. */
    }
    macKC.v.keychar = keychar;
    xEvent.xkey.keycode = macKC.uint;
    setXEventPoint(&xEvent, tkwin, w);

    /*
     * 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);
    return theEvent;
}
@end


@implementation TKContentView

@synthesize tkDirtyRect = _tkDirtyRect;
-(id)init {
    self = [super init];
    if (self) {
        _needsRedisplay = NO;
@synthesize tkNeedsDisplay = _tkNeedsDisplay;
    }
    return self;
}

/*
 * Implementation of the NSTextInputClient protocol.
 */

/* [NSTextInputClient inputText: replacementRange:] is called by
 * interpretKeyEvents when a composition sequence is complete.  It is also
 * called when we delete over working text.  In that case the call is followed
 * called when we delete working text.  In that case the call is followed
 * immediately by doCommandBySelector: deleteBackward:
 */
- (void)insertText: (id)aString
  replacementRange: (NSRange)repRange
{
    int i, len;
    int i, len, state;
    XEvent xEvent;
    NSString *str;
    NSString *str, *keystr, *lower;
    TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
    Tk_Window tkwin = (Tk_Window)winPtr;
    Bool sendingIMEText = NO;

    str = ([aString isKindOfClass: [NSAttributedString class]]) ?
        [aString string] : aString;
    len = [str length];

    if (NS_KEYLOG) {
	TKLog(@"insertText '%@'\tlen = %d", aString, len);
    }

    processingCompose = NO;

    /*
     * Clear any working text.
     */

    if (privateWorkingText != nil) {
	sendingIMEText = YES;
    	[self deleteWorkingText];
    }

    /*
     * Insert the string as a sequence of keystrokes.
     */

    setupXEvent(&xEvent, [self window], 0);
    setupXEvent(&xEvent, tkwin, textInputModifiers);
    setXEventPoint(&xEvent, tkwin, [self window]);
    xEvent.xany.type = KeyPress;

    /*
     * Apple evidently sets location to 0 to signal that an accented letter has
     * been selected from the accent menu.  An unaccented letter has already
     * been displayed and we need to erase it before displaying the accented
     * letter.
     */

    if (repRange.location == 0) {
	TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
	Tk_Window focusWin = (Tk_Window) winPtr->dispPtr->focusPtr;
	TkSendVirtualEvent(focusWin, "TkAccentBackspace", NULL);
	Tk_Window focusWin = (Tk_Window)winPtr->dispPtr->focusPtr;
	Tk_SendVirtualEvent(focusWin, "TkAccentBackspace", NULL);
    }

    /*
     * Next we generate an XEvent for each unicode character in our string.
     * This string could contain non-BMP characters, for example if the
     * emoji palette was used.
     *
     * NSString uses UTF-16 internally, which means that a non-BMP character is
     * represented by a sequence of two 16-bit "surrogates".  In principle we
     * could record this in the XEvent by setting the keycode to the 32-bit
     * represented by a sequence of two 16-bit "surrogates".  We record this in
     * the XEvent by setting the low order 21-bits of the keycode to the UCS-32
     * unicode code point and setting the trans_chars string to the 4-byte
     * UTF-8 string for the non-BMP character.  However, that will not work
     * value value of the character and the virtual keycode in the high order
     * when TCL_UTF_MAX is set to 3, as is the case for Tcl 8.6.  A workaround
     * used internally by Tcl 8.6 is to encode each surrogate as a 3-byte
     * sequence using the UTF-8 algorithm (ignoring the fact that the UTF-8
     * encoding specification does not allow encoding UTF-16 surrogates).
     * byte to the special value NON_BMP.
     * This gives a 6-byte encoding of the non-BMP character which we write into
     * the trans_chars field of the XEvent.
     */

    state = xEvent.xkey.state;
    for (i = 0; i < len; i++) {
	UniChar keychar;
	MacKeycode macKC = {0};
	xEvent.xkey.nbytes = TkUtfAtIndex(str, i, xEvent.xkey.trans_chars,
					   &xEvent.xkey.keycode);
	if (xEvent.xkey.keycode > 0xffff){

	keychar = [str characterAtIndex:i];
	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;
	} else if (repRange.location == 0 || sendingIMEText) {
	    macKC.v.virtual = REPLACEMENT_VIRTUAL;
	} else {
	    macKC.uint = TkMacOSXAddVirtual(macKC.uint);
	    xEvent.xkey.state |= INDEX2STATE(macKC.x.xvirtual);
	}
	keystr = [[NSString alloc] initWithCharacters:&keychar length:1];
	lower = [keystr lowercaseString];
	if (![keystr isEqual: lower]) {
	    macKC.v.o_s |= INDEX_SHIFT;
	    xEvent.xkey.state |= ShiftMask;
	}
	if (xEvent.xkey.state & Mod2Mask) {
	    i++;
	    macKC.v.o_s |= INDEX_OPTION;
	}
	xEvent.xkey.keycode = macKC.uint;
    	xEvent.xany.type = KeyPress;
    	Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL);
	xEvent.xkey.state = state;
    }
    releaseCode = (UInt16) [str characterAtIndex: 0];
}

/*
 * This required method is allowed to return nil.
 */

- (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)theRange
      actualRange:(NSRangePointer)thePointer
{
    (void)theRange;
    (void)thePointer;

    return nil;
}

/*
 * This method is supposed to insert (or replace selected text with) the string
 * argument. If the argument is an NSString, it should be displayed with a
 * distinguishing appearance, e.g underlined.
 */

- (void)setMarkedText: (id)aString
	selectedRange: (NSRange)selRange
     replacementRange: (NSRange)repRange
{
    TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
    Tk_Window focusWin = (Tk_Window) winPtr->dispPtr->focusPtr;
    Tk_Window focusWin = (Tk_Window)winPtr->dispPtr->focusPtr;
    NSString *temp;
    NSString *str;
    (void)selRange;

    str = ([aString isKindOfClass: [NSAttributedString class]]) ?
        [aString string] : aString;

    if (focusWin) {

	/*
	 * Remember the widget where the composition is happening, in case it
	 * gets defocussed during the composition.
	 */

411
412
413
414
415
416
417
418


419
420
421
422
423

424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472



473
474
475
476
477
478
479
428
429
430
431
432
433
434

435
436
437
438
439


440
441
442
443
444
445
446

447
448
449
450
451
452
453
454
455
456
457
458
459









460
461
462
463
464
465
466
467

468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488







-
+
+



-
-
+






-













-
-
-
-
-
-
-
-
-








-











+
+
+







	return;
    }

    /*
     * Use our insertText method to display the marked text.
     */

    TkSendVirtualEvent(focusWin, "TkStartIMEMarkedText", NULL);
    Tk_SendVirtualEvent(focusWin, "TkStartIMEMarkedText", NULL);
    processingCompose = YES;
    temp = [str copy];
    [self insertText: temp replacementRange:repRange];
    privateWorkingText = temp;
    processingCompose = YES;
    TkSendVirtualEvent(focusWin, "TkEndIMEMarkedText", NULL);
    Tk_SendVirtualEvent(focusWin, "TkEndIMEMarkedText", NULL);
}

- (BOOL)hasMarkedText
{
    return privateWorkingText != nil;
}


- (NSRange)markedRange
{
    NSRange rng = privateWorkingText != nil
	? NSMakeRange(0, [privateWorkingText length])
	: NSMakeRange(NSNotFound, 0);

    if (NS_KEYLOG) {
	TKLog(@"markedRange request");
    }
    return rng;
}

- (void)cancelComposingText
{
    if (NS_KEYLOG) {
	TKLog(@"cancelComposingText");
    }
    [self deleteWorkingText];
    processingCompose = NO;
}

- (void)unmarkText
{
    if (NS_KEYLOG) {
	TKLog(@"unmarkText");
    }
    [self deleteWorkingText];
    processingCompose = NO;
}


/*
 * Called by the system to get a position for popup character selection windows
 * such as a Character Palette, or a selection menu for IME.
 */

- (NSRect)firstRectForCharacterRange: (NSRange)theRange
			 actualRange: (NSRangePointer)thePointer
{
    NSRect rect;
    NSPoint pt;
    (void)theRange;
    (void)thePointer;

    pt.x = caret_x;
    pt.y = caret_y;

    pt = [self convertPoint: pt toView: nil];
    pt = [[self window] tkConvertPointToScreen: pt];
    pt.y -= caret_height;

492
493
494
495
496
497
498
499
500


501
502
503
504
505
506
507
501
502
503
504
505
506
507


508
509
510
511
512
513
514
515
516







-
-
+
+







{
    if (NS_KEYLOG) {
	TKLog(@"doCommandBySelector: %@", NSStringFromSelector(aSelector));
    }
    processingCompose = NO;
    if (aSelector == @selector (deleteBackward:)) {
	TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
	Tk_Window focusWin = (Tk_Window) winPtr->dispPtr->focusPtr;
	TkSendVirtualEvent(focusWin, "TkAccentBackspace", NULL);
	Tk_Window focusWin = (Tk_Window)winPtr->dispPtr->focusPtr;
	Tk_SendVirtualEvent(focusWin, "TkAccentBackspace", NULL);
    }
}

- (NSArray *)validAttributesForMarkedText
{
    static NSArray *arr = nil;
    if (arr == nil) {
520
521
522
523
524
525
526

527
528
529
530
531
532
533
534
535


536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557

558
559
560
561
562
563
564







+









+
+










-







	TKLog(@"selectedRange request");
    }
    return NSMakeRange(0, 0);
}

- (NSUInteger)characterIndexForPoint: (NSPoint)thePoint
{
    (void)thePoint;
    if (NS_KEYLOG) {
	TKLog(@"characterIndexForPoint request");
    }
    return NSNotFound;
}

- (NSAttributedString *)attributedSubstringFromRange: (NSRange)theRange
{
    static NSAttributedString *str = nil;
    (void)theRange;

    if (str == nil) {
	str = [NSAttributedString new];
    }
    if (NS_KEYLOG) {
	TKLog(@"attributedSubstringFromRange request");
    }
    return str;
}
/* End of NSTextInputClient implementation. */

@synthesize needsRedisplay = _needsRedisplay;
@end


@implementation TKContentView(TKKeyEvent)

/*
 * Tell the widget to erase the displayed composing characters.  This
565
566
567
568
569
570
571
572

573
574
575










576
577
578
579
580
581
582
583

584
585
586


587
588

589
590








591

592
593

594
595
596
597

598
599
600
601
602
603



































604
605
606
607
608
609
610
576
577
578
579
580
581
582

583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603

604
605


606
607
608

609
610
611
612
613
614
615
616
617
618
619

620
621

622
623
624
625

626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674







-
+



+
+
+
+
+
+
+
+
+
+







-
+

-
-
+
+

-
+


+
+
+
+
+
+
+
+
-
+

-
+



-
+






+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







		  (unsigned long)[privateWorkingText length]);
	}

	[privateWorkingText release];
	privateWorkingText = nil;
	processingCompose = NO;
	if (composeWin) {
	    TkSendVirtualEvent(composeWin, "TkClearIMEMarkedText", NULL);
	    Tk_SendVirtualEvent(composeWin, "TkClearIMEMarkedText", NULL);
	}
    }
}

- (void)cancelComposingText
{
    if (NS_KEYLOG) {
	TKLog(@"cancelComposingText");
    }
    [self deleteWorkingText];
    processingCompose = NO;
}

@end

/*
 * Set up basic fields in xevent for keyboard input.
 */

static void
setupXEvent(XEvent *xEvent, NSWindow *w, unsigned int state)
setupXEvent(XEvent *xEvent, Tk_Window tkwin, NSUInteger modifiers)
{
    TkWindow *winPtr = TkMacOSXGetTkWindow(w);
    Tk_Window tkwin = (Tk_Window) winPtr;
    unsigned int state = 0;
    Display *display = Tk_Display(tkwin);

    if (!winPtr) {
    if (tkwin == NULL) {
	return;
    }
    if (modifiers) {
	state = (modifiers & NSAlphaShiftKeyMask ? LockMask    : 0) |
	        (modifiers & NSShiftKeyMask      ? ShiftMask   : 0) |
	        (modifiers & NSControlKeyMask    ? ControlMask : 0) |
	        (modifiers & NSCommandKeyMask    ? Mod1Mask    : 0) |
	        (modifiers & NSAlternateKeyMask  ? Mod2Mask    : 0) |
	        (modifiers & NSNumericPadKeyMask ? Mod3Mask    : 0) |
	        (modifiers & NSFunctionKeyMask   ? Mod4Mask    : 0) ;

    }
    memset(xEvent, 0, sizeof(XEvent));
    xEvent->xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
    xEvent->xany.serial = LastKnownRequestProcessed(display);
    xEvent->xany.display = Tk_Display(tkwin);
    xEvent->xany.window = Tk_WindowId(tkwin);

    xEvent->xkey.root = XRootWindow(Tk_Display(tkwin), 0);
    xEvent->xkey.root = XRootWindow(display, 0);
    xEvent->xkey.time = TkpGetMS();
    xEvent->xkey.state = state;
    xEvent->xkey.same_screen = true;
    /* No need to initialize other fields implicitly here,
     * because of the memset() above. */
}

static void
setXEventPoint(
    XEvent *xEvent,
    Tk_Window tkwin,
    NSWindow *w)
{
    TkWindow *winPtr = (TkWindow *) tkwin;
    NSPoint local = [w  mouseLocationOutsideOfEventStream];
    NSPoint global = [w tkConvertPointToScreen: local];
    int win_x, win_y;

    if (Tk_IsEmbedded(winPtr)) {
	TkWindow *contPtr = TkpGetOtherWindow(winPtr);
	if (Tk_IsTopLevel(contPtr)) {
	    local.x -= contPtr->wmInfoPtr->xInParent;
	    local.y -= contPtr->wmInfoPtr->yInParent;
	} else {
	    TkWindow *topPtr = TkMacOSXGetHostToplevel(winPtr)->winPtr;
	    local.x -= (topPtr->wmInfoPtr->xInParent + contPtr->changes.x);
	    local.y -= (topPtr->wmInfoPtr->yInParent + contPtr->changes.y);
	}
    } else if (winPtr->wmInfoPtr != NULL) {
	local.x -= winPtr->wmInfoPtr->xInParent;
	local.y -= winPtr->wmInfoPtr->yInParent;
    }
    tkwin = Tk_TopCoordsToWindow(tkwin, local.x, local.y, &win_x, &win_y);
    local.x = win_x;
    local.y = win_y;
    global.y = TkMacOSXZeroScreenHeight() - global.y;
    xEvent->xbutton.x = local.x;
    xEvent->xbutton.y = local.y;
    xEvent->xbutton.x_root = global.x;
    xEvent->xbutton.y_root = global.y;
}

#pragma mark -

/*
 *----------------------------------------------------------------------
 *
 * XGrabKeyboard --
627
628
629
630
631
632
633




634
635
636
637


638
639
640
641
642
643
644
691
692
693
694
695
696
697
698
699
700
701
702
703


704
705
706
707
708
709
710
711
712







+
+
+
+


-
-
+
+







    Bool owner_events,
    int pointer_mode,
    int keyboard_mode,
    Time time)
{
    keyboardGrabWinPtr = Tk_IdToWindow(display, grab_window);
    TkWindow *captureWinPtr = (TkWindow *) TkpGetCapture();
    (void)owner_events;
    (void)pointer_mode;
    (void)keyboard_mode;
    (void)time;

    if (keyboardGrabWinPtr && captureWinPtr) {
	NSWindow *w = TkMacOSXDrawableWindow(grab_window);
	MacDrawable *macWin = (MacDrawable *) grab_window;
	NSWindow *w = TkMacOSXGetNSWindowForDrawable(grab_window);
	MacDrawable *macWin = (MacDrawable *)grab_window;

	if (w && macWin->toplevel->winPtr == (TkWindow *) captureWinPtr) {
	    if (modalSession) {
		Tcl_Panic("XGrabKeyboard: already grabbed");
	    }
	    keyboardGrabNSWindow = w;
	    [w retain];
665
666
667
668
669
670
671



672
673
674
675
676
677
678
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749







+
+
+







 */

int
XUngrabKeyboard(
    Display* display,
    Time time)
{
    (void)display;
    (void)time;

    if (modalSession) {
	[NSApp endModalSession:modalSession];
	modalSession = nil;
    }
    if (keyboardGrabNSWindow) {
	[keyboardGrabNSWindow release];
	keyboardGrabNSWindow = nil;
702
703
704
705
706
707
708
709
710
711








712
713
714
715
716
717



718
719
720
721
722
723
724
725
726
727
728

729


730
731
732
733



734
735




736
737


738
739
740




741

742
743
744
745
746
747


748
749

750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766

767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
773
774
775
776
777
778
779



780
781
782
783
784
785
786
787
788
789
790
791
792

793
794
795
796
797
798
799
800
801
802
803
804
805
806
807

808
809
810
811


812
813
814
815
816
817
818
819
820


821
822
823
824
825
826
827
828
829

830
831
832
833
834
835

836
837
838
839
840
841
842
843
844
845
846
847
848







849

850

851
852














































































853
854
855
856
857
858
859
860







-
-
-
+
+
+
+
+
+
+
+





-
+
+
+











+
-
+
+


-
-
+
+
+


+
+
+
+
-
-
+
+



+
+
+
+
-
+





-
+
+


+








-
-
-
-
-
-
-

-
+
-


-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-








}

/*
 *----------------------------------------------------------------------
 *
 * Tk_SetCaretPos --
 *
 *	This enables correct placement of the XIM caret. This is called by
 *	widgets to indicate their cursor placement, and the caret location is
 *	used by TkpGetString to place the XIM caret.
 *	This enables correct placement of the popups used for character
 *      selection by the NSTextInputClient.  It gets called by text entry
 *      widgets whenever the cursor is drawn.  It does nothing if the widget's
 *      NSWindow is not the current KeyWindow.  Otherwise it updates the
 *      display's caret structure and records the caret geometry in static
 *      variables for use by the NSTextInputClient implementation.  Any
 *      widget passed to this function will be marked as being able to input
 *      text by setting the TK_CAN_INPUT_TEXT flag.
 *
 * Results:
 *	None
 *
 * Side effects:
 *	None
 *      Sets the CAN_INPUT_TEXT flag on the widget passed as tkwin.  May update
 *      the display's caret structure as well as the static variables caret_x,
 *      caret_y and caret_height.
 *
 *----------------------------------------------------------------------
 */

void
Tk_SetCaretPos(
    Tk_Window tkwin,
    int x,
    int y,
    int height)
 {
    TkWindow *winPtr = (TkWindow *) tkwin;
    TkCaret *caretPtr = &(((TkWindow *) tkwin)->dispPtr->caret);
    TkCaret *caretPtr = &(winPtr->dispPtr->caret);
    NSWindow *w = TkMacOSXGetNSWindowForDrawable(Tk_WindowId(tkwin));

    /*
     * Prevent processing anything if the values haven't changed. Windows only
     * has one display, so we can do this with statics.
     * Register this widget as being capable of text input, so we know we
     * should process (appropriate) key events for this window with the
     * NSTextInputClient protocol.
     */

    winPtr->flags |= TK_CAN_INPUT_TEXT;
    if (w && ![w isKeyWindow]) {
	return;
    }
    if ((caretPtr->winPtr == ((TkWindow *) tkwin))
	    && (caretPtr->x == x) && (caretPtr->y == y)) {
    if ((caretPtr->winPtr == winPtr
	 && caretPtr->x == x) && (caretPtr->y == y)) {
	return;
    }

    /*
     * Update the display's caret information.
     */

    caretPtr->winPtr = ((TkWindow *) tkwin);
    caretPtr->winPtr = winPtr;
    caretPtr->x = x;
    caretPtr->y = y;
    caretPtr->height = height;

    /*
     * As in Windows, adjust to the toplevel to get the coords right.
     * Record the caret geometry in static variables for use when processing
     * key events.  We use the TKContextView coordinate system for this.
     */

    caret_height = height;
    while (!Tk_IsTopLevel(tkwin)) {
	x += Tk_X(tkwin);
	y += Tk_Y(tkwin);
	tkwin = Tk_Parent(tkwin);
	if (tkwin == NULL) {
	    return;
	}
    }

    /*
     * But adjust for fact that NS uses flipped view.
     */

    y = Tk_Height(tkwin) - y;

    caret_x = x;
    caret_y = y;
    caret_y = Tk_Height(tkwin) - y;
    caret_height = height;
}


static unsigned convert_ns_to_X_keysym[] =
{
    NSHomeFunctionKey,		0x50,
    NSLeftArrowFunctionKey,	0x51,
    NSUpArrowFunctionKey,	0x52,
    NSRightArrowFunctionKey,	0x53,
    NSDownArrowFunctionKey,	0x54,
    NSPageUpFunctionKey,	0x55,
    NSPageDownFunctionKey,	0x56,
    NSEndFunctionKey,		0x57,
    NSBeginFunctionKey,		0x58,
    NSSelectFunctionKey,	0x60,
    NSPrintFunctionKey,		0x61,
    NSExecuteFunctionKey,	0x62,
    NSInsertFunctionKey,	0x63,
    NSUndoFunctionKey,		0x65,
    NSRedoFunctionKey,		0x66,
    NSMenuFunctionKey,		0x67,
    NSFindFunctionKey,		0x68,
    NSHelpFunctionKey,		0x6A,
    NSBreakFunctionKey,		0x6B,

    NSF1FunctionKey,		0xBE,
    NSF2FunctionKey,		0xBF,
    NSF3FunctionKey,		0xC0,
    NSF4FunctionKey,		0xC1,
    NSF5FunctionKey,		0xC2,
    NSF6FunctionKey,		0xC3,
    NSF7FunctionKey,		0xC4,
    NSF8FunctionKey,		0xC5,
    NSF9FunctionKey,		0xC6,
    NSF10FunctionKey,		0xC7,
    NSF11FunctionKey,		0xC8,
    NSF12FunctionKey,		0xC9,
    NSF13FunctionKey,		0xCA,
    NSF14FunctionKey,		0xCB,
    NSF15FunctionKey,		0xCC,
    NSF16FunctionKey,		0xCD,
    NSF17FunctionKey,		0xCE,
    NSF18FunctionKey,		0xCF,
    NSF19FunctionKey,		0xD0,
    NSF20FunctionKey,		0xD1,
    NSF21FunctionKey,		0xD2,
    NSF22FunctionKey,		0xD3,
    NSF23FunctionKey,		0xD4,
    NSF24FunctionKey,		0xD5,

    NSBackspaceCharacter,	0x08,  /* 8: Not on some KBs. */
    NSDeleteCharacter,		0xFF,  /* 127: Big 'delete' key upper right. */
    NSDeleteFunctionKey,	0x9F,  /* 63272: Del forw key off main array. */

    NSTabCharacter,		0x09,
    0x19,			0x09,  /* left tab->regular since pass shift */
    NSCarriageReturnCharacter,	0x0D,
    NSNewlineCharacter,		0x0D,
    NSEnterCharacter,		0x8D,

    0x1B,			0x1B   /* escape */
};


static unsigned
isFunctionKey(
    unsigned code)
{
    const unsigned last_keysym = (sizeof(convert_ns_to_X_keysym)
                                / sizeof(convert_ns_to_X_keysym[0]));
    unsigned keysym;

    for (keysym = 0; keysym < last_keysym; keysym += 2) {
	if (code == convert_ns_to_X_keysym[keysym]) {
	    return 0xFF00 | convert_ns_to_X_keysym[keysym + 1];
	}
    }
    return 0;
}

/*
 * Local Variables:
 * mode: objc
 * c-basic-offset: 4
 * fill-column: 79
 * coding: utf-8
 * End:
 */
Changes to macosx/tkMacOSXKeyboard.c.
1
2
3
4
5
6
7
8




9
10
11
12
13
14
15

16


17




18

19
20
21
22
23









24
25
26
27
28
29
30


31
32




33
34
35
36






37
38
39
40
41
42
43
44
45
46
47
48
49
50














51
52

53
54

55
56
57
58
59
60
61
62
63
64








65
66
67
68
69
70
71














72
73
74
75
76







77
78
79







80
81
82
83
84
85
86
87
88
89
90
91
92
93
94

95
96


97











98
99

100
101
102
103
104
105
106
107
108
109




110
111
112


113
114
115

116

117
118
119
120





121
122
123



124

125

126
127
128
129
130
131
132


133
134
135


136
137
138
139
140
141
142

143
144
145
146


147
148
149
150
151
152
153
154
155

156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173

174
175
176
177



178

179
180
181
182






183





184
185
186
187
188
189





















190

191

192
193
194
195
196
197

198

199
200
201





202
203
204
205
206
207

208

209
210
211
212
213
214

215
216
217

218
219
220


221

222
223






224
225
226
227
228
229
230
231





232
233
234


235
236
237
238
239
240
241








242
243
244
245
246







247
248
249
250






251
252
253
254
255
256
257
258

259
260
261





262
263
264

265
266

267
268
269
270

271
272
273
274

275
276
277
278

279
280

281
282
283
284

285
286
287
288

289
290
291
292
293
294
295
296
297
298
299
300
301

302
303
304
305
306
307
308

309
310
311
312
313

314
315
316
317
318
319
320
321
322

323
324
325
326

327
328

329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347




348
349
350


351
352
353
354
355
356
357
358
359
360
361




362
363
364
365
366




367
368
369
370
371

372


373
374
375
376


377
378
379
380
381
382
383
384
385
386
387
388
389







390
391
392
393





394
395
396
397
398
399
400




401
402
403
404
405
406
407
408
409



410

411
412
413



414
415
416
417






418









419
420
421
422
423
424
425
426


427
428
429

430
431
432
433
434
435
436
437
438
439

440
441
442
443
444



445
446
447







448
449

450
451
452
453
454
455
456
457
458


459
460
461

462
463
464
465
466
467
468
469
470
471

472
473
474
475
476
477
478
479
480
481

482
483
484
485
486
487
488
489
490
491
492


493
494
495
496
497
498
499
1
2
3
4
5



6
7
8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
23
24

25
26




27
28
29
30
31
32
33
34
35







36
37


38
39
40
41




42
43
44
45
46
47














48
49
50
51
52
53
54
55
56
57
58
59
60
61
62

63


64










65
66
67
68
69
70
71
72







73
74
75
76
77
78
79
80
81
82
83
84
85
86





87
88
89
90
91
92
93



94
95
96
97
98
99
100















101


102
103

104
105
106
107
108
109
110
111
112
113
114
115

116










117
118
119
120



121
122



123
124
125




126
127
128
129
130
131


132
133
134
135
136

137
138
139
140
141
142


143
144



145
146
147
148
149
150
151
152
153
154
155
156
157

158
159
160
161
162
163
164
165
166
167

168
169
170
171




172
173
174
175
176
177
178
179
180
181

182
183
184


185
186
187
188
189




190
191
192
193
194
195
196
197
198
199
200
201






202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224

225
226
227
228
229
230

231
232
233



234
235
236
237
238

239
240
241
242
243
244

245
246
247
248
249
250

251

252

253



254
255
256
257


258
259
260
261
262
263
264







265
266
267
268
269



270
271







272
273
274
275
276
277
278
279





280
281
282
283
284
285
286




287
288
289
290
291
292
293
294
295
296
297
298
299

300
301


302
303
304
305
306
307
308

309
310

311
312
313
314

315

316
317

318
319
320
321
322
323
324

325
326
327
328

329
330
331
332

333
334
335
336
337
338
339
340
341
342
343
344
345

346
347
348
349
350
351
352

353
354
355
356
357

358
359

360
361
362
363
364


365
366
367

368
369
370

371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388


389
390
391
392
393
394

395
396
397
398
399
400
401
402
403
404



405
406
407
408
409
410



411
412
413
414
415


416

417
418
419
420
421
422


423
424


425
426









427
428
429
430
431
432
433




434
435
436
437
438







439
440
441
442


443
444




445
446
447
448

449

450
451
452
453
454




455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477

478
479
480
481

482
483
484
485
486
487
488
489
490
491

492
493
494
495
496
497
498
499
500



501
502
503
504
505
506
507
508

509

510
511
512
513
514
515
516

517
518
519
520

521
522
523
524
525
526
527
528
529
530

531
532
533
534







535
536
537
538
539
540
541
542
543
544
545

546
547
548
549
550
551
552
553
554





-
-
-
+
+
+
+






-
+

+
+

+
+
+
+
-
+

-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
-
-
+
+
+
+
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+
-
-
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
+
-
+
+
+
+
+
+
+
+
+
+
+

-
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
-
+
+
-
-
-
+

+
-
-
-
-
+
+
+
+
+

-
-
+
+
+

+
-
+





-
-
+
+
-
-
-
+
+







+



-
+
+








-
+



-
-
-
-










-
+


-
-
+
+
+

+
-
-
-
-
+
+
+
+
+
+

+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
-
+





-
+

+
-
-
-
+
+
+
+
+
-





+
-
+





-
+
-

-
+
-
-
-
+
+

+
-
-
+
+
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
-
-
-
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+







-
+

-
-
+
+
+
+
+


-
+

-
+



-
+
-


-
+




+

-
+



-
+



-
+












-
+






-
+




-
+

-





-
-
+


-

+

-
+

















-
-
+
+
+
+


-
+
+








-
-
-
+
+
+
+


-
-
-
+
+
+
+

-
-

-
+

+
+


-
-
+
+
-
-


-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
-
-


-
-
-
-

+
+
+
-
+
-


+
+
+
-
-
-
-
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+







-
+
+


-
+









-
+





+
+
+
-
-
-
+
+
+
+
+
+
+

-
+
-







-
+
+


-
+









-
+



-
-
-
-
-
-
-
+










-
+
+







/*
 * 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 <[email protected]>
 * Copyright © 1995-1997 Sun Microsystems, Inc.
 * Copyright © 2001-2009, Apple Inc.
 * Copyright © 2005-2009 Daniel A. Steffen <[email protected]>
 * 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 "tkMacOSXPrivate.h"
#include "tkMacOSXEvent.h"
#include "tkMacOSXInt.h"
#include "tkMacOSXConstants.h"
#include "tkMacOSXKeysyms.h"

/*
 * About keyboards
 * ---------------
 * Keyboards are complicated.  This long comment is an attempt to provide
 * enough information about them to make it possible to read and understand
 * A couple of simple definitions to make code a bit more self-explaining.
 * the code in this file.
 *
 * For the assignments of Mod1==meta==command and Mod2==alt==option, see also
 * tkMacOSXMouseEvent.c.
 */

 * Every key on a keyboard is identified by a number between 0 and 127.  In
 * macOS, pressing or releasing a key on the keyboard generates an NSEvent of
 * type KeyDown, KeyUp or FlagsChanged.  The 8-bit identifier of the key that
 * was involved in this event is provided in the attribute [NSEvent keyCode].
 * Apple also refers to this number as a "Virtual KeyCode".  In this file, to
 * avoid confusion with other uses of the word keycode, we will refer to this
 * key identifier as a "virtual keycode", usually the value of a variable named
 * "virtual".
 *
#define LATIN1_MAX	 255
#define MAC_KEYCODE_MAX	 0x7F
#define MAC_KEYCODE_MASK 0x7F
#define COMMAND_MASK	 Mod1Mask
#define OPTION_MASK	 Mod2Mask


 * Some of the keys on a keyboard, such as the Shift, Option, Command or
 * Control keys, are "modifier" keys.  The effect of pressing or releasing a
/*
 * Tables enumerating the special keys defined on Mac keyboards. These are
 * key depends on three quantities:
 *     - which key is being pressed or released
 *     - which modifier keys are being held down at the moment
 *     - the current keyboard layout
 * necessary for correct keysym mappings for all keys where the keysyms are
 * not identical with their ASCII or Latin-1 code points.
 */

 * If the key is a modifier key then the effect of pressing or releasing it is
 * only to change the list of which modifier keys are being held down.  Apple
 * reports this by sending an NSEvent of type FlagsChanged.  X11 reports this
 * as a KeyPress or KeyRelease event for the modifier key.  Note that there may
 * be combinations of modifier key states and key presses which have no effect.
 *
typedef struct {
    int keycode;		/* Macintosh keycode. */
    KeySym keysym;		/* X windows keysym. */
} KeyInfo;

/*
 * Notes on keyArray:
 *
 * 0x34, XK_Return - Powerbooks use this and some keymaps define it.
 *
 * 0x4C, XK_Return - XFree86 and Apple's X11 call this one XK_KP_Enter.
 *
 * 0x47, XK_Clear - This key is NumLock when used on PCs, but Mac
 * applications don't use it like that, nor does Apple's X11.
 * In X11 every meaningful effect from a key action is identified by a 16 bit
 * value known as a keysym.  Every keysym has an associated string name, also
 * known as a keysym.  The Tk bind command uses the X11 keysym string to
 * specify a key event which should invoke a certain action and it provides the
 * numeric and symbolic keysyms to the bound proc as %N and %K respectively.
 * An X11 XEvent which reports a KeyPress or KeyRelease does not include the
 * keysym.  Instead it includes a platform-specific numerical value called a
 * keycode which is available to the bound procedure as %k.  A platform port of
 * Tk must provide functions which convert between keycodes and numerical
 * keysyms.  Conversion between numerical and symbolic keysyms is provided by
 * the generic Tk code, although platforms are allowed to provide their own by
 * defining the XKeysymToString and XStringToKeysym functions and undefining
 * the macro REDO_KEYSYM_LOOKUP.  This macOS port uses the conversion provided
 * by the generic code.
 *
 * All other keycodes are taken from the published ADB keyboard layouts.
 * When the keyboard focus is on a Tk widget which provides text input, there
 */

 * are some X11 KeyPress events which cause text to be inserted.  We will call
static KeyInfo keyArray[] = {
    {0x24,	XK_Return},
    {0x30,	XK_Tab},
    {0x33,	XK_BackSpace},
    {0x34,	XK_Return},
    {0x35,	XK_Escape},

    {0x47,	XK_Clear},
    {0x4C,	XK_KP_Enter},

 * these "printable" events. The UCS-32 character stored in the keycode field
 * of an XKeyEvent depends on more than the three items above.  It may also
 * depend on the sequence of keypresses that preceded the one being reported by
 * the XKeyEvent.  For example, on macOS an <Alt-e> event does not cause text
 * to be inserted but a following <a> event causes an accented 'a' to be
 * inserted.  The events in such a composition sequence, other than the final
 * one, are known as "dead-key" events.
 *
    {0x72,	XK_Help},
    {0x73,	XK_Home},
    {0x74,	XK_Page_Up},
    {0x75,	XK_Delete},
    {0x77,	XK_End},
    {0x79,	XK_Page_Down},

 * MacOS packages the information described above in a different way.  Every
 * meaningful effect from a key action *other than changing the state of
 * modifier keys* is identified by a unicode string which is provided as the
 * [NSEvent characters] attribute of a KeyDown or KeyUp event.  FlagsChanged
 * events do not have characters.  In principle, the characters attribute could
 * be an arbitrary unicode string but in practice it is always a single UTF-16
 * character which we usually store in a variable named keychar.  While the
 * keychar is a legal unicode code point, it does not necessarily represent a
 * glyph. MacOS uses unicode code points in the private-use range 0xF700-0xF8FF
 * for non-printable events which have no associated ASCII code point.  For
 * example, pressing the F2 key generates an NSEvent with the character 0xF705,
 * the Backspace key produces 0x7F (ASCII del) and the Delete key produces
 * 0xF728.
 *
    {0x7B,	XK_Left},
    {0x7C,	XK_Right},
    {0x7D,	XK_Down},
    {0x7E,	XK_Up},

 * With the exception of modifier keys, it is possible to translate between
 * numerical X11 keysyms and macOS keychars; this file constructs Tcl hash
 * tables to do this job, using data defined in the file tkMacOSXKeysyms.h.
 * The code here adopts the convention that the keychar of any modifier key
 * is MOD_KEYCHAR.  Keys which do not appear on any Macintosh keyboard, such
 * as the Menu key on PC keyboards, are assigned UNKNOWN_KEYCHAR.
 *
    {0,		0}
};

 * The macosx platform-specific scheme for generating a keycode when mapping an
 * NSEvent of type KeyUp, KeyDown or FlagsChanged to an XEvent of type KeyPress
 * or KeyRelease is as follows:
 *     keycode = (virtual << 24) | index << 22 | keychar
 * where index is a 2-bit quantity whose bits indicate the state of the Option
 * and Shift keys.
 *
static KeyInfo virtualkeyArray[] = {
    {122,	XK_F1},
    {120,	XK_F2},
    {99,	XK_F3},
    {118,	XK_F4},
    {96,	XK_F5},
    {97,	XK_F6},
    {98,	XK_F7},
    {100,	XK_F8},
    {101,	XK_F9},
    {109,	XK_F10},
    {103,	XK_F11},
    {111,	XK_F12},
    {105,	XK_F13},
    {107,	XK_F14},
 * A few remarks are in order.  First, we are using 32 bits for the keycode and
    {113,	XK_F15},
    {0,		0}
 * we are allowing room for up to 22 bits for the keychar.  This means that
 * there is enough room in the keycode to hold a UTF-32 character, which only
};
 * requires 21 bits.  Second, the KeyCode type for the keycode field in an
 * XEvent is currently defined as unsigned int, which was modified from the
 * unsigned short used in X11 in order to accomodate macOS. Finally, there is
 * no obstruction to generating KeyPress events for keys that represent letters
 * which do not exist on the current keyboard layout.  And different keyboard
 * layouts can assign a given letter to different keys.  So we need a
 * convention for what value to assign to "virtual" when computing the keycode
 * for a generated event.  The convention used here is as follows: If there is
 * a key on the current keyboard which produces the keychar, use the virtual
 * keycode of that key.  Otherwise set virtual = NO_VIRTUAL.
 */

#define NUM_MOD_KEYCODES 14

static KeyCode modKeyArray[NUM_MOD_KEYCODES] = {
    XK_Shift_L,
    XK_Shift_R,
    XK_Control_L,
    XK_Control_R,
    XK_Caps_Lock,
    XK_Shift_Lock,
    XK_Meta_L,
    XK_Meta_R,
    XK_Alt_L,
/*
 * See tkMacOSXPrivate.h for macros and structures related to key event processing.
 */

    XK_Alt_R,
    XK_Super_L,
    XK_Super_R,
/*
 * Hash tables and array used to translate between various key attributes.
    XK_Hyper_L,
    XK_Hyper_R,
};
 */

static Tcl_HashTable special2keysym;	/* Special virtual keycode to keysym */
static int initialized = 0;
static Tcl_HashTable keycodeTable;	/* keyArray hashed by keycode value. */
static Tcl_HashTable vkeyTable;		/* virtualkeyArray hashed by virtual
					 * keycode value. */
static Tcl_HashTable keysym2keycode;	/* keysym to XEvent keycode */
static Tcl_HashTable keysym2unichar;	/* keysym to unichar */
static Tcl_HashTable unichar2keysym;	/* unichar to X11 keysym */
static Tcl_HashTable unichar2xvirtual;	/* unichar to virtual with index */
static UniChar xvirtual2unichar[512];	/* virtual with index to unichar */

static int latin1Table[LATIN1_MAX+1];	/* Reverse mapping table for
					 * controls, ASCII and Latin-1. */
/*
 * Flags.
 */

static BOOL initialized = NO;
static int keyboardChanged = 1;
static BOOL keyboardChanged = YES;

/*
 * Prototypes for static functions used in this file.
 */

static void	InitKeyMaps (void);
static void	InitLatin1Table(Display *display);
static void	InitHashTables(void);
static void     UpdateKeymaps(void);
static int	XKeysymToMacKeycode(Display *display, KeySym keysym);
static int	KeycodeToUnicode(UniChar * uniChars, int maxChars,
			UInt16 keyaction, UInt32 keycode, UInt32 modifiers,
static int	KeyDataToUnicode(UniChar *uniChars, int maxChars,
			UInt16 keyaction, UInt32 virtual, UInt32 modifiers,
			UInt32 * deadKeyStatePtr);

#pragma mark TKApplication(TKKeyboard)

@implementation TKApplication(TKKeyboard)
- (void) keyboardChanged: (NSNotification *) notification
{
    (void)notification;
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
    TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
#endif
    keyboardChanged = 1;
    keyboardChanged = YES;
    UpdateKeymaps();
}
@end

#pragma mark -

/*
 *----------------------------------------------------------------------
 *
 * InitKeyMaps --
 * InitHashTables --
 *
 *	Creates hash tables used by some of the functions in this file.
 *
 *	FIXME: As keycodes are defined to be in the limited range 0-127, it
 *	would be easier and more efficient to use directly initialized plain
 *	arrays and drop this function.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Allocates memory & creates some hash tables.
 *
 *----------------------------------------------------------------------
 */

static void
InitKeyMaps(void)
InitHashTables(void)
{
    Tcl_HashEntry *hPtr;
    KeyInfo *kPtr;
    int dummy;
    const KeyInfo *kPtr;
    const KeysymInfo *ksPtr;
    int dummy, index;

    Tcl_InitHashTable(&special2keysym, TCL_ONE_WORD_KEYS);
    Tcl_InitHashTable(&keycodeTable, TCL_ONE_WORD_KEYS);
    for (kPtr = keyArray; kPtr->keycode != 0; kPtr++) {
	hPtr = Tcl_CreateHashEntry(&keycodeTable, INT2PTR(kPtr->keycode),
		&dummy);
    Tcl_InitHashTable(&keysym2keycode, TCL_ONE_WORD_KEYS);
    for (kPtr = keyArray; kPtr->virtual != 0; kPtr++) {
	MacKeycode macKC;
	macKC.v.o_s = 0;
	hPtr = Tcl_CreateHashEntry(&special2keysym, INT2PTR(kPtr->virtual),
				   &dummy);
	Tcl_SetHashValue(hPtr, INT2PTR(kPtr->keysym));
	hPtr = Tcl_CreateHashEntry(&keysym2keycode, INT2PTR(kPtr->keysym),
				   &dummy);
	macKC.v.virtual = kPtr->virtual;
	macKC.v.keychar = kPtr->keychar;
	Tcl_SetHashValue(hPtr, INT2PTR(macKC.uint));
    }
    Tcl_InitHashTable(&vkeyTable, TCL_ONE_WORD_KEYS);
    for (kPtr = virtualkeyArray; kPtr->keycode != 0; kPtr++) {
	hPtr = Tcl_CreateHashEntry(&vkeyTable, INT2PTR(kPtr->keycode),
		&dummy);
	Tcl_SetHashValue(hPtr, INT2PTR(kPtr->keysym));

	/*
	 * The Carbon framework does not work for finding the unicode character
	 * of a special key.  But that does not depend on the keyboard layout,
	 * so we can record the information here.
	 */

	for (index = 3; index >= 0; index--) {
	    macKC.v.o_s = index;
	    xvirtual2unichar[macKC.x.xvirtual] = macKC.x.keychar;
	}
    }
    Tcl_InitHashTable(&keysym2unichar, TCL_ONE_WORD_KEYS);
    Tcl_InitHashTable(&unichar2keysym, TCL_ONE_WORD_KEYS);
    for (ksPtr = keysymTable; ksPtr->keysym != 0; ksPtr++) {
	hPtr = Tcl_CreateHashEntry(&keysym2unichar, INT2PTR(ksPtr->keysym),
				   &dummy);
	Tcl_SetHashValue(hPtr, INT2PTR(ksPtr->keycode));
	hPtr = Tcl_CreateHashEntry(&unichar2keysym, INT2PTR(ksPtr->keycode),
				   &dummy);
	Tcl_SetHashValue(hPtr, INT2PTR(ksPtr->keysym));
    }
    UpdateKeymaps();
    initialized = 1;
    initialized = YES;
}

/*
 *----------------------------------------------------------------------
 *
 * InitLatin1Table --
 * UpdateKeymaps --
 *
 *	Called when the keyboard changes to update the hash tables that provide
 *	Creates a simple table to be used for mapping from keysyms to keycodes.
 *	Always needs to be called before using latin1Table, because the
 *	keyboard layout may have changed, and than the table must be
 *      maps between unicode characters and virtual keycodes with indexes.  In
 *      order for the map from characters to virtual keycodes to be
 *      well-defined we have to ignore virtual keycodes for keypad keys, since
 *      each keypad key has the same character as the corresponding key on the
 *      main keyboard.
 *	re-computed.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Initializes, if necessary, and updates the unichar2xvirtual hash table
 *	Sets the global latin1Table.
 *      and the xvirtual2unichar array.
 *
 *----------------------------------------------------------------------
 */

static void
InitLatin1Table(
UpdateKeymaps()
    Display *display)
{
    int keycode;
    static Bool keymapInitialized = false;
    KeySym keysym;
    int state;
    int modifiers;
    Tcl_HashEntry *hPtr;
    int virtual, index, dummy;

    if (!keymapInitialized) {
    memset(latin1Table, 0, sizeof(latin1Table));

	Tcl_InitHashTable(&unichar2xvirtual, TCL_ONE_WORD_KEYS);
	keymapInitialized = true;
    } else {
	Tcl_DeleteHashTable(&unichar2xvirtual);
	Tcl_InitHashTable(&unichar2xvirtual, TCL_ONE_WORD_KEYS);
    }
    /*
     * In the common X11 implementations, a keymap has four columns
     * "plain", "Shift", "Mode_switch" and "Mode_switch + Shift". We don't
     * use "Mode_switch", but we use "Option" instead. (This is similar to
     * Apple's X11 implementation, where "Mode_switch" is used as an alias
     * for "Option".)
     *
     * So here we go through all 4 columns of the keymap and find all
     * This loop goes backwards so that a lookup by keychar will provide the
     * minimal modifier mask.  Simpler combinations will overwrite more complex
     * ones when constructing the table.
     */

     * Latin-1 compatible keycodes. We go through the columns back-to-front
     * from the more exotic columns to the more simple, so that simple
     * keycode-modifier combinations are preferred in the resulting table.
    for (index = 3; index >= 0; index--) {
        for (virtual = 0; virtual < 128; virtual++) {
     */

    for (state = 3; state >= 0; state--) {
	modifiers = 0;
	if (state & 1) {
	    modifiers |= shiftKey;
	}
	    MacKeycode macKC;
	    macKC.v = (keycode_v) {.virtual = virtual, .o_s = index, .keychar = 0};
	    int modifiers = INDEX2CARBON(index), result;
	    UniChar keychar = 0;
	    result = KeyDataToUnicode(&keychar, 1, kUCKeyActionDown, virtual,
				      modifiers, NULL);
	    if (keychar == 0x10) {

	if (state & 2) {
	    modifiers |= optionKey;
	}

	for (keycode = 0; keycode <= MAC_KEYCODE_MAX; keycode++) {
		/*
		 * This is a special key, handled in InitHashTables.
		 */

		continue;
	    }
	    macKC.v.keychar = keychar;
	    keysym = XKeycodeToKeysym(display,keycode<<16,state);
	    if (keysym <= LATIN1_MAX) {
		latin1Table[keysym] = keycode | modifiers;
	    }
	    if (! ON_KEYPAD(virtual)) {
		hPtr = Tcl_CreateHashEntry(&unichar2xvirtual,
					   INT2PTR(macKC.x.keychar), &dummy);
		Tcl_SetHashValue(hPtr, INT2PTR(macKC.x.xvirtual));
            }
	    xvirtual2unichar[macKC.x.xvirtual] = macKC.x.keychar;
	}
    }
}

/*
 *----------------------------------------------------------------------
 *
 * KeycodeToUnicode --
 * KeyDataToUnicode --
 *
 *	Given MacOS key event data this function generates the Unicode
 *	characters. It does this using OS resources and APIs.
 *	Given MacOS key event data this function generates the keychar.  It
 *	does this by using OS resources from the Carbon framework.  Note that
 *      the Carbon functions used here are not aware of the keychars in the
 *      private-use range which macOS now uses for special keys.  For those
 *      keys this function returns 0x10 (ASCII dle).
 *
 *	The parameter deadKeyStatePtr can be NULL, if no deadkey handling is
 *	needed.
 *	needed (which is always the case here).
 *
 *	This function is called from XKeycodeToKeysym() in tkMacOSKeyboard.c.
 *	This function is called in XKeycodeToKeysym and UpdateKeymaps.
 *
 * Results:
 *	The number of characters generated if any, 0 if we are waiting for
 *	another byte of a dead-key sequence. Fills in the uniChars array with a
 *	another byte of a dead-key sequence.
 *	Unicode string.
 *
 * Side Effects:
 *	None
 *	 Fills in the uniChars array with a Unicode string.
 *
 *----------------------------------------------------------------------
 */


static int
KeycodeToUnicode(
KeyDataToUnicode(
    UniChar *uniChars,
    int maxChars,
    UInt16 keyaction,
    UInt32 keycode,
    UInt32 virtual,
    UInt32 modifiers,
    UInt32 *deadKeyStatePtr)
{
    static const void *uchr = NULL;
    static const void *layoutData = NULL;
    static UInt32 keyboardType = 0;
    UniCharCount actuallength = 0;

    if (keyboardChanged) {
	TISInputSourceRef currentKeyboardLayout =
		TISCopyCurrentKeyboardLayoutInputSource();

	if (currentKeyboardLayout) {
	    CFDataRef keyLayoutData = (CFDataRef) TISGetInputSourceProperty(
		    currentKeyboardLayout, kTISPropertyUnicodeKeyLayoutData);

	    if (keyLayoutData) {
		uchr = CFDataGetBytePtr(keyLayoutData);
		layoutData = CFDataGetBytePtr(keyLayoutData);
		keyboardType = LMGetKbdType();
	    }
	    CFRelease(currentKeyboardLayout);
	}
	keyboardChanged = 0;
    }
    if (uchr) {
    if (layoutData) {
	OptionBits options = 0;
	UInt32 dummyState;
	OSStatus err;

	keycode &= 0xFF;
	virtual &= 0xFF;
	modifiers = (modifiers >> 8) & 0xFF;

	if (!deadKeyStatePtr) {
	    options = kUCKeyTranslateNoDeadKeysMask;
	    dummyState = 0;
	    deadKeyStatePtr = &dummyState;
	}

	err = ChkErr(UCKeyTranslate, uchr, keycode, keyaction, modifiers,
	err = ChkErr(UCKeyTranslate, layoutData, virtual, keyaction, modifiers,
		keyboardType, options, deadKeyStatePtr, maxChars,
		&actuallength, uniChars);

	if (!actuallength && *deadKeyStatePtr) {

	    /*
	     * More data later
	     * We are waiting for another key.
	     */

	    return 0;
	}
	*deadKeyStatePtr = 0;
	if (err != noErr) {
	    actuallength = 0;
	}
    }
    return actuallength;
}

/*
 *----------------------------------------------------------------------
 *
 * XKeycodeToKeysym --
 *
 *	Translate from a system-dependent keycode to a system-independent
 *	keysym.
 *	This is a stub function which translates from the keycode used in an
 *      XEvent to a numerical keysym.  On macOS, the display parameter is
 *      ignored and only the the virtual keycode stored in the .virtual bitfield
 *      of a MacKeycode.v.
 *
 * Results:
 *	Returns the translated keysym, or NoSymbol on failure.
 *      Returns the corresponding numerical keysym, or NoSymbol if the keysym
 *      cannot be found.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

KeySym
XKeycodeToKeysym(
    Display* display,
    KeyCode keycode,
XkbKeycodeToKeysym(
    TCL_UNUSED(Display *),
    unsigned int keycode,
    TCL_UNUSED(int),
    int index)
{
    register Tcl_HashEntry *hPtr;
    int newKeycode;
    UniChar newChar;
    Tcl_HashEntry *hPtr;
    MacKeycode macKC;
    int modifiers, result;
    UniChar keychar = 0;

    (void) display; /*unused*/

    if (!initialized) {
	InitKeyMaps();
	InitHashTables();
    }
    macKC.uint = keycode;
    macKC.v.o_s = index;

    /*
     * When determining what keysym to produce we first check to see if the key
     * is a function key. We then check to see if the character is another
     * First check if the virtual keycode corresponds to a special key, such as
     * an Fn function key or Tab, Backspace, Home, End, etc.
     * non-printing key. Finally, we return the key syms for all ASCII and
     * Latin-1 chars.
     */

    newKeycode = keycode >> 16;

    if ((keycode & 0xFFFF) >= 0xF700) { /* NSEvent.h function key unicodes */
	hPtr = Tcl_FindHashEntry(&vkeyTable, INT2PTR(newKeycode));
	if (hPtr != NULL) {
	    return (KeySym) Tcl_GetHashValue(hPtr);
	}
    }
    hPtr = Tcl_FindHashEntry(&keycodeTable, INT2PTR(newKeycode));
    hPtr = Tcl_FindHashEntry(&special2keysym, INT2PTR(macKC.v.virtual));
    if (hPtr != NULL) {
	return (KeySym) Tcl_GetHashValue(hPtr);
    }

    /*
     * If the virtual value in this keycode does not correspond to an actual
    if (hPtr != NULL) {
	return (KeySym) Tcl_GetHashValue(hPtr);
    }

     * key in the current keyboard layout, try using its keychar to look up a
     * keysym.
     */

    if (macKC.v.virtual > 127) {
    /*
     * Add in the Mac modifier flags for shift and option.
     */

    if (index & 1) {
	newKeycode |= shiftKey;
    }
	hPtr = Tcl_FindHashEntry(&unichar2keysym, INT2PTR(macKC.v.keychar));
	if (hPtr != NULL) {
	    return (KeySym) Tcl_GetHashValue(hPtr);
	}
    if (index & 2) {
	newKeycode |= optionKey;
    }

    newChar = 0;
    KeycodeToUnicode(&newChar, 1, kUCKeyActionDown, newKeycode & 0x00FF,
	    newKeycode & 0xFF00, NULL);

    /*
     * If the virtual keycode does belong to a key, use the virtual and the
     * Option-Shift from index to look up a keychar by using the Carbon
     * Framework; then translate the keychar to a keysym using the
     * X11 keysyms are identical to Unicode for ASCII and Latin-1. Give up for
     * unicode2keysym hash table.
     * other characters for now.
     */

    modifiers = INDEX2CARBON(macKC.v.o_s);
    result = KeyDataToUnicode(&keychar, 1, kUCKeyActionDown, macKC.v.virtual,
			      modifiers, NULL);
    if ((newChar >= XK_space) && (newChar <= LATIN1_MAX)) {
	return newChar;
    }

    if (result) {
	hPtr = Tcl_FindHashEntry(&unichar2keysym, INT2PTR(keychar));
	if (hPtr != NULL) {
	    return (KeySym) Tcl_GetHashValue(hPtr);
	}
    }
    return NoSymbol;
}

KeySym
XKeycodeToKeysym(
    TCL_UNUSED(Display *),
    unsigned int keycode,
    int index)
{
    return XkbKeycodeToKeysym(NULL, keycode, 0, index);
}

/*
 *----------------------------------------------------------------------
 *
 * TkpGetString --
 *
 *	Retrieve the string equivalent for the given keyboard event.
 *	This is a stub function which retrieves the string stored in the
 *      transchars field of an XEvent and converts it to a Tcl_DString.
 *
 * Results:
 *	Returns the UTF string.
 *	Returns a pointer to the string value of the DString.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

const char *
TkpGetString(
    TkWindow *winPtr,		/* Window where event occurred: Needed to get
    TCL_UNUSED(TkWindow *),	/* Window where event occurred: Needed to get
				 * input context. */
    XEvent *eventPtr,		/* X keyboard event. */
    Tcl_DString *dsPtr)		/* Uninitialized or empty string to hold
				 * result. */
{
    MacKeycode macKC;
    char utfChars[8];
    int length = 0;
    (void) winPtr; /*unused*/
    int ch;


    macKC.uint = eventPtr->xkey.keycode;
    if (IS_PRINTABLE(macKC.v.keychar)) {
	length = TkUniCharToUtf(macKC.v.keychar, utfChars);
    }
    utfChars[length] = 0;

    Tcl_DStringInit(dsPtr);
    return Tcl_DStringAppend(dsPtr, eventPtr->xkey.trans_chars,
    return Tcl_DStringAppend(dsPtr, utfChars, length);
	    TkUtfToUniChar(eventPtr->xkey.trans_chars, &ch));
}

/*
 *----------------------------------------------------------------------
 *
 * XGetModifierMapping --
 *
 *	Fetch the current keycodes used as modifiers.
 *	X11 stub function to get the keycodes used as modifiers.  This
 *      is never called by the macOS port.
 *
 * Results:
 *	Returns a new modifier map.
 *	Returns a newly allocated modifier map.
 *
 * Side effects:
 *	Allocates a new modifier map data structure.
 *
 *----------------------------------------------------------------------
 */

XModifierKeymap *
XGetModifierMapping(
    Display *display)
    TCL_UNUSED(Display *))
{
    XModifierKeymap *modmap;

    (void) display; /*unused*/

    /*
     * MacOSX doesn't use the key codes for the modifiers for anything, and we
     * don't generate them either. So there is no modifier map.
     */
    modmap = ckalloc(sizeof(XModifierKeymap));
    modmap = (XModifierKeymap *)ckalloc(sizeof(XModifierKeymap));
    modmap->max_keypermod = 0;
    modmap->modifiermap = NULL;
    return modmap;
}

/*
 *----------------------------------------------------------------------
 *
 * XFreeModifiermap --
 *
 *	Deallocate a modifier map that was created by XGetModifierMapping.
 *	Deallocates a modifier map that was created by XGetModifierMapping.
 *      This is also never called by the macOS port.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Frees the datastructure referenced by modmap.
 *
512
513
514
515
516
517
518
519
520
521
522




523
524
525
526
527
528
529
530
531
532
533
534
535

536
537
538
539
540
541
542

543
544
545
546
547
548
549
550

551
552
553
554
555
556
557
558
559
560
561
562
563
564

565
566
567
568
569
570
571
572
573
574
575
576

577
578
579
580
581
582
583

584
585
586
587
588
589

590
591
592
593
594
595
596
597
598
599
600

601
602
603
604
605

606
607
608
609
610
611

612
613
614
615
616

617
618
619

620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642

643
644

645
646
647





648
649
650

651
652
653
654
655
656
657
658
659
660
661































662
663
664
665
666
667
668
669

670
671

672
673
674
675
676
677
678

679
680




681

682
683
684
685
686
687
688

689
690
691
692
693
694
695
696
697
698
699
700
701
702
703



704
705
706









707
708
709


710
711

712
713
714
715
716
717
718













719
720
721



722
723
724
725


726
727

728
729
730
731
732
733
734
735
736

737
738


739
740
741
742
743
744
745

746

747
748
749
750
751
752
753
754
755
756
757


758
759
760
761
762
763
764
765
766
767
768

769
770
771
772
773
774
775





776
777

778
779

780
781

782
783

784
785
786
787
788
789
790

791
792

793
794

795
796
797

798
799
800
801


802
803
804
805
806
807
808
809
810
811
812
813
814
815

816
817
818
819

820
821
822
823
824
825
826
827
828


829
830
831
832
833
834
835
836
837
838
839

840
841
842

843
844
845
846
847



848
849
850

851
852
853
854
855
856
857
858

859
860
861
862


863
864
865
866
867
868
869
870
871
872
873



874
875
876
877
878
879
880
881
882
883
884


885
886
887
888
889
890
891

892
893
894
895
896
897
898
899
900
901
902
903
904
905




906
907
908
909



910
911
912
913
914
915
916
917
918




919
920
921
922
923
924
925
926
927
928

929

930
931

932
933
934
935
936
937
938
939
940
941

942
943
944













































945
946
947
948
949
950
951
952
567
568
569
570
571
572
573




574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589

590
591
592
593
594
595
596

597
598
599
600
601
602
603
604

605
606













607












608







609






610











611





612






613





614



615













616
617
618
619
620
621
622
623
624

625
626
627
628



629
630
631
632
633
634


635

636
637








638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675

676


677

678
679




680
681
682
683
684
685
686

687
688
689
690

691
692

693
694
695
696
697
698







699


700
701
702
703
704

705
706
707
708
709
710
711
712
713
714


715
716


717
718






719
720
721
722
723
724
725
726
727
728
729
730
731



732
733
734




735
736


737

738
739
740
741
742
743
744
745
746


747
748
749
750
751
752
753
754

755

756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779

780

781
782




783
784
785
786
787
788

789
790

791
792

793
794

795
796






797
798

799
800

801
802


803




804
805
806
807
808
809






810
811
812

813

814
815

816









817
818
819

820






821

822
823
824

825
826
827



828
829
830
831
832

833








834




835
836
837
838
839
840
841
842
843
844



845
846
847
848
849
850
851
852
853
854
855
856


857
858

859
860
861
862
863

864
865
866
867
868
869
870
871
872
873
874
875
876


877
878
879
880
881
882
883
884
885
886
887
888
889







890
891
892
893
894
895



896
897

898
899
900

901


902

903
904
905
906
907
908
909
910

911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967







-
-
-
-
+
+
+
+












-
+






-
+







-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
+
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
+
-
-
-
-
-
-
+
-
-
-
-
-
+
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-









-
+


+
-
-
-
+
+
+
+
+

-
-
+
-


-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







-
+
-
-
+
-


-
-
-
-
+


+
+
+
+
-
+



-


-
+





-
-
-
-
-
-
-

-
-
+
+
+


-
+
+
+
+
+
+
+
+
+

-
-
+
+
-
-
+

-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
-
-
-
-
+
+
-
-
+
-








+
-
-
+
+






-
+
-
+











+
+










-
+
-


-
-
-
-
+
+
+
+
+

-
+

-
+

-
+

-
+

-
-
-
-
-
-
+

-
+

-
+

-
-
+
-
-
-
-
+
+




-
-
-
-
-
-



-
+
-


-
+
-
-
-
-
-
-
-
-
-
+
+

-

-
-
-
-
-
-

-
+


-
+


-
-
-
+
+
+


-
+
-
-
-
-
-
-
-
-
+
-
-
-
-
+
+








-
-
-
+
+
+









-
-
+
+
-





-
+












-
-
+
+
+
+




+
+
+


-
-
-
-
-
-
-
+
+
+
+


-
-
-


-


+
-
+
-
-
+
-








-
+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








}

/*
 *----------------------------------------------------------------------
 *
 * XKeysymToString, XStringToKeysym --
 *
 *	These X window functions map keysyms to strings & strings to keysyms.
 *	However, Tk already does this for the most common keysyms. Therefore,
 *	these functions only need to support keysyms that will be specific to
 *	the Macintosh. Currently, there are none.
 *	These X11 stub functions map keysyms to strings & strings to keysyms.
 *      A platform can do its own conversion by defining these and undefining
 *      REDO_KEYSYM_LOOKUP.  The macOS port defines REDO_KEYSYM_LOOKUP so these
 *      are never called and Tk does the conversion for us.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

char *
XKeysymToString(
    KeySym keysym)
    TCL_UNUSED(KeySym))
{
    return NULL;
}

KeySym
XStringToKeysym(
    const char* string)
    TCL_UNUSED(const char *))
{
    return NoSymbol;
}

/*
 *----------------------------------------------------------------------
 *
 * XKeysymToMacKeycode --
 * XKeysymToKeycode --
 *
 *	An internal function like XKeysymToKeycode but only generating the Mac
 *	specific keycode plus the modifiers Shift and Option.
 *
 * Results:
 *	A Mac keycode with the actual keycode in the low byte and Mac-style
 *	modifier bits in the high byte.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

 *	This is a stub function which converts a numerical keysym to the
static int
XKeysymToMacKeycode(
    Display *display,
    KeySym keysym)
{
    KeyInfo *kPtr;
    if (keysym <= LATIN1_MAX) {
	/*
	 * Handle keysyms in the Latin-1 range where keysym and Unicode
	 * character code point are the same.
	 */

 *      platform-specific keycode used in a KeyPress or KeyRelease XEvent.
	if (keyboardChanged) {
	    InitLatin1Table(display);
	    keyboardChanged = 0;
	}
	return latin1Table[keysym];
    }

 *      For macOS the keycode is an unsigned int with bitfields described
    /*
     * Handle special keys from our exception tables. Don't mind if this is
     * slow, neither the test suite nor [event generate] need to be optimized
     * (we hope).
     */

 *      in the definition of the MacKeycode type.
    for (kPtr = keyArray; kPtr->keycode != 0; kPtr++) {
	if (kPtr->keysym == keysym) {
	    return kPtr->keycode;
	}
    }
    for (kPtr = virtualkeyArray; kPtr->keycode != 0; kPtr++) {
	if (kPtr->keysym == keysym) {
	    return kPtr->keycode;
	}
    }

 *
    /*
     * Modifier keycodes only come from generated events.  No translation
     * is needed.
     */

 * Results:
    for (int i=0; i < NUM_MOD_KEYCODES; i++) {
	if (keysym == modKeyArray[i]) {
	    return keysym;
	}
    }

 *
    /*
     * For other keysyms (not Latin-1 and not special keys), we'd need a
     * generic keysym-to-unicode table. We don't have that, so we give up here.
     */

 *      A macOS KeyCode. See the description of keycodes at the top of this
    return 0;
}

 *	file and the definition of the MacKeycode type in tkMacOSXPrivate.h.
/*
 *----------------------------------------------------------------------
 *
 * XKeysymToKeycode --
 *
 *	The function XKeysymToKeycode takes an X11 keysym and converts it into
 *	a Mac keycode. It is in the stubs table for compatibility but not used
 *	anywhere in the core.
 *
 * Results:
 *	A 32 bit keycode with the the mac keycode (without modifiers) in the
 *	higher 16 bits of the keycode and the ASCII or Latin-1 code in the
 *	lower 8 bits of the keycode.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

KeyCode
XKeysymToKeycode(
    Display* display,
    TCL_UNUSED(Display *),
    KeySym keysym)
{
    Tcl_HashEntry *hPtr;
    int macKeycode = XKeysymToMacKeycode(display, keysym);
    KeyCode result;

    MacKeycode macKC;
    if (!initialized) {
	InitHashTables();
    }

    /*
     * See also TkpSetKeycodeAndState. The 0x0010 magic is used in
     * XKeycodeToKeysym. For special keys like XK_Return the lower 8 bits of
     * First check for a special key.
     * the keysym are usually a related ASCII control code.
     */

    if ((keysym >= XK_F1) && (keysym <= XK_F35)) {
	result = 0x0010;
    } else {
	result = 0x00FF & keysym;
    }
    result |= (macKeycode & MAC_KEYCODE_MASK) << 16;

    return result;
    hPtr = Tcl_FindHashEntry(&keysym2keycode, INT2PTR(keysym));
    if (hPtr != NULL) {
	return (KeyCode) Tcl_GetHashValue(hPtr);
    }

    /*
     * Initialize the keycode as if the keysym cannot be converted to anything
     * else.
     */

    macKC.v.virtual = NO_VIRTUAL;
    macKC.v.o_s = 0;
    macKC.v.keychar = 0;

    /*
     * If the keysym is recognized fill in the keychar.  Also fill in the
     * xvirtual field if the key exists on the current keyboard.
     */

    hPtr = (Tcl_HashEntry *) Tcl_FindHashEntry(&keysym2unichar,
					       INT2PTR(keysym));
    if (hPtr != NULL) {
	unsigned long data = (unsigned long) Tcl_GetHashValue(hPtr);
	macKC.x.keychar = (unsigned int) data;
	hPtr = Tcl_FindHashEntry(&unichar2xvirtual, INT2PTR(macKC.x.keychar));
	if (hPtr != NULL) {
	    data = (unsigned long) Tcl_GetHashValue(hPtr);
	    macKC.x.xvirtual = (unsigned int) data;
	}
    }
    return (KeyCode) macKC.uint;
}

/*
 *----------------------------------------------------------------------
 *
 * TkpSetKeycodeAndState --
 *
 *	The function TkpSetKeycodeAndState takes a keysym and fills in the
 *	This function accepts a keysym and an XEvent and sets some fields of
 *	appropriate members of an XEvent. It is similar to XKeysymToKeycode,
 *	but it also sets the modifier mask in the XEvent. It is used by [event
 *	the XEvent.  It is used by the event generate command.
 *	generate] and it is in the stubs table.
 *
 * Results:
 *	Fills an XEvent, sets the member xkey.keycode with a keycode
 *	formatted the same as XKeysymToKeycode and the member xkey.state with
 *	the modifiers implied by the keysym. Also fills in xkey.trans_chars,
 *	so that the actual characters can be retrieved later.
 *      None
 *
 * Side effects:
 *
 *	Modifies the XEvent. Sets the xkey.keycode to a keycode value formatted
 *	by XKeysymToKeycode and updates the shift and option flags in
 *	xkey.state if either of those modifiers is required to generate the
 *	None.
 *	keysym.
 *
 *----------------------------------------------------------------------
 */

void
TkpSetKeycodeAndState(
    Tk_Window tkwin,
    TCL_UNUSED(Tk_Window),
    KeySym keysym,
    XEvent *eventPtr)
{
    if (keysym == NoSymbol) {
	eventPtr->xkey.keycode = 0;
    } else if ( modKeyArray[0] <= keysym &&
		keysym <= modKeyArray[NUM_MOD_KEYCODES - 1]) {
	/*
	 * Keysyms for pure modifiers only arise in generated events.
	 * We should just copy them to the keycode.
	 */
	eventPtr->xkey.keycode = keysym;
    } else {
	Display *display = Tk_Display(tkwin);
	int macKeycode = XKeysymToMacKeycode(display, keysym);
	int eventIndex = STATE2INDEX(eventPtr->xkey.state);
	MacKeycode macKC;
	macKC.uint = XKeysymToKeycode(NULL, keysym);

	/*
	 * See also XKeysymToKeycode.
	 * We have a virtual keycode and a minimal choice for Shift and Option
	 * modifiers which generates the keychar that corresponds to the
	 * specified keysym.  But we might not have the correct keychar yet,
	 * because the xEvent may have specified modifiers beyond our minimal
	 * set.  For example, the events described by <Oslash>, <Shift-oslash>,
	 * <Shift-Option-O> and <Shift-Option-o> should all produce the same
	 * uppercase Danish O.  So we may need to add the extra modifiers and
	 * do another lookup for the keychar.  We don't want to do this for
	 * special keys, however.
	 */
	if ((keysym >= XK_F1) && (keysym <= XK_F35)) {
	    eventPtr->xkey.keycode = 0x0010;

	if (macKC.v.o_s != eventIndex) {
	} else {
	    eventPtr->xkey.keycode = 0x00FF & keysym;
	    macKC.v.o_s |= eventIndex;
	}
	eventPtr->xkey.keycode |= (macKeycode & MAC_KEYCODE_MASK) << 16;

	if (shiftKey & macKeycode) {
	    eventPtr->xkey.state |= ShiftMask;
	}
	if (optionKey & macKeycode) {
	if (macKC.v.keychar < 0xF700) {
	    UniChar keychar = macKC.v.keychar;
	    NSString *str, *lower, *upper;
	    if (macKC.v.virtual != NO_VIRTUAL) {
		macKC.x.keychar = xvirtual2unichar[macKC.x.xvirtual];
	    } else {
		str = [[NSString alloc] initWithCharacters:&keychar length:1];
		lower = [str lowercaseString];
		upper = [str uppercaseString];
		if (![str isEqual: lower]) {
		    macKC.v.o_s |= INDEX_SHIFT;
		}
		if (macKC.v.o_s & INDEX_SHIFT) {
	    eventPtr->xkey.state |= OPTION_MASK;
	}

		    macKC.v.keychar = [upper characterAtIndex:0];
		}
	    }
	if (keysym <= LATIN1_MAX) {
	    int done = TkUniCharToUtf(keysym, eventPtr->xkey.trans_chars);

	    eventPtr->xkey.trans_chars[done] = 0;
	}
	eventPtr->xkey.keycode = macKC.uint;
	} else {
	    eventPtr->xkey.trans_chars[0] = 0;
	eventPtr->xkey.state |= INDEX2STATE(macKC.v.o_s);
	}
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TkpGetKeySym --
 *
 *	This is a stub function called in tkBind.c.  Given a KeyPress or
 *	Given an X KeyPress or KeyRelease event, map the keycode in the event
 *	into a keysym.
 *	KeyRelease XEvent, it maps the keycode in the event to a numerical
 *      keysym.
 *
 * Results:
 *	The return value is the keysym corresponding to eventPtr, or NoSymbol
 *	if no matching keysym could be found.
 *
 * Side effects:
 *	In the first call for a given display, keycode-to-keysym maps get
 *	In the first call for a given display, calls TkpInitKeymapInfo.
 *	loaded.
 *
 *
 *----------------------------------------------------------------------
 */

KeySym
TkpGetKeySym(
    TkDisplay *dispPtr,		/* Display in which to map keycode. */
    XEvent *eventPtr)		/* Description of X event. */
{
    KeySym sym;
    int index;
    MacKeycode macKC;
    macKC.uint = eventPtr->xkey.keycode;

    /*
     * Refresh the mapping information if it's stale.
     */

    if (dispPtr->bindInfoStale) {
	TkpInitKeymapInfo(dispPtr);
    }

    /*
     * Handle pure modifier keys specially. We use -1 as a signal for
     * Modifier key events have a special mac keycode (see tkProcessKeyEvent).
     * this.
     */

    if (eventPtr->xany.send_event == -1) {
	int modifier = eventPtr->xkey.keycode & NSDeviceIndependentModifierFlagsMask;

	if (modifier == NSCommandKeyMask) {
    if (macKC.v.keychar == MOD_KEYCHAR) {
	switch (macKC.v.virtual) {
	case 54:
	    return XK_Meta_R;
	case 55:
	    return XK_Meta_L;
	} else if (modifier == NSShiftKeyMask) {
	case 56:
	    return XK_Shift_L;
	} else if (modifier == NSAlphaShiftKeyMask) {
	case 57:
	    return XK_Caps_Lock;
	} else if (modifier == NSAlternateKeyMask) {
	case 58:
	    return XK_Alt_L;
	} else if (modifier == NSControlKeyMask) {
	case 59:
	    return XK_Control_L;
	} else if (modifier == NSNumericPadKeyMask) {
	    return XK_Num_Lock;
	} else if (modifier == NSFunctionKeyMask) {
	    return XK_Super_L;
/*
	} else if (modifier == rightShiftKey) {
	case 60:
	    return XK_Shift_R;
	} else if (modifier == rightOptionKey) {
	case 61:
	    return XK_Alt_R;
	} else if (modifier == rightControlKey) {
	case 62:
	    return XK_Control_R;
*/
	} else {
	case 63:
	    /*
	     * If we get here, we probably need to implement something new.
	     */

	    return XK_Super_L;
	default:
	    return NoSymbol;
	}
    }

    /* If nbytes has been set, it's not a function key, but a regular key that
       has been translated in tkMacOSXKeyEvent.c; just use that. */
    if (eventPtr->xkey.nbytes) {
      return eventPtr->xkey.keycode;
    }

    /*
     * Figure out which of the four slots in the keymap vector to use for this
     * key. Refer to Xlib documentation for more info on how this computation
     * works. (Note: We use "Option" in keymap columns 2 and 3 where other
     * works.
     * implementations have "Mode_switch".)
     */

    index = 0;
    index = STATE2INDEX(eventPtr->xkey.state);

    /*
     * We want Option key combinations to use their base chars as keysyms, so
     * we ignore the option modifier here.
     */

#if 0
    if (eventPtr->xkey.state & OPTION_MASK) {
	index |= 2;
    if (eventPtr->xkey.state & LockMask) {
	index |= INDEX_SHIFT;
    }
#endif

    if ((eventPtr->xkey.state & ShiftMask)
	    || (/* (dispPtr->lockUsage != LU_IGNORE)
	    && */ (eventPtr->xkey.state & LockMask))) {
	index |= 1;
    }

    /*
     * First try of the actual translation.
     * First do the straightforward lookup.
     */

    sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode, index);
    sym = XkbKeycodeToKeysym(dispPtr->display, macKC.uint, 0, index);

    /*
     * Special handling: If the key was shifted because of Lock, but lock is
     * only caps lock, not shift lock, and the shifted keysym isn't upper-case
     * alphabetic, then switch back to the unshifted keysym.
     * Special handling: If the key was shifted because of Lock, which is only
     * caps lock on macOS, not shift lock, and if the shifted keysym isn't
     * upper-case alphabetic, then switch back to the unshifted keysym.
     */

    if ((index & 1) && !(eventPtr->xkey.state & ShiftMask)
    if ((index & INDEX_SHIFT) && !(eventPtr->xkey.state & ShiftMask)) {
	    /*&& (dispPtr->lockUsage == LU_CAPS)*/ ) {
	/*
	 * FIXME: Keysyms are only identical to Unicode for ASCII and Latin-1,
	 * so we can't use Tcl_UniCharIsUpper() for keysyms outside that range.
	 * This may be a serious problem here.
	 */

	if ((sym == NoSymbol) || (sym > LATIN1_MAX)
	if ((sym == NoSymbol) || !Tcl_UniCharIsUpper(sym)) {
		|| !Tcl_UniCharIsUpper(sym)) {
	    index &= ~1;
	    sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode,
		    index);
	    sym = XkbKeycodeToKeysym(dispPtr->display, macKC.uint, 0,
				   index & ~INDEX_SHIFT);
	}
    }

    /*
     * Another bit of special handling: If this is a shifted key and there is
     * no keysym defined, then use the keysym for the unshifted key.
     */

    if ((index & 1) && (sym == NoSymbol)) {
	sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode,
		index & ~1);
    if ((index & INDEX_SHIFT) && (sym == NoSymbol)) {
	sym = XkbKeycodeToKeysym(dispPtr->display, macKC.uint, 0,
			       index & ~INDEX_SHIFT);
    }
    return sym;
}

/*
 *--------------------------------------------------------------
 *
 * TkpInitKeymapInfo --
 *
 *	This procedure is invoked to scan keymap information to recompute stuff
 *	that's important for binding, such as the modifier key (if any) that
 *	This procedure initializes fields in the display that pertain
 *      to modifier keys.
 *	corresponds to the "Mode_switch" keysym.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Keymap-related information in dispPtr is updated.
 *	Modifier key information in dispPtr is initialized.
 *
 *--------------------------------------------------------------
 */

void
TkpInitKeymapInfo(
    TkDisplay *dispPtr)		/* Display for which to recompute keymap
				 * information. */
{
    dispPtr->bindInfoStale = 0;

    /*
     * Behaviours that are variable on X11 are defined constant on MacOSX.
     * lockUsage is only used above in TkpGetKeySym(), nowhere else currently.
     * On macOS the caps lock key is always interpreted to mean that alphabetic
     * keys become uppercase but other keys do not get shifted.  (X11 allows
     * a configuration option which makes the caps lock equivalent to holding
     * down the shift key.)
     * There is no offical "Mode_switch" key.
     */

    dispPtr->lockUsage = LU_CAPS;

    /* This field is no longer used by tkBind.c */

    dispPtr->modeModMask = 0;

#if 0
    /*
     * With this, <Alt> and <Meta> become synonyms for <Command> and <Option>
     * in bindings like they are (and always have been) in the keysyms that
     * are reported by KeyPress events. But the init scripts like text.tcl
     * have some disabling bindings for <Meta>, so we don't want this without
     * some changes in those scripts. See also bug #700311.
    /* The Alt and Meta keys are interchanged on Macintosh keyboards compared
     * to PC keyboards.  These fields could be set to make the Alt key on a PC
     * keyboard behave likd an Alt key. That would also require interchanging
     * Mod1Mask and Mod2Mask in tkMacOSXKeyEvent.c.
     */

    dispPtr->altModMask = OPTION_MASK;
    dispPtr->metaModMask = COMMAND_MASK;
#else
    dispPtr->altModMask = 0;
    dispPtr->metaModMask = 0;
#endif

    /*
     * The modKeyCodes table lists the keycodes that appear in KeyPress or
     * MacOSX doesn't create a key event when a modifier key is pressed or
     * KeyRelease XEvents for modifier keys.  In tkBind.c this table is
     * released.  However, it is possible to generate key events for
     * modifier keys, and this is done in the tests.  So we construct an array
     * searched to determine whether an XEvent corresponds to a modifier key.
     * containing the keycodes of the standard modifier keys from static data.
     */

    if (dispPtr->modKeyCodes != NULL) {
	ckfree(dispPtr->modKeyCodes);
    }
    dispPtr->numModKeyCodes = NUM_MOD_KEYCODES;
    dispPtr->modKeyCodes = (KeyCode *)ckalloc(NUM_MOD_KEYCODES * sizeof(KeyCode));
    for (int i = 0; i < NUM_MOD_KEYCODES; i++) {
	dispPtr->modKeyCodes[i] = modKeyArray[i];
	dispPtr->modKeyCodes[i] = XKeysymToKeycode(NULL, modKeyArray[i]);
    }
}

/*
 *--------------------------------------------------------------
 *
 * TkMacOSXAddVirtual --
 *
 *	This procedure is an internal utility which accepts an unsigned int
 *      that has been partially filled as a MacKeycode, having the Option and
 *      Shift state set in the o_s field and the keychar field set but with the
 *      virtual keycode blank.  It looks up the virtual keycode for the keychar
 *      (possibly NO_VIRTUAL) and returns an unsigned int which is a complete
 *      MacKeycode with the looked up virtual keycode added.  This is used when
 *      creating XEvents for the unicode characters which are generated by the
 *      NSTextInputClient.
 *
 * Results:
 *      An unsigned int which is a complete MacKeycode, including a virtual
 *	keycode which matches the Option-Shift state and keychar.
 *
 * Side effects:
 *	None
 *
 *--------------------------------------------------------------
 */
unsigned
TkMacOSXAddVirtual(
    unsigned int keycode)
{
    MacKeycode macKC;
    Tcl_HashEntry *hPtr;
    macKC.uint = keycode;

    if (!initialized) {
	InitHashTables();
    }

    hPtr = (Tcl_HashEntry *) Tcl_FindHashEntry(&unichar2xvirtual,
					       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;
    }
    return macKC.uint;
}
/*
 * Local Variables:
 * mode: objc
 * c-basic-offset: 4
 * fill-column: 79
 * coding: utf-8
 * End:
 */
Added macosx/tkMacOSXKeysyms.h.




























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
 * tkMacOSXKeysyms.h --
 *
 *      Contains data used for processing key events, some of which was
 *      moved from tkMacOSXKeyboard.c.
 *
 * 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 <[email protected]>
 * 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.
 */

#ifndef TKMACOSXKEYSYMS_H
#define TKMACOSXKEYSYMS_H 1

/*
 * This table enumerates the keys on Mac keyboards which do not represent
 * letters.  This is static data -- these keys do not change when the keyboard
 * layout changes.  The unicode representation of a special key which is not a
 * modifier and does not have an ASCII code point lies in the reserved range
 * 0xF700 - 0xF8FF.
 *
 * The table includes every key listed in Apple's documentation of Function-Key
 * Unicodes which is not marked as "Not on most Macintosh keyboards", as well
 * 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] */
    KeySym keysym;	/* X11 keysym */
    KeyCode keychar;	/* XEvent keycode & 0xFFFF */
} KeyInfo;

static const KeyInfo keyArray[] = {
    {36,	XK_Return,	NSNewlineCharacter},
    {48,	XK_Tab,		NSTabCharacter},
    {51,	XK_BackSpace,	NSDeleteCharacter},
    {52,	XK_Return,	NSNewlineCharacter},  /* Used on some Powerbooks */
    {53,	XK_Escape,	0x1B},
    {54,	XK_Meta_R,      MOD_KEYCHAR},
    {55,	XK_Meta_L,	MOD_KEYCHAR},
    {56,	XK_Shift_L,	MOD_KEYCHAR},
    {57,	XK_Caps_Lock,   MOD_KEYCHAR},
    {58,	XK_Alt_L,	MOD_KEYCHAR},
    {59,	XK_Control_L,	MOD_KEYCHAR},
    {60,	XK_Shift_R, 	MOD_KEYCHAR},
    {61,	XK_Alt_R,	MOD_KEYCHAR},
    {62,	XK_Control_R,	MOD_KEYCHAR},
    {63,	XK_Super_L,	MOD_KEYCHAR},
    {64,	XK_F17,		NSF17FunctionKey},
    {65,	XK_KP_Decimal,	'.'},
    {67,	XK_KP_Multiply, '*'},
    {69,	XK_KP_Add,	'+'},
    {71,	XK_Clear,       NSClearLineFunctionKey}, /* Numlock on PC */
    {75,	XK_KP_Divide,   '/'},
    {76,	XK_KP_Enter,	NSEnterCharacter},       /* Fn Return */
    {78,	XK_KP_Subtract, '-'},
    {79,	XK_F18,		NSF18FunctionKey},
    {80,	XK_F19,		NSF19FunctionKey},
    {81,	XK_KP_Equal,	'='},
    {82,	XK_KP_0,	'0'},
    {83,	XK_KP_1,	'1'},
    {84,	XK_KP_2,	'2'},
    {85,	XK_KP_3,	'3'},
    {86,	XK_KP_4,	'4'},
    {87,	XK_KP_5,	'5'},
    {88,	XK_KP_6,	'6'},
    {89,	XK_KP_7,	'7'},
    {90,	XK_F20,		NSF20FunctionKey}, /* For scripting only */
    {91,	XK_KP_8,	'8'},
    {92,	XK_KP_9,	'9'},
    {96,	XK_F5,		NSF5FunctionKey},
    {97,	XK_F6,		NSF6FunctionKey},
    {98,	XK_F7,		NSF7FunctionKey},
    {99,	XK_F3,		NSF3FunctionKey},
    {100,	XK_F8,		NSF8FunctionKey},
    {101,	XK_F9,		NSF9FunctionKey},
    {103,	XK_F11,		NSF11FunctionKey},
    {105,	XK_F13,		NSF13FunctionKey},
    {106,	XK_F16,		NSF16FunctionKey},
    {107,	XK_F14,		NSF14FunctionKey},
    {109,	XK_F10,		NSF10FunctionKey},
    {110,       XK_Menu,	UNKNOWN_KEYCHAR},
    {111,	XK_F12,		NSF12FunctionKey},
    {113,	XK_F15,		NSF15FunctionKey},
    {114,	XK_Help,	NSHelpFunctionKey},
    {115,	XK_Home,	NSHomeFunctionKey},     /* Fn Left */
    {116,	XK_Page_Up,	NSPageUpFunctionKey},   /* Fn Up */
    {117,	XK_Delete,	NSDeleteFunctionKey},   /* Fn Delete */
    {118,	XK_F4,		NSF4FunctionKey},
    {119,	XK_End,		NSEndFunctionKey},      /* Fn Right */
    {120,	XK_F2,		NSF2FunctionKey},
    {121,	XK_Page_Down,	NSPageDownFunctionKey}, /* Fn Down */
    {122,	XK_F1,		NSF1FunctionKey},
    {123,	XK_Left,	NSLeftArrowFunctionKey},
    {124,	XK_Right,	NSRightArrowFunctionKey},
    {125,	XK_Down,	NSDownArrowFunctionKey},
    {126,	XK_Up,		NSUpArrowFunctionKey},
    {0, 0, 0}
};

/*
 * X11 keysyms for modifier keys, in order.  This list includes keys
 * which do not appear on Apple keyboards, such as Shift_Lock and
 * Super_R.  While most systems don't provide events for the "fn"
 * function key, Apple does.  We map it to Super_L when processing a
 * FlagsChanged NSEvent.
 */

#define NUM_MOD_KEYCODES 14
static const KeyCode modKeyArray[NUM_MOD_KEYCODES] = {
    XK_Shift_L,
    XK_Shift_R,
    XK_Control_L,
    XK_Control_R,
    XK_Caps_Lock,
    XK_Shift_Lock,
    XK_Meta_L,
    XK_Meta_R,
    XK_Alt_L,
    XK_Alt_R,
    XK_Super_L,
    XK_Super_R,
    XK_Hyper_L,
    XK_Hyper_R,
};

/*
 * This table pairs X11 Keysyms for alphanumeric characters with the
 * unicode code point for that letter.
 * The data comes from http://www.cl.cam.ac.uk/~mgk25/ucs/keysyms.txt
 */

typedef struct KeysymInfo {
    KeySym keysym;
    KeyCode keycode;
} KeysymInfo;

const KeysymInfo keysymTable[] = {
    {0x0020, 0x0020}, /* space */
    {0x0021, 0x0021}, /* exclam */
    {0x0022, 0x0022}, /* quotedbl */
    {0x0023, 0x0023}, /* numbersign */
    {0x0024, 0x0024}, /* dollar */
    {0x0025, 0x0025}, /* percent */
    {0x0026, 0x0026}, /* ampersand */
    {0x0027, 0x0027}, /* apostrophe */
    {0x0028, 0x0028}, /* parenleft */
    {0x0029, 0x0029}, /* parenright */
    {0x002a, 0x002a}, /* asterisk */
    {0x002b, 0x002b}, /* plus */
    {0x002c, 0x002c}, /* comma */
    {0x002d, 0x002d}, /* minus */
    {0x002e, 0x002e}, /* period */
    {0x002f, 0x002f}, /* slash */
    {0x0030, 0x0030}, /* 0 */
    {0x0031, 0x0031}, /* 1 */
    {0x0032, 0x0032}, /* 2 */
    {0x0033, 0x0033}, /* 3 */
    {0x0034, 0x0034}, /* 4 */
    {0x0035, 0x0035}, /* 5 */
    {0x0036, 0x0036}, /* 6 */
    {0x0037, 0x0037}, /* 7 */
    {0x0038, 0x0038}, /* 8 */
    {0x0039, 0x0039}, /* 9 */
    {0x003a, 0x003a}, /* colon */
    {0x003b, 0x003b}, /* semicolon */
    {0x003c, 0x003c}, /* less */
    {0x003d, 0x003d}, /* equal */
    {0x003e, 0x003e}, /* greater */
    {0x003f, 0x003f}, /* question */
    {0x0040, 0x0040}, /* at */
    {0x0041, 0x0041}, /* A */
    {0x0042, 0x0042}, /* B */
    {0x0043, 0x0043}, /* C */
    {0x0044, 0x0044}, /* D */
    {0x0045, 0x0045}, /* E */
    {0x0046, 0x0046}, /* F */
    {0x0047, 0x0047}, /* G */
    {0x0048, 0x0048}, /* H */
    {0x0049, 0x0049}, /* I */
    {0x004a, 0x004a}, /* J */
    {0x004b, 0x004b}, /* K */
    {0x004c, 0x004c}, /* L */
    {0x004d, 0x004d}, /* M */
    {0x004e, 0x004e}, /* N */
    {0x004f, 0x004f}, /* O */
    {0x0050, 0x0050}, /* P */
    {0x0051, 0x0051}, /* Q */
    {0x0052, 0x0052}, /* R */
    {0x0053, 0x0053}, /* S */
    {0x0054, 0x0054}, /* T */
    {0x0055, 0x0055}, /* U */
    {0x0056, 0x0056}, /* V */
    {0x0057, 0x0057}, /* W */
    {0x0058, 0x0058}, /* X */
    {0x0059, 0x0059}, /* Y */
    {0x005a, 0x005a}, /* Z */
    {0x005b, 0x005b}, /* bracketleft */
    {0x005c, 0x005c}, /* backslash */
    {0x005d, 0x005d}, /* bracketright */
    {0x005e, 0x005e}, /* asciicircum */
    {0x005f, 0x005f}, /* underscore */
    {0x0060, 0x0060}, /* grave */
    {0x0061, 0x0061}, /* a */
    {0x0062, 0x0062}, /* b */
    {0x0063, 0x0063}, /* c */
    {0x0064, 0x0064}, /* d */
    {0x0065, 0x0065}, /* e */
    {0x0066, 0x0066}, /* f */
    {0x0067, 0x0067}, /* g */
    {0x0068, 0x0068}, /* h */
    {0x0069, 0x0069}, /* i */
    {0x006a, 0x006a}, /* j */
    {0x006b, 0x006b}, /* k */
    {0x006c, 0x006c}, /* l */
    {0x006d, 0x006d}, /* m */
    {0x006e, 0x006e}, /* n */
    {0x006f, 0x006f}, /* o */
    {0x0070, 0x0070}, /* p */
    {0x0071, 0x0071}, /* q */
    {0x0072, 0x0072}, /* r */
    {0x0073, 0x0073}, /* s */
    {0x0074, 0x0074}, /* t */
    {0x0075, 0x0075}, /* u */
    {0x0076, 0x0076}, /* v */
    {0x0077, 0x0077}, /* w */
    {0x0078, 0x0078}, /* x */
    {0x0079, 0x0079}, /* y */
    {0x007a, 0x007a}, /* z */
    {0x007b, 0x007b}, /* braceleft */
    {0x007c, 0x007c}, /* bar */
    {0x007d, 0x007d}, /* braceright */
    {0x007e, 0x007e}, /* asciitilde */
    {0x00a0, 0x00a0}, /* nobreakspace */
    {0x00a1, 0x00a1}, /* exclamdown */
    {0x00a2, 0x00a2}, /* cent */
    {0x00a3, 0x00a3}, /* sterling */
    {0x00a4, 0x00a4}, /* currency */
    {0x00a5, 0x00a5}, /* yen */
    {0x00a6, 0x00a6}, /* brokenbar */
    {0x00a7, 0x00a7}, /* section */
    {0x00a8, 0x00a8}, /* diaeresis */
    {0x00a9, 0x00a9}, /* copyright */
    {0x00aa, 0x00aa}, /* ordfeminine */
    {0x00ab, 0x00ab}, /* guillemotleft */
    {0x00ac, 0x00ac}, /* notsign */
    {0x00ad, 0x00ad}, /* hyphen */
    {0x00ae, 0x00ae}, /* registered */
    {0x00af, 0x00af}, /* macron */
    {0x00b0, 0x00b0}, /* degree */
    {0x00b1, 0x00b1}, /* plusminus */
    {0x00b2, 0x00b2}, /* twosuperior */
    {0x00b3, 0x00b3}, /* threesuperior */
    {0x00b4, 0x00b4}, /* acute */
    {0x00b5, 0x00b5}, /* mu */
    {0x00b6, 0x00b6}, /* paragraph */
    {0x00b7, 0x00b7}, /* periodcentered */
    {0x00b8, 0x00b8}, /* cedilla */
    {0x00b9, 0x00b9}, /* onesuperior */
    {0x00ba, 0x00ba}, /* masculine */
    {0x00bb, 0x00bb}, /* guillemotright */
    {0x00bc, 0x00bc}, /* onequarter */
    {0x00bd, 0x00bd}, /* onehalf */
    {0x00be, 0x00be}, /* threequarters */
    {0x00bf, 0x00bf}, /* questiondown */
    {0x00c0, 0x00c0}, /* Agrave */
    {0x00c1, 0x00c1}, /* Aacute */
    {0x00c2, 0x00c2}, /* Acircumflex */
    {0x00c3, 0x00c3}, /* Atilde */
    {0x00c4, 0x00c4}, /* Adiaeresis */
    {0x00c5, 0x00c5}, /* Aring */
    {0x00c6, 0x00c6}, /* AE */
    {0x00c7, 0x00c7}, /* Ccedilla */
    {0x00c8, 0x00c8}, /* Egrave */
    {0x00c9, 0x00c9}, /* Eacute */
    {0x00ca, 0x00ca}, /* Ecircumflex */
    {0x00cb, 0x00cb}, /* Ediaeresis */
    {0x00cc, 0x00cc}, /* Igrave */
    {0x00cd, 0x00cd}, /* Iacute */
    {0x00ce, 0x00ce}, /* Icircumflex */
    {0x00cf, 0x00cf}, /* Idiaeresis */
    {0x00d0, 0x00d0}, /* ETH */
    {0x00d1, 0x00d1}, /* Ntilde */
    {0x00d2, 0x00d2}, /* Ograve */
    {0x00d3, 0x00d3}, /* Oacute */
    {0x00d4, 0x00d4}, /* Ocircumflex */
    {0x00d5, 0x00d5}, /* Otilde */
    {0x00d6, 0x00d6}, /* Odiaeresis */
    {0x00d7, 0x00d7}, /* multiply */
    {0x00d8, 0x00d8}, /* Oslash */
    {0x00d9, 0x00d9}, /* Ugrave */
    {0x00da, 0x00da}, /* Uacute */
    {0x00db, 0x00db}, /* Ucircumflex */
    {0x00dc, 0x00dc}, /* Udiaeresis */
    {0x00dd, 0x00dd}, /* Yacute */
    {0x00de, 0x00de}, /* THORN */
    {0x00df, 0x00df}, /* ssharp */
    {0x00e0, 0x00e0}, /* agrave */
    {0x00e1, 0x00e1}, /* aacute */
    {0x00e2, 0x00e2}, /* acircumflex */
    {0x00e3, 0x00e3}, /* atilde */
    {0x00e4, 0x00e4}, /* adiaeresis */
    {0x00e5, 0x00e5}, /* aring */
    {0x00e6, 0x00e6}, /* ae */
    {0x00e7, 0x00e7}, /* ccedilla */
    {0x00e8, 0x00e8}, /* egrave */
    {0x00e9, 0x00e9}, /* eacute */
    {0x00ea, 0x00ea}, /* ecircumflex */
    {0x00eb, 0x00eb}, /* ediaeresis */
    {0x00ec, 0x00ec}, /* igrave */
    {0x00ed, 0x00ed}, /* iacute */
    {0x00ee, 0x00ee}, /* icircumflex */
    {0x00ef, 0x00ef}, /* idiaeresis */
    {0x00f0, 0x00f0}, /* eth */
    {0x00f1, 0x00f1}, /* ntilde */
    {0x00f2, 0x00f2}, /* ograve */
    {0x00f3, 0x00f3}, /* oacute */
    {0x00f4, 0x00f4}, /* ocircumflex */
    {0x00f5, 0x00f5}, /* otilde */
    {0x00f6, 0x00f6}, /* odiaeresis */
    {0x00f7, 0x00f7}, /* division */
    {0x00f8, 0x00f8}, /* oslash */
    {0x00f9, 0x00f9}, /* ugrave */
    {0x00fa, 0x00fa}, /* uacute */
    {0x00fb, 0x00fb}, /* ucircumflex */
    {0x00fc, 0x00fc}, /* udiaeresis */
    {0x00fd, 0x00fd}, /* yacute */
    {0x00fe, 0x00fe}, /* thorn */
    {0x00ff, 0x00ff}, /* ydiaeresis */
    {0x01a1, 0x0104}, /* Aogonek */
    {0x01a2, 0x02d8}, /* breve */
    {0x01a3, 0x0141}, /* Lstroke */
    {0x01a5, 0x013d}, /* Lcaron */
    {0x01a6, 0x015a}, /* Sacute */
    {0x01a9, 0x0160}, /* Scaron */
    {0x01aa, 0x015e}, /* Scedilla */
    {0x01ab, 0x0164}, /* Tcaron */
    {0x01ac, 0x0179}, /* Zacute */
    {0x01ae, 0x017d}, /* Zcaron */
    {0x01af, 0x017b}, /* Zabovedot */
    {0x01b1, 0x0105}, /* aogonek */
    {0x01b2, 0x02db}, /* ogonek */
    {0x01b3, 0x0142}, /* lstroke */
    {0x01b5, 0x013e}, /* lcaron */
    {0x01b6, 0x015b}, /* sacute */
    {0x01b7, 0x02c7}, /* caron */
    {0x01b9, 0x0161}, /* scaron */
    {0x01ba, 0x015f}, /* scedilla */
    {0x01bb, 0x0165}, /* tcaron */
    {0x01bc, 0x017a}, /* zacute */
    {0x01bd, 0x02dd}, /* doubleacute */
    {0x01be, 0x017e}, /* zcaron */
    {0x01bf, 0x017c}, /* zabovedot */
    {0x01c0, 0x0154}, /* Racute */
    {0x01c3, 0x0102}, /* Abreve */
    {0x01c5, 0x0139}, /* Lacute */
    {0x01c6, 0x0106}, /* Cacute */
    {0x01c8, 0x010c}, /* Ccaron */
    {0x01ca, 0x0118}, /* Eogonek */
    {0x01cc, 0x011a}, /* Ecaron */
    {0x01cf, 0x010e}, /* Dcaron */
    {0x01d0, 0x0110}, /* Dstroke */
    {0x01d1, 0x0143}, /* Nacute */
    {0x01d2, 0x0147}, /* Ncaron */
    {0x01d5, 0x0150}, /* Odoubleacute */
    {0x01d8, 0x0158}, /* Rcaron */
    {0x01d9, 0x016e}, /* Uring */
    {0x01db, 0x0170}, /* Udoubleacute */
    {0x01de, 0x0162}, /* Tcedilla */
    {0x01e0, 0x0155}, /* racute */
    {0x01e3, 0x0103}, /* abreve */
    {0x01e5, 0x013a}, /* lacute */
    {0x01e6, 0x0107}, /* cacute */
    {0x01e8, 0x010d}, /* ccaron */
    {0x01ea, 0x0119}, /* eogonek */
    {0x01ec, 0x011b}, /* ecaron */
    {0x01ef, 0x010f}, /* dcaron */
    {0x01f0, 0x0111}, /* dstroke */
    {0x01f1, 0x0144}, /* nacute */
    {0x01f2, 0x0148}, /* ncaron */
    {0x01f5, 0x0151}, /* odoubleacute */
    {0x01f8, 0x0159}, /* rcaron */
    {0x01f9, 0x016f}, /* uring */
    {0x01fb, 0x0171}, /* udoubleacute */
    {0x01fe, 0x0163}, /* tcedilla */
    {0x01ff, 0x02d9}, /* abovedot */
    {0x02a1, 0x0126}, /* Hstroke */
    {0x02a6, 0x0124}, /* Hcircumflex */
    {0x02a9, 0x0130}, /* Iabovedot */
    {0x02ab, 0x011e}, /* Gbreve */
    {0x02ac, 0x0134}, /* Jcircumflex */
    {0x02b1, 0x0127}, /* hstroke */
    {0x02b6, 0x0125}, /* hcircumflex */
    {0x02b9, 0x0131}, /* idotless */
    {0x02bb, 0x011f}, /* gbreve */
    {0x02bc, 0x0135}, /* jcircumflex */
    {0x02c5, 0x010a}, /* Cabovedot */
    {0x02c6, 0x0108}, /* Ccircumflex */
    {0x02d5, 0x0120}, /* Gabovedot */
    {0x02d8, 0x011c}, /* Gcircumflex */
    {0x02dd, 0x016c}, /* Ubreve */
    {0x02de, 0x015c}, /* Scircumflex */
    {0x02e5, 0x010b}, /* cabovedot */
    {0x02e6, 0x0109}, /* ccircumflex */
    {0x02f5, 0x0121}, /* gabovedot */
    {0x02f8, 0x011d}, /* gcircumflex */
    {0x02fd, 0x016d}, /* ubreve */
    {0x02fe, 0x015d}, /* scircumflex */
    {0x03a2, 0x0138}, /* kra */
    {0x03a3, 0x0156}, /* Rcedilla */
    {0x03a5, 0x0128}, /* Itilde */
    {0x03a6, 0x013b}, /* Lcedilla */
    {0x03aa, 0x0112}, /* Emacron */
    {0x03ab, 0x0122}, /* Gcedilla */
    {0x03ac, 0x0166}, /* Tslash */
    {0x03b3, 0x0157}, /* rcedilla */
    {0x03b5, 0x0129}, /* itilde */
    {0x03b6, 0x013c}, /* lcedilla */
    {0x03ba, 0x0113}, /* emacron */
    {0x03bb, 0x0123}, /* gcedilla */
    {0x03bc, 0x0167}, /* tslash */
    {0x03bd, 0x014a}, /* ENG */
    {0x03bf, 0x014b}, /* eng */
    {0x03c0, 0x0100}, /* Amacron */
    {0x03c7, 0x012e}, /* Iogonek */
    {0x03cc, 0x0116}, /* Eabovedot */
    {0x03cf, 0x012a}, /* Imacron */
    {0x03d1, 0x0145}, /* Ncedilla */
    {0x03d2, 0x014c}, /* Omacron */
    {0x03d3, 0x0136}, /* Kcedilla */
    {0x03d9, 0x0172}, /* Uogonek */
    {0x03dd, 0x0168}, /* Utilde */
    {0x03de, 0x016a}, /* Umacron */
    {0x03e0, 0x0101}, /* amacron */
    {0x03e7, 0x012f}, /* iogonek */
    {0x03ec, 0x0117}, /* eabovedot */
    {0x03ef, 0x012b}, /* imacron */
    {0x03f1, 0x0146}, /* ncedilla */
    {0x03f2, 0x014d}, /* omacron */
    {0x03f3, 0x0137}, /* kcedilla */
    {0x03f9, 0x0173}, /* uogonek */
    {0x03fd, 0x0169}, /* utilde */
    {0x03fe, 0x016b}, /* umacron */
    {0x047e, 0x203e}, /* overline */
    {0x04a1, 0x3002}, /* kana_fullstop */
    {0x04a2, 0x300c}, /* kana_openingbracket */
    {0x04a3, 0x300d}, /* kana_closingbracket */
    {0x04a4, 0x3001}, /* kana_comma */
    {0x04a5, 0x30fb}, /* kana_conjunctive */
    {0x04a6, 0x30f2}, /* kana_WO */
    {0x04a7, 0x30a1}, /* kana_a */
    {0x04a8, 0x30a3}, /* kana_i */
    {0x04a9, 0x30a5}, /* kana_u */
    {0x04aa, 0x30a7}, /* kana_e */
    {0x04ab, 0x30a9}, /* kana_o */
    {0x04ac, 0x30e3}, /* kana_ya */
    {0x04ad, 0x30e5}, /* kana_yu */
    {0x04ae, 0x30e7}, /* kana_yo */
    {0x04af, 0x30c3}, /* kana_tsu */
    {0x04b0, 0x30fc}, /* prolongedsound */
    {0x04b1, 0x30a2}, /* kana_A */
    {0x04b2, 0x30a4}, /* kana_I */
    {0x04b3, 0x30a6}, /* kana_U */
    {0x04b4, 0x30a8}, /* kana_E */
    {0x04b5, 0x30aa}, /* kana_O */
    {0x04b6, 0x30ab}, /* kana_KA */
    {0x04b7, 0x30ad}, /* kana_KI */
    {0x04b8, 0x30af}, /* kana_KU */
    {0x04b9, 0x30b1}, /* kana_KE */
    {0x04ba, 0x30b3}, /* kana_KO */
    {0x04bb, 0x30b5}, /* kana_SA */
    {0x04bc, 0x30b7}, /* kana_SHI */
    {0x04bd, 0x30b9}, /* kana_SU */
    {0x04be, 0x30bb}, /* kana_SE */
    {0x04bf, 0x30bd}, /* kana_SO */
    {0x04c0, 0x30bf}, /* kana_TA */
    {0x04c1, 0x30c1}, /* kana_CHI */
    {0x04c2, 0x30c4}, /* kana_TSU */
    {0x04c3, 0x30c6}, /* kana_TE */
    {0x04c4, 0x30c8}, /* kana_TO */
    {0x04c5, 0x30ca}, /* kana_NA */
    {0x04c6, 0x30cb}, /* kana_NI */
    {0x04c7, 0x30cc}, /* kana_NU */
    {0x04c8, 0x30cd}, /* kana_NE */
    {0x04c9, 0x30ce}, /* kana_NO */
    {0x04ca, 0x30cf}, /* kana_HA */
    {0x04cb, 0x30d2}, /* kana_HI */
    {0x04cc, 0x30d5}, /* kana_FU */
    {0x04cd, 0x30d8}, /* kana_HE */
    {0x04ce, 0x30db}, /* kana_HO */
    {0x04cf, 0x30de}, /* kana_MA */
    {0x04d0, 0x30df}, /* kana_MI */
    {0x04d1, 0x30e0}, /* kana_MU */
    {0x04d2, 0x30e1}, /* kana_ME */
    {0x04d3, 0x30e2}, /* kana_MO */
    {0x04d4, 0x30e4}, /* kana_YA */
    {0x04d5, 0x30e6}, /* kana_YU */
    {0x04d6, 0x30e8}, /* kana_YO */
    {0x04d7, 0x30e9}, /* kana_RA */
    {0x04d8, 0x30ea}, /* kana_RI */
    {0x04d9, 0x30eb}, /* kana_RU */
    {0x04da, 0x30ec}, /* kana_RE */
    {0x04db, 0x30ed}, /* kana_RO */
    {0x04dc, 0x30ef}, /* kana_WA */
    {0x04dd, 0x30f3}, /* kana_N */
    {0x04de, 0x309b}, /* voicedsound */
    {0x04df, 0x309c}, /* semivoicedsound */
    {0x05ac, 0x060c}, /* Arabic_comma */
    {0x05bb, 0x061b}, /* Arabic_semicolon */
    {0x05bf, 0x061f}, /* Arabic_question_mark */
    {0x05c1, 0x0621}, /* Arabic_hamza */
    {0x05c2, 0x0622}, /* Arabic_maddaonalef */
    {0x05c3, 0x0623}, /* Arabic_hamzaonalef */
    {0x05c4, 0x0624}, /* Arabic_hamzaonwaw */
    {0x05c5, 0x0625}, /* Arabic_hamzaunderalef */
    {0x05c6, 0x0626}, /* Arabic_hamzaonyeh */
    {0x05c7, 0x0627}, /* Arabic_alef */
    {0x05c8, 0x0628}, /* Arabic_beh */
    {0x05c9, 0x0629}, /* Arabic_tehmarbuta */
    {0x05ca, 0x062a}, /* Arabic_teh */
    {0x05cb, 0x062b}, /* Arabic_theh */
    {0x05cc, 0x062c}, /* Arabic_jeem */
    {0x05cd, 0x062d}, /* Arabic_hah */
    {0x05ce, 0x062e}, /* Arabic_khah */
    {0x05cf, 0x062f}, /* Arabic_dal */
    {0x05d0, 0x0630}, /* Arabic_thal */
    {0x05d1, 0x0631}, /* Arabic_ra */
    {0x05d2, 0x0632}, /* Arabic_zain */
    {0x05d3, 0x0633}, /* Arabic_seen */
    {0x05d4, 0x0634}, /* Arabic_sheen */
    {0x05d5, 0x0635}, /* Arabic_sad */
    {0x05d6, 0x0636}, /* Arabic_dad */
    {0x05d7, 0x0637}, /* Arabic_tah */
    {0x05d8, 0x0638}, /* Arabic_zah */
    {0x05d9, 0x0639}, /* Arabic_ain */
    {0x05da, 0x063a}, /* Arabic_ghain */
    {0x05e0, 0x0640}, /* Arabic_tatweel */
    {0x05e1, 0x0641}, /* Arabic_feh */
    {0x05e2, 0x0642}, /* Arabic_qaf */
    {0x05e3, 0x0643}, /* Arabic_kaf */
    {0x05e4, 0x0644}, /* Arabic_lam */
    {0x05e5, 0x0645}, /* Arabic_meem */
    {0x05e6, 0x0646}, /* Arabic_noon */
    {0x05e7, 0x0647}, /* Arabic_ha */
    {0x05e8, 0x0648}, /* Arabic_waw */
    {0x05e9, 0x0649}, /* Arabic_alefmaksura */
    {0x05ea, 0x064a}, /* Arabic_yeh */
    {0x05eb, 0x064b}, /* Arabic_fathatan */
    {0x05ec, 0x064c}, /* Arabic_dammatan */
    {0x05ed, 0x064d}, /* Arabic_kasratan */
    {0x05ee, 0x064e}, /* Arabic_fatha */
    {0x05ef, 0x064f}, /* Arabic_damma */
    {0x05f0, 0x0650}, /* Arabic_kasra */
    {0x05f1, 0x0651}, /* Arabic_shadda */
    {0x05f2, 0x0652}, /* Arabic_sukun */
    {0x06a1, 0x0452}, /* Serbian_dje */
    {0x06a2, 0x0453}, /* Macedonia_gje */
    {0x06a3, 0x0451}, /* Cyrillic_io */
    {0x06a4, 0x0454}, /* Ukrainian_ie */
    {0x06a5, 0x0455}, /* Macedonia_dse */
    {0x06a6, 0x0456}, /* Ukrainian_i */
    {0x06a7, 0x0457}, /* Ukrainian_yi */
    {0x06a8, 0x0458}, /* Cyrillic_je */
    {0x06a9, 0x0459}, /* Cyrillic_lje */
    {0x06aa, 0x045a}, /* Cyrillic_nje */
    {0x06ab, 0x045b}, /* Serbian_tshe */
    {0x06ac, 0x045c}, /* Macedonia_kje */
    {0x06ae, 0x045e}, /* Byelorussian_shortu */
    {0x06af, 0x045f}, /* Cyrillic_dzhe */
    {0x06b0, 0x2116}, /* numerosign */
    {0x06b1, 0x0402}, /* Serbian_DJE */
    {0x06b2, 0x0403}, /* Macedonia_GJE */
    {0x06b3, 0x0401}, /* Cyrillic_IO */
    {0x06b4, 0x0404}, /* Ukrainian_IE */
    {0x06b5, 0x0405}, /* Macedonia_DSE */
    {0x06b6, 0x0406}, /* Ukrainian_I */
    {0x06b7, 0x0407}, /* Ukrainian_YI */
    {0x06b8, 0x0408}, /* Cyrillic_JE */
    {0x06b9, 0x0409}, /* Cyrillic_LJE */
    {0x06ba, 0x040a}, /* Cyrillic_NJE */
    {0x06bb, 0x040b}, /* Serbian_TSHE */
    {0x06bc, 0x040c}, /* Macedonia_KJE */
    {0x06be, 0x040e}, /* Byelorussian_SHORTU */
    {0x06bf, 0x040f}, /* Cyrillic_DZHE */
    {0x06c0, 0x044e}, /* Cyrillic_yu */
    {0x06c1, 0x0430}, /* Cyrillic_a */
    {0x06c2, 0x0431}, /* Cyrillic_be */
    {0x06c3, 0x0446}, /* Cyrillic_tse */
    {0x06c4, 0x0434}, /* Cyrillic_de */
    {0x06c5, 0x0435}, /* Cyrillic_ie */
    {0x06c6, 0x0444}, /* Cyrillic_ef */
    {0x06c7, 0x0433}, /* Cyrillic_ghe */
    {0x06c8, 0x0445}, /* Cyrillic_ha */
    {0x06c9, 0x0438}, /* Cyrillic_i */
    {0x06ca, 0x0439}, /* Cyrillic_shorti */
    {0x06cb, 0x043a}, /* Cyrillic_ka */
    {0x06cc, 0x043b}, /* Cyrillic_el */
    {0x06cd, 0x043c}, /* Cyrillic_em */
    {0x06ce, 0x043d}, /* Cyrillic_en */
    {0x06cf, 0x043e}, /* Cyrillic_o */
    {0x06d0, 0x043f}, /* Cyrillic_pe */
    {0x06d1, 0x044f}, /* Cyrillic_ya */
    {0x06d2, 0x0440}, /* Cyrillic_er */
    {0x06d3, 0x0441}, /* Cyrillic_es */
    {0x06d4, 0x0442}, /* Cyrillic_te */
    {0x06d5, 0x0443}, /* Cyrillic_u */
    {0x06d6, 0x0436}, /* Cyrillic_zhe */
    {0x06d7, 0x0432}, /* Cyrillic_ve */
    {0x06d8, 0x044c}, /* Cyrillic_softsign */
    {0x06d9, 0x044b}, /* Cyrillic_yeru */
    {0x06da, 0x0437}, /* Cyrillic_ze */
    {0x06db, 0x0448}, /* Cyrillic_sha */
    {0x06dc, 0x044d}, /* Cyrillic_e */
    {0x06dd, 0x0449}, /* Cyrillic_shcha */
    {0x06de, 0x0447}, /* Cyrillic_che */
    {0x06df, 0x044a}, /* Cyrillic_hardsign */
    {0x06e0, 0x042e}, /* Cyrillic_YU */
    {0x06e1, 0x0410}, /* Cyrillic_A */
    {0x06e2, 0x0411}, /* Cyrillic_BE */
    {0x06e3, 0x0426}, /* Cyrillic_TSE */
    {0x06e4, 0x0414}, /* Cyrillic_DE */
    {0x06e5, 0x0415}, /* Cyrillic_IE */
    {0x06e6, 0x0424}, /* Cyrillic_EF */
    {0x06e7, 0x0413}, /* Cyrillic_GHE */
    {0x06e8, 0x0425}, /* Cyrillic_HA */
    {0x06e9, 0x0418}, /* Cyrillic_I */
    {0x06ea, 0x0419}, /* Cyrillic_SHORTI */
    {0x06eb, 0x041a}, /* Cyrillic_KA */
    {0x06ec, 0x041b}, /* Cyrillic_EL */
    {0x06ed, 0x041c}, /* Cyrillic_EM */
    {0x06ee, 0x041d}, /* Cyrillic_EN */
    {0x06ef, 0x041e}, /* Cyrillic_O */
    {0x06f0, 0x041f}, /* Cyrillic_PE */
    {0x06f1, 0x042f}, /* Cyrillic_YA */
    {0x06f2, 0x0420}, /* Cyrillic_ER */
    {0x06f3, 0x0421}, /* Cyrillic_ES */
    {0x06f4, 0x0422}, /* Cyrillic_TE */
    {0x06f5, 0x0423}, /* Cyrillic_U */
    {0x06f6, 0x0416}, /* Cyrillic_ZHE */
    {0x06f7, 0x0412}, /* Cyrillic_VE */
    {0x06f8, 0x042c}, /* Cyrillic_SOFTSIGN */
    {0x06f9, 0x042b}, /* Cyrillic_YERU */
    {0x06fa, 0x0417}, /* Cyrillic_ZE */
    {0x06fb, 0x0428}, /* Cyrillic_SHA */
    {0x06fc, 0x042d}, /* Cyrillic_E */
    {0x06fd, 0x0429}, /* Cyrillic_SHCHA */
    {0x06fe, 0x0427}, /* Cyrillic_CHE */
    {0x06ff, 0x042a}, /* Cyrillic_HARDSIGN */
    {0x07a1, 0x0386}, /* Greek_ALPHAaccent */
    {0x07a2, 0x0388}, /* Greek_EPSILONaccent */
    {0x07a3, 0x0389}, /* Greek_ETAaccent */
    {0x07a4, 0x038a}, /* Greek_IOTAaccent */
    {0x07a5, 0x03aa}, /* Greek_IOTAdiaeresis */
    {0x07a7, 0x038c}, /* Greek_OMICRONaccent */
    {0x07a8, 0x038e}, /* Greek_UPSILONaccent */
    {0x07a9, 0x03ab}, /* Greek_UPSILONdieresis */
    {0x07ab, 0x038f}, /* Greek_OMEGAaccent */
    {0x07ae, 0x0385}, /* Greek_accentdieresis */
    {0x07af, 0x2015}, /* Greek_horizbar */
    {0x07b1, 0x03ac}, /* Greek_alphaaccent */
    {0x07b2, 0x03ad}, /* Greek_epsilonaccent */
    {0x07b3, 0x03ae}, /* Greek_etaaccent */
    {0x07b4, 0x03af}, /* Greek_iotaaccent */
    {0x07b5, 0x03ca}, /* Greek_iotadieresis */
    {0x07b6, 0x0390}, /* Greek_iotaaccentdieresis */
    {0x07b7, 0x03cc}, /* Greek_omicronaccent */
    {0x07b8, 0x03cd}, /* Greek_upsilonaccent */
    {0x07b9, 0x03cb}, /* Greek_upsilondieresis */
    {0x07ba, 0x03b0}, /* Greek_upsilonaccentdieresis */
    {0x07bb, 0x03ce}, /* Greek_omegaaccent */
    {0x07c1, 0x0391}, /* Greek_ALPHA */
    {0x07c2, 0x0392}, /* Greek_BETA */
    {0x07c3, 0x0393}, /* Greek_GAMMA */
    {0x07c4, 0x0394}, /* Greek_DELTA */
    {0x07c5, 0x0395}, /* Greek_EPSILON */
    {0x07c6, 0x0396}, /* Greek_ZETA */
    {0x07c7, 0x0397}, /* Greek_ETA */
    {0x07c8, 0x0398}, /* Greek_THETA */
    {0x07c9, 0x0399}, /* Greek_IOTA */
    {0x07ca, 0x039a}, /* Greek_KAPPA */
    {0x07cb, 0x039b}, /* Greek_LAMDA */
    {0x07cc, 0x039c}, /* Greek_MU */
    {0x07cd, 0x039d}, /* Greek_NU */
    {0x07ce, 0x039e}, /* Greek_XI */
    {0x07cf, 0x039f}, /* Greek_OMICRON */
    {0x07d0, 0x03a0}, /* Greek_PI */
    {0x07d1, 0x03a1}, /* Greek_RHO */
    {0x07d2, 0x03a3}, /* Greek_SIGMA */
    {0x07d4, 0x03a4}, /* Greek_TAU */
    {0x07d5, 0x03a5}, /* Greek_UPSILON */
    {0x07d6, 0x03a6}, /* Greek_PHI */
    {0x07d7, 0x03a7}, /* Greek_CHI */
    {0x07d8, 0x03a8}, /* Greek_PSI */
    {0x07d9, 0x03a9}, /* Greek_OMEGA */
    {0x07e1, 0x03b1}, /* Greek_alpha */
    {0x07e2, 0x03b2}, /* Greek_beta */
    {0x07e3, 0x03b3}, /* Greek_gamma */
    {0x07e4, 0x03b4}, /* Greek_delta */
    {0x07e5, 0x03b5}, /* Greek_epsilon */
    {0x07e6, 0x03b6}, /* Greek_zeta */
    {0x07e7, 0x03b7}, /* Greek_eta */
    {0x07e8, 0x03b8}, /* Greek_theta */
    {0x07e9, 0x03b9}, /* Greek_iota */
    {0x07ea, 0x03ba}, /* Greek_kappa */
    {0x07eb, 0x03bb}, /* Greek_lambda */
    {0x07ec, 0x03bc}, /* Greek_mu */
    {0x07ed, 0x03bd}, /* Greek_nu */
    {0x07ee, 0x03be}, /* Greek_xi */
    {0x07ef, 0x03bf}, /* Greek_omicron */
    {0x07f0, 0x03c0}, /* Greek_pi */
    {0x07f1, 0x03c1}, /* Greek_rho */
    {0x07f2, 0x03c3}, /* Greek_sigma */
    {0x07f3, 0x03c2}, /* Greek_finalsmallsigma */
    {0x07f4, 0x03c4}, /* Greek_tau */
    {0x07f5, 0x03c5}, /* Greek_upsilon */
    {0x07f6, 0x03c6}, /* Greek_phi */
    {0x07f7, 0x03c7}, /* Greek_chi */
    {0x07f8, 0x03c8}, /* Greek_psi */
    {0x07f9, 0x03c9}, /* Greek_omega */
    {0x08a1, 0x23b7}, /* leftradical */
    {0x08a4, 0x2320}, /* topintegral */
    {0x08a5, 0x2321}, /* botintegral */
    {0x08a7, 0x23a1}, /* topleftsqbracket */
    {0x08a8, 0x23a3}, /* botleftsqbracket */
    {0x08a9, 0x23a4}, /* toprightsqbracket */
    {0x08aa, 0x23a6}, /* botrightsqbracket */
    {0x08ab, 0x239b}, /* topleftparens */
    {0x08ac, 0x239d}, /* botleftparens */
    {0x08ad, 0x239e}, /* toprightparens */
    {0x08ae, 0x23a0}, /* botrightparens */
    {0x08af, 0x23a8}, /* leftmiddlecurlybrace */
    {0x08b0, 0x23ac}, /* rightmiddlecurlybrace */
    {0x08bc, 0x2264}, /* lessthanequal */
    {0x08bd, 0x2260}, /* notequal */
    {0x08be, 0x2265}, /* greaterthanequal */
    {0x08bf, 0x222b}, /* integral */
    {0x08c0, 0x2234}, /* therefore */
    {0x08c1, 0x221d}, /* variation */
    {0x08c2, 0x221e}, /* infinity */
    {0x08c5, 0x2207}, /* nabla */
    {0x08c8, 0x223c}, /* approximate */
    {0x08c9, 0x2243}, /* similarequal */
    {0x08cd, 0x21d4}, /* ifonlyif */
    {0x08ce, 0x21d2}, /* implies */
    {0x08cf, 0x2261}, /* identical */
    {0x08d6, 0x221a}, /* radical */
    {0x08da, 0x2282}, /* includedin */
    {0x08db, 0x2283}, /* includes */
    {0x08dc, 0x2229}, /* intersection */
    {0x08dd, 0x222a}, /* union */
    {0x08de, 0x2227}, /* logicaland */
    {0x08df, 0x2228}, /* logicalor */
    {0x08ef, 0x2202}, /* partialderivative */
    {0x08f6, 0x0192}, /* function */
    {0x08fb, 0x2190}, /* leftarrow */
    {0x08fc, 0x2191}, /* uparrow */
    {0x08fd, 0x2192}, /* rightarrow */
    {0x08fe, 0x2193}, /* downarrow */
    {0x09e0, 0x25c6}, /* soliddiamond */
    {0x09e1, 0x2592}, /* checkerboard */
    {0x09e2, 0x2409}, /* ht */
    {0x09e3, 0x240c}, /* ff */
    {0x09e4, 0x240d}, /* cr */
    {0x09e5, 0x240a}, /* lf */
    {0x09e8, 0x2424}, /* nl */
    {0x09e9, 0x240b}, /* vt */
    {0x09ea, 0x2518}, /* lowrightcorner */
    {0x09eb, 0x2510}, /* uprightcorner */
    {0x09ec, 0x250c}, /* upleftcorner */
    {0x09ed, 0x2514}, /* lowleftcorner */
    {0x09ee, 0x253c}, /* crossinglines */
    {0x09ef, 0x23ba}, /* horizlinescan1 */
    {0x09f0, 0x23bb}, /* horizlinescan3 */
    {0x09f1, 0x2500}, /* horizlinescan5 */
    {0x09f2, 0x23bc}, /* horizlinescan7 */
    {0x09f3, 0x23bd}, /* horizlinescan9 */
    {0x09f4, 0x251c}, /* leftt */
    {0x09f5, 0x2524}, /* rightt */
    {0x09f6, 0x2534}, /* bott */
    {0x09f7, 0x252c}, /* topt */
    {0x09f8, 0x2502}, /* vertbar */
    {0x0aa1, 0x2003}, /* emspace */
    {0x0aa2, 0x2002}, /* enspace */
    {0x0aa3, 0x2004}, /* em3space */
    {0x0aa4, 0x2005}, /* em4space */
    {0x0aa5, 0x2007}, /* digitspace */
    {0x0aa6, 0x2008}, /* punctspace */
    {0x0aa7, 0x2009}, /* thinspace */
    {0x0aa8, 0x200a}, /* hairspace */
    {0x0aa9, 0x2014}, /* emdash */
    {0x0aaa, 0x2013}, /* endash */
    {0x0aae, 0x2026}, /* ellipsis */
    {0x0aaf, 0x2025}, /* doubbaselinedot */
    {0x0ab0, 0x2153}, /* onethird */
    {0x0ab1, 0x2154}, /* twothirds */
    {0x0ab2, 0x2155}, /* onefifth */
    {0x0ab3, 0x2156}, /* twofifths */
    {0x0ab4, 0x2157}, /* threefifths */
    {0x0ab5, 0x2158}, /* fourfifths */
    {0x0ab6, 0x2159}, /* onesixth */
    {0x0ab7, 0x215a}, /* fivesixths */
    {0x0ab8, 0x2105}, /* careof */
    {0x0abb, 0x2012}, /* figdash */
    {0x0ac3, 0x215b}, /* oneeighth */
    {0x0ac4, 0x215c}, /* threeeighths */
    {0x0ac5, 0x215d}, /* fiveeighths */
    {0x0ac6, 0x215e}, /* seveneighths */
    {0x0ac9, 0x2122}, /* trademark */
    {0x0ad0, 0x2018}, /* leftsinglequotemark */
    {0x0ad1, 0x2019}, /* rightsinglequotemark */
    {0x0ad2, 0x201c}, /* leftdoublequotemark */
    {0x0ad3, 0x201d}, /* rightdoublequotemark */
    {0x0ad4, 0x211e}, /* prescription */
    {0x0ad6, 0x2032}, /* minutes */
    {0x0ad7, 0x2033}, /* seconds */
    {0x0ad9, 0x271d}, /* latincross */
    {0x0aec, 0x2663}, /* club */
    {0x0aed, 0x2666}, /* diamond */
    {0x0aee, 0x2665}, /* heart */
    {0x0af0, 0x2720}, /* maltesecross */
    {0x0af1, 0x2020}, /* dagger */
    {0x0af2, 0x2021}, /* doubledagger */
    {0x0af3, 0x2713}, /* checkmark */
    {0x0af4, 0x2717}, /* ballotcross */
    {0x0af5, 0x266f}, /* musicalsharp */
    {0x0af6, 0x266d}, /* musicalflat */
    {0x0af7, 0x2642}, /* malesymbol */
    {0x0af8, 0x2640}, /* femalesymbol */
    {0x0af9, 0x260e}, /* telephone */
    {0x0afa, 0x2315}, /* telephonerecorder */
    {0x0afb, 0x2117}, /* phonographcopyright */
    {0x0afc, 0x2038}, /* caret */
    {0x0afd, 0x201a}, /* singlelowquotemark */
    {0x0afe, 0x201e}, /* doublelowquotemark */
    {0x0bc2, 0x22a5}, /* downtack */
    {0x0bc4, 0x230a}, /* downstile */
    {0x0bca, 0x2218}, /* jot */
    {0x0bcc, 0x2395}, /* quad */
    {0x0bce, 0x22a4}, /* uptack */
    {0x0bcf, 0x25cb}, /* circle */
    {0x0bd3, 0x2308}, /* upstile */
    {0x0bdc, 0x22a2}, /* lefttack */
    {0x0bfc, 0x22a3}, /* righttack */
    {0x0cdf, 0x2017}, /* hebrew_doublelowline */
    {0x0ce0, 0x05d0}, /* hebrew_aleph */
    {0x0ce1, 0x05d1}, /* hebrew_bet */
    {0x0ce2, 0x05d2}, /* hebrew_gimel */
    {0x0ce3, 0x05d3}, /* hebrew_dalet */
    {0x0ce4, 0x05d4}, /* hebrew_he */
    {0x0ce5, 0x05d5}, /* hebrew_waw */
    {0x0ce6, 0x05d6}, /* hebrew_zain */
    {0x0ce7, 0x05d7}, /* hebrew_chet */
    {0x0ce8, 0x05d8}, /* hebrew_tet */
    {0x0ce9, 0x05d9}, /* hebrew_yod */
    {0x0cea, 0x05da}, /* hebrew_finalkaph */
    {0x0ceb, 0x05db}, /* hebrew_kaph */
    {0x0cec, 0x05dc}, /* hebrew_lamed */
    {0x0ced, 0x05dd}, /* hebrew_finalmem */
    {0x0cee, 0x05de}, /* hebrew_mem */
    {0x0cef, 0x05df}, /* hebrew_finalnun */
    {0x0cf0, 0x05e0}, /* hebrew_nun */
    {0x0cf1, 0x05e1}, /* hebrew_samech */
    {0x0cf2, 0x05e2}, /* hebrew_ayin */
    {0x0cf3, 0x05e3}, /* hebrew_finalpe */
    {0x0cf4, 0x05e4}, /* hebrew_pe */
    {0x0cf5, 0x05e5}, /* hebrew_finalzade */
    {0x0cf6, 0x05e6}, /* hebrew_zade */
    {0x0cf7, 0x05e7}, /* hebrew_qoph */
    {0x0cf8, 0x05e8}, /* hebrew_resh */
    {0x0cf9, 0x05e9}, /* hebrew_shin */
    {0x0cfa, 0x05ea}, /* hebrew_taw */
    {0x0da1, 0x0e01}, /* Thai_kokai */
    {0x0da2, 0x0e02}, /* Thai_khokhai */
    {0x0da3, 0x0e03}, /* Thai_khokhuat */
    {0x0da4, 0x0e04}, /* Thai_khokhwai */
    {0x0da5, 0x0e05}, /* Thai_khokhon */
    {0x0da6, 0x0e06}, /* Thai_khorakhang */
    {0x0da7, 0x0e07}, /* Thai_ngongu */
    {0x0da8, 0x0e08}, /* Thai_chochan */
    {0x0da9, 0x0e09}, /* Thai_choching */
    {0x0daa, 0x0e0a}, /* Thai_chochang */
    {0x0dab, 0x0e0b}, /* Thai_soso */
    {0x0dac, 0x0e0c}, /* Thai_chochoe */
    {0x0dad, 0x0e0d}, /* Thai_yoying */
    {0x0dae, 0x0e0e}, /* Thai_dochada */
    {0x0daf, 0x0e0f}, /* Thai_topatak */
    {0x0db0, 0x0e10}, /* Thai_thothan */
    {0x0db1, 0x0e11}, /* Thai_thonangmontho */
    {0x0db2, 0x0e12}, /* Thai_thophuthao */
    {0x0db3, 0x0e13}, /* Thai_nonen */
    {0x0db4, 0x0e14}, /* Thai_dodek */
    {0x0db5, 0x0e15}, /* Thai_totao */
    {0x0db6, 0x0e16}, /* Thai_thothung */
    {0x0db7, 0x0e17}, /* Thai_thothahan */
    {0x0db8, 0x0e18}, /* Thai_thothong */
    {0x0db9, 0x0e19}, /* Thai_nonu */
    {0x0dba, 0x0e1a}, /* Thai_bobaimai */
    {0x0dbb, 0x0e1b}, /* Thai_popla */
    {0x0dbc, 0x0e1c}, /* Thai_phophung */
    {0x0dbd, 0x0e1d}, /* Thai_fofa */
    {0x0dbe, 0x0e1e}, /* Thai_phophan */
    {0x0dbf, 0x0e1f}, /* Thai_fofan */
    {0x0dc0, 0x0e20}, /* Thai_phosamphao */
    {0x0dc1, 0x0e21}, /* Thai_moma */
    {0x0dc2, 0x0e22}, /* Thai_yoyak */
    {0x0dc3, 0x0e23}, /* Thai_rorua */
    {0x0dc4, 0x0e24}, /* Thai_ru */
    {0x0dc5, 0x0e25}, /* Thai_loling */
    {0x0dc6, 0x0e26}, /* Thai_lu */
    {0x0dc7, 0x0e27}, /* Thai_wowaen */
    {0x0dc8, 0x0e28}, /* Thai_sosala */
    {0x0dc9, 0x0e29}, /* Thai_sorusi */
    {0x0dca, 0x0e2a}, /* Thai_sosua */
    {0x0dcb, 0x0e2b}, /* Thai_hohip */
    {0x0dcc, 0x0e2c}, /* Thai_lochula */
    {0x0dcd, 0x0e2d}, /* Thai_oang */
    {0x0dce, 0x0e2e}, /* Thai_honokhuk */
    {0x0dcf, 0x0e2f}, /* Thai_paiyannoi */
    {0x0dd0, 0x0e30}, /* Thai_saraa */
    {0x0dd1, 0x0e31}, /* Thai_maihanakat */
    {0x0dd2, 0x0e32}, /* Thai_saraaa */
    {0x0dd3, 0x0e33}, /* Thai_saraam */
    {0x0dd4, 0x0e34}, /* Thai_sarai */
    {0x0dd5, 0x0e35}, /* Thai_saraii */
    {0x0dd6, 0x0e36}, /* Thai_saraue */
    {0x0dd7, 0x0e37}, /* Thai_sarauee */
    {0x0dd8, 0x0e38}, /* Thai_sarau */
    {0x0dd9, 0x0e39}, /* Thai_sarauu */
    {0x0dda, 0x0e3a}, /* Thai_phinthu */
    {0x0ddf, 0x0e3f}, /* Thai_baht */
    {0x0de0, 0x0e40}, /* Thai_sarae */
    {0x0de1, 0x0e41}, /* Thai_saraae */
    {0x0de2, 0x0e42}, /* Thai_sarao */
    {0x0de3, 0x0e43}, /* Thai_saraaimaimuan */
    {0x0de4, 0x0e44}, /* Thai_saraaimaimalai */
    {0x0de5, 0x0e45}, /* Thai_lakkhangyao */
    {0x0de6, 0x0e46}, /* Thai_maiyamok */
    {0x0de7, 0x0e47}, /* Thai_maitaikhu */
    {0x0de8, 0x0e48}, /* Thai_maiek */
    {0x0de9, 0x0e49}, /* Thai_maitho */
    {0x0dea, 0x0e4a}, /* Thai_maitri */
    {0x0deb, 0x0e4b}, /* Thai_maichattawa */
    {0x0dec, 0x0e4c}, /* Thai_thanthakhat */
    {0x0ded, 0x0e4d}, /* Thai_nikhahit */
    {0x0df0, 0x0e50}, /* Thai_leksun */
    {0x0df1, 0x0e51}, /* Thai_leknung */
    {0x0df2, 0x0e52}, /* Thai_leksong */
    {0x0df3, 0x0e53}, /* Thai_leksam */
    {0x0df4, 0x0e54}, /* Thai_leksi */
    {0x0df5, 0x0e55}, /* Thai_lekha */
    {0x0df6, 0x0e56}, /* Thai_lekhok */
    {0x0df7, 0x0e57}, /* Thai_lekchet */
    {0x0df8, 0x0e58}, /* Thai_lekpaet */
    {0x0df9, 0x0e59}, /* Thai_lekkao */
    {0x13bc, 0x0152}, /* OE */
    {0x13bd, 0x0153}, /* oe */
    {0x13be, 0x0178}, /* Ydiaeresis */
    {0x20a0, 0x20a0}, /* EcuSign */
    {0x20a1, 0x20a1}, /* ColonSign */
    {0x20a2, 0x20a2}, /* CruzeiroSign */
    {0x20a3, 0x20a3}, /* FFrancSign */
    {0x20a4, 0x20a4}, /* LiraSign */
    {0x20a5, 0x20a5}, /* MillSign */
    {0x20a6, 0x20a6}, /* NairaSign */
    {0x20a7, 0x20a7}, /* PesetaSign */
    {0x20a8, 0x20a8}, /* RupeeSign */
    {0x20a9, 0x20a9}, /* WonSign */
    {0x20aa, 0x20aa}, /* NewSheqelSign */
    {0x20ab, 0x20ab}, /* DongSign */
    {0x20ac, 0x20ac}, /* EuroSign */
    {0x06ad, 0x0491}, /* Ukrainian_ghe_with_upturn */
    {0x06bd, 0x0490}, /* Ukrainian_GHE_WITH_UPTURN */
    {0x14a2, 0x0587}, /* Armenian_ligature_ew */
    {0x14a3, 0x0589}, /* Armenian_verjaket */
    {0x14aa, 0x055d}, /* Armenian_but */
    {0x14ad, 0x058a}, /* Armenian_yentamna */
    {0x14af, 0x055c}, /* Armenian_amanak */
    {0x14b0, 0x055b}, /* Armenian_shesht */
    {0x14b1, 0x055e}, /* Armenian_paruyk */
    {0x14b2, 0x0531}, /* Armenian_AYB */
    {0x14b3, 0x0561}, /* Armenian_ayb */
    {0x14b4, 0x0532}, /* Armenian_BEN */
    {0x14b5, 0x0562}, /* Armenian_ben */
    {0x14b6, 0x0533}, /* Armenian_GIM */
    {0x14b7, 0x0563}, /* Armenian_gim */
    {0x14b8, 0x0534}, /* Armenian_DA */
    {0x14b9, 0x0564}, /* Armenian_da */
    {0x14ba, 0x0535}, /* Armenian_YECH */
    {0x14bb, 0x0565}, /* Armenian_yech */
    {0x14bc, 0x0536}, /* Armenian_ZA */
    {0x14bd, 0x0566}, /* Armenian_za */
    {0x14be, 0x0537}, /* Armenian_E */
    {0x14bf, 0x0567}, /* Armenian_e */
    {0x14c0, 0x0538}, /* Armenian_AT */
    {0x14c1, 0x0568}, /* Armenian_at */
    {0x14c2, 0x0539}, /* Armenian_TO */
    {0x14c3, 0x0569}, /* Armenian_to */
    {0x14c4, 0x053a}, /* Armenian_ZHE */
    {0x14c5, 0x056a}, /* Armenian_zhe */
    {0x14c6, 0x053b}, /* Armenian_INI */
    {0x14c7, 0x056b}, /* Armenian_ini */
    {0x14c8, 0x053c}, /* Armenian_LYUN */
    {0x14c9, 0x056c}, /* Armenian_lyun */
    {0x14ca, 0x053d}, /* Armenian_KHE */
    {0x14cb, 0x056d}, /* Armenian_khe */
    {0x14cc, 0x053e}, /* Armenian_TSA */
    {0x14cd, 0x056e}, /* Armenian_tsa */
    {0x14ce, 0x053f}, /* Armenian_KEN */
    {0x14cf, 0x056f}, /* Armenian_ken */
    {0x14d0, 0x0540}, /* Armenian_HO */
    {0x14d1, 0x0570}, /* Armenian_ho */
    {0x14d2, 0x0541}, /* Armenian_DZA */
    {0x14d3, 0x0571}, /* Armenian_dza */
    {0x14d4, 0x0542}, /* Armenian_GHAT */
    {0x14d5, 0x0572}, /* Armenian_ghat */
    {0x14d6, 0x0543}, /* Armenian_TCHE */
    {0x14d7, 0x0573}, /* Armenian_tche */
    {0x14d8, 0x0544}, /* Armenian_MEN */
    {0x14d9, 0x0574}, /* Armenian_men */
    {0x14da, 0x0545}, /* Armenian_HI */
    {0x14db, 0x0575}, /* Armenian_hi */
    {0x14dc, 0x0546}, /* Armenian_NU */
    {0x14dd, 0x0576}, /* Armenian_nu */
    {0x14de, 0x0547}, /* Armenian_SHA */
    {0x14df, 0x0577}, /* Armenian_sha */
    {0x14e0, 0x0548}, /* Armenian_VO */
    {0x14e1, 0x0578}, /* Armenian_vo */
    {0x14e2, 0x0549}, /* Armenian_CHA */
    {0x14e3, 0x0579}, /* Armenian_cha */
    {0x14e4, 0x054a}, /* Armenian_PE */
    {0x14e5, 0x057a}, /* Armenian_pe */
    {0x14e6, 0x054b}, /* Armenian_JE */
    {0x14e7, 0x057b}, /* Armenian_je */
    {0x14e8, 0x054c}, /* Armenian_RA */
    {0x14e9, 0x057c}, /* Armenian_ra */
    {0x14ea, 0x054d}, /* Armenian_SE */
    {0x14eb, 0x057d}, /* Armenian_se */
    {0x14ec, 0x054e}, /* Armenian_VEV */
    {0x14ed, 0x057e}, /* Armenian_vev */
    {0x14ee, 0x054f}, /* Armenian_TYUN */
    {0x14ef, 0x057f}, /* Armenian_tyun */
    {0x14f0, 0x0550}, /* Armenian_RE */
    {0x14f1, 0x0580}, /* Armenian_re */
    {0x14f2, 0x0551}, /* Armenian_TSO */
    {0x14f3, 0x0581}, /* Armenian_tso */
    {0x14f4, 0x0552}, /* Armenian_VYUN */
    {0x14f5, 0x0582}, /* Armenian_vyun */
    {0x14f6, 0x0553}, /* Armenian_PYUR */
    {0x14f7, 0x0583}, /* Armenian_pyur */
    {0x14f8, 0x0554}, /* Armenian_KE */
    {0x14f9, 0x0584}, /* Armenian_ke */
    {0x14fa, 0x0555}, /* Armenian_O */
    {0x14fb, 0x0585}, /* Armenian_o */
    {0x14fc, 0x0556}, /* Armenian_FE */
    {0x14fd, 0x0586}, /* Armenian_fe */
    {0x14fe, 0x055a}, /* Armenian_apostrophe */
    {0x15d0, 0x10d0}, /* Georgian_an */
    {0x15d1, 0x10d1}, /* Georgian_ban */
    {0x15d2, 0x10d2}, /* Georgian_gan */
    {0x15d3, 0x10d3}, /* Georgian_don */
    {0x15d4, 0x10d4}, /* Georgian_en */
    {0x15d5, 0x10d5}, /* Georgian_vin */
    {0x15d6, 0x10d6}, /* Georgian_zen */
    {0x15d7, 0x10d7}, /* Georgian_tan */
    {0x15d8, 0x10d8}, /* Georgian_in */
    {0x15d9, 0x10d9}, /* Georgian_kan */
    {0x15da, 0x10da}, /* Georgian_las */
    {0x15db, 0x10db}, /* Georgian_man */
    {0x15dc, 0x10dc}, /* Georgian_nar */
    {0x15dd, 0x10dd}, /* Georgian_on */
    {0x15de, 0x10de}, /* Georgian_par */
    {0x15df, 0x10df}, /* Georgian_zhar */
    {0x15e0, 0x10e0}, /* Georgian_rae */
    {0x15e1, 0x10e1}, /* Georgian_san */
    {0x15e2, 0x10e2}, /* Georgian_tar */
    {0x15e3, 0x10e3}, /* Georgian_un */
    {0x15e4, 0x10e4}, /* Georgian_phar */
    {0x15e5, 0x10e5}, /* Georgian_khar */
    {0x15e6, 0x10e6}, /* Georgian_ghan */
    {0x15e7, 0x10e7}, /* Georgian_qar */
    {0x15e8, 0x10e8}, /* Georgian_shin */
    {0x15e9, 0x10e9}, /* Georgian_chin */
    {0x15ea, 0x10ea}, /* Georgian_can */
    {0x15eb, 0x10eb}, /* Georgian_jil */
    {0x15ec, 0x10ec}, /* Georgian_cil */
    {0x15ed, 0x10ed}, /* Georgian_char */
    {0x15ee, 0x10ee}, /* Georgian_xan */
    {0x15ef, 0x10ef}, /* Georgian_jhan */
    {0x15f0, 0x10f0}, /* Georgian_hae */
    {0x15f1, 0x10f1}, /* Georgian_he */
    {0x15f2, 0x10f2}, /* Georgian_hie */
    {0x15f3, 0x10f3}, /* Georgian_we */
    {0x15f4, 0x10f4}, /* Georgian_har */
    {0x15f5, 0x10f5}, /* Georgian_hoe */
    {0x15f6, 0x10f6}, /* Georgian_fi */
    {0x12a1, 0x1e02}, /* Babovedot */
    {0x12a2, 0x1e03}, /* babovedot */
    {0x12a6, 0x1e0a}, /* Dabovedot */
    {0x12a8, 0x1e80}, /* Wgrave */
    {0x12aa, 0x1e82}, /* Wacute */
    {0x12ab, 0x1e0b}, /* dabovedot */
    {0x12ac, 0x1ef2}, /* Ygrave */
    {0x12b0, 0x1e1e}, /* Fabovedot */
    {0x12b1, 0x1e1f}, /* fabovedot */
    {0x12b4, 0x1e40}, /* Mabovedot */
    {0x12b5, 0x1e41}, /* mabovedot */
    {0x12b7, 0x1e56}, /* Pabovedot */
    {0x12b8, 0x1e81}, /* wgrave */
    {0x12b9, 0x1e57}, /* pabovedot */
    {0x12ba, 0x1e83}, /* wacute */
    {0x12bb, 0x1e60}, /* Sabovedot */
    {0x12bc, 0x1ef3}, /* ygrave */
    {0x12bd, 0x1e84}, /* Wdiaeresis */
    {0x12be, 0x1e85}, /* wdiaeresis */
    {0x12bf, 0x1e61}, /* sabovedot */
    {0x12d0, 0x0174}, /* Wcircumflex */
    {0x12d7, 0x1e6a}, /* Tabovedot */
    {0x12de, 0x0176}, /* Ycircumflex */
    {0x12f0, 0x0175}, /* wcircumflex */
    {0x12f7, 0x1e6b}, /* tabovedot */
    {0x12fe, 0x0177}, /* ycircumflex */
    {0x0590, 0x06f0}, /* Farsi_0 */
    {0x0591, 0x06f1}, /* Farsi_1 */
    {0x0592, 0x06f2}, /* Farsi_2 */
    {0x0593, 0x06f3}, /* Farsi_3 */
    {0x0594, 0x06f4}, /* Farsi_4 */
    {0x0595, 0x06f5}, /* Farsi_5 */
    {0x0596, 0x06f6}, /* Farsi_6 */
    {0x0597, 0x06f7}, /* Farsi_7 */
    {0x0598, 0x06f8}, /* Farsi_8 */
    {0x0599, 0x06f9}, /* Farsi_9 */
    {0x05a5, 0x066a}, /* Arabic_percent */
    {0x05a6, 0x0670}, /* Arabic_superscript_alef */
    {0x05a7, 0x0679}, /* Arabic_tteh */
    {0x05a8, 0x067e}, /* Arabic_peh */
    {0x05a9, 0x0686}, /* Arabic_tcheh */
    {0x05aa, 0x0688}, /* Arabic_ddal */
    {0x05ab, 0x0691}, /* Arabic_rreh */
    {0x05ae, 0x06d4}, /* Arabic_fullstop */
    {0x05b0, 0x0660}, /* Arabic_0 */
    {0x05b1, 0x0661}, /* Arabic_1 */
    {0x05b2, 0x0662}, /* Arabic_2 */
    {0x05b3, 0x0663}, /* Arabic_3 */
    {0x05b4, 0x0664}, /* Arabic_4 */
    {0x05b5, 0x0665}, /* Arabic_5 */
    {0x05b6, 0x0666}, /* Arabic_6 */
    {0x05b7, 0x0667}, /* Arabic_7 */
    {0x05b8, 0x0668}, /* Arabic_8 */
    {0x05b9, 0x0669}, /* Arabic_9 */
    {0x05f3, 0x0653}, /* Arabic_madda_above */
    {0x05f4, 0x0654}, /* Arabic_hamza_above */
    {0x05f5, 0x0655}, /* Arabic_hamza_below */
    {0x05f6, 0x0698}, /* Arabic_jeh */
    {0x05f7, 0x06a4}, /* Arabic_veh */
    {0x05f8, 0x06a9}, /* Arabic_keheh */
    {0x05f9, 0x06af}, /* Arabic_gaf */
    {0x05fa, 0x06ba}, /* Arabic_noon_ghunna */
    {0x05fb, 0x06be}, /* Arabic_heh_doachashmee */
    {0x05fc, 0x06cc}, /* Farsi_yeh */
    {0x05fd, 0x06d2}, /* Arabic_yeh_baree */
    {0x05fe, 0x06c1}, /* Arabic_heh_goal */
    {0x0680, 0x0492}, /* Cyrillic_GHE_bar */
    {0x0681, 0x0496}, /* Cyrillic_ZHE_descender */
    {0x0682, 0x049a}, /* Cyrillic_KA_descender */
    {0x0683, 0x049c}, /* Cyrillic_KA_vertstroke */
    {0x0684, 0x04a2}, /* Cyrillic_EN_descender */
    {0x0685, 0x04ae}, /* Cyrillic_U_straight */
    {0x0686, 0x04b0}, /* Cyrillic_U_straight_bar */
    {0x0687, 0x04b2}, /* Cyrillic_HA_descender */
    {0x0688, 0x04b6}, /* Cyrillic_CHE_descender */
    {0x0689, 0x04b8}, /* Cyrillic_CHE_vertstroke */
    {0x068a, 0x04ba}, /* Cyrillic_SHHA */
    {0x068c, 0x04d8}, /* Cyrillic_SCHWA */
    {0x068d, 0x04e2}, /* Cyrillic_I_macron */
    {0x068e, 0x04e8}, /* Cyrillic_O_bar */
    {0x068f, 0x04ee}, /* Cyrillic_U_macron */
    {0x0690, 0x0493}, /* Cyrillic_ghe_bar */
    {0x0691, 0x0497}, /* Cyrillic_zhe_descender */
    {0x0692, 0x049b}, /* Cyrillic_ka_descender */
    {0x0693, 0x049d}, /* Cyrillic_ka_vertstroke */
    {0x0694, 0x04a3}, /* Cyrillic_en_descender */
    {0x0695, 0x04af}, /* Cyrillic_u_straight */
    {0x0696, 0x04b1}, /* Cyrillic_u_straight_bar */
    {0x0697, 0x04b3}, /* Cyrillic_ha_descender */
    {0x0698, 0x04b7}, /* Cyrillic_che_descender */
    {0x0699, 0x04b9}, /* Cyrillic_che_vertstroke */
    {0x069a, 0x04bb}, /* Cyrillic_shha */
    {0x069c, 0x04d9}, /* Cyrillic_schwa */
    {0x069d, 0x04e3}, /* Cyrillic_i_macron */
    {0x069e, 0x04e9}, /* Cyrillic_o_bar */
    {0x069f, 0x04ef}, /* Cyrillic_u_macron */
    {0x16a3, 0x1e8a}, /* Xabovedot */
    {0x16a6, 0x012c}, /* Ibreve */
    {0x16a9, 0x01b5}, /* Zstroke */
    {0x16aa, 0x01e6}, /* Gcaron */
    {0x16af, 0x019f}, /* Obarred */
    {0x16b3, 0x1e8b}, /* xabovedot */
    {0x16b6, 0x012d}, /* ibreve */
    {0x16b9, 0x01b6}, /* zstroke */
    {0x16ba, 0x01e7}, /* gcaron */
    {0x16bd, 0x01d2}, /* ocaron */
    {0x16bf, 0x0275}, /* obarred */
    {0x16c6, 0x018f}, /* SCHWA */
    {0x16f6, 0x0259}, /* schwa */
    {0x16d1, 0x1e36}, /* Lbelowdot */
    {0x16e1, 0x1e37}, /* lbelowdot */
    {0x1ea0, 0x1ea0}, /* Abelowdot */
    {0x1ea1, 0x1ea1}, /* abelowdot */
    {0x1ea2, 0x1ea2}, /* Ahook */
    {0x1ea3, 0x1ea3}, /* ahook */
    {0x1ea4, 0x1ea4}, /* Acircumflexacute */
    {0x1ea5, 0x1ea5}, /* acircumflexacute */
    {0x1ea6, 0x1ea6}, /* Acircumflexgrave */
    {0x1ea7, 0x1ea7}, /* acircumflexgrave */
    {0x1ea8, 0x1ea8}, /* Acircumflexhook */
    {0x1ea9, 0x1ea9}, /* acircumflexhook */
    {0x1eaa, 0x1eaa}, /* Acircumflextilde */
    {0x1eab, 0x1eab}, /* acircumflextilde */
    {0x1eac, 0x1eac}, /* Acircumflexbelowdot */
    {0x1ead, 0x1ead}, /* acircumflexbelowdot */
    {0x1eae, 0x1eae}, /* Abreveacute */
    {0x1eaf, 0x1eaf}, /* abreveacute */
    {0x1eb0, 0x1eb0}, /* Abrevegrave */
    {0x1eb1, 0x1eb1}, /* abrevegrave */
    {0x1eb2, 0x1eb2}, /* Abrevehook */
    {0x1eb3, 0x1eb3}, /* abrevehook */
    {0x1eb4, 0x1eb4}, /* Abrevetilde */
    {0x1eb5, 0x1eb5}, /* abrevetilde */
    {0x1eb6, 0x1eb6}, /* Abrevebelowdot */
    {0x1eb7, 0x1eb7}, /* abrevebelowdot */
    {0x1eb8, 0x1eb8}, /* Ebelowdot */
    {0x1eb9, 0x1eb9}, /* ebelowdot */
    {0x1eba, 0x1eba}, /* Ehook */
    {0x1ebb, 0x1ebb}, /* ehook */
    {0x1ebc, 0x1ebc}, /* Etilde */
    {0x1ebd, 0x1ebd}, /* etilde */
    {0x1ebe, 0x1ebe}, /* Ecircumflexacute */
    {0x1ebf, 0x1ebf}, /* ecircumflexacute */
    {0x1ec0, 0x1ec0}, /* Ecircumflexgrave */
    {0x1ec1, 0x1ec1}, /* ecircumflexgrave */
    {0x1ec2, 0x1ec2}, /* Ecircumflexhook */
    {0x1ec3, 0x1ec3}, /* ecircumflexhook */
    {0x1ec4, 0x1ec4}, /* Ecircumflextilde */
    {0x1ec5, 0x1ec5}, /* ecircumflextilde */
    {0x1ec6, 0x1ec6}, /* Ecircumflexbelowdot */
    {0x1ec7, 0x1ec7}, /* ecircumflexbelowdot */
    {0x1ec8, 0x1ec8}, /* Ihook */
    {0x1ec9, 0x1ec9}, /* ihook */
    {0x1eca, 0x1eca}, /* Ibelowdot */
    {0x1ecb, 0x1ecb}, /* ibelowdot */
    {0x1ecc, 0x1ecc}, /* Obelowdot */
    {0x1ecd, 0x1ecd}, /* obelowdot */
    {0x1ece, 0x1ece}, /* Ohook */
    {0x1ecf, 0x1ecf}, /* ohook */
    {0x1ed0, 0x1ed0}, /* Ocircumflexacute */
    {0x1ed1, 0x1ed1}, /* ocircumflexacute */
    {0x1ed2, 0x1ed2}, /* Ocircumflexgrave */
    {0x1ed3, 0x1ed3}, /* ocircumflexgrave */
    {0x1ed4, 0x1ed4}, /* Ocircumflexhook */
    {0x1ed5, 0x1ed5}, /* ocircumflexhook */
    {0x1ed6, 0x1ed6}, /* Ocircumflextilde */
    {0x1ed7, 0x1ed7}, /* ocircumflextilde */
    {0x1ed8, 0x1ed8}, /* Ocircumflexbelowdot */
    {0x1ed9, 0x1ed9}, /* ocircumflexbelowdot */
    {0x1eda, 0x1eda}, /* Ohornacute */
    {0x1edb, 0x1edb}, /* ohornacute */
    {0x1edc, 0x1edc}, /* Ohorngrave */
    {0x1edd, 0x1edd}, /* ohorngrave */
    {0x1ede, 0x1ede}, /* Ohornhook */
    {0x1edf, 0x1edf}, /* ohornhook */
    {0x1ee0, 0x1ee0}, /* Ohorntilde */
    {0x1ee1, 0x1ee1}, /* ohorntilde */
    {0x1ee2, 0x1ee2}, /* Ohornbelowdot */
    {0x1ee3, 0x1ee3}, /* ohornbelowdot */
    {0x1ee4, 0x1ee4}, /* Ubelowdot */
    {0x1ee5, 0x1ee5}, /* ubelowdot */
    {0x1ee6, 0x1ee6}, /* Uhook */
    {0x1ee7, 0x1ee7}, /* uhook */
    {0x1ee8, 0x1ee8}, /* Uhornacute */
    {0x1ee9, 0x1ee9}, /* uhornacute */
    {0x1eea, 0x1eea}, /* Uhorngrave */
    {0x1eeb, 0x1eeb}, /* uhorngrave */
    {0x1eec, 0x1eec}, /* Uhornhook */
    {0x1eed, 0x1eed}, /* uhornhook */
    {0x1eee, 0x1eee}, /* Uhorntilde */
    {0x1eef, 0x1eef}, /* uhorntilde */
    {0x1ef0, 0x1ef0}, /* Uhornbelowdot */
    {0x1ef1, 0x1ef1}, /* uhornbelowdot */
    {0x1ef4, 0x1ef4}, /* Ybelowdot */
    {0x1ef5, 0x1ef5}, /* ybelowdot */
    {0x1ef6, 0x1ef6}, /* Yhook */
    {0x1ef7, 0x1ef7}, /* yhook */
    {0x1ef8, 0x1ef8}, /* Ytilde */
    {0x1ef9, 0x1ef9}, /* ytilde */
    {0x1efa, 0x01a0}, /* Ohorn */
    {0x1efb, 0x01a1}, /* ohorn */
    {0x1efc, 0x01af}, /* Uhorn */
    {0x1efd, 0x01b0}, /* uhorn */
    {0, 0}
};

#endif
Changes to macosx/tkMacOSXMenu.c.
1
2
3
4
5
6
7
8
9




10
11
12
13
14
15
16
1
2
3
4
5




6
7
8
9
10
11
12
13
14
15
16





-
-
-
-
+
+
+
+







/*
 * 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 <[email protected]>
 * Copyright (c) 2012 Adrian Robert.
 * Copyright © 1996-1997 Sun Microsystems, Inc.
 * Copyright © 2001-2009 Apple Inc.
 * Copyright © 2005-2009 Daniel A. Steffen <[email protected]>
 * 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.
 */

#include "tkMacOSXPrivate.h"
#include "tkMenubutton.h"
32
33
34
35
36
37
38
39

40
41
42
43
44

45
46
47
48
49
50
51


52
53
54
55
56
57
58
59
60
61

62
63
64
65
66
67

68
69
70
71
72
73
74
32
33
34
35
36
37
38

39
40
41
42
43

44
45
46
47
48
49


50
51
52
53
54
55
56
57
58
59
60

61
62
63
64
65
66

67
68
69
70
71
72
73
74







-
+




-
+





-
-
+
+









-
+





-
+







#define ENTRY_WINDOWS_MENU	ENTRY_PLATFORM_FLAG3

#define sl(s) ((int) (sizeof(s "") - 1))

#define SPECIALMENU(n, f) {.name = "." #n, .len = sl(#n) + 1, \
	.flag = ENTRY_##f##_MENU }
static const struct {
    const char *name; const size_t len; const int flag;
    const char *name; size_t len; int flag;
} specialMenus[] = {
    SPECIALMENU(help,	HELP),
    SPECIALMENU(apple,	APPLE),
    SPECIALMENU(window,	WINDOWS),
    {NULL}
    {NULL, 0, 0}
};
#undef SPECIALMENU

#define MODIFIER(n, f) {.name = #n, .len = sl(#n), .mask = f }
static const struct {
    const char *name; const size_t len; const NSUInteger mask;
} modifiers[] = {
    const char *name; size_t len; NSUInteger mask;
} allModifiers[] = {
    MODIFIER(Control,	NSControlKeyMask),
    MODIFIER(Ctrl,	NSControlKeyMask),
    MODIFIER(Option,	NSAlternateKeyMask),
    MODIFIER(Opt,	NSAlternateKeyMask),
    MODIFIER(Alt,	NSAlternateKeyMask),
    MODIFIER(Shift,	NSShiftKeyMask),
    MODIFIER(Command,	NSCommandKeyMask),
    MODIFIER(Cmd,	NSCommandKeyMask),
    MODIFIER(Meta,	NSCommandKeyMask),
    {NULL}
    {NULL, 0, 0}
};
#undef MODIFIER

#define ACCEL(n, c) {.name = #n, .len = sl(#n), .ch = c }
static const struct {
    const char *name; const size_t len; const UniChar ch;
    const char *name; size_t len; UniChar ch;
} specialAccelerators[] = {
    ACCEL(PageUp,	NSPageUpFunctionKey),
    ACCEL(PageDown,	NSPageDownFunctionKey),
    ACCEL(Left,		NSLeftArrowFunctionKey),
    ACCEL(Right,	NSRightArrowFunctionKey),
    ACCEL(Up,		NSUpArrowFunctionKey),
    ACCEL(Down,		NSDownArrowFunctionKey),
82
83
84
85
86
87
88
89

90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109





























































110
111
112
113
114
115
116
82
83
84
85
86
87
88

89
90
91
92
93



94

95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173







-
+




-
-
-

-











+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    ACCEL(Delete,	NSDeleteCharacter),
    ACCEL(Home,		NSHomeFunctionKey),
    ACCEL(End,		NSEndFunctionKey),
    ACCEL(Return,	NSCarriageReturnCharacter),
    ACCEL(Help,		NSHelpFunctionKey),
    ACCEL(Power,	0x233d),
    ACCEL(Eject,	0xf804),
    {NULL}
    {NULL, 0, 0}
};
#undef ACCEL
#undef sl

static int gNoTkMenus = 0;	/* This is used by Tk_MacOSXTurnOffMenus as
				 * the flag that Tk is not to draw any
				 * menus. */
static int inPostMenu = 0;
static unsigned long defaultBg = 0, defaultFg = 0;
static SInt32 menuMarkColumnWidth = 0, menuIconTrailingEdgeMargin = 0;
static SInt32 menuTextLeadingEdgeMargin = 0, menuTextTrailingEdgeMargin = 0;
static SInt16 menuItemExtraHeight = 0, menuItemExtraWidth = 0;
static SInt16 menuSeparatorHeight = 0;

static void	CheckForSpecialMenu(TkMenu *menuPtr);
static NSString *ParseAccelerator(const char *accel, NSUInteger *maskPtr);
static int	GenerateMenuSelectEvent(TKMenu *menu, NSMenuItem *menuItem);
static void	MenuSelectEvent(TkMenu *menuPtr);
static void	RecursivelyClearActiveMenu(TkMenu *menuPtr);
static int	ModifierCharWidth(Tk_Font tkfont);

#pragma mark TkBackgroundLoop

/*
 * The function TkMacOSXEventsCheckProc (in tkMacOSXNotify.c) is the "check
 * proc" for the macOS event source.  Its job is to remove NSEvents from the
 * default event queue of the NSApplication.  It does this by calling the
 * method [NSApp nextEventMatchingMask: untilDate: inMode: dequeue:]. As a
 * rule, when the untilDate is set to the distant past this method returns
 * immediately.  An exception to that rule is when the next event is the button
 * press on a menu button.  In that case, the method starts running a nested
 * event loop in the mode NSEventTrackingRunLoopMode which does not return
 * until the menu has been dismissed.  In Tk 8.6.10 and earlier, this meant
 * that the Tk event loop would block in its call to the check proc as long as
 * the menu was posted.  For example, opening a menu during the Rube Goldberg
 * demo would cause the animation to stop.  This was also the case for
 * menubuttons.
 *
 * The TKBackground object below works around this problem, and allows a Tk
 * event loop to run while a menu is open.  It is a subclass of NSThread which
 * inserts requests to call [NSApp _runBackgroundLoop] onto the queue
 * associated with the NSEventTrackingRunLoopMode.  One of these threads gets
 * started in the callback [NSApp menuBeginTracking] and cancelled in [NSApp
 * menuEndTracking].
 */

@interface TKBackgroundLoop: NSThread
@end

@implementation TKBackgroundLoop
- (void) main
{
    NSAutoreleasePool *pool = [NSAutoreleasePool new];
    NSArray *modeArray = [NSArray arrayWithObjects: NSEventTrackingRunLoopMode,
				  nil];
    while(1) {

	/*
	 * Queue a request to process Tk events during event tracking.
	 */

	[NSApp performSelectorOnMainThread:@selector(_runBackgroundLoop)
				withObject:nil
			     waitUntilDone:true
				     modes:modeArray];
	if ([self isCancelled]) {
	    [NSThread exit];
	}

	/*
	 * Allow the tracked events to be processed too.
	 */

	[NSThread sleepForTimeInterval:0.001];
    }
    [pool drain];
}
@end

TKBackgroundLoop *backgroundLoop = nil;


#pragma mark TKMenu

/*
 * This interface is not declared in tkMacOSXPrivate.h because it requires
 * tkMenu.h.
 */
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
312
313
314
315
316
317
318






319
320
321
322
323
324
325







-
-
-
-
-
-







	NSMenuItem *menuItem = (NSMenuItem *) sender;
	TkMenu *menuPtr = (TkMenu *) _tkMenu;
	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);

	    if (result != TCL_OK && result != TCL_CONTINUE &&
		    result != TCL_BREAK) {
283
284
285
286
287
288
289


290
291
292
293
294
295
296
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349







+
+







@end

@implementation TKMenu(TKMenuDelegate)

- (BOOL) menuHasKeyEquivalent: (NSMenu *) menu forEvent: (NSEvent *) event
	target: (id *) target action: (SEL *) action
{
    (void)menu;

    /*
     * Use lowercaseString when comparing keyEquivalents since the notion of
     * a shifted upper case letter does not make much sense.
     */

    NSString *key = [[event charactersIgnoringModifiers] lowercaseString];
    NSUInteger modifiers = [event modifierFlags] &
339
340
341
342
343
344
345


346
347
348
349
350
351
352
353
354


355
356
357
358
359
360
361


362
363
364
365
366
367
368
369

370
371
372
373
374
375
376
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436







+
+









+
+







+
+








+







	}
    }
    return NO;
}

- (void) menuWillOpen: (NSMenu *) menu
{
    (void)menu;

    if (_tkMenu) {
	//RecursivelyClearActiveMenu(_tkMenu);
	GenerateMenuSelectEvent((TKMenu *)[self supermenu],
		[self itemInSupermenu]);
    }
}

- (void) menuDidClose: (NSMenu *) menu
{
    (void)menu;

    if (_tkMenu) {
	RecursivelyClearActiveMenu(_tkMenu);
    }
}

- (void) menu: (NSMenu *) menu willHighlightItem: (NSMenuItem *) item
{
    (void)menu;

    if (_tkMenu) {
	GenerateMenuSelectEvent(self, item);
    }
}

- (void) menuNeedsUpdate: (NSMenu *) menu
{
    TkMenu *menuPtr = (TkMenu *) _tkMenu;
    (void)menu;

    if (menuPtr) {
	Tcl_Interp *interp = menuPtr->interp;

	Tcl_Preserve(interp);
	Tcl_Preserve(menuPtr);

388
389
390
391
392
393
394

395
396
397






398
399
400
401
402
403

404
405
406





407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486




487
488
489
490
491
492
493







+



+
+
+
+
+
+






+



+
+
+
+
+







-
-
-
-








#pragma mark TKApplication(TKMenu)

@implementation TKApplication(TKMenu)

- (void) menuBeginTracking: (NSNotification *) notification
{
    (void)notification;
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
    TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
#endif
    if (backgroundLoop) {
	[backgroundLoop cancel];
	[backgroundLoop release];
    }
    backgroundLoop = [[TKBackgroundLoop alloc] init];
    [backgroundLoop start];
    //TkMacOSXClearMenubarActive();
    //TkMacOSXPreprocessMenu();
}

- (void) menuEndTracking: (NSNotification *) notification
{
    (void)notification;
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
    TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
#endif
    if (backgroundLoop) {
	[backgroundLoop cancel];
	[backgroundLoop release];
	backgroundLoop = nil;
    }
    if (!inPostMenu) {
	TkMacOSXClearMenubarActive();
    }
}

- (void) tkSetMainMenu: (TKMenu *) menu
{
    if (gNoTkMenus) {
	return;
    }

    TKMenu *applicationMenu = nil;

    if (menu) {
	NSMenuItem *applicationMenuItem = [menu numberOfItems] ?
		[menu itemAtIndex:0] : nil;

	if (![menu isSpecial:tkMainMenu]) {
606
607
608
609
610
611
612
613
614
615
616
617













618
619
620
621

622
623
624
625
626
627
628
629

630
631
632
633

634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655



























656
657
658
659
660
661








662
663
664







665
666

667
668
669
670
671
672
673
675
676
677
678
679
680
681

682
683


684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699

700
701
702
703
704
705
706
707

708
709



710

711
712
713
714
715
716
717
718
719
720
721
722
723








724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750






751
752
753
754
755
756
757
758



759
760
761
762
763
764
765
766

767
768
769
770
771
772
773
774







-


-
-
+
+
+
+
+
+
+
+
+
+
+
+
+



-
+







-
+

-
-
-
+
-













-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+

-
+







    NSMenuItem *menuItem = (NSMenuItem *) mePtr->platformEntryData;
    NSString *title = @"";
    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);
    Tcl_Obj *fontPtr = (mePtr->fontPtr ?
			mePtr->fontPtr : mePtr->menuPtr->fontPtr);
    static unsigned long defaultBg, defaultFg;
    static int initialized = 0;

    if (!initialized) {
	TkColor *tkColPtr = TkpGetColor(NULL, DEF_MENU_BG_COLOR);
	defaultBg = tkColPtr->color.pixel;
	ckfree(tkColPtr);
	tkColPtr = TkpGetColor(NULL, DEF_MENU_FG);
	defaultFg = tkColPtr->color.pixel;
	ckfree(tkColPtr);
    }

    if (mePtr->image) {
    	Tk_SizeOfImage(mePtr->image, &imageWidth, &imageHeight);
	image = TkMacOSXGetNSImageWithTkImage(mePtr->menuPtr->display,
	image = TkMacOSXGetNSImageFromTkImage(mePtr->menuPtr->display,
		mePtr->image, imageWidth, imageHeight);
    } else if (mePtr->bitmapPtr != None) {
	Pixmap bitmap = Tk_GetBitmapFromObj(mePtr->menuPtr->tkwin,
		mePtr->bitmapPtr);

	Tk_SizeOfBitmap(mePtr->menuPtr->display, bitmap, &imageWidth,
		&imageHeight);
	image = TkMacOSXGetNSImageWithBitmap(mePtr->menuPtr->display, bitmap,
	image = TkMacOSXGetNSImageFromBitmap(mePtr->menuPtr->display, bitmap,
		gc, imageWidth, imageHeight);
	if (gc->foreground == defaultFg) {
	    // Use a semantic foreground color by default
	    [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)
		length:mePtr->labelLength encoding:NSUTF8StringEncoding]
		autorelease];
	if ([title hasSuffix:@"..."]) {
	    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);


#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];
    }
	    attributes = [[attributes mutableCopy] autorelease];
	    [(NSMutableDictionary *) attributes setObject:color
		    forKey:NSForegroundColorAttributeName];
	}
	if (attributes) {
	    attributedTitle = [[[NSAttributedString alloc]
    if (gc->background != defaultBg) {
	NSColor *bgcolor = TkMacOSXGetNSColor(gc, gc->background);
	[attributes setObject:bgcolor
	 	       forKey:NSBackgroundColorAttributeName];
    }

#else

		    initWithString:title attributes:attributes] autorelease];
	}
    }
    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),
		&modifierMask);
    }
692
693
694
695
696
697
698
699
700
701





702
703
704
705
706

707
708
709

710
711
712
713
714
715
716
717
718

719
720
721
722
723
724
725
726
793
794
795
796
797
798
799



800
801
802
803
804
805
806



807

808

809









810

811
812
813
814
815
816
817







-
-
-
+
+
+
+
+


-
-
-
+
-

-
+
-
-
-
-
-
-
-
-
-
+
-







		submenu = nil;
	    } else {
		[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.
		     * 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].
		     */

		    int i = 0;
		    NSArray *itemArray = [submenu itemArray];

		    for (int i = 0; i < menuRefPtr->menuPtr->numEntries; i++) {
		    for (NSMenuItem *item in itemArray) {
			TkMenuEntry *submePtr = menuRefPtr->menuPtr->entries[i];

			NSMenuItem *item = (NSMenuItem *) submePtr->platformEntryData;
			/*
			 * 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)];
			[item setEnabled:(submePtr->state != ENTRY_DISABLED)];
			i++;
		    }
		}
	    }
	}
    }
    [menuItem setSubmenu:submenu];

781
782
783
784
785
786
787
788

789
790
791
792
793
794
795
872
873
874
875
876
877
878

879
880
881
882
883
884
885
886







-
+







 *	The menu is posted and handled.
 *
 *----------------------------------------------------------------------
 */

int
TkpPostMenu(
    Tcl_Interp *interp,		/* The interpreter this menu lives in */
    TCL_UNUSED(Tcl_Interp *),		/* The interpreter this menu lives in */
    TkMenu *menuPtr,		/* The menu we are posting */
    int x, int y,		/* The screen coordinates where the top left
				 * corner of the menu, or of the specified
				 * entry, will be located. */
    int index)
{
    int result;
805
806
807
808
809
810
811
812

813
814
815
816
817
818
819
896
897
898
899
900
901
902

903
904
905
906
907
908
909
910







-
+







	 * Fix for bug 07cfc9f03e: use the view for the parent real (non-menu)
	 * toplevel window, rather than always using the root window.
	 * This allows menus to appear on a separate monitor than the root
	 * window, and to use the appearance of their parent real window
	 * rather than the appearance of the root window.
	 */
	realWinPtr = (TkWindow*) realWin;
	realWinView = TkMacOSXDrawableView(realWinPtr->privatePtr);
	realWinView = TkMacOSXGetNSViewForDrawable(realWinPtr->privatePtr);
	if (realWinView != nil) {
	    break;
	}
	realWin = Tk_Parent(realWin);
    }
    NSWindow *win = [realWinView window];
    NSView *view = [win contentView];
878
879
880
881
882
883
884
885

886
887
888
889
890
891
892
969
970
971
972
973
974
975

976
977
978
979
980
981
982
983







-
+







 *	A useless window is posted.
 *
 *----------------------------------------------------------------------
 */

int
TkpPostTearoffMenu(
    Tcl_Interp *interp,		/* The interpreter this menu lives in */
    TCL_UNUSED(Tcl_Interp *),	/* The interpreter this menu lives in */
    TkMenu *menuPtr,		/* The menu we are posting */
    int x, int y, int index)	/* The screen coordinates where the top left
				 * corner of the menu, or of the specified
				 * entry, will be located. */
{
    int vRootX, vRootY, vRootWidth, vRootHeight;
    int result;
1026
1027
1028
1029
1030
1031
1032
1033
1034


1035
1036
1037
1038
1039
1040
1041
1117
1118
1119
1120
1121
1122
1123


1124
1125
1126
1127
1128
1129
1130
1131
1132







-
-
+
+







    }

    if (menuName) {
	Tk_Window menubar = NULL;

	if (winPtr->wmInfoPtr &&
		winPtr->wmInfoPtr->menuPtr &&
		winPtr->wmInfoPtr->menuPtr->masterMenuPtr) {
	    menubar = winPtr->wmInfoPtr->menuPtr->masterMenuPtr->tkwin;
		winPtr->wmInfoPtr->menuPtr->mainMenuPtr) {
	    menubar = winPtr->wmInfoPtr->menuPtr->mainMenuPtr->tkwin;
	}

	/*
	 * Attempt to find the NSMenu directly.  If that fails, ask Tk to find
	 * it.
	 */

1081
1082
1083
1084
1085
1086
1087
1088

1089
1090
1091
1092
1093
1094
1095
1096


1097
1098
1099
1100
1101

1102
1103
1104
1105
1106

1107
1108
1109
1110
1111
1112
1113
1172
1173
1174
1175
1176
1177
1178

1179
1180
1181
1182
1183
1184
1185


1186
1187
1188
1189
1190
1191

1192
1193
1194
1195
1196

1197
1198
1199
1200
1201
1202
1203
1204







-
+






-
-
+
+




-
+




-
+







 *----------------------------------------------------------------------
 */

static void
CheckForSpecialMenu(
    TkMenu *menuPtr)		/* The menu we are checking */
{
    if (!menuPtr->masterMenuPtr->tkwin) {
    if (!menuPtr->mainMenuPtr->tkwin) {
	return;
    }
    for (TkMenuEntry *cascadeEntryPtr = menuPtr->menuRefPtr->parentEntryPtr;
	    cascadeEntryPtr;
	    cascadeEntryPtr = cascadeEntryPtr->nextCascadePtr) {
	if (cascadeEntryPtr->menuPtr->menuType == MENUBAR
		&& cascadeEntryPtr->menuPtr->masterMenuPtr->tkwin) {
	    TkMenu *masterMenuPtr = cascadeEntryPtr->menuPtr->masterMenuPtr;
		&& cascadeEntryPtr->menuPtr->mainMenuPtr->tkwin) {
	    TkMenu *mainMenuPtr = cascadeEntryPtr->menuPtr->mainMenuPtr;
	    int i = 0;
	    Tcl_DString ds;

	    Tcl_DStringInit(&ds);
	    Tcl_DStringAppend(&ds, Tk_PathName(masterMenuPtr->tkwin), -1);
	    Tcl_DStringAppend(&ds, Tk_PathName(mainMenuPtr->tkwin), -1);
	    while (specialMenus[i].name) {
		Tcl_DStringAppend(&ds, specialMenus[i].name,
			specialMenus[i].len);
		if (strcmp(Tcl_DStringValue(&ds),
			Tk_PathName(menuPtr->masterMenuPtr->tkwin)) == 0) {
			Tk_PathName(menuPtr->mainMenuPtr->tkwin)) == 0) {
		    cascadeEntryPtr->entryFlags |= specialMenus[i].flag;
		} else {
		    cascadeEntryPtr->entryFlags &= ~specialMenus[i].flag;
		}
		Tcl_DStringSetLength(&ds, Tcl_DStringLength(&ds) -
			specialMenus[i].len);
		i++;
1141
1142
1143
1144
1145
1146
1147
1148
1149


1150
1151

1152
1153

1154
1155
1156
1157
1158
1159

1160
1161
1162
1163
1164
1165
1166
1232
1233
1234
1235
1236
1237
1238


1239
1240
1241

1242
1243

1244
1245
1246
1247
1248
1249

1250
1251
1252
1253
1254
1255
1256
1257







-
-
+
+

-
+

-
+





-
+







    unichar ch = 0;
    size_t len;
    int i;

    *maskPtr = 0;
    while (1) {
	i = 0;
	while (modifiers[i].name) {
	    int l = modifiers[i].len;
	while (allModifiers[i].name) {
	    int l = allModifiers[i].len;

	    if (!strncasecmp(accel, modifiers[i].name, l) &&
	    if (!strncasecmp(accel, allModifiers[i].name, l) &&
		    (accel[l] == '-' || accel[l] == '+')) {
		*maskPtr |= modifiers[i].mask;
		*maskPtr |= allModifiers[i].mask;
		accel += l+1;
		break;
	    }
	    i++;
	}
	if (!modifiers[i].name || !*accel) {
	if (!allModifiers[i].name || !*accel) {
	    break;
	}
    }
    len = strlen(accel);
    if (len > 1) {
	i = 0;
	if (accel[0] == 'F' && len < 4 && accel[1] > '0' && accel[1] <= '9') {
1258
1259
1260
1261
1262
1263
1264
1265

1266
1267
1268
1269
1270
1271
1272
1349
1350
1351
1352
1353
1354
1355

1356
1357
1358
1359
1360
1361
1362
1363







-
+







    TkMenuEntry *mePtr;
    int haveAccel = 0;

    /*
     * Do nothing if this menu is a clone.
     */

    if (menuPtr->tkwin == NULL || menuPtr->masterMenuPtr != menuPtr) {
    if (menuPtr->tkwin == NULL || menuPtr->mainMenuPtr != menuPtr) {
	return;
    }

    menuSize = [(NSMenu *) menuPtr->platformData size];
    Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->borderWidthPtr,
	    &borderWidth);
    Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->activeBorderWidthPtr,
1376
1377
1378
1379
1380
1381
1382
1383

1384
1385
1386
1387



1388
1389
1390

1391
1392
1393
1394
1395
1396
1397
1467
1468
1469
1470
1471
1472
1473

1474
1475



1476
1477
1478
1479
1480

1481
1482
1483
1484
1485
1486
1487
1488







-
+

-
-
-
+
+
+


-
+







		modifierWidth = modifierCharWidth;
	    } else if (mePtr->accelLength == 0) {
		if (haveAccel && !mePtr->hideMargin) {
		    modifierWidth = modifierCharWidth;
		}
	    } else {
		NSUInteger modifMask = [menuItem keyEquivalentModifierMask];
		int i = 0;
		int j = 0;

		while (modifiers[i].name) {
		    if (modifMask & modifiers[i].mask) {
			modifMask &= ~modifiers[i].mask;
		while (allModifiers[j].name) {
		    if (modifMask & allModifiers[j].mask) {
			modifMask &= ~allModifiers[j].mask;
			modifierWidth += modifierCharWidth;
		    }
		    i++;
		    j++;
		}
		accelWidth = [[menuItem keyEquivalent] sizeWithAttributes:
			TkMacOSXNSFontAttributesForFont(tkfont)].width;
	    }
	    if (!mePtr->hideMargin) {
		indicatorSpace = menuMarkColumnWidth;
	    }
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1660
1661
1662
1663
1664
1665
1666
























1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682


1683
1684
1685
1686
1687
1688
1689
1690
1691







1692
1693
1694
1695
1696
1697
1698







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
















-
-









-
-
-
-
-
-
-







	}
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tk_MacOSXTurnOffMenus --
 *
 *	Turns off all the menu drawing code. This is more than just disabling
 *	the "menu" command, this means that Tk will NEVER touch the menubar.
 *	It is needed in the Plugin, where Tk does not own the menubar.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	A flag is set which will disable all menu drawing.
 *
 *----------------------------------------------------------------------
 */

void
Tk_MacOSXTurnOffMenus(void)
{
    gNoTkMenus = 1;
}

/*
 *----------------------------------------------------------------------
 *
 * TkpMenuInit --
 *
 *	Initializes Mac-specific menu data.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Allocates a hash table.
 *
 *----------------------------------------------------------------------
 */

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:);
    observe(NSMenuDidEndTrackingNotification, menuEndTracking:);
#undef observe

    [NSMenuItem setUsesUserKeyEquivalents:NO];
    tkColPtr = TkpGetColor(NULL, DEF_MENU_BG_COLOR);
    defaultBg = tkColPtr->color.pixel;
    ckfree(tkColPtr);
    tkColPtr = TkpGetColor(NULL, DEF_MENU_FG);
    defaultFg = tkColPtr->color.pixel;
    ckfree(tkColPtr);

    ChkErr(GetThemeMetric, kThemeMetricMenuMarkColumnWidth,
	    &menuMarkColumnWidth);
    ChkErr(GetThemeMetric, kThemeMetricMenuTextLeadingEdgeMargin,
	    &menuTextLeadingEdgeMargin);
    ChkErr(GetThemeMetric, kThemeMetricMenuTextTrailingEdgeMargin,
	    &menuTextTrailingEdgeMargin);
    ChkErr(GetThemeMetric, kThemeMetricMenuIconTrailingEdgeMargin,
1687
1688
1689
1690
1691
1692
1693
1694
1695


1696
1697
1698
1699
1700
1701
1702
1745
1746
1747
1748
1749
1750
1751


1752
1753
1754
1755
1756
1757
1758
1759
1760







-
-
+
+







 *	An idle handler is set up to do the reconfiguration.
 *
 *----------------------------------------------------------------------
 */

void
TkpMenuNotifyToplevelCreate(
    Tcl_Interp *interp,		/* The interp the menu lives in. */
    const char *menuName)	/* The name of the menu to reconfigure. */
    TCL_UNUSED(Tcl_Interp *),	/* The interp the menu lives in. */
    TCL_UNUSED(const char *))	/* The name of the menu to reconfigure. */
{
    /*
     * Nothing to do.
     */
}

/*
1716
1717
1718
1719
1720
1721
1722
1723
1724


1725
1726
1727
1728
1729
1730
1731
1774
1775
1776
1777
1778
1779
1780


1781
1782
1783
1784
1785
1786
1787
1788
1789







-
-
+
+







 *	Alt-key bindings.
 *
 *--------------------------------------------------------------
 */

void
TkpInitializeMenuBindings(
    Tcl_Interp *interp,		/* The interpreter to set. */
    Tk_BindingTable bindingTable)
    TCL_UNUSED(Tcl_Interp *),		/* The interpreter to set. */
    TCL_UNUSED(Tk_BindingTable))
				/* The table to add to. */
{
    /*
     * Nothing to do.
     */
}

1757
1758
1759
1760
1761
1762
1763
1764





1765
1766
1767
1768
1769
1770

1771
1772
1773
1774
1775
1776
1777
1778
1779
1780




1781
1782
1783
1784
1785
1786
1787






1788
1789
1790
1791
1792
1793
1794
1815
1816
1817
1818
1819
1820
1821

1822
1823
1824
1825
1826
1827
1828
1829
1830
1831

1832
1833
1834
1835
1836
1837
1838




1839
1840
1841
1842
1843






1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856







-
+
+
+
+
+





-
+






-
-
-
-
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+








/*
 *----------------------------------------------------------------------
 *
 * 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
TkpDrawMenuEntry(
    TkMenuEntry *mePtr,		/* The entry to draw */
    Drawable d,			/* What to draw into */
    Tk_Font tkfont,		/* Precalculated font for menu */
    const Tk_FontMetrics *menuMetricsPtr,
    TCL_UNUSED(TkMenuEntry *),		/* The entry to draw */
    TCL_UNUSED(Drawable),			/* What to draw into */
    TCL_UNUSED(Tk_Font),		/* Precalculated font for menu */
    TCL_UNUSED(const Tk_FontMetrics *),
				/* Precalculated metrics for menu */
    int x,			/* X-coordinate of topleft of entry */
    int y,			/* Y-coordinate of topleft of entry */
    int width,			/* Width of the entry rectangle */
    int height,			/* Height of the current rectangle */
    int strictMotif,		/* Boolean flag */
    int drawArrow)		/* Whether or not to draw the cascade arrow
    TCL_UNUSED(int),			/* X-coordinate of topleft of entry */
    TCL_UNUSED(int),			/* Y-coordinate of topleft of entry */
    TCL_UNUSED(int),			/* Width of the entry rectangle */
    TCL_UNUSED(int),			/* Height of the current rectangle */
    TCL_UNUSED(int),		/* Boolean flag */
    TCL_UNUSED(int))		/* Whether or not to draw the cascade arrow
				 * for cascade items. */
{
}

#pragma mark Obsolete

/*
1829
1830
1831
1832
1833
1834
1835
1836

1837
1838
1839
1840
1841
1842
1843
1891
1892
1893
1894
1895
1896
1897

1898
1899
1900
1901
1902
1903
1904
1905







-
+







 *	A hash table entry in the command table is created with a NULL value.
 *
 *----------------------------------------------------------------------
 */

int
TkMacOSXUseMenuID(
    short macID)		/* The id to take out of the table */
    TCL_UNUSED(short))		/* The id to take out of the table */
{
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
1852
1853
1854
1855
1856
1857
1858
1859
1860


1861
1862
1863
1864
1865
1866
1867
1914
1915
1916
1917
1918
1919
1920


1921
1922
1923
1924
1925
1926
1927
1928
1929







-
-
+
+







 *	Commands for the event are scheduled for execution at idle time.
 *
 *----------------------------------------------------------------------
 */

int
TkMacOSXDispatchMenuEvent(
    int menuID,			/* The menu id of the menu we are invoking */
    int index)			/* The one-based index of the item that was
    TCL_UNUSED(int),			/* The menu id of the menu we are invoking */
    TCL_UNUSED(int))			/* The one-based index of the item that was
				 * selected. */
{
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
Changes to macosx/tkMacOSXMenubutton.c.
1
2
3
4
5
6
7
8
9
10
11





12
13
14
15
16
17
18
1
2
3
4
5
6





7
8
9
10
11
12
13
14
15
16
17
18






-
-
-
-
-
+
+
+
+
+







/*
 * 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 <[email protected]>
 * 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 <[email protected]>
 * 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.
 *
 */

#include "tkMacOSXPrivate.h"
72
73
74
75
76
77
78


79
80
81
82
83
84
85
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87







+
+







 * The structure below defines menubutton class behavior by means of
 * procedures that can be invoked from generic window code.
 */

Tk_ClassProcs tkpMenubuttonClass = {
    sizeof(Tk_ClassProcs),	/* size */
    TkMenuButtonWorldChanged,	/* worldChangedProc */
	NULL,
	NULL
};

/*
 * We use Apple's Pop-Up Button widget to represent the Tk Menubutton.
 * However, we do not use the NSPopUpButton class for this control.  Instead we
 * render the Pop-Up Button using the HITheme library.  This imposes some
 * constraints on what can be done.  The HITheme renderer allows only specific
129
130
131
132
133
134
135
136

137
138
139
140
141
142
143
131
132
133
134
135
136
137

138
139
140
141
142
143
144
145







-
+







 *----------------------------------------------------------------------
 */

TkMenuButton *
TkpCreateMenuButton(
    Tk_Window tkwin)
{
    MacMenuButton *mbPtr = (MacMenuButton *) ckalloc(sizeof(MacMenuButton));
    MacMenuButton *mbPtr = (MacMenuButton *)ckalloc(sizeof(MacMenuButton));

    Tk_CreateEventHandler(tkwin, ActivateMask, MenuButtonEventProc, mbPtr);
    mbPtr->flags = FIRST_DRAW;
    mbPtr->btnkind = kThemePopupButton;
    bzero(&mbPtr->drawinfo, sizeof(mbPtr->drawinfo));
    bzero(&mbPtr->lastdrawinfo, sizeof(mbPtr->lastdrawinfo));
    return (TkMenuButton *) mbPtr;
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
176
177
178
179
180
181
182







183
184
185
186
187
188
189







-
-
-
-
-
-
-







        return;
    }

    pixmap = (Pixmap) Tk_WindowId(tkwin);

    TkMacOSXComputeMenuButtonDrawParams(butPtr, dpPtr);

    /*
     * Set up clipping region.  Make sure the we are using the port for this
     * button, or we will set the wrong window's clip.
     */

    TkMacOSXSetUpClippingRgn(pixmap);

    /*
     * Draw the native portion of the buttons.
     */

    TkMacOSXDrawMenuButton(mbPtr,  dpPtr->gc, pixmap);

    /*
218
219
220
221
222
223
224
225

226
227
228
229
230
231
232
213
214
215
216
217
218
219

220
221
222
223
224
225
226
227







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

void
TkpDestroyMenuButton(
    TkMenuButton *mbPtr)
    TCL_UNUSED(TkMenuButton *))
{
}

/*
 *----------------------------------------------------------------------
 *
 * TkpComputeMenuButtonGeometry --
242
243
244
245
246
247
248
249

250
251
252
253
254
255
256
237
238
239
240
241
242
243

244
245
246
247
248
249
250
251







-
+







 *	The menu button's window may change size.
 *
 *----------------------------------------------------------------------
 */

void
TkpComputeMenuButtonGeometry(butPtr)
    register TkMenuButton *butPtr;	/* Widget record for menu button. */
    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;

    /*
358
359
360
361
362
363
364
365

366
367
368
369
370
371
372
353
354
355
356
357
358
359

360
361
362
363
364
365
366
367







-
+







}

/*
 *----------------------------------------------------------------------
 *
 * DrawMenuButtonImageAndText --
 *
 *        Draws the image and text associated witha button or label.
 *        Draws the image and text associated with a button or label.
 *
 * Results:
 *        None.
 *
 * Side effects:
 *        The image and text are drawn.
 *
389
390
391
392
393
394
395
396

397
398
399
400
401
402
403
384
385
386
387
388
389
390

391
392
393
394
395
396
397
398







-
+







    if (tkwin == NULL || !Tk_IsMapped(tkwin)) {
        return;
    }

    DrawParams *dpPtr = &mbPtr->drawParams;
    pixmap = (Pixmap) Tk_WindowId(tkwin);

    if (butPtr->image != None) {
    if (butPtr->image != NULL) {
        Tk_SizeOfImage(butPtr->image, &width, &height);
        haveImage = 1;
    } else if (butPtr->bitmap != None) {
        Tk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height);
        haveImage = 1;
    }

540
541
542
543
544
545
546
547

548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569

570
571
572
573
574
575
576
535
536
537
538
539
540
541

542

543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562

563
564
565
566
567
568
569
570







-
+
-




















-
+







 *
 *--------------------------------------------------------------
 */

static void
TkMacOSXDrawMenuButton(
    MacMenuButton *mbPtr, /* Mac menubutton. */
    GC gc,                /* The GC we are drawing into - needed for the bevel
    TCL_UNUSED(GC),       /* The GC we are drawing into - not used */
                           * button */
    Pixmap pixmap)        /* The pixmap we are drawing into - needed for the
                           * bevel button */
{
    TkMenuButton *butPtr = (TkMenuButton *) mbPtr;
    TkWindow *winPtr = (TkWindow *) butPtr->tkwin;
    HIRect cntrRect;
    TkMacOSXDrawingContext dc;
    DrawParams *dpPtr = &mbPtr->drawParams;
    int useNewerHITools = 1;

    TkMacOSXComputeMenuButtonParams(butPtr, &mbPtr->btnkind, &mbPtr->drawinfo);

    cntrRect = CGRectMake(winPtr->privatePtr->xOff, winPtr->privatePtr->yOff,
	    Tk_Width(butPtr->tkwin), Tk_Height(butPtr->tkwin));

    if (useNewerHITools == 1) {
        HIRect contHIRec;
        static HIThemeButtonDrawInfo hiinfo;

        MenuButtonBackgroundDrawCB(mbPtr, 32, true);
	if (!TkMacOSXSetupDrawingContext(pixmap, dpPtr->gc, 1, &dc)) {
	if (!TkMacOSXSetupDrawingContext(pixmap, dpPtr->gc, &dc)) {
	    return;
	}

        hiinfo.version = 0;
        hiinfo.state = mbPtr->drawinfo.state;
        hiinfo.kind = mbPtr->btnkind;
        hiinfo.value = mbPtr->drawinfo.value;
593
594
595
596
597
598
599
600

601
602
603
604
605
606
607
587
588
589
590
591
592
593

594
595
596
597
598
599
600
601







-
+








        HIThemeDrawButton(&cntrRect, &hiinfo, dc.context,
		kHIThemeOrientationNormal, &contHIRec);
	TkMacOSXRestoreDrawingContext(&dc);
        MenuButtonContentDrawCB(mbPtr->btnkind, &mbPtr->drawinfo,
		mbPtr, 32, true);
    } else {
	if (!TkMacOSXSetupDrawingContext(pixmap, dpPtr->gc, 1, &dc)) {
	if (!TkMacOSXSetupDrawingContext(pixmap, dpPtr->gc, &dc)) {
	    return;
	}
	TkMacOSXRestoreDrawingContext(&dc);
    }
    mbPtr->lastdrawinfo = mbPtr->drawinfo;
}

621
622
623
624
625
626
627
628
629


630
631
632
633
634
635
636
615
616
617
618
619
620
621


622
623
624
625
626
627
628
629
630







-
-
+
+







 *
 *--------------------------------------------------------------
 */

static void
MenuButtonBackgroundDrawCB (
    MacMenuButton *ptr,
    SInt16 depth,
    Boolean isColorDev)
    TCL_UNUSED(SInt16),
    TCL_UNUSED(Boolean))
{
    TkMenuButton* butPtr = (TkMenuButton *) ptr;
    Tk_Window tkwin = butPtr->tkwin;
    Pixmap pixmap;

    if (tkwin == NULL || !Tk_IsMapped(tkwin)) {
        return;
654
655
656
657
658
659
660
661
662


663
664
665


666
667
668
669
670
671
672
648
649
650
651
652
653
654


655
656
657


658
659
660
661
662
663
664
665
666







-
-
+
+

-
-
+
+







 *      The content of the button gets updated.
 *
 *--------------------------------------------------------------
 */

static void
MenuButtonContentDrawCB (
    ThemeButtonKind kind,
    const HIThemeButtonDrawInfo *drawinfo,
    TCL_UNUSED(ThemeButtonKind),
    TCL_UNUSED(const HIThemeButtonDrawInfo *),
    MacMenuButton *ptr,
    SInt16 depth,
    Boolean isColorDev)
    TCL_UNUSED(SInt16),
    TCL_UNUSED(Boolean))
{
    TkMenuButton *butPtr = (TkMenuButton *) ptr;
    Tk_Window tkwin = butPtr->tkwin;

    if (tkwin == NULL || !Tk_IsMapped(tkwin)) {
        return;
    }
705
706
707
708
709
710
711
712

713
714
715
716
717
718
719
699
700
701
702
703
704
705

706
707
708
709
710
711
712
713







-
+







	}
	if (eventPtr->type == ActivateNotify) {
	    mbPtr->flags |= ACTIVE;
	} else {
	    mbPtr->flags &= ~ACTIVE;
	}
	if ((buttonPtr->flags & REDRAW_PENDING) == 0) {
	    Tcl_DoWhenIdle(TkpDisplayMenuButton, (ClientData) buttonPtr);
	    Tcl_DoWhenIdle(TkpDisplayMenuButton, buttonPtr);
	    buttonPtr->flags |= REDRAW_PENDING;
	}
    }
}

/*
 *----------------------------------------------------------------------
Changes to macosx/tkMacOSXMenus.c.
1
2
3
4
5
6
7
8



9
10
11
12
13
14
15
1
2
3
4
5



6
7
8
9
10
11
12
13
14
15





-
-
-
+
+
+







/*
 * 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 <[email protected]>
 * Copyright © 1995-1996 Sun Microsystems, Inc.
 * Copyright © 2001-2009 Apple Inc.
 * Copyright © 2005-2009 Daniel A. Steffen <[email protected]>
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tkMacOSXPrivate.h"
#include "tkMenu.h"
108
109
110
111
112
113
114
115

116
117
118
119
120
121
122
108
109
110
111
112
113
114

115
116
117
118
119
120
121
122







-
+







    	    	   target:nil],
	    nil];

    /*
     * On OS X 10.12 we get duplicate tab control items if we create them here.
     */

    if ([NSApp macMinorVersion] > 12) {
    if ([NSApp macOSVersion] > 101200) {
	_defaultWindowsMenuItems = [_defaultWindowsMenuItems
	     arrayByAddingObjectsFromArray:
	     [NSArray arrayWithObjects:
        	    [NSMenuItem separatorItem],
    	            [NSMenuItem itemWithTitle:@"Show Previous Tab"
		           action:@selector(selectPreviousTab:)
		           target:nil
195
196
197
198
199
200
201


202
203
204

205
206
207
208
209
210
211
195
196
197
198
199
200
201
202
203
204
205

206
207
208
209
210
211
212
213







+
+


-
+







    } else {
        return [super validateUserInterfaceItem:anItem];
    }
}

- (void) orderFrontStandardAboutPanel: (id) sender
{
    (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) {
	    Tcl_BackgroundException(_eventInterp, code);
	}
227
228
229
230
231
232
233


234
235
236
237
238
239
240
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244







+
+







	}
	Tcl_ResetResult(_eventInterp);
    }
}

- (void) tkSource: (id) sender
{
    (void)sender;

    if (_eventInterp) {
	if (Tcl_EvalEx(_eventInterp, "tk_getOpenFile -filetypes {"
		"{{TCL Scripts} {.tcl} TEXT} {{Text Files} {} TEXT}}",
		-1, TCL_EVAL_GLOBAL) == TCL_OK) {
	    Tcl_Obj *path = Tcl_GetObjResult(_eventInterp);
	    int len;

252
253
254
255
256
257
258


259
260
261
262
263
264
265
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271







+
+







	}
	Tcl_ResetResult(_eventInterp);
    }
}

- (void) tkDemo: (id) sender
{
	(void)sender;

    if (_eventInterp) {
	Tcl_Obj *path = GetWidgetDemoPath(_eventInterp);

	if (path) {
	    Tcl_IncrRefCount(path);

	    [_demoMenuItem setHidden:YES];
277
278
279
280
281
282
283


284
285
286
287
288
289
290
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298







+
+








#pragma mark TKContentView(TKMenus)

@implementation TKContentView(TKMenus)

- (BOOL) validateUserInterfaceItem: (id <NSValidatedUserInterfaceItem>) anItem
{
    (void)anItem;

    return YES;
}

#define EDIT_ACTION(a, e) \
    - (void) a: (id) sender \
    { \
	if ([sender isKindOfClass:[NSMenuItem class]]) { \
318
319
320
321
322
323
324
325

326
327
328


329
330

331

332
333

334
335
336
337

338
339
340
341
342
343
344
326
327
328
329
330
331
332

333
334


335
336


337
338
339
340

341
342


343
344
345
346
347
348
349
350
351







-
+

-
-
+
+
-
-
+

+

-
+

-
-

+







 *----------------------------------------------------------------------
 */

static Tcl_Obj *
GetWidgetDemoPath(
    Tcl_Interp *interp)
{
    Tcl_Obj *libpath, *result = NULL;
    Tcl_Obj *result = NULL;

    libpath = Tcl_GetVar2Ex(interp, "tk_library", NULL, TCL_GLOBAL_ONLY);
    if (libpath) {
    if (Tcl_EvalEx(interp, "::tk::pkgconfig get demodir,runtime",
		   -1, TCL_EVAL_GLOBAL) == TCL_OK) {
	Tcl_Obj *demo[2] = {	Tcl_NewStringObj("demos", 5),
				Tcl_NewStringObj("widget", 6) };
	Tcl_Obj *libpath, *demo[1] = { Tcl_NewStringObj("widget", 6) };

	libpath = Tcl_GetObjResult(interp);
	Tcl_IncrRefCount(libpath);
	result = Tcl_FSJoinToPath(libpath, 2, demo);
	result = Tcl_FSJoinToPath(libpath, 1, demo);
	Tcl_DecrRefCount(libpath);
    } else {
	Tcl_ResetResult(interp);
    }
    Tcl_ResetResult(interp);
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXHandleMenuSelect --
352
353
354
355
356
357
358
359
360
361



362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
359
360
361
362
363
364
365



366
367
368
369
370
371























372
373
374
375
376
377
378







-
-
-
+
+
+



-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







 *	None.
 *
 *----------------------------------------------------------------------
 */

void
TkMacOSXHandleMenuSelect(
    short theMenu,
    unsigned short theItem,
    int optionKeyPressed)
    TCL_UNUSED(short),
    TCL_UNUSED(unsigned short),
    TCL_UNUSED(int))
{
    Tcl_Panic("TkMacOSXHandleMenuSelect: Obsolete, no more Carbon!");
}

/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXInitMenus --
 *
 *	This procedure initializes the Macintosh menu bar.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void
TkMacOSXInitMenus(
    Tcl_Interp *interp)
{
    [NSApp _setupMenus];
}

/*
 *----------------------------------------------------------------------
 *
 * GenerateEditEvent --
 *
 *	Takes an edit menu item and posts the corasponding a virtual event to
411
412
413
414
415
416
417
418

419
420
421
422
423
424
425
395
396
397
398
399
400
401

402
403
404
405
406
407
408
409







-
+







    int x, y;
    TkWindow *winPtr = TkMacOSXGetTkWindow([NSApp keyWindow]);
    Tk_Window tkwin;

    if (!winPtr) {
	return;
    }
    tkwin = (Tk_Window) winPtr->dispPtr->focusPtr;
    tkwin = (Tk_Window)winPtr->dispPtr->focusPtr;
    if (!tkwin) {
	return;
    }
    bzero(&event, sizeof(XVirtualEvent));
    event.type = VirtualEvent;
    event.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
    event.send_event = false;
Changes to macosx/tkMacOSXMouseEvent.c.
1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
16

17
18
19
20
21
22
23
24
25
26

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

46
47


48
49
50
51
52
53
54


55
56

57
58
59
60
61
62





63
64
65
66
67
68
69
70
71
72





















73





74
75
76


77
78
79
80
81


82
83

84
85
86
87
88






89
90
91


92
93
94



95
96
97
98
99





100
101
102




103
104
105



106
107

108
109
110
111
112

113
114




115
116
117
118

119
120
121
122

123
124

125
126

127
128
129
130
131
132
133
134
135






136



137
138








139
140
141
142
143
144
145














146

147
148
149
150
151
152







153
154

155
156
157
158



159
160
161
162
163


164
165
166
167
168
169
170
171
172
173
174
175
176














177
178
179
180




181
182






183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201




202
203
204
205
206
207


























208
209
210
211
212
213

214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

46


47
48
49
50
51
52
53
54
55
56
57
58

59
60





61
62
63
64
65
66
67
68
69






70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90

91
92
93
94
95
96

97
98
99
100
101
102


103
104


105
106




107
108
109
110
111
112



113
114



115
116
117





118
119
120
121
122



123
124
125
126



127
128
129


130



131

132


133
134
135
136
137



138




139


140


141









142
143
144
145
146
147
148
149
150
151


152
153
154
155
156
157
158
159







160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175






176
177
178
179
180
181
182


183




184
185
186





187
188

189











190
191
192
193
194
195
196
197
198
199
200
201
202
203

204


205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232



233
234
235
236
237
238




239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269

270






















271
272
273
274
275
276
277






-
-
+
+







-
+










+


















-
+
-
-
+
+







+
+

-
+

-
-
-
-
-
+
+
+
+
+




-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+

-

+
+



-
-
+
+
-
-
+

-
-
-
-
+
+
+
+
+
+
-
-
-
+
+
-
-
-
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
+
+
+
+
-
-
-
+
+
+
-
-
+
-
-
-

-
+
-
-
+
+
+
+

-
-
-
+
-
-
-
-
+
-
-
+
-
-
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+

+
+
+
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
+
-
-
-
-
+
+
+
-
-
-
-
-
+
+
-

-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-

-
-
+
+
+
+


+
+
+
+
+
+
















-
-
-
+
+
+
+


-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







/*
 * 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 <[email protected]>
 * Copyright © 2001-2009 Apple Inc.
 * Copyright © 2005-2009 Daniel A. Steffen <[email protected]>
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tkMacOSXPrivate.h"
#include "tkMacOSXWm.h"
#include "tkMacOSXEvent.h"
#include "tkMacOSXInt.h"
#include "tkMacOSXDebug.h"
#include "tkMacOSXConstants.h"

typedef struct {
    unsigned int state;
    long delta;
    Window window;
    Point global;
    Point local;
} MouseEventData;

static Tk_Window captureWinPtr = NULL;	/* Current capture window; may be
					 * NULL. */

static int		GenerateButtonEvent(MouseEventData *medPtr);
static unsigned int	ButtonModifiers2State(UInt32 buttonState,
			    UInt32 keyModifiers);

#pragma mark TKApplication(TKMouseEvent)

enum {
    NSWindowWillMoveEventType = 20
};

/*
 * In OS X 10.6 an NSEvent of type NSMouseMoved would always have a non-Nil
 * window attribute pointing to the active window.  As of 10.8 this behavior
 * had changed.  The new behavior was that if the mouse were ever moved outside
 * of a window, all subsequent NSMouseMoved NSEvents would have a Nil window
 * attribute.  To work around this the TKApplication remembers the last non-Nil
 * attribute until the mouse returned to the window.  In 11.1 it changed again.
 * window that it received in a mouse event. If it receives an NSEvent with a
 * Nil window attribute then the saved window is used.
 * The window attribute can be non-nil, but referencing a window which does not
 * belong to the application.
 */

@implementation TKApplication(TKMouseEvent)
- (NSEvent *) tkProcessMouseEvent: (NSEvent *) theEvent
{
    NSWindow *eventWindow = [theEvent window];
    NSEventType eventType = [theEvent type];
    NSRect viewFrame = [[eventWindow contentView] frame];
    NSPoint location = [theEvent locationInWindow];
    TkWindow *winPtr = NULL, *grabWinPtr;
    Tk_Window tkwin;
    Tk_Window tkwin = NULL, capture, target;
    NSPoint local, global;
#if 0
    NSTrackingArea *trackingArea = nil;
    NSInteger eventNumber, clickCount, buttonNumber;
#endif
    [NSEvent stopPeriodicEvents];
    NSInteger button;
    Bool inTitleBar = NO;
    int win_x, win_y;
    unsigned int buttonState = 0;
    static int validPresses = 0, ignoredPresses = 0;

#ifdef TK_MAC_DEBUG_EVENTS
    TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, theEvent);
#endif
    switch (eventType) {
    case NSMouseEntered:
    case NSMouseExited:
    case NSCursorUpdate:
    case NSLeftMouseDown:
    case NSLeftMouseUp:

    /*
     * If this event is not for a Tk toplevel, it should just be passed up the
     * responder chain.  However, there is an exception for synthesized events,
     * which are used in testing.  Those events are recognized by having their
     * both the windowNumber and the eventNumber set to -1.
     */

    if (eventWindow && ![eventWindow isMemberOfClass:[TKWindow class]]) {
	if ([theEvent windowNumber] != -1 || [theEvent eventNumber] != -1)
	    return theEvent;
    }

    /*
     * Check if the event is located in the titlebar.
     */

    if (eventWindow) {
	inTitleBar = viewFrame.size.height < location.y;
    }

    case NSRightMouseDown:
    button = [theEvent buttonNumber] + Button1;
    if ((button & -2) == Button2) {
	button ^= 1; /* Swap buttons 2/3 */
    }
    switch (eventType) {
    case NSRightMouseUp:
    case NSOtherMouseDown:
    case NSOtherMouseUp:
	buttonState &= ~Tk_GetButtonMask(button);
	break;
    case NSLeftMouseDragged:
    case NSRightMouseDragged:
    case NSOtherMouseDragged:
    case NSMouseMoved:
    case NSTabletPoint:
    case NSRightMouseDown:
    case NSOtherMouseDown:
    case NSTabletProximity:
    case NSScrollWheel:
	buttonState |= Tk_GetButtonMask(button);
	break;
    default: /* Unrecognized mouse event. */
	return theEvent;
    }

    case NSMouseEntered:
	if ([eventWindow respondsToSelector:@selector(mouseInResizeArea)] &&
	    !inTitleBar) {
	    [(TKWindow *)eventWindow setMouseInResizeArea:YES];
	}
	break;
    /*
     * Compute the mouse position in Tk screen coordinates (global) and in the
     * Tk coordinates of its containing Tk Window (local). If a grab is in effect,
    case NSMouseExited:
	if ([eventWindow respondsToSelector:@selector(mouseInResizeArea)]) {
     * the local coordinates should be relative to the grab window.
     */

	    [(TKWindow *)eventWindow setMouseInResizeArea:NO];
	    break;
	}
    if (eventWindow) {
	local = [theEvent locationInWindow];
	global = [eventWindow tkConvertPointToScreen: local];
	tkwin = TkMacOSXGetCapture();
	if (tkwin) {
    case NSLeftMouseUp:
    case NSLeftMouseDown:
    case NSMouseMoved:
    case NSScrollWheel:
#if 0
	    winPtr = (TkWindow *) tkwin;
	    eventWindow = TkMacOSXDrawableWindow(winPtr->window);
	    if (eventWindow) {
    case NSCursorUpdate:
    case NSTabletPoint:
    case NSTabletProximity:
#endif
		local = [eventWindow tkConvertPointFromScreen: global];
	    } else {
		return theEvent;
	break;
    default: /* This type of event is ignored. */
	return theEvent;
	    }
	}
    }
	local.y = [eventWindow frame].size.height - local.y;
	global.y = TkMacOSXZeroScreenHeight() - global.y;
    } else {

	/*
    /*
	 * If the event has no NSWindow, the location is in screen coordinates.
	 */
     * Update the button state.  We ignore left button presses that start a
     * resize or occur in the title bar.  See tickets [d72abe6b54] and
     * [39cbacb9e8].
     */

	global = [theEvent locationInWindow];
	tkwin = TkMacOSXGetCapture();
	if (tkwin) {
    if (eventType == NSLeftMouseDown) {
	    winPtr = (TkWindow *) tkwin;
	    eventWindow = TkMacOSXDrawableWindow(winPtr->window);
	} else {
	    eventWindow = [NSApp mainWindow];
	if ([eventWindow respondsToSelector:@selector(mouseInResizeArea)] &&
	}
	if (!eventWindow) {
	    [(TKWindow *) eventWindow mouseInResizeArea]) {
	    return theEvent;
	}

	local = [eventWindow tkConvertPointFromScreen: global];
	local.y = [eventWindow frame].size.height - local.y;
	global.y = TkMacOSXZeroScreenHeight() - global.y;
    }

    /*
     * If we still don't have a window, try using the toplevel that
     * manages the NSWindow.
     */
	    /*
	     * When the left button is pressed in the resize area, we receive
	     * NSMouseDown, but when it is released we do not receive
	     * NSMouseUp.  So ignore the event and clear the button state but
	     * do not change the ignoredPresses count.
	     */

	    buttonState &= ~Tk_GetButtonMask(Button1);
	    return theEvent;
	}
    if (!tkwin) {
	winPtr = TkMacOSXGetTkWindow(eventWindow);
	if (inTitleBar) {
	    ignoredPresses++;
	    return theEvent;
	}
	validPresses++;
	buttonState |= Tk_GetButtonMask(Button1);
    }
    if (eventType == NSLeftMouseUp) {
	tkwin = (Tk_Window) winPtr;
    }
    if (!tkwin) {

	/*
	 * We can't find a window for this event.  We have to ignore it.
	 */
	if (ignoredPresses > 0) {
	    ignoredPresses--;
	} else if (validPresses > 0) {
	    validPresses--;
	}
	if (validPresses == 0) {
	    buttonState &= ~Tk_GetButtonMask(Button1);
	}
    }

    /*
     * Find an appropriate NSWindow to attach to this event, and its
     * associated Tk window.
     */

    capture = TkpGetCapture();
#ifdef TK_MAC_DEBUG_EVENTS
	TkMacOSXDbgMsg("tkwin == NULL");
#endif
	return theEvent;
    }

    if (capture) {
	winPtr = (TkWindow *) capture;
	eventWindow = TkMacOSXGetNSWindowForDrawable(winPtr->window);
	if (!eventWindow) {
	    return theEvent;
	}
    } else {
    /*
     * Ignore the event if a local grab is in effect and the Tk event window is
	if (eventWindow) {
     * not in the grabber's subtree.
     */

    grabWinPtr = winPtr->dispPtr->grabWinPtr;
	    winPtr = TkMacOSXGetTkWindow(eventWindow);
	}
	if (!winPtr) {
    if (grabWinPtr && /* There is a grab in effect ... */
	!winPtr->dispPtr->grabFlags && /* and it is a local grab ... */
	grabWinPtr->mainPtr == winPtr->mainPtr){ /* in the same application. */
	Tk_Window tkwin2, tkEventWindow = Tk_CoordsToWindow(global.x, global.y, tkwin);
	if (!tkEventWindow) {
	    eventWindow = [NSApp mainWindow];
	    winPtr = TkMacOSXGetTkWindow(eventWindow);
	    return theEvent;
	}
	for (tkwin2 = tkEventWindow;
	     !Tk_IsTopLevel(tkwin2);
	     tkwin2 = Tk_Parent(tkwin2)) {
	    if (tkwin2 == (Tk_Window) grabWinPtr) {
		break;
	    }
	}
	if (tkwin2 != (Tk_Window) grabWinPtr) {
	    return theEvent;
	}
    }
    }
    if (!winPtr) {

	/*
	 * We couldn't find a Tk window for this event.  We have to ignore it.
	 */

#ifdef TK_MAC_DEBUG_EVENTS
	TkMacOSXDbgMsg("Event received with no Tk window.");
#endif
	return theEvent;
    }
    tkwin = (Tk_Window) winPtr;


    /*
     * Convert local from NSWindow flipped coordinates to the toplevel's
     * coordinates.
     * Compute the mouse position in local (window) and global (screen)
     * coordinates.  These are Tk coordinates, meaning that the local origin is
     * at the top left corner of the containing toplevel and the global origin
     * is at top left corner of the primary screen.
     */

    global = [NSEvent mouseLocation];
    local = [eventWindow tkConvertPointFromScreen: global];
    global.x = floor(global.x);
    global.y = floor(TkMacOSXZeroScreenHeight() - global.y);
    local.x = floor(local.x);
    local.y = floor([eventWindow frame].size.height - local.y);
    if (Tk_IsEmbedded(winPtr)) {
	TkWindow *contPtr = TkpGetOtherWindow(winPtr);
	if (Tk_IsTopLevel(contPtr)) {
	    local.x -= contPtr->wmInfoPtr->xInParent;
	    local.y -= contPtr->wmInfoPtr->yInParent;
	} else {
	    TkWindow *topPtr = TkMacOSXGetHostToplevel(winPtr)->winPtr;
	    local.x -= (topPtr->wmInfoPtr->xInParent + contPtr->changes.x);
	    local.y -= (topPtr->wmInfoPtr->yInParent + contPtr->changes.y);
	}
    } else {
	local.x -= winPtr->wmInfoPtr->xInParent;
	local.y -= winPtr->wmInfoPtr->yInParent;
    }

    /*
     * Use the toplevel coordinates to find the containing Tk window.  Then
     * convert local into the coordinates of that window.  (The converted
     * local coordinates are only needed for scrollwheel events.)
     * Use the local coordinates to find the Tk window which should receive
     * this event.  Also convert local into the coordinates of that window.
     * (The converted local coordinates are only needed for scrollwheel
     * events.)
     */

    int win_x, win_y;
    tkwin = Tk_TopCoordsToWindow(tkwin, local.x, local.y, &win_x, &win_y);
    local.x = win_x;
    local.y = win_y;
    target = Tk_TopCoordsToWindow(tkwin, local.x, local.y, &win_x, &win_y);

    /*
     * Ignore the event if a local grab is in effect and the Tk window is
     * not in the grabber's subtree.
     */

    grabWinPtr = winPtr->dispPtr->grabWinPtr;
    if (grabWinPtr && /* There is a grab in effect ... */
	!winPtr->dispPtr->grabFlags && /* and it is a local grab ... */
	grabWinPtr->mainPtr == winPtr->mainPtr){ /* in the same application. */
	Tk_Window tkwin2;
	if (!target) {
	    return theEvent;
	}
	for (tkwin2 = target;
	     !Tk_IsTopLevel(tkwin2);
	     tkwin2 = Tk_Parent(tkwin2)) {
	    if (tkwin2 == (Tk_Window)grabWinPtr) {
		break;
	    }
	}
	if (tkwin2 != (Tk_Window)grabWinPtr) {
	    return theEvent;
	}
    }

    /*
     *  Generate an XEvent for this mouse event.
     */

    unsigned int state = 0;
    unsigned int state = buttonState;
    int button = [theEvent buttonNumber] + Button1;
    EventRef eventRef = (EventRef)[theEvent eventRef];
    UInt32 buttons;
    OSStatus err = GetEventParameter(eventRef, kEventParamMouseChord,
	    typeUInt32, NULL, sizeof(UInt32), NULL, &buttons);

    if (err == noErr) {
	state |= (buttons & 0x1F) * Button1Mask;
    } else if (button <= Button5) {
	switch (eventType) {
	case NSLeftMouseDown:
	case NSRightMouseDown:
	case NSLeftMouseDragged:
	case NSRightMouseDragged:
	case NSOtherMouseDown:
	    state |= TkGetButtonMask(button);
	    break;
	default:
	    break;
	}
    }

    NSUInteger modifiers = [theEvent modifierFlags];

    if (modifiers & NSAlphaShiftKeyMask) {
	state |= LockMask;
    }
    if (modifiers & NSShiftKeyMask) {
	state |= ShiftMask;
256
257
258
259
260
261
262
263



264
265
266
267
268


269

270

271


272
273
274
275
276
277
278
279
280
281
282
283


284
285
286
287
288


289
290

291
292
293
294
295

296
297
298
299

300
301
302
303
304

305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
291
292
293
294
295
296
297

298
299
300
301
302
303


304
305
306
307

308
309
310
311
312
313
314
315
316




317


318
319
320
321
322


323
324
325

326
327


328

329
330
331
332

333
334


335

336
337
338
339
340
341
342
343
344
345




























346
347
348
349
350
351
352







-
+
+
+



-
-
+
+

+
-
+

+
+





-
-
-
-

-
-
+
+



-
-
+
+

-
+

-
-

-
+



-
+

-
-

-
+









-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







    if (modifiers & NSFunctionKeyMask) {
	state |= Mod4Mask;
    }

    if (eventType != NSScrollWheel) {

	/*
	 * For normal mouse events, Tk_UpdatePointer will send the XEvent.
	 * For normal mouse events, Tk_UpdatePointer will send the appropriate
	 * XEvents using its cached state information.  Unfortunately, it will
	 * also recompute the local coordinates.
	 */

#ifdef TK_MAC_DEBUG_EVENTS
	TKLog(@"UpdatePointer %p x %f.0 y %f.0 %d",
		tkwin, global.x, global.y, state);
	TKLog(@"UpdatePointer %p x %.1f y %.1f %d",
		target, global.x, global.y, state);
#endif

	Tk_UpdatePointer(tkwin, global.x, global.y, state);
	Tk_UpdatePointer(target, global.x, global.y, state);
    } else {
	CGFloat delta;
	XEvent xEvent;

	/*
	 * For scroll wheel events we need to send the XEvent here.
	 */

	CGFloat delta;
	int coarseDelta;
	XEvent xEvent;

	xEvent.type = MouseWheelEvent;
	xEvent.xbutton.x = local.x;
	xEvent.xbutton.y = local.y;
	xEvent.xbutton.x = win_x;
	xEvent.xbutton.y = win_y;
	xEvent.xbutton.x_root = global.x;
	xEvent.xbutton.y_root = global.y;
	xEvent.xany.send_event = false;
	xEvent.xany.display = Tk_Display(tkwin);
	xEvent.xany.window = Tk_WindowId(tkwin);
	xEvent.xany.display = Tk_Display(target);
	xEvent.xany.window = Tk_WindowId(target);

	delta = [theEvent deltaY];
	delta = [theEvent deltaY] * 120;
	if (delta != 0.0) {
	    coarseDelta = (delta > -1.0 && delta < 1.0) ?
		    (signbit(delta) ? -1 : 1) : lround(delta);
	    xEvent.xbutton.state = state;
	    xEvent.xkey.keycode = coarseDelta;
	    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];
	delta = [theEvent deltaX] * 120;
	if (delta != 0.0) {
	    coarseDelta = (delta > -1.0 && delta < 1.0) ?
		    (signbit(delta) ? -1 : 1) : lround(delta);
	    xEvent.xbutton.state = state | ShiftMask;
	    xEvent.xkey.keycode = coarseDelta;
	    xEvent.xkey.keycode = (delta > 0) ? ceil(delta) : floor(delta);
	    xEvent.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
	    Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL);
	}
    }
    return theEvent;
}
@end

#pragma mark -

/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXKeyModifiers --
 *
 *	Returns the current state of the modifier keys.
 *
 * Results:
 *	An OS Modifier state.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

EventModifiers
TkMacOSXModifierState(void)
{
    UInt32 keyModifiers;
    int isFrontProcess = (GetCurrentEvent() && Tk_MacOSXIsAppInFront());

    keyModifiers = isFrontProcess ? GetCurrentEventKeyModifiers() :
	    GetCurrentKeyModifiers();

    return (EventModifiers) (keyModifiers & USHRT_MAX);
}

/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXButtonKeyState --
 *
 *	Returns the current state of the button & modifier keys.
392
393
394
395
396
397
398
399

400
401
402










403
404
405
406
407
408
409
396
397
398
399
400
401
402

403
404
405

406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422







-
+


-
+
+
+
+
+
+
+
+
+
+







ButtonModifiers2State(
    UInt32 buttonState,
    UInt32 keyModifiers)
{
    unsigned int state;

    /*
     * Tk on OSX supports at most 5 buttons.
     * Tk on OSX supports at most 9 buttons.
     */

    state = (buttonState & 0x1F) * Button1Mask;
    state = (buttonState & 0x079) * Button1Mask;
	/* Handle swapped buttons 2/3 */
	if (buttonState & 0x02) {
	    state |= Button3Mask;
	}
	if (buttonState & 0x04) {
	    state |= Button2Mask;
	}
	/* Handle buttons 8/9 */
    state |= (buttonState & 0x180) * (Button8Mask >> 7);

    if (keyModifiers & alphaLock) {
	state |= LockMask;
    }
    if (keyModifiers & shiftKey) {
	state |= ShiftMask;
    }
455
456
457
458
459
460
461



462
463
464
465
466
467
468


469
470
471
472
473
474
475
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482


483
484
485
486
487
488
489
490
491







+
+
+





-
-
+
+







    int *root_y_return,
    int *win_x_return,
    int *win_y_return,
    unsigned int *mask_return)
{
    int getGlobal = (root_x_return && root_y_return);
    int getLocal = (win_x_return && win_y_return && w != None);
    (void)display;
    (void)root_return;
    (void)child_return;

    if (getGlobal || getLocal) {
	NSPoint global = [NSEvent mouseLocation];

	if (getLocal) {
	    MacDrawable *macWin = (MacDrawable *) w;
	    NSWindow *win = TkMacOSXDrawableWindow(w);
	    MacDrawable *macWin = (MacDrawable *)w;
	    NSWindow *win = TkMacOSXGetNSWindowForDrawable(w);

	    if (win) {
		NSPoint local;

		local = [win tkConvertPointFromScreen:global];
		local.y = [win frame].size.height - local.y;
		if (macWin->winPtr && macWin->winPtr->wmInfoPtr) {
499
500
501
502
503
504
505
506

507
508
509
510
511
512
513
515
516
517
518
519
520
521

522
523
524
525
526
527
528
529







-
+







 *	This procedure generates an X button event for the current pointer
 *	state as reported by XQueryPointer().
 *
 * Results:
 *	True if event(s) are generated - false otherwise.
 *
 * Side effects:
 *	Additional events may be place on the Tk event queue. Grab state may
 *	Additional events may be placed on the Tk event queue. Grab state may
 *	also change.
 *
 *----------------------------------------------------------------------
 */

MODULE_SCOPE int
TkGenerateButtonEventForXPointer(
537
538
539
540
541
542
543
544

545
546
547
548
549
550
551
552
553
554
555
556
557
558


559
560
561
562
563
564
565
553
554
555
556
557
558
559

560
561
562
563
564
565
566
567
568
569
570
571
572


573
574
575
576
577
578
579
580
581







-
+












-
-
+
+







 *	generates the appropriate X button event. It also handles the state
 *	changes needed to implement implicit grabs.
 *
 * Results:
 *	True if event(s) are generated, false otherwise.
 *
 * Side effects:
 *	Additional events may be place on the Tk event queue. Grab state may
 *	Additional events may be placed on the Tk event queue. Grab state may
 *	also change.
 *
 *----------------------------------------------------------------------
 */

int
TkGenerateButtonEvent(
    int x,			/* X location of mouse, */
    int y,			/* Y location of mouse. */
    Window window,		/* X Window containing button event. */
    unsigned int state)		/* Button Key state suitable for X event. */
{
    MacDrawable *macWin = (MacDrawable *) window;
    NSWindow *win = TkMacOSXDrawableWindow(window);
    MacDrawable *macWin = (MacDrawable *)window;
    NSWindow *win = TkMacOSXGetNSWindowForDrawable(window);
    MouseEventData med;

    bzero(&med, sizeof(MouseEventData));
    med.state = state;
    med.window = window;
    med.global.h = x;
    med.global.v = y;
589
590
591
592
593
594
595
596

597
598
599
600
601
602
603
604
605
606
607
608
609
610

611
612
613
614
615
616
617
618
619
620
621
622

623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638

















639
640
641
642
643
644
645
605
606
607
608
609
610
611

612
613
614
615
616
617
618
619
620
621
622
623
624
625

626
627
628
629
630
631
632
633
634
635
636
637

638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678







-
+













-
+











-
+
















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







 *	Generate an X button event from a MouseEventData structure. Handles
 *	the state changes needed to implement implicit grabs.
 *
 * Results:
 *	True if event(s) are generated - false otherwise.
 *
 * Side effects:
 *	Additional events may be place on the Tk event queue. Grab state may
 *	Additional events may be placed on the Tk event queue. Grab state may
 *	also change.
 *
 *----------------------------------------------------------------------
 */

static int
GenerateButtonEvent(
    MouseEventData *medPtr)
{
    Tk_Window tkwin;
    int dummy;
    TkDisplay *dispPtr;

#if UNUSED
#ifdef UNUSED

    /*
     * ButtonDown events will always occur in the front window. ButtonUp
     * events, however, may occur anywhere on the screen. ButtonUp events
     * should only be sent to Tk if in the front window or during an implicit
     * grab.
     */

    if ((medPtr->activeNonFloating == NULL)
	    || ((!(TkpIsWindowFloating(medPtr->whichWin))
	    && (medPtr->activeNonFloating != medPtr->whichWin))
	    && TkMacOSXGetCapture() == NULL)) {
	    && TkpGetCapture() == NULL)) {
	return false;
    }
#endif

    dispPtr = TkGetDisplayList();
    tkwin = Tk_IdToWindow(dispPtr->display, medPtr->window);

    if (tkwin != NULL) {
	tkwin = Tk_TopCoordsToWindow(tkwin, medPtr->local.h, medPtr->local.v,
		&dummy, &dummy);
    }

    Tk_UpdatePointer(tkwin, medPtr->global.h, medPtr->global.v, medPtr->state);
    return true;
}

/*
 *----------------------------------------------------------------------
 *
 * TkpWarpPointer --
 *
 *	Move the mouse cursor to the screen location specified by the warpX and
 *	warpY fields of a TkDisplay.
 *
 * Results:
 *	None
 *
 * Side effects:
 *	The mouse cursor is moved.
 *
 *----------------------------------------------------------------------
 */

void
TkpWarpPointer(
    TkDisplay *dispPtr)
{
    CGPoint pt;

    if (dispPtr->warpWindow) {
676
677
678
679
680
681
682
683
684

685
686
687
688
689
690

691
692
693
694
695
696
697
698
699
700
701
702

703
704
705
706
707
708
709
710
711
712
713
714
709
710
711
712
713
714
715


716
717
718
719
720
721

722
723
724
725
726
727
728
729
730
731
732
733

734
735
736
737
738
739
740
741
742
743
744
745
746







-
-
+





-
+











-
+












void
TkpSetCapture(
    TkWindow *winPtr)		/* Capture window, or NULL. */
{
    while (winPtr && !Tk_IsTopLevel(winPtr)) {
	winPtr = winPtr->parentPtr;
    }
    [NSEvent stopPeriodicEvents];
    captureWinPtr = (Tk_Window) winPtr;
    captureWinPtr = (Tk_Window)winPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXGetCapture --
 * TkpGetCapture --
 *
 * Results:
 *	Returns the current grab window
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

Tk_Window
TkMacOSXGetCapture(void)
TkpGetCapture(void)
{
    return captureWinPtr;
}

/*
 * Local Variables:
 * mode: objc
 * c-basic-offset: 4
 * fill-column: 79
 * coding: utf-8
 * End:
 */
Changes to macosx/tkMacOSXNotify.c.
1
2
3
4
5
6
7
8
9
10




11
12
13
14
15

16
17

18
19
20
21
22
23
24
25
26
1
2
3
4
5
6




7
8
9
10
11
12
13
14
15
16
17

18
19

20
21
22
23
24
25
26






-
-
-
-
+
+
+
+





+

-
+

-







/*
 * 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 <[email protected]>
 * Copyright 2015 Marc Culler.
 * Copyright © 1995-1997 Sun Microsystems, Inc.
 * Copyright © 2001-2009, Apple Inc.
 * Copyright © 2005-2009 Daniel A. Steffen <[email protected]>
 * 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 <tclInt.h>
#include "tkMacOSXPrivate.h"
#include "tkMacOSXEvent.h"
#include "tkMacOSXInt.h"
#include "tkMacOSXConstants.h"
#include <tclInt.h>
#import <objc/objc-auto.h>

/* This is not used for anything at the moment. */
typedef struct ThreadSpecificData {
    int initialized;
} ThreadSpecificData;
static Tcl_ThreadDataKey dataKey;
137
138
139
140
141
142
143




































144
145

146
147
148
149








150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169

170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213

214
215
216
217
218
219
220


221
222
223
224
225
226
227







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


+




+
+
+
+
+
+
+
+



















-
+






-
-







/*
 * Since the contentView is the first responder for a Tk Window, it is
 * responsible for sending events up the responder chain.  We also check the
 * pasteboard here.
 */
- (void) sendEvent: (NSEvent *) theEvent
{

    /*
     * Workaround for an Apple bug.  When an accented character is selected
     * from an NSTextInputClient popup character viewer with the mouse, Apple
     * sends an event of type NSAppKitDefined and subtype 21. If that event is
     * sent up the responder chain it causes Apple to print a warning to the
     * console log and, extremely obnoxiously, also to stderr, which says
     * "Window move completed without beginning."  Apparently they are sending
     * the "move completed" event without having sent the "move began" event of
     * subtype 20, and then announcing their error on our stderr.  Also, of
     * course, no movement is occurring.  The popup is not movable and is just
     * being closed.  The bug has been reported to Apple.  If they ever fix it,
     * this block should be removed.
     */

#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101500
    if ([theEvent type] == NSAppKitDefined) {
	static Bool aWindowIsMoving = NO;
	switch([theEvent subtype]) {
	case 20:
	    aWindowIsMoving = YES;
	    break;
	case 21:
	    if (aWindowIsMoving) {
		aWindowIsMoving = NO;
		break;
	    } else {
		// printf("Bug!!!!\n");
		return;
	    }
	default:
	    break;
	}
    }
#endif

    [super sendEvent:theEvent];
    [NSApp tkCheckPasteboard];

#ifdef TK_MAC_DEBUG_EVENTS
    fprintf(stderr, "Sending event of type %d\n", (int)[theEvent type]);
    DebugPrintQueue();
#endif

}

- (void) _runBackgroundLoop
{
    while(Tcl_DoOneEvent(TCL_IDLE_EVENTS|TCL_TIMER_EVENTS|TCL_DONT_WAIT)){
	TkMacOSXDrawAllViews(NULL);
    }
}
@end

#pragma mark -

/*
 *----------------------------------------------------------------------
 *
 * GetRunLoopMode --
 *
 * Results:
 *	RunLoop mode that should be passed to -nextEventMatchingMask:
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

NSString *
static NSString *
GetRunLoopMode(NSModalSession modalSession)
{
    NSString *runLoopMode = nil;

    if (modalSession) {
	runLoopMode = NSModalPanelRunLoopMode;
    } else if (TkMacOSXGetCapture()) {
	runLoopMode = NSEventTrackingRunLoopMode;
    }
    if (!runLoopMode) {
	runLoopMode = [[NSRunLoop currentRunLoop] currentMode];
    }
    if (!runLoopMode) {
	runLoopMode = NSDefaultRunLoopMode;
    }
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
265
266
267
268
269
270
271

272
273
274
275
276
277
278







-








		Tcl_Panic("Tk_MacOSXSetupTkNotifier: %s",
		    "first [load] of TkAqua has to occur in the main thread!");
	    }
	    Tcl_CreateEventSource(TkMacOSXEventsSetupProc,
		    TkMacOSXEventsCheckProc, NULL);
	    TkCreateExitHandler(TkMacOSXNotifyExitHandler, NULL);
	    Tcl_SetServiceMode(TCL_SERVICE_ALL);
	    TclMacOSXNotifierAddRunLoopMode(NSEventTrackingRunLoopMode);
	    TclMacOSXNotifierAddRunLoopMode(NSModalPanelRunLoopMode);
	}
    }
}

/*
248
249
250
251
252
253
254
255

256

257
258
259
260
261
262
263
264
265
266
















































































267
268
269
270

271
272
273
274
275
276
277
278
279

280
281


282
283
284
285



286












287
288

289
290
291
292

293
294
295
296
297
298
299

300
301
302
303
304









305
306
307
308
309
310
311

312
313

314
315


316
317

318
319
320
321




322
323

324
325
326
327

328
329
330
331
332
333
334
290
291
292
293
294
295
296

297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392

393
394
395
396
397
398
399
400
401
402
403


404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426

427
428
429

430
431
432
433
434
435
436
437

438
439
440



441
442
443
444
445
446
447
448
449
450
451
452
453
454
455

456


457


458
459


460
461
462


463
464
465
466


467
468
469


470
471
472
473
474
475
476
477







-
+

+










+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
+









+
-
-
+
+




+
+
+

+
+
+
+
+
+
+
+
+
+
+
+

-
+


-

+






-
+


-
-
-
+
+
+
+
+
+
+
+
+






-
+
-
-
+
-
-
+
+
-
-
+


-
-
+
+
+
+
-
-
+


-
-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
TkMacOSXNotifyExitHandler(
    ClientData clientData)	/* Not used. */
    ClientData dummy)	/* Not used. */
{
    (void)dummy;
    TSD_INIT();

    Tcl_DeleteEventSource(TkMacOSXEventsSetupProc,
	    TkMacOSXEventsCheckProc, NULL);
    tsdPtr->initialized = 0;
}

/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXDrawAllViews --
 *
 *       This static function is meant to be run as an idle task.  It attempts
 *       to redraw all views which have the tkNeedsDisplay property set to YES.
 *       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.
 *
 *       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
 *       by drawRect.
 *
 *       If this function is called directly with non-NULL clientData parameter
 *       then the int which it references will be set to the number of windows
 *       that need display, but the needsDisplay property of those windows will
 *       not be changed.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Parts of windows may get redrawn.
 *
 *----------------------------------------------------------------------
 */

void
TkMacOSXDrawAllViews(
    ClientData clientData)
{
       int count = 0, *dirtyCount = (int *)clientData;

    for (NSWindow *window in [NSApp windows]) {
	if ([[window contentView] isMemberOfClass:[TKContentView class]]) {
	    TKContentView *view = [window contentView];
	    if ([view tkNeedsDisplay]) {
		count++;
		if (dirtyCount) {
		   continue;
		}
		[view setNeedsDisplayInRect:[view tkDirtyRect]];
	    }
	} else {
	    [window displayIfNeeded];
	}
    }
    if (dirtyCount) {
    	*dirtyCount = count;
    }
    [NSApp nextEventMatchingMask:NSAnyEventMask
		       untilDate:[NSDate distantPast]
			  inMode:GetRunLoopMode(TkMacOSXGetModalSession())
			 dequeue:NO];
    for (NSWindow *window in [NSApp windows]) {
	if ([[window contentView] isMemberOfClass:[TKContentView class]]) {
	    TKContentView *view = [window contentView];

	    /*
	     * If we did not run drawRect, we set needsDisplay back to NO.
	     * Note that if drawRect did run it may have added to Tk's dirty
	     * rect, due to attempts to draw outside of drawRect's dirty rect.
	     */

	    if ([view needsDisplay]) {
		[view setNeedsDisplay: NO];
	    }
	}
    }
    [NSApp setNeedsToDraw:NO];
}

/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXEventsSetupProc --
 *
 *	This procedure implements the setup part of the MacOSX event source. It
 *	is invoked by Tcl_DoOneEvent before calling TkMacOSXEventsProc to
 *	is invoked by Tcl_DoOneEvent before calling TkMacOSXEventsCheckProc to
 *	process all queued NSEvents.  In our case, all we need to do is to set
 *	the Tcl MaxBlockTime to 0 before starting the loop to process all
 *	queued NSEvents.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *
 *	If NSEvents are queued, or if there is any drawing that needs to be
 *	If NSEvents are queued, then the maximum block time will be set to 0 to
 *	ensure that control returns immediately to Tcl.
 *      done, then the maximum block time will be set to 0 to ensure that
 *      Tcl_WaitForEvent returns immediately.
 *
 *----------------------------------------------------------------------
 */

#define TICK 200
static Tcl_TimerToken ticker = NULL;

static void
Heartbeat(
    TCL_UNUSED(ClientData))
{

    if (ticker) {
	ticker = Tcl_CreateTimerHandler(TICK, Heartbeat, NULL);
    }
}

static const Tcl_Time zeroBlockTime = { 0, 0 };

static void
TkMacOSXEventsSetupProc(
    ClientData clientData,
    ClientData dummy,
    int flags)
{
    static Bool havePeriodicEvents = NO;
    NSString *runloopMode = [[NSRunLoop currentRunLoop] currentMode];
    (void)dummy;

    /*
     * runloopMode will be nil if we are in a Tcl event loop.
     */

    if (flags & TCL_WINDOW_EVENTS && !runloopMode) {
	static const Tcl_Time zeroBlockTime = { 0, 0 };

	[NSApp _resetAutoreleasePool];

	/*
	 * Call this with dequeue=NO -- just checking if the queue is empty.
	 */
 	/*
	 * After calling this setup proc, Tcl_DoOneEvent will call
 	 * 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 heartbeat.
  	 */

	NSEvent *currentEvent =
	        [NSApp nextEventMatchingMask:NSAnyEventMask
			untilDate:[NSDate distantPast]
			inMode:GetRunLoopMode(TkMacOSXGetModalSession())
			dequeue:NO];
	if (currentEvent) {
	if ((currentEvent) || [NSApp needsToDraw] ) {
	    if (currentEvent.type > 0) {
		Tcl_SetMaxBlockTime(&zeroBlockTime);
	    Tcl_SetMaxBlockTime(&zeroBlockTime);
		[NSEvent stopPeriodicEvents];
		havePeriodicEvents = NO;
	    Tcl_DeleteTimerHandler(ticker);
	    ticker = NULL;
	    }
	} else if (!havePeriodicEvents){
	} else if (ticker == NULL) {

	    /*
	     * When the user is not generating events we schedule a "hearbeat"
	     * event to fire every 0.1 seconds.  This helps to make the vwait
	     * When the user is not generating events we schedule a "heartbeat"
	     * TimerHandler to fire every 200 milliseconds.  The handler does
	     * nothing, but when its timer fires it causes Tcl_WaitForEvent to
	     * return.  This helps avoid hangs when calling vwait during the
	     * command more responsive when there is no user input, e.g. when
	     * running the test suite.
	     * non-regression tests.
	     */

	    havePeriodicEvents = YES;
	    [NSEvent startPeriodicEventsAfterDelay:0.0 withPeriod:0.1];
	    ticker = Tcl_CreateTimerHandler(TICK, Heartbeat, NULL);
	}
    }
}

/*
 *----------------------------------------------------------------------
 *
344
345
346
347
348
349
350
351

352
353
354

355
356
357
358
359
360
361
487
488
489
490
491
492
493

494
495
496
497
498
499
500
501
502
503
504
505







-
+



+







 *	NSevents are used to generate X events, which are added to the Tcl
 *      event queue.
 *
 *----------------------------------------------------------------------
 */
static void
TkMacOSXEventsCheckProc(
    ClientData clientData,
    TCL_UNUSED(ClientData),
    int flags)
{
    NSString *runloopMode = [[NSRunLoop currentRunLoop] currentMode];
    int eventsFound = 0;

    /*
     * runloopMode will be nil if we are in a Tcl event loop.
     */

    if (flags & TCL_WINDOW_EVENTS && !runloopMode) {
	NSEvent *currentEvent = nil;
386
387
388
389
390
391
392

393
394
395
396
397
398
399
400


401
402
403

404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419



















420
421
422
423
424
425
426
427
428
429
430
530
531
532
533
534
535
536
537
538
539
540
541

542

543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595







+




-

-

+
+



+
















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+











		break;
	    }
	    currentEvent = [NSApp nextEventMatchingMask:NSAnyEventMask
		    untilDate:[NSDate distantPast]
		    inMode:GetRunLoopMode(modalSession)
		    dequeue:YES];
	    if (currentEvent) {

		/*
		 * Generate Xevents.
		 */

		int oldServiceMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
		NSEvent *processedEvent = [NSApp tkProcessEvent:currentEvent];
		Tcl_SetServiceMode(oldServiceMode);
		if (processedEvent) {
		    eventsFound++;

#ifdef TK_MAC_DEBUG_EVENTS
		    TKLog(@"   event: %@", currentEvent);
#endif

		    if (modalSession) {
			[NSApp _modalSession:modalSession sendEvent:currentEvent];
		    } else {
			[NSApp sendEvent:currentEvent];
		    }
		}
	    } else {
		break;
	    }
	} while (1);

	/*
	 * Now we can unlock the pool.
	 */

	[NSApp _unlockAutoreleasePool];

	/*
	 * Add an idle task to the end of the idle queue which will redisplay
	 * all of our dirty windows.  We want this to happen after all other
	 * idle tasks have run so that all widgets will be configured before
	 * they are displayed.  The drawRect method "borrows" the idle queue
	 * while drawing views. That is, it sends expose events which cause
	 * display procs to be posted as idle tasks and then runs an inner
	 * event loop to processes those idle tasks.  We are trying to arrange
	 * for the idle queue to be empty when it starts that process and empty
	 * when it finishes.
	 */

	int dirtyCount = 0;
	TkMacOSXDrawAllViews(&dirtyCount);
	if (dirtyCount > 0) {
	    Tcl_CancelIdleCall(TkMacOSXDrawAllViews, NULL);
	    Tcl_DoWhenIdle(TkMacOSXDrawAllViews, NULL);
	}
    }
}

/*
 * Local Variables:
 * mode: objc
 * c-basic-offset: 4
 * fill-column: 79
 * coding: utf-8
 * End:
 */
Changes to macosx/tkMacOSXPort.h.
1
2
3
4

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27









28
29
30
31
32
33
34
1
2
3

4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19








20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35



-
+















-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+







/*
 * tkMacOSXPort.h --
 *
 *	This file is included by all of the Tk C files. It contains
 *	This file is included by all of the Tk C files.  It contains
 *	information that may be configuration-dependent, such as
 *	#includes for system include files and a few other things.
 *
 * Copyright (c) 1994-1996 Sun Microsystems, Inc.
 * Copyright 2001-2009, Apple Inc.
 * Copyright (c) 2005-2009 Daniel A. Steffen <[email protected]>
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#ifndef _TKMACPORT
#define _TKMACPORT

#include <stdio.h>
#include <ctype.h>
#include <fcntl.h>
#include <limits.h>
#include <math.h>
#include <pwd.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <pwd.h>
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <ctype.h>
#include <math.h>
#include <string.h>
#include <limits.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/file.h>
#ifdef HAVE_SYS_SELECT_H
#   include <sys/select.h>
#endif
#include <sys/stat.h>
#ifndef _TCL
44
45
46
47
48
49
50



51
52
53
54
55
56
57
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61







+
+
+







#	include <time.h>
#   endif
#endif
#if HAVE_INTTYPES_H
#    include <inttypes.h>
#endif
#include <unistd.h>
#if defined(__GNUC__) && !defined(__cplusplus)
#   pragma GCC diagnostic ignored "-Wc++-compat"
#endif
#include <X11/Xlib.h>
#include <X11/cursorfont.h>
#include <X11/keysym.h>
#include <X11/Xatom.h>
#include <X11/Xfuncproto.h>
#include <X11/Xutil.h>

102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160


161
162
163
164
165
166








167
168
169
170
171



172
173
174
175
176
177

178
179

180
181



182
183



184



185
186
106
107
108
109
110
111
112




















113
114
115
116
117
118
119
120
121











122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137




138
139
140
141
142
143
144
145
146
147



148
149
150
151
152




153
154
155
156


157
158
159


160
161
162
163
164
165
166
167
168







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-









-
-
-
-
-
-
-
-
-
-
-












+
+


-
-
-
-
+
+
+
+
+
+
+
+


-
-
-
+
+
+


-
-
-
-
+


+
-
-
+
+
+
-
-
+
+
+

+
+
+



/*
 * The following define causes Tk to use its internal keysym hash table
 */

#define REDO_KEYSYM_LOOKUP

/*
 * Defines for X functions that are used by Tk but are treated as
 * no-op functions on the Macintosh.
 */

#undef XFlush
#define XFlush(display) (0)
#undef XFree
#define XFree(data) (((data) != NULL) ? (ckfree(data),0) : 0)
#undef XGrabServer
#define XGrabServer(display) (0)
#undef XNoOp
#define XNoOp(display) (display->request++,0)
#undef XUngrabServer
#define XUngrabServer(display) (0)
#undef XSynchronize
#define XSynchronize(display, onoff) (display->request++,NULL)
#undef XVisualIDFromVisual
#define XVisualIDFromVisual(visual) (visual->visualid)

/*
 * The following functions are not used on the Mac, so we stub them out.
 */

#define TkpCmapStressed(tkwin,colormap) (0)
#define TkpFreeColor(tkColPtr)
#define TkSetPixmapColormap(p,c) {}
#define TkpSync(display)

/*
 * TkMacOSXGetCapture is a legacy function used on the Mac. When fixing
 * [943d5ebe51], TkpGetCapture was added to the Windows port. Both
 * are actually the same feature and should bear the same name. However,
 * in order to avoid potential backwards incompatibilities, renaming
 * TkMacOSXGetCapture into TkpGetCapture in *PlatDecls.h shall not be
 * done in a patch release, therefore use a define here.
 */

#define TkpGetCapture TkMacOSXGetCapture

/*
 * This macro stores a representation of the window handle in a string.
 */

#define TkpPrintWindowId(buf,w) \
	sprintf((buf), "0x%lx", (unsigned long) (w))

/*
 * Turn off Tk double-buffering as Aqua windows are already double-buffered.
 */

#define TK_NO_DOUBLE_BUFFERING 1
#define TK_HAS_DYNAMIC_COLORS 1
#define TK_DYNAMIC_COLORMAP 0x0fffffff

/*
 * Magic pixel code values for system colors.
 *
 * NOTE: values must be kept in sync with indices into the
 *	 systemColorMap array in tkMacOSXColor.c !
 * Inform tkImgPhInstance.c that our tkPutImage can render an image with an
 * alpha channel directly into a window.
 */

#define TKPUTIMAGE_CAN_BLEND

/*
 * Used by xcolor.c
 */

#define TRANSPARENT_PIXEL		30
#define APPEARANCE_PIXEL		52
#define PIXEL_MAGIC ((unsigned char) 0x69)
MODULE_SCOPE unsigned long TkMacOSXRGBPixel(unsigned long red, unsigned long green,
					    unsigned long blue);
#define TkpGetPixel(p) (TkMacOSXRGBPixel(p->red >> 8, p->green >> 8, p->blue >> 8))

/*
 * The following macro returns the pixel value that corresponds to the
 * 16-bit RGB values in the given XColor structure.
 * The format is: (PIXEL_MAGIC <<< 24) | (R << 16) | (G << 8) | B
 * where each of R, G and B is the high order byte of a 16-bit component.
 * Used by tkWindow.c
 */

MODULE_SCOPE void TkMacOSXHandleMapOrUnmap(Tk_Window tkwin, XEvent *event);
#define TkpGetPixel(p) ((((((PIXEL_MAGIC << 8) \
	| (((p)->red >> 8) & 0xff)) << 8) \

#define TkpHandleMapOrUnmap(tkwin, event)  TkMacOSXHandleMapOrUnmap(tkwin, event)

	| (((p)->green >> 8) & 0xff)) << 8) \
	| (((p)->blue >> 8) & 0xff))
/*
 * Used by tkAppInit
 */

#define USE_CUSTOM_EXIT_PROC
EXTERN int TkpWantsExitProc(void);
EXTERN TCL_NORETURN void TkpExitProc(void *);

#endif /* _TKMACPORT */
Changes to macosx/tkMacOSXPrivate.h.
1
2
3
4
5
6
7



8
9
10
11
12
13
14
15
16
17
18
19
20
21




22

23

24
25
26
27
28
29
30
1
2
3
4
5


6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37





-
-
+
+
+














+
+
+
+

+

+







/*
 * tkMacOSXPrivate.h --
 *
 *	Macros and declarations that are purely internal & private to TkAqua.
 *
 * Copyright (c) 2005-2009 Daniel A. Steffen <[email protected]>
 * Copyright 2008-2009, Apple Inc.
 * Copyright © 2005-2009 Daniel A. Steffen <[email protected]>
 * 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$
 */

#ifndef _TKMACPRIV
#define _TKMACPRIV

#if !__OBJC__
#error Objective-C compiler required
#endif

#ifndef __clang__
#define instancetype id
#endif

#define TextStyle MacTextStyle
#define Cursor QDCursor
#import <ApplicationServices/ApplicationServices.h>
#undef Cursor
#import <Cocoa/Cocoa.h>
#ifndef NO_CARBON_H
#import <Carbon/Carbon.h>
#endif
#undef TextStyle
#import <objc/runtime.h> /* for sel_isEqual() */

94
95
96
97
98
99
100
101
102
103



104
105

106
107
108
109
110
111
112
113
114
115
116
117

118
119
120


121
122
123
124




































































125
126
127
128
129
130
131
101
102
103
104
105
106
107



108
109
110
111

112
113
114
115
116
117
118
119
120
121
122
123
124
125
126


127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207







-
-
-
+
+
+

-
+












+

-
-
+
+




+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    } while (0)

/*
 * Macro to do very common check for noErr return from given API and output
 * debug message in case of failure.
 */
#define ChkErr(f, ...) ({ \
	OSStatus err = f(__VA_ARGS__); \
	if (err != noErr) { \
	    TkMacOSXDbgOSErr(f, err); \
	OSStatus err_ = f(__VA_ARGS__); \
	if (err_ != noErr) { \
	    TkMacOSXDbgOSErr(f, err_); \
	} \
	err;})
	err_;})

#else /* TK_MAC_DEBUG */
#define TKLog(f, ...)
#define TkMacOSXDbgMsg(m, ...)
#define TkMacOSXDbgOSErr(f, err)
#define ChkErr(f, ...) ({f(__VA_ARGS__);})
#endif /* TK_MAC_DEBUG */

/*
 * Macro abstracting use of TkMacOSXGetNamedSymbol to init named symbols.
 */

#define UNINITIALISED_SYMBOL	((void*)(-1L))
#define TkMacOSXInitNamedSymbol(module, ret, symbol, ...) \
    static ret (* symbol)(__VA_ARGS__) = (void*)(-1L); \
    if (symbol == (void*)(-1L)) { \
    static ret (* symbol)(__VA_ARGS__) = UNINITIALISED_SYMBOL; \
    if (symbol == UNINITIALISED_SYMBOL) { \
	symbol = TkMacOSXGetNamedSymbol(STRINGIFY(module), \
		STRINGIFY(symbol)); \
    }

/*
 *  The structure of a 32-bit XEvent keycode on macOS. It may be viewed as
 *  an unsigned int or as having either two or three bitfields.
 */

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. */
} 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
			       * is used as a key for looking up the character
			       * produced when pressing a key with a particular
			       * Shift and Option modifier state. */
} keycode_x;

typedef union MacKeycode_t {
  unsigned int uint;
  keycode_v v;
  keycode_x x;
} MacKeycode;

/*
 * 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 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
 * keys.  It is used as an index when building the keymaps and it
 * is the value of the o_s bitfield of a keycode_v.
 */

#define INDEX_SHIFT 1
#define INDEX_OPTION 2
#define INDEX2STATE(index) ((index & INDEX_SHIFT ? ShiftMask : 0) |	\
			    (index & INDEX_OPTION ? Mod2Mask : 0))
#define INDEX2CARBON(index) ((index & INDEX_SHIFT ? shiftKey : 0) |	\
			     (index & INDEX_OPTION ? optionKey : 0))
#define STATE2INDEX(state) ((state & ShiftMask ? INDEX_SHIFT : 0) |	\
			    (state & Mod2Mask ? INDEX_OPTION : 0))

/*
 * Special values for the virtual bitfield.  Actual virtual keycodes are < 128.
 */

#define NO_VIRTUAL 0xFF /* Not generated by a key or the NSText"InputClient. */
#define REPLACEMENT_VIRTUAL 0x80 /* A BMP char sent by the NSTextInputClient. */
#define NON_BMP_VIRTUAL 0x81 /* A non-BMP char sent by the NSTextInputClient. */

/*
 * A special character is used in the keycode for simulated modifier KeyPress
 * or KeyRelease XEvents.  It is near the end of the private-use range but
 * different from the UniChar 0xF8FF which Apple uses for their logo character.
 * A different special character is used for keys, like the Menu key, which do
 * not appear on Macintosh keyboards.
 */

#define MOD_KEYCHAR 0xF8FE
#define UNKNOWN_KEYCHAR 0xF8FD

/*
 * Structure encapsulating current drawing environment.
 */

typedef struct TkMacOSXDrawingContext {
    CGContextRef context;
    NSView *view;
139
140
141
142
143
144
145
146
147


148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194

195
196
197
198
199
200
201
202




203
204
205
206
207
208
209
210
211
212

213
214

215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241









242
243
244
245
246
247
248
215
216
217
218
219
220
221


222
223
224

225
226
227
228
229
230




231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250



251
252




253
254
255
256
257

258
259
260
261
262




263
264
265
266



267
268
269
270



271
272

273
274

275


276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291






292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307







-
-
+
+

-






-
-
-
-




















-
-
-


-
-
-
-





-
+




-
-
-
-
+
+
+
+
-
-
-




-
-
-
+

-
+

-

-
-
















-
-
-
-
-
-
+
+
+
+
+
+
+
+
+








MODULE_SCOPE long tkMacOSXMacOSXVersion;

/*
 * Prototypes for TkMacOSXRegion.c.
 */

MODULE_SCOPE HIShapeRef	TkMacOSXGetNativeRegion(TkRegion r);
MODULE_SCOPE void	TkMacOSXSetWithNativeRegion(TkRegion r,
MODULE_SCOPE HIShapeRef	TkMacOSXGetNativeRegion(Region r);
MODULE_SCOPE void	TkMacOSXSetWithNativeRegion(Region r,
			    HIShapeRef rgn);
MODULE_SCOPE void	TkMacOSXOffsetRegion(TkRegion r, short dx, short dy);
MODULE_SCOPE HIShapeRef	TkMacOSXHIShapeCreateEmpty(void);
MODULE_SCOPE HIMutableShapeRef TkMacOSXHIShapeCreateMutableWithRect(
			    const CGRect *inRect);
MODULE_SCOPE OSStatus	TkMacOSXHIShapeSetWithShape(
			    HIMutableShapeRef inDestShape,
			    HIShapeRef inSrcShape);
#if 0
MODULE_SCOPE OSStatus	TkMacOSXHIShapeSetWithRect(HIMutableShapeRef inShape,
			    const CGRect *inRect);
#endif
MODULE_SCOPE OSStatus	TkMacOSHIShapeDifferenceWithRect(
			    HIMutableShapeRef inShape, const CGRect *inRect);
MODULE_SCOPE OSStatus	TkMacOSHIShapeUnionWithRect(HIMutableShapeRef inShape,
			    const CGRect *inRect);
MODULE_SCOPE OSStatus	TkMacOSHIShapeUnion(HIShapeRef inShape1,
			    HIShapeRef inShape2, HIMutableShapeRef outResult);

/*
 * Prototypes of TkAqua internal procs.
 */

MODULE_SCOPE void *	TkMacOSXGetNamedSymbol(const char *module,
			    const char *symbol);
MODULE_SCOPE void	TkMacOSXDisplayChanged(Display *display);
MODULE_SCOPE CGFloat	TkMacOSXZeroScreenHeight();
MODULE_SCOPE CGFloat	TkMacOSXZeroScreenTop();
MODULE_SCOPE int	TkMacOSXUseAntialiasedText(Tcl_Interp *interp,
			    int enable);
MODULE_SCOPE int	TkMacOSXInitCGDrawing(Tcl_Interp *interp, int enable,
			    int antiAlias);
MODULE_SCOPE int	TkMacOSXGenerateFocusEvent(TkWindow *winPtr,
			    int activeFlag);
MODULE_SCOPE WindowClass TkMacOSXWindowClass(TkWindow *winPtr);
MODULE_SCOPE int	TkMacOSXIsWindowZoomed(TkWindow *winPtr);
MODULE_SCOPE int	TkGenerateButtonEventForXPointer(Window window);
MODULE_SCOPE EventModifiers TkMacOSXModifierState(void);
MODULE_SCOPE NSBitmapImageRep* TkMacOSXBitmapRepFromDrawableRect(Drawable drawable,
			    int x, int y, unsigned int width, unsigned int height);
MODULE_SCOPE CGImageRef TkMacOSXCreateCGImageWithXImage(XImage *image);
MODULE_SCOPE void       TkMacOSXDrawCGImage(Drawable d, GC gc, CGContextRef context,
			    CGImageRef image, unsigned long imageForeground,
			    unsigned long imageBackground, CGRect imageBounds,
			    CGRect srcBounds, CGRect dstBounds);
MODULE_SCOPE int	TkMacOSXSetupDrawingContext(Drawable d, GC gc,
			    int useCG, TkMacOSXDrawingContext *dcPtr);
			    TkMacOSXDrawingContext *dcPtr);
MODULE_SCOPE void	TkMacOSXRestoreDrawingContext(
			    TkMacOSXDrawingContext *dcPtr);
MODULE_SCOPE void	TkMacOSXSetColorInContext(GC gc, unsigned long pixel,
			    CGContextRef context);
MODULE_SCOPE int	TkMacOSXMakeFullscreen(TkWindow *winPtr,
			    NSWindow *window, int fullscreen,
			    Tcl_Interp *interp);
MODULE_SCOPE void	TkMacOSXEnterExitFullscreen(TkWindow *winPtr,
#define TkMacOSXGetTkWindow(window) (TkWindow *)Tk_MacOSXGetTkWindow(window)
#define TkMacOSXGetNSWindowForDrawable(drawable) ((NSWindow *)Tk_MacOSXGetNSWindowForDrawable(drawable))
#define TkMacOSXGetNSViewForDrawable(macWin) ((NSView *)Tk_MacOSXGetNSViewForDrawable((Drawable)(macWin)))
#define TkMacOSXGetCGContextForDrawable(drawable) ((CGContextRef)Tk_MacOSXGetCGContextForDrawable(drawable))
			    int active);
MODULE_SCOPE NSWindow*	TkMacOSXDrawableWindow(Drawable drawable);
MODULE_SCOPE NSView*	TkMacOSXDrawableView(MacDrawable *macWin);
MODULE_SCOPE void	TkMacOSXWinCGBounds(TkWindow *winPtr, CGRect *bounds);
MODULE_SCOPE HIShapeRef	TkMacOSXGetClipRgn(Drawable drawable);
MODULE_SCOPE void	TkMacOSXInvalidateViewRegion(NSView *view,
			    HIShapeRef rgn);
MODULE_SCOPE CGContextRef TkMacOSXGetCGContextForDrawable(Drawable drawable);
MODULE_SCOPE CGImageRef	TkMacOSXCreateCGImageWithDrawable(Drawable drawable);
MODULE_SCOPE NSImage*	TkMacOSXGetNSImageWithTkImage(Display *display,
MODULE_SCOPE NSImage*	TkMacOSXGetNSImageFromTkImage(Display *display,
			    Tk_Image image, int width, int height);
MODULE_SCOPE NSImage*	TkMacOSXGetNSImageWithBitmap(Display *display,
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 Tcl_Obj *	TkMacOSXGetStringObjFromCFString(CFStringRef str);
MODULE_SCOPE TkWindow*	TkMacOSXGetTkWindow(NSWindow *w);
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);
MODULE_SCOPE void	TkMacOSXApplyWindowAttributes(TkWindow *winPtr,
			    NSWindow *macWindow);
MODULE_SCOPE int	TkMacOSXStandardAboutPanelObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TkMacOSXIconBitmapObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE void       TkMacOSXDrawSolidBorder(Tk_Window tkwin, GC gc,
			    int inset, int thickness);
MODULE_SCOPE int 	TkMacOSXServices_Init(Tcl_Interp *interp);
MODULE_SCOPE int	TkMacOSXRegisterServiceWidgetObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE NSString*  TkUtfToNSString(const char *source, size_t numBytes);
MODULE_SCOPE int        TkUtfAtIndex(NSString *string, int index, char *uni,
				      unsigned int *code);
MODULE_SCOPE char*      TkNSStringToUtf(NSString *string, int *numBytes);
			    Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
MODULE_SCOPE unsigned   TkMacOSXAddVirtual(unsigned int keycode);
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 *);


#pragma mark Private Objective-C Classes

#define VISIBILITY_HIDDEN __attribute__((visibility("hidden")))

enum { tkMainMenu = 1, tkApplicationMenu, tkWindowsMenu, tkHelpMenu};

265
266
267
268
269
270
271


272
273
274
275

276


277
278


279
280

281


282
283
284
285
286
287
288
324
325
326
327
328
329
330
331
332
333
334
335

336
337
338
339
340

341
342
343

344
345
346
347
348
349
350
351
352
353
354







+
+



-
+

+
+

-
+
+

-
+

+
+







    Tcl_Interp *_eventInterp;
    NSMenu *_servicesMenu;
    TKMenu *_defaultMainMenu, *_defaultApplicationMenu;
    NSMenuItem *_demoMenuItem;
    NSArray *_defaultApplicationMenuItems, *_defaultWindowsMenuItems;
    NSArray *_defaultHelpMenuItems, *_defaultFileMenuItems;
    NSAutoreleasePool *_mainPool;
    NSThread *_backgoundLoop;

#ifdef __i386__
    /* The Objective C runtime used on i386 requires this. */
    int _poolLock;
    int _macMinorVersion;
    int _macOSVersion;  /* 10000 * major + 100*minor */
    Bool _isDrawing;
    Bool _needsToDraw;
    Bool _isSigned;
#endif
}

}
@property int poolLock;
@property int macMinorVersion;
@property int macOSVersion;
@property Bool isDrawing;
@property Bool needsToDraw;
@property Bool isSigned;

@end
@interface TKApplication(TKInit)
- (NSString *)tkFrameworkImagePath:(NSString*)image;
- (void)_resetAutoreleasePool;
- (void)_lockAutoreleasePool;
- (void)_unlockAutoreleasePool;
300
301
302
303
304
305
306

307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322

323
324
325
326
327
328
329
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397







+
















+







@end
@interface TKApplication(TKMenus)
- (void) _setupMenus;
@end
@interface NSApplication(TKNotify)
/* We need to declare this hidden method. */
- (void) _modalSession: (NSModalSession) session sendEvent: (NSEvent *) event;
- (void) _runBackgroundLoop;
@end
@interface TKApplication(TKEvent)
- (NSEvent *)tkProcessEvent:(NSEvent *)theEvent;
@end
@interface TKApplication(TKMouseEvent)
- (NSEvent *)tkProcessMouseEvent:(NSEvent *)theEvent;
@end
@interface TKApplication(TKKeyEvent)
- (NSEvent *)tkProcessKeyEvent:(NSEvent *)theEvent;
@end
@interface TKApplication(TKClipboard)
- (void)tkProvidePasteboard:(TkDisplay *)dispPtr;
- (void)tkCheckPasteboard;
@end
@interface TKApplication(TKHLEvents)
- (void) terminate: (id) sender;
- (void) superTerminate: (id) sender;
- (void) preferences: (id) sender;
- (void) handleQuitApplicationEvent:   (NSAppleEventDescriptor *)event
		     withReplyEvent:   (NSAppleEventDescriptor *)replyEvent;
- (void) handleOpenApplicationEvent:   (NSAppleEventDescriptor *)event
		     withReplyEvent:   (NSAppleEventDescriptor *)replyEvent;
- (void) handleReopenApplicationEvent: (NSAppleEventDescriptor *)event
		       withReplyEvent: (NSAppleEventDescriptor *)replyEvent;
345
346
347
348
349
350
351
352


353
354


355
356
357
358

359
360
361


362

363
364
365
366
367
368
369
370
371
372









373
374
375
376
377
378
379

380
381




382











383
384
385
386
387
388
389
413
414
415
416
417
418
419

420
421
422

423
424
425
426
427
428
429
430
431
432
433
434

435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460

461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486







-
+
+

-
+
+




+



+
+
-
+










+
+
+
+
+
+
+
+
+






-
+


+
+
+
+

+
+
+
+
+
+
+
+
+
+
+







 * input from the Character Palette.
 */

@interface TKContentView : NSView <NSTextInputClient>
{
@private
    NSString *privateWorkingText;
    Bool _needsRedisplay;
    Bool _tkNeedsDisplay;
    NSRect _tkDirtyRect;
}
@property Bool needsRedisplay;
@property Bool tkNeedsDisplay;
@property NSRect tkDirtyRect;
@end

@interface TKContentView(TKKeyEvent)
- (void) deleteWorkingText;
- (void) cancelComposingText;
@end

@interface TKContentView(TKWindowEvent)
- (void) addTkDirtyRect: (NSRect) rect;
- (void) clearTkDirtyRect;
- (void) generateExposeEvents: (HIShapeRef) shape;
- (void) generateExposeEvents: (NSRect) rect;
- (void) tkToolbarButton: (id) sender;
@end

@interface NSWindow(TKWm)
- (NSPoint) tkConvertPointToScreen:(NSPoint)point;
- (NSPoint) tkConvertPointFromScreen:(NSPoint)point;
@end

VISIBILITY_HIDDEN
@interface TKWindow : NSWindow
{
#ifdef __i386__
    /* The Objective C runtime used on i386 requires this. */
    Bool _mouseInResizeArea;
    Window _tkWindow;
#endif
}
@property Bool mouseInResizeArea;
@property Window tkWindow;
@end

@interface TKWindow(TKWm)
- (void)    tkLayoutChanged;
@end

@interface NSDrawerWindow : NSWindow
@interface TKDrawerWindow : NSWindow
{
    id _i1, _i2;
#ifdef __i386__
    /* The Objective C runtime used on i386 requires this. */
    Window _tkWindow;
#endif
}
@property Window tkWindow;
@end

@interface TKPanel : NSPanel
{
#ifdef __i386__
    /* The Objective C runtime used on i386 requires this. */
    Window _tkWindow;
#endif
}
@property Window tkWindow;
@end

#pragma mark NSMenu & NSMenuItem Utilities

@interface NSMenu(TKUtils)
+ (id)menuWithTitle:(NSString *)title;
+ (id)menuWithTitle:(NSString *)title menuItems:(NSArray *)items;
425
426
427
428
429
430
431






432





433
434
435




































436
437
438
439
440
441
442
443
522
523
524
525
526
527
528
529
530
531
532
533
534

535
536
537
538
539
540


541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584







+
+
+
+
+
+
-
+
+
+
+
+

-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








 * declare it here to be a method of the TKMenu category.
 */

@interface NSApplication(TKMenu)
- (void) setAppleMenu: (NSMenu *) menu;
@end

/*
 * These methods are exposed because they are needed to prevent zombie windows
 * on systems with a TouchBar.  The TouchBar Key-Value observer holds a
 * reference to the key window, which prevents deallocation of the key window
 * when it is closed.
 */
#endif /* _TKMACPRIV */

@interface NSApplication(TkWm)
- (id) _setKeyWindow: (NSWindow *) window;
- (id) _setMainWindow: (NSWindow *) window;
@end

int TkMacOSXGetAppPath(ClientData cd, Tcl_Interp *ip, int objc, Tcl_Obj *const objv[]);


/*
 *---------------------------------------------------------------------------
 *
 * TKNSString --
 *
 * When Tcl is compiled with TCL_UTF_MAX = 3 (the default for 8.6) it cannot
 * deal directly with UTF-8 encoded non-BMP characters, since their UTF-8
 * encoding requires 4 bytes. Instead, when using these versions of Tcl, Tk
 * uses the CESU-8 encoding internally.  This encoding is similar to UTF-8
 * except that it allows encoding surrogate characters as 3-byte sequences
 * using the same algorithm which UTF-8 uses for non-surrogates.  This means
 * that a non-BMP character is encoded as a string of length 6.  Apple's
 * NSString class does not provide a constructor which accepts a CESU-8 encoded
 * byte sequence as initial data.  So we add a new class which does provide
 * such a constructor.  It also has a DString property which is a DString whose
 * string pointer is a byte sequence encoding the NSString with the current Tk
 * encoding, namely UTF-8 if TCL_UTF_MAX >= 4 or CESU-8 if TCL_UTF_MAX = 3.
 *
 *---------------------------------------------------------------------------
 */

@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;
@end

#endif /* _TKMACPRIV */

/*
 * Local Variables:
 * mode: objc
 * c-basic-offset: 4
 * fill-column: 79
 * coding: utf-8
 * End:
 */
Changes to macosx/tkMacOSXRegion.c.
1
2
3
4
5
6
7
8



9
10
11
12
13
14










15
16
17
18
19
20

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35


36
37




38
39
40
41
42
43

44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59


60
61

62

63
64
65
66
67
68
69
70

71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88




89
90
91
92
93
94
95
96
97
98

99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116




117
118
119
120
121
122
123
124
125
126

127
128
129
130
131
132
133
134
135
136
137
138
139
140
141

142
143
144


145
146
147
148
149
150
151
1
2
3
4
5



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

30
31
32
33
34
35
36
37
38
39
40
41
42
43


44
45
46

47
48
49
50
51
52
53
54
55

56
57
58
59
60
61
62
63
64
65
66
67
68
69
70


71
72
73
74
75

76
77
78
79
80
81
82
83

84
85
86
87
88
89
90
91
92
93
94
95
96
97
98




99
100
101
102
103
104
105
106
107
108
109
110
111

112
113
114
115
116
117
118
119
120
121
122
123
124
125
126




127
128
129
130
131
132
133
134
135
136
137
138
139

140
141
142
143
144
145
146
147
148
149
150
151
152
153
154

155
156


157
158
159
160
161
162
163
164
165





-
-
-
+
+
+






+
+
+
+
+
+
+
+
+
+





-
+













-
-
+
+

-
+
+
+
+





-
+














-
-
+
+


+
-
+







-
+














-
-
-
-
+
+
+
+









-
+














-
-
-
-
+
+
+
+









-
+














-
+

-
-
+
+







/*
 * 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 <[email protected]>
 * Copyright © 1995-1996 Sun Microsystems, Inc.
 * Copyright © 2001-2009, Apple Inc.
 * Copyright © 2006-2009 Daniel A. Steffen <[email protected]>
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tkMacOSXPrivate.h"
static void RetainRegion(TkRegion r);
static void ReleaseRegion(TkRegion r);

#ifdef DEBUG
static int totalRegions = 0;
static int totalRegionRetainCount = 0;
#define DebugLog(msg, ...) fprintf(stderr, (msg), ##__VA_ARGS__)
#else
#define DebugLog(msg, ...)
#endif


/*
 *----------------------------------------------------------------------
 *
 * TkCreateRegion --
 * XCreateRegion --
 *
 *	Implements the equivelent of the X window function XCreateRegion. See
 *	Xwindow documentation for more details.
 *
 * Results:
 *	Returns an allocated region handle.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

TkRegion
TkCreateRegion(void)
Region
XCreateRegion(void)
{
    return (TkRegion) HIShapeCreateMutable();
    Region region = (Region) HIShapeCreateMutable();
    DebugLog("Created region: total regions = %d\n", ++totalRegions);
    RetainRegion(region);
    return region;
}

/*
 *----------------------------------------------------------------------
 *
 * TkDestroyRegion --
 * XDestroyRegion --
 *
 *	Implements the equivelent of the X window function XDestroyRegion. See
 *	Xwindow documentation for more details.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Memory is freed.
 *
 *----------------------------------------------------------------------
 */

int
TkDestroyRegion(
    TkRegion r)
XDestroyRegion(
    Region r)
{
    if (r) {
	DebugLog("Destroyed region: total regions = %d\n", --totalRegions);
	CFRelease(r);
	ReleaseRegion(r);
    }
    return Success;
}

/*
 *----------------------------------------------------------------------
 *
 * TkIntersectRegion --
 * XIntersectRegion --
 *
 *	Implements the equivalent of the X window function XIntersectRegion.
 *	See Xwindow documentation for more details.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TkIntersectRegion(
    TkRegion sra,
    TkRegion srb,
    TkRegion dr_return)
XIntersectRegion(
    Region sra,
    Region srb,
    Region dr_return)
{
    ChkErr(HIShapeIntersect, (HIShapeRef) sra, (HIShapeRef) srb,
	   (HIMutableShapeRef) dr_return);
    return Success;
}

/*
 *----------------------------------------------------------------------
 *
 * TkSubtractRegion --
 * XSubtractRegion --
 *
 *	Implements the equivalent of the X window function XSubtractRegion.
 *	See X window documentation for more details.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TkSubtractRegion(
    TkRegion sra,
    TkRegion srb,
    TkRegion dr_return)
XSubtractRegion(
    Region sra,
    Region srb,
    Region dr_return)
{
    ChkErr(HIShapeDifference, (HIShapeRef) sra, (HIShapeRef) srb,
	   (HIMutableShapeRef) dr_return);
    return Success;
}

/*
 *----------------------------------------------------------------------
 *
 * TkUnionRectWithRegion --
 * XUnionRectWithRegion --
 *
 *	Implements the equivelent of the X window function
 *	XUnionRectWithRegion. See Xwindow documentation for more details.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TkUnionRectWithRegion(
XUnionRectWithRegion(
    XRectangle* rectangle,
    TkRegion src_region,
    TkRegion dest_region_return)
    Region src_region,
    Region dest_region_return)
{
    const CGRect r = CGRectMake(rectangle->x, rectangle->y,
	    rectangle->width, rectangle->height);

    if (src_region == dest_region_return) {
	ChkErr(TkMacOSHIShapeUnionWithRect,
		(HIMutableShapeRef) dest_region_return, &r);
173
174
175
176
177
178
179
180

181
182
183
184
185
186
187
188

189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205


206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224

225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240


241
242
243
244
245
246
247
187
188
189
190
191
192
193

194
195
196
197
198
199
200
201

202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217


218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237

238
239
240
241
242
243
244
245
246
247
248
249
250
251
252


253
254
255
256
257
258
259
260
261







-
+







-
+















-
-
+
+


















-
+














-
-
+
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TkMacOSXIsEmptyRegion(
    TkRegion r)
    Region r)
{
    return HIShapeIsEmpty((HIMutableShapeRef) r) ? 1 : 0;
}

/*
 *----------------------------------------------------------------------
 *
 * TkRectInRegion --
 * XRectInRegion --
 *
 *	Implements the equivelent of the X window function XRectInRegion. See
 *	Xwindow documentation for more details.
 *
 * Results:
 *	Returns RectanglePart or RectangleOut. Note that this is not a complete
 *	implementation since it doesn't test for RectangleIn.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TkRectInRegion(
    TkRegion region,
XRectInRegion(
    Region region,
    int x,
    int y,
    unsigned int width,
    unsigned int height)
{
    if (TkMacOSXIsEmptyRegion(region)) {
	return RectangleOut;
    } else {
	const CGRect r = CGRectMake(x, y, width, height);

	return HIShapeIntersectsRect((HIShapeRef) region, &r) ?
		RectanglePart : RectangleOut;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TkClipBox --
 * XClipBox --
 *
 *	Implements the equivelent of the X window function XClipBox. See
 *	Xwindow documentation for more details.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TkClipBox(
    TkRegion r,
XClipBox(
    Region r,
    XRectangle *rect_return)
{
    CGRect rect;

    HIShapeGetBounds((HIShapeRef) r, &rect);
    rect_return->x = rect.origin.x;
    rect_return->y = rect.origin.y;
265
266
267
268
269
270
271
272

273
274
275
276
277
278
279
279
280
281
282
283
284
285

286
287
288
289
290
291
292
293







-
+







 *	The region is updated, with extra pixels added to it.
 *
 *----------------------------------------------------------------------
 */

void
TkpBuildRegionFromAlphaData(
    TkRegion region,			/* Region to update. */
    Region region,			/* Region to update. */
    unsigned int x,			/* Where in region to update. */
    unsigned int y,			/* Where in region to update. */
    unsigned int width,			/* Size of rectangle to update. */
    unsigned int height,		/* Size of rectangle to update. */
    unsigned char *dataPtr,		/* Data to read from. */
    unsigned int pixelStride,		/* num bytes from one piece of alpha
					 * data to the next in the line. */
306
307
308
309
310
311
312
313

314
315
316
317
318
319
320
321
322
323

324
325
326
327
328
329
330
331
332
333
334
335
336
337
338



339
340

341
342
343
344
345
346

347
348
349
350
351
352
353
354
355
356
357
358
359
360
361



362
363

364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384

385
386
387
388
389
390
391
320
321
322
323
324
325
326

327
328
329
330
331
332
333
334
335
336

337
338
339
340
341
342
343
344
345
346
347
348
349



350
351
352
353
354
355
356
357
358
359
360

361
362
363
364
365
366
367
368
369
370
371
372
373



374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399

400
401
402
403
404
405
406
407







-
+









-
+












-
-
-
+
+
+


+





-
+












-
-
-
+
+
+


+




















-
+







		lineDataPtr += pixelStride;
	    }
	    if (end > x1) {
		rect.x = x + x1;
		rect.y = y + y1;
		rect.width = end - x1;
		rect.height = 1;
		TkUnionRectWithRegion(&rect, region, region);
		XUnionRectWithRegion(&rect, region, region);
	    }
	}
	dataPtr += lineStride;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TkpRetainRegion --
 * RetainRegion --
 *
 *	Increases reference count of region.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void
TkpRetainRegion(
    TkRegion r)
static void
RetainRegion(
    Region r)
{
    CFRetain(r);
    DebugLog("Retained region: total count is %d\n", ++totalRegionRetainCount);
}

/*
 *----------------------------------------------------------------------
 *
 * TkpReleaseRegion --
 * ReleaseRegion --
 *
 *	Decreases reference count of region.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	May free memory.
 *
 *----------------------------------------------------------------------
 */

void
TkpReleaseRegion(
    TkRegion r)
static void
ReleaseRegion(
    Region r)
{
    CFRelease(r);
    DebugLog("Released region: total count is %d\n", --totalRegionRetainCount);
}

/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXSetEmptyRegion --
 *
 *	Set region to emtpy.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void
TkMacOSXSetEmptyRegion(
    TkRegion r)
    Region r)
{
    ChkErr(HIShapeSetEmpty, (HIMutableShapeRef) r);
}

/*
 *----------------------------------------------------------------------
 *
400
401
402
403
404
405
406
407

408
409
410
411
412
413
414
416
417
418
419
420
421
422

423
424
425
426
427
428
429
430







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

HIShapeRef
TkMacOSXGetNativeRegion(
    TkRegion r)
    Region r)
{
    return (HIShapeRef) CFRetain(r);
}

/*
 *----------------------------------------------------------------------
 *
423
424
425
426
427
428
429
430

431
432
433
434
435
436
437
438
439

440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456





457
458

459
460
461
462
463
464
465

466
467
468
469
470
471
472
439
440
441
442
443
444
445

446
447
448
449
450
451
452
453
454

455
456
457
458
459
460
461
462
463
464
465
466
467





468
469
470
471
472
473
474
475
476
477
478
479
480
481

482
483
484
485
486
487
488
489







-
+








-
+












-
-
-
-
-
+
+
+
+
+


+






-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

void
TkMacOSXSetWithNativeRegion(
    TkRegion r,
    Region r,
    HIShapeRef rgn)
{
    ChkErr(TkMacOSXHIShapeSetWithShape, (HIMutableShapeRef) r, rgn);
}

/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXOffsetRegion --
 * XOffsetRegion --
 *
 *	Offsets region by given distances.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void
TkMacOSXOffsetRegion(
    TkRegion r,
    short dx,
    short dy)
int
XOffsetRegion(
    Region r,
    int dx,
    int dy)
{
    ChkErr(HIShapeOffset, (HIMutableShapeRef) r, dx, dy);
    return Success;
}

/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXHIShapeCreateEmpty, TkMacOSXHIShapeCreateMutableWithRect,
 * TkMacOSXHIShapeSetWithShape, TkMacOSXHIShapeSetWithRect,
 * TkMacOSXHIShapeSetWithShape,
 * TkMacOSHIShapeDifferenceWithRect, TkMacOSHIShapeUnionWithRect,
 * TkMacOSHIShapeUnion --
 *
 *	Wrapper functions for missing/buggy HIShape API
 *
 *----------------------------------------------------------------------
 */
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
514
515
516
517
518
519
520
















521
522
523
524
525
526
527







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







{
    OSStatus result;

    result = HIShapeSetWithShape(inDestShape, inSrcShape);
    return result;
}

#if 0
OSStatus
TkMacOSXHIShapeSetWithRect(
    HIMutableShapeRef inShape,
    const CGRect *inRect)
{
    OSStatus result;
    HIShapeRef rgn = HIShapeCreateWithRect(inRect);

    result = TkMacOSXHIShapeSetWithShape(inShape, rgn);
    CFRelease(rgn);

    return result;
}
#endif

OSStatus
TkMacOSHIShapeDifferenceWithRect(
    HIMutableShapeRef inShape,
    const CGRect *inRect)
{
    OSStatus result;
    HIShapeRef rgn = HIShapeCreateWithRect(inRect);
Changes to macosx/tkMacOSXScale.c.
1
2
3
4
5
6
7
8
9
10




11
12
13
14
15
16
17
1
2
3
4
5
6




7
8
9
10
11
12
13
14
15
16
17






-
-
-
-
+
+
+
+







/*
 * 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 <[email protected]>
 * Copyright 2008-2009, Apple Inc.
 * Copyright © 1996 Sun Microsystems, Inc.
 * Copyright © 1998-2000 Scriptics Corporation.
 * Copyright © 2006-2009 Daniel A. Steffen <[email protected]>
 * 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.
 */

#include "tkMacOSXPrivate.h"
#include "tkScale.h"
72
73
74
75
76
77
78
79

80
81
82
83
84
85
86
72
73
74
75
76
77
78

79
80
81
82
83
84
85
86







-
+







 *----------------------------------------------------------------------
 */

TkScale *
TkpCreateScale(
    Tk_Window tkwin)
{
    MacScale *macScalePtr = ckalloc(sizeof(MacScale));
    MacScale *macScalePtr = (MacScale *)ckalloc(sizeof(MacScale));

    macScalePtr->scaleHandle = NULL;
    if (scaleActionProc == NULL) {
	scaleActionProc = NewControlActionUPP(ScaleActionProc);
    }

    Tk_CreateEventHandler(tkwin, ButtonPressMask,
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
145
146
147
148
149
150
151


152
153
154
155
156
157
158







-
-







    Tk_Window tkwin = scalePtr->tkwin;
    Tcl_Interp *interp = scalePtr->interp;
    int result;
    char string[TCL_DOUBLE_SPACE];
    MacScale *macScalePtr = clientData;
    Rect r;
    WindowRef windowRef;
    CGrafPtr destPort, savePort;
    Boolean portChanged;
    MacDrawable *macDraw;
    SInt32 initialValue, minValue, maxValue;
    UInt16 numTicks;
    Tcl_DString buf;

#ifdef TK_MAC_DEBUG_SCALE
    TkMacOSXDbgMsg("TkpDisplayScale");
175
176
177
178
179
180
181
182

183
184
185
186
187
188
189
173
174
175
176
177
178
179

180
181
182
183
184
185
186
187







-
+







                scalePtr->value) < 0) {
            string[TCL_DOUBLE_SPACE - 1] = '\0';
        }
	Tcl_DStringInit(&buf);
	Tcl_DStringAppend(&buf, scalePtr->command, -1);
	Tcl_DStringAppend(&buf, " ", -1);
	Tcl_DStringAppend(&buf, string, -1);
	result = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, 0);
	result = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, TCL_EVAL_GLOBAL);
	Tcl_DStringFree(&buf);
	if (result != TCL_OK) {
	    Tcl_AddErrorInfo(interp, "\n    (command executed by scale)");
	    Tcl_BackgroundException(interp, result);
	}
	Tcl_Release(interp);
    }
211
212
213
214
215
216
217
218

219
220
221
222

223
224
225
226
227
228
229
209
210
211
212
213
214
215

216




217
218
219
220
221
222
223
224







-
+
-
-
-
-
+







	    Tk_Height(tkwin) - 2*scalePtr->highlightWidth,
	    scalePtr->borderWidth, scalePtr->relief);

    /*
     * Set up port for drawing Macintosh control.
     */

    macDraw = (MacDrawable *) Tk_WindowId(tkwin);
    macDraw = (MacDrawable *)Tk_WindowId(tkwin);
    destPort = TkMacOSXGetDrawablePort(Tk_WindowId(tkwin));
    windowRef = TkMacOSXDrawableWindow(Tk_WindowId(tkwin));
    portChanged = QDSwapPort(destPort, &savePort);
    TkMacOSXSetUpClippingRgn(Tk_WindowId(tkwin));
    windowRef = TkMacOSXGetNSWindowForDrawable(Tk_WindowId(tkwin));

    /*
     * Create Macintosh control.
     */

#define MAC_OSX_SCROLL_WIDTH 10

289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
284
285
286
287
288
289
290



291
292
293
294
295
296
297







-
-
-







     * Finally draw the control.
     */

    SetControlVisibility(macScalePtr->scaleHandle, true, true);
    HiliteControl(macScalePtr->scaleHandle, 0);
    Draw1Control(macScalePtr->scaleHandle);

    if (portChanged) {
	QDSwapPort(savePort, NULL);
    }
done:
    scalePtr->flags &= ~REDRAW_ALL;
}

/*
 *----------------------------------------------------------------------
 *
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
315
316
317
318
319
320
321


322
323
324
325


326
327
328
329
330
331
332
333
334
335
336




337
338
339
340
341
342
343







-
-




-
-











-
-
-
-







    TkScale *scalePtr,		/* Widget record for scale. */
    int x, int y)		/* Coordinates within scalePtr's window. */
{
    MacScale *macScalePtr = (MacScale *) scalePtr;
    ControlPartCode part;
    Point where;
    Rect bounds;
    CGrafPtr destPort, savePort;
    Boolean portChanged;

#ifdef TK_MAC_DEBUG_SCALE
    TkMacOSXDbgMsg("TkpScaleElement");
#endif
    destPort = TkMacOSXGetDrawablePort(Tk_WindowId(scalePtr->tkwin));
    portChanged = QDSwapPort(destPort, &savePort);

    /*
     * All of the calculations in this procedure mirror those in
     * DisplayScrollbar. Be sure to keep the two consistent.
     */

    TkMacOSXWinBounds((TkWindow *) scalePtr->tkwin, &bounds);
    where.h = x + bounds.left;
    where.v = y + bounds.top;
    part = TestControl(macScalePtr->scaleHandle, where);

    if (portChanged) {
	QDSwapPort(savePort, NULL);
    }

#ifdef TK_MAC_DEBUG_SCALE
    fprintf (stderr,"ScalePart %d, pos ( %d %d )\n", part, where.h, where.v );
#endif

    switch (part) {
    case inSlider:
	return SLIDER;
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
381
382
383
384
385
386
387


388
389
390
391
392
393
394
395
396
397
398








399
400
401
402
403
404
405







-
-











-
-
-
-
-
-
-
-







    ClientData clientData,	/* Information about window. */
    XEvent *eventPtr)		/* Information about event. */
{
    MacScale *macScalePtr = (MacScale *) clientData;
    Point where;
    Rect bounds;
    int part;
    CGrafPtr destPort, savePort;
    Boolean portChanged;

#ifdef TK_MAC_DEBUG_SCALE
    fprintf(stderr,"MacScaleEventProc\n" );
#endif

    /*
     * To call Macintosh control routines we must have the port set to the
     * window containing the control. We will then test which part of the
     * control was hit and act accordingly.
     */

    destPort = TkMacOSXGetDrawablePort(Tk_WindowId(macScalePtr->info.tkwin));
    portChanged = QDSwapPort(destPort, &savePort);
    TkMacOSXSetUpClippingRgn(Tk_WindowId(macScalePtr->info.tkwin));

    TkMacOSXWinBounds((TkWindow *) macScalePtr->info.tkwin, &bounds);
    where.h = eventPtr->xbutton.x + bounds.left;
    where.v = eventPtr->xbutton.y + bounds.top;
#ifdef TK_MAC_DEBUG_SCALE
    TkMacOSXDbgMsg("calling TestControl");
#endif
    part = TestControl(macScalePtr->scaleHandle, where);
    if (part == 0) {
	return;
    }

443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
417
418
419
420
421
422
423




424
425
426
427
428
429
430







-
-
-
-








    /*
     * The HandleControlClick call will "eat" the ButtonUp event. We now
     * generate a ButtonUp event so Tk will unset implicit grabs etc.
     */

    TkGenerateButtonEventForXPointer(Tk_WindowId(macScalePtr->info.tkwin));

    if (portChanged) {
	QDSwapPort(savePort, NULL);
    }
}

/*
 *--------------------------------------------------------------
 *
 * ScaleActionProc --
 *
Changes to macosx/tkMacOSXScrlbr.c.
1
2
3
4
5
6
7
8
9
10
11





12
13
14
15
16
17
18
1
2
3
4
5
6





7
8
9
10
11
12
13
14
15
16
17
18






-
-
-
-
-
+
+
+
+
+







/*
 * 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 <[email protected]>
 * 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 <[email protected]>
 * 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.
 */

#include "tkInt.h"
#include "tkScrollbar.h"
117
118
119
120
121
122
123
124

125
126
127
128
129
130
131
117
118
119
120
121
122
123

124
125
126
127
128
129
130
131







-
+







 *----------------------------------------------------------------------
 */

TkScrollbar *
TkpCreateScrollbar(
    Tk_Window tkwin)
{
    MacScrollbar *scrollPtr = ckalloc(sizeof(MacScrollbar));
    MacScrollbar *scrollPtr = (MacScrollbar *)ckalloc(sizeof(MacScrollbar));

    scrollPtr->troughGC = NULL;
    scrollPtr->copyGC = NULL;
    scrollPtr->info = defaultInfo;
    scrollPtr->buttonDown = false;

    Tk_CreateEventHandler(tkwin,
170
171
172
173
174
175
176
177
178


179
180
181
182
183
184
185
170
171
172
173
174
175
176


177
178
179
180
181
182
183
184
185







-
-
+
+







 */

static void drawMacScrollbar(
    TkScrollbar *scrollPtr,
    MacScrollbar *msPtr,
    CGContextRef context)
{
    MacDrawable *macWin = (MacDrawable *) Tk_WindowId(scrollPtr->tkwin);
    NSView *view = TkMacOSXDrawableView(macWin);
    Drawable d = Tk_WindowId(scrollPtr->tkwin);
    NSView *view = TkMacOSXGetNSViewForDrawable(d);
    CGPathRef path;
    CGPoint inner[2], outer[2], thumbOrigin;
    CGSize thumbSize;
    CGRect troughBounds = msPtr->info.bounds;
    troughBounds.origin.y = [view bounds].size.height -
	(troughBounds.origin.y + troughBounds.size.height);
    if (scrollPtr->vertical) {
242
243
244
245
246
247
248
249

250
251

252
253
254
255
256
257
258
259
260
261
262


263
264
265
266

267
268
269
270
271
272
273
242
243
244
245
246
247
248

249
250

251
252
253
254
255
256
257
258
259
260


261
262
263
264
265

266
267
268
269
270
271
272
273







-
+

-
+









-
-
+
+



-
+







}
#endif

void
TkpDisplayScrollbar(
    ClientData clientData)	/* Information about window. */
{
    register TkScrollbar *scrollPtr = clientData;
    TkScrollbar *scrollPtr = clientData;
    MacScrollbar *msPtr = (MacScrollbar *) scrollPtr;
    register Tk_Window tkwin = scrollPtr->tkwin;
    Tk_Window tkwin = scrollPtr->tkwin;
    TkWindow *winPtr = (TkWindow *) tkwin;
    TkMacOSXDrawingContext dc;

    scrollPtr->flags &= ~REDRAW_PENDING;

    if (tkwin == NULL || !Tk_IsMapped(tkwin)) {
	return;
    }

    MacDrawable *macWin = (MacDrawable *) winPtr->window;
    NSView *view = TkMacOSXDrawableView(macWin);
    MacDrawable *macWin = (MacDrawable *)winPtr->window;
    NSView *view = TkMacOSXGetNSViewForDrawable(macWin);

    if ((view == NULL)
	    || (macWin->flags & TK_DO_NOT_DRAW)
	    || !TkMacOSXSetupDrawingContext((Drawable) macWin, NULL, 1, &dc)) {
	    || !TkMacOSXSetupDrawingContext((Drawable)macWin, NULL, &dc)) {
	return;
    }

    /*
     * Transform NSView coordinates to CoreGraphics coordinates.
     */

312
313
314
315
316
317
318
319

320
321
322
323
324
325
326
312
313
314
315
316
317
318

319
320
321
322
323
324
325
326







-
+







     */

    UpdateControlValues(scrollPtr);

    if (SNOW_LEOPARD_STYLE) {
	HIThemeDrawTrack(&msPtr->info, 0, dc.context,
			 kHIThemeOrientationInverted);
    } else if ([NSApp macMinorVersion] <= 8) {
    } else if ([NSApp macOSVersion] <= 100800) {
	HIThemeDrawTrack(&msPtr->info, 0, dc.context,
			 kHIThemeOrientationNormal);
    } else {
#if MAC_OS_X_VERSION_MAX_ALLOWED > 1080

	/*
	 * Switch back to NSView coordinates and draw a modern scrollbar.
350
351
352
353
354
355
356
357

358
359
360
361
362
363
364
350
351
352
353
354
355
356

357
358
359
360
361
362
363
364







-
+







 *	The scrollbar will be displayed differently.
 *
 *----------------------------------------------------------------------
 */

extern void
TkpComputeScrollbarGeometry(
    register TkScrollbar *scrollPtr)
    TkScrollbar *scrollPtr)
				/* Scrollbar whose geometry may have
				 * changed. */
{
    /*
     * The code below is borrowed from tkUnixScrlbr.c but has been adjusted to
     * account for some differences between macOS and X11. The Unix scrollbar
     * has an arrow button on each end.  On macOS 10.6 (Snow Leopard) the
373
374
375
376
377
378
379
380

381
382
383
384
385
386
387
373
374
375
376
377
378
379

380
381
382
383
384
385
386
387







-
+








    int fieldLength;

    if (scrollPtr->highlightWidth < 0) {
	scrollPtr->highlightWidth = 0;
    }
    scrollPtr->inset = scrollPtr->highlightWidth + scrollPtr->borderWidth;
    if ([NSApp macMinorVersion] == 6) {
    if ([NSApp macOSVersion] == 100600) {
	scrollPtr->arrowLength = scrollPtr->width;
    } else {
	scrollPtr->arrowLength = 0;
    }
    fieldLength = (scrollPtr->vertical ? Tk_Height(scrollPtr->tkwin)
	    : Tk_Width(scrollPtr->tkwin))
	    - 2*(scrollPtr->arrowLength + scrollPtr->inset);
480
481
482
483
484
485
486
487

488

489
490
491
492
493
494
495
480
481
482
483
484
485
486

487
488
489
490
491
492
493
494
495
496







-
+

+







 *	Currently, none.
 *
 *----------------------------------------------------------------------
 */

void
TkpConfigureScrollbar(
    register TkScrollbar *scrollPtr)
    TkScrollbar *scrollPtr)
{
    (void)scrollPtr;
    /* empty */
}

/*
 *--------------------------------------------------------------
 *
 * TkpScrollbarPosition --
505
506
507
508
509
510
511
512

513
514
515
516
517
518
519
520
521
522

523
524
525
526
527
528
529
506
507
508
509
510
511
512

513
514
515
516
517
518
519
520
521
522

523
524
525
526
527
528
529
530







-
+









-
+







 *	None.
 *
 *--------------------------------------------------------------
 */

int
TkpScrollbarPosition(
    register TkScrollbar *scrollPtr,
    TkScrollbar *scrollPtr,
				/* Scrollbar widget record. */
    int x, int y)		/* Coordinates within scrollPtr's window. */
{
    /*
     * The code below is borrowed from tkUnixScrlbr.c and needs no adjustment
     * since it does not involve the arrow buttons.
     */

    int length, width, tmp;
    register const int inset = scrollPtr->inset;
    const int inset = scrollPtr->inset;

    if (scrollPtr->vertical) {
	length = Tk_Height(scrollPtr->tkwin);
	width = Tk_Width(scrollPtr->tkwin);
    } else {
	tmp = x;
	x = y;
585
586
587
588
589
590
591
592

593
594
595
596
597

598
599
600
601
602
603
604
586
587
588
589
590
591
592

593
594
595
596
597

598
599
600
601
602
603
604
605







-
+




-
+








static void
UpdateControlValues(
    TkScrollbar *scrollPtr)		/* Scrollbar data struct. */
{
    MacScrollbar *msPtr = (MacScrollbar *) scrollPtr;
    Tk_Window tkwin = scrollPtr->tkwin;
    MacDrawable *macWin = (MacDrawable *) Tk_WindowId(scrollPtr->tkwin);
    MacDrawable *macWin = (MacDrawable *)Tk_WindowId(scrollPtr->tkwin);
    double dViewSize;
    HIRect contrlRect;
    short width, height;

    NSView *view = TkMacOSXDrawableView(macWin);
    NSView *view = TkMacOSXGetNSViewForDrawable(macWin);
    CGFloat viewHeight = [view bounds].size.height;
    NSRect frame;

    frame = NSMakeRect(macWin->xOff, macWin->yOff, Tk_Width(tkwin),
	    Tk_Height(tkwin));
    frame = NSInsetRect(frame, scrollPtr->inset, scrollPtr->inset);
    frame.origin.y = viewHeight - (frame.origin.y + frame.size.height);
657
658
659
660
661
662
663
664

665
666
667
668
669
670
671
658
659
660
661
662
663
664

665
666
667
668
669
670
671
672







-
+







}

/*
 *--------------------------------------------------------------
 *
 * ScrollbarEvent --
 *
 *	This procedure is invoked in response to <ButtonPress>,
 *	This procedure is invoked in response to <Button>,
 *      <ButtonRelease>, <EnterNotify>, and <LeaveNotify> events.  The
 *      Scrollbar appearance is modified for each event.
 *
 *--------------------------------------------------------------
 */

static int
Changes to macosx/tkMacOSXSend.c.
1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28




29
30
31
32
33
34
35
1
2
3
4
5

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24




25
26
27
28
29
30
31
32
33
34
35





-
+


















-
-
-
-
+
+
+
+







/*
 * tkMacOSXSend.c --
 *
 *	This file provides procedures that implement the "send" command,
 *	allowing commands to be passed from interpreter to interpreter. This
 *	current implementation for the Mac has most functionality stubed out.
 *	current implementation for the Mac has most functionality stubbed out.
 *
 *	The current plan, which we have not had time to implement, is for the
 *	first Wish app to create a gestalt of type 'WIsH'. This gestalt will
 *	point to a table, in system memory, of Tk apps. Each Tk app, when it
 *	starts up, will register their name, and process ID, in this table.
 *	This will allow us to implement "tk appname".
 *
 *	Then the send command will look up the process id of the target app in
 *	this table, and send an AppleEvent to that process. The AppleEvent
 *	handler is much like the do script handler, except that you have to
 *	specify the name of the tk app as well, since there may be many
 *	interps in one wish app, and you need to send it to the right one.
 *
 *	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 <[email protected]>
 * 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 <[email protected]>
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tkMacOSXInt.h"

277
278
279
280
281
282
283
284

285
286

287
288
289
290
291
292
293
277
278
279
280
281
282
283

284
285

286
287
288
289
290
291
292
293







-
+

-
+







    Tcl_DecrRefCount(resultObjPtr);
    Tcl_ResetResult(interp);

    /*
     * We have found a unique name. Now add it to the registry.
     */

    riPtr = ckalloc(sizeof(RegisteredInterp));
    riPtr = (RegisteredInterp *)ckalloc(sizeof(RegisteredInterp));
    riPtr->interp = interp;
    riPtr->name = ckalloc(strlen(actualName) + 1);
    riPtr->name = (char *)ckalloc(strlen(actualName) + 1);
    riPtr->nextPtr = interpListPtr;
    interpListPtr = riPtr;
    strcpy(riPtr->name, actualName);

    /*
     * TODO: DeleteProc
     */
316
317
318
319
320
321
322
323

324
325
326
327
328
329
330
331
332
333
334

335
336
337
338
339
340
341
316
317
318
319
320
321
322

323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342







-
+











+







 *	See the user documentation.
 *
 *--------------------------------------------------------------
 */

int
Tk_SendObjCmd(
    ClientData clientData,	/* Used only for deletion */
    ClientData dummy,	/* Not used */
    Tcl_Interp *interp,		/* The interp we are sending from */
    int objc,			/* Number of arguments */
    Tcl_Obj *const objv[])	/* The arguments */
{
    const char *const sendOptions[] = {"-async", "-displayof", "--", NULL};
    char *stringRep, *destName;
    /*int async = 0;*/
    int i, index, firstArg;
    RegisteredInterp *riPtr;
    Tcl_Obj *listObjPtr;
    int result = TCL_OK;
    (void)dummy;

    for (i = 1; i < (objc - 1); ) {
	stringRep = Tcl_GetString(objv[i]);
	if (stringRep[0] == '-') {
	    if (Tcl_GetIndexFromObjStruct(interp, objv[i], sendOptions,
		    sizeof(char *), "option", 0, &index) != TCL_OK) {
		return TCL_ERROR;
462
463
464
465
466
467
468

469
470
471
472
473
474
475
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477







+







TkGetInterpNames(
    Tcl_Interp *interp,		/* Interpreter for returning a result. */
    Tk_Window tkwin)		/* Window whose display is to be used for the
				 * lookup. */
{
    Tcl_Obj *listObjPtr;
    RegisteredInterp *riPtr;
    (void)tkwin;

    listObjPtr = Tcl_NewListObj(0, NULL);
    riPtr = interpListPtr;
    while (riPtr != NULL) {
	Tcl_ListObjAppendElement(interp, listObjPtr,
		Tcl_NewStringObj(riPtr->name, -1));
	riPtr = riPtr->nextPtr;
494
495
496
497
498
499
500
501

502
503
504

505
506
507
508
509
510
511
512
513
514
515
496
497
498
499
500
501
502

503


504
505
506
507
508
509
510
511
512
513
514
515
516







-
+
-
-

+











 *	Sets up various data structures and windows.
 *
 *--------------------------------------------------------------
 */

static int
SendInit(
    Tcl_Interp *interp)		/* Interpreter to use for error reporting (no
    Tcl_Interp *dummy)		/* Not used */
				 * errors are ever returned, but the
				 * interpreter is needed anyway). */
{
    (void)dummy;
    return TCL_OK;
}

/*
 * Local Variables:
 * mode: objc
 * c-basic-offset: 4
 * fill-column: 79
 * coding: utf-8
 * End:
 */
Changes to macosx/tkMacOSXServices.c.
1
2
3
4
5
6
7
8



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24


25
26

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47


48
49
50
51
52
53
54
1
2
3
4
5



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22


23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46


47
48
49
50
51
52
53
54
55





-
-
-
+
+
+














-
-
+
+


+



















-
-
+
+







/*
 * 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.
 */

#include <tkInt.h>
#include <tkMacOSXInt.h>

/*
 * Event proc which calls the PerformService procedure.
 */

static int
ServicesEventProc(
    Tcl_Event *event,
    int flags)
    TCL_UNUSED(Tcl_Event *),
    TCL_UNUSED(int))
{
    TkMainInfo *info = TkGetMainInfoList();

    Tcl_GlobalEval(info->interp, "::tk::mac::PerformService");
    return 1;
}

/*
 * The Wish application can send the current selection in the Tk clipboard
 * to other applications which accept messages of type NSString.  The TkService
 * object provides this service via its provideService method.  (The method
 * must be specified in the application's Info.plist file for this to work.)
 */

@interface TkService : NSObject {

}

+ (void) initialize;
- (void) provideService:(NSPasteboard *)pboard
	       userData:(NSString *)data
		  error:(NSString **)error;
- (BOOL)writeSelectionToPasteboard:(NSPasteboard *)pboard
			     types:(NSArray *)types;
- (BOOL) writeSelectionToPasteboard:(NSPasteboard *)pboard
			      types:(NSArray *)types;

@end

/*
 * Class methods.
 */

100
101
102
103
104
105
106


107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126

127
128
129
130
131
132
133

134
135
136
137
138
139
140

141
142
143
144
145
146
147
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128

129
130
131
132
133
134
135
136
137
138
139
140
141
142
143

144
145
146
147
148
149
150
151







+
+



















-
+







+






-
+







- (void)provideService:(NSPasteboard *)pboard
	      userData:(NSString *)data
		 error:(NSString **)error
{
    NSString *pboardString = nil, *pboardType = nil;
    NSArray *types = [pboard types];
    Tcl_Event *event;
    (void)data;
    (void)error;

    /*
     * Get a string from the private pasteboard and copy it to the general
     * pasteboard to make it available to other applications.
     */

    for (NSString *typeString in types) {
	if ([typeString isEqualToString:@"NSStringPboardType"] ||
	    [typeString isEqualToString:@"NSPasteboardTypeString"]) {
	    pboardString = [pboard stringForType:typeString];
	    pboardType = typeString;
	    break;
	}
    }
    if (pboardString) {
	NSPasteboard *generalpasteboard = [NSPasteboard generalPasteboard];
	[generalpasteboard declareTypes:[NSArray arrayWithObjects:pboardType, nil]
				  owner:nil];
	[generalpasteboard setString:pboardString forType:pboardType];
	event = ckalloc(sizeof(Tcl_Event));
	event = (Tcl_Event *)ckalloc(sizeof(Tcl_Event));
	event->proc = ServicesEventProc;
	Tcl_QueueEvent((Tcl_Event *)event, TCL_QUEUE_TAIL);
    }
}
@end

/*

 * Instantiate a TkService object and register it with the NSApplication.
 * This is called exactly one time from TkpInit.
 */

int
TkMacOSXServices_Init(
    Tcl_Interp *interp)
    TCL_UNUSED(Tcl_Interp *))
{
    /*
     * Initialize an instance of TkService and register it with the NSApp.
     */

    TkService *service = [[TkService alloc] init];
    [NSApp setServicesProvider:service];
Changes to macosx/tkMacOSXSubwindows.c.
1
2
3
4
5
6
7
8



9
10
11
12
13
14
15
16

17
18
19
20
21
22
23
1
2
3
4
5



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24





-
-
-
+
+
+








+







/*
 * 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 <[email protected]>
 * Copyright © 1995-1997 Sun Microsystems, Inc.
 * Copyright © 2001-2009 Apple Inc.
 * Copyright © 2006-2009 Daniel A. Steffen <[email protected]>
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tkMacOSXPrivate.h"
#include "tkMacOSXDebug.h"
#include "tkMacOSXWm.h"
#include "tkMacOSXConstants.h"

/*
#ifdef TK_MAC_DEBUG
#define TK_MAC_DEBUG_CLIP_REGIONS
#endif
*/

34
35
36
37
38
39
40
41

42
43
44
45
46
47
48
49
50
51
52
53
54

55
56
57

58
59
60
61
62
63
64
65
66
67
68
69
70
71

72
73
74
75
76
77
78
35
36
37
38
39
40
41

42
43
44
45
46
47
48
49
50
51
52
53
54

55
56
57

58
59
60
61
62
63
64
65
66
67
68
69
70
71

72
73
74
75
76
77
78
79







-
+












-
+


-
+













-
+









/*
 *----------------------------------------------------------------------
 *
 * XDestroyWindow --
 *
 *	Dealocates the given X Window.
 *	Deallocates the given X Window.
 *
 * Results:
 *	The window id is returned.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
XDestroyWindow(
    Display *display,		/* Display. */
    TCL_UNUSED(Display *),		/* Display. */
    Window window)		/* Window. */
{
    MacDrawable *macWin = (MacDrawable *) window;
    MacDrawable *macWin = (MacDrawable *)window;

    /*
     * Remove any dangling pointers that may exist if the window we are
     * deleting is being tracked by the grab code.
     */

    TkPointerDeadWindow(macWin->winPtr);
    TkMacOSXSelDeadWindow(macWin->winPtr);
    macWin->toplevel->referenceCount--;

    if (!Tk_IsTopLevel(macWin->winPtr)) {
	TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW);
	if (macWin->winPtr->parentPtr != NULL) {
	    TkMacOSXInvalClipRgns((Tk_Window) macWin->winPtr->parentPtr);
	    TkMacOSXInvalClipRgns((Tk_Window)macWin->winPtr->parentPtr);
	}
	if (macWin->visRgn) {
	    CFRelease(macWin->visRgn);
            macWin->visRgn = NULL;
	}
	if (macWin->aboveVisRgn) {
	    CFRelease(macWin->aboveVisRgn);
115
116
117
118
119
120
121
122
123




124
125
126

127
128
129



130
131
132
133
134
135
136
137
138



139

140
141

142

143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176








177
178
179
180
181
182
183
184
185
186

187
188
189
190

191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

213
214


215
216



217
218



219
220
221
222
223
224


225
226
227
228
229








230
231
232
233
234
235
236
116
117
118
119
120
121
122


123
124
125
126
127
128

129
130
131

132
133
134
135
136
137
138
139
140
141
142
143
144
145
146

147
148

149

150
151
152
153
154
155
156
157
158
159
160
161
162
163
164

165
166
167
168
169
170
171
172
173
174
175
176
177
178






179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195

196
197
198


199














200
201
202
203
204
205
206

207
208
209
210
211


212
213
214


215
216
217
218
219
220
221
222
223
224
225





226
227
228
229
230
231
232
233
234
235
236
237
238
239
240







-
-
+
+
+
+


-
+


-
+
+
+









+
+
+
-
+

-
+
-
+














-


+











-
-
-
-
-
-
+
+
+
+
+
+
+
+









-
+


-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-







-
+


+
+
-
-
+
+
+
-
-
+
+
+






+
+
-
-
-
-
-
+
+
+
+
+
+
+
+







}

/*
 *----------------------------------------------------------------------
 *
 * XMapWindow --
 *
 *	Map the given X Window to the screen. See X window documentation for
 *	more details.
 *	This X11 stub maps the given X11 Window but does not update any of
 *      the Tk structures describing the window.  Tk applications should
 *	never call this directly, but it is called by Tk_MapWindow and
 *      Tk_WmMapWindow.
 *
 * Results:
 *	None.
 *	Returns Success or BadWindow.
 *
 * Side effects:
 *	The subwindow or toplevel may appear on the screen.
 *	The subwindow or toplevel may appear on the screen.  VisibilityNotify
 *      events are generated.
 *
 *
 *----------------------------------------------------------------------
 */

int
XMapWindow(
    Display *display,		/* Display. */
    Window window)		/* Window. */
{
    if (!window) {
	return BadWindow;
    }
    MacDrawable *macWin = (MacDrawable *) window;
    MacDrawable *macWin = (MacDrawable *)window;
    TkWindow *winPtr = macWin->winPtr;
    NSWindow *win = TkMacOSXDrawableWindow(window);
    NSWindow *win = TkMacOSXGetNSWindowForDrawable(window);
    XEvent event;
    static Bool initialized = NO;

    /*
     * Under certain situations it's possible for this function to be called
     * before the toplevel window it's associated with has actually been
     * mapped. In that case we need to create the real Macintosh window now as
     * this function as well as other X functions assume that the portPtr is
     * valid.
     */

    if (!TkMacOSXHostToplevelExists(macWin->toplevel->winPtr)) {
	TkMacOSXMakeRealWindowExist(macWin->toplevel->winPtr);
    }

    display->request++;
    winPtr->flags |= TK_MAPPED;
    if (Tk_IsTopLevel(winPtr)) {
	if (!Tk_IsEmbedded(winPtr)) {
	    TKContentView *view = [win contentView];

	    /*
	     * We want to activate Tk when a toplevel is mapped but we must not
	     * supply YES here.  This is because during Tk initialization the
	     * root window is mapped before applicationDidFinishLaunching
	     * returns. Forcing the app to activate too early can make the menu
	     * bar unresponsive.
	     */

	    TkMacOSXApplyWindowAttributes(winPtr, win);
	    [win setExcludedFromWindowsMenu:NO];
	    [NSApp activateIgnoringOtherApps:NO];
	    [[win contentView] setNeedsDisplay:YES];
	    if ([win canBecomeKeyWindow]) {
		[win makeKeyAndOrderFront:NSApp];
	    } else {
		[win orderFrontRegardless];
	    [NSApp activateIgnoringOtherApps:initialized];
	    [view addTkDirtyRect: [view bounds]];
	    if (initialized) {
		if ([win canBecomeKeyWindow]) {
		    [win makeKeyAndOrderFront:NSApp];
		} else {
		    [win orderFrontRegardless];
		}
	    }
	} else {
	    TkWindow *contWinPtr = TkpGetOtherWindow(winPtr);

	    /*
	     * Rebuild the container's clipping region and display
	     * the window.
	     */

	    TkMacOSXInvalClipRgns((Tk_Window) contWinPtr);
	    TkMacOSXInvalClipRgns((Tk_Window)contWinPtr);
	    TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW);
	}

	TkMacOSXInvalClipRgns((Tk_Window) winPtr);
	TkMacOSXInvalClipRgns((Tk_Window)winPtr);

	/*
	 * We only need to send the MapNotify event for toplevel windows.
	 */

	event.xany.serial = LastKnownRequestProcessed(display);
	event.xany.send_event = False;
	event.xany.display = display;

	event.xmap.window = window;
	event.xmap.type = MapNotify;
	event.xmap.event = window;
	event.xmap.override_redirect = winPtr->atts.override_redirect;
	Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
    } else {

	/*
	 * For non-toplevel windows, rebuild the parent's clipping region
	 * and redisplay the window.
	 */

	TkMacOSXInvalClipRgns((Tk_Window) winPtr->parentPtr);
	TkMacOSXInvalClipRgns((Tk_Window)winPtr->parentPtr);
    }

    /*
     * Mark the toplevel as needing to be redrawn, unless the window is being
    if ([NSApp isDrawing]) {
	[[win contentView] setNeedsRedisplay:YES];
     * mapped while drawing is taking place.
     */

    } else {
	[[win contentView] setNeedsDisplay:YES];
    TKContentView *view = [win contentView];
    if (view != [NSView focusView]) {
	[view addTkDirtyRect:[view bounds]];
    }

    /*
     * Generate VisibilityNotify events for window and all mapped children.
     */

    if (initialized) {
	XEvent event;
    event.xany.send_event = False;
    event.xany.display = display;
    event.xvisibility.type = VisibilityNotify;
    event.xvisibility.state = VisibilityUnobscured;
    NotifyVisibility(winPtr, &event);
	event.xany.send_event = False;
	event.xany.display = display;
	event.xvisibility.type = VisibilityNotify;
	event.xvisibility.state = VisibilityUnobscured;
	NotifyVisibility(winPtr, &event);
    } else {
	initialized = YES;
    }
    return Success;
}

/*
 *----------------------------------------------------------------------
 *
 * NotifyVisibility --
265
266
267
268
269
270
271
272
273




274
275
276

277
278
279
280
281
282
283
284
285
286
287
288
289

290
291
292
293
294





295
296
297
298
299

300
301

302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325

326
327
328

329
330
331
332
333

334
335


336
337
338
339
340
341
342
269
270
271
272
273
274
275


276
277
278
279
280
281

282
283
284
285
286
287
288
289
290
291
292
293
294

295
296
297



298
299
300
301
302
303
304
305
306
307
308
309

310














311
312
313
314
315
316
317
318
319

320
321
322

323
324
325



326


327
328
329
330
331
332
333
334
335







-
-
+
+
+
+


-
+












-
+


-
-
-
+
+
+
+
+





+

-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-









-
+


-
+


-
-
-
+
-
-
+
+







}

/*
 *----------------------------------------------------------------------
 *
 * XUnmapWindow --
 *
 *	Unmap the given X Window to the screen. See X window documentation for
 *	more details.
 *	This X11 stub maps the given X11 Window but does not update any of
 *	The Tk structures describing the window.  Tk applications should
 *	never call this directly, but it is called by Tk_UnmapWindow and
 *      Tk_WmUnmapWindow.
 *
 * Results:
 *	None.
 *	Always returns Success or BadWindow.
 *
 * Side effects:
 *	The subwindow or toplevel may be removed from the screen.
 *
 *----------------------------------------------------------------------
 */

int
XUnmapWindow(
    Display *display,		/* Display. */
    Window window)		/* Window. */
{
    MacDrawable *macWin = (MacDrawable *) window;
    MacDrawable *macWin = (MacDrawable *)window;
    TkWindow *winPtr = macWin->winPtr;
    TkWindow *parentPtr = winPtr->parentPtr;
    NSWindow *win = TkMacOSXDrawableWindow(window);
    XEvent event;

    NSWindow *win = TkMacOSXGetNSWindowForDrawable(window);

    if (!window) {
	return BadWindow;
    }
    display->request++;
    if (Tk_IsTopLevel(winPtr)) {
	if (!Tk_IsEmbedded(winPtr) &&
		winPtr->wmInfoPtr->hints.initial_state!=IconicState) {
	    [win orderOut:nil];
	    [win setExcludedFromWindowsMenu:YES];
	}
	TkMacOSXInvalClipRgns((Tk_Window) winPtr);
	TkMacOSXInvalClipRgns((Tk_Window)winPtr);

	/*
	 * We only need to send the UnmapNotify event for toplevel windows.
	 */

	event.xany.serial = LastKnownRequestProcessed(display);
	event.xany.send_event = False;
	event.xany.display = display;

	event.xunmap.type = UnmapNotify;
	event.xunmap.window = window;
	event.xunmap.event = window;
	event.xunmap.from_configure = false;
	Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
    } else {
	/*
	 * Rebuild the visRgn clip region for the parent so it will be allowed
	 * to draw in the space from which this subwindow was removed and then
	 * redraw the window.
	 */

	if (parentPtr && parentPtr->privatePtr->visRgn) {
	    TkMacOSXInvalidateViewRegion(
		    TkMacOSXDrawableView(parentPtr->privatePtr),
		    TkMacOSXGetNSViewForDrawable(parentPtr->privatePtr),
		    parentPtr->privatePtr->visRgn);
	}
	TkMacOSXInvalClipRgns((Tk_Window) parentPtr);
	TkMacOSXInvalClipRgns((Tk_Window)parentPtr);
	TkMacOSXUpdateClipRgn(parentPtr);
    }
    winPtr->flags &= ~TK_MAPPED;
    if ([NSApp isDrawing]) {
	[[win contentView] setNeedsRedisplay:YES];
    TKContentView *view = [win contentView];
    } else {
	[[win contentView] setNeedsDisplay:YES];
    if (view != [NSView focusView]) {
	[view addTkDirtyRect:[view bounds]];
    }
    return Success;
}

/*
 *----------------------------------------------------------------------
 *
357
358
359
360
361
362
363
364

365
366
367
368

369
370



371

372
373
374
375
376





377
378
379
380
381
382
383
350
351
352
353
354
355
356

357
358
359
360

361
362
363
364
365
366

367
368




369
370
371
372
373
374
375
376
377
378
379
380







-
+



-
+


+
+
+
-
+

-
-
-
-
+
+
+
+
+







int
XResizeWindow(
    Display *display,		/* Display. */
    Window window,		/* Window. */
    unsigned int width,
    unsigned int height)
{
    MacDrawable *macWin = (MacDrawable *) window;
    MacDrawable *macWin = (MacDrawable *)window;

    display->request++;
    if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {
	NSWindow *w = macWin->winPtr->wmInfoPtr->window;
	TKWindow *w = (TKWindow *)macWin->winPtr->wmInfoPtr->window;

	if (w) {
	    if ([w styleMask] & NSFullScreenWindowMask) {
		[w tkLayoutChanged];
	    } else {
	    NSRect r = [w contentRectForFrameRect:[w frame]];
		NSRect r = [w contentRectForFrameRect:[w frame]];

	    r.origin.y += r.size.height - height;
	    r.size.width = width;
	    r.size.height = height;
	    [w setFrame:[w frameRectForContentRect:r] display:YES];
		r.origin.y += r.size.height - height;
		r.size.width = width;
		r.size.height = height;
		[w setFrame:[w frameRectForContentRect:r] display:NO];
	    }
	}
    } else {
	MoveResizeWindow(macWin);
    }
    return Success;
}

402
403
404
405
406
407
408
409

410
411
412
413
414
415
416
399
400
401
402
403
404
405

406
407
408
409
410
411
412
413







-
+







XMoveResizeWindow(
    Display *display,		/* Display. */
    Window window,		/* Window. */
    int x, int y,
    unsigned int width,
    unsigned int height)
{
    MacDrawable *macWin = (MacDrawable *) window;
    MacDrawable *macWin = (MacDrawable *)window;

    display->request++;
    if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {
	NSWindow *w = macWin->winPtr->wmInfoPtr->window;

	if (w) {
	    /*
425
426
427
428
429
430
431
432

433
434
435
436
437
438
439
422
423
424
425
426
427
428

429
430
431
432
433
434
435
436







-
+







	    CGFloat Height = (CGFloat) height;
	    CGFloat XOff = (CGFloat) macWin->winPtr->wmInfoPtr->xInParent;
	    CGFloat YOff = (CGFloat) macWin->winPtr->wmInfoPtr->yInParent;
	    NSRect r = NSMakeRect(
		    X + XOff, TkMacOSXZeroScreenHeight() - Y - YOff - Height,
	    	    Width, Height);

	    [w setFrame:[w frameRectForContentRect:r] display:YES];
	    [w setFrame:[w frameRectForContentRect:r] display:NO];
	}
    } else {
	MoveResizeWindow(macWin);
    }
    return Success;
}

455
456
457
458
459
460
461
462

463
464
465
466
467
468
469
452
453
454
455
456
457
458

459
460
461
462
463
464
465
466







-
+








int
XMoveWindow(
    Display *display,		/* Display. */
    Window window,		/* Window. */
    int x, int y)
{
    MacDrawable *macWin = (MacDrawable *) window;
    MacDrawable *macWin = (MacDrawable *)window;

    display->request++;
    if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {
	NSWindow *w = macWin->winPtr->wmInfoPtr->window;

	if (w) {
	    [w setFrameTopLeftPoint: NSMakePoint(
493
494
495
496
497
498
499
500

501
502
503
504
505
506
507
490
491
492
493
494
495
496

497
498
499
500
501
502
503
504







-
+








static void
MoveResizeWindow(
    MacDrawable *macWin)
{
    int deltaX = 0, deltaY = 0, parentBorderwidth = 0;
    MacDrawable *macParent = NULL;
    NSWindow *macWindow = TkMacOSXDrawableWindow((Drawable) macWin);
    NSWindow *macWindow = TkMacOSXGetNSWindowForDrawable((Drawable)macWin);

    /*
     * Find the Parent window, for an embedded window it will be its container.
     */

    if (Tk_IsEmbedded(macWin->winPtr)) {
	TkWindow *contWinPtr = TkpGetOtherWindow(macWin->winPtr);
530
531
532
533
534
535
536
537

538
539
540
541
542
543
544
527
528
529
530
531
532
533

534
535
536
537
538
539
540
541







-
+







		macWin->winPtr->changes.x - macWin->xOff;
	deltaY = macParent->yOff + parentBorderwidth +
		macWin->winPtr->changes.y - macWin->yOff;
    }
    if (macWindow) {
	TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW);
	if (macParent) {
	    TkMacOSXInvalClipRgns((Tk_Window) macParent->winPtr);
	    TkMacOSXInvalClipRgns((Tk_Window)macParent->winPtr);
	}
    }
    UpdateOffsets(macWin->winPtr, deltaX, deltaY);
    if (macWindow) {
	TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW);
    }
    GenerateConfigureNotify(macWin->winPtr, 0);
598
599
600
601
602
603
604
605

606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635

636
637
638
639
640

641
642
643
644
645
646

647
648
649

650
651
652
653
654
655
656
657
658
595
596
597
598
599
600
601

602
603
604
605
606
607
608
609
610
611
612
613
614

615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630

631
632
633
634
635

636
637
638
639
640
641

642
643
644
645
646
647

648
649
650
651
652
653
654







-
+












-
















-
+




-
+





-
+



+

-







 */

int
XRaiseWindow(
    Display *display,		/* Display. */
    Window window)		/* Window. */
{
    MacDrawable *macWin = (MacDrawable *) window;
    MacDrawable *macWin = (MacDrawable *)window;

    display->request++;
    if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {
	TkWmRestackToplevel(macWin->winPtr, Above, NULL);
    } else {
	/*
	 * TODO: this should generate damage
	 */
    }
    return Success;
}

#if 0
/*
 *----------------------------------------------------------------------
 *
 * XLowerWindow --
 *
 *	Change the stacking order of a window.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Changes the stacking order of the specified window.
 *
 *----------------------------------------------------------------------
 */

void
int
XLowerWindow(
    Display *display,		/* Display. */
    Window window)		/* Window. */
{
    MacDrawable *macWin = (MacDrawable *) window;
    MacDrawable *macWin = (MacDrawable *)window;

    display->request++;
    if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {
	TkWmRestackToplevel(macWin->winPtr, Below, NULL);
    } else {
        /*
	/*
	 * TODO: this should generate damage
	 */
    }
    return Success;
}
#endif

/*
 *----------------------------------------------------------------------
 *
 * XConfigureWindow --
 *
 *	Change the size, position, stacking, or border of the specified window.
669
670
671
672
673
674
675
676

677
678

679
680
681
682
683
684
685
665
666
667
668
669
670
671

672
673

674
675
676
677
678
679
680
681







-
+

-
+







 */

int
XConfigureWindow(
    Display *display,		/* Display. */
    Window w,			/* Window. */
    unsigned int value_mask,
    XWindowChanges *values)
    TCL_UNUSED(XWindowChanges *))
{
    MacDrawable *macWin = (MacDrawable *) w;
    MacDrawable *macWin = (MacDrawable *)w;
    TkWindow *winPtr = macWin->winPtr;

    display->request++;

    /*
     * Change the shape and/or position of the window.
     */
693
694
695
696
697
698
699
700

701
702
703
704
705

706
707
708
709
710

711
712
713
714
715
716
717
689
690
691
692
693
694
695

696


697
698

699





700
701
702
703
704
705
706
707







-
+
-
-


-
+
-
-
-
-
-
+







     * Change the stacking order of the window. Tk actually keeps all the
     * information we need for stacking order. All we need to do is make sure
     * the clipping regions get updated and generate damage that will ensure
     * things get drawn correctly.
     */

    if (value_mask & CWStackMode) {
	NSView *view = TkMacOSXDrawableView(macWin);
	NSView *view = TkMacOSXGetNSViewForDrawable(macWin);
	Rect bounds;
	NSRect r;

	if (view) {
	    TkMacOSXInvalClipRgns((Tk_Window) winPtr->parentPtr);
	    TkMacOSXInvalClipRgns((Tk_Window)winPtr->parentPtr);
	    TkMacOSXWinBounds(winPtr, &bounds);
	    r = NSMakeRect(bounds.left,
		    [view bounds].size.height - bounds.bottom,
		    bounds.right - bounds.left, bounds.bottom - bounds.top);
	    [view setNeedsDisplayInRect:r];
	    TkpRedrawWidget((Tk_Window)winPtr);
	}
    }

#if 0
    TkGenWMMoveRequestEvent(macWin->winPtr,
	    macWin->winPtr->changes.x, macWin->winPtr->changes.y);
#endif
822
823
824
825
826
827
828
829

830
831
832
833
834
835
836
812
813
814
815
816
817
818

819
820
821
822
823
824
825
826







-
+







	     */

	    TkMacOSXWinCGBounds(winPtr, &bounds);
	    rgn = TkMacOSXHIShapeCreateMutableWithRect(&bounds);

	    /*
	     * Clip away the area of any windows that may obscure this window.
	     * For a non-toplevel window, first, clip to the parents visible
	     * For a non-toplevel window, first, clip to the parent's visible
	     * clip region. Second, clip away any siblings that are higher in
	     * the stacking order. For an embedded toplevel, just clip to the
	     * container's visible clip region. Remember, we only allow one
	     * contained window in a frame, and don't support any other widgets
	     * in the frame either. This is not currently enforced, however.
	     */

851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
841
842
843
844
845
846
847









848
849
850
851
852
853
854







-
-
-
-
-
-
-
-
-







		}
	    } else if (Tk_IsEmbedded(winPtr)) {
		win2Ptr = TkpGetOtherWindow(winPtr);
		if (win2Ptr) {
		    TkMacOSXUpdateClipRgn(win2Ptr);
		    ChkErr(HIShapeIntersect,
			    win2Ptr->privatePtr->aboveVisRgn, rgn, rgn);
		} else if (tkMacOSXEmbedHandler != NULL) {
		    TkRegion r = TkCreateRegion();
		    HIShapeRef visRgn;

		    tkMacOSXEmbedHandler->getClipProc((Tk_Window) winPtr, r);
		    visRgn = TkMacOSXGetNativeRegion(r);
		    ChkErr(HIShapeIntersect, visRgn, rgn, rgn);
		    CFRelease(visRgn);
		    TkpReleaseRegion(r);
		}

		/*
		 * TODO: Here we should handle out of process embedding.
		 */
	    }
	    macWin->aboveVisRgn = HIShapeCreateCopy(rgn);
943
944
945
946
947
948
949
950

951
952
953
954
955
956
957
958
959
960
961

962
963
964
965
966
967
968

969
970
971
972
973
974
975
924
925
926
927
928
929
930

931
932
933
934
935
936
937
938
939
940
941

942
943
944
945
946
947
948

949
950
951
952
953
954
955
956







-
+










-
+






-
+







/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXVisableClipRgn --
 *
 *	This function returns the Macintosh clipping region for the given
 *	window. The caller is responsible for disposing of the returned region
 *	via TkDestroyRegion().
 *	via XDestroyRegion().
 *
 * Results:
 *	The region.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

TkRegion
Region
TkMacOSXVisableClipRgn(
    TkWindow *winPtr)
{
    if (winPtr->privatePtr->flags & TK_CLIP_INVALID) {
	TkMacOSXUpdateClipRgn(winPtr);
    }
    return (TkRegion) HIShapeCreateMutableCopy(winPtr->privatePtr->visRgn);
    return (Region) HIShapeCreateMutableCopy(winPtr->privatePtr->visRgn);
}

/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXInvalidateViewRegion --
 *
983
984
985
986
987
988
989
990

991
992
993
994
995


996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007


1008
1009
1010
1011
1012
1013
1014
964
965
966
967
968
969
970

971
972
973
974
975

976
977
978
979
980
981
982
983
984
985
986
987


988
989
990
991
992
993
994
995
996







-
+




-
+
+










-
-
+
+







 *
 *----------------------------------------------------------------------
 */

static OSStatus
InvalViewRect(
    int msg,
    HIShapeRef rgn,
    TCL_UNUSED(HIShapeRef),
    const CGRect *rect,
    void *ref)
{
    static CGAffineTransform t;
    NSView *view = ref;
    TKContentView *view = ref;
    NSRect dirtyRect;

    if (!view) {
	return paramErr;
    }
    switch (msg) {
    case kHIShapeEnumerateInit:
	t = CGAffineTransformMake(1.0, 0.0, 0.0, -1.0, 0.0,
		NSHeight([view bounds]));
	break;
    case kHIShapeEnumerateRect:
	[view setNeedsDisplayInRect:NSRectFromCGRect(
		CGRectApplyAffineTransform(*rect, t))];
	dirtyRect = NSRectFromCGRect(CGRectApplyAffineTransform(*rect, t));
	[view addTkDirtyRect:dirtyRect];
	break;
    }
    return noErr;
}

void
TkMacOSXInvalidateViewRegion(
1046
1047
1048
1049
1050
1051
1052
1053

1054
1055
1056
1057
1058
1059
1060

1061
1062


1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074


1075
1076
1077

1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098

1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169


1170





1171
1172


1173
1174
1175

1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191

















1192
1193
1194
1195
1196
1197
1198
1028
1029
1030
1031
1032
1033
1034

1035
1036
1037
1038
1039
1040
1041

1042
1043

1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055


1056
1057
1058
1059

1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075






1076































































1077
1078
1079
1080
1081
1082
1083
1084
1085
1086

1087
1088
1089
1090
1091
1092

1093
1094
1095
1096

1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108





1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132







-
+






-
+

-
+
+










-
-
+
+


-
+















-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-








+
+
-
+
+
+
+
+

-
+
+


-
+











-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







{
#ifdef TK_MAC_DEBUG_CLIP_REGIONS
    TkMacOSXDbgMsg("%s", macWin->winPtr->pathName);
#endif
    if (macWin->flags & TK_CLIP_INVALID) {
	TkMacOSXUpdateClipRgn(macWin->winPtr);
    }
    TkMacOSXInvalidateViewRegion(TkMacOSXDrawableView(macWin),
    TkMacOSXInvalidateViewRegion(TkMacOSXGetNSViewForDrawable(macWin),
	    (flag == TK_WINDOW_ONLY) ? macWin->visRgn : macWin->aboveVisRgn);
}

/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXDrawableWindow --
 * TkMacOSXGetNSWindowForDrawable --
 *
 *	This function returns the NSWindow for a given X drawable.
 *	This function returns the NSWindow for a given X drawable, if the
 *      drawable is a window.  If the drawable is a pixmap it returns nil.
 *
 * Results:
 *	A NSWindow, or nil for off screen pixmaps.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

NSWindow *
TkMacOSXDrawableWindow(
void *
Tk_MacOSXGetNSWindowForDrawable(
    Drawable drawable)
{
    MacDrawable *macWin = (MacDrawable *) drawable;
    MacDrawable *macWin = (MacDrawable *)drawable;
    NSWindow *result = nil;

    if (!macWin || macWin->flags & TK_IS_PIXMAP) {
	result = nil;
    } else if (macWin->toplevel && macWin->toplevel->winPtr &&
	    macWin->toplevel->winPtr->wmInfoPtr &&
	    macWin->toplevel->winPtr->wmInfoPtr->window) {
	result = macWin->toplevel->winPtr->wmInfoPtr->window;
    } else if (macWin->winPtr && macWin->winPtr->wmInfoPtr &&
	    macWin->winPtr->wmInfoPtr->window) {
	result = macWin->winPtr->wmInfoPtr->window;
    } else if (macWin->toplevel && (macWin->toplevel->flags & TK_EMBEDDED)) {
	TkWindow *contWinPtr = TkpGetOtherWindow(macWin->toplevel->winPtr);

	if (contWinPtr) {
	    result = TkMacOSXDrawableWindow((Drawable) contWinPtr->privatePtr);
	}
    }
    return result;
}

	    result = TkMacOSXGetNSWindowForDrawable((Drawable)contWinPtr->privatePtr);
void *
TkMacOSXDrawable(
    Drawable drawable)
{
    return TkMacOSXDrawableWindow(drawable);
}

/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXGetDrawablePort --
 *
 *	This function returns the Graphics Port for a given X drawable.
 *
 * Results:
 *	NULL.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void *
TkMacOSXGetDrawablePort(
    Drawable drawable)
{
    return NULL;
}

/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXDrawableView --
 *
 *	This function returns the NSView for a given X drawable.
 *
 * Results:
 *	A NSView* or nil.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

NSView *
TkMacOSXDrawableView(
    MacDrawable *macWin)
{
    NSView *result = nil;

    if (!macWin) {
	result = nil;
    } else if (!macWin->toplevel) {
	result = macWin->view;
    } else if (!(macWin->toplevel->flags & TK_EMBEDDED)) {
	result = macWin->toplevel->view;
    } else {
	TkWindow *contWinPtr = TkpGetOtherWindow(macWin->toplevel->winPtr);

	if (contWinPtr) {
	    result = TkMacOSXDrawableView(contWinPtr->privatePtr);
	}
    }
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXGetNSViewForDrawable/TkMacOSXGetRootControl --
 *
 * TkMacOSXGetRootControl --
 *	The function name TkMacOSXGetRootControl is being preserved only
 *      because it exists in a stubs table.  Nobody knows what it means to
 *      get a "RootControl".  The macro TkMacOSXGetNSViewForDrawable calls
 *      this function and should always be used rather than directly using
 *      the obscure official name of this function.
 *
 *	This function returns the NSView for a given X drawable.
 *      It returns the NSView for a given X drawable in the case that the
 *      drawable is a window.  If the drawable is a pixmap it returns nil.
 *
 * Results:
 *	A NSView* .
 *	A NSView* or nil.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void *
TkMacOSXGetRootControl(
    Drawable drawable)
{
    /*
     * will probably need to fix this up for embedding
     */

    return TkMacOSXDrawableView((MacDrawable *) drawable);
    void *result = NULL;
    MacDrawable *macWin = (MacDrawable *)drawable;

    if (!macWin) {
	result = NULL;
    } else if (!macWin->toplevel) {
	result = macWin->view;
    } else if (!(macWin->toplevel->flags & TK_EMBEDDED)) {
	result = macWin->toplevel->view;
    } else {
	TkWindow *contWinPtr = TkpGetOtherWindow(macWin->toplevel->winPtr);

	if (contWinPtr) {
	    result = TkMacOSXGetRootControl((Drawable)contWinPtr->privatePtr);
	}
    }
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXInvalClipRgns --
 *
1250
1251
1252
1253
1254
1255
1256
1257

1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270

1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284

1285
1286
1287
1288
1289
1290
1291
1292
1293

1294
1295
1296
1297
1298
1299
1300
1184
1185
1186
1187
1188
1189
1190

1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203

1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217

1218
1219
1220
1221
1222
1223
1224
1225
1226

1227
1228
1229
1230
1231
1232
1233
1234







-
+












-
+













-
+








-
+







     * Invalidate clip regions for all children & their descendants, unless the
     * child is a toplevel.
     */

    childPtr = winPtr->childList;
    while (childPtr) {
	if (!Tk_IsTopLevel(childPtr)) {
	    TkMacOSXInvalClipRgns((Tk_Window) childPtr);
	    TkMacOSXInvalClipRgns((Tk_Window)childPtr);
	}
	childPtr = childPtr->nextPtr;
    }

    /*
     * Also, if the window is a container, mark its embedded window.
     */

    if (Tk_IsContainer(winPtr)) {
	childPtr = TkpGetOtherWindow(winPtr);

	if (childPtr) {
	    TkMacOSXInvalClipRgns((Tk_Window) childPtr);
	    TkMacOSXInvalClipRgns((Tk_Window)childPtr);
	}

	/*
	 * TODO: Here we should handle out of process embedding.
	 */
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXWinBounds --
 *
 *	Given a Tk window this function determines the windows bounds in
 *	Given a Tk window this function determines the window's bounds in
 *	relation to the Macintosh window's coordinate system. This is also the
 *	same coordinate system as the Tk toplevel window in which this window
 *	is contained.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *	Fills in a Rect.
 *
 *----------------------------------------------------------------------
 */

void
TkMacOSXWinBounds(
    TkWindow *winPtr,
1309
1310
1311
1312
1313
1314
1315
1316

1317
1318
1319


1320
1321
1322
1323
1324
1325

1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339

































1340
1341
1342
1343
1344
1345
1346
1243
1244
1245
1246
1247
1248
1249

1250



1251
1252
1253
1254
1255
1256
1257

1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312







-
+
-
-
-
+
+





-
+














+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







}

/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXWinCGBounds --
 *
 *	Given a Tk window this function determines the windows bounds in
 *	Given a Tk window this function determines the window's bounds in
 *	relation to the Macintosh window's coordinate system. This is also the
 *	same coordinate system as the Tk toplevel window in which this window
 *	is contained.
 *	the coordinate system of the Tk toplevel window in which this window
 *	is contained.  This fills in a CGRect struct.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *	Fill in a CGRect.
 *
 *----------------------------------------------------------------------
 */

void
TkMacOSXWinCGBounds(
    TkWindow *winPtr,
    CGRect *bounds)
{
    bounds->origin.x = winPtr->privatePtr->xOff;
    bounds->origin.y = winPtr->privatePtr->yOff;
    bounds->size.width = winPtr->changes.width;
    bounds->size.height = winPtr->changes.height;
}
/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXWinNSBounds --
 *
 *	Given a Tk window this function determines the window's bounds in
 *	the coordinate system of the TKContentView in which this Tk window
 *	is contained, which has the origin at the lower left corner.  This
 *      fills in an NSRect struct and requires the TKContentView as a
 *      parameter
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Fills in an NSRect.
 *
 *----------------------------------------------------------------------
 */

void
TkMacOSXWinNSBounds(
    TkWindow *winPtr,
    NSView *view,
    NSRect *bounds)
{
    bounds->size.width = winPtr->changes.width;
    bounds->size.height = winPtr->changes.height;
    bounds->origin.x = winPtr->privatePtr->xOff;
    bounds->origin.y = ([view bounds].size.height -
		       bounds->size.height -
		       winPtr->privatePtr->yOff);
}

/*
 *----------------------------------------------------------------------
 *
 * UpdateOffsets --
 *
 *	Updates the X & Y offsets of the given TkWindow from the TopLevel it is
1413
1414
1415
1416
1417
1418
1419
1420

1421
1422
1423
1424
1425
1426
1427
1428
1429
1430

1431
1432
1433
1434
1435
1436
1437
1379
1380
1381
1382
1383
1384
1385

1386
1387
1388
1389
1390
1391
1392
1393
1394
1395

1396
1397
1398
1399
1400
1401
1402
1403







-
+









-
+







 *
 *----------------------------------------------------------------------
 */

Pixmap
Tk_GetPixmap(
    Display *display,	/* Display for new pixmap (can be null). */
    Drawable d,		/* Drawable where pixmap will be used (ignored). */
    TCL_UNUSED(Drawable),		/* Drawable where pixmap will be used (ignored). */
    int width,		/* Dimensions of pixmap. */
    int height,
    int depth)		/* Bits per pixel for pixmap. */
{
    MacDrawable *macPix;

    if (display != NULL) {
	display->request++;
    }
    macPix = ckalloc(sizeof(MacDrawable));
    macPix = (MacDrawable *)ckalloc(sizeof(MacDrawable));
    macPix->winPtr = NULL;
    macPix->xOff = 0;
    macPix->yOff = 0;
    macPix->visRgn = NULL;
    macPix->aboveVisRgn = NULL;
    macPix->drawRgn = NULL;
    macPix->referenceCount = 0;
1461
1462
1463
1464
1465
1466
1467
1468

1469
1470
1471
1472
1473
1474
1475
1427
1428
1429
1430
1431
1432
1433

1434
1435
1436
1437
1438
1439
1440
1441







-
+







 */

void
Tk_FreePixmap(
    Display *display,		/* Display. */
    Pixmap pixmap)		/* Pixmap to destroy */
{
    MacDrawable *macPix = (MacDrawable *) pixmap;
    MacDrawable *macPix = (MacDrawable *)pixmap;

    display->request++;
    if (macPix->context) {
	char *data = CGBitmapContextGetData(macPix->context);

	if (data) {
	    ckfree(data);
Added macosx/tkMacOSXSysTray.c.

































































































































































































































































































































































































































































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
 * 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 <tkInt.h>
#include <tkMacOSXInt.h>
#include "tkMacOSXPrivate.h"

/*
 * Prior to macOS 10.14 user notifications were handled by the NSApplication's
 * NSUserNotificationCenter via a NSUserNotificationCenterDelegate object.
 * These classes were defined in the CoreFoundation framework.  In macOS 10.14
 * a separate UserNotifications framework was introduced which adds some
 * additional features, including custom controls on the notification window
 * but primarily a requirement that an application must be authorized before
 * being allowed to post a notification.  This framework uses a different
 * class, the UNUserNotificationCenter, and its delegate follows a different
 * protocol, named UNUserNotificationCenterDelegate.
 *
 * In macOS 11.0 the NSUserNotificationCenter and its delegate protocol were
 * deprecated.  To make matters more complicated, it turns out that there is a
 * secret undocumented additional requirement that an app which is not signed
 * can never be authorized to send notifications via the UNNotificationCenter.
 * (As of 11.0, it appears that it is sufficient to sign the app with a
 * self-signed certificate, however.)
 *
 * The workaround implemented here is to define two classes, TkNSNotifier and
 * TkUNNotifier, each of which provides one of these protocols on macOS 10.14
 * and newer.  If the TkUSNotifier is able to obtain authorization it is used.
 * Otherwise, TkNSNotifier is used.  Building TkNSNotifier on 11.0 or later
 * produces deprecation warnings which are suppressed by enclosing the
 * interface and implementation in #pragma blocks.  The first time that the tk
 * systray command in initialized in an interpreter an attempt is made to
 * obtain authorization for sending notifications with the UNNotificationCenter
 * on systems and the result is saved in a static variable.
 */

//#define DEBUG
#ifdef DEBUG

/*
 * This macro uses the do ... while(0) trick to swallow semicolons.  It logs to
 * a temp file because apps launched from an icon have no stdout or stderr and
 * because NSLog has a tendency to not produce any console messages at certain
 * stages of launching an app.
 */

#define DEBUG_LOG(format, ...)                \
    do {				      \
    FILE* logfile = fopen("/tmp/tklog", "a"); \
    fprintf(logfile, format, ##__VA_ARGS__);  \
    fflush(logfile);                          \
    fclose(logfile); } while (0)
#else
#define DEBUG_LOG(format, ...)
#endif

#define BUILD_TARGET_HAS_NOTIFICATION (MAC_OS_X_VERSION_MAX_ALLOWED >= 101000)
#define BUILD_TARGET_HAS_UN_FRAMEWORK (MAC_OS_X_VERSION_MAX_ALLOWED >= 101400)
#if MAC_OS_X_VERSION_MAX_ALLOWED > 101500
#define ALERT_OPTION  UNNotificationPresentationOptionList | \
    		      UNNotificationPresentationOptionBanner
#else
#define ALERT_OPTION  UNNotificationPresentationOptionAlert
#endif

#if BUILD_TARGET_HAS_UN_FRAMEWORK
#import <UserNotifications/UserNotifications.h>
static NSString *TkNotificationCategory;
#endif

#if BUILD_TARGET_HAS_NOTIFICATION

/*
 * 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 TkNSNotifier. A TkNSNotifier object has no attributes
 * but implements the NSUserNotificationCenterDelegate protocol.  It also has
 * one additional method which posts a user notification. There is one
 * TkNSNotifier for the application, shared by all interpreters.
 */

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
@interface TkNSNotifier: NSObject {
}

/*
 * Post a notification.
 */

- (void) postNotificationWithTitle : (NSString *) title message: (NSString *) detail;

/*
 * The following methods comprise the NSUserNotificationCenterDelegate protocol.
 */

- (void) userNotificationCenter:(NSUserNotificationCenter *)center
    didDeliverNotification:(NSUserNotification *)notification;

- (void) userNotificationCenter:(NSUserNotificationCenter *)center
    didActivateNotification:(NSUserNotification *)notification;

- (BOOL) userNotificationCenter:(NSUserNotificationCenter *)center
    shouldPresentNotification:(NSUserNotification *)notification;

@end
#pragma clang diagnostic pop

/*
 * The singleton instance of TkNSNotifier shared by all interpreters in this
 * application.
 */

static TkNSNotifier *NSnotifier = nil;

#if BUILD_TARGET_HAS_UN_FRAMEWORK

/*
 * Class declaration for TkUNNotifier. A TkUNNotifier object has no attributes
 * but implements the UNUserNotificationCenterDelegate protocol It also has two
 * additional methods.  One requests authorization to post notification via the
 * UserNotification framework and the other posts a user notification. There is
 * at most one TkUNNotifier for the application, shared by all interpreters.
 */

@interface TkUNNotifier: NSObject {
}

 /*
 * Request authorization to post a notification.
 */

- (void) requestAuthorization;

/*
 * Post a notification.
 */

- (void) postNotificationWithTitle : (NSString *) title message: (NSString *) detail;

/*
 * The following methods comprise the UNNotificationCenterDelegate protocol:
 */

- (void)userNotificationCenter:(UNUserNotificationCenter *)center
    didReceiveNotificationResponse:(UNNotificationResponse *)response
    withCompletionHandler:(void (^)(void))completionHandler;

- (void)userNotificationCenter:(UNUserNotificationCenter *)center
    willPresentNotification:(UNNotification *)notification
    withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler;

- (void)userNotificationCenter:(UNUserNotificationCenter *)center
   openSettingsForNotification:(UNNotification *)notification;

@end

/*
 * The singleton instance of TkUNNotifier shared by all interpeters is stored
 * in this static variable.
 */

static TkUNNotifier *UNnotifier = nil;

#endif

/*
 * 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;

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
@implementation TkNSNotifier : NSObject

-  (void) postNotificationWithTitle : (NSString * ) title
			     message: (NSString * ) detail
{
    NSUserNotification *notification;
    NSUserNotificationCenter *center;

    center = [NSUserNotificationCenter defaultUserNotificationCenter];
    notification = [[NSUserNotification alloc] init];
    notification.title = title;
    notification.informativeText = detail;
    notification.soundName = NSUserNotificationDefaultSoundName;
    DEBUG_LOG("Sending NSNotification.\n");
    [center deliverNotification:notification];
}

/*
 * Implementation of the NSUserNotificationDelegate protocol.
 */

- (BOOL) userNotificationCenter: (NSUserNotificationCenter *) center
         shouldPresentNotification: (NSUserNotification *)notification
{
    (void) center;
    (void) notification;

    return YES;
}

- (void) userNotificationCenter:(NSUserNotificationCenter *)center
         didDeliverNotification:(NSUserNotification *)notification
{
    (void) center;
    (void) notification;
}

- (void) userNotificationCenter:(NSUserNotificationCenter *)center
	 didActivateNotification:(NSUserNotification *)notification
{
    (void) center;
    (void) notification;
}

@end
#pragma clang diagnostic pop

/*
 * Static variable which records whether the app is authorized to send
 * notifications via the UNUserNotificationCenter.
 */

#if BUILD_TARGET_HAS_UN_FRAMEWORK

@implementation TkUNNotifier : NSObject

- (void) requestAuthorization
{
    UNUserNotificationCenter *center;
    UNAuthorizationOptions options = UNAuthorizationOptionAlert |
				     UNAuthorizationOptionSound |
				     UNAuthorizationOptionBadge |
	    UNAuthorizationOptionProvidesAppNotificationSettings;
    if (![NSApp isSigned]) {

	/*
	 * No point in even asking.
	 */

	DEBUG_LOG("Unsigned app: UNUserNotifications are not available.\n");
	return;
    }

    center = [UNUserNotificationCenter currentNotificationCenter];
    [center requestAuthorizationWithOptions: options
	  completionHandler: ^(BOOL granted, NSError* error)
	    {
		if (error || granted == NO) {
		    DEBUG_LOG("Authorization for UNUserNotifications denied\n");
		}
	    }];
}

-  (void) postNotificationWithTitle: (NSString * ) title
			     message: (NSString * ) detail
{
    UNUserNotificationCenter *center;
    UNMutableNotificationContent* content;
    UNNotificationRequest *request;
    center = [UNUserNotificationCenter currentNotificationCenter];
    center.delegate = (id) self;
    content = [[UNMutableNotificationContent alloc] init];
    content.title = title;
    content.body = detail;
    content.sound = [UNNotificationSound defaultSound];
    content.categoryIdentifier = TkNotificationCategory;
    request = [UNNotificationRequest
		  requestWithIdentifier:[[NSUUID UUID] UUIDString]
				content:content
				trigger:nil
	       ];
    [center addNotificationRequest: request
	withCompletionHandler: ^(NSError* error) {
	    if (error) {
		DEBUG_LOG("addNotificationRequest: error = %s\n", \
			  [NSString stringWithFormat:@"%@", \
				    error.userInfo].UTF8String);
	    }
	}];
}

/*
 * Implementation of the UNUserNotificationDelegate protocol.
 */

- (void) userNotificationCenter:(UNUserNotificationCenter *)center
         didReceiveNotificationResponse:(UNNotificationResponse *)response
	 withCompletionHandler:(void (^)(void))completionHandler
{
    /*
     * Called when the user dismisses a notification.
     */

    DEBUG_LOG("didReceiveNotification\n");
    completionHandler();
}

- (void) userNotificationCenter:(UNUserNotificationCenter *)center
    willPresentNotification:(UNNotification *)notification
    withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
{

    /*
     * This is called before presenting a notification, even when the user has
     * turned off notifications.
     */

    DEBUG_LOG("willPresentNotification\n");
    completionHandler(ALERT_OPTION);
}

- (void) userNotificationCenter:(UNUserNotificationCenter *)center
   openSettingsForNotification:(UNNotification *)notification
{
    DEBUG_LOG("openSettingsForNotification\n");
    // Does something need to be done here?
}

@end

#endif

/*
 *----------------------------------------------------------------------
 *
 * 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;
    }

    NSString *title = [NSString stringWithUTF8String: Tcl_GetString(objv[1])];
    NSString *message = [NSString stringWithUTF8String: Tcl_GetString(objv[2])];

    /*
     * Update the authorization status in case the user enabled or disabled
     * notifications after the app started up.
     */

#if BUILD_TARGET_HAS_UN_FRAMEWORK

    if (UNnotifier && [NSApp isSigned]) {
    	UNUserNotificationCenter *center;

    	center = [UNUserNotificationCenter currentNotificationCenter];
        [center getNotificationSettingsWithCompletionHandler:
    	    ^(UNNotificationSettings *settings)
    	    {
#if !defined(DEBUG)
		(void) settings;
#endif
    		DEBUG_LOG("Reported authorization status is %ld\n",
			  settings.authorizationStatus);
    	    }];
           }

#endif

    if ([NSApp macOSVersion] < 101400 || ![NSApp isSigned]) {
	DEBUG_LOG("Using the NSUserNotificationCenter\n");
	[NSnotifier postNotificationWithTitle : title message: message];
    } else {

#if BUILD_TARGET_HAS_UN_FRAMEWORK

	DEBUG_LOG("Using the UNUserNotificationCenter\n");
	[UNnotifier postNotificationWithTitle : title message: message];
#endif
    }

    return TCL_OK;
}

#endif // if BUILD_TARGET_HAS_NOTIFICATION

/*
 *----------------------------------------------------------------------
 *
 * 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
 *
 *----------------------------------------------------------------------
 */

#if BUILD_TARGET_HAS_NOTIFICATION

int
MacSystrayInit(Tcl_Interp *interp)
{

    /*
     * Initialize the TkStatusItem for this interpreter and, if necessary,
     * the shared TkNSNotifier and TkUNNotifier.
     */

    StatusItemInfo info = (StatusItemInfo) ckalloc(sizeof(StatusItemInfo));
    *info = 0;

    if (NSnotifier == nil) {
	NSnotifier = [[TkNSNotifier alloc] init];
    }

#if BUILD_TARGET_HAS_UN_FRAMEWORK

    if (@available(macOS 10.14, *)) {
	UNUserNotificationCenter *center;
	UNNotificationCategory *category;
	NSSet *categories;

	if (UNnotifier == nil) {
	    UNnotifier = [[TkUNNotifier alloc] init];

	    /*
	     * Request authorization to use the UserNotification framework.  If
	     * the app code is signed and there are no notification preferences
	     * settings for this app, a dialog will be opened to prompt the
	     * user to choose settings.  Note that the request is asynchronous,
	     * so even if the preferences setting exists the result is not
	     * available immediately.
	     */

	    [UNnotifier requestAuthorization];
	}
	TkNotificationCategory = @"Basic Tk Notification";
	center = [UNUserNotificationCenter currentNotificationCenter];
	center = [UNUserNotificationCenter currentNotificationCenter];
	category = [UNNotificationCategory
		       categoryWithIdentifier:TkNotificationCategory
		       actions:@[]
		       intentIdentifiers:@[]
		       options: UNNotificationCategoryOptionNone];
	categories = [NSSet setWithObjects:category, nil];
	[center setNotificationCategories: categories];
    }
#endif

    Tcl_CreateObjCommand(interp, "::tk::systray::_systray", MacSystrayObjCmd, info,
            (Tcl_CmdDeleteProc *)MacSystrayDestroy);
    Tcl_CreateObjCommand(interp, "::tk::sysnotify::_sysnotify", SysNotifyObjCmd, NULL, NULL);
    return TCL_OK;
}

#else

int
MacSystrayInit(TCL_UNUSED(Tcl_Interp *))
{
    return TCL_OK;
}

#endif // BUILD_TARGET_HAS_NOTIFICATION

/*
 * Local Variables:
 * mode: objc
 * c-basic-offset: 4
 * fill-column: 79
 * coding: utf-8
 * End:
 */
Changes to macosx/tkMacOSXTest.c.
1
2
3
4
5
6
7
8
9



10
11
12
13
14
15
16


17
18
19
20
21
22
23
24
25
26
27





28
29
30
31
32
33
34
1
2
3
4
5
6



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

29
30
31
32
33
34
35
36
37
38
39
40






-
-
-
+
+
+







+
+










-
+
+
+
+
+







/*
 * 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 <[email protected]>
 * Copyright © 1996 Sun Microsystems, Inc.
 * Copyright © 2001-2009 Apple Inc.
 * Copyright © 2005-2009 Daniel A. Steffen <[email protected]>
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tkMacOSXPrivate.h"
#include "tkMacOSXConstants.h"
#include "tkMacOSXWm.h"


/*
 * Forward declarations of procedures defined later in this file:
 */

#if MAC_OS_X_VERSION_MAX_ALLOWED < 1080
static int		DebuggerObjCmd (ClientData dummy, Tcl_Interp *interp,
					int objc, Tcl_Obj *const objv[]);
#endif
static int		PressButtonObjCmd (ClientData dummy, Tcl_Interp *interp,
					int objc, Tcl_Obj *const objv[]);
					int objc, Tcl_Obj *const *objv);
static int		InjectKeyEventObjCmd (ClientData dummy, Tcl_Interp *interp,
					int objc, Tcl_Obj *const *objv);
static int		MenuBarHeightObjCmd (ClientData dummy, Tcl_Interp *interp,
					int objc, Tcl_Obj *const *objv);


/*
 *----------------------------------------------------------------------
 *
 * TkplatformtestInit --
 *
52
53
54
55
56
57
58
59


60
61
62
63
64
65
66
58
59
60
61
62
63
64

65
66
67
68
69
70
71
72
73







-
+
+







     * Add commands for platform specific tests on MacOS here.
     */

#if MAC_OS_X_VERSION_MAX_ALLOWED < 1080
    Tcl_CreateObjCommand(interp, "debugger", DebuggerObjCmd, NULL, NULL);
#endif
    Tcl_CreateObjCommand(interp, "pressbutton", PressButtonObjCmd, NULL, NULL);

    Tcl_CreateObjCommand(interp, "injectkeyevent", InjectKeyEventObjCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "menubarheight", MenuBarHeightObjCmd, NULL, NULL);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * DebuggerObjCmd --
89
90
91
92
93
94
95

































96
97
98
99

100
101
102
103
104
105
106
107
108
109
110



111
112
113
114
115
116
117
118
119
120















121
122

123
124
125
126
127
128
129
130
131
132
133
134





135
136
137
138
139
140
141
142
143
144
145
146
147
148

149
150
151
152
153


154
155
156
157
158
159
160
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138

139






140
141



142
143
144
145
146
147
148
149
150
151



152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167

168
169
170
171
172
173
174
175
176
177



178
179
180
181
182
183
184
185
186
187
188
189
190
191
192

193
194

195
196
197
198
199

200
201
202
203
204
205
206
207
208







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
+
-
-
-
-
-
-


-
-
-
+
+
+







-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+









-
-
-
+
+
+
+
+










-


-
+




-
+
+







    return TCL_OK;
}
#endif

/*
 *----------------------------------------------------------------------
 *
 * MenuBarHeightObjCmd --
 *
 *	This procedure calls [NSMenu menuBarHeight] and returns the result
 *      as an integer.  Windows can never be placed to overlap the MenuBar,
 *      so tests need to be aware of its size.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
MenuBarHeightObjCmd(
    TCL_UNUSED(void *),		/* Not used. */
    Tcl_Interp *interp,			/* Not used. */
    TCL_UNUSED(int),				/* Not used. */
    TCL_UNUSED(Tcl_Obj *const *))		/* Not used. */
{
    static int height = 0;
    if (height == 0) {
	height = (int) [[NSApp mainMenu] menuBarHeight];
    }
    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(height));
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TkTestLogDisplay --
 *
 *      The test image display procedure calls this to determine whether it
 *      should write a log message recording that it has being run.  On OSX
 *      should write a log message recording that it has being run.
 *      10.14 and later, only calls to the display procedure which occur inside
 *      of the drawRect method should be logged, since those are the only ones
 *      which actually draw anything.  On earlier systems the opposite is true.
 *      The calls from within the drawRect method are redundant, since the
 *      first time the display procedure is run it will do the drawing and that
 *      first call will usually not occur inside of drawRect.
 *
 * Results:
 *      On OSX 10.14 and later, returns true if and only if called from
 *      within [NSView drawRect].  On earlier systems returns false if
 *      and only if called from with [NSView drawRect].
 *      Returns true if and only if the NSView of the drawable is the
 *      current focusView, which on 10.14 and newer systems can only be the
 *      case when within [NSView drawRect].
 *
 * Side effects:
 *	None
 *
 *----------------------------------------------------------------------
 */
MODULE_SCOPE Bool
TkTestLogDisplay(void) {
    if ([NSApp macMinorVersion] >= 14) {
	return [NSApp isDrawing];
TkTestLogDisplay(
    Drawable drawable)
{
    MacDrawable *macWin = (MacDrawable *)drawable;
    NSWindow *win = nil;
    if (macWin->toplevel && macWin->toplevel->winPtr &&
	macWin->toplevel->winPtr->wmInfoPtr &&
	macWin->toplevel->winPtr->wmInfoPtr->window) {
	win = macWin->toplevel->winPtr->wmInfoPtr->window;
    } else if (macWin->winPtr && macWin->winPtr->wmInfoPtr &&
	       macWin->winPtr->wmInfoPtr->window) {
	win = macWin->winPtr->wmInfoPtr->window;
    }
    if (win) {
	return ([win contentView] == [NSView focusView]);
    } else {
	return ![NSApp isDrawing];
	return True;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * PressButtonObjCmd --
 *
 *	This Tcl command simulates a button press at a specific screen
 *      location.  It injects NSEvents into the NSApplication event queue,
 *      as opposed to adding events to the Tcl queue as event generate
 *      would do.  One application is for testing the grab command.
 *      location.  It injects NSEvents into the NSApplication event queue, as
 *      opposed to adding events to the Tcl queue as event generate would do.
 *      One application is for testing the grab command. These events have
 *      their unused context property set to 1 as a signal indicating that they
 *      should not be ignored by [NSApp tkProcessMouseEvent].
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

        /* ARGSUSED */
static int
PressButtonObjCmd(
    ClientData clientData,
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    int x, y, i, value, wNum;
    int x = 0, y = 0, i, value;
    NSInteger signal = -1;
    CGPoint pt;
    NSPoint loc;
    NSEvent *motion, *press, *release;
    NSArray *screens = [NSScreen screens];
    CGFloat ScreenHeight = 0;
    enum {X=1, Y};

180
181
182
183
184
185
186
187






188
189
190
191
192
193

194
195

196
197
198
199
200
201
202
203

204
205

206
207
208
209
210
211
212
213

214
215

216
217

218
219
220
221






222






































































































223
224
225
226
227
228
229
230
228
229
230
231
232
233
234

235
236
237
238
239
240
241
242
243
244
245

246
247

248
249
250
251
252
253
254
255

256
257

258
259
260
261
262
263
264
265

266
267

268
269

270
271
272
273
274
275
276
277
278
279
280

281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390







-
+
+
+
+
+
+





-
+

-
+







-
+

-
+







-
+

-
+

-
+




+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








	default:
	    break;
	}
    }
    pt.x = loc.x = x;
    pt.y = y;
    loc.y = ScreenHeight - y;
    wNum = 0;

    /*
     *  We set the window number and the eventNumber to -1 as a signal to
     *  processMouseEvent.
     */

    CGWarpMouseCursorPosition(pt);
    motion = [NSEvent mouseEventWithType:NSMouseMoved
	location:loc
	modifierFlags:0
	timestamp:GetCurrentEventTime()
	windowNumber:wNum
	windowNumber:signal
	context:nil
	eventNumber:0
	eventNumber:signal
	clickCount:1
	pressure:0.0];
    [NSApp postEvent:motion atStart:NO];
    press = [NSEvent mouseEventWithType:NSLeftMouseDown
	location:loc
	modifierFlags:0
	timestamp:GetCurrentEventTime()
	windowNumber:wNum
	windowNumber:signal
	context:nil
	eventNumber:1
	eventNumber:signal
	clickCount:1
	pressure:0.0];
    [NSApp postEvent:press atStart:NO];
    release = [NSEvent mouseEventWithType:NSLeftMouseUp
	location:loc
	modifierFlags:0
	timestamp:GetCurrentEventTime()
	windowNumber:wNum
	windowNumber:signal
	context:nil
	eventNumber:2
	eventNumber:signal
	clickCount:1
	pressure:0.0];
	pressure:-1.0];
    [NSApp postEvent:release atStart:NO];
    return TCL_OK;
}

static int
InjectKeyEventObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])

{
    static const char *const optionStrings[] = {
	"press", "release", "flagschanged", NULL};
    NSUInteger types[3] = {NSKeyDown, NSKeyUp, NSFlagsChanged};
    static const char *const argStrings[] = {
	"-shift", "-control", "-option", "-command", "-function", "-x", "-y", NULL};
    enum args {KEYEVENT_SHIFT, KEYEVENT_CONTROL, KEYEVENT_OPTION, KEYEVENT_COMMAND,
	       KEYEVENT_FUNCTION, KEYEVENT_X, KEYEVENT_Y};
    int i, index, keysym, mods = 0, x = 0, y = 0;
    NSString *chars = nil, *unmod = nil, *upper, *lower;
    NSEvent *keyEvent;
    NSUInteger type;
    MacKeycode macKC;

    if (objc < 3) {
    wrongArgs:
        Tcl_WrongNumArgs(interp, 1, objv, "option keysym ?arg?");
        return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0,
            &index) != TCL_OK) {
        return TCL_ERROR;
    }
    type = types[index];
    if (Tcl_GetIntFromObj(interp, objv[2], &keysym) != TCL_OK) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			 "keysym must be an integer"));
	Tcl_SetErrorCode(interp, "TK", "TEST", "INJECT", "KEYSYM", NULL);
	return TCL_ERROR;
    }
    macKC.uint = XKeysymToKeycode(NULL, keysym);
    for (i = 3; i < objc; i++) {
	if (Tcl_GetIndexFromObjStruct(interp, objv[i], argStrings,
                sizeof(char *), "option", TCL_EXACT, &index) != TCL_OK) {
            return TCL_ERROR;
        }
        switch ((enum args) index) {
	case KEYEVENT_SHIFT:
	    mods |= NSShiftKeyMask;
            break;
	case KEYEVENT_CONTROL:
	    mods |= NSControlKeyMask;
            break;
	case KEYEVENT_OPTION:
	    mods |= NSAlternateKeyMask;
            break;
	case KEYEVENT_COMMAND:
	    mods |= NSCommandKeyMask;
            break;
	case KEYEVENT_FUNCTION:
	    mods |= NSFunctionKeyMask;
            break;
	case KEYEVENT_X:
	    if (++i >= objc) {
                goto wrongArgs;
            }
	    if (Tcl_GetIntFromObj(interp,objv[i], &x) != TCL_OK) {
		return TCL_ERROR;
	    }
	    break;
	case KEYEVENT_Y:
	    if (++i >= objc) {
                goto wrongArgs;
            }
	    if (Tcl_GetIntFromObj(interp,objv[i], &y) != TCL_OK) {
		return TCL_ERROR;
	    }
	    break;
	}
    }
    if (type != NSFlagsChanged) {
	UniChar keychar = macKC.v.keychar;
	chars = [[NSString alloc] initWithCharacters: &keychar length:1];
	upper = [chars uppercaseString];
	lower = [chars lowercaseString];
	if (![upper isEqual: lower] && [chars isEqual: upper]) {
	    mods |= NSShiftKeyMask;
	}
	if (mods & NSShiftKeyMask) {
	    chars = upper;
	    unmod = lower;
	    macKC.v.o_s |= INDEX_SHIFT;
	} else {
	    unmod = chars;
	}
	if (macKC.v.o_s & INDEX_OPTION) {
	    mods |= NSAlternateKeyMask;
	}
    }
    keyEvent = [NSEvent keyEventWithType:type
	location:NSMakePoint(x, y)
        modifierFlags:mods
	timestamp:GetCurrentEventTime()
	windowNumber:0
	context:nil
	characters:chars
	charactersIgnoringModifiers:unmod
	isARepeat:NO
	keyCode:macKC.v.virtual];
    [NSApp postEvent:keyEvent atStart:NO];
    return TCL_OK;
}
/*
 * Local Variables:
 * mode: objc
 * c-basic-offset: 4
 * fill-column: 79
 * coding: utf-8
 * End:
 */
Changes to macosx/tkMacOSXWindowEvent.c.
1
2
3
4
5
6
7
8
9
10




11
12
13
14
15
16
17
18

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34


35
36
37
38
39
40
41

42
43


44
45
46
47
48
49
50
1
2
3
4
5
6




7
8
9
10
11
12
13
14
15
16
17

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32


33
34
35
36

37
38
39

40
41

42
43
44
45
46
47
48
49
50






-
-
-
-
+
+
+
+







-
+














-
-
+
+


-



-
+

-
+
+







/*
 * 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 <[email protected]>
 * Copyright (c) 2015 Kevin Walzer/WordTech Communications LLC.
 * Copyright (c) 2015 Marc Culler.
 * Copyright © 2001-2009 Apple Inc.
 * Copyright © 2005-2009 Daniel A. Steffen <[email protected]>
 * 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.
 */

#include "tkMacOSXPrivate.h"
#include "tkMacOSXWm.h"
#include "tkMacOSXEvent.h"
#include "tkMacOSXInt.h"
#include "tkMacOSXDebug.h"
#include "tkMacOSXConstants.h"

/*
#ifdef TK_MAC_DEBUG
#define TK_MAC_DEBUG_EVENTS
#define TK_MAC_DEBUG_DRAWING
#endif
*/

/*
 * Declaration of functions used only in this file
 */

static int		GenerateUpdates(HIShapeRef updateRgn,
			   CGRect *updateBounds, TkWindow *winPtr);
static int		GenerateUpdates(
			    CGRect *updateBounds, TkWindow *winPtr);
static int		GenerateActivateEvents(TkWindow *winPtr,
			    int activeFlag);
static void		DoWindowActivate(ClientData clientData);

#pragma mark TKApplication(TKWindowEvent)

#ifdef TK_MAC_DEBUG_NOTIFICATIONS
extern NSString *NSWindowDidOrderOnScreenNotification;
extern NSString *NSWindowWillOrderOnScreenNotification;
extern NSString *NSWindowDidOrderOnScreenNotification;

#ifdef TK_MAC_DEBUG_NOTIFICATIONS
extern NSString *NSWindowDidOrderOffScreenNotification;
#endif


@implementation TKApplication(TKWindowEvent)

- (void) windowActivation: (NSNotification *) notification
86
87
88
89
90
91
92
93
94
95
96



97
98

99
100
101

102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117

118
119
120
121
122



123
124
125


126
127
128
129
130




131
132

133
134
135
136
137
138
139
140
141


142
143
144
145
146
147
148
149
150
151
152
153


154
155
156
157
158
159
160
86
87
88
89
90
91
92




93
94
95
96

97



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113

114

115



116
117
118
119


120
121
122




123
124
125
126
127

128



129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157







-
-
-
-
+
+
+

-
+
-
-
-
+















-
+
-

-
-
-
+
+
+

-
-
+
+

-
-
-
-
+
+
+
+

-
+
-
-
-






+
+












+
+







	}
	if (!movedOnly && (winPtr->changes.width != bounds.size.width ||
		winPtr->changes.height !=  bounds.size.height)) {
	    width = bounds.size.width - wmPtr->xInParent;
	    height = bounds.size.height - wmPtr->yInParent;
	    flags |= TK_SIZE_CHANGED;
	}
	if (Tcl_GetServiceMode() != TCL_SERVICE_NONE) {
	    /*
	     * Propagate geometry changes immediately.
	     */
	/*
	 * Propagate geometry changes immediately.
	 */

	    flags |= TK_MACOSX_HANDLE_EVENT_IMMEDIATELY;
	flags |= TK_MACOSX_HANDLE_EVENT_IMMEDIATELY;
	}

	TkGenWMConfigureEvent((Tk_Window) winPtr, x, y, width, height, flags);
	TkGenWMConfigureEvent((Tk_Window)winPtr, x, y, width, height, flags);
    }

}

- (void) windowExpanded: (NSNotification *) notification
{
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
    TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
#endif
    NSWindow *w = [notification object];
    TkWindow *winPtr = TkMacOSXGetTkWindow(w);

    if (winPtr) {
	winPtr->wmInfoPtr->hints.initial_state =
		TkMacOSXIsWindowZoomed(winPtr) ? ZoomState : NormalState;
	Tk_MapWindow((Tk_Window) winPtr);
	Tk_MapWindow((Tk_Window)winPtr);
	if (Tcl_GetServiceMode() != TCL_SERVICE_NONE) {

	    /*
	     * Process all Tk events generated by Tk_MapWindow().
	     */
	/*
	 * Process all Tk events generated by Tk_MapWindow().
	 */

	    while (Tcl_ServiceEvent(0)) {}
	    while (Tcl_DoOneEvent(TCL_IDLE_EVENTS|TCL_DONT_WAIT)) {}
	while (Tcl_ServiceEvent(0)) {}
	while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {}

	    /*
	     * NSWindowDidDeminiaturizeNotification is received after
	     * NSWindowDidBecomeKeyNotification, so activate manually
	     */
	/*
	 * NSWindowDidDeminiaturizeNotification is received after
	 * NSWindowDidBecomeKeyNotification, so activate manually
	 */

	    GenerateActivateEvents(winPtr, 1);
	GenerateActivateEvents(winPtr, 1);
	} else {
	    Tcl_DoWhenIdle(DoWindowActivate, winPtr);
	}
    }
}

- (NSRect)windowWillUseStandardFrame:(NSWindow *)window
                        defaultFrame:(NSRect)newFrame
{
    (void)window;

    /*
     * This method needs to be implemented in order for [NSWindow isZoomed] to
     * give the correct answer. But it suffices to always validate every
     * request.
     */

    return newFrame;
}

- (NSSize)window:(NSWindow *)window
  willUseFullScreenContentSize:(NSSize)proposedSize
{
    (void)window;

    /*
     * We don't need to change the proposed size, but we do need to implement
     * this method.  Otherwise the full screen window will be sized to the
     * screen's visibleFrame, leaving black bands at the top and bottom.
     */

    return proposedSize;
181
182
183
184
185
186
187
188

189
190
191
192
193
194
195
196
197
198
199
200

201
202
203
204
205
206
207
208
209




























210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247

248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265


266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290


291
292
293
294
295
296
297
178
179
180
181
182
183
184

185
186
187
188
189
190
191
192
193
194
195
196

197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
















249
250
251
252
253
254
255

256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286


287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308







-
+











-
+









+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+














-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







-
+


















+
+










-
-













+
+







#ifdef TK_MAC_DEBUG_NOTIFICATIONS
    TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
#endif
    NSWindow *w = [notification object];
    TkWindow *winPtr = TkMacOSXGetTkWindow(w);

    if (winPtr) {
	Tk_UnmapWindow((Tk_Window) winPtr);
	Tk_UnmapWindow((Tk_Window)winPtr);
    }
}

- (BOOL) windowShouldClose: (NSWindow *) w
{
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
    TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, w);
#endif
    TkWindow *winPtr = TkMacOSXGetTkWindow(w);

    if (winPtr) {
	TkGenWMDestroyEvent((Tk_Window) winPtr);
	TkGenWMDestroyEvent((Tk_Window)winPtr);
    }

    /*
     * If necessary, TkGenWMDestroyEvent() handles [close]ing the window, so
     * can always return NO from -windowShouldClose: for a Tk window.
     */

    return (winPtr ? NO : YES);
}

- (void) windowBecameVisible: (NSNotification *) notification
{
    NSWindow *window = [notification object];
    TkWindow *winPtr = TkMacOSXGetTkWindow(window);
    if (winPtr) {
	TKContentView *view = [window contentView];

#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101500
	if (@available(macOS 10.15, *)) {
	    [view viewDidChangeEffectiveAppearance];
	}
#endif
	[view addTkDirtyRect:[view bounds]];
	Tcl_CancelIdleCall(TkMacOSXDrawAllViews, NULL);
	Tcl_DoWhenIdle(TkMacOSXDrawAllViews, NULL);
    }
}

- (void) windowMapped: (NSNotification *) notification
{
    NSWindow *w = [notification object];
    TkWindow *winPtr = TkMacOSXGetTkWindow(w);

    if (winPtr) {
	while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {}
    }
}

#ifdef TK_MAC_DEBUG_NOTIFICATIONS

- (void) windowDragStart: (NSNotification *) notification
{
    TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
}

- (void) windowLiveResize: (NSNotification *) notification
{
    TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
    //BOOL start = [[notification name] isEqualToString:NSWindowWillStartLiveResizeNotification];
}

- (void) windowMapped: (NSNotification *) notification
{
    TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
    NSWindow *w = [notification object];
    TkWindow *winPtr = TkMacOSXGetTkWindow(w);

    if (winPtr) {
	//Tk_MapWindow((Tk_Window) winPtr);
    }
}

- (void) windowBecameVisible: (NSNotification *) notification
{
    TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
}

- (void) windowUnmapped: (NSNotification *) notification
{
    TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
    NSWindow *w = [notification object];
    TkWindow *winPtr = TkMacOSXGetTkWindow(w);

    if (winPtr) {
	//Tk_UnmapWindow((Tk_Window) winPtr);
	//Tk_UnmapWindow((Tk_Window)winPtr);
    }
}

#endif /* TK_MAC_DEBUG_NOTIFICATIONS */

- (void) _setupWindowNotifications
{
    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];

#define observe(n, s) \
	[nc addObserver:self selector:@selector(s) name:(n) object:nil]

    observe(NSWindowDidBecomeKeyNotification, windowActivation:);
    observe(NSWindowDidResignKeyNotification, windowActivation:);
    observe(NSWindowDidMoveNotification, windowBoundsChanged:);
    observe(NSWindowDidResizeNotification, windowBoundsChanged:);
    observe(NSWindowDidDeminiaturizeNotification, windowExpanded:);
    observe(NSWindowDidMiniaturizeNotification, windowCollapsed:);
    observe(NSWindowWillOrderOnScreenNotification, windowMapped:);
    observe(NSWindowDidOrderOnScreenNotification, windowBecameVisible:);

#if !(MAC_OS_X_VERSION_MAX_ALLOWED < 1070)
    observe(NSWindowDidEnterFullScreenNotification, windowEnteredFullScreen:);
    observe(NSWindowDidExitFullScreenNotification, windowExitedFullScreen:);
#endif

#ifdef TK_MAC_DEBUG_NOTIFICATIONS
    observe(NSWindowWillMoveNotification, windowDragStart:);
    observe(NSWindowWillStartLiveResizeNotification, windowLiveResize:);
    observe(NSWindowDidEndLiveResizeNotification, windowLiveResize:);
    observe(NSWindowWillOrderOnScreenNotification, windowMapped:);
    observe(NSWindowDidOrderOnScreenNotification, windowBecameVisible:);
    observe(NSWindowDidOrderOffScreenNotification, windowUnmapped:);
#endif
#undef observe

}
@end

#pragma mark TKApplication(TKApplicationEvent)

@implementation TKApplication(TKApplicationEvent)

- (void) applicationActivate: (NSNotification *) notification
{
    (void)notification;

#ifdef TK_MAC_DEBUG_NOTIFICATIONS
    TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
#endif
    [NSApp tkCheckPasteboard];

    /*
     * When the application is activated with Command-Tab it will create a
308
309
310
311
312
313
314


315
316
317














318
319
320
321
322



323
324
325
326
327
328
329
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359







+
+



+
+
+
+
+
+
+
+
+
+
+
+
+
+





+
+
+







	    [win orderOut:nil];
	}
    }
}

- (void) applicationDeactivate: (NSNotification *) notification
{
    (void)notification;

#ifdef TK_MAC_DEBUG_NOTIFICATIONS
    TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
#endif

    /*
     * To prevent zombie windows on systems with a TouchBar, set the key window
     * to nil if the current key window is not visible.  This allows a closed
     * Help or About window to be deallocated so it will not reappear as a
     * zombie when the app is reactivated.
     */

    NSWindow *keywindow = [NSApp keyWindow];
    if (keywindow && ![keywindow isVisible]) {
	[NSApp _setKeyWindow:nil];
	[NSApp _setMainWindow:nil];
    }

}

- (BOOL)applicationShouldHandleReopen:(NSApplication *)sender
                    hasVisibleWindows:(BOOL)flag
{
    (void)sender;
    (void)flag;

    /*
     * Allowing the default response means that withdrawn windows will get
     * displayed on the screen with unresponsive title buttons.  We don't
     * really want that.  Besides, we can write our own code to handle this
     * with ::tk::mac::ReopenApplication.  So we just say NO.
     */

348
349
350
351
352
353
354


355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

372
373
374
375
376
377








378
379
380


381
382
383


384
385
386
387
388
389
390
























391
392
393
394
395
396
397
398

399
400

401
402
403
404
405
406
407

408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429

430
431
432

433
434
435
436
437
438
439
440
441
442
443

444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460

461
462
463
464
465
466
467
468
469
470
471
472
473

474
475
476
477
478
479
480
481
482
483

484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558

559
560
561
562
563

564
565
566
567
568
569
570
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402

403
404
405




406
407
408
409
410
411
412
413
414
415

416
417
418
419

420
421
422
423
424
425



426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456

457
458

459
460
461
462
463
464
465

466
467
468
469
470
471
472

473
474
475
476
477
478

479
480
481
482
483



484

485

486
487
488









489



490
491
492
493
494
495
496
497
498
499
500
501
502

503
504
505
506
507
508
509
510
511
512
513
514
515

516
517
518
519
520
521
522
523
524
525

526
527
528
529
530
531
532
533
534
535




















































536
537
538
539
540
541
542
543
544
545
546
547
548

549
550
551
552
553

554
555
556
557
558
559
560
561







+
+
















-
+


-
-
-
-
+
+
+
+
+
+
+
+


-
+
+


-
+
+




-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







-
+

-
+






-
+






-






-





-
-
-
+
-

-
+


-
-
-
-
-
-
-
-
-
+
-
-
-













-
+












-
+









-
+









-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-













-
+




-
+







	}
	Tcl_ResetResult(_eventInterp);
    }
}

- (void) displayChanged: (NSNotification *) notification
{
    (void)notification;

#ifdef TK_MAC_DEBUG_NOTIFICATIONS
    TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
#endif
    TkDisplay *dispPtr = TkGetDisplayList();

    if (dispPtr) {
	TkMacOSXDisplayChanged(dispPtr->display);
    }
}
@end

#pragma mark -

/*
 *----------------------------------------------------------------------
 *
 * TkpAppIsDrawing --
 * TkpWillDrawWidget --
 *
 *      A widget display procedure can call this to determine whether it is
 *      being run inside of the drawRect method. This is needed for some tests,
 *      especially of the Text widget, which record data in a global Tcl
 *      variable and assume that display procedures will be run in a
 *      predictable sequence as Tcl idle tasks.
 *      being run inside of the drawRect method. If not, it may be desirable
 *      for the display procedure to simply clear the REDRAW_PENDING flag
 *      and return.  The widget can be recorded in order to schedule a
 *      redraw, via and Expose event, from within drawRect.
 *
 *      This is also needed for some tests, especially of the Text widget,
 *      which record data in a global Tcl variable and assume that display
 *      procedures will be run in a predictable sequence as Tcl idle tasks.
 *
 * Results:
 *	True only while running the drawRect method of a TKContentView;
 *      True if called from the drawRect method of a TKContentView with
 *      tkwin NULL or pointing to a widget in the current focusView.
 *
 * Side effects:
 *	None
 *	Currently none.  One day the tkwin parameter may be recorded to
 *      handle redrawing the widget later.
 *
 *----------------------------------------------------------------------
 */

MODULE_SCOPE Bool
TkpAppIsDrawing(void) {
    return [NSApp isDrawing];
int
TkpWillDrawWidget(Tk_Window tkwin) {
    int result;
    if (tkwin) {
	TkWindow *winPtr = (TkWindow *)tkwin;
	TKContentView *view = (TKContentView *)TkMacOSXGetNSViewForDrawable(
	    (Drawable)winPtr->privatePtr);
	result = ([NSApp isDrawing] && view == [NSView focusView]);
#if 0
	printf("TkpWillDrawWidget: %s %d  %d \n", Tk_PathName(tkwin),
	       [NSApp isDrawing], (view == [NSView focusView]));
	if (!result) {
	    NSRect dirtyRect;
	    TkMacOSXWinNSBounds(winPtr, view, &dirtyRect);
	    printf("TkpAppCanDraw: dirtyRect for %s is %s\n",
		   Tk_PathName(tkwin),
		   NSStringFromRect(dirtyRect).UTF8String);
	    [view addTkDirtyRect:dirtyRect];
	}
#endif
    } else {
	result = [NSApp isDrawing];
    }
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * GenerateUpdates --
 *
 *	Given a Macintosh update region and a Tk window this function geneates
 *	Given an update rectangle and a Tk window, this function generates
 *	an X Expose event for the window if it meets the update region. The
 *	function will then recursivly have each damaged window generate Expose
 *	function will then recursively have each damaged window generate Expose
 *	events for its child windows.
 *
 * Results:
 *	True if event(s) are generated - false otherwise.
 *
 * Side effects:
 *	Additional events may be place on the Tk event queue.
 *	Additional events may be placed on the Tk event queue.
 *
 *----------------------------------------------------------------------
 */

static int
GenerateUpdates(
    HIShapeRef updateRgn,
    CGRect *updateBounds,
    TkWindow *winPtr)
{
    TkWindow *childPtr;
    XEvent event;
    CGRect bounds, damageBounds;
    HIShapeRef boundsRgn, damageRgn;

    TkMacOSXWinCGBounds(winPtr, &bounds);
    if (!CGRectIntersectsRect(bounds, *updateBounds)) {
	return 0;
    }
    if (!HIShapeIntersectsRect(updateRgn, &bounds)) {
	return 0;
    }


    /*
     * Compute the bounding box of the area that the damage occured in.
     * Compute the bounding box of the area that the damage occurred in.
     */

    boundsRgn = HIShapeCreateWithRect(&bounds);
    damageRgn = HIShapeCreateIntersection(updateRgn, boundsRgn);
    if (HIShapeIsEmpty(damageRgn)) {
	CFRelease(damageRgn);
	CFRelease(boundsRgn);
	return 0;
    }
    HIShapeGetBounds(damageRgn, &damageBounds);

    damageBounds = CGRectIntersection(bounds, *updateBounds);
    CFRelease(damageRgn);
    CFRelease(boundsRgn);

    event.xany.serial = LastKnownRequestProcessed(Tk_Display(winPtr));
    event.xany.send_event = false;
    event.xany.window = Tk_WindowId(winPtr);
    event.xany.display = Tk_Display(winPtr);
    event.type = Expose;
    event.xexpose.x = damageBounds.origin.x - bounds.origin.x;
    event.xexpose.y = damageBounds.origin.y - bounds.origin.y;
    event.xexpose.width = damageBounds.size.width;
    event.xexpose.height = damageBounds.size.height;
    event.xexpose.count = 0;
    Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);

#ifdef TK_MAC_DEBUG_DRAWING
    TKLog(@"Expose %p {{%d, %d}, {%d, %d}}", event.xany.window, event.xexpose.x,
    TKLog(@"Exposed %p {{%d, %d}, {%d, %d}}", event.xany.window, event.xexpose.x,
	event.xexpose.y, event.xexpose.width, event.xexpose.height);
#endif

    /*
     * Generate updates for the children of this window
     */

    for (childPtr = winPtr->childList; childPtr != NULL;
	    childPtr = childPtr->nextPtr) {
	if (!Tk_IsMapped(childPtr) || Tk_IsTopLevel(childPtr)) {
	    continue;
	}
	GenerateUpdates(updateRgn, updateBounds, childPtr);
	GenerateUpdates(updateBounds, childPtr);
    }

    /*
     * Generate updates for any contained windows
     */

    if (Tk_IsContainer(winPtr)) {
	childPtr = TkpGetOtherWindow(winPtr);
	if (childPtr != NULL && Tk_IsMapped(childPtr)) {
	    GenerateUpdates(updateRgn, updateBounds, childPtr);
	    GenerateUpdates(updateBounds, childPtr);
	}

	/*
	 * TODO: Here we should handle out of process embedding.
	 */
    }

    return 1;
}

/*
 *----------------------------------------------------------------------
 *
 * GenerateActivateEvents --
 *
 *	Given a Macintosh window activate event this function generates all the
 *	X Activate events needed by Tk.
 *
 * Results:
 *	True if event(s) are generated - false otherwise.
 *
 * Side effects:
 *	Additional events may be place on the Tk event queue.
 *
 *----------------------------------------------------------------------
 */

int
GenerateActivateEvents(
    TkWindow *winPtr,
    int activeFlag)
{
    TkGenerateActivateEvents(winPtr, activeFlag);
    if (activeFlag || ![NSApp isActive]) {
	TkMacOSXGenerateFocusEvent(winPtr, activeFlag);
    }
    return true;
}

/*
 *----------------------------------------------------------------------
 *
 * DoWindowActivate --
 *
 *	Idle handler that calls GenerateActivateEvents().
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Additional events may be place on the Tk event queue.
 *
 *----------------------------------------------------------------------
 */

void
DoWindowActivate(
    ClientData clientData)
{
    GenerateActivateEvents(clientData, 1);
}

/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXGenerateFocusEvent --
 *
 *	Given a Macintosh window activate event this function generates all
 *	the X Focus events needed by Tk.
 *
 * Results:
 *	True if event(s) are generated - false otherwise.
 *
 * Side effects:
 *	Additional events may be place on the Tk event queue.
 *	Additional events may be placed on the Tk event queue.
 *
 *----------------------------------------------------------------------
 */

MODULE_SCOPE int
static int
TkMacOSXGenerateFocusEvent(
    TkWindow *winPtr,		/* Root X window for event. */
    int activeFlag)
{
    XEvent event;

    /*
595
596
597
598
599
600
601





























602
603
604
605
606
607
608
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    event.xfocus.mode = NotifyNormal;
    event.xfocus.detail = NotifyDetailNone;

    Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
    return true;
}

/*
 *----------------------------------------------------------------------
 *
 * GenerateActivateEvents --
 *
 *	Given a Macintosh window activate event this function generates all the
 *	X Activate events needed by Tk.
 *
 * Results:
 *	True if event(s) are generated - false otherwise.
 *
 * Side effects:
 *	Additional events may be placed on the Tk event queue.
 *
 *----------------------------------------------------------------------
 */

int
GenerateActivateEvents(
    TkWindow *winPtr,
    int activeFlag)
{
    TkGenerateActivateEvents(winPtr, activeFlag);
    if (activeFlag || ![NSApp isActive]) {
	TkMacOSXGenerateFocusEvent(winPtr, activeFlag);
    }
    return true;
}

/*
 *----------------------------------------------------------------------
 *
 * TkGenWMConfigureEvent --
 *
 *	Generate a ConfigureNotify event for Tk. Depending on the value of flag
 *	the values of width/height, x/y, or both may be changed.
709
710
711
712
713
714
715
716

717
718
719
720
721
722
723
729
730
731
732
733
734
735

736
737
738
739
740
741
742
743







-
+







	    wmPtr->configWidth = width;
	    wmPtr->configHeight = height;
	}
    }

    /*
     * Now set up the changes structure. Under X we wait for the
     * ConfigureNotify to set these values. On the Mac we know imediatly that
     * ConfigureNotify to set these values. On the Mac we know immediately that
     * this is what we want - so we just set them. However, we need to make
     * sure the windows clipping region is marked invalid so the change is
     * visible to the subwindow.
     */

    winPtr->changes.x = x;
    winPtr->changes.y = y;
800
801
802
803
804
805
806
807

808
809
810
811
812
813
814
815
816
817
818
819
820
821
822


823
824
825
826
827
828
829
820
821
822
823
824
825
826

827
828
829
830
831
832
833
834
835
836
837
838
839
840


841
842
843
844
845
846
847
848
849







-
+













-
-
+
+







	    Tcl_Preserve(protPtr);
	    interp = protPtr->interp;
	    Tcl_Preserve(interp);
	    result = Tcl_EvalEx(interp, protPtr->command, -1, TCL_EVAL_GLOBAL);
	    if (result != TCL_OK) {
		Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
			"\n    (command for \"%s\" window manager protocol)",
			Tk_GetAtomName((Tk_Window) winPtr, protocol)));
			Tk_GetAtomName((Tk_Window)winPtr, protocol)));
		Tcl_BackgroundException(interp, result);
	    }
	    Tcl_Release(interp);
	    Tcl_Release(protPtr);
	    return;
	}
    }

    /*
     * No handler was present for this protocol. If this is a WM_DELETE_WINDOW
     * message then just destroy the window.
     */

    if (protocol == Tk_InternAtom((Tk_Window) winPtr, "WM_DELETE_WINDOW")) {
	Tk_DestroyWindow((Tk_Window) winPtr);
    if (protocol == Tk_InternAtom((Tk_Window)winPtr, "WM_DELETE_WINDOW")) {
	Tk_DestroyWindow((Tk_Window)winPtr);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tk_MacOSXIsAppInFront --
883
884
885
886
887
888
889
890

891
892
893
894
895
896
897
898
899
900

901
902
903
904

905
906

907
908
909
910
911

912
913
914

915
916
917




918
919


920




921
922
923
924

925
926
927
928

929
930



931
932
933
934
935
936
937
938
939

940
941
942
943
944
945
946

947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962

963
964

965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981

982
983
984
985
986
987
988
903
904
905
906
907
908
909

910
911
912
913
914
915





916




917


918





919



920



921
922
923
924


925
926

927
928
929
930
931
932
933

934

935
936
937
938


939
940
941
942
943
944
945
946
947
948
949

950
951
952
953
954
955
956

957
















958


959





960
961
962
963
964
965
966
967
968
969
970

971
972
973
974
975
976
977
978







-
+





-
-
-
-
-
+
-
-
-
-
+
-
-
+
-
-
-
-
-
+
-
-
-
+
-
-
-
+
+
+
+
-
-
+
+
-
+
+
+
+



-
+
-



+
-
-
+
+
+








-
+






-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
-
-
-
-
-











-
+








/*
 * Restrict event processing to ConfigureNotify events.
 */

static Tk_RestrictAction
ConfigureRestrictProc(
    ClientData arg,
    TCL_UNUSED(void *),
    XEvent *eventPtr)
{
    return (eventPtr->type==ConfigureNotify ? TK_PROCESS_EVENT : TK_DEFER_EVENT);
}

/*
 * If a window gets mapped inside the drawRect method, this will be run as an
 * idle task, after drawRect returns, to clean up the mess.
 */

@implementation TKContentView(TKWindowEvent)
static void
RedisplayView(
    ClientData clientdata)
{

    NSView *view = (NSView *) clientdata;

- (void) addTkDirtyRect: (NSRect) rect
    /*
     * Make sure that we are not trying to displaying a view that no longer
     * exists.
     */

{
    for (NSWindow *w in [NSApp orderedWindows]) {
	if ([w contentView] == view) {
	    [view setNeedsDisplay:YES];
    _tkNeedsDisplay = YES;
	    break;
	}
    }
    _tkDirtyRect = NSUnionRect(_tkDirtyRect, rect);
    [NSApp setNeedsToDraw:YES];
}

}

- (void) clearTkDirtyRect
{
@implementation TKContentView(TKWindowEvent)
    _tkNeedsDisplay = NO;
    _tkDirtyRect = NSZeroRect;
    [NSApp setNeedsToDraw:NO];
}

- (void) drawRect: (NSRect) rect
{
    const NSRect *rectsBeingDrawn;
    (void)rect;
    NSInteger rectsBeingDrawnCount;

#ifdef TK_MAC_DEBUG_DRAWING
    TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
    if (winPtr) {
    if (winPtr) fprintf(stderr, "drawRect: drawing %s\n",
			Tk_PathName(winPtr));
	fprintf(stderr, "drawRect: drawing %s in %s\n",
	    Tk_PathName(winPtr), NSStringFromRect(rect).UTF8String);
    }
#endif

    /*
     * We do not allow recursive calls to drawRect, but we only log them on OSX
     * > 10.13, where they should never happen.
     */

    if ([NSApp isDrawing]) {
	if ([NSApp macMinorVersion] > 13) {
	if ([NSApp macOSVersion] > 101300) {
	    TKLog(@"WARNING: a recursive call to drawRect was aborted.");
	}
	return;
    }

    [NSApp setIsDrawing: YES];

    [self clearTkDirtyRect];
    [self getRectsBeingDrawn:&rectsBeingDrawn count:&rectsBeingDrawnCount];
    CGFloat height = [self bounds].size.height;
    HIMutableShapeRef drawShape = HIShapeCreateMutable();

    while (rectsBeingDrawnCount--) {
	CGRect r = NSRectToCGRect(*rectsBeingDrawn++);

#ifdef TK_MAC_DEBUG_DRAWING
	fprintf(stderr, "drawRect: %dx%d@(%d,%d)\n", (int)r.size.width,
	       (int)r.size.height, (int)r.origin.x, (int)r.origin.y);
#endif

	r.origin.y = height - (r.origin.y + r.size.height);
	HIShapeUnionWithRect(drawShape, &r);
    }
    [self generateExposeEvents:(HIShapeRef)drawShape];
    [self generateExposeEvents:rect];
    CFRelease(drawShape);
    [NSApp setIsDrawing: NO];
    [NSApp setIsDrawing:NO];

    if ([self needsRedisplay]) {
	[self setNeedsRedisplay:NO];
	Tcl_DoWhenIdle(RedisplayView, self);
    }

#ifdef TK_MAC_DEBUG_DRAWING
    fprintf(stderr, "drawRect: done.\n");
#endif
}

-(void) setFrameSize: (NSSize)newsize
{
    [super setFrameSize: newsize];
    NSWindow *w = [self window];
    TkWindow *winPtr = TkMacOSXGetTkWindow(w);
    Tk_Window tkwin = (Tk_Window) winPtr;
    Tk_Window tkwin = (Tk_Window)winPtr;

    if (![self inLiveResize] &&
	[w respondsToSelector: @selector (tkLayoutChanged)]) {
	[(TKWindow *)w tkLayoutChanged];
    }

    if (winPtr) {
1019
1020
1021
1022
1023
1024
1025
1026



1027
1028
1029
1030
1031


1032

1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049

1050
1051
1052
1053

1054
1055
1056
1057
1058
1059
1060
1061
1062


1063
1064
1065
1066


1067
1068
1069
1070

1071
1072

1073
1074
1075


1076
1077


1078
1079
1080
1081

1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094


1095

1096
1097
1098
1099
1100
1101
1102
1103







1104
1105













1106
1107
1108
1109
1110
1111
1112
1113
1114




















1115
1116
1117
1118
1119
1120
1121
1122
















1123
1124
1125





1126
1127
1128
1129
1130





1131
1132
1133
1134
1135
1136
















1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151



1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171


1172

1173
1174
1175
1176
1177

1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195


1196
1197
1198
1199
1200
1201
1202
1203

1204
1205
1206
1207
1208
1209
1210
1009
1010
1011
1012
1013
1014
1015

1016
1017
1018
1019
1020



1021
1022

1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039

1040
1041
1042

1043
1044
1045
1046
1047
1048
1049
1050
1051
1052

1053
1054
1055
1056


1057
1058




1059


1060

1061
1062
1063
1064
1065

1066
1067
1068
1069
1070

1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082


1083
1084
1085
1086
1087
1088
1089
1090
1091



1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115







1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137






1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153



1154
1155
1156
1157
1158





1159
1160
1161
1162
1163






1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193

1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218

1219





1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247

1248
1249
1250
1251
1252
1253
1254
1255







-
+
+
+


-
-
-
+
+
-
+
















-
+


-

+








-
+
+


-
-
+
+
-
-
-
-
+
-
-
+
-


+
+

-
+
+



-
+











-
-
+
+

+





-
-
-
+
+
+
+
+
+
+


+
+
+
+
+
+
+
+
+
+
+
+
+


-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+














-
+
+
+




















+
+
-
+
-
-
-
-
-
+


















+
+







-
+







	 */

	TkMacOSXSetDrawingEnabled(winPtr, 1);
	TkMacOSXInvalClipRgns(tkwin);
	TkMacOSXUpdateClipRgn(winPtr);

	 /*
	  * Generate and process expose events to redraw the window.
	  * Generate and process expose events to redraw the window.  To avoid
	  * crashes, only do this if we are being called from drawRect.  See
	  * ticket [1fa8c3ed8d].
	  */

	HIRect bounds = NSRectToCGRect([self bounds]);
	HIShapeRef shape = HIShapeCreateWithRect(&bounds);
	[self generateExposeEvents: shape];
	if([NSApp isDrawing] || [self inLiveResize]) {
	    [self generateExposeEvents: [self bounds]];
	[w displayIfNeeded];
	}

	/*
	 * Finally, unlock the main autoreleasePool.
	 */

	[NSApp _unlockAutoreleasePool];
    }
}

/*
 * Core method of this class: generates expose events for redrawing.  The
 * expose events are immediately removed from the Tcl event loop and processed.
 * This causes drawing procedures to be scheduled as idle events.  Then all
 * pending idle events are processed so the drawing will actually take place.
 */

- (void) generateExposeEvents: (HIShapeRef) shape
- (void) generateExposeEvents: (NSRect) rect
{
    unsigned long serial;
    CGRect updateBounds;
    int updatesNeeded;
    CGRect updateBounds;
    TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
    ClientData oldArg;
    Tk_RestrictProc *oldProc;
    if (!winPtr) {
	return;
    }

    /*
     * Generate Tk Expose events.
     * Generate Tk Expose events.  All of these events will share the same
     * serial number.
     */

    HIShapeGetBounds(shape, &updateBounds);

    updateBounds = NSRectToCGRect(rect);
    updateBounds.origin.y = ([self bounds].size.height - updateBounds.origin.y
    /*
     * All of these events will share the same serial number.
     */

			     - updateBounds.size.height);
    serial = LastKnownRequestProcessed(Tk_Display(winPtr));
    updatesNeeded = GenerateUpdates(shape, &updateBounds, winPtr);
    updatesNeeded = GenerateUpdates(&updateBounds, winPtr);

    if (updatesNeeded) {

	serial = LastKnownRequestProcessed(Tk_Display(winPtr));

	/*
	 * First process all of the Expose events.
	 * Use the ExposeRestrictProc to process only the expose events.  This
	 * will create idle drawing tasks, which we handle before we return.
	 */

    	oldProc = Tk_RestrictEvents(ExposeRestrictProc, UINT2PTR(serial), &oldArg);
    	while (Tcl_ServiceEvent(TCL_WINDOW_EVENTS)) {};
    	while (Tcl_ServiceEvent(TCL_WINDOW_EVENTS|TCL_DONT_WAIT)) {};
    	Tk_RestrictEvents(oldProc, oldArg, &oldArg);

	/*
	 * Starting with OSX 10.14, which uses Core Animation to draw windows,
	 * all drawing must be done within the drawRect method.  (The CGContext
	 * which draws to the backing CALayer is created by the NSView before
	 * calling drawRect, and destroyed when drawRect returns.  Drawing done
	 * with the current CGContext outside of the drawRect method has no
	 * effect.)
	 *
	 * Fortunately, Tk schedules all drawing to be done while Tcl is idle.
	 * So we can do the drawing by processing all of the idle events that
	 * were created when the expose events were processed.
	 * So to run any display procs which were scheduled by the expose
	 * events we process all idle events before returning.
	 */

	while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {}
    }
}

/*
 * This method is called when a user changes between light and dark mode. The
 * implementation here generates a Tk virtual event which can be bound to a
 * function that redraws the window in an appropriate style.
 * In macOS 10.14 and later this method is called when a user changes between
 * light and dark mode or changes the accent color. The implementation
 * generates two virtual events.  The first is either <<LightAqua>> or
 * <<DarkAqua>>, depending on the view's current effective appearance.  The
 * second is <<AppearnceChanged>> and has a data string describing the
 * effective appearance of the view and the current accent and highlight
 * colors.
 */

#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400

static const char *const accentNames[] = {
    "Graphite",
    "Red",
    "Orange",
    "Yellow",
    "Green",
    "Blue",
    "Purple",
    "Pink"
};

- (void) viewDidChangeEffectiveAppearance
{
    XVirtualEvent event;
    int x, y;
    NSWindow *w = [self window];
    TkWindow *winPtr = TkMacOSXGetTkWindow(w);
    Tk_Window tkwin = (Tk_Window) winPtr;

    if (!winPtr) {
    Tk_Window tkwin = (Tk_Window)TkMacOSXGetTkWindow([self window]);
    if (!tkwin) {
	return;
    }
    NSAppearanceName effectiveAppearanceName = [[self effectiveAppearance] name];
    NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
    static const char *defaultColor = NULL;

    if (effectiveAppearanceName == NSAppearanceNameAqua) {
	Tk_SendVirtualEvent(tkwin, "LightAqua", NULL);
    } else if (effectiveAppearanceName == NSAppearanceNameDarkAqua) {
	Tk_SendVirtualEvent(tkwin, "DarkAqua", NULL);
    }
    if ([NSApp macOSVersion] < 101500) {

	/*
	 * Mojave cannot handle the KVO shenanigans that we need for the
	 * highlight and accent color notifications.
	 */

	return;
    }
    bzero(&event, sizeof(XVirtualEvent));
    event.type = VirtualEvent;
    event.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
    event.send_event = false;
    event.display = Tk_Display(tkwin);
    event.event = Tk_WindowId(tkwin);
    if (!defaultColor) {
	defaultColor = [NSApp macOSVersion] < 110000 ? "Blue" : "Multicolor";
	preferences = [[NSUserDefaults standardUserDefaults] retain];

	/*
	 * AppKit calls this method when the user changes the Accent Color
	 * but not when the user changes the Highlight Color.  So we register
	 * to receive KVO notifications for Highlight Color as well.
	 */

	[preferences addObserver:self
		      forKeyPath:@"AppleHighlightColor"
			 options:NSKeyValueObservingOptionNew
			 context:NULL];
    }
    NSString *accent = [preferences stringForKey:@"AppleAccentColor"];
    event.root = XRootWindow(Tk_Display(tkwin), 0);
    event.subwindow = None;
    event.time = TkpGetMS();
    NSArray *words = [[preferences stringForKey:@"AppleHighlightColor"]
			        componentsSeparatedByString: @" "];
    NSString *highlight = [words count] > 3 ? [words objectAtIndex:3] : nil;
    const char *accentName = accent ? accentNames[1 + accent.intValue] : defaultColor;
    const char *highlightName = highlight ? highlight.UTF8String: defaultColor;
    XQueryPointer(NULL, winPtr->window, NULL, NULL,
    		  &event.x_root, &event.y_root, &x, &y, &event.state);
    Tk_TopCoordsToWindow(tkwin, x, y, &event.x, &event.y);
    event.same_screen = true;
    if (TkMacOSXInDarkMode(tkwin)) {
    char data[256];
    snprintf(data, 256, "Appearance %s Accent %s Highlight %s",
	     effectiveAppearanceName.UTF8String, accentName,
	     highlightName);
    Tk_SendVirtualEvent(tkwin, "AppearanceChanged", Tcl_NewStringObj(data, -1));
	event.name = Tk_GetUid("DarkAqua");
    } else {
        event.name = Tk_GetUid("LightAqua");
    }
    Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL);
}
}

- (void)observeValueForKeyPath:(NSString *)keyPath
		      ofObject:(id)object
			change:(NSDictionary *)change
		       context:(void *)context
{
    NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
    if (object == preferences && [keyPath isEqualToString:@"AppleHighlightColor"]) {
	if (@available(macOS 10.14, *)) {
	    [self viewDidChangeEffectiveAppearance];
	}
    }
}

#endif

/*
 * This is no-op on 10.7 and up because Apple has removed this widget, but we
 * are leaving it here for backwards compatibility.
 */

- (void) tkToolbarButton: (id) sender
{
#ifdef TK_MAC_DEBUG_EVENTS
    TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd);
#endif
    XVirtualEvent event;
    int x, y;
    TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
    Tk_Window tkwin = (Tk_Window) winPtr;
    Tk_Window tkwin = (Tk_Window)winPtr;
    (void)sender;

    if (!winPtr){
	return;
    }
    bzero(&event, sizeof(XVirtualEvent));
    event.type = VirtualEvent;
    event.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
    event.send_event = false;
    event.display = Tk_Display(tkwin);
    event.event = Tk_WindowId(tkwin);
    event.root = XRootWindow(Tk_Display(tkwin), 0);
    event.subwindow = None;
    event.time = TkpGetMS();
    XQueryPointer(NULL, winPtr->window, NULL, NULL,
	    &event.x_root, &event.y_root, &x, &y, &event.state);
    Tk_TopCoordsToWindow(tkwin, x, y, &event.x, &event.y);
    event.same_screen = true;
    event.name = Tk_GetUid("ToolbarButton");
    Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL);
}

/*
 * On Catalina this is never called and drawRect clips to the rect that
- (BOOL) isOpaque
 * is passed to it by AppKit.
{
    NSWindow *w = [self window];
      return (w && (([w styleMask] & NSTexturedBackgroundWindowMask) ||
    	    ![w isOpaque]) ? NO : YES);
}
 */

- (BOOL) wantsDefaultClipping
{
    return NO;
}

- (BOOL) acceptsFirstResponder
{
    return YES;
}

/*
 * This keyDown method does nothing, which is a huge improvement over the
 * default keyDown method which beeps every time a key is pressed.
 */

- (void) keyDown: (NSEvent *) theEvent
{
    (void)theEvent;

#ifdef TK_MAC_DEBUG_EVENTS
    TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, theEvent);
#endif
}

/*
 * When the services menu is opened this is called for each Responder in
 * the Responder chain until a service provider is found.  The TkContentView
 * the Responder chain until a service provider is found.  The TKContentView
 * should be the first (and generally only) Responder in the chain.  We
 * return the TkServices object that was created in TkpInit.
 */

- (id)validRequestorForSendType:(NSString *)sendType
		     returnType:(NSString *)returnType
{
Changes to macosx/tkMacOSXWm.c.
1
2
3
4
5
6
7
8
9
10
11
12





13
14
15
16
17
18
19
20
21

22
23
24






25
26
27
28
29
30
31
1
2
3
4
5
6
7





8
9
10
11
12
13
14
15
16
17
18
19
20

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37







-
-
-
-
-
+
+
+
+
+








-
+



+
+
+
+
+
+







/*
 * tkMacOSXWm.c --
 *
 *	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 <[email protected]>
 * 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 <[email protected]>
 * 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.
 */

#include "tkMacOSXPrivate.h"
#include "tkScrollbar.h"
#include "tkMacOSXWm.h"
#include "tkMacOSXEvent.h"
#include "tkMacOSXInt.h"
#include "tkMacOSXDebug.h"
#include "tkMacOSXConstants.h"

/*
 * Setting this to 1 prints when each window is freed, setting it to 2 adds
 * dumps of the autorelease pools, and setting it to 3 also shows each retain
 * and release.
 */

#define DEBUG_ZOMBIES 0

/*
#ifdef TK_MAC_DEBUG
#define TK_MAC_DEBUG_WINDOWS
#endif
*/
173
174
175
176
177
178
179
180

181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
179
180
181
182
183
184
185

186
187
188
189
190
191
192
193
194







195
196
197
198
199
200
201







-
+








-
-
-
-
-
-
-







 */

static void TopLevelReqProc(ClientData dummy, Tk_Window tkwin);

static const Tk_GeomMgr wmMgrType = {
    "wm",			/* name */
    TopLevelReqProc,		/* requestProc */
    NULL,			/* lostSlaveProc */
    NULL,			/* lostContentProc */
};

/*
 * The following keeps state for Aqua dock icon bounce notification.
 */

static int tkMacOSXWmAttrNotifyVal = 0;

/*
 * Hash table for Mac Window -> TkWindow mapping.
 */

static Tcl_HashTable windowTable;
static int windowHashInit = false;

/*
 * Forward declarations for procedures defined in this file:
 */

static NSRect		InitialWindowBounds(TkWindow *winPtr,
			    NSWindow *macWindow);
static int		ParseGeometry(Tcl_Interp *interp, char *string,
310
311
312
313
314
315
316
317

318
319
320
321
322
323
324
309
310
311
312
313
314
315

316
317
318
319
320
321
322
323







-
+







static int		WmWinTabbingId(Tcl_Interp *interp, TkWindow *winPtr,
			    int objc, Tcl_Obj *const objv[]);
static int		WmWinAppearance(Tcl_Interp *interp, TkWindow *winPtr,
			    int objc, Tcl_Obj *const objv[]);
static void		ApplyWindowAttributeFlagChanges(TkWindow *winPtr,
			    NSWindow *macWindow, UInt64 oldAttributes,
			    int oldFlags, int create, int initial);
static void		ApplyMasterOverrideChanges(TkWindow *winPtr,
static void		ApplyContainerOverrideChanges(TkWindow *winPtr,
			    NSWindow *macWindow);
static void		GetMinSize(TkWindow *winPtr, int *minWidthPtr,
			    int *minHeightPtr);
static void		GetMaxSize(TkWindow *winPtr, int *maxWidthPtr,
			    int *maxHeightPtr);
static void		RemapWindows(TkWindow *winPtr,
			    MacDrawable *parentWin);
350
351
352
353
354
355
356

357


358
359



360



361


362
363
364
365
366
367
368
349
350
351
352
353
354
355
356

357
358
359

360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376







+
-
+
+

-
+
+
+

+
+
+

+
+







}
#endif

@end

#pragma mark -

@implementation TKPanel: NSPanel
#pragma mark TKWindow(TKWm)
@synthesize tkWindow = _tkWindow;
@end

@implementation TKWindow: NSWindow
@implementation TKDrawerWindow: NSWindow
@synthesize tkWindow = _tkWindow;
@end

@implementation TKWindow: NSWindow
@synthesize mouseInResizeArea = _mouseInResizeArea;
@synthesize tkWindow = _tkWindow;
@end

#pragma mark TKWindow(TKWm)

@implementation TKWindow(TKWm)

/*
 * This method synchronizes Tk's understanding of the bounds of a contentView
 * with the window's.  It is needed because there are situations when the
 * window manager can change the layout of an NSWindow without having been
426
427
428
429
430
431
432

433

434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450

451
452
453
454
455
456
457
458
459
460
461
462
463
464

465
466
467
468
469
470
471
472
473
474
475
476

477
478
479
480
481
482
483
434
435
436
437
438
439
440
441

442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458

459
460
461
462
463
464
465
466
467
468
469
470
471
472

473
474
475
476
477
478
479
480
481
482
483
484

485
486
487
488
489
490
491
492







+
-
+
















-
+













-
+











-
+







    }
    return frameSize;
}

- (BOOL) canBecomeKeyWindow
{
    TkWindow *winPtr = TkMacOSXGetTkWindow(self);

    if (!winPtr) {
    if (!winPtr || !winPtr->wmInfoPtr) {
	return NO;
    }
    return (winPtr->wmInfoPtr &&
	    (winPtr->wmInfoPtr->macClass == kHelpWindowClass ||
	     winPtr->wmInfoPtr->attributes & kWindowNoActivatesAttribute)
	    ) ? NO : YES;
}

#if DEBUG_ZOMBIES
- (id) retain
{
    id result = [super retain];
    const char *title = [[self title] UTF8String];
    if (title == nil) {
	title = "unnamed window";
    }
    if (DEBUG_ZOMBIES > 1) {
    if (DEBUG_ZOMBIES > 2) {
	fprintf(stderr, "Retained <%s>. Count is: %lu\n",
		title, [self retainCount]);
    }
    return result;
}

- (id) autorelease
{
    id result = [super autorelease];
    const char *title = [[self title] UTF8String];
    if (title == nil) {
	title = "unnamed window";
    }
    if (DEBUG_ZOMBIES > 1) {
    if (DEBUG_ZOMBIES > 2) {
	fprintf(stderr, "Autoreleased <%s>. Count is %lu\n",
		title, [self retainCount]);
    }
    return result;
}

- (oneway void) release {
    const char *title = [[self title] UTF8String];
    if (title == nil) {
	title = "unnamed window";
    }
    if (DEBUG_ZOMBIES > 1) {
    if (DEBUG_ZOMBIES > 2) {
	fprintf(stderr, "Releasing <%s>. Count is %lu\n",
		title, [self retainCount]);
    }
    [super release];
}

- (void) dealloc {
513
514
515
516
517
518
519
520

521
522
523
524
525
526
527
522
523
524
525
526
527
528

529
530
531
532
533
534
535
536







-
+







 *----------------------------------------------------------------------
 */

static void
SetWindowSizeLimits(
    TkWindow *winPtr)
{
    NSWindow *macWindow = TkMacOSXDrawableWindow(winPtr->window);
    NSWindow *macWindow = TkMacOSXGetNSWindowForDrawable(winPtr->window);
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    int minWidth, minHeight, maxWidth, maxHeight, base;

    if (!macWindow) {
	return;
    }
    GetMinSize(winPtr, &minWidth, &minHeight);
655
656
657
658
659
660
661
662

663
664
665
666
667
668

669
670
671
672
673
674
675
664
665
666
667
668
669
670

671
672
673
674
675
676

677
678
679
680
681
682
683
684







-
+





-
+







 *----------------------------------------------------------------------
 */

void
TkWmNewWindow(
    TkWindow *winPtr)		/* Newly-created top-level window. */
{
    WmInfo *wmPtr = ckalloc(sizeof(WmInfo));
    WmInfo *wmPtr = (WmInfo *)ckalloc(sizeof(WmInfo));

    wmPtr->winPtr = winPtr;
    wmPtr->reparent = None;
    wmPtr->titleUid = NULL;
    wmPtr->iconName = NULL;
    wmPtr->master = NULL;
    wmPtr->container = NULL;
    wmPtr->hints.flags = InputHint | StateHint;
    wmPtr->hints.input = True;
    wmPtr->hints.initial_state = NormalState;
    wmPtr->hints.icon_pixmap = None;
    wmPtr->hints.icon_window = None;
    wmPtr->hints.icon_x = wmPtr->hints.icon_y = 0;
    wmPtr->hints.icon_mask = None;
719
720
721
722
723
724
725
726

727
728
729
730
731
732
733
734





































































735
736
737
738
739
740
741
728
729
730
731
732
733
734

735
736
737
738
739
740
741
742

743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818







-
+







-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    UpdateVRootGeometry(wmPtr);

    /*
     * Tk must monitor structure events for top-level windows, in order to
     * detect size and position changes caused by window managers.
     */

    Tk_CreateEventHandler((Tk_Window) winPtr, StructureNotifyMask,
    Tk_CreateEventHandler((Tk_Window)winPtr, StructureNotifyMask,
	    TopLevelEventProc, winPtr);

    /*
     * Arrange for geometry requests to be reflected from the window to the
     * window manager.
     */

    Tk_ManageGeometry((Tk_Window) winPtr, &wmMgrType, (ClientData) 0);
    Tk_ManageGeometry((Tk_Window)winPtr, &wmMgrType, NULL);
}

/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXHandleMapOrUnmap --
 *
 *      The mechanism used by a geometry manager to propogate the information
 *      about which of its content widgets are mapped is to call Tk_MapWindow
 *      or Tk_UnmapNotify.  Those functions generate MapNotify or UnmapNotify
 *      events and then handle them immediately.  Other platforms use
 *      Tk_HandleEvent to do this.  But that does not work correctly on macOS
 *      due to the fact that the calls to Tk_MapNotify or Tk_UnmapNotify can
 *      occur in display procedures which are being run in the drawRect method
 *      of a TKContentView. The events will be processed after drawRect
 *      returns, but they need to be processed immediately in some cases.

 *      This function operates as a macOS alternative to Tk_HandleEvent, for
 *      processing MapNotify or UnmapNotify events only.  It is called by
 *      Tk_MapWindow, Tk_UnmapWindow, TkWmMapWindow and TkWmUnmapWindow.
 *      Rather than using Tk_HandleEvent it installs a filter which restricts
 *      to the MapNotify or UnmapNotify events, it queues the event and then
 *      processes window events with the filter installed.  This allows the
 *      event to be handled immediately even from within the drawRect method.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Handles a MapNotify or UnMapNotify event.
 *
 *----------------------------------------------------------------------
 */
static Tk_RestrictAction
MapUnmapRestrictProc(
    TCL_UNUSED(void*),
    XEvent *eventPtr)
{
    return (eventPtr->type==MapNotify || eventPtr->type==UnmapNotify ?
	    TK_PROCESS_EVENT : TK_DEFER_EVENT);
}

MODULE_SCOPE
void TkMacOSXHandleMapOrUnmap(
    Tk_Window tkwin,
    XEvent *event)
{
    ClientData oldArg;
    Tk_RestrictProc *oldProc;
    TkWindow *winPtr = (TkWindow *) tkwin;
    const Tk_GeomMgr *geomMgrPtr = winPtr->geomMgrPtr;

    /*
     * Sadly, this approach does not work with the "text" geometry manager.
     * The mysterious unexplained crash elicited by textDisp-5.2 occurs.  So we
     * have to check for the "text" manager and revert to using Tk_HandleEvent
     * in that case.  Hopefully this can be removed when the revised text
     * widget is in place.
     */

    if (geomMgrPtr && strcmp(geomMgrPtr->name, "text") == 0) {
	Tk_HandleEvent(event);
	return;
    }
    oldProc = Tk_RestrictEvents(MapUnmapRestrictProc, NULL, &oldArg);
    Tk_QueueWindowEvent(event, TCL_QUEUE_TAIL);
    while (Tcl_DoOneEvent(TCL_WINDOW_EVENTS|TCL_DONT_WAIT)) {}
    Tk_RestrictEvents(oldProc, oldArg, &oldArg);
}

/*
 *----------------------------------------------------------------------
 *
 * TkWmMapWindow --
 *
759
760
761
762
763
764
765


766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781

782
783
784
785
786
787
788
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859

860
861
862
863
864
865
866
867







+
+















-
+








void
TkWmMapWindow(
    TkWindow *winPtr)		/* Top-level window that's about to be
				 * mapped. */
{
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    XEvent event;

    if (wmPtr->flags & WM_NEVER_MAPPED) {
	/*
	 * Create the underlying Mac window for this Tk window.
	 */

	if (!TkMacOSXHostToplevelExists(winPtr)) {
	    TkMacOSXMakeRealWindowExist(winPtr);
	}

	wmPtr->flags &= ~WM_NEVER_MAPPED;

	/*
	 * Generate configure event when we first map the window.
	 */

	TkGenWMConfigureEvent((Tk_Window) winPtr, wmPtr->x, wmPtr->y, -1, -1,
	TkGenWMConfigureEvent((Tk_Window)winPtr, wmPtr->x, wmPtr->y, -1, -1,
		TK_LOCATION_CHANGED);

	/*
	 * This is the first time this window has ever been mapped. Store all
	 * the window-manager-related information for the window.
	 */

822
823
824
825
826
827
828
829

830
831

832








833
834
835
836
837
838
839
901
902
903
904
905
906
907

908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927







-
+


+

+
+
+
+
+
+
+
+







    if (wmPtr->flags & WM_UPDATE_PENDING) {
	Tcl_CancelIdleCall(UpdateGeometryInfo, winPtr);
    }
    UpdateGeometryInfo(winPtr);
    wmPtr->flags &= ~WM_ABOUT_TO_MAP;

    /*
     * Map the window.
     * Map the window and process a MapNotify event for it.
     */

    winPtr->flags |= TK_MAPPED;
    XMapWindow(winPtr->display, winPtr->window);
    event.xany.serial = LastKnownRequestProcessed(winPtr->display);
    event.xany.send_event = False;
    event.xany.display = winPtr->display;
    event.xmap.window = winPtr->window;
    event.xmap.type = MapNotify;
    event.xmap.event = winPtr->window;
    event.xmap.override_redirect = winPtr->atts.override_redirect;
    TkpHandleMapOrUnmap((Tk_Window)winPtr, &event);
}

/*
 *----------------------------------------------------------------------
 *
 * TkWmUnmapWindow --
 *
850
851
852
853
854
855
856










857

858
859
860
861
862
863
864
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963







+
+
+
+
+
+
+
+
+
+

+







 */

void
TkWmUnmapWindow(
    TkWindow *winPtr)		/* Top-level window that's about to be
				 * unmapped. */
{
    XEvent event;

    event.xany.serial = LastKnownRequestProcessed(winPtr->display);
    event.xany.send_event = False;
    event.xany.display = winPtr->display;
    event.xunmap.type = UnmapNotify;
    event.xunmap.window = winPtr->window;
    event.xunmap.event = winPtr->window;
    event.xunmap.from_configure = false;
    winPtr->flags &= ~TK_MAPPED;
    XUnmapWindow(winPtr->display, winPtr->window);
    TkpHandleMapOrUnmap((Tk_Window)winPtr, &event);
}

/*
 *----------------------------------------------------------------------
 *
 * TkWmDeadWindow --
 *
875
876
877
878
879
880
881

882
883
884
885
886
887
888

889
890
891
892
893


894
895
896
897
898
899
900
901
902
903
904
905
906
907
908

909
910
911
912

913
914
915
916
917
918
919
974
975
976
977
978
979
980
981
982
983
984
985
986
987

988
989
990
991


992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007

1008
1009
1010
1011

1012
1013
1014
1015
1016
1017
1018
1019







+






-
+



-
-
+
+














-
+



-
+







 */

void
TkWmDeadWindow(
    TkWindow *winPtr)		/* Top-level window that's being deleted. */
{
    WmInfo *wmPtr = winPtr->wmInfoPtr, *wmPtr2;
    TKWindow *deadNSWindow;

    if (wmPtr == NULL) {
	return;
    }

    /*
     *If the dead window is a transient, remove it from the master's list.
     *If the dead window is a transient, remove it from the container's list.
     */

    RemoveTransient(winPtr);
    Tk_ManageGeometry((Tk_Window) winPtr, NULL, NULL);
    Tk_DeleteEventHandler((Tk_Window) winPtr, StructureNotifyMask,
    Tk_ManageGeometry((Tk_Window)winPtr, NULL, NULL);
    Tk_DeleteEventHandler((Tk_Window)winPtr, StructureNotifyMask,
	    TopLevelEventProc, winPtr);
    if (wmPtr->hints.flags & IconPixmapHint) {
	Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_pixmap);
    }
    if (wmPtr->hints.flags & IconMaskHint) {
	Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_mask);
    }
    if (wmPtr->iconName != NULL) {
	ckfree(wmPtr->iconName);
    }
    if (wmPtr->leaderName != NULL) {
	ckfree(wmPtr->leaderName);
    }
    if (wmPtr->icon != NULL) {
	wmPtr2 = ((TkWindow *) wmPtr->icon)->wmInfoPtr;
	wmPtr2 = ((TkWindow *)wmPtr->icon)->wmInfoPtr;
	wmPtr2->iconFor = NULL;
    }
    if (wmPtr->iconFor != NULL) {
	wmPtr2 = ((TkWindow *) wmPtr->iconFor)->wmInfoPtr;
	wmPtr2 = ((TkWindow *)wmPtr->iconFor)->wmInfoPtr;
	wmPtr2->icon = NULL;
	wmPtr2->hints.flags &= ~IconWindowHint;
    }
    while (wmPtr->protPtr != NULL) {
	ProtocolHandler *protPtr = wmPtr->protPtr;
	wmPtr->protPtr = protPtr->nextPtr;
	Tcl_EventuallyFree(protPtr, TCL_DYNAMIC);
932
933
934
935
936
937
938
939

940
941

942
943

944
945
946
947
948
949
950
951
952
953
954
955
956


957
958

959
960




961
962
963




964
965
966
967

968

969

970
971

972
973
974
975
976

977
978
979
980
981
982
983
984
985













986
987
988

989
990
991


992
993
994
995
996
997
998
999
1000
1001



1002
1003
1004
1005
1006
1007
1008
1009










1010
1011
1012
1013

1014
1015
1016
1017
1018



1019


1020

1021

1022
1023
1024
1025







1026
1027
1028
1029
1030
1031
1032
1032
1033
1034
1035
1036
1037
1038

1039
1040

1041
1042

1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054


1055
1056


1057
1058
1059
1060
1061
1062
1063



1064
1065
1066
1067

1068
1069

1070
1071
1072

1073
1074

1075
1076
1077
1078
1079

1080
1081
1082







1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096


1097



1098
1099










1100
1101
1102








1103
1104
1105
1106
1107
1108
1109
1110
1111
1112

1113


1114

1115
1116


1117
1118
1119
1120
1121
1122
1123
1124

1125
1126
1127
1128

1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142







-
+

-
+

-
+











-
-
+
+
-
-
+


+
+
+
+
-
-
-
+
+
+
+
-


-
+

+
-
+

-
+




-
+


-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
+
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-

-
-
+
-


-
-
+
+
+

+
+

+
-
+



-
+
+
+
+
+
+
+







     * If the dead window has a transient, remove references to it from
     * the transient.
     */

    for (Transient *transientPtr = wmPtr->transientPtr;
	    transientPtr != NULL; transientPtr = transientPtr->nextPtr) {
    	TkWindow *winPtr2 = transientPtr->winPtr;
    	TkWindow *masterPtr = (TkWindow *) TkGetTransientMaster(winPtr2);
    	TkWindow *containerPtr = (TkWindow *)TkMacOSXGetContainer(winPtr2);

    	if (masterPtr == winPtr) {
    	if (containerPtr == winPtr) {
    	    wmPtr2 = winPtr2->wmInfoPtr;
    	    wmPtr2->master = NULL;
    	    wmPtr2->container = NULL;
    	}
    }

    while (wmPtr->transientPtr != NULL) {
	Transient *transientPtr = wmPtr->transientPtr;

	wmPtr->transientPtr = transientPtr->nextPtr;
	ckfree(transientPtr);
    }

    /*
     * Delete the Mac window and remove it from the windowTable. The window
     * could be nil if the window was never mapped. However, we don't do this
     * Unregister the NSWindow and remove all references to it from the Tk
     * data structures.  If the NSWindow is a child, disassociate it from
     * for embedded windows, they don't go in the window list, and they do not
     * own their portPtr's.
     * the parent.  Then close and release the NSWindow.
     */

    deadNSWindow = (TKWindow *)wmPtr->window;
    if (deadNSWindow && !Tk_IsEmbedded(winPtr)) {
	NSWindow *parent = [deadNSWindow parentWindow];
	[deadNSWindow setTkWindow:None];
    NSWindow *window = wmPtr->window;

    if (window && !Tk_IsEmbedded(winPtr)) {
        if (winPtr->window) {
            ((MacDrawable *)winPtr->window)->view = nil;
        }
	wmPtr->window = NULL;
	NSWindow *parent = [window parentWindow];

	if (parent) {
	    [parent removeChildWindow:window];
	    [parent removeChildWindow:deadNSWindow];
	}

#if DEBUG_ZOMBIES > 0
#if DEBUG_ZOMBIES > 1
	{
	    const char *title = [[window title] UTF8String];
	    const char *title = [[deadNSWindow title] UTF8String];
	    if (title == nil) {
		title = "unnamed window";
	    }
	    fprintf(stderr, ">>>> Closing <%s>. Count is: %lu\n", title,
		    [window retainCount]);
		    [deadNSWindow retainCount]);
	}
#endif
	[window close];
	TkMacOSXUnregisterMacWindow(window);
        if (winPtr->window) {
            ((MacDrawable *) winPtr->window)->view = nil;
        }
	wmPtr->window = NULL;
        [window release];

	/*
	 * When a window is closed we want to move the focus to the next
	 * highest window.  Apple's documentation says that calling the
	 * orderOut method of the key window will accomplish this.  But
	 * experiment shows that this is not the case.  So we have to reset the
	 * key window ourselves.  When the window is the last one on the screen
	 * there is no choice for a new key window.  Moreover, if the host
	 * computer has a TouchBar then the TouchBar holds a reference to the
	 * key window which prevents it from being deallocated until it stops
	 * being the key window.  On these systems the only option for
	 * preventing zombies is to set the key window to nil.
	 */

	/* Activate the highest window left on the screen. */
	NSArray *windows = [NSApp orderedWindows];
	for (NSWindow *w in [NSApp orderedWindows]) {
	for (id nswindow in windows) {
	    TkWindow *winPtr2 = TkMacOSXGetTkWindow(nswindow);

	    TkWindow *winPtr2 = TkMacOSXGetTkWindow(w);
	    BOOL isOnScreen;
	    if (winPtr2 && nswindow != window) {
		WmInfo *wmPtr = winPtr2->wmInfoPtr;
		BOOL minimized = (wmPtr->hints.initial_state == IconicState
			|| wmPtr->hints.initial_state == WithdrawnState);

		/*
		 * If no windows are left on the screen and the next window is
		 * iconified or withdrawn, we don't want to make it be the
		 * KeyWindow because that would cause it to be displayed on the
		 * screen.

	    if (!winPtr2 || !winPtr2->wmInfoPtr) {
		continue;
		 */

		if ([nswindow canBecomeKeyWindow] && !minimized) {
		    [nswindow makeKeyAndOrderFront:NSApp];
		    break;
		}
	    }
	}
	    }
	    wmPtr2 = winPtr2->wmInfoPtr;
	    isOnScreen = (wmPtr2->hints.initial_state != IconicState &&
			  wmPtr2->hints.initial_state != WithdrawnState);
	    if (w != deadNSWindow && isOnScreen && [w canBecomeKeyWindow]) {
		[w makeKeyAndOrderFront:NSApp];
		break;
	    }
	}


	/*
	 * Process all window events immediately to force the closed window to
	 * be deallocated.  But don't do this for the root window as that is
	 * Prevent zombies on systems with a TouchBar.
	 * unnecessary and can lead to segfaults.
	 */

	if (winPtr->parentPtr) {
	    while (Tcl_DoOneEvent(TCL_WINDOW_EVENTS|TCL_DONT_WAIT)) {}
	if (deadNSWindow == [NSApp keyWindow]) {
	    [NSApp _setKeyWindow:nil];
	    [NSApp _setMainWindow:nil];
	}
	[deadNSWindow close];
	[deadNSWindow release];
	[NSApp _resetAutoreleasePool];

#if DEBUG_ZOMBIES > 0
#if DEBUG_ZOMBIES > 1
	fprintf(stderr, "================= Pool dump ===================\n");
	[NSAutoreleasePool showPools];
#endif
    }

    }

    /*
     * Deallocate the wmInfo and clear the wmInfoPtr.
     */

    ckfree(wmPtr);
    winPtr->wmInfoPtr = NULL;
}

/*
 *----------------------------------------------------------------------
 *
1044
1045
1046
1047
1048
1049
1050
1051

1052
1053
1054
1055
1056
1057
1058
1154
1155
1156
1157
1158
1159
1160

1161
1162
1163
1164
1165
1166
1167
1168







-
+







 *	A window property may get updated.
 *
 *----------------------------------------------------------------------
 */

void
TkWmSetClass(
    TkWindow *winPtr)		/* Newly-created top-level window. */
    TCL_UNUSED(TkWindow *))		/* Newly-created top-level window. */
{
    return;
}

/*
 *----------------------------------------------------------------------
 *
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081

1082
1083
1084
1085
1086
1087
1088
1176
1177
1178
1179
1180
1181
1182

1183
1184
1185
1186
1187
1188
1189

1190
1191
1192
1193
1194
1195
1196
1197







-







-
+







 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

/* ARGSUSED */
int
Tk_WmObjCmd(
    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 = (Tk_Window) clientData;
    Tk_Window tkwin = (Tk_Window)clientData;
    static const char *const optionStrings[] = {
	"aspect", "attributes", "client", "colormapwindows",
	"command", "deiconify", "focusmodel", "forget",
	"frame", "geometry", "grid", "group",
	"iconbitmap", "iconify", "iconmask", "iconname",
	"iconphoto", "iconposition", "iconwindow",
	"manage", "maxsize", "minsize", "overrideredirect",
1113
1114
1115
1116
1117
1118
1119
1120

1121
1122
1123
1124
1125
1126
1127
1222
1223
1224
1225
1226
1227
1228

1229
1230
1231
1232
1233
1234
1235
1236







-
+







    if ((argv1[0] == 't') && (strncmp(argv1, "tracing", length) == 0)
	    && (length >= 3)) {
	if ((objc != 2) && (objc != 3)) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?boolean?");
	    return TCL_ERROR;
	}
	if (objc == 2) {
	    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(wmTracing));
	    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(wmTracing != 0));
	    return TCL_OK;
	}
	return Tcl_GetBooleanFromObj(interp, objv[2], &wmTracing);
    }

    if (Tcl_GetIndexFromObjStruct(interp, objv[1], optionStrings,
	    sizeof(char *), "option", 0, &index) != TCL_OK) {
1231
1232
1233
1234
1235
1236
1237
1238

1239
1240
1241
1242
1243
1244

1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259




1260
1261
1262
1263
1264
1265
1266
1340
1341
1342
1343
1344
1345
1346

1347
1348
1349
1350
1351
1352

1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364




1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375







-
+





-
+











-
-
-
-
+
+
+
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmAspectCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    int numer1, denom1, numer2, denom2;

    if ((objc != 3) && (objc != 7)) {
	Tcl_WrongNumArgs(interp, 2, objv,
		"window ?minNumer minDenom maxNumer maxDenom?");
	return TCL_ERROR;
    }
    if (objc == 3) {
	if (wmPtr->sizeHintsFlags & PAspect) {
	    Tcl_Obj *results[4];

	    results[0] = Tcl_NewIntObj(wmPtr->minAspect.x);
	    results[1] = Tcl_NewIntObj(wmPtr->minAspect.y);
	    results[2] = Tcl_NewIntObj(wmPtr->maxAspect.x);
	    results[3] = Tcl_NewIntObj(wmPtr->maxAspect.y);
	    results[0] = Tcl_NewWideIntObj(wmPtr->minAspect.x);
	    results[1] = Tcl_NewWideIntObj(wmPtr->minAspect.y);
	    results[2] = Tcl_NewWideIntObj(wmPtr->maxAspect.x);
	    results[3] = Tcl_NewWideIntObj(wmPtr->maxAspect.y);
	    Tcl_SetObjResult(interp, Tcl_NewListObj(4, results));
	}
	return TCL_OK;
    }
    if (*Tcl_GetString(objv[3]) == '\0') {
	wmPtr->sizeHintsFlags &= ~PAspect;
    } else {
1335
1336
1337
1338
1339
1340
1341
1342

1343
1344
1345
1346
1347
1348
1349
1444
1445
1446
1447
1448
1449
1450

1451
1452
1453
1454
1455
1456
1457
1458







-
+







	[macWindow setAlphaValue:dval];
	break;
    }
    case WMATT_FULLSCREEN:
	if (Tcl_GetBooleanFromObj(interp, value, &boolean) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (boolean != ((wmPtr->flags & WM_FULLSCREEN) != 0)) {
	if (boolean != (([macWindow styleMask] & NSFullScreenWindowMask) != 0)) {
#if !(MAC_OS_X_VERSION_MAX_ALLOWED < 1070)
	    [macWindow toggleFullScreen:macWindow];
#else
	    TKLog(@"The fullscreen attribute is ignored on this system.");
#endif
	}
	break;
1413
1414
1415
1416
1417
1418
1419
1420

1421
1422
1423
1424
1425
1426
1427
1522
1523
1524
1525
1526
1527
1528

1529
1530
1531
1532
1533
1534
1535
1536







-
+







		wmPtr->flags &= ~WM_TRANSPARENT;
		wmPtr->attributes &= ~kWindowNoShadowAttribute;
	    }
	    ApplyWindowAttributeFlagChanges(winPtr, macWindow, oldAttributes,
		    oldFlags, 1, 0);
	    [macWindow setBackgroundColor:boolean ? [NSColor clearColor] : nil];
	    [macWindow setOpaque:!boolean];
	    TkMacOSXInvalidateWindow((MacDrawable *) winPtr->window,
	    TkMacOSXInvalidateWindow((MacDrawable *)winPtr->window,
		    TK_PARENT_WINDOW);
	    }
	break;
    case WMATT_TYPE:
	TKLog(@"The type attribute is ignored on macOS.");
	break;
    case _WMATT_LAST_ATTRIBUTE:
1452
1453
1454
1455
1456
1457
1458
1459

1460
1461
1462

1463
1464
1465

1466
1467
1468
1469
1470
1471
1472

1473
1474
1475

1476
1477
1478
1479
1480
1481
1482
1561
1562
1563
1564
1565
1566
1567

1568
1569
1570

1571
1572
1573

1574
1575
1576
1577
1578
1579
1580

1581
1582
1583

1584
1585
1586
1587
1588
1589
1590
1591







-
+


-
+


-
+






-
+


-
+







    WmInfo *wmPtr = winPtr->wmInfoPtr;

    switch (attribute) {
    case WMATT_ALPHA:
	result = Tcl_NewDoubleObj([macWindow alphaValue]);
	break;
    case WMATT_FULLSCREEN:
	result = Tcl_NewBooleanObj(wmPtr->flags & WM_FULLSCREEN);
	result = Tcl_NewBooleanObj([macWindow styleMask] & NSFullScreenWindowMask);
	break;
    case WMATT_MODIFIED:
	result = Tcl_NewBooleanObj([macWindow isDocumentEdited]);
	result = Tcl_NewWideIntObj([macWindow isDocumentEdited] != 0);
	break;
    case WMATT_NOTIFY:
	result = Tcl_NewBooleanObj(tkMacOSXWmAttrNotifyVal);
	result = Tcl_NewWideIntObj(tkMacOSXWmAttrNotifyVal != 0);
	break;
    case WMATT_TITLEPATH:
	result = Tcl_NewStringObj([[macWindow representedFilename] UTF8String],
		-1);
	break;
    case WMATT_TOPMOST:
	result = Tcl_NewBooleanObj(wmPtr->flags & WM_TOPMOST);
	result = Tcl_NewWideIntObj((wmPtr->flags & WM_TOPMOST) != 0);
	break;
    case WMATT_TRANSPARENT:
	result = Tcl_NewBooleanObj(wmPtr->flags & WM_TRANSPARENT);
	result = Tcl_NewWideIntObj((wmPtr->flags & WM_TRANSPARENT) != 0);
	break;
    case WMATT_TYPE:
	result = Tcl_NewStringObj("unsupported", -1);
	break;
    case _WMATT_LAST_ATTRIBUTE:
    default:
	break;
1499
1500
1501
1502
1503
1504
1505
1506

1507
1508
1509
1510
1511
1512
1513
1514
1515
1516

1517
1518
1519
1520
1521

1522
1523
1524
1525
1526
1527
1528
1608
1609
1610
1611
1612
1613
1614

1615
1616
1617
1618
1619
1620
1621
1622
1623
1624

1625
1626
1627
1628
1629

1630
1631
1632
1633
1634
1635
1636
1637







-
+









-
+




-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmAttributesCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    int attribute = 0;
    NSWindow *macWindow;

    if (winPtr->window == None) {
	Tk_MakeWindowExist((Tk_Window) winPtr);
	Tk_MakeWindowExist((Tk_Window)winPtr);
    }
    if (!TkMacOSXHostToplevelExists(winPtr)) {
	TkMacOSXMakeRealWindowExist(winPtr);
    }
    macWindow = TkMacOSXDrawableWindow(winPtr->window);
    macWindow = TkMacOSXGetNSWindowForDrawable(winPtr->window);

    if (objc == 3) {		/* wm attributes $win */
	Tcl_Obj *result = Tcl_NewObj();

	for (attribute = 0; attribute < _WMATT_LAST_ATTRIBUTE; ++attribute) {
	    Tcl_ListObjAppendElement(NULL, result,
		    Tcl_NewStringObj(WmAttributeNames[attribute], -1));
1571
1572
1573
1574
1575
1576
1577
1578

1579
1580
1581
1582
1583
1584

1585
1586
1587
1588
1589
1590
1591
1680
1681
1682
1683
1684
1685
1686

1687
1688
1689
1690
1691
1692

1693
1694
1695
1696
1697
1698
1699
1700







-
+





-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmClientCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    char *argv3;
    int length;

    if ((objc != 3) && (objc != 4)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?name?");
	return TCL_ERROR;
    }
1603
1604
1605
1606
1607
1608
1609
1610

1611
1612
1613
1614
1615
1616
1617
1712
1713
1714
1715
1716
1717
1718

1719
1720
1721
1722
1723
1724
1725
1726







-
+







	    wmPtr->clientMachine = NULL;
	}
	return TCL_OK;
    }
    if (wmPtr->clientMachine != NULL) {
	ckfree(wmPtr->clientMachine);
    }
    wmPtr->clientMachine = ckalloc(length + 1);
    wmPtr->clientMachine = (char *)ckalloc(length + 1);
    strcpy(wmPtr->clientMachine, argv3);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
1633
1634
1635
1636
1637
1638
1639
1640

1641
1642
1643
1644
1645
1646
1647
1648
1649
1650

1651
1652
1653
1654
1655
1656
1657
1658

1659
1660
1661
1662
1663
1664
1665
1666
1667

1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678

1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697

1698
1699
1700
1701
1702
1703
1704
1742
1743
1744
1745
1746
1747
1748

1749
1750
1751
1752
1753
1754
1755
1756
1757
1758

1759
1760
1761
1762
1763
1764
1765
1766

1767
1768
1769
1770
1771
1772
1773
1774
1775

1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786

1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805

1806
1807
1808
1809
1810
1811
1812
1813







-
+









-
+







-
+








-
+










-
+


















-
+







WmColormapwindowsCmd(
    Tk_Window tkwin,		/* 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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    TkWindow **cmapList, *winPtr2;
    int i, windowObjc, gotToplevel = 0;
    Tcl_Obj **windowObjv, *resultObj;

    if ((objc != 3) && (objc != 4)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?windowList?");
	return TCL_ERROR;
    }
    if (objc == 3) {
	Tk_MakeWindowExist((Tk_Window) winPtr);
	Tk_MakeWindowExist((Tk_Window)winPtr);
	resultObj = Tcl_NewObj();
	for (i = 0; i < wmPtr->cmapCount; i++) {
	    if ((i == (wmPtr->cmapCount-1))
		    && (wmPtr->flags & WM_ADDED_TOPLEVEL_COLORMAP)) {
		break;
	    }
	    Tcl_ListObjAppendElement(NULL, resultObj,
		    TkNewWindowObj((Tk_Window) wmPtr->cmapList[i]));
		    Tk_NewWindowObj((Tk_Window)wmPtr->cmapList[i]));
	}
	Tcl_SetObjResult(interp, resultObj);
	return TCL_OK;
    }
    if (Tcl_ListObjGetElements(interp, objv[3], &windowObjc, &windowObjv)
	    != TCL_OK) {
	return TCL_ERROR;
    }
    cmapList = ckalloc((windowObjc+1) * sizeof(TkWindow*));
    cmapList = (TkWindow **)ckalloc((windowObjc+1) * sizeof(TkWindow*));
    for (i = 0; i < windowObjc; i++) {
	if (TkGetWindowFromObj(interp, tkwin, windowObjv[i],
		(Tk_Window *) &winPtr2) != TCL_OK) {
	    ckfree(cmapList);
	    return TCL_ERROR;
	}
	if (winPtr2 == winPtr) {
	    gotToplevel = 1;
	}
	if (winPtr2->window == None) {
	    Tk_MakeWindowExist((Tk_Window) winPtr2);
	    Tk_MakeWindowExist((Tk_Window)winPtr2);
	}
	cmapList[i] = winPtr2;
    }
    if (!gotToplevel) {
	wmPtr->flags |= WM_ADDED_TOPLEVEL_COLORMAP;
	cmapList[windowObjc] = winPtr;
	windowObjc++;
    } else {
	wmPtr->flags &= ~WM_ADDED_TOPLEVEL_COLORMAP;
    }
    wmPtr->flags |= WM_COLORMAPS_EXPLICIT;
    if (wmPtr->cmapList != NULL) {
	ckfree(wmPtr->cmapList);
    }
    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;
}

/*
1716
1717
1718
1719
1720
1721
1722
1723

1724
1725
1726
1727
1728
1729

1730
1731
1732
1733
1734
1735
1736
1825
1826
1827
1828
1829
1830
1831

1832
1833
1834
1835
1836
1837

1838
1839
1840
1841
1842
1843
1844
1845







-
+





-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmCommandCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    int len;

    if ((objc != 3) && (objc != 4)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?value?");
	return TCL_ERROR;
    }
    if (objc == 3) {
1773
1774
1775
1776
1777
1778
1779
1780

1781
1782
1783
1784
1785
1786
1787


1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812

1813
1814
1815
1816
1817
1818
1819

1820
1821
1822
1823
1824
1825
1826

1827
1828

1829
1830

1831
1832

1833
1834
1835
1836
1837
1838
1839
1882
1883
1884
1885
1886
1887
1888

1889
1890
1891
1892
1893
1894


1895
1896
1897
1898
1899
1900
1901

1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919

1920
1921
1922
1923
1924
1925
1926

1927
1928
1929
1930
1931
1932
1933

1934
1935

1936
1937

1938
1939

1940
1941
1942
1943
1944
1945
1946
1947







-
+





-
-
+
+





-


















-
+






-
+






-
+

-
+

-
+

-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmDeiconifyCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    NSWindow *win = TkMacOSXDrawableWindow(winPtr->window);
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    NSWindow *win = TkMacOSXGetNSWindowForDrawable(winPtr->window);

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "window");
	return TCL_ERROR;
    }

    if (wmPtr->iconFor != NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"can't deiconify %s: it is an icon for %s",
		Tcl_GetString(objv[2]), Tk_PathName(wmPtr->iconFor)));
	Tcl_SetErrorCode(interp, "TK", "WM", "DEICONIFY", "ICON", NULL);
	return TCL_ERROR;
    } else if (winPtr->flags & TK_EMBEDDED) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"can't deiconify %s: it is an embedded window",
		winPtr->pathName));
	Tcl_SetErrorCode(interp, "TK", "WM", "DEICONIFY", "EMBEDDED", NULL);
	return TCL_ERROR;
    }

    TkpWmSetState(winPtr, TkMacOSXIsWindowZoomed(winPtr) ?
	    ZoomState : NormalState);
    [win setExcludedFromWindowsMenu:NO];
    TkMacOSXApplyWindowAttributes(winPtr, win);
    [win orderFront:nil];
    [win orderFront:NSApp];
    if (wmPtr->icon) {
	Tk_UnmapWindow((Tk_Window)wmPtr->icon);
    }

    /*
     * If this window has a transient, the transient must also be deiconified if
     * it was withdrawn by the master.
     * it was withdrawn by the container.
     */

    for (Transient *transientPtr = wmPtr->transientPtr;
	    transientPtr != NULL; transientPtr = transientPtr->nextPtr) {
	TkWindow *winPtr2 = transientPtr->winPtr;
	WmInfo *wmPtr2 = winPtr2->wmInfoPtr;
	TkWindow *masterPtr = (TkWindow *) TkGetTransientMaster(winPtr2);
	TkWindow *containerPtr = (TkWindow *)TkMacOSXGetContainer(winPtr2);

    	if (masterPtr == winPtr) {
    	if (containerPtr == winPtr) {
	    if ((wmPtr2->hints.initial_state == WithdrawnState) &&
		    ((transientPtr->flags & WITHDRAWN_BY_MASTER) != 0)) {
		    ((transientPtr->flags & WITHDRAWN_BY_CONTAINER) != 0)) {
		TkpWmSetState(winPtr2, NormalState);
		transientPtr->flags &= ~WITHDRAWN_BY_MASTER;
		transientPtr->flags &= ~WITHDRAWN_BY_CONTAINER;
	    }
	}
    }

    return TCL_OK;
}

1852
1853
1854
1855
1856
1857
1858
1859

1860
1861
1862
1863
1864
1865

1866
1867
1868
1869
1870
1871
1872
1960
1961
1962
1963
1964
1965
1966

1967
1968
1969
1970
1971
1972

1973
1974
1975
1976
1977
1978
1979
1980







-
+





-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmFocusmodelCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    static const char *const optionStrings[] = {
	"active", "passive", NULL };
    enum options {
	OPT_ACTIVE, OPT_PASSIVE };
    int index;

    if ((objc != 3) && (objc != 4)) {
1906
1907
1908
1909
1910
1911
1912
1913

1914
1915
1916
1917



1918
1919

1920
1921
1922
1923
1924
1925
1926
1927

1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938

1939
1940
1941
1942
1943
1944
1945
2014
2015
2016
2017
2018
2019
2020

2021
2022



2023
2024
2025
2026

2027
2028
2029
2030
2031
2032
2033
2034

2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045

2046
2047
2048
2049
2050
2051
2052
2053







-
+

-
-
-
+
+
+

-
+







-
+










-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmForgetCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    TCL_UNUSED(Tk_Window),	/* Main window of the application. */
    TkWindow *winPtr,		/* Toplevel or Frame to work with */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
    TCL_UNUSED(Tcl_Interp *),	/* Current interpreter. */
    TCL_UNUSED(int),			/* Number of arguments. */
    TCL_UNUSED(Tcl_Obj *const *))	/* Argument objects. */
{
    register Tk_Window frameWin = (Tk_Window) winPtr;
    Tk_Window frameWin = (Tk_Window)winPtr;

    if (Tk_IsTopLevel(frameWin)) {
	MacDrawable *macWin;

	Tk_MakeWindowExist(frameWin);
	Tk_MakeWindowExist((Tk_Window)winPtr->parentPtr);

	macWin = (MacDrawable *) winPtr->window;
	macWin = (MacDrawable *)winPtr->window;

    	TkFocusJoin(winPtr);
    	Tk_UnmapWindow(frameWin);

	macWin->toplevel->referenceCount--;
	macWin->toplevel = winPtr->parentPtr->privatePtr->toplevel;
	macWin->toplevel->referenceCount++;
	macWin->flags &= ~TK_HOST_EXISTS;

	TkWmDeadWindow(winPtr);
	RemapWindows(winPtr, (MacDrawable *) winPtr->parentPtr->window);
	RemapWindows(winPtr, (MacDrawable *)winPtr->parentPtr->window);

        /*
         * Make sure wm no longer manages this window
         */
        Tk_ManageGeometry(frameWin, NULL, NULL);

	winPtr->flags &= ~(TK_TOP_HIERARCHY|TK_TOP_LEVEL|TK_HAS_WRAPPER|TK_WIN_MANAGED);
1972
1973
1974
1975
1976
1977
1978
1979

1980
1981
1982
1983
1984
1985

1986
1987
1988
1989
1990
1991
1992
1993
1994
1995

1996
1997
1998
1999
2000
2001
2002
2080
2081
2082
2083
2084
2085
2086

2087
2088
2089
2090
2091
2092

2093
2094
2095
2096
2097
2098
2099
2100
2101
2102

2103
2104
2105
2106
2107
2108
2109
2110







-
+





-
+









-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmFrameCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    Window window;
    char buf[TCL_INTEGER_SPACE];

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "window");
	return TCL_ERROR;
    }
    window = wmPtr->reparent;
    if (window == None) {
	window = Tk_WindowId((Tk_Window) winPtr);
	window = Tk_WindowId((Tk_Window)winPtr);
    }
    sprintf(buf, "0x%" TCL_Z_MODIFIER "x", (size_t)window);
    Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, -1));
    return TCL_OK;
}

/*
2014
2015
2016
2017
2018
2019
2020
2021

2022
2023
2024
2025
2026
2027
2028


2029
2030
2031
2032
2033
2034
2035
2122
2123
2124
2125
2126
2127
2128

2129
2130
2131
2132
2133
2134


2135
2136
2137
2138
2139
2140
2141
2142
2143







-
+





-
-
+
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmGeometryCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    NSWindow *win = TkMacOSXDrawableWindow(winPtr->window);
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    NSWindow *win = TkMacOSXGetNSWindowForDrawable(winPtr->window);
    char xSign = '+', ySign = '+';
    int width, height, x = wmPtr->x, y= wmPtr->y;
    char *argv3;

    if ((objc != 3) && (objc != 4)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?newGeometry?");
	return TCL_ERROR;
2085
2086
2087
2088
2089
2090
2091
2092

2093
2094
2095
2096
2097
2098

2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114




2115
2116
2117
2118
2119
2120
2121
2193
2194
2195
2196
2197
2198
2199

2200
2201
2202
2203
2204
2205

2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218




2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229







-
+





-
+












-
-
-
-
+
+
+
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmGridCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    int reqWidth, reqHeight, widthInc, heightInc;
    const char *errorMsg;

    if ((objc != 3) && (objc != 7)) {
	Tcl_WrongNumArgs(interp, 2, objv,
		"window ?baseWidth baseHeight widthInc heightInc?");
	return TCL_ERROR;
    }
    if (objc == 3) {
	if (wmPtr->sizeHintsFlags & PBaseSize) {
	    Tcl_Obj *results[4];

	    results[0] = Tcl_NewIntObj(wmPtr->reqGridWidth);
	    results[1] = Tcl_NewIntObj(wmPtr->reqGridHeight);
	    results[2] = Tcl_NewIntObj(wmPtr->widthInc);
	    results[3] = Tcl_NewIntObj(wmPtr->heightInc);
	    results[0] = Tcl_NewWideIntObj(wmPtr->reqGridWidth);
	    results[1] = Tcl_NewWideIntObj(wmPtr->reqGridHeight);
	    results[2] = Tcl_NewWideIntObj(wmPtr->widthInc);
	    results[3] = Tcl_NewWideIntObj(wmPtr->heightInc);
	    Tcl_SetObjResult(interp, Tcl_NewListObj(4, results));
	}
	return TCL_OK;
    }
    if (*Tcl_GetString(objv[3]) == '\0') {
	/*
	 * Turn off gridding and reset the width and height to make sense as
2147
2148
2149
2150
2151
2152
2153
2154

2155
2156
2157
2158
2159
2160
2161
2255
2256
2257
2258
2259
2260
2261

2262
2263
2264
2265
2266
2267
2268
2269







-
+







	} else if (widthInc <= 0) {
	    errorMsg = "widthInc can't be <= 0";
	    goto error;
	} else if (heightInc <= 0) {
	    errorMsg = "heightInc can't be <= 0";
	    goto error;
	}
	Tk_SetGrid((Tk_Window) winPtr, reqWidth, reqHeight, widthInc,
	Tk_SetGrid((Tk_Window)winPtr, reqWidth, reqHeight, widthInc,
		heightInc);
    }
    wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
    WmUpdateGeom(wmPtr, winPtr);
    return TCL_OK;

  error:
2185
2186
2187
2188
2189
2190
2191
2192

2193
2194
2195
2196
2197
2198
2199
2293
2294
2295
2296
2297
2298
2299

2300
2301
2302
2303
2304
2305
2306
2307







-
+







WmGroupCmd(
    Tk_Window tkwin,		/* 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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    Tk_Window tkwin2;
    char *argv3;
    int length;

    if ((objc != 3) && (objc != 4)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?pathName?");
	return TCL_ERROR;
2218
2219
2220
2221
2222
2223
2224
2225

2226
2227
2228
2229
2230
2231
2232
2326
2327
2328
2329
2330
2331
2332

2333
2334
2335
2336
2337
2338
2339
2340







-
+







	}
	Tk_MakeWindowExist(tkwin2);
	if (wmPtr->leaderName != NULL) {
	    ckfree(wmPtr->leaderName);
	}
	wmPtr->hints.window_group = Tk_WindowId(tkwin2);
	wmPtr->hints.flags |= WindowGroupHint;
	wmPtr->leaderName = ckalloc(length + 1);
	wmPtr->leaderName = (char *)ckalloc(length + 1);
	strcpy(wmPtr->leaderName, argv3);
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
2243
2244
2245
2246
2247
2248
2249
2250

2251
2252
2253
2254
2255
2256

2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275

2276
2277
2278
2279
2280

2281
2282
2283
2284
2285
2286
2287
2288
2289
2290

2291
2292
2293
2294
2295
2296
2297
2351
2352
2353
2354
2355
2356
2357

2358
2359
2360
2361
2362
2363

2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382

2383
2384
2385
2386
2387

2388
2389
2390
2391
2392
2393
2394
2395
2396
2397

2398
2399
2400
2401
2402
2403
2404
2405







-
+





-
+


















-
+




-
+









-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmIconbitmapCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    Pixmap pixmap;
    char *str;
    int len;

    if ((objc != 3) && (objc != 4)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?bitmap?");
	return TCL_ERROR;
    }
    if (objc == 3) {
	if (wmPtr->hints.flags & IconPixmapHint) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    Tk_NameOfBitmap(winPtr->display,wmPtr->hints.icon_pixmap),
		    -1));
	}
	return TCL_OK;
    }
    str = Tcl_GetStringFromObj(objv[3], &len);
    if (winPtr->window == None) {
	Tk_MakeWindowExist((Tk_Window) winPtr);
	Tk_MakeWindowExist((Tk_Window)winPtr);
    }
    if (!TkMacOSXHostToplevelExists(winPtr)) {
	TkMacOSXMakeRealWindowExist(winPtr);
    }
    if (WmSetAttribute(winPtr, TkMacOSXDrawableWindow(winPtr->window), interp,
    if (WmSetAttribute(winPtr, TkMacOSXGetNSWindowForDrawable(winPtr->window), interp,
	    WMATT_TITLEPATH, objv[3]) == TCL_OK) {
	if (!len) {
	    if (wmPtr->hints.icon_pixmap != None) {
		Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_pixmap);
		wmPtr->hints.icon_pixmap = None;
	    }
	    wmPtr->hints.flags &= ~IconPixmapHint;
	}
    } else {
	pixmap = Tk_GetBitmap(interp, (Tk_Window) winPtr, Tk_GetUid(str));
	pixmap = Tk_GetBitmap(interp, (Tk_Window)winPtr, Tk_GetUid(str));
	if (pixmap == None) {
	    return TCL_ERROR;
	}
	wmPtr->hints.icon_pixmap = pixmap;
	wmPtr->hints.flags |= IconPixmapHint;
    }
    return TCL_OK;
2312
2313
2314
2315
2316
2317
2318
2319

2320
2321
2322
2323
2324
2325

2326
2327
2328
2329
2330
2331

2332
2333
2334
2335
2336
2337
2338

2339
2340
2341
2342
2343
2344
2345

2346
2347
2348
2349
2350
2351

2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364

2365
2366
2367
2368
2369
2370
2371


2372
2373
2374

2375
2376
2377
2378
2379
2380
2381
2420
2421
2422
2423
2424
2425
2426

2427
2428
2429
2430
2431
2432

2433
2434
2435
2436
2437
2438

2439
2440
2441
2442
2443
2444
2445

2446
2447
2448
2449
2450
2451
2452

2453
2454
2455
2456
2457
2458

2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471

2472
2473
2474
2475
2476
2477


2478
2479
2480
2481

2482
2483
2484
2485
2486
2487
2488
2489







-
+





-
+





-
+






-
+






-
+





-
+












-
+





-
-
+
+


-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmIconifyCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "window");
	return TCL_ERROR;
    }

    if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) {
    if (Tk_Attributes((Tk_Window)winPtr)->override_redirect) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"can't iconify \"%s\": override-redirect flag is set",
		winPtr->pathName));
	Tcl_SetErrorCode(interp, "TK", "WM", "ICONIFY", "OVERRIDE_REDIRECT",
		NULL);
	return TCL_ERROR;
    } else if (wmPtr->master != NULL) {
    } else if (wmPtr->container != NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"can't iconify \"%s\": it is a transient", winPtr->pathName));
	Tcl_SetErrorCode(interp, "TK", "WM", "ICONIFY", "TRANSIENT", NULL);
	return TCL_ERROR;
    } else if (wmPtr->iconFor != NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"can't iconify %s: it is an icon for %s",
		"can't iconify \"%s\": it is an icon for \"%s\"",
		winPtr->pathName, Tk_PathName(wmPtr->iconFor)));
	Tcl_SetErrorCode(interp, "TK", "WM", "ICONIFY", "ICON", NULL);
	return TCL_ERROR;
    } else if (winPtr->flags & TK_EMBEDDED) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"can't iconify %s: it is an embedded window",
		"can't iconify \"%s\": it is an embedded window",
		winPtr->pathName));
	Tcl_SetErrorCode(interp, "TK", "WM", "ICONIFY", "EMBEDDED", NULL);
	return TCL_ERROR;
    }

    TkpWmSetState(winPtr, IconicState);
    if (wmPtr->icon) {
	Tk_MapWindow((Tk_Window)wmPtr->icon);
    }

    /*
     * If this window has a transient the transient must be withdrawn when
     * the master is iconified.
     * the container is iconified.
     */

    for (Transient *transientPtr = wmPtr->transientPtr;
	    transientPtr != NULL; transientPtr = transientPtr->nextPtr) {
	TkWindow *winPtr2 = transientPtr->winPtr;
	TkWindow *masterPtr = (TkWindow *) TkGetTransientMaster(winPtr2);
    	if (masterPtr == winPtr &&
	TkWindow *containerPtr = (TkWindow *)TkMacOSXGetContainer(winPtr2);
    	if (containerPtr == winPtr &&
		winPtr2->wmInfoPtr->hints.initial_state != WithdrawnState) {
	    TkpWmSetState(winPtr2, WithdrawnState);
	    transientPtr->flags |= WITHDRAWN_BY_MASTER;
	    transientPtr->flags |= WITHDRAWN_BY_CONTAINER;
	}
    }

    return TCL_OK;
}

/*
2399
2400
2401
2402
2403
2404
2405
2406

2407
2408
2409
2410
2411
2412
2413
2507
2508
2509
2510
2511
2512
2513

2514
2515
2516
2517
2518
2519
2520
2521







-
+







WmIconmaskCmd(
    Tk_Window tkwin,		/* 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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    Pixmap pixmap;
    char *argv3;

    if ((objc != 3) && (objc != 4)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?bitmap?");
	return TCL_ERROR;
    }
2453
2454
2455
2456
2457
2458
2459
2460

2461
2462
2463
2464
2465
2466

2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485

2486
2487
2488
2489
2490
2491
2492
2561
2562
2563
2564
2565
2566
2567

2568
2569
2570
2571
2572
2573

2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592

2593
2594
2595
2596
2597
2598
2599
2600







-
+





-
+


















-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmIconnameCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    const char *argv3;
    int length;

    if (objc > 4) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?newName?");
	return TCL_ERROR;
    }
    if (objc == 3) {
	if (wmPtr->iconName != NULL) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(wmPtr->iconName, -1));
	}
	return TCL_OK;
    }

    if (wmPtr->iconName != NULL) {
	ckfree(wmPtr->iconName);
    }
    argv3 = Tcl_GetStringFromObj(objv[3], &length);
    wmPtr->iconName = ckalloc(length + 1);
    wmPtr->iconName = (char *)ckalloc(length + 1);
    strcpy(wmPtr->iconName, argv3);
    if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
	XSetIconName(winPtr->display, winPtr->window, wmPtr->iconName);
    }
    return TCL_OK;
}

2530
2531
2532
2533
2534
2535
2536
2537

2538
2539
2540
2541
2542
2543
2544
2638
2639
2640
2641
2642
2643
2644

2645
2646
2647
2648
2649
2650
2651
2652







-
+







     * Parse args.
     */

    if (strcmp(Tcl_GetString(objv[3]), "-default") == 0) {
	isDefault = 1;
	if (objc == 4) {
	    Tcl_WrongNumArgs(interp, 2, objv,
			     "window ?-default? image1 ?image2 ...?");
		    "window ?-default? image1 ?image2 ...?");
	    return TCL_ERROR;
	}
    }

    /*
     * Get icon name. We only use the first icon name because macOS does not
     * support multiple images in Tk photos.
2562
2563
2564
2565
2566
2567
2568
2569

2570
2571
2572
2573
2574
2575
2576
2670
2671
2672
2673
2674
2675
2676

2677
2678
2679
2680
2681
2682
2683
2684







-
+







	      icon));
	Tcl_SetErrorCode(interp, "TK", "WM", "ICONPHOTO", "PHOTO", NULL);
	return TCL_ERROR;
    }

    Tk_SizeOfImage(tk_icon, &width, &height);
    if (width != 0 && height != 0) {
	newIcon = TkMacOSXGetNSImageWithTkImage(winPtr->display, tk_icon,
	newIcon = TkMacOSXGetNSImageFromTkImage(winPtr->display, tk_icon,
						width, height);
    }
    Tk_FreeImage(tk_icon);
    if (newIcon == NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
	    "failed to create an iconphoto with image \"%s\"", icon));
	Tcl_SetErrorCode(interp, "TK", "WM", "ICONPHOTO", "IMAGE", NULL);
2595
2596
2597
2598
2599
2600
2601
2602

2603
2604
2605
2606
2607
2608

2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621


2622
2623
2624
2625
2626
2627
2628
2703
2704
2705
2706
2707
2708
2709

2710
2711
2712
2713
2714
2715

2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727


2728
2729
2730
2731
2732
2733
2734
2735
2736







-
+





-
+











-
-
+
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmIconpositionCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    int x, y;

    if ((objc != 3) && (objc != 5)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?x y?");
	return TCL_ERROR;
    }

    if (objc == 3) {
	if (wmPtr->hints.flags & IconPositionHint) {
	    Tcl_Obj *results[2];

	    results[0] = Tcl_NewIntObj(wmPtr->hints.icon_x);
	    results[1] = Tcl_NewIntObj(wmPtr->hints.icon_y);
	    results[0] = Tcl_NewWideIntObj(wmPtr->hints.icon_x);
	    results[1] = Tcl_NewWideIntObj(wmPtr->hints.icon_y);
	    Tcl_SetObjResult(interp, Tcl_NewListObj(2, results));
	}
	return TCL_OK;
    }

    if (*Tcl_GetString(objv[3]) == '\0') {
	wmPtr->hints.flags &= ~IconPositionHint;
2659
2660
2661
2662
2663
2664
2665
2666

2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677

2678
2679
2680
2681
2682
2683
2684
2685

2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702

2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713

2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728

2729
2730
2731
2732
2733
2734
2735
2767
2768
2769
2770
2771
2772
2773

2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784

2785
2786
2787
2788
2789
2790
2791
2792

2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809

2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820

2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835

2836
2837
2838
2839
2840
2841
2842
2843







-
+










-
+







-
+
















-
+










-
+














-
+







WmIconwindowCmd(
    Tk_Window tkwin,		/* 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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    Tk_Window tkwin2;
    WmInfo *wmPtr2;

    if ((objc != 3) && (objc != 4)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?pathName?");
	return TCL_ERROR;
    }

    if (objc == 3) {
	if (wmPtr->icon != NULL) {
	    Tcl_SetObjResult(interp, TkNewWindowObj(wmPtr->icon));
	    Tcl_SetObjResult(interp, Tk_NewWindowObj(wmPtr->icon));
	}
	return TCL_OK;
    }

    if (*Tcl_GetString(objv[3]) == '\0') {
	wmPtr->hints.flags &= ~IconWindowHint;
	if (wmPtr->icon != NULL) {
	    wmPtr2 = ((TkWindow *) wmPtr->icon)->wmInfoPtr;
	    wmPtr2 = ((TkWindow *)wmPtr->icon)->wmInfoPtr;
	    wmPtr2->iconFor = NULL;
	    wmPtr2->hints.initial_state = WithdrawnState;
	}
	wmPtr->icon = NULL;
    } else {
	if (TkGetWindowFromObj(interp, tkwin, objv[3], &tkwin2) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (!Tk_IsTopLevel(tkwin2)) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "can't use %s as icon window: not at top level",
		    Tk_PathName(tkwin2)));
	    Tcl_SetErrorCode(interp, "TK", "WM", "ICONWINDOW", "TOPLEVEL",
		    NULL);
	    return TCL_ERROR;
	}
	wmPtr2 = ((TkWindow *) tkwin2)->wmInfoPtr;
	wmPtr2 = ((TkWindow *)tkwin2)->wmInfoPtr;
	if (wmPtr2->iconFor != NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "%s is already an icon for %s",
		    Tcl_GetString(objv[3]), Tk_PathName(wmPtr2->iconFor)));
	    Tcl_SetErrorCode(interp, "TK", "WM", "ICONWINDOW", "ICON", NULL);
	    return TCL_ERROR;
	}
	if (wmPtr->icon != NULL) {
	    TkWindow *oldIcon = (TkWindow *)wmPtr->icon;
	    WmInfo *wmPtr3 = oldIcon->wmInfoPtr;
	    NSWindow *win = TkMacOSXDrawableWindow(oldIcon->window);
	    NSWindow *win = TkMacOSXGetNSWindowForDrawable(oldIcon->window);

	    /*
	     * The old icon should be withdrawn.
	     */

	    TkpWmSetState(oldIcon, WithdrawnState);
	    [win orderOut:nil];
    	    [win setExcludedFromWindowsMenu:YES];
	    wmPtr3->iconFor = NULL;
	}
	Tk_MakeWindowExist(tkwin2);
	wmPtr->hints.icon_window = Tk_WindowId(tkwin2);
	wmPtr->hints.flags |= IconWindowHint;
	wmPtr->icon = tkwin2;
	wmPtr2->iconFor = (Tk_Window) winPtr;
	wmPtr2->iconFor = (Tk_Window)winPtr;
	if (!(wmPtr2->flags & WM_NEVER_MAPPED)) {
	    /*
	     * If the window is in normal or zoomed state, the icon should be
	     * unmapped.
	     */

	    if (wmPtr->hints.initial_state == NormalState ||
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767





2768
2769
2770


2771
2772
2773

2774
2775
2776
2777
2778
2779
2780
2781
2782












2783
2784
2785
2786
2787
2788
2789


2790
2791
2792
2793
2794
2795
2796
2864
2865
2866
2867
2868
2869
2870





2871
2872
2873
2874
2875
2876


2877
2878
2879
2880

2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907


2908
2909
2910
2911
2912
2913
2914
2915
2916







-
-
-
-
-
+
+
+
+
+

-
-
+
+


-
+









+
+
+
+
+
+
+
+
+
+
+
+





-
-
+
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmManageCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    TkWindow *winPtr,           /* Toplevel or Frame to work with */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
    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. */
{
    register Tk_Window frameWin = (Tk_Window) winPtr;
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    Tk_Window frameWin = (Tk_Window)winPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;

    if (!Tk_IsTopLevel(frameWin)) {
	MacDrawable *macWin = (MacDrawable *) winPtr->window;
	MacDrawable *macWin = (MacDrawable *)winPtr->window;

	if (!Tk_IsManageable(frameWin)) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "window \"%s\" is not manageable: must be a"
		    " 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) {
		Tk_MakeWindowExist((Tk_Window) winPtr);
		macWin = (MacDrawable *) winPtr->window;
		Tk_MakeWindowExist((Tk_Window)winPtr);
		macWin = (MacDrawable *)winPtr->window;
	    }
	}
	wmPtr = winPtr->wmInfoPtr;
	winPtr->flags &= ~TK_MAPPED;
	macWin->toplevel->referenceCount--;
	macWin->toplevel = macWin;
	macWin->toplevel->referenceCount++;
2820
2821
2822
2823
2824
2825
2826
2827

2828
2829
2830
2831
2832
2833

2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846


2847
2848
2849
2850
2851
2852
2853
2940
2941
2942
2943
2944
2945
2946

2947
2948
2949
2950
2951
2952

2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964


2965
2966
2967
2968
2969
2970
2971
2972
2973







-
+





-
+











-
-
+
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmMaxsizeCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    int width, height;

    if ((objc != 3) && (objc != 5)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?width height?");
	return TCL_ERROR;
    }

    if (objc == 3) {
	Tcl_Obj *results[2];

	GetMaxSize(winPtr, &width, &height);
	results[0] = Tcl_NewIntObj(width);
	results[1] = Tcl_NewIntObj(height);
	results[0] = Tcl_NewWideIntObj(width);
	results[1] = Tcl_NewWideIntObj(height);
	Tcl_SetObjResult(interp, Tcl_NewListObj(2, results));
	return TCL_OK;
    }

    if ((Tcl_GetIntFromObj(interp, objv[3], &width) != TCL_OK)
	    || (Tcl_GetIntFromObj(interp, objv[4], &height) != TCL_OK)) {
	return TCL_ERROR;
2874
2875
2876
2877
2878
2879
2880
2881

2882
2883
2884
2885
2886
2887

2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900


2901
2902
2903
2904
2905
2906
2907
2994
2995
2996
2997
2998
2999
3000

3001
3002
3003
3004
3005
3006

3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018


3019
3020
3021
3022
3023
3024
3025
3026
3027







-
+





-
+











-
-
+
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmMinsizeCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    int width, height;

    if ((objc != 3) && (objc != 5)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?width height?");
	return TCL_ERROR;
    }

    if (objc == 3) {
	Tcl_Obj *results[2];

	GetMinSize(winPtr, &width, &height);
	results[0] = Tcl_NewIntObj(width);
	results[1] = Tcl_NewIntObj(height);
	results[0] = Tcl_NewWideIntObj(width);
	results[1] = Tcl_NewWideIntObj(height);
	Tcl_SetObjResult(interp, Tcl_NewListObj(2, results));
	return TCL_OK;
    }

    if ((Tcl_GetIntFromObj(interp, objv[3], &width) != TCL_OK)
	    || (Tcl_GetIntFromObj(interp, objv[4], &height) != TCL_OK)) {
	return TCL_ERROR;
2928
2929
2930
2931
2932
2933
2934
2935

2936
2937
2938
2939
2940
2941
2942
2943

2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961


2962
2963
2964
2965
2966
2967
2968
3048
3049
3050
3051
3052
3053
3054

3055
3056
3057
3058
3059
3060
3061
3062

3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079


3080
3081
3082
3083
3084
3085
3086
3087
3088







-
+







-
+
















-
-
+
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmOverrideredirectCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    int flag;
    XSetWindowAttributes atts;
    TKWindow *win = (TKWindow *)TkMacOSXDrawableWindow(winPtr->window);
    TKWindow *win = (TKWindow *)TkMacOSXGetNSWindowForDrawable(winPtr->window);

    if ((objc != 3) && (objc != 4)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?boolean?");
	return TCL_ERROR;
    }

    if (objc == 3) {
	Tcl_SetObjResult(interp, Tcl_NewBooleanObj(
		Tk_Attributes((Tk_Window) winPtr)->override_redirect));
	return TCL_OK;
    }

    if (Tcl_GetBooleanFromObj(interp, objv[3], &flag) != TCL_OK) {
	return TCL_ERROR;
    }
    atts.override_redirect = flag ? True : False;
    Tk_ChangeWindowAttributes((Tk_Window) winPtr, CWOverrideRedirect, &atts);
    ApplyMasterOverrideChanges(winPtr, win);
    Tk_ChangeWindowAttributes((Tk_Window)winPtr, CWOverrideRedirect, &atts);
    ApplyContainerOverrideChanges(winPtr, win);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * WmPositionfromCmd --
2977
2978
2979
2980
2981
2982
2983
2984

2985
2986
2987
2988
2989
2990

2991
2992
2993
2994
2995
2996
2997
3097
3098
3099
3100
3101
3102
3103

3104
3105
3106
3107
3108
3109

3110
3111
3112
3113
3114
3115
3116
3117







-
+





-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmPositionfromCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    static const char *const optionStrings[] = {
	"program", "user", NULL };
    enum options {
	OPT_PROGRAM, OPT_USER };
    int index;

    if ((objc != 3) && (objc != 4)) {
3043
3044
3045
3046
3047
3048
3049
3050

3051
3052
3053
3054
3055
3056
3057


3058
3059
3060
3061
3062
3063
3064
3163
3164
3165
3166
3167
3168
3169

3170
3171
3172
3173
3174
3175


3176
3177
3178
3179
3180
3181
3182
3183
3184







-
+





-
-
+
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmProtocolCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    register ProtocolHandler *protPtr, *prevPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    ProtocolHandler *protPtr, *prevPtr;
    Atom protocol;
    char *cmd;
    int cmdLength;
    Tcl_Obj *resultObj;

    if ((objc < 3) || (objc > 5)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?name? ?command?");
3076
3077
3078
3079
3080
3081
3082
3083

3084
3085
3086
3087
3088
3089
3090
3196
3197
3198
3199
3200
3201
3202

3203
3204
3205
3206
3207
3208
3209
3210







-
+







	    Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewStringObj(
		    Tk_GetAtomName((Tk_Window)winPtr, protPtr->protocol),-1));
	}
	Tcl_SetObjResult(interp, resultObj);
	return TCL_OK;
    }

    protocol = Tk_InternAtom((Tk_Window) winPtr, Tcl_GetString(objv[3]));
    protocol = Tk_InternAtom((Tk_Window)winPtr, Tcl_GetString(objv[3]));
    if (objc == 4) {
	/*
	 * Return the command to handle a given protocol.
	 */

	for (protPtr = wmPtr->protPtr; protPtr != NULL;
		protPtr = protPtr->nextPtr) {
3114
3115
3116
3117
3118
3119
3120
3121

3122
3123
3124
3125
3126

3127
3128
3129
3130
3131
3132
3133
3234
3235
3236
3237
3238
3239
3240

3241
3242
3243
3244
3245

3246
3247
3248
3249
3250
3251
3252
3253







-
+




-
+







		ckfree(protPtr->command);
	    Tcl_EventuallyFree(protPtr, TCL_DYNAMIC);
	    break;
	}
    }
    cmd = Tcl_GetStringFromObj(objv[4], &cmdLength);
    if (cmdLength > 0) {
	protPtr = ckalloc(sizeof(ProtocolHandler));
	protPtr = (ProtocolHandler *)ckalloc(sizeof(ProtocolHandler));
	protPtr->protocol = protocol;
	protPtr->nextPtr = wmPtr->protPtr;
	wmPtr->protPtr = protPtr;
	protPtr->interp = interp;
	protPtr->command = ckalloc(cmdLength+1);
	protPtr->command = (char *)ckalloc(cmdLength+1);
	strcpy(protPtr->command, cmd);
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
3144
3145
3146
3147
3148
3149
3150
3151

3152
3153
3154
3155
3156
3157

3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169

3170
3171



3172
3173
3174
3175
3176
3177
3178
3264
3265
3266
3267
3268
3269
3270

3271
3272
3273
3274
3275
3276

3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290


3291
3292
3293
3294
3295
3296
3297
3298
3299
3300







-
+





-
+












+
-
-
+
+
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmResizableCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    int width, height;
    UInt64 oldAttributes = wmPtr->attributes;
    int oldFlags = wmPtr->flags;

    if ((objc != 3) && (objc != 5)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?width height?");
	return TCL_ERROR;
    }

    if (objc == 3) {
	Tcl_Obj *results[2];

	results[0] = Tcl_NewWideIntObj(
	results[0] = Tcl_NewBooleanObj(!(wmPtr->flags & WM_WIDTH_NOT_RESIZABLE));
	results[1] = Tcl_NewBooleanObj(!(wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE));
		(wmPtr->flags & WM_WIDTH_NOT_RESIZABLE) == 0);
	results[1] = Tcl_NewWideIntObj(
		(wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE) == 0);
	Tcl_SetObjResult(interp, Tcl_NewListObj(2, results));
	return TCL_OK;
    }

    if ((Tcl_GetBooleanFromObj(interp, objv[3], &width) != TCL_OK)
	    || (Tcl_GetBooleanFromObj(interp, objv[4], &height) != TCL_OK)) {
	return TCL_ERROR;
3221
3222
3223
3224
3225
3226
3227
3228

3229
3230
3231
3232
3233
3234

3235
3236
3237
3238
3239
3240
3241
3343
3344
3345
3346
3347
3348
3349

3350
3351
3352
3353
3354
3355

3356
3357
3358
3359
3360
3361
3362
3363







-
+





-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmSizefromCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    static const char *const optionStrings[] = {
	"program", "user", NULL };
    enum options {
	OPT_PROGRAM, OPT_USER };
    int index;

    if ((objc != 3) && (objc != 4)) {
3314
3315
3316
3317
3318
3319
3320
3321

3322
3323
3324
3325
3326
3327
3328
3436
3437
3438
3439
3440
3441
3442

3443
3444
3445
3446
3447
3448
3449
3450







-
+








    if (objc == 3) {
	windows = TkWmStackorderToplevel(winPtr);
	if (windows != NULL) {
	    resultObj = Tcl_NewObj();
	    for (windowPtr = windows; *windowPtr ; windowPtr++) {
		Tcl_ListObjAppendElement(NULL, resultObj,
		    TkNewWindowObj((Tk_Window) *windowPtr));
			Tk_NewWindowObj((Tk_Window)*windowPtr));
	    }
	    Tcl_SetObjResult(interp, resultObj);
	    ckfree(windows);
	    return TCL_OK;
	} else {
	    return TCL_ERROR;
	}
3389
3390
3391
3392
3393
3394
3395
3396

3397
3398
3399
3400
3401
3402
3403
3511
3512
3513
3514
3515
3516
3517

3518
3519
3520
3521
3522
3523
3524
3525







-
+







	    return TCL_ERROR;
	}
	if (index == OPT_ISABOVE) {
	    result = index1 > index2;
	} else { /* OPT_ISBELOW */
	    result = index1 < index2;
	}
	Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result));
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(result != 0));
	return TCL_OK;
    }
}

/*
 *----------------------------------------------------------------------
 *
3413
3414
3415
3416
3417
3418
3419
3420

3421
3422
3423
3424
3425
3426

3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441

3442
3443
3444
3445
3446
3447
3448

3449
3450
3451
3452
3453
3454
3455
3535
3536
3537
3538
3539
3540
3541

3542
3543
3544
3545
3546
3547

3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562

3563
3564
3565
3566
3567
3568
3569

3570
3571
3572
3573
3574
3575
3576
3577







-
+





-
+














-
+






-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmStateCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    static const char *const optionStrings[] = {
	"normal", "iconic", "withdrawn", "zoomed", NULL };
    enum options {
	OPT_NORMAL, OPT_ICONIC, OPT_WITHDRAWN, OPT_ZOOMED };
    int index;

    if ((objc < 3) || (objc > 4)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?state?");
	return TCL_ERROR;
    }

    if (objc == 4) {
	if (wmPtr->iconFor != NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "can't change state of %s: it is an icon for %s",
		    "can't change state of \"%s\": it is an icon for \"%s\"",
		    Tcl_GetString(objv[2]), Tk_PathName(wmPtr->iconFor)));
	    Tcl_SetErrorCode(interp, "TK", "WM", "STATE", "ICON", NULL);
	    return TCL_ERROR;
	}
	if (winPtr->flags & TK_EMBEDDED) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "can't change state of %s: it is an embedded window",
		    "can't change state of \"%s\": it is an embedded window",
		    winPtr->pathName));
	    Tcl_SetErrorCode(interp, "TK", "WM", "STATE", "EMBEDDED", NULL);
	    return TCL_ERROR;
	}

	if (Tcl_GetIndexFromObjStruct(interp, objv[3], optionStrings,
		sizeof(char *), "argument", 0, &index) != TCL_OK) {
3463
3464
3465
3466
3467
3468
3469
3470

3471
3472
3473
3474
3475
3476
3477
3478

3479
3480
3481
3482
3483
3484
3485
3585
3586
3587
3588
3589
3590
3591

3592
3593
3594
3595
3596
3597
3598
3599

3600
3601
3602
3603
3604
3605
3606
3607







-
+







-
+







	    /*
	     * This varies from 'wm deiconify' because it does not force the
	     * window to be raised and receive focus
	     */

	    break;
	case OPT_ICONIC:
	    if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) {
	    if (Tk_Attributes((Tk_Window)winPtr)->override_redirect) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"can't iconify \"%s\": override-redirect flag is set",
			winPtr->pathName));
		Tcl_SetErrorCode(interp, "TK", "WM", "STATE",
			"OVERRIDE_REDIRECT", NULL);
		return TCL_ERROR;
	    }
	    if (wmPtr->master != NULL) {
	    if (wmPtr->container != NULL) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"can't iconify \"%s\": it is a transient",
			winPtr->pathName));
		Tcl_SetErrorCode(interp, "TK", "WM", "STATE", "TRANSIENT",
			NULL);
		return TCL_ERROR;
	    }
3533
3534
3535
3536
3537
3538
3539
3540

3541
3542
3543
3544
3545
3546

3547
3548
3549
3550
3551
3552
3553
3655
3656
3657
3658
3659
3660
3661

3662
3663
3664
3665
3666
3667

3668
3669
3670
3671
3672
3673
3674
3675







-
+





-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmTitleCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    char *argv3;
    int length;

    if (objc > 4) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?newTitle?");
	return TCL_ERROR;
    }
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596



3597
3598
3599
3600
3601

3602
3603
3604
3605

3606
3607

3608
3609
3610
3611
3612
3613
3614

3615
3616
3617
3618


3619
3620

3621
3622
3623

3624
3625

3626
3627
3628
3629
3630
3631
3632
3633
3634
3635

3636
3637
3638
3639
3640
3641
3642
3643

3644
3645
3646
3647
3648
3649
3650


3651
3652
3653
3654


3655
3656
3657
3658
3659
3660
3661

3662
3663
3664
3665
3666
3667
3668

3669
3670
3671
3672
3673
3674
3675
3676

3677
3678
3679
3680
3681
3682
3683

3684
3685
3686

3687
3688

3689
3690
3691
3692
3693
3694
3695
3696
3697
3698


3699
3700
3701
3702
3703
3704
3705


3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716

3717
3718
3719

3720
3721
3722
3723


3724
3725
3726
3727

3728
3729
3730
3731
3732
3733
3734
3709
3710
3711
3712
3713
3714
3715



3716
3717
3718
3719
3720
3721
3722

3723
3724
3725
3726

3727
3728

3729
3730
3731
3732
3733
3734
3735

3736
3737
3738


3739
3740
3741

3742
3743
3744

3745
3746

3747
3748
3749
3750
3751
3752
3753
3754
3755
3756

3757
3758
3759
3760
3761
3762
3763
3764

3765
3766
3767
3768
3769
3770


3771
3772
3773
3774


3775
3776
3777
3778
3779
3780
3781
3782

3783
3784
3785
3786
3787
3788
3789

3790
3791
3792
3793
3794
3795
3796
3797

3798
3799
3800
3801
3802
3803
3804

3805
3806
3807

3808
3809

3810
3811
3812
3813
3814
3815
3816
3817
3818


3819
3820
3821
3822
3823
3824
3825


3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837

3838
3839
3840

3841
3842
3843


3844
3845
3846
3847
3848

3849
3850
3851
3852
3853
3854
3855
3856







-
-
-
+
+
+




-
+



-
+

-
+






-
+


-
-
+
+

-
+


-
+

-
+









-
+







-
+





-
-
+
+


-
-
+
+






-
+






-
+







-
+






-
+


-
+

-
+








-
-
+
+





-
-
+
+










-
+


-
+


-
-
+
+



-
+







WmTransientCmd(
    Tk_Window tkwin,		/* 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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    Tk_Window master;
    TkWindow *masterPtr, *w;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    Tk_Window container;
    TkWindow *containerPtr, *w;
    WmInfo *wmPtr2;
    Transient *transient;

    if ((objc != 3) && (objc != 4)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?master?");
	Tcl_WrongNumArgs(interp, 2, objv, "window ?window?");
	return TCL_ERROR;
    }
    if (objc == 3) {
	if (wmPtr->master != NULL) {
	if (wmPtr->container != NULL) {
	    Tcl_SetObjResult(interp,
		Tcl_NewStringObj(Tk_PathName(wmPtr->master), -1));
		Tcl_NewStringObj(Tk_PathName(wmPtr->container), -1));
	}
	return TCL_OK;
    }
    if (*Tcl_GetString(objv[3]) == '\0') {
	RemoveTransient(winPtr);
    } else {
	if (TkGetWindowFromObj(interp, tkwin, objv[3], &master) != TCL_OK) {
	if (TkGetWindowFromObj(interp, tkwin, objv[3], &container) != TCL_OK) {
	    return TCL_ERROR;
	}
	masterPtr = (TkWindow*) master;
	while (!Tk_TopWinHierarchy(masterPtr)) {
	containerPtr = (TkWindow*) container;
	while (!Tk_TopWinHierarchy(containerPtr)) {
            /*
             * Ensure that the master window is actually a Tk toplevel.
             * Ensure that the container window is actually a Tk toplevel.
             */

            masterPtr = masterPtr->parentPtr;
            containerPtr = containerPtr->parentPtr;
        }
	Tk_MakeWindowExist((Tk_Window)masterPtr);
	Tk_MakeWindowExist((Tk_Window)containerPtr);

	if (wmPtr->iconFor != NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "can't make \"%s\" a transient: it is an icon for %s",
		    Tcl_GetString(objv[2]), Tk_PathName(wmPtr->iconFor)));
	    Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "ICON", NULL);
	    return TCL_ERROR;
	}

	wmPtr2 = masterPtr->wmInfoPtr;
	wmPtr2 = containerPtr->wmInfoPtr;

	/*
	 * Under some circumstances, wmPtr2 is NULL here.
	 */

	if (wmPtr2 != NULL && wmPtr2->iconFor != NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "can't make \"%s\" a master: it is an icon for %s",
		    "can't make \"%s\" a container: it is an icon for %s",
		    Tcl_GetString(objv[3]), Tk_PathName(wmPtr2->iconFor)));
	    Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "ICON", NULL);
	    return TCL_ERROR;
	}

	for (w = masterPtr; w != NULL && w->wmInfoPtr != NULL;
		w = (TkWindow *)w->wmInfoPtr->master) {
	for (w = containerPtr; w != NULL && w->wmInfoPtr != NULL;
		w = (TkWindow *)w->wmInfoPtr->container) {
	    if (w == winPtr) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "setting \"%s\" as master creates a transient/master cycle",
		    Tk_PathName(masterPtr)));
		    "can't set \"%s\" as container: would cause management loop",
		    Tk_PathName(containerPtr)));
		Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "SELF", NULL);
		return TCL_ERROR;
	    }
	}

	/*
	 * Add the transient to the master's list, if it not already there.
	 * Add the transient to the container's list, if it not already there.
	 */

	for (transient = wmPtr2->transientPtr;
	     transient != NULL && transient->winPtr != winPtr;
	     transient = transient->nextPtr) {}
	if (transient == NULL) {
	    transient = ckalloc(sizeof(Transient));
	    transient = (Transient *)ckalloc(sizeof(Transient));
	    transient->winPtr = winPtr;
	    transient->flags = 0;
	    transient->nextPtr = wmPtr2->transientPtr;
	    wmPtr2->transientPtr = transient;
	}

	/*
	 * If the master is withdrawn or iconic then withdraw the transient.
	 * If the container is withdrawn or iconic then withdraw the transient.
	 */

	if ((wmPtr2->hints.initial_state == WithdrawnState ||
		wmPtr2->hints.initial_state == IconicState) &&
		wmPtr->hints.initial_state != WithdrawnState) {
	    TkpWmSetState(winPtr, WithdrawnState);
	    transient->flags |= WITHDRAWN_BY_MASTER;
	    transient->flags |= WITHDRAWN_BY_CONTAINER;
	}

	wmPtr->master = (Tk_Window) masterPtr;
	wmPtr->container = (Tk_Window)containerPtr;
    }
    ApplyMasterOverrideChanges(winPtr, NULL);
    ApplyContainerOverrideChanges(winPtr, NULL);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * RemoveTransient --
 *
 *      Clears the transient's master record and removes the transient from the
 *      master's list.
 *      Clears the transient's container record and removes the transient from the
 *      container's list.
 *
 * Results:
 *	None
 *
 * Side effects:
 *      References to a master are removed from the transient's wmInfo
 *	structure and references to the transient are removed from its master's
 *      References to a container are removed from the transient's wmInfo
 *	structure and references to the transient are removed from its container's
 *	wmInfo.
 *
 *----------------------------------------------------------------------
 */

static void
RemoveTransient(
    TkWindow *winPtr)
{
    WmInfo *wmPtr = winPtr->wmInfoPtr, *wmPtr2;
    TkWindow *masterPtr;
    TkWindow *containerPtr;
    Transient *transPtr, *temp;

    if (wmPtr == NULL || wmPtr->master == NULL) {
    if (wmPtr == NULL || wmPtr->container == NULL) {
	return;
    }
    masterPtr = (TkWindow*)wmPtr->master;
    wmPtr2 = masterPtr->wmInfoPtr;
    containerPtr = (TkWindow *)wmPtr->container;
    wmPtr2 = containerPtr->wmInfoPtr;
    if (wmPtr2 == NULL) {
	return;
    }
    wmPtr->master = NULL;
    wmPtr->container= NULL;
    transPtr = wmPtr2->transientPtr;
    while (transPtr != NULL) {
	if (transPtr->winPtr != winPtr) {
	    break;
	}
	temp = transPtr->nextPtr;
	ckfree(transPtr);
3761
3762
3763
3764
3765
3766
3767
3768

3769
3770
3771
3772
3773
3774

3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802

3803
3804

3805
3806
3807

3808
3809
3810
3811
3812
3813
3814
3883
3884
3885
3886
3887
3888
3889

3890
3891
3892
3893
3894
3895

3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912




3913
3914
3915
3916
3917
3918
3919

3920
3921

3922
3923
3924

3925
3926
3927
3928
3929
3930
3931
3932







-
+





-
+
















-
-
-
-







-
+

-
+


-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmWithdrawCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "window");
	return TCL_ERROR;
    }

    if (wmPtr->iconFor != NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"can't withdraw %s: it is an icon for %s",
		Tcl_GetString(objv[2]), Tk_PathName(wmPtr->iconFor)));
	Tcl_SetErrorCode(interp, "TK", "WM", "WITHDRAW", "ICON", NULL);
	return TCL_ERROR;
    }

    TkpWmSetState(winPtr, WithdrawnState);

    NSWindow *win = TkMacOSXDrawableWindow(winPtr->window);
    [win orderOut:nil];
    [win setExcludedFromWindowsMenu:YES];

    /*
     * If this window has a transient, the transient must also be withdrawn.
     */

    for (Transient *transientPtr = wmPtr->transientPtr;
	    transientPtr != NULL; transientPtr = transientPtr->nextPtr) {
	TkWindow *winPtr2 = transientPtr->winPtr;
	TkWindow *masterPtr = (TkWindow *) TkGetTransientMaster(winPtr2);
	TkWindow *containerPtr = (TkWindow *)TkMacOSXGetContainer(winPtr2);

    	if (masterPtr == winPtr &&
    	if (containerPtr == winPtr &&
		winPtr2->wmInfoPtr->hints.initial_state != WithdrawnState) {
	    TkpWmSetState(winPtr2, WithdrawnState);
	    transientPtr->flags |= WITHDRAWN_BY_MASTER;
	    transientPtr->flags |= WITHDRAWN_BY_CONTAINER;
	}
    }

    return TCL_OK;
}

/*
3857
3858
3859
3860
3861
3862
3863
3864

3865
3866
3867
3868
3869
3870
3871
3975
3976
3977
3978
3979
3980
3981

3982
3983
3984
3985
3986
3987
3988
3989







-
+







    int reqWidth,		/* Width (in grid units) corresponding to the
				 * requested geometry for tkwin. */
    int reqHeight,		/* Height (in grid units) corresponding to the
				 * requested geometry for tkwin. */
    int widthInc, int heightInc)/* Pixel increments corresponding to a change
				 * of one grid unit. */
{
    TkWindow *winPtr = (TkWindow *) tkwin;
    TkWindow *winPtr = (TkWindow *)tkwin;
    WmInfo *wmPtr;

    /*
     * Ensure widthInc and heightInc are greater than 0
     */

    if (widthInc <= 0) {
3951
3952
3953
3954
3955
3956
3957
3958

3959
3960
3961
3962
3963
3964
3965
4069
4070
4071
4072
4073
4074
4075

4076
4077
4078
4079
4080
4081
4082
4083







-
+







 */

void
Tk_UnsetGrid(
    Tk_Window tkwin)		/* Token for window that is currently
				 * controlling gridding. */
{
    TkWindow *winPtr = (TkWindow *) tkwin;
    TkWindow *winPtr = (TkWindow *)tkwin;
    WmInfo *wmPtr;

    /*
     * Find the top-level window for tkwin, plus the window manager
     * information.
     */

4024
4025
4026
4027
4028
4029
4030
4031

4032
4033
4034
4035
4036
4037
4038

4039
4040
4041
4042
4043
4044
4045
4142
4143
4144
4145
4146
4147
4148

4149
4150
4151
4152
4153
4154
4155

4156
4157
4158
4159
4160
4161
4162
4163







-
+






-
+







	     * Tk_DestroyWindow will try to destroy the window, but of course
	     * it's already gone.
	     */

	    Tk_ErrorHandler handler = Tk_CreateErrorHandler(winPtr->display,
		    -1, -1, -1, NULL, NULL);

	    Tk_DestroyWindow((Tk_Window) winPtr);
	    Tk_DestroyWindow((Tk_Window)winPtr);
	    Tk_DeleteErrorHandler(handler);
	}
	if (wmTracing) {
	    TkMacOSXDbgMsg("TopLevelEventProc: %s deleted", winPtr->pathName);
	}
    } else if (eventPtr->type == ReparentNotify) {
	Tcl_Panic("recieved unwanted reparent event");
	Tcl_Panic("received unwanted reparent event");
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TopLevelReqProc --
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063

4064
4065
4066

4067
4068
4069
4070
4071
4072
4073
4171
4172
4173
4174
4175
4176
4177

4178
4179

4180
4181
4182

4183
4184
4185
4186
4187
4188
4189
4190







-


-
+


-
+







 * Side effects:
 *	Arrange for the window to be resized to satisfy the request (this
 *	happens as a when-idle action).
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static void
TopLevelReqProc(
    ClientData dummy,		/* Not used. */
    TCL_UNUSED(void *),		/* Not used. */
    Tk_Window tkwin)		/* Information about window. */
{
    TkWindow *winPtr = (TkWindow *) tkwin;
    TkWindow *winPtr = (TkWindow *)tkwin;
    WmInfo *wmPtr;

    wmPtr = winPtr->wmInfoPtr;
    wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
    if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {
	Tcl_DoWhenIdle(UpdateGeometryInfo, winPtr);
	wmPtr->flags |= WM_UPDATE_PENDING;
4239
4240
4241
4242
4243
4244
4245
4246

4247
4248
4249
4250
4251
4252
4253
4356
4357
4358
4359
4360
4361
4362

4363
4364
4365
4366
4367
4368
4369
4370







-
+







	     * geometry, except to make sure that the desired size is known by
	     * the container. Also, zero out any position information, since
	     * embedded windows are not allowed to move.
	     */

	    wmPtr->x = wmPtr->y = 0;
	    wmPtr->flags &= ~(WM_NEGATIVE_X|WM_NEGATIVE_Y);
	    Tk_GeometryRequest((Tk_Window) contWinPtr, width, height);
	    Tk_GeometryRequest((Tk_Window)contWinPtr, width, height);
	}
	return;
    }
    if (wmPtr->flags & WM_MOVE_PENDING) {
	wmPtr->configWidth = width;
	wmPtr->configHeight = height;
	if (wmTracing) {
4492
4493
4494
4495
4496
4497
4498
4499

4500
4501
4502
4503
4504
4505
4506
4609
4610
4611
4612
4613
4614
4615

4616
4617
4618
4619
4620
4621
4622
4623







-
+







void
Tk_GetRootCoords(
    Tk_Window tkwin,		/* Token for window. */
    int *xPtr,			/* Where to store x-displacement of (0,0). */
    int *yPtr)			/* Where to store y-displacement of (0,0). */
{
    int x, y;
    TkWindow *winPtr = (TkWindow *) tkwin;
    TkWindow *winPtr = (TkWindow *)tkwin;

    /*
     * Search back through this window's parents all the way to a top-level
     * window, combining the offsets of each window within its parent.
     */

    x = y = 0;
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4631
4632
4633
4634
4635
4636
4637





















4638
4639
4640
4641
4642
4643
4644







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







		x += winPtr->wmInfoPtr->xInParent;
		y += winPtr->wmInfoPtr->yInParent;
		break;
	    }

	    otherPtr = TkpGetOtherWindow(winPtr);
	    if (otherPtr == NULL) {
		if (tkMacOSXEmbedHandler->getOffsetProc != NULL) {
		    Point theOffset;

		    /*
		     * We do not require that the changes.x & changes.y for a
		     * non-Tk master window be kept up to date. So we first
		     * subtract off the possibly bogus values that have been
		     * added on at the top of this pass through the loop, and
		     * then call out to the getOffsetProc to give us the
		     * correct offset.
		     */

		    x -= winPtr->changes.x + winPtr->changes.border_width;
		    y -= winPtr->changes.y + winPtr->changes.border_width;

		    tkMacOSXEmbedHandler->getOffsetProc((Tk_Window) winPtr,
			    &theOffset);

		    x += theOffset.h;
		    y += theOffset.v;
		}
		break;
	    }

	    /*
	     * The container window is in the same application. Query its
	     * coordinates.
	     */
4656
4657
4658
4659
4660
4661
4662
4663

4664
4665
4666

4667
4668
4669
4670
4671
4672
4673
4752
4753
4754
4755
4756
4757
4758

4759
4760
4761

4762
4763
4764
4765
4766
4767
4768
4769







-
+


-
+







	    }
	}
	if (nextPtr == NULL) {
	    break;
	}
	winPtr = nextPtr;
    }
    if (winPtr->mainPtr != ((TkWindow *) tkwin)->mainPtr) {
    if (winPtr->mainPtr != ((TkWindow *)tkwin)->mainPtr) {
	return NULL;
    }
    return (Tk_Window) winPtr;
    return (Tk_Window)winPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * Tk_TopCoordsToWindow --
 *
4699
4700
4701
4702
4703
4704
4705
4706

4707
4708
4709
4710
4711
4712
4713
4795
4796
4797
4798
4799
4800
4801

4802
4803
4804
4805
4806
4807
4808
4809







-
+







{
    TkWindow *winPtr, *childPtr;
    TkWindow *nextPtr;		/* Coordinates of highest child found so far
				 * that contains point. */
    int x, y;			/* Coordinates in winPtr. */
    Window *children;		/* Children of winPtr, or NULL. */

    winPtr = (TkWindow *) tkwin;
    winPtr = (TkWindow *)tkwin;
    x = rootX;
    y = rootY;
    while (1) {
	nextPtr = NULL;
	children = NULL;

	/*
4752
4753
4754
4755
4756
4757
4758
4759

4760
4761
4762
4763
4764
4765
4766
4848
4849
4850
4851
4852
4853
4854

4855
4856
4857
4858
4859
4860
4861
4862







-
+







	}
	winPtr = nextPtr;
	x -= winPtr->changes.x;
	y -= winPtr->changes.y;
    }
    *newX = x;
    *newY = y;
    return (Tk_Window) winPtr;
    return (Tk_Window)winPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * UpdateVRootGeometry --
 *
4853
4854
4855
4856
4857
4858
4859
4860

4861
4862
4863
4864
4865
4866
4867
4949
4950
4951
4952
4953
4954
4955

4956
4957
4958
4959
4960
4961
4962
4963







-
+







				 * queried. */
    int *xPtr, int *yPtr,	/* Store x and y offsets of virtual root
				 * here. */
    int *widthPtr,		/* Store dimensions of virtual root here. */
    int *heightPtr)
{
    WmInfo *wmPtr;
    TkWindow *winPtr = (TkWindow *) tkwin;
    TkWindow *winPtr = (TkWindow *)tkwin;

    /*
     * Find the top-level window for tkwin, and locate the window manager
     * information for that window.
     */

    while (!(winPtr->flags & TK_TOP_LEVEL)) {
4904
4905
4906
4907
4908
4909
4910
4911

4912
4913
4914
4915
4916
4917
4918
5000
5001
5002
5003
5004
5005
5006

5007
5008
5009
5010
5011
5012
5013
5014







-
+







 */

void
Tk_MoveToplevelWindow(
    Tk_Window tkwin,		/* Window to move. */
    int x, int y)		/* New location for window (within parent). */
{
    TkWindow *winPtr = (TkWindow *) tkwin;
    TkWindow *winPtr = (TkWindow *)tkwin;
    WmInfo *wmPtr = winPtr->wmInfoPtr;

    if (!(winPtr->flags & TK_TOP_LEVEL)) {
	Tcl_Panic("Tk_MoveToplevelWindow called with non-toplevel window");
    }
    wmPtr->x = x;
    wmPtr->y = y;
4974
4975
4976
4977
4978
4979
4980
4981

4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997

4998
4999
5000
5001
5002
5003
5004
5070
5071
5072
5073
5074
5075
5076

5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092

5093
5094
5095
5096
5097
5098
5099
5100







-
+















-
+







     */

    if (winPtr->window == None ||
	    wmPtr == NULL      ||
	    wmPtr->hints.initial_state == WithdrawnState) {
	return;
    }
    macWindow = TkMacOSXDrawableWindow(winPtr->window);
    macWindow = TkMacOSXGetNSWindowForDrawable(winPtr->window);
    if (macWindow == nil) {
	return;
    }
    if (otherPtr) {
	/*
	 * When otherPtr is non-NULL, if the other window has no drawable or is
	 * withdrawn, do nothing.
	 */

	WmInfo *otherWmPtr = otherPtr->wmInfoPtr;
	if (winPtr->window == None ||
		otherWmPtr == NULL ||
		otherWmPtr->hints.initial_state == WithdrawnState) {
	    return;
	}
	otherMacWindow = TkMacOSXDrawableWindow(otherPtr->window);
	otherMacWindow = TkMacOSXGetNSWindowForDrawable(otherPtr->window);
	if (otherMacWindow == nil) {
	    return;
	}

	/*
	 * If the other window is OK, get its number.
	 */
5079
5080
5081
5082
5083
5084
5085
5086

5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103

5104
5105
5106
5107
5108
5109
5110
5175
5176
5177
5178
5179
5180
5181

5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198

5199
5200
5201
5202
5203
5204
5205
5206







-
+
















-
+







    }

    /*
     * Make a new bigger array and use it to reset the property. Automatically
     * add the toplevel itself as the last element of the list.
     */

    newPtr = ckalloc((count+2) * sizeof(TkWindow *));
    newPtr = (TkWindow **)ckalloc((count+2) * sizeof(TkWindow *));
    if (count > 0) {
	memcpy(newPtr, oldPtr, count * sizeof(TkWindow *));
    }
    if (count == 0) {
	count++;
    }
    newPtr[count-1] = winPtr;
    newPtr[count] = topPtr;
    if (oldPtr != NULL) {
	ckfree(oldPtr);
    }

    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.
     */
}

/*
 *----------------------------------------------------------------------
 *
5191
5192
5193
5194
5195
5196
5197
5198

5199
5200
5201
5202
5203
5204
5205
5287
5288
5289
5290
5291
5292
5293

5294
5295
5296
5297
5298
5299
5300
5301







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

void
TkGetPointerCoords(
    Tk_Window tkwin,		/* Toplevel window that identifies screen on
    TCL_UNUSED(Tk_Window),	/* Toplevel window that identifies screen on
				 * which lookup is to be done. */
    int *xPtr, int *yPtr)	/* Store pointer coordinates here. */
{
    XQueryPointer(NULL, None, NULL, NULL, xPtr, yPtr, NULL, NULL, NULL);
}

/*
5299
5300
5301
5302
5303
5304
5305
5306
5307


5308
5309
5310
5311
5312
5313
5314
5395
5396
5397
5398
5399
5400
5401


5402
5403
5404
5405
5406
5407
5408
5409
5410







-
-
+
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TkMacOSXGrowToplevel(
    void *whichWindow,
    XPoint start)
    TCL_UNUSED(void *),
    TCL_UNUSED(XPoint))
{
    return false;
}

/*
 *----------------------------------------------------------------------
 *
5332
5333
5334
5335
5336
5337
5338
5339

5340
5341
5342
5343
5344
5345
5346

5347
5348
5349

5350
5351
5352

5353
5354
5355
5356
5357
5358
5359
5360
5361

5362
5363
5364
5365

5366
5367
5368
5369
5370
5371
5372
5373
5374
5375


5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389

5390
5391
5392



5393
5394
5395
5396
5397

5398
5399
5400
5401
5402
5403
5404
5405

5406
5407



5408
5409

5410

5411
5412
5413
5414
5415
5416
5417
5418
5419
5420



5421
5422

5423


5424

5425
5426

5427
5428
5429
5430
5431
5432
5433
5428
5429
5430
5431
5432
5433
5434

5435
5436
5437
5438
5439
5440
5441

5442
5443
5444

5445
5446
5447

5448
5449
5450
5451
5452
5453
5454
5455
5456

5457
5458
5459
5460

5461
5462
5463
5464
5465
5466
5467
5468
5469
5470

5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487



5488
5489
5490

5491



5492


5493
5494
5495
5496
5497

5498
5499

5500
5501
5502
5503
5504
5505

5506
5507
5508
5509
5510
5511
5512
5513



5514
5515
5516
5517

5518
5519
5520
5521

5522
5523

5524
5525
5526
5527
5528
5529
5530
5531







-
+






-
+


-
+


-
+








-
+



-
+









-
+
+














+
-
-
-
+
+
+
-

-
-
-
+
-
-





-
+

-
+
+
+


+
-
+







-
-
-
+
+
+

-
+

+
+
-
+

-
+







    Tk_Uid titleUid)
{
    if (Tk_IsEmbedded(winPtr)) {
	return;
    }

    NSString *title = [[NSString alloc] initWithUTF8String:titleUid];
    [TkMacOSXDrawableWindow(winPtr->window) setTitle:title];
    [TkMacOSXGetNSWindowForDrawable(winPtr->window) setTitle:title];
    [title release];
}

/*
 *----------------------------------------------------------------------
 *
 * TkGetTransientMaster --
 * TkMacOSXGetContainer --
 *
 *	If the passed window has the TRANSIENT_FOR property set this will
 *	return the master window. Otherwise it will return None.
 *	return the container window. Otherwise it will return None.
 *
 * Results:
 *	The master window or None.
 *	The container window or None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

Tk_Window
TkGetTransientMaster(
TkMacOSXGetContainer(
    TkWindow *winPtr)
{
    if (winPtr->wmInfoPtr != NULL) {
	return (Tk_Window)winPtr->wmInfoPtr->master;
	return (Tk_Window)winPtr->wmInfoPtr->container;
    }
    return NULL;
}

/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXGetXWindow --
 *
 *	Returns the X window Id associated with the given NSWindow*.
 *	Stub function that returns the X window Id associated with the
 *      given NSWindow*.
 *
 * Results:
 *	The window id is returned. None is returned if not a Tk window.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

Window
TkMacOSXGetXWindow(
    void *macWinPtr)
{
    Window window = None;
    Tcl_HashEntry *hPtr;

    if (!macWinPtr || !windowHashInit) {
    TKWindow *w = (TKWindow *)macWinPtr;
    if ([w respondsToSelector: @selector (tkWindow)]) {
	window = [w tkWindow];
	return None;
    }
    hPtr = Tcl_FindHashEntry(&windowTable, macWinPtr);
    if (hPtr == NULL) {
	return None;
    return window ? window : None;
    }
    return (Window) Tcl_GetHashValue(hPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXGetTkWindow --
 * Tk_MacOSXGetTkWindow --
 *
 *	Returns the TkWindow* associated with the given NSWindow*.
 *	Returns the Tk_Window associated with the given NSWindow*.  This
 *      function is a stub, so the NSWindow* parameter must be declared as
 *      void*.
 *
 * Results:
 *	A Tk_Window, or NULL if the NSWindow is not associated with
 *	The TkWindow* returned. NULL is returned if not a Tk window.
 *      any Tk window.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

TkWindow*
TkMacOSXGetTkWindow(
    NSWindow *w)
Tk_Window
Tk_MacOSXGetTkWindow(
    void *w)
{
    Window window = TkMacOSXGetXWindow(w);
    Window window = None;
    TkDisplay *dispPtr = TkGetDisplayList();
    if ([(NSWindow *)w respondsToSelector: @selector (tkWindow)]) {
	window = [(TKWindow *)w tkWindow];

    }
    return (window != None ?
	    (TkWindow *)Tk_IdToWindow(dispPtr->display, window) : NULL);
	    Tk_IdToWindow(dispPtr->display, window) : NULL);
}

/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXIsWindowZoomed --
 *
5444
5445
5446
5447
5448
5449
5450
5451

5452
5453
5454
5455
5456
5457
5458
5542
5543
5544
5545
5546
5547
5548

5549
5550
5551
5552
5553
5554
5555
5556







-
+







 *----------------------------------------------------------------------
 */

MODULE_SCOPE int
TkMacOSXIsWindowZoomed(
    TkWindow *winPtr)
{
    NSWindow *macWindow = TkMacOSXDrawableWindow(winPtr->window);
    NSWindow *macWindow = TkMacOSXGetNSWindowForDrawable(winPtr->window);
    return [macWindow isZoomed];
}

/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXZoomToplevel --
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5615
5616
5617
5618
5619
5620
5621

5622
5623
5624
5625
5626
5627
5628







-







 *
 * Side effects:
 *	Changes the style of a new Mac window.
 *
 *----------------------------------------------------------------------
 */

/* ARGSUSED */
int
TkUnsupported1ObjCmd(
    ClientData clientData,	/* Main window associated with interpreter. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
5564
5565
5566
5567
5568
5569
5570
5571

5572
5573
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583

5584
5585
5586
5587
5588
5589
5590
5591
5592
5593

5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607

5608
5609
5610
5611
5612
5613
5614
5661
5662
5663
5664
5665
5666
5667

5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679

5680
5681
5682
5683
5684
5685
5686
5687
5688
5689

5690
5691
5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703

5704
5705
5706
5707
5708
5709
5710
5711







-
+











-
+









-
+













-
+







    case TKMWS_STYLE:
	if ((objc < 3) || (objc > 5)) {
	    Tcl_WrongNumArgs(interp, 2, objv, "window ?class attributes?");
	    return TCL_ERROR;
	}
	return WmWinStyle(interp, winPtr, objc, objv);
    case TKMWS_TABID:
	if ([NSApp macMinorVersion] < 12) {
	if ([NSApp macOSVersion] < 101200) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
                "Tabbing identifiers did not exist until OSX 10.12.", -1));
	    Tcl_SetErrorCode(interp, "TK", "WINDOWSTYLE", "TABBINGID", NULL);
	    return TCL_ERROR;
	}
	if ((objc < 3) || (objc > 4)) {
	    Tcl_WrongNumArgs(interp, 2, objv, "window ?newid?");
	    return TCL_ERROR;
	}
	return WmWinTabbingId(interp, winPtr, objc, objv);
    case TKMWS_APPEARANCE:
	if ([NSApp macMinorVersion] < 9) {
	if ([NSApp macOSVersion] < 100900) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
                "Window appearances did not exist until OSX 10.9.", -1));
	    Tcl_SetErrorCode(interp, "TK", "WINDOWSTYLE", "APPEARANCE", NULL);
	    return TCL_ERROR;
	}
	if ((objc < 3) || (objc > 4)) {
	    Tcl_WrongNumArgs(interp, 2, objv, "window ?appearancename?");
	    return TCL_ERROR;
	}
	if (objc == 4 && [NSApp macMinorVersion] < 14) {
	if (objc == 4 && [NSApp macOSVersion] < 101400) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "Window appearances cannot be changed before OSX 10.14.",
		    -1));
	    Tcl_SetErrorCode(interp, "TK", "WINDOWSTYLE", "APPEARANCE", NULL);
	    return TCL_ERROR;
	}
	return WmWinAppearance(interp, winPtr, objc, objv);
    case TKMWS_ISDARK:
	if ((objc != 3)) {
	    Tcl_WrongNumArgs(interp, 2, objv, "window");
	    return TCL_ERROR;
	}
	Tcl_SetObjResult(interp, Tcl_NewBooleanObj(
		TkMacOSXInDarkMode((Tk_Window) winPtr)));
		TkMacOSXInDarkMode((Tk_Window)winPtr)));
	return TCL_OK;
    default:
	return TCL_ERROR;
    }
}

/*
5653
5654
5655
5656
5657
5658
5659
5660

5661
5662
5663
5664
5665
5666
5667

5668
5669
5670
5671
5672
5673
5674
5750
5751
5752
5753
5754
5755
5756

5757
5758
5759
5760
5761
5762
5763

5764
5765
5766
5767
5768
5769
5770
5771







-
+






-
+







	{ "toolbar",		kToolbarWindowClass			     },
	{ "plain",		kPlainWindowClass			     },
	{ "overlay",		kOverlayWindowClass			     },
	{ "sheetAlert",		kSheetAlertWindowClass			     },
	{ "altPlain",		kAltPlainWindowClass			     },
	{ "simple",		kSimpleWindowClass			     },
	{ "drawer",		kDrawerWindowClass			     },
	{ NULL }
	{ NULL, 0 }
    };
    static const struct StrIntMap compositeAttrMap[] = {
	{ "none",		kWindowNoAttributes			     },
	{ "standardDocument",	kWindowStandardDocumentAttributes	     },
	{ "standardFloating",	kWindowStandardFloatingAttributes	     },
	{ "fullZoom",		kWindowFullZoomAttribute		     },
	{ NULL }
	{ NULL, 0 }
    };

    /*
     * Map window attributes. Color and opacity are mapped to NULL; these are
     * parsed from the objv in TkUnsupported1ObjCmd.
     */

5697
5698
5699
5700
5701
5702
5703
5704

5705
5706
5707
5708
5709
5710
5711
5794
5795
5796
5797
5798
5799
5800

5801
5802
5803
5804
5805
5806
5807
5808







-
+







	{ "ignoreClicks",	kWindowIgnoreClicksAttribute		     },
	{ "noConstrain",	kWindowNoConstrainAttribute		     },
	{ "doesNotHide",	tkWindowDoesNotHideAttribute		     },
	{ "canJoinAllSpaces",	tkCanJoinAllSpacesAttribute		     },
	{ "moveToActiveSpace",	tkMoveToActiveSpaceAttribute		     },
	{ "nonActivating",	tkNonactivatingPanelAttribute		     },
	{ "hud",		tkHUDWindowAttribute			     },
	{ NULL }
	{ NULL, 0 }
    };

    int index, i;
    WmInfo *wmPtr = winPtr->wmInfoPtr;

    if (objc == 3) {
	Tcl_Obj *attributeList, *newResult = NULL;
5824
5825
5826
5827
5828
5829
5830
5831








5832
5833
5834

5835
5836
5837
5838
5839
5840


5841
5842
5843
5844
5845
5846
5847
5921
5922
5923
5924
5925
5926
5927

5928
5929
5930
5931
5932
5933
5934
5935
5936
5937

5938
5939
5940
5941
5942
5943

5944
5945
5946
5947
5948
5949
5950
5951
5952







-
+
+
+
+
+
+
+
+


-
+





-
+
+







static int
WmWinTabbingId(
    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 = TkMacOSXDrawableWindow(winPtr->window);
    NSWindow *win = TkMacOSXGetNSWindowForDrawable(winPtr->window);
    if (win) {
	idString = win.tabbingIdentifier;
	result = Tcl_NewStringObj(idString.UTF8String, [idString length]);
    }
    if (result == NULL) {
	NSLog(@"Failed to read tabbing identifier; try calling update idletasks before getting/setting the tabbing identifier of the window.");
	NSLog(@"Failed to read tabbing identifier; try calling update idletasks"
	      " before getting/setting the tabbing identifier of the window.");
	return TCL_OK;
    }
    Tcl_SetObjResult(interp, result);
    if (objc == 3) {
	return TCL_OK;
    } else if (objc == 4) {
	int len;
5902
5903
5904
5905
5906
5907
5908







5909
5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920
5921
5922
5923
5924

5925
5926
5927
5928
5929
5930
5931
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019
6020
6021
6022
6023
6024
6025
6026
6027
6028
6029
6030
6031
6032
6033
6034
6035

6036
6037
6038
6039
6040
6041
6042
6043







+
+
+
+
+
+
+















-
+







static int
WmWinAppearance(
    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 {
	APPEARANCE_AQUA, APPEARANCE_DARKAQUA, APPEARANCE_AUTO
    };
    Tcl_Obj *result = NULL;
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101300
    NSAppearanceName appearance;
#else
    NSString *appearance;
#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 101300

    const char *resultString = "unrecognized";
    NSWindow *win = TkMacOSXDrawableWindow(winPtr->window);
    NSWindow *win = TkMacOSXGetNSWindowForDrawable(winPtr->window);
    if (win) {
	appearance = win.appearance.name;
	if (appearance == nil) {
	    resultString = appearanceStrings[APPEARANCE_AUTO];
	} else if (appearance == NSAppearanceNameAqua) {
	    resultString = appearanceStrings[APPEARANCE_AQUA];
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400
5992
5993
5994
5995
5996
5997
5998
5999

6000
6001
6002
6003
6004
6005
6006
6104
6105
6106
6107
6108
6109
6110

6111
6112
6113
6114
6115
6116
6117
6118







-
+







TkpMakeMenuWindow(
    Tk_Window tkwin,		/* New window. */
    int transient)		/* 1 means menu is only posted briefly as a
				 * popup or pulldown or cascade. 0 means menu
				 * is always visible, e.g. as a floating
				 * menu. */
{
    TkWindow *winPtr = (TkWindow *) tkwin;
    TkWindow *winPtr = (TkWindow *)tkwin;

    if (transient) {
	winPtr->wmInfoPtr->macClass = kSimpleWindowClass;
	winPtr->wmInfoPtr->attributes = kWindowNoActivatesAttribute;
    } else {
	winPtr->wmInfoPtr->macClass = kFloatingWindowClass;
	winPtr->wmInfoPtr->attributes = kWindowStandardFloatingAttributes;
6029
6030
6031
6032
6033
6034
6035
6036

6037
6038
6039
6040
6041
6042

6043
6044
6045
6046
6047
6048
6049
6050
6051
6052
6053
6054
6055
6056
6057
6058
6059
6060

6061
6062
6063
6064
6065
6066
6067
6068
6069
6070
6071
6072
6073
6141
6142
6143
6144
6145
6146
6147

6148
6149
6150
6151
6152
6153

6154
6155
6156
6157
6158
6159
6160
6161
6162
6163
6164
6165
6166
6167
6168
6169
6170


6171






6172
6173
6174
6175
6176
6177
6178







-
+





-
+
















-
-
+
-
-
-
-
-
-







void
TkMacOSXMakeRealWindowExist(
    TkWindow *winPtr)		/* Tk window. */
{
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    MacDrawable *macWin;
    WindowClass macClass;
    Bool overrideRedirect = Tk_Attributes((Tk_Window) winPtr)->override_redirect;
    Bool overrideRedirect = Tk_Attributes((Tk_Window)winPtr)->override_redirect;

    if (TkMacOSXHostToplevelExists(winPtr)) {
	return;
    }

    macWin = (MacDrawable *) winPtr->window;
    macWin = (MacDrawable *)winPtr->window;

    /*
     * If this is embedded, make sure its container's toplevel exists, then
     * return...
     */

    if (Tk_IsEmbedded(winPtr)) {
	TkWindow *contWinPtr = TkpGetOtherWindow(winPtr);

	if (contWinPtr != NULL) {
	    TkMacOSXMakeRealWindowExist(
		    contWinPtr->privatePtr->toplevel->winPtr);
	    macWin->flags |= TK_HOST_EXISTS;
	    return;
	}

	if (tkMacOSXEmbedHandler == NULL) {
	    Tcl_Panic("TkMacOSXMakeRealWindowExist could not find container");
	Tcl_Panic("TkMacOSXMakeRealWindowExist could not find container");
	}
	if (tkMacOSXEmbedHandler->containerExistProc &&
		tkMacOSXEmbedHandler->containerExistProc((Tk_Window) winPtr)
		!= TCL_OK) {
	    Tcl_Panic("ContainerExistProc could not make container");
	}
	return;

	/*
	 * TODO: Here we should handle out of process embedding.
	 */
    }

6096
6097
6098
6099
6100
6101
6102
6103

6104
6105

6106
6107
6108
6109
6110
6111


6112

6113
6114
6115
6116
6117
6118
6119
6120
6121
6122
6123
6124
6125

6126
6127
6128
6129
6130
6131
6132
6133
6134
6135
6136
6137
6138
6139
6140
6141
6142
6143
6144
6145

6146
6147
6148
6149
6150
6151
6152
6153


6154
6155
6156
6157
6158
6159
6160

6161
6162
6163
6164



6165
6166
6167
6168
6169
6170
6171
6172
6173
6174

6175
6176
6177
6178
6179
6180
6181
6182
6183
6184
6185
6186
6187
6188
6189
6190
6191
6192
6193
6194
6195
6196
6197
6198
6199
6200
6201
6202
6203
6204
6205



6206
6207
6208
6209


6210
6211
6212
6213

6214
6215

6216

6217
6218

6219
6220

6221
6222
6223
6224
6225
6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6237

6238
6239

6240
6241
6242
6243

6244
6245





6246
6247
6248
6249
6250
6251
6252
6253


6254
6255
6256
6257
6258
6259
6260
6201
6202
6203
6204
6205
6206
6207

6208
6209

6210
6211
6212
6213
6214
6215
6216
6217
6218

6219
6220
6221
6222
6223
6224
6225
6226
6227
6228
6229
6230
6231

6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250
6251

6252
6253
6254
6255
6256
6257
6258


6259
6260
6261
6262
6263
6264
6265
6266

6267
6268



6269
6270
6271
6272
6273
6274
6275
6276





6277























6278
6279
6280
6281
6282



6283
6284
6285




6286
6287




6288


6289

6290
6291

6292


6293

















6294


6295




6296


6297
6298
6299
6300
6301
6302







6303
6304
6305
6306
6307
6308
6309
6310
6311







-
+

-
+






+
+
-
+












-
+



















-
+






-
-
+
+






-
+

-
-
-
+
+
+





-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-





-
-
-
+
+
+
-
-
-
-
+
+
-
-
-
-
+
-
-
+
-
+

-
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
-
-
-
-
+
-
-
+
+
+
+
+

-
-
-
-
-
-
-
+
+







	((attributes & kWindowResizableAttribute) ? NSResizableWindowMask : 0) |
	((attributes & kWindowMetalAttribute) ?
		NSTexturedBackgroundWindowMask : 0) |
	((attributes & kWindowUnifiedTitleAndToolbarAttribute) ?
		NSUnifiedTitleAndToolbarWindowMask : 0) |
	((attributes & kWindowSideTitlebarAttribute) ? 1 << 9 : 0) |
	(attributes >> WM_NSMASK_SHIFT);
    Class winClass = (macClass == kDrawerWindowClass ? [NSDrawerWindow class] :
    Class winClass = (macClass == kDrawerWindowClass ? [TKDrawerWindow class] :
	    (styleMask & (NSUtilityWindowMask|NSDocModalWindowMask|
	    NSNonactivatingPanelMask|NSHUDWindowMask)) ? [NSPanel class] :
	    NSNonactivatingPanelMask|NSHUDWindowMask)) ? [TKPanel class] :
	    [TKWindow class]);
    NSRect structureRect = [winClass frameRectForContentRect:NSZeroRect
	    styleMask:styleMask];
    NSRect contentRect = NSMakeRect(5 - structureRect.origin.x,
	    TkMacOSXZeroScreenHeight() - (TkMacOSXZeroScreenTop() + 5 +
	    structureRect.origin.y + structureRect.size.height + 200), 200, 200);
    if (wmPtr->hints.initial_state == WithdrawnState) {
    }
    NSWindow *window = [[winClass alloc] initWithContentRect:contentRect
    TKWindow *window = [[winClass alloc] initWithContentRect:contentRect
	    styleMask:styleMask backing:NSBackingStoreBuffered defer:YES];
    if (!window) {
    	Tcl_Panic("couldn't allocate new Mac window");
    }
    TKContentView *contentView = [[TKContentView alloc]
				     initWithFrame:NSZeroRect];
    [window setContentView:contentView];
    [contentView release];
    [window setDelegate:NSApp];
    [window setAcceptsMouseMovedEvents:YES];
    [window setReleasedWhenClosed:NO];
    if (styleMask & NSUtilityWindowMask) {
	[(NSPanel*)window setFloatingPanel:YES];
	[(TKPanel*)window setFloatingPanel:YES];
    }
    if ((styleMask & (NSTexturedBackgroundWindowMask|NSHUDWindowMask)) &&
	    !(styleMask & NSDocModalWindowMask)) {
        /*
	 * Workaround for [Bug 2824538]: Textured windows are draggable from
	 *                               opaque content.
	 */
	[window setMovableByWindowBackground:NO];
    }
    [window setDocumentEdited:NO];
    wmPtr->window = window;
    macWin->view = window.contentView;
    TkMacOSXApplyWindowAttributes(winPtr, window);
    NSRect geometry = InitialWindowBounds(winPtr, window);
    geometry.size.width += structureRect.size.width;
    geometry.size.height += structureRect.size.height;
    geometry.origin.y = TkMacOSXZeroScreenHeight() - (geometry.origin.y +
	    geometry.size.height);
    [window setFrame:geometry display:YES];
    TkMacOSXRegisterOffScreenWindow((Window) macWin, window);
    [window setTkWindow: (Window) macWin];

    macWin->flags |= TK_HOST_EXISTS;
    if (overrideRedirect) {
    	XSetWindowAttributes atts;

    	atts.override_redirect = True;
    	Tk_ChangeWindowAttributes((Tk_Window) winPtr, CWOverrideRedirect, &atts);
    	ApplyMasterOverrideChanges(winPtr, NULL);
    	Tk_ChangeWindowAttributes((Tk_Window)winPtr, CWOverrideRedirect, &atts);
    	ApplyContainerOverrideChanges(winPtr, NULL);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TkpDisplayWindow --
 * TkpRedrawWidget --
 *
 *      Mark the contentView of this window as needing display so the window
 *      will be drawn by the window manager.  If this is called within the
 *      drawRect method, do nothing.
 *      Mark the bounding rectangle of this widget as needing display so the
 *      widget will be drawn by [NSView drawRect:].  If this is called within
 *      the drawRect method, do nothing.
 *
 * Results:
 *      None.
 *
 * Side effects:
 *      The window's contentView is marked as needing display.
 *
 *----------------------------------------------------------------------
 */

 *      The widget's bounding rectangle is marked as dirty.
MODULE_SCOPE void
TkpDisplayWindow(Tk_Window tkwin) {
    if (![NSApp isDrawing]) {
    	TkWindow *winPtr = (TkWindow *) tkwin;
    	NSWindow *w = TkMacOSXDrawableWindow(winPtr->window);

    	[[w contentView] setNeedsDisplay: YES];
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXRegisterOffScreenWindow --
 *
 *	This function adds the passed in Off Screen Port to the hash table that
 *	maps Mac windows to root X windows.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	An entry is added to the windowTable hash table.
 *
 *----------------------------------------------------------------------
 */

void
TkMacOSXRegisterOffScreenWindow(
    Window window,		/* Window structure. */
    void *portPtr)		/* Pointer to a Mac Window. */
TkpRedrawWidget(Tk_Window tkwin) {
    TkWindow *winPtr = (TkWindow *)tkwin;
    NSWindow *w;
{
    Tcl_HashEntry *valueHashPtr;
    int isNew;

    Rect tkBounds;
    NSRect bounds;
    if (!windowHashInit) {
	Tcl_InitHashTable(&windowTable, TCL_ONE_WORD_KEYS);
	windowHashInit = true;
    }

    valueHashPtr = Tcl_CreateHashEntry(&windowTable, (char *) portPtr, &isNew);
    if (!isNew) {
    if ([NSApp isDrawing]) {
	Tcl_Panic("Same macintosh window allocated twice!");
	return;
    }
    Tcl_SetHashValue(valueHashPtr, window);
    w = TkMacOSXGetNSWindowForDrawable(winPtr->window);
}

    if (w) {
/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXUnregisterMacWindow --
 *
 *	Given a macintosh port window, this function removes the association
 *	between this window and the root X window that Tk cares about.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	An entry is removed from the windowTable hash table.
 *
 *----------------------------------------------------------------------
 */

	TKContentView *view = [w contentView];
void
TkMacOSXUnregisterMacWindow(
	TkMacOSXWinBounds(winPtr, &tkBounds);
    void *macWinPtr)	/* Reference to a Mac Window */
{
    Tcl_HashEntry *entryPtr;

	bounds = NSMakeRect(tkBounds.left,
    if (!windowHashInit) {
	Tcl_Panic("TkMacOSXUnregisterMacWindow: unmapping before inited");
			    [view bounds].size.height - tkBounds.bottom,
			    tkBounds.right - tkBounds.left,
			    tkBounds.bottom - tkBounds.top);
	[view setTkNeedsDisplay:YES];
	[view setTkDirtyRect:bounds];
    }
    entryPtr = Tcl_FindHashEntry(&windowTable, macWinPtr);
    if (!entryPtr) {
	TkMacOSXDbgMsg("Failed to find window %p", macWinPtr);
    } else {
	Tcl_DeleteHashEntry(entryPtr);
    }
}
}


/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXSetScrollbarGrow --
 *
 *	Sets a flag for a toplevel window indicating that the passed Tk
6374
6375
6376
6377
6378
6379
6380
6381

6382
6383
6384

6385

6386
6387
6388
6389
6390
6391
6392
6393
6394
6395

6396
6397

6398
6399
6400
6401




6402
6403
6404





6405
6406
6407
6408
6409
6410
6411
6425
6426
6427
6428
6429
6430
6431

6432
6433
6434

6435
6436
6437
6438
6439
6440
6441
6442
6443
6444
6445
6446

6447
6448

6449




6450
6451
6452
6453



6454
6455
6456
6457
6458
6459
6460
6461
6462
6463
6464
6465







-
+


-
+

+









-
+

-
+
-
-
-
-
+
+
+
+
-
-
-
+
+
+
+
+







    NSWindow *macWin;

    wmPtr->hints.initial_state = state;
    if (wmPtr->flags & WM_NEVER_MAPPED) {
	return;
    }

    macWin = TkMacOSXDrawableWindow(winPtr->window);
    macWin = TkMacOSXGetNSWindowForDrawable(winPtr->window);

    if (state == WithdrawnState) {
	Tk_UnmapWindow((Tk_Window) winPtr);
	Tk_UnmapWindow((Tk_Window)winPtr);
    } else if (state == IconicState) {

	/*
	 * The window always gets unmapped. If we can show the icon version of
	 * the window we also collapse it.
	 */

	if (macWin && ([macWin styleMask] & NSMiniaturizableWindowMask) &&
		![macWin isMiniaturized]) {
	    [macWin miniaturize:NSApp];
	}
	Tk_UnmapWindow((Tk_Window) winPtr);
	Tk_UnmapWindow((Tk_Window)winPtr);
    } else if (state == NormalState || state == ZoomState) {
	Tk_MapWindow((Tk_Window) winPtr);
	Tk_MapWindow((Tk_Window)winPtr);
	if (macWin && ([macWin styleMask] & NSMiniaturizableWindowMask) &&
		[macWin isMiniaturized]) {
	    [macWin deminiaturize:NSApp];
	}
	[macWin deminiaturize:NSApp];
	[macWin orderFront:NSApp];
	TkMacOSXZoomToplevel(macWin, state == NormalState ? inZoomIn : inZoomOut);
    }
	TkMacOSXZoomToplevel(macWin, state == NormalState ? inZoomIn :
		inZoomOut);
    }
    /*
     * Make sure windows are updated after the state change.
     */

    while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)){}
}

/*
 *----------------------------------------------------------------------
 *
 * TkpIsWindowFloating --
 *
6422
6423
6424
6425
6426
6427
6428
6429
6430
6431
6432
6433
6434
6435
6436
6437
6438
6439
6440
6441
6442
6443
6444
6445
6446
6447
6448
6449
6450
6451
6452
6453
6454
6455
6456
6457
6458
6476
6477
6478
6479
6480
6481
6482























6483
6484
6485
6486
6487
6488
6489







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-








int
TkpIsWindowFloating(
    void *wRef)
{
    return [(NSWindow *)wRef level] == kCGFloatingWindowLevel;
}

/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXWindowClass --
 *
 *	Returns OS X window class of window
 *
 * Results:
 *	1 or 0 depending on window's floating attribute.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

MODULE_SCOPE WindowClass
TkMacOSXWindowClass(
    TkWindow *winPtr)
{
    return winPtr->wmInfoPtr->macClass;
}

/*
 *--------------------------------------------------------------
 *
 * TkMacOSXWindowOffset --
 *
 *	Determines the x and y offset from the orgin of the toplevel window
6525
6526
6527
6528
6529
6530
6531
6532
6533
6534
6535




6536
6537
6538
6539
6540
6541
6542
6556
6557
6558
6559
6560
6561
6562




6563
6564
6565
6566
6567
6568
6569
6570
6571
6572
6573







-
-
-
-
+
+
+
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

int
XSetInputFocus(
    Display* display,
    Window focus,
    int revert_to,
    Time time)
    TCL_UNUSED(Display *),
    TCL_UNUSED(Window),
    TCL_UNUSED(int),
    TCL_UNUSED(Time))
{
    /*
     * Don't need to do a thing. Tk manages the focus for us.
     */
    return Success;
}

6570
6571
6572
6573
6574
6575
6576
6577

6578
6579
6580
6581
6582
6583
6584
6601
6602
6603
6604
6605
6606
6607

6608
6609
6610
6611
6612
6613
6614
6615







-
+







				 * application. */
{
    if (winPtr->atts.override_redirect) {
	return 0;
    }

    if (Tk_IsTopLevel(winPtr) && !Tk_IsEmbedded(winPtr)) {
    	NSWindow *win = TkMacOSXDrawableWindow(winPtr->window);
    	NSWindow *win = TkMacOSXGetNSWindowForDrawable(winPtr->window);

    	TkWmRestackToplevel(winPtr, Above, NULL);
    	if (force) {
    	    [NSApp activateIgnoringOtherApps:YES];
    	}
	if (win && [win canBecomeKeyWindow]) {
	    [win makeKeyAndOrderFront:NSApp];
6625
6626
6627
6628
6629
6630
6631
6632

6633
6634
6635
6636
6637
6638
6639
6656
6657
6658
6659
6660
6661
6662

6663
6664
6665
6666
6667
6668
6669
6670







-
+







    TkWindow *childPtr;
    Tcl_HashEntry *hPtr;
    int newEntry;

    if (Tk_IsMapped(winPtr) && Tk_IsTopLevel(winPtr) && !Tk_IsEmbedded(winPtr)
	    && (winPtr->display == display)) {
	hPtr = Tcl_CreateHashEntry(table,
		(char*) TkMacOSXDrawableWindow(winPtr->window), &newEntry);
		(void *)TkMacOSXGetNSWindowForDrawable(winPtr->window), &newEntry);
	Tcl_SetHashValue(hPtr, winPtr);
    }

    for (childPtr = winPtr->childList; childPtr != NULL;
	    childPtr = childPtr->nextPtr) {
	WmStackorderToplevelWrapperMap(childPtr, display, table);
    }
6663
6664
6665
6666
6667
6668
6669
6670

6671
6672
6673
6674
6675
6676
6677
6694
6695
6696
6697
6698
6699
6700

6701
6702
6703
6704
6705
6706
6707
6708







-
+







    TkWindow *childWinPtr, **windows, **windowPtr;
    Tcl_HashTable table;
    Tcl_HashEntry *hPtr;
    NSArray *macWindows = [NSApp orderedWindows];
    NSArray* backToFront = [[macWindows reverseObjectEnumerator] allObjects];
    NSInteger windowCount = [macWindows count];

    windows = windowPtr = ckalloc((windowCount + 1) * sizeof(TkWindow *));
    windows = windowPtr = (TkWindow **)ckalloc((windowCount + 1) * sizeof(TkWindow *));
    if (windows != NULL) {
	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);
6704
6705
6706
6707
6708
6709
6710
6711
6712


6713
6714
6715
6716
6717
6718
6719
6735
6736
6737
6738
6739
6740
6741


6742
6743
6744
6745
6746
6747
6748
6749
6750







-
-
+
+







TkMacOSXApplyWindowAttributes(
    TkWindow *winPtr,
    NSWindow *macWindow)
{
    WmInfo *wmPtr = winPtr->wmInfoPtr;

    ApplyWindowAttributeFlagChanges(winPtr, macWindow, 0, 0, 0, 1);
    if (wmPtr->master != NULL || winPtr->atts.override_redirect) {
	ApplyMasterOverrideChanges(winPtr, macWindow);
    if (wmPtr->container != NULL || winPtr->atts.override_redirect) {
	ApplyContainerOverrideChanges(winPtr, macWindow);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * ApplyWindowAttributeFlagChanges --
6745
6746
6747
6748
6749
6750
6751
6752

6753
6754
6755
6756
6757
6758
6759
6760

6761
6762
6763
6764
6765
6766
6767
6776
6777
6778
6779
6780
6781
6782

6783
6784
6785
6786
6787
6788
6789
6790

6791
6792
6793
6794
6795
6796
6797
6798







-
+







-
+








    if (changedAttributes || wmPtr->flags != oldFlags || initial) {
	if (!macWindow) {
	    if (winPtr->window == None) {
		if (!create) {
		    return;
		}
		Tk_MakeWindowExist((Tk_Window) winPtr);
		Tk_MakeWindowExist((Tk_Window)winPtr);
	    }
	    if (!TkMacOSXHostToplevelExists(winPtr)) {
		if (!create) {
		    return;
		}
		TkMacOSXMakeRealWindowExist(winPtr);
	    }
	    macWindow = TkMacOSXDrawableWindow(winPtr->window);
	    macWindow = TkMacOSXGetNSWindowForDrawable(winPtr->window);
	}
	if ((changedAttributes & kWindowCloseBoxAttribute) || initial) {
	    [[macWindow standardWindowButton:NSWindowCloseButton]
		    setEnabled:!!(newAttributes & kWindowCloseBoxAttribute)];
	}
	if ((changedAttributes & kWindowCollapseBoxAttribute) || initial) {
	    [[macWindow standardWindowButton:NSWindowMiniaturizeButton]
6830
6831
6832
6833
6834
6835
6836
6837

6838
6839
6840
6841
6842
6843
6844
6845

6846
6847
6848
6849
6850
6851
6852
6853
6854
6855
6856
6857
6858
6859

6860


6861
6862
6863
6864
6865
6866
6867
6861
6862
6863
6864
6865
6866
6867

6868
6869
6870
6871
6872
6873
6874
6875

6876
6877
6878
6879
6880

6881
6882
6883
6884
6885
6886
6887
6888
6889
6890

6891
6892
6893
6894
6895
6896
6897
6898
6899







-
+







-
+




-









+
-
+
+







	    /*
	     * This behavior, which makes the green button expand a window to
	     * full screen, was included in the default as of OSX 10.13.  For
	     * uniformity we use the new default in all versions of the OS
	     * after 10.10.
	     */

#if !(MAC_OS_X_VERSION_MAX_ALLOWED < 101000)
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101100
	    if (!(macWindow.styleMask & NSUtilityWindowMask)) {
		/*
		 * Exclude overrideredirect, transient, and "help"-styled
		 * windows from moving into their own fullscreen space.
		 */

		if ((winPtr->atts.override_redirect) ||
			(wmPtr->master != NULL) ||
			(wmPtr->container != NULL) ||
			(winPtr->wmInfoPtr->macClass == kHelpWindowClass)) {
		    b |= (NSWindowCollectionBehaviorCanJoinAllSpaces |
			    NSWindowCollectionBehaviorFullScreenAuxiliary);
		} else {
		    NSSize screenSize = [[macWindow screen] frame].size;
		    b |= NSWindowCollectionBehaviorFullScreenPrimary;

		    /*
		     * The default max size has height less than the screen
		     * height. This causes the window manager to refuse to
		     * 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 ([NSApp macMinorVersion] > 10) {
		    if ([NSApp macOSVersion] >= 101100) {
			NSSize screenSize = [[macWindow screen] frame].size;
			[macWindow setMaxFullScreenContentSize:screenSize];
		    }
		}
	    }
#endif

	    if (newAttributes & tkCanJoinAllSpacesAttribute) {
6875
6876
6877
6878
6879
6880
6881
6882

6883
6884
6885
6886
6887
6888
6889
6890
6891
6892
6893
6894
6895
6896
6897
6898
6899
6900
6901
6902
6903

6904
6905

6906
6907
6908
6909
6910
6911
6912
6913
6914
6915
6916
6917

6918
6919
6920
6921
6922
6923
6924
6925
6926
6927
6928
6929
6930

6931
6932
6933
6934
6935
6936
6937
6938
6939
6940
6941
6942
6943
6944

6945
6946
6947
6948
6949
6950
6951

6952
6953
6954
6955
6956
6957

6958
6959
6960
6961
6962
6963
6964
6907
6908
6909
6910
6911
6912
6913

6914
6915
6916
6917
6918
6919
6920
6921
6922
6923
6924
6925
6926
6927
6928
6929
6930
6931
6932
6933
6934

6935
6936

6937
6938
6939
6940
6941
6942
6943
6944
6945
6946
6947
6948

6949
6950
6951
6952
6953
6954
6955
6956
6957
6958
6959
6960
6961

6962
6963
6964
6965
6966
6967
6968
6969
6970
6971
6972
6973
6974
6975

6976
6977
6978
6979
6980
6981
6982

6983
6984
6985
6986
6987
6988

6989
6990
6991
6992
6993
6994
6995
6996







-
+




















-
+

-
+











-
+












-
+













-
+






-
+





-
+







		b |= NSWindowCollectionBehaviorParticipatesInCycle;
	    }
	    [macWindow setCollectionBehavior:b];
	}
	if ((wmPtr->flags & WM_TOPMOST) != (oldFlags & WM_TOPMOST)) {
	    [macWindow setLevel:(wmPtr->flags & WM_TOPMOST) ?
		    kCGUtilityWindowLevel : ([macWindow isKindOfClass:
		    [NSPanel class]] && [macWindow isFloatingPanel] ?
		    [TKPanel class]] && [macWindow isFloatingPanel] ?
		    kCGFloatingWindowLevel : kCGNormalWindowLevel)];
	}

	/*
	 * The change of window class/attributes might have changed the window
	 * frame geometry:
	 */

	NSRect structureRect = [macWindow frameRectForContentRect:NSZeroRect];

	wmPtr->xInParent = -structureRect.origin.x;
	wmPtr->yInParent = structureRect.origin.y + structureRect.size.height;
	wmPtr->parentWidth = winPtr->changes.width + structureRect.size.width;
	wmPtr->parentHeight = winPtr->changes.height + structureRect.size.height;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * ApplyMasterOverrideChanges --
 * ApplyContainerOverrideChanges --
 *
 *	This procedure applies changes to override_redirect or master.
 *	This procedure applies changes to override_redirect or container.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
ApplyMasterOverrideChanges(
ApplyContainerOverrideChanges(
    TkWindow *winPtr,
    NSWindow *macWindow)
{
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    UInt64 oldAttributes = wmPtr->attributes;
    int oldFlags = wmPtr->flags;
    unsigned long styleMask;
    NSRect structureRect;
    NSWindow *parentWindow;

    if (!macWindow && winPtr->window != None &&
	    TkMacOSXHostToplevelExists(winPtr)) {
	macWindow = TkMacOSXDrawableWindow(winPtr->window);
	macWindow = TkMacOSXGetNSWindowForDrawable(winPtr->window);
    }
    styleMask = [macWindow styleMask];

    /*
     * FIX: We need an UpdateWrapper equivalent to make this 100% correct
     */

    if (winPtr->atts.override_redirect) {
	if (wmPtr->macClass == kDocumentWindowClass) {
	    wmPtr->macClass = kSimpleWindowClass;
	    wmPtr->attributes = macClassAttrs[kSimpleWindowClass].defaultAttrs;
	}
	wmPtr->attributes |= kWindowNoActivatesAttribute;
	if ([NSApp macMinorVersion] == 6) {
	if ([NSApp macOSVersion] == 100600) {
	    styleMask = 0;
	} else {
	    styleMask &= ~NSTitledWindowMask;
	}
    } else {
	if (wmPtr->macClass == kSimpleWindowClass &&
		oldAttributes == kWindowNoActivatesAttribute) {
	    (oldAttributes & kWindowNoActivatesAttribute)) {
	    wmPtr->macClass = kDocumentWindowClass;
	    wmPtr->attributes =
		    macClassAttrs[kDocumentWindowClass].defaultAttrs;
	}
	wmPtr->attributes &= ~kWindowNoActivatesAttribute;
	if ([NSApp macMinorVersion] == 6) {
	if ([NSApp macOSVersion] == 100600) {
	    styleMask = NSTitledWindowMask         |
		        NSClosableWindowMask       |
		        NSMiniaturizableWindowMask |
		        NSResizableWindowMask;
	} else {
	    styleMask |= NSTitledWindowMask;
	}
6976
6977
6978
6979
6980
6981
6982
6983

6984
6985

6986
6987
6988
6989
6990
6991
6992
6993
6994
6995
6996
6997
6998
6999
7000
7001
7002


7003
7004
7005
7006
7007




7008
7009
7010
7011
7012
7013
7014
7015





7016
7017
7018

7019
7020
7021
7022
7023
7024
7025
7026

7027
7028
7029
7030
7031



7032
7033
7034
7035
7036
7037
7038
7008
7009
7010
7011
7012
7013
7014

7015
7016

7017
7018
7019
7020
7021
7022
7023
7024
7025
7026
7027
7028
7029
7030
7031
7032


7033
7034
7035




7036
7037
7038
7039
7040
7041
7042





7043
7044
7045
7046
7047
7048
7049

7050
7051
7052
7053
7054
7055
7056
7057

7058
7059
7060



7061
7062
7063
7064
7065
7066
7067
7068
7069
7070







-
+

-
+















-
-
+
+

-
-
-
-
+
+
+
+



-
-
-
-
-
+
+
+
+
+


-
+







-
+


-
-
-
+
+
+







	wmPtr->yInParent = structureRect.origin.y + structureRect.size.height;
	wmPtr->parentWidth = winPtr->changes.width + structureRect.size.width;
	wmPtr->parentHeight = winPtr->changes.height + structureRect.size.height;
	if (winPtr->atts.override_redirect) {
	    [macWindow setExcludedFromWindowsMenu:YES];
	    [macWindow setStyleMask:styleMask];
	    if (wmPtr->hints.initial_state == NormalState) {
		[macWindow orderFront:nil];
		[macWindow orderFront:NSApp];
	    }
	    if (wmPtr->master != NULL) {
	    if (wmPtr->container != NULL) {
		wmPtr->flags |= WM_TOPMOST;
	    } else {
		wmPtr->flags &= ~WM_TOPMOST;
	    }
	} else {
	    const char *title = winPtr->wmInfoPtr->titleUid;

	    if (!title) {
		title = winPtr->nameUid;
	    }
	    [macWindow setStyleMask:styleMask];
	    [macWindow setTitle:[NSString stringWithUTF8String:title]];
	    [macWindow setExcludedFromWindowsMenu:NO];
	    wmPtr->flags &= ~WM_TOPMOST;
	}
	if (wmPtr->master != None) {
	    TkWindow *masterWinPtr = (TkWindow *) wmPtr->master;
	if (wmPtr->container != None) {
	    TkWindow *containerWinPtr = (TkWindow *)wmPtr->container;

	    if (masterWinPtr && (masterWinPtr->window != None)
		    && TkMacOSXHostToplevelExists(masterWinPtr)) {
		NSWindow *masterMacWin = TkMacOSXDrawableWindow(
			masterWinPtr->window);
	    if (containerWinPtr && (containerWinPtr->window != None)
		    && TkMacOSXHostToplevelExists(containerWinPtr)) {
		NSWindow *containerMacWin = TkMacOSXGetNSWindowForDrawable(
			containerWinPtr->window);

		/*
		 * Try to add the transient window as a child window of the
		 * master. A child NSWindow retains its relative position with
		 * respect to the parent when the parent is moved.  This is
		 * pointless if the parent is offscreen, and adding a child to
		 * an offscreen window causes the parent to be displayed as a
		 * zombie.  So we only do this if the parent is visible.
		 * container. A child NSWindow retains its relative position
		 * with respect to the parent when the parent is moved.  This
		 * is pointless if the parent is offscreen, and adding a child
		 * to an offscreen window causes the parent to be displayed as
		 * a zombie.  So we only do this if the parent is visible.
		 */

		if (masterMacWin && [masterMacWin isVisible]
		if (containerMacWin && [containerMacWin isVisible]
			&& (winPtr->flags & TK_MAPPED)) {
		    /*
		     * If the transient is already a child of some other window,
		     * remove it.
		     */

		    parentWindow = [macWindow parentWindow];
		    if (parentWindow && parentWindow != masterMacWin) {
		    if (parentWindow && parentWindow != containerMacWin) {
			[parentWindow removeChildWindow:macWindow];
		    }

		    [masterMacWin addChildWindow:macWindow
					 ordered:NSWindowAbove];
		    [macWindow orderFront:NSApp];
		    [containerMacWin addChildWindow:macWindow
					    ordered:NSWindowAbove];
		}
	    }
	} else {
	    parentWindow = [macWindow parentWindow];
	    if (parentWindow) {
		[parentWindow removeChildWindow:macWindow];
	    }
7223
7224
7225
7226
7227
7228
7229
7230

7231
7232
7233
7234
7235
7236
7237
7238
7239
7240
7241
7242
7243
7244
7245
7246
7247

7248
7249
7250
7251
7252
7253
7254
7255
7256
7257
7258
7255
7256
7257
7258
7259
7260
7261

7262
7263
7264
7265
7266
7267
7268
7269
7270
7271
7272
7273
7274
7275
7276
7277
7278

7279
7280
7281
7282
7283
7284
7285
7286
7287
7288
7289
7290







-
+
















-
+












    /*
     * Remove the OS specific window. It will get rebuilt when the window gets
     * Mapped.
     */

    if (winPtr->window != None) {
	MacDrawable *macWin = (MacDrawable *) winPtr->window;
	MacDrawable *macWin = (MacDrawable *)winPtr->window;

	macWin->toplevel->referenceCount--;
	macWin->toplevel = parentWin->toplevel;
	macWin->toplevel->referenceCount++;
	winPtr->flags &= ~TK_MAPPED;
#ifdef TK_REBUILD_TOPLEVEL
	winPtr->flags |= TK_REBUILD_TOPLEVEL;
#endif
    }

    /*
     * Repeat for all the children.
     */

    for (childPtr = winPtr->childList; childPtr != NULL;
	    childPtr = childPtr->nextPtr) {
	RemapWindows(childPtr, (MacDrawable *) winPtr->window);
	RemapWindows(childPtr, (MacDrawable *)winPtr->window);
    }
}

/*
 * Local Variables:
 * mode: objc
 * c-basic-offset: 4
 * fill-column: 79
 * coding: utf-8
 * End:
 */
Changes to macosx/tkMacOSXWm.h.
1
2
3
4
5
6
7


8
9
10
11
12
13
14
1
2
3
4
5


6
7
8
9
10
11
12
13
14





-
-
+
+







/*
 * tkMacOSXWm.h --
 *
 *	Declarations of Macintosh specific window manager structures.
 *
 * Copyright 2001-2009, Apple Inc.
 * Copyright (c) 2006-2009 Daniel A. Steffen <[email protected]>
 * Copyright © 2001-2009 Apple Inc.
 * Copyright © 2006-2009 Daniel A. Steffen <[email protected]>
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#ifndef _TKMACWM
#define _TKMACWM
33
34
35
36
37
38
39
40

41
42
43
44
45
46
47
48
49

50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69


70
71
72
73
74
75
76
33
34
35
36
37
38
39

40
41
42
43
44
45
46
47
48

49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67


68
69
70
71
72
73
74
75
76







-
+








-
+


















-
-
+
+







				 * for this protocol arrives. The actual size
				 * of the structure varies to accommodate the
				 * needs of the actual command. THIS MUST BE
				 * THE LAST FIELD OF THE STRUCTURE. */
} ProtocolHandler;

/* The following data structure is used in the TkWmInfo to maintain a list of all of the
 * transient windows belonging to a given master.
 * transient windows belonging to a given container.
 */

typedef struct Transient {
    TkWindow *winPtr;
    int flags;
    struct Transient *nextPtr;
} Transient;

#define WITHDRAWN_BY_MASTER 0x1
#define WITHDRAWN_BY_CONTAINER 0x1

/*
 * A data structure of the following type holds window-manager-related
 * information for each top-level window in an application.
 */

typedef struct TkWmInfo {
    TkWindow *winPtr;		/* Pointer to main Tk information for this
				 * window. */
    Window reparent;		/* If the window has been reparented, this
				 * gives the ID of the ancestor of the window
				 * that is a child of the root window (may not
				 * be window's immediate parent). If the window
				 * isn't reparented, this has the value
				 * None. */
    Tk_Uid titleUid;		/* Title to display in window caption. If NULL,
				 * use name of widget. */
    char *iconName;		/* Name to display in icon. */
    Tk_Window master;		/* Master window for TRANSIENT_FOR property, or
				 * None. */
    Tk_Window container;		/* Container window for TRANSIENT_FOR property,
				 * or None. */
    XWMHints hints;		/* Various pieces of information for window
				 * manager. */
    char *leaderName;		/* Path name of leader of window group
				 * (corresponds to hints.window_group).
				 * Malloc-ed. Note: this field doesn't get
				 * updated if leader is destroyed. */
    Tk_Window icon;		/* Window to use as icon for this window, or
Changes to macosx/tkMacOSXXCursors.h.
1
2
3
4
5
6
7
8
9
10



11
12
13
14
15
16
17
1
2
3
4
5
6
7



8
9
10
11
12
13
14
15
16
17







-
-
-
+
+
+







/*
 * tkMacOSXXCursors.h --
 *
 *	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. ([email protected])
 *
 * Copyright (c) 1995-1996 Sun Microsystems, Inc.
 * Copyright 2008-2009, Apple Inc.
 * Copyright (c) 2008-2009 Daniel A. Steffen <[email protected]>
 * Copyright © 1995-1996 Sun Microsystems, Inc.
 * Copyright © 2008-2009 Apple Inc.
 * Copyright © 2008-2009 Daniel A. Steffen <[email protected]>
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

static const unsigned char tkMacOSXXCursors[][68] = {

Changes to macosx/tkMacOSXXStubs.c.
1
2
3
4
5
6
7
8
9
10
11
12




13
14
15
16
17
18
19

20
21
22
23
24
25
26
1
2
3
4
5
6
7
8




9
10
11
12
13
14
15
16
17
18

19
20
21
22
23
24
25
26








-
-
-
-
+
+
+
+






-
+







/*
 * tkMacOSXXStubs.c --
 *
 *	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 <[email protected]>
 * Copyright 2014 Marc Culler.
 * Copyright © 1995-1997 Sun Microsystems, Inc.
 * Copyright © 2001-2009, Apple Inc.
 * Copyright © 2005-2009 Daniel A. Steffen <[email protected]>
 * 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.
 */

#include "tkMacOSXPrivate.h"
#include "tkMacOSXEvent.h"
#include "tkMacOSXInt.h"

#include <IOKit/IOKitLib.h>
#include <IOKit/hidsystem/IOHIDShared.h>

/*
 * Because this file is still under major development Debugger statements are
 * used through out this file. The define TCL_DEBUG will decide whether the
163
164
165
166
167
168
169
170

171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203




































204
205







206
207
208
209
210
211
212
213
214
215
216
217


















218
219
220
221
222
223
224
163
164
165
166
167
168
169

170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188





189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234


235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278







-
+


















-
-
-
-
-










+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+












+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    }
    return 0.0;
}

/*
 *----------------------------------------------------------------------
 *
 * TkpOpenDisplay --
 * TkpOpenDisplay/XkbOpenDisplay --
 *
 *	Create the Display structure and fill it with device specific
 *	information.
 *
 * Results:
 *	Returns a Display structure on success or NULL on failure.
 *
 * Side effects:
 *	Allocates a new Display structure.
 *
 *----------------------------------------------------------------------
 */

TkDisplay *
TkpOpenDisplay(
    const char *display_name)
{
    Display *display;
    Screen *screen;
    int fd = 0;
    static NSRect maxBounds = {{0, 0}, {0, 0}};
    static char vendor[25] = "";
    NSArray *cgVers;
    NSAutoreleasePool *pool = [NSAutoreleasePool new];

    if (gMacDisplay != NULL) {
	if (strcmp(gMacDisplay->display->display_name, display_name) == 0) {
	    return gMacDisplay;
	} else {
	    return NULL;
	}
    }

    display = XkbOpenDisplay((char *)display_name, NULL, NULL, NULL, NULL, NULL);

    /*
     * Initialize screen bits that may change
     */

    TkMacOSXDisplayChanged(display);

    gMacDisplay = (TkDisplay *)ckalloc(sizeof(TkDisplay));

    /*
     * This is the quickest way to make sure that all the *Init flags get
     * properly initialized
     */

    bzero(gMacDisplay, sizeof(TkDisplay));
    gMacDisplay->display = display;
    [pool drain];

    /*
     * Key map info must be available immediately, because of "send event".
     */
    TkpInitKeymapInfo(gMacDisplay);

    return gMacDisplay;
}

Display *
XkbOpenDisplay(
    TCL_UNUSED(const char *),
	int *ev_rtrn,
	int *err_rtrn,
	int *major_rtrn,
	int *minor_rtrn,
	int *reason)
{
    display = ckalloc(sizeof(Display));
    screen  = ckalloc(sizeof(Screen));
    Display *display = (Display *)ckalloc(sizeof(Display));
    Screen *screen = (Screen *)ckalloc(sizeof(Screen));
    int fd = 0;
    NSArray *cgVers;
    static char vendor[25] = "";
    static NSRect maxBounds = {{0, 0}, {0, 0}};

    bzero(display, sizeof(Display));
    bzero(screen, sizeof(Screen));

    display->resource_alloc = MacXIdAlloc;
    display->request	    = 0;
    display->qlen	    = 0;
    display->fd		    = fd;
    display->screens	    = screen;
    display->nscreens	    = 1;
    display->default_screen = 0;
    display->display_name   = (char *) macScreenName;

    /*
     * These screen bits never change
     */
    screen->root	= ROOT_ID;
    screen->display	= display;
    screen->black_pixel = 0x00000000;
    screen->white_pixel = 0x00FFFFFF;
    screen->ext_data	= (XExtData *) &maxBounds;

    screen->root_visual = (Visual *)ckalloc(sizeof(Visual));
    screen->root_visual->visualid     = 0;
    screen->root_visual->c_class      = TrueColor;
    screen->root_visual->red_mask     = 0x00FF0000;
    screen->root_visual->green_mask   = 0x0000FF00;
    screen->root_visual->blue_mask    = 0x000000FF;
    screen->root_visual->bits_per_rgb = 24;
    screen->root_visual->map_entries  = 256;

    cgVers = [[[NSBundle bundleWithIdentifier:@"com.apple.CoreGraphics"]
	    objectForInfoDictionaryKey:@"CFBundleShortVersionString"]
	    componentsSeparatedByString:@"."];
    if ([cgVers count] >= 2) {
	display->proto_major_version = [[cgVers objectAtIndex:1] integerValue];
    }
    if ([cgVers count] >= 3) {
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

266
267
268
269

270
271

272
273

274
275
276
277
278

279
280
281
282
283
284
285
286
287
288

289
290
291
292
293
294
295
295
296
297
298
299
300
301








302









303




304


305


306





307



308






309
310
311
312
313
314
315
316







-
-
-
-
-
-
-
-

-
-
-
-
-
-
-
-
-
+
-
-
-
-
+
-
-
+
-
-
+
-
-
-
-
-
+
-
-
-

-
-
-
-
-
-
+







	major = systemVersion.majorVersion;
	minor = systemVersion.minorVersion;
	patch = systemVersion.patchVersion;
#endif
	display->release = major << 16 | minor << 8 | patch;
    }

    /*
     * These screen bits never change
     */
    screen->root	= ROOT_ID;
    screen->display	= display;
    screen->black_pixel = 0x00000000 | PIXEL_MAGIC << 24;
    screen->white_pixel = 0x00FFFFFF | PIXEL_MAGIC << 24;
    screen->ext_data	= (XExtData *) &maxBounds;

    screen->root_visual = ckalloc(sizeof(Visual));
    screen->root_visual->visualid     = 0;
    screen->root_visual->c_class      = TrueColor;
    screen->root_visual->red_mask     = 0x00FF0000;
    screen->root_visual->green_mask   = 0x0000FF00;
    screen->root_visual->blue_mask    = 0x000000FF;
    screen->root_visual->bits_per_rgb = 24;
    screen->root_visual->map_entries  = 256;

    if (ev_rtrn) *ev_rtrn = 0;
    /*
     * Initialize screen bits that may change
     */

    if (err_rtrn) *err_rtrn = 0;
    TkMacOSXDisplayChanged(display);

    if (major_rtrn) *major_rtrn = 0;
    gMacDisplay = ckalloc(sizeof(TkDisplay));

    if (minor_rtrn) *minor_rtrn = 0;
    /*
     * This is the quickest way to make sure that all the *Init flags get
     * properly initialized
     */

    if (reason) *reason = 0;
    bzero(gMacDisplay, sizeof(TkDisplay));
    gMacDisplay->display = display;
    [pool drain];

    /*
     * Key map info must be available immediately, because of "send event".
     */
    TkpInitKeymapInfo(gMacDisplay);

    return gMacDisplay;
    return display;
}

/*
 *----------------------------------------------------------------------
 *
 * TkpCloseDisplay --
 *
383
384
385
386
387
388
389
390

391
392
393
394
395
396
397
404
405
406
407
408
409
410

411
412
413
414
415
416
417
418







-
+







 *	was previously on the stack.
 *
 *----------------------------------------------------------------------
 */

static XID
MacXIdAlloc(
    Display *display)		/* Display for which to allocate. */
    TCL_UNUSED(Display *))		/* Display for which to allocate. */
{
    static long int cur_id = 100;
    /*
     * Some special XIds are reserved
     *   - this is why we start at 100
     */

413
414
415
416
417
418
419
420
421


422
423
424
425
426
427
428
429
430
431
432
433
434
435


436
437
438
439
440
441
442
443

444
445
446
447
448
449
450
451

452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469

470
471
472
473
474
475
476
477
478
479
480
481

482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501








502
503
504
505
506
507
508
509
510
511



512
513
514
515
516
517
518
519
520


521
522
523
524
525
526
527
528
529
530
531



532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552

553
554
555
556
557
558
559
560
561
562
563
564
565
566
567





568
569
570
571
572
573
574
575
576


577
578
579
580
581
582
583
434
435
436
437
438
439
440


441
442
443
444
445
446
447
448
449
450
451
452
453
454


455
456
457
458
459
460
461
462
463

464
465
466
467
468
469
470
471

472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489

490
491
492
493
494
495
496
497
498
499
500
501

502
503
504
505
506
507
508
509
510
511
512
513
514








515
516
517
518
519
520
521
522
523
524
525
526
527
528
529



530
531
532
533
534
535
536
537
538
539


540
541
542
543
544
545
546
547
548
549



550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572

573
574
575
576
577
578
579
580
581
582
583





584
585
586
587
588
589
590
591
592
593
594
595


596
597
598
599
600
601
602
603
604







-
-
+
+












-
-
+
+







-
+







-
+

















-
+











-
+












-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+







-
-
-
+
+
+







-
-
+
+








-
-
-
+
+
+




















-
+










-
-
-
-
-
+
+
+
+
+







-
-
+
+







 *	This function will call panic and exit.
 *
 *----------------------------------------------------------------------
 */

static int
DefaultErrorHandler(
    Display* display,
    XErrorEvent* err_evt)
    TCL_UNUSED(Display *),
    TCL_UNUSED(XErrorEvent *))
{
    /*
     * This call should never be called. Tk replaces it with its own error
     * handler.
     */

    Tcl_Panic("Warning hit bogus error handler!");
    return 0;
}

char *
XGetAtomName(
    Display * display,
    Atom atom)
    Display *display,
    TCL_UNUSED(Atom))
{
    display->request++;
    return NULL;
}

XErrorHandler
XSetErrorHandler(
    XErrorHandler handler)
    TCL_UNUSED(XErrorHandler))
{
    return DefaultErrorHandler;
}

Window
XRootWindow(
    Display *display,
    int screen_number)
    TCL_UNUSED(int))
{
    display->request++;
    return ROOT_ID;
}

int
XGetGeometry(
    Display *display,
    Drawable d,
    Window *root_return,
    int *x_return,
    int *y_return,
    unsigned int *width_return,
    unsigned int *height_return,
    unsigned int *border_width_return,
    unsigned int *depth_return)
{
    TkWindow *winPtr = ((MacDrawable *) d)->winPtr;
    TkWindow *winPtr = ((MacDrawable *)d)->winPtr;

    display->request++;
    *root_return = ROOT_ID;
    if (winPtr) {
	*x_return = Tk_X(winPtr);
	*y_return = Tk_Y(winPtr);
	*width_return = Tk_Width(winPtr);
	*height_return = Tk_Height(winPtr);
	*border_width_return = winPtr->changes.border_width;
	*depth_return = Tk_Depth(winPtr);
    } else {
	CGSize size = ((MacDrawable *) d)->size;
	CGSize size = ((MacDrawable *)d)->size;
	*x_return = 0;
	*y_return =  0;
	*width_return = size.width;
	*height_return = size.height;
	*border_width_return = 0;
	*depth_return = 32;
    }
    return 1;
}

int
XChangeProperty(
    Display* display,
    Window w,
    Atom property,
    Atom type,
    int format,
    int mode,
    _Xconst unsigned char* data,
    int nelements)
    TCL_UNUSED(Display *),
    TCL_UNUSED(Window),
    TCL_UNUSED(Atom),
    TCL_UNUSED(Atom),
    TCL_UNUSED(int),
    TCL_UNUSED(int),
    TCL_UNUSED(_Xconst unsigned char *),
    TCL_UNUSED(int))
{
    Debugger();
    return Success;
}

int
XSelectInput(
    Display* display,
    Window w,
    long event_mask)
    TCL_UNUSED(Display *),
    TCL_UNUSED(Window),
    TCL_UNUSED(long))
{
    Debugger();
    return Success;
}

int
XBell(
    Display* display,
    int percent)
    TCL_UNUSED(Display *),
    TCL_UNUSED(int))
{
    NSBeep();
    return Success;
}

#if 0
void
XSetWMNormalHints(
    Display* display,
    Window w,
    XSizeHints* hints)
    TCL_UNUSED(Display *),
    TCL_UNUSED(Window),
    TCL_UNUSED(XSizeHints *))
{
    /*
     * Do nothing. Shouldn't even be called.
     */
}

XSizeHints *
XAllocSizeHints(void)
{
    /*
     * Always return NULL. Tk code checks to see if NULL is returned & does
     * nothing if it is.
     */

    return NULL;
}
#endif

GContext
XGContextFromGC(
    GC gc)
    TCL_UNUSED(GC))
{
    /*
     * TODO: currently a no-op
     */

    return 0;
}

Status
XSendEvent(
    Display* display,
    Window w,
    Bool propagate,
    long event_mask,
    XEvent* event_send)
    TCL_UNUSED(Display *),
    TCL_UNUSED(Window),
    TCL_UNUSED(Bool),
    TCL_UNUSED(long),
    TCL_UNUSED(XEvent *))
{
    Debugger();
    return 0;
}

int
XClearWindow(
    Display* display,
    Window w)
    TCL_UNUSED(Display *),
    TCL_UNUSED(Window))
{
    return Success;
}

/*
int
XDrawPoint(
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616









617
618
619
620
621
622
623
624


625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642














643










































































644
645
646


647
648
649
650
651
652
653
622
623
624
625
626
627
628









629
630
631
632
633
634
635
636
637
638
639
640
641
642
643


644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753


754
755
756
757
758
759
760
761
762







-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+






-
-
+
+


















+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
+
+







{
    return Success;
}
*/

int
XWarpPointer(
    Display* display,
    Window src_w,
    Window dest_w,
    int src_x,
    int src_y,
    unsigned int src_width,
    unsigned int src_height,
    int dest_x,
    int dest_y)
    TCL_UNUSED(Display *),
    TCL_UNUSED(Window),
    TCL_UNUSED(Window),
    TCL_UNUSED(int),
    TCL_UNUSED(int),
    TCL_UNUSED(unsigned int),
    TCL_UNUSED(unsigned int),
    TCL_UNUSED(int),
    TCL_UNUSED(int))
{
    return Success;
}

int
XQueryColor(
    Display* display,
    Colormap colormap,
    TCL_UNUSED(Display *),
    TCL_UNUSED(Colormap),
    XColor* def_in_out)
{
    unsigned long p;
    unsigned char r, g, b;
    XColor *d = def_in_out;

    p		= d->pixel;
    r		= (p & 0x00FF0000) >> 16;
    g		= (p & 0x0000FF00) >> 8;
    b		= (p & 0x000000FF);
    d->red	= (r << 8) | r;
    d->green	= (g << 8) | g;
    d->blue	= (b << 8) | b;
    d->flags	= DoRed|DoGreen|DoBlue;
    d->pad	= 0;
    return Success;
}

Bool
XTranslateCoordinates(
    TCL_UNUSED(Display *),
    TCL_UNUSED(Window),
    TCL_UNUSED(Window),
    TCL_UNUSED(int),
    TCL_UNUSED(int),
    TCL_UNUSED(int *),
    TCL_UNUSED(int *),
    TCL_UNUSED(Window *))
{
    return 0;
}

int
XSetCommand(
    TCL_UNUSED(Display *),
    TCL_UNUSED(Window),
    TCL_UNUSED(char **),
    TCL_UNUSED(int))
{
    return Success;
}

int
XGetWindowAttributes(
    TCL_UNUSED(Display *),
    TCL_UNUSED(Window),
    TCL_UNUSED(XWindowAttributes *))
{
    return Success;
}

Status
XGetWMColormapWindows(
    TCL_UNUSED(Display *),
    TCL_UNUSED(Window),
    TCL_UNUSED(Window **),
    TCL_UNUSED(int *))
{
    return Success;
}

int
XIconifyWindow(
    TCL_UNUSED(Display *),
    TCL_UNUSED(Window),
    TCL_UNUSED(int))
{
    return Success;
}

XHostAddress *
XListHosts(
    TCL_UNUSED(Display *),
    TCL_UNUSED(int *),
    TCL_UNUSED(Bool *))
{
    return NULL;
}

int
XLookupColor(
    TCL_UNUSED(Display *),
    TCL_UNUSED(Colormap),
    TCL_UNUSED(_Xconst char *),
    TCL_UNUSED(XColor *),
    TCL_UNUSED(XColor *))
{
    return Success;
}

int
XNextEvent(
    TCL_UNUSED(Display *),
    TCL_UNUSED(XEvent *))
{
    return Success;
}

int
XPutBackEvent(
    TCL_UNUSED(Display *),
    TCL_UNUSED(XEvent *))
{
    return Success;
}

int
XQueryColors(
    Display* display,
    Colormap colormap,
    TCL_UNUSED(Display *),
    TCL_UNUSED(Colormap),
    XColor* defs_in_out,
    int ncolors)
{
    int i;
    unsigned long p;
    unsigned char r, g, b;
    XColor *d = defs_in_out;
663
664
665
666
667
668
669
670

671
672
673
674
675
676
677






678
679
680
681
682
683
684
685
686
687
688
689
690
691






692
693
694
695
696

697
698
699
700
701
702
703
704
705































706
707

708
709
710
711
712
713
714
715
716
717
718


719
720
721
722
723
724
725
726
727
728
729
730

731
732
733
734
735
736
737
738
739
740
741

742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769

770
771
772
773
774

775
776
777
778
779




780
781
782
783
784
785
786
787
788
789
790
791
792
793
772
773
774
775
776
777
778

779







780
781
782
783
784
785
786
787
788
789
790
791
792
793






794
795
796
797
798
799
800
801
802
803

804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845

846
847
848
849
850
851
852
853
854
855


856
857
858
859
860
861
862
863
864
865
866
867
868

869
870
871
872
873
874
875
876
877
878
879

880



















881
882
883
884
885
886
887
888

889
890
891
892
893

894
895




896
897
898
899
900
901
902
903
904


905
906
907
908
909
910
911







-
+
-
-
-
-
-
-
-
+
+
+
+
+
+








-
-
-
-
-
-
+
+
+
+
+
+




-
+









+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+









-
-
+
+











-
+










-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-








-
+




-
+

-
-
-
-
+
+
+
+





-
-







	d->flags	= DoRed|DoGreen|DoBlue;
	d->pad		= 0;
    }
    return Success;
}

int
XQueryTree(display, w, root_return, parent_return, children_return,
XQueryTree(
	nchildren_return)
    Display* display;
    Window w;
    Window* root_return;
    Window* parent_return;
    Window** children_return;
    unsigned int* nchildren_return;
    TCL_UNUSED(Display *),
    TCL_UNUSED(Window),
    TCL_UNUSED(Window *),
    TCL_UNUSED(Window *),
    TCL_UNUSED(Window **),
    TCL_UNUSED(unsigned int *))
{
    return 0;
}


int
XGetWindowProperty(
    Display *display,
    Window w,
    Atom property,
    long long_offset,
    long long_length,
    Bool delete,
    Atom req_type,
    TCL_UNUSED(Window),
    TCL_UNUSED(Atom),
    TCL_UNUSED(long),
    TCL_UNUSED(long),
    TCL_UNUSED(Bool),
    TCL_UNUSED(Atom),
    Atom *actual_type_return,
    int *actual_format_return,
    unsigned long *nitems_return,
    unsigned long *bytes_after_return,
    unsigned char ** prop_return)
    TCL_UNUSED(unsigned char **))
{
    display->request++;
    *actual_type_return = None;
    *actual_format_return = *bytes_after_return = 0;
    *nitems_return = 0;
    return 0;
}

int
XWindowEvent(
    TCL_UNUSED(Display *),
    TCL_UNUSED(Window),
    TCL_UNUSED(long),
    TCL_UNUSED(XEvent *))
{
    return Success;
}

int
XWithdrawWindow(
    TCL_UNUSED(Display *),
    TCL_UNUSED(Window),
    TCL_UNUSED(int))
{
    return Success;
}

int
XmbLookupString(
    TCL_UNUSED(XIC),
    TCL_UNUSED(XKeyPressedEvent *),
    TCL_UNUSED(char *),
    TCL_UNUSED(int),
    TCL_UNUSED(KeySym *),
    TCL_UNUSED(Status *))
{
    return Success;
}

int
XRefreshKeyboardMapping(
    XMappingEvent *x)
    TCL_UNUSED(XMappingEvent *))
{
    /* used by tkXEvent.c */
    Debugger();
    return Success;
}

int
XSetIconName(
    Display* display,
    Window w,
    const char *icon_name)
    TCL_UNUSED(Window),
    TCL_UNUSED(const char *))
{
    /*
     * This is a no-op, no icon name for Macs.
     */
    display->request++;
    return Success;
}

int
XForceScreenSaver(
    Display* display,
    int mode)
    TCL_UNUSED(int))
{
    /*
     * This function is just a no-op. It is defined to reset the screen saver.
     * However, there is no real way to do this on a Mac. Let me know if there
     * is!
     */

    display->request++;
    return Success;
}


void
Tk_FreeXId(
    Display *display,
    XID xid)
{
    /* no-op function needed for stubs implementation. */
}

int
XSync(
    Display *display,
    Bool discard)
{
    TkMacOSXFlushWindows();
    display->request++;
    return 0;
}

#if 0
int
XSetClipRectangles(
    Display *d,
    GC gc,
    int clip_x_origin,
    int clip_y_origin,
    XRectangle* rectangles,
    int n,
    int ordering)
    TCL_UNUSED(int))
{
    TkRegion clipRgn = TkCreateRegion();

    while (n--) {
	XRectangle rect = *rectangles;
    	XRectangle rect = *rectangles;

	rect.x += clip_x_origin;
	rect.y += clip_y_origin;
	TkUnionRectWithRegion(&rect, clipRgn, clipRgn);
	rectangles++;
    	rect.x += clip_x_origin;
    	rect.y += clip_y_origin;
    	TkUnionRectWithRegion(&rect, clipRgn, clipRgn);
    	rectangles++;
    }
    TkSetRegion(d, gc, clipRgn);
    TkDestroyRegion(clipRgn);
    return 1;
}
#endif

/*
 *----------------------------------------------------------------------
 *
 * TkGetServerInfo --
 *
 *	Given a window, this procedure returns information about the window
 *	server for that window. This procedure provides the guts of the "winfo
838
839
840
841
842
843
844
845
846
847
848




849
850
851
852
853
854
855
856
857



858
859
860
861
862
863
864
865
866



867
868
869
870
871
872
873
874
875



876
877
878
879
880
881
882
883
884



885
886
887
888
889
890
891
892
893



894
895
896
897
898
899
900
901
902



903
904
905
906
907
908
909
910
911
912



913
914
915

916
917
918
919
920
921
922



923
924
925
926
927
928

929
930
931
932
933








934











935
936
937
938
939
940
941
942
943
944
945
946

947
948

949
950
951
952
953
954
955

956
957
958
959







960

961
962
963
964
965
966
967
968
969
970
971
972

973
974
975
976
977
978
979
980
981
982
983
984
985
986
987

988
989
990

991
992
993
994
995
996
997
956
957
958
959
960
961
962




963
964
965
966
967
968
969
970
971
972



973
974
975
976
977
978
979
980
981



982
983
984
985
986
987
988
989
990



991
992
993
994
995
996
997
998
999



1000
1001
1002
1003
1004
1005
1006
1007
1008



1009
1010
1011
1012
1013
1014
1015
1016
1017



1018
1019
1020
1021
1022
1023
1024
1025
1026
1027



1028
1029
1030
1031
1032

1033
1034
1035
1036
1037



1038
1039
1040
1041
1042
1043
1044
1045

1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059

1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077

1078
1079
1080

1081
1082

1083
1084
1085
1086

1087
1088

1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100

1101
1102
1103
1104
1105
1106
1107
1108
1109

1110
1111

1112
1113
1114
1115
1116

1117
1118
1119
1120
1121
1122
1123
1124
1125

1126
1127
1128

1129
1130
1131
1132
1133
1134
1135
1136







-
-
-
-
+
+
+
+






-
-
-
+
+
+






-
-
-
+
+
+






-
-
-
+
+
+






-
-
-
+
+
+






-
-
-
+
+
+






-
-
-
+
+
+







-
-
-
+
+
+


-
+




-
-
-
+
+
+





-
+





+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+







-



-
+

-
+



-


-
+




+
+
+
+
+
+
+
-
+








-


-
+




-









-
+


-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

int
XChangeWindowAttributes(
    Display *display,
    Window w,
    unsigned long value_mask,
    XSetWindowAttributes *attributes)
    TCL_UNUSED(Display *),
    TCL_UNUSED(Window),
    TCL_UNUSED(unsigned long),
    TCL_UNUSED(XSetWindowAttributes *))
{
    return Success;
}

int
XSetWindowBackground(
    Display *display,
    Window window,
    unsigned long value)
    TCL_UNUSED(Display *),
    TCL_UNUSED(Window),
    TCL_UNUSED(unsigned long))
{
    return Success;
}

int
XSetWindowBackgroundPixmap(
    Display *display,
    Window w,
    Pixmap background_pixmap)
    TCL_UNUSED(Display *),
    TCL_UNUSED(Window),
    TCL_UNUSED(Pixmap))
{
    return Success;
}

int
XSetWindowBorder(
    Display *display,
    Window w,
    unsigned long border_pixel)
    TCL_UNUSED(Display *),
    TCL_UNUSED(Window),
    TCL_UNUSED(unsigned long))
{
    return Success;
}

int
XSetWindowBorderPixmap(
    Display *display,
    Window w,
    Pixmap border_pixmap)
    TCL_UNUSED(Display *),
    TCL_UNUSED(Window),
    TCL_UNUSED(Pixmap))
{
    return Success;
}

int
XSetWindowBorderWidth(
    Display *display,
    Window w,
    unsigned int width)
    TCL_UNUSED(Display *),
    TCL_UNUSED(Window),
    TCL_UNUSED(unsigned int))
{
    return Success;
}

int
XSetWindowColormap(
    Display *display,
    Window w,
    Colormap colormap)
    TCL_UNUSED(Display *),
    TCL_UNUSED(Window),
    TCL_UNUSED(Colormap))
{
    Debugger();
    return Success;
}

Status
XStringListToTextProperty(
    char **list,
    int count,
    XTextProperty *text_prop_return)
    TCL_UNUSED(char **),
    TCL_UNUSED(int),
    TCL_UNUSED(XTextProperty *))
{
    Debugger();
    return (Status) 0;
    return Success;
}

void
XSetWMClientMachine(
    Display *display,
    Window w,
    XTextProperty *text_prop)
    TCL_UNUSED(Display *),
    TCL_UNUSED(Window),
    TCL_UNUSED(XTextProperty *))
{
    Debugger();
}

XIC
XCreateIC(XIM xim, ...)
XCreateIC(TCL_UNUSED(XIM), ...)
{
    Debugger();
    return (XIC) 0;
}

int
XDeleteProperty(
    TCL_UNUSED(Display *),
    TCL_UNUSED(Window),
    TCL_UNUSED(Atom))
{
    return Success;
}
#undef XVisualIDFromVisual

int
XGetInputFocus(
    Display *display,
    TCL_UNUSED(Window *),
    TCL_UNUSED(int *))
{
    display->request++;
    return Success;
}

VisualID
XVisualIDFromVisual(
    Visual *visual)
{
    return visual->visualid;
}

#undef XSynchronize
XAfterFunction
XSynchronize(
    Display *display,
    Bool onoff)
    TCL_UNUSED(Bool))
{
	display->request++;
    display->request++;
    return NULL;
}

#undef XUngrabServer
int
XUngrabServer(
    Display *display)
    TCL_UNUSED(Display *))
{
    return 0;
}

int
XFreeCursor(
    TCL_UNUSED(Display *),
    TCL_UNUSED(Cursor))
{
    return Success;
}
#undef XNoOp

int
XNoOp(
    Display *display)
{
	display->request++;
    return 0;
}

#undef XGrabServer
int
XGrabServer(
    Display *display)
    TCL_UNUSED(Display *))
{
    return 0;
}

#undef XFree
int
XFree(
    void *data)
{
	if ((data) != NULL) {
		ckfree(data);
	}
    return 0;
}
#undef XFlush

int
XFlush(
    Display *display)
    TCL_UNUSED(Display *))
{
    return 0;
}

/*
 *----------------------------------------------------------------------
 *
1007
1008
1009
1010
1011
1012
1013
1014

1015
1016
1017
1018
1019
1020
1021
1146
1147
1148
1149
1150
1151
1152

1153
1154
1155
1156
1157
1158
1159
1160







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

const char *
TkGetDefaultScreenName(
    Tcl_Interp *interp,		/* Not used. */
    TCL_UNUSED(Tcl_Interp *),
    const char *screenName)		/* If NULL, use default string. */
{
    if ((screenName == NULL) || (screenName[0] == '\0')) {
	screenName = macScreenName;
    }
    return screenName;
}
1034
1035
1036
1037
1038
1039
1040
1041

1042
1043
1044
1045
1046
1047
1048
1049
1050

1051
1052
1053
1054
1055
1056
1057
1173
1174
1175
1176
1177
1178
1179

1180
1181
1182
1183
1184
1185
1186
1187
1188

1189
1190
1191
1192
1193
1194
1195
1196







-
+








-
+







 * Side effects:
 *	None.
 *----------------------------------------------------------------------
 */

long
Tk_GetUserInactiveTime(
    Display *dpy)
    TCL_UNUSED(Display *))
{
    io_registry_entry_t regEntry;
    CFMutableDictionaryRef props = NULL;
    CFTypeRef timeObj;
    long ret = -1l;
    uint64_t time;
    IOReturn result;

    regEntry = IOServiceGetMatchingService(kIOMasterPortDefault,
    regEntry = IOServiceGetMatchingService(0,
	    IOServiceMatching("IOHIDSystem"));

    if (regEntry == 0) {
	return -1l;
    }

    result = IORegistryEntryCreateCFProperties(regEntry, &props,
1100
1101
1102
1103
1104
1105
1106
1107

1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1239
1240
1241
1242
1243
1244
1245

1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258







-
+












 *	to zero.
 *
 *----------------------------------------------------------------------
 */

void
Tk_ResetUserInactiveTime(
    Display *dpy)
    TCL_UNUSED(Display *))
{
    lastInactivityReset = TkpGetMS();
}

/*
 * Local Variables:
 * mode: objc
 * c-basic-offset: 4
 * fill-column: 79
 * coding: utf-8
 * End:
 */
Changes to macosx/ttkMacOSXTheme.c.
1
2
3
4
5
6
7
8
9
10
11






12
13
14
15
16
17
18
1
2
3
4
5






6
7
8
9
10
11
12
13
14
15
16
17
18





-
-
-
-
-
-
+
+
+
+
+
+







/*
 * 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 <[email protected]>
 * 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 <[email protected]>
 * 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:
 *
 * <URL: http://developer.apple.com/documentation/Carbon/Reference/
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

43
44
45
46
47
48
49
27
28
29
30
31
32
33

34
35
36
37
38
39
40

41
42
43
44
45
46
47
48







-







-
+







 *
 *      The QuickDraw/Carbon coordinate system is relative to the top-level
 *      window, not to the Tk_Window.  BoxToRect() accounts for this.
 */

#include "tkMacOSXPrivate.h"
#include "ttk/ttkTheme.h"
#include <math.h>

/*
 * Macros for handling drawing contexts.
 */

#define BEGIN_DRAWING(d) {	   \
	TkMacOSXDrawingContext dc; \
	if (!TkMacOSXSetupDrawingContext((d), NULL, 1, &dc)) {return;}
	if (!TkMacOSXSetupDrawingContext((d), NULL, &dc)) {return;}
#define END_DRAWING \
    TkMacOSXRestoreDrawingContext(&dc);}

#define HIOrientation kHIThemeOrientationNormal
#define NoThemeMetric 0xFFFFFFFF

#ifdef __LP64__
149
150
151
152
153
154
155
156

157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172

173
174
175
176
177
178
179
148
149
150
151
152
153
154

155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170

171
172
173
174
175
176
177
178







-
+















-
+







 *    to a native Rect relative to the containing port.
 */

static inline CGRect BoxToRect(
    Drawable d,
    Ttk_Box b)
{
    MacDrawable *md = (MacDrawable *) d;
    MacDrawable *md = (MacDrawable *)d;
    CGRect rect;

    rect.origin.y       = b.y + md->yOff;
    rect.origin.x       = b.x + md->xOff;
    rect.size.height    = b.height;
    rect.size.width     = b.width;

    return rect;
}

/*
 * Table mapping Tk states to Appearance manager ThemeStates
 */

static Ttk_StateTable ThemeStateTable[] = {
    {kThemeStateActive, TTK_STATE_ALTERNATE | TTK_STATE_BACKGROUND},
    {kThemeStateActive, TTK_STATE_ALTERNATE | TTK_STATE_BACKGROUND, 0},
    {kThemeStateUnavailable, TTK_STATE_DISABLED, 0},
    {kThemeStatePressed, TTK_STATE_PRESSED, 0},
    {kThemeStateInactive, TTK_STATE_BACKGROUND, 0},
    {kThemeStateActive, 0, 0}

    /* Others: Not sure what these are supposed to mean.  Up/Down have
     * something to do with "little arrow" increment controls...  Dunno what
228
229
230
231
232
233
234
235

236
237
238
239


240
241
242
243
244
245
246
247
248
249





250
251
252
253

254
255
256
257
258
259


260
261
262


263
264
265

266
267

268
269

270
271
272

273
274
275
276
277
278
279

280
281
282
283
284
285
286
227
228
229
230
231
232
233

234
235
236


237
238
239
240
241
242
243





244
245
246
247
248
249
250
251

252
253
254
255
256


257
258
259


260
261
262
263

264
265

266
267

268
269
270

271
272
273
274
275
276
277

278
279
280
281
282
283
284
285







-
+


-
-
+
+





-
-
-
-
-
+
+
+
+
+



-
+




-
-
+
+

-
-
+
+


-
+

-
+

-
+


-
+






-
+







 * For systems older than 10.14, [NSColor windowBackGroundColor] generates
 * garbage when called from this function.  In 10.14 it works correctly, and
 * must be used in order to have a background color which responds to Dark
 * Mode.  So we use this hard-wired RGBA color on the older systems which don't
 * support Dark Mode anyway.
 */

static CGFloat windowBackground[4] = {
static const CGFloat WINDOWBACKGROUND[4] = {
    235.0 / 255, 235.0 / 255, 235.0 / 255, 1.0
};
static CGFloat whiteRGBA[4] = {1.0, 1.0, 1.0, 1.0};
static CGFloat blackRGBA[4] = {0.0, 0.0, 0.0, 1.0};
static const CGFloat WHITERGBA[4] = {1.0, 1.0, 1.0, 1.0};
static const CGFloat BLACKRGBA[4] = {0.0, 0.0, 0.0, 1.0};

/*----------------------------------------------------------------------
 * GetBackgroundColor --
 *
 *      Fills the array rgba with the color coordinates for a background color.
 *      Start with the background color of a window's geometry master, or the
 *      standard ttk window background if there is no master. If the contrast
 *      parameter is nonzero, modify this color to be darker, for the aqua
 *      appearance, or lighter for the DarkAqua appearance.  This is primarily
 *      used by the Fill and Background elements.
 *      Start with the background color of a window's geometry container, or
 *      the standard ttk window background if there is no container. If the
 *      contrast parameter is nonzero, modify this color to be darker, for the
 *      aqua appearance, or lighter for the DarkAqua appearance.  This is
 *      primarily used by the Fill and Background elements.
 */

static void GetBackgroundColor(
    CGContextRef context,
    TCL_UNUSED(CGContextRef),
    Tk_Window tkwin,
    int contrast,
    CGFloat *rgba)
{
    TkWindow *winPtr = (TkWindow *) tkwin;
    TkWindow *masterPtr = (TkWindow *) TkGetGeomMaster(tkwin);
    TkWindow *winPtr = (TkWindow *)tkwin;
    TkWindow *containerPtr = (TkWindow *)TkGetContainer(tkwin);

    while (masterPtr && masterPtr->privatePtr) {
	if (masterPtr->privatePtr->flags & TTK_HAS_CONTRASTING_BG) {
    while (containerPtr && containerPtr->privatePtr) {
	if (containerPtr->privatePtr->flags & TTK_HAS_CONTRASTING_BG) {
	    break;
	}
	masterPtr = (TkWindow *) TkGetGeomMaster(masterPtr);
	containerPtr = (TkWindow *)TkGetContainer(containerPtr);
    }
    if (masterPtr && masterPtr->privatePtr) {
    if (containerPtr && containerPtr->privatePtr) {
	for (int i = 0; i < 4; i++) {
	    rgba[i] = masterPtr->privatePtr->fillRGBA[i];
	    rgba[i] = containerPtr->privatePtr->fillRGBA[i];
	}
    } else {
	if ([NSApp macMinorVersion] > 13) {
	if ([NSApp macOSVersion] > 101300) {
	    NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
	    NSColor *windowColor = [[NSColor windowBackgroundColor]
		colorUsingColorSpace: deviceRGB];
	    [windowColor getComponents: rgba];
	} else {
	    for (int i = 0; i < 4; i++) {
		rgba[i] = windowBackground[i];
		rgba[i] = WINDOWBACKGROUND[i];
	    }
	}
    }
    if (contrast) {
	int isDark = (rgba[0] + rgba[1] + rgba[2] < 1.5);

	if (isDark) {
299
300
301
302
303
304
305
306

307
308


309
310
311
312
313
314
315
316

317
318
319
320
321
322
323
298
299
300
301
302
303
304

305
306

307
308
309
310
311
312
313
314
315

316
317
318
319
320
321
322
323







-
+

-
+
+







-
+







            }
        }
    }
}


/*----------------------------------------------------------------------
 * +++ Single Arrow Buttons --
 * +++ Single Arrow Images --
 *
 * Used in ListHeaders and Comboboxes.
 * Used in ListHeaders and Comboboxes as well as disclosure triangles in
 * macOS 11.
 */

static void DrawDownArrow(
    CGContextRef context,
    CGRect bounds,
    CGFloat inset,
    CGFloat size,
    CGFloat *rgba)
    const CGFloat *rgba)
{
    CGFloat x, y;

    CGContextSetRGBStrokeColor(context, rgba[0], rgba[1], rgba[2], rgba[3]);
    CGContextSetLineWidth(context, 1.5);
    x = bounds.origin.x + inset;
    y = bounds.origin.y + trunc(bounds.size.height / 2);
331
332
333
334
335
336
337
338

339
340
341
342
343
344
345
346
347
348
349
350
351
352
353










































354
355
356
357
358
359
360
361
362
363
364
365
366

367
368
369
370
371
372
373
331
332
333
334
335
336
337

338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407

408
409
410
411
412
413
414
415







-
+















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+












-
+







}

static void DrawUpArrow(
    CGContextRef context,
    CGRect bounds,
    CGFloat inset,
    CGFloat size,
    CGFloat *rgba)
    const CGFloat *rgba)
{
    CGFloat x, y;

    CGContextSetRGBStrokeColor(context, rgba[0], rgba[1], rgba[2], rgba[3]);
    CGContextSetLineWidth(context, 1.5);
    x = bounds.origin.x + inset;
    y = bounds.origin.y + trunc(bounds.size.height / 2);
    CGContextBeginPath(context);
    CGPoint arrow[3] = {
	{x, y + size / 4}, {x + size / 2, y - size / 4},
	{x + size, y + size / 4}
    };
    CGContextAddLines(context, arrow, 3);
    CGContextStrokePath(context);
}

static void DrawClosedDisclosure(
    CGContextRef context,
    CGRect bounds,
    CGFloat inset,
    CGFloat size,
    CGFloat *rgba)
{
    CGFloat x, y;

    CGContextSetRGBStrokeColor(context, rgba[0], rgba[1], rgba[2], rgba[3]);
    CGContextSetLineWidth(context, 1.5);
    x = bounds.origin.x + inset;
    y = bounds.origin.y + trunc(bounds.size.height / 2);
    CGContextBeginPath(context);
    CGPoint arrow[3] = {
	{x, y - size / 4 - 1}, {x + size / 2, y}, {x, y + size / 4 + 1}
    };
    CGContextAddLines(context, arrow, 3);
    CGContextStrokePath(context);
}

static void DrawOpenDisclosure(
    CGContextRef context,
    CGRect bounds,
    CGFloat inset,
    CGFloat size,
    CGFloat *rgba)
{
    CGFloat x, y;

    CGContextSetRGBStrokeColor(context, rgba[0], rgba[1], rgba[2], rgba[3]);
    CGContextSetLineWidth(context, 1.5);
    x = bounds.origin.x + inset;
    y = bounds.origin.y + trunc(bounds.size.height / 2);
    CGContextBeginPath(context);
    CGPoint arrow[3] = {
	{x, y - size / 4}, {x + size / 2, y + size / 2}, {x + size, y - size / 4}
    };
    CGContextAddLines(context, arrow, 3);
    CGContextStrokePath(context);
}

/*----------------------------------------------------------------------
 * +++ Double Arrow Buttons --
 *
 * Used in MenuButtons and SpinButtons.
 */

static void DrawUpDownArrows(
    CGContextRef context,
    CGRect bounds,
    CGFloat inset,
    CGFloat size,
    CGFloat *rgba)
    const CGFloat *rgba)
{
    CGFloat x, y;

    CGContextSetRGBStrokeColor(context, rgba[0], rgba[1], rgba[2], rgba[3]);
    CGContextSetLineWidth(context, 1.5);
    x = bounds.origin.x + inset;
    y = bounds.origin.y + trunc(bounds.size.height / 2);
497
498
499
500
501
502
503

504



505

506
507
508
509
510
511
512
513
514
539
540
541
542
543
544
545
546
547
548
549
550

551
552

553
554
555
556
557
558
559







+

+
+
+
-
+

-







static void SolidFillRoundedRectangle(
    CGContextRef context,
    CGRect bounds,
    CGFloat radius,
    NSColor *color)
{
    CGPathRef path;

    CHECK_RADIUS(radius, bounds)
    path = CGPathCreateWithRoundedRect(bounds, radius, radius, NULL);
    if (!path) {
	return;

    }
    CGContextSetFillColorWithColor(context, CGCOLOR(color));
    path = CGPathCreateWithRoundedRect(bounds, radius, radius, NULL);
    CGContextBeginPath(context);
    CGContextAddPath(context, path);
    CGContextFillPath(context);
    CFRelease(path);
}

/*----------------------------------------------------------------------
543
544
545
546
547
548
549
550

551
552
553
554
555
556
557
588
589
590
591
592
593
594

595
596
597
598
599
600
601
602







-
+








    /*
     * Apple changes the background of a list header when the window is not
     * active.  But Ttk does not indicate that in the state of a TreeHeader.
     * So we have to query the Apple window manager.
     */

    NSWindow *win = TkMacOSXDrawableWindow(Tk_WindowId(tkwin));
    NSWindow *win = TkMacOSXGetNSWindowForDrawable(Tk_WindowId(tkwin));
    CGFloat *bgRGBA = [win isKeyWindow] ? activeBgRGBA : inactiveBgRGBA;
    CGFloat x = bounds.origin.x, y = bounds.origin.y;
    CGFloat w = bounds.size.width, h = bounds.size.height;
    CGPoint top[2] = {{x, y + 1}, {x + w, y + 1}};
    CGPoint bottom[2] = {{x, y + h}, {x + w, y + h}};
    CGPoint separator[2] = {{x + w - 1, y + 3}, {x + w - 1, y + h - 3}};

583
584
585
586
587
588
589
590

591
592

593
594
595
596
597
598
599
628
629
630
631
632
633
634

635
636

637
638
639
640
641
642
643
644







-
+

-
+







    CGContextRestoreGState(context);

    if (state & TTK_TREEVIEW_STATE_SORTARROW) {
	CGRect arrowBounds = bounds;
	arrowBounds.origin.x = bounds.origin.x + bounds.size.width - 16;
	arrowBounds.size.width = 16;
	if (state & TTK_STATE_ALTERNATE) {
	    DrawUpArrow(context, arrowBounds, 3, 8, blackRGBA);
	    DrawUpArrow(context, arrowBounds, 3, 8, BLACKRGBA);
	} else if (state & TTK_STATE_SELECTED) {
	    DrawDownArrow(context, arrowBounds, 3, 8, blackRGBA);
	    DrawDownArrow(context, arrowBounds, 3, 8, BLACKRGBA);
	}
    }
}

/*----------------------------------------------------------------------
 * +++ Drawing procedures for widgets in Apple's "Dark Mode" (10.14 and up).
 *
707
708
709
710
711
712
713
714

715
716

717
718
719
720
721
722
723
752
753
754
755
756
757
758

759
760

761
762
763
764
765
766
767
768







-
+

-
+








	if (!(state & TTK_STATE_BACKGROUND) &&
	    !(state & TTK_STATE_DISABLED)) {
	    GradientFillRoundedRectangle(context, arrowBounds, 4,
		darkSelectedGradient, 2);
	}
	if (kind == kThemePopupButton) {
	    DrawUpDownArrows(context, arrowBounds, 3, 7, whiteRGBA);
	    DrawUpDownArrows(context, arrowBounds, 3, 7, WHITERGBA);
	} else {
	    DrawDownArrow(context, arrowBounds, 4, 8, whiteRGBA);
	    DrawDownArrow(context, arrowBounds, 4, 8, WHITERGBA);
	}
    }

    HighlightButtonBorder(context, bounds);
}

/*----------------------------------------------------------------------
768
769
770
771
772
773
774
775

776
777
778
779
780
781
782
813
814
815
816
817
818
819

820
821
822
823
824
825
826
827







-
+







	    clip.origin.y += clip.size.height;
	}
	CGContextClipToRect(context, clip);
	GradientFillRoundedRectangle(context, bounds, 5,
	    darkSelectedGradient, 2);
	CGContextRestoreGState(context);
    }
    DrawUpDownArrows(context, bounds, 3, 5, whiteRGBA);
    DrawUpDownArrows(context, bounds, 3, 5, WHITERGBA);
    HighlightButtonBorder(context, bounds);
}

/*----------------------------------------------------------------------
 * +++ DrawDarkBevelButton --
 *
 *      This is a standalone drawing procedure which draws RoundedBevelButtons
1035
1036
1037
1038
1039
1040
1041
1042

1043
1044
1045
1046
1047
1048
1049
1080
1081
1082
1083
1084
1085
1086

1087
1088
1089
1090
1091
1092
1093
1094







-
+







 *      This is a standalone drawing procedure which draws a separator widget
 *      in Dark Mode.
 */

static void DrawDarkSeparator(
    CGRect bounds,
    CGContextRef context,
    Tk_Window tkwin)
    TCL_UNUSED(Tk_Window))
{
    static CGFloat fill[4] = {1.0, 1.0, 1.0, 0.3};
    NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
    NSColor *fillColor = [NSColor colorWithColorSpace: deviceRGB
	components: fill
	count:4];

1161
1162
1163
1164
1165
1166
1167
1168

1169
1170
1171
1172
1173
1174
1175
1176

1177

1178
1179

1180
1181
1182
1183
1184
1185
1186
1187
1206
1207
1208
1209
1210
1211
1212

1213
1214
1215
1216
1217
1218
1219
1220
1221
1222

1223
1224

1225

1226
1227
1228
1229
1230
1231
1232







-
+








+
-
+

-
+
-







 *      This is a standalone drawing procedure which draws column
 *      headers for a Treeview in the Dark Mode.
 */

static void DrawDarkListHeader(
    CGRect bounds,
    CGContextRef context,
    Tk_Window tkwin,
    TCL_UNUSED(Tk_Window),
    int state)
{
    NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
    NSColor *stroke;

    CGContextSetStrokeColorSpace(context, deviceRGB.CGColorSpace);
    CGFloat x = bounds.origin.x, y = bounds.origin.y;
    CGFloat w = bounds.size.width, h = bounds.size.height;

    CGPoint top[2] = {{x, y}, {x + w, y}};
    CGPoint top[2] = {{x, y + 1}, {x + w, y + 1}};
    CGPoint bottom[2] = {{x, y + h}, {x + w, y + h}};
    CGPoint separator[2] = {{x + w, y + 3}, {x + w, y + h - 3}};
    CGPoint separator[2] = {{x + w - 1, y + 3}, {x + w - 1, y + h - 3}};

    CGContextSaveGState(context);
    CGContextSetShouldAntialias(context, false);
    stroke = [NSColor colorWithColorSpace: deviceRGB
	components: darkFrameBottom
	count: 4];
    CGContextSetStrokeColorWithColor(context, CGCOLOR(stroke));
    CGContextBeginPath(context);
1195
1196
1197
1198
1199
1200
1201
1202

1203
1204

1205
1206
1207
1208
1209
1210
1211
1240
1241
1242
1243
1244
1245
1246

1247
1248

1249
1250
1251
1252
1253
1254
1255
1256







-
+

-
+








    if (state & TTK_TREEVIEW_STATE_SORTARROW) {
	CGRect arrowBounds = bounds;

	arrowBounds.origin.x = bounds.origin.x + bounds.size.width - 16;
	arrowBounds.size.width = 16;
	if (state & TTK_STATE_ALTERNATE) {
	    DrawUpArrow(context, arrowBounds, 3, 8, whiteRGBA);
	    DrawUpArrow(context, arrowBounds, 3, 8, WHITERGBA);
	} else if (state & TTK_STATE_SELECTED) {
	    DrawDownArrow(context, arrowBounds, 3, 8, whiteRGBA);
	    DrawDownArrow(context, arrowBounds, 3, 8, WHITERGBA);
	}
    }
}

/*----------------------------------------------------------------------
 * +++ Button element: Used for elements drawn with DrawThemeButton.
 */
1227
1228
1229
1230
1231
1232
1233
1234

1235
1236
1237
1238
1239
1240
1241
1272
1273
1274
1275
1276
1277
1278

1279
1280
1281
1282
1283
1284
1285
1286







-
+







    PopupButtonParams = {kThemePopupButton, kThemeMetricPopupButtonHeight},
    DisclosureParams =  {
    kThemeDisclosureButton, kThemeMetricDisclosureTriangleHeight
},
    ListHeaderParams =
{kThemeListHeaderButton, kThemeMetricListHeaderHeight};
static Ttk_StateTable ButtonValueTable[] = {
    {kThemeButtonOff, TTK_STATE_ALTERNATE | TTK_STATE_BACKGROUND},
    {kThemeButtonOff, TTK_STATE_ALTERNATE | TTK_STATE_BACKGROUND, 0},
    {kThemeButtonMixed, TTK_STATE_ALTERNATE, 0},
    {kThemeButtonOn, TTK_STATE_SELECTED, 0},
    {kThemeButtonOff, 0, 0}

    /*
     * Others: kThemeDisclosureRight, kThemeDisclosureDown,
     * kThemeDisclosureLeft
1256
1257
1258
1259
1260
1261
1262
1263

1264
1265
1266
1267
1268
1269
1270
1301
1302
1303
1304
1305
1306
1307

1308
1309
1310
1311
1312
1313
1314
1315







-
+







 *
 *      Fill in an appearance manager HIThemeButtonDrawInfo record.
 */

static inline HIThemeButtonDrawInfo computeButtonDrawInfo(
    ThemeButtonParams *params,
    Ttk_State state,
    Tk_Window tkwin)
    TCL_UNUSED(Tk_Window))
{

    /*
     * See ButtonElementDraw for the explanation of why we always draw
     * PushButtons in the active state.
     */

1292
1293
1294
1295
1296
1297
1298
1299
1300


1301
1302
1303

1304
1305

1306
1307
1308

1309
1310
1311
1312
1313
1314
1315
1337
1338
1339
1340
1341
1342
1343


1344
1345
1346
1347

1348
1349

1350
1351
1352

1353
1354
1355
1356
1357
1358
1359
1360







-
-
+
+


-
+

-
+


-
+








/*----------------------------------------------------------------------
 * +++ Button elements.
 */

static void ButtonElementMinSize(
    void *clientData,
    void *elementRecord,
    Tk_Window tkwin,
    TCL_UNUSED(void *),
    TCL_UNUSED(Tk_Window),
    int *minWidth,
    int *minHeight,
    Ttk_Padding *paddingPtr)
    TCL_UNUSED(Ttk_Padding *))
{
    ThemeButtonParams *params = clientData;
    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.
         */

1370
1371
1372
1373
1374
1375
1376
1377

1378
1379
1380
1381
1382
1383
1384
1415
1416
1417
1418
1419
1420
1421

1422
1423
1424
1425
1426
1427
1428
1429







-
+







	CGRectGetMaxX(backgroundBounds) - CGRectGetMaxX(contentBounds);
    verticalPad = backgroundBounds.size.height - contentBounds.size.height;
    paddingPtr->top = paddingPtr->bottom = verticalPad / 2;
}

static void ButtonElementDraw(
    void *clientData,
    void *elementRecord,
    TCL_UNUSED(void *),
    Tk_Window tkwin,
    Drawable d,
    Ttk_Box b,
    Ttk_State state)
{
    ThemeButtonParams *params = clientData;
    CGRect bounds = BoxToRect(d, b);
1405
1406
1407
1408
1409
1410
1411
1412

1413
1414
1415
1416
1417
1418
1419
1450
1451
1452
1453
1454
1455
1456

1457
1458
1459
1460
1461
1462
1463
1464







-
+







	default:
	    ChkErr(HIThemeDrawButton, &bounds, &info, dc.context,
		HIOrientation, NULL);
	}
    } else if (info.kind == kThemePushButton &&
	       (state & TTK_STATE_PRESSED)) {
	bounds.size.height += 2;
	if ([NSApp macMinorVersion] > 8) {
	if ([NSApp macOSVersion] > 100800) {
	    GradientFillRoundedRectangle(dc.context, bounds, 4,
					 pressedPushButtonGradient, 2);
	}
    } else {

        /*
         * Apple's PushButton and PopupButton do not change their fill color
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473







1474
1475
1476
1477
1478
1479




1480
1481
1482
1483
1484
1485




1486
1487
1488
1489
1490
1491
1492
1505
1506
1507
1508
1509
1510
1511







1512
1513
1514
1515
1516
1517
1518
1519
1520




1521
1522
1523
1524
1525
1526




1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537







-
-
-
-
-
-
-
+
+
+
+
+
+
+


-
-
-
-
+
+
+
+


-
-
-
-
+
+
+
+








/*----------------------------------------------------------------------
 * +++ Notebook elements.
 */

/* Tab position logic, c.f. ttkNotebook.c TabState() */
static Ttk_StateTable TabStyleTable[] = {
    {kThemeTabFrontInactive, TTK_STATE_SELECTED | TTK_STATE_BACKGROUND},
    {kThemeTabNonFrontInactive, TTK_STATE_BACKGROUND},
    {kThemeTabFrontUnavailable, TTK_STATE_DISABLED | TTK_STATE_SELECTED},
    {kThemeTabNonFrontUnavailable, TTK_STATE_DISABLED},
    {kThemeTabFront, TTK_STATE_SELECTED},
    {kThemeTabNonFrontPressed, TTK_STATE_PRESSED},
    {kThemeTabNonFront, 0}
    {kThemeTabFrontInactive, TTK_STATE_SELECTED | TTK_STATE_BACKGROUND, 0},
    {kThemeTabNonFrontInactive, TTK_STATE_BACKGROUND, 0},
    {kThemeTabFrontUnavailable, TTK_STATE_DISABLED | TTK_STATE_SELECTED, 0},
    {kThemeTabNonFrontUnavailable, TTK_STATE_DISABLED, 0},
    {kThemeTabFront, TTK_STATE_SELECTED, 0},
    {kThemeTabNonFrontPressed, TTK_STATE_PRESSED, 0},
    {kThemeTabNonFront, 0, 0}
};
static Ttk_StateTable TabAdornmentTable[] = {
    {kHIThemeTabAdornmentNone, TTK_STATE_FIRST_TAB | TTK_STATE_LAST_TAB},
    {kHIThemeTabAdornmentTrailingSeparator, TTK_STATE_FIRST_TAB},
    {kHIThemeTabAdornmentNone, TTK_STATE_LAST_TAB},
    {kHIThemeTabAdornmentTrailingSeparator, 0},
    {kHIThemeTabAdornmentNone, TTK_STATE_FIRST_TAB | TTK_STATE_LAST_TAB, 0},
    {kHIThemeTabAdornmentTrailingSeparator, TTK_STATE_FIRST_TAB, 0},
    {kHIThemeTabAdornmentNone, TTK_STATE_LAST_TAB, 0},
    {kHIThemeTabAdornmentTrailingSeparator, 0, 0},
};
static Ttk_StateTable TabPositionTable[] = {
    {kHIThemeTabPositionOnly, TTK_STATE_FIRST_TAB | TTK_STATE_LAST_TAB},
    {kHIThemeTabPositionFirst, TTK_STATE_FIRST_TAB},
    {kHIThemeTabPositionLast, TTK_STATE_LAST_TAB},
    {kHIThemeTabPositionMiddle, 0},
    {kHIThemeTabPositionOnly, TTK_STATE_FIRST_TAB | TTK_STATE_LAST_TAB, 0},
    {kHIThemeTabPositionFirst, TTK_STATE_FIRST_TAB, 0},
    {kHIThemeTabPositionLast, TTK_STATE_LAST_TAB, 0},
    {kHIThemeTabPositionMiddle, 0, 0},
};

/*
 * Apple XHIG Tab View Specifications:
 *
 * Control sizes: Tab views are available in regular, small, and mini sizes.
 * The tab height is fixed for each size, but you control the size of the pane
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532




1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543


1544
1545
1546
1547
1548
1549
1550
1567
1568
1569
1570
1571
1572
1573




1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586


1587
1588
1589
1590
1591
1592
1593
1594
1595







-
-
-
-
+
+
+
+









-
-
+
+







 *
 * <URL: http://developer.apple.com/documentation/userexperience/Conceptual/
 *       AppleHIGuidelines/XHIGControls/XHIGControls.html#//apple_ref/doc/uid/
 *       TP30000359-TPXREF116>
 */

static void TabElementSize(
    void *clientData,
    void *elementRecord,
    Tk_Window tkwin,
    int *minWidth,
    TCL_UNUSED(void *),
    TCL_UNUSED(void *),
    TCL_UNUSED(Tk_Window),
    TCL_UNUSED(int *),
    int *minHeight,
    Ttk_Padding *paddingPtr)
{
    GetThemeMetric(kThemeMetricLargeTabHeight, (SInt32 *) minHeight);
    *paddingPtr = Ttk_MakePadding(0, 0, 0, 2);

}

static void TabElementDraw(
    void *clientData,
    void *elementRecord,
    TCL_UNUSED(void *),
    TCL_UNUSED(void *),
    Tk_Window tkwin,
    Drawable d,
    Ttk_Box b,
    Ttk_State state)
{
    CGRect bounds = BoxToRect(d, b);
    HIThemeTabDrawInfo info = {
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587





1588
1589
1590
1591
1592
1593
1594
1595


1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606

1607
1608
1609
1610
1611
1612
1613
1621
1622
1623
1624
1625
1626
1627





1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638


1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650

1651
1652
1653
1654
1655
1656
1657
1658







-
-
-
-
-
+
+
+
+
+






-
-
+
+










-
+







};

/*
 * Notebook panes:
 */

static void PaneElementSize(
    void *clientData,
    void *elementRecord,
    Tk_Window tkwin,
    int *minWidth,
    int *minHeight,
    TCL_UNUSED(void *),
    TCL_UNUSED(void *),
    TCL_UNUSED(Tk_Window),
    TCL_UNUSED(int *),
    TCL_UNUSED(int *),
    Ttk_Padding *paddingPtr)
{
    *paddingPtr = Ttk_MakePadding(9, 5, 9, 9);
}

static void PaneElementDraw(
    void *clientData,
    void *elementRecord,
    TCL_UNUSED(void *),
    TCL_UNUSED(void *),
    Tk_Window tkwin,
    Drawable d,
    Ttk_Box b,
    Ttk_State state)
{
    CGRect bounds = BoxToRect(d, b);

    bounds.origin.y -= kThemeMetricTabFrameOverlap;
    bounds.size.height += kThemeMetricTabFrameOverlap;
    BEGIN_DRAWING(d)
    if ([NSApp macMinorVersion] > 8) {
    if ([NSApp macOSVersion] > 100800) {
	DrawGroupBox(bounds, dc.context, tkwin);
    } else {
	HIThemeTabPaneDrawInfo info = {
	    .version = 1,
	    .state = Ttk_StateTableLookup(ThemeStateTable, state),
	    .direction = kThemeTabNorth,
	    .size = kHIThemeTabSizeNormal,
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648





1649
1650
1651
1652
1653
1654
1655
1656


1657
1658
1659
1660
1661
1662
1663
1664
1665

1666
1667
1668
1669
1670
1671
1672
1682
1683
1684
1685
1686
1687
1688





1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699


1700
1701
1702
1703
1704
1705
1706
1707
1708
1709

1710
1711
1712
1713
1714
1715
1716
1717







-
-
-
-
-
+
+
+
+
+






-
-
+
+








-
+







 * inside the specified rectangle and is a maximum of 2 pixels thick."
 *
 * "Maximum of 2 pixels thick" is apparently a lie; looks more like 4 to me
 * with shading.
 */

static void GroupElementSize(
    void *clientData,
    void *elementRecord,
    Tk_Window tkwin,
    int *minWidth,
    int *minHeight,
    TCL_UNUSED(void *),
    TCL_UNUSED(void *),
    TCL_UNUSED(Tk_Window),
    TCL_UNUSED(int *),
    TCL_UNUSED(int *),
    Ttk_Padding *paddingPtr)
{
    *paddingPtr = Ttk_UniformPadding(4);
}

static void GroupElementDraw(
    void *clientData,
    void *elementRecord,
    TCL_UNUSED(void *),
    TCL_UNUSED(void *),
    Tk_Window tkwin,
    Drawable d,
    Ttk_Box b,
    Ttk_State state)
{
    CGRect bounds = BoxToRect(d, b);

    BEGIN_DRAWING(d)
    if ([NSApp macMinorVersion] > 8) {
    if ([NSApp macOSVersion] > 100800) {
	DrawGroupBox(bounds, dc.context, tkwin);
    } else {
	const HIThemeGroupBoxDrawInfo info = {
	    .version = 0,
	    .state = Ttk_StateTableLookup(ThemeStateTable, state),
	    .kind = kHIThemeGroupBoxKindPrimaryOpaque,
	    };
1695
1696
1697
1698
1699
1700
1701
1702

1703
1704
1705


1706
1707
1708
1709
1710
1711
1712
1713





1714
1715
1716
1717
1718
1719
1720

1721
1722
1723
1724
1725
1726
1727
1740
1741
1742
1743
1744
1745
1746

1747
1748


1749
1750
1751
1752
1753





1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764

1765
1766
1767
1768
1769
1770
1771
1772







-
+

-
-
+
+



-
-
-
-
-
+
+
+
+
+






-
+







    Tcl_Obj     *fieldbackgroundObj;
} EntryElement;

#define ENTRY_DEFAULT_BACKGROUND "systemTextBackgroundColor"

static Ttk_ElementOptionSpec EntryElementOptions[] = {
    {"-background", TK_OPTION_BORDER,
     Tk_Offset(EntryElement, backgroundObj), ENTRY_DEFAULT_BACKGROUND},
     offsetof(EntryElement, backgroundObj), ENTRY_DEFAULT_BACKGROUND},
    {"-fieldbackground", TK_OPTION_BORDER,
     Tk_Offset(EntryElement, fieldbackgroundObj), ENTRY_DEFAULT_BACKGROUND},
    {0}
     offsetof(EntryElement, fieldbackgroundObj), ENTRY_DEFAULT_BACKGROUND},
    {NULL, TK_OPTION_BOOLEAN, 0, NULL}
};

static void EntryElementSize(
    void *clientData,
    void *elementRecord,
    Tk_Window tkwin,
    int *minWidth,
    int *minHeight,
    TCL_UNUSED(void *),
    TCL_UNUSED(void *),
    TCL_UNUSED(Tk_Window),
    TCL_UNUSED(int *),
    TCL_UNUSED(int *),
    Ttk_Padding *paddingPtr)
{
    *paddingPtr = Ttk_MakePadding(7, 5, 7, 6);
}

static void EntryElementDraw(
    void *clientData,
    TCL_UNUSED(void *),
    void *elementRecord,
    Tk_Window tkwin,
    Drawable d,
    Ttk_Box b,
    Ttk_State state)
{
    EntryElement *e = elementRecord;
1781
1782
1783
1784
1785
1786
1787
1788

1789
1790
1791
1792
1793
1794
1795
1826
1827
1828
1829
1830
1831
1832

1833
1834
1835
1836
1837
1838
1839
1840







-
+







	if (backgroundPtr != NULL) {
	    XFillRectangle(Tk_Display(tkwin), d,
		Tk_3DBorderGC(tkwin, backgroundPtr, TK_3D_FLAT_GC),
		inner.x, inner.y, inner.width, inner.height);
	}
	BEGIN_DRAWING(d)
	if (backgroundPtr == NULL) {
	    if ([NSApp macMinorVersion] > 8) {
	    if ([NSApp macOSVersion] > 100800) {
		background = [NSColor textBackgroundColor];
		CGContextSetFillColorWithColor(dc.context, CGCOLOR(background));
	    } else {
		CGContextSetRGBFillColor(dc.context, 1.0, 1.0, 1.0, 1.0);
	    }
	    CGContextFillRect(dc.context, bounds);
	}
1822
1823
1824
1825
1826
1827
1828
1829


1830
1831
1832
1833


1834
1835
1836
1837
1838
1839
1840



1841


1842
1843
1844
1845
1846


1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864




1865
1866
1867
1868
1869
1870
1871
1872
1873
1874












1875
1876
1877
1878
1879
1880
1881
1867
1868
1869
1870
1871
1872
1873

1874
1875
1876
1877


1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889

1890
1891
1892
1893
1894


1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911

1912

1913
1914
1915
1916
1917









1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936







-
+
+


-
-
+
+







+
+
+
-
+
+



-
-
+
+















-

-
+
+
+
+

-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+







 *      rectangle.  Measurement indicates that the arrow button has width 18.
 *
 *      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(
    void *clientData,
    void *elementRecord,
    TCL_UNUSED(void *),
    TCL_UNUSED(void *),
    Tk_Window tkwin,
    int *minWidth,
    int *minHeight,
    Ttk_Padding *paddingPtr)
{
    *minWidth = 24;
    *minHeight = 23;
    if (TkMacOSXInDarkMode(tkwin)) {
	*paddingPtr = DarkComboboxPadding;
    } else {
    *paddingPtr = ComboboxPadding;
	*paddingPtr = ComboboxPadding;
    }
}

static void ComboboxElementDraw(
    void *clientData,
    void *elementRecord,
    TCL_UNUSED(void *),
    TCL_UNUSED(void *),
    Tk_Window tkwin,
    Drawable d,
    Ttk_Box b,
    Ttk_State state)
{
    CGRect bounds = BoxToRect(d, b);
    const HIThemeButtonDrawInfo info = {
	.version = 0,
	.state = Ttk_StateTableLookup(ThemeStateTable, state),
	.kind = kThemeComboBox,
	.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 macMinorVersion] > 8) {
	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,
    sizeof(NullElement),
    TtkNullElementOptions,
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912



1913
1914
1915

1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927


1928
1929
1930
1931
1932
1933
1934
1958
1959
1960
1961
1962
1963
1964



1965
1966
1967
1968
1969

1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980


1981
1982
1983
1984
1985
1986
1987
1988
1989







-
-
-
+
+
+


-
+










-
-
+
+







 *      "pressed down" state by the down button.  The drawing must be done in
 *      that order.  So the up button must be listed first in the layout.
 */

static Ttk_Padding SpinbuttonMargins = {0, 0, 2, 0};

static void SpinButtonUpElementSize(
    void *clientData,
    void *elementRecord,
    Tk_Window tkwin,
    TCL_UNUSED(void *),
    TCL_UNUSED(void *),
    TCL_UNUSED(Tk_Window),
    int *minWidth,
    int *minHeight,
    Ttk_Padding *paddingPtr)
    TCL_UNUSED(Ttk_Padding *))
{
    SInt32 s;

    ChkErr(GetThemeMetric, kThemeMetricLittleArrowsWidth, &s);
    *minWidth = s + Ttk_PaddingWidth(SpinbuttonMargins);
    ChkErr(GetThemeMetric, kThemeMetricLittleArrowsHeight, &s);
    *minHeight = (s + Ttk_PaddingHeight(SpinbuttonMargins)) / 2;
}

static void SpinButtonUpElementDraw(
    void *clientData,
    void *elementRecord,
    TCL_UNUSED(void *),
    TCL_UNUSED(void *),
    Tk_Window tkwin,
    Drawable d,
    Ttk_Box b,
    Ttk_State state)
{
    CGRect bounds = BoxToRect(d, Ttk_PadBox(b, SpinbuttonMargins));
    int infoState;
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969



1970
1971
1972

1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984


1985
1986
1987
1988
1989
1990
1991
2015
2016
2017
2018
2019
2020
2021



2022
2023
2024
2025
2026

2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037


2038
2039
2040
2041
2042
2043
2044
2045
2046







-
-
-
+
+
+


-
+










-
-
+
+







    TK_STYLE_VERSION_2,
    sizeof(NullElement),
    TtkNullElementOptions,
    SpinButtonUpElementSize,
    SpinButtonUpElementDraw
};
static void SpinButtonDownElementSize(
    void *clientData,
    void *elementRecord,
    Tk_Window tkwin,
    TCL_UNUSED(void *),
    TCL_UNUSED(void *),
    TCL_UNUSED(Tk_Window),
    int *minWidth,
    int *minHeight,
    Ttk_Padding *paddingPtr)
    TCL_UNUSED(Ttk_Padding *))
{
    SInt32 s;

    ChkErr(GetThemeMetric, kThemeMetricLittleArrowsWidth, &s);
    *minWidth = s + Ttk_PaddingWidth(SpinbuttonMargins);
    ChkErr(GetThemeMetric, kThemeMetricLittleArrowsHeight, &s);
    *minHeight = (s + Ttk_PaddingHeight(SpinbuttonMargins)) / 2;
}

static void SpinButtonDownElementDraw(
    void *clientData,
    void *elementRecord,
    TCL_UNUSED(void *),
    TCL_UNUSED(void *),
    Tk_Window tkwin,
    Drawable d,
    Ttk_Box b,
    Ttk_State state)
{
    CGRect bounds = BoxToRect(d, Ttk_PadBox(b, SpinbuttonMargins));
    int infoState = 0;
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065





2066
2067
2068
2069
2070


2071
2072
2073

2074
2075

2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092

2093

2094
2095

2096
2097
2098
2099
2100






2101
2102
2103
2104

2105
2106
2107
2108
2109
2110
2111
2109
2110
2111
2112
2113
2114
2115





2116
2117
2118
2119
2120
2121
2122
2123


2124
2125
2126
2127

2128
2129

2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146

2147
2148
2149
2150

2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165

2166
2167
2168
2169
2170
2171
2172
2173







-
-
-
-
-
+
+
+
+
+



-
-
+
+


-
+

-
+
















-
+

+

-
+





+
+
+
+
+
+



-
+







    Tcl_Obj *fromObj;           /* minimum value */
    Tcl_Obj *toObj;             /* maximum value */
    Tcl_Obj *valueObj;          /* current value */
    Tcl_Obj *orientObj;         /* horizontal / vertical */
} TrackElement;

static Ttk_ElementOptionSpec TrackElementOptions[] = {
    {"-from", TK_OPTION_DOUBLE, Tk_Offset(TrackElement, fromObj)},
    {"-to", TK_OPTION_DOUBLE, Tk_Offset(TrackElement, toObj)},
    {"-value", TK_OPTION_DOUBLE, Tk_Offset(TrackElement, valueObj)},
    {"-orient", TK_OPTION_STRING, Tk_Offset(TrackElement, orientObj)},
    {0, 0, 0}
    {"-from", TK_OPTION_DOUBLE, offsetof(TrackElement, fromObj), NULL},
    {"-to", TK_OPTION_DOUBLE, offsetof(TrackElement, toObj), NULL},
    {"-value", TK_OPTION_DOUBLE, offsetof(TrackElement, valueObj), NULL},
    {"-orient", TK_OPTION_STRING, offsetof(TrackElement, orientObj), NULL},
    {NULL, TK_OPTION_BOOLEAN, 0, NULL}
};
static void TrackElementSize(
    void *clientData,
    void *elementRecord,
    Tk_Window tkwin,
    TCL_UNUSED(void *),
    TCL_UNUSED(Tk_Window),
    int *minWidth,
    int *minHeight,
    Ttk_Padding *paddingPtr)
    TCL_UNUSED(Ttk_Padding *))
{
    TrackElementData *data = clientData;
    TrackElementData *data = (TrackElementData *)clientData;
    SInt32 size = 24;   /* reasonable default ... */

    ChkErr(GetThemeMetric, data->thicknessMetric, &size);
    *minWidth = *minHeight = size;
}

static void TrackElementDraw(
    void *clientData,
    void *elementRecord,
    Tk_Window tkwin,
    Drawable d,
    Ttk_Box b,
    Ttk_State state)
{
    TrackElementData *data = clientData;
    TrackElement *elem = elementRecord;
    int orientation = TTK_ORIENT_HORIZONTAL;
    Ttk_Orient orientation = TTK_ORIENT_HORIZONTAL;
    double from = 0, to = 100, value = 0, factor;
    CGRect bounds;

    Ttk_GetOrientFromObj(NULL, elem->orientObj, &orientation);
    TtkGetOrientFromObj(NULL, elem->orientObj, &orientation);
    Tcl_GetDoubleFromObj(NULL, elem->fromObj, &from);
    Tcl_GetDoubleFromObj(NULL, elem->toObj, &to);
    Tcl_GetDoubleFromObj(NULL, elem->valueObj, &value);
    factor = RangeToFactor(to);

    /*
     * 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 = data->kind,
	.bounds = BoxToRect(d, b),
	.bounds = bounds,
	.min = from * factor,
	.max = to * factor,
	.value = value * factor,
	.attributes = kThemeTrackShowThumb |
	    (orientation == TTK_ORIENT_HORIZONTAL ?
	    kThemeTrackHorizontal : 0),
	.enableState = Ttk_StateTableLookup(ThemeTrackEnableTable, state),
2119
2120
2121
2122
2123
2124
2125
2126

2127
2128
2129
2130
2131
2132
2133
2181
2182
2183
2184
2185
2186
2187

2188
2189
2190
2191
2192
2193
2194
2195







-
+







	    info.trackInfo.slider.thumbDir = kThemeThumbDownward;
	} else {
	    info.trackInfo.slider.thumbDir = kThemeThumbPlain;
	}
    }
    BEGIN_DRAWING(d)
    if (TkMacOSXInDarkMode(tkwin)) {
	CGRect bounds = BoxToRect(d, b);
	bounds = BoxToRect(d, b);
	NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
	NSColor *trackColor = [NSColor colorWithColorSpace: deviceRGB
	    components: darkTrack
	    count: 4];
	if (orientation == TTK_ORIENT_HORIZONTAL) {
	    bounds = CGRectInset(bounds, 1, bounds.size.height / 2 - 2);
	} else {
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162



2163
2164
2165

2166
2167
2168
2169
2170
2171
2172
2215
2216
2217
2218
2219
2220
2221



2222
2223
2224
2225
2226

2227
2228
2229
2230
2231
2232
2233
2234







-
-
-
+
+
+


-
+







 * Has geometry only. The Scale widget adjusts the position of this element,
 * and uses it for hit detection. In the Aqua theme, the slider is actually
 * drawn as part of the trough element.
 *
 */

static void SliderElementSize(
    void *clientData,
    void *elementRecord,
    Tk_Window tkwin,
    TCL_UNUSED(void *),
    TCL_UNUSED(void *),
    TCL_UNUSED(Tk_Window),
    int *minWidth,
    int *minHeight,
    Ttk_Padding *paddingPtr)
    TCL_UNUSED(Ttk_Padding *))
{
    *minWidth = *minHeight = 24;
}

static Ttk_ElementSpec SliderElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(NullElement),
2189
2190
2191
2192
2193
2194
2195
2196

2197
2198

2199
2200

2201
2202

2203
2204
2205


2206
2207
2208
2209
2210



2211
2212
2213

2214
2215
2216
2217
2218
2219
2220
2221
2222

2223
2224
2225
2226
2227
2228
2229
2230
2231






2232



2233
2234
2235
2236






















2237




2238

2239
2240
2241

2242
2243
2244
2245

2246
2247
2248


2249
2250

2251
2252
2253

2254
2255
2256
2257
2258

2259
2260
2261
2262
2263
2264
2265
2251
2252
2253
2254
2255
2256
2257

2258
2259

2260
2261

2262
2263

2264
2265


2266
2267
2268
2269



2270
2271
2272
2273
2274

2275
2276
2277
2278
2279
2280
2281
2282
2283

2284
2285
2286
2287
2288
2289
2290
2291


2292
2293
2294
2295
2296
2297
2298
2299
2300
2301




2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323

2324
2325
2326
2327
2328
2329
2330
2331

2332




2333
2334


2335
2336
2337

2338

2339

2340
2341

2342
2343

2344
2345
2346
2347
2348
2349
2350
2351







-
+

-
+

-
+

-
+

-
-
+
+


-
-
-
+
+
+


-
+








-
+







-
-
+
+
+
+
+
+

+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+

+


-
+
-
-
-
-
+

-
-
+
+

-
+
-

-
+

-


-
+







    Tcl_Obj *maximumObj;        /* maximum value */
    Tcl_Obj *phaseObj;          /* animation phase */
    Tcl_Obj *modeObj;           /* progress bar mode */
} PbarElement;

static Ttk_ElementOptionSpec PbarElementOptions[] = {
    {"-orient", TK_OPTION_STRING,
     Tk_Offset(PbarElement, orientObj), "horizontal"},
     offsetof(PbarElement, orientObj), "horizontal"},
    {"-value", TK_OPTION_DOUBLE,
     Tk_Offset(PbarElement, valueObj), "0"},
     offsetof(PbarElement, valueObj), "0"},
    {"-maximum", TK_OPTION_DOUBLE,
     Tk_Offset(PbarElement, maximumObj), "100"},
     offsetof(PbarElement, maximumObj), "100"},
    {"-phase", TK_OPTION_INT,
     Tk_Offset(PbarElement, phaseObj), "0"},
     offsetof(PbarElement, phaseObj), "0"},
    {"-mode", TK_OPTION_STRING,
     Tk_Offset(PbarElement, modeObj), "determinate"},
    {0, 0, 0, 0}
     offsetof(PbarElement, modeObj), "determinate"},
    {NULL, TK_OPTION_BOOLEAN, 0, NULL}
};
static void PbarElementSize(
    void *clientData,
    void *elementRecord,
    Tk_Window tkwin,
    TCL_UNUSED(void *),
    TCL_UNUSED(void *),
    TCL_UNUSED(Tk_Window),
    int *minWidth,
    int *minHeight,
    Ttk_Padding *paddingPtr)
    TCL_UNUSED(Ttk_Padding *))
{
    SInt32 size = 24;           /* @@@ Check HIG for correct default */

    ChkErr(GetThemeMetric, kThemeMetricLargeProgressBarThickness, &size);
    *minWidth = *minHeight = size;
}

static void PbarElementDraw(
    void *clientData,
    TCL_UNUSED(void *),
    void *elementRecord,
    Tk_Window tkwin,
    Drawable d,
    Ttk_Box b,
    Ttk_State state)
{
    PbarElement *pbar = elementRecord;
    int orientation = TTK_ORIENT_HORIZONTAL, phase = 0;
    double value = 0, maximum = 100, factor;
    Ttk_Orient orientation = TTK_ORIENT_HORIZONTAL;

    /*
     * 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;

    Ttk_GetOrientFromObj(NULL, pbar->orientObj, &orientation);
    Tcl_GetDoubleFromObj(NULL, pbar->valueObj, &value);
    Tcl_GetDoubleFromObj(NULL, pbar->maximumObj, &maximum);
    Tcl_GetIntFromObj(NULL, pbar->phaseObj, &phase);
    TtkGetOrientFromObj(NULL, pbar->orientObj, &orientation);
    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;
    }

    factor = RangeToFactor(maximum);
    /*
     * 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 =
	.kind = kind,
	    (!strcmp("indeterminate",
	    Tcl_GetString(pbar->modeObj)) && value) ?
	    kThemeIndeterminateBar : kThemeProgressBar,
	.bounds = BoxToRect(d, b),
	.bounds = bounds,
	.min = 0,
	.max = maximum * factor,
	.value = value * factor,
	.max = imaximum,
	.value = ivalue,
	.attributes = kThemeTrackShowThumb |
	    (orientation == TTK_ORIENT_HORIZONTAL ?
	    (orientation == TTK_ORIENT_HORIZONTAL ? kThemeTrackHorizontal : 0),
	    kThemeTrackHorizontal : 0),
	.enableState = Ttk_StateTableLookup(ThemeTrackEnableTable, state),
	.trackInfo.progress.phase = phase,
	.trackInfo.progress.phase = phase
    };

    BEGIN_DRAWING(d)
    if (TkMacOSXInDarkMode(tkwin)) {
	CGRect bounds = BoxToRect(d, b);
	bounds = BoxToRect(d, b);
	NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
	NSColor *trackColor = [NSColor colorWithColorSpace: deviceRGB
	    components: darkTrack
	    count: 4];
	if (orientation == TTK_ORIENT_HORIZONTAL) {
	    bounds = CGRectInset(bounds, 1, bounds.size.height / 2 - 3);
	} else {
2286
2287
2288
2289
2290
2291
2292
2293
2294


2295
2296
2297

2298
2299

2300
2301
2302
2303
2304
2305

2306
2307
2308

2309
2310
2311
2312

2313
2314
2315
2316
2317

2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338

2339
2340
2341
2342
2343

2344
2345
2346

2347
2348
2349
2350
2351
2352

2353
2354
2355
2356
2357
2358
2359
2360
2361
2362

2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380

2381
2382

2383
2384
2385

2386
2387
2388

2389
2390

2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401

2402
2403
2404
2405
2406
2407
2408
2409

2410
2411

2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425

2426
2427
2428
2429
2430
2431
2432
2372
2373
2374
2375
2376
2377
2378


2379
2380
2381
2382

2383
2384

2385
2386
2387
2388
2389
2390

2391
2392
2393

2394
2395
2396
2397

2398
2399
2400
2401
2402

2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423

2424
2425
2426
2427
2428

2429
2430
2431

2432
2433
2434
2435
2436
2437

2438
2439
2440
2441
2442
2443
2444
2445
2446
2447

2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465

2466
2467

2468
2469
2470

2471
2472
2473

2474
2475

2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486

2487
2488
2489
2490
2491
2492
2493
2494

2495
2496

2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510

2511
2512
2513
2514
2515
2516
2517
2518







-
-
+
+


-
+

-
+





-
+


-
+



-
+




-
+




















-
+




-
+


-
+





-
+









-
+

















-
+

-
+


-
+


-
+

-
+










-
+







-
+

-
+













-
+







typedef struct
{
    Tcl_Obj *orientObj;
} ScrollbarElement;

static Ttk_ElementOptionSpec ScrollbarElementOptions[] = {
    {"-orient", TK_OPTION_STRING,
     Tk_Offset(ScrollbarElement, orientObj), "horizontal"},
    {0, 0, 0, 0}
     offsetof(ScrollbarElement, orientObj), "horizontal"},
    {NULL, TK_OPTION_BOOLEAN, 0, NULL}
};
static void TroughElementSize(
    void *clientData,
    TCL_UNUSED(void *),
    void *elementRecord,
    Tk_Window tkwin,
    TCL_UNUSED(Tk_Window),
    int *minWidth,
    int *minHeight,
    Ttk_Padding *paddingPtr)
{
    ScrollbarElement *scrollbar = elementRecord;
    int orientation = TTK_ORIENT_HORIZONTAL;
    Ttk_Orient orientation = TTK_ORIENT_HORIZONTAL;
    SInt32 thickness = 15;

    Ttk_GetOrientFromObj(NULL, scrollbar->orientObj, &orientation);
    TtkGetOrientFromObj(NULL, scrollbar->orientObj, &orientation);
    ChkErr(GetThemeMetric, kThemeMetricScrollBarWidth, &thickness);
    if (orientation == TTK_ORIENT_HORIZONTAL) {
	*minHeight = thickness;
	if ([NSApp macMinorVersion] > 7) {
	if ([NSApp macOSVersion] > 100700) {
	    *paddingPtr = Ttk_MakePadding(4, 4, 4, 3);
	}
    } else {
	*minWidth = thickness;
	if ([NSApp macMinorVersion] > 7) {
	if ([NSApp macOSVersion] > 100700) {
	    *paddingPtr = Ttk_MakePadding(4, 4, 3, 4);
	}
    }
}

static CGFloat lightTrough[4] = {250.0 / 255, 250.0 / 255, 250.0 / 255, 1.0};
static CGFloat darkTrough[4] = {45.0 / 255, 46.0 / 255, 49.0 / 255, 1.0};
static CGFloat lightInactiveThumb[4] = {
    200.0 / 255, 200.0 / 255, 200.0 / 255, 1.0
};
static CGFloat lightActiveThumb[4] = {
    133.0 / 255, 133.0 / 255, 133.0 / 255, 1.0
};
static CGFloat darkInactiveThumb[4] = {
    116.0 / 255, 117.0 / 255, 118.0 / 255, 1.0
};
static CGFloat darkActiveThumb[4] = {
    158.0 / 255, 158.0 / 255, 159.0 / 255, 1.0
};
static void TroughElementDraw(
    void *clientData,
    TCL_UNUSED(void *),
    void *elementRecord,
    Tk_Window tkwin,
    Drawable d,
    Ttk_Box b,
    Ttk_State state)
    TCL_UNUSED(Ttk_State))
{
    ScrollbarElement *scrollbar = elementRecord;
    int orientation = TTK_ORIENT_HORIZONTAL;
    Ttk_Orient orientation = TTK_ORIENT_HORIZONTAL;
    CGRect bounds = BoxToRect(d, b);
    NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
    NSColor *troughColor;
    CGFloat *rgba = TkMacOSXInDarkMode(tkwin) ? darkTrough : lightTrough;

    Ttk_GetOrientFromObj(NULL, scrollbar->orientObj, &orientation);
    TtkGetOrientFromObj(NULL, scrollbar->orientObj, &orientation);
    if (orientation == TTK_ORIENT_HORIZONTAL) {
	bounds = CGRectInset(bounds, 0, 1);
    } else {
	bounds = CGRectInset(bounds, 1, 0);
    }
    troughColor = [NSColor colorWithColorSpace: deviceRGB
	components: rgba
	count: 4];
    BEGIN_DRAWING(d)
    if ([NSApp macMinorVersion] > 8) {
    if ([NSApp macOSVersion] > 100800) {
	CGContextSetFillColorWithColor(dc.context, CGCOLOR(troughColor));
    } else {
	ChkErr(HIThemeSetFill, kThemeBrushDocumentWindowBackground, NULL,
	    dc.context, HIOrientation);
    }
    CGContextFillRect(dc.context, bounds);
    END_DRAWING
}

static Ttk_ElementSpec TroughElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(ScrollbarElement),
    ScrollbarElementOptions,
    TroughElementSize,
    TroughElementDraw
};
static void ThumbElementSize(
    void *clientData,
    TCL_UNUSED(void *),
    void *elementRecord,
    Tk_Window tkwin,
    TCL_UNUSED(Tk_Window),
    int *minWidth,
    int *minHeight,
    Ttk_Padding *paddingPtr)
    TCL_UNUSED(Ttk_Padding *))
{
    ScrollbarElement *scrollbar = elementRecord;
    int orientation = TTK_ORIENT_HORIZONTAL;
    Ttk_Orient orientation = TTK_ORIENT_HORIZONTAL;

    Ttk_GetOrientFromObj(NULL, scrollbar->orientObj, &orientation);
    TtkGetOrientFromObj(NULL, scrollbar->orientObj, &orientation);
    if (orientation == TTK_ORIENT_VERTICAL) {
	*minHeight = 18;
	*minWidth = 8;
    } else {
	*minHeight = 8;
	*minWidth = 18;
    }
}

static void ThumbElementDraw(
    void *clientData,
    TCL_UNUSED(void *),
    void *elementRecord,
    Tk_Window tkwin,
    Drawable d,
    Ttk_Box b,
    Ttk_State state)
{
    ScrollbarElement *scrollbar = elementRecord;
    int orientation = TTK_ORIENT_HORIZONTAL;
    Ttk_Orient orientation = TTK_ORIENT_HORIZONTAL;

    Ttk_GetOrientFromObj(NULL, scrollbar->orientObj, &orientation);
    TtkGetOrientFromObj(NULL, scrollbar->orientObj, &orientation);

    /*
     * In order to make ttk scrollbars work correctly it is necessary to be
     * able to display the thumb element at the size and location which the ttk
     * scrollbar widget requests.  The algorithm that HIToolbox uses to
     * determine the thumb geometry from the input values of min, max, value
     * and viewSize is undocumented.  A seemingly natural algorithm is
     * implemented below.  This code uses that algorithm for older OS versions,
     * because using HITools also handles drawing the buttons and 3D thumb used
     * on those systems.  For newer systems the cleanest approach is to just
     * draw the thumb directly.
     */

    if ([NSApp macMinorVersion] > 8) {
    if ([NSApp macOSVersion] > 100800) {
	CGRect thumbBounds = BoxToRect(d, b);
	NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
	NSColor *thumbColor;
	CGFloat *rgba;
	if ((orientation == TTK_ORIENT_HORIZONTAL &&
	    thumbBounds.size.width >= Tk_Width(tkwin) - 8) ||
	    (orientation == TTK_ORIENT_VERTICAL &&
2444
2445
2446
2447
2448
2449
2450
2451

2452
2453
2454
2455
2456
2457
2458
2530
2531
2532
2533
2534
2535
2536

2537
2538
2539
2540
2541
2542
2543
2544







-
+







	    components: rgba
	    count: 4];
	BEGIN_DRAWING(d)
	SolidFillRoundedRectangle(dc.context, thumbBounds, 4, thumbColor);
	END_DRAWING
    } else {
	double thumbSize, trackSize, visibleSize, factor, fraction;
	MacDrawable *macWin = (MacDrawable *) Tk_WindowId(tkwin);
	MacDrawable *macWin = (MacDrawable *)Tk_WindowId(tkwin);
	CGRect troughBounds = {{macWin->xOff, macWin->yOff},
			       {Tk_Width(tkwin), Tk_Height(tkwin)}};

        /*
         * The info struct has integer fields, which will be converted to
         * floats in the drawing routine.  All of values provided in the info
         * struct, namely min, max, value, and viewSize are only defined up to
2478
2479
2480
2481
2482
2483
2484
2485

2486
2487
2488
2489
2490
2491
2492
2564
2565
2566
2567
2568
2569
2570

2571
2572
2573
2574
2575
2576
2577
2578







-
+







	    trackSize = troughBounds.size.height;
	    thumbSize = b.height;
	    fraction = b.y / trackSize;
	}
	visibleSize = (thumbSize / trackSize) * factor;
	info.max = factor - visibleSize;
	info.trackInfo.scrollbar.viewsize = visibleSize;
	if ([NSApp macMinorVersion] < 8 ||
	if ([NSApp macOSVersion] < 100800 ||
	    orientation == TTK_ORIENT_HORIZONTAL) {
	    info.value = factor * fraction;
	} else {
	    info.value = info.max - factor * fraction;
	}
	if ((state & TTK_STATE_PRESSED) ||
	    (state & TTK_STATE_HOVER)) {
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518



2519
2520
2521

2522
2523

2524
2525
2526
2527
2528
2529
2530
2595
2596
2597
2598
2599
2600
2601



2602
2603
2604
2605
2606

2607
2608

2609
2610
2611
2612
2613
2614
2615
2616







-
-
-
+
+
+


-
+

-
+







    TK_STYLE_VERSION_2,
    sizeof(ScrollbarElement),
    ScrollbarElementOptions,
    ThumbElementSize,
    ThumbElementDraw
};
static void ArrowElementSize(
    void *clientData,
    void *elementRecord,
    Tk_Window tkwin,
    TCL_UNUSED(void *),
    TCL_UNUSED(void *),
    TCL_UNUSED(Tk_Window),
    int *minWidth,
    int *minHeight,
    Ttk_Padding *paddingPtr)
    TCL_UNUSED(Ttk_Padding *))
{
    if ([NSApp macMinorVersion] < 8) {
    if ([NSApp macOSVersion] < 100800) {
	*minHeight = *minWidth = 14;
    } else {
	*minHeight = *minWidth = -1;
    }
}

static Ttk_ElementSpec ArrowElementSpec = {
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549



2550
2551
2552

2553
2554
2555
2556
2557
2558
2559


2560
2561
2562
2563
2564
2565
2566
2626
2627
2628
2629
2630
2631
2632



2633
2634
2635
2636
2637

2638
2639
2640
2641
2642
2643


2644
2645
2646
2647
2648
2649
2650
2651
2652







-
-
-
+
+
+


-
+





-
-
+
+







 *
 *    DrawThemeSeparator() guesses the orientation of the line from the width
 *    and height of the rectangle, so the same element can can be used for
 *    horizontal, vertical, and general separators.
 */

static void SeparatorElementSize(
    void *clientData,
    void *elementRecord,
    Tk_Window tkwin,
    TCL_UNUSED(void *),
    TCL_UNUSED(void *),
    TCL_UNUSED(Tk_Window),
    int *minWidth,
    int *minHeight,
    Ttk_Padding *paddingPtr)
    TCL_UNUSED(Ttk_Padding *))
{
    *minWidth = *minHeight = 1;
}

static void SeparatorElementDraw(
    void *clientData,
    void *elementRecord,
    TCL_UNUSED(void *),
    TCL_UNUSED(void *),
    Tk_Window tkwin,
    Drawable d,
    Ttk_Box b,
    unsigned int state)
{
    CGRect bounds = BoxToRect(d, b);
    const HIThemeSeparatorDrawInfo info = {
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601



2602
2603
2604

2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623



2624
2625
2626
2627
2628
2629
2630
2678
2679
2680
2681
2682
2683
2684



2685
2686
2687
2688
2689

2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706



2707
2708
2709
2710
2711
2712
2713
2714
2715
2716







-
-
-
+
+
+


-
+
















-
-
-
+
+
+







 * +++ Size grip elements -- (obsolete)
 */

static const ThemeGrowDirection sizegripGrowDirection
    = kThemeGrowRight | kThemeGrowDown;

static void SizegripElementSize(
    void *clientData,
    void *elementRecord,
    Tk_Window tkwin,
    TCL_UNUSED(void *),
    TCL_UNUSED(void *),
    TCL_UNUSED(Tk_Window),
    int *minWidth,
    int *minHeight,
    Ttk_Padding *paddingPtr)
    TCL_UNUSED(Ttk_Padding *))
{
    HIThemeGrowBoxDrawInfo info = {
	.version = 0,
	.state = kThemeStateActive,
	.kind = kHIThemeGrowBoxKindNormal,
	.direction = sizegripGrowDirection,
	.size = kHIThemeGrowBoxSizeNormal,
    };
    CGRect bounds = CGRectZero;

    ChkErr(HIThemeGetGrowBoxBounds, &bounds.origin, &info, &bounds);
    *minWidth = bounds.size.width;
    *minHeight = bounds.size.height;
}

static void SizegripElementDraw(
    void *clientData,
    void *elementRecord,
    Tk_Window tkwin,
    TCL_UNUSED(void *),
    TCL_UNUSED(void *),
    TCL_UNUSED(Tk_Window),
    Drawable d,
    Ttk_Box b,
    unsigned int state)
{
    CGRect bounds = BoxToRect(d, b);
    HIThemeGrowBoxDrawInfo info = {
	.version = 0,
2691
2692
2693
2694
2695
2696
2697
2698
2699


2700
2701
2702
2703
2704
2705
2706
2707

2708
2709
2710
2711
2712
2713
2714
2777
2778
2779
2780
2781
2782
2783


2784
2785
2786
2787
2788
2789
2790
2791
2792

2793
2794
2795
2796
2797
2798
2799
2800







-
-
+
+







-
+







 *      the coordinate system of the top-level window.  Apparently failing to
 *      do this used to cause graphics anomalies when drawing into an
 *      off-screen graphics port.  The code for handling this is currently
 *      commented out.
 */

static void FillElementDraw(
    void *clientData,
    void *elementRecord,
    TCL_UNUSED(void *),
    TCL_UNUSED(void *),
    Tk_Window tkwin,
    Drawable d,
    Ttk_Box b,
    Ttk_State state)
{
    CGRect bounds = BoxToRect(d, b);

    if ([NSApp macMinorVersion] > 8) {
    if ([NSApp macOSVersion] > 100800) {
	NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
	NSColor *bgColor;
	CGFloat fill[4];
	BEGIN_DRAWING(d)
	GetBackgroundColor(dc.context, tkwin, 0, fill);
	bgColor = [NSColor colorWithColorSpace: deviceRGB components: fill
					 count: 4];
2729
2730
2731
2732
2733
2734
2735
2736

2737
2738
2739
2740
2741
2742
2743
2815
2816
2817
2818
2819
2820
2821

2822
2823
2824
2825
2826
2827
2828
2829







-
+







}

static void BackgroundElementDraw(
    void *clientData,
    void *elementRecord,
    Tk_Window tkwin,
    Drawable d,
    Ttk_Box b,
    TCL_UNUSED(Ttk_Box),
    unsigned int state)
{
    FillElementDraw(clientData, elementRecord, tkwin, d, Ttk_WinBox(tkwin),
	state);
}

static Ttk_ElementSpec FillElementSpec = {
2766
2767
2768
2769
2770
2771
2772
2773
2774


2775
2776
2777
2778


2779
2780
2781
2782
2783
2784
2785
2852
2853
2854
2855
2856
2857
2858


2859
2860
2861
2862


2863
2864
2865
2866
2867
2868
2869
2870
2871







-
-
+
+


-
-
+
+







 *    <URL: http://developer.apple.com/documentation/Carbon/Reference/
 *    Appearance_Manager/appearance_manager/constant_7.html#/
 *    /apple_ref/doc/uid/TP30000243/C005321>
 *
 */

static void ToolbarBackgroundElementDraw(
    void *clientData,
    void *elementRecord,
    TCL_UNUSED(void *),
    TCL_UNUSED(void *),
    Tk_Window tkwin,
    Drawable d,
    Ttk_Box b,
    Ttk_State state)
    TCL_UNUSED(Ttk_Box),
    TCL_UNUSED(Ttk_State))
{
    ThemeBrush brush = kThemeBrushToolbarBackground;
    CGRect bounds = BoxToRect(d, Ttk_WinBox(tkwin));

    BEGIN_DRAWING(d)
    ChkErr(HIThemeSetFill, brush, NULL, dc.context, HIOrientation);
    //QDSetPatternOrigin(PatternOrigin(tkwin, d));
2795
2796
2797
2798
2799
2800
2801
2802

2803
2804
2805
2806
2807
2808
2809
2810
2811
2812


2813
2814
2815
2816

2817
2818
2819
2820
2821

2822
2823
2824
2825
2826
2827
2828
2881
2882
2883
2884
2885
2886
2887

2888
2889
2890
2891
2892
2893
2894
2895
2896


2897
2898
2899
2900
2901

2902
2903
2904
2905
2906

2907
2908
2909
2910
2911
2912
2913
2914







-
+








-
-
+
+



-
+




-
+







    ToolbarBackgroundElementDraw
};

/*----------------------------------------------------------------------
 * +++ 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;

static Ttk_ElementOptionSpec FieldElementOptions[] = {
    {"-fieldbackground", TK_OPTION_BORDER,
     Tk_Offset(FieldElement, backgroundObj), "white"},
    {NULL, 0, 0, NULL}
     offsetof(FieldElement, backgroundObj), "white"},
    {NULL, TK_OPTION_BOOLEAN, 0, NULL}
};

static void FieldElementDraw(
    void *clientData,
    TCL_UNUSED(void *),
    void *elementRecord,
    Tk_Window tkwin,
    Drawable d,
    Ttk_Box b,
    Ttk_State state)
    TCL_UNUSED(Ttk_State))
{
    FieldElement *e = elementRecord;
    Tk_3DBorder backgroundPtr =
	Tk_Get3DBorderFromObj(tkwin, e->backgroundObj);

    XFillRectangle(Tk_Display(tkwin), d,
	Tk_3DBorderGC(tkwin, backgroundPtr, TK_3D_FLAT_GC),
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851



2852
2853
2854
2855
2856

2857
2858
2859
2860
2861
2862





2863
2864
2865
2866
2867
2868
2869
2870





2871
2872
2873
2874
2875
2876
2877
2878
2879

2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899

2900
2901
2902
2903
2904
2905
2906
2907
2908
2909

2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926

2927
2928
2929
2930
2931
2932
2933
2928
2929
2930
2931
2932
2933
2934



2935
2936
2937
2938
2939
2940
2941

2942
2943





2944
2945
2946
2947
2948
2949
2950
2951





2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964

2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984

2985
2986
2987
2988
2989
2990
2991
2992
2993
2994

2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011

3012
3013
3014
3015
3016
3017
3018
3019







-
-
-
+
+
+




-
+

-
-
-
-
-
+
+
+
+
+



-
-
-
-
-
+
+
+
+
+








-
+



















-
+









-
+
















-
+







 *
 *    On systems older than 10.9 The header is a kThemeListHeaderButton drawn
 *    by HIToolbox.  On newer systems those buttons do not match the Apple
 *    buttons, so we draw them from scratch.
 */

static Ttk_StateTable TreeHeaderValueTable[] = {
    {kThemeButtonOn, TTK_STATE_ALTERNATE},
    {kThemeButtonOn, TTK_STATE_SELECTED},
    {kThemeButtonOff, 0}
    {kThemeButtonOn, TTK_STATE_ALTERNATE, 0},
    {kThemeButtonOn, TTK_STATE_SELECTED, 0},
    {kThemeButtonOff, 0, 0}
};

static Ttk_StateTable TreeHeaderAdornmentTable[] = {
    {kThemeAdornmentHeaderButtonSortUp,
     TTK_STATE_ALTERNATE | TTK_TREEVIEW_STATE_SORTARROW},
     TTK_STATE_ALTERNATE | TTK_TREEVIEW_STATE_SORTARROW, 0},
    {kThemeAdornmentDefault,
     TTK_STATE_SELECTED | TTK_TREEVIEW_STATE_SORTARROW},
    {kThemeAdornmentHeaderButtonNoSortArrow, TTK_STATE_ALTERNATE},
    {kThemeAdornmentHeaderButtonNoSortArrow, TTK_STATE_SELECTED},
    {kThemeAdornmentFocus, TTK_STATE_FOCUS},
    {kThemeAdornmentNone, 0}
     TTK_STATE_SELECTED | TTK_TREEVIEW_STATE_SORTARROW, 0},
    {kThemeAdornmentHeaderButtonNoSortArrow, TTK_STATE_ALTERNATE, 0},
    {kThemeAdornmentHeaderButtonNoSortArrow, TTK_STATE_SELECTED, 0},
    {kThemeAdornmentFocus, TTK_STATE_FOCUS, 0},
    {kThemeAdornmentNone, 0, 0}
};

static void TreeAreaElementSize (
    void *clientData,
    void *elementRecord,
    Tk_Window tkwin,
    int *minWidth,
    int *minHeight,
    TCL_UNUSED(void *),
    TCL_UNUSED(void *),
    TCL_UNUSED(Tk_Window),
    TCL_UNUSED(int *),
    TCL_UNUSED(int *),
    Ttk_Padding *paddingPtr)
{

    /*
     * Padding is needed to get the heading text to align correctly, since the
     * widget expects the heading to be the same height as a row.
     */

    if ([NSApp macMinorVersion] > 8) {
    if ([NSApp macOSVersion] > 100800) {
	paddingPtr->top = 4;
    }
}

static Ttk_ElementSpec TreeAreaElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(NullElement),
    TtkNullElementOptions,
    TreeAreaElementSize,
    TtkNullElementDraw
};
static void TreeHeaderElementSize(
    void *clientData,
    void *elementRecord,
    Tk_Window tkwin,
    int *minWidth,
    int *minHeight,
    Ttk_Padding *paddingPtr)
{
    if ([NSApp macMinorVersion] > 8) {
    if ([NSApp macOSVersion] > 100800) {
	*minHeight = 24;
    } else {
	ButtonElementSize(clientData, elementRecord, tkwin, minWidth,
	    minHeight, paddingPtr);
    }
}

static void TreeHeaderElementDraw(
    void *clientData,
    void *elementRecord,
    TCL_UNUSED(void *),
    Tk_Window tkwin,
    Drawable d,
    Ttk_Box b,
    Ttk_State state)
{
    ThemeButtonParams *params = clientData;
    CGRect bounds = BoxToRect(d, b);
    const HIThemeButtonDrawInfo info = {
	.version = 0,
	.state = Ttk_StateTableLookup(ThemeStateTable, state),
	.kind = params->kind,
	.value = Ttk_StateTableLookup(TreeHeaderValueTable, state),
	.adornment = Ttk_StateTableLookup(TreeHeaderAdornmentTable, state),
    };

    BEGIN_DRAWING(d)
    if ([NSApp macMinorVersion] > 8) {
    if ([NSApp macOSVersion] > 100800) {

        /*
         * Compensate for the padding added in TreeHeaderElementSize, so
         * the larger heading will be drawn at the top of the widget.
         */

	bounds.origin.y -= 4;
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967



2968
2969
2970

2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982


2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000












3001

3002

3003
3004
3005
3006
3007
3008
3009
3044
3045
3046
3047
3048
3049
3050



3051
3052
3053
3054
3055

3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066


3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098

3099
3100
3101
3102
3103
3104
3105
3106
3107
3108







-
-
-
+
+
+


-
+










-
-
+
+


















+
+
+
+
+
+
+
+
+
+
+
+
-
+

+







#define TTK_TREEVIEW_STATE_OPEN         TTK_STATE_USER1
#define TTK_TREEVIEW_STATE_LEAF         TTK_STATE_USER2
static Ttk_StateTable DisclosureValueTable[] = {
    {kThemeDisclosureDown, TTK_TREEVIEW_STATE_OPEN, 0},
    {kThemeDisclosureRight, 0, 0},
};
static void DisclosureElementSize(
    void *clientData,
    void *elementRecord,
    Tk_Window tkwin,
    TCL_UNUSED(void *),
    TCL_UNUSED(void *),
    TCL_UNUSED(Tk_Window),
    int *minWidth,
    int *minHeight,
    Ttk_Padding *paddingPtr)
    TCL_UNUSED(Ttk_Padding *))
{
    SInt32 s;

    ChkErr(GetThemeMetric, kThemeMetricDisclosureTriangleWidth, &s);
    *minWidth = s;
    ChkErr(GetThemeMetric, kThemeMetricDisclosureTriangleHeight, &s);
    *minHeight = s;
}

static void DisclosureElementDraw(
    void *clientData,
    void *elementRecord,
    TCL_UNUSED(void *),
    TCL_UNUSED(void *),
    Tk_Window tkwin,
    Drawable d,
    Ttk_Box b,
    Ttk_State state)
{
    if (!(state & TTK_TREEVIEW_STATE_LEAF)) {
	int triangleState = TkMacOSXInDarkMode(tkwin) ?
	    kThemeStateInactive : kThemeStateActive;
	CGRect bounds = BoxToRect(d, b);
	const HIThemeButtonDrawInfo info = {
	    .version = 0,
	    .state = triangleState,
	    .kind = kThemeDisclosureTriangle,
	    .value = Ttk_StateTableLookup(DisclosureValueTable, state),
	    .adornment = kThemeAdornmentDrawIndicatorOnly,
	};

	BEGIN_DRAWING(d)
	if ([NSApp macOSVersion] >= 110000) {
	    CGFloat rgba[4];
	    NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
	    NSColor *stroke = [[NSColor textColor]
		colorUsingColorSpace: deviceRGB];
	    [stroke getComponents: rgba];
	    if (state & TTK_TREEVIEW_STATE_OPEN) {
		DrawOpenDisclosure(dc.context, bounds, 2, 8, rgba);
	    } else {
		DrawClosedDisclosure(dc.context, bounds, 2, 12, rgba);
	    }
	} else {
	ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation,
	    ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation,
	    NULL);
	}
	END_DRAWING
    }
}

static Ttk_ElementSpec DisclosureElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(NullElement),
3045
3046
3047
3048
3049
3050
3051
3052
3053


3054
3055
3056
3057
3058
3059
3060
3061


3062
3063
3064
3065

3066
3067
3068
3069
3070
3071
3072
3144
3145
3146
3147
3148
3149
3150


3151
3152
3153
3154
3155
3156
3157
3158


3159
3160
3161
3162
3163

3164
3165
3166
3167
3168
3169
3170
3171







-
-
+
+






-
-
+
+



-
+







    TTK_GROUP("Combobox.button", TTK_FILL_BOTH,
    TTK_GROUP("Combobox.padding", TTK_FILL_BOTH,
    TTK_NODE("Combobox.textarea", TTK_FILL_BOTH))))

/* Notebook tabs -- no focus ring */
TTK_LAYOUT("Tab",
    TTK_GROUP("Notebook.tab", TTK_FILL_BOTH,
    TTK_GROUP("Notebook.padding", TTK_EXPAND | TTK_FILL_BOTH,
    TTK_NODE("Notebook.label", TTK_EXPAND | TTK_FILL_BOTH))))
    TTK_GROUP("Notebook.padding", TTK_FILL_BOTH,
    TTK_NODE("Notebook.label", TTK_FILL_BOTH))))

/* Spinbox -- buttons 2px to the right of the field. */
TTK_LAYOUT("TSpinbox",
    TTK_GROUP("Spinbox.buttons", TTK_PACK_RIGHT,
    TTK_NODE("Spinbox.uparrow", TTK_PACK_TOP | TTK_STICK_E)
    TTK_NODE("Spinbox.downarrow", TTK_PACK_BOTTOM | TTK_STICK_E))
    TTK_GROUP("Spinbox.field", TTK_EXPAND | TTK_FILL_X,
    TTK_NODE("Spinbox.textarea", TTK_EXPAND | TTK_FILL_X)))
    TTK_GROUP("Spinbox.field", TTK_FILL_X,
    TTK_NODE("Spinbox.textarea", TTK_FILL_X)))

/* Progress bars -- track only */
TTK_LAYOUT("TProgressbar",
    TTK_NODE("Progressbar.track", TTK_EXPAND | TTK_FILL_BOTH))
    TTK_NODE("Progressbar.track", TTK_FILL_BOTH))

/* Treeview -- no border. */
TTK_LAYOUT("Treeview",
    TTK_GROUP("Treeview.field", TTK_FILL_BOTH,
    TTK_GROUP("Treeview.padding", TTK_FILL_BOTH,
    TTK_NODE("Treeview.treearea", TTK_FILL_BOTH))))

3083
3084
3085
3086
3087
3088
3089
3090

3091
3092
3093
3094
3095
3096
3097

3098
3099
3100
3101
3102
3103
3104
3105
3182
3183
3184
3185
3186
3187
3188

3189

3190
3191
3192
3193
3194

3195

3196
3197
3198
3199
3200
3201
3202







-
+
-





-
+
-







    TTK_NODE("Treeitem.image", TTK_PACK_LEFT)
    TTK_NODE("Treeitem.text", TTK_PACK_LEFT)))

/* Scrollbar Layout -- Buttons at the bottom (Snow Leopard and Lion only) */

TTK_LAYOUT("Vertical.TScrollbar",
    TTK_GROUP("Vertical.Scrollbar.trough", TTK_FILL_Y,
    TTK_NODE("Vertical.Scrollbar.thumb",
    TTK_NODE("Vertical.Scrollbar.thumb", TTK_FILL_BOTH)
    TTK_PACK_TOP | TTK_EXPAND | TTK_FILL_BOTH)
    TTK_NODE("Vertical.Scrollbar.downarrow", TTK_PACK_BOTTOM)
    TTK_NODE("Vertical.Scrollbar.uparrow", TTK_PACK_BOTTOM)))

TTK_LAYOUT("Horizontal.TScrollbar",
    TTK_GROUP("Horizontal.Scrollbar.trough", TTK_FILL_X,
    TTK_NODE("Horizontal.Scrollbar.thumb",
    TTK_NODE("Horizontal.Scrollbar.thumb", TTK_FILL_BOTH)
    TTK_PACK_LEFT | TTK_EXPAND | TTK_FILL_BOTH)
    TTK_NODE("Horizontal.Scrollbar.rightarrow", TTK_PACK_RIGHT)
    TTK_NODE("Horizontal.Scrollbar.leftarrow", TTK_PACK_RIGHT)))

TTK_END_LAYOUT_TABLE

/*----------------------------------------------------------------------
 * +++ Initialization --
Changes to tests/all.tcl.
1
2
3
4
5
6
7

8
9
10
11
12

13
14
15
16
17

18


19

1
2
3
4
5
6

7
8
9
10
11

12
13
14
15
16

17
18
19
20

21






-
+




-
+




-
+

+
+
-
+
# all.tcl --
#
# 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 (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.

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]
    [file join [tcltest::testsDirectory] constraints.tcl]
tcltest::configure -singleproc 1
set ErrorOnFailures [info exists env(ERROR_ON_FAILURES)]
encoding system utf-8
tcltest::runAllTests
if {[tcltest::runAllTests] && $ErrorOnFailures} {exit 1}
Changes to tests/arc.tcl.
48
49
50
51
52
53
54
55

56
57
58
59
60
61
62
63
64
65

66
67

68
69
70
71
72
73
74
48
49
50
51
52
53
54

55
56
57
58
59
60
61
62
63
64

65
66

67
68
69
70
71
72
73
74







-
+









-
+

-
+







.t.c create arc 340 450 460 570 -start 320 -extent 270 -fill $fill1 -width 14 \
	-style chord -outline {}
.t.c create arc 500 450 620 570 -start 350 -extent -110 -fill $fill1 -width 14 \
	-style chord -outline {}
.t.c addtag arc withtag all
.t.c addtag circle withtag [.t.c create oval 320 200 340 220 -fill MistyRose3]

.t.c bind arc <Any-Enter> {
.t.c bind arc <Enter> {
    set prevFill [lindex [.t.c itemconf current -fill] 4]
    set prevOutline [lindex [.t.c itemconf current -outline] 4]
    if {($prevFill != "") || ($prevOutline == "")} {
	.t.c itemconf current -fill $fill3
    }
    if {$prevOutline != ""} {
	.t.c itemconf current -outline $outline2
    }
}
.t.c bind arc <Any-Leave> {.t.c itemconf current -fill $prevFill -outline $prevOutline}
.t.c bind arc <Leave> {.t.c itemconf current -fill $prevFill -outline $prevOutline}

bind .t.c <1> {markarea %x %y}
bind .t.c <Button-1> {markarea %x %y}
bind .t.c <B1-Motion> {strokearea %x %y}

proc markarea {x y} {
    global areaX1 areaY1
    set areaX1 $x
    set areaY1 $y
}
85
86
87
88
89
90
91
92

93
94
95
96

97
98
99
100
101
102
103
85
86
87
88
89
90
91

92
93
94
95

96
97
98
99
100
101
102
103







-
+



-
+







}

bind .t.c <Control-f> {
    puts stdout "Enclosed: [.t.c find enclosed $areaX1 $areaY1 $areaX2 $areaY2]"
    puts stdout "Overlapping: [.t.c find overl $areaX1 $areaY1 $areaX2 $areaY2]"
}

bind .t.c <3> {puts stdout "%x %y"}
bind .t.c <Button-3> {puts stdout "%x %y"}

# The code below allows the circle to be move by shift-dragging.

bind .t.c <Shift-1> {
bind .t.c <Shift-Button-1> {
    set curx %x
    set cury %y
}

bind .t.c <Shift-B1-Motion> {
    .t.c move circle [expr {%x-$curx}] [expr {%y-$cury}]
    set curx %x
Changes to tests/bell.test.
1
2
3
4
5


6
7
8
9
10
11
12
13
14
15
16
17
18

19
20
21
22
23
24
25
1
2
3


4
5
6
7
8
9
10
11
12
13
14
15
16
17

18
19
20
21
22
23
24
25



-
-
+
+












-
+







# This file is a Tcl script to test out Tk's "bell" command.
# It is organized in the standard fashion for Tcl tests.
#
# Copyright (c) 1994 The Regents of the University of California.
# Copyright (c) 1998-2000 by Scriptics Corporation.
# Copyright © 1994 The Regents of the University of California.
# Copyright © 1998-2000 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
namespace import ::tcltest::*
eval tcltest::configure $argv
tcltest::loadTestedCommands

test bell-1.1 {bell command} -body {
    bell a
} -returnCodes {error} -result {bad option "a": must be -displayof or -nice}

test bell-1.2 {bell command} -body {
    bell a b 
    bell a b
} -returnCodes {error} -result {bad option "a": must be -displayof or -nice}

test bell-1.3 {bell command} -body {
    bell -displayof gorp
} -returnCodes {error} -result {bad window path name "gorp"}

test bell-1.4 {bell command} -body {
Changes to tests/bgerror.test.
1
2
3
4
5


6
7
8
9
10
11
12
1
2
3


4
5
6
7
8
9
10
11
12



-
-
+
+







# This file is a Tcl script to test the bgerror command.
# It is organized in the standard fashion for Tcl tests.
#
# Copyright (c) 1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
namespace import ::tcltest::*
eval tcltest::configure $argv
tcltest::loadTestedCommands

Changes to tests/bind.test.
1
2
3
4
5
6
7



8
9
10
11
12
13
14




15
16
17
18
19
20
21
1
2
3
4



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25




-
-
-
+
+
+







+
+
+
+







# This file is a Tcl script to test out Tk's "bind" and "bindtags"
# commands plus the procedures in tkBind.c.  It is organized in the
# standard fashion for Tcl tests.
#
# Copyright (c) 1994 The Regents of the University of California.
# Copyright (c) 1994-1995 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1994 The Regents of the University of California.
# Copyright © 1994-1995 Sun Microsystems, Inc.
# 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]


toplevel .t -width 100 -height 50
wm geom .t +0+0
update idletasks

foreach p [event info] {event delete $p}
foreach event [bind Test] {
32
33
34
35
36
37
38
39
40
41
42
43
44



45
46
47
48
49
50
51
52



53
54
55
56
57
58
59
60
61
36
37
38
39
40
41
42






43
44
45








46
47
48


49
50
51
52
53
54
55







-
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
+
+
+
-
-







    bind xyz <Enter> {}
    bind {a b} <Enter> {}
    bind .t <Enter> {}
}

# move the mouse pointer away of the testing area
# otherwise some spurious events may pollute the tests
# also, this will procure a known grab state at startup
# for tests mixing grabs and pointer warps
proc pointerAway {} {
    toplevel .top
    wm geometry .top 50x50-50-50
    update
toplevel .top
wm geometry .top 50x50-50-50
update
    # On KDE/Plasma _with_the_Aurorae_theme_ (at least), setting up the toplevel
    # will not be finished right after the above 'update'. The WM still
    # needs some time before the window is fully ready. For me 50 ms is enough,
    # but let's wait more (it depends on computer performance).
    after 100 ; update
    event generate .top <Button-1> -warp 1
    update
    destroy .top
event generate .top <Button-1> -warp 1
update
destroy .top
}
pointerAway

test bind-1.1 {bind command} -body {
    bind
} -returnCodes error -result {wrong # args: should be "bind window ?pattern? ?command?"}
test bind-1.2 {bind command} -body {
    bind a b c d
} -returnCodes error -result {wrong # args: should be "bind window ?pattern? ?command?"}
303
304
305
306
307
308
309
310

311
312

313
314
315
316
317
318
319
320
321
322
323
324
325
326
327



328
329
330
331
332
333
334
335


336
337
338
339
340
341
342
297
298
299
300
301
302
303

304
305

306
307
308
309
310
311
312
313
314
315
316
317
318



319
320
321
322
323
324
325
326
327


328
329
330
331
332
333
334
335
336







-
+

-
+












-
-
-
+
+
+






-
-
+
+







} -cleanup {
    destroy .t.c
} -result {}


test bind-6.1 {Tk_DeleteBindTable procedure} -body {
    canvas .t.c
    .t.c bind foo <1> {string 1}
    .t.c bind foo <Button-1> {string 1}
    .t.c create rectangle 0 0 100 100
    .t.c bind 1 <2> {string 2}
    .t.c bind 1 <Button-2> {string 2}
    destroy .t.c
} -cleanup {
    destroy .t.c
} -result {}
test bind-7.1 {Tk_CreateBinding procedure: bad binding} -body {
    canvas .t.c
    .t.c bind foo <
} -cleanup {
    destroy .t.c
} -returnCodes error -result {no event type or button # or keysym}
test bind-7.3 {Tk_CreateBinding procedure: append} -body {
    canvas .t.c
    .t.c bind foo <1> "button 1"
    .t.c bind foo <1> "+more button 1"
    .t.c bind foo <1>
    .t.c bind foo <Button-1> "button 1"
    .t.c bind foo <Button-1> "+more button 1"
    .t.c bind foo <Button-1>
} -cleanup {
    destroy .t.c
} -result {button 1
more button 1}
test bind-7.4 {Tk_CreateBinding procedure: append to non-existing} -body {
    canvas .t.c
    .t.c bind foo <1> "+button 1"
    .t.c bind foo <1>
    .t.c bind foo <Button-1> "+button 1"
    .t.c bind foo <Button-1>
} -cleanup {
    destroy .t.c
} -result {button 1}

test bind-8.1 {Tk_CreateBinding: error} -body {
    bind . <xyz> "xyz"
} -returnCodes error -result {bad event type or keysym "xyz"}
362
363
364
365
366
367
368
369

370
371
372

373
374
375
376
377
378
379
356
357
358
359
360
361
362

363
364
365

366
367
368
369
370
371
372
373







-
+


-
+







} -cleanup {
    destroy .t.f
} -result {{a c d} {a c} c {}}
test bind-9.3 {Tk_DeleteBinding procedure} -setup {
    set result {}
} -body {
    frame .t.f -class Test -width 150 -height 100
    foreach i {<1> <Meta-1> <Control-1> <Double-Alt-1>} {
    foreach i {<Button-1> <Meta-Button-1> <Control-Button-1> <Double-Alt-Button-1>} {
        bind .t.f $i "binding for $i"
    }
    foreach i {<Control-1> <Double-Alt-1> <1> <Meta-1>} {
    foreach i {<Control-Button-1> <Double-Alt-Button-1> <Button-1> <Meta-Button-1>} {
        bind .t.f $i {}
        lappend result [lsort [bind .t.f]]
    }
    return $result
} -cleanup {
    destroy .t.f
} -result {{<Button-1> <Double-Alt-Button-1> <Meta-Button-1>} {<Button-1> <Meta-Button-1>} <Meta-Button-1> {}}
390
391
392
393
394
395
396
397

398
399
400
401
402
403

404
405
406

407
408
409
410
411
412
413
414
415

416
417
418
419
420
421
422
423
424
425
426
427
428
429
430

431
432
433
434
435
436
437
438
439
440
441
442
443
444


445
446
447
448
449
450
451



452
453
454
455
456


457
458
459

460
461
462
463
464
465
466
467
468
469


470
471
472

473
474
475
476
477
478



479
480
481
482
483
484
485
486
487
488

489
490

491
492
493
494
495

496
497

498
499
500
501
502
503
504

505
506
507
508
509
510
511
512
513
514
515
516
517
518
519

520
521
522
523
524
525
526
384
385
386
387
388
389
390

391
392
393
394
395
396

397
398
399

400
401
402
403
404
405
406
407
408

409
410
411
412
413
414
415
416
417
418
419
420
421
422
423

424
425
426
427
428
429
430
431
432
433
434
435
436


437
438
439
440
441
442



443
444
445
446
447
448


449
450
451
452

453
454
455
456
457
458
459
460
461


462
463
464
465

466
467
468
469



470
471
472
473
474
475
476
477
478
479
480
481

482
483

484
485
486
487
488

489
490

491
492
493
494
495
496
497

498
499
500
501
502
503
504
505
506
507
508
509
510
511
512

513
514
515
516
517
518
519
520







-
+





-
+


-
+








-
+














-
+












-
-
+
+




-
-
-
+
+
+



-
-
+
+


-
+








-
-
+
+


-
+



-
-
-
+
+
+









-
+

-
+




-
+

-
+






-
+














-
+







    .t.c bind foo a
} -cleanup {
    destroy .t.c
} -result {Test}

test bind-11.1 {Tk_GetAllBindings procedure} -body {
    frame .t.f
    foreach i "! a \\\{ ~ <Delete> <space> <<Paste>> <Tab> <Linefeed> <less> <Meta-a> <Acircumflex>" {
    foreach i "! a \\\{ ~ <Delete> <space> <<Paste>> <Tab> <Linefeed> <Key-<> <Meta-a> <Â>" {
        bind .t.f $i Test
    }
    lsort [bind .t.f]
} -cleanup {
    destroy .t.f
} -result {! <<Paste>> <Key-Acircumflex> <Key-Delete> <Key-Linefeed> <Key-Tab> <Key-less> <Key-space> <Meta-Key-a> a \{ ~}
} -result "! <<Paste>> <Key-<> <Key-Delete> <Key-Linefeed> <Key-Tab> <Key-space> <Key-Â> <Meta-Key-a> a \\\{ ~"
test bind-11.2 {Tk_GetAllBindings procedure} -body {
    frame .t.f
    foreach i "<Double-1> <Triple-1> <Meta-Control-a> <Double-Alt-Enter> <1>" {
    foreach i "<Double-Button-1> <Triple-Button-1> <Meta-Control-a> <Double-Alt-Enter> <Button-1>" {
        bind .t.f $i Test
    }
    lsort [bind .t.f]
} -cleanup {
    destroy .t.f
} -result {<Button-1> <Control-Meta-Key-a> <Double-Alt-Enter> <Double-Button-1> <Triple-Button-1>}
test bind-11.3 {Tk_GetAllBindings procedure} -body {
    frame .t.f
    foreach i "<Double-Triple-1> abcd a<Leave>b" {
    foreach i "<Double-Triple-Button-1> abcd a<Leave>b" {
        bind .t.f $i Test
    }
    lsort [bind .t.f]
} -cleanup {
    destroy .t.f
} -result {<Triple-Button-1> a<Leave>b abcd}


test bind-12.1 {Tk_DeleteAllBindings procedure} -body {
    frame .t.f -class Test -width 150 -height 100
    destroy .t.f
} -result {}
test bind-12.2 {Tk_DeleteAllBindings procedure} -body {
    frame .t.f -class Test -width 150 -height 100
    foreach i "a b c <Meta-1> <Alt-a> <Control-a>" {
    foreach i "a b c <Meta-Button-1> <Alt-a> <Control-a>" {
        bind .t.f $i x
    }
    destroy .t.f
} -result {}

test bind-13.1 {Tk_BindEvent procedure} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind Test <KeyPress> {lappend x "%W %K Test KeyPress"}
    bind all <KeyPress> {lappend x "%W %K all KeyPress"}
    bind Test <Key> {lappend x "%W %K Test Key"}
    bind all <Key> {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 <Key-colon>
    event generate .t.f <Key-plus>
    event generate .t.f <Key-underscore>
    event generate .t.f <:>
    event generate .t.f <+>
    event generate .t.f <_>
    return $x
} -cleanup {
    destroy .t.f
    bind all <KeyPress> {}
    bind Test <KeyPress> {}
    bind all <Key> {}
    bind Test <Key> {}
    bind all _ {}
    bind Test : {}
} -result {{.t.f colon .t.f :} {.t.f colon Test :} {.t.f colon all KeyPress} {.t.f plus Test KeyPress} {.t.f plus all KeyPress} {.t.f underscore Test KeyPress} {.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
    update
    set x {}
} -body {
    bind Test <KeyPress> {lappend x "%W %K Test press any"; break}
    bind all <KeyPress> {continue; lappend x "%W %K all press any"}
    bind Test <Key> {lappend x "%W %K Test press any"; break}
    bind all <Key> {continue; lappend x "%W %K all press any"}
    bind .t.f : {lappend x "%W %K .t.f pressed colon"}

    event generate .t.f <Key-colon>
    event generate .t.f <:>
    return $x
} -cleanup {
    destroy .t.f
    bind all <KeyPress> {}
    bind Test <KeyPress> {}
} -result {{.t.f colon .t.f pressed colon} {.t.f colon Test press any}}
    bind all <Key> {}
    bind Test <Key> {}
} -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
    focus -force .t.f
    update
    set x {}
} -body {
    bind Test <KeyPress> {lappend x "%W %K Test press any"; error Test}
    bind Test <Key> {lappend x "%W %K Test press any"; error Test}
    bind .t.f : {lappend x "%W %K .t.f pressed colon"}
    event generate .t.f <Key-colon>
    event generate .t.f <:>
    update
    list $x $errorInfo
} -cleanup {
    destroy .t.f
    bind Test <KeyPress> {}
    bind Test <Key> {}
    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 <Key-colon>
        event generate .t.f <:>
    }
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind Test : {lappend x "%W %K Test"}
    bind .t.f : {lappend x "%W %K .t.f"}
    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 <Destroy> {lappend x "%W destroyed"}
    set x {}
    frame .t.g -gorp foo
} -cleanup {
    bind all <Destroy> {}
540
541
542
543
544
545
546
547

548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564

565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580


581
582
583
584
585
586

587
588
589
590
591
592
593
534
535
536
537
538
539
540

541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557

558
559
560
561
562
563
564
565
566
567
568
569
570
571
572


573
574
575
576
577
578
579

580
581
582
583
584
585
586
587







-
+
















-
+














-
-
+
+





-
+







    focus -force .t.f
    update
    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 <Key-colon>
    event generate .t.f <:>
    return $x
} -cleanup {
    bind Test : {}
    bind all : {}
    destroy .t.f
} -result {{.t.f (.t.f binding)} {.t.f (Test binding)} {.t.f (all binding)}}
test bind-13.8 {Tk_BindEvent procedure} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    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 <Key-colon>
    event generate .t.f <:>
    return $x
} -cleanup {
    bind Test : {}
    bind all : {}
    destroy .t.f
} -result {{.t.f (.t.f binding)} {.t.f (Test binding)} {.t.f (all binding)}}

test bind-13.9 {Tk_BindEvent procedure} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <1> {lappend x "%W z (.t.f <1> binding)"}
    bind .t.f <ButtonPress> {lappend x "%W z (.t.f <ButtonPress> binding)"}
    bind .t.f <Button-1> {lappend x "%W z (.t.f <Button-1> binding)"}
    bind .t.f <Button> {lappend x "%W z (.t.f <Button> binding)"}
    event generate .t.f <Button-1>
    event generate .t.f <Button-2>
    return $x
} -cleanup {
    destroy .t.f
} -result {{.t.f z (.t.f <1> binding)} {.t.f z (.t.f <ButtonPress> binding)}}
} -result {{.t.f z (.t.f <Button-1> binding)} {.t.f z (.t.f <Button> binding)}}
test bind-13.10 {Tk_BindEvent procedure: ignore NotifyInferior} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
622
623
624
625
626
627
628
629

630
631

632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647


648
649
650
651

652
653
654
655
656
657
658
616
617
618
619
620
621
622

623
624

625
626
627
628
629
630
631
632
633
634
635
636
637
638
639


640
641
642
643
644

645
646
647
648
649
650
651
652







-
+

-
+














-
-
+
+



-
+







    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <Key> "lappend x %K%#"
    bind .t.f <KeyRelease> "lappend x %K%#"
    event generate .t.f <Key-Shift_L> -serial 100 -when tail
    event generate .t.f <Shift_L> -serial 100 -when tail
    event generate .t.f <KeyRelease-Shift_L> -serial 101 -when tail
    event generate .t.f <Key-Shift_L> -serial 102 -when tail
    event generate .t.f <Shift_L> -serial 102 -when tail
    event generate .t.f <KeyRelease-Shift_L> -serial 103 -when tail
    update
} -cleanup {
    destroy .t.f
} -result {}
test bind-13.13 {Tk_BindEvent procedure: valid key detail} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Key> "lappend x Key%K"
    bind .t.f <KeyRelease> "lappend x Release%K"
    event generate .t.f <Key> -keysym colon
    event generate .t.f <KeyRelease> -keysym colon
    event generate .t.f <Key> -keysym :
    event generate .t.f <KeyRelease> -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
    set x {}
} -body {
942
943
944
945
946
947
948
949

950
951

952
953
954

955
956
957
958
959
960
961
936
937
938
939
940
941
942

943
944

945
946
947

948
949
950
951
952
953
954
955







-
+

-
+


-
+







    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bindtags .t.f {a b c d e f g h i j k l m n o p}
    foreach p [bindtags .t.f] {
        bind $p <1> "lappend x $p"
        bind $p <Button-1> "lappend x $p"
    }
    event generate .t.f <1>
    event generate .t.f <Button-1>
    return $x
} -cleanup {
    foreach p [bindtags .t.f] {bind $p <1> {}}
    foreach p [bindtags .t.f] {bind $p <Button-1> {}}
    destroy .t.f
} -result {a b c d e f g h i j k l m n o p}
test bind-13.34 {Tk_BindEvent procedure: multiple tags} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
972
973
974
975
976
977
978
979
980


981
982
983
984

985
986
987
988
989
990
991
992
993
994



995
996
997
998

999
1000
1001
1002
1003
1004
1005
966
967
968
969
970
971
972


973
974
975
976
977

978
979
980
981
982
983
984
985



986
987
988
989
990
991

992
993
994
995
996
997
998
999







-
-
+
+



-
+







-
-
-
+
+
+



-
+







test bind-13.35 {Tk_BindEvent procedure: execute binding} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <1> {lappend x 1}
    event generate .t.f <1>
    bind .t.f <Button-1> {lappend x 1}
    event generate .t.f <Button-1>
    return $x
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1
test bind-13.38 {Tk_BindEvent procedure: binding gets to run} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind Test <1> {lappend x Test}
    bind .t.f <1> {lappend x .t.f}
    event generate .t.f <1>
    bind Test <Button-1> {lappend x Test}
    bind .t.f <Button-1> {lappend x .t.f}
    event generate .t.f <Button-1>
    return $x
} -cleanup {
    destroy .t.f
    bind Test <1> {}
    bind Test <Button-1> {}
} -result {.t.f Test}
test bind-13.41 {Tk_BindEvent procedure: continue in script} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
1060
1061
1062
1063
1064
1065
1066
1067

1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085

1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100

1101
1102
1103
1104
1105
1106
1107

1108
1109
1110
1111
1112
1113
1114
1115
1116

1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132

1133
1134
1135
1136
1137
1138
1139

1140
1141
1142

1143
1144
1145
1146
1147
1148
1149

1150
1151
1152
1153
1154
1155
1156

1157
1158
1159

1160
1161
1162
1163
1164
1165
1166

1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177



1178
1179
1180
1181

1182
1183
1184
1185
1186
1187
1188
1189
1190

1191
1192
1193
1194

1195
1196
1197
1198
1199
1200
1201
1202
1203

1204
1205
1206
1207

1208
1209
1210
1211
1212
1213
1214
1215
1216

1217
1218
1219
1220

1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235



1236
1237
1238
1239

1240
1241
1242
1243
1244
1245
1246
1247
1248
1249


1250
1251
1252
1253

1254
1255
1256
1257
1258
1259
1260

1261
1262
1263
1264
1265
1266
1267
1268
1269
1270

1271
1272
1273
1274
1275
1276
1277

1278
1279
1280
1281
1282
1283
1284
1285
1286
1287

1288
1289
1290
1291
1292
1293
1294

1295
1296
1297
1298
1299
1300
1301
1302
1303
1304

1305
1306
1307
1308
1309
1310
1311

1312
1313
1314
1315
1316
1317
1318
1319
1320
1321

1322
1323
1324
1325
1326
1327
1328

1329
1330
1331
1332
1333
1334
1335
1336
1337
1338

1339
1340
1341
1342
1343
1344
1345

1346
1347
1348
1349
1350
1351
1352
1353
1354
1355

1356
1357
1358
1359
1360
1361
1362

1363
1364
1365
1366
1367
1368
1369
1370
1371
1372

1373
1374
1375
1376
1377
1378
1379

1380
1381
1382
1383
1384
1385
1386
1387
1388
1389

1390
1391
1392
1393
1394
1395
1396

1397
1398
1399
1400
1401
1402
1403
1404

1405
1406
1407
1408
1409
1410
1411

1412
1413
1414
1415
1416
1417
1418
1419

1420
1421
1422
1423
1424
1425
1426
1054
1055
1056
1057
1058
1059
1060

1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078

1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093

1094
1095
1096
1097
1098
1099
1100

1101
1102
1103
1104
1105
1106
1107
1108
1109

1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125

1126
1127
1128
1129
1130
1131
1132

1133
1134
1135

1136
1137
1138
1139
1140
1141
1142

1143
1144
1145
1146
1147
1148
1149

1150
1151
1152

1153
1154
1155
1156
1157
1158
1159

1160
1161
1162
1163
1164
1165
1166
1167
1168



1169
1170
1171
1172
1173
1174

1175
1176
1177
1178
1179
1180
1181
1182
1183

1184
1185
1186
1187

1188
1189
1190
1191
1192
1193
1194
1195
1196

1197
1198
1199
1200

1201
1202
1203
1204
1205
1206
1207
1208
1209

1210
1211
1212
1213

1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226



1227
1228
1229
1230
1231
1232

1233
1234
1235
1236
1237
1238
1239
1240
1241


1242
1243
1244
1245
1246

1247
1248
1249
1250
1251
1252
1253

1254
1255
1256
1257
1258
1259
1260
1261
1262
1263

1264
1265
1266
1267
1268
1269
1270

1271
1272
1273
1274
1275
1276
1277
1278
1279
1280

1281
1282
1283
1284
1285
1286
1287

1288
1289
1290
1291
1292
1293
1294
1295
1296
1297

1298
1299
1300
1301
1302
1303
1304

1305
1306
1307
1308
1309
1310
1311
1312
1313
1314

1315
1316
1317
1318
1319
1320
1321

1322
1323
1324
1325
1326
1327
1328
1329
1330
1331

1332
1333
1334
1335
1336
1337
1338

1339
1340
1341
1342
1343
1344
1345
1346
1347
1348

1349
1350
1351
1352
1353
1354
1355

1356
1357
1358
1359
1360
1361
1362
1363
1364
1365

1366
1367
1368
1369
1370
1371
1372

1373
1374
1375
1376
1377
1378
1379
1380
1381
1382

1383
1384
1385
1386
1387
1388
1389

1390
1391
1392
1393
1394
1395
1396
1397

1398
1399
1400
1401
1402
1403
1404

1405
1406
1407
1408
1409
1410
1411
1412

1413
1414
1415
1416
1417
1418
1419
1420







-
+

















-
+














-
+






-
+








-
+















-
+






-
+


-
+






-
+






-
+


-
+






-
+








-
-
-
+
+
+



-
+








-
+



-
+








-
+



-
+








-
+



-
+












-
-
-
+
+
+



-
+








-
-
+
+



-
+






-
+









-
+






-
+









-
+






-
+









-
+






-
+









-
+






-
+









-
+






-
+









-
+






-
+









-
+






-
+









-
+






-
+







-
+






-
+







-
+







    event generate .t.f <Key-1>
    event generate .t.f <KeyRelease-1>
    event generate .t.f <Key-2>
    event generate .t.f <KeyRelease-2>
    return $x
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1
test bind-15.2 {MatchPatterns procedure, ignoring type mismatches} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f 12 {set x 1}
    set x 0
    event generate .t.f <Key-1>
    event generate .t.f <Enter>
    event generate .t.f <KeyRelease-1>
    event generate .t.f <Leave>
    event generate .t.f <Key-2>
    event generate .t.f <KeyRelease-2>
    return $x
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1
test bind-15.3 {MatchPatterns procedure, ignoring type mismatches} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f 12 {set x 1}
    set x 0
    event generate .t.f <Key-1>
    event generate .t.f <Button-1>
    event generate .t.f <Key-2>
    return $x
} -cleanup {
    destroy .t.f
} -result {0}
} -result 0
test bind-15.4 {MatchPatterns procedure, ignoring type mismatches} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <Double-1> {set x 1}
    bind .t.f <Double-Button-1> {set x 1}
    set x 0
    event generate .t.f <Button-1>
    event generate .t.f <ButtonRelease-1>
    event generate .t.f <Button-1>
    event generate .t.f <ButtonRelease-1>
    return $x
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1
test bind-15.5 {MatchPatterns procedure, ignoring type mismatches} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <Double-ButtonRelease> {set x 1}
    set x 0
    event generate .t.f <Button-1>
    event generate .t.f <ButtonRelease-1>
    event generate .t.f <Button-2>
    event generate .t.f <ButtonRelease-2>
    return $x
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1
test bind-15.6 {MatchPatterns procedure, ignoring type mismatches} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <Double-1> {set x 1}
    bind .t.f <Double-Button-1> {set x 1}
    set x 0
    event generate .t.f <Button-1>
    event generate .t.f <Key-a>
    event generate .t.f <a>
    event generate .t.f <ButtonRelease-1>
    event generate .t.f <Button-1>
    event generate .t.f <ButtonRelease-1>
    return $x
} -cleanup {
    destroy .t.f
} -result {0}
} -result 0
test bind-15.7 {MatchPatterns procedure, ignoring type mismatches} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <Double-1> {set x 1}
    bind .t.f <Double-Button-1> {set x 1}
    set x 0
    event generate .t.f <Button-1>
    event generate .t.f <Key-Shift_L>
    event generate .t.f <Shift_L>
    event generate .t.f <ButtonRelease-1>
    event generate .t.f <Button-1>
    event generate .t.f <ButtonRelease-1>
    return $x
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1
test bind-15.8 {MatchPatterns procedure, ignoring type mismatches} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f ab {set x 1}
    set x 0
    event generate .t.f <Key-a>
    event generate .t.f <Key-c>
    event generate .t.f <Key-b>
    event generate .t.f <a>
    event generate .t.f <c>
    event generate .t.f <b>
    return $x
} -cleanup {
    destroy .t.f
} -result {0}
} -result 0
test bind-15.9 {MatchPatterns procedure, modifier checks} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <M1-M2-Key> {set x 1}
    set x 0
    event generate .t.f <Key-a> -state 0x18
    event generate .t.f <a> -state 0x18
    return $x
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1
test bind-15.10 {MatchPatterns procedure, modifier checks} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <M1-M2-Key> {set x 1}
    set x 0
    event generate .t.f <Key-a> -state 0xfc
    event generate .t.f <a> -state 0xfc
    return $x
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1
test bind-15.11 {MatchPatterns procedure, modifier checks} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <M1-M2-Key> {set x 1}
    set x 0
    event generate .t.f <Key-a> -state 0x8
    event generate .t.f <a> -state 0x8
    return $x
} -cleanup {
    destroy .t.f
} -result {0}
} -result 0
test bind-15.12 {MatchPatterns procedure, ignore modifier presses and releases} -constraints {
    nonPortable
} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    # This test is non-portable because the Shift_L keysym may behave
    # differently on some platforms.
    bind .t.f aB {set x 1}
    set x 0
    event generate .t.f <Key-a>
    event generate .t.f <Key-Shift_L>
    event generate .t.f <Key-b> -state 1
    event generate .t.f <a>
    event generate .t.f <Shift_L>
    event generate .t.f <b> -state 1
    return $x
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1
test bind-15.13 {MatchPatterns procedure, checking detail} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f ab {set x 1}
    set x 0
    event generate .t.f <Key-a>
    event generate .t.f <Key-c>
    event generate .t.f <a>
    event generate .t.f <c>
    return $x
} -cleanup {
    destroy .t.f
} -result {0}
} -result 0
test bind-15.14 {MatchPatterns procedure, checking "nearby"} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <Double-1> {set x 1}
    bind .t.f <Double-Button-1> {set x 1}
    set x 0
    event generate .t.f <Button-2>
    event generate .t.f <ButtonRelease-2>
    event generate .t.f <Button-1> -x 30 -y 40
    event generate .t.f <Button-1> -x 31 -y 39
    event generate .t.f <ButtonRelease-1>
    return $x
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1
test bind-15.15 {MatchPatterns procedure, checking "nearby"} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <Double-1> {set x 1}
    bind .t.f <Double-Button-1> {set x 1}
    set x 0
    event generate .t.f <Button-2>
    event generate .t.f <ButtonRelease-2>
    event generate .t.f <Button-1> -x 30 -y 40
    event generate .t.f <Button-1> -x 29 -y 41
    event generate .t.f <ButtonRelease-1>
    return $x
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1
test bind-15.16 {MatchPatterns procedure, checking "nearby"} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <Double-1> {set x 1}
    bind .t.f <Double-Button-1> {set x 1}
    set x 0
    event generate .t.f <Button-2>
    event generate .t.f <ButtonRelease-2>
    event generate .t.f <Button-1> -x 30 -y 40
    event generate .t.f <Button-1> -x 40 -y 40
    event generate .t.f <ButtonRelease-2>
    return $x
} -cleanup {
    destroy .t.f
} -result {0}
} -result 0
test bind-15.17 {MatchPatterns procedure, checking "nearby"} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <Double-1> {set x 1}
    bind .t.f <Double-Button-1> {set x 1}
    set x 0
    event generate .t.f <Button-2>
    event generate .t.f <ButtonRelease-2>
    event generate .t.f <Button-1> -x 30 -y 40
    event generate .t.f <Button-1> -x 20 -y 40
    event generate .t.f <ButtonRelease-1>
    return $x
} -cleanup {
    destroy .t.f
} -result {0}
} -result 0
test bind-15.18 {MatchPatterns procedure, checking "nearby"} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <Double-1> {set x 1}
    bind .t.f <Double-Button-1> {set x 1}
    set x 0
    event generate .t.f <Button-2>
    event generate .t.f <ButtonRelease-2>
    event generate .t.f <Button-1> -x 30 -y 40
    event generate .t.f <Button-1> -x 30 -y 30
    event generate .t.f <ButtonRelease-1>
    return $x
} -cleanup {
    destroy .t.f
} -result {0}
} -result 0
test bind-15.19 {MatchPatterns procedure, checking "nearby"} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <Double-1> {set x 1}
    bind .t.f <Double-Button-1> {set x 1}
    set x 0
    event generate .t.f <Button-2>
    event generate .t.f <ButtonRelease-2>
    event generate .t.f <Button-1> -x 30 -y 40
    event generate .t.f <Button-1> -x 30 -y 50
    event generate .t.f <ButtonRelease-1>
    return $x
} -cleanup {
    destroy .t.f
} -result {0}
} -result 0
test bind-15.20 {MatchPatterns procedure, checking "nearby"} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <Double-1> {set x 1}
    bind .t.f <Double-Button-1> {set x 1}
    set x 0
    event generate .t.f <Button-2>
    event generate .t.f <ButtonRelease-2>
    event generate .t.f <Button-1> -time 300
    event generate .t.f <Button-1> -time 700
    event generate .t.f <ButtonRelease-1>
    return $x
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1
test bind-15.21 {MatchPatterns procedure, checking "nearby"} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <Double-1> {set x 1}
    bind .t.f <Double-Button-1> {set x 1}
    set x 0
    event generate .t.f <Button-2>
    event generate .t.f <ButtonRelease-2>
    event generate .t.f <Button-1> -time 300
    event generate .t.f <Button-1> -time 900
    event generate .t.f <ButtonRelease-1>
    return $x
} -cleanup {
    destroy .t.f
} -result {0}
} -result 0
test bind-15.22 {MatchPatterns procedure, time wrap-around} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <Double-1> {set x 1}
    bind .t.f <Double-Button-1> {set x 1}
    set x 0
    event generate .t.f <Button-1> -time -100
    event generate .t.f <Button-1> -time 200
    event generate .t.f <ButtonRelease-1>
    return $x
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1
test bind-15.23 {MatchPatterns procedure, time wrap-around} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <Double-1> {set x 1}
    bind .t.f <Double-Button-1> {set x 1}
    set x 0
    event generate .t.f <Button-1> -time -100
    event generate .t.f <Button-1> -time 500
    event generate .t.f <ButtonRelease-1>
    return $x
} -cleanup {
    destroy .t.f
} -result {0}
} -result 0
test bind-15.24 {MatchPatterns procedure, virtual event} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
1478
1479
1480
1481
1482
1483
1484
1485

1486
1487
1488
1489
1490
1491
1492

1493
1494
1495
1496
1497
1498
1499

1500
1501
1502
1503
1504
1505
1506

1507
1508
1509
1510
1511
1512
1513

1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531


1532
1533
1534
1535
1536
1537
1538

1539
1540
1541
1542
1543
1544
1545
1546
1547
1548

1549
1550
1551
1552

1553
1554
1555
1556
1557
1558
1559
1560
1561
1562

1563
1564
1565
1566

1567
1568
1569
1570
1571
1572
1573
1574
1575
1576



1577
1578
1579
1580
1581
1582
1583
1584
1585


1586
1587
1588
1589
1590
1591
1592
1472
1473
1474
1475
1476
1477
1478

1479
1480
1481
1482
1483
1484
1485

1486
1487
1488
1489
1490
1491
1492

1493
1494
1495
1496
1497
1498
1499

1500
1501
1502
1503
1504
1505
1506

1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523


1524
1525
1526
1527
1528
1529
1530
1531

1532
1533
1534
1535
1536
1537
1538
1539
1540
1541

1542
1543
1544
1545

1546
1547
1548
1549
1550
1551
1552
1553
1554
1555

1556
1557
1558
1559

1560
1561
1562
1563
1564
1565
1566
1567



1568
1569
1570
1571
1572
1573
1574
1575
1576
1577


1578
1579
1580
1581
1582
1583
1584
1585
1586







-
+






-
+






-
+






-
+






-
+
















-
-
+
+






-
+









-
+



-
+









-
+



-
+







-
-
-
+
+
+







-
-
+
+







} -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
    focus -force .t.f
    update
} -body {
    bind .t.f <KeyPress> {set x 0}
    bind .t.f <Key> {set x 0}
    bind .t.f 1 {set x 1}
    set x none
    event generate .t.f <Key-1>
    return $x
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1
test bind-15.28 {MatchPatterns procedure, conflict resolution} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <KeyPress> {set x 0}
    bind .t.f <Key> {set x 0}
    bind .t.f 1 {set x 1}
    set x none
    event generate .t.f <Key-2>
    return $x
} -cleanup {
    destroy .t.f
} -result {0}
} -result 0
test bind-15.29 {MatchPatterns procedure, conflict resolution} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <KeyPress> {lappend x 0}
    bind .t.f <Key> {lappend x 0}
    bind .t.f 1 {lappend x 1}
    bind .t.f 21 {lappend x 2}
    set x none
    event generate .t.f <Key-2>
    event generate .t.f <KeyRelease-2>
    event generate .t.f <Key-1>
    set x
} -cleanup {
    destroy .t.f
} -result {none 0 2}
test bind-15.30 {MatchPatterns procedure, conflict resolution} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <ButtonPress> {set x 0}
    bind .t.f <1> {set x 1}
    bind .t.f <Button> {set x 0}
    bind .t.f <Button-1> {set x 1}
    set x none
    event generate .t.f <Button-1>
    event generate .t.f <ButtonRelease-1>
    return $x
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1
test bind-15.31 {MatchPatterns procedure, conflict resolution} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <M1-Key> {set x 0}
    bind .t.f <M2-Key> {set x 1}
    event generate .t.f <Key-a> -state 0x18
    event generate .t.f <a> -state 0x18
    return $x
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1
test bind-15.32 {MatchPatterns procedure, conflict resolution} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <M2-Key> {set x 0}
    bind .t.f <M1-Key> {set x 1}
    set x none
    event generate .t.f <Key-a> -state 0x18
    event generate .t.f <a> -state 0x18
    return $x
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1
test bind-15.33 {MatchPatterns procedure, conflict resolution} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <1> {lappend x single}
    bind Test <1> {lappend x single(Test)}
    bind Test <Double-1> {lappend x double(Test)}
    bind .t.f <Button-1> {lappend x single}
    bind Test <Button-1> {lappend x single(Test)}
    bind Test <Double-Button-1> {lappend x double(Test)}
    event generate .t.f <Button-1>
    event generate .t.f <Button-1>
    event generate .t.f <Button-1>
    event generate .t.f <ButtonRelease-1>
    set x
} -cleanup {
    destroy .t.f
    bind Test <1> {}
    bind Test <Double-1> {}
    bind Test <Button-1> {}
    bind Test <Double-Button-1> {}
} -result {single single(Test) single double(Test) single double(Test)}


test bind-16.1 {ExpandPercents procedure} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
1607
1608
1609
1610
1611
1612
1613
1614

1615
1616
1617
1618
1619
1620
1621
1601
1602
1603
1604
1605
1606
1607

1608
1609
1610
1611
1612
1613
1614
1615







-
+







} -body {
    bind .t.f <Enter> {set x %#}
    set x none
    event generate .t.f <Enter> -serial 1234
    set x
} -cleanup {
    destroy .t.f
} -result {1234}
} -result 1234
test bind-16.3 {ExpandPercents procedure} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <Configure> {set x %a}
1634
1635
1636
1637
1638
1639
1640
1641

1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654

1655
1656
1657
1658
1659
1660
1661
1628
1629
1630
1631
1632
1633
1634

1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647

1648
1649
1650
1651
1652
1653
1654
1655







-
+












-
+







    bind .t.f <Button> {set x %b}
    set x none
    event generate .t.f <Button-3>
    event generate .t.f <ButtonRelease-3>
    set x
} -cleanup {
    destroy .t.f
} -result {3}
} -result 3
test bind-16.5 {ExpandPercents procedure} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <Expose> {set x %c}
    set x none
    event generate .t.f <Expose> -count 47
    set x
} -cleanup {
    destroy .t.f
} -result {47}
} -result 47
test bind-16.6 {ExpandPercents procedure} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <Enter> {set x %d}
1751
1752
1753
1754
1755
1756
1757
1758

1759
1760
1761
1762
1763
1764
1765
1745
1746
1747
1748
1749
1750
1751

1752
1753
1754
1755
1756
1757
1758
1759







-
+







} -body {
    bind .t.f <Enter> {set x %f}
    set x none
    event generate .t.f <Enter> -focus 1
    return $x
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1
test bind-16.14 {ExpandPercents procedure} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <Expose> {set x "%x %y %w %h"}
1790
1791
1792
1793
1794
1795
1796
1797

1798
1799
1800
1801
1802
1803
1804
1784
1785
1786
1787
1788
1789
1790

1791
1792
1793
1794
1795
1796
1797
1798







-
+







} -body {
    bind .t.f <Key> {set x "%k"}
    set x none
    event generate .t.f <Key> -keycode 146
    set x
} -cleanup {
    destroy .t.f
} -result {146}
} -result 146
test bind-16.17 {ExpandPercents procedure} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <Enter> {set x "%m"}
1856
1857
1858
1859
1860
1861
1862
1863

1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876

1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889

1890
1891
1892
1893
1894
1895
1896
1850
1851
1852
1853
1854
1855
1856

1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869

1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882

1883
1884
1885
1886
1887
1888
1889
1890







-
+












-
+












-
+







} -body {
    bind .t.f <Map> {set x "%o"}
    set x none
    event generate .t.f <Map> -override 1 -window .t.f
    return $x
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1
test bind-16.22 {ExpandPercents procedure} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <Reparent> {set x "%o"}
    set x none
    event generate .t.f <Reparent> -override true -window .t.f
    return $x
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1
test bind-16.23 {ExpandPercents procedure} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <Configure> {set x "%o"}
    set x none
    event generate .t.f <Configure> -override 1 -window .t.f
    return $x
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1
test bind-16.24 {ExpandPercents procedure} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <Circulate> {set x "%p"}
1915
1916
1917
1918
1919
1920
1921
1922

1923
1924
1925
1926
1927
1928
1929

1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942

1943
1944
1945
1946
1947
1948
1949
1909
1910
1911
1912
1913
1914
1915

1916
1917
1918
1919
1920
1921
1922

1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935

1936
1937
1938
1939
1940
1941
1942
1943







-
+






-
+












-
+







} -result {PlaceOnBottom}
test bind-16.26 {ExpandPercents procedure} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <1> {set x "%s"}
    bind .t.f <Button-1> {set x "%s"}
    set x none
    event generate .t.f <Button-1> -state 1402
    event generate .t.f <ButtonRelease-1>
    set x
} -cleanup {
    destroy .t.f
} -result {1402}
} -result 1402
test bind-16.27 {ExpandPercents procedure} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <Enter> {set x "%s"}
    set x none
    event generate .t.f <Enter> -state 0x3ff
    set x
} -cleanup {
    destroy .t.f
} -result {1023}
} -result 1023
test bind-16.28 {ExpandPercents procedure} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <Visibility> {set x "%s"}
1988
1989
1990
1991
1992
1993
1994
1995

1996
1997
1998
1999
2000
2001
2002
1982
1983
1984
1985
1986
1987
1988

1989
1990
1991
1992
1993
1994
1995
1996







-
+







    bind .t.f <Button> {set x "%t"}
    set x none
    event generate .t.f <Button> -time 4294
    event generate .t.f <ButtonRelease>
    set x
} -cleanup {
    destroy .t.f
} -result {4294}
} -result 4294
test bind-16.32 {ExpandPercents procedure} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <Button> {set x "%x %y"}
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057












2058
2059
2060
2061

2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074

2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087

2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105








2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118

2119
2120
2121
2122

2123
2124
2125
2126
2127
2128
2129
2130
2131

2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148

2149
2150
2151
2152
2153
2154
2155
2033
2034
2035
2036
2037
2038
2039












2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054

2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067

2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080

2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091








2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111

2112
2113
2114
2115

2116
2117
2118
2119
2120
2121
2122
2123
2124

2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141

2142
2143
2144
2145
2146
2147
2148
2149







-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+



-
+












-
+












-
+










-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+












-
+



-
+








-
+
















-
+







    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Key> {lappend x "%A"}
    event generate .t.f <Key-a>
    event generate .t.f <Key-A> -state 1
    event generate .t.f <Key-Tab>
    event generate .t.f <Key-Return>
    event generate .t.f <Key-F1>
    event generate .t.f <Key-Shift_L>
    event generate .t.f <Key-space>
    event generate .t.f <Key-dollar> -state 1
    event generate .t.f <Key-braceleft> -state 1
    event generate .t.f <Key-Multi_key>
    event generate .t.f <Key-e>
    event generate .t.f <Key-apostrophe>
    event generate .t.f <a>
    event generate .t.f <A> -state 1
    event generate .t.f <Tab>
    event generate .t.f <Return>
    event generate .t.f <F1>
    event generate .t.f <Shift_L>
    event generate .t.f <space>
    event generate .t.f <dollar> -state 1
    event generate .t.f <braceleft> -state 1
    event generate .t.f <Multi_key>
    event generate .t.f <e>
    event generate .t.f <apostrophe>
    set x
} -cleanup {
    destroy .t.f
} -result {a A {	} {\r} {{}} {{}} { } {\$} \\\{ {{}} {{}} \u00e9}
} -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
} -body {
    bind .t.f <Configure> {set x "%B"}
    set x none
    event generate .t.f <Configure> -borderwidth 24 -window .t.f
    set x
} -cleanup {
    destroy .t.f
} -result {24}
} -result 24
test bind-16.37 {ExpandPercents procedure} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <Enter> {set x "%E"}
    set x none
    event generate .t.f <Enter> -sendevent 1
    return $x
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1
test bind-16.38 {ExpandPercents procedure} -constraints {
    nonPortable
} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Key> {lappend x %K}
    event generate .t.f <Key-a>
    event generate .t.f <Key-A> -state 1
    event generate .t.f <Key-Tab>
    event generate .t.f <Key-F1>
    event generate .t.f <Key-Shift_L>
    event generate .t.f <Key-space>
    event generate .t.f <Key-dollar> -state 1
    event generate .t.f <Key-braceleft> -state 1
    event generate .t.f <a>
    event generate .t.f <A> -state 1
    event generate .t.f <Tab>
    event generate .t.f <F1>
    event generate .t.f <Shift_L>
    event generate .t.f <space>
    event generate .t.f <dollar> -state 1
    event generate .t.f <braceleft> -state 1
    set x
} -cleanup {
    destroy .t.f
} -result {a A Tab F1 Shift_L space dollar braceleft}
test bind-16.39 {ExpandPercents procedure} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <Key> {set x "%N"}
    set x none
    event generate .t.f <Key-space>
    event generate .t.f <space>
    set x
} -cleanup {
    destroy .t.f
} -result {32}
} -result 32
test bind-16.40 {ExpandPercents procedure} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <Key> {set x "%S"}
    set x none
    event generate .t.f <Key-space> -subwindow .t
    event generate .t.f <space> -subwindow .t
    set x
} -cleanup {
    destroy .t.f
} -result [winfo id .t]
test bind-16.41 {ExpandPercents procedure} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <Key> {set x "%T"}
    set x none
    event generate .t.f <Key>
    set x
} -cleanup {
    destroy .t.f
} -result {2}
} -result 2
test bind-16.42 {ExpandPercents procedure} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
2197
2198
2199
2200
2201
2202
2203
2204

2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225

2226
2227
2228
2229
2230
2231
2232













2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249

2250
2251
2252
2253
2254
2255
2256
2257
2258
2259

2260
2261
2262
2263
2264
2265

2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277


2278
2279
2280
2281

2282
2283
2284
2285
2286
2287
2288
2191
2192
2193
2194
2195
2196
2197

2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218

2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255

2256
2257
2258
2259
2260
2261
2262
2263
2264
2265

2266
2267
2268
2269
2270
2271

2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282


2283
2284
2285
2286
2287

2288
2289
2290
2291
2292
2293
2294
2295







-
+




















-
+







+
+
+
+
+
+
+
+
+
+
+
+
+
















-
+









-
+





-
+










-
-
+
+



-
+







    foreach p [event info] {event delete $p}
    update
} -body {
    bind .t.e <Key> {set x "%M"}
    bind Entry <Key> {set y "%M"}
    bind all <Key> {set z "%M"}
    set x none; set y none; set z none
    event gen .t.e <Key-a>
    event gen .t.e <a>
    list $x $y $z
} -cleanup {
    destroy .t.e
    bind all <Key> $savedBind(All)
    bind Entry <Key> $savedBind(Entry)
    unset savedBind
} -result {0 1 2}
test bind-16.46 {ExpandPercents procedure} -setup {
    set savedBind(All) [bind all <Key>]
    set savedBind(Entry) [bind Entry <Key>]
    entry .t.e
    pack .t.e
    focus -force .t.e
    foreach p [event info] {event delete $p}
    update
} -body {
    bind all <Key> {set z "%M"}
    bind Entry <Key> {set y "%M"}
    bind .t.e <Key> {set x "%M"}
    set x none; set y none; set z none
    event gen .t.e <Key-a>
    event gen .t.e <a>
    list $x $y $z
} -cleanup {
    destroy .t.e
    bind Entry <Key> $savedBind(Entry)
    bind all <Key> $savedBind(All)
    unset savedBind
} -result {0 1 2}
test bind-16.47 {ExpandPercents procedure} -constraints {aquaOrWin32 needsTcl87} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <Key> {set x "%K"}
    set x none
    event generate .t.f <Key> -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 {
    event xyz
} -returnCodes error -result {bad option "xyz": must be add, delete, generate, or info}
test bind-17.3 {event command: add} -body {
    event add
} -returnCodes error -result {wrong # args: should be "event add virtual sequence ?sequence ...?"}
test bind-17.4 {event command: add 1} -body {
    event delete <<Paste>>
    event add <<Paste>> <Control-v>
    event info <<Paste>>
} -cleanup {
    event delete <<Paste>> <Control-v>
} -result {<Control-Key-v>}
} -result <Control-Key-v>
test bind-17.5 {event command: add 2} -body {
    event delete <<Paste>>
    event add <<Paste>> <Control-v> <Button-2>
    lsort [event info <<Paste>>]
} -cleanup {
    event delete <<Paste>> <Control-v> <Button-2>
} -result {<Button-2> <Control-Key-v>}

test bind-17.6 {event command: add with error} -body {
    event add <<Paste>> <Control-v> <Button-2> abc <xyz> <1>
    event add <<Paste>> <Control-v> <Button-2> abc <xyz> <Button-1>
} -cleanup {
    event delete <<Paste>>
} -returnCodes error -result {bad event type or keysym "xyz"}
test bind-17.7 {event command: add with error} -body {
    event delete <<Paste>>
    catch {event add <<Paste>> <Control-v> <Button-2> abc <xyz> <1>}
    catch {event add <<Paste>> <Control-v> <Button-2> abc <xyz> <Button-1>}
    lsort [event info <<Paste>>]
} -cleanup {
    event delete <<Paste>>
} -result {<Button-2> <Control-Key-v> abc}

test bind-17.8 {event command: delete} -body {
    event delete
} -returnCodes error -result {wrong # args: should be "event delete virtual ?sequence ...?"}
test bind-17.9 {event command: delete many} -body {
    event delete <<Paste>>
    event add <<Paste>> <3> <1> <2> t
    event delete <<Paste>> <1> <2>
    event add <<Paste>> <Button-3> <Button-1> <Button-2> t
    event delete <<Paste>> <Button-1> <Button-2>
    lsort [event info <<Paste>>]
} -cleanup {
    event delete <<Paste>>
    event delete <<Paste>> <3> t
    event delete <<Paste>> <Button-3> t
} -result {<Button-3> t}
test bind-17.10 {event command: delete all} -body {
    event add <<Paste>> a b
    event delete <<Paste>>
    event info <<Paste>>
} -cleanup {
    event delete <<Paste>> a b
2322
2323
2324
2325
2326
2327
2328
2329
2330


2331
2332
2333
2334

2335
2336
2337
2338
2339
2340
2341
2329
2330
2331
2332
2333
2334
2335


2336
2337
2338
2339
2340

2341
2342
2343
2344
2345
2346
2347
2348







-
-
+
+



-
+







test bind-17.16 {event command: generate} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <1> "lappend x 1"
    event generate .t.f <1>
    bind .t.f <Button-1> "lappend x 1"
    event generate .t.f <Button-1>
    set x
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1
test bind-17.17 {event command: generate} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    event generate .t.f <xyz>
2355
2356
2357
2358
2359
2360
2361
2362

2363
2364
2365
2366
2367
2368
2369
2370

2371
2372
2373
2374
2375
2376
2377
2362
2363
2364
2365
2366
2367
2368

2369
2370
2371
2372
2373
2374
2375
2376

2377
2378
2379
2380
2381
2382
2383
2384







-
+







-
+







} -returnCodes error -result {bad event type or keysym "Ctrl"}
test bind-18.3 {CreateVirtualEvent procedure: new physical} -body {
    event delete <<xyz>>
    event add <<xyz>> <Control-v>
    event info <<xyz>>
} -cleanup {
    event delete <<xyz>>
} -result {<Control-Key-v>}
} -result <Control-Key-v>
test bind-18.4 {CreateVirtualEvent procedure: duplicate physical} -body {
    event delete <<xyz>>
    event add <<xyz>> <Control-v>
    event add <<xyz>> <Control-v>
    event info <<xyz>>
} -cleanup {
    event delete <<xyz>>
} -result {<Control-Key-v>}
} -result <Control-Key-v>
test bind-18.5 {CreateVirtualEvent procedure: existing physical} -body {
    foreach p [event info] {event delete $p}
    event add <<xyz>> <Control-v>
    event add <<abc>> <Control-v>
    list [lsort [event info]] [event info <<xyz>>] [event info <<abc>>]
} -cleanup {
    event delete <<xyz>>
2412
2413
2414
2415
2416
2417
2418
2419

2420
2421
2422
2423
2424
2425
2426
2419
2420
2421
2422
2423
2424
2425

2426
2427
2428
2429
2430
2431
2432
2433







-
+







} -result {}
test bind-19.4 {DeleteVirtualEvent procedure: delete 1, not owned} -setup {
    event delete <<xyz>>
} -body {
    event add <<xyz>> <Control-v>
    event delete <<xyz>> <Button-1>
    event info <<xyz>>
} -result {<Control-Key-v>}
} -result <Control-Key-v>
test bind-19.5 {DeleteVirtualEvent procedure: delete 1, badly formed} -body {
    event add <<xyz>> <Control-v>
    event delete <<xyz>> <xyz>
} -cleanup {
    event delete <<xyz>>
} -returnCodes error -result {bad event type or keysym "xyz"}
test bind-19.6 {DeleteVirtualEvent procedure: delete 1, badly formed} -body {
2469
2470
2471
2472
2473
2474
2475
2476

2477
2478
2479
2480
2481
2482
2483
2476
2477
2478
2479
2480
2481
2482

2483
2484
2485
2486
2487
2488
2489
2490







-
+







    event generate .t.f <ButtonRelease-2>
    event delete <<xyz>>
    event generate .t.f <Button-2> -serial 102
    event generate .t.f <ButtonRelease-2>
    set x
} -cleanup {
    destroy .t.f
} -result {101}
} -result 101
test bind-19.12 {DeleteVirtualEvent procedure: owned by 1, first in chain} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
    event delete <<xyz>>
2690
2691
2692
2693
2694
2695
2696
2697

2698
2699
2700
2701

2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722

2723
2724
2725
2726
2727
2728

2729
2730
2731
2732
2733
2734
2735
2697
2698
2699
2700
2701
2702
2703

2704
2705
2706
2707

2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728

2729
2730
2731
2732
2733
2734

2735
2736
2737
2738
2739
2740
2741
2742







-
+



-
+




















-
+





-
+







test bind-20.2 {GetVirtualEvent procedure: non-existent event} -body {
    event delete <<asd>>
    event info <<asd>>
} -result {}
test bind-20.3 {GetVirtualEvent procedure: owns 1} -setup {
    event delete <<xyz>>
} -body {
    event add <<xyz>> <Control-Key-v>
    event add <<xyz>> <Control-v>
    event info <<xyz>>
} -cleanup {
    event delete <<xyz>>
} -result {<Control-Key-v>}
} -result <Control-Key-v>
test bind-20.4 {GetVirtualEvent procedure: owns many} -setup {
    event delete <<xyz>>
} -body {
    event add <<xyz>> <Control-v> <Button-2> spack
    event info <<xyz>>
} -cleanup {
    event delete <<xyz>>
} -result {<Control-Key-v> <Button-2> spack}


test bind-21.1 {GetAllVirtualEvents procedure: no events} -body {
    foreach p [event info] {event delete $p}
    event info
} -result {}
test bind-21.2 {GetAllVirtualEvents procedure: 1 event} -body {
    foreach p [event info] {event delete $p}
    event add <<xyz>> <Control-v>
    event info
} -cleanup {
    event delete <<xyz>>
} -result {<<xyz>>}
} -result <<xyz>>
test bind-21.3 {GetAllVirtualEvents procedure: many events} -body {
    foreach p [event info] {event delete $p}
    event add <<xyz>> <Control-v>
    event add <<xyz>> <Button-2>
    event add <<abc>> <Control-v>
    event add <<def>> <Key-F6>
    event add <<def>> <F6>
    lsort [event info]
} -cleanup {
    event delete <<xyz>>
    event delete <<abc>>
    event delete <<def>>
} -result {<<abc>> <<def>> <<xyz>>}

2790
2791
2792
2793
2794
2795
2796
2797

2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814

2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827

2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841

2842
2843
2844
2845
2846
2847
2848
2797
2798
2799
2800
2801
2802
2803

2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820

2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833

2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847

2848
2849
2850
2851
2852
2853
2854
2855







-
+
















-
+












-
+













-
+







    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Key> {set x "%s %K"}
    event generate .t.f <Control-Key-space>
    event generate .t.f <Control-space>
    set x
} -cleanup {
    destroy .t.f
} -result {4 space}
test bind-22.11 {HandleEventGenerate} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <<Paste>> {set x "%s"}
    event generate .t.f <<Paste>> -state 1
    set x
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1
test bind-22.12 {HandleEventGenerate} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Motion> {set x "%s"}
    event generate .t.f <Control-Motion>
    set x
} -cleanup {
    destroy .t.f
} -result {4}
} -result 4
test bind-22.13 {HandleEventGenerate} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Button> {lappend x %#}
    event generate .t.f <Button> -when now -serial 100
    event generate .t.f <ButtonRelease> -when now
    set x
} -cleanup {
    destroy .t.f
} -result {100}
} -result 100
test bind-22.14 {HandleEventGenerate} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
2990
2991
2992
2993
2994
2995
2996
2997

2998
2999
3000
3001
3002
3003
3004
2997
2998
2999
3000
3001
3002
3003

3004
3005
3006
3007
3008
3009
3010
3011







-
+







    set x {}
} -body {
    bind .t.f <Configure> "lappend x %B"
    event generate .t.f <Configure> -borderwidth 2i
    expr {[winfo pixels .t.f 2i] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.26 {HandleEventGenerate: options <Key> -borderwidth 2i} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
3084
3085
3086
3087
3088
3089
3090
3091

3092
3093
3094
3095
3096
3097
3098
3091
3092
3093
3094
3095
3096
3097

3098
3099
3100
3101
3102
3103
3104
3105







-
+







    set x {}
} -body {
    bind .t.f <Expose> "lappend x %c"
    event generate .t.f <Expose> -count 20
    return $x
} -cleanup {
    destroy .t.f
} -result {20}
} -result 20

test bind-22.33 {HandleEventGenerate: options <Key> -count 20} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
3192
3193
3194
3195
3196
3197
3198
3199

3200
3201
3202
3203
3204
3205
3206
3199
3200
3201
3202
3203
3204
3205

3206
3207
3208
3209
3210
3211
3212
3213







-
+







    set x {}
} -body {
    bind .t.f <Enter> "lappend x %f"
    event generate .t.f <Enter> -focus 1
    return $x
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.40 {HandleEventGenerate: options <Key> -focus 1} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
3232
3233
3234
3235
3236
3237
3238
3239

3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253

3254
3255
3256
3257
3258
3259
3260
3239
3240
3241
3242
3243
3244
3245

3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259

3260
3261
3262
3263
3264
3265
3266
3267







-
+













-
+







    set x {}
} -body {
    bind .t.f <Expose> "lappend x %h"
    event generate .t.f <Expose> -height 2i
    expr {$x eq [winfo pixels .t.f 2i]}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.43 {HandleEventGenerate: options <Configure> -height 2i} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Configure> "lappend x %h"
    event generate .t.f <Configure> -height 2i
    expr {$x eq [winfo pixels .t.f 2i]}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.44 {HandleEventGenerate: options <Key> -height 2i} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
3286
3287
3288
3289
3290
3291
3292
3293

3294
3295
3296
3297
3298
3299
3300
3293
3294
3295
3296
3297
3298
3299

3300
3301
3302
3303
3304
3305
3306
3307







-
+







    set x {}
} -body {
    bind .t.f <Key> "lappend x %k"
    event generate .t.f <Key> -keycode 20
    return $x
} -cleanup {
    destroy .t.f
} -result {20}
} -result 20

test bind-22.47 {HandleEventGenerate: options <Button> -keycode 20} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
3419
3420
3421
3422
3423
3424
3425
3426

3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440

3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454

3455
3456
3457
3458
3459
3460
3461
3426
3427
3428
3429
3430
3431
3432

3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446

3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460

3461
3462
3463
3464
3465
3466
3467
3468







-
+













-
+













-
+







    set x {}
} -body {
    bind .t.f <Map> "lappend x %o"
    event generate .t.f <Map> -override 1
    return $x
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.57 {HandleEventGenerate: options <Reparent> -override 1} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Reparent> "lappend x %o"
    event generate .t.f <Reparent> -override 1
    return $x
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.58 {HandleEventGenerate: options <Configure> -override 1} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Configure> "lappend x %o"
    event generate .t.f <Configure> -override 1
    return $x
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.59 {HandleEventGenerate: options <Key> -override 1} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
3527
3528
3529
3530
3531
3532
3533
3534

3535
3536
3537
3538
3539
3540
3541
3534
3535
3536
3537
3538
3539
3540

3541
3542
3543
3544
3545
3546
3547
3548







-
+







    set x {}
} -body {
    bind .t.f <Key> "lappend x %R"
    event generate .t.f <Key> -root .t
    expr {[winfo id .t] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.65 {HandleEventGenerate: options <Key> -root xyz} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
3554
3555
3556
3557
3558
3559
3560
3561

3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575

3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589

3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603

3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617

3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631

3632
3633
3634
3635
3636
3637
3638
3561
3562
3563
3564
3565
3566
3567

3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581

3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595

3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609

3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623

3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637

3638
3639
3640
3641
3642
3643
3644
3645







-
+













-
+













-
+













-
+













-
+













-
+







    set x {}
} -body {
    bind .t.f <Key> "lappend x %R"
    event generate .t.f <Key> -root [winfo id .t]
    expr {[winfo id .t] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.67 {HandleEventGenerate: options <Button> -root .t} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Button> "lappend x %R"
    event generate .t.f <Button> -root .t
    expr {[winfo id .t] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.68 {HandleEventGenerate: options <ButtonRelease> -root .t} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <ButtonRelease> "lappend x %R"
    event generate .t.f <ButtonRelease> -root .t
    expr {[winfo id .t] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.69 {HandleEventGenerate: options <Motion> -root .t} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Motion> "lappend x %R"
    event generate .t.f <Motion> -root .t
    expr {[winfo id .t] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.70 {HandleEventGenerate: options <<Paste>> -root .t} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <<Paste>> "lappend x %R"
    event generate .t.f <<Paste>> -root .t
    expr {[winfo id .t] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.71 {HandleEventGenerate: options <Enter> -root .t} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Enter> "lappend x %R"
    event generate .t.f <Enter> -root .t
    expr {[winfo id .t] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.72 {HandleEventGenerate: options <Configure> -root .t} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
3664
3665
3666
3667
3668
3669
3670
3671

3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685

3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699

3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713

3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727

3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741

3742
3743
3744
3745
3746
3747
3748
3671
3672
3673
3674
3675
3676
3677

3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691

3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705

3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719

3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733

3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747

3748
3749
3750
3751
3752
3753
3754
3755







-
+













-
+













-
+













-
+













-
+













-
+







    set x {}
} -body {
    bind .t.f <Key> "lappend x %X"
    event generate .t.f <Key> -rootx 2i
    expr {[winfo pixels .t.f 2i] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.75 {HandleEventGenerate: options <Button> -rootx 2i} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Button> "lappend x %X"
    event generate .t.f <Button> -rootx 2i
    expr {[winfo pixels .t.f 2i] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.76 {HandleEventGenerate: options <ButtonRelease> -rootx 2i} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <ButtonRelease> "lappend x %X"
    event generate .t.f <ButtonRelease> -rootx 2i
    expr {[winfo pixels .t.f 2i] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.77 {HandleEventGenerate: options <Motion> -rootx 2i} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Motion> "lappend x %X"
    event generate .t.f <Motion> -rootx 2i
    expr {[winfo pixels .t.f 2i] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.78 {HandleEventGenerate: options <<Paste>> -rootx 2i} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <<Paste>> "lappend x %X"
    event generate .t.f <<Paste>> -rootx 2i
    expr {[winfo pixels .t.f 2i] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.79 {HandleEventGenerate: options <Enter> -rootx 2i} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Enter> "lappend x %X"
    event generate .t.f <Enter> -rootx 2i
    expr {[winfo pixels .t.f 2i] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.80 {HandleEventGenerate: options <Configure> -rootx 2i} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
3774
3775
3776
3777
3778
3779
3780
3781

3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795

3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809

3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823

3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837

3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851

3852
3853
3854
3855
3856
3857
3858
3781
3782
3783
3784
3785
3786
3787

3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801

3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815

3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829

3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843

3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857

3858
3859
3860
3861
3862
3863
3864
3865







-
+













-
+













-
+













-
+













-
+













-
+







    set x {}
} -body {
    bind .t.f <Key> "lappend x %Y"
    event generate .t.f <Key> -rooty 2i
    expr {[winfo pixels .t.f 2i] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.83 {HandleEventGenerate: options <Button> -rooty 2i} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Button> "lappend x %Y"
    event generate .t.f <Button> -rooty 2i
    expr {[winfo pixels .t.f 2i] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.84 {HandleEventGenerate: options <ButtonRelease> -rooty 2i} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <ButtonRelease> "lappend x %Y"
    event generate .t.f <ButtonRelease> -rooty 2i
    expr {[winfo pixels .t.f 2i] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.85 {HandleEventGenerate: options <Motion> -rooty 2i} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Motion> "lappend x %Y"
    event generate .t.f <Motion> -rooty 2i
    expr {[winfo pixels .t.f 2i] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.86 {HandleEventGenerate: options <<Paste>> -rooty 2i} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <<Paste>> "lappend x %Y"
    event generate .t.f <<Paste>> -rooty 2i
    expr {[winfo pixels .t.f 2i] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.87 {HandleEventGenerate: options <Enter> -rooty 2i} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Enter> "lappend x %Y"
    event generate .t.f <Enter> -rooty 2i
    expr {[winfo pixels .t.f 2i] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.88 {HandleEventGenerate: options <Configure> -rooty 2i} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
3884
3885
3886
3887
3888
3889
3890
3891

3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905

3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919

3920
3921
3922
3923
3924
3925
3926
3891
3892
3893
3894
3895
3896
3897

3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911

3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925

3926
3927
3928
3929
3930
3931
3932
3933







-
+













-
+













-
+







    set x {}
} -body {
    bind .t.f <Key> "lappend x %E"
    event generate .t.f <Key> -sendevent 1
    return $x
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.91 {HandleEventGenerate: options <Key> -sendevent yes} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Key> "lappend x %E"
    event generate .t.f <Key> -sendevent yes
    return $x
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.92 {HandleEventGenerate: options <Key> -sendevent 43} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Key> "lappend x %E"
    event generate .t.f <Key> -sendevent 43
    return $x
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.93 {HandleEventGenerate: options <Key> -serial xyz} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
3939
3940
3941
3942
3943
3944
3945
3946

3947
3948
3949
3950
3951
3952
3953
3946
3947
3948
3949
3950
3951
3952

3953
3954
3955
3956
3957
3958
3959
3960







-
+







    set x {}
} -body {
    bind .t.f <Key> "lappend x %#"
    event generate .t.f <Key> -serial 100
    return $x
} -cleanup {
    destroy .t.f
} -result {100}
} -result 100

test bind-22.95 {HandleEventGenerate: options <Key> -state xyz} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
3966
3967
3968
3969
3970
3971
3972
3973

3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987

3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001

4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015

4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029

4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043

4044
4045
4046
4047
4048
4049
4050
3973
3974
3975
3976
3977
3978
3979

3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993

3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007

4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021

4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035

4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049

4050
4051
4052
4053
4054
4055
4056
4057







-
+













-
+













-
+













-
+













-
+













-
+







    set x {}
} -body {
    bind .t.f <Key> "lappend x %s"
    event generate .t.f <Key> -state 1
    return $x
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.97 {HandleEventGenerate: options <Button> -state 1025} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Button> "lappend x %s"
    event generate .t.f <Button> -state 1025
    return $x
} -cleanup {
    destroy .t.f
} -result {1025}
} -result 1025

test bind-22.98 {HandleEventGenerate: options <ButtonRelease> -state 1025} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <ButtonRelease> "lappend x %s"
    event generate .t.f <ButtonRelease> -state 1025
    return $x
} -cleanup {
    destroy .t.f
} -result {1025}
} -result 1025

test bind-22.99 {HandleEventGenerate: options <Motion> -state 1} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Motion> "lappend x %s"
    event generate .t.f <Motion> -state 1
    return $x
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.100 {HandleEventGenerate: options <<Paste>> -state 1} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <<Paste>> "lappend x %s"
    event generate .t.f <<Paste>> -state 1
    return $x
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.101 {HandleEventGenerate: options <Enter> -state 1} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Enter> "lappend x %s"
    event generate .t.f <Enter> -state 1
    return $x
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.102 {HandleEventGenerate: options <Visibility> -state xyz} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
4103
4104
4105
4106
4107
4108
4109
4110

4111
4112
4113
4114
4115
4116
4117
4110
4111
4112
4113
4114
4115
4116

4117
4118
4119
4120
4121
4122
4123
4124







-
+







    set x {}
} -body {
    bind .t.f <Key> "lappend x %S"
    event generate .t.f <Key> -subwindow .t
    expr {[winfo id .t] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.107 {HandleEventGenerate: options <Key> -subwindow xyz} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
4130
4131
4132
4133
4134
4135
4136
4137

4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151

4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165

4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179

4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193

4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207

4208
4209
4210
4211
4212
4213
4214
4137
4138
4139
4140
4141
4142
4143

4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157

4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171

4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185

4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199

4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213

4214
4215
4216
4217
4218
4219
4220
4221







-
+













-
+













-
+













-
+













-
+













-
+







    set x {}
} -body {
    bind .t.f <Key> "lappend x %S"
    event generate .t.f <Key> -subwindow [winfo id .t]
    expr {[winfo id .t] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.109 {HandleEventGenerate: options <Button> -subwindow .t} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Button> "lappend x %S"
    event generate .t.f <Button> -subwindow .t
    expr {[winfo id .t] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.110 {HandleEventGenerate: options <ButtonRelease> -subwindow .t} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <ButtonRelease> "lappend x %S"
    event generate .t.f <ButtonRelease> -subwindow .t
    expr {[winfo id .t] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.111 {HandleEventGenerate: options <Motion> -subwindow .t} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Motion> "lappend x %S"
    event generate .t.f <Motion> -subwindow .t
    expr {[winfo id .t] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.112 {HandleEventGenerate: options <<Paste>> -subwindow .t} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <<Paste>> "lappend x %S"
    event generate .t.f <<Paste>> -subwindow .t
    expr {[winfo id .t] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.113 {HandleEventGenerate: options <Enter> -subwindow .t} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Enter> "lappend x %S"
    event generate .t.f <Enter> -subwindow .t
    expr {[winfo id .t] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.114 {HandleEventGenerate: options <Configure> -subwindow .t} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
4240
4241
4242
4243
4244
4245
4246
4247

4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261

4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275

4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289

4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303

4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317

4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331

4332
4333
4334
4335
4336
4337
4338
4247
4248
4249
4250
4251
4252
4253

4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267

4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281

4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295

4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309

4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323

4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337

4338
4339
4340
4341
4342
4343
4344
4345







-
+













-
+













-
+













-
+













-
+













-
+













-
+







    set x {}
} -body {
    bind .t.f <Key> "lappend x %t"
    event generate .t.f <Key> -time 100
    return $x
} -cleanup {
    destroy .t.f
} -result {100}
} -result 100

test bind-22.117 {HandleEventGenerate: options <Button> -time 100} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Button> "lappend x %t"
    event generate .t.f <Button> -time 100
    return $x
} -cleanup {
    destroy .t.f
} -result {100}
} -result 100

test bind-22.118 {HandleEventGenerate: options <ButtonRelease> -time 100} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <ButtonRelease> "lappend x %t"
    event generate .t.f <ButtonRelease> -time 100
    return $x
} -cleanup {
    destroy .t.f
} -result {100}
} -result 100

test bind-22.119 {HandleEventGenerate: options <Motion> -time 100} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Motion> "lappend x %t"
    event generate .t.f <Motion> -time 100
    return $x
} -cleanup {
    destroy .t.f
} -result {100}
} -result 100

test bind-22.120 {HandleEventGenerate: options <<Paste>> -time 100} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <<Paste>> "lappend x %t"
    event generate .t.f <<Paste>> -time 100
    return $x
} -cleanup {
    destroy .t.f
} -result {100}
} -result 100

test bind-22.121 {HandleEventGenerate: options <Enter> -time 100} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Enter> "lappend x %t"
    event generate .t.f <Enter> -time 100
    return $x
} -cleanup {
    destroy .t.f
} -result {100}
} -result 100

test bind-22.122 {HandleEventGenerate: options <Property> -time 100} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Property> "lappend x %t"
    event generate .t.f <Property> -time 100
    return $x
} -cleanup {
    destroy .t.f
} -result {100}
} -result 100

test bind-22.123 {HandleEventGenerate: options <Configure> -time 100} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
4364
4365
4366
4367
4368
4369
4370
4371

4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385

4386
4387
4388
4389
4390
4391
4392
4371
4372
4373
4374
4375
4376
4377

4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391

4392
4393
4394
4395
4396
4397
4398
4399







-
+













-
+







    set x {}
} -body {
    bind .t.f <Expose> "lappend x %w"
    event generate .t.f <Expose> -width 2i
    expr {[winfo pixels .t.f 2i] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.126 {HandleEventGenerate: options <Configure> -width 2i} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Configure> "lappend x %w"
    event generate .t.f <Configure> -width 2i
    expr {[winfo pixels .t.f 2i] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.127 {HandleEventGenerate: options <Key> -width 2i} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
4569
4570
4571
4572
4573
4574
4575
4576

4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590

4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604

4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618

4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632

4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646

4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660

4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674

4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688

4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702

4703
4704
4705
4706
4707
4708
4709
4576
4577
4578
4579
4580
4581
4582

4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596

4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610

4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624

4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638

4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652

4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666

4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680

4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694

4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708

4709
4710
4711
4712
4713
4714
4715
4716







-
+













-
+













-
+













-
+













-
+













-
+













-
+













-
+













-
+













-
+







    set x {}
} -body {
    bind .t.f <Key> "lappend x %x"
    event generate .t.f <Key> -x 2i
    expr {[winfo pixels .t.f 2i] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.141 {HandleEventGenerate: options <Button> -x 2i} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Button> "lappend x %x"
    event generate .t.f <Button> -x 2i
    expr {[winfo pixels .t.f 2i] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.142 {HandleEventGenerate: options <ButtonRelease> -x 2i} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <ButtonRelease> "lappend x %x"
    event generate .t.f <ButtonRelease> -x 2i
    expr {[winfo pixels .t.f 2i] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.143 {HandleEventGenerate: options <Motion> -x 2i} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Motion> "lappend x %x"
    event generate .t.f <Motion> -x 2i
    expr {[winfo pixels .t.f 2i] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.144 {HandleEventGenerate: options <<Paste>> -x 2i} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <<Paste>> "lappend x %x"
    event generate .t.f <<Paste>> -x 2i
    expr {[winfo pixels .t.f 2i] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.145 {HandleEventGenerate: options <Enter> -x 2i} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Enter> "lappend x %x"
    event generate .t.f <Enter> -x 2i
    expr {[winfo pixels .t.f 2i] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.146 {HandleEventGenerate: options <Expose> -x 2i} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Expose> "lappend x %x"
    event generate .t.f <Expose> -x 2i
    expr {[winfo pixels .t.f 2i] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.147 {HandleEventGenerate: options <Configure> -x 2i} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Configure> "lappend x %x"
    event generate .t.f <Configure> -x 2i
    expr {[winfo pixels .t.f 2i] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.148 {HandleEventGenerate: options <Gravity> -x 2i} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Gravity> "lappend x %x"
    event generate .t.f <Gravity> -x 2i
    expr {[winfo pixels .t.f 2i] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.149 {HandleEventGenerate: options <Reparent> -x 2i} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Reparent> "lappend x %x"
    event generate .t.f <Reparent> -x 2i
    expr {[winfo pixels .t.f 2i] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.150 {HandleEventGenerate: options <Map> -x 2i} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
4735
4736
4737
4738
4739
4740
4741
4742

4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756

4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770

4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784

4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798

4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812

4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826

4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840

4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854

4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868

4869
4870
4871
4872
4873
4874
4875
4742
4743
4744
4745
4746
4747
4748

4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762

4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776

4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790

4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804

4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818

4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832

4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846

4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860

4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874

4875
4876
4877
4878
4879
4880
4881
4882







-
+













-
+













-
+













-
+













-
+













-
+













-
+













-
+













-
+













-
+







    set x {}
} -body {
    bind .t.f <Key> "lappend x %y"
    event generate .t.f <Key> -y 2i
    expr {[winfo pixels .t.f 2i] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.153 {HandleEventGenerate: options <Button> -y 2i} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Button> "lappend x %y"
    event generate .t.f <Button> -y 2i
    expr {[winfo pixels .t.f 2i] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.154 {HandleEventGenerate: options <ButtonRelease> -y 2i} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <ButtonRelease> "lappend x %y"
    event generate .t.f <ButtonRelease> -y 2i
    expr {[winfo pixels .t.f 2i] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.155 {HandleEventGenerate: options <Motion> -y 2i} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Motion> "lappend x %y"
    event generate .t.f <Motion> -y 2i
    expr {[winfo pixels .t.f 2i] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.156 {HandleEventGenerate: options <<Paste>> -y 2i} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <<Paste>> "lappend x %y"
    event generate .t.f <<Paste>> -y 2i
    expr {[winfo pixels .t.f 2i] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.157 {HandleEventGenerate: options <Enter> -y 2i} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Enter> "lappend x %y"
    event generate .t.f <Enter> -y 2i
    expr {[winfo pixels .t.f 2i] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.158 {HandleEventGenerate: options <Expose> -y 2i} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Expose> "lappend x %y"
    event generate .t.f <Expose> -y 2i
    expr {[winfo pixels .t.f 2i] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.159 {HandleEventGenerate: options <Configure> -y 2i} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Configure> "lappend x %y"
    event generate .t.f <Configure> -y 2i
    expr {[winfo pixels .t.f 2i] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.160 {HandleEventGenerate: options <Gravity> -y 2i} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Gravity> "lappend x %y"
    event generate .t.f <Gravity> -y 2i
    expr {[winfo pixels .t.f 2i] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.161 {HandleEventGenerate: options <Reparent> -y 2i} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Reparent> "lappend x %y"
    event generate .t.f <Reparent> -y 2i
    expr {[winfo pixels .t.f 2i] eq $x}
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1

test bind-22.162 {HandleEventGenerate: options <Map> -y 2i} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944




4945
4946
4947
4948
4949
4950
4951
4941
4942
4943
4944
4945
4946
4947




4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958







-
-
-
-
+
+
+
+







} -returnCodes error -result {virtual event not allowed in definition of another virtual event}
test bind-24.5 {FindSequence procedure, multiple bindings} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <1> {lappend x single}
    bind .t.f <Double-1> {lappend x double}
    bind .t.f <Triple-1> {lappend x triple}
    bind .t.f <Quadruple-1> {lappend x quadruple}
    bind .t.f <Button-1> {lappend x single}
    bind .t.f <Double-Button-1> {lappend x double}
    bind .t.f <Triple-Button-1> {lappend x triple}
    bind .t.f <Quadruple-Button-1> {lappend x quadruple}
    set x press
    event generate .t.f <Button-1>
    event generate .t.f <ButtonRelease-1>
    lappend x press
    event generate .t.f <Button-1>
    event generate .t.f <ButtonRelease-1>
    lappend x press
5092
5093
5094
5095
5096
5097
5098
5099

5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119

5120
5121
5122
5123
5124
5125
5126
5099
5100
5101
5102
5103
5104
5105

5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125

5126
5127
5128
5129
5130
5131
5132
5133







-
+



















-
+







} -cleanup {
    destroy .t.f
} -result test
test bind-25.2 {ParseEventDescription procedure: misinterpreted modifier} -setup {
    button .b
} -body {
    bind .b <Control-M> a
    bind .b <M-M> b
    bind .b <Meta-M> b
    lsort [bind .b]
} -cleanup {
    destroy .b
} -result {<Control-Key-M> <Meta-Key-M>}
test bind-25.3 {ParseEventDescription procedure} -setup {
    frame .t.f -class Test -width 150 -height 100
} -body {
    bind .t.f <a---> {nothing}
    bind .t.f
} -cleanup {
    destroy .t.f
} -result a
test bind-25.4 {ParseEventDescription} -setup {
    frame .t.f -class Test -width 150 -height 100
} -body {
    bind .t.f <<Shift-Paste>> {puts hi}
    bind .t.f
} -cleanup {
    destroy .t.f
} -result {<<Shift-Paste>>}
} -result <<Shift-Paste>>

# 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}
test bind-25.6 {ParseEventDescription procedure error cases} -body {
    bind .t \x7f {puts hi}
5196
5197
5198
5199
5200
5201
5202
5203

5204
5205
5206
5207
5208
5209
5210
5203
5204
5205
5206
5207
5208
5209

5210
5211
5212
5213
5214
5215
5216
5217







-
+







} -cleanup {
    destroy .t.f
} -result <Meta-Key-a>

test bind-25.22 {modifier names} -setup {
    frame .t.f -class Test -width 150 -height 100
} -body {
    bind .t.f <M-a> foo
    bind .t.f <Meta-a> foo
    bind .t.f
} -cleanup {
    destroy .t.f
} -result <Meta-Key-a>

test bind-25.23 {modifier names} -setup {
    frame .t.f -class Test -width 150 -height 100
5445
5446
5447
5448
5449
5450
5451




































5452
5453
5454
5455
5456
5457
5458
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







} -body {
    bind .t.f <Extended-Return> foo
    bind .t.f
} -cleanup {
    destroy .t.f
} -result <Extended-Key-Return>

test bind-25.50 {modifier names} -setup {
    frame .t.f -class Test -width 150 -height 100
} -body {
    bind .t.f <Button6-a> foo
    bind .t.f
} -cleanup {
    destroy .t.f
} -result <B6-Key-a>

test bind-25.51 {modifier names} -setup {
    frame .t.f -class Test -width 150 -height 100
} -body {
    bind .t.f <Button7-a> foo
    bind .t.f
} -cleanup {
    destroy .t.f
} -result <B7-Key-a>

test bind-25.52 {modifier names} -setup {
    frame .t.f -class Test -width 150 -height 100
} -body {
    bind .t.f <Button8-a> foo
    bind .t.f
} -cleanup {
    destroy .t.f
} -result <B8-Key-a>

test bind-25.53 {modifier names} -setup {
    frame .t.f -class Test -width 150 -height 100
} -body {
    bind .t.f <Button9-a> foo
    bind .t.f
} -cleanup {
    destroy .t.f
} -result <B9-Key-a>



test bind-26.1 {event names} -setup {
    frame .t.f -class Test -width 150 -height 100
} -body {
    bind .t.f <FocusIn> {nothing}
    bind .t.f
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5548
5549
5550
5551
5552
5553
5554














5555
5556
5557
5558
5559
5560
5561







-
-
-
-
-
-
-
-
-
-
-
-
-
-







    set x xyzzy
    event generate .t.f <Button>
    list $x [bind .t.f]
} -cleanup {
    destroy .t.f
} -result {{event Button} <Button>}

test bind-26.6 {event names: ButtonPress} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <ButtonPress> "set x {event ButtonPress}"
    set x xyzzy
    event generate .t.f <ButtonPress>
    list $x [bind .t.f]
} -cleanup {
    destroy .t.f
} -result {{event ButtonPress} <Button>}

test bind-26.7 {event names: ButtonRelease} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <ButtonRelease> "set x {event ButtonRelease}"
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5632
5633
5634
5635
5636
5637
5638














5639
5640
5641
5642
5643
5644
5645







-
-
-
-
-
-
-
-
-
-
-
-
-
-







    set x xyzzy
    event generate .t.f <Key>
    list $x [bind .t.f]
} -cleanup {
    destroy .t.f
} -result {{event Key} <Key>}

test bind-26.13 {event names: KeyPress} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <KeyPress> "set x {event KeyPress}"
    set x xyzzy
    event generate .t.f <KeyPress>
    list $x [bind .t.f]
} -cleanup {
    destroy .t.f
} -result {{event KeyPress} <Key>}

test bind-26.14 {event names: KeyRelease} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <KeyRelease> "set x {event KeyRelease}"
5778
5779
5780
5781
5782
5783
5784
5785
5786


5787
5788
5789
5790
5791
5792
5793
5793
5794
5795
5796
5797
5798
5799


5800
5801
5802
5803
5804
5805
5806
5807
5808







-
-
+
+







} -result {{event Unmap} <Unmap>}


test bind-27.1 {button names} -body {
    bind .t <Expose-1> foo
} -returnCodes error -result {specified button "1" for non-button event}
test bind-27.2 {button names} -body {
    bind .t <Button-6> foo
} -returnCodes error -result {bad button number "6"}
    bind .t <Button-10> foo
} -returnCodes error -result {bad button number "10"}
test bind-27.3 {button names} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <Button-1> {lappend x "button 1"}
5850
5851
5852
5853
5854
5855
5856
























































5857
5858
5859
5860
5861
5862
5863
5864
5865

5866
5867
5868
5869
5870
5871
5872
5873
5874
5875
5876
5877
5878
5879
5880
5881
5882


5883
5884

5885
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896


5897
5898

5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910


5911
5912

5913
5914
5915
5916
5917
5918
5919
5920
5921
5922
5923
5924


5925
5926

5927
5928
5929
5930
5931

5932
5933

5934
5935
5936
5937
5938


5939
5940

5941
5942
5943
5944

5945
5946
5947
5948
5949
5950
5951

5952
5953
5954
5955
5956
5957
5958






















5959
5960
5961
5962
5963
5964
5965
5865
5866
5867
5868
5869
5870
5871
5872
5873
5874
5875
5876
5877
5878
5879
5880
5881
5882
5883
5884
5885
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920
5921
5922
5923
5924
5925
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935

5936
5937
5938
5939
5940
5941
5942
5943
5944
5945
5946
5947
5948
5949
5950
5951


5952
5953
5954

5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965


5966
5967
5968

5969
5970
5971
5972
5973
5974
5975
5976
5977
5978
5979


5980
5981
5982

5983
5984
5985
5986
5987
5988
5989
5990
5991
5992
5993


5994
5995
5996

5997
5998
5999
6000
6001

6002
6003

6004
6005
6006
6007


6008
6009
6010

6011
6012
6013
6014

6015
6016
6017
6018
6019
6020
6021

6022
6023
6024
6025
6026
6027
6028

6029
6030
6031
6032
6033
6034
6035
6036
6037
6038
6039
6040
6041
6042
6043
6044
6045
6046
6047
6048
6049
6050
6051
6052
6053
6054
6055
6056
6057







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








-
+















-
-
+
+

-
+










-
-
+
+

-
+










-
-
+
+

-
+










-
-
+
+

-
+




-
+

-
+



-
-
+
+

-
+



-
+






-
+






-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    set x [bind .t.f]
    event generate .t.f <Button-5>
    event generate .t.f <ButtonRelease-5>
    set x
} -cleanup {
    destroy .t.f
} -result {<Button-5> {button 5}}
test bind-27.8 {button names} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <Button-6> {lappend x "button 6"}
    set x [bind .t.f]
    event generate .t.f <Button-6>
    event generate .t.f <ButtonRelease-6>
    set x
} -cleanup {
    destroy .t.f
} -result {<Button-6> {button 6}}
test bind-27.9 {button names} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <Button-7> {lappend x "button 7"}
    set x [bind .t.f]
    event generate .t.f <Button-7>
    event generate .t.f <ButtonRelease-7>
    set x
} -cleanup {
    destroy .t.f
} -result {<Button-7> {button 7}}
test bind-27.10 {button names} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <Button-8> {lappend x "button 8"}
    set x [bind .t.f]
    event generate .t.f <Button-8>
    event generate .t.f <ButtonRelease-8>
    set x
} -cleanup {
    destroy .t.f
} -result {<Button-8> {button 8}}
test bind-27.11 {button names} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <Button-9> {lappend x "button 9"}
    set x [bind .t.f]
    event generate .t.f <Button-9>
    event generate .t.f <ButtonRelease-9>
    set x
} -cleanup {
    destroy .t.f
} -result {<Button-9> {button 9}}

test bind-28.1 {keysym names} -body {
    bind .t <Expose-a> foo
} -returnCodes error -result {specified keysym "a" for non-key event}
test bind-28.2 {keysym names} -body {
    bind .t <Gorp> foo
} -returnCodes error -result {bad event type or keysym "Gorp"}
test bind-28.3 {keysym names} -body {
    bind .t <Key-Stupid> foo
    bind .t <Stupid> foo
} -returnCodes error -result {bad event type or keysym "Stupid"}
test bind-28.4 {keysym names} -body {
    frame .t.f -class Test -width 150 -height 100
    bind .t.f <a> foo
    bind .t.f
} -cleanup {
    destroy .t.f
} -result {a}

test bind-28.5 {keysym names} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <Key-colon> "lappend x \"keysym received\""
    bind .t.f <Key-underscore> "lappend x {bad binding match}"
    bind .t.f <:> "lappend x \"keysym received\""
    bind .t.f <_> "lappend x {bad binding match}"
    set x [lsort [bind .t.f]]
    event generate .t.f <Key-colon> ;# -state 0
    event generate .t.f <:> ;# -state 0
    set x
} -cleanup {
    destroy .t.f
} -result {: _ {keysym received}}
test bind-28.6 {keysym names} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <Key-Return> "lappend x \"keysym Return\""
    bind .t.f <Key-x> "lappend x {bad binding match}"
    bind .t.f <Return> "lappend x \"keysym Return\""
    bind .t.f <x> "lappend x {bad binding match}"
    set x [lsort [bind .t.f]]
    event generate .t.f <Key-Return> -state 0
    event generate .t.f <Return> -state 0
    set x
} -cleanup {
    destroy .t.f
} -result {<Key-Return> x {keysym Return}}
test bind-28.7 {keysym names} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <Key-X> "lappend x \"keysym X\""
    bind .t.f <Key-x> "lappend x {bad binding match}"
    bind .t.f <X> "lappend x \"keysym X\""
    bind .t.f <x> "lappend x {bad binding match}"
    set x [lsort [bind .t.f]]
    event generate .t.f <Key-X> -state 1
    event generate .t.f <X> -state 1
    set x
} -cleanup {
    destroy .t.f
} -result {X x {keysym X}}
test bind-28.8 {keysym names} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
} -body {
    bind .t.f <Key-X> "lappend x \"keysym X\""
    bind .t.f <Key-x> "lappend x {bad binding match}"
    bind .t.f <X> "lappend x \"keysym X\""
    bind .t.f <x> "lappend x {bad binding match}"
    set x [lsort [bind .t.f]]
    event generate .t.f <Key-X> -state 1
    event generate .t.f <X> -state 1
    set x
} -cleanup {
    destroy .t.f
} -result {X x {keysym X}}
test bind-28.9 {keysym names, Eth -> ETH} -body {
test bind-28.9 {keysym names, Ð} -body {
    frame .t.f -class Test -width 150 -height 100
    bind .t.f <Eth> foo
    bind .t.f <Ð> foo
    bind .t.f
} -cleanup {
    destroy .t.f
} -result {<Key-ETH>}
test bind-28.10 {keysym names, Ooblique -> Oslash} -body {
} -result <Key-Ð>
test bind-28.10 {keysym names, Ø} -constraints nodeprecated -body {
    frame .t.f -class Test -width 150 -height 100
    bind .t.f <Ooblique> foo
    bind .t.f <Ø> foo
    bind .t.f
} -cleanup {
    destroy .t.f
} -result {<Key-Oslash>}
} -result <Key-Ø>
test bind-28.11 {keysym names, gcedilla} -body {
    frame .t.f -class Test -width 150 -height 100
    bind .t.f <gcedilla> foo
    bind .t.f
} -cleanup {
    destroy .t.f
} -result {<Key-gcedilla>}
} -result <Key-gcedilla>
test bind-28.12 {keysym names, Greek_IOTAdiaeresis -> Greek_IOTAdieresis} -body {
    frame .t.f -class Test -width 150 -height 100
    bind .t.f <Greek_IOTAdiaeresis> foo
    bind .t.f
} -cleanup {
    destroy .t.f
} -result {<Key-Greek_IOTAdieresis>}
} -result <Key-Greek_IOTAdieresis>
test bind-28.13 {keysym names, Unicode} -body {
    frame .t.f -class Test -width 150 -height 100
    bind .t.f <€> foo
    bind .t.f
} -cleanup {
    destroy .t.f
} -result "<Key-€>"
test bind-28.14 {keysym names, Emoji} -body {
    frame .t.f -class Test -width 150 -height 100
    bind .t.f <\U1F44D> foo
    bind .t.f
} -cleanup {
    destroy .t.f
} -result "<Key-\U1F44D>"
test bind-28.15 {keysym names, Emoji} -constraints needsTcl87 -body {
    frame .t.f -class Test -width 150 -height 100
    bind .t.f <👍> foo
    bind .t.f
} -cleanup {
    destroy .t.f
} -result "<Key-👍>"


test bind-29.1 {Tcl_BackgroundError procedure} -setup {
    proc bgerror msg {
        global x errorInfo
        set x [list $msg $errorInfo]
    }
6032
6033
6034
6035
6036
6037
6038
6039

6040
6041
6042
6043
6044
6045
6046
6124
6125
6126
6127
6128
6129
6130

6131
6132
6133
6134
6135
6136
6137
6138







-
+







    set x {}
} -body {
    bind .t.f <MouseWheel> {set x %D}
    event generate .t.f <MouseWheel> -delta 120
    set x
} -cleanup {
    destroy .t.f
} -result {120}
} -result 120
test bind-30.3 {MouseWheel events} -setup {
    frame .t.f -class Test -width 150 -height 100
    pack .t.f
    focus -force .t.f
    update
    set x {}
} -body {
6143
6144
6145
6146
6147
6148
6149


6150
6151
6152
6153
6154
6155

6156
6157
6158
6159
6160
6161
6162
6163
6164
6165
6166
6167
6168

6169
6170
6171
6172
6173
6174
6175
6176

6177
6178
6179
6180
6181
6182
6183
6184
6185
6186
6187
6188
6189
6190
6191




6192
6193
6194
6195
6196
6197
6198
6199
6200
6201
6202
6203


6204
6205

6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219




6220
6221
6222
6223
6224
6225
6226
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
6262

6263
6264
6265
6266
6267
6268
6269
6270

6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282




6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296


6297
6298
6299

6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310




6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
6321







+
+






+












-
+







-
+











-
-
-
-
+
+
+
+










-
-
+
+

-
+










-
-
-
-
+
+
+
+







    event generate .t.f <<TestUserData>> -data [string index abc 1] -when head
    list $x [update] $x
} -cleanup {
    destroy .t.f
} -result {{} {} {TestUserData >b<}}

test bind-32.1 {-warp, window was destroyed before the idle callback DoWarp} -setup {
    # note: this test is now essentially useless
    #       since DoWarp no longer exist, not even as an idle callback
    frame .t.f
    pack .t.f
    focus -force .t.f
    update
} -body {
    event generate .t.f <Button-1> -warp 1
    after 50  ; # Win specific - wait for SendInput to be executed
    event generate .t.f <ButtonRelease-1>
    destroy .t.f
    update  ;  # shall simply not crash
} -cleanup {
} -result {}
test bind-32.2 {detection of double click should not fail} -setup {
    pack [frame .t.f]
    focus -force .t.f
    bind .t.f <Double-Button-1> { set x "Double" }
    update
    set x {}
} -body {
    event generate .t.f <ButtonPress-1>
    event generate .t.f <Button-1>
    event generate .t.f <ButtonRelease-1>
    # Simulate a lot of intervening exposure events. The old implementation
    # that used an event ring overflowed, and the double click was not detected.
    # But new implementation should work properly.
    for {set i 0} {$i < 1000} {incr i} {
        event generate .t.f <Expose>
    }
    event generate .t.f <ButtonPress-1>
    event generate .t.f <Button-1>
    event generate .t.f <ButtonRelease-1>
    set x
} -cleanup {
    destroy .t.f
} -result {Double}
test bind-32.3 {should trigger best match of modifier states} -setup {
    pack [frame .t.f]
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Alt-Control-Key-A> { lappend x "Alt-Control" }
    bind .t.f <Shift-Control-Key-A> { lappend x "Shift-Control" }
    bind .t.f <Shift-Key-A> { lappend x "Shift" }
    event generate .t.f <Alt-Control-Key-A>
    bind .t.f <Alt-Control-A> { lappend x "Alt-Control" }
    bind .t.f <Shift-Control-A> { lappend x "Shift-Control" }
    bind .t.f <Shift-A> { lappend x "Shift" }
    event generate .t.f <Alt-Control-A>
    set x
} -cleanup {
    destroy .t.f
} -result {Shift-Control}
test bind-32.4 {should not trigger Double-1} -setup {
    pack [frame .t.f]
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Double-1> { set x "Double" }
    event generate .t.f <1> -time current
    bind .t.f <Double-Button-1> { set x "Double" }
    event generate .t.f <Button-1> -time current
    after 1000
    event generate .t.f <1> -time current
    event generate .t.f <Button-1> -time current
    set x
} -cleanup {
    destroy .t.f
} -result {}
test bind-32.5 {should trigger Quadruple-1} -setup {
    pack [frame .t.f]
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Quadruple-1> { set x "Quadruple" }
    bind .t.f <Triple-1> { set x "Triple" }
    bind .t.f <Double-1> { set x "Double" }
    bind .t.f <1> { set x "Single" }
    bind .t.f <Quadruple-Button-1> { set x "Quadruple" }
    bind .t.f <Triple-Button-1> { set x "Triple" }
    bind .t.f <Double-Button-1> { set x "Double" }
    bind .t.f <Button-1> { set x "Single" }
    # Old implementation triggered "Double", but new implementation
    # triggers "Quadruple", the latter behavior conforms to other toolkits.
    event generate .t.f <Button-1> -time 0
    event generate .t.f <Button-1> -time 400
    event generate .t.f <Button-1> -time 800
    event generate .t.f <Button-1> -time 1200
    set x
6242
6243
6244
6245
6246
6247
6248
6249
6250
6251
6252




6253
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
6264

6265
6266
6267
6268
6269




6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282


6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293



6294
6295
6296
6297
6298



6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312

6313
6314
6315
6316
6317
6318
6319
6320
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330



6331
6332
6333
6334
6335

6336
6337
6338
6339
6340
6341
6342
6343
6344
6345
6346





6347
6348
6349
6350
6351
6352
6353
6354
6355
6356
6357
6358
6359
6360
6361
6362





6363
6364
6365
6366
6367

6368
6369
6370
6371
6372
6373
6374



6375
6376
6377
6378
6379



6380
6381
6382

6383
6384
6385
6386
6387
6388
6389
6390
6391


6392
6393
6394


6395
6396
6397
6398
6399

6400
6401
6402
6403
6404
6405
6406
6407
6408




6409
6410
6411
6412
6413
6414
6415
6416
6417


6418
6419
6420
6421
6422
6423
6424


6425
6426
6427


6428
6429
6430
6431
6432
6433
6434
6435
6436

6437
6438
6439
6440
6441
6442
6443
6444
6445
6446




6447
6448
6449
6450

6451
6452
6453
6454
6455
6456
6457
6458
6459
6460




6461
6462
6463
6464

6465
6466
6467
6468
6469
6470
6471
6472


6473
6474
6475
6476
6477




6478
6479
6480
6481
6482

6483
6484
6485
6486
6487
6488
6489
6490
6491



6492
6493
6494
6495
6496

6497
6498
6499
6500
6501
6502
6503
6504
6505
6506




6507
6508
6509
6510
6511

6512
6513
6514
6515
6516
6517
6518
6519
6520
6521
6522
6523
6524







6525
6526
6527
6528
6529
6530
6531
6532
6533
6534
6535
6536
6537
6538
6539
6540
6541







6542
6543
6544
6545
6546
6547
6548
6549
6550
6551
6552
6553
6554
6555
6556
6557
6558
6559
6560
6561
6562











6563
6564
6565
6566
6567
6568
6569
6570

6571
6572
6573
6574
6575
6576
6577
6578
6579
6580




6581
6582
6583
6584
6585
6586
6587
6588
6589
6590
6591
6592
6593
6594




6595
6596
6597
6598
6599
6600
6601
6602
6603
6604
6605
6606
6607
6608
6609
6610
6611
6612
6613






6614
6615
6616
6617
6618
6619
6620
6621
6622
6623
6624
6625
6626
6627
6628
6629






6630
6631
6632
6633
6634
6635
6636


































































































6637
6638
6639
6640
6641
6642
6643
6644

6645
6646
6647
6648
6649
6650
6651

6652
6653
6654
6655
6656
6657

6658
6659
6660
6661
6662
6663
6664
6665
6666
6667
6668
6669
6670

6671
6672
6673
6674
6675
6676

6677
6678
6679
6680

6681
6682
6683
6684
6685
6686
6687
6688
6689
6690
6691
6692
6693
6694
6695
6696
6697
6698
6699

6700
6701
6702
6703
6704
6705
6706
6707
6708

6709
6710

6711
6712
6713
6714
6715
6716
6717
6718
6719
6720
6721




























































6722
6723










































































6724
6725
6726
6727
6728
6729
6730
6731
6732
6733
6734
6735
6736
6737

6738
6739
6740
6741

6742
6743
6744
6745


6746
6747
6748
6749

6750
6751
6752
6753
6754
6755
6756
6757
6758

6759
6760
6761
6762
6763
6764
6765
6766
6767
6337
6338
6339
6340
6341
6342
6343




6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
6356
6357
6358

6359
6360




6361
6362
6363
6364
6365
6366
6367
6368
6369
6370
6371
6372
6373
6374
6375


6376
6377
6378
6379
6380
6381
6382
6383
6384
6385



6386
6387
6388
6389
6390



6391
6392
6393
6394
6395
6396
6397
6398
6399
6400
6401
6402
6403
6404
6405
6406

6407
6408
6409
6410
6411
6412
6413
6414
6415
6416
6417
6418
6419
6420
6421
6422



6423
6424
6425
6426
6427
6428
6429

6430
6431
6432
6433
6434
6435
6436





6437
6438
6439
6440
6441
6442
6443
6444
6445
6446
6447
6448
6449
6450
6451
6452





6453
6454
6455
6456
6457
6458
6459
6460
6461

6462
6463
6464
6465
6466



6467
6468
6469
6470
6471



6472
6473
6474
6475
6476

6477
6478
6479
6480
6481
6482
6483
6484


6485
6486
6487


6488
6489
6490
6491
6492
6493

6494
6495
6496
6497
6498
6499




6500
6501
6502
6503
6504
6505
6506






6507
6508
6509
6510
6511
6512
6513


6514
6515
6516


6517
6518
6519
6520
6521
6522





6523
6524
6525
6526
6527
6528
6529




6530
6531
6532
6533
6534
6535
6536

6537
6538
6539
6540
6541
6542
6543




6544
6545
6546
6547
6548
6549
6550

6551
6552
6553
6554
6555
6556
6557


6558
6559
6560




6561
6562
6563
6564
6565
6566
6567
6568

6569
6570
6571
6572
6573
6574
6575



6576
6577
6578
6579
6580
6581
6582

6583
6584
6585
6586
6587
6588
6589




6590
6591
6592
6593
6594
6595
6596
6597

6598
6599
6600
6601
6602
6603
6604







6605
6606
6607
6608
6609
6610
6611
6612
6613
6614
6615
6616
6617
6618
6619
6620
6621







6622
6623
6624
6625
6626
6627
6628
6629
6630
6631
6632
6633
6634
6635
6636
6637
6638











6639
6640
6641
6642
6643
6644
6645
6646
6647
6648
6649
6650
6651
6652





6653
6654
6655
6656
6657
6658
6659




6660
6661
6662
6663
6664
6665
6666
6667
6668
6669
6670
6671
6672
6673




6674
6675
6676
6677
6678
6679
6680
6681
6682
6683
6684
6685
6686
6687
6688
6689
6690






6691
6692
6693
6694
6695
6696
6697
6698
6699
6700
6701
6702
6703
6704
6705
6706






6707
6708
6709
6710
6711
6712
6713
6714
6715
6716
6717
6718
6719
6720
6721
6722
6723
6724
6725
6726
6727
6728
6729
6730
6731
6732
6733
6734
6735
6736
6737
6738
6739
6740
6741
6742
6743
6744
6745
6746
6747
6748
6749
6750
6751
6752
6753
6754
6755
6756
6757
6758
6759
6760
6761
6762
6763
6764
6765
6766
6767
6768
6769
6770
6771
6772
6773
6774
6775
6776
6777
6778
6779
6780
6781
6782
6783
6784
6785
6786
6787
6788
6789
6790
6791
6792
6793
6794
6795
6796
6797
6798
6799
6800
6801
6802
6803
6804
6805
6806
6807
6808
6809
6810
6811
6812
6813
6814
6815
6816
6817
6818
6819
6820
6821
6822
6823
6824

6825
6826
6827
6828
6829
6830


6831
6832
6833
6834
6835


6836
6837
6838
6839
6840
6841
6842
6843
6844
6845
6846
6847
6848

6849
6850
6851
6852
6853


6854
6855
6856


6857
6858
6859
6860
6861
6862
6863
6864
6865
6866
6867
6868
6869
6870
6871
6872
6873
6874


6875
6876
6877
6878
6879
6880
6881
6882
6883

6884
6885

6886
6887
6888
6889
6890
6891
6892
6893
6894
6895
6896
6897
6898
6899
6900
6901
6902
6903
6904
6905
6906
6907
6908
6909
6910
6911
6912
6913
6914
6915
6916
6917
6918
6919
6920
6921
6922
6923
6924
6925
6926
6927
6928
6929
6930
6931
6932
6933
6934
6935
6936
6937
6938
6939
6940
6941
6942
6943
6944
6945
6946
6947
6948
6949
6950
6951
6952
6953
6954
6955
6956
6957


6958
6959
6960
6961
6962
6963
6964
6965
6966
6967
6968
6969
6970
6971
6972
6973
6974
6975
6976
6977
6978
6979
6980
6981
6982
6983
6984
6985
6986
6987
6988
6989
6990
6991
6992
6993
6994
6995
6996
6997
6998
6999
7000
7001
7002
7003
7004
7005
7006
7007
7008
7009
7010
7011
7012
7013
7014
7015
7016
7017
7018
7019
7020
7021
7022
7023
7024
7025
7026
7027
7028
7029
7030
7031
7032
7033
7034
7035
7036
7037
7038
7039
7040
7041
7042
7043
7044

7045


7046

7047
7048
7049


7050
7051


7052

7053
7054
7055
7056
7057
7058
7059
7060
7061

7062
7063
7064
7065
7066
7067
7068
7069
7070
7071







-
-
-
-
+
+
+
+











-
+

-
-
-
-
+
+
+
+











-
-
+
+








-
-
-
+
+
+


-
-
-
+
+
+













-
+















-
-
-
+
+
+




-
+






-
-
-
-
-
+
+
+
+
+











-
-
-
-
-
+
+
+
+
+




-
+




-
-
-
+
+
+


-
-
-
+
+
+


-
+







-
-
+
+

-
-
+
+




-
+





-
-
-
-
+
+
+
+



-
-
-
-
-
-
+
+





-
-
+
+

-
-
+
+




-
-
-
-
-
+






-
-
-
-
+
+
+
+



-
+






-
-
-
-
+
+
+
+



-
+






-
-
+
+

-
-
-
-
+
+
+
+




-
+






-
-
-
+
+
+




-
+






-
-
-
-
+
+
+
+




-
+






-
-
-
-
-
-
-
+
+
+
+
+
+
+










-
-
-
-
-
-
-
+
+
+
+
+
+
+










-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+



-
-
-
-
-
+






-
-
-
-
+
+
+
+










-
-
-
-
+
+
+
+













-
-
-
-
-
-
+
+
+
+
+
+










-
-
-
-
-
-
+
+
+
+
+
+







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







-
+





-
-
+




-
-
+












-
+




-
-
+


-
-
+

















-
-
+








-
+

-
+











+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+













-
+
-
-

-
+


-
-
+
+
-
-

-
+








-
+









} -result {sendevent=1}
test bind-32.7 {test sequences} -setup {
    pack [frame .t.f]
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Double-1> { lappend x "Double" }
    bind .t.f <1><1><a> { lappend x "11" }
    event generate .t.f <1>
    event generate .t.f <1>
    bind .t.f <Double-Button-1> { lappend x "Double" }
    bind .t.f <Button-1><Button-1><a> { lappend x "11" }
    event generate .t.f <Button-1>
    event generate .t.f <Button-1>
    event generate .t.f <a>
    set x
} -cleanup {
    destroy .t.f
} -result {Double 11}
test bind-32.8 {test sequences} -setup {
    pack [frame .t.f]
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <a><1><Double-1><1><a> { lappend x "Double" }
    bind .t.f <a><Button-1><Double-Button-1><Button-1><a> { lappend x "Double" }
    event generate .t.f <a>
    event generate .t.f <1>
    event generate .t.f <1>
    event generate .t.f <1>
    event generate .t.f <1>
    event generate .t.f <Button-1>
    event generate .t.f <Button-1>
    event generate .t.f <Button-1>
    event generate .t.f <Button-1>
    event generate .t.f <a>
    set x
} -cleanup {
    destroy .t.f
} -result {Double}
test bind-32.9 {trigger events for modifier keys} -setup {
    pack [frame .t.f]
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Any-Key> { set x "Key" }
    event generate .t.f <KeyPress> -keysym Caps_Lock
    bind .t.f <Key> { set x "Key" }
    event generate .t.f <Key> -keysym Caps_Lock
    set x
} -cleanup {
    destroy .t.f
} -result {Key}
test bind-32.10 {reset key state when destroying window} -setup {
    set x {}
} -body {
    pack [frame .t.f]; update; focus -force .t.f
    bind .t.f <Key-A> { set x "A" }
    event generate .t.f <KeyPress-A>
    event generate .t.f <KeyPress-A>
    bind .t.f <A> { set x "A" }
    event generate .t.f <A>
    event generate .t.f <A>
    destroy .t.f; update
    pack [frame .t.f]; update; focus -force .t.f
    bind .t.f <Key-A> { set x "A" }
    bind .t.f <Double-Key-A> { set x "AA" }
    event generate .t.f <KeyPress-A>
    bind .t.f <A> { set x "A" }
    bind .t.f <Double-A> { set x "AA" }
    event generate .t.f <A>
    destroy .t.f
    set x
} -result {A}
test bind-32.11 {match detailed virtual} -setup {
    pack [frame .t.f -class Test]
    focus -force .t.f
    update
    set x {}
} -body {
    event add <<TestControlButton1>> <Control-Button-1>
    bind Test <<TestControlButton1>> { set x "Control-Button-1" }
    bind Test <Button-1> { set x "Button-1" }
    bind .t.f <Button-1> { set x "Button-1" }
    event generate .t.f <Control-ButtonPress-1>
    event generate .t.f <Control-Button-1>
    set x
} -cleanup {
    destroy .t.f
    event delete <<TestControlButton1>>
    bind Test <Button-1> {#}
} -result {Control-Button-1}
test bind-32.12 {don't detect repetition when window has changed} -setup {
    pack [frame .t.f]
    pack [frame .t.g]
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Button-1> { set x "1" }
    bind .t.f <Double-Button-1> { set x "11" }
    event generate .t.f <ButtonPress-1>
    event generate .t.g <ButtonPress-1>
    event generate .t.f <ButtonPress-1>
    event generate .t.f <Button-1>
    event generate .t.g <Button-1>
    event generate .t.f <Button-1>
    set x
} -cleanup {
    destroy .t.f
    destroy .t.g
} -result {1}
} -result 1
test bind-32.13 {don't detect repetition when window has changed} -setup {
    pack [frame .t.f]
    pack [frame .t.g]
    update
    set x {}
} -body {
    bind .t.f <Key-A> { set x "A" }
    bind .t.f <Double-Key-A> { set x "AA" }
    focus -force .t.f; event generate .t.f <KeyPress-A>
    focus -force .t.g; event generate .t.g <KeyPress-A>
    focus -force .t.f; event generate .t.f <KeyPress-A>
    bind .t.f <A> { set x "A" }
    bind .t.f <Double-A> { set x "AA" }
    focus -force .t.f; event generate .t.f <A>
    focus -force .t.g; event generate .t.g <A>
    focus -force .t.f; event generate .t.f <A>
    set x
} -cleanup {
    destroy .t.f
    destroy .t.g
} -result {A}
test bind-32.14 {don't detect repetition when window has changed} -setup {
    pack [frame .t.f]
    pack [frame .t.g]
    update
    set x {}
} -body {
    bind .t.f <ButtonPress-1> { set x "1" }
    bind .t.f <Double-ButtonPress-1> { set x "11" }
    focus -force .t.f; event generate .t.f <ButtonPress-1>
    focus -force .t.g; event generate .t.g <ButtonPress-1>
    focus -force .t.f; event generate .t.f <ButtonPress-1>
    bind .t.f <Button-1> { set x "1" }
    bind .t.f <Double-Button-1> { set x "11" }
    focus -force .t.f; event generate .t.f <Button-1>
    focus -force .t.g; event generate .t.g <Button-1>
    focus -force .t.f; event generate .t.f <Button-1>
    set x
} -cleanup {
    destroy .t.f
    destroy .t.g
} -result {1}
} -result 1
test bind-32.15 {reset button state when destroying window} -setup {
    set x {}
} -body {
    pack [frame .t.f]; update; focus -force .t.f
    bind .t.f <ButtonPress-1> { set x "1" }
    event generate .t.f <ButtonPress-1>
    event generate .t.f <ButtonPress-1>
    bind .t.f <Button-1> { set x "1" }
    event generate .t.f <Button-1>
    event generate .t.f <Button-1>
    destroy .t.f; update
    pack [frame .t.f]; update; focus -force .t.f
    bind .t.f <ButtonPress-1> { set x "1" }
    bind .t.f <Double-ButtonPress-1> { set x "11" }
    event generate .t.f <ButtonPress-1>
    bind .t.f <Button-1> { set x "1" }
    bind .t.f <Double-Button-1> { set x "11" }
    event generate .t.f <Button-1>
    destroy .t.f
    set x
} -result {1}
} -result 1

test bind-33.1 {prefer longest match} -setup {
    pack [frame .t.f]
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <a><1><1> { lappend x "a11" }
    bind .t.f <Double-1> { lappend x "Double" }
    bind .t.f <a><Button-1><Button-1> { lappend x "a11" }
    bind .t.f <Double-Button-1> { lappend x "Double" }
    event generate .t.f <a>
    event generate .t.f <1>
    event generate .t.f <1>
    event generate .t.f <Button-1>
    event generate .t.f <Button-1>
    set x
} -cleanup {
    destroy .t.f
} -result {a11}
test bind-33.2 {should prefer most specific event} -setup {
test bind-33.2 {prefer most specific event} -setup {
    pack [frame .t.f]
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Double-1> { lappend x "Double" }
    bind .t.f <1><1> { lappend x "11" }
    event generate .t.f <1>
    event generate .t.f <1>
    bind .t.f <Double-Button-1> { lappend x "Double" }
    bind .t.f <Button-1><Button-1> { lappend x "11" }
    event generate .t.f <Button-1>
    event generate .t.f <Button-1>
    set x
} -cleanup {
    destroy .t.f
    # This test case shows that old implementation has an issue, because
    # it is expected that <Double-1> is matching, this binding
    # is more specific. But new implementation will be conform to old,
    # and so "11" is the expected result.
} -result {11}
test bind-33.3 {should prefer most specific event} -setup {
} -result {Double}
test bind-33.3 {prefer most specific event} -setup {
    pack [frame .t.f]
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <a><Double-1><a> { lappend x "Double" }
    bind .t.f <a><1><1><a> { lappend x "11" }
    bind .t.f <a><Double-Button-1><a> { lappend x "Double" }
    bind .t.f <a><Button-1><Button-1><a> { lappend x "11" }
    event generate .t.f <a>
    event generate .t.f <1>
    event generate .t.f <1>
    event generate .t.f <Button-1>
    event generate .t.f <Button-1>
    event generate .t.f <a>
    set x
} -cleanup {
    destroy .t.f
    # Also this test case shows that old implementation has an issue, it is
    # expected that <a><Double-1><a> is matching, because <Double-1> is more
    # specific than <1><1>. But new implementation will be conform to old,
    # and so "11" is the expected result.
} -result {11}
} -result {Double}
test bind-33.4 {prefer most specific event} -setup {
    pack [frame .t.f]
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <1><1> { lappend x "11" }
    bind .t.f <Double-1> { lappend x "Double" }
    event generate .t.f <1> -time 0
    event generate .t.f <1> -time 1000
    bind .t.f <Button-1><Button-1> { lappend x "11" }
    bind .t.f <Double-Button-1> { lappend x "Double" }
    event generate .t.f <Button-1> -time 0
    event generate .t.f <Button-1> -time 1000
    set x
} -cleanup {
    destroy .t.f
} -result {11}
} -result 11
test bind-33.5 {prefer most specific event} -setup {
    pack [frame .t.f]
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <1><1> { lappend x "11" }
    bind .t.f <Double-ButtonPress> { lappend x "Double" }
    event generate .t.f <1>
    event generate .t.f <1>
    bind .t.f <Button-1><Button-1> { lappend x "11" }
    bind .t.f <Double-Button> { lappend x "Double" }
    event generate .t.f <Button-1>
    event generate .t.f <Button-1>
    set x
} -cleanup {
    destroy .t.f
} -result {11}
} -result 11
test bind-33.6 {prefer most specific event} -setup {
    pack [frame .t.f]
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <a><1><1><1><1><a> { lappend x "1111" }
    bind .t.f <a><ButtonPress><Double-ButtonPress><ButtonPress><a> { lappend x "Any-Double-Any" }
    bind .t.f <a><Button-1><Button-1><Button-1><Button-1><a> { lappend x "1111" }
    bind .t.f <a><Button><Double-Button><Button><a> { lappend x "Any-Double-Any" }
    event generate .t.f <a>
    event generate .t.f <1>
    event generate .t.f <1>
    event generate .t.f <1>
    event generate .t.f <1>
    event generate .t.f <Button-1>
    event generate .t.f <Button-1>
    event generate .t.f <Button-1>
    event generate .t.f <Button-1>
    event generate .t.f <a>
    set x
} -cleanup {
    destroy .t.f
} -result {1111}
} -result 1111
test bind-33.7 {prefer most specific event} -setup {
    pack [frame .t.f]
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <ButtonPress-1><a> { lappend x "1" }
    bind .t.f <ButtonPress><a> { lappend x "Any" }
    event generate .t.f <1>
    bind .t.f <Button-1><a> { lappend x "1" }
    bind .t.f <Button><a> { lappend x "Any" }
    event generate .t.f <Button-1>
    event generate .t.f <a>
    set x
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1
test bind-33.8 {prefer most specific event} -setup {
    pack [frame .t.f]
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Double-ButtonPress-1><a> { lappend x "1" }
    bind .t.f <ButtonPress><ButtonPress><a> { lappend x "Any" }
    event generate .t.f <1>
    event generate .t.f <1>
    bind .t.f <Double-Button-1><a> { lappend x "1" }
    bind .t.f <Button><Button><a> { lappend x "Any" }
    event generate .t.f <Button-1>
    event generate .t.f <Button-1>
    event generate .t.f <a>
    set x
} -cleanup {
    destroy .t.f
} -result {1}
} -result 1
test bind-33.9 {prefer last in case of homogeneous equal patterns} -setup {
    pack [frame .t.f]
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <1><2><2><Double-1> { lappend x "first" }
    bind .t.f <1><Double-2><1><1> { lappend x "last" }
    event generate .t.f <1>
    event generate .t.f <2>
    event generate .t.f <2>
    event generate .t.f <1>
    event generate .t.f <1>
    bind .t.f <Button-1><Button-2><Button-2><Double-Button-1> { lappend x "first" }
    bind .t.f <Button-1><Double-Button-2><Button-1><Button-1> { lappend x "last" }
    event generate .t.f <Button-1>
    event generate .t.f <Button-2>
    event generate .t.f <Button-2>
    event generate .t.f <Button-1>
    event generate .t.f <Button-1>
    set x
} -cleanup {
    destroy .t.f
} -result {last}
test bind-33.10 {prefer last in case of homogeneous equal patterns} -setup {
    pack [frame .t.f]
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <1><Double-2><1><1> { lappend x "first" }
    bind .t.f <1><2><2><Double-1> { lappend x "last" }
    event generate .t.f <1>
    event generate .t.f <2>
    event generate .t.f <2>
    event generate .t.f <1>
    event generate .t.f <1>
    bind .t.f <Button-1><Double-Button-2><Button-1><Button-1> { lappend x "first" }
    bind .t.f <Button-1><Button-2><Button-2><Double-Button-1> { lappend x "last" }
    event generate .t.f <Button-1>
    event generate .t.f <Button-2>
    event generate .t.f <Button-2>
    event generate .t.f <Button-1>
    event generate .t.f <Button-1>
    set x
} -cleanup {
    destroy .t.f
} -result {last}
test bind-33.11 {should prefer most specific} -setup {
    pack [frame .t.f]
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <2><Double-1><Double-2><Double-1><2><2> { lappend x "first" }
    bind .t.f <2><1><1><2><2><Double-1><Double-2> { lappend x "last" }
    event generate .t.f <2>
    event generate .t.f <1>
    event generate .t.f <1>
    event generate .t.f <2>
    event generate .t.f <2>
    event generate .t.f <1>
    event generate .t.f <1>
    event generate .t.f <2>
    event generate .t.f <2>
    bind .t.f <Button-2><Double-Button-1><Double-Button-2><Double-Button-1><Button-2><Button-2> { lappend x "first" }
    bind .t.f <Button-2><Button-1><Button-1><Button-2><Button-2><Double-Button-1><Double-Button-2> { lappend x "last" }
    event generate .t.f <Button-2>
    event generate .t.f <Button-1>
    event generate .t.f <Button-1>
    event generate .t.f <Button-2>
    event generate .t.f <Button-2>
    event generate .t.f <Button-1>
    event generate .t.f <Button-1>
    event generate .t.f <Button-2>
    event generate .t.f <Button-2>
    set x
} -cleanup {
    destroy .t.f
    # This test case shows that old implementation has an issue, because
    # it is expected that first one is matching, this binding
    # is more specific. But new implementation will be conform to old,
    # and so "last" is the expected result.
} -result {last}
} -result {first}
test bind-33.12 {prefer last in case of homogeneous equal patterns} -setup {
    pack [frame .t.f]
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Control-1><1> { lappend x "first" }
    bind .t.f <1><Control-1> { lappend x "last" }
    event generate .t.f <Control-1>
    event generate .t.f <Control-1>
    bind .t.f <Control-Button-1><Button-1> { lappend x "first" }
    bind .t.f <Button-1><Control-Button-1> { lappend x "last" }
    event generate .t.f <Control-Button-1>
    event generate .t.f <Control-Button-1>
    set x
} -cleanup {
    destroy .t.f
} -result {last}
test bind-33.13 {prefer last in case of homogeneous equal patterns} -setup {
    pack [frame .t.f]
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <1><Control-1> { lappend x "first" }
    bind .t.f <Control-1><1> { lappend x "last" }
    event generate .t.f <Control-1>
    event generate .t.f <Control-1>
    bind .t.f <Button-1><Control-1> { lappend x "first" }
    bind .t.f <Control-1><Button-1> { lappend x "last" }
    event generate .t.f <Control-Button-1>
    event generate .t.f <Control-Button-1>
    set x
} -cleanup {
    destroy .t.f
    # Old implementation failed, and returned "first", but this was wrong,
    # because both bindings are homogeneous equal, so the most recently defined
    # must be preferred.
} -result {last}
test bind-33.14 {prefer last in case of homogeneous equal patterns} -setup {
    pack [frame .t.f]
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <1><ButtonPress><1><ButtonPress> { lappend x "first" }
    bind .t.f <ButtonPress><1><ButtonPress><1> { lappend x "last" }
    event generate .t.f <1>
    event generate .t.f <1>
    event generate .t.f <1>
    event generate .t.f <1>
    bind .t.f <Button-1><Button><Button-1><Button> { lappend x "first" }
    bind .t.f <Button><Button-1><Button><Button-1> { lappend x "last" }
    event generate .t.f <Button-1>
    event generate .t.f <Button-1>
    event generate .t.f <Button-1>
    event generate .t.f <Button-1>
    set x
} -cleanup {
    destroy .t.f
} -result {last}
test bind-33.15 {prefer last in case of homogeneous equal patterns} -setup {
    pack [frame .t.f]
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <ButtonPress><1><ButtonPress><1> { lappend x "first" }
    bind .t.f <1><ButtonPress><1><ButtonPress> { lappend x "last" }
    event generate .t.f <1>
    event generate .t.f <1>
    event generate .t.f <1>
    event generate .t.f <1>
    bind .t.f <Button><Button-1><Button><Button-1> { lappend x "first" }
    bind .t.f <Button-1><Button><Button-1><Button> { lappend x "last" }
    event generate .t.f <Button-1>
    event generate .t.f <Button-1>
    event generate .t.f <Button-1>
    event generate .t.f <Button-1>
    set x
} -cleanup {
    destroy .t.f
    # Old implementation failed, and returned "first", but this was wrong,
    # because both bindings are homogeneous equal, so the most recently defined
    # must be preferred.
} -result {last}
test bind-33.16 {simulate use of the keyboard to trigger a pattern sequence with modifier - bug [16ef161925]} -setup {
    pack [frame .t.f]
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Escape><Control-c> { lappend x "Esc_Control-c" }
    event generate .t.f <Escape>
    event generate .t.f <Control_L>
    event generate .t.f <Control_L>
    event generate .t.f <Control_L>
    event generate .t.f <Control-c>
    set x
} -cleanup {
    destroy .t.f
} -result {Esc_Control-c}
test bind-33.17 {simulate use of the keyboard to trigger a pattern sequence with modifier - bug [16ef161925]} -setup {
    pack [frame .t.f]
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Escape><Control-c> { lappend x "Esc_Control-c" }
    bind .t.f <Escape><Control_L><Control-c> { lappend x "Esc_Ctrl_L_Control-c" }
    event generate .t.f <Escape>
    event generate .t.f <Control_L>
    event generate .t.f <Control_L>
    event generate .t.f <Control_L>
    event generate .t.f <Control-c>
    set x
} -cleanup {
    destroy .t.f
} -result {Esc_Ctrl_L_Control-c}
test bind-33.18 {simulate use of the keyboard to trigger a pattern sequence with modifier - bug [16ef161925]} -setup {
    pack [frame .t.f]
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Escape><Control-c> { lappend x "Esc_Control-c" }
    bind .t.f <Escape><Control_L><Control-c> { lappend x "Esc_Ctrl_L_Control-c" }
    bind .t.f <Escape><Control_L><Control_L><Control-c> { lappend x "Esc_Ctrl_L(2)_Control-c" }
    event generate .t.f <Escape>
    event generate .t.f <Control_L>
    event generate .t.f <Control_L>
    event generate .t.f <Control_L>
    event generate .t.f <Control-c>
    set x
} -cleanup {
    destroy .t.f
} -result {Esc_Ctrl_L(2)_Control-c}
test bind-33.19 {simulate use of the keyboard to trigger a pattern sequence with modifier - bug [16ef161925]} -setup {
    pack [frame .t.f]
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Escape><Control-c> { lappend x "Esc_Control-c" }
    bind .t.f <Escape><Key><Key><Control-c> { lappend x "Esc_Key(2)_Control-c" }
    event generate .t.f <Escape>
    event generate .t.f <Alt_L>
    event generate .t.f <Control_L>
    event generate .t.f <Control-c>
    set x
} -cleanup {
    destroy .t.f
} -result {Esc_Key(2)_Control-c}
test bind-33.20 {simulate use of the keyboard to trigger a pattern sequence with mixed Key and Button types - bug [16ef161925]} -setup {
    pack [frame .t.f]
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Key-1><Button-1> { lappend x "1_Button1" }
    event generate .t.f <Key-1>
    event generate .t.f <KeyRelease-1>
    event generate .t.f <Button-1>
    set x
} -cleanup {
    destroy .t.f
} -result {1_Button1}
test bind-33.21 {simulate use of the keyboard to trigger a pattern sequence with mixed Key and Button types - bug [16ef161925]} -setup {
    pack [frame .t.f]
    focus -force .t.f
    update
    set x {}
} -body {
    bind .t.f <Key-1><Button-1> { lappend x "1_Button1" }
    bind .t.f <Key-1><Button-1><Key-2> { lappend x "1_Button1_2" }
    event generate .t.f <Key-1>
    event generate .t.f <KeyRelease-1>
    event generate .t.f <Button-1>
    event generate .t.f <Key-2>
    event generate .t.f <KeyRelease-2>
    set x
} -cleanup {
    destroy .t.f
} -result {1_Button1 1_Button1_2}

test bind-34.1 {-warp works relatively to a window} -setup {
    toplevel .top
    wm geometry .top +100+100
    update
} -body {
    # In order to avoid platform-dependent coordinate results due to
    # decorations and borders, this test warps the pointer twice 
    # decorations and borders, this test warps the pointer twice
    # relatively to a window that moved in the meantime, and checks
    # how much the pointer moved
    wm geometry .top +200+200
    update
    event generate .top <Motion> -x 20 -y 20 -warp 1
    update idletasks ; # DoWarp is an idle callback
    after 50         ; # Win specific - wait for SendInput to be executed
    after 50  ; # Win specific - wait for SendInput to be executed
    set pointerPos1 [winfo pointerxy .top]
    wm geometry .top +600+600
    update
    event generate .top <Motion> -x 20 -y 20 -warp 1
    update idletasks ; # DoWarp is an idle callback
    after 50         ; # Win specific - wait for SendInput to be executed
    after 50  ; # Win specific - wait for SendInput to be executed
    set pointerPos2 [winfo pointerxy .top]
    # from the first warped position to the second one, the mouse
    # pointer should have moved the same amount as the window moved
    set res 1
    foreach pos1 $pointerPos1 pos2 $pointerPos2 {
        if {$pos1 != [expr {$pos2 - 400}]} {
            set res [list $pointerPos1 $pointerPos2]
        }
    }
    set res
} -cleanup {
    destroy .top
} -result {1}
} -result 1
test bind-34.2 {-warp works relatively to the screen} -setup {
} -body {
    # Contrary to bind-34.1, we're directly checking screen coordinates
    event generate {} <Motion> -x 20 -y 20 -warp 1
    update idletasks ; # DoWarp is an idle callback
    after 50         ; # Win specific - wait for SendInput to be executed
    after 50  ; # Win specific - wait for SendInput to be executed
    set res [winfo pointerxy .]
    event generate {} <Motion> -x 200 -y 200 -warp 1
    update idletasks ; # DoWarp is an idle callback
    after 50         ; # Win specific - wait for SendInput to be executed
    after 50  ; # Win specific - wait for SendInput to be executed
    lappend res {*}[winfo pointerxy .]
} -cleanup {
} -result {20 20 200 200}
test bind-34.3 {-warp works with null or negative coordinates} -setup {
    # On some OS/WM, at least Linux with KDE, the "Screen edges" feature
    # provides hot spots that can be associated with some action.
    # When activated, the WM will not allow warping to happen on top of
    # a hot spot (which would trigger the corresponding action as an
    # unwanted effect) but will warp the pointer to the hot spot limit only.
    if {[tk windowingsystem] eq "x11"} {
        set halo 1
    } else {
        set halo 0
    }
    set res {}
} -body {
    event generate {} <Motion> -x 0 -y 0 -warp 1
    update idletasks ; # DoWarp is an idle callback
    after 50         ; # Win specific - wait for SendInput to be executed
    after 50  ; # Win specific - wait for SendInput to be executed
    foreach dim [winfo pointerxy .] {
        if {$dim <= $halo} {
            lappend res ok
        } else {
            lappend res $dim
        }
    }
    event generate {} <Motion> -x 100 -y 100 -warp 1
    update idletasks ; after 50
    after 50  ; # Win specific - wait for SendInput to be executed
    event generate {} <Motion> -x -1 -y -1 -warp 1
    update idletasks ; after 50
    after 50  ; # Win specific - wait for SendInput to be executed
    foreach dim [winfo pointerxy .] {
        if {$dim <= $halo} {
            lappend res ok
        } else {
            lappend res $dim
        }
    }
    set res
} -cleanup {
} -result {ok ok ok ok}

set keyInfo {}
set numericKeysym {}
proc testKey {window event type mods} {
    global keyInfo numericKeysym
    set keyInfo {}
    set numericKeysym {}
    bind $window <Key> {
	set keyInfo [format "%K,0x%%X,0x%%X,%A" %N %k]
	set numericKeysym %N
    }
    focus -force $window
    update
    event generate $window $event
    if {$keyInfo == {}} {
        vwait keyInfo
    }
    set save $keyInfo
    set keyInfo {}
    set injectcmd [list injectkeyevent $type $numericKeysym]
    foreach {option} $mods {
	lappend injectcmd $option
    }
    eval $injectcmd
    if {$keyInfo == {}} {
        vwait keyInfo
    }
    if {$save != $keyInfo} {
	return "[format "0x%x" $numericKeysym] ($mods): $save != $keyInfo"
    }
    return pass
}
proc testKeyWithMods {window keysym type} {
    set result [testKey $window "<$keysym>" $type {}]
    if {$result != {pass}} {
	return $result
    }
    set result [testKey $window "<Shift-$keysym>" $type {-shift}]
    if {$result != {pass}} {
	return $result
    }
    set result [testKey $window "<Option-$keysym>" $type {-option}]
    if {$result != {pass}} {
	return $result
    }
    set result [testKey $window "<Shift-Option-$keysym>" $type {-shift -option}]
    if {$result != {pass}} {
	return $result
    }
    return pass
}
test bind-35.0 {Generated and real key events agree} -constraints {aqua} -body {
    foreach k {o O F2 Home Right Greek_sigma Greek_ALPHA} {
	set result [testKeyWithMods . $k press]
	if {$result != "pass"} {
	    return $result
	}
    }
    return pass
} -cleanup {
} -result pass
test bind-35.1 {pointer warp with grab on master, bug [e3888d5820]} -setup {
    pointerAway

test bind-35.1 {Key events agree for entry widgets} -constraints {aqua} -setup {
    toplevel .new
    entry .new.e
    pack .new.e
} -body {
    foreach k {o O F2 Home Right Greek_sigma Greek_ALPHA Menu} {
	set result [testKeyWithMods .new.e $k press]
	if {$result != "pass"} {
	    return $result
	}
    }
    return pass
} -cleanup {
    destroy .new.e
    destroy .new
} -result pass

test bind-35.2 {Can bind to function keys} -constraints {aqua} -body {
    global keyInfo numericKeysym
    bind . <Key> {}
    bind . <Key> {
	lappend keyInfo %K
	set numericKeysym %N
    }
    set keyInfo {}
    set numericKeysym {}
    focus -force .
    event generate . <F2>
    injectkeyevent press $numericKeysym -function
    vwait keyInfo
    return $keyInfo
} -cleanup {
} -result {F2 F2}

test bind-35.3 {Events agree for modifier keys} -constraints {aqua} -setup {
} -body {
    global keyInfo numericalKeysym
    set result {}
    bind . <Key> {
    	set keyInfo [format "%K,0x%%X,0x%%X,%A" %N %k]
    	set numericalKeysym [format "0x%x" %N]
    }
    foreach event {
	{<Control_L> -control}
	{<Control_R> -control}
	{<Alt_L> -option}
	{<Alt_R> -option}
	{<Meta_L> -command}
	{<Meta_R> -command}
	{<Shift_L> -shift}
	{<Shift_R> -shift}
    } {
	set keyInfo {}
	event generate . [lindex $event 0]
	if {$keyInfo == {}} {
	    vwait keyInfo
	}
	set save $keyInfo
	injectkeyevent flagschanged $numericKeysym [lindex $event 1]
	if {$keyInfo == {}} {
	    vwait keyInfo
	}
	if {$save != $keyInfo} {
	    return "$save != $keyInfo"
	}
    }
    return pass
} -cleanup {
} -result pass

test bind-36.1 {pointer warp with grab on toplevel, bug [e3888d5820]} -setup {
    event generate {} <Motion> -warp 1 -x 50 -y 50
    after 50  ; # Win specific - wait for SendInput to be executed
    toplevel .top
    grab release .top
    wm geometry .top 200x200+300+300
    label .top.l -height 5 -width 20 -highlightthickness 2 \
            -highlightbackground black -bg yellow -text "My label"
    pack .top.l -side bottom
    update
    # On KDE/Plasma _with_the_Aurorae_theme_ (at least), setting up the toplevel
    # and the label will not be finished after the above 'update'. The WM still
    # needs some time before the window is fully ready. For me 50 ms is enough,
    # but let's wait more (it depends on computer performance).
    after 100 ; update
} -body {
    grab .top  ; # this will queue events
    grab .top
    after 50
    update
    event generate .top.l <Motion> -warp 1 -x 10 -y 10
    update idletasks ; after 50
    after 50  ; # Win specific - wait for SendInput to be executed
    foreach {x1 y1} [winfo pointerxy .top.l] {}
    event generate {} <Motion> -warp 1 -x 50 -y 50
    update idletasks ; after 50
    grab release .top  ; # this will queue events
    after 50  ; # Win specific - wait for SendInput to be executed
    grab release .top
    after 50
    update
    event generate .top.l <Motion> -warp 1 -x 10 -y 10
    update idletasks ; after 50
    after 50  ; # Win specific - wait for SendInput to be executed
    foreach {x2 y2} [winfo pointerxy .top.l] {}
    # success if the coords are the same with or without the grab, and if they
    # are at (10,10) inside the label widget as requested by the warping
    expr {$x1==$x2 && $y1==$y2 && $x1==[winfo rootx .top.l]+10 \
                               && $y1==[winfo rooty .top.l]+10}
} -cleanup {
    destroy .top
    unset x1 y1 x2 y2
} -result {1}
} -result 1

# cleanup
cleanupTests
return

# vi:set ts=4 sw=4 et:
# Local Variables:
# mode: tcl
# End:
Changes to tests/bitmap.test.
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15
16
17
18

19
20
21
22
23
24
25
1
2
3
4


5
6
7
8
9
10
11
12
13
14
15
16
17

18
19
20
21
22
23
24
25




-
-
+
+











-
+







# This file is a Tcl script to test out the procedures in the file
# tkBitmap.c.  It is organized in the standard white-box fashion for
# Tcl tests.
#
# Copyright (c) 1998 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1998 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
namespace import ::tcltest::*
eval tcltest::configure $argv
tcltest::loadTestedCommands

test bitmap-1.1 {Tk_AllocBitmapFromObj - converting internal reps} -constraints {
    testbitmap
} -body {
    set x gray25
    lindex $x 0             
    lindex $x 0
    button .b -bitmap $x
    lindex $x 0
    testbitmap gray25
} -cleanup {
    destroy .b
} -result {{1 0}}
test bitmap-1.2 {Tk_AllocBitmapFromObj - discard stale bitmap} -constraints {
50
51
52
53
54
55
56
57

58
59
60
61
62

63
64
65
66
67
68
69
50
51
52
53
54
55
56

57
58
59
60
61

62
63
64
65
66
67
68
69







-
+




-
+







} -cleanup {
    destroy .b1 .b2
} -result {{{1 1}} {{2 1}}}

test bitmap-2.1 {Tk_GetBitmap procedure} -body {
    button .b1 -bitmap bad_name
} -cleanup {
    destroy .b1 
    destroy .b1
} -returnCodes error -result {bitmap "bad_name" not defined}
test bitmap-2.2 {Tk_GetBitmap procedure} -body {
    button .b1 -bitmap @xyzzy
} -cleanup {
    destroy .b1 
    destroy .b1
} -returnCodes error -result {error reading bitmap file "xyzzy"}

test bitmap-3.1 {Tk_FreeBitmapFromObj - reference counts} -constraints {
    testbitmap
} -setup {
    set result {}
} -body {
Changes to tests/border.test.
1
2
3
4
5


6
7
8
9
10
11
12
13
14


15
16
17
18
19
20
21
22
23
24
25


26
27
28
29
30
31
32
33
34
35
36
37
38
39


40
41
42
43
44
45
46
47
48
49
50
51
52

53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73

74
75
76
77
78
79
80
1
2
3


4
5
6
7
8
9
10
11
12


13
14
15
16
17
18
19
20
21
22
23


24
25
26
27
28
29
30
31
32
33
34
35
36
37


38
39
40
41
42
43
44
45
46
47
48
49
50
51

52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72

73
74
75
76
77
78
79
80



-
-
+
+







-
-
+
+









-
-
+
+












-
-
+
+












-
+




















-
+







# This file is a Tcl script to test out the procedures in the file
# tkBorder.c.  It is organized in the standard fashion for Tcl tests.
#
# Copyright (c) 1998 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1998 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
namespace import ::tcltest::*
eval tcltest::configure $argv
tcltest::loadTestedCommands

test border-1.1 {Tk_AllocBorderFromObj - converting internal reps} -constraints {  
    testborder 
test border-1.1 {Tk_AllocBorderFromObj - converting internal reps} -constraints {
    testborder
} -body {
    set x orange
    lindex $x 0
    button .b1 -bg $x -text .b1
    lindex $x 0
    testborder orange
} -cleanup {
    destroy .b1
} -result {{1 0}}
test border-1.2 {Tk_AllocBorderFromObj - discard stale border} -constraints {  
    testborder 
test border-1.2 {Tk_AllocBorderFromObj - discard stale border} -constraints {
    testborder
} -setup {
    set result {}
} -body {
    set x orange
    button .b1 -bg $x -text First
    destroy .b1
    lappend result [testborder orange]
    button .b2 -bg $x -text Second
    lappend result [testborder orange]
} -cleanup {
    destroy .b1 .b2
} -result {{} {{1 1}}}
test border-1.3 {Tk_AllocBorderFromObj - reuse existing border} -constraints {  
    testborder 
test border-1.3 {Tk_AllocBorderFromObj - reuse existing border} -constraints {
    testborder
} -setup {
    set result {}
} -body {
    set x orange
    button .b1 -bg $x -text First
    lappend result [testborder orange]
    button .b2 -bg $x -text Second
    pack .b1 .b2 -side top
    lappend result [testborder orange]
} -cleanup {
    destroy .b1 .b2
} -result {{{1 1}} {{2 1}}}
test border-1.4 {Tk_AllocBorderFromObj - try other borders in list} -constraints {  
test border-1.4 {Tk_AllocBorderFromObj - try other borders in list} -constraints {
    testborder pseudocolor8
} -setup {
    toplevel .t -visual {pseudocolor 8} -colormap new
    wm geom .t +0+0
    set result {}
} -body {
    set x purple
    button .b1 -bg $x -text First
    pack .b1 -side top
    lappend result [testborder purple]
    button .t.b -bg $x -text Second
    pack .t.b -side top
    lappend result [testborder purple]
    button .b2 -bg $x -text Third
    pack .b2 -side top
    lappend result [testborder purple]
} -cleanup {
    destroy .b1 .b2 .t
} -result {{{1 1}} {{1 1} {1 0}} {{1 0} {2 1}}}

test border-2.1 {Tk_Free3DBorder - reference counts} -constraints {  
test border-2.1 {Tk_Free3DBorder - reference counts} -constraints {
    testborder pseudocolor8
} -setup {
    toplevel .t -visual {pseudocolor 8} -colormap new
    wm geom .t +0+0
    set result {}
} -body {
    set x purple
90
91
92
93
94
95
96
97

98
99
100
101
102
103
104
90
91
92
93
94
95
96

97
98
99
100
101
102
103
104







-
+







    destroy .b2
    lappend result [testborder purple]
    destroy .t.b
    lappend result [testborder purple]
} -cleanup {
    destroy .b1 .b2 .t
} -result {{{1 0} {2 1}} {{1 0} {1 1}} {{1 0}} {}}
test border-2.2 {Tk_Free3DBorder - unlinking from list} -constraints {  
test border-2.2 {Tk_Free3DBorder - unlinking from list} -constraints {
    testborder pseudocolor8
} -setup {
    toplevel .t -visual {pseudocolor 8} -colormap new
    wm geom .t +0+0
    toplevel .t2 -visual {pseudocolor 8} -colormap new
    toplevel .t3 -visual {pseudocolor 8} -colormap new
    set result {}
123
124
125
126
127
128
129

130
131


132
133
134
135
136
137
138
123
124
125
126
127
128
129
130


131
132
133
134
135
136
137
138
139







+
-
-
+
+







    lappend result [testborder purple]
    destroy .t
    lappend result [testborder purple]
} -cleanup {
    destroy .b .t2 .t3 .t
} -result {{{4 1} {3 0} {2 0} {1 0}} {{4 1} {2 0} {1 0}} {{4 1} {2 0}} {{2 0}} {}}


test border-3.1 {FreeBorderObjProc} -constraints {  
    testborder 
test border-3.1 {FreeBorderObjProc} -constraints {
    testborder
} -setup {
    set result {}
    proc copy {s} {return [string index $s 0][string range $s 1 end]}
} -body {
    set x [copy purple]
    button .b -bg $x -text .b1
    set y [copy purple]
Changes to tests/busy.test.
1
2
3
4
5
6
7

8
9

10
11
12
13
14
15
16
17
18
19
20

21
22
23
24

25
26

27

28
29
30

31
32

33

34
35
36

37
38
39
40

41

42
43
44
45

46
47
48
49

50

51
52
53
54

55
56
57
58

59

60
61
62
63

64
65
66
67

68

69
70
71
72

73
74
75
76
77
78
79
80
81
82

83

84
85
86

87
88

89

90
91
92

93
94
95
96
97
98
99
1
2
3
4
5
6

7
8

9
10
11
12
13
14
15
16
17
18
19

20
21
22
23

24
25

26
27
28
29
30

31
32

33
34
35
36
37

38
39
40
41

42
43
44
45
46
47

48
49
50
51

52
53
54
55
56
57

58
59
60
61

62
63
64
65
66
67

68
69
70
71

72
73
74
75
76
77

78
79
80
81
82
83
84
85
86
87

88
89
90
91
92

93
94

95
96
97
98
99

100
101
102
103
104
105
106
107






-
+

-
+










-
+



-
+

-
+

+


-
+

-
+

+


-
+



-
+

+



-
+



-
+

+



-
+



-
+

+



-
+



-
+

+



-
+









-
+

+


-
+

-
+

+


-
+







# Tests for the tk busy command.
#
# This file contains a collection of tests for one or more of the Tk built-in
# commands. Sourcing this file runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright (c) 1998-2000 by Jos Decoster. All rights reserved.
# Copyright © 1998-2000 Jos Decoster. All rights reserved.

package require tcltest 2.1
package require tcltest 2.2
tcltest::configure {*}$argv
tcltest::loadTestedCommands
namespace import -force tcltest::test

# There's currently no way to test the actual grab effect, per se, in an
# automated test. Therefore, this test suite only covers the interface to the
# grab command (ie, error messages, etc.)

test busy-1.1 {Tk_BusyObjCmd} -returnCodes error -body {
    tk busy
} -result {wrong # args: should be "tk busy options ?arg arg ...?"}
} -result {wrong # args: should be "tk busy options ?arg ...?"}

test busy-2.1 {tk busy hold} -returnCodes error -body {
    tk busy hold
} -result {wrong # args: should be "tk busy hold window ?option value ...?"}
} -result {wrong # args: should be "tk busy hold window ?-option value ...?"}
test busy-2.2 {tk busy hold root window} -body {
    tk busy hold .
    set res [tk busy hold .]
    update
    set res
} -cleanup {
    tk busy forget .
} -result {}
} -result {._Busy}
test busy-2.3 {tk busy hold root window with shortcut} -body {
    tk busy .
    set res [tk busy .]
    update
    set res
} -cleanup {
    tk busy forget .
} -result {}
} -result {._Busy}
test busy-2.4 {tk busy hold nested window} -setup {
    pack [frame .f]
} -body {
    tk busy hold .f
    set res [tk busy hold .f]
    update
    set res
} -cleanup {
    tk busy forget .f
    destroy .f
} -result {}
} -result {.f_Busy}
test busy-2.5 {tk busy hold nested window with shortcut} -setup {
    pack [frame .f]
} -body {
    tk busy .f
    set res [tk busy .f]
    update
    set res
} -cleanup {
    tk busy forget .f
    destroy .f
} -result {}
} -result {.f_Busy}
test busy-2.6 {tk busy hold toplevel window} -setup {
    toplevel .f
} -body {
    tk busy hold .f
    set res [tk busy hold .f]
    update
    set res
} -cleanup {
    tk busy forget .f
    destroy .f
} -result {}
} -result {.f._Busy}
test busy-2.7 {tk busy hold toplevel window with shortcut} -setup {
    toplevel .f
} -body {
    tk busy .f
    set res [tk busy .f]
    update
    set res
} -cleanup {
    tk busy forget .f
    destroy .f
} -result {}
} -result {.f._Busy}
test busy-2.8 {tk busy hold non existing window} -body {
    tk busy hold .f
    update
} -returnCodes error -result {bad window path name ".f"}
test busy-2.9 {tk busy hold (shortcut) non existing window} -body {
    tk busy .f
    update
} -returnCodes {error} -result {bad window path name ".f"}
test busy-2.10 {tk busy hold root window with cursor} -body {
    tk busy hold . -cursor arrow
    set res [tk busy hold . -cursor arrow]
    update
    set res
} -cleanup {
    tk busy forget .
} -result {}
} -result {._Busy}
test busy-2.11 {tk busy hold (shortcut) root window, cursor} -body {
    tk busy . -cursor arrow
    set res [tk busy . -cursor arrow]
    update
    set res
} -cleanup {
    tk busy forget .
} -result {}
} -result {._Busy}
test busy-2.12 {tk busy hold root window, invalid cursor} -body {
    tk busy hold . -cursor nonExistingCursor
    update
} -returnCodes error -cleanup {
    tk busy forget .
} -result {bad cursor spec "nonExistingCursor"}
test busy-2.13 {tk busy hold (shortcut) root window, invalid cursor} -body {
170
171
172
173
174
175
176
177

178
179
180
181
182
183
184
178
179
180
181
182
183
184

185
186
187
188
189
190
191
192







-
+







} -cleanup {
    tk busy forget .f
    destroy .f
} -result {hand1}

test busy-4.1 {tk busy configure no window} -returnCodes error -body {
    tk busy configure
} -result {wrong # args: should be "tk busy configure window ?option? ?value ...?"}
} -result {wrong # args: should be "tk busy configure window ?-option value ...?"}

test busy-4.2 {tk busy configure invalid window} -body {
    tk busy configure .f
} -returnCodes error -result {bad window path name ".f"}

test busy-4.3 {tk busy configure non-busy window} -setup {
    pack [frame .f]
338
339
340
341
342
343
344
345

346
347
348
349
350
351
352

353
354
355
356
357
358
359
360
361
362

363
364
365
366
367
368
369
370
371
372

373
374
375
376
377
378
379
346
347
348
349
350
351
352

353
354
355
356
357
358
359

360
361
362
363
364
365
366
367
368
369

370
371
372
373
374
375
376
377
378
379

380
381
382
383
384
385
386
387







-
+






-
+









-
+









-
+







} -result {1 0}

test busy-6.1 {tk busy status} -returnCodes error -body {
    tk busy status
} -result {wrong # args: should be "tk busy status window"}
test busy-6.2 {tk busy status non existing window} -body {
    tk busy status .f
} -result {0}
} -result 0
test busy-6.3 {tk busy status non busy window} -setup {
    pack [frame .f]
} -body {
    tk busy status .f
} -cleanup {
    destroy .f
} -result {0}
} -result 0
test busy-6.4 {tk busy status busy window} -setup {
    pack [frame .f]
    tk busy hold .f
    update
} -body {
    tk busy status .f
} -cleanup {
    tk busy forget .f
    destroy .f
} -result {1}
} -result 1
test busy-6.5 {tk busy status forgotten busy window} -setup {
    pack [frame .f]
    tk busy hold .f
    update
    tk busy forget .f
} -body {
    tk busy status .f
} -cleanup {
    destroy .f
} -result {0}
} -result 0

test busy-7.1 {tk busy current no busy} -body {
    tk busy current
} -result {}
test busy-7.2 {tk busy current 1 busy} -setup {
    pack [frame .f]
    tk busy hold .f
468
469
470
471
472
473
474
475
























476
477
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


    tk busy forget .f1
} -body {
    lsort [tk busy current *3*]
} -cleanup {
    tk busy forget .f2
    destroy .f1 .f2
} -result {}

test busy-8.1 {tk busy busywindow with a busy toplevel} -body {
    toplevel .top
    tk busy .top
    tk busy busywindow .top
} -cleanup {
    tk busy forget .top
    destroy .top
} -result {.top._Busy}
test busy-8.2 {tk busy busywindow with a busy widget} -body {
    pack [frame .f]
    tk busy .f
    tk busy busywindow .f
} -cleanup {
    tk busy forget .f
    destroy .f
} -result {.f_Busy}
test busy-8.3 {tk busy busywindow with a nonexisting widget} -body {
    tk busy .
    tk busy busywindow .nonExistingWidget
} -cleanup {
    tk busy forget .
} -result {}


::tcltest::cleanupTests
return
Changes to tests/butGeom2.tcl.
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
1
2
3
4
5
6
7
8
9
10

11
12
13
14
15
16
17
18










-
+







# This file creates a visual test for button layout.  It is part of
# the Tk visual test suite, which is invoked via the "visual" script.

catch {destroy .t}
toplevel .t
wm title .t "Visual Tests for Button Geometry"
wm iconname .t "Button Geometry"
wm geom .t +0+0
wm minsize .t 1 1

label .t.l -text {This screen exercises the color options for various flavors of buttons.  Select display options below, and they will be applied to the appropiate button widgets.} -wraplength 5i
label .t.l -text {This screen exercises the color options for various flavors of buttons.  Select display options below, and they will be applied to the appropriate button widgets.} -wraplength 5i
pack .t.l -side top -fill both

button .t.quit -text Quit -command {destroy .t}
pack .t.quit -side bottom -pady 2m

set sepId 1
proc sep {} {
Changes to tests/button.test.
1
2
3
4
5
6
7



8
9
10
11
12
13
14
1
2
3
4



5
6
7
8
9
10
11
12
13
14




-
-
-
+
+
+







# This file is a Tcl script to test labels, buttons, checkbuttons, and
# radiobuttons in Tk (i.e., all the widgets defined in tkButton.c).  It is
# organized in the standard fashion for Tcl tests.
#
# Copyright (c) 1994 The Regents of the University of California.
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1994 The Regents of the University of California.
# Copyright © 1994-1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
namespace import ::tcltest::*
eval tcltest::configure $argv
tcltest::loadTestedCommands
imageInit
330
331
332
333
334
335
336
337

338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356

357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375

376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394

395
396
397
398
399
400
401
330
331
332
333
334
335
336

337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355

356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374

375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393

394
395
396
397
398
399
400
401







-
+


















-
+


















-
+


















-
+







    pack .l
    update
} -body {
    .l configure -bd 4
    .l cget -bd
} -cleanup {
    destroy .l
} -result {4}
} -result 4
test button-1.34 {configuration option: "bd" for label} -setup {
    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .l
    update
} -body {
    .l configure -bd badValue
} -cleanup {
    destroy .l
} -returnCodes {error} -result {bad screen distance "badValue"}
test button-1.35 {configuration option: "bd" for button} -setup {
    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .b
    update
} -body {
    .b configure -bd 4
    .b cget -bd
} -cleanup {
    destroy .b
} -result {4}
} -result 4
test button-1.36 {configuration option: "bd" for button} -setup {
    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .b
    update
} -body {
    .b configure -bd badValue
} -cleanup {
    destroy .b
} -returnCodes {error} -result {bad screen distance "badValue"}
test button-1.37 {configuration option: "bd" for checkbutton} -setup {
    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .c
    update
} -body {
    .c configure -bd 4
    .c cget -bd
} -cleanup {
    destroy .c
} -result {4}
} -result 4
test button-1.38 {configuration option: "bd" for checkbutton} -setup {
    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .c
    update
} -body {
    .c configure -bd badValue
} -cleanup {
    destroy .c
} -returnCodes {error} -result {bad screen distance "badValue"}
test button-1.39 {configuration option: "bd" for radiobutton} -setup {
    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .r
    update
} -body {
    .r configure -bd 4
    .r cget -bd
} -cleanup {
    destroy .r
} -result {4}
} -result 4
test button-1.40 {configuration option: "bd" for radiobutton} -setup {
    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .r
    update
} -body {
    .r configure -bd badValue
} -cleanup {
558
559
560
561
562
563
564
565

566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584

585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603

604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622

623
624
625
626
627
628
629
558
559
560
561
562
563
564

565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583

584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602

603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621

622
623
624
625
626
627
628
629







-
+


















-
+


















-
+


















-
+








test button-1.57 {configuration option: "borderwidth" for label} -setup {
    label .l -highlightthickness 2 -font {Helvetica -12 bold}
    pack .l
    update
} -body {
    .l configure -borderwidth 1.3
    .l cget -borderwidth 
    .l cget -borderwidth
} -cleanup {
    destroy .l
} -result {1.3}
test button-1.58 {configuration option: "borderwidth" for label} -setup {
    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .l
    update
} -body {
    .l configure -borderwidth badValue
} -cleanup {
    destroy .l
} -returnCodes {error} -result {bad screen distance "badValue"}
test button-1.59 {configuration option: "borderwidth" for button} -setup {
    button .b -highlightthickness 2 -font {Helvetica -12 bold}
    pack .b
    update
} -body {
    .b configure -borderwidth 1.3
    .b cget -borderwidth 
    .b cget -borderwidth
} -cleanup {
    destroy .b
} -result {1.3}
test button-1.60 {configuration option: "borderwidth" for button} -setup {
    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .b
    update
} -body {
    .b configure -borderwidth badValue
} -cleanup {
    destroy .b
} -returnCodes {error} -result {bad screen distance "badValue"}
test button-1.61 {configuration option: "borderwidth" for checkbutton} -setup {
    checkbutton .c -highlightthickness 2 -font {Helvetica -12 bold}
    pack .c
    update
} -body {
    .c configure -borderwidth 1.3
    .c cget -borderwidth 
    .c cget -borderwidth
} -cleanup {
    destroy .c
} -result {1.3}
test button-1.62 {configuration option: "borderwidth" for checkbutton} -setup {
    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .c
    update
} -body {
    .c configure -borderwidth badValue
} -cleanup {
    destroy .c
} -returnCodes {error} -result {bad screen distance "badValue"}
test button-1.63 {configuration option: "borderwidth" for radiobutton} -setup {
    radiobutton .r -highlightthickness 2 -font {Helvetica -12 bold}
    pack .r
    update
} -body {
    .r configure -borderwidth 1.3
    .r cget -borderwidth 
    .r cget -borderwidth
} -cleanup {
    destroy .r
} -result {1.3}
test button-1.64 {configuration option: "borderwidth" for radiobutton} -setup {
    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .r
    update
999
1000
1001
1002
1003
1004
1005
1006

1007
1008
1009
1010
1011
1012
1013
1014
1015
1016

1017
1018
1019
1020
1021
1022
1023
1024
1025

1026
1027
1028
1029
1030
1031
1032
1033
1034
1035

1036
1037
1038
1039
1040
1041
1042
1043
1044

1045
1046
1047
1048
1049
1050
1051
1052
1053
1054

1055
1056
1057
1058
1059
1060
1061
1062
1063

1064
1065
1066
1067
1068
1069
1070
1071
1072
1073

1074
1075
1076
1077
1078
1079
1080
999
1000
1001
1002
1003
1004
1005

1006
1007
1008
1009
1010
1011
1012
1013
1014
1015

1016
1017
1018
1019
1020
1021
1022
1023
1024

1025
1026
1027
1028
1029
1030
1031
1032
1033
1034

1035
1036
1037
1038
1039
1040
1041
1042
1043

1044
1045
1046
1047
1048
1049
1050
1051
1052
1053

1054
1055
1056
1057
1058
1059
1060
1061
1062

1063
1064
1065
1066
1067
1068
1069
1070
1071
1072

1073
1074
1075
1076
1077
1078
1079
1080







-
+









-
+








-
+









-
+








-
+









-
+








-
+









-
+







} -body {
    .r configure -fg non-existent
} -cleanup {
    destroy .r
} -returnCodes {error} -result {unknown color name "non-existent"}

test button-1.103 {configuration option: "font" for label} -setup {
    label .l -borderwidth 2 -highlightthickness 2 
    label .l -borderwidth 2 -highlightthickness 2
    pack .l
    update
} -body {
    .l configure -font {Helvetica -12}
    .l cget -font
} -cleanup {
    destroy .l
} -result {Helvetica -12}
test button-1.104 {configuration option: "activebackground" for label} -setup {
    label .l -borderwidth 2 -highlightthickness 2 
    label .l -borderwidth 2 -highlightthickness 2
    pack .l
    update
} -body {
    .l configure -font {}
} -cleanup {
    destroy .l
} -returnCodes {error} -result {font "" doesn't exist}
test button-1.105 {configuration option: "font" for button} -setup {
    button .b -borderwidth 2 -highlightthickness 2 
    button .b -borderwidth 2 -highlightthickness 2
    pack .b
    update
} -body {
    .b configure -font {Helvetica -12}
    .b cget -font
} -cleanup {
    destroy .b
} -result {Helvetica -12}
test button-1.106 {configuration option: "activebackground" for button} -setup {
    button .b -borderwidth 2 -highlightthickness 2 
    button .b -borderwidth 2 -highlightthickness 2
    pack .b
    update
} -body {
    .b configure -font {}
} -cleanup {
    destroy .b
} -returnCodes {error} -result {font "" doesn't exist}
test button-1.107 {configuration option: "font" for checkbutton} -setup {
    checkbutton .c -borderwidth 2 -highlightthickness 2 
    checkbutton .c -borderwidth 2 -highlightthickness 2
    pack .c
    update
} -body {
    .c configure -font {Helvetica -12}
    .c cget -font
} -cleanup {
    destroy .c
} -result {Helvetica -12}
test button-1.108 {configuration option: "activebackground" for checkbutton} -setup {
    checkbutton .c -borderwidth 2 -highlightthickness 2 
    checkbutton .c -borderwidth 2 -highlightthickness 2
    pack .c
    update
} -body {
    .c configure -font {}
} -cleanup {
    destroy .c
} -returnCodes {error} -result {font "" doesn't exist}
test button-1.109 {configuration option: "font" for radiobutton} -setup {
    radiobutton .r -borderwidth 2 -highlightthickness 2 
    radiobutton .r -borderwidth 2 -highlightthickness 2
    pack .r
    update
} -body {
    .r configure -font {Helvetica -12}
    .r cget -font
} -cleanup {
    destroy .r
} -result {Helvetica -12}
test button-1.110 {configuration option: "activebackground" for radiobutton} -setup {
    radiobutton .r -borderwidth 2 -highlightthickness 2 
    radiobutton .r -borderwidth 2 -highlightthickness 2
    pack .r
    update
} -body {
    .r configure -font {}
} -cleanup {
    destroy .r
} -returnCodes {error} -result {font "" doesn't exist}
1161
1162
1163
1164
1165
1166
1167
1168

1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187

1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206

1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225

1226
1227
1228
1229
1230
1231
1232
1161
1162
1163
1164
1165
1166
1167

1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186

1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205

1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224

1225
1226
1227
1228
1229
1230
1231
1232







-
+


















-
+


















-
+


















-
+







    pack .l
    update
} -body {
    .l configure -height 18
    .l cget -height
} -cleanup {
    destroy .l
} -result {18}
} -result 18
test button-1.120 {configuration option: "height" for label} -setup {
    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .l
    update
} -body {
    .l configure -height 20.0
} -cleanup {
    destroy .l
} -returnCodes {error} -result {expected integer but got "20.0"}
test button-1.121 {configuration option: "height" for button} -setup {
    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .b
    update
} -body {
    .b configure -height 18
    .b cget -height
} -cleanup {
    destroy .b
} -result {18}
} -result 18
test button-1.122 {configuration option: "height" for button} -setup {
    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .b
    update
} -body {
    .b configure -height 20.0
} -cleanup {
    destroy .b
} -returnCodes {error} -result {expected integer but got "20.0"}
test button-1.123 {configuration option: "height" for checkbutton} -setup {
    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .c
    update
} -body {
    .c configure -height 18
    .c cget -height
} -cleanup {
    destroy .c
} -result {18}
} -result 18
test button-1.124 {configuration option: "height" for checkbutton} -setup {
    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .c
    update
} -body {
    .c configure -height 20.0
} -cleanup {
    destroy .c
} -returnCodes {error} -result {expected integer but got "20.0"}
test button-1.125 {configuration option: "height" for radiobutton} -setup {
    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .r
    update
} -body {
    .r configure -height 18
    .r cget -height
} -cleanup {
    destroy .r
} -result {18}
} -result 18
test button-1.126 {configuration option: "height" for radiobutton} -setup {
    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .r
    update
} -body {
    .r configure -height 20.0
} -cleanup {
1562
1563
1564
1565
1566
1567
1568
1569

1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588

1589
1590
1591
1592
1593
1594
1595
1562
1563
1564
1565
1566
1567
1568

1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587

1588
1589
1590
1591
1592
1593
1594
1595







-
+


















-
+







    pack .c
    update
} -body {
    .c configure -indicatoron yes
    .c cget -indicatoron
} -cleanup {
    destroy .c
} -result {1}
} -result 1
test button-1.160 {configuration option: "indicatoron" for checkbutton} -setup {
    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .c
    update
} -body {
    .c configure -indicatoron no_way
} -cleanup {
    destroy .c
} -returnCodes {error} -result {expected boolean value but got "no_way"}
test button-1.161 {configuration option: "indicatoron" for radiobutton} -setup {
    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .r
    update
} -body {
    .r configure -indicatoron yes
    .r cget -indicatoron
} -cleanup {
    destroy .r
} -result {1}
} -result 1
test button-1.162 {configuration option: "indicatoron" for radiobutton} -setup {
    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .r
    update
} -body {
    .r configure -indicatoron no_way
} -cleanup {
1951
1952
1953
1954
1955
1956
1957
1958

1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978

1979
1980
1981
1982
1983
1984
1985
1951
1952
1953
1954
1955
1956
1957

1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977

1978
1979
1980
1981
1982
1983
1984
1985







-
+



















-
+







    pack .b
    update
} -body {
    .b configure -repeatdelay 100
    .b cget -repeatdelay
} -cleanup {
    destroy .b
} -result {100}
} -result 100
test button-1.200 {configuration option: "repeatdelay" for button} -setup {
    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .b
    update
} -body {
    .b configure -repeatdelay foo
} -cleanup {
    destroy .b
} -returnCodes {error} -result {expected integer but got "foo"}

test button-1.201 {configuration option: "repeatinterval" for button} -setup {
    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .b
    update
} -body {
    .b configure -repeatinterval 100
    .b cget -repeatinterval
} -cleanup {
    destroy .b
} -result {100}
} -result 100
test button-1.202 {configuration option: "repeatinterval" for button} -setup {
    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .b
    update
} -body {
    .b configure -repeatinterval foo
} -cleanup {
2401
2402
2403
2404
2405
2406
2407
2408

2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427

2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446

2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465

2466
2467
2468
2469
2470
2471
2472
2401
2402
2403
2404
2405
2406
2407

2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426

2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445

2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464

2465
2466
2467
2468
2469
2470
2471
2472







-
+


















-
+


















-
+


















-
+







    pack .l
    update
} -body {
    .l configure -underline 5
    .l cget -underline
} -cleanup {
    destroy .l
} -result {5}
} -result 5
test button-1.244 {configuration option: "underline" for label} -setup {
    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .l
    update
} -body {
    .l configure -underline 3p
} -cleanup {
    destroy .l
} -returnCodes {error} -result {expected integer but got "3p"}
test button-1.245 {configuration option: "underline" for button} -setup {
    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .b
    update
} -body {
    .b configure -underline 5
    .b cget -underline
} -cleanup {
    destroy .b
} -result {5}
} -result 5
test button-1.246 {configuration option: "underline" for button} -setup {
    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .b
    update
} -body {
    .b configure -underline 3p
} -cleanup {
    destroy .b
} -returnCodes {error} -result {expected integer but got "3p"}
test button-1.247 {configuration option: "underline" for checkbutton} -setup {
    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .c
    update
} -body {
    .c configure -underline 5
    .c cget -underline
} -cleanup {
    destroy .c
} -result {5}
} -result 5
test button-1.248 {configuration option: "underline" for checkbutton} -setup {
    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .c
    update
} -body {
    .c configure -underline 3p
} -cleanup {
    destroy .c
} -returnCodes {error} -result {expected integer but got "3p"}
test button-1.249 {configuration option: "underline" for radiobutton} -setup {
    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .r
    update
} -body {
    .r configure -underline 5
    .r cget -underline
} -cleanup {
    destroy .r
} -result {5}
} -result 5
test button-1.250 {configuration option: "underline" for radiobutton} -setup {
    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .r
    update
} -body {
    .r configure -underline 3p
} -cleanup {
2510
2511
2512
2513
2514
2515
2516
2517

2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536

2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555

2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574

2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594

2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613

2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632

2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651

2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672

2673
2674
2675
2676
2677
2678
2679
2510
2511
2512
2513
2514
2515
2516

2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535

2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554

2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573

2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593

2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612

2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631

2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650

2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671

2672
2673
2674
2675
2676
2677
2678
2679







-
+


















-
+


















-
+


















-
+



















-
+


















-
+


















-
+


















-
+




















-
+







    pack .l
    update
} -body {
    .l configure -width 402
    .l cget -width
} -cleanup {
    destroy .l
} -result {402}
} -result 402
test button-1.255 {configuration option: "width" for label} -setup {
    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .l
    update
} -body {
    .l configure -width 3p
} -cleanup {
    destroy .l
} -returnCodes {error} -result {expected integer but got "3p"}
test button-1.256 {configuration option: "width" for button} -setup {
    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .b
    update
} -body {
    .b configure -width 402
    .b cget -width
} -cleanup {
    destroy .b
} -result {402}
} -result 402
test button-1.257 {configuration option: "width" for button} -setup {
    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .b
    update
} -body {
    .b configure -width 3p
} -cleanup {
    destroy .b
} -returnCodes {error} -result {expected integer but got "3p"}
test button-1.258 {configuration option: "width" for checkbutton} -setup {
    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .c
    update
} -body {
    .c configure -width 402
    .c cget -width
} -cleanup {
    destroy .c
} -result {402}
} -result 402
test button-1.259 {configuration option: "width" for checkbutton} -setup {
    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .c
    update
} -body {
    .c configure -width 3p
} -cleanup {
    destroy .c
} -returnCodes {error} -result {expected integer but got "3p"}
test button-1.260 {configuration option: "width" for radiobutton} -setup {
    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .r
    update
} -body {
    .r configure -width 402
    .r cget -width
} -cleanup {
    destroy .r
} -result {402}
} -result 402
test button-1.261 {configuration option: "width" for radiobutton} -setup {
    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .r
    update
} -body {
    .r configure -width 3p
} -cleanup {
    destroy .r
} -returnCodes {error} -result {expected integer but got "3p"}

test button-1.262 {configuration option: "wraplength" for label} -setup {
    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .l
    update
} -body {
    .l configure -wraplength 100
    .l cget -wraplength
} -cleanup {
    destroy .l
} -result {100}
} -result 100
test button-1.263 {configuration option: "wraplength" for label} -setup {
    label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .l
    update
} -body {
    .l configure -wraplength 6x
} -cleanup {
    destroy .l
} -returnCodes {error} -result {bad screen distance "6x"}
test button-1.264 {configuration option: "wraplength" for button} -setup {
    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .b
    update
} -body {
    .b configure -wraplength 100
    .b cget -wraplength
} -cleanup {
    destroy .b
} -result {100}
} -result 100
test button-1.265 {configuration option: "wraplength" for button} -setup {
    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .b
    update
} -body {
    .b configure -wraplength 6x
} -cleanup {
    destroy .b
} -returnCodes {error} -result {bad screen distance "6x"}
test button-1.266 {configuration option: "wraplength" for checkbutton} -setup {
    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .c
    update
} -body {
    .c configure -wraplength 100
    .c cget -wraplength
} -cleanup {
    destroy .c
} -result {100}
} -result 100
test button-1.267 {configuration option: "wraplength" for checkbutton} -setup {
    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .c
    update
} -body {
    .c configure -wraplength 6x
} -cleanup {
    destroy .c
} -returnCodes {error} -result {bad screen distance "6x"}
test button-1.268 {configuration option: "wraplength" for radiobutton} -setup {
    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .r
    update
} -body {
    .r configure -wraplength 100
    .r cget -wraplength
} -cleanup {
    destroy .r
} -result {100}
} -result 100
test button-1.269 {configuration option: "wraplength" for radiobutton} -setup {
    radiobutton .r -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .r
    update
} -body {
    .r configure -wraplength 6x
} -cleanup {
    destroy .r
} -returnCodes {error} -result {bad screen distance "6x"}

test button-1.270 {configuration options} -body {
# Additional check to make sure that -selectcolor may be empty in
# checkbox widgets
    checkbutton .c
    .c configure -selectcolor {}
} -cleanup {
    destroy .c
} -result {}

# ex-tests 3.*
test button-2.1 {ButtonCreate - not enough arguments} -body {   
test button-2.1 {ButtonCreate - not enough arguments} -body {
    button
} -returnCodes {error} -result {wrong # args: should be "button pathName ?-option value ...?"}

test button-2.2 {ButtonCreate procedure - setting label class} -body {
    label .x
    winfo class .x
} -cleanup {
2705
2706
2707
2708
2709
2710
2711
2712

2713
2714
2715


2716
2717
2718
2719
2720
2721

2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734

2735
2736
2737
2738

2739
2740

2741
2742
2743
2744
2745
2746
2747
2705
2706
2707
2708
2709
2710
2711

2712
2713


2714
2715
2716
2717
2718
2719
2720

2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733

2734
2735
2736
2737

2738
2739

2740
2741
2742
2743
2744
2745
2746
2747







-
+

-
-
+
+





-
+












-
+



-
+

-
+







    destroy .x
    rename gorp button
} -result {Button}

test button-2.7 {ButtonCreate - bad window name} -body {
    button foo
} -cleanup {
    destroy foo             
    destroy foo
} -returnCodes {error} -result {bad window path name "foo"}
######### test ex 3.8 
test button-2.8 {ButtonCreate procedure - error in default option value} -body { 
######### test ex 3.8
test button-2.8 {ButtonCreate procedure - error in default option value} -body {
    option add *funny.background bogus
    button .funny
} -cleanup {
    option clear
    destroy .funny
} -returnCodes {error} -result {unknown color name "bogus"} 
} -returnCodes {error} -result {unknown color name "bogus"}
test button-2.9 {ButtonCreate procedure - error in default option value} -body {
   option add *funny.background bogus
    catch {button .funny}
    return $errorInfo
} -cleanup {
    option clear
    destroy .funny
} -result {unknown color name "bogus"
    (database entry for "-background" in widget ".funny")
    invoked from within
"button .funny"}

test button-2.10 {ButtonCreate procedure - option error} -body {    
test button-2.10 {ButtonCreate procedure - option error} -body {
    button .x -gorp foo
}  -cleanup {
    destroy .x
} -returnCodes {error} -result {unknown option "-gorp"} 
} -returnCodes {error} -result {unknown option "-gorp"}
test button-2.11 {ButtonCreate procedure - option error} -body {
    catch {button .x -gorp foo} 
    catch {button .x -gorp foo}
    winfo exists .x
}  -cleanup {
    destroy .x
} -result 0
######### ex 3.10
test button-2.12 {ButtonCreate procedure - return value} -body {
    set x [button .abcd]
2784
2785
2786
2787
2788
2789
2790
2791

2792
2793
2794
2795
2796
2797

2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810

2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823

2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837

2838
2839
2840
2841
2842
2843

2844
2845
2846
2847
2848
2849
2850
2784
2785
2786
2787
2788
2789
2790

2791
2792
2793
2794
2795
2796

2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809

2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822

2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836

2837
2838
2839
2840
2841
2842

2843
2844
2845
2846
2847
2848
2849
2850







-
+





-
+












-
+












-
+













-
+





-
+








#ex 4.7
test button-3.6 {ButtonWidgetCmd procedure, "cget" option} -body {
    label .l
    .l cget -disabledforeground
} -cleanup {
    destroy .l
} -returnCodes {ok} -match {glob} -result {*} 
} -returnCodes {ok} -match {glob} -result {*}
test button-3.7 {ButtonWidgetCmd procedure, "cget" option} -body {
    button .b
    .b cget -disabledforeground
} -cleanup {
    destroy .b
} -returnCodes {ok} -match {glob} -result {*} 
} -returnCodes {ok} -match {glob} -result {*}
test button-3.8 {ButtonWidgetCmd procedure, "cget" option} -body {
    button .b
    .b cget -variable
} -cleanup {
    destroy .b
} -returnCodes {error} -result {unknown option "-variable"}

test button-3.9 {ButtonWidgetCmd procedure, "cget" option} -body {
    checkbutton .c
    .c cget -variable
} -cleanup {
    destroy .c
} -returnCodes {ok} -match {glob} -result {*} 
} -returnCodes {ok} -match {glob} -result {*}
test button-3.10 {ButtonWidgetCmd procedure, "cget" option} -body {
    checkbutton .c
    .c cget -value
} -cleanup {
    destroy .c
} -returnCodes {error} -result {unknown option "-value"}

test button-3.11 {ButtonWidgetCmd procedure, "cget" option} -body {
    radiobutton .r
    .r cget -value
} -cleanup {
    destroy .r
} -returnCodes {ok} -match {glob} -result {*} 
} -returnCodes {ok} -match {glob} -result {*}
test button-3.12 {ButtonWidgetCmd procedure, "cget" option} -body {
    radiobutton .r
    .r cget -onvalue
} -cleanup {
    destroy .r
} -returnCodes {error} -result {unknown option "-onvalue"}

# ex 4.6
test button-3.13 {ButtonWidgetCmd procedure, "configure" option} -body {
    button .b -highlightthickness 3
    lindex [.b configure -highlightthickness] 4
} -cleanup {
    destroy .b
}  -result {3}
}  -result 3
test button-3.14 {ButtonWidgetCmd procedure, "configure" option} -body {
    checkbutton .c
    llength [.c configure]
} -cleanup {
    destroy .c
} -result {41} 
} -result 41
test button-3.15 {ButtonWidgetCmd procedure, "configure" option} -body {
    button .b
    .b configure -gorp
} -cleanup {
    destroy .b
} -returnCodes {error} -result {unknown option "-gorp"}
test button-3.16 {ButtonWidgetCmd procedure, "configure" option} -setup {
2885
2886
2887
2888
2889
2890
2891
2892

2893
2894
2895
2896
2897
2898
2899
2900

2901
2902
2903
2904
2905
2906
2907
2908

2909
2910

2911
2912
2913
2914
2915
2916
2917
2918

2919
2920
2921
2922
2923
2924
2925
2885
2886
2887
2888
2889
2890
2891

2892
2893
2894
2895
2896
2897
2898
2899

2900
2901
2902
2903
2904
2905
2906
2907

2908
2909

2910
2911
2912
2913
2914
2915
2916
2917

2918
2919
2920
2921
2922
2923
2924
2925







-
+







-
+







-
+

-
+







-
+







test button-3.21 {ButtonWidgetCmd procedure, "deselect" option} -body {
    checkbutton .c -variable checkvar -onvalue 1 -offvalue 0
    set checkvar 1
    .c d
    return $checkvar
} -cleanup {
    destroy .c
} -result {0} 
} -result 0
test button-3.22 {ButtonWidgetCmd procedure, "deselect" option} -body {
    radiobutton .r -variable radiovar -value red
    set radiovar green
    .r deselect
    return $radiovar
} -cleanup {
    destroy .r
} -result {green} 
} -result {green}
test button-3.23 {ButtonWidgetCmd procedure, "deselect" option} -body {
    radiobutton .r -variable radiovar -value red
    set radiovar red
    .r deselect
    return $radiovar
} -cleanup {
    destroy .r
} -result {} 
} -result {}

test button-3.24 {ButtonWidgetCmd procedure, "deselect" option} -body {  
test button-3.24 {ButtonWidgetCmd procedure, "deselect" option} -body {
    checkbutton .c -variable checkvar -onvalue 1 -offvalue 0
    set checkvar 1
    trace variable checkvar w bogusTrace
    .c deselect
} -cleanup {
    destroy .c
    trace vdelete checkvar w bogusTrace
} -returnCodes {error} -result {can't set "checkvar": trace aborted} 
} -returnCodes {error} -result {can't set "checkvar": trace aborted}
test button-3.25 {ButtonWidgetCmd procedure, "deselect" option} -body {
    checkbutton .c -variable checkvar -onvalue 1 -offvalue 0
    set checkvar 1
    trace variable checkvar w bogusTrace
    catch {.c deselect}
    list $errorInfo $checkvar
} -cleanup {
2933
2934
2935
2936
2937
2938
2939
2940

2941
2942
2943
2944
2945
2946
2947
2933
2934
2935
2936
2937
2938
2939

2940
2941
2942
2943
2944
2945
2946
2947







-
+







    radiobutton .r -variable radiovar -value red
    set radiovar red
    trace variable radiovar w bogusTrace
    .r deselect
} -cleanup {
    destroy .r
    trace vdelete radiovar w bogusTrace
} -match {glob} -returnCodes {error} -result {can't set "radiovar": trace aborted} 
} -match {glob} -returnCodes {error} -result {can't set "radiovar": trace aborted}
test button-3.27 {ButtonWidgetCmd procedure, "deselect" option} -body {
    radiobutton .r -variable radiovar -value red
    set radiovar red
    trace variable radiovar w bogusTrace
    catch {.r deselect}
    list $errorInfo $radiovar
} -cleanup {
2960
2961
2962
2963
2964
2965
2966
2967

2968
2969
2970
2971
2972
2973

2974
2975
2976
2977
2978
2979

2980
2981
2982
2983
2984
2985
2986
2960
2961
2962
2963
2964
2965
2966

2967
2968
2969
2970
2971
2972

2973
2974
2975
2976
2977
2978

2979
2980
2981
2982
2983
2984
2985
2986







-
+





-
+





-
+







} -returnCodes {error} -result {wrong # args: should be ".b flash"}
test button-3.29 {ButtonWidgetCmd procedure, "flash" option} -body {
    label .l
    .l flash
} -cleanup {
    destroy .l
} -returnCodes {error} -result {bad option "flash": must be cget or configure}
test button-3.30 {ButtonWidgetCmd procedure, "flash" option} -body {                    
test button-3.30 {ButtonWidgetCmd procedure, "flash" option} -body {
    button .b
    catch {.b flash}
} -cleanup {
    destroy .b
} -returnCodes {ok} -match {glob} -result {*}
test button-3.31 {ButtonWidgetCmd procedure, "flash" option} -body {                    
test button-3.31 {ButtonWidgetCmd procedure, "flash" option} -body {
    checkbutton .c
    catch {.c flash}
} -cleanup {
    destroy .c
} -returnCodes {ok} -match {glob} -result {*}
test button-3.32 {ButtonWidgetCmd procedure, "flash" option} -body {                    
test button-3.32 {ButtonWidgetCmd procedure, "flash" option} -body {
    radiobutton .r
    catch {.r f}
} -cleanup {
    destroy .r
} -returnCodes {ok} -match {glob} -result {*}

test button-3.33 {ButtonWidgetCmd procedure, "invoke" option} -body {
3056
3057
3058
3059
3060
3061
3062
3063

3064
3065
3066
3067
3068
3069
3070

3071
3072
3073
3074
3075
3076
3077
3078

3079
3080
3081
3082
3083
3084
3085
3056
3057
3058
3059
3060
3061
3062

3063
3064
3065
3066
3067
3068
3069

3070
3071
3072
3073
3074
3075
3076
3077

3078
3079
3080
3081
3082
3083
3084
3085







-
+






-
+







-
+







    set checkvar bogus
    .c s
    return $checkvar
} -cleanup {
    destroy .c
} -result  {lovely}
test button-3.43 {ButtonWidgetCmd procedure, "select" option} -body {
    radiobutton .r -variable radiovar -value red    
    radiobutton .r -variable radiovar -value red
    set radiovar green
    .r select
    return $radiovar
} -cleanup {
    destroy .r
} -result  {red}
test button-3.44 {ButtonWidgetCmd procedure, "select" option} -body { 
test button-3.44 {ButtonWidgetCmd procedure, "select" option} -body {
    radiobutton .r -variable radiovar -value red
    set radiovar yellow
    trace variable radiovar w bogusTrace
    .r select
} -cleanup {
    destroy .r
    trace vdelete radiovar w bogusTrace
} -returnCodes {error} -result {can't set "radiovar": trace aborted} 
} -returnCodes {error} -result {can't set "radiovar": trace aborted}
test button-3.45 {ButtonWidgetCmd procedure, "select" option} -body {
    radiobutton .r -variable radiovar -value red
    set radiovar yellow
    trace variable radiovar w bogusTrace
    catch {.r select}
    list $errorInfo $radiovar
} -cleanup {
3124
3125
3126
3127
3128
3129
3130
3131

3132
3133
3134
3135
3136
3137
3138
3139

3140
3141
3142
3143
3144

3145
3146
3147
3148
3149
3150
3151
3152
3153

3154
3155
3156
3157
3158
3159
3160
3161

3162
3163
3164
3165
3166

3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177

3178
3179
3180
3181
3182
3183
3184

3185
3186
3187

3188
3189
3190
3191
3192
3193
3194
3124
3125
3126
3127
3128
3129
3130

3131
3132
3133
3134
3135
3136
3137
3138

3139
3140
3141
3142
3143

3144
3145
3146
3147
3148
3149
3150
3151
3152

3153
3154
3155
3156
3157
3158
3159
3160

3161
3162
3163
3164
3165

3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176

3177
3178
3179
3180
3181
3182
3183

3184
3185
3186

3187
3188
3189
3190
3191
3192
3193
3194







-
+







-
+




-
+








-
+







-
+




-
+










-
+






-
+


-
+







    lappend result $checkvar
    .c toggle
    lappend result $checkvar
    return $result
} -cleanup {
    destroy .c
} -result {sunshine rain sunshine}
test button-3.51 {ButtonWidgetCmd procedure, "toggle" option} -body {  
test button-3.51 {ButtonWidgetCmd procedure, "toggle" option} -body {
    checkbutton .c -variable checkvar -onvalue xyz -offvalue abc
    set checkvar xyz
    trace variable checkvar w bogusTrace
    .c toggle
} -cleanup {
    destroy .c
    trace vdelete checkvar w bogusTrace
} -returnCodes {error} -result {can't set "checkvar": trace aborted} 
} -returnCodes {error} -result {can't set "checkvar": trace aborted}
test button-3.52 {ButtonWidgetCmd procedure, "toggle" option} -body {
    checkbutton .c -variable checkvar -onvalue xyz -offvalue abc
    set checkvar xyz
    trace variable checkvar w bogusTrace
    catch {.c toggle} 
    catch {.c toggle}
    list $errorInfo $checkvar
} -cleanup {
    trace vdelete checkvar w bogusTrace
    destroy .c
} -match {glob} -result {{*trace aborted
    while executing
*
".c toggle"} abc}
test button-3.53 {ButtonWidgetCmd procedure, "toggle" option} -body {   
test button-3.53 {ButtonWidgetCmd procedure, "toggle" option} -body {
    checkbutton .c -variable checkvar -onvalue xyz -offvalue abc
    set checkvar abc
    trace variable checkvar w bogusTrace
    .c toggle
} -cleanup {
    trace vdelete checkvar w bogusTrace
    destroy .c
} -returnCodes {error} -result {can't set "checkvar": trace aborted} 
} -returnCodes {error} -result {can't set "checkvar": trace aborted}
test button-3.54 {ButtonWidgetCmd procedure, "toggle" option} -body {
    checkbutton .c -variable checkvar -onvalue xyz -offvalue abc
    set checkvar abc
    trace variable checkvar w bogusTrace
    catch {.c toggle} 
    catch {.c toggle}
    list $errorInfo $checkvar
} -cleanup {
    trace vdelete checkvar w bogusTrace
    destroy .c
} -match {glob} -result {{*trace aborted
    while executing
*
".c toggle"} xyz}
test button-3.55 {ButtonWidgetCmd procedure, "toggle" option} -setup {
    unset -nocomplain checkvar
} -body { 
} -body {
    checkbutton .c -variable checkvar -onvalue xyz -offvalue abc
    unset checkvar
    set checkvar(1) 1
    .c toggle
} -cleanup {
    destroy .c
} -returnCodes {error} -result {can't set "checkvar": variable is array} 
} -returnCodes {error} -result {can't set "checkvar": variable is array}
test button-3.56 {ButtonWidgetCmd procedure, "toggle" option} -setup {
    unset -nocomplain checkvar
} -body { 
} -body {
    checkbutton .c -variable checkvar -onvalue xyz -offvalue abc
    unset checkvar
    set checkvar(1) 1
    catch {.c toggle}
    return $errorInfo
} -cleanup {
    destroy .c
3205
3206
3207
3208
3209
3210
3211
3212
3213


3214
3215
3216
3217

3218
3219
3220
3221
3222
3223
3224

3225
3226
3227

3228
3229
3230
3231
3232
3233
3234
3205
3206
3207
3208
3209
3210
3211


3212
3213
3214
3215
3216

3217
3218
3219
3220
3221
3222
3223

3224
3225
3226

3227
3228
3229
3230
3231
3232
3233
3234







-
-
+
+



-
+






-
+


-
+







    button .b1 -image image1
    button .b2 -fg #ff0000 -text "Button 2"
    button .b3 -state active -text "Button 3"
    button .b4 -disabledforeground #0000ff -state disabled -text "Button 4"
    checkbutton .b5 -variable x -text "Checkbutton 5"
    set x 1
    pack .b1 .b2 .b3 .b4 .b5
    update 
    deleteWindows  
    update
    deleteWindows
} -cleanup {
    destroy .b1 .b2 .b3 .b4 .b5
    image delete image1
} -result {} 
} -result {}

test button-5.1 {ConfigureButton - textvariable trace} -body {
    button .b -bd 4 -bg green
    .b configure -bd 7 -bg red -fg bogus
} -cleanup {
    destroy .b
} -returnCodes {error} -result {unknown color name "bogus"} 
} -returnCodes {error} -result {unknown color name "bogus"}
test button-5.2 {ConfigureButton - textvariable trace} -body {
    button .b -bd 4 -bg green
    catch {.b configure -bd 7 -bg red -fg bogus} 
    catch {.b configure -bd 7 -bg red -fg bogus}
    list [.b cget -bd] [.b cget -bg]
} -cleanup {
    destroy .b
} -result {4 green}
test button-5.3 {ConfigureButton - textvariable trace} -body {
    button .b -textvariable x
    set x From-x
3245
3246
3247
3248
3249
3250
3251
3252

3253
3254
3255
3256
3257
3258
3259
3245
3246
3247
3248
3249
3250
3251

3252
3253
3254
3255
3256
3257
3258
3259







-
+







    set y 1
    .c configure -textvariable y
    set x 0
    .c toggle
    return $y
} -cleanup {
    destroy .c
} -result {1}
} -result 1

test button-5.5 {ConfigureButton - image handling} -constraints {
    testImageType
} -setup {
    imageCleanup
    image create test image1
    image create test image2
3267
3268
3269
3270
3271
3272
3273
3274

3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285

3286
3287
3288
3289
3290
3291
3292
3267
3268
3269
3270
3271
3272
3273

3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284

3285
3286
3287
3288
3289
3290
3291
3292







-
+










-
+







    imageCleanup
} -result {image2}

test button-5.6 {ConfigureButton - default value for variable} -body {
    checkbutton .c
    .c cget -variable
} -cleanup {
    destroy .c 
    destroy .c
} -result {c}
test button-5.7 {ConfigureButton - setting selected state from variable} -body {
    set x 0
    set y Shiny
    checkbutton .c -variable x
    .c configure -variable y -onvalue Shiny
    .c toggle
    return $y
} -cleanup {
    destroy .c
} -result {0}
} -result 0
test button-5.8 {ConfigureButton - setting selected state from variable} -setup {
    unset -nocomplain x
} -body {
    checkbutton .c -variable x -offvalue Bogus
    return $x
} -cleanup {
    destroy .c
3301
3302
3303
3304
3305
3306
3307
3308

3309
3310
3311
3312
3313
3314
3315
3301
3302
3303
3304
3305
3306
3307

3308
3309
3310
3311
3312
3313
3314
3315







-
+







    destroy .r
} -result {}

test button-5.10 {ConfigureButton - error in setting variable} -setup {
    unset -nocomplain x
} -body {
    trace variable x w bogusTrace
    radiobutton .r -variable x 
    radiobutton .r -variable x
} -cleanup {
    destroy .r
    trace vdelete x w bogusTrace
} -returnCodes {error} -result {can't set "x": trace aborted}

test button-5.11 {ConfigureButton - bad image name} -body {
    button .b -image bogus
3338
3339
3340
3341
3342
3343
3344
3345

3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358

3359
3360
3361
3362
3363

3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374

3375
3376
3377
3378
3379
3380


3381
3382

3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396

3397
3398
3399

3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417

3418
3419
3420
3421
3422
3423
3424
3425

3426
3427
3428
3429
3430
3431
3432
3338
3339
3340
3341
3342
3343
3344

3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357

3358
3359
3360
3361
3362

3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373

3374
3375
3376
3377
3378


3379
3380
3381

3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395

3396
3397
3398

3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416

3417
3418
3419
3420
3421
3422
3423
3424

3425
3426
3427
3428
3429
3430
3431
3432







-
+












-
+




-
+










-
+




-
-
+
+

-
+













-
+


-
+

















-
+







-
+







    unset -nocomplain x
} -body {
    trace variable x w bogusTrace
    radiobutton .r -text foo -textvariable x
} -cleanup {
    trace vdelete x w bogusTrace
    destroy .r
} -returnCodes {error} -result {can't set "x": trace aborted} 
} -returnCodes {error} -result {can't set "x": trace aborted}
test button-5.15 {ConfigureButton - variable handling} -setup {
    unset -nocomplain x
} -body {
    trace variable x w bogusTrace
    catch {radiobutton .r -text foo -textvariable x}
	return $x
} -cleanup {
    trace vdelete x w bogusTrace
    destroy .r
} -result {foo}

#ex 6.14
test button-5.16 {ConfigureButton - -width option} -body { 
test button-5.16 {ConfigureButton - -width option} -body {
    button .b -text "Button 1"
    .b configure -width 1i
} -cleanup {
    destroy .b
} -returnCodes {error} -result {expected integer but got "1i"} 
} -returnCodes {error} -result {expected integer but got "1i"}
test button-5.17 {ConfigureButton - -width option} -body {
    button .b -text "Button 1"
    catch {.b configure -width 1i}
    return $errorInfo
} -cleanup {
    destroy .b
} -result  {expected integer but got "1i"
    (processing -width option)
    invoked from within
".b configure -width 1i"}
test button-5.18 {ConfigureButton - -height option} -body { 
test button-5.18 {ConfigureButton - -height option} -body {
    button .b -text "Button 1"
    .b configure -height 0.5c
} -cleanup {
    destroy .b
} -returnCodes {error} -result {expected integer but got "0.5c"} 
test button-5.19 {ConfigureButton - -height option} -body { 
} -returnCodes {error} -result {expected integer but got "0.5c"}
test button-5.19 {ConfigureButton - -height option} -body {
    button .b -text "Button 1"
    catch {.b configure -height 0.5c} 
    catch {.b configure -height 0.5c}
    return $errorInfo
} -cleanup {
    destroy .b
} -result {expected integer but got "0.5c"
    (processing -height option)
    invoked from within
".b configure -height 0.5c"}
#ex 6.16
test button-5.20 {ConfigureButton - -width option} -body {
    button .b -bitmap questhead
    .b configure -width abc
} -cleanup {
    destroy .b
} -returnCodes {error} -result  {bad screen distance "abc"} 
} -returnCodes {error} -result  {bad screen distance "abc"}
test button-5.21 {ConfigureButton - -width option} -body {
    button .b -bitmap questhead
    catch {.b configure -width abc} 
    catch {.b configure -width abc}
    return $errorInfo
} -cleanup {
    destroy .b
} -result {bad screen distance "abc"
    (processing -width option)
    invoked from within
".b configure -width abc"}
test button-5.22 {ConfigureButton - -height option} -constraints {
    testImageType
} -setup {
    image create test image1
} -body {
    button .b -image image1
    .b configure -height 0.5x
} -cleanup {
    destroy .b
    image delete image1
} -returnCodes {error} -result {bad screen distance "0.5x"} 
} -returnCodes {error} -result {bad screen distance "0.5x"}
test button-5.23 {ConfigureButton - -height option} -constraints {
    testImageType
} -setup {
    image create test image1
} -body {
#ztestImageType
    button .b -image image1
    catch {.b configure -height 0.5x} 
    catch {.b configure -height 0.5x}
    return $errorInfo
} -cleanup {
    destroy .b
    image delete image1
} -result  {bad screen distance "0.5x"
    (processing -height option)
    invoked from within
3483
3484
3485
3486
3487
3488
3489
3490

3491
3492
3493
3494
3495
3496
3497
3483
3484
3485
3486
3487
3488
3489

3490
3491
3492
3493
3494
3495
3496
3497







-
+







    .b configure -text "Button 1"
    set old [winfo reqwidth .b]
    .b configure -text "Much longer text"
    set new [winfo reqwidth .b]
    expr {$old == $new}
} -cleanup {
    destroy .b
} -result {0}
} -result 0

test button-6.1 {ButtonEventProc procedure} -body {
    button .b -text "Test Button" -command {
	   destroy .b
	   set x [list [winfo exists .b] [info commands .b]]
}
    .b invoke
3519
3520
3521
3522
3523
3524
3525
3526

3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537

3538
3539

3540
3541
3542
3543
3544
3545
3546
3547
3548
3549

3550
3551
3552
3553
3554
3555
3556
3557
3558


3559
3560

3561
3562
3563
3564
3565
3566
3567
3568
3569
3570

3571
3572
3573
3574
3575
3576
3577
3578

3579
3580
3581
3582

3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593

3594
3595
3596
3597
3598
3599
3600
3601
3602

3603
3604
3605
3606
3607
3608
3609
3519
3520
3521
3522
3523
3524
3525

3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536

3537
3538

3539
3540
3541
3542
3543
3544
3545
3546
3547
3548

3549
3550
3551
3552
3553
3554
3555
3556


3557
3558
3559

3560
3561
3562
3563
3564
3565
3566
3567
3568
3569

3570
3571
3572
3573
3574
3575
3576
3577

3578
3579
3580
3581

3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592

3593
3594
3595
3596
3597
3598
3599
3600
3601

3602
3603
3604
3605
3606
3607
3608
3609







-
+










-
+

-
+









-
+







-
-
+
+

-
+









-
+







-
+



-
+










-
+








-
+







    list [info command .b*] [winfo children .]
} -cleanup {
    destroy .b
} -result {{} {}}

test button-8.1 {TkInvokeButton procedure} -setup {
    set x 0
} -body { 
} -body {
    checkbutton .c -variable x
    set result $x
    .c invoke
    lappend result $x
    .c invoke
    lappend result $x
} -cleanup {
    destroy .c
} -result {0 1 0}

test button-8.2 {TkInvokeButton procedure} -setup {     
test button-8.2 {TkInvokeButton procedure} -setup {
    set x 0
} -body { 
} -body {
    checkbutton .c -variable x
    trace variable x w bogusTrace
    .c invoke
} -cleanup {
    destroy .c
    trace vdelete x w bogusTrace
} -returnCodes {error} -result {can't set "x": trace aborted}
test button-8.3 {TkInvokeButton procedure} -setup {
    set x 0
} -body { 
} -body {
    checkbutton .c -variable x
    trace variable x w bogusTrace
    catch {.c invoke}
    return $x
} -cleanup {
    destroy .c
    trace vdelete x w bogusTrace
} -result {1}
test button-8.4 {TkInvokeButton procedure} -setup {   
} -result 1
test button-8.4 {TkInvokeButton procedure} -setup {
    set x 1
} -body { 
} -body {
    checkbutton .c -variable x
    trace variable x w bogusTrace
    .c invoke
} -cleanup {
    destroy .c
    trace vdelete x w bogusTrace
} -returnCodes {error} -result {can't set "x": trace aborted}
test button-8.5 {TkInvokeButton procedure} -setup {
    set x 1
} -body { 
} -body {
    checkbutton .c -variable x
    trace variable x w bogusTrace
    catch {.c invoke}
    return $x
} -cleanup {
    destroy .c
    trace vdelete x w bogusTrace
} -result {0}
} -result 0

test button-8.6 {TkInvokeButton procedure} -setup {
    set x 0
} -body { 
} -body {
    radiobutton .r -variable x -value red
    set result $x
    .r invoke
    lappend result $x
    .r invoke
    lappend result $x
} -cleanup {
    destroy .r
} -result {0 red red}

test button-8.7 {TkInvokeButton procedure} -body {  
test button-8.7 {TkInvokeButton procedure} -body {
    radiobutton .r -variable x -value red
    set x green
    trace variable x w bogusTrace
    .r invoke
} -cleanup {
    destroy .r
    trace vdelete x w bogusTrace
} -returnCodes {error} -result {can't set "x": trace aborted}
test button-8.8 {TkInvokeButton procedure} -body { 
test button-8.8 {TkInvokeButton procedure} -body {
    radiobutton .r -variable x -value red
    set x green
    trace variable x w bogusTrace
    catch {.r invoke}
    list $errorInfo $x
} -cleanup {
    destroy .r
3661
3662
3663
3664
3665
3666
3667
3668

3669
3670
3671
3672
3673
3674
3675
3676
3677
3678

3679
3680
3681
3682
3683
3684
3685
3686
3687
3688

3689
3690
3691
3692
3693
3694
3695
3696
3697
3698

3699
3700
3701
3702
3703
3704
3705
3706
3707
3708

3709
3710
3711
3712
3713
3714
3715
3716
3717
3718

3719
3720
3721
3722
3723
3724
3725
3661
3662
3663
3664
3665
3666
3667

3668
3669
3670
3671
3672
3673
3674
3675
3676
3677

3678
3679
3680
3681
3682
3683
3684
3685
3686
3687

3688
3689
3690
3691
3692
3693
3694
3695
3696
3697

3698
3699
3700
3701
3702
3703
3704
3705
3706
3707

3708
3709
3710
3711
3712
3713
3714
3715
3716
3717

3718
3719
3720
3721
3722
3723
3724
3725







-
+









-
+









-
+









-
+









-
+









-
+







    set x 0
    checkbutton .c -variable x
    set x 44
    .c toggle
    return $x
} -cleanup {
    destroy .c
} -result {1}
} -result 1
test button-9.3 {ButtonVarProc procedure} -setup {
    set x 1
} -body {
    checkbutton .c -variable x
    set x 44
    .c toggle
    return $x
} -cleanup {
    destroy .c
} -result {1}
} -result 1
test button-9.4 {ButtonVarProc procedure} -setup {
    set x 0
} -body {
    checkbutton .c -variable x
    set x 1
    .c toggle
    return $x
} -cleanup {
    destroy .c
} -result {0}
} -result 0
test button-9.5 {ButtonVarProc procedure} -setup {
    set x 1
} -body {
    checkbutton .c -variable x
    set x 1
    .c toggle
    return $x
} -cleanup {
    destroy .c
} -result {0}
} -result 0
test button-9.6 {ButtonVarProc procedure} -setup {
    set x 0
} -body {
    checkbutton .c -variable x
    set x 0
    .c toggle
    return $x
} -cleanup {
    destroy .c
} -result {1}
} -result 1
test button-9.7 {ButtonVarProc procedure} -setup {
    set x 1
} -body {
    checkbutton .c -variable x
    set x 0
    .c toggle
    return $x
} -cleanup {
    destroy .c
} -result {1}
} -result 1
test button-9.8 {ButtonVarProc procedure, can't read variable} -setup {
# This test does nothing but produce a core dump if there's a prbblem.
    unset -nocomplain a
} -body {
    checkbutton .c -variable a
    unset a
    set a(32) 0
3747
3748
3749
3750
3751
3752
3753
3754

3755
3756
3757

3758
3759
3760
3761
3762
3763
3764
3747
3748
3749
3750
3751
3752
3753

3754
3755
3756

3757
3758
3759
3760
3761
3762
3763
3764







-
+


-
+







    .b configure -textvariable x
    set old [winfo reqwidth .b]
    set x New
    set new [winfo reqwidth .b]
    expr {$old == $new}
} -cleanup {
    destroy .b
} -result {0}
} -result 0

test button-11.1 {ButtonImageProc procedure} -constraints {
    testImageType 
    testImageType
} -setup {
    label .l -highlightthickness 0 -font {Helvetica -12 bold}
    image create test image1
} -body {
    .l configure -image image1 -padx 0 -pady 0 -bd 0
    pack .l
    set result "[winfo reqwidth .l] [winfo reqheight .l]"
3776
3777
3778
3779
3780
3781
3782
3783

3784
3785
3786
3787
3788
3789
3790
3791















































































3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807






3808
3809
3810

3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822

3823
3824
3825
3826
3827




3828
3829
3830

3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842

3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862

3863
3864
3865
3866



3867
3868
3869

3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881

3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959

3960
3961
3962
3963
3964
3965
3966
3776
3777
3778
3779
3780
3781
3782

3783
3784
3785
3786
3787
3788
3789
3790

3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880





3881
3882
3883
3884
3885
3886
3887
3888

3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900

3901
3902




3903
3904
3905
3906
3907
3908

3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920

3921









3922










3923




3924
3925
3926
3927
3928

3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940

3941




























































3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958

3959
3960
3961
3962
3963
3964
3965
3966







-
+







-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+











-
-
-
-
-
+
+
+
+
+
+


-
+











-
+

-
-
-
-
+
+
+
+


-
+











-
+
-
-
-
-
-
-
-
-
-

-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
+
+
+


-
+











-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

















-
+







    destroy .b

    set res1 [list [winfo children .] [interp hidden]]
    set res2 [list {} $l]
    expr {$res1 == $res2}
} -cleanup {
    destroy .b
} -result {1}
} -result 1

test button-13.1 {size behavior: label} -setup {
    label .a -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    label .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    label .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    set result {}
} -body {
	.a configure -text Hej 
	.a configure -text Hej
	.b configure -text Hej -width 10 -height 1
	.c configure -text "" -width 10 -height 1

# With -width, width should not be affected by text change
	lappend result [expr {[winfo reqwidth .b] == [winfo reqwidth .c]}]
# With -height, height should not be affected by text change
	lappend result [expr {[winfo reqheight .b] == [winfo reqheight .c]}]
# A one line text should be as high as -height 1
	lappend result [expr {[winfo reqheight .a] == [winfo reqheight .b]}]
} -cleanup {
    destroy .a .b .c
} -result {1 1 1}
test button-13.2 {size behavior: label} -setup {
    label .a -borderwidth 2 -highlightthickness 2 -font {Arial 20}
    label .b -borderwidth 2 -highlightthickness 2 -font {Arial 20}
    label .c -borderwidth 2 -highlightthickness 2 -font {Arial 20}
    set result {}
} -body {
	.a configure -text Hej
	.b configure -text Hej -width 10 -height 1
	.c configure -text "" -width 10 -height 1

# With -width, width should not be affected by text change
	lappend result [expr {[winfo reqwidth .b] == [winfo reqwidth .c]}]
# With -height, height should not be affected by text change
	lappend result [expr {[winfo reqheight .b] == [winfo reqheight .c]}]
# A one line text should be as high as -height 1
	lappend result [expr {[winfo reqheight .a] == [winfo reqheight .b]}]
} -cleanup {
    destroy .a .b .c
} -result {1 1 1}

test button-13.3 {size behavior: button} -setup {
    button .a -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    button .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    set result {}
} -body {
	.a configure -text Hej
	.b configure -text Hej -width 10 -height 1
	.c configure -text "" -width 10 -height 1

# With -width, width should not be affected by text change
	lappend result [expr {[winfo reqwidth .b] == [winfo reqwidth .c]}]
# With -height, height should not be affected by text change
	lappend result [expr {[winfo reqheight .b] == [winfo reqheight .c]}]
# A one line text should be as high as -height 1
	lappend result [expr {[winfo reqheight .a] == [winfo reqheight .b]}]
} -cleanup {
    destroy .a .b .c
} -result {1 1 1}
test button-13.4 {size behavior: button} -setup {
    button .a -borderwidth 2 -highlightthickness 2 -font {Arial 20}
    button .b -borderwidth 2 -highlightthickness 2 -font {Arial 20}
    button .c -borderwidth 2 -highlightthickness 2 -font {Arial 20}
    set result {}
} -body {
	.a configure -text Hej
	.b configure -text Hej -width 10 -height 1
	.c configure -text "" -width 10 -height 1

# With -width, width should not be affected by text change
	lappend result [expr {[winfo reqwidth .b] == [winfo reqwidth .c]}]
# With -height, height should not be affected by text change
	lappend result [expr {[winfo reqheight .b] == [winfo reqheight .c]}]
# A one line text should be as high as -height 1
	lappend result [expr {[winfo reqheight .a] == [winfo reqheight .b]}]
} -cleanup {
    destroy .a .b .c
} -result {1 1 1}

test button-13.5 {size behavior: radiobutton} -setup {
    radiobutton .a -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    radiobutton .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    radiobutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    set result {}
} -body {
	.a configure -text Hej
	.b configure -text Hej -width 10 -height 1
	.c configure -text "" -width 10 -height 1

# With -width, width should not be affected by text change
	lappend result [expr {[winfo reqwidth .b] == [winfo reqwidth .c]}]
# With -height, height should not be affected by text change
	lappend result [expr {[winfo reqheight .b] == [winfo reqheight .c]}]
# A one line text should be as high as -height 1
	lappend result [expr {[winfo reqheight .a] == [winfo reqheight .b]}]
} -cleanup {
    destroy .a .b .c
} -result {1 1 1} 
test button-13.2 {size behavior: label} -setup {
    label .a -borderwidth 2 -highlightthickness 2 -font {Arial 20}
    label .b -borderwidth 2 -highlightthickness 2 -font {Arial 20}
    label .c -borderwidth 2 -highlightthickness 2 -font {Arial 20}
} -result {1 1 1}

test button-13.6 {size behavior: radiobutton} -setup {
    radiobutton .a -borderwidth 2 -highlightthickness 2 -font {Arial 20}
    radiobutton .b -borderwidth 2 -highlightthickness 2 -font {Arial 20}
    radiobutton .c -borderwidth 2 -highlightthickness 2 -font {Arial 20}
    set result {}
} -body {
	.a configure -text Hej 
	.a configure -text Hej
	.b configure -text Hej -width 10 -height 1
	.c configure -text "" -width 10 -height 1

# With -width, width should not be affected by text change
	lappend result [expr {[winfo reqwidth .b] == [winfo reqwidth .c]}]
# With -height, height should not be affected by text change
	lappend result [expr {[winfo reqheight .b] == [winfo reqheight .c]}]
# A one line text should be as high as -height 1
	lappend result [expr {[winfo reqheight .a] == [winfo reqheight .b]}]
} -cleanup {
    destroy .a .b .c
} -result {1 1 1} 
} -result {1 1 1}

test button-13.3 {size behavior: button} -setup {
    button .a -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    button .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    button .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
test button-13.7 {size behavior: checkbutton} -setup {
    checkbutton .a -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    checkbutton .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    set result {}
} -body {
	.a configure -text Hej 
	.a configure -text Hej
	.b configure -text Hej -width 10 -height 1
	.c configure -text "" -width 10 -height 1

# With -width, width should not be affected by text change
	lappend result [expr {[winfo reqwidth .b] == [winfo reqwidth .c]}]
# With -height, height should not be affected by text change
	lappend result [expr {[winfo reqheight .b] == [winfo reqheight .c]}]
# A one line text should be as high as -height 1
	lappend result [expr {[winfo reqheight .a] == [winfo reqheight .b]}]
} -cleanup {
    destroy .a .b .c
} -result {1 1 1} 
} -result {1 1 1}
test button-13.4 {size behavior: button} -setup {
    button .a -borderwidth 2 -highlightthickness 2 -font {Arial 20}
    button .b -borderwidth 2 -highlightthickness 2 -font {Arial 20}
    button .c -borderwidth 2 -highlightthickness 2 -font {Arial 20}
    set result {}
} -body {
	.a configure -text Hej 
	.b configure -text Hej -width 10 -height 1
	.c configure -text "" -width 10 -height 1

# With -width, width should not be affected by text change
	lappend result [expr {[winfo reqwidth .b] == [winfo reqwidth .c]}]
# With -height, height should not be affected by text change
	lappend result [expr {[winfo reqheight .b] == [winfo reqheight .c]}]
# A one line text should be as high as -height 1
	lappend result [expr {[winfo reqheight .a] == [winfo reqheight .b]}]
} -cleanup {
    destroy .a .b .c
} -result {1 1 1} 

test button-13.8 {size behavior: checkbutton} -setup {
test button-13.5 {size behavior: radiobutton} -setup {
    radiobutton .a -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    radiobutton .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    radiobutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    checkbutton .a -borderwidth 2 -highlightthickness 2 -font {Arial 20}
    checkbutton .b -borderwidth 2 -highlightthickness 2 -font {Arial 20}
    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Arial 20}
    set result {}
} -body {
	.a configure -text Hej 
	.a configure -text Hej
	.b configure -text Hej -width 10 -height 1
	.c configure -text "" -width 10 -height 1

# With -width, width should not be affected by text change
	lappend result [expr {[winfo reqwidth .b] == [winfo reqwidth .c]}]
# With -height, height should not be affected by text change
	lappend result [expr {[winfo reqheight .b] == [winfo reqheight .c]}]
# A one line text should be as high as -height 1
	lappend result [expr {[winfo reqheight .a] == [winfo reqheight .b]}]
} -cleanup {
    destroy .a .b .c
} -result {1 1 1} 
} -result {1 1 1}

test button-13.6 {size behavior: radiobutton} -setup {
    radiobutton .a -borderwidth 2 -highlightthickness 2 -font {Arial 20}
    radiobutton .b -borderwidth 2 -highlightthickness 2 -font {Arial 20}
    radiobutton .c -borderwidth 2 -highlightthickness 2 -font {Arial 20}
    set result {}
} -body {
	.a configure -text Hej 
	.b configure -text Hej -width 10 -height 1
	.c configure -text "" -width 10 -height 1

# With -width, width should not be affected by text change
	lappend result [expr {[winfo reqwidth .b] == [winfo reqwidth .c]}]
# With -height, height should not be affected by text change
	lappend result [expr {[winfo reqheight .b] == [winfo reqheight .c]}]
# A one line text should be as high as -height 1
	lappend result [expr {[winfo reqheight .a] == [winfo reqheight .b]}]
} -cleanup {
    destroy .a .b .c
} -result {1 1 1} 

test button-13.7 {size behavior: checkbutton} -setup {
    checkbutton .a -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    checkbutton .b -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    set result {}
} -body {
	.a configure -text Hej 
	.b configure -text Hej -width 10 -height 1
	.c configure -text "" -width 10 -height 1

# With -width, width should not be affected by text change
	lappend result [expr {[winfo reqwidth .b] == [winfo reqwidth .c]}]
# With -height, height should not be affected by text change
	lappend result [expr {[winfo reqheight .b] == [winfo reqheight .c]}]
# A one line text should be as high as -height 1
	lappend result [expr {[winfo reqheight .a] == [winfo reqheight .b]}]
} -cleanup {
    destroy .a .b .c
} -result {1 1 1} 

test button-13.8 {size behavior: checkbutton} -setup {
    checkbutton .a -borderwidth 2 -highlightthickness 2 -font {Arial 20}
    checkbutton .b -borderwidth 2 -highlightthickness 2 -font {Arial 20}
    checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Arial 20}
    set result {}
} -body {
	.a configure -text Hej 
	.b configure -text Hej -width 10 -height 1
	.c configure -text "" -width 10 -height 1

# With -width, width should not be affected by text change
	lappend result [expr {[winfo reqwidth .b] == [winfo reqwidth .c]}]
# With -height, height should not be affected by text change
	lappend result [expr {[winfo reqheight .b] == [winfo reqheight .c]}]
# A one line text should be as high as -height 1
	lappend result [expr {[winfo reqheight .a] == [winfo reqheight .b]}]
} -cleanup {
    destroy .a .b .c
} -result {1 1 1} 

test button-14.1 {bug fix: [011706ec42] tk::ButtonInvoke unsafe wrt widget destruction} -body {
    proc destroy_button {} {
        if {[winfo exists .top.b]} {
            destroy .top.b
        }
    }
    toplevel .top
    button .top.b -text Foo -command destroy_button
    bind .top.b <space> destroy_button
    pack .top.b
    focus -force .top.b
    update
    event generate .top.b <space>
    update  ; # shall not trigger error  invalid command name ".top.b"
} -cleanup {
    destroy .top.b .top
} -result {} 
} -result {}

test button-15.1 {Bug [5d991b822e]} {
    # Want this not to segfault
    set var INIT
    button .b -textvariable var
    trace add variable var unset {apply {args {
	.b configure -textvariable {}
Changes to tests/canvImg.test.
1
2
3
4
5
6
7



8
9
10
11
12
13
14
1
2
3
4



5
6
7
8
9
10
11
12
13
14




-
-
-
+
+
+







# This file is a Tcl script to test out the procedures in tkCanvImg.c,
# which implement canvas "image" items.  It is organized in the standard
# fashion for Tcl tests.
#
# Copyright (c) 1994 The Regents of the University of California.
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1994 The Regents of the University of California.
# Copyright © 1994-1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
namespace import ::tcltest::*
eval tcltest::configure $argv
tcltest::loadTestedCommands
imageInit
170
171
172
173
174
175
176
177

178
179
180
181
182
183
184
170
171
172
173
174
175
176

177
178
179
180
181
182
183
184







-
+







    .c itemconfigure i1 -image foo2
    update idletasks
    update
    # On MacOS we need to wait for the test image display procedure to run.
    while {"timed out" ni $y && [lindex $y end 1] ne "display"} {
        vwait y
    }
    after cancel timer
    after cancel $timer
    list $x $y [.c bbox i1]
} -cleanup {
    .c delete all
    image delete foo
    image delete foo2
} -result {{{foo free}} {{foo2 get} {foo2 display 0 0 80 60}} {50 100 130 160}}
test canvImg-4.3 {ConfiugreImage procedure} -constraints testImageType -setup {
318
319
320
321
322
323
324
325

326
327
328
329
330
331
332
333
334
335
336
337
338

339
340
341
342
343
344
345
346
347
348
349
350
351

352
353
354
355
356
357
358
318
319
320
321
322
323
324

325
326
327
328
329
330
331
332
333
334
335
336
337

338
339
340
341
342
343
344
345
346
347
348
349
350

351
352
353
354
355
356
357
358







-
+












-
+












-
+







    .c create image 20 30 -image foo -tags i1 -anchor s
    .c bbox i1
} -cleanup {
    .c delete all
    imageCleanup
} -result {5 15 35 30}
test canvImg-6.10 {ComputeImageBbox procedure} -constraints {
    testImageType 
    testImageType
} -setup {
    image create test foo
    .c delete all
} -body {
    .c delete all
    .c create image 20 30 -image foo -tags i1 -anchor sw
    .c bbox i1
} -cleanup {
    .c delete all
    image delete foo
} -result {20 15 50 30}
test canvImg-6.11 {ComputeImageBbox procedure} -constraints {
    testImageType 
    testImageType
} -setup {
    image create test foo
    .c delete all
} -body {
    .c delete all
    .c create image 20 30 -image foo -tags i1 -anchor w
    .c bbox i1
} -cleanup {
    .c delete all
    image delete foo
} -result {20 23 50 38}
test canvImg-6.12 {ComputeImageBbox procedure} -constraints {
	testImageType 
	testImageType
} -setup {
    image create test foo
    .c delete all
} -body {
    .c delete all
    .c create image 20 30 -image foo -tags i1 -anchor center
    .c bbox i1
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753

754
755
756
757
758
759
760
761
762
763
764
765

766
767
768
769
770
771
772
773
774

775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793

794
795

796
797
798

799
800
801
802
803
804
805
806
807
808
809
810


811
812
813
814
815
816


817
818
819
820
821
822
823
824
825
723
724
725
726
727
728
729






730
731
732
733
734
735
736
737
738
739
740
741

742
743
744
745

746
747
748
749
750
751
752
753
754
755
756
757

758
759
760
761
762
763
764
765
766

767
768
769
770
771
772
773
774
775
776
777
778
779
780






781
782

783
784
785

786
787
788
789
790
791
792
793

794
795


796
797
798
799
800
801


802
803
804
805
806
807
808
809
810
811
812







-
-
-
-
-
-












-




-
+











-
+








-
+













-
-
-
-
-
-
+

-
+


-
+







-


-
-
+
+




-
-
+
+









    .c scale image 25 0 2.0 1.5
    .c bbox image
} -cleanup {
	.c delete all
	image delete foo
} -result {75 150 105 165}

if {[tk windowingsystem] == "aqua" && $tcl_platform(osVersion) > 18} {
    # Aqua >= 10.14 will redraw the entire image.
    set result_10_1 {{foo display 0 0 30 15}}
} else {
    set result_10_1 {{foo display 2 4 6 8}} 
}
test canvImg-10.1 {TranslateImage procedure} -constraints testImageType -setup {
    .c delete all
    update
} -body {
    image create test foo -variable x
    .c create image 50 100 -image foo -tags image -anchor nw
    update
    set x {}
    set timer [after 500 {lappend x "timed out"}]
    foo changed 2 4 6 8 30 15
    vwait x
    after cancel $timer
    update
    return $x
} -cleanup {
    .c delete all
    image delete foo
} -result $result_10_1
} -result {{foo display 2 4 6 8}}

test canvImg-11.1 {TranslateImage procedure} -constraints testImageType -setup {
    .c delete all
    update
} -body {
    image create test foo -variable x
    .c create image 50 100 -image foo -tags image -anchor nw
    update
    set x {}
    set timer [after 500 {lappend x "timed out"}]
    foo changed 2 4 6 8 40 50
        vwait x
    vwait x
    after cancel $timer
    update
    return $x
} -cleanup {
    .c delete all
    image delete foo
} -result {{foo display 0 0 40 50}}
test canvImg-11.2 {ImageChangedProc procedure} -constraints {
	testImageType 
	testImageType
} -setup {
    .c delete all
} -body {
    image create test foo -variable x
    .c create image 50 100 -image foo -tags image -anchor center
    update
    set x {}
    foo changed 0 0 0 0 40 50
    .c bbox image
} -cleanup {
	.c delete all
	image delete foo
} -result {30 75 70 125}
if {[tk windowingsystem] == "aqua" && $tcl_platform(osVersion) > 18} {
    # Aqua >= 10.14 will redraw the entire image.
    set result_11_3 {{foo2 display 0 0 80 60}}
} else {
    set result_11_3 {{foo2 display 0 0 20 40}} 
}

test canvImg-11.3 {ImageChangedProc procedure} -constraints {
	testImageType 
	testImageType
} -setup {
    .c delete all
    update
    update idletasks
} -body {
    image create test foo -variable x
    image create test foo2 -variable z
    foo changed 0 0 0 0 40 50
    foo2 changed 0 0 0 0 80 60
    .c create image 50 100 -image foo -tags image -anchor nw
    .c create image 70 110 -image foo2 -anchor nw
    update
    set z {}
    set timer [after 500 {lappend z "timed out"}]
    image create test foo -variable x
    vwait x
    image delete foo
    vwait z
    after cancel $timer
    return $z
} -cleanup {
    .c delete all
    image delete foo foo2
} -result $result_11_3
    image delete foo2
} -result {{foo2 display 0 0 80 60}}

# cleanup
imageFinish
cleanupTests
return

# Local variables:
# mode: tcl
# End:
Changes to tests/canvMoveto.test.
1
2
3
4
5
6



7
8
9

10
11
12
13
14
15
16
1
2
3



4
5
6
7
8

9
10
11
12
13
14
15
16



-
-
-
+
+
+


-
+







# This file is a Tcl script to test out the canvas "moveto" command. It is
# derived from canvRect.test.
#
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright (c) 2004 Neil McKay.
# Copyright © 1994-1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# Copyright © 2004 Neil McKay.
# All rights reserved.

package require tcltest 2.1
package require tcltest 2.2
eval tcltest::configure $argv
tcltest::loadTestedCommands

canvas .c -width 400 -height 300 -bd 2 -relief sunken
.c create rectangle 20 20 80 80 -tag {test rect1}
.c create rectangle 40 40 90 100 -tag {test rect2}

29
30
31
32
33
34
35
36

37
38
39
40
41
42
43
29
30
31
32
33
34
35

36
37
38
39
40
41
42
43







-
+







test canvMoveto-1.5 {Bad args handling for "moveto" command} -body {
    .c moveto test 12 20 -anchor
} -returnCodes error -result {wrong # args: should be ".c moveto tagOrId x y"}

test canvMoveto-2.1 {Canvas "moveto" command coordinates} {
    .c moveto test 200 150
    .c bbox test
} {200 150 272 232} 
} {200 150 272 232}
test canvMoveto-2.2 {Canvas "moveto" command, blank y coordinate} {
    .c moveto test 200 150
    .c moveto test 150 {}
    .c bbox test
} {150 150 222 232}
test canvMoveto-2.3 {Canvas "moveto" command, blank x coordinate} {
    .c moveto test 200 150
Changes to tests/canvPs.test.
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

23
24
25
26
27


28
29
30
31
32

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

52
53
54
55
56
57
58

59
60

61
62
63
64
65

66
67
68
69
70
71
72
1
2
3
4


5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

22
23
24
25


26
27
28
29
30
31

32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

51
52
53
54
55
56
57

58
59

60
61
62
63
64

65
66
67
68
69
70
71
72




-
-
+
+















-
+



-
-
+
+




-
+


















-
+






-
+

-
+




-
+







# This file is a Tcl script to test out procedures to write postscript
# for canvases to files and channels. It exercises the procedure
# TkCanvPostscriptCmd in generic/tkCanvPs.c
#
# Copyright (c) 1995 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1995 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
namespace import ::tcltest::*
eval tcltest::configure $argv
tcltest::loadTestedCommands
imageInit

# canvas used in 1.* and 2.* test cases
canvas .c -width 400 -height 300 -bd 2 -relief sunken
.c create rectangle 20 20 80 80 -fill red
pack .c
update

test canvPs-1.1 {test writing to a file} -constraints {
    unixOrPc
    unixOrWin
} -setup {
    set foo [makeFile {} foo.ps]
} -body {
    .c postscript -file $foo
    file exists $foo
    set res [.c postscript -file $foo]
    lappend res [file exists $foo]
} -cleanup {
    removeFile foo.ps
} -result 1
test canvPs-1.2 {test writing to a file, idempotency} -constraints {
    unixOrPc
    unixOrWin
} -setup {
    set foo [makeFile {} foo.ps]
    set bar [makeFile {} bar.ps]
} -body {
    .c postscript -file $foo
    .c postscript -file $bar
    set status ok
    if {[file size $bar] != [file size $foo]} {
	set status broken
    }
    set status
} -cleanup {
    removeFile foo.ps
    removeFile bar.ps
} -result ok


test canvPs-2.1 {test writing to a channel} -constraints {
    unixOrPc
    unixOrWin
} -setup {
    set foo [makeFile {} foo.ps]
    file delete $foo
} -body {
    set chan [open $foo w]
    fconfigure $chan -translation lf
    .c postscript -channel $chan
    set res [.c postscript -channel $chan]
    close $chan
    file exists $foo
    lappend res [file exists $foo]
} -cleanup {
    removeFile foo.ps
} -result 1
test canvPs-2.2 {test writing to channel, idempotency} -constraints {
    unixOrPc
    unixOrWin
} -setup {
    set foo [makeFile {} foo.ps]
    set bar [makeFile {} bar.ps]
    file delete $foo
    file delete $bar
} -body {
    set c1 [open $foo w]
154
155
156
157
158
159
160
161

162
163
164
165
166
167
168
169
170
171
172
173
174
175

176
177
178
179
180
181
182
154
155
156
157
158
159
160

161
162
163
164
165
166
167
168
169
170
171
172
173
174

175
176
177
178
179
180
181
182







-
+













-
+







    update
    .c postscript -file $bar
    file exists $bar
} -cleanup {
    destroy .c
    imageCleanup
    removeFile bar.ps
} -result {1}
} -result 1
test canvPs-3.2 {test ps generation with an embedded window not mapped} -setup {
    set bar [makeFile {} bar.ps]
    file delete $bar
} -body {
    pack [canvas .c -width 200 -height 200 -background white]
    entry .c.e -background pink -foreground blue -width 14
    .c.e insert 0 "we gonna be postscripted"
    .c create window 50 180 -anchor nw -window .c.e
    .c postscript -file $bar
    file exists $bar
} -cleanup {
    destroy .c
    removeFile bar.ps
} -result {1}
} -result 1


test canvPs-4.1 {test ps generation with single-point uncolored poly, bug 734498} -body {
    pack [canvas .c]
    .c create poly 10 20 10 20
    .c postscript
} -cleanup {
Changes to tests/canvRect.test.
1
2
3
4
5
6


7
8
9
10
11
12
13
1
2
3
4


5
6
7
8
9
10
11
12
13




-
-
+
+







# This file is a Tcl script to test out the procedures in tkRectOval.c,
# which implement canvas "rectangle" and "oval" items.  It is organized
# in the standard fashion for Tcl tests.
#
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1994-1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
namespace import ::tcltest::*
eval tcltest::configure $argv
tcltest::loadTestedCommands

224
225
226
227
228
229
230
231

232
233
234
235
236
237
238
224
225
226
227
228
229
230

231
232
233
234
235
236
237
238







-
+







	set xId  [.c create rectangle 10 20 30 35 -tags x -fill green]
	set yId [.c create rectangle 15 25 25 30  -tags y -fill red]
    .c itemconfigure y -outline {}
    list [expr {[.c find closest 20 24.9] eq $xId}] \
		 [expr {[.c find closest 20 25.1] eq $yId}] \
	    [expr {[.c find closest 20 29.9] eq $yId}] \
		 [expr {[.c find closest 20 30.1] eq $xId}]
		

} -cleanup {
	.c delete all
} -result {1 1 1 1}
test canvRect-6.3 {RectToPoint procedure} -body {
	set xId  [.c create rectangle 10 20 30 35 -tags x -fill green]
	set yId [.c create rectangle 15 25 25 30  -tags y -fill red]
    .c itemconfigure y -width 1 -outline black
246
247
248
249
250
251
252
253

254
255
256
257
258
259
260
246
247
248
249
250
251
252

253
254
255
256
257
258
259
260







-
+







test canvRect-6.4 {RectToPoint procedure} -body {
	set xId  [.c create rectangle 10 20 30 35 -tags x -fill green]
	set yId [.c create rectangle 15 25 25 30  -tags y -fill red]
    .c itemconfigure  y -width 1 -outline black
    list [expr {[.c find closest 20 24.4] eq $xId}] \
		 [expr {[.c find closest 20 24.6] eq $yId}] \
	    [expr {[.c find closest 20 30.4] eq $yId}] \
		 [expr {[.c find closest 20 30.6] eq $xId}]		
		 [expr {[.c find closest 20 30.6] eq $xId}]
} -cleanup {
	.c delete all
} -result {1 1 1 1}

test canvRect-6.5 {RectToPoint procedure} -body {
	set xId  [.c create rectangle 10 20 30 35 -tags x -fill green]
	set yId [.c create rectangle 15 25 25 30  -tags y -fill red]
271
272
273
274
275
276
277
278

279
280
281
282

283
284

285
286
287
288
289

290
291
292
293
294
295
296
271
272
273
274
275
276
277

278
279
280
281

282
283

284
285
286
287
288

289
290
291
292
293
294
295
296







-
+



-
+

-
+




-
+







	set xId  [.c create rectangle 10 20 30 35 -tags x -fill green]
	set yId [.c create rectangle 15 25 25 30  -tags y -fill red]
	.c itemconfigure x -fill {} -outline black -width 3
	.c itemconfigure y -outline {}
    list [expr {[.c find closest 20 23.2] eq $xId}] \
		 [expr {[.c find closest 20 23.3] eq $yId}] \
	    [expr {[.c find closest 20 31.7] eq $yId}] \
		 [expr {[.c find closest 20 31.8] eq $xId}] 
		 [expr {[.c find closest 20 31.8] eq $xId}]
} -cleanup {
	.c delete all
} -result {1 1 1 1}
		

test canvRect-6.7 {RectToPoint procedure} -body {
	set xId [.c create rectangle 10 20 30 40 -outline {} -fill black]		
	set xId [.c create rectangle 10 20 30 40 -outline {} -fill black]
	set yId [.c create rectangle 40 40 50 50 -outline {} -fill black]
    list [expr {[.c find closest 35 35] eq $xId}] \
		 [expr {[.c find closest 36 36] eq $yId}] \
	    [expr {[.c find closest 37 37] eq $yId}] \
		 [expr {[.c find closest 38 38] eq $yId}] 
		 [expr {[.c find closest 38 38] eq $yId}]
} -cleanup {
	.c delete all
} -result {1 1 1 1}


test canvRect-7.1 {RectToArea procedure} -body {
	set xId  [.c create rectangle 10 20 30 35 -fill green -outline {}]
Changes to tests/canvText.test.
1
2
3
4
5
6


7
8
9
10
11
12



13
14
15
16
17
18
19
1
2
3
4


5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22




-
-
+
+






+
+
+







# This file is a Tcl script to test out the procedures in tkCanvText.c,
# which implement canvas "text" items.  It is organized in the standard
# fashion for Tcl tests.
#
# Copyright (c) 1996-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1996-1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
namespace import ::tcltest::*
eval tcltest::configure $argv
tcltest::loadTestedCommands

testConstraint failsOnUbuntu [expr {![info exists ::env(CI)] || ![string match Linux $::tcl_platform(os)]}]
testConstraint failsOnXQuarz [expr {$tcl_platform(os) ne "Darwin" || [tk windowingsystem] ne "x11" }]

# Canvas used in 1.* - 17.* tests
canvas .c -width 400 -height 300 -bd 2 -relief sunken
pack .c
update

# Item used in 1.*  tests
246
247
248
249
250
251
252
253

254
255
256
257
258
259
260
249
250
251
252
253
254
255

256
257
258
259
260
261
262
263







-
+







} -body {
    .c itemconfig test -text "abcdefghi"
    .c icursor test 6
    .c dchars test 4 end
    .c index test insert
} -cleanup {
	.c delete test
} -result {4}
} -result 4


test canvText-5.1 {ConfigureText procedure: adjust cursor} -body {
    .c create text 10 10 -tag x -fill blue -font "times 40" -stipple gray50 \
	-text "xyz"
    .c delete x
} -result {}
569
570
571
572
573
574
575
576

577
578
579
580
581
582
583
584
585
586

587
588
589
590
591
592
593
572
573
574
575
576
577
578

579
580
581
582
583
584
585
586
587
588

589
590
591
592
593
594
595
596







-
+









-
+







    focus .c
    .c focus test
} -body {
    .c itemconfig test -text "abcdefg"
    .c icursor test 3
    .c insert test 2 "xyz"
    .c index test insert
} -result {6}
} -result 6
test canvText-8.9 {TextInsert procedure: inserting after cursor} -setup {
    .c create text 20 20 -tag test
    focus .c
    .c focus test
} -body {
    .c itemconfig test -text "abcdefg"
    .c icursor test 3
    .c insert test 4 "xyz"
    .c index test insert
} -result {3}
} -result 3

# Item used in 9.* tests
.c create text 20 20 -tag test
test canvText-9.1 {TextInsert procedure: before beginning/after end} -body {
    # Can't test this because GetTextIndex filters out those numbers.
} -result {}
test canvText-9.2 {TextInsert procedure: start > end} -body {
669
670
671
672
673
674
675
676

677
678
679
680
681
682

683
684
685
686
687
688

689
690
691
692
693
694
695
696
697
698

699
700
701
702
703
704
705
672
673
674
675
676
677
678

679
680
681
682
683
684

685
686
687
688
689
690

691
692
693
694
695
696
697
698
699
700

701
702
703
704
705
706
707
708







-
+





-
+





-
+









-
+







    list [.c index test sel.first] [.c index test sel.last]
} -result {2 8}
test canvText-9.13 {TextInsert procedure: move cursor} -body {
    .c itemconfig test -text "abcdefghijk"
    .c icursor test 6
    .c dchars test 2 4
    .c index test insert
} -result {3}
} -result 3
test canvText-9.14 {TextInsert procedure: keep cursor >= first} -body {
    .c itemconfig test -text "abcdefghijk"
    .c icursor test 6
    .c dchars test 2 10
    .c index test insert
} -result {2}
} -result 2
test canvText-9.15 {TextInsert procedure: cursor doesn't move} -body {
    .c itemconfig test -text "abcdefghijk"
    .c icursor test 5
    .c dchars test 7 9
    .c index test insert
} -result {5}
} -result 5
.c delete test


test canvText-10.1 {TextToPoint procedure} -body {
    .c create text 0 0 -tag test
    .c itemconfig test -text 0 -anchor center
    .c index test @0,0
} -cleanup {
	.c delete test
} -result {0}
} -result 0


test canvText-11.1 {TextToArea procedure} -setup {
    .c create text 0 0 -tag test
    focus .c
    .c focus test
} -body {
830
831
832
833
834
835
836
837

838
839
840
841
842
843
844
833
834
835
836
837
838
839

840
841
842
843
844
845
846
847







-
+







} -body {
    .c itemconfig test -text "abcdefghijklmno" -anchor nw
    .c itemconfig -text "abcdefg"
    .c icursor test 3
    .c index test insert
} -cleanup {
    .c delete test
} -result {3}
} -result 3

test canvText-16.1 {GetSelText procedure} -setup {
    .c create text 0 0 -tag test
    focus .c
    .c focus test
} -body {
    .c itemconfig test -text "abcdefghijklmno" -anchor nw
936
937
938
939
940
941
942
943

944
945
946
947
948
949
950
939
940
941
942
943
944
945

946
947
948
949
950
951
952
953







-
+







    set y2 [expr {160 + ($metrics(-linespace) / 2)}]
    lappend results [$c index tbox1 @$x,$y1]
    lappend results [$c index tbox2 @$x,$y2]
} -cleanup {
    destroy .c
} -result {{Yeah } Yeah- 4 4}

test canvText-20.1 {angled text bounding box} -setup {
test canvText-20.1 {angled text bounding box} -constraints {failsOnUbuntu failsOnXQuarz} -setup {
    destroy .c
    canvas .c
    proc transpose {bbox} {
	lassign $bbox a b c d
	list $b $a $d $c
    }
} -body {
959
960
961
962
963
964
965














966
967
968
969
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986







+
+
+
+
+
+
+
+
+
+
+
+
+
+




    list [expr {$bb0 eq $bb2 ? "ok" : "$bb0,$bb2"}] \
	[expr {$bb1 eq $bb3 ? "ok" : "$bb1,$bb3"}] \
	[expr {$bb0 eq [transpose $bb1] ? "ok" : "$bb0,$bb1"}] \
} -cleanup {
    destroy .c
    rename transpose {}
} -result {ok ok ok}

test canvText-20.2 {crash on angled text selection (X11, without xft) - bug 2712f43f6e} -setup {
    destroy .c
    canvas .c -background bisque -selectforeground green2
    grid .c
    set id [.c create text 50 150 -anchor w -text "Angled text" \
	    -angle 30 -font {Helvetica 32} -fill darkblue]
} -body {
    .c select clear
    .c select from $id 0
    .c select to $id 8 ; update    ;  # used to crash on X11 (--disable-xft build only)
} -cleanup {
    destroy .c
} -result {}

# cleanup
cleanupTests
return
Changes to tests/canvWind.test.
1
2
3
4
5
6


7
8
9
10
11
12
13
1
2
3
4


5
6
7
8
9
10
11
12
13




-
-
+
+







# This file is a Tcl script to test out the procedures in tkCanvWind.c,
# which implement canvas "window" items.  It is organized in the standard
# fashion for Tcl tests.
#
# Copyright (c) 1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
namespace import ::tcltest::*
eval tcltest::configure $argv
tcltest::loadTestedCommands

Changes to tests/canvas.test.
1
2
3
4
5
6
7



8
9
10

11
12
13
14
15
16
17
1
2
3
4



5
6
7
8
9

10
11
12
13
14
15
16
17




-
-
-
+
+
+


-
+







# This file is a Tcl script to test out the procedures in tkCanvas.c, which
# implements generic code for canvases. It is organized in the standard
# fashion for Tcl tests.
#
# Copyright (c) 1995-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-2000 Ajuba Solutions.
# Copyright (c) 2008 Donal K. Fellows
# Copyright © 1995-1996 Sun Microsystems, Inc.
# Copyright © 1998-2000 Ajuba Solutions.
# Copyright © 2008 Donal K. Fellows
# All rights reserved.

package require tcltest 2.1
package require tcltest 2.2
eval tcltest::configure $argv
tcltest::loadTestedCommands
imageInit

# XXX - This test file is woefully incomplete. At present, only a few of the
# features are tested.

33
34
35
36
37
38
39
40

41
42
43
44
45
46
47

48
49
50
51
52
53
54
55
56
57
58
59
60
61

62
63
64
65
66
67
68
69
70
71
72
73
74
75

76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96

97
98
99
100
101
102
103
104
105
106
107
108
109
110

111
112
113
114
115
116
117

118
119
120
121
122
123
124

125
126
127
128
129
130
131

132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152

153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170

171
172
173
174
175
176
177
33
34
35
36
37
38
39

40
41
42
43
44
45
46

47
48
49
50
51
52
53
54
55
56
57
58
59
60

61
62
63
64
65
66
67
68
69
70
71
72
73
74

75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95

96
97
98
99
100
101
102
103
104
105
106
107
108
109

110
111
112
113
114
115
116

117
118
119
120
121
122
123

124
125
126
127
128
129
130

131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151

152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169

170
171
172
173
174
175
176
177







-
+






-
+













-
+













-
+




















-
+













-
+






-
+






-
+






-
+




















-
+

















-
+







} -result {#ff0000}
test canvas-1.4 {configuration options: bad value for "bg"} -body {
    .c configure -bg non-existent
} -returnCodes error -result {unknown color name "non-existent"}
test canvas-1.5 {configuration options: good value for "bd"} -body {
    .c configure -bd 4
    .c cget -bd
} -result {4}
} -result 4
test canvas-1.6 {configuration options: bad value for "bd"} -body {
    .c configure -bd badValue
} -returnCodes error -result {bad screen distance "badValue"}
test canvas-1.7 {configuration options: good value for "borderwidth"} -body {
    .c configure -borderwidth 1.3
    .c cget -borderwidth
} -result {1}
} -result 1
test canvas-1.8 {configuration options: bad value for "borderwidth"} -body {
    .c configure -borderwidth badValue
} -returnCodes error -result {bad screen distance "badValue"}
test canvas-1.9 {configuration options: good value for "closeenough"} -body {
    .c configure -closeenough 24
    .c cget -closeenough
} -result {24.0}
test canvas-1.10 {configuration options: bad value for "closeenough"} -body {
    .c configure -closeenough bogus
} -returnCodes error -result {expected floating-point number but got "bogus"}
test canvas-1.11 {configuration options: good value for "confine"} -body {
    .c configure -confine true
    .c cget -confine
} -result {1}
} -result 1
test canvas-1.12 {configuration options: bad value for "confine"} -body {
    .c configure -confine silly
} -returnCodes error -result {expected boolean value but got "silly"}
test canvas-1.13 {configuration options: good value for "cursor"} -body {
    .c configure -cursor arrow
    .c cget -cursor
} -result {arrow}
test canvas-1.14 {configuration options: bad value for "cursor"} -body {
    .c configure -cursor badValue
} -returnCodes error -result {bad cursor spec "badValue"}
test canvas-1.15 {configuration options: good value for "height"} -body {
    .c configure -height 2.1
    .c cget -height
} -result {2}
} -result 2
test canvas-1.16 {configuration options: bad value for "height"} -body {
    .c configure -height x42
} -returnCodes error -result {bad screen distance "x42"}
test canvas-1.17 {configuration options: good value for "highlightbackground"} -body {
    .c configure -highlightbackground #112233
    .c cget -highlightbackground
} -result {#112233}
test canvas-1.18 {configuration options: bad value for "highlightbackground"} -body {
    .c configure -highlightbackground ugly
} -returnCodes error -result {unknown color name "ugly"}
test canvas-1.19 {configuration options: good value for "highlightcolor"} -body {
    .c configure -highlightcolor #110022
    .c cget -highlightcolor
} -result {#110022}
test canvas-1.20 {configuration options: bad value for "highlightcolor"} -body {
    .c configure -highlightcolor bogus
} -returnCodes error -result {unknown color name "bogus"}
test canvas-1.21 {configuration options: good value for "highlightthickness"} -body {
    .c configure -highlightthickness 18
    .c cget -highlightthickness
} -result {18}
} -result 18
test canvas-1.22 {configuration options: bad value for "highlightthickness"} -body {
    .c configure -highlightthickness badValue
} -returnCodes error -result {bad screen distance "badValue"}
test canvas-1.23 {configuration options: good value for "insertbackground"} -body {
    .c configure -insertbackground #110022
    .c cget -insertbackground
} -result {#110022}
test canvas-1.24 {configuration options: bad value for "insertbackground"} -body {
    .c configure -insertbackground bogus
} -returnCodes error -result {unknown color name "bogus"}
test canvas-1.25 {configuration options: good value for "insertborderwidth"} -body {
    .c configure -insertborderwidth 1.3
    .c cget -insertborderwidth
} -result {1}
} -result 1
test canvas-1.26 {configuration options: bad value for "insertborderwidth"} -body {
    .c configure -insertborderwidth 2.6x
} -returnCodes error -result {bad screen distance "2.6x"}
test canvas-1.27 {configuration options: good value for "insertofftime"} -body {
    .c configure -insertofftime 100
    .c cget -insertofftime
} -result {100}
} -result 100
test canvas-1.28 {configuration options: bad value for "insertofftime"} -body {
    .c configure -insertofftime 3.2
} -returnCodes error -result {expected integer but got "3.2"}
test canvas-1.29 {configuration options: good value for "insertontime"} -body {
    .c configure -insertontime 100
    .c cget -insertontime
} -result {100}
} -result 100
test canvas-1.30 {configuration options: bad value for "insertontime"} -body {
    .c configure -insertontime 3.2
} -returnCodes error -result {expected integer but got "3.2"}
test canvas-1.31 {configuration options: good value for "insertwidth"} -body {
    .c configure -insertwidth 1.3
    .c cget -insertwidth
} -result {1}
} -result 1
test canvas-1.32 {configuration options: bad value for "insertwidth"} -body {
    .c configure -insertwidth 6x
} -returnCodes error -result {bad screen distance "6x"}
test canvas-1.33 {configuration options: good value for "relief"} -body {
    .c configure -relief groove
    .c cget -relief
} -result {groove}
test canvas-1.34 {configuration options: bad value for "relief"} -body {
    .c configure -relief 1.5
} -returnCodes error -result {bad relief "1.5": must be flat, groove, raised, ridge, solid, or sunken}
test canvas-1.35 {configuration options: good value for "selectbackground"} -body {
    .c configure -selectbackground #110022
    .c cget -selectbackground
} -result {#110022}
test canvas-1.36 {configuration options: bad value for "selectbackground"} -body {
    .c configure -selectbackground bogus
} -returnCodes error -result {unknown color name "bogus"}
test canvas-1.37 {configuration options: good value for "selectborderwidth"} -body {
    .c configure -selectborderwidth 1.3
    .c cget -selectborderwidth
} -result {1}
} -result 1
test canvas-1.38 {configuration options: bad value for "selectborderwidth"} -body {
    .c configure -selectborderwidth badValue
} -returnCodes error -result {bad screen distance "badValue"}
test canvas-1.39 {configuration options: good value for "selectforeground"} -body {
    .c configure -selectforeground #654321
    .c cget -selectforeground
} -result {#654321}
test canvas-1.40 {configuration options: bad value for "selectforeground"} -body {
    .c configure -selectforeground bogus
} -returnCodes error -result {unknown color name "bogus"}
test canvas-1.41 {configuration options: good value for "takefocus"} -body {
    .c configure -takefocus "any string"
    .c cget -takefocus
} -result {any string}
test canvas-1.42 {configuration options: good value for "width"} -body {
    .c configure -width 402
    .c cget -width
} -result {402}
} -result 402
test canvas-1.43 {configuration options: bad value for "width"} -body {
    .c configure -width xyz
} -returnCodes error -result {bad screen distance "xyz"}
test canvas-1.44 {configuration options: good value for "xscrollcommand"} -body {
    .c configure -xscrollcommand {Some command}
    .c cget -xscrollcommand
} -result {Some command}
223
224
225
226
227
228
229










230
231
232
233
234
235
236
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246







+
+
+
+
+
+
+
+
+
+







    .c xview moveto 0.6
    update
    set x [list [.c xview]]
    .c xview scroll 2 units
    update
    lappend x [.c xview]
} -result {{0.6 0.9} {0.66 0.96}}
test canvas-2.5 {CanvasWidgetCmd, raise/lower option, no error on non-existing tags} -setup {
    .c create line 0 0 10 10 -tags aline
} -body {
    .c raise aline noline
    .c raise bline aline
    .c lower aline noline
    .c lower bline aline
} -cleanup {
    .c delete aline
} -result {}
catch {destroy .c}

# Canvas used in 3.* test cases
canvas .c -width 60 -height 40 -scrollregion {0 0 200 80} \
	-borderwidth 0 -highlightthickness 0
pack .c
update
336
337
338
339
340
341
342


343
344


















345
346
347
348
349
350
351
346
347
348
349
350
351
352
353
354


355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379







+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







} -body {
    .c create arc -100 10 100 210 -start 10 -extent 50 -style arc -tags arc1
    set arcBox [.c bbox arc1]
    .c create arc 100 10 300 210 -start 10 -extent 50 -style chord -tags arc2
    set coordBox [.c bbox arc2]
    .c create arc 300 10 500 210 -start 10 -extent 50 -style pieslice -tags arc3
    set pieBox [.c bbox arc3]
    .c create arc 100 200 300 200 -height [expr {(1-0.5*sqrt(3))*200}] -style arc -tags arc4
    set arcSegBox [.c bbox arc4]
    list $arcBox $coordBox $pieBox
} -result {{48 21 100 94} {248 21 300 94} {398 21 500 112}}
    list $arcBox $coordBox $pieBox $arcSegBox
} -result {{48 21 100 94} {248 21 300 94} {398 21 500 112} {98 171 302 202}}
test canvas-8.2 {canvas very small arc} -setup {
    catch {destroy .c}
    canvas .c
} -body {
    # no Inf or NaN must be generated even for very small arcs
    .c create arc 0 100 0 100 -height 100 -style arc -outline "" -tags arc1
    set arcBox [.c bbox arc1]
    .c create arc 0 100 0 100 -height 100 -style arc -outline blue -tags arc2
    set outlinedArcBox [.c bbox arc2]
    set coords [.c coords arc1]
    set start [.c itemcget arc1 -start]
    set extent [.c itemcget arc1 -extent]
    set width [.c itemcget arc1 -width]
    set height [.c itemcget arc1 -height]
    list $arcBox $outlinedArcBox $coords $start $extent $width $height
} -result {{-1 99 1 101} {-2 98 2 102} {0.0 100.0 0.0 100.0} 0.0 0.0 1.0 0.0}

test canvas-9.1 {canvas id creation and deletion} -setup {
    catch {destroy .c}
    canvas .c
} -body {
    # With Tk 8.0.4 the ids are now stored in a hash table. You can use this
    # test as a performance test with older versions by changing the value of
533
534
535
536
537
538
539
540
541


542
543

544
545
546
547
548
549
550
551
552

553
554

555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575

576
577
578
579
580
581
582
561
562
563
564
565
566
567


568
569
570

571
572
573
574
575
576
577
578
579

580
581

582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602

603
604
605
606
607
608
609
610







-
-
+
+

-
+








-
+

-
+




















-
+







    .c coords 1
} {}

test canvas-12.1 {canvas mm obj, patch SF-403327, 102471} -setup {
    destroy .c
    pack [canvas .c]
} -body {
    set qx [expr {1.+1.}] 
    # qx has type double and no string representation 
    set qx [expr {1.+1.}]
    # qx has type double and no string representation
    .c scale all $qx 0 1. 1.
    # qx has now type MMRep and no string representation 
    # qx has now type MMRep and no string representation
    list $qx [string length $qx]
} -result {2.0 3}
test canvas-12.2 {canvas mm obj, patch SF-403327, 102471} -setup {
    destroy .c
    pack [canvas .c]
} -body {
    set val 10
    incr val
    # qx has type double and no string representation 
    # qx has type double and no string representation
    .c scale all $val 0 1 1
    # qx has now type MMRep and no string representation 
    # qx has now type MMRep and no string representation
    incr val
} -result 12

# procedure used in 13.1 test case
proc kill_canvas {w} {
    destroy $w
    pack [canvas $w -height 200 -width 200] -fill both -expand yes
    update idle
    $w create rectangle 80 80 120 120 -fill blue -tags blue
    # bind a button press to re-build the canvas
    $w bind blue <ButtonRelease-1> [subst {
	[lindex [info level 0] 0] $w
	append ::x ok
    }]
}
test canvas-13.1 {canvas delete during event, SF bug-228024} -body {
    kill_canvas .c
    set ::x {}
    # do this many times to improve chances of triggering the crash
    for {set i 0} {$i < 30} {incr i} {
	event generate .c <1> -x 100 -y 100
	event generate .c <Button-1> -x 100 -y 100
	event generate .c <ButtonRelease-1> -x 100 -y 100
    }
    return $::x
} -result {okokokokokokokokokokokokokokokokokokokokokokokokokokokokokok}

test canvas-14.1 {canvas scan SF bug 581560} -setup {
    destroy .c
723
724
725
726
727
728
729
730

731
732

733
734
735
736
737
738
739
751
752
753
754
755
756
757

758
759

760
761
762
763
764
765
766
767







-
+

-
+







} -returnCodes error -body {
    .c create window 0
} -result {wrong # coordinates: expected 2, got 1}
test canvas-15.19 "basic coords check: centimeters are larger than pixels" -setup {
    destroy .c
    canvas .c
} -body {
    set id [.c create rect 0 0 1cm 1cm] 
    set id [.c create rect 0 0 1cm 1cm]
    expr {[lindex [.c coords $id] 2]>1}
} -result {1}
} -result 1
destroy .c

test canvas-16.1 {arc coords check} -setup {
    canvas .c
} -body {
    set id [.c create arc {0 10 20 30} -start 33]
    .c itemcget $id -start
988
989
990
991
992
993
994















































































































































































































































































995
996
997
998
999
1000
1001
1002
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








    set res [list [.c gettags 1]]
    .c dtag 1 tagA
    lappend res [.c gettags 1]
} -cleanup {
    destroy .c
} -result {{tagA tagA tagA tagA tagA tagA} {}}

destroy .c
test canvas-21.1 {canvas rotate} -setup {
    pack [canvas .c]
} -body {
    .c create line 50 50 50 100 100 100
    .c rotate all 75 75 90
    lmap c [.c coords all] {format %.2f $c}
} -cleanup {
    destroy .c
} -result {50.00 100.00 100.00 100.00 100.00 50.00}
test canvas-21.2 {canvas rotate} -setup {
    pack [canvas .c]
} -body {
    .c create line 50 50 50 100 100 100
    .c rotate all 75 75 -10
    lmap c [.c coords all] {format %.2f $c}
} -cleanup {
    destroy .c
} -result {54.72 46.04 46.04 95.28 95.28 103.96}
test canvas-21.3 {canvas rotate: syntax} -setup {
    pack [canvas .c]
} -body {
    .c rotate all 75 75
} -returnCodes error -cleanup {
    destroy .c
} -result {wrong # args: should be ".c rotate tagOrId x y angle"}
test canvas-21.4 {canvas rotate: syntax} -setup {
    pack [canvas .c]
} -body {
    .c rotate all 75 75 123 123
} -returnCodes error -cleanup {
    destroy .c
} -result {wrong # args: should be ".c rotate tagOrId x y angle"}
test canvas-21.5 {canvas rotate: syntax} -setup {
    pack [canvas .c]
} -body {
    .c rotate {!} 1 1 1
} -returnCodes error -cleanup {
    destroy .c
} -result {missing tag in tag search expression}
test canvas-21.6 {canvas rotate: syntax} -setup {
    pack [canvas .c]
} -body {
    .c rotate all x 1 1
} -returnCodes error -cleanup {
    destroy .c
} -result {bad screen distance "x"}
test canvas-21.7 {canvas rotate: syntax} -setup {
    pack [canvas .c]
} -body {
    .c rotate all 1 x 1
} -returnCodes error -cleanup {
    destroy .c
} -result {bad screen distance "x"}
test canvas-21.8 {canvas rotate: syntax} -setup {
    pack [canvas .c]
} -body {
    .c rotate all 1 1 x
} -returnCodes error -cleanup {
    destroy .c
} -result {expected floating-point number but got "x"}
test canvas-21.9 {canvas rotate: nothing to rotate} -setup {
    pack [canvas .c]
} -body {
    .c rotate all 75 75 10
} -cleanup {
    destroy .c
} -result {}
test canvas-21.10 {canvas rotate: multiple things to rotate} -setup {
    pack [canvas .c]
} -body {
    .c create line 50 50 50 100 -tag a
    .c create line 50 50 100 50 -tag b
    .c rotate all 75 75 45
    list [lmap c [.c coords a] {format %.2f $c}] [lmap c [.c coords b] {format %.2f $c}]
} -cleanup {
    destroy .c
} -result {{39.64 75.00 75.00 110.36} {39.64 75.00 75.00 39.64}}

test canvas-22.1 {canvas rotate: arc item rotation behaviour} -setup {
    pack [canvas .c]
} -body {
    .c create arc 50 50 75 75 -start 45 -extent 90
    .c rotate all 100 100 90
    list [lmap c [.c coords all] {format %.2f $c}] \
	[lmap o {-start -extent} {.c itemcget all $o}] \
	[.c bbox all]
} -cleanup {
    destroy .c
} -result {{50.00 125.00 75.00 150.00} {45.0 90.0} {52 123 73 140}}
test canvas-22.2 {canvas rotate: bitmap item rotation behaviour} -setup {
    pack [canvas .c]
} -body {
    .c create bitmap 50 50 -bitmap info -anchor se
    .c rotate all 100 100 90
    list [lmap c [.c coords all] {format %.2f $c}] \
	[lmap o {-bitmap -anchor} {.c itemcget all $o}] \
	[.c bbox all]
} -cleanup {
    destroy .c
} -result {{50.00 150.00} {info se} {42 129 50 150}}
test canvas-22.3 {canvas rotate: image item rotation behaviour} -setup {
    pack [canvas .c]
    image create photo dummy -width 50 -height 50
} -body {
    .c create image 50 50 -image dummy -anchor se
    .c rotate all 100 100 90
    list [lmap c [.c coords all] {format %.2f $c}] \
	[lmap o {-image -anchor} {.c itemcget all $o}] \
	[.c bbox all]
} -cleanup {
    destroy .c
    image delete dummy
} -result {{50.00 150.00} {dummy se} {0 100 50 150}}
test canvas-22.4 {canvas rotate: line item rotation behaviour} -setup {
    pack [canvas .c]
} -body {
    .c create line 50 50 75 50 50 75 75 75
    .c rotate all 100 100 90
    list [lmap c [.c coords all] {format %.2f $c}] \
	[lmap o {} {.c itemcget all $o}] \
	[.c bbox all]
} -cleanup {
    destroy .c
} -result {{50.00 150.00 50.00 125.00 75.00 150.00 75.00 125.00} {} {48 123 77 152}}
test canvas-22.5 {canvas rotate: oval item rotation behaviour} -setup {
    pack [canvas .c]
} -body {
    .c create oval 50 50 65 85
    .c rotate all 100 100 90
    list [lmap c [.c coords all] {format %.2f $c}] \
	[lmap o {} {.c itemcget all $o}] \
	[.c bbox all]
} -cleanup {
    destroy .c
} -result {{60.00 125.00 75.00 160.00} {} {59 124 76 161}}
test canvas-22.6 {canvas rotate: polygon item rotation behaviour} -setup {
    pack [canvas .c]
} -body {
    .c create polygon 50 50 75 50 50 75 75 75
    .c rotate all 100 100 90
    list [lmap c [.c coords all] {format %.2f $c}] \
	[lmap o {} {.c itemcget all $o}] \
	[.c bbox all]
} -cleanup {
    destroy .c
} -result {{50.00 150.00 50.00 125.00 75.00 150.00 75.00 125.00} {} {48 123 77 152}}
test canvas-22.7 {canvas rotate: rectangle item rotation behaviour} -setup {
    pack [canvas .c]
} -body {
    .c create rectangle 50 50 75 75
    .c rotate all 100 100 90
    list [lmap c [.c coords all] {format %.2f $c}] \
	[lmap o {} {.c itemcget all $o}] \
	[.c bbox all]
} -cleanup {
    destroy .c
} -result {{50.00 125.00 75.00 150.00} {} {49 124 76 151}}
test canvas-22.8 {canvas rotate: text item rotation behaviour} -setup {
    pack [canvas .c]
} -body {
    .c create text 50 50 -text foo -angle 45
    .c rotate all 100 100 90
    list [lmap c [.c coords all] {format %.2f $c}] \
	[lmap o {-text -angle} {.c itemcget all $o}]
    # [.c bbox all]
    # No testing of text bounding box; fonts too variable!
} -cleanup {
    destroy .c
} -result {{50.00 150.00} {foo 45.0}}
test canvas-22.9 {canvas rotate: window item rotation behaviour} -setup {
    pack [canvas .c]
} -body {
    .c create window 50 50 -window [frame .c.f -width 25 -height 25] \
	-anchor se
    .c rotate all 100 100 90
    list [lmap c [.c coords all] {format %.2f $c}] \
	[lmap o {} {.c itemcget all $o}] \
	[.c bbox all]
} -cleanup {
    destroy .c
} -result {{50.00 150.00} {} {25 125 50 150}}

# Procedure used in test cases 23.1 23.2 23.3
proc matchPixels {pixels expected} {
    set matched 1
    foreach pline $pixels eline $expected {
        foreach ppixel $pline epixel $eline {
            if {$ppixel != $epixel} {
                set matched 0
                break
            }
        }
    }
    return $matched
}

test canvas-23.1 {canvas image} -setup {
    canvas .c
    image create photo testimage
} -body  {
    .c configure -background #c0c0c0 -scrollregion {0 0 9 9}
    .c create rectangle 0 0 0 9 -fill #000080 -outline #000080
    .c image testimage
    matchPixels [testimage data] { \
            {#000080 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \
            {#000080 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \
            {#000080 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \
            {#000080 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \
            {#000080 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \
            {#000080 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \
            {#000080 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \
            {#000080 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \
            {#000080 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \
            {#000080 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0}}
} -cleanup {
    destroy .c
    image delete testimage
} -result 1

test canvas-23.2 {canvas image with subsample} -setup {
    canvas .c
    image create photo testimage
} -body  {
    .c configure -background #c0c0c0 -scrollregion {0 0 9 9}
    .c create rectangle 0 0 1 9 -fill #008000 -outline #008000
    .c image testimage 2
    matchPixels [testimage data] { \
        {#008000 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \
        {#008000 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \
        {#008000 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \
        {#008000 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \
        {#008000 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0}}
} -cleanup {
    destroy .c
    image delete testimage
} -result 1

test canvas-23.3 {canvas image with subsample and zoom} -setup {
    canvas .c
    image create photo testimage
} -body  {
    .c configure -background #c0c0c0 -scrollregion {0 0 9 9}
    .c create rectangle 0 0 9 0 -fill #800000 -outline #800000
    .c image testimage 1 2
    matchPixels [testimage data] { \
        {#800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000} \
        {#800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000 #800000} \
        {#c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \
        {#c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \
        {#c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \
        {#c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \
        {#c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \
        {#c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \
        {#c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \
        {#c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \
        {#c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \
        {#c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \
        {#c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \
        {#c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \
        {#c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \
        {#c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \
        {#c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \
        {#c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \
        {#c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0} \
        {#c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0 #c0c0c0}}
} -cleanup {
    destroy .c
    image delete testimage
} -result 1

# cleanup
imageCleanup
cleanupTests
return

# Local Variables:
# mode: tcl
# End:
Changes to tests/choosedir.test.
1
2
3
4
5


6
7
8
9
10
11
12
1
2
3


4
5
6
7
8
9
10
11
12



-
-
+
+







# This file is a Tcl script to test out Tk's "tk_chooseDir" and
# It is organized in the standard fashion for Tcl tests.
#
# Copyright (c) 1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
namespace import ::tcltest::*
eval tcltest::configure $argv
tcltest::loadTestedCommands

22
23
24
25
26
27
28
29

30
31
32
33
34
35
36
22
23
24
25
26
27
28

29
30
31
32
33
34
35
36







-
+








proc ToEnterDirsByKey {parent dirs} {
    after 100 [list EnterDirsByKey $parent $dirs]
}

proc PressButton {btn} {
    event generate $btn <Enter>
    event generate $btn <1> -x 5 -y 5
    event generate $btn <Button-1> -x 5 -y 5
    event generate $btn <ButtonRelease-1> -x 5 -y 5
}

proc EnterDirsByKey {parent dirs} {
    global tk_strictMotif
    if {$parent == "."} {
	set w .__tk_choosedir
64
65
66
67
68
69
70
71

72
73
74
75
76
77
78
64
65
66
67
68
69
70

71
72
73
74
75
76
77
78







-
+








    if {$type == "mouse"} {
	PressButton $button
    } else {
	event generate $w <Enter>
	focus $w
	event generate $button <Enter>
	event generate $w <KeyPress> -keysym Return
	event generate $w <Key> -keysym Return
    }
}


#----------------------------------------------------------------------
#
# The test suite proper
Changes to tests/clipboard.test.
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22


23
24
25
26
27
28
29
1
2
3
4


5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31




-
-
+
+
















+
+







# This file is a Tcl script to test out Tk's clipboard management code,
# especially the "clipboard" command.  It is organized in the standard
# fashion for Tcl tests.
#
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1994 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

#
# Note: Multiple display clipboard handling will only be tested if the
# environment variable TK_ALT_DISPLAY is set to an alternate display.
#

#################################################################
# Note that some of these tests may fail if another application #
# is grabbing the clipboard (e.g. an X server, or a VNC viewer) #
#################################################################

package require tcltest 2.2
namespace import ::tcltest::*
eval tcltest::configure $argv
tcltest::loadTestedCommands

testConstraint failsOnXQuarz [expr {$tcl_platform(os) ne "Darwin" || [tk windowingsystem] ne "x11" }]

# set up a very large buffer to test INCR retrievals
set longValue ""
foreach i {a b c d e f g j h i j k l m o p q r s t u v w x y z} {
    set j $i.1$i.2$i.3$i.4$i.5$i.6$i.7$i.8$i.9$i.10$i.11$i.12$i.13$i.14
    append longValue A$j B$j C$j D$j E$j F$j G$j H$j I$j K$j L$j M$j N$j
}
176
177
178
179
180
181
182
183

184
185
186
187
188
189
190
178
179
180
181
182
183
184

185
186
187
188
189
190
191
192







-
+







    clipboard append "Test"
    clipboard append -t TEST "Test2"
    clipboard append "Test3"
    selection clear -s CLIPBOARD
    clipboard get
} -cleanup {
    clipboard clear
}  -returnCodes error -result {CLIPBOARD selection doesn't exist or form "STRING" not defined} 
}  -returnCodes error -result {CLIPBOARD selection doesn't exist or form "STRING" not defined}
test clipboard-4.5 {ClipboardLostSel procedure} -setup {
    clipboard clear
} -body {
    clipboard append "Test"
    clipboard append -t TEST "Test2"
    clipboard append "Test3"
    selection clear -s CLIPBOARD
229
230
231
232
233
234
235
236

237
238
239
240
241
242
243
231
232
233
234
235
236
237

238
239
240
241
242
243
244
245







-
+







    clipboard append "first chunk"
    selection own -s CLIPBOARD .
	clipboard append " second chunk"
	clipboard get
} -cleanup {
    clipboard clear
}  -returnCodes ok -result {first chunk second chunk}
test clipboard-6.2 {Tk_ClipboardAppend procedure} -constraints x11 -setup {
test clipboard-6.2 {Tk_ClipboardAppend procedure} -constraints {x11 failsOnXQuarz} -setup {
    clipboard clear
} -body {
    setupbg
    clipboard append -f INTEGER -t TEST "16"
    set result [dobg {clipboard get TEST}]
    return $result
} -cleanup {
Changes to tests/clrpick.test.
1
2
3
4
5


6
7
8
9
10
11
12
1
2
3


4
5
6
7
8
9
10
11
12



-
-
+
+







# This file is a Tcl script to test out Tk's "tk_chooseColor" command.
# It is organized in the standard fashion for Tcl tests.
#
# Copyright (c) 1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
eval tcltest::configure $argv
tcltest::loadTestedCommands
namespace import -force tcltest::test

93
94
95
96
97
98
99
100

101
102
103
104
105
106
107
93
94
95
96
97
98
99

100
101
102
103
104
105
106
107







-
+







    if {!$isNative} {
	after 200 ChooseColorByKey . $r $g $b
    }
}

proc PressButton {btn} {
    event generate $btn <Enter>
    event generate $btn <1> -x 5 -y 5
    event generate $btn <Button-1> -x 5 -y 5
    event generate $btn <ButtonRelease-1> -x 5 -y 5
}

proc ChooseColorByKey {parent r g b} {
    set w .__tk__color
    upvar ::tk::dialog::color::[winfo name $w] data

133
134
135
136
137
138
139
140

141
142
143
144
145
146
147
133
134
135
136
137
138
139

140
141
142
143
144
145
146
147







-
+








    if {$type == "mouse"} {
	PressButton $button
    } else {
	event generate $w <Enter>
	focus $w
	event generate $button <Enter>
	event generate $w <KeyPress> -keysym Return
	event generate $w <Key> -keysym Return
    }
}



test clrpick-2.1 {tk_chooseColor command} -constraints {
    nonUnixUserInteraction colorsLeftover
Changes to tests/cmds.test.
1
2
3
4
5


6
7
8
9
10
11
12
1
2
3


4
5
6
7
8
9
10
11
12



-
-
+
+







# This file is a Tcl script to test the procedures in the file
# tkCmds.c.  It is organized in the standard fashion for Tcl tests.
#
# Copyright (c) 1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
eval tcltest::configure $argv
tcltest::loadTestedCommands
namespace import -force tcltest::test

35
36
37
38
39
40
41
42

43
44
45
46
47
48
49
35
36
37
38
39
40
41

42
43
44
45
46
47
48
49







-
+







    frame .f
    button .f.b -text "Test"
    pack .f.b
    set x init
} -body {
    after 100 {set x deleted; destroy .f}
    tkwait visibility .f.b
} -returnCodes {error} -result {window ".f.b" was deleted before its visibility changed} 
} -returnCodes {error} -result {window ".f.b" was deleted before its visibility changed}
test cmds-1.6 {tkwait visibility, window gets deleted} -setup {
    frame .f
    button .f.b -text "Test"
    pack .f.b
    set x init
} -body {
    after 100 {set x deleted; destroy .f}
Changes to tests/color.test.
1
2
3
4
5


6
7
8

9
10
11
12
13
14
15
1
2
3


4
5
6
7

8
9
10
11
12
13
14
15



-
-
+
+


-
+







# This file is a Tcl script to test out the procedures in the file
# tkColor.c.  It is organized in the standard fashion for Tcl tests.
#
# Copyright (c) 1995-1998 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1995-1998 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.1
package require tcltest 2.2
eval tcltest::configure $argv
tcltest::loadTestedCommands

# cname --
# Returns a proper name for a color, given its intensities.
#
# Arguments:
158
159
160
161
162
163
164
165

166
167
168
169
170
171
172
158
159
160
161
162
163
164

165
166
167
168
169
170
171
172







-
+







    button .b2 -foreground $x -text Third
    pack .b2 -side top
    lappend result [testcolor purple]
} {{{1 1}} {{1 1} {1 0}} {{1 0} {2 1}}}
test color-1.5 {Color table} nonPortable {
    set fd [open ../xlib/rgb.txt]
    set result {}
    while {[gets $fd line] != -1} {
    while {[gets $fd line] >= 0} {
    	if {[string index $line 0] == "!"} continue
	set rgb [c255 [winfo rgb . [lrange $line 3 end]]]
	if {$rgb != [lrange $line 0 2] } {
		append result $line\n
	}

    }
Changes to tests/config.test.
1
2
3
4
5
6


7
8
9
10
11
12
13
1
2
3
4


5
6
7
8
9
10
11
12
13




-
-
+
+







# This file is a Tcl script to test the procedures in tkConfig.c,
# which comprise the new new option configuration system.  It is
# organized in the standard "white-box" fashion for Tcl tests.
#
# Copyright (c) 1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
namespace import ::tcltest::*
eval tcltest::configure $argv
tcltest::loadTestedCommands

192
193
194
195
196
197
198
199

200
201
202
203
204
205
206
192
193
194
195
196
197
198

199
200
201
202
203
204
205
206







-
+







    killTables
    option clear
} -returnCodes error -result {unknown color name "non-existent"}
test config-3.7 {Tk_InitOptions - bad initial value} -constraints {
    testobjconfig
} -body {
    option add *a.color non-existent
    catch {testobjconfig alltypes .a} 
    catch {testobjconfig alltypes .a}
    return $errorInfo
} -cleanup {
    killTables
    option clear
} -result {unknown color name "non-existent"
    (database entry for "-color" in widget ".a")
    invoked from within
231
232
233
234
235
236
237
238

239
240
241
242
243
244
245
231
232
233
234
235
236
237

238
239
240
241
242
243
244
245







-
+







test config-4.2 {DoObjConfig - boolean} -constraints testobjconfig -setup {
    catch {rename .foo {}}
} -body {
    testobjconfig alltypes .foo -boolean 0
    .foo cget -boolean
} -cleanup {
    killTables
} -returnCodes ok -result {0}
} -returnCodes ok -result 0
test config-4.3 {DoObjConfig - boolean} -constraints testobjconfig -setup {
    catch {rename .foo {}}
} -body {
    testobjconfig alltypes .foo -boolean 0
    .foo cget -boolean
    rename .foo {}
} -cleanup {
255
256
257
258
259
260
261
262

263
264
265
266
267
268
269
255
256
257
258
259
260
261

262
263
264
265
266
267
268
269







-
+







test config-4.5 {DoObjConfig - boolean} -constraints testobjconfig -setup {
    catch {rename .foo {}}
} -body {
    testobjconfig alltypes .foo -boolean 1
    .foo cget -boolean
} -cleanup {
    killTables
} -returnCodes ok -result {1}
} -returnCodes ok -result 1
test config-4.6 {DoObjConfig - boolean} -constraints testobjconfig -setup {
    catch {rename .foo {}}
} -body {
    testobjconfig alltypes .foo -boolean 1
    .foo cget -boolean
    rename .foo {}
} -cleanup {
283
284
285
286
287
288
289
290

291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306

307
308
309
310
311
312
313
283
284
285
286
287
288
289

290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305

306
307
308
309
310
311
312
313







-
+















-
+







} -setup {
    catch {rename .foo {}}
} -body {
    testobjconfig internal .foo -boolean 0
    .foo cget -boolean
} -cleanup {
    killTables
} -result {0}
} -result 0

test config-4.9 {DoObjConfig - integer} -constraints testobjconfig -setup {
    catch {rename .foo {}}
} -body {
    testobjconfig alltypes .foo -integer 3
} -cleanup {
    killTables
} -returnCodes ok -result {.foo}
test config-4.10 {DoObjConfig - integer} -constraints testobjconfig -setup {
    catch {rename .foo {}}
} -body {
    testobjconfig alltypes .foo -integer 3
    .foo cget -integer
} -cleanup {
    killTables
} -returnCodes ok -result {3}
} -returnCodes ok -result 3
test config-4.11 {DoObjConfig - integer} -constraints testobjconfig -setup {
    catch {rename .foo {}}
} -body {
    testobjconfig alltypes .foo -integer 3
    .foo cget -integer
    rename .foo {}
} -cleanup {
329
330
331
332
333
334
335
336

337
338
339
340
341
342
343
329
330
331
332
333
334
335

336
337
338
339
340
341
342
343







-
+







} -setup {
    catch {rename .foo {}}
} -body {
    testobjconfig internal .foo -integer 421
    .foo cget -integer
} -cleanup {
    killTables
} -result {421}
} -result 421

test config-4.14 {DoObjConfig - double} -constraints testobjconfig -setup {
    catch {rename .foo {}}
} -body {
    testobjconfig alltypes .foo -double 3.14
} -cleanup {
    killTables
468
469
470
471
472
473
474
475

476
477
478
479
480
481
482
468
469
470
471
472
473
474

475
476
477
478
479
480
481
482







-
+







test config-4.30 {DoObjConfig - new string table} -constraints {
    testobjconfig
} -body {
    testobjconfig alltypes .foo -stringtable two
    .foo configure -stringtable three
} -cleanup {
    killTables
} -returnCodes ok -result {16}
} -returnCodes ok -result 16
test config-4.31 {DoObjConfig - new string table} -constraints {
    testobjconfig
} -body {
    testobjconfig alltypes .foo -stringtable two
    .foo configure -stringtable three
    .foo cget -stringtable
} -cleanup {
554
555
556
557
558
559
560
561

562
563
564
565
566
567

568
569

570
571
572
573
574
575
576
577
578

579
580
581
582
583
584
585
554
555
556
557
558
559
560

561
562
563
564
565
566

567
568

569
570
571
572
573
574
575
576
577

578
579
580
581
582
583
584
585







-
+





-
+

-
+








-
+







    testobjconfig alltypes .foo -color {}
    .foo cget -color
    rename .foo {}
} -cleanup {
    killTables
} -returnCodes ok
test config-4.42 {DoObjConfig - getting rid of old color} -constraints {
    testobjconfig 
    testobjconfig
} -body {
    testobjconfig alltypes .foo -color #333333
    .foo configure -color #444444
} -cleanup {
    killTables
} -returnCodes ok -result {32}
} -returnCodes ok -result 32
test config-4.43 {DoObjConfig - getting rid of old color} -constraints {
    testobjconfig 
    testobjconfig
} -body {
    testobjconfig alltypes .foo -color #333333
    .foo configure -color #444444
    .foo cget -color
} -cleanup {
    killTables
} -returnCodes ok -result {#444444}
test config-4.44 {DoObjConfig - getting rid of old color} -constraints {
    testobjconfig 
    testobjconfig
} -body {
    testobjconfig alltypes .foo -color #333333
    .foo configure -color #444444
    .foo cget -color
    rename .foo {}
} -cleanup {
    killTables
603
604
605
606
607
608
609
610

611
612
613
614
615
616
617
603
604
605
606
607
608
609

610
611
612
613
614
615
616
617







-
+







test config-4.47 {DoObjConfig - new font} -constraints testobjconfig -setup {
    catch {rename .foo {}}
} -body {
    testobjconfig alltypes .foo -font {Courier 12}
    .foo configure -font {Helvetica 72}
} -cleanup {
    killTables
} -returnCodes ok -result {64}
} -returnCodes ok -result 64
test config-4.48 {DoObjConfig - new font} -constraints testobjconfig -setup {
    catch {rename .foo {}}
} -body {
    testobjconfig alltypes .foo -font {Courier 12}
    .foo configure -font {Helvetica 72}
    .foo cget -font
} -cleanup {
661
662
663
664
665
666
667
668

669
670
671

672
673
674

675
676
677
678
679
680
681
661
662
663
664
665
666
667

668
669
670

671
672
673

674
675
676
677
678
679
680
681







-
+


-
+


-
+







    testobjconfig alltypes .foo -bitmap gray75
    .foo cget -bitmap
} -cleanup {
    killTables
} -returnCodes ok -result {gray75}
test config-4.55 {DoObjConfig - new bitmap} -constraints testobjconfig -body {
    testobjconfig alltypes .foo -bitmap gray75
    .foo configure -bitmap gray50 
    .foo configure -bitmap gray50
} -cleanup {
    killTables
} -returnCodes ok -result {128}
} -returnCodes ok -result 128
test config-4.56 {DoObjConfig - new bitmap} -constraints testobjconfig -body {
    testobjconfig alltypes .foo -bitmap gray75
    .foo configure -bitmap gray50 
    .foo configure -bitmap gray50
    .foo cget -bitmap
} -cleanup {
    killTables
} -returnCodes ok -result {gray50}
test config-4.57 {DoObjConfig - invalid bitmap} -constraints {
    testobjconfig
} -body {
741
742
743
744
745
746
747
748

749
750
751
752
753
754

755
756

757
758
759
760
761
762
763
741
742
743
744
745
746
747

748
749
750
751
752
753

754
755

756
757
758
759
760
761
762
763







-
+





-
+

-
+







} -body {
    testobjconfig internal .foo -border #123456
    .foo cget -border
} -cleanup {
    killTables
} -result {#123456}
test config-4.67 {DoObjConfig - getting rid of old border} -constraints {
    testobjconfig 
    testobjconfig
} -body {
    testobjconfig alltypes .foo -border #333333
    .foo configure -border #444444
} -cleanup {
    killTables
} -returnCodes ok -result {256}
} -returnCodes ok -result 256
test config-4.68 {DoObjConfig - getting rid of old border} -constraints {
    testobjconfig 
    testobjconfig
} -body {
    testobjconfig alltypes .foo -border #333333
    .foo configure -border #444444
    .foo cget -border
} -cleanup {
    killTables
} -returnCodes ok -result {#444444}
786
787
788
789
790
791
792
793

794
795
796

797
798
799

800
801
802
803
804
805
806
786
787
788
789
790
791
792

793
794
795

796
797
798

799
800
801
802
803
804
805
806







-
+


-
+


-
+







    testobjconfig internal .foo -relief ridge
    .foo cget -relief
} -cleanup {
    killTables
} -result {ridge}
test config-4.73 {DoObjConfig - new relief} -constraints testobjconfig -body {
    testobjconfig alltypes .foo -relief raised
    .foo configure -relief flat 
    .foo configure -relief flat
} -cleanup {
    killTables
} -returnCodes ok -result {512}
} -returnCodes ok -result 512
test config-4.74 {DoObjConfig - new relief} -constraints testobjconfig -body {
    testobjconfig alltypes .foo -relief raised
    .foo configure -relief flat 
    .foo configure -relief flat
    .foo cget -relief
} -cleanup {
    killTables
} -returnCodes ok -result {flat}

test config-4.75 {DoObjConfig - cursor} -constraints testobjconfig -body {
    testobjconfig alltypes .foo -cursor arrow
834
835
836
837
838
839
840
841

842
843
844
845
846
847
848
834
835
836
837
838
839
840

841
842
843
844
845
846
847
848







-
+







    killTables
} -returnCodes ok -result {}
test config-4.80 {DoObjConfig - new cursor} -constraints testobjconfig -body {
    testobjconfig alltypes .foo -cursor xterm
    .foo configure -cursor arrow
} -cleanup {
    killTables
} -returnCodes ok -result {1024}
} -returnCodes ok -result 1024
test config-4.81 {DoObjConfig - new cursor} -constraints testobjconfig -body {
    testobjconfig alltypes .foo -cursor xterm
    .foo configure -cursor arrow
    .foo cget -cursor
} -cleanup {
    killTables
} -returnCodes ok -result {arrow}
874
875
876
877
878
879
880
881

882
883
884
885
886
887
888
874
875
876
877
878
879
880

881
882
883
884
885
886
887
888







-
+







    killTables
} -returnCodes error -result {bad justification "foo": must be left, right, or center}
test config-4.86 {DoObjConfig - new justify} -constraints testobjconfig -body {
    testobjconfig alltypes .foo -justify left
    .foo configure -justify right
} -cleanup {
    killTables
} -returnCodes ok -result {2048}
} -returnCodes ok -result 2048
test config-4.87 {DoObjConfig - new justify} -constraints testobjconfig -body {
    testobjconfig alltypes .foo -justify left
    .foo configure -justify right
    .foo cget -justify
} -cleanup {
    killTables
} -returnCodes ok -result {right}
911
912
913
914
915
916
917
918

919
920
921

922
923
924
925
926
927
928
911
912
913
914
915
916
917

918
919
920

921
922
923
924
925
926
927
928







-
+


-
+







test config-4.91 {DoObjConfig - invalid anchor} -constraints testobjconfig -body {
    testobjconfig alltypes .foo -anchor foo
} -cleanup {
    killTables
} -returnCodes error -result {bad anchor "foo": must be n, ne, e, se, s, sw, w, nw, or center}
test config-4.92 {DoObjConfig - new anchor} -constraints testobjconfig -body {
    testobjconfig alltypes .foo -anchor e
    .foo configure -anchor n 
    .foo configure -anchor n
} -cleanup {
    killTables
} -returnCodes ok -result {4096}
} -returnCodes ok -result 4096
test config-4.93 {DoObjConfig - new anchor} -constraints testobjconfig -body {
    testobjconfig alltypes .foo -anchor e
    .foo configure -anchor n
    .foo cget -anchor
} -cleanup {
    killTables
} -returnCodes ok -result {n}
942
943
944
945
946
947
948
949

950
951
952
953
954
955
956
957
958
959
960

961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979

980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996

997
998
999
1000
1001
1002
1003
942
943
944
945
946
947
948

949
950
951
952
953
954
955
956
957
958
959

960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978

979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995

996
997
998
999
1000
1001
1002
1003







-
+










-
+


















-
+
















-
+







    killTables
} -returnCodes ok -result {.foo}
test config-4.96 {DoObjConfig - pixel} -constraints testobjconfig -body {
    testobjconfig alltypes .foo -pixel 42
    .foo cget -pixel
} -cleanup {
    killTables
} -returnCodes ok -result {42}
} -returnCodes ok -result 42
test config-4.97 {DoObjConfig - invalid pixel} -constraints testobjconfig -body {
    testobjconfig alltypes .foo -pixel foo
} -cleanup {
    killTables
} -returnCodes error -result {bad screen distance "foo"}
test config-4.98 {DoObjConfig - new pixel} -constraints testobjconfig -body {
    testobjconfig alltypes .foo -pixel 42m
    .foo configure -pixel 3c
} -cleanup {
    killTables
} -returnCodes ok -result {8192}
} -returnCodes ok -result 8192
test config-4.99 {DoObjConfig - new pixel} -constraints testobjconfig -body {
    testobjconfig alltypes .foo -pixel 42m
    .foo configure -pixel 3c
    .foo cget -pixel
} -cleanup {
    killTables
} -returnCodes ok -result {3c}
test config-4.100 {DoObjConfig - pixel internal value} -constraints {
    testobjconfig
} -setup {
    catch {rename .foo {}}
} -body {
    testobjconfig internal .foo -pixel [winfo screenmmwidth .]m
    set screenW [winfo screenwidth .]
    set result [.foo cget -pixel]
    expr {$screenW eq $result}
} -cleanup {
    killTables
} -result {1}
} -result 1

test config-4.101 {DoObjConfig - window} -constraints testobjconfig -body {
    toplevel .bar
    testobjconfig twowindows .foo -window .bar
} -cleanup {
    killTables
} -returnCodes ok -result {.foo}
test config-4.102 {DoObjConfig - window} -constraints testobjconfig -body {
    toplevel .bar
    testobjconfig twowindows .foo -window .bar
    .foo cget -window
} -cleanup {
    killTables
} -returnCodes ok -result {.bar}
test config-4.103 {DoObjConfig - invalid window} -constraints testobjconfig -body {
    toplevel .bar
    testobjconfig twowindows .foo -window foo 
    testobjconfig twowindows .foo -window foo
} -cleanup {
    killTables
} -returnCodes error -result {bad window path name "foo"}
test config-4.104 {DoObjConfig - null window} -constraints testobjconfig -body {
    toplevel .bar
    testobjconfig twowindows .foo -window {}
} -cleanup {
1013
1014
1015
1016
1017
1018
1019
1020

1021
1022
1023
1024
1025
1026
1027
1013
1014
1015
1016
1017
1018
1019

1020
1021
1022
1023
1024
1025
1026
1027







-
+







test config-4.106 {DoObjConfig - new window} -constraints testobjconfig -body {
    toplevel .bar
    toplevel .blamph
    testobjconfig twowindows .foo -window .bar
    .foo configure -window .blamph
} -cleanup {
    killTables
} -returnCodes ok -result {0}
} -returnCodes ok -result 0
test config-4.107 {DoObjConfig - new window} -constraints testobjconfig -body {
    toplevel .bar
    toplevel .blamph
    testobjconfig twowindows .foo -window .bar
    .foo configure -window .blamph
    .foo cget -window
} -cleanup {
1201
1202
1203
1204
1205
1206
1207
1208

1209
1210
1211
1212
1213

1214
1215
1216
1217
1218
1219
1220

1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233

1234
1235
1236
1237
1238
1239
1240
1201
1202
1203
1204
1205
1206
1207

1208
1209
1210
1211
1212

1213
1214
1215
1216
1217
1218
1219

1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232

1233
1234
1235
1236
1237
1238
1239
1240







-
+




-
+






-
+












-
+







test config-7.3 {Tk_SetOptions - synonym} -constraints testobjconfig -body {
    .a configure -synonym blue
    .a cget -color
} -result {blue}
test config-7.4 {Tk_SetOptions - missing value} -constraints {
    testobjconfig
} -body {
    .a configure -color green -relief 
    .a configure -color green -relief
} -returnCodes error -result {value for "-relief" missing}
test config-7.5 {Tk_SetOptions - missing value} -constraints {
    testobjconfig
} -body {
    catch {.a configure -color green -relief} 
    catch {.a configure -color green -relief}
    .a cget -color
} -result {green}
test config-7.6 {Tk_SetOptions - saving old values} -constraints {
    testobjconfig
} -body {
    .a configure -color red -int 7 -relief raised -double 3.14159
    .a csave -color green -int 432 -relief sunken -double 2.0 -color bogus 
    .a csave -color green -int 432 -relief sunken -double 2.0 -color bogus
} -returnCodes error -result {unknown color name "bogus"}
test config-7.7 {Tk_SetOptions - saving old values} -constraints {
    testobjconfig
} -body {
    .a configure -color red -int 7 -relief raised -double 3.14159
    catch {.a csave -color green -int 432 -relief sunken -double 2.0 -color bogus}
    list [.a cget -color] [.a cget -int] [.a cget -relief] [.a cget -double]
} -result {red 7 raised 3.14159}

test config-7.8 {Tk_SetOptions - error in DoObjConfig call} -constraints {
    testobjconfig
} -body {
    .a configure -color bogus 
    .a configure -color bogus
} -returnCodes error -result {unknown color name "bogus"}
test config-7.9 {Tk_SetOptions - error in DoObjConfig call} -constraints {
    testobjconfig
} -body {
    catch {.a configure -color bogus}
    return $errorInfo
} -result {unknown color name "bogus"
1254
1255
1256
1257
1258
1259
1260
1261

1262
1263
1264
1265

1266
1267
1268
1269
1270
1271
1272
1254
1255
1256
1257
1258
1259
1260

1261
1262
1263
1264

1265
1266
1267
1268
1269
1270
1271
1272







-
+



-
+







    return $errorInfo
} -result {unknown color name "bogus"
    (processing "-synonym" option)
    invoked from within
".a configure -synonym bogus"}
test config-7.12 {Tk_SetOptions - returning mask} -constraints testobjconfig -body {
    format %x [.a configure -color red -int 7 -relief raised -double 3.14159]
} -result {226}
} -result 226
test config-7.13 {Tk_SetOptions - error in DoObjConfig with custom option} -constraints {
    testobjconfig
} -body {
    .a configure -custom bad 
    .a configure -custom bad
} -returnCodes error -result {expected good value, got "BAD"}
test config-7.14 {Tk_SetOptions - error in DoObjConfig with custom option} -constraints {
    testobjconfig
} -body {
    catch {.a configure -custom bad}
    return $errorInfo
} -result {expected good value, got "BAD"
1300
1301
1302
1303
1304
1305
1306
1307

1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324

1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341

1342
1343
1344
1345
1346
1347
1348
1300
1301
1302
1303
1304
1305
1306

1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323

1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340

1341
1342
1343
1344
1345
1346
1347
1348







-
+
















-
+
















-
+







test config-8.3 {Tk_RestoreSavedOptions - freeing object memory} -constraints {
    testobjconfig
} -body {
    testobjconfig alltypes .a
    .a csave -color green -color black -color blue -color #ffff00 -color #ff00ff
} -cleanup {
    killTables
} -result {32}
} -result 32
test config-8.4 {Tk_RestoreSavedOptions - boolean internal form} -constraints {
    testobjconfig
} -body {
    testobjconfig internal .a
    .a csave -boolean 0 -color bogus
} -cleanup {
    killTables
} -returnCodes error -match glob -result *
test config-8.5 {Tk_RestoreSavedOptions - boolean internal form} -constraints {
    testobjconfig
} -body {
    testobjconfig internal .a
    catch {.a csave -boolean 0 -color bogus}
    .a cget -boolean
} -cleanup {
    killTables
} -result {1}
} -result 1
test config-8.6 {Tk_RestoreSavedOptions - integer internal form} -constraints {
    testobjconfig
} -body {
    testobjconfig internal .a
    .a csave -integer 24 -color bogus
} -cleanup {
    killTables
} -returnCodes error -match glob -result *
test config-8.7 {Tk_RestoreSavedOptions - integer internal form} -constraints {
    testobjconfig
} -body {
    testobjconfig internal .a
    catch {.a csave -integer 24 -color bogus}
    .a cget -integer
} -cleanup {
    killTables
} -result {148962237}
} -result 148962237
test config-8.8 {Tk_RestoreSavedOptions - double internal form} -constraints {
    testobjconfig
} -body {
    testobjconfig internal .a
    catch {.a csave -double 62.4 -color bogus}
    .a cget -double
} -cleanup {
1616
1617
1618
1619
1620
1621
1622
1623

1624
1625
1626
1627

1628
1629
1630
1631
1632
1633
1634
1616
1617
1618
1619
1620
1621
1622

1623
1624
1625
1626

1627
1628
1629
1630
1631
1632
1633
1634







-
+



-
+








if {[testConstraint testobjconfig]} {
    testobjconfig internal .a
}
test config-12.1 {GetObjectForOption - boolean} -constraints testobjconfig -body {
    .a configure -boolean 0
    .a cget -boolean
} -result {0}
} -result 0
test config-12.2 {GetObjectForOption - integer} -constraints testobjconfig -body {
    .a configure -integer 1247
    .a cget -integer
} -result {1247}
} -result 1247
test config-12.3 {GetObjectForOption - double} -constraints testobjconfig -body {
    .a configure -double -88.82
    .a cget -double
} -result {-88.82}
test config-12.4 {GetObjectForOption - string} -constraints testobjconfig -body {
    .a configure -string "test value"
    .a cget -string
1676
1677
1678
1679
1680
1681
1682
1683

1684
1685
1686
1687
1688
1689
1690
1676
1677
1678
1679
1680
1681
1682

1683
1684
1685
1686
1687
1688
1689
1690







-
+







test config-12.13 {GetObjectForOption - anchor} -constraints testobjconfig -body {
    .a configure -anchor e
    .a cget -anchor
} -result {e}
test config-12.14 {GetObjectForOption - pixels} -constraints testobjconfig -body {
    .a configure -pixel 193.2
    .a cget -pixel
} -result {193}
} -result 193
test config-12.15 {GetObjectForOption - window} -constraints testobjconfig -body {
    .a configure -window .a
    .a cget -window
} -result {.a}
test config-12.16 {GetObjectForOption -custom} -constraints testobjconfig -body {
    .a configure -custom foobar
    .a cget -custom
Changes to tests/constraints.tcl.
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
16
17
18
19
20

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

41
42
43
44
45
46
47
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15
16
17
18
19

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

40
41
42
43
44
45
46
47







-
+











-
+



















-
+







if {[namespace exists tk::test]} {
    deleteWindows
    wm geometry . {}
    raise .
    return
}

package require Tk 8.4
package require tk
tk appname tktest
wm title . tktest
# If the main window isn't already mapped (e.g. because the tests are
# being run automatically) , specify a precise size for it so that the
# user won't have to position it manually.

if {![winfo ismapped .]} {
    wm geometry . +0+0
    update
}

package require tcltest 2.1
package require tcltest 2.2

namespace eval tk {
    namespace eval test {

	namespace export loadTkCommand
	proc loadTkCommand {} {
	    set tklib {}
	    foreach pair [info loaded {}] {
		foreach {lib pfx} $pair break
		if {$pfx eq "Tk"} {
		    set tklib $lib
		    break
		}
	    }
	    return [list load $tklib Tk]
	}

	namespace eval bg {
	    # Manage a background process.
	    # Replace with slave interp or thread?
	    # Replace with child interp or thread?
	    namespace import ::tcltest::interpreter
	    namespace import ::tk::test::loadTkCommand
	    namespace export setup cleanup do

	    proc cleanup {} {
		variable fd
		# catch in case the background process has closed $fd
193
194
195
196
197
198
199
200
201


202
203
204
205
206
207
208
193
194
195
196
197
198
199


200
201
202
203
204
205
206
207
208







-
-
+
+







testConstraint haveDISPLAY [expr {[info exists env(DISPLAY)] && [testConstraint x11]}]
testConstraint altDisplay  [info exists env(TK_ALT_DISPLAY)]
testConstraint noExceed [expr {
    ![testConstraint unix] || [catch {font actual "\{xyz"}]
}]

# constraints for testing facilities defined in the tktest executable...
testConstraint testImageType [expr {[lsearch [image types] test] >= 0}]
testConstraint testOldImageType [expr {[lsearch [image types] oldtest] >= 0}]
testConstraint testImageType [expr {"test" in [image types]}]
testConstraint testOldImageType [expr {"oldtest" in [image types]}]
testConstraint testbitmap    [llength [info commands testbitmap]]
testConstraint testborder    [llength [info commands testborder]]
testConstraint testcbind     [llength [info commands testcbind]]
testConstraint testclipboard [llength [info commands testclipboard]]
testConstraint testcolor     [llength [info commands testcolor]]
testConstraint testcursor    [llength [info commands testcursor]]
testConstraint testembed     [llength [info commands testembed]]
243
244
245
246
247
248
249
250

251
252
253

254
255
256
257
258
259
260
243
244
245
246
247
248
249

250
251
252

253
254
255
256
257
258
259
260







-
+


-
+







testConstraint pseudocolor8 [expr {
    ([catch {
	toplevel .t -visual {pseudocolor 8} -colormap new
    }] == 0) && ([winfo depth .t] == 8)
}]
destroy .t
testConstraint haveTruecolor24 [expr {
    [lsearch -exact [winfo visualsavailable .] {truecolor 24}] >= 0
    {truecolor 24} in [winfo visualsavailable .]
}]
testConstraint haveGrayscale8 [expr {
    [lsearch -exact [winfo visualsavailable .] {grayscale 8}] >= 0
    {grayscale 8} in [winfo visualsavailable .]
}]
testConstraint defaultPseudocolor8 [expr {
    ([winfo visual .] eq "pseudocolor") && ([winfo depth .] == 8)
}]

# constraint based on whether our display is secure
setupbg
Changes to tests/cursor.test.
1
2
3
4
5
6


7
8
9
10
11
12
13
1
2
3
4


5
6
7
8
9
10
11
12
13




-
-
+
+







# This file is a Tcl script to test out the procedures in the file
# tkCursor.c.  It is organized in the standard white-box fashion for
# Tcl tests.
#
# Copyright (c) 1998 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1998 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
namespace import ::tcltest::*
eval tcltest::configure $argv
tcltest::loadTestedCommands

104
105
106
107
108
109
110
111

112
113
114
115
116
117
118
104
105
106
107
108
109
110

111
112
113
114
115
116
117
118







-
+







	set wincur(file) ""
} -body {
	setWincur wincur
    button .b -cursor [list @$wincur(file)]
} -cleanup {
    destroy .b
	removeDirectory $wincur(dir)
	unset wincur	
	unset wincur
} -result {.b}
test cursor-2.4 {Tk_GetCursor procedure: cursor specs are lists} -constraints {
    win
} -setup {
	unset -nocomplain wincur
	set wincur(file) ""
} -body {
Changes to tests/dialog.test.
21
22
23
24
25
26
27
28

29
30
31
32
33
34
35
36
37
38
39

40
41
42
43
44

45
46
47
48
49
50
51
52
53
54

55
56
57
58
59
60
61
62
63

64
65
66
67
21
22
23
24
25
26
27

28
29
30
31
32
33
34
35
36
37
38

39
40
41
42
43

44
45
46
47
48
49
50
51
52
53

54
55
56
57
58
59
60
61
62

63
64
65
66
67







-
+










-
+




-
+









-
+








-
+





test dialog-2.1 {tk_dialog operation} -setup {
    proc PressButton {btn} {
        if {![winfo ismapped $btn]} {
            update
        }
        event generate $btn <Enter>
        event generate $btn <1> -x 5 -y 5
        event generate $btn <Button-1> -x 5 -y 5
        event generate $btn <ButtonRelease-1> -x 5 -y 5
    }
} -body {
    set x [after 5000 [list set tk::Priv(button) "no response"]]
    after 100 PressButton .d.button0
    set res [tk_dialog .d foo foo info 0 click]
    after cancel $x
    return $res
} -cleanup {
    destroy .d
} -result {0}
} -result 0
test dialog-2.2 {tk_dialog operation} -setup {
    proc HitReturn {w} {
        event generate $w <Enter>
        focus -force $w
        event generate $w <KeyPress> -keysym Return
        event generate $w <Key> -keysym Return
    }
} -body {
    set x [after 5000 [list set tk::Priv(button) "no response"]]
    after 100 HitReturn .d
    set res [tk_dialog .d foo foo info 1 click default]
    after cancel $x
    return $res
} -cleanup {
    destroy .d
} -result {1}
} -result 1
test dialog-2.3 {tk_dialog operation} -body {
    set x [after 5000 [list set tk::Priv(button) "no response"]]
    after 100 destroy .d
    set res [tk_dialog .d foo foo info 0 click]
    after cancel $x
    return $res
} -cleanup {
    destroy .b
} -result {-1}
} -result -1

cleanupTests
return

Changes to tests/embed.test.
1
2
3
4


5
6
7
8
9
10
11
1
2


3
4
5
6
7
8
9
10
11


-
-
+
+







# This file is a Tcl script to test out embedded Windows.
#
# Copyright (c) 1996-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1996-1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
namespace import ::tcltest::*
eval tcltest::configure $argv
tcltest::loadTestedCommands

Changes to tests/entry.test.
1
2
3
4
5
6



7
8
9
10
11
12
13




14

15
16
17
18
19

20
21
22
23
24
25
26
1
2
3



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

24
25
26
27
28
29
30
31



-
-
-
+
+
+







+
+
+
+

+




-
+







# This file is a Tcl script to test entry widgets in Tk.  It is
# organized in the standard fashion for Tcl tests.
#
# Copyright (c) 1994 The Regents of the University of California.
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1994 The Regents of the University of California.
# Copyright © 1994-1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
namespace import ::tcltest::*
eval tcltest::configure $argv
tcltest::loadTestedCommands

testConstraint failsOnUbuntu [expr {![info exists ::env(CI)] || ![string match Linux $::tcl_platform(os)]}]
testConstraint failsOnUbuntuNoXft [expr {[testConstraint failsOnUbuntu] || (![catch {tk::pkgconfig get fontsystem} fs] && ($fs eq "xft"))}]
testConstraint failsOnXQuarz [expr {$tcl_platform(os) ne "Darwin" || [tk windowingsystem] ne "x11" }]

# For xscrollcommand
set scrollInfo {}
proc scroll args {
        global scrollInfo
        set scrollInfo $args
}
# For trace variable 
# For trace variable
proc override args {
        global x
        set x 12345
}

# Procedures used in widget VALIDATION tests
proc doval {W d i P s S v V} {
65
66
67
68
69
70
71
72

73
74
75
76
77
78
79
70
71
72
73
74
75
76

77
78
79
80
81
82
83
84







-
+







    pack .e
    update
} -body {
    .e configure -bd 4
    .e cget -bd
} -cleanup {
    destroy .e
} -result {4}
} -result 4
test entry-1.4 {configuration option: "bd" for entry} -setup {
    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .e
    update
} -body {
    .e configure -bd badValue
} -cleanup {
102
103
104
105
106
107
108
109

110
111
112

113
114
115
116
117
118
119
107
108
109
110
111
112
113

114
115
116

117
118
119
120
121
122
123
124







-
+


-
+








test entry-1.7 {configuration option: "borderwidth" for entry} -setup {
    entry .e -highlightthickness 2 -font {Helvetica -12 bold}
    pack .e
    update
} -body {
    .e configure -borderwidth 1.3
    .e cget -borderwidth 
    .e cget -borderwidth
} -cleanup {
    destroy .e
} -result {1}
} -result 1
test entry-1.8 {configuration option: "borderwidth" for entry} -setup {
    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .e
    update
} -body {
    .e configure -borderwidth badValue
} -cleanup {
185
186
187
188
189
190
191
192

193
194
195
196
197
198
199
190
191
192
193
194
195
196

197
198
199
200
201
202
203
204







-
+







    pack .e
    update
} -body {
    .e configure -exportselection yes
    .e cget -exportselection
} -cleanup {
    destroy .e
} -result {1}
} -result 1
test entry-1.16 {configuration option: "exportselection" for entry} -setup {
    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .e
    update
} -body {
    .e configure -exportselection xyzzy
} -cleanup {
217
218
219
220
221
222
223
224

225
226
227
228
229
230
231
232
233
234

235
236
237
238
239
240
241
222
223
224
225
226
227
228

229
230
231
232
233
234
235
236
237
238

239
240
241
242
243
244
245
246







-
+









-
+







} -body {
    .e configure -fg non-existent
} -cleanup {
    destroy .e
} -returnCodes {error} -result {unknown color name "non-existent"}

test entry-1.19 {configuration option: "font" for entry} -setup {
    entry .e -borderwidth 2 -highlightthickness 2 
    entry .e -borderwidth 2 -highlightthickness 2
    pack .e
    update
} -body {
    .e configure -font {Helvetica -12}
    .e cget -font
} -cleanup {
    destroy .e
} -result {Helvetica -12}
test entry-1.20 {configuration option: "font" for entry} -setup {
    entry .e -borderwidth 2 -highlightthickness 2 
    entry .e -borderwidth 2 -highlightthickness 2
    pack .e
    update
} -body {
    .e configure -font {}
} -cleanup {
    destroy .e
} -returnCodes {error} -result {font "" doesn't exist}
305
306
307
308
309
310
311
312

313
314
315
316
317
318
319
320
321
322

323
324
325
326
327
328
329
310
311
312
313
314
315
316

317
318
319
320
321
322
323
324
325
326

327
328
329
330
331
332
333
334







-
+









-
+







    pack .e
    update
} -body {
    .e configure -highlightthickness 6
    .e cget -highlightthickness
} -cleanup {
    destroy .e
} -result {6}
} -result 6
test entry-1.28 {configuration option: "highlightthickness" for entry} -setup {
    entry .e -borderwidth 2 -font {Helvetica -12 bold}
    pack .e
    update
} -body {
    .e configure -highlightthickness -2
    .e cget -highlightthickness
} -cleanup {
    destroy .e
} -result {0}
} -result 0
test entry-1.29 {configuration option: "highlightthickness" for entry} -setup {
    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .e
    update
} -body {
    .e configure -highlightthickness badValue
} -cleanup {
355
356
357
358
359
360
361
362

363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382

383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402

403
404
405
406
407
408
409
360
361
362
363
364
365
366

367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386

387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406

407
408
409
410
411
412
413
414







-
+



















-
+



















-
+







    pack .e
    update
} -body {
    .e configure -insertborderwidth 1.3
    .e cget -insertborderwidth
} -cleanup {
    destroy .e
} -result {1}
} -result 1
test entry-1.33 {configuration option: "insertborderwidth" for entry} -setup {
    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .e
    update
} -body {
    .e configure -insertborderwidth 2.6x
} -cleanup {
    destroy .e
} -returnCodes {error} -result {bad screen distance "2.6x"}

test entry-1.34 {configuration option: "insertofftime" for entry} -setup {
    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .e
    update
} -body {
    .e configure -insertofftime 100
    .e cget -insertofftime
} -cleanup {
    destroy .e
} -result {100}
} -result 100
test entry-1.35 {configuration option: "insertofftime" for entry} -setup {
    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .e
    update
} -body {
    .e configure -insertofftime 3.2
} -cleanup {
    destroy .e
} -returnCodes {error} -result {expected integer but got "3.2"}

test entry-1.36 {configuration option: "insertontime" for entry} -setup {
    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .e
    update
} -body {
    .e configure -insertontime 100
    .e cget -insertontime
} -cleanup {
    destroy .e
} -result {100}
} -result 100
test entry-1.37 {configuration option: "insertontime" for entry} -setup {
    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .e
    update
} -body {
    .e configure -insertontime 3.2
} -cleanup {
508
509
510
511
512
513
514
515

516
517
518
519
520
521
522
513
514
515
516
517
518
519

520
521
522
523
524
525
526
527







-
+







    pack .e
    update
} -body {
    .e configure -selectborderwidth 1.3
    .e cget -selectborderwidth
} -cleanup {
    destroy .e
} -result {1}
} -result 1
test entry-1.48 {configuration option: "selectborderwidth" for entry} -setup {
    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .e
    update
} -body {
    .e configure -selectborderwidth badValue
} -cleanup {
601
602
603
604
605
606
607
608

609
610
611
612
613
614
615
606
607
608
609
610
611
612

613
614
615
616
617
618
619
620







-
+







    pack .e
    update
} -body {
    .e configure -width 402
    .e cget -width
} -cleanup {
    destroy .e
} -result {402}
} -result 402
test entry-1.57 {configuration option: "width" for entry} -setup {
    entry .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .e
    update
} -body {
    .e configure -width 3p
} -cleanup {
623
624
625
626
627
628
629

















630
631
632
633
634
635
636
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







} -body {
    .e configure -xscrollcommand {Some command}
    .e cget -xscrollcommand
} -cleanup {
    destroy .e
} -result {Some command}

test entry-1.59 {configuration option: "-placeholder"} -setup {
    pack [entry .e]
} -body {
    .e configure -placeholder {Some text}
    .e cget -placeholder
} -cleanup {
    destroy .e
} -result {Some text}

test entry-1.60 {configuration option: "-placeholderforeground"} -setup {
    pack [entry .e]
} -body {
    .e configure -placeholder {Some text} -placeholderforeground red
    .e cget -placeholderforeground
} -cleanup {
    destroy .e
} -result {red}


test entry-2.1 {Tk_EntryCmd procedure} -body {
    entry
} -returnCodes error -result {wrong # args: should be "entry pathName ?-option value ...?"}
test entry-2.2 {Tk_EntryCmd procedure} -body {
    entry gorp
658
659
660
661
662
663
664
665

666
667
668
669
670
671
672
673
674

675
676
677
678
679
680
681
682
683

684
685
686
687
688
689
690
691
692

693
694
695
696
697
698
699
700
701

702
703
704
705
706
707
708
709
710

711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729

730
731
732
733
734

735
736
737
738
739
740
741
742

743
744
745
746
747

748
749
750
751
752
753

754
755
756
757
758
759
760
761
762
763
764
765

766
767
768
769

770
771
772
773
774
775

776
777
778
779
780
781
782

783
784
785
786
787
788
789

790
791
792
793
794
795
796

797
798
799
800
801
802

803
804

805
806
807
808
809
810
811

812
813

814
815
816
817
818
819
820

821
822
823
824
825
826
827

828
829

830
831
832
833
834
835
836

837
838
839
840
841
842
843

844
845
846
847
848
849
850

851
852
853
854
855
856
857
858
859

860
861
862
863
864
865
866

867
868

869
870
871
872
873
874
875

876
877
878
879

880
881
882
883

884
885
886
887

888
889
890
891

892
893
894
895
896

897
898
899
900

901
902
903
904
905
906
907

908
909
910
911

912
913
914
915
916
917
918
919
920

921
922
923
924

925
926
927
928
929
930
931
932
933

934
935

936
937
938
939
940
941
942

943
944
945
946
947
948
949

950
951
952
953
954
955
956

957
958
959
960
961
962
963

964
965

966
967
968
969
970
971
972

973
974
975
976
977
978
979

980
981
982
983
984
985
986
987
988

989
990
991
992
993
994
995
996
997

998
999
1000

1001
1002
1003
1004
1005
1006

1007
1008
1009
1010
1011
1012
1013

1014
1015
1016
1017
1018
1019
1020

1021
1022
1023
1024
1025
1026
1027
1028
1029

1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040

1041
1042
1043
1044
1045
1046
1047
1048
1049

1050
1051
1052
1053

1054
1055
1056
1057
1058
1059
1060
1061
1062

1063
1064

1065
1066
1067
1068
1069
1070
1071

1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082

1083
1084
1085
1086
1087
1088
1089
1090
1091

1092
1093
1094
1095
1096
1097
1098
1099
1100

1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111

1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122

1123
1124

1125
1126
1127
1128
1129
1130
1131

1132
1133
1134
1135
1136
1137
1138
1139

1140
1141
1142
1143
1144
1145
1146

1147
1148
1149
1150
1151
1152
1153

1154
1155
1156
1157
1158
1159
1160

1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174

1175
1176
1177
1178
1179
1180
1181
1182
1183

1184
1185
1186
1187
1188
1189
1190
1191

1192
1193
1194
1195

1196
1197
1198
1199
1200
1201
1202
1203
1204

1205
1206
1207
1208

1209
1210
1211
1212
1213
1214
1215
1216
1217

1218
1219
1220
1221
1222
1223
1224
680
681
682
683
684
685
686

687
688
689
690
691
692
693
694
695

696
697
698
699
700
701
702
703
704

705
706
707
708
709
710
711
712
713

714
715
716
717
718
719
720
721
722

723
724
725
726
727
728
729
730
731

732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750

751
752
753
754
755

756
757
758
759
760
761
762
763

764
765
766
767
768

769
770
771
772
773
774

775
776
777
778
779
780
781
782
783
784
785
786

787
788
789
790

791
792
793
794
795
796

797
798
799
800
801
802
803

804
805
806
807
808
809
810

811
812
813
814
815
816
817

818
819
820
821
822
823

824
825

826
827
828
829
830
831
832

833
834

835
836
837
838
839
840
841

842
843
844
845
846
847
848

849
850

851
852
853
854
855
856
857

858
859
860
861
862
863
864

865
866
867
868
869
870
871

872
873
874
875
876
877
878
879
880

881
882
883
884
885
886
887

888
889

890
891
892
893
894
895
896

897
898
899
900

901
902
903
904

905
906
907
908

909
910
911
912

913
914
915
916
917

918
919
920
921

922
923
924
925
926
927
928

929
930
931
932

933
934
935
936
937
938
939
940
941

942
943
944
945

946
947
948
949
950
951
952
953
954

955
956

957
958
959
960
961
962
963

964
965
966
967
968
969
970

971
972
973
974
975
976
977

978
979
980
981
982
983
984

985
986

987
988
989
990
991
992
993

994
995
996
997
998
999
1000

1001
1002
1003
1004
1005
1006
1007
1008
1009

1010
1011
1012
1013
1014
1015
1016
1017
1018

1019
1020
1021

1022
1023
1024
1025
1026
1027

1028
1029
1030
1031
1032
1033
1034

1035
1036
1037
1038
1039
1040
1041

1042
1043
1044
1045
1046
1047
1048
1049
1050

1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061

1062
1063
1064
1065
1066
1067
1068
1069
1070

1071
1072
1073
1074

1075
1076
1077
1078
1079
1080
1081
1082
1083

1084
1085

1086
1087
1088
1089
1090
1091
1092

1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103

1104
1105
1106
1107
1108
1109
1110
1111
1112

1113
1114
1115
1116
1117
1118
1119
1120
1121

1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132

1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143

1144
1145

1146
1147
1148
1149
1150
1151
1152

1153
1154
1155
1156
1157
1158
1159
1160

1161
1162
1163
1164
1165
1166
1167

1168
1169
1170
1171
1172
1173
1174

1175
1176
1177
1178
1179
1180
1181

1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195

1196
1197
1198
1199
1200
1201
1202
1203
1204

1205
1206
1207
1208
1209
1210
1211
1212

1213
1214
1215
1216

1217
1218
1219
1220
1221
1222
1223
1224
1225

1226
1227
1228
1229

1230
1231
1232
1233
1234
1235
1236
1237
1238

1239
1240
1241
1242
1243
1244
1245
1246







-
+








-
+








-
+








-
+








-
+








-
+


















-
+




-
+







-
+




-
+





-
+











-
+



-
+





-
+






-
+






-
+






-
+





-
+

-
+






-
+

-
+






-
+






-
+

-
+






-
+






-
+






-
+








-
+






-
+

-
+






-
+



-
+



-
+



-
+



-
+




-
+



-
+






-
+



-
+








-
+



-
+








-
+

-
+






-
+






-
+






-
+






-
+

-
+






-
+






-
+








-
+








-
+


-
+





-
+






-
+






-
+








-
+










-
+








-
+



-
+








-
+

-
+






-
+










-
+








-
+








-
+










-
+










-
+

-
+






-
+







-
+






-
+






-
+






-
+













-
+








-
+







-
+



-
+








-
+



-
+








-
+







    entry .e
} -cleanup {
    destroy .e
} -result {.e}


test entry-3.1 {EntryWidgetCmd procedure} -setup {
    entry .e 
    entry .e
    pack .e
    update
} -body {
    .e
} -cleanup {
    destroy .e
} -returnCodes error -result {wrong # args: should be ".e option ?arg ...?"}
test entry-3.2 {EntryWidgetCmd procedure, "bbox" widget command} -setup {
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
    update
} -body {
    .e bbox
} -cleanup {
    destroy .e
} -returnCodes error -result {wrong # args: should be ".e bbox index"}
test entry-3.3 {EntryWidgetCmd procedure, "bbox" widget command} -setup {
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
    update
} -body {
    .e bbox a b
} -cleanup {
    destroy .e
} -returnCodes error -result {wrong # args: should be ".e bbox index"}
test entry-3.4 {EntryWidgetCmd procedure, "bbox" widget command} -setup {
    entry .e 
    entry .e
    pack .e
    update
} -body {
    .e bbox bogus
} -cleanup {
    destroy .e
} -returnCodes error -result {bad entry index "bogus"}
test entry-3.5 {EntryWidgetCmd procedure, "bbox" widget command} -setup {
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
    update
} -body {
   .e bbox 0
} -cleanup {
    destroy .e
} -result [list 5 5 0 $cy]

# Previously the result was count using previousli counted font measurements 
# Previously the result was count using previousli counted font measurements
# and metrics. It was changed to less verbose solution - the result is the one
# that passes fonts constraint (this concerns tests 3.6, 3.7, 3.8, 3.10)
test entry-3.6 {EntryWidgetCmd procedure, "bbox" widget command} -constraints {
	fonts
} -setup {
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
    update
} -body {
# Tcl_UtfAtIndex(): no utf chars
    .e insert 0 "abc"
    list [.e bbox 3] [.e bbox end]
} -cleanup {
    destroy .e
} -result {{19 5 7 13} {19 5 7 13}}
test entry-3.7 {EntryWidgetCmd procedure, "bbox" widget command} -constraints {
	fonts
} -setup {
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
    update
} -body {
# Tcl_UtfAtIndex(): utf at end
    .e insert 0 "ab\u4e4e"
    .e insert 0 "ab"
    .e bbox end
} -cleanup {
    destroy .e
} -result {19 5 12 13}
test entry-3.8 {EntryWidgetCmd procedure, "bbox" widget command} -constraints {
	fonts
} -setup {
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
    update
} -body {
# Tcl_UtfAtIndex(): utf before index
    .e insert 0 "ab\u4e4ec"
    .e insert 0 "abc"
    .e bbox 3
} -cleanup {
    destroy .e
} -result {31 5 7 13}
test entry-3.9 {EntryWidgetCmd procedure, "bbox" widget command} -setup {
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
    update
} -body {
# Tcl_UtfAtIndex(): no chars
    .e bbox end
} -cleanup {
    destroy .e
} -result "5 5 0 $cy"
test entry-3.10 {EntryWidgetCmd procedure, "bbox" widget command} -constraints {
	fonts
} -setup {
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
    update
} -body {
    .e insert 0 "abcdefghij\u4e4eklmnop"
    .e insert 0 "abcdefghijklmnop"
    list [.e bbox 0] [.e bbox 1] [.e bbox 10] [.e bbox end]
} -cleanup {
    destroy .e
} -result {{5 5 7 13} {12 5 7 13} {75 5 12 13} {122 5 7 13}}
test entry-3.11 {EntryWidgetCmd procedure, "cget" widget command} -setup {
    entry .e 
    entry .e
} -body {
    .e cget
} -cleanup {
    destroy .e
} -returnCodes error -result {wrong # args: should be ".e cget option"}
test entry-3.12 {EntryWidgetCmd procedure, "cget" widget command} -setup {
    entry .e 
    entry .e
} -body {
    .e cget a b
} -cleanup {
    destroy .e
} -returnCodes error -result {wrong # args: should be ".e cget option"}
test entry-3.13 {EntryWidgetCmd procedure, "cget" widget command} -setup {
    entry .e 
    entry .e
} -body {
    .e cget -gorp
} -cleanup {
    destroy .e
} -returnCodes error -result {unknown option "-gorp"}
test entry-3.14 {EntryWidgetCmd procedure, "cget" widget command} -setup {
    entry .e 
    entry .e
} -body {
    .e configure -bd 4
    .e cget -bd
} -cleanup {
    destroy .e
} -result {4}
} -result 4
test entry-3.15 {EntryWidgetCmd procedure, "configure" widget command} -setup {
    entry .e 
    entry .e
    pack .e
    update
} -body {
    llength [.e configure]
} -cleanup {
    destroy .e
} -result {36}
} -result 38
test entry-3.16 {EntryWidgetCmd procedure, "configure" widget command} -setup {
    entry .e 
    entry .e
} -body {
    .e configure -foo
} -cleanup {
    destroy .e
} -returnCodes error -result {unknown option "-foo"}
test entry-3.17 {EntryWidgetCmd procedure, "configure" widget command} -setup {
    entry .e 
    entry .e
} -body {
    .e configure -bd 4
    .e configure -bg #ffffff
    lindex [.e configure -bd] 4
} -cleanup {
    destroy .e
} -result {4}
} -result 4
test entry-3.18 {EntryWidgetCmd procedure, "delete" widget command} -setup {
    entry .e 
    entry .e
} -body {
    .e delete
} -cleanup {
    destroy .e
} -returnCodes error -result {wrong # args: should be ".e delete firstIndex ?lastIndex?"}
test entry-3.19 {EntryWidgetCmd procedure, "delete" widget command} -setup {
    entry .e 
    entry .e
} -body {
    .e delete a b c
} -cleanup {
    destroy .e
} -returnCodes error -result {wrong # args: should be ".e delete firstIndex ?lastIndex?"}
test entry-3.20 {EntryWidgetCmd procedure, "delete" widget command} -setup {
    entry .e 
    entry .e
} -body {
    .e delete foo
} -cleanup {
    destroy .e
} -returnCodes error -result {bad entry index "foo"}
test entry-3.21 {EntryWidgetCmd procedure, "delete" widget command} -setup {
    entry .e 
    entry .e
} -body {
    .e delete 0 bar
} -cleanup {
    destroy .e
} -returnCodes error -result {bad entry index "bar"}
test entry-3.22 {EntryWidgetCmd procedure, "delete" widget command} -setup {
    entry .e
    pack .e
    update 
    update
} -body {
    .e insert end "01234567890"
    .e delete 2 4
    .e get
} -cleanup {
    destroy .e
} -result {014567890}
} -result 014567890
test entry-3.23 {EntryWidgetCmd procedure, "delete" widget command} -setup {
    entry .e 
    entry .e
} -body {
    .e insert end "01234567890"
    .e delete 6
    .e get
} -cleanup {
    destroy .e
} -result {0123457890}
} -result 0123457890
test entry-3.24 {EntryWidgetCmd procedure, "delete" widget command} -setup {
    entry .e
    pack .e
    update 
    update
    set x {}
} -body {
# UTF
    .e insert end "01234\u4e4e67890"
    .e insert end "0123467890"
    .e delete 6
    lappend x [.e get]
    .e delete 0 end
    .e insert end "012345\u4e4e7890"
    .e insert end "0123457890"
    .e delete 6
    lappend x [.e get]
    .e delete 0 end
    .e insert end "0123456\u4e4e890"
    .e insert end "0123456890"
    .e delete 6
    lappend x [.e get]
} -cleanup {
    destroy .e
} -result [list "01234\u4e4e7890" "0123457890" "012345\u4e4e890"]
} -result [list "012347890" "0123457890" "012345890"]
test entry-3.25 {EntryWidgetCmd procedure, "delete" widget command} -setup {
    entry .e
    pack .e
    update  
    update
} -body {
    .e insert end "01234567890"
    .e delete 6 5
    .e get
} -cleanup {
    destroy .e
} -result {01234567890}
} -result 01234567890
test entry-3.26 {EntryWidgetCmd procedure, "delete" widget command} -setup {
    entry .e
    pack .e
    update  
    update
} -body {
    .e insert end "01234567890"
    .e configure -state disabled
    .e delete 2 8
    .e configure -state normal
    .e get
} -cleanup {
    destroy .e
} -result {01234567890}
} -result 01234567890
test entry-3.26a {EntryWidgetCmd procedure, "delete" widget command} -setup {
    entry .e
    pack .e
    update  
    update
} -body {
    .e insert end "01234567890"
    .e configure -state readonly
    .e delete 2 8
    .e configure -state normal
    .e get
} -cleanup {
    destroy .e
} -result {01234567890}
} -result 01234567890
test entry-3.27 {EntryWidgetCmd procedure, "get" widget command} -setup {
    entry .e 
    entry .e
} -body {
    .e get foo
} -cleanup {
    destroy .e
} -returnCodes error -result {wrong # args: should be ".e get"}
test entry-3.28 {EntryWidgetCmd procedure, "icursor" widget command} -setup {
    entry .e 
    entry .e
} -body {
    .e icursor
} -cleanup {
    destroy .e
} -returnCodes error -result {wrong # args: should be ".e icursor pos"}
test entry-3.29 {EntryWidgetCmd procedure, "icursor" widget command} -setup {
    entry .e 
    entry .e
} -body {
    .e icursor foo
} -cleanup {
    destroy .e
} -returnCodes error -result {bad entry index "foo"}
test entry-3.30 {EntryWidgetCmd procedure, "icursor" widget command} -setup {
    entry .e 
    entry .e
} -body {
    .e insert end "01234567890"
    .e icursor 4
    .e index insert
} -cleanup {
    destroy .e
} -result {4}
} -result 4
test entry-3.31 {EntryWidgetCmd procedure, "index" widget command} -setup {
    entry .e 
    entry .e
} -body {
    .e in
} -cleanup {
    destroy .e
} -returnCodes error -result {ambiguous option "in": must be bbox, cget, configure, delete, get, icursor, index, insert, scan, selection, validate, or xview}
test entry-3.32 {EntryWidgetCmd procedure, "index" widget command} -setup {
    entry .e 
    entry .e
} -body {
    .e index
} -cleanup {
    destroy .e
} -returnCodes error -result {wrong # args: should be ".e index string"}
test entry-3.33 {EntryWidgetCmd procedure, "index" widget command} -setup {
    entry .e 
    entry .e
} -body {
    .e index foo
} -cleanup {
    destroy .e
} -returnCodes error -result {bad entry index "foo"}
test entry-3.34 {EntryWidgetCmd procedure, "index" widget command} -setup {
    entry .e
    pack .e
    update  
    update
} -body {
    .e index 0
} -cleanup {
    destroy .e
} -returnCodes {ok} -match glob -result {*}
test entry-3.35 {EntryWidgetCmd procedure, "index" widget command} -setup {
    entry .e
    pack .e
    update  
    update
} -body {
# UTF
    .e insert 0 abc\u4e4e\u0153def
    .e insert 0 abc乎œdef
    list [.e index 3] [.e index 4] [.e index end]
} -cleanup {
    destroy .e
} -result {3 4 8}
test entry-3.36 {EntryWidgetCmd procedure, "insert" widget command} -setup {
    entry .e 
    entry .e
} -body {
    .e insert a
} -cleanup {
    destroy .e
} -returnCodes error -result {wrong # args: should be ".e insert index text"}
test entry-3.37 {EntryWidgetCmd procedure, "insert" widget command} -setup {
    entry .e 
    entry .e
} -body {
    .e insert a b c
} -cleanup {
    destroy .e
} -returnCodes error -result {wrong # args: should be ".e insert index text"}
test entry-3.38 {EntryWidgetCmd procedure, "insert" widget command} -setup {
    entry .e 
    entry .e
} -body {
    .e insert foo Text
} -cleanup {
    destroy .e
} -returnCodes error -result {bad entry index "foo"}
test entry-3.39 {EntryWidgetCmd procedure, "insert" widget command} -setup {
    entry .e
    pack .e
    update  
    update
} -body {
    .e insert end "01234567890"
    .e insert 3 xxx
    .e get
} -cleanup {
    destroy .e
} -result {012xxx34567890}
test entry-3.40 {EntryWidgetCmd procedure, "insert" widget command} -setup {
    entry .e
    pack .e
    update  
    update
} -body {
    .e insert end "01234567890"
    .e configure -state disabled
    .e insert 3 xxx
    .e configure -state normal
    .e get
} -cleanup {
    destroy .e
} -result {01234567890}
} -result 01234567890
test entry-3.40a {EntryWidgetCmd procedure, "insert" widget command} -setup {
    entry .e
    pack .e
    update  
    update
} -body {
    .e insert end "01234567890"
    .e configure -state readonly
    .e insert 3 xxx
    .e configure -state normal
    .e get
} -cleanup {
    destroy .e
} -result {01234567890}
} -result 01234567890
test entry-3.41 {EntryWidgetCmd procedure, "insert" widget command} -setup {
    entry .e 
    entry .e
} -body {
    .e insert a b c
} -cleanup {
    destroy .e
} -returnCodes error -result {wrong # args: should be ".e insert index text"}
test entry-3.42 {EntryWidgetCmd procedure, "scan" widget command} -setup {
    entry .e 
    entry .e
    pack .e
    update
} -body {
    .e scan a
} -cleanup {
    destroy .e
} -returnCodes error -result {wrong # args: should be ".e scan mark|dragto x"}
test entry-3.43 {EntryWidgetCmd procedure, "scan" widget command} -setup {
    entry .e
    pack .e
    update 
    update
} -body {
    .e scan a b c
} -cleanup {
    destroy .e
} -returnCodes error -result {wrong # args: should be ".e scan mark|dragto x"}
test entry-3.44 {EntryWidgetCmd procedure, "scan" widget command} -setup {
    entry .e
    pack .e
    update 
    update
} -body {
    .e scan foobar 20
} -cleanup {
    destroy .e
} -returnCodes error -result {bad scan option "foobar": must be mark or dragto}
test entry-3.45 {EntryWidgetCmd procedure, "scan" widget command} -setup {
    entry .e
    pack .e
    update 
    update
} -body {
    .e scan mark 20.1
} -cleanup {
    destroy .e
} -returnCodes error -result {expected integer but got "20.1"}

# This test is non-portable because character sizes vary.
test entry-3.46 {EntryWidgetCmd procedure, "scan" widget command} -constraints {
    fonts
} -setup {
    entry .e -font {Helvetica -12} -borderwidth 2 -highlightthickness 2 
    entry .e -font {Helvetica -12} -borderwidth 2 -highlightthickness 2
    pack .e
    update
} -body {
    .e insert end "This is quite a long string, in fact a "
    .e insert end "very very long string"
    .e scan mark 30
    .e scan dragto 28
    .e index @0
} -cleanup {
    destroy .e
} -result {2}
} -result 2
test entry-3.47 {EntryWidgetCmd procedure, "select" widget command} -setup {
    entry .e 
    entry .e
} -body {
    .e select
} -cleanup {
    destroy .e
} -returnCodes error -result {wrong # args: should be ".e selection option ?index?"}
test entry-3.48 {EntryWidgetCmd procedure, "select" widget command} -setup {
    entry .e 
    entry .e
} -body {
    .e select foo
} -cleanup {
    destroy .e
} -returnCodes error -result {bad selection option "foo": must be adjust, clear, from, present, range, or to}

test entry-3.49 {EntryWidgetCmd procedure, "select clear" widget command} -setup {
    entry .e 
    entry .e
} -body {
    .e select clear gorp
} -cleanup {
    destroy .e
} -returnCodes error -result {wrong # args: should be ".e selection clear"}
test entry-3.50 {EntryWidgetCmd procedure, "select clear" widget command} -setup {
    entry .e 
    entry .e
} -body {
    .e insert end "0123456789"
    .e select from 1
    .e select to 4
    update
    .e select clear
    selection get 
    selection get
} -cleanup {
    destroy .e
} -returnCodes error -result {PRIMARY selection doesn't exist or form "STRING" not defined}
test entry-3.50.1 {EntryWidgetCmd procedure, "select clear" widget command} -setup {
    entry .e
    pack .e
    update  
    update
} -body {
    .e insert end "0123456789"
    .e select from 1
    .e select to 4
    update
    .e select clear
    catch {selection get}
    selection own
} -cleanup {
    destroy .e
} -result {.e}

test entry-3.51 {EntryWidgetCmd procedure, "selection present" widget command} -setup {
    entry .e 
    entry .e
} -body {
    .e selection present foo
} -cleanup {
    destroy .e
} -returnCodes error -result {wrong # args: should be ".e selection present"}
test entry-3.52 {EntryWidgetCmd procedure, "selection present" widget command} -setup {
    entry .e
    pack .e
    update  
    update
} -body {
    .e insert end 0123456789
    .e select from 3
    .e select to 6
    .e selection present
} -cleanup {
    destroy .e
} -result {1}
} -result 1
test entry-3.53 {EntryWidgetCmd procedure, "selection present" widget command} -setup {
    entry .e
    pack .e
    update  
    update
} -body {
    .e insert end 0123456789
    .e select from 3
    .e select to 6
    .e configure -exportselection false
    .e selection present
} -cleanup {
    destroy .e
} -result {1}
} -result 1
test entry-3.54 {EntryWidgetCmd procedure, "selection present" widget command} -setup {
    entry .e
    pack .e
    update 
    update
} -body {
    .e insert end 0123456789
    .e select from 3
    .e select to 6
    .e delete 0 end
    .e selection present
} -cleanup {
    destroy .e
} -result {0}
} -result 0
test entry-3.55 {EntryWidgetCmd procedure, "selection adjust" widget command} -setup {
    entry .e
} -body {
    .e select adjust x
} -cleanup {
    destroy .e
} -returnCodes error -result {bad entry index "x"}
1238
1239
1240
1241
1242
1243
1244
1245

1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259

1260
1261
1262
1263
1264
1265
1266
1260
1261
1262
1263
1264
1265
1266

1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280

1281
1282
1283
1284
1285
1286
1287
1288







-
+













-
+







    .e select from 1
    .e select to 5
    update
    .e select adjust 4
    selection get
} -cleanup {
    destroy .e
} -result {123}
} -result 123
test entry-3.58 {EntryWidgetCmd procedure, "selection adjust" widget command} -setup {
    entry .e
    pack .e
    update
} -body {
    .e insert end "0123456789"
    .e select from 1
    .e select to 5
    update
    .e select adjust 2
    selection get
} -cleanup {
    destroy .e
} -result {234}
} -result 234
test entry-3.59 {EntryWidgetCmd procedure, "selection from" widget command} -setup {
    entry .e
} -body {
    .e select from 2 3
} -cleanup {
    destroy .e
} -returnCodes error -result {wrong # args: should be ".e selection from index"}
1340
1341
1342
1343
1344
1345
1346
1347

1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359

1360
1361
1362
1363
1364
1365
1366
1367
1368

1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382

1383
1384
1385
1386
1387
1388
1389
1390
1391

1392
1393
1394
1395
1396
1397
1398
1399
1400

1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412

1413
1414
1415
1416
1417
1418
1419
1420
1421

1422
1423

1424
1425
1426
1427
1428
1429
1430
1431
1432

1433
1434

1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447

1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461

1462
1463
1464
1465
1466
1467
1468
1469

1470
1471
1472
1473

1474
1475

1476
1477
1478
1479
1480
1481
1482
1483

1484
1485
1486
1487

1488
1489

1490
1491
1492
1493
1494
1495
1496
1497
1498

1499
1500

1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511

1512
1513
1514
1515
1516
1517
1518
1519

1520
1521
1522
1523

1524
1525

1526
1527
1528
1529
1530
1531
1532
1533
1534
1535

1536
1537

1538
1539
1540
1541
1542

1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559

1560
1561
1562
1563
1564
1565
1566
1362
1363
1364
1365
1366
1367
1368

1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380

1381
1382
1383
1384
1385
1386
1387
1388
1389

1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403

1404
1405
1406
1407
1408
1409
1410
1411
1412

1413
1414
1415
1416
1417
1418
1419
1420
1421

1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433

1434
1435
1436
1437
1438
1439
1440
1441
1442

1443
1444

1445
1446
1447
1448
1449
1450
1451
1452
1453

1454
1455

1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468

1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482

1483
1484
1485
1486
1487
1488
1489
1490

1491
1492
1493
1494

1495
1496

1497
1498
1499
1500
1501
1502
1503
1504

1505
1506
1507
1508

1509
1510

1511
1512
1513
1514
1515
1516
1517
1518
1519

1520
1521

1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532

1533
1534
1535
1536
1537
1538
1539
1540

1541
1542
1543
1544

1545
1546

1547
1548
1549
1550
1551
1552
1553
1554
1555
1556

1557
1558

1559
1560
1561
1562
1563

1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580

1581
1582
1583
1584
1585
1586
1587
1588







-
+











-
+








-
+













-
+








-
+








-
+











-
+








-
+

-
+








-
+

-
+












-
+













-
+







-
+



-
+

-
+







-
+



-
+

-
+








-
+

-
+










-
+







-
+



-
+

-
+









-
+

-
+




-
+
















-
+







} -body {
    .e select to 2 3
} -cleanup {
    destroy .e
} -returnCodes error -result {wrong # args: should be ".e selection to index"}

test entry-3.65 {EntryWidgetCmd procedure, "xview" widget command} -setup {
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
    update
} -body {
    .e insert end "This is quite a long text string, so long that it "
    .e insert end "runs off the end of the window quite a bit."
    .e xview 5
    format {%.7f %.7f} {*}[.e xview]
} -cleanup {
    destroy .e
} -result {0.0537634 0.2688172}
test entry-3.66 {EntryWidgetCmd procedure, "xview" widget command} -setup {
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
    update
} -body {
    .e xview gorp
} -cleanup {
    destroy .e
} -returnCodes error -result {bad entry index "gorp"}
test entry-3.67 {EntryWidgetCmd procedure, "xview" widget command} -setup {
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
    update
} -body {
    .e insert end "This is quite a long text string, so long that it "
    .e insert end "runs off the end of the window quite a bit."
    .e xview 0
    .e icursor 10
    .e xview insert
    format {%.6f %.6f} {*}[.e xview]
} -cleanup {
    destroy .e
} -result {0.107527 0.322581}
test entry-3.68 {EntryWidgetCmd procedure, "xview" widget command} -setup {
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
    update
} -body {
    .e xview moveto foo bar
} -cleanup {
    destroy .e
} -returnCodes error -result {wrong # args: should be ".e xview moveto fraction"}
test entry-3.69 {EntryWidgetCmd procedure, "xview" widget command} -setup {
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
    update
} -body {
    .e xview moveto foo
} -cleanup {
    destroy .e
} -returnCodes error -result {expected floating-point number but got "foo"}
test entry-3.70 {EntryWidgetCmd procedure, "xview" widget command} -setup {
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
    update
} -body {
    .e insert end "This is quite a long text string, so long that it "
    .e insert end "runs off the end of the window quite a bit."
    .e xview moveto 0.5
    format {%.6f %.6f} {*}[.e xview]
} -cleanup {
    destroy .e
} -result {0.505376 0.720430}
test entry-3.71 {EntryWidgetCmd procedure, "xview" widget command} -setup {
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
    update
} -body {
    .e insert end "This is quite a long text string, so long that it "
    .e insert end "runs off the end of the window quite a bit."
    .e xview scroll 24
} -cleanup {
    destroy .e
} -returnCodes error -result {wrong # args: should be ".e xview scroll number units|pages"}
} -returnCodes error -result {wrong # args: should be ".e xview scroll number pages|units"}
test entry-3.72 {EntryWidgetCmd procedure, "xview" widget command} -setup {
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
} -body {
    .e insert end "This is quite a long text string, so long that it "
    .e insert end "runs off the end of the window quite a bit."
    update
    .e xview scroll gorp units
} -cleanup {
    destroy .e
} -returnCodes error -result {expected integer but got "gorp"}
} -returnCodes error -result {expected floating-point number but got "gorp"}
test entry-3.73 {EntryWidgetCmd procedure, "xview" widget command} -setup {
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
} -body {
    .e insert end "This is quite a long text string, so long that it "
    .e insert end "runs off the end of the window quite a bit."
    update
    .e xview moveto 0
    .e xview scroll 1 pages
    format {%.6f %.6f} {*}[.e xview]
} -cleanup {
    destroy .e
} -result {0.193548 0.408602}
test entry-3.74 {EntryWidgetCmd procedure, "xview" widget command} -setup {
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
    update
} -body {
    .e insert end "This is quite a long text string, so long that it "
    .e insert end "runs off the end of the window quite a bit."
    .e xview moveto .9
    update
    .e xview scroll -2 p
    format {%.6f %.6f} {*}[.e xview]
} -cleanup {
    destroy .e
} -result {0.397849 0.612903}
test entry-3.75 {EntryWidgetCmd procedure, "xview" widget command} -setup {
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
} -body {
    .e insert end "This is quite a long text string, so long that it "
    .e insert end "runs off the end of the window quite a bit."
    update
    .e xview 30
    update
    .e xview scroll 2 units 
    .e xview scroll 2 units
    .e index @0
} -cleanup {
    destroy .e
} -result {32}
} -result 32
test entry-3.76 {EntryWidgetCmd procedure, "xview" widget command} -setup {
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
} -body {
    .e insert end "This is quite a long text string, so long that it "
    .e insert end "runs off the end of the window quite a bit."
    update
    .e xview 30
    update
    .e xview scroll -1 units 
    .e xview scroll -1 units
    .e index @0
} -cleanup {
    destroy .e
} -result {29}
} -result 29
test entry-3.77 {EntryWidgetCmd procedure, "xview" widget command} -setup {
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
} -body {
    .e insert end "This is quite a long text string, so long that it "
    .e insert end "runs off the end of the window quite a bit."
    update
    .e xview scroll 23 foobars
} -cleanup {
    destroy .e
} -returnCodes error -result {bad argument "foobars": must be units or pages}
} -returnCodes error -result {bad argument "foobars": must be pages or units}
test entry-3.78 {EntryWidgetCmd procedure, "xview" widget command} -setup {
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
} -body {
    .e insert end "This is quite a long text string, so long that it "
    .e insert end "runs off the end of the window quite a bit."
    update
    .e xview eat 23 hamburgers
} -cleanup {
    destroy .e
} -returnCodes error -result {unknown option "eat": must be moveto or scroll}
test entry-3.79 {EntryWidgetCmd procedure, "xview" widget command} -setup {
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
    update
} -body {
    .e insert end "This is quite a long text string, so long that it "
    .e insert end "runs off the end of the window quite a bit."
    .e xview 0
    update
    .e xview -4
    .e xview -1
    .e index @0
} -cleanup {
    destroy .e
} -result {0}
} -result 0
test entry-3.80 {EntryWidgetCmd procedure, "xview" widget command} -setup {
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
} -body {
    .e insert end "This is quite a long text string, so long that it "
    .e insert end "runs off the end of the window quite a bit."
    update
    .e xview 300
    .e index @0
} -cleanup {
    destroy .e
} -result {73}
} -result 73
test entry-3.86 {EntryWidgetCmd procedure, "xview" widget command} -setup {
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
} -body {
    .e insert end "This is quite a long text string, so long that it "
    .e insert end "runs off the end of the window quite a bit."
    .e insert 10 \u4e4e
    .e insert 10 
    update
# UTF
# If Tcl_NumUtfChars wasn't used, wrong answer would be:
# 0.106383 0.117021 0.117021
    set x {}
    .e xview moveto .1
    lappend x [format {%.6f} [lindex [.e xview] 0]]
    .e xview moveto .11
    lappend x [format {%.6f} [lindex [.e xview] 0]]
    .e xview moveto .12
    lappend x [format {%.6f} [lindex [.e xview] 0]]
} -cleanup {
    destroy .e
} -result {0.095745 0.106383 0.117021}

test entry-3.82 {EntryWidgetCmd procedure} -setup {
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    entry .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
    update
} -body {
    .e gorp
} -cleanup {
    destroy .e
} -returnCodes error -result {bad option "gorp": must be bbox, cget, configure, delete, get, icursor, index, insert, scan, selection, validate, or xview}
1579
1580
1581
1582
1583
1584
1585
1586

1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603

1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618

1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638

1639
1640
1641
1642
1643

1644
1645
1646
1647
1648
1649
1650

1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662

1663
1664
1665
1666
1667
1668
1669

1670
1671
1672
1673

1674

1675
1676

1677
1678
1679
1680
1681
1682
1683
1684
1685

1686
1687

1688
1689
1690
1691
1692
1693
1694
1601
1602
1603
1604
1605
1606
1607

1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624

1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639

1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659

1660
1661
1662
1663
1664

1665
1666
1667
1668
1669
1670
1671

1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683

1684
1685
1686
1687
1688
1689
1690

1691
1692
1693
1694
1695
1696

1697

1698
1699
1700
1701
1702
1703
1704
1705
1706
1707

1708
1709

1710
1711
1712
1713
1714
1715
1716
1717







-
+
















-
+














-
+



















-
+




-
+






-
+











-
+






-
+




+
-
+
-

+








-
+

-
+








test entry-5.1 {ConfigureEntry procedure, -textvariable} -body {
    set x 12345
    entry .e -textvariable x
    .e get
} -cleanup {
    destroy .e
} -result {12345}
} -result 12345
test entry-5.2 {ConfigureEntry procedure, -textvariable} -body {
    set x 12345
    entry .e -textvariable x
    set y abcde
    .e configure -textvariable y
    set x 54321
    .e get
} -cleanup {
    destroy .e
} -result {abcde}
test entry-5.3 {ConfigureEntry procedure, -textvariable} -setup {
    unset -nocomplain x
    entry .e
} -body {
    .e insert 0 "Some text"
    .e configure -textvariable x
    return $x
    set x
} -cleanup {
    destroy .e
} -result {Some text}
test entry-5.4 {ConfigureEntry procedure, -textvariable} -setup {
    unset -nocomplain x
    entry .e
} -body {
    trace variable x w override
    .e insert 0 "Some text"
    .e configure -textvariable x
    list $x [.e get]
} -cleanup {
    destroy .e
    trace vdelete x w override
    unset x;  
    unset x;
} -result {12345 12345}

test entry-5.5 {ConfigureEntry procedure} -setup {
    set x {}
    entry .e1
    entry .e2
} -body {
    .e2 insert end "This is some sample text"
    .e1 configure -exportselection false
    .e1 insert end "0123456789"
    pack .e1 .e2
    .e2 select from 0
    .e2 select to 10
    lappend x [selection get]
    .e1 select from 1
    .e1 select to 5
    lappend x [selection get]
    .e1 configure -exportselection 1
    lappend x [selection get]
    return $x
    set x
} -cleanup {
    destroy .e1 .e2
} -result {{This is so} {This is so} 1234}
test entry-5.6 {ConfigureEntry procedure} -setup {
    entry .e 
    entry .e
    pack .e
} -body {
    .e insert end "0123456789"
    .e select from 1
    .e select to 5
    .e configure -exportselection 0
    selection get 
    selection get
} -cleanup {
    destroy .e
} -returnCodes error -result {PRIMARY selection doesn't exist or form "STRING" not defined}
test entry-5.6.1 {ConfigureEntry procedure} -setup {
    entry .e
    pack .e
} -body {
    .e insert end "0123456789"
    .e select from 1
    .e select to 5
    .e configure -exportselection 0
    catch {selection get} 
    catch {selection get}
    list [.e index sel.first] [.e index sel.last]
} -cleanup {
    destroy .e
} -result {1 5}

test entry-5.7 {ConfigureEntry procedure} -setup {
    entry .e -font {Helvetica -12} -borderwidth 2 -highlightthickness 2 
    entry .e -font {Helvetica -12} -borderwidth 2 -highlightthickness 2
    pack .e
} -body {
    .e configure -font {Courier -12} -width 4 -xscrollcommand scroll
    .e insert end "01234567890"
    update idletasks
    set timeout [after 500 {set $scrollInfo "timeout"}]
    set timeout [after 500 {set scrollInfo {-1000000 -1000000}}]
    vwait scrollInfo
    .e configure -width 5
    vwait scrollInfo
    format {%.6f %.6f} {*}$scrollInfo
} -cleanup {
    destroy .e
    after cancel $timeout
} -result {0.000000 0.363636}


test entry-5.8 {ConfigureEntry procedure} -constraints {
    fonts
    fonts failsOnXQuarz
} -setup {
    entry .e -borderwidth 2 -highlightthickness 2 
    entry .e -borderwidth 2 -highlightthickness 2
    pack .e
} -body {
    .e configure -width 0 -font {Helvetica -12}
    .e insert end "0123"
    update
    .e configure -font {Helvetica -24}
    update
1735
1736
1737
1738
1739
1740
1741
1742

1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756

1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770

1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782

1783
1784
1785
1786
1787
1788
1789
1790
1791
1792

1793
1794
1795
1796
1797

1798
1799
1800
1801
1802
1803
1804

1805
1806
1807
1808
1809
1810
1811

1812
1813
1814
1815
1816
1817
1818
1758
1759
1760
1761
1762
1763
1764

1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778

1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792

1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804

1805
1806
1807
1808
1809
1810
1811
1812
1813
1814

1815
1816
1817
1818
1819

1820
1821
1822
1823
1824
1825
1826

1827
1828
1829
1830
1831
1832
1833

1834
1835
1836
1837
1838
1839
1840
1841







-
+













-
+













-
+











-
+









-
+




-
+






-
+






-
+







} -result {}

# No tests for DisplayEntry.

test entry-6.1 {EntryComputeGeometry procedure} -constraints {
    fonts
} -setup {
    entry .e 
    entry .e
    pack .e
} -body {
    .e configure -font {Courier -12} -bd 2 -relief raised -width 20 \
        -highlightthickness 3
    .e insert end 012\t45
    update
    list [.e index @61] [.e index @62]
} -cleanup {
    destroy .e
} -result {3 4}
test entry-6.2 {EntryComputeGeometry procedure} -constraints {
    fonts
} -setup {
    entry .e 
    entry .e
    pack .e
} -body {
    .e configure -font {Courier -12} -bd 2 -relief raised -width 20 \
        -justify center -highlightthickness 3
    .e insert end 012\t45
    update
    list [.e index @96] [.e index @97]
} -cleanup {
    destroy .e
} -result {3 4}
test entry-6.3 {EntryComputeGeometry procedure} -constraints {
    fonts
} -setup {
    entry .e 
    entry .e
    pack .e
} -body {
    .e configure -font {Courier -12} -bd 2 -relief raised -width 20 \
        -justify right -highlightthickness 3
    .e insert end 012\t45
    update
    list [.e index @131] [.e index @132]
} -cleanup {
    destroy .e
} -result {3 4}
test entry-6.4 {EntryComputeGeometry procedure} -setup {
    entry .e 
    entry .e
    pack .e
} -body {
    .e configure -font {Courier -12} -bd 2 -relief raised -width 5
    .e insert end "01234567890"
    update
    .e xview 6
    .e index @0
} -cleanup {
    destroy .e
} -result {6}
} -result 6
test entry-6.5 {EntryComputeGeometry procedure} -setup {
    entry .e -highlightthickness 2
    pack .e
} -body {
    .e configure -font {Courier -12} -bd 2 -relief raised -width 5 	    
    .e configure -font {Courier -12} -bd 2 -relief raised -width 5
    .e insert end "01234567890"
    update
    .e xview 7
    .e index @0
} -cleanup {
    destroy .e
} -result {6}
} -result 6
test entry-6.6 {EntryComputeGeometry procedure} -constraints {
    fonts
} -setup {
    entry .e -highlightthickness 2
    pack .e
} -body {
    .e configure -font {Courier -12} -bd 2 -relief raised -width 10 
    .e configure -font {Courier -12} -bd 2 -relief raised -width 10
    .e insert end "01234\t67890"
    update
    .e xview 3
    list [.e index @39] [.e index @40]
} -cleanup {
    destroy .e
} -result {5 6}
1844
1845
1846
1847
1848
1849
1850
1851

1852
1853
1854
1855
1856
1857
1858

1859
1860
1861
1862
1863
1864
1865
1867
1868
1869
1870
1871
1872
1873

1874
1875
1876
1877
1878
1879
1880

1881
1882
1883
1884
1885
1886
1887
1888







-
+






-
+







} -result {116 39}
test entry-6.9 {EntryComputeGeometry procedure} -constraints {
    fonts
} -setup {
    entry .e -highlightthickness 2
    pack .e
} -body {
    .e configure -font {Helvetica -24} -bd 3 -relief raised -width 0 
    .e configure -font {Helvetica -24} -bd 3 -relief raised -width 0
    update
    list [winfo reqwidth .e] [winfo reqheight .e]
} -cleanup {
    destroy .e
} -result {25 39}
test entry-6.10 {EntryComputeGeometry procedure} -constraints {
    unix fonts 
    unix fonts
} -setup {
    entry .e -highlightthickness 2 -font {Helvetica -12}
    pack .e
} -body {
    .e configure -bd 1 -relief raised -width 0 -show .
    .e insert 0 12345
    update
1906
1907
1908
1909
1910
1911
1912
1913

1914
1915
1916
1917
1918

1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931


1932
1933
1934
1935

1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1929
1930
1931
1932
1933
1934
1935

1936
1937
1938
1939
1940
1941
1942
1943
1944

1945
1946
1947
1948
1949
1950
1951
1952


1953
1954
1955
1956
1957
1958
1959
1960
1961

1962
1963
1964
1965
1966
1967
1968







-
+





+


-








-
-
+
+




+


-







    list [.e index @80] [.e index @81] [.e index @115] [.e index @116]
} -cleanup {
    destroy .e
} -result {6 7 7 8}


test entry-7.1 {InsertChars procedure} -setup {
    unset -nocomplain contents 
    unset -nocomplain contents
    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
    focus .e
} -body {
    .e configure -textvariable contents -xscrollcommand scroll
    set timeout [after 500 {set scrollInfo {-1000000 -1000000}}]
    .e insert 0 abcde
    .e insert 2 XXX
    set timeout [after 500 {set $scrollInfo "timeout"}]
    vwait scrollInfo
    list [.e get] $contents [format {%.6f %.6f} {*}$scrollInfo]
} -cleanup {
    destroy .e
    after cancel $timeout
} -result {abXXXcde abXXXcde {0.000000 1.000000}}

test entry-7.2 {InsertChars procedure} -setup {
    unset -nocomplain contents 
    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2 
    unset -nocomplain contents
    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
    focus .e
} -body {
    .e configure -textvariable contents -xscrollcommand scroll
    set timeout [after 500 {set scrollInfo {-1000000 -1000000}}]
    .e insert 0 abcde
    .e insert 500 XXX
    set timeout [after 500 {set $scrollInfo "timeout"}]
    vwait scrollInfo
    list [.e get] $contents [format {%.6f %.6f} {*}$scrollInfo]
} -cleanup {
    destroy .e
    after cancel $timeout
} -result {abcdeXXX abcdeXXX {0.000000 1.000000}}
test entry-7.3 {InsertChars procedure} -setup {
1995
1996
1997
1998
1999
2000
2001
2002

2003
2004
2005
2006
2007
2008
2009
2010
2011
2012

2013
2014

2015
2016
2017
2018
2019
2020
2021
2022
2023

2024
2025

2026
2027
2028
2029
2030
2031
2032
2033
2034
2035

2036
2037

2038
2039
2040
2041
2042
2043
2044
2045
2046
2047

2048
2049
2050
2051
2052

2053
2054
2055
2056
2057
2058
2059
2060
2061

2062
2063
2064
2065

2066
2067
2068
2069

2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081

2082
2083
2084
2085

2086
2087

2088
2089
2090
2091
2092
2093
2094
2095
2096
2097

2098
2099
2100
2101

2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112

2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128

2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144

2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160

2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174

2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190

2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203

2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219

2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235

2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246

2247
2248

2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259

2260
2261

2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272

2273
2274

2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285

2286
2287

2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298

2299
2300

2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313



2314
2315
2316
2317
2318
2319









2320

2321
2322

2323

2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344

2345
2346
2347
2348
2349
2350
2351
2352
2353

2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366

2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379

2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392

2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404

2405
2406
2407

2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420

2421
2422
2423

2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435

2436
2437
2438

2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449

2450
2451
2452
2453
2454
2455
2456
2018
2019
2020
2021
2022
2023
2024

2025
2026
2027
2028
2029
2030
2031
2032
2033
2034

2035
2036

2037
2038
2039
2040
2041
2042
2043
2044
2045

2046
2047

2048
2049
2050
2051
2052
2053
2054
2055
2056
2057

2058
2059

2060
2061
2062
2063
2064
2065
2066
2067
2068
2069

2070
2071
2072
2073
2074

2075
2076
2077
2078
2079
2080
2081
2082
2083

2084
2085
2086
2087

2088
2089
2090
2091
2092
2093
2094
2095

2096
2097
2098
2099
2100
2101
2102
2103

2104
2105
2106
2107
2108
2109
2110

2111

2112
2113
2114
2115
2116
2117
2118
2119

2120
2121
2122
2123
2124
2125
2126
2127

2128
2129
2130
2131
2132
2133
2134

2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150

2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166

2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182

2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196

2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212

2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225

2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241

2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257

2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268

2269
2270

2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281

2282
2283

2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294

2295
2296

2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307

2308
2309

2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320

2321
2322

2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333



2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351

2352
2353
2354
2355

2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376

2377
2378
2379
2380
2381
2382
2383
2384
2385

2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398

2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411

2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424

2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436

2437
2438
2439

2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452

2453
2454
2455

2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467

2468
2469
2470

2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481

2482
2483
2484
2485
2486
2487
2488
2489







-
+









-
+

-
+








-
+

-
+









-
+

-
+









-
+




-
+








-
+



-
+




+


-








-
+




+

-
+
-








-
+




+


-







-
+















-
+















-
+















-
+













-
+















-
+












-
+















-
+















-
+










-
+

-
+










-
+

-
+










-
+

-
+










-
+

-
+










-
+

-
+










-
-
-
+
+
+






+
+
+
+
+
+
+
+
+
-
+


+
-
+




















-
+








-
+












-
+












-
+












-
+











-
+


-
+












-
+


-
+











-
+


-
+










-
+







    set x "[.e index sel.first] [.e index sel.last]"
    .e select to 5
    lappend x [.e index sel.first] [.e index sel.last]
} -cleanup {
    destroy .e
} -result {2 6 2 5}
test entry-7.7 {InsertChars procedure} -setup {
    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2 
    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
} -body {
    .e configure -xscrollcommand scroll
    .e insert 0 0123456789
    .e icursor 4
    .e insert 4 XXX
    .e index insert
} -cleanup {
    destroy .e
} -result {7}
} -result 7
test entry-7.8 {InsertChars procedure} -setup {
    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2 
    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
} -body {
    .e insert 0 0123456789
    .e icursor 4
    .e insert 5 XXX
    .e index insert
} -cleanup {
    destroy .e
} -result {4}
} -result 4
test entry-7.9 {InsertChars procedure} -setup {
    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2 
    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
} -body {
    .e insert 0 "This is a very long string"
    update
    .e xview 4
    .e insert 3 XXX
    .e index @0
} -cleanup {
    destroy .e
} -result {7}
} -result 7
test entry-7.10 {InsertChars procedure} -setup {
    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2 
    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
} -body {
    .e insert 0 "This is a very long string"
    update
    .e xview 4
    .e insert 4 XXX
    .e index @0
} -cleanup {
    destroy .e
} -result {4}
} -result 4

test entry-7.11 {InsertChars procedure} -constraints {
    fonts
} -setup {
    entry .e -width 0 -font {Courier -12} -highlightthickness 2 -bd 2 
    entry .e -width 0 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
} -body {
    .e insert 0 "xyzzy"
    update
    .e insert 2 00
    winfo reqwidth .e
} -cleanup {
    destroy .e
} -result {59}
} -result 59

test entry-8.1 {DeleteChars procedure} -setup {
    unset -nocomplain contents
    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2 
    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
    focus .e
} -body {
    .e configure -textvariable contents -xscrollcommand scroll
    set timeout [after 500 {set scrollInfo {-1000000 -1000000}}]
    .e insert 0 abcde
    .e delete 2 4
    set timeout [after 500 {set $scrollInfo "timeout"}]
    vwait scrollInfo
    list [.e get] $contents [format {%.6f %.6f} {*}$scrollInfo]
} -cleanup {
    destroy .e
    after cancel $timeout
} -result {abe abe {0.000000 1.000000}}
test entry-8.2 {DeleteChars procedure} -setup {
    unset -nocomplain contents
    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2 
    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
    focus .e
} -body {
    .e configure -textvariable contents -xscrollcommand scroll
    set timeout [after 500 {set scrollInfo {-1000000 -1000000}}]
    .e insert 0 abcde
    .e delete -2 2
    .e delete -1 2
    set timeout [after 500 {set $scrollInfo "timeout"}]
    vwait scrollInfo
    list [.e get] $contents [format {%.6f %.6f} {*}$scrollInfo]
} -cleanup {
    destroy .e
    after cancel $timeout
} -result {cde cde {0.000000 1.000000}}
test entry-8.3 {DeleteChars procedure} -setup {
    unset -nocomplain contents
    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2 
    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
    focus .e
} -body {
    .e configure -textvariable contents -xscrollcommand scroll
    set timeout [after 500 {set scrollInfo {-1000000 -1000000}}]
    .e insert 0 abcde
    .e delete 3 1000
    set timeout [after 500 {set $scrollInfo "timeout"}]
    vwait scrollInfo
    list [.e get] $contents [format {%.6f %.6f} {*}$scrollInfo]
} -cleanup {
    destroy .e
    after cancel $timeout
} -result {abc abc {0.000000 1.000000}}
test entry-8.4 {DeleteChars procedure} -setup {
    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2 
    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
    focus .e
} -body {
    .e insert 0 0123456789abcde
    .e select from 3
    .e select to 8
    .e delete 1 3
    update
    set x "[.e index sel.first] [.e index sel.last]"
    .e select to 5
    lappend x [.e index sel.first] [.e index sel.last]
} -cleanup {
    destroy .e
} -result {1 6 1 5}
test entry-8.5 {DeleteChars procedure} -setup {
    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2 
    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
    focus .e
} -body {
    .e insert 0 0123456789abcde
    .e select from 3
    .e select to 8
    .e delete 1 4
    update
    set x "[.e index sel.first] [.e index sel.last]"
    .e select to 4
    lappend x [.e index sel.first] [.e index sel.last]
} -cleanup {
    destroy .e
} -result {1 5 1 4}
test entry-8.6 {DeleteChars procedure} -setup {
    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2 
    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
    focus .e
} -body {
    .e insert 0 0123456789abcde
    .e select from 3
    .e select to 8
    .e delete 1 7
    update
    set x "[.e index sel.first] [.e index sel.last]"
    .e select to 5
    lappend x [.e index sel.first] [.e index sel.last]
} -cleanup {
    destroy .e
} -result {1 2 1 5}
test entry-8.7 {DeleteChars procedure} -setup {
    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2 
    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
    focus .e
} -body {
    .e insert 0 0123456789abcde
    .e select from 3
    .e select to 8
    .e delete 1 8
    update
    .e index sel.first
} -cleanup {
    destroy .e
} -returnCodes error -result {selection isn't in widget .e}
test entry-8.8 {DeleteChars procedure} -setup {
    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2 
    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
    focus .e
} -body {
    .e insert 0 0123456789abcde
    .e select from 3
    .e select to 8
    .e delete 3 7
    update
    set x "[.e index sel.first] [.e index sel.last]"
    .e select to 8
    lappend x [.e index sel.first] [.e index sel.last]
} -cleanup {
    destroy .e
} -result {3 4 3 8}
test entry-8.9 {DeleteChars procedure} -setup {
    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2 
    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
} -body {
    .e insert 0 0123456789abcde
    .e select from 3
    .e select to 8
    .e delete 3 8
    update
    .e index sel.first
} -cleanup {
    destroy .e
} -returnCodes error -result {selection isn't in widget .e}
test entry-8.10 {DeleteChars procedure} -setup {
    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2 
    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
    focus .e
} -body {
    .e insert 0 0123456789abcde
    .e select from 8
    .e select to 3
    .e delete 5 8
    update
    set x "[.e index sel.first] [.e index sel.last]"
    .e select to 8
    lappend x [.e index sel.first] [.e index sel.last]
} -cleanup {
    destroy .e
} -result {3 5 5 8}
test entry-8.11 {DeleteChars procedure} -setup {
    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2 
    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
    focus .e
} -body {
    .e insert 0 0123456789abcde
    .e select from 8
    .e select to 3
    .e delete 8 10
    update
    set x "[.e index sel.first] [.e index sel.last]"
    .e select to 4
    lappend x [.e index sel.first] [.e index sel.last]
} -cleanup {
    destroy .e
} -result {3 8 4 8}
test entry-8.12 {DeleteChars procedure} -setup {
    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2 
    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
    focus .e
} -body {
    .e insert 0 0123456789abcde
    .e icursor 4
    .e delete 1 4
    update
    .e index insert
} -cleanup {
    destroy .e
} -result {1}
} -result 1
test entry-8.13 {DeleteChars procedure} -setup {
    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2 
    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
    focus .e
} -body {
    .e insert 0 0123456789abcde
    .e icursor 4
    .e delete 1 5
    update
    .e index insert
} -cleanup {
    destroy .e
} -result {1}
} -result 1
test entry-8.14 {DeleteChars procedure} -setup {
    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2 
    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
    focus .e
} -body {
    .e insert 0 0123456789abcde
    .e icursor 4
    .e delete 4 6
    update
    .e index insert
} -cleanup {
    destroy .e
} -result {4}
} -result 4
test entry-8.15 {DeleteChars procedure} -setup {
    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2 
    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
    focus .e
} -body {
    .e insert 0 "This is a very long string"
    .e xview 4
    .e delete 1 4
    update
    .e index @0
} -cleanup {
    destroy .e
} -result {1}
} -result 1
test entry-8.16 {DeleteChars procedure} -setup {
    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2 
    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
    focus .e
} -body {
    .e insert 0 "This is a very long string"
    .e xview 4
    .e delete 1 5
    update
    .e index @0
} -cleanup {
    destroy .e
} -result {1}
} -result 1
test entry-8.17 {DeleteChars procedure} -setup {
    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2 
    entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
    focus .e
} -body {
    .e insert 0 "This is a very long string"
    .e xview 4
    .e delete 4 6
    update
    .e index @0
} -cleanup {
    destroy .e
} -result {4}
test entry-8.18 {DeleteChars procedure} -setup {
    entry .e -width 0 -font {Courier -12} -highlightthickness 2 -bd 2 
} -result 4
test entry-8.18 {DeleteChars procedure} -constraints failsOnUbuntuNoXft -setup {
    entry .e -width 0 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
    focus .e
} -body {
    .e insert 0 "xyzzy"
    update
    .e delete 2 4
    # To check that deletion actually happened we measure the new width
    # of the widget, based on the measuring width of the remaining text ("xyy")
    # in the widget. For that purpose we have to mirror the code in tkEntry.c
    # for computation of the reqwidth
    # note: XPAD corresponds to the hardcoded    #define XPAD 1
    set XPAD 1
    set expected [expr { [font measure [.e cget -font] "xyy"] \
                          + 2 * ( [.e cget -borderwidth] + \
                                [.e cget -highlightthickness] + $XPAD ) } ]
    winfo reqwidth .e
    expr {[winfo reqwidth .e] == $expected}
} -cleanup {
    destroy .e
    unset XPAD expected
} -result {31}
} -result 1

test entry-9.1 {EntryValueChanged procedure} -setup {
    unset -nocomplain x
} -body {
    trace variable x w override
    entry .e -textvariable x -width 0
    .e insert 0 foo
    list $x [.e get]
} -cleanup {
    destroy .e
    trace vdelete x w override
    unset x
} -result {12345 12345}


test entry-10.1 {EntrySetValue procedure} -constraints fonts -body {
    set x abcde
    set y ab
    entry .e  -font {Helvetica -12} -highlightthickness 2 -bd 2  -width 0
    pack .e
    .e configure -textvariable x 
    .e configure -textvariable x
    .e configure -textvariable y
    update
    list [.e get] [winfo reqwidth .e]
} -cleanup {
    destroy .e
} -result {ab 24}
test entry-10.2 {EntrySetValue procedure, updating selection} -setup {
    unset -nocomplain x
    entry .e -font {Helvetica -12} -highlightthickness 2 -bd 2 
    entry .e -font {Helvetica -12} -highlightthickness 2 -bd 2
    pack .e
} -body {
    .e configure -textvariable x
    .e insert 0 "abcdefghjklmnopqrstu"
    .e selection range 4 10
    set x "a"
    .e index sel.first
} -cleanup {
    destroy .e
} -returnCodes error -result {selection isn't in widget .e}
test entry-10.3 {EntrySetValue procedure, updating selection} -setup {
    unset -nocomplain x
    entry .e -font {Helvetica -12} -highlightthickness 2 -bd 2 
    entry .e -font {Helvetica -12} -highlightthickness 2 -bd 2
    pack .e
} -body {
    .e configure -textvariable x
    .e insert 0 "abcdefghjklmnopqrstu"
    .e selection range 4 10
    set x "abcdefg"
    list [.e index sel.first] [.e index sel.last]
} -cleanup {
    destroy .e
} -result {4 7}
test entry-10.4 {EntrySetValue procedure, updating selection} -setup {
    unset -nocomplain x
    entry .e -font {Helvetica -12} -highlightthickness 2 -bd 2 
    entry .e -font {Helvetica -12} -highlightthickness 2 -bd 2
    pack .e
} -body {
    .e configure -textvariable x
    .e insert 0 "abcdefghjklmnopqrstu"
    .e selection range 4 10
    set x "abcdefghijklmn"
    list [.e index sel.first] [.e index sel.last]
} -cleanup {
    destroy .e
} -result {4 10}
test entry-10.5 {EntrySetValue procedure, updating display position} -setup {
    unset -nocomplain x
    entry .e -highlightthickness 2 -bd 2 
    entry .e -highlightthickness 2 -bd 2
    pack .e
} -body {
    .e configure -width 10 -font {Courier -12} -textvariable x
    .e insert 0 "abcdefghjklmnopqrstuvwxyz"
    .e xview 10
    update
    set x "abcdefg"
    update
    .e index @0
} -cleanup {
    destroy .e
} -result {0}
} -result 0
test entry-10.6 {EntrySetValue procedure, updating display position} -setup {
    unset -nocomplain x
    entry .e -highlightthickness 2 -bd 2 
    entry .e -highlightthickness 2 -bd 2
    pack .e
} -body {
    .e configure -width 10 -font {Courier -12} -textvariable x
    pack .e
    .e insert 0 "abcdefghjklmnopqrstuvwxyz"
    .e xview 10
    update
    set x "1234567890123456789012"
    update
    .e index @0
} -cleanup {
    destroy .e
} -result {10}
} -result 10
test entry-10.7 {EntrySetValue procedure, updating insertion cursor} -setup {
    unset -nocomplain x
    entry .e -highlightthickness 2 -bd 2 
    entry .e -highlightthickness 2 -bd 2
    pack .e
    update
} -body {
    .e configure -width 10 -font {Courier -12} -textvariable x
    pack .e
    .e insert 0 "abcdefghjklmnopqrstuvwxyz"
    .e icursor 5
    set x "123"
    .e index insert
} -cleanup {
    destroy .e
} -result {3}
} -result 3
test entry-10.8 {EntrySetValue procedure, updating insertion cursor} -setup {
    unset -nocomplain x
    entry .e -highlightthickness 2 -bd 2 
    entry .e -highlightthickness 2 -bd 2
    pack .e
} -body {
    .e configure -width 10 -font {Courier -12} -textvariable x
    pack .e
    .e insert 0 "abcdefghjklmnopqrstuvwxyz"
    .e icursor 5
    set x "123456"
    .e index insert
} -cleanup {
    destroy .e
} -result {5}
} -result 5

test entry-11.1 {EntryEventProc procedure} -setup {
    entry .e -highlightthickness 2 -bd 2 -font {Helvetica -12}
    pack .e
} -body {
    .e insert 0 abcdefg
    destroy .e
2486
2487
2488
2489
2490
2491
2492
2493

2494
2495

2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512

2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525

2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539

2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558

2559
2560
2561
2562
2563
2564
2565
2519
2520
2521
2522
2523
2524
2525

2526
2527

2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544

2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557

2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571

2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590

2591
2592
2593
2594
2595
2596
2597
2598







-
+

-
+
















-
+












-
+













-
+


















-
+







} -body {
    .e insert 0 012345678901234567890
    .e xview 4
    update
    .e index end
} -cleanup {
    destroy .e
} -result {21}
} -result 21
test entry-13.2 {GetEntryIndex procedure} -body {
    entry .e 
    entry .e
    .e index abogus
} -cleanup {
    destroy .e
} -returnCodes error -result {bad entry index "abogus"}
test entry-13.3 {GetEntryIndex procedure} -setup {
    entry .e -font {Courier -12} -width 5 -bd 2 -relief sunken
    pack .e
} -body {
    .e insert 0 012345678901234567890
    .e xview 4
    update
    .e select from 1
    .e select to 6
    .e index anchor
} -cleanup {
    destroy .e
} -result {1}
} -result 1
test entry-13.4 {GetEntryIndex procedure} -setup {
    entry .e -font {Courier -12} -width 5 -bd 2 -relief sunken
    pack .e
} -body {
    .e insert 0 012345678901234567890
    .e xview 4
    update
    .e select from 4
    .e select to 1
    .e index anchor
} -cleanup {
    destroy .e
} -result {4}
} -result 4
test entry-13.5 {GetEntryIndex procedure} -setup {
    entry .e -font {Courier -12} -width 5 -bd 2 -relief sunken
    pack .e
} -body {
    .e insert 0 012345678901234567890
    .e xview 4
    update
    .e select from 3
    .e select to 15
    .e select adjust 4
    .e index anchor
} -cleanup {
    destroy .e
} -result {15}
} -result 15
test entry-13.6 {GetEntryIndex procedure} -setup {
    entry .e
} -body {
    .e index ebogus
} -cleanup {
    destroy .e
} -returnCodes error -result {bad entry index "ebogus"}
test entry-13.7 {GetEntryIndex procedure} -setup {
    entry .e -font {Courier -12} -width 5 -bd 2 -relief sunken
    pack .e
} -body {
    .e insert 0 012345678901234567890
    .e xview 4
    update
    .e icursor 2
    .e index insert
} -cleanup {
    destroy .e
} -result {2}
} -result 2
test entry-13.8 {GetEntryIndex procedure} -setup {
    entry .e
} -body {
    .e index ibogus
} -cleanup {
    destroy .e
} -returnCodes error -result {bad entry index "ibogus"}
2579
2580
2581
2582
2583
2584
2585
2586

2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606

2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623

2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642

2643
2644
2645
2646
2647
2648
2649
2612
2613
2614
2615
2616
2617
2618

2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638

2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655

2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674

2675
2676
2677
2678
2679
2680
2681
2682







-
+



















-
+
















-
+


















-
+













test entry-13.10 {GetEntryIndex procedure} -constraints x11 -body {
# On unix, when selection is cleared, entry widget's internal 
# On unix, when selection is cleared, entry widget's internal
# selection range is reset.
# Previous settings:
	entry .e -font {Courier -12} -width 5 -bd 2 -relief sunken
	pack .e
	.e insert 0 012345678901234567890
	.e xview 4
	update
    .e select from 1
    .e select to 6
    list [.e index sel.first] [.e index sel.last]
# Testing:
    selection clear .e
    .e index sel.first
} -cleanup {
    destroy .e
} -returnCodes error -result {selection isn't in widget .e}

test entry-13.11 {GetEntryIndex procedure} -constraints aquaOrWin32 -body {
# On mac and pc, when selection is cleared, entry widget remembers
# last selected range.  When selection ownership is restored to 
# last selected range.  When selection ownership is restored to
# entry, the old range will be rehighlighted.
# Previous settings:
	entry .e -font {Courier -12} -width 5 -bd 2 -relief sunken
	pack .e
	.e insert 0 012345678901234567890
	.e xview 4
	update
    .e select from 1
    .e select to 6
    list [.e index sel.first] [.e index sel.last]
# Testing:
    selection clear .e
    catch {selection get}
    .e index sel.first
} -cleanup {
    destroy .e
} -result {1}           
} -result 1

test entry-13.12 {GetEntryIndex procedure} -constraints x11 -body {
# Previous settings:
	entry .e -font {Courier -12} -width 5 -bd 2 -relief sunken
	pack .e
	.e insert 0 012345678901234567890
	.e xview 4
	update
    .e select from 1
    .e select to 6
    list [.e index sel.first] [.e index sel.last]
# Testing:
    selection clear .e
    .e index sbogus
} -cleanup {
    destroy .e
} -returnCodes error -result {selection isn't in widget .e}

# why when string in .e index changed to not beginning with s, 
# why when string in .e index changed to not beginning with s,
# it behaves differently?
test entry-13.12.1 {GetEntryIndex procedure} -constraints unix -body {
# Previous settings:
	entry .e -font {Courier -12} -width 5 -bd 2 -relief sunken
	pack .e
	.e insert 0 012345678901234567890
	.e xview 4
2673
2674
2675
2676
2677
2678
2679
2680





















2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714


2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729

2730
2731
2732
2733
2734
2735
2736
2737

2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748

2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759

2760
2761
2762

2763
2764
2765
2766
2767
2768
2769
2770

2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781

2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792

2793
2794

2795
2796
2797
2798
2799
2800
2801
2802
2803
2804

2805
2806
2807
2808
2809

2810
2811
2812

2813
2814
2815

2816
2817
2818
2819
2820
2821
2822
2823

2824
2825
2826

2827
2828
2829
2830
2831
2832
2833
2834

2835
2836
2837
2838
2839
2840
2841
2706
2707
2708
2709
2710
2711
2712

2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745






















2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761

2762
2763
2764
2765
2766
2767
2768
2769

2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780

2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791

2792
2793
2794

2795
2796
2797
2798
2799
2800
2801
2802

2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813

2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824

2825
2826

2827
2828
2829
2830
2831
2832
2833
2834
2835
2836

2837
2838
2839
2840
2841

2842
2843
2844

2845
2846
2847

2848
2849
2850
2851
2852
2853
2854
2855

2856
2857
2858

2859
2860
2861
2862
2863
2864
2865
2866

2867
2868
2869
2870
2871
2872
2873
2874







-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+












-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+














-
+







-
+










-
+










-
+


-
+







-
+










-
+










-
+

-
+









-
+




-
+


-
+


-
+







-
+


-
+







-
+







    .e index sbogus
} -cleanup {
    destroy .e
} -returnCodes error -result {bad entry index "sbogus"}

test entry-13.14 {GetEntryIndex procedure} -constraints win -body {
# On mac and pc, when selection is cleared, entry widget remembers
# last selected range.  When selection ownership is restored to 
# last selected range.  When selection ownership is restored to
# entry, the old range will be rehighlighted.
# Previous settings:
	entry .e -font {Courier -12} -width 5 -bd 2 -relief sunken
	pack .e
	.e insert 0 012345678901234567890
	.e xview 4
	update
    .e select from 1
    .e select to 6
    list [.e index sel.first] [.e index sel.last]
# Testing:
    selection clear .e
    selection get
} -cleanup {
    destroy .e
} -returnCodes error -match glob -result {*}

test entry-13.14.1 {GetEntryIndex procedure} -constraints win -body {
# On mac and pc, when selection is cleared, entry widget remembers
# last selected range.  When selection ownership is restored to
# entry, the old range will be rehighlighted.
# Previous settings:
	entry .e -font {Courier -12} -width 5 -bd 2 -relief sunken
	pack .e
	.e insert 0 012345678901234567890
	.e xview 4
	update
    .e select from 1
    .e select to 6
    list [.e index sel.first] [.e index sel.last]
# Testing:
    selection clear .e
    selection get 
} -cleanup {
    destroy .e
} -returnCodes error -match glob -result {*}

test entry-13.14.1 {GetEntryIndex procedure} -constraints win -body {
# On mac and pc, when selection is cleared, entry widget remembers
# last selected range.  When selection ownership is restored to 
# entry, the old range will be rehighlighted.
# Previous settings:
	entry .e -font {Courier -12} -width 5 -bd 2 -relief sunken
	pack .e
	.e insert 0 012345678901234567890
	.e xview 4
	update
    .e select from 1
    .e select to 6
    list [.e index sel.first] [.e index sel.last]
# Testing:
    selection clear .e  
    catch {selection get} 
    .e index sbogus      
    catch {selection get}
    .e index sbogus
} -cleanup {
    destroy .e
} -returnCodes error -match glob -result {*}

test entry-13.15 {GetEntryIndex procedure} -body {
    entry .e
    selection clear .e
    .e index @xyz
} -cleanup {
    destroy .e
} -returnCodes error -result {bad entry index "@xyz"}

test entry-13.16 {GetEntryIndex procedure} -constraints fonts -body {
    entry .e -width 5 -relief sunken -highlightthickness 2 -bd 2\
        -font {Courier -12} 
        -font {Courier -12}
    pack .e
    .e insert 0 012345678901234567890
    .e xview 4
    update
    .e index @4
} -cleanup {
    destroy .e
} -result {4}
} -result 4
test entry-13.17 {GetEntryIndex procedure} -constraints fonts -body {
    entry .e -width 5 -relief sunken -highlightthickness 2 -bd 2\
        -font {Courier -12}
    pack .e
    .e insert 0 012345678901234567890
    .e xview 4
    update
    .e index @11
} -cleanup {
    destroy .e
} -result {4}
} -result 4
test entry-13.18 {GetEntryIndex procedure} -constraints fonts -body {
    entry .e -width 5 -relief sunken -highlightthickness 2 -bd 2\
        -font {Courier -12}
    pack .e
    .e insert 0 012345678901234567890
    .e xview 4
    update
    .e index @12
} -cleanup {
    destroy .e
} -result {5}
} -result 5
test entry-13.19 {GetEntryIndex procedure} -constraints fonts -body {
    entry .e -width 5 -relief sunken -highlightthickness 2 -bd 2\
        -font {Courier -12} 
        -font {Courier -12}
    pack .e
    .e insert 0 012345678901234567890
    .e xview 4
    update
    .e index @[expr {[winfo width .e] - 6}]
} -cleanup {
    destroy .e
} -result {8}
} -result 8
test entry-13.20 {GetEntryIndex procedure} -constraints fonts -body {
    entry .e -width 5 -relief sunken -highlightthickness 2 -bd 2\
        -font {Courier -12}
    pack .e
    .e insert 0 012345678901234567890
    .e xview 4
    update
    .e index @[expr {[winfo width .e] - 5}]
} -cleanup {
    destroy .e
} -result {9}
} -result 9
test entry-13.21 {GetEntryIndex procedure} -body {
    entry .e -width 5 -relief sunken -highlightthickness 2 -bd 2\
        -font {Courier -12}
    pack .e
    .e insert 0 012345678901234567890
    .e xview 4
    update
    .e index @1000
} -cleanup {
    destroy .e
} -result {9}
} -result 9
test entry-13.22 {GetEntryIndex procedure} -setup {
    entry .e 
    entry .e
    pack .e
    update
} -body {
    .e index 1xyz
} -cleanup {
    destroy .e
} -returnCodes error -result {bad entry index "1xyz"}
test entry-13.23 {GetEntryIndex procedure} -body {
    entry .e -width 5 -relief sunken -highlightthickness 2 -bd 2\
        -font {Courier -12} 
        -font {Courier -12}
    pack .e
    .e insert 0 012345678901234567890
    .e xview 4
    update
    .e index -10
    .e index -1
} -cleanup {
    destroy .e
} -result {0}
} -result 0
test entry-13.24 {GetEntryIndex procedure} -body {
    entry .e -width 5 -relief sunken -highlightthickness 2 -bd 2\
        -font {Courier -12} 
        -font {Courier -12}
    pack .e
    .e insert 0 012345678901234567890
    .e xview 4
    update
    .e index 12
} -cleanup {
    destroy .e
} -result {12}
} -result 12
test entry-13.25 {GetEntryIndex procedure} -body {
    entry .e -width 5 -relief sunken -highlightthickness 2 -bd 2\
        -font {Courier -12} 
        -font {Courier -12}
    pack .e
    .e insert 0 012345678901234567890
    .e xview 4
    update
    .e index 49
} -cleanup {
    destroy .e
} -result {21}
} -result 21
test entry-13.26 {GetEntryIndex procedure} -constraints fonts -body {
    entry .e -highlightthickness 2 -bd 2 -font {Helvetica -12}
    selection clear .e
    .e configure -show .
    .e insert 0 XXXYZZY
    pack .e
    update
2868
2869
2870
2871
2872
2873
2874
2875

2876
2877
2878
2879
2880
2881

2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902

2903
2904
2905
2906
2907
2908
2909
2901
2902
2903
2904
2905
2906
2907

2908
2909
2910
2911
2912
2913

2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934

2935
2936
2937
2938
2939
2940
2941
2942







-
+





-
+




















-
+







test entry-14.3 {EntryFetchSelection procedure} -setup {
    set x {}
    for {set i 1} {$i <= 500} {incr i} {
        append x "This is line $i, out of 500\n"
}
} -body {
    entry .e
    .e insert end $x    
    .e insert end $x
    .e select from 0
    .e select to end
    string compare [selection get] $x
} -cleanup {
    destroy .e
} -result {0}
} -result 0

test entry-15.1 {EntryLostSelection} -body {
    entry .e
    .e insert 0 "Text"
    .e select from 0
    .e select to 4
    set result [selection get]
    selection clear
    .e select from 0
    .e select to 4
    lappend result [selection get]
} -cleanup {
    destroy .e
} -result {Text Text}

# is scrollcommand needed here??
test entry-16.1 {EntryVisibleRange procedure} -constraints fonts  -body {
    entry .e -width 10 -font {Helvetica -12}
    pack .e
    update
    .e insert 0 "............................." 
    .e insert 0 "............................."
    format {%.6f %.6f} {*}[.e xview]
} -cleanup {
    destroy .e
} -result {0.000000 0.827586}
test entry-16.2 {EntryVisibleRange procedure} -constraints {
    unix fonts
} -body {
2933
2934
2935
2936
2937
2938
2939


2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951

2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963

2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979

2980


2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001

3002
3003
3004
3005
3006
3007
3008
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976

2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988

2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000

3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012

3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036

3037
3038
3039
3040
3041
3042
3043
3044







+
+


-









+


-









+


-












-
+

+
+




















-
+







    destroy .e
} -result {0.000000 1.000000}


test entry-17.1 {EntryUpdateScrollbar procedure} -body {
    entry .e -width 10 -xscrollcommand scroll -font {Courier -12}
    pack .e
    update idletasks
    set timeout [after 500 {set scrollInfo {-1000000 -1000000}}]
    .e delete 0 end
    .e insert 0 123
    set timeout [after 500 {set $scrollInfo "timeout"}]
    vwait scrollInfo
    format {%.6f %.6f} {*}$scrollInfo
} -cleanup {
    destroy .e
    after cancel $timeout
} -result {0.000000 1.000000}
test entry-17.2 {EntryUpdateScrollbar procedure} -body {
    entry .e -width 10 -xscrollcommand scroll -font {Courier -12}
    pack .e
    set timeout [after 500 {set scrollInfo {-1000000 -1000000}}]
    .e insert 0 0123456789abcdef
    .e xview 3
    set timeout [after 500 {set $scrollInfo "timeout"}]
    vwait scrollInfo
    format {%.6f %.6f} {*}$scrollInfo
} -cleanup {
    destroy .e
    after cancel $timeout
} -result {0.187500 0.812500}
test entry-17.3 {EntryUpdateScrollbar procedure} -body {
    entry .e -width 10 -xscrollcommand scroll -font {Courier -12}
    pack .e
    set timeout [after 500 {set scrollInfo {-1000000 -1000000}}]
    .e insert 0 abcdefghijklmnopqrs
    .e xview 6
    set timeout [after 500 {set $scrollInfo "timeout"}]
    vwait scrollInfo
    format {%.6f %.6f} {*}$scrollInfo
} -cleanup {
    destroy .e
    after cancel $timeout
} -result {0.315789 0.842105}
test entry-17.4 {EntryUpdateScrollbar procedure} -setup {
    proc bgerror msg {
	global x
	set x $msg
}
} -body {
    entry .e -width 5 -xscrollcommand thisisnotacommand
    entry .e -width 5
    pack .e
    update idletasks
    .e configure -xscrollcommand thisisnotacommand
    vwait x
    list $x $errorInfo
} -cleanup {
    destroy .e
    rename bgerror {}
} -result {{invalid command name "thisisnotacommand"} {invalid command name "thisisnotacommand"
    while executing
"thisisnotacommand 0.0 1.0"
    (horizontal scrolling command executed by .e)}}


test entry-18.1 {Entry widget vs hiding} -setup {
    entry .e
} -body {
    set l [interp hidden]
    interp hide {} .e
    destroy .e
    set res1 [list [winfo children .] [interp hidden]]
    set res2 [list {} $l]
    expr {$res1 == $res2}
} -result {1} 
} -result 1

##
## Entry widget VALIDATION tests
##
# The validation tests build each one upon the previous, so cascading
# failures aren't good
#
3016
3017
3018
3019
3020
3021
3022
3023

3024
3025
3026
3027
3028
3029
3030
3052
3053
3054
3055
3056
3057
3058

3059
3060
3061
3062
3063
3064
3065
3066







-
+







    entry .e -validate all \
        -validatecommand [list doval %W %d %i %P %s %S %v %V] \
        -invalidcommand bell \
        -textvariable ::e \
        -background red -foreground white
    pack .e
    .e insert 0 a
    return $::vVals
    set ::vVals
} -cleanup {
    destroy .e
} -result {.e 1 0 a {} a all key}

test entry-19.2 {entry widget validation} -setup {
    unset -nocomplain ::e ::vVals
} -body {
3048
3049
3050
3051
3052
3053
3054
3055

3056
3057
3058
3059
3060
3061
3062
3084
3085
3086
3087
3088
3089
3090

3091
3092
3093
3094
3095
3096
3097
3098







-
+







        -validatecommand [list doval %W %d %i %P %s %S %v %V] \
        -invalidcommand bell \
        -textvariable ::e \
        -background red -foreground white
    pack .e
    .e insert 0 ab   ;# previous settings
    .e insert end c
    return $::vVals
    set ::vVals
} -cleanup {
    destroy .e
} -result {.e 1 2 abc ab c all key}

test entry-19.4 {entry widget validation} -setup {
    unset -nocomplain ::e ::vVals
} -body {
3080
3081
3082
3083
3084
3085
3086
3087

3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104

3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121

3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140

3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161

3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179

3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200

3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218

3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237

3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256

3257
3258
3259
3260
3261
3262
3263
3116
3117
3118
3119
3120
3121
3122

3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139

3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156

3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175

3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196

3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214

3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235

3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253

3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272

3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291

3292
3293
3294
3295
3296
3297
3298
3299







-
+
















-
+
















-
+


















-
+




















-
+

















-
+




















-
+

















-
+


















-
+


















-
+







        -validatecommand [list doval %W %d %i %P %s %S %v %V] \
        -invalidcommand bell \
        -textvariable ::e \
        -background red -foreground white
    pack .e
    .e insert 0 a123bc   ;# previous settings
    .e delete 2
    return $::vVals
    set ::vVals
} -cleanup {
    destroy .e
} -result {.e 0 2 a13bc a123bc 2 all key}

test entry-19.6 {entry widget validation} -setup {
    unset -nocomplain ::e ::vVals
} -body {
    entry .e -validate all \
        -validatecommand [list doval %W %d %i %P %s %S %v %V] \
        -invalidcommand bell \
        -textvariable ::e \
        -background red -foreground white
    pack .e
    .e insert 0 a13bc   ;# previous settings
    .e configure -validate key
    .e delete 1 3
    return $::vVals
    set ::vVals
} -cleanup {
    destroy .e
} -result {.e 0 1 abc a13bc 13 key key}

test entry-19.7 {entry widget validation} -setup {
    unset -nocomplain ::e ::vVals
} -body {
    entry .e -validate focus \
        -validatecommand [list doval %W %d %i %P %s %S %v %V] \
        -invalidcommand bell \
        -textvariable ::e \
        -background red -foreground white
    pack .e
    .e insert end abc                 ;# previous settings
    set ::vVals {}
    .e insert end d
    return $::vVals
    set ::vVals
} -cleanup {
    destroy .e
} -result {}

test entry-19.8 {entry widget validation} -setup {
    unset -nocomplain ::e ::vVals
} -body {
    entry .e -validate all \
        -validatecommand [list doval %W %d %i %P %s %S %v %V] \
        -invalidcommand bell \
        -textvariable ::e \
        -background red -foreground white
    pack .e
    .e configure -validate focus    ;# previous settings
    .e insert end abcd              ;# previous settings
    focus -force .e
# update necessary to process FocusIn event
    update
    return $::vVals
    set ::vVals
} -cleanup {
    destroy .e
} -result {.e -1 -1 abcd abcd {} focus focusin}

test entry-19.9 {entry widget validation} -setup {
    unset -nocomplain ::e ::vVals
} -body {
    entry .e -validate focus \
        -validatecommand [list doval %W %d %i %P %s %S %v %V] \
        -invalidcommand bell \
        -textvariable ::e \
        -background red -foreground white
    pack .e
    .e insert end abcd      ;# previous settings
    focus -force .e         ;# previous settings
    update                  ;# previous settings
# update necessary to process FocusIn event
    focus -force .
# update necessary to process FocusOut event
    update
    return $::vVals
    set ::vVals
} -cleanup {
    destroy .e
} -result {.e -1 -1 abcd abcd {} focus focusout}

test entry-19.10 {entry widget validation} -setup {
    unset -nocomplain ::e ::vVals
} -body {
    entry .e -validate all \
        -validatecommand [list doval %W %d %i %P %s %S %v %V] \
        -invalidcommand bell \
        -textvariable ::e \
        -background red -foreground white
    pack .e
    .e insert end abcd          ;# previous settings
    focus -force .e
# update necessary to process FocusIn event
    update
    return $::vVals
    set ::vVals
} -cleanup {
    destroy .e
} -result {.e -1 -1 abcd abcd {} all focusin}

test entry-19.11 {entry widget validation} -setup {
    unset -nocomplain ::e ::vVals
} -body {
    entry .e -validate all \
        -validatecommand [list doval %W %d %i %P %s %S %v %V] \
        -invalidcommand bell \
        -textvariable ::e \
        -background red -foreground white
    pack .e
    .e insert end abcd          ;# previous settings
    focus -force .e             ;# previous settings
# update necessary to process FocusIn event
    update                      ;# previous settings
    focus -force .
# update necessary to process FocusOut event
    update
    return $::vVals
    set ::vVals
} -cleanup {
    destroy .e
} -result {.e -1 -1 abcd abcd {} all focusout}

test entry-19.12 {entry widget validation} -setup {
    unset -nocomplain ::e ::vVals
} -body {
    entry .e -validate focusin \
        -validatecommand [list doval %W %d %i %P %s %S %v %V] \
        -invalidcommand bell \
        -textvariable ::e \
        -background red -foreground white
    pack .e
    .e insert 0 abcd              ;# previous settings
    focus -force .e
# update necessary to process FocusIn event
    update
    return $::vVals
    set ::vVals
} -cleanup {
    destroy .e
} -result {.e -1 -1 abcd abcd {} focusin focusin}

test entry-19.13 {entry widget validation} -setup {
    unset -nocomplain ::e ::vVals
} -body {
    entry .e -validate focusin \
        -validatecommand [list doval %W %d %i %P %s %S %v %V] \
        -invalidcommand bell \
        -textvariable ::e \
        -background red -foreground white
    pack .e
    .e insert end abcd              ;# previous settings
    set ::vVals {}
    focus -force .
# update necessary to process FocusOut event
    update
    return $::vVals
    set ::vVals
} -cleanup {
    destroy .e
} -result {}

test entry-19.14 {entry widget validation} -setup {
    unset -nocomplain ::e ::vVals
} -body {
    entry .e -validate focuso \
        -validatecommand [list doval %W %d %i %P %s %S %v %V] \
        -invalidcommand bell \
        -textvariable ::e \
        -background red -foreground white
    pack .e
    .e insert end abcd              ;# previous settings
    set ::vVals {}                  ;# previous settings
    focus -force .e
# update necessary to process FocusIn event
    update
    return $::vVals
    set ::vVals
} -cleanup {
    destroy .e
} -result {}

test entry-19.15 {entry widget validation} -setup {
    unset -nocomplain ::e ::vVals
} -body {
3271
3272
3273
3274
3275
3276
3277
3278

3279
3280
3281
3282
3283
3284
3285
3307
3308
3309
3310
3311
3312
3313

3314
3315
3316
3317
3318
3319
3320
3321







-
+







    set ::vVals {}                  ;# previous settings
    focus -force .e                 ;# previous settings
# update necessary to process FocusIn event
    update                          ;# previous settings
    focus -force .
# update necessary to process FocusOut event
    update
    return $::vVals
    set ::vVals
} -cleanup {
    destroy .e
} -result {.e -1 -1 abcd abcd {} focusout focusout}

# the same as 19.16 but added [.e validate] to returned list
test entry-19.16 {entry widget validation} -setup {
    unset -nocomplain ::e ::vVals
3348
3349
3350
3351
3352
3353
3354
3355

3356
3357
3358
3359
3360
3361

3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380

3381
3382
3383
3384
3385
3386




















3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400

3401
3402
3403
3404
3405
3406
3407
3408
3409
3410

3411
3412
3413
3414
3415
3416
3417
3418
3419

3420
3421
3422
3423
3424
3425
3426
3427
3428
3429

3430
3431
3432
3433
3434
3435
3436
3437

3438
3439
3440
3441
3442
3443
3444
3445
3446
3447

3448
3449
3450
3451
3452
3453

3454
3455
3456
3457
3458
3459

3460
3461
3462
3463
3464
3465
3466
3384
3385
3386
3387
3388
3389
3390

3391
3392
3393
3394
3395
3396

3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415

3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455

3456
3457
3458
3459
3460
3461
3462
3463
3464
3465

3466
3467
3468
3469
3470
3471
3472
3473
3474

3475
3476
3477
3478
3479
3480
3481
3482
3483
3484

3485
3486
3487
3488
3489
3490
3491
3492

3493
3494
3495
3496
3497
3498
3499
3500
3501
3502

3503
3504
3505
3506
3507
3508

3509
3510
3511
3512
3513
3514

3515
3516
3517
3518
3519
3520
3521
3522







-
+





-
+


















-
+






+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+













-
+









-
+








-
+









-
+







-
+









-
+





-
+





-
+







    entry .e -validate all \
        -validatecommand [list doval3 %W %d %i %P %s %S %v %V] \
        -invalidcommand bell \
        -textvariable ::e \
        -background red -foreground white
    pack .e
    set ::e nextdata                 ;# previous settings
    

    .e configure -validatecommand [list doval2 %W %d %i %P %s %S %v %V]
    .e validate
    list [.e cget -validate] [.e get] $::vVals
} -cleanup {
    destroy .e
} -result {none mydata {.e -1 -1 nextdata nextdata {} all forced}}
} -result {none nextdata {.e -1 -1 nextdata nextdata {} all forced}}

## This leaves validate alone because we trigger validation through the
## textvar (a write trace), and the write during validation triggers
## nothing (by definition of avoiding loops on var traces).  This is
## one of those "dangerous" conditions where the user will have a
## different value in the entry widget shown as is in the textvar.
test entry-19.20 {entry widget validation} -setup {
    unset -nocomplain ::e ::vVals
} -body {
    entry .e -validate all \
        -validatecommand [list doval %W %d %i %P %s %S %v %V] \
        -invalidcommand bell \
        -textvariable ::e \
        -background red -foreground white
    pack .e
    set ::e nextdata                 ;# previous settings
    .e configure -validatecommand [list doval2 %W %d %i %P %s %S %v %V] ;# prev
    .e validate                     ;# previous settings
    

    .e configure -validate all
    set ::e testdata
    list [.e cget -validate] [.e get] $::e $::vVals
} -cleanup {
    destroy .e
} -result {all testdata mydata {.e -1 -1 testdata mydata {} all forced}}

## This leaves validate alone because we trigger validation through the
## textvar (a write trace), and the write during validation triggers
## nothing (by definition of avoiding loops on var traces).  This is
## one of those "dangerous" conditions where the user will have a
## different value in the entry widget shown as is in the textvar.
test entry-19.21 {entry widget validation - bug 40e4bf6198} -setup {
    unset -nocomplain ::e ::vVals
} -body {
    entry .e -validate key \
        -validatecommand [list doval2 %W %d %i %P %s %S %v %V] \
        -textvariable ::e
    pack .e
    set ::e origdata
    .e insert 0 A
    list [.e cget -validate] [.e get] $::e $::vVals
} -cleanup {
    destroy .e
} -result {none origdata mydata {.e 1 0 Aorigdata origdata A key key}}

##
## End validation tests
##

test entry-20.1 {widget deletion while active} -body {
    entry .e -validate all \
	    -validatecommand { destroy %W ; return 1 } \
	    -invalidcommand bell
    update
    .e insert 0 abc
    winfo exists .e
} -cleanup {
    destroy .e
} -result {0}
} -result 0

test entry-20.2 {widget deletion while active} -body {
    entry .e -validate all \
	    -validatecommand { return 0 } \
	    -invalidcommand { destroy %W }
    .e insert 0 abc
    winfo exists .e
} -cleanup {
    destroy .e
} -result {0}
} -result 0

test entry-20.3 {widget deletion while active} -body {
    entry .e -validate all \
	    -validatecommand { rename .e {} ; return 1 }
    .e insert 0 abc
    winfo exists .e
} -cleanup {
    destroy .e
} -result {0}
} -result 0

test entry-20.4 {widget deletion while active} -body {
    entry .e -validate all \
	    -validatecommand { return 0 } \
	    -invalidcommand { rename .e {} }
    .e insert 0 abc
    winfo exists .e
} -cleanup {
    destroy .e
} -result {0}
} -result 0

test entry-20.5 {widget deletion while active} -body {
    entry .e -validatecommand { destroy .e ; return 0 }
    .e validate
    winfo exists .e
} -cleanup {
    destroy .e
} -result {0}
} -result 0

test entry-20.6 {widget deletion while active} -body {
    pack [entry .e]
    update
    .e config -xscrollcommand { destroy .e }
    update idle
    winfo exists .e
} -cleanup {
    destroy .e
} -result {0}
} -result 0

test entry-20.7 {widget deletion with textvariable active} -body {
# SF bugs 607390 and 617446
    set FOO init
    entry .e -textvariable FOO -validate all \
	    -vcmd {%W configure -bg white; format 1}
	    -validatecommand {%W configure -bg white; format 1}
    bind .e <Destroy> { set FOO hello }
    destroy .e
    winfo exists .e
} -cleanup {
    destroy .e
} -result {0}
} -result 0


test entry-21.1 {selection present while disabled, bug 637828} -body {
    entry .e
    .e insert end 0123456789
    .e select from 3
    .e select to 6
Changes to tests/event.test.
1
2
3
4
5
6



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

49
50
51
52
53
54
55
56
57

58
59
60
61
62
63

64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83

84
85
86
87
88
89
90
91
92


93
94
95
96
97
98
99
1
2
3



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22



23























24









25






26










27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44


45
46
47
48
49
50
51
52
53



-
-
-
+
+
+
















-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-










+







-
-
+
+







# This file is a Tcl script to test the code in tkEvent.c.  It is
# organized in the standard fashion for Tcl tests.
#
# Copyright (c) 1994 The Regents of the University of California.
# Copyright (c) 1994-1995 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1994 The Regents of the University of California.
# Copyright © 1994-1995 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
eval tcltest::configure $argv
tcltest::loadTestedCommands
namespace import -force tcltest::test

# XXX This test file is woefully incomplete.  Right now it only tests
# a few of the procedures in tkEvent.c.  Please add more tests whenever
# possible.

# Setup table used to query key events.

proc _init_keypress_lookup {} {
    global keypress_lookup

    scan A %c start
    scan Z %c finish

    # Characters with meaning to Tcl...
    for {set i $start} {$i <= $finish} {incr i} {
        set l [format %c $i]
        set keypress_lookup($l) $l
    }

    scan a %c start
    scan z %c finish

    for {set i $start} {$i <= $finish} {incr i} {
        set l [format %c $i]
        set keypress_lookup($l) $l
    }

    scan 0 %c start
    scan 9 %c finish

    for {set i $start} {$i <= $finish} {incr i} {
        set l [format %c $i]
        set keypress_lookup($l) $l
    }

    # Most punctuation
    array set keypress_lookup {
    array set keypress_lookup [list \
        ! exclam
        % percent
        & ampersand
        ( parenleft
        ) parenright
        * asterisk
        + plus
        , comma
        - minus
	    -    minus \
        . period
        / slash
        : colon
        < less
        = equal
        > greater
	    >    greater \
        ? question
        @ at
        ^ asciicircum
        _ underscore
        | bar
        ~ asciitilde
        ' apostrophe
    }
    # Characters with meaning to Tcl...
    array set keypress_lookup [list \
	    \"   quotedbl \
	    \#   numbersign \
	    \$   dollar \
	    \;   semicolon \
	    \[   bracketleft \
	    \\   backslash \
	    \]   bracketright \
	    \{   braceleft \
	    \}   braceright \
	    " "  space \
	    \xA0 nobreakspace \
	    "\n" Return \
	    "\t" Tab]
}

# Lookup an event in the keypress table.
# For example:
# Q -> Q
# . -> period
# / -> slash
# ; -> semicolon
# > -> greater
# Delete -> Delete
# Escape -> Escape

proc _keypress_lookup {char} {
    global keypress_lookup

    if {! [info exists keypress_lookup]} {
107
108
109
110
111
112
113
114

115
116
117
118
119
120
121
122
123
124
125
126
127

128
129
130
131
132
133
134
61
62
63
64
65
66
67

68
69
70
71
72
73
74
75
76
77
78
79
80

81
82
83
84
85
86
87
88







-
+












-
+







    if {[info exists keypress_lookup($char)]} {
        return $keypress_lookup($char)
    } else {
        return $char
    }
}

# Lookup and generate a pair of KeyPress and KeyRelease events
# Lookup and generate a pair of Key and KeyRelease events

proc _keypress {win key} {
    set keysym [_keypress_lookup $key]

    # Force focus to the window before delivering
    # each event so that a window manager using
    # a focus follows mouse will not steal away
    # the focus if the mouse is moved around.

    if {[focus] != $win} {
        focus -force $win
    }
    event generate $win <KeyPress-$keysym>
    event generate $win <Key-$keysym>
    _pause 50
    if {[focus] != $win} {
        focus -force $win
    }
    event generate $win <KeyRelease-$keysym>
    _pause 50
}
190
191
192
193
194
195
196
197

198
199
200

201
202
203
204
205
206
207
144
145
146
147
148
149
150

151
152
153

154
155
156
157
158
159
160
161







-
+


-
+







} -body {
    button .b -text Test
    pack .b
    bindtags .b .b
    update
    bind .b <Destroy> {
	    lappend x destroy
	    event generate .b <1>
	    event generate .b <Button-1>
	    event generate .b <ButtonRelease-1>
    }
    bind .b <1> {
    bind .b <Button-1> {
	    lappend x button
    }

    destroy .b
    return $x
} -cleanup {
    deleteWindows
241
242
243
244
245
246
247
248

249
250
251
252
253
254
255
195
196
197
198
199
200
201

202
203
204
205
206
207
208
209







-
+







test event-2.2(keypress) {type into entry widget and then delete some text} -setup {
	deleteWindows
} -body {
    set t [toplevel .t]
    set e [entry $t.e]
    pack $e
    tkwait visibility $e
    # Avoid a hang when macOS puts the mouse pointer on the green button 
    # Avoid a hang when macOS puts the mouse pointer on the green button
    wm geometry .t +200+100
    _keypress_string $e MELLO
    _keypress $e BackSpace
    _keypress $e BackSpace
    $e get
} -cleanup {
    deleteWindows
265
266
267
268
269
270
271
272

273
274
275
276
277
278
279
219
220
221
222
223
224
225

226
227
228
229
230
231
232
233







-
+







    _keypress_string $e JUMP

    set result [$e get]

    event generate $e <Enter>
    for {set i 0} {$i < 3} {incr i} {
        _pause 100
        event generate $e <ButtonPress-1>
        event generate $e <Button-1>
        _pause 100
        event generate $e <ButtonRelease-1>
    }

    _keypress $e Delete
    _keypress_string $e UP
    lappend result [$e get]
319
320
321
322
323
324
325
326

327
328
329
330
331
332
333
273
274
275
276
277
278
279

280
281
282
283
284
285
286
287







-
+







    _keypress_string $e JUMP

    set result [$e get 1.0 1.end]

    event generate $e <Enter>
    for {set i 0} {$i < 3} {incr i} {
        _pause 100
        event generate $e <ButtonPress-1>
        event generate $e <Button-1>
        _pause 100
        event generate $e <ButtonRelease-1>
    }

    _keypress $e Delete
    _keypress_string $e UP
    lappend result [$e get 1.0 1.end]
351
352
353
354
355
356
357
358

359
360
361
362

363
364
365
366
367
368
369
305
306
307
308
309
310
311

312
313
314
315

316
317
318
319
320
321
322
323







-
+



-
+







    lappend result [$e get 1.0 1.end]

    # Get the x,y coords of the second T in "Tcl/Tk"
    foreach {anchor_x anchor_y} [_text_ind_to_x_y $e $anchor] break

    # Click down to set the insert cursor position
    event generate $e <Enter>
    event generate $e <ButtonPress-1> -x $anchor_x -y $anchor_y
    event generate $e <Button-1> -x $anchor_x -y $anchor_y

    # Save the position of the insert cursor
    lappend result [$e index insert]
    

    # Now drag until selend is highlighted, then click up

    set current $anchor
    while {[$e compare $current <= $selend]} {
        foreach {current_x current_y} [_text_ind_to_x_y $e $current] break
        event generate $e <B1-Motion> -x $current_x -y $current_y
        set current [$e index [list $current + 1 char]]
377
378
379
380
381
382
383
384

385
386
387
388
389
390
391
331
332
333
334
335
336
337

338
339
340
341
342
343
344
345







-
+







    lappend result [$e index insert]

    # Save the highlighted text
    lappend result [_get_selection $e]

    # Now click and click and drag to the left, over "Tcl/Tk selection"

    event generate $e <ButtonPress-1> -x $current_x -y $current_y
    event generate $e <Button-1> -x $current_x -y $current_y

    while {[$e compare $current >= [list $anchor - 4 char]]} {
        foreach {current_x current_y} [_text_ind_to_x_y $e $current] break
        event generate $e <B1-Motion> -x $current_x -y $current_y
        set current [$e index [list $current - 1 char]]
        _pause 50
    }
418
419
420
421
422
423
424
425

426
427
428
429

430
431
432
433
434
435
436
372
373
374
375
376
377
378

379
380
381
382

383
384
385
386
387
388
389
390







-
+



-
+







    lappend result [$e get]

    # Get the x,y coords of the second T in "Tcl/Tk"
    foreach {anchor_x anchor_y} [_text_ind_to_x_y $e $anchor] break

    # Click down to set the insert cursor position
    event generate $e <Enter>
    event generate $e <ButtonPress-1> -x $anchor_x -y $anchor_y
    event generate $e <Button-1> -x $anchor_x -y $anchor_y

    # Save the position of the insert cursor
    lappend result [$e index insert]
    

    # Now drag until selend is highlighted, then click up

    set current $anchor
    while {$current <= $selend} {
        foreach {current_x current_y} [_text_ind_to_x_y $e $current] break
        event generate $e <B1-Motion> -x $current_x -y $current_y
        incr current
444
445
446
447
448
449
450
451

452
453
454
455
456
457
458
398
399
400
401
402
403
404

405
406
407
408
409
410
411
412







-
+







    lappend result [$e index insert]

    # Save the highlighted text
    lappend result [_get_selection $e]

    # Now click and click and drag to the left, over "Tcl/Tk selection"

    event generate $e <ButtonPress-1> -x $current_x -y $current_y
    event generate $e <Button-1> -x $current_x -y $current_y

    while {$current >= ($anchor - 4)} {
        foreach {current_x current_y} [_text_ind_to_x_y $e $current] break
        event generate $e <B1-Motion> -x $current_x -y $current_y
        incr current -1
        _pause 50
    }
483
484
485
486
487
488
489
490

491
492
493
494

495
496
497
498
499
500
501
437
438
439
440
441
442
443

444
445
446
447

448
449
450
451
452
453
454
455







-
+



-
+







    set anchor 1.8

    # Get the x,y coords of the second e in "select"
    foreach {anchor_x anchor_y} [_text_ind_to_x_y $e $anchor] break

    # Click down, release, then click down again
    event generate $e <Enter>
    event generate $e <ButtonPress-1> -x $anchor_x -y $anchor_y
    event generate $e <Button-1> -x $anchor_x -y $anchor_y
    _pause 50
    event generate $e <ButtonRelease-1> -x $anchor_x -y $anchor_y
    _pause 50
    event generate $e <ButtonPress-1> -x $anchor_x -y $anchor_y
    event generate $e <Button-1> -x $anchor_x -y $anchor_y
    _pause 50

    # Save the highlighted text
    set result [list]
    lappend result [_get_selection $e]

    # Insert cursor should be at beginning of "select"
554
555
556
557
558
559
560
561

562
563
564
565

566
567
568
569
570
571
572
508
509
510
511
512
513
514

515
516
517
518

519
520
521
522
523
524
525
526







-
+



-
+







    set anchor 8

    # Get the x,y coords of the second e in "select"
    foreach {anchor_x anchor_y} [_text_ind_to_x_y $e $anchor] break

    # Click down, release, then click down again
    event generate $e <Enter>
    event generate $e <ButtonPress-1> -x $anchor_x -y $anchor_y
    event generate $e <Button-1> -x $anchor_x -y $anchor_y
    _pause 50
    event generate $e <ButtonRelease-1> -x $anchor_x -y $anchor_y
    _pause 50
    event generate $e <ButtonPress-1> -x $anchor_x -y $anchor_y
    event generate $e <Button-1> -x $anchor_x -y $anchor_y
    _pause 50

    set result [list]
    lappend result [_get_selection $e]

    # Insert cursor should be at the end of "select"
    lappend result [$e index insert]
608
609
610
611
612
613
614
615

616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633

634
635
636
637
638

639
640
641
642
643

644
645
646
647
648
649
650
562
563
564
565
566
567
568

569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586

587
588
589
590
591

592
593
594
595
596

597
598
599
600
601
602
603
604







-
+

















-
+




-
+




-
+







    lappend result [$e index insert]

    return $result
} -cleanup {
    deleteWindows
} -result {select 11 7 select 4 { select} {Word select} 2}

test event-5.1(triple-click-drag) {Triple click and drag across lines in a 
test event-5.1(triple-click-drag) {Triple click and drag across lines in a
        text widget, this should extend the selection to the new line} -setup {
	deleteWindows
} -body {
    set t [toplevel .t]
    set e [text $t.e]
    pack $e
    tkwait visibility $e
    _keypress_string $e "LINE ONE\nLINE TWO\nLINE THREE"

    set anchor 3.2

    # Triple click one third line leaving mouse down

    foreach {anchor_x anchor_y} [_text_ind_to_x_y $e $anchor] break

    event generate $e <Enter>

    event generate $e <ButtonPress-1> -x $anchor_x -y $anchor_y
    event generate $e <Button-1> -x $anchor_x -y $anchor_y
    _pause 50
    event generate $e <ButtonRelease-1> -x $anchor_x -y $anchor_y
    _pause 50

    event generate $e <ButtonPress-1> -x $anchor_x -y $anchor_y
    event generate $e <Button-1> -x $anchor_x -y $anchor_y
    _pause 50
    event generate $e <ButtonRelease-1> -x $anchor_x -y $anchor_y
    _pause 50

    event generate $e <ButtonPress-1> -x $anchor_x -y $anchor_y
    event generate $e <Button-1> -x $anchor_x -y $anchor_y
    _pause 50

    set result [list]
    lappend result [_get_selection $e]

    # Drag up to second line

676
677
678
679
680
681
682
683

684
685
686
687
688
689
690
630
631
632
633
634
635
636

637
638
639
640
641
642
643
644







-
+







        destroyed, when the mouse is moved into another window it
        should not generate a <B1-motion> event since the mouse
        was not pressed down in that window} -setup {
	deleteWindows
} -body {
    set t [toplevel .t]

    event generate $t <ButtonPress-1>
    event generate $t <Button-1>
    destroy $t
    set t [toplevel .t]
    set motion nomotion
    bind $t <B1-Motion> {set motion inmotion}
    event generate $t <Motion>
    return $motion
} -cleanup {
715
716
717
718
719
720
721
722

723
724
725
726

727
728
729
730
731
732
733
734
735
736
737

738
739
740
741
742
743
744

745
746
747
748

749
750
751
752
753
754
755
669
670
671
672
673
674
675

676
677
678
679

680
681
682
683
684
685
686
687
688
689
690

691
692
693
694
695
696
697

698
699
700
701

702
703
704
705
706
707
708
709







-
+



-
+










-
+






-
+



-
+








    set right_x [expr {($x1 + $width) - 2}]
    set right_y $middle_y

    # Double click near left hand egde of the letter A

    event generate $e <Enter>
    event generate $e <ButtonPress-1> -x $left_x -y $left_y
    event generate $e <Button-1> -x $left_x -y $left_y
    _pause 50
    event generate $e <ButtonRelease-1> -x $left_x -y $left_y
    _pause 50
    event generate $e <ButtonPress-1> -x $left_x -y $left_y
    event generate $e <Button-1> -x $left_x -y $left_y
    _pause 50
    event generate $e <ButtonRelease-1> -x $left_x -y $left_y
    _pause 50

    set result [list]
    lappend result [$e index insert]
    lappend result [_get_selection $e]

    # Clear selection by clicking at 0,0

    event generate $e <ButtonPress-1> -x 0 -y 0
    event generate $e <Button-1> -x 0 -y 0
    _pause 50
    event generate $e <ButtonRelease-1> -x 0 -y 0
    _pause 50

    # Double click near right hand edge of the letter A

    event generate $e <ButtonPress-1> -x $right_x -y $right_y
    event generate $e <Button-1> -x $right_x -y $right_y
    _pause 50
    event generate $e <ButtonRelease-1> -x $right_x -y $right_y
    _pause 50
    event generate $e <ButtonPress-1> -x $right_x -y $right_y
    event generate $e <Button-1> -x $right_x -y $right_y
    _pause 50
    event generate $e <ButtonRelease-1> -x $right_x -y $right_y
    _pause 50

    lappend result [$e index insert]
    lappend result [_get_selection $e]

781
782
783
784
785
786
787
788

789
790
791
792

793
794
795
796
797
798
799
800

801
802
803

804
805
806
807
808
809
810

811
812
813
814

815
816
817
818
819
820
821
822
823
824
825
826
827
828

829
830
831
832
833
834
835
836
837

838
839
840
841
842
843
844
735
736
737
738
739
740
741

742
743
744
745

746
747
748
749
750
751
752
753

754
755
756

757
758
759
760
761
762
763

764
765
766
767

768
769
770
771
772
773
774
775
776
777
778
779
780
781

782
783
784
785
786
787
788
789
790

791
792
793
794
795
796
797
798







-
+



-
+







-
+


-
+






-
+



-
+













-
+








-
+








    set right_x [expr {($x1 + $width) - 2}]
    set right_y $middle_y

    # Double click near left hand egde of the letter A

    event generate $e <Enter>
    event generate $e <ButtonPress-1> -x $left_x -y $left_y
    event generate $e <Button-1> -x $left_x -y $left_y
    _pause 50
    event generate $e <ButtonRelease-1> -x $left_x -y $left_y
    _pause 50
    event generate $e <ButtonPress-1> -x $left_x -y $left_y
    event generate $e <Button-1> -x $left_x -y $left_y
    _pause 50
    event generate $e <ButtonRelease-1> -x $left_x -y $left_y
    _pause 50

    set result [list]
    lappend result [$e index insert]
    lappend result [_get_selection $e]
  

    # Clear selection by clicking at 0,0

    event generate $e <ButtonPress-1> -x 0 -y 0
    event generate $e <Button-1> -x 0 -y 0
    _pause 50
    event generate $e <ButtonRelease-1> -x 0 -y 0
    _pause 50

    # Double click near right hand edge of the letter A

    event generate $e <ButtonPress-1> -x $right_x -y $right_y
    event generate $e <Button-1> -x $right_x -y $right_y
    _pause 50
    event generate $e <ButtonRelease-1> -x $right_x -y $right_y
    _pause 50
    event generate $e <ButtonPress-1> -x $right_x -y $right_y
    event generate $e <Button-1> -x $right_x -y $right_y
    _pause 50
    event generate $e <ButtonRelease-1> -x $right_x -y $right_y
    _pause 50

    lappend result [$e index insert]
    lappend result [_get_selection $e]

    return $result
} -cleanup {
    deleteWindows
} -result {4 A 4 A}

test event-8 {event generate with keysyms corresponding to
              multi-byte virtual keycodes - bug 
              multi-byte virtual keycodes - bug
              e36963bfe8df9f5e528134707a91b9c0051de723} -constraints nonPortable -setup {
    deleteWindows
    set res [list ]
} -body {
    set t [toplevel .t]
    set e [entry $t.e]
    pack $e
    tkwait visibility $e
    bind $e <KeyPress> {lappend res keycode: %k keysym: %K}
    bind $e <Key> {lappend res keycode: %k keysym: %K}
    focus -force $e
    update
    event generate $e <diaeresis>
    # The value now contained in $res depends on the actual
    # physical keyboard layout and keycode generated, from
    # the hardware on which the test suite happens to run.
    # We don't need (and we can't really) check correctness
856
857
858
859
860
861
862

863
864
865
866
867
868
869
870
871
872
873
874
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829







+












                physical key - in this case, test is actually void."
    }
} -cleanup {
    deleteWindows
} -result {OK}

# cleanup
update
unset -nocomplain keypress_lookup
rename _init_keypress_lookup {}
rename _keypress_lookup {}
rename _keypress {}
rename _pause {}
rename _text_ind_to_x_y {}
rename _get_selection {}

cleanupTests
return


Changes to tests/filebox.test.
1
2
3
4
5
6


7
8
9

10
11
12
13
14
15
16
1
2
3
4


5
6
7
8

9
10
11
12
13
14
15
16




-
-
+
+


-
+







# This file is a Tcl script to test out Tk's "tk_getOpenFile" and
# "tk_getSaveFile" commands. It is organized in the standard fashion
# for Tcl tests.
#
# Copyright (c) 1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.1
package require tcltest 2.2
eval tcltest::configure $argv
tcltest::loadTestedCommands

test fileDialog-0.1 {GetFileName: file types: MakeFilter() fails} {
    # MacOS type that is too long

    set res [list [catch {tk_getSaveFile -filetypes {{"foo" .foo {\0\0\0\0\0}}}} msg] $msg]
44
45
46
47
48
49
50
51

52
53
54
55
56
57
58
44
45
46
47
48
49
50

51
52
53
54
55
56
57
58







-
+







    if {!$isNative} {
	after 100 EnterFileByKey $parent [list $fileName] [list $fileDir]
    }
}

proc PressButton {btn} {
    event generate $btn <Enter>
    event generate $btn <1> -x 5 -y 5
    event generate $btn <Button-1> -x 5 -y 5
    event generate $btn <ButtonRelease-1> -x 5 -y 5
}

proc EnterFileByKey {parent fileName fileDir} {
    global tk_strictMotif
    if {$parent == "."} {
	set w .__tk_filedialog
89
90
91
92
93
94
95
96

97
98
99
100
101
102
103
89
90
91
92
93
94
95

96
97
98
99
100
101
102
103







-
+








    if {$type == "mouse"} {
	PressButton $button
    } else {
	event generate $w <Enter>
	focus $w
	event generate $button <Enter>
	event generate $w <KeyPress> -keysym Return
	event generate $w <Key> -keysym Return
    }
}


#----------------------------------------------------------------------
#
# The test suite proper
163
164
165
166
167
168
169
170

171
172
173
174
175
176
177
163
164
165
166
167
168
169

170
171
172
173
174
175
176
177







-
+







    test filebox-1.1.2-$mode "tk_getOpenFile command" -constraints aqua -body {
	tk_getOpenFile -foo
    } -returnCodes error -result $unknownOptionsMsg(tk_getOpenFile,aqua)

    catch {tk_getOpenFile -foo 1} msg
    regsub -all ,      $msg "" options
    regsub \"-foo\" $options "" options
    

    foreach option $options {
        if {[string index $option 0] eq "-"} {
	    test filebox-1.2-$mode$option "tk_getOpenFile command" -body {
		tk_getOpenFile $option
	    } -returnCodes error -result "value for \"$option\" missing"
        }
    }
Changes to tests/focus.test.
1
2
3
4
5
6


7
8
9
10
11
12



13
14
15
16
17
18
19
1
2
3
4


5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22




-
-
+
+






+
+
+







# This file is a Tcl script to test out the "focus" command and the
# other procedures in the file tkFocus.c.  It is organized in the
# standard fashion for Tcl tests.
#
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1994-1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
eval tcltest::configure $argv
tcltest::loadTestedCommands
namespace import -force tcltest::test

testConstraint failsOnUbuntu [expr {![info exists ::env(CI)] || ![string match Linux $::tcl_platform(os)]}]
testConstraint failsOnXQuarz [expr {$tcl_platform(os) ne "Darwin" || [tk windowingsystem] ne "x11" }]

proc focusSetup {} {
    destroy .t
    toplevel .t
    wm geom .t +0+0
    foreach i {b1 b2 b3 b4} {
	    button .t.$i -text .t.$i -relief raised -bd 2
60
61
62
63
64
65
66
67

68
69
70
71
72
73
74
63
64
65
66
67
68
69

70
71
72
73
74
75
76
77







-
+







update
bind all <FocusIn> {
    append focusInfo "in %W %d\n"
}
bind all <FocusOut> {
    append focusInfo "out %W %d\n"
}
bind all <KeyPress> {
bind all <Key> {
    append focusInfo "press %W %K"
}
focusSetup
if {[testConstraint altDisplay]} {
    focusSetupAlt
}

100
101
102
103
104
105
106
107

108
109
110
111
112
113
114
103
104
105
106
107
108
109

110
111
112
113
114
115
116
117







-
+







test focus-1.6 {Tk_FocusCmd procedure} -constraints unix -body {
    focus .gorp
} -returnCodes error -result {bad window path name ".gorp"}
test focus-1.7 {Tk_FocusCmd procedure} -constraints unix -body {
    focus .gorp a
} -returnCodes error -result {bad option ".gorp": must be -displayof, -force, or -lastfor}
test focus-1.8 {Tk_FocusCmd procedure, focussing on dead window} -constraints {
	unix 
	unix
} -setup {
    destroy .t2
} -body {
    focusClear
    toplevel .t2
    wm geom .t2 +10+10
    frame .t2.f -width 200 -height 100 -bd 2 -relief raised
126
127
128
129
130
131
132
133

134
135
136
137
138

139
140
141
142
143

144
145
146
147
148

149
150
151
152
153
154
155

156
157
158
159
160
161
162
129
130
131
132
133
134
135

136
137
138
139
140

141
142
143
144
145

146
147
148
149
150

151
152
153
154
155
156
157

158
159
160
161
162
163
164
165







-
+




-
+




-
+




-
+






-
+







    lappend x [focus]
    destroy .t2
    return $x
} -cleanup {
    destroy .t2
} -result {.t2.f2 .t2 .t2}
test focus-1.9 {Tk_FocusCmd procedure, -displayof option} -constraints {
	unix 
	unix
} -body {
    focus -displayof
} -returnCodes error -result {wrong # args: should be "focus -displayof window"}
test focus-1.10 {Tk_FocusCmd procedure, -displayof option} -constraints {
	unix 
	unix
} -body {
    focus -displayof a b
} -returnCodes error -result {wrong # args: should be "focus -displayof window"}
test focus-1.11 {Tk_FocusCmd procedure, -displayof option} -constraints {
	unix 
	unix
} -body {
    focus -displayof .lousy
} -returnCodes error -result {bad window path name ".lousy"}
test focus-1.12 {Tk_FocusCmd procedure, -displayof option} -constraints {
	unix 
	unix
} -body {
    focusClear
    focus .t
    focus -displayof .t.b3
}  -result {}
test focus-1.13 {Tk_FocusCmd procedure, -displayof option} -constraints {
	unix 
	unix
} -body {
    focusClear
    focus -force .t
    focus -displayof .t.b3
} -result {.t}
test focus-1.14 {Tk_FocusCmd procedure, -displayof option} -constraints {
	unix altDisplay
181
182
183
184
185
186
187
188

189
190
191
192
193

194
195
196
197
198

199
200
201
202
203

204
205
206
207
208
209
210
211
212

213
214
215
216
217
218
219
184
185
186
187
188
189
190

191
192
193
194
195

196
197
198
199
200

201
202
203
204
205

206
207
208
209
210
211
212
213
214

215
216
217
218
219
220
221
222







-
+




-
+




-
+




-
+








-
+







    focusClear
    focus .t.b1
    set x  [list [focus]]
    focus -force .t.b1
    lappend x [focus]
} -result {{} .t.b1}
test focus-1.20 {Tk_FocusCmd procedure, -lastfor option} -constraints {
    unix 
    unix
} -body {
    focus -lastfor
} -returnCodes error -result {wrong # args: should be "focus -lastfor window"}
test focus-1.21 {Tk_FocusCmd procedure, -lastfor option} -constraints {
    unix 
    unix
} -body {
    focus -lastfor 1 2
} -returnCodes error -result {wrong # args: should be "focus -lastfor window"}
test focus-1.22 {Tk_FocusCmd procedure, -lastfor option} -constraints {
    unix 
    unix
} -body {
    focus -lastfor who_knows?
} -returnCodes error -result {bad window path name "who_knows?"}
test focus-1.23 {Tk_FocusCmd procedure, -lastfor option} -constraints {
    unix 
    unix
} -body {
    focusClear
    focusSetup
    focus .b
    focus .t.b1
    list [focus -lastfor .] [focus -lastfor .t.b3]
} -result {.b .t.b1}
test focus-1.24 {Tk_FocusCmd procedure, -lastfor option} -constraints {
    unix 
    unix
} -body {
    focusClear
    focusSetup
    update
    focus -lastfor .t.b2
} -result {.t}
test focus-1.25 {Tk_FocusCmd procedure} -constraints unix -body {
304
305
306
307
308
309
310
311

312
313
314
315
316
317
318
319

320
321
322
323

324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344

345
346
347
348
349
350
351
307
308
309
310
311
312
313

314
315
316
317
318
319
320
321

322
323
324
325

326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346

347
348
349
350
351
352
353
354







-
+







-
+



-
+




















-
+







    list $focusInfo [focus]
} -result {{out . NotifyNonlinear
in .t NotifyNonlinearVirtual
in .t.b1 NotifyNonlinear
} .t.b1}

test focus-2.6 {TkFocusFilterEvent procedure, FocusIn events} -constraints {
    unix  testwrapper
    unix  testwrapper failsOnUbuntu failsOnXQuarz
} -body {
    focus .t.b1
    focus .
    update
    event gen [testwrapper .t] <FocusIn> -detail NotifyAncestor
    set focusInfo {}
    set x [focus]
    event gen . <KeyPress-x>
    event gen . <x>
    list $x $focusInfo
} -result {.t.b1 {press .t.b1 x}}
test focus-2.7 {TkFocusFilterEvent procedure, FocusOut events} -constraints {
    unix  testwrapper
    unix  testwrapper failsOnUbuntu failsOnXQuarz
} -body {
    set result {}
    foreach detail {NotifyAncestor NotifyInferior NotifyNonlinear
	    NotifyNonlinearVirtual NotifyPointer NotifyPointerRoot
	    NotifyVirtual} {
	    focus -force .t.b1
	    event gen [testwrapper .t] <FocusOut> -detail $detail
	    update
	    lappend result [focus]
    }
    return $result
} -result {{} .t.b1 {} {} .t.b1 .t.b1 {}}
test focus-2.8 {TkFocusFilterEvent procedure, FocusOut events} -constraints {
    unix  testwrapper
} -body {
    focus -force .t.b1
    event gen .t.b1 <FocusOut> -detail NotifyAncestor
    focus
} -result {.t.b1}
test focus-2.9 {TkFocusFilterEvent procedure, FocusOut events} -constraints {
    unix  testwrapper
    unix  testwrapper failsOnUbuntu failsOnXQuarz
} -body {
    focus .t.b1
    event gen [testwrapper .] <FocusOut> -detail NotifyAncestor
    focus
} -result {}
test focus-2.10 {TkFocusFilterEvent procedure, Enter events} -constraints {
    unix  testwrapper
595
596
597
598
599
600
601
602

603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620

621
622
623
624
625
626
627
598
599
600
601
602
603
604

605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622

623
624
625
626
627
628
629
630







-
+

















-
+









# I don't know how to test most of the remaining procedures of this file
# explicitly;  they've already been exercised by the preceding tests.

# Test 5.1 fails (before and after update)
test focus-5.1 {ChangeXFocus procedure, don't take focus unless have it} -constraints {
    unix testwrapper secureserver
    unix testwrapper secureserver failsOnUbuntu failsOnXQuarz
} -body {
    setupbg
    focusSetup
    focus -force .t
    update
    set result [focus]
    send [dobg {tk appname}] {focus -force .; update}
    lappend result [focus]
    focus .t.b2
    update
    lappend result [focus]
} -cleanup {
    cleanupbg
} -result {.t {} {}}
destroy .t
bind all <FocusIn> {}
bind all <FocusOut> {}
bind all <KeyPress> {}
bind all <Key> {}


fixfocus
test focus-6.1 {miscellaneous - embedded application in same process} -constraints {
    unix  testwrapper
} -setup {
    eval interp delete [interp slaves]
726
727
728
729
730
731
732




















733
734
735
736
737
738
739
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







} -cleanup {
    destroy .t
    cleanupbg
    bind all <FocusIn> {}
    bind all <FocusOut> {}
} -result {{.t.f2.e1 {} {focus out .t.f2.e1 NotifyNonlinear} {focus out .t.f2 NotifyNonlinearVirtual} {focus in .t.f1 NotifyNonlinear} | {focus out .t.f1 NotifyNonlinear} {focus in .t.f2 NotifyNonlinearVirtual} {focus in .t.f2.e1 NotifyNonlinear}} {{focus in . NotifyVirtual} {focus in .e1 NotifyAncestor} | {focus out .e1 NotifyAncestor} {focus out . NotifyVirtual}}}

test focus-7.1 {TkSetFocusWin procedure, unmapped windows} -setup {
    # TkSetFocusWin handles the case of not yet mapped windows
    # by not setting the focus on them right at the time it is
    # requested, but by scheduling an event handler that will
    # set the focus later once it gets mapped. The purpose of
    # this test is to check that event scheduling and deletion
    # work as expected (bug [08e2f8e6f0]).
    toplevel .top
    spinbox .top.s1
    spinbox .top.s2
    spinbox .top.s3
    grid .top.s1 .top.s2 .top.s3
} -body {
    focus -force .top.s2
    focus -force .top.s3
    update
    focus
} -cleanup {
    destroy .top
} -result {.top.s3}


deleteWindows

# cleanup
cleanupTests
return
Changes to tests/focusTcl.test.
1
2
3
4
5
6
7


8
9
10
11
12
13
14
1
2
3
4
5


6
7
8
9
10
11
12
13
14





-
-
+
+







# This file is a Tcl script to test out the features of the script
# file focus.tcl, which includes the procedures tk_focusNext and
# tk_focusPrev, among other things.  This file is organized in the
# standard fashion for Tcl tests.
#
# Copyright (c) 1995 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1995 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
eval tcltest::configure $argv
tcltest::loadTestedCommands
namespace import -force tcltest::test

Changes to tests/font.test.
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15




16
17
18
19
20
21
22
1
2
3
4


5
6
7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
22
23
24
25




-
-
+
+








-
+
+
+
+







# This file is a Tcl script to test out Tk's "font" command
# plus the procedures in tkFont.c.  It is organized in the
# standard white-box fashion for Tcl tests.
#
# Copyright (c) 1996-1998 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1996-1998 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
namespace import ::tcltest::*
eval tcltest::configure $argv
tcltest::loadTestedCommands

# Some tests require support for 4-byte UTF-8 sequences
testConstraint fullutf [expr {[format %c 0x010000] != "\ufffd"}]
testConstraint fullutf [expr {[format %c 0x010000] != "\uFFFD"}]
testConstraint utfcompat [expr {([string length "\U10000"] == 2) && [package vsatisfies [package provide Tcl] 8]}]
testConstraint failsOnUbuntu [expr {![info exists ::env(CI)] || ![string match Linux $::tcl_platform(os)]}]
testConstraint failsOnUbuntuNoXft [expr {[testConstraint failsOnUbuntu] || (![catch {tk::pkgconfig get fontsystem} fs] && ($fs eq "xft"))}]

set defaultfontlist [font names]

proc getnondefaultfonts {} {
    global defaultfontlist
    set nondeffonts [list ]
    foreach afont [font names] {
56
57
58
59
60
61
62
63
64
65



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84






85
86
87
88
89
90
91
92
93



94
95
96
97

98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116

117
118
119
120

121
122
123

124
125
126
127
128
129
130

131
132
133
134
135
136
137
138
139

140
141
142
143
144
145
146

147
148
149
150
151

152
153
154

155
156

157
158

159
160

161
162
163
164

165
166
167
168
169
170
171
59
60
61
62
63
64
65



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81






82
83
84
85
86
87
88
89
90
91
92
93



94
95
96
97
98
99

100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118

119
120
121
122

123
124
125

126
127
128
129
130
131
132

133
134
135
136
137
138
139
140
141

142
143
144
145
146
147
148

149
150
151
152
153

154
155
156

157
158

159
160

161
162

163
164
165
166

167
168
169
170
171
172
173
174







-
-
-
+
+
+













-
-
-
-
-
-
+
+
+
+
+
+






-
-
-
+
+
+



-
+


















-
+



-
+


-
+






-
+








-
+






-
+




-
+


-
+

-
+

-
+

-
+



-
+









test font-1.1 {TkFontPkgInit} -setup {
    catch {interp delete foo}
} -body {
    interp create foo
    foo eval {
		load {} Tk
		wm geometry . +0+0
		update
	load {} Tk
	wm geometry . +0+0
	update
    }
    interp delete foo
} -result {}


test font-2.1 {TkFontPkgFree} -setup {
    catch {interp delete foo}
    set x {}
} -body {
    interp create foo

    # Makes sure that named font was visible only to child interp.
    foo eval {
		load {} Tk
		wm geometry . +0+0
		button .b -font {times 16} -text "hi"
		pack .b
		font create wiggles -family courier -underline 1
		update
	load {} Tk
	wm geometry . +0+0
	button .b -font {times 16} -text "hi"
	pack .b
	font create wiggles -family courier -underline 1
	update
    }
    lappend x [catch {font configure wiggles} msg; set msg]

    # Tests cancelling the idle handler for TheWorldHasChanged,
    # because app goes away before idle serviced.
    foo eval {
		.b config -font wiggles
		font config wiggles -size 24
		destroy .
	.b config -font wiggles
	font config wiggles -size 24
	destroy .
    }
    lappend x [foo eval {catch {font families} msg; set msg}]
} -cleanup {
        interp delete foo
    interp delete foo
} -result {{named font "wiggles" doesn't exist} {can't invoke "font" command: application has been destroyed}}


test font-3.1 {font command: general} -body {
    font
} -returnCodes error -result {wrong # args: should be "font option ?arg?"}
test font-3.2 {font command: general} -body {
    font xyz
} -returnCodes error -result {bad option "xyz": must be actual, configure, create, delete, families, measure, metrics, or names}


test font-4.1 {font command: actual: arguments} -body {
    # (skip < 0)
    font actual xyz -displayof
} -returnCodes error -result {value for "-displayof" missing}
test font-4.2 {font command: actual: arguments} -body {
    # (objc < 3)
    font actual
} -returnCodes error -result {wrong # args: should be "font actual font ?-displayof window? ?option? ?--? ?char?"}
} -returnCodes error -result {wrong # args: should be "font actual font ?-displayof window? ?-option? ?--? ?char?"}
test font-4.3 {font command: actual: arguments} -body {
    # (objc - skip > 4) when skip == 0
    font actual xyz abc def
} -returnCodes error -result {wrong # args: should be "font actual font ?-displayof window? ?option? ?--? ?char?"}
} -returnCodes error -result {wrong # args: should be "font actual font ?-displayof window? ?-option? ?--? ?char?"}
test font-4.4 {font command: actual: displayof specified, so skip to next} -body {
    catch {font actual xyz -displayof . -size}
} -result {0}
} -result 0
test font-4.5 {font command: actual: displayof specified, so skip to next} -body {
    lindex [font actual xyz -displayof .] 0
} -result {-family}
test font-4.6 {font command: actual: arguments} -body {
    # (objc - skip > 4) when skip == 2
    font actual xyz -displayof . abc def
} -returnCodes error -result {wrong # args: should be "font actual font ?-displayof window? ?option? ?--? ?char?"}
} -returnCodes error -result {wrong # args: should be "font actual font ?-displayof window? ?-option? ?--? ?char?"}
test font-4.7 {font command: actual: arguments} -constraints noExceed -body {
    # (tkfont == NULL)
    font actual "\{xyz"
} -returnCodes error -result "font \"{xyz\" doesn't exist"
test font-4.8 {font command: actual: all attributes} -body {
    # not (objc > 3) so objPtr = NULL
    lindex [font actual {-family times}] 0
} -result {-family}
test font-4.9 {font command: actual} -constraints {unix noExceed} -body {
test font-4.9 {font command: actual} -constraints {unix noExceed failsOnUbuntu} -body {
    # (objc > 3) so objPtr = objv[3 + skip]
    string tolower [font actual {-family times} -family]
} -result {times}
test font-4.10 {font command: actual} -constraints win -body {
    # (objc > 3) so objPtr = objv[3 + skip]
    font actual {-family times} -family
} -result {Times New Roman}
} -result {times}
test font-4.11 {font command: bad option} -body {
    font actual xyz -style
} -returnCodes error -result {bad option "-style": must be -family, -size, -weight, -slant, -underline, or -overstrike}
test font-4.12 {font command: actual} -body {
    font actual {-family times} -- \ud800
    font actual {-family times} -- \uD800
} -match glob -result {*}
test font-4.13 {font command: actual} -body {
    font actual {-family times} -- \udc00
    font actual {-family times} -- \uDC00
} -match glob -result {*}
test font-4.14 {font command: actual} -constraints win -body {
test font-4.14 {font command: actual} -constraints {utfcompat win} -body {
    font actual {-family times} -family -- \uD800\uDC00
} -result {Times New Roman}
} -result {times}
test font-4.15 {font command: actual} -body {
    font actual {-family times} -- \udc00\ud800
    font actual {-family times} -- \uDC00\uD800
} -returnCodes 1 -match glob -result {expected a single character but got "*"}
test font-4.16 {font command: actual} -constraints {fullutf win} -body {
    font actual {-family times} -family -- \U10000
} -result {Times New Roman}
} -result {times}


test font-5.1 {font command: configure} -body {
    # (objc < 3)
    font configure
} -returnCodes error -result {wrong # args: should be "font configure fontname ?-option value ...?"}
test font-5.2 {font command: configure: non-existent font} -body {
189
190
191
192
193
194
195
196

197
198
199
200
201
202
203
204

205
206

207
208
209
210
211
212
213
214
215
216
217

218
219
220
221
222
223
224
225

226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245

246
247
248
249
250
251
252
192
193
194
195
196
197
198

199
200
201
202
203
204
205
206

207
208

209
210
211
212
213
214
215
216
217
218
219

220
221
222
223
224
225
226
227

228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247

248
249
250
251
252
253
254
255







-
+







-
+

-
+










-
+







-
+



















-
+







test font-5.4 {font command: configure: get all options} -setup {
    catch {font delete xyz}
} -body {
    # (objc == 3) so objPtr = NULL
    font create xyz -family xyz
    lindex [font configure xyz] 1
} -cleanup {
	font delete xyz
    font delete xyz
} -result xyz
test font-5.5 {font command: configure: get one option} -setup {
    clearnondefaultfonts
} -body {
    # (objc == 4) so objPtr = objv[3]
    font create xyz -family xyz
    font configure xyz -family
	getnondefaultfonts
    getnondefaultfonts
} -cleanup {
	font delete xyz
    font delete xyz
} -result xyz
test font-5.6 {font command: configure: update existing font} -setup {
    catch {font delete xyz}
} -body {
    # else result = ConfigAttributesObj()
    font create xyz
    font configure xyz -family xyz
    update
    font configure xyz -family
} -cleanup {
	font delete xyz
    font delete xyz
} -result xyz
test font-5.7 {font command: configure: bad option} -setup {
    catch {font delete xyz}
} -body {
    font create xyz
    font configure xyz -style
} -cleanup {
	font delete xyz
    font delete xyz
} -returnCodes error -result {bad option "-style": must be -family, -size, -weight, -slant, -underline, or -overstrike}


test font-6.1 {font command: create: make up name} -setup {
    clearnondefaultfonts
} -body {
    # (objc < 3) so name = NULL
    font create
    getnondefaultfonts
} -cleanup {
    font delete font1
} -result {font1}
test font-6.2 {font command: create: name specified} -setup {
    clearnondefaultfonts
} -body {
    # not (objc < 3)
    font create xyz
    getnondefaultfonts
} -cleanup {
	font delete xyz
    font delete xyz
} -result {xyz}
test font-6.3 {font command: create: name not really specified} -setup {
    clearnondefaultfonts
} -body {
    # (name[0] == '-') so name = NULL
    font create -family xyz
    getnondefaultfonts
280
281
282
283
284
285
286
287

288
289
290
291
292
293
294
295
296

297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312

313
314
315
316
317
318
319
283
284
285
286
287
288
289

290
291
292
293
294
295
296
297
298

299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314

315
316
317
318
319
320
321
322







-
+








-
+















-
+







test font-6.7 {font command: create: already exists} -setup {
    catch {font delete xyz}
} -body {
    # (CreateNamedFont() != TCL_OK)
    font create xyz
    font create xyz
} -cleanup {
	font delete xyz
    font delete xyz
} -returnCodes error -result {named font "xyz" already exists}

test font-7.1 {font command: delete: arguments} -body {
    # (objc < 3)
    font delete
} -returnCodes error -result {wrong # args: should be "font delete fontname ?fontname ...?"}
test font-7.2 {font command: delete: loop test} -setup {
    clearnondefaultfonts
	set x {}
    set x {}
} -body {
    # for (i = 2; i < objc; i++)
    font create a -underline 1
    font create b -underline 1
    font create c -underline 1
    font create d -underline 1
    font create e -underline 1
    lappend x [lsort [getnondefaultfonts]]
    font delete a e c b
    lappend x [lsort [getnondefaultfonts]]
} -cleanup {
    getnondefaultfonts
} -result {{a b c d e} d}
test font-7.3 {font command: delete: loop test} -setup {
    clearnondefaultfonts
	set x {}
    set x {}
} -body {
    # (namedHashPtr == NULL) in middle of loop
    font create a -underline 1
    font create b -underline 1
    font create c -underline 1
    font create d -underline 1
    font create e -underline 1
338
339
340
341
342
343
344
345

346
347
348
349
350
351
352
353
354
355
356
357
358
359

360
361
362
363
364
365
366
341
342
343
344
345
346
347

348
349
350
351
352
353
354
355
356
357
358
359
360
361

362
363
364
365
366
367
368
369







-
+













-
+







    # (nfPtr->refCount != 0)
    font create xyz
    .t.f configure -font xyz
    font delete xyz
    font actual xyz
    font configure xyz
} -cleanup {
	destroy .t.f
    destroy .t.f
} -returnCodes error -result {named font "xyz" doesn't exist}
test font-7.6 {font command: delete: mark for later deletion} -setup {
    destroy .t.f
    catch {font delete xyz}
    pack [label .t.f]
    update
} -body {
    # (nfPtr->refCount != 0)
    font create xyz
    .t.f configure -font xyz
    font delete xyz
    font actual xyz
    catch {font configure xyz}
	.t.f cget -font
    .t.f cget -font
} -cleanup {
	destroy .t.f
} -result xyz
test font-7.7 {font command: delete: actually delete} -setup {
    catch {font delete xyz}
} -body {
    # not (nfPtr->refCount != 0)
378
379
380
381
382
383
384
385

386
387
388
389
390
391
392
381
382
383
384
385
386
387

388
389
390
391
392
393
394
395







-
+







    # (objc - skip != 2) when skip == 0
    font families xyz
} -returnCodes error -result {wrong # args: should be "font families ?-displayof window?"}
test font-8.3 {font command: families: arguments} -body {
    # (objc - skip != 2) when skip == 2
    font families -displayof . xyz
} -returnCodes error -result {wrong # args: should be "font families ?-displayof window?"}
test font-8.4 {font command: families} -body {
test font-8.4 {font command: families} -constraints failsOnUbuntu -body {
    # TkpGetFontFamilies()
    regexp -nocase times [font families]
} -result 1


test font-9.1 {font command: measure: arguments} -body {
    # (skip < 0)
425
426
427
428
429
430
431
432

433
434
435
436

437
438
439
440
441
442
443
428
429
430
431
432
433
434

435
436
437
438

439
440
441
442
443
444
445
446







-
+



-
+







test font-10.2 {font command: metrics: arguments} -body {
    # (skip < 0)
    font metrics xyz -displayof
} -returnCodes error -result {value for "-displayof" missing}
test font-10.3 {font command: metrics: arguments} -body {
    # (objc < 3)
    font metrics
} -returnCodes error -result {wrong # args: should be "font metrics font ?-displayof window? ?option?"}
} -returnCodes error -result {wrong # args: should be "font metrics font ?-displayof window? ?-option?"}
test font-10.4 {font command: metrics: arguments} -body {
    # (objc - skip) > 4) when skip == 0
    font metrics xyz abc def
} -returnCodes error -result {wrong # args: should be "font metrics font ?-displayof window? ?option?"}
} -returnCodes error -result {wrong # args: should be "font metrics font ?-displayof window? ?-option?"}
test font-10.5 {font command: metrics: arguments} -body {
    # (objc - skip) > 4) when skip == 2
    font metrics xyz -displayof . abc
} -returnCodes error -result {bad metric "abc": must be -ascent, -descent, -linespace, or -fixed}
test font-10.6 {font command: metrics: bad font} -constraints noExceed -body {
    # (tkfont == NULL)
    font metrics "\{xyz"
510
511
512
513
514
515
516
517

518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536

537
538

539
540
541
542
543

544
545
546
547
548
549
550

551
552
553
554
555
556
557
558
559

560
561
562
563
564
565
566
567
568

569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584


585
586
587
588
589
590
591
592
593

594
595
596
597
598
599
600
601
602
603
604
605
606

607
608
609
610
611
612
613
614
615
616
617
618
619
620
621

622
623
624
625
626
627
628
513
514
515
516
517
518
519

520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538

539
540

541
542
543
544
545

546
547
548
549
550
551
552

553
554
555
556
557
558
559
560
561

562
563
564
565
566
567
568
569
570

571
572
573
574
575
576
577
578
579
580
581
582
583
584
585


586
587
588
589
590
591
592
593
594
595

596
597
598
599
600
601
602
603
604
605
606
607
608

609
610
611
612
613
614
615
616
617
618
619
620
621
622
623

624
625
626
627
628
629
630
631







-
+


















-
+

-
+




-
+






-
+








-
+








-
+














-
-
+
+








-
+












-
+














-
+







test font-12.1 {UpdateDependantFonts procedure: no users} -setup {
    catch {font delete xyz}
} -body {
    # (nfPtr->refCount == 0)
    font create xyz
    font configure xyz -family times
} -cleanup {
	font delete xyz
    font delete xyz
} -result {}
test font-12.2 {UpdateDependantFonts procedure: pings the widgets} -setup {
    destroy .t.f
    catch {font delete xyz}
    pack [label .t.f]
    update
} -body {
    font create xyz -family times -size 20
    .t.f config -font xyz -text "abcd" -padx 0 -bd 0 -highlightthickness 0
    set a1 [font measure xyz "abcd"]
    update
    set b1 [winfo reqwidth .t.f]
    font configure xyz -family helvetica -size 20
    set a2 [font measure xyz "abcd"]
    update
    set b2 [winfo reqwidth .t.f]
    expr {$a1==$b1 && $a2==$b2}
} -cleanup {
	destroy .t.f
    destroy .t.f
    font delete xyz
} -result {1}
} -result 1


test font-13.1 {CreateNamedFont: new named font} -setup {
    catch {font delete xyz}
	set x {}
    set x {}
} -body {
    # not (new == 0)
    lappend x [getnondefaultfonts]
    font create xyz
    lappend x [getnondefaultfonts]
} -cleanup {
	font delete xyz
    font delete xyz
} -result {{} xyz}
test font-13.2 {CreateNamedFont: named font already exists} -setup {
    catch {font delete xyz}
} -body {
    # (new == 0)
    font create xyz
    font create xyz
} -cleanup {
	font delete xyz
    font delete xyz
} -returnCodes error -result {named font "xyz" already exists}
test font-13.3 {CreateNamedFont: named font already exists} -setup {
    catch {font delete xyz}
} -body {
    # (nfPtr->deletePending == 0)
    font create xyz
    font create xyz
} -cleanup {
	font delete xyz
    font delete xyz
} -returnCodes error -result {named font "xyz" already exists}
test font-13.4 {CreateNamedFont: recreate "deleted" font} -setup {
    destroy .t.f
    catch {font delete xyz}
    pack [label .t.f]
    update
} -body {
    # not (nfPtr->deletePending == 0)
    font create xyz -family times
    .t.f configure -font xyz
    font delete xyz
    font create xyz -family courier
    font configure xyz -family
} -cleanup {
	font delete xyz
	destroy .t.f
    font delete xyz
    destroy .t.f
} -result {courier}


test font-14.1 {Tk_GetFont procedure} -body {
} -result {}


test font-15.1 {Tk_AllocFontFromObj - converting internal reps} -constraints {
	testfont
    testfont
} -setup {
    destroy .b1 .b2
} -body {
    set x {Times 16}
    lindex $x 0
    button .b1 -font $x
    lindex $x 0
    testfont counts {Times 16}
} -cleanup {
    destroy .b1 .b2
} -result {{1 0}}
test font-15.2 {Tk_AllocFontFromObj - discard stale font} -constraints {
	testfont
    testfont
} -setup {
    destroy .b1 .b2
    set result {}
} -body {
    set x {Times 16}
    button .b1 -font $x
    destroy .b1
    lappend result [testfont counts {Times 16}]
    button .b2 -font $x
    lappend result [testfont counts {Times 16}]
} -cleanup {
    destroy .b2
} -result {{} {{1 1}}}
test font-15.3 {Tk_AllocFontFromObj - reuse existing font} -constraints {
	testfont
    testfont
} -setup {
    destroy .b1 .b2
    set result {}
} -body {
    set x {Times 16}
    button .b1 -font $x
    lappend result [testfont counts {Times 16}]
637
638
639
640
641
642
643
644

645
646
647
648
649
650
651
652
653
654
655
656

657
658
659
660
661
662
663
664
665
666
667

668
669
670
671
672
673
674
640
641
642
643
644
645
646

647
648
649
650
651
652
653
654
655
656
657
658

659
660
661
662
663
664
665
666
667
668
669

670
671
672
673
674
675
676
677







-
+











-
+










-
+







    pack [label .t.f]
    update
} -body {
    # (new == 0)
    .t.f config -font {-family fixed}
    lindex [font actual {-family fixed}] 0
} -cleanup {
	destroy .t.f
    destroy .t.f
} -result {-family}
test font-15.5 {Tk_AllocFontFromObj procedure: get named font} -setup {
    destroy .t.f
    catch {font delete xyz}
    pack [label .t.f]
    update
} -body {
    # (namedHashPtr != NULL)
    font create xyz
    .t.f config -font xyz
} -cleanup {
	destroy .t.f
    destroy .t.f
    font delete xyz
} -result {}
test font-15.6 {Tk_AllocFontFromObj procedure: not a named font} -setup {
    destroy .t.f
    pack [label .t.f]
    update
} -body {
    # not (namedHashPtr != NULL)
    .t.f config -font {times 20}
} -cleanup {
	destroy .t.f
    destroy .t.f
} -result {-family} -result {}
test font-15.7 {Tk_AllocFontFromObj procedure: get native font} -constraints {
	unix
} -setup {
    destroy .t.f
    pack [label .t.f]
    update
704
705
706
707
708
709
710
711

712
713
714
715
716
717
718
719
720

721
722
723
724
725
726
727
728
729
730
731

732
733
734
735
736
737
738
739
740
741
742
743

744
745
746
747
748
749
750
707
708
709
710
711
712
713

714
715
716
717
718
719
720
721
722

723
724
725
726
727
728
729
730
731
732
733

734
735
736
737
738
739
740
741
742
743
744
745

746
747
748
749
750
751
752
753







-
+








-
+










-
+











-
+







    font actual "\{xyz"
} -returnCodes error -result "font \"{xyz\" doesn't exist"
test font-15.11 {Tk_AllocFontFromObj procedure: get attribute font} -body {
    # not (ParseFontNameObj() != TCL_OK)
    lindex [font actual {plan 9}] 0
} -result {-family}
test font-15.12 {Tk_AllocFontFromObj procedure: setup tab width} -setup {
	destroy .l
    destroy .l
} -body {
    # Tk_MeasureChars(fontPtr, "0", ...)
    label .l -bd 0 -padx 0  -highlightthickness 0 -font $fixed -text "a\tb"
    update
    set res1 [winfo reqwidth .l]
	set res2 [expr [font measure $fixed "0"]*9]
	expr {$res1 eq $res2}
} -cleanup {
	destroy .l
    destroy .l
} -result 1
test font-15.13 {Tk_AllocFontFromObj procedure: underline position} -setup {
    destroy .t.f
    pack [label .t.f]
    update
} -body {
    # (fontPtr->underlineHeight == 0) because size was < 10
    .t.f config -text "underline" -font "times -8 underline"
    update
} -cleanup {
	destroy .t.f
    destroy .t.f
} -result {}


test font-16.1 {Tk_NameOfFont procedure} -setup {
    destroy .t.f
    pack [label .t.f]
    update
} -body {
    .t.f config -font -family\ fixed
    .t.f cget -font
} -cleanup {
	destroy .t.f
    destroy .t.f
} -result {-family fixed}


test font-17.1 {Tk_FreeFontFromObj - reference counts} -constraints {
	testfont
} -setup {
    destroy .b1 .b2 .b3
922
923
924
925
926
927
928
929

930
931
932
933
934
935
936
925
926
927
928
929
930
931

932
933
934
935
936
937
938
939







-
+







    if {[string match lucida*bright $x]} {
		psfontname "{lucida bright} 10"
    } else {
		set x {LucidaBright}
    }
} -result {LucidaBright}
test font-21.6 {Tk_PostscriptFontName procedure: spaces} -constraints {
	x11
	x11 failsOnUbuntu
} -body {
    psfontname "{new century schoolbook} 10"
} -result {NewCenturySchlbk-Roman}

test font-21.7 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
    unix
} -body {
1444
1445
1446
1447
1448
1449
1450
1451

1452
1453
1454
1455
1456




1457
1458
1459

1460
1461
1462
1463
1464

1465
1466
1467
1468
1469
1470
1471
1472

1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491



1492
1493
1494
1495
1496
1497



1498
1499
1500
1501
1502
1503



1504
1505
1506
1507
1508
1509



1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520



1521
1522
1523
1524
1525
1526



1527
1528
1529
1530
1531

1532
1533

1534
1535

1536
1537

1538
1539
1540
1541
1542
1543
1544
1545

1546
1547

1548
1549
1550
1551



1552
1553
1554
1555
1556
1557
1558
1559
1560
1561



1562
1563
1564
1565



1566
1567
1568
1569
1570
1571
1572
1573
1574
1575



1576
1577
1578
1579



1580
1581
1582
1583
1584
1585
1586
1587
1588



1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600









1601
1602
1603
1604
1605
1606
1607
1608
1609
1610





1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622

1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634

1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651

1652
1653
1654
1655
1656
1657
1658
1447
1448
1449
1450
1451
1452
1453

1454
1455




1456
1457
1458
1459
1460
1461

1462
1463
1464
1465
1466

1467
1468
1469
1470
1471
1472
1473
1474

1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491



1492
1493
1494
1495
1496
1497



1498
1499
1500
1501
1502
1503



1504
1505
1506
1507
1508
1509



1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520



1521
1522
1523
1524
1525
1526



1527
1528
1529
1530
1531
1532
1533

1534
1535

1536
1537

1538
1539

1540
1541
1542
1543
1544
1545
1546
1547

1548
1549

1550
1551



1552
1553
1554
1555
1556
1557
1558
1559
1560
1561



1562
1563
1564
1565



1566
1567
1568
1569
1570
1571
1572
1573
1574
1575



1576
1577
1578
1579



1580
1581
1582
1583
1584
1585
1586
1587
1588



1589
1590
1591
1592
1593
1594









1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608





1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624

1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636

1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653

1654
1655
1656
1657
1658
1659
1660
1661







-
+

-
-
-
-
+
+
+
+


-
+




-
+







-
+
















-
-
-
+
+
+



-
-
-
+
+
+



-
-
-
+
+
+



-
-
-
+
+
+








-
-
-
+
+
+



-
-
-
+
+
+




-
+

-
+

-
+

-
+







-
+

-
+

-
-
-
+
+
+







-
-
-
+
+
+

-
-
-
+
+
+







-
-
-
+
+
+

-
-
-
+
+
+






-
-
-
+
+
+



-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+





-
-
-
-
-
+
+
+
+
+











-
+











-
+
















-
+







    win
} -body {
    set x [psfontname {{times new roman} 12 italic bold}]
} -result {Times-BoldItalic}


test font-22.1 {Tk_TextWidth procedure} -setup {
	destroy .t.l
    destroy .t.l
} -body {
	label .t.l -padx 0 -pady 0 -bd 0 -highlightthickness 0 -justify left \
		-text "0" -font "Courier -12"
	pack .t.l
	set ax [winfo reqwidth .t.l]
    label .t.l -padx 0 -pady 0 -bd 0 -highlightthickness 0 -justify left \
	    -text "0" -font "Courier -12"
    pack .t.l
    set ax [winfo reqwidth .t.l]
    expr {[font measure [.t.l cget -font] "000"] eq $ax*3}
} -cleanup {
	destroy .t.l
    destroy .t.l
} -result 1


test font-23.1 {Tk_UnderlineChars procedure} -setup {
	destroy .t.t
    destroy .t.t
} -body {
    text .t.t
    .t.t insert 1.0 abc\tdefg
    .t.t tag config sel -underline 1
    .t.t tag add sel 1.0 end
    update
} -cleanup {
	destroy .t.t
    destroy .t.t
} -result {}


# Data used in 24.* tests
destroy .t.l
label .t.l -padx 0 -pady 0 -bd 0 -highlightthickness 0 -justify left \
	-text "0" -font "Courier -12"
pack .t.l
update
set ax [winfo reqwidth .t.l]
set ay [winfo reqheight .t.l]
test font-24.1 {Tk_ComputeTextLayout: empty string} -body {
    .t.l config -text ""
} -result {}
test font-24.2 {Tk_ComputeTextLayout: simple string} -body {
    .t.l config -text "000"
	update
	list [expr {[winfo reqwidth .t.l] eq [expr {$ax * 3}]}] \
		[expr {[winfo reqheight .t.l] eq $ay}]
    update
    list [expr {[winfo reqwidth .t.l] eq [expr {$ax * 3}]}] \
	    [expr {[winfo reqheight .t.l] eq $ay}]
} -result {1 1}
test font-24.3 {Tk_ComputeTextLayout: find special chars} -body {
    .t.l config -text "000\n000"
	update
	list [expr {[winfo reqwidth .t.l] eq [expr {$ax * 3}]}] \
		[expr {[winfo reqheight .t.l] eq [expr {$ay * 2}]}]
    update
    list [expr {[winfo reqwidth .t.l] eq [expr {$ax * 3}]}] \
	    [expr {[winfo reqheight .t.l] eq [expr {$ay * 2}]}]
} -result {1 1}
test font-24.4 {Tk_ComputeTextLayout: calls Tk_MeasureChars} -body {
    .t.l config -text "000\n000"
	update
	list [expr {[winfo reqwidth .t.l] eq [expr {$ax * 3}]}] \
		[expr {[winfo reqheight .t.l] eq [expr {$ay * 2}]}]
    update
    list [expr {[winfo reqwidth .t.l] eq [expr {$ax * 3}]}] \
	    [expr {[winfo reqheight .t.l] eq [expr {$ay * 2}]}]
} -result {1 1}
test font-24.5 {Tk_ComputeTextLayout: break line} -body {
    .t.l config -text "000\t00000" -wrap [expr 9 * $ax]
	update
	list [expr {[winfo reqwidth .t.l] eq [expr {$ax * 8}]}] \
		[expr {[winfo reqheight .t.l] eq [expr {$ay * 2}]}]
    update
    list [expr {[winfo reqwidth .t.l] eq [expr {$ax * 8}]}] \
	    [expr {[winfo reqheight .t.l] eq [expr {$ay * 2}]}]
} -cleanup {
    .t.l config -wrap 0
} -result {1 1}
test font-24.6 {Tk_ComputeTextLayout: normal ended on special char} -body {
    .t.l config -text "000\n000"
} -result {}
test font-24.7 {Tk_ComputeTextLayout: special char was \n} -body {
    .t.l config -text "000\n0000"
	update
	list [expr {[winfo reqwidth .t.l] eq [expr {$ax * 4}]}] \
		[expr {[winfo reqheight .t.l] eq [expr {$ay * 2}]}]
    update
    list [expr {[winfo reqwidth .t.l] eq [expr {$ax * 4}]}] \
	    [expr {[winfo reqheight .t.l] eq [expr {$ay * 2}]}]
} -result {1 1}
test font-24.8 {Tk_ComputeTextLayout: special char was \t} -body {
    .t.l config -text "000\t00"
	update
	list [expr {[winfo reqwidth .t.l] eq [expr {$ax * 10}]}] \
		[expr {[winfo reqheight .t.l] eq $ay}]
    update
    list [expr {[winfo reqwidth .t.l] eq [expr {$ax * 10}]}] \
	    [expr {[winfo reqheight .t.l] eq $ay}]
} -result {1 1}
test font-24.9 {Tk_ComputeTextLayout: tab didn't cause break} -body {
    set x {}
    .t.l config -text "000\t000"
	update
    update
    lappend x [expr {[winfo reqwidth .t.l] eq [expr {$ax * 11}]}]
	lappend x [expr {[winfo reqheight .t.l] eq $ay}]
    lappend x [expr {[winfo reqheight .t.l] eq $ay}]
    .t.l config -text "000\t000" -wrap [expr 100 * $ax]
	update
    update
    lappend x [expr {[winfo reqwidth .t.l] eq [expr {$ax * 11}]}]
	lappend x [expr {[winfo reqheight .t.l] eq $ay}]
    lappend x [expr {[winfo reqheight .t.l] eq $ay}]
    return $x
} -cleanup {
    .t.l config -wrap 0
} -result {1 1 1 1}
test font-24.10 {Tk_ComputeTextLayout: tab caused break} -body {
    set x {}
    .t.l config -text "000\t"
	update
    update
    lappend x [expr {[winfo reqwidth .t.l] eq [expr {$ax * 8}]}]
	lappend x [expr {[winfo reqheight .t.l] eq $ay}]
    lappend x [expr {[winfo reqheight .t.l] eq $ay}]
    .t.l config -text "000\t00" -wrap [expr $ax * 6]
	update
	lappend x [expr {[winfo reqwidth .t.l] eq [expr {$ax * 8}]}]
	lappend x [expr {[winfo reqheight .t.l] eq [expr {$ay * 2}]}]
    update
    lappend x [expr {[winfo reqwidth .t.l] eq [expr {$ax * 8}]}]
    lappend x [expr {[winfo reqheight .t.l] eq [expr {$ay * 2}]}]
    return $x
} -cleanup {
    .t.l config -wrap 0
} -result {1 1 1 1}
test font-24.11 {Tk_ComputeTextLayout: absorb spaces at eol} -body {
    set x {}
    .t.l config -text "000            000" -wrap [expr {$ax * 5}]
	update
	lappend x [expr {[winfo reqwidth .t.l] eq [expr {$ax * 3}]}]
	lappend x [expr {[winfo reqheight .t.l] eq [expr {$ay * 2}]}]
    update
    lappend x [expr {[winfo reqwidth .t.l] eq [expr {$ax * 3}]}]
    lappend x [expr {[winfo reqheight .t.l] eq [expr {$ay * 2}]}]
    .t.l config -text "000            "
	update
	lappend x [expr {[winfo reqwidth .t.l] eq [expr {$ax * 3}]}]
	lappend x [expr {[winfo reqheight .t.l] eq $ay}]
    update
    lappend x [expr {[winfo reqwidth .t.l] eq [expr {$ax * 3}]}]
    lappend x [expr {[winfo reqheight .t.l] eq $ay}]
    return $x
} -cleanup {
    .t.l config -wrap 0
} -result {1 1 1 1}
test font-24.12 {Tk_ComputeTextLayout: append non-printing spaces to chunk} -body {
    set x {}
    .t.l config -text "000            0000" -wrap [expr {$ax * 5}]
	update
	lappend x [expr {[winfo reqwidth .t.l] eq [expr {$ax * 4}]}]
	lappend x [expr {[winfo reqheight .t.l] eq [expr {$ay * 2}]}]
    update
    lappend x [expr {[winfo reqwidth .t.l] eq [expr {$ax * 4}]}]
    lappend x [expr {[winfo reqheight .t.l] eq [expr {$ay * 2}]}]
    .t.l config -text "000\t00            0000" -wrap [expr {$ax * 12}]
	update
	lappend x [expr {[winfo reqwidth .t.l] eq [expr {$ax * 10}]}]
	lappend x [expr {[winfo reqheight .t.l] eq [expr {$ay * 2}]}]
    update
    lappend x [expr {[winfo reqwidth .t.l] eq [expr {$ax * 10}]}]
    lappend x [expr {[winfo reqheight .t.l] eq [expr {$ay * 2}]}]
    return $x
} -cleanup {
    .t.l config -wrap 0
} -result {1 1 1 1}
test font-24.13 {Tk_ComputeTextLayout: many lines -> realloc line array} -body {
    .t.l config -text "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
	update
	list [expr {[winfo reqwidth .t.l] eq 1}] \
		[expr {[winfo reqheight .t.l] eq [expr {$ay * 129}]}]
    update
    list [expr {[winfo reqwidth .t.l] eq 1}] \
	    [expr {[winfo reqheight .t.l] eq [expr {$ay * 129}]}]
} -result {1 1}
test font-24.14 {Tk_ComputeTextLayout: text ended with \n} -body {
    set x {}
	.t.l config -text "0000"
	update
	lappend x [expr {[winfo reqwidth .t.l] eq [expr {$ax * 4}]}]
	lappend x [expr {[winfo reqheight .t.l] eq $ay}]
	.t.l config -text "0000\n"
	update
	lappend x [expr {[winfo reqwidth .t.l] eq [expr {$ax * 4}]}]
	lappend x [expr {[winfo reqheight .t.l] eq [expr {$ay * 2}]}]
    return $x
    .t.l config -text "0000"
    update
    lappend x [expr {[winfo reqwidth .t.l] eq [expr {$ax * 4}]}]
    lappend x [expr {[winfo reqheight .t.l] eq $ay}]
    .t.l config -text "0000\n"
    update
    lappend x [expr {[winfo reqwidth .t.l] eq [expr {$ax * 4}]}]
    lappend x [expr {[winfo reqheight .t.l] eq [expr {$ay * 2}]}]
    set x
} -result {1 1 1 1}
destroy .t.l

test font-24.15 {Tk_ComputeTextLayout: justification} -setup {
    set x {}
	destroy .t.c
	canvas .t.c -closeenough 0
	.t.c create text 0 0 -tags text -anchor nw -just left -font "Courier -12"
	pack .t.c
	update
    destroy .t.c
    canvas .t.c -closeenough 0
    .t.c create text 0 0 -tags text -anchor nw -just left -font "Courier -12"
    pack .t.c
    update
} -body {
    csetup "000\n00000"
    .t.c itemconfig text -just left
    lappend x [.t.c index text @[expr $ax*2],0]
    .t.c itemconfig text -just center
    lappend x [.t.c index text @[expr $ax*2],0]
    .t.c itemconfig text -just right
    lappend x [.t.c index text @[expr $ax*2],0]
    .t.c itemconfig text -just left
    return $x
} -cleanup {
	destroy .t.c
    destroy .t.c
} -result {2 1 0}


test font-25.1 {Tk_FreeTextLayout procedure} -setup {
    destroy .t.f
    pack [label .t.f]
    update
} -body {
    .t.f config -text foo
    .t.f config -text boo
} -cleanup {
	destroy .t.f
    destroy .t.f
} -result {}


# Canvas created for tests: 26.*
destroy .t.c
canvas .t.c -closeenough 0
.t.c create text 0 0 -tags text -anchor nw -just left -font "Courier -12"
pack .t.c
update
test font-26.1 {Tk_DrawTextLayout procedure: auto-detect last char} -setup {
    destroy .t.f
    pack [label .t.f]
    update
} -body {
    .t.f config -text foo
} -cleanup {
	destroy .t.f
    destroy .t.f
} -result {}
test font-26.2 {Tk_DrawTextLayout procedure: multiple chunks} -body {
    csetup "000\t00\n000"
} -result {}
test font-26.3 {Tk_DrawTextLayout: draw subset of chunk: numDisplay <= 0} -body {
    csetup "000\t00"
    .t.c select from text 3
1676
1677
1678
1679
1680
1681
1682
1683

1684
1685
1686
1687
1688
1689
1690

1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705

1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717

1718
1719
1720
1721

1722
1723
1724
1725

1726
1727
1728
1729

1730
1731
1732
1733

1734
1735
1736
1737

1738
1739
1740
1741

1742
1743
1744
1745

1746
1747
1748
1749
1750
1751
1752

1753
1754
1755
1756

1757
1758
1759
1760
1761
1762
1763
1679
1680
1681
1682
1683
1684
1685

1686
1687
1688
1689
1690
1691
1692

1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707

1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719

1720
1721
1722
1723

1724
1725
1726
1727

1728
1729
1730
1731

1732
1733
1734
1735

1736
1737
1738
1739

1740
1741
1742
1743

1744
1745
1746
1747

1748
1749
1750
1751
1752
1753
1754

1755
1756
1757
1758

1759
1760
1761
1762
1763
1764
1765
1766







-
+






-
+














-
+











-
+



-
+



-
+



-
+



-
+



-
+



-
+



-
+






-
+



-
+







destroy .t.c

#  Label used in 27.* tests
destroy .t.f
pack [label .t.f]
update
test font-27.1 {Tk_UnderlineTextLayout procedure: no underline chosen} -body {
    .t.f config -text "foo" -under -1
    .t.f config -text "foo" -underline -1
} -result {}
test font-27.2 {Tk_UnderlineTextLayout procedure: underline not visible} -body {
    .t.f config -text "000          00000" -wrap [expr $ax*7] -under 10
} -result {}
test font-27.3 {Tk_UnderlineTextLayout procedure: underline is visible} -body {
    .t.f config -text "000          00000" -wrap [expr $ax*7] -under 5
    .t.f config -wrap -1 -under -1
    .t.f config -wrap -1 -underline -1
} -result {}
destroy .t.f



# Canvas created for tests: 28.*
destroy .t.c
canvas .t.c -closeenough 0
.t.c create text 0 0 -tags text -anchor nw -just left -font "Courier -12"
pack .t.c
update
test font-28.1 {Tk_PointToChar procedure: above all lines} -body {
    csetup "000"
    .t.c index text @-1,0
} -result {0}
} -result 0
test font-28.2 {Tk_PointToChar procedure: no chars} -body {
    # After fixing the following bug:
    #
    # In canvas text item, it was impossible to click to position the
    # insertion point just after the last character.
    #
    # introduced another bug that Tk_PointToChar() would return a character
    # index of 1 if TextLayout contained 0 characters.

    csetup ""
    .t.c index text @100,100
} -result {0}
} -result 0
test font-28.3 {Tk_PointToChar procedure: loop test} -body {
    csetup "000\n000\n000\n000"
    .t.c index text @10000,0
} -result {3}
} -result 3
test font-28.4 {Tk_PointToChar procedure: intersect line} -body {
    csetup "000\n000\n000"
    .t.c index text @0,$ay
} -result {4}
} -result 4
test font-28.5 {Tk_PointToChar procedure: to the left of all chunks} -body {
    csetup "000\n000\n000"
    .t.c index text @-100,$ay
} -result {4}
} -result 4
test font-28.6 {Tk_PointToChar procedure: past any possible chunk} -body {
    csetup "000\n000\n000"
    .t.c index text @100000,$ay
} -result {7}
} -result 7
test font-28.7 {Tk_PointToChar procedure: which chunk on this line} -body {
    csetup "000\n000\t000\t000\n000"
    .t.c index text @[expr $ax*2],$ay
} -result {6}
} -result 6
test font-28.8 {Tk_PointToChar procedure: which chunk on this line} -body {
    csetup "000\n000\t000\t000\n000"
    .t.c index text @[expr $ax*10],$ay
} -result {10}
} -result 10
test font-28.9 {Tk_PointToChar procedure: in special chunk} -body {
    csetup "000\n000\t000\t000\n000"
    .t.c index text @[expr $ax*6],$ay
} -result {7}
} -result 7
test font-28.10 {Tk_PointToChar procedure: past all chars in chunk} -body {
    csetup "000 0000000"
    .t.c itemconfig text -width [expr $ax*5]
    set x [.t.c index text @[expr $ax*5],0]
    .t.c itemconfig text -width 0
    return $x
} -result {3}
} -result 3
test font-28.11 {Tk_PointToChar procedure: below all chunks} -body {
    csetup "000 0000000"
    .t.c index text @0,1000000
} -result {11}
} -result 11
destroy .t.c


#  Label used in 29.* tests
destroy .t.f
pack [label .t.f]
update
1789
1790
1791
1792
1793
1794
1795
1796

1797
1798
1799
1800
1801
1802
1803


1804
1805
1806

1807
1808
1809
1810
1811
1812
1813


1814
1815
1816

1817
1818
1819
1820
1821
1822

1823
1824
1825
1826

1827
1828
1829
1830
1831
1832
1833


1834
1835
1836

1837
1838
1839
1840
1841
1842

1843
1844
1845
1846
1847

1848
1849
1850
1851
1852
1853
1854

1855
1856
1857
1858
1859

1860
1861
1862
1863
1864
1865

1866
1867
1868
1869

1870
1871
1872
1873
1874
1875

1876
1877
1878
1879

1880
1881
1882
1883
1884
1885
1886


1887
1888
1889

1890
1891
1892
1893
1894
1895

1896
1897
1898
1899

1900
1901
1902
1903
1904
1905
1906
1907
1908
1909

1910
1911
1912
1913
1914
1915
1916

1917
1918
1919
1920

1921
1922
1923
1924
1925
1926
1927


1928
1929
1930
1931
1932
1933
1934
1792
1793
1794
1795
1796
1797
1798

1799
1800
1801
1802
1803
1804


1805
1806
1807
1808

1809
1810
1811
1812
1813
1814


1815
1816
1817
1818

1819
1820
1821
1822
1823
1824

1825
1826
1827
1828

1829
1830
1831
1832
1833
1834


1835
1836
1837
1838

1839
1840
1841
1842
1843
1844

1845
1846
1847
1848
1849

1850
1851
1852
1853
1854
1855
1856

1857
1858
1859
1860
1861

1862
1863
1864
1865
1866
1867

1868
1869
1870
1871

1872
1873
1874
1875
1876
1877

1878
1879
1880
1881

1882
1883
1884
1885
1886
1887


1888
1889
1890
1891

1892
1893
1894
1895
1896
1897

1898
1899
1900
1901

1902
1903
1904
1905
1906
1907
1908
1909
1910
1911

1912
1913
1914
1915
1916
1917
1918

1919
1920
1921
1922

1923
1924
1925
1926
1927
1928


1929
1930
1931
1932
1933
1934
1935
1936
1937







-
+





-
-
+
+


-
+





-
-
+
+


-
+





-
+



-
+





-
-
+
+


-
+





-
+




-
+






-
+




-
+





-
+



-
+





-
+



-
+





-
-
+
+


-
+





-
+



-
+









-
+






-
+



-
+





-
-
+
+







destroy .t.c
canvas .t.c -closeenough 0
.t.c create text 0 0 -tags text -anchor nw -just left -font "Courier -12"
pack .t.c
update
test font-30.1 {Tk_DistanceToTextLayout procedure: loop once} -body {
    csetup "000\n000\n000"
	.t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}
    .t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}
    set x {}
    event generate .t.c <Leave>
    event generate .t.c <Enter> -x 0 -y 0
    return $x
} -cleanup {
	bind all <Enter> {}
} -result {0}
    bind all <Enter> {}
} -result 0
test font-30.2 {Tk_DistanceToTextLayout procedure: loop multiple} -body {
    csetup "000\n000\n000"
	.t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}
    .t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}
    set x {}
    event generate .t.c <Leave>
    event generate .t.c <Enter> -x $ax -y $ay
    return $x
} -cleanup {
	bind all <Enter> {}
} -result {5}
    bind all <Enter> {}
} -result 5
test font-30.3 {Tk_DistanceToTextLayout procedure: loop to end} -body {
    csetup "000\n0\n000"
	.t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}
    .t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}
    set x {}
    event generate .t.c <Leave>
    event generate .t.c <Enter> -x [expr $ax*2] -y $ay
    return $x
} -cleanup {
	bind all <Enter> {}
    bind all <Enter> {}
} -result {}
test font-30.4 {Tk_DistanceToTextLayout procedure: hit a special char (tab)} -body {
    csetup "000\t000\n000"
	.t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}
    .t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}
    set x {}
    event generate .t.c <Leave>
    event generate .t.c <Enter> -x [expr $ax*6] -y 0
    return $x
} -cleanup {
	bind all <Enter> {}
} -result {3}
    bind all <Enter> {}
} -result 3
test font-30.5 {Tk_DistanceToTextLayout procedure: ignore newline} -body {
    csetup "000\n0\n000"
	.t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}
    .t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}
    set x {}
    event generate .t.c <Leave>
    event generate .t.c <Enter> -x [expr $ax*2] -y $ay
    return $x
} -cleanup {
	bind all <Enter> {}
    bind all <Enter> {}
} -result {}
test font-30.6 {Tk_DistanceToTextLayout procedure: ignore spaces at eol} -body {
    csetup "000\n000      000000000"
    .t.c itemconfig text -width [expr $ax*10]
	.t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}
    .t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}
    set x {}
    event generate .t.c <Leave>
    event generate .t.c <Enter> -x [expr $ax*5] -y $ay
    .t.c itemconfig text -width 0
    return $x
} -cleanup {
	bind all <Enter> {}
    bind all <Enter> {}
} -result {}
.t.c itemconfig text -justify center
test font-30.7 {Tk_DistanceToTextLayout procedure: on left side} -body {
    csetup "0\n000"
	.t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}
    .t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}
    set x {}
    event generate .t.c <Leave>
    event generate .t.c <Enter> -x 0 -y 0
    return $x
} -cleanup {
	bind all <Enter> {}
    bind all <Enter> {}
} -result {}
test font-30.8 {Tk_DistanceToTextLayout procedure: on right side} -body {
    csetup "0\n000"
	.t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}
    .t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}
    set x {}
    event generate .t.c <Leave>
    event generate .t.c <Enter> -x [expr $ax*2] -y 0
    return $x
} -cleanup {
	bind all <Enter> {}
    bind all <Enter> {}
} -result {}
test font-30.9 {Tk_DistanceToTextLayout procedure: inside line} -body {
    csetup "0\n000"
	.t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}
    .t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}
    set x {}
    event generate .t.c <Leave>
    event generate .t.c <Enter> -x $ax -y 0
    return $x
} -cleanup {
	bind all <Enter> {}
} -result {0}
    bind all <Enter> {}
} -result 0
test font-30.10 {Tk_DistanceToTextLayout procedure: above line} -body {
    csetup "0\n000"
	.t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}
    .t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}
    set x {}
    event generate .t.c <Leave>
    event generate .t.c <Enter> -x 0 -y 0
    return $x
} -cleanup {
	bind all <Enter> {}
    bind all <Enter> {}
} -result {}
test font-30.11 {Tk_DistanceToTextLayout procedure: below line} -body {
    csetup "000\n0"
	.t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}
    .t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}
    set x {}
    event generate .t.c <Leave>
    event generate .t.c <Enter> -x 0 -y $ay
    return $x
} -cleanup {
	bind all <Enter> {}
} -result {}
test font-30.12 {Tk_DistanceToTextLayout procedure: in line} -body {
    csetup "0\n000"
	.t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}
    .t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}
    set x {}
    event generate .t.c <Leave>
    event generate .t.c <Enter> -x $ax -y $ay
    return $x
} -cleanup {
	bind all <Enter> {}
} -result {3}
} -result 3
.t.c itemconfig text -justify left
test font-30.13 {Tk_DistanceToTextLayout procedure: exact hit} -body {
    csetup "000"
	.t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}
    .t.c bind all <Enter> {lappend x [.t.c index current @%x,%y]}
    set x {}
    event generate .t.c <Leave>
    event generate .t.c <Enter> -x $ax -y 0
    return $x
} -cleanup {
	bind all <Enter> {}
} -result {1}
    bind all <Enter> {}
} -result 1
destroy .t.c


# Canvas created for tests 31.*
destroy .t.c
canvas .t.c -closeenough 0
.t.c create text 0 0 -tags text -anchor nw -just left -font "Courier -12"
1966
1967
1968
1969
1970
1971
1972
1973

1974
1975
1976
1977
1978
1979
1980
1981
1982





1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995

1996
1997
1998
1999
2000
2001
2002
1969
1970
1971
1972
1973
1974
1975

1976
1977
1978
1979
1980





1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997

1998
1999
2000
2001
2002
2003
2004
2005







-
+




-
-
-
-
-
+
+
+
+
+












-
+







    .t.c itemconfigure text -angle 90
    # Coordinates of the rectangle to check can be hardcoded:
    # The goal of this test is to check whether the overlap detection algorithm
    # works when the rectangle is entirely included in a chunk of the text layout.
    # The text has been rotated 90 degrees around it's upper left corner,
    # so it's enough to check with a small rectangle with small negative y coords.
    .t.c find overlapping 5 -7 7 -5
} -result {1}
} -result 1
destroy .t.c


test font-32.1 {Tk_TextLayoutToPostscript: ensure buffer doesn't overflow} -setup {
	destroy .t.c
	canvas .t.c -closeenough 0
	.t.c create text 0 0 -tags text -anchor nw -just left -font "Courier -12"
	pack .t.c
	update
    destroy .t.c
    canvas .t.c -closeenough 0
    .t.c create text 0 0 -tags text -anchor nw -just left -font "Courier -12"
    pack .t.c
    update
} -body {
    # If there were a whole bunch of returns or tabs in a row, then the
    # temporary buffer could overflow and write on the stack.
    csetup "qwertyuiopasdfghjklzxcvbnm1234qwertyuiopasdfghjklzxcvbnm\n"
    .t.c itemconfig text -width 800
    .t.c insert text end "qwertyuiopasdfghjklzxcvbnm1234qwertyuiopasdfghjklzxcvbnm\n"
    .t.c insert text end "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
    .t.c insert text end "end"
    set x [.t.c postscript]
    set i [string first "(qwerty" $x]
    string range $x $i [expr {$i + 278}]
} -cleanup {
	destroy .t.c
    destroy .t.c
} -result {(qwertyuiopasdfghjklzxcvbnm1234qwertyuiopasdfghjklzxcvbnm)]
[(qwertyuiopasdfghjklzxcvbnm1234qwertyuiopasdfghjklzxcvbnm)]
[()]
[()]
[()]
[()]
[()]
2046
2047
2048
2049
2050
2051
2052
2053

2054
2055
2056
2057
2058




2059
2060
2061
2062
2063
2064

2065
2066
2067
2068
2069




2070
2071

2072
2073
2074
2075

2076
2077
2078
2079
2080




2081
2082

2083
2084
2085
2086

2087
2088
2089
2090
2091




2092
2093

2094
2095
2096
2097

2098
2099
2100
2101
2102




2103
2104

2105
2106
2107
2108

2109
2110
2111
2112
2113




2114
2115

2116
2117
2118
2119

2120
2121
2122

2123
2124
2125

2126
2127
2128

2129
2130
2131

2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142

2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153

2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166

2167
2168
2169
2170
2171
2172


2173
2174

2175
2176
2177
2178

2179
2180
2181


2182
2183
2184


2185
2186
2187

2188
2189
2190


2191
2192

2193
2194
2195
2196

2197
2198
2199


2200
2201

2202
2203
2204
2205

2206
2207
2208


2209
2210
2211


2212
2213
2214

2215
2216
2217


2218
2219
2220


2221
2222
2223
2224
2225
2226
2227
2049
2050
2051
2052
2053
2054
2055

2056
2057




2058
2059
2060
2061
2062
2063
2064
2065
2066

2067
2068




2069
2070
2071
2072
2073

2074
2075
2076
2077

2078
2079




2080
2081
2082
2083
2084

2085
2086
2087
2088

2089
2090




2091
2092
2093
2094
2095

2096
2097
2098
2099

2100
2101




2102
2103
2104
2105
2106

2107
2108
2109
2110

2111
2112




2113
2114
2115
2116
2117

2118
2119
2120
2121

2122
2123
2124

2125
2126
2127

2128
2129
2130

2131
2132
2133

2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144

2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155

2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168

2169
2170
2171
2172
2173


2174
2175
2176

2177
2178
2179
2180

2181
2182


2183
2184
2185


2186
2187
2188
2189

2190
2191


2192
2193
2194

2195
2196
2197
2198

2199
2200


2201
2202
2203

2204
2205
2206
2207

2208
2209


2210
2211
2212


2213
2214
2215
2216

2217
2218


2219
2220
2221


2222
2223
2224
2225
2226
2227
2228
2229
2230







-
+

-
-
-
-
+
+
+
+





-
+

-
-
-
-
+
+
+
+

-
+



-
+

-
-
-
-
+
+
+
+

-
+



-
+

-
-
-
-
+
+
+
+

-
+



-
+

-
-
-
-
+
+
+
+

-
+



-
+

-
-
-
-
+
+
+
+

-
+



-
+


-
+


-
+


-
+


-
+










-
+










-
+












-
+




-
-
+
+

-
+



-
+

-
-
+
+

-
-
+
+


-
+

-
-
+
+

-
+



-
+

-
-
+
+

-
+



-
+

-
-
+
+

-
-
+
+


-
+

-
-
+
+

-
-
+
+







} -body {
    # (objc & 1)
    font create xyz -family
} -returnCodes error -result {value for "-family" option missing}

test font-34.3 {ConfigAttributesObj procedure: family} -setup {
    catch {font delete xyz}
	set x {}
    set x {}
} -body {
	font create xyz -family xyz
	lappend x [font config xyz -family]
	font config xyz -family times
	lappend x [font config xyz -family]
    font create xyz -family xyz
    lappend x [font config xyz -family]
    font config xyz -family times
    lappend x [font config xyz -family]
} -cleanup {
	font delete xyz
} -result {xyz times}
test font-34.4 {ConfigAttributesObj procedure: size} -setup {
    catch {font delete xyz}
	set x {}
    set x {}
} -body {
	font create xyz -size 20
	lappend x [font config xyz -size]
	font config xyz -size 40
	lappend x [font config xyz -size]
    font create xyz -size 20
    lappend x [font config xyz -size]
    font config xyz -size 40
    lappend x [font config xyz -size]
} -cleanup {
	font delete xyz
    font delete xyz
} -result {20 40}
test font-34.5 {ConfigAttributesObj procedure: weight} -setup {
    catch {font delete xyz}
	set x {}
    set x {}
} -body {
	font create xyz -weight normal
	lappend x [font config xyz -weight]
	font config xyz -weight bold
	lappend x [font config xyz -weight]
    font create xyz -weight normal
    lappend x [font config xyz -weight]
    font config xyz -weight bold
    lappend x [font config xyz -weight]
} -cleanup {
	font delete xyz
    font delete xyz
} -result {normal bold}
test font-34.6 {ConfigAttributesObj procedure: slant} -setup {
    catch {font delete xyz}
	set x {}
    set x {}
} -body {
	font create xyz -slant roman
	lappend x [font config xyz -slant]
	font config xyz -slant italic
	lappend x [font config xyz -slant]
    font create xyz -slant roman
    lappend x [font config xyz -slant]
    font config xyz -slant italic
    lappend x [font config xyz -slant]
} -cleanup {
	font delete xyz
    font delete xyz
} -result {roman italic}
test font-34.7 {ConfigAttributesObj procedure: underline} -setup {
    catch {font delete xyz}
	set x {}
    set x {}
} -body {
	font create xyz -underline 0
	lappend x [font config xyz -underline]
	font config xyz -underline 1
	lappend x [font config xyz -underline]
    font create xyz -underline 0
    lappend x [font config xyz -underline]
    font config xyz -underline 1
    lappend x [font config xyz -underline]
} -cleanup {
	font delete xyz
    font delete xyz
} -result {0 1}
test font-34.8 {ConfigAttributesObj procedure: overstrike} -setup {
    catch {font delete xyz}
	set x {}
    set x {}
} -body {
	font create xyz -overstrike 0
	lappend x [font config xyz -overstrike]
	font config xyz -overstrike 1
	lappend x [font config xyz -overstrike]
    font create xyz -overstrike 0
    lappend x [font config xyz -overstrike]
    font config xyz -overstrike 1
    lappend x [font config xyz -overstrike]
} -cleanup {
	font delete xyz
    font delete xyz
} -result {0 1}

test font-34.9 {ConfigAttributesObj procedure: size} -body {
	font create xyz -size xyz
    font create xyz -size xyz
} -returnCodes error -result {expected integer but got "xyz"}
test font-34.10 {ConfigAttributesObj procedure: weight} -body {
	font create xyz -weight xyz
    font create xyz -weight xyz
} -returnCodes error -result {bad -weight value "xyz": must be normal, or bold}
test font-34.11 {ConfigAttributesObj procedure: slant} -body {
	font create xyz -slant xyz
    font create xyz -slant xyz
} -returnCodes error -result {bad -slant value "xyz": must be roman, or italic}
test font-34.12 {ConfigAttributesObj procedure: underline} -body {
	font create xyz -underline xyz
    font create xyz -underline xyz
} -returnCodes error -result {expected boolean value but got "xyz"}
test font-34.13 {ConfigAttributesObj procedure: overstrike} -body {
	font create xyz -overstrike xyz
    font create xyz -overstrike xyz
} -returnCodes error -result {expected boolean value but got "xyz"}


test font-35.1 {GetAttributeInfoObj procedure: one attribute} -setup {
    catch {font delete xyz}
} -body {
    # (objPtr != NULL)
    font create xyz -family xyz
    font config xyz -family
} -cleanup {
	font delete xyz
    font delete xyz
} -result {xyz}


test font-36.1 {GetAttributeInfoObj procedure: unknown attribute} -setup {
    catch {font delete xyz}
} -body {
    # (Tcl_GetIndexFromObj() != TCL_OK)
    font create xyz
    font config xyz -xyz
} -cleanup {
	font delete xyz
    font delete xyz
} -returnCodes {
    error
} -result {bad option "-xyz": must be -family, -size, -weight, -slant, -underline, or -overstrike}


test font-37.1 {GetAttributeInfoObj procedure: all attributes} -setup {
    catch {font delete xyz}
} -body {
    # not (objPtr != NULL)
    font create xyz -family xyz
    font config xyz
} -cleanup {
	font delete xyz
    font delete xyz
} -result {-family xyz -size 0 -weight normal -slant roman -underline 0 -overstrike 0}
test font-37.2 {GetAttributeInfo procedure: family} -setup {
    catch {font delete xyz}
} -body {
	font create xyz -family xyz
	font config xyz -family
    font create xyz -family xyz
    font config xyz -family
} -cleanup {
	font delete xyz
    font delete xyz
} -result {xyz}
test font-37.3 {GetAttributeInfo procedure: size} -setup {
    catch {font delete xyz}
	set x {}
    set x {}
} -body {
	font create xyz -size 20
	font config xyz -size
    font create xyz -size 20
    font config xyz -size
} -cleanup {
	font delete xyz
} -result {20}
    font delete xyz
} -result 20
test font-37.4 {GetAttributeInfo procedure: weight} -setup {
    catch {font delete xyz}
	set x {}
    set x {}
} -body {
	font create xyz -weight normal
	font config xyz -weight
    font create xyz -weight normal
    font config xyz -weight
} -cleanup {
	font delete xyz
    font delete xyz
} -result {normal}
test font-37.5 {GetAttributeInfo procedure: slant} -setup {
    catch {font delete xyz}
	set x {}
    set x {}
} -body {
	font create xyz -slant italic
	font config xyz -slant
    font create xyz -slant italic
    font config xyz -slant
} -cleanup {
	font delete xyz
    font delete xyz
} -result {italic}
test font-37.6 {GetAttributeInfo procedure: underline} -setup {
    catch {font delete xyz}
	set x {}
    set x {}
} -body {
	font create xyz -underline yes
	font config xyz -underline
    font create xyz -underline yes
    font config xyz -underline
} -cleanup {
	font delete xyz
} -result {1}
    font delete xyz
} -result 1
test font-37.7 {GetAttributeInfo procedure: overstrike} -setup {
    catch {font delete xyz}
	set x {}
    set x {}
} -body {
	font create xyz -overstrike no
	font config xyz -overstrike
    font create xyz -overstrike no
    font config xyz -overstrike
} -cleanup {
	font delete xyz
} -result {0}
    font delete xyz
} -result 0


# In tests below, one field is set to "xyz" so that font name doesn't
# look like a native X font, so that ParseFontNameObj or TkParseXLFD will
# be called.

test font-38.1 {ParseFontNameObj procedure: begins with -} -body {
2251
2252
2253
2254
2255
2256
2257
2258

2259
2260
2261
2262
2263
2264
2265
2254
2255
2256
2257
2258
2259
2260

2261
2262
2263
2264
2265
2266
2267
2268







-
+







test font-38.9 {ParseFontNameObj procedure: arguments} -body {
    font actual {times 20 xyz xyz}
} -returnCodes error -result {unknown font style "xyz"}
test font-38.10 {ParseFontNameObj procedure: arguments} -body {
    font actual {times xyz xyz}
} -returnCodes error -result {expected integer but got "xyz"}
test font-38.11 {ParseFontNameObj procedure: stylelist loop} -constraints {
	unixOrPc
	unixOrWin failsOnUbuntuNoXft
} -body {
    lrange [font actual {times 12 bold italic overstrike underline}] 4 end
} -result {-weight bold -slant italic -underline 1 -overstrike 1}
test font-38.12 {ParseFontNameObj procedure: stylelist error} -body {
    font actual {times 12 bold xyz}
} -returnCodes error -result {unknown font style "xyz"}
test font-38.13 "ParseFontNameObj: options with hyphenated family: bug #2791352" -body {
2333
2334
2335
2336
2337
2338
2339
2340
2341


2342
2343

2344
2345
2346
2347
2348
2349




2350
2351

2352
2353
2354
2355


2356
2357
2358
2359
2360
2361
2362
2363
2364


2365
2366
2367
2368
2369
2370
2371
2372

2373
2374
2375
2376

2377
2378
2379
2380
2381

2382
2383
2384
2385
2386
2387
2388
2336
2337
2338
2339
2340
2341
2342


2343
2344
2345

2346
2347
2348




2349
2350
2351
2352
2353

2354
2355
2356


2357
2358
2359
2360
2361
2362
2363
2364
2365


2366
2367
2368
2369
2370
2371
2372
2373
2374

2375
2376
2377
2378

2379
2380
2381
2382
2383

2384
2385
2386
2387
2388
2389
2390
2391







-
-
+
+

-
+


-
-
-
-
+
+
+
+

-
+


-
-
+
+







-
-
+
+







-
+



-
+




-
+







    font actual -xyz--*-*-*-*-*-*-*-*-*-*-*-*
    font actual -xyz-*-*-*-*-*-*-*-*-*-*-*-*-*
    font actual -xyz-?-*-*-*-*-*-*-*-*-*-*-*-*
    lindex [font actual -xyz-times-*-*-*-*-*-*-*-*-*-*-*-*] 1
} -result [font actual {times 0} -family]


test font-44.1 {TkFontGetPixels: size < 0} -setup {
	set oldscale [tk scaling]
test font-44.1 {TkFontGetPixels: size < 0} -constraints failsOnUbuntu -setup {
    set oldscale [tk scaling]
} -body {
	tk scaling 0.5
    tk scaling 0.5
    font actual {times -12} -size
} -cleanup {
	tk scaling $oldscale
} -result {24}
test font-44.2 {TkFontGetPoints: size >= 0} -constraints noExceed -setup {
	set oldscale [tk scaling]
    tk scaling $oldscale
} -result 24
test font-44.2 {TkFontGetPoints: size >= 0} -constraints {noExceed failsOnUbuntuNoXft} -setup {
    set oldscale [tk scaling]
} -body {
	tk scaling 0.5
    tk scaling 0.5
    font actual {times 12} -size
} -cleanup {
	tk scaling $oldscale
} -result {12}
    tk scaling $oldscale
} -result 12


test font-45.1 {TkFontGetAliasList: no match} -body {
    font actual {snarky 10} -family
} -result [font actual {-size 10} -family]
test font-45.2 {TkFontGetAliasList: match} -constraints win -body {
    font actual {times 10} -family
} -result {Times New Roman}
test font-45.3 {TkFontGetAliasList: match} -constraints {noExceed} -body {
} -result {times}
test font-45.3 {TkFontGetAliasList: match} -constraints {noExceed failsOnUbuntu} -body {
    if {[font actual {{times new roman} 10} -family] eq "Times New Roman"} {
        # avoid test failure on systems that have a real "times new roman" font
        set res 1
    } else {
        set res [expr {[font actual {{times new roman} 10} -family] eq \
                       [font actual {times 10} -family]} ]
    }
} -result {1}
} -result 1


test font-46.1 {font actual, with character, no option, no --} -body {
	font actual {times 10} a
    font actual {times 10} a
} -match glob -result [list -family [font actual {times 10} -family] -size *\
		 -slant roman -underline 0 -overstrike 0]

test font-46.2 {font actual, with character introduced by --} -body {
	font actual {times 10} -- -
    font actual {times 10} -- -
} -match glob -result [list -family [font actual {times 10} -family] -size *\
		 -slant roman -underline 0 -overstrike 0]

test font-46.3 {font actual, with character and option} -body {
    font actual {times 10} -family a
} -result [font actual {times 10} -family]

Changes to tests/fontchooser.test.
1
2
3

4
5

6
7
8



9
10
11

12
13
14
15
16
17
18
1
2

3
4

5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21


-
+

-
+



+
+
+


-
+







# Test the "tk::fontchooser" command
#
# Copyright (c) 2008 Pat Thoyts
# Copyright © 2008 Pat Thoyts

package require tcltest 2.1
package require tcltest 2.2
eval tcltest::configure $argv
tcltest::loadTestedCommands

testConstraint failsOnUbuntu [expr {![info exists ::env(CI)] || ![string match Linux $::tcl_platform(os)]}]
testConstraint failsOnUbuntuNoXft [expr {[testConstraint failsOnUbuntu] || (![catch {tk::pkgconfig get fontsystem} fs] && ($fs eq "xft"))}]

# the following helper functions are related to the functions used
# in winDialog.test where they are used to send messages to the win32
# dialog (hence the wierdness).
# dialog (hence the weirdness).

proc start {cmd} {
    set ::tk_dialog {}
    set ::iter_after 0
    after 1 $cmd
}
proc then {cmd} {
75
76
77
78
79
80
81
82

83
84
85
86
87
88
89
78
79
80
81
82
83
84

85
86
87
88
89
90
91
92







-
+








test fontchooser-1.7 {tk fontchooser: usage} -returnCodes error -body {
    tk fontchooser configure -parent abc
} -result {bad window path name "abc"}

test fontchooser-1.8 {tk fontchooser: usage} -returnCodes ok -body {
    tk fontchooser configure -visible
} -result {0}
} -result 0

test fontchooser-1.9 {tk fontchooser: usage} -returnCodes error -body {
    tk fontchooser configure -visible 1
} -match glob -result {*}

# -------------------------------------------------------------------------
#
105
106
107
108
109
110
111
112

113
114
115
116
117
118
119
120

121
122
123
124
125
126
127
108
109
110
111
112
113
114

115
116
117
118
119
120
121
122

123
124
125
126
127
128
129
130







-
+







-
+







    }
    set x
} -result {Hello}

test fontchooser-2.1 {fontchooser -title (cyrillic)} -constraints scriptImpl -body {
    start {
        tk::fontchooser::Configure \
            -title "\u041f\u0440\u0438\u0432\u0435\u0442"
            -title "Привет"
        tk::fontchooser::Show
    }
    then {
        set x [wm title $::tk_dialog]
        Click cancel
    }
    set x
} -result "\u041f\u0440\u0438\u0432\u0435\u0442"
} -result "Привет"

test fontchooser-3.0 {fontchooser -parent} -constraints scriptImpl -body {
    start {
        tk::fontchooser::Configure -parent .
        tk::fontchooser::Show
    }
    then {
151
152
153
154
155
156
157
158

159
160
161
162
163
164
165
166
167
168
169

170
171
172
173
174
175
176
177
178
179
180

181
182

183
184
185
186
187
188
189
190
191






192
193
194
195
196
197
198
199
200
201
154
155
156
157
158
159
160

161
162
163
164
165
166
167
168
169
170
171

172
173
174
175
176
177
178
179
180
181
182

183
184

185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210







-
+










-
+










-
+

-
+









+
+
+
+
+
+










        tk::fontchooser::Configure -command ApplyFont -font courier
        tk::fontchooser::Show
    }
    then {
        Click ok
    }
    expr {$::testfont ne {}}
} -result {1}
} -result 1

test fontchooser-4.2 {fontchooser -font} -constraints scriptImpl -body {
    start {
        tk::fontchooser::Configure -command ApplyFont -font TkDefaultFont
        tk::fontchooser::Show
    }
    then {
        Click ok
    }
    expr {$::testfont ne {}}
} -result {1}
} -result 1

test fontchooser-4.3 {fontchooser -font} -constraints scriptImpl -body {
    start {
        tk::fontchooser::Configure -command ApplyFont -font {times 14 bold}
        tk::fontchooser::Show
    }
    then {
        Click ok
    }
    expr {$::testfont ne {}}
} -result {1}
} -result 1

test fontchooser-4.4 {fontchooser -font} -constraints scriptImpl -body {
test fontchooser-4.4 {fontchooser -font} -constraints {scriptImpl failsOnUbuntuNoXft} -body {
    start {
        tk::fontchooser::Configure -command ApplyFont -font {times 14 bold}
        tk::fontchooser::Show
    }
    then {
        Click ok
    }
    lrange $::testfont 1 end
} -result {14 bold}

test fontchooser-5.1 {fontchooser multiple configure} -constraints {scriptImpl} -body {
    tk fontchooser configure -title TestTitle -command foo
    tk fontchooser configure -command bar
    tk fontchooser configure -title
} -result {TestTitle}

# -------------------------------------------------------------------------

cleanupTests
return

# Local Variables:
# mode: tcl
# indent-tabs-mode: nil
# End:
Changes to tests/frame.test.
1
2


3
4
5
6
7



8
9
10
11
12

13
14


15
16
17


18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33




34
35
36
37
38
39
40
41
42


43
44
45
46
47
48
49
50
51
52
53
54

















55










56
57

58
59
60
61
62
63
64
65
66
67
68
69

70
71

72
73
74

75
76
77
78
79
80
81
82
83
84
85
86

87
88

89
90
91

92
93
94
95
96
97
98
99
100
101
102
103

104
105

106
107
108

109
110
111
112
113
114
115

116
117
118
119
120
121
122
123
124
125
126
127
128
129
130

131
132
133
134
135
136
137

138
139
140
141

142
143

144
145

146
147
148
149
150
151
152
153
154
155

156
157

158
159

160
161
162
163
164
165
166
167
168

169
170
171
172
173
174
175
176
177

178
179
180
181
182
183
184
185
186

187
188
189
190
191
192
193
194
195

196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213

214
215
216
217
218
219
220
221
222

223
224
225
226
227
228
229
230
231

232
233
234
235
236
237
238
239
240

241
242
243
244
245
246
247
248
249

250
251
252
253
254
255
256
257
258

259
260
261
262
263
264
265
266
267
268

269
270

271
272
273
274
275
276
277
278
279
280
281
282

283
284
285
286
287
288
289
290

291
292
293
294
295
296
297
298
299
300
301
302
303
304

305
306

307
308
309

310
311
312
313
314
315
316
317
318
319
320
321
322
323

324
325

326
327
328

329
330
331
332
333

334
335

336
337
338
339
340
341
342
343
344
345
346
347
348
349

350
351
352
353
354
355
356
357

358
359
360

361
362
363
364
365
366
367
368
369
370
371








372



373

374








375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410

411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426

427
428

429
430
431

432
433
434

435
436
437
438







439
440
441
442

443
444
445
446


447
448
449
450
451
452

453
454

455
456
457

458
459
460
461
462
463
464

465
466
467
468
469

470
471

472
473

474
475
476
477
478
479
480
481
482
483

484
485

486
487

488
489
490
491
492
493
494
495
496
497

498
499
500
501
502
503
504

505
506
507
508
509
510
511

512
513
514
515
516
517
518

519
520
521
522
523
524
525
526
527
528
529
530
531
532

533
534
535
536
537
538
539

540
541
542
543
544
545
546

547
548
549
550
551
552
553

554
555
556
557
558
559
560

561
562
563
564
565
566
567
568

569
570

571
572
573
574

575
576
577
578
579
580
581

582
583

584
585

586
587
588
589
590
591
592
593

594
595
596
597
598
599
600
601
602

603
604
605
606
607
608
609
610
611
612
613
614
615
616
617

618
619
620
621
622
623
624
625
626
627

628
629
630
631
632
633
634
635
636
637
638

639
640
641
642
643
644
645
646
647
648
649
650
651

652
653
654
655
656
657
658
659
660
661
662
663
664
665





666
667
668
669
670
671
672
673
674
675


676
677




678



679
680



681
682
683
684
685
686
687
688
689
690
691



692
693
694
695
696
697

698
699

700
701
702
703
704
705
706
707


708
709

710
711

712
713
714
715
716
717
718
719


720
721

722
723

724
725
726
727
728
729
730
731
732
733
734


735
736

737
738

739
740
741
742
743
744
745
746
747
748
749


750
751
752
753

754
755
756
757
758
759
760
761
762
763
764

765
766

767
768
769
770
771
772
773
774


775
776

777
778

779
780
781
782
783
784
785
786
787


788
789

790
791

792
793
794
795
796
797
798
799


800
801

802
803

804
805
806
807
808
809
810
811
812
813

814
815
816

817
818

819
820
821
822
823
824
825
826
827
828
829

830
831
832

833
834

835
836
837
838
839
840
841
842
843


844
845
846
847
848
849

850
851
852
853
854
855
856


1
2
3
4



5
6
7
8
9
10
11

12
13
14
15
16
17


18
19
20
21
22
23
24
25
26
27
28
29
30
31




32
33
34
35
36
37
38
39
40
41
42


43
44
45
46
47
48
49
50
51





52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80

81
82
83
84
85
86
87
88
89
90
91
92

93
94

95

96

97
98
99
100
101
102
103
104
105
106
107
108

109
110

111

112

113
114
115
116
117
118
119
120
121
122
123
124

125
126

127

128

129
130
131
132
133
134
135

136
137
138
139
140
141
142
143
144
145
146
147
148
149
150

151
152
153
154
155
156
157

158
159
160
161

162
163

164
165

166
167
168
169
170
171
172
173
174
175

176

177
178
179

180
181
182
183
184
185
186
187
188

189
190
191
192
193
194
195
196
197

198
199
200
201
202
203
204
205
206

207
208
209
210
211
212
213
214
215

216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233

234
235
236
237
238
239
240
241
242

243
244
245
246
247
248
249
250
251

252
253
254
255
256
257
258
259
260

261
262
263
264
265
266
267
268
269

270
271
272
273
274
275
276
277
278

279
280
281
282
283
284
285
286
287
288

289
290

291
292
293
294
295
296
297
298
299
300
301
302

303
304
305
306
307
308

309

310
311
312
313
314
315
316
317
318
319
320
321
322
323

324
325

326

327

328
329
330
331
332
333
334
335
336
337
338
339
340
341

342
343

344

345

346
347
348
349
350

351
352

353
354
355
356

357
358
359
360
361
362
363

364

365
366
367
368
369
370



371



372
373

374
375
376
377
378
379



380
381
382
383
384
385
386
387
388
389
390
391
392
393

394
395
396
397
398
399
400
401
402
403
404
405
406
407
408



























409

410
411

412
413
414
415
416
417
418
419
420

421
422
423

424
425

426

427

428
429
430

431
432



433
434
435
436
437
438
439
440
441
442

443
444
445


446
447
448
449
450
451
452

453
454

455

456

457
458
459
460
461
462
463

464
465
466
467
468

469
470

471
472

473
474
475
476
477
478
479
480
481
482

483

484
485
486

487

488
489
490
491
492
493
494
495

496
497
498
499
500
501
502

503
504
505
506
507
508
509

510
511
512
513
514
515
516

517
518
519
520
521
522
523
524
525
526
527
528
529
530

531
532
533
534
535
536
537

538
539
540
541
542
543
544

545
546
547
548
549
550
551

552
553
554
555
556
557
558

559
560
561
562
563
564
565
566

567
568

569
570
571
572

573
574
575
576
577
578


579
580

581
582

583
584
585
586
587
588
589
590

591
592
593
594
595
596
597
598
599

600
601
602
603
604
605
606
607
608
609
610

611
612
613

614
615
616
617
618
619
620
621
622
623

624
625
626
627
628
629
630
631
632
633
634

635
636
637
638
639
640
641
642
643
644
645
646
647

648
649
650
651
652
653
654
655
656
657





658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674


675
676
677
678
679
680
681
682


683
684
685
686
687
688
689
690
691
692




693
694
695

696
697
698
699

700
701

702
703
704
705
706
707
708


709
710
711

712
713

714
715
716
717
718
719
720


721
722
723

724
725

726
727
728
729
730
731
732
733
734
735


736
737
738

739
740

741
742
743
744
745
746
747
748
749
750


751
752
753
754
755

756
757
758
759
760
761
762
763
764
765
766

767
768

769
770
771
772
773
774
775


776
777
778

779
780

781
782
783
784
785
786
787
788


789
790
791

792
793

794
795
796
797
798
799
800


801
802
803

804
805

806
807
808
809
810
811
812
813
814
815

816
817
818

819
820

821
822

823
824
825
826
827
828
829
830

831
832
833

834
835

836
837

838
839
840
841
842


843
844
845
846
847

848

849
850
851
852
853
854
855
856
-
-
+
+


-
-
-
+
+
+




-
+


+
+

-
-
+
+












-
-
-
-
+
+
+
+







-
-
+
+







-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+

-
+











-
+

-
+
-

-
+











-
+

-
+
-

-
+











-
+

-
+
-

-
+






-
+














-
+






-
+



-
+

-
+

-
+









-
+
-

+

-
+








-
+








-
+








-
+








-
+

















-
+








-
+








-
+








-
+








-
+








-
+









-
+

-
+











-
+





-

-
+













-
+

-
+
-

-
+













-
+

-
+
-

-
+




-
+

-
+



-







-

-
+





-
-
-
+
-
-
-
+

-






-
-
-
+
+
+
+
+
+
+
+

+
+
+

+
-
+
+
+
+
+
+
+
+







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
+

-









-



-
+

-
+
-

-
+


-
+

-
-
-
+
+
+
+
+
+
+



-
+


-
-
+
+





-
+

-
+
-

-
+






-
+




-
+

-
+

-
+









-
+
-

+

-
+
-








-
+






-
+






-
+






-
+













-
+






-
+






-
+






-
+






-
+







-
+

-
+



-
+





-
-
+

-
+

-
+







-
+








-
+










-



-
+









-
+










-
+












-
+









-
-
-
-
-
+
+
+
+
+










+
+
-
-
+
+
+
+

+
+
+
-
-
+
+
+







-
-
-
-
+
+
+
-




-
+

-
+






-
-
+
+

-
+

-
+






-
-
+
+

-
+

-
+









-
-
+
+

-
+

-
+









-
-
+
+



-
+










-
+

-
+






-
-
+
+

-
+

-
+







-
-
+
+

-
+

-
+






-
-
+
+

-
+

-
+









-
+


-
+

-
+

-








-
+


-
+

-
+

-





-
-
+
+



-

-
+







# This file is a Tcl script to test out the "frame" and "toplevel"
# commands of Tk.  It is organized in the standard fashion for Tcl
# This file is a Tcl script to test out the "frame", "labelframe" and
# "toplevel" commands of Tk.  It is organized in the standard fashion for Tcl
# tests.
#
# Copyright (c) 1994 The Regents of the University of California.
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1994 The Regents of the University of California.
# Copyright © 1994-1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
namespace import ::tcltest::*
eval tcltest::configure $argv
tcltest::configure {*}$argv
tcltest::loadTestedCommands

tcltest::testConstraint x11 [expr {[tk windowingsystem] eq "x11"}]

# eatColors --
# Creates a toplevel window and allocates enough colors in it to
# use up all the slots in the colormap.
# Creates a toplevel window and allocates enough colors in it to use up all
# the slots in an 8-bit colormap.
#
# Arguments:
# w -		Name of toplevel window to create.

proc eatColors {w} {
    catch {destroy $w}
    toplevel $w
    wm geom $w +0+0
    canvas $w.c -width 400 -height 200 -bd 0
    pack $w.c
    for {set y 0} {$y < 8} {incr y} {
	for {set x 0} {$x < 40} {incr x} {
	    set color [format #%02x%02x%02x [expr $x*6] [expr $y*30] 0]
	    $w.c create rectangle [expr 10*$x] [expr 20*$y] \
		    [expr 10*$x + 10] [expr 20*$y + 20] -outline {} \
		    -fill $color
	    set color [format #%02x%02x%02x [expr {$x*6}] [expr {$y*30}] 0]
	    $w.c create rectangle [expr {10*$x}] [expr {20*$y}] \
		[expr {10*$x + 10}] [expr {20*$y + 20}] -outline {} \
		-fill $color
	}
    }
    update
}

# colorsFree --
#
# Returns 1 if there appear to be free colormap entries in a window,
# 0 otherwise.
# Returns 1 if there appear to be free colormap entries in a window, 0
# otherwise.
#
# Arguments:
# w -			Name of window in which to check.
# red, green, blue -	Intensities to use in a trial color allocation
#			to see if there are colormap entries free.

proc colorsFree {w {red 31} {green 245} {blue 192}} {
    set vals [winfo rgb $w [format #%02x%02x%02x $red $green $blue]]
    expr ([lindex $vals 0]/256 == $red) && ([lindex $vals 1]/256 == $green) \
	    && ([lindex $vals 2]/256 == $blue)
}

    lassign [winfo rgb $w [format "#%02x%02x%02x" $red $green $blue]] r g b
    expr {($r/256 == $red) && ($g/256 == $green) && ($b/256 == $blue)}
}

# uniq --
#
# Returns the unique items of a list in the order they first appear.
#
# Arguments:
# list -		The list to uniq-ify.
proc uniq {list} {
    set d {}
    foreach item $list {
	dict set d $item {}
    }
    return [dict keys $d]
}

# optnames --
#
# Returns the option names out of a list of option details.
#
# Arguments:
# options -		The option detail list.
proc optnames {options} {
    lsort [lmap desc $options {lindex $desc 0}]
}

test frame-1.1 {frame configuration options} -setup {
	deleteWindows
    deleteWindows
} -body {
    frame .f -class NewFrame
    .f configure -class
} -cleanup {
    deleteWindows
} -result {-class class Class Frame NewFrame}
test frame-1.2 {frame configuration options} -setup {
    deleteWindows
} -body {
    frame .f -class NewFrame
    .f configure -class Different
} -cleanup {
} -returnCodes error -cleanup {
    deleteWindows
} -returnCodes error -result {can't modify -class option after widget is created}
} -result {can't modify -class option after widget is created}

test frame-1.3 {frame configuration options} -setup {
	deleteWindows
    deleteWindows
} -body {
    frame .f -colormap new
    .f configure -colormap
} -cleanup {
    deleteWindows
} -result {-colormap colormap Colormap {} new}
test frame-1.4 {frame configuration options} -setup {
    deleteWindows
} -body {
    frame .f -colormap new
    .f configure -colormap .
} -cleanup {
} -returnCodes error -cleanup {
    deleteWindows
} -returnCodes error -result {can't modify -colormap option after widget is created}
} -result {can't modify -colormap option after widget is created}

test frame-1.5 {frame configuration options} -setup {
	deleteWindows
    deleteWindows
} -body {
    frame .f -visual default
    .f configure -visual
} -cleanup {
    deleteWindows
} -result {-visual visual Visual {} default}
test frame-1.6 {frame configuration options} -setup {
    deleteWindows
} -body {
    frame .f -visual default
    .f configure -visual best
} -cleanup {
} -returnCodes error -cleanup {
    deleteWindows
} -returnCodes error -result {can't modify -visual option after widget is created}
} -result {can't modify -visual option after widget is created}

test frame-1.7 {frame configuration options} -setup {
	deleteWindows
    deleteWindows
} -body {
    frame .f -screen bogus
} -cleanup {
    deleteWindows
} -returnCodes error -result {unknown option "-screen"}
test frame-1.8 {frame configuration options} -setup {
	deleteWindows
    deleteWindows
} -body {
    frame .f -container true
} -cleanup {
    deleteWindows
} -result {.f}
test frame-1.9 {frame configuration options} -setup {
    deleteWindows
} -body {
    frame .f -container true
    .f configure -container
} -cleanup {
    deleteWindows
} -result {-container container Container 0 1}
test frame-1.10 {frame configuration options} -setup {
	deleteWindows
    deleteWindows
} -body {
    frame .f -container bogus
} -cleanup {
    deleteWindows
} -returnCodes error -result {expected boolean value but got "bogus"}
test frame-1.11 {frame configuration options} -setup {
	deleteWindows
    deleteWindows
} -body {
    frame .f
    .f configure -container 1
} -cleanup {
} -returnCodes error -cleanup {
    deleteWindows
} -returnCodes error -result {can't modify -container option after widget is created}
} -result {can't modify -container option after widget is created}
test frame-1.12 {frame configuration options} -setup {
	deleteWindows
    deleteWindows
} -body {
    # Make sure all options can be set to the default value
    frame .f
    set opts {}
    foreach opt [.f configure] {
        if {[llength $opt] == 5} {
            lappend opts [lindex $opt 0] [lindex $opt 4]
        }
    }
    eval frame .g $opts
    frame .g {*}$opts
    destroy .f .g
} -cleanup {
    destroy .f .g
    deleteWindows
} -result {}
} -result .g

destroy .f
frame .f
test frame-1.13 {frame configuration options} -body {
    .f configure -background #ff0000
    lindex [.f configure -background] 4
} -cleanup {
    .f configure -background [lindex [.f configure -background] 3]
} -result {#ff0000}
} -result "#ff0000"
test frame-1.14 {frame configuration options} -body {
    .f configure -background non-existent
} -returnCodes error -result {unknown color name "non-existent"}
test frame-1.15 {frame configuration options} -body {
    .f configure -bd 4
    lindex [.f configure -bd] 4
} -cleanup {
    .f configure -bd [lindex [.f configure -bd] 3]
} -result {4}
} -result 4
test frame-1.16 {frame configuration options} -body {
    .f configure -bd badValue
} -returnCodes error -result {bad screen distance "badValue"}
test frame-1.17 {frame configuration options} -body {
    .f configure -bg #00ff00
    lindex [.f configure -bg] 4
} -cleanup {
    .f configure -bg [lindex [.f configure -bg] 3]
} -result {#00ff00}
} -result "#00ff00"
test frame-1.18 {frame configuration options} -body {
    .f configure -bg non-existent
} -returnCodes error -result {unknown color name "non-existent"}
test frame-1.19 {frame configuration options} -body {
    .f configure -borderwidth 1.3
    lindex [.f configure -borderwidth] 4
} -cleanup {
    .f configure -borderwidth [lindex [.f configure -borderwidth] 3]
} -result {1}
} -result 1
test frame-1.20 {frame configuration options} -body {
    .f configure -borderwidth badValue
} -returnCodes error -result {bad screen distance "badValue"}
test frame-1.21 {frame configuration options} -body {
    .f configure -cursor arrow
    lindex [.f configure -cursor] 4
} -cleanup {
    .f configure -cursor [lindex [.f configure -cursor] 3]
} -result {arrow}
test frame-1.22 {frame configuration options} -body {
    .f configure -cursor badValue
} -returnCodes error -result {bad cursor spec "badValue"}
test frame-1.23 {frame configuration options} -body {
    .f configure -height 100
    lindex [.f configure -height] 4
} -cleanup {
    .f configure -height [lindex [.f configure -height] 3]
} -result {100}
} -result 100
test frame-1.24 {frame configuration options} -body {
    .f configure -height not_a_number
} -returnCodes error -result {bad screen distance "not_a_number"}
test frame-1.25 {frame configuration options} -body {
    .f configure -highlightbackground #112233
    lindex [.f configure -highlightbackground] 4
} -cleanup {
    .f configure -highlightbackground [lindex [.f configure -highlightbackground] 3]
} -result {#112233}
} -result "#112233"
test frame-1.26 {frame configuration options} -body {
    .f configure -highlightbackground ugly
} -returnCodes error -result {unknown color name "ugly"}
test frame-1.27 {frame configuration options} -body {
    .f configure -highlightcolor #123456
    lindex [.f configure -highlightcolor] 4
} -cleanup {
    .f configure -highlightcolor [lindex [.f configure -highlightcolor] 3]
} -result {#123456}
} -result "#123456"
test frame-1.28 {frame configuration options} -body {
    .f configure -highlightcolor non-existent
} -returnCodes error -result {unknown color name "non-existent"}
test frame-1.29 {frame configuration options} -body {
    .f configure -highlightthickness 6
    lindex [.f configure -highlightthickness] 4
} -cleanup {
    .f configure -highlightthickness [lindex [.f configure -highlightthickness] 3]
} -result {6}
} -result 6
test frame-1.30 {frame configuration options} -body {
    .f configure -highlightthickness badValue
} -returnCodes error -result {bad screen distance "badValue"}
test frame-1.31 {frame configuration options} -body {
    .f configure -padx 3
    lindex [.f configure -padx] 4
} -cleanup {
    .f configure -padx [lindex [.f configure -padx] 3]
} -result {3}
} -result 3
test frame-1.32 {frame configuration options} -body {
    .f configure -padx badValue
} -returnCodes error -result {bad screen distance "badValue"}
test frame-1.33 {frame configuration options} -body {
    .f configure -pady 4
    lindex [.f configure -pady] 4
} -cleanup {
    .f configure -pady [lindex [.f configure -pady] 3]
} -result {4}
} -result 4
test frame-1.34 {frame configuration options} -body {
    .f configure -pady badValue
} -returnCodes error -result {bad screen distance "badValue"}
test frame-1.35 {frame configuration options} -body {
    .f configure -relief ridge
    lindex [.f configure -relief] 4
} -cleanup {
    .f configure -relief [lindex [.f configure -relief] 3]
} -result {ridge}
test frame-1.36 {frame configuration options} -body {
test frame-1.36 {frame configuration options} -returnCodes error -body {
    .f configure -relief badValue
} -returnCodes error -result {bad relief "badValue": must be flat, groove, raised, ridge, solid, or sunken}
} -result {bad relief "badValue": must be flat, groove, raised, ridge, solid, or sunken}
test frame-1.37 {frame configuration options} -body {
    .f configure -takefocus {any string}
    lindex [.f configure -takefocus] 4
} -cleanup {
    .f configure -takefocus [lindex [.f configure -takefocus] 3]
} -result {any string}
test frame-1.38 {frame configuration options} -body {
    .f configure -width 32
    lindex [.f configure -width] 4
} -cleanup {
    .f configure -width [lindex [.f configure -width] 3]
} -result {32}
} -result 32
test frame-1.39 {frame configuration options} -body {
    .f configure -width badValue
} -returnCodes error -result {bad screen distance "badValue"}
destroy .f


test frame-2.1 {toplevel configuration options} -setup {
	deleteWindows
    deleteWindows
} -body {
    toplevel .t -width 200 -height 100 -class NewClass
    wm geometry .t +0+0
    .t configure -class
} -cleanup {
    deleteWindows
} -result {-class class Class Toplevel NewClass}
test frame-2.2 {toplevel configuration options} -setup {
    deleteWindows
} -body {
    toplevel .t -width 200 -height 100 -class NewClass
    wm geometry .t +0+0
    .t configure -class Another
} -cleanup {
} -returnCodes error -cleanup {
    deleteWindows
} -returnCodes error -result {can't modify -class option after widget is created}
} -result {can't modify -class option after widget is created}

test frame-2.3 {toplevel configuration options} -setup {
	deleteWindows
    deleteWindows
} -body {
    toplevel .t -width 200 -height 100 -colormap new
    wm geometry .t +0+0
    .t configure -colormap
} -cleanup {
    deleteWindows
} -result {-colormap colormap Colormap {} new}
test frame-2.4 {toplevel configuration options} -setup {
    deleteWindows
} -body {
    toplevel .t -width 200 -height 100 -colormap new
    wm geometry .t +0+0
    .t configure -colormap .
} -cleanup {
} -returnCodes error -cleanup {
    deleteWindows
} -returnCodes error -result {can't modify -colormap option after widget is created}
} -result {can't modify -colormap option after widget is created}

test frame-2.5 {toplevel configuration options} -setup {
	deleteWindows
    deleteWindows
} -body {
    toplevel .t -width 200 -height 100
    wm geometry .t +0+0
    .t configure -container 1
} -cleanup {
} -returnCodes error -cleanup {
    deleteWindows
} -returnCodes error -result {can't modify -container option after widget is created}
} -result {can't modify -container option after widget is created}
test frame-2.6 {toplevel configuration options} -setup {
    deleteWindows
} -body {
    catch {destroy .t}
    toplevel .t -width 200 -height 100
    wm geometry .t +0+0
    catch {.t configure -container 1}
    .t configure -container
} -cleanup {
    deleteWindows
} -result {-container container Container 0 0}

test frame-2.7 {toplevel configuration options} -setup {
	deleteWindows
    deleteWindows
} -body {
    toplevel .t -width 200 -height 100 -colormap bogus
} -cleanup {
    deleteWindows
} -returnCodes error -result {bad window path name "bogus"}


test frame-2.8 {toplevel configuration options} -constraints {
test frame-2.8 {toplevel configuration options} -constraints win -setup {
    win
} -setup {
	deleteWindows
    deleteWindows
} -body {
    catch {destroy .t}
    toplevel .t -width 200 -height 100
    wm geometry .t +0+0
    .t configure -use 0x44022
} -cleanup {
    deleteWindows
} -returnCodes error -result {window "0x44022" doesn't exist}
test frame-2.9 {toplevel configuration options} -constraints {
    win
} -setup {
test frame-2.9 {toplevel configuration options} -constraints win -setup {
    deleteWindows
} -body {
    toplevel .t -width 200 -height 100
    wm geometry .t +0+0
    catch {.t configure -use 0x44022}
    .t configure -use
} -cleanup {
    deleteWindows
} -result {-use use Use {} {}}
test frame-2.10 {toplevel configuration options} -constraints nonwin -setup {
    deleteWindows
} -body {
    toplevel .t -width 200 -height 100
    catch {destroy .t}
    wm geometry .t +0+0
    .t configure -use 0x44022
} -cleanup {
    deleteWindows
} -returnCodes error -result {can't modify -use option after widget is created}
test frame-2.11 {toplevel configuration options} -constraints nonwin -setup {
    deleteWindows
} -body {
    toplevel .t -width 200 -height 100
    wm geometry .t +0+0
    catch {.t configure -use 0x44022}
    .t configure -use
} -cleanup {
    deleteWindows
} -result {-use use Use {} {}}

test frame-2.10 {toplevel configuration options} -constraints {
    nonwin
} -setup {
    deleteWindows
} -body {
    catch {destroy .t}
    toplevel .t -width 200 -height 100
    wm geometry .t +0+0
    .t configure -use 0x44022
} -cleanup {
    deleteWindows
} -returnCodes error -result {can't modify -use option after widget is created}
test frame-2.11 {toplevel configuration options} -constraints {
    nonwin
} -setup {
	deleteWindows
} -body {
    catch {destroy .t}
    toplevel .t -width 200 -height 100
    wm geometry .t +0+0
    catch {.t configure -use 0x44022}
    .t configure -use
} -cleanup {
    deleteWindows
} -result {-use use Use {} {}}

test frame-2.12 {toplevel configuration options} -setup {
	deleteWindows
    deleteWindows
} -body {
    catch {destroy .t}
    toplevel .t -width 200 -height 100 -visual default
    wm geometry .t +0+0
    .t configure -visual
} -cleanup {
    deleteWindows
} -result {-visual visual Visual {} default}
test frame-2.13 {toplevel configuration options} -setup {
    deleteWindows
} -body {
    catch {destroy .t}
    toplevel .t -width 200 -height 100 -visual default
    wm geometry .t +0+0
    .t configure -visual best
} -cleanup {
} -returnCodes error -cleanup {
    deleteWindows
} -returnCodes error -result {can't modify -visual option after widget is created}
} -result {can't modify -visual option after widget is created}

test frame-2.14 {toplevel configuration options} -setup {
	deleteWindows
    deleteWindows
} -body {
    toplevel .t -width 200 -height 100 -visual who_knows?
} -cleanup {
} -returnCodes error -cleanup {
    deleteWindows
} -returnCodes error -result {unknown or ambiguous visual name "who_knows?": class must be best, directcolor, grayscale, greyscale, pseudocolor, staticcolor, staticgray, staticgrey, truecolor, or default}
test frame-2.15 {toplevel configuration options} -constraints haveDISPLAY -setup {
	deleteWindows
} -result {unknown or ambiguous visual name "who_knows?": class must be best, directcolor, grayscale, greyscale, pseudocolor, staticcolor, staticgray, staticgrey, truecolor, or default}
set expectedScreen ""
if {[tcltest::testConstraint haveDISPLAY]} {
    set expectedScreen [list -screen screen Screen {} $env(DISPLAY)]
}
test frame-2.15 {toplevel configuration options} -constraints {x11 haveDISPLAY} -setup {
    deleteWindows
} -body {
    toplevel .t -width 200 -height 100 -screen $env(DISPLAY)
    wm geometry .t +0+0
    string compare [.t configure -screen] "-screen screen Screen {} $env(DISPLAY)"
    .t configure -screen
} -cleanup {
    deleteWindows
} -result {0}
test frame-2.16 {toplevel configuration options} -constraints haveDISPLAY -setup {
} -result $expectedScreen
test frame-2.16 {toplevel configuration options} -constraints {x11 haveDISPLAY} -setup {
    deleteWindows
} -body {
    toplevel .t -width 200 -height 100 -screen $env(DISPLAY)
    wm geometry .t +0+0
    .t configure -screen another
} -cleanup {
} -returnCodes error -cleanup {
    deleteWindows
} -returnCodes error -result {can't modify -screen option after widget is created}
} -result {can't modify -screen option after widget is created}

test frame-2.17 {toplevel configuration options} -setup {
	deleteWindows
    deleteWindows
} -body {
    toplevel .t -width 200 -height 100 -screen bogus
} -cleanup {
    deleteWindows
} -returnCodes error -result {couldn't connect to display "bogus"}
test frame-2.18 {toplevel configuration options} -setup {
	deleteWindows
    deleteWindows
} -body {
    toplevel .t -container 1 -width 300 -height 120
    wm geometry .t +0+0
    toplevel .x -container 1 -use [winfo id .t]
} -cleanup {
} -returnCodes error -cleanup {
    deleteWindows
} -returnCodes error -result {windows cannot have both the -use and the -container option set}
} -result {windows cannot have both the -use and the -container option set}
test frame-2.19 {toplevel configuration options} -setup {
	deleteWindows
    deleteWindows
    set opts {}
} -body {
    # Make sure all options can be set to the default value
    toplevel .f
    foreach opt [.f configure] {
        if {[llength $opt] == 5} {
            lappend opts [lindex $opt 0] [lindex $opt 4]
        }
    }
    eval toplevel .g $opts
    toplevel .g {*}$opts
    destroy .f .g
} -cleanup {
    destroy .f .g
    deleteWindows
} -result {}
} -result .g


destroy .t
toplevel .t -width 300 -height 150
wm geometry .t +0+0
update
test frame-2.20 {toplevel configuration options} -body {
    .t configure -background #ff0000
    lindex [.t configure -background] 4
} -result {#ff0000}
} -result "#ff0000"
test frame-2.21 {toplevel configuration options} -body {
    .t configure -background non-existent
} -returnCodes error -result {unknown color name "non-existent"}
test frame-2.22 {toplevel configuration options} -body {
    .t configure -bd 4
    lindex [.t configure -bd] 4
} -result {4}
} -result 4
test frame-2.23 {toplevel configuration options} -body {
    .t configure -bd badValue
} -returnCodes error -result {bad screen distance "badValue"}
test frame-2.24 {toplevel configuration options} -body {
    .t configure -bg #00ff00
    lindex [.t configure -bg] 4
} -result {#00ff00}
} -result "#00ff00"
test frame-2.25 {toplevel configuration options} -body {
    .t configure -bg non-existent
} -returnCodes error -result {unknown color name "non-existent"}
test frame-2.26 {toplevel configuration options} -body {
    .t configure -borderwidth 1.3
    lindex [.t configure -borderwidth] 4
} -result {1}
} -result 1
test frame-2.27 {toplevel configuration options} -body {
    .t configure -borderwidth badValue
} -returnCodes error -result {bad screen distance "badValue"}
test frame-2.28 {toplevel configuration options} -body {
    .t configure -cursor arrow
    lindex [.t configure -cursor] 4
} -result {arrow}
test frame-2.29 {toplevel configuration options} -body {
    .t configure -cursor badValue
} -returnCodes error -result {bad cursor spec "badValue"}
test frame-2.30 {toplevel configuration options} -body {
    .t configure -height 100
    lindex [.t configure -height] 4
} -result {100}
} -result 100
test frame-2.31 {toplevel configuration options} -body {
    .t configure -height not_a_number
} -returnCodes error -result {bad screen distance "not_a_number"}
test frame-2.32 {toplevel configuration options} -body {
    .t configure -highlightcolor #123456
    lindex [.t configure -highlightcolor] 4
} -result {#123456}
} -result "#123456"
test frame-2.33 {toplevel configuration options} -body {
    .t configure -highlightcolor non-existent
} -returnCodes error -result {unknown color name "non-existent"}
test frame-2.34 {toplevel configuration options} -body {
    .t configure -highlightthickness 3
    lindex [.t configure -highlightthickness] 4
} -result {3}
} -result 3
test frame-2.35 {toplevel configuration options} -body {
    .t configure -highlightthickness badValue
} -returnCodes error -result {bad screen distance "badValue"}
test frame-2.36 {toplevel configuration options} -body {
    .t configure -padx 3
    lindex [.t configure -padx] 4
} -result {3}
} -result 3
test frame-2.37 {toplevel configuration options} -body {
    .t configure -padx badValue
} -returnCodes error -result {bad screen distance "badValue"}
test frame-2.38 {toplevel configuration options} -body {
    .t configure -pady 4
    lindex [.t configure -pady] 4
} -result {4}
} -result 4
test frame-2.39 {toplevel configuration options} -body {
    .t configure -pady badValue
} -returnCodes error -result {bad screen distance "badValue"}
test frame-2.40 {toplevel configuration options} -body {
    .t configure -relief ridge
    lindex [.t configure -relief] 4
} -result {ridge}
test frame-2.41 {toplevel configuration options} -body {
test frame-2.41 {toplevel configuration options} -returnCodes error -body {
    .t configure -relief badValue
} -returnCodes error -result {bad relief "badValue": must be flat, groove, raised, ridge, solid, or sunken}
} -result {bad relief "badValue": must be flat, groove, raised, ridge, solid, or sunken}
test frame-2.42 {toplevel configuration options} -body {
    .t configure -width 32
    lindex [.t configure -width] 4
} -result {32}
} -result 32
test frame-2.43 {toplevel configuration options} -body {
    .t configure -width badValue
} -returnCodes error -result {bad screen distance "badValue"}
destroy .t


test frame-3.1 {TkCreateFrame procedure} -body {
test frame-3.1 {TkCreateFrame procedure} -returnCodes error -body {
    frame
} -returnCodes error -result {wrong # args: should be "frame pathName ?-option value ...?"}
} -result {wrong # args: should be "frame pathName ?-option value ...?"}
test frame-3.2 {TkCreateFrame procedure} -setup {
	deleteWindows
    deleteWindows
    frame .f
} -body {
    .f configure -class
} -cleanup {
    deleteWindows
} -result {-class class Class Frame Frame}
test frame-3.3 {TkCreateFrame procedure} -setup {
	deleteWindows
    deleteWindows
    toplevel .t
    wm geometry .t +0+0
} -body {
    .t configure -class
} -cleanup {
    deleteWindows
} -result {-class class Class Toplevel Toplevel}
test frame-3.4 {TkCreateFrame procedure} -setup {
	deleteWindows
    deleteWindows
} -body {
    toplevel .t -width 350 -class NewClass -bg black -visual default -height 90
    wm geometry .t +0+0
    update
    list [lindex [.t configure -width] 4] \
	    [lindex [.t configure -background] 4] \
	    [lindex [.t configure -height] 4]
} -cleanup {
    deleteWindows
} -result {350 black 90}

# Be sure that the -class, -colormap, and -visual options are processed
# before configuring the widget.
test frame-3.5 {TkCreateFrame procedure} -setup {
	deleteWindows
    deleteWindows
} -body {
    option add *NewFrame.background #123456
    frame .f -class NewFrame
    lindex [.f configure -background] 4
} -cleanup {
    deleteWindows
    option clear
} -result {#123456}
test frame-3.7 {TkCreateFrame procedure} -setup {
	deleteWindows
    deleteWindows
} -body {
    option add *NewFrame.background #332211
    option add *f.class NewFrame
    frame .f
    list [lindex [.f configure -class] 4] [lindex [.f configure -background] 4]
} -cleanup {
    deleteWindows
    option clear
} -result {NewFrame #332211}
test frame-3.8 {TkCreateFrame procedure} -setup {
	deleteWindows
    deleteWindows
} -body {
    option add *Silly.background #122334
    option add *f.Class Silly
    frame .f
    list [lindex [.f configure -class] 4] [lindex [.f configure -background] 4]
} -cleanup {
    deleteWindows
    option clear
} -result {Silly #122334}
test frame-3.9 {TkCreateFrame procedure, -use option} -constraints {
    unix
} -setup {
	deleteWindows
    deleteWindows
} -body {
    toplevel .t -container 1 -width 300 -height 120
    wm geometry .t +0+0
    toplevel .x -width 140 -height 300 -use [winfo id .t] -bg green
    tkwait visibility .x
    list [expr {[winfo rootx .x] - [winfo rootx .t]}] \
	    [expr {[winfo rooty .x] - [winfo rooty .t]}] \
	    [winfo width .t] [winfo height .t]
} -cleanup {
# This call to update idletasks was added to prevent a crash that was
# observed on OSX 10.12 (Sierra) only.  Any change, such as using the
# Development version to make debugging symbols available, adding a print
# statement, or calling update idletasks here, would make the test pass
# with no segfault.
    # This call to update idletasks was added to prevent a crash that was
    # observed on OSX 10.12 (Sierra) only.  Any change, such as using the
    # Development version to make debugging symbols available, adding a print
    # statement, or calling update idletasks here, would make the test pass
    # with no segfault.
    update idletasks
    deleteWindows
} -result {0 0 140 300}
test frame-3.10 {TkCreateFrame procedure, -use option} -constraints {
    unix
} -setup {
    deleteWindows
} -body {
    toplevel .t -container 1 -width 300 -height 120
    wm geometry .t +0+0
    if {[tk windowingsystem] eq "aqua"} {
	update idletasks
    option add *x.use [winfo id .t]
    update
    } else {
	update
    }
    option add *x.use [winfo id .t]
    toplevel .x -width 140 -height 300 -bg green
    if {[tk windowingsystem] eq "aqua"} {
	update idletasks
    } else {
    tkwait visibility .x
    update
	tkwait visibility .x
	update
    }
    list [expr {[winfo rootx .x] - [winfo rootx .t]}] \
	    [expr {[winfo rooty .x] - [winfo rooty .t]}] \
	    [winfo width .t] [winfo height .t]
} -cleanup {
    destroy .t
    option clear
} -result {0 0 140 300}

# The tests below require specific display characteristics (i.e. that
# they are run on a pseudocolor display of depth 8).  Even so, they
# are non-portable: some machines don't seem to ever run out of
# The tests below require specific display characteristics (i.e. that they are
# run on a pseudocolor display of depth 8).  Even so, they are non-portable:
# some machines don't seem to ever run out of colors.
# colors.
if {[testConstraint defaultPseudocolor8]} {
    eatColors .t1
}
test frame-3.11 {TkCreateFrame procedure} -constraints {
	defaultPseudocolor8 nonPortable
    defaultPseudocolor8 nonPortable
} -setup {
	deleteWindows
    destroy .t
} -body {
    toplevel .t -width 300 -height 200 -bg #475601
    wm geometry .t +0+0
    update
    colorsFree .t
} -cleanup {
    deleteWindows
} -result {0}
    destroy .t
} -result 0
test frame-3.12 {TkCreateFrame procedure} -constraints {
	defaultPseudocolor8 nonPortable
    defaultPseudocolor8 nonPortable
} -setup {
	deleteWindows
    destroy .t
} -body {
    toplevel .t -width 300 -height 200 -bg #475601 -colormap new
    wm geometry .t +0+0
    update
    colorsFree .t
} -cleanup {
    deleteWindows
} -result {1}
    destroy .t
} -result 1
test frame-3.13 {TkCreateFrame procedure} -constraints {
	defaultPseudocolor8 nonPortable
    defaultPseudocolor8 nonPortable
} -setup {
	deleteWindows
    destroy .t
} -body {
    option add *t.class Toplevel2
    option add *Toplevel2.colormap new
    toplevel .t -width 300 -height 200 -bg #475601
    wm geometry .t +0+0
    update
    option clear
    colorsFree .t
} -cleanup {
    deleteWindows
} -result {1}
    destroy .t
} -result 1
test frame-3.14 {TkCreateFrame procedure} -constraints {
	defaultPseudocolor8 nonPortable
    defaultPseudocolor8 nonPortable
} -setup {
	deleteWindows
    destroy .t
} -body {
    option add *t.class Toplevel3
    option add *Toplevel3.Colormap new
    toplevel .t -width 300 -height 200 -bg #475601 -colormap new
    wm geometry .t +0+0
    update
    option clear
    colorsFree .t
} -cleanup {
    deleteWindows
} -result {1}
    destroy .t
} -result 1
test frame-3.15 {TkCreateFrame procedure, -use and -colormap} -constraints {
    defaultPseudocolor8 unix nonPortable
} -setup {
    deleteWindows
    destroy .t
} -body {
    toplevel .t -container 1 -width 300 -height 120
    wm geometry .t +0+0
    toplevel .x -width 140 -height 300 -use [winfo id .t] -bg green -colormap new
    tkwait visibility .x
    list [colorsFree .t] [colorsFree .x]
} -cleanup {
    destroy .t
} -result {0 1}
test frame-3.16 {TkCreateFrame procedure} -constraints {
	defaultPseudocolor8 nonPortable
    defaultPseudocolor8 nonPortable
} -setup {
	deleteWindows
    destroy .t
} -body {
    toplevel .t -width 300 -height 200 -bg #475601 -visual default
    wm geometry .t +0+0
    update
    colorsFree .t
} -cleanup {
    deleteWindows
} -result {0}
    destroy .t
} -result 0
test frame-3.17 {TkCreateFrame procedure} -constraints {
	defaultPseudocolor8 nonPortable
    defaultPseudocolor8 nonPortable
} -setup {
	deleteWindows
    destroy .t
} -body {
    toplevel .t -width 300 -height 200 -bg #475601 -visual default \
	    -colormap new
    wm geometry .t +0+0
    update
    colorsFree .t
} -cleanup {
    deleteWindows
} -result {1}
    destroy .t
} -result 1
test frame-3.18 {TkCreateFrame procedure} -constraints {
	defaultPseudocolor8 haveGrayscale8 nonPortable
    defaultPseudocolor8 haveGrayscale8 nonPortable
} -setup {
	deleteWindows
    destroy .t
} -body {
    toplevel .t -visual {grayscale 8} -width 300 -height 200 -bg #434343
    wm geometry .t +0+0
    update
    colorsFree .t 131 131 131
} -cleanup {
    deleteWindows
} -result {1}
    destroy .t
} -result 1
test frame-3.19 {TkCreateFrame procedure} -constraints {
	defaultPseudocolor8 haveGrayscale8 nonPortable
    defaultPseudocolor8 haveGrayscale8 nonPortable
} -setup {
	deleteWindows
    destroy .t
} -body {
    option add *t.class T4
    option add *T4.visual {grayscale 8}
    toplevel .t -width 300 -height 200 -bg #434343
    wm geometry .t +0+0
    update
    option clear
    list [colorsFree .t 131 131 131] [lindex [.t configure -visual] 4]
} -cleanup {
    deleteWindows
    destroy .t
} -result {1 {grayscale 8}}
test frame-3.20 {TkCreateFrame procedure} -constraints {
	defaultPseudocolor8 haveGrayscale8 nonPortable
    defaultPseudocolor8 haveGrayscale8 nonPortable
} -setup {
	deleteWindows
    destroy .t
} -body {
    set x ok
    option add *t.class T5
    option add *T5.Visual {grayscale 8}
    toplevel .t -width 300 -height 200 -bg #434343
    wm geometry .t +0+0
    update
    option clear
    list [colorsFree .t 131 131 131] [lindex [.t configure -visual] 4]
} -cleanup {
    deleteWindows
    destroy .t
} -result {1 {grayscale 8}}
test frame-3.21 {TkCreateFrame procedure} -constraints {
	defaultPseudocolor8 haveGrayscale8 nonPortable
    defaultPseudocolor8 haveGrayscale8 nonPortable
} -setup {
	deleteWindows
    destroy .t
} -body {
    set x ok
    toplevel .t -visual {grayscale 8} -width 300 -height 200 -bg #434343
    wm geometry .t +0+0
    update
    colorsFree .t 131 131 131
} -cleanup {
    deleteWindows
} -result {1}
    destroy .t
} -result 1
if {[testConstraint defaultPseudocolor8]} {
    destroy .t1
}

test frame-3.22 {TkCreateFrame procedure, default dimensions} -setup {
	deleteWindows
    deleteWindows
} -body {
    toplevel .t
    wm geometry .t +0+0
    update
    set result "[winfo reqwidth .t] [winfo reqheight .t]"
    frame .t.f -bg red
    pack .t.f
867
868
869
870
871
872
873
874
875
876

877
878
879
880
881
882

883
884
885
886
887
888
889
890
891
892
893
894
895
867
868
869
870
871
872
873

874

875
876
877
878
879
880

881
882
883
884
885
886

887
888
889
890
891
892
893







-

-
+





-
+





-







test frame-3.24 {TkCreateFrame procedure} -setup {
    deleteWindows
} -body {
    toplevel .t -width 300 -height 200 -colormap new -bogus option
    wm geometry .t +0+0
} -returnCodes error -result {unknown option "-bogus"}


test frame-4.1 {TkCreateFrame procedure} -setup {
	deleteWindows
    deleteWindows
} -body {
    catch {frame .f -gorp glob}
    winfo exists .f
} -result 0
test frame-4.2 {TkCreateFrame procedure} -setup {
	deleteWindows
    deleteWindows
} -body {
    list [frame .f -width 200 -height 100] [winfo exists .f]
} -cleanup {
    deleteWindows
} -result {.f 1}


frame .f -highlightcolor black
test frame-5.1 {FrameWidgetCommand procedure} -body {
    .f
} -returnCodes error -result {wrong # args: should be ".f option ?arg ...?"}
test frame-5.2 {FrameWidgetCommand procedure, cget option} -body {
    .f cget
910
911
912
913
914
915
916
917
918
919
920


921
922
923
924
925
926
927
928
929
930
931
932
933
934
935


936
937
938
939

940
941
942
943
944
945
946
947

948
949
950
951
952
953
954
955

956
957
958
959
960
961
962
963
964
965
966
967
968
969

970
971
972
973
974
975
976
977

978
979
980
981
982
983
984
985
986
987
988
989
990
991

992
993
994
995
996
997
998
999
1000

1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031

1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042

1043
1044
1045
1046
1047
1048
1049

1050
1051

1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065

1066
1067
1068
1069

1070
1071
1072
1073
1074
1075

1076
1077
1078

1079
1080
1081
1082

1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093

1094
1095

1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108

1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120

1121
1122
1123
1124
1125
1126
1127


1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149




1150
1151
1152
1153
1154
1155
1156


1157
1158
1159
1160
1161
1162



1163


1164
1165
1166



1167


1168
1169
1170
1171
1172
1173
1174

1175
1176
1177
1178

1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190

1191
1192

1193
1194

1195
1196
1197
1198
1199
1200
1201

1202
1203
1204
1205
1206
1207
1208

1209
1210
1211
1212
1213
1214
1215

1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230

1231
1232
1233
1234
1235
1236
1237

1238
1239
1240
1241

1242
1243

1244
1245
1246
1247
1248
1249
1250
1251
1252

1253
1254

1255
1256
1257
1258
1259
1260
1261

1262
1263

1264
1265
1266
1267
1268
1269
1270

1271
1272

1273
1274
1275
1276
1277
1278
1279

1280
1281

1282
1283
1284
1285
1286
1287
1288
1289
1290

1291
1292
1293
1294
1295
1296
1297

1298
1299

1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312

1313
1314

1315
1316
1317
1318
1319
1320
1321

1322
1323

1324
1325
1326
1327
1328
1329
1330

1331
1332

1333
1334
1335
1336
1337
1338
1339

1340
1341

1342
1343
1344
1345
1346
1347
1348

1349
1350

1351
1352
1353
1354
1355
1356
1357
1358
1359
1360



1361
1362
1363
1364
1365
1366

1367
1368

1369
1370
1371
1372
1373
1374
1375

1376
1377

1378
1379
1380
1381
1382
1383
1384
1385
1386
1387



1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405

1406
1407

1408
1409
1410
1411
1412
1413

1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428

1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447

1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466

1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480

1481
1482
1483
1484
1485
1486
1487
908
909
910
911
912
913
914

915


916
917
918
919
920
921
922
923
924
925
926
927
928
929
930


931
932
933
934
935

936
937
938
939
940
941
942
943

944
945
946
947
948
949
950
951

952
953
954
955
956
957
958
959
960
961
962
963
964
965

966
967
968
969
970
971
972
973

974
975
976
977
978
979
980
981
982
983
984
985
986
987

988
989
990
991
992
993
994
995
996

997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011

1012
1013
1014
1015
1016
1017
1018
1019
1020
1021

1022
1023
1024
1025

1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036

1037
1038
1039
1040
1041
1042
1043

1044
1045

1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059

1060
1061

1062

1063
1064

1065
1066
1067

1068



1069
1070

1071

1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082

1083

1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095

1096

1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108

1109
1110
1111
1112
1113
1114


1115
1116


1117
1118

1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132



1133
1134
1135
1136
1137
1138
1139
1140
1141
1142

1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153

1154
1155
1156
1157
1158
1159
1160
1161

1162
1163
1164
1165
1166
1167
1168
1169

1170
1171

1172

1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184

1185
1186

1187
1188

1189
1190
1191
1192
1193
1194
1195

1196
1197
1198
1199
1200
1201
1202

1203
1204
1205
1206
1207
1208
1209

1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224

1225
1226
1227
1228
1229
1230
1231

1232
1233
1234
1235

1236
1237

1238

1239
1240
1241
1242
1243
1244
1245

1246
1247

1248
1249
1250
1251
1252
1253
1254

1255
1256

1257
1258
1259
1260
1261
1262
1263

1264
1265

1266
1267
1268
1269
1270
1271
1272

1273
1274

1275
1276
1277
1278
1279
1280
1281
1282
1283

1284
1285
1286
1287
1288
1289
1290

1291
1292

1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305

1306
1307

1308
1309
1310
1311
1312
1313
1314

1315
1316

1317
1318
1319
1320
1321
1322
1323

1324
1325

1326
1327
1328
1329
1330
1331
1332

1333
1334

1335
1336
1337
1338
1339
1340
1341

1342
1343

1344
1345
1346
1347
1348
1349
1350
1351



1352
1353
1354
1355
1356
1357
1358
1359

1360
1361

1362
1363
1364
1365
1366
1367
1368

1369
1370

1371
1372
1373
1374
1375
1376
1377
1378



1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398

1399
1400

1401
1402
1403
1404

1405

1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420

1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439

1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458

1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472

1473
1474
1475
1476
1477
1478
1479
1480







-

-
-
+
+













-
-
+
+



-
+







-
+







-
+













-
+







-
+













-
+








-
+














-










-




-
+










-
+






-
+

-
+













-
+

-

-
+

-



-
+
-
-
-
+

-

-
+










-
+
-

+










-

-
+











-
+





-
-
+
+
-
-


-














-
-
-
+
+
+
+






-
+
+






+
+
+
-
+
+



+
+
+
-
+
+






-
+

-

-
+











-
+

-
+

-
+






-
+






-
+






-
+














-
+






-
+



-
+

-
+
-







-
+

-
+






-
+

-
+






-
+

-
+






-
+

-
+








-
+






-
+

-
+












-
+

-
+






-
+

-
+






-
+

-
+






-
+

-
+






-
+

-
+







-
-
-
+
+
+





-
+

-
+






-
+

-
+







-
-
-
+
+
+

















-
+

-
+



-

-
+














-
+


















-
+


















-
+













-
+







    destroy .t
} -body {
    toplevel .t
    .t cget -screen
} -cleanup {
    destroy .t
} -returnCodes ok -match glob -result *

test frame-5.8 {FrameWidgetCommand procedure, configure option} -body {
    llength [.f configure]
} -result {18}
    optnames [.f configure]
} -result {-background -backgroundimage -bd -bg -bgimg -borderwidth -class -colormap -container -cursor -height -highlightbackground -highlightcolor -highlightthickness -padx -pady -relief -takefocus -tile -visual -width}
test frame-5.9 {FrameWidgetCommand procedure, configure option} -body {
    .f configure -gorp
} -returnCodes error -result {unknown option "-gorp"}
test frame-5.10 {FrameWidgetCommand procedure, configure option} -body {
    .f configure -gorp bogus
} -returnCodes error -result {unknown option "-gorp"}
test frame-5.11 {FrameWidgetCommand procedure, configure option} -body {
    .f configure -width 200 -height
} -returnCodes error -result {value for "-height" missing}
test frame-5.12 {FrameWidgetCommand procedure} -body {
    .f swizzle
} -returnCodes error -result {bad option "swizzle": must be cget or configure}
test frame-5.13 {FrameWidgetCommand procedure, configure option} -body {
    llength [. configure]
} -result {21}
    optnames [. configure]
} -result {-background -backgroundimage -bd -bg -bgimg -borderwidth -class -colormap -container -cursor -height -highlightbackground -highlightcolor -highlightthickness -menu -padx -pady -relief -screen -takefocus -tile -use -visual -width}
destroy .f

test frame-6.1 {ConfigureFrame procedure} -setup {
	deleteWindows
    deleteWindows
} -body {
    frame .f -width 150
    list [winfo reqwidth .f] [winfo reqheight .f]
} -cleanup {
    deleteWindows
} -result {150 1}
test frame-6.2 {ConfigureFrame procedure} -setup {
	deleteWindows
    deleteWindows
} -body {
    frame .f -height 97
    list [winfo reqwidth .f] [winfo reqheight .f]
} -cleanup {
    deleteWindows
} -result {1 97}
test frame-6.3 {ConfigureFrame procedure} -setup {
	deleteWindows
    deleteWindows
} -body {
    frame .f
    set result {}
    lappend result [winfo reqwidth .f] [winfo reqheight .f]
    .f configure -width 100 -height 180
    lappend result [winfo reqwidth .f] [winfo reqheight .f]
    .f configure -width 0 -height 0
    lappend result [winfo reqwidth .f] [winfo reqheight .f]
} -cleanup {
    deleteWindows
} -result {1 1 100 180 100 180}

test frame-7.1 {FrameEventProc procedure} -setup {
	deleteWindows
    deleteWindows
} -body {
    frame .frame2
    set result [info commands .frame2]
    destroy .frame2
    lappend result [info commands .frame2]
} -result {.frame2 {}}
test frame-7.2 {FrameEventProc procedure} -setup {
	deleteWindows
    deleteWindows
    set x {}
} -body {
    frame .f1 -bg #543210
    rename .f1 .f2
    lappend x [winfo children .]
    lappend x [.f2 cget -bg]
    destroy .f1
    lappend x [info command .f*] [winfo children .]
} -cleanup {
    deleteWindows
} -result {.f1 #543210 {} {}}

test frame-8.1 {FrameCmdDeletedProc procedure} -setup {
	deleteWindows
    deleteWindows
} -body {
    frame .f1
    rename .f1 {}
    list [info command .f*] [winfo children .]
} -cleanup {
    deleteWindows
} -result {{} {}}
test frame-8.2 {FrameCmdDeletedProc procedure} -setup {
	deleteWindows
    deleteWindows
} -body {
    toplevel .f1 -menu .m
    wm geometry .f1 +0+0
    update
    rename .f1 {}
    update
    list [info command .f*] [winfo children .]
} -cleanup {
    deleteWindows
} -result {{} {}}
#
# This one fails with the dash-patch!!!! Still don't know why  :-(
#
#test frame-8.3 {FrameCmdDeletedProc procedure} -setup {
#    eval destroy [winfo children .]
#    deleteWindows
#} -body {
#    toplevel .f1 -menu .m
#    wm geometry .f1 +0+0
#    menu .m
#    update
#    rename .f1 {}
#    update
#    list [info command .f*] [winfo children .]
#} -cleanup {
#    eval destroy [winfo children .]
#    deleteWindows
#} -result {{} .m}

test frame-9.1 {MapFrame procedure} -setup {
	deleteWindows
    deleteWindows
} -body {
    toplevel .t -width 100 -height 400
    wm geometry .t +0+0
    set result [winfo ismapped .t]
    update idletasks
    lappend result [winfo ismapped .t]
} -cleanup {
    deleteWindows
} -result {0 1}
test frame-9.2 {MapFrame procedure} -setup {
	deleteWindows
    deleteWindows
} -body {
    toplevel .t -width 100 -height 400
    wm geometry .t +0+0
    destroy .t
    update
    winfo exists .t
} -result {0}
} -result 0
test frame-9.3 {MapFrame procedure, window deleted while mapping} -setup {
	deleteWindows
    deleteWindows
} -body {
    toplevel .t2 -width 200 -height 200
    wm geometry .t2 +0+0
    tkwait visibility .t2
    toplevel .t -width 100 -height 400
    wm geometry .t +0+0
    frame .t2.f -width 50 -height 50
    bind .t2.f <Configure> {destroy .t}
    pack .t2.f -side top
    update idletasks
    winfo exists .t
} -cleanup {
    deleteWindows
} -result {0}
} -result 0


test frame-10.1 {frame widget vs hidden commands} -setup {
	deleteWindows
    deleteWindows
} -body {
    set l [interp hidden]
    frame .t
    interp hide {} .t
    destroy .t
    set res1 [list [winfo children .] [interp hidden]]
    list [winfo children .] [lsort [interp hidden]]
    set res2 [list {} $l]
    expr {$res1 eq $res2}
} -result 1
} -result [list {} [lsort [interp hidden]]]


test frame-11.1 {TkInstallFrameMenu} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 add cascade -menu .m1.system
    menu .m1.system -tearoff 0
    .m1.system add command -label foo
    toplevel .t -menu .m1
} -cleanup {
    deleteWindows
} -result {.t}
test frame-11.2 {TkInstallFrameMenu - frame renamed} -setup {
	deleteWindows
    deleteWindows
} -body {
    catch {rename foo {}}
} -body {
    menu .m1
    .m1 add cascade -menu .m1.system
    menu .m1.system -tearoff 0
    .m1.system add command -label foo
    toplevel .t
    rename .t foo
} -cleanup {
    deleteWindows
} -result {}


test frame-12.1 {FrameWorldChanged procedure} -setup {
	deleteWindows
    deleteWindows
} -body {
    # Test -bd -padx and -pady
    frame .f -borderwidth 2 -padx 3 -pady 4
    place .f -x 0 -y 0 -width 40 -height 40
    pack [frame .f.f] -fill both -expand 1
    update
    list [winfo x .f.f] [winfo y .f.f] [winfo width .f.f] [winfo height .f.f]
} -cleanup {
    deleteWindows
} -result {5 6 30 28}
test frame-12.2 {FrameWorldChanged procedure} -setup {
	deleteWindows
    deleteWindows
} -body {
    # Test all -labelanchor positions
    set font {helvetica 12}
    labelframe .f -highlightthickness 1 -bd 3 -padx 1 -pady 2 -font $font \
            -text "Mupp"
    set fh [expr {[font metrics $font -linespace] + 2 - 3}]
    set fw [expr {[font measure $font "Mupp"] + 2 - 3}]
    set fh [expr {max([font metrics $font -linespace] + 2 - 3, 0)}]
    set fw [expr {max([font measure $font "Mupp"] + 2 - 3, 0)}]
    if {$fw < 0} {set fw 0}
    if {$fh < 0} {set fh 0}
    place .f -x 0 -y 0 -width 100 -height 100
    pack [frame .f.f] -fill both -expand 1

    set result {}
    foreach lp {nw n ne en e es se s sw ws w wn} {
        .f configure -labelanchor $lp
        update
        set expx 5
        set expy 6
        set expw 90
        set exph 88
        switch -glob $lp {
            n* {incr expy $fh ; incr exph -$fh}
            s* {incr exph -$fh}
            w* {incr expx $fw ; incr expw -$fw}
            e* {incr expw -$fw}
        }
        lappend result [expr {\
                [winfo x .f.f] == $expx && [winfo y .f.f] == $expy &&\
                [winfo width .f.f] == $expw && [winfo height .f.f] == $exph}]
        lappend result [expr {
	    [winfo x .f.f] == $expx && [winfo y .f.f] == $expy &&
	    [winfo width .f.f] == $expw && [winfo height .f.f] == $exph
	}]
    }
    return $result
} -cleanup {
    deleteWindows
} -result {1 1 1 1 1 1 1 1 1 1 1 1}
test frame-12.3 {FrameWorldChanged procedure} -setup {
	deleteWindows
    deleteWindows
	update idletasks
} -body {
    # Check reaction on font change
    font create myfont -family courier -size 10
    labelframe .f -font myfont -text Mupp
    place .f -x 0 -y 0 -width 40 -height 40
    pack [frame .f.f] -fill both -expand 1
    if {[tk windowingsystem] eq "aqua"} {
	update idletasks
    } else {
    update
	update
    }
    set h1 [font metrics myfont -linespace]
    set y1 [winfo y .f.f]
    font configure myfont -size 20
    if {[tk windowingsystem] eq "aqua"} {
	update idletasks
    } else {
    update
	update
    }
    set h2 [font metrics myfont -linespace]
    set y2 [winfo y .f.f]
    expr {($h2 - $h1) - ($y2 - $y1)}
} -cleanup {
    deleteWindows
    font delete myfont
} -result {0}
} -result 0


test frame-13.1 {labelframe configuration options} -setup {
	deleteWindows
    deleteWindows
} -body {
    labelframe .f -class NewFrame
    .f configure -class
} -cleanup {
    deleteWindows
} -result {-class class Class Labelframe NewFrame}
test frame-13.2 {labelframe configuration options} -setup {
    deleteWindows
} -body {
    labelframe .f -class NewFrame
    .f configure -class Different
} -cleanup {
} -returnCodes error -cleanup {
    deleteWindows
} -returnCodes error -result {can't modify -class option after widget is created}
} -result {can't modify -class option after widget is created}
test frame-13.3 {labelframe configuration options} -setup {
	deleteWindows
    deleteWindows
} -body {
    labelframe .f -colormap new
} -cleanup {
    deleteWindows
} -result {.f}
test frame-13.4 {labelframe configuration options} -setup {
	deleteWindows
    deleteWindows
} -body {
    labelframe .f -visual default
} -cleanup {
    deleteWindows
} -result {.f}
test frame-13.5 {labelframe configuration options} -setup {
	deleteWindows
    deleteWindows
} -body {
    labelframe .f -screen bogus
} -cleanup {
    deleteWindows
} -returnCodes error -result {unknown option "-screen"}
test frame-13.6 {labelframe configuration options} -setup {
	deleteWindows
    deleteWindows
} -body {
    labelframe .f -container true
} -cleanup {
    deleteWindows
} -result {.f}
test frame-13.7 {labelframe configuration options} -setup {
    deleteWindows
} -body {
    labelframe .f -container true
    .f configure -container
} -cleanup {
    deleteWindows
} -result {-container container Container 0 1}
test frame-13.8 {labelframe configuration options} -setup {
	deleteWindows
    deleteWindows
} -body {
     labelframe .f -container bogus
} -cleanup {
    deleteWindows
} -returnCodes error -result {expected boolean value but got "bogus"}
test frame-13.9 {labelframe configuration options} -setup {
	deleteWindows
    deleteWindows
} -body {
    labelframe .f
    .f configure -container 1
} -cleanup {
} -returnCodes error -cleanup {
    deleteWindows
} -returnCodes error -result {can't modify -container option after widget is created}
} -result {can't modify -container option after widget is created}

destroy .f
labelframe .f
test frame-13.10 {labelframe configuration options} -body {
    .f configure -background #ff0000
    lindex [.f configure -background] 4
} -cleanup {
    .f configure -background [lindex [.f configure -background] 3]
} -result {#ff0000}
} -result "#ff0000"
test frame-13.11 {labelframe configuration options} -body {
        .f configure -background non-existent
    .f configure -background non-existent
} -returnCodes error -result {unknown color name "non-existent"}
test frame-13.12 {labelframe configuration options} -body {
    .f configure -bd 4
    lindex [.f configure -bd] 4
} -cleanup {
    .f configure -bd [lindex [.f configure -bd] 3]
} -result {4}
} -result 4
test frame-13.13 {labelframe configuration options} -body {
        .f configure -bd badValue
    .f configure -bd badValue
} -returnCodes error -result {bad screen distance "badValue"}
test frame-13.14 {labelframe configuration options} -body {
    .f configure -bg #00ff00
    lindex [.f configure -bg] 4
} -cleanup {
    .f configure -bg [lindex [.f configure -bg] 3]
} -result {#00ff00}
} -result "#00ff00"
test frame-13.15 {labelframe configuration options} -body {
        .f configure -bg non-existent
    .f configure -bg non-existent
} -returnCodes error -result {unknown color name "non-existent"}
test frame-13.16 {labelframe configuration options} -body {
    .f configure -borderwidth 1.3
    lindex [.f configure -borderwidth] 4
} -cleanup {
    .f configure -borderwidth [lindex [.f configure -borderwidth] 3]
} -result {1}
} -result 1
test frame-13.17 {labelframe configuration options} -body {
        .f configure -borderwidth badValue
    .f configure -borderwidth badValue
} -returnCodes error -result {bad screen distance "badValue"}
test frame-13.18 {labelframe configuration options} -body {
    .f configure -cursor arrow
    lindex [.f configure -cursor] 4
} -cleanup {
    .f configure -cursor [lindex [.f configure -cursor] 3]
} -result {arrow}
test frame-13.19 {labelframe configuration options} -body {
        .f configure -cursor badValue
    .f configure -cursor badValue
} -returnCodes error -result {bad cursor spec "badValue"}
test frame-13.20 {labelframe configuration options} -body {
    .f configure -fg #0000ff
    lindex [.f configure -fg] 4
} -cleanup {
    .f configure -fg [lindex [.f configure -fg] 3]
} -result {#0000ff}
} -result "#0000ff"
test frame-13.21 {labelframe configuration options} -body {
        .f configure -fg non-existent
    .f configure -fg non-existent
} -returnCodes error -result {unknown color name "non-existent"}
test frame-13.22 {labelframe configuration options} -body {
    .f configure -font {courier 8}
    lindex [.f configure -font] 4
} -cleanup {
    .f configure -font [lindex [.f configure -font] 3]
} -result {courier 8}
test frame-13.23 {labelframe configuration options} -body {
    .f configure -foreground #ff0000
    lindex [.f configure -foreground] 4
} -cleanup {
    .f configure -foreground [lindex [.f configure -foreground] 3]
} -result {#ff0000}
} -result "#ff0000"
test frame-13.24 {labelframe configuration options} -body {
        .f configure -foreground non-existent
    .f configure -foreground non-existent
} -returnCodes error -result {unknown color name "non-existent"}
test frame-13.25 {labelframe configuration options} -body {
    .f configure -height 100
    lindex [.f configure -height] 4
} -cleanup {
    .f configure -height [lindex [.f configure -height] 3]
} -result {100}
} -result 100
test frame-13.26 {labelframe configuration options} -body {
        .f configure -height not_a_number
    .f configure -height not_a_number
} -returnCodes error -result {bad screen distance "not_a_number"}
test frame-13.27 {labelframe configuration options} -body {
    .f configure -highlightbackground #112233
    lindex [.f configure -highlightbackground] 4
} -cleanup {
    .f configure -highlightbackground [lindex [.f configure -highlightbackground] 3]
} -result {#112233}
} -result "#112233"
test frame-13.28 {labelframe configuration options} -body {
        .f configure -highlightbackground ugly
    .f configure -highlightbackground ugly
} -returnCodes error -result {unknown color name "ugly"}
test frame-13.29 {labelframe configuration options} -body {
    .f configure -highlightcolor #123456
    lindex [.f configure -highlightcolor] 4
} -cleanup {
    .f configure -highlightcolor [lindex [.f configure -highlightcolor] 3]
} -result {#123456}
} -result "#123456"
test frame-13.30 {labelframe configuration options} -body {
        .f configure -highlightcolor non-existent
    .f configure -highlightcolor non-existent
} -returnCodes error -result {unknown color name "non-existent"}
test frame-13.31 {labelframe configuration options} -body {
    .f configure -highlightthickness 6
    lindex [.f configure -highlightthickness] 4
} -cleanup {
    .f configure -highlightthickness [lindex [.f configure -highlightthickness] 3]
} -result {6}
} -result 6
test frame-13.32 {labelframe configuration options} -body {
        .f configure -highlightthickness badValue
    .f configure -highlightthickness badValue
} -returnCodes error -result {bad screen distance "badValue"}
test frame-13.33 {labelframe configuration options} -body {
    .f configure -labelanchor se
    lindex [.f configure -labelanchor] 4
} -cleanup {
    .f configure -labelanchor [lindex [.f configure -labelanchor] 3]
} -result {se}
test frame-13.34 {labelframe configuration options} -body {
        .f configure -labelanchor badValue
} -returnCodes error -result {bad labelanchor "badValue": must be e, en, es, n, ne, nw, s, se, sw, w, wn, or ws}
test frame-13.34 {labelframe configuration options} -returnCodes error -body {
    .f configure -labelanchor badValue
} -result {bad labelanchor "badValue": must be e, en, es, n, ne, nw, s, se, sw, w, wn, or ws}
test frame-13.35 {labelframe configuration options} -body {
    .f configure -padx 3
    lindex [.f configure -padx] 4
} -cleanup {
    .f configure -padx [lindex [.f configure -padx] 3]
} -result {3}
} -result 3
test frame-13.36 {labelframe configuration options} -body {
        .f configure -padx badValue
    .f configure -padx badValue
} -returnCodes error -result {bad screen distance "badValue"}
test frame-13.37 {labelframe configuration options} -body {
    .f configure -pady 4
    lindex [.f configure -pady] 4
} -cleanup {
    .f configure -pady [lindex [.f configure -pady] 3]
} -result {4}
} -result 4
test frame-13.38 {labelframe configuration options} -body {
        .f configure -pady badValue
    .f configure -pady badValue
} -returnCodes error -result {bad screen distance "badValue"}
test frame-13.39 {labelframe configuration options} -body {
    .f configure -relief ridge
    lindex [.f configure -relief] 4
} -cleanup {
    .f configure -relief [lindex [.f configure -relief] 3]
} -result {ridge}
test frame-13.40 {labelframe configuration options} -body {
        .f configure -relief badValue
} -returnCodes error -result {bad relief "badValue": must be flat, groove, raised, ridge, solid, or sunken}
test frame-13.40 {labelframe configuration options} -returnCodes error -body {
    .f configure -relief badValue
} -result {bad relief "badValue": must be flat, groove, raised, ridge, solid, or sunken}
test frame-13.41 {labelframe configuration options} -body {
    .f configure -takefocus {any string}
    lindex [.f configure -takefocus] 4
} -cleanup {
    .f configure -takefocus [lindex [.f configure -takefocus] 3]
} -result {any string}
test frame-13.42 {labelframe configuration options} -body {
    .f configure -text {any string}
    lindex [.f configure -text] 4
} -cleanup {
    .f configure -text [lindex [.f configure -text] 3]
} -result {any string}
test frame-13.43 {labelframe configuration options} -body {
    .f configure -width 32
    lindex [.f configure -width] 4
} -cleanup {
    .f configure -width [lindex [.f configure -width] 3]
} -result {32}
} -result 32
test frame-13.44 {labelframe configuration options} -body {
        .f configure -width badValue
    .f configure -width badValue
} -returnCodes error -result {bad screen distance "badValue"}
destroy .f


test frame-14.1 {labelframe labelwidget option} -setup {
	deleteWindows
    deleteWindows
} -body {
    # Test that label is moved in stacking order
    label .l -text Mupp -font {helvetica 8}
    labelframe .f -labelwidget .l
    pack .f
    frame .f.f -width 50 -height 50
    pack .f.f
    update
    list [winfo children .] [winfo width .f] \
        [expr {[winfo height .f] - [winfo height .l]}]
} -cleanup {
    deleteWindows
} -result {{.f .l} 54 52}
test frame-14.2 {labelframe labelwidget option} -setup {
	deleteWindows
    deleteWindows
} -body {
    # Test the labelframe's reaction if the label is destroyed
    label .l -text Aratherlonglabel
    labelframe .f -labelwidget .l
    pack .f
    label .f.l -text Mupp
    pack .f.l
    update
    set res [list [.f cget -labelwidget]]
    lappend res [expr {[winfo width .f] - [winfo width .l]}]
    destroy .l
    lappend res [.f cget -labelwidget]
    update
    lappend res [expr {[winfo width .f] - [winfo width .f.l]}]
} -cleanup {
    deleteWindows
} -result {.l 12 {} 4}
test frame-14.3 {labelframe labelwidget option} -setup {
	deleteWindows
    deleteWindows
} -body {
    # Test the labelframe's reaction if the label is stolen
    label .l -text Aratherlonglabel
    labelframe .f -labelwidget .l
    pack .f
    label .f.l -text Mupp
    pack .f.l
    update
    set res [list [.f cget -labelwidget]]
    lappend res [expr {[winfo width .f] - [winfo width .l]}]
    pack .l
    lappend res [.f cget -labelwidget]
    update
    lappend res [expr {[winfo width .f] - [winfo width .f.l]}]
} -cleanup {
    deleteWindows
} -result {.l 12 {} 4}
test frame-14.4 {labelframe labelwidget option} -setup {
	deleteWindows
    deleteWindows
} -body {
    # Test the label's reaction if the labelframe is destroyed
    label .l -text Mupp
    labelframe .f -labelwidget .l
    pack .f
    update
    set res [list [winfo manager .l]]
    destroy .f
    lappend res [winfo manager .l]
} -cleanup {
    deleteWindows
} -result {labelframe {}}
test frame-14.5 {labelframe labelwidget option} -setup {
	deleteWindows
    deleteWindows
} -body {
    # Test that the labelframe reacts on changes in label
    label .l -text Aratherlonglabel
    labelframe .f -labelwidget .l
    pack .f
    label .f.l -text Mupp
    pack .f.l
1496
1497
1498
1499
1500
1501
1502
1503

1504
1505
1506
1507
1508




1509
1510
1511
1512
1513
1514
1515
1516


1517
1518
1519
1520

























































































































































































































































































1521





1522
1523
1524
1525
1526
1527



1489
1490
1491
1492
1493
1494
1495

1496
1497




1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511




1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801



1802
1803
1804







-
+

-
-
-
-
+
+
+
+








+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+



-
-
-
+
+
+
    update
    lappend res [expr {[winfo width .f] - [winfo width .l]}]
    lappend res [expr {[winfo width .f] > $first}]
} -cleanup {
    deleteWindows
} -result {12 12 1 12 1}
test frame-14.6 {labelframe labelwidget option} -setup {
	deleteWindows
    deleteWindows
} -body {
    # Destroying a labelframe with a child label caused a crash
    # when not handling mapping of the label correctly.
    # This test does not test anything directly, it's just ment
    # to catch if the same mistake is made again.
    # Destroying a labelframe with a child label caused a crash when not
    # handling mapping of the label correctly.
    # This test does not test anything directly, it's just ment to catch if
    # the same mistake is made again.
    labelframe .f
    pack .f
    label .f.l -text Mupp
    .f configure -labelwidget .f.l
    update
} -cleanup {
    deleteWindows
} -result {}

test frame-15.1 {TIP 262: frame background images} -setup {
deleteWindows
rename eatColors {}
rename colorsFree {}

    deleteWindows
    image create photo gorp -width 10 -height 10
    gorp put black -to 2 2 7 7
} -body {
    frame .f -width 100 -height 100
    pack .f
    list [image inuse gorp] [.f configure -backgroundimage gorp;update] \
	[image inuse gorp] [winfo width .f] [winfo height .f]
} -cleanup {
    image delete gorp
    deleteWindows
} -result {0 {} 1 100 100}
test frame-15.2 {TIP 262: frame background images} -setup {
    deleteWindows
    catch {rename gorp ""}
} -body {
    frame .f -width 100 -height 100
    pack .f
    update
    .f configure -backgroundimage gorp
} -returnCodes error -cleanup {
    deleteWindows
} -result {image "gorp" doesn't exist}
test frame-15.3 {TIP 262: frame background images} -setup {
    deleteWindows
    image create photo gorp -width 10 -height 10
    gorp put black -to 2 2 7 7
} -body {
    frame .f -width 100 -height 100 -backgroundimage gorp
    pack .f
    .f configure -tile yes
    update
    list [.f cget -bgimg] [.f cget -tile]
} -cleanup {
    image delete gorp
    deleteWindows
} -result {gorp 1}
test frame-15.4 {TIP 262: frame background images} -setup {
    deleteWindows
    image create photo gorp -width 10 -height 10
    gorp put black -to 2 2 7 7
} -body {
    frame .f -width 100 -height 100 -backgroundimage gorp
    pack .f
    .f configure -tile yes
    update
    gorp put red -to 15 15 20 20
    update
    list [.f cget -bgimg] [.f cget -tile]
} -cleanup {
    image delete gorp
    deleteWindows
} -result {gorp 1}
test frame-15.5 {TIP 262: frame background images} -setup {
    deleteWindows
    image create photo gorp -width 10 -height 10
    gorp put black -to 2 2 7 7
    set result {}
} -body {
    frame .f -width 100 -height 100 -backgroundimage gorp
    pack .f
    .f configure -tile yes
    update
    image delete gorp
    update
    set result [list [.f cget -bgimg] [.f cget -tile]]
    image create photo gorp -width 250 -height 250
    update
    lappend result [.f cget -backgroundimage]
} -cleanup {
    catch {image delete gorp}
    deleteWindows
} -result {gorp 1 gorp}
test frame-15.6 {TIP 262: frame background images} -setup {
    deleteWindows
    set result {}
    . configure -width 200 -height 200
} -constraints testImageType -body {
    image create test gorp -variable result
    pack [frame .f -width 100 -height 100 -bgimg gorp]
    update idletasks; update
    return [uniq $result]
} -cleanup {
    deleteWindows
    catch {image delete gorp}
} -result {{gorp get} {gorp display 0 0 30 15}}
test frame-15.6a {TIP 262: frame background images (offsets)} -setup {
    deleteWindows
    set result {}
    . configure -width 200 -height 200
} -constraints testImageType -body {
    image create test gorp -variable result
    pack [frame .f -width 10 -height 10 -bgimg gorp]
    update idletasks; update
    # On MacOS must wait for the test image display procedure to run.
    set timer [after 300 {lappend result "timedout"}]
    while {"timedout" ni $result &&
	   "gorp display 10 2 10 10" ni $result} {
       vwait result
    }
    after cancel $timer
    update idletasks; update
    return [uniq $result]
} -cleanup {
    deleteWindows
    catch {image delete gorp}
} -result {{gorp get} {gorp display 10 2 10 10}}
test frame-15.7 {TIP 262: frame background images} -setup {
    deleteWindows
    set result {}
    . configure -width 200 -height 200
} -constraints testImageType -body {
    image create test gorp -variable result
    pack [frame .f -width 50 -height 25 -bgimg gorp -tile 1]
    update idletasks; update
    # On MacOS must wait for the test image display procedure to run.
    set timer [after 300 {lappend result "timedout"}]
    while {"timedout" ni $result &&
	   "gorp display 0 0 20 10" ni $result} {
	vwait result
    }
    after cancel $timer
    if {[lindex $result end] eq "timedout"} {
	return [lreplace $result end end]
    }
    return [uniq $result]
} -cleanup {
    deleteWindows
    catch {image delete gorp}
} -result {{gorp get} {gorp display 0 0 30 15} {gorp display 0 0 30 10} {gorp display 0 0 20 15} {gorp display 0 0 20 10}}
test frame-15.7a {TIP 262: frame background images (offsets)} -setup {
    deleteWindows
    set result {}
    . configure -width 200 -height 200
} -constraints testImageType -body {
    image create test gorp -variable result
    pack [frame .f -width 50 -height 25 -bgimg gorp -tile 1 -highlightthick 1]
    update idletasks; update
    # On MacOS must wait for the test image display procedure to run.
    set timer [after 300 {lappend result "timedout"}]
    while {"timedout" ni $result &&
	   "gorp display 0 0 18 8" ni $result} {
	vwait result
   }
    after cancel $timer
    return [uniq $result]
} -cleanup {
    deleteWindows
    catch {image delete gorp}
} -result {{gorp get} {gorp display 0 0 30 15} {gorp display 0 0 30 8} {gorp display 0 0 18 15} {gorp display 0 0 18 8}}
test frame-15.7b {TIP 262: frame background images (offsets)} -setup {
    deleteWindows
    set result {}
    . configure -width 200 -height 200
} -constraints testImageType -body {
    image create test gorp -variable result
    pack [frame .f -width 50 -height 25 -bgimg gorp -tile 1 -bd 2]
    update idletasks; update
    return [uniq $result]
} -cleanup {
    deleteWindows
    catch {image delete gorp}
} -result {{gorp get} {gorp display 0 0 30 15} {gorp display 0 0 30 6} {gorp display 0 0 16 15} {gorp display 0 0 16 6}}
test frame-15.7c {TIP 262: frame background images (offsets)} -setup {
    deleteWindows
    set result {}
    . configure -width 200 -height 200
} -constraints testImageType -body {
    image create test gorp -variable result
    pack [frame .f -width 50 -height 25 -bgimg gorp -tile 1 -bd 2 -highlightthick 1]
    update idletasks; update
    return [uniq $result]
} -cleanup {
    deleteWindows
    catch {image delete gorp}
} -result {{gorp get} {gorp display 0 0 30 15} {gorp display 0 0 30 4} {gorp display 0 0 14 15} {gorp display 0 0 14 4}}
test frame-15.8 {TIP 262: toplevel background images} -setup {
    deleteWindows
    image create photo gorp -width 10 -height 10
    gorp put black -to 2 2 7 7
} -body {
    toplevel .t -width 100 -height 100
    update
    # Used to verify that setting a background image doesn't change the widget size
    set w [winfo width .t]
    set h [winfo height .t]
    list [image inuse gorp] [.t configure -backgroundimage gorp;update] \
	[image inuse gorp] \
	[expr {$w-[winfo width .t]}] [expr {$h-[winfo height .t]}]
} -cleanup {
    image delete gorp
    deleteWindows
} -result {0 {} 1 0 0}
test frame-15.9 {TIP 262: toplevel background images} -setup {
    deleteWindows
    catch {rename gorp ""}
} -body {
    toplevel .t -width 100 -height 100
    update
    .t configure -backgroundimage gorp
} -returnCodes error -cleanup {
    deleteWindows
} -result {image "gorp" doesn't exist}
test frame-15.10 {TIP 262: toplevel background images} -setup {
    deleteWindows
    image create photo gorp -width 10 -height 10
    gorp put black -to 2 2 7 7
} -body {
    toplevel .t -width 100 -height 100 -backgroundimage gorp -tile yes
    update
    list [.t cget -bgimg] [.t cget -tile]
} -cleanup {
    image delete gorp
    deleteWindows
} -result {gorp 1}
test frame-15.11 {TIP 262: toplevel background images} -setup {
    deleteWindows
    image create photo gorp -width 10 -height 10
    gorp put black -to 2 2 7 7
} -body {
    toplevel .t -width 100 -height 100 -backgroundimage gorp -tile yes
    update
    gorp put red -to 15 15 20 20
    update
    list [.t cget -bgimg] [.t cget -tile]
} -cleanup {
    image delete gorp
    deleteWindows
} -result {gorp 1}
test frame-15.12 {TIP 262: toplevel background images} -setup {
    deleteWindows
    image create photo gorp -width 10 -height 10
    gorp put black -to 2 2 7 7
    set result {}
} -body {
    toplevel .t -width 100 -height 100 -backgroundimage gorp -tile yes
    update
    image delete gorp
    update
    set result [list [.t cget -bgimg] [.t cget -tile]]
    image create photo gorp -width 250 -height 250
    update
    lappend result [.t cget -backgroundimage]
} -cleanup {
    catch {image delete gorp}
    deleteWindows
} -result {gorp 1 gorp}
test frame-15.13 {TIP 262: toplevel background images} -setup {
    deleteWindows
    set result {}
} -constraints testImageType -body {
    image create test gorp -variable result
    toplevel .t -width 100 -height 100 -bgimg gorp
    wm overrideredirect .t 1;	# Reduce trouble from window managers
    update idletasks; update
    return [uniq $result]
} -cleanup {
    deleteWindows
    catch {image delete gorp}
} -result {{gorp get} {gorp display 0 0 30 15}}
test frame-15.14 {TIP 262: toplevel background images} -setup {
    deleteWindows
    set result {}
} -constraints testImageType -body {
    image create test gorp -variable result
    toplevel .t -width 50 -height 25 -bgimg gorp -tile 1
    wm overrideredirect .t 1;	# Reduce trouble from window managers
    update idletasks; update
    # On MacOS must wait for the test image display procedure to run.
    set timer [after 300 {lappend result "timedout"}]
    while {"timedout" ni $result &&
	   "gorp display 0 0 20 10" ni $result} {
	vwait result
   }
    after cancel $timer
    return [uniq $result]
} -cleanup {
    deleteWindows
    catch {image delete gorp}
} -result {{gorp get} {gorp display 0 0 30 15} {gorp display 0 0 30 10} {gorp display 0 0 20 15} {gorp display 0 0 20 10}}

# cleanup
deleteWindows
apply {cmds {foreach cmd $cmds {rename $cmd {}}}} {
    eatColors colorsFree uniq optnames
}

cleanupTests
return




# Local Variables:
# mode: tcl
# End:
Changes to tests/geometry.test.
1
2
3
4
5
6
7



8
9
10
11
12
13
14
1
2
3
4



5
6
7
8
9
10
11
12
13
14




-
-
-
+
+
+







# This file is a Tcl script to test the procedures in the file
# tkGeometry.c (generic support for geometry managers).  It is
# organized in the standard fashion for Tcl tests.
#
# Copyright (c) 1994 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1994 The Regents of the University of California.
# Copyright © 1994 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

proc getsize w {
    regexp {(^[^+-]*)} [wm geometry $w] foo x
    return $x
}

266
267
268
269
270
271
272
273

274
275
276
277
278
279
280
281
282
283
284
285

286
287
288
289
290
291
266
267
268
269
270
271
272

273
274
275
276
277
278
279
280
281
282
283
284

285
286
287
288
289
290
291







-
+











-
+






    }
    destroy .t
} -body {
    toplevel .t
    wm geometry .t +0+0
    tkwait visibility .t
    update
    pack [frame .t.f] 
    pack [frame .t.f]
    button .t.quit -text Quit -command exit
    pack .t.quit -in .t.f
    wm iconify .t
    set x 0
    after 500 {set x 1}
    tkwait variable x
    wm deiconify .t
    update
    winfo ismapped .t.quit
} -cleanup {
    destroy .t
} -result {1}
} -result 1


# cleanup
cleanupTests
return

Changes to tests/get.test.
1
2
3
4
5
6


7
8
9
10
11
12
13
1
2
3
4


5
6
7
8
9
10
11
12
13




-
-
+
+







# This file is a Tcl script to test out the procedures in the file
# tkGet.c.  It is organized in the standard fashion for Tcl
# white-box tests.
#
# Copyright (c) 1998 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1998 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
eval tcltest::configure $argv
tcltest::loadTestedCommands
namespace import -force tcltest::test

Changes to tests/grab.test.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







# Tests for the grab command.
#
# This file contains a collection of tests for one or more of the Tk
# built-in commands.  Sourcing this file runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1998-2000 by Ajuba Solutions.
# Copyright © 1998-2000 Ajuba Solutions.
# All rights reserved.

package require tcltest 2.2
eval tcltest::configure $argv
tcltest::loadTestedCommands
namespace import -force tcltest::test

103
104
105
106
107
108
109
110

111
112
113
114
115
116
117
103
104
105
106
107
108
109

110
111
112
113
114
115
116
117







-
+







    set curr [grab current .]
    if { [string length $curr] > 0 } {
	grab release $curr
    }
    grab status .
} -cleanup {
    grab release .
} -result {none}
} -result none
test grab-2.2 {Tk_GrabObjCmd, grab status gives correct status} -body {
    set curr [grab current .]
    if { [string length $curr] > 0 } {
	grab release $curr
    }
    grab .
    grab status .
Changes to tests/grid.test.
1
2
3
4
5


6
7
8
9
10
11
12
1
2
3


4
5
6
7
8
9
10
11
12



-
-
+
+







# This file is a Tcl script to test out the *NEW* "grid" command of Tk. It is
# (almost) organized in the standard fashion for Tcl tests.
#
# Copyright (c) 1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
eval tcltest::configure $argv
tcltest::loadTestedCommands
namespace import -force tcltest::test

41
42
43
44
45
46
47
48

49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

67
68
69

70
71
72
73
74
75
76
41
42
43
44
45
46
47

48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65

66
67
68

69
70
71
72
73
74
75
76







-
+

















-
+


-
+







wm geometry . {}

test grid-1.1 {basic argument checking} -body {
    grid
} -returnCodes error -result {wrong # args: should be "grid option arg ?arg ...?"}
test grid-1.2 {basic argument checking} -body {
    grid foo bar
} -returnCodes error -result {bad option "foo": must be anchor, bbox, columnconfigure, configure, forget, info, location, propagate, remove, rowconfigure, size, or slaves}
} -returnCodes error -result {bad option "foo": must be anchor, bbox, columnconfigure, configure, content, forget, info, location, propagate, remove, rowconfigure, or size}
test grid-1.3 {basic argument checking} -body {
    button .b
    grid .b -row 0 -column
} -cleanup {
    grid_reset 1.3
} -returnCodes error -result {extra option or option with no value}
test grid-1.4 {basic argument checking} -body {
    button .b
    grid configure .b - foo
} -cleanup {
    grid_reset 1.4
} -returnCodes error -result {unexpected parameter "foo" in configure list: should be window name or option}
test grid-1.5 {basic argument checking} -body {
    grid .
} -returnCodes error -result {can't manage ".": it's a top-level window}
test grid-1.6 {basic argument checking} -body {
    grid x
} -returnCodes error -result {can't determine master window}
} -returnCodes error -result {can't determine container window}
test grid-1.7 {basic argument checking} -body {
    grid configure x
} -returnCodes error -result {can't determine master window}
} -returnCodes error -result {can't determine container window}
test grid-1.8 {basic argument checking} -body {
    button .b
    grid x .b
} -cleanup {
    grid_reset 1.8
} -returnCodes ok -result {}
test grid-1.9 {basic argument checking} -body {
89
90
91
92
93
94
95
96

97
98
99
100
101
102
103
89
90
91
92
93
94
95

96
97
98
99
100
101
102
103







-
+







    grid .b
    destroy .b
    update
    grid bbox .
} -result {0 0 0 0}
test grid-2.3 {bbox: argument checking} -body {
    grid bbox . 0 0 5
} -returnCodes error -result {wrong # args: should be "grid bbox master ?column row ?column row??"}
} -returnCodes error -result {wrong # args: should be "grid bbox window ?column row ?column row??"}
test grid-2.4 {bbox} -body {
    grid bbox .bad 0 0
} -returnCodes error -result {bad window path name ".bad"}
test grid-2.5 {bbox} -body {
    grid bbox . x 0
} -returnCodes error -result {expected integer but got "x"}
test grid-2.6 {bbox} -body {
141
142
143
144
145
146
147
148

149
150
151
152
153
154
155
141
142
143
144
145
146
147

148
149
150
151
152
153
154
155







-
+








test grid-3.1 {configure: basic argument checking} -body {
    grid configure foo
} -returnCodes error -result {bad argument "foo": must be name of window}
test grid-3.2 {configure: basic argument checking} -body {
    button .b
    grid configure .b
    grid slaves .
    grid content .
} -cleanup {
    grid_reset 3.2
} -result {.b}
test grid-3.3 {configure: basic argument checking} -body {
    button .b
    grid .b -row -1
} -cleanup {
175
176
177
178
179
180
181
182

183
184
185
186

187
188
189
190
191
192
193
194
195
196

197
198
199
200
201
202
203
204
205
206
207
208
209

210
211
212
213
214
215
216
217
218
219

220
221
222
223
224
225
226
227

228
229

230
231
232
233
234
235
236
175
176
177
178
179
180
181

182
183
184
185

186
187
188
189
190
191
192
193
194
195

196
197
198
199
200
201
202
203
204
205
206
207
208

209
210
211
212
213
214
215
216
217
218

219
220
221
222
223
224
225
226

227
228

229
230
231
232
233
234
235
236







-
+



-
+









-
+












-
+









-
+







-
+

-
+







} -returnCodes error -result {bad columnspan value "0": must be a positive integer}
test grid-3.7 {configure: basic argument checking} -body {
    frame .f
    button .f.b
    grid .f .f.b
} -cleanup {
    grid_reset 3.7
} -returnCodes error -result {can't put .f.b inside .}
} -returnCodes error -result {can't put ".f.b" inside "."}
test grid-3.8 {configure: basic argument checking} -body {
    button .b
    grid configure x .b
    grid slaves .
    grid content .
} -cleanup {
    grid_reset 3.8
} -result {.b}
test grid-3.9 {configure: basic argument checking} -body {
    button .b
    grid configure y .b
} -cleanup {
    grid_reset 3.9
} -returnCodes error -result {invalid window shortcut, "y" should be '-', 'x', or '^'}
test grid-3.10 {ConfigureSlave procedure, bad -in option} -body {
test grid-3.10 {ConfigureContent procedure, bad -in option} -body {
    frame .f
    grid .f -in .f
} -cleanup {
    grid_reset 3.10
} -returnCodes error -result {window can't be managed in itself}
test grid-3.11 {prevent management loops} -body {
    frame .f1
    frame .f2
    grid .f1 -in .f2
    grid .f2 -in .f1
} -cleanup {
    grid_reset 3.11
} -returnCodes error -result {can't put .f2 inside .f1, would cause management loop}
} -returnCodes error -result {can't put ".f2" inside ".f1": would cause management loop}
test grid-3.12 {prevent management loops} -body {
    frame .f1
    frame .f2
    frame .f3
    grid .f1 -in .f2
    grid .f2 -in .f3
    grid .f3 -in .f1
} -cleanup {
    grid_reset 3.12
} -returnCodes error -result {can't put .f3 inside .f1, would cause management loop}
} -returnCodes error -result {can't put ".f3" inside ".f1": would cause management loop}

test grid-4.1 {forget: basic argument checking} -body {
    grid forget foo
} -returnCodes error -result {bad window path name "foo"}
test grid-4.2 {forget} -body {
    button .c
    grid [button .b]
    set a [grid slaves .]
    set a [grid content .]
    grid forget .b .c
    lappend a [grid slaves .]
    lappend a [grid content .]
    return $a
} -cleanup {
    grid_reset 4.2
} -result {.b {}}
test grid-4.3 {forget} -body {
    button .c
    grid .c -row 2 -column 2 -rowspan 2 -columnspan 2 -padx 3 -pady 4 -sticky ns
289
290
291
292
293
294
295
296

297
298
299
300
301
302
303
289
290
291
292
293
294
295

296
297
298
299
300
301
302
303







-
+







    grid info .1
} -cleanup {
    grid_reset 5.4
} -returnCodes ok -result {}

test grid-6.1 {location: basic argument checking} -body {
    grid location .
} -returnCodes error -result {wrong # args: should be "grid location master x y"}
} -returnCodes error -result {wrong # args: should be "grid location window x y"}
test grid-6.2 {location: basic argument checking} -body {
    grid location .bad 0 0
} -returnCodes error -result {bad window path name ".bad"}
test grid-6.3 {location: basic argument checking} -body {
    grid location . x y
} -returnCodes error -result {bad screen distance "x"}
test grid-6.4 {location: basic argument checking} -body {
385
386
387
388
389
390
391
392

393
394
395
396
397

398
399
400
401
402
403
404
385
386
387
388
389
390
391

392
393
394
395
396

397
398
399
400
401
402
403
404







-
+




-
+







} -cleanup {
    grid_reset 7.1
} -returnCodes error -result {wrong # args: should be "grid propagate window ?boolean?"}
test grid-7.2 {propagate} -body {
    grid propagate .
} -cleanup {
    grid_reset 7.2
} -result {1}
} -result 1
test grid-7.3 {propagate} -body {
    grid propagate . 0;grid propagate .
} -cleanup {
    grid_reset 7.3
} -result {0}
} -result 0
test grid-7.4 {propagate} -body {
    grid propagate .x
} -cleanup {
    grid_reset 7.4
} -returnCodes error -result {bad window path name ".x"}
test grid-7.5 {propagate} -body {
    grid propagate . x
512
513
514
515
516
517
518
519
520


521
522
523


524
525
526
527
528
529





530
531
532


533
534
535


536
537
538


539
540
541


542
543
544


545
546

547
548
549
550
551

552
553
554
555

556
557
558
559
560
561
562
563
564

565
566
567

568
569
570
571
572
573
574
575
576
577
578
579

580
581
582
583
584

585
586
587
588
589
590
591
592
593
594
595
596
597
598
599

600
601
602
603
604
605
606
512
513
514
515
516
517
518


519
520
521


522
523
524





525
526
527
528
529
530


531
532
533


534
535
536


537
538
539


540
541
542


543
544
545

546
547
548
549
550

551
552
553
554

555
556
557
558
559
560
561
562
563

564
565
566

567
568
569
570
571
572
573
574
575
576
577
578

579
580
581
582
583

584
585
586
587
588
589
590
591
592
593
594
595
596
597
598

599
600
601
602
603
604
605
606







-
-
+
+

-
-
+
+

-
-
-
-
-
+
+
+
+
+

-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+

-
+




-
+



-
+








-
+


-
+











-
+




-
+














-
+







    update
    lappend a [grid size .]
    return $a
} -cleanup {
    grid_reset 8.6
} -result {{51 11} {51 11} {31 11} {21 11} {16 1} {1 1}}

test grid-9.1 {slaves} -body {
    grid slaves .
test grid-9.1 {content} -body {
    grid content .
} -returnCodes ok -result {}
test grid-9.2 {slaves} -body {
    grid slaves .foo
test grid-9.2 {content} -body {
    grid content .foo
} -returnCodes error -result {bad window path name ".foo"}
test grid-9.3 {slaves} -body {
    grid slaves a b
} -returnCodes error -result {wrong # args: should be "grid slaves window ?-option value ...?"}
test grid-9.4 {slaves} -body {
    grid slaves . a b
test grid-9.3 {content} -body {
    grid content a b
} -returnCodes error -result {wrong # args: should be "grid content window ?-option value ...?"}
test grid-9.4 {content} -body {
    grid content . a b
} -returnCodes error -result {bad option "a": must be -column or -row}
test grid-9.5 {slaves} -body {
    grid slaves . -column x
test grid-9.5 {content} -body {
    grid content . -column x
} -returnCodes error -result {expected integer but got "x"}
test grid-9.6 {slaves} -body {
    grid slaves . -row -3
test grid-9.6 {content} -body {
    grid content . -row -3
} -returnCodes error -result {-3 is an invalid value: should NOT be < 0}
test grid-9.7 {slaves} -body {
    grid slaves . -foo 3
test grid-9.7 {content} -body {
    grid content . -foo 3
} -returnCodes error -result {bad option "-foo": must be -column or -row}
test grid-9.8 {slaves} -body {
    grid slaves .x -row 3
test grid-9.8 {content} -body {
    grid content .x -row 3
} -returnCodes error -result {bad window path name ".x"}
test grid-9.9 {slaves} -body {
    grid slaves . -row 3
test grid-9.9 {content} -body {
    grid content . -row 3
} -returnCodes ok -result {}
test grid-9.10 {slaves} -body {
test grid-9.10 {content} -body {
    foreach i {0 1 2} {
	label .$i -text $i
	grid .$i -row $i -column $i
    }
    grid slaves .
    grid content .
} -cleanup {
    grid_reset 9.10
} -result {.2 .1 .0}
test grid-9.11 {slaves} -body {
test grid-9.11 {content} -body {
    catch {unset a}
    foreach i {0 1 2} {
	label .$i -text $i
	label .$i-x -text $i-x
	grid .$i -row $i -column $i
	grid .$i-x -row $i -column [incr i]
    }
    foreach row {0 1 2 3} {
	lappend a $row{[grid slaves . -row $row]}
	lappend a $row{[grid content . -row $row]}
    }
    foreach col {0 1 2 3} {
	lappend a $col{[grid slaves . -column $col]}
	lappend a $col{[grid content . -column $col]}
    }
    return $a
} -cleanup {
    grid_reset 9.11
} -result {{0{.0-x .0}} {1{.1-x .1}} {2{.2-x .2}} 3{} 0{.0} {1{.1 .0-x}} {2{.2 .1-x}} 3{.2-x}}

# column/row configure
test grid-10.1 {column/row configure} -body {
    grid columnconfigure .
} -cleanup {
    grid_reset 10.1
} -returnCodes error -result {wrong # args: should be "grid columnconfigure master index ?-option value ...?"}
} -returnCodes error -result {wrong # args: should be "grid columnconfigure window index ?-option value ...?"}
test grid-10.2 {column/row configure} -body {
    grid columnconfigure . 0 -weight 0 -pad
} -cleanup {
    grid_reset 10.2
} -returnCodes error -result {wrong # args: should be "grid columnconfigure master index ?-option value ...?"}
} -returnCodes error -result {wrong # args: should be "grid columnconfigure window index ?-option value ...?"}
test grid-10.3 {column/row configure} -body {
    grid columnconfigure .f 0 -weight
} -cleanup {
    grid_reset 10.3
} -returnCodes error -result {bad window path name ".f"}
test grid-10.4 {column/row configure} -body {
    grid columnconfigure . nine -weight
} -cleanup {
    grid_reset 10.4
} -returnCodes error -result {expected integer but got "nine" (when retrieving options only integer indices are allowed)}
test grid-10.5 {column/row configure} -body {
    grid columnconfigure . 265 -weight
} -cleanup {
    grid_reset 10.5
} -result {0}
} -result 0
test grid-10.6 {column/row configure} -body {
    grid columnconfigure . 0
} -cleanup {
    grid_reset 10.6
} -result {-minsize 0 -pad 0 -uniform {} -weight 0}
test grid-10.7 {column/row configure} -body {
    grid columnconfigure . 0 -foo
618
619
620
621
622
623
624
625

626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641

642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657

658
659
660
661
662
663
664
618
619
620
621
622
623
624

625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640

641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656

657
658
659
660
661
662
663
664







-
+















-
+















-
+







    grid_reset 10.9
} -returnCodes error -result {bad screen distance "foo"}
test grid-10.10 {column/row configure} -body {
    grid columnconfigure . 0 -minsize 10
    grid columnconfigure . 0 -minsize
} -cleanup {
    grid_reset 10.10
} -result {10}
} -result 10
test grid-10.11 {column/row configure} -body {
    grid columnconfigure . 0 -weight bad
} -cleanup {
    grid_reset 10.11
} -returnCodes error -result {expected integer but got "bad"}
test grid-10.12 {column/row configure} -body {
    grid columnconfigure . 0 -weight -3
} -cleanup {
    grid_reset 10.12
} -returnCodes error -result {invalid arg "-weight": should be non-negative}
test grid-10.13 {column/row configure} -body {
    grid columnconfigure . 0 -weight 3
    grid columnconfigure . 0 -weight
} -cleanup {
    grid_reset 10.13
} -result {3}
} -result 3
test grid-10.14 {column/row configure} -body {
    grid columnconfigure . 0 -pad foo
} -cleanup {
    grid_reset 10.14
} -returnCodes error -result {bad screen distance "foo"}
test grid-10.15 {column/row configure} -body {
    grid columnconfigure . 0 -pad -3
} -cleanup {
    grid_reset 10.15
} -returnCodes error -result {invalid arg "-pad": should be non-negative}
test grid-10.16 {column/row configure} -body {
    grid columnconfigure . 0 -pad 3
    grid columnconfigure . 0 -pad
} -cleanup {
    grid_reset 10.16
} -result {3}
} -result 3
test grid-10.17 {column/row configure} -body {
    frame .f
    set a ""
    grid columnconfigure .f 0 -weight 0
    lappend a [grid columnconfigure .f 0 -weight]
    grid columnconfigure .f 0 -weight 1
    lappend a [grid columnconfigure .f 0 -weight]
852
853
854
855
856
857
858
859

860
861
862
863
864
865

866
867
868
869
870
871
872
852
853
854
855
856
857
858

859
860
861
862
863
864

865
866
867
868
869
870
871
872







-
+





-
+







grid_reset 10.39

# auto-placement tests
test grid-11.1 {default widget placement} -body {
    grid ^
} -cleanup {
    grid_reset 11.1
} -returnCodes error -result {can't use '^', cant find master}
} -returnCodes error -result {can't use '^', can't find container window}
test grid-11.2 {default widget placement} -body {
    button .b
    grid .b ^
} -cleanup {
    grid_reset 11.2
} -returnCodes error -result {can't find slave to extend with "^"}
} -returnCodes error -result {can't find content to extend with "^"}
test grid-11.3 {default widget placement} -body {
    button .b
    grid .b - - .c
} -cleanup {
    grid_reset 11.3
} -returnCodes error -result {bad window path name ".c"}
test grid-11.4 {default widget placement} -body {
913
914
915
916
917
918
919
920

921
922
923
924
925
926
927
913
914
915
916
917
918
919

920
921
922
923
924
925
926
927







-
+







} -returnCodes error -result {must specify window before shortcut '-'}
test grid-11.9 {default widget placement} -body {
    frame .f -width 20 -height 20 -highlightthickness 0 -bg red
    grid .f -row 5 -column 5
    grid .f x ^
} -cleanup {
    grid_reset 11.9
} -returnCodes error -result {can't find slave to extend with "^"}
} -returnCodes error -result {can't find content to extend with "^"}
test grid-11.10 {default widget placement} -body {
    foreach i {1 2 3} {
	frame .f$i -width 100 -height 50 -highlightthickness 0 -bg red
    }
    grid .f1 .f2  -sticky nsew
    grid .f3   ^  -sticky nsew
    update
1158
1159
1160
1161
1162
1163
1164
1165

1166
1167
1168
1169
1170
1171
1172
1158
1159
1160
1161
1162
1163
1164

1165
1166
1167
1168
1169
1170
1171
1172







-
+







} -returnCodes error -result {bad window path name ".bad"}
test grid-13.4 {-in} -body {
    frame .f -bg red
    toplevel .top
    grid .f -in .top
} -cleanup {
    grid_reset 13.3
} -returnCodes error -result {can't put .f inside .top}
} -returnCodes error -result {can't put ".f" inside ".top"}
destroy .top
test grid-13.5 {-ipadx} -body {
    frame .f -width 20 -height 20 -highlightthickness 0 -bg red
    grid .f -ipadx x
} -cleanup {
    grid_reset 13.4
} -returnCodes error -result {bad ipadx value "x": must be positive screen distance}
1301
1302
1303
1304
1305
1306
1307
1308

1309
1310
1311

1312
1313
1314
1315
1316
1317
1318
1301
1302
1303
1304
1305
1306
1307

1308
1309
1310

1311
1312
1313
1314
1315
1316
1317
1318







-
+


-
+







    frame .1
    frame .2
    button .b
    grid .1 .2
    grid .b -in .1
    set a ""
    catch {unset info}; array set info [grid info .b]
    lappend a [grid slaves .1],[grid slaves .2],$info(-in)
    lappend a [grid content .1],[grid content .2],$info(-in)
    grid .b -in .2
    catch {unset info}; array set info [grid info .b]
    lappend a [grid slaves .1],[grid slaves .2],$info(-in)
    lappend a [grid content .1],[grid content .2],$info(-in)
    unset info
    return $a
} -cleanup {
    grid_reset 13.13
} -result {.b,,.1 ,.b,.2}

test grid-14.1 {structure notify} -body {
1365
1366
1367
1368
1369
1370
1371
1372

1373
1374
1375

1376
1377

1378
1379

1380
1381
1382
1383

1384
1385
1386
1387
1388

1389
1390

1391
1392

1393
1394
1395
1396
1397
1398
1399
1365
1366
1367
1368
1369
1370
1371

1372
1373
1374

1375
1376

1377
1378

1379
1380
1381
1382

1383
1384
1385
1386
1387

1388
1389

1390
1391

1392
1393
1394
1395
1396
1397
1398
1399







-
+


-
+

-
+

-
+



-
+




-
+

-
+

-
+







    update
    bind . <Configure> {}
    array get A
} -cleanup {
    grid_reset 14.3
} -result {.2 2 .0 1 . 2 .1 1}

test grid-15.1 {lost slave} -body {
test grid-15.1 {lost content} -body {
    button .b
    grid .b
    set a [grid slaves .]
    set a [grid content .]
    pack .b
    lappend a [grid slaves .]
    lappend a [grid content .]
    grid .b
    lappend a [grid slaves .]
    lappend a [grid content .]
} -cleanup {
    grid_reset 15.1
} -result {.b {} .b}
test grid-15.2 {lost slave} -body {
test grid-15.2 {lost content} -body {
    frame .f
    grid .f
    button .b
    grid .b -in .f
    set a [grid slaves .f]
    set a [grid content .f]
    pack .b -in .f
    lappend a [grid slaves .f]
    lappend a [grid content .f]
    grid .b -in .f
    lappend a [grid slaves .f]
    lappend a [grid content .f]
} -cleanup {
    grid_reset 15.2
} -result {.b {} .b}

test grid-16.1 {layout centering} -body {
    foreach i {0 1 2} {
	frame .$i -bg gray  -width 75 -height 50 -bd 2 -relief ridge
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1821
1822
1823
1824
1825
1826
1827

1828
1829
1830
1831
1832
1833
1834







-







    frame .t.f
    label .t.f.l -text foobar
    grid .t.f.l
    destroy .t
    set result ok
} -result ok


test grid-18.1 {test respect for internalborder} -body {
    toplevel .pack
    wm geometry .pack 200x200
    frame .pack.l -width 15 -height 10
    labelframe .pack.lf -labelwidget .pack.l
    pack .pack.lf -fill both -expand 1
    frame .pack.lf.f
1971
1972
1973
1974
1975
1976
1977
1978

1979
1980

1981
1982
1983
1984
1985
1986
1987
1970
1971
1972
1973
1974
1975
1976

1977
1978

1979
1980
1981
1982
1983
1984
1985
1986







-
+

-
+








test grid-22.1 {remove: basic argument checking} {
    list [catch {grid remove foo} msg] $msg
} {1 {bad window path name "foo"}}
test grid-22.2 {remove} {
    button .c
    grid [button .b]
    set a [grid slaves .]
    set a [grid content .]
    grid remove .b .c
    lappend a [grid slaves .]
    lappend a [grid content .]
    return $a
} {.b {}}
grid_reset 22.2
test grid-22.3 {remove} {
    button .c
    grid .c -row 2 -column 2 -rowspan 2 -columnspan 2 -padx 3 -pady 4 -sticky ns
    grid remove .c
2020
2021
2022
2023
2024
2025
2026
2027

2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043

2044



















































































































2045
2046
2047
2048
2049
2050
2051
2052
2019
2020
2021
2022
2023
2024
2025

2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041

2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166







-
+















-
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








    # is ignored.
    destroy .a
    grid .c -row 0 -column 0
    grid info .c
} {-in . -column 0 -row 0 -columnspan 2 -rowspan 2 -ipadx 0 -ipady 0 -padx {3 5} -pady {4 7} -sticky ns}
grid_reset 22.5

test grid-23 {grid configure -in leaked from previous master - bug
test grid-23 {grid configure -in leaked from previous container window - bug
              6aea69fccbb266b7f0437686379fbe5b55442958} {
    frame .f
    frame .g
    pack .f .g
    text .t
    grid .t -in .f
    pack forget .f
    update
    grid .t -in .g
    # .t is now managed by .g; following lines must have no effect on .t
    pack .f
    update
    pack forget .f
    update
    winfo ismapped .t ; # must return 1
} {1}
} 1
grid_reset 23

test grid-24.1 {<<NoManagedChild>> fires on last grid forget} -setup {
    global A
    unset -nocomplain A
} -body {
    grid [frame .1]
    update
    bind . <<NoManagedChild>> {set A 1}
    grid forget .1
    update
    info exists A
} -cleanup {
    bind . <<NoManagedChild>> {}
    grid_reset 24.1
} -result 1
test grid-24.2 {<<NoManagedChild>> fires on last grid remove} -setup {
    global A
    unset -nocomplain A
} -body {
    grid [frame .1]
    update
    bind . <<NoManagedChild>> {set A 1}
    grid remove .1
    update
    info exists A
} -cleanup {
    bind . <<NoManagedChild>> {}
    grid_reset 24.2
} -result 1
test grid-24.3 {<<NoManagedChild>> fires on last gridded child destruction} -setup {
    global A
    unset -nocomplain A
} -body {
    grid [frame .1]
    update
    bind . <<NoManagedChild>> {incr A}
    destroy .1
    update
    set A
} -cleanup {
    bind . <<NoManagedChild>> {}
    grid_reset 24.3
} -result 1
test grid-24.4 {<Configure> does not fire on last grid forget} -setup {
    global A
    unset -nocomplain A
} -body {
    grid [frame .1]
    update
    bind . <Configure> {set A 1}
    grid forget .1
    update
    info exists A
} -cleanup {
    bind . <Configure> {}
    grid_reset 24.4
} -result 0
test grid-24.5 {<Configure> fires on forelast grid forget} -setup {
    global A
    unset -nocomplain A
} -body {
    grid [frame .1]
    grid [frame .2]
    update
    bind . <Configure> {set A 1}
    grid forget .1
    update
    info exists A
} -cleanup {
    bind . <Configure> {}
    grid_reset 24.5
} -result 1
test grid-24.6 {<<NoManagedChild>> does not fire on forelast grid forget} -setup {
    global A
    unset -nocomplain A
} -body {
    grid [frame .1]
    grid [frame .2]
    update
    bind . <<NoManagedChild>> {set A 1}
    grid forget .1
    update
    info exists A
} -cleanup {
    bind . <<NoManagedChild>> {}
    grid_reset 24.6
} -result 0
test grid-24.7 {<<NoManagedChild>> does not fire on grid anchor} -setup {
    global A
    unset -nocomplain A
} -body {
    bind . <<NoManagedChild>> {set A 1}
    grid anchor . w
    update
    info exists A
} -cleanup {
    grid anchor . nw
    bind . <<NoManagedChild>> {}
    grid_reset 24.7
} -result 0
test grid-24.8 {<<NoManagedChild>> does not fire on last grid forget if propagation is off} -setup {
    global A
    unset -nocomplain A
} -body {
    grid [frame .1]
    grid propagate . 0
    update
    bind . <<NoManagedChild>> {set A 1}
    grid forget .1
    update
    info exists A
} -cleanup {
    bind . <<NoManagedChild>> {}
    grid_reset 24.8
} -result 0

# cleanup
cleanupTests
return

# Local Variables:
# mode: tcl
# End:
Changes to tests/image.test.
1
2
3
4
5
6
7



8
9
10
11
12
13
14
1
2
3
4



5
6
7
8
9
10
11
12
13
14




-
-
-
+
+
+







# This file is a Tcl script to test out the "image" command and the
# other procedures in the file tkImage.c.  It is organized in the
# standard fashion for Tcl tests.
#
# Copyright (c) 1994 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1994 The Regents of the University of California.
# Copyright © 1994 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
namespace import ::tcltest::*
eval tcltest::configure $argv
tcltest::loadTestedCommands

46
47
48
49
50
51
52
53

54
55
56
57
58
59
60
46
47
48
49
50
51
52

53
54
55
56
57
58
59
60







-
+







} -body {
    scan [image create test] image%d first
    image create test myimage
    scan [image create test -variable x] image%d second
    expr {$second-$first}
} -cleanup {
    imageCleanup
} -result {1}
} -result 1

test image-1.7 {Tk_ImageCmd procedure, "create" option} -constraints {
    testImageType
} -setup {
    imageCleanup
} -body {
    image create test myimage -variable x
304
305
306
307
308
309
310
311



312
313
314

315
316
317
318

319
320
321
322
323
324
325
304
305
306
307
308
309
310

311
312
313
314
315

316


317

318
319
320
321
322
323
324
325







-
+
+
+


-
+
-
-

-
+







    image type myimage
} -cleanup {
    .c delete all
    imageCleanup
} -returnCodes error -result {image "myimage" doesn't exist}


test image-6.1 {Tk_ImageCmd procedure, "types" option} -body {
test image-6.1 {Tk_ImageCmd procedure, "types" option} -constraints {
    testImageType
} -body {
    image types x
} -returnCodes error -result {wrong # args: should be "image types"}
test image-6.2 {Tk_ImageCmd procedure, "types" option} -constraints {
test image-6.2 {Tk_ImageCmd procedure, "types" option} -body {
    testImageType
} -body {
    lsort [image types]
} -result {bitmap oldtest photo test}
} -match glob -result {bitmap*photo test}


test image-7.1 {Tk_ImageCmd procedure, "width" option} -body {
    image width
} -returnCodes error -result {wrong # args: should be "image width name"}
test image-7.2 {Tk_ImageCmd procedure, "width" option} -body {
    image width a b
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
353
354
355
356
357
358
359






360
361
362
363
364
365
366







-
-
-
-
-
-







    button .b -image myimage2
    lappend res [image inuse myimage2]
} -cleanup {
    imageCleanup
    catch {destroy .b}
} -result [list 0 1]

if {[tk windowingsystem] == "aqua" && $tcl_platform(osVersion) > 18} {
    # Aqua >= 10.14 will redraw the entire image in drawRect.
    set result_9_1 {{foo display 0 0 30 15}}
} else {
    set result_9_1 {{foo display 5 6 7 8}}
}
test image-9.1 {Tk_ImageChanged procedure} -constraints testImageType -setup {
    .c delete all
    imageCleanup
    update
} -body {
    image create test foo -variable x
    .c create image 50 50 -image foo
381
382
383
384
385
386
387
388

389
390
391
392
393
394

395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414

415
416
417
418
419
420
421
375
376
377
378
379
380
381

382






383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402

403
404
405
406
407
408
409
410







-
+
-
-
-
-
-
-
+



















-
+







        vwait x
    }
    after cancel $timer
    return $x
} -cleanup {
    .c delete all
    imageCleanup
} -result $result_9_1
} -result {{foo display 5 6 7 8}}
if {[tk windowingsystem] == "aqua" && $tcl_platform(osVersion) > 18} {
    # Aqua >= 10.14 will redraw the entire image.
    set result_9_2 {{foo display 0 0 30 15} {foo display 0 0 30 15}}
} else {
    set result_9_2 {{foo display 5 6 25 9} {foo display 0 0 12 14}}
}

test image-9.2 {Tk_ImageChanged procedure} -constraints testImageType -setup {
    .c delete all
    imageCleanup
    update
} -body {
    image create test foo -variable x
    .c create image 50 50 -image foo
    .c create image 90 100 -image foo
    update
    set x {}
    foo changed 5 6 7 8 30 15
    set timer [after 500 {lappend x "timed out"}]
    image create test myimage -variable x
    vwait x
    after cancel $timer
    return $x
} -cleanup {
    .c delete all
    imageCleanup
} -result $result_9_2
} -result {{foo display 5 6 25 9} {foo display 0 0 12 14}}

test image-10.1 {Tk_GetImage procedure} -setup {
    imageCleanup
} -body {
    .c create image 100 10 -image bad_name
} -cleanup {
    imageCleanup
Changes to tests/imgBmap.test.
1
2
3
4
5
6
7



8
9
10
11
12
13
14
1
2
3
4



5
6
7
8
9
10
11
12
13
14




-
-
-
+
+
+







# This file is a Tcl script to test out images of type "bitmap" (i.e.,
# the procedures in the file tkImgBmap.c).  It is organized in the
# standard fashion for Tcl tests.
#
# Copyright (c) 1994 The Regents of the University of California.
# Copyright (c) 1994-1995 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1994 The Regents of the University of California.
# Copyright © 1994-1995 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
namespace import ::tcltest::*
eval tcltest::configure $argv
tcltest::loadTestedCommands
imageInit
133
134
135
136
137
138
139
140

141
142
143
144
145
146

147
148
149
150
151

152
153
154
155
156
157

158
159
160
161

162
163
164
165
166
167
168
169
170

171
172
173
174
175
176
177
178
179

180
181
182
183
184
185
186
133
134
135
136
137
138
139

140
141
142
143
144
145

146
147
148
149
150

151
152
153
154
155
156

157
158
159
160

161
162
163
164
165
166
167
168
169

170
171
172
173
174
175
176
177
178

179
180
181
182
183
184
185
186







-
+





-
+




-
+





-
+



-
+








-
+








-
+







	    [lindex [image1 configure -foreground] 4] \
	    [lindex [image1 configure -background] 4]
} -cleanup {
    image delete image1
} -result {image1 image1 0 0 #000000 {}}


test imageBmap-3.1 {ImgBmapConfigureMaster procedure, memory de-allocation} -body {
test imageBmap-3.1 {ImgBmapConfigureModel procedure, memory de-allocation} -body {
    image create bitmap i1 -data $data1
    i1 configure -data $data1
} -cleanup {
	image delete i1
} -result {}
test imageBmap-3.2 {ImgBmapConfigureMaster procedure} -body {
test imageBmap-3.2 {ImgBmapConfigureModel procedure} -body {
    image create bitmap i1 -data $data1
    list [catch {i1 configure -data bogus} msg] $msg [image width i1] \
	    [image height i1]
} -result {1 {format error in bitmap data} 16 16}
test imageBmap-3.3 {ImgBmapConfigureMaster procedure, memory de-allocation} -body {
test imageBmap-3.3 {ImgBmapConfigureModel procedure, memory de-allocation} -body {
    image create bitmap i1 -data $data1 -maskdata $data2
    i1 configure -maskdata $data2
} -cleanup {
	image delete i1
} -result {}
test imageBmap-3.4 {ImgBmapConfigureMaster procedure} -body {
test imageBmap-3.4 {ImgBmapConfigureModel procedure} -body {
    image create bitmap i1
    i1 configure -maskdata $data2
} -returnCodes error -result {can't have mask without bitmap}
test imageBmap-3.5 {ImgBmapConfigureMaster procedure} -body {
test imageBmap-3.5 {ImgBmapConfigureModel procedure} -body {
    image create bitmap i1 -data $data1 -maskdata {
	#define foo_width 8
	#define foo_height 16
	static char foo_bits[] = {
	   0xff, 0xff, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
	   0x81, 0x81, 0xff, 0xff, 0xff, 0xff, 0x81, 0x81};
	}
} -returnCodes error -result {bitmap and mask have different sizes}
test imageBmap-3.6 {ImgBmapConfigureMaster procedure} -body {
test imageBmap-3.6 {ImgBmapConfigureModel procedure} -body {
    image create bitmap i1 -data $data1 -maskdata {
	#define foo_width 16
	#define foo_height 8
	static char foo_bits[] = {
	   0xff, 0xff, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
	   0x81, 0x81, 0xff, 0xff, 0xff, 0xff, 0x81, 0x81};
	}
} -returnCodes error -result {bitmap and mask have different sizes}
test imageBmap-3.7 {ImgBmapConfigureMaster procedure} -setup {
test imageBmap-3.7 {ImgBmapConfigureModel procedure} -setup {
    destroy .c
    pack [canvas .c]
} -body {
    image create bitmap i1 -data $data1
    .c create image 100 100 -image i1 -tags i1.1 -anchor nw
    .c create image 200 100 -image i1 -tags i1.2 -anchor nw
    update
362
363
364
365
366
367
368
369

370
371
372
373
374
375
376
362
363
364
365
366
367
368

369
370
371
372
373
374
375
376







-
+







    i1 cget -foreground
} -result {#123456}
test imageBmap-7.5 {ImgBmapCmd procedure, "cget" option} -body {
    i1 cget -stupid
} -returnCodes error -result {unknown option "-stupid"}
test imageBmap-7.6 {ImgBmapCmd procedure} -body {
    llength [i1 configure]
} -result {6}
} -result 6
test imageBmap-7.7 {ImgBmapCmd procedure} -body {
    i1 co -foreground #001122
    i1 configure -foreground
} -result {-foreground {} {} #000000 #001122}
test imageBmap-7.8 {ImgBmapCmd procedure} -body {
    i1 configure -gorp
} -returnCodes error -result {unknown option "-gorp"}
499
500
501
502
503
504
505
506
507


508
509
510
511
512
513
514
515
516
517
518
519
520
499
500
501
502
503
504
505


506
507
508
509
510
511
512
513
514
515
516
517
518
519
520







-
-
+
+













    lappend x [info command new*]
} -result {{} newi2 foo.bm {}}


test imageBmap-12.1 {ImgBmapCmdDeletedProc procedure} -body {
    image create bitmap i2 -file foo.bm -maskfile foo2.bm
    rename i2 {}
    list [lsearch -exact [imageNames] i2] [catch {i2 foo} msg] $msg
} -result {-1 1 {invalid command name "i2"}}
    list [expr {"i2" in [imageNames]}] [catch {i2 foo} msg] $msg
} -result {0 1 {invalid command name "i2"}}

removeFile foo.bm
removeFile foo2.bm
imageFinish

# cleanup
cleanupTests
return

# Local Variables:
# mode: tcl
# fill-column: 78
# End:
Added tests/imgListFormat.test.





















































































































































































































































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# This file is a Tcl script to test out the default image data format
# ("list format") implementend in the file tkImgListFormat.c.
# It is organized in the standard fashion for Tcl tests.
#
# Copyright © 2017 Simon Bachmann
# All rights reserved.
#
# Author: Simon Bachmann ([email protected])

package require tcltest 2.2
namespace import ::tcltest::*
tcltest::configure {*}$argv
tcltest::loadTestedCommands

imageInit

# find the teapot.ppm file for use in these tests
set teapotPhotoFile [file join [file dirname [info script]] teapot.ppm]
testConstraint hasTeapotPhoto [file exists $teapotPhotoFile]
# let's see if we have the semi-transparent one as well
set transpTeapotPhotoFile [file join [file dirname [info script]] teapotTransparent.png]
testConstraint hasTranspTeapotPhoto [file exists $transpTeapotPhotoFile]

# ---------------------------------------------------------------------


test imgListFormat-1.1 {ParseFormatOptions: default values} -setup {
    image create photo photo1
} -body {
    photo1 put {{red green} {blue black}}
    lindex [photo1 data] 1 1
} -cleanup {
    imageCleanup
} -result {#000000}
test imgListFormat-1.2 {ParseFormatOptions: format name as first arg} -setup {
    image create photo photo1
} -body {
    photo1 put #1256ef -format {default} -to 0 0 10 10
} -cleanup {
    imageCleanup
} -result {}
test imgListFormat-1.3 {ParseFormatOptions: unknown option} -setup {
    image create photo photo1
} -body {
    photo1 data -format {default -bogus}
} -cleanup {
    imageCleanup
} -returnCodes error -result {bad format option "-bogus": must be -colorformat}
test imgListFormat-1.4 {ParseFormatOptions: option not allowed} -setup {
    image create photo photo1
} -body {
    photo1 put yellow -format {default -colorformat rgb}
} -cleanup {
    imageCleanup
} -returnCodes error -result \
    {bad format option "-colorformat": no options allowed}
test imgListFormat-1.5 {ParseFormatOptions: no -colorformat value} -setup {
    image create photo photo1 -data black
} -body {
    photo1 data -format {default -colorformat}
} -returnCodes error -result {the "-colorformat" option requires a value}
test imgListFormat-1.6 {ParseFormatOptions: bad -colorformat val #1} -setup {
    image create photo photo1
} -body {
    photo1 put yellow
    photo1 data -format {default -colorformat bogus}
} -cleanup {
    imageCleanup
} -returnCodes error -result \
    {bad color format "bogus": must be rgb, rgba, or list}
test imgListFormat-1.7 {ParseFormatOptions: bad -colorformat val #2} -setup {
    image create photo photo1
} -body {
    photo1 data -format {default -colorformat tkcolor}
} -returnCodes error -result \
    {bad color format "tkcolor": must be rgb, rgba, or list}
test imgListFormat-1.8 {ParseFormatOptions: bad -colorformat #3} -setup {
    image create photo photo1
} -body {
    photo1 data -format {default -colorformat emptystring}
} -returnCodes error -result \
    {bad color format "emptystring": must be rgb, rgba, or list}
test imgListFormat-1.9 {ParseFormatOptions: bad -colorformat #4} -setup {
    image create photo photo1
} -body {
    photo1 data -format {default -colorformat rgb-short}
} -cleanup {
    imageCleanup
} -returnCodes error -result \
    {bad color format "rgb-short": must be rgb, rgba, or list}
test imgListFormat-1.10 {ParseFormatOptions: bad -colorformat #5} -setup {
    image create photo photo1
} -body {
    photo1 data -format {default -colorformat rgba-short}
} -returnCodes error -result \
    {bad color format "rgba-short": must be rgb, rgba, or list}
test imgListFormat-1.11 {valid colorformats} -setup {
    image create photo photo1
} -body {
    photo1 put white#78
    set result {}
    lappend result [photo1 data -format {default -colorformat rgb}]
    lappend result [photo1 data -format {default -colorformat rgba}]
    lappend result [photo1 data -format {default -colorformat list}]
    set result
} -cleanup {
    imageCleanup
    unset result
} -result {{{#ffffff}} {{#ffffff78}} {{{255 255 255 120}}}}

# GetBadOptMsg: only use case already tested with imgListFormat-1.4

test imgListFormat-3.1 {StringMatchDef: data is not a list} -body {
    testphotostringmatch {not a " proper list}
    # " (this comment is here only for editor highlighting)
} -returnCodes error -result {unmatched open quote in list}
# empty data case tested with imgPhoto-4.95 (imgPhoto.test)
test imgListFormat-3.2 {StringMatchDef: \
        list element not a proper list} -body {
    testphotostringmatch {{red white} {not "} {blue green}}
    # "
} -returnCodes error -result {unmatched open quote in list}
test imgListFormat-3.3 {StringMatchDef: \
        sublists with differen lengths} -body {
    testphotostringmatch {{#001122 #334455 #667788}
		{#99AABB #CCDDEE}
		{#FF0011 #223344 #556677}}
} -returnCodes error -result \
    {invalid row # 1: all rows must have the same number of elements}
test imgListFormat-3.4 {StringMatchDef: base64 data is not parsed as valid \
} -setup {
    image create photo photo1
} -body {
    photo1 put {
	iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCA
	YAAAEFsT2yAAAABGdBTUEAAYagMeiWXwAA
	ABdJREFUCJkFwQEBAAAAgiD6P9pACRoqDk
	fUBvt1wUFKAAAAAElFTkSuQmCC
    } -format default
} -cleanup {
    imageCleanup
} -returnCodes error -result {invalid color name "iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCA"}
test imgListFormat-3.5 {StringMatchDef: valid data} -setup {
    image create photo photo1
} -body {
    photo1 put {{blue green}
		{yellow magenta}
	        {#000000 #FFFFFFFF}}
    list [image width photo1] [image height photo1] \
	[photo1 get 0 2 -withalpha]
} -cleanup {
    imageCleanup
} -result {2 3 {0 0 0 255}}

# ImgStringRead: most of the error cases cannot be tested with current code,
# as the errors are detected by StringMatchDef
test imgListFormat-4.1 {StringReadDef: use with -format opt} -setup {
    image create photo photo1
} -body {
    photo1 put white -format "default"
    photo1 get 0 0
} -cleanup {
    imageCleanup
} -result {255 255 255}
test imgListFormat-4.2 {StringReadDef: suboptions to format} -setup {
    image create photo photo1
} -body {
    photo1 put white -format {default -bogus}
} -cleanup {
    imageCleanup
} -returnCodes error -result \
    {bad format option "-bogus": no options allowed}
test imgListFormat-4.3 {StringReadDef: erroneous non-option argument} -setup {
    image create photo photo1
} -body {
    photo1 put orange -format {default bogus}
} -returnCodes error -result {bad format option "bogus": no options allowed}
test imgListFormat-4.4 {StringReadDef: normal use case} -constraints {
    hasTeapotPhoto
} -setup {
    image create photo photo1 -file $teapotPhotoFile
    image create photo photo2
} -body {
    set imgData [photo1 data]
    photo2 put $imgData
    string equal [photo1 data] [photo2 data]
} -cleanup {
    imageCleanup
    unset imgData
} -result 1
test imgListFormat-4.5 {StringReadDef: correct compositing rule} -constraints {
    hasTranspTeapotPhoto
} -setup {
    image create photo photo1 -file $transpTeapotPhotoFile
    image create photo photo2
} -body {
    photo2 put #FF0000 -to 0 0 50 50
    photo2 put [photo1 data -format {default -colorformat rgba}] -to 10 10 40 40
    list [photo2 get 0 0 -withalpha] [photo2 get 20 25 -withalpha] \
	[photo2 get 49 49 -withalpha]
} -cleanup {
    imageCleanup
} -result {{255 0 0 255} {0 78 185 225} {255 0 0 255}}

test imgListFormat-5.1 {StringWriteDef: format options not a list} -setup {
    image create photo photo1
} -body {
    photo1 data -format {default " bogus}
    # "
} -cleanup {
    imageCleanup
} -returnCodes error -result {unmatched open quote in list}
test imgListFormat-5.2 {StringWriteDef: invalid format option} -setup {
    image create photo photo1
} -body {
    photo1 data -format {default -bogus}
} -cleanup {
    imageCleanup
} -returnCodes error -result {bad format option "-bogus": must be -colorformat}
test imgListFormat-5.3 {StringWriteDef: non-option arg in format} -setup {
    image create photo photo1
} -body {
    photo1 data -format {default -colorformat list bogus}
} -cleanup {
    imageCleanup
} -returnCodes error -result {bad format option "bogus": must be -colorformat}
test imgListFormat-5.4 {StringWriteDef: empty image} -setup {
    image create photo photo1
} -body {
    photo1 data -format {default -colorformat rgba}
} -cleanup {
    imageCleanup
} -result {}
test imgListFormat-5.5 {StirngWriteDef: size of data} -setup {
    image create photo photo1
} -body {
    photo1 put blue -to 0 0 35 64
    set imgData [photo1 data]
    list [llength [lindex $imgData 0]] [llength $imgData]
} -cleanup {
    unset imgData
    imageCleanup
} -result {35 64}
test imgListFormat-5.6 {StringWriteDef: test some pixels #1} -constraints {
    hasTeapotPhoto
} -setup {
    set result {}
    image create photo photo1 -file $teapotPhotoFile
} -body {
    set imgData [photo1 data]
    # note: with [lindex], the coords are inverted (y x)
    lappend result [lindex $imgData 0 0]
    lappend result [lindex $imgData 3 2]
    lappend result [lindex $imgData 107 53]
    lappend result [lindex $imgData 203 157]
    lappend result [lindex $imgData 255 255]
    set result
} -cleanup {
    unset result
    unset imgData
    imageCleanup
} -result {{#135cc0} #135cc0 #a06d52 #e1c8ba #135cc0}
test imgListFormat-5.7 {StringWriteDef: test some pixels #2} -constraints {
    hasTeapotPhoto
} -setup {
    set result {}
    image create photo photo1 -file $teapotPhotoFile
} -body {
    set imgData [photo1 data -format {default -colorformat rgba}]
    # note: with [lindex], the coords are inverted (y x)
    lappend result [lindex $imgData 0 0]
    lappend result [lindex $imgData 3 2]
    lappend result [lindex $imgData 107 53]
    lappend result [lindex $imgData 203 157]
    lappend result [lindex $imgData 255 255]
    set result
} -cleanup {
    unset result
    unset imgData
    imageCleanup
} -result {{#135cc0ff} #135cc0ff #a06d52ff #e1c8baff #135cc0ff}
test imgListFormat-5.8 {StringWriteDef: test some pixels #3} -constraints {
    hasTranspTeapotPhoto
} -setup {
    image create photo photo1 -file $transpTeapotPhotoFile
} -body {
    set imgData [photo1 data -format {default -colorformat rgb}]
    set result {}
    lappend result [lindex $imgData 3 2]
    lappend result [lindex $imgData 107 53]
    lappend result [lindex $imgData 203 157]
    set result
} -cleanup {
    unset result
    unset imgData
    imageCleanup
} -result {{#004eb9} #a14100 #ffca9f}
test imgListFormat-5.9 {StringWriteDef: test some pixels #4} -constraints {
    hasTranspTeapotPhoto
} -setup {
    image create photo photo1 -file $transpTeapotPhotoFile
} -body {
    set imgData [photo1 data -format {default -colorformat rgba}]
    set result [lindex $imgData 3 2]
    lappend result [lindex $imgData 107 53]
    lappend result [lindex $imgData 203 157]
    set result
} -cleanup {
    unset result
    unset imgData
    imageCleanup
} -result {{#004eb9e1} #a14100aa #ffca9faf}
test imgListFormat-5.10 {StringWriteDef: test some pixels #5} -constraints {
    hasTranspTeapotPhoto
} -setup {
    image create photo photo1 -file $transpTeapotPhotoFile
} -body {
    set imgData [photo1 data -format {default -colorformat list}]
    set result {}
    lappend result [lindex $imgData 3 2]
    lappend result [lindex $imgData 107 53]
    lappend result [lindex $imgData 203 157]
    set result
} -cleanup {
    unset imgData
    unset result
    imageCleanup
} -result {{0 78 185 225} {161 65 0 170} {255 202 159 175}}

test imgListFormat-6.1 {ParseColor: empty string} -setup {
    image create photo photo1
    set result {}
} -body {
    photo1 put {{"" ""} {"" ""}}
    lappend result [image width photo1]
    lappend result [image height photo1]
    lappend result [photo1 get 1 1 -withalpha]
    set result
} -cleanup {
    unset result
    imageCleanup
} -result {2 2 {0 0 0 0}}
test imgListFormat-6.2 {ParseColor: empty string, mixed} -setup {
    image create photo photo1
} -body {
    photo1 put {{black white} {{} white}}
    list [photo1 get 0 0 -withalpha] [photo1 get 0 1 -withalpha]
} -cleanup {
    imageCleanup
} -result {{0 0 0 255} {0 0 0 0}}
test imgListFormat-6.3 {ParseColor: color name too long} -setup {
    image create photo photo1
    set longstr {}
    for {set i 1} {$i <= 100} {incr i} {
        append longstr "z"
    }
} -body {
    photo1 put [list [list blue] [list $longstr]]
} -cleanup {
    imageCleanup
    unset longstr
} -returnCodes error -result {invalid color}
test imgListFormat-6.4 {ParseColor: #XXX color, different forms} -setup {
    image create photo photo1
} -body {
    photo1 put {{#A123 #334455} {#012 #fffefd#00}}
    photo1 data -format {default -colorformat rgba}
} -cleanup {
    imageCleanup
} -result {{#aa112233 #334455ff} {#001122ff #fffefd00}}
test imgListFormat-6.5 {ParseColor: list format} -setup {
    image create photo photo1
} -body {
    photo1 put [list [list [list 255 255 255]]]
    photo1 get 0 0 -withalpha
} -cleanup {
    imageCleanup
} -result {255 255 255 255}
test imgListFormat-6.6 {ParseColor: string format} -setup {
    image create photo photo1
} -body {
    photo1 put [list [list [list white]]]
    photo1 get 0 0 -withalpha
} -cleanup {
    imageCleanup
} -result {255 255 255 255}
test imgListFormat-6.7 {ParseColor: invalid color} -setup {
    image create photo photo1
} -body {
    photo1 put {{blue red} {green bogus}}
} -cleanup {
    imageCleanup
} -returnCodes error -result {invalid color name "bogus"}
test imgListFormat-6.8 {ParseColor: overall test} -setup {
    image create photo photo1
    set result {}
} -body {
    photo1 put {
		{[email protected] snow#80 snow#8 #[email protected] #fffffabbfacc#8}
		{#fffffafffaff#80 #[email protected] #ffffaafaa#8 #ffffaafaa#80 #fee#8}
		{#fee#80 #[email protected] #[email protected] #fffafa#8 #fffafa#80}
		{{0xff 250 0xfa 128} {255 250 250} #fee8 #fffafa80 snow}}
    for {set y 0} {$y < 4} {incr y} {
		for {set x 0} {$x < 5} {incr x} {
			lappend result [photo1 get $x $y -withalpha]
		}
    }
    set result
} -cleanup {
    imageCleanup
    unset result
} -result \
{{255 250 250 128} {255 250 250 128} {255 250 250 136} {255 250 250 128}\
{255 250 250 136} {255 250 250 128} {255 250 250 128} {255 250 250 136}\
{255 250 250 128} {255 238 238 136} {255 238 238 128} {255 238 238 128}\
{255 250 250 128} {255 250 250 136} {255 250 250 128} {255 250 250 128}\
{255 250 250 255} {255 238 238 136} {255 250 250 128} {255 250 250 255}}

# Note: these tests were written for an earlier implementation of
# ParseColorAsList. For this reason, their order and layout do not follow the
# current code very well. Test coverage is pretty good, nevertheless.
test imgListFormat-7.1 {ParseColorAsList: invalid list} -setup {
    image create photo photo1
} -body {
    photo1 put {{{123 45 67 89} {123 45 " 67}}}
	#"
} -cleanup {
    imageCleanup
} -returnCodes error -result {invalid color name "123 45 " 67"}
#"
test imgListFormat-7.2 {ParseColorAsList: too few elements in list} -setup {
    image create photo photo1
} -body {
    photo1 put {{{0 255 0 255} {0 255}}}
} -cleanup {
    imageCleanup
} -returnCodes error -result {invalid color name "0 255"}
test imgListFormat-7.3 {ParseColorAsList: too many elements in list} -setup {
    image create photo photo1
} -body {
    photo1 put {{{0 100 200 255} {0 100 200 255 0}}}
} -returnCodes error -result {invalid color name "0 100 200 255 0"}
test imgListFormat-7.4 {ParseColorAsList: not an integer value} -setup {
    image create photo photo1
} -body {
    photo1 put {{{9 0xf3 87 65} {43 21 10 1.0}}}
} -cleanup {
    imageCleanup
} -returnCodes error -result {invalid color name "43 21 10 1.0"}
test imgListFormat-7.5 {ParseColorAsList: negative value in list} -setup {
    image create photo photo1
} -body {
    photo1 put {{{121 121 121} {121 121 -1}}}
} -cleanup {
    imageCleanup
} -returnCodes error -result {invalid color name "121 121 -1"}
test imgListFormat-7.6 {ParseColorAsList: value in list too large} -setup {
    image create photo photo1
} -body {
    photo1 put {{{0 1 2 3} {254 255 256}}}
} -cleanup {
    imageCleanup
} -returnCodes error -result {invalid color name "254 255 256"}
test imgListFormat-7.7 {ParseColorAsList: suffix not allowed} -setup {
    image create photo photo1
} -body {
    photo1 put {{{100 100 100} {100 100 100#FE}}}
} -cleanup {
    imageCleanup
} -returnCodes error -result {invalid color name "100 100 100#FE"}
test imgListFormat-7.8 {ParseColorAsList: valid list form} -setup {
    image create photo photo1
} -body {
    photo1 put {{{0x0 0x10 0xfe 0xff} {0 100 254}}
		{{30 30 30 0} {1 1 254 1}}}
    list [photo1 get 0 0 -withalpha] [photo1 get 1 0 -withalpha] \
	[photo1 get 0 1 -withalpha] [photo1 get 1 1 -withalpha]
} -cleanup {
    imageCleanup
} -result {{0 16 254 255} {0 100 254 255} {30 30 30 0} {1 1 254 1}}
test imgListFormat-7.9 {ParseColorAsList: additional spaces in list} -setup {
    image create photo photo1
} -body {
    photo1 put { { { 1 2 3} {1  2	 3} } { {1 2 3  } {  1  2  3   4  }  } }
    photo1 data -format {default -colorformat rgba}
} -cleanup {
    imageCleanup
} -result {{#010203ff #010203ff} {#010203ff #01020304}}
test imgListFormat-7.10 {ParseColorAsList: list format, string rep} -setup {
	image create photo photo1
} -body {
	photo1 put {{"111 222 33 44"}}
	photo1 get 0 0 -withalpha
} -cleanup {
	imageCleanup
} -result {111 222 33 44}

test imgListFormat-8.1 {ParseColorAsHex: RGB format} -setup {
    image create photo photo1
} -body {
    photo1 put {{#010 #001100}}
    photo1 data
} -cleanup {
    imageCleanup
} -result {{#001100 #001100}}
test imgListFormat-8.2 {ParseColorAsHex: invalid hex digit} -setup {
    image create photo photo1
} -body {
    photo1 put {#ABCD #ABCZ}
} -cleanup {
    imageCleanup
} -returnCodes error -result {invalid color name "#ABCZ"}
test imgListFormat-8.3 {ParseColorAsHex: RGB with suffix, 8 chars} -setup {
    image create photo photo1
} -body {
    photo1 put {{#FFfFFf #AbCdef#0}}
    photo1 data
} -cleanup {
    imageCleanup
} -result {{#ffffff #abcdef}}
test imgListFormat-8.4 {ParseColor: valid #RGBA color} -setup {
    image create photo photo1
} -body {
    photo1 put {{#9bd5020d #7acF}}
    list [photo1 get 0 0 -withalpha] [photo1 get 1 0 -withalpha]
} -cleanup {
    imageCleanup
} -result {{155 213 2 13} {119 170 204 255}}

test imgListFormat-9.1 {ParseColorAsStandard:
        Tk color, valid suffixes} -setup {
    image create photo photo1
    set result {}
} -body {
    photo1 put {{[email protected] #114433#C} {#8D4#1A magenta}}
    lappend result [photo1 get 0 0 -withalpha]
    lappend result [photo1 get 1 0 -withalpha]
    lappend result [photo1 get 0 1 -withalpha]
    lappend result [photo1 get 1 1 -withalpha]
    set result
} -cleanup {
    unset result
    imageCleanup
} -result {{0 0 255 181} {17 68 51 204} {136 221 68 26} {255 0 255 255}}
test imgListFormat-9.2 {ParseColorAsStandard:
        Tk color with and w/o suffixes} -setup {
    image create photo photo1
    set result {}
} -body {
    photo1 put {{#52D8a0 #2B5} {#[email protected] maroon#4}}
    lappend result [photo1 get 0 0 -withalpha]
    lappend result [photo1 get 1 0 -withalpha]
    lappend result [photo1 get 0 1 -withalpha]
    lappend result [photo1 get 1 1 -withalpha]
    set result
} -cleanup {
    unset result
    imageCleanup
} -result {{82 216 160 255} {34 187 85 255} {238 68 119 3} {128 0 0 68}}
test imgListFormat-9.3 {ParseColorAsStandard: wrong digit count} -setup {
    image create photo photo1
} -body {
    photo1 put {{#000 #00}}
} -returnCodes error -result {invalid color name "#00"}
test imgListFormat-9.4 {ParseColorAsStandard: @A suffix, not a float} -setup {
    image create photo photo1
} -body {
    photo1 put {{[email protected] blue@bogus}}
} -cleanup {
    imageCleanup
} -returnCodes error -result \
    {invalid alpha suffix "@bogus": expected floating-point value}
test imgListFormat-9.5 {ParseColorAsStandard: @A, value too low} -setup {
    image create photo photo1
} -body {
    photo1 put {[email protected] [email protected]}
} -cleanup {
    imageCleanup
} -returnCodes error -result \
    {invalid alpha suffix "@-0.1": value must be in the range from 0 to 1}
test imgListFormat-9.6 {ParseColorAsStandard: @A, value too high} -setup {
    image create photo photo1
} -body {
    photo1 put {#000000@0 #[email protected]}
} -cleanup {
    imageCleanup
} -returnCodes error -result \
    {invalid alpha suffix "@1.0001": value must be in the range from 0 to 1}
test imgListFormat-9.7 {ParseColorAsStandard: @A suffix, edge values} -setup {
    imageCleanup
    image create photo photo1
} -body {
    photo1 put {{yellow@1e-22 [email protected] [email protected] \
		 [email protected]}}
    list [photo1 get 0 0 -withalpha] [photo1 get 1 0 -withalpha] \
	[photo1 get 2 0 -withalpha] [photo1 get 3 0 -withalpha]
} -cleanup {
    imageCleanup
} -result {{255 255 0 0} {255 255 0 31} {255 255 0 32} {255 255 0 255}}
test imgListFormat-9.8 {ParseColorAsStandard: # suffix, no hex digits} -setup {
    image create photo photo1
} -body {
    photo1 put {{black#f} {black#}}
} -cleanup {
    imageCleanup
} -returnCodes error -result {invalid alpha suffix "#"}
test imgListFormat-9.9 {ParseColorAsStandard:
        '#' suffix, too many digits} -setup {
    image create photo photo1
} -body {
    photo1 put {{#ABC#12 #ABC#123}}
} -cleanup {
    imageCleanup
} -returnCodes error -result {invalid alpha suffix "#123"}
test imgListFormat-9.10 {ParseColorAsStandard:
        invalid digit in #X suffix} -setup {
    image create photo photo1
} -body {
    photo1 put {#000#a #000#g}
} -cleanup {
    imageCleanup
} -returnCodes error -result {invalid alpha suffix "#g": expected hex digit}
test imgListFormat-9.11 {ParseColorAsStandard:
        invalid digit in #XX suffix} -setup {
    image create photo photo1
} -body {
    photo1 put {green#2 green#2W}
} -cleanup {
    imageCleanup
} -returnCodes error -result {invalid alpha suffix "#2W": expected hex digit}
test imgListFormat-9.12 {ParseColorAsStandard:
        invalid color: not a hex digit} -setup {
    image create photo photo1
} -body {
    photo1 put {#[email protected] #[email protected]}
} -cleanup {
    imageCleanup
} -returnCodes error -result {invalid color name "#[email protected]"}
test imgListFormat-9.13 {ParseColorAsStandard: suffix not allowed #1} -setup {
    image create photo photo1
} -body {
    photo1 put {#[email protected] #[email protected]}
} -cleanup {
    imageCleanup
} -returnCodes error -result {invalid color name "#[email protected]"}
test imgListFormat-9.14 {ParseColorAsStandard: suffix not allowed #2} -setup {
    image create photo photo1
} -body {
    photo1 put {#1111 #1111#1}
} -cleanup {
    imageCleanup
} -returnCodes error -result {invalid color name "#1111#1"}


# ---------------------------------------------------------------------

imageFinish

# cleanup
cleanupTests
return
Changes to tests/imgPNG.test.
1
2
3
4
5
6
7
8




9
10
11
12
13
14
15
1
2
3
4




5
6
7
8
9
10
11
12
13
14
15




-
-
-
-
+
+
+
+







# This file is a Tcl script to test out the code in tkImgFmtPNG.c, which reads
# and write PNG-format image files for photo widgets. The files is organized
# in the standard fashion for Tcl tests.
#
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright (c) 1998 Willem van Schaik (images only)
# Copyright (c) 2008 Donal K. Fellows
# Copyright © 1994-1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# Copyright © 1998 Willem van Schaik (images only)
# Copyright © 2008 Donal K. Fellows
# All rights reserved.

package require tcltest 2.2
namespace import ::tcltest::*
eval tcltest::configure $argv
tcltest::loadTestedCommands
imageInit
1109
1110
1111
1112
1113
1114
1115
1116

1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1109
1110
1111
1112
1113
1114
1115

1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127







-
+











} -body {
    # the image contains an unknown chunk iDOT
    # since the name of this chunk starts with a lowercase letter,
    # it's an ancillary chunk that shall not trigger an error
    catch {set i [image create photo -file $fileName]}
} -cleanup {
    image delete $i
} -result {0}
} -result 0

}
namespace delete png
imageFinish
cleanupTests
return

# Local Variables:
# mode: tcl
# fill-column: 78
# End:
Changes to tests/imgPPM.test.
1
2
3
4
5
6


7
8
9
10
11
12
13
1
2
3
4


5
6
7
8
9
10
11
12
13




-
-
+
+







# This file is a Tcl script to test out the code in tkImgFmtPPM.c,
# which reads and write PPM-format image files for photo widgets.
# The files is organized in the standard fashion for Tcl tests.
#
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1994-1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
namespace import ::tcltest::*
eval tcltest::configure $argv
tcltest::loadTestedCommands

Changes to tests/imgPhoto.test.
1
2
3
4
5
6
7
8




9
10
11




































































12
13
14
15
16
17
18



19
20

21
22
23
24
25
26
27
1
2
3
4




5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84


85
86
87


88
89
90
91
92
93
94
95




-
-
-
-
+
+
+
+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
-
+
+
+
-
-
+







# This file is a Tcl script to test out the "photo" image type and the other
# procedures in the file tkImgPhoto.c. It is organized in the standard fashion
# for Tcl tests.
#
# Copyright (c) 1994 The Australian National University
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright (c) 2002-2008 Donal K. Fellows
# Copyright © 1994 The Australian National University
# Copyright © 1994-1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# Copyright © 2002-2008 Donal K. Fellows
# All rights reserved.
#
# Author: Paul Mackerras ([email protected])

#
# This file is somewhat caothic: the order of the tests does not
# really follow the order of the corresponding functions in
# tkImgPhoto.c. Probably, because early versions had only a few tests
# and over time test cases were added in bits and pieces.
# To be noted, also, that this file is not complete: large portions of
# code in tkImgPhoto.c have no test coverage.
#
# To help keeping the overview, the table below lists where to find
# tests for each of the functions in tkImgPhoto.c. The function are
# listed in the order as they appear in the source file.
#

#
# Function name                         Tests for function
#--------------------------------------------------------------------------
# PhotoFormatThreadExitProc             no tests
# Tk_Create*PhotoImageFormat            no tests
# ImgPhotoCreate                        imgPhoto-2.*
# ImgPhotoCmd                           imgPhoto-4.*, imgPhoto-17.*
# GetExtension:                         no tests
# ParseSubcommandOptions:               imgPhoto-1.*
# ImgPhotoConfigureModel:              imgPhoto-3.*, imgPhoto-15.*
# toggleComplexAlphaIfNeeded:           no tests
# ImgPhotoDelete:                       imgPhoto-8.*
# ImgPhotoCmdDeleteProc:                imgPhoto-9.*
# ImgPhotoSetSize:                      no tests
# MatchFileFormat:                      imgPhoto-18.*
# MatchSringFormat:                     imgPhoto-19.*
# Tk_FindPhoto:                         imgPhoto-11.*
# Tk_PhotoPutBlock:                     imgPhoto-10.*, imgPhoto-16.*
# Tk_PhotoPutZoomedBlock:               imgPhoto-12.*
# Tk_DitherPhoto:                       no tets
# Tk_PhotoBlank:                        no tests
# Tk_PhotoExpand:                       no tests
# Tk_PhotoGetSize:                      no tests
# Tk_PhotoSetSize:                      no tests
# TkGetPhotoValidRegion:                no tests
# ImgGetPhoto:                          no tests
# Tk_PhotoGetImage                      no tests
# ImgPostscriptPhoto                    no tests
# Tk_PhotoPutBlock_NoComposite          no tests, probably none needed
# Tk_PhotoPutZoomedBlock_NoComposite    no tests, probably none needed
# Tk_PhotoExpand_Panic                  no tests, probably none needed
# Tk_PhotoPutBlock_Panic                no tests, probably none needed
# Tk_PhotoPutZoomedBlock_Panic          no tests, probably none needed
# Tk_PhotoSetSize_Panic                 no tests, probably none needed
#--------------------------------------------------------------------------
#

#
# Some tests are not specific to a function in tkImgPhoto.c. They are:
#

#
# Test name(s)          Description
#--------------------------------------------------------------------------
# imgPhoto-5.*          Do not really belong to this file. ImgPhotoGet and
#                       ImgPhotoFree are defined in tkImgPhInstance.c.
# imgPhoto-6.*          Do not really belong to this file. ImgPhotoDisplay
#                       is defined in tkImgPhInstance.c.
# imgPhoto-7.*          Do not really belong to this file. ImgPhotoFree is
#                       defined in tkImgPhInstance.c.
# imgPhoto-13.*         Tests for separation in different interpreters
# imgPhoto-14.*         Test GIF format. Would belong to imgGIF.test
#                       - which does not exist.
#

package require tcltest 2.2
namespace import ::tcltest::*
tcltest::configure {*}$argv
tcltest::loadTestedCommands

# Used for 4.65 - 4.73 tests

#
# Used for imgPhoto-4.65 - imgPhoto-4.73
# Now for some heftier testing, checking that setting and resetting of pixels'
# transparency status doesn't "leak" with any one-off errors.
#
proc foreachPixel {img xVar yVar script} {
    upvar 1 $xVar x $yVar y
    set width [image width $img]
    set height [image height $img]
    for {set x 0} {$x<$width} {incr x} {
	for {set y 0} {$y<$height} {incr y} {
	    uplevel 1 $script
54
55
56
57
58
59
60
61
62
63
64
65





66
67
68
69
70
71
72
73
74
75
122
123
124
125
126
127
128





129
130
131
132
133



134
135
136
137
138
139
140







-
-
-
-
-
+
+
+
+
+
-
-
-







set README [makeFile {
    README -- Tk test suite design document.
} README-imgPhoto]

# find the teapot.ppm file for use in these tests
set teapotPhotoFile [file join [file dirname [info script]] teapot.ppm]
testConstraint hasTeapotPhoto [file exists $teapotPhotoFile]

proc base64ok {} {
    expr {
        ![catch {package require base64}]
    }
# let's see if we have the semi-transparent one as well
set transpTeapotPhotoFile [file join [file dirname [info script]] teapotTransparent.png]
testConstraint hasTranspTeapotPhoto [file exists $transpTeapotPhotoFile]
testConstraint needsTcl867 [package vsatisfies [package provide Tcl] 8.6.7-]

}

testConstraint base64PackageNeeded [base64ok]

test imgPhoto-1.1 {options for photo images} -body {
    image create photo photo1 -width 79 -height 83
    list [photo1 cget -width] [photo1 cget -height] \
	[image width photo1] [image height photo1]
} -cleanup {
    image delete photo1
111
112
113
114
115
116
117
















118

119
120
121
122
123
124
125
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198

199
200
201
202
203
204
205
206







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+







} -returnCodes error -result {value for "-format" missing}
test imgPhoto-1.10 {options for photo images - error case} -body {
    image create photo -data
} -returnCodes error -result {value for "-data" missing}
test imgPhoto-1.11 {options for photo images - error case} -body {
    image create photo photo1 -format
} -returnCodes error -result {value for "-format" missing}
test imgPhoto-1.12 {option -alpha, normal use} -setup {
    image create photo photo1
} -body {
    photo1 put "white" -to 0 0
    photo1 transparency get 0 0 -alpha
} -cleanup {
    imageCleanup
} -result 255
test imgPhoto-1.13 {option -withalpha, normal use} -setup {
    image create photo photo1
} -body {
    photo1 put {{blue green}}
    photo1 get 1 0 -withalpha
} -cleanup {
    imageCleanup
} -result {0 128 0 255}


test imgPhoto-2.1 {ImgPhotoCreate procedure} -setup {
    imageCleanup
} -body {
    catch {image create photo -blah blah}
    imageNames
} -result {}
test imgPhoto-2.2 {ImgPhotoCreate procedure} -setup {
134
135
136
137
138
139
140
141
142


143
144
145
146
147
148
149
150

151
152
153
154
155
156
157
158
159

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176


































177

178
179
180
181
182
183
184
215
216
217
218
219
220
221


222
223
224
225
226
227
228
229
230

231
232
233
234
235
236
237
238
239

240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291

292
293
294
295
296
297
298
299







-
-
+
+







-
+








-
+

















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+







# test imgPhoto-2.3 {ImgPhotoCreate procedure: creation failure} {
#     image create photo photo1
#     image create photo photo2 -width 10 -height 10
#     catch {image create photo photo2 -file bogus.img} msg
#     photo1 copy photo2
#     set msg
# } {couldn't open "bogus.img": no such file or directory}

test imgPhoto-3.1 {ImgPhotoConfigureMaster procedure} -constraints {

test imgPhoto-3.1 {ImgPhotoConfigureModel procedure} -constraints {
    hasTeapotPhoto
} -body {
    image create photo photo1 -file $teapotPhotoFile
    photo1 configure -file $teapotPhotoFile
} -cleanup {
    image delete photo1
} -result {}
test imgPhoto-3.2 {ImgPhotoConfigureMaster procedure} -constraints {
test imgPhoto-3.2 {ImgPhotoConfigureModel procedure} -constraints {
    hasTeapotPhoto
} -body {
    image create photo photo1 -file $teapotPhotoFile
    list [catch {photo1 configure -file bogus} err] [string tolower $err] \
	[image width photo1] [image height photo1]
} -cleanup {
    image delete photo1
} -result {1 {couldn't open "bogus": no such file or directory} 256 256}
test imgPhoto-3.3 {ImgPhotoConfigureMaster procedure} -constraints {
test imgPhoto-3.3 {ImgPhotoConfigureModel procedure} -constraints {
    hasTeapotPhoto
} -setup {
    destroy .c
    pack [canvas .c]
    update
} -body {
    image create photo photo1
    .c create image 10 10 -image photo1 -tags photo1.1 -anchor nw
    .c create image 300 10 -image photo1 -tags photo1.2 -anchor nw
    update
    photo1 configure -file $teapotPhotoFile
    update
    list [image width photo1] [image height photo1] [.c bbox photo1.1] [.c bbox photo1.2]
} -cleanup {
    destroy .c
    image delete photo1
} -result {256 256 {10 10 266 266} {300 10 556 266}}
test imgPhoto-3.4 {ImgPhotoConfigureModel: -data <ppm>} -constraints {
    hasTeapotPhoto
} -setup {
    image create photo photo1 -file $teapotPhotoFile
    image create photo photo2
} -body {
    photo2 configure -data [photo1 data -format ppm -from 100 100 120 120]
    list [image width photo2] [image height photo2]
} -cleanup {
    imageCleanup
} -result {20 20}
# This testcase fails with Tcl < 8.6.7, due to [25842c]
test imgPhoto-3.5 {ImgPhotoConfigureModel: -data <png>} -constraints {
    hasTeapotPhoto needsTcl867
} -setup {
    image create photo photo1 -file $teapotPhotoFile
    image create photo photo2
} -body {
    photo2 configure -data [photo1 data -format png -from 120 120 140 140]
    list [image width photo2] [image height photo2]
} -cleanup {
    imageCleanup
} -result {20 20}
test imgPhoto-3.6 {ImgPhotoConfigureModel: -data <default>} -constraints {
    hasTeapotPhoto
} -setup {
    image create photo photo1 -file $teapotPhotoFile
    image create photo photo2
} -body {
    photo2 configure -data [photo1 data -from 80 90 100 110]
    list [image width photo2] [image height photo2]
} -cleanup {
    imageCleanup
} -result {20 20}


test imgPhoto-4.1 {ImgPhotoCmd procedure} -setup {
    image create photo photo1
} -body {
    photo1
} -returnCodes error -cleanup {
    image delete photo1
} -result {wrong # args: should be "photo1 option ?arg ...?"}
369
370
371
372
373
374
375

376
377

378
379
380
381
382




383
384
385

386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403

404
405
406



407
408
409
410
411
412
413
414
415
416
417
418
419
420

421
422
423
424
425
426
427

428
429
430


431




432
433
434
435

436
437
438
439
440
441
442
484
485
486
487
488
489
490
491
492

493
494
495
496


497
498
499
500
501
502

503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520

521
522
523

524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539

540
541
542
543
544
545
546

547
548
549
550
551
552

553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568







+

-
+



-
-
+
+
+
+


-
+

















-
+


-
+
+
+













-
+






-
+



+
+
-
+
+
+
+




+







    lappend result [image width photo1] [image height photo1]
    photo1 conf -height 0
    photo1 copy photo2 -from 0 0 10 10 -shrink
    lappend result [image width photo1] [image height photo1]
} -cleanup {
    image delete photo1 photo2
} -result {256 256 49 51 49 51 49 51 10 51 10 10}
# tests for <imageName> data: imgPhoto-4.
test imgPhoto-4.22 {ImgPhotoCmd procedure: get option} -constraints {
    hasTeapotPhoto
    hasTranspTeapotPhoto
} -setup {
    image create photo photo1
} -body {
    photo1 read $teapotPhotoFile
    list [photo1 get 100 100] [photo1 get 150 100] [photo1 get 100 150]
    photo1 read $transpTeapotPhotoFile
    list [photo1 get 100 100 -withalpha] \
	[photo1 get 150 100 -withalpha] \
	[photo1 get 100 150] [photo1 get 150 150]
} -cleanup {
    image delete photo1
} -result {{169 117 90} {172 115 84} {35 35 35}}
} -result {{175 71 0 162} {179 73 0 168} {14 8 0} {0 0 0}}
test imgPhoto-4.23 {ImgPhotoCmd procedure: get option} -setup {
    image create photo photo1
} -body {
    photo1 get 256 0
} -cleanup {
    image delete photo1
} -returnCodes error -result {photo1 get: coordinates out of range}
test imgPhoto-4.24 {ImgPhotoCmd procedure: get option} -setup {
    image create photo photo1
} -body {
    photo1 get 0 -1
} -cleanup {
    image delete photo1
} -returnCodes error -result {photo1 get: coordinates out of range}
test imgPhoto-4.25 {ImgPhotoCmd procedure: get option} -setup {
    image create photo photo1
} -body {
    photo1 get
    photo1 get 0
} -cleanup {
    image delete photo1
} -returnCodes error -result {wrong # args: should be "photo1 get x y"}
} -returnCodes error -result \
    {wrong # args: should be "photo1 get x y ?-withalpha?"}
# more test for image get: 4.101-4.102
test imgPhoto-4.26 {ImgPhotoCmd procedure: put option} -setup {
    image create photo photo1
} -body {
    photo1 put
} -returnCodes error -cleanup {
    image delete photo1
} -result {wrong # args: should be "photo1 put data ?-option value ...?"}
test imgPhoto-4.27 {ImgPhotoCmd procedure: put option} -setup {
    image create photo photo1
} -body {
    photo1 put {{white} {white white}}
} -returnCodes error -cleanup {
    image delete photo1
} -result {all elements of color list must have the same number of elements}
} -result {invalid row # 1: all rows must have the same number of elements}
test imgPhoto-4.28 {ImgPhotoCmd procedure: put option} -setup {
    image create photo photo1
} -body {
    photo1 put {{blahgle}}
} -cleanup {
    image delete photo1
} -returnCodes error -result {can't parse color "blahgle"}
} -returnCodes error -result {invalid color name "blahgle"}
test imgPhoto-4.29 {ImgPhotoCmd procedure: put option} -setup {
    image create photo photo1
} -body {
    # SB: odd thing - this test passed with tk 8.6.6, even if the data
    # is in the wrong position:
    photo1 put -to 10 10 20 20 {{white}}
    #photo1 put -to 10 10 20 20 {{white}}

    # this is how it's supposed to be:
    photo1 put {{white}} -to 10 10 20 20
    photo1 get 19 19
} -cleanup {
    image delete photo1
} -result {255 255 255}
# more tests for image put: 4.90-4.100
test imgPhoto-4.30 {ImgPhotoCmd procedure: read option} -setup {
    image create photo photo1
} -body {
    photo1 read
} -returnCodes error -cleanup {
    image delete photo1
} -result {wrong # args: should be "photo1 read fileName ?-option value ...?"}
510
511
512
513
514
515
516

517
518
519
520
521
522
523
524
525
526
527
528
529
530

531
532
533
534
535
536
537

538
539
540
541

542
543
544

545
546
547
548
549
550
551
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656

657
658
659
660
661
662
663

664
665
666
667

668
669
670

671
672
673
674
675
676
677
678







+













-
+






-
+



-
+


-
+







test imgPhoto-4.39 {ImgPhotoCmd procedure: write option} -setup {
    image create photo photo1
} -body {
    photo1 write teapot.tmp -format bogus
} -cleanup {
    image delete photo1
} -returnCodes error -result {image file format "bogus" is unknown}
# more tests on "imageName write": imgPhoto-17.*
test imgPhoto-4.40 {ImgPhotoCmd procedure: transparency option} -setup {
    image create photo photo1
} -body {
    photo1 transparency
} -returnCodes error -cleanup {
    image delete photo1
} -result {wrong # args: should be "photo1 transparency option ?arg ...?"}
test imgPhoto-4.41 {ImgPhotoCmd procedure: transparency get option} -setup {
    image create photo photo1
} -body {
    photo1 transparency get
} -returnCodes error -cleanup {
    image delete photo1
} -result {wrong # args: should be "photo1 transparency get x y"}
} -result {wrong # args: should be "photo1 transparency get x y ?-option?"}
test imgPhoto-4.42 {ImgPhotoCmd procedure: transparency get option} -setup {
    image create photo photo1
} -body {
    photo1 transparency get 0
} -returnCodes error -cleanup {
    image delete photo1
} -result {wrong # args: should be "photo1 transparency get x y"}
} -result {wrong # args: should be "photo1 transparency get x y ?-option?"}
test imgPhoto-4.43 {ImgPhotoCmd procedure: transparency get option} -setup {
    image create photo photo1
} -body {
    photo1 transparency get 0 0 0
    photo1 transparency get 0 0 0 -alpha
} -returnCodes error -cleanup {
    image delete photo1
} -result {wrong # args: should be "photo1 transparency get x y"}
} -result {wrong # args: should be "photo1 transparency get x y ?-option?"}
test imgPhoto-4.44 {ImgPhotoCmd procedure: transparency get option} -setup {
    image create photo photo1
} -body {
    photo1 transparency get bogus 0
} -cleanup {
    image delete photo1
} -returnCodes error -result {expected integer but got "bogus"}
597
598
599
600
601
602
603

604
605
606
607
608
609

610

611
612
613
614
615
616

617

618
619
620
621
622
623

624

625
626
627
628

629
630

631

632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647

648
649
650
651
652
653
654
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738

739
740
741
742
743
744
745
746

747
748
749
750
751
752
753
754

755
756
757
758

759
760
761
762

763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787







+






+
-
+






+
-
+






+
-
+



-
+


+
-
+
















+







} -body {
    photo1 put white
    photo1 blank
    photo1 transparency get 0 0
} -cleanup {
    image delete photo1
} -result 1
# more tests for transparency get: 4.65, 4.66, 4.76-4.81
test imgPhoto-4.52 {ImgPhotoCmd procedure: transparency set option} -setup {
    image create photo photo1
} -body {
    photo1 transparency set
} -returnCodes error -cleanup {
    image delete photo1
} -result \
} -result {wrong # args: should be "photo1 transparency set x y boolean"}
    {wrong # args: should be "photo1 transparency set x y newVal ?-option?"}
test imgPhoto-4.53 {ImgPhotoCmd procedure: transparency set option} -setup {
    image create photo photo1
} -body {
    photo1 transparency set 0
} -returnCodes error -cleanup {
    image delete photo1
} -result \
} -result {wrong # args: should be "photo1 transparency set x y boolean"}
    {wrong # args: should be "photo1 transparency set x y newVal ?-option?"}
test imgPhoto-4.54 {ImgPhotoCmd procedure: transparency set option} -setup {
    image create photo photo1
} -body {
    photo1 transparency set 0 0
} -returnCodes error -cleanup {
    image delete photo1
} -result \
} -result {wrong # args: should be "photo1 transparency set x y boolean"}
    {wrong # args: should be "photo1 transparency set x y newVal ?-option?"}
test imgPhoto-4.55 {ImgPhotoCmd procedure: transparency set option} -setup {
    image create photo photo1
} -body {
    photo1 transparency set 0 0 0 0
    photo1 transparency set 0 0 0 0 -alpha
} -returnCodes error -cleanup {
    image delete photo1
} -result \
} -result {wrong # args: should be "photo1 transparency set x y boolean"}
    {wrong # args: should be "photo1 transparency set x y newVal ?-option?"}
test imgPhoto-4.56 {ImgPhotoCmd procedure: transparency set option} -setup {
    image create photo photo1
} -body {
    photo1 transparency set bogus 0 0
} -cleanup {
    image delete photo1
} -returnCodes error -result {expected integer but got "bogus"}
test imgPhoto-4.57 {ImgPhotoCmd procedure: transparency set option} -setup {
    image create photo photo1
} -body {
    photo1 transparency set 0 bogus 0
} -cleanup {
    image delete photo1
} -returnCodes error -result {expected integer but got "bogus"}
test imgPhoto-4.58 {ImgPhotoCmd procedure: transparency set option} -setup {
    image create photo photo1
    photo1 put blue
} -body {
    photo1 transparency set 0 0 bogus
} -cleanup {
    image delete photo1
} -returnCodes error -result {expected boolean value but got "bogus"}
test imgPhoto-4.59 {ImgPhotoCmd procedure: transparency set option} -setup {
    image create photo photo1
692
693
694
695
696
697
698

699
700
701
702
703
704
705
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839







+







} -body {
    photo1 put white
    photo1 transparency set 0 0 true
    photo1 transparency get 0 0
} -cleanup {
    image delete photo1
} -result 1
# more tests for transparency set: 4.67, 4.68, 4.82-4.89
# Now for some heftier testing, checking that setting and resetting of pixels'
# transparency status doesn't "leak" with any one-off errors.
test imgPhoto-4.65 {ImgPhotoCmd procedure: transparency get option} -setup {
    image create photo photo1
} -body {
    photo1 put white -to 0 0 3 3
    checkImgTrans photo1
816
817
818
819
820
821
822
823
824


825
826
827
828
829
830
831
832
833
834




































835

















































































































































































































































































































































































836
837
838
839
840
841
842
950
951
952
953
954
955
956


957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004

1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380







-
-
+
+










+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    file copy -force $teapotPhotoFile -teapotPhotoFile
    image create photo photo1
    photo1 read -teapotPhotoFile
} -cleanup {
    image delete photo1
    file delete ./-teapotPhotoFile
} -result {}
test imgPhoto-4.76 {ImgPhotoCmd procedure: copy to same image} -constraints {
    hasTeapotPhoto 
test imgPhoto-4.75.1 {ImgPhotoCmd procedure: copy to same image} -constraints {
    hasTeapotPhoto
} -setup {
    imageCleanup
    image create photo photo1 -file $teapotPhotoFile
} -body {
    # non-regression test for bug [5239fd749b] - shall just not crash
    photo1 copy photo1 -to 0 0 2000 1000
    photo1 copy photo1 -subsample 2 2 -shrink
} -cleanup {
    imageCleanup
} -result {}
test imgPhoto-4.76 {ImgPhotoCmd, transparency get: too many options} -setup {
    image create photo photo1
} -body {
    photo1 put white -to 0 0 1 1
    photo1 transparency get 0 0 -alpha -bogus
} -cleanup {
    imageCleanup
} -returnCodes error -result \
    {wrong # args: should be "photo1 transparency get x y ?-option?"}
test imgPhoto-4.77 {ImgPhotoCmd, transparency get: invalid option} -setup {
    image create photo photo1
} -body {
    photo1 put white -to 0 0 1 1
    photo1 transparency get 0 0 -bogus
} -cleanup {
    imageCleanup
} -returnCodes error -result \
    {unrecognized option "-bogus": must be -alpha}
test imgPhoto-4.78 {ImgPhotoCmd, transparency get: normal use} -setup {
    image create photo photo1
} -body {
    photo1 put white -to 0 0 1 1
    set result [photo1 transparency get 0 0]
    lappend result [photo1 transparency get 0 0 -alpha]
} -cleanup {
    imageCleanup
} -result {0 255}
test imgPhoto-4.79 {ImgPhotoCmd, transparency get: no option} -constraints {
    hasTranspTeapotPhoto
} -setup {
    image create photo photo1 -file $transpTeapotPhotoFile
    set result {}
} -body {
    set pixelCoords {{156 239} {76 207} {153 213} {139 43} {75 112}}
    foreach coord $pixelCoords {
	lappend result [photo1 transparency get {*}$coord]

    }
    set result
} -cleanup {
    imageCleanup
} -result {0 1 0 0 0}
# test imgPhoto-4.80: deleted (was transparency get: -boolean)
test imgPhoto-4.81 {ImgPhotoCmd, transparency get: -alpha} -constraints {
    hasTranspTeapotPhoto
} -setup {
    image create photo photo1 -file $transpTeapotPhotoFile
    set result {}
} -body {
    set pixelCoords {{156 239} {76 207} {153 213} {139 43} {75 112}}
    foreach coord $pixelCoords {
	lappend result [photo1 transparency get {*}$coord -alpha]
    }
    set result
} -cleanup {
    imageCleanup
} -result {255 0 1 254 206}
test imgPhoto-4.82 {ImgPhotoCmd, transparency set: too many opts} -setup {
    image create photo photo1
} -body {
    photo1 transparency set 0 0 -alpha -bogus 1
} -cleanup {
    imageCleanup
} -returnCodes error -result \
    {wrong # args: should be "photo1 transparency set x y newVal ?-option?"}
test imgPhoto-4.83 {ImgPhotoCmd, transparency set: invalid opt} -setup {
    image create photo photo1 -data black
} -body {
    photo1 transparency set 0 0 0 -bogus
} -cleanup {
    imageCleanup
} -returnCodes error -result \
    {unrecognized option "-bogus": must be -alpha}
test imgPhoto-4.84 {ImgPhotoCmd, transparency set: invalid newVal} -setup {
    image create photo photo1 -data white
} -body {
    photo1 transparency set 0 0 bogus -alpha
} -cleanup {
    imageCleanup
} -returnCodes error -result {expected integer but got "bogus"}
test imgPhoto-4.85 {ImgPhotoCmd, transparency set: invalid newVal} -setup {
    image create photo photo1 -data red
} -body {
    photo1 transparency set 0 0 -1 -alpha
} -returnCodes error -result \
    {invalid alpha value "-1": must be integer between 0 and 255}
test imgPhoto-4.86 {ImgPhotoCmd, transparency set: invalid newVal} -setup {
    image create photo photo1 -data green
} -body {
    photo1 transparency set 0 0 256 -alpha
} -cleanup {
    imageCleanup
} -returnCodes error -result \
    {invalid alpha value "256": must be integer between 0 and 255}
test imgPhoto-4.87 {ImgPhotoCmd, transparency set: no opt} -setup {
    image create photo photo1
} -body {
    photo1 put white -to 0 0 2 1
    photo1 transparency set 0 0 0
    photo1 transparency set 1 0 1
    list [photo1 transparency get 0 0 -alpha] \
        [photo1 transparency get 1 0 -alpha]
} -cleanup {
    imageCleanup
} -result {255 0}
# deleted: test imgPhoto-4.88 {ImgPhotoCmd, transparency set: -boolean}
test imgPhoto-4.89 {ImgPhotoCmd, transparency set: -alpha} -setup {
    image create photo photo1
} -body {
    photo1 put white -to 0 0 2 2
    photo1 transparency set 0 0 0 -alpha
    photo1 transparency set 1 0 1 -alpha
    photo1 transparency set 0 1 254 -alpha
    photo1 transparency set 1 1 255 -alpha
    list [photo1 transparency get 0 0] [photo1 transparency get 1 0] \
	[photo1 transparency get 0 1] [photo1 transparency get 1 1]
} -cleanup {
    imageCleanup
} -result {1 0 0 0}
test imgPhoto-4.90 {ImgPhotoCmd put: existing but not allowed opt} -setup {
    image create photo photo1
} -body {
    photo1 put yellow -from 0 0 1 1
} -cleanup {
    imageCleanup
} -returnCodes error -result \
    {unrecognized option "-from": must be -format, or -to}
test imgPhoto-4.91 {ImgPhotoCmd put: invalid option} -setup {
    image create photo photo1
} -body {
    photo1 put {{0 1 2 3}} -bogus x
} -returnCodes error -result \
    {unrecognized option "-bogus": must be -format, or -to}
test imgPhoto-4.92 {ImgPhotocmd put: missing data} -setup {
    image create photo photo1
} -body {
    photo1 put -to 0 0
} -returnCodes error -result \
    {wrong # args: should be "photo1 put data ?-option value ...?"}
test imgPhoto-4.93 {ImgPhotoCmd put: data in ppm format} -constraints {
    hasTeapotPhoto
} -setup {
    image create photo photo1 -file $teapotPhotoFile
    image create photo photo2
} -body {
    set imgdata [photo1 data -format ppm]
    photo2 put $imgdata -format ppm
    set result {}
    if {[image width photo1] != [image width photo2] \
            || [image height photo1] != [image height photo2]} {
        lappend result [list [image width photo2] [image height photo2]]
    } else {
        lappend result 1
    }
    foreach point {{206 125} {67 12} {13 46} {19 184}} {
        if {[photo1 get {*}$point] ne [photo2 get {*}$point]} {
            lappend result [photo2 get {*}$point]
        } else {
            lappend result 1
        }
    }
    set result
} -cleanup {
    imageCleanup
} -result {1 1 1 1 1}
test imgPhoto-4.94 {ImgPhotoCmd put: unknown format} -setup {
    image create photo photo1
} -body {
    photo1 put {no real data} -format bogus
} -cleanup {
    imageCleanup
} -returnCodes error -result {image format "bogus" is not supported}
test imgPhoto-4.95 {ImgPhotoCmd put: default fmt, invalid data} -setup {
    image create photo photo1
} -body {
    photo1 put {{red green blue} {red " blue}}
    #"
} -cleanup {
    imageCleanup
} -returnCodes error -result {unmatched open quote in list}
test imgPhoto-4.96 {ImgPhotoCmd put: "default" handler is selected} -setup {
    image create photo photo1
    image create photo photo2
    set imgData {{{1 2 3 4} {5 6 7 8} {9 10 11 12}}
        {{13 14 15 15} {17 18 19 20} {21 22 23 24}}}
} -body {
    photo1 put $imgData
    photo2 put $imgData -format default
    set result {}
    lappend result [list [image width photo1] [image height photo1]]
    lappend result [list [image width photo2] [image height photo2]]
    lappend result [string equal \
        [photo1 data -format "default -colorformat rgba"] \
        [photo2 data -format "default -colorformat rgba"]]
    set result
} -cleanup {
    imageCleanup
    unset result
    unset imgData
} -result {{3 2} {3 2} 1}
test imgPhoto-4.97 {ImgPhotoCmd put: image size} -setup {
    image create photo photo1
} -body {
    photo1 put {{red green blue} {blue red green}}
    list [image width photo1] [image height photo1]
} -cleanup {
    imageCleanup
} -result {3 2}
test imgPhoto-4.98 {ImgPhotoCmd put: -to with 2 coords} -setup {
    image create photo photo1
} -body {
    photo1 put {{"alice blue" "blanched almond"}
		{"deep sky blue" "ghost white"}
		{#AABBCC #AABBCCDD}} -to 5 6
    list [image width photo1] [image height photo1]
} -cleanup {
    imageCleanup
} -result {7 9}
test imgPhoto-4.99 {ImgPhotoCmd put: -to with 4 coords} -setup {
    image create photo photo1
} -body {
    photo1 put {{#123 #456 #678} {#9AB #CDE #F01}} -to 1 2 20 21
    set result {}
    lappend result [photo1 get 19 20 -withalpha]
    lappend result [string equal \
	[photo1 data -from 1 2 4 4] [photo1 data -from 4 2 7 4]]
    lappend result [string equal \
	[photo1 data -from 10 12 13 14] [photo1 data -from 16 16 19 18]]
    set result
} -cleanup {
    imageCleanup
} -result {{17 34 51 255} 1 1}
test imgPhoto-4.100 {ImgPhotoCmd put: no changes on empty data} -setup {
    image create photo photo1
} -body {
    photo1 put {{brown blue} {cyan coral}}
    set imgData [photo1 data]
    photo1 put {}
    string equal $imgData [photo1 data]
} -cleanup {
    imageCleanup
} -result 1
test imgPhoto-4.101 {ImgPhotoCmd get: too many args} -setup {
    image create photo photo1
} -body {
    photo1 get 0 0 -withalpha bogus
} -cleanup {
    imageCleanup
} -returnCodes error -result \
    {wrong # args: should be "photo1 get x y ?-withalpha?"}
test imgPhoto-4.102 {ImgPhotoCmd get: invalid option} -setup {
    image create photo photo1
} -body {
    photo1 get 0 0 -bogus
} -cleanup {
    imageCleanup
} -returnCodes error -result \
    {unrecognized option "-bogus": must be -withalpha}
test imgPhoto-4.103 {ImgPhotoCmd data: accepted opts} -setup {
    image create photo photo1 -data black
} -body {
    photo1 data -format default -from 0 0 -grayscale -background blue
} -cleanup {
    imageCleanup
} -result {{#000000}}
test imgPhoto-4.104 {ImgPhotoCmd data: existing but not accepted opt} -setup {
    image create photo photo1
} -body {
    photo1 data -to
} -cleanup {
    imageCleanup
} -returnCodes error -result \
{unrecognized option "-to": must be -background, -format, -from, or -grayscale}
test imgPhoto-4.105 {ImgPhotoCmd data: invalid option} -setup {
    image create photo photo1
} -body {
    photo1 data -bogus
} -cleanup {
    imageCleanup
} -returnCodes error -result \
{unrecognized option "-bogus": must be -background, -format, -from, or -grayscale}
test imgPhoto-4.106 {ImgPhotoCmd data: extra arg before options} -setup {
    image create photo photo1
} -body {
    photo1 data bogus -grayscale
} -cleanup {
    imageCleanup
} -returnCodes error -result \
    {wrong # args: should be "photo1 data ?-option value ...?"}
test imgPhoto-4.107 {ImgPhotoCmd data: extra arg after options} -setup {
    image create photo photo1
} -body {
    photo1 data -format default bogus
} -cleanup {
    imageCleanup
} -returnCodes error -result \
    {wrong # args: should be "photo1 data ?-option value ...?"}
test imgPhoto-4.108 {ImgPhotoCmd data: invalid -from coords #1} -setup {
    image create photo photo1 -data blue
} -body {
    photo1 data -from 2 0
} -cleanup {
    imageCleanup
} -returnCodes error -result \
    {coordinates for -from option extend outside image}
test imgPhoto-4.109 {ImgPhotoCmd data: invalid -from coords #2} -setup {
    image create photo photo1 -data blue
} -body {
    photo1 data -from 0 2
} -cleanup {
    imageCleanup
} -returnCodes error -result \
    {coordinates for -from option extend outside image}
test imgPhoto-4.110 {ImgPhotoCmd data: invalid -from coords #3} -setup {
    image create photo photo1 -data blue
} -body {
    photo1 data -from 0 0 2 1
} -cleanup {
    imageCleanup
} -returnCodes error -result \
    {coordinates for -from option extend outside image}
test imgPhoto-4.111 {ImgPhotoCmd data: invalid -from coords #4} -setup {
    image create photo photo1 -data blue
} -body {
    photo1 data -from 0 0 1 2
} -cleanup {
    imageCleanup
} -returnCodes error -result \
    {coordinates for -from option extend outside image}
test imgPhoto-4.112 {ImgPhotoCmd data: -from with 2 coords} -setup {
    image create photo photo1 -data {
        {black black black black black}
        {white white white white white}
        {green green green green green}}
} -body {
    set imgData [photo1 data -from 2 1]
    list [llength [lindex $imgData 0]] [llength $imgData]
} -cleanup {
    imageCleanup
    unset imgData
} -result {3 2}
test imgPhoto-4.113 {ImgPhotoCmd data: default is rgb format} -setup {
    image create photo photo1 -data red
} -body {
    photo1 data
} -cleanup {
    imageCleanup
} -result {{#ff0000}}
test imgPhoto-4.114 {ImgPhotoCmd data: unknown format} -setup {
    image create photo photo1
} -body {
    photo1 data -format bogus
} -cleanup {
    imageCleanup
} -returnCodes error -result {image string format "bogus" is unknown}
test imgPhoto-4.115 {ImgPhotoCmd data: rgb colorformat} -setup {
    image create photo photo1 -data {{red#a green#b} {blue#c white}}
} -body {
    photo1 data -format {default -colorformat rgb}
} -result {{#ff0000 #008000} {#0000ff #ffffff}}
test imgPhoto-4.116 {ImgPhotoCmd data: rgba colorformat} -setup {
    image create photo photo1 -data {{red green} {blue white}}
} -body {
    photo1 data -format {default -colorformat rgba}
} -result {{#ff0000ff #008000ff} {#0000ffff #ffffffff}}
test imgPhoto-4.117 {ImgPhotoCmd data: list colorformat} -setup {
    image create photo photo1 -data {{red#a green} {blue#c white#d}}
} -body {
    photo1 data -format {default -colorformat list}
} -result {{{255 0 0 170} {0 128 0 255}} {{0 0 255 204} {255 255 255 221}}}
# This testcase fails with Tcl < 8.6.7, due to [25842c]
test imgPhoto-4.118 {ImgPhotoCmd data: using data for new image
    results in same image as orignial } -constraints {
        hasTeapotPhoto hasTranspTeapotPhoto needsTcl867
} -setup {
    image create photo teapot -file $teapotPhotoFile
    teapot copy teapot -from 50 60 70 80 -shrink
    image create photo teapotTransp -file $transpTeapotPhotoFile
    teapotTransp copy teapotTransp -from 100 110 120 130 -shrink
    image create photo photo1
} -body {
    set result {}
    # We don't test gif here, as there seems to be a problem with
    # <imgName> data and gif format ("too many colors", probably a bug)
    foreach fmt {ppm png {default -colorformat rgba} \
            {default -colorformat list}} {
        set imgData [teapotTransp data -format $fmt]
        photo1 blank
        photo1 put $imgData
        if { ! [string equal [photo1 data] [teapotTransp data]]} {
            lappend result $fmt
        }
    }
    set imgData [teapot data -format default]
    photo1 blank
    photo1 put $imgData
    if { ! [string equal [photo1 data] [teapot data]]} {
        lappend result default
    }
    set result
} -cleanup {
    unset imgData
    unset result
    imageCleanup
} -result {}

test imgPhoto-5.1 {ImgPhotoGet/Free procedures, shared instances} -constraints {
    hasTeapotPhoto
} -setup {
    destroy .c
    pack [canvas .c]
    imageCleanup
} -body {
851
852
853
854
855
856
857
858

859
860
861
862
863
864
865
866
867
868
869
870
871
872

873
874
875
876
877
878
879
1389
1390
1391
1392
1393
1394
1395

1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409

1410
1411
1412
1413
1414
1415
1416
1417







-
+













-
+







    .c delete i1.2
    photo1 configure -height 1
    update
    image delete photo1
} -cleanup {
    destroy .c
} -result {}


test imgPhoto-6.1 {ImgPhotoDisplay procedure, blank display} -setup {
    destroy .c
    pack [canvas .c]
    imageCleanup
} -body {
    image create photo photo1 -width 10 -height 10
    photo1 blank
    .c create image 10 10 -image photo1
    update
} -cleanup {
    destroy .c
    image delete photo1
} -result {}


test imgPhoto-7.1 {ImgPhotoFree procedure, resource freeing} -constraints {
    hasTeapotPhoto
} -setup {
    destroy .c
    pack [canvas .c]
    imageCleanup
} -body {
926
927
928
929
930
931
932
933

934
935
936
937
938
939
940
1464
1465
1466
1467
1468
1469
1470

1471
1472
1473
1474
1475
1476
1477
1478







-
+







    destroy .b1
    update
    .f.b2 configure -image {}
    update
    destroy .f
    image delete photo1
} -result {}


test imgPhoto-8.1 {ImgPhotoDelete procedure} -constraints hasTeapotPhoto -body {
    image create photo photo2 -file $teapotPhotoFile
    image delete photo2
} -result {}
test imgPhoto-8.2 {ImgPhotoDelete procedure} -constraints {
    hasTeapotPhoto
} -setup {
950
951
952
953
954
955
956
957

958
959
960
961
962
963
964
965



966
967
968
969
970
971
972
1488
1489
1490
1491
1492
1493
1494

1495
1496
1497
1498
1499
1500



1501
1502
1503
1504
1505
1506
1507
1508
1509
1510







-
+





-
-
-
+
+
+







    image create photo photo1
    image create photo photo2 -width 10 -height 10
    image delete photo2
    photo1 copy photo2
} -returnCodes error -cleanup {
    imageCleanup
} -result {image "photo2" doesn't exist or is not a photo image}


test imgPhoto-9.1 {ImgPhotoCmdDeletedProc procedure} -constraints {
    hasTeapotPhoto
} -body {
    image create photo photo2 -file $teapotPhotoFile
    rename photo2 {}
    list [lsearch -exact [imageNames] photo2] [catch {photo2 foo} msg] $msg
} -result {-1 1 {invalid command name "photo2"}}

    list [expr {"photo2" in [imageNames]}] [catch {photo2 foo} msg] $msg
} -result {0 1 {invalid command name "photo2"}}

test imgPhoto-10.1 {Tk_ImgPhotoPutBlock procedure} -setup {
    imageCleanup
} -body {
    image create photo photo1
    photo1 put "{#ff0000 #ff0000 #ff0000 #ff0000 #ff0000 #ff0000 #ff0000 #ff0000}" -to 0 0
    photo1 put "{#00ff00 #00ff00}" -to 2 0
    list [photo1 get 2 0] [photo1 get 3 0] [photo1 get 4 0]
980
981
982
983
984
985
986
987

988
989
990
991
992
993
994
995
996
997
998
999
1000
1001

1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022

1023
1024
1025
1026
1027
1028
1029
1518
1519
1520
1521
1522
1523
1524

1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538

1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549

1550
1551
1552
1553
1554
1555
1556
1557
1558

1559
1560
1561
1562
1563
1564
1565
1566







-
+













-
+










-









-
+







    image create photo photo1 -file $teapotPhotoFile
    image create photo photo2 -file $teapotPhotoFile
    photo2 copy photo1 -to 1 2
    photo1 copy photo1 -to 1 2
    string equal [photo1 data] [photo2 data]
} -cleanup {
    imageCleanup
} -result {1}
} -result 1
test imgPhoto-10.3 {Tk_ImgPhotoPutBlock, same source and dest img} -constraints {
    hasTeapotPhoto
} -setup {
    imageCleanup
} -body {
    # Test for bug e4336bef5d
    image create photo photo1 -file $teapotPhotoFile
    image create photo photo2 -file $teapotPhotoFile
    photo2 copy photo1 -from 2 1 -to 4 5 300 300
    photo1 copy photo1 -from 2 1 -to 4 5 300 300
    string equal [photo1 data] [photo2 data]
} -cleanup {
    imageCleanup
} -result {1}
} -result 1
test imgPhoto-10.4 {Tk_ImgPhotoPutBlock, empty image} -setup {
    imageCleanup
} -body {
    image create photo photo1
    photo1 copy photo1 -to 0 5 10 20
    list [image width photo1] [image height photo1]
} -cleanup {
    imageCleanup
} -result {0 0}


test imgPhoto-11.1 {Tk_FindPhoto} -setup {
    imageCleanup
} -body {
    image create bitmap i1
    image create photo photo1
    photo1 copy i1
} -cleanup {
    imageCleanup
} -returnCodes error -result {image "i1" doesn't exist or is not a photo image}


test imgPhoto-12.1 {Tk_PhotoPutZoomedBlock} -constraints hasTeapotPhoto -body {
    image create photo p3 -file $teapotPhotoFile
    set result [list [p3 get 50 50] [p3 get 100 100]]
    p3 copy p3 -zoom 2
    lappend result [image width p3] [image height p3] [p3 get 100 100]
} -cleanup {
    image delete p3
1037
1038
1039
1040
1041
1042
1043
1044

1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056

1057
1058
1059
1060
1061
1062
1063
1574
1575
1576
1577
1578
1579
1580

1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592

1593
1594
1595
1596
1597
1598
1599
1600







-
+











-
+







    image create photo photo1 -file $teapotPhotoFile
    image create photo photo2 -file $teapotPhotoFile
    photo2 copy photo1 -to 0 1 200 200 -zoom 2 3
    photo1 copy photo1 -to 0 1 200 200 -zoom 2 3
    string equal [photo1 data] [photo2 data]
} -cleanup {
    imageCleanup
} -result {1}
} -result 1
test imgPhoto-12.3 {Tk_ImgPhotoPutZoomedBlock, same source and dest img} -setup {
    imageCleanup
} -body {
    # Test for bug e4336bef5d
    image create photo photo1 -file $teapotPhotoFile
    image create photo photo2 -file $teapotPhotoFile
    photo2 copy photo1 -from 1 0 -to 4 5 300 300 -zoom 1 2
    photo1 copy photo1 -from 1 0 -to 4 5 300 300 -zoom 1 2
    string equal [photo1 data] [photo2 data]
} -cleanup {
    imageCleanup
} -result {1}
} -result 1
test imgPhoto-12.4 {Tk_ImgPhotoPutZoomedBlock, empty image} -setup {
    imageCleanup
} -body {
    image create photo photo1
    photo1 copy photo1 -to 0 5 10 20
    list [image width photo1] [image height photo1]
} -cleanup {
1104
1105
1106
1107
1108
1109
1110
1111

1112
1113
1114
1115
1116
1117
1118
1641
1642
1643
1644
1645
1646
1647

1648
1649
1650
1651
1652
1653
1654
1655







-
+







} -body {
    x1 eval [list image create photo T1_data -data $data]
    x2 eval [list image create photo T1_data -data $data]
} -cleanup {
    interp delete x1
    interp delete x2
} -result T1_data


test imgPhoto-14.1 {GIF writes work correctly} -setup {
    set data {
	R0lGODlhYwA5APcAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgAysnGy8hKzM
	hASs3MTcjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
1248
1249
1250
1251
1252
1253
1254
1255

1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266

1267
1268
1269
1270
1271
1272
1273
1785
1786
1787
1788
1789
1790
1791

1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802

1803
1804
1805
1806
1807
1808
1809
1810







-
+










-
+







test imgPhoto-15.1 {photo images can fail to allocate memory gracefully} -constraints {
    nonPortable
} -body {
    # This is not portable to very large machines with more than around 3GB of
    # free memory available...
    image create photo -width 32000 -height 32000
} -returnCodes error -result {not enough free memory for image buffer}


test imgPhoto-16.1 {copying to self doesn't access freed memory} -setup {
    set i [image create photo]
} -body {
    # Bug 877950 makes this crash when trying to copy out of a deallocated
    # area.
    $i put red -to 0 0 1000 1000
    $i copy $i -from 0 0 1000 1000 -to 500 0
} -cleanup {
    image delete $i
} -result {}


# Check that we can guess our supported output formats [Bug 2983824]
test imgPhoto-17.1 {photo write: format guessing from filename} -setup {
    set i [image create photo -width 3 -height 3]
} -body {
    set f [makeFile {} test.png]
    $i write $f
    set fd [open $f]
1298
1299
1300
1301
1302
1303
1304






















1305


















































































1306
1307

1308
1309

1310
1311
1312
1313

1314
1315
1316
1317
1318
1319
1320
1321
1322

1323
1324
1325
1326
1327
1328
1329
1330
1331
1332

1333
1334
1335
1336
1337
1338
1339

1340
1341
1342
1343

1344
1345
1346
1347
1348
1349
1350
1351

1352
1353
1354
1355
1356
1357
1358
1359
1360

1361
1362
1363
1364
1365
1366
1367
1368


1369
1370
1371
1372
1373
1374
1375

1376
1377
1378
1379
1380
1381
1382
1383
1384

1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400

1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413

1414
1415
1416
1417
1418

1419
1420

1421
1422
1423
1424
1425
1426
1427
1428
1429

1430
1431
1432
1433
1434
1435
1436
1437
1438
1439

1440
1441
1442
1443
1444
1445
1446
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863

1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946

1947
1948

1949




1950
1951
1952
1953
1954
1955
1956
1957
1958

1959
1960
1961
1962
1963
1964
1965
1966
1967
1968

1969
1970
1971
1972
1973
1974
1975

1976




1977
1978
1979
1980
1981
1982
1983
1984

1985
1986
1987
1988
1989
1990
1991
1992
1993

1994
1995
1996
1997
1998
1999
2000


2001
2002
2003
2004
2005
2006
2007


2008
2009
2010
2011
2012
2013
2014
2015
2016

2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032

2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045

2046


2047
2048

2049


2050
2051
2052
2053
2054
2055
2056
2057
2058

2059
2060
2061
2062
2063
2064
2065
2066
2067
2068

2069
2070
2071
2072
2073
2074
2075
2076







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+

-
+
-
-
-
-
+








-
+









-
+






-
+
-
-
-
-
+







-
+








-
+






-
-
+
+





-
-
+








-
+















-
+












-
+
-
-


-
+
-
-
+








-
+









-
+







    set fd [open $f]
    read $fd 3
} -cleanup {
    catch {close $fd}
    image delete $i
    catch {removeFile $f}
} -result "P6\n"
test imgPhoto-17.4 {photo write: default format not supported} -setup {
    image create photo photo1 -data {{blue blue} {red red} {green green}}
    set f [makeFile {} test.txt]
} -body {
    photo1 write $f -format default
} -cleanup {
    imageCleanup
    catch {removeFile $f}
    unset f
} -returnCodes error -result \
    {image file format "default" has no file writing capability}
test imgPhoto-17.5 {photo write: file with extension .default} -setup {
    image create photo photo1 -data {{black}}
    set f [makeFile {} test.default]
} -body {
    photo1 write $f
} -cleanup {
    imageCleanup
    catch {removeFile $f}
    unset f
} -returnCodes error -result \
    {image file format "default" has no file writing capability}


test imgPhoto-18.1 {MatchFileFormat: "default" format not supported} -setup {
    image create photo photo1
    set f [makeFile {} test.txt]
} -body {
    photo1 read $f -format default
} -cleanup {
    imageCleanup
    catch {removeFile $f}
    unset f
} -returnCodes error -result {-file option isn't supported for default images}

test imgPhoto-19.1 {MatchStringFormat: with "-format default"} -setup {
    image create photo photo1
} -body {
    photo1 put {{red blue red} {yellow green yellow}} -format default
    list [image width photo1] [image height photo1]
} -cleanup {
    imageCleanup
} -result {3 2}
test imgPhoto-19.2 {MatchStringFormat: without -format option,
        default fmt} -body {
    image create photo photo1
    photo1 put {{red} {green}}
    list [image width photo1] [image height photo1]
} -cleanup {
    imageCleanup
} -result {1 2}
test imgPhoto-19.3 {MatchStringFormat: "-format ppm"} -setup {
    image create photo photo1
    image create photo photo2
    photo2 put {cyan cyan}
    set imgData [photo2 data -format ppm]
} -body {
    photo1 put $imgData -format ppm
    list [image width photo1] [image height photo1]
} -cleanup {
    unset imgData
    imageCleanup
} -result {1 2}
test imgPhoto-19.4 {MatchStringFormat: ppm fmt, without opt} -constraints {
    hasTeapotPhoto
} -setup {
    image create photo photo1 -file $teapotPhotoFile
    image create photo photo2
} -body {
    set imgData [photo1 data -format ppm]
    photo2 put $imgData
    list [image width photo2] [image height photo2]
} -cleanup {
    imageCleanup
    unset imgData
} -result {256 256}
test imgPhoto-19.5 {MatchStirngFormat: unknown -format} -setup {
    image create photo photo1
} -body {
    photo1 put {} -format bogus
} -cleanup {
    imageCleanup
} -returnCodes error -result {image format "bogus" is not supported}
test imgPhoto-19.6 {MatchStringFormat: invalid data for default} -setup {
    image create photo photo1
} -body {
    photo1 put bogus
} -cleanup {
    imageCleanup
} -returnCodes error -result {invalid color name "bogus"}
test imgPhoto-19.7 {MatchStringFormat: invalid data for default} -setup {
    image create photo photo1
} -body {
    photo1 put bogus -format dEFault
} -cleanup {
    imageCleanup
} -returnCodes error -result {invalid color name "bogus"}
test imgPhoto-19.8 {MatchStirngFormat: invalid data for gif} -setup {
    image create photo photo1
} -body {
    photo1 put bogus -format giF
} -cleanup {
    imageCleanup
} -returnCodes error -result {couldn't recognize image data}

# Reject corrupted or truncated image [Bug b601ce3ab1].
# WARNING - tests 18.1-18.9 will cause a segfault on 8.5.19 and lower,
# WARNING - tests 20.1-20.9 will cause a segfault on 8.5.19 and lower,
#           and on 8.6.6 and lower.
test imgPhoto-18.1 {Reject corrupted GIF (binary string)} -constraints {
test imgPhoto-20.1 {Reject corrupted GIF (binary string)} -setup {
    base64PackageNeeded
} -setup {
    package require base64
    set data [base64::decode {
    set data [binary decode base64 {
	R0lGODlhAAQABP8zM/8z/zP/MzP/////M////yH5CiwheLrcLTBCd6Tv2qW16tdK4jhV
	5qpraXIvM1JlNyAgOw==
    }]
} -body {
    image create photo gif1 -data $data
} -cleanup {
    catch {image delete gif1}
} -returnCodes error -result {error reading color map|not enough free memory for image buffer} -match regexp
test imgPhoto-18.2 {Reject corrupted GIF (base 64 string)} -setup {
test imgPhoto-20.2 {Reject corrupted GIF (base 64 string)} -setup {
    set data {
	R0lGODlhAAQABP8zM/8z/zP/MzP/////M////yH5CiwheLrcLTBCd6Tv2qW16tdK4jhV
	5qpraXIvM1JlNyAgOw==
    }
} -body {
    image create photo gif1 -data $data
} -cleanup {
    catch {image delete gif1}
} -returnCodes error -result {error reading color map|not enough free memory for image buffer} -match regexp
test imgPhoto-18.3 {Reject corrupted GIF (file)} -setup {
test imgPhoto-20.3 {Reject corrupted GIF (file)} -setup {
    set fileName [file join [file dirname [info script]] corruptMangled.gif]
} -body {
    image create photo gif1 -file $fileName
} -cleanup {
    catch {image delete gif1}
} -returnCodes error -result {error reading color map|not enough free memory for image buffer} -match regexp
test imgPhoto-18.4 {Reject truncated GIF (binary string)} -constraints {
test imgPhoto-20.4 {Reject truncated GIF (binary string)} -setup {
    base64PackageNeeded
} -setup {
    package require base64
    set data [base64::decode {
    set data [binary decode base64 {
	R0lGODlhEAAQAMIHAAAAADMz//8zM/8z/zP/MzP///8=
    }]
} -body {
    image create photo gif1 -data $data
} -cleanup {
    catch {image delete gif1}
} -returnCodes error -result {error reading color map}
test imgPhoto-18.5 {Reject truncated GIF (base 64 string)} -setup {
test imgPhoto-20.5 {Reject truncated GIF (base 64 string)} -setup {
    set data {
	R0lGODlhEAAQAMIHAAAAADMz//8zM/8z/zP/MzP///8=
    }
} -body {
    image create photo gif1 -data $data
} -cleanup {
    catch {image delete gif1}
} -returnCodes error -result {error reading color map}
test imgPhoto-18.6 {Reject truncated GIF (file)} -setup {
test imgPhoto-20.6 {Reject truncated GIF (file)} -setup {
    set fileName [file join [file dirname [info script]] corruptTruncated.gif]
} -body {
    image create photo gif1 -file $fileName
} -cleanup {
    catch {image delete gif1}
} -returnCodes error -result {error reading color map}
test imgPhoto-18.7 {Reject corrupted GIF (> 4Gb) (binary string)} -constraints {
    base64PackageNeeded nonPortable
test imgPhoto-20.7 {Reject corrupted GIF (> 4Gb) (binary string)} -constraints {
    nonPortable
} -setup {
    # About the non portability constraint of this test: see ticket [cc42cc18a5]
    # If there is insufficient memory, the error message
    # {not enough free memory for image buffer} should be returned.
    # Instead, some systems (e.g. FreeBSD 11.1) terminate the test interpreter.
    package require base64
    set data [base64::decode {
    set data [binary decode base64 {
	R0lGODlhwmYz//8zM/8z/zP/MzP/////M////yH5Ciwhe
	LrcLTBCd6Tv2qW16tdK4jhV5qpraXIvM1JlNyAgOw==
    }]
} -body {
    image create photo gif1 -data $data
} -cleanup {
    catch {image delete gif1}
} -returnCodes error -result {error reading color map|not enough free memory for image buffer} -match regexp
test imgPhoto-18.8 {Reject corrupted GIF (> 4Gb) (base 64 string)} -constraints {
test imgPhoto-20.8 {Reject corrupted GIF (> 4Gb) (base 64 string)} -constraints {
    nonPortable
} -setup {
    # About the non portability constraint of this test: see ticket [cc42cc18a5]
    # If there is insufficient memory, the error message
    # {not enough free memory for image buffer} should be returned.
    # Instead, some systems (e.g. FreeBSD 11.1) terminate the test interpreter.
    set data {
	R0lGODlhwmYz//8zM/8z/zP/MzP/////M////yH5Ciwhe
	LrcLTBCd6Tv2qW16tdK4jhV5qpraXIvM1JlNyAgOw==
    }
} -body {
    image create photo gif1 -data $data
} -cleanup {
    catch {image delete gif1}
} -returnCodes error -result {error reading color map|not enough free memory for image buffer} -match regexp
test imgPhoto-18.9 {Reject corrupted GIF (> 4Gb) (file)} -constraints {
test imgPhoto-20.9 {Reject corrupted GIF (> 4Gb) (file)} -constraints {
    nonPortable
} -setup {
    # About the non portability constraint of this test: see ticket [cc42cc18a5]
    # If there is insufficient memory, the error message
    # {not enough free memory for image buffer} should be returned.
    # Instead, some systems (e.g. FreeBSD 11.1) terminate the test interpreter.
    set fileName [file join [file dirname [info script]] corruptMangled4G.gif]
} -body {
    image create photo gif1 -file $fileName
} -cleanup {
    catch {image delete gif1}
} -returnCodes error -result {error reading color map|not enough free memory for image buffer} -match regexp
test imgPhoto-18.10 {Valid GIF (binary string)} -constraints {
test imgPhoto-20.10 {Valid GIF (binary string)} -setup {
    base64PackageNeeded
} -setup {
    # Test the binary string reader with a valid GIF.
    # This is not tested elsewhere.
    # Tests 18.11, 18.12, with matching data, are included for completeness.
    # Tests 20.11, 20.12, with matching data, are included for completeness.
    package require base64
    set data [base64::decode {
    set data [binary decode base64 {
	R0lGODlhEAAQAMIHAAAAADMz//8zM/8z/zP/MzP/////M////yH5BAEKAAcALAAA
	AAAQABAAAAMheLrcLTBCd6QV79qlterXB0riOFXmmapraXIvM1IdZTcJADs=
    }]
} -body {
    image create photo gif1 -data $data
} -cleanup {
    catch {image delete gif1}
} -result gif1
test imgPhoto-18.11 {Valid GIF (base 64 string)} -setup {
test imgPhoto-20.11 {Valid GIF (base 64 string)} -setup {
    set data {
	R0lGODlhEAAQAMIHAAAAADMz//8zM/8z/zP/MzP/////M////yH5BAEKAAcALAAA
	AAAQABAAAAMheLrcLTBCd6QV79qlterXB0riOFXmmapraXIvM1IdZTcJADs=
    }
} -body {
    image create photo gif1 -data $data
} -cleanup {
    catch {image delete gif1}
} -result gif1
test imgPhoto-18.12 {Valid GIF (file)} -setup {
test imgPhoto-20.12 {Valid GIF (file)} -setup {
    set fileName [file join [file dirname [info script]] red.gif]
} -body {
    image create photo gif1 -file $fileName
} -cleanup {
    catch {image delete gif1}
} -result gif1

Added tests/imgSVGnano.test.






































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# This file is a Tcl script to test out the code in tkImgSVGnano.c, which reads
# and write SVG-format image files for photo widgets. The files is organized
# in the standard fashion for Tcl tests.
#
# Copyright © 2018 Rene Zaumseil
# All rights reserved.

package require tcltest 2.2
namespace import ::tcltest::*
eval tcltest::configure $argv
tcltest::loadTestedCommands
imageInit

namespace eval svgnano {

    variable data

    set data(plus) {\
            <svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
                <path fill="none" stroke="#000000" d="M0 0 h16 v16 h-16 z"/>
                <path fill="none" stroke="#000000" d="M8 4 v 8 M4 8 h 8"/>
                <circle fill="yellow" stroke="red" cx="10" cy="80" r="10" />
                <ellipse fill="none" stroke="blue" stroke-width="3" cx="60" cy="60" rx="10" ry="20" />
                <line x1="10" y1="90" x2="50" y2="99"/>
                <rect fill="none" stroke="green"  x="20" y="20" width="60" height="50" rx="3" ry="3"/>
                <polyline fill="red" stroke="purple" points="80,10 90,20 85,40"/>
                <polygon fill ="yellow" points="80,80 70,85 90,90"/>
                </svg>}
                set data(bad) {<svg xmlns="http://www.w3.org/2000/svg" width="0" height="0:w">
            </svg>\
    }

    tcltest::makeFile $data(plus) plus.svg
    set data(plusFilePath) [file join [tcltest::configure -tmpdir] plus.svg]

    tcltest::makeFile $data(bad) bad.svg
    set data(badFilePath) [file join [tcltest::configure -tmpdir] bad.svg]


test imgSVGnano-1.1 {reading simple image} -setup {
    catch {rename foo ""}
} -body {
    image create photo foo -data $data(plus)
    list [image width foo] [image height foo]
} -cleanup {
    rename foo ""
} -result {100 100}

test imgSVGnano-1.2 {simple image with options} -setup {
    catch {rename foo ""}
} -body {
    image create photo foo -data $data(plus) -format {svg -dpi 100 -scale 3}
    list [image width foo] [image height foo]
} -cleanup {
    rename foo ""
} -result {300 300}

# test on crash found by Koen Danckaert
test imgSVGnano-1.3 {reformat image options} -setup {
    catch {rename foo ""}
} -body {
    image create photo foo -data $data(plus)
    catch {foo configure -format {svg -scale}}
    list {}
} -cleanup {
    rename foo ""
} -result {{}}

test imgSVGnano-1.4 {image options} -setup {
    catch {rename foo ""}
} -body {
    image create photo foo -data $data(plus)
    foo configure -format {svg -scale 2}
    foo configure -format {svg -dpi 600}
    list [image width foo] [image height foo]
} -cleanup {
    rename foo ""
} -result {100 100}

test imgSVGnano-1.5 {reading simple image from file} -setup {
    catch {rename foo ""}
} -body {
    image create photo foo -file $data(plusFilePath)
    list [image width foo] [image height foo]
} -cleanup {
    rename foo ""
} -result {100 100}
test imgSVGnano-1.6 {simple image from file with options} -setup {
    catch {rename foo ""}
} -body {
    image create photo foo -file $data(plusFilePath) -format {svg -dpi 100 -scale 3}
    list [image width foo] [image height foo]
} -cleanup {
    rename foo ""
} -result {300 300}

test imgSVGnano-1.7 {very small scale gives 1x1 image} -body {
    image create photo foo -format "svg -scale 0.000001"\
	    -data $data(plus)
    list [image width foo] [image height foo]
} -cleanup {
    rename foo ""
} -result {1 1}
test imgSVGnano-1.8 {very small scale gives 1x1 image, from file} -body {
    image create photo foo -format "svg -scale 0.000001"\
	    -file $data(plusFilePath)
    list [image width foo] [image height foo]
} -cleanup {
    rename foo ""
} -result {1 1}

test imgSVGnano-2.1 {reading a bad image} -body {
    image create photo foo -format svg -data $data(bad)
} -returnCodes error -result {couldn't recognize image data}
test imgSVGnano-2.2 {using bad option} -body {
    image create photo foo -data $data(plus) -format {svg -scale 0}
} -returnCodes error -result {-scale value must be positive}
test imgSVGnano-2.3 {using bad option} -body {
    image create photo foo -data $data(plus)
    foo configure -format {svg 1.0}
} -cleanup {
    rename foo ""
} -returnCodes error -result {bad option "1.0": must be -dpi, -scale, -scaletoheight, or -scaletowidth}
test imgSVGnano-2.4 {reading a bad image from file} -body {
    image create photo foo -format svg -file $data(badFilePath)
} -returnCodes error -match glob\
    -result {couldn't recognize data in image file "*/bad.svg"}

# -scaletoheight and -scaletowidth options
test imgSVGnano-3.1 {multiple scale options} -body {
    image create photo foo -format "svg -scale 1 -scaletowidth 20"\
	    -data $data(bad)
} -returnCodes error -result {only one of -scale, -scaletoheight, -scaletowidth may be given}

test imgSVGnano-3.2 {no number parameter to -scaletowidth} -body {
    image create photo foo -format "svg -scaletowidth invalid"\
	    -data $data(plus)
} -returnCodes error -result {expected integer but got "invalid"}

test imgSVGnano-3.3 {no number parameter to -scaletoheight} -body {
    image create photo foo -format "svg -scaletoheight invalid"\
	    -data $data(plus)
} -returnCodes error -result {expected integer but got "invalid"}

test imgSVGnano-3.4 {zero parameter to -scaletowidth} -body {
    image create photo foo -format "svg -scaletowidth 0"\
	    -data $data(plus)
} -returnCodes error -result {-scaletowidth value must be positive}

test imgSVGnano-3.5 {zero parameter to -scaletoheight} -body {
    image create photo foo -format "svg -scaletoheight 0"\
	    -data $data(plus)
} -returnCodes error -result {-scaletoheight value must be positive}

test imgSVGnano-3.6 {no number parameter to -scaletoheight} -body {
    image create photo foo -format "svg -scaletoheight invalid"\
	    -data $data(plus)
} -returnCodes error -result {expected integer but got "invalid"}

test imgSVGnano-3.7 {option -scaletowidth} -body {
    image create photo foo -format "svg -scaletowidth 20"\
	    -data $data(plus)
    image width foo
} -cleanup {
    rename foo ""
} -result 20

test imgSVGnano-3.8 {option -scaletoheight} -body {
    image create photo foo -format "svg -scaletoheight 20"\
	    -data $data(plus)
    image height foo
} -cleanup {
    rename foo ""
} -result 20

test imgSVGnano-3.10 {change from -scaletoheight to -scale} -body {
    set res {}
    image create photo foo -format "svg -scaletoheight 16"\
	    -data $data(plus)
    lappend res [image width foo] [image height foo]
    foo configure -format "svg -scale 2"
    lappend res [image width foo] [image height foo]
} -cleanup {
    rename foo ""
    unset res
} -result {16 16 200 200}

# svg file access
test imgSVGnano-4.1 {reread file on configure -scale} -setup {
    catch {rename foo ""}
    set res {}
} -body {
    image create photo foo -file $data(plusFilePath)
    lappend res [image width foo] [image height foo]
    foo configure -format "svg -scale 2"
    lappend res [image width foo] [image height foo]
} -cleanup {
    rename foo ""
    unset res
} -result {100 100 200 200}

test imgSVGnano-4.2 {error on file not accessible on reread due to configure} -setup {
    catch {rename foo ""}
    tcltest::makeFile $data(plus) tmpplus.svg
    image create photo foo -file [file join [tcltest::configure -tmpdir] tmpplus.svg]
    tcltest::removeFile tmpplus.svg
} -body {
    foo configure -format "svg -scale 2"
} -cleanup {
    rename foo ""
    tcltest::removeFile tmpplus.svg
} -returnCodes error -match glob -result {couldn't open "*/tmpplus.svg": no such file or directory}

# Special images
test imgSVGnano-5.0 {image without any of  "width", "height" and "viewbox"} -body {
    image create photo foo -data\
			{<?xml version="1.0"?><!DOCTYPE svg PUBLIC\
			"-//W3C//DTD SVG 1.0//EN\"\
			"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">\
			<svg xmlns="http://www.w3.org/2000/svg">\
			<g style="fill-opacity:0.7;">\
			<circle cx="6.5cm" cy="2cm" r="100" style="fill:green;\
			stroke:black; stroke-width:0.1cm" transform="translate(-70,150)"/>\
			</g></svg>}
} -cleanup {
    rename foo ""
} -result {foo}

test imgSVGnano-5.1 {bug ea665e08f3 - too many values in parameters of the transform attribute} -body {
    # shall not loop endlessly
    image create photo foo -data\
			{<?xml version="1.0"?><!DOCTYPE svg PUBLIC\
			"-//W3C//DTD SVG 1.0//EN\"\
			"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">\
			<svg xmlns="http://www.w3.org/2000/svg">\
			<circle cx="6.5cm" cy="2cm" r="100" transform="skewX(1 1)"/>\
			</g></svg>}
} -cleanup {
    rename foo ""
} -result {foo}

test imgSVGnano-5.2 {bug d6e9b4db40 - "<svg" and ">" must be present} -body {
    image create photo foo -format svg -data\
			{<?xml version="1.0"?><!DOCTYPE svg PUBLIC\
			"-//W3C//DTD SVG 1.0//EN\" \
			"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">\
			<sERRORvBADFILEg xmlns="http://www.w3.org/2000/svg">\
			<circle cx="6.5cm" cy="2cm" r="100" transform="skewX(1 1)"/>\
			</g></svg>}
} -returnCodes error -result {couldn't recognize image data}

};# end of namespace svgnano

namespace delete svgnano
imageFinish
cleanupTests
return

# Local Variables:
# mode: tcl
# fill-column: 78
# End:
Changes to tests/listbox.test.
1
2
3
4
5
6



7
8
9
10
11
12
13
1
2
3



4
5
6
7
8
9
10
11
12
13



-
-
-
+
+
+







# This file is a Tcl script to test out the "listbox" command
# of Tk.  It is organized in the standard fashion for Tcl tests.
#
# 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.
# All rights reserved.

package require tcltest 2.2
eval tcltest::configure $argv
tcltest::loadTestedCommands
namespace import -force tcltest::test

372
373
374
375
376
377
378
379

380
381
382
383

384
385
386
387

388
389
390
391
392
393
394
372
373
374
375
376
377
378

379
380
381
382

383
384
385
386

387
388
389
390
391
392
393
394







-
+



-
+



-
+







test listbox-3.5 {ListboxWidgetCmd procedure, "activate" option} -body {
    .l activate 3
    .l index active
} -result 3
test listbox-3.6 {ListboxWidgetCmd procedure, "activate" option} -body {
    .l activate -1
    .l index active
} -result {0}
} -result 0
test listbox-3.7 {ListboxWidgetCmd procedure, "activate" option} -body {
    .l activate 30
    .l index active
} -result {17}
} -result 17
test listbox-3.8 {ListboxWidgetCmd procedure, "activate" option} -body {
    .l activate end
    .l index active
} -result {17}
} -result 17
test listbox-3.9 {ListboxWidgetCmd procedure, "bbox" option} -body {
    .l bbox
} -returnCodes error -result {wrong # args: should be ".l bbox index"}
test listbox-3.10 {ListboxWidgetCmd procedure, "bbox" option} -body {
    .l bbox a b
} -returnCodes error -result {wrong # args: should be ".l bbox index"}
test listbox-3.11 {ListboxWidgetCmd procedure, "bbox" option} -body {
504
505
506
507
508
509
510
511

512
513
514
515
516
517
518
519
520
521
522
523

524
525
526

527
528
529
530
531
532
533
504
505
506
507
508
509
510

511
512
513
514
515
516
517
518
519
520
521
522

523
524
525

526
527
528
529
530
531
532
533







-
+











-
+


-
+







    for {set i 0} {$i < [llength $lres]} {incr i 4} {
        set res [expr {$res * [expr {[lindex $lres $i] >= 0}] }]
    }
    set res
} -cleanup {
    destroy .top.l .top
    unset -nocomplain lres res
} -result {1}
} -result 1
test listbox-3.19 {ListboxWidgetCmd procedure, "cget" option} -body {
    .l cget
} -returnCodes error -result {wrong # args: should be ".l cget option"}
test listbox-3.20 {ListboxWidgetCmd procedure, "cget" option} -body {
    .l cget a b
} -returnCodes error -result {wrong # args: should be ".l cget option"}
test listbox-3.21 {ListboxWidgetCmd procedure, "cget" option} -body {
    .l cget -gorp
} -returnCodes error -result {unknown option "-gorp"}
test listbox-3.22 {ListboxWidgetCmd procedure, "cget" option} -body {
    .l cget -setgrid
} -result {0}
} -result 0
test listbox-3.23 {ListboxWidgetCmd procedure, "configure" option} -body {
    llength [.l configure]
} -result {28}
} -result 28
test listbox-3.24 {ListboxWidgetCmd procedure, "configure" option} -body {
    .l configure -gorp
} -returnCodes error -result {unknown option "-gorp"}
test listbox-3.25 {ListboxWidgetCmd procedure, "configure" option} -body {
    .l configure -setgrid
} -result {-setgrid setGrid SetGrid 0 0}
test listbox-3.26 {ListboxWidgetCmd procedure, "configure" option} -body {
583
584
585
586
587
588
589
590

591
592
593
594
595
596
597
598
599
600

601
602
603
604
605
606
607
583
584
585
586
587
588
589

590
591
592
593
594
595
596
597
598
599

600
601
602
603
604
605
606
607







-
+









-
+







    destroy .l2
} -result {el1 el5 5}
test listbox-3.36 {ListboxWidgetCmd procedure, "delete" option} -setup {
    destroy .l2
} -body {
    listbox .l2
    .l2 insert 0 el0 el1 el2 el3 el4 el5 el6 el7
    .l2 delete -3 2
    .l2 delete -1 2
    .l2 get 0 end
} -cleanup {
    destroy .l2
} -result {el3 el4 el5 el6 el7}
test listbox-3.37 {ListboxWidgetCmd procedure, "delete" option} -setup {
    destroy .l2
} -body {
    listbox .l2
    .l2 insert 0 el0 el1 el2 el3 el4 el5 el6 el7
    .l2 delete -3 -1
    .l2 delete -1 -1
    .l2 get 0 end
} -cleanup {
    destroy .l2
} -result {el0 el1 el2 el3 el4 el5 el6 el7}
test listbox-3.38 {ListboxWidgetCmd procedure, "delete" option} -setup {
    destroy .l2
} -body {
680
681
682
683
684
685
686
687

688
689
690

691
692
693
694
695
696
697
680
681
682
683
684
685
686

687
688
689

690
691
692
693
694
695
696
697







-
+


-
+







} -cleanup {
    destroy .l2
} -result {{two words} el4 el5 el6 el7}
test listbox-3.49 {ListboxWidgetCmd procedure, "get" option} -body {
    .l get -1
} -result {}
test listbox-3.50 {ListboxWidgetCmd procedure, "get" option} -body {
    .l get -2 -1
    .l get -1 -1
} -result {}
test listbox-3.51 {ListboxWidgetCmd procedure, "get" option} -body {
    .l get -2 3
    .l get -1 3
} -result {el0 el1 el2 el3}
test listbox-3.52 {ListboxWidgetCmd procedure, "get" option} -body {
    .l get 12 end
} -result {el12 el13 el14 el15 el16 el17}
test listbox-3.53 {ListboxWidgetCmd procedure, "get" option} -body {
    .l get 12 20
} -result {el12 el13 el14 el15 el16 el17}
714
715
716
717
718
719
720
721

722
723
724
725
726
727

728
729
730
731
732
733
734
714
715
716
717
718
719
720

721
722
723
724
725
726

727
728
729
730
731
732
733
734







-
+





-
+







    .l index @
} -returnCodes error -result {bad listbox index "@": must be active, anchor, end, @x,y, or a number}
test listbox-3.60 {ListboxWidgetCmd procedure, "index" option} -body {
    .l index 2
} -result 2
test listbox-3.61 {ListboxWidgetCmd procedure, "index" option} -body {
    .l index -1
} -result {-1}
} -result -1
test listbox-3.62 {ListboxWidgetCmd procedure, "index" option} -body {
    .l index end
} -result 18
test listbox-3.63 {ListboxWidgetCmd procedure, "index" option} -body {
    .l index 34
} -result 34
} -result 18
test listbox-3.64 {ListboxWidgetCmd procedure, "insert" option} -body {
    .l insert
} -returnCodes error -result {wrong # args: should be ".l insert index ?element ...?"}
test listbox-3.65 {ListboxWidgetCmd procedure, "insert" option} -body {
    .l insert badIndex
} -returnCodes error -result {bad listbox index "badIndex": must be active, anchor, end, @x,y, or a number}
test listbox-3.66 {ListboxWidgetCmd procedure, "insert" option} -setup {
779
780
781
782
783
784
785
786

787
788
789
790
791
792
793
779
780
781
782
783
784
785

786
787
788
789
790
791
792
793







-
+







} -returnCodes error -result {wrong # args: should be ".l nearest y"}
test listbox-3.72 {ListboxWidgetCmd procedure, "nearest" option} -body {
    .l nearest 20p
} -returnCodes error -result {expected integer but got "20p"}
test listbox-3.73 {ListboxWidgetCmd procedure, "nearest" option} -body {
    .l yview 3
    .l nearest 1000
} -result {7}
} -result 7
test listbox-3.74 {ListboxWidgetCmd procedure, "scan" option} -body {
    .l scan a b
} -returnCodes error -result {wrong # args: should be ".l scan mark|dragto x y"}
test listbox-3.75 {ListboxWidgetCmd procedure, "scan" option} -body {
    .l scan a b c d
} -returnCodes error -result {wrong # args: should be ".l scan mark|dragto x y"}
test listbox-3.76 {ListboxWidgetCmd procedure, "scan" option} -body {
826
827
828
829
830
831
832
833

834
835
836
837
838

839
840
841
842
843

844
845
846
847
848

849
850
851
852
853

854
855
856
857
858

859
860
861
862
863

864
865
866
867
868

869
870
871
872
873

874
875
876
877
878

879
880
881
882
883
884
885
826
827
828
829
830
831
832

833
834
835
836
837

838
839
840
841
842

843
844
845
846
847

848
849
850
851
852

853
854
855
856
857

858
859
860
861
862

863
864
865
866
867

868
869
870
871
872

873
874
875
876
877

878
879
880
881
882
883
884
885







-
+




-
+




-
+




-
+




-
+




-
+




-
+




-
+




-
+




-
+







test listbox-3.82 {ListboxWidgetCmd procedure, "see" option} -body {
    .l see gorp
} -returnCodes error -result {bad listbox index "gorp": must be active, anchor, end, @x,y, or a number}
test listbox-3.83 {ListboxWidgetCmd procedure, "see" option} -body {
    .l yview 7
    .l see 7
    .l index @0,0
} -result {7}
} -result 7
test listbox-3.84 {ListboxWidgetCmd procedure, "see" option} -body {
    .l yview 7
    .l see 11
    .l index @0,0
} -result {7}
} -result 7
test listbox-3.85 {ListboxWidgetCmd procedure, "see" option} -body {
    .l yview 7
    .l see 6
    .l index @0,0
} -result {6}
} -result 6
test listbox-3.86 {ListboxWidgetCmd procedure, "see" option} -body {
    .l yview 7
    .l see 5
    .l index @0,0
} -result {3}
} -result 3
test listbox-3.87 {ListboxWidgetCmd procedure, "see" option} -body {
    .l yview 7
    .l see 12
    .l index @0,0
} -result {8}
} -result 8
test listbox-3.88 {ListboxWidgetCmd procedure, "see" option} -body {
    .l yview 7
    .l see 13
    .l index @0,0
} -result {11}
} -result 11
test listbox-3.89 {ListboxWidgetCmd procedure, "see" option} -body {
    .l yview 7
    .l see -1
    .l index @0,0
} -result {0}
} -result 0
test listbox-3.90 {ListboxWidgetCmd procedure, "see" option} -body {
    .l yview 7
    .l see end
    .l index @0,0
} -result {13}
} -result 13
test listbox-3.91 {ListboxWidgetCmd procedure, "see" option} -body {
    .l yview 7
    .l see 322
    .l index @0,0
} -result {13}
} -result 13
test listbox-3.92 {ListboxWidgetCmd procedure, "see" option, partial last line} -body {
    mkPartial
    .partial.l see 4
    .partial.l index @0,0
} -result {1}
} -result 1
test listbox-3.93 {ListboxWidgetCmd procedure, "selection" option} -body {
    .l select a
} -returnCodes error -result {wrong # args: should be ".l selection option index ?index?"}
test listbox-3.94 {ListboxWidgetCmd procedure, "selection" option} -body {
    .l select a b c d
} -returnCodes error -result {wrong # args: should be ".l selection option index ?index?"}
test listbox-3.95 {ListboxWidgetCmd procedure, "selection" option} -body {
894
895
896
897
898
899
900
901

902
903
904
905

906
907
908
909

910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929

930
931
932
933
934

935
936
937
938

939
940
941
942
943
944
945
946

947
948
949
950
951
952
953
894
895
896
897
898
899
900

901
902
903
904

905
906
907
908

909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928

929
930
931
932
933

934
935
936
937

938
939
940
941
942
943
944
945

946
947
948
949
950
951
952
953







-
+



-
+



-
+



















-
+




-
+



-
+







-
+







test listbox-3.98 {ListboxWidgetCmd procedure, "selection" option} -body {
    list [.l selection anchor 5; .l index anchor] \
	    [.l selection anchor 0; .l index anchor]
} -result {5 0}
test listbox-3.99 {ListboxWidgetCmd procedure, "selection" option} -body {
    .l selection anchor -1
    .l index anchor
} -result {0}
} -result 0
test listbox-3.100 {ListboxWidgetCmd procedure, "selection" option} -body {
    .l selection anchor end
    .l index anchor
} -result {17}
} -result 17
test listbox-3.101 {ListboxWidgetCmd procedure, "selection" option} -body {
    .l selection anchor 44
    .l index anchor
} -result {17}
} -result 17
test listbox-3.102 {ListboxWidgetCmd procedure, "selection" option} -body {
    .l selection clear 0 end
    .l selection set 2 8
    .l selection clear 3 4
    .l curselection
} -result {2 5 6 7 8}
test listbox-3.103 {ListboxWidgetCmd procedure, "selection" option} -body {
    .l selection includes 0 0
} -returnCodes error -result {wrong # args: should be ".l selection includes index"}
test listbox-3.104 {ListboxWidgetCmd procedure, "selection" option} -body {
    .l selection clear 0 end
    .l selection set 2 8
    .l selection clear 4
    list [.l selection includes 3] [.l selection includes 4] \
	    [.l selection includes 5]
} -result {1 0 1}
test listbox-3.105 {ListboxWidgetCmd procedure, "selection" option} -body {
    .l selection set 0 end
    .l selection includes -1
} -result {0}
} -result 0
test listbox-3.106 {ListboxWidgetCmd procedure, "selection" option} -body {
    .l selection clear 0 end
    .l selection set end
    .l selection includes end
} -result {1}
} -result 1
test listbox-3.107 {ListboxWidgetCmd procedure, "selection" option} -body {
    .l selection set 0 end
    .l selection includes 44
} -result {0}
} -result 0
test listbox-3.108 {ListboxWidgetCmd procedure, "selection" option} -setup {
    destroy .l2
} -body {
    listbox .l2
    .l2 selection includes 0
} -cleanup {
    destroy .l2
} -result {0}
} -result 0
test listbox-3.109 {ListboxWidgetCmd procedure, "selection" option} -body {
    .l selection clear 0 end
    .l selection set 2
    .l selection set 5 7
    .l curselection
} -result {2 5 6 7}
test listbox-3.110 {ListboxWidgetCmd procedure, "selection" option} -body {
961
962
963
964
965
966
967
968

969
970
971
972
973
974
975
961
962
963
964
965
966
967

968
969
970
971
972
973
974
975







-
+







    .l selection badOption 0 0
} -returnCodes error -result {bad option "badOption": must be anchor, clear, includes, or set}
test listbox-3.112 {ListboxWidgetCmd procedure, "size" option} -body {
    .l size a
} -returnCodes error -result {wrong # args: should be ".l size"}
test listbox-3.113 {ListboxWidgetCmd procedure, "size" option} -body {
    .l size
} -result {18}
} -result 18
test listbox-3.114 {ListboxWidgetCmd procedure, "xview" option} -setup {
    destroy .l2
} -body {
    listbox .l2
    update
    format {%.6g %.6g} {*}[.l2 xview]
} -cleanup {
1238
1239
1240
1241
1242
1243
1244
1245

1246
1247
1248
1249
1250
1251
1252
1238
1239
1240
1241
1242
1243
1244

1245
1246
1247
1248
1249
1250
1251
1252







-
+







    pack .l
    update
} -body {
    .l configure -highlightthickness -3
    .l cget -highlightthickness
} -cleanup {
    deleteWindows
} -result {0}
} -result 0
test listbox-4.3 {ConfigureListbox procedure} -setup {
    deleteWindows
    destroy .l
    listbox .l -setgrid 1 -width 25 -height 15
    pack .l
    update
} -body {
1569
1570
1571
1572
1573
1574
1575
1576

1577
1578
1579
1580
1581
1582
1583

1584
1585
1586
1587
1588
1589
1590
1591

1592
1593
1594
1595
1596
1597
1598
1599

1600
1601
1602
1603
1604
1605
1606

1607
1608
1609
1610
1611
1612
1613

1614
1615
1616
1617
1618

1619
1620
1621
1622
1623

1624
1625
1626
1627
1628
1629
1630
1569
1570
1571
1572
1573
1574
1575

1576
1577
1578
1579
1580
1581
1582

1583
1584
1585
1586
1587
1588
1589
1590

1591
1592
1593
1594
1595
1596
1597
1598

1599
1600
1601
1602
1603
1604
1605

1606
1607
1608
1609
1610
1611
1612

1613
1614
1615
1616
1617

1618
1619
1620
1621
1622

1623
1624
1625
1626
1627
1628
1629
1630







-
+






-
+







-
+







-
+






-
+






-
+




-
+




-
+







} -result {q r s a b A c d x y z}
test listbox-6.2 {InsertEls procedure} -body {
    .l delete 0 end
    .l insert 0 a b c d e f g h i j
    .l selection anchor 2
    .l insert 2 A B
    .l index anchor
} -result {4}
} -result 4
test listbox-6.3 {InsertEls procedure} -body {
    .l delete 0 end
    .l insert 0 a b c d e f g h i j
    .l selection anchor 2
    .l insert 3 A B
    .l index anchor
} -result {2}
} -result 2
test listbox-6.4 {InsertEls procedure} -body {
    .l delete 0 end
    .l insert 0 a b c d e f g h i j
    .l yview 3
    update
    .l insert 2 A B
    .l index @0,0
} -result {5}
} -result 5
test listbox-6.5 {InsertEls procedure} -body {
    .l delete 0 end
    .l insert 0 a b c d e f g h i j
    .l yview 3
    update
    .l insert 3 A B
    .l index @0,0
} -result {3}
} -result 3
test listbox-6.6 {InsertEls procedure} -body {
    .l delete 0 end
    .l insert 0 a b c d e f g h i j
    .l activate 5
    .l insert 5 A B
    .l index active
} -result {7}
} -result 7
test listbox-6.7 {InsertEls procedure} -body {
    .l delete 0 end
    .l insert 0 a b c d e f g h i j
    .l activate 5
    .l insert 6 A B
    .l index active
} -result {5}
} -result 5
test listbox-6.8 {InsertEls procedure} -body {
    .l delete 0 end
    .l insert 0 a b c
    .l index active
} -result {2}
} -result 2
test listbox-6.9 {InsertEls procedure} -body {
    .l delete 0 end
    .l insert 0
    .l index active
} -result {0}
} -result 0
test listbox-6.10 {InsertEls procedure} -body {
    .l delete 0 end
    .l insert 0 a b "two words"  c d e f g h i j
    update
    set log {}
    .l insert 0 word
    update
1724
1725
1726
1727
1728
1729
1730
1731

1732
1733
1734
1735
1736
1737
1738

1739
1740
1741
1742
1743
1744
1745

1746
1747
1748
1749
1750
1751
1752

1753
1754
1755
1756
1757
1758
1759
1760

1761
1762
1763
1764
1765
1766
1767
1768

1769
1770
1771
1772
1773
1774
1775
1776

1777
1778
1779
1780
1781
1782
1783
1784

1785
1786
1787
1788
1789
1790
1791

1792
1793
1794
1795
1796
1797
1798

1799
1800
1801
1802
1803
1804
1805

1806
1807
1808
1809
1810
1811
1812

1813
1814
1815
1816
1817
1818
1819

1820
1821
1822
1823
1824
1825
1826
1724
1725
1726
1727
1728
1729
1730

1731
1732
1733
1734
1735
1736
1737

1738
1739
1740
1741
1742
1743
1744

1745
1746
1747
1748
1749
1750
1751

1752
1753
1754
1755
1756
1757
1758
1759

1760
1761
1762
1763
1764
1765
1766
1767

1768
1769
1770
1771
1772
1773
1774
1775

1776
1777
1778
1779
1780
1781
1782
1783

1784
1785
1786
1787
1788
1789
1790

1791
1792
1793
1794
1795
1796
1797

1798
1799
1800
1801
1802
1803
1804

1805
1806
1807
1808
1809
1810
1811

1812
1813
1814
1815
1816
1817
1818

1819
1820
1821
1822
1823
1824
1825
1826







-
+






-
+






-
+






-
+







-
+







-
+







-
+







-
+






-
+






-
+






-
+






-
+






-
+







} -result {8 h}
test listbox-7.5 {DeleteEls procedure} -body {
    .l delete 0 end
    .l insert 0 a b c d e f g h i j
    .l selection anchor 2
    .l delete 0 1
    .l index anchor
} -result {0}
} -result 0
test listbox-7.6 {DeleteEls procedure} -body {
    .l delete 0 end
    .l insert 0 a b c d e f g h i j
    .l selection anchor 2
    .l delete 2
    .l index anchor
} -result {2}
} -result 2
test listbox-7.7 {DeleteEls procedure} -body {
    .l delete 0 end
    .l insert 0 a b c d e f g h i j
    .l selection anchor 4
    .l delete 2 5
    .l index anchor
} -result {2}
} -result 2
test listbox-7.8 {DeleteEls procedure} -body {
    .l delete 0 end
    .l insert 0 a b c d e f g h i j
    .l selection anchor 3
    .l delete 4 5
    .l index anchor
} -result {3}
} -result 3
test listbox-7.9 {DeleteEls procedure} -body {
    .l delete 0 end
    .l insert 0 a b c d e f g h i j
    .l yview 3
    update
    .l delete 1 2
    .l index @0,0
} -result {1}
} -result 1
test listbox-7.10 {DeleteEls procedure} -body {
    .l delete 0 end
    .l insert 0 a b c d e f g h i j
    .l yview 3
    update
    .l delete 3 4
    .l index @0,0
} -result {3}
} -result 3
test listbox-7.11 {DeleteEls procedure} -body {
    .l delete 0 end
    .l insert 0 a b c d e f g h i j
    .l yview 3
    update
    .l delete 4 6
    .l index @0,0
} -result {3}
} -result 3
test listbox-7.12 {DeleteEls procedure} -body {
    .l delete 0 end
    .l insert 0 a b c d e f g h i j
    .l yview 3
    update
    .l delete 3 end
    .l index @0,0
} -result {1}
} -result 1
test listbox-7.13 {DeleteEls procedure, updating view with partial last line} -body {
    mkPartial
    .partial.l yview 8
    update
    .partial.l delete 10 13
    .partial.l index @0,0
} -result {7}
} -result 7
test listbox-7.14 {DeleteEls procedure} -body {
    .l delete 0 end
    .l insert 0 a b c d e f g h i j
    .l activate 6
    .l delete 3 4
    .l index active
} -result {4}
} -result 4
test listbox-7.15 {DeleteEls procedure} -body {
    .l delete 0 end
    .l insert 0 a b c d e f g h i j
    .l activate 6
    .l delete 5 7
    .l index active
} -result {5}
} -result 5
test listbox-7.16 {DeleteEls procedure} -body {
    .l delete 0 end
    .l insert 0 a b c d e f g h i j
    .l activate 6
    .l delete 5 end
    .l index active
} -result {4}
} -result 4
test listbox-7.17 {DeleteEls procedure} -body {
    .l delete 0 end
    .l insert 0 a b c d e f g h i j
    .l activate 6
    .l delete 0 end
    .l index active
} -result {0}
} -result 0
test listbox-7.18 {DeleteEls procedure} -body {
    .l delete 0 end
    .l insert 0 a b c "two words" d e f g h i j
    update
    set log {}
    .l delete 4 6
    update
1983
1984
1985
1986
1987
1988
1989
1990

1991
1992
1993
1994
1995
1996
1997
1983
1984
1985
1986
1987
1988
1989

1990
1991
1992
1993
1994
1995
1996
1997







-
+







} -body {
    pack [listbox .l]
    .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11
    update
    .l index end
} -cleanup {
    destroy .l
} -result {12}
} -result 12
test listbox-10.6 {GetListboxIndex procedure} -setup {
    destroy .l
} -body {
    pack [listbox .l]
    .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11
    update
    .l get end
2098
2099
2100
2101
2102
2103
2104
2105

2106
2107
2108
2109
2110
2111
2112
2113
2114
2115

2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132

2133
2134
2135

2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146

2147
2148
2149
2150
2151
2152
2153
2098
2099
2100
2101
2102
2103
2104

2105
2106
2107
2108
2109
2110
2111
2112
2113
2114

2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131

2132
2133
2134

2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145

2146
2147
2148
2149
2150
2151
2152
2153







-
+









-
+
















-
+


-
+










-
+







} -body {
    pack [listbox .l]
    .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11
    update
    .l index 3
} -cleanup {
    destroy .l
} -result {3}
} -result 3
test listbox-10.17 {GetListboxIndex procedure} -setup {
    destroy .l
} -body {
    pack [listbox .l]
    .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11
    update
    .l index 20
} -cleanup {
    destroy .l
} -result {20}
} -result 12
test listbox-10.18 {GetListboxIndex procedure} -setup {
    destroy .l
} -body {
    pack [listbox .l]
    .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11
    update
    .l get 20
} -cleanup {
    destroy .l
} -result {}
test listbox-10.19 {GetListboxIndex procedure} -setup {
    destroy .l
} -body {
    pack [listbox .l]
    .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11
    update
    .l index -2
    .l index -1
} -cleanup {
    destroy .l
} -result  -2
} -result -1
test listbox-10.20 {GetListboxIndex procedure} -setup {
    destroy .l
} -body {
    pack [listbox .l]
    .l insert 0 el0 el1 el2 el3 el4 el5 el6 el7 el8 el9 el10 el11
    .l delete 0 end
    update
    .l index 1
} -cleanup {
    destroy .l
} -result 1
} -result 0


test listbox-11.1 {ChangeListboxView procedure, boundary conditions for index} -setup {
    destroy .l
} -body {
    listbox .l -height 5
    pack .l
2222
2223
2224
2225
2226
2227
2228
2229

2230
2231
2232
2233
2234
2235
2236
2222
2223
2224
2225
2226
2227
2228

2229
2230
2231
2232
2233
2234
2235
2236







-
+







} -result {{0.3 0.8} {}}
test listbox-11.6 {ChangeListboxView procedure, partial last line} -body {
    mkPartial
    .partial.l yview 13
    .partial.l index @0,0
} -cleanup {
    destroy .l
} -result {11}
} -result 11


# Listbox used in 12.* tests
destroy .l
listbox .l -font $fixed -xscrollcommand "record x" -width 10
.l insert 0 0123456789a123456789b123456789c123456789d123456789e123456789f123456789g123456789h123456789i123456789
pack .l
2310
2311
2312
2313
2314
2315
2316
2317

2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329

2330
2331
2332
2333
2334
2335
2336
2337
2338
2339

2340
2341
2342
2343
2344
2345
2346
2310
2311
2312
2313
2314
2315
2316

2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328

2329
2330
2331
2332
2333
2334
2335
2336
2337
2338

2339
2340
2341
2342
2343
2344
2345
2346







-
+











-
+









-
+







    lappend x [format {%.6g %.6g} {*}[.l xview]] [format {%.6g %.6g} {*}[.l yview]]
} -result {{0.8 1} {0.75 1} {0.6 0.8} {0.25 0.5}}


test listbox-14.1 {NearestListboxElement procedure, partial last line} -body {
    mkPartial
    .partial.l nearest [winfo height .partial.l]
} -result {4}
} -result 4
# Listbox used in 14.* tests
destroy .l
listbox .l -font $fixed -width 20 -height 10
.l insert 0 a b c d e f g h i j k l m n o p q r s t
.l yview 4
pack .l
update
test listbox-14.2 {NearestListboxElement procedure} -constraints {
	fonts
} -body {
    .l index @50,0
} -result {4}
} -result 4
test listbox-14.3 {NearestListboxElement procedure} -constraints {
	fonts
} -body {
    list [.l index @50,35] [.l index @50,36]
} -result {5 6}
test listbox-14.4 {NearestListboxElement procedure} -constraints {
	fonts
} -body {
    .l index @50,200
} -result {13}
} -result 13


# Listbox used in 15.* 16.* and 17.* tests
destroy .l
listbox .l -font $fixed -width 20 -height 10
pack .l
update
2374
2375
2376
2377
2378
2379
2380
2381

2382
2383
2384
2385
2386
2387
2388
2374
2375
2376
2377
2378
2379
2380

2381
2382
2383
2384
2385
2386
2387
2388







-
+







    .l select set 0 end
    .l curselection
} -result {}
test listbox-15.4 {ListboxSelect procedure, boundary conditions for indices} -body {
    .l delete 0 end
    .l insert 0 a b c d e f
    .l select clear 0 end
    .l select set -2 -1
    .l select set -1 -1
    .l curselection
} -result {}
test listbox-15.5 {ListboxSelect procedure, boundary conditions for indices} -body {
    .l delete 0 end
    .l insert 0 a b c d e f
    .l select clear 0 end
    .l select set -1 3
2411
2412
2413
2414
2415
2416
2417
2418

2419
2420
2421
2422
2423
2424
2425
2411
2412
2413
2414
2415
2416
2417

2418
2419
2420
2421
2422
2423
2424
2425







-
+







} -result {4 5}
test listbox-15.9 {ListboxSelect procedure, boundary conditions for indices} -body {
    .l delete 0 end
    .l insert 0 a b c d e f
    .l select clear 0 end
    .l select set end 30
    .l curselection
} -result {5}
} -result 5
test listbox-15.10 {ListboxSelect procedure, boundary conditions for indices} -body {
    .l delete 0 end
    .l insert 0 a b c d e f
    .l select clear 0 end
    .l select set 20 25
    .l curselection
} -result {}
2447
2448
2449
2450
2451
2452
2453
2454

2455
2456
2457
2458
2459
2460
2461
2447
2448
2449
2450
2451
2452
2453

2454
2455
2456
2457
2458
2459
2460
2461







-
+







    .l delete 0 end
    .l insert 0 1$long 2$long 3$long 4$long 5$long
    .l selection set 0 end
    set sel [selection get]
    string compare 1$long\n2$long\n3$long\n4$long\n5$long $sel
} -cleanup {
    catch {unset long sel}
} -result {0}
} -result 0


test listbox-17.1 {ListboxLostSelection procedure} -setup {
    destroy .e
} -body {
    .l delete 0 end
    .l insert 0 a b c d e
2658
2659
2660
2661
2662
2663
2664
2665

2666
2667
2668
2669
2670


2671
2672

2673
2674

2675
2676
2677
2678
2679

2680
2681
2682
2683
2684
2685
2686
2687
2688


2689
2690

2691
2692

2693
2694

2695
2696
2697
2698
2699

2700
2701
2702
2703
2704
2705
2706
2658
2659
2660
2661
2662
2663
2664

2665
2666

2667


2668
2669
2670

2671
2672

2673
2674
2675
2676


2677
2678
2679
2680
2681
2682

2683


2684
2685
2686

2687
2688

2689
2690

2691
2692
2693
2694


2695
2696
2697
2698
2699
2700
2701
2702







-
+

-

-
-
+
+

-
+

-
+



-
-
+





-

-
-
+
+

-
+

-
+

-
+



-
-
+







    .l curselection
} -cleanup {
    destroy .l
} -result 2
test listbox-21.9 {ListboxListVarProc, test hscrollbar after listvar mod} -setup {
    destroy .l
} -body {
    catch {unset x}
    set x {}
    listbox .l -font $fixed -width 10 -xscrollcommand "record x" -listvar x
    set log {}
    pack .l
    set timeout [after 500 {set log timeout}] 
    vwait log
    update idletasks
    set log {}
    lappend x "0000000000"
    update
    update idletasks
    lappend x "00000000000000000000"
    update
    update idletasks
    set log
} -cleanup {
    destroy .l
    after cancel $timeout
} -result [list {x 0 1} {x 0 1} {x 0 0.5}]
} -result [list {x 0 1} {x 0 0.5}]
test listbox-21.10 {ListboxListVarProc, test hscrollbar after listvar mod} -setup {
    destroy .l
} -body {
    catch {unset x}
    listbox .l -font $fixed -width 10 -xscrollcommand "record x" -listvar x
    set log {}
    pack .l
    set timeout [after 500 {set log timeout}] 
    vwait log
    update idletasks
    set log {}
    lappend x "0000000000"
    update
    update idletasks
    lappend x "00000000000000000000"
    update
    update idletasks
    set x [list "0000000000"]
    update
    update idletasks
    set log
} -cleanup {
    destroy .l
    after cancel timeout
} -result [list {x 0 1} {x 0 1} {x 0 0.5} {x 0 1}]
} -result [list {x 0 1} {x 0 0.5} {x 0 1}]
test listbox-21.11 {ListboxListVarProc, bad list} -setup {
    destroy .l
} -body {
    catch {unset x}
    listbox .l -listvar x
    set x [list a b c d]
    catch {set x "this is a \" bad list"} result
2760
2761
2762
2763
2764
2765
2766
2767

2768
2769
2770
2771
2772
2773
2774
2756
2757
2758
2759
2760
2761
2762

2763
2764
2765
2766
2767
2768
2769
2770







-
+







    destroy .l
} -body {
    catch {unset x}
    listbox .l -font $fixed -height 3 -yscrollcommand "record y" -listvar x
    update
    set log {}
    pack .l
    set timeout [after 500 {set log timeout}] 
    set timeout [after 500 {lappend log timeout3}]
    vwait log
    update
    lappend x a b c d e f
    vwait log
    set log
} -cleanup {
    destroy .l
2797
2798
2799
2800
2801
2802
2803
2804
2805


2806

2807
2808
2809

2810
2811
2812
2813
2814
2815
2816

2817
2818
2819
2820
2821
2822
2823
2793
2794
2795
2796
2797
2798
2799

2800
2801
2802

2803

2804

2805
2806
2807
2808
2809
2810
2811

2812
2813
2814
2815
2816
2817
2818
2819







-

+
+
-
+
-

-
+






-
+









# UpdateHScrollbar
test listbox-22.1 {UpdateHScrollbar} -setup {
    destroy .l
} -body {
    listbox .l -font $fixed -width 10 -xscrollcommand "record x"
    set log {}
    pack .l
    update idletasks
    set log {}
    set timeout [after 500 {set log timeout}] 
    set timeout [after 500 {lappend log timeout4}]
    vwait log
    .l insert end "0000000000"
    update
    vwait log
    .l insert end "00000000000000000000"
    vwait log
    set log
} -cleanup {
    destroy .l
    after cancel $timeout
} -result [list {x 0 1} {x 0 1} {x 0 0.5}]
} -result [list {x 0 1} {x 0 0.5}]


# ConfigureListboxItem
test listbox-23.1 {ConfigureListboxItem} -setup {
    destroy .l
} -body {
    listbox .l
2854
2855
2856
2857
2858
2859
2860
2861

2862
2863
2864
2865
2866
2867
2868
2850
2851
2852
2853
2854
2855
2856

2857
2858
2859
2860
2861
2862
2863
2864







-
+







} -body {
    listbox .l
    .l insert end a
    catch {.l itemco} result
    set result
} -cleanup {
    destroy .l
} -result {wrong # args: should be ".l itemconfigure index ?-option? ?value? ?-option value ...?"}
} -result {wrong # args: should be ".l itemconfigure index ?-option value ...?"}
test listbox-23.5 {ConfigureListboxItem, multiple calls} -setup {
    destroy .l
} -body {
    listbox .l
    set i 0
    foreach color {red orange yellow green blue white violet} {
	.l insert end $color
3152
3153
3154
3155
3156
3157
3158
3159

3160
3161
3162
3163
3164
3165
3166
3148
3149
3150
3151
3152
3153
3154

3155
3156
3157
3158
3159
3160
3161
3162







-
+







    unset -nocomplain res
} -body {
    pack [listbox .l -state normal]
    update
    bind .l <<ListboxSelect>> {lappend res [%W curselection]}
    .l insert end a b c
    focus -force .l
    event generate .l <1> -x 5 -y 5  ; # <<ListboxSelect>> fires
    event generate .l <Button-1> -x 5 -y 5  ; # <<ListboxSelect>> fires
    .l configure -state disabled
    focus -force .l
    event generate .l <Control-Home> ; # <<ListboxSelect>> does NOT fire
    .l configure -state normal
    focus -force .l
    event generate .l <Control-End>  ; # <<ListboxSelect>> fires
    .l selection clear 0 end         ; # <<ListboxSelect>> does NOT fire
3175
3176
3177
3178
3179
3180
3181
3182

3183
3184
3185
3186
3187
3188
3189
3171
3172
3173
3174
3175
3176
3177

3178
3179
3180
3181
3182
3183
3184
3185







-
+







    destroy .l
} -body {
    pack [listbox .l -exportselection true]
    update
    bind .l <<ListboxSelect>> {lappend res [list [selection own] [%W curselection]]}
    .l insert end a b c
    focus -force .l
    event generate .l <1> -x 5 -y 5  ; # <<ListboxSelect>> fires
    event generate .l <Button-1> -x 5 -y 5  ; # <<ListboxSelect>> fires
    selection clear                  ; # <<ListboxSelect>> fires again
    update
    set res
} -cleanup {
    destroy .l
} -result {{.l 0} {{} {}}}

3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3213
3214
3215
3216
3217
3218
3219












-
-
-
-
-
resetGridInfo
deleteWindows
option clear

# cleanup
cleanupTests
return





Changes to tests/main.test.
1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15






-
-
+
+







# This file contains tests for the tkMain.c file.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1997 by Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
namespace import ::tcltest::*
eval tcltest::configure $argv
tcltest::loadTestedCommands

23
24
25
26
27
28
29
30

31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

48
49
50
51
52
53
54
55
56
57
58

59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79

80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97

98
99
100
101
102
103
104
23
24
25
26
27
28
29

30

31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

46

47
48
49
50
51
52
53
54
55

56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76

77

78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93

94
95
96
97
98
99
100
101







-
+
-















-
+
-









-
+




















-
+
-
















-
+








test main-2.1 {Tk_MainEx: -encoding option} -constraints stdio -setup {
	set script [makeFile {} script]
	file delete $script
	set f [open $script w]
	fconfigure $f -encoding utf-8
	puts $f {puts [list $argv0 $argv $tcl_interactive]}
	puts -nonewline $f {puts [string equal \u20ac }
	puts $f {puts [string equal \u20AC €]; exit}
	puts $f "\u20ac]; exit"
	close $f
	catch {set f [open "|[list [interpreter] -encoding utf-8 script]" r]}
} -body {
	read $f
} -cleanup {
	close $f
	removeFile script
} -result "script {} 0\n1\n"

test main-2.2 {Tk_MainEx: -encoding option} -constraints stdio -setup {
	set script [makeFile {} script]
	file delete $script
	set f [open $script w]
	fconfigure $f -encoding utf-8
	puts $f {puts [list $argv0 $argv $tcl_interactive]}
	puts -nonewline $f {puts [string equal \u20ac }
	puts $f {puts [string equal \u20AC €]; exit}
	puts $f "\u20ac]; exit"
	close $f
	catch {set f [open "|[list [interpreter] -encoding ascii script]" r]}
} -body {
	read $f
} -cleanup {
	close $f
	removeFile script
} -result "script {} 0\n0\n"

    # Procedure to simulate interactive typing of commands, line by line, 
    # Procedure to simulate interactive typing of commands, line by line,
	# for test 2.3
    proc type {chan script} {
        foreach line [split $script \n] {
            if {[catch {
                puts $chan $line
                flush $chan
            }]} {
                return
            }
            # Grrr... Behavior depends on this value.
            after 1000
        }
    }

test main-2.3 {Tk_MainEx: -encoding option} -constraints stdio -setup {
	set script [makeFile {} script]
	file delete $script
	set f [open $script w]
	fconfigure $f -encoding utf-8
	puts $f {puts [list $argv0 $argv $tcl_interactive]}
	puts -nonewline $f {puts [string equal \u20ac }
	puts $f {puts [string equal \u20AC €]}
	puts $f "\u20ac]"
	close $f
	catch {set f [open "|[list [interpreter] -enc utf-8 script]" r+]}
} -body {
	type $f {
		puts $argv
		exit
	}
	gets $f
} -cleanup {
	close $f
	removeFile script
} -returnCodes ok -result {-enc utf-8 script}

test main-3.1 {Tk_ParseArgv: -help option} -constraints unix -body {
    # Run only on unix as Win32 pops up native dialog
    exec [interpreter] -help
} -returnCodes error -match glob -result {% application-specific initialization failed: Command-specific options:*}
} -returnCodes error -match glob -result {*application-specific initialization failed: Command-specific options:*}

test main-3.2 {Tk_ParseArgv: -help option} -setup {
    set maininterp [interp create]
} -body {
    $maininterp eval { set argc 1 ; set argv -help }
    load {} Tk $maininterp
} -cleanup {
Changes to tests/menu.test.
1
2
3
4
5


6
7
8
9
10
11
12
1
2
3


4
5
6
7
8
9
10
11
12



-
-
+
+







# This file is a Tcl script to test menus in Tk.  It is
# organized in the standard fashion for Tcl tests.
#
# Copyright (c) 1995-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1995-1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
namespace import ::tcltest::*
eval tcltest::configure $argv
tcltest::loadTestedCommands
imageInit
25
26
27
28
29
30
31
32

33
34
35
36
37
38
39
40
41

42
43
44

45
46
47
48
49
50

51
52
53

54
55
56
57
58
59
60
61

62
63
64

65
66
67
68
69
70
71
72
73
74

75
76
77

78
79
80
81
82
83
84
85
86
87

88
89
90

91
92
93
94
95
96
97
98
99
100

101
102
103

104
105
106
107
108
109
110
111
112
113
114
115

116
117
118

119
120
121
122
123
124

125
126
127

128
129
130
131
132
133
134
135

136
137
138

139
140
141
142
143
144
145
146
147
148

149
150
151
152
153
154
155
25
26
27
28
29
30
31

32
33
34
35
36
37
38
39
40

41
42
43

44
45
46
47
48
49

50
51
52

53
54
55
56
57
58
59
60

61
62
63

64
65
66
67
68
69
70
71
72
73

74
75
76

77
78
79
80
81
82
83
84
85
86

87
88
89

90
91
92
93
94
95
96
97
98
99

100
101
102

103
104
105
106
107
108
109
110
111
112
113
114

115
116
117

118
119
120
121
122
123

124
125
126

127
128
129
130
131
132
133
134

135
136
137

138
139
140
141
142
143
144
145
146
147

148
149
150
151
152
153
154
155







-
+








-
+


-
+





-
+


-
+







-
+


-
+









-
+


-
+









-
+


-
+









-
+


-
+











-
+


-
+





-
+


-
+







-
+


-
+









-
+







    destroy .m1
    menu .m1 foo
} -returnCodes error -result {unknown option "foo"}
test menu-1.4 {Tk_MenuCmd procedure} -body {
    destroy .m1
    menu .m1
} -cleanup {
	deleteWindows
    deleteWindows
} -result {.m1}
test menu-1.5 {Tk_MenuCmd - creating menubar} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add cascade -label Test -menu ""
    list [. configure -menu .m1] [. configure -menu ""]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} {}}
test menu-1.6 {Tk_MenuCmd procedure menu ref no cascade} -setup {
	deleteWindows
    deleteWindows
} -body {
    toplevel .t2 -menu .m1
    wm geometry .t2 +0+0
    menu .m1
} -cleanup {
	deleteWindows
    deleteWindows
} -result {.m1}
test menu-1.7 {Tk_MenuCmd procedure one clone cascade} -setup {
	deleteWindows
    deleteWindows
} -body {
    toplevel .t2 -menu .m1
    wm geometry .t2 +0+0
    menu .m1
    .m1 add cascade -menu .m2
    menu .m2
} -cleanup {
	deleteWindows
    deleteWindows
} -result {.m2}
test menu-1.8 {Tk_MenuCmd procedure two clone cascades} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 add cascade -menu .m2
    toplevel .t2 -menu .m1
    wm geometry .t2 +0+0
    toplevel .t3 -menu .m1
    wm geometry .t3 +0+0
    menu .m2
} -cleanup {
	deleteWindows
    deleteWindows
} -result {.m2}
test menu-1.9 {Tk_MenuCmd procedure two clone cascades different order} -setup {
	deleteWindows
    deleteWindows
} -body {
    toplevel .t2 -menu .m1
    wm geometry .t2 +0+0
    menu .m1
    .m1 add cascade -menu .m2
    toplevel .t3 -menu .m1
    wm geometry .t3 +0+0
    list [menu .m2]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {.m2}
test menu-1.10 {Tk_MenuCmd procedure two clone cascades menus last} -setup {
	deleteWindows
    deleteWindows
} -body {
    toplevel .t2 -menu .m1
    wm geometry .t2 +0+0
    toplevel .t3 -menu .m1
    wm geometry .t3 +0+0
    menu .m1
    .m1 add cascade -menu .m2
    list [menu .m2]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {.m2}
test menu-1.11 {Tk_MenuCmd procedure three clones cascades} -setup {
	deleteWindows
    deleteWindows
} -body {
    toplevel .t2 -menu .m1
    wm geometry .t2 +0+0
    toplevel .t3 -menu .m1
    wm geometry .t3 +0+0
    toplevel .t4 -menu .m1
    wm geometry .t4 +0+0
    menu .m1
    .m1 add cascade -menu .m2
    list [menu .m2]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {.m2}
test menu-1.12 {Tk_MenuCmd procedure} -setup {
	deleteWindows
    deleteWindows
} -body {
    toplevel .t2 -menu .m1
    wm geometry .t2 +0+0
    list [menu .m1]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {.m1}
test menu-1.13 {Tk_MenuCmd procedure} -setup {
	deleteWindows
    deleteWindows
} -body {
    toplevel .t2 -menu .m1
    wm geometry .t2 +0+0
    toplevel .t3 -menu .m1
    wm geometry .t3 +0+0
    list [menu .m1]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {.m1}
test menu-1.14 {Tk_MenuCmd procedure} -setup {
	deleteWindows
    deleteWindows
} -body {
    toplevel .t2 -menu .m1
    wm geometry .t2 +0+0
    toplevel .t3 -menu .m1
    wm geometry .t3 +0+0
    toplevel .t4 -menu .m1
    wm geometry .t4 +0+0
    list [menu .m1]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {.m1}

# Used for 2.1 - 2.30 tests
destroy .m1
menu .m1
test menu-2.1 {configuration options -activebackground #012345} -body {
    .m1 configure -activebackground #012345
171
172
173
174
175
176
177








178
179
180
181
182
183
184
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192







+
+
+
+
+
+
+
+







    .m1 configure -activeforeground #ff0000
    .m1 cget -activeforeground
} -result {#ff0000}
test menu-2.6 {configuration options -activeforeground non-existent} -body {
    .m1 configure -activeforeground non-existent
} -returnCodes error -result {unknown color name "non-existent"}

test menu-2.6a {configuration options -activerelief sunken} -body {
    .m1 configure -activerelief sunken
    .m1 cget -activerelief
} -result {sunken}
test menu-2.6b {configuration options -activerelief badValue} -body {
    .m1 configure -activerelief badValue
} -returnCodes error -result {bad relief "badValue": must be flat, groove, raised, ridge, solid, or sunken}

test menu-2.7 {configuration options -background #ff0000} -body {
    .m1 configure -background #ff0000
    .m1 cget -background
} -result {#ff0000}
test menu-2.8 {configuration options -background non-existent} -body {
    .m1 configure -background non-existent
} -returnCodes error -result {unknown color name "non-existent"}
258
259
260
261
262
263
264
265

266
267
268
269

270
271
272
273
274
275
276
277
278
279

280
281
282
283
284
285
286
266
267
268
269
270
271
272

273
274
275
276

277
278
279
280
281
282
283
284
285
286

287
288
289
290
291
292
293
294







-
+



-
+









-
+







test menu-2.27 {configuration options -takefocus {any string}} -body {
    .m1 configure -takefocus {any string}
    .m1 cget -takefocus
} -result {any string}
test menu-2.28 {configuration options -tearoff 0} -body {
    .m1 configure -tearoff 0
    .m1 cget -tearoff
} -result {0}
} -result 0
test menu-2.29 {configuration options -tearoff 1} -body {
    .m1 configure -tearoff 1
    .m1 cget -tearoff
} -result {1}
} -result 1
test menu-2.30 {configuration options -tearoffcommand {any old string}} -body {
    .m1 configure -tearoffcommand {any old string}
    .m1 cget -tearoffcommand
} -result {any old string}
destroy .m1

# We need to test all of the options with all of the different types of
# menu entries. The following code sets up .m1 with 6 items. It then
# runs through the 2.31 - 2.228 tests below
# index 0 is tearoff, 1 command, 2 cascade, 3 separator, 4 checkbutton, 
# index 0 is tearoff, 1 command, 2 cascade, 3 separator, 4 checkbutton,
# 5 radiobutton
deleteWindows
menu .m1 -tearoff 1
.m1 add command -label "command"
menu .m2 -tearoff 1
.m2 add command -label "test"
.m1 add cascade -label "cascade" -menu .m2
533
534
535
536
537
538
539
540

541
542
543
544
545

546
547
548
549
550
551
552
553
554

555
556
557
558
559

560
561
562
563
564
565
566
541
542
543
544
545
546
547

548
549
550
551
552

553
554
555
556
557
558
559
560
561

562
563
564
565
566

567
568
569
570
571
572
573
574







-
+




-
+








-
+




-
+







test menu-2.85 {entry configuration options 0 -columnbreak 1 tearoff} -body {
    .m1 entryconfigure 0 -columnbreak 1
} -returnCodes error -result {unknown option "-columnbreak"}

test menu-2.86 {entry configuration options 1 -columnbreak 1 command} -body {
    .m1 entryconfigure 1 -columnbreak 1
    lindex [.m1 entryconfigure 1 -columnbreak] 4
} -result {1}
} -result 1

test menu-2.87 {entry configuration options 2 -columnbreak 1 cascade} -body {
    .m1 entryconfigure 2 -columnbreak 1
    lindex [.m1 entryconfigure 2 -columnbreak] 4
} -result {1}
} -result 1

test menu-2.88 {entry configuration options 3 -columnbreak 1 separator} -body {
    .m1 entryconfigure 3 -columnbreak 1
} -returnCodes error -result {unknown option "-columnbreak"}

test menu-2.89 {entry configuration options 4 -columnbreak 1 checkbutton} -body {
    .m1 entryconfigure 4 -columnbreak 1
    lindex [.m1 entryconfigure 4 -columnbreak] 4
} -result {1}
} -result 1

test menu-2.90 {entry configuration options 5 -columnbreak 1 radiobutton} -body {
    .m1 entryconfigure 5 -columnbreak 1
    lindex [.m1 entryconfigure 5 -columnbreak] 4
} -result {1}
} -result 1

test menu-2.91 {entry configuration options 0 -command beep tearoff} -body {
    .m1 entryconfigure 0 -command beep
} -returnCodes error -result {unknown option "-command"}

test menu-2.92 {entry configuration options 1 -command beep command} -body {
    .m1 entryconfigure 1 -command beep
767
768
769
770
771
772
773
774

775
776
777
778
779
780

781
782
783
784
785
786
787

788
789
790
791
792

793
794
795
796

797
798
799
800
801

802
803
804
805
806
807
808
775
776
777
778
779
780
781

782
783
784
785
786
787

788
789
790
791
792
793
794

795
796
797
798
799

800
801
802
803

804
805
806
807
808

809
810
811
812
813
814
815
816







-
+





-
+






-
+




-
+



-
+




-
+







} -returnCodes error -result {image "bogus" doesn't exist}

test menu-2.132 {entry configuration options 5 -image bogus radiobutton} -body {
    .m1 entryconfigure 5 -image bogus
} -returnCodes error -result {image "bogus" doesn't exist}

test menu-2.133 {entry configuration options 0 -image {} tearoff} -body {
    .m1 entryconfigure 0 -image 
    .m1 entryconfigure 0 -image
} -returnCodes error -result {unknown option "-image"}

test menu-2.134 {entry configuration options 1 -image {} command} -setup {
    .m1 entryconfigure 1 -image {}
} -body {
    .m1 entryconfigure 1 -image 
    .m1 entryconfigure 1 -image
    lindex [.m1 entryconfigure 1 -image] 4
} -result {}

test menu-2.135 {entry configuration options 2 -image {} cascade} -setup {
    .m1 entryconfigure 2 -image {}
} -body {
    .m1 entryconfigure 2 -image 
    .m1 entryconfigure 2 -image
    lindex [.m1 entryconfigure 2 -image] 4
} -result {}

test menu-2.136 {entry configuration options 3 -image {} separator} -body {
    .m1 entryconfigure 3 -image 
    .m1 entryconfigure 3 -image
} -returnCodes error -result {unknown option "-image"}

test menu-2.137 {entry configuration options 4 -image {} checkbutton} -body {
    .m1 entryconfigure 4 -image 
    .m1 entryconfigure 4 -image
    lindex [.m1 entryconfigure 4 -image] 4
} -result {}

test menu-2.138 {entry configuration options 5 -image {} radiobutton} -body {
    .m1 entryconfigure 5 -image 
    .m1 entryconfigure 5 -image
    lindex [.m1 entryconfigure 5 -image] 4
} -result {}

test menu-2.139 {entry configuration options 0 -indicatoron 1 tearoff} -body {
    .m1 entryconfigure 0 -indicatoron 1
} -returnCodes error -result {unknown option "-indicatoron"}

817
818
819
820
821
822
823
824

825
826
827
828
829

830
831
832
833
834
835
836
825
826
827
828
829
830
831

832
833
834
835
836

837
838
839
840
841
842
843
844







-
+




-
+







test menu-2.142 {entry configuration options 3 -indicatoron 1 separator} -body {
    .m1 entryconfigure 3 -indicatoron 1
} -returnCodes error -result {unknown option "-indicatoron"}

test menu-2.143 {entry configuration options 4 -indicatoron 1 checkbutton} -body {
    .m1 entryconfigure 4 -indicatoron 1
    lindex [.m1 entryconfigure 4 -indicatoron] 4
} -result {1}
} -result 1

test menu-2.144 {entry configuration options 5 -indicatoron 1 radiobutton} -body {
    .m1 entryconfigure 5 -indicatoron 1
    lindex [.m1 entryconfigure 5 -indicatoron] 4
} -result {1}
} -result 1

test menu-2.145 {entry configuration options 0 -label test tearoff} -body {
    .m1 entryconfigure 0 -label test
} -returnCodes error -result {unknown option "-label"}

test menu-2.146 {entry configuration options 1 -label test command} -body {
    .m1 entryconfigure 1 -label test
1048
1049
1050
1051
1052
1053
1054
1055

1056
1057
1058
1059

1060
1061
1062
1063

1064
1065
1066
1067

1068
1069
1070
1071

1072
1073
1074
1075
1076

1077
1078
1079
1080
1081
1082
1083
1056
1057
1058
1059
1060
1061
1062

1063
1064
1065
1066

1067
1068
1069
1070

1071
1072
1073
1074

1075
1076
1077
1078

1079
1080
1081
1082
1083

1084
1085
1086
1087
1088
1089
1090
1091







-
+



-
+



-
+



-
+



-
+




-
+







} -returnCodes error -result {image "bogus" doesn't exist}

test menu-2.192 {entry configuration options 5 -selectimage bogus radiobutton} -body {
    .m1 entryconfigure 5 -selectimage bogus
} -returnCodes error -result {image "bogus" doesn't exist}

test menu-2.193 {entry configuration options 0 -selectimage {} tearoff} -body {
    .m1 entryconfigure 0 -selectimage 
    .m1 entryconfigure 0 -selectimage
} -returnCodes error -result {unknown option "-selectimage"}

test menu-2.194 {entry configuration options 1 -selectimage {} command} -body {
    .m1 entryconfigure 1 -selectimage 
    .m1 entryconfigure 1 -selectimage
} -returnCodes error -result {unknown option "-selectimage"}

test menu-2.195 {entry configuration options 2 -selectimage {} cascade} -body {
    .m1 entryconfigure 2 -selectimage 
    .m1 entryconfigure 2 -selectimage
} -returnCodes error -result {unknown option "-selectimage"}

test menu-2.196 {entry configuration options 3 -selectimage {} separator} -body {
    .m1 entryconfigure 3 -selectimage 
    .m1 entryconfigure 3 -selectimage
} -returnCodes error -result {unknown option "-selectimage"}

test menu-2.197 {entry configuration options 4 -selectimage {} checkbutton} -body {
    .m1 entryconfigure 4 -selectimage 
    .m1 entryconfigure 4 -selectimage
    lindex [.m1 entryconfigure 4 -selectimage] 4
} -result {}

test menu-2.198 {entry configuration options 5 -selectimage {} radiobutton} -body {
    .m1 entryconfigure 5 -selectimage 
    .m1 entryconfigure 5 -selectimage
    lindex [.m1 entryconfigure 5 -selectimage] 4
} -result {}

test menu-2.199 {entry configuration options 0 -state normal tearoff} -body {
    .m1 entryconfigure 0 -state normal
    lindex [.m1 entryconfigure 0 -state] 4
} -result {normal}
1160
1161
1162
1163
1164
1165
1166
1167

1168
1169
1170
1171
1172

1173
1174
1175
1176
1177
1178
1179
1180
1181

1182
1183
1184
1185
1186

1187
1188
1189
1190
1191
1192
1193
1168
1169
1170
1171
1172
1173
1174

1175
1176
1177
1178
1179

1180
1181
1182
1183
1184
1185
1186
1187
1188

1189
1190
1191
1192
1193

1194
1195
1196
1197
1198
1199
1200
1201







-
+




-
+








-
+




-
+







test menu-2.217 {entry configuration options 0 -underline 0 tearoff} -body {
    .m1 entryconfigure 0 -underline 0
} -returnCodes error -result {unknown option "-underline"}

test menu-2.218 {entry configuration options 1 -underline 0 command} -body {
    .m1 entryconfigure 1 -underline 0
    lindex [.m1 entryconfigure 1 -underline] 4
} -result {0}
} -result 0

test menu-2.219 {entry configuration options 2 -underline 0 cascade} -body {
    .m1 entryconfigure 2 -underline 0
    lindex [.m1 entryconfigure 2 -underline] 4
} -result {0}
} -result 0

test menu-2.220 {entry configuration options 3 -underline 0 separator} -body {
    .m1 entryconfigure 3 -underline 0
} -returnCodes error -result {unknown option "-underline"}

test menu-2.221 {entry configuration options 4 -underline 0 checkbutton} -body {
    .m1 entryconfigure 4 -underline 0
    lindex [.m1 entryconfigure 4 -underline] 4
} -result {0}
} -result 0

test menu-2.222 {entry configuration options 5 -underline 0 radiobutton} -body {
    .m1 entryconfigure 5 -underline 0
    lindex [.m1 entryconfigure 5 -underline] 4
} -result {0}
} -result 0

test menu-2.223 {entry configuration options 0 -underline 3p tearoff} -body {
    .m1 entryconfigure 0 -underline 3p
} -returnCodes error -result {unknown option "-underline"}

test menu-2.224 {entry configuration options 1 -underline 3p command} -body {
    .m1 entryconfigure 1 -underline 3p
1221
1222
1223
1224
1225
1226
1227
1228

1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240

1241
1242
1243
1244
1245
1246
1247
1229
1230
1231
1232
1233
1234
1235

1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247

1248
1249
1250
1251
1252
1253
1254
1255







-
+











-
+







} -body {
    menu .m1
    .m1
} -cleanup {
	destroy .m1
} -returnCodes error -result {wrong # args: should be ".m1 option ?arg ...?"}
test menu-3.2 {MenuWidgetCmd, Tcl_Preserve and Tcl_Release} -constraints {
	nonUnixUserInteraction 
	nonUnixUserInteraction
} -setup {
    destroy .m1
} -body  {
    menu .m1 -postcommand "destroy .m1"
    .m1 add command -label "menu-3.2: Hit Escape"
    .m1 post 40 40
} -cleanup {
    destroy .m1
} -returnCodes ok -result {}
test menu-3.3 {MenuWidgetCmd procedure, "activate" option} -setup {
	destroy .m1
} -body {    
} -body {
    menu .m1
    .m1 add command -label "test"
    .m1 activate
} -cleanup {
	destroy .m1
} -returnCodes error -result {wrong # args: should be ".m1 activate index"}
test menu-3.4 {MenuWidgetCmd procedure, "activate" option} -setup {
1355
1356
1357
1358
1359
1360
1361
1362

1363
1364
1365
1366
1367
1368
1369
1363
1364
1365
1366
1367
1368
1369

1370
1371
1372
1373
1374
1375
1376
1377







-
+







test menu-3.18 {MenuWidgetCmd procedure, "configure" option} -setup {
	destroy .m1
} -body {
    menu .m1
    llength [.m1 configure]
} -cleanup {
	destroy .m1
} -result {20}
} -result 21
test menu-3.19 {MenuWidgetCmd procedure, "configure" option} -setup {
	destroy .m1
} -body {
    menu .m1
    .m1 configure -gorp
} -returnCodes error -result {unknown option "-gorp"}
test menu-3.20 {MenuWidgetCmd procedure, "configure" option} -setup {
1410
1411
1412
1413
1414
1415
1416
1417

1418
1419
1420
1421
1422
1423
1424
1418
1419
1420
1421
1422
1423
1424

1425
1426
1427
1428
1429
1430
1431
1432







-
+







	destroy .m1
} -result {}
test menu-3.26 {MenuWidgetCmd procedure, "delete" option} -setup {
	destroy .m1
} -body {
    menu .m1
    .m1 add command -label "foo"
    .m1 delete 1 0 
    .m1 delete 1 0
} -cleanup {
	destroy .m1
} -result {}
test menu-3.27 {MenuWidgetCmd procedure, "delete" option} -setup {
	destroy .m1
} -body {
    menu .m1
1507
1508
1509
1510
1511
1512
1513
1514

1515
1516
1517
1518
1519
1520
1521
1515
1516
1517
1518
1519
1520
1521

1522
1523
1524
1525
1526
1527
1528
1529







-
+







	destroy .m1
} -body {
    menu .m1
    .m1 add command -label "test"
    llength [.m1 entryconfigure 1]
} -cleanup {
	destroy .m1
} -result {15}
} -result 15
test menu-3.37 {MenuWidgetCmd procedure, "entryconfigure" option} -setup {
	destroy .m1
} -body {
    menu .m1
    .m1 add command -label "test"
    lindex [.m1 entryconfigure 1 -label] 4
} -cleanup {
1623
1624
1625
1626
1627
1628
1629
1630

1631
1632

1633
1634
1635
1636
1637
1638
1639
1631
1632
1633
1634
1635
1636
1637

1638
1639

1640
1641
1642
1643
1644
1645
1646
1647







-
+

-
+







} -cleanup {
	destroy .m1
} -returnCodes error -result {expected integer but got "bar"}
test menu-3.50 {MenuWidgetCmd procedure, "post" option} -constraints {
	nonUnixUserInteraction
} -setup {
	destroy .m1
} -body { 
} -body {
    menu .m1
    .m1 add command -label "menu-3.53: hit Escape" -command "puts hello"
    .m1 add command -label "menu-3.50: hit Escape" -command "puts hello"
    .m1 post 40 40
} -cleanup {
	destroy .m1
} -result {}
test menu-3.51 {MenuWidgetCmd procedure, "postcascade" option} -setup {
	destroy .m1
} -body {
1650
1651
1652
1653
1654
1655
1656
1657

1658
1659

1660
1661
1662
1663
1664
1665
1666
1658
1659
1660
1661
1662
1663
1664

1665
1666

1667
1668
1669
1670
1671
1672
1673
1674







-
+

-
+







} -cleanup {
	destroy .m1
} -returnCodes error -result {bad menu entry index "foo"}
test menu-3.53 {MenuWidgetCmd procedure, "postcascade" option} -constraints {
	nonUnixUserInteraction
} -setup {
	destroy .m1 .m2
} -body { 
} -body {
    menu .m1
    .m1 add command -label "menu-3.56 - hit Escape"
    .m1 add command -label "menu-3.53 - hit Escape"
    menu .m2
    .m1 post 40 40
    .m1 add cascade -menu .m2
    .m1 postcascade 1
} -cleanup {
	destroy .m1 .m2
} -result {}
1752
1753
1754
1755
1756
1757
1758
1759

1760
1761
1762


1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782

1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794

1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806

1807
1808
1809
1810
1811
1812
1813
1814
1815
1816

1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834

1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852








1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873


1874
1875
1876
1877
1878
1879
1880
1760
1761
1762
1763
1764
1765
1766

1767
1768


1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789

1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801

1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813

1814
1815
1816
1817
1818
1819
1820
1821
1822
1823

1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841

1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887


1888
1889
1890
1891
1892
1893
1894
1895
1896







-
+

-
-
+
+



















-
+











-
+











-
+









-
+

















-
+


















+
+
+
+
+
+
+
+



















-
-
+
+







} -cleanup {
	destroy .m1
} -returnCodes error -result {wrong # args: should be ".m1 unpost"}
test menu-3.64 {MenuWidgetCmd procedure, "unpost" option} -constraints {
	nonUnixUserInteraction
} -setup {
	destroy .m1
} -body { 
} -body {
    menu .m1
    .m1 add command -label "menu-3.68 - hit Escape"
    .m1 post 40 40 
    .m1 add command -label "menu-3.64 - hit Escape"
    .m1 post 40 40
    .m1 unpost
} -cleanup {
	destroy .m1
} -result {}
test menu-3.65 {MenuWidgetCmd procedure, "yposition" option} -setup {
	destroy .m1
} -body {
    menu .m1
    .m1 yposition
} -cleanup {
	destroy .m1
} -returnCodes error -result {wrong # args: should be ".m1 yposition index"}
test menu-3.66a {MenuWidgetCmd procedure, "yposition" option, no tearoff} -setup {
	destroy .m1
} -body {
    menu .m1 -tearoff 0
    .m1 yposition 1
} -cleanup {
	destroy .m1
} -result {0}
} -result 0
test menu-3.66b {MenuWidgetCmd procedure, "yposition" option, with tearoff} -constraints {
    notAqua
} -setup {
	destroy .m1
} -body {
    # on Win or Linux, tearoff menus are supported
    # see menu-3.66c for aqua
    menu .m1 -tearoff 1
    .m1 yposition 1
} -cleanup {
	destroy .m1
} -result {1}
} -result 1
test menu-3.66c {MenuWidgetCmd procedure, "yposition" option, with tearoff} -constraints {
    aqua
} -setup {
	destroy .m1
} -body {
    # on OS X, tearoff menus are not supported
    # see menu-3.66b for win or linux
    menu .m1 -tearoff 1
    .m1 yposition 1
} -cleanup {
	destroy .m1
} -result {0}
} -result 0
test menu-3.67 {MenuWidgetCmd procedure, bad option} -setup {
	destroy .m1
} -body {
    menu .m1
    .m1 foo
} -cleanup {
	destroy .m1
} -returnCodes error -result {bad option "foo": must be activate, add, cget, clone, configure, delete, entrycget, entryconfigure, index, insert, invoke, post, postcascade, type, unpost, xposition, or yposition}
test menu-3.68 {MenuWidgetCmd procedure, fix for bug#508988} -setup {
	deleteWindows
    deleteWindows
} -body {
    set t .t
    set m1 .t.m1
    set c1 .t.c1
    set c2 .t.c2
    toplevel .t
    menu $m1 -tearoff 1
    menu $c1 -tearoff 1
    $c1 add command -label c1
    menu $c2 -tearoff 1
    $c2 add command -label c2
    $m1 add cascade -label c1 -menu $c1
    $t configure -menu $m1
    $m1 entryconfigure 1 -menu $c2 -label c2
    $t configure -menu ""
    list [winfo exists $c1] [winfo exists $c2]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {1 1}
test menu-3.69 {MenuWidgetCmd procedure, "xposition" option} -setup {
    destroy .m1
    menu .m1
} -body {
    .m1 xposition
} -cleanup {
    destroy .m1
} -returnCodes error -result {wrong # args: should be ".m1 xposition index"}
test menu-3.70 {MenuWidgetCmd procedure, "xposition" option} -setup {
    destroy .m1
    menu .m1
} -body {
    .m1 xposition 1
    subst {} ;# just checking that the xposition does not produce an error...
} -cleanup {
    destroy .m1
} -result {}
test menu-3.71 {MenuWidgetCmd procedure, "index end" option, bug [f3cd942e9e]} -setup {
    destroy .m1
} -body {
    menu .m1
    list [.m1 index "end"]
} -cleanup {
    destroy .m1
} -result none


test menu-4.1 {TkInvokeMenu: disabled} -setup {
    destroy .m1
} -body {
    catch {unset foo}
    menu .m1
    .m1 add checkbutton -label "test" -variable foo -onvalue on -offvalue off \
	-state disabled
    list [catch {.m1 invoke 1} msg] $foo
} -cleanup {
    destroy .m1
} -result {0 off}
test menu-4.2 {TkInvokeMenu: tearoff} -setup {
    destroy .m1
} -body {
    menu .m1
	catch {.m1 invoke 0}
} -cleanup {
	deleteWindows
} -result {0}
    deleteWindows
} -result 0
test menu-4.3 {TkInvokeMenu: checkbutton -on} -setup {
    destroy .m1
} -body {
    catch {unset foo}
    menu .m1
    .m1 add checkbutton -label "test" -variable foo -onvalue on -offvalue off
    list [catch {.m1 invoke 1} msg] $msg [catch {set foo} msg2] $msg2 \
1894
1895
1896
1897
1898
1899
1900
1901

1902
1903
1904
1905
1906
1907
1908
1910
1911
1912
1913
1914
1915
1916

1917
1918
1919
1920
1921
1922
1923
1924







-
+







    destroy .m1
} -result {0 {} 0 off 0 {}}
test menu-4.5 {TkInvokeMenu: checkbutton array element} -setup {
    destroy .m1
} -body {
    catch {unset foo}
    menu .m1
    .m1 add checkbutton -label "test" -variable foo(1) -onvalue on 
    .m1 add checkbutton -label "test" -variable foo(1) -onvalue on
    list [catch {.m1 invoke 1} msg] $msg [catch {set foo(1)} msg2] $msg2 [catch {unset foo} msg3] $msg3
} -cleanup {
	destroy .m1
} -result {0 {} 0 on 0 {}}
test menu-4.6 {TkInvokeMenu: radiobutton} -setup {
    destroy .m1
} -body {
1962
1963
1964
1965
1966
1967
1968
1969

1970
1971
1972
1973
1974
1975
1976
1978
1979
1980
1981
1982
1983
1984

1985
1986
1987
1988
1989
1990
1991
1992







-
+







	destroy .m1
} -result {0 menu-4.8 0 menu-4.8 0 {}}
test menu-4.11 {TkInvokeMenu} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add cascade -label "test" -menu .m1.m2
    list [catch {.m1 invoke 1} msg] $msg 
    list [catch {.m1 invoke 1} msg] $msg
} -cleanup {
	destroy .m1
} -result {0 {}}
test menu-4.12 {TkInvokeMenu} -setup {
    destroy .m1
} -body {
    menu .m1 -tearoff 1
2022
2023
2024
2025
2026
2027
2028
2029

2030
2031
2032
2033
2034
2035
2036
2038
2039
2040
2041
2042
2043
2044

2045
2046
2047
2048
2049
2050
2051
2052







-
+







    menu .m1
    menu .m2
    .m1 add cascade -menu .m2
    . configure -menu .m1
    list [destroy .m2] [.m1 entrycget 1 -menu] [. configure -menu ""] [destroy .m1]
} -returnCodes ok -result {{} .m2 {} {}}
test menu-5.6 {DestroyMenuInstance - cascades of cloned menus} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 add cascade -menu .m2
    menu .m2
    . configure -menu .m1
    toplevel .t2
    wm geometry .t2 +0+0
2048
2049
2050
2051
2052
2053
2054
2055

2056
2057
2058
2059
2060
2061
2062
2064
2065
2066
2067
2068
2069
2070

2071
2072
2073
2074
2075
2076
2077
2078







-
+







    destroy .m1
} -body {
    menu .m1
    set tearoff1 [tk::TearOffMenu .m1]
    set tearoff2 [tk::TearOffMenu .m1]
    list [destroy $tearoff1] [destroy .m1]
} -returnCodes ok -result {{} {}}
test menu-5.9 {DestroyMenuInstace - master menu} -setup {
test menu-5.9 {DestroyMenuInstace - main menu} -setup {
    destroy .m1
} -body {
    menu .m1
    tk::TearOffMenu .m1
    destroy .m1
} -returnCodes ok
test menu-5.10 {DestroyMenuInstance - freeing entries} -setup {
2118
2119
2120
2121
2122
2123
2124
2125
2126


2127
2128
2129
2130
2131
2132
2133
2134

2135
2136
2137
2138
2139
2140
2141
2134
2135
2136
2137
2138
2139
2140


2141
2142
2143
2144
2145
2146
2147
2148
2149

2150
2151
2152
2153
2154
2155
2156
2157







-
-
+
+







-
+







    destroy .m1 .m2
} -body {
    menu .m1
    .m1 clone .m2
    .m1 clone .m1.m3
    destroy .m1
} -cleanup {
	deleteWindows
} -returnCodes ok 
    deleteWindows
} -returnCodes ok
test menu-6.5 {TkDestroyMenu} -setup {
    destroy .m1 .m2
} -body {
    menu .m1
    .m1 clone .m2
    destroy .m1
    winfo exists .m2
} -result {0}
} -result 0
test menu-6.6 {TkDestroyMenu} -setup {
    destroy .m1 .m2
} -body {
    menu .m1
    .m1 clone .m2 tearoff
    destroy .m1
} -result {}
2259
2260
2261
2262
2263
2264
2265
2266

2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277

2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288

2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299

2300
2301
2302
2303
2304
2305
2306
2275
2276
2277
2278
2279
2280
2281

2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292

2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303

2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314

2315
2316
2317
2318
2319
2320
2321
2322







-
+










-
+










-
+










-
+







    menu .m1
    menu .m2
    .m1 add cascade -menu .cascade
    .m2 add cascade -menu .cascade
    list [destroy .m1] [destroy .m2]
} -returnCodes ok -result {{} {}}
test menu-7.5 {UnhookCascadeEntry} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    menu .m2
    menu .m3
    .m1 add cascade -menu .cascade
    .m2 add cascade -menu .cascade
    .m3 add cascade -menu .cascade
    list [destroy .m1] [destroy .m2 .m3]
} -returnCodes ok -result {{} {}}
test menu-7.6 {UnhookCascadeEntry} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    menu .m2
    menu .m3
    .m1 add cascade -menu .cascade
    .m2 add cascade -menu .cascade
    .m3 add cascade -menu .cascade
    list [destroy .m2] [destroy .m1 .m3]
} -returnCodes ok -result {{} {}}
test menu-7.7 {UnhookCascadeEntry} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    menu .m2
    menu .m3
    .m1 add cascade -menu .cascade
    .m2 add cascade -menu .cascade
    .m3 add cascade -menu .cascade
    list [destroy .m3] [destroy .m1 .m2]
} -returnCodes ok -result {{} {}}
test menu-7.8 {UnhookCascadeEntry} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    menu .m2
    .m1 add cascade -menu .m2
    list [destroy .m1] [destroy .m2]
} -returnCodes ok -result {{} {}}
test menu-7.9 {UnhookCascadeEntry} -setup {
2346
2347
2348
2349
2350
2351
2352
2353

2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370

2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385

2386
2387

2388
2389
2390
2391
2392
2393
2394
2395
2396

2397
2398
2399
2400
2401
2402
2403
2404

2405
2406
2407
2408
2409
2410
2411
2412
2413

2414
2415
2416
2417
2418
2419
2420
2421
2422
2423

2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434

2435
2436
2437

2438
2439
2440
2441
2442
2443

2444
2445
2446

2447
2448
2449
2450
2451
2452

2453
2454
2455
2456
2457
2458
2459
2460

2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473

2474
2475
2476
2477
2478
2479
2480
2481
2482
2483

2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495

2496
2497
2498
2499
2500
2501
2502
2503
2504

2505
2506
2507
2508
2509
2510
2511
2512
2513

2514
2515
2516

2517
2518

2519
2520
2521
2522

2523
2524
2525

2526
2527
2528
2529
2530
2531

2532
2533
2534

2535
2536
2537
2538
2539
2540

2541
2542
2543

2544
2545
2546
2547
2548
2549
2550

2551
2552
2553

2554
2555
2556
2557
2558
2559

2560
2561
2562

2563
2564
2565
2566
2567
2568

2569
2570
2571

2572
2573
2574
2575
2576
2577

2578
2579
2580

2581
2582
2583
2584
2585
2586

2587
2588
2589

2590
2591
2592

2593
2594

2595
2596

2597
2598

2599
2600
2601
2602

2603
2604
2605

2606
2607
2608

2609
2610

2611
2612

2613
2614
2615
2616

2617
2618
2619

2620
2621
2622
2623
2624
2625

2626
2627
2628

2629
2630
2631
2632
2633

2634
2635
2636

2637
2638
2639
2640
2641

2642
2643
2644
2645
2646
2647
2648
2362
2363
2364
2365
2366
2367
2368

2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385

2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400

2401
2402

2403
2404
2405
2406
2407
2408
2409
2410
2411

2412
2413
2414
2415
2416
2417
2418
2419

2420
2421
2422
2423
2424
2425
2426
2427
2428

2429
2430
2431
2432
2433
2434
2435
2436
2437
2438

2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449

2450
2451
2452

2453
2454
2455
2456
2457
2458

2459
2460
2461

2462
2463
2464
2465
2466
2467

2468
2469
2470
2471
2472
2473
2474
2475

2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488

2489
2490
2491
2492
2493
2494
2495
2496
2497
2498

2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510

2511
2512
2513
2514
2515
2516
2517
2518
2519

2520
2521
2522
2523
2524
2525
2526
2527
2528

2529
2530
2531

2532
2533

2534
2535
2536
2537

2538
2539
2540

2541
2542
2543
2544
2545
2546

2547
2548
2549

2550
2551
2552
2553
2554
2555

2556
2557
2558

2559
2560
2561
2562
2563
2564
2565

2566
2567
2568

2569
2570
2571
2572
2573
2574

2575
2576
2577

2578
2579
2580
2581
2582
2583

2584
2585
2586

2587
2588
2589
2590
2591
2592

2593
2594
2595

2596
2597
2598
2599
2600
2601

2602
2603
2604

2605
2606
2607

2608
2609

2610
2611

2612
2613

2614
2615
2616
2617

2618
2619
2620

2621
2622
2623

2624
2625

2626
2627

2628
2629
2630
2631

2632
2633
2634

2635
2636
2637
2638
2639
2640

2641
2642
2643

2644
2645
2646
2647
2648

2649
2650
2651

2652
2653
2654
2655
2656

2657
2658
2659
2660
2661
2662
2663
2664







-
+
















-
+














-
+

-
+








-
+







-
+








-
+









-
+










-
+


-
+





-
+


-
+





-
+







-
+












-
+









-
+











-
+








-
+








-
+


-
+

-
+



-
+


-
+





-
+


-
+





-
+


-
+






-
+


-
+





-
+


-
+





-
+


-
+





-
+


-
+





-
+


-
+


-
+

-
+

-
+

-
+



-
+


-
+


-
+

-
+

-
+



-
+


-
+





-
+


-
+




-
+


-
+




-
+







} -result {{} {}}
test menu-8.4 {DestroyMenuEntry} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add checkbutton -variable foo
    list [.m1 delete 1] [destroy .m1]
} -result {{} {}} 
} -result {{} {}}
test menu-8.5 {DestroyMenuEntry} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add command -label "test"
    list [.m1 delete 1] [destroy .m1]
} -result {{} {}}
test menu-8.6 {DestroyMenuEntry} -setup {
    destroy .m1
} -body {
    menu .m1 -tearoff 1
    .m1 add command -label "one"
    .m1 add command -label "two"
    list [.m1 delete 1] [.m1 entrycget 1 -label] [destroy .m1]
} -result {{} two {}}
test menu-8.7 {DestroyMenuEntry} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 add command -label "one"
    .m1 clone .m2 tearoff
    list [.m2 delete 1] [destroy .m1]
} -result {{} {}}


# test menu-9 - Can only change when fonts change on system, which cannot
# be done from tcl.
test menu-9.1 {ConfigureMenu} -setup {
    destroy .m1
} -body {
    menu .m1
    list [.m1 configure -postcommand "beep"] [.m1 cget -postcommand] 
    list [.m1 configure -postcommand "beep"] [.m1 cget -postcommand]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} beep}
test menu-9.2 {ConfigureMenu}  -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add command -label "test"
    list [.m1 configure -tearoff 0] [.m1 entrycget 1 -label]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} test}
test menu-9.3 {ConfigureMenu}  -setup {
    destroy .m1
} -body {
    menu .m1
    list [.m1 configure -postcommand "beep"] [.m1 cget -postcommand]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} beep}
test menu-9.4 {ConfigureMenu}  -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add command -label "test"
    .m1 configure -fg red
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}
test menu-9.5 {ConfigureMenu}  -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add command -label "test"
    .m1 add command -label "two"
    .m1 configure -fg red
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}
test menu-9.6 {ConfigureMenu}  -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add command -label "test"
    .m1 add command -label "two"
    .m1 add command -label "three"
    .m1 configure -fg red
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}
test menu-9.7 {ConfigureMenu} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 clone .m2 tearoff
    list [.m1 configure -fg red] [.m2 cget -fg]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} red}
test menu-9.8 {ConfigureMenu} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 clone .m2 tearoff
    list [.m2 configure -fg red] [.m1 cget -fg]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} red}
test menu-9.9 {ConfigureMenu}  -setup {
    destroy .m1
} -body {
    menu .m1
    list [. configure -menu .m1] [. configure -menu ""]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} {}}


test menu-10.1 {PostProcessEntry: array variable} -setup {
    destroy .m1
} -body {
    catch {unset foo}
    menu .m1
    set foo(1) on
    .m1 add checkbutton -variable foo(1) -onvalue on -offvalue off -label "Nonsense"
    set foo(1)
} -cleanup {
	deleteWindows
    deleteWindows
} -result {on}
test menu-10.2 {PostProcessEntry: array variable} -setup {
    destroy .m1
} -body {
    catch {unset foo}
    menu .m1
    .m1 add checkbutton -variable foo(1) -onvalue on -offvalue off -label "Nonsense"
    set foo(1)
} -cleanup {
	deleteWindows
    deleteWindows
} -result {off}


test menu-11.1 {ConfigureMenuEntry} -setup {
    destroy .m1
} -body {
    catch {unset foo}
    menu .m1
    .m1 add checkbutton -variable foo -onvalue on -offvalue off -label "Nonsense"
    list [.m1 entryconfigure 1 -variable bar] [.m1 entrycget 1 -variable]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} bar}
test menu-11.2 {ConfigureMenuEntry} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add command -label "test"
    list [.m1 entryconfigure 1 -label ""] [.m1 entrycget 1 -label]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} {}}
test menu-11.3 {ConfigureMenuEntry} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add command
    list [.m1 entryconfigure 1 -label "test"] [.m1 entrycget 1 -label]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} test}
test menu-11.4 {ConfigureMenuEntry} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1 
    menu .m1
    .m1 add command
    list [.m1 entryconfigure 1 -accel "S"] [.m1 entrycget 1 -accel]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} S}
test menu-11.5 {ConfigureMenuEntry} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 add command
    list [.m1 entryconfigure 1 -label "test"] [.m1 entrycget 1 -label]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} test}
test menu-11.6 {ConfigureMenuEntry} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 add command
    .m1 entryconfigure 1 -label "test"
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}
test menu-11.7 {ConfigureMenuEntry} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m2
    menu .m1
    .m1 add cascade
    .m1 entryconfigure 1 -label "test" -menu .m2
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}
test menu-11.8 {ConfigureMenuEntry} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 add cascade
    .m1 entryconfigure 1 -label "test" -menu .m2
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}
test menu-11.9 {ConfigureMenuEntry} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 add cascade -menu .m3
    .m1 entryconfigure 1 -label "test" -menu .m2
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}
test menu-11.10 {ConfigureMenuEntry} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 add cascade
    .m1 entryconfigure 1 -label "test" -menu .m2
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}
test menu-11.11 {ConfigureMenuEntry} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 add cascade -menu .m2
    .m1 entryconfigure 1 -label "test" -menu .m2
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}
test menu-11.12 {ConfigureMenuEntry} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    menu .m2 
    menu .m2
    .m2 add cascade -menu .m1
    menu .m3 
    menu .m3
    .m3 add cascade -menu .m1
    menu .m4 
    menu .m4
    .m4 add cascade -menu .m1
    menu .m5 
    menu .m5
    .m5 add cascade
    .m5 entryconfigure 1 -label "test" -menu .m1
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}
test menu-11.13 {ConfigureMenuEntry} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    menu .m2 
    menu .m2
    .m2 add cascade -menu .m1
    menu .m3 
    menu .m3
    .m3 add cascade -menu .m1
    menu .m4 
    menu .m4
    .m4 add cascade -menu .m1
    .m3 entryconfigure 1 -label "test" -menu .m1
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}
test menu-11.14 {ConfigureMenuEntry} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 add checkbutton
    list [.m1 entryconfigure 1 -variable "test"] [.m1 entrycget 1 -variable]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} test}
test menu-11.15 {ConfigureMenuEntry} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    list [.m1 add checkbutton -label "test"] [.m1 entrycget 1 -variable]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} test}
test menu-11.16 {ConfigureMenuEntry} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 add radiobutton -label "test"
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}
test menu-11.17 {ConfigureMenuEntry} -setup {
    deleteWindows
} -body {
    menu .m1
    .m1 add checkbutton
    list [.m1 entryconfigure 1 -onvalue "test"] [.m1 entrycget 1 -onvalue]
2840
2841
2842
2843
2844
2845
2846
2847

2848
2849
2850
2851
2852
2853
2854

2855
2856
2857

2858
2859
2860
2861
2862
2863

2864
2865
2866

2867
2868
2869
2870
2871
2872

2873
2874
2875

2876
2877
2878
2879
2880
2881
2882
2883

2884
2885
2886
2887

2888
2889
2890
2891
2892

2893
2894
2895

2896
2897
2898
2899
2900
2901

2902
2903
2904
2905

2906
2907
2908
2909
2910

2911
2912
2913

2914
2915
2916
2917
2918
2919
2920

2921
2922
2923

2924
2925
2926
2927
2928
2929

2930
2931
2932

2933
2934
2935
2936
2937

2938
2939
2940
2941

2942
2943
2944
2945
2946
2947

2948
2949
2950
2951
2952
2953

2954
2955
2956

2957
2958
2959
2960
2961
2962

2963
2964
2965
2966
2967
2968
2969

2970
2971
2972

2973
2974
2975
2976
2977

2978
2979
2980

2981
2982
2983
2984
2985

2986
2987
2988

2989
2990
2991
2992
2993

2994
2995
2996

2997
2998
2999
3000
3001

3002
3003
3004

3005
3006
3007
3008
3009

3010
3011
3012

3013
3014
3015
3016
3017
3018

3019
3020
3021
3022
3023

3024
3025
3026

3027
3028
3029
3030
3031
3032
3033

3034
3035
3036

3037
3038
3039
3040
3041
3042
3043

3044
3045
3046

3047
3048
3049
3050
3051
3052

3053
3054
3055
3056
3057
3058
3059
3060

3061
3062
3063

3064
3065
3066
3067
3068
3069
3070

3071
3072
3073

3074
3075
3076
3077
3078
3079
3080
3081

3082
3083
3084

3085
3086
3087
3088
3089
3090
3091
3092

3093
3094
3095

3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108

3109
3110
3111
3112
3113

3114
3115
3116
3117
3118
3119
3120
3121

3122
3123
3124
3125

3126
3127
3128
3129
3130
3131
3132

3133
3134
3135

3136
3137
3138
3139
3140
3141
3142
3143

3144
3145
3146

3147
3148
3149
3150
3151
3152
3153

3154
3155
3156

3157
3158
3159
3160
3161
3162
3163

3164
3165
3166

3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177

3178
3179
3180

3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191

3192
3193
3194
3195
3196

3197
3198
3199
3200
3201
3202

3203
3204
3205

3206
3207
3208
3209
3210
3211

3212
3213
3214

3215
3216
3217
3218
3219
3220
3221
3222

3223
3224
3225

3226
3227
3228
3229
3230
3231
3232
3233

3234
3235
3236
3237
3238
3239


3240
3241
3242
3243
3244

3245
3246
3247
3248


3249
3250
3251
3252
3253

3254
3255
3256
3257

3258
3259
3260
3261
3262

3263
3264
3265

3266
3267
3268
3269

3270
3271
3272

3273
3274
3275
3276
3277

3278
3279
3280

3281
3282
3283
3284
3285

3286
3287
3288

3289
3290
3291
3292
3293
3294

3295
3296
3297
3298
3299

3300
3301
3302

3303
3304
3305
3306
3307
3308

3309
3310
3311

3312
3313
3314
3315
3316
3317

3318
3319
3320

3321
3322
3323
3324
3325
3326
3327

3328
3329
3330

3331
3332
3333
3334
3335

3336
3337
3338

3339
3340
3341
3342
3343
3344
3345
3346

3347
3348
3349
3350
3351
3352

3353
3354
3355
3356
3357
3358

3359
3360
3361
3362

3363
3364
3365
3366
3367
3368
3369
3370


3371
3372

3373
3374
3375
3376
3377
3378
3379
3380


3381
3382

3383
3384
3385
3386
3387
3388
3389
3390
3391
3392


3393
3394

3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406


3407
3408

3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421


3422
3423
3424

3425
3426
3427
3428
3429
3430

3431
3432
3433

3434
3435
3436
3437
3438
3439
3440
3441
3442

3443
3444
3445
3446

3447
3448
3449
3450
3451

3452
3453
3454

3455
3456
3457
3458
3459
3460

3461
3462
3463

3464
3465
3466
3467
3468
3469
3470
3471
3472
3473

3474
3475
3476
3477
3478

3479
3480
3481

3482
3483
3484
3485
3486

3487
3488
3489

3490
3491
3492
3493
3494
3495
3496

3497
3498
3499

3500
3501
3502
3503
3504
3505
3506
3507

3508
3509
3510

3511
3512
3513
3514
3515
3516
3517
3518
3519

3520
3521
3522

3523
3524
3525
3526
3527
3528
3529
3530
3531

3532
3533
3534

3535
3536
3537
3538
3539
3540
3541
3542
3543
3544

3545
3546
3547

3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558

3559
3560
3561

3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573

3574
3575
3576

3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588

3589
3590
3591

3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603

3604
3605
3606

3607
3608
3609
3610
3611
3612

3613
3614
3615

3616
3617
3618
3619
3620

3621
3622
3623

3624
3625
3626
3627
3628
3629

3630
3631
3632

3633
3634
3635
3636
3637

3638
3639
3640

3641
3642
3643
3644
3645
3646
3647

3648
3649
3650
3651
3652
3653

3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664

3665
3666
3667
3668
3669
3670

3671
3672
3673
3674
3675

3676
3677
3678
3679

3680
3681
3682

3683
3684
3685
3686
3687
3688

3689
3690
3691
3692
3693

3694
3695
3696
3697
3698
3699
3700

3701
3702
3703
3704
3705

3706
3707
3708
3709
3710
3711
3712
3713

3714
3715
3716
3717
3718

3719
3720
3721
3722
3723

3724
3725
3726

3727
3728
3729
3730
3731
3732
3733

3734
3735
3736

3737
3738
3739
3740
3741

3742
3743
3744

3745
3746
3747
3748
3749
3750
3751
3752

3753
3754
3755
3756
3757

3758
3759
3760
3761
3762
3763
3764

3765
3766
3767

3768
3769

3770
3771
3772
3773
3774
3775
3776
3777
3778

3779
3780
3781

3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792

3793
3794
3795

3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806

3807
3808
3809

3810
3811
3812
3813
3814
3815
3816
3817
3818

3819
3820
3821

3822
3823
3824
3825
3826
3827
3828

3829
3830
3831

3832
3833
3834
3835
3836
3837

3838
3839
3840

3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854

3855
3856
3857
3858

3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876

3877
3878
3879
3880
3881

3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899

3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919

3920
3921
3922
3923
3924
3925
3926
2856
2857
2858
2859
2860
2861
2862

2863
2864
2865
2866
2867
2868
2869

2870
2871
2872

2873
2874
2875
2876
2877
2878

2879
2880
2881

2882
2883
2884
2885
2886
2887

2888
2889
2890

2891
2892
2893
2894
2895
2896
2897
2898

2899
2900
2901
2902

2903
2904
2905
2906
2907

2908
2909
2910

2911
2912
2913
2914
2915
2916

2917
2918
2919
2920

2921
2922
2923
2924
2925

2926
2927
2928

2929
2930
2931
2932
2933
2934
2935

2936
2937
2938

2939
2940
2941
2942
2943
2944

2945
2946
2947

2948
2949
2950
2951
2952

2953
2954
2955
2956

2957
2958
2959
2960
2961
2962

2963
2964
2965
2966
2967
2968

2969
2970
2971

2972
2973
2974
2975
2976
2977

2978
2979
2980
2981
2982
2983
2984

2985
2986
2987

2988
2989
2990
2991
2992

2993
2994
2995

2996
2997
2998
2999
3000

3001
3002
3003

3004
3005
3006
3007
3008

3009
3010
3011

3012
3013
3014
3015
3016

3017
3018
3019

3020
3021
3022
3023
3024

3025
3026
3027

3028
3029
3030
3031
3032
3033

3034
3035
3036
3037
3038

3039
3040
3041

3042
3043
3044
3045
3046
3047
3048

3049
3050
3051

3052
3053
3054
3055
3056
3057
3058

3059
3060
3061

3062
3063
3064
3065
3066
3067

3068
3069
3070
3071
3072
3073
3074
3075

3076
3077
3078

3079
3080
3081
3082
3083
3084
3085

3086
3087
3088

3089
3090
3091
3092
3093
3094
3095
3096

3097
3098
3099

3100
3101
3102
3103
3104
3105
3106
3107

3108
3109
3110

3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123

3124
3125
3126
3127
3128

3129
3130
3131
3132
3133
3134
3135
3136

3137
3138
3139
3140

3141
3142
3143
3144
3145
3146
3147

3148
3149
3150

3151
3152
3153
3154
3155
3156
3157
3158

3159
3160
3161

3162
3163
3164
3165
3166
3167
3168

3169
3170
3171

3172
3173
3174
3175
3176
3177
3178

3179
3180
3181

3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192

3193
3194
3195

3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206

3207
3208
3209
3210
3211

3212
3213
3214
3215
3216
3217

3218
3219
3220

3221
3222
3223
3224
3225
3226

3227
3228
3229

3230
3231
3232
3233
3234
3235
3236
3237

3238
3239
3240

3241
3242
3243
3244
3245
3246
3247
3248

3249
3250
3251
3252
3253


3254
3255
3256
3257
3258
3259

3260
3261
3262


3263
3264
3265
3266
3267
3268

3269
3270
3271
3272

3273
3274
3275
3276
3277

3278
3279
3280

3281
3282
3283
3284

3285
3286
3287

3288
3289
3290
3291
3292

3293
3294
3295

3296
3297
3298
3299
3300

3301
3302
3303

3304
3305
3306
3307
3308
3309

3310
3311
3312
3313
3314

3315
3316
3317

3318
3319
3320
3321
3322
3323

3324
3325
3326

3327
3328
3329
3330
3331
3332

3333
3334
3335

3336
3337
3338
3339
3340
3341
3342

3343
3344
3345

3346
3347
3348
3349
3350

3351
3352
3353

3354
3355
3356
3357
3358
3359
3360
3361

3362
3363
3364
3365
3366
3367

3368
3369
3370
3371
3372
3373

3374
3375
3376
3377

3378
3379
3380
3381
3382
3383
3384


3385
3386
3387

3388
3389
3390
3391
3392
3393
3394


3395
3396
3397

3398
3399
3400
3401
3402
3403
3404
3405
3406


3407
3408
3409

3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420


3421
3422
3423

3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435


3436
3437
3438
3439

3440
3441
3442
3443
3444
3445

3446
3447
3448

3449
3450
3451
3452
3453
3454
3455
3456
3457

3458
3459
3460
3461

3462
3463
3464
3465
3466

3467
3468
3469

3470
3471
3472
3473
3474
3475

3476
3477
3478

3479
3480
3481
3482
3483
3484
3485
3486
3487
3488

3489
3490
3491
3492
3493

3494
3495
3496

3497
3498
3499
3500
3501

3502
3503
3504

3505
3506
3507
3508
3509
3510
3511

3512
3513
3514

3515
3516
3517
3518
3519
3520
3521
3522

3523
3524
3525

3526
3527
3528
3529
3530
3531
3532
3533
3534

3535
3536
3537

3538
3539
3540
3541
3542
3543
3544
3545
3546

3547
3548
3549

3550
3551
3552
3553
3554
3555
3556
3557
3558
3559

3560
3561
3562

3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573

3574
3575
3576

3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588

3589
3590
3591

3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603

3604
3605
3606

3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618

3619
3620
3621

3622
3623
3624
3625
3626
3627

3628
3629
3630

3631
3632
3633
3634
3635

3636
3637
3638

3639
3640
3641
3642
3643
3644

3645
3646
3647

3648
3649
3650
3651
3652

3653
3654
3655

3656
3657
3658
3659
3660
3661
3662

3663
3664
3665
3666
3667
3668

3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679

3680
3681
3682
3683
3684
3685

3686
3687
3688
3689
3690

3691
3692
3693
3694

3695
3696
3697

3698
3699
3700
3701
3702
3703

3704
3705
3706
3707
3708

3709
3710
3711
3712
3713
3714
3715

3716
3717
3718
3719
3720

3721
3722
3723
3724
3725
3726
3727
3728

3729
3730
3731
3732
3733

3734
3735
3736
3737
3738

3739
3740
3741

3742
3743
3744
3745
3746
3747
3748

3749
3750
3751

3752
3753
3754
3755
3756

3757
3758
3759

3760
3761
3762
3763
3764
3765
3766
3767

3768
3769
3770
3771
3772

3773
3774
3775
3776
3777
3778
3779

3780
3781
3782

3783
3784

3785
3786
3787
3788
3789
3790
3791
3792
3793

3794
3795
3796

3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807

3808
3809
3810

3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821

3822
3823
3824

3825
3826
3827
3828
3829
3830
3831
3832
3833

3834
3835
3836

3837
3838
3839
3840
3841
3842
3843

3844
3845
3846

3847
3848
3849
3850
3851
3852

3853
3854
3855

3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869

3870
3871
3872
3873

3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891

3892
3893
3894
3895
3896

3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914

3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934

3935
3936
3937
3938
3939
3940
3941
3942







-
+






-
+


-
+





-
+


-
+





-
+


-
+







-
+



-
+




-
+


-
+





-
+



-
+




-
+


-
+






-
+


-
+





-
+


-
+




-
+



-
+





-
+





-
+


-
+





-
+






-
+


-
+




-
+


-
+




-
+


-
+




-
+


-
+




-
+


-
+




-
+


-
+





-
+




-
+


-
+






-
+


-
+






-
+


-
+





-
+







-
+


-
+






-
+


-
+







-
+


-
+







-
+


-
+












-
+




-
+







-
+



-
+






-
+


-
+







-
+


-
+






-
+


-
+






-
+


-
+










-
+


-
+










-
+




-
+





-
+


-
+





-
+


-
+







-
+


-
+







-
+




-
-
+
+




-
+


-
-
+
+




-
+



-
+




-
+


-
+



-
+


-
+




-
+


-
+




-
+


-
+





-
+




-
+


-
+





-
+


-
+





-
+


-
+






-
+


-
+




-
+


-
+







-
+





-
+





-
+



-
+






-
-
+
+

-
+






-
-
+
+

-
+








-
-
+
+

-
+










-
-
+
+

-
+











-
-
+
+


-
+





-
+


-
+








-
+



-
+




-
+


-
+





-
+


-
+









-
+




-
+


-
+




-
+


-
+






-
+


-
+







-
+


-
+








-
+


-
+








-
+


-
+









-
+


-
+










-
+


-
+











-
+


-
+











-
+


-
+











-
+


-
+





-
+


-
+




-
+


-
+





-
+


-
+




-
+


-
+






-
+





-
+










-
+





-
+




-
+



-
+


-
+





-
+




-
+






-
+




-
+







-
+




-
+




-
+


-
+






-
+


-
+




-
+


-
+







-
+




-
+






-
+


-
+

-
+








-
+


-
+










-
+


-
+










-
+


-
+








-
+


-
+






-
+


-
+





-
+


-
+













-
+



-
+

















-
+




-
+

















-
+



















-
+







    deleteWindows
} -body {
    menu .m1
    .m1 add command -label "active"
    .m1 entrycget -1 -label
} -returnCodes error -result {bad menu entry index "-1"}
test menu-13.9 {TkGetMenuIndex} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 add command -label "test"
    .m1 add command -label "test2"
    .m1 entrycget 999 -label
} -cleanup {
	deleteWindows
    deleteWindows
} -result {test2}
test menu-13.10 {TkGetMenuIndex} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 insert 999 command -label "test"
    .m1 entrycget 1 -label
} -cleanup {
	deleteWindows
    deleteWindows
} -result {test}
test menu-13.11 {TkGetMenuIndex} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 add command -label "1test"
    .m1 entrycget 1test -label
} -cleanup {
	deleteWindows
    deleteWindows
} -result {1test}
test menu-13.12 {TkGetMenuIndex} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 add command -label "test"
    .m1 add command -label "test2" -command "beep"
    .m1 add command -label "test3"
    .m1 entrycget test2 -command
} -cleanup {
	deleteWindows
    deleteWindows
} -result {beep}

test menu-14.1 {MenuCmdDeletedProc} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    destroy .m1
} -cleanup {
	deleteWindows
    deleteWindows
} -returnCodes ok
test menu-14.2 {MenuCmdDeletedProc} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 clone .m2
    destroy .m1
} -cleanup {
	deleteWindows
    deleteWindows
} -returnCodes ok

test menu-15.1 {MenuNewEntry} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 add command -label "test"
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}
test menu-15.2 {MenuNewEntry} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 add command -label "test"
    .m1 add command -label "test3"
    .m1 insert 2 command -label "test2"
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}
test menu-15.3 {MenuNewEntry} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 add command -label "test"
    .m1 add command -label "test2"
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}
test menu-15.4 {MenuNewEntry} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 add command -label "test"
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}

test menu-16.1 {MenuAddOrInsert} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 insert foo command -label "test"
} -returnCodes error -result {bad menu entry index "foo"}
test menu-16.2 {MenuAddOrInsert} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 add command -label "test"
    .m1 insert test command -label "foo"
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}
test menu-16.3 {MenuAddOrInsert} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 insert -1 command -label "test"
} -returnCodes error -result {bad menu entry index "-1"}
test menu-16.4 {MenuAddOrInsert} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1 -tearoff 1
    .m1 add command -label "test"
    .m1 insert 0 command -label "test2"
    .m1 entrycget 1 -label
} -cleanup {
	deleteWindows
    deleteWindows
} -result {test2}
test menu-16.5 {MenuAddOrInsert} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 add cascade
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}
test menu-16.6 {MenuAddOrInsert} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 add checkbutton
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}
test menu-16.7 {MenuAddOrInsert} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 add command
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}
test menu-16.8 {MenuAddOrInsert} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 add radiobutton
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}
test menu-16.9 {MenuAddOrInsert} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 add separator
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}
test menu-16.10 {MenuAddOrInsert} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 add blork
} -returnCodes error -result {bad menu entry type "blork": must be cascade, checkbutton, command, radiobutton, or separator}
test menu-16.11 {MenuAddOrInsert} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 add command
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}
test menu-16.12 {MenuAddOrInsert} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 clone .m2
    .m2 clone .m3
    list [.m2 add command -label "test"] [.m1 entrycget 1 -label] [.m3 entrycget 1 -label]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} test test}
test menu-16.13 {MenuAddOrInsert} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 clone .m2
    .m2 clone .m3
    list [.m3 add command -label "test"] [.m1 entrycget 1 -label] [.m2 entrycget 1 -label]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} test test}
test menu-16.14 {MenuAddOrInsert} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 add command -blork
} -returnCodes error -result {unknown option "-blork"}
test menu-16.15 {MenuAddOrInsert} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 add command -label "File"
    menu .container
    . configure -menu .container
    list [.container add cascade -label "File" -menu .m1] [. configure -menu ""]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} {}}
test menu-16.16 {MenuAddOrInsert} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    menu .m2
    set tearoff [tk::TearOffMenu .m2]
    list [.m2 add cascade -menu .m1] [$tearoff unpost]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} {}}
test menu-16.17 {MenuAddOrInsert} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    menu .container
    . configure -menu .container
    set tearoff [tk::TearOffMenu .container]
    list [.container add cascade -label "File" -menu .m1] [. configure -menu ""]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} {}}
test menu-16.18 {MenuAddOrInsert} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    menu .container
    .container add cascade -menu .m1
    . configure -menu .container
    list [.container add cascade -label "File" -menu .m1] [. configure -menu ""]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} {}}
test menu-16.19 {MenuAddOrInsert - Insert a cascade deep into the tree} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .menubar
    menu .menubar.test -tearoff 0
    .menubar add cascade -label Test -underline 0 -menu .menubar.test
    menu .menubar.test.cascade -tearoff 0
    .menubar.test.cascade add command -label SubItem -command "puts SubItemSelected"
    . configure -menu .menubar
    list [catch {.menubar.test add cascade -label SubMenu \
		-menu .menubar.test.cascade}] \
		[info commands .\#menubar.\#menubar\#test.\#menubar\#test\#cascade] \
		[. configure -menu ""]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {0 .#menubar.#menubar#test.#menubar#test#cascade {}}


test menu-17.1 {MenuVarProc} -setup {
	deleteWindows
    deleteWindows
} -body {
    catch {unset foo}
    menu .m1
    set foo "hello"
    list [.m1 add checkbutton -variable foo -onvalue hello -offvalue goodbye] \
		[unset foo]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} {}}
# menu-17.2 - Don't know how to generate the flags in the if
test menu-17.2 {MenuVarProc} -setup {
	deleteWindows
    deleteWindows
} -body {
    catch {unset foo}
    menu .m1
    list [.m1 add checkbutton -variable foo -onvalue hello -offvalue goodbye] \
		[set foo ""]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} {}}
test menu-17.3 {MenuVarProc} -setup {
	deleteWindows
    deleteWindows
} -body {
    catch {unset foo}
    menu .m1
    set foo "hello"
    list [.m1 add checkbutton -variable foo -onvalue hello -offvalue goodbye] \
		[set foo "hello"] [unset foo]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} hello {}}
test menu-17.4 {MenuVarProc} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    set foo "goodbye"
    list [.m1 add checkbutton -variable foo -onvalue hello -offvalue goodbye] \
		[set foo "hello"] [unset foo]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} hello {}}
test menu-17.5 {MenuVarProc} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    set foo "hello"
    list [.m1 add checkbutton -variable foo -onvalue hello -offvalue goodbye] \
		[set foo "goodbye"] [unset foo]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} goodbye {}}
test menu-17.6 {MenuVarProc [5d991b822e]} -setup {
	deleteWindows
    deleteWindows
} -body {
    # Want this not to crash
    menu .b
    set var INIT
    .b add checkbutton -variable var
    trace add variable var unset {apply {args {
        .b entryconfigure 1 -variable {}
    }}}
    unset var
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}
test menu-17.7 {MenuVarProc [5d991b822e]} -setup {
	deleteWindows
    deleteWindows
} -body {
    # Want this not to duplicate traces
    menu .b
    set var INIT
    .b add checkbutton -variable var
    trace add variable var unset {apply {args {
        .b entryconfigure 1 -variable new
    }}}
    unset var
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}


test menu-18.1 {TkActivateMenuEntry} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 add command -label "test"
    .m1 activate 1
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}
test menu-18.2 {TkActivateMenuEntry} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 add command -label "test"
    .m1 activate 0
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}
test menu-18.3 {TkActivateMenuEntry} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 add command -label "test"
    .m1 add command -label "test2"
    .m1 activate 1
    .m1 activate 2
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}
test menu-18.4 {TkActivateMenuEntry} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 add command -label "test"
    .m1 add command -label "test2"
    .m1 activate 1
    .m1 activate 1
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}


test menu-19.1 {TkPostCommand} -constraints nonUnixUserInteraction -setup {
	deleteWindows
} -body { 
    deleteWindows
} -body {
    menu .m1 -postcommand "set menu_test menu-19.1"
    .m1 add command -label "menu-19.1 - hit Escape"
    list [.m1 post 40 40] [.m1 unpost] [set menu_test]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {menu-19.1 {} menu-19.1}
test menu-19.2 {TkPostCommand} -constraints nonUnixUserInteraction -setup {
	deleteWindows
} -body { 
    deleteWindows
} -body {
    menu .m1
    .m1 add command -label "menu-19.2 - hit Escape"
    list [.m1 post 40 40] [.m1 unpost]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} {}}

test menu-20.1 {CloneMenu} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 clone .m2]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}
test menu-20.2 {CloneMenu} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 clone .m2 normal
	deleteWindows
    deleteWindows
} -result {}
test menu-20.3 {CloneMenu} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 clone .m2 tearoff
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}
test menu-20.4 {CloneMenu} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 clone .m2 menubar
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}
test menu-20.5 {CloneMenu} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 clone .m2 foo
} -returnCodes error -result {bad menu type "foo": must be normal, tearoff, or menubar}
test menu-20.6 {CloneMenu - hooking up bookeeping ptrs} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 clone .m2
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}
test menu-20.7 {CloneMenu - hooking up bookeeping ptrs - multiple children} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 clone .m2
    .m1 clone .m3
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}
test menu-20.8 {CloneMenu - cascade entries} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 add cascade -menu .m2
    .m1 clone .foo
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}
test menu-20.9 {CloneMenu - cascades entries} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 add cascade -menu .m2
    menu .m2
    .m1 clone .foo
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}
test menu-20.10 {CloneMenu - tearoff fields} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1 -tearoff 1
    list [.m1 clone .m2 normal] [.m2 cget -tearoff]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} 1}
test menu-20.11 {CloneMenu} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    menu .m2
    .m1 clone .m2
} -returnCodes error -result {window name "m2" already exists in parent}

test menu-21.1 {MenuDoYPosition} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 yposition glorp
} -returnCodes error -result {bad menu entry index "glorp"}
test menu-21.2 {MenuDoYPosition} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 add command -label "Test"
    .m1 yposition 1
} -cleanup {
	deleteWindows
    deleteWindows
} -returnCodes ok -match glob -result {*}

test menu-22.1 {GetIndexFromCoords} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 add command -label "test"
    .m1 configure -tearoff 0
    .m1 index @5
} -cleanup {
	deleteWindows
} -result {0}
    deleteWindows
} -result 0
test menu-22.2 {GetIndexFromCoords} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 add command -label "test"
    .m1 configure -tearoff 0
    .m1 index @5,5
} -cleanup {
	deleteWindows
} -result {0}
    deleteWindows
} -result 0
test menu-22.3 {GetIndexFromCoords: mapped window, y only} -setup {
	deleteWindows
    deleteWindows
} -constraints {x11} -body {
    menu .m1
    .m1 add command -label "test"
    .m1 configure -tearoff 0
    tk_popup .m1 0 0
    tkwait visibility .m1
    .m1 index @5
} -cleanup {
	deleteWindows
} -result {0}
    deleteWindows
} -result 0
test menu-22.4 {GetIndexFromCoords: mapped window x,y} -setup {
	deleteWindows
    deleteWindows
} -constraints {x11} -body {
    menu .m1
    .m1 add command -label "test"
    .m1 configure -tearoff 0
    tk_popup .m1 0 0
    tkwait visibility .m1
    update
    set x [expr {[winfo width .m1] - [.m1 cget -borderwidth] - 1}]
    .m1 index @$x,5
} -cleanup {
	deleteWindows
} -result {0}
    deleteWindows
} -result 0
test menu-22.5 {GetIndexFromCoords: mapped wide window} -setup {
	deleteWindows
    deleteWindows
} -constraints {x11} -body {
    menu .m1
    .m1 add command -label "test"
    .m1 configure -tearoff 0
    tk_popup .m1 0 0
    tkwait visibility .m1
    wm geometry .m1 200x100
    update
    set x [expr {[winfo width .m1] - [.m1 cget -borderwidth] - 1}]
    .m1 index @$x,5
} -cleanup {
	deleteWindows
} -result {0}
    deleteWindows
} -result 0

test menu-23.1 {RecursivelyDeleteMenu} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    . configure -menu .m1
    . configure -menu ""
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}
test menu-23.2 {RecursivelyDeleteMenu} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m2
    .m2 add command -label "test2"
    menu .m1
    .m1 add cascade -label "test1" -menu .m2
    . configure -menu .m1
    . configure -menu ""
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}

test menu-24.1 {TkNewMenuName} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    list [. configure -menu .m1] [. configure -menu ""]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} {}}
test menu-24.2 {TkNewMenuName} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    menu .m1\#0
    list [. configure -menu .m1] [. configure -menu ""]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} {}}
test menu-24.3 {TkNewMenuName} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .#m
    rename .#m hideme
    list [catch {. configure -menu [menu .m]}] [. configure -menu ""] [destroy .#m] \
		[destroy .m] [destroy hideme]
} -result {0 {} {} {} {}}


test menu-25.1 {TkSetWindowMenuBar} -setup {
	deleteWindows
    deleteWindows
} -body {
    . configure -menu ""
    list [. configure -menu .m1] [. configure -menu ""]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} {}}
test menu-25.2 {TkSetWindowMenuBar} -setup {
	deleteWindows
    deleteWindows
} -body {
    . configure -menu ""
    list [. configure -menu .m1] [. configure -menu ""]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} {}}
test menu-25.3 {TkSetWindowMenuBar} -setup {
	deleteWindows
    deleteWindows
} -body {
    . configure -menu ""
    destroy .m1
    menu .m1
    list [. configure -menu .m1] [. configure -menu ""]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} {}}
test menu-25.4 {TkSetWindowMenuBar} -setup {
	deleteWindows
    deleteWindows
} -body {
    . configure -menu ""
    menu .m1
    . configure -menu .m1
    menu .m2
    list [. configure -menu .m2] [. configure -menu ""]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} {}}
test menu-25.5 {TkSetWindowMenuBar} -setup {
	deleteWindows
    deleteWindows
} -body {
    . configure -menu ""
    menu .m1
    . configure -menu .m1
    .m1 clone .m2
    menu .m3
    list [. configure -menu .m3] [. configure -menu ""]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} {}}
test menu-25.6 {TkSetWindowMenuBar} -setup {
	deleteWindows
    deleteWindows
} -body {
    . configure -menu ""
    menu .m1
    .m1 clone .m2
    . configure -menu .m2
    menu .m3
    list [. configure -menu .m3] [. configure -menu ""]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} {}}
test menu-25.7 {TkSetWindowMenuBar} -setup {
	deleteWindows
    deleteWindows
} -body {
    . configure -menu ""
    menu .m1
    menu .m2
    . configure -menu .m1
    toplevel .t2
    .t2 configure -menu .m1
    list [.t2 configure -menu .m2] [. configure -menu ""]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} {}}
test menu-25.8 {TkSetWindowMenuBar} -setup {
	deleteWindows
    deleteWindows
} -body {
    . configure -menu ""
    menu .m1
    menu .m2
    . configure -menu .m1
    toplevel .t2
    wm geometry .t2 +0+0
    .t2 configure -menu .m1
    list [. configure -menu .m2] [. configure -menu ""]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} {}}
test menu-25.9 {TkSetWindowMenuBar} -setup {
	deleteWindows
    deleteWindows
} -body {
    . configure -menu ""
    menu .m1
    menu .m2
    . configure -menu .m1
    toplevel .t2 -menu .m1
    wm geometry .t2 +0+0
    toplevel .t3 -menu .m1
    wm geometry .t3 +0+0
    list [.t3 configure -menu .m2] [. configure -menu ""]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} {}}
test menu-25.10 {TkSetWindowMenuBar} -setup {
	deleteWindows
    deleteWindows
} -body {
    . configure -menu ""
    menu .m1
    menu .m2
    . configure -menu .m1
    toplevel .t2 -menu .m1
    wm geometry .t2 +0+0
    toplevel .t3 -menu .m1
    wm geometry .t3 +0+0
    list [.t2 configure -menu .m2] [. configure -menu ""]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} {}}
test menu-25.11 {TkSetWindowMenuBar} -setup {
	deleteWindows
    deleteWindows
} -body {
    . configure -menu ""
    menu .m1
    menu .m2
    . configure -menu .m1
    toplevel .t2 -menu .m1
    wm geometry .t2 +0+0
    toplevel .t3 -menu .m1
    wm geometry .t3 +0+0
    list [. configure -menu .m2] [. configure -menu ""]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} {}}
test menu-25.12 {TkSetWindowMenuBar} -setup {
	deleteWindows
    deleteWindows
} -body {
    . configure -menu ""
    menu .m1
    list [. configure -menu .m1] [. configure -menu ""]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} {}}
test menu-25.13 {TkSetWindowMenuBar} -setup {
	deleteWindows
    deleteWindows
} -body {
    . configure -menu ""
    list [. configure -menu .m1] [. configure -menu ""]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} {}}
test menu-25.14 {TkSetWindowMenuBar} -setup {
	deleteWindows
    deleteWindows
} -body {
    . configure -menu ""
    menu .m1
    list [. configure -menu .m1] [. configure -menu ""]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} {}}
test menu-25.15 {TkSetWindowMenuBar} -setup {
	deleteWindows
    deleteWindows
} -body {
    . configure -menu ""
    list [. configure -menu .m1] [. configure -menu ""]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} {}}
test menu-25.16 {TkSetWindowMenuBar} -setup {
	deleteWindows
    deleteWindows
} -body {
    . configure -menu ""
    menu .m1
    . configure -menu .m1
    list [toplevel .t2 -menu m1] [. configure -menu ""]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {.t2 {}}


test menu-26.1 {DestroyMenuHashTable} -setup {
    catch {interp delete testinterp}
	deleteWindows
    deleteWindows
} -body {
    interp create testinterp
    load {} Tk testinterp
    interp eval testinterp {menu .m1}
    interp delete testinterp
} -returnCodes ok -result {}


test menu-27.1 {GetMenuHashTable} -setup {
    catch {interp delete testinterp}
	deleteWindows
    deleteWindows
} -body {
    interp create testinterp
    load {} Tk testinterp
    list [catch {interp eval testinterp {menu .m1}} msg] $msg [interp delete testinterp]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {0 .m1 {}}


test menu-28.1 {TkCreateMenuReferences - not there before} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
} -cleanup {
	deleteWindows
    deleteWindows
} -result {.m1}
test menu-28.2 {TkCreateMenuReferences - there already} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 add cascade -menu .m2
    menu .m2
} -cleanup {
	deleteWindows
    deleteWindows
} -result {.m2}


test menu-29.1 {TkFindMenuReferences - not there} -setup {
	deleteWindows
    deleteWindows
} -body {
    . configure -menu ""
    menu .m1
    .m1 add cascade -menu .m2
    list [. configure -menu .m1] [. configure -menu ""]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} {}}


test menu-30.1 {TkFindMenuReferences - there already} -setup {
	deleteWindows
    deleteWindows
} -body {
    . configure -menu ""
    menu .m1
    menu .m2
    .m1 add cascade -menu .m2
    list [. configure -menu .m1] [. configure -menu ""]
} -cleanup {
	deleteWindows
    deleteWindows
} -result {{} {}}


test menu-31.1 {TkFreeMenuReferences - menuPtr} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    destroy .m1
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}
test menu-31.2 {TkFreeMenuReferences - cascadePtr} -setup {
	deleteWindows
    deleteWindows
} -body {
    . configure -menu ""
    menu .m1
    .m1 add cascade -menu .m2
    .m1 entryconfigure 1 -menu .m3
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}
test menu-31.3 {TkFreeMenuReferences - topLevelListPtr} -setup {
	deleteWindows
    deleteWindows
} -body {
    . configure -menu .m1
    . configure -menu ""
} -cleanup {
	deleteWindows
    deleteWindows
} -returnCodes ok -result {}
test menu-31.4 {TkFreeMenuReferences - not empty} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 add cascade -menu .m3
    menu .m2
    .m2 add cascade -menu .m3
    .m2 entryconfigure 1 -menu ".foo"
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}


test menu-32.1 {DeleteMenuCloneEntries} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 add command -label foo
    .m1 clone .m2
    .m1 delete 1
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}
test menu-32.2 {DeleteMenuCloneEntries} -setup {
	deleteWindows
    deleteWindows
} -body {
    

    menu .m1
    .m1 add command -label one
    .m1 add command -label two
    .m1 add command -label three
    .m1 add command -label four
    .m1 clone .m2
    .m1 delete 2 3
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}
test menu-32.3 {DeleteMenuCloneEntries} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1 -tearoff 0
    .m1 add command -label one
    .m1 add command -label two
    .m1 add command -label three
    .m1 add command -label four
    .m1 clone .m2
    .m2 configure -tearoff 1
    .m1 delete 1 2
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}
test menu-32.4 {DeleteMenuCloneEntries} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 add command -label one
    .m1 add command -label two
    .m1 add command -label three
    .m1 add command -label four
    .m1 clone .m2
    .m2 configure -tearoff 0
    .m1 delete 2 3
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}
test menu-32.5 {DeleteMenuCloneEntries} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 add command -label one
    .m1 add command -label two
    .m1 clone .m2
    .m1 activate one
    .m1 delete one
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}
test menu-32.6 {DeleteMenuCloneEntries - reentrancy - crashes tk8.0} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1
    .m1 add command -label test \
		-command ".m1 delete test ; .m1 add command -label test -command \".m1 delete test\"; .m1 delete test"
    .m1 invoke test
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}
test menu-32.7 {DeleteMenuCloneEntries - one entry} -setup {
	deleteWindows
    deleteWindows
} -body {
    menu .m1 -tearoff 0
    .m1 add command -label Hello
    .m1 delete Hello
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}
test menu-32.8 {Ensure all menu clone commands are deleted} -setup {
	deleteWindows
    deleteWindows
} -body {
    # SF bug #465324
    menu .menubar
    . configure -menu .menubar
    menu .menubar.test
    .menubar.test add command -label "hi"
    for {set i 0} {$i < 10} {incr i} {
		.menubar add cascade -menu .menubar.test -label "Test"
		.menubar delete Test
    }

    info commands .#menubar*test*
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}
test menu-32.9 {Ensure deleting of clones doesn't corrupt menu refs} -setup {
    set res {}
	deleteWindows
    deleteWindows
} -body {
    menu .menubar
    . configure -menu .menubar
    menu .menubar.test
    .menubar add cascade -menu .menubar.test -label "Test"
    menu .menubar.cascade

    .menubar.test add cascade -menu .menubar.cascade -label "Cascade"
    lappend res [.menubar.test entrycget 1 -menu]
    lappend res [.#menubar.#menubar#test entrycget 1 -menu]
    destroy .menubar.test
    menu .menubar.test
    .menubar.test add cascade -menu .menubar.cascade -label "Cascade"
    lappend res [.menubar.test entrycget 1 -menu]
    lappend res [.#menubar.#menubar#test entrycget 1 -menu]
    return $res
} -cleanup {
	deleteWindows
    deleteWindows
} -result {.menubar.cascade .#menubar.#menubar#test.#menubar#cascade .menubar.cascade .#menubar.#menubar#test.#menubar#cascade}


test menu-33.1 {menu vs command hiding} -setup {
	deleteWindows
    deleteWindows
} -body {
	set l [interp hidden]
    menu .m
    interp hide {} .m
    destroy .m
    set result [list [winfo children .] [interp hidden]]
	expr {$result eq [list {} $l]}
} -result 1

# menu-34 MenuInit only called at boot time

# creating menus on two different screens then deleting the
# menu from the first screen crashes Tk8.3.1
#
test menu-34.1 {menus on multiple screens - crashes tk8.3.1, Bug 5454} -constraints {
	altDisplay
} -setup {
	deleteWindows
    deleteWindows
} -body {
    toplevel .one
    menu .one.m
    toplevel .two -screen $::env(TK_ALT_DISPLAY)
    menu .two.m
    destroy .one
    destroy .two
} -result {}

test menu-35.1 {menu -underline string overruns Bug 1599877} -setup {
   destroy .m
} -body {
    # ensure that -underline does not do string overruns [Bug 1599877]
    menu .m
    .m add command -label "File" -underline [expr {1<<30}]
    . configure -menu .m
    update
    tk::TraverseToMenu . "e"
} -cleanup {
	deleteWindows
    deleteWindows
} -result {}

test menu-37.1 {menubar menues cannot be posted - bug 2160206} -setup {
    catch {destroy .m}
} -body {
    # On Linux the following used to panic
    # It now returns an error (on all platforms)
3937
3938
3939
3940
3941
3942
3943
3944

3945
3946
3947
3948
3949
3950
3951

3952
3953
3954
3955
3956
3957
3958
3959
3960

3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3953
3954
3955
3956
3957
3958
3959

3960
3961
3962
3963
3964
3965
3966

3967
3968
3969
3970
3971
3972
3973
3974
3975

3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987







-
+






-
+








-
+











    menu .top.mb.m;
    .top.mb.m add command -label "Item 1";
    .top.mb.m add command -label "Item 2";
    .top.mb configure -menu .top.mb.m;
    pack .top.mb
    update
    # simulate mouse click on the menubutton, which posts its menu
    event generate .top.mb <ButtonPress-1> -warp 1
    event generate .top.mb <Button-1> -warp 1
    update
    after 50
    event generate .top.mb <ButtonRelease-1>
    update
    # simulate mouse click on the menu again, i.e. without
    # entering/leaving the posted menu
    event generate .top.mb <ButtonPress-1>
    event generate .top.mb <Button-1>
    update
    after 50
    event generate .top.mb <ButtonRelease-1>
    update
    # the menu shall have been unposted by the second click
    winfo ismapped .top.mb.m
} -cleanup {
    destroy .top.mb.m .top.m .top
} -result {0}
} -result 0


# cleanup
imageFinish
deleteWindows
cleanupTests
return

# Local variables:
# mode: tcl
# End:
Changes to tests/menuDraw.test.
1
2
3
4
5


6
7
8
9
10
11
12
1
2
3


4
5
6
7
8
9
10
11
12



-
-
+
+







# This file is a Tcl script to test drawing of menus in Tk.  It is
# organized in the standard fashion for Tcl tests.
#
# Copyright (c) 1996-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1996-1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
eval tcltest::configure $argv
tcltest::loadTestedCommands
namespace import -force tcltest::test
imageInit
72
73
74
75
76
77
78
79

80
81
82
83
84
85
86
72
73
74
75
76
77
78

79
80
81
82
83
84
85
86







-
+







} -result {}
test menuDraw-5.3 {TkMenuConfigureDrawOptions - no disabledFg} -setup {
    deleteWindows
} -body {
    menu .m1 -disabledforeground ""
} -cleanup {
    deleteWindows
} -result {.m1}  
} -result {.m1}


test menuDraw-6.1 {TkMenuConfigureEntryDrawOptions - no tkfont specified} -setup {
    deleteWindows
} -body {
    menu .m1
    .m1 add command -label "foo"
317
318
319
320
321
322
323
324

325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341

342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357

358
359
360
361
362
363
364
317
318
319
320
321
322
323

324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340

341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356

357
358
359
360
361
362
363
364







-
+
















-
+















-
+







    update idletasks
} -cleanup {
    deleteWindows
} -result {}


test menuDraw-11.1 {TkMenuSelectImageProc - entry selected; redraw not pending} -constraints {
    testImageType 
    testImageType
} -setup {
    deleteWindows
    imageCleanup
} -body {
    image create test image1
    image create test image2
    menu .m1
    .m1 add checkbutton -image image1 -selectimage image2
    .m1 invoke 1
    set tearoff [tk::TearOffMenu .m1 40 40]
    update idletasks
    list [image delete image2] [destroy .m1]
} -cleanup {
    imageCleanup
} -result {{} {}}
test menuDraw-11.2 {TkMenuSelectImageProc - entry selected; redraw pending} -constraints {
    testImageType 
    testImageType
} -setup {
    deleteWindows
    imageCleanup
} -body {
    image create test image1
    image create test image2
    menu .m1
    .m1 add checkbutton -image image1 -selectimage image2
    .m1 invoke 1
    set tearoff [tk::TearOffMenu .m1 40 40]
    list [image delete image2] [destroy .m1]
} -cleanup {
    imageCleanup
} -result {{} {}}
test menuDraw-11.3 {TkMenuSelectImageProc - entry not selected} -constraints {
    testImageType 
    testImageType
} -setup {
    deleteWindows
    imageCleanup
} -body {
    image create test image1
    image create test image2
    menu .m1
447
448
449
450
451
452
453
454

455
456
457
458
459
460
461
447
448
449
450
451
452
453

454
455
456
457
458
459
460
461







-
+







    .m1 add command -label "six"
    set tearoff [tk::TearOffMenu .m1 40 40]
    update
} -cleanup {
    deleteWindows
} -result {}
test menuDraw-12.6 {Display menu - testing for extra space and menubars} -constraints {
    unix 
    unix
} -setup {
    deleteWindows
} -body {
    menu .m1
    .m1 add cascade -label foo
    . configure -menu .m1
    update
557
558
559
560
561
562
563
564

565
566
567
568
569
570
571
557
558
559
560
561
562
563

564
565
566
567
568
569
570
571







-
+







} -body {
    menu .m1
    .m1 add command -label "foo" -state active
    set tearoff [tk::TearOffMenu .m1 40 40]
    $tearoff index active
} -cleanup {
    deleteWindows
} -result {none}
} -result none
test menuDraw-15.3 {TkPostTearoffMenu - post command} -setup {
    deleteWindows
} -body {
    catch {unset foo}
    menu .m1 -postcommand "set foo .m1"
    .m1 add command -label "foo"
    list [catch {tk::TearOffMenu .m1 40 40}] [set foo] [unset foo] [destroy .m1]
664
665
666
667
668
669
670
671

672
673
674
675
676
677
678
664
665
666
667
668
669
670

671
672
673
674
675
676
677
678







-
+







    deleteWindows
} -body {
    menu .m1
    .m1 add cascade -label test -menu .m2
    menu .m2
    .m2 add command -label "Hit ESCAPE to get rid of this menu"
    set tearoff [tk::TearOffMenu .m1 40 40]
    $tearoff postcascade 0 
    $tearoff postcascade 0
} -cleanup {
    deleteWindows
} -result {}


test menuDraw-17.1 {AdjustMenuCoords - menubar} -constraints unix -setup {
    deleteWindows
Changes to tests/menubut.test.
1
2
3
4
5
6



7
8
9
10
11
12
13
1
2
3



4
5
6
7
8
9
10
11
12
13



-
-
-
+
+
+







# This file is a Tcl script to test menubuttons in Tk.  It is
# organized in the standard fashion for Tcl tests.
#
# Copyright (c) 1994 The Regents of the University of California.
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1994 The Regents of the University of California.
# Copyright © 1994-1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

# XXX This test file is woefully incomplete right now.  If any part
# XXX of a procedure has tests then the whole procedure has tests,
# XXX but many procedures have no tests.

package require tcltest 2.2
67
68
69
70
71
72
73
74

75
76
77
78
79
80
81
67
68
69
70
71
72
73

74
75
76
77
78
79
80
81







-
+







    .mb configure -background non-existent
} -returnCodes error -result {unknown color name "non-existent"}
test menubutton-1.9 {configuration options} -body {
    .mb configure -bd 4
    .mb cget -bd
} -cleanup {
    .mb configure -bd [lindex [.mb configure -bd] 3]
} -result {4}
} -result 4
test menubutton-1.10 {configuration options} -body {
    .mb configure -bd badValue
} -returnCodes error -result {bad screen distance "badValue"}
test menubutton-1.11 {configuration options} -body {
    .mb configure -bg #ff0000
    .mb cget -bg
} -cleanup {
94
95
96
97
98
99
100
101

102
103
104
105
106
107
108
94
95
96
97
98
99
100

101
102
103
104
105
106
107
108







-
+







    .mb configure -bitmap badValue
} -returnCodes error -result {bitmap "badValue" not defined}
test menubutton-1.15 {configuration options} -body {
    .mb configure -borderwidth 1.3
    .mb cget -borderwidth
} -cleanup {
    .mb configure -borderwidth [lindex [.mb configure -borderwidth] 3]
} -result {1}
} -result 1
test menubutton-1.16 {configuration options} -body {
    .mb configure -borderwidth badValue
} -returnCodes error -result {bad screen distance "badValue"}
test menubutton-1.17 {configuration options} -body {
    .mb configure -cursor arrow
    .mb cget -cursor
} -cleanup {
154
155
156
157
158
159
160
161

162
163
164
165
166
167
168
154
155
156
157
158
159
160

161
162
163
164
165
166
167
168







-
+







    .mb configure -foreground bogus
} -returnCodes error -result {unknown color name "bogus"}
test menubutton-1.28 {configuration options} -body {
    .mb configure -height 18
    .mb cget -height
} -cleanup {
    .mb configure -height [lindex [.mb configure -height] 3]
} -result {18}
} -result 18
test menubutton-1.29 {configuration options} -body {
    .mb configure -height 20.0
} -returnCodes error -result {expected integer but got "20.0"}
test menubutton-1.30 {configuration options} -body {
    .mb configure -highlightbackground #112233
    .mb cget -highlightbackground
} -cleanup {
181
182
183
184
185
186
187
188

189
190
191
192
193
194
195
181
182
183
184
185
186
187

188
189
190
191
192
193
194
195







-
+







    .mb configure -highlightcolor bogus
} -returnCodes error -result {unknown color name "bogus"}
test menubutton-1.34 {configuration options} -body {
    .mb configure -highlightthickness 18
    .mb cget -highlightthickness
} -cleanup {
    .mb configure -highlightthickness [lindex [.mb configure -highlightthickness] 3]
} -result {18}
} -result 18
test menubutton-1.35 {configuration options} -body {
    .mb configure -highlightthickness badValue
} -returnCodes error -result {bad screen distance "badValue"}
test menubutton-1.36 {configuration options} -constraints {
    testImageType
} -setup {
    catch {image delete image1}
209
210
211
212
213
214
215
216

217
218
219
220
221
222
223
209
210
211
212
213
214
215

216
217
218
219
220
221
222
223







-
+







    .mb configure -image [lindex [.mb configure -image] 3]
} -returnCodes error -result {image "bogus" doesn't exist}
test menubutton-1.38 {configuration options} -body {
    .mb configure -indicatoron yes
    .mb cget -indicatoron
} -cleanup {
    .mb configure -indicatoron [lindex [.mb configure -indicatoron] 3]
} -result {1}
} -result 1
test menubutton-1.39 {configuration options} -body {
    .mb configure -indicatoron no_way
} -returnCodes error -result {expected boolean value but got "no_way"}
test menubutton-1.40 {configuration options} -body {
    .mb configure -justify right
    .mb cget -justify
} -cleanup {
233
234
235
236
237
238
239
240

241
242
243
244
245
246
247
248
249

250
251
252
253
254
255
256
233
234
235
236
237
238
239

240
241
242
243
244
245
246
247
248

249
250
251
252
253
254
255
256







-
+








-
+







    .mb configure -menu [lindex [.mb configure -menu] 3]
} -result {any old string}
test menubutton-1.43 {configuration options} -body {
    .mb configure -padx 12
    .mb cget -padx
} -cleanup {
    .mb configure -padx [lindex [.mb configure -padx] 3]
} -result {12}
} -result 12
test menubutton-1.44 {configuration options} -body {
    .mb configure -padx 420x
} -returnCodes error -result {bad screen distance "420x"}
test menubutton-1.45 {configuration options} -body {
    .mb configure -pady 12
    .mb cget -pady
} -cleanup {
    .mb configure -pady [lindex [.mb configure -pady] 3]
} -result {12}
} -result 12
test menubutton-1.46 {configuration options} -body {
    .mb configure -pady 420x
} -returnCodes error -result {bad screen distance "420x"}
test menubutton-1.47 {configuration options} -body {
    .mb configure -relief groove
    .mb cget -relief
} -cleanup {
287
288
289
290
291
292
293
294

295
296
297
298
299
300
301
302
303

304
305
306
307
308
309
310
311
312

313
314
315
316
317
318
319
287
288
289
290
291
292
293

294
295
296
297
298
299
300
301
302

303
304
305
306
307
308
309
310
311

312
313
314
315
316
317
318
319







-
+








-
+








-
+







    .mb configure -textvariable [lindex [.mb configure -textvariable] 3]
} -result {i}
test menubutton-1.54 {configuration options} -body {
    .mb configure -underline 5
    .mb cget -underline
} -cleanup {
    .mb configure -underline [lindex [.mb configure -underline] 3]
} -result {5}
} -result 5
test menubutton-1.55 {configuration options} -body {
    .mb configure -underline 3p
} -returnCodes error -result {expected integer but got "3p"}
test menubutton-1.56 {configuration options} -body {
    .mb configure -width 402
    .mb cget -width
} -cleanup {
    .mb configure -width [lindex [.mb configure -width] 3]
} -result {402}
} -result 402
test menubutton-1.57 {configuration options} -body {
    .mb configure -width 3p
} -returnCodes error -result {expected integer but got "3p"}
test menubutton-1.58 {configuration options} -body {
    .mb configure -wraplength 100
    .mb cget -wraplength
} -cleanup {
    .mb configure -wraplength [lindex [.mb configure -wraplength] 3]
} -result {100}
} -result 100
test menubutton-1.59 {configuration options} -body {
    .mb configure -wraplength 6x
} -returnCodes error -result {bad screen distance "6x"}


deleteWindows
menubutton .mb -text "Test"
360
361
362
363
364
365
366
367

368
369
370

371
372
373
374
375
376
377
360
361
362
363
364
365
366

367
368
369

370
371
372
373
374
375
376
377







-
+


-
+







} -returnCodes error -result {wrong # args: should be ".mb cget option"}
test menubutton-3.5 {ButtonWidgetCmd procedure, "cget" option} -body {
    .mb cget -gorp
} -returnCodes error -result {unknown option "-gorp"}
test menubutton-3.6 {ButtonWidgetCmd procedure, "cget" option} -body {
    .mb configure -highlightthickness 3
    .mb cget -highlightthickness
} -result {3}
} -result 3
test menubutton-3.7 {ButtonWidgetCmd procedure, "configure" option} -body {
    llength [.mb configure]
} -result {33}
} -result 33
test menubutton-3.8 {ButtonWidgetCmd procedure, "configure" option} -body {
    .mb configure -gorp
} -returnCodes error -result {unknown option "-gorp"}
test menubutton-3.9 {ButtonWidgetCmd procedure, "configure" option} -body {
    .mb co -bg #ffffff -fg
} -returnCodes error -result {value for "-fg" missing}
test menubutton-3.10 {ButtonWidgetCmd procedure, "configure" option} -body {
390
391
392
393
394
395
396
397

398
399
400
401
402
403
404
390
391
392
393
394
395
396

397
398
399
400
401
402
403
404







-
+







test menubutton-4.1 {ConfigureMenuButton procedure} -setup {
    deleteWindows
} -body {
    button .mb1 -text "Menubutton 1"
    .mb1 configure -width 1i
} -cleanup {
    deleteWindows
} -returnCodes error -result {expected integer but got "1i"} 
} -returnCodes error -result {expected integer but got "1i"}
test menubutton-4.2 {ConfigureMenuButton procedure} -setup {
    deleteWindows
} -body {
    button .mb1 -text "Menubutton 1"
    catch {.mb1 configure -width 1i}
    return $errorInfo
} -cleanup {
447
448
449
450
451
452
453
454

455
456
457
458
459
460
461
462
463
464
465
466
467

468
469
470
471
472
473
474
447
448
449
450
451
452
453

454
455
456
457
458
459
460
461
462
463
464
465
466

467
468
469
470
471
472
473
474







-
+












-
+







    deleteWindows
} -result {bad screen distance "abc"
    (processing -width option)
    invoked from within
".mb1 configure -width abc"}

test menubutton-4.7 {ConfigureMenuButton procedure} -constraints {
    testImageType 
    testImageType
} -setup {
    deleteWindows
    imageCleanup
} -body {
    image create test image1
    button .mb1 -image image1
    .mb1 configure -height 0.5x
} -cleanup {
    deleteWindows
    imageCleanup
} -returnCodes error -result {bad screen distance "0.5x"}
test menubutton-4.8 {ConfigureMenuButton procedure} -constraints {
    testImageType 
    testImageType
} -setup {
    deleteWindows
    imageCleanup
} -body {
    image create test image1
    button .mb1 -image image1
    catch {.mb1 configure -height 0.5x}
495
496
497
498
499
500
501
502

503
504
505
506
507
508
509
495
496
497
498
499
500
501

502
503
504
505
506
507
508
509







-
+







    deleteWindows
} -result {102 46 20 12}

test menubutton-4.10 {ConfigureMenuButton procedure - bad direction} -setup {
    deleteWindows
} -body {
    menubutton .mb -text "Test"
    .mb configure -direction badValue 
    .mb configure -direction badValue
} -cleanup {
    deleteWindows
} -returnCodes error -result {bad direction "badValue": must be above, below, flush, left, or right}
test menubutton-4.11 {ConfigureMenuButton procedure - bad direction} -setup {
    deleteWindows
} -body {
    menubutton .mb -text "Test"
544
545
546
547
548
549
550
551

552
553
554
555
556
557
558
559
560
561
562
563
564

565
566
567
568
569
570
571
572
573
574
575
576
577

578
579
580
581
582
583
584
585
586
587
588
589
590

591
592
593
594
595
596
597
598
599
600
601
602
603
604

605
606
607
608
609
610
611
544
545
546
547
548
549
550

551
552
553
554
555
556
557
558
559
560
561
562
563

564
565
566
567
568
569
570
571
572
573
574
575
576

577
578
579
580
581
582
583
584
585
586
587
588
589

590
591
592
593
594
595
596
597
598
599
600
601
602
603

604
605
606
607
608
609
610
611







-
+












-
+












-
+












-
+













-
+








if {[tk windowingsystem] == "aqua"} {
    set extraWidth 36
} else {
    set extraWidth 0
}
test menubutton-7.1 {ComputeMenuButtonGeometry procedure} -constraints {
    testImageType 
    testImageType
} -setup {
    deleteWindows
    image create test image1
} -body {
    menubutton .mb -image image1 -bd 4 -highlightthickness 0
    pack .mb
    list [winfo reqwidth .mb] [winfo reqheight .mb]
} -cleanup {
    deleteWindows
    imageCleanup
} -result [list [expr {38 + $extraWidth}] 23]
test menubutton-7.2 {ComputeMenuButtonGeometry procedure} -constraints {
    testImageType 
    testImageType
} -setup {
    deleteWindows
    image create test image1
} -body {
    menubutton .mb -image image1 -bd 3 -highlightthickness 1
    pack .mb
    list [winfo reqwidth .mb] [winfo reqheight .mb]
} -cleanup {
    deleteWindows
    imageCleanup
} -result [list [expr {38 + $extraWidth}] 23]
test menubutton-7.3 {ComputeMenuButtonGeometry procedure} -constraints {
    testImageType 
    testImageType
} -setup {
    deleteWindows
    image create test image1
} -body {
    menubutton .mb -image image1 -bd 1 -highlightthickness 3 -padx 5 -pady 5
    pack .mb
    list [winfo reqwidth .mb] [winfo reqheight .mb]
} -cleanup {
    deleteWindows
    imageCleanup
} -result [list [expr {38 + $extraWidth}] 23]
test menubutton-7.4 {ComputeMenuButtonGeometry procedure} -constraints {
    testImageType 
    testImageType
} -setup {
    deleteWindows
    image create test image1
} -body {
    menubutton .mb -image image1 -bd 2 -relief raised -width 40 \
        -highlightthickness 2
    pack .mb
    list [winfo reqwidth .mb] [winfo reqheight .mb]
} -cleanup {
    deleteWindows
    imageCleanup
} -result [list [expr {48 + $extraWidth}] 23]
test menubutton-7.5 {ComputeMenuButtonGeometry procedure} -constraints {
    testImageType 
    testImageType
} -setup {
    deleteWindows
    image create test image1
} -body {
    menubutton .mb -image image1 -bd 2 -relief raised -height 30 \
        -highlightthickness 2
    pack .mb
Changes to tests/message.test.
1
2
3
4
5
6



7
8
9
10
11
12
13
14
15
16


17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

36
37
38

39
40
41
42
43
44

45
46
47
48
49
50
51
52
53
54
55

56
57
58

59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75

76
77
78

79
80
81
82
83
84

85
86
87
88
89
90
91
92
93
94
95

96
97
98

99
100

101
102
103
104
105
106
107
108
109
110
111
112
113
114
115

116
117
118

119
120
121
122
123
124

125
126
127
128
129
130
131
132
133
134
135

136
137
138

139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155

156
157
158

159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175

176
177
178

179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195

196
197
198

199
200
201

202
203
204
205
206
207
208
209
210
211
212
213
214
215

216
217
218

219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235

236
237
238

239
240
241

242
243
244
245
246
247
248
249
250
251
252
253
254
255

256
257
258

259
260
261

262
263
264

265
266
267
268
269
270
271
272
273
274
275

276
277
278

279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295

296
297
298

299
300
301

302
303
304
305
306
307
308
309
310
311
312
313
314
315

316
317
318

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335

336
337
338

339
340
341

342
343
344
345
346
347
348
349
350
351
352
353
354
355

356
357
358

359
360
361
362
363
364
365
366

367
368
369

370
371
372

373
374
375
376
377

378
379
380

381
382
383

384
385
386

387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406

407
408
409
410
411
412
413
414

415
416

417
418
419
420
421
422

423
424
425
426
427
428
429
1
2
3



4
5
6
7
8
9
10
11
12
13
14


15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

35
36
37

38
39
40
41
42
43

44
45
46
47
48
49
50
51
52
53
54

55
56
57

58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74

75
76
77

78
79
80
81
82
83

84
85
86
87
88
89
90
91
92
93
94

95
96
97

98
99

100
101
102
103
104
105
106
107
108
109
110
111
112
113
114

115
116
117

118
119
120
121
122
123

124
125
126
127
128
129
130
131
132
133
134

135
136
137

138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154

155
156
157

158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174

175
176
177

178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194

195
196
197

198
199
200

201
202
203
204
205
206
207
208
209
210
211
212
213
214

215
216
217

218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234

235
236
237

238
239
240

241
242
243
244
245
246
247
248
249
250
251
252
253
254

255
256
257

258
259
260

261
262
263

264
265
266
267
268
269
270
271
272
273
274

275
276
277

278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294

295
296
297

298
299
300

301
302
303
304
305
306
307
308
309
310
311
312
313
314

315
316
317

318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334

335
336
337

338
339
340

341
342
343
344
345
346
347
348
349
350
351
352
353
354

355
356
357

358
359
360
361
362
363
364
365

366
367
368

369
370
371

372
373
374
375
376

377
378
379

380
381
382

383
384
385

386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405

406
407
408
409
410
411
412
413

414
415

416
417
418
419
420
421

422
423
424
425
426
427
428
429



-
-
-
+
+
+








-
-
+
+


















-
+


-
+





-
+










-
+


-
+
















-
+


-
+





-
+










-
+


-
+

-
+














-
+


-
+





-
+










-
+


-
+
















-
+


-
+
















-
+


-
+
















-
+


-
+


-
+













-
+


-
+
















-
+


-
+


-
+













-
+


-
+


-
+


-
+










-
+


-
+
















-
+


-
+


-
+













-
+


-
+
















-
+


-
+


-
+













-
+


-
+







-
+


-
+


-
+




-
+


-
+


-
+


-
+



















-
+







-
+

-
+





-
+







# This file is a Tcl script to test out the "message" command
# of Tk.  It is organized in the standard fashion for Tcl tests.
#
# Copyright (c) 1994 The Regents of the University of California.
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-2000 by Ajuba Solutions.
# Copyright © 1994 The Regents of the University of California.
# Copyright © 1994-1996 Sun Microsystems, Inc.
# Copyright © 1998-2000 Ajuba Solutions.
# All rights reserved.

package require tcltest 2.2
namespace import ::tcltest::*
tcltest::loadTestedCommands
eval tcltest::configure $argv


test message-1.1 {configuration option: "anchor"} -setup { 
    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold} 
test message-1.1 {configuration option: "anchor"} -setup {
    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .m
    update
} -body {
    .m configure -anchor w
    .m cget -anchor
} -cleanup {
    destroy .m
} -result {w}
test message-1.2 {configuration option: "anchor"} -setup {
    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .m
    update
} -body {
    .m configure -anchor bogus
} -cleanup {
    destroy .m
} -returnCodes {error} -result {bad anchor "bogus": must be n, ne, e, se, s, sw, w, nw, or center}

test message-1.3 {configuration option: "aspect"} -setup { 
test message-1.3 {configuration option: "aspect"} -setup {
    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .m
    update 
    update
} -body {
    .m configure -aspect 3
    .m cget -aspect
} -cleanup {
    destroy .m
} -result {3}
} -result 3
test message-1.4 {configuration option: "aspect"} -setup {
    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .m
    update
} -body {
    .m configure -aspect bogus
} -cleanup {
    destroy .m
} -returnCodes {error} -result {expected integer but got "bogus"}

test message-1.5 {configuration option: "background"} -setup { 
test message-1.5 {configuration option: "background"} -setup {
    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .m
    update 
    update
} -body {
    .m configure -background #ff0000
    .m cget -background
} -cleanup {
    destroy .m
} -result {#ff0000}
test message-1.6 {configuration option: "background"} -setup {
    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .m
    update
} -body {
    .m configure -background non-existent
} -cleanup {
    destroy .m
} -returnCodes {error} -result {unknown color name "non-existent"}

test message-1.7 {configuration option: "bd"} -setup { 
test message-1.7 {configuration option: "bd"} -setup {
    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .m
    update 
    update
} -body {
    .m configure -bd 4
    .m cget -bd
} -cleanup {
    destroy .m
} -result {4}
} -result 4
test message-1.8 {configuration option: "bd"} -setup {
    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .m
    update
} -body {
    .m configure -bd badValue
} -cleanup {
    destroy .m
} -returnCodes {error} -result {bad screen distance "badValue"}

test message-1.9 {configuration option: "bg"} -setup { 
test message-1.9 {configuration option: "bg"} -setup {
    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .m
    update 
    update
} -body {
    .m configure -bg #ff0000 
    .m configure -bg #ff0000
    .m cget -bg
} -cleanup {
    destroy .m
} -result {#ff0000}
test message-1.10 {configuration option: "bg"} -setup {
    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .m
    update
} -body {
    .m configure -bg non-existent
} -cleanup {
    destroy .m
} -returnCodes {error} -result {unknown color name "non-existent"}

test message-1.11 {configuration option: "borderwidth"} -setup { 
test message-1.11 {configuration option: "borderwidth"} -setup {
    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .m
    update 
    update
} -body {
    .m configure -borderwidth 1.3
    .m cget -borderwidth
} -cleanup {
    destroy .m
} -result {1}
} -result 1
test message-1.12 {configuration option: "borderwidth"} -setup {
    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .m
    update
} -body {
    .m configure -borderwidth badValue
} -cleanup {
    destroy .m
} -returnCodes {error} -result {bad screen distance "badValue"}

test message-1.13 {configuration option: "cursor"} -setup { 
test message-1.13 {configuration option: "cursor"} -setup {
    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .m
    update 
    update
} -body {
    .m configure -cursor arrow
    .m cget -cursor
} -cleanup {
    destroy .m
} -result {arrow}
test message-1.14 {configuration option: "cursor"} -setup {
    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .m
    update
} -body {
    .m configure -cursor badValue
} -cleanup {
    destroy .m
} -returnCodes {error} -result {bad cursor spec "badValue"}

test message-1.15 {configuration option: "fg"} -setup { 
test message-1.15 {configuration option: "fg"} -setup {
    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .m
    update 
    update
} -body {
    .m configure -fg #00ff00
    .m cget -fg
} -cleanup {
    destroy .m
} -result {#00ff00}
test message-1.16 {configuration option: "fg"} -setup {
    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .m
    update
} -body {
    .m configure -fg badValue
} -cleanup {
    destroy .m
} -returnCodes {error} -result {unknown color name "badValue"}

test message-1.17 {configuration option: "font"} -setup { 
test message-1.17 {configuration option: "font"} -setup {
    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .m
    update 
    update
} -body {
    .m configure -font fixed
    .m cget -font
} -cleanup {
    destroy .m
} -result {fixed}
test message-1.18 {configuration option: "font"} -setup {
    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .m
    update
} -body {
    .m configure -font {}
} -cleanup {
    destroy .m
} -returnCodes {error} -result {font "" doesn't exist}

test message-1.19 {configuration option: "-foreground"} -setup { 
test message-1.19 {configuration option: "-foreground"} -setup {
    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .m
    update 
    update
} -body {
    .m configure -foreground  green
    .m cget -foreground 
    .m cget -foreground
} -cleanup {
    destroy .m
} -result {green}
test message-1.20 {configuration option: "-foreground"} -setup {
    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .m
    update
} -body {
    .m configure -foreground  badValue
} -cleanup {
    destroy .m
} -returnCodes {error} -result {unknown color name "badValue"}

test message-1.21 {configuration option: "highlightbackground"} -setup { 
test message-1.21 {configuration option: "highlightbackground"} -setup {
    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .m
    update 
    update
} -body {
    .m configure -highlightbackground  #112233
    .m cget -highlightbackground
} -cleanup {
    destroy .m
} -result {#112233}
test message-1.22 {configuration option: "highlightbackground"} -setup {
    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .m
    update
} -body {
    .m configure -highlightbackground  ugly
} -cleanup {
    destroy .m
} -returnCodes {error} -result {unknown color name "ugly"}

test message-1.23 {configuration option: "highlightcolor"} -setup { 
test message-1.23 {configuration option: "highlightcolor"} -setup {
    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .m
    update 
    update
} -body {
    .m configure -highlightcolor #123456
    .m cget -highlightcolor 
    .m cget -highlightcolor
} -cleanup {
    destroy .m
} -result {#123456}
test message-1.24 {configuration option: "highlightcolor"} -setup {
    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .m
    update
} -body {
    .m configure -highlightcolor non-existent
} -cleanup {
    destroy .m
} -returnCodes {error} -result {unknown color name "non-existent"}

test message-1.25 {configuration option: "highlightthickness"} -setup { 
test message-1.25 {configuration option: "highlightthickness"} -setup {
    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .m
    update 
    update
} -body {
    .m configure -highlightthickness  2
    .m cget -highlightthickness 
    .m cget -highlightthickness
} -cleanup {
    destroy .m
} -result {2}
} -result 2
test message-1.26 {configuration option: "highlightthickness"} -setup {
    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .m
    update
} -body {
    .m configure -highlightthickness  badValue
} -cleanup {
    destroy .m
} -returnCodes {error} -result {bad screen distance "badValue"}

test message-1.27 {configuration option: "justify"} -setup { 
test message-1.27 {configuration option: "justify"} -setup {
    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .m
    update 
    update
} -body {
    .m configure -justify  right
    .m cget -justify
} -cleanup {
    destroy .m
} -result {right}
test message-1.28 {configuration option: "justify"} -setup {
    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .m
    update
} -body {
    .m configure -justify bogus
} -cleanup {
    destroy .m
} -returnCodes {error} -result {bad justification "bogus": must be left, right, or center}

test message-1.29 {configuration option: "padx"} -setup { 
test message-1.29 {configuration option: "padx"} -setup {
    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .m
    update 
    update
} -body {
    .m configure -padx  12m
    .m cget -padx 
    .m cget -padx
} -cleanup {
    destroy .m
} -result {12m}
test message-1.30 {configuration option: "padx"} -setup {
    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .m
    update
} -body {
    .m configure -padx 420x
} -cleanup {
    destroy .m
} -returnCodes {error} -result {bad screen distance "420x"}

test message-1.31 {configuration option: "pady"} -setup { 
test message-1.31 {configuration option: "pady"} -setup {
    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .m
    update 
    update
} -body {
    .m configure -pady  12m
    .m cget -pady
} -cleanup {
    destroy .m
} -result {12m}
test message-1.32 {configuration option: "pady"} -setup {
    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .m
    update
} -body {
    .m configure -pady 420x
} -cleanup {
    destroy .m
} -returnCodes {error} -result {bad screen distance "420x"}

test message-1.33 {configuration option: "relief"} -setup { 
test message-1.33 {configuration option: "relief"} -setup {
    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .m
    update 
    update
} -body {
    .m configure -relief ridge
    .m cget -relief 
    .m cget -relief
} -cleanup {
    destroy .m
} -result {ridge}
test message-1.34 {configuration option: "relief"} -setup {
    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .m
    update
} -body {
    .m configure -relief  badValue
} -cleanup {
    destroy .m
} -returnCodes {error} -result {bad relief "badValue": must be flat, groove, raised, ridge, solid, or sunken}

test message-1.35 {configuration options: "text"} -setup { 
test message-1.35 {configuration options: "text"} -setup {
    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .m
    update 
    update
} -body {
    .m configure -text "Sample text"
    .m cget -text
} -cleanup {
    destroy .m
} -result {Sample text}

test message-1.36 {configuration option: "textvariable"} -setup { 
test message-1.36 {configuration option: "textvariable"} -setup {
    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .m
    update 
    update
} -body {
    .m configure -textvariable  i
    .m cget -textvariable 
    .m cget -textvariable
} -cleanup {
    destroy .m
} -result {i}

test message-1.37 {configuration option: "width"} -setup { 
test message-1.37 {configuration option: "width"} -setup {
    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .m
    update 
    update
} -body {
    .m configure -width  2
    .m cget -width 
    .m cget -width
} -cleanup {
    destroy .m
} -result {2}
} -result 2
test message-1.38 {configuration option: "width"} -setup {
    message .m -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold}
    pack .m
    update
} -body {
    .m configure -width badValue
} -cleanup {
    destroy .m
} -returnCodes {error} -result {bad screen distance "badValue"}


test message-2.1 {Tk_MessageObjCmd procedure} -body {
    message
} -returnCodes {error} -result {wrong # args: should be "message pathName ?-option value ...?"}

test message-2.2 {Tk_MessageObjCmd procedure} -body {
    message foo
} -returnCodes {error} -result {bad window path name "foo"}
test message-2.3 {Tk_MessageObjCmd procedure} -body {
    catch {message foo}  
    catch {message foo}
    winfo child .
} -result {}

test message-2.4 {Tk_MessageObjCmd procedure} -body {
    message .s -gorp dump
} -returnCodes {error} -result {unknown option "-gorp"}
test message-2.5 {Tk_MessageObjCmd procedure} -body {
    catch {message .s -gorp dump}  
    catch {message .s -gorp dump}
    winfo child .
} -result {} 
} -result {}


test message-3.1 {MessageWidgetObjCmd procedure} -setup {
    message .m
} -body {
    .m 
    .m
} -cleanup {
    destroy .m
} -returnCodes error -result {wrong # args: should be ".m option ?arg ...?"}
test message-3.2 {MessageWidgetObjCmd procedure, "cget"} -setup {
    message .m
} -body {
    .m cget
438
439
440
441
442
443
444
445

446
447
448
449
450
451
452
453
454
455

456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471

472
473
474
475
476
477
478
438
439
440
441
442
443
444

445
446
447
448
449
450
451
452
453
454

455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470

471
472
473
474
475
476
477
478







-
+









-
+















-
+







    destroy .m
} -returnCodes error -result {unknown option "-gorp"}

test message-3.4 {MessageWidgetObjCmd procedure, "configure"} -setup {
    message .m
} -body {
    .m configure -text foobar
    lindex [.m configure -text] 4 
    lindex [.m configure -text] 4
} -cleanup {
    destroy .m
} -result {foobar}
test message-3.5 {MessageWidgetObjCmd procedure, "configure"} -setup {
    message .m
} -body {
    llength [.m configure]
} -cleanup {
    destroy .m
} -result {21}
} -result 21
test message-3.6 {MessageWidgetObjCmd procedure, "configure"} -setup {
    message .m
} -body {
    .m configure -foo
} -cleanup {
    destroy .m
} -returnCodes error -result {unknown option "-foo"}
test message-3.7 {MessageWidgetObjCmd procedure, "configure"} -setup {
    message .m
} -body {
    .m configure -bd 4
    .m configure -bg #ffffff
    lindex [.m configure -bd] 4
} -cleanup {
    destroy .m
} -result {4}
} -result 4

test message-4.1 {Bug [5d991b822e]} {
    # Want this not to segfault, or write to variable with empty name
    unset -nocomplain {}
    set var INIT
    message .b -textvariable var
    trace add variable var unset {apply {args {
Changes to tests/msgbox.test.
1
2
3
4
5


6
7
8
9
10
11
12
1
2
3


4
5
6
7
8
9
10
11
12



-
-
+
+







# This file is a Tcl script to test out Tk's "tk_messageBox" command.
# It is organized in the standard fashion for Tcl tests.
#
# Copyright (c) 1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
eval tcltest::configure $argv
tcltest::loadTestedCommands
namespace import -force tcltest::test

90
91
92
93
94
95
96
97

98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116

117
118
119
120
121
122
123
124

125
126
127
128
129
130

131
132
133
134
135
136
137

138
139
140
141
142
143
144

145
146
147
148
149
150
151

152
153
154
155
156
157
158

159
160
161
162
163
164
165

166
167
168
169
170
171
172

173
174
175
176
177
178
179

180
181
182
183
184
185

186
187
188
189
190
191
192

193
194
195
196
197
198
199

200
201
202
203
204
205
206

207
208
209
210
211
212
213

214
215
216
217
218
219
220

221
222
223
224
225
226

227
228
229
230
231
232
233

234
235
236
237
238
239
240

241
242
243
244
245
246
247

248
249
250
251
252
253
254

255
256
257
258
259
260
261

262
263
264
265
266
267
268

269
270
271
272
273
274

275
276
277
278
279
280
281

282
283
284
285
286
287
288

289
290
291
292
293
294
295

296
297
298
299
300
301
302

303
304
305
306
307
308
309

310
311
312
313
314
315
316

317
318
319
320
321
322

323
324
325
326
327
328
329

330
331
332
333
334
335
336

337
338
339
340
341
342
343

344
345
346
347
348
349
350

351
352
353
354
355
356
357

358
359
360
361
362
363
364

365
366
367
368
369
370

371
372
373
374
375
376
377

378
379
380
381
382
383
384

385
386
387
388
389
390
391

392
393
394
395
396
397
398

399
400
401
402
403
404
405

406
407
408
409
410
411
412

413
414
415
416
417
418
419
420
421
422

423
424
425
426
427
428
429
430
431
432
433

434
435
436
437
438
439
440
90
91
92
93
94
95
96

97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115

116
117
118
119
120
121
122
123

124
125
126
127
128
129

130
131
132
133
134
135
136

137
138
139
140
141
142
143

144
145
146
147
148
149
150

151
152
153
154
155
156
157

158
159
160
161
162
163
164

165
166
167
168
169
170
171

172
173
174
175
176
177
178

179
180
181
182
183
184

185
186
187
188
189
190
191

192
193
194
195
196
197
198

199
200
201
202
203
204
205

206
207
208
209
210
211
212

213
214
215
216
217
218
219

220
221
222
223
224
225

226
227
228
229
230
231
232

233
234
235
236
237
238
239

240
241
242
243
244
245
246

247
248
249
250
251
252
253

254
255
256
257
258
259
260

261
262
263
264
265
266
267

268
269
270
271
272
273

274
275
276
277
278
279
280

281
282
283
284
285
286
287

288
289
290
291
292
293
294

295
296
297
298
299
300
301

302
303
304
305
306
307
308

309
310
311
312
313
314
315

316
317
318
319
320
321

322
323
324
325
326
327
328

329
330
331
332
333
334
335

336
337
338
339
340
341
342

343
344
345
346
347
348
349

350
351
352
353
354
355
356

357
358
359
360
361
362
363

364
365
366
367
368
369

370
371
372
373
374
375
376

377
378
379
380
381
382
383

384
385
386
387
388
389
390

391
392
393
394
395
396
397

398
399
400
401
402
403
404

405
406
407
408
409
410
411

412
413
414
415
416
417
418
419
420
421

422
423
424
425
426
427
428
429
430
431
432

433
434
435
436
437
438
439
440







-
+


















-
+







-
+





-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+





-
+






-
+






-
+






-
+






-
+






-
+





-
+






-
+






-
+






-
+






-
+






-
+






-
+





-
+






-
+






-
+






-
+






-
+






-
+






-
+





-
+






-
+






-
+






-
+






-
+






-
+






-
+





-
+






-
+






-
+






-
+






-
+






-
+






-
+









-
+










-
+







    if {!$isNative} {
	after 100 SendEventToMsg $parent $btn key
    }
}

proc PressButton {btn} {
    event generate $btn <Enter>
    event generate $btn <ButtonPress-1> -x 5 -y 5
    event generate $btn <Button-1> -x 5 -y 5
    event generate $btn <ButtonRelease-1> -x 5 -y 5
}

proc SendEventToMsg {parent btn type} {
    if {$parent != "."} {
	set w $parent.__tk__messagebox
    } else {
	set w .__tk__messagebox
    }
    if ![winfo ismapped $w.$btn] {
	update
    }
    if {$type == "mouse"} {
	PressButton $w.$btn
    } else {
	event generate $w <Enter>
	focus $w
	event generate $w.$btn <Enter>
	event generate $w <KeyPress> -keysym Return
	event generate $w <Key> -keysym Return
    }
}
#
# Try out all combinations of (type) x (default button) and
# (type) x (icon).
#
test msgbox-2.1 {tk_messageBox command} -constraints {
    nonUnixUserInteraction 
    nonUnixUserInteraction
} -body {
    ChooseMsg . abort
    tk_messageBox -title Hi -message "Please press abort" -type abortretryignore
} -result {abort}
test msgbox-2.2 {tk_messageBox command -icon option} -constraints {
    nonUnixUserInteraction 
    nonUnixUserInteraction
} -body {
    ChooseMsg . abort
    tk_messageBox -title Hi -message "Please press abort" \
        -type abortretryignore -icon warning
} -result {abort}
test msgbox-2.3 {tk_messageBox command -icon option} -constraints {
    nonUnixUserInteraction 
    nonUnixUserInteraction
} -body {
    ChooseMsg . abort
    tk_messageBox -title Hi -message "Please press abort" \
        -type abortretryignore -icon error
} -result {abort}
test msgbox-2.4 {tk_messageBox command -icon option} -constraints {
    nonUnixUserInteraction 
    nonUnixUserInteraction
} -body {
    ChooseMsg . abort
    tk_messageBox -title Hi -message "Please press abort" \
        -type abortretryignore -icon info
} -result {abort}
test msgbox-2.5 {tk_messageBox command -icon option} -constraints {
    nonUnixUserInteraction 
    nonUnixUserInteraction
} -body {
    ChooseMsg . abort
    tk_messageBox -title Hi -message "Please press abort" \
        -type abortretryignore -icon question
} -result {abort}
test msgbox-2.6 {tk_messageBox command} -constraints {
    nonUnixUserInteraction 
    nonUnixUserInteraction
} -body {
    ChooseMsg . abort
    tk_messageBox -title Hi -message "Please press abort" \
        -type abortretryignore -default abort
} -result {abort}
test msgbox-2.7 {tk_messageBox command} -constraints {
    nonUnixUserInteraction 
    nonUnixUserInteraction
} -body {
    ChooseMsg . retry
    tk_messageBox -title Hi -message "Please press retry" \
        -type abortretryignore -default retry
} -result {retry}
test msgbox-2.8 {tk_messageBox command} -constraints {
    nonUnixUserInteraction 
    nonUnixUserInteraction
} -body {
    ChooseMsg . ignore
    tk_messageBox -title Hi -message "Please press ignore" \
        -type abortretryignore -default ignore
} -result {ignore}
test msgbox-2.9 {tk_messageBox command} -constraints {
    nonUnixUserInteraction 
    nonUnixUserInteraction
} -body {
    ChooseMsg . ok
    tk_messageBox -title Hi -message "Please press ok" -type ok
} -result {ok}
test msgbox-2.10 {tk_messageBox command -icon option} -constraints {
    nonUnixUserInteraction 
    nonUnixUserInteraction
} -body {
    ChooseMsg . ok
    tk_messageBox -title Hi -message "Please press ok" \
        -type ok -icon warning
} -result {ok}
test msgbox-2.11 {tk_messageBox command -icon option} -constraints {
    nonUnixUserInteraction 
    nonUnixUserInteraction
} -body {
    ChooseMsg . ok
    tk_messageBox -title Hi -message "Please press ok" \
        -type ok -icon error
} -result {ok}
test msgbox-2.12 {tk_messageBox command -icon option} -constraints {
    nonUnixUserInteraction 
    nonUnixUserInteraction
} -body {
    ChooseMsg . ok
    tk_messageBox -title Hi -message "Please press ok" \
        -type ok -icon info
} -result {ok}
test msgbox-2.13 {tk_messageBox command -icon option} -constraints {
    nonUnixUserInteraction 
    nonUnixUserInteraction
} -body {
    ChooseMsg . ok
    tk_messageBox -title Hi -message "Please press ok" \
        -type ok -icon question
} -result {ok}
test msgbox-2.14 {tk_messageBox command} -constraints {
    nonUnixUserInteraction 
    nonUnixUserInteraction
} -body {
    ChooseMsg . ok
    tk_messageBox -title Hi -message "Please press ok" \
        -type ok -default ok
} -result {ok}
test msgbox-2.15 {tk_messageBox command} -constraints {
    nonUnixUserInteraction 
    nonUnixUserInteraction
} -body {
    ChooseMsg . ok
    tk_messageBox -title Hi -message "Please press ok" -type okcancel
} -result {ok}
test msgbox-2.16 {tk_messageBox command -icon option} -constraints {
    nonUnixUserInteraction 
    nonUnixUserInteraction
} -body {
    ChooseMsg . ok
    tk_messageBox -title Hi -message "Please press ok" \
        -type okcancel -icon warning
} -result {ok}
test msgbox-2.17 {tk_messageBox command -icon option} -constraints {
    nonUnixUserInteraction 
    nonUnixUserInteraction
} -body {
    ChooseMsg . ok
    tk_messageBox -title Hi -message "Please press ok" \
        -type okcancel -icon error
} -result {ok}
test msgbox-2.18 {tk_messageBox command -icon option} -constraints {
    nonUnixUserInteraction 
    nonUnixUserInteraction
} -body {
    ChooseMsg . ok
    tk_messageBox -title Hi -message "Please press ok" \
        -type okcancel -icon info
} -result {ok}
test msgbox-2.19 {tk_messageBox command -icon option} -constraints {
    nonUnixUserInteraction 
    nonUnixUserInteraction
} -body {
    ChooseMsg . ok
    tk_messageBox -title Hi -message "Please press ok" \
        -type okcancel -icon question
} -result {ok}
test msgbox-2.20 {tk_messageBox command} -constraints {
    nonUnixUserInteraction 
    nonUnixUserInteraction
} -body {
    ChooseMsg . ok
    tk_messageBox -title Hi -message "Please press ok" \
        -type okcancel -default ok
} -result {ok}
test msgbox-2.21 {tk_messageBox command} -constraints {
    nonUnixUserInteraction 
    nonUnixUserInteraction
} -body {
    ChooseMsg . cancel
    tk_messageBox -title Hi -message "Please press cancel" \
        -type okcancel -default cancel
} -result {cancel}
test msgbox-2.22 {tk_messageBox command} -constraints {
    nonUnixUserInteraction 
    nonUnixUserInteraction
} -body {
    ChooseMsg . retry
    tk_messageBox -title Hi -message "Please press retry" -type retrycancel
} -result {retry}
test msgbox-2.23 {tk_messageBox command -icon option} -constraints {
    nonUnixUserInteraction 
    nonUnixUserInteraction
} -body {
    ChooseMsg . retry
    tk_messageBox -title Hi -message "Please press retry" \
        -type retrycancel -icon warning
} -result {retry}
test msgbox-2.24 {tk_messageBox command -icon option} -constraints {
    nonUnixUserInteraction 
    nonUnixUserInteraction
} -body {
    ChooseMsg . retry
    tk_messageBox -title Hi -message "Please press retry" \
        -type retrycancel -icon error
} -result {retry}
test msgbox-2.25 {tk_messageBox command -icon option} -constraints {
    nonUnixUserInteraction 
    nonUnixUserInteraction
} -body {
    ChooseMsg . retry
    tk_messageBox -title Hi -message "Please press retry" \
        -type retrycancel -icon info
} -result {retry}
test msgbox-2.26 {tk_messageBox command -icon option} -constraints {
    nonUnixUserInteraction 
    nonUnixUserInteraction
} -body {
    ChooseMsg . retry
    tk_messageBox -title Hi -message "Please press retry" \
        -type retrycancel -icon question
} -result {retry}
test msgbox-2.27 {tk_messageBox command} -constraints {
    nonUnixUserInteraction 
    nonUnixUserInteraction
} -body {
    ChooseMsg . retry
    tk_messageBox -title Hi -message "Please press retry" \
        -type retrycancel -default retry
} -result {retry}
test msgbox-2.28 {tk_messageBox command} -constraints {
    nonUnixUserInteraction 
    nonUnixUserInteraction
} -body {
    ChooseMsg . cancel
    tk_messageBox -title Hi -message "Please press cancel" \
        -type retrycancel -default cancel
} -result {cancel}
test msgbox-2.29 {tk_messageBox command} -constraints {
    nonUnixUserInteraction 
    nonUnixUserInteraction
} -body {
    ChooseMsg . yes
    tk_messageBox -title Hi -message "Please press yes" -type yesno
} -result {yes}
test msgbox-2.30 {tk_messageBox command -icon option} -constraints {
    nonUnixUserInteraction 
    nonUnixUserInteraction
} -body {
    ChooseMsg . yes
    tk_messageBox -title Hi -message "Please press yes" \
        -type yesno -icon warning
} -result {yes}
test msgbox-2.31 {tk_messageBox command -icon option} -constraints {
    nonUnixUserInteraction 
    nonUnixUserInteraction
} -body {
    ChooseMsg . yes
    tk_messageBox -title Hi -message "Please press yes" \
        -type yesno -icon error
} -result {yes}
test msgbox-2.32 {tk_messageBox command -icon option} -constraints {
    nonUnixUserInteraction 
    nonUnixUserInteraction
} -body {
    ChooseMsg . yes
    tk_messageBox -title Hi -message "Please press yes" \
        -type yesno -icon info
} -result {yes}
test msgbox-2.33 {tk_messageBox command -icon option} -constraints {
    nonUnixUserInteraction 
    nonUnixUserInteraction
} -body {
    ChooseMsg . yes
    tk_messageBox -title Hi -message "Please press yes" \
        -type yesno -icon question
} -result {yes}
test msgbox-2.34 {tk_messageBox command} -constraints {
    nonUnixUserInteraction 
    nonUnixUserInteraction
} -body {
    ChooseMsg . yes
    tk_messageBox -title Hi -message "Please press yes" \
        -type yesno -default yes
} -result {yes}
test msgbox-2.35 {tk_messageBox command} -constraints {
    nonUnixUserInteraction 
    nonUnixUserInteraction
} -body {
    ChooseMsg . no
    tk_messageBox -title Hi -message "Please press no" \
        -type yesno -default no
} -result {no}
test msgbox-2.36 {tk_messageBox command} -constraints {
    nonUnixUserInteraction 
    nonUnixUserInteraction
} -body {
    ChooseMsg . yes
    tk_messageBox -title Hi -message "Please press yes" -type yesnocancel
} -result {yes}
test msgbox-2.37 {tk_messageBox command -icon option} -constraints {
    nonUnixUserInteraction 
    nonUnixUserInteraction
} -body {
    ChooseMsg . yes
    tk_messageBox -title Hi -message "Please press yes" \
        -type yesnocancel -icon warning
} -result {yes}
test msgbox-2.38 {tk_messageBox command -icon option} -constraints {
    nonUnixUserInteraction 
    nonUnixUserInteraction
} -body {
    ChooseMsg . yes
    tk_messageBox -title Hi -message "Please press yes" \
        -type yesnocancel -icon error
} -result {yes}
test msgbox-2.39 {tk_messageBox command -icon option} -constraints {
    nonUnixUserInteraction 
    nonUnixUserInteraction
} -body {
    ChooseMsg . yes
    tk_messageBox -title Hi -message "Please press yes" \
        -type yesnocancel -icon info
} -result {yes}
test msgbox-2.40 {tk_messageBox command -icon option} -constraints {
    nonUnixUserInteraction 
    nonUnixUserInteraction
} -body {
    ChooseMsg . yes
    tk_messageBox -title Hi -message "Please press yes" \
        -type yesnocancel -icon question
} -result {yes}
test msgbox-2.41 {tk_messageBox command} -constraints {
    nonUnixUserInteraction 
    nonUnixUserInteraction
} -body {
    ChooseMsg . yes
    tk_messageBox -title Hi -message "Please press yes" \
        -type yesnocancel -default yes
} -result {yes}
test msgbox-2.42 {tk_messageBox command} -constraints {
    nonUnixUserInteraction 
    nonUnixUserInteraction
} -body {
    ChooseMsg . no
    tk_messageBox -title Hi -message "Please press no" \
        -type yesnocancel -default no
} -result {no}
test msgbox-2.43 {tk_messageBox command} -constraints {
    nonUnixUserInteraction 
    nonUnixUserInteraction
} -body {
    ChooseMsg . cancel
    tk_messageBox -title Hi -message "Please press cancel" \
        -type yesnocancel -default cancel
} -result {cancel}


# These tests will hang your test suite if they fail.
test msgbox-3.1 {tk_messageBox handles withdrawn parent} -constraints {
	nonUnixUserInteraction 
	nonUnixUserInteraction
} -body {
    wm withdraw .
    ChooseMsg . "ok"
    tk_messageBox -title Hi -message "Please press ok" \
	    -type ok -default ok
} -cleanup {
    wm deiconify .
} -result {ok}

test msgbox-3.2 {tk_messageBox handles iconified parent} -constraints {
	nonUnixUserInteraction 
	nonUnixUserInteraction
} -body {
    wm iconify .
    ChooseMsg . "ok"
    tk_messageBox -title Hi -message "Please press ok" \
	    -type ok -default ok
} -cleanup {
    wm deiconify .
Changes to tests/obj.test.
1
2
3
4
5


6
7
8
9
10
11
12
1
2
3


4
5
6
7
8
9
10
11
12



-
-
+
+







# This file is a Tcl script to test new object types in Tk.
# It is organized in the standard fashion for Tcl tests.
#
# Copyright (c) 1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
namespace import ::tcltest::*
eval tcltest::configure $argv
tcltest::loadTestedCommands

Changes to tests/oldpack.test.
1
2
3
4
5
6
7



8
9
10
11
12
13
14
1
2
3
4



5
6
7
8
9
10
11
12
13
14




-
-
-
+
+
+







# This file is a Tcl script to test out the old syntax of Tk's
# "pack" command (before release 3.3).  It is organized in the
# standard fashion for Tcl tests.
#
# Copyright (c) 1991-1994 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1991-1994 The Regents of the University of California.
# Copyright © 1994 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
eval tcltest::configure $argv
tcltest::loadTestedCommands
namespace import -force tcltest::test

25
26
27
28
29
30
31
32





33
34

35
36
37
38
39
40
41
25
26
27
28
29
30
31
32
33
34
35
36
37
38

39
40
41
42
43
44
45
46








+
+
+
+
+

-
+







place .pack.green.l -relwidth 1.0 -relheight 1.0
frame .pack.blue -width 40 -height 40
label .pack.blue.l -text B -bd 2 -relief raised
place .pack.blue.l -relwidth 1.0 -relheight 1.0
frame .pack.violet -width 80 -height 20
label .pack.violet.l -text P -bd 2 -relief raised
place .pack.violet.l -relwidth 1.0 -relheight 1.0

if {![catch {pack ap .pack .pack.red top}]} {

# Don't execute any of this file if Tk is compiled with -DTCL_NO_DEPRECATED


test oldpack-1.1 {basic positioning} -body {
    pack ap .pack .pack.red top
    #pack ap .pack .pack.red top
    update
    winfo geometry .pack.red
} -result 10x20+45+0
test oldpack-1.2 {basic positioning} -body {
    pack append .pack .pack.red bottom
    update
    winfo geometry .pack.red
448
449
450
451
452
453
454
455

456
457
458

459
460
461
462
463
464
465
453
454
455
456
457
458
459

460
461
462

463
464
465
466
467
468
469
470







-
+


-
+







    pack
} -returnCodes error -result {wrong # args: should be "pack option arg ?arg ...?"}
test oldpack-8.2 {syntax errors} -body {
    pack append
} -returnCodes error -result {wrong # args: should be "pack option arg ?arg ...?"}
test oldpack-8.3 {syntax errors} -body {
    pack gorp foo
} -returnCodes error -result {bad option "gorp": must be configure, forget, info, propagate, or slaves}
} -returnCodes error -result {bad option "gorp": must be configure, content, forget, info, or propagate}
test oldpack-8.4 {syntax errors} -body {
    pack a .pack
} -returnCodes error -result {bad option "a": must be configure, forget, info, propagate, or slaves}
} -returnCodes error -result {bad option "a": must be configure, content, forget, info, or propagate}
test oldpack-8.5 {syntax errors} -body {
    pack after foobar
} -returnCodes error -result {bad window path name "foobar"}
test oldpack-8.6 {syntax errors} -setup {
    destroy .pack.yellow
} -body {
    frame .pack.yellow -bg yellow
488
489
490
491
492
493
494
495

496
497
498
499
500
501
502
493
494
495
496
497
498
499

500
501
502
503
504
505
506
507







-
+







    pack info foobar
} -returnCodes error -result {bad window path name "foobar"}
test oldpack-8.12 {syntax errors} -body {
    pack append .pack .pack.blue
} -returnCodes error -result {wrong # args: window ".pack.blue" should be followed by options}
test oldpack-8.13 {syntax errors} -body {
    pack append . .pack.blue top
} -returnCodes error -result {can't pack .pack.blue inside .}
} -returnCodes error -result {can't pack ".pack.blue" inside "."}
test oldpack-8.14 {syntax errors} -body {
    pack append .pack .pack.blue f
} -returnCodes error -result {bad option "f": should be top, bottom, left, right, expand, fill, fillx, filly, padx, pady, or frame}
test oldpack-8.15 {syntax errors} -body {
    pack append .pack .pack.blue pad
} -returnCodes error -result {bad option "pad": should be top, bottom, left, right, expand, fill, fillx, filly, padx, pady, or frame}
test oldpack-8.16 {syntax errors} -body {
523
524
525
526
527
528
529
530

531
532
533
534
535
536
537

538
539
540
541
542
543

544
545
546

547
548
549
550
551
552
528
529
530
531
532
533
534

535
536
537
538
539
540
541

542
543
544
545
546
547

548
549
550
551
552
553
554
555
556
557
558







-
+






-
+





-
+



+







# Test "pack info" command output.

test oldpack-9.1 {information output} -body {
    pack append .pack .pack.blue {top fillx frame n} \
    .pack.red {bottom filly frame s} .pack.green {left fill frame w} \
    .pack.violet {right expand frame e}
    list [pack slaves .pack] [pack info .pack.blue] [pack info .pack.red] \
    list [pack content .pack] [pack info .pack.blue] [pack info .pack.red] \
        [pack info .pack.green] [pack info .pack.violet]
} -result {{.pack.blue .pack.red .pack.green .pack.violet} {-in .pack -anchor n -expand 0 -fill x -ipadx 0 -ipady 0 -padx 0 -pady 0 -side top} {-in .pack -anchor s -expand 0 -fill y -ipadx 0 -ipady 0 -padx 0 -pady 0 -side bottom} {-in .pack -anchor w -expand 0 -fill both -ipadx 0 -ipady 0 -padx 0 -pady 0 -side left} {-in .pack -anchor e -expand 1 -fill none -ipadx 0 -ipady 0 -padx 0 -pady 0 -side right}}
test oldpack-9.2 {information output} -body {
    pack append .pack .pack.blue {padx 10 frame nw} \
    .pack.red {pady 20 frame ne} .pack.green {frame se} \
    .pack.violet {frame sw}
    list [pack slaves .pack] [pack info .pack.blue] [pack info .pack.red] \
    list [pack content .pack] [pack info .pack.blue] [pack info .pack.red] \
        [pack info .pack.green] [pack info .pack.violet]
} -result {{.pack.blue .pack.red .pack.green .pack.violet} {-in .pack -anchor nw -expand 0 -fill none -ipadx 0 -ipady 0 -padx 5 -pady 0 -side top} {-in .pack -anchor ne -expand 0 -fill none -ipadx 0 -ipady 0 -padx 0 -pady 10 -side top} {-in .pack -anchor se -expand 0 -fill none -ipadx 0 -ipady 0 -padx 0 -pady 0 -side top} {-in .pack -anchor sw -expand 0 -fill none -ipadx 0 -ipady 0 -padx 0 -pady 0 -side top}}
test oldpack-9.3 {information output} -body {
    pack append .pack .pack.blue {frame center} .pack.red {frame center} \
    .pack.green {frame c} .pack.violet {frame c}
    list [pack slaves .pack] [pack info .pack.blue] [pack info .pack.red] \
    list [pack content .pack] [pack info .pack.blue] [pack info .pack.red] \
        [pack info .pack.green] [pack info .pack.violet]
} -result {{.pack.blue .pack.red .pack.green .pack.violet} {-in .pack -anchor center -expand 0 -fill none -ipadx 0 -ipady 0 -padx 0 -pady 0 -side top} {-in .pack -anchor center -expand 0 -fill none -ipadx 0 -ipady 0 -padx 0 -pady 0 -side top} {-in .pack -anchor center -expand 0 -fill none -ipadx 0 -ipady 0 -padx 0 -pady 0 -side top} {-in .pack -anchor center -expand 0 -fill none -ipadx 0 -ipady 0 -padx 0 -pady 0 -side top}}

}
destroy .pack

# cleanup
cleanupTests
return

Changes to tests/option.file1.
9
10
11
12
13
14
15
16

17
18
9
10
11
12
13
14
15

16
17
18







-
+


*\
x3 \
  : pur\
ple
*x 4:	brown
# More comments, this time delimited by hash-marks.
	# Comment-line with space.
*x6:	  
*x6:
*x9: \ \	\\\101\n
# comment line as last line of file.
Changes to tests/option.file3.
9
10
11
12
13
14
15
16

17
18
9
10
11
12
13
14
15

16
17
18







-
+


*\
x3 \
  : pur\
ple
*x 4:	brówn
# More comments, this time delimited by hash-marks.
	# Comment-line with space.
*x6:	  
*x6:
*x9: \ \	\\\101\n
# comment line as last line of file.
Changes to tests/option.test.
1
2
3
4
5
6



7
8
9
10
11
12
13
1
2
3



4
5
6
7
8
9
10
11
12
13



-
-
-
+
+
+







# This file is a Tcl script to test out the option-handling facilities
# of Tk.  It is organized in the standard fashion for Tcl tests.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
namespace import ::tcltest::*
eval tcltest::configure $argv
tcltest::loadTestedCommands

281
282
283
284
285
286
287
288

289
290
291
292
293
294
295
281
282
283
284
285
286
287

288
289
290
291
292
293
294
295







-
+







} -result {}
test option-12.6 {stack pushing/popping} -body {
    option get .op1 z Color2
} -result {}

# Test the major priority levels (widgetDefault, etc.)

# Configurations for tests 13.* 
# Configurations for tests 13.*
option clear
option add $appName.op1.a 100 100
option add $appName.op1.A interactive interactive
option add $appName.op1.b userDefault userDefault
option add $appName.op1.B startupFile startupFile
option add $appName.op1.c widgetDefault widgetDefault
option add $appName.op1.C 0 0
397
398
399
400
401
402
403
404

405
406
407
408
409
410
411
397
398
399
400
401
402
403

404
405
406
407
408
409
410
411







-
+







} -result burgundy
test option-15.10 {database files} -body {
    set option2 [file join [testsDirectory] option.file2]
    option read $option2
} -returnCodes error -result {missing colon on line 2}
set option3 [file join [testsDirectory] option.file3]
option read $option3
test option-15.11 {database files} {option get . {x 4} color} br\xf3wn
test option-15.11 {database files} {option get . {x 4} color} brówn

test option-16.1 {ReadOptionFile} -body {
    set option4 [makeFile {} option.file3]
    set file [open $option4 w]
    fconfigure $file -translation crlf
    puts $file "*x7: true\n*x8: false"
    close $file
Changes to tests/pack.test.
1
2


3
4
5
6



7
8
9
10
11
12
13


14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

32
33
34
35
36
37
38


1
2
3



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

33
34
35
36
37
38
39
40
-
-
+
+

-
-
-
+
+
+







+
+

















-
+







# This file is a Tcl script to test out the "pack" command
# of Tk.  It is organized in the standard fashion for Tcl tests.
# This file is a Tcl script to test out the "pack" command of Tk.  It is
# organized in the standard fashion for Tcl tests.
#
# Copyright (c) 1993 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1993 The Regents of the University of California.
# Copyright © 1994 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
eval tcltest::configure $argv
tcltest::loadTestedCommands
namespace import -force tcltest::test

testConstraint failsOnUbuntu [expr {![info exists ::env(CI)] || ![string match Linux $::tcl_platform(os)]}]
testConstraint failsOnXQuarz [expr {$tcl_platform(os) ne "Darwin" || [tk windowingsystem] ne "x11" }]

# Create some test windows.

destroy .pack
toplevel .pack
wm geom .pack 300x200+0+0
wm minsize .pack 1 1
update idletasks
foreach i {a b c d} {
    frame .pack.$i
    label .pack.$i.label -text $i -relief raised
    place .pack.$i.label -relwidth 1.0 -relheight 1.0
}
.pack.a config -width 20 -height 40
.pack.b config -width 50 -height 30
.pack.c config -width 80 -height 80
.pack.d config -width 40 -height 30


test pack-1.1 {-side option} -setup {
    pack forget .pack.a .pack.b .pack.c .pack.d
} -body {
    pack .pack.a -side top
    pack .pack.b -expand yes -fill both
    update
    list [winfo geometry .pack.a] [winfo geometry .pack.b]
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
229
230
231
232
233
234
235

236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253

254
255
256
257
258
259
260







-


















-







    pack forget .pack.a .pack.b .pack.c .pack.d
} -body {
    pack .pack.a -side top -ipadx 5 -padx {5 15} -fill x
    pack .pack.b -expand yes -fill both
    update
    list [winfo geometry .pack.a] [winfo geometry .pack.b]
} -result {280x40+5+0 300x160+0+40}

test pack-2.22 {x padding and filling} -setup {
    pack forget .pack.a .pack.b .pack.c .pack.d
} -body {
    pack .pack.a -padx 1c
    set x [pack info .pack.a]
    set res1 [lindex $x [expr [lsearch -exact $x -padx]+1]]
    set res2 [winfo pixels .pack 1c]
    expr {$res1 eq $res2}
} -result 1
test pack-2.23 {x padding and filling} -setup {
    pack forget .pack.a .pack.b .pack.c .pack.d
} -body {
    pack .pack.a -ipadx 1c
    set x [pack info .pack.a]
    set res1 [lindex $x [expr [lsearch -exact $x -ipadx]+1]]
    set res2 [winfo pixels .pack 1c]
    expr {$res1 eq $res2}
} -result 1


test pack-3.1 {y padding and filling} -setup {
    pack forget .pack.a .pack.b .pack.c .pack.d
} -body {
    pack .pack.a -side right -pady 20
    pack .pack.b -expand yes -fill both
    update
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
416
417
418
419
420
421
422

423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440

441
442
443
444
445
446
447







-


















-







    pack forget .pack.a .pack.b .pack.c .pack.d
} -body {
    pack .pack.a -side top -ipady 5 -pady {1 19} -fill y
    pack .pack.b -expand yes -fill both
    update
    list [winfo geometry .pack.a] [winfo geometry .pack.b]
} -result {20x50+140+1 300x130+0+70}

test pack-3.22 {y padding and filling} -setup {
    pack forget .pack.a .pack.b .pack.c .pack.d
} -body {
    pack .pack.a -pady 1c
    set x [pack info .pack.a]
    set res1 [lindex $x [expr [lsearch -exact $x -pady]+1]]
    set res2 [winfo pixels .pack 1c]
    expr {$res1 eq $res2}
} -result 1
test pack-3.23 {y padding and filling} -setup {
    pack forget .pack.a .pack.b .pack.c .pack.d
} -body {
    pack .pack.a -ipady 1c
    set x [pack info .pack.a]
    set res1 [lindex $x [expr [lsearch -exact $x -ipady]+1]]
    set res2 [winfo pixels .pack 1c]
    expr {$res1 eq $res2}
} -result 1


test pack-4.1 {anchors} -setup {
    pack forget .pack.a .pack.b .pack.c .pack.d
} -body {
    pack .pack.a -side top -ipadx 5 -padx 10 -ipady 15 -pady 20 -expand y -anchor n
    update
    winfo geometry .pack.a
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
498
499
500
501
502
503
504

505
506
507
508
509
510
511







-







test pack-4.9 {anchors} -setup {
    pack forget .pack.a .pack.b .pack.c .pack.d
} -body {
    pack .pack.a -side top -ipadx 5 -padx 10 -ipady 15 -pady 20 -expand y -anchor center
    update
    winfo geometry .pack.a
} -result {30x70+135+65}


# Repeat above tests, but with a frame that isn't at (0,0), so that
# we can be sure that the frame offset is being added in correctly.

test pack-5.1 {more anchors} -setup {
    pack forget .pack.a .pack.b .pack.c .pack.d
} -body {
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
583
584
585
586
587
588
589

590
591
592
593
594
595
596







-







} -body {
    pack .pack.a -side  top
    pack .pack.c -side left
    pack .pack.b -side top -ipadx 5 -padx 10 -ipady 15 -pady 20 -expand y -anchor center
    update
    winfo geometry .pack.b
} -result {60x60+160+90}


test pack-6.1 {-expand option} -setup {
    pack forget .pack.a .pack.b .pack.c .pack.d
} -body {
    pack .pack.a .pack.b .pack.c .pack.d -side left
    update
    list [winfo geometry .pack.a] [winfo geometry .pack.b] \
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
689
690
691
692
693
694
695

696
697
698
699
700
701
702







-







    pack .pack.b -side top -expand yes -fill both
    pack .pack.c -side right -expand 1 -fill both
    pack .pack.d -side bottom -expand yes -fill both
    update
    list [winfo geometry .pack.a] [winfo geometry .pack.b] \
        [winfo geometry .pack.c] [winfo geometry .pack.d]
} -result {100x200+0+0 200x100+100+0 160x100+140+100 40x100+100+100}

test pack-6.12 {-expand option} -setup {
    toplevel .pack2 -height 400 -width 400
    wm geometry .pack2 +0+0
    pack propagate .pack2 0
    foreach i {w1 w2 w3} {
        frame .pack2.$i -width 30 -height 30 -bd 2 -relief raised
        label .pack2.$i.l -text $i
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
722
723
724
725
726
727
728

729
730
731
732
733
734
735







-







    pack .pack2.w1 .pack2.w2 .pack2.w3 -padx 5 -ipadx 4 -pady 2 \
        -ipady 6 -expand 1 -side top
    update
    list [winfo geometry .pack2.w1] [winfo geometry .pack2.w2] [winfo geometry .pack2.w3]
} -cleanup {
    destroy .pack2
} -result {38x42+181+45 38x42+181+178 38x42+181+312}


wm geometry .pack {}
test pack-7.1 {requesting size for parent} -setup {
    pack forget .pack.a .pack.b .pack.c .pack.d
} -body {
    pack .pack.a .pack.b .pack.c .pack.d -side left -padx 5 -pady 10
    update
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
780
781
782
783
784
785
786

787
788
789
790
791
792
793







-







} -body {
    pack .pack.a -side right
    pack .pack.c -side bottom
    pack .pack.d -side top
    update
    list [winfo reqwidth .pack] [winfo reqheight .pack]
} -result {100 110}


# For the tests below, create a couple of "pad" windows to shrink
# the available space for the remaining windows.  The tests have to
# be done this way rather than shrinking the whole window, because
# some window managers like mwm won't let a top-level window get
# very small.

868
869
870
871
872
873
874
875
876
877
878
879
880
881

882
883
884
885
886
887
888

889
890
891
892
893
894
895

896
897
898
899
900
901
902

903
904
905
906
907
908
909
910

911
912
913
914
915
916
917

918
919
920
921
922
923
924

925
926
927
928
929
930
931

932
933
934
935
936
937
938

939
940
941
942
943
944
945

946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966

967
968
969
970
971
972
973

974
975
976
977
978

979
980
981
982
983
984
985
986
987

988
989
990
991
992
993
994
995
996
997
998
999

1000
1001
1002
1003
1004
1005
1006
1007
861
862
863
864
865
866
867

868
869
870
871
872

873
874
875
876
877
878
879

880
881
882
883
884
885
886

887
888
889
890
891
892
893

894
895
896
897
898
899
900
901

902
903
904
905
906
907
908

909
910
911
912
913
914
915

916
917
918
919
920
921
922

923
924
925
926
927
928
929

930
931
932
933
934
935
936

937
938

939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956

957
958
959
960
961
962
963

964
965
966
967
968

969
970
971
972
973
974
975
976
977

978
979
980
981
982
983
984
985
986
987
988
989

990

991
992
993
994
995
996
997







-





-
+






-
+






-
+






-
+







-
+






-
+






-
+






-
+






-
+






-
+

-


















-
+






-
+




-
+








-
+











-
+
-







test pack-8.9 {insufficient space} -body {
    list [winfo geometry .pack.a] [winfo ismapped .pack.a] \
        [winfo geometry .pack.b] [winfo ismapped .pack.b] \
        [winfo geometry .pack.c] [winfo ismapped .pack.c]
} -result {20x40+0+20 1 50x30+100+25 1 80x80+20+0 1}
pack forget .pack.right .pack.bottom


test pack-9.1 {window ordering} -setup {
    pack forget .pack.a .pack.b .pack.c .pack.d
} -body {
    pack .pack.a .pack.b .pack.c .pack.d -side top
    pack .pack.a -after .pack.b
    pack slaves .pack
    pack content .pack
} -result {.pack.b .pack.a .pack.c .pack.d}
test pack-9.2 {window ordering} -setup {
    pack forget .pack.a .pack.b .pack.c .pack.d
} -body {
    pack .pack.a .pack.b .pack.c .pack.d -side top
    pack .pack.a -after .pack.a
    pack slaves .pack
    pack content .pack
} -result {.pack.a .pack.b .pack.c .pack.d}
test pack-9.3 {window ordering} -setup {
    pack forget .pack.a .pack.b .pack.c .pack.d
} -body {
    pack .pack.a .pack.b .pack.c .pack.d -side top
    pack .pack.a -before .pack.d
    pack slaves .pack
    pack content .pack
} -result {.pack.b .pack.c .pack.a .pack.d}
test pack-9.4 {window ordering} -setup {
    pack forget .pack.a .pack.b .pack.c .pack.d
} -body {
    pack .pack.a .pack.b .pack.c .pack.d -side top
    pack .pack.d -before .pack.a
    pack slaves .pack
    pack content .pack
} -result {.pack.d .pack.a .pack.b .pack.c}
test pack-9.5 {window ordering} -setup {
    pack forget .pack.a .pack.b .pack.c .pack.d
} -body {
    pack .pack.a .pack.b .pack.c .pack.d -side top
    pack propagate .pack.c 0
    pack .pack.a -in .pack.c
    list [pack slaves .pack] [pack slaves .pack.c]
    list [pack content .pack] [pack content .pack.c]
} -result {{.pack.b .pack.c .pack.d} .pack.a}
test pack-9.6 {window ordering} -setup {
    pack forget .pack.a .pack.b .pack.c .pack.d
} -body {
    pack .pack.a .pack.b .pack.c .pack.d -side top
    pack .pack.a -in .pack
    pack slaves .pack
    pack content .pack
} -result {.pack.b .pack.c .pack.d .pack.a}
test pack-9.7 {window ordering} -setup {
    pack forget .pack.a .pack.b .pack.c .pack.d
} -body {
    pack .pack.a .pack.b .pack.c .pack.d -side top
    pack .pack.a -padx 0
    pack slaves .pack
    pack content .pack
} -result {.pack.a .pack.b .pack.c .pack.d}
test pack-9.8 {window ordering} -setup {
    pack forget .pack.a .pack.b .pack.c .pack.d
} -body {
    pack .pack.a .pack.b .pack.c
    pack .pack.d
    pack slaves .pack
    pack content .pack
} -result {.pack.a .pack.b .pack.c .pack.d}
test pack-9.9 {window ordering} -setup {
    pack forget .pack.a .pack.b .pack.c .pack.d
} -body {
    pack .pack.a .pack.b .pack.c .pack.d
    pack .pack.b .pack.d .pack.c -before .pack.a
    pack slaves .pack
    pack content .pack
} -result {.pack.b .pack.d .pack.c .pack.a}
test pack-9.10 {window ordering} -setup {
    pack forget .pack.a .pack.b .pack.c .pack.d
} -body {
    pack .pack.a .pack.b .pack.c .pack.d
    pack .pack.a .pack.c .pack.d .pack.b -after .pack.a
    pack slaves .pack
    pack content .pack
} -result {.pack.a .pack.c .pack.d .pack.b}


test pack-10.1 {retaining/clearing configuration state} -setup {
    pack forget .pack.a .pack.b .pack.c .pack.d
} -body {
    pack .pack.a -side bottom -anchor n -padx 1 -pady 2 -ipadx 3 -ipady 4 \
    -fill both -expand 1
    pack forget .pack.a
    pack .pack.a
    pack info .pack.a
} -result {-in .pack -anchor center -expand 0 -fill none -ipadx 0 -ipady 0 -padx 0 -pady 0 -side top}
test pack-10.2 {retaining/clearing configuration state} -setup {
    pack forget .pack.a .pack.b .pack.c .pack.d
} -body {
    pack .pack.a -side bottom -anchor n -padx 1 -pady 2 -ipadx 3 -ipady 4 \
    -fill both -expand 1
    pack .pack.a -pady 14
    pack info .pack.a
} -result {-in .pack -anchor n -expand 1 -fill both -ipadx 3 -ipady 4 -padx 1 -pady 14 -side bottom}
test pack-10.3 {bad -in window does not change master} -setup {
test pack-10.3 {bad -in window does not change container window} -setup {
    pack forget .pack.a .pack.b .pack.c .pack.d
} -body {
    set result [list [winfo manager .pack.a]]
    catch {pack .pack.a -in .pack.a}
    lappend result [winfo manager .pack.a]
} -result {{} {}}
test pack-10.4 {bad -in window does not change master} -setup {
test pack-10.4 {bad -in window does not change container window} -setup {
    pack forget .pack.a .pack.b .pack.c .pack.d
} -body {
    winfo manager .pack.a
    pack .pack.a -in .pack.a
} -returnCodes error -result {can't pack .pack.a inside itself}
} -returnCodes error -result {can't pack ".pack.a" inside itself}
test pack-10.5 {prevent management loops} -body {
    frame .f1
    frame .f2
    pack .f1 -in .f2
    pack .f2 -in .f1
} -cleanup {
    destroy .f1
    destroy .f2
} -returnCodes error -result {can't put .f2 inside .f1, would cause management loop}
} -returnCodes error -result {can't put ".f2" inside ".f1": would cause management loop}
test pack-10.6 {prevent management loops} -body {
    frame .f1
    frame .f2
    frame .f3
    pack .f1 -in .f2
    pack .f2 -in .f3
    pack .f3 -in .f1
} -cleanup {
    destroy .f1
    destroy .f2
    destroy .f3
} -returnCodes error -result {can't put .f3 inside .f1, would cause management loop}
} -returnCodes error -result {can't put ".f3" inside ".f1": would cause management loop}


test pack-11.1 {info option} -setup {
    pack forget .pack.a .pack.b .pack.c .pack.d
} -body {
    pack .pack.a -in .pack
    set i [pack info .pack.a]
    lindex $i [expr [lsearch -exact $i -in]+1]
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150

1151
1152
1153
1154
1155
1156
1157
1119
1120
1121
1122
1123
1124
1125

1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138

1139
1140
1141
1142
1143
1144
1145
1146







-













-
+







    pack forget .pack.a .pack.b .pack.c .pack.d
} -body {
    pack .pack.a -side right
    set i [pack info .pack.a]
    lindex $i [expr [lsearch -exact $i -side]+1]
} -result right


test pack-12.1 {command options and errors} -body {
    pack
} -returnCodes error -result {wrong # args: should be "pack option arg ?arg ...?"}
test pack-12.2 {command options and errors} -body {
    pack foo
} -returnCodes error -result {wrong # args: should be "pack option arg ?arg ...?"}
test pack-12.3 {command options and errors} -body {
    pack configure x
} -returnCodes error -result {bad argument "x": must be name of window}
test pack-12.4 {command options and errors} -setup {
    pack forget .pack.a .pack.b .pack.c .pack.d
} -body {
    pack configure .pack.b .pack.c
    pack slaves .pack
    pack content .pack
} -result {.pack.b .pack.c}
test pack-12.5 {command options and errors} -setup {
    pack forget .pack.a .pack.b .pack.c .pack.d
} -body {
    pack .foo
} -returnCodes error -result {bad window path name ".foo"}
test pack-12.6 {command options and errors} -setup {
1290
1291
1292
1293
1294
1295
1296
1297

1298
1299
1300
1301
1302
1303

1304
1305
1306
1307
1308

1309
1310
1311
1312
1313
1314

1315
1316
1317
1318
1319
1320
1321
1279
1280
1281
1282
1283
1284
1285

1286
1287
1288
1289
1290
1291

1292
1293
1294
1295
1296

1297
1298
1299
1300
1301
1302

1303
1304
1305
1306
1307
1308
1309
1310







-
+





-
+




-
+





-
+







} -body {
    pack .pack.a ? 22
} -returnCodes error -result {bad option "?": must be -after, -anchor, -before, -expand, -fill, -in, -ipadx, -ipady, -padx, -pady, or -side}
test pack-12.33 {command options and errors} -setup {
    pack forget .pack.a .pack.b .pack.c .pack.d
} -body {
    pack .pack.a -in .
} -returnCodes error -result {can't pack .pack.a inside .}
} -returnCodes error -result {can't pack ".pack.a" inside "."}
test pack-12.34 {command options and errors} -setup {
    pack forget .pack.a .pack.b .pack.c .pack.d
} -body {
    frame .pack.a.a
    pack .pack.a.a -in .pack.b
} -returnCodes error -result {can't pack .pack.a.a inside .pack.b}
} -returnCodes error -result {can't pack ".pack.a.a" inside ".pack.b"}
test pack-12.35 {command options and errors} -setup {
    pack forget .pack.a .pack.b .pack.c .pack.d
} -body {
    pack .pack.a -in .pack.a
} -returnCodes error -result {can't pack .pack.a inside itself}
} -returnCodes error -result {can't pack ".pack.a" inside itself}
test pack-12.36 {command options and errors} -setup {
    pack forget .pack.a .pack.b .pack.c .pack.d
} -body {
    pack .pack.a .pack.b .pack.c .pack.d
    pack forget .pack.a .pack.d
    pack slaves .pack
    pack content .pack
} -result {.pack.b .pack.c}
test pack-12.37 {command options and errors} -setup {
    pack forget .pack.a .pack.b .pack.c .pack.d
} -body {
    .pack configure -width 300 -height 200
    pack propagate .pack 0
    pack .pack.a
1348
1349
1350
1351
1352
1353
1354
1355

1356
1357
1358
1359
1360
1361


1362
1363
1364
1365

1366
1367
1368
1369
1370

1371
1372
1373
1374
1375
1376

1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388

1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1337
1338
1339
1340
1341
1342
1343

1344
1345
1346
1347
1348


1349
1350
1351
1352
1353

1354
1355
1356
1357
1358

1359
1360
1361
1362
1363
1364

1365

1366
1367
1368
1369
1370
1371
1372
1373
1374
1375

1376
1377
1378

1379
1380
1381
1382
1383
1384
1385







-
+




-
-
+
+



-
+




-
+





-
+
-










-
+


-







    pack forget .pack.a .pack.b .pack.c .pack.d
} -body {
    pack propagate .pack foo bar
} -returnCodes error -result {wrong # args: should be "pack propagate window ?boolean?"}
test pack-12.42 {command options and errors} -setup {
    pack forget .pack.a .pack.b .pack.c .pack.d
} -body {
    pack slaves
    pack content
} -returnCodes error -result {wrong # args: should be "pack option arg ?arg ...?"}
test pack-12.43 {command options and errors} -setup {
    pack forget .pack.a .pack.b .pack.c .pack.d
} -body {
    pack slaves a b
} -returnCodes error -result {wrong # args: should be "pack slaves window"}
    pack content a b
} -returnCodes error -result {wrong # args: should be "pack content window"}
test pack-12.44 {command options and errors} -setup {
    pack forget .pack.a .pack.b .pack.c .pack.d
} -body {
    pack slaves .x
    pack content .x
} -returnCodes error -result {bad window path name ".x"}
test pack-12.45 {command options and errors} -setup {
    pack forget .pack.a .pack.b .pack.c .pack.d
} -body {
    pack slaves .pack.a
    pack content .pack.a
} -returnCodes ok -result {}
test pack-12.46 {command options and errors} -setup {
    pack forget .pack.a .pack.b .pack.c .pack.d
} -body {
    pack lousy .pack
} -returnCodes error -result {bad option "lousy": must be configure, forget, info, propagate, or slaves}
} -returnCodes error -result {bad option "lousy": must be configure, content, forget, info, or propagate}


test pack-13.1 {window deletion} -setup {
    pack forget .pack.a .pack.b .pack.c .pack.d .pack.right .pack.bottom
} -body {
    pack .pack.right -side right
    pack .pack.bottom -side bottom
    pack .pack.a .pack.d .pack.b .pack.c -side top
    update
    destroy .pack.d
    update
    set result [list [pack slaves .pack] [winfo geometry .pack.a] \
    set result [list [pack content .pack] [winfo geometry .pack.a] \
        [winfo geometry .pack.b] [winfo geometry .pack.c]]
} -result {{.pack.right .pack.bottom .pack.a .pack.b .pack.c} 20x40+30+0 50x30+15+40 80x80+0+70}


test pack-14.1 {respond to changes in expansion} -setup {
    pack forget .pack.a .pack.b .pack.c .pack.d .pack.right .pack.bottom
} -body {
    pack .pack.right -side right
    pack .pack.bottom -side bottom
    wm geom .pack {}
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531

1532
1533
1534
1535
1536
1537
1538
1539
1540

1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551



1552
1553
1554








1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572

1573
1574
1575
1576
1577
1578

1579
1580
1581
1582

1583
1584
1585


1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598

1599
1600
1601
1602
1603
1604

1605
1606
1607
1608

1609
1610
1611
1612
1613
1614

1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632

1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649























































































1650

1651
1652
1653
1654
1655
1656



1498
1499
1500
1501
1502
1503
1504

1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515


1516
1517
1518
1519
1520
1521
1522
1523
1524

1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539



1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550

1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563

1564
1565
1566

1567
1568

1569
1570
1571
1572

1573
1574
1575

1576
1577
1578
1579

1580
1581
1582
1583
1584
1585
1586
1587
1588

1589
1590
1591

1592
1593

1594
1595
1596
1597

1598
1599
1600
1601

1602

1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620

1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725

1726
1727
1728
1729
1730


1731
1732
1733







-











-
-
+








-
+











+
+
+
-
-
-
+
+
+
+
+
+
+
+



-













-
+


-


-
+



-
+


-
+
+


-









-
+


-


-
+



-
+



-

-
+

















-
+

















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+




-
-
+
+
+
    pack .pack.a -before .pack.b -side top
    update
    lappend result [winfo geometry .pack.b] [winfo ismapped .pack.b]
} -cleanup {
    destroy .pack.f1 .pack.f2
} -result {50x16+25+22 1 50x16+25+22 0}


test pack-16.1 {geometry manager name} -setup {
    pack forget .pack.a .pack.b .pack.c .pack.d
    set result {}
} -body {
    lappend result [winfo manager .pack.a]
    pack .pack.a
    lappend result [winfo manager .pack.a]
    pack forget .pack.a
    lappend result [winfo manager .pack.a]
} -result {{} pack {}}


test pack-17.1 {PackLostSlaveProc procedure} -setup {
test pack-17.1 {PackLostContentProc procedure} -setup {
    pack forget .pack.a .pack.b .pack.c .pack.d
} -body {
    pack .pack.a
    update
    place .pack.a -x 40 -y 10
    update
    list [winfo manager .pack.a] [winfo geometry .pack.a]
} -result {place 20x40+40+10}
test pack-17.2 {PackLostSlaveProc procedure} -setup {
test pack-17.2 {PackLostContentProc procedure} -setup {
    pack forget .pack.a .pack.b .pack.c .pack.d
} -body {
    pack .pack.a
    update
    place .pack.a -x 40 -y 10
    update
    winfo manager .pack.a
    winfo geometry .pack.a
    pack info .pack.a
} -returnCodes error -result {window ".pack.a" isn't packed}

if {[tk windowingsystem] ne "aqua"} {
    proc packUpdate {} {
	update

test pack-18.1 {unmap slaves when master unmapped} -constraints {
    tempNotPc
    }
} else {
    proc packUpdate {} {
    }
}

test pack-18.1 {unmap content when container unmapped} -constraints {
    tempNotPc failsOnUbuntu failsOnXQuarz
} -setup {
    eval destroy [winfo child .pack]
} -body {

    # adjust the position of .pack before test to avoid a screen switch
    # that occurs with window managers that have desktops four times as big
    # as the screen (screen switch causes scale and other tests to fail).

    wm geometry .pack +100+100

    # On the PC, when the width/height is configured while the window is
    # unmapped, the changes don't take effect until the window is remapped.
    # Who knows why?

    eval destroy [winfo child .pack]
    frame .pack.a -width 100 -height 50 -relief raised -bd 2
    pack .pack.a
    update
    update idletasks
    set result [winfo ismapped .pack.a]
    wm iconify .pack
    update
    lappend result [winfo ismapped .pack.a]
    .pack.a configure -width 200 -height 75
    update
    update idletasks
    lappend result [winfo width .pack.a ] [winfo height .pack.a] \
    [winfo ismapped .pack.a]
    wm deiconify .pack
    update
    packUpdate
    lappend result [winfo ismapped .pack.a]
} -result {1 0 200 75 0 1}
test pack-18.2 {unmap slaves when master unmapped} -setup {

test pack-18.2 {unmap content when container unmapped} -constraints {failsOnUbuntu failsOnXQuarz} -setup {
    eval destroy [winfo child .pack]
} -body {

    # adjust the position of .pack before test to avoid a screen switch
    # that occurs with window managers that have desktops four times as big
    # as the screen (screen switch causes scale and other tests to fail).

    wm geometry .pack +100+100
    frame .pack.a -relief raised -bd 2
    frame .pack.b -width 70 -height 30 -relief sunken -bd 2
    pack .pack.a
    pack .pack.b -in .pack.a
    update
    update idletasks
    set result [winfo ismapped .pack.b]
    wm iconify .pack
    update
    lappend result [winfo ismapped .pack.b]
    .pack.b configure -width 100 -height 30
    update
    update idletasks
    lappend result [winfo width .pack.b ] [winfo height .pack.b] \
    [winfo ismapped .pack.b]
    wm deiconify .pack
    update
    packUpdate
    lappend result [winfo ismapped .pack.b]
} -result {1 0 100 30 0 1}


test pack-19.1 {test respect for internalborder} -setup {
    catch {eval pack forget [pack slaves .pack]}
    catch {eval pack forget [pack content .pack]}
    destroy .pack.l .pack.lf
} -body {
    wm geometry .pack 200x200
    frame .pack.l -width 15 -height 10
    labelframe .pack.lf -labelwidget .pack.l
    pack .pack.lf -fill both -expand 1
    frame .pack.lf.f
    pack .pack.lf.f -fill both -expand 1
    update
    set res [list [winfo geometry .pack.lf.f]]
    .pack.lf configure -labelanchor e -padx 3 -pady 5
    update
    lappend res [winfo geometry .pack.lf.f]
} -cleanup {
    destroy .pack.l .pack.lf
} -result {196x188+2+10 177x186+5+7}
test pack-19.2 {test support for minreqsize} -setup {
    catch {eval pack forget [pack slaves .pack]}
    catch {eval pack forget [pack content .pack]}
    destroy .pack.l .pack.lf
} -body {
    wm geometry .pack {}
    frame .pack.l -width 150 -height 100
    labelframe .pack.lf -labelwidget .pack.l
    pack .pack.lf -fill both -expand 1
    frame .pack.lf.f -width 20 -height 25
    pack .pack.lf.f
    update
    set res [list [winfo geometry .pack.lf]]
    .pack.lf configure -labelanchor ws
    update
    lappend res [winfo geometry .pack.lf]
} -cleanup {
    destroy .pack.l .pack.lf
} -result {162x127+0+0 172x112+0+0}

test pack-20.1 {<<NoManagedChild>> fires on last pack forget} -setup {
    global A
    unset -nocomplain A
} -body {
    pack [frame .1]
    update
    bind . <<NoManagedChild>> {set A 1}
    pack forget .1
    update
    info exists A
} -cleanup {
    bind . <<NoManagedChild>> {}
    destroy .1
} -result 1
test pack-20.2 {<<NoManagedChild>> fires on last packed child destruction} -setup {
    global A
    unset -nocomplain A
} -body {
    pack [frame .1]
    update
    bind . <<NoManagedChild>> {incr A}
    destroy .1
    update
    set A
} -cleanup {
    bind . <<NoManagedChild>> {}
    destroy .1
} -result 1
test pack-20.3 {<Configure> does not fire on last pack forget} -setup {
    global A
    unset -nocomplain A
} -body {
    pack [frame .1]
    update
    bind . <Configure> {set A 1}
    pack forget .1
    update
    info exists A
} -cleanup {
    bind . <Configure> {}
    destroy .1
} -result 0
test pack-20.4 {<<NoManagedChild>> does not fire on forelast pack forget} -setup {
    global A
    unset -nocomplain A
} -body {
    pack [frame .1]
    pack [frame .2]
    update
    bind . <<NoManagedChild>> {set A 1}
    pack forget .1
    update
    info exists A
} -cleanup {
    bind . <<NoManagedChild>> {}
    destroy .1 .2
} -result 0
test pack-20.5 {<Configure> does not fire on last pack forget} -setup {
    global A
    unset -nocomplain A
} -body {
    pack [frame .1]
    pack [frame .2]
    update
    bind . <Configure> {set A 1}
    pack forget .1
    update
    info exists A
} -cleanup {
    bind . <Configure> {}
    destroy .1 .2
} -result 1
test pack-20.6 {<<NoManagedChild>> does not fire on last pack forget if propagation is off} -setup {
    global A
    unset -nocomplain A
} -body {
    pack [frame .1]
    pack propagate . 0
    update
    bind . <<NoManagedChild>> {set A 1}
    pack forget .1
    update
    info exists A
} -cleanup {
    bind . <<NoManagedChild>> {}
    destroy .1
} -result 0


# cleanup
cleanupTests
return



# Local Variables:
# mode: tcl
# End:
Changes to tests/packgrid.test.
1
2
3
4
5

6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21
22
23
24
25

26
27

28
29
30
31
32
33
34
35
36
37
38
39

40
41

42
43
44
45
46
47
48
49
50
51
52
53
54
55

56
57
58
59
60
61
62
63
64
65
66
67
68
69

70
71
72
73
74
75
76
77
78
79
80
81
82
83

84
85
86
87
88
89
90
91
92
93
94
95
96
97

98
99
100
101
102
103
104
105
106

107
108
109
110
111
112

113
114
115
116
117
118
119
120
121

122
123
124
125
126
127

128
129
130
131
132
133
134
135
136
137
138
139
140

141
142

143
144
145
146
147
148
149
150
151
152
153
154
155
156

157
158

159
160
161
162
163
164
165
166
167
168
169
170
171
172
173

174
175

176
177
178
179
180
181
182
183
184
185
186
187
188
189

190
191

192
193
194
195
196
197
198
199
200
201
202
203
204
205

206
207
208
209
210
211
212
213
214
215
216
217
218
219

220
221
222
223
224
225
226
227
228
229
230
231
232

233
234

235
236
237
238
239
240
241
242
243
244
245
246
247

248
249

250
251
252
253
254
255
256
257
258
259
260
261
262
263
264

265
266
267
268
269
270
271
1
2
3
4

5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
20
21
22
23
24

25
26

27
28
29
30
31
32
33
34
35
36
37
38

39
40

41
42
43
44
45
46
47
48
49
50
51
52
53
54

55
56
57
58
59
60
61
62
63
64
65
66
67
68

69
70
71
72
73
74
75
76
77
78
79
80
81
82

83
84
85
86
87
88
89
90
91
92
93
94
95
96

97
98
99
100
101
102
103
104
105

106
107
108
109
110
111

112
113
114
115
116
117
118
119
120

121
122
123
124
125
126

127
128
129
130
131
132
133
134
135
136
137
138
139

140
141

142
143
144
145
146
147
148
149
150
151
152
153
154
155

156
157

158
159
160
161
162
163
164
165
166
167
168
169
170
171
172

173
174

175
176
177
178
179
180
181
182
183
184
185
186
187
188

189
190

191
192
193
194
195
196
197
198
199
200
201
202
203
204

205
206
207
208
209
210
211
212
213
214
215
216
217
218

219
220
221
222
223
224
225
226
227
228
229
230
231

232
233

234
235
236
237
238
239
240
241
242
243
244
245
246

247
248

249
250
251
252
253
254
255
256
257
258
259
260
261
262
263

264
265
266
267
268
269
270
271




-
+







-
+











-
+

-
+











-
+

-
+













-
+













-
+













-
+













-
+








-
+





-
+








-
+





-
+












-
+

-
+













-
+

-
+














-
+

-
+













-
+

-
+













-
+













-
+












-
+

-
+












-
+

-
+














-
+







# This file is a Tcl script to test out interaction between Tk's "pack" and
# "grid" commands.
# It is organized in the standard fashion for Tcl tests.
#
# Copyright (c) 2008 Peter Spjuth
# Copyright © 2008 Peter Spjuth
# All rights reserved.

package require tcltest 2.2
eval tcltest::configure $argv
tcltest::loadTestedCommands
namespace import -force tcltest::*

test packgrid-1.1 {pack and grid in same master} -setup {
test packgrid-1.1 {pack and grid in same container window} -setup {
    grid propagate . true
    pack propagate . true
    label .p -text PACK
    label .g -text GRID
} -body {
    # Basic conflict
    grid .g
    pack .p
} -returnCodes error -cleanup {
    destroy .p
    destroy .g
} -result {cannot use geometry manager pack inside . which already has slaves managed by grid}
} -result {cannot use geometry manager pack inside . because grid is already managing it's content windows}

test packgrid-1.2 {pack and grid in same master} -setup {
test packgrid-1.2 {pack and grid in same container window} -setup {
    grid propagate . true
    pack propagate . true
    label .p -text PACK
    label .g -text GRID
} -body {
    # Basic conflict
    pack .p
    grid .g
} -returnCodes error -cleanup {
    destroy .p
    destroy .g
} -result {cannot use geometry manager grid inside . which already has slaves managed by pack}
} -result {cannot use geometry manager grid inside . because pack is already managing it's content windows}

test packgrid-1.3 {pack and grid in same master} -setup {
test packgrid-1.3 {pack and grid in same container window} -setup {
    grid propagate . false
    pack propagate . true
    label .p -text PACK
    label .g -text GRID
} -body {
    # Ok if one is non-propagating
    grid .g
    pack .p
} -cleanup {
    destroy .p
    destroy .g
} -result {}

test packgrid-1.4 {pack and grid in same master} -setup {
test packgrid-1.4 {pack and grid in same container window} -setup {
    grid propagate . false
    pack propagate . true
    label .p -text PACK
    label .g -text GRID
} -body {
    # Ok if one is non-propagating
    pack .p
    grid .g
} -cleanup {
    destroy .p
    destroy .g
} -result {}

test packgrid-1.5 {pack and grid in same master} -setup {
test packgrid-1.5 {pack and grid in same container window} -setup {
    grid propagate . true
    pack propagate . false
    label .p -text PACK
    label .g -text GRID
} -body {
    # Ok if one is non-propagating
    grid .g
    pack .p
} -cleanup {
    destroy .p
    destroy .g
} -result {}

test packgrid-1.6 {pack and grid in same master} -setup {
test packgrid-1.6 {pack and grid in same container window} -setup {
    grid propagate . true
    pack propagate . false
    label .p -text PACK
    label .g -text GRID
} -body {
    # Ok if one is non-propagating
    pack .p
    grid .g
} -cleanup {
    destroy .p
    destroy .g
} -result {}

test packgrid-1.7 {pack and grid in same master} -setup {
test packgrid-1.7 {pack and grid in same container window} -setup {
    grid propagate . true
    pack propagate . true
    label .p -text PACK
    label .g -text GRID
} -body {
    # Basic conflict should stop widget from being handled
    grid .g
    catch { pack .p }
    pack slaves .
    pack content .
} -cleanup {
    destroy .p
    destroy .g
} -result {}

test packgrid-1.8 {pack and grid in same master} -setup {
test packgrid-1.8 {pack and grid in same container window} -setup {
    grid propagate . true
    pack propagate . true
    label .p -text PACK
    label .g -text GRID
} -body {
    # Basic conflict should stop widget from being handled
    pack .p
    catch { grid .g }
    grid slaves .
    grid content .
} -cleanup {
    destroy .p
    destroy .g
} -result {}

test packgrid-2.1 {pack and grid in same master, change propagation} -setup {
test packgrid-2.1 {pack and grid in same container window, change propagation} -setup {
    grid propagate . false
    pack propagate . true
    label .p -text PACK
    label .g -text GRID
    pack .p
    grid .g
    update
} -body {
    grid propagate . true
} -returnCodes error -cleanup {
    destroy .p
    destroy .g
} -result {cannot use geometry manager grid inside . which already has slaves managed by pack}
} -result {cannot use geometry manager grid inside . because pack is already managing it's content windows}

test packgrid-2.2 {pack and grid in same master, change propagation} -setup {
test packgrid-2.2 {pack and grid in same container window, change propagation} -setup {
    grid propagate . true
    pack propagate . false
    label .p -text PACK
    label .g -text GRID
    pack .p
    grid .g
    update
} -body {
    pack propagate . true
} -returnCodes error -cleanup {
    destroy .p
    update
    destroy .g
} -result {cannot use geometry manager pack inside . which already has slaves managed by grid}
} -result {cannot use geometry manager pack inside . because grid is already managing it's content windows}

test packgrid-2.3 {pack and grid in same master, change propagation} -setup {
test packgrid-2.3 {pack and grid in same container window, change propagation} -setup {
    grid propagate . false
    pack propagate . false
    label .p -text PACK
    label .g -text GRID
    pack .p
    grid .g
    update
} -body {
    grid propagate . true
    update
    pack propagate . true
} -returnCodes error -cleanup {
    destroy .p
    destroy .g
} -result {cannot use geometry manager pack inside . which already has slaves managed by grid}
} -result {cannot use geometry manager pack inside . because grid is already managing it's content windows}

test packgrid-2.4 {pack and grid in same master, change propagation} -setup {
test packgrid-2.4 {pack and grid in same container window, change propagation} -setup {
    grid propagate . false
    pack propagate . false
    label .p -text PACK
    label .g -text GRID
    pack .p
    grid .g
    update
} -body {
    pack propagate . true
    grid propagate . true
} -returnCodes error -cleanup {
    destroy .p
    destroy .g
} -result {cannot use geometry manager grid inside . which already has slaves managed by pack}
} -result {cannot use geometry manager grid inside . because pack is already managing it's content windows}

test packgrid-3.1 {stealing slave} -setup {
test packgrid-3.1 {stealing content} -setup {
    grid propagate . true
    pack propagate . true
    label .p -text PACK
    label .g -text GRID
} -body {
    # Ok to steal if the other one is emptied
    grid .g
    pack .g
} -cleanup {
    destroy .p
    destroy .g
} -result {}

test packgrid-3.2 {stealing slave} -setup {
test packgrid-3.2 {stealing content} -setup {
    grid propagate . true
    pack propagate . true
    label .p -text PACK
    label .g -text GRID
} -body {
    # Ok to steal if the other one is emptied
    pack .g
    grid .g
} -cleanup {
    destroy .p
    destroy .g
} -result {}

test packgrid-3.3 {stealing slave} -setup {
test packgrid-3.3 {stealing content} -setup {
    grid propagate . true
    pack propagate . true
    label .p -text PACK
    label .g -text GRID
} -body {
    # Not ok to steal if the other one is not emptied
    grid .g
    grid .p
    pack .g
}  -returnCodes error -cleanup {
    destroy .p
    destroy .g
} -result {cannot use geometry manager pack inside . which already has slaves managed by grid}
} -result {cannot use geometry manager pack inside . because grid is already managing it's content windows}

test packgrid-3.4 {stealing slave} -setup {
test packgrid-3.4 {stealing content} -setup {
    grid propagate . true
    pack propagate . true
    label .p -text PACK
    label .g -text GRID
} -body {
    # Not ok to steal if the other one is not emptied
    pack .g
    pack .p
    grid .g
}  -returnCodes error -cleanup {
    destroy .p
    destroy .g
} -result {cannot use geometry manager grid inside . which already has slaves managed by pack}
} -result {cannot use geometry manager grid inside . because pack is already managing it's content windows}

test packgrid-4.1 {slave stolen after master destruction - bug [aa7679685e]} -setup {
test packgrid-4.1 {content stolen after container destruction - bug [aa7679685e]} -setup {
    frame .f
    button .b -text hello
} -body {
    pack .f
    grid .b -in .f
    destroy .f
    set res [winfo manager .b]
    # shall not crash
    pack .b
    set res
} -cleanup {
    destroy .b
} -result {}

test packgrid-4.2 {slave stolen after master destruction - bug [aa7679685e]} -setup {
test packgrid-4.2 {content stolen after container destruction - bug [aa7679685e]} -setup {
    frame .f
    button .b -text hello
} -body {
    pack .f
    pack .b -in .f
    destroy .f
    set res [winfo manager .b]
Changes to tests/panedwindow.test.
1
2
3
4
5
6



7
8
9
10
11
12
13
1
2
3



4
5
6
7
8
9
10
11
12
13



-
-
-
+
+
+







# This file is a Tcl script to test entry widgets in Tk.  It is
# organized in the standard fashion for Tcl tests.
#
# Copyright (c) 1994 The Regents of the University of California.
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1994 The Regents of the University of California.
# Copyright © 1994-1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
eval tcltest::configure $argv
tcltest::loadTestedCommands
namespace import -force tcltest::test

494
495
496
497
498
499
500
501

502
503
504
505
506
507
508
509
510
511
512
513
514

515
516
517
518
519
520
521
494
495
496
497
498
499
500

501
502
503
504
505
506
507
508
509
510
511
512
513

514
515
516
517
518
519
520
521







-
+












-
+







	deleteWindows
} -body {
    # There are no sashes until you have 2 panes
    panedwindow .p
    .p add [frame .p.f]
    list [catch {.p sash coord -1} msg] $msg \
	    [catch {.p sash coord  0} msg] $msg \
	    [catch {.p sash coord  1} msg] $msg 
	    [catch {.p sash coord  1} msg] $msg
} -cleanup {
	deleteWindows
} -result [list 1 "invalid sash index" 1 "invalid sash index" 1 "invalid sash index"]
test panedwindow-6.10 {sash coord subcommand, errors} -setup {
	deleteWindows
} -body {
    # There are no sashes until you have 2 panes
    panedwindow .p
    .p add [frame .p.f] [frame .p.f2]
    list [catch {.p sash coord -1} msg] $msg \
	    [catch {.p sash coord  0} msg] \
	    [catch {.p sash coord  1} msg] $msg \
	    [catch {.p sash coord  2} msg] $msg 
	    [catch {.p sash coord  2} msg] $msg
} -cleanup {
	deleteWindows
} -result [list 1 "invalid sash index" 0 1 "invalid sash index" 1 "invalid sash index"]


test panedwindow-7.1 {sash mark subcommand, errors} -setup {
	deleteWindows
618
619
620
621
622
623
624
625

626
627
628
629
630
631
632
618
619
620
621
622
623
624

625
626
627
628
629
630
631
632







-
+







} -body {
    panedwindow .p
    .p add [button .b] [button .c]
    .p sash dragto 0 0 bar
} -cleanup {
	deleteWindows
} -returnCodes error -result {expected integer but got "bar"}
    


test panedwindow-9.1 {sash mark/sash dragto interaction} -setup {
	deleteWindows
} -body {
    panedwindow .p -borderwidth 0 -sashpad 0 -sashwidth 4 -showhandle false
    .p add [frame .f -width 20 -height 20] [button .c -text foobar]
    .p sash mark 0 10 10
921
922
923
924
925
926
927
928

929
930
931
932
933
934
935
921
922
923
924
925
926
927

928
929
930
931
932
933
934
935







-
+







    update
    .p sash place 1 200 0
    update
    lappend result [winfo reqwidth .p]
} -cleanup {
	deleteWindows
} -result {68 100}
    


test panedwindow-12.1 {horizontal panedwindow lays out widgets properly} -setup {
	deleteWindows
    set result {}
} -body {
    panedwindow .p -showhandle false -borderwidth 2 -sashpad 2 -sashwidth 2
    foreach win {.p.f .p.f2 .p.f3} {.p add [frame $win -width 20 -height 10]}
1018
1019
1020
1021
1022
1023
1024
1025

1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036

1037
1038
1039
1040
1041
1042
1043
1018
1019
1020
1021
1022
1023
1024

1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035

1036
1037
1038
1039
1040
1041
1042
1043







-
+










-
+







    set result [list [winfo width .p.f]]
    .p.f configure -width 30
    update
    lappend result [winfo width .p.f]
} -cleanup {
	deleteWindows
} -result [list 20 20]
test panedwindow-12.7 {horizontal panedwindow reqheight is max slave height} -setup {
test panedwindow-12.7 {horizontal panedwindow reqheight is max pane height} -setup {
	deleteWindows
} -body {
    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4
    .p add [frame .p.f -width 20 -height 20] [frame .p.f2 -width 20 -height 20]
    set result [winfo reqheight .p]
    .p.f config -height 40
    lappend result [winfo reqheight .p]
} -cleanup {
	deleteWindows
} -result {20 40}
test panedwindow-12.8 {horizontal panedwindow reqheight is max slave height} -setup {
test panedwindow-12.8 {horizontal panedwindow reqheight is max pane height} -setup {
	deleteWindows
} -body {
    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4
    foreach win {.p.f .p.f2} {.p add [frame $win -width 20 -height 20]}
    .p paneconfigure .p.f -height 15
    set result [winfo reqheight .p]
    .p.f config -height 40
1083
1084
1085
1086
1087
1088
1089
1090

1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102

1103
1104
1105
1106
1107
1108
1109
1083
1084
1085
1086
1087
1088
1089

1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101

1102
1103
1104
1105
1106
1107
1108
1109







-
+











-
+







    set result [list [winfo height .p.f]]
    .p.f configure -height 30
    update
    lappend result [winfo height .p.f]
} -cleanup {
	deleteWindows
} -result [list 20 20]
test panedwindow-12.12 {vertical panedwindow reqwidth is max slave width} -setup {
test panedwindow-12.12 {vertical panedwindow reqwidth is max pane width} -setup {
	deleteWindows
} -body {
    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4 \
            -orient vertical
    .p add [frame .p.f -width 20 -height 20] [frame .p.f2 -width 20 -height 20]
    set result [winfo reqwidth .p]
    .p.f config -width 40
    lappend result [winfo reqwidth .p]
} -cleanup {
	deleteWindows
} -result {20 40}
test panedwindow-12.13 {vertical panedwindow reqwidth is max slave width} -setup {
test panedwindow-12.13 {vertical panedwindow reqwidth is max pane width} -setup {
	deleteWindows
} -body {
    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4 \
            -orient vertical
    foreach win {.p.f .p.f2} {.p add [frame $win -width 20 -height 20]}
    .p paneconfigure .p.f -width 15
    set result [winfo reqwidth .p]
1129
1130
1131
1132
1133
1134
1135
1136

1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147

1148
1149
1150
1151
1152


1153
1154
1155
1156
1157
1158
1159
1129
1130
1131
1132
1133
1134
1135

1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146

1147
1148
1149
1150


1151
1152
1153
1154
1155
1156
1157
1158
1159







-
+










-
+



-
-
+
+







} -result [list 10 10]


test panedwindow-13.1 {PanestructureProc, widget yields managements} -setup {
	deleteWindows
} -body {
    # Check that the panedwindow correctly yields geometry management of
    # a slave when the slave is destroyed.
    # a pane when the pane is destroyed.

    # This test should not cause a core dump, and it should not cause
    # a memory leak.
    panedwindow .p
    .p add [button .b]
    destroy .p
    pack .b
    destroy .b
    set result ""
} -result {}
test panedwindow-13.2 {PanedWindowLostSlaveProc, widget yields management} -setup {
test panedwindow-13.2 {PanedWindowLostPaneProc, widget yields management} -setup {
	deleteWindows
} -body {
    # Check that the paned window correctly yields geometry management of
    # a slave when some other geometry manager steals the slave from us.
    
    # a pane when some other geometry manager steals the pane from us.

    # This test should not cause a core dump, and it should not cause a
    # memory leak.
    panedwindow .p
    .p add [button .b]
    pack .p
    update
    pack .b
1514
1515
1516
1517
1518
1519
1520
1521

1522
1523

1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541

1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555

1556
1557
1558
1559
1560
1561

1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575

1576
1577
1578
1579
1580
1581

1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597

1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613

1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628

1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644

1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662


1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679


1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696

1697
1698

1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716

1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732

1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748

1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763

1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779

1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797


1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814


1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834

1835
1836

1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855

1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870

1871
1872
1873
1874
1875
1876

1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891

1892
1893
1894
1895
1896
1897

1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914

1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931

1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948

1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965

1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984


1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002


2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020

2021
2022

2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041

2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058

2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075

2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091

2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108

2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127


2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145


2146
2147
2148
2149
2150
2151
2152
1514
1515
1516
1517
1518
1519
1520

1521
1522

1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540

1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554

1555
1556
1557
1558
1559
1560

1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574

1575
1576
1577
1578
1579
1580

1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596

1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612

1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627

1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643

1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660


1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677


1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695

1696
1697

1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715

1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731

1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747

1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762

1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778

1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795


1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812


1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833

1834
1835

1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854

1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869

1870
1871
1872
1873
1874
1875

1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890

1891
1892
1893
1894
1895
1896

1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913

1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930

1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947

1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964

1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982


1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000


2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019

2020
2021

2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040

2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057

2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074

2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090

2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107

2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125


2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143


2144
2145
2146
2147
2148
2149
2150
2151
2152







-
+

-
+

















-
+













-
+





-
+













-
+





-
+















-
+















-
+














-
+















-
+
















-
-
+
+















-
-
+
+
















-
+

-
+

















-
+















-
+















-
+














-
+















-
+
















-
-
+
+















-
-
+
+



















-
+

-
+


















-
+














-
+





-
+














-
+





-
+
















-
+
















-
+
















-
+
















-
+

















-
-
+
+
















-
-
+
+

















-
+

-
+


















-
+
















-
+
















-
+















-
+
















-
+

















-
-
+
+
















-
-
+
+







    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
    foreach w {.f1 .f2} c {red blue} {
	    .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
    }

    # Get the requested width of the paned window
    lappend result [winfo reqwidth .p]
    

    .p sash place 0 30 0
    

    # Get the reqwidth again, to make sure it hasn't changed
    lappend result [winfo reqwidth .p]

    # Check that the sash moved
    lappend result [.p sash coord 0]
} -cleanup {
	deleteWindows
} -result [list 42 42 {30 0}]
test panedwindow-17.2 {MoveSash, move right (unmapped) clipped by reqwidth} -setup {
	deleteWindows
} -body {
    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
    foreach w {.f1 .f2} c {red blue} {
	    .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
    }

    .p sash place 0 100 0
    

    # Get the new sash coord; it should be clipped by the reqwidth of
    # the panedwindow.
    .p sash coord 0
} -cleanup {
	deleteWindows
} -result [list 40 0]
test panedwindow-17.3 {MoveSash, move right (mapped, width < reqwidth) clipped by width} -setup {
	deleteWindows
} -body {
    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
    foreach w {.f1 .f2} c {red blue} {
	    .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
    }
    

    # Put the panedwindow up on the display and give it a width < reqwidth
    place .p -x 0 -y 0 -width 32
    update

    .p sash place 0 100 0
    

    # Get the new sash coord; it should be clipped by the visible width of
    # the panedwindow.
    .p sash coord 0
} -cleanup {
	deleteWindows
} -result [list 30 0]
test panedwindow-17.4 {MoveSash, move right (mapped, width > reqwidth) clipped by width} -setup {
	deleteWindows
} -body {
    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
    foreach w {.f1 .f2} c {red blue} {
	    .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
    }
    

    # Put the panedwindow up on the display and give it a width > reqwidth
    place .p -x 0 -y 0 -width 102
    update

    .p sash place 0 200 0
    

    # Get the new sash coord; it should be clipped by the visible width of
    # the panedwindow.
    .p sash coord 0
} -cleanup {
	deleteWindows
} -result [list 100 0]
test panedwindow-17.5 {MoveSash, move right respects minsize} -setup {
	deleteWindows
} -body {
    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
    foreach w {.f1 .f2} c {red blue} {
	    .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10
    }

    .p sash place 0 100 0
    

    # Get the new sash coord; it should have moved as far as possible while
    # respecting minsizes.
    .p sash coord 0
} -cleanup {
	deleteWindows
} -result [list 30 0]
test panedwindow-17.6 {MoveSash, move right respects minsize} -setup {
	deleteWindows
} -body {
    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
    foreach w {.f1 .f2 .f3} c {red blue} {
	    .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10
    }

    .p sash place 0 100 0
    

    # Get the new sash coord; it should have moved as far as possible.
    .p sash coord 0
} -cleanup {
	deleteWindows
} -result [list 40 0]
test panedwindow-17.7 {MoveSash, move right pushes other sashes} -setup {
	deleteWindows
} -body {
    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
    foreach w {.f1 .f2 .f3} c {red blue} {
	    .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
    }

    .p sash place 0 100 0
    

    # Get the new sash coord; it should have moved as far as possible while
    # respecting minsizes.
    .p sash coord 1
} -cleanup {
	deleteWindows
} -result [list 62 0]
test panedwindow-17.8 {MoveSash, move right pushes other sashes, respects minsize} -setup {
	deleteWindows
} -body {
    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
    foreach w {.f1 .f2 .f3} c {red blue} {
	    .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10
    }

    .p sash place 0 100 0
    

    # Get the new sash coord; it should have moved as far as possible while
    # respecting minsizes.
    .p sash coord 1
} -cleanup {
	deleteWindows
} -result [list 52 0]
test panedwindow-17.9 {MoveSash, move right respects minsize, exludes pad} -setup {
	deleteWindows
} -body {
    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
    foreach w {.f1 .f2 .f3} c {red blue} {
	    .p add [frame $w -height 20 -width 20 -bg $c] \
		    -sticky nsew -minsize 10 -padx 5
    }

    .p sash place 0 100 0
    
    # Get the new sash coord; it should have moved as far as possible, 

    # Get the new sash coord; it should have moved as far as possible,
    # respecting minsizes.
    .p sash coord 0
} -cleanup {
	deleteWindows
} -result [list 50 0]
test panedwindow-17.10 {MoveSash, move right, negative minsize becomes 0} -setup {
	deleteWindows
} -body {
    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
    foreach w {.f1 .f2 .f3} c {red blue} {
	    .p add [frame $w -height 20 -width 20 -bg $c] \
		    -sticky nsew -minsize -50
    }

    .p sash place 0 50 0
    
    # Get the new sash coord; it should have moved as far as possible, 

    # Get the new sash coord; it should have moved as far as possible,
    # respecting minsizes.
    list [.p sash coord 0] [.p sash coord 1]
} -cleanup {
	deleteWindows
} -result [list [list 50 0] [list 52 0]]
test panedwindow-17.11 {MoveSash, move left} -setup {
	deleteWindows
} -body {
    set result {}
    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
    foreach w {.f1 .f2} c {red blue} {
	    .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
    }

    # Get the requested width of the paned window
    lappend result [winfo reqwidth .p]
    

    .p sash place 0 10 0
    

    # Get the reqwidth again, to make sure it hasn't changed
    lappend result [winfo reqwidth .p]

    # Check that the sash moved
    lappend result [.p sash coord 0]
} -cleanup {
	deleteWindows
} -result [list 42 42 {10 0}]
test panedwindow-17.12 {MoveSash, move left, can't move outside of window} -setup {
	deleteWindows
} -body {
    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
    foreach w {.f1 .f2} c {red blue} {
	    .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
    }

    .p sash place 0 -100 0
    

    # Get the new sash coord; it should be clipped by the reqwidth of
    # the panedwindow.
    .p sash coord 0
} -cleanup {
	deleteWindows
} -result [list 0 0]
test panedwindow-17.13 {MoveSash, move left respects minsize} -setup {
	deleteWindows
} -body {
    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
    foreach w {.f1 .f2} c {red blue} {
	    .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10
    }

    .p sash place 0 0 0
    

    # Get the new sash coord; it should have moved as far as possible while
    # respecting minsizes.
    .p sash coord 0
} -cleanup {
	deleteWindows
} -result [list 10 0]
test panedwindow-17.14 {MoveSash, move left respects minsize} -setup {
	deleteWindows
} -body {
    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
    foreach w {.f1 .f2 .f3} c {red blue} {
	    .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10
    }

    .p sash place 1 0 0
    

    # Get the new sash coord; it should have moved as far as possible.
    .p sash coord 1
} -cleanup {
	deleteWindows
} -result [list 22 0]
test panedwindow-17.15 {MoveSash, move left pushes other sashes} -setup {
	deleteWindows
} -body {
    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
    foreach w {.f1 .f2 .f3} c {red blue} {
	    .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
    }

    .p sash place 1 0 0
    

    # Get the new sash coord; it should have moved as far as possible while
    # respecting minsizes.
    .p sash coord 0
} -cleanup {
	deleteWindows
} -result [list 0 0]
test panedwindow-17.16 {MoveSash, move left pushes other sashes, respects minsize} -setup {
	deleteWindows
} -body {
    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
    foreach w {.f1 .f2 .f3} c {red blue} {
	    .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10
    }

    .p sash place 1 0 0
    

    # Get the new sash coord; it should have moved as far as possible while
    # respecting minsizes.
    .p sash coord 0
} -cleanup {
	deleteWindows
} -result [list 10 0]
test panedwindow-17.17 {MoveSash, move left respects minsize, exludes pad} -setup {
	deleteWindows
} -body {
    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
    foreach w {.f1 .f2 .f3} c {red blue} {
	    .p add [frame $w -height 20 -width 20 -bg $c] \
		    -sticky nsew -minsize 10 -padx 5
    }

    .p sash place 1 0 0
    
    # Get the new sash coord; it should have moved as far as possible, 

    # Get the new sash coord; it should have moved as far as possible,
    # respecting minsizes.
    .p sash coord 1
} -cleanup {
	deleteWindows
} -result [list 42 0]
test panedwindow-17.18 {MoveSash, move left, negative minsize becomes 0} -setup {
	deleteWindows
} -body {
    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
    foreach w {.f1 .f2 .f3} c {red blue green} {
	    .p add [frame $w -height 20 -width 20 -bg $c] \
		    -sticky nsew -minsize -50
    }

    .p sash place 1 10 0
    
    # Get the new sash coord; it should have moved as far as possible, 

    # Get the new sash coord; it should have moved as far as possible,
    # respecting minsizes.
    list [.p sash coord 0] [.p sash coord 1]
} -cleanup {
	deleteWindows
} -result [list [list 8 0] [list 10 0]]


test panedwindow-18.1 {MoveSash, move down} -setup {
	deleteWindows
} -body {
    set result {}
    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
            -orient vertical
    foreach w {.f1 .f2} c {red blue} {
	    .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
    }

    # Get the requested width of the paned window
    lappend result [winfo reqheight .p]
    

    .p sash place 0 0 30
    

    # Get the reqwidth again, to make sure it hasn't changed
    lappend result [winfo reqheight .p]

    # Check that the sash moved
    lappend result [.p sash coord 0]
} -cleanup {
	deleteWindows
} -result [list 42 42 {0 30}]
test panedwindow-18.2 {MoveSash, move down (unmapped) clipped by reqheight} -setup {
	deleteWindows
} -body {
    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
            -orient vertical
    foreach w {.f1 .f2} c {red blue} {
	    .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
    }

    .p sash place 0 0 100
    

    # Get the new sash coord; it should be clipped by the reqheight of
    # the panedwindow.
    .p sash coord 0
} -cleanup {
	deleteWindows
} -result [list 0 40]
test panedwindow-18.3 {MoveSash, move down (mapped, height < reqheight) clipped by height} -setup {
	deleteWindows
} -body {
    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
            -orient vertical
    foreach w {.f1 .f2} c {red blue} {
	    .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
    }
    

    # Put the panedwindow up on the display and give it a height < reqheight
    place .p -x 0 -y 0 -height 32
    update

    .p sash place 0 0 100
    

    # Get the new sash coord; it should be clipped by the visible height of
    # the panedwindow.
    .p sash coord 0
} -cleanup {
	deleteWindows
} -result [list 0 30]
test panedwindow-18.4 {MoveSash, move down (mapped, height > reqheight) clipped by height} -setup {
	deleteWindows
} -body {
    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
            -orient vertical
    foreach w {.f1 .f2} c {red blue} {
	    .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
    }
    

    # Put the panedwindow up on the display and give it a width > reqwidth
    place .p -x 0 -y 0 -height 102
    update

    .p sash place 0 0 200
    

    # Get the new sash coord; it should be clipped by the visible width of
    # the panedwindow.
    .p sash coord 0
} -cleanup {
	deleteWindows
} -result [list 0 100]
test panedwindow-18.5 {MoveSash, move down respects minsize} -setup {
	deleteWindows
} -body {
    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
            -orient vertical
    foreach w {.f1 .f2} c {red blue} {
	    .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10
    }

    .p sash place 0 0 100
    

    # Get the new sash coord; it should have moved as far as possible while
    # respecting minsizes.
    .p sash coord 0
} -cleanup {
	deleteWindows
} -result [list 0 30]
test panedwindow-18.6 {MoveSash, move down respects minsize} -setup {
	deleteWindows
} -body {
    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
            -orient vertical
    foreach w {.f1 .f2 .f3} c {red blue} {
	    .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10
    }

    .p sash place 0 0 100
    

    # Get the new sash coord; it should have moved as far as possible while
    # respecting minsizes.
    .p sash coord 0
} -cleanup {
	deleteWindows
} -result [list 0 40]
test panedwindow-18.7 {MoveSash, move down pushes other sashes} -setup {
	deleteWindows
} -body {
    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
            -orient vertical
    foreach w {.f1 .f2 .f3} c {red blue} {
	    .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
    }

    .p sash place 0 0 100
    

    # Get the new sash coord; it should have moved as far as possible while
    # respecting minsizes.
    .p sash coord 1
} -cleanup {
	deleteWindows
} -result [list 0 62]
test panedwindow-18.8 {MoveSash, move down pushes other sashes, respects minsize} -setup {
	deleteWindows
} -body {
    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
            -orient vertical
    foreach w {.f1 .f2 .f3} c {red blue} {
	    .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10
    }

    .p sash place 0 0 100
    

    # Get the new sash coord; it should have moved as far as possible while
    # respecting minsizes.
    .p sash coord 1
} -cleanup {
	deleteWindows
} -result [list 0 52]
test panedwindow-18.9 {MoveSash, move down respects minsize, exludes pad} -setup {
	deleteWindows
} -body {
    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
            -orient vertical
    foreach w {.f1 .f2 .f3} c {red blue} {
	    .p add [frame $w -height 20 -width 20 -bg $c] \
		    -sticky nsew -minsize 10 -pady 5
    }

    .p sash place 0 0 100
    
    # Get the new sash coord; it should have moved as far as possible, 

    # Get the new sash coord; it should have moved as far as possible,
    # respecting minsizes.
    .p sash coord 0
} -cleanup {
	deleteWindows
} -result [list 0 50]
test panedwindow-18.10 {MoveSash, move right, negative minsize becomes 0} -setup {
	deleteWindows
} -body {
    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
            -orient vertical
    foreach w {.f1 .f2 .f3} c {red blue} {
	    .p add [frame $w -height 20 -width 20 -bg $c] \
		    -sticky nsew -minsize -50
    }

    .p sash place 0 0 50
    
    # Get the new sash coord; it should have moved as far as possible, 

    # Get the new sash coord; it should have moved as far as possible,
    # respecting minsizes.
    list [.p sash coord 0] [.p sash coord 1]
} -cleanup {
	deleteWindows
} -result [list [list 0 50] [list 0 52]]
test panedwindow-18.11 {MoveSash, move up} -setup {
	deleteWindows
} -body {
    set result {}
    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
            -orient vertical
    foreach w {.f1 .f2} c {red blue} {
	    .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
    }

    # Get the requested width of the paned window
    lappend result [winfo reqheight .p]
    

    .p sash place 0 0 10
    

    # Get the reqwidth again, to make sure it hasn't changed
    lappend result [winfo reqheight .p]

    # Check that the sash moved
    lappend result [.p sash coord 0]
} -cleanup {
	deleteWindows
} -result [list 42 42 {0 10}]
test panedwindow-18.12 {MoveSash, move up, can't move outside of window} -setup {
	deleteWindows
} -body {
    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
            -orient vertical
    foreach w {.f1 .f2} c {red blue} {
	    .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
    }

    .p sash place 0 0 -100
    

    # Get the new sash coord; it should be clipped by the reqwidth of
    # the panedwindow.
    .p sash coord 0
} -cleanup {
	deleteWindows
} -result [list 0 0]
test panedwindow-18.13 {MoveSash, move up respects minsize} -setup {
	deleteWindows
} -body {
    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
            -orient vertical
    foreach w {.f1 .f2} c {red blue} {
	    .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10
    }

    .p sash place 0 0 0
    

    # Get the new sash coord; it should have moved as far as possible while
    # respecting minsizes.
    .p sash coord 0
} -cleanup {
	deleteWindows
} -result [list 0 10]
test panedwindow-18.14 {MoveSash, move up respects minsize} -setup {
	deleteWindows
} -body {
    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
            -orient vertical
    foreach w {.f1 .f2 .f3} c {red blue} {
	    .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10
    }

    .p sash place 1 0 0
    

    # Get the new sash coord; it should have moved as far as possible.
    .p sash coord 1
} -cleanup {
	deleteWindows
} -result [list 0 22]
test panedwindow-18.15 {MoveSash, move up pushes other sashes} -setup {
	deleteWindows
} -body {
    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
            -orient vertical
    foreach w {.f1 .f2 .f3} c {red blue} {
	    .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
    }

    .p sash place 1 0 0
    

    # Get the new sash coord; it should have moved as far as possible while
    # respecting minsizes.
    .p sash coord 0
} -cleanup {
	deleteWindows
} -result [list 0 0]
test panedwindow-18.16 {MoveSash, move up pushes other sashes, respects minsize} -setup {
	deleteWindows
} -body {
    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
            -orient vertical
    foreach w {.f1 .f2 .f3} c {red blue} {
	    .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10
    }

    .p sash place 1 0 0
    

    # Get the new sash coord; it should have moved as far as possible while
    # respecting minsizes.
    .p sash coord 0
} -cleanup {
	deleteWindows
} -result [list 0 10]
test panedwindow-18.17 {MoveSash, move up respects minsize, exludes pad} -setup {
	deleteWindows
} -body {
    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
            -orient vertical
    foreach w {.f1 .f2 .f3} c {red blue} {
	    .p add [frame $w -height 20 -width 20 -bg $c] \
		    -sticky nsew -minsize 10 -pady 5
    }

    .p sash place 1 0 0
    
    # Get the new sash coord; it should have moved as far as possible, 

    # Get the new sash coord; it should have moved as far as possible,
    # respecting minsizes.
    .p sash coord 1
} -cleanup {
	deleteWindows
} -result [list 0 42]
test panedwindow-18.18 {MoveSash, move up, negative minsize becomes 0} -setup {
	deleteWindows
} -body {
    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
            -orient vertical
    foreach w {.f1 .f2 .f3} c {red blue green} {
	    .p add [frame $w -height 20 -width 20 -bg $c] \
		    -sticky nsew -minsize -50
    }

    .p sash place 1 0 10
    
    # Get the new sash coord; it should have moved as far as possible, 

    # Get the new sash coord; it should have moved as far as possible,
    # respecting minsizes.
    list [.p sash coord 0] [.p sash coord 1]
} -cleanup {
	deleteWindows
} -result [list [list 0 8] [list 0 10]]


2237
2238
2239
2240
2241
2242
2243
2244

2245
2246
2247

2248
2249
2250
2251
2252
2253
2254
2237
2238
2239
2240
2241
2242
2243

2244
2245
2246

2247
2248
2249
2250
2251
2252
2253
2254







-
+


-
+







    set result [list [list [winfo reqwidth .p] [winfo reqheight .p]]]
    .p paneconfigure .f3 -width 40
    lappend result [list [winfo reqwidth .p] [winfo reqheight .p]]
} -cleanup {
	deleteWindows
} -result [list [list 60 60] [list 80 60]]

test panedwindow-19.7 {ComputeGeometry, one slave, reqsize set properly} -setup {
test panedwindow-19.7 {ComputeGeometry, one pane, reqsize set properly} -setup {
    deleteWindows
} -body {
    # With just one slave, sashpad and sashwidth should not
    # With just one pane, sashpad and sashwidth should not
    # affect the panedwindow's geometry, since no sash should
    # ever be drawn.
    panedwindow .p -borderwidth 0 -sashpad 0 \
        -sashwidth 0 -handlesize 6 -showhandle 0
    .p add [frame .p.f -width 20 -height 20 -bg red] -padx 0 -sticky ""
    list [winfo reqwidth .p] [winfo reqheight .p]
} -cleanup {
2278
2279
2280
2281
2282
2283
2284
2285

2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306

2307
2308
2309

2310
2311
2312
2313
2314
2315
2316
2278
2279
2280
2281
2282
2283
2284

2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305

2306
2307
2308

2309
2310
2311
2312
2313
2314
2315
2316







-
+




















-
+


-
+







                            -sticky ""
    }
    list [.p sash coord 0] [.p sash coord 1]
} -cleanup {
    deleteWindows
} -result {{20 0} {40 0}}

test panedwindow-19.10 {ComputeGeometry/ArrangePanes, slave coords} -setup {
test panedwindow-19.10 {ComputeGeometry/ArrangePanes, pane coords} -setup {
    deleteWindows
} -body {
    panedwindow .p -borderwidth 0 -sashpad 0 \
        -sashwidth 0 -handlesize 6 -showhandle 0
    foreach w {.p.f1 .p.f2 .p.f3} {
        .p add [frame $w -width 20 -height 20 -bg blue] \
            -sticky nsew -pady 3 -padx 11
    }
    pack .p
    update
    set result {}
    foreach w {.p.f1 .p.f2 .p.f3} {
        lappend result [list [winfo x $w] [winfo y $w] \
            [winfo width $w] [winfo height $w]]
    }
    return $result
} -cleanup {
    deleteWindows
} -result {{11 3 20 20} {53 3 20 20} {95 3 20 20}}

test panedwindow-19.11 {ComputeGeometry, one slave, vertical} -setup {
test panedwindow-19.11 {ComputeGeometry, one pane, vertical} -setup {
    deleteWindows
} -body {
    # With just one slave, sashpad and sashwidth should not
    # With just one pane, sashpad and sashwidth should not
    # affect the panedwindow's geometry, since no sash should
    # ever be drawn.
    panedwindow .p -borderwidth 0 -sashpad 0 \
        -orient vertical -sashwidth 0 -handlesize 6 \
        -showhandle 0
    .p add [frame .f -width 20 -height 20 -bg red] -pady 0 \
                    -sticky ""
2345
2346
2347
2348
2349
2350
2351
2352

2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373

2374
2375
2376

2377
2378
2379
2380
2381
2382
2383
2345
2346
2347
2348
2349
2350
2351

2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372

2373
2374
2375

2376
2377
2378
2379
2380
2381
2382
2383







-
+




















-
+


-
+







                            -sticky ""
    }
    list [.p sash coord 0] [.p sash coord 1]
} -cleanup {
    deleteWindows
} -result {{0 20} {0 40}}

test panedwindow-19.14 {ComputeGeometry/ArrangePanes, slave coords, vert} -setup {
test panedwindow-19.14 {ComputeGeometry/ArrangePanes, pane coords, vert} -setup {
    deleteWindows
} -body {
    panedwindow .p -borderwidth 0 -sashpad 0 \
        -sashwidth 0 -handlesize 6 -showhandle 0 \
        -orient vertical
    foreach w {.p.f1 .p.f2 .p.f3} {
        .p add [frame $w -width 20 -height 20 -bg blue] \
            -sticky nsew -pady 11 -padx 3
    }
    pack .p
    update
    set result {}
    foreach w {.p.f1 .p.f2 .p.f3} {
        lappend result [list [winfo x $w] [winfo y $w] \
            [winfo width $w] [winfo height $w]]
        }
    return $result
} -cleanup {
    deleteWindows
} -result {{3 11 20 20} {3 53 20 20} {3 95 20 20}}
test panedwindow-19.15 {ComputeGeometry, one slave, reqsize set properly} -setup {
test panedwindow-19.15 {ComputeGeometry, one pane, reqsize set properly} -setup {
    deleteWindows
} -body {
    # With just one slave, sashpad and sashwidth should not
    # With just one pane, sashpad and sashwidth should not
    # affect the panedwindow's geometry, since no sash should
    # ever be drawn.
    panedwindow .p -borderwidth 0 -sashpad 0 \
        -sashwidth 0 -handlesize 6 -showhandle 1
    .p add [frame .p.f -width 20 -height 20 -bg red] -padx 1 -sticky ""
    list [winfo reqwidth .p] [winfo reqheight .p]
} -cleanup {
2407
2408
2409
2410
2411
2412
2413
2414

2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435

2436
2437
2438

2439
2440
2441
2442
2443
2444
2445
2407
2408
2409
2410
2411
2412
2413

2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434

2435
2436
2437

2438
2439
2440
2441
2442
2443
2444
2445







-
+




















-
+


-
+







                            -sticky ""
    }
    list [.p sash coord 0] [.p sash coord 1]
} -cleanup {
    deleteWindows
} -result {{23 0} {49 0}}

test panedwindow-19.18 {ComputeGeometry/ArrangePanes, slave coords} -setup {
test panedwindow-19.18 {ComputeGeometry/ArrangePanes, pane coords} -setup {
    deleteWindows
} -body {
    panedwindow .p -borderwidth 0 -sashpad 0 \
        -sashwidth 0 -handlesize 6 -showhandle 1
    foreach w {.p.f1 .p.f2 .p.f3} {
        .p add [frame $w -width 20 -height 20 -bg blue] \
            -sticky nsew -pady 3 -padx 11
    }
    pack .p
    update
    set result {}
    foreach w {.p.f1 .p.f2 .p.f3} {
        lappend result [list [winfo x $w] [winfo y $w] \
            [winfo width $w] [winfo height $w]]
    }
    return $result
} -cleanup {
    deleteWindows
} -result {{11 3 20 20} {59 3 20 20} {107 3 20 20}}

test panedwindow-19.19 {ComputeGeometry, one slave, vertical} -setup {
test panedwindow-19.19 {ComputeGeometry, one pane, vertical} -setup {
    deleteWindows
} -body {
    # With just one slave, sashpad and sashwidth should not
    # With just one pane, sashpad and sashwidth should not
    # affect the panedwindow's geometry, since no sash should
    # ever be drawn.
    panedwindow .p -borderwidth 0 -sashpad 0 \
        -orient vertical -sashwidth 0 -handlesize 6 \
        -showhandle 1
    .p add [frame .f -width 20 -height 20 -bg red] -pady 1 \
                    -sticky ""
2474
2475
2476
2477
2478
2479
2480
2481

2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502

2503
2504
2505

2506
2507
2508
2509
2510
2511
2512
2474
2475
2476
2477
2478
2479
2480

2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501

2502
2503
2504

2505
2506
2507
2508
2509
2510
2511
2512







-
+




















-
+


-
+







                            -sticky ""
    }
    list [.p sash coord 0] [.p sash coord 1]
} -cleanup {
    deleteWindows
} -result {{0 23} {0 49}}

test panedwindow-19.22 {ComputeGeometry/ArrangePanes, slave coords, vert} -setup {
test panedwindow-19.22 {ComputeGeometry/ArrangePanes, pane coords, vert} -setup {
    deleteWindows
} -body {
    panedwindow .p -borderwidth 0 -sashpad 0 \
        -sashwidth 0 -handlesize 6 -showhandle 1 \
        -orient vertical
    foreach w {.p.f1 .p.f2 .p.f3} {
        .p add [frame $w -width 20 -height 20 -bg blue] \
            -sticky nsew -pady 11 -padx 3
    }
    pack .p
    update
    set result {}
    foreach w {.p.f1 .p.f2 .p.f3} {
        lappend result [list [winfo x $w] [winfo y $w] \
            [winfo width $w] [winfo height $w]]
        }
    return $result
} -cleanup {
    deleteWindows
} -result {{3 11 20 20} {3 59 20 20} {3 107 20 20}}
test panedwindow-19.23 {ComputeGeometry, one slave, reqsize set properly} -setup {
test panedwindow-19.23 {ComputeGeometry, one pane, reqsize set properly} -setup {
    deleteWindows
} -body {
    # With just one slave, sashpad and sashwidth should not
    # With just one pane, sashpad and sashwidth should not
    # affect the panedwindow's geometry, since no sash should
    # ever be drawn.
    panedwindow .p -borderwidth 0 -sashpad 0 \
        -sashwidth 3 -handlesize 6 -showhandle 0
    .p add [frame .p.f -width 20 -height 20 -bg red] -padx 0 -sticky ""
    list [winfo reqwidth .p] [winfo reqheight .p]
} -cleanup {
2536
2537
2538
2539
2540
2541
2542
2543

2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564

2565
2566
2567

2568
2569
2570
2571
2572
2573
2574
2536
2537
2538
2539
2540
2541
2542

2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563

2564
2565
2566

2567
2568
2569
2570
2571
2572
2573
2574







-
+




















-
+


-
+







                            -sticky ""
    }
    list [.p sash coord 0] [.p sash coord 1]
} -cleanup {
    deleteWindows
} -result {{20 0} {43 0}}

test panedwindow-19.26 {ComputeGeometry/ArrangePanes, slave coords} -setup {
test panedwindow-19.26 {ComputeGeometry/ArrangePanes, pane coords} -setup {
    deleteWindows
} -body {
    panedwindow .p -borderwidth 0 -sashpad 0 \
        -sashwidth 3 -handlesize 6 -showhandle 0
    foreach w {.p.f1 .p.f2 .p.f3} {
        .p add [frame $w -width 20 -height 20 -bg blue] \
            -sticky nsew -pady 3 -padx 11
    }
    pack .p
    update
    set result {}
    foreach w {.p.f1 .p.f2 .p.f3} {
        lappend result [list [winfo x $w] [winfo y $w] \
            [winfo width $w] [winfo height $w]]
    }
    return $result
} -cleanup {
    deleteWindows
} -result {{11 3 20 20} {56 3 20 20} {101 3 20 20}}

test panedwindow-19.27 {ComputeGeometry, one slave, vertical} -setup {
test panedwindow-19.27 {ComputeGeometry, one pane, vertical} -setup {
    deleteWindows
} -body {
    # With just one slave, sashpad and sashwidth should not
    # With just one pane, sashpad and sashwidth should not
    # affect the panedwindow's geometry, since no sash should
    # ever be drawn.
    panedwindow .p -borderwidth 0 -sashpad 0 \
        -orient vertical -sashwidth 3 -handlesize 6 \
        -showhandle 0
    .p add [frame .f -width 20 -height 20 -bg red] -pady 0 \
                    -sticky ""
2603
2604
2605
2606
2607
2608
2609
2610

2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631

2632
2633
2634

2635
2636
2637
2638
2639
2640
2641
2603
2604
2605
2606
2607
2608
2609

2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630

2631
2632
2633

2634
2635
2636
2637
2638
2639
2640
2641







-
+




















-
+


-
+







                            -sticky ""
    }
    list [.p sash coord 0] [.p sash coord 1]
} -cleanup {
    deleteWindows
} -result {{0 20} {0 43}}

test panedwindow-19.30 {ComputeGeometry/ArrangePanes, slave coords, vert} -setup {
test panedwindow-19.30 {ComputeGeometry/ArrangePanes, pane coords, vert} -setup {
    deleteWindows
} -body {
    panedwindow .p -borderwidth 0 -sashpad 0 \
        -sashwidth 3 -handlesize 6 -showhandle 0 \
        -orient vertical
    foreach w {.p.f1 .p.f2 .p.f3} {
        .p add [frame $w -width 20 -height 20 -bg blue] \
            -sticky nsew -pady 11 -padx 3
    }
    pack .p
    update
    set result {}
    foreach w {.p.f1 .p.f2 .p.f3} {
        lappend result [list [winfo x $w] [winfo y $w] \
            [winfo width $w] [winfo height $w]]
        }
    return $result
} -cleanup {
    deleteWindows
} -result {{3 11 20 20} {3 56 20 20} {3 101 20 20}}
test panedwindow-19.31 {ComputeGeometry, one slave, reqsize set properly} -setup {
test panedwindow-19.31 {ComputeGeometry, one pane, reqsize set properly} -setup {
    deleteWindows
} -body {
    # With just one slave, sashpad and sashwidth should not
    # With just one pane, sashpad and sashwidth should not
    # affect the panedwindow's geometry, since no sash should
    # ever be drawn.
    panedwindow .p -borderwidth 0 -sashpad 0 \
        -sashwidth 3 -handlesize 6 -showhandle 1
    .p add [frame .p.f -width 20 -height 20 -bg red] -padx 1 -sticky ""
    list [winfo reqwidth .p] [winfo reqheight .p]
} -cleanup {
2665
2666
2667
2668
2669
2670
2671
2672

2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693

2694
2695
2696

2697
2698
2699
2700
2701
2702
2703
2665
2666
2667
2668
2669
2670
2671

2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692

2693
2694
2695

2696
2697
2698
2699
2700
2701
2702
2703







-
+




















-
+


-
+







                            -sticky ""
    }
    list [.p sash coord 0] [.p sash coord 1]
} -cleanup {
    deleteWindows
} -result {{21 0} {47 0}}

test panedwindow-19.34 {ComputeGeometry/ArrangePanes, slave coords} -setup {
test panedwindow-19.34 {ComputeGeometry/ArrangePanes, pane coords} -setup {
    deleteWindows
} -body {
    panedwindow .p -borderwidth 0 -sashpad 0 \
        -sashwidth 3 -handlesize 6 -showhandle 1
    foreach w {.p.f1 .p.f2 .p.f3} {
        .p add [frame $w -width 20 -height 20 -bg blue] \
            -sticky nsew -pady 3 -padx 11
    }
    pack .p
    update
    set result {}
    foreach w {.p.f1 .p.f2 .p.f3} {
        lappend result [list [winfo x $w] [winfo y $w] \
            [winfo width $w] [winfo height $w]]
    }
    return $result
} -cleanup {
    deleteWindows
} -result {{11 3 20 20} {59 3 20 20} {107 3 20 20}}

test panedwindow-19.35 {ComputeGeometry, one slave, vertical} -setup {
test panedwindow-19.35 {ComputeGeometry, one pane, vertical} -setup {
    deleteWindows
} -body {
    # With just one slave, sashpad and sashwidth should not
    # With just one pane, sashpad and sashwidth should not
    # affect the panedwindow's geometry, since no sash should
    # ever be drawn.
    panedwindow .p -borderwidth 0 -sashpad 0 \
        -orient vertical -sashwidth 3 -handlesize 6 \
        -showhandle 1
    .p add [frame .f -width 20 -height 20 -bg red] -pady 1 \
                    -sticky ""
2732
2733
2734
2735
2736
2737
2738
2739

2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760

2761
2762
2763

2764
2765
2766
2767
2768
2769
2770
2732
2733
2734
2735
2736
2737
2738

2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759

2760
2761
2762

2763
2764
2765
2766
2767
2768
2769
2770







-
+




















-
+


-
+







                            -sticky ""
    }
    list [.p sash coord 0] [.p sash coord 1]
} -cleanup {
    deleteWindows
} -result {{0 21} {0 47}}

test panedwindow-19.38 {ComputeGeometry/ArrangePanes, slave coords, vert} -setup {
test panedwindow-19.38 {ComputeGeometry/ArrangePanes, pane coords, vert} -setup {
    deleteWindows
} -body {
    panedwindow .p -borderwidth 0 -sashpad 0 \
        -sashwidth 3 -handlesize 6 -showhandle 1 \
        -orient vertical
    foreach w {.p.f1 .p.f2 .p.f3} {
        .p add [frame $w -width 20 -height 20 -bg blue] \
            -sticky nsew -pady 11 -padx 3
    }
    pack .p
    update
    set result {}
    foreach w {.p.f1 .p.f2 .p.f3} {
        lappend result [list [winfo x $w] [winfo y $w] \
            [winfo width $w] [winfo height $w]]
        }
    return $result
} -cleanup {
    deleteWindows
} -result {{3 11 20 20} {3 59 20 20} {3 107 20 20}}
test panedwindow-19.39 {ComputeGeometry, one slave, reqsize set properly} -setup {
test panedwindow-19.39 {ComputeGeometry, one pane, reqsize set properly} -setup {
    deleteWindows
} -body {
    # With just one slave, sashpad and sashwidth should not
    # With just one pane, sashpad and sashwidth should not
    # affect the panedwindow's geometry, since no sash should
    # ever be drawn.
    panedwindow .p -borderwidth 0 -sashpad 5 \
        -sashwidth 0 -handlesize 6 -showhandle 0
    .p add [frame .p.f -width 20 -height 20 -bg red] -padx 0 -sticky ""
    list [winfo reqwidth .p] [winfo reqheight .p]
} -cleanup {
2794
2795
2796
2797
2798
2799
2800
2801

2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822

2823
2824
2825

2826
2827
2828
2829
2830
2831
2832
2794
2795
2796
2797
2798
2799
2800

2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821

2822
2823
2824

2825
2826
2827
2828
2829
2830
2831
2832







-
+




















-
+


-
+







                            -sticky ""
    }
    list [.p sash coord 0] [.p sash coord 1]
} -cleanup {
    deleteWindows
} -result {{25 0} {55 0}}

test panedwindow-19.42 {ComputeGeometry/ArrangePanes, slave coords} -setup {
test panedwindow-19.42 {ComputeGeometry/ArrangePanes, pane coords} -setup {
    deleteWindows
} -body {
    panedwindow .p -borderwidth 0 -sashpad 5 \
        -sashwidth 0 -handlesize 6 -showhandle 0
    foreach w {.p.f1 .p.f2 .p.f3} {
        .p add [frame $w -width 20 -height 20 -bg blue] \
            -sticky nsew -pady 3 -padx 11
    }
    pack .p
    update
    set result {}
    foreach w {.p.f1 .p.f2 .p.f3} {
        lappend result [list [winfo x $w] [winfo y $w] \
            [winfo width $w] [winfo height $w]]
    }
    return $result
} -cleanup {
    deleteWindows
} -result {{11 3 20 20} {63 3 20 20} {115 3 20 20}}

test panedwindow-19.43 {ComputeGeometry, one slave, vertical} -setup {
test panedwindow-19.43 {ComputeGeometry, one pane, vertical} -setup {
    deleteWindows
} -body {
    # With just one slave, sashpad and sashwidth should not
    # With just one pane, sashpad and sashwidth should not
    # affect the panedwindow's geometry, since no sash should
    # ever be drawn.
    panedwindow .p -borderwidth 0 -sashpad 5 \
        -orient vertical -sashwidth 0 -handlesize 6 \
        -showhandle 0
    .p add [frame .f -width 20 -height 20 -bg red] -pady 0 \
                    -sticky ""
2861
2862
2863
2864
2865
2866
2867
2868

2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889

2890
2891
2892

2893
2894
2895
2896
2897
2898
2899
2861
2862
2863
2864
2865
2866
2867

2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888

2889
2890
2891

2892
2893
2894
2895
2896
2897
2898
2899







-
+




















-
+


-
+







                            -sticky ""
    }
    list [.p sash coord 0] [.p sash coord 1]
} -cleanup {
    deleteWindows
} -result {{0 25} {0 55}}

test panedwindow-19.46 {ComputeGeometry/ArrangePanes, slave coords, vert} -setup {
test panedwindow-19.46 {ComputeGeometry/ArrangePanes, pane coords, vert} -setup {
    deleteWindows
} -body {
    panedwindow .p -borderwidth 0 -sashpad 5 \
        -sashwidth 0 -handlesize 6 -showhandle 0 \
        -orient vertical
    foreach w {.p.f1 .p.f2 .p.f3} {
        .p add [frame $w -width 20 -height 20 -bg blue] \
            -sticky nsew -pady 11 -padx 3
    }
    pack .p
    update
    set result {}
    foreach w {.p.f1 .p.f2 .p.f3} {
        lappend result [list [winfo x $w] [winfo y $w] \
            [winfo width $w] [winfo height $w]]
        }
    return $result
} -cleanup {
    deleteWindows
} -result {{3 11 20 20} {3 63 20 20} {3 115 20 20}}
test panedwindow-19.47 {ComputeGeometry, one slave, reqsize set properly} -setup {
test panedwindow-19.47 {ComputeGeometry, one pane, reqsize set properly} -setup {
    deleteWindows
} -body {
    # With just one slave, sashpad and sashwidth should not
    # With just one pane, sashpad and sashwidth should not
    # affect the panedwindow's geometry, since no sash should
    # ever be drawn.
    panedwindow .p -borderwidth 0 -sashpad 5 \
        -sashwidth 0 -handlesize 6 -showhandle 1
    .p add [frame .p.f -width 20 -height 20 -bg red] -padx 1 -sticky ""
    list [winfo reqwidth .p] [winfo reqheight .p]
} -cleanup {
2923
2924
2925
2926
2927
2928
2929
2930

2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951

2952
2953
2954

2955
2956
2957
2958
2959
2960
2961
2923
2924
2925
2926
2927
2928
2929

2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950

2951
2952
2953

2954
2955
2956
2957
2958
2959
2960
2961







-
+




















-
+


-
+







                            -sticky ""
    }
    list [.p sash coord 0] [.p sash coord 1]
} -cleanup {
    deleteWindows
} -result {{28 0} {64 0}}

test panedwindow-19.50 {ComputeGeometry/ArrangePanes, slave coords} -setup {
test panedwindow-19.50 {ComputeGeometry/ArrangePanes, pane coords} -setup {
    deleteWindows
} -body {
    panedwindow .p -borderwidth 0 -sashpad 5 \
        -sashwidth 0 -handlesize 6 -showhandle 1
    foreach w {.p.f1 .p.f2 .p.f3} {
        .p add [frame $w -width 20 -height 20 -bg blue] \
            -sticky nsew -pady 3 -padx 11
    }
    pack .p
    update
    set result {}
    foreach w {.p.f1 .p.f2 .p.f3} {
        lappend result [list [winfo x $w] [winfo y $w] \
            [winfo width $w] [winfo height $w]]
    }
    return $result
} -cleanup {
    deleteWindows
} -result {{11 3 20 20} {69 3 20 20} {127 3 20 20}}

test panedwindow-19.51 {ComputeGeometry, one slave, vertical} -setup {
test panedwindow-19.51 {ComputeGeometry, one pane, vertical} -setup {
    deleteWindows
} -body {
    # With just one slave, sashpad and sashwidth should not
    # With just one pane, sashpad and sashwidth should not
    # affect the panedwindow's geometry, since no sash should
    # ever be drawn.
    panedwindow .p -borderwidth 0 -sashpad 5 \
        -orient vertical -sashwidth 0 -handlesize 6 \
        -showhandle 1
    .p add [frame .f -width 20 -height 20 -bg red] -pady 1 \
                    -sticky ""
2990
2991
2992
2993
2994
2995
2996
2997

2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018

3019
3020
3021

3022
3023
3024
3025
3026
3027
3028
2990
2991
2992
2993
2994
2995
2996

2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017

3018
3019
3020

3021
3022
3023
3024
3025
3026
3027
3028







-
+




















-
+


-
+







                            -sticky ""
    }
    list [.p sash coord 0] [.p sash coord 1]
} -cleanup {
    deleteWindows
} -result {{0 28} {0 64}}

test panedwindow-19.54 {ComputeGeometry/ArrangePanes, slave coords, vert} -setup {
test panedwindow-19.54 {ComputeGeometry/ArrangePanes, pane coords, vert} -setup {
    deleteWindows
} -body {
    panedwindow .p -borderwidth 0 -sashpad 5 \
        -sashwidth 0 -handlesize 6 -showhandle 1 \
        -orient vertical
    foreach w {.p.f1 .p.f2 .p.f3} {
        .p add [frame $w -width 20 -height 20 -bg blue] \
            -sticky nsew -pady 11 -padx 3
    }
    pack .p
    update
    set result {}
    foreach w {.p.f1 .p.f2 .p.f3} {
        lappend result [list [winfo x $w] [winfo y $w] \
            [winfo width $w] [winfo height $w]]
        }
    return $result
} -cleanup {
    deleteWindows
} -result {{3 11 20 20} {3 69 20 20} {3 127 20 20}}
test panedwindow-19.55 {ComputeGeometry, one slave, reqsize set properly} -setup {
test panedwindow-19.55 {ComputeGeometry, one pane, reqsize set properly} -setup {
    deleteWindows
} -body {
    # With just one slave, sashpad and sashwidth should not
    # With just one pane, sashpad and sashwidth should not
    # affect the panedwindow's geometry, since no sash should
    # ever be drawn.
    panedwindow .p -borderwidth 0 -sashpad 5 \
        -sashwidth 3 -handlesize 6 -showhandle 0
    .p add [frame .p.f -width 20 -height 20 -bg red] -padx 0 -sticky ""
    list [winfo reqwidth .p] [winfo reqheight .p]
} -cleanup {
3052
3053
3054
3055
3056
3057
3058
3059

3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080

3081
3082
3083

3084
3085
3086
3087
3088
3089
3090
3052
3053
3054
3055
3056
3057
3058

3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079

3080
3081
3082

3083
3084
3085
3086
3087
3088
3089
3090







-
+




















-
+


-
+







                            -sticky ""
    }
    list [.p sash coord 0] [.p sash coord 1]
} -cleanup {
    deleteWindows
} -result {{25 0} {58 0}}

test panedwindow-19.58 {ComputeGeometry/ArrangePanes, slave coords} -setup {
test panedwindow-19.58 {ComputeGeometry/ArrangePanes, pane coords} -setup {
    deleteWindows
} -body {
    panedwindow .p -borderwidth 0 -sashpad 5 \
        -sashwidth 3 -handlesize 6 -showhandle 0
    foreach w {.p.f1 .p.f2 .p.f3} {
        .p add [frame $w -width 20 -height 20 -bg blue] \
            -sticky nsew -pady 3 -padx 11
    }
    pack .p
    update
    set result {}
    foreach w {.p.f1 .p.f2 .p.f3} {
        lappend result [list [winfo x $w] [winfo y $w] \
            [winfo width $w] [winfo height $w]]
    }
    return $result
} -cleanup {
    deleteWindows
} -result {{11 3 20 20} {66 3 20 20} {121 3 20 20}}

test panedwindow-19.59 {ComputeGeometry, one slave, vertical} -setup {
test panedwindow-19.59 {ComputeGeometry, one pane, vertical} -setup {
    deleteWindows
} -body {
    # With just one slave, sashpad and sashwidth should not
    # With just one pane, sashpad and sashwidth should not
    # affect the panedwindow's geometry, since no sash should
    # ever be drawn.
    panedwindow .p -borderwidth 0 -sashpad 5 \
        -orient vertical -sashwidth 3 -handlesize 6 \
        -showhandle 0
    .p add [frame .f -width 20 -height 20 -bg red] -pady 0 \
                    -sticky ""
3119
3120
3121
3122
3123
3124
3125
3126

3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147

3148
3149
3150

3151
3152
3153
3154
3155
3156
3157
3119
3120
3121
3122
3123
3124
3125

3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146

3147
3148
3149

3150
3151
3152
3153
3154
3155
3156
3157







-
+




















-
+


-
+







                            -sticky ""
    }
    list [.p sash coord 0] [.p sash coord 1]
} -cleanup {
    deleteWindows
} -result {{0 25} {0 58}}

test panedwindow-19.62 {ComputeGeometry/ArrangePanes, slave coords, vert} -setup {
test panedwindow-19.62 {ComputeGeometry/ArrangePanes, pane coords, vert} -setup {
    deleteWindows
} -body {
    panedwindow .p -borderwidth 0 -sashpad 5 \
        -sashwidth 3 -handlesize 6 -showhandle 0 \
        -orient vertical
    foreach w {.p.f1 .p.f2 .p.f3} {
        .p add [frame $w -width 20 -height 20 -bg blue] \
            -sticky nsew -pady 11 -padx 3
    }
    pack .p
    update
    set result {}
    foreach w {.p.f1 .p.f2 .p.f3} {
        lappend result [list [winfo x $w] [winfo y $w] \
            [winfo width $w] [winfo height $w]]
        }
    return $result
} -cleanup {
    deleteWindows
} -result {{3 11 20 20} {3 66 20 20} {3 121 20 20}}
test panedwindow-19.63 {ComputeGeometry, one slave, reqsize set properly} -setup {
test panedwindow-19.63 {ComputeGeometry, one pane, reqsize set properly} -setup {
    deleteWindows
} -body {
    # With just one slave, sashpad and sashwidth should not
    # With just one pane, sashpad and sashwidth should not
    # affect the panedwindow's geometry, since no sash should
    # ever be drawn.
    panedwindow .p -borderwidth 0 -sashpad 5 \
        -sashwidth 3 -handlesize 6 -showhandle 1
    .p add [frame .p.f -width 20 -height 20 -bg red] -padx 1 -sticky ""
    list [winfo reqwidth .p] [winfo reqheight .p]
} -cleanup {
3181
3182
3183
3184
3185
3186
3187
3188

3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209

3210
3211
3212

3213
3214
3215
3216
3217
3218
3219
3181
3182
3183
3184
3185
3186
3187

3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208

3209
3210
3211

3212
3213
3214
3215
3216
3217
3218
3219







-
+




















-
+


-
+







                            -sticky ""
    }
    list [.p sash coord 0] [.p sash coord 1]
} -cleanup {
    deleteWindows
} -result {{26 0} {62 0}}

test panedwindow-19.66 {ComputeGeometry/ArrangePanes, slave coords} -setup {
test panedwindow-19.66 {ComputeGeometry/ArrangePanes, pane coords} -setup {
    deleteWindows
} -body {
    panedwindow .p -borderwidth 0 -sashpad 5 \
        -sashwidth 3 -handlesize 6 -showhandle 1
    foreach w {.p.f1 .p.f2 .p.f3} {
        .p add [frame $w -width 20 -height 20 -bg blue] \
            -sticky nsew -pady 3 -padx 11
    }
    pack .p
    update
    set result {}
    foreach w {.p.f1 .p.f2 .p.f3} {
        lappend result [list [winfo x $w] [winfo y $w] \
            [winfo width $w] [winfo height $w]]
    }
    return $result
} -cleanup {
    deleteWindows
} -result {{11 3 20 20} {69 3 20 20} {127 3 20 20}}

test panedwindow-19.67 {ComputeGeometry, one slave, vertical} -setup {
test panedwindow-19.67 {ComputeGeometry, one pane, vertical} -setup {
    deleteWindows
} -body {
    # With just one slave, sashpad and sashwidth should not
    # With just one pane, sashpad and sashwidth should not
    # affect the panedwindow's geometry, since no sash should
    # ever be drawn.
    panedwindow .p -borderwidth 0 -sashpad 5 \
        -orient vertical -sashwidth 3 -handlesize 6 \
        -showhandle 1
    .p add [frame .f -width 20 -height 20 -bg red] -pady 1 \
                    -sticky ""
3248
3249
3250
3251
3252
3253
3254
3255

3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276

3277
3278
3279

3280
3281
3282
3283
3284
3285
3286
3248
3249
3250
3251
3252
3253
3254

3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275

3276
3277
3278

3279
3280
3281
3282
3283
3284
3285
3286







-
+




















-
+


-
+







                            -sticky ""
    }
    list [.p sash coord 0] [.p sash coord 1]
} -cleanup {
    deleteWindows
} -result {{0 26} {0 62}}

test panedwindow-19.70 {ComputeGeometry/ArrangePanes, slave coords, vert} -setup {
test panedwindow-19.70 {ComputeGeometry/ArrangePanes, pane coords, vert} -setup {
    deleteWindows
} -body {
    panedwindow .p -borderwidth 0 -sashpad 5 \
        -sashwidth 3 -handlesize 6 -showhandle 1 \
        -orient vertical
    foreach w {.p.f1 .p.f2 .p.f3} {
        .p add [frame $w -width 20 -height 20 -bg blue] \
            -sticky nsew -pady 11 -padx 3
    }
    pack .p
    update
    set result {}
    foreach w {.p.f1 .p.f2 .p.f3} {
        lappend result [list [winfo x $w] [winfo y $w] \
            [winfo width $w] [winfo height $w]]
        }
    return $result
} -cleanup {
    deleteWindows
} -result {{3 11 20 20} {3 69 20 20} {3 127 20 20}}
test panedwindow-19.71 {ComputeGeometry, one slave, reqsize set properly} -setup {
test panedwindow-19.71 {ComputeGeometry, one pane, reqsize set properly} -setup {
    deleteWindows
} -body {
    # With just one slave, sashpad and sashwidth should not
    # With just one pane, sashpad and sashwidth should not
    # affect the panedwindow's geometry, since no sash should
    # ever be drawn.
    panedwindow .p -borderwidth 2 -sashpad 0 \
        -sashwidth 0 -handlesize 6 -showhandle 0
    .p add [frame .p.f -width 20 -height 20 -bg red] -padx 0 -sticky ""
    list [winfo reqwidth .p] [winfo reqheight .p]
} -cleanup {
3310
3311
3312
3313
3314
3315
3316
3317

3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338

3339
3340
3341

3342
3343
3344
3345
3346
3347
3348
3310
3311
3312
3313
3314
3315
3316

3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337

3338
3339
3340

3341
3342
3343
3344
3345
3346
3347
3348







-
+




















-
+


-
+







                            -sticky ""
    }
    list [.p sash coord 0] [.p sash coord 1]
} -cleanup {
    deleteWindows
} -result {{22 2} {42 2}}

test panedwindow-19.74 {ComputeGeometry/ArrangePanes, slave coords} -setup {
test panedwindow-19.74 {ComputeGeometry/ArrangePanes, pane coords} -setup {
    deleteWindows
} -body {
    panedwindow .p -borderwidth 2 -sashpad 0 \
        -sashwidth 0 -handlesize 6 -showhandle 0
    foreach w {.p.f1 .p.f2 .p.f3} {
        .p add [frame $w -width 20 -height 20 -bg blue] \
            -sticky nsew -pady 3 -padx 11
    }
    pack .p
    update
    set result {}
    foreach w {.p.f1 .p.f2 .p.f3} {
        lappend result [list [winfo x $w] [winfo y $w] \
            [winfo width $w] [winfo height $w]]
    }
    return $result
} -cleanup {
    deleteWindows
} -result {{13 5 20 20} {55 5 20 20} {97 5 20 20}}

test panedwindow-19.75 {ComputeGeometry, one slave, vertical} -setup {
test panedwindow-19.75 {ComputeGeometry, one pane, vertical} -setup {
    deleteWindows
} -body {
    # With just one slave, sashpad and sashwidth should not
    # With just one pane, sashpad and sashwidth should not
    # affect the panedwindow's geometry, since no sash should
    # ever be drawn.
    panedwindow .p -borderwidth 2 -sashpad 0 \
        -orient vertical -sashwidth 0 -handlesize 6 \
        -showhandle 0
    .p add [frame .f -width 20 -height 20 -bg red] -pady 0 \
                    -sticky ""
3377
3378
3379
3380
3381
3382
3383
3384

3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405

3406
3407
3408

3409
3410
3411
3412
3413
3414
3415
3377
3378
3379
3380
3381
3382
3383

3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404

3405
3406
3407

3408
3409
3410
3411
3412
3413
3414
3415







-
+




















-
+


-
+







                            -sticky ""
    }
    list [.p sash coord 0] [.p sash coord 1]
} -cleanup {
    deleteWindows
} -result {{2 22} {2 42}}

test panedwindow-19.78 {ComputeGeometry/ArrangePanes, slave coords, vert} -setup {
test panedwindow-19.78 {ComputeGeometry/ArrangePanes, pane coords, vert} -setup {
    deleteWindows
} -body {
    panedwindow .p -borderwidth 2 -sashpad 0 \
        -sashwidth 0 -handlesize 6 -showhandle 0 \
        -orient vertical
    foreach w {.p.f1 .p.f2 .p.f3} {
        .p add [frame $w -width 20 -height 20 -bg blue] \
            -sticky nsew -pady 11 -padx 3
    }
    pack .p
    update
    set result {}
    foreach w {.p.f1 .p.f2 .p.f3} {
        lappend result [list [winfo x $w] [winfo y $w] \
            [winfo width $w] [winfo height $w]]
        }
    return $result
} -cleanup {
    deleteWindows
} -result {{5 13 20 20} {5 55 20 20} {5 97 20 20}}
test panedwindow-19.79 {ComputeGeometry, one slave, reqsize set properly} -setup {
test panedwindow-19.79 {ComputeGeometry, one pane, reqsize set properly} -setup {
    deleteWindows
} -body {
    # With just one slave, sashpad and sashwidth should not
    # With just one pane, sashpad and sashwidth should not
    # affect the panedwindow's geometry, since no sash should
    # ever be drawn.
    panedwindow .p -borderwidth 2 -sashpad 0 \
        -sashwidth 0 -handlesize 6 -showhandle 1
    .p add [frame .p.f -width 20 -height 20 -bg red] -padx 1 -sticky ""
    list [winfo reqwidth .p] [winfo reqheight .p]
} -cleanup {
3439
3440
3441
3442
3443
3444
3445
3446

3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467

3468
3469
3470

3471
3472
3473
3474
3475
3476
3477
3439
3440
3441
3442
3443
3444
3445

3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466

3467
3468
3469

3470
3471
3472
3473
3474
3475
3476
3477







-
+




















-
+


-
+







                            -sticky ""
    }
    list [.p sash coord 0] [.p sash coord 1]
} -cleanup {
    deleteWindows
} -result {{25 2} {51 2}}

test panedwindow-19.82 {ComputeGeometry/ArrangePanes, slave coords} -setup {
test panedwindow-19.82 {ComputeGeometry/ArrangePanes, pane coords} -setup {
    deleteWindows
} -body {
    panedwindow .p -borderwidth 2 -sashpad 0 \
        -sashwidth 0 -handlesize 6 -showhandle 1
    foreach w {.p.f1 .p.f2 .p.f3} {
        .p add [frame $w -width 20 -height 20 -bg blue] \
            -sticky nsew -pady 3 -padx 11
    }
    pack .p
    update
    set result {}
    foreach w {.p.f1 .p.f2 .p.f3} {
        lappend result [list [winfo x $w] [winfo y $w] \
            [winfo width $w] [winfo height $w]]
    }
    return $result
} -cleanup {
    deleteWindows
} -result {{13 5 20 20} {61 5 20 20} {109 5 20 20}}

test panedwindow-19.83 {ComputeGeometry, one slave, vertical} -setup {
test panedwindow-19.83 {ComputeGeometry, one pane, vertical} -setup {
    deleteWindows
} -body {
    # With just one slave, sashpad and sashwidth should not
    # With just one pane, sashpad and sashwidth should not
    # affect the panedwindow's geometry, since no sash should
    # ever be drawn.
    panedwindow .p -borderwidth 2 -sashpad 0 \
        -orient vertical -sashwidth 0 -handlesize 6 \
        -showhandle 1
    .p add [frame .f -width 20 -height 20 -bg red] -pady 1 \
                    -sticky ""
3506
3507
3508
3509
3510
3511
3512
3513

3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534

3535
3536
3537

3538
3539
3540
3541
3542
3543
3544
3506
3507
3508
3509
3510
3511
3512

3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533

3534
3535
3536

3537
3538
3539
3540
3541
3542
3543
3544







-
+




















-
+


-
+







                            -sticky ""
    }
    list [.p sash coord 0] [.p sash coord 1]
} -cleanup {
    deleteWindows
} -result {{2 25} {2 51}}

test panedwindow-19.86 {ComputeGeometry/ArrangePanes, slave coords, vert} -setup {
test panedwindow-19.86 {ComputeGeometry/ArrangePanes, pane coords, vert} -setup {
    deleteWindows
} -body {
    panedwindow .p -borderwidth 2 -sashpad 0 \
        -sashwidth 0 -handlesize 6 -showhandle 1 \
        -orient vertical
    foreach w {.p.f1 .p.f2 .p.f3} {
        .p add [frame $w -width 20 -height 20 -bg blue] \
            -sticky nsew -pady 11 -padx 3
    }
    pack .p
    update
    set result {}
    foreach w {.p.f1 .p.f2 .p.f3} {
        lappend result [list [winfo x $w] [winfo y $w] \
            [winfo width $w] [winfo height $w]]
        }
    return $result
} -cleanup {
    deleteWindows
} -result {{5 13 20 20} {5 61 20 20} {5 109 20 20}}
test panedwindow-19.87 {ComputeGeometry, one slave, reqsize set properly} -setup {
test panedwindow-19.87 {ComputeGeometry, one pane, reqsize set properly} -setup {
    deleteWindows
} -body {
    # With just one slave, sashpad and sashwidth should not
    # With just one pane, sashpad and sashwidth should not
    # affect the panedwindow's geometry, since no sash should
    # ever be drawn.
    panedwindow .p -borderwidth 2 -sashpad 0 \
        -sashwidth 3 -handlesize 6 -showhandle 0
    .p add [frame .p.f -width 20 -height 20 -bg red] -padx 0 -sticky ""
    list [winfo reqwidth .p] [winfo reqheight .p]
} -cleanup {
3568
3569
3570
3571
3572
3573
3574
3575

3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596

3597
3598
3599

3600
3601
3602
3603
3604
3605
3606
3568
3569
3570
3571
3572
3573
3574

3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595

3596
3597
3598

3599
3600
3601
3602
3603
3604
3605
3606







-
+




















-
+


-
+







                            -sticky ""
    }
    list [.p sash coord 0] [.p sash coord 1]
} -cleanup {
    deleteWindows
} -result {{22 2} {45 2}}

test panedwindow-19.90 {ComputeGeometry/ArrangePanes, slave coords} -setup {
test panedwindow-19.90 {ComputeGeometry/ArrangePanes, pane coords} -setup {
    deleteWindows
} -body {
    panedwindow .p -borderwidth 2 -sashpad 0 \
        -sashwidth 3 -handlesize 6 -showhandle 0
    foreach w {.p.f1 .p.f2 .p.f3} {
        .p add [frame $w -width 20 -height 20 -bg blue] \
            -sticky nsew -pady 3 -padx 11
    }
    pack .p
    update
    set result {}
    foreach w {.p.f1 .p.f2 .p.f3} {
        lappend result [list [winfo x $w] [winfo y $w] \
            [winfo width $w] [winfo height $w]]
    }
    return $result
} -cleanup {
    deleteWindows
} -result {{13 5 20 20} {58 5 20 20} {103 5 20 20}}

test panedwindow-19.91 {ComputeGeometry, one slave, vertical} -setup {
test panedwindow-19.91 {ComputeGeometry, one pane, vertical} -setup {
    deleteWindows
} -body {
    # With just one slave, sashpad and sashwidth should not
    # With just one pane, sashpad and sashwidth should not
    # affect the panedwindow's geometry, since no sash should
    # ever be drawn.
    panedwindow .p -borderwidth 2 -sashpad 0 \
        -orient vertical -sashwidth 3 -handlesize 6 \
        -showhandle 0
    .p add [frame .f -width 20 -height 20 -bg red] -pady 0 \
                    -sticky ""
3635
3636
3637
3638
3639
3640
3641
3642

3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663

3664
3665
3666

3667
3668
3669
3670
3671
3672
3673
3635
3636
3637
3638
3639
3640
3641

3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662

3663
3664
3665

3666
3667
3668
3669
3670
3671
3672
3673







-
+




















-
+


-
+







                            -sticky ""
    }
    list [.p sash coord 0] [.p sash coord 1]
} -cleanup {
    deleteWindows
} -result {{2 22} {2 45}}

test panedwindow-19.94 {ComputeGeometry/ArrangePanes, slave coords, vert} -setup {
test panedwindow-19.94 {ComputeGeometry/ArrangePanes, pane coords, vert} -setup {
    deleteWindows
} -body {
    panedwindow .p -borderwidth 2 -sashpad 0 \
        -sashwidth 3 -handlesize 6 -showhandle 0 \
        -orient vertical
    foreach w {.p.f1 .p.f2 .p.f3} {
        .p add [frame $w -width 20 -height 20 -bg blue] \
            -sticky nsew -pady 11 -padx 3
    }
    pack .p
    update
    set result {}
    foreach w {.p.f1 .p.f2 .p.f3} {
        lappend result [list [winfo x $w] [winfo y $w] \
            [winfo width $w] [winfo height $w]]
        }
    return $result
} -cleanup {
    deleteWindows
} -result {{5 13 20 20} {5 58 20 20} {5 103 20 20}}
test panedwindow-19.95 {ComputeGeometry, one slave, reqsize set properly} -setup {
test panedwindow-19.95 {ComputeGeometry, one pane, reqsize set properly} -setup {
    deleteWindows
} -body {
    # With just one slave, sashpad and sashwidth should not
    # With just one pane, sashpad and sashwidth should not
    # affect the panedwindow's geometry, since no sash should
    # ever be drawn.
    panedwindow .p -borderwidth 2 -sashpad 0 \
        -sashwidth 3 -handlesize 6 -showhandle 1
    .p add [frame .p.f -width 20 -height 20 -bg red] -padx 1 -sticky ""
    list [winfo reqwidth .p] [winfo reqheight .p]
} -cleanup {
3697
3698
3699
3700
3701
3702
3703
3704

3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725

3726
3727
3728

3729
3730
3731
3732
3733
3734
3735
3697
3698
3699
3700
3701
3702
3703

3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724

3725
3726
3727

3728
3729
3730
3731
3732
3733
3734
3735







-
+




















-
+


-
+







                            -sticky ""
    }
    list [.p sash coord 0] [.p sash coord 1]
} -cleanup {
    deleteWindows
} -result {{23 2} {49 2}}

test panedwindow-19.98 {ComputeGeometry/ArrangePanes, slave coords} -setup {
test panedwindow-19.98 {ComputeGeometry/ArrangePanes, pane coords} -setup {
    deleteWindows
} -body {
    panedwindow .p -borderwidth 2 -sashpad 0 \
        -sashwidth 3 -handlesize 6 -showhandle 1
    foreach w {.p.f1 .p.f2 .p.f3} {
        .p add [frame $w -width 20 -height 20 -bg blue] \
            -sticky nsew -pady 3 -padx 11
    }
    pack .p
    update
    set result {}
    foreach w {.p.f1 .p.f2 .p.f3} {
        lappend result [list [winfo x $w] [winfo y $w] \
            [winfo width $w] [winfo height $w]]
    }
    return $result
} -cleanup {
    deleteWindows
} -result {{13 5 20 20} {61 5 20 20} {109 5 20 20}}

test panedwindow-19.99 {ComputeGeometry, one slave, vertical} -setup {
test panedwindow-19.99 {ComputeGeometry, one pane, vertical} -setup {
    deleteWindows
} -body {
    # With just one slave, sashpad and sashwidth should not
    # With just one pane, sashpad and sashwidth should not
    # affect the panedwindow's geometry, since no sash should
    # ever be drawn.
    panedwindow .p -borderwidth 2 -sashpad 0 \
        -orient vertical -sashwidth 3 -handlesize 6 \
        -showhandle 1
    .p add [frame .f -width 20 -height 20 -bg red] -pady 1 \
                    -sticky ""
3764
3765
3766
3767
3768
3769
3770
3771

3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792

3793
3794
3795

3796
3797
3798
3799
3800
3801
3802
3764
3765
3766
3767
3768
3769
3770

3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791

3792
3793
3794

3795
3796
3797
3798
3799
3800
3801
3802







-
+




















-
+


-
+







                            -sticky ""
    }
    list [.p sash coord 0] [.p sash coord 1]
} -cleanup {
    deleteWindows
} -result {{2 23} {2 49}}

test panedwindow-19.102 {ComputeGeometry/ArrangePanes, slave coords, vert} -setup {
test panedwindow-19.102 {ComputeGeometry/ArrangePanes, pane coords, vert} -setup {
    deleteWindows
} -body {
    panedwindow .p -borderwidth 2 -sashpad 0 \
        -sashwidth 3 -handlesize 6 -showhandle 1 \
        -orient vertical
    foreach w {.p.f1 .p.f2 .p.f3} {
        .p add [frame $w -width 20 -height 20 -bg blue] \
            -sticky nsew -pady 11 -padx 3
    }
    pack .p
    update
    set result {}
    foreach w {.p.f1 .p.f2 .p.f3} {
        lappend result [list [winfo x $w] [winfo y $w] \
            [winfo width $w] [winfo height $w]]
        }
    return $result
} -cleanup {
    deleteWindows
} -result {{5 13 20 20} {5 61 20 20} {5 109 20 20}}
test panedwindow-19.103 {ComputeGeometry, one slave, reqsize set properly} -setup {
test panedwindow-19.103 {ComputeGeometry, one pane, reqsize set properly} -setup {
    deleteWindows
} -body {
    # With just one slave, sashpad and sashwidth should not
    # With just one pane, sashpad and sashwidth should not
    # affect the panedwindow's geometry, since no sash should
    # ever be drawn.
    panedwindow .p -borderwidth 2 -sashpad 5 \
        -sashwidth 0 -handlesize 6 -showhandle 0
    .p add [frame .p.f -width 20 -height 20 -bg red] -padx 0 -sticky ""
    list [winfo reqwidth .p] [winfo reqheight .p]
} -cleanup {
3826
3827
3828
3829
3830
3831
3832
3833

3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854

3855
3856
3857

3858
3859
3860
3861
3862
3863
3864
3826
3827
3828
3829
3830
3831
3832

3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853

3854
3855
3856

3857
3858
3859
3860
3861
3862
3863
3864







-
+




















-
+


-
+







                            -sticky ""
    }
    list [.p sash coord 0] [.p sash coord 1]
} -cleanup {
    deleteWindows
} -result {{27 2} {57 2}}

test panedwindow-19.106 {ComputeGeometry/ArrangePanes, slave coords} -setup {
test panedwindow-19.106 {ComputeGeometry/ArrangePanes, pane coords} -setup {
    deleteWindows
} -body {
    panedwindow .p -borderwidth 2 -sashpad 5 \
        -sashwidth 0 -handlesize 6 -showhandle 0
    foreach w {.p.f1 .p.f2 .p.f3} {
        .p add [frame $w -width 20 -height 20 -bg blue] \
            -sticky nsew -pady 3 -padx 11
    }
    pack .p
    update
    set result {}
    foreach w {.p.f1 .p.f2 .p.f3} {
        lappend result [list [winfo x $w] [winfo y $w] \
            [winfo width $w] [winfo height $w]]
    }
    return $result
} -cleanup {
    deleteWindows
} -result {{13 5 20 20} {65 5 20 20} {117 5 20 20}}

test panedwindow-19.107 {ComputeGeometry, one slave, vertical} -setup {
test panedwindow-19.107 {ComputeGeometry, one pane, vertical} -setup {
    deleteWindows
} -body {
    # With just one slave, sashpad and sashwidth should not
    # With just one pane, sashpad and sashwidth should not
    # affect the panedwindow's geometry, since no sash should
    # ever be drawn.
    panedwindow .p -borderwidth 2 -sashpad 5 \
        -orient vertical -sashwidth 0 -handlesize 6 \
        -showhandle 0
    .p add [frame .f -width 20 -height 20 -bg red] -pady 0 \
                    -sticky ""
3893
3894
3895
3896
3897
3898
3899
3900

3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921

3922
3923
3924

3925
3926
3927
3928
3929
3930
3931
3893
3894
3895
3896
3897
3898
3899

3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920

3921
3922
3923

3924
3925
3926
3927
3928
3929
3930
3931







-
+




















-
+


-
+







                            -sticky ""
    }
    list [.p sash coord 0] [.p sash coord 1]
} -cleanup {
    deleteWindows
} -result {{2 27} {2 57}}

test panedwindow-19.110 {ComputeGeometry/ArrangePanes, slave coords, vert} -setup {
test panedwindow-19.110 {ComputeGeometry/ArrangePanes, pane coords, vert} -setup {
    deleteWindows
} -body {
    panedwindow .p -borderwidth 2 -sashpad 5 \
        -sashwidth 0 -handlesize 6 -showhandle 0 \
        -orient vertical
    foreach w {.p.f1 .p.f2 .p.f3} {
        .p add [frame $w -width 20 -height 20 -bg blue] \
            -sticky nsew -pady 11 -padx 3
    }
    pack .p
    update
    set result {}
    foreach w {.p.f1 .p.f2 .p.f3} {
        lappend result [list [winfo x $w] [winfo y $w] \
            [winfo width $w] [winfo height $w]]
        }
    return $result
} -cleanup {
    deleteWindows
} -result {{5 13 20 20} {5 65 20 20} {5 117 20 20}}
test panedwindow-19.111 {ComputeGeometry, one slave, reqsize set properly} -setup {
test panedwindow-19.111 {ComputeGeometry, one pane, reqsize set properly} -setup {
    deleteWindows
} -body {
    # With just one slave, sashpad and sashwidth should not
    # With just one pane, sashpad and sashwidth should not
    # affect the panedwindow's geometry, since no sash should
    # ever be drawn.
    panedwindow .p -borderwidth 2 -sashpad 5 \
        -sashwidth 0 -handlesize 6 -showhandle 1
    .p add [frame .p.f -width 20 -height 20 -bg red] -padx 1 -sticky ""
    list [winfo reqwidth .p] [winfo reqheight .p]
} -cleanup {
3955
3956
3957
3958
3959
3960
3961
3962

3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983

3984
3985
3986

3987
3988
3989
3990
3991
3992
3993
3955
3956
3957
3958
3959
3960
3961

3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982

3983
3984
3985

3986
3987
3988
3989
3990
3991
3992
3993







-
+




















-
+


-
+







                            -sticky ""
    }
    list [.p sash coord 0] [.p sash coord 1]
} -cleanup {
    deleteWindows
} -result {{30 2} {66 2}}

test panedwindow-19.114 {ComputeGeometry/ArrangePanes, slave coords} -setup {
test panedwindow-19.114 {ComputeGeometry/ArrangePanes, pane coords} -setup {
    deleteWindows
} -body {
    panedwindow .p -borderwidth 2 -sashpad 5 \
        -sashwidth 0 -handlesize 6 -showhandle 1
    foreach w {.p.f1 .p.f2 .p.f3} {
        .p add [frame $w -width 20 -height 20 -bg blue] \
            -sticky nsew -pady 3 -padx 11
    }
    pack .p
    update
    set result {}
    foreach w {.p.f1 .p.f2 .p.f3} {
        lappend result [list [winfo x $w] [winfo y $w] \
            [winfo width $w] [winfo height $w]]
    }
    return $result
} -cleanup {
    deleteWindows
} -result {{13 5 20 20} {71 5 20 20} {129 5 20 20}}

test panedwindow-19.115 {ComputeGeometry, one slave, vertical} -setup {
test panedwindow-19.115 {ComputeGeometry, one pane, vertical} -setup {
    deleteWindows
} -body {
    # With just one slave, sashpad and sashwidth should not
    # With just one pane, sashpad and sashwidth should not
    # affect the panedwindow's geometry, since no sash should
    # ever be drawn.
    panedwindow .p -borderwidth 2 -sashpad 5 \
        -orient vertical -sashwidth 0 -handlesize 6 \
        -showhandle 1
    .p add [frame .f -width 20 -height 20 -bg red] -pady 1 \
                    -sticky ""
4022
4023
4024
4025
4026
4027
4028
4029

4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050

4051
4052
4053

4054
4055
4056
4057
4058
4059
4060
4022
4023
4024
4025
4026
4027
4028

4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049

4050
4051
4052

4053
4054
4055
4056
4057
4058
4059
4060







-
+




















-
+


-
+







                            -sticky ""
    }
    list [.p sash coord 0] [.p sash coord 1]
} -cleanup {
    deleteWindows
} -result {{2 30} {2 66}}

test panedwindow-19.118 {ComputeGeometry/ArrangePanes, slave coords, vert} -setup {
test panedwindow-19.118 {ComputeGeometry/ArrangePanes, pane coords, vert} -setup {
    deleteWindows
} -body {
    panedwindow .p -borderwidth 2 -sashpad 5 \
        -sashwidth 0 -handlesize 6 -showhandle 1 \
        -orient vertical
    foreach w {.p.f1 .p.f2 .p.f3} {
        .p add [frame $w -width 20 -height 20 -bg blue] \
            -sticky nsew -pady 11 -padx 3
    }
    pack .p
    update
    set result {}
    foreach w {.p.f1 .p.f2 .p.f3} {
        lappend result [list [winfo x $w] [winfo y $w] \
            [winfo width $w] [winfo height $w]]
        }
    return $result
} -cleanup {
    deleteWindows
} -result {{5 13 20 20} {5 71 20 20} {5 129 20 20}}
test panedwindow-19.119 {ComputeGeometry, one slave, reqsize set properly} -setup {
test panedwindow-19.119 {ComputeGeometry, one pane, reqsize set properly} -setup {
    deleteWindows
} -body {
    # With just one slave, sashpad and sashwidth should not
    # With just one pane, sashpad and sashwidth should not
    # affect the panedwindow's geometry, since no sash should
    # ever be drawn.
    panedwindow .p -borderwidth 2 -sashpad 5 \
        -sashwidth 3 -handlesize 6 -showhandle 0
    .p add [frame .p.f -width 20 -height 20 -bg red] -padx 0 -sticky ""
    list [winfo reqwidth .p] [winfo reqheight .p]
} -cleanup {
4084
4085
4086
4087
4088
4089
4090
4091

4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112

4113
4114
4115

4116
4117
4118
4119
4120
4121
4122
4084
4085
4086
4087
4088
4089
4090

4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111

4112
4113
4114

4115
4116
4117
4118
4119
4120
4121
4122







-
+




















-
+


-
+







                            -sticky ""
    }
    list [.p sash coord 0] [.p sash coord 1]
} -cleanup {
    deleteWindows
} -result {{27 2} {60 2}}

test panedwindow-19.122 {ComputeGeometry/ArrangePanes, slave coords} -setup {
test panedwindow-19.122 {ComputeGeometry/ArrangePanes, pane coords} -setup {
    deleteWindows
} -body {
    panedwindow .p -borderwidth 2 -sashpad 5 \
        -sashwidth 3 -handlesize 6 -showhandle 0
    foreach w {.p.f1 .p.f2 .p.f3} {
        .p add [frame $w -width 20 -height 20 -bg blue] \
            -sticky nsew -pady 3 -padx 11
    }
    pack .p
    update
    set result {}
    foreach w {.p.f1 .p.f2 .p.f3} {
        lappend result [list [winfo x $w] [winfo y $w] \
            [winfo width $w] [winfo height $w]]
    }
    return $result
} -cleanup {
    deleteWindows
} -result {{13 5 20 20} {68 5 20 20} {123 5 20 20}}

test panedwindow-19.123 {ComputeGeometry, one slave, vertical} -setup {
test panedwindow-19.123 {ComputeGeometry, one pane, vertical} -setup {
    deleteWindows
} -body {
    # With just one slave, sashpad and sashwidth should not
    # With just one pane, sashpad and sashwidth should not
    # affect the panedwindow's geometry, since no sash should
    # ever be drawn.
    panedwindow .p -borderwidth 2 -sashpad 5 \
        -orient vertical -sashwidth 3 -handlesize 6 \
        -showhandle 0
    .p add [frame .f -width 20 -height 20 -bg red] -pady 0 \
                    -sticky ""
4151
4152
4153
4154
4155
4156
4157
4158

4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179

4180
4181
4182

4183
4184
4185
4186
4187
4188
4189
4151
4152
4153
4154
4155
4156
4157

4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178

4179
4180
4181

4182
4183
4184
4185
4186
4187
4188
4189







-
+




















-
+


-
+







                            -sticky ""
    }
    list [.p sash coord 0] [.p sash coord 1]
} -cleanup {
    deleteWindows
} -result {{2 27} {2 60}}

test panedwindow-19.126 {ComputeGeometry/ArrangePanes, slave coords, vert} -setup {
test panedwindow-19.126 {ComputeGeometry/ArrangePanes, pane coords, vert} -setup {
    deleteWindows
} -body {
    panedwindow .p -borderwidth 2 -sashpad 5 \
        -sashwidth 3 -handlesize 6 -showhandle 0 \
        -orient vertical
    foreach w {.p.f1 .p.f2 .p.f3} {
        .p add [frame $w -width 20 -height 20 -bg blue] \
            -sticky nsew -pady 11 -padx 3
    }
    pack .p
    update
    set result {}
    foreach w {.p.f1 .p.f2 .p.f3} {
        lappend result [list [winfo x $w] [winfo y $w] \
            [winfo width $w] [winfo height $w]]
        }
    return $result
} -cleanup {
    deleteWindows
} -result {{5 13 20 20} {5 68 20 20} {5 123 20 20}}
test panedwindow-19.127 {ComputeGeometry, one slave, reqsize set properly} -setup {
test panedwindow-19.127 {ComputeGeometry, one pane, reqsize set properly} -setup {
    deleteWindows
} -body {
    # With just one slave, sashpad and sashwidth should not
    # With just one pane, sashpad and sashwidth should not
    # affect the panedwindow's geometry, since no sash should
    # ever be drawn.
    panedwindow .p -borderwidth 2 -sashpad 5 \
        -sashwidth 3 -handlesize 6 -showhandle 1
    .p add [frame .p.f -width 20 -height 20 -bg red] -padx 1 -sticky ""
    list [winfo reqwidth .p] [winfo reqheight .p]
} -cleanup {
4213
4214
4215
4216
4217
4218
4219
4220

4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241

4242
4243
4244

4245
4246
4247
4248
4249
4250
4251
4213
4214
4215
4216
4217
4218
4219

4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240

4241
4242
4243

4244
4245
4246
4247
4248
4249
4250
4251







-
+




















-
+


-
+







                            -sticky ""
    }
    list [.p sash coord 0] [.p sash coord 1]
} -cleanup {
    deleteWindows
} -result {{28 2} {64 2}}

test panedwindow-19.130 {ComputeGeometry/ArrangePanes, slave coords} -setup {
test panedwindow-19.130 {ComputeGeometry/ArrangePanes, pane coords} -setup {
    deleteWindows
} -body {
    panedwindow .p -borderwidth 2 -sashpad 5 \
        -sashwidth 3 -handlesize 6 -showhandle 1
    foreach w {.p.f1 .p.f2 .p.f3} {
        .p add [frame $w -width 20 -height 20 -bg blue] \
            -sticky nsew -pady 3 -padx 11
    }
    pack .p
    update
    set result {}
    foreach w {.p.f1 .p.f2 .p.f3} {
        lappend result [list [winfo x $w] [winfo y $w] \
            [winfo width $w] [winfo height $w]]
    }
    return $result
} -cleanup {
    deleteWindows
} -result {{13 5 20 20} {71 5 20 20} {129 5 20 20}}

test panedwindow-19.131 {ComputeGeometry, one slave, vertical} -setup {
test panedwindow-19.131 {ComputeGeometry, one pane, vertical} -setup {
    deleteWindows
} -body {
    # With just one slave, sashpad and sashwidth should not
    # With just one pane, sashpad and sashwidth should not
    # affect the panedwindow's geometry, since no sash should
    # ever be drawn.
    panedwindow .p -borderwidth 2 -sashpad 5 \
        -orient vertical -sashwidth 3 -handlesize 6 \
        -showhandle 1
    .p add [frame .f -width 20 -height 20 -bg red] -pady 1 \
                    -sticky ""
4280
4281
4282
4283
4284
4285
4286
4287

4288
4289
4290
4291
4292
4293
4294
4280
4281
4282
4283
4284
4285
4286

4287
4288
4289
4290
4291
4292
4293
4294







-
+







                            -sticky ""
    }
    list [.p sash coord 0] [.p sash coord 1]
} -cleanup {
    deleteWindows
} -result {{2 28} {2 64}}

test panedwindow-19.134 {ComputeGeometry/ArrangePanes, slave coords, vert} -setup {
test panedwindow-19.134 {ComputeGeometry/ArrangePanes, pane coords, vert} -setup {
    deleteWindows
} -body {
    panedwindow .p -borderwidth 2 -sashpad 5 \
        -sashwidth 3 -handlesize 6 -showhandle 1 \
        -orient vertical
    foreach w {.p.f1 .p.f2 .p.f3} {
        .p add [frame $w -width 20 -height 20 -bg blue] \
4313
4314
4315
4316
4317
4318
4319
4320

4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331

4332
4333
4334
4335
4336
4337
4338
4313
4314
4315
4316
4317
4318
4319

4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330

4331
4332
4333
4334
4335
4336
4337
4338







-
+










-
+







    panedwindow .p
    .p add [frame .f -width 20 -height 20 -bg blue]
    destroy .f
    .p panes
} -cleanup {
	deleteWindows
} -result {}
test panedwindow-20.2 {destroyed slave causes geometry recomputation} -setup {
test panedwindow-20.2 {destroyed pane causes geometry recomputation} -setup {
	deleteWindows
} -body {
    panedwindow .p -borderwidth 0 -sashpad 0 -sashwidth 2
    .p add [frame .f -width 20 -height 20 -bg blue] \
	    [frame .f2 -width 20 -height 20 -bg red]
    destroy .f
    winfo reqwidth .p
} -cleanup {
    deleteWindows
} -result 20
    


test panedwindow-21.1 {ArrangePanes, extra space is given to the last pane} -setup {
	deleteWindows
} -body {
    panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
    .p add [frame .f1 -width 20 -height 20 -bg blue] \
	    [frame .f2 -width 20 -height 20 -bg red] -sticky nsew
4533
4534
4535
4536
4537
4538
4539
4540

4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553

4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565

4566
4567
4568
4569
4570
4571
4572
4533
4534
4535
4536
4537
4538
4539

4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552

4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564

4565
4566
4567
4568
4569
4570
4571
4572







-
+












-
+











-
+







	lappend result [winfo width .f1] [winfo width .f2] [winfo width .f3] \
		[winfo width .f4] [winfo width .p]
} -cleanup {
    deleteWindows
} -result {50 150 1 1 211 50 150 1 89 300}


test panedwindow-22.1 {PanedWindowReqProc, react to slave geometry changes} -setup {
test panedwindow-22.1 {PanedWindowReqProc, react to pane geometry changes} -setup {
	deleteWindows
} -body {
    # Basically just want to make sure that the PanedWindowReqProc is called
    panedwindow .p -borderwidth 0 -sashpad 0 -sashwidth 2
    .p add [frame .f1 -width 20 -height 20 -bg blue] \
	    [frame .f2 -width 20 -height 40 -bg red]
    set result [winfo reqheight .p]
    .f1 configure -height 80
    lappend result [winfo reqheight .p]
} -cleanup {
	deleteWindows
} -result {40 80}
test panedwindow-22.2 {PanedWindowReqProc, react to slave geometry changes} -setup {
test panedwindow-22.2 {PanedWindowReqProc, react to pane geometry changes} -setup {
	deleteWindows
} -body {
    panedwindow .p -orient horizontal -sashpad 0 -sashwidth 2
    .p add [frame .f1 -width 10] [frame .f2 -width 10]
    set result [winfo reqwidth .p]
    .f1 configure -width 20
    lappend result [winfo reqwidth .p]
    destroy .p .f1 .f2
    expr {[lindex $result 1] - [lindex $result 0]}
} -cleanup {
	deleteWindows
} -result {10}
} -result 10


test panedwindow-23.1 {ConfigurePanes, can't add panedwindow to itself} -setup {
	deleteWindows
} -body {
    panedwindow .p
    .p add .p
4820
4821
4822
4823
4824
4825
4826
4827

4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842

4843
4844
4845
4846
4847
4848
4849
4820
4821
4822
4823
4824
4825
4826

4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841

4842
4843
4844
4845
4846
4847
4848
4849







-
+














-
+








    .p add .a .b .c
    .p add .d .b -before .a
    .p panes
} -cleanup {
	deleteWindows
} -result {.d .b .a .c}
test panedwindow-23.22 {ConfigurePanes, slave specified multiple times} -setup {
test panedwindow-23.22 {ConfigurePanes, pane specified multiple times} -setup {
	deleteWindows
} -body {
    # This test should not cause a core dump

    panedwindow .p
    button .a
    button .b
    button .c

    .p add .a .a .b .c
    .p panes
} -cleanup {
	deleteWindows
} -result {.a .b .c}
test panedwindow-23.23 {ConfigurePanes, slave specified multiple times} -setup {
test panedwindow-23.23 {ConfigurePanes, pane specified multiple times} -setup {
	deleteWindows
} -body {
    # This test should not cause a core dump

    panedwindow .p
    button .a
    button .b
5142
5143
5144
5145
5146
5147
5148
5149

5150
5151
5152
5153
5154
5155
5156
5142
5143
5144
5145
5146
5147
5148

5149
5150
5151
5152
5153
5154
5155
5156







-
+







	    .p add [button $w]
    }
    foreach w {.a .b .c .d .e .f .g .h .i .j .k .l .m .n .o .p .q .r .s .t} {
	    destroy $w
    }
    set result {}
} -result {}
test panedwindow-25.2 {UnmapNotify and MapNotify events are propagated to slaves} -setup {
test panedwindow-25.2 {UnmapNotify and MapNotify events are propagated to panes} -setup {
    deleteWindows
} -body {
    panedwindow .pw
    .pw add [button .pw.b]
    pack .pw
    update
    set result [winfo ismapped .pw.b]
5457
5458
5459
5460
5461
5462
5463
5464

5465
5466
5467
5468
5469
5470
5471
5457
5458
5459
5460
5461
5462
5463

5464
5465
5466
5467
5468
5469
5470
5471







-
+







} -body {
    destroy .p
    panedwindow .p
    rename .p {}
    winfo exists .p
} -cleanup {
	deleteWindows
} -result {0}
} -result 0


test panedwindow-28.1 {resizing width} -setup {
	deleteWindows
} -body {
    panedwindow .p -bd 5
    frame .f1 -width 100 -height 50 -bg blue
Added tests/pkgconfig.test.




































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# -*- tcl -*-
# Commands covered:  pkgconfig
#
# This file contains a collection of tests for one or more of the Tk
# built-in commands.  Sourcing this file into Tk runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994-1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# Copyright © 2017 Stuart Cassoff <[email protected]>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

package require tcltest 2.2
namespace import ::tcltest::*
eval tcltest::configure $argv
tcltest::loadTestedCommands

testConstraint nodeprecated [expr {"nodeprecated" ni [tk::pkgconfig list]}]

test pkgconfig-1.1 {query keys} {nonwin nodeprecated} {
    lsort [::tk::pkgconfig list]
} [list \
    64bit bindir,install bindir,runtime debug demodir,install demodir,runtime \
    docdir,install docdir,runtime fontsystem includedir,install includedir,runtime \
    libdir,install libdir,runtime mem_debug optimized profiled \
    scriptdir,install scriptdir,runtime threaded \
]
test pkgconfig-1.2 {query keys multiple times} {
    string compare [::tk::pkgconfig list] [::tk::pkgconfig list]
} 0
test pkgconfig-1.3 {query value multiple times} {
    string compare \
	    [::tk::pkgconfig get 64bit] \
	    [::tk::pkgconfig get 64bit]
} 0


test pkgconfig-2.0 {error: missing subcommand} {
    catch {::tk::pkgconfig} msg
    set msg
} {wrong # args: should be "::tk::pkgconfig subcommand ?arg?"}
test pkgconfig-2.1 {error: illegal subcommand} {
    catch {::tk::pkgconfig foo} msg
    set msg
} {bad subcommand "foo": must be get or list}
test pkgconfig-2.2 {error: list with arguments} {
    catch {::tk::pkgconfig list foo} msg
    set msg
} {wrong # args: should be "::tk::pkgconfig list"}
test pkgconfig-2.3 {error: get without arguments} {
    catch {::tk::pkgconfig get} msg
    set msg
} {wrong # args: should be "::tk::pkgconfig get key"}
test pkgconfig-2.4 {error: query unknown key} {
    catch {::tk::pkgconfig get foo} msg
    set msg
} {key not known}
test pkgconfig-2.5 {error: query with to many arguments} {
    catch {::tk::pkgconfig get foo bar} msg
    set msg
} {wrong # args: should be "::tk::pkgconfig subcommand ?arg?"}

# cleanup
cleanupTests
return
Changes to tests/place.test.
1
2
3
4
5


6
7
8
9
10
11
12
13
14



15
16
17
18
19
20
21
1
2
3


4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24



-
-
+
+









+
+
+







# This file is a Tcl script to test out the "place" command.  It is
# organized in the standard fashion for Tcl tests.
#
# Copyright (c) 1995 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1995 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
namespace import ::tcltest::*
eval tcltest::configure $argv
tcltest::loadTestedCommands

# Used for constraining memory leak tests
testConstraint memory [llength [info commands memory]]

testConstraint failsOnUbuntu [expr {![info exists ::env(CI)] || ![string match Linux $::tcl_platform(os)]}]
testConstraint failsOnXQuarz [expr {$tcl_platform(os) ne "Darwin" || [tk windowingsystem] ne "x11" }]

# XXX - This test file is woefully incomplete.  At present, only a
# few of the features are tested.

# Widgets used in tests 1.* - 8.*
toplevel .t -width 300 -height 200 -bd 0
wm geom .t +0+0
49
50
51
52
53
54
55
56

57
58
59

60
61
62
63
64
65
66


67
68
69
70
71
72
73
74

75
76
77

78
79
80

81
82
83
84
85
86
87


88
89
90
91
92
93
94
95

96
97
98

99
100
101
102
103


104
105
106
107
108
109
110

111
112
113
114
115
116


117
118
119
120
121


122
123
124
125

126
127
128
129
130
131

132
133
134
135
136
137
138
139
140

141
142

143
144
145

146
147
148
149
150
151
152


153
154
155
156
157
158
159
160

161
162

163
164
165

166
167
168
169
170
171
172


173
174
175
176
177
178
179
180

181
182
183
184
185
186
187
52
53
54
55
56
57
58

59
60
61

62
63
64
65
66
67


68
69
70
71
72
73
74
75
76

77
78
79

80
81
82

83
84
85
86
87
88


89
90
91
92
93
94
95
96
97

98
99
100

101
102
103
104


105
106
107
108
109
110
111
112

113
114
115
116
117


118
119
120
121
122


123
124
125
126
127

128
129
130
131
132
133

134
135
136
137
138
139
140
141
142

143
144

145
146
147

148
149
150
151
152
153


154
155
156
157
158
159
160
161
162

163
164

165
166
167

168
169
170
171
172
173


174
175
176
177
178
179
180
181
182

183
184
185
186
187
188
189
190







-
+


-
+





-
-
+
+







-
+


-
+


-
+





-
-
+
+







-
+


-
+



-
-
+
+






-
+




-
-
+
+



-
-
+
+



-
+





-
+








-
+

-
+


-
+





-
-
+
+







-
+

-
+


-
+





-
-
+
+







-
+







        -bordermode ignore
    place info .t.f2
} -cleanup {
    destroy ".t.a.b"
} -result {-in {.t.a b} -x 1 -relx 0.2 -y 2 -rely 0.2 -width {} -relwidth 0.3 -height 4 -relheight {} -anchor w -bordermode ignore}


test place-2.1 {ConfigureSlave procedure, -height option} -body {
test place-2.1 {ConfigureContent procedure, -height option} -body {
    place .t.f2 -height abcd
} -returnCodes error -result {bad screen distance "abcd"}
test place-2.2 {ConfigureSlave procedure, -height option} -setup {
test place-2.2 {ConfigureContent procedure, -height option} -setup {
    place forget .t.f2
} -body {
    place .t.f2 -in .t.f -height 40
    update
    winfo height .t.f2
} -result {40}
test place-2.3 {ConfigureSlave procedure, -height option} -setup {
} -result 40
test place-2.3 {ConfigureContent procedure, -height option} -setup {
    place forget .t.f2
} -body {
    place .t.f2 -in .t.f -height 120
    update
    place .t.f2 -height {}
    update
    winfo height .t.f2
} -result {60}
} -result 60


test place-3.1 {ConfigureSlave procedure, -relheight option} -body {
test place-3.1 {ConfigureContent procedure, -relheight option} -body {
    place .t.f2 -relheight abcd
} -returnCodes error -result {expected floating-point number but got "abcd"}
test place-3.2 {ConfigureSlave procedure, -relheight option} -setup {
test place-3.2 {ConfigureContent procedure, -relheight option} -setup {
    place forget .t.f2
} -body {
    place .t.f2 -in .t.f -relheight .5
    update
    winfo height .t.f2
} -result {40}
test place-3.3 {ConfigureSlave procedure, -relheight option} -setup {
} -result 40
test place-3.3 {ConfigureContent procedure, -relheight option} -setup {
    place forget .t.f2
} -body {
    place .t.f2 -in .t.f -relheight .8
    update
    place .t.f2 -relheight {}
    update
    winfo height .t.f2
} -result {60}
} -result 60


test place-4.1 {ConfigureSlave procedure, bad -in options} -setup {
test place-4.1 {ConfigureContent procedure, bad -in options} -setup {
    place forget .t.f2
} -body {
    place .t.f2 -in .t.f2
} -returnCodes error -result {can't place .t.f2 relative to itself}
test place-4.2 {ConfigureSlave procedure, bad -in option} -setup {
} -returnCodes error -result {can't place ".t.f2" relative to itself}
test place-4.2 {ConfigureContent procedure, bad -in option} -setup {
    place forget .t.f2
} -body {
    set result [list [winfo manager .t.f2]]
    catch {place .t.f2 -in .t.f2}
    lappend result [winfo manager .t.f2]
} -result {{} {}}
test place-4.3 {ConfigureSlave procedure, bad -in option} -setup {
test place-4.3 {ConfigureContent procedure, bad -in option} -setup {
    place forget .t.f2
} -body {
    winfo manager .t.f2
    place .t.f2 -in .t.f2
} -returnCodes error -result {can't place .t.f2 relative to itself}
test place-4.4 {ConfigureSlave procedure, bad -in option} -setup {
} -returnCodes error -result {can't place ".t.f2" relative to itself}
test place-4.4 {ConfigureContent procedure, bad -in option} -setup {
    place forget .t.f2
} -body {
    place .t.f2 -in .
} -returnCodes error -result {can't place .t.f2 relative to .}
test place-4.5 {ConfigureSlave procedure, bad -in option} -setup {
} -returnCodes error -result {can't place ".t.f2" relative to "."}
test place-4.5 {ConfigureContent procedure, bad -in option} -setup {
} -body {
    frame .t.f1
    place .t.f1 -in .t.f1
} -returnCodes error -result {can't place .t.f1 relative to itself}
} -returnCodes error -result {can't place ".t.f1" relative to itself}
test place-4.6 {prevent management loops} -setup {
    place forget .t.f1
} -body {
    place .t.f1 -in .t.f2
    place .t.f2 -in .t.f1
} -returnCodes error -result {can't put .t.f2 inside .t.f1, would cause management loop}
} -returnCodes error -result {can't put ".t.f2" inside ".t.f1": would cause management loop}
test place-4.7 {prevent management loops} -setup {
    place forget .t.f1
    place forget .t.f2
} -body {
    frame .t.f3
    place .t.f1 -in .t.f2
    place .t.f2 -in .t.f3
    place .t.f3 -in .t.f1
} -returnCodes error -result {can't put .t.f3 inside .t.f1, would cause management loop}
} -returnCodes error -result {can't put ".t.f3" inside ".t.f1": would cause management loop}

test place-5.1 {ConfigureSlave procedure, -relwidth option} -body {
test place-5.1 {ConfigureContent procedure, -relwidth option} -body {
    place .t.f2 -relwidth abcd
} -returnCodes error -result {expected floating-point number but got "abcd"}
test place-5.2 {ConfigureSlave procedure, -relwidth option} -setup {
test place-5.2 {ConfigureContent procedure, -relwidth option} -setup {
    place forget .t.f2
} -body {
    place .t.f2 -in .t.f -relwidth .5
    update
    winfo width .t.f2
} -result {75}
test place-5.3 {ConfigureSlave procedure, -relwidth option} -setup {
} -result 75
test place-5.3 {ConfigureContent procedure, -relwidth option} -setup {
    place forget .t.f2
} -body {
    place .t.f2 -in .t.f -relwidth .8
    update
    place .t.f2 -relwidth {}
    update
    winfo width .t.f2
} -result {30}
} -result 30

test place-6.1 {ConfigureSlave procedure, -width option} -body {
test place-6.1 {ConfigureContent procedure, -width option} -body {
    place .t.f2 -width abcd
} -returnCodes error -result {bad screen distance "abcd"}
test place-6.2 {ConfigureSlave procedure, -width option} -setup {
test place-6.2 {ConfigureContent procedure, -width option} -setup {
    place forget .t.f2
} -body {
    place .t.f2 -in .t.f -width 100
    update
    winfo width .t.f2
} -result {100}
test place-6.3 {ConfigureSlave procedure, -width option} -setup {
} -result 100
test place-6.3 {ConfigureContent procedure, -width option} -setup {
    place forget .t.f2
} -body {
    place .t.f2 -in .t.f -width 120
    update
    place .t.f2 -width {}
    update
    winfo width .t.f2
} -result {30}
} -result 30


test place-7.1 {ReconfigurePlacement procedure, computing position} -setup {
    place forget .t.f2
} -body {
    place .t.f2 -in .t.f -x -2 -relx .5 -y 3 -rely .4
    update
254
255
256
257
258
259
260



261
262







263
264
265
266
267

268
269
270
271
272
273

274
275
276

277
278
279

280
281

282
283
284
285

286
287
288
289
290
291

292
293
294

295
296
297
298
299
300
301
257
258
259
260
261
262
263
264
265
266


267
268
269
270
271
272
273
274
275
276
277

278
279
280

281
282

283
284
285

286
287
288

289
290
291
292
293
294
295

296
297
298

299
300

301
302
303

304
305
306
307
308
309
310
311







+
+
+
-
-
+
+
+
+
+
+
+




-
+


-


-
+


-
+


-
+


+



-
+


-


-
+


-
+







} -body {
    place .t.f2 -in .t.f -width 10 -relwidth .4 -height -4 -relheight .5
    place .t.f2 -width {} -relwidth {} -height {} -relheight {}
    update
    list [winfo width .t.f2] [winfo height .t.f2]
} -result {30 60}

if {[tk windowingsystem] ne "aqua"} {
    proc placeUpdate {} {
	update

test place-8.1 {MasterStructureProc, mapping and unmapping slaves} -setup {
    }
} else {
    proc placeUpdate {} {
    }
}

test place-8.1 {PlaceStructureProc, mapping and unmapping content} -constraints {failsOnUbuntu failsOnXQuarz} -setup {
    place forget .t.f2
    place forget .t.f
} -body {
    place .t.f2 -relx 1.0 -rely 1.0 -anchor sw
    update
    update idletasks
    set result [winfo ismapped .t.f2]
    wm iconify .t
    update
    lappend result [winfo ismapped .t.f2]
    place .t.f2 -x 40 -y 30 -relx 0 -rely 0 -anchor nw
    update
    update idletasks
    lappend result [winfo x .t.f2] [winfo y .t.f2] [winfo ismapped .t.f2]
    wm deiconify .t
    update
    placeUpdate
    lappend result [winfo ismapped .t.f2]
} -result {1 0 40 30 0 1}
test place-8.2 {MasterStructureProc, mapping and unmapping slaves} -setup {
test place-8.2 {PlaceStructureProc, mapping and unmapping content} -constraints {failsOnUbuntu failsOnXQuarz} -setup {
    place forget .t.f2
    place forget .t.f
    update idletasks
} -body {
    place .t.f -x 0 -y 0 -width 200 -height 100
    place .t.f2 -in .t.f -relx 1.0 -rely 1.0 -anchor sw -width 50 -height 20
    update
    update idletasks
    set result [winfo ismapped .t.f2]
    wm iconify .t
    update
    lappend result [winfo ismapped .t.f2]
    place .t.f2 -x 40 -y 30 -relx 0 -rely 0 -anchor nw
    update
    update idletasks
    lappend result [winfo x .t.f2] [winfo y .t.f2] [winfo ismapped .t.f2]
    wm deiconify .t
    update
    placeUpdate
    lappend result [winfo ismapped .t.f2]
} -result {1 0 42 32 0 1}
destroy .t


test place-9.1 {PlaceObjCmd} -body {
    place
318
319
320
321
322
323
324
325

326
327
328
329
330
331
332
328
329
330
331
332
333
334

335
336
337
338
339
340
341
342







-
+







test place-9.5 {PlaceObjCmd} -setup {
    destroy .foo
} -body {
    frame .foo
    place badopt .foo
} -cleanup {
    destroy .foo
} -returnCodes error -result {bad option "badopt": must be configure, forget, info, or slaves}
} -returnCodes error -result {bad option "badopt": must be configure, content, forget, or info}
test place-9.6 {PlaceObjCmd, configure errors} -setup {
    destroy .foo
} -body {
    frame .foo
    place configure .foo
} -cleanup {
    destroy .foo
369
370
371
372
373
374
375
376

377
378
379
380

381
382
383

384
385
386

387
388
389
390
391
392
393
394

395
396
397
398
399
400
401
402

403
404
405
406
407
408
409
410

411
412
413
414
415
416
417
418

419
420

421
422
423
424

425
426
427
428

429
430
431
432
433
434

435
436
437
438
439
440
441
379
380
381
382
383
384
385

386
387
388
389

390
391
392

393
394
395

396
397
398
399
400
401
402
403

404
405
406
407
408
409
410
411

412
413
414
415
416
417
418
419

420
421
422
423
424
425
426
427

428
429

430
431
432
433

434
435
436
437

438
439
440
441
442
443

444
445
446
447
448
449
450
451







-
+



-
+


-
+


-
+







-
+







-
+







-
+







-
+

-
+



-
+



-
+





-
+







    destroy .foo
} -body {
    frame .foo
    place info .foo bar
} -cleanup {
    destroy .foo
} -returnCodes error -result {wrong # args: should be "place info pathName"}
test place-9.12 {PlaceObjCmd, slaves errors} -setup {
test place-9.12 {PlaceObjCmd, content errors} -setup {
    destroy .foo
} -body {
    frame .foo
    place slaves .foo bar
    place content .foo bar
} -cleanup {
    destroy .foo
} -returnCodes error -result {wrong # args: should be "place slaves pathName"}
} -returnCodes error -result {wrong # args: should be "place content pathName"}


test place-10.1 {ConfigureSlave} -setup {
test place-10.1 {ConfigureContent} -setup {
    destroy .foo
} -body {
    frame .foo
    place .foo -badopt
} -cleanup {
    destroy .foo
} -returnCodes error -result {unknown option "-badopt"}
test place-10.2 {ConfigureSlave} -setup {
test place-10.2 {ConfigureContent} -setup {
    destroy .foo
} -body {
    frame .foo
    place .foo -anchor
} -cleanup {
    destroy .foo
} -returnCodes error -result {value for "-anchor" missing}
test place-10.3 {ConfigureSlave} -setup {
test place-10.3 {ConfigureContent} -setup {
    destroy .foo
} -body {
    frame .foo
    place .foo -bordermode j
} -cleanup {
    destroy .foo
} -returnCodes error -result {bad bordermode "j": must be inside, outside, or ignore}
test place-10.4 {ConfigureSlave} -setup {
test place-10.4 {ConfigureContent} -setup {
    destroy .foo
} -body {
    frame .foo
    place configure .foo -x 0 -y
} -cleanup {
    destroy .foo
} -returnCodes error -result {value for "-y" missing}
    


test place-11.1 {PlaceObjCmd, slaves command} -setup {
test place-11.1 {PlaceObjCmd, content command} -setup {
    destroy .foo
} -body {
    frame .foo
    place slaves .foo
    place content .foo
} -cleanup {
    destroy .foo
} -result {}
test place-11.2 {PlaceObjCmd, slaves command} -setup {
test place-11.2 {PlaceObjCmd, content command} -setup {
    destroy .foo .bar
} -body {
    frame .foo
    frame .bar
    place .bar -in .foo
    place slaves .foo
    place content .foo
} -cleanup {
    destroy .foo .bar
} -result [list .bar]


test place-12.1 {PlaceObjCmd, forget command} -setup {
    destroy .foo
489
490
491
492
493
494
495
496

497
498
499
500
501
502
503
499
500
501
502
503
504
505

506
507
508
509
510
511
512
513







-
+







                set end [getbytes]
            }
            lappend res [expr {$end - $tmp}]
        }
        return $res
    }
} -body {
    # Test all manners of forgetting a slave
    # Test all manners of forgetting content
    frame .f
    frame .f.f
    stress {
        place .f.f -x [expr {1 + 1}] -y [expr {2 + 2}]
        place forget .f.f
    } {
        place .f.f -x [expr {1 + 1}] -y [expr {2 + 2}]
Changes to tests/raise.test.
1
2
3
4
5
6
7
8



9
10
11
12
13
14
15
1
2
3
4
5



6
7
8
9
10
11
12
13
14
15





-
-
-
+
+
+







# This file is a Tcl script to test out Tk's "raise" and
# "lower" commands, plus associated code to manage window
# stacking order.  It is organized in the standard fashion
# for Tcl tests.
#
# Copyright (c) 1993-1994 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1993-1994 The Regents of the University of California.
# Copyright © 1994 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
eval tcltest::configure $argv
tcltest::loadTestedCommands
namespace import -force tcltest::test

Changes to tests/safe.test.
1
2
3
4
5
6



7
8
9
10
11
12
13
1
2
3



4
5
6
7
8
9
10
11
12
13



-
-
-
+
+
+







# This file is a Tcl script to test the Safe Tk facility. It is organized in
# the standard fashion for Tk tests.
#
# Copyright (c) 1994 The Regents of the University of California.
# Copyright (c) 1994-1995 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1994 The Regents of the University of California.
# Copyright © 1994-1995 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
eval tcltest::configure $argv
tcltest::loadTestedCommands
namespace import -force tcltest::test

24
25
26
27
28
29
30
31

32
33
34
35

36
37







38










39
40
41
42
43





44
45
46
47


48
49
50
51
52
53
54
24
25
26
27
28
29
30

31
32
33
34
35
36


37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54





55
56
57
58
59

60


61
62
63
64
65
66
67
68
69







-
+




+
-
-
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-

-
-
+
+







#     invoked from within
# "uplevel #0 [list source $file]"
#
#
# This probably means that tk wasn't installed properly.

## it indicates that something went wrong sourcing tk.tcl.
## Ensure that any changes that occured to tk.tcl will work or are properly
## Ensure that any changes that occurred to tk.tcl will work or are properly
## prevented in a safe interpreter.  -- hobbs

# The set of hidden commands is platform dependent:

set hidden_cmds [list bell cd clipboard encoding exec exit \
set hidden_cmds {bell cd clipboard encoding exec exit fconfigure glob grab load menu open pwd selection socket source tcl:encoding:dirs toplevel unload wm}
lappend hidden_cmds {*}[apply {{} {
	fconfigure glob grab load menu open pwd selection \
	socket source toplevel unload wm]
if {[package vsatisfies [package provide Tcl] 8.6.7-]} {
    lappend hidden_cmds tcl:encoding:dirs
}
if {[package vsatisfies [package provide Tcl] 8.7-]} {
    lappend hidden_cmds file tcl:encoding:system tcl:file:tempdir
    foreach cmd {
	cmdtype nameofexecutable
    } {lappend hidden_cmds tcl:info:$cmd}
    foreach cmd {
	autopurge list purge status
    } {lappend hidden_cmds tcl:process:$cmd}
    foreach cmd {
	lmkimg lmkzip mkimg mkkey mkzip mount  mount_data unmount
    } {lappend hidden_cmds tcl:zipfs:$cmd}
}
foreach cmd {
	atime attributes copy delete dirname executable exists extension
	isdirectory isfile link lstat mkdir mtime nativename normalize owned
	readable readlink rename rootname size stat tail tempfile type
	volumes writable
    } {lappend result tcl:file:$cmd}; return $result
    atime attributes copy delete dirname executable exists extension
    isdirectory isfile link lstat mkdir mtime nativename normalize
    owned readable readlink rename rootname size stat tail tempfile
    type volumes writable
} {lappend hidden_cmds tcl:file:$cmd}
}}]
if {[tk windowingsystem] ne "x11"} {
    lappend hidden_cmds tk_chooseColor tk_chooseDirectory tk_getOpenFile \
	tk_getSaveFile tk_messageBox
    lappend hidden_cmds tk_chooseColor tk_chooseDirectory \
	tk_getOpenFile tk_getSaveFile tk_messageBox
}
if {[llength [info commands send]]} {
    lappend hidden_cmds send
}

set saveAutoPath $::auto_path
set auto_path [list [info library] $::tk_library]
178
179
180
181
182
183
184
185

186
187
188
189
190

191
192
193
194
195
196
197
193
194
195
196
197
198
199

200
201
202
203
204

205
206
207
208
209
210
211
212







-
+




-
+







    pack $w
    set i [safe::loadTk [safe::interpCreate] -use [winfo id $w]]
    interp eval $i {button .b -text "hello world!"; pack .b}
    safe::interpDelete $i
    destroy $w
} -result {}

test safe-5.1 {loading Tk in safe interps without master's clearance} -body {
test safe-5.1 {loading Tk in safe interps without parent's clearance} -body {
    set i [safe::interpCreate]
    interp eval $i {load {} Tk}
} -cleanup {
    safe::interpDelete $i
} -returnCodes error -result {not allowed}
} -returnCodes error -match glob -result {*not allowed}
test safe-5.2 {multi-level Tk loading with clearance} -setup {
    set safeParent [safe::interpCreate]
} -body {
    # No error shall occur in that test and no window shall remain at the end.
    set i [safe::interpCreate [list $safeParent x]]
    safe::loadTk $i
    interp eval $i {
Changes to tests/safePrimarySelection.test.
1
2
3
4
5
6



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

37
38
39
40
41

42
43
44
45
46
47
48
1
2
3



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

36
37
38
39
40

41
42
43
44
45
46
47
48



-
-
-
+
+
+












-
-
-
+
+
+














-
+




-
+







# This file is a Tcl script to test entry widgets in Tk.  It is
# organized in the standard fashion for Tcl tests.
#
# Copyright (c) 1994 The Regents of the University of California.
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1994 The Regents of the University of California.
# Copyright © 1994-1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
namespace import ::tcltest::*
eval tcltest::configure $argv
tcltest::loadTestedCommands

# ------------------------------------------------------------------------------
# Tests that a Safe Base interpreter cannot write to the PRIMARY selection.
# ------------------------------------------------------------------------------
# - Tests 3.*, 6.* test that the fix for ticket de156e9efe implemented in branch
#   bug-de156e9efe has been applied and still works.  They test that a Safe Base
#   slave interpreter cannot write to the PRIMARY selection.
# - The other tests verify that the master interpreter and an unsafe slave CAN
#   write to the PRIMARY selection, and therefore that the test scripts
#   child interpreter cannot write to the PRIMARY selection.
# - The other tests verify that the parent interpreter and an child interpreter
#   CAN write to the PRIMARY selection, and therefore that the test scripts
#   themselves are valid.
# - A text, entry, ttk::entry, listbox, spinbox or ttk::spinbox widget can have
#   option -exportselection 1, meaning (in an unsafe interpreter) that a
#   selection made in one of these widgets is automatically written to the
#   PRIMARY selection.
# - A safe interpreter must not write to the PRIMARY selection.
# - The spinbox, ttk::spinbox are variants of entry, ttk::entry respectively.
# ------------------------------------------------------------------------------

namespace eval ::_test_tmp {}

# ------------------------------------------------------------------------------
#  Proc ::_test_tmp::unsafeInterp
# ------------------------------------------------------------------------------
# Command that creates an unsafe child interpreter and tries to load Tk.
# Command that creates an child interpreter and tries to load Tk.
# - This is necessary for loading Tk if the tests are done in the build
#   directory without installing Tk.  In that case the usual auto_path loading
#   mechanism cannot work because the tk binary is not where pkgIndex.tcl says
#   it is.
# - This command is not needed for Safe Base slaves because safe::loadTk does
# - This command is not needed for Safe Base children because safe::loadTk does
#   something similar and works correctly.
# - Based on scripts in winSend.test.
# ------------------------------------------------------------------------------

namespace eval ::_test_tmp {
    variable TkLoadCmd
}
59
60
61
62
63
64
65
66

67
68
69
70
71
72
73
59
60
61
62
63
64
65

66
67
68
69
70
71
72
73







-
+







    interp create $name
    $name eval [list set argv [list -name $name]]
    catch {{*}$TkLoadCmd $name}
}


set ::_test_tmp::script {
    package require Tk
    package require tk
    namespace eval ::_test_tmp {}

    proc ::_test_tmp::getPrimarySelection {} {
        if {[catch {::tk::GetSelection . PRIMARY} sel]} {
            set sel {}
        }
        return $sel
204
205
206
207
208
209
210
211

212
213
214
215


216
217
218
219
220
221
222
223
224
225
226
227


228
229
230
231
232
233
234
235
236
237
238
239


240
241
242
243
244
245
246
247
248
249
250
251


252
253
254
255
256
257
258
259
260
261
262
263


264
265
266
267
268
269
270
271
272
273
274
275


276
277
278
279
280
281
282
283
284

285
286
287


288
289
290
291
292
293
294
295
296

297
298
299


300
301
302
303
304
305
306
307
308
309
310
311


312
313
314
315
316
317
318
319
320

321
322
323


324
325
326
327
328
329
330
331
332

333
334
335


336
337
338
339

340
341
342
343
344
345
346
347
348
349
350
351
352


353
354
355
356

357
358
359
360
361
362
363
364
365
366
367
368
369


370
371
372
373

374
375
376
377
378
379
380
381
382
383
384
385
386


387
388
389
390

391
392
393
394
395
396
397
398
399
400
401
402
403


404
405
406
407

408
409
410
411
412
413
414
415
416
417
418
419
420


421
422
423
424

425
426
427
428
429
430
431
432
433
434

435
436
437


438
439
440
441

442
443
444
445
446
447
448
449
450
451

452
453
454


455
456
457
458

459
460
461
462
463
464
465
466
467
468
469
470
471


472
473
474
475

476
477
478
479
480
481
482
483
484
485

486
487
488


489
490
491
492

493
494
495
496
497
498
499
500
501
502

503
504
505


506
507
508
509
510

511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526


527
528
529
530
531

532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547


548
549
550
551
552

553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568


569
570
571
572
573

574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589


590
591
592
593
594

595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610


611
612
613
614
615

616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631


632
633
634
635
636

637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652


653
654
655
656
657

658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673


674
675
676
677
678

679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694


695
696
697
698
699

700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715


716
717
718
719
720
721
722
723
724
725
726
727


728
729
730
731
732
733
734
735
736
737
738
739


740
741
742
743
744
745
746
747
748
749
750
751


752
753
754
755
756
757
758
759
760
761
762
763


764
765
766
767
768
769
770
771
772
773
774
775


776
777
778
779
780
781
782
783
784

785
786
787


788
789
790
791
792
793
794
795
796

797
798
799


800
801
802
803
804
805
806
807
808
809
810
811


812
813
814
815
816
817
818
819
820

821
822
823


824
825
826
827
828
829
830
831
832

833
834
835


836
837
838
839

840
841
842
843
844
845
846
847
848
849
850
851
852


853
854
855
856

857
858
859
860
861
862
863
864
865
866
867
868
869


870
871
872
873

874
875
876
877
878
879
880
881
882
883
884
885
886


887
888
889
890

891
892
893
894
895
896
897
898
899
900
901
902
903


904
905
906
907

908
909
910
911
912
913
914
915
916
917
918
919
920


921
922
923
924

925
926
927
928
929
930
931
932
933
934

935
936
937


938
939
940
941

942
943
944
945
946
947
948
949
950
951

952
953
954


955
956
957
958

959
960
961
962
963
964
965
966
967
968
969
970
971


972
973
974
975

976
977
978
979
980
981
982
983
984
985

986
987
988


989
990
991
992

993
994
995
996
997
998
999
1000
1001
1002

1003
1004
1005


1006
1007
1008
1009
1010

1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026


1027
1028
1029
1030
1031

1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047


1048
1049
1050
1051
1052

1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068


1069
1070
1071
1072
1073

1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089


1090
1091
1092
1093
1094

1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110


1111
1112
1113
1114
1115

1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131


1132
1133
1134
1135
1136

1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152


1153
1154
1155
1156
1157

1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173


1174
1175
1176
1177
1178

1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194


1195
1196
1197
1198
1199

1200
1201
1202
1203
1204
1205
1206
204
205
206
207
208
209
210

211
212
213


214
215
216
217
218
219
220
221
222
223
224
225


226
227
228
229
230
231
232
233
234
235
236
237


238
239
240
241
242
243
244
245
246
247
248
249


250
251
252
253
254
255
256
257
258
259
260
261


262
263
264
265
266
267
268
269
270
271
272
273


274
275
276
277
278
279
280
281
282
283

284
285


286
287
288
289
290
291
292
293
294
295

296
297


298
299
300
301
302
303
304
305
306
307
308
309


310
311
312
313
314
315
316
317
318
319

320
321


322
323
324
325
326
327
328
329
330
331

332
333


334
335
336
337
338

339
340
341
342
343
344
345
346
347
348
349
350


351
352
353
354
355

356
357
358
359
360
361
362
363
364
365
366
367


368
369
370
371
372

373
374
375
376
377
378
379
380
381
382
383
384


385
386
387
388
389

390
391
392
393
394
395
396
397
398
399
400
401


402
403
404
405
406

407
408
409
410
411
412
413
414
415
416
417
418


419
420
421
422
423

424
425
426
427
428
429
430
431
432
433

434
435


436
437
438
439
440

441
442
443
444
445
446
447
448
449
450

451
452


453
454
455
456
457

458
459
460
461
462
463
464
465
466
467
468
469


470
471
472
473
474

475
476
477
478
479
480
481
482
483
484

485
486


487
488
489
490
491

492
493
494
495
496
497
498
499
500
501

502
503


504
505
506
507
508
509

510
511
512
513
514
515
516
517
518
519
520
521
522
523
524


525
526
527
528
529
530

531
532
533
534
535
536
537
538
539
540
541
542
543
544
545


546
547
548
549
550
551

552
553
554
555
556
557
558
559
560
561
562
563
564
565
566


567
568
569
570
571
572

573
574
575
576
577
578
579
580
581
582
583
584
585
586
587


588
589
590
591
592
593

594
595
596
597
598
599
600
601
602
603
604
605
606
607
608


609
610
611
612
613
614

615
616
617
618
619
620
621
622
623
624
625
626
627
628
629


630
631
632
633
634
635

636
637
638
639
640
641
642
643
644
645
646
647
648
649
650


651
652
653
654
655
656

657
658
659
660
661
662
663
664
665
666
667
668
669
670
671


672
673
674
675
676
677

678
679
680
681
682
683
684
685
686
687
688
689
690
691
692


693
694
695
696
697
698

699
700
701
702
703
704
705
706
707
708
709
710
711
712
713


714
715
716
717
718
719
720
721
722
723
724
725


726
727
728
729
730
731
732
733
734
735
736
737


738
739
740
741
742
743
744
745
746
747
748
749


750
751
752
753
754
755
756
757
758
759
760
761


762
763
764
765
766
767
768
769
770
771
772
773


774
775
776
777
778
779
780
781
782
783

784
785


786
787
788
789
790
791
792
793
794
795

796
797


798
799
800
801
802
803
804
805
806
807
808
809


810
811
812
813
814
815
816
817
818
819

820
821


822
823
824
825
826
827
828
829
830
831

832
833


834
835
836
837
838

839
840
841
842
843
844
845
846
847
848
849
850


851
852
853
854
855

856
857
858
859
860
861
862
863
864
865
866
867


868
869
870
871
872

873
874
875
876
877
878
879
880
881
882
883
884


885
886
887
888
889

890
891
892
893
894
895
896
897
898
899
900
901


902
903
904
905
906

907
908
909
910
911
912
913
914
915
916
917
918


919
920
921
922
923

924
925
926
927
928
929
930
931
932
933

934
935


936
937
938
939
940

941
942
943
944
945
946
947
948
949
950

951
952


953
954
955
956
957

958
959
960
961
962
963
964
965
966
967
968
969


970
971
972
973
974

975
976
977
978
979
980
981
982
983
984

985
986


987
988
989
990
991

992
993
994
995
996
997
998
999
1000
1001

1002
1003


1004
1005
1006
1007
1008
1009

1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024


1025
1026
1027
1028
1029
1030

1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045


1046
1047
1048
1049
1050
1051

1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066


1067
1068
1069
1070
1071
1072

1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087


1088
1089
1090
1091
1092
1093

1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108


1109
1110
1111
1112
1113
1114

1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129


1130
1131
1132
1133
1134
1135

1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150


1151
1152
1153
1154
1155
1156

1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171


1172
1173
1174
1175
1176
1177

1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192


1193
1194
1195
1196
1197
1198

1199
1200
1201
1202
1203
1204
1205
1206







-
+


-
-
+
+










-
-
+
+










-
-
+
+










-
-
+
+










-
-
+
+










-
-
+
+








-
+

-
-
+
+








-
+

-
-
+
+










-
-
+
+








-
+

-
-
+
+








-
+

-
-
+
+



-
+











-
-
+
+



-
+











-
-
+
+



-
+











-
-
+
+



-
+











-
-
+
+



-
+











-
-
+
+



-
+









-
+

-
-
+
+



-
+









-
+

-
-
+
+



-
+











-
-
+
+



-
+









-
+

-
-
+
+



-
+









-
+

-
-
+
+




-
+














-
-
+
+




-
+














-
-
+
+




-
+














-
-
+
+




-
+














-
-
+
+




-
+














-
-
+
+




-
+














-
-
+
+




-
+














-
-
+
+




-
+














-
-
+
+




-
+














-
-
+
+




-
+














-
-
+
+










-
-
+
+










-
-
+
+










-
-
+
+










-
-
+
+










-
-
+
+








-
+

-
-
+
+








-
+

-
-
+
+










-
-
+
+








-
+

-
-
+
+








-
+

-
-
+
+



-
+











-
-
+
+



-
+











-
-
+
+



-
+











-
-
+
+



-
+











-
-
+
+



-
+











-
-
+
+



-
+









-
+

-
-
+
+



-
+









-
+

-
-
+
+



-
+











-
-
+
+



-
+









-
+

-
-
+
+



-
+









-
+

-
-
+
+




-
+














-
-
+
+




-
+














-
-
+
+




-
+














-
-
+
+




-
+














-
-
+
+




-
+














-
-
+
+




-
+














-
-
+
+




-
+














-
-
+
+




-
+














-
-
+
+




-
+














-
-
+
+




-
+







            update
            return
            # selects 3
        }
    }
}

# Do this once for the master interpreter.
# Do this once for the parent interpreter.
eval $::_test_tmp::script

test safePrimarySelection-1.1 {master interpreter, text, no existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-1.1 {parent interpreter, text, no existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -body {
    ::_test_tmp::tryText
    ::_test_tmp::getPrimarySelection
} -cleanup {
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -result {PAYLOAD}

test safePrimarySelection-1.2 {master interpreter, entry, no existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-1.2 {parent interpreter, entry, no existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -body {
    ::_test_tmp::tryEntry
    ::_test_tmp::getPrimarySelection
} -cleanup {
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -result {PAYLOAD}

test safePrimarySelection-1.3 {master interpreter, ttk::entry, no existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-1.3 {parent interpreter, ttk::entry, no existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -body {
    ::_test_tmp::tryTtkEntry
    ::_test_tmp::getPrimarySelection
} -cleanup {
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -result {PAYLOAD}

test safePrimarySelection-1.4 {master interpreter, listbox, no existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-1.4 {parent interpreter, listbox, no existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -body {
    ::_test_tmp::tryListbox
    ::_test_tmp::getPrimarySelection
} -cleanup {
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -result {PAYLOAD}

test safePrimarySelection-1.5 {master interpreter, spinbox as entry, no existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-1.5 {parent interpreter, spinbox as entry, no existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -body {
    ::_test_tmp::trySpinbox 1
    ::_test_tmp::getPrimarySelection
} -cleanup {
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -result {PAYLOAD}

test safePrimarySelection-1.6 {master interpreter, spinbox spun, no existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-1.6 {parent interpreter, spinbox spun, no existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -body {
    ::_test_tmp::trySpinbox 2
    ::_test_tmp::getPrimarySelection
} -cleanup {
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -result {2}
} -result 2

test safePrimarySelection-1.7 {master interpreter, spinbox spun/selected/spun, no existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-1.7 {parent interpreter, spinbox spun/selected/spun, no existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -body {
    ::_test_tmp::trySpinbox 3
    ::_test_tmp::getPrimarySelection
} -cleanup {
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -result {3}
} -result 3

test safePrimarySelection-1.8 {master interpreter, ttk::spinbox as entry, no existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-1.8 {parent interpreter, ttk::spinbox as entry, no existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -body {
    ::_test_tmp::tryTtkSpinbox 1
    ::_test_tmp::getPrimarySelection
} -cleanup {
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -result {PAYLOAD}

test safePrimarySelection-1.9 {master interpreter, ttk::spinbox spun, no existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-1.9 {parent interpreter, ttk::spinbox spun, no existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -body {
    ::_test_tmp::tryTtkSpinbox 2
    ::_test_tmp::getPrimarySelection
} -cleanup {
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -result {2}
} -result 2

test safePrimarySelection-1.10 {master interpreter, ttk::spinbox spun/selected/spun, no existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-1.10 {parent interpreter, ttk::spinbox spun/selected/spun, no existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -body {
    ::_test_tmp::tryTtkSpinbox 3
    ::_test_tmp::getPrimarySelection
} -cleanup {
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -result {3}
} -result 3

test safePrimarySelection-2.1 {unsafe slave interpreter, text, no existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-2.1 {child interpreter, text, no existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -body {
    set int2 slave2
    set int2 child2
    ::_test_tmp::unsafeInterp $int2
    $int2 eval $::_test_tmp::script
    $int2 eval ::_test_tmp::tryText
    $int2 eval ::_test_tmp::getPrimarySelection
} -cleanup {
    interp delete $int2
    destroy {*}[winfo children .]
    unset int2
    ::_test_tmp::clearPrimarySelection
} -result {PAYLOAD}

test safePrimarySelection-2.2 {unsafe slave interpreter, entry, no existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-2.2 {child interpreter, entry, no existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -body {
    set int2 slave2
    set int2 child2
    ::_test_tmp::unsafeInterp $int2
    $int2 eval $::_test_tmp::script
    $int2 eval ::_test_tmp::tryEntry
    $int2 eval ::_test_tmp::getPrimarySelection
} -cleanup {
    interp delete $int2
    destroy {*}[winfo children .]
    unset int2
    ::_test_tmp::clearPrimarySelection
} -result {PAYLOAD}

test safePrimarySelection-2.3 {unsafe slave interpreter, ttk::entry, no existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-2.3 {child interpreter, ttk::entry, no existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -body {
    set int2 slave2
    set int2 child2
    ::_test_tmp::unsafeInterp $int2
    $int2 eval $::_test_tmp::script
    $int2 eval ::_test_tmp::tryTtkEntry
    $int2 eval ::_test_tmp::getPrimarySelection
} -cleanup {
    interp delete $int2
    destroy {*}[winfo children .]
    unset int2
    ::_test_tmp::clearPrimarySelection
} -result {PAYLOAD}

test safePrimarySelection-2.4 {unsafe slave interpreter, listbox, no existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-2.4 {child interpreter, listbox, no existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -body {
    set int2 slave2
    set int2 child2
    ::_test_tmp::unsafeInterp $int2
    $int2 eval $::_test_tmp::script
    $int2 eval ::_test_tmp::tryListbox
    $int2 eval ::_test_tmp::getPrimarySelection
} -cleanup {
    interp delete $int2
    destroy {*}[winfo children .]
    unset int2
    ::_test_tmp::clearPrimarySelection
} -result {PAYLOAD}

test safePrimarySelection-2.5 {unsafe slave interpreter, spinbox as entry, no existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-2.5 {child interpreter, spinbox as entry, no existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -body {
    set int2 slave2
    set int2 child2
    ::_test_tmp::unsafeInterp $int2
    $int2 eval $::_test_tmp::script
    $int2 eval ::_test_tmp::trySpinbox 1
    $int2 eval ::_test_tmp::getPrimarySelection
} -cleanup {
    interp delete $int2
    destroy {*}[winfo children .]
    unset int2
    ::_test_tmp::clearPrimarySelection
} -result {PAYLOAD}

test safePrimarySelection-2.6 {unsafe slave interpreter, spinbox spun, no existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-2.6 {child interpreter, spinbox spun, no existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -body {
    set int2 slave2
    set int2 child2
    ::_test_tmp::unsafeInterp $int2
    $int2 eval $::_test_tmp::script
    $int2 eval ::_test_tmp::trySpinbox 2
    $int2 eval ::_test_tmp::getPrimarySelection
} -cleanup {
    interp delete $int2
    destroy {*}[winfo children .]
    unset int2
    ::_test_tmp::clearPrimarySelection
} -result {2}
} -result 2

test safePrimarySelection-2.7 {unsafe slave interpreter, spinbox spun/selected/spun, no existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-2.7 {child interpreter, spinbox spun/selected/spun, no existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -body {
    set int2 slave2
    set int2 child2
    ::_test_tmp::unsafeInterp $int2
    $int2 eval $::_test_tmp::script
    $int2 eval ::_test_tmp::trySpinbox 3
    $int2 eval ::_test_tmp::getPrimarySelection
} -cleanup {
    interp delete $int2
    destroy {*}[winfo children .]
    unset int2
    ::_test_tmp::clearPrimarySelection
} -result {3}
} -result 3

test safePrimarySelection-2.8 {unsafe slave interpreter, ttk::spinbox as entry, no existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-2.8 {child interpreter, ttk::spinbox as entry, no existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -body {
    set int2 slave2
    set int2 child2
    ::_test_tmp::unsafeInterp $int2
    $int2 eval $::_test_tmp::script
    $int2 eval ::_test_tmp::tryTtkSpinbox 1
    $int2 eval ::_test_tmp::getPrimarySelection
} -cleanup {
    interp delete $int2
    destroy {*}[winfo children .]
    unset int2
    ::_test_tmp::clearPrimarySelection
} -result {PAYLOAD}

test safePrimarySelection-2.9 {unsafe slave interpreter, ttk::spinbox spun, no existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-2.9 {child interpreter, ttk::spinbox spun, no existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -body {
    set int2 slave2
    set int2 child2
    ::_test_tmp::unsafeInterp $int2
    $int2 eval $::_test_tmp::script
    $int2 eval ::_test_tmp::tryTtkSpinbox 2
    $int2 eval ::_test_tmp::getPrimarySelection
} -cleanup {
    interp delete $int2
    destroy {*}[winfo children .]
    unset int2
    ::_test_tmp::clearPrimarySelection
} -result {2}
} -result 2

test safePrimarySelection-2.10 {unsafe slave interpreter, ttk::spinbox spun/selected/spun, no existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-2.10 {child interpreter, ttk::spinbox spun/selected/spun, no existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -body {
    set int2 slave2
    set int2 child2
    ::_test_tmp::unsafeInterp $int2
    $int2 eval $::_test_tmp::script
    $int2 eval ::_test_tmp::tryTtkSpinbox 3
    $int2 eval ::_test_tmp::getPrimarySelection
} -cleanup {
    interp delete $int2
    destroy {*}[winfo children .]
    unset int2
    ::_test_tmp::clearPrimarySelection
} -result {3}
} -result 3

test safePrimarySelection-3.1 {IMPORTANT, safe slave interpreter, text, no existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-3.1 {IMPORTANT, safe interpreter, text, no existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -body {
    set res0 [::_test_tmp::getPrimarySelection]
    set int2 slave2
    set int2 child2
    ::safe::interpCreate $int2
    ::safe::loadTk $int2
    $int2 eval $::_test_tmp::script
    $int2 eval ::_test_tmp::tryText
    set res1 [$int2 eval ::_test_tmp::getPrimarySelection]
    set res2 [::_test_tmp::getPrimarySelection]
    set res3 $res0--$res1--$res2
} -cleanup {
    interp delete $int2
    destroy {*}[winfo children .]
    unset int2 res0 res1 res2 res3
    ::_test_tmp::clearPrimarySelection
} -result {----}

test safePrimarySelection-3.2 {IMPORTANT, safe slave interpreter, entry, no existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-3.2 {IMPORTANT, safe interpreter, entry, no existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -body {
    set res0 [::_test_tmp::getPrimarySelection]
    set int2 slave2
    set int2 child2
    ::safe::interpCreate $int2
    ::safe::loadTk $int2
    $int2 eval $::_test_tmp::script
    $int2 eval ::_test_tmp::tryEntry
    set res1 [$int2 eval ::_test_tmp::getPrimarySelection]
    set res2 [::_test_tmp::getPrimarySelection]
    set res3 $res0--$res1--$res2
} -cleanup {
    interp delete $int2
    destroy {*}[winfo children .]
    unset int2 res0 res1 res2 res3
    ::_test_tmp::clearPrimarySelection
} -result {----}

test safePrimarySelection-3.3 {IMPORTANT, safe slave interpreter, ttk::entry, no existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-3.3 {IMPORTANT, safe interpreter, ttk::entry, no existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -body {
    set res0 [::_test_tmp::getPrimarySelection]
    set int2 slave2
    set int2 child2
    ::safe::interpCreate $int2
    ::safe::loadTk $int2
    $int2 eval $::_test_tmp::script
    $int2 eval ::_test_tmp::tryTtkEntry
    set res1 [$int2 eval ::_test_tmp::getPrimarySelection]
    set res2 [::_test_tmp::getPrimarySelection]
    set res3 $res0--$res1--$res2
} -cleanup {
    interp delete $int2
    destroy {*}[winfo children .]
    unset int2 res0 res1 res2 res3
    ::_test_tmp::clearPrimarySelection
} -result {----}

test safePrimarySelection-3.4 {IMPORTANT, safe slave interpreter, listbox, no existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-3.4 {IMPORTANT, safe interpreter, listbox, no existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -body {
    set res0 [::_test_tmp::getPrimarySelection]
    set int2 slave2
    set int2 child2
    ::safe::interpCreate $int2
    ::safe::loadTk $int2
    $int2 eval $::_test_tmp::script
    $int2 eval ::_test_tmp::tryListbox
    set res1 [$int2 eval ::_test_tmp::getPrimarySelection]
    set res2 [::_test_tmp::getPrimarySelection]
    set res3 $res0--$res1--$res2
} -cleanup {
    interp delete $int2
    destroy {*}[winfo children .]
    unset int2 res0 res1 res2 res3
    ::_test_tmp::clearPrimarySelection
} -result {----}

test safePrimarySelection-3.5 {IMPORTANT, safe slave interpreter, spinbox as entry, no existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-3.5 {IMPORTANT, safe interpreter, spinbox as entry, no existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -body {
    set res0 [::_test_tmp::getPrimarySelection]
    set int2 slave2
    set int2 child2
    ::safe::interpCreate $int2
    ::safe::loadTk $int2
    $int2 eval $::_test_tmp::script
    $int2 eval ::_test_tmp::trySpinbox 1
    set res1 [$int2 eval ::_test_tmp::getPrimarySelection]
    set res2 [::_test_tmp::getPrimarySelection]
    set res3 $res0--$res1--$res2
} -cleanup {
    interp delete $int2
    destroy {*}[winfo children .]
    unset int2 res0 res1 res2 res3
    ::_test_tmp::clearPrimarySelection
} -result {----}

test safePrimarySelection-3.6 {IMPORTANT, safe slave interpreter, spinbox spun, no existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-3.6 {IMPORTANT, safe interpreter, spinbox spun, no existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -body {
    set res0 [::_test_tmp::getPrimarySelection]
    set int2 slave2
    set int2 child2
    ::safe::interpCreate $int2
    ::safe::loadTk $int2
    $int2 eval $::_test_tmp::script
    $int2 eval ::_test_tmp::trySpinbox 2
    set res1 [$int2 eval ::_test_tmp::getPrimarySelection]
    set res2 [::_test_tmp::getPrimarySelection]
    set res3 $res0--$res1--$res2
} -cleanup {
    interp delete $int2
    destroy {*}[winfo children .]
    unset int2 res0 res1 res2 res3
    ::_test_tmp::clearPrimarySelection
} -result {----}

test safePrimarySelection-3.7 {IMPORTANT, safe slave interpreter, spinbox spun/selected/spun, no existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-3.7 {IMPORTANT, safe interpreter, spinbox spun/selected/spun, no existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -body {
    set res0 [::_test_tmp::getPrimarySelection]
    set int2 slave2
    set int2 child2
    ::safe::interpCreate $int2
    ::safe::loadTk $int2
    $int2 eval $::_test_tmp::script
    $int2 eval ::_test_tmp::trySpinbox 3
    set res1 [$int2 eval ::_test_tmp::getPrimarySelection]
    set res2 [::_test_tmp::getPrimarySelection]
    set res3 $res0--$res1--$res2
} -cleanup {
    interp delete $int2
    destroy {*}[winfo children .]
    unset int2 res0 res1 res2 res3
    ::_test_tmp::clearPrimarySelection
} -result {----}

test safePrimarySelection-3.8 {IMPORTANT, safe slave interpreter, ttk::spinbox as entry, no existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-3.8 {IMPORTANT, safe interpreter, ttk::spinbox as entry, no existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -body {
    set res0 [::_test_tmp::getPrimarySelection]
    set int2 slave2
    set int2 child2
    ::safe::interpCreate $int2
    ::safe::loadTk $int2
    $int2 eval $::_test_tmp::script
    $int2 eval ::_test_tmp::tryTtkSpinbox 1
    set res1 [$int2 eval ::_test_tmp::getPrimarySelection]
    set res2 [::_test_tmp::getPrimarySelection]
    set res3 $res0--$res1--$res2
} -cleanup {
    interp delete $int2
    destroy {*}[winfo children .]
    unset int2 res0 res1 res2 res3
    ::_test_tmp::clearPrimarySelection
} -result {----}

test safePrimarySelection-3.9 {IMPORTANT, safe slave interpreter, ttk::spinbox spun, no existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-3.9 {IMPORTANT, safe interpreter, ttk::spinbox spun, no existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -body {
    set res0 [::_test_tmp::getPrimarySelection]
    set int2 slave2
    set int2 child2
    ::safe::interpCreate $int2
    ::safe::loadTk $int2
    $int2 eval $::_test_tmp::script
    $int2 eval ::_test_tmp::tryTtkSpinbox 2
    set res1 [$int2 eval ::_test_tmp::getPrimarySelection]
    set res2 [::_test_tmp::getPrimarySelection]
    set res3 $res0--$res1--$res2
} -cleanup {
    interp delete $int2
    destroy {*}[winfo children .]
    unset int2 res0 res1 res2 res3
    ::_test_tmp::clearPrimarySelection
} -result {----}

test safePrimarySelection-3.10 {IMPORTANT, safe slave interpreter, ttk::spinbox spun/selected/spun, no existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-3.10 {IMPORTANT, safe interpreter, ttk::spinbox spun/selected/spun, no existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -body {
    set res0 [::_test_tmp::getPrimarySelection]
    set int2 slave2
    set int2 child2
    ::safe::interpCreate $int2
    ::safe::loadTk $int2
    $int2 eval $::_test_tmp::script
    $int2 eval ::_test_tmp::tryTtkSpinbox 3
    set res1 [$int2 eval ::_test_tmp::getPrimarySelection]
    set res2 [::_test_tmp::getPrimarySelection]
    set res3 $res0--$res1--$res2
} -cleanup {
    interp delete $int2
    destroy {*}[winfo children .]
    unset int2 res0 res1 res2 res3
    ::_test_tmp::clearPrimarySelection
} -result {----}

test safePrimarySelection-4.1 {master interpreter, text, existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-4.1 {parent interpreter, text, existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::setPrimarySelection
} -body {
    ::_test_tmp::tryText
    ::_test_tmp::getPrimarySelection
} -cleanup {
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -result {PAYLOAD}

test safePrimarySelection-4.2 {master interpreter, entry, existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-4.2 {parent interpreter, entry, existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::setPrimarySelection
} -body {
    ::_test_tmp::tryEntry
    ::_test_tmp::getPrimarySelection
} -cleanup {
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -result {PAYLOAD}

test safePrimarySelection-4.3 {master interpreter, ttk::entry, existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-4.3 {parent interpreter, ttk::entry, existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::setPrimarySelection
} -body {
    ::_test_tmp::tryTtkEntry
    ::_test_tmp::getPrimarySelection
} -cleanup {
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -result {PAYLOAD}

test safePrimarySelection-4.4 {master interpreter, listbox, existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-4.4 {parent interpreter, listbox, existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::setPrimarySelection
} -body {
    ::_test_tmp::tryListbox
    ::_test_tmp::getPrimarySelection
} -cleanup {
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -result {PAYLOAD}

test safePrimarySelection-4.5 {master interpreter, spinbox as entry, existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-4.5 {parent interpreter, spinbox as entry, existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::setPrimarySelection
} -body {
    ::_test_tmp::trySpinbox 1
    ::_test_tmp::getPrimarySelection
} -cleanup {
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -result {PAYLOAD}

test safePrimarySelection-4.6 {master interpreter, spinbox spun, existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-4.6 {parent interpreter, spinbox spun, existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::setPrimarySelection
} -body {
    ::_test_tmp::trySpinbox 2
    ::_test_tmp::getPrimarySelection
} -cleanup {
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -result {2}
} -result 2

test safePrimarySelection-4.7 {master interpreter, spinbox spun/selected/spun, existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-4.7 {parent interpreter, spinbox spun/selected/spun, existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::setPrimarySelection
} -body {
    ::_test_tmp::trySpinbox 3
    ::_test_tmp::getPrimarySelection
} -cleanup {
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -result {3}
} -result 3

test safePrimarySelection-4.8 {master interpreter, ttk::spinbox as entry, existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-4.8 {parent interpreter, ttk::spinbox as entry, existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::setPrimarySelection
} -body {
    ::_test_tmp::tryTtkSpinbox 1
    ::_test_tmp::getPrimarySelection
} -cleanup {
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -result {PAYLOAD}

test safePrimarySelection-4.9 {master interpreter, ttk::spinbox spun, existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-4.9 {parent interpreter, ttk::spinbox spun, existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::setPrimarySelection
} -body {
    ::_test_tmp::tryTtkSpinbox 2
    ::_test_tmp::getPrimarySelection
} -cleanup {
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -result {2}
} -result 2

test safePrimarySelection-4.10 {master interpreter, ttk::spinbox spun/selected/spun, existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-4.10 {parent interpreter, ttk::spinbox spun/selected/spun, existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::setPrimarySelection
} -body {
    ::_test_tmp::tryTtkSpinbox 3
    ::_test_tmp::getPrimarySelection
} -cleanup {
    destroy {*}[winfo children .]
    ::_test_tmp::clearPrimarySelection
} -result {3}
} -result 3

test safePrimarySelection-5.1 {unsafe slave interpreter, text, existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-5.1 {child interpreter, text, existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::setPrimarySelection
} -body {
    set int2 slave2
    set int2 child2
    ::_test_tmp::unsafeInterp $int2
    $int2 eval $::_test_tmp::script
    $int2 eval ::_test_tmp::tryText
    $int2 eval ::_test_tmp::getPrimarySelection
} -cleanup {
    interp delete $int2
    destroy {*}[winfo children .]
    unset int2
    ::_test_tmp::clearPrimarySelection
} -result {PAYLOAD}

test safePrimarySelection-5.2 {unsafe slave interpreter, entry, existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-5.2 {child interpreter, entry, existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::setPrimarySelection
} -body {
    set int2 slave2
    set int2 child2
    ::_test_tmp::unsafeInterp $int2
    $int2 eval $::_test_tmp::script
    $int2 eval ::_test_tmp::tryEntry
    $int2 eval ::_test_tmp::getPrimarySelection
} -cleanup {
    interp delete $int2
    destroy {*}[winfo children .]
    unset int2
    ::_test_tmp::clearPrimarySelection
} -result {PAYLOAD}

test safePrimarySelection-5.3 {unsafe slave interpreter, ttk::entry, existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-5.3 {child interpreter, ttk::entry, existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::setPrimarySelection
} -body {
    set int2 slave2
    set int2 child2
    ::_test_tmp::unsafeInterp $int2
    $int2 eval $::_test_tmp::script
    $int2 eval ::_test_tmp::tryTtkEntry
    $int2 eval ::_test_tmp::getPrimarySelection
} -cleanup {
    interp delete $int2
    destroy {*}[winfo children .]
    unset int2
    ::_test_tmp::clearPrimarySelection
} -result {PAYLOAD}

test safePrimarySelection-5.4 {unsafe slave interpreter, listbox, existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-5.4 {child interpreter, listbox, existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::setPrimarySelection
} -body {
    set int2 slave2
    set int2 child2
    ::_test_tmp::unsafeInterp $int2
    $int2 eval $::_test_tmp::script
    $int2 eval ::_test_tmp::tryListbox
    $int2 eval ::_test_tmp::getPrimarySelection
} -cleanup {
    interp delete $int2
    destroy {*}[winfo children .]
    unset int2
    ::_test_tmp::clearPrimarySelection
} -result {PAYLOAD}

test safePrimarySelection-5.5 {unsafe slave interpreter, spinbox as entry, existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-5.5 {child interpreter, spinbox as entry, existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::setPrimarySelection
} -body {
    set int2 slave2
    set int2 child2
    ::_test_tmp::unsafeInterp $int2
    $int2 eval $::_test_tmp::script
    $int2 eval ::_test_tmp::trySpinbox 1
    $int2 eval ::_test_tmp::getPrimarySelection
} -cleanup {
    interp delete $int2
    destroy {*}[winfo children .]
    unset int2
    ::_test_tmp::clearPrimarySelection
} -result {PAYLOAD}

test safePrimarySelection-5.6 {unsafe slave interpreter, spinbox spun, existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-5.6 {child interpreter, spinbox spun, existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::setPrimarySelection
} -body {
    set int2 slave2
    set int2 child2
    ::_test_tmp::unsafeInterp $int2
    $int2 eval $::_test_tmp::script
    $int2 eval ::_test_tmp::trySpinbox 2
    $int2 eval ::_test_tmp::getPrimarySelection
} -cleanup {
    interp delete $int2
    destroy {*}[winfo children .]
    unset int2
    ::_test_tmp::clearPrimarySelection
} -result {2}
} -result 2

test safePrimarySelection-5.7 {unsafe slave interpreter, spinbox spun/selected/spun, existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-5.7 {child interpreter, spinbox spun/selected/spun, existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::setPrimarySelection
} -body {
    set int2 slave2
    set int2 child2
    ::_test_tmp::unsafeInterp $int2
    $int2 eval $::_test_tmp::script
    $int2 eval ::_test_tmp::trySpinbox 3
    $int2 eval ::_test_tmp::getPrimarySelection
} -cleanup {
    interp delete $int2
    destroy {*}[winfo children .]
    unset int2
    ::_test_tmp::clearPrimarySelection
} -result {3}
} -result 3

test safePrimarySelection-5.8 {unsafe slave interpreter, ttk::spinbox as entry, existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-5.8 {child interpreter, ttk::spinbox as entry, existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::setPrimarySelection
} -body {
    set int2 slave2
    set int2 child2
    ::_test_tmp::unsafeInterp $int2
    $int2 eval $::_test_tmp::script
    $int2 eval ::_test_tmp::tryTtkSpinbox 1
    $int2 eval ::_test_tmp::getPrimarySelection
} -cleanup {
    interp delete $int2
    destroy {*}[winfo children .]
    unset int2
    ::_test_tmp::clearPrimarySelection
} -result {PAYLOAD}

test safePrimarySelection-5.9 {unsafe slave interpreter, ttk::spinbox spun, existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-5.9 {child interpreter, ttk::spinbox spun, existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::setPrimarySelection
} -body {
    set int2 slave2
    set int2 child2
    ::_test_tmp::unsafeInterp $int2
    $int2 eval $::_test_tmp::script
    $int2 eval ::_test_tmp::tryTtkSpinbox 2
    $int2 eval ::_test_tmp::getPrimarySelection
} -cleanup {
    interp delete $int2
    destroy {*}[winfo children .]
    unset int2
    ::_test_tmp::clearPrimarySelection
} -result {2}
} -result 2

test safePrimarySelection-5.10 {unsafe slave interpreter, ttk::spinbox spun/selected/spun, existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-5.10 {child interpreter, ttk::spinbox spun/selected/spun, existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::setPrimarySelection
} -body {
    set int2 slave2
    set int2 child2
    ::_test_tmp::unsafeInterp $int2
    $int2 eval $::_test_tmp::script
    $int2 eval ::_test_tmp::tryTtkSpinbox 3
    $int2 eval ::_test_tmp::getPrimarySelection
} -cleanup {
    interp delete $int2
    destroy {*}[winfo children .]
    unset int2
    ::_test_tmp::clearPrimarySelection
} -result {3}
} -result 3

test safePrimarySelection-6.1 {IMPORTANT, safe slave interpreter, text, existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-6.1 {IMPORTANT, safe interpreter, text, existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::setPrimarySelection
} -body {
    set res0 [::_test_tmp::getPrimarySelection]
    set int2 slave2
    set int2 child2
    ::safe::interpCreate $int2
    ::safe::loadTk $int2
    $int2 eval $::_test_tmp::script
    $int2 eval ::_test_tmp::tryText
    set res1 [$int2 eval ::_test_tmp::getPrimarySelection]
    set res2 [::_test_tmp::getPrimarySelection]
    set res3 $res0--$res1--$res2
} -cleanup {
    interp delete $int2
    destroy {*}[winfo children .]
    unset int2 res0 res1 res2 res3
    ::_test_tmp::clearPrimarySelection
} -result {OLD_VALUE----OLD_VALUE}

test safePrimarySelection-6.2 {IMPORTANT, safe slave interpreter, entry, existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-6.2 {IMPORTANT, safe interpreter, entry, existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::setPrimarySelection
} -body {
    set res0 [::_test_tmp::getPrimarySelection]
    set int2 slave2
    set int2 child2
    ::safe::interpCreate $int2
    ::safe::loadTk $int2
    $int2 eval $::_test_tmp::script
    $int2 eval ::_test_tmp::tryEntry
    set res1 [$int2 eval ::_test_tmp::getPrimarySelection]
    set res2 [::_test_tmp::getPrimarySelection]
    set res3 $res0--$res1--$res2
} -cleanup {
    interp delete $int2
    destroy {*}[winfo children .]
    unset int2 res0 res1 res2 res3
    ::_test_tmp::clearPrimarySelection
} -result {OLD_VALUE----OLD_VALUE}

test safePrimarySelection-6.3 {IMPORTANT, safe slave interpreter, ttk::entry, existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-6.3 {IMPORTANT, safe interpreter, ttk::entry, existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::setPrimarySelection
} -body {
    set res0 [::_test_tmp::getPrimarySelection]
    set int2 slave2
    set int2 child2
    ::safe::interpCreate $int2
    ::safe::loadTk $int2
    $int2 eval $::_test_tmp::script
    $int2 eval ::_test_tmp::tryTtkEntry
    set res1 [$int2 eval ::_test_tmp::getPrimarySelection]
    set res2 [::_test_tmp::getPrimarySelection]
    set res3 $res0--$res1--$res2
} -cleanup {
    interp delete $int2
    destroy {*}[winfo children .]
    unset int2 res0 res1 res2 res3
    ::_test_tmp::clearPrimarySelection
} -result {OLD_VALUE----OLD_VALUE}

test safePrimarySelection-6.4 {IMPORTANT, safe slave interpreter, listbox, existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-6.4 {IMPORTANT, safe interpreter, listbox, existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::setPrimarySelection
} -body {
    set res0 [::_test_tmp::getPrimarySelection]
    set int2 slave2
    set int2 child2
    ::safe::interpCreate $int2
    ::safe::loadTk $int2
    $int2 eval $::_test_tmp::script
    $int2 eval ::_test_tmp::tryListbox
    set res1 [$int2 eval ::_test_tmp::getPrimarySelection]
    set res2 [::_test_tmp::getPrimarySelection]
    set res3 $res0--$res1--$res2
} -cleanup {
    interp delete $int2
    destroy {*}[winfo children .]
    unset int2 res0 res1 res2 res3
    ::_test_tmp::clearPrimarySelection
} -result {OLD_VALUE----OLD_VALUE}

test safePrimarySelection-6.5 {IMPORTANT, safe slave interpreter, spinbox as entry, existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-6.5 {IMPORTANT, safe interpreter, spinbox as entry, existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::setPrimarySelection
} -body {
    set res0 [::_test_tmp::getPrimarySelection]
    set int2 slave2
    set int2 child2
    ::safe::interpCreate $int2
    ::safe::loadTk $int2
    $int2 eval $::_test_tmp::script
    $int2 eval ::_test_tmp::trySpinbox 1
    set res1 [$int2 eval ::_test_tmp::getPrimarySelection]
    set res2 [::_test_tmp::getPrimarySelection]
    set res3 $res0--$res1--$res2
} -cleanup {
    interp delete $int2
    destroy {*}[winfo children .]
    unset int2 res0 res1 res2 res3
    ::_test_tmp::clearPrimarySelection
} -result {OLD_VALUE----OLD_VALUE}

test safePrimarySelection-6.6 {IMPORTANT, safe slave interpreter, spinbox spun, existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-6.6 {IMPORTANT, safe interpreter, spinbox spun, existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::setPrimarySelection
} -body {
    set res0 [::_test_tmp::getPrimarySelection]
    set int2 slave2
    set int2 child2
    ::safe::interpCreate $int2
    ::safe::loadTk $int2
    $int2 eval $::_test_tmp::script
    $int2 eval ::_test_tmp::trySpinbox 2
    set res1 [$int2 eval ::_test_tmp::getPrimarySelection]
    set res2 [::_test_tmp::getPrimarySelection]
    set res3 $res0--$res1--$res2
} -cleanup {
    interp delete $int2
    destroy {*}[winfo children .]
    unset int2 res0 res1 res2 res3
    ::_test_tmp::clearPrimarySelection
} -result {OLD_VALUE----OLD_VALUE}

test safePrimarySelection-6.7 {IMPORTANT, safe slave interpreter, spinbox spun/selected/spun, existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-6.7 {IMPORTANT, safe interpreter, spinbox spun/selected/spun, existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::setPrimarySelection
} -body {
    set res0 [::_test_tmp::getPrimarySelection]
    set int2 slave2
    set int2 child2
    ::safe::interpCreate $int2
    ::safe::loadTk $int2
    $int2 eval $::_test_tmp::script
    $int2 eval ::_test_tmp::trySpinbox 3
    set res1 [$int2 eval ::_test_tmp::getPrimarySelection]
    set res2 [::_test_tmp::getPrimarySelection]
    set res3 $res0--$res1--$res2
} -cleanup {
    interp delete $int2
    destroy {*}[winfo children .]
    unset int2 res0 res1 res2 res3
    ::_test_tmp::clearPrimarySelection
} -result {OLD_VALUE----OLD_VALUE}

test safePrimarySelection-6.8 {IMPORTANT, safe slave interpreter, ttk::spinbox as entry, existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-6.8 {IMPORTANT, safe interpreter, ttk::spinbox as entry, existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::setPrimarySelection
} -body {
    set res0 [::_test_tmp::getPrimarySelection]
    set int2 slave2
    set int2 child2
    ::safe::interpCreate $int2
    ::safe::loadTk $int2
    $int2 eval $::_test_tmp::script
    $int2 eval ::_test_tmp::tryTtkSpinbox 1
    set res1 [$int2 eval ::_test_tmp::getPrimarySelection]
    set res2 [::_test_tmp::getPrimarySelection]
    set res3 $res0--$res1--$res2
} -cleanup {
    interp delete $int2
    destroy {*}[winfo children .]
    unset int2 res0 res1 res2 res3
    ::_test_tmp::clearPrimarySelection
} -result {OLD_VALUE----OLD_VALUE}

test safePrimarySelection-6.9 {IMPORTANT, safe slave interpreter, ttk::spinbox spun, existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-6.9 {IMPORTANT, safe interpreter, ttk::spinbox spun, existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::setPrimarySelection
} -body {
    set res0 [::_test_tmp::getPrimarySelection]
    set int2 slave2
    set int2 child2
    ::safe::interpCreate $int2
    ::safe::loadTk $int2
    $int2 eval $::_test_tmp::script
    $int2 eval ::_test_tmp::tryTtkSpinbox 2
    set res1 [$int2 eval ::_test_tmp::getPrimarySelection]
    set res2 [::_test_tmp::getPrimarySelection]
    set res3 $res0--$res1--$res2
} -cleanup {
    interp delete $int2
    destroy {*}[winfo children .]
    unset int2 res0 res1 res2 res3
    ::_test_tmp::clearPrimarySelection
} -result {OLD_VALUE----OLD_VALUE}

test safePrimarySelection-6.10 {IMPORTANT, safe slave interpreter, ttk::spinbox spun/selected/spun, existing selection} -setup {
    catch {interp delete slave2}
test safePrimarySelection-6.10 {IMPORTANT, safe interpreter, ttk::spinbox spun/selected/spun, existing selection} -setup {
    catch {interp delete child2}
    destroy {*}[winfo children .]
    ::_test_tmp::setPrimarySelection
} -body {
    set res0 [::_test_tmp::getPrimarySelection]
    set int2 slave2
    set int2 child2
    ::safe::interpCreate $int2
    ::safe::loadTk $int2
    $int2 eval $::_test_tmp::script
    $int2 eval ::_test_tmp::tryTtkSpinbox 3
    set res1 [$int2 eval ::_test_tmp::getPrimarySelection]
    set res2 [::_test_tmp::getPrimarySelection]
    set res3 $res0--$res1--$res2
Changes to tests/scale.test.
1
2
3
4
5
6



7
8
9
10
11
12
13
1
2
3



4
5
6
7
8
9
10
11
12
13



-
-
-
+
+
+







# This file is a Tcl script to test out the "scale" command
# of Tk.  It is organized in the standard fashion for Tcl tests.
#
# Copyright (c) 1994 The Regents of the University of California.
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1994 The Regents of the University of California.
# Copyright © 1994-1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
namespace import ::tcltest::*
eval tcltest::configure $argv
tcltest::loadTestedCommands

42
43
44
45
46
47
48
49

50
51
52
53
54
55
56
42
43
44
45
46
47
48

49
50
51
52
53
54
55
56







-
+







        .s configure -background non-existent
} -returnCodes error -result {unknown color name "non-existent"}
test scale-1.5 {configuration options} -body {
    .s configure -bd 4
    .s cget -bd
} -cleanup {
    .s configure -bd [lindex [.s configure -bd] 3]
} -result {4}
} -result 4
test scale-1.6 {configuration options} -body {
        .s configure -bd badValue
} -returnCodes error -result {bad screen distance "badValue"}
test scale-1.7 {configuration options} -body {
    .s configure -bigincrement 12.5
    .s cget -bigincrement
} -cleanup {
69
70
71
72
73
74
75
76

77
78
79
80
81
82
83
69
70
71
72
73
74
75

76
77
78
79
80
81
82
83







-
+







        .s configure -bg non-existent
} -returnCodes error -result {unknown color name "non-existent"}
test scale-1.11 {configuration options} -body {
    .s configure -borderwidth 1.3
    .s cget -borderwidth
} -cleanup {
    .s configure -borderwidth [lindex [.s configure -borderwidth] 3]
} -result {1}
} -result 1
test scale-1.12 {configuration options} -body {
        .s configure -borderwidth badValue
} -returnCodes error -result {bad screen distance "badValue"}
test scale-1.13 {configuration options} -body {
    .s configure -command {set x}
    .s cget -command
} -cleanup {
93
94
95
96
97
98
99
100

101
102
103
104
105
106
107
93
94
95
96
97
98
99

100
101
102
103
104
105
106
107







-
+







        .s configure -cursor badValue
} -returnCodes error -result {bad cursor spec "badValue"}
test scale-1.17 {configuration options} -body {
    .s configure -digits 5
    .s cget -digits
} -cleanup {
    .s configure -digits [lindex [.s configure -digits] 3]
} -result {5}
} -result 5
test scale-1.18 {configuration options} -body {
        .s configure -digits badValue
} -returnCodes error -result {expected integer but got "badValue"}
test scale-1.19 {configuration options} -body {
    .s configure -fg #00ff00
    .s cget -fg
} -cleanup {
153
154
155
156
157
158
159
160

161
162
163
164
165
166
167
168
169
170
171
172
173
174
175

176
177
178
179
180
181
182
153
154
155
156
157
158
159

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174

175
176
177
178
179
180
181
182







-
+














-
+







        .s configure -highlightcolor non-existent
} -returnCodes error -result {unknown color name "non-existent"}
test scale-1.31 {configuration options} -body {
    .s configure -highlightthickness 2
    .s cget -highlightthickness
} -cleanup {
    .s configure -highlightthickness [lindex [.s configure -highlightthickness] 3]
} -result {2}
} -result 2
test scale-1.32 {configuration options} -body {
        .s configure -highlightthickness badValue
} -returnCodes error -result {bad screen distance "badValue"}
test scale-1.33 {configuration options} -body {
    .s configure -label {Some text}
    .s cget -label
} -cleanup {
    .s configure -label [lindex [.s configure -label] 3]
} -result {Some text}
test scale-1.35 {configuration options} -body {
    .s configure -length 130
    .s cget -length
} -cleanup {
    .s configure -length [lindex [.s configure -length] 3]
} -result {130}
} -result 130
test scale-1.36 {configuration options} -body {
        .s configure -length badValue
} -returnCodes error -result {bad screen distance "badValue"}
test scale-1.37 {configuration options} -body {
    .s configure -orient horizontal
    .s cget -orient
} -cleanup {
201
202
203
204
205
206
207
208

209
210
211
212
213
214
215
216
217

218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235

236
237
238
239
240
241
242
243
244

245
246
247
248
249
250
251
201
202
203
204
205
206
207

208
209
210
211
212
213
214
215
216

217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234

235
236
237
238
239
240
241
242
243

244
245
246
247
248
249
250
251







-
+








-
+

















-
+








-
+







        .s configure -relief badValue
} -returnCodes error -result {bad relief "badValue": must be flat, groove, raised, ridge, solid, or sunken}
test scale-1.43 {configuration options} -body {
    .s configure -repeatdelay 14
    .s cget -repeatdelay
} -cleanup {
    .s configure -repeatdelay [lindex [.s configure -repeatdelay] 3]
} -result {14}
} -result 14
test scale-1.44 {configuration options} -body {
        .s configure -repeatdelay bogus
} -returnCodes error -result {expected integer but got "bogus"}
test scale-1.45 {configuration options} -body {
    .s configure -repeatinterval 14
    .s cget -repeatinterval
} -cleanup {
    .s configure -repeatinterval [lindex [.s configure -repeatinterval] 3]
} -result {14}
} -result 14
test scale-1.46 {configuration options} -body {
        .s configure -repeatinterval bogus
} -returnCodes error -result {expected integer but got "bogus"}
test scale-1.47 {configuration options} -body {
    .s configure -resolution 2.0
    .s cget -resolution
} -cleanup {
    .s configure -resolution [lindex [.s configure -resolution] 3]
} -result {2.0}
test scale-1.48 {configuration options} -body {
        .s configure -resolution badValue
} -returnCodes error -result {expected floating-point number but got "badValue"}
test scale-1.49 {configuration options} -body {
    .s configure -showvalue 0
    .s cget -showvalue
} -cleanup {
    .s configure -showvalue [lindex [.s configure -showvalue] 3]
} -result {0}
} -result 0
test scale-1.50 {configuration options} -body {
        .s configure -showvalue badValue
} -returnCodes error -result {expected boolean value but got "badValue"}
test scale-1.51 {configuration options} -body {
    .s configure -sliderlength 86
    .s cget -sliderlength
} -cleanup {
    .s configure -sliderlength [lindex [.s configure -sliderlength] 3]
} -result {86}
} -result 86
test scale-1.52 {configuration options} -body {
        .s configure -sliderlength badValue
} -returnCodes error -result {bad screen distance "badValue"}
test scale-1.53 {configuration options} -body {
    .s configure -sliderrelief raised
    .s cget -sliderrelief
} -cleanup {
309
310
311
312
313
314
315
316

317
318
319
320
321
322
323
324
325
326
327

328
329
330
331
332
333
334
309
310
311
312
313
314
315

316
317
318
319
320
321
322
323
324
325
326

327
328
329
330
331
332
333
334







-
+










-
+







    .s configure -variable [lindex [.s configure -variable] 3]
} -result {x}
test scale-1.69 {configuration options} -body {
    .s configure -width 32
    .s cget -width
} -cleanup {
    .s configure -width [lindex [.s configure -width] 3]
} -result {32}
} -result 32
test scale-1.70 {configuration options} -body {
        .s configure -width badValue
} -returnCodes error -result {bad screen distance "badValue"}
destroy .s


test scale-2.1 {Tk_ScaleCmd procedure} -body {
    scale
} -returnCodes error -result {wrong # args: should be "scale pathName ?-option value ...?"}
test scale-2.2 {Tk_ScaleCmd procedure} -body {
    scale foo 
    scale foo
} -returnCodes error -result {bad window path name "foo"}
test scale-2.3 {Tk_ScaleCmd procedure} -body {
    catch {scale foo}
    winfo child .
} -result {}
test scale-2.4 {Tk_ScaleCmd procedure} -body {
    scale .s -gorp dumb
355
356
357
358
359
360
361
362

363
364
365
366
367
368
369
355
356
357
358
359
360
361

362
363
364
365
366
367
368
369







-
+







} -returnCodes error -result {wrong # args: should be ".s cget option"}
test scale-3.4 {ScaleWidgetCmd procedure, cget option} -body {
    .s cget -gorp
} -returnCodes error -result {unknown option "-gorp"}
test scale-3.5 {ScaleWidgetCmd procedure, cget option} -body {
    .s configure -highlightthickness 2
    .s cget -highlightthickness
} -result {2}
} -result 2
test scale-3.6 {ScaleWidgetCmd procedure, configure option} -body {
    list [llength [.s configure]] [lindex [.s configure] 6]
} -result {33 {-command command Command {} {}}}
test scale-3.7 {ScaleWidgetCmd procedure, configure option} -body {
    .s configure -foo
} -returnCodes error -result {unknown option "-foo"}
test scale-3.8 {ScaleWidgetCmd procedure, configure option} -body {
462
463
464
465
466
467
468
469

470
471
472
473
474
475
476
462
463
464
465
466
467
468

469
470
471
472
473
474
475
476







-
+







    .s configure -from 100 -to 200 -orient vertical -resolution 1
    update
    .s set 118
    .s configure -state disabled
    .s set 181
    .s configure -state normal
    .s get
} -result {118}
} -result 118
test scale-3.29 {ScaleWidgetCmd procedure} -body {
    .s dumb
} -returnCodes error -result {bad option "dumb": must be cget, configure, coords, get, identify, or set}
test scale-3.30 {ScaleWidgetCmd procedure} -body {
    .s c
} -returnCodes error -result {ambiguous option "c": must be cget, configure, coords, get, identify, or set}
test scale-3.31 {ScaleWidgetCmd procedure} -body {
584
585
586
587
588
589
590
591

592
593
594
595
596

597
598
599
600
601

602
603
604
605
606

607
608
609
610
611

612
613
614
615
616
617
618
619
620

621
622
623
624
625
626
627
584
585
586
587
588
589
590

591
592
593
594
595

596
597
598
599
600

601
602
603
604
605

606
607
608
609
610

611
612
613
614
615
616
617
618
619

620
621
622
623
624
625
626
627







-
+




-
+




-
+




-
+




-
+








-
+







destroy .s
scale .s -orient horizontal -length 200
pack .s
test scale-6.1 {ComputeFormat procedure} -body {
    .s configure -from 10 -to 100 -resolution 10
    .s set 49.3
    .s get
} -result {50}
} -result 50
test scale-6.2 {ComputeFormat procedure} -body {
    .s configure -from 100 -to 1000 -resolution 100
    .s set 493
    .s get
} -result {500}
} -result 500
test scale-6.3 {ComputeFormat procedure} -body {
    .s configure -from 1000 -to 10000 -resolution 1000
    .s set 4930
    .s get
} -result {5000}
} -result 5000
test scale-6.4 {ComputeFormat procedure} -body {
    .s configure -from 10000 -to 100000 -resolution 10000
    .s set 49000
    .s get
} -result {50000}
} -result 50000
test scale-6.5 {ComputeFormat procedure} -body {
    .s configure -from 100000 -to 1000000 -resolution 100000
    .s set 493000
    .s get
} -result {500000}
} -result 500000
test scale-6.6 {ComputeFormat procedure} -constraints {
	nonPortable
} -body {
    # This test is non-portable because some platforms format the
    # result as 5e+06.
    .s configure -from 1000000 -to 10000000 -resolution 1000000
    .s set 4930000
    .s get
} -result {5000000}
} -result 5000000
test scale-6.7 {ComputeFormat procedure} -body {
    .s configure -from 1000000000 -to 10000000000 -resolution 1000000000
    .s set 4930000000
    expr {[.s get] == 5.0e+09}
} -result 1
test scale-6.8 {ComputeFormat procedure} -body {
    .s configure -from .1 -to 1 -resolution .1
648
649
650
651
652
653
654
655

656
657
658
659
660
661
662
663
664
665

666
667
668
669
670

671
672
673
674
675

676
677
678
679
680
681
682
648
649
650
651
652
653
654

655
656
657
658
659
660
661
662
663
664

665
666
667
668
669

670
671
672
673
674

675
676
677
678
679
680
681
682







-
+









-
+




-
+




-
+







    .s set .00006
    .s get
} -result {0.00006}
test scale-6.13 {ComputeFormat procedure} -body {
    .s configure -from .000001 -to .00001 -resolution .000001
    .s set .000006
    expr {[.s get] == 6.0e-06}
} -result {1}
} -result 1
test scale-6.14 {ComputeFormat procedure} -body {
    .s configure -to .00001 -from .0001 -resolution .00001
    .s set .00006
    .s get
} -result {0.00006}
test scale-6.15 {ComputeFormat procedure} -body {
    .s configure -to .000001 -from .00001 -resolution .000001
    .s set .000006
    expr {[.s get] == 6.0e-06}
} -result {1}
} -result 1
test scale-6.16 {ComputeFormat procedure} -body {
    .s configure -from .00001 -to .0001 -resolution .00001 -digits 1
    .s set .00006
    expr {[.s get] == 6e-05}
} -result {1}
} -result 1
test scale-6.17 {ComputeFormat procedure} -body {
    .s configure -from 10000000 -to 100000000 -resolution 10000000 -digits 3
    .s set 49300000
    .s get
} -result {50000000}
} -result 50000000
test scale-6.18 {ComputeFormat procedure} -body {
    .s configure -length 200 -from 0 -to 10 -resolution 0 -digits 0
    .s set .111111111
    .s get
} -result {0.11}
test scale-6.19 {ComputeFormat procedure} -body {
    .s configure -length 200 -from 1000 -to 1002 -resolution 0 -digits 0
1131
1132
1133
1134
1135
1136
1137
1138

1139
1140
1141
1142
1143
1144

1145
1146
1147
1148
1149
1150
1151

1152
1153
1154
1155
1156
1157

1158
1159
1160
1161
1162
1163
1164
1131
1132
1133
1134
1135
1136
1137

1138
1139
1140
1141
1142
1143

1144
1145
1146
1147
1148
1149
1150

1151
1152
1153
1154
1155
1156

1157
1158
1159
1160
1161
1162
1163
1164







-
+





-
+






-
+





-
+







} -result 24

test scale-14.5 {RoundValueToResolution procedure} -body {
    .s configure -from -100 -to 0 -sliderlength 10 -length 114 -bd 2 \
        -orient horizontal -resolution 4.0
    update
    .s get 84 152
} -result {-28}
} -result -28
test scale-14.6 {RoundValueToResolution procedure} -body {
    .s configure -from -100 -to 0 -sliderlength 10 -length 114 -bd 2 \
        -orient horizontal -resolution 4.0
    update
    .s get 86 152
} -result {-24}
} -result -24

test scale-14.7 {RoundValueToResolution procedure} -body {
    .s configure -from 0 -to -100 -sliderlength 10 -length 114 -bd 2 \
        -orient horizontal -resolution 4.0
    update
    .s get 84 152
} -result {-72}
} -result -72
test scale-14.8 {RoundValueToResolution procedure} -body {
    .s configure -from 0 -to -100 -sliderlength 10 -length 114 -bd 2 \
        -orient horizontal -resolution 4.0
    update
    .s get 86 152
} -result {-76}
} -result -76

test scale-14.9 {RoundValueToResolution procedure} -body {
    .s configure -from 0 -to 2.25  -sliderlength 10 -length 114 -bd 2 \
        -orient horizontal -resolution 0
    update
    .s get 84 152
} -result {1.64}
1201
1202
1203
1204
1205
1206
1207
1208

1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229

1230
1231
1232
1233
1234
1235
1236
1237
1238

1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259

1260
1261
1262
1263
1264
1265
1266
1201
1202
1203
1204
1205
1206
1207

1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228

1229
1230
1231
1232
1233
1234
1235
1236
1237

1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258

1259
1260
1261
1262
1263
1264
1265
1266







-
+




















-
+








-
+




















-
+







    update
} -body {
    .s configure -length 400 -bd 0 -from 1 -to 9 -resolution 2 -tickinterval 1
    update
    .s get 200 0
} -cleanup {
    destroy .s
} -result {5}
} -result 5
test scale-14a.2 {RoundValueToResolution, RoundIntervalToResolution procedures} -setup {
    pack [scale .s -orient horizontal]
    update
} -body {
    .s configure -length 400 -bd 0 -from -1.5 -to 1.5 -resolution 1 \
            -tickinterval 1 -digits 2
    update
    .s get 250 0
} -cleanup {
    destroy .s
} -result {0.5}


test scale-15.1 {ScaleVarProc procedure} -setup {
    deleteWindows
} -body {
    set y -130
    scale .s -from 0 -to -200 -variable y -orient horizontal -length 150
    pack .s
    return $y
} -result {-130}
} -result -130
test scale-15.2 {ScaleVarProc procedure} -setup {
    deleteWindows
} -body {
    set y -130
    scale .s -from -200 -to 0 -variable y -orient horizontal -length 150
    pack .s
    set y -87
    .s get
} -result {-87}
} -result -87
test scale-15.3 {ScaleVarProc procedure} -setup {
    deleteWindows
} -body {
    set y -130
    scale .s -from -200 -to 0 -variable y -orient horizontal -length 150
    pack .s
    set y 40q
} -cleanup {
    deleteWindows
} -returnCodes error -result {can't set "y": can't assign non-numeric value to scale variable}
test scale-15.4 {ScaleVarProc procedure} -setup {
    deleteWindows
} -body {
    set y -130
    scale .s -from -200 -to 0 -variable y -orient horizontal -length 150
    pack .s
    catch {set y 40q}
    .s get
} -cleanup {
    deleteWindows
} -result {-130}
} -result -130
test scale-15.5 {ScaleVarProc procedure} -setup {
    deleteWindows
} -body {
    set y 1
    scale .s -from 1 -to 0 -variable y -orient horizontal -length 150
    pack .s
    set y x
1340
1341
1342
1343
1344
1345
1346
1347

1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367

1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388

1389
1390
1391
1392
1393
1394
1395
1340
1341
1342
1343
1344
1345
1346

1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366

1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387

1388
1389
1390
1391
1392
1393
1394
1395







-
+



















-
+




















-
+








    # Bug 4833 changed the result to realize that x should pick up
    # a value from the scale.  In an FPE occurs, it is due to the
    # lack of errno being set to 0 by some libc's. (see bug 4942)
    return $x
} -cleanup {
    deleteWindows
} -result {100}
} -result 100


test scale-18.1 {DestroyScale, -cursor option [Bug: 3897]} -setup {
    deleteWindows
} -body {
    scale .s -cursor trek
    destroy .s
} -result {}

test scale-18.2 {Scale button 1 events [Bug 787065]} -setup {
    destroy .s
    set ::error {}
    proc bgerror {args} {set ::error $args}
} -body {
    set y 5
    scale .s -from 0 -to 10 -variable y -orient horizontal -length 150
    pack .s
    tkwait visibility .s
    list [catch {
        event generate .s <1> -x 0 -y 0
        event generate .s <Button-1> -x 0 -y 0
        event generate .s <ButtonRelease-1> -x 0 -y 0
        update
        set ::error
    } msg] $msg
} -cleanup {
    unset ::error
    rename bgerror {}
    destroy .s
} -result {0 {}}

test scale-18.3 {Scale button 2 events [Bug 787065]} -setup {
    destroy .s
    set ::error {}
    proc bgerror {args} {set ::error $args}
} -body {
    set y 5
    scale .s -from 0 -to 10 -variable y -orient horizontal -length 150
    pack .s
    tkwait visibility .s
    list [catch {
        event generate .s <2> -x 0 -y 0
        event generate .s <Button-2> -x 0 -y 0
        event generate .s <ButtonRelease-2> -x 0 -y 0
        update
        set ::error
    } msg] $msg
} -cleanup {
    unset ::error
    rename bgerror {}
1407
1408
1409
1410
1411
1412
1413
1414

1415
1416
1417

1418
1419
1420

1421
1422
1423

1424
1425
1426
1427
1428
1429
1430
1407
1408
1409
1410
1411
1412
1413

1414
1415
1416

1417
1418
1419

1420
1421
1422

1423
1424
1425
1426
1427
1428
1429
1430







-
+


-
+


-
+


-
+







        scale .s3 -from 100 -to 0 -resolution 1  -variable x3 -digits 4 -orient horizontal -length 100
        scale .s4 -from 100 -to 0 -resolution -1 -variable x4 -digits 4 -orient horizontal -length 100
        pack .s1 .s2 .s3 .s4 -side left
        update
    } \
    -body {
        foreach {x y} [.s1 coord 50] {}
        event generate .s1 <1> -x $x -y $y
        event generate .s1 <Button-1> -x $x -y $y
        event generate .s1 <ButtonRelease-1> -x $x -y $y
        foreach {x y} [.s2 coord 50] {}
        event generate .s2 <1> -x $x -y $y
        event generate .s2 <Button-1> -x $x -y $y
        event generate .s2 <ButtonRelease-1> -x $x -y $y
        foreach {x y} [.s3 coord 50] {}
        event generate .s3 <1> -x $x -y $y
        event generate .s3 <Button-1> -x $x -y $y
        event generate .s3 <ButtonRelease-1> -x $x -y $y
        foreach {x y} [.s4 coord 50] {}
        event generate .s4 <1> -x $x -y $y
        event generate .s4 <Button-1> -x $x -y $y
        event generate .s4 <ButtonRelease-1> -x $x -y $y
        update
        list $x1 $x2 $x3 $x4
    } \
    -cleanup {
        unset x1 x2 x3 x4 x y
        destroy .s1 .s2 .s3 .s4
Changes to tests/scrollbar.test.
1
2
3
4
5
6
7



8
9
10

11
12




13
14
15
16
17
18
19
20
21
22
23
24
25
26

27
28
29
30
31
32
33
1
2
3
4



5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

30
31
32
33
34
35
36
37




-
-
-
+
+
+


-
+


+
+
+
+













-
+







# This file is a Tcl script to test out scrollbar widgets and
# the "scrollbar" command of Tk.  It is organized in the standard
# fashion for Tcl tests.
#
# Copyright (c) 1994 The Regents of the University of California.
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1994 The Regents of the University of California.
# Copyright © 1994-1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.1
package require tcltest 2.2
eval tcltest::configure $argv
tcltest::loadTestedCommands

testConstraint failsOnUbuntu [expr {![info exists ::env(CI)] || ![string match Linux $::tcl_platform(os)]}]
testConstraint failsOnXQuarz [expr {$tcl_platform(os) ne "Darwin" || [tk windowingsystem] ne "x11" }]
testConstraint nodeprecated [expr {"nodeprecated" ni [tk::pkgconfig list]}]

proc scroll args {
    global scrollInfo
    set scrollInfo $args
}

proc getTroughSize {w} {
    if {[testConstraint testmetrics]} {
        # Only Windows has [testmetrics]
	if [string match v* [$w cget -orient]] {
	    return [expr {[winfo height $w] - 2*[testmetrics cyvscroll $w]}]
	} else {
	    return [expr {[winfo width $w] - 2*[testmetrics cxhscroll $w]}]
	}	    
	}
    } else {
        if {[tk windowingsystem] eq "x11"} {
            # Calculations here assume that the arrow area is a square.
	    if [string match v* [$w cget -orient]] {
	        return [expr {[winfo height $w] \
		        - ([winfo width $w] \
			    - [$w cget -highlightthickness] \
56
57
58
59
60
61
62
63

64
65
66
67
68
69
70
60
61
62
63
64
65
66

67
68
69
70
71
72
73
74







-
+







# XXX Note: this test file is woefully incomplete.  Right now there are
# only bits and pieces of tests.  Please make this file more complete
# as you fix bugs and add features.

foreach {width height} [wm minsize .] {
    set height [expr {($height < 200) ? 200 : $height}]
    set width [expr {($width < 1) ? 1 : $width}]
} 
}

frame .f -height $height -width $width
pack .f -side left
scrollbar .s
pack .s -side right -fill y
update
set i 1
193
194
195
196
197
198
199
200

201
202
203
204
205
206
207
197
198
199
200
201
202
203

204
205
206
207
208
209
210
211







-
+







} {}
test scrollbar-3.14.1 {ScrollbarWidgetCmd procedure, "cget" option} emptyTest {
    # empty test; duplicated scrollbar-3.13
} {}
destroy .s2
test scrollbar-3.15 {ScrollbarWidgetCmd procedure, "configure" option} {
    llength [.s configure]
} {20}
} 20
test scrollbar-3.16 {ScrollbarWidgetCmd procedure, "configure" option} {
    list [catch {.s configure -bad} msg] $msg
} {1 {unknown option "-bad"}}
test scrollbar-3.17 {ScrollbarWidgetCmd procedure, "configure" option} {
    .s configure -orient
} {-orient orient Orient vertical vertical}
test scrollbar-3.18 {ScrollbarWidgetCmd procedure, "configure" option} {
226
227
228
229
230
231
232
233

234
235
236
237
238
239
240
230
231
232
233
234
235
236

237
238
239
240
241
242
243
244







-
+







    list [catch {.s delta 18 xxyz} msg] $msg
} {1 {expected integer but got "xxyz"}}
test scrollbar-3.24 {ScrollbarWidgetCmd procedure, "delta" option} {
    list [catch {.s delta 18 xxyz} msg] $msg
} {1 {expected integer but got "xxyz"}}
test scrollbar-3.25 {ScrollbarWidgetCmd procedure, "delta" option} {
    format {%.6g} [.s delta 20 0]
} {0}
} 0
test scrollbar-3.26 {ScrollbarWidgetCmd procedure, "delta" option} {
    format {%.6g} [.s delta 0 20]
} [format %.6g [expr {20.0/([getTroughSize .s]-1)}]]
test scrollbar-3.27 {ScrollbarWidgetCmd procedure, "delta" option} {
    format {%.6g} [.s delta 0 -20]
} [format %.6g [expr {-20.0/([getTroughSize .s]-1)}]]
test scrollbar-3.28 {ScrollbarWidgetCmd procedure, "delta" option} {
258
259
260
261
262
263
264
265

266
267
268

269
270
271
272
273

274
275

276
277
278
279


280
281
282
283
284
285
286
262
263
264
265
266
267
268

269
270
271

272
273
274
275
276

277
278

279
280
281


282
283
284
285
286
287
288
289
290







-
+


-
+




-
+

-
+


-
-
+
+







    list [catch {.s fraction silly 24} msg] $msg
} {1 {expected integer but got "silly"}}
test scrollbar-3.32 {ScrollbarWidgetCmd procedure, "fraction" option} {
    list [catch {.s fraction 24 bogus} msg] $msg
} {1 {expected integer but got "bogus"}}
test scrollbar-3.33 {ScrollbarWidgetCmd procedure, "fraction" option} {
    format {%.6g} [.s fraction 0 0]
} {0}
} 0
test scrollbar-3.34 {ScrollbarWidgetCmd procedure, "fraction" option} {
    format {%.6g} [.s fraction 0 1000]
} {1}
} 1
test scrollbar-3.35 {ScrollbarWidgetCmd procedure, "fraction" option} {
    format {%.6g} [.s fraction 4 21]
} [format %.6g [expr {(21.0 - ([winfo height .s] - [getTroughSize .s])/2.0) \
       /([getTroughSize .s] - 1)}]]
test scrollbar-3.36 {ScrollbarWidgetCmd procedure, "fraction" option} x11 {
test scrollbar-3.36 {ScrollbarWidgetCmd procedure, "fraction" option} {x11 failsOnUbuntu failsOnXQuarz} {
    format {%.6g} [.s fraction 4 179]
} {1}
} 1
test scrollbar-3.37 {ScrollbarWidgetCmd procedure, "fraction" option} {testmetrics} {
    format {%.6g} [.s fraction 4 [expr {200 - [testmetrics cyvscroll .s]}]]
} {1}
test scrollbar-3.38 {ScrollbarWidgetCmd procedure, "fraction" option} x11 {
} 1
test scrollbar-3.38 {ScrollbarWidgetCmd procedure, "fraction" option} {x11 failsOnUbuntu failsOnXQuarz} {
    format {%.6g} [.s fraction 4 178]
} {0.993711}
test scrollbar-3.39 {ScrollbarWidgetCmd procedure, "fraction" option} {testmetrics win} {
    expr {
    [format {%.6g} [.s fraction 4 [expr {200 - [testmetrics cyvscroll .s] - 2}]]]
	== [format %g [expr {(200.0 - [testmetrics cyvscroll .s]*2 - 2)
			   / ($height - 1 - [testmetrics cyvscroll .s]*2)}]]}
305
306
307
308
309
310
311
312

313
314
315
316
317

318
319
320
321
322
323
324
309
310
311
312
313
314
315

316
317
318
319
320

321
322
323
324
325
326
327
328







-
+




-
+







        # macOS aqua
        place configure .t.s -width [expr {2*([.t.s cget -highlightthickness] + [.t.s cget -bd])}]
    }
}
update
test scrollbar-3.42 {ScrollbarWidgetCmd procedure, "fraction" option} {
    format {%.6g} [.t.s fraction 100 0]
} {0}
} 0
destroy .t
test scrollbar-3.43 {ScrollbarWidgetCmd procedure, "get" option} {
    list [catch {.s get a} msg] $msg
} {1 {wrong # args: should be ".s get"}}
test scrollbar-3.44 {ScrollbarWidgetCmd procedure, "get" option} {
test scrollbar-3.44 {ScrollbarWidgetCmd procedure, "get" option} nodeprecated {
    .s set 100 10 13 14
    .s get
} {100 10 13 14}
test scrollbar-3.45 {ScrollbarWidgetCmd procedure, "get" option} {
    .s set 0.6 0.8
    set result {}
    foreach element [.s get] {
337
338
339
340
341
342
343
344

345
346
347
348
349
350
351
341
342
343
344
345
346
347

348
349
350
351
352
353
354
355







-
+







} {1 {expected integer but got "bogus"}}
test scrollbar-3.49 {ScrollbarWidgetCmd procedure, "identify" option} {
    list [catch {.s identify -1 bogus} msg] $msg
} {1 {expected integer but got "bogus"}}
test scrollbar-3.50.1 {ScrollbarWidgetCmd procedure, "identify" option} notAqua {
    .s identify 5 5
} {arrow1}
test scrollbar-3.50.1 {ScrollbarWidgetCmd procedure, "identify" option} aqua {
test scrollbar-3.50.2 {ScrollbarWidgetCmd procedure, "identify" option} aqua {
    # macOS scrollbars have no arrows nowadays
    .s identify 5 5
} {trough1}
test scrollbar-3.51 {ScrollbarWidgetCmd procedure, "identify" option} {
    .s identify 5 35
} {trough1}
test scrollbar-3.52 {ScrollbarWidgetCmd procedure, "identify" option} {
376
377
378
379
380
381
382
383

384
385
386
387

388
389
390
391

392
393
394
395
396
397
398
399
400
401
402

403
404
405

406
407
408

409
410
411

412
413
414
415


416
417
418
419


420
421
422
423


424
425
426
427
428

429
430
431

432
433
434
435
436
437
438
380
381
382
383
384
385
386

387
388
389
390

391
392
393
394

395
396
397
398
399
400
401
402
403
404
405

406
407
408

409
410
411

412
413
414

415
416
417


418
419
420
421


422
423
424
425


426
427
428
429
430
431

432
433
434

435
436
437
438
439
440
441
442







-
+



-
+



-
+










-
+


-
+


-
+


-
+


-
-
+
+


-
-
+
+


-
-
+
+




-
+


-
+







    set result {}
    foreach element [.s get] {
	lappend result [format %.1f $element]
    }
    set result
} {0.0 0.3}
test scrollbar-3.60 {ScrollbarWidgetCmd procedure, "set" option} {
    .s set 1.1 .4 
    .s set 1.1 .4
    .s get
} {1.0 1.0}
test scrollbar-3.61 {ScrollbarWidgetCmd procedure, "set" option} {
    .s set .5 -.3 
    .s set .5 -.3
    .s get
} {0.5 0.5}
test scrollbar-3.62 {ScrollbarWidgetCmd procedure, "set" option} {
    .s set .5 87 
    .s set .5 87
    .s get
} {0.5 1.0}
test scrollbar-3.63 {ScrollbarWidgetCmd procedure, "set" option} {
    .s set .4 .3
    set result {}
    foreach element [.s get] {
	lappend result [format %.1f $element]
    }
    set result
} {0.4 0.4}
test scrollbar-3.64 {ScrollbarWidgetCmd procedure, "set" option} {
test scrollbar-3.64 {ScrollbarWidgetCmd procedure, "set" option} nodeprecated {
    list [catch {.s set abc def ghi jkl} msg] $msg
} {1 {expected integer but got "abc"}}
test scrollbar-3.65 {ScrollbarWidgetCmd procedure, "set" option} {
test scrollbar-3.65 {ScrollbarWidgetCmd procedure, "set" option} nodeprecated {
    list [catch {.s set 1 def ghi jkl} msg] $msg
} {1 {expected integer but got "def"}}
test scrollbar-3.66 {ScrollbarWidgetCmd procedure, "set" option} {
test scrollbar-3.66 {ScrollbarWidgetCmd procedure, "set" option} nodeprecated {
    list [catch {.s set 1 2 ghi jkl} msg] $msg
} {1 {expected integer but got "ghi"}}
test scrollbar-3.67 {ScrollbarWidgetCmd procedure, "set" option} {
test scrollbar-3.67 {ScrollbarWidgetCmd procedure, "set" option} nodeprecated {
    list [catch {.s set 1 2 3 jkl} msg] $msg
} {1 {expected integer but got "jkl"}}
test scrollbar-3.68 {ScrollbarWidgetCmd procedure, "set" option} {
    .s set -10 50 20 30 
test scrollbar-3.68 {ScrollbarWidgetCmd procedure, "set" option} nodeprecated {
    .s set -10 50 20 30
    .s get
} {0 50 0 0}
test scrollbar-3.69 {ScrollbarWidgetCmd procedure, "set" option} {
    .s set 100 -10 20 30 
test scrollbar-3.69 {ScrollbarWidgetCmd procedure, "set" option} nodeprecated {
    .s set 100 -10 20 30
    .s get
} {100 0 20 30}
test scrollbar-3.70 {ScrollbarWidgetCmd procedure, "set" option} {
    .s set 100 50 30 20 
test scrollbar-3.70 {ScrollbarWidgetCmd procedure, "set" option} nodeprecated {
    .s set 100 50 30 20
    .s get
} {100 50 30 30}
test scrollbar-3.71 {ScrollbarWidgetCmd procedure, "set" option} {
    list [catch {.s set 1 2 3} msg] $msg
} {1 {wrong # args: should be ".s set firstFraction lastFraction" or ".s set totalUnits windowUnits firstUnit lastUnit"}}
} {1 {wrong # args: should be ".s set firstFraction lastFraction"}}
test scrollbar-3.72 {ScrollbarWidgetCmd procedure, "set" option} {
    list [catch {.s set 1 2 3 4 5} msg] $msg
} {1 {wrong # args: should be ".s set firstFraction lastFraction" or ".s set totalUnits windowUnits firstUnit lastUnit"}}
} {1 {wrong # args: should be ".s set firstFraction lastFraction"}}
test scrollbar-3.73 {ScrollbarWidgetCmd procedure} {
    list [catch {.s bogus} msg] $msg
} {1 {bad option "bogus": must be activate, cget, configure, delta, fraction, get, identify, or set}}
test scrollbar-3.74 {ScrollbarWidgetCmd procedure} {
    list [catch {.s c} msg] $msg
} {1 {ambiguous option "c": must be activate, cget, configure, delta, fraction, get, identify, or set}}

487
488
489
490
491
492
493
494

495
496
497
498
499
500
501
502

503
504
505
506
507
508
509
491
492
493
494
495
496
497

498
499
500
501
502
503
504
505

506
507
508
509
510
511
512
513







-
+







-
+







test scrollbar-6.11.1 {ScrollbarPosition procedure} x11 {
    .s identify 8 4
} {arrow1}
test scrollbar-6.11.2 {ScrollbarPosition procedure} aqua {
    # macOS scrollbars have no arrows nowadays
    .s identify 8 4
} {trough1}
test scrollbar-6.12.1 {ScrollbarPosition procedure} x11 {
test scrollbar-6.12.1 {ScrollbarPosition procedure} {x11 failsOnUbuntu failsOnXQuarz} {
    .s identify 8 19
} {arrow1}
test scrollbar-6.12.2 {ScrollbarPosition procedure} aqua {
    # macOS scrollbars have no arrows nowadays
    .s identify 8 19
} {trough1}
test scrollbar-6.14 {ScrollbarPosition procedure} win {
    .s identify [expr {[winfo width .s] / 2}] 0 
    .s identify [expr {[winfo width .s] / 2}] 0
} {arrow1}
test scrollbar-6.15 {ScrollbarPosition procedure} {testmetrics win} {
    .s identify [expr {[winfo width .s] / 2}] [expr {[testmetrics cyvscroll .s] - 1}]
} {arrow1}
test scrollbar-6.16 {ScrollbarPosition procedure} unix {
    .s identify 8 20
} {trough1}
545
546
547
548
549
550
551
552

553
554
555
556
557
558
559
549
550
551
552
553
554
555

556
557
558
559
560
561
562
563







-
+







    .s identify [expr {[winfo width .s] / 2}] [expr {int(.4 / [.s delta 0 1])
						 + [testmetrics cyvscroll .s]}]
} {trough2}
test scrollbar-6.28 {ScrollbarPosition procedure} {testmetrics win} {
    .s identify [expr {[winfo width .s] / 2}] [expr {[winfo height .s]
						 - [testmetrics cyvscroll .s] - 1}]
} {trough2}
test scrollbar-6.29.1 {ScrollbarPosition procedure} x11 {
test scrollbar-6.29.1 {ScrollbarPosition procedure} {x11 failsOnUbuntu failsOnXQuarz} {
    .s identify 8 180
} {arrow2}
test scrollbar-6.29.2 {ScrollbarPosition procedure} aqua {
    # macOS scrollbars have no arrows nowadays
    .s identify 8 180
} {trough2}
test scrollbar-6.30.1 {ScrollbarPosition procedure} x11 {
569
570
571
572
573
574
575
576

577
578
579
580
581
582
583
573
574
575
576
577
578
579

580
581
582
583
584
585
586
587







-
+







} {arrow2}
test scrollbar-6.33 {ScrollbarPosition procedure} win {
    .s identify [expr {[winfo width .s] / 2}] [expr {[winfo height .s] - 1}]
} {arrow2}
test scrollbar-6.34 {ScrollbarPosition procedure} unix {
    .s identify 4 100
} {trough2}
test scrollbar-6.35 {ScrollbarPosition procedure} unix {
test scrollbar-6.35 {ScrollbarPosition procedure} {unix failsOnUbuntu failsOnXQuarz} {
    .s identify 18 100
} {trough2}
test scrollbar-6.37 {ScrollbarPosition procedure} win {
    .s identify 0 100
} {trough2}
test scrollbar-6.38 {ScrollbarPosition procedure} win {
    .s identify [expr {[winfo width .s] - 1}] 100
606
607
608
609
610
611
612
613

614
615

616
617
618
619
620
621
622
610
611
612
613
614
615
616

617
618

619
620
621
622
623
624
625
626







-
+

-
+







} {slider}
test scrollbar-6.41.2 {ScrollbarPosition procedure} aqua {
    # macOS scrollbars have no arrows nowadays
    .t.s identify 82 8
} {trough2}
test scrollbar-6.43 {ScrollbarPosition procedure} {testmetrics win} {
    .t.s identify [expr {int(.4 / [.t.s delta 1 0]) + [testmetrics cxhscroll .t.s]
		       - 1}] [expr {[winfo height .t.s] / 2}] 
		       - 1}] [expr {[winfo height .t.s] / 2}]
} {slider}
test scrollbar-6.44 {ScrollbarPosition procedure} unix {
test scrollbar-6.44 {ScrollbarPosition procedure} {unix failsOnUbuntu failsOnXQuarz} {
    .t.s identify 100 18
} {trough2}
test scrollbar-6.46 {ScrollbarPosition procedure} win {
    .t.s identify 100 [expr {[winfo height .t.s] - 1}]
} {trough2}

test scrollbar-7.1 {EventuallyRedraw} {
641
642
643
644
645
646
647
648

649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669

670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688

689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717

718
719
720
721
722
723
724
725
726
727
728
729
730
731

732
733
734
735
736
737
738
739

740
741
742
743
744
745
746
747
748
749
750
751
752
753
754

755
756
757
758

759
760
761
762

763
764
765
766
767
768
769
770
771
772
773

774
775
776
777

778
779
780
781

782
783
784
785
786
787
788
645
646
647
648
649
650
651

652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672

673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691

692
693
694
695
696
697
698
699
700
701
702
703
704
705














706

707
708
709
710
711
712
713
714
715
716
717
718
719
720

721
722
723
724
725
726
727
728

729
730
731
732
733
734
735
736
737
738
739
740
741
742
743

744
745
746
747

748
749
750
751

752
753
754
755
756
757
758
759
760
761
762

763
764
765
766

767
768
769
770

771
772
773
774
775
776
777
778







-
+




















-
+


















-
+













-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
+













-
+







-
+














-
+



-
+



-
+










-
+



-
+



-
+







    scrollbar .t.f.s -command doit
    pack .t.f -fill both -expand 1
    pack .t.f.s -fill y -expand 1 -side right
    wm geometry .t 100x100
    .t.f.s set 0 .5
    update
    set result [winfo exists .t.f.s]
    event generate .t.f.s <ButtonPress> -button 1 -x [expr {[winfo width .t.f.s] / 2}] -y 5
    event generate .t.f.s <Button> -button 1 -x [expr {[winfo width .t.f.s] / 2}] -y 5
    event generate .t <ButtonRelease> -button 1
    update
    lappend result [winfo exists .t.f.s] [winfo exists .t.f]
    rename bgerror {}
    set result
} {1 0 0}
test scrollbar-8.2 {TkScrollbarEventProc: recursive deletion} notAqua {
    # constrained by notAqua because this test clicks on an arrow of the
    # scrollbar - but macOS has no such arrows in modern scrollbars
    proc doit {args} { destroy .t.f.s }
    proc bgerror {args} {}
    destroy .t.f
    frame .t.f
    scrollbar .t.f.s -command doit
    pack .t.f -fill both -expand 1
    pack .t.f.s -fill y -expand 1 -side right
    wm geometry .t 100x100
    .t.f.s set 0 .5
    update
    set result [winfo exists .t.f.s]
    event generate .t.f.s <ButtonPress> -button 1 -x [expr {[winfo width .t.f.s] / 2}] -y 5
    event generate .t.f.s <Button> -button 1 -x [expr {[winfo width .t.f.s] / 2}] -y 5
    event generate .t.f <ButtonRelease> -button 1
    update
    lappend result [winfo exists .t.f.s] [winfo exists .t.f]
    rename bgerror {}
    set result
} {1 0 1}

set l [interp hidden]
deleteWindows

test scrollbar-9.1 {scrollbar widget vs hidden commands} {
    catch {destroy .s}
    scrollbar .s
    interp hide {} .s
    destroy .s
    list [winfo children .] [interp hidden]
} [list {} $l]

test scrollbar-10.1.1 {<MouseWheel> event on scrollbar} -constraints {notAqua} -setup {
test scrollbar-10.1 {<MouseWheel> event on scrollbar} -setup {
    destroy .t .s
} -body {
    pack [text .t -yscrollcommand {.s set}] -side left
    for {set i 1} {$i < 100} {incr i} {.t insert end "Line $i\n"}
    pack [scrollbar .s -command {.t yview}] -fill y -expand 1 -side left
    update
    focus -force .s
    event generate .s <MouseWheel> -delta -120
    after 200 {set eventprocessed 1} ; vwait eventprocessed
    .t index @0,0
} -cleanup {
    destroy .t .s
} -result {5.0}
test scrollbar-10.1.2 {<MouseWheel> event on scrollbar} -constraints {aqua} -setup {
    destroy .t .s
} -body {
    pack [text .t -yscrollcommand {.s set}] -side left
    for {set i 1} {$i < 100} {incr i} {.t insert end "Line $i\n"}
    pack [scrollbar .s -command {.t yview}] -fill y -expand 1 -side left
    update
    focus -force .s
    event generate .s <MouseWheel> -delta -4
    after 200 {set eventprocessed 1} ; vwait eventprocessed
    .t index @0,0
} -cleanup {
    destroy .t .s
} -result {5.0}

test scrollbar-10.2.1 {<MouseWheel> event on scrollbar} -constraints {notAqua} -setup {
test scrollbar-10.2 {<MouseWheel> event on scrollbar} -setup {
    destroy .t .s
} -body {
    pack [text .t -xscrollcommand {.s set} -wrap none] -side top
    for {set i 1} {$i < 100} {incr i} {.t insert end "Char $i "}
    pack [scrollbar .s -command {.t xview} -orient horizontal] -fill x -expand 1 -side top
    update
    focus -force .s
    event generate .s <Shift-MouseWheel> -delta -120
    after 200 {set eventprocessed 1} ; vwait eventprocessed
    .t index @0,0
} -cleanup {
    destroy .t .s
} -result {1.4}
test scrollbar-10.2.2 {<MouseWheel> event on scrollbar} -constraints {aqua} -setup {
test scrollbar-10.2.3 {<MouseWheel> event on horizontal scrollbar} -setup {
    destroy .t .s
} -body {
    pack [text .t -xscrollcommand {.s set} -wrap none] -side top
    for {set i 1} {$i < 100} {incr i} {.t insert end "Char $i "}
    pack [scrollbar .s -command {.t xview} -orient horizontal] -fill x -expand 1 -side top
    update
    focus -force .s
    event generate .s <Shift-MouseWheel> -delta -4
    event generate .s <MouseWheel> -delta -120
    after 200 {set eventprocessed 1} ; vwait eventprocessed
    .t index @0,0
} -cleanup {
    destroy .t .s
} -result {1.4}

test scrollbar-11.1 {bug fix: [011706ec42] Scrollbar unsafe wrt widget destruction} -body {
    proc destroy_scrollbar {} {
        if {[winfo exists .top.s]} {
            destroy .top.s
        }
    }
    toplevel .top
    scrollbar .top.s
    bind .top.s <2> {destroy_scrollbar}
    bind .top.s <Button-2> {destroy_scrollbar}
    pack .top.s
    focus -force .top.s
    update
    event generate .top.s <2>
    event generate .top.s <Button-2>
    update  ; # shall not trigger error  invalid command name ".top.s"
} -cleanup {
    destroy .top.s .top
} -result {} 
} -result {}
test scrollbar-11.2 {bug fix: [011706ec42] Scrollbar unsafe wrt widget destruction} -body {
    proc destroy_scrollbar {{y 0}} {
        if {[winfo exists .top.s]} {
            destroy .top.s
        }
    }
    toplevel .top
    wm minsize .top 50 400
    update
    scrollbar .top.s
    bind .top.s <2> {after idle destroy_scrollbar}
    bind .top.s <Button-2> {after idle destroy_scrollbar}
    pack .top.s -expand true -fill y
    focus -force .top.s
    update
    event generate .top.s <2> -x 2 -y [expr {[winfo height .top.s] / 2}]
    event generate .top.s <Button-2> -x 2 -y [expr {[winfo height .top.s] / 2}]
    update  ; # shall not trigger error  invalid command name ".top.s"
} -cleanup {
    destroy .top.s .top
} -result {} 
} -result {}

catch {destroy .s}
catch {destroy .t}

# cleanup
cleanupTests
return
Changes to tests/select.test.
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

26
27
28
29
30
31
32
1
2
3
4


5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33




-
-
+
+



















+







# This file is a Tcl script to test out Tk's selection management code,
# especially the "selection" command. It is organized in the standard fashion
# for Tcl tests.
#
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1994 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

#
# Note: Multiple display selection handling will only be tested if the
# environment variable TK_ALT_DISPLAY is set to an alternate display.
#

package require tcltest 2.2
namespace import ::tcltest::*
namespace import ::tk::test:loadTkCommand
eval tcltest::configure $argv
tcltest::loadTestedCommands

testConstraint cliboardManagerPresent 0
if {![catch {selection get -selection CLIPBOARD_MANAGER -type TARGETS}]} {
    if {"SAVE_TARGETS" in [selection get -selection CLIPBOARD_MANAGER -type TARGETS]} {
        testConstraint cliboardManagerPresent 1
    }
}
testConstraint failsOnUbuntu [expr {![info exists ::env(CI)] || ![string match Linux $::tcl_platform(os)]}]

global longValue selValue selInfo

set selValue {}
set selInfo {}

proc handler {type offset count} {
891
892
893
894
895
896
897
898

899
900
901
902
903
904
905
906
907
908
909
910
911

912
913
914
915
916
917
918
919
920
921
922
923
924

925
926
927
928
929
930
931
892
893
894
895
896
897
898

899
900
901
902
903
904
905
906
907
908
909
910
911

912
913
914
915
916
917
918
919
920
921
922
923
924

925
926
927
928
929
930
931
932







-
+












-
+












-
+







    lappend result [dobg {selection get TEST}]
    cleanupbg
    lappend result $selInfo
} -result {{0x400 } {TEST 0 4000}}
test select-9.2 {SelCvtToX and SelCvtFromX procedures} -setup {
    setup
    setupbg
} -constraints x11 -body {
} -constraints {x11 failsOnUbuntu} -body {
    set selValue "1024 0xffff  2048 -2  "
    set selInfo ""
    selection handle -selection PRIMARY -format INTEGER -type TEST \
	.f1 {handler TEST}
    set result ""
    lappend result [dobg {selection get TEST}]
    cleanupbg
    lappend result $selInfo
} -result {{0x400 0xffff 0x800 0xfffffffe } {TEST 0 4000}}
test select-9.3 {SelCvtToX and SelCvtFromX procedures} -setup {
    setup
    setupbg
} -constraints x11 -body {
} -constraints {x11 failsOnUbuntu} -body {
    set selValue "   "
    set selInfo ""
    selection handle -selection PRIMARY -format INTEGER -type TEST \
	.f1 {handler TEST}
    set result ""
    lappend result [dobg {selection get TEST}]
    cleanupbg
    lappend result $selInfo
} -result {{ } {TEST 0 4000}}
test select-9.4 {SelCvtToX and SelCvtFromX procedures} -setup {
    setup
    setupbg
} -constraints x11 -body {
} -constraints {x11 failsOnUbuntu} -body {
    set selValue "16 foobar 32"
    set selInfo ""
    selection handle -selection PRIMARY -format INTEGER -type TEST \
	.f1 {handler TEST}
    set result ""
    lappend result [dobg {selection get TEST}]
    cleanupbg
948
949
950
951
952
953
954
955

956
957
958
959
960
961
962
949
950
951
952
953
954
955

956
957
958
959
960
961
962
963







-
+







} -result {MULTIPLE TARGETS TIMESTAMP TK_APPLICATION TK_WINDOW {text/x-tk-test;detail="foo bar"}}

##############################################################################
# note, we are not testing MULTIPLE style selections

# most control paths have been exercised above
test select-10.1 {ConvertSelection procedure, race with selection clear} -constraints {
    x11 
    x11
} -setup {
    setup
} -body {
    proc Ready {fd} {
	variable x
	lappend x [gets $fd]
    }
1002
1003
1004
1005
1006
1007
1008
1009

1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024

1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039

1040
1041
1042
1043
1044
1045
1046
1003
1004
1005
1006
1007
1008
1009

1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024

1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039

1040
1041
1042
1043
1044
1045
1046
1047







-
+














-
+














-
+







    dobg {selection get ERROR}
} -cleanup {
    cleanupbg
} -result {PRIMARY selection doesn't exist or form "ERROR" not defined}
# testing timers
# This one hangs in Exceed
test select-10.4 {ConvertSelection procedure} -constraints {
    x11 noExceed
    x11 noExceed failsOnUbuntu
} -setup {
    setup
    setupbg
} -body {
    set selValue $longValue
    set selInfo ""
    selection handle .f1 {errIncrHandler STRING}
    set result ""
    set pass 0
    lappend result [dobg {selection get}]
    cleanupbg
    lappend result $selInfo
} -result {{selection owner didn't respond} {STRING 0 4000 STRING 4000 4000 STRING 8000 4000 STRING 12000 4000 STRING 16000 4000 STRING 0 4000 STRING 4000 4000}}
test select-10.5 {ConvertSelection procedure, reentrancy issues} -constraints {
    x11 
    x11 failsOnUbuntu
} -setup {
    setup
    setupbg
} -body {
    set selValue "Test value"
    set selInfo ""
    selection handle -type TEST .f1 { handler TEST }
    selection handle -type STRING .f1 { badHandler .f1 STRING }
    set result ""
    lappend result [dobg {selection get}]
    cleanupbg
    lappend result $selInfo
} -result {{PRIMARY selection doesn't exist or form "STRING" not defined} {.f1 STRING 0 4000}}
test select-10.6 {ConvertSelection procedure, reentrancy issues} -constraints {
    x11 
    x11 failsOnUbuntu
} -setup {
    setup
    setupbg
} -body {
    proc weirdHandler {type offset count} {
	destroy .f1
	handler $type $offset $count
1055
1056
1057
1058
1059
1060
1061
1062

1063
1064
1065
1066
1067
1068
1069
1056
1057
1058
1059
1060
1061
1062

1063
1064
1065
1066
1067
1068
1069
1070







-
+







} -cleanup {
    rename weirdHandler {}
} -result {{PRIMARY selection doesn't exist or form "STRING" not defined} {STRING 0 4000}}

##############################################################################

# testing reentrancy
test select-11.1 {TkSelPropProc procedure} -constraints x11 -setup {
test select-11.1 {TkSelPropProc procedure} -constraints {x11 failsOnUbuntu} -setup {
    setup
    setupbg
} -body {
    set selValue $longValue
    set selInfo ""
    selection handle -type TEST .f1 { handler TEST }
    selection handle -type STRING .f1 { reallyBadHandler .f1 STRING }
1127
1128
1129
1130
1131
1132
1133
1134

1135
1136
1137
1138
1139
1140
1141
1128
1129
1130
1131
1132
1133
1134

1135
1136
1137
1138
1139
1140
1141
1142







-
+







    set selInfo ""
    set result [list [selection get TARGETS] $selInfo]
    selection handle .f1 {} TARGETS
    lappend result [selection get TARGETS]
} -result {{Targets value} {TARGETS.f1 0 4000} {MULTIPLE TARGETS TIMESTAMP TK_APPLICATION TK_WINDOW}}

test select-13.1 {SelectionSize procedure, handler deleted} -constraints {
    x11 
    x11 failsOnUbuntu
} -setup {
    setup
    setupbg
} -body {
    proc badHandler {path type offset count} {
	global selValue selInfo abortCount
	incr abortCount -1
Changes to tests/send.test.
1
2
3
4
5
6
7
8




9
10
11
12
13

14
15
16
17

18
19
20
21
22
23
24
1
2
3
4




5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
20
21
22
23
24
25




-
-
-
-
+
+
+
+




-
+




+







# This file is a Tcl script to test out the "send" command and the
# other procedures in the file tkSend.c.  It is organized in the
# standard fashion for Tcl tests.
#
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright (c) 2001 by ActiveState Corporation.
# Copyright © 1994 Sun Microsystems, Inc.
# Copyright © 1994-1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# Copyright © 2001 ActiveState Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

package require tcltest 2.1
package require tcltest 2.2
eval tcltest::configure $argv
tcltest::loadTestedCommands

testConstraint xhost [llength [auto_execok xhost]]
testConstraint failsOnUbuntu [expr {![info exists ::env(CI)] || ![string match Linux $::tcl_platform(os)]}]

# Compute a script that will load Tk into a child interpreter.

foreach pkg [info loaded] {
    if {[lindex $pkg 1] == "Tk"} {
	set loadTk "load $pkg"
	break
282
283
284
285
286
287
288
289

290
291
292
293
294
295
296
297
298
299

300
301
302
303
304
305
306
283
284
285
286
287
288
289

290
291
292
293
294
295
296
297
298
299

300
301
302
303
304
305
306
307







-
+









-
+







test send-8.14 {Tk_SendCmd procedure, local interp killed by send} {secureserver testsend} {
    newApp "" t_s_2 Test
    list [catch {send t_s_2 {destroy .; concat result}} msg] $msg
} {0 result}

catch {interp delete t_s_2}

test send-8.15 {Tk_SendCmd procedure, local interp, error info} {secureserver testsend} {
test send-8.15 {Tk_SendCmd procedure, local interp, error info} {secureserver testsend failsOnUbuntu} {
    catch {error foo}
    list [catch {send t_s_1 {if 1 {open bogus_file_name}}} msg] $msg $errorInfo $errorCode
} {1 {couldn't open "bogus_file_name": no such file or directory} {couldn't open "bogus_file_name": no such file or directory
    while executing
"open bogus_file_name"
    invoked from within
"if 1 {open bogus_file_name}"
    invoked from within
"send t_s_1 {if 1 {open bogus_file_name}}"} {POSIX ENOENT {no such file or directory}}}
test send-8.16 {Tk_SendCmd procedure, bogusCommWindow} {secureserver testsend} {
test send-8.16 {Tk_SendCmd procedure, bogusCommWindow} {secureserver testsend failsOnUbuntu} {
    testsend prop root InterpRegistry "10234 bogus\n"
    set result [list [catch {send bogus bogus command} msg] $msg]
    winfo interps
    tk appname tktest
    set result
} {1 {no application named "bogus"}}

397
398
399
400
401
402
403
404

405
406
407
408
409
410
411

412
413
414
415
416
417
418
398
399
400
401
402
403
404

405
406
407
408
409
410
411

412
413
414
415
416
417
418
419







-
+






-
+







} {12345 newA newB}
test send-10.4 {SendEventProc procedure, leading nulls, bogus commands} {secureserver testsend} {
    testsend prop comm Comm \
	    "\n\nx\n-bogus\n\nc\n-n tktest\n-s set a 44\n"
    set a null
    update
    set a
} {44}
} 44
test send-10.5 {SendEventProc procedure, extraneous command options} {secureserver testsend} {
    testsend prop comm Comm \
	    "c\n-n tktest\n-x miscellanous\n-y who knows?\n-s set a new\n"
    set a null
    update
    set a
} {new}
} new
test send-10.6 {SendEventProc procedure, unknown interpreter} {secureserver testsend} {
    testsend prop [winfo id .f] Comm {}
    testsend prop comm Comm \
	    "c\n-n unknown\n-r $id 44\n-s set a new\n"
    set a null
    update
    list [testsend prop [winfo id .f] Comm] $a
518
519
520
521
522
523
524
525

526
527
528


529
530
531
532
533
534
535
519
520
521
522
523
524
525

526
527


528
529
530
531
532
533
534
535
536







-
+

-
-
+
+







    setupbg
    dobg {tk appname t_s_3}
    set x [list [catch {send t_s_3 exit} msg] $msg]
    cleanupbg
    set x
} {1 {target application died}}

test send-11.1 {AppendPropCarefully and AppendErrorProc procedures} {secureserver testsend} {
test send-11.1 {AppendPropCarefully and AppendErrorProc procedures} -constraints {secureserver testsend} -body {
    testsend prop root InterpRegistry "0x21447 dummy\n"
    list [catch {send dummy foo} msg] $msg
} {1 {no application named "dummy"}}
    send dummy foo
} -returnCodes 1 -match regexp -result {^(target application died|no application named "dummy")$}
test send-11.2 {AppendPropCarefully and AppendErrorProc procedures} {secureserver testsend} {
    testsend prop comm Comm "c\n-r0x123 44\n-n tktest\n-s concat a b c\n"
    update
} {}

winfo interps
tk appname tktest
Changes to tests/spinbox.test.
1
2
3
4
5
6



7
8
9
10
11
12
13



14

15
16
17
18
19

20
21
22
23
24
25
26
1
2
3



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

23
24
25
26
27
28
29
30



-
-
-
+
+
+







+
+
+

+




-
+







# This file is a Tcl script to test spinbox widgets in Tk.  It is
# organized in the standard fashion for Tcl tests.
#
# Copyright (c) 1994 The Regents of the University of California.
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1994 The Regents of the University of California.
# Copyright © 1994-1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
namespace import ::tcltest::*
eval tcltest::configure $argv
tcltest::loadTestedCommands

testConstraint failsOnUbuntu [expr {![info exists ::env(CI)] || ![string match Linux $::tcl_platform(os)]}]
testConstraint failsOnUbuntuNoXft [expr {[testConstraint failsOnUbuntu] || (![catch {tk::pkgconfig get fontsystem} fs] && ($fs eq "xft"))}]

# For xscrollcommand
set scrollInfo {}
proc scroll args {
        global scrollInfo
        set scrollInfo $args
}
# For trace variable 
# For trace variable
proc override args {
        global x
        set x 12345
}

# Procedures used in widget VALIDATION tests
proc doval {W d i P s S v V} {
89
90
91
92
93
94
95
96

97
98
99
100
101
102
103
93
94
95
96
97
98
99

100
101
102
103
104
105
106
107







-
+







    pack .e
    update
} -body {
    .e configure -bd 4
    .e cget -bd
} -cleanup {
    destroy .e
} -result {4}
} -result 4
test spinbox-1.6 {configuration option: "bd" for spinbox} -setup {
        spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \
        -relief sunken
    pack .e
    update
} -body {
    .e configure -bd badValue
133
134
135
136
137
138
139
140

141
142
143
144
145
146
147
137
138
139
140
141
142
143

144
145
146
147
148
149
150
151







-
+







    pack .e
    update
} -body {
    .e configure -borderwidth 1.3
    .e cget -borderwidth
} -cleanup {
    destroy .e
} -result {1}
} -result 1
test spinbox-1.10 {configuration option: "borderwidth" for spinbox} -setup {
        spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \
        -relief sunken
    pack .e
    update
} -body {
    .e configure -borderwidth badValue
277
278
279
280
281
282
283
284

285
286
287
288
289
290
291
281
282
283
284
285
286
287

288
289
290
291
292
293
294
295







-
+







    pack .e
    update
} -body {
    .e configure -exportselection yes
    .e cget -exportselection
} -cleanup {
    destroy .e
} -result {1}
} -result 1
test spinbox-1.23 {configuration option: "exportselection" for spinbox} -setup {
        spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \
        -relief sunken
    pack .e
    update
} -body {
    .e configure -exportselection xyzzy
453
454
455
456
457
458
459
460

461
462
463
464
465
466
467
457
458
459
460
461
462
463

464
465
466
467
468
469
470
471







-
+







    pack .e
    update
} -body {
    .e configure -highlightthickness 6
    .e cget -highlightthickness
} -cleanup {
    destroy .e
} -result {6}
} -result 6
test spinbox-1.39 {configuration option: "highlightthickness" for spinbox} -setup {
        spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \
        -relief sunken
    pack .e
    update
} -body {
    .e configure -highlightthickness bogus
475
476
477
478
479
480
481
482

483
484
485
486
487
488
489
479
480
481
482
483
484
485

486
487
488
489
490
491
492
493







-
+







    pack .e
    update
} -body {
    .e configure -highlightthickness -2
    .e cget -highlightthickness
} -cleanup {
    destroy .e
} -result {0}
} -result 0

test spinbox-1.41 {configuration option: "increment"} -setup {
        spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \
        -relief sunken
    pack .e
    update
} -body {
531
532
533
534
535
536
537
538

539
540
541
542
543
544
545
535
536
537
538
539
540
541

542
543
544
545
546
547
548
549







-
+







    pack .e
    update
} -body {
    .e configure -insertborderwidth 1.3
    .e cget -insertborderwidth
} -cleanup {
    destroy .e
} -result {1}
} -result 1
test spinbox-1.46 {configuration option: "insertborderwidth" for spinbox} -setup {
        spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \
        -relief sunken
    pack .e
    update
} -body {
    .e configure -insertborderwidth 2.6x
553
554
555
556
557
558
559
560

561
562
563
564
565
566
567
557
558
559
560
561
562
563

564
565
566
567
568
569
570
571







-
+







    pack .e
    update
} -body {
    .e configure -insertofftime 100
    .e cget -insertofftime
} -cleanup {
    destroy .e
} -result {100}
} -result 100
test spinbox-1.48 {configuration option: "insertofftime" for spinbox} -setup {
        spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \
        -relief sunken
    pack .e
    update
} -body {
    .e configure -insertofftime 3.2
575
576
577
578
579
580
581
582

583
584
585
586
587
588
589
579
580
581
582
583
584
585

586
587
588
589
590
591
592
593







-
+







    pack .e
    update
} -body {
    .e configure -insertontime 100
    .e cget -insertontime
} -cleanup {
    destroy .e
} -result {100}
} -result 100
test spinbox-1.50 {configuration option: "insertontime" for spinbox} -setup {
        spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \
        -relief sunken
    pack .e
    update
} -body {
    .e configure -insertontime 3.2
687
688
689
690
691
692
693
694

695
696
697
698
699
700
701
691
692
693
694
695
696
697

698
699
700
701
702
703
704
705







-
+







    pack .e
    update
} -body {
    .e configure -repeatdelay 500
    .e cget -repeatdelay
} -cleanup {
    destroy .e
} -result {500}
} -result 500
test spinbox-1.60 {configuration option: "repeatdelay" for spinbox} -setup {
        spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \
        -relief sunken
    pack .e
    update
} -body {
    .e configure -repeatdelay 3p
709
710
711
712
713
714
715
716

717
718
719
720
721
722
723
713
714
715
716
717
718
719

720
721
722
723
724
725
726
727







-
+







    pack .e
    update
} -body {
    .e configure -repeatinterval -500
    .e cget -repeatinterval
} -cleanup {
    destroy .e
} -result {-500}
} -result -500
test spinbox-1.62 {configuration option: "repeatinterval" for spinbox} -setup {
        spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \
        -relief sunken
    pack .e
    update
} -body {
    .e configure -repeatinterval 3p
753
754
755
756
757
758
759
760

761
762
763
764
765
766
767
757
758
759
760
761
762
763

764
765
766
767
768
769
770
771







-
+







    pack .e
    update
} -body {
    .e configure -selectborderwidth 1.3
    .e cget -selectborderwidth
} -cleanup {
    destroy .e
} -result {1}
} -result 1
test spinbox-1.66 {configuration option: "selectborderwidth" for spinbox} -setup {
        spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \
        -relief sunken
    pack .e
    update
} -body {
    .e configure -selectborderwidth badValue
911
912
913
914
915
916
917
918

919
920
921
922
923
924
925


926
927
928
929
930
931
932
933
934
935
936
937
938
939
940

941
942
943
944
945
946
947
915
916
917
918
919
920
921

922
923
924
925
926
927


928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943

944
945
946
947
948
949
950
951







-
+





-
-
+
+














-
+







    update
} -body {
    .e configure -values {bad {}list}
} -cleanup {
    destroy .e
} -returnCodes {error} -result {list element in braces followed by "list" instead of space}

test spinbox-1.80 {configuration option: "vcmd"} -setup {
test spinbox-1.80 {configuration option: "validatecommand"} -setup {
        spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \
        -relief sunken
    pack .e
    update
} -body {
    .e configure -vcmd "a command"
    .e cget -vcmd
    .e configure -validatecommand "a command"
    .e cget -validatecommand
} -cleanup {
    destroy .e
} -result {a command}

test spinbox-1.81 {configuration option: "width"} -setup {
        spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \
        -relief sunken
    pack .e
    update
} -body {
    .e configure -width 402
    .e cget -width
} -cleanup {
    destroy .e
} -result {402}
} -result 402
test spinbox-1.82 {configuration option: "width" for spinbox} -setup {
        spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \
        -relief sunken
    pack .e
    update
} -body {
    .e configure -width 3p
955
956
957
958
959
960
961
962

963
964
965
966
967
968
969
959
960
961
962
963
964
965

966
967
968
969
970
971
972
973







-
+







    pack .e
    update
} -body {
    .e configure -wrap yes
    .e cget -wrap
} -cleanup {
    destroy .e
} -result {1}
} -result 1
test spinbox-1.84 {configuration option: "wrap" for spinbox} -setup {
        spinbox .e -borderwidth 2 -highlightthickness 2 -font {Helvetica -12} \
        -relief sunken
    pack .e
    update
} -body {
    .e configure -wrap xyzzy
1013
1014
1015
1016
1017
1018
1019
1020

1021
1022
1023
1024
1025
1026
1027
1028
1029

1030
1031
1032
1033
1034
1035
1036
1037
1038

1039
1040
1041
1042
1043
1044
1045
1046
1047

1048
1049
1050
1051
1052
1053
1054
1055
1056

1057
1058
1059
1060
1061
1062
1063
1064
1065

1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084

1085
1086
1087
1088
1089

1090
1091
1092
1093
1094
1095
1096
1097

1098
1099
1100
1101
1102

1103
1104
1105
1106
1107
1108

1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120

1121
1122
1123
1124

1125
1126
1127
1128
1129
1130

1131
1132
1133
1134
1135
1136
1137

1138
1139
1140
1141
1142
1143
1144

1145
1146
1147
1148
1149
1150
1151

1152
1153
1154
1155
1156
1157

1158
1159

1160
1161
1162
1163
1164
1165
1166

1167
1168

1169
1170
1171
1172
1173
1174
1175

1176
1177
1178
1179
1180
1181
1182

1183
1184

1185
1186
1187
1188
1189
1190
1191

1192
1193
1194
1195
1196
1197
1198

1199
1200
1201
1202
1203
1204
1205

1206
1207
1208
1209
1210
1211
1212
1213
1214

1215
1216
1217
1218
1219
1220
1221

1222
1223

1224
1225
1226
1227
1228
1229
1230

1231
1232
1233
1234

1235
1236
1237
1238

1239
1240
1241
1242

1243
1244
1245
1246

1247
1248
1249
1250
1251

1252
1253
1254
1255

1256
1257
1258
1259
1260
1261
1262

1263
1264
1265
1266

1267
1268
1269
1270
1271
1272
1273
1274
1275

1276
1277
1278
1279

1280
1281
1282
1283
1284
1285
1286
1287
1288

1289
1290

1291
1292
1293
1294
1295
1296
1297

1298
1299
1300
1301
1302
1303
1304

1305
1306
1307
1308
1309
1310
1311

1312
1313
1314
1315
1316
1317
1318

1319
1320

1321
1322
1323
1324
1325
1326
1327

1328
1329
1330
1331
1332
1333
1334

1335
1336
1337
1338
1339
1340
1341
1342
1343

1344
1345
1346
1347
1348
1349
1350
1351
1352

1353
1354
1355

1356
1357
1358
1359
1360
1361

1362
1363
1364
1365
1366
1367
1368

1369
1370
1371
1372
1373
1374
1375

1376
1377
1378
1379
1380
1381
1382
1383
1384

1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395

1396
1397
1398
1399
1400
1401
1402
1403
1404

1405
1406
1407
1408

1409
1410
1411
1412
1413
1414
1415
1416
1417

1418
1419

1420
1421
1422
1423
1424
1425
1426

1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437

1438
1439
1440
1441
1442
1443
1444
1445
1446

1447
1448
1449
1450
1451
1452
1453
1454
1455

1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466

1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477

1478
1479

1480
1481
1482
1483
1484
1485
1486

1487
1488
1489
1490
1491
1492
1493
1494

1495
1496
1497
1498
1499
1500
1501

1502
1503
1504
1505
1506
1507
1508

1509
1510
1511
1512
1513
1514
1515

1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529

1530
1531
1532
1533
1534
1535
1536
1537
1538

1539
1540
1541
1542
1543
1544
1545
1546

1547
1548
1549
1550

1551
1552
1553
1554
1555
1556
1557
1558
1559

1560
1561
1562
1563

1564
1565
1566
1567
1568
1569
1570
1571
1572

1573
1574
1575
1576
1577
1578
1579
1017
1018
1019
1020
1021
1022
1023

1024
1025
1026
1027
1028
1029
1030
1031
1032

1033
1034
1035
1036
1037
1038
1039
1040
1041

1042
1043
1044
1045
1046
1047
1048
1049
1050

1051
1052
1053
1054
1055
1056
1057
1058
1059

1060
1061
1062
1063
1064
1065
1066
1067
1068

1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087

1088
1089
1090
1091
1092

1093
1094
1095
1096
1097
1098
1099
1100

1101
1102
1103
1104
1105

1106
1107
1108
1109
1110
1111

1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123

1124
1125
1126
1127

1128
1129
1130
1131
1132
1133

1134
1135
1136
1137
1138
1139
1140

1141
1142
1143
1144
1145
1146
1147

1148
1149
1150
1151
1152
1153
1154

1155
1156
1157
1158
1159
1160

1161
1162

1163
1164
1165
1166
1167
1168
1169

1170
1171

1172
1173
1174
1175
1176
1177
1178

1179
1180
1181
1182
1183
1184
1185

1186
1187

1188
1189
1190
1191
1192
1193
1194

1195
1196
1197
1198
1199
1200
1201

1202
1203
1204
1205
1206
1207
1208

1209
1210
1211
1212
1213
1214
1215
1216
1217

1218
1219
1220
1221
1222
1223
1224

1225
1226

1227
1228
1229
1230
1231
1232
1233

1234
1235
1236
1237

1238
1239
1240
1241

1242
1243
1244
1245

1246
1247
1248
1249

1250
1251
1252
1253
1254

1255
1256
1257
1258

1259
1260
1261
1262
1263
1264
1265

1266
1267
1268
1269

1270
1271
1272
1273
1274
1275
1276
1277
1278

1279
1280
1281
1282

1283
1284
1285
1286
1287
1288
1289
1290
1291

1292
1293

1294
1295
1296
1297
1298
1299
1300

1301
1302
1303
1304
1305
1306
1307

1308
1309
1310
1311
1312
1313
1314

1315
1316
1317
1318
1319
1320
1321

1322
1323

1324
1325
1326
1327
1328
1329
1330

1331
1332
1333
1334
1335
1336
1337

1338
1339
1340
1341
1342
1343
1344
1345
1346

1347
1348
1349
1350
1351
1352
1353
1354
1355

1356
1357
1358

1359
1360
1361
1362
1363
1364

1365
1366
1367
1368
1369
1370
1371

1372
1373
1374
1375
1376
1377
1378

1379
1380
1381
1382
1383
1384
1385
1386
1387

1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398

1399
1400
1401
1402
1403
1404
1405
1406
1407

1408
1409
1410
1411

1412
1413
1414
1415
1416
1417
1418
1419
1420

1421
1422

1423
1424
1425
1426
1427
1428
1429

1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440

1441
1442
1443
1444
1445
1446
1447
1448
1449

1450
1451
1452
1453
1454
1455
1456
1457
1458

1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469

1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480

1481
1482

1483
1484
1485
1486
1487
1488
1489

1490
1491
1492
1493
1494
1495
1496
1497

1498
1499
1500
1501
1502
1503
1504

1505
1506
1507
1508
1509
1510
1511

1512
1513
1514
1515
1516
1517
1518

1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532

1533
1534
1535
1536
1537
1538
1539
1540
1541

1542
1543
1544
1545
1546
1547
1548
1549

1550
1551
1552
1553

1554
1555
1556
1557
1558
1559
1560
1561
1562

1563
1564
1565
1566

1567
1568
1569
1570
1571
1572
1573
1574
1575

1576
1577
1578
1579
1580
1581
1582
1583







-
+








-
+








-
+








-
+








-
+








-
+


















-
+




-
+







-
+




-
+





-
+











-
+



-
+





-
+






-
+






-
+






-
+





-
+

-
+






-
+

-
+






-
+






-
+

-
+






-
+






-
+






-
+








-
+






-
+

-
+






-
+



-
+



-
+



-
+



-
+




-
+



-
+






-
+



-
+








-
+



-
+








-
+

-
+






-
+






-
+






-
+






-
+

-
+






-
+






-
+








-
+








-
+


-
+





-
+






-
+






-
+








-
+










-
+








-
+



-
+








-
+

-
+






-
+










-
+








-
+








-
+










-
+










-
+

-
+






-
+







-
+






-
+






-
+






-
+













-
+








-
+







-
+



-
+








-
+



-
+








-
+







    spinbox .e
} -cleanup {
    destroy .e
} -result {.e}


test spinbox-3.1 {SpinboxWidgetCmd procedure} -setup {
    spinbox .e 
    spinbox .e
    pack .e
    update
} -body {
    .e
} -cleanup {
    destroy .e
} -returnCodes error -result {wrong # args: should be ".e option ?arg ...?"}
test spinbox-3.2 {SpinboxWidgetCmd procedure, "bbox" widget command} -setup {
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
    update
} -body {
    .e bbox
} -cleanup {
    destroy .e
} -returnCodes error -result {wrong # args: should be ".e bbox index"}
test spinbox-3.3 {SpinboxWidgetCmd procedure, "bbox" widget command} -setup {
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
    update
} -body {
    .e bbox a b
} -cleanup {
    destroy .e
} -returnCodes error -result {wrong # args: should be ".e bbox index"}
test spinbox-3.4 {SpinboxWidgetCmd procedure, "bbox" widget command} -setup {
    spinbox .e 
    spinbox .e
    pack .e
    update
} -body {
    .e bbox bogus
} -cleanup {
    destroy .e
} -returnCodes error -result {bad spinbox index "bogus"}
test spinbox-3.5 {SpinboxWidgetCmd procedure, "bbox" widget command} -setup {
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
    update
} -body {
   .e bbox 0
} -cleanup {
    destroy .e
} -result [list 5 5 0 $cy]

# Oryginaly the result was count using measurements 
# Oryginaly the result was count using measurements
# and metrics. It was changed to less verbose solution - the result is the one
# that passes fonts constraint (this concerns tests 3.6, 3.7, 3.8, 3.10)
test spinbox-3.6 {SpinboxWidgetCmd procedure, "bbox" widget command} -constraints {
	fonts
} -setup {
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
    update
} -body {
# Tcl_UtfAtIndex(): no utf chars
    .e insert 0 "abc"
    list [.e bbox 3] [.e bbox end]
} -cleanup {
    destroy .e
} -result {{19 5 7 13} {19 5 7 13}}
test spinbox-3.7 {SpinboxWidgetCmd procedure, "bbox" widget command} -constraints {
	fonts
} -setup {
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
    update
} -body {
# Tcl_UtfAtIndex(): utf at end
    .e insert 0 "ab\u4e4e"
    .e insert 0 "ab"
    .e bbox end
} -cleanup {
    destroy .e
} -result {19 5 12 13}
test spinbox-3.8 {SpinboxWidgetCmd procedure, "bbox" widget command} -constraints {
	fonts
} -setup {
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
    update
} -body {
# Tcl_UtfAtIndex(): utf before index
    .e insert 0 "ab\u4e4ec"
    .e insert 0 "abc"
    .e bbox 3
} -cleanup {
    destroy .e
} -result {31 5 7 13}
test spinbox-3.9 {SpinboxWidgetCmd procedure, "bbox" widget command} -setup {
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
    update
} -body {
# Tcl_UtfAtIndex(): no chars
    .e bbox end
} -cleanup {
    destroy .e
} -result "5 5 0 $cy"
test spinbox-3.10 {SpinboxWidgetCmd procedure, "bbox" widget command} -constraints {
	fonts
} -setup {
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
    update
} -body {
    .e insert 0 "abcdefghij\u4e4eklmnop"
    .e insert 0 "abcdefghijklmnop"
    list [.e bbox 0] [.e bbox 1] [.e bbox 10] [.e bbox end]
} -cleanup {
    destroy .e
} -result {{5 5 7 13} {12 5 7 13} {75 5 12 13} {122 5 7 13}}
test spinbox-3.11 {SpinboxWidgetCmd procedure, "cget" widget command} -setup {
    spinbox .e 
    spinbox .e
} -body {
    .e cget
} -cleanup {
    destroy .e
} -returnCodes error -result {wrong # args: should be ".e cget option"}
test spinbox-3.12 {SpinboxWidgetCmd procedure, "cget" widget command} -setup {
    spinbox .e 
    spinbox .e
} -body {
    .e cget a b
} -cleanup {
    destroy .e
} -returnCodes error -result {wrong # args: should be ".e cget option"}
test spinbox-3.13 {SpinboxWidgetCmd procedure, "cget" widget command} -setup {
    spinbox .e 
    spinbox .e
} -body {
    .e cget -gorp
} -cleanup {
    destroy .e
} -returnCodes error -result {unknown option "-gorp"}
test spinbox-3.14 {SpinboxWidgetCmd procedure, "cget" widget command} -setup {
    spinbox .e 
    spinbox .e
} -body {
    .e configure -bd 4
    .e cget -bd
} -cleanup {
    destroy .e
} -result {4}
} -result 4
test spinbox-3.15 {SpinboxWidgetCmd procedure, "configure" widget command} -setup {
    spinbox .e 
    spinbox .e
    pack .e
    update
} -body {
    llength [.e configure]
} -cleanup {
    destroy .e
} -result {49}
} -result 51
test spinbox-3.16 {SpinboxWidgetCmd procedure, "configure" widget command} -setup {
    spinbox .e 
    spinbox .e
} -body {
    .e configure -foo
} -cleanup {
    destroy .e
} -returnCodes error -result {unknown option "-foo"}
test spinbox-3.17 {SpinboxWidgetCmd procedure, "configure" widget command} -setup {
    spinbox .e 
    spinbox .e
} -body {
    .e configure -bd 4
    .e configure -bg #ffffff
    lindex [.e configure -bd] 4
} -cleanup {
    destroy .e
} -result {4}
} -result 4
test spinbox-3.18 {SpinboxWidgetCmd procedure, "delete" widget command} -setup {
    spinbox .e 
    spinbox .e
} -body {
    .e delete
} -cleanup {
    destroy .e
} -returnCodes error -result {wrong # args: should be ".e delete firstIndex ?lastIndex?"}
test spinbox-3.19 {SpinboxWidgetCmd procedure, "delete" widget command} -setup {
    spinbox .e 
    spinbox .e
} -body {
    .e delete a b c
} -cleanup {
    destroy .e
} -returnCodes error -result {wrong # args: should be ".e delete firstIndex ?lastIndex?"}
test spinbox-3.20 {SpinboxWidgetCmd procedure, "delete" widget command} -setup {
    spinbox .e 
    spinbox .e
} -body {
    .e delete foo
} -cleanup {
    destroy .e
} -returnCodes error -result {bad spinbox index "foo"}
test spinbox-3.21 {SpinboxWidgetCmd procedure, "delete" widget command} -setup {
    spinbox .e 
    spinbox .e
} -body {
    .e delete 0 bar
} -cleanup {
    destroy .e
} -returnCodes error -result {bad spinbox index "bar"}
test spinbox-3.22 {SpinboxWidgetCmd procedure, "delete" widget command} -setup {
    spinbox .e
    pack .e
    update 
    update
} -body {
    .e insert end "01234567890"
    .e delete 2 4
    .e get
} -cleanup {
    destroy .e
} -result {014567890}
} -result 014567890
test spinbox-3.23 {SpinboxWidgetCmd procedure, "delete" widget command} -setup {
    spinbox .e 
    spinbox .e
} -body {
    .e insert end "01234567890"
    .e delete 6
    .e get
} -cleanup {
    destroy .e
} -result {0123457890}
} -result 0123457890
test spinbox-3.24 {SpinboxWidgetCmd procedure, "delete" widget command} -setup {
    spinbox .e
    pack .e
    update 
    update
    set x {}
} -body {
# UTF
    .e insert end "01234\u4e4e67890"
    .e insert end "0123467890"
    .e delete 6
    lappend x [.e get]
    .e delete 0 end
    .e insert end "012345\u4e4e7890"
    .e insert end "0123457890"
    .e delete 6
    lappend x [.e get]
    .e delete 0 end
    .e insert end "0123456\u4e4e890"
    .e insert end "0123456890"
    .e delete 6
    lappend x [.e get]
} -cleanup {
    destroy .e
} -result [list "01234\u4e4e7890" "0123457890" "012345\u4e4e890"]
} -result [list "012347890" "0123457890" "012345890"]
test spinbox-3.25 {SpinboxWidgetCmd procedure, "delete" widget command} -setup {
    spinbox .e
    pack .e
    update  
    update
} -body {
    .e insert end "01234567890"
    .e delete 6 5
    .e get
} -cleanup {
    destroy .e
} -result {01234567890}
} -result 01234567890
test spinbox-3.26 {SpinboxWidgetCmd procedure, "delete" widget command} -setup {
    spinbox .e
    pack .e
    update  
    update
} -body {
    .e insert end "01234567890"
    .e configure -state disabled
    .e delete 2 8
    .e configure -state normal
    .e get
} -cleanup {
    destroy .e
} -result {01234567890}
} -result 01234567890
test spinbox-3.26.1 {SpinboxWidgetCmd procedure, "delete" widget command} -setup {
    spinbox .e
    pack .e
    update  
    update
} -body {
    .e insert end "01234567890"
    .e configure -state readonly
    .e delete 2 8
    .e configure -state normal
    .e get
} -cleanup {
    destroy .e
} -result {01234567890}
} -result 01234567890
test spinbox-3.27 {SpinboxWidgetCmd procedure, "get" widget command} -setup {
    spinbox .e 
    spinbox .e
} -body {
    .e get foo
} -cleanup {
    destroy .e
} -returnCodes error -result {wrong # args: should be ".e get"}
test spinbox-3.28 {SpinboxWidgetCmd procedure, "icursor" widget command} -setup {
    spinbox .e 
    spinbox .e
} -body {
    .e icursor
} -cleanup {
    destroy .e
} -returnCodes error -result {wrong # args: should be ".e icursor pos"}
test spinbox-3.29 {SpinboxWidgetCmd procedure, "icursor" widget command} -setup {
    spinbox .e 
    spinbox .e
} -body {
    .e icursor foo
} -cleanup {
    destroy .e
} -returnCodes error -result {bad spinbox index "foo"}
test spinbox-3.30 {SpinboxWidgetCmd procedure, "icursor" widget command} -setup {
    spinbox .e 
    spinbox .e
} -body {
    .e insert end "01234567890"
    .e icursor 4
    .e index insert
} -cleanup {
    destroy .e
} -result {4}
} -result 4
test spinbox-3.31 {SpinboxWidgetCmd procedure, "index" widget command} -setup {
    spinbox .e 
    spinbox .e
} -body {
    .e in
} -cleanup {
    destroy .e
} -returnCodes error -result {ambiguous option "in": must be bbox, cget, configure, delete, get, icursor, identify, index, insert, invoke, scan, selection, set, validate, or xview}
test spinbox-3.32 {SpinboxWidgetCmd procedure, "index" widget command} -setup {
    spinbox .e 
    spinbox .e
} -body {
    .e index
} -cleanup {
    destroy .e
} -returnCodes error -result {wrong # args: should be ".e index string"}
test spinbox-3.33 {SpinboxWidgetCmd procedure, "index" widget command} -setup {
    spinbox .e 
    spinbox .e
} -body {
    .e index foo
} -cleanup {
    destroy .e
} -returnCodes error -result {bad spinbox index "foo"}
test spinbox-3.34 {SpinboxWidgetCmd procedure, "index" widget command} -setup {
    spinbox .e
    pack .e
    update  
    update
} -body {
    .e index 0
} -cleanup {
    destroy .e
} -returnCodes {ok} -match glob -result {*}
test spinbox-3.35 {SpinboxWidgetCmd procedure, "index" widget command} -setup {
    spinbox .e
    pack .e
    update  
    update
} -body {
# UTF
    .e insert 0 abc\u4e4e\u0153def
    .e insert 0 abc乎œdef
    list [.e index 3] [.e index 4] [.e index end]
} -cleanup {
    destroy .e
} -result {3 4 8}
test spinbox-3.36 {SpinboxWidgetCmd procedure, "insert" widget command} -setup {
    spinbox .e 
    spinbox .e
} -body {
    .e insert a
} -cleanup {
    destroy .e
} -returnCodes error -result {wrong # args: should be ".e insert index text"}
test spinbox-3.37 {SpinboxWidgetCmd procedure, "insert" widget command} -setup {
    spinbox .e 
    spinbox .e
} -body {
    .e insert a b c
} -cleanup {
    destroy .e
} -returnCodes error -result {wrong # args: should be ".e insert index text"}
test spinbox-3.38 {SpinboxWidgetCmd procedure, "insert" widget command} -setup {
    spinbox .e 
    spinbox .e
} -body {
    .e insert foo Text
} -cleanup {
    destroy .e
} -returnCodes error -result {bad spinbox index "foo"}
test spinbox-3.39 {SpinboxWidgetCmd procedure, "insert" widget command} -setup {
    spinbox .e
    pack .e
    update  
    update
} -body {
    .e insert end "01234567890"
    .e insert 3 xxx
    .e get
} -cleanup {
    destroy .e
} -result {012xxx34567890}
test spinbox-3.40 {SpinboxWidgetCmd procedure, "insert" widget command} -setup {
    spinbox .e
    pack .e
    update  
    update
} -body {
    .e insert end "01234567890"
    .e configure -state disabled
    .e insert 3 xxx
    .e configure -state normal
    .e get
} -cleanup {
    destroy .e
} -result {01234567890}
} -result 01234567890
test spinbox-3.40.1 {SpinboxWidgetCmd procedure, "insert" widget command} -setup {
    spinbox .e
    pack .e
    update  
    update
} -body {
    .e insert end "01234567890"
    .e configure -state readonly
    .e insert 3 xxx
    .e configure -state normal
    .e get
} -cleanup {
    destroy .e
} -result {01234567890}
} -result 01234567890
test spinbox-3.41 {SpinboxWidgetCmd procedure, "insert" widget command} -setup {
    spinbox .e 
    spinbox .e
} -body {
    .e insert a b c
} -cleanup {
    destroy .e
} -returnCodes error -result {wrong # args: should be ".e insert index text"}
test spinbox-3.42 {SpinboxWidgetCmd procedure, "scan" widget command} -setup {
    spinbox .e 
    spinbox .e
    pack .e
    update
} -body {
    .e scan a
} -cleanup {
    destroy .e
} -returnCodes error -result {wrong # args: should be ".e scan mark|dragto x"}
test spinbox-3.43 {SpinboxWidgetCmd procedure, "scan" widget command} -setup {
    spinbox .e
    pack .e
    update 
    update
} -body {
    .e scan a b c
} -cleanup {
    destroy .e
} -returnCodes error -result {wrong # args: should be ".e scan mark|dragto x"}
test spinbox-3.44 {SpinboxWidgetCmd procedure, "scan" widget command} -setup {
    spinbox .e
    pack .e
    update 
    update
} -body {
    .e scan foobar 20
} -cleanup {
    destroy .e
} -returnCodes error -result {bad scan option "foobar": must be mark or dragto}
test spinbox-3.45 {SpinboxWidgetCmd procedure, "scan" widget command} -setup {
    spinbox .e
    pack .e
    update 
    update
} -body {
    .e scan mark 20.1
} -cleanup {
    destroy .e
} -returnCodes error -result {expected integer but got "20.1"}

# This test is non-portable because character sizes vary.
test spinbox-3.46 {SpinboxWidgetCmd procedure, "scan" widget command} -constraints {
    fonts
} -setup {
    spinbox .e -font {Helvetica -12} -borderwidth 2 -highlightthickness 2 
    spinbox .e -font {Helvetica -12} -borderwidth 2 -highlightthickness 2
    pack .e
    update
} -body {
    .e insert end "This is quite a long string, in fact a "
    .e insert end "very very long string"
    .e scan mark 30
    .e scan dragto 28
    .e index @0
} -cleanup {
    destroy .e
} -result {2}
} -result 2
test spinbox-3.47 {SpinboxWidgetCmd procedure, "select" widget command} -setup {
    spinbox .e 
    spinbox .e
} -body {
    .e select
} -cleanup {
    destroy .e
} -returnCodes error -result {wrong # args: should be ".e selection option ?index?"}
test spinbox-3.48 {SpinboxWidgetCmd procedure, "select" widget command} -setup {
    spinbox .e 
    spinbox .e
} -body {
    .e select foo
} -cleanup {
    destroy .e
} -returnCodes error -result {bad selection option "foo": must be adjust, clear, element, from, present, range, or to}

test spinbox-3.49 {SpinboxWidgetCmd procedure, "select clear" widget command} -setup {
    spinbox .e 
    spinbox .e
} -body {
    .e select clear gorp
} -cleanup {
    destroy .e
} -returnCodes error -result {wrong # args: should be ".e selection clear"}
test spinbox-3.50 {SpinboxWidgetCmd procedure, "select clear" widget command} -setup {
    spinbox .e 
    spinbox .e
} -body {
    .e insert end "0123456789"
    .e select from 1
    .e select to 4
    update
    .e select clear
    selection get 
    selection get
} -cleanup {
    destroy .e
} -returnCodes error -result {PRIMARY selection doesn't exist or form "STRING" not defined}
test spinbox-3.50.1 {SpinboxWidgetCmd procedure, "select clear" widget command} -setup {
    spinbox .e
    pack .e
    update  
    update
} -body {
    .e insert end "0123456789"
    .e select from 1
    .e select to 4
    update
    .e select clear
    catch {selection get}
    selection own
} -cleanup {
    destroy .e
} -result {.e}

test spinbox-3.51 {SpinboxWidgetCmd procedure, "selection present" widget command} -setup {
    spinbox .e 
    spinbox .e
} -body {
    .e selection present foo
} -cleanup {
    destroy .e
} -returnCodes error -result {wrong # args: should be ".e selection present"}
test spinbox-3.52 {SpinboxWidgetCmd procedure, "selection present" widget command} -setup {
    spinbox .e
    pack .e
    update  
    update
} -body {
    .e insert end 0123456789
    .e select from 3
    .e select to 6
    .e selection present
} -cleanup {
    destroy .e
} -result {1}
} -result 1
test spinbox-3.53 {SpinboxWidgetCmd procedure, "selection present" widget command} -setup {
    spinbox .e
    pack .e
    update  
    update
} -body {
    .e insert end 0123456789
    .e select from 3
    .e select to 6
    .e configure -exportselection false
    .e selection present
} -cleanup {
    destroy .e
} -result {1}
} -result 1
test spinbox-3.54 {SpinboxWidgetCmd procedure, "selection present" widget command} -setup {
    spinbox .e
    pack .e
    update 
    update
} -body {
    .e insert end 0123456789
    .e select from 3
    .e select to 6
    .e delete 0 end
    .e selection present
} -cleanup {
    destroy .e
} -result {0}
} -result 0
test spinbox-3.55 {SpinboxWidgetCmd procedure, "selection adjust" widget command} -setup {
    spinbox .e
} -body {
    .e select adjust x
} -cleanup {
    destroy .e
} -returnCodes error -result {bad spinbox index "x"}
1593
1594
1595
1596
1597
1598
1599
1600

1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614

1615
1616
1617
1618
1619
1620
1621
1597
1598
1599
1600
1601
1602
1603

1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617

1618
1619
1620
1621
1622
1623
1624
1625







-
+













-
+







    .e select from 1
    .e select to 5
    update
    .e select adjust 4
    selection get
} -cleanup {
    destroy .e
} -result {123}
} -result 123
test spinbox-3.58 {SpinboxWidgetCmd procedure, "selection adjust" widget command} -setup {
    spinbox .e
    pack .e
    update
} -body {
    .e insert end "0123456789"
    .e select from 1
    .e select to 5
    update
    .e select adjust 2
    selection get
} -cleanup {
    destroy .e
} -result {234}
} -result 234
test spinbox-3.59 {SpinboxWidgetCmd procedure, "selection from" widget command} -setup {
    spinbox .e
} -body {
    .e select from 2 3
} -cleanup {
    destroy .e
} -returnCodes error -result {wrong # args: should be ".e selection from index"}
1695
1696
1697
1698
1699
1700
1701
1702

1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714

1715
1716
1717
1718
1719
1720
1721
1722
1723

1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737

1738
1739
1740
1741
1742
1743
1744
1745
1746

1747
1748
1749
1750
1751
1752
1753
1754
1755

1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767

1768
1769
1770
1771
1772
1773
1774
1775
1776

1777
1778

1779
1780
1781
1782
1783
1784
1785
1786
1787

1788
1789

1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802

1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816

1817
1818
1819
1820
1821
1822
1823
1824

1825
1826
1827
1828

1829
1830

1831
1832
1833
1834
1835
1836
1837
1838

1839
1840
1841
1842

1843
1844

1845
1846
1847
1848
1849
1850
1851
1852
1853

1854
1855

1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866

1867
1868
1869
1870
1871
1872
1873
1874

1875
1876
1877
1878

1879
1880

1881
1882
1883
1884
1885
1886
1887
1888
1889
1890

1891
1892

1893
1894
1895
1896
1897

1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914

1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929

1930
1931
1932
1933
1934
1935
1936
1699
1700
1701
1702
1703
1704
1705

1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717

1718
1719
1720
1721
1722
1723
1724
1725
1726

1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740

1741
1742
1743
1744
1745
1746
1747
1748
1749

1750
1751
1752
1753
1754
1755
1756
1757
1758

1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770

1771
1772
1773
1774
1775
1776
1777
1778
1779

1780
1781

1782
1783
1784
1785
1786
1787
1788
1789
1790

1791
1792

1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805

1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819

1820
1821
1822
1823
1824
1825
1826
1827

1828
1829
1830
1831

1832
1833

1834
1835
1836
1837
1838
1839
1840
1841

1842
1843
1844
1845

1846
1847

1848
1849
1850
1851
1852
1853
1854
1855
1856

1857
1858

1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869

1870
1871
1872
1873
1874
1875
1876
1877

1878
1879
1880
1881

1882
1883

1884
1885
1886
1887
1888
1889
1890
1891
1892
1893

1894
1895

1896
1897
1898
1899
1900

1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917

1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932

1933
1934
1935
1936
1937
1938
1939
1940







-
+











-
+








-
+













-
+








-
+








-
+











-
+








-
+

-
+








-
+

-
+












-
+













-
+







-
+



-
+

-
+







-
+



-
+

-
+








-
+

-
+










-
+







-
+



-
+

-
+









-
+

-
+




-
+
















-
+














-
+







    .e configure -state normal
    list [.e index sel.first] [.e index sel.last]
} -cleanup {
    destroy .e
} -result {2 4}

test spinbox-3.65 {SpinboxWidgetCmd procedure, "xview" widget command} -setup {
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
    update
} -body {
    .e insert end "This is quite a long text string, so long that it "
    .e insert end "runs off the end of the window quite a bit."
    .e xview 5
    format {%.6f %.6f} {*}[.e xview]
} -cleanup {
    destroy .e
} -result {0.053763 0.268817}
test spinbox-3.66 {SpinboxWidgetCmd procedure, "xview" widget command} -setup {
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
    update
} -body {
    .e xview gorp
} -cleanup {
    destroy .e
} -returnCodes error -result {bad spinbox index "gorp"}
test spinbox-3.67 {SpinboxWidgetCmd procedure, "xview" widget command} -setup {
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
    update
} -body {
    .e insert end "This is quite a long text string, so long that it "
    .e insert end "runs off the end of the window quite a bit."
    .e xview 0
    .e icursor 10
    .e xview insert
    format {%.6f %.6f} {*}[.e xview]
} -cleanup {
    destroy .e
} -result {0.107527 0.322581}
test spinbox-3.68 {SpinboxWidgetCmd procedure, "xview" widget command} -setup {
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
    update
} -body {
    .e xview moveto foo bar
} -cleanup {
    destroy .e
} -returnCodes error -result {wrong # args: should be ".e xview moveto fraction"}
test spinbox-3.69 {SpinboxWidgetCmd procedure, "xview" widget command} -setup {
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
    update
} -body {
    .e xview moveto foo
} -cleanup {
    destroy .e
} -returnCodes error -result {expected floating-point number but got "foo"}
test spinbox-3.70 {SpinboxWidgetCmd procedure, "xview" widget command} -setup {
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
    update
} -body {
    .e insert end "This is quite a long text string, so long that it "
    .e insert end "runs off the end of the window quite a bit."
    .e xview moveto 0.5
    format {%.6f %.6f} {*}[.e xview]
} -cleanup {
    destroy .e
} -result {0.505376 0.720430}
test spinbox-3.71 {SpinboxWidgetCmd procedure, "xview" widget command} -setup {
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
    update
} -body {
    .e insert end "This is quite a long text string, so long that it "
    .e insert end "runs off the end of the window quite a bit."
    .e xview scroll 24
} -cleanup {
    destroy .e
} -returnCodes error -result {wrong # args: should be ".e xview scroll number units|pages"}
} -returnCodes error -result {wrong # args: should be ".e xview scroll number pages|units"}
test spinbox-3.72 {SpinboxWidgetCmd procedure, "xview" widget command} -setup {
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
} -body {
    .e insert end "This is quite a long text string, so long that it "
    .e insert end "runs off the end of the window quite a bit."
    update
    .e xview scroll gorp units
} -cleanup {
    destroy .e
} -returnCodes error -result {expected integer but got "gorp"}
} -returnCodes error -result {expected floating-point number but got "gorp"}
test spinbox-3.73 {SpinboxWidgetCmd procedure, "xview" widget command} -setup {
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
} -body {
    .e insert end "This is quite a long text string, so long that it "
    .e insert end "runs off the end of the window quite a bit."
    update
    .e xview moveto 0
    .e xview scroll 1 pages
    format {%.6f %.6f} {*}[.e xview]
} -cleanup {
    destroy .e
} -result {0.193548 0.408602}
test spinbox-3.74 {SpinboxWidgetCmd procedure, "xview" widget command} -setup {
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
    update
} -body {
    .e insert end "This is quite a long text string, so long that it "
    .e insert end "runs off the end of the window quite a bit."
    .e xview moveto .9
    update
    .e xview scroll -2 p
    format {%.6f %.6f} {*}[.e xview]
} -cleanup {
    destroy .e
} -result {0.397849 0.612903}
test spinbox-3.75 {SpinboxWidgetCmd procedure, "xview" widget command} -setup {
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
} -body {
    .e insert end "This is quite a long text string, so long that it "
    .e insert end "runs off the end of the window quite a bit."
    update
    .e xview 30
    update
    .e xview scroll 2 units 
    .e xview scroll 2 units
    .e index @0
} -cleanup {
    destroy .e
} -result {32}
} -result 32
test spinbox-3.76 {SpinboxWidgetCmd procedure, "xview" widget command} -setup {
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
} -body {
    .e insert end "This is quite a long text string, so long that it "
    .e insert end "runs off the end of the window quite a bit."
    update
    .e xview 30
    update
    .e xview scroll -1 units 
    .e xview scroll -1 units
    .e index @0
} -cleanup {
    destroy .e
} -result {29}
} -result 29
test spinbox-3.77 {SpinboxWidgetCmd procedure, "xview" widget command} -setup {
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
} -body {
    .e insert end "This is quite a long text string, so long that it "
    .e insert end "runs off the end of the window quite a bit."
    update
    .e xview scroll 23 foobars
} -cleanup {
    destroy .e
} -returnCodes error -result {bad argument "foobars": must be units or pages}
} -returnCodes error -result {bad argument "foobars": must be pages or units}
test spinbox-3.78 {SpinboxWidgetCmd procedure, "xview" widget command} -setup {
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
} -body {
    .e insert end "This is quite a long text string, so long that it "
    .e insert end "runs off the end of the window quite a bit."
    update
    .e xview eat 23 hamburgers
} -cleanup {
    destroy .e
} -returnCodes error -result {unknown option "eat": must be moveto or scroll}
test spinbox-3.79 {SpinboxWidgetCmd procedure, "xview" widget command} -setup {
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
    update
} -body {
    .e insert end "This is quite a long text string, so long that it "
    .e insert end "runs off the end of the window quite a bit."
    .e xview 0
    update
    .e xview -4
    .e xview -1
    .e index @0
} -cleanup {
    destroy .e
} -result {0}
} -result 0
test spinbox-3.80 {SpinboxWidgetCmd procedure, "xview" widget command} -setup {
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
} -body {
    .e insert end "This is quite a long text string, so long that it "
    .e insert end "runs off the end of the window quite a bit."
    update
    .e xview 300
    .e index @0
} -cleanup {
    destroy .e
} -result {73}
} -result 73
test spinbox-3.81 {SpinboxWidgetCmd procedure, "xview" widget command} -setup {
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
} -body {
    .e insert end "This is quite a long text string, so long that it "
    .e insert end "runs off the end of the window quite a bit."
    .e insert 10 \u4e4e
    .e insert 10 
    update
# UTF
# If Tcl_NumUtfChars wasn't used, wrong answer would be:
# 0.106383 0.117021 0.117021
    set x {}
    .e xview moveto .1
    lappend x [format {%.6f} [lindex [.e xview] 0]]
    .e xview moveto .11
    lappend x [format {%.6f} [lindex [.e xview] 0]]
    .e xview moveto .12
    lappend x [format {%.6f} [lindex [.e xview] 0]]
} -cleanup {
    destroy .e
} -result {0.095745 0.106383 0.117021}

test spinbox-3.82 {SpinboxWidgetCmd procedure} -setup {
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2 
    spinbox .e -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .e
    update
} -body {
    .e gorp
} -cleanup {
    destroy .e
} -returnCodes error -result {bad option "gorp": must be bbox, cget, configure, delete, get, icursor, identify, index, insert, invoke, scan, selection, set, validate, or xview}

test spinbox-5.1 {ConfigureSpinbox procedure, -textvariable} -body {
    set x 12345
    spinbox .e -textvariable x
    .e get
} -cleanup {
    destroy .e
} -result {12345}
} -result 12345
test spinbox-5.2 {ConfigureSpinbox procedure, -textvariable} -body {
    set x 12345
    spinbox .e -textvariable x
    set y abcde
    .e configure -textvariable y
    set x 54321
    .e get
1978
1979
1980
1981
1982
1983
1984
1985

1986
1987
1988
1989
1990
1991
1992

1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004

2005
2006
2007
2008
2009
2010
2011

2012
2013
2014
2015

2016

2017
2018

2019
2020
2021
2022
2023
2024
2025
2026
2027
2028

2029
2030
2031
2032
2033
2034
2035
1982
1983
1984
1985
1986
1987
1988

1989
1990
1991
1992
1993
1994
1995

1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007

2008
2009
2010
2011
2012
2013
2014

2015
2016
2017
2018
2019
2020

2021

2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032

2033
2034
2035
2036
2037
2038
2039
2040







-
+






-
+











-
+






-
+




+
-
+
-

+









-
+







    .e1 configure -exportselection 1
    lappend x [selection get]
    set x
} -cleanup {
    destroy .e1 .e2
} -result {{This is so} {This is so} 1234}
test spinbox-5.6 {ConfigureSpinbox procedure} -setup {
    spinbox .e 
    spinbox .e
    pack .e
} -body {
    .e insert end "0123456789"
    .e select from 1
    .e select to 5
    .e configure -exportselection 0
    selection get 
    selection get
} -cleanup {
    destroy .e
} -returnCodes error -result {PRIMARY selection doesn't exist or form "STRING" not defined}
test spinbox-5.6.1 {ConfigureSpinbox procedure} -setup {
    spinbox .e
    pack .e
} -body {
    .e insert end "0123456789"
    .e select from 1
    .e select to 5
    .e configure -exportselection 0
    catch {selection get} 
    catch {selection get}
    list [.e index sel.first] [.e index sel.last]
} -cleanup {
    destroy .e
} -result {1 5}

test spinbox-5.7 {ConfigureSpinbox procedure} -setup {
    spinbox .e -font {Helvetica -12} -borderwidth 2 -highlightthickness 2 
    spinbox .e -font {Helvetica -12} -borderwidth 2 -highlightthickness 2
    pack .e
} -body {
    .e configure -font {Courier -12} -width 4 -xscrollcommand scroll
    .e insert end "01234567890"
    update idletasks
    set timeout [after 500 {set $scrollInfo "timeout"}]
    set timeout [after 500 {set scrollInfo {-1000000 -1000000}}]
    vwait scrollInfo
    .e configure -width 5
    vwait scrollInfo
    format {%.6f %.6f} {*}$scrollInfo
} -cleanup {
    destroy .e
    after cancel $timeout
} -result {0.000000 0.363636}

test spinbox-5.8 {ConfigureSpinbox procedure} -constraints {
    fonts
} -setup {
    spinbox .e -borderwidth 2 -highlightthickness 2 
    spinbox .e -borderwidth 2 -highlightthickness 2
    pack .e
} -body {
    .e configure -width 0 -font {Helvetica -12}
    .e insert end "0123"
    update
    .e configure -font {Helvetica -24}
    update
2070
2071
2072
2073
2074
2075
2076















2077
2078
2079
2080
2081
2082
2083

2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096

2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110

2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122

2123
2124
2125
2126
2127
2128
2129
2130
2131
2132

2133
2134
2135
2136
2137

2138
2139
2140
2141
2142
2143
2144

2145
2146
2147
2148
2149
2150
2151

2152
2153
2154
2155
2156
2157
2158
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102

2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115

2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129

2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141

2142
2143
2144
2145
2146
2147
2148
2149
2150
2151

2152
2153
2154
2155
2156

2157
2158
2159
2160
2161
2162
2163

2164
2165
2166
2167
2168
2169
2170

2171
2172
2173
2174
2175
2176
2177
2178







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






-
+












-
+













-
+











-
+









-
+




-
+






-
+






-
+







# If "0" in selected font had 0 width, caused divide-by-zero error.
    .e configure -font {{open look glyph}}
    .e scan dragto 30
    update
} -cleanup {
    destroy .e
} -result {}
test spinbox-5.12 {ConfigureSpinbox procedure, -from and -to swapping} -setup {
    spinbox .e
} -body {
    # this statement used to trigger error "-to value must be greater than -from value"
    # because default value for -to is zero (bug [841280ffff])
    set res [catch {.e configure -from 10}]
    .e configure -from 1971 -to 2016  ; # standard case
    lappend res [.e cget -from] [.e cget -to]
    .e configure -from 2016 -to 1971  ; # auto-swapping happens
    lappend res [.e cget -from] [.e cget -to]
    .e configure -to 1971 -from 2016 ; # auto-swapping, order of options does not matter
    lappend res [.e cget -from] [.e cget -to]
} -cleanup {
    destroy .e
} -result {0 1971.0 2016.0 1971.0 2016.0 1971.0 2016.0}

# No tests for DisplaySpinbox.

test spinbox-6.1 {SpinboxComputeGeometry procedure} -constraints {
    fonts
} -setup {
    spinbox .e 
    spinbox .e
    pack .e
} -body {
    .e configure -font {Courier -12} -bd 2 -relief raised -width 20 -highlightthickness 3
    .e insert end 012\t45
    update
    list [.e index @61] [.e index @62]
} -cleanup {
    destroy .e
} -result {3 4}
test spinbox-6.2 {SpinboxComputeGeometry procedure} -constraints {
    fonts
} -setup {
    spinbox .e 
    spinbox .e
    pack .e
} -body {
    .e configure -font {Courier -12} -bd 2 -relief raised -width 20 -justify center \
	    -highlightthickness 3
    .e insert end 012\t45
    update
    list [.e index @96] [.e index @97]
} -cleanup {
    destroy .e
} -result {3 4}
test spinbox-6.3 {SpinboxComputeGeometry procedure} -constraints {
    fonts
} -setup {
    spinbox .e 
    spinbox .e
    pack .e
} -body {
    .e configure -font {Courier -12} -bd 2 -relief raised -width 20 -justify right \
	    -highlightthickness 3
    .e insert end 012\t45
    update
    list [.e index @131] [.e index @132]
} -cleanup {
    destroy .e
} -result {3 4}
test spinbox-6.4 {SpinboxComputeGeometry procedure} -setup {
    spinbox .e 
    spinbox .e
    pack .e
} -body {
    .e configure -font {Courier -12} -bd 2 -relief raised -width 5
    .e insert end "01234567890"
    update
    .e xview 6
    .e index @0
} -cleanup {
    destroy .e
} -result {6}
} -result 6
test spinbox-6.5 {SpinboxComputeGeometry procedure} -setup {
    spinbox .e -highlightthickness 2
    pack .e
} -body {
    .e configure -font {Courier -12} -bd 2 -relief raised -width 5 	    
    .e configure -font {Courier -12} -bd 2 -relief raised -width 5
    .e insert end "01234567890"
    update
    .e xview 7
    .e index @0
} -cleanup {
    destroy .e
} -result {6}
} -result 6
test spinbox-6.6 {SpinboxComputeGeometry procedure} -constraints {
    fonts
} -setup {
    spinbox .e -highlightthickness 2
    pack .e
} -body {
    .e configure -font {Courier -12} -bd 2 -relief raised -width 10 
    .e configure -font {Courier -12} -bd 2 -relief raised -width 10
    .e insert end "01234\t67890"
    update
    .e xview 3
    list [.e index @39] [.e index @40]
} -cleanup {
    destroy .e
} -result {5 6}
2184
2185
2186
2187
2188
2189
2190
2191

2192
2193
2194
2195
2196
2197
2198
2199
2200

2201
2202
2203
2204
2205
2206


2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218


2219
2220
2221
2222
2223


2224
2225
2226
2227
2228
2229
2230
2231
2232
2204
2205
2206
2207
2208
2209
2210

2211
2212
2213
2214
2215
2216
2217
2218
2219

2220
2221
2222
2223
2224
2225
2226
2227
2228
2229

2230
2231
2232
2233
2234
2235
2236
2237


2238
2239
2240
2241
2242
2243
2244
2245
2246
2247

2248
2249
2250
2251
2252
2253
2254







-
+








-
+






+
+

-








-
-
+
+





+
+

-







} -result {133 39}
test spinbox-6.9 {SpinboxComputeGeometry procedure} -constraints {
    fonts
} -setup {
    spinbox .e -highlightthickness 2
    pack .e
} -body {
    .e configure -font {Helvetica -24} -bd 3 -relief raised -width 0 
    .e configure -font {Helvetica -24} -bd 3 -relief raised -width 0
    update
    list [winfo reqwidth .e] [winfo reqheight .e]
} -cleanup {
    destroy .e
} -result {42 39}


test spinbox-7.1 {InsertChars procedure} -setup {
    unset -nocomplain contents 
    unset -nocomplain contents
    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
    focus .e
} -body {
    .e configure -textvariable contents -xscrollcommand scroll
    .e insert 0 abcde
    update idletasks
    set timeout [after 500 {set scrollInfo {-1000000 -1000000}}]
    .e insert 2 XXX
    set timeout [after 500 {set $scrollInfo "timeout"}]
    vwait scrollInfo
    list [.e get] $contents [format {%.6f %.6f} {*}$scrollInfo]
} -cleanup {
    destroy .e
    after cancel $timeout
} -result {abXXXcde abXXXcde {0.000000 1.000000}}

test spinbox-7.2 {InsertChars procedure} -setup {
    unset -nocomplain contents 
    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2 
    unset -nocomplain contents
    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
    focus .e
} -body {
    .e configure -textvariable contents -xscrollcommand scroll
    .e insert 0 abcde
    update idletasks
    set timeout [after 500 {set scrollInfo {-1000000 -1000000}}]
    .e insert 500 XXX
    set timeout [after 500 {set $scrollInfo "timeout"}]
    vwait scrollInfo
    list [.e get] $contents [format {%.6f %.6f} {*}$scrollInfo]
} -cleanup {
    destroy .e
    after cancel $timeout
} -result {abcdeXXX abcdeXXX {0.000000 1.000000}}
test spinbox-7.3 {InsertChars procedure} -setup {
2282
2283
2284
2285
2286
2287
2288
2289

2290
2291
2292
2293
2294
2295
2296
2297
2298
2299

2300
2301

2302
2303
2304
2305
2306
2307
2308
2309
2310

2311
2312

2313
2314
2315
2316
2317
2318
2319
2320
2321
2322

2323
2324

2325
2326
2327
2328
2329
2330
2331
2332
2333
2334

2335
2336
2337
2338
2339

2340
2341
2342
2343
2344
2345
2346
2347
2348

2349
2350
2351
2352


2353
2354
2355
2356
2357


2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368


2369
2370
2371
2372
2373
2374
2375



2376
2377
2378
2379
2380
2381
2382
2383
2384


2385
2386
2387
2388
2389


2390
2391
2392
2393
2394
2395
2396
2397
2398
2399

2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415

2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431

2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447

2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461

2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477

2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490

2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506

2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522

2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533

2534
2535

2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546

2547
2548

2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559

2560
2561

2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572

2573
2574

2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585

2586
2587

2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600



2601
2602
2603
2604
2605
2606














2607

2608
2609

2610

2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630

2631
2632
2633
2634
2635
2636
2637
2638
2639

2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652

2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665

2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678

2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690

2691
2692
2693

2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706

2707
2708
2709

2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721

2722
2723
2724

2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735

2736
2737
2738
2739
2740
2741
2742
2304
2305
2306
2307
2308
2309
2310

2311
2312
2313
2314
2315
2316
2317
2318
2319
2320

2321
2322

2323
2324
2325
2326
2327
2328
2329
2330
2331

2332
2333

2334
2335
2336
2337
2338
2339
2340
2341
2342
2343

2344
2345

2346
2347
2348
2349
2350
2351
2352
2353
2354
2355

2356
2357
2358
2359
2360

2361
2362
2363
2364
2365
2366
2367
2368
2369

2370
2371
2372


2373
2374
2375
2376
2377
2378
2379
2380
2381
2382

2383
2384
2385
2386
2387
2388
2389


2390
2391
2392
2393
2394
2395
2396


2397
2398
2399
2400
2401
2402
2403
2404
2405
2406


2407
2408
2409
2410
2411
2412
2413
2414
2415
2416

2417
2418
2419
2420
2421
2422
2423

2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439

2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455

2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471

2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485

2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501

2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514

2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530

2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546

2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557

2558
2559

2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570

2571
2572

2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583

2584
2585

2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596

2597
2598

2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609

2610
2611

2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622



2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645

2646
2647
2648
2649

2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669

2670
2671
2672
2673
2674
2675
2676
2677
2678

2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691

2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704

2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717

2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729

2730
2731
2732

2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745

2746
2747
2748

2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760

2761
2762
2763

2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774

2775
2776
2777
2778
2779
2780
2781
2782







-
+









-
+

-
+








-
+

-
+









-
+

-
+









-
+




-
+








-
+


-
-
+
+





+
+

-







-
-
+
+





-
-
+
+
+







-
-
+
+





+
+

-







-
+















-
+















-
+















-
+













-
+















-
+












-
+















-
+















-
+










-
+

-
+










-
+

-
+










-
+

-
+










-
+

-
+










-
+

-
+










-
-
-
+
+
+






+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+


+
-
+



















-
+








-
+












-
+












-
+












-
+











-
+


-
+












-
+


-
+











-
+


-
+










-
+







    set x "[.e index sel.first] [.e index sel.last]"
    .e select to 5
    lappend x [.e index sel.first] [.e index sel.last]
} -cleanup {
    destroy .e
} -result {2 6 2 5}
test spinbox-7.7 {InsertChars procedure} -setup {
    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2 
    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
} -body {
    .e configure -xscrollcommand scroll
    .e insert 0 0123456789
    .e icursor 4
    .e insert 4 XXX
    .e index insert
} -cleanup {
    destroy .e
} -result {7}
} -result 7
test spinbox-7.8 {InsertChars procedure} -setup {
    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2 
    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
} -body {
    .e insert 0 0123456789
    .e icursor 4
    .e insert 5 XXX
    .e index insert
} -cleanup {
    destroy .e
} -result {4}
} -result 4
test spinbox-7.9 {InsertChars procedure} -setup {
    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2 
    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
} -body {
    .e insert 0 "This is a very long string"
    update
    .e xview 4
    .e insert 3 XXX
    .e index @0
} -cleanup {
    destroy .e
} -result {7}
} -result 7
test spinbox-7.10 {InsertChars procedure} -setup {
    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2 
    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
} -body {
    .e insert 0 "This is a very long string"
    update
    .e xview 4
    .e insert 4 XXX
    .e index @0
} -cleanup {
    destroy .e
} -result {4}
} -result 4

test spinbox-7.11 {InsertChars procedure} -constraints {
    fonts
} -setup {
    spinbox .e -width 0 -font {Courier -12} -highlightthickness 2 -bd 2 
    spinbox .e -width 0 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
} -body {
    .e insert 0 "xyzzy"
    update
    .e insert 2 00
    winfo reqwidth .e
} -cleanup {
    destroy .e
} -result {70}
} -result 70

test spinbox-8.1 {DeleteChars procedure} -setup {
    unset -nocomplain contents 
    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2 
    unset -nocomplain contents
    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
    focus .e
} -body {
    .e configure -textvariable contents -xscrollcommand scroll
    .e insert 0 abcde
    update idletasks
    set timeout [after 500 {set scrollInfo {-1000000 -1000000}}]
    .e delete 2 4
    set timeout [after 500 {set $scrollInfo "timeout"}]
    vwait scrollInfo
    list [.e get] $contents [format {%.6f %.6f} {*}$scrollInfo]
} -cleanup {
    destroy .e
    after cancel $timeout
} -result {abe abe {0.000000 1.000000}}
test spinbox-8.2 {DeleteChars procedure} -setup {
    unset -nocomplain contents 
    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2 
    unset -nocomplain contents
    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
    focus .e
} -body {
    .e configure -textvariable contents -xscrollcommand scroll
    .e insert 0 abcde
    .e delete -2 2
    set timeout [after 500 {set $scrollInfo "timeout"}]
    update idletasks
    set timeout [after 500 {set scrollInfo {-1000000 -1000000}}]
    .e delete -1 2
    vwait scrollInfo
    list [.e get] $contents [format {%.6f %.6f} {*}$scrollInfo]
} -cleanup {
    destroy .e
    after cancel $timeout
} -result {cde cde {0.000000 1.000000}}
test spinbox-8.3 {DeleteChars procedure} -setup {
    unset -nocomplain contents 
    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2 
    unset -nocomplain contents
    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
    focus .e
} -body {
    .e configure -textvariable contents -xscrollcommand scroll
    .e insert 0 abcde
    update idletasks
    set timeout [after 500 {set scrollInfo {-1000000 -1000000}}]
    .e delete 3 1000
    set timeout [after 500 {set $scrollInfo "timeout"}]
    vwait scrollInfo
    list [.e get] $contents [format {%.6f %.6f} {*}$scrollInfo]
} -cleanup {
    destroy .e
    after cancel $timeout
} -result {abc abc {0.000000 1.000000}}
test spinbox-8.4 {DeleteChars procedure} -setup {
    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2 
    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
    focus .e
} -body {
    .e insert 0 0123456789abcde
    .e select from 3
    .e select to 8
    .e delete 1 3
    update
    set x "[.e index sel.first] [.e index sel.last]"
    .e select to 5
    lappend x [.e index sel.first] [.e index sel.last]
} -cleanup {
    destroy .e
} -result {1 6 1 5}
test spinbox-8.5 {DeleteChars procedure} -setup {
    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2 
    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
    focus .e
} -body {
    .e insert 0 0123456789abcde
    .e select from 3
    .e select to 8
    .e delete 1 4
    update
    set x "[.e index sel.first] [.e index sel.last]"
    .e select to 4
    lappend x [.e index sel.first] [.e index sel.last]
} -cleanup {
    destroy .e
} -result {1 5 1 4}
test spinbox-8.6 {DeleteChars procedure} -setup {
    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2 
    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
    focus .e
} -body {
    .e insert 0 0123456789abcde
    .e select from 3
    .e select to 8
    .e delete 1 7
    update
    set x "[.e index sel.first] [.e index sel.last]"
    .e select to 5
    lappend x [.e index sel.first] [.e index sel.last]
} -cleanup {
    destroy .e
} -result {1 2 1 5}
test spinbox-8.7 {DeleteChars procedure} -setup {
    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2 
    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
    focus .e
} -body {
    .e insert 0 0123456789abcde
    .e select from 3
    .e select to 8
    .e delete 1 8
    update
    .e index sel.first
} -cleanup {
    destroy .e
} -returnCodes error -result {selection isn't in widget .e}
test spinbox-8.8 {DeleteChars procedure} -setup {
    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2 
    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
    focus .e
} -body {
    .e insert 0 0123456789abcde
    .e select from 3
    .e select to 8
    .e delete 3 7
    update
    set x "[.e index sel.first] [.e index sel.last]"
    .e select to 8
    lappend x [.e index sel.first] [.e index sel.last]
} -cleanup {
    destroy .e
} -result {3 4 3 8}
test spinbox-8.9 {DeleteChars procedure} -setup {
    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2 
    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
} -body {
    .e insert 0 0123456789abcde
    .e select from 3
    .e select to 8
    .e delete 3 8
    update
    .e index sel.first
} -cleanup {
    destroy .e
} -returnCodes error -result {selection isn't in widget .e}
test spinbox-8.10 {DeleteChars procedure} -setup {
    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2 
    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
    focus .e
} -body {
    .e insert 0 0123456789abcde
    .e select from 8
    .e select to 3
    .e delete 5 8
    update
    set x "[.e index sel.first] [.e index sel.last]"
    .e select to 8
    lappend x [.e index sel.first] [.e index sel.last]
} -cleanup {
    destroy .e
} -result {3 5 5 8}
test spinbox-8.11 {DeleteChars procedure} -setup {
    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2 
    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
    focus .e
} -body {
    .e insert 0 0123456789abcde
    .e select from 8
    .e select to 3
    .e delete 8 10
    update
    set x "[.e index sel.first] [.e index sel.last]"
    .e select to 4
    lappend x [.e index sel.first] [.e index sel.last]
} -cleanup {
    destroy .e
} -result {3 8 4 8}
test spinbox-8.12 {DeleteChars procedure} -setup {
    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2 
    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
    focus .e
} -body {
    .e insert 0 0123456789abcde
    .e icursor 4
    .e delete 1 4
    update
    .e index insert
} -cleanup {
    destroy .e
} -result {1}
} -result 1
test spinbox-8.13 {DeleteChars procedure} -setup {
    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2 
    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
    focus .e
} -body {
    .e insert 0 0123456789abcde
    .e icursor 4
    .e delete 1 5
    update
    .e index insert
} -cleanup {
    destroy .e
} -result {1}
} -result 1
test spinbox-8.14 {DeleteChars procedure} -setup {
    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2 
    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
    focus .e
} -body {
    .e insert 0 0123456789abcde
    .e icursor 4
    .e delete 4 6
    update
    .e index insert
} -cleanup {
    destroy .e
} -result {4}
} -result 4
test spinbox-8.15 {DeleteChars procedure} -setup {
    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2 
    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
    focus .e
} -body {
    .e insert 0 "This is a very long string"
    .e xview 4
    .e delete 1 4
    update
    .e index @0
} -cleanup {
    destroy .e
} -result {1}
} -result 1
test spinbox-8.16 {DeleteChars procedure} -setup {
    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2 
    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
    focus .e
} -body {
    .e insert 0 "This is a very long string"
    .e xview 4
    .e delete 1 5
    update
    .e index @0
} -cleanup {
    destroy .e
} -result {1}
} -result 1
test spinbox-8.17 {DeleteChars procedure} -setup {
    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2 
    spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
    focus .e
} -body {
    .e insert 0 "This is a very long string"
    .e xview 4
    .e delete 4 6
    update
    .e index @0
} -cleanup {
    destroy .e
} -result {4}
test spinbox-8.18 {DeleteChars procedure} -setup {
    spinbox .e -width 0 -font {Courier -12} -highlightthickness 2 -bd 2 
} -result 4
test spinbox-8.18 {DeleteChars procedure} -constraints failsOnUbuntuNoXft -setup {
    spinbox .e -width 0 -font {Courier -12} -highlightthickness 2 -bd 2
    pack .e
    focus .e
} -body {
    .e insert 0 "xyzzy"
    update
    .e delete 2 4
    # To check that deletion actually happened we measure the new width
    # of the widget, based on the measuring width of the remaining text ("xyy")
    # in the widget. For that purpose we have to mirror the code in tkEntry.c
    # for computation of the reqwidth
    # note: XPAD corresponds to the hardcoded    #define XPAD 1
    set XPAD 1
    set buttonWidth [expr { [font measure [.e cget -font] "0"] + 2 * (1 + $XPAD) }]
    if {$buttonWidth < 11} {
        set buttonWidth 11
    }
    set expected [expr { [font measure [.e cget -font] "xyy"] \
                          + 2 * ( [.e cget -borderwidth] + \
                                [.e cget -highlightthickness] + $XPAD ) \
                          + $buttonWidth } ]
    winfo reqwidth .e
    expr {[winfo reqwidth .e] == $expected}
} -cleanup {
    destroy .e
    unset XPAD buttonWidth expected
} -result {42}
} -result 1

test spinbox-9.1 {SpinboxValueChanged procedure} -setup {
    unset -nocomplain x
} -body {
    trace variable x w override
    spinbox .e -textvariable x -width 0
    .e insert 0 foo
    list $x [.e get]
} -cleanup {
    destroy .e
    trace vdelete x w override
} -result {12345 12345}


test spinbox-10.1 {SpinboxSetValue procedure} -constraints fonts -body {
    set x abcde
    set y ab
    spinbox .e  -font {Helvetica -12} -highlightthickness 2 -bd 2  -width 0
    pack .e
    .e configure -textvariable x 
    .e configure -textvariable x
    .e configure -textvariable y
    update
    list [.e get] [winfo reqwidth .e]
} -cleanup {
    destroy .e
} -result {ab 35}
test spinbox-10.2 {SpinboxSetValue procedure, updating selection} -setup {
    unset -nocomplain x
    spinbox .e -font {Helvetica -12} -highlightthickness 2 -bd 2 
    spinbox .e -font {Helvetica -12} -highlightthickness 2 -bd 2
    pack .e
} -body {
    .e configure -textvariable x
    .e insert 0 "abcdefghjklmnopqrstu"
    .e selection range 4 10
    set x "a"
    .e index sel.first
} -cleanup {
    destroy .e
} -returnCodes error -result {selection isn't in widget .e}
test spinbox-10.3 {SpinboxSetValue procedure, updating selection} -setup {
    unset -nocomplain x
    spinbox .e -font {Helvetica -12} -highlightthickness 2 -bd 2 
    spinbox .e -font {Helvetica -12} -highlightthickness 2 -bd 2
    pack .e
} -body {
    .e configure -textvariable x
    .e insert 0 "abcdefghjklmnopqrstu"
    .e selection range 4 10
    set x "abcdefg"
    list [.e index sel.first] [.e index sel.last]
} -cleanup {
    destroy .e
} -result {4 7}
test spinbox-10.4 {SpinboxSetValue procedure, updating selection} -setup {
    unset -nocomplain x
    spinbox .e -font {Helvetica -12} -highlightthickness 2 -bd 2 
    spinbox .e -font {Helvetica -12} -highlightthickness 2 -bd 2
    pack .e
} -body {
    .e configure -textvariable x
    .e insert 0 "abcdefghjklmnopqrstu"
    .e selection range 4 10
    set x "abcdefghijklmn"
    list [.e index sel.first] [.e index sel.last]
} -cleanup {
    destroy .e
} -result {4 10}
test spinbox-10.5 {SpinboxSetValue procedure, updating display position} -setup {
    unset -nocomplain x
    spinbox .e -highlightthickness 2 -bd 2 
    spinbox .e -highlightthickness 2 -bd 2
    pack .e
} -body {
    .e configure -width 10 -font {Courier -12} -textvariable x
    .e insert 0 "abcdefghjklmnopqrstuvwxyz"
    .e xview 10
    update
    set x "abcdefg"
    update
    .e index @0
} -cleanup {
    destroy .e
} -result {0}
} -result 0
test spinbox-10.6 {SpinboxSetValue procedure, updating display position} -setup {
    unset -nocomplain x
    spinbox .e -highlightthickness 2 -bd 2 
    spinbox .e -highlightthickness 2 -bd 2
    pack .e
} -body {
    .e configure -width 10 -font {Courier -12} -textvariable x
    pack .e
    .e insert 0 "abcdefghjklmnopqrstuvwxyz"
    .e xview 10
    update
    set x "1234567890123456789012"
    update
    .e index @0
} -cleanup {
    destroy .e
} -result {10}
} -result 10
test spinbox-10.7 {SpinboxSetValue procedure, updating insertion cursor} -setup {
    unset -nocomplain x
    spinbox .e -highlightthickness 2 -bd 2 
    spinbox .e -highlightthickness 2 -bd 2
    pack .e
    update
} -body {
    .e configure -width 10 -font {Courier -12} -textvariable x
    pack .e
    .e insert 0 "abcdefghjklmnopqrstuvwxyz"
    .e icursor 5
    set x "123"
    .e index insert
} -cleanup {
    destroy .e
} -result {3}
} -result 3
test spinbox-10.8 {SpinboxSetValue procedure, updating insertion cursor} -setup {
    unset -nocomplain x
    spinbox .e -highlightthickness 2 -bd 2 
    spinbox .e -highlightthickness 2 -bd 2
    pack .e
} -body {
    .e configure -width 10 -font {Courier -12} -textvariable x
    pack .e
    .e insert 0 "abcdefghjklmnopqrstuvwxyz"
    .e icursor 5
    set x "123456"
    .e index insert
} -cleanup {
    destroy .e
} -result {5}
} -result 5

test spinbox-11.1 {SpinboxEventProc procedure} -setup {
    spinbox .e -highlightthickness 2 -bd 2 -font {Helvetica -12}
    pack .e
} -body {
    .e insert 0 abcdefg
    destroy .e
2772
2773
2774
2775
2776
2777
2778
2779

2780
2781

2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798

2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811

2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825

2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844

2845
2846
2847
2848
2849
2850
2851
2812
2813
2814
2815
2816
2817
2818

2819
2820

2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837

2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850

2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864

2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883

2884
2885
2886
2887
2888
2889
2890
2891







-
+

-
+
















-
+












-
+













-
+


















-
+







} -body {
    .e insert 0 012345678901234567890
    .e xview 4
    update
    .e index end
} -cleanup {
    destroy .e
} -result {21}
} -result 21
test spinbox-13.2 {GetSpinboxIndex procedure} -body {
    spinbox .e 
    spinbox .e
    .e index abogus
} -cleanup {
    destroy .e
} -returnCodes error -result {bad spinbox index "abogus"}
test spinbox-13.3 {GetSpinboxIndex procedure} -setup {
    spinbox .e -font {Courier -12} -width 5 -bd 2 -relief sunken
    pack .e
} -body {
    .e insert 0 012345678901234567890
    .e xview 4
    update
    .e select from 1
    .e select to 6
    .e index anchor
} -cleanup {
    destroy .e
} -result {1}
} -result 1
test spinbox-13.4 {GetSpinboxIndex procedure} -setup {
    spinbox .e -font {Courier -12} -width 5 -bd 2 -relief sunken
    pack .e
} -body {
    .e insert 0 012345678901234567890
    .e xview 4
    update
    .e select from 4
    .e select to 1
    .e index anchor
} -cleanup {
    destroy .e
} -result {4}
} -result 4
test spinbox-13.5 {GetSpinboxIndex procedure} -setup {
    spinbox .e -font {Courier -12} -width 5 -bd 2 -relief sunken
    pack .e
} -body {
    .e insert 0 012345678901234567890
    .e xview 4
    update
    .e select from 3
    .e select to 15
    .e select adjust 4
    .e index anchor
} -cleanup {
    destroy .e
} -result {15}
} -result 15
test spinbox-13.6 {GetSpinboxIndex procedure} -setup {
    spinbox .e
} -body {
    .e index ebogus
} -cleanup {
    destroy .e
} -returnCodes error -result {bad spinbox index "ebogus"}
test spinbox-13.7 {GetSpinboxIndex procedure} -setup {
    spinbox .e -font {Courier -12} -width 5 -bd 2 -relief sunken
    pack .e
} -body {
    .e insert 0 012345678901234567890
    .e xview 4
    update
    .e icursor 2
    .e index insert
} -cleanup {
    destroy .e
} -result {2}
} -result 2
test spinbox-13.8 {GetSpinboxIndex procedure} -setup {
    spinbox .e
} -body {
    .e index ibogus
} -cleanup {
    destroy .e
} -returnCodes error -result {bad spinbox index "ibogus"}
2860
2861
2862
2863
2864
2865
2866
2867

2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887

2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904

2905
2906
2907
2908
2909
2910
2911
2900
2901
2902
2903
2904
2905
2906

2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926

2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943

2944
2945
2946
2947
2948
2949
2950
2951







-
+



















-
+
















-
+







    .e select to 6
    list [.e index sel.first] [.e index sel.last]
} -cleanup {
    destroy .e
} -result {1 6}

test spinbox-13.10 {GetSpinboxIndex procedure} -constraints x11 -body {
# On unix, when selection is cleared, spinbox widget's internal 
# On unix, when selection is cleared, spinbox widget's internal
# selection range is reset.
# Previous settings:
	spinbox .e -font {Courier -12} -width 5 -bd 2 -relief sunken
	pack .e
	.e insert 0 012345678901234567890
	.e xview 4
	update
    .e select from 1
    .e select to 6
    list [.e index sel.first] [.e index sel.last]
# Testing:
    selection clear .e
    .e index sel.first
} -cleanup {
    destroy .e
} -returnCodes error -result {selection isn't in widget .e}

test spinbox-13.11 {GetSpinboxIndex procedure} -constraints aquaOrWin32 -body {
# On mac and pc, when selection is cleared, spinbox widget remembers
# last selected range.  When selection ownership is restored to 
# last selected range.  When selection ownership is restored to
# spinbox, the old range will be rehighlighted.
# Previous settings:
	spinbox .e -font {Courier -12} -width 5 -bd 2 -relief sunken
	pack .e
	.e insert 0 012345678901234567890
	.e xview 4
	update
    .e select from 1
    .e select to 6
    list [.e index sel.first] [.e index sel.last]
# Testing:
    selection clear .e
    catch {selection get}
    .e index sel.first
} -cleanup {
    destroy .e
} -result {1}           
} -result 1

test spinbox-13.12 {GetSpinboxIndex procedure} -constraints x11 -body {
# Previous settings:
	spinbox .e -font {Courier -12} -width 5 -bd 2 -relief sunken
	pack .e
	.e insert 0 012345678901234567890
	.e xview 4
2952
2953
2954
2955
2956
2957
2958
2959





















2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993


2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008

3009
3010
3011
3012
3013
3014
3015
3016

3017
3018
3019

3020
3021
3022
3023
3024
3025
3026
3027

3028
3029
3030

3031
3032
3033
3034
3035
3036
3037
3038

3039
3040
3041

3042
3043
3044
3045
3046
3047
3048
3049

3050
3051
3052

3053
3054
3055
3056
3057
3058
3059
3060

3061
3062
3063

3064
3065
3066
3067
3068
3069
3070
3071

3072
3073

3074
3075
3076
3077
3078
3079
3080
3081
3082
3083

3084
3085
3086
3087
3088

3089
3090
3091

3092
3093
3094

3095
3096
3097
3098
3099
3100
3101
3102

3103
3104
3105

3106
3107
3108
3109
3110
3111
3112
3113

3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133

3134
3135
3136
3137
3138
3139

3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160

3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175


3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190



3191
3192
3193
3194
3195
3196
3197
3198
3199


3200
3201

3202
3203
3204
3205
3206
3207
3208

3209
3210
3211
3212
3213
3214
3215

3216


3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237

3238
3239
3240
3241
3242
3243
3244
2992
2993
2994
2995
2996
2997
2998

2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031






















3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047

3048
3049
3050
3051
3052
3053
3054
3055

3056
3057
3058

3059
3060
3061
3062
3063
3064
3065
3066

3067
3068
3069

3070
3071
3072
3073
3074
3075
3076
3077

3078
3079
3080

3081
3082
3083
3084
3085
3086
3087
3088

3089
3090
3091

3092
3093
3094
3095
3096
3097
3098
3099

3100
3101
3102

3103
3104
3105
3106
3107
3108
3109
3110

3111
3112

3113
3114
3115
3116
3117
3118
3119
3120
3121
3122

3123
3124
3125
3126
3127

3128
3129
3130

3131
3132
3133

3134
3135
3136
3137
3138
3139
3140
3141

3142
3143
3144

3145
3146
3147
3148
3149
3150
3151
3152

3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172

3173
3174
3175
3176
3177
3178

3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199

3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219

3220
3221
3222
3223
3224
3225
3226
3227
3228
3229


3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244

3245

3246
3247
3248
3249
3250

3251
3252
3253
3254
3255
3256
3257

3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281

3282
3283
3284
3285
3286
3287
3288
3289







-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+












-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+














-
+







-
+


-
+







-
+


-
+







-
+


-
+







-
+


-
+







-
+


-
+







-
+

-
+









-
+




-
+


-
+


-
+







-
+


-
+







-
+



















-
+





-
+




















-
+















+
+


-










-
-
+
+
+









+
+

-
+
-





-
+






-
+

+
+




















-
+







    .e index sbogus
} -cleanup {
    destroy .e
} -returnCodes error -result {bad spinbox index "sbogus"}

test spinbox-13.14 {GetSpinboxIndex procedure} -constraints win -body {
# On mac and pc, when selection is cleared, spinbox widget remembers
# last selected range.  When selection ownership is restored to 
# last selected range.  When selection ownership is restored to
# spinbox, the old range will be rehighlighted.
# Previous settings:
	spinbox .e -font {Courier -12} -width 5 -bd 2 -relief sunken
	pack .e
	.e insert 0 012345678901234567890
	.e xview 4
	update
    .e select from 1
    .e select to 6
    list [.e index sel.first] [.e index sel.last]
# Testing:
    selection clear .e
    selection get
} -cleanup {
    destroy .e
} -returnCodes error -match glob -result {*}

test spinbox-13.14.1 {GetSpinboxIndex procedure} -constraints win -body {
# On mac and pc, when selection is cleared, spinbox widget remembers
# last selected range.  When selection ownership is restored to
# spinbox, the old range will be rehighlighted.
# Previous settings:
	spinbox .e -font {Courier -12} -width 5 -bd 2 -relief sunken
	pack .e
	.e insert 0 012345678901234567890
	.e xview 4
	update
    .e select from 1
    .e select to 6
    list [.e index sel.first] [.e index sel.last]
# Testing:
    selection clear .e
    selection get 
} -cleanup {
    destroy .e
} -returnCodes error -match glob -result {*}

test spinbox-13.14.1 {GetSpinboxIndex procedure} -constraints win -body {
# On mac and pc, when selection is cleared, spinbox widget remembers
# last selected range.  When selection ownership is restored to 
# spinbox, the old range will be rehighlighted.
# Previous settings:
	spinbox .e -font {Courier -12} -width 5 -bd 2 -relief sunken
	pack .e
	.e insert 0 012345678901234567890
	.e xview 4
	update
    .e select from 1
    .e select to 6
    list [.e index sel.first] [.e index sel.last]
# Testing:
    selection clear .e  
    catch {selection get} 
    .e index sbogus      
    catch {selection get}
    .e index sbogus
} -cleanup {
    destroy .e
} -returnCodes error -match glob -result {*}

test spinbox-13.15 {GetSpinboxIndex procedure} -body {
    spinbox .e
    selection clear .e
    .e index @xyz
} -cleanup {
    destroy .e
} -returnCodes error -result {bad spinbox index "@xyz"}

test spinbox-13.16 {GetSpinboxIndex procedure} -constraints fonts -body {
    spinbox .e -width 5 -relief sunken -highlightthickness 2 -bd 2 \
        -font {Courier -12} 
        -font {Courier -12}
    pack .e
    .e insert 0 012345678901234567890
    .e xview 4
    update
    .e index @4
} -cleanup {
    destroy .e
} -result {4}
} -result 4
test spinbox-13.17 {GetSpinboxIndex procedure} -constraints fonts -body {
    spinbox .e -width 5 -relief sunken -highlightthickness 2 -bd 2 \
        -font {Courier -12} 
        -font {Courier -12}
    pack .e
    .e insert 0 012345678901234567890
    .e xview 4
    update
    .e index @11
} -cleanup {
    destroy .e
} -result {4}
} -result 4
test spinbox-13.18 {GetSpinboxIndex procedure} -constraints fonts -body {
    spinbox .e -width 5 -relief sunken -highlightthickness 2 -bd 2 \
        -font {Courier -12} 
        -font {Courier -12}
    pack .e
    .e insert 0 012345678901234567890
    .e xview 4
    update
    .e index @12
} -cleanup {
    destroy .e
} -result {5}
} -result 5
test spinbox-13.19 {GetSpinboxIndex procedure} -constraints fonts -body {
    spinbox .e -width 5 -relief sunken -highlightthickness 2 -bd 2 \
        -font {Courier -12} 
        -font {Courier -12}
    pack .e
    .e insert 0 012345678901234567890
    .e xview 4
    update
    .e index @[expr {[winfo width .e] - 6-11}]
} -cleanup {
    destroy .e
} -result {8}
} -result 8
test spinbox-13.20 {GetSpinboxIndex procedure} -constraints fonts -body {
    spinbox .e -width 5 -relief sunken -highlightthickness 2 -bd 2 \
        -font {Courier -12} 
        -font {Courier -12}
    pack .e
    .e insert 0 012345678901234567890
    .e xview 4
    update
    .e index @[expr {[winfo width .e] - 5}]
} -cleanup {
    destroy .e
} -result {9}
} -result 9
test spinbox-13.21 {GetSpinboxIndex procedure} -body {
    spinbox .e -width 5 -relief sunken -highlightthickness 2 -bd 2 \
        -font {Courier -12} 
        -font {Courier -12}
    pack .e
    .e insert 0 012345678901234567890
    .e xview 4
    update
    .e index @1000
} -cleanup {
    destroy .e
} -result {9}
} -result 9
test spinbox-13.22 {GetSpinboxIndex procedure} -setup {
    spinbox .e 
    spinbox .e
    pack .e
    update
} -body {
    .e index 1xyz
} -cleanup {
    destroy .e
} -returnCodes error -result {bad spinbox index "1xyz"}
test spinbox-13.23 {GetSpinboxIndex procedure} -body {
    spinbox .e -width 5 -relief sunken -highlightthickness 2 -bd 2 \
        -font {Courier -12} 
        -font {Courier -12}
    pack .e
    .e insert 0 012345678901234567890
    .e xview 4
    update
    .e index -10
    .e index -1
} -cleanup {
    destroy .e
} -result {0}
} -result 0
test spinbox-13.24 {GetSpinboxIndex procedure} -body {
    spinbox .e -width 5 -relief sunken -highlightthickness 2 -bd 2 \
        -font {Courier -12} 
        -font {Courier -12}
    pack .e
    .e insert 0 012345678901234567890
    .e xview 4
    update
    .e index 12
} -cleanup {
    destroy .e
} -result {12}
} -result 12
test spinbox-13.25 {GetSpinboxIndex procedure} -body {
    spinbox .e -width 5 -relief sunken -highlightthickness 2 -bd 2 \
        -font {Courier -12} 
        -font {Courier -12}
    pack .e
    .e insert 0 012345678901234567890
    .e xview 4
    update
    .e index 49
} -cleanup {
    destroy .e
} -result {21}
} -result 21

# XXX Still need to write tests for SpinboxScanTo and SpinboxSelectTo.

test spinbox-14.1 {SpinboxFetchSelection procedure} -body {
    spinbox .e
    .e insert end "This is a test string"
    .e select from 1
    .e select to 18
    selection get
} -cleanup {
    destroy .e
} -result {his is a test str}
test spinbox-14.3 {SpinboxFetchSelection procedure} -setup {
    set x {}
    for {set i 1} {$i <= 500} {incr i} {
        append x "This is line $i, out of 500\n"
}
} -body {
    spinbox .e
    .e insert end $x    
    .e insert end $x
    .e select from 0
    .e select to end
    string compare [selection get] $x
} -cleanup {
    destroy .e
} -result {0}
} -result 0

test spinbox-15.1 {SpinboxLostSelection} -body {
    spinbox .e
    .e insert 0 "Text"
    .e select from 0
    .e select to 4
    set result [selection get]
    selection clear
    .e select from 0
    .e select to 4
    lappend result [selection get]
} -cleanup {
    destroy .e
} -result {Text Text}


test spinbox-16.1 {SpinboxVisibleRange procedure} -constraints fonts  -body {
    spinbox .e -width 10 -font {Helvetica -12}
    pack .e
    update
    .e insert 0 "............................." 
    .e insert 0 "............................."
    format {%.6f %.6f} {*}[.e xview]
} -cleanup {
    destroy .e
} -result {0.000000 0.827586}
test spinbox-16.2 {SpinboxVisibleRange procedure} -body {
    spinbox .e
    format {%.6f %.6f} {*}[.e xview]
} -cleanup {
    destroy .e
} -result {0.000000 1.000000}


test spinbox-17.1 {SpinboxUpdateScrollbar procedure} -body {
    spinbox .e -width 10 -xscrollcommand scroll -font {Courier -12}
    pack .e
    update idletasks
    set timeout [after 500 {set scrollInfo {-1000000 -1000000}}]
    .e delete 0 end
    .e insert 0 123
    set timeout [after 500 {set $scrollInfo "timeout"}]
    vwait scrollInfo
    format {%.6f %.6f} {*}$scrollInfo
} -cleanup {
    destroy .e
    after cancel $timeout
} -result {0.000000 1.000000}
test spinbox-17.2 {SpinboxUpdateScrollbar procedure} -body {
    spinbox .e -width 10 -xscrollcommand scroll -font {Courier -12}
    pack .e
    .e insert 0 0123456789abcdef
    .e xview 3
    set timeout [after 500 {set $scrollInfo "timeout"}]
    update idletasks
    set timeout [after 500 {set $scrollInfo {-1000000 -1000000}}]
    .e xview 3
    vwait scrollInfo
    format {%.6f %.6f} {*}$scrollInfo
} -cleanup {
    destroy .e
    after cancel $timeout
} -result {0.187500 0.812500}
test spinbox-17.3 {SpinboxUpdateScrollbar procedure} -body {
    spinbox .e -width 10 -xscrollcommand scroll -font {Courier -12}
    pack .e
    update idletasks
    set timeout [after 500 {set scrollInfo {-1000000 -1000000}}]
    .e insert 0 abcdefghijklmnopqrs
    .e xview 6
    .e xview
    set timeout [after 500 {set $scrollInfo "timeout"}]
    vwait scrollInfo
    format {%.6f %.6f} {*}$scrollInfo
} -cleanup {
    destroy .e
    after cancel $timeout
} -result {0.315789 0.842105}
} -result {0.000000 0.526316}
test spinbox-17.4 {SpinboxUpdateScrollbar procedure} -setup {
    proc bgerror msg {
	global x
	set x $msg
}
} -body {
    spinbox .e -width 5 -xscrollcommand thisisnotacommand
    spinbox .e -width 5
    pack .e
    update idletasks
    .e configure -xscrollcommand thisisnotacommand
    vwait x
    list $x $errorInfo
} -cleanup {
    destroy .e
    rename bgerror {}
} -result {{invalid command name "thisisnotacommand"} {invalid command name "thisisnotacommand"
    while executing
"thisisnotacommand 0.0 1.0"
    (horizontal scrolling command executed by .e)}}


test spinbox-18.1 {Spinbox widget vs hiding} -setup {
    spinbox .e
} -body {
    set l [interp hidden]
    interp hide {} .e
    destroy .e
    set res1 [list [winfo children .] [interp hidden]]
    set res2 [list {} $l]
    expr {$res1 == $res2}
} -result {1} 
} -result 1

##
## Spinbox widget VALIDATION tests
##
# The validation tests build each one upon the previous, so cascading
# failures aren't good
#
3584
3585
3586
3587
3588
3589
3590
3591

3592
3593
3594
3595
3596
3597

3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616

3617
3618
3619
3620
3621
3622




















3623
3624
3625
3626
3627
3628
3629
3629
3630
3631
3632
3633
3634
3635

3636
3637
3638
3639
3640
3641

3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660

3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694







-
+





-
+


















-
+






+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    spinbox .e -validate all \
        -validatecommand [list doval3 %W %d %i %P %s %S %v %V] \
        -invalidcommand bell \
        -textvariable ::e \
        -background red -foreground white
    pack .e
    set ::e nextdata                 ;# previous settings
    

    .e configure -validatecommand [list doval2 %W %d %i %P %s %S %v %V]
    .e validate
    list [.e cget -validate] [.e get] $::vVals
} -cleanup {
    destroy .e
} -result {none mydata {.e -1 -1 nextdata nextdata {} all forced}}
} -result {none nextdata {.e -1 -1 nextdata nextdata {} all forced}}

## This leaves validate alone because we trigger validation through the
## textvar (a write trace), and the write during validation triggers
## nothing (by definition of avoiding loops on var traces).  This is
## one of those "dangerous" conditions where the user will have a
## different value in the spinbox widget shown as is in the textvar.
test spinbox-19.20 {spinbox widget validation} -setup {
    unset -nocomplain ::e ::vVals
} -body {
    spinbox .e -validate all \
        -validatecommand [list doval %W %d %i %P %s %S %v %V] \
        -invalidcommand bell \
        -textvariable ::e \
        -background red -foreground white
    pack .e
    set ::e nextdata                 ;# previous settings
    .e configure -validatecommand [list doval2 %W %d %i %P %s %S %v %V] ;# prev
    .e validate                     ;# previous settings
    

    .e configure -validate all
    set ::e testdata
    list [.e cget -validate] [.e get] $::e $::vVals
} -cleanup {
    destroy .e
} -result {all testdata mydata {.e -1 -1 testdata mydata {} all forced}}

## This leaves validate alone because we trigger validation through the
## textvar (a write trace), and the write during validation triggers
## nothing (by definition of avoiding loops on var traces).  This is
## one of those "dangerous" conditions where the user will have a
## different value in the entry widget shown as is in the textvar.
test spinbox-19.21 {spinbox widget validation - bug 40e4bf6198} -setup {
    unset -nocomplain ::e ::vVals
} -body {
    spinbox .e -validate key \
        -validatecommand [list doval2 %W %d %i %P %s %S %v %V] \
        -textvariable ::e
    pack .e
    set ::e origdata
    .e insert 0 A
    list [.e cget -validate] [.e get] $::e $::vVals
} -cleanup {
    destroy .e
} -result {none origdata mydata {.e 1 0 Aorigdata origdata A key key}}

##
## End validation tests
##

test spinbox-20.1 {spinbox config, -format specifier} -body {
    spinbox .e
    .e config -format %2f
3771
3772
3773
3774
3775
3776
3777
3778

3779
3780
3781
3782
3783
3784
3785
3786

3787
3788
3789
3790
3791
3792
3793
3794

3795
3796
3797
3798
3799
3800
3801
3836
3837
3838
3839
3840
3841
3842

3843
3844
3845
3846
3847
3848
3849
3850

3851
3852
3853
3854
3855
3856
3857
3858

3859
3860
3861
3862
3863
3864
3865
3866







-
+







-
+







-
+








test spinbox-22.1 {spinbox config, -from changes SF bug 559078} -body {
    set val 5
    spinbox .e -from 1 -to 10 -textvariable val
    set val
} -cleanup {
    destroy .e
} -result {5}
} -result 5
test spinbox-22.2 {spinbox config, -from changes SF bug 559078} -body {
    set val 5
    spinbox .e -from 1 -to 10 -textvariable val
    .e configure -from 3 -to 10
    set val
} -cleanup {
    destroy .e
} -result {5}
} -result 5
test spinbox-22.3 {spinbox config, -from changes SF bug 559078} -body {
    set val 5
    spinbox .e -from 3 -to 10 -textvariable val
    .e configure -from 6 -to 10
    set val
} -cleanup {
    destroy .e
} -result {6}
} -result 6

test spinbox-23.1 {selection present while disabled, bug 637828} -body {
    spinbox .e
    .e insert end 0123456789
    .e select from 3
    .e select to 6
    set out [.e selection present]
Added tests/systray.test.































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# This file is a Tcl script to test systray and sysnotify features in Tk.
# It is organized in the standard fashion for Tcl tests.
#
# Copyright © 2020 Kevin Walzer/WordTech Communications LLC.
# Copyright © 2020 Francois Vogel.
# All rights reserved.

package require tcltest 2.2
namespace import ::tcltest::*
eval tcltest::configure $argv
tcltest::loadTestedCommands

test systray-1 {systray icon creation, all options} -setup {
    image create photo _book -data R0lGODlhDwAPAKIAAP//////AP8AAMDAwICAgAAAAAAAAAAAACwAAAAADwAPAAADSQhA2u5ksPeKABKSCaya29d4WKgERFF0l1IMQCAKatvBJ0OTdzzXI1xMB3TBZAvATtB6NSLKleXi3OBoLqrVgc0yv+DVSEUuFxIAOw==
} -body {
    tk systray create -image _book -text "Systray sample" \
            -button1 {puts "button 1 click"} -button3 {puts "button 3 click"}
} -cleanup {
    tk systray destroy
    image delete _book
} -result {}

test systray-2 {systray create, argument checking} -body {
    tk systray create
} -returnCodes {error} -result {missing required option "-image"}

test systray-3 {systray create, argument checking} -body {
    tk systray create -text Hell
} -returnCodes {error} -result {missing required option "-image"}

test systray-4 {systray create, argument checking} -setup {
    image create photo _book -data R0lGODlhDwAPAKIAAP//////AP8AAMDAwICAgAAAAAAAAAAAACwAAAAADwAPAAADSQhA2u5ksPeKABKSCaya29d4WKgERFF0l1IMQCAKatvBJ0OTdzzXI1xMB3TBZAvATtB6NSLKleXi3OBoLqrVgc0yv+DVSEUuFxIAOw==
} -body {
    tk systray create -image _book -gorp invalidOption
} -returnCodes {error} -result {unknown option "-gorp": must be -image, -text, -button1 or -button3}

test systray-5 {systray icon creation, only required option present} -setup {
    image create photo _book -data R0lGODlhDwAPAKIAAP//////AP8AAMDAwICAgAAAAAAAAAAAACwAAAAADwAPAAADSQhA2u5ksPeKABKSCaya29d4WKgERFF0l1IMQCAKatvBJ0OTdzzXI1xMB3TBZAvATtB6NSLKleXi3OBoLqrVgc0yv+DVSEUuFxIAOw==
} -body {
    tk systray create -image _book
} -cleanup {
    tk systray destroy
    image delete _book
} -result {}

test systray-6 {systray icon creation, some options present} -setup {
    image create photo _book -data R0lGODlhDwAPAKIAAP//////AP8AAMDAwICAgAAAAAAAAAAAACwAAAAADwAPAAADSQhA2u5ksPeKABKSCaya29d4WKgERFF0l1IMQCAKatvBJ0OTdzzXI1xMB3TBZAvATtB6NSLKleXi3OBoLqrVgc0yv+DVSEUuFxIAOw==
} -body {
    tk systray create -image _book -button3 {puts b3}
} -cleanup {
    tk systray destroy
    image delete _book
} -result {}

test systray-7 {systray icon, all parameters modification, introspection} -setup {
    image create photo _book -data R0lGODlhDwAPAKIAAP//////AP8AAMDAwICAgAAAAAAAAAAAACwAAAAADwAPAAADSQhA2u5ksPeKABKSCaya29d4WKgERFF0l1IMQCAKatvBJ0OTdzzXI1xMB3TBZAvATtB6NSLKleXi3OBoLqrVgc0yv+DVSEUuFxIAOw==
    image create photo _page -data R0lGODlhCwAPAKIAAP//////AMDAwICAgAAA/wAAAAAAAAAAACwAAAAACwAPAAADMzi6CzAugiAgDGE68aB0RXgRJBFVX0SNpQlUWfahQOvSsgrX7eZJMlQMWBEYj8iQchlKAAA7
} -body {
    tk systray create -image _book -text "Systray icon text"
    tk systray configure -image _page
    tk systray configure -text "Another text for my icon"
    tk systray configure -button1 {set a 1}
    tk systray configure -button3 {set b 2}
    tk systray configure
} -cleanup {
    tk systray destroy
    image delete _book
    image delete _page
} -result {-image _page -text {Another text for my icon} -button1 {set a 1} -button3 {set b 2}}

test systray-8 {systray icon, single parameter modification, introspection} -setup {
    image create photo _book -data R0lGODlhDwAPAKIAAP//////AP8AAMDAwICAgAAAAAAAAAAAACwAAAAADwAPAAADSQhA2u5ksPeKABKSCaya29d4WKgERFF0l1IMQCAKatvBJ0OTdzzXI1xMB3TBZAvATtB6NSLKleXi3OBoLqrVgc0yv+DVSEUuFxIAOw==
} -body {
    tk systray create -image _book -text "Systray icon text" -button1 {puts b1}
    tk systray configure -button1 {set a 1}
    tk systray configure -button1
} -cleanup {
    tk systray destroy
    image delete _book
} -result {set a 1}

test systray-9 {systray icon, several parameters modification at once, introspection} -setup {
    image create photo _book -data R0lGODlhDwAPAKIAAP//////AP8AAMDAwICAgAAAAAAAAAAAACwAAAAADwAPAAADSQhA2u5ksPeKABKSCaya29d4WKgERFF0l1IMQCAKatvBJ0OTdzzXI1xMB3TBZAvATtB6NSLKleXi3OBoLqrVgc0yv+DVSEUuFxIAOw==
} -body {
    tk systray create -image _book -text "Systray icon text" -button1 {puts b1}
    tk systray configure -button1 {set a 1} -text NewText
    list [tk systray configure -button1] [tk systray configure -text]
} -cleanup {
    tk systray destroy
    image delete _book
} -result {{set a 1} NewText}

test systray-10 {configure non-existing systray icon} -setup {
    catch {tk systray destroy}
} -body {
    tk systray configure
} -returnCodes {error} -result {systray not created}

test systray-11 {destroy non-existing systray icon} -setup {
    catch {tk systray destroy}
} -body {
    tk systray destroy
} -returnCodes {error} -result {systray not created}

test systray-12 {destroy systray icon works} -setup {
    image create photo _book -data R0lGODlhDwAPAKIAAP//////AP8AAMDAwICAgAAAAAAAAAAAACwAAAAADwAPAAADSQhA2u5ksPeKABKSCaya29d4WKgERFF0l1IMQCAKatvBJ0OTdzzXI1xMB3TBZAvATtB6NSLKleXi3OBoLqrVgc0yv+DVSEUuFxIAOw==
} -body {
    tk systray create -image _book
    tk systray destroy
    tk systray create -image _book
} -result {}

test systray-13 {systray icon creation, attempt to create more than one in an interp} -setup {
    image create photo _book -data R0lGODlhDwAPAKIAAP//////AP8AAMDAwICAgAAAAAAAAAAAACwAAAAADwAPAAADSQhA2u5ksPeKABKSCaya29d4WKgERFF0l1IMQCAKatvBJ0OTdzzXI1xMB3TBZAvATtB6NSLKleXi3OBoLqrVgc0yv+DVSEUuFxIAOw==
} -body {
    tk systray create -image _book
    tk systray create -image _book
} -cleanup {
    tk systray destroy
    image delete _book
} -returnCodes {error} -result {only one system tray icon supported per interpeter}

test systray-14 {systray icon creation, create one per interp, visibiliy checks} -setup {
    image create photo _book -data R0lGODlhDwAPAKIAAP//////AP8AAMDAwICAgAAAAAAAAAAAACwAAAAADwAPAAADSQhA2u5ksPeKABKSCaya29d4WKgERFF0l1IMQCAKatvBJ0OTdzzXI1xMB3TBZAvATtB6NSLKleXi3OBoLqrVgc0yv+DVSEUuFxIAOw==
} -body {
    tk systray create -image _book -text "first interp"
    interp create second
    # load Tk into the 'second' interp
    foreach pkg [info loaded] {
        if {[lindex $pkg 1] == "Tk"} {
        set loadTk "load $pkg"
        break
        }
    }
    eval $loadTk second
    # create the icon in the 'second' interp
    second eval {
        # should trigger an error: image _book unknown in 'second' interp'
        # image from higer interp should not be visible by 'tk systray'
        tk systray create -image _book -text "second interp"
    }
} -cleanup {
    tk systray destroy
    image delete _book
    interp delete second
} -returnCodes {error} -result {image "_book" doesn't exist}

test systray-15 {systray icon creation, create one per interp} -setup {
    image create photo _book -data R0lGODlhDwAPAKIAAP//////AP8AAMDAwICAgAAAAAAAAAAAACwAAAAADwAPAAADSQhA2u5ksPeKABKSCaya29d4WKgERFF0l1IMQCAKatvBJ0OTdzzXI1xMB3TBZAvATtB6NSLKleXi3OBoLqrVgc0yv+DVSEUuFxIAOw==
} -body {
    tk systray create -image _book -text "first interp"
    interp create second
    # load Tk into the 'second' interp
    foreach pkg [info loaded] {
        if {[lindex $pkg 1] == "Tk"} {
        set loadTk "load $pkg"
        break
        }
    }
    eval $loadTk second
    # create the icon in the 'second' interp
    second eval {
        image create photo _page -data R0lGODlhCwAPAKIAAP//////AMDAwICAgAAA/wAAAAAAAAAAACwAAAAACwAPAAADMzi6CzAugiAgDGE68aB0RXgRJBFVX0SNpQlUWfahQOvSsgrX7eZJMlQMWBEYj8iQchlKAAA7
        tk systray create -image _page -text "second interp"
    }
} -cleanup {
    second eval {
        tk systray destroy
        image delete _page
    }
    interp delete second
    tk systray destroy
    image delete _book
} -result {}

test systray-16 {systray icon creation from a bitmap, on Linux and macOS only} -constraints {
    nonwin
} -setup {
    set data1 {
        #define foo_width 16
        #define foo_height 16
        static unsigned char foo_bits[] = {
           0xff, 0xff, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
           0x81, 0x81, 0xff, 0xff, 0xff, 0xff, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
           0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xff, 0xff
        };
    }
    image create bitmap cross -data $data1
} -body {
    tk systray create -image cross
} -cleanup {
    tk systray destroy
    image delete cross
} -result {}


test sysnotify-1 {system notification popup} -setup {
    image create photo _book -data R0lGODlhDwAPAKIAAP//////AP8AAMDAwICAgAAAAAAAAAAAACwAAAAADwAPAAADSQhA2u5ksPeKABKSCaya29d4WKgERFF0l1IMQCAKatvBJ0OTdzzXI1xMB3TBZAvATtB6NSLKleXi3OBoLqrVgc0yv+DVSEUuFxIAOw==
    tk systray create -image _book -text "Systray sample"
} -body {
    tk sysnotify {Alert} {This is an alert}
} -cleanup {
    tk systray destroy
    image delete _book
} -result {}

test sysnotify-2.1 {system notification stems from a systray icon on Windows} -constraints {
    win
} -setup {
    catch {tk systray destroy}
} -body {
    tk sysnotify {Alert} {This is an alert}
} -returnCodes {error} -result {must create a system tray icon with the "tk systray" command first}
test sysnotify-2.2 {system notification is not linked to any systray icon on X11 or aqua} -constraints {
    nonwin
} -setup {
    catch {tk systray destroy}
} -body {
    tk sysnotify {Alert} {This is an alert}
} -result {}


cleanupTests
Added tests/teapotTransparent.png.

cannot compute difference between binary files

Changes to tests/text.test.
1
2
3
4
5
6



7
8
9
10
11
12
13
1
2
3



4
5
6
7
8
9
10
11
12
13



-
-
-
+
+
+







# This file is a Tcl script to test the code in the file tkText.c.
# This file is organized in the standard fashion for Tcl tests.
#
# Copyright (c) 1992-1994 The Regents of the University of California.
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1992-1994 The Regents of the University of California.
# Copyright © 1994-1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
eval tcltest::configure $argv
tcltest::loadTestedCommands
namespace import -force tcltest::test

24
25
26
27
28
29
30
31

32
33
34
35
36
37
38
39
40

41
42
43
44
45
46
47
24
25
26
27
28
29
30

31
32
33
34
35
36
37
38
39

40
41
42
43
44
45
46
47







-
+








-
+







    pack .t
    update
} -body {
    .t configure -autoseparators yes
    .t cget -autoseparators
} -cleanup {
    destroy .t
} -result {1}
} -result 1
test text-1.1b {configuration option: "autoseparators", default} -setup {
    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}
    pack .t
    update
} -body {
    .t cget -autoseparators
} -cleanup {
    destroy .t
} -result {1}
} -result 1
test text-1.2 {configuration option: "autoseparators"} -setup {
    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}
    pack .t
    update
} -body {
    .t configure -autoseparators nah
} -cleanup {
71
72
73
74
75
76
77
78

79
80
81
82
83
84
85
71
72
73
74
75
76
77

78
79
80
81
82
83
84
85







-
+







    pack .t
    update
} -body {
    .t configure -bd 4
    .t cget -bd
} -cleanup {
    destroy .t
} -result {4}
} -result 4
test text-1.6 {configuration option: "bd"} -setup {
    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}
    pack .t
    update
} -body {
    .t configure -bd foo
} -cleanup {
109
110
111
112
113
114
115
116

117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135

136
137
138
139
140
141
142
109
110
111
112
113
114
115

116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134

135
136
137
138
139
140
141
142







-
+


















-
+







    pack .t
    update
} -body {
    .t configure -blockcursor 0
    .t cget -blockcursor
} -cleanup {
    destroy .t
} -result {0}
} -result 0
test text-1.10 {configuration option: "blockcursor"} -setup {
    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}
    pack .t
    update
} -body {
    .t configure -blockcursor xx
} -cleanup {
    destroy .t
} -match glob -returnCodes {error} -result {*}
test text-1.11 {configuration option: "borderwidth"} -setup {
    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}
    pack .t
    update
} -body {
    .t configure -borderwidth 7
    .t cget -borderwidth
} -cleanup {
    destroy .t
} -result {7}
} -result 7
test text-1.12 {configuration option: "borderwidth"} -setup {
    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}
    pack .t
    update
} -body {
    .t configure -borderwidth ++
} -cleanup {
166
167
168
169
170
171
172
173

174
175
176
177
178
179
180
166
167
168
169
170
171
172

173
174
175
176
177
178
179
180







-
+







    pack .t
    update
} -body {
    .t configure -exportselection no
    .t cget -exportselection
} -cleanup {
    destroy .t
} -result {0}
} -result 0
test text-1.16 {configuration option: "exportselection"} -setup {
    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}
    pack .t
    update
} -body {
    .t configure -exportselection maybe
} -cleanup {
242
243
244
245
246
247
248
249

250
251
252
253
254
255
256
242
243
244
245
246
247
248

249
250
251
252
253
254
255
256







-
+







    pack .t
    update
} -body {
    .t configure -height 5
    .t cget -height
} -cleanup {
    destroy .t
} -result {5}
} -result 5
test text-1.24 {configuration option: "height"} -setup {
    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}
    pack .t
    update
} -body {
    .t configure -height bad
} -cleanup {
299
300
301
302
303
304
305
306

307
308
309
310
311
312
313
299
300
301
302
303
304
305

306
307
308
309
310
311
312
313







-
+







    pack .t
    update
} -body {
    .t configure -highlightthickness -2
    .t cget -highlightthickness
} -cleanup {
    destroy .t
} -result {0}
} -result 0
test text-1.30 {configuration option: "highlightthickness"} -setup {
    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}
    pack .t
    update
} -body {
    .t configure -highlightthickness bad
} -cleanup {
356
357
358
359
360
361
362
363

364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382

383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401

402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420

421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439

440
441
442
443
444
445
446
447
448

449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467

468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486

487
488
489
490
491
492
493
356
357
358
359
360
361
362

363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381

382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400

401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419

420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438

439
440
441
442
443
444
445
446
447

448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466

467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485

486
487
488
489
490
491
492
493







-
+


















-
+


















-
+


















-
+


















-
+








-
+


















-
+


















-
+







    pack .t
    update
} -body {
    .t configure -insertborderwidth 45
    .t cget -insertborderwidth
} -cleanup {
    destroy .t
} -result {45}
} -result 45
test text-1.36 {configuration option: "insertborderwidth"} -setup {
    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}
    pack .t
    update
} -body {
    .t configure -insertborderwidth bogus
} -cleanup {
    destroy .t
} -match glob -returnCodes {error} -result {*}
test text-1.37 {configuration option: "insertofftime"} -setup {
    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}
    pack .t
    update
} -body {
    .t configure -insertofftime 100
    .t cget -insertofftime
} -cleanup {
    destroy .t
} -result {100}
} -result 100
test text-1.38 {configuration option: "insertofftime"} -setup {
    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}
    pack .t
    update
} -body {
    .t configure -insertofftime 2.4
} -cleanup {
    destroy .t
} -match glob -returnCodes {error} -result {*}
test text-1.39 {configuration option: "insertontime"} -setup {
    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}
    pack .t
    update
} -body {
    .t configure -insertontime 47
    .t cget -insertontime
} -cleanup {
    destroy .t
} -result {47}
} -result 47
test text-1.40 {configuration option: "insertontime"} -setup {
    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}
    pack .t
    update
} -body {
    .t configure -insertontime e1
} -cleanup {
    destroy .t
} -match glob -returnCodes {error} -result {*}
test text-1.41 {configuration option: "insertwidth"} -setup {
    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}
    pack .t
    update
} -body {
    .t configure -insertwidth 2.3
    .t cget -insertwidth
} -cleanup {
    destroy .t
} -result {2}
} -result 2
test text-1.42 {configuration option: "insertwidth"} -setup {
    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}
    pack .t
    update
} -body {
    .t configure -insertwidth 47d
} -cleanup {
    destroy .t
} -match glob -returnCodes {error} -result {*}
test text-1.43 {configuration option: "maxundo"} -setup {
    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}
    pack .t
    update
} -body {
    .t configure -maxundo 5
    .t cget -maxundo
} -cleanup {
    destroy .t
} -result {5}
} -result 5
test text-1.43b {configuration option: "maxundo", default} -setup {
    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}
    pack .t
    update
} -body {
    .t cget -maxundo
} -cleanup {
    destroy .t
} -result {0}
} -result 0
test text-1.44 {configuration option: "maxundo"} -setup {
    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}
    pack .t
    update
} -body {
    .t configure -maxundo noway
} -cleanup {
    destroy .t
} -match glob -returnCodes {error} -result {*}
test text-1.45 {configuration option: "padx"} -setup {
    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}
    pack .t
    update
} -body {
    .t configure -padx 3.4
    .t cget -padx
} -cleanup {
    destroy .t
} -result {3}
} -result 3
test text-1.46 {configuration option: "padx"} -setup {
    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}
    pack .t
    update
} -body {
    .t configure -padx 2.4.
} -cleanup {
    destroy .t
} -match glob -returnCodes {error} -result {*}
test text-1.47 {configuration option: "pady"} -setup {
    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}
    pack .t
    update
} -body {
    .t configure -pady 82
    .t cget -pady
} -cleanup {
    destroy .t
} -result {82}
} -result 82
test text-1.48 {configuration option: "pady"} -setup {
    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}
    pack .t
    update
} -body {
    .t configure -pady bogus
} -cleanup {
536
537
538
539
540
541
542
543

544
545
546
547
548
549
550
536
537
538
539
540
541
542

543
544
545
546
547
548
549
550







-
+







    pack .t
    update
} -body {
    .t configure -selectborderwidth 21
    .t cget -selectborderwidth
} -cleanup {
    destroy .t
} -result {21}
} -result 21
test text-1.54 {configuration option: "selectborderwidth"} -setup {
    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}
    pack .t
    update
} -body {
    .t configure -selectborderwidth 3x
} -cleanup {
574
575
576
577
578
579
580
581

582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600

601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619

620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638

639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657

658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676

677
678
679
680
681
682
683
574
575
576
577
578
579
580

581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599

600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618

619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637

638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656

657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675

676
677
678
679
680
681
682
683







-
+


















-
+


















-
+


















-
+


















-
+


















-
+







    pack .t
    update
} -body {
    .t configure -spacing1 20
    .t cget -spacing1
} -cleanup {
    destroy .t
} -result {20}
} -result 20
test text-1.58 {configuration option: "spacing1"} -setup {
    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}
    pack .t
    update
} -body {
    .t configure -spacing1 1.3x
} -cleanup {
    destroy .t
} -match glob -returnCodes {error} -result {*}
test text-1.59 {configuration option: "spacing1"} -setup {
    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}
    pack .t
    update
} -body {
    .t configure -spacing1 -5
    .t cget -spacing1
} -cleanup {
    destroy .t
} -result {0}
} -result 0
test text-1.60 {configuration option: "spacing1"} -setup {
    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}
    pack .t
    update
} -body {
    .t configure -spacing1 bogus
} -cleanup {
    destroy .t
} -match glob -returnCodes {error} -result {*}
test text-1.61 {configuration option: "spacing2"} -setup {
    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}
    pack .t
    update
} -body {
    .t configure -spacing2 5
    .t cget -spacing2
} -cleanup {
    destroy .t
} -result {5}
} -result 5
test text-1.62 {configuration option: "spacing2"} -setup {
    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}
    pack .t
    update
} -body {
    .t configure -spacing2 bogus
} -cleanup {
    destroy .t
} -match glob -returnCodes {error} -result {*}
test text-1.63 {configuration option: "spacing2"} -setup {
    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}
    pack .t
    update
} -body {
    .t configure -spacing2 -1
    .t cget -spacing2
} -cleanup {
    destroy .t
} -result {0}
} -result 0
test text-1.64 {configuration option: "spacing2"} -setup {
    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}
    pack .t
    update
} -body {
    .t configure -spacing2 bogus
} -cleanup {
    destroy .t
} -match glob -returnCodes {error} -result {*}
test text-1.65 {configuration option: "spacing3"} -setup {
    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}
    pack .t
    update
} -body {
    .t configure -spacing3 20
    .t cget -spacing3
} -cleanup {
    destroy .t
} -result {20}
} -result 20
test text-1.66 {configuration option: "spacing3"} -setup {
    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}
    pack .t
    update
} -body {
    .t configure -spacing3 bogus
} -cleanup {
    destroy .t
} -match glob -returnCodes {error} -result {*}
test text-1.67 {configuration option: "spacing3"} -setup {
    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}
    pack .t
    update
} -body {
    .t configure -spacing3 -10
    .t cget -spacing3
} -cleanup {
    destroy .t
} -result {0}
} -result 0
test text-1.68 {configuration option: "spacing3"} -setup {
    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}
    pack .t
    update
} -body {
    .t configure -spacing3 bogus
} -cleanup {
745
746
747
748
749
750
751
752

753
754
755
756
757
758
759
760
761

762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780

781
782
783
784
785
786
787
745
746
747
748
749
750
751

752
753
754
755
756
757
758
759
760

761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779

780
781
782
783
784
785
786
787







-
+








-
+


















-
+







    pack .t
    update
} -body {
    .t configure -undo 1
    .t cget -undo
} -cleanup {
    destroy .t
} -result {1}
} -result 1
test text-1.75b {configuration option: "undo", default} -setup {
    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}
    pack .t
    update
} -body {
    .t cget -undo
} -cleanup {
    destroy .t
} -result {0}
} -result 0
test text-1.76 {configuration option: "undo"} -setup {
    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}
    pack .t
    update
} -body {
    .t configure -undo eh
} -cleanup {
    destroy .t
} -match glob -returnCodes {error} -result {*}
test text-1.77 {configuration option: "width"} -setup {
    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}
    pack .t
    update
} -body {
    .t configure -width 73
    .t cget -width
} -cleanup {
    destroy .t
} -result {73}
} -result 73
test text-1.78 {configuration option: "width"} -setup {
    text .t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold}
    pack .t
    update
} -body {
    .t configure -width 2.4
} -cleanup {
906
907
908
909
910
911
912
913

914
915
916
917
918
919
920
921
922

923
924
925
926
927
928
929
930
931

932
933
934
935
936
937
938
906
907
908
909
910
911
912

913
914
915
916
917
918
919
920
921

922
923
924
925
926
927
928
929
930

931
932
933
934
935
936
937
938







-
+








-
+








-
+







    destroy .t
} -result {2 red}
test text-2.7 {Tk_TextCmd procedure} -constraints {
    win
} -body {
    catch {destroy .t}
    text .t
    .t tag cget sel -relief 
    .t tag cget sel -relief
} -cleanup {
    destroy .t
} -result {flat}
test text-2.8 {Tk_TextCmd procedure} -constraints {
    aqua
} -body {
    catch {destroy .t}
    text .t
    .t tag cget sel -relief 
    .t tag cget sel -relief
} -cleanup {
    destroy .t
} -result {flat}
test text-2.9 {Tk_TextCmd procedure} -constraints {
    unix notAqua
} -body {
    catch {destroy .t}
    text .t
    .t tag cget sel -relief 
    .t tag cget sel -relief
} -cleanup {
    destroy .t
} -result {raised}
test text-2.10 {Tk_TextCmd procedure} -body {
    list [text .t] [winfo class .t]
} -cleanup {
    destroy .t
1000
1001
1002
1003
1004
1005
1006
1007

1008
1009
1010
1011
1012
1013
1014
1000
1001
1002
1003
1004
1005
1006

1007
1008
1009
1010
1011
1012
1013
1014







-
+







test text-5.4 {TextWidgetCmd procedure, "cget" option} -setup {
    text .t
} -body {
    .t configure -bd 17
    .t cget -bd
} -cleanup {
    destroy .t
} -result {17}
} -result 17


test text-6.1 {TextWidgetCmd procedure, "compare" option} -setup {
    text .t
} -body {
    .t compare a b
} -cleanup {
1194
1195
1196
1197
1198
1199
1200
1201

1202
1203
1204
1205
1206
1207
1208
1209

1210
1211
1212
1213
1214
1215
1216
1194
1195
1196
1197
1198
1199
1200

1201
1202
1203
1204
1205
1206
1207
1208

1209
1210
1211
1212
1213
1214
1215
1216







-
+







-
+







test text-7.3 {TextWidgetCmd procedure, "debug" option} -setup {
    text .t
} -body {
    .t debug true
    .t deb
} -cleanup {
    destroy .t
} -result {1}
} -result 1
test text-7.4 {TextWidgetCmd procedure, "debug" option} -setup {
    text .t
} -body {
    .t debug false
    .t debug
} -cleanup {
    destroy .t
} -result {0}
} -result 0


test text-8.1 {TextWidgetCmd procedure, "delete" option} -setup {
    text .t
} -body {
    .t delete
} -cleanup {
1248
1249
1250
1251
1252
1253
1254
1255

1256
1257
1258
1259
1260
1261
1262
1248
1249
1250
1251
1252
1253
1254

1255
1256
1257
1258
1259
1260
1261
1262







-
+







12345
Line 4
bOy GIrl .#@? x_yz
!@#$%
Line 7"
    .t configure -state disabled
    .t delete 2.3
    .t g 2.0 2.end
    .t get 2.0 2.end
} -cleanup {
    destroy .t
} -result {abcdefghijklm}
test text-8.6 {TextWidgetCmd procedure, "delete" option} -setup {
    text .t
} -body {
    .t insert 1.0 "Line 1
1454
1455
1456
1457
1458
1459
1460
1461

1462
1463
1464
1465
1466
1467
1468
1454
1455
1456
1457
1458
1459
1460

1461
1462
1463
1464
1465
1466
1467
1468







-
+







    .t configure -undo 1
    # Ensure it is treated as a single undo action
    .t replace 2.1 2.3 foo
    .t edit undo
    string equal [.t get 1.0 end-1c] $prevtext
} -cleanup {
    destroy .t
} -result {1}
} -result 1
test text-8.22 {TextWidgetCmd procedure, "replace" option with undo} -setup {
    text .t
    set res {}
} -body {
    .t insert 1.0 "Line 1
aefghijklm
12345
1481
1482
1483
1484
1485
1486
1487
1488













1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505

1506
1507

1508
1509
1510
1511
1512

1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531

1532
1533
1534

1535
1536
1537
1538
1539

1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560

1561
1562

1563
1564
1565
1566
1567

1568
1569
1570
1571
1572
1573
1574
1481
1482
1483
1484
1485
1486
1487

1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516

1517
1518

1519
1520
1521
1522
1523

1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542

1543
1544
1545

1546
1547
1548
1549
1550

1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571

1572
1573

1574
1575
1576
1577
1578

1579
1580
1581
1582
1583
1584
1585
1586







-
+
+
+
+
+
+
+
+
+
+
+
+
+
















-
+

-
+




-
+


















-
+


-
+




-
+




















-
+

-
+




-
+







    proc .t {args} { lappend ::res $args ; uplevel 1 test.t $args }
    .t edit undo
    return $res
} -cleanup {
    rename .t {}
    rename test.t .t
    destroy .t
} -result {{edit undo} {delete 2.1 2.4} {mark set insert 2.1} {see insert} {insert 2.1 ef} {mark set insert 2.3} {see insert}}
} -result [list {edit undo} {delete 2.1 2.4} {mark set insert 2.1} {see insert} \
                {mark set tk::undoMarkL2 2.1} {mark set tk::undoMarkR2 2.4} \
                {mark gravity tk::undoMarkL2 left} {mark gravity tk::undoMarkR2 right} \
                {insert 2.1 ef} {mark set insert 2.3} {see insert} \
                {mark set tk::undoMarkL1 2.1} {mark set tk::undoMarkR1 2.3} \
                {mark gravity tk::undoMarkL1 left} {mark gravity tk::undoMarkR1 right} \
                {mark names} \
                {index tk::undoMarkL1} {index tk::undoMarkR1} \
                {mark unset tk::undoMarkL1 tk::undoMarkR1} \
                {index tk::undoMarkL2} {index tk::undoMarkR2} \
                {mark unset tk::undoMarkL2 tk::undoMarkR2} \
                {compare 2.1 > 2.3} {compare 2.6 > 2.3} ]

test text-8.23 {TextWidgetCmd procedure, "replace" option with undo} -setup {
    text .t
} -body {
    .t insert 1.0 "Line 1
aefghijklm
12345
Line 4
bOy GIrl .#@? x_yz
!@#$%
Line 7"
    set prevtext [.t get 1.0 end-1c]
    .t configure -undo 0
    .t configure -undo 1
    # Ensure that undo (even composite undo like 'replace')
    # works when the widget shows nothing useful.
    .t replace 2.1 2.3 foo
    .t configure -start 1 -end 1
    .t configure -startline 1 -endline 1
    .t edit undo
    .t configure -start {} -end {}
    .t configure -startline {} -endline {}
    .t configure -undo 0
    string equal [.t get 1.0 end-1c] $prevtext
} -cleanup {
    destroy .t
} -result {1}
} -result 1
test text-8.24 {TextWidgetCmd procedure, "replace" option with peers, undo} -setup {
    text .t
} -body {
    .t insert 1.0 "Line 1
aefghijklm
12345
Line 4
bOy GIrl .#@? x_yz
!@#$%
Line 7"
    set prevtext [.t get 1.0 end-1c]
    .t configure -undo 0
    .t configure -undo 1
    .t peer create .tt -undo 1
# Ensure that undo (even composite undo like 'replace')
# works when the the event took place in one peer, which
# is then deleted, before the undo takes place in another peer.
    .tt replace 2.1 2.3 foo
    .tt configure -start 1 -end 1
    .tt configure -startline 1 -endline 1
    destroy .tt
    .t edit undo
    .t configure -start {} -end {}
    .t configure -startline {} -endline {}
    .t configure -undo 0
    string equal [.t get 1.0 end-1c] $prevtext
} -cleanup {
    destroy .t
} -result {1}
} -result 1
test text-8.25 {TextWidgetCmd procedure, "replace" option with peers, undo} -setup {
    text .t
} -body {
    .t insert 1.0 "Line 1
aefghijklm
12345
Line 4
bOy GIrl .#@? x_yz
!@#$%
Line 7"
    set prevtext [.t get 1.0 end-1c]
    .t configure -undo 0
    .t configure -undo 1
    .t peer create .tt -undo 1
# Ensure that undo (even composite undo like 'replace')
# works when the the event took place in one peer, which
# is then deleted, before the undo takes place in another peer
# which isn't showing everything.
    .tt replace 2.1 2.3 foo
    set res [.tt get 2.1 2.4]
    .tt configure -start 1 -end 1
    .tt configure -startline 1 -endline 1
    destroy .tt
    .t configure -start 3 -end 4
    .t configure -startline 3 -endline 4
# msg will actually be set to a silently ignored error message here,
# (that the .tt command doesn't exist), but that is not important.
    lappend res [catch {.t edit undo}]
    .t configure -undo 0
    .t configure -start {} -end {}
    .t configure -startline {} -endline {}
    lappend res [string equal [.t get 1.0 end-1c] $prevtext]
} -cleanup {
    destroy .t
} -result {foo 0 1}
test text-8.26 {TextWidgetCmd procedure, "replace" option crash} -setup {
    text .tt
} -body {
2031
2032
2033
2034
2035
2036
2037
2038

2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059

2060
2061
2062
2063
2064
2065
2066
2043
2044
2045
2046
2047
2048
2049

2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070

2071
2072
2073
2074
2075
2076
2077
2078







-
+




















-
+







Line 4
bOy GIrl .#@? x_yz
!@#$%
Line 7"
    .t tag configure elide -elide 1
    .t tag add elide 5.2 5.4
    .t window create 5.4
    .t delete 5.4 
    .t delete 5.4
    .t tag add elide 5.5 5.6
    .t get -displaychars 5.2 5.8
} -cleanup {
    destroy .t
} -result {Grl}


test text-10.1 {TextWidgetCmd procedure, "count" option} -setup {
    text .t
} -body {
    .t count
} -cleanup {
    destroy .t
} -returnCodes {error} -result {wrong # args: should be ".t count ?-option value ...? index1 index2"}
test text-10.2 {TextWidgetCmd procedure, "count" option} -setup {
    text .t
} -body {
    .t count blah 1.0 2.0
} -cleanup {
    destroy .t
} -returnCodes {error} -result {bad option "blah" must be -chars, -displaychars, -displayindices, -displaylines, -indices, -lines, -update, -xpixels, or -ypixels}
} -returnCodes {error} -result {bad option "blah": must be -chars, -displaychars, -displayindices, -displaylines, -indices, -lines, -update, -xpixels, or -ypixels}
test text-10.3 {TextWidgetCmd procedure, "count" option} -setup {
    text .t
} -body {
    .t count a b
} -cleanup {
    destroy .t
} -returnCodes {error} -result {bad text index "a"}
2087
2088
2089
2090
2091
2092
2093
2094

2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108

2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122

2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136

2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150

2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164

2165
2166
2167
2168
2169
2170
2171
2099
2100
2101
2102
2103
2104
2105

2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119

2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133

2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147

2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161

2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175

2176
2177
2178
2179
2180
2181
2182
2183







-
+













-
+













-
+













-
+













-
+













-
+







bOy GIrl .#@? x_yz
!@#$%
Line 7"
} -body {
    .t count 5.7 5.3
} -cleanup {
    destroy .t
} -result {-4}
} -result -4
test text-10.7 {TextWidgetCmd procedure, "count" option} -setup {
    text .t
    .t insert 1.0 "Line 1
aefghijklm
12345
Line 4
bOy GIrl .#@? x_yz
!@#$%
Line 7"
} -body {
    .t count 5.3 5.5
} -cleanup {
    destroy .t
} -result {2}
} -result 2
test text-10.8 {TextWidgetCmd procedure, "count" option} -setup {
    text .t
} -body {
    .t insert 1.0 "Line 1
aefghijklm
12345
Line 4
bOy GIrl .#@? x_yz
!@#$%
Line 7"
    .t count 5.3 end
} -cleanup {
    destroy .t
} -result {29}
} -result 29
test text-10.9 {TextWidgetCmd procedure, "count" option} -setup {
    text .t
    .t insert 1.0 "Line 1
aefghijklm
12345
Line 4
bOy GIrl .#@? x_yz
!@#$%
Line 7"
} -body {
    .t count 5.2 5.7
} -cleanup {
    destroy .t
} -result {5}
} -result 5
test text-10.10 {TextWidgetCmd procedure, "count" option} -setup {
    text .t
    .t insert 1.0 "Line 1
aefghijklm
12345
Line 4
bOy GIrl .#@? x_yz
!@#$%
Line 7"
} -body {
    .t count 5.2 5.3
} -cleanup {
    destroy .t
} -result {1}
} -result 1
test text-10.11 {TextWidgetCmd procedure, "count" option} -setup {
    text .t
    .t insert 1.0 "Line 1
aefghijklm
12345
Line 4
bOy GIrl .#@? x_yz
!@#$%
Line 7"
} -body {
    .t count 5.2 5.4
} -cleanup {
    destroy .t
} -result {2}
} -result 2
test text-10.12 {TextWidgetCmd procedure, "count" option} -setup {
    text .t
    .t insert 1.0 "Line 1
aefghijklm
12345
Line 4
bOy GIrl .#@? x_yz
2187
2188
2189
2190
2191
2192
2193
2194

2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210

2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227

2228
2229
2230
2231
2232
2233
2234
2199
2200
2201
2202
2203
2204
2205

2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221

2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238

2239
2240
2241
2242
2243
2244
2245
2246







-
+















-
+
















-
+







!@#$%
Line 7"
    .t tag configure elide -elide 1
    .t tag add elide 2.2 3.4
    .t count -displayindices 2.0 3.0
} -cleanup {
    destroy .t
} -result {2}
} -result 2
test text-10.14 {TextWidgetCmd procedure, "count" option} -setup {
    text .t
} -body {
    .t insert 1.0 "Line 1
aefghijklm
12345
Line 4
bOy GIrl .#@? x_yz
!@#$%
Line 7"
    .t tag configure elide -elide 1
    .t tag add elide 2.2 3.4
    .t count -displayindices 2.2 3.0
} -cleanup {
    destroy .t
} -result {0}
} -result 0
test text-10.15 {TextWidgetCmd procedure, "count" option} -setup {
    text .t
} -body {
    .t insert 1.0 "Line 1
aefghijklm
12345
Line 4
bOy GIrl .#@? x_yz
!@#$%
Line 7"
    .t tag configure elide -elide 1
    .t tag add elide 2.2 3.4
    .t tag add elide 4.0 4.1
    .t count -displayindices 2.0 4.2
} -cleanup {
    destroy .t
} -result {5}
} -result 5
test text-10.16 {TextWidgetCmd procedure, "count" option} -setup {
    text .t
} -body {
    .t insert 1.0 "Line 1
aefghijklm
12345
Line 4
2243
2244
2245
2246
2247
2248
2249
2250

2251
2252
2253
2254
2255
2256
2257
2255
2256
2257
2258
2259
2260
2261

2262
2263
2264
2265
2266
2267
2268
2269







-
+







# Creating this window here means that the elidden text
# now starts at 2.3
    .t window create 2.1 -window .t.w1
    .t window create 3.1 -window .t.w2
    .t count -displayindices 2.0 3.0
} -cleanup {
    destroy .t
} -result {3}
} -result 3
test text-10.17 {TextWidgetCmd procedure, "count" option} -setup {
    text .t
} -body {
    .t insert 1.0 "Line 1
aefghijklm
12345
Line 4
2266
2267
2268
2269
2270
2271
2272
2273

2274
2275
2276
2277
2278
2279
2280
2278
2279
2280
2281
2282
2283
2284

2285
2286
2287
2288
2289
2290
2291
2292







-
+







# Creating this window here means that the elidden text
# now starts at 2.3
    .t window create 2.1 -window .t.w1
    .t window create 3.1 -window .t.w2
    .t count -displayindices 2.2 3.0
} -cleanup {
    destroy .t
} -result {1}
} -result 1
test text-10.18 {TextWidgetCmd procedure, "count" option} -setup {
    text .t
} -body {
    .t insert 1.0 "Line 1
aefghijklm
12345
Line 4
2291
2292
2293
2294
2295
2296
2297
2298

2299
2300
2301
2302
2303
2304
2305
2303
2304
2305
2306
2307
2308
2309

2310
2311
2312
2313
2314
2315
2316
2317







-
+







# Creating this window here means that the elidden text
# now starts at 2.3, but 'a' is automatically moved to 2.3
    .t window create 2.1 -window .t.w1
    .t window create 3.1 -window .t.w2
    .t count -displayindices a 3.0
} -cleanup {
    destroy .t
} -result {0}
} -result 0
test text-10.19 {TextWidgetCmd procedure, "count" option} -setup {
    text .t
} -body {
    .t insert 1.0 "Line 1
aefghijklm
12345
Line 4
2315
2316
2317
2318
2319
2320
2321
2322

2323
2324
2325
2326
2327
2328
2329
2327
2328
2329
2330
2331
2332
2333

2334
2335
2336
2337
2338
2339
2340
2341







-
+







# Creating this window here means that the elidden text
# now starts at 2.3
    .t window create 2.1 -window .t.w1
    .t window create 3.1 -window .t.w2
    .t count -displayindices 2.0 4.2
} -cleanup {
    destroy .t
} -result {6}
} -result 6
test text-10.20 {TextWidgetCmd procedure, "count" option} -setup {
    text .t
} -body {
    .t insert 1.0 "Line 1
aefghijklm
12345
Line 4
2339
2340
2341
2342
2343
2344
2345
2346

2347
2348
2349
2350
2351
2352
2353
2351
2352
2353
2354
2355
2356
2357

2358
2359
2360
2361
2362
2363
2364
2365







-
+







# Creating this window here means that the elidden text
# now starts at 2.3
    .t window create 2.1 -window .t.w1
    .t window create 3.1 -window .t.w2
    .t count -displaychars 2.0 3.0
} -cleanup {
    destroy .t
} -result {2}
} -result 2
test text-10.21 {TextWidgetCmd procedure, "count" option} -setup {
    text .t
} -body {
    .t insert 1.0 "Line 1
aefghijklm
12345
Line 4
2363
2364
2365
2366
2367
2368
2369
2370

2371
2372
2373
2374
2375
2376
2377
2375
2376
2377
2378
2379
2380
2381

2382
2383
2384
2385
2386
2387
2388
2389







-
+







# Creating this window here means that the elidden text
# now starts at 2.3
    .t window create 2.1 -window .t.w1
    .t window create 3.1 -window .t.w2
    .t count -displaychars 2.2 3.0
} -cleanup {
    destroy .t
} -result {1}
} -result 1
test text-10.22 {TextWidgetCmd procedure, "count" option} -setup {
    text .t
} -body {
    .t insert 1.0 "Line 1
aefghijklm
12345
Line 4
2388
2389
2390
2391
2392
2393
2394
2395

2396
2397
2398
2399
2400
2401
2402
2400
2401
2402
2403
2404
2405
2406

2407
2408
2409
2410
2411
2412
2413
2414







-
+







# Creating this window here means that the elidden text
# now starts at 2.3, but 'a' is automatically moved to 2.3
    .t window create 2.1 -window .t.w1
    .t window create 3.1 -window .t.w2
    .t count -displaychars a 3.0
} -cleanup {
    destroy .t
} -result {0}
} -result 0
test text-10.23 {TextWidgetCmd procedure, "count" option} -setup {
    text .t
} -body {
    .t insert 1.0 "Line 1
aefghijklm
12345
Line 4
2412
2413
2414
2415
2416
2417
2418
2419

2420
2421
2422
2423
2424
2425
2426
2424
2425
2426
2427
2428
2429
2430

2431
2432
2433
2434
2435
2436
2437
2438







-
+







# Creating this window here means that the elidden text
# now starts at 2.3
    .t window create 2.1 -window .t.w1
    .t window create 3.1 -window .t.w2
    .t count -displaychars 2.0 4.2
} -cleanup {
    destroy .t
} -result {5}
} -result 5
test text-10.24 {TextWidgetCmd procedure, "count" option} -setup {
    text .t
} -body {
    .t insert 1.0 "Line 1
aefghijklm
12345
Line 4
2487
2488
2489
2490
2491
2492
2493
2494

2495
2496
2497
2498
2499
2500
2501
2499
2500
2501
2502
2503
2504
2505

2506
2507
2508
2509
2510
2511
2512
2513







-
+







# now starts at 2.3
    .t window create 2.1 -window .t.w1
    .t window create 3.1 -window .t.w2
    .t count -displaychars 2.0 4.2
    .t count -indices 2.0 4.2
} -cleanup {
    destroy .t
} -result {21}
} -result 21
test text-10.27 {TextWidgetCmd procedure, "count" option} -setup {
    text .t
} -body {
    .t insert 1.0 "Line 1
aefghijklm
12345
Line 4
2512
2513
2514
2515
2516
2517
2518
2519

2520
2521
2522
2523
2524
2525
2526
2524
2525
2526
2527
2528
2529
2530

2531
2532
2533
2534
2535
2536
2537
2538







-
+







# now starts at 2.3
    .t window create 2.1 -window .t.w1
    .t window create 3.1 -window .t.w2
    .t count -displaychars 2.0 4.2
    .t count -chars 2.2 3.0
} -cleanup {
    destroy .t
} -result {10}
} -result 10
test text-10.28 {TextWidgetCmd procedure, "count" option} -setup {
    text .t
} -body {
    .t insert 1.0 "Line 1
aefghijklm
12345
Line 4
2537
2538
2539
2540
2541
2542
2543
2544

2545
2546
2547
2548
2549
2550
2551
2549
2550
2551
2552
2553
2554
2555

2556
2557
2558
2559
2560
2561
2562
2563







-
+







# Creating this window here means that the elidden text
# now starts at 2.3, but 'a' is automatically moved to 2.3
    .t window create 2.1 -window .t.w1
    .t window create 3.1 -window .t.w2
    .t count -chars a 3.0
} -cleanup {
    destroy .t
} -result {9}
} -result 9
test text-10.29 {TextWidgetCmd procedure, "count" option} -setup {
    text .t
} -body {
    .t insert 1.0 "Line 1
aefghijklm
12345
Line 4
2562
2563
2564
2565
2566
2567
2568
2569

2570
2571
2572
2573
2574
2575
2576
2577
2578
2579

2580
2581
2582
2583
2584
2585
2586
2587
2588
2589

2590
2591
2592
2593
2594
2595
2596
2597
2598
2599

2600
2601
2602
2603
2604
2605
2606
2607
2608
2609

2610
2611
2612
2613
2614
2615
2616
2617
2618
2619

2620
2621
2622
2623
2624
2625
2626
2627
2628
2629

2630
2631
2632
2633
2634
2635
2636
2637
2638
2639

2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650

2651
2652
2653
2654
2655
2656
2657
2574
2575
2576
2577
2578
2579
2580

2581
2582
2583
2584
2585
2586
2587
2588
2589
2590

2591
2592
2593
2594
2595
2596
2597
2598
2599
2600

2601
2602
2603
2604
2605
2606
2607
2608
2609
2610

2611
2612
2613
2614
2615
2616
2617
2618
2619
2620

2621
2622
2623
2624
2625
2626
2627
2628
2629
2630

2631
2632
2633
2634
2635
2636
2637
2638
2639
2640

2641
2642
2643
2644
2645
2646
2647
2648
2649
2650

2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661

2662
2663
2664
2665
2666
2667
2668
2669







-
+









-
+









-
+









-
+









-
+









-
+









-
+









-
+










-
+







# now starts at 2.3
    .t window create 2.1 -window .t.w1
    .t window create 3.1 -window .t.w2
    .t count -displaychars 2.0 4.2
    .t count -chars 2.0 4.2
} -cleanup {
    destroy .t
} -result {19}
} -result 19
test text-10.30 {TextWidgetCmd procedure, "count" option} -setup {
    text .t
} -body {
    .t insert end [string repeat "abcde " 50]\n
    .t insert end [string repeat "fghij " 50]\n
    .t insert end [string repeat "klmno " 50]
    .t count -lines 1.0 end
} -cleanup {
    destroy .t
} -result {3}
} -result 3
test text-10.31 {TextWidgetCmd procedure, "count" option} -setup {
    text .t
} -body {
    .t insert end [string repeat "abcde " 50]\n
    .t insert end [string repeat "fghij " 50]\n
    .t insert end [string repeat "klmno " 50]
    .t count -lines end 1.0
} -cleanup {
    destroy .t
} -result {-3}
} -result -3
test text-10.32 {TextWidgetCmd procedure, "count" option} -setup {
    text .t
} -body {
    .t insert end [string repeat "abcde " 50]\n
    .t insert end [string repeat "fghij " 50]\n
    .t insert end [string repeat "klmno " 50]
    .t count -lines 1.0 2.0 3.0
} -cleanup {
    destroy .t
} -returnCodes {error} -result {bad option "1.0" must be -chars, -displaychars, -displayindices, -displaylines, -indices, -lines, -update, -xpixels, or -ypixels}
} -returnCodes {error} -result {bad option "1.0": must be -chars, -displaychars, -displayindices, -displaylines, -indices, -lines, -update, -xpixels, or -ypixels}
test text-10.33 {TextWidgetCmd procedure, "count" option} -setup {
    text .t
} -body {
    .t insert end [string repeat "abcde " 50]\n
    .t insert end [string repeat "fghij " 50]\n
    .t insert end [string repeat "klmno " 50]
    .t count -lines end end
} -cleanup {
    destroy .t
} -result {0}
} -result 0
test text-10.34 {TextWidgetCmd procedure, "count" option} -setup {
    text .t
} -body {
    .t insert end [string repeat "abcde " 50]\n
    .t insert end [string repeat "fghij " 50]\n
    .t insert end [string repeat "klmno " 50]
    .t count -lines 1.5 2.5
} -cleanup {
    destroy .t
} -result {1}
} -result 1
test text-10.35 {TextWidgetCmd procedure, "count" option} -setup {
    text .t
} -body {
    .t insert end [string repeat "abcde " 50]\n
    .t insert end [string repeat "fghij " 50]\n
    .t insert end [string repeat "klmno " 50]
    .t count -lines 2.5 "2.5 lineend"
} -cleanup {
    destroy .t
} -result {0}
} -result 0
test text-10.36 {TextWidgetCmd procedure, "count" option} -setup {
    text .t
} -body {
    .t insert end [string repeat "abcde " 50]\n
    .t insert end [string repeat "fghij " 50]\n
    .t insert end [string repeat "klmno " 50]
    .t count -lines 2.7 "1.0 lineend"
} -cleanup {
    destroy .t
} -result {-1}
} -result -1
test text-10.37 {TextWidgetCmd procedure, "count" option} -setup {
    text .t
} -body {
    .t insert end [string repeat "abcde " 50]\n
    .t insert end [string repeat "fghij " 50]\n
    .t insert end [string repeat "klmno " 50]
    .t configure -wrap none
    .t count -displaylines 1.0 end
} -cleanup {
    destroy .t
} -result {3}
} -result 3
test text-10.38 {TextWidgetCmd procedure, "count" option} -setup {
    text .t -font {Courier -12} -borderwidth 2 -highlightthickness 2
    pack .t -expand 1 -fill both
} -body {
    .t configure -width 20 -height 10
    update
    .t insert end [string repeat "abcde " 50]\n
2675
2676
2677
2678
2679
2680
2681
2682

2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698


2699
2700
2701
2702
2703
2704
2705
2687
2688
2689
2690
2691
2692
2693

2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708


2709
2710
2711
2712
2713
2714
2715
2716
2717







-
+














-
-
+
+







    lappend res [.t count -displaylines 1.19 3.24] [.t count -displaylines 1.0 end]
    .t tag add hidden 2.9 3.17
    .t tag configure hidden -elide true
    lappend res [.t count -displaylines 1.19 3.24] [.t count -displaylines 1.0 end]
} -cleanup {
    destroy .t
} -result {2 6 1 5}
test text-9.2.45 {TextWidgetCmd procedure, "count" option} -setup {
test text-10.40 {TextWidgetCmd procedure, "count" option} -setup {
    text .t
    pack .t
    update
    set res {}
} -body {
    for {set i 1} {$i < 5} {incr i} {
      .t insert end "Line $i+++Line $i---Line $i///Line $i - This is Line [format %c [expr {64+$i}]]\n"
    }
    .t tag configure hidden -elide true
    .t tag add hidden 2.15 3.10
    .t configure -wrap none
    set res [.t count -displaylines 2.0 3.0]
} -cleanup {
    destroy .t
} -result {0}
test text-9.2.46 {TextWidgetCmd procedure, "count" option} -setup {
} -result 0
test text-10.41 {TextWidgetCmd procedure, "count" option} -setup {
    toplevel .mytop
    pack [text .mytop.t -font TkFixedFont -bd 0 -padx 0 -wrap char]
    set spec [font measure TkFixedFont "Line 1+++Line 1---Li"]  ; # 20 chars
    append spec x300+0+0
    wm geometry .mytop $spec
    .mytop.t delete 1.0 end
    update
2713
2714
2715
2716
2717
2718
2719
2720

2721
2722
2723
2724
2725
2726
2727
2725
2726
2727
2728
2729
2730
2731

2732
2733
2734
2735
2736
2737
2738
2739







-
+







    .mytop.t tag configure hidden -elide true
    .mytop.t tag add hidden 2.30 3.10
    lappend res [.mytop.t count -displaylines 2.0 3.0]
    lappend res [.mytop.t count -displaylines 2.0 3.50]
} -cleanup {
    destroy .mytop
} -result {1 3}
test text-9.2.47 {TextWidgetCmd procedure, "count" option} -setup {
test text-10.42 {TextWidgetCmd procedure, "count" option} -setup {
    text .t
    pack .t
    update
    set res {}
} -body {
    for {set i 1} {$i < 25} {incr i} {
        .t insert end "Line $i\n"
2767
2768
2769
2770
2771
2772
2773
2774

2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787

2788
2789
2790
2791
2792
2793
2794
2779
2780
2781
2782
2783
2784
2785

2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798

2799
2800
2801
2802
2803
2804
2805
2806







-
+












-
+







} -body {
    .t insert end "hello"
    .t tag configure elide1 -elide 0
    .t tag add elide1 1.2 1.4
    .t count -displaychars 1.0 1.5
} -cleanup {
    destroy .t
} -result {5}
} -result 5
test text-11.3 {counting with tag priority eliding} -setup {
    text .t -font {Courier -12} -borderwidth 2 -highlightthickness 2
} -body {
    .t insert end "hello"
# Newer tags are higher priority
    .t tag configure elide1 -elide 0
    .t tag configure elide2 -elide 1
    .t tag add elide1 1.2 1.4
    .t tag add elide2 1.2 1.4
    .t count -displaychars 1.0 1.5
} -cleanup {
    destroy .t
} -result {3}
} -result 3
test text-11.4 {counting with tag priority eliding}  -setup {
    text .t -font {Courier -12} -borderwidth 2 -highlightthickness 2
    set res {}
} -body {
    .t insert end "hello"
# Newer tags are higher priority
    .t tag configure elide1 -elide 0
2913
2914
2915
2916
2917
2918
2919
2920

2921
2922
2923
2924
2925
2926
2927
2925
2926
2927
2928
2929
2930
2931

2932
2933
2934
2935
2936
2937
2938
2939







-
+







    lappend res [.t count -displaychars 1.0 end-1c]
    lappend res [.t count -displaychars 1.0 1.2]
    lappend res [.t count -displaychars 2.0 end]
    lappend res [.t count -displaychars 2.0 end-1c]
    lappend res [.t index "1.0 +1 indices"]
    lappend res [.t index "1.0 +1 display indices"]
    lappend res [.t index "1.0 +1 display chars"]
    lappend res [.t index end] 
    lappend res [.t index end]
    lappend res [.t index "end -1 indices"]
    lappend res [.t index "end -1 display indices"]
    lappend res [.t index "end -1 display chars"]
    lappend res [.t index "end -2 indices"]
    lappend res [.t index "end -2 display indices"]
    lappend res [.t index "end -2 display chars"]
} -cleanup {
3085
3086
3087
3088
3089
3090
3091
3092

3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113

3114
3115
3116
3117
3118
3119
3120
3121
3122
3123

3124
3125
3126
3127
3128
3129
3130
3097
3098
3099
3100
3101
3102
3103

3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124

3125
3126
3127
3128
3129
3130
3131
3132
3133
3134

3135
3136
3137
3138
3139
3140
3141
3142







-
+




















-
+









-
+







    toplevel .top
    pack [text .top.yt]
    update
    set content {}
    for {set i 1} {$i < 300} {incr i} {
        append content [string repeat "$i " 50] \n
    }
    # Sync the widget and process all <<WidgetViewSync>> events before binding. 
    # Sync the widget and process all <<WidgetViewSync>> events before binding.
    .top.yt sync
    update
    bind .top.yt <<WidgetViewSync>> {lappend res Sync:%d}
    set res {}
    # The next line triggers <<WidgetViewSync>> with %d==0 i.e. out of sync.
    .top.yt insert 1.0 $content
    vwait res
    # Verify that the line metrics are not up-to-date (pendingsync is 1).
    lappend res "Pending:[.top.yt pendingsync]"
    # Update all line metrics by calling the sync command.
    .top.yt sync
    # <<WidgetViewSync>> should fire with %d==1 i.e. back in sync.
    vwait res
    # At this time the line metrics should be up-to-date (pendingsync is 0).
    lappend res "Pending:[.top.yt pendingsync]"
    set res
} -cleanup {
    destroy .top.yt .top
} -result {Sync:0 Pending:1 Sync:1 Pending:0}

test text-11a.51 {<<WidgetViewSync>> calls TkSendVirtualEvent(),
test text-11a.51 {<<WidgetViewSync>> calls Tk_SendVirtualEvent(),
                  NOT Tk_HandleEvent().
                  Bug [b362182e45704dd7bbd6aed91e48122035ea3d16]} -setup {
    destroy .top.t .top
} -body {
    set res {}
    toplevel .top
    pack [text .top.t]
    update
    for {set i 1} {$i < 10000} {incr i} {
        .top.t insert end "Hello world!\n" 
        .top.t insert end "Hello world!\n"
    }
    bind .top.t <<WidgetViewSync>> {destroy .top.t}
    .top.t tag add mytag 1.5 8000.8    ; # shall not crash
    update
    set res "Still doing fine!"
} -cleanup {
    destroy .top.t .top
3319
3320
3321
3322
3323
3324
3325
3326

3327
3328
3329
3330

3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349

3350
3351
3352
3353
3354
3355
3356
3331
3332
3333
3334
3335
3336
3337

3338
3339
3340
3341

3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360

3361
3362
3363
3364
3365
3366
3367
3368







-
+



-
+


















-
+







} -result {1 1 0}
test text-14.5 {ConfigureText procedure} -setup {
    text .t
} -body {
    .t configure -tabs {30 foo}
} -cleanup {
    destroy .t
} -returnCodes {error} -result {bad tab alignment "foo": must be left, right, center, or numeric} 
} -returnCodes {error} -result {bad tab alignment "foo": must be left, right, center, or numeric}
test text-14.6 {ConfigureText procedure} -setup {
    text .t
} -body {
    catch {.t configure -tabs {30 foo}} 
    catch {.t configure -tabs {30 foo}}
    .t configure -tabs {10 20 30}
    return $errorInfo
} -cleanup {
    destroy .t
} -result {bad tab alignment "foo": must be left, right, center, or numeric
    (while processing -tabs option)
    invoked from within
".t configure -tabs {30 foo}"}
test text-14.7 {ConfigureText procedure} -setup {
    text .t
} -body {
    .t configure -tabs {10 20 30}
    .t configure -tabs {}
    .t cget -tabs
} -cleanup {
    destroy .t
} -result {}
test text-14.8 {ConfigureText procedure} -setup {
   text .t 
   text .t
} -body {
    .t configure -wrap bogus
} -cleanup {
    destroy .t
} -returnCodes {error} -result {bad wrap "bogus": must be char, none, or word}
test text-14.9 {ConfigureText procedure} -setup {
    text .t -font {Courier -12} -borderwidth 2 -highlightthickness 2
3368
3369
3370
3371
3372
3373
3374
3375

3376
3377
3378
3379
3380
3381
3382
3380
3381
3382
3383
3384
3385
3386

3387
3388
3389
3390
3391
3392
3393
3394







-
+







} -body {
    .t configure -selectborderwidth {}
    .t tag cget sel -borderwidth
} -cleanup {
    destroy .t
} -result {}
test text-14.11 {ConfigureText procedure} -setup {
    text .t 
    text .t
} -body {
    .t configure -selectborderwidth foo
} -cleanup {
    destroy .t
} -returnCodes {error} -result {bad screen distance "foo"}
test text-14.12 {ConfigureText procedure} -body {
    text .t
3410
3411
3412
3413
3414
3415
3416
3417

3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431

3432
3433
3434
3435
3436
3437
3438
3422
3423
3424
3425
3426
3427
3428

3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442

3443
3444
3445
3446
3447
3448
3449
3450







-
+













-
+







    .t.e select to 1
    text .t2 -exportselection 1
    .t2 insert insert 1234657890
    .t2 tag add sel 1.0 1.4
    selection get
} -cleanup {
    destroy .t .t2
} -result {1234}
} -result 1234
test text-14.15 {ConfigureText procedure} -body {
    text .t
    entry .t.e
    .t.e insert end abcdefg
    .t.e select from 0
    .t.e select to 1
    text .t2 -exportselection 0
    .t2 insert insert 1234657890
    .t2 tag add sel 1.0 1.4
    .t2 configure -exportselection 1
    selection get
} -cleanup {
    destroy .t2 .t
} -result {1234}
} -result 1234
test text-14.16 {ConfigureText procedure} -body {
    text .t
    entry .t.e
    .t.e insert end abcdefg
    .t.e select from 0
    text .t2 -exportselection 1
    .t2 insert insert 1234657890
3453
3454
3455
3456
3457
3458
3459
3460

3461
3462
3463
3464
3465

3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479

3480
3481
3482
3483
3484
3485
3486
3465
3466
3467
3468
3469
3470
3471

3472
3473
3474
3475
3476

3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490

3491
3492
3493
3494
3495
3496
3497
3498







-
+




-
+













-
+







    .t2 tag add sel 1.0 1.4
    set result [selection get]
    .t2 configure -exportselection 0
    catch {selection get}
    return $result
} -cleanup {
    destroy .t .t2
} -result {1234}
} -result 1234
test text-14.18 {ConfigureText procedure} -constraints fonts -setup {
    toplevel .top
    text .top.t -font {Courier -12} -borderwidth 2 -highlightthickness 2
} -body {
    .top.t configure -width 20 -height 10 
    .top.t configure -width 20 -height 10
    pack .top.t
    update
    set geom [wm geometry .top]
    set x [string range $geom 0 [string first + $geom]]
} -cleanup {
    destroy .top
} -result {150x140+}
# This test was failing Windows because the title bar on .t was a certain
# minimum size and it was interfering with the size requested by the -setgrid.
# The "overrideredirect" gets rid of the titlebar so the toplevel can shrink
# to the appropriate size.
# On macOS, however, there is no way to make the window overlap the menubar.
if {[tk windowingsystem] == "aqua"} {
    set minY 23
    set minY [expr [menubarheight] + 1]
} else {
    set minY 0
}
test text-14.19 {ConfigureText procedure} -setup {
    toplevel .top
    text .top.t -font {Courier -12} -borderwidth 2 -highlightthickness 2
} -body {
3554
3555
3556
3557
3558
3559
3560
3561

3562
3563
3564
3565
3566
3567
3568
3566
3567
3568
3569
3570
3571
3572

3573
3574
3575
3576
3577
3578
3579
3580







-
+







    list [info command .tx*] [winfo exists .tx1]
} -cleanup {
    destroy .txt1
} -result {{} 0}
test text-17.2 {TextCmdDeletedProc procedure, disabling -setgrid} -constraints {
    fonts
} -body {
   toplevel .top 
   toplevel .top
   text .top.t -borderwidth 2 -highlightthickness 2 -font {Courier -12 bold} \
    -setgrid 1 -width 20 -height 10
   pack .top.t
   update
   set geom [wm geometry .top]
   set x [string range $geom 0 [string first + $geom]]
   rename .top.t {}
3956
3957
3958
3959
3960
3961
3962
3963

3964
3965
3966
3967
3968
3969
3970
3968
3969
3970
3971
3972
3973
3974

3975
3976
3977
3978
3979
3980
3981
3982







-
+







        append x "This is line $i, padded to just about 53 characters.\n"
    }
    .t insert end $x
    .t tag add sel 1.0 end
    expr {[selection get] eq "$x\n"}
} -cleanup {
    destroy .t
} -result {1}
} -result 1


test text-21.1 {TkTextLostSelection procedure} -constraints {x11} -setup {
    text .t
    .t insert 1.0 "Line 1"
    entry .t.e
    .t.e insert end "abcdefg"
4565
4566
4567
4568
4569
4570
4571
4572
4573


4574
4575
4576
4577
4578
4579
4580


4581
4582
4583
4584
4585
4586
4587

4588
4589
4590


4591
4592
4593
4594
4595
4596
4597
4577
4578
4579
4580
4581
4582
4583


4584
4585
4586
4587
4588
4589
4590


4591
4592
4593
4594
4595
4596
4597
4598

4599
4600


4601
4602
4603
4604
4605
4606
4607
4608
4609







-
-
+
+





-
-
+
+






-
+

-
-
+
+







    set p $p$p$p$p$p
    .t search -nocase $p 1.0
} -cleanup {
    destroy .t
} -result {}
test text-22.69 {TextSearchCmd, unicode} -body {
    text .t
    .t insert end "foo\u30c9\u30cabar"
    .t search \u30c9\u30ca 1.0
    .t insert end "fooドナbar"
    .t search ドナ 1.0
} -cleanup {
    destroy .t
} -result {1.3}
test text-22.70 {TextSearchCmd, unicode} -body {
    text .t
    .t insert end "foo\u30c9\u30cabar"
    list [.t search -count n \u30c9\u30ca 1.0] $n
    .t insert end "fooドナbar"
    list [.t search -count n ドナ 1.0] $n
} -cleanup {
    destroy .t
} -result {1.3 2}
test text-22.71 {TextSearchCmd, unicode with non-text segments} -body {
    text .t
    button .b1 -text baz
    .t insert end "foo\u30c9"
    .t insert end "foo"
    .t window create end -window .b1
    .t insert end "\u30cabar"
    list [.t search -count n \u30c9\u30ca 1.0] $n
    .t insert end "bar"
    list [.t search -count n ドナ 1.0] $n
} -cleanup {
    destroy .t .b1
} -result {1.3 3}
test text-22.72 {TextSearchCmd, hidden text does not affect match index} -body {
    pack [text .t]
    .t insert end "12345H7890"
    .t search 7 1.0
4946
4947
4948
4949
4950
4951
4952
4953

4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970

4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984

4985
4986
4987
4988
4989
4990
4991
4958
4959
4960
4961
4962
4963
4964

4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981

4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995

4996
4997
4998
4999
5000
5001
5002
5003







-
+
















-
+













-
+







    .t search -backwards "\n\n" 1.0
} -cleanup {
    destroy .t
} -result {}
test text-22.119 {TextSearchCmd, multiline regexp matching} -body {
    pack [text .t]
    .t insert 1.0 {    Tcl_Obj *objPtr));
static Tcl_Obj*         FSNormalizeAbsolutePath 
static Tcl_Obj*         FSNormalizeAbsolutePath
			    _ANSI_ARGS_((Tcl_Interp* interp, Tcl_Obj *pathPtr));}
    set markExpr "^(\[A-Za-z0-9~_\]+\[ \t\n\r\]*\\(|(\[^ \t\(#\n\r/@:\*\]\[^=\(\r\n\]*\[ \t\]+\\*?)?"
    append markExpr "(\[A-Za-z0-9~_\]+(<\[^>\]*>)?(::)?(\[A-Za-z0-9~_\]+::)*\[-A-Za-z0-9~_+ <>\|\\*/\]+|\[A-Za-z0-9~_\]+)"
    append markExpr "\[ \n\t\r\]*\\()"
    .t search -forwards -regexp $markExpr 1.41 end
} -cleanup {
    destroy .t
} -result {}
test text-22.120 {TextSearchCmd, multiline regexp matching} -body {
# Practical example which used to crash Tk, but only after the
# search is complete.  This is memory corruption caused by
# a bug in Tcl's handling of string objects.
# (Tcl bug 635200)
    pack [text .t]
    .t insert 1.0 {static int		SetFsPathFromAny _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Obj *objPtr));
static Tcl_Obj*         FSNormalizeAbsolutePath 
static Tcl_Obj*         FSNormalizeAbsolutePath
			    _ANSI_ARGS_((Tcl_Interp* interp, Tcl_Obj *pathPtr));}
    set markExpr "^(\[A-Za-z0-9~_\]+\[ \t\n\r\]*\\(|(\[^ \t\(#\n\r/@:\*\]\[^=\(\r\n\]*\[ \t\]+\\*?)?"
    append markExpr "(\[A-Za-z0-9~_\]+(<\[^>\]*>)?(::)?(\[A-Za-z0-9~_\]+::)*\[-A-Za-z0-9~_+ <>\|\\*/\]+|\[A-Za-z0-9~_\]+)"
    append markExpr "\[ \n\t\r\]*\\()"
    .t search -forwards -regexp $markExpr 1.41 end
} -cleanup {
    destroy .t
} -result {}
test text-22.121 {TextSearchCmd, multiline regexp matching} -body {
    pack [text .t]
    .t insert 1.0 {
static int		SetFsPathFromAny _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Obj *objPtr));
static Tcl_Obj*         FSNormalizeAbsolutePath 
static Tcl_Obj*         FSNormalizeAbsolutePath
			    _ANSI_ARGS_((Tcl_Interp* interp, Tcl_Obj *pathPtr));}
    set markExpr "^(\[A-Za-z0-9~_\]+\[ \t\n\r\]*\\(|(\[^ \t\(#\n\r/@:\*\]\[^=\(\r\n\]*\[ \t\]+\\*?)?"
    append markExpr "(\[A-Za-z0-9~_\]+(<\[^>\]*>)?(::)?(\[A-Za-z0-9~_\]+::)*\[-A-Za-z0-9~_+ <>\|\\*/\]+|\[A-Za-z0-9~_\]+)"
    append markExpr "\[ \n\t\r\]*\\()"
    .t search -backwards -all -regexp $markExpr end
} -cleanup {
    destroy .t
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071



5072
5073

5074
5075
5076
5077
5078
5079
5080
5074
5075
5076
5077
5078
5079
5080



5081
5082
5083
5084

5085
5086
5087
5088
5089
5090
5091
5092







-
-
-
+
+
+

-
+







} -result {1.31}
test text-22.132 {TextSearchCmd, multiline regexp matching} -body {
    pack [text .t]
    .t insert 1.0 {

void
Tcl_SetObjLength(objPtr, length)
    register Tcl_Obj *objPtr;	/* Pointer to object.  This object must
                                * not currently be shared. */
    register int length;	/* Number of bytes desired for string
    Tcl_Obj *objPtr;		/* Pointer to object.  This object must
				 * not currently be shared. */
    int length;			/* Number of bytes desired for string
				 * representation of object, not including
                            * terminating null byte. */
				 * terminating null byte. */
\{
    char *new;
}
    set markExpr "^(\[A-Za-z0-9~_\]+\[ \t\n\r\]*\\(|(\[^ \t\(#\n\r/@:\*\]\[^=\(\r\n\]*\[ \t\]+\\*?)?"
    append markExpr "(\[A-Za-z0-9~_\]+(<\[^>\]*>)?(::)?(\[A-Za-z0-9~_\]+::)*\[-A-Za-z0-9~_+ <>\|\\*/\]+|\[A-Za-z0-9~_\]+)"
    append markExpr "\[ \n\t\r\]*\\()"
    .t search -all -regexp -- $markExpr 1.0
5808
5809
5810
5811
5812
5813
5814
5815

5816
5817
5818
5819
5820
5821
5822
5820
5821
5822
5823
5824
5825
5826

5827
5828
5829
5830
5831
5832
5833
5834







-
+







} -result {{} {} 1.0 2.1 2.0 3.1 2.0 3.0}
test text-22.217.1 {elide up to match, with UTF-8 chars before the match} -setup {
    pack [text .t]
    set res {}
} -body {
    .t tag configure e -elide 0
    .t insert end A {} xyz e bb\n
    .t insert end \u00c4 {} xyz e bb
    .t insert end Ä {} xyz e bb
    set res {}
    lappend res [.t search bb 1.0 "1.0 lineend"]
    lappend res [.t search bb 2.0 "2.0 lineend"]
    lappend res [.t search -regexp bb 1.0 "1.0 lineend"]
    lappend res [.t search -regexp bb 2.0 "2.0 lineend"]
    .t tag configure e -elide 1
    lappend res [.t search bb 1.0 "1.0 lineend"]
6173
6174
6175
6176
6177
6178
6179
6180

6181
6182
6183
6184
6185
6186
6187
6188

6189
6190
6191
6192
6193
6194
6195
6196

6197
6198
6199
6200
6201
6202
6203
6204

6205
6206
6207
6208
6209
6210
6211
6212

6213
6214
6215
6216
6217
6218
6219
6185
6186
6187
6188
6189
6190
6191

6192
6193
6194
6195
6196
6197
6198
6199

6200
6201
6202
6203
6204
6205
6206
6207

6208
6209
6210
6211
6212
6213
6214
6215

6216
6217
6218
6219
6220
6221
6222
6223

6224
6225
6226
6227
6228
6229
6230
6231







-
+







-
+







-
+







-
+







-
+







    destroy .t
} -returnCodes {error} -result {bad screen distance "!44"}


test text-24.1 {TextDumpCmd procedure, bad args} -body {
    pack [text .t]
    .t insert 1.0 "One Line"
    .t mark set insert 1.0 
    .t mark set insert 1.0
    .t dump
} -cleanup {
    destroy .t
} -returnCodes {error} -result {Usage: .t dump ?-all -image -text -mark -tag -window? ?-command script? index ?index2?}
test text-24.2 {TextDumpCmd procedure, bad args} -body {
    pack [text .t]
    .t insert 1.0 "One Line"
    .t mark set insert 1.0 
    .t mark set insert 1.0
    .t dump -all
} -cleanup {
    destroy .t
} -returnCodes {error} -result {Usage: .t dump ?-all -image -text -mark -tag -window? ?-command script? index ?index2?}
test text-24.3 {TextDumpCmd procedure, bad args} -body {
    pack [text .t]
    .t insert 1.0 "One Line"
    .t mark set insert 1.0 
    .t mark set insert 1.0
    .t dump -command
} -cleanup {
    destroy .t
} -returnCodes {error} -result {Usage: .t dump ?-all -image -text -mark -tag -window? ?-command script? index ?index2?}
test text-24.4 {TextDumpCmd procedure, bad args} -body {
    pack [text .t]
    .t insert 1.0 "One Line"
    .t mark set insert 1.0 
    .t mark set insert 1.0
    .t dump -bogus
} -cleanup {
    destroy .t
} -returnCodes {error} -result {bad option "-bogus": must be -all, -command, -image, -mark, -tag, -text, or -window}
test text-24.5 {TextDumpCmd procedure, bad args} -body {
    pack [text .t]
    .t insert 1.0 "One Line"
    .t mark set insert 1.0 
    .t mark set insert 1.0
    .t dump bogus
} -cleanup {
    destroy .t
} -returnCodes {error} -result {bad text index "bogus"}
test text-24.6 {TextDumpCmd procedure, one index} -body {
    pack [text .t]
    .t insert 1.0 "One Line"
6242
6243
6244
6245
6246
6247
6248
6249

6250
6251
6252
6253
6254
6255
6256
6254
6255
6256
6257
6258
6259
6260

6261
6262
6263
6264
6265
6266
6267
6268







-
+







    .t dump 1.5 1.5
} -cleanup {
    destroy .t
} -result {}
test text-24.10 {TextDumpCmd procedure, negative range} -body {
    pack [text .t]
    .t insert 1.0 "One Line"
    .t mark set insert 1.0 
    .t mark set insert 1.0
    .t dump 1.5 1.0
} -cleanup {
    destroy .t
} -result {}
test text-24.11 {TextDumpCmd procedure, stop at begin-line} -body {
    pack [text .t]
    .t insert end "Line One\nLine Two\nLine Three\nLine Four"
6415
6416
6417
6418
6419
6420
6421
6422

6423
6424
6425
6426

6427
6428
6429
6430

6431
6432
6433
6434

6435
6436
6437
6438
6439
6440
6441
6442
6443
6444
6445
6446
6447
6448
6449
6450

6451
6452
6453
6454
6455
6456
6457
6427
6428
6429
6430
6431
6432
6433

6434
6435
6436
6437

6438
6439
6440
6441

6442
6443
6444
6445

6446
6447
6448
6449
6450
6451
6452
6453
6454
6455
6456
6457
6458
6459
6460
6461

6462
6463
6464
6465
6466
6467
6468
6469







-
+



-
+



-
+



-
+















-
+







    return $x
} -cleanup {
    destroy .t
    rename Append {}
} -result {mark 1.0 current mark 1.0 insert mark 2.4 m}
test text-24.25 {TextDumpCmd procedure, unicode characters} -body {
    text .t
    .t insert 1.0 \xb1\xb1\xb1
    .t insert 1.0 ±±±
    .t dump -all 1.0 2.0
} -cleanup {
    destroy .t
} -result "text \xb1\xb1\xb1 1.0 mark insert 1.3 mark current 1.3 text {\n} 1.3"
} -result "text ±±± 1.0 mark insert 1.3 mark current 1.3 text {\n} 1.3"
test text-24.26 {TextDumpCmd procedure, unicode characters} -body {
    text .t
    .t delete 1.0 end
    .t insert 1.0 abc\xb1\xb1\xb1
    .t insert 1.0 abc±±±
    .t dump -all 1.0 2.0
} -cleanup {
    destroy .t
} -result "text abc\xb1\xb1\xb1 1.0 mark insert 1.6 mark current 1.6 text {\n} 1.6"
} -result "text abc±±± 1.0 mark insert 1.6 mark current 1.6 text {\n} 1.6"
test text-24.27 {TextDumpCmd procedure, peer present} -body {
    text .t
    .t peer create .t.t
    .t dump -all 1.0 end
} -cleanup {
    destroy .t
} -result "mark insert 1.0 mark current 1.0 text {\n} 1.0"

test text-25.1 {text widget vs hidden commands} -body {
    text .t
    set y [list {} [interp hidden]]
    interp hide {} .t
    destroy .t
    set x [list [winfo children .] [interp hidden]]
    expr {$x eq $y}
} -result {1}
} -result 1


test text-26.1 {bug fix - 1642} -body {
    pack [text .t]
    .t insert end "line 1\n"
    .t insert end "line 2\n"
    .t insert end "line 3\n"
6536
6537
6538
6539
6540
6541
6542
6543

6544
6545
6546
6547
6548
6549
6550
6551
6552

6553
6554
6555
6556
6557
6558
6559
6560

6561
6562
6563
6564
6565
6566

6567
6568
6569
6570
6571
6572
6573
6548
6549
6550
6551
6552
6553
6554

6555
6556
6557
6558
6559
6560
6561
6562
6563

6564
6565
6566
6567
6568
6569
6570
6571

6572
6573
6574
6575
6576
6577
6578
6579
6580
6581
6582
6583
6584
6585
6586







-
+








-
+







-
+






+







test text-27.8 {TextEditCmd procedure, modified flag} -body {
    text .t
    pack .t
    .t insert end "line 1\n"
    .t edit modified
} -cleanup {
    destroy .t
} -result {1}
} -result 1
test text-27.9 {TextEditCmd procedure, reset modified flag} -body {
    text .t
    pack .t
    .t insert end "line 1\n"
    .t edit modified 0
    .t edit modified
} -cleanup {
    destroy .t
} -result {0}
} -result 0
test text-27.10 {TextEditCmd procedure, set modified flag} -body {
    text .t
    pack .t
    .t edit modified 1
    .t edit modified
} -cleanup {
    destroy .t
} -result {1}
} -result 1
test text-27.11 {TextEditCmd procedure, set modified flag repeat} -setup {
    text .t
    pack .t
# Make sure the Text is mapped before we start
    update
    set ::retval {}
    update
} -body {
    bind .t <<Modified>> "lappend ::retval modified"
# Shouldn't require [update idle] to trigger event [Bug 1809538]
    lappend ::retval [.t edit modified]
    .t edit modified 1
    update
    lappend ::retval [.t edit modified]
6623
6624
6625
6626
6627
6628
6629
6630

6631
6632
6633
6634
6635
6636
6637
6636
6637
6638
6639
6640
6641
6642

6643
6644
6645
6646
6647
6648
6649
6650







-
+







    bind .tt <<Modified>> {incr ::retval}
    .t insert end "This increments ::retval once for each peer, i.e. twice."
    .t edit modified 0  ; # shall increment twice as well, not just once
    update
    set ::retval
} -cleanup {
    destroy .t .tt
} -result {4}
} -result 4
test text-27.15 {<<Selection>> virtual event on sel tagging} -body {
    set ::retval no_selection
    pack [text .t]
    bind .t <<Selection>> "set ::retval selection_changed"
    update idletasks
    .t insert end "nothing special\n"
    .t tag add sel 1.0 1.1
6688
6689
6690
6691
6692
6693
6694

6695

6696
6697
6698
6699
6700
6701
6702
6701
6702
6703
6704
6705
6706
6707
6708

6709
6710
6711
6712
6713
6714
6715
6716







+
-
+







    .t insert end "and it will be impacted by the <Delete> event received.\n"
    .t insert end "Therefore a <<Selection>> event must fire back."
    .t tag add sel 1.0 1.28
    bind .t <<Selection>> "set ::retval <<Selection>>_fired"
    update
    set ::retval no_<<Selection>>_event_fired
    .t mark set insert 1.15
    update idletasks
    focus .t
    focus -force .t
    event generate .t <Delete>
    update
    set ::retval
} -cleanup {
    destroy .t
} -result {<<Selection>>_fired}
test text-27.15e {No <<Selection>> virtual event on <Delete> with cursor outside selection} -body {
6741
6742
6743
6744
6745
6746
6747
6748

6749
6750
6751
6752
6753
6754
6755
6755
6756
6757
6758
6759
6760
6761

6762
6763
6764
6765
6766
6767
6768
6769







-
+







    event generate .t <<Cut>>
    update
    set ::retval
} -cleanup {
    destroy .t
} -result {no_<<Selection>>_event_fired}
test text-27.16 {-maxundo configuration option} -body {
    text .t -undo 1  -autoseparators 1 -maxundo 2
    text .t -undo 1 -autoseparators 1 -maxundo 2
    pack .t
    .t insert end "line 1\n"
    .t delete 1.4 1.6
    .t insert end "line 2\n"
    catch {.t edit undo}
    catch {.t edit undo}
    catch {.t edit undo}
6805
6806
6807
6808
6809
6810
6811
6812

6813
6814
6815
6816
6817
6818
6819

6820
6821
6822
6823
6824
6825
6826
6819
6820
6821
6822
6823
6824
6825

6826
6827
6828
6829
6830
6831
6832

6833
6834
6835
6836
6837
6838
6839
6840







-
+






-
+







    .t edit modified 0
    .t edit undo
    .t insert end bar
    .t edit modified
} -cleanup {
    destroy .t
} -result 1
test text-27.19 {patch 1669632 (i) - undo after <Control-1>} -setup {
test text-27.19 {patch 1669632 (i) - undo after <Control-Button-1>} -setup {
    destroy .t
} -body {
    text .t -undo 1
    .t insert end foo\nbar
    .t edit reset
    .t insert 2.2 WORLD
    event generate .t <Control-1> -x 1 -y 1
    event generate .t <Control-Button-1> -x 1 -y 1
    .t insert insert HELLO
    .t edit undo
    .t get 2.2 2.7
} -cleanup {
    destroy .t
} -result WORLD
test text-27.20 {patch 1669632 (iv) - undo after <<SelectNone>>} -setup {
6845
6846
6847
6848
6849
6850
6851
6852

6853
6854
6855
6856
6857
6858
6859
6859
6860
6861
6862
6863
6864
6865

6866
6867
6868
6869
6870
6871
6872
6873







-
+







test text-27.21 {patch 1669632 (vii) - <<Undo>> shall not remove separators} -setup {
    destroy .t
} -body {
    text .t -undo 1
    .t insert end "This is an example text"
    .t edit reset
    .t insert 1.5 "WORLD "
    event generate .t <Control-1> -x 1 -y 1
    event generate .t <Control-Button-1> -x 1 -y 1
    .t insert insert HELLO
    event generate .t <<Undo>>
    .t insert insert E
    event generate .t <<Undo>>
    .t get 1.0 "1.0 lineend"
} -cleanup {
    destroy .t
6962
6963
6964
6965
6966
6967
6968




























































6969
6970
6971
6972
6973
6974
6975
6976
6977
6978
6979
6980
6981

6982
6983
6984
6985
6986
6987

6988
6989
6990
6991
6992
6993
6994
6976
6977
6978
6979
6980
6981
6982
6983
6984
6985
6986
6987
6988
6989
6990
6991
6992
6993
6994
6995
6996
6997
6998
6999
7000
7001
7002
7003
7004
7005
7006
7007
7008
7009
7010
7011
7012
7013
7014
7015
7016
7017
7018
7019
7020
7021
7022
7023
7024
7025
7026
7027
7028
7029
7030
7031
7032
7033
7034
7035
7036
7037
7038
7039
7040
7041
7042
7043
7044
7045
7046
7047
7048
7049
7050
7051
7052
7053
7054

7055
7056
7057
7058
7059
7060

7061
7062
7063
7064
7065
7066
7067
7068







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+












-
+





-
+







    .t edit undo
    update ; lappend res $nbUS
    .t edit reset
    update ; lappend res $nbUS
} -cleanup {
    destroy .t
} -result {0 0 1 2 3 4 4 5 6 6 7 8 8 9}
test text-27.26 {edit undo and edit redo return ranges} -setup {
    destroy .t
    set res {}
} -body {
    text .t -undo true -autoseparators false
    .t insert end "Hello "
    .t edit separator
    .t insert end "World!\n"
    .t insert 1.6 "GREAT "
    .t insert end "Another edit here!!"
    lappend res [.t edit undo]
    lappend res [.t edit redo]
    .t edit separator
    .t delete 1.6
    .t delete 1.9 1.10
    .t insert 1.9 L
    lappend res [.t edit undo]
    lappend res [.t edit redo]
    .t replace 1.6 1.10 Tcl/Tk
    .t replace 2.8 2.12 "one bites the dust"
    lappend res [.t edit undo]
    lappend res [.t edit redo]
} -cleanup {
    destroy .t
} -result [list {1.6 2.0}           \
                {1.6 2.19}          \
                {1.6 1.7 1.10 1.12} \
                {1.6 1.7 1.9 1.11}  \
                {1.6 1.16 2.8 2.19} \
                {1.6 1.16 2.8 2.30} ]
test text-27.27 {edit undo and edit redo return ranges} -setup {
    destroy .t
    set res {}
} -body {
    text .t -undo true -autoseparators false
    for {set i 3} {$i >= 1} {incr i -1} {
        .t insert 1.0 "Line $i\n"
    }
    lappend res [.t edit undo]
    lappend res [.t edit redo]
} -cleanup {
    destroy .t
} -result [list {1.0 2.0} \
                {1.0 4.0} ]
test text-27.28 {edit undo and edit redo do not leave \
                 spurious temporary marks behind them} -setup {
    destroy .t
    set res {}
} -body {
    pack [text .t -undo true -autoseparators false]
    .t insert end "Hello World.\n"
    .t edit separator
    .t insert end "Again hello.\n"
    .t edit undo
    lappend res [expr {[lsearch [.t mark names] tk::undoMark*]<0}]
    .t edit redo
    lappend res [expr {[lsearch [.t mark names] tk::undoMark*]<0}]
} -cleanup {
    destroy .t
} -result {1 1}


test text-28.1 {bug fix - 624372, ControlUtfProc long lines} -body {
    pack [text .t -wrap none]
    .t insert end [string repeat "\1" 500]
} -cleanup {
    destroy .t
} -result {}


test text-29.1 {tabs - must be positive and must be increasing} -body {
    pack [text .t -wrap none]
    .t configure -tabs {0}
    .t configure -tabs 0
} -cleanup {
    destroy .t
} -returnCodes {error} -result {tab stop "0" is not at a positive distance}
test text-29.2 {tabs - must be positive and must be increasing} -body {
    pack [text .t -wrap none]
    .t configure -tabs {-5}
    .t configure -tabs -5
} -cleanup {
    destroy .t
} -returnCodes {error} -result {tab stop "-5" is not at a positive distance}
test text-29.3 {tabs - must be positive and must be increasing} -constraints {
    knownBug
} -body {
# This bug will be fixed in Tk 9.0, when we can allow a minor
7003
7004
7005
7006
7007
7008
7009
7010

7011
7012
7013
7014
7015
7016
7017
7018
7019
7020
7021
7022
7023

7024
7025
7026
7027
7028
7029
7030
7031
7032
7033
7034

7035
7036
7037
7038
7039
7040
7041
7042
7043
7044
7045

7046
7047
7048
7049
7050
7051
7052
7053
7054
7055
7056

7057
7058
7059
7060
7061
7062
7063
7077
7078
7079
7080
7081
7082
7083

7084
7085
7086
7087
7088
7089
7090
7091
7092
7093
7094
7095
7096

7097
7098
7099
7100
7101
7102
7103
7104
7105
7106
7107

7108
7109
7110
7111
7112
7113
7114
7115
7116
7117
7118

7119
7120
7121
7122
7123
7124
7125
7126
7127
7128
7129

7130
7131
7132
7133
7134
7135
7136
7137







-
+












-
+










-
+










-
+










-
+







    .t insert end "a\tb\tc\td\te"
    catch {.t configure -tabs {10c 5c}}
    update ; update ; update
# This test must simply not go into an infinite loop to succeed
    set result 1
} -cleanup {
    destroy .t
} -result {1}
} -result 1


test text-30.1 {repeated insert and scroll} -body {
    pack [text .t]
    for {set i 0} {$i < 30} {incr i} {
        .t insert end "blabla\n"
        eval .t yview moveto 1
    }
# This test must simply not crash to succeed
    set result 1
} -cleanup {
    destroy .t
} -result {1}
} -result 1
test text-30.2 {repeated insert and scroll} -body {
    pack [text .t]
    for {set i 0} {$i < 30} {incr i} {
        .t insert end "blabla\n"
        eval .t yview scroll 1 pages
    }
# This test must simply not crash to succeed
    set result 1
} -cleanup {
    destroy .t
} -result {1}
} -result 1
test text-30.3 {repeated insert and scroll} -body {
    pack [text .t]
    for {set i 0} {$i < 30} {incr i} {
        .t insert end "blabla\n"
        eval .t yview scroll 100 pixels
    }
# This test must simply not crash to succeed
    set result 1
} -cleanup {
    destroy .t
} -result {1}
} -result 1
test text-30.4 {repeated insert and scroll} -body {
    pack [text .t]
    for {set i 0} {$i < 30} {incr i} {
        .t insert end "blabla\n"
        eval .t yview scroll 10 units
    }
# This test must simply not crash to succeed
    set result 1
} -cleanup {
    destroy .t
} -result {1}
} -result 1


test text-31.1 {peer widgets} -body {
    toplevel .top
    pack [text .t]
    pack [.t peer create .top.t]
    destroy .t .top
7094
7095
7096
7097
7098
7099
7100
7101

7102
7103
7104
7105
7106
7107
7108
7109
7110
7111

7112
7113
7114
7115
7116
7117
7118
7119
7120
7121
7122
7123
7124
7125
7126


7127
7128
7129
7130
7131
7132
7133
7134
7135
7136
7137
7138
7139

7140
7141
7142
7143
7144
7145
7146

7147
7148
7149
7150
7151
7152
7153

7154
7155
7156
7157
7158
7159
7160
7161
7162
7163
7164
7165
7166

7167
7168
7169
7170
7171
7172
7173
7174
7175
7176
7177
7178
7179

7180
7181
7182
7183
7184
7185
7186
7187
7188
7189
7190
7191
7192
7193
7194
7195

7196
7197
7198
7199
7200
7201
7202
7203
7204
7205
7206
7207
7208
7209
7210

7211
7212
7213
7214
7215
7216
7217
7218
7219
7220
7221
7222
7223
7224
7225

7226
7227
7228
7229
7230
7231
7232
7233
7234
7235
7236
7237
7238
7239

7240
7241

7242
7243
7244
7245
7246
7247
7248
7249
7250
7251
7252
7253
7254
7255
7256
7257
7258
7259
7260
7261


7262
7263
7264
7265
7266
7267
7268
7269
7270
7271
7272
7273
7274
7275
7276
7277
7278
7279
7280
7281


7282
7283
7284
7285
7286
7287
7288
7289
7290
7291
7292
7293
7294
7295
7296
7297
7298
7299
7300
7301
7302

7303
7304

7305
7306

7307
7308
7309
7310
7311
7312
7313
7314
7315
7316
7317
7318
7319
7320
7321
7322
7323
7324
7325

7326
7327
7328
7329
7330
7331
7332
7168
7169
7170
7171
7172
7173
7174

7175
7176
7177
7178
7179
7180
7181
7182
7183
7184

7185
7186
7187
7188
7189
7190
7191
7192
7193
7194
7195
7196
7197
7198


7199
7200
7201
7202
7203
7204
7205
7206
7207
7208
7209
7210
7211
7212

7213
7214
7215
7216
7217
7218
7219

7220
7221
7222
7223
7224
7225
7226

7227
7228
7229
7230
7231
7232
7233
7234
7235
7236
7237
7238
7239

7240
7241
7242
7243
7244
7245
7246
7247
7248
7249
7250
7251
7252

7253
7254
7255
7256
7257
7258
7259
7260
7261
7262
7263
7264
7265
7266
7267
7268

7269
7270
7271
7272
7273
7274
7275
7276
7277
7278
7279
7280
7281
7282
7283

7284
7285
7286
7287
7288
7289
7290
7291
7292
7293
7294
7295
7296
7297
7298

7299
7300
7301
7302
7303
7304
7305
7306
7307
7308
7309
7310
7311
7312

7313
7314

7315
7316
7317
7318
7319
7320
7321
7322
7323
7324
7325
7326
7327
7328
7329
7330
7331
7332
7333


7334
7335
7336
7337
7338
7339
7340
7341
7342
7343
7344
7345
7346
7347
7348
7349
7350
7351
7352
7353


7354
7355
7356
7357
7358
7359
7360
7361
7362
7363
7364
7365
7366
7367
7368
7369
7370
7371
7372
7373
7374
7375

7376
7377

7378
7379

7380
7381
7382
7383
7384
7385
7386
7387
7388
7389
7390
7391
7392
7393
7394
7395
7396
7397
7398

7399
7400
7401
7402
7403
7404
7405
7406







-
+









-
+













-
-
+
+












-
+






-
+






-
+












-
+












-
+















-
+














-
+














-
+













-
+

-
+


















-
-
+
+


















-
-
+
+




















-
+

-
+

-
+


















-
+







} -result {}
test text-31.4 {peer widgets} -body {
    toplevel .top
    pack [text .t]
    for {set i 1} {$i < 20} {incr i} {
	   .t insert end "Line $i\n"
    }
    pack [.t peer create .top.t -start 5 -end 11]
    pack [.t peer create .top.t -startline 5 -endline 11]
    update
    destroy .t .top
} -result {}
test text-31.5 {peer widgets} -body {
    toplevel .top
    pack [text .t]
    for {set i 1} {$i < 20} {incr i} {
	   .t insert end "Line $i\n"
    }
    pack [.t peer create .top.t -start 5 -end 11]
    pack [.t peer create .top.t -startline 5 -endline 11]
    pack [.top.t peer create .top.t2]
    set res [list [.top.t index end] [.top.t2 index end]]
    update
    return $res
} -cleanup {
    destroy .t .top
} -result {7.0 7.0}
test text-31.6 {peer widgets} -body {
    toplevel .top
    pack [text .t]
    for {set i 1} {$i < 20} {incr i} {
	   .t insert end "Line $i\n"
    }
    pack [.t peer create .top.t -start 5 -end 11]
    pack [.top.t peer create .top.t2 -start {} -end {}]
    pack [.t peer create .top.t -startline 5 -endline 11]
    pack [.top.t peer create .top.t2 -startline {} -endline {}]
    set res [list [.top.t index end] [.top.t2 index end]]
    update
    return $res
} -cleanup {
    destroy .t .top
} -result {7.0 21.0}
test text-31.7 {peer widgets} -body {
    toplevel .top
    pack [text .t]
    for {set i 1} {$i < 20} {incr i} {
	   .t insert end "Line $i\n"
    }
    pack [.t peer create .top.t -start 5 -end 11]
    pack [.t peer create .top.t -startline 5 -endline 11]
    update ; update
    set p1 [.top.t count -update -ypixels 1.0 end]
    set p2 [.t count -update -ypixels 5.0 11.0]
    expr {$p1 eq $p2}
} -cleanup {
    destroy .t .top
} -result {1}
} -result 1
test text-31.8 {peer widgets} -body {
    toplevel .top
    pack [text .t]
    for {set i 1} {$i < 20} {incr i} {
	   .t insert end "Line $i\n"
    }
    pack [.t peer create .top.t -start 5 -end 11]
    pack [.t peer create .top.t -startline 5 -endline 11]
    update ; update
    .t delete 3.0 6.0
    .top.t index end
} -cleanup {
    destroy .t .top
} -result {6.0}
test text-31.9 {peer widgets} -body {
    toplevel .top
    pack [text .t]
    for {set i 1} {$i < 20} {incr i} {
	   .t insert end "Line $i\n"
    }
    pack [.t peer create .top.t -start 5 -end 11]
    pack [.t peer create .top.t -startline 5 -endline 11]
    update ; update
    .t delete 8.0 12.0
    .top.t index end
} -cleanup {
    destroy .t .top
} -result {4.0}
test text-31.10 {peer widgets} -body {
    toplevel .top
    pack [text .t]
        for {set i 1} {$i < 20} {incr i} {
        .t insert end "Line $i\n"
    }
    pack [.t peer create .top.t -start 5 -end 11]
    pack [.t peer create .top.t -startline 5 -endline 11]
    update ; update
    .t delete 3.0 13.0
    .top.t index end
} -cleanup {
    destroy .t .top
} -result {1.0}
test text-31.11 {peer widgets} -setup {
    pack [text .t]
    set res {}
} -body {
    for {set i 1} {$i < 100} {incr i} {
        .t insert end "Line $i\n"
    }
    .t tag add sel 1.0 end-1c
    lappend res [.t tag ranges sel]
    .t configure -start 10 -end 20
    .t configure -startline 10 -endline 20
    lappend res [.t tag ranges sel]
    return $res
} -cleanup {
    destroy .t
} -result {{1.0 100.0} {1.0 11.0}}
test text-31.12 {peer widgets} -setup {
    pack [text .t]
    set res {}
} -body {
    for {set i 1} {$i < 100} {incr i} {
	   .t insert end "Line $i\n"
    }
    .t tag add sel 1.0 end-1c
    lappend res [.t tag ranges sel]
    .t configure -start 11
    .t configure -startline 11
    lappend res [.t tag ranges sel]
    return $res
} -cleanup {
    destroy .t
} -result {{1.0 100.0} {1.0 90.0}}
test text-31.13 {peer widgets} -setup {
    pack [text .t]
    set res {}
} -body {
    for {set i 1} {$i < 100} {incr i} {
	   .t insert end "Line $i\n"
    }
    .t tag add sel 1.0 end-1c
    lappend res [.t tag ranges sel]
    .t configure -end 90
    .t configure -endline 90
    lappend res [.t tag ranges sel]
    destroy .t
    return $res
} -cleanup {
    destroy .t
} -result {{1.0 100.0} {1.0 90.0}}
test text-31.14 {peer widgets} -setup {
    pack [text .t]
    set res {}
} -body {
    for {set i 1} {$i < 20} {incr i} {
	   .t insert end "Line $i\n"
    }
    .t tag add sel 1.0 3.0 5.0 7.0 9.0 11.0 13.0 15.0 17.0 19.0 
    .t tag add sel 1.0 3.0 5.0 7.0 9.0 11.0 13.0 15.0 17.0 19.0
    lappend res [.t tag prevrange sel 1.0]
    .t configure -start 6 -end 12
    .t configure -startline 6 -endline 12
    lappend res [.t tag ranges sel]
    lappend res "next" [.t tag nextrange sel 4.0] \
      [.t tag nextrange sel 5.0] [.t tag nextrange sel 6.0] \
      [.t tag nextrange sel 7.0]
    lappend res "prev" [.t tag prevrange sel 1.0] \
      [.t tag prevrange sel 2.0] [.t tag prevrange sel 3.0] \
      [.t tag prevrange sel 4.0]
    return $res
} -cleanup {
    destroy .t
} -result {{} {1.0 2.0 4.0 6.0} next {4.0 6.0} {} {} {} prev {} {1.0 2.0} {1.0 2.0} {1.0 2.0}}
test text-31.15 {peer widgets} -setup {
    pack [text .t]
    set res {}
} -body {
    for {set i 1} {$i < 20} {incr i} {
	   .t insert end "Line $i\n"
    }
    .t tag add sel 1.0 3.0 9.0 11.0 13.0 15.0 17.0 19.0 
    .t configure -start 6 -end 12
    .t tag add sel 1.0 3.0 9.0 11.0 13.0 15.0 17.0 19.0
    .t configure -startline 6 -endline 12
    lappend res [.t tag ranges sel]
    lappend res "next" [.t tag nextrange sel 4.0] \
      [.t tag nextrange sel 5.0] [.t tag nextrange sel 6.0] \
      [.t tag nextrange sel 7.0]
    lappend res "prev" [.t tag prevrange sel 1.0] \
      [.t tag prevrange sel 2.0] [.t tag prevrange sel 3.0] \
      [.t tag prevrange sel 4.0]
    return $res
} -cleanup {
    destroy .t
} -result {{4.0 6.0} next {4.0 6.0} {} {} {} prev {} {} {} {}}
test text-31.16 {peer widgets} -setup {
    pack [text .t]
    set res {}
} -body {
    for {set i 1} {$i < 20} {incr i} {
	.t insert end "Line $i\n"
    }
    .t tag add sel 1.0 7.0 9.0 11.0 13.0 15.0 17.0 19.0 
    .t configure -start 6 -end 12
    .t tag add sel 1.0 7.0 9.0 11.0 13.0 15.0 17.0 19.0
    .t configure -startline 6 -endline 12
    lappend res [.t tag ranges sel]
    lappend res "next" [.t tag nextrange sel 4.0] \
      [.t tag nextrange sel 5.0] [.t tag nextrange sel 6.0] \
      [.t tag nextrange sel 7.0]
    lappend res "prev" [.t tag prevrange sel 1.0] \
      [.t tag prevrange sel 2.0] [.t tag prevrange sel 3.0] \
      [.t tag prevrange sel 4.0]
    return $res
} -cleanup {
    destroy .t
} -result {{1.0 2.0 4.0 6.0} next {4.0 6.0} {} {} {} prev {} {1.0 2.0} {1.0 2.0} {1.0 2.0}}
test text-31.17 {peer widgets} -setup {
    pack [text .t]
    set res {}
} -body {
    for {set i 1} {$i < 20} {incr i} {
	   .t insert end "Line $i\n"
    }
    .t tag add sel 1.0 11.0
    lappend res [.t tag ranges sel]
    lappend res [catch {.t configure -start 15 -end 10}]
    lappend res [catch {.t configure -startline 15 -endline 10}]
    lappend res [.t tag ranges sel]
    .t configure -start 6 -end 12
    .t configure -startline 6 -endline 12
    lappend res [.t tag ranges sel]
    .t configure -start {} -end {}
    .t configure -startline {} -endline {}
    lappend res [.t tag ranges sel]
    return $res
} -cleanup {
    destroy .t
} -result {{1.0 11.0} 1 {1.0 11.0} {1.0 6.0} {1.0 11.0}}
test text-31.18 {peer widgets} -setup {
    pack [text .t]
    set res {}
} -body {
    for {set i 1} {$i < 20} {incr i} {
	   .t insert end "Line $i\n"
    }
    .t tag add sel 1.0 11.0
    lappend res [.t index sel.first]
    lappend res [.t index sel.last]
    return $res
} -cleanup {
    destroy .t
} -result {1.0 11.0} 
} -result {1.0 11.0}
test text-31.19 {peer widgets} -body {
    pack [text .t]
    for {set i 1} {$i < 20} {incr i} {
	   .t insert end "Line $i\n"
    }
    .t tag delete sel
    .t index sel.first
7363
7364
7365
7366
7367
7368
7369
7370

7371
7372
7373

7374
7375

7376
7377
7378
7379
7380
7381
7382
7437
7438
7439
7440
7441
7442
7443

7444
7445
7446

7447
7448

7449
7450
7451
7452
7453
7454
7455
7456







-
+


-
+

-
+







    set w [makeText]
    update ; after 1000 ; update
    set before [$w count -ypixels 1.0 2.0]
    $w insert 1.0 "a"
    update
    set after [$w count -ypixels 1.0 2.0]
    destroy .g
    expr {$before eq $after} 
    expr {$before eq $after}
} -cleanup {
    destroy .t
} -result {1}
} -result 1

test text-32.2 {peer widget -start, -end and deletion (bug 1630262)} -setup {
test text-32.2 {peer widget -start, -endline and deletion (bug 1630262)} -setup {
    destroy .t .pt
    set res {}
} -body {
    text .t
    .t peer create .pt
    for {set i 1} {$i < 100} {incr i} {
      .t insert end "Line $i\n"
7396
7397
7398
7399
7400
7401
7402
7403

7404
7405

7406
7407
7408
7409
7410
7411
7412
7413
7414
7415
7416
7417
7418
7419
7420
7421
7422
7423
7424
7425
7426

7427
7428
7429
7430
7431
7432
7433
7470
7471
7472
7473
7474
7475
7476

7477
7478

7479
7480
7481
7482
7483
7484
7485
7486
7487
7488
7489
7490
7491
7492
7493
7494
7495
7496
7497
7498
7499

7500
7501
7502
7503
7504
7505
7506
7507







-
+

-
+




















-
+







    # 4. delete to the end line: line1 < line2 in DeleteIndexRange,
    #    and resetView is true only for .t, not for .pt
    .pt delete 2.0 end
    # this test succeeds provided there is no crash
    set res 1
} -cleanup {
    destroy .pt
} -result {1}
} -result 1

test text-32.3 {peer widget -start, -end and deletion (bug 1630262)} -setup {
test text-32.3 {peer widget -start, -endline and deletion (bug 1630262)} -setup {
    destroy .t .pt
    set res {}
} -body {
    text .t
    .t peer create .pt
    for {set i 1} {$i < 100} {incr i} {
      .t insert end "Line $i\n"
    }
    .t configure -startline 5
    .pt configure -startline 3
    # the following delete shall not crash
    # (it did before fixing bug 1630262)
    .pt delete 2.0 3.0
    # moreover -startline shall be correct
    # (was wrong before fixing bug 1630262)
    lappend res [.t cget -start] [.pt cget -start]
} -cleanup {
    destroy .pt
} -result {4 3}

test text-32.4 {peer widget -start, -end and deletion (bug 1630262)} -setup {
test text-32.4 {peer widget -start, -endline and deletion (bug 1630262)} -setup {
    destroy .t .pt
    set res {}
} -body {
    text .t
    .t peer create .pt
    for {set i 1} {$i < 100} {incr i} {
      .t insert end "Line $i\n"
7480
7481
7482
7483
7484
7485
7486
7487

7488
7489
7490
7491
7492
7493
7494
7554
7555
7556
7557
7558
7559
7560

7561
7562
7563
7564
7565
7566
7567
7568







-
+







    .t peer names foo
} -cleanup {
    destroy .t
} -returnCodes {error} -result {wrong # args: should be ".t peer names"}
test text-33.3 {TextWidgetCmd procedure, "peer" option} -setup {
    text .t
} -body {
    .t pee names
    .t peer names
} -cleanup {
    destroy .t
} -returnCodes {ok} -result {}
test text-33.4 {TextWidgetCmd procedure, "peer" option} -setup {
    text .t
} -body {
    .t peer names
7512
7513
7514
7515
7516
7517
7518
7519

7520
7521
7522
7523

7524
7525
7526
7527
7528
7529

7530
7531
7532
7533
7534
7535
7536
7537
7538

7539
7540
7541
7542
7543
7544
7545
7546
7547
7548

7549
7550

7551
7552

7553
7554
7555
7556
7557
7558
7559
7560
7561
7562
7563
7564

7565
7566

7567
7568

7569
7570
7571
7572
7573
7574
7575

7576
7577
7578
7579
7580
7581
7582
7583
7584

7585
7586

7587
7588

7589
7590

7591
7592

7593
7594

7595
7596
7597
7598
7599
7600
7601
7602
7603
7604
7605
7606
7607
7608
7609
7610
7611
7612
7613
7614
7615
7616
7617
7618
7619
7620
7621
7622
7623
7624
7625
7626
7627
7628
7629
7630
7631
7632
7633
7634
7635
7636
7637
7638
7586
7587
7588
7589
7590
7591
7592

7593
7594
7595
7596

7597
7598
7599
7600
7601
7602

7603
7604
7605
7606
7607
7608
7609
7610
7611

7612
7613
7614
7615
7616
7617
7618
7619
7620
7621

7622
7623

7624
7625

7626
7627
7628
7629
7630
7631
7632
7633
7634
7635
7636
7637

7638
7639

7640
7641

7642
7643
7644
7645
7646
7647
7648

7649
7650
7651
7652
7653
7654
7655
7656
7657

7658
7659

7660
7661

7662
7663

7664
7665

7666
7667

7668
7669
7670
7671
7672
7673
7674
7675
7676

7677
7678
7679
7680
7681
7682
7683
7684
7685
7686
7687
7688
7689

7690
7691
7692
7693
7694
7695
7696
7697
7698
7699
7700
7701
7702

7703
7704
7705
7706
7707
7708
7709







-
+



-
+





-
+








-
+









-
+

-
+

-
+











-
+

-
+

-
+






-
+








-
+

-
+

-
+

-
+

-
+

-
+








-













-













-







    destroy .t2
    lappend res [.t peer names]
} -cleanup {
    destroy .t
} -result {.t2 .t {}}
test text-33.7 {peer widget -start, -end} -body {
    text .t
    set res [.t configure -start 10 -end 5]
    set res [.t configure -startline 10 -endline 5]
    return $res
} -cleanup {
    destroy .t
} -returnCodes {2} -result {}
} -returnCodes 2 -result {}
test text-33.8 {peer widget -start, -end} -body {
    text .t
    for {set i 1} {$i < 100} {incr i} {
	   .t insert end "Line $i\n"
    }
    .t configure -start 10 -end 5
    .t configure -startline 10 -endline 5
} -cleanup {
    destroy .t
} -returnCodes {error} -result {-startline must be less than or equal to -endline}
test text-33.9 {peer widget -start, -end} -body {
    text .t
    for {set i 1} {$i < 100} {incr i} {
	.t insert end "Line $i\n"
    }
    .t configure -start 5 -end 10
    .t configure -startline 5 -endline 10
} -cleanup {
    destroy .t
} -returnCodes {ok} -result {}
test text-33.10 {peer widget -start, -end} -body {
    text .t
    for {set i 1} {$i < 100} {incr i} {
	   .t insert end "Line $i\n"
    }
    set res [.t index end]
    lappend res [catch {.t configure -start 5 -end 10 -tab foo}]
    lappend res [catch {.t configure -startline 5 -endline 10 -tab foo}]
    lappend res [.t index end]
    lappend res [catch {.t configure -tab foo -start 15 -end 20}]
    lappend res [catch {.t configure -tab foo -startline 15 -endline 20}]
    lappend res [.t index end]
    .t configure -start {} -end {}
    .t configure -startline {} -endline {}
    lappend res [.t index end]
    return $res
} -cleanup {
    destroy .t
} -result {101.0 1 101.0 1 101.0 101.0}
test text-33.11 {peer widget -start, -end} -body {
    text .t
    for {set i 1} {$i < 100} {incr i} {
	   .t insert end "Line $i\n"
    }
    set res [.t index end]
    lappend res [catch {.t configure -start 5 -end 15}]
    lappend res [catch {.t configure -startline 5 -endline 15}]
    lappend res [.t index end]
    lappend res [catch {.t configure -start 10 -end 40}]
    lappend res [catch {.t configure -startline 10 -endline 40}]
    lappend res [.t index end]
    .t configure -start {} -end {}
    .t configure -startline {} -endline {}
    lappend res [.t index end]
    return $res
} -cleanup {
    destroy .t
} -result {101.0 0 11.0 0 31.0 101.0}

test text-34.1 {peer widget -start, -end and selection} -setup {
test text-34.1 {peer widget -start, -endline and selection} -setup {
    text .t
    set res {}
} -body {
    for {set i 1} {$i < 100} {incr i} {
	   .t insert end "Line $i\n"
    }
    .t tag add sel 10.0 20.0
    lappend res [.t tag ranges sel]
    .t configure -start 5 -end 30
    .t configure -startline 5 -endline 30
    lappend res [.t tag ranges sel]
    .t configure -start 5 -end 15
    .t configure -startline 5 -endline 15
    lappend res [.t tag ranges sel]
    .t configure -start 15 -end 30
    .t configure -startline 15 -endline 30
    lappend res [.t tag ranges sel]
    .t configure -start 15 -end 16
    .t configure -startline 15 -endline 16
    lappend res [.t tag ranges sel]
    .t configure -start 25 -end 30
    .t configure -startline 25 -endline 30
    lappend res [.t tag ranges sel]
    .t configure -start {} -end {}
    .t configure -startline {} -endline {}
    lappend res [.t tag ranges sel]
    return $res
} -cleanup {
    destroy .t
} -result {{10.0 20.0} {6.0 16.0} {6.0 11.0} {1.0 6.0} {1.0 2.0} {} {10.0 20.0}}

test text-35.1 {widget dump -command alters tags} -setup {
     proc Dumpy {key value index} {
#puts "KK: $key, $value"
      .t tag add $value [list $index linestart] [list $index lineend]
    }
    text .t
} -body {
    .t insert end "abc\n" a "---" {} "def" b "   \n" {} "ghi\n" c
    .t tag configure b -background red
    .t dump -all -command Dumpy 1.0 end
    set result "ok"
} -cleanup {
    destroy .t
} -result {ok}
test text-35.2 {widget dump -command makes massive changes} -setup {
    proc Dumpy {key value index} {
#puts "KK: $key, $value"
      .t delete 1.0 end
    }
    text .t
} -body {
    .t insert end "abc\n" a "---" {} "def" b "   \n" {} "ghi\n" c
    .t tag configure b -background red
    .t dump -all -command Dumpy 1.0 end
    set result "ok"
} -cleanup {
    destroy .t
} -result {ok}
test text-35.3 {widget dump -command destroys widget} -setup {
    proc Dumpy {key value index} {
#puts "KK: $key, $value"
        destroy .t
    }
    text .t
} -body {
    .t insert end "abc\n" a "---" {} "def" b "   \n" {} "ghi\n" c
    .t tag configure b -background red
    .t dump -all -command Dumpy 1.0 end
7646
7647
7648
7649
7650
7651
7652
7653
7654


7655
7656
7657
7658
7659
7660
7661
7662
7663
7664
7665
7666
7667
7668
7669
7670
7671
7672


7673
7674
7675
7676
7677
7678
7679
7680
7681
7682
7683
7684
7685
7686
7687
7688
7689
7690


7691
7692
7693
7694
7695
7696
7697
7717
7718
7719
7720
7721
7722
7723


7724
7725
7726
7727
7728
7729
7730
7731
7732
7733
7734
7735
7736
7737
7738
7739
7740
7741


7742
7743
7744
7745
7746
7747
7748
7749
7750
7751
7752
7753
7754
7755
7756
7757
7758
7759


7760
7761
7762
7763
7764
7765
7766
7767
7768







-
-
+
+
















-
-
+
+
















-
-
+
+







    set save [interp bgerror {}]
    interp bgerror {} returnerror-36.1
    proc returnerror-36.1 {m opts} {set ::my_error $m}
    set ::my_error {}
    pack [set w [text .t-1]]
} -body {
    tkwait visibility $w
    event generate $w <1>
    event generate $w <1>
    event generate $w <Button-1>
    event generate $w <Button-1>
    update
    set ::my_error
} -cleanup {
    destroy .t-1
    rename returnerror-36.1 ""
    interp bgerror {} $save
    unset -nocomplain save ::my_error w
} -result {}
test text-36.2 "bug #1777362: event handling with hyphenated windows" -setup {
    set save [interp bgerror {}]
    interp bgerror {} returnerror-36.2
    proc returnerror-36.2 {m opts} {set ::my_error $m}
    set ::my_error {}
    pack [set w [text .t+1]]
} -body {
    tkwait visibility $w
    event generate $w <1>
    event generate $w <1>
    event generate $w <Button-1>
    event generate $w <Button-1>
    update
    set ::my_error
} -cleanup {
    destroy $w
    rename returnerror-36.2 ""
    interp bgerror {} $save
    unset -nocomplain save ::my_error w
} -result {}
test text-36.3 "bug #1777362: event handling with hyphenated windows" -setup {
    set save [interp bgerror {}]
    interp bgerror {} returnerror-36.3
    proc returnerror-36.3 {m opts} {set ::my_error $m}
    set ::my_error {}
    pack [set w [text .t*1]]
} -body {
    tkwait visibility $w
    event generate $w <1>
    event generate $w <1>
    event generate $w <Button-1>
    event generate $w <Button-1>
    update
    set ::my_error
} -cleanup {
    destroy $w
    rename returnerror-36.3 ""
    interp bgerror {} $save
    unset -nocomplain save ::my_error w
Changes to tests/textBTree.test.
1
2
3
4
5
6
7
8



9
10
11
12
13
14
15
1
2
3
4
5



6
7
8
9
10
11
12
13
14
15





-
-
-
+
+
+







# This file is a Tcl script to test out the B-tree facilities of
# Tk's text widget (the contents of the file "tkTextBTree.c".  There are
# several file with additional tests for other features of text widgets.
# This file is organized in the standard fashion for Tcl tests.
#
# Copyright (c) 1992-1994 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1992-1994 The Regents of the University of California.
# Copyright © 1994 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
namespace import ::tcltest::*
eval tcltest::configure $argv
tcltest::loadTestedCommands

Changes to tests/textDisp.test.
1
2
3
4
5
6



7
8
9

10
11
12



13
14
15
16
17
18
19





20
21
22





23
24
25
26
27
28
29
1
2
3



4
5
6
7
8

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42



-
-
-
+
+
+


-
+



+
+
+







+
+
+
+
+



+
+
+
+
+







# This file is a Tcl script to test the code in the file tkTextDisp.c.
# This file is organized in the standard fashion for Tcl tests.
#
# Copyright (c) 1994 The Regents of the University of California.
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1994 The Regents of the University of California.
# Copyright © 1994-1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.1
package require tcltest 2.2
eval tcltest::configure $argv
tcltest::loadTestedCommands
namespace import -force tcltest::test

testConstraint failsOnUbuntu [expr {![info exists ::env(CI)] || ![string match Linux $::tcl_platform(os)]}]
testConstraint failsOnXQuarz [expr {$tcl_platform(os) ne "Darwin" || [tk windowingsystem] ne "x11" }]

# Platform specific procedure for updating the text widget.

if {[tk windowingsystem] == "aqua"} {
    proc updateText {} {
	update idletasks
    }
    proc delay {} {
	update idletasks
	after 100
	update idletasks
    }
} else {
    proc updateText {} {
	update
    }
    proc delay {} {
	update
	after 100
	update
    }
}

# The procedure below is used as the scrolling command for the text;
# it just saves the scrolling information in a variable "scrollInfo".

proc scroll args {
49
50
51
52
53
54
55





56




57
58
59
60
61
62
63
62
63
64
65
66
67
68
69
70
71
72
73

74
75
76
77
78
79
80
81
82
83
84







+
+
+
+
+
-
+
+
+
+







# because some window managers don't allow the overall width of a window
# to get very narrow.

catch {destroy .f .t}
frame .f -width 100 -height 20
pack .f -side left

# On macOS the font "Courier New" has different metrics than "Courier",
# and this causes tests 20.1 - 20.5 to fail.  So we use "Courier" as the
# fixed font for testing on Aqua.

if {[tk windowingsystem] eq "aqua"} {
set fixedFont {Courier -12}
   set fixedFont {Courier -12}
} else {
  set fixedFont {"Courier New" -12}
}
# 15 on XP, 13 on Solaris 8
set fixedHeight [font metrics $fixedFont -linespace]
# 7 on all platforms
set fixedWidth [font measure $fixedFont m]
# 12 on XP
set fixedAscent [font metrics $fixedFont -ascent]
set fixedDiff [expr {$fixedHeight - 13}] ;# 2 on XP
201
202
203
204
205
206
207
208

209
210

211
212
213
214
215
216
217
218

219
220
221
222
223
224
225
222
223
224
225
226
227
228

229
230

231
232
233
234
235
236
237
238

239
240
241
242
243
244
245
246







-
+

-
+







-
+







    destroy .txt
} {}

test textDisp-1.1 {GetStyle procedure, priorities and tab stops} {
    .t delete 1.0 end
    .t insert 1.0 "x\ty"
    .t tag delete x y z
    .t tag configure x -tabs {50}
    .t tag configure x -tabs 50
    .t tag configure y -foreground black
    .t tag configure z -tabs {70}
    .t tag configure z -tabs 70
    .t tag add x 1.0 1.end
    .t tag add y 1.0 1.end
    .t tag add z 1.0 1.end
    update idletasks
    set x [lindex [.t bbox 1.2] 0]
    .t tag configure z -tabs {}
    lappend x [lindex [.t bbox 1.2] 0]
    .t tag configure z -tabs {30}
    .t tag configure z -tabs 30
    .t tag raise x
    update idletasks
    lappend x [lindex [.t bbox 1.2] 0]
} [list 75 55 55]
.t tag delete x y z
test textDisp-1.2 {GetStyle procedure, wrapmode} {textfonts} {
    .t configure -wrap char
263
264
265
266
267
268
269
270

271
272
273
274
275
276
277
284
285
286
287
288
289
290

291
292
293
294
295
296
297
298







-
+







} [list [list 138 5 7 $fixedHeight] [list 5 [expr {$fixedDiff + 18}] 7 $fixedHeight]]
test textDisp-2.5 {LayoutDLine, word wrap} {textfonts} {
    .t configure -wrap word
    .t delete 1.0 end
    .t insert 1.0 "This isx some sample text for testing."
    list [.t bbox 1.13] [.t bbox 1.19] [.t bbox 1.20] [.t bbox 1.21]
} [list [list 96 5 $fixedWidth $fixedHeight] [list 138 5 $fixedWidth $fixedHeight] [list 145 5 0  $fixedHeight] [list 5 [expr {$fixedDiff + 18}] $fixedWidth $fixedHeight]]
test textDisp-2.6 {LayoutDLine, word wrap} {
test textDisp-2.6 {LayoutDLine, word wrap} failsOnUbuntu {
    .t configure -wrap word
    .t delete 1.0 end
    .t insert 1.0 "This isxxx some sample text for testing."
    list [.t bbox 1.15] [.t bbox 1.16]
} [list [list 110 5 35 $fixedHeight] [list 5 [expr {$fixedDiff + 18}] 7 $fixedHeight]]
test textDisp-2.7 {LayoutDLine, marks and tags} {textfonts} {
    .t configure -wrap word
482
483
484
485
486
487
488
489

490
491
492
493
494
495
496
503
504
505
506
507
508
509

510
511
512
513
514
515
516
517







-
+







    .t tag delete x y
    .t tag configure x -tabs 70
    .t tag configure y -tabs 80
    .t insert 1.0 "ab\tcde"
    .t tag add x 1.0 end
    .t tag add y 1.1 end
    lindex [.t bbox 1.3] 0
} {75}
} 75
test textDisp-2.25 {LayoutDLine, tabs, breaking chunks at tabs} {textfonts} {
    .t delete 1.0 end
    .t tag delete x
    .t tag configure x -tabs [list 30 60 90 120]
    .t insert 1.0 "a\tb\tc\td\te"
    .t mark set dummy1 1.1
    .t mark set dummy2 1.2
598
599
600
601
602
603
604
605

606
607
608
609
610
611
612
619
620
621
622
623
624
625

626
627
628
629
630
631
632
633







-
+







} [list [list 5 [expr {$fixedDiff + 18}] 1 $fixedHeight] {} [list 5 [expr {2*$fixedDiff + 31}] 1 $fixedHeight] {1.0 2.0 3.0}]
if {$tcl_platform(platform) == "windows"} {
    wm overrideredirect . 0
}
test textDisp-4.6 {UpdateDisplayInfo, tiny window} {
    # This test was failing on Windows because the title bar on .
    # was a certain minimum size and it was interfering with the size
    # requested.  The "overrideredirect" gets rid of the titlebar so 
    # requested.  The "overrideredirect" gets rid of the titlebar so
    # the toplevel can shrink to the appropriate size.  On Unix, setting
    # the overrideredirect on "." confuses the window manager and
    # causes subsequent tests to fail.

    if {$tcl_platform(platform) == "windows"} {
	wm overrideredirect . 1
    }
630
631
632
633
634
635
636
637

638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656

657
658
659
660
661
662
663
651
652
653
654
655
656
657

658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676

677
678
679
680
681
682
683
684







-
+


















-
+







set bw [.t cget -borderwidth]
set px [.t cget -padx]
set py [.t cget -pady]
set hlth [.t cget -highlightthickness]
test textDisp-4.7 {UpdateDisplayInfo, filling in extra vertical space} {
    # This test was failing on Windows because the title bar on .
    # was a certain minimum size and it was interfering with the size
    # requested.  The "overrideredirect" gets rid of the titlebar so 
    # requested.  The "overrideredirect" gets rid of the titlebar so
    # the toplevel can shrink to the appropriate size.  On Unix, setting
    # the overrideredirect on "." confuses the window manager and
    # causes subsequent tests to fail.

    if {$tcl_platform(platform) == "windows"} {
	wm overrideredirect . 1
    }
    .t delete 1.0 end
    .t insert end "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17"
    .t yview 1.0
    updateText
    .t yview 16.0
    updateText
    set x [list [.t index @0,0] $tk_textRelayout $tk_textRedraw]
    wm overrideredirect . 0
    updateText
    set x
} {8.0 {16.0 17.0 15.0 14.0 13.0 12.0 11.0 10.0 9.0 8.0} {8.0 9.0 10.0 11.0 12.0 13.0 14.0 15.0 16.0 17.0}}
test textDisp-4.8 {UpdateDisplayInfo, filling in extra vertical space} {
test textDisp-4.8 {UpdateDisplayInfo, filling in extra vertical space} failsOnXQuarz {
    .t delete 1.0 end
    .t insert end "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17"
    .t yview 16.0
    updateText
    .t delete 5.0 14.0
    updateText
    set x [list [.t index @0,0] $tk_textRelayout $tk_textRedraw]
696
697
698
699
700
701
702
703

704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719

720
721
722
723
724
725
726
717
718
719
720
721
722
723

724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739

740
741
742
743
744
745
746
747







-
+















-
+







    .t yview moveto 1
    updateText
    .t yview moveto 0
    updateText
    .t yview moveto 1
    updateText
    winfo ismapped .b
} {0}
} 0
.t configure -wrap word
.t delete 1.0 end
.t insert end "Line 1\nLine 2\nLine 3\nLine 4\nLine 5\nLine 6\nLine 7\n"
.t insert end "Line 8\nLine 9\nLine 10\nLine 11\nLine 12\nLine 13\n"
.t insert end "Line 14\nLine 15\nLine 16"
.t tag delete x
.t tag configure x -relief raised -borderwidth 2 -background white
test textDisp-4.13 {UpdateDisplayInfo, special handling for top/bottom lines} {
    .t tag add x 1.0 end
    .t yview 1.0
    updateText
    .t yview scroll 3 units
    updateText
    list $tk_textRelayout $tk_textRedraw
} {{11.0 12.0 13.0} {4.0 10.0 11.0 12.0 13.0}}
test textDisp-4.14 {UpdateDisplayInfo, special handling for top/bottom lines} {
test textDisp-4.14 {UpdateDisplayInfo, special handling for top/bottom lines} failsOnXQuarz {
    .t tag remove x 1.0 end
    .t yview 1.0
    updateText
    .t yview scroll 3 units
    updateText
    list $tk_textRelayout $tk_textRedraw
} {{11.0 12.0 13.0} {11.0 12.0 13.0}}
845
846
847
848
849
850
851
852

853
854
855
856
857
858
859
866
867
868
869
870
871
872

873
874
875
876
877
878
879
880







-
+







    bind .t.f <Configure> {.t.f configure -width 30 -height 30}
    .t window create insert -window .t.f
    updateText
    list [winfo width .t.f] [winfo height .t.f]
} [list 30 30]

.t configure -wrap char
test textDisp-6.1 {scrolling in DisplayText, scroll up} {
test textDisp-6.1 {scrolling in DisplayText, scroll up} failsOnXQuarz {
    .t delete 1.0 end
    .t insert 1.0 "Line 1"
    foreach i {2 3 4 5 6 7 8 9 10 11 12 13 14 15} {
	.t insert end "\nLine $i"
    }
    updateText
    .t delete 2.0 3.0
1133
1134
1135
1136
1137
1138
1139
1140

1141
1142
1143
1144
1145
1146
1147
1154
1155
1156
1157
1158
1159
1160

1161
1162
1163
1164
1165
1166
1167
1168







-
+







	.t insert end "\nLine $i"
    }
    updateText
    .t delete 1.41 1.44
    updateText
    list $tk_textRelayout $tk_textRedraw
} {{1.0 1.20 1.40} {1.0 1.20 1.40}}
test textDisp-8.7 {TkTextChanged} {
test textDisp-8.7 {TkTextChanged} failsOnXQuarz {
    .t delete 1.0 end
    .t insert 1.0 "Line 1 is so long that it wraps around, two times"
    foreach i {2 3 4 5 6 7 8 9 10 11 12 13 14 15} {
	.t insert end "\nLine $i"
    }
    updateText
    .t delete 1.2 1.end
1155
1156
1157
1158
1159
1160
1161
1162

1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173

1174
1175
1176
1177
1178
1179
1180
1176
1177
1178
1179
1180
1181
1182

1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193

1194
1195
1196
1197
1198
1199
1200
1201







-
+










-
+







	.t insert end "\nLine $i"
    }
    updateText
    .t delete 2.2
    updateText
    list $tk_textRelayout $tk_textRedraw
} {2.0 2.0}
test textDisp-8.9 {TkTextChanged} {
test textDisp-8.9 {TkTextChanged} failsOnXQuarz {
    .t delete 1.0 end
    .t insert 1.0 "Line 1 is so long that it wraps around, two times"
    foreach i {2 3 4 5 6 7 8 9 10 11 12 13 14 15} {
	.t insert end "\nLine $i"
    }
    updateText
    .t delete 2.0 3.0
    updateText
    list $tk_textRelayout $tk_textRedraw
} {{2.0 8.0} {2.0 8.0}}
test textDisp-8.10 {TkTextChanged} {
test textDisp-8.10 {TkTextChanged} failsOnUbuntu {
    .t configure -wrap char
    .t delete 1.0 end
    .t insert 1.0 "Line 1\nLine 2 is long enough to wrap\nLine 3 is also long enough to wrap\nLine 4"
    .t tag add big 2.19
    updateText
    .t delete 2.19
    updateText
1226
1227
1228
1229
1230
1231
1232
1233

1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251

1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262

1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273

1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284

1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295

1296
1297
1298
1299
1300
1301
1302
1247
1248
1249
1250
1251
1252
1253

1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271

1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282

1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293

1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304

1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315

1316
1317
1318
1319
1320
1321
1322
1323







-
+

















-
+










-
+










-
+










-
+










-
+







    .t insert 1.0 \nLine2\nLine3\n
    updateText
    .t insert 3.0 ""
    .t delete 1.0 2.0
    update idletasks
} {}

test textDisp-9.1 {TkTextRedrawTag} {
test textDisp-9.1 {TkTextRedrawTag} failsOnUbuntu {
    .t configure -wrap char
    .t delete 1.0 end
    .t insert 1.0 "Line 1\nLine 2 is long enough to wrap around\nLine 3\nLine 4"
    updateText
    .t tag add big 2.2 2.4
    updateText
    list $tk_textRelayout $tk_textRedraw
} {{2.0 2.18} {2.0 2.18}}
test textDisp-9.2 {TkTextRedrawTag} {textfonts} {
    .t configure -wrap char
    .t delete 1.0 end
    .t insert 1.0 "Line 1\nLine 2 is long enough to wrap around\nLine 3\nLine 4"
    updateText
    .t tag add big 1.2 2.4
    updateText
    list $tk_textRelayout $tk_textRedraw
} {{1.0 2.0 2.17} {1.0 2.0 2.17}}
test textDisp-9.3 {TkTextRedrawTag} {
test textDisp-9.3 {TkTextRedrawTag} failsOnUbuntu {
    .t configure -wrap char
    .t delete 1.0 end
    .t insert 1.0 "Line 1\nLine 2 is long enough to wrap around\nLine 3\nLine 4"
    updateText
    .t tag add big 2.2 2.4
    updateText
    .t tag remove big 1.0 end
    updateText
    list $tk_textRelayout $tk_textRedraw
} {{2.0 2.20} {2.0 2.20 eof}}
test textDisp-9.4 {TkTextRedrawTag} {
test textDisp-9.4 {TkTextRedrawTag} failsOnUbuntu {
    .t configure -wrap char
    .t delete 1.0 end
    .t insert 1.0 "Line 1\nLine 2 is long enough to wrap around\nLine 3\nLine 4"
    updateText
    .t tag add big 2.2 2.20
    updateText
    .t tag remove big 1.0 end
    updateText
    list $tk_textRelayout $tk_textRedraw
} {{2.0 2.20} {2.0 2.20 eof}}
test textDisp-9.5 {TkTextRedrawTag} {
test textDisp-9.5 {TkTextRedrawTag} {failsOnUbuntu failsOnXQuarz} {
    .t configure -wrap char
    .t delete 1.0 end
    .t insert 1.0 "Line 1\nLine 2 is long enough to wrap around\nLine 3\nLine 4"
    updateText
    .t tag add big 2.2 2.end
    updateText
    .t tag remove big 1.0 end
    updateText
    list $tk_textRelayout $tk_textRedraw
} {{2.0 2.20} {2.0 2.20 eof}}
test textDisp-9.6 {TkTextRedrawTag} {
test textDisp-9.6 {TkTextRedrawTag} failsOnUbuntu {
    .t configure -wrap char
    .t delete 1.0 end
    .t insert 1.0 "Line 1\nLine 2 is long enough to wrap\nLine 3 is also long enough to wrap"
    updateText
    .t tag add big 2.2 3.5
    updateText
    .t tag remove big 1.0 end
    updateText
    list $tk_textRelayout $tk_textRedraw
} {{2.0 2.20 3.0 3.20} {2.0 2.20 3.0 3.20 eof}}
test textDisp-9.7 {TkTextRedrawTag} {
test textDisp-9.7 {TkTextRedrawTag} failsOnUbuntu {
    .t configure -wrap char
    .t delete 1.0 end
    .t insert 1.0 "Line 1\nLine 2 is long enough to wrap\nLine 3 is also long enough to wrap\nLine 4"
    .t tag add big 2.19
    updateText
    .t tag remove big 2.19
    updateText
1324
1325
1326
1327
1328
1329
1330
1331

1332
1333
1334
1335

1336
1337
1338
1339
1340
1341
1342
1345
1346
1347
1348
1349
1350
1351

1352
1353
1354
1355

1356
1357
1358
1359
1360
1361
1362
1363







-
+



-
+







} {2.0 2.17}
test textDisp-9.10 {TkTextRedrawTag} {
    .t configure -wrap char
    .t delete 1.0 end
    .t insert 1.0 "Line 1\nLine 2 is long enough to wrap\nLine 3 is also long enough to wrap\nLine 4"
    .t tag add big 1.0 2.0
    updateText
    set tk_textRedraw {none}
    set tk_textRedraw none
    .t tag add big 1.3 1.5
    updateText
    set tk_textRedraw
} {none}
} none
test textDisp-9.11 {TkTextRedrawTag} {
    .t configure -wrap char
    .t delete 1.0 end
    .t insert 1.0 "Line 1\nLine 2 is long enough to wrap\nLine 3 is also long enough to wrap\nLine 4"
    .t tag add big 1.0 2.0
    updateText
    .t tag add big 1.0 2.0
1428
1429
1430
1431
1432
1433
1434
1435

1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449

1450
1451
1452
1453
1454
1455
1456
1449
1450
1451
1452
1453
1454
1455

1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469

1470
1471
1472
1473
1474
1475
1476
1477







-
+













-
+







}
updateText
test textDisp-11.1 {TkTextSetYView} {
    .t yview 30.0
    updateText
    .t index @0,0
} {30.0}
test textDisp-11.2 {TkTextSetYView} {
test textDisp-11.2 {TkTextSetYView} failsOnXQuarz {
    .t yview 30.0
    updateText
    .t yview 32.0
    updateText
    list [.t index @0,0] $tk_textRedraw
} {32.0 {40.0 41.0}}
test textDisp-11.3 {TkTextSetYView} {
    .t yview 30.0
    updateText
    .t yview 28.0
    updateText
    list [.t index @0,0] $tk_textRedraw
} {28.0 {28.0 29.0}}
test textDisp-11.4 {TkTextSetYView} {
test textDisp-11.4 {TkTextSetYView} failsOnXQuarz {
    .t yview 30.0
    updateText
    .t yview 31.4
    updateText
    list [.t index @0,0] $tk_textRedraw
} {31.0 40.0}
test textDisp-11.5 {TkTextSetYView} {
1473
1474
1475
1476
1477
1478
1479
1480

1481
1482
1483
1484
1485
1486
1487
1488

1489
1490
1491
1492
1493
1494
1495
1494
1495
1496
1497
1498
1499
1500

1501
1502
1503
1504
1505
1506
1507
1508

1509
1510
1511
1512
1513
1514
1515
1516







-
+







-
+







    .t yview 30.0
    updateText
    set tk_textRedraw {}
    .t yview -pickplace 26.0
    updateText
    list [.t index @0,0] $tk_textRedraw
} {21.0 {21.0 22.0 23.0 24.0 25.0 26.0 27.0 28.0 29.0}}
test textDisp-11.8 {TkTextSetYView} {
test textDisp-11.8 {TkTextSetYView} failsOnXQuarz {
    .t yview 30.0
    updateText
    set tk_textRedraw {}
    .t yview -pickplace 41.0
    updateText
    list [.t index @0,0] $tk_textRedraw
} {32.0 {40.0 41.0}}
test textDisp-11.9 {TkTextSetYView} {
test textDisp-11.9 {TkTextSetYView} failsOnXQuarz {
    .t yview 30.0
    updateText
    set tk_textRedraw {}
    .t yview -pickplace 43.0
    updateText
    list [.t index @0,0] $tk_textRedraw
} {38.0 {40.0 41.0 42.0 43.0 44.0 45.0 46.0 47.0 48.0}}
1505
1506
1507
1508
1509
1510
1511
1512

1513
1514
1515
1516
1517
1518
1519
1526
1527
1528
1529
1530
1531
1532

1533
1534
1535
1536
1537
1538
1539
1540







-
+







    .t yview 195.0
    updateText
    set tk_textRedraw {}
    .t yview 197.0
    updateText
    list [.t index @0,0] $tk_textRedraw
} {191.0 {191.0 192.0 193.0 194.0 195.0 196.0}}
test textDisp-11.12 {TkTextSetYView, wrapped line is off-screen} {
test textDisp-11.12 {TkTextSetYView, wrapped line is off-screen} failsOnXQuarz {
    .t insert 10.0 "Long line with enough text to wrap\n"
    .t yview 1.0
    updateText
    set tk_textRedraw {}
    .t see 10.30
    updateText
    list [.t index @0,0] $tk_textRedraw
1806
1807
1808
1809
1810
1811
1812
1813

1814
1815
1816
1817
1818
1819
1820
1827
1828
1829
1830
1831
1832
1833

1834
1835
1836
1837
1838
1839
1840
1841







-
+







    .top2.t2 insert "1.0 lineend" ç
    .top2.t2 see "1.0 lineend"
    updateText
    set new [.top2.t2 index @0,0]
    set res [.top2.t2 compare $ref == $new]
    destroy .top2
    set res
} {0}
} 0
wm geom . {}

.t configure -wrap none
test textDisp-14.1 {TkTextXviewCmd procedure} {
    .t delete 1.0 end
    updateText
    .t insert end xxxxxxxxx\n
1846
1847
1848
1849
1850
1851
1852
1853

1854
1855
1856
1857
1858
1859
1860
1867
1868
1869
1870
1871
1872
1873

1874
1875
1876
1877
1878
1879
1880
1881







-
+







} {1 {wrong # args: should be ".t xview moveto fraction"}}
test textDisp-14.5 {TkTextXviewCmd procedure} {
    list [catch {.t xview moveto a b} msg] $msg
} {1 {wrong # args: should be ".t xview moveto fraction"}}
test textDisp-14.6 {TkTextXviewCmd procedure} {
    list [catch {.t xview moveto a} msg] $msg
} {1 {expected floating-point number but got "a"}}
test textDisp-14.7 {TkTextXviewCmd procedure} {
test textDisp-14.7 {TkTextXviewCmd procedure} failsOnUbuntu {
    .t delete 1.0 end
    .t insert end xxxxxxxxx\n
    .t insert end "xxxxx xxxxxxxxxxx xxxx xxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxx\n"
    .t insert end "xxxx xxxxxxxxx xxxxxxxxxxxxx"
    .t xview moveto .3
    .t xview
} [list [expr {118.0/392}] [expr {258.0/392}]]
1872
1873
1874
1875
1876
1877
1878
1879

1880
1881
1882

1883
1884
1885

1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905

1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916

1917
1918
1919
1920
1921
1922
1923
1893
1894
1895
1896
1897
1898
1899

1900
1901
1902

1903
1904
1905

1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925

1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936

1937
1938
1939
1940
1941
1942
1943
1944







-
+


-
+


-
+



















-
+










-
+







    .t insert end "xxxxx xxxxxxxxxxx xxxx xxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxx\n"
    .t insert end "xxxx xxxxxxxxx xxxxxxxxxxxxx"
    .t xview m 1.4
    .t xview
} [list [expr {9.0/14}] 1.0]
test textDisp-14.10 {TkTextXviewCmd procedure} {
    list [catch {.t xview scroll a} msg] $msg
} {1 {wrong # args: should be ".t xview scroll number units|pages|pixels"}}
} {1 {wrong # args: should be ".t xview scroll number pages|pixels|units"}}
test textDisp-14.11 {TkTextXviewCmd procedure} {
    list [catch {.t xview scroll a b c} msg] $msg
} {1 {wrong # args: should be ".t xview scroll number units|pages|pixels"}}
} {1 {wrong # args: should be ".t xview scroll number pages|pixels|units"}}
test textDisp-14.12 {TkTextXviewCmd procedure} {
    list [catch {.t xview scroll gorp units} msg] $msg
} {1 {expected integer but got "gorp"}}
} {1 {expected floating-point number but got "gorp"}}
test textDisp-14.13 {TkTextXviewCmd procedure} {
    .t delete 1.0 end
    .t insert end xxxxxxxxx\n
    .t insert end "a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 c0 c1 c2 c3 c4 c5 c6 c7 c8 c9\n"
    .t insert end "xxxx xxxxxxxxx xxxxxxxxxxxxx"
    .t xview moveto 0
    .t xview scroll 2 pa
    set x [.t index @0,22]
    .t xview scroll -1 pa
    lappend x [.t index @0,22]
    .t xview scroll -2 pages
    lappend x [.t index @0,22]
} {2.36 2.18 2.0}
test textDisp-14.14 {TkTextXviewCmd procedure} {
    .t delete 1.0 end
    .t insert end xxxxxxxxx\n
    .t insert end "a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 c0 c1 c2 c3 c4 c5 c6 c7 c8 c9\n"
    .t insert end "xxxx xxxxxxxxx xxxxxxxxxxxxx"
    .t xview moveto 0
    .t xview scroll 21 u  
    .t xview scroll 21 u
    set x [.t index @0,22]
    .t xview scroll -1 u
    lappend x [.t index @0,22]
    .t xview scroll 100 units
    lappend x [.t index @0,22]
    .t xview scroll -15 units
    lappend x [.t index @0,22]
} {2.21 2.20 2.99 2.84}
test textDisp-14.15 {TkTextXviewCmd procedure} {
    list [catch {.t xview scroll 14 globs} msg] $msg
} {1 {bad argument "globs": must be units, pages, or pixels}}
} {1 {bad argument "globs": must be pages, pixels, or units}}
test textDisp-14.16 {TkTextXviewCmd procedure} {
    list [catch {.t xview flounder} msg] $msg
} {1 {bad option "flounder": must be moveto or scroll}}

.t configure -wrap char
.t delete 1.0 end
for {set i 1} {$i < 99} {incr i} {
1995
1996
1997
1998
1999
2000
2001
2002

2003
2004
2005
2006
2007
2008
2009
2016
2017
2018
2019
2020
2021
2022

2023
2024
2025
2026
2027
2028
2029
2030







-
+







    # Should scroll and should not crash!
    .tf.f.t yview scroll 1 unit
    # Check that it has scrolled
    set newind [.tf.f.t index @0,[winfo height .tf.f.t]]
    set res [.tf.f.t compare $newind > $refind]
    destroy .tf
    set res
} {1}
} 1

.t configure -wrap char
.t delete 1.0 end
.t insert insert "Line 1"
for {set i 2} {$i <= 200} {incr i} {
    .t insert end "\nLine $i"
}
2046
2047
2048
2049
2050
2051
2052
2053

2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065

2066
2067
2068
2069

2070
2071
2072
2073

2074
2075
2076
2077
2078
2079

2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099

2100
2101
2102

2103
2104
2105


2106
2107
2108


2109
2110
2111
2112
2113
2114
2115
2116
2117

2118
2119
2120
2121
2122
2123
2124
2067
2068
2069
2070
2071
2072
2073

2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085

2086
2087
2088
2089

2090
2091
2092
2093

2094
2095
2096
2097
2098
2099

2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119

2120
2121
2122

2123
2124


2125
2126
2127


2128
2129
2130
2131
2132
2133
2134
2135
2136
2137

2138
2139
2140
2141
2142
2143
2144
2145







-
+











-
+



-
+



-
+





-
+



















-
+


-
+

-
-
+
+

-
-
+
+








-
+







} {1 {bad text index "bad_mark_name"}}
test textDisp-16.9 {TkTextYviewCmd procedure, "moveto" option} {
    list [catch {.t yview moveto a b} msg] $msg
} {1 {wrong # args: should be ".t yview moveto fraction"}}
test textDisp-16.10 {TkTextYviewCmd procedure, "moveto" option} {
    list [catch {.t yview moveto gorp} msg] $msg
} {1 {expected floating-point number but got "gorp"}}
test textDisp-16.11 {TkTextYviewCmd procedure, "moveto" option} {
test textDisp-16.11 {TkTextYviewCmd procedure, "moveto" option} failsOnUbuntu {
    .t yview moveto 0.5
    .t index @0,0
} {103.0}
test textDisp-16.12 {TkTextYviewCmd procedure, "moveto" option} {
    .t yview moveto -1
    .t index @0,0
} {1.0}
test textDisp-16.13 {TkTextYviewCmd procedure, "moveto" option} {
    .t yview moveto 1.1
    .t index @0,0
} {191.0}
test textDisp-16.14 {TkTextYviewCmd procedure, "moveto" option} {
test textDisp-16.14 {TkTextYviewCmd procedure, "moveto" option} failsOnUbuntu {
    .t yview moveto .75
    .t index @0,0
} {151.60}
test textDisp-16.15 {TkTextYviewCmd procedure, "moveto" option} {
test textDisp-16.15 {TkTextYviewCmd procedure, "moveto" option} failsOnUbuntu {
    .t yview moveto .752
    .t index @0,0
} {151.60}
test textDisp-16.16 {TkTextYviewCmd procedure, "moveto" option} {textfonts} {
test textDisp-16.16 {TkTextYviewCmd procedure, "moveto" option} textfonts {
    set count [expr {5 * $bigHeight + 150 * $fixedHeight}]
    set extra [expr {0.04 * double($fixedDiff * 150) / double($count)}]
    .t yview moveto [expr {.753 - $extra}]
    .t index @0,0
} {151.60}
test textDisp-16.17 {TkTextYviewCmd procedure, "moveto" option} {
test textDisp-16.17 {TkTextYviewCmd procedure, "moveto" option} failsOnUbuntu {
    .t yview moveto .755
    .t index @0,0
} {151.80}
test textDisp-16.18 {TkTextYviewCmd procedure, "moveto" roundoff} {textfonts} {
    catch {destroy .top1}
    toplevel .top1
    wm geometry .top1 +0+0
    text .top1.t -height 3 -width 4 -wrap none -setgrid 1 -padx 6 \
	-spacing3 6
    pack .top1.t
    updateText
    .top1.t insert end "1\n2\n3\n4\n5\n6"
    .top1.t yview moveto 0.3333
    set result [.top1.t yview]
    destroy .top1
    set result
} [list [expr {1.0/3}] [expr {5.0/6}]]
test textDisp-16.19 {TkTextYviewCmd procedure, "scroll" option} {
    list [catch {.t yview scroll a} msg] $msg
} {1 {wrong # args: should be ".t yview scroll number units|pages|pixels"}}
} {1 {wrong # args: should be ".t yview scroll number pages|pixels|units"}}
test textDisp-16.20 {TkTextYviewCmd procedure, "scroll" option} {
    list [catch {.t yview scroll a b c} msg] $msg
} {1 {wrong # args: should be ".t yview scroll number units|pages|pixels"}}
} {1 {wrong # args: should be ".t yview scroll number pages|pixels|units"}}
test textDisp-16.21 {TkTextYviewCmd procedure, "scroll" option} {
    list [catch {.t yview scroll badInt bogus} msg] $msg
} {1 {bad argument "bogus": must be units, pages, or pixels}}
    list [catch {.t yview scroll bogus bogus} msg] $msg
} {1 {bad argument "bogus": must be pages, pixels, or units}}
test textDisp-16.21.2 {TkTextYviewCmd procedure, "scroll" option} {
    list [catch {.t yview scroll badInt units} msg] $msg
} {1 {expected integer but got "badInt"}}
    list [catch {.t yview scroll bogus units} msg] $msg
} {1 {expected floating-point number but got "bogus"}}
test textDisp-16.22 {TkTextYviewCmd procedure, "scroll" option, back pages} {
    .t yview 50.0
    updateText
    .t yview scroll -1 pages
    .t index @0,0
} {42.0}
test textDisp-16.22.1 {TkTextYviewCmd procedure, "scroll" option, back pages} {
    list [catch {.t yview scroll -3 p} res] $res
} {1 {ambiguous argument "p": must be units, pages, or pixels}}
} {1 {ambiguous argument "p": must be pages, pixels, or units}}
test textDisp-16.23 {TkTextYviewCmd procedure, "scroll" option, back pages} {
    .t yview 50.0
    updateText
    .t yview scroll -3 pa
    .t index @0,0
} {26.0}
test textDisp-16.24 {TkTextYviewCmd procedure, "scroll" option, back pages} {
2155
2156
2157
2158
2159
2160
2161
2162

2163
2164
2165
2166
2167
2168
2169
2176
2177
2178
2179
2180
2181
2182

2183
2184
2185
2186
2187
2188
2189
2190







-
+







    updateText
    .t yview scroll 1 page
    set res [expr {int([.t index @0,0])}]
    if {$fixedDiff > 1} {
	incr res -1
    }
    set res
} {102}
} 102
test textDisp-16.29 {TkTextYviewCmd procedure, "scroll" option, forward pages} {
    .t configure -height 1
    updateText
    .t yview 50.0
    updateText
    .t yview scroll 1 pages
    set x [.t index @0,0]
2181
2182
2183
2184
2185
2186
2187
2188

2189
2190
2191
2192
2193
2194
2195
2202
2203
2204
2205
2206
2207
2208

2209
2210
2211
2212
2213
2214
2215
2216







-
+







    .t yview 149.0
    updateText
    .t yview scroll 4 units
    .t index @0,0
} {151.40}
test textDisp-16.32 {TkTextYviewCmd procedure} {
    list [catch {.t yview scroll 12 bogoids} msg] $msg
} {1 {bad argument "bogoids": must be units, pages, or pixels}}
} {1 {bad argument "bogoids": must be pages, pixels, or units}}
test textDisp-16.33 {TkTextYviewCmd procedure} {
    list [catch {.t yview bad_arg 1 2} msg] $msg
} {1 {bad option "bad_arg": must be moveto or scroll}}
test textDisp-16.34 {TkTextYviewCmd procedure} {
    set res {}
    .t yview 1.0
    lappend res [format %.12g [expr {[lindex [.t yview] 0]
2236
2237
2238
2239
2240
2241
2242
2243

2244
2245
2246
2247
2248
2249
2250
2257
2258
2259
2260
2261
2262
2263

2264
2265
2266
2267
2268
2269
2270
2271







-
+







} {0 {}}
test textDisp-16.38 {TkTextYviewCmd procedure} {
    list [catch {.t yview scroll 1.3blah pixels} msg] $msg
} {1 {bad screen distance "1.3blah"}}
test textDisp-16.39 {TkTextYviewCmd procedure} {
    list [catch {.t yview scroll 1.3i pixels} msg] $msg
} {0 {}}
test textDisp-16.40 {text count -xpixels} {
test textDisp-16.40 {text count -xpixels} failsOnUbuntu {
    set res {}
    lappend res [.t count -xpixels 1.0 1.5] \
      [.t count -xpixels 1.5 1.0] \
      [.t count -xpixels 1.0 13.0] \
      [.t count -xpixels 1.0 "1.0 displaylineend"] \
      [.t count -xpixels 1.0 "1.0 lineend"] \
      [.t count -xpixels 1.0 "1.0 displaylineend"] \
2355
2356
2357
2358
2359
2360
2361
2362

2363
2364
2365
2366
2367
2368
2369
2376
2377
2378
2379
2380
2381
2382

2383
2384
2385
2386
2387
2388
2389
2390







-
+







    list $x [.t index @0,0]
} {6.12 2.5}
test textDisp-17.8 {TkTextScanCmd procedure} {textfonts} {
    .t yview 1.0
    .t xview moveto 0
    .t scan mark 0 60
    .t scan dragto 30 100
    .t scan dragto 25 95 
    .t scan dragto 25 95
    .t index @0,0
} {4.7}
test textDisp-17.9 {TkTextScanCmd procedure} {textfonts} {
    .t yview end
    .t xview moveto 0
    .t xview scroll 100 units
    .t scan mark 90 60
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2498
2499
2500
2501
2502
2503
2504


2505
2506
2507
2508
2509
2510
2511







-
-







    (procedure "scrollError" line 2)
    invoked from within
"scrollError 0.0 1.0"
    (horizontal scrolling command executed by text)}}
catch {rename bgerror {}}
catch {rename bogus {}}
.t configure -xscrollcommand {} -yscrollcommand scroll

.t configure -xscrollcommand {} -yscrollcommand scroll
test textDisp-19.1 {GetYView procedure} {
    .t configure -wrap char
    .t delete 1.0 end
    updateText
    set scrollInfo
} {0.0 1.0}
test textDisp-19.2 {GetYView procedure} {
2550
2551
2552
2553
2554
2555
2556
2557

2558
2559
2560
2561
2562
2563
2564
2569
2570
2571
2572
2573
2574
2575

2576
2577
2578
2579
2580
2581
2582
2583







-
+







	.t insert end "\nLine $i"
    }
    .t insert 2.end " is really quite long; in fact it's so long that it wraps three times"
    .t yview 2.26
    updateText
    set x $scrollInfo
} {0.125 0.75}
test textDisp-19.8 {GetYView procedure} {
test textDisp-19.8 {GetYView procedure} failsOnUbuntu {
    .t configure -wrap char
    .t delete 1.0 end
    .t insert 1.0 "Line 1"
    foreach i {2 3 4 5 6 7 8 9 10 11 12 13} {
	.t insert end "\nLine $i"
    }
    .t insert 10.end " is really quite long; in fact it's so long that it wraps three times"
2623
2624
2625
2626
2627
2628
2629
2630

2631
2632
2633

2634
2635
2636

2637
2638
2639

2640
2641
2642

2643
2644
2645

2646
2647
2648

2649
2650
2651

2652
2653
2654

2655
2656
2657

2658
2659
2660

2661
2662
2663

2664
2665
2666
2667
2668
2669

2670
2671
2672
2673
2674

2675
2676
2677
2678
2679

2680
2681
2682
2683
2684

2685
2686
2687
2688
2689

2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710

2711
2712
2713
2714
2715
2716
2717
2642
2643
2644
2645
2646
2647
2648

2649
2650
2651

2652
2653
2654

2655
2656
2657

2658
2659
2660

2661
2662
2663

2664
2665
2666

2667
2668
2669

2670
2671
2672

2673
2674
2675

2676
2677
2678

2679
2680
2681

2682
2683
2684
2685
2686
2687

2688
2689
2690
2691
2692

2693
2694
2695
2696
2697

2698
2699
2700
2701
2702

2703
2704
2705
2706
2707

2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728

2729
2730
2731
2732
2733
2734
2735
2736







-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+





-
+




-
+




-
+




-
+




-
+




















-
+







    .t yview insert
    updateText
    .t count -update -ypixels 1.0 end
    set scrollInfo
} {0.5 1.0}
test textDisp-19.11.2 {TextWidgetCmd procedure, "count -displaylines"} {
    .t count -displaylines 1.0 end
} {20}
} 20
test textDisp-19.11.3 {TextWidgetCmd procedure, "count -displaylines"} {
    .t count -displaylines end 1.0
} {-20}
} -20
test textDisp-19.11.4 {TextWidgetCmd procedure, "count -displaylines"} {
    .t count -displaylines 1.1 1.3
} {0}
} 0
test textDisp-19.11.5 {TextWidgetCmd procedure, "count -displaylines"} {
    .t count -displaylines 16.0 16.1
} {0}
} 0
test textDisp-19.11.5.1 {TextWidgetCmd procedure, "count -displaylines"} {
    .t count -displaylines 16.0 16.5
} {0}
} 0
test textDisp-19.11.6 {TextWidgetCmd procedure, "count -displaylines"} {
    .t count -displaylines 16.0 16.24
} {1}
} 1
test textDisp-19.11.7 {TextWidgetCmd procedure, "count -displaylines"} {
    .t count -displaylines 16.0 16.40
} {2}
} 2
test textDisp-19.11.8 {TextWidgetCmd procedure, "count -displaylines"} {
    .t count -displaylines "16.0 displaylineend +1c" "16.0 lineend"
} {3}
} 3
test textDisp-19.11.9 {TextWidgetCmd procedure, "count -displaylines"} {
    .t count -displaylines 16.0 "16.0 lineend"
} {4}
} 4
test textDisp-19.11.10 {TextWidgetCmd procedure, "count -displaylines"} {
    .t count -displaylines 16.0 "16.0 +4displaylines"
} {4}
} 4
test textDisp-19.11.11 {TextWidgetCmd procedure, "count -displaylines"} {
    .t count -displaylines 16.0 "16.0 +2displaylines"
} {2}
} 2
test textDisp-19.11.12 {TextWidgetCmd procedure, "count -displaylines"} {
    .t count -displaylines "16.0 +1displayline" "16.0 +2displaylines -1c"
} {0}
} 0
.t tag configure elide -elide 1
test textDisp-19.11.13 {TextWidgetCmd procedure, "count -displaylines"} {
    .t tag remove elide 1.0 end
    .t tag add elide "16.0 +1displaylines" "16.0 +1displaylines +6c"
    .t count -displaylines 16.0 "16.0 +4displaylines"
} {4}
} 4
test textDisp-19.11.14 {TextWidgetCmd procedure, "count -displaylines"} {
    .t tag remove elide 1.0 end
    .t tag add elide "16.0 +1displaylines" "16.0 +1displaylines displaylineend"
    .t count -displaylines 16.0 "16.0 +4displaylines"
} {4}
} 4
test textDisp-19.11.15 {TextWidgetCmd procedure, "count -displaylines"} {
    .t tag remove elide 1.0 end
    .t tag add elide "16.0 +1displaylines" "16.0 +2displaylines"
    .t count -displaylines 16.0 "16.0 +4displaylines -1c"
} {3}
} 3
test textDisp-19.11.15a {TextWidgetCmd procedure, "count -displaylines"} {
    .t tag remove elide 1.0 end
    .t tag add elide "16.0 +1displaylines" "16.0 +2displaylines"
    .t count -displaylines 16.0 "16.0 +4displaylines"
} {4}
} 4
test textDisp-19.11.16 {TextWidgetCmd procedure, "count -displaylines"} {
    .t tag remove elide 1.0 end
    .t tag add elide "12.0" "14.0"
    .t count -displaylines 12.0 16.0
} {2}
} 2
test textDisp-19.11.17 {TextWidgetCmd procedure, "index +displaylines"} {
    .t tag remove elide 1.0 end
    .t tag add elide "12.0" "14.0"
    list [.t index "11.5 +2d lines"] \
      [.t index "12.0 +2d lines"] [.t index "11.0 +2d lines"] \
      [.t index "13.0 +2d lines"] [.t index "13.1 +3d lines"] \
      [.t index "13.0 +4d lines"]
} {15.5 16.0 15.0 16.0 16.21 16.39}
test textDisp-19.11.18 {TextWidgetCmd procedure, "index +displaylines"} {
    .t tag remove elide 1.0 end
    .t tag add elide "12.0" "14.0"
    list [.t index "15.5 -2d lines"] \
      [.t index "16.0 -2d lines"] [.t index "15.0 -2d lines"] \
      [.t index "16.0 -3d lines"] [.t index "16.23 -4d lines"] \
      [.t index "16.42 -5d lines"]
} {11.5 14.0 11.0 11.0 11.2 11.3}
test textDisp-19.11.19 {TextWidgetCmd procedure, "count -displaylines"} {
    .t tag remove elide 1.0 end
    .t tag add elide "12.0" "16.0 +1displaylines"
    .t count -displaylines 12.0 17.0
} {4}
} 4
test textDisp-19.11.20 {TextWidgetCmd procedure, "index +displaylines"} {
    .t tag remove elide 1.0 end
    .t tag add elide "12.0" "16.0 +1displaylines"
    list [.t index "11.5 +2d lines"] \
      [.t index "12.0 +2d lines"] [.t index "11.0 +2d lines"] \
      [.t index "13.0 +2d lines"] [.t index "13.0 +3d lines"] \
      [.t index "13.0 +4d lines"]
2847
2848
2849
2850
2851
2852
2853
2854

2855
2856
2857
2858
2859
2860
2861
2866
2867
2868
2869
2870
2871
2872

2873
2874
2875
2876
2877
2878
2879
2880







-
+







      [.t count -ypixels 1.0 end] \
      [.t count -update -ypixels 1.0 end] \
      [.t count -ypixels 15.0 16.0] \
      [.t count -ypixels 15.0 "16.0 displaylineend +1c"] \
      [.t count -ypixels 16.0 "16.0 displaylineend +1c"] \
      [.t count -ypixels "16.0 +1 displaylines" "16.0 +4 displaylines +3c"]
} [list [expr {260 + 20 * $fixedDiff}] [expr {260 + 20 * $fixedDiff}] $fixedHeight [expr {2*$fixedHeight}] $fixedHeight [expr {3*$fixedHeight}]]
test textDisp-19.17 {count -ypixels with indices in elided lines} {
test textDisp-19.17 {count -ypixels with indices in elided lines} {failsOnUbuntu failsOnXQuarz} {
    .t configure -wrap none
    .t delete 1.0 end
    for {set i 1} {$i < 100} {incr i} {
        .t insert end [string repeat "Line $i" 20]
        .t insert end "\n"
    }
    .t tag add hidden 5.15 20.15
2874
2875
2876
2877
2878
2879
2880
2881

2882
2883
2884
2885
2886
2887
2888
2893
2894
2895
2896
2897
2898
2899

2900
2901
2902
2903
2904
2905
2906
2907







-
+







      [.t count -ypixels 5.0 25.0] \
      [.t count -ypixels 25.0 5.0] \
      [.t count -ypixels 25.4 27.50] \
      [.t count -ypixels 35.0 38.0]
    .t yview 35.0
    lappend res [.t count -ypixels 5.0 25.0]
} [list [expr {4 * $fixedHeight}] [expr {3 * $fixedHeight}] 0 0 0 0 0 0 [expr {5 * $fixedHeight}] [expr {- 5 * $fixedHeight}] [expr {2 * $fixedHeight}] [expr {3 * $fixedHeight}] [expr {5 * $fixedHeight}]]
test textDisp-19.18 {count -ypixels with indices in elided lines} {
test textDisp-19.18 {count -ypixels with indices in elided lines} {failsOnUbuntu failsOnXQuarz} {
    .t configure -wrap none
    .t delete 1.0 end
    for {set i 1} {$i < 100} {incr i} {
        .t insert end [string repeat "Line $i" 20]
        .t insert end "\n"
    }
    .t tag add hidden 5.15 20.15
2912
2913
2914
2915
2916
2917
2918
2919

2920
2921
2922
2923
2924

2925
2926
2927
2928
2929

2930
2931
2932
2933
2934

2935
2936
2937
2938
2939
2940

2941
2942
2943
2944
2945
2946
2947
2931
2932
2933
2934
2935
2936
2937

2938
2939
2940
2941
2942

2943
2944
2945
2946
2947

2948
2949
2950
2951
2952

2953
2954
2955
2956
2957
2958

2959
2960
2961
2962
2963
2964
2965
2966







-
+




-
+




-
+




-
+





-
+







.t insert end "Line 1"
for {set i 2} {$i <= 200} {incr i} {
    .t insert end "\nLine $i"
}
.t configure -wrap word
.t delete 50.0 51.0
.t insert 50.0 "This is a long line, one that will wrap around twice.\n"
test textDisp-20.1 {FindDLine} {
test textDisp-20.1 {FindDLine} failsOnUbuntu {
    .t yview 48.0
    list [.t dlineinfo 46.0] [.t dlineinfo 47.0] [.t dlineinfo 49.0] \
	    [.t dlineinfo 58.0]
} [list {} {} [list 3 [expr {$fixedDiff + 16}] 49 [expr {$fixedDiff + 13}] [expr {$fixedDiff + 10}]] {}]
test textDisp-20.2 {FindDLine} { 
test textDisp-20.2 {FindDLine} failsOnUbuntu {
    .t yview 100.0
    .t yview -pickplace 53.0
    list [.t dlineinfo 50.0] [.t dlineinfo 50.14] [.t dlineinfo 50.21]
} [list [list 3 [expr {-1 - $fixedDiff/2}] 140 [expr {$fixedDiff + 13}] [expr {$fixedDiff + 10}]] [list 3 [expr {-1 - $fixedDiff/2}] 140 [expr {$fixedDiff + 13}] [expr {$fixedDiff + 10}]] [list 3 [expr {12 + $fixedDiff/2}] 133 [expr {$fixedDiff + 13}] [expr {$fixedDiff + 10}]]]
test textDisp-20.3 {FindDLine} {
test textDisp-20.3 {FindDLine} failsOnUbuntu {
    .t yview 100.0
    .t yview 49.0
    list [.t dlineinfo 50.0] [.t dlineinfo 50.24] [.t dlineinfo 57.0]
} [list [list 3 [expr {$fixedDiff + 16}] 140 [expr {$fixedDiff + 13}] [expr {$fixedDiff + 10}]] [list 3 [expr {2*$fixedDiff + 29}] 133 [expr {$fixedDiff + 13}] [expr {$fixedDiff + 10}]] {}]
test textDisp-20.4 {FindDLine} {
test textDisp-20.4 {FindDLine} failsOnUbuntu {
    .t yview 100.0
    .t yview 42.0
    list [.t dlineinfo 50.0] [.t dlineinfo 50.24] [.t dlineinfo 50.40]
} [list [list 3 [expr {8*$fixedDiff + 107}] 140 [expr {$fixedDiff + 13}] [expr {$fixedDiff + 10}]] [list 3 [expr {9*$fixedDiff + 120}] 133 [expr {$fixedDiff + 13}] [expr {$fixedDiff + 10}]] {}]
.t config -wrap none
test textDisp-20.5 {FindDLine} {
test textDisp-20.5 {FindDLine} failsOnUbuntu {
    .t yview 100.0
    .t yview 48.0
    list [.t dlineinfo 50.0] [.t dlineinfo 50.20] [.t dlineinfo 50.40]
} [list [list 3 [expr {3+2*$fixedHeight}] 371 [expr {$fixedDiff + 13}] [expr {$fixedDiff + 10}]] [list 3 [expr {3+2*$fixedHeight}] 371 [expr {$fixedDiff + 13}] [expr {$fixedDiff + 10}]] [list 3 [expr {3+2*$fixedHeight}] 371 [expr {$fixedDiff + 13}] [expr {$fixedDiff + 10}]]]

.t config -wrap word
test textDisp-21.1 {TkTextPixelIndex} {textfonts} {
2966
2967
2968
2969
2970
2971
2972
2973

2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990

2991
2992
2993
2994
2995
2996
2997
2985
2986
2987
2988
2989
2990
2991

2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008

3009
3010
3011
3012
3013
3014
3015
3016







-
+
















-
+







test textDisp-21.4 {count -displaylines regression} {
    set message {
   QOTW:  "C/C++, which is used by 16% of users, is the most popular programming language, but Tcl, used by 0%, seems to be the language of choice for the highest scoring users."
(new line)
Use the Up (cursor) key to scroll up one line at a time.  At the second press, the cursor either gets locked or jumps several lines.

Connect with Tkcon.  The command
.u count -displaylines \ 
.u count -displaylines \
3.10 2.173
should give answer -1; it gives me 5.

Using 8.5a4 (ActiveState beta 4) under Linux.  No problem with ActiveState beta 3.
}

toplevel .tt
pack [text .tt.u] -side right
.tt.u configure -width 30 -height 27 -wrap word -bg #FFFFFF
.tt.u insert end $message
.tt.u mark set insert 3.10
tkwait visibility .tt.u
set res [.tt.u count -displaylines 3.10 2.173]
destroy .tt
unset message
set res
} {-1}
} -1

.t delete 1.0 end
.t insert end "Line 1"
for {set i 2} {$i <= 200} {incr i} {
    .t insert end "\nLine $i"
}
.t configure -wrap word
3391
3392
3393
3394
3395
3396
3397
3398

3399
3400
3401
3402
3403
3404
3405
3410
3411
3412
3413
3414
3415
3416

3417
3418
3419
3420
3421
3422
3423
3424







-
+







test textDisp-24.24 {TkTextCharLayoutProc, justification and tabs} {textfonts} {
    .t delete 1.0 end
    .t tag configure x -justify center
    .t insert 1.0 aa\tbb\tcc\tdd\t
    .t tag add x 1.0 end
    list [.t bbox 1.0] [.t bbox 1.10]
} [list [list 45 3 7 $fixedHeight] [list 94 3 7 $fixedHeight]]
test textDisp-24.25 {TkTextCharLayoutProc, justification and tabs} -constraints {textfonts} -setup {
test textDisp-24.25 {TkTextCharLayoutProc, justification and tabs} -constraints {textfonts failsOnXQuarz} -setup {
    text .tt -tabs {40 right} -wrap none -font $fixedFont
    pack .tt
} -body {
    .tt insert end \t9\n\t99\n\t999
    updateText
    list [.tt bbox 1.1] [.tt bbox 2.2] [.tt bbox 3.3]
} -cleanup {
3470
3471
3472
3473
3474
3475
3476
3477

3478
3479
3480
3481
3482
3483
3484
3485
3486

3487
3488
3489
3490
3491
3492
3493
3494
3495

3496
3497
3498
3499
3500
3501
3502
3503
3504

3505
3506
3507
3508
3509
3510
3511
3512
3513

3514
3515
3516
3517
3518
3519
3520
3521
3522

3523
3524
3525
3526
3527
3528
3529
3530
3531
3532

3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545

3546
3547
3548
3549
3550
3551
3552
3489
3490
3491
3492
3493
3494
3495

3496
3497
3498
3499
3500
3501
3502
3503
3504

3505
3506
3507
3508
3509
3510
3511
3512
3513

3514
3515
3516
3517
3518
3519
3520
3521
3522

3523
3524
3525
3526
3527
3528
3529
3530
3531

3532
3533
3534
3535
3536
3537
3538
3539
3540

3541
3542
3543
3544
3545
3546
3547
3548
3549
3550

3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563

3564
3565
3566
3567
3568
3569
3570
3571







-
+








-
+








-
+








-
+








-
+








-
+









-
+












-
+







    .t insert 1.0 a\t1.234
    .t tag delete x
    .t tag configure x -tabs {120 numeric}
    .t tag add x 1.0 end
    .t tag add y 1.2
    .t tag add y 1.5
    lindex [.t bbox 1.3] 0
} {120}
} 120
test textDisp-26.6 {AdjustForTab procedure, numeric alignment} {
    .t delete 1.0 end
    .t insert 1.0 a\t1,456.234
    .t tag delete x
    .t tag configure x -tabs {120 numeric}
    .t tag add x 1.0 end
    .t tag add y 1.2
    lindex [.t bbox 1.7] 0
} {120}
} 120
test textDisp-26.7 {AdjustForTab procedure, numeric alignment} {
    .t delete 1.0 end
    .t insert 1.0 a\t1.456.234,7
    .t tag delete x
    .t tag configure x -tabs {120 numeric}
    .t tag add x 1.0 end
    .t tag add y 1.2
    lindex [.t bbox 1.11] 0
} {120}
} 120
test textDisp-26.8 {AdjustForTab procedure, numeric alignment} {
    .t delete 1.0 end
    .t insert 1.0 a\ttest
    .t tag delete x
    .t tag configure x -tabs {120 numeric}
    .t tag add x 1.0 end
    .t tag add y 1.2
    lindex [.t bbox 1.6] 0
} {120}
} 120
test textDisp-26.9 {AdjustForTab procedure, numeric alignment} {
    .t delete 1.0 end
    .t insert 1.0 a\t1234
    .t tag delete x
    .t tag configure x -tabs {120 numeric}
    .t tag add x 1.0 end
    .t tag add y 1.2
    lindex [.t bbox 1.6] 0
} {120}
} 120
test textDisp-26.10 {AdjustForTab procedure, numeric alignment} {
    .t delete 1.0 end
    .t insert 1.0 a\t1.234567
    .t tag delete x
    .t tag configure x -tabs {120 numeric}
    .t tag add x 1.0 end
    .t tag add y 1.5
    lindex [.t bbox 1.3] 0
} {120}
} 120
test textDisp-26.11 {AdjustForTab procedure, numeric alignment} {
    .t delete 1.0 end
    .t insert 1.0 a\tx=1.234567
    .t tag delete x
    .t tag configure x -tabs {120 numeric}
    .t tag add x 1.0 end
    .t tag add y 1.7
    .t tag add y 1.9
    lindex [.t bbox 1.5] 0
} {120}
} 120
test textDisp-26.12 {AdjustForTab procedure, adjusting chunks} {
    .t delete 1.0 end
    .t insert 1.0 a\tx1.234567
    .t tag delete x
    .t tag configure x -tabs {120 numeric}
    .t tag add x 1.0 end
    .t tag add y 1.7
    .t tag add y 1.9
    button .b -text "="
    .t window create 1.3 -window .b
    updateText
    lindex [.t bbox 1.5] 0
} {120}
} 120
test textDisp-26.13 {AdjustForTab procedure, not enough space} {textfonts} {
    .t delete 1.0 end
    .t insert 1.0 "abc\txyz\tqrs\txyz\t0"
    .t tag delete x
    .t tag configure x -tabs {10 30 center 50 right 120}
    .t tag add x 1.0 end
    list [lindex [.t bbox 1.4] 0] [lindex [.t bbox 1.8] 0] \
3695
3696
3697
3698
3699
3700
3701
3702

3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718

3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734

3735
3736
3737
3738
3739
3740
3741
3714
3715
3716
3717
3718
3719
3720

3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736

3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752

3753
3754
3755
3756
3757
3758
3759
3760







-
+















-
+















-
+







    updateText
    set res [.t bbox 1.20]
    # Now, Tk's interpolated tabs should be the same as
    # non-interpolated.
    .t configure -tabs $precisetab
    updateText
    expr {[lindex $res 0] - [lindex [.t bbox 1.20] 0]}
} {0}
} 0

.t configure -wrap char -tabs {} -width 20
updateText
test textDisp-27.8 {SizeOfTab procedure, right alignment} {textfonts} {
    .t delete 1.0 end
    .t insert 1.0 a\t\txyzzyabc
    .t tag delete x
    .t tag configure x -tabs {100 left 140 right}
    .t tag add x 1.0 end
    list [.t bbox 1.6] [.t bbox 1.7]
} [list [list 137 5 7 $fixedHeight] [list 4 [expr {$fixedDiff + 18}] 7 $fixedHeight]]
test textDisp-27.9 {SizeOfTab procedure, left alignment} {textfonts} {
    .t delete 1.0 end
    .t insert 1.0 a\txyzzyabc
    .t tag delete x
    .t tag configure x -tabs {120}
    .t tag configure x -tabs 120
    .t tag add x 1.0 end
    list [.t bbox 1.3] [.t bbox 1.4]
} [list [list 131 5 13 $fixedHeight] [list 4 [expr {$fixedDiff + 18}] 7 $fixedHeight]]
test textDisp-27.10 {SizeOfTab procedure, numeric alignment} {textfonts} {
    .t delete 1.0 end
    .t insert 1.0 a\t123.4
    .t tag delete x
    .t tag configure x -tabs {120 numeric}
    .t tag add x 1.0 end
    list [.t bbox 1.3] [.t bbox 1.4]
} [list [list 117 5 27 $fixedHeight] [list 4 [expr {$fixedDiff + 18}] 7 $fixedHeight]]
test textDisp-27.11 {SizeOfTab procedure, making tabs at least as wide as a space} {textfonts} {
    .t delete 1.0 end
    .t insert 1.0 abc\tdefghijklmnopqrst
    .t tag delete x
    .t tag configure x -tabs {120}
    .t tag configure x -tabs 120
    .t tag add x 1.0 end
    list [.t bbox 1.5] [.t bbox 1.6]
} [list [list 131 5 13 $fixedHeight] [list 4 [expr {$fixedDiff + 18}] 7 $fixedHeight]]

proc bizarre_scroll args {
    .t2.t delete 5.0 end
}
3870
3871
3872
3873
3874
3875
3876
3877

3878
3879
3880
3881
3882
3883
3884
3889
3890
3891
3892
3893
3894
3895

3896
3897
3898
3899
3900
3901
3902
3903







-
+







    updateText
    set xv [.t2.t xview]
    set xd [expr {[lindex $xv 1] - [lindex $xv 0]}]
    .t2.t xview moveto [expr {1.0-$xd}]
    set iWidth [lindex [.t2.t bbox end-2c] 2]
    .t2.t xview scroll 2 units
    set iWidth2 [lindex [.t2.t bbox end-2c] 2]
    

    if {($iWidth == $iWidth2) && $iWidth >= 2} {
	set result "correct"
    } else {
	set result "last character is not completely visible when it should be"
    }
} {correct}
test textDisp-29.3 {miscellaneous: lines wrap but are still too long} {textfonts} {
3900
3901
3902
3903
3904
3905
3906
3907

3908
3909
3910
3911
3912
3913
3914

3915
3916
3917
3918
3919
3920

3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933

3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950

3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964

3965
3966
3967
3968
3969

3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987

3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004

4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017

4018
4019
4020
4021
4022

4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039

4040
4041
4042
4043

4044
4045
4046
4047
4048
4049
4050
3919
3920
3921
3922
3923
3924
3925

3926
3927
3928
3929
3930
3931
3932

3933
3934
3935
3936
3937
3938

3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951

3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968

3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982

3983
3984
3985
3986
3987

3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005

4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022

4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035

4036
4037
4038
4039
4040

4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057

4058
4059
4060
4061

4062
4063
4064
4065
4066
4067
4068
4069







-
+






-
+





-
+












-
+
















-
+













-
+




-
+

















-
+
















-
+












-
+




-
+
















-
+



-
+







} [list [list [expr {16.0/30}] 1.0] 300x50+-155+[expr {$fixedDiff + 18}] {}]
test textDisp-30.1 {elidden text joining multiple logical lines} {
    .t2.t delete 1.0 end
    .t2.t insert 1.0 "1111\n2222\n3333"
    .t2.t tag configure elidden -elide 1 -background red
    .t2.t tag add elidden 1.2 3.2
    .t2.t count -displaylines 1.0 end
} {1}
} 1
test textDisp-30.2 {elidden text joining multiple logical lines} {
    .t2.t delete 1.0 end
    .t2.t insert 1.0 "1111\n2222\n3333"
    .t2.t tag configure elidden -elide 1 -background red
    .t2.t tag add elidden 1.2 2.2
    .t2.t count -displaylines 1.0 end
} {2}
} 2
catch {destroy .t2}

.t configure -height 1
updateText

test textDisp-31.1 {line embedded window height update} {
test textDisp-31.1 {line embedded window height update} failsOnUbuntu {
    set res {}
    .t delete 1.0 end
    .t insert end "abcd\nefgh\nijkl\nmnop\nqrst\nuvwx\nyx"
    frame .t.f -background red -width 100 -height 100
    .t window create 3.0 -window .t.f
    lappend res [.t count -update -ypixels 1.0 end]
    .t.f configure -height 10
    lappend res [.t count -ypixels 1.0 end]
    lappend res [.t count -update -ypixels 1.0 end]
    set res
} [list [expr {100 + $fixedHeight * 6}] [expr {100 + $fixedHeight * 6}] [expr {$fixedHeight * 7}]]

test textDisp-31.2 {line update index shifting} {
test textDisp-31.2 {line update index shifting} failsOnUbuntu {
    set res {}
    .t.f configure -height 100
    updateText
    lappend res [.t count -update -ypixels 1.0 end]
    .t.f configure -height 10
    .t insert 1.0 "abc\n"
    .t insert 1.0 "abc\n"
    lappend res [.t count -ypixels 1.0 end]
    lappend res [.t count -update -ypixels 1.0 end]
    .t.f configure -height 100
    .t delete 1.0 3.0
    lappend res [.t count -ypixels 1.0 end]
    lappend res [.t count -update -ypixels 1.0 end]
    set res
} [list [expr {100 + $fixedHeight * 6}] [expr {100 + $fixedHeight * 8}] [expr {$fixedHeight * 9}] [expr {$fixedHeight * 7}] [expr {100 + $fixedHeight * 6}]]

test textDisp-31.3 {line update index shifting} {
test textDisp-31.3 {line update index shifting} failsOnUbuntu {
    # Should do exactly the same as the above, as long
    # as we are correctly tagging the correct lines for
    # recalculation.  The 'update' and 'delay' must be
    # long enough to ensure all asynchronous updates
    # have been performed.
    set res {}
    .t.f configure -height 100
    updateText
    lappend res [.t count -update -ypixels 1.0 end]
    .t.f configure -height 10
    .t insert 1.0 "abc\n"
    .t insert 1.0 "abc\n"
    lappend res [.t count -ypixels 1.0 end]
    update ; after 1000 ; update
    delay
    lappend res [.t count -ypixels 1.0 end]
    .t.f configure -height 100
    .t delete 1.0 3.0
    lappend res [.t count -ypixels 1.0 end]
    update ; after 1000 ; update
    delay
    lappend res [.t count -ypixels 1.0 end]
    set res
} [list [expr {100 + $fixedHeight * 6}] [expr {100 + $fixedHeight * 8}] [expr {$fixedHeight * 9}] [expr {$fixedHeight * 7}] [expr {100 + $fixedHeight * 6}]]

test textDisp-31.4 {line embedded image height update} {
    set res {}
    image create photo textest -height 100 -width 10
    .t delete 3.0
    .t image create 3.0 -image textest
    updateText
    lappend res [.t count -update -ypixels 1.0 end]
    textest configure -height 10
    lappend res [.t count -ypixels 1.0 end]
    lappend res [.t count -update -ypixels 1.0 end]
    set res
} [list [expr {100 + $fixedHeight * 6}] [expr {100 + $fixedHeight * 6}] [expr {$fixedHeight * 7}]]

test textDisp-31.5 {line update index shifting} {
test textDisp-31.5 {line update index shifting} failsOnUbuntu {
    set res {}
    textest configure -height 100
    updateText
    lappend res [.t count -update -ypixels 1.0 end]
    textest configure -height 10
    .t insert 1.0 "abc\n"
    .t insert 1.0 "abc\n"
    lappend res [.t count -ypixels 1.0 end]
    lappend res [.t count -update -ypixels 1.0 end]
    textest configure -height 100
    .t delete 1.0 3.0
    lappend res [.t count -ypixels 1.0 end]
    lappend res [.t count -update -ypixels 1.0 end]
    set res
} [list [expr {100 + $fixedHeight * 6}] [expr {100 + $fixedHeight * 8}] [expr {$fixedHeight * 9}] [expr {$fixedHeight * 7}] [expr {100 + $fixedHeight * 6}]]

test textDisp-31.6 {line update index shifting} {
test textDisp-31.6 {line update index shifting} failsOnUbuntu {
    # Should do exactly the same as the above, as long
    # as we are correctly tagging the correct lines for
    # recalculation.  The 'update' and 'delay' must be
    # long enough to ensure all asynchronous updates
    # have been performed.
    set res {}
    textest configure -height 100
    lappend res [.t count -update -ypixels 1.0 end]
    textest configure -height 10
    .t insert 1.0 "abc\n"
    .t insert 1.0 "abc\n"
    lappend res [.t count -ypixels 1.0 end]
    update ; after 1000 ; update
    delay
    lappend res [.t count -ypixels 1.0 end]
    textest configure -height 100
    .t delete 1.0 3.0
    lappend res [.t count -ypixels 1.0 end]
    update ; after 1000 ; update
    delay
    lappend res [.t count -ypixels 1.0 end]
    set res
} [list [expr {100 + $fixedHeight * 6}] [expr {100 + $fixedHeight * 8}] [expr {$fixedHeight * 9}] [expr {$fixedHeight * 7}] [expr {100 + $fixedHeight * 6}]]

test textDisp-31.7 {line update index shifting, elided} {
    # The 'update' and 'delay' must be long enough to ensure all
    # asynchronous updates have been performed.
    set res {}
    .t delete 1.0 end
    lappend res [.t count -update -ypixels 1.0 end]
    .t insert 1.0 "abc\nabc"
    .t insert 1.0 "abc\n"
    lappend res [.t count -update -ypixels 1.0 end]
    .t tag configure elide -elide 1
    .t tag add elide 1.3 2.1
    lappend res [.t count -ypixels 1.0 end]
    update ; after 1000 ; update
    delay
    lappend res [.t count -ypixels 1.0 end]
    .t delete 1.0 3.0
    lappend res [.t count -ypixels 1.0 end]
    update ; after 1000 ; update
    delay
    lappend res [.t count -ypixels 1.0 end]
    set res
} [list [expr {$fixedHeight * 1}] [expr {$fixedHeight * 3}] [expr {$fixedHeight * 3}] [expr {$fixedHeight * 2}] [expr {$fixedHeight * 1}] [expr {$fixedHeight * 1}]]

test textDisp-32.0 {everything elided} {
    # Must not crash
    pack [text .tt]
4171
4172
4173
4174
4175
4176
4177

4178
4179
4180
4181
4182
4183
4184
4185

4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198

4199

4200

4201

4202
4203
4204

4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217

4218
4219
4220
4221
4222
4223
4224
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224

4225

4226

4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239

4240
4241
4242
4243
4244
4245
4246
4247







+








+













+

+

+
-
+
-

-
+












-
+







} -cleanup {
    image delete $img
    destroy .tt
}

test textDisp-33.0 {one line longer than fits in the widget} {
    pack [text .tt -wrap char]
    updateText
    .tt insert 1.0 [string repeat "more wrap + " 300]
    updateText
    .tt see 1.0
    lindex [.tt yview] 0
} {0.0}
test textDisp-33.1 {one line longer than fits in the widget} {
    destroy .tt
    pack [text .tt -wrap char]
    updateText
    .tt insert 1.0 [string repeat "more wrap + " 300]
    updateText
    .tt yview "1.0 +1 displaylines"
    if {[lindex [.tt yview] 0] > 0.1} {
	set result "window should be scrolled to the top"
    } else {
	set result "ok"
    }
} {ok}
test textDisp-33.2 {one line longer than fits in the widget} {
    destroy .tt
    pack [text .tt -wrap char]
    .tt debug 1
    updateText
    set tk_textHeightCalc ""
    set timer [after 200 lappend tk_textHeightCalc "Timed out"]
    .tt insert 1.0 [string repeat "more wrap + " 1]
    vwait tk_textHeightCalc
    after 100 ; update idletasks
    after cancel $timer
    # Nothing should have been recalculated.
    set tk_textHeightCalc
} {}
} {1.0}
test textDisp-33.3 {one line longer than fits in the widget} {
    destroy .tt
    pack [text .tt -wrap char]
    .tt debug 1
    set tk_textHeightCalc ""
    .tt insert 1.0 [string repeat "more wrap + " 300]
    updateText
    .tt count -update -ypixels 1.0 end
    updateText
    # Each line should have been recalculated just once
    .tt debug 0
    expr {[llength $tk_textHeightCalc] == [.tt count -displaylines 1.0 end]}
} {1}
} 1
test textDisp-33.4 {one line longer than fits in the widget} {
    destroy .tt
    pack [text .tt -wrap char]
    .tt debug 1
    set tk_textHeightCalc ""
    .tt insert 1.0 [string repeat "more wrap + " 300]
    updateText
4281
4282
4283
4284
4285
4286
4287
4288

4289
4290
4291
4292
4293
4294
4295
4304
4305
4306
4307
4308
4309
4310

4311
4312
4313
4314
4315
4316
4317
4318







-
+







    # i.e. to check that the fix for this bug really is still in.
    wm geometry . "[expr {$width * 2}]x$height+$left+$top"
    updateText
    .t1 sync
    set negative
} -cleanup {
    destroy .t1
} -result {0}
} -result 0

test textDisp-35.1 {Init value of charHeight - Dancing scrollbar bug 1499165} -setup {
    pack [text .t1] -fill both -expand y -side left
    .t insert end "[string repeat a\nb\nc\n 500000]THE END\n"
    set res {}
} -body {
    .t see 10000.0
Changes to tests/textImage.test.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







# textImage.test -- test images embedded in text widgets
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 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
imageInit
70
71
72
73
74
75
76
77

78
79
80
81
82
83
84
85
86
87

88
89
90
91
92
93
94
95
96
97

98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117

118
119
120
121
122
123
124
70
71
72
73
74
75
76

77
78
79
80
81
82
83
84
85
86

87
88
89
90
91
92
93
94
95
96

97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116

117
118
119
120
121
122
123
124







-
+









-
+









-
+



















-
+







} -returnCodes error -result {no embedded image at index "1.1"}

test textImage-1.6 {configure argument checking} -setup {
    destroy .t
} -body {
    text .t -font test_font -bd 0 -highlightthickness 0 -padx 0 -pady 0
    pack .t
    .t image configure 
    .t image configure
} -cleanup {
    destroy .t
} -returnCodes error -result {wrong # args: should be ".t image configure index ?-option value ...?"}

test textImage-1.7 {configure argument checking} -setup {
    destroy .t
} -body {
    text .t -font test_font -bd 0 -highlightthickness 0 -padx 0 -pady 0
    pack .t
    .t image configure blurf 
    .t image configure blurf
} -cleanup {
    destroy .t
} -returnCodes error -result {bad text index "blurf"}

test textImage-1.8 {configure argument checking} -setup {
    destroy .t
} -body {
    text .t -font test_font -bd 0 -highlightthickness 0 -padx 0 -pady 0
    pack .t
    .t image configure 1.1 
    .t image configure 1.1
} -cleanup {
    destroy .t
} -returnCodes error -result {no embedded image at index "1.1"}

test textImage-1.9 {create argument checking} -setup {
    destroy .t
} -body {
    text .t -font test_font -bd 0 -highlightthickness 0 -padx 0 -pady 0
    pack .t
    .t image create
} -cleanup {
    destroy .t
} -returnCodes error -result {wrong # args: should be ".t image create index ?-option value ...?"}

test textImage-1.10 {create argument checking} -setup {
    destroy .t
} -body {
    text .t -font test_font -bd 0 -highlightthickness 0 -padx 0 -pady 0
    pack .t
    .t image create blurf 
    .t image create blurf
} -cleanup {
    destroy .t
} -returnCodes error -result {bad text index "blurf"}

test textImage-1.11 {basic argument checking} -setup {
    destroy .t
} -body {
217
218
219
220
221
222
223
224

225
226
227
228
229
230
231
217
218
219
220
221
222
223

224
225
226
227
228
229
230
231







-
+







        small put red -to 0 0 4 4
    }
    text .t -font test_font -bd 0 -highlightthickness 0 -padx 0 -pady 0
    pack .t
    .t image create end -image small
    foreach i {align padx pady image name} {
        lappend result $i:[.t image cget small -$i]
    } 
    }
    return $result
} -cleanup {
    destroy .t
    image delete small
} -result {align:center padx:0 pady:0 image:small name:}

test textImage-1.18 {basic configure options} -setup {
239
240
241
242
243
244
245
246

247
248
249
250
251
252
253
239
240
241
242
243
244
245

246
247
248
249
250
251
252
253







-
+







        large put green -to 0 0 50 50
    }
    text .t -font test_font -bd 0 -highlightthickness 0 -padx 0 -pady 0
    pack .t
    .t image create end -image small
    foreach {option value}  {align top padx 5 pady 7 image large name none} {
        .t image configure small -$option $value
    } 
    }
    update
    .t image configure small
} -cleanup {
    destroy .t
    image delete small large
} -result {{-align {} {} center top} {-padx {} {} 0 5} {-pady {} {} 0 7} {-image {} {} {} large} {-name {} {} {} none}}

305
306
307
308
309
310
311
312

313
314
315
316
317
318
319
305
306
307
308
309
310
311

312
313
314
315
316
317
318
319







-
+







    .t image create end -image vary -align top
    update
    lappend result base:[.t bbox vary]
    foreach i {10 20 40} {
        vary configure -width $i -height $i
        update
        lappend result $i:[.t bbox vary]
    } 
    }
    return $result
} -cleanup {
    destroy .t
    image delete vary
} -result {{base:0 0 5 5} {10:0 0 10 10} {20:0 0 20 20} {40:0 0 40 40}}

test textImage-3.2 {delayed image management, see also bug 1591493} -setup {
Changes to tests/textIndex.test.
1
2
3
4
5
6



7
8
9

10
11
12
13
14
15
16
17
18
19
20

21
22
23
24
25
26
27
28
29
30
31
32
33

34
35
36
37
38
39
40
1
2
3



4
5
6
7
8

9
10
11
12
13
14
15
16
17
18
19

20
21
22
23
24
25
26
27
28
29
30
31
32

33
34
35
36
37
38
39
40



-
-
-
+
+
+


-
+










-
+












-
+







# This file is a Tcl script to test the code in the file tkTextIndex.c.
# This file is organized in the standard fashion for Tcl tests.
#
# Copyright (c) 1994 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1994 The Regents of the University of California.
# Copyright © 1994 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.1
package require tcltest 2.2
eval tcltest::configure $argv
tcltest::loadTestedCommands
namespace import -force tcltest::test

catch {destroy .t}
text .t -font {Courier -12} -width 20 -height 10
pack .t -expand 1 -fill both
update
.t debug on
wm geometry . {}
  

# The statements below reset the main window;  it's needed if the window
# manager is mwm to make mwm forget about a previous minimum size setting.

wm withdraw .
wm minsize . 1 1
wm positionfrom . user
wm deiconify .

.t insert 1.0 "Line 1
abcdefghijklm
12345
Line 4
b\u4e4fy GIrl .#@? x_yz
by GIrl .#@? x_yz
!@#$%
Line 7"

image create photo textimage -width 10 -height 10
textimage put red -to 0 0 9 9

test textIndex-1.1 {TkTextMakeByteIndex} {testtext} {
70
71
72
73
74
75
76
77

78
79
80
81
82
83
84
85
86
87

88
89
90
91
92
93
94
70
71
72
73
74
75
76

77
78
79
80
81
82
83
84
85
86

87
88
89
90
91
92
93
94







-
+









-
+







    testtext .t byteindex 1 0
} {1.0 0}
test textIndex-1.9 {TkTextMakeByteIndex: shortcut for 0} {testtext} {
    # not (byteIndex == 0)
    testtext .t byteindex 3 80
} {3.5 5}
test textIndex-1.10 {TkTextMakeByteIndex: verify index is in range} {testtext} {
    # for (segPtr = indexPtr->linePtr->segPtr; ; segPtr = segPtr->nextPtr) 
    # for (segPtr = indexPtr->linePtr->segPtr; ; segPtr = segPtr->nextPtr)
    # one segment

    testtext .t byteindex 3 5
} {3.5 5}
test textIndex-1.11 {TkTextMakeByteIndex: verify index is in range} {testtext} {
    # for (segPtr = indexPtr->linePtr->segPtr; ; segPtr = segPtr->nextPtr)
    #     index += segPtr->size
    # Multiple segments, make sure add segment size to index.

    .t mark set foo 3.2 
    .t mark set foo 3.2
    set x [testtext .t byteindex 3 7]
    .t mark unset foo
    set x
} {3.5 5}
test textIndex-1.12 {TkTextMakeByteIndex: verify index is in range} {testtext} {
    # (segPtr == NULL)
    testtext .t byteindex 3 7
113
114
115
116
117
118
119
120
121


122
123
124
125
126
127
128

129
130
131

132
133
134
135
136
137
138
113
114
115
116
117
118
119


120
121
122
123
124
125
126
127

128
129
130

131
132
133
134
135
136
137
138







-
-
+
+






-
+


-
+







    set x
} {3.4 4}
test textIndex-1.16 {TkTextMakeByteIndex: UTF-8 characters} {testtext} {
    testtext .t byteindex 5 100
} {5.18 20}
test textIndex-1.17 {TkTextMakeByteIndex: prevent splitting UTF-8 character} \
	{testtext} {
    # ((byteIndex > index) && (segPtr->typePtr == &tkTextCharType)) 
    # Wrong answer would be \xb9 (the 2nd byte of UTF rep of 0x4e4f).
    # ((byteIndex > index) && (segPtr->typePtr == &tkTextCharType))
    # Wrong answer would be ¹ (the 2nd byte of UTF rep of 0x4e4f).

    set x [testtext .t byteindex 5 2]
    list $x [.t get insert]
} {{5.2 4} y}
test textIndex-1.18 {TkTextMakeByteIndex: prevent splitting UTF-8 character} \
	{testtext} {
    # ((byteIndex > index) && (segPtr->typePtr == &tkTextCharType)) 
    # ((byteIndex > index) && (segPtr->typePtr == &tkTextCharType))
    testtext .t byteindex 5 1
    .t get insert
} "\u4e4f"
} ""

test textIndex-2.1 {TkTextMakeCharIndex} {
    # (lineIndex < 0)
    .t index -1.3
} 1.0
test textIndex-2.2 {TkTextMakeCharIndex} {
    # (lineIndex < 0), because lineIndex == strtol(argv[2]) - 1
164
165
166
167
168
169
170
171

172
173
174
175
176
177
178
179
180
181
182
183
184
185
186

187
188
189
190
191
192
193
164
165
166
167
168
169
170

171
172
173
174
175
176
177
178
179
180
181
182
183
184
185

186
187
188
189
190
191
192
193







-
+














-
+








    .t index 3.5
} 3.5
test textIndex-2.9 {TkTextMakeCharIndex: verify index is in range} {
    # for (segPtr = indexPtr->linePtr->segPtr; ; segPtr = segPtr->nextPtr)
    # Multiple segments, make sure add segment size to index.

    .t mark set foo 3.2 
    .t mark set foo 3.2
    set x [.t index 3.7]
    .t mark unset foo
    set x
} 3.5
test textIndex-2.10 {TkTextMakeCharIndex: verify index is in range} {
    # (segPtr == NULL)
    .t index 3.7
} 3.5
test textIndex-2.11 {TkTextMakeCharIndex: verify index is in range} {
    # not (segPtr == NULL)
    .t index 3.4
} 3.4
test textIndex-2.12 {TkTextMakeCharIndex: verify index is in range} {
    # (segPtr->typePtr == &tkTextCharType)
    # Wrong answer would be \xb9 (the 2nd byte of UTF rep of 0x4e4f).
    # Wrong answer would be ¹ (the 2nd byte of UTF rep of 0x4e4f).

    .t mark set insert 5.2
    .t get insert
} y
test textIndex-2.13 {TkTextMakeCharIndex: verify index is in range} {
    # not (segPtr->typePtr == &tkTextCharType)

435
436
437
438
439
440
441
442

443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461

462
463
464
465
466
467
468
435
436
437
438
439
440
441

442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460

461
462
463
464
465
466
467
468







-
+


















-
+







    # border condition: last char

    .t index {2.3 + 10 chars}
} 2.13
test textIndex-12.6 {TkTextIndexForwChars: find index} {
    # for ( ; segPtr != NULL; segPtr = segPtr->nextPtr)
    # border condition: segPtr == NULL -> beginning of next line
    

    .t index {2.3 + 11 chars}
} 3.0
test textIndex-12.7 {TkTextIndexForwChars: find index} {
    # (segPtr->typePtr == &tkTextCharType)
    .t index {2.3 + 2 chars}
} 2.5
test textIndex-12.8 {TkTextIndexForwChars: find index} {
    # (charCount == 0)
    # No more chars, so we found byte offset.

    .t index {2.3 + 2 chars}
} 2.5
test textIndex-12.9 {TkTextIndexForwChars: find index} {
    # not (segPtr->typePtr == &tkTextCharType)

    .t image create 2.4 -image textimage
    set x [.t get {2.3 + 3 chars}]
    .t delete 2.4
    set x    
    set x
} "f"
test textIndex-12.10 {TkTextIndexForwChars: find index} {
    # dstPtr->byteIndex += segPtr->size - byteOffset
    # When moving to next segment, account for bytes in last segment.
    # Wrong answer would be 2.4

    .t mark set foo 2.4
584
585
586
587
588
589
590
591

592
593
594
595

596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611

612
613
614
615
616
617
618
584
585
586
587
588
589
590

591
592
593
594

595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610

611
612
613
614
615
616
617
618







-
+



-
+















-
+








    .t mark set foo 3.4
    set x [.t index {3.5 - 10 chars}]
    .t mark unset foo
    set x
} 2.9
test textIndex-14.12 {TkTextIndexBackChars: move to previous line} {
    # (lineIndex == 0) 
    # (lineIndex == 0)
    .t index {1.5 - 10 chars}
} 1.0
test textIndex-14.13 {TkTextIndexBackChars: move to previous line} {
    # not (lineIndex == 0) 
    # not (lineIndex == 0)
    .t index {2.5 - 10 chars}
} 1.2
test textIndex-14.14 {TkTextIndexBackChars: move to previous line} {
    # for (segPtr = oldPtr; segPtr != NULL; segPtr = segPtr->nextPtr)
    # Set byteIndex to end of previous line so we can subtract more
    # bytes from it.  Otherwise we get an TkTextIndex with a negative
    # byteIndex.

    .t index {2.5 - 6 chars}
} 1.6
test textIndex-14.15 {TkTextIndexBackChars: UTF} {
    .t get {5.3 - 1 chars}
} y
test textIndex-14.16 {TkTextIndexBackChars: UTF} {
    .t get {5.3 - 2 chars}
} \u4e4f
} 
test textIndex-14.17 {TkTextIndexBackChars: UTF} {
    .t get {5.3 - 3 chars}
} b

proc getword index {
    .t get [.t index "$index wordstart"] [.t index "$index wordend"]
}
805
806
807
808
809
810
811
812

813
814
815

816
817
818
819
820
821
822
805
806
807
808
809
810
811

812
813
814

815
816
817
818
819
820
821
822







-
+


-
+








test textIndex-19.12.1 {Display lines} {
    .t index "2.50 - 100 displaylines"
} {1.0}

test textIndex-19.12.2 {Display lines} {
    .t compare [.t index "2.50 + 100 displaylines"] == "end - 1 c"
} {1}
} 1

test textIndex-19.13 {Display lines} {
    destroy {*}[pack slaves .]
    destroy {*}[pack content .]
    text .txt -height 1 -wrap word -yscroll ".sbar set" -width 400
    scrollbar .sbar -command ".txt yview"
    grid .txt .sbar -sticky news
    grid configure .sbar -sticky ns
    grid rowconfigure    . 0 -weight 1
    grid columnconfigure . 0 -weight 1
    .txt configure -width 10
867
868
869
870
871
872
873
874

875
876
877

878
879
880

881
882
883

884
885
886

887
888
889
890
891
892
893
867
868
869
870
871
872
873

874
875
876

877
878
879

880
881
882

883
884
885

886
887
888
889
890
891
892
893







-
+


-
+


-
+


-
+


-
+







test textIndex-21.8 {text index wordend} {
    text_test_word worde "x.y" 0
} 1
test textIndex-21.9 {text index wordend} {
    text_test_word worde "x.y" end-1
} 2
test textIndex-21.10 {text index wordend, unicode} {
    text_test_word wordend "xyz\u00c7de fg" 0
    text_test_word wordend "xyzÇde fg" 0
} 6
test textIndex-21.11 {text index wordend, unicode} {
    text_test_word wordend "xyz\uc700de fg" 0
    text_test_word wordend "xyzde fg" 0
} 6
test textIndex-21.12 {text index wordend, unicode} {
    text_test_word wordend "xyz\u203fde fg" 0
    text_test_word wordend "xyzde fg" 0
} 6
test textIndex-21.13 {text index wordend, unicode} {
    text_test_word wordend "xyz\u2045de fg" 0
    text_test_word wordend "xyzde fg" 0
} 3
test textIndex-21.14 {text index wordend, unicode} {
    text_test_word wordend "\uc700\uc700 abc" 8
    text_test_word wordend "윀윀 abc" 8
} 6

test textIndex-22.5 {text index wordstart} {
    text_test_word wordstart "one two three_words" 400
} 8
test textIndex-22.6 {text index wordstart} {
    text_test_word wordstart "one two three_words" 2
901
902
903
904
905
906
907
908

909
910
911

912
913
914

915
916
917
918
919
920


921
922
923
924
925
926
927
901
902
903
904
905
906
907

908
909
910

911
912
913

914
915
916
917
918


919
920
921
922
923
924
925
926
927







-
+


-
+


-
+




-
-
+
+







test textIndex-22.9 {text index wordstart} {
    text_test_word wordstart "one two three" 4
} 4
test textIndex-22.10 {text index wordstart} {
    text_test_word wordstart "one two three" end-5
} 7
test textIndex-22.11 {text index wordstart, unicode} {
    text_test_word wordstart "one tw\u00c7o three" 7
    text_test_word wordstart "one twÇo three" 7
} 4
test textIndex-22.12 {text index wordstart, unicode} {
    text_test_word wordstart "ab\uc700\uc700 cdef ghi" 12
    text_test_word wordstart "ab윀윀 cdef ghi" 12
} 10
test textIndex-22.13 {text index wordstart, unicode} {
    text_test_word wordstart "\uc700\uc700 abc" 8
    text_test_word wordstart "윀윀 abc" 8
} 3
test textIndex-22.14 {text index wordstart, unicode, start index at internal segment start} {
    catch {destroy .t}
    text .t
    .t insert end "C'est du texte en fran\u00e7ais\n"
    .t insert end "\u042D\u0442\u043E\u0020\u0442\u0435\u043A\u0441\u0442\u0020\u043D\u0430\u0020\u0440\u0443\u0441\u0441\u043A\u043E\u043C"
    .t insert end "C'est du texte en français\n"
    .t insert end "Это текст на русском"
    .t mark set insert 1.23
    set res [.t index "1.23 wordstart"]
    .t mark set insert 2.16
    lappend res [.t index "2.16 wordstart"] [.t index "2.15 wordstart"]
} {1.18 2.13 2.13}
test textIndex-22.15 {text index display wordstart} {
    catch {destroy .t}
Changes to tests/textMark.test.
1
2
3
4
5
6



7
8
9
10
11
12
13
1
2
3



4
5
6
7
8
9
10
11
12
13



-
-
-
+
+
+







# This file is a Tcl script to test the code in the file tkTextMark.c.
# This file is organized in the standard fashion for Tcl tests.
#
# Copyright (c) 1994 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1994 The Regents of the University of California.
# Copyright © 1994 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
namespace import ::tcltest::*
tcltest::configure {*}$argv
tcltest::loadTestedCommands

23
24
25
26
27
28
29
30

31
32
33
34
35
36
37
23
24
25
26
27
28
29

30
31
32
33
34
35
36
37







-
+







.t insert 1.0 "Line 1
abcdefghijklm
12345
Line 4
bOy GIrl .#@? x_yz
!@#$%
Line 7"
  

# The statements below reset the main window; it's needed if the window
# manager is mwm to make mwm forget about a previous minimum size setting.

wm withdraw .
wm minsize . 1 1
wm positionfrom . user
wm deiconify .
48
49
50
51
52
53
54
55

56
57
58
59
60
61
62
48
49
50
51
52
53
54

55
56
57
58
59
60
61
62







-
+







test textMark-1.4 {TkTextMarkCmd - "gravity" option} -body {
    .t mark set x 1.3
    .t insert 1.3 x
    list [.t mark gravity x] [.t index x]
} -result {right 1.4}
test textMark-1.5 {TkTextMarkCmd - "gravity" option} -body {
    .t mark set x 1.3
    .t mark g x left
    .t mark gr x left
    .t insert 1.3 x
    list [.t mark gravity x] [.t index x]
} -result {left 1.3}
test textMark-1.6 {TkTextMarkCmd - "gravity" option} -body {
    .t mark set x 1.3
    .t mark gravity x right
    .t insert 1.3 x
173
174
175
176
177
178
179
180

181
182
183
184
185
186
187
173
174
175
176
177
178
179

180
181
182
183
184
185
186
187







-
+







} -cleanup {
  .t configure -startline {} -endline {}
  .pt configure -startline {} -endline {}
  .t mark unset mymark
} -result {1 {bad text index "mymark"} 1.0 1.0 1 {bad text index "mymark"} L 1 {bad text index "mymark"}}
test textMark-6.5 {insert and current marks in an empty peer - bug 3487407} -body {
  .t mark set insert 1.0
  .t configure -start 5 -end 5
  .t configure -startline 5 -endline 5
  set res [.t index insert]
} -cleanup {
  .t configure -startline {} -endline {}
} -result {1.0}

test textMark-7.1 {MarkFindNext - invalid mark name} -body {
    .t mark next bogus
Changes to tests/textTag.test.
1
2
3
4
5
6



7
8
9
10
11
12
13


















14
15
16
17
18
19
20
21
22
23
24
25
26

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

44
45
46
47
48
49
50
51

52
53
54
55
56
57
58

59
60
61
62
63
64
65
66

67
68
69
70
71
72
73

74
75
76
77
78
79
80
81


82
83
84
85
86
87
88

89
90
91
92
93
94
95
96

97
98
99
100
101
102
103

104
105
106
107
108
109
110
111

112
113
114
115
116
117
118
119

120
121
122
123
124
125
126

127
128
129
130
131
132
133
134

135
136
137
138
139
140
141

142
143
144
145
146
147
148
149


150
151
152
153
154
155
156

157
158
159
160
161
162
163
164


165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182

183
184
185
186
187
188
189
190


191
192
193
194
195
196
197

198
199
200
201
202
203
204
205

206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223

224
225
226
227
228
229
230
231

232
233
234
235
236
237
238

239
240
241
242
243
244
245
246


247
248
249
250
251
252
253
254
255
1
2
3



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33



34
35
36
37
38
39


40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

57


58
59
60
61
62

63


64
65
66
67

68


69
70
71
72
73

74


75
76
77
78

79


80
81
82
83


84
85


86
87
88
89

90


91
92
93
94
95

96


97
98
99
100

101


102
103
104
105
106

107


108
109
110
111
112

113


114
115
116
117

118


119
120
121
122
123

124


125
126
127
128

129


130
131
132
133


134
135


136
137
138
139

140


141
142
143
144


145
146


147
148
149
150
151
152
153
154
155
156
157
158
159
160
161

162


163
164
165
166


167
168


169
170
171
172

173


174
175
176
177
178

179


180
181
182
183
184
185
186
187
188
189
190
191
192
193
194

195


196
197
198
199
200

201


202
203
204
205

206


207
208
209
210


211
212


213
214
215
216
217
218
219



-
-
-
+
+
+







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
-
-






-
-
+
















-
+
-
-





-
+
-
-




-
+
-
-





-
+
-
-




-
+
-
-




-
-
+
+
-
-




-
+
-
-





-
+
-
-




-
+
-
-





-
+
-
-





-
+
-
-




-
+
-
-





-
+
-
-




-
+
-
-




-
-
+
+
-
-




-
+
-
-




-
-
+
+
-
-















-
+
-
-




-
-
+
+
-
-




-
+
-
-





-
+
-
-















-
+
-
-





-
+
-
-




-
+
-
-




-
-
+
+
-
-







# This file is a Tcl script to test the code in the file tkTextTag.c.
# This file is organized in the standard fashion for Tcl tests.
#
# Copyright (c) 1994 The Regents of the University of California.
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1994 The Regents of the University of California.
# Copyright © 1994-1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
namespace import ::tcltest::*
eval tcltest::configure $argv
tcltest::loadTestedCommands

set textWidgetFont {Courier 12}
set bigFont        {Courier 24}

# what is needed is a font that is both fixed-width and featuring a
# specific size because in some tests (that will be constrained by
# haveFontSizes), a tag applying the $bigFont will be set to some
# characters, which action has the effect of changing what character
# is under the mouse pointer, which is the purpose of the tests
testConstraint haveFontSizes [expr {
    [font metrics $textWidgetFont -fixed] &&
    [font actual  $textWidgetFont -size] == 12 &&
    [font metrics $bigFont -fixed] &&
    [font actual  $bigFont -size] == 24 }
]

testConstraint failsOnUbuntu [expr {![info exists ::env(CI)] || ![string match Linux $::tcl_platform(os)]}]
testConstraint failsOnUbuntuNoXft [expr {[testConstraint failsOnUbuntu] || (![catch {tk::pkgconfig get fontsystem} fs] && ($fs eq "xft"))}]

destroy .t
text .t -width 20 -height 10
testConstraint haveCourier12 [expr {[catch {
    .t configure -font {Courier 12}
}] == 0}]

pack .t -expand 1 -fill both
update
.t debug on

wm geometry . {}
set bigFont {Helvetica 24}
  

# The statements below reset the main window;  it's needed if the window
# manager is mwm, to make mwm forget about a previous minimum size setting.

wm withdraw .
wm minsize . 1 1
wm positionfrom . user
wm deiconify .

.t insert 1.0 "Line 1
abcdefghijklm
12345
Line 4
bOy GIrl .#@? x_yz
!@#$%
Line 7"

test textTag-1.1 {tag configuration options} -constraints {
test textTag-1.1 {tag configuration options} -body {
    haveCourier12
} -body {
    .t tag configure x -background #012345
    .t tag cget x -background
} -cleanup {
    .t tag configure x -background [lindex [.t tag configure x -background] 3]
} -result {#012345}
test textTag-1.2 {configuration options} -constraints {
test textTag-1.2 {configuration options} -body {
    haveCourier12
} -body {
    .t tag configure x -background non-existent
} -cleanup {
    .t tag configure x -background [lindex [.t tag configure x -background] 3]
} -returnCodes error -result {unknown color name "non-existent"}
test textTag-1.3 {tag configuration options} -constraints {
test textTag-1.3 {tag configuration options} -body {
    haveCourier12
} -body {
    .t tag configure x -bgstipple gray50
    .t tag cget x -bgstipple
} -cleanup {
    .t tag configure x -bgstipple [lindex [.t tag configure x -bgstipple] 3]
} -result {gray50}
test textTag-1.4 {configuration options} -constraints {
test textTag-1.4 {configuration options} -body {
    haveCourier12
} -body {
    .t tag configure x -bgstipple badStipple
} -cleanup {
    .t tag configure x -bgstipple [lindex [.t tag configure x -bgstipple] 3]
} -returnCodes error -result {bitmap "badStipple" not defined}
test textTag-1.5 {tag configuration options} -constraints {
test textTag-1.5 {tag configuration options} -body {
    haveCourier12
} -body {
    .t tag configure x -borderwidth 2
    .t tag cget x -borderwidth
} -cleanup {
    .t tag configure x -borderwidth [lindex [.t tag configure x -borderwidth] 3]
} -result {2}
test textTag-1.6 {configuration options} -constraints {
} -result 2
test textTag-1.6 {configuration options} -body {
    haveCourier12
} -body {
    .t tag configure x -borderwidth 46q
} -cleanup {
    .t tag configure x -borderwidth [lindex [.t tag configure x -borderwidth] 3]
} -returnCodes error -result {bad screen distance "46q"}
test textTag-1.7 {tag configuration options} -constraints {
test textTag-1.7 {tag configuration options} -body {
    haveCourier12
} -body {
    .t tag configure x -fgstipple gray25
    .t tag cget x -fgstipple
} -cleanup {
    .t tag configure x -fgstipple [lindex [.t tag configure x -fgstipple] 3]
} -result {gray25}
test textTag-1.8 {configuration options} -constraints {
test textTag-1.8 {configuration options} -body {
    haveCourier12
} -body {
    .t tag configure x -fgstipple bogus
} -cleanup {
    .t tag configure x -fgstipple [lindex [.t tag configure x -fgstipple] 3]
} -returnCodes error -result {bitmap "bogus" not defined}
test textTag-1.9 {tag configuration options} -constraints {
test textTag-1.9 {tag configuration options} -body {
    haveCourier12
} -body {
    .t tag configure x -font fixed
    .t tag cget x -font
} -cleanup {
    .t tag configure x -font [lindex [.t tag configure x -font] 3]
} -result {fixed}
test textTag-1.10 {tag configuration options} -constraints {
test textTag-1.10 {tag configuration options} -body {
    haveCourier12
} -body {
    .t tag configure x -foreground #001122
    .t tag cget x -foreground
} -cleanup {
    .t tag configure x -foreground [lindex [.t tag configure x -foreground] 3]
} -result {#001122}
test textTag-1.11 {configuration options} -constraints {
test textTag-1.11 {configuration options} -body {
    haveCourier12
} -body {
    .t tag configure x -foreground {silly color}
} -cleanup {
    .t tag configure x -foreground [lindex [.t tag configure x -foreground] 3]
} -returnCodes error -result {unknown color name "silly color"}
test textTag-1.12 {tag configuration options} -constraints {
test textTag-1.12 {tag configuration options} -body {
    haveCourier12
} -body {
    .t tag configure x -justify left
    .t tag cget x -justify
} -cleanup {
    .t tag configure x -justify [lindex [.t tag configure x -justify] 3]
} -result {left}
test textTag-1.13 {configuration options} -constraints {
test textTag-1.13 {configuration options} -body {
    haveCourier12
} -body {
    .t tag configure x -justify middle
} -cleanup {
    .t tag configure x -justify [lindex [.t tag configure x -justify] 3]
} -returnCodes error -result {bad justification "middle": must be left, right, or center}
test textTag-1.14 {tag configuration options} -constraints {
test textTag-1.14 {tag configuration options} -body {
    haveCourier12
} -body {
    .t tag configure x -lmargin1 10
    .t tag cget x -lmargin1
} -cleanup {
    .t tag configure x -lmargin1 [lindex [.t tag configure x -lmargin1] 3]
} -result {10}
test textTag-1.15 {configuration options} -constraints {
} -result 10
test textTag-1.15 {configuration options} -body {
    haveCourier12
} -body {
    .t tag configure x -lmargin1 bad
} -cleanup {
    .t tag configure x -lmargin1 [lindex [.t tag configure x -lmargin1] 3]
} -returnCodes error -result {bad screen distance "bad"}
test textTag-1.16 {tag configuration options} -constraints {
test textTag-1.16 {tag configuration options} -body {
    haveCourier12
} -body {
    .t tag configure x -lmargin2 10
    .t tag cget x -lmargin2
} -cleanup {
    .t tag configure x -lmargin2 [lindex [.t tag configure x -lmargin2] 3]
} -result {10}
test textTag-1.17 {configuration options} -constraints {
} -result 10
test textTag-1.17 {configuration options} -body {
    haveCourier12
} -body {
    .t tag configure x -lmargin2 bad
} -cleanup {
    .t tag configure x -lmargin2 [lindex [.t tag configure x -lmargin2] 3]
} -returnCodes error -result {bad screen distance "bad"}
test textTag-1.17a {tag configuration options} -body {
    .t tag configure x -lmargincolor lightgreen
    .t tag cget x -lmargincolor
} -cleanup {
    .t tag configure x -lmargincolor [lindex [.t tag configure x -lmargincolor] 3]
} -result {lightgreen}
test textTag-1.17b {configuration options} -body {
    .t tag configure x -lmargincolor non-existent
} -cleanup {
    .t tag configure x -lmargincolor [lindex [.t tag configure x -lmargincolor] 3]
} -returnCodes error -result {unknown color name "non-existent"}
test textTag-1.18 {tag configuration options} -constraints {
test textTag-1.18 {tag configuration options} -body {
    haveCourier12
} -body {
    .t tag configure x -offset 2
    .t tag cget x -offset
} -cleanup {
    .t tag configure x -offset [lindex [.t tag configure x -offset] 3]
} -result {2}
test textTag-1.19 {configuration options} -constraints {
} -result 2
test textTag-1.19 {configuration options} -body {
    haveCourier12
} -body {
    .t tag configure x -offset 100xyz
} -cleanup {
    .t tag configure x -offset [lindex [.t tag configure x -offset] 3]
} -returnCodes error -result {bad screen distance "100xyz"}
test textTag-1.20 {tag configuration options} -constraints {
test textTag-1.20 {tag configuration options} -body {
    haveCourier12
} -body {
    .t tag configure x -overstrike on
    .t tag cget x -overstrike
} -cleanup {
    .t tag configure x -overstrike [lindex [.t tag configure x -overstrike] 3]
} -result {on}
test textTag-1.21 {configuration options} -constraints {
test textTag-1.21 {configuration options} -body {
    haveCourier12
} -body {
    .t tag configure x -overstrike stupid
} -cleanup {
    .t tag configure x -overstrike [lindex [.t tag configure x -overstrike] 3]
} -returnCodes error -result {expected boolean value but got "stupid"}
test textTag-1.21a {tag configuration options} -body {
    .t tag configure x -overstrikefg red
    .t tag cget x -overstrikefg
} -cleanup {
    .t tag configure x -overstrikefg [lindex [.t tag configure x -overstrikefg] 3]
} -result {red}
test textTag-1.21b {configuration options} -body {
    .t tag configure x -overstrikefg stupid
} -cleanup {
    .t tag configure x -overstrikefg [lindex [.t tag configure x -overstrikefg] 3]
} -returnCodes error -result {unknown color name "stupid"}
test textTag-1.22 {tag configuration options} -constraints {
test textTag-1.22 {tag configuration options} -body {
    haveCourier12
} -body {
    .t tag configure x -relief raised
    .t tag cget x -relief
} -cleanup {
    .t tag configure x -relief [lindex [.t tag configure x -relief] 3]
} -result {raised}
test textTag-1.23 {configuration options} -constraints {
test textTag-1.23 {configuration options} -body {
    haveCourier12
} -body {
    .t tag configure x -relief stupid
} -cleanup {
    .t tag configure x -relief [lindex [.t tag configure x -relief] 3]
} -returnCodes error -result {bad relief "stupid": must be flat, groove, raised, ridge, solid, or sunken}
test textTag-1.24 {tag configuration options} -constraints {
test textTag-1.24 {tag configuration options} -body {
    haveCourier12
} -body {
    .t tag configure x -rmargin 10
    .t tag cget x -rmargin
} -cleanup {
    .t tag configure x -rmargin [lindex [.t tag configure x -rmargin] 3]
} -result {10}
test textTag-1.25 {configuration options} -constraints {
} -result 10
test textTag-1.25 {configuration options} -body {
    haveCourier12
} -body {
    .t tag configure x -rmargin bad
} -cleanup {
    .t tag configure x -rmargin [lindex [.t tag configure x -rmargin] 3]
} -returnCodes error -result {bad screen distance "bad"}
test textTag-1.25a {tag configuration options} -body {
    .t tag configure x -rmargincolor darkblue
    .t tag cget x -rmargincolor
279
280
281
282
283
284
285
286

287
288
289
290
291
292
293
294


295
296
297
298
299
300
301

302
303
304
305
306
307
308
309


310
311
312
313
314
315
316

317
318
319
320
321
322
323
324


325
326
327
328
329
330
331

332
333
334
335
336
337
338
339

340
341
342
343
344
345
346

347
348
349
350
351
352
353
354

355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374

375
376
377
378
379

380
381
382
383
384

385
386
387
388
389

390
391
392
393
394

395
396
397
398
399

400
401
402
403
404
405
406
407
408

409
410
411
412
413
414
415
416
417
418

419
420
421
422
423
424
425
426
427
428

429
430
431
432
433
434
435
436
437
438
439
440
441
442

443
444
445
446
447
448
449
450
451
452
453
454
455
456
457

458
459
460
461
462
463
464

465
466
467
468
469
470
471
472
473

474
475
476
477
478
479
480
481
482
483
484
485

486
487
488

489
490
491
492
493

494
495
496
497
498

499
500
501
502
503
504
505
506

507
508
509
510
511

512
513
514
515
516
517
518
519
520

521
522
523
524
525

526
527
528
529
530

531
532
533
534
535
536
537
538
539
540
541

542
543
544
545
546
547
548
549
550
551
552

553
554
555
556
557
558
559
560

561
562
563
564
565
566
567
568
569
570

571
572
573
574
575

576
577
578
579
580

581
582
583
584
585
586

587
588
589
590
591

592
593
594
595
596
597
598
599
600
601
602

603
604
605
606
607


608
609
610
611
612

613
614
615
616
617
618
619

620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635

636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651

652
653
654
655
656
657
658

659
660
661
662
663
664
665
666

667
668
669
670
671
672
673
674
675

676
677
678
679
680
681
682
683

684
685
686
687
688
689
690
691

692
693
694
695
696
697
698
699
700

701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721

722
723
724
725
726
727
728
729

730
731
732
733
734
735
736
737
738
739
740
741
742
743

744
745
746
747
748
749
750
751
752
753
754
755
756
757
758

759
760
761
762
763
764
765
766
767
768

769
770
771
772
773
774
775
776

777
778
779
780
781
782
783
784

785
786
787
788
789
790
791
792

793
794
795
796
797
798
799
800
801
802
803
804

805
806
807
808
809
810
811
812
813
243
244
245
246
247
248
249

250


251
252
253
254


255
256


257
258
259
260

261


262
263
264
265


266
267


268
269
270
271

272


273
274
275
276


277
278


279
280
281
282

283


284
285
286
287
288

289


290
291
292
293

294


295
296
297
298
299

300


301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317

318


319
320

321


322
323

324


325
326

327


328
329

330


331
332

333


334
335
336
337
338
339

340


341
342
343
344
345
346
347

348


349
350
351
352
353
354
355

356


357
358
359
360
361
362
363
364
365
366
367

368


369
370
371
372
373
374
375
376
377
378
379
380

381


382
383
384
385

386


387
388
389
390
391
392

393
394
395
396
397
398
399
400
401
402
403
404

405
406
407

408


409
410

411


412
413

414


415
416
417
418
419

420


421
422

423


424
425
426
427
428
429

430


431
432

433
434
435
436
437

438


439
440
441
442
443
444
445
446

447


448
449
450
451
452
453
454
455

456


457
458
459
460
461

462


463
464
465
466
467
468
469

470


471
472

473


474
475

476


477
478
479

480


481
482

483


484
485
486
487
488
489
490
491

492


493


494
495


496
497

498


499
500
501
502

503


504
505
506
507
508
509
510
511
512
513
514
515
516

517


518
519
520
521
522
523
524
525
526
527
528
529
530

531


532
533
534
535

536


537
538
539
540
541

542


543
544
545
546
547
548

549


550
551
552
553
554

555


556
557
558
559
560

561


562
563
564
565
566
567

568


569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586

587


588
589
590
591
592

593


594
595
596
597
598
599
600
601
602
603
604

605


606
607
608
609
610
611
612
613
614
615
616
617

618


619
620
621
622
623
624
625

626


627
628
629
630
631

632


633
634
635
636
637

638


639
640
641
642
643

644


645
646
647
648
649
650
651
652
653

654


655
656
657
658
659
660
661







-
+
-
-




-
-
+
+
-
-




-
+
-
-




-
-
+
+
-
-




-
+
-
-




-
-
+
+
-
-




-
+
-
-





-
+
-
-




-
+
-
-





-
+
-
-

















-
+
-
-


-
+
-
-


-
+
-
-


-
+
-
-


-
+
-
-


-
+
-
-






-
+
-
-







-
+
-
-







-
+
-
-











-
+
-
-












-
+
-
-




-
+
-
-






-
+











-
+


-
+
-
-


-
+
-
-


-
+
-
-





-
+
-
-


-
+
-
-






-
+
-
-


-
+




-
+
-
-








-
+
-
-








-
+
-
-





-
+
-
-







-
+
-
-


-
+
-
-


-
+
-
-



-
+
-
-


-
+
-
-








-
+
-
-

-
-
+
+
-
-


-
+
-
-




-
+
-
-













-
+
-
-













-
+
-
-




-
+
-
-





-
+
-
-






-
+
-
-





-
+
-
-





-
+
-
-






-
+
-
-


















-
+
-
-





-
+
-
-











-
+
-
-












-
+
-
-







-
+
-
-





-
+
-
-





-
+
-
-





-
+
-
-









-
+
-
-







    .t tag configure x -selectforeground [lindex [.t tag configure x -selectforeground] 3]
} -result {#012345}
test textTag-1.25f {configuration options} -body {
    .t tag configure x -selectforeground non-existent
} -cleanup {
    .t tag configure x -selectforeground [lindex [.t tag configure x -selectforeground] 3]
} -returnCodes error -result {unknown color name "non-existent"}
test textTag-1.26 {tag configuration options} -constraints {
test textTag-1.26 {tag configuration options} -body {
    haveCourier12
} -body {
    .t tag configure x -spacing1 10
    .t tag cget x -spacing1
} -cleanup {
    .t tag configure x -spacing1 [lindex [.t tag configure x -spacing1] 3]
} -result {10}
test textTag-1.27 {configuration options} -constraints {
} -result 10
test textTag-1.27 {configuration options} -body {
    haveCourier12
} -body {
    .t tag configure x -spacing1 bad
} -cleanup {
    .t tag configure x -spacing1 [lindex [.t tag configure x -spacing1] 3]
} -returnCodes error -result {bad screen distance "bad"}
test textTag-1.28 {tag configuration options} -constraints {
test textTag-1.28 {tag configuration options} -body {
    haveCourier12
} -body {
    .t tag configure x -spacing2 10
    .t tag cget x -spacing2
} -cleanup {
    .t tag configure x -spacing2 [lindex [.t tag configure x -spacing2] 3]
} -result {10}
test textTag-1.29 {configuration options} -constraints {
} -result 10
test textTag-1.29 {configuration options} -body {
    haveCourier12
} -body {
    .t tag configure x -spacing2 bad
} -cleanup {
    .t tag configure x -spacing2 [lindex [.t tag configure x -spacing2] 3]
} -returnCodes error -result {bad screen distance "bad"}
test textTag-1.30 {tag configuration options} -constraints {
test textTag-1.30 {tag configuration options} -body {
    haveCourier12
} -body {
    .t tag configure x -spacing3 10
    .t tag cget x -spacing3
} -cleanup {
    .t tag configure x -spacing3 [lindex [.t tag configure x -spacing3] 3]
} -result {10}
test textTag-1.31 {configuration options} -constraints {
} -result 10
test textTag-1.31 {configuration options} -body {
    haveCourier12
} -body {
    .t tag configure x -spacing3 bad
} -cleanup {
    .t tag configure x -spacing3 [lindex [.t tag configure x -spacing3] 3]
} -returnCodes error -result {bad screen distance "bad"}
test textTag-1.32 {tag configuration options} -constraints {
test textTag-1.32 {tag configuration options} -body {
    haveCourier12
} -body {
    .t tag configure x -tabs {10 20 30}
    .t tag cget x -tabs
} -cleanup {
    .t tag configure x -tabs [lindex [.t tag configure x -tabs] 3]
} -result {10 20 30}
test textTag-1.33 {configuration options} -constraints {
test textTag-1.33 {configuration options} -body {
    haveCourier12
} -body {
    .t tag configure x -tabs {10 fork}
} -cleanup {
    .t tag configure x -tabs [lindex [.t tag configure x -tabs] 3]
} -returnCodes error -result {bad tab alignment "fork": must be left, right, center, or numeric}
test textTag-1.34 {tag configuration options} -constraints {
test textTag-1.34 {tag configuration options} -body {
    haveCourier12
} -body {
    .t tag configure x -underline no
    .t tag cget x -underline
} -cleanup {
    .t tag configure x -underline [lindex [.t tag configure x -underline] 3]
} -result {no}
test textTag-1.35 {configuration options} -constraints {
test textTag-1.35 {configuration options} -body {
    haveCourier12
} -body {
    .t tag configure x -underline stupid
} -cleanup {
    .t tag configure x -underline [lindex [.t tag configure x -underline] 3]
} -returnCodes error -result {expected boolean value but got "stupid"}
test textTag-1.36 {tag configuration options} -body {
    .t tag configure x -underlinefg red
    .t tag cget x -underlinefg
} -cleanup {
    .t tag configure x -underlinefg [lindex [.t tag configure x -underlinefg] 3]
} -result {red}
test textTag-1.37 {configuration options} -body {
    .t tag configure x -underlinefg stupid
} -cleanup {
    .t tag configure x -underlinefg [lindex [.t tag configure x -underlinefg] 3]
} -returnCodes error -result {unknown color name "stupid"}


test textTag-2.1 {TkTextTagCmd - "add" option} -constraints {
test textTag-2.1 {TkTextTagCmd - "add" option} -body {
	haveCourier12 
} -body {
    .t tag
} -returnCodes error -result {wrong # args: should be ".t tag option ?arg ...?"}
test textTag-2.2 {TkTextTagCmd - "add" option} -constraints {
test textTag-2.2 {TkTextTagCmd - "add" option} -body {
	haveCourier12 
} -body {
    .t tag gorp
} -returnCodes error -result {bad tag option "gorp": must be add, bind, cget, configure, delete, lower, names, nextrange, prevrange, raise, ranges, or remove}
test textTag-2.3 {TkTextTagCmd - "add" option} -constraints {
test textTag-2.3 {TkTextTagCmd - "add" option} -body {
	haveCourier12 
} -body {
    .t tag add foo
} -returnCodes error -result {wrong # args: should be ".t tag add tagName index1 ?index2 index1 index2 ...?"}
test textTag-2.4 {TkTextTagCmd - "add" option} -constraints {
test textTag-2.4 {TkTextTagCmd - "add" option} -body {
	haveCourier12 
} -body {
    .t tag add x gorp
} -returnCodes error -result {bad text index "gorp"}
test textTag-2.5 {TkTextTagCmd - "add" option} -constraints {
test textTag-2.5 {TkTextTagCmd - "add" option} -body {
	haveCourier12 
} -body {
    .t tag add x 1.2 gorp
} -returnCodes error -result {bad text index "gorp"}
test textTag-2.6 {TkTextTagCmd - "add" option} -constraints {
test textTag-2.6 {TkTextTagCmd - "add" option} -setup {
	haveCourier12 
} -setup {
    .t tag delete sel
} -body {
    .t tag add sel 3.2 3.4
    .t tag add sel 3.2 3.0
    .t tag ranges sel
} -result {3.2 3.4}
test textTag-2.7 {TkTextTagCmd - "add" option} -constraints {
test textTag-2.7 {TkTextTagCmd - "add" option} -setup {
	haveCourier12 
} -setup {
    .t tag delete x
} -body {
    .t tag add x 1.0 1.end
    .t tag ranges x
} -cleanup {
    .t tag delete x
} -result {1.0 1.6}
test textTag-2.8 {TkTextTagCmd - "add" option} -constraints {
test textTag-2.8 {TkTextTagCmd - "add" option} -setup {
	haveCourier12 
} -setup {
    .t tag remove x 1.0 end
} -body {
    .t tag add x 1.2
    .t tag ranges x
} -cleanup {
    .t tag delete x
} -result {1.2 1.3}
test textTag-2.9 {TkTextTagCmd - "add" option} -constraints {
test textTag-2.9 {TkTextTagCmd - "add" option} -setup {
	haveCourier12 
} -setup {
    destroy .t.e
} -body {
    entry .t.e
    .t.e insert 0 "Text"
    .t.e select from 0
    .t.e select to 4
    .t tag add sel 3.2 3.4
    selection get
} -cleanup {
    destroy .t.e
} -result 34
test textTag-2.10 {TkTextTagCmd - "add" option} -constraints {
test textTag-2.10 {TkTextTagCmd - "add" option} -setup {
	haveCourier12 
} -setup {
    destroy .t.e
} -body {
    entry .t.e
    .t.e insert 0 "Text"
    .t.e select from 0
    .t.e select to 4
    .t configure -exportselection 0
    .t tag add sel 3.2 3.4
    selection get
} -cleanup {
    destroy .t.e
}  -result {Text}
test textTag-2.11 {TkTextTagCmd - "add" option} -constraints {
test textTag-2.11 {TkTextTagCmd - "add" option} -body {
	haveCourier12 
} -body {
    .t tag remove sel 1.0 end
    .t tag add sel 1.1 1.5 2.4 3.1 4.2 4.4
    .t tag ranges sel
} -result {1.1 1.5 2.4 3.1 4.2 4.4}
test textTag-2.12 {TkTextTagCmd - "add" option} -constraints {
test textTag-2.12 {TkTextTagCmd - "add" option} -body {
	haveCourier12 
} -body {
    .t tag remove sel 1.0 end
    .t tag add sel 1.1 1.5 2.4
    .t tag ranges sel
} -cleanup {
    .t tag remove sel 1.0 end
} -result {1.1 1.5 2.4 2.5}
test textTag-2.14 {tag add before -startline - Bug 1615425} haveCourier12 {
test textTag-2.14 {tag add before -startline - Bug 1615425} -body {
    text .tt
    for {set i 1} {$i <10} {incr i} {
        .tt insert end "Line $i\n"
    }
    .tt tag configure mytag -font {Courier 12 bold}
    .tt peer create .ptt
    .ptt configure -startline 3 -endline 7
    # the test succeeds if next line does not crash
    .tt tag add mytag 1.0 1.end
    destroy .ptt .tt
    set res 1
} {1}
} -result 1


test textTag-3.1 {TkTextTagCmd - "bind" option} -constraints {
test textTag-3.1 {TkTextTagCmd - "bind" option} -body {
	haveCourier12 
} -body {
    .t tag bind
} -returnCodes error -result {wrong # args: should be ".t tag bind tagName ?sequence? ?command?"}
test textTag-3.2 {TkTextTagCmd - "bind" option} -constraints {
test textTag-3.2 {TkTextTagCmd - "bind" option} -body {
	haveCourier12 
} -body {
    .t tag bind 1 2 3 4
} -returnCodes error -result {wrong # args: should be ".t tag bind tagName ?sequence? ?command?"}
test textTag-3.3 {TkTextTagCmd - "bind" option} -constraints {
test textTag-3.3 {TkTextTagCmd - "bind" option} -body {
	haveCourier12 
} -body {
    .t tag bind x <Enter> script1
    .t tag bind x <Enter>
} -cleanup {
    .t tag delete x
} -result {script1}
test textTag-3.4 {TkTextTagCmd - "bind" option} -constraints {
test textTag-3.4 {TkTextTagCmd - "bind" option} -body {
	haveCourier12 
} -body {
    .t tag bind x <Gorp> script2
} -returnCodes error -result {bad event type or keysym "Gorp"}
test textTag-3.5 {TkTextTagCmd - "bind" option} -constraints {
test textTag-3.5 {TkTextTagCmd - "bind" option} -body {
	haveCourier12 
} -body {
    .t tag delete x
    .t tag bind x <Enter> script1
    .t tag bind x <FocusIn> script2
} -cleanup {
    .t tag delete x
} -returnCodes error -result {requested illegal events; only key, button, motion, enter, leave, and virtual events may be used}
test textTag-3.6 {TkTextTagCmd - "bind" option} -constraints {
test textTag-3.6 {TkTextTagCmd - "bind" option} -body {
    haveCourier12 
} -body {
    .t tag delete x
    .t tag bind x <Enter> script1
    catch {.t tag bind x <FocusIn> script2} 
    catch {.t tag bind x <FocusIn> script2}
    .t tag bind x
} -cleanup {
    .t tag delete x
} -result {<Enter>}
test textTag-3.7 {TkTextTagCmd - "bind" option} -constraints {
test textTag-3.7 {TkTextTagCmd - "bind" option} -body {
	haveCourier12 
} -body {
    .t tag delete x
    .t tag bind x <Enter> script1
    .t tag bind x <Leave> script2
    .t tag bind x a xyzzy
    list [lsort [.t tag bind x]] [.t tag bind x <Enter>] [.t tag bind x a]
} -cleanup {
    .t tag delete x
} -result {{<Enter> <Leave> a} script1 xyzzy}
test textTag-3.8 {TkTextTagCmd - "bind" option} -constraints {
test textTag-3.8 {TkTextTagCmd - "bind" option} -body {
	haveCourier12 
} -body {
    .t tag delete x
    .t tag bind x <Enter> script1
    .t tag bind x <Enter> +script2
    .t tag bind x <Enter>
} -cleanup {
    .t tag delete x
} -result {script1
script2}
test textTag-3.9 {TkTextTagCmd - "bind" option} -constraints {
test textTag-3.9 {TkTextTagCmd - "bind" option} -body {
	haveCourier12 
} -body {
    .t tag delete x
    .t tag bind x <Enter>
} -cleanup {
    .t tag delete x
} -returnCodes ok -result {}
test textTag-3.10 {TkTextTagCmd - "bind" option} -constraints {
test textTag-3.10 {TkTextTagCmd - "bind" option} -body {
	haveCourier12 
} -body {
    .t tag delete x
    .t tag bind x <
} -cleanup {
    .t tag delete x
} -returnCodes error -result {no event type or button # or keysym}


test textTag-4.1 {TkTextTagCmd - "cget" option} -constraints {
test textTag-4.1 {TkTextTagCmd - "cget" option} -body {
	haveCourier12 
} -body {
    .t tag cget a
} -returnCodes error -result {wrong # args: should be ".t tag cget tagName option"}
test textTag-4.2 {TkTextTagCmd - "cget" option} -constraints {
test textTag-4.2 {TkTextTagCmd - "cget" option} -body {
	haveCourier12 
} -body {
    .t tag cget a b c
} -returnCodes error -result {wrong # args: should be ".t tag cget tagName option"}
test textTag-4.3 {TkTextTagCmd - "cget" option} -constraints {
test textTag-4.3 {TkTextTagCmd - "cget" option} -body {
	haveCourier12 
} -body {
    .t tag delete foo
    .t tag cget foo bar
} -returnCodes error -result {tag "foo" isn't defined in text widget}
test textTag-4.4 {TkTextTagCmd - "cget" option} -constraints {
test textTag-4.4 {TkTextTagCmd - "cget" option} -body {
	haveCourier12 
} -body {
    .t tag cget sel bogus
} -returnCodes error -result {unknown option "bogus"}
test textTag-4.5 {TkTextTagCmd - "cget" option} -constraints {
test textTag-4.5 {TkTextTagCmd - "cget" option} -body {
	haveCourier12 
} -body {
    .t tag delete x
    .t tag configure x -background red
    .t tag cget x -background
} -cleanup {
    .t tag delete x
} -result {red}


test textTag-5.1 {TkTextTagCmd - "configure" option} -constraints {
test textTag-5.1 {TkTextTagCmd - "configure" option} -body {
	haveCourier12 
} -body {
    .t tag configure
} -returnCodes error -result {wrong # args: should be ".t tag configure tagName ?-option? ?value? ?-option value ...?"}
test textTag-5.2 {TkTextTagCmd - "configure" option} -constraints {
} -returnCodes error -result {wrong # args: should be ".t tag configure tagName ?-option value ...?"}
test textTag-5.2 {TkTextTagCmd - "configure" option} -body {
	haveCourier12 
} -body {
    .t tag configure x -foo
} -returnCodes error -result {unknown option "-foo"}
test textTag-5.3 {TkTextTagCmd - "configure" option} -constraints {
test textTag-5.3 {TkTextTagCmd - "configure" option} -body {
	haveCourier12 
} -body {
    .t tag configure x -background red -underline
} -cleanup {
    .t tag delete x
} -returnCodes error -result {value for "-underline" missing}
test textTag-5.4 {TkTextTagCmd - "configure" option} -constraints {
test textTag-5.4 {TkTextTagCmd - "configure" option} -body {
	haveCourier12 
} -body {
    .t tag delete x
    .t tag configure x -underline yes
    .t tag configure x -underline
} -cleanup {
    .t tag delete x
} -result {-underline {} {} {} yes}
test textTag-5.4a {TkTextTagCmd - "configure" option} -body {
    .t tag delete x
    .t tag configure x -underlinefg lightgreen
    .t tag configure x -underlinefg
} -cleanup {
    .t tag delete x
} -result {-underlinefg {} {} {} lightgreen}
test textTag-5.5 {TkTextTagCmd - "configure" option} -constraints {
test textTag-5.5 {TkTextTagCmd - "configure" option} -body {
	haveCourier12 
} -body {
    .t tag delete x
    .t tag configure x -overstrike on
    .t tag cget x -overstrike
} -cleanup {
    .t tag delete x
} -result {on}
test textTag-5.5a {TkTextTagCmd - "configure" option} -body {
    .t tag delete x
    .t tag configure x -overstrikefg lightgreen
    .t tag configure x -overstrikefg
} -cleanup {
    .t tag delete x
} -result {-overstrikefg {} {} {} lightgreen}
test textTag-5.6 {TkTextTagCmd - "configure" option} -constraints {
test textTag-5.6 {TkTextTagCmd - "configure" option} -body {
	haveCourier12 
} -body {
    .t tag configure x -overstrike foo
} -cleanup {
    .t tag delete x
} -returnCodes error -result {expected boolean value but got "foo"}
test textTag-5.7 {TkTextTagCmd - "configure" option} -constraints {
test textTag-5.7 {TkTextTagCmd - "configure" option} -body {
	haveCourier12 
} -body {
    .t tag delete x
    .t tag configure x -underline stupid
} -cleanup {
    .t tag delete x
} -returnCodes error -result {expected boolean value but got "stupid"}
test textTag-5.8 {TkTextTagCmd - "configure" option} -constraints {
test textTag-5.8 {TkTextTagCmd - "configure" option} -body {
	haveCourier12 
} -body {
    .t tag delete x
    .t tag configure x -justify left
    .t tag configure x -justify
} -cleanup {
    .t tag delete x
} -result {-justify {} {} {} left}
test textTag-5.9 {TkTextTagCmd - "configure" option} -constraints {
test textTag-5.9 {TkTextTagCmd - "configure" option} -body {
	haveCourier12 
} -body {
    .t tag delete x
    .t tag configure x -justify bogus
} -cleanup {
    .t tag delete x
} -returnCodes error -result {bad justification "bogus": must be left, right, or center}
test textTag-5.10 {TkTextTagCmd - "configure" option} -constraints {
test textTag-5.10 {TkTextTagCmd - "configure" option} -body {
	haveCourier12 
} -body {
    .t tag delete x
    .t tag configure x -justify fill
} -cleanup {
    .t tag delete x
} -returnCodes error -result {bad justification "fill": must be left, right, or center}
test textTag-5.11 {TkTextTagCmd - "configure" option} -constraints {
test textTag-5.11 {TkTextTagCmd - "configure" option} -body {
    haveCourier12 
} -body {
    .t tag delete x
    .t tag configure x -offset 2
    .t tag configure x -offset
} -cleanup {
    .t tag delete x
} -result {-offset {} {} {} 2}
test textTag-5.12 {TkTextTagCmd - "configure" option} -constraints {
test textTag-5.12 {TkTextTagCmd - "configure" option} -body {
    haveCourier12 
} -body {
    .t tag delete x
    .t tag configure x -offset 1.0q
} -cleanup {
    .t tag delete x
} -returnCodes error -result {bad screen distance "1.0q"}
test textTag-5.13 {TkTextTagCmd - "configure" option} -body {
    .t tag delete x
    .t tag configure x -lmargin1 2 -lmargin2 4 -rmargin 5 \
        -lmargincolor darkblue -rmargincolor lightgreen
    list [.t tag configure x -lmargin1] [.t tag configure x -lmargin2] \
        [.t tag configure x -rmargin] [.t tag configure x -lmargincolor] \
        [.t tag configure x -rmargincolor]
} -cleanup {
    .t tag delete x
} -result [list {-lmargin1 {} {} {} 2} {-lmargin2 {} {} {} 4} \
                {-rmargin {} {} {} 5} \
                {-lmargincolor {} {} {} darkblue} {-rmargincolor {} {} {} lightgreen} \
          ]
test textTag-5.14 {TkTextTagCmd - "configure" option} -constraints {
test textTag-5.14 {TkTextTagCmd - "configure" option} -body {
    haveCourier12 
} -body {
    .t tag delete x
    .t tag configure x -lmargin1 2.0x
} -cleanup {
    .t tag delete x
} -returnCodes error -result {bad screen distance "2.0x"}
test textTag-5.15 {TkTextTagCmd - "configure" option} -constraints {
test textTag-5.15 {TkTextTagCmd - "configure" option} -body {
    haveCourier12 
} -body {
    .t tag delete x
    .t tag configure x -lmargin2 gorp
} -cleanup {
    .t tag delete x
} -returnCodes error -result {bad screen distance "gorp"}
test textTag-5.15a {TkTextTagCmd - "configure" option} -body {
    .t tag delete x
    .t tag configure x -lmargincolor rainbow
} -cleanup {
    .t tag delete x
} -returnCodes error -result {unknown color name "rainbow"}
test textTag-5.16 {TkTextTagCmd - "configure" option} -constraints {
test textTag-5.16 {TkTextTagCmd - "configure" option} -body {
    haveCourier12 
} -body {
    .t tag delete x
    .t tag configure x -rmargin 140.1.1
} -cleanup {
    .t tag delete x
} -returnCodes error -result {bad screen distance "140.1.1"}
test textTag-5.16a {TkTextTagCmd - "configure" option} -body {
    .t tag delete x
    .t tag configure x -rmargincolor rainbow
} -cleanup {
    .t tag delete x
} -returnCodes error -result {unknown color name "rainbow"}
.t tag delete x
test textTag-5.17 {TkTextTagCmd - "configure" option} -constraints {
test textTag-5.17 {TkTextTagCmd - "configure" option} -body {
    haveCourier12 
} -body {
    .t tag delete x
    .t tag configure x -spacing1 2 -spacing2 4 -spacing3 6
    list [.t tag configure x -spacing1] [.t tag configure x -spacing2] \
        [.t tag configure x -spacing3]
} -cleanup {
    .t tag delete x
} -result {{-spacing1 {} {} {} 2} {-spacing2 {} {} {} 4} {-spacing3 {} {} {} 6}}
test textTag-5.18 {TkTextTagCmd - "configure" option} -constraints {
test textTag-5.18 {TkTextTagCmd - "configure" option} -body {
    haveCourier12 
} -body {
    .t tag delete x
    .t tag configure x -spacing1 2.0x
} -cleanup {
    .t tag delete x
} -returnCodes error -result {bad screen distance "2.0x"}
test textTag-5.19 {TkTextTagCmd - "configure" option} -constraints {
test textTag-5.19 {TkTextTagCmd - "configure" option} -body {
    haveCourier12 
} -body {
    .t tag delete x
    .t tag configure x -spacing1 lousy
} -cleanup {
    .t tag delete x
} -returnCodes error -result {bad screen distance "lousy"}
test textTag-5.20 {TkTextTagCmd - "configure" option} -constraints {
test textTag-5.20 {TkTextTagCmd - "configure" option} -body {
    haveCourier12 
} -body {
    .t tag delete x
    .t tag configure x -spacing1 4.2.3
} -cleanup {
    .t tag delete x
} -returnCodes error -result {bad screen distance "4.2.3"}
test textTag-5.21 {TkTextTagCmd - "configure" option} -constraints {
test textTag-5.21 {TkTextTagCmd - "configure" option} -body {
    haveCourier12 
} -body {
    .t configure -selectborderwidth 2 -selectforeground blue \
        -selectbackground black
    .t tag configure sel -borderwidth 4 -foreground green -background yellow
    set x {}
    foreach i {-selectborderwidth -selectforeground -selectbackground} {
        lappend x [lindex [.t configure $i] 4]
    }
    return $x
} -result {4 green yellow}
test textTag-5.22 {TkTextTagCmd - "configure" option} -constraints {
test textTag-5.22 {TkTextTagCmd - "configure" option} -body {
    haveCourier12 
} -body {
    .t configure -selectborderwidth 20
    .t tag configure sel -borderwidth {}
    .t cget -selectborderwidth
} -result {}
test textTag-5.23 {TkTextTagCmd - "configure" option} -body {
    set x {}
    # when [.t tag cget sel -selectbackground] == "", mirroring happens between
851
852
853
854
855
856
857
858

859
860
861
862
863

864
865
866
867
868

869
870
871
872
873
874
875
876
877
878
879
880
881

882
883
884
885
886
887
888
889
890
891
892

893
894
895
896
897
898
899
900
901
902
903
904

905
906
907
908
909

910
911
912
913
914

915
916
917
918
919

920
921
922
923
924
925
926
927
928
929
930
931
932
933

934
935
936
937
938
939
940
941
942
943
944
945
946
947

948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963

964
965
966
967
968
969
970

971
972
973
974
975
976
977
978
979
980
981
982
983

984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000

1001
1002
1003
1004
1005

1006
1007
1008
1009
1010

1011
1012
1013
1014
1015

1016
1017
1018
1019
1020
1021
1022
1023
1024
1025

1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037

1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049

1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061

1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073

1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085

1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097

1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109

1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121

1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133

1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147

1148
1149
1150
1151
1152

1153
1154
1155
1156
1157

1158
1159
1160
1161
1162
1163
1164
1165
1166

1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178

1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190

1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202

1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214

1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226

1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238

1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250

1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262

1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274

1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286

1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300

1301
1302
1303
1304
1305

1306
1307
1308
1309
1310

1311
1312
1313
1314
1315

1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329

1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343

1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359

1360
1361
1362
1363
1364

1365
1366
1367
1368
1369
1370

1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382

1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395

1396
1397
1398
1399
1400

1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411

1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429

1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440

1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453

1454
1455
1456
1457
1458
1459
1460
1461
1462
1463

1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478


1479
1480
1481
1482
1483
1484
1485
1486
1487









1488
1489

1490
1491
1492
1493
1494
1495
1496
699
700
701
702
703
704
705

706


707
708

709


710
711

712


713
714
715
716
717
718
719
720
721
722

723


724
725
726
727
728
729
730
731

732


733
734
735
736
737
738
739
740
741

742


743
744

745


746
747

748


749
750

751


752
753
754
755
756
757
758
759
760
761
762

763


764
765
766
767
768
769
770
771
772
773
774

775


776
777
778
779
780
781
782
783
784
785
786
787
788

789


790
791
792
793

794


795
796
797
798
799
800
801
802
803
804

805


806
807
808
809
810
811
812
813
814
815
816
817
818
819

820


821
822

823


824
825

826


827
828

829


830
831
832
833
834
835
836

837


838
839
840
841
842
843
844
845
846

847


848
849
850
851
852
853
854
855
856

857


858
859
860
861
862
863
864
865
866

867


868
869
870
871
872
873
874
875
876

877


878
879
880
881
882
883
884
885
886

887


888
889
890
891
892
893
894
895
896

897


898
899
900
901
902
903
904
905
906

907


908
909
910
911
912
913
914
915
916

917


918
919
920
921
922
923
924
925
926

927


928
929
930
931
932
933
934
935
936
937
938

939


940
941

942


943
944

945


946
947
948
949
950
951

952


953
954
955
956
957
958
959
960
961

962


963
964
965
966
967
968
969
970
971

972


973
974
975
976
977
978
979
980
981

982


983
984
985
986
987
988
989
990
991

992


993
994
995
996
997
998
999
1000
1001

1002


1003
1004
1005
1006
1007
1008
1009
1010
1011

1012


1013
1014
1015
1016
1017
1018
1019
1020
1021

1022


1023
1024
1025
1026
1027
1028
1029
1030
1031

1032


1033
1034
1035
1036
1037
1038
1039
1040
1041

1042


1043
1044
1045
1046
1047
1048
1049
1050
1051

1052


1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063

1064


1065
1066

1067


1068
1069

1070


1071
1072

1073


1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084

1085


1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096

1097


1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110

1111


1112
1113

1114


1115
1116
1117

1118


1119
1120
1121
1122
1123
1124
1125
1126
1127

1128


1129
1130
1131
1132
1133
1134
1135
1136
1137
1138

1139


1140
1141

1142


1143
1144
1145
1146
1147
1148
1149
1150

1151


1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166

1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177

1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190

1191
1192
1193
1194
1195
1196
1197
1198
1199
1200

1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215

1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236

1237
1238
1239
1240
1241
1242
1243
1244







-
+
-
-


-
+
-
-


-
+
-
-










-
+
-
-








-
+
-
-









-
+
-
-


-
+
-
-


-
+
-
-


-
+
-
-











-
+
-
-











-
+
-
-













-
+
-
-




-
+
-
-










-
+
-
-














-
+
-
-


-
+
-
-


-
+
-
-


-
+
-
-







-
+
-
-









-
+
-
-









-
+
-
-









-
+
-
-









-
+
-
-









-
+
-
-









-
+
-
-









-
+
-
-









-
+
-
-









-
+
-
-











-
+
-
-


-
+
-
-


-
+
-
-






-
+
-
-









-
+
-
-









-
+
-
-









-
+
-
-









-
+
-
-









-
+
-
-









-
+
-
-









-
+
-
-









-
+
-
-









-
+
-
-









-
+
-
-











-
+
-
-


-
+
-
-


-
+
-
-


-
+
-
-











-
+
-
-











-
+
-
-













-
+
-
-


-
+
-
-



-
+
-
-









-
+
-
-










-
+
-
-


-
+
-
-








-
+
-
-















-
+










-
+












-
+









-
+














-
+
+









+
+
+
+
+
+
+
+
+

-
+







    lappend x [.t tag cget sel -selectforeground]
    .t configure -selectforeground black
    .t tag configure sel -selectforeground white
    lappend x [.t cget -selectforeground]
    return $x
} -result {yellow blue red white}

test textTag-6.1 {TkTextTagCmd - "delete" option} -constraints {
test textTag-6.1 {TkTextTagCmd - "delete" option} -body {
    haveCourier12 
} -body {
    .t tag delete
} -returnCodes error -result {wrong # args: should be ".t tag delete tagName ?tagName ...?"}
test textTag-6.2 {TkTextTagCmd - "delete" option} -constraints {
test textTag-6.2 {TkTextTagCmd - "delete" option} -body {
    haveCourier12 
} -body {
    .t tag delete zork
} -returnCodes ok -result {}
test textTag-6.3 {TkTextTagCmd - "delete" option} -constraints {
test textTag-6.3 {TkTextTagCmd - "delete" option} -setup {
    haveCourier12 
} -setup {
    .t tag delete {*}[.t tag names]
} -body {
    .t tag config x -background black
    .t tag config y -foreground white
    .t tag config z -background black
    .t tag delete y z
    lsort [.t tag names]
} -cleanup {
    .t tag delete x
} -result {sel x}
test textTag-6.4 {TkTextTagCmd - "delete" option} -constraints {
test textTag-6.4 {TkTextTagCmd - "delete" option} -setup {
    haveCourier12 
} -setup {
    .t tag delete {*}[.t tag names]
} -body {
    .t tag config x -background black
    .t tag config y -foreground white
    .t tag config z -background black
    eval .t tag delete [.t tag names]
    .t tag names
} -result {sel}
test textTag-6.5 {TkTextTagCmd - "delete" option} -constraints {
test textTag-6.5 {TkTextTagCmd - "delete" option} -body {
    haveCourier12 
} -body {
    .t tag bind x <Enter> foo
    .t tag delete x
    .t tag configure x -background black
    .t tag bind x
} -cleanup {
    .t tag delete x
} -result {}


test textTag-7.1 {TkTextTagCmd - "lower" option} -constraints {
test textTag-7.1 {TkTextTagCmd - "lower" option} -body {
    haveCourier12 
} -body {
    .t tag lower
} -returnCodes error -result {wrong # args: should be ".t tag lower tagName ?belowThis?"}
test textTag-7.2 {TkTextTagCmd - "lower" option} -constraints {
test textTag-7.2 {TkTextTagCmd - "lower" option} -body {
    haveCourier12 
} -body {
    .t tag lower foo
} -returnCodes error -result {tag "foo" isn't defined in text widget}
test textTag-7.3 {TkTextTagCmd - "lower" option} -constraints {
test textTag-7.3 {TkTextTagCmd - "lower" option} -body {
    haveCourier12 
} -body {
    .t tag lower sel bar
} -returnCodes error -result {tag "bar" isn't defined in text widget}
test textTag-7.4 {TkTextTagCmd - "lower" option} -constraints {
test textTag-7.4 {TkTextTagCmd - "lower" option} -setup {
    haveCourier12 
} -setup {
    .t tag delete {*}[.t tag names]
    .t tag remove sel 1.0 end
    foreach i {a b c d} {
        .t tag configure $i -background black
    }
} -body {
    .t tag lower c
    .t tag names
} -cleanup {
    .t tag delete {*}[.t tag names]
} -result {c sel a b d}
test textTag-7.5 {TkTextTagCmd - "lower" option} -constraints {
test textTag-7.5 {TkTextTagCmd - "lower" option} -setup {
    haveCourier12 
} -setup {
    .t tag delete {*}[.t tag names]
    .t tag remove sel 1.0 end
    foreach i {a b c d} {
        .t tag configure $i -background black
    }
} -body {
    .t tag lower d b
    .t tag names
} -cleanup {
    .t tag delete {*}[.t tag names]
} -result {sel a d b c}
test textTag-7.6 {TkTextTagCmd - "lower" option} -constraints {
test textTag-7.6 {TkTextTagCmd - "lower" option} -setup {
    haveCourier12 
} -setup {
    .t tag delete {*}[.t tag names]
    .t tag remove sel 1.0 end
    foreach i {a b c d} {
        .t tag configure $i -background black
    }
} -body {
    .t tag lower a c
    .t tag names
} -cleanup {
    .t tag delete {*}[.t tag names]
} -result {sel b a c d}


test textTag-8.1 {TkTextTagCmd - "names" option} -constraints {
test textTag-8.1 {TkTextTagCmd - "names" option} -body {
    haveCourier12 
} -body {
    .t tag names a b
} -cleanup {
    .t tag delete {*}[.t tag names]
} -returnCodes error -result {wrong # args: should be ".t tag names ?index?"}
test textTag-8.2 {TkTextTagCmd - "names" option} -constraints {
test textTag-8.2 {TkTextTagCmd - "names" option} -setup {
    haveCourier12 
} -setup {
    .t tag delete {*}[.t tag names]
    .t tag remove sel 1.0 end
    foreach i {a b c d} {
        .t tag configure $i -background black
    }
} -body {
    .t tag names
} -cleanup {
    .t tag delete {*}[.t tag names]
} -result {sel a b c d}
test textTag-8.3 {TkTextTagCmd - "names" option} -constraints {
test textTag-8.3 {TkTextTagCmd - "names" option} -setup {
    haveCourier12 
} -setup {
    .t tag delete {*}[.t tag names]
    .t tag remove sel 1.0 end
    foreach i {a b c d} {
        .t tag configure $i -background black
    }
} -body {
    .t tag add "a b" 2.1 2.6
    .t tag add c 2.4 2.7
    .t tag names 2.5
} -cleanup {
    .t tag delete {*}[.t tag names]
} -result {c {a b}}


test textTag-9.1 {TkTextTagCmd - "nextrange" option} -constraints {
test textTag-9.1 {TkTextTagCmd - "nextrange" option} -body {
    haveCourier12 
} -body {
    .t tag nextrange x
} -returnCodes error -result {wrong # args: should be ".t tag nextrange tagName index1 ?index2?"}
test textTag-9.2 {TkTextTagCmd - "nextrange" option} -constraints {
test textTag-9.2 {TkTextTagCmd - "nextrange" option} -body {
    haveCourier12 
} -body {
    .t tag nextrange x 1 2 3
} -returnCodes error -result {wrong # args: should be ".t tag nextrange tagName index1 ?index2?"}
test textTag-9.3 {TkTextTagCmd - "nextrange" option} -constraints {
test textTag-9.3 {TkTextTagCmd - "nextrange" option} -body {
    haveCourier12 
} -body {
    .t tag nextrange foo 1.0
} -returnCodes ok -result {}
test textTag-9.4 {TkTextTagCmd - "nextrange" option} -constraints {
test textTag-9.4 {TkTextTagCmd - "nextrange" option} -setup {
    haveCourier12 
} -setup {
    .t tag delete x
} -body {
    .t tag add x 2.3 2.5
    .t tag nextrange x foo
} -cleanup {
    .t tag delete x
} -returnCodes error -result {bad text index "foo"}
test textTag-9.5 {TkTextTagCmd - "nextrange" option} -constraints {
test textTag-9.5 {TkTextTagCmd - "nextrange" option} -setup {
    haveCourier12 
} -setup {
    .t tag delete x
} -body {
    .t tag add x 2.3 2.5
    .t tag add x 2.9 3.1
    .t tag add x 7.2
    .t tag nextrange x 1.0 bar
} -cleanup {
    .t tag delete x
} -returnCodes error -result {bad text index "bar"}
test textTag-9.6 {TkTextTagCmd - "nextrange" option} -constraints {
test textTag-9.6 {TkTextTagCmd - "nextrange" option} -setup {
    haveCourier12 
} -setup {
    .t tag delete x
} -body {
    .t tag add x 2.3 2.5
    .t tag add x 2.9 3.1
    .t tag add x 7.2
    .t tag nextrange x 1.0
} -cleanup {
    .t tag delete x
} -result {2.3 2.5}
test textTag-9.7 {TkTextTagCmd - "nextrange" option} -constraints {
test textTag-9.7 {TkTextTagCmd - "nextrange" option} -setup {
    haveCourier12 
} -setup {
    .t tag delete x
} -body {
    .t tag add x 2.3 2.5
    .t tag add x 2.9 3.1
    .t tag add x 7.2
    .t tag nextrange x 2.2
} -cleanup {
    .t tag delete x
} -result {2.3 2.5}
test textTag-9.8 {TkTextTagCmd - "nextrange" option} -constraints {
test textTag-9.8 {TkTextTagCmd - "nextrange" option} -setup {
    haveCourier12 
} -setup {
    .t tag delete x
} -body {
    .t tag add x 2.3 2.5
    .t tag add x 2.9 3.1
    .t tag add x 7.2
    .t tag nextrange x 2.3
} -cleanup {
    .t tag delete x
} -result {2.3 2.5}
test textTag-9.9 {TkTextTagCmd - "nextrange" option} -constraints {
test textTag-9.9 {TkTextTagCmd - "nextrange" option} -setup {
    haveCourier12 
} -setup {
    .t tag delete x
} -body {
    .t tag add x 2.3 2.5
    .t tag add x 2.9 3.1
    .t tag add x 7.2
    .t tag nextrange x 2.4
} -cleanup {
    .t tag delete x
} -result {2.9 3.1}
test textTag-9.10 {TkTextTagCmd - "nextrange" option} -constraints {
test textTag-9.10 {TkTextTagCmd - "nextrange" option} -setup {
    haveCourier12 
} -setup {
    .t tag delete x
} -body {
    .t tag add x 2.3 2.5
    .t tag add x 2.9 3.1
    .t tag add x 7.2
    .t tag nextrange x 2.4 2.9
} -cleanup {
    .t tag delete x
} -result {}
test textTag-9.11 {TkTextTagCmd - "nextrange" option} -constraints {
test textTag-9.11 {TkTextTagCmd - "nextrange" option} -setup {
    haveCourier12 
} -setup {
    .t tag delete x
} -body {
    .t tag add x 2.3 2.5
    .t tag add x 2.9 3.1
    .t tag add x 7.2
    .t tag nextrange x 2.4 2.10
} -cleanup {
    .t tag delete x
} -result {2.9 3.1}
test textTag-9.12 {TkTextTagCmd - "nextrange" option} -constraints {
test textTag-9.12 {TkTextTagCmd - "nextrange" option} -setup {
    haveCourier12 
} -setup {
    .t tag delete x
} -body {
    .t tag add x 2.3 2.5
    .t tag add x 2.9 3.1
    .t tag add x 7.2
    .t tag nextrange x 2.4 2.11
} -cleanup {
    .t tag delete x
} -result {2.9 3.1}
test textTag-9.13 {TkTextTagCmd - "nextrange" option} -constraints {
test textTag-9.13 {TkTextTagCmd - "nextrange" option} -setup {
    haveCourier12 
} -setup {
    .t tag delete x
} -body {
    .t tag add x 2.3 2.5
    .t tag add x 2.9 3.1
    .t tag add x 7.2
    .t tag nextrange x 7.0
} -cleanup {
    .t tag delete x
} -result {7.2 7.3}
test textTag-9.14 {TkTextTagCmd - "nextrange" option} -constraints {
test textTag-9.14 {TkTextTagCmd - "nextrange" option} -setup {
    haveCourier12 
} -setup {
    .t tag delete x
} -body {
    .t tag add x 2.3 2.5
    .t tag add x 2.9 3.1
    .t tag add x 7.2
    .t tag nextrange x 7.3
} -cleanup {
    .t tag delete x
} -result {}


test textTag-10.1 {TkTextTagCmd - "prevrange" option} -constraints {
test textTag-10.1 {TkTextTagCmd - "prevrange" option} -body {
    haveCourier12 
} -body {
    .t tag prevrange x
} -returnCodes error -result {wrong # args: should be ".t tag prevrange tagName index1 ?index2?"}
test textTag-10.2 {TkTextTagCmd - "prevrange" option} -constraints {
test textTag-10.2 {TkTextTagCmd - "prevrange" option} -body {
    haveCourier12 
} -body {
    .t tag prevrange x 1 2 3
} -returnCodes error -result {wrong # args: should be ".t tag prevrange tagName index1 ?index2?"}
test textTag-10.3 {TkTextTagCmd - "prevrange" option} -constraints {
test textTag-10.3 {TkTextTagCmd - "prevrange" option} -setup {
    haveCourier12 
} -setup {
    .t tag delete x
} -body {
    .t tag prevrange foo end
} -cleanup {
    .t tag delete x
} -returnCodes ok -result {}
test textTag-10.4 {TkTextTagCmd - "prevrange" option} -constraints {
test textTag-10.4 {TkTextTagCmd - "prevrange" option} -setup {
    haveCourier12 
} -setup {
    .t tag delete x
} -body {
    .t tag add x 2.3 2.5
    .t tag add x 2.9 3.1
    .t tag add x 7.2
    .t tag prevrange x foo
} -cleanup {
    .t tag delete x
} -returnCodes error -result {bad text index "foo"}
test textTag-10.5 {TkTextTagCmd - "prevrange" option} -constraints {
test textTag-10.5 {TkTextTagCmd - "prevrange" option} -setup {
    haveCourier12 
} -setup {
    .t tag delete x
} -body {
    .t tag add x 2.3 2.5
    .t tag add x 2.9 3.1
    .t tag add x 7.2
    .t tag prevrange x end bar
} -cleanup {
    .t tag delete x
} -returnCodes error -result {bad text index "bar"}
test textTag-10.6 {TkTextTagCmd - "prevrange" option} -constraints {
test textTag-10.6 {TkTextTagCmd - "prevrange" option} -setup {
    haveCourier12 
} -setup {
    .t tag delete x
} -body {
    .t tag add x 2.3 2.5
    .t tag add x 2.9 3.1
    .t tag add x 7.2
    .t tag prevrange x end
} -cleanup {
    .t tag delete x
} -result {7.2 7.3}
test textTag-10.7 {TkTextTagCmd - "prevrange" option} -constraints {
test textTag-10.7 {TkTextTagCmd - "prevrange" option} -setup {
    haveCourier12 
} -setup {
    .t tag delete x
} -body {
    .t tag add x 2.3 2.5
    .t tag add x 2.9 3.1
    .t tag add x 7.2
    .t tag prevrange x 2.4
} -cleanup {
    .t tag delete x
} -result {2.3 2.5}
test textTag-10.8 {TkTextTagCmd - "prevrange" option} -constraints {
test textTag-10.8 {TkTextTagCmd - "prevrange" option} -setup {
    haveCourier12 
} -setup {
    .t tag delete x
} -body {
    .t tag add x 2.3 2.5
    .t tag add x 2.9 3.1
    .t tag add x 7.2
    .t tag prevrange x 2.5
} -cleanup {
    .t tag delete x
} -result {2.3 2.5}
test textTag-10.9 {TkTextTagCmd - "prevrange" option} -constraints {
test textTag-10.9 {TkTextTagCmd - "prevrange" option} -setup {
    haveCourier12 
} -setup {
    .t tag delete x
} -body {
    .t tag add x 2.3 2.5
    .t tag add x 2.9 3.1
    .t tag add x 7.2
    .t tag prevrange x 2.9
} -cleanup {
    .t tag delete x
} -result {2.3 2.5}
test textTag-10.10 {TkTextTagCmd - "prevrange" option} -constraints {
test textTag-10.10 {TkTextTagCmd - "prevrange" option} -setup {
    haveCourier12 
} -setup {
    .t tag delete x
} -body {
    .t tag add x 2.3 2.5
    .t tag add x 2.9 3.1
    .t tag add x 7.2
    .t tag prevrange x 2.9 2.6
} -cleanup {
    .t tag delete x
} -result {}
test textTag-10.11 {TkTextTagCmd - "prevrange" option} -constraints {
test textTag-10.11 {TkTextTagCmd - "prevrange" option} -setup {
    haveCourier12 
} -setup {
    .t tag delete x
} -body {
    .t tag add x 2.3 2.5
    .t tag add x 2.9 3.1
    .t tag add x 7.2
    .t tag prevrange x 2.9 2.5
} -cleanup {
    .t tag delete x
} -result {}
test textTag-10.12 {TkTextTagCmd - "prevrange" option} -constraints {
test textTag-10.12 {TkTextTagCmd - "prevrange" option} -setup {
    haveCourier12 
} -setup {
    .t tag delete x
} -body {
    .t tag add x 2.3 2.5
    .t tag add x 2.9 3.1
    .t tag add x 7.2
    .t tag prevrange x 2.9 2.3
} -cleanup {
    .t tag delete x
} -result {2.3 2.5}
test textTag-10.13 {TkTextTagCmd - "prevrange" option} -constraints {
test textTag-10.13 {TkTextTagCmd - "prevrange" option} -setup {
    haveCourier12 
} -setup {
    .t tag delete x
} -body {
    .t tag add x 2.3 2.5
    .t tag add x 2.9 3.1
    .t tag add x 7.2
    .t tag prevrange x 7.0
} -cleanup {
    .t tag delete x
} -result {2.9 3.1}
test textTag-10.14 {TkTextTagCmd - "prevrange" option} -constraints {
test textTag-10.14 {TkTextTagCmd - "prevrange" option} -setup {
    haveCourier12 
} -setup {
    .t tag delete x
} -body {
    .t tag add x 2.3 2.5
    .t tag add x 2.9 3.1
    .t tag add x 7.2
    .t tag prevrange x 2.3
} -cleanup {
    .t tag delete x
} -result {}


test textTag-11.1 {TkTextTagCmd - "raise" option} -constraints {
test textTag-11.1 {TkTextTagCmd - "raise" option} -body {
    haveCourier12 
} -body {
    .t tag raise
} -returnCodes error -result {wrong # args: should be ".t tag raise tagName ?aboveThis?"}
test textTag-11.2 {TkTextTagCmd - "raise" option} -constraints {
test textTag-11.2 {TkTextTagCmd - "raise" option} -body {
    haveCourier12 
} -body {
    .t tag raise foo
} -returnCodes error -result {tag "foo" isn't defined in text widget}
test textTag-11.3 {TkTextTagCmd - "raise" option} -constraints {
test textTag-11.3 {TkTextTagCmd - "raise" option} -body {
    haveCourier12 
} -body {
    .t tag raise sel bar
} -returnCodes error -result {tag "bar" isn't defined in text widget}
test textTag-11.4 {TkTextTagCmd - "raise" option} -constraints {
test textTag-11.4 {TkTextTagCmd - "raise" option} -setup {
    haveCourier12 
} -setup {
    .t tag delete {*}[.t tag names]
    .t tag remove sel 1.0 end
    foreach i {a b c d} {
        .t tag configure $i -background black
    }
} -body {
    .t tag raise c
    .t tag names
} -cleanup {
    .t tag delete {*}[.t tag names]
} -result {sel a b d c}
test textTag-11.5 {TkTextTagCmd - "raise" option} -constraints {
test textTag-11.5 {TkTextTagCmd - "raise" option} -setup {
    haveCourier12 
} -setup {
    .t tag delete {*}[.t tag names]
    .t tag remove sel 1.0 end
    foreach i {a b c d} {
        .t tag configure $i -background black
    }
} -body {
    .t tag raise d b
    .t tag names
} -cleanup {
    .t tag delete {*}[.t tag names]
} -result {sel a b d c}
test textTag-11.6 {TkTextTagCmd - "raise" option} -constraints {
test textTag-11.6 {TkTextTagCmd - "raise" option} -setup {
    haveCourier12 
} -setup {
    .t tag delete {*}[.t tag names]
    .t tag remove sel 1.0 end
    foreach i {a b c d} {
        .t tag configure $i -background black
    }
} -body {
    .t tag raise a c
    .t tag names
} -cleanup {
    .t tag delete {*}[.t tag names]
} -result {sel b c a d}


test textTag-12.1 {TkTextTagCmd - "ranges" option} -constraints {
test textTag-12.1 {TkTextTagCmd - "ranges" option} -body {
    haveCourier12 
} -body {
    .t tag ranges
} -returnCodes error -result {wrong # args: should be ".t tag ranges tagName"}
test textTag-12.2 {TkTextTagCmd - "ranges" option} -constraints {
test textTag-12.2 {TkTextTagCmd - "ranges" option} -body {
    haveCourier12 
} -body {
    .t tag delete x
    .t tag ranges x
} -result {}
test textTag-12.3 {TkTextTagCmd - "ranges" option} -constraints {
test textTag-12.3 {TkTextTagCmd - "ranges" option} -setup {
    haveCourier12 
} -setup {
    .t tag delete x
} -body {
    .t tag add x 2.2
    .t tag add x 2.7 4.15
    .t tag add x 5.2 5.5
    .t tag ranges x
} -cleanup {
    .t tag delete x
} -result {2.2 2.3 2.7 4.6 5.2 5.5}
test textTag-12.4 {TkTextTagCmd - "ranges" option} -constraints {
test textTag-12.4 {TkTextTagCmd - "ranges" option} -setup {
    haveCourier12 
} -setup {
    .t tag delete x
} -body {
    .t tag add x 1.0 3.0
    .t tag add x 4.0 end
    .t tag ranges x
} -cleanup {
    .t tag delete x
} -result {1.0 3.0 4.0 8.0}


test textTag-13.1 {TkTextTagCmd - "remove" option} -constraints {
test textTag-13.1 {TkTextTagCmd - "remove" option} -body {
    haveCourier12 
} -body {
    .t tag remove
} -returnCodes error -result {wrong # args: should be ".t tag remove tagName index1 ?index2 index1 index2 ...?"}
test textTag-13.2 {TkTextTagCmd - "remove" option} -constraints {
test textTag-13.2 {TkTextTagCmd - "remove" option} -setup {
    haveCourier12 
} -setup {
    .t tag delete x
} -body {
    .t tag add x 2.2 2.11
    .t tag remove x 2.3 2.7
    .t tag ranges x
} -cleanup {
    .t tag delete x
} -result {2.2 2.3 2.7 2.11}
test textTag-13.3 {TkTextTagCmd - "remove" option} -constraints {
test textTag-13.3 {TkTextTagCmd - "remove" option} -setup {
    haveCourier12 
} -setup {
    destroy .t.e
} -body {
    entry .t.e
    .t.e insert 0 "Text"
    .t configure -exportselection 1
    .t tag remove sel 1.0 end
    .t tag add sel 2.4 3.3
    .t.e select to 4
    .t tag remove sel 2.7 3.1
    selection get
} -cleanup {
    destroy .t.e
} -result {Text}


test textTag-14.1 {SortTags} -constraints haveCourier12 -setup {
test textTag-14.1 {SortTags} -setup {
    .t tag delete a b c d
} -body {
    foreach i {a b c d} {
        .t tag add $i 2.0 2.2
    }
    .t tag names 2.1
} -cleanup {
    .t tag delete a b c d
} -result {a b c d}
.t tag delete a b c d
test textTag-14.2 {SortTags} -constraints haveCourier12 -setup {
test textTag-14.2 {SortTags} -setup {
    .t tag delete a b c d
} -body {
    foreach i {a b c d} {
        .t tag configure $i -background black
    }
    foreach i {d c b a} {
        .t tag add $i 2.0 2.2
    }
    .t tag names 2.1
} -cleanup {
    .t tag delete a b c d
} -result {a b c d}
test textTag-14.3 {SortTags} -constraints haveCourier12 -setup {
test textTag-14.3 {SortTags} -setup {
    .t tag delete {*}[.t tag names]
} -body {
    for {set i 0} {$i < 30} {incr i} {
        .t tag add x$i 2.0 2.2
    }
    .t tag names 2.1
} -cleanup {
    .t tag delete {*}[.t tag names]
} -result {x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11 x12 x13 x14 x15 x16 x17 x18 x19 x20 x21 x22 x23 x24 x25 x26 x27 x28 x29}
test textTag-14.4 {SortTags} -constraints haveCourier12 -setup {
test textTag-14.4 {SortTags} -setup {
    .t tag delete {*}[.t tag names]
} -body {
    for {set i 0} {$i < 30} {incr i} {
        .t tag configure x$i -background black
    }
    for {set i 29} {$i >= 0} {incr i -1} {
        .t tag add x$i 2.0 2.2
    }
    .t tag names 2.1
} -cleanup {
    .t tag delete {*}[.t tag names]
} -result {x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11 x12 x13 x14 x15 x16 x17 x18 x19 x20 x21 x22 x23 x24 x25 x26 x27 x28 x29}



set curFont [.t cget -font]
set curWrap [.t cget -wrap]
set c [.t bbox 2.1]
set x1 [expr {[lindex $c 0] + [lindex $c 2]/2}]
set y1 [expr {[lindex $c 1] + [lindex $c 3]/2}]
set c [.t bbox 3.2]
set x2 [expr {[lindex $c 0] + [lindex $c 2]/2}]
set y2 [expr {[lindex $c 1] + [lindex $c 3]/2}]
set c [.t bbox 4.3]
set x3 [expr {[lindex $c 0] + [lindex $c 2]/2}]
set y3 [expr {[lindex $c 1] + [lindex $c 3]/2}]
.t configure -font $textWidgetFont -wrap none
update
set c [.t bbox 2.1]
set x4 [expr [lindex $c 0] + [lindex $c 2]/2]
set y4 [expr [lindex $c 1] + [lindex $c 3]/2]
set c [.t bbox 3.2]
set x5 [expr [lindex $c 0] + [lindex $c 2]/2]
set y5 [expr [lindex $c 1] + [lindex $c 3]/2]
.t configure -font $curFont -wrap $curWrap

test textTag-15.1 {TkTextBindProc} -constraints haveCourier12 -setup {
test textTag-15.1 {TkTextBindProc} -setup {
    .t tag delete x y
    wm geometry . +200+200 ; update
    event generate {} <Motion> -warp 1 -x 5 -y 5 ; update idletasks ; after 50
} -body {
    bind .t <ButtonRelease> {lappend x up}
    .t tag bind x <ButtonRelease> {lappend x x-up}
    .t tag bind y <ButtonRelease> {lappend x y-up}
1508
1509
1510
1511
1512
1513
1514
1515

1516
1517
1518
1519
1520
1521

1522
1523
1524
1525

1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544

1545
1546
1547
1548
1549
1550
1551


1552
1553
1554
1555


1556
1557
1558
1559
1560
1561
1562
1256
1257
1258
1259
1260
1261
1262

1263
1264
1265
1266
1267
1268

1269
1270
1271
1272

1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291

1292
1293
1294
1295
1296
1297


1298
1299
1300
1301


1302
1303
1304
1305
1306
1307
1308
1309
1310







-
+





-
+



-
+


















-
+





-
-
+
+


-
-
+
+







    event gen .t <ButtonRelease> -x $x3 -y $y3
    return $x
} -cleanup {
    .t tag delete x y
    bind .t <ButtonRelease> {}
} -result {x-up up up y-up up}

test textTag-15.2 {TkTextBindProc} -constraints haveCourier12 -setup {
test textTag-15.2 {TkTextBindProc} -setup {
    .t tag delete x y
    wm geometry . +200+200 ; update
    event generate {} <Motion> -warp 1 -x 5 -y 5 ; update idletasks ; after 50
} -body {
    .t tag bind x <Enter> {lappend x x-enter}
    .t tag bind x <ButtonPress> {lappend x x-down}
    .t tag bind x <Button> {lappend x x-down}
    .t tag bind x <ButtonRelease> {lappend x x-up}
    .t tag bind x <Leave> {lappend x x-leave}
    .t tag bind y <Enter> {lappend x y-enter}
    .t tag bind y <ButtonPress> {lappend x y-down}
    .t tag bind y <Button> {lappend x y-down}
    .t tag bind y <ButtonRelease> {lappend x y-up}
    .t tag bind y <Leave> {lappend x y-leave}
    event gen .t <Motion> -x 0 -y 0
    set x {}
    .t tag add x 2.0 2.4
    .t tag add y 4.3
    event gen .t <Motion> -x $x1 -y $y1
    lappend x |
    event gen .t <Button> -x $x1 -y $y1
    lappend x |
    event gen .t <Motion> -x $x3 -y $y3 -state 0x100
    lappend x |
    event gen .t <ButtonRelease> -x $x3 -y $y3
    return $x
} -cleanup {
    .t tag delete x y
} -result {x-enter | x-down | | x-up x-leave y-enter}

test textTag-15.3 {TkTextBindProc} -constraints haveCourier12 -setup {
test textTag-15.3 {TkTextBindProc} -setup {
    .t tag delete x y
    wm geometry . +200+200 ; update
    event generate {} <Motion> -warp 1 -x 5 -y 5 ; update idletasks ; after 50
} -body {
    .t tag bind x <Enter> {lappend x x-enter}
    .t tag bind x <Any-ButtonPress-1> {lappend x x-down}
    .t tag bind x <Any-ButtonRelease-1> {lappend x x-up}
    .t tag bind x <Button-1> {lappend x x-down}
    .t tag bind x <ButtonRelease-1> {lappend x x-up}
    .t tag bind x <Leave> {lappend x x-leave}
    .t tag bind y <Enter> {lappend x y-enter}
    .t tag bind y <Any-ButtonPress-1> {lappend x y-down}
    .t tag bind y <Any-ButtonRelease-1> {lappend x y-up}
    .t tag bind y <Button-1> {lappend x y-down}
    .t tag bind y <ButtonRelease-1> {lappend x y-up}
    .t tag bind y <Leave> {lappend x y-leave}
    event gen .t <Motion> -x 0 -y 0
    set x {}
    .t tag add x 2.0 2.4
    .t tag add y 4.3
    event gen .t <Motion> -x $x1 -y $y1
    lappend x |
1571
1572
1573
1574
1575
1576
1577
1578

1579
1580
1581
1582
1583
1584
1585
1586
1587
1319
1320
1321
1322
1323
1324
1325

1326


1327
1328
1329
1330
1331
1332
1333







-
+
-
-







    event gen .t <ButtonRelease-2> -x $x3 -y $y3 -state 0x200
    return $x
} -cleanup {
    .t tag delete x y
} -result {x-enter | x-down | | | x-up | x-leave y-enter}


test textTag-16.1 {TkTextPickCurrent procedure} -constraints {
test textTag-16.1 {TkTextPickCurrent procedure} -setup {
    haveCourier12 
} -setup {
    .t tag delete {*}[.t tag names]
    wm geometry . +200+200 ; update
    event generate {} <Motion> -warp 1 -x 5 -y 5 ; update idletasks ; after 50
} -body {
    event gen .t <ButtonRelease-1> -state 0x100 -x $x1 -y $y1
    set x [.t index current]
    event gen .t <Motion> -x $x2 -y $y2
1595
1596
1597
1598
1599
1600
1601
1602

1603
1604
1605
1606

1607
1608
1609
1610


1611
1612
1613
1614
1615
1616

1617
1618
1619

1620
1621
1622
1623
1624
1625
1626
1627
1628
1341
1342
1343
1344
1345
1346
1347

1348
1349
1350
1351
1352
1353
1354
1355


1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366

1367


1368
1369
1370
1371
1372
1373
1374







-
+




+


-
-
+
+






+


-
+
-
-







    event gen .t <ButtonRelease-3> -state 0x300 -x $x3 -y $y3
    lappend x [.t index current]
    event gen .t <ButtonRelease-1> -state 0x100 -x $x3 -y $y3
    lappend x [.t index current]
} -result {2.1 3.2 3.2 3.2 3.2 3.2 4.3}

test textTag-16.2 {TkTextPickCurrent procedure} -constraints {
    haveCourier12 
    haveFontSizes failsOnUbuntuNoXft
} -setup {
    .t tag delete {*}[.t tag names]
    wm geometry . +200+200 ; update
    event generate {} <Motion> -warp 1 -x 5 -y 5 ; update idletasks ; after 50
    .t configure -font $textWidgetFont -wrap none
} -body {
    .t tag configure big -font $bigFont
    event gen .t <ButtonRelease-1> -state 0x100 -x $x1 -y $y1
    event gen .t <Motion> -x $x2 -y $y2
    event gen .t <ButtonRelease-1> -state 0x100 -x $x4 -y $y4
    event gen .t <Motion> -x $x5 -y $y5
    set x [.t index current]
    .t tag add big 3.0
    update
    lappend x [.t index current]
} -cleanup {
    .t tag delete big
    .t configure -font $curFont -wrap $curWrap
} -result {3.2 3.1}

test textTag-16.3 {TkTextPickCurrent procedure} -constraints {
test textTag-16.3 {TkTextPickCurrent procedure} -setup {
    haveCourier12 
} -setup {
    foreach i {a b c d} {
        .t tag remove $i 1.0 end
    }
    wm geometry . +200+200 ; update
    event generate {} <Motion> -warp 1 -x 5 -y 5 ; update idletasks ; after 50
} -body {
    foreach i {a b c d} {
1642
1643
1644
1645
1646
1647
1648
1649

1650
1651
1652
1653
1654
1655
1656
1657
1658
1388
1389
1390
1391
1392
1393
1394

1395


1396
1397
1398
1399
1400
1401
1402







-
+
-
-







    lappend x |
    event gen .t <Motion> -x $x3 -y $y3
    return $x
} -cleanup {
    .t tag delete {*}[.t tag names]
} -result {enter-a enter-b | leave-b enter-c | leave-a leave-c}

test textTag-16.4 {TkTextPickCurrent procedure} -constraints {
test textTag-16.4 {TkTextPickCurrent procedure} -setup {
    haveCourier12 
} -setup {
    foreach i {a b c d} {
        .t tag remove $i 1.0 end
    }
    wm geometry . +200+200 ; update
    event generate {} <Motion> -warp 1 -x 5 -y 5 ; update idletasks ; after 50
} -body {
    foreach i {a b c d} {
1672
1673
1674
1675
1676
1677
1678
1679

1680
1681
1682
1683
1684
1685

1686
1687
1688

1689
1690
1691

1692
1693
1694

1695
1696
1697
1698

1699
1700
1701
1702
1703
1704

1705
1706
1707

1708
1709
1710

1711
1712
1713
1714

1715
1716
1717
1718

1719
1720
1721
1722
1723
1724

1725
1726
1727
1728
1729
1730

1731
1732
1733

1734
1735
1736
1737

1738
1739
1740
1741
1742
1743
1744
1416
1417
1418
1419
1420
1421
1422

1423
1424
1425
1426
1427
1428
1429
1430
1431
1432

1433
1434
1435

1436
1437
1438
1439
1440
1441
1442
1443

1444
1445
1446
1447
1448
1449
1450
1451
1452
1453

1454
1455
1456

1457
1458
1459
1460
1461
1462
1463
1464
1465

1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478

1479
1480
1481

1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494







-
+






+


-
+


-
+



+



-
+






+


-
+


-
+




+



-
+






+





-
+


-
+




+







    event gen .t <Motion> -x $x2 -y $y2
    return $x
} -cleanup {
    .t tag delete {*}[.t tag names]
} -result {enter-a enter-b enter-c | leave-c leave-b}

test textTag-16.5 {TkTextPickCurrent procedure} -constraints {
    haveCourier12 
    haveFontSizes
} -setup {
    foreach i {big a b c d} {
        .t tag remove $i 1.0 end
    }
    wm geometry . +200+200 ; update
    event generate {} <Motion> -warp 1 -x 5 -y 5 ; update idletasks ; after 50
    .t configure -font $textWidgetFont -wrap none
} -body {
    .t tag configure big -font $bigFont
    event gen .t <Motion> -x $x1 -y $y1
    event gen .t <Motion> -x $x4 -y $y4
    .t tag bind a <Enter> {.t tag add big 3.0 3.2}
    .t tag add a 3.2
    event gen .t <Motion> -x $x2 -y $y2
    event gen .t <Motion> -x $x5 -y $y5
    .t index current
} -cleanup {
    .t tag delete a big
    .t configure -font $curFont -wrap $curWrap
} -result {3.2}

test textTag-16.6 {TkTextPickCurrent procedure} -constraints {
    haveCourier12 
    haveFontSizes failsOnUbuntuNoXft
} -setup {
    foreach i {big a b c d} {
        .t tag remove $i 1.0 end
    }
    wm geometry . +200+200 ; update
    event generate {} <Motion> -warp 1 -x 5 -y 5 ; update idletasks ; after 50
    .t configure -font $textWidgetFont -wrap none
} -body {
    .t tag configure big -font $bigFont
    event gen .t <Motion> -x $x1 -y $y1
    event gen .t <Motion> -x $x4 -y $y4
    .t tag bind a <Enter> {.t tag add big 3.0 3.2}
    .t tag add a 3.2
    event gen .t <Motion> -x $x2 -y $y2
    event gen .t <Motion> -x $x5 -y $y5
    update
    .t index current
} -cleanup {
    .t tag delete a big
    .t configure -font $curFont -wrap $curWrap
} -result {3.1}

test textTag-16.7 {TkTextPickCurrent procedure} -constraints {
    haveCourier12 
    haveFontSizes failsOnUbuntuNoXft
} -setup {
    foreach i {big a b c d} {
        .t tag remove $i 1.0 end
    }
    wm geometry . +200+200 ; update
    event generate {} <Motion> -warp 1 -x 5 -y 5 ; update idletasks ; after 50
    .t configure -font $textWidgetFont -wrap none
} -body {
    .t tag configure big -font $bigFont
    .t tag bind a <Enter> {.t tag add big 3.0 3.2}
    .t tag add a 3.2

    event gen .t <Motion> -x $x1 -y $y1
    event gen .t <Motion> -x $x4 -y $y4
    .t tag bind a <Leave> {.t tag add big 3.0 3.2}
    .t tag add a 2.1
    event gen .t <Motion> -x $x2 -y $y2
    event gen .t <Motion> -x $x5 -y $y5
    update
    .t index current
} -cleanup {
    .t tag delete a big
    .t configure -font $curFont -wrap $curWrap
} -result {3.1}


test textTag-17.1 {insert procedure inserts tags} -setup {
    .t delete 1.0 end
} -body {
    # Objectification of the text widget had a problem
1754
1755
1756
1757
1758
1759
1760
1761

1762
1763
1764
1765
1766
1767
1768
1504
1505
1506
1507
1508
1509
1510

1511
1512
1513
1514
1515
1516
1517
1518







-
+







    wm geometry . +200+200 ; update
    event generate {} <Motion> -warp 1 -x 5 -y 5 ; update idletasks ; after 50
} -body {
    text .t -width 30 -height 4 -relief sunken -borderwidth 10 \
      -highlightthickness 10 -pady 2
    pack .t
    update ; # map the window, otherwise -warp can't be done
    

    .t insert end " Tag here " TAG " no tag here"
    .t tag configure TAG -borderwidth 4 -relief raised
    .t tag bind TAG <Enter>  {lappend res "%x %y tag-Enter"}
    .t tag bind TAG <Leave>  {lappend res "%x %y tag-Leave"}
    bind .t <Enter> {lappend res Enter}
    bind .t <Leave> {lappend res Leave}

Changes to tests/textWind.test.
1
2
3
4
5
6



7
8
9
10
11
12
13


14
15
16

17
18
19
20
21
22
23
1
2
3



4
5
6
7
8
9
10
11
12
13
14
15
16
17

18
19
20
21
22
23
24
25



-
-
-
+
+
+







+
+


-
+







# This file is a Tcl script to test the code in the file tkTextWind.c.
# This file is organized in the standard fashion for Tcl tests.
#
# Copyright (c) 1994 The Regents of the University of California.
# Copyright (c) 1994-1995 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1994 The Regents of the University of California.
# Copyright © 1994-1995 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
namespace import ::tcltest::*
tcltest::configure {*}$argv
tcltest::loadTestedCommands

testConstraint failsOnUbuntu [expr {![info exists ::env(CI)] || ![string match Linux $::tcl_platform(os)]}]

deleteWindows

set fixedFont {"Courier New" -12}
set fixedFont {"Courier" -12}
set fixedHeight [font metrics $fixedFont -linespace]
set fixedWidth [font measure $fixedFont m]
set fixedAscent [font metrics $fixedFont -ascent]

# Widget used in almost all tests
set tWidth 30
set tHeight 6
38
39
40
41
42
43
44
45

46
47
48
49
50
51
52
40
41
42
43
44
45
46

47
48
49
50
51
52
53
54







-
+







wm minsize . 1 1
wm positionfrom . user
wm deiconify .

# This update is needed on MacOS to make sure that the window is mapped
# when the tests begin.

update 
update

set bw [.t cget -borderwidth]
set px [.t cget -padx]
set py [.t cget -pady]
set hlth [.t cget -highlightthickness]
set padx [expr {$bw+$px+$hlth}]
set pady [expr {$bw+$py+$hlth}]
167
168
169
170
171
172
173
174

175
176
177
178
179
180
181
169
170
171
172
173
174
175

176
177
178
179
180
181
182
183







-
+







    destroy .f
} -body {
    frame .f -width 10 -height 6 -bg $color
    .t window create 1.3 -window .f -padx 1 -pady 2
    .t window cget .f -pady
} -cleanup {
    destroy .f
} -returnCodes ok -result {2}
} -returnCodes ok -result 2
test textWind-2.8 {TkTextWindowCmd procedure} -body {
    .t window co
} -returnCodes error -result {wrong # args: should be ".t window configure index ?-option value ...?"}
test textWind-2.9 {TkTextWindowCmd procedure} -body {
    .t window configure gorp
} -returnCodes error -result {bad text index "gorp"}
test textWind-2.10 {TkTextWindowCmd procedure} -body {
578
579
580
581
582
583
584
585

586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602

603
604
605
606
607
608
609
580
581
582
583
584
585
586

587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603

604
605
606
607
608
609
610
611







-
+
















-
+







} -result [list \
    [list [expr {$padx+2*$fixedWidth}] $pady 10 20] \
    [list [expr {$padx+2*$fixedWidth+10}] [expr {$pady+((20-$fixedHeight)/2)}] $fixedWidth $fixedHeight] \
    [list [expr {$padx+2*$fixedWidth}] $pady 25 30] \
    [list [expr {$padx+2*$fixedWidth+25}] [expr {$pady+((30-$fixedHeight)/2)}] $fixedWidth $fixedHeight]]


test textWind-7.1 {EmbWinLostSlaveProc procedure} -setup {
test textWind-7.1 {EmbWinLostContentProc procedure} -setup {
    .t delete 1.0 end
    destroy .f
} -body {
    .t insert 1.0 "Some sample text"
    frame .f -width 10 -height 20 -bg $color
    .t window create 1.2 -window .f
    update
    place .f -in .t -x 100 -y 50
    update
    list [winfo geom .f] [.t bbox 1.2]
} -cleanup {
    destroy .f
} -result [list \
    10x20+[expr {$padx+100}]+[expr {$pady+50}] \
    [list [expr {$padx+2*$fixedWidth}] [expr {$pady+($fixedHeight/2)}] 0 0]]

test textWind-7.2 {EmbWinLostSlaveProc procedure} -setup {
test textWind-7.2 {EmbWinLostContentProc procedure} -setup {
    .t delete 1.0 end
    destroy .t.f
} -body {
    .t insert 1.0 "Some sample text"
    frame .t.f -width 10 -height 20 -bg $color
    .t window create 1.2 -window .t.f
    update
747
748
749
750
751
752
753

754


755
756
757

758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774

775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793

794
795
796
797
798
799
800
749
750
751
752
753
754
755
756

757
758
759
760
761
762
763
764
765
766

767
768
769
770
771
772
773
774
775
776
777

778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796

797
798
799
800
801
802
803
804







+
-
+
+



+




-











-
+


















-
+







    1]

test textWind-10.5 {EmbWinLayoutProc procedure, error in creating window} -setup {
    .t delete 1.0 end
    destroy .t.f
    proc bgerror args {
        global msg
        if {$msg == ""} {
	lappend msg $args
	    lappend msg $args
	}
    }
} -body {
    .t insert 1.0 "Some sample text"
    set msg {}
    .t window create 1.5 -create {
        frame .t.f
        frame .t.f.f -width 10 -height 20 -bg $color
    }
    set msg {}
    update idletasks
    lappend msg [winfo exists .t.f.f]
} -cleanup {
    destroy .t.f
    rename bgerror {}
} -result {{{can't embed .t.f.f relative to .t}} 1}

test textWind-10.6 {EmbWinLayoutProc procedure, error in creating window} -setup {
    .t delete 1.0 end
    proc bgerror args {
        global msg
        if {[lsearch -exact $msg $args] == -1} {
        if {[lsearch -exact $msg $args] < 0} {
            lappend msg $args
        }
    }
} -body {
    .t insert 1.0 "Some sample text"
    update
    .t window create 1.5 -create {
        concat .t
    }
    set msg {}
    update
    lappend msg [.t bbox 1.5]
} -cleanup {
    rename bgerror {}
} -result [list \
    {{can't embed .t relative to .t}} \
    [list [expr {$padx+5*$fixedWidth}] [expr {$pady+($fixedHeight/2)}] 0 0]]

test textWind-10.7 {EmbWinLayoutProc procedure, error in creating window} -setup {
test textWind-10.7 {EmbWinLayoutProc procedure, error in creating window} -constraints failsOnUbuntu -setup {
    .t delete 1.0 end
    destroy .t2
    proc bgerror args {
        global msg
	lappend msg $args
    }
} -body {
854
855
856
857
858
859
860
861

862
863
864
865
866
867
868
869
870
871
872
873
874
875
876

877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892

893
894
895
896
897
898
899
900


901
902
903
904
905
906
907
908

909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924

925
926
927
928
929
930
931
858
859
860
861
862
863
864

865
866
867
868
869
870
871
872
873
874
875
876
877
878
879

880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895

896
897
898
899
900
901
902


903
904
905
906
907
908
909
910
911

912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927

928
929
930
931
932
933
934
935







-
+














-
+















-
+






-
-
+
+







-
+















-
+








test textWind-10.10 {EmbWinLayoutProc procedure, doesn't fit on line} -setup {
    .t delete 1.0 end
    destroy .f
} -body {
    .t configure -wrap char
    .t insert 1.0 "Some sample text"
    frame .f -width 125 -height 20 -bg $color -bd 2 -relief raised
    frame .f -width [expr {($tWidth-12)*$fixedWidth-1}] -height 20 -bg $color -bd 2 -relief raised
    .t window create 1.12 -window .f
    list [.t bbox .f] [.t bbox 1.13]
} -cleanup {
    destroy .f
} -result [list \
    [list [expr {$padx+12*$fixedWidth}] $pady [expr {$tWidth*$fixedWidth-12*$fixedWidth}] 20] \
    [list $padx [expr {$pady+20}] $fixedWidth $fixedHeight]]

test textWind-10.11 {EmbWinLayoutProc procedure, doesn't fit on line} -setup {
    .t delete 1.0 end
    destroy .f
} -body {
    .t configure -wrap char
    .t insert 1.0 "Some sample text"
    frame .f -width 126 -height 20 -bg $color -bd 2 -relief raised
    frame .f -width [expr {($tWidth-12)*$fixedWidth}] -height 20 -bg $color -bd 2 -relief raised
    .t window create 1.12 -window .f
    update
    list [.t bbox .f] [.t bbox 1.13]
} -cleanup {
    destroy .f
} -result [list \
    [list [expr {$padx+12*$fixedWidth}] $pady [expr {$tWidth*$fixedWidth-12*$fixedWidth}] 20] \
    [list $padx [expr {$pady+20}] $fixedWidth $fixedHeight]]

test textWind-10.12 {EmbWinLayoutProc procedure, doesn't fit on line} -setup {
    .t delete 1.0 end
    destroy .f
} -body {
    .t configure -wrap char
    .t insert 1.0 "Some sample text"
    frame .f -width 127 -height 20 -bg $color -bd 2 -relief raised
    frame .f -width [expr {($tWidth-12)*$fixedWidth+1}] -height 20 -bg $color -bd 2 -relief raised
    .t window create 1.12 -window .f
    update
    list [.t bbox .f] [.t bbox 1.13]
} -cleanup {
    destroy .f
} -result [list \
    [list $padx [expr {$pady+$fixedHeight}] 127 20] \
    [list [expr {$padx+127}] [expr {$pady+$fixedHeight+((20-$fixedHeight)/2)}] $fixedWidth $fixedHeight]]
    [list $padx [expr {$pady+$fixedHeight}] [expr {($tWidth-12)*$fixedWidth+1}] 20] \
    [list [expr {$padx+($tWidth-12)*$fixedWidth+1}] [expr {$pady+$fixedHeight+((20-$fixedHeight)/2)}] $fixedWidth $fixedHeight]]

test textWind-10.13 {EmbWinLayoutProc procedure, doesn't fit on line} -setup {
    .t delete 1.0 end
    destroy .f
} -body {
    .t configure -wrap none
    .t insert 1.0 "Some sample text"
    frame .f -width 130 -height 20 -bg $color -bd 2 -relief raised
    frame .f -width [expr {($tWidth-12)*$fixedWidth+5}] -height 20 -bg $color -bd 2 -relief raised
    .t window create 1.12 -window .f
    update
    list [.t bbox .f] [.t bbox 1.13]
} -cleanup {
    destroy .f
} -result [list \
    [list [expr {$padx+12*$fixedWidth}] $pady [expr {$tWidth*$fixedWidth-12*$fixedWidth}] 20] \
    {}]

test textWind-10.14 {EmbWinLayoutProc procedure, doesn't fit on line} -setup {
    .t delete 1.0 end
    destroy .f
} -body {
    .t configure -wrap none
    .t insert 1.0 "Some sample text"
    frame .f -width 130 -height 220 -bg $color -bd 2 -relief raised
    frame .f -width [expr {($tWidth-12)*$fixedWidth+5}] -height 220 -bg $color -bd 2 -relief raised
    .t window create 1.12 -window .f
    update
    list [.t bbox .f] [.t bbox 1.13]
} -cleanup {
    destroy .f
} -result [list \
    [list [expr {$padx+12*$fixedWidth}] $pady [expr {$tWidth*$fixedWidth-12*$fixedWidth}] [expr {$tHeight*$fixedHeight}]] \
1401
1402
1403
1404
1405
1406
1407
1408

1409
1410
1411
1412
1413
1414
1415
1405
1406
1407
1408
1409
1410
1411

1412
1413
1414
1415
1416
1417
1418
1419







-
+







    frame .f -width 20 -height 10 -bg blue
    .t window create 1.3 -window .f
    toplevel .tt
    pack [.t peer create .tt.t]
    update ; update
    destroy .t .tt
    winfo exists .f
} -result {0}
} -result 0

test textWind-17.2 {peer widgets and embedded windows} -setup {
    destroy .t .f .tt
} -body {
    pack [text .t]
    .t insert end "Line 1\nLine 2"
    frame .f -width 20 -height 10 -bg blue
Changes to tests/tk.test.
1
2
3
4
5
6



7
8
9
10
11
12


13
14
15
16
17
18

19
20
21
22
23
24
25
26
27
28
29
30
31

32
33
34
35
36
37
38
1
2
3



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

20
21
22
23
24
25
26
27
28
29
30
31
32

33
34
35
36
37
38
39
40



-
-
-
+
+
+






+
+





-
+












-
+







# This file is a Tcl script to test the tk command.
# It is organized in the standard fashion for Tcl tests.
#
# Copyright (c) 1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright (c) 2002 ActiveState Corporation.
# Copyright © 1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# Copyright © 2002 ActiveState Corporation.

package require tcltest 2.2
eval tcltest::configure $argv
tcltest::loadTestedCommands
namespace import -force tcltest::test

testConstraint testprintf [llength [info command testprintf]]

test tk-1.1 {tk command: general} -body {
    tk
} -returnCodes error -result {wrong # args: should be "tk subcommand ?arg ...?"}
test tk-1.2 {tk command: general} -body {
    tk xyz
} -returnCodes error -result {unknown or ambiguous subcommand "xyz": must be appname, busy, caret, fontchooser, inactive, scaling, useinputmethods, or windowingsystem}
} -returnCodes error -result {unknown or ambiguous subcommand "xyz": must be appname, busy, caret, fontchooser, inactive, scaling, sysnotify, systray, useinputmethods, or windowingsystem}

# Value stored to restore default settings after 2.* tests
set appname [tk appname]
test tk-2.1 {tk command: appname} -body {
    tk appname xyz abc
} -returnCodes error -result {wrong # args: should be "tk appname ?newName?"}
test tk-2.2 {tk command: appname} -body {
    tk appname foobazgarply
} -result {foobazgarply}
test tk-2.3 {tk command: appname} -constraints unix -body {
    tk appname bazfoogarply
    expr {[lsearch -exact [winfo interps] [tk appname]] >= 0}
} -result {1}
} -result 1
test tk-2.4 {tk command: appname} -body {
    tk appname [tk appname]
} -result [tk appname]
tk appname $appname

# Value stored to restore default settings after 3.* tests
set scaling [tk scaling]
60
61
62
63
64
65
66
67

68
69
70
71

72
73
74
75
76

77
78
79
80
81

82
83
84
85
86
87
88
62
63
64
65
66
67
68

69
70
71
72

73
74
75
76
77

78
79
80
81
82

83
84
85
86
87
88
89
90







-
+



-
+




-
+




-
+







test tk-3.7 {tk command: scaling: set new} -body {
    tk scaling -displayof . 1.25
    format %.3g [tk scaling]
} -result 1.25
test tk-3.8 {tk command: scaling: negative} -body {
    tk scaling -1
    expr {[tk scaling] > 0}
} -result {1}
} -result 1
test tk-3.9 {tk command: scaling: too big} -body {
    tk scaling 1000000
    expr {[tk scaling] < 10000}
} -result {1}
} -result 1
test tk-3.10 {tk command: scaling: widthmm} -body {
    tk scaling 1.25
    expr {int((25.4*[winfo screenwidth .])/(72*1.25) + 0.5) \
        - [winfo screenmmwidth .]}
} -result {0}
} -result 0
test tk-3.11 {tk command: scaling: heightmm} -body {
    tk scaling 1.25
    expr {int((25.4*[winfo screenheight .])/(72*1.25) + 0.5) \
        - [winfo screenmmheight .]}
} -result {0}
} -result 0
tk scaling $scaling

# Value stored to restore default settings after 4.* tests
set useim [tk useinputmethods]
test tk-4.1 {tk command: useinputmethods} -body {
    tk useinputmethods -displayof
} -returnCodes error -result {value for "-displayof" missing}
133
134
135
136
137
138
139
140

141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160

161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178




179
180
181
182
183
184
135
136
137
138
139
140
141

142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161

162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190







-
+



















-
+


















+
+
+
+






    tk caret . -x 0 -y
} -returnCodes error -result {wrong # args: should be "tk caret window ?-x x? ?-y y? ?-height height?"}
test tk-5.5 {tk caret} -body {
    tk caret . -x 10 -y 11 -h 12; tk caret .
} -result {-height 12 -x 10 -y 11}
test tk-5.6 {tk caret} -body {
    tk caret . -x 20 -y 25 -h 30; tk caret . -hei
} -result {30}
} -result 30

# tk inactive
test tk-6.1 {tk inactive} -body {
    string is integer [tk inactive]
} -result 1
test tk-6.2 {tk inactive reset} -body {
    tk inactive reset
} -returnCodes ok -match glob -result *
test tk-6.3 {tk inactive wrong argument} -body {
    tk inactive foo
} -returnCodes 1 -result {bad option "foo": must be reset}
test tk-6.4 {tk inactive too many arguments} -body {
    tk inactive reset foo
} -returnCodes 1 -result {wrong # args: should be "tk inactive ?-displayof window? ?reset?"}
test tk-6.5 {tk inactive} -body {
    tk inactive reset
    update
    after 100
    set i [tk inactive]
    expr {$i == -1 || ( $i > 90 && $i < 200 )}
    expr {$i < 0 || ( $i > 90 && $i < 200 )}
} -result 1

test tk-7.1 {tk inactive in a safe interpreter} -body {
# tk inactive in safe interpreters
    safe::interpCreate foo
    safe::loadTk foo
    foo eval {tk inactive}
} -cleanup {
    ::safe::interpDelete foo
} -result -1
test tk-7.2 {tk inactive reset in a safe interpreter} -body {
# tk inactive in safe interpreters
    safe::interpCreate foo
    safe::loadTk foo
    foo eval {tk inactive reset}
} -cleanup {
    ::safe::interpDelete foo
} -returnCodes 1 -result {resetting the user inactivity timer is not allowed in a safe interpreter}

test tk-8.1 {Test for ticket [1cc44617e2], see if TCL_LL_MODIFIER works as expected on all platforms} -constraints testprintf -body {
    testprintf -21474836480
} -result {-21474836480 18446744052234715136}

# tests of [tk busy] in busy.test

# cleanup
cleanupTests
return
Changes to tests/ttk/all.tcl.
1
2
3
4
5
6
7

8
9
10
11
12

13
14
15
16
17
18


19

20
1
2
3
4
5
6

7
8
9
10
11

12
13
14
15
16
17
18
19
20

21







-
+




-
+






+
+
-
+
-
# all.tcl --
#
# This file contains a top-level script to run all of the ttk
# tests.  Execute it by invoking "source all.tcl" when running tktest
# in this directory.
#
# Copyright (c) 2007 by the Tk developers.
# Copyright © 2007 the Tk developers.
#
# 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 [file dirname [tcltest::testsDirectory]] constraints.tcl]
tcltest::configure -singleproc 1
set ErrorOnFailures [info exists env(ERROR_ON_FAILURES)]
encoding system utf-8
tcltest::runAllTests
if {[tcltest::runAllTests] && $ErrorOnFailures} {exit 1}

Changes to tests/ttk/checkbutton.test.
1
2
3
4
5
6



7
8
9
10
11
12
13
1
2
3
4


5
6
7
8
9
10
11
12
13
14




-
-
+
+
+







#
# ttk::checkbutton widget tests.
#

package require Tk
package require tcltest ; namespace import -force tcltest::*
package require tk
package require tcltest 2.2
namespace import -force tcltest::*
loadTestedCommands

test checkbutton-1.1 "Checkbutton check" -body {
    pack [ttk::checkbutton .cb -text "TCheckbutton" -variable cb]
}
test checkbutton-1.2 "Checkbutton invoke" -body {
    .cb invoke
52
53
54
55
56
57
58
59

60
61
62
63
64
65
66
67
68
69
70
71
72














73
53
54
55
56
57
58
59

60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88







-
+













+
+
+
+
+
+
+
+
+
+
+
+
+
+

    }
    toplevel .top
    ttk::menubutton .top.mb -text Button -style TLabel
    bind .top.mb <ButtonRelease-1> destroy_button
    pack .top.mb
    focus -force .top.mb
    update
    event generate .top.mb <1>
    event generate .top.mb <Button-1>
    event generate .top.mb <ButtonRelease-1>
    update  ; # shall not trigger error  invalid command name ".top.b"
} -result {}

# Bug [fa8de77936]
test checkbutton-1.8 "Empty -variable" -body {
    # shall simply not crash
    ttk::checkbutton .cbev -variable {}
    .cbev invoke
} -cleanup {
    destroy .cbev
} -result {}

test checkbutton-2.1 "style command" -body {
    ttk::checkbutton .w
    list [.w cget -style] [.w style] [winfo class .w]
} -cleanup {
    destroy .w
} -result {{} TCheckbutton TCheckbutton}
test checkbutton-2.2 "style command" -body {
    ttk::style configure customStyle.TCheckbutton
    ttk::checkbutton .w -style customStyle.TCheckbutton
    list [.w cget -style] [.w style] [winfo class .w]
} -cleanup {
    destroy .w
} -result {customStyle.TCheckbutton customStyle.TCheckbutton TCheckbutton}

tcltest::cleanupTests
Changes to tests/ttk/combobox.test.
1
2
3
4
5
6



7
8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
1
2
3
4


5
6
7
8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
23




-
-
+
+
+








-
+







#
# ttk::combobox widget tests
#

package require Tk 8.5
package require tcltest ; namespace import -force tcltest::*
package require tk
package require tcltest 2.2
namespace import -force tcltest::*
loadTestedCommands

test combobox-1.0 "Combobox tests -- setup" -body {
    ttk::combobox .cb
} -result .cb

test combobox-1.1 "Bad -values list" -body {
    .cb configure -values "bad \{list"
} -result "unmatched open brace in list" -returnCodes 1
} -result "unmatched open brace in list" -returnCodes error

test combobox-1.end "Combobox tests -- cleanup" -body {
    destroy .cb
}

test combobox-2.0 "current command" -body {
    ttk::combobox .cb -values [list a b c d e a]
34
35
36
37
38
39
40
41

42
43
44
45
46

47
48
49
50
51
52

53
54
55
56
57
58
59
60
61

62
63
64
65
66
67
68
35
36
37
38
39
40
41

42
43
44
45
46

47
48
49
50
51
52

53
54
55
56
57
58
59
60
61

62
63
64
65
66
67
68
69







-
+




-
+





-
+








-
+







} -result 2

test combobox-2.3 "current -- change value" -body {
    .cb set "b"
    .cb current
} -result 1

test combobox-2.4 "current -- value not in list" -body { 
test combobox-2.4 "current -- value not in list" -body {
    .cb set "z"
    .cb current
} -result -1

test combobox-2.5 "current -- set to end index" -body { 
test combobox-2.5 "current -- set to end index" -body {
    .cb configure -values [list a b c d e thelastone]
    .cb current end
    .cb get
} -result thelastone

test combobox-2.6 "current -- set to unknown index" -body { 
test combobox-2.6 "current -- set to unknown index" -body {
    .cb configure -values [list a b c d e]
    .cb current notanindex
} -returnCodes error -result {Incorrect index notanindex}

test combobox-2.end "Cleanup" -body { destroy .cb }

test combobox-3 "Read postoffset value dynamically from current style" -body {
    ttk::combobox .cb -values [list a b c] -style "DerivedStyle.TCombobox"
    pack .cb -expand true -fill both 
    pack .cb -expand true -fill both
    ttk::style configure DerivedStyle.TCombobox -postoffset [list 25 0 0 0]
    ttk::combobox::Post .cb
    expr {[winfo rootx .cb.popdown] - [winfo rootx .cb]}
} -result 25 -cleanup {
    destroy .cb
}

81
82
83
84
85
86
87














88
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103







+
+
+
+
+
+
+
+
+
+
+
+
+
+

    lappend result Select [winfo ismapped .cb.popdown] [.cb get]
    update
    set result
} -result [list Start 0 {} Post 1 {} Select 0 b Event 0 b] -cleanup {
    destroy .cb
}

test combobox-4.1 "style command" -body {
    ttk::combobox .w
    list [.w cget -style] [.w style] [winfo class .w]
} -cleanup {
    destroy .w
} -result {{} TCombobox TCombobox}
test combobox-4.2 "style command" -body {
    ttk::style configure customStyle.TCombobox
    ttk::combobox .w -style customStyle.TCombobox
    list [.w cget -style] [.w style] [winfo class .w]
} -cleanup {
    destroy .w
} -result {customStyle.TCombobox customStyle.TCombobox TCombobox}

tcltest::cleanupTests
Changes to tests/ttk/entry.test.
1
2
3
4
5
6



7


8
9
10
11
12
13
14
1
2
3
4


5
6
7
8
9
10
11
12
13
14
15
16
17




-
-
+
+
+

+
+







#
# Tile package: entry widget tests
#

package require Tk 8.5
package require tcltest ; namespace import -force tcltest::*
package require tk
package require tcltest 2.2
namespace import -force tcltest::*
loadTestedCommands

testConstraint failsOnUbuntu [expr {![info exists ::env(CI)] || ![string match Linux $::tcl_platform(os)]}]

variable scrollInfo
proc scroll args {
    global scrollInfo
    set scrollInfo $args
}

69
70
71
72
73
74
75












76
77
78
79
80
81
82
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97







+
+
+
+
+
+
+
+
+
+
+
+








test entry-2.1 "Create entry before scrollbar" -body {
    pack [ttk::entry .te -xscrollcommand [list .tsb set]] \
	-expand true -fill both
    pack [ttk::scrollbar .tsb -orient horizontal -command [list .te xview]] \
    	-expand false -fill x
}  -cleanup {destroy .te .tsb}

test entry-2.1.1 "Create entry before scrollbar - scrollbar catches up" -constraints failsOnUbuntu -body {
    pack [ttk::entry .te -xscrollcommand [list .tsb set]] \
	-expand true -fill both
    .te insert end [string repeat "abc" 50]
    catch {update} ; # error triggers because the -xscrollcommand callback
                     # errors out: invalid command name ".tsb"
    pack [ttk::scrollbar .tsb -orient horizontal -command [list .te xview]] \
    	-expand false -fill x
    update ; # no error
    lappend res [expr [lindex [.tsb get] 1] < 1] ; # scrollbar did update
} -result 1 -cleanup {destroy .te .tsb}

test entry-2.2 "Initial scroll position" -body {
    ttk::entry .e -font fixed -width 5 -xscrollcommand scroll
    .e insert end "0123456789"
    pack .e;
    set timeout [after 500 {set $scrollInfo "timeout"}]
    vwait scrollInfo
90
91
92
93
94
95
96
97

98
99
100
101
102
103
104
105
106
107
108
109
110
111

112
113
114
115
116
117
118
119







-
+







# Bounding box / scrolling tests.
test entry-3.0 "Series 3 setup" -body {
    ttk::style theme use default
    variable fixed TkFixedFont
    variable cw [font measure $fixed a]
    variable ch [font metrics $fixed -linespace]
    variable bd 2	;# border + padding
    variable ux [font measure $fixed \u4e4e]
    variable ux [font measure $fixed ]

    pack [ttk::entry .e -font $fixed -width 20]
    update
}

test entry-3.1 "bbox widget command" -body {
    .e delete 0 end
112
113
114
115
116
117
118
119

120
121
122
123
124
125
126

127
128
129
130
131
132
133

134
135
136
137
138
139
140

141
142
143
144
145
146
147
127
128
129
130
131
132
133

134
135
136
137
138
139
140

141
142
143
144
145
146
147

148
149
150
151
152
153
154

155
156
157
158
159
160
161
162







-
+






-
+






-
+






-
+







} -result {0.0 0.5}

test entry-3.3 "xview" -body {
    .e delete 0 end;
    .e insert end abcdefghijklmnopqrstuvwxyz
    .e xview end
    set result [.e index @0]
} -result {7}
} -result 7

test entry-3.4 "xview" -body {
    .e delete 0 end;
    .e insert end abcdefghijklmnopqrstuvwxyz
    .e xview moveto 1.0
    set result [.e index @0]
} -result {7}
} -result 7

test entry-3.5 "xview" -body {
    .e delete 0 end;
    .e insert end abcdefghijklmnopqrstuvwxyz
    .e xview scroll 5 units
    set result [.e index @0]
} -result {5}
} -result 5

test entry-3.6 "xview" -body {
    .e delete 0 end;
    .e insert end [string repeat abcdefghijklmnopqrstuvwxyz 5]
    .e xview scroll 2 pages
    set result [.e index @0]
} -result {40}
} -result 40

test entry-3.last "Series 3 cleanup" -body {
    destroy .e
}

# Selection tests:

308
309
310
311
312
313
314






























315

316
317
318
319
320
321
322
323
324
325
326














327
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359

360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+











+
+
+
+
+
+
+
+
+
+
+
+
+
+

    .e insert insert e ; lappend result [.e index insert] [.e index end]
    set result
} -result [list 1 3  2 3  3 3  3 3  3 3] -cleanup {
    unset V
    destroy .e
}

test entry-10.1 {configuration option: "-placeholder"} -setup {
    pack [ttk::entry .e]
} -body {
    .e configure -placeholder {Some text}
    .e cget -placeholder
} -cleanup {
    destroy .e
} -result {Some text}

test entry-10.2 {configuration option: "-placeholderforeground"} -setup {
    pack [ttk::entry .e]
} -body {
    .e configure -placeholder {Some text} -placeholderforeground red
    .e cget -placeholderforeground
} -cleanup {
    destroy .e
} -result {red}

test entry-10.3 {styling option: "-placeholderforeground"} -setup {
    pack [ttk::entry .e]
} -body {
    set current [ttk::style configure TEntry -placeholderforeground]
    ttk::style configure TEntry -placeholderforeground blue
    set res [ttk::style configure TEntry -placeholderforeground]
    ttk::style configure TEntry -placeholderforeground $current
    set res
} -cleanup {
    destroy .e
} -result {blue}

test entry-10.1 {Bug [2830360fff] - Don't loose invalid at focus events} -setup {
test entry-11.1 {Bug [2830360fff] - Don't loose invalid at focus events} -setup {
    pack [ttk::entry .e]
    update
} -body {
    .e state invalid
    set res [.e state]
    event generate .e <FocusOut>
    lappend res [.e state]
} -result {invalid invalid} -cleanup {
    destroy .e
}

test entry-12.1 "style command" -body {
    ttk::entry .w
    list [.w cget -style] [.w style] [winfo class .w]
} -cleanup {
    destroy .w
} -result {{} TEntry TEntry}
test entry-12.2 "style command" -body {
    ttk::style configure customStyle.TEntry
    ttk::entry .w -style customStyle.TEntry
    list [.w cget -style] [.w style] [winfo class .w]
} -cleanup {
    destroy .w
} -result {customStyle.TEntry customStyle.TEntry TEntry}

tcltest::cleanupTests
Changes to tests/ttk/image.test.
1
2



3
4
5
6
7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
22
23
24
25
26

27
28
29
30
31
32
33


1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
22
23
24
25
26

27
28
29
30
31
32
33
34
-
-
+
+
+











-
+











-
+







package require Tk 8.5
package require tcltest ; namespace import -force tcltest::*
package require tk
package require tcltest 2.2
namespace import -force tcltest::*
loadTestedCommands

test image-1.1 "Bad image element" -body {
    ttk::style element create BadImage image badimage
} -returnCodes error -result {image "badimage" doesn't exist}

test image-1.2 "Duplicate element" -setup {
    image create photo test.element -width 10 -height 10
    ttk::style element create testElement image test.element
} -body {
    ttk::style element create testElement image test.element
} -returnCodes 1 -result "Duplicate element testElement"
} -returnCodes error -result "Duplicate element testElement"

test image-2.0 "Deletion of displayed image (label)" -setup {
     image create photo test.image -width 10 -height 10
} -body {
    pack [set w [ttk::label .ttk_image20 -image test.image]]
    tkwait visibility $w
    image delete test.image
    update
} -cleanup {
    destroy .ttk_image20
} -result {}
    

test image-2.1 "Deletion of displayed image (checkbutton)" -setup {
     image create photo test.image -width 10 -height 10
} -body {
    pack [set w [ttk::checkbutton .ttk_image21 -image test.image]]
    tkwait visibility $w
    image delete test.image
    update
Changes to tests/ttk/labelframe.test.
1
2



3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19

20
21
22
23
24

25
26
27
28

29
30
31
32
33
34

35
36
37
38
39
40

41
42
43
44
45

46
47
48
49
50

51
52
53
54
55

56
57
58
59
60

61
62
63
64
65
66

67
68
69
70
71
72
73

74
75
76

77
78
79
80
81
82
83
84

85
86
87
88
89
90

91
92
93
94
95

96
97
98
99
100
101
102

103
104
105
106
107
108
109

110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129














130


1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19

20
21
22
23
24

25
26
27
28

29
30
31
32
33
34

35
36
37
38
39
40

41
42
43
44
45

46
47
48
49
50

51
52
53
54
55

56
57
58
59
60

61
62
63
64
65
66

67
68
69
70
71
72
73

74
75
76

77
78
79
80
81
82
83
84

85
86
87
88
89
90

91
92
93
94
95

96
97
98
99
100
101
102

103
104
105
106
107
108
109

110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
-
-
+
+
+










-
+





-
+




-
+



-
+





-
+





-
+




-
+




-
+




-
+




-
+





-
+






-
+


-
+







-
+





-
+




-
+






-
+






-
+




















+
+
+
+
+
+
+
+
+
+
+
+
+
+

package require Tk 8.5
package require tcltest ; namespace import -force tcltest::*
package require tk
package require tcltest 2.2
namespace import -force tcltest::*
loadTestedCommands

test labelframe-1.0 "Setup" -body {
    pack [ttk::labelframe .lf] -expand true -fill both
}

test labelframe-2.1 "Can't use indirect descendant as labelwidget" -body {
    ttk::frame .lf.t
    ttk::checkbutton .lf.t.cb
    .lf configure -labelwidget .lf.t.cb
} -returnCodes 1 -result "can't *" -match glob \
} -returnCodes error -result "can't *" -match glob \
  -cleanup { destroy .lf.t } ;

test labelframe-2.2 "Can't use toplevel as labelwidget" -body {
    toplevel .lf.t
    .lf configure -labelwidget .lf.t
} -returnCodes 1 -result "can't *" -match glob \
} -returnCodes error -result "can't *" -match glob \
  -cleanup { destroy .lf.t } ;

test labelframe-2.3 "Can't use non-windows as -labelwidget" -body {
    .lf configure -labelwidget BogusWindowName
} -returnCodes 1 -result {bad window path name "BogusWindowName"}
} -returnCodes error -result {bad window path name "BogusWindowName"}

test labelframe-2.4 "Can't use nonexistent-windows as -labelwidget" -body {
    .lf configure -labelwidget .nosuchwindow
} -returnCodes 1 -result {bad window path name ".nosuchwindow"}
} -returnCodes error -result {bad window path name ".nosuchwindow"}


###
# See also series labelframe-4.x
#
test labelframe-3.1 "Add child slave" -body {
test labelframe-3.1 "Add child content" -body {
    checkbutton .lf.cb -text "abcde"
    .lf configure -labelwidget .lf.cb
    list [update; winfo viewable .lf.cb] [winfo manager .lf.cb]
} -result [list 1 labelframe]

test labelframe-3.2 "Remove child slave" -body {
test labelframe-3.2 "Remove child content" -body {
    .lf configure -labelwidget {}
    list [update; winfo viewable .lf.cb] [winfo manager .lf.cb]
} -result [list 0 {}]

test labelframe-3.3 "Re-add child slave" -body {
test labelframe-3.3 "Re-add child content" -body {
    .lf configure -labelwidget .lf.cb
    list [update; winfo viewable .lf.cb] [winfo manager .lf.cb]
} -result [list 1 labelframe]

test labelframe-3.4 "Re-manage child slave" -body {
test labelframe-3.4 "Re-manage child content" -body {
    pack .lf.cb -side right
    list [update; winfo viewable .lf.cb] [winfo manager .lf.cb] [.lf cget -labelwidget]
} -result [list 1 pack {}]

test labelframe-3.5 "Re-add child slave" -body {
test labelframe-3.5 "Re-add child content" -body {
    .lf configure -labelwidget .lf.cb
    list [update; winfo viewable .lf.cb] [winfo manager .lf.cb]
} -result [list 1 labelframe]

test labelframe-3.6 "Destroy child slave" -body {
test labelframe-3.6 "Destroy child content" -body {
    destroy .lf.cb
    .lf cget -labelwidget
} -result {}

###
# Re-run series labelframe-3.x with nonchild slaves.
# Re-run series labelframe-3.x with nonchild content.
#
# @@@ ODDITY, 14 Nov 2005:
# @@@ labelframe-4.1 fails if .cb is a [checkbutton],
# @@@ but seems to succeed if it's some other widget class.
# @@@ I suspect a race condition; unable to track it down ATM.
#
# @@@ FOLLOWUP: This *may* have been caused by a bug in ManagerIdleProc 
# @@@ FOLLOWUP: This *may* have been caused by a bug in ManagerIdleProc
# @@@ (see manager.c r1.11). There's still probably a race condition in here.
#
test labelframe-4.1 "Add nonchild slave" -body {
test labelframe-4.1 "Add nonchild content" -body {
    checkbutton .cb -text "abcde"
    .lf configure -labelwidget .cb
    update
    list [winfo ismapped .cb] [winfo viewable .cb] [winfo manager .cb]

} -result [list 1 1 labelframe]

test labelframe-4.2 "Remove nonchild slave" -body {
test labelframe-4.2 "Remove nonchild content" -body {
    .lf configure -labelwidget {}
    update;
    list [winfo ismapped .cb] [winfo viewable .cb] [winfo manager .cb]
} -result [list 0 0 {}]

test labelframe-4.3 "Re-add nonchild slave" -body {
test labelframe-4.3 "Re-add nonchild content" -body {
    .lf configure -labelwidget .cb
    list [update; winfo viewable .cb] [winfo manager .cb]
} -result [list 1 labelframe]

test labelframe-4.4 "Re-manage nonchild slave" -body {
test labelframe-4.4 "Re-manage nonchild content" -body {
    pack .cb -side right
    list [update; winfo viewable .cb] \
    	[winfo manager .cb] \
	[.lf cget -labelwidget]
} -result [list 1 pack {}]

test labelframe-4.5 "Re-add nonchild slave" -body {
test labelframe-4.5 "Re-add nonchild content" -body {
    .lf configure -labelwidget .cb
    list [update; winfo viewable .cb] \
    	[winfo manager .cb] \
	[.lf cget -labelwidget]
} -result [list 1 labelframe .cb]

test labelframe-4.6 "Destroy nonchild slave" -body {
test labelframe-4.6 "Destroy nonchild content" -body {
    destroy .cb
    .lf cget -labelwidget
} -result {}

test labelframe-5.0 "Cleanup" -body {
    destroy .lf
}

# 1342876 -- labelframe should raise sibling -labelwidget above self.
#
test labelframe-6.1 "Stacking order" -body {
    toplevel .t
    pack [ttk::checkbutton .t.x1]
    pack [ttk::labelframe .t.lf -labelwidget [ttk::label .t.lb]]
    pack [ttk::checkbutton .t.x2]
    winfo children .t
} -cleanup {
    destroy .t
} -result [list .t.x1 .t.lf .t.lb .t.x2]

test labelframe-7.1 "style command" -body {
    ttk::labelframe .w
    list [.w cget -style] [.w style] [winfo class .w]
} -cleanup {
    destroy .w
} -result {{} TLabelframe TLabelframe}
test labelframe-7.2 "style command" -body {
    ttk::style configure customStyle.TLabelframe
    ttk::labelframe .w -style customStyle.TLabelframe
    list [.w cget -style] [.w style] [winfo class .w]
} -cleanup {
    destroy .w
} -result {customStyle.TLabelframe customStyle.TLabelframe TLabelframe}

tcltest::cleanupTests
Changes to tests/ttk/layout.test.
1
2



3
4
5
6
7
8
9


1
2
3
4
5
6
7
8
9
10
-
-
+
+
+







package require Tk 8.5
package require tcltest ; namespace import -force tcltest::*
package require tk
package require tcltest 2.2
namespace import -force tcltest::*
loadTestedCommands

test layout-1.1 "Size computations for mixed-orientation layouts" -body {
    ttk::style theme use default

    set block [image create photo -width 10 -height 10]
    ttk::style element create block image $block
Changes to tests/ttk/notebook.test.
1
2



3
4
5
6
7
8
9


1
2
3
4
5
6
7
8
9
10
-
-
+
+
+







package require Tk 8.5
package require tcltest ; namespace import -force tcltest::*
package require tk
package require tcltest 2.2
namespace import -force tcltest::*
loadTestedCommands

test notebook-1.0 "Setup" -body {
    ttk::notebook .nb
} -result .nb

#
20
21
22
23
24
25
26
27

28
29
30
31

32
33
34
35
36
37
38
21
22
23
24
25
26
27

28
29
30
31

32
33
34
35
36
37
38
39







-
+



-
+







    .nb add [frame .sibling]
} -returnCodes error -result "*" -match glob

test notebook-1.3 "Cannot add toplevel" -body {
    .nb add [toplevel .nb.t]
} -cleanup {
    destroy .t.nb
} -returnCodes 1 -match glob -result "can't add .nb.t*"
} -returnCodes error -match glob -result "can't add .nb.t*"

test notebook-1.4 "Try to select bad tab" -body {
    .nb select @6000,6000
} -returnCodes 1 -match glob -result "* not found"
} -returnCodes error -match glob -result "* not found"

#
# Now add stuff:
#
test notebook-2.0 "Add children" -body {
    pack .nb -expand true -fill both
    .nb add [frame .nb.foo] -text "Foo"
507
508
509
510
511
512
513














514
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529







+
+
+
+
+
+
+
+
+
+
+
+
+
+

test notebook-1343984-2 "don't autoselect on destroy" -body {
    set ::history [list]
    destroy .nb
    update
    set ::history
} -result [list DESTROY .nb.frame1 DESTROY .nb.frame2 DESTROY .nb.frame3]

test notebook-8.1 "style command" -body {
    ttk::notebook .w
    list [.w cget -style] [.w style] [winfo class .w]
} -cleanup {
    destroy .w
} -result {{} TNotebook TNotebook}
test notebook-8.2 "style command" -body {
    ttk::style configure customStyle.TNotebook
    ttk::notebook .w -style customStyle.TNotebook
    list [.w cget -style] [.w style] [winfo class .w]
} -cleanup {
    destroy .w
} -result {customStyle.TNotebook customStyle.TNotebook TNotebook}

tcltest::cleanupTests
Changes to tests/ttk/panedwindow.test.
1
2



3
4
5
6
7
8
9


1
2
3
4
5
6
7
8
9
10
-
-
+
+
+







package require Tk 8.5
package require tcltest ; namespace import -force tcltest::*
package require tk
package require tcltest 2.2
namespace import -force tcltest::*
loadTestedCommands

proc propagate-geometry {} { update idletasks }

# Basic sanity checks:
#
test panedwindow-1.0 "Setup" -body {
42
43
44
45
46
47
48
49

50
51
52
53
54
55
56
43
44
45
46
47
48
49

50
51
52
53
54
55
56
57







-
+








test panedwindow-1.7 "Make sure empty panedwindow still still doesn't crash" -body {
    update
}

test panedwindow-1.8 "Re-forget pane" -body {
    .pw forget .pw.f1
} -returnCodes 1 -result ".pw.f1 is not managed by .pw"
} -returnCodes error -result ".pw.f1 is not managed by .pw"

test panedwindow-1.end "Cleanup" -body {
    destroy .pw
}

# Resize behavior:
#
106
107
108
109
110
111
112
113
114


115
116
117
118
119
120
121

122
123
124
125

126
127
128
129
130
131
132
107
108
109
110
111
112
113


114
115
116
117
118
119
120
121

122
123
124
125

126
127
128
129
130
131
132
133







-
-
+
+






-
+



-
+







test panedwindow-2.end "Cleanup" -body { destroy .pw }

#
# ...
#
test panedwindow-3.0 "configure pane" -body {
    ttk::panedwindow .pw
    .pw add [listbox .pw.lb1] 
    .pw add [listbox .pw.lb2] 
    .pw add [listbox .pw.lb1]
    .pw add [listbox .pw.lb2]
    .pw pane 1 -weight 2
    .pw pane 1 -weight
} -result 2

test panedwindow-3.1 "configure pane -- errors" -body {
    .pw pane 1 -weight -4
} -returnCodes 1 -match glob -result "-weight must be nonnegative"
} -returnCodes error -match glob -result "-weight must be nonnegative"

test panedwindow-3.2 "add pane -- errors" -body {
    .pw add [ttk::label .pw.l] -weight -1
} -returnCodes 1 -match glob -result "-weight must be nonnegative"
} -returnCodes error -match glob -result "-weight must be nonnegative"


test panedwindow-3.end "cleanup" -body { destroy .pw }


test panedwindow-4.1 "forget" -body {
    pack [ttk::panedwindow .pw -orient vertical] -expand true -fill both
142
143
144
145
146
147
148
149

150
151
152
153
154
155
156
143
144
145
146
147
148
149

150
151
152
153
154
155
156
157







-
+







    .pw forget .pw.l3
    .pw forget .pw.l4
    update
}

test panedwindow-4.2 "forget forgotten" -body {
    .pw forget .pw.l1
} -returnCodes 1 -result ".pw.l1 is not managed by .pw"
} -returnCodes error -result ".pw.l1 is not managed by .pw"

# checkorder $winlist --
#	Ensure that Y coordinates windows in $winlist are strictly increasing.
#
proc checkorder {winlist} {
    set pos -1
    set positions [list]
249
250
251
252
253
254
255
256

257
258
259
260
261
262
263
264
265

266
267
268
269
270
271
272
273
274
275
276
277

278
279
280
281
282
283

284
285
286
287
288
289
290


















291
250
251
252
253
254
255
256

257
258
259
260
261
262
263
264
265

266
267
268
269
270
271
272
273
274
275
276
277

278
279
280
281
282
283

284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310







-
+








-
+











-
+





-
+







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

    wm geometry . {}
    ttk::panedwindow .pw -orient vertical

    frame .pw.f1 -width 100 -height 50
    frame .pw.f2 -width 100 -height 50

    list [winfo reqwidth .pw.f1] [winfo reqheight .pw.f1]
} -result [list 100 50] 
} -result [list 100 50]

test paned-propagation-1 "Initial request size" -body {
    .pw add .pw.f1
    .pw add .pw.f2
    propagate-geometry
    list [winfo reqwidth .pw] [winfo reqheight .pw]
} -result [list 100 105]

test paned-propagation-2 "Slave change before map" -body {
test paned-propagation-2 "Pane change before map" -body {
    .pw.f1 configure -width 200 -height 100
    propagate-geometry
    list [winfo reqwidth .pw] [winfo reqheight .pw]
} -result [list 200 155]

test paned-propagation-3 "Map window" -body {
    pack .pw -expand true -fill both
    update
    list [winfo width .pw] [winfo height .pw] [.pw sashpos 0]
} -result [list 200 155 100]

test paned-propagation-4 "Slave change after map, off-axis" -body {
test paned-propagation-4 "Pane change after map, off-axis" -body {
    .pw.f1 configure -width 100 ;# should be granted
    propagate-geometry
    list [winfo reqwidth .pw] [winfo reqheight .pw] [.pw sashpos 0]
} -result [list 100 155 100]

test paned-propagation-5 "Slave change after map, on-axis" -body {
test paned-propagation-5 "Pane change after map, on-axis" -body {
    .pw.f1 configure -height 50 ;# should be denied
    propagate-geometry
    list [winfo reqwidth .pw] [winfo reqheight .pw] [.pw sashpos 0]
} -result [list 100 155 100]

test paned-propagation-cleanup "Clean up." -body { destroy .pw }

test panedwindow-6.1 "style command" -body {
    # Contrary to ttk::scrollbar, ttk::progressbar and ttk::scale,
    # ttk::panedwindow has same style TPanedwindow whatever -orient is
    ttk::panedwindow .wv  ; # default is  -orient vertical
    ttk::panedwindow .wh -orient horizontal
    list [.wv cget -style] [.wv style] [winfo class .wv]\
         [.wh cget -style] [.wh style] [winfo class .wh]
} -cleanup {
    destroy .wv .wh
} -result {{} TPanedwindow TPanedwindow {} TPanedwindow TPanedwindow}
test panedwindow-6.2 "style command" -body {
    ttk::style configure customStyle.TPanedwindow
    ttk::panedwindow .w -style customStyle.TPanedwindow
    list [.w cget -style] [.w style] [winfo class .w]
} -cleanup {
    destroy .w
} -result {customStyle.TPanedwindow customStyle.TPanedwindow TPanedwindow}

tcltest::cleanupTests
Changes to tests/ttk/progressbar.test.
1
2



3
4
5
6
7
8
9


1
2
3
4
5
6
7
8
9
10
-
-
+
+
+







package require Tk 8.5
package require tcltest ; namespace import -force tcltest::*
package require tk
package require tcltest 2.2
namespace import -force tcltest::*
loadTestedCommands


test progressbar-1.1 "Setup" -body {
    ttk::progressbar .pb
} -result .pb

72
73
74
75
76
77
78
79

80
81
82
83
84























































85
73
74
75
76
77
78
79

80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141







-
+





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

    set PB
} -result 6.0

test progressbar-2.5 "error in write trace" -body {
    trace variable PB w { error "YIPES!" ;# }
    .pb step
    set PB		;# NOTREACHED
} -cleanup { unset PB } -returnCodes 1 -match glob -result "*YIPES!"
} -cleanup { unset PB } -returnCodes error -match glob -result "*YIPES!"

test progressbar-end "Cleanup" -body {
    destroy .pb
}

# check existence and default value of each non-core option of the widget
test progressbar-3.1 "progressbar non-core options" -setup {
    set res {}
    ttk::progressbar .defaultpb
} -body {
    foreach option {-anchor -foreground -justify -style -text -wraplength \
                    -length -maximum -mode -orient -phase -value -variable} {
        lappend res [.defaultpb cget $option]
    }
    set res
} -cleanup {
    unset res
    destroy .defaultpb
} -result {w black left {} {} 0 100 100 determinate horizontal 0 0.0 {}}

test progressbar-3.2 "TIP #442 options are taken into account" -setup {
    set res {}
    pack [ttk::progressbar .p -value 0 -maximum 50 -orient horizontal -mode determinate -length 500]
    set thefont [font actual {Arial 10}]
} -body {
    .p configure -anchor c -foreground blue -justify right \
            -text "TIP #442\noptions are now tested" -wraplength 100
    update
    .p step 10
    .p configure -anchor e -font $thefont -foreground green -justify center \
            -text "Changing the value of each option\nfrom TIP #442" -wraplength 250
    update
    .p step 20
    .p configure -orient vertical -text "Cannot be seen"
    update
    foreach option {-anchor -foreground -justify -text -wraplength} {
        lappend res [list $option [.p cget $option]]
    }
    set res
} -cleanup {
    unset res thefont
    destroy .p
} -result {{-anchor e} {-foreground green} {-justify center} {-text {Cannot be seen}} {-wraplength 250}}

test progressbar-4.1 "style command" -body {
    ttk::progressbar .wh  ; # default is  -orient horizontal
    ttk::progressbar .wv -orient vertical
    list [.wh cget -style] [.wh style] [winfo class .wh]\
         [.wv cget -style] [.wv style] [winfo class .wv]
} -cleanup {
    destroy .wh .wv
} -result {{} Horizontal.TProgressbar TProgressbar {} Vertical.TProgressbar TProgressbar}
test progressbar-4.2 "style command" -body {
    ttk::style configure customStyle.Vertical.TProgressbar
    ttk::progressbar .w -orient vertical -style customStyle.Vertical.TProgressbar
    list [.w cget -style] [.w style] [winfo class .w]
} -cleanup {
    destroy .w
} -result {customStyle.Vertical.TProgressbar Vertical.customStyle.Vertical.TProgressbar TProgressbar}

tcltest::cleanupTests
Changes to tests/ttk/radiobutton.test.
1
2
3
4
5
6



7
8
9
10
11
12
13
1
2
3
4


5
6
7
8
9
10
11
12
13
14




-
-
+
+
+







#
# ttk::radiobutton widget tests.
#

package require Tk
package require tcltest ; namespace import -force tcltest::*
package require tk
package require tcltest 2.2
namespace import -force tcltest::*
loadTestedCommands

test radiobutton-1.1 "Radiobutton check" -body {
    pack \
    	[ttk::radiobutton .rb1 -text "One" -variable choice -value 1] \
	[ttk::radiobutton .rb2 -text "Two" -variable choice -value 2] \
	[ttk::radiobutton .rb3 -text "Three" -variable choice -value 3] \
41
42
43
44
45
46
47














48
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63







+
+
+
+
+
+
+
+
+
+
+
+
+
+

} -result {0 1 1}

test radiobutton-1.8 "Reset radiobutton variable" -body {
    set ::choice 2
    list [info exists ::choice] [.rb1 instate alternate] [.rb2 instate alternate]
} -result {1 0 0}

test radiobutton-2.1 "style command" -body {
    ttk::radiobutton .w
    list [.w cget -style] [.w style] [winfo class .w]
} -cleanup {
    destroy .w
} -result {{} TRadiobutton TRadiobutton}
test radiobutton-2.2 "style command" -body {
    ttk::style configure customStyle.TRadiobutton
    ttk::radiobutton .w -style customStyle.TRadiobutton
    list [.w cget -style] [.w style] [winfo class .w]
} -cleanup {
    destroy .w
} -result {customStyle.TRadiobutton customStyle.TRadiobutton TRadiobutton}

tcltest::cleanupTests
Added tests/ttk/scale.test.





















































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
package require tk
package require tcltest 2.2
namespace import -force tcltest::*
loadTestedCommands

test scale-1.0 "Self-destruction" -body {
    trace variable v w { destroy .s ;# }
    ttk::scale .s -variable v
    pack .s ; update
    .s set 1 ; update
} -returnCodes error -match glob -result "*"

test scale-2.1 "-state option" -setup {
    ttk::scale .s
    set res ""
} -body {
    # defaults
    lappend res [.s instate disabled] [.s cget -state]
    # set -state: instate returns accordingly
    .s configure -state disabled
    lappend res [.s instate disabled] [.s cget -state]
    # back to normal
    .s configure -state normal
    lappend res [.s instate disabled] [.s cget -state]
    # use state command: -state does NOT reflect it
    .s state disabled
    lappend res [.s instate disabled] [.s cget -state]
    # further use state command
    .s state readonly
    lappend res [.s state] [.s cget -state]
} -cleanup {
    destroy .s
    unset -nocomplain res
} -result {0 normal 1 disabled 0 normal 1 normal {disabled readonly} normal}

test scale-3.1 "style command" -body {
    ttk::scale .wh  ; # default is  -orient horizontal
    ttk::scale .wv -orient vertical
    list [.wh cget -style] [.wh style] [winfo class .wh] \
         [.wv cget -style] [.wv style] [winfo class .wv]
} -cleanup {
    destroy .wh .wv
} -result {{} Horizontal.TScale TScale {} Vertical.TScale TScale}
test scale-3.2 "style command" -body {
    ttk::style configure customStyle.Vertical.TScale
    ttk::scale .w -orient vertical -style customStyle.Vertical.TScale
    list [.w cget -style] [.w style] [winfo class .w]
} -cleanup {
    destroy .w
} -result {customStyle.Vertical.TScale Vertical.customStyle.Vertical.TScale TScale}

tcltest::cleanupTests

Changes to tests/ttk/scrollbar.test.
1
2



3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22


23
24
25
26
27
28
29
30
31

32
33
34
35
36
37
38
39
40

41
42
43
44
45
46
47


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21


22
23
24
25
26
27
28
29
30
31

32
33
34
35
36
37
38
39
40

41
42
43
44
45
46
47
48
-
-
+
+
+


















-
-
+
+








-
+








-
+







package require Tk 8.5
package require tcltest ; namespace import -force tcltest::*
package require tk
package require tcltest 2.2
namespace import -force tcltest::*
loadTestedCommands

testConstraint coreScrollbar [expr {[tk windowingsystem] eq "aqua"}]

# Before 2019 the code in library/ttk/scrollbar.tcl would replace the
# constructor of ttk::scrollbar with the constructor of tk::scrollbar
# unless the -class or -style options were specified..
# Now there is an implementation of ttk::scrollbar for macOS.  The
# tests are left in place, though, except that scrollbar-swapout-1
# test was changed to expect the class to be TScrollbar instead of
# Scrollbar.

test scrollbar-swapout-1 "Don't use core scrollbars on OSX..." \
 -constraints {
     coreScrollbar
} -body {
    ttk::scrollbar .sb -command "yadda"
    list [winfo class .sb] [.sb cget -command]
} -result [list TScrollbar yadda] -cleanup { 
    destroy .sb 
} -result [list TScrollbar yadda] -cleanup {
    destroy .sb
}

test scrollbar-swapout-2 "... regardless of whether -style ..." \
-constraints {
    coreScrollbar
} -body {
    ttk::style layout Vertical.Custom.TScrollbar \
    	[ttk::style layout Vertical.TScrollbar] ; # See #1833339
    ttk::scrollbar .sb -command "yadda" -style Custom.TScrollbar 
    ttk::scrollbar .sb -command "yadda" -style Custom.TScrollbar
    list [winfo class .sb] [.sb cget -command] [.sb cget -style]
} -result [list TScrollbar yadda Custom.TScrollbar] -cleanup {
    destroy .sb
}

test scrollbar-swapout-3 "... or -class is specified." -constraints {
    coreScrollbar
} -body {
    ttk::scrollbar .sb -command "yadda" -class Custom.TScrollbar 
    ttk::scrollbar .sb -command "yadda" -class Custom.TScrollbar
    list [winfo class .sb] [.sb cget -command]
} -result [list Custom.TScrollbar yadda] -cleanup {
    destroy .sb
}

test scrollbar-1.0 "Setup" -body {
    ttk::scrollbar .tsb
66
67
68
69
70
71
72
73
74
75
76
















77
78
79
80
81






82
83
84
85
86









87
88
89
90
91




92
93
94
95
96
97
98
99
100
101




















102
103

104
105

106
107
108
67
68
69
70
71
72
73




74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89





90
91
92
93
94
95





96
97
98
99
100
101
102
103
104
105




106
107
108
109










110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130

131


132
133
134
135







-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+

-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+
-
-
+



    pack .tsb -side bottom -anchor s -expand 1 -fill x
    wm geometry . 200x200
    update
    set w [winfo width .tsb] ; set h [winfo height .tsb]
    expr {$h < $w}
} -result 1

#
# Scale tests:
#

test scrollbar-10.1.1 {<MouseWheel> event on scrollbar} -setup {
    destroy .t .s
} -body {
    pack [text .t -yscrollcommand {.s set}] -side left
    for {set i 1} {$i < 100} {incr i} {.t insert end "Line $i\n"}
    pack [ttk::scrollbar .s -command {.t yview}] -fill y -expand 1 -side left
    update
    focus -force .s
    event generate .s <MouseWheel> -delta -120
    after 200 {set eventprocessed 1} ; vwait eventprocessed
    .t index @0,0
} -cleanup {
    destroy .t .s
} -result {5.0}

test scrollbar-10.2.1 {<Shift-MouseWheel> event on horizontal scrollbar} -setup {
test scale-1.0 "Self-destruction" -body {
    trace variable v w { destroy .s ;# }
    ttk::scale .s -variable v
    pack .s ; update
    .s set 1 ; update
    destroy .t .s
} -body {
    pack [text .t -xscrollcommand {.s set} -wrap none] -side top
    for {set i 1} {$i < 100} {incr i} {.t insert end "Char $i "}
    pack [ttk::scrollbar .s -command {.t xview} -orient horizontal] -fill x -expand 1 -side top
    update
} -returnCodes 1 -match glob -result "*"

test scale-2.1 "-state option" -setup {
    ttk::scale .s
    set res ""
    focus -force .s
    event generate .s <Shift-MouseWheel> -delta -120
    after 200 {set eventprocessed 1} ; vwait eventprocessed
    .t index @0,0
} -cleanup {
    destroy .t .s
} -result {1.4}
test scrollbar-10.2.2 {<MouseWheel> event on horizontal scrollbar} -setup {
    destroy .t .s
} -body {
    # defaults
    lappend res [.s instate disabled] [.s cget -state]
    # set -state: instate returns accordingly
    .s configure -state disabled
    pack [text .t -xscrollcommand {.s set} -wrap none] -side top
    for {set i 1} {$i < 100} {incr i} {.t insert end "Char $i "}
    pack [ttk::scrollbar .s -command {.t xview} -orient horizontal] -fill x -expand 1 -side top
    update
    lappend res [.s instate disabled] [.s cget -state]
    # back to normal
    .s configure -state normal
    lappend res [.s instate disabled] [.s cget -state]
    # use state command: -state does NOT reflect it
    .s state disabled
    lappend res [.s instate disabled] [.s cget -state]
    # further use state command
    .s state readonly
    lappend res [.s state] [.s cget -state]
    focus -force .s
    event generate .s <MouseWheel> -delta -120
    after 200 {set eventprocessed 1} ; vwait eventprocessed
    .t index @0,0
} -cleanup {
    destroy .t .s
} -result {1.4}

test scrollbar-11.1 "style command" -body {
    ttk::scrollbar .wv  ; # default is  -orient vertical
    ttk::scrollbar .wh -orient horizontal
    list [.wv cget -style] [.wv style] [winfo class .wv] \
         [.wh cget -style] [.wh style] [winfo class .wh]
} -cleanup {
    destroy .wv .wh
} -result {{} Vertical.TScrollbar TScrollbar {} Horizontal.TScrollbar TScrollbar}
test scrollbar-11.2 "style command" -body {
    ttk::style configure customStyle.Horizontal.TScrollbar
    ttk::scrollbar .w -orient horizontal -style customStyle.Horizontal.TScrollbar
    list [.w cget -style] [.w style] [winfo class .w]
} -cleanup {
    destroy .s
    destroy .w
    unset -nocomplain res
} -result {0 normal 1 disabled 0 normal 1 normal {disabled readonly} normal}
} -result {customStyle.Horizontal.TScrollbar Horizontal.customStyle.Horizontal.TScrollbar TScrollbar}

tcltest::cleanupTests

Changes to tests/ttk/spinbox.test.
1
2
3
4
5
6



7
8
9
10
11
12
13
1
2
3
4


5
6
7
8
9
10
11
12
13
14




-
-
+
+
+







#
# ttk::spinbox widget tests
#

package require Tk
package require tcltest ; namespace import -force tcltest::*
package require tk
package require tcltest 2.2
namespace import -force tcltest::*
loadTestedCommands

test spinbox-1.0 "Spinbox tests -- setup" -body {
    ttk::spinbox .sb
} -cleanup { destroy .sb } -result .sb

test spinbox-1.1 "Bad -values list" -setup {
122
123
124
125
126
127
128
129

130
131
132
133
134
135
136
123
124
125
126
127
128
129

130
131
132
133
134
135
136
137







-
+







    .sb configure -validate focus
    .sb configure -validate focusin
    .sb configure -validate focusout
    .sb configure -validate none
    .sb cget -validate
} -cleanup {
    destroy .sb
} -result {none}
} -result none

test spinbox-1.8.3 "option -validate" -setup {
    ttk::spinbox .sb -from 0 -to 100
} -body {
    .sb configure -validate bogus
} -cleanup {
    destroy .sb
144
145
146
147
148
149
150
151

152
153
154
155
156
157
158
145
146
147
148
149
150
151

152
153
154
155
156
157
158
159







-
+







    pack .sb
    .sb set 50
    focus -force .sb
    after 500 {set ::spinbox_wait 1} ; vwait ::spinbox_wait
    set ::spinbox_test
} -cleanup {
    destroy .sb
} -result {50}
} -result 50


test spinbox-2.0 "current command -- unset should be 0" -constraints nyi -setup {
    ttk::spinbox .sb -values [list a b c d e a]
} -body {
    .sb current
} -cleanup {
200
201
202
203
204
205
206
207
208


209
210
211

212

213
214
215

216

217
218
219
220
221




























































222
223
224
225
226
227
228
201
202
203
204
205
206
207

208
209
210
211
212
213
214

215
216
217
218
219

220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292







-

+
+



+
-
+



+
-
+





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







} -result -1

test spinbox-3.0 "textarea should expand to fill widget" -setup {
    set SBV 5
    set ::spinbox_test {}
    ttk::spinbox .sb -from 0 -to 10 -textvariable SBV
} -body {
    grid .sb -sticky ew
    grid columnconfigure . 0 -weight 1
    update idletasks
    set timer [after 500 {set ::spinbox_test timedout}]
    bind . <Map> {
        after idle {
            wm geometry . "210x80"
	    update idletasks
            after 100 {set ::spinbox_test [.sb identify element 5 5]}
            set ::spinbox_test [.sb identify element 25 5]
        }
        bind . <Map> {}
    }
    grid .sb -sticky ew
    after 500 {set ::spinbox_wait 1} ; vwait ::spinbox_wait
    vwait ::spinbox_test
    set ::spinbox_test
} -cleanup {
    destroy .sb
    unset -nocomplain ::spinbox_test SBV
} -result {textarea}

test spinbox-4.0 "Increment with duplicates in -values, wrap" -setup {
    ttk::spinbox .sb -values {one two three 4 5 two six} -wrap true
    set max [expr {[llength [.sb cget -values]] + 2}]
} -body {
    set ::spinbox_test [.sb get]
    for {set i 0} {$i < $max} {incr i} {
        event generate .sb <<Increment>>
        lappend ::spinbox_test [.sb get]
    }
    for {set i 0} {$i < $max} {incr i} {
        event generate .sb <<Decrement>>
        lappend ::spinbox_test [.sb get]
    }
    set ::spinbox_test
} -cleanup {
    destroy .sb
    unset -nocomplain ::spinbox_test max
} -result {one two three 4 5 two six one two one six two 5 4 three two one six}

test spinbox-4.1 "Increment with duplicates in -values, wrap, initial value set" -setup {
    ttk::spinbox .sb -values {one two three 4 5 two six} -wrap true
    set max [expr {[llength [.sb cget -values]] + 2}]
} -body {
    .sb set three
    set ::spinbox_test [.sb get]
    for {set i 0} {$i < $max} {incr i} {
        event generate .sb <<Increment>>
        lappend ::spinbox_test [.sb get]
    }
    .sb set two    ; # the first "two" in the -values list becomes the current value
    for {set i 0} {$i < $max} {incr i} {
        event generate .sb <<Decrement>>
        lappend ::spinbox_test [.sb get]
    }
    set ::spinbox_test
} -cleanup {
    destroy .sb
    unset -nocomplain ::spinbox_test max
} -result {three 4 5 two six one two three 4 5 one six two 5 4 three two one six}

test spinbox-4.2 "Increment with duplicates in -values, no wrap" -setup {
    ttk::spinbox .sb -values {one two three 4 5 two six} -wrap false
    set max [expr {[llength [.sb cget -values]] + 2}]
} -body {
    set ::spinbox_test [.sb get]
    for {set i 0} {$i < $max} {incr i} {
        event generate .sb <<Increment>>
        lappend ::spinbox_test [.sb get]
    }
    for {set i 0} {$i < $max} {incr i} {
        event generate .sb <<Decrement>>
        lappend ::spinbox_test [.sb get]
    }
    set ::spinbox_test
} -cleanup {
    destroy .sb
    unset -nocomplain ::spinbox_test max
} -result {one two three 4 5 two six six six two 5 4 three two one one one one}


# nostomp: NB intentional difference between ttk::spinbox and tk::spinbox;
# see also #1439266
#
test spinbox-nostomp-1 "don't stomp on -variable (init; -from/to)" -body {
    set SBV 55
    ttk::spinbox .sb -textvariable SBV -from 0 -to 100 -increment 5
249
250
251
252
253
254
255
256

257
258
259
260
261
262
263
313
314
315
316
317
318
319

320
321
322
323
324
325
326
327







-
+







} -cleanup {
   unset SBV
   destroy .sb
} -result [list 55 55]

test spinbox-nostomp-4 "don't stomp on -variable (configure; -values)" -body {
    set SBV Apr
    ttk::spinbox .sb 
    ttk::spinbox .sb
    .sb configure -textvariable SBV -values {Jan Feb Mar Apr May Jun Jul Aug}
    list $SBV [.sb get]
} -cleanup {
   unset SBV
   destroy .sb
} -result [list Apr Apr]

274
275
276
277
278
279
280
281

282
283
284
285
286
287
288
289
290
291
292
293
294
295
296














297
298
299
300
301
338
339
340
341
342
343
344

345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379







-
+















+
+
+
+
+
+
+
+
+
+
+
+
+
+






    event generate .sb <<Decrement>>; lappend result $secs
    event generate .sb <<Decrement>>; lappend result $secs
    event generate .sb <<Decrement>>; lappend result $secs
    event generate .sb <<Decrement>>; lappend result $secs

    set result
} -result [list 07 08 09 10 11 10 09 08 07] -cleanup { 
} -result [list 07 08 09 10 11 10 09 08 07] -cleanup {
    destroy .sb
    unset secs
}

test spinbox-dieoctaldie-2 "Cope with general bad input" -body {
    set result [list]
    ttk::spinbox .sb -from 0 -to 100 -format %03.0f
    .sb set asdfasdf ; lappend result [.sb get]
    event generate .sb <<Increment>> ; lappend result [.sb get]
    .sb set asdfasdf ; lappend result [.sb get]
    event generate .sb <<Decrement>> ; lappend result [.sb get]
} -result [list asdfasdf 000 asdfasdf 000] -cleanup {
    destroy .sb
}

test spinbox-5.1 "style command" -body {
    ttk::spinbox .w
    list [.w cget -style] [.w style] [winfo class .w]
} -cleanup {
    destroy .w
} -result {{} TSpinbox TSpinbox}
test spinbox-5.2 "style command" -body {
    ttk::style configure customStyle.TSpinbox
    ttk::spinbox .w -style customStyle.TSpinbox
    list [.w cget -style] [.w style] [winfo class .w]
} -cleanup {
    destroy .w
} -result {customStyle.TSpinbox customStyle.TSpinbox TSpinbox}

tcltest::cleanupTests

# Local variables:
# mode: tcl
# End:
Changes to tests/ttk/treetags.test.
1
2
3



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

20
21
22
23
24
25
26
27
28
29
30
31

32
33
34
35
36
37
38
1


2
3
4
5
6
7
8
9
10
11
12
13
14

15
16
17
18

19
20
21
22
23
24
25
26
27
28
29
30

31
32
33
34
35
36
37
38

-
-
+
+
+










-




-
+











-
+








package require Tk
package require tcltest ; namespace import -force tcltest::*
package require tk
package require tcltest 2.2
namespace import -force tcltest::*
loadTestedCommands

### treeview tag invariants:
#

proc assert {expr {message ""}} {
    if {![uplevel 1 [list expr $expr]]} {
        error "PANIC: $message ($expr failed)"
    }
}
proc in {e l} { expr {[lsearch -exact $l $e] >= 0} }

proc itemConstraints {tv item} {
    # $tag in [$tv item $item -tags] <==> [$tv tag has $tag $item]
    foreach tag [$tv item $item -tags] {
	assert {[in $item [$tv tag has $tag]]}
	assert {$item in [$tv tag has $tag]}
    }
    foreach child [$tv children $item] {
	itemConstraints $tv $child
    }
}

proc treeConstraints {tv} {
    # $item in [$tv tag has $tag] <==> [$tv tag has $tag $item]
    #
    foreach tag [$tv tag names] {
	foreach item [$tv tag has $tag] {
	    assert {[in $tag [$tv item $item -tags]]}
	    assert {$tag in [$tv item $item -tags]}
	}
    }

    itemConstraints $tv {}
}
#
###
101
102
103
104
105
106
107
108

109
110
111
112
113
114
115






116
117
118
119
120
121
122
123
124
125
126
127


128
129
130
131
132
133

134
135

136
137
138
139
140
141
142

143
144
145

146
147

148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168

169
170
171
172
173
174
175
101
102
103
104
105
106
107

108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131


132
133
134
135
136
137
138

139
140

141
142
143
144
145
146
147

148
149
150

151
152

153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173

174
175
176
177
178
179
180
181







-
+







+
+
+
+
+
+










-
-
+
+





-
+

-
+






-
+


-
+

-
+




















-
+







} -result [list [list] [list item2] [list]]

test treetags-1.8 "tag names" -body {
    lsort [$tv tag names]
} -result [list tag1 tag2 tag3]

test treetags-1.9 "tag names - tag added to item" -body {
    $tv item item1 -tags tag4 
    $tv item item1 -tags tag4
    lsort [$tv tag names]
} -result [list tag1 tag2 tag3 tag4]

test treetags-1.10 "tag names - tag configured" -body {
    $tv tag configure tag5
    lsort [$tv tag names]
} -result [list tag1 tag2 tag3 tag4 tag5]

test treetags-1.11 "tag delete" -body {
    $tv tag delete tag5
    $tv tag delete tag4
    lsort [$tv tag names]
} -result [list tag1 tag2 tag3]

test treetags-1.end "cleanup" -body {
    $tv item item1 -tags tag1
    $tv item item2 -tags tag2
    list [$tv tag has tag1] [$tv tag has tag2] [$tv tag has tag3]
} -cleanup {
    treeConstraints $tv
} -result [list [list item1] [list item2] [list]]

test treetags-2.0 "tag bind" -body {
    $tv tag bind tag1 <KeyPress> {set ::KEY %A}
    $tv tag bind tag1 <KeyPress>
    $tv tag bind tag1 <Key> {set ::KEY %A}
    $tv tag bind tag1 <Key>
} -cleanup {
    treeConstraints $tv
} -result {set ::KEY %A}

test treetags-2.1 "Events delivered to tags" -body {
    focus -force $tv ; update	;# needed so [event generate] delivers KeyPress
    focus -force $tv ; update	;# needed so [event generate] delivers Key
    $tv focus item1
    event generate $tv <KeyPress-a>
    event generate $tv <a>
    set ::KEY
} -cleanup {
    treeConstraints $tv
} -result a

test treetags-2.2 "Events delivered to correct tags" -body {
    $tv tag bind tag2 <KeyPress> [list set ::KEY2 %A]
    $tv tag bind tag2 <Key> [list set ::KEY2 %A]

    $tv focus item1
    event generate $tv <KeyPress-b>
    event generate $tv <b>
    $tv focus item2
    event generate $tv <KeyPress-c>
    event generate $tv <c>

    list $::KEY $::KEY2
} -cleanup {
    treeConstraints $tv
} -result [list b c]

test treetags-2.3 "Virtual events delivered to focus item" -body {
    set ::bong 0
    $tv tag bind tag2 <<Bing>> { incr bong }
    $tv focus item2
    event generate $tv <<Bing>>
    $tv focus item1
    event generate $tv <<Bing>>
    set bong
} -cleanup {
    treeConstraints $tv
} -result 1

test treetags-2.4 "Bad events" -body {
    $tv tag bind bad <Enter> { puts "Entered!" }
} -returnCodes 1 -result "unsupported event <Enter>*" -match glob
} -returnCodes error -result "unsupported event <Enter>*" -match glob

test treetags-3.0 "tag configure - set" -body {
    $tv tag configure tag1 -foreground blue -background red
} -cleanup {
    treeConstraints $tv
} -result {}

197
198
199
200
201
202
203
204

205
206
207
208
209

210
211
212
213
214
215
216
217
218
219
220
221
203
204
205
206
207
208
209

210
211
212
213
214

215
216
217
218
219
220
221
222
223
224
225
226
227







-
+




-
+












    $tv tag configure tag2 -font {times 20}
}

test treetags-3.4 "stomp tags in tag binding procedure" -body {
    set result [list]
    $tv tag bind rm1 <<Remove>> { lappend ::result rm1 [%W focus] <<Remove>> }
    $tv tag bind rm2 <<Remove>> {
    	lappend ::result rm2 [%W focus] <<Remove>> 
    	lappend ::result rm2 [%W focus] <<Remove>>
	%W item [%W focus] -tags {tag1}
    }
    $tv tag bind rm3 <<Remove>> { lappend ::result rm3 [%W focus] <<Remove>> }

    $tv item item1 -tags {rm1 rm2 rm3} 
    $tv item item1 -tags {rm1 rm2 rm3}
    $tv focus item1
    event generate $tv <<Remove>>
    set result
} -cleanup {
    treeConstraints $tv
} -result [list rm1 item1 <<Remove>> rm2 item1 <<Remove>> rm3 item1 <<Remove>>]

#

test treetags-end "Cleanup" -body { destroy $tv }

tcltest::cleanupTests
Changes to tests/ttk/treeview.test.
1
2
3
4
5
6
7



8
9
10
11
12
13
14
1
2
3
4
5


6
7
8
9
10
11
12
13
14
15





-
-
+
+
+







#
# [7Jun2005] TO CHECK: [$tv see {}] -- shouldn't work (at least, shouldn't do
# what it currently does)
#

package require Tk 8.5
package require tcltest ; namespace import -force tcltest::*
package require tk
package require tcltest 2.2
namespace import -force tcltest::*
loadTestedCommands

# consistencyCheck --
#	Traverse the tree to make sure the item data structures
#	are properly linked.
#
#	Since [$tv children] follows ->next links and [$tv index]
41
42
43
44
45
46
47
48

49
50
51
52

53
54
55
56

57
58
59
60

61
62
63
64
65
66

67
68
69
70

71
72
73
74

75
76
77
78
79
80
81
82
83
84
85
86

87
88
89
90
91
92
93
42
43
44
45
46
47
48

49
50
51
52

53
54
55
56

57
58
59
60

61
62
63
64
65
66

67
68
69
70

71
72
73
74

75
76
77
78
79
80
81
82
83
84
85
86

87
88
89
90
91
92
93
94







-
+



-
+



-
+



-
+





-
+



-
+



-
+











-
+







test treeview-1.1 "columns" -body {
    .tv configure -columns {a b c}
}

test treeview-1.2 "Bad columns" -body {
    #.tv configure -columns {illegal "list"value}
    ttk::treeview .badtv -columns {illegal "list"value}
} -returnCodes 1 -result "list element in quotes followed by*" -match glob
} -returnCodes error -result "list element in quotes followed by*" -match glob

test treeview-1.3 "bad displaycolumns" -body {
    .tv configure -displaycolumns {a b d}
} -returnCodes 1 -result "Invalid column index d"
} -returnCodes error -result "Invalid column index d"

test treeview-1.4 "more bad displaycolumns" -body {
    .tv configure -displaycolumns {1 2 3}
} -returnCodes 1 -result "Column index 3 out of bounds"
} -returnCodes error -result "Column index 3 out of bounds"

test treeview-1.5 "Don't forget to check negative numbers" -body {
    .tv configure -displaycolumns {1 -2 3}
} -returnCodes 1 -result "Column index -2 out of bounds"
} -returnCodes error -result "Column index -2 out of bounds"

# Item creation.
#
test treeview-2.1 "insert -- not enough args" -body {
    .tv insert
} -returnCodes 1 -result "wrong # args: *" -match glob
} -returnCodes error -result "wrong # args: *" -match glob

test treeview-2.3 "insert -- bad integer index" -body {
    .tv insert {} badindex
} -returnCodes 1 -result "expected integer *" -match glob
} -returnCodes error -result "expected integer *" -match glob

test treeview-2.4 "insert -- bad parent node" -body {
    .tv insert badparent end
} -returnCodes 1 -result "Item badparent not found" -match glob
} -returnCodes error -result "Item badparent not found" -match glob

test treeview-2.5 "insert -- finaly insert a node" -body {
    .tv insert {} end -id newnode -text "New node"
} -result newnode

test treeview-2.6 "insert -- make sure node was inserted" -body {
    .tv children {}
} -result [list newnode]

test treeview-2.7 "insert -- prevent duplicate node names" -body {
    .tv insert {} end -id newnode
} -returnCodes 1 -result "Item newnode already exists"
} -returnCodes error -result "Item newnode already exists"

test treeview-2.8 "insert -- new node at end" -body {
    .tv insert {} end -id lastnode
    consistencyCheck .tv
    .tv children {}
} -result [list newnode lastnode]

121
122
123
124
125
126
127
128

129
130
131
132
133
134
135
122
123
124
125
126
127
128

129
130
131
132
133
134
135
136







-
+







    .tv insert {} 0 -id newfirstone
    consistencyCheck .tv
    .tv children {}
} -result [list newfirstone firstnode newnode anotherone onemore lastnode newlastone]

test treeview-2.14 "insert -- bad options" -body {
    .tv insert {} end -badoption foo
} -returnCodes 1 -result {unknown option "-badoption"}
} -returnCodes error -result {unknown option "-badoption"}

test treeview-2.15 "insert -- at position 0 w/no children" -body {
    .tv insert newnode 0 -id newnode.n2 -text "Foo"
    .tv children newnode
} -result newnode.n2	;# don't crash

test treeview-2.16 "insert -- insert way past end" -body {
197
198
199
200
201
202
203
204

205
206
207
208
209
210
211
198
199
200
201
202
203
204

205
206
207
208
209
210
211
212







-
+







    .tv children {}
} -result [list newfirstone firstnode anotherone onemore lastnode newlastone]

test treeview-3.11 "Can't detach root item" -body {
    .tv detach [list {}]
    update
    consistencyCheck .tv
} -returnCodes 1 -result "Cannot detach root item"
} -returnCodes error -result "Cannot detach root item"
consistencyCheck .tv

test treeview-3.12 "Reattach" -body {
    .tv move newnode {} end
    consistencyCheck .tv
    .tv children {}
} -result [list newfirstone firstnode anotherone onemore lastnode newlastone newnode]
270
271
272
273
274
275
276
277

278
279
280
281
282
283
284
271
272
273
274
275
276
277

278
279
280
281
282
283
284
285







-
+







test treeview-4.3 "opened - closed node" -body {
    .tv item newnode -open 0
    .tv item newnode -open
} -result 0

test treeview-5.1 "item -- error checks" -body {
    .tv item newnode -text "Bad values" -values "{bad}list"
} -returnCodes 1 -result "list element in braces followed by*" -match glob
} -returnCodes error -result "list element in braces followed by*" -match glob

test treeview-5.2 "item -- error leaves options unchanged " -body {
    .tv item newnode -text
} -result "New node"

test treeview-5.3 "Heading" -body {
    .tv heading #0 -text "Heading"
293
294
295
296
297
298
299
300

301
302
303
304

305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320

321
322
323
324
325
326
327
294
295
296
297
298
299
300

301
302
303
304

305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320

321
322
323
324
325
326
327
328







-
+



-
+















-
+







test treeview-5.5 "set cell" -body {
    .tv set newnode 1 XXX
    .tv item newnode -values
} -result [list a XXX c]

test treeview-5.6 "set illegal cell" -body {
    .tv set newnode #0 YYY
} -returnCodes 1 -result "Display column #0 cannot be set"
} -returnCodes error -result "Display column #0 cannot be set"

test treeview-5.7 "set illegal cell" -body {
    .tv set newnode 3 YY	;# 3 == current #columns
} -returnCodes 1 -result "Column index 3 out of bounds"
} -returnCodes error -result "Column index 3 out of bounds"

test treeview-5.8 "set display columns" -body {
    .tv configure -displaycolumns [list 2 1 0]
    .tv set newnode #1 X
    .tv set newnode #2 Y
    .tv set newnode #3 Z
    .tv item newnode -values
} -result [list Z Y X]

test treeview-5.9 "display columns part 2" -body {
    list [.tv column #1 -id] [.tv column #2 -id] [.tv column #3 -id]
} -result [list c b a]

test treeview-5.10 "cannot set column -id" -body {
    .tv column #1 -id X
} -returnCodes 1 -result "Attempt to change read-only option"
} -returnCodes error -result "Attempt to change read-only option"

test treeview-5.11 "get" -body {
    .tv set newnode #1
} -result X

test treeview-5.12 "get dictionary" -body {
    .tv set newnode
401
402
403
404
405
406
407
408

409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429

430
431
432
433
434
435
436
402
403
404
405
406
407
408

409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429

430
431
432
433
434
435
436
437







-
+




















-
+







    .tv move d3 d 0
    consistencyCheck .tv
    .tv children d
} -result [list d3 d1 d2]

test treeview-7.2 "illegal move" -body {
   .tv move d d2 end
} -returnCodes 1 -result "Cannot insert d as descendant of d2"
} -returnCodes error -result "Cannot insert d as descendant of d2"

test treeview-7.3 "illegal move has no effect" -body {
    consistencyCheck .tv
    .tv children d
} -result [list d3 d1 d2]

test treeview-7.4 "Replace children" -body {
    .tv children d [list d3 d2 d1]
    consistencyCheck .tv
    .tv children d
} -result [list d3 d2 d1]

test treeview-7.5 "replace children - precondition" -body {
    # Just check to make sure the test suite so far has left
    # us in the state we expect to be in:
    list [.tv parent newnode] [.tv children newnode]
} -result [list {} [list newnode.n1 newnode.n2 newnode.n3]]

test treeview-7.6 "Replace children - illegal move" -body {
    .tv children newnode.n1 [list newnode.n1 newnode.n2 newnode.n3]
} -returnCodes 1 -result "Cannot insert newnode.n1 as descendant of newnode.n1"
} -returnCodes error -result "Cannot insert newnode.n1 as descendant of newnode.n1"

consistencyCheck .tv

test treeview-8.0 "Selection set" -body {
    .tv selection set [list newnode.n1 newnode.n3 newnode.n2]
    .tv selection
} -result [list newnode.n1 newnode.n2 newnode.n3]
453
454
455
456
457
458
459
460

461
462
463
464
465
466
467
468
469

470
471
472
473
474
475
476
454
455
456
457
458
459
460

461
462
463
464
465
466
467
468
469

470
471
472
473
474
475
476
477







-
+








-
+







test treeview-8.4 "Selection - clear" -body {
    .tv selection set {}
    .tv selection
} -result {}

test treeview-8.5 "Selection - bad operation" -body {
    .tv selection badop foo
} -returnCodes 1 -match glob -result {bad selection operation "badop": must be *}
} -returnCodes error -match glob -result {bad selection operation "badop": must be *}

test treeview-8.6 "Selection - <<TreeviewSelect>> on selection add" -body {
    .tv selection set {}
    bind .tv <<TreeviewSelect>> {set res 1}
    set res 0
    .tv selection add newnode.n1
    update
    set res
} -result {1}
} -result 1

test treeview-8.7 "<<TreeviewSelect>> on selected item deletion" -body {
    .tv selection set {}
    .tv insert "" end -id selectedDoomed -text DeadItem
    .tv insert "" end -id doomed -text AlsoDead
    .tv selection add selectedDoomed
    update
503
504
505
506
507
508
509






















































510
511
512
513
514
515
516
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    }
} -body {
    .tree yview scroll 5 units
    .tree identify item 2 2
} -cleanup {
    destroy .tree
} -result {I006}

test treeview-9.2 {scrolling on see command - bug [14188104c3]} -setup {
    toplevel .top
    ttk::treeview .top.tree -show {} -height 10 -columns {label} \
            -yscrollcommand [list .top.vs set]
    ttk::scrollbar .top.vs -command {.top.tree yview}
    grid .top.tree -row 0 -column 0 -sticky ns
    grid .top.vs -row 0 -column 1 -sticky ns
    update
    proc setrows {n} {
        .top.tree delete [.top.tree children {}]
        for {set i 1} {$i <= $n} {incr i} {
            .top.tree insert {} end -id row$i \
                    -values [list [format "Row %2.2d" $i]]
        }
        .top.tree see row1
        update idletasks
    }
} -body {
    setrows 10
    set res [.top.vs get]
    setrows 20
    lappend res [expr [lindex [.top.vs get] 1] < 1]
} -cleanup {
    destroy .top
} -result {0.0 1.0 1}

test treeview-9.3 {scrolling on see command, requested item is closed} -setup {
    toplevel .top
    ttk::treeview .top.tree -show tree -height 10 -columns {label} \
            -yscrollcommand [list .top.vs set]
    ttk::scrollbar .top.vs -command {.top.tree yview}
    grid .top.tree -row 0 -column 0 -sticky ns
    grid .top.vs -row 0 -column 1 -sticky ns

    .top.tree insert {} end -id a -text a
    .top.tree insert a  end -id b -text b
    .top.tree insert b  end -id c -text c
    .top.tree insert c  end -id d -text d
    .top.tree insert d  end -id e -text e
    for {set i 6} {$i <= 15} {incr i} {
        .top.tree insert {} end -id row$i \
                -values [list [format "Row %2.2d" $i]]
    }
    update
} -body {
    set before [lindex [.top.vs get] 1]
    .top.tree see e
    update idletasks
    set after [lindex [.top.vs get] 1]
    expr $after < $before
} -cleanup {
    destroy .top
} -result 1

### identify tests:
#
proc identify* {tv comps args} {
    foreach {x y} $args {
	foreach comp $comps {
	    lappend result [$tv identify $comp $x $y]
641
642
643
644
645
646
647
648

649
650

651
652
653
654
655
656
657
696
697
698
699
700
701
702

703
704

705
706
707
708
709
710
711
712







-
+

-
+







} -cleanup {
    destroy .tv
}

test treeview-3006842 "Null bindings" -setup {
    ttk::treeview .tv -show tree
} -body {
    .tv tag bind empty <ButtonPress-1> {}
    .tv tag bind empty <Button-1> {}
    .tv insert {} end -text "Click me" -tags empty
    event generate .tv <ButtonPress-1> -x 10 -y 10
    event generate .tv <Button-1> -x 10 -y 10
    .tv tag bind empty
} -result {} -cleanup {
    destroy .tv
}

test treeview-3085489-1 "tag add, no -tags" -setup {
    ttk::treeview .tv
671
672
673
674
675
676
677
678

679
680
681
682
683
684
685

686
687
688
689
690
691
692
693
694
695
696
697

698
699
700
701
702
703
704
726
727
728
729
730
731
732

733
734
735
736
737
738
739

740
741
742
743
744
745
746
747
748
749
750
751

752
753
754
755
756
757
758
759







-
+






-
+











-
+







    .tv item $item -tags
} -cleanup {
    destroy .tv
} -result [list]

test treeview-368fa4561e "indicators cannot be clicked on leafs" -setup {
    pack [ttk::treeview .tv]
    .tv insert {} end -id foo -text "<-- (1) Click the blank space to my left" 
    .tv insert {} end -id foo -text "<-- (1) Click the blank space to my left"
    update
} -body {
    foreach {x y w h} [.tv bbox foo #0] {}
    set res [.tv item foo -open]
    # using $h even for x computation is intentional here in order to simulate
    # a mouse click on the (invisible since we're on a leaf) indicator
    event generate .tv <ButtonPress-1> \
    event generate .tv <Button-1> \
            -x [expr {$x + $h / 2}] \
            -y [expr {$y + $h / 2}]
    lappend res [.tv item foo -open]
    .tv insert foo end -text "sub"
    lappend res [.tv item foo -open]
} -cleanup {
    destroy .tv
} -result {0 0 0}

test treeview-ce470f20fd-1 "dragging further than the right edge of the treeview is allowed" -setup {
    pack [ttk::treeview .tv]
    .tv heading #0 -text "Drag my right edge -->" 
    .tv heading #0 -text "Drag my right edge -->"
    update
} -body {
    set res [.tv column #0 -width]
    .tv drag #0 400
    lappend res [expr {[.tv column #0 -width] > $res}]
} -cleanup {
    destroy .tv
760
761
762
763
764
765
766
767

768
769
770
771
772
773
774
775
776
777
778
779
780
781
782














783
815
816
817
818
819
820
821

822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852







-
+















+
+
+
+
+
+
+
+
+
+
+
+
+
+

    }
    .tv configure -displaycolumns {colB colA colC}
    nostretch .tv
    .tv column colA -width 50 ; .tv column bar -width 60 ; # slack created
    update idletasks ; # redisplay treeview
} -body {
    # only some columns are displayed (and in a different order than declared
    # in -columns), a non-displayed column becomes stretchable  --> nothing 
    # in -columns), a non-displayed column becomes stretchable  --> nothing
    # happens
    set origTreeWidth [winfo width .tv]
    set res [list [.tv column bar -width] [.tv column colA -width]]
    .tv column bar -stretch 1
    update idletasks ; # no change, widget redisplayed
    lappend res [.tv column bar -width] [.tv column colA -width]
    # this column becomes visible  --> widget resizes
    .tv configure -displaycolumns {bar colC colA colB}
    update idletasks ; # no slack anymore because the widget resizes (shrinks)
    lappend res [.tv column bar -width] [.tv column colA -width] \
                [expr {[winfo width .tv] < $origTreeWidth}]
} -cleanup {
    destroy .tv
} -result {60 50 60 50 60 50 1}

test treeview-11.1 "style command" -body {
    ttk::treeview .w
    list [.w cget -style] [.w style] [winfo class .w]
} -cleanup {
    destroy .w
} -result {{} Treeview Treeview}
test treeview-11.2 "style command" -body {
    ttk::style configure customStyle.Treeview
    ttk::treeview .w -style customStyle.Treeview
    list [.w cget -style] [.w style] [winfo class .w]
} -cleanup {
    destroy .w
} -result {customStyle.Treeview customStyle.Treeview Treeview}

tcltest::cleanupTests
Changes to tests/ttk/ttk.test.
1
2
3



4
5
6
7
8
9
10
1


2
3
4
5
6
7
8
9
10
11

-
-
+
+
+








package require Tk 8.5
package require tcltest ; namespace import -force tcltest::*
package require tk
package require tcltest 2.2
namespace import -force tcltest::*
loadTestedCommands

proc skip args {}
proc ok {} { return }

variable widgetClasses {
    button checkbutton radiobutton menubutton label entry
27
28
29
30
31
32
33
34

35
36
37
38
39
40
41
28
29
30
31
32
33
34

35
36
37
38
39
40
41
42







-
+







    destroy $w
}
test ttk-6.1 "Self-destructing checkbutton" -body {
    pack [ttk::checkbutton .sd -text "Self-destruction" -variable ::sd]
    trace variable sd w [list selfdestruct .sd]
    update
    .sd invoke
} -returnCodes 1
} -returnCodes error
test ttk-6.2 "Checkbutton self-destructed" -body {
    winfo exists .sd
} -result 0

# test ttk-6.3 not applicable [see #2175411]

test ttk-6.4 "Destroy widget in configure" -setup {
130
131
132
133
134
135
136
137
138


139
140
141
142
143
144
145
146
147
148

149
150
151
152
153
154
155
131
132
133
134
135
136
137


138
139
140
141
142
143
144
145
146
147
148

149
150
151
152
153
154
155
156







-
-
+
+









-
+







    .t.b invoke
    list [winfo exists .t] [winfo exists .t.b]
} -result [list 0 0]

#
# Basic tests.
#
test ttk-1.1 "Create button" -body {
    pack [ttk::button .t] -expand true -fill both
test ttk-1.1 "Create multiline button showing justified text" -body {
    pack [ttk::button .t -text "Hello\nWorld!!" -justify center] -expand true -fill both
    update
}

test ttk-1.2 "Check style" -body {
    .t cget -style
} -result {}

test ttk-1.3 "Set bad style" -body {
    .t configure -style "nosuchstyle"
} -returnCodes 1 -result {Layout nosuchstyle not found}
} -returnCodes error -result {Layout nosuchstyle not found}

test ttk-1.4 "Original style preserved" -body {
    .t cget -style
} -result ""

proc checkstate {w} {
    foreach statespec {
203
204
205
206
207
208
209
210
211
212



213
214
215
216
217
218
219
204
205
206
207
208
209
210



211
212
213
214
215
216
217
218
219
220







-
-
-
+
+
+







} -result 1

test ttk-2.8 "bug 3223850: button state disabled during click" -setup {
    destroy .b
    set ttk28 {}
    pack [ttk::button .b -command {set ::ttk28 failed}]
    update
} -body { 
    bind .b <ButtonPress-1> {after 0 {.b configure -state disabled}}
    after 1 {event generate .b <ButtonPress-1>}
} -body {
    bind .b <Button-1> {after 0 {.b configure -state disabled}}
    after 1 {event generate .b <Button-1>}
    after 20 {event generate .b <ButtonRelease-1>}
    set aid [after 100 {set ::ttk28 [.b instate {disabled !pressed}]}]
    vwait ::ttk28
    after cancel $aid
    set ttk28
} -cleanup {
    destroy .b
230
231
232
233
234
235
236
237

238
239
240
241

242
243
244
245
246
247
248
249
250
251
252
253
254

255
256
257
258
259
260
261
231
232
233
234
235
236
237

238
239
240
241

242
243
244
245
246
247
248
249
250
251
252
253
254

255
256
257
258
259
260
261
262







-
+



-
+












-
+







	catch {destroy .w}
    }
}

# misc. error detection
test ttk-3.0 "Bad option" -body {
    ttk::button .bad -badoption foo
} -returnCodes 1 -result {unknown option "-badoption"} -match glob
} -returnCodes error -result {unknown option "-badoption"} -match glob

test ttk-3.1 "Make sure widget command not created" -body {
    .bad state disabled
} -returnCodes 1 -result {invalid command name ".bad"} -match glob
} -returnCodes error -result {invalid command name ".bad"} -match glob

test ttk-3.2 "Propagate errors from variable traces" -body {
    set A 0
    trace add variable A write {error "failure" ;# }
    ttk::checkbutton .cb -variable A
    .cb invoke
} -cleanup {
    unset ::A ; destroy .cb
} -returnCodes error -result {can't set "A": failure}

test ttk-3.3 "Constructor failure with cursor" -body {
    ttk::button .b -cursor bottom_right_corner -style BadStyle
} -returnCodes 1 -result "Layout BadStyle not found"
} -returnCodes error -result "Layout BadStyle not found"

test ttk-3.4 "SF#2009213" -body {
    ttk::style configure TScale -sliderrelief {}
    pack [ttk::scale .s]
    update
} -cleanup {
    ttk::style configure TScale -sliderrelief raised
383
384
385
386
387
388
389
390

391
392
393
394
395

396
397
398
399
400
401
402
384
385
386
387
388
389
390

391
392
393
394
395

396
397
398
399
400
401
402
403







-
+




-
+







    icon blank
} -cleanup { destroy .b }

#------------------------------------------------------------------------

test ttk-9.1 "Traces on nonexistant namespaces" -body {
    ttk::checkbutton .tcb -variable foo::bar
} -returnCodes 1 -result "*parent namespace doesn't exist*" -match glob
} -returnCodes error -result "*parent namespace doesn't exist*" -match glob

test ttk-9.2 "Traces on nonexistant namespaces II" -body {
    ttk::checkbutton .tcb -variable X
    .tcb configure -variable foo::bar
} -returnCodes 1 -result "*parent namespace doesn't exist*" -match glob
} -returnCodes error -result "*parent namespace doesn't exist*" -match glob

test ttk-9.3 "Restore saved options on configure error" -body {
    .tcb cget -variable
} -result X

test ttk-9.4 "Textvariable tests" -body {
    set tcbLabel "Testing..."
453
454
455
456
457
458
459
460

461
462
463
464
465
466
467
454
455
456
457
458
459
460

461
462
463
464
465
466
467
468







-
+








test ttk-10.3 "Check class resource" -body {
    .f cget -class
} -result Foo

test ttk-10.4 "Try to modify class resource" -body {
    .f configure -class Bar
} -returnCodes 1 -match glob -result "*read-only option*"
} -returnCodes error -match glob -result "*read-only option*"

test ttk-10.5 "Check class resource again" -body {
    .f cget -class
} -result Foo

test ttk-11.1 "-state test, setup" -body {
    ttk::button .b
543
544
545
546
547
548
549
550

551
552
553
554
555
556
557

558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575

576
577
578
579
580

581
582
583
584
585

586
587
588
589
590
591
592
544
545
546
547
548
549
550

551
552
553
554
555
556
557

558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575

576
577
578
579
580

581
582
583
584
585

586
587
588
589
590
591
592
593







-
+






-
+

















-
+




-
+




-
+







    .t.f configure -borderwidth 1
    ttk::style theme use alt
    update
}

test ttk-13.1 "Custom styles -- bad -style option" -body {
    ttk::button .tb1 -style badstyle
} -returnCodes 1 -result "*badstyle not found*" -match glob
} -returnCodes error -result "*badstyle not found*" -match glob

test ttk-13.4 "Custom styles -- bad -style option" -body {
    ttk::button .tb1
    .tb1 configure -style badstyle
} -cleanup {
    destroy .tb1
} -returnCodes 1 -result "*badstyle not found*" -match glob
} -returnCodes error -result "*badstyle not found*" -match glob

test ttk-13.5 "Custom layouts -- missing element definition" -body {
    ttk::style layout badstyle {
    	NoSuchElement
    }
    ttk::button .tb1 -style badstyle
} -cleanup {
    destroy .tb1
} -result .tb1
# @@@ Should: signal an error, possibly a background error.

#
# See #793909
#

test ttk-14.1 "-variable in nonexistant namespace" -body {
    ttk::checkbutton .tw -variable ::nsn::foo
} -returnCodes 1 -result {can't trace *: parent namespace doesn't exist} \
} -returnCodes error -result {can't trace *: parent namespace doesn't exist} \
  -match glob -cleanup { destroy .tw }

test ttk-14.2 "-textvariable in nonexistant namespace" -body {
    ttk::label .tw -textvariable ::nsn::foo
} -returnCodes 1 -result {can't trace *: parent namespace doesn't exist} \
} -returnCodes error -result {can't trace *: parent namespace doesn't exist} \
  -match glob -cleanup { destroy .tw }

test ttk-14.3 "-textvariable in nonexistant namespace" -body {
    ttk::entry .tw -textvariable ::nsn::foo
} -returnCodes 1 -result {can't trace *: parent namespace doesn't exist} \
} -returnCodes error -result {can't trace *: parent namespace doesn't exist} \
  -match glob -cleanup { destroy .tw }

test ttk-15.1 {Bug 3062331} -setup {
    destroy .b
} -body {
    set Y {}
    ttk::button .b -textvariable Y
624
625
626
627
628
629
630
631

632
633
634
635
636

637
638
639
640
641

642
643
644
645
646

647
648
649
650
651

652
653
654
655











656
657
658
659
660
661
625
626
627
628
629
630
631

632
633
634
635
636

637
638
639
640
641

642
643
644
645
646

647
648
649
650
651

652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673







-
+




-
+




-
+




-
+




-
+




+
+
+
+
+
+
+
+
+
+
+






    set usage $args
    append usage " ?$varpart ...?"
    return "wrong # args: should be \"$usage\""
}

test ttk-ensemble-0 "style element create: insufficient args" -body {
     ttk::style
} -returnCodes 1 -result \
} -returnCodes error -result \
    [wrong#varargs arg ttk::style option]

test ttk-ensemble-1 "style element create: insufficient args" -body {
     ttk::style element
} -returnCodes 1 -result \
} -returnCodes error -result \
    [wrong#varargs arg ttk::style element option]

test ttk-ensemble-2 "style element create: insufficient args" -body {
     ttk::style element create
} -returnCodes 1 -result \
} -returnCodes error -result \
    [wrong#varargs {-option value} ttk::style element create name type]

test ttk-ensemble-3 "style element create: insufficient args" -body {
     ttk::style element create plain.background
} -returnCodes 1 -result \
} -returnCodes error -result \
    [wrong#varargs {-option value} ttk::style element create name type]

test ttk-ensemble-4 "style element create: insufficient args" -body {
     ttk::style element create plain.background from
} -returnCodes 1 -result [wrong#args theme ?element?]
} -returnCodes error -result [wrong#args theme ?element?]

test ttk-ensemble-5 "style element create: valid" -body {
     ttk::style element create plain.background from default
} -returnCodes 0 -result ""

test ttk-16.1 {ttk::style theme styles - no such theme} -body {
    ttk::style theme styles noSuchTheme
} -returnCodes 1 -result {theme "noSuchTheme" doesn't exist}
test ttk-16.2 {ttk::style theme styles - theme exists} -body {
    # simply check this produces a list with some style names,
    # without checking exact content (not needed, and may vary
    # depending on platform, versions, improvements...)
    expr {[llength [ttk::style theme styles alt]] > 0}
} -result 1


eval destroy [winfo children .]

tcltest::cleanupTests

#*EOF*
Changes to tests/ttk/validate.test.
1
2
3
4
5
6
7


8
9
10
11
12
13
14
1
2
3
4
5


6
7
8
9
10
11
12
13
14





-
-
+
+







##
## Entry widget validation tests
## Derived from core test suite entry-19.1 through entry-19.20
##

package require Tk 8.5
package require tcltest 2.1
package require tk
package require tcltest 2.2
namespace import -force tcltest::*

loadTestedCommands

testConstraint ttkEntry 1
testConstraint coreEntry [expr {![testConstraint ttkEntry]}]

157
158
159
160
161
162
163
164

165
166
167
168
169
170
171
157
158
159
160
161
162
163

164
165
166
167
168
169
170
171







-
+








test validate-1.18 {entry widget validation} -constraints coreEntry -body {
    .e configure -validate all
    set ::e nextdata
    list [.e cget -validate] $::vVals
} -result {none {.e -1 -1 nextdata newdata {} all forced}}
# DIFFERENCE: ttk::entry doesn't validate when setting linked -variable
# DIFFERENCE: ttk::entry doesn't disable validation 
# DIFFERENCE: ttk::entry doesn't disable validation

proc doval {W d i P s S v V} {
    set ::vVals [list $W $d $i $P $s $S $v $V]
    set ::e mydata
    return 1
}

Changes to tests/ttk/vsapi.test.
1
2
3
4
5



6
7
8
9

10
11
12
13
14
15
16
1
2
3


4
5
6
7
8
9

10
11
12
13
14
15
16
17



-
-
+
+
+



-
+







# -*- tcl -*-
#

package require Tk 8.5
package require tcltest ; namespace import -force tcltest::*
package require tk
package require tcltest 2.2
namespace import -force tcltest::*
loadTestedCommands

testConstraint xpnative \
    [expr {[lsearch -exact [ttk::style theme names] xpnative] != -1}]
    [expr {"xpnative" in [ttk::style theme names]}]

test vsapi-1.1 "WINDOW WP_SMALLCLOSEBUTTON" -constraints {xpnative} -body {
    ttk::style element create smallclose vsapi \
        WINDOW 19 {disabled 4 pressed 3 active 2 {} 1}
    ttk::style layout CloseButton {CloseButton.smallclose -sticky news}
    ttk::button .b -style CloseButton
    pack .b -expand true -fill both
Changes to tests/unixButton.test.
1
2
3
4
5
6
7
8



9
10
11
12
13
14
15
16
17
18
19

20
21
22
23
24
25
26
1
2
3
4
5



6
7
8
9
10
11
12
13
14
15
16
17
18

19
20
21
22
23
24
25
26





-
-
-
+
+
+










-
+







# This file is a Tcl script to test the Unix specific behavior of
# labels, buttons, checkbuttons, and radiobuttons in Tk (i.e., all the
# widgets defined in tkUnixButton.c).  It is organized in the standard
# fashion for Tcl tests.
#
# Copyright (c) 1994 The Regents of the University of California.
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1994 The Regents of the University of California.
# Copyright © 1994-1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
eval tcltest::configure $argv
tcltest::loadTestedCommands
namespace import -force tcltest::test
imageInit

# Create entries in the option database to be sure that geometry options
# like border width have predictable values.
 

option add *Label.borderWidth 2
option add *Label.highlightThickness 0
option add *Label.font {Helvetica -12 bold}
option add *Button.borderWidth 2
option add *Button.highlightThickness 2
option add *Button.font {Helvetica -12 bold}
option add *Checkbutton.borderWidth 2
66
67
68
69
70
71
72
73

74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94

95
96
97
98
99
100
101
66
67
68
69
70
71
72

73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93

94
95
96
97
98
99
100
101







-
+




















-
+







    deleteWindows
    image delete image1
} -result [list 68 48 \
                74 54 \
	        [expr {72 + $bigIndicator}] 52 \
	        [expr {72 + $bigIndicator}] 52]
test unixbutton-1.2 {TkpComputeButtonGeometry procedure} -constraints {
    unix 
    unix
} -setup {
    deleteWindows
} -body {
    label .b1 -bitmap question -bd 3 -padx 0 -pady 2
    button .b2 -bitmap question -bd 3 -padx 0 -pady 2
    checkbutton .b3 -bitmap question -bd 3 -padx 1 -pady 1
    radiobutton .b4 -bitmap question -bd 3 -padx 2 -pady 0
    pack .b1 .b2 .b3 .b4
    update
    list [winfo reqwidth .b1] [winfo reqheight .b1] \
        [winfo reqwidth .b2] [winfo reqheight .b2] \
        [winfo reqwidth .b3] [winfo reqheight .b3] \
        [winfo reqwidth .b4] [winfo reqheight .b4]
} -cleanup {
    deleteWindows
} -result [list 23 33 \
	        29 39 \
	        [expr {27 + $smallIndicator}] 37 \
	        [expr {27 + $smallIndicator}] 37]
test unixbutton-1.3 {TkpComputeButtonGeometry procedure} -constraints {
    unix 
    unix
} -setup {
    deleteWindows
} -body {
    label .b1 -bitmap question -bd 3 -highlightthickness 4
    button .b2 -bitmap question -bd 3 -highlightthickness 0
    checkbutton .b3 -bitmap question -bd 3 -highlightthickness 1 \
        -indicatoron 0
188
189
190
191
192
193
194
195

196
197
198
199
200
201
202
203

204
205

206
207
208
209
210
211
212
213
214
215

216
217
218
219
220
221
222
223
224
225
226
227

228
229
230
231
232
233
234
188
189
190
191
192
193
194

195
196
197
198
199
200
201
202

203
204

205
206
207
208
209
210
211
212
213
214

215
216
217
218
219
220
221
222
223
224
225
226

227
228
229
230
231
232
233
234







-
+







-
+

-
+









-
+











-
+







        [winfo reqwidth .b2] [winfo reqheight .b2] \
        [winfo reqwidth .b3] [winfo reqheight .b3] \
        [winfo reqwidth .b4] [winfo reqheight .b4]
} -cleanup {
    deleteWindows
} -result {62 30 56 24 58 22 62 22}
test unixbutton-1.9 {TkpComputeButtonGeometry procedure} -constraints {
    unix 
    unix
} -setup {
    deleteWindows
} -body {
    button .b2 -bitmap question -default active
    list [winfo reqwidth .b2] [winfo reqheight .b2]
} -cleanup {
    deleteWindows
} -result [list [expr {17 + $defaultBorder}] [expr {27 + $defaultBorder}]] 
} -result [list [expr {17 + $defaultBorder}] [expr {27 + $defaultBorder}]]
test unixbutton-1.10 {TkpComputeButtonGeometry procedure} -constraints {
    unix 
    unix
} -setup {
    deleteWindows
} -body {
    button .b2 -bitmap question -default normal
    list [winfo reqwidth .b2] [winfo reqheight .b2]
} -cleanup {
    deleteWindows
} -result [list [expr {17 + $defaultBorder}] [expr {27 + $defaultBorder}]]
test unixbutton-1.11 {TkpComputeButtonGeometry procedure} -constraints {
    unix 
    unix
} -setup {
    deleteWindows
} -body {
    button .b2 -bitmap question -default disabled
    list [winfo reqwidth .b2] [winfo reqheight .b2]
} -cleanup {
    deleteWindows
} -result {27 37}


test unixbutton-2.1 {disabled coloring check, bug 669595} -constraints {
    unix 
    unix
} -setup {
    deleteWindows
    catch {unset value}
} -body {
    # this was just a visual bug, but at least this shows the visual
    set on 1
    set off 0
Changes to tests/unixEmbed.test.
1
2
3
4
5
6


7
8
9
10
11
12
13



14
15
16
17
18
19

20
21
22
23
24
25
26
1
2
3
4


5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

22
23
24
25
26
27
28
29




-
-
+
+







+
+
+





-
+







# This file is a Tcl script to test out the procedures in the file
# tkUnixEmbed.c.  It is organized in the standard fashion for Tcl
# tests.
#
# Copyright (c) 1996-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1996-1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
eval tcltest::configure $argv
tcltest::loadTestedCommands
namespace import -force tcltest::test

testConstraint failsOnUbuntu [expr {![info exists ::env(CI)] || ![string match Linux $::tcl_platform(os)]}]
testConstraint failsOnXQuarz [expr {$tcl_platform(os) ne "Darwin" || [tk windowingsystem] ne "x11" }]

namespace eval ::_test_tmp {}

# ------------------------------------------------------------------------------
#  Proc ::_test_tmp::testInterp
# ------------------------------------------------------------------------------
# Command that creates an unsafe child interpreter and tries to load Tk.
# Command that creates an child interpreter and tries to load Tk.
# This code is borrowed from safePrimarySelection.test
# This is necessary for loading Tktest if the tests are done in the build
# directory without installing Tk.  In that case the usual auto_path loading
# mechanism cannot work because the tk binary is not where pkgIndex.tcl says
# it is.
# ------------------------------------------------------------------------------

110
111
112
113
114
115
116
117

118
119
120
121
122
123
124
125
126
127
128
129
130

131
132
133
134
135
136
137
113
114
115
116
117
118
119

120
121
122
123
124
125
126
127
128
129
130
131
132

133
134
135
136
137
138
139
140







-
+












-
+







    wm geometry .t +0+0
    eatColors .t.t
    frame .t.f -container 1
    toplevel .x -use [winfo id .t.f]
    colorsFree .x
} -cleanup {
	deleteWindows
} -result {0}
} -result 0
test unixEmbed-1.4 {TkpUseWindow procedure, inheriting colormap} -constraints {
	unix nonPortable
} -setup {
	deleteWindows
} -body {
    toplevel .t -container 1 -colormap new
    wm geometry .t +0+0
    eatColors .t2
    toplevel .x -use [winfo id .t]
    colorsFree .x
} -cleanup {
	deleteWindows
} -result {1}
} -result 1

test unixEmbed-1.5 {TkpUseWindow procedure, creating Container records} -constraints {
	unix testembed notAqua
} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
146
147
148
149
150
151
152
153
154
155



156
157
158
159
160
161


162
163
164
165
166
167

168
169
170
171
172
173
174
149
150
151
152
153
154
155



156
157
158
159
160
161
162


163
164
165
166
167
168
169

170
171
172
173
174
175
176
177







-
-
-
+
+
+




-
-
+
+





-
+







} -cleanup {
	deleteWindows
} -result {{{XXX {} {} .t}} 0}
test unixEmbed-1.5a {TkpUseWindow procedure, creating Container records} -constraints {
    unix testembed
} -setup {
    deleteWindows
    catch {interp delete slave}
    ::_test_tmp::testInterp slave
    load {} Tktest slave
    catch {interp delete child}
    ::_test_tmp::testInterp child
    load {} Tktest child
} -body {
    frame .f1 -container 1 -width 200 -height 50
    frame .f2 -container 1 -width 200 -height 50
    pack .f1 .f2
    slave alias w winfo id .f1
    slave eval {
    child alias w winfo id .f1
    child eval {
        destroy [winfo child .]
        toplevel .t -use [w]
        list [testembed] [expr {[lindex [lindex [testembed all] 0] 0] - [w]}]
    }
} -cleanup {
    interp delete slave
    interp delete child
    deleteWindows
} -result {{{XXX {} {} .t}} 0}
test unixEmbed-1.6 {TkpUseWindow procedure, creating Container records} -constraints {
	unix testembed notAqua
} -setup {
	deleteWindows
} -body {
186
187
188
189
190
191
192
193
194
195



196
197
198
199
200
201
202



203
204
205
206
207
208
209

210
211
212
213
214
215
216
189
190
191
192
193
194
195



196
197
198
199
200
201
202



203
204
205
206
207
208
209
210
211

212
213
214
215
216
217
218
219







-
-
-
+
+
+




-
-
-
+
+
+






-
+







} -cleanup {
	deleteWindows
} -result {{XXX {} {} .t2} {XXX {} {} .t1}}
test unixEmbed-1.6a {TkpUseWindow procedure, creating Container records} -constraints {
    unix testembed
} -setup {
    deleteWindows
    catch {interp delete slave}
    ::_test_tmp::testInterp slave
    load {} Tktest slave
    catch {interp delete child}
    ::_test_tmp::testInterp child
    load {} Tktest child
} -body {
    frame .f1 -container 1 -width 200 -height 50
    frame .f2 -container 1 -width 200 -height 50
    pack .f1 .f2
    slave alias w1 winfo id .f1
    slave alias w2 winfo id .f2
    slave eval {
    child alias w1 winfo id .f1
    child alias w2 winfo id .f2
    child eval {
        destroy [winfo child .]
        toplevel .t1 -use [w1]
        toplevel .t2 -use [w2]
        testembed
    }
} -cleanup {
    interp delete slave
    interp delete child
    deleteWindows
} -result {{XXX {} {} .t2} {XXX {} {} .t1}}
test unixEmbed-1.7 {TkpUseWindow procedure, container and embedded in same app} -constraints {
	unix testembed
} -setup {
	deleteWindows
} -body {
249
250
251
252
253
254
255
256
257
258



259
260
261
262
263


264
265
266
267
268
269
270

271
272
273
274
275
276
277
252
253
254
255
256
257
258



259
260
261
262
263
264


265
266
267
268
269
270
271
272

273
274
275
276
277
278
279
280







-
-
-
+
+
+



-
-
+
+






-
+







} -cleanup {
	deleteWindows
} -result {}
test unixEmbed-2.1a {EmbeddedEventProc procedure} -constraints {
    unix testembed
} -setup {
    deleteWindows
    catch {interp delete slave}
    ::_test_tmp::testInterp slave
    load {} Tktest slave
    catch {interp delete child}
    ::_test_tmp::testInterp child
    load {} Tktest child
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    slave alias w1 winfo id .f1
    slave eval {
    child alias w1 winfo id .f1
    child eval {
        destroy [winfo child .]
        toplevel .t1 -use [w1]
        testembed
    }
    destroy .f1
    update
    slave eval {
    child eval {
        testembed
    }
} -cleanup {
    deleteWindows
} -result {}
test unixEmbed-2.2 {EmbeddedEventProc procedure} -constraints {
	unix testembed notAqua
291
292
293
294
295
296
297
298
299
300



301
302
303
304
305


306
307
308
309
310
311
312
313

314
315
316
317
318
319
320
294
295
296
297
298
299
300



301
302
303
304
305
306


307
308
309
310
311
312
313
314
315

316
317
318
319
320
321
322
323







-
-
-
+
+
+



-
-
+
+







-
+







} -cleanup {
	deleteWindows
} -result {}
test unixEmbed-2.2a {EmbeddedEventProc procedure} -constraints {
    unix testembed
} -setup {
    deleteWindows
    catch {interp delete slave}
    ::_test_tmp::testInterp slave
    load {} Tktest slave
    catch {interp delete child}
    ::_test_tmp::testInterp child
    load {} Tktest child
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    slave alias w1 winfo id .f1
    slave eval {
    child alias w1 winfo id .f1
    child eval {
        destroy [winfo child .]
        toplevel .t1 -use [w1]
        testembed
        destroy .t1
        testembed
    }
} -cleanup {
    interp delete slave
    interp delete child
    deleteWindows
} -result {}
test unixEmbed-2.3 {EmbeddedEventProc procedure} -constraints {
	unix testembed notAqua
} -setup {
	deleteWindows
} -body {
357
358
359
360
361
362
363
364
365
366



367
368
369
370

371
372

373
374
375
376
377
378
379

380
381
382
383
384
385
386
360
361
362
363
364
365
366



367
368
369
370
371
372

373
374

375
376
377
378
379
380
381

382
383
384
385
386
387
388
389







-
-
-
+
+
+



-
+

-
+






-
+







    list $x [testembed]
} -cleanup {
	deleteWindows
} -result {{{XXX .f1 {} {}}} {{XXX .f1 XXX {}}}}
test unixEmbed-3.1a {ContainerEventProc procedure, detect creation} -constraints {
    unix testembed
} -setup {
    catch {interp delete slave}
    ::_test_tmp::testInterp slave
    load {} Tktest slave
    catch {interp delete child}
    ::_test_tmp::testInterp child
    load {} Tktest child
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    slave alias w1 winfo id .f1
    child alias w1 winfo id .f1
    set x [testembed]
    slave eval {
    child eval {
        destroy [winfo child .]
        toplevel .t1 -use [w1]
        wm withdraw .t1
    }
    list $x [testembed]
} -cleanup {
    interp delete slave
    interp delete child
    deleteWindows
} -result {{{XXX .f1 {} {}}} {{XXX .f1 {} {}}}}
test unixEmbed-3.2 {ContainerEventProc procedure, set size on creation} -constraints {
	unix
} -setup {
	deleteWindows
    update
414
415
416
417
418
419
420
421
422
423



424
425
426
427
428


429
430
431
432
433
434
435
436
437

438
439
440
441
442
443
444
417
418
419
420
421
422
423



424
425
426
427
428
429


430
431
432
433
434
435
436
437
438
439

440
441
442
443
444
445
446
447







-
-
-
+
+
+



-
-
+
+








-
+







} -cleanup {
	deleteWindows
} -result {200x200+0+0}
test unixEmbed-3.3a {ContainerEventProc procedure, disallow position changes} -constraints {
    unix
} -setup {
    deleteWindows
    catch {interp delete slave}
    ::_test_tmp::testInterp slave
    load {} Tktest slave
    catch {interp delete child}
    ::_test_tmp::testInterp child
    load {} Tktest child
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    slave alias w1 winfo id .f1
    slave eval {
    child alias w1 winfo id .f1
    child eval {
        destroy [winfo child .]
        toplevel .t1 -use [w1] -bd 2 -relief raised
        update
        wm geometry .t1 +30+40
        update
        wm geometry .t1
    }
} -cleanup {
    interp delete slave
    interp delete child
    deleteWindows
} -result {200x200+0+0}
test unixEmbed-3.4 {ContainerEventProc procedure, disallow position changes} -constraints {
	unix notAqua
} -setup {
	deleteWindows
} -body {
458
459
460
461
462
463
464
465
466
467



468
469
470
471
472


473
474
475
476
477
478
479
480
481

482
483
484
485
486
487
488
461
462
463
464
465
466
467



468
469
470
471
472
473


474
475
476
477
478
479
480
481
482
483

484
485
486
487
488
489
490
491







-
-
-
+
+
+



-
-
+
+








-
+







} -cleanup {
	deleteWindows
} -result {300x100+0+0}
test unixEmbed-3.4a {ContainerEventProc procedure, disallow position changes} -constraints {
    unix
} -setup {
    deleteWindows
    catch {interp delete slave}
    ::_test_tmp::testInterp slave
    load {} Tktest slave
    catch {interp delete child}
    ::_test_tmp::testInterp child
    load {} Tktest child
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    slave alias w1 winfo id .f1
    slave eval {
    child alias w1 winfo id .f1
    child eval {
        destroy [winfo child .]
        toplevel .t1 -use [w1]
        update
        wm geometry .t1 300x100+30+40
        update
        wm geometry .t1
    }
} -cleanup {
    interp delete slave
    interp delete child
    deleteWindows
} -result {300x100+0+0}
test unixEmbed-3.5 {ContainerEventProc procedure, geometry requests} -constraints {
	unix notAqua
} -setup {
	deleteWindows
} -body {
502
503
504
505
506
507
508
509
510
511



512
513
514
515
516


517
518
519
520
521
522

523
524

525
526
527
528
529
530
531
505
506
507
508
509
510
511



512
513
514
515
516
517


518
519
520
521
522
523
524

525
526

527
528
529
530
531
532
533
534







-
-
-
+
+
+



-
-
+
+





-
+

-
+







} -cleanup {
	deleteWindows
} -result {300 80 300x80+0+0}
test unixEmbed-3.5a {ContainerEventProc procedure, geometry requests} -constraints {
    unix
} -setup {
    deleteWindows
    catch {interp delete slave}
    ::_test_tmp::testInterp slave
    load {} Tktest slave
    catch {interp delete child}
    ::_test_tmp::testInterp child
    load {} Tktest child
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    slave alias w1 winfo id .f1
    slave eval {
    child alias w1 winfo id .f1
    child eval {
        destroy [winfo child .]
        toplevel .t1 -use [w1]
        .t1 configure -width 300 -height 80
        update
    }
    list [winfo width .f1] [winfo height .f1] [slave eval {wm geometry .t1}]
    list [winfo width .f1] [winfo height .f1] [child eval {wm geometry .t1}]
} -cleanup {
    interp delete slave
    interp delete child
    deleteWindows
} -result {300 80 300x80+0+0}
test unixEmbed-3.6 {ContainerEventProc procedure, map requests} -constraints {
	unix notAqua
} -setup {
	deleteWindows
} -body {
547
548
549
550
551
552
553
554
555
556



557
558
559
560
561


562
563
564
565
566
567
568
569
570
571
572

573
574
575
576
577
578
579
550
551
552
553
554
555
556



557
558
559
560
561
562


563
564
565
566
567
568
569
570
571
572
573
574

575
576
577
578
579
580
581
582







-
-
-
+
+
+



-
-
+
+










-
+







} -cleanup {
	deleteWindows
} -result {mapped}
test unixEmbed-3.6a {ContainerEventProc procedure, map requests} -constraints {
    unix
} -setup {
    deleteWindows
    catch {interp delete slave}
    ::_test_tmp::testInterp slave
    load {} Tktest slave
    catch {interp delete child}
    ::_test_tmp::testInterp child
    load {} Tktest child
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    slave alias w1 winfo id .f1
    slave eval {
    child alias w1 winfo id .f1
    child eval {
        destroy [winfo child .]
        toplevel .t1 -use [w1]
        set x unmapped
        bind .t1 <Map> {set x mapped}
        update
        after 100
        update
        set x
    }
} -cleanup {
    interp delete slave
    interp delete child
    deleteWindows
} -result {mapped}
test unixEmbed-3.7 {ContainerEventProc procedure, destroy events} -constraints {
	unix notAqua
} -setup {
	deleteWindows
} -body {
595
596
597
598
599
600
601
602
603
604



605
606
607
608

609
610
611

612
613
614
615
616
617
618
619
620

621
622
623
624
625
626
627
598
599
600
601
602
603
604



605
606
607
608
609
610

611
612
613

614
615
616
617
618
619
620
621
622

623
624
625
626
627
628
629
630







-
-
-
+
+
+



-
+


-
+








-
+







} -cleanup {
	deleteWindows
} -result {dead 0}
test unixEmbed-3.7a {ContainerEventProc procedure, destroy events} -constraints {
    unix
} -setup {
    deleteWindows
    catch {interp delete slave}
    ::_test_tmp::testInterp slave
    load {} Tktest slave
    catch {interp delete child}
    ::_test_tmp::testInterp child
    load {} Tktest child
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    slave alias w1 winfo id .f1
    child alias w1 winfo id .f1
    bind .f1 <Destroy> {set x dead}
    set x alive
    slave eval {
    child eval {
        destroy [winfo child .]
        toplevel .t1 -use [w1]
        update
        destroy .t1
    }
    update
    list $x [winfo exists .f1]
} -cleanup {
    interp delete slave
    interp delete child
    deleteWindows
} -result {dead 0}

test unixEmbed-4.1 {EmbedStructureProc procedure, configure events} -constraints {
	unix notAqua
} -setup {
	deleteWindows
644
645
646
647
648
649
650
651
652
653



654
655
656
657
658


659
660
661
662
663
664
665
666
667

668
669
670
671
672
673
674
647
648
649
650
651
652
653



654
655
656
657
658
659


660
661
662
663
664
665
666
667
668
669

670
671
672
673
674
675
676
677







-
-
-
+
+
+



-
-
+
+








-
+







} -cleanup {
	deleteWindows
} -result {180x100+0+0}
test unixEmbed-4.1a {EmbedStructureProc procedure, configure events} -constraints {
    unix
} -setup {
    deleteWindows
    catch {interp delete slave}
    ::_test_tmp::testInterp slave
    load {} Tktest slave
    catch {interp delete child}
    ::_test_tmp::testInterp child
    load {} Tktest child
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    slave alias w1 winfo id .f1
    slave eval {
    child alias w1 winfo id .f1
    child eval {
        destroy [winfo child .]
        toplevel .t1 -use [w1]
        update
        .t1 configure -width 180 -height 100
        update
        winfo geometry .t1
    }
} -cleanup {
    interp delete slave
    interp delete child
    deleteWindows
} -result {180x100+0+0}
test unixEmbed-4.2 {EmbedStructureProc procedure, destroy events} -constraints {
	unix testembed notAqua
} -setup {
	deleteWindows
} -body {
687
688
689
690
691
692
693
694
695
696



697
698
699
700
701
702


703
704
705
706
707
708
709
710

711
712
713
714
715
716
717
690
691
692
693
694
695
696



697
698
699
700
701
702
703


704
705
706
707
708
709
710
711
712

713
714
715
716
717
718
719
720







-
-
-
+
+
+




-
-
+
+







-
+







} -cleanup {
	deleteWindows
} -result {{{XXX .f1 XXX {}}} {}}
test unixEmbed-4.2a {EmbedStructureProc procedure, destroy events} -constraints {
    unix testembed
} -setup {
    deleteWindows
    catch {interp delete slave}
    ::_test_tmp::testInterp slave
    load {} Tktest slave
    catch {interp delete child}
    ::_test_tmp::testInterp child
    load {} Tktest child
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    update
    slave alias w1 winfo id .f1
    slave eval {
    child alias w1 winfo id .f1
    child eval {
        destroy [winfo child .]
        toplevel .t1 -use [w1]
    }
    set x [testembed]
    destroy .f1
    list $x [testembed]
} -cleanup {
    interp delete slave
    interp delete child
    deleteWindows
} -result "{{XXX .f1 {} {}}} {}"


test unixEmbed-5.1 {EmbedFocusProc procedure, FocusIn events} -constraints {
	unix notAqua
} -setup {
733
734
735
736
737
738
739
740
741
742



743
744
745
746
747


748
749
750
751
752
753
754
755
756
757

758
759

760
761
762
763
764
765
766
736
737
738
739
740
741
742



743
744
745
746
747
748


749
750
751
752
753
754
755
756
757
758
759

760
761

762
763
764
765
766
767
768
769







-
-
-
+
+
+



-
-
+
+









-
+

-
+







} -cleanup {
	deleteWindows
} -result {{focus in .t1}}
test unixEmbed-5.1a {EmbedFocusProc procedure, FocusIn events} -constraints {
    unix
} -setup {
    deleteWindows
    catch {interp delete slave}
    ::_test_tmp::testInterp slave
    load {} Tktest slave
    catch {interp delete child}
    ::_test_tmp::testInterp child
    load {} Tktest child
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    slave alias w1 winfo id .f1
    slave eval {
    child alias w1 winfo id .f1
    child eval {
        destroy [winfo child .]
        toplevel .t1 -use [w1]
        bind .t1 <FocusIn> {lappend x "focus in %W"}
        bind .t1 <FocusOut> {lappend x "focus out %W"}
        update
        set x {}
    }
    focus -force .f1
    update
    slave eval {set x}
    child eval {set x}
} -cleanup {
    interp delete slave
    interp delete child
    deleteWindows
} -result {{focus in .t1}}
test unixEmbed-5.2 {EmbedFocusProc procedure, focusing on dead window} -constraints {
	unix notAqua
} -setup {
	deleteWindows
} -body {
781
782
783
784
785
786
787
788
789
790



791
792
793
794
795


796
797
798
799
800
801
802
803
804
805

806
807
808
809
810
811
812
784
785
786
787
788
789
790



791
792
793
794
795
796


797
798
799
800
801
802
803
804
805
806
807

808
809
810
811
812
813
814
815







-
-
-
+
+
+



-
-
+
+









-
+







} -cleanup {
	deleteWindows
} -result {}
test unixEmbed-5.2a {EmbedFocusProc procedure, focusing on dead window} -constraints {
    unix
} -setup {
    deleteWindows
    catch {interp delete slave}
    ::_test_tmp::testInterp slave
    load {} Tktest slave
    catch {interp delete child}
    ::_test_tmp::testInterp child
    load {} Tktest child
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    slave alias w1 winfo id .f1
    slave eval {
    child alias w1 winfo id .f1
    child eval {
        destroy [winfo child .]
        toplevel .t1 -use [w1]
        update
        after 200 {destroy .t1}
    }
    after 400
    focus -force .f1
    update
} -cleanup {
    interp delete slave
    interp delete child
    deleteWindows
} -result {}
test unixEmbed-5.3 {EmbedFocusProc procedure, FocusOut events} -constraints {
	unix notAqua
} -setup {
	deleteWindows
} -body {
829
830
831
832
833
834
835
836
837
838



839
840
841
842
843


844
845
846
847
848
849
850
851
852
853

854
855
856

857
858

859
860
861
862
863
864
865
832
833
834
835
836
837
838



839
840
841
842
843
844


845
846
847
848
849
850
851
852
853
854
855

856
857
858

859
860

861
862
863
864
865
866
867
868







-
-
-
+
+
+



-
-
+
+









-
+


-
+

-
+







} -cleanup {
	deleteWindows
} -result {{{focus in .t1}} {{focus in .t1} {focus out .t1}}}
test unixEmbed-5.3a {EmbedFocusProc procedure, FocusOut events} -constraints {
    unix
} -setup {
    deleteWindows
    catch {interp delete slave}
    ::_test_tmp::testInterp slave
    load {} Tktest slave
    catch {interp delete child}
    ::_test_tmp::testInterp child
    load {} Tktest child
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    slave alias w1 winfo id .f1
    slave eval {
    child alias w1 winfo id .f1
    child eval {
        destroy [winfo child .]
        toplevel .t1 -use [w1]
        set x {}
        bind .t1 <FocusIn> {lappend x "focus in %W"}
        bind .t1 <FocusOut> {lappend x "focus out %W"}
        update
    }
    focus -force .f1
    update
    set x [slave eval {update; set x }]
    set x [child eval {update; set x }]
    focus .
    update
    list $x [slave eval {update; set x}]
    list $x [child eval {update; set x}]
} -cleanup {
    interp delete slave
    interp delete child
    deleteWindows
} -result {{{focus in .t1}} {{focus in .t1} {focus out .t1}}}


test unixEmbed-6.1 {EmbedGeometryRequest procedure, window changes size} -constraints {
	unix notAqua
} -setup {
881
882
883
884
885
886
887
888
889
890



891
892
893
894
895


896
897
898
899
900
901
902
903
904
905
906

907
908
909
910
911
912
913
884
885
886
887
888
889
890



891
892
893
894
895
896


897
898
899
900
901
902
903
904
905
906
907
908

909
910
911
912
913
914
915
916







-
-
-
+
+
+



-
-
+
+










-
+







} -cleanup {
	deleteWindows
} -result {{{configure .t1 300 120}} 300x120+0+0}
test unixEmbed-6.1a {EmbedGeometryRequest procedure, window changes size} -constraints {
    unix
} -setup {
    deleteWindows
    catch {interp delete slave}
    ::_test_tmp::testInterp slave
    load {} Tktest slave
    catch {interp delete child}
    ::_test_tmp::testInterp child
    load {} Tktest child
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    slave alias w1 winfo id .f1
    slave eval {
    child alias w1 winfo id .f1
    child eval {
        destroy [winfo child .]
        toplevel .t1 -use [w1]
        update
        bind .t1 <Configure> {set x {configure .t1 %w %h}}
        set x {}
        .t1 configure -width 300 -height 120
        update
        list $x [winfo geom .t1]
    }
} -cleanup {
    interp delete slave
    interp delete child
    deleteWindows
} -result {{configure .t1 300 120} 300x120+0+0}
test unixEmbed-6.2 {EmbedGeometryRequest procedure, window changes size} -constraints {
	unix notAqua
} -setup {
	deleteWindows
} -body {
927
928
929
930
931
932
933
934
935
936



937
938
939
940
941
942


943
944
945
946
947
948
949
950
951
952
953

954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973

974
975
976
977

978
979

980
981
982
983
984
985
986

987
988
989
990
991

992
993
994
995
996



997
998
999
1000
1001
1002


1003
1004
1005
1006
1007

1008
1009

1010
1011

1012
1013

1014
1015
1016
1017
1018
1019

1020
1021

1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038

1039
1040
1041
1042

1043
1044

1045
1046
1047
1048
1049
1050
1051

1052
1053
1054
1055
1056
1057
1058
1059



1060
1061
1062
1063
1064


1065
1066
1067
1068
1069
1070
1071

1072
1073

1074
1075

1076
1077

1078
1079
1080
1081
1082
1083

1084
1085

1086
1087
1088
1089

1090
1091
1092
1093
1094
1095
1096
930
931
932
933
934
935
936



937
938
939
940
941
942
943


944
945
946
947
948
949
950
951
952
953
954
955

956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975

976
977
978
979

980
981

982
983
984
985
986
987
988

989
990
991
992
993

994
995
996



997
998
999
1000
1001
1002
1003


1004
1005
1006
1007
1008
1009

1010
1011

1012
1013

1014
1015

1016
1017
1018
1019
1020
1021

1022
1023

1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040

1041
1042
1043
1044

1045
1046

1047
1048
1049
1050
1051
1052
1053

1054
1055
1056
1057
1058
1059



1060
1061
1062
1063
1064
1065


1066
1067
1068
1069
1070
1071
1072
1073

1074
1075

1076
1077

1078
1079

1080
1081
1082
1083
1084
1085

1086
1087

1088
1089
1090
1091

1092
1093
1094
1095
1096
1097
1098
1099







-
-
-
+
+
+




-
-
+
+










-
+



















-
+



-
+

-
+






-
+




-
+


-
-
-
+
+
+




-
-
+
+




-
+

-
+

-
+

-
+





-
+

-
+
















-
+



-
+

-
+






-
+





-
-
-
+
+
+



-
-
+
+






-
+

-
+

-
+

-
+





-
+

-
+



-
+







} -cleanup {
	deleteWindows
} -result {{{configure .t1 200 200}} 200x200+0+0}
test unixEmbed-6.2a {EmbedGeometryRequest procedure, window changes size} -constraints {
    unix
} -setup {
    deleteWindows
    catch {interp delete slave}
    ::_test_tmp::testInterp slave
    load {} Tktest slave
    catch {interp delete child}
    ::_test_tmp::testInterp child
    load {} Tktest child
} -body {
    frame .f1 -container 1 -width 200 -height 50
    place .f1 -width 200 -height 200
    update
    slave alias w1 winfo id .f1
    slave eval {
    child alias w1 winfo id .f1
    child eval {
        destroy [winfo child .]
        toplevel .t1 -use [w1]
        update
        bind .t1 <Configure> {set x {configure .t1 %w %h}}
	set x {}
        .t1 configure -width 300 -height 120
        update
        list $x [winfo geom .t1]
    }
} -cleanup {
    interp delete slave
    interp delete child
    deleteWindows
} -result {{configure .t1 200 200} 200x200+0+0}

# Can't think up any tests for TkpGetOtherWindow procedure.

test unixEmbed-7.1 {TkpRedirectKeyEvent procedure, forward keystroke} -constraints {
	unix notAqua
} -setup {
	deleteWindows
} -body {
    deleteWindows
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    dobg "set w1 [winfo id .f1]"
    dobg {
	    eval destroy [winfo child .]
	    toplevel .t1 -use $w1
    }
    focus -force .
    bind . <KeyPress> {lappend x {key %A %E}}
    bind . <Key> {lappend x {key %A %E}}
    set x {}
    set y [dobg {
	    update
	    bind .t1 <KeyPress> {lappend y {key %A}}
	    bind .t1 <Key> {lappend y {key %A}}
	    set y {}
	    event generate .t1 <KeyPress> -keysym a
	    event generate .t1 <Key> -keysym a
	    set y
    }]
    update
    list $x $y
} -cleanup {
	deleteWindows
    bind . <KeyPress> {}
    bind . <Key> {}
} -result {{{key a 1}} {}}
# TkpRedirectKeyEvent is not implemented in win or aqua.  If someone
# implements it they should change the constraints for this test.
test unixEmbed-7.1a {TkpRedirectKeyEvent procedure, forward keystroke} -constraints {
    unix notAqua
    unix notAqua failsOnXQuarz
} -setup {
    deleteWindows
    catch {interp delete slave}
    ::_test_tmp::testInterp slave
    load {} Tktest slave
    catch {interp delete child}
    ::_test_tmp::testInterp child
    load {} Tktest child
} -body {
    deleteWindows
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    slave alias w1 winfo id .f1
    slave eval {
    child alias w1 winfo id .f1
    child eval {
        destroy [winfo child .]
        toplevel .t1 -use [w1]
    }
    focus -force .
    bind . <KeyPress> {lappend x {key %A %E}}
    bind . <Key> {lappend x {key %A %E}}
    set x {}
    set y [slave eval {
    set y [child eval {
        update
        bind .t1 <KeyPress> {lappend y {key %A}}
        bind .t1 <Key> {lappend y {key %A}}
        set y {}
        event generate .t1 <KeyPress> -keysym a
        event generate .t1 <Key> -keysym a
        set y
    }]
    update
    list $x $y
} -cleanup {
    interp delete slave
    interp delete child
    deleteWindows
    bind . <KeyPress> {}
    bind . <Key> {}
} -result {{{key a 1}} {}}
test unixEmbed-7.2 {TkpRedirectKeyEvent procedure, don't forward keystroke width} -constraints {
	unix notAqua
} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    dobg "set w1 [winfo id .f1]"
    dobg {
	    eval destroy [winfo child .]
	    toplevel .t1 -use $w1
    }
    update
    focus -force .f1
    update
    bind . <KeyPress> {lappend x {key %A}}
    bind . <Key> {lappend x {key %A}}
    set x {}
    set y [dobg {
	    update
	    bind .t1 <KeyPress> {lappend y {key %A}}
	    bind .t1 <Key> {lappend y {key %A}}
	    set y {}
	    event generate .t1 <KeyPress> -keysym b
	    event generate .t1 <Key> -keysym b
	    set y
    }]
    update
    list $x $y
} -cleanup {
	deleteWindows
    bind . <KeyPress> {}
    bind . <Key> {}
} -result {{} {{key b}}}
test unixEmbed-7.2a {TkpRedirectKeyEvent procedure, don't forward keystroke width} -constraints {
    unix
} -setup {
    deleteWindows
    catch {interp delete slave}
    ::_test_tmp::testInterp slave
    load {} Tktest slave
    catch {interp delete child}
    ::_test_tmp::testInterp child
    load {} Tktest child
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    slave alias w1 winfo id .f1
    slave eval {
    child alias w1 winfo id .f1
    child eval {
        destroy [winfo child .]
        toplevel .t1 -use [w1]
    }
    update
    focus -force .f1
    update
    bind . <KeyPress> {lappend x {key %A}}
    bind . <Key> {lappend x {key %A}}
    set x {}
    set y [slave eval {
    set y [child eval {
        update
        bind .t1 <KeyPress> {lappend y {key %A}}
        bind .t1 <Key> {lappend y {key %A}}
        set y {}
        event generate .t1 <KeyPress> -keysym b
        event generate .t1 <Key> -keysym b
        set y
    }]
    update
    list $x $y
} -cleanup {
    interp delete slave
    interp delete child
    deleteWindows
    bind . <KeyPress> {}
    bind . <Key> {}
} -result {{} {{key b}}}

test unixEmbed-8.1 {TkpClaimFocus procedure} -constraints {
    unix notAqua
    unix notAqua failsOnUbuntu failsOnXQuarz
} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    frame .f2 -width 200 -height 50
    pack .f1 .f2
    dobg "set w1 [winfo id .f1]"
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118



1119
1120
1121
1122
1123
1124
1125


1126
1127
1128
1129
1130
1131
1132

1133
1134
1135
1136
1137
1138
1139

1140
1141
1142
1143
1144
1145
1146
1112
1113
1114
1115
1116
1117
1118



1119
1120
1121
1122
1123
1124
1125
1126


1127
1128
1129
1130
1131
1132
1133
1134

1135
1136
1137
1138
1139
1140
1141

1142
1143
1144
1145
1146
1147
1148
1149







-
-
-
+
+
+





-
-
+
+






-
+






-
+







	    lappend x [focus]
    }] [focus]
} -cleanup {
	deleteWindows
} -result {{{} .t1} .f1}
test unixEmbed-8.1a {TkpClaimFocus procedure} -constraints unix -setup {
    deleteWindows
    catch {interp delete slave}
    ::_test_tmp::testInterp slave
    load {} Tktest slave
    catch {interp delete child}
    ::_test_tmp::testInterp child
    load {} Tktest child
} -body {
    frame .f1 -container 1 -width 200 -height 50
    frame .f2 -width 200 -height 50
    pack .f1 .f2
    update
    slave alias w1 winfo id .f1
    slave eval {
    child alias w1 winfo id .f1
    child eval {
        destroy [winfo child .]
        toplevel .t1 -use [w1] -highlightthickness 2 -bd 2 -relief sunken
    }
    # This should clear focus from the application embedded in .f1
    focus -force .f2
    update
    list [slave eval {
    list [child eval {
        set x [list [focus]]
        focus .t1
	update
        lappend x [focus]
    }] [focus]
} -cleanup {
    interp delete slave
    interp delete child
    deleteWindows
} -result {{{} .t1} .f1}
test unixEmbed-8.2 {TkpClaimFocus procedure} -constraints unix -setup {
    deleteWindows
    catch {interp delete child}
    interp create child
} -body {
1184
1185
1186
1187
1188
1189
1190
1191

1192
1193

1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216



1217
1218
1219
1220
1221


1222
1223
1224
1225
1226
1227
1228
1229
1230

1231
1232
1233
1234
1235
1236

1237
1238

1239
1240
1241
1242
1243

1244
1245

1246
1247

1248
1249
1250
1251
1252
1253

1254
1255

1256
1257
1258

1259
1260

1261
1262

1263
1264
1265
1266
1267
1268
1269

1270
1271

1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285

1286
1287

1288
1289
1290
1291
1292
1293
1294
1187
1188
1189
1190
1191
1192
1193

1194
1195

1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216



1217
1218
1219
1220
1221
1222


1223
1224
1225
1226
1227
1228
1229
1230
1231
1232

1233
1234
1235
1236
1237
1238

1239
1240

1241
1242
1243

1244

1245
1246

1247
1248

1249
1250
1251
1252
1253
1254

1255
1256

1257
1258
1259
1260
1261
1262

1263
1264

1265
1266
1267
1268
1269
1270
1271

1272
1273

1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287

1288
1289

1290
1291
1292
1293
1294
1295
1296
1297







-
+

-
+




















-
-
-
+
+
+



-
-
+
+








-
+





-
+

-
+


-

-
+

-
+

-
+





-
+

-
+



+

-
+

-
+






-
+

-
+













-
+

-
+







	    lappend x [testembed]
    }
    set x
} -cleanup {
	deleteWindows
} -result {{{XXX .f4 {} {}} {XXX .f3 {} {}} {XXX .f2 {} {}} {XXX .f1 {} {}}} {{XXX .f4 {} {}} {XXX .f2 {} {}} {XXX .f1 {} {}}} {{XXX .f2 {} {}} {XXX .f1 {} {}}} {{XXX .f2 {} {}}} {}}
test unixEmbed-9.2 {EmbedWindowDeleted procedure, check embeddedPtr} -constraints {
	unix testembed notAqua
    unix testembed notAqua
} -setup {
	deleteWindows
    deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    update
    dobg "set w1 [winfo id .f1]"
    dobg {
	    eval destroy [winfo child .]
	    toplevel .t1 -use $w1 -highlightthickness 2 -bd 2 -relief sunken
	    set x {}
	    lappend x [testembed]
	    destroy .t1
	    lappend x [testembed]
    }
} -cleanup {
	deleteWindows
} -result {{{XXX {} {} .t1}} {}}
test unixEmbed-9.2a {EmbedWindowDeleted procedure, check embeddedPtr} -constraints {
    unix testembed
} -setup {
    deleteWindows
    catch {interp delete slave}
    ::_test_tmp::testInterp slave
    load {} Tktest slave
    catch {interp delete child}
    ::_test_tmp::testInterp child
    load {} Tktest child
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    slave alias w1 winfo id .f1
    slave eval {
    child alias w1 winfo id .f1
    child eval {
        destroy [winfo child .]
        toplevel .t1 -use [w1] -highlightthickness 2 -bd 2 -relief sunken
        set x {}
        lappend x [testembed]
        destroy .t1
        lappend x [testembed]
    }
} -cleanup {
    interp delete slave
    interp delete child
    deleteWindows
} -result {{{XXX {} {} .t1}} {}}


test unixEmbed-10.1 {geometry propagation in tkUnixWm.c/UpdateGeometryInfo} -constraints {
	unix
    unix failsOnUbuntu failsOnXQuarz
} -setup {
	deleteWindows
    deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    update
    pack .f1
    update
    update idletasks
    toplevel .t1 -use [winfo id .f1] -width 150 -height 80
    update
    update idletasks
    wm geometry .t1 +40+50
    update
    update idletasks
    wm geometry .t1
} -cleanup {
	deleteWindows
} -result {150x80+0+0}
test unixEmbed-10.2 {geometry propagation in tkUnixWm.c/UpdateGeometryInfo} -constraints {
	unix
    unix failsOnUbuntu failsOnXQuarz
} -setup {
	deleteWindows
    deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    update idletasks
    toplevel .t1 -use [winfo id .f1] -width 150 -height 80
    update
    update idletasks
    wm geometry .t1 70x300+10+20
    update
    update idletasks
    wm geometry .t1
} -cleanup {
	deleteWindows
} -result {70x300+0+0}

test unixEmbed-11.1 {focus -force works for embedded toplevels} -constraints {
	unix
    unix
} -setup {
	deleteWindows
    deleteWindows
} -body {
    toplevel .t
    pack [frame .t.f -container 1 -width 200 -height 200] -fill both
    update idletasks
    toplevel .embed -use [winfo id .t.f] -bg green
    update idletasks
    focus -force .t
    focus -force .embed
    focus
} -cleanup {
    deleteWindows
} -result .embed
test unixEmbed-11.2 {mouse coordinates in embedded toplevels} -constraints {
	unix pressbutton
    unix pressbutton
} -setup {
	deleteWindows
    deleteWindows
} -body {
    toplevel .main
    set result {}
    pack [button .main.b -text "Main Button" \
	      -command {lappend result ".main.b"}] -padx 30 -pady 30
    pack [frame .main.f -container 1 -width 200 -height 200] -fill both
    update idletasks
Changes to tests/unixFont.test.
1
2
3
4
5
6
7
8
9
10
11
12


13
14
15

16
17




18
19
20
21
22
23
24
1
2
3
4
5
6
7
8
9
10


11
12
13
14

15
16
17
18
19
20
21
22
23
24
25
26
27
28










-
-
+
+


-
+


+
+
+
+







# This file is a Tcl script to test out the procedures in tkUnixFont.c.
# It is organized in the standard fashion for Tcl tests.
#
# Many of these tests are visually oriented and cannot be checked
# programmatically (such as "does an underlined font appear to be
# underlined?"); these tests attempt to exercise the code in question,
# but there are no results that can be checked.  Some tests depend on the
# fonts having or not having certain properties, which may not be valid
# at all sites.
#
# Copyright (c) 1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.1
package require tcltest 2.2
eval tcltest::configure $argv
tcltest::loadTestedCommands

testConstraint failsOnUbuntu [expr {![info exists ::env(CI)] || ![string match Linux $::tcl_platform(os)]}]
testConstraint failsOnUbuntuNoXft [expr {[testConstraint failsOnUbuntu] || (![catch {tk::pkgconfig get fontsystem} fs] && ($fs eq "xft"))}]
testConstraint failsOnXQuarz [expr {$tcl_platform(os) ne "Darwin" || [tk windowingsystem] ne "x11" }]

if {[tk windowingsystem] eq "x11"} {
    set xlsf [auto_execok xlsfonts]
}
foreach {constraint font} {
    hasArial	arial
    hasCourierNew	"courier new"
65
66
67
68
69
70
71
72

73
74

75
76
77
78
79
80
81

82
83
84
85
86
87
88

89
90
91
92
93
94
95

96
97
98
99
100
101
102
103
104
105

106
107
108
109
110
111

112
113
114

115
116
117

118
119

120
121
122
123
124
125
126
69
70
71
72
73
74
75

76
77

78
79
80
81
82
83
84

85
86
87
88
89
90
91

92
93
94
95
96
97
98

99
100
101
102
103
104
105
106
107
108

109
110
111
112
113
114

115
116
117

118
119
120

121
122

123
124
125
126
127
128
129
130







-
+

-
+






-
+






-
+






-
+









-
+





-
+


-
+


-
+

-
+







    update
    return "[winfo reqwidth .b.l] [winfo reqheight .b.l]"
}

test unixfont-1.1 {TkpGetNativeFont procedure: not native} {x11 noExceed} {
    list [catch {font measure {} xyz} msg] $msg
} {1 {font "" doesn't exist}}
test unixfont-1.2 {TkpGetNativeFont procedure: native} x11 {
test unixfont-1.2 {TkpGetNativeFont procedure: native} {x11 failsOnUbuntu} {
    font measure fixed 0
} {6}
} 6

test unixfont-2.1 {TkpGetFontFromAttributes procedure: no family} x11 {
    font actual {-size 10}
    set x {}
} {}
test unixfont-2.2 {TkpGetFontFromAttributes procedure: Times relatives} \
	{x11 noExceed hasTimesNew} {
	{x11 noExceed hasTimesNew failsOnUbuntu} {
    set x {}
    lappend x [lindex [font actual {-family "Times New Roman"}] 1]
    lappend x [lindex [font actual {-family "New York"}] 1]
    lappend x [lindex [font actual {-family "Times"}] 1]
} {times times times}
test unixfont-2.3 {TkpGetFontFromAttributes procedure: Courier relatives} \
	{x11 noExceed hasCourierNew} {
	{x11 noExceed hasCourierNew failsOnUbuntu} {
    set x {}
    lappend x [lindex [font actual {-family "Courier New"}] 1]
    lappend x [lindex [font actual {-family "Monaco"}] 1]
    lappend x [lindex [font actual {-family "Courier"}] 1]
} {courier courier courier}
test unixfont-2.4 {TkpGetFontFromAttributes procedure: Helvetica relatives} \
	{x11 noExceed hasArial} {
	{x11 noExceed hasArial failsOnUbuntu} {
    set x {}
    lappend x [lindex [font actual {-family "Arial"}] 1]
    lappend x [lindex [font actual {-family "Geneva"}] 1]
    lappend x [lindex [font actual {-family "Helvetica"}] 1]
} {helvetica helvetica helvetica}
test unixfont-2.5 {TkpGetFontFromAttributes procedure: fallback} x11 {
    font actual {-xyz-xyz-*-*-*-*-*-*-*-*-*-*-*-*}
    set x {}
} {}
test unixfont-2.6 {TkpGetFontFromAttributes: fallback to fixed family} x11 {
test unixfont-2.6 {TkpGetFontFromAttributes: fallback to fixed family} {x11 failsOnUbuntu} {
    lindex [font actual {-family fixed -size 10}] 1
} {fixed}
test unixfont-2.7 {TkpGetFontFromAttributes: fixed family not available!} x11 {
    # no test available
} {}
test unixfont-2.8 {TkpGetFontFromAttributes: loop over returned font names} x11 {
test unixfont-2.8 {TkpGetFontFromAttributes: loop over returned font names} {x11 failsOnUbuntu} {
    lindex [font actual {-family fixed -size 31}] 1
} {fixed}
test unixfont-2.9 {TkpGetFontFromAttributes: reject adobe courier if possible} {x11 noExceed} {
test unixfont-2.9 {TkpGetFontFromAttributes: reject adobe courier if possible} {x11 noExceed failsOnUbuntu} {
    lindex [font actual {-family courier}] 1
} {courier}
test unixfont-2.10 {TkpGetFontFromAttributes: scalable font found} x11 {
test unixfont-2.10 {TkpGetFontFromAttributes: scalable font found} {x11 failsOnUbuntuNoXft} {
    lindex [font actual {-family courier -size 37}] 3
} {37}
} 37
test unixfont-2.11 {TkpGetFontFromAttributes: font cannot be loaded} x11 {
    # On Linux, XListFonts() was returning names for fonts that do not
    # actually exist, causing the subsequent XLoadQueryFont() to fail
    # unexpectedly.  Now falls back to another font if that happens.

    font actual {-size 14}
    set x {}
162
163
164
165
166
167
168
169

170
171
172
173

174
175
176
177

178
179
180
181
182
183
184
185
186
187
188
189

190
191
192
193
194
195
196
166
167
168
169
170
171
172

173
174
175
176

177
178
179
180

181
182
183
184
185
186
187
188
189
190
191
192

193
194
195
196
197
198
199
200







-
+



-
+



-
+











-
+







    .b.l config -text "000000 00000"
    getsize
} "[expr $ax*6] [expr $ay*2]"
test unixfont-5.7 {Tk_MeasureChars procedure: already saw space in line} x11 {
    .b.l config -text "000000     00000"
    getsize
} "[expr $ax*6] [expr $ay*2]"
test unixfont-5.8 {Tk_MeasureChars procedure: internal spaces significant} x11 {
test unixfont-5.8 {Tk_MeasureChars procedure: internal spaces significant} {x11 failsOnUbuntu} {
    .b.l config -text "00  000     00000"
    getsize
} "[expr $ax*7] [expr $ay*2]"
test unixfont-5.9 {Tk_MeasureChars procedure: TK_PARTIAL_OK} x11 {
test unixfont-5.9 {Tk_MeasureChars procedure: TK_PARTIAL_OK} {x11 failsOnUbuntu} {
    .b.c dchars $t 0 end
    .b.c insert $t 0 "0000"
    .b.c index $t @[expr int($ax*2.5)],1
} {2}
} 2
test unixfont-5.10 {Tk_MeasureChars procedure: TK_AT_LEAST_ONE} x11 {
    .b.l config -text "000000000000"
    getsize
} "[expr $ax*10] [expr $ay*2]"
test unixfont-5.11 {Tk_MeasureChars: TK_AT_LEAST_ONE + not even one char fit!} x11 {
    set a [.b.l cget -wrap]
    .b.l config -text "000000" -wrap 1
    set x [getsize]
    .b.l config -wrap $a
    set x
} "$ax [expr $ay*6]"
test unixfont-5.12 {Tk_MeasureChars procedure: include eol spaces} x11 {
test unixfont-5.12 {Tk_MeasureChars procedure: include eol spaces} {x11 failsOnUbuntu} {
    .b.l config -text "000   \n000"
    getsize
} "[expr $ax*6] [expr $ay*2]"

test unixfont-6.1 {Tk_DrawChars procedure: loop test} x11 {
    .b.l config -text "a"
    update
239
240
241
242
243
244
245
246

247
248
249
250
251
252
253
254
255
256

257
258

259
260
261
262
263
264
265
266
267


268
269
270
271
272
273
274
243
244
245
246
247
248
249

250
251
252
253
254
255
256
257
258
259

260
261

262
263
264
265
266
267
268
269


270
271
272
273
274
275
276
277
278







-
+









-
+

-
+







-
-
+
+







    font configure xyz -family times
    update
    destroy .c
    font delete xyz
} {}
test unixfont-8.2 {AllocFont procedure: parse information from XLFD} x11 {
    expr {[lindex [font actual {-family times -size 0}] 3] == 0}
} {0}
} 0
test unixfont-8.3 {AllocFont procedure: can't parse info from name} x11 {
    catch {unset fontArray}
    # check that font actual returns the correct attributes.
    # the values of those attributes are system dependent.
    array set fontArray [font actual a12biluc]
    set result [lsort [array names fontArray]]
    catch {unset fontArray}
    set result
} {-family -overstrike -size -slant -underline -weight}
test unixfont-8.4 {AllocFont procedure: classify characters} x11 {
test unixfont-8.4 {AllocFont procedure: classify characters} {x11 failsOnUbuntu failsOnXQuarz} {
    set x 0
    incr x [font measure $courier "\u4000"]   ;# 6
    incr x [font measure $courier "䀀"]   ;# 6
    incr x [font measure $courier "\002"]   ;# 4
    incr x [font measure $courier "\012"]   ;# 2
    incr x [font measure $courier "\101"]   ;# 1
    set x
} [expr $cx*13]
test unixfont-8.5 {AllocFont procedure: setup widths of normal chars} x11 {
    font metrics $courier -fixed
} {1}
test unixfont-8.6 {AllocFont procedure: setup widths of special chars} x11 {
} 1
test unixfont-8.6 {AllocFont procedure: setup widths of special chars} {x11 failsOnUbuntu failsOnXQuarz} {
    set x 0
    incr x [font measure $courier "\001"]   ;# 4
    incr x [font measure $courier "\002"]   ;# 4
    incr x [font measure $courier "\012"]   ;# 2
    set x
} [expr $cx*10]
test unixfont-8.7 {AllocFont procedure: XA_UNDERLINE_POSITION} x11 {
288
289
290
291
292
293
294
295

296
297
298
299
300
301
302
303
304

305
306
307
308
309
310
311
292
293
294
295
296
297
298

299
300
301
302
303
304
305
306
307

308
309
310
311
312
313
314
315







-
+








-
+







    set x {}
} {}
test unixfont-8.11 {AllocFont procedure: XA_UNDERLINE_POSITION was 0} x11 {
    catch {font actual -adobe-courier-bold-i-normal--0-0-0-0-m-0-iso8859-1}
    set x {}
} {}

test unixfont-9.1 {GetControlCharSubst procedure: 2 chars subst} x11 {
test unixfont-9.1 {GetControlCharSubst procedure: 2 chars subst} {x11 failsOnUbuntu failsOnXQuarz} {
    .b.c dchars $t 0 end
    .b.c insert $t 0 "0\a0"
    set x {}
    lappend x [.b.c index $t @[expr $ax*0],0]
    lappend x [.b.c index $t @[expr $ax*1],0]
    lappend x [.b.c index $t @[expr $ax*2],0]
    lappend x [.b.c index $t @[expr $ax*3],0]
} {0 1 1 2}
test unixfont-9.2 {GetControlCharSubst procedure: 4 chars subst} x11 {
test unixfont-9.2 {GetControlCharSubst procedure: 4 chars subst} {x11 failsOnUbuntu failsOnXQuarz} {
    .b.c dchars $t 0 end
    .b.c insert $t 0 "0\0010"
    set x {}
    lappend x [.b.c index $t @[expr $ax*0],0]
    lappend x [.b.c index $t @[expr $ax*1],0]
    lappend x [.b.c index $t @[expr $ax*2],0]
    lappend x [.b.c index $t @[expr $ax*3],0]
Changes to tests/unixMenu.test.
1
2
3
4
5
6
7


8
9
10
11
12
13
14
1
2
3
4
5


6
7
8
9
10
11
12
13
14





-
-
+
+







# This file is a Tcl script to test menus in Tk.  It is
# organized in the standard fashion for Tcl tests. This
# file tests the Macintosh-specific features of the menu
# system.
#
# Copyright (c) 1995-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1995-1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
namespace import ::tcltest::*
eval tcltest::configure $argv
tcltest::loadTestedCommands

31
32
33
34
35
36
37
38

39
40
41
42
43
44
45
46
47

48
49
50
51
52
53
54
31
32
33
34
35
36
37

38
39
40
41
42
43
44
45
46

47
48
49
50
51
52
53
54







-
+








-
+







test unixMenu-2.1 {TkpDestroyMenu - nothing to do} -constraints unix -body {}


test unixMenu-3.1 {TkpDestroymenuEntry - nothing to do} -constraints unix -body {}


test unixMenu-4.1 {TkpConfigureMenuEntry - non-cascade entry} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1 -tearoff 0
    .m1 add command -label test
    list [.m1 entryconfigure test -label foo] [destroy .m1]
} -returnCodes ok -result {{} {}}
test unixMenu-4.2 {TkpConfigureMenuEntry - cascade entry} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1 -tearoff 0
    .m1 add cascade -menu .m2 -label test
    menu .m1.foo -tearoff 0
    list [.m1 entryconfigure test -menu .m1.foo] [destroy .m1]
75
76
77
78
79
80
81
82

83
84
85
86
87
88
89
90
91
92

93
94
95
96
97
98
99
75
76
77
78
79
80
81

82
83
84
85
86
87
88
89
90
91

92
93
94
95
96
97
98
99







-
+









-
+







} -returnCodes ok -result {{} {} {}}


test unixMenu-7.1 {TkpSetMainMenubar - nothing to do} -constraints unix -body {}


test unixMenu-8.1 {GetMenuIndicatorGeometry - indicator off} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add checkbutton -label foo -indicatoron 0
    tk::TearOffMenu .m1 40 40
    destroy .m1
} -returnCodes ok
test unixMenu-8.2 {GetMenuIndicatorGeometry - not checkbutton or radio} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add command -label foo
    tk::TearOffMenu .m1 40 40
    destroy .m1
108
109
110
111
112
113
114
115

116
117

118
119
120
121
122
123
124
125
126
127
128

129
130
131
132
133
134
135
108
109
110
111
112
113
114

115
116

117
118
119
120
121
122
123
124
125
126
127

128
129
130
131
132
133
134
135







-
+

-
+










-
+







    image create test image1
    .m1 add checkbutton -image image1 -label foo
    .m1 invoke foo
    tk::TearOffMenu .m1 40 40
    destroy .m1
} -cleanup {
    image delete image1
} -returnCodes ok 
} -returnCodes ok
test unixMenu-8.4 {GetMenuIndicatorGeometry - checkbutton bitmap} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add checkbutton -bitmap questhead -label foo
    .m1 invoke foo
    tk::TearOffMenu .m1 40 40
    destroy .m1
} -returnCodes ok
test unixMenu-8.5 {GetMenuIndicatorGeometry - checkbutton} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add checkbutton -label foo
    .m1 invoke foo
    tk::TearOffMenu .m1 40 40
146
147
148
149
150
151
152
153

154
155
156
157
158
159
160
161
162

163
164

165
166
167
168
169
170
171
172
173
174
175

176
177
178
179
180
181
182
183
184

185
186
187
188

189
190
191
192
193
194
195
196
197
198

199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218

219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238

239
240
241
242
243
244
245
246
247
248
249
250

251
252
253
254
255
256
257
258
259
260
261

262
263
264
265
266
267
268
269
270
271

272
273
274
275
276
277
278
279
280
281

282
283
284
285
286
287
288
289
290
291
292
293

294
295
296
297
298
299
300
301
302
303

304
305
306
307
308
309
310
311
312
313

314
315
316
317
318
319
320
321
322
323

324
325
326
327
328
329
330
331
332
333
334

335
336
337
338
339
340
341
342
343
344

345
346
347
348
349
350
351
352
353
354

355
356
357
358
359
360
361
146
147
148
149
150
151
152

153
154
155
156
157
158
159
160
161

162
163

164
165
166
167
168
169
170
171
172
173
174

175
176
177
178
179
180
181
182
183

184
185
186
187

188
189
190
191
192
193
194
195
196
197

198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217

218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237

238
239
240
241
242
243
244
245
246
247
248
249

250
251
252
253
254
255
256
257
258
259
260

261
262
263
264
265
266
267
268
269
270

271
272
273
274
275
276
277
278
279
280

281
282
283
284
285
286
287
288
289
290
291
292

293
294
295
296
297
298
299
300
301
302

303
304
305
306
307
308
309
310
311
312

313
314
315
316
317
318
319
320
321
322

323
324
325
326
327
328
329
330
331
332
333

334
335
336
337
338
339
340
341
342
343

344
345
346
347
348
349
350
351
352
353

354
355
356
357
358
359
360
361







-
+








-
+

-
+










-
+








-
+



-
+









-
+



















-
+



















-
+











-
+










-
+









-
+









-
+











-
+









-
+









-
+









-
+










-
+









-
+









-
+







    .m1 add radiobutton -image image1 -label foo
    .m1 invoke foo
    tk::TearOffMenu .m1 40 40
    destroy .m1
    image delete image1
} -returnCodes ok
test unixMenu-8.7 {GetMenuIndicatorGeometry - radiobutton bitmap} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add radiobutton -bitmap questhead -label foo
    .m1 invoke foo
    tk::TearOffMenu .m1 40 40
    destroy .m1
} -returnCodes ok 
} -returnCodes ok
test unixMenu-8.8 {GetMenuIndicatorGeometry - radiobutton} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add radiobutton -label foo
    .m1 invoke foo
    tk::TearOffMenu .m1 40 40
    destroy .m1
} -returnCodes ok
test unixMenu-8.9 {GetMenuIndicatorGeometry - hideMargin} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add radiobutton -label foo -hidemargin 1
    .m1 invoke foo
    tk::TearOffMenu .m1 40 40
    destroy .m1
} -returnCodes ok 
} -returnCodes ok


test unixMenu-9.1 {GetMenuAccelGeometry - cascade entry} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add cascade -label foo
    tk::TearOffMenu .m1 40 40
    destroy .m1
} -returnCodes ok
test unixMenu-9.2 {GetMenuAccelGeometry - non-null label} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add command -label foo -accel "Ctrl+S"
    tk::TearOffMenu .m1 40 40
    destroy .m1
} -returnCodes ok
test unixMenu-9.3 {GetMenuAccelGeometry - null label} -constraints unix -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add command -label foo
    tk::TearOffMenu .m1 40 40
    destroy .m1
} -returnCodes ok


test unixMenu-10.1 {DrawMenuEntryBackground - active menubar} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add cascade -label foo
    . configure -menu .m1
    .m1 activate 1
    list [update] [. configure -menu ""] [destroy .m1]
} -returnCodes ok -result {{} {} {}}
test unixMenu-10.2 {DrawMenuEntryBackground - active} -constraints unix -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add command -label foo
    set tearoff [tk::TearOffMenu .m1 40 40]
    $tearoff activate 0
    list [update] [destroy .m1]
} -returnCodes ok -result {{} {}}
test unixMenu-10.3 {DrawMenuEntryBackground - non-active} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add command -label foo
    set tearoff [tk::TearOffMenu .m1 40 40]
    list [update] [destroy .m1]
} -returnCodes ok -result {{} {}}


test unixMenu-11.1 {DrawMenuEntryAccelerator - menubar} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add command -label foo -accel "Ctrl+U"
    . configure -menu .m1
    list [update] [. configure -menu ""] [destroy .m1]
} -result {{} {} {}}
# drawArrow parameter is never false under Unix
test unixMenu-11.2 {DrawMenuEntryAccelerator - cascade entry} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add cascade -label foo
    set tearoff [tk::TearOffMenu .m1 40 40]
    list [update] [destroy .m1]
}  -result {{} {}}
test unixMenu-11.3 {DrawMenuEntryAccelerator - normal entry} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add command -label foo -accel "Ctrl+U"
    set tearoff [tk::TearOffMenu .m1 40 40]
    list [update] [destroy .m1]
} -result {{} {}}
test unixMenu-11.4 {DrawMenuEntryAccelerator - null entry} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add command -label foo
    set tearoff [tk::TearOffMenu .m1 40 40]
    list [update] [destroy .m1]
} -result {{} {}}


test unixMenu-12.1 {DrawMenuEntryIndicator - non-check or radio} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add command -label foo
    set tearoff [tk::TearOffMenu .m1 40 40]
    list [update] [destroy .m1]
} -result {{} {}}
test unixMenu-12.2 {DrawMenuEntryIndicator - checkbutton - indicator off} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add checkbutton -label foo -indicatoron 0
    set tearoff [tk::TearOffMenu .m1 40 40]
    list [update] [destroy .m1]
} -result {{} {}}
test unixMenu-12.3 {DrawMenuEntryIndicator - checkbutton - not selected} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add checkbutton -label foo
    set tearoff [tk::TearOffMenu .m1 40 40]
    list [update] [destroy .m1]
} -result {{} {}}
test unixMenu-12.4 {DrawMenuEntryIndicator - checkbutton - selected} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add checkbutton -label foo
    .m1 invoke 1
    set tearoff [tk::TearOffMenu .m1 40 40]
    list [update] [destroy .m1]
} -result {{} {}}
test unixMenu-12.5 {DrawMenuEntryIndicator - radiobutton - indicator off} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add radiobutton -label foo -indicatoron 0
    set tearoff [tk::TearOffMenu .m1 40 40]
    list [update] [destroy .m1]
} -result {{} {}}
test unixMenu-12.6 {DrawMenuEntryIndicator - radiobutton - not selected} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add radiobutton -label foo
    set tearoff [tk::TearOffMenu .m1 40 40]
    list [update] [destroy .m1]
} -result {{} {}}
test unixMenu-12.7 {DrawMenuEntryIndicator - radiobutton - selected} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add radiobutton -label foo
    .m1 invoke 1
    set tearoff [tk::TearOffMenu .m1 40 40]
442
443
444
445
446
447
448
449

450
451
452
453
454
455
456
457
458
459

460
461
462
463
464
465
466
467
468
469

470
471
472
473
474
475
476
477
478
479

480
481
482
483
484
485
486
487
488
489

490
491
492
493
494
495
496
497
498
499

500
501
502
503
504
505
506
507
508
509
510

511
512
513
514
515
516
517
518
519
520
521
522

523
524
525
526
527
528
529
530
531
532
533
534

535
536
537
538
539
540
541
542
543
544
545
546

547
548
549
550
551
552
553
442
443
444
445
446
447
448

449
450
451
452
453
454
455
456
457
458

459
460
461
462
463
464
465
466
467
468

469
470
471
472
473
474
475
476
477
478

479
480
481
482
483
484
485
486
487
488

489
490
491
492
493
494
495
496
497
498

499
500
501
502
503
504
505
506
507
508
509

510
511
512
513
514
515
516
517
518
519
520
521

522
523
524
525
526
527
528
529
530
531
532
533

534
535
536
537
538
539
540
541
542
543
544
545

546
547
548
549
550
551
552
553







-
+









-
+









-
+









-
+









-
+









-
+










-
+











-
+











-
+











-
+







    list [tk::MbPost .mb] [tk::MenuUnpost .mb.m] [destroy .mb]
} -result {{} {} {}}


# Don't know how to reproduce the case where the tkwin has been deleted.

test unixMenu-19.1 {TkpComputeMenubarGeometry - zero entries} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    . configure -menu .m1
    list [update] [. configure -menu ""] [destroy .m1]
} -result {{} {} {}}
# Don't know how to generate one width windows
test unixMenu-19.2 {TkpComputeMenubarGeometry - one entry} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add cascade -label File
    . configure -menu .m1
    list [update] [. configure -menu ""] [destroy .m1]
} -result {{} {} {}}
test unixMenu-19.3 {TkpComputeMenubarGeometry - entry with different font} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1 -font "Courier 24"
    .m1 add cascade -label File -font "Helvetica 18"
    . configure -menu .m1
    list [update] [. configure -menu ""] [destroy .m1]
} -result {{} {} {}}
test unixMenu-19.4 {TkpComputeMenubarGeometry - separator} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add separator
    . configure -menu .m1
    list [update] [. configure -menu ""] [destroy .m1]
} -result {{} {} {}}
test unixMenu-19.5 {TkpComputeMenubarGeometry - First entry} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1 -tearoff 0
    .m1 add cascade -label File
    . configure -menu .m1
    list [update] [. configure -menu ""] [destroy .m1]
} -result {{} {} {}}
test unixMenu-19.6 {TkpComputeMenubarGeometry - First entry too wide} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1 -tearoff 0
    .m1 add cascade -label File -font "Times 72"
    . configure -menu .m1
    wm geometry . 10x10
    list [update] [. configure -menu ""] [destroy .m1]
} -result {{} {} {}}
test unixMenu-19.7 {TkpComputeMenubarGeometry - two entries fit} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1 -tearoff 0
    .m1 add cascade -label File
    .m1 add cascade -label Edit
    . configure -menu .m1
    wm geometry . 200x200
    list [update] [. configure -menu ""] [destroy .m1]
} -result {{} {} {}}
test unixMenu-19.8 {TkpComputeMenubarGeometry - two entries; 2nd don't fit} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1 -tearoff 0
    .m1 add cascade -label File
    .m1 add cascade -label Edit -font "Times 72"
    . configure -menu .m1
    wm geometry . 100x100
    list [update] [. configure -menu ""] [destroy .m1]
} -result {{} {} {}}
test unixMenu-19.9 {TkpComputeMenubarGeometry - two entries; 1st dont fit} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1 -tearoff 0
    .m1 add cascade -label File -font "Times 72"
    .m1 add cascade -label Edit
    . configure -menu .m1
    wm geometry . 100x100
    list [update] [. configure -menu ""] [destroy .m1]
} -result {{} {} {}}
test unixMenu-19.10 {TkpComputeMenubarGeometry - two entries; neither fit} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1 -tearoff 0 -font "Times 72"
    .m1 add cascade -label File
    .m1 add cascade -label Edit
    . configure -menu .m1
641
642
643
644
645
646
647
648

649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664

665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680

681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696

697
698
699
700
701
702
703
704
705
706
707
708
709
710

711
712
713
714
715
716
717
718
719
720
721
722
723
724

725
726
727
728
729
730
731
641
642
643
644
645
646
647

648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663

664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679

680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695

696
697
698
699
700
701
702
703
704
705
706
707
708
709

710
711
712
713
714
715
716
717
718
719
720
721
722
723

724
725
726
727
728
729
730
731







-
+















-
+















-
+















-
+













-
+













-
+







    .m1 add cascade -label "B"
    .m1 add cascade -label "C"
    . configure -menu .m1
    wm geometry . 100x10
    list [update] [. configure -menu ""] [destroy .m1]
} -result {{} {} {}}
test unixMenu-19.19 {TkpComputeMenubarGeometry - help menu in first position} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1 -tearoff 0
    .m1 add cascade -label Help -menu .m1.help
    menu .m1.help -tearoff 0
    .m1 add cascade -label File -menu .m1.file
    menu .m1.file -tearoff 0
    .m1 add cascade -label Edit -menu .m1.edit
    menu .m1.edit -tearoff 0
    . configure -menu .m1
    wm geometry . 100x10
    list [update] [. configure -menu ""] [destroy .m1]
} -result {{} {} {}}
test unixMenu-19.20 {TkpComputeMenubarGeometry - help menu in middle} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1 -tearoff 0
    .m1 add cascade -label Edit -menu .m1.edit
    menu .m1.edit -tearoff 0
    .m1 add cascade -label Help -menu .m1.help
    menu .m1.help -tearoff 0
    .m1 add cascade -label File -menu .m1.file
    menu .m1.file -tearoff 0
    . configure -menu .m1
    wm geometry . 100x10
    list [update] [. configure -menu ""] [destroy .m1]
} -result {{} {} {}}
test unixMenu-19.21 {TkpComputeMenubarGeometry - help menu in first position} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1 -tearoff 0
    .m1 add cascade -label File -menu .m1.file
    menu .m1.file -tearoff 0
    .m1 add cascade -label Edit -menu .m1.edit
    menu .m1.edit -tearoff 0
    .m1 add cascade -label Help -menu .m1.help
    menu .m1.help -tearoff 0
    . configure -menu .m1
    wm geometry . 100x10
    list [update] [. configure -menu ""] [destroy .m1]
} -result {{} {} {}}
test unixMenu-19.22 {TkpComputeMenubarGeometry - help item fits} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1 -tearoff 0
    .m1 add cascade -label File -menu .m1.file
    menu .m1.file -tearoff 0
    .m1 add cascade -label Help -menu .m1.help
    menu .m1.help -tearoff 0
    . configure -menu .m1
    wm geometry . 100x10
    list [update] [. configure -menu ""] [destroy .m1]
} -result {{} {} {}}
test unixMenu-19.23 {TkpComputeMenubarGeometry - help item does not fit} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1 -tearoff 0
    .m1 add cascade -label File -menu .m1.file
    menu .m1.file -tearoff 0
    .m1 add cascade -label Help -menu .m1.help -font "Helvetica 72"
    menu .m1.help -tearoff 0
    . configure -menu .m1
    wm geometry . 100x10
    list [update] [. configure -menu ""] [destroy .m1]
} -result {{} {} {}}
test unixMenu-19.24 {TkpComputeMenubarGeometry - help item only one} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1 -tearoff 0
    .m1 add cascade -label Help -menu .m1.help
    menu .m1.help -tearoff 0
    . configure -menu .m1
762
763
764
765
766
767
768
769

770
771
772
773
774
775
776
777
778
779

780
781
782
783
784
785
786
787
788
789

790
791
792
793
794
795
796
797
798
799
800
801
802
803
804

805
806
807
808
809
810
811
812
813
814
815

816
817
818
819
820
821
822
823
824
825
826

827
828
829
830
831
832
833
834
835
836
837
838

839
840
841
842
843
844
845
846
847
848

849
850
851
852
853
854
855
856
857
858

859
860
861
862
863
864
865
866
867
868

869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886

887
888
889
890
891
892
893
894
895
896
897

898
899
900
901
902
903
904
905
906
907
908

909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928

929
930
931
932
933
934
935
936
937
938
939
940

941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960

961
962
963
964
965
966
967
762
763
764
765
766
767
768

769
770
771
772
773
774
775
776
777
778

779
780
781
782
783
784
785
786
787
788

789
790
791
792
793
794
795
796
797
798
799
800
801
802
803

804
805
806
807
808
809
810
811
812
813
814

815
816
817
818
819
820
821
822
823
824
825

826
827
828
829
830
831
832
833
834
835
836
837

838
839
840
841
842
843
844
845
846
847

848
849
850
851
852
853
854
855
856
857

858
859
860
861
862
863
864
865
866
867

868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885

886
887
888
889
890
891
892
893
894
895
896

897
898
899
900
901
902
903
904
905
906
907

908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927

928
929
930
931
932
933
934
935
936
937
938
939

940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959

960
961
962
963
964
965
966
967







-
+









-
+









-
+














-
+










-
+










-
+











-
+









-
+









-
+









-
+

















-
+










-
+










-
+



















-
+











-
+



















-
+







} -body {
    menu .m1 -tearoff 0
    .m1 add cascade -label test -menu .m1.test
    list [menu .m1.test] [destroy .m1]
} -result {.m1.test {}}
# Don't know how to automate missing tkwins
test unixMenu-22.2 {SetHelpMenu - menubar but no help menu} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1 -tearoff 0
    . configure -menu .m1
    .m1 add cascade -label .m1.file
    list [menu .m1.file] [. configure -menu ""] [destroy .m1]
} -result {.m1.file {} {}}
test unixMenu-22.3 {SetHelpMenu - menubar with help menu} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1 -tearoff 0
    . configure -menu .m1
    .m1 add cascade -label .m1.help
    list [menu .m1.help] [. configure -menu ""] [destroy .m1]
} -result {.m1.help {} {}}
test unixMenu-22.4 {SetHelpMenu - multiple menubars with same help menu} -constraints {
    unix 
    unix
} -setup {
    destroy .m1 .t2
} -body {
    toplevel .t2
    wm geometry .t2 +40+40
    menu .m1 -tearoff 0
    . configure -menu .m1
    .t2 configure -menu .m1
    .m1 add cascade -label .m1.help
    list [menu .m1.help] [. configure -menu ""] [destroy .m1] [destroy .t2]
} -result {.m1.help {} {} {}}


test unixMenu-23.1 {TkpDrawMenuEntry - gc for active and not strict motif} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add command -label foo
    set tearoff [tk::TearOffMenu .m1 40 40]
    .m1 entryconfigure 1 -state active
    list [update] [destroy .m1]
} -result {{} {}}
test unixMenu-23.2 {TkpDrawMenuEntry - gc for active menu item with its own gc} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add command -label foo -activeforeground red
    set tearoff [tk::TearOffMenu .m1 40 40]
    .m1 entryconfigure 1 -state active
    list [update] [destroy .m1]
} -result {{} {}}
test unixMenu-23.3 {TkpDrawMenuEntry - gc for active and strict motif} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    set tk_strictMotif 1
    .m1 add command -label foo
    set tearoff [tk::TearOffMenu .m1 40 40]
    .m1 entryconfigure 1 -state active
    list [update] [destroy .m1] [set tk_strictMotif 0]
} -result {{} {} 0}
test unixMenu-23.4 {TkpDrawMenuEntry - gc for disabled with disabledfg and custom entry} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1 -disabledforeground blue
    .m1 add command -label foo -state disabled -background red
    set tearoff [tk::TearOffMenu .m1 40 40]
    list [update] [destroy .m1]
} -result {{} {}}
test unixMenu-23.5 {TkpDrawMenuEntry - gc for disabled with disabledFg} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1 -disabledforeground blue
    .m1 add command -label foo -state disabled
    set tearoff [tk::TearOffMenu .m1 40 40]
    list [update] [destroy .m1]
} -result {{} {}}
test unixMenu-23.6 {TkpDrawMenuEntry - gc for disabled - no disabledFg} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1 -disabledforeground ""
    .m1 add command -label foo -state disabled
    set tearoff [tk::TearOffMenu .m1 40 40]
    list [update] [destroy .m1]
} -result {{} {}}
test unixMenu-23.7 {TkpDrawMenuEntry - gc for normal - custom entry} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add command -label foo -foreground red
    set tearoff [tk::TearOffMenu .m1 40 40]
    list [update] [destroy .m1]
} -result {{} {}}
test unixMenu-23.8 {TkpDrawMenuEntry - gc for normal} -constraints unix -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add command -label foo
    set tearoff [tk::TearOffMenu .m1 40 40]
    list [update] [destroy .m1]
} -result {{} {}}
test unixMenu-23.9 {TkpDrawMenuEntry - gc for indicator - custom entry} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add checkbutton -label foo -selectcolor orange
    .m1 invoke 1
    set tearoff [tk::TearOffMenu .m1 40 40]
    list [update] [destroy .m1]
} -result {{} {}}
test unixMenu-23.10 {TkpDrawMenuEntry - gc for indicator} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add checkbutton -label foo
    .m1 invoke 1
    set tearoff [tk::TearOffMenu .m1 40 40]
    list [update] [destroy .m1]
} -result {{} {}}
test unixMenu-23.11 {TkpDrawMenuEntry - border - custom entry} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add command -label foo -activebackground green
    set tearoff [tk::TearOffMenu .m1 40 40]
    .m1 entryconfigure 1 -state active
    list [update] [destroy .m1]
} -result {{} {}}
test unixMenu-23.12 {TkpDrawMenuEntry - border} -constraints unix -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add command -label foo
    set tearoff [tk::TearOffMenu .m1 40 40]
    .m1 entryconfigure 1 -state active
    list [update] [destroy .m1]
} -result {{} {}}
test unixMenu-23.13 {TkpDrawMenuEntry - active border - strict motif} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    set tk_strictMotif 1
    menu .m1
    .m1 add command -label foo
    set tearoff [tk::TearOffMenu .m1 40 40]
    .m1 entryconfigure 1 -state active
    list [update] [destroy .m1] [set tk_strictMotif 0]
} -result {{} {} 0}
test unixMenu-23.14 {TkpDrawMenuEntry - active border - custom entry} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add command -label foo -activeforeground yellow
    set tearoff [tk::TearOffMenu .m1 40 40]
    .m1 entryconfigure 1 -state active
    list [update] [destroy .m1]
} -result {{} {}}
test unixMenu-23.15 {TkpDrawMenuEntry - active border} -constraints unix -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add command -label foo
    set tearoff [tk::TearOffMenu .m1 40 40]
    .m1 entryconfigure 1 -state active
    list [update] [destroy .m1]
} -result {{} {}}
test unixMenu-23.16 {TkpDrawMenuEntry - font - custom entry} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add command -label foo -font "Helvectica 72"
    set tearoff [tk::TearOffMenu .m1 40 40]
    list [update] [destroy .m1]
987
988
989
990
991
992
993
994

995
996
997
998
999
1000
1001
987
988
989
990
991
992
993

994
995
996
997
998
999
1000
1001







-
+







} -body {
    menu .m1
    .m1 add command -label foo
    set tearoff [tk::TearOffMenu .m1 40 40]
    list [update] [destroy .m1]
} -result {{} {}}
test unixMenu-23.20 {TkpDrawMenuEntry - disabled cascade item} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add cascade -label File -menu .m1.file
    menu .m1.file
    .m1.file add command -label foo
1054
1055
1056
1057
1058
1059
1060
1061

1062
1063
1064
1065
1066
1067
1068
1069

1070
1071
1072
1073
1074
1075
1076
1077
1078

1079
1080
1081
1082
1083
1084
1085
1086
1087
1088

1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109

1110
1111
1112
1113
1114
1115
1116
1117
1118

1119
1120
1121
1122
1123
1124
1125
1126
1127

1128
1129
1130
1131
1132
1133
1134
1135
1136
1137

1138
1139
1140
1141
1142
1143
1144
1145
1146
1147

1148
1149
1150
1151
1152
1153
1154
1155
1156

1157
1158
1159
1160
1161
1162
1163
1164
1165
1166

1167
1168
1169
1170
1171
1172
1173
1174
1175
1176

1177
1178
1179
1180
1181
1182
1183
1054
1055
1056
1057
1058
1059
1060

1061
1062
1063
1064
1065
1066
1067
1068

1069
1070
1071
1072
1073
1074
1075
1076
1077

1078
1079
1080
1081
1082
1083
1084
1085
1086
1087

1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108

1109
1110
1111
1112
1113
1114
1115
1116
1117

1118
1119
1120
1121
1122
1123
1124
1125
1126

1127
1128
1129
1130
1131
1132
1133
1134
1135
1136

1137
1138
1139
1140
1141
1142
1143
1144
1145
1146

1147
1148
1149
1150
1151
1152
1153
1154
1155

1156
1157
1158
1159
1160
1161
1162
1163
1164
1165

1166
1167
1168
1169
1170
1171
1172
1173
1174
1175

1176
1177
1178
1179
1180
1181
1182
1183







-
+







-
+








-
+









-
+




















-
+








-
+








-
+









-
+









-
+








-
+









-
+









-
+







    menu .m1
    .m1 add command -label "This is a test."
    list [update idletasks] [destroy .m1]
} -result {{} {}}


test unixMenu-25.1 {TkpComputeStandardMenuGeometry - no entries} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    list [update idletasks] [destroy .m1]
} -result {{} {}}
test unixMenu-25.2 {TkpComputeStandardMenuGeometry - one entry} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add command -label "one"
    list [update idletasks] [destroy .m1]
} -result {{} {}}
test unixMenu-25.3 {TkpComputeStandardMenuGeometry - more than one entry} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add command -label "one"
    .m1 add command -label "two"
    list [update idletasks] [destroy .m1]
} -result {{} {}}
test unixMenu-25.4 {TkpComputeStandardMenuGeometry - separator} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add separator
    list [update idletasks] [destroy .m1]
} -result {{} {}}
test unixMenu-25.5 {TkpComputeStandardMenuGeometry - tearoff entry} -constraints {
    unix nonUnixUserInteraction
} -setup {
    destroy .mb
} -body {
    menubutton .mb -text "test" -menu .mb.m
    menu .mb.m
    .mb.m add command -label test
    pack .mb
    catch {tk::MbPost .mb}
    list [update] [tk::MenuUnpost .mb.m] [destroy .mb]
} -result {{} {} {}}
test unixMenu-25.6 {TkpComputeStandardMenuGeometry - standard label geometry} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add command -label "test"
    list [update idletasks] [destroy .m1]
} -result {{} {}}
test unixMenu-25.7 {TkpComputeStandardMenuGeometry - different font for entry} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1 -font "Helvetica 12"
    .m1 add command -label "test" -font "Courier 12"
    list [update idletasks] [destroy .m1]
} -result {{} {}}
test unixMenu-25.8 {TkpComputeStandardMenuGeometry - second entry larger} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add command -label "test"
    .m1 add command -label "test test"
    list [update idletasks] [destroy .m1]
} -result {{} {}}
test unixMenu-25.9 {TkpComputeStandardMenuGeometry - first entry larger} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add command -label "test test"
    .m1 add command -label "test"
    list [update idletasks] [destroy .m1]
} -result {{} {}}
test unixMenu-25.10 {TkpComputeStandardMenuGeometry - accelerator} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add command -label "test" -accel "Ctrl+S"
    list [update idletasks] [destroy .m1]
} -result {{} {}}
test unixMenu-25.11 {TkpComputeStandardMenuGeometry - second accel larger} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add command -label "test" -accel "1"
    .m1 add command -label "test" -accel "1 1"
    list [update idletasks] [destroy .m1]
} -result {{} {}}
test unixMenu-25.12 {TkpComputeStandardMenuGeometry - second accel smaller} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add command -label "test" -accel "1 1"
    .m1 add command -label "test" -accel "1"
    list [update idletasks] [destroy .m1]
} -result {{} {}}
test unixMenu-25.13 {TkpComputeStandardMenuGeometry - indicator} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add checkbutton -label test
    .m1 invoke 1
    list [update idletasks] [destroy .m1]
1207
1208
1209
1210
1211
1212
1213
1214

1215
1216
1217
1218
1219
1220
1221
1222

1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233

1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244

1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255

1256
1257
1258

1259
1260
1261
1262
1263
1264
1265
1207
1208
1209
1210
1211
1212
1213

1214
1215
1216
1217
1218
1219
1220
1221

1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232

1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243

1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254

1255
1256
1257

1258
1259
1260
1261
1262
1263
1264
1265







-
+







-
+










-
+










-
+










-
+


-
+







    .m1 add checkbutton -image image1
    .m1 invoke 1
    .m1 add checkbutton -label test
    .m1 invoke 2
    list [update idletasks] [destroy .m1] [image delete image1]
} -result {{} {} {}}
test unixMenu-25.16 {TkpComputeStandardMenuGeometry - zero sized menus} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1 -tearoff 0
    list [update idletasks] [destroy .m1]
} -result {{} {}}
test unixMenu-25.17 {TkpComputeStandardMenuGeometry - first column bigger} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add command -label one
    .m1 add command -label two
    .m1 add command -label three -columnbreak 1
    list [update idletasks] [destroy .m1]
} -result {{} {}}
test unixMenu-25.18 {TkpComputeStandardMenuGeometry - second column bigger} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1 -tearoff 0
    .m1 add command -label one
    .m1 add command -label two -columnbreak 1
    .m1 add command -label three
    list [update idletasks] [destroy .m1]
} -result {{} {}}
test unixMenu-25.19 {TkpComputeStandardMenuGeometry - three columns} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1 -tearoff 0
    .m1 add command -label one
    .m1 add command -label two -columnbreak 1
    .m1 add command -label three
    .m1 add command -label four
    .m1 add command -label five -columnbreak 1
    .m1 add command -label six
    list [update idletasks] [destroy .m1]    
    list [update idletasks] [destroy .m1]
} -result {{} {}}
test unixMenu-25.20 {TkpComputeStandardMenuGeometry - hide margin} -constraints {
    unix 
    unix
} -setup {
    destroy .m1
} -body {
    menu .m1 -tearoff 0
    .m1 add checkbutton -label one -hidemargin 1
    list [update idletasks] [destroy .m1]
} -result {{} {}}
Changes to tests/unixSelect.test.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







# This file contains tests for the tkUnixSelect.c file.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1999 by Scriptics Corporation.
# 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.

package require tcltest 2.2
namespace import ::tcltest::*
tcltest::configure {*}$argv
111
112
113
114
115
116
117
118

119
120
121
122
123
124

125
126
127
128
129
130
131
132
133
134

135
136
137
138
139
140

141
142
143
144
145
146
147
148
149
150
151

152
153
154
155

156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175

176
177
178
179
180

181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197

198
199
200
201

202
203
204
205
206
207
208
209
210
211
212
213
214

215
216
217
218
219
220
221
222
223
224
225
226
227
228
229

230
231
232
233
234
235

236
237
238
239
240
241
242
243
244
245

246
247
248
249
250
251

252
253
254
255
256
257
258
259
260
261

262
263
264
265
266
267

268
269
270
271
272
273
274
275
276
277
278
279
280

281
282
283
284
285
286

287
288
289
290
291
292
293
294
295
296

297
298
299
300
301
302

303
304
305
306
307
308
309
310
311
312

313
314
315
316
317
318

319
320
321
322
323
324
325
326
327
328

329
330
331
332
333
334

335
336
337
338
339
340
341
342
343
344

345
346
347
348
349
350

351
352
353
354
355
356
357
358
359
360

361
362
363
364
365
366

367
368
369
370
371
372
373
374
375
376

377
378
379
380
381
382

383
384
385
386
387
388
389
390
391
392

393
394
395
396
397
398
399
400

401
402
403
404
405
406
407
408
409
410

411
412
413
414
415
416
417
418

419
420
421
422
423
424
425
111
112
113
114
115
116
117

118
119
120
121
122
123

124
125
126
127
128
129
130
131
132
133

134
135
136
137
138
139

140
141
142
143
144
145
146
147
148
149
150

151
152
153
154

155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174

175
176
177
178
179

180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196

197
198
199
200

201
202
203
204
205
206
207
208
209
210
211
212
213

214
215
216
217
218
219
220
221
222
223
224
225
226
227
228

229
230
231
232
233
234

235
236
237
238
239
240
241
242
243
244

245
246
247
248
249
250

251
252
253
254
255
256
257
258
259
260

261
262
263
264
265
266

267
268
269
270
271
272
273
274
275
276
277
278
279

280
281
282
283
284
285

286
287
288
289
290
291
292
293
294
295

296
297
298
299
300
301

302
303
304
305
306
307
308
309
310
311

312
313
314
315
316
317

318
319
320
321
322
323
324
325
326
327

328
329
330
331
332
333

334
335
336
337
338
339
340
341
342
343

344
345
346
347
348
349

350
351
352
353
354
355
356
357
358
359

360
361
362
363
364
365

366
367
368
369
370
371
372
373
374
375

376
377
378
379
380
381

382
383
384
385
386
387
388
389
390
391

392
393
394
395
396
397
398
399

400
401
402
403
404
405
406
407
408
409

410
411
412
413
414
415
416
417

418
419
420
421
422
423
424
425







-
+





-
+









-
+





-
+










-
+



-
+



















-
+




-
+
















-
+



-
+












-
+














-
+





-
+









-
+





-
+









-
+





-
+












-
+





-
+









-
+





-
+









-
+





-
+









-
+





-
+









-
+





-
+









-
+





-
+









-
+





-
+









-
+







-
+









-
+







-
+







    x11
} -setup {
    destroy .e
    setupbg
} -body {
    pack [entry .e]
    update
    .e insert 0 \u00fcber
    .e insert 0 über
    .e selection range 0 end
    dobg {string length [selection get]}
} -cleanup {
    cleanupbg
    destroy .e
} -result {4}
} -result 4

test unixSelect-1.2 {TkSelGetSelection procedure: simple i18n text, iso8859-1} -constraints {
    x11
} -setup {
    setupbg
} -body {
    dobg {
        pack [entry .e]
        update
        .e insert 0 \u00fc\u0444
        .e insert 0 üф
        .e selection range 0 end
    }
    selection get
} -cleanup {
    cleanupbg
} -result \u00fc?
} -result ü?

test unixSelect-1.3 {TkSelGetSelection procedure: simple i18n text, iso2022} -constraints {
    x11
} -setup {
    setupbg
    setup
} -body {
    selection handle -type COMPOUND_TEXT -format COMPOUND_TEXT . \
        {handler COMPOUND_TEXT}
    selection own .
    set selValue \u00fc\u0444
    set selValue üф
    set selInfo {}
    set result [dobg {
        set x [selection get -type COMPOUND_TEXT]
        list [string equal \u00fc\u0444 $x] [string length $x]
        list [string equal üф $x] [string length $x]
    }]
    lappend result $selInfo
} -cleanup {
    cleanupbg
} -result {1 2 {COMPOUND_TEXT 0 4000}}

test unixSelect-1.4 {TkSelGetSelection procedure: INCR i18n text, iso2022} -constraints {
    x11
} -setup {
    setupbg
    setup
} -body {
    # This test is subtle.  The selection ends up getting fetched twice by
    # Tk:  once to compute the length, and again to actually send the data.
    # The first time through, we don't convert the data to ISO2022, so the
    # buffer boundaries end up being different in the two passes.
    selection handle -type COMPOUND_TEXT -format COMPOUND_TEXT . \
        {handler COMPOUND_TEXT}
    selection own .
    set selValue [string repeat x 3999]\u00fc\u0444[string repeat x 3999]
    set selValue [string repeat x 3999]üф[string repeat x 3999]
    set selInfo {}
    set result [dobg {
        set x [selection get -type COMPOUND_TEXT]
        list [string equal \
            [string repeat x 3999]\u00fc\u0444[string repeat x 3999] $x] \
            [string repeat x 3999]üф[string repeat x 3999] $x] \
            [string length $x]
    }]
    lappend result $selInfo
} -cleanup {
    cleanupbg
} -result {1 8000 {COMPOUND_TEXT 0 4000 COMPOUND_TEXT 4000 3999 COMPOUND_TEXT 7998 4000 COMPOUND_TEXT 0 4000 COMPOUND_TEXT 4000 3998 COMPOUND_TEXT 7997 4000}}

test unixSelect-1.5 {TkSelGetSelection procedure: simple i18n text, iso2022} -constraints {
    x11
} -setup {
    setupbg
    setup
} -body {
    selection handle -type COMPOUND_TEXT -format COMPOUND_TEXT . \
        {handler COMPOUND_TEXT}
    selection own .
    set selValue \u00fc\u0444
    set selValue üф
    set selInfo {}
    set result [dobg {
        set x [selection get -type COMPOUND_TEXT]
        list [string equal \u00fc\u0444 $x] [string length $x]
        list [string equal üф $x] [string length $x]
    }]
    lappend result $selInfo
} -cleanup {
    cleanupbg
} -result {1 2 {COMPOUND_TEXT 0 4000}}

test unixSelect-1.6 {TkSelGetSelection procedure: INCR i18n text} -constraints {
    x11
} -setup {
    setupbg
} -body {
    dobg [subst -nobackslashes {entry .e; pack .e; update
    .e insert 0 \u00fcber$longValue
    .e insert 0 über$longValue
    .e selection range 0 end}]
    string length [selection get]
} -cleanup {
    cleanupbg
} -result [expr {4 + [string length $longValue]}]

test unixSelect-1.7 {TkSelGetSelection procedure: INCR i18n text} -constraints {
    x11
} -setup {
    setupbg
} -body {
    dobg {
        pack [entry .e]
        update
        .e insert 0 [string repeat x 3999]\u00fc
        .e insert 0 [string repeat x 3999]ü
        .e selection range 0 end
    }
    selection get
} -cleanup {
    cleanupbg
} -result [string repeat x 3999]\u00fc
} -result [string repeat x 3999]ü

test unixSelect-1.8 {TkSelGetSelection procedure: INCR i18n text} -constraints {
    x11
} -setup {
    setupbg
} -body {
    dobg {
        pack [entry .e]
        update
        .e insert 0 \u00fc[string repeat x 3999]
        .e insert 0 ü[string repeat x 3999]
        .e selection range 0 end
    }
    selection get
} -cleanup {
    cleanupbg
} -result \u00fc[string repeat x 3999]
} -result ü[string repeat x 3999]

test unixSelect-1.9 {TkSelGetSelection procedure: INCR i18n text} -constraints {
    x11
} -setup {
    setupbg
} -body {
    dobg {
        pack [entry .e]
        update
        .e insert 0 [string repeat x 3999]\u00fc[string repeat x 4000]
        .e insert 0 [string repeat x 3999]ü[string repeat x 4000]
        .e selection range 0 end
    }
    selection get
} -cleanup {
    cleanupbg
} -result [string repeat x 3999]\u00fc[string repeat x 4000]
} -result [string repeat x 3999]ü[string repeat x 4000]
# Now some tests to make sure that the right thing is done when
# transferring UTF8 selections, to prevent [Bug 614650] and its ilk
# from rearing its ugly head again.

test unixSelect-1.10 {TkSelGetSelection procedure: INCR i18n text, utf-8} -constraints {
    x11
} -setup {
    setupbg
} -body {
    dobg {
        pack [entry .e]
        update
        .e insert 0 [string repeat x 3999]\u00fc
        .e insert 0 [string repeat x 3999]ü
        .e selection range 0 end
    }
    selection get -type UTF8_STRING
} -cleanup {
    cleanupbg
} -result [string repeat x 3999]\u00fc
} -result [string repeat x 3999]ü

test unixSelect-1.11 {TkSelGetSelection procedure: INCR i18n text, utf-8} -constraints {
    x11
} -setup {
    setupbg
} -body {
    dobg {
        pack [entry .e]
        update
        .e insert 0 \u00fc[string repeat x 3999]
        .e insert 0 ü[string repeat x 3999]
        .e selection range 0 end
    }
    selection get -type UTF8_STRING
} -cleanup {
    cleanupbg
} -result \u00fc[string repeat x 3999]
} -result ü[string repeat x 3999]

test unixSelect-1.12 {TkSelGetSelection procedure: INCR i18n text, utf-8} -constraints {
    x11
} -setup {
    setupbg
} -body {
    dobg {
        pack [entry .e]
        update
        .e insert 0 [string repeat x 3999]\u00fc[string repeat x 4000]
        .e insert 0 [string repeat x 3999]ü[string repeat x 4000]
        .e selection range 0 end
    }
    selection get -type UTF8_STRING
} -cleanup {
    cleanupbg
} -result [string repeat x 3999]\u00fc[string repeat x 4000]
} -result [string repeat x 3999]ü[string repeat x 4000]

test unixSelect-1.13 {TkSelGetSelection procedure: simple i18n text, utf-8} -constraints {
    x11
} -setup {
    destroy .e
    setupbg
} -body {
    pack [entry .e]
    update
    .e insert 0 \u00fcber\u0444
    .e insert 0 überф
    .e selection range 0 end
    dobg {string length [selection get -type UTF8_STRING]}
} -cleanup {
    destroy .e
    cleanupbg
} -result {5}
} -result 5

test unixSelect-1.14 {TkSelGetSelection procedure: simple i18n text, utf-8} -constraints {
    x11
} -setup {
    setupbg
} -body {
    dobg {
        pack [entry .e]
        update
        .e insert 0 \u00fc\u0444
        .e insert 0 üф
        .e selection range 0 end
    }
    selection get -type UTF8_STRING
} -cleanup {
    cleanupbg
} -result \u00fc\u0444
} -result üф

test unixSelect-1.15 {TkSelGetSelection procedure: INCR i18n text, utf-8} -constraints {
    x11
} -setup {
    setupbg
} -body {
    dobg {
        pack [entry .e]
        update
        .e insert 0 [string repeat [string repeat \u00c4\u00e4 50]\n 21]
        .e insert 0 [string repeat [string repeat Ää 50]\n 21]
        .e selection range 0 end
    }
    selection get -type UTF8_STRING
} -cleanup {
    cleanupbg
} -result [string repeat [string repeat \u00c4\u00e4 50]\n 21]
} -result [string repeat [string repeat Ää 50]\n 21]

test unixSelect-1.16 {TkSelGetSelection procedure: INCR i18n text, utf-8} -constraints {
    x11
} -setup {
    setupbg
} -body {
    dobg {
        pack [entry .e]
        update
        .e insert 0 i[string repeat [string repeat \u00c4\u00e4 50]\n 21]
        .e insert 0 i[string repeat [string repeat Ää 50]\n 21]
        .e selection range 0 end
    }
    selection get -type UTF8_STRING
} -cleanup {
    cleanupbg
} -result i[string repeat [string repeat \u00c4\u00e4 50]\n 21]
} -result i[string repeat [string repeat Ää 50]\n 21]

test unixSelect-1.17 {TkSelGetSelection procedure: INCR i18n text, utf-8} -constraints {
    x11
} -setup {
    setupbg
} -body {
    dobg {
        pack [text .t]
        update
        .t insert 1.0 [string repeat [string repeat \u00c4\u00e4 50]\n 21]
        .t insert 1.0 [string repeat [string repeat Ää 50]\n 21]
        # Has to be selected in a separate stage
        .t tag add sel 1.0 21.end+1c
    }
    after 10
    selection get -type UTF8_STRING
} -cleanup {
    cleanupbg
} -result [string repeat [string repeat \u00c4\u00e4 50]\n 21]
} -result [string repeat [string repeat Ää 50]\n 21]

test unixSelect-1.18 {TkSelGetSelection procedure: INCR i18n text, utf-8} -constraints {
    x11
} -setup {
    setupbg
} -body {
    dobg {
        pack [text .t]
        update
        .t insert 1.0 i[string repeat [string repeat \u00c4\u00e4 50]\n 21]
        .t insert 1.0 i[string repeat [string repeat Ää 50]\n 21]
        # Has to be selected in a separate stage
        .t tag add sel 1.0 21.end+1c
    }
    after 10
    selection get -type UTF8_STRING
} -cleanup {
    cleanupbg
} -result i[string repeat [string repeat \u00c4\u00e4 50]\n 21]
} -result i[string repeat [string repeat Ää 50]\n 21]

test unixSelect-1.19 {Automatic UTF8_STRING support for selection handle} -constraints {
    unix
} -setup {
    destroy .l
} -body {
    # See Bug #666346 "Selection handling crashes under KDE 3.0"
Changes to tests/unixWm.test.
1
2
3
4
5
6
7



8
9
10
11
12
13
14
15



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

49
50
51



52
53
54
55
56
57
58
59

60
61
62
63
64
65
66
1
2
3
4



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24










25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42



43
44
45
46
47
48
49
50
51
52

53
54
55
56
57
58
59
60




-
-
-
+
+
+








+
+
+






-
-
-
-
-
-
-
-
-
-

















+
-
-
-
+
+
+







-
+







# This file is a Tcl script to test out Tk's interactions with
# the window manager, including the "wm" command.  It is organized
# in the standard fashion for Tcl tests.
#
# Copyright (c) 1992-1994 The Regents of the University of California.
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1992-1994 The Regents of the University of California.
# Copyright © 1994-1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
eval tcltest::configure $argv
tcltest::loadTestedCommands

namespace import -force ::tk::test:loadTkCommand

testConstraint failsOnUbuntu [expr {![info exists ::env(CI)] || ![string match Linux $::tcl_platform(os)]}]
testConstraint failsOnXQuarz [expr {$tcl_platform(os) ne "Darwin" || [tk windowingsystem] ne "x11" }]

proc sleep ms {
    global x
    after $ms {set x 1}
    vwait x
}

# The macOS window manager shows an animation when a window is deiconified.
# Tests which check the geometry of a window after deiconifying it should
# wait for the animation to finish.

 proc animationDelay {} {
    if {[tk windowingsystem] == "aqua"} {
    sleep 250
    }
 }

# Procedure to set up a collection of top-level windows

proc makeToplevels {} {
    deleteWindows
    foreach i {.raise1 .raise2 .raise3} {
	toplevel $i
	wm geom $i 150x100+0+0
	update
    }
}

# On macOS windows are not allowed to overlap the menubar at the top
# of the screen.  So tests which move a window and then check whether
# it got moved to the requested location should use a y coordinate
# larger than the height of the menubar (normally 23 pixels).

if {[tk windowingsystem] eq "aqua"} {
    set mb [expr [menubarheight] + 1]
    set Y0 23
    set Y2 25
    set Y5 28
    set Y0 $mb
    set Y2 [expr $mb + 2]
    set Y5 [expr $mb + 5]
} else {
    set Y0 0
    set Y2 2
    set Y5 5
}

set i 1
foreach geom "+23+80 +80+23 +0+$Y0" {
foreach geom "+$Y0+80 +80+$Y0 +0+$Y0" {
    destroy .t
    test unixWm-1.$i {initial window position} unix {
	toplevel .t -width 200 -height 150
	wm geom .t $geom
	update
	wm geom .t
    } 200x150$geom
78
79
80
81
82
83
84
85

86
87
88
89
90
91
92
93
94
95
96
97

98
99
100

101
102

103
104

105
106
107
108
109
110
111
112
113
114
115
116

117
118

119
120

121
122
123
124
125
126
127
72
73
74
75
76
77
78

79
80
81
82
83
84
85
86
87
88
89
90

91
92
93

94
95

96
97

98
99
100
101
102
103
104
105
106
107
108
109

110
111

112
113

114
115
116
117
118
119
120
121







-
+











-
+


-
+

-
+

-
+











-
+

-
+

-
+







wm geom .t +200+200
update
wm geom .t +150+150
update
scan [wm geom .t] %dx%d+%d+%d width height x y
set xerr [expr 150-$x]
set yerr [expr 150-$y]
foreach geom "+20+80 +80+23 +0+$Y0 -0-0 +0-0 -0+$Y0 -10-5 -10+$Y5 +10-5" {
foreach geom "+20+80 +80+$Y0 +0+$Y0 -0-0 +0-0 -0+$Y0 -10-5 -10+$Y5 +10-5" {
    test unixWm-2.$i {moving window while mapped} unix {
	wm geom .t $geom
	update
	scan [wm geom .t] %dx%d%1s%d%1s%d width height xsign x ysign y
	format "%s%d%s%d" $xsign [eval expr $x$xsign$xerr] $ysign \
		[eval expr $y$ysign$yerr]
    } $geom
    incr i
}

set i 1
foreach geom "+20+80 +80+23 +0+$Y0 -0-0 +0-0 -0+$Y0 -10-5 -10+$Y5 +10-5" {
foreach geom "+20+80 +80+$Y0 +0+$Y0 -0-0 +0-0 -0+$Y0 -10-5 -10+$Y5 +10-5" {
    test unixWm-3.$i {moving window while iconified} unix {
	wm iconify .t
	sleep 200
	update idletasks
	wm geom .t $geom
	update
	update idletasks
	wm deiconify .t
	animationDelay
	update idletasks
	scan [wm geom .t] %dx%d%1s%d%1s%d width height xsign x ysign y
	format "%s%d%s%d" $xsign [eval expr $x$xsign$xerr] $ysign \
		[eval expr $y$ysign$yerr]
    } $geom
    incr i
}

set i 1
foreach geom "+20+80 +100+40 +0+$Y0" {
    test unixWm-4.$i {moving window while withdrawn} unix {
	wm withdraw .t
	sleep 200
	update idletasks
	wm geom .t $geom
	update
	update idletasks
	wm deiconify .t
	animationDelay
	update idletasks
	wm geom .t
    } 100x150$geom
    incr i
}

test unixWm-5.1 {compounded state changes} {unix nonPortable} {
    destroy .t
190
191
192
193
194
195
196
197

198
199
200
201
202
203
204

205
206
207
208
209
210

211
212
213
214
215
216
217

218
219
220
221
222
223
224
184
185
186
187
188
189
190

191
192
193
194
195
196
197

198
199
200
201
202
203

204
205
206
207
208
209
210

211
212
213
214
215
216
217
218







-
+






-
+





-
+






-
+







    wm withdraw .t
    wm iconify .t
    list [winfo ismapped .t] [wm state .t]
} {0 iconic}

destroy .t
toplevel .t -width 200 -height 100
wm geom .t +10+23
wm geom .t +10+$Y0
wm minsize .t 1 1
update
test unixWm-6.1 {size changes} unix {
    .t config -width 180 -height 150
    update
    wm geom .t
} 180x150+10+23
} 180x150+10+$Y0
test unixWm-6.2 {size changes} unix {
    wm geom .t 250x60
    .t config -width 170 -height 140
    update
    wm geom .t
} 250x60+10+23
} 250x60+10+$Y0
test unixWm-6.3 {size changes} unix {
    wm geom .t 250x60
    .t config -width 170 -height 140
    wm geom .t {}
    update
    wm geom .t
} 170x140+10+23
} 170x140+10+$Y0
test unixWm-6.4 {size changes} {unix nonPortable userInteraction} {
    wm minsize .t 1 1
    update
    puts stdout "Please resize window \"t\" with the mouse (but don't move it!),"
    puts -nonewline stdout "then hit return: "
    flush stdout
    gets stdin
292
293
294
295
296
297
298
299

300
301
302
303

304
305
306
307
308
309
310
311
312
313

314
315
316
317
318
319
320
286
287
288
289
290
291
292

293
294
295
296
297
298
299
300
301
302
303
304
305
306
307

308
309
310
311
312
313
314
315







-
+




+









-
+







    list [catch {wm iconwindow} msg] $msg
} {1 {wrong # args: should be "wm option window ?arg ...?"}}
test unixWm-8.3 {icon windows} unix {
    destroy .t
    toplevel .t -width 100 -height 30
    list [catch {wm iconwindow .t b c} msg] $msg
} {1 {wrong # args: should be "wm iconwindow window ?pathName?"}}
test unixWm-8.4 {icon windows} unix {
test unixWm-8.4 {icon windows} {unix failsOnUbuntu} {
    destroy .t
    destroy .icon
    toplevel .t -width 100 -height 30
    wm geom .t +0+0
    update idletasks
    set result [wm iconwindow .t]
    toplevel .icon -width 50 -height 50 -bg red
    wm iconwindow .t .icon
    lappend result [wm iconwindow .t] [wm state .icon]
    wm iconwindow .t {}
    lappend result [wm iconwindow .t] [wm state .icon]
    update
    lappend result [winfo ismapped .t] [winfo ismapped .icon]
    wm iconify .t
    update
    update idletasks
    lappend result [winfo ismapped .t] [winfo ismapped .icon]
} {.icon icon {} withdrawn 1 0 0 0}
test unixWm-8.5 {icon windows} unix {
    destroy .t
    toplevel .t -width 100 -height 30
    list [catch {wm iconwindow .t .gorp} msg] $msg
} {1 {bad window path name ".gorp"}}
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
339
340
341
342
343
344
345

346
347
348
349
350
351
352







-







    wm geom .icon +0+0
    update
    set result [winfo ismapped .icon]
    toplevel .t -width 100 -height 30
    wm geom .t +0+0
    tkwait visibility .t	;# Needed to keep tvtwm happy.
    wm iconwindow .t .icon
    sleep 500
    lappend result [winfo ismapped .t] [winfo ismapped .icon]
} {1 1 0}
test unixWm-8.9 {icon windows} {unix nonPortable} {
    # This test is non-portable because some window managers will
    # destroy an icon window when it's associated window is destroyed.

    destroy .t
416
417
418
419
420
421
422
423
424
425

426
427
428
429
430
431
432
433
434

435
436
437
438
439
440
441

442
443
444
445
446
447
448
410
411
412
413
414
415
416

417

418
419
420

421
422
423
424
425

426
427
428
429
430
431
432

433
434
435
436
437
438
439
440







-

-
+


-





-
+






-
+







command
}
test unixWm-9.3 {TkWmMapWindow procedure, iconic windows} unix {
    destroy .t
    toplevel .t -width 100 -height 300 -bg blue
    wm geom .t +0+0
    wm iconify .t
    sleep 500
    winfo ismapped .t
} {0}
} 0
test unixWm-9.4 {TkWmMapWindow procedure, icon windows} unix {
    destroy .t
    sleep 500
    toplevel .t -width 100 -height 50 -bg blue
    tkwait visibility .t
    wm iconwindow . .t
    update
    set result [winfo ismapped .t]
} {0}
} 0
test unixWm-9.5 {TkWmMapWindow procedure, normal windows} unix {
    destroy .t
    toplevel .t -width 200 -height 20
    wm geom .t +0+0
    update
    winfo ismapped .t
} {1}
} 1

test unixWm-10.1 {TkWmDeadWindow procedure, canceling UpdateGeometry idle handler} unix {
    destroy .t
    toplevel .t -width 100 -height 50
    wm geom .t +0+0
    update
    .t configure -width 200 -height 100
639
640
641
642
643
644
645
646

647
648
649
650
651
652
653
631
632
633
634
635
636
637

638
639
640
641
642
643
644
645







-
+







    destroy .icon
    toplevel .icon -width 50 -height 50 -bg red
    wm iconwindow .t .icon
    set result [list [catch {wm deiconify .icon} msg] $msg]
    destroy .icon
    set result
} {1 {can't deiconify .icon: it is an icon for .t}}
test unixWm-16.3 {Tk_WmCmd procedure, "deiconify" option} unix {
test unixWm-16.3 {Tk_WmCmd procedure, "deiconify" option} {unix failsOnUbuntu} {
    wm iconify .t
    set result {}
    lappend result [winfo ismapped .t] [wm state .t]
    wm deiconify .t
    lappend result [winfo ismapped .t] [wm state .t]
} {0 iconic 1 normal}

668
669
670
671
672
673
674
675

676
677
678
679
680
681
682
683
684
685

686
687
688
689
690
691
692
660
661
662
663
664
665
666

667
668
669
670
671
672
673
674
675
676

677
678
679
680
681
682
683
684







-
+









-
+







} {passive active passive}

test unixWm-18.1 {Tk_WmCmd procedure, "frame" option} unix {
    list [catch {wm frame .t 12} msg] $msg
} {1 {wrong # args: should be "wm frame window"}}
test unixWm-18.2 {Tk_WmCmd procedure, "frame" option} {unix nonPortable} {
    expr [wm frame .t] == [winfo id .t]
} {0}
} 0
test unixWm-18.3 {Tk_WmCmd procedure, "frame" option} {unix nonPortable} {
    destroy .t2
    toplevel .t2
    wm geom .t2 +0+0
    wm overrideredirect .t2 1
    update
    set result [expr [wm frame .t2] == [winfo id .t2]]
    destroy .t2
    set result
} {1}
} 1

test unixWm-19.1 {Tk_WmCmd procedure, "geometry" option} unix {
    list [catch {wm geometry .t 12 13} msg] $msg
} {1 {wrong # args: should be "wm geometry window ?newGeometry?"}}
test unixWm-19.2 {Tk_WmCmd procedure, "geometry" option} {unix nonPortable} {
    wm geometry .t -1+5
    update
789
790
791
792
793
794
795
796

797
798
799
800
801
802
803
781
782
783
784
785
786
787

788
789
790
791
792
793
794
795







-
+







    toplevel .t2
    wm geom .t2 +0+0
    wm group .t .t2
    set hints [testprop [testwrapper .t] WM_HINTS]
    set result [expr [testwrapper .t2] - [lindex $hints 8]]
    destroy .t2
    set result
} {0}
} 0
test unixWm-21.5 {Tk_WmCmd procedure, "group" option, create leader wrapper} {unix testwrapper} {
    destroy .t2
    destroy .t3
    toplevel .t2 -width 120 -height 300
    wm geometry .t2 +0+0
    toplevel .t3 -width 120 -height 300
    wm geometry .t2 +0+0
857
858
859
860
861
862
863
864
865


866
867
868
869

870
871

872
873
874
875
876


877
878
879
880

881
882
883

884
885
886
887
888
889
890
849
850
851
852
853
854
855


856
857
858
859
860

861
862

863
864
865
866


867
868
869
870
871

872
873
874

875
876
877
878
879
880
881
882







-
-
+
+



-
+

-
+



-
-
+
+



-
+


-
+







    destroy .t2
    toplevel .t2
    wm geom .t2 +0+0
    wm iconwindow .t .t2
    set result [list [catch {wm iconify .t2} msg] $msg]
    destroy .t2
    set result
} {1 {can't iconify .t2: it is an icon for .t}}
test unixWm-23.5 {Tk_WmCmd procedure, "iconify" option} unix {
} {1 {can't iconify ".t2": it is an icon for ".t"}}
test unixWm-23.5 {Tk_WmCmd procedure, "iconify" option} {unix failsOnUbuntu} {
    destroy .t2
    toplevel .t2
    wm geom .t2 +0+0
    update
    update idletasks
    wm iconify .t2
    update
    update idletasks
    set result [winfo ismapped .t2]
    destroy .t2
    set result
} {0}
test unixWm-23.6 {Tk_WmCmd procedure, "iconify" option} unix {
} 0
test unixWm-23.6 {Tk_WmCmd procedure, "iconify" option} {unix failsOnUbuntu} {
    destroy .t2
    toplevel .t2
    wm geom .t2 -0+0
    update
    update idletasks
    set result [winfo ismapped .t2]
    wm iconify .t2
    update
    update idletasks
    lappend result [winfo ismapped .t2]
    destroy .t2
    set result
} {1 0}

test unixWm-24.1 {Tk_WmCmd procedure, "iconmask" option} unix {
    list [catch {wm iconmask .t 12 13} msg] $msg
1305
1306
1307
1308
1309
1310
1311
1312

1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323

1324
1325
1326
1327
1328
1329
1330
1297
1298
1299
1300
1301
1302
1303

1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314

1315
1316
1317
1318
1319
1320
1321
1322







-
+










-
+







    lappend result [wm transient .t2] [expr [testwrapper .t] - $transient]
    wm transient .t2 {}
    lappend result [wm transient .t2] \
	    [testprop [testwrapper .t2] WM_TRANSIENT_FOR]
    destroy .t2
    set result
} {{} {} .t 0 {} {}}
test unixWm-37.4 {TkWmDeadWindow, destroy on master should clear transient} {unix testwrapper} {
test unixWm-37.4 {TkWmDeadWindow, destroy on toplevel should clear transient} {unix testwrapper} {
    destroy .t2
    toplevel .t2
    destroy .t3
    toplevel .t3
    wm transient .t2 .t3
    update
    destroy .t3
    update
    list [wm transient .t2] [testprop [testwrapper .t2] WM_TRANSIENT_FOR]
} {{} {}}
test unixWm-37.5 {Tk_WmCmd procedure, "transient" option, create master wrapper} {unix testwrapper} {
test unixWm-37.5 {Tk_WmCmd procedure, "transient" option, create toplevel wrapper} {unix testwrapper} {
    destroy .t2
    destroy .t3
    toplevel .t2 -width 120 -height 300
    wm geometry .t2 +0+0
    toplevel .t3 -width 120 -height 300
    wm geometry .t2 +0+0
    set result [list [testwrapper .t2]]
1380
1381
1382
1383
1384
1385
1386
1387
1388


1389
1390
1391
1392

1393
1394
1395
1396
1397
1398
1399
1372
1373
1374
1375
1376
1377
1378

1379
1380
1381
1382
1383
1384

1385
1386
1387
1388
1389
1390
1391
1392







-

+
+



-
+







    update
    wm geometry .t
} "20x20+0+$Y0"

test unixWm-41.1 {ConfigureEvent procedure, internally generated size changes} unix {
    destroy .t
    toplevel .t -width 400 -height 150
    wm geometry .t +0+0
    tkwait visibility .t
    wm geometry .t +0+0
    update idletasks
    set result {}
    lappend result [winfo width .t] [winfo height .t]
    .t configure -width 200 -height 300
    sleep 500
    update idletasks
    lappend result [winfo width .t] [winfo height .t]
} {400 150 200 300}
test unixWm-41.2 {ConfigureEvent procedure, menubars} {nonPortable testmenubar} {
    destroy .t
    toplevel .t -width 300 -height 200 -bd 2 -relief raised
    wm geom .t +0+0
    update
1439
1440
1441
1442
1443
1444
1445
1446

1447
1448
1449
1450
1451
1452
1453
1454
1455
1456

1457
1458
1459
1460

1461
1462
1463
1464
1465
1466
1467
1432
1433
1434
1435
1436
1437
1438

1439
1440
1441
1442
1443
1444
1445
1446
1447
1448

1449
1450
1451
1452

1453
1454
1455
1456
1457
1458
1459
1460







-
+









-
+



-
+







    update
    set result
} {configured: 130 200}

# No tests for ReparentEvent or ComputeReparentGeometry; I can't figure
# out how to exercise these procedures reliably.

test unixWm-42.1 {WrapperEventProc procedure, map and unmap events} unix {
test unixWm-42.1 {WrapperEventProc procedure, map and unmap events} {unix failsOnUbuntu} {
    destroy .t
    toplevel .t -width 400 -height 150
    wm geometry .t +0+0
    tkwait visibility .t
    set result {}
    bind .t <Map> {set x "mapped"}
    bind .t <Unmap> {set x "unmapped"}
    set x {no event}
    wm iconify .t
    animationDelay
    update idletasks
    lappend result $x [winfo ismapped .t]
    set x {no event}
    wm deiconify .t
    animationDelay
    update idletasks
    lappend result $x [winfo ismapped .t]
} {unmapped 0 mapped 1}

test unixWm-43.1 {TopLevelReqProc procedure, embedded in same process} unix {
    destroy .t
    toplevel .t -width 200 -height 200
    wm geom .t +0+0
1556
1557
1558
1559
1560
1561
1562
1563

1564
1565
1566
1567
1568
1569
1570
1571
1572
1573

1574
1575
1576
1577
1578
1579
1580
1549
1550
1551
1552
1553
1554
1555

1556
1557
1558
1559
1560
1561
1562
1563
1564
1565

1566
1567
1568
1569
1570
1571
1572
1573







-
+









-
+







    tkwait visibility .t
    wm geometry .t 20x1
    update
    list [winfo width .t] [winfo height .t]
} {100 1}
destroy .t
toplevel .t -width 80 -height 60
test unixWm-44.7 {UpdateGeometryInfo procedure, computing position} unix {
test unixWm-44.7 {UpdateGeometryInfo procedure, computing position} {unix failsOnXQuarz} {
    tkwait visibility .t
    wm overrideredirect .t 1
    update
    wm geometry .t +5-10
    update
    list [winfo x .t] [winfo y .t]
} [list 5 [expr [winfo screenheight .t] - 70]]
destroy .t
toplevel .t -width 80 -height 60
test unixWm-44.8 {UpdateGeometryInfo procedure, computing position} unix {
test unixWm-44.8 {UpdateGeometryInfo procedure, computing position} {unix failsOnXQuarz} {
    tkwait visibility .t
    wm overrideredirect .t 1
    update
    wm geometry .t -30+$Y2
    update
    list [winfo x .t] [winfo y .t]
} [list [expr [winfo screenwidth .t] - 110] $Y2]
1616
1617
1618
1619
1620
1621
1622
1623

1624
1625
1626
1627
1628
1629
1630
1609
1610
1611
1612
1613
1614
1615

1616
1617
1618
1619
1620
1621
1622
1623







-
+







    wm geometry .t +0+0
    tkwait visibility .t
    set property [testprop [testwrapper .t] WM_NORMAL_HINTS]
    list [expr [lindex $property 5]] [expr [lindex $property 6]] \
	    [expr [lindex $property 7]] [expr [lindex $property 8]] \
	    [expr [lindex $property 9]] [expr [lindex $property 10]]
} {40 30 320 210 10 5}
test unixWm-45.2 {UpdateSizeHints procedure} {unix testwrapper} {
test unixWm-45.2 {UpdateSizeHints procedure} {unix testwrapper failsOnUbuntu failsOnXQuarz} {
    destroy .t
    toplevel .t -width 80 -height 60
    wm minsize .t 30 40
    wm maxsize .t 200 500
    wm geometry .t +0+0
    tkwait visibility .t
    set property [testprop [testwrapper .t] WM_NORMAL_HINTS]
1644
1645
1646
1647
1648
1649
1650
1651

1652
1653
1654
1655
1656
1657
1658
1637
1638
1639
1640
1641
1642
1643

1644
1645
1646
1647
1648
1649
1650
1651







-
+







    tkwait visibility .t
    set property [testprop [testwrapper .t] WM_NORMAL_HINTS]
    list [winfo height .t] \
	    [expr [lindex $property 5]] [expr [lindex $property 6]] \
	    [expr [lindex $property 7]] [expr [lindex $property 8]] \
	    [expr [lindex $property 9]] [expr [lindex $property 10]]
} {60 40 53 320 233 10 5}
test unixWm-45.4 {UpdateSizeHints procedure, not resizable with menu} {testmenubar testwrapper} {
test unixWm-45.4 {UpdateSizeHints procedure, not resizable with menu} {testmenubar testwrapper failsOnUbuntu failsOnXQuarz} {
    destroy .t
    toplevel .t -width 80 -height 60
    frame .t.menu -height 23 -width 50
    testmenubar window .t .t.menu
    wm resizable .t 0 0
    wm geometry .t +0+0
    tkwait visibility .t
1740
1741
1742
1743
1744
1745
1746
1747

1748
1749
1750

1751
1752
1753
1754
1755
1756
1757
1733
1734
1735
1736
1737
1738
1739

1740
1741
1742

1743
1744
1745
1746
1747
1748
1749
1750







-
+


-
+







    list [catch {wm geometry .t +20-} msg] $msg
} {1 {bad geometry specifier "+20-"}}
test unixWm-48.10 {ParseGeometry procedure} unix {
    list [catch {wm geometry .t +20+10z} msg] $msg
} {1 {bad geometry specifier "+20+10z"}}
test unixWm-48.11 {ParseGeometry procedure} unix {
    catch {wm geometry .t +-10+20}
} {0}
} 0
test unixWm-48.12 {ParseGeometry procedure} unix {
    catch {wm geometry .t +30+-10}
} {0}
} 0
test unixWm-48.13 {ParseGeometry procedure, resize causes window to move} unix {
    destroy .t
    toplevel .t -width 200 -height 200
    wm geom .t +0+0
    update
    wm geom .t -0-0
    update
1798
1799
1800
1801
1802
1803
1804
1805

1806
1807
1808
1809
1810
1811
1812
1791
1792
1793
1794
1795
1796
1797

1798
1799
1800
1801
1802
1803
1804
1805







-
+







if {[tk windowingsystem] == "aqua"} {
    # Modern mac windows have no border.
    set result_50_1 {{} {} .t .t .t2 {} .t2 .t .t}
} else {
    # Windows are assumed to have a border (invisible in Gnome 3).
    set result_50_1 {{} {} .t {} .t2 {} .t2 {} .t}
}
test unixWm-50.1 {Tk_CoordsToWindow procedure, finding a toplevel, x-coords, title bar} unix {
test unixWm-50.1 {Tk_CoordsToWindow procedure, finding a toplevel, x-coords, title bar} {unix failsOnUbuntu failsOnXQuarz} {
    update
    toplevel .t -width 300 -height 400 -bg green
    wm geom .t +100+100
    tkwait visibility .t
    toplevel .t2 -width 100 -height 200 -bg red
    wm geom .t2 +200+200
    tkwait visibility .t2
1846
1847
1848
1849
1850
1851
1852
1853

1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864




1865
1866
1867
1868
1869
1870
1871
1872
1873
1874



1875
1876
1877
1878
1879
1880
1881
1882
1883
1884

1885
1886
1887
1888
1889
1890
1891



1892
1893
1894


1895
1896
1897
1898
1899
1900
1901
1839
1840
1841
1842
1843
1844
1845

1846
1847
1848
1849
1850
1851
1852
1853




1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864



1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876

1877
1878
1879
1880
1881



1882
1883
1884
1885


1886
1887
1888
1889
1890
1891
1892
1893
1894







-
+







-
-
-
-
+
+
+
+







-
-
-
+
+
+









-
+




-
-
-
+
+
+

-
-
+
+







	 [winfo containing [expr $x +200] [expr $y2 + 100]] \
	 [winfo containing [expr $x +200] [expr $y + 450]]
} {{} {} .t .t .t2 .t2 .t {}}
test unixWm-50.3 {
	Tk_CoordsToWindow procedure, finding a toplevel with embedding
} tempNotWin {
    deleteWindows
    catch {interp delete slave}
    catch {interp delete child}

    toplevel .t -width 300 -height 400 -bg blue
    wm geom .t +100+100
    frame .t.f -container 1 -bg red
    place .t.f -x 150 -y 50
    tkwait visibility .t.f
    update
    interp create slave
    load {} Tk slave
    slave alias frameid winfo id .t.f
    slave eval {
    interp create child
    load {} Tk child
    child alias frameid winfo id .t.f
    child eval {
	wm withdraw .
        toplevel .x -width 100 -height 80 -use [frameid] -bg yellow
        tkwait visibility .x
        update
        set x [winfo rootx .x]
        set y [winfo rooty .x]
    }
    set result [list [slave eval {winfo containing [expr $x - 1]  [expr $y + 50]}] \
	       	     [slave eval {winfo containing $x [expr $y + 50]}]]
    interp delete slave
    set result [list [child eval {winfo containing [expr $x - 1]  [expr $y + 50]}] \
	       	     [child eval {winfo containing $x [expr $y + 50]}]]
    interp delete child
    set x [winfo rootx .t]
    set y [winfo rooty .t]
    lappend result [winfo containing [expr $x + 200] [expr $y + 49]] \
	[winfo containing [expr $x + 200] [expr $y +50]]
    set result
} {{} .x .t .t.f}
test unixWm-50.4 {Tk_CoordsToWindow procedure, window in other application} unix {
    destroy .t

    catch {interp delete slave}
    catch {interp delete child}
    toplevel .t -width 200 -height 200 -bg green
    wm geometry .t +100+100
    tkwait visibility .t
    update
    interp create slave
    load {} Tk slave
    slave eval {wm geometry . 200x200+100+100; tkwait visibility . ; update}
    interp create child
    load {} Tk child
    child eval {wm geometry . 200x200+100+100; tkwait visibility . ; update}
    set result [list [winfo containing 200 200] \
	    [slave eval {winfo containing 200 200}]]
    interp delete slave
	    [child eval {winfo containing 200 200}]]
    interp delete child
    set result
} {{} .}
test unixWm-50.5 {Tk_CoordsToWindow procedure, handling menubars} {unix testmenubar} {
    deleteWindows
    toplevel .t -width 300 -height 400 -bd 2 -relief raised
    frame .t.f -width 150 -height 120 -bg green
    place .t.f -x 10 -y 150
1949
1950
1951
1952
1953
1954
1955
1956

1957
1958
1959
1960
1961
1962

1963
1964
1965
1966
1967
1968
1969
1970

1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982

1983
1984
1985
1986
1987
1988
1989
1990
1991

1992
1993
1994

1995
1996
1997
1998
1999
2000
2001
1942
1943
1944
1945
1946
1947
1948

1949
1950
1951
1952
1953
1954

1955
1956
1957
1958
1959
1960
1961
1962

1963
1964
1965

1966
1967
1968
1969
1970
1971
1972
1973

1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986

1987
1988
1989
1990
1991
1992
1993
1994







-
+





-
+







-
+


-








-
+









+


-
+







	    [winfo containing $x [expr $y + 250]] \
	    [winfo containing $x [expr $y + 350]] \
	    [winfo containing $x [expr $y + 450]]
} {.t .t.f .t.f.f .t {}}
test unixWm-50.8 {Tk_CoordsToWindow procedure, more basics} unix {
    destroy .t
    toplevel .t -width 400 -height 300 -bg green
    wm geom .t +0+0
    wm geom .t +0+30
    frame .t.f -width 200 -height 100 -bd 2 -relief raised
    place .t.f -x 100 -y 100
    frame .t.f.f -width 200 -height 100 -bd 2 -relief raised
    place .t.f.f -x 100 -y 0
    update
    set x [winfo rooty .t]
    set x [winfo rootx .t]
    set y [expr [winfo rooty .t] + 150]
    list [winfo containing [expr $x + 50] $y] \
	    [winfo containing [expr $x + 150] $y] \
	    [winfo containing [expr $x + 250] $y] \
	    [winfo containing [expr $x + 350] $y] \
	    [winfo containing [expr $x + 450] $y]
} {.t .t.f .t.f.f .t {}}
test unixWm-50.9 {Tk_CoordsToWindow procedure, unmapped windows} unix {
test unixWm-50.9 {Tk_CoordsToWindow procedure, unmapped windows} {unix failsOnUbuntu} {
    destroy .t
    destroy .t2
    sleep 500		;# Give window manager time to catch up.
    toplevel .t -width 200 -height 200 -bg green
    wm geometry .t +0+0
    tkwait visibility .t
    toplevel .t2 -width 200 -height 200 -bg red
    wm geometry .t2 +0+0
    tkwait visibility .t2
    set result [list [winfo containing 100 100]]
    wm iconify .t2
    animationDelay
    update idletasks
    lappend result [winfo containing 100 100]
} {.t2 .t}
test unixWm-50.10 {Tk_CoordsToWindow procedure, unmapped windows} unix {
    destroy .t
    toplevel .t -width 200 -height 200 -bg green
    wm geometry .t +0+0
    frame .t.f -width 150 -height 150 -bd 2 -relief raised
    place .t.f -x 25 -y 25
    tkwait visibility .t.f
    update idletasks
    set result [list [winfo containing 100 100]]
    place forget .t.f
    update
    update idletasks
    lappend result [winfo containing 100 100]
} {.t.f .t}
deleteWindows
wm deiconify .

# No tests for UpdateVRootGeometry, Tk_GetVRootGeometry,
# Tk_MoveToplevelWindow, UpdateWmProtocols, or TkWmProtocolEventProc.
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065

2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2010
2011
2012
2013
2014
2015
2016

2017
2018
2019
2020
2021
2022
2023
2024
2025
2026

2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040

2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054

2055
2056
2057
2058
2059
2060
2061
2062

2063
2064
2065

2066
2067
2068
2069
2070
2071
2072







-










-














-














-
+







-



-







    update
    raise .raise3
    raise .raise2
    raise .raise1 .raise3
    set result [winfo containing [winfo rootx .raise1] \
	    [winfo rooty .raise1]]
    destroy .raise2
    sleep 500
    list $result [winfo containing [winfo rootx .raise1] \
	    [winfo rooty .raise1]]
} {.raise2 .raise1}
test unixWm-51.4 {TkWmRestackToplevel procedure, basic tests} {unix nonPortable} {
    makeToplevels
    raise .raise2
    raise .raise1
    lower .raise3 .raise1
    set result [winfo containing 100 100]
    destroy .raise1
    sleep 500
    lappend result [winfo containing 100 100]
} {.raise1 .raise3}
test unixWm-51.5 {TkWmRestackToplevel procedure, basic tests} {unix nonPortable} {
    makeToplevels
    update
    raise .raise2
    raise .raise1
    raise .raise3
    frame .raise1.f1
    frame .raise1.f1.f2
    lower .raise3 .raise1.f1.f2
    set result [winfo containing [winfo rootx .raise1] \
	    [winfo rooty .raise1]]
    destroy .raise1
    sleep 500
    list $result [winfo containing [winfo rootx .raise2] \
	    [winfo rooty .raise2]]
} {.raise1 .raise3}
deleteWindows
test unixWm-51.6 {TkWmRestackToplevel procedure, window to be stacked isn't mapped} unix {
    destroy .t
    toplevel .t -width 200 -height 200 -bg green
    wm geometry .t +0+0
    tkwait visibility .t
    destroy .t2
    toplevel .t2 -width 200 -height 200 -bg red
    wm geometry .t2 +0+0
    winfo containing 100 100
} {.t}
test unixWm-51.7 {TkWmRestackToplevel procedure, other window isn't mapped} unix {
test unixWm-51.7 {TkWmRestackToplevel procedure, other window isn't mapped} {unix failsOnXQuarz} {
    foreach w {.t .t2 .t3} {
	destroy $w
	update
	toplevel $w -width 200 -height 200 -bg green
	wm geometry $w +0+0
    }
    raise .t .t2
    sleep 2000
    update
    set result [list [winfo containing 100 100]]
    lower .t3
    sleep 2000
    lappend result [winfo containing 100 100]
} {.t3 .t}
test unixWm-51.8 {TkWmRestackToplevel procedure, overrideredirect windows} unix {
    destroy .t
    toplevel .t -width 200 -height 200 -bg green
    wm overrideredirect .t 1
    wm geometry .t +0+0
2246
2247
2248
2249
2250
2251
2252
2253

2254
2255
2256
2257
2258
2259
2260
2234
2235
2236
2237
2238
2239
2240

2241
2242
2243
2244
2245
2246
2247
2248







-
+







    .m add command -label Second
    .m add command -label Third
    .m post 30 30
    update
    set result [wm overrideredirect .m]
    destroy .m
    set result
} {1}
} 1

# No tests for TkGetPointerCoords, CreateWrapper, or GetMaxSize.

test unixWm-55.1 {TkUnixSetMenubar procedure} {unix testmenubar} {
    destroy .t
    toplevel .t -width 300 -height 200 -bd 2 -relief raised
    wm geom .t +0+0
Changes to tests/util.test.
1
2
3
4
5
6



7
8
9
10
11
12
13
1
2
3



4
5
6
7
8
9
10
11
12
13



-
-
-
+
+
+







# This file is a Tcl script to test out the procedures in the file
# tkUtil.c.  It is organized in the standard fashion for Tcl tests.
#
# Copyright (c) 1994 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1994 The Regents of the University of California.
# Copyright © 1994 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
eval tcltest::configure $argv
tcltest::loadTestedCommands
namespace import -force tcltest::test

24
25
26
27
28
29
30
31

32
33
34

35
36
37

38
39
40
41
42

43
44
45
46
47

48
49
50
51
52

53
54
55
56
57

58
59
60

61
62
63
64
65
66
67
68
24
25
26
27
28
29
30

31
32
33

34
35
36

37
38
39
40
41

42
43
44
45
46

47
48
49
50
51

52
53
54
55
56

57
58
59

60
61
62
63
64
65
66
67
68







-
+


-
+


-
+




-
+




-
+




-
+




-
+


-
+








test util-1.3 {Tk_GetScrollInfo procedure} -body {
    .l yview 0
    .l yview moveto .5
    .l yview
} -result {0.5 0.75}
test util-1.4 {Tk_GetScrollInfo procedure} -body {
    .l yview scroll a
} -returnCodes error -result {wrong # args: should be ".l yview scroll number units|pages"}
} -returnCodes error -result {wrong # args: should be ".l yview scroll number pages|units"}
test util-1.5 {Tk_GetScrollInfo procedure} -body {
    .l yview scroll a b c
} -returnCodes error -result {wrong # args: should be ".l yview scroll number units|pages"}
} -returnCodes error -result {wrong # args: should be ".l yview scroll number pages|units"}
test util-1.6 {Tk_GetScrollInfo procedure} -body {
    .l yview scroll xyz units
} -returnCodes error -result {expected integer but got "xyz"}
} -returnCodes error -result {expected floating-point number but got "xyz"}
test util-1.7 {Tk_GetScrollInfo procedure} -body {
    .l yview 0
    .l yview scroll 2 pages
    .l nearest 0
} -result {6}
} -result 6
test util-1.8 {Tk_GetScrollInfo procedure} -body {
    .l yview 15
    .l yview scroll -2 pages
    .l nearest 0
} -result {9}
} -result 9
test util-1.9 {Tk_GetScrollInfo procedure} -body {
    .l yview 0
    .l yview scroll 2 units
    .l nearest 0
} -result {2}
} -result 2
test util-1.10 {Tk_GetScrollInfo procedure} -body {
    .l yview 15
    .l yview scroll -2 units
    .l nearest 0
} -result {13}
} -result 13
test util-1.11 {Tk_GetScrollInfo procedure} -body {
    .l yview scroll 3 zips
} -returnCodes error -result {bad argument "zips": must be units or pages}
} -returnCodes error -result {bad argument "zips": must be pages or units}
test util-1.12 {Tk_GetScrollInfo procedure} -body {
    .l yview dropdead 3 times
} -returnCodes error -result {unknown option "dropdead": must be moveto or scroll}

# cleanup
cleanupTests
return

Changes to tests/visual.test.
1
2
3
4
5
6
7



8
9
10
11
12
13
14
1
2
3
4



5
6
7
8
9
10
11
12
13
14




-
-
-
+
+
+







# This file is a Tcl script to test the visual- and colormap-handling
# procedures in the file tkVisual.c.  It is organized in the standard
# fashion for Tcl tests.
#
# Copyright (c) 1994 The Regents of the University of California.
# Copyright (c) 1994-1995 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1994 The Regents of the University of California.
# Copyright © 1994-1995 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
namespace import ::tcltest::*
tcltest::configure {*}$argv
tcltest::loadTestedCommands

451
452
453
454
455
456
457
458

459
460
461
462
463
464
465
466
467
468
469
470
471

472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487

488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503

504
505
506
507
508
509
510
451
452
453
454
455
456
457

458
459
460
461
462
463
464
465
466
467
468
469
470

471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486

487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502

503
504
505
506
507
508
509
510







-
+












-
+















-
+















-
+







    eatColors .t1
    toplevel .t2 -width 30 -height 20
    wm geom .t2 +0+0
    update
    colorsFree .t2
} -cleanup {
    deleteWindows
} -result {0}
} -result 0
test visual-7.2 {Tk_GetColormap, "new"} -constraints {
    defaultPseudocolor8 nonPortable
} -setup {
    deleteWindows
} -body {
    eatColors .t1
    toplevel .t2 -width 30 -height 20 -colormap new
    wm geom .t2 +0+0
    update
    colorsFree .t2
} -cleanup {
    deleteWindows
} -result {1}
} -result 1
test visual-7.3 {Tk_GetColormap, copy from other window} -constraints {
    defaultPseudocolor8 nonPortable
} -setup {
    deleteWindows
} -body {
    eatColors .t1
    toplevel .t3 -width 400 -height 50 -colormap new
    wm geom .t3 +0+0
    toplevel .t2 -width 30 -height 20 -colormap .t3
    wm geom .t2 +0+0
    update
    destroy .t3
    colorsFree .t2
} -cleanup {
    deleteWindows
} -result {1}
} -result 1
test visual-7.4 {Tk_GetColormap, copy from other window} -constraints {
    defaultPseudocolor8 nonPortable
} -setup {
    deleteWindows
} -body {
    eatColors .t1
    toplevel .t3 -width 400 -height 50 -colormap new
    wm geom .t3 +0+0
    toplevel .t2 -width 30 -height 20 -colormap .
    wm geom .t2 +0+0
    update
    destroy .t3
    colorsFree .t2
} -cleanup {
    deleteWindows
} -result {0}
} -result 0
test visual-7.5 {Tk_GetColormap, copy from other window} -constraints {
    defaultPseudocolor8 nonPortable
} -setup {
    deleteWindows
} -body {
    toplevel .t1 -width 400 -height 50 -colormap .choke.lots
} -cleanup {
Changes to tests/visual_bb.test.
19
20
21
22
23
24
25
26

27
28
29
30
31
32
33
19
20
21
22
23
24
25

26
27
28
29
30
31
32
33







-
+








# Each menu entry invokes a visual test file

proc runTest {file} {
    global testNum

    test "2.$testNum" "testing $file" {userInteraction} {
    uplevel \#0 source [file join [testsDirectory] $file]
    uplevel #0 [list source -encoding utf-8 [file join [testsDirectory] $file]]
    concat ""
    } {}
    incr testNum
}

# The following procedure is invoked to print the contents of a canvas:

48
49
50
51
52
53
54
55

56
57
58
59
60
61
62
63
64
65
66
67

68
69
70
71
72
73
74
75
76
77
78
79

80
81
82
83
84
85
86
87
88
89
90
91
92

93
94

95
96
97


98
99
100
101
102
103
104
105
106
107

108
109
110
111
112
113
114
115
116
48
49
50
51
52
53
54

55
56
57
58
59
60
61
62
63
64
65
66

67
68
69
70
71
72
73
74
75
76
77
78

79
80
81
82
83
84
85
86
87
88
89
90
91

92
93

94
95


96
97
98
99
100
101
102
103
104
105
106

107
108
109
110
111
112
113
114
115
116







-
+











-
+











-
+












-
+

-
+

-
-
+
+









-
+









    # menu bar and a message explaining the basic operation
    # of the program.
    #-------------------------------------------------------

    frame .menu -relief raised -borderwidth 1
    message .msg -font {Times 18} -relief raised -width 4i \
        -borderwidth 1 -text "This application provides a collection of visual tests for the Tk toolkit.  Each menu entry invokes a test, which displays information on the screen.  You can then verify visually that the information is being displayed in the correct way.  The tests under the \"Postscript\" menu exercise the Postscript-generation capabilities of canvas widgets."
   

    pack .menu -side top -fill x
    pack .msg -side bottom -expand yes -fill both

    #-------------------------------------------------------
    # The code below creates all the menus, which invoke procedures
    # to create particular demonstrations of various widgets.
    #-------------------------------------------------------

    menubutton .menu.file -text "File" -menu .menu.file.m
    menu .menu.file.m
    .menu.file.m add command -label "Quit" -command end
   

    menubutton .menu.group1 -text "Group 1" -menu .menu.group1.m
    menu .menu.group1.m
    .menu.group1.m add command -label "Canvas arcs" -command {runTest arc.tcl}
    .menu.group1.m add command -label "Beveled borders in text widgets" \
        -command {runTest bevel.tcl}
    .menu.group1.m add command -label "Colormap management" \
        -command {runTest cmap.tcl}
    .menu.group1.m add command -label "Label/button geometry" \
        -command {runTest butGeom.tcl}
    .menu.group1.m add command -label "Label/button colors" \
        -command {runTest butGeom2.tcl}
   

    menubutton .menu.ps -text "Canvas Postscript" -menu .menu.ps.m
    menu .menu.ps.m
    .menu.ps.m add command -label "Rectangles and other graphics" \
        -command {runTest canvPsGrph.tcl}
    .menu.ps.m add command -label "Text" \
        -command {runTest canvPsText.tcl}
    .menu.ps.m add command -label "Bitmaps" \
        -command {runTest canvPsBmap.tcl}
    .menu.ps.m add command -label "Images" \
        -command {runTest canvPsImg.tcl}
    .menu.ps.m add command -label "Arcs" \
        -command {runTest canvPsArc.tcl}
   

    pack .menu.file .menu.group1 .menu.ps -side left -padx 1m
   

    # Set up for keyboard-based menu traversal
   
    bind . <Any-FocusIn> {

    bind . <FocusIn> {
    if {("%d" == "NotifyVirtual") && ("%m" == "NotifyNormal")} {
        focus .menu
    }
    }
    tk_menuBar .menu .menu.file .menu.group1 .menu.ps

    # Set up a class binding to allow objects to be deleted from a canvas
    # by clicking with mouse button 1:

    bind Canvas <1> {%W delete [%W find closest %x %y]}
    bind Canvas <Button-1> {%W delete [%W find closest %x %y]}

    concat ""
} -result {}

if {![testConstraint userInteraction]} {
    cleanupTests
} else {
    vwait EndOfVisualTests
}
Changes to tests/winButton.test.
1
2
3
4
5
6
7
8



9
10
11
12
13
14
15
1
2
3
4
5



6
7
8
9
10
11
12
13
14
15





-
-
-
+
+
+







# This file is a Tcl script to test the Windows specific behavior of
# labels, buttons, checkbuttons, and radiobuttons in Tk (i.e., all the
# widgets defined in tkWinButton.c).  It is organized in the standard
# fashion for Tcl tests.
#
# Copyright (c) 1994 The Regents of the University of California.
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1994 The Regents of the University of California.
# Copyright © 1994-1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
namespace import ::tcltest::*
tcltest::configure {*}$argv
tcltest::loadTestedCommands
imageInit
Changes to tests/winClipboard.test.
1
2
3
4
5
6
7
8
9
10


11
12
13
14
15
16
17
1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
16
17








-
-
+
+







# This file is a Tcl script to test out Tk's Windows specific
# clipboard code.  It is organized in the standard fashion for Tcl
# tests.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1997 by Sun Microsystems, Inc.
# Copyright (c) 1998-2000 by Scriptics Corporation.
# Copyright © 1997 Sun Microsystems, Inc.
# Copyright © 1998-2000 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
eval tcltest::configure $argv
tcltest::loadTestedCommands
namespace import -force tcltest::test

66
67
68
69
70
71
72
73

74
75
76
77
78

79
80
81
82
83
84
85

86
87
88
89

90
91
92
93
94
95
96
97
66
67
68
69
70
71
72

73
74
75
76
77

78
79
80
81
82
83
84

85
86
87
88

89

90
91
92
93
94
95
96







-
+




-
+






-
+



-
+
-








test winClipboard-1.5 {TkSelGetSelection & TkWinClipboardRender} -constraints {
    win testclipboard
} -setup {
    clipboard clear
} -body {
    set map [list "\r" "\\r" "\n" "\\n"]
    clipboard append "line 1\u00c7\nline 2"
    clipboard append "line 1Ç\nline 2"
    list [string map $map [selection get -selection CLIPBOARD]]\
        [string map $map [testclipboard]]
} -cleanup {
    clipboard clear
} -result [list "line 1\u00c7\\nline 2" "line 1\u00c7\\nline 2"]
} -result [list "line 1Ç\\nline 2" "line 1Ç\\nline 2"]

test winClipboard-1.6 {TkSelGetSelection & TkWinClipboardRender} -constraints {
    win testclipboard
} -setup {
    clipboard clear
} -body {
    clipboard append "\u043f\u0440\u0438\u0432\u0435\u0442 \u043c\u0438\u0444"
    clipboard append "привет миф"
    list [selection get -selection CLIPBOARD] [testclipboard]
} -cleanup {
    clipboard clear
} -result [list "\u043f\u0440\u0438\u0432\u0435\u0442 \u043c\u0438\u0444"\
} -result [list "привет миф" "привет миф"]
              "\u043f\u0440\u0438\u0432\u0435\u0442 \u043c\u0438\u0444"]

test winClipboard-2.1 {TkSelUpdateClipboard reentrancy problem} -constraints {
    win testclipboard
} -setup {
    clipboard clear
} -body {
    clipboard append -type OUR_ACTION "action data"
Changes to tests/winDialog.test.
1
2
3
4
5
6
7
8



9
10
11
12
13
14
15
1
2
3
4
5



6
7
8
9
10
11
12
13
14
15





-
-
-
+
+
+







# -*- tcl -*-
# This file is a Tcl script to test the Windows specific behavior of
# the common dialog boxes.  It is organized in the standard
# fashion for Tcl tests.
#
# Copyright (c) 1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright (c) 1998-1999 ActiveState Corporation.
# Copyright © 1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# Copyright © 1998-1999 ActiveState Corporation.

package require tcltest 2.2
namespace import ::tcltest::*
tcltest::configure {*}$argv
tcltest::loadTestedCommands

if {[testConstraint testwinevent]} {
114
115
116
117
118
119
120
121

122
123
124
125
126
127
128
114
115
116
117
118
119
120

121
122
123
124
125
126
127
128







-
+







test winDialog-1.1 {Tk_ChooseColorObjCmd} -constraints {
    testwinevent
} -body {
    start {tk_chooseColor}
    then {
        Click cancel
    }
} -result {0}
} -result 0
test winDialog-1.2 {Tk_ChooseColorObjCmd} -constraints {
    testwinevent
} -body {
    start {set clr [tk_chooseColor -initialcolor "#ff9933"]}
    then {
        set x [Click cancel]
    }
157
158
159
160
161
162
163
164

165
166
167
168
169
170
171
172
173
174

175
176
177
178
179
180
181
157
158
159
160
161
162
163

164
165
166
167
168
169
170
171
172
173

174
175
176
177
178
179
180
181







-
+









-
+







    testwinevent
} -setup {
    catch {unset a x}
} -body {
    set x {}
    start {
        set clr [tk_chooseColor -initialcolor "#ff9933" \
                     -title "\u041f\u0440\u0438\u0432\u0435\u0442"]
                     -title "Привет"]
    }
    then {
        if {[catch {
            array set a [testgetwindowinfo $::tk_dialog]
            if {[info exists a(text)]} {lappend x $a(text)}
        } err]} { lappend x $err }
        lappend x [Click ok]
    }
    lappend x $clr
} -result [list "\u041f\u0440\u0438\u0432\u0435\u0442" 0 "#ff9933"]
} -result [list "Привет" 0 "#ff9933"]
test winDialog-1.6 {Tk_ChooseColorObjCmd: -parent} -constraints {
    testwinevent
} -setup {
    catch {unset a x}
} -body {
    start {set clr [tk_chooseColor -initialcolor "#ff9933" -parent .]}
    set x {}
225
226
227
228
229
230
231
232

233
234
235
236
237
238
239
240
241
242
243
244
245

246
247
248
249
250
251
252
253
254
255
256
257
258

259
260
261
262

263
264
265
266
267
268
269
225
226
227
228
229
230
231

232
233
234
235
236
237
238
239
240
241
242
243
244

245
246
247
248
249
250
251
252
253
254
255
256
257

258
259
260
261

262
263
264
265
266
267
268
269







-
+












-
+












-
+



-
+







test winDialog-5.1 {GetFileName: no arguments} -constraints {
    nt testwinevent
} -body {
    start {tk_getOpenFile -title Open}
    then {
        Click cancel
    }
} -result {0}
} -result 0
test winDialog-5.2 {GetFileName: one argument} -constraints {
    nt
} -body {
    tk_getOpenFile -foo
} -returnCodes error -result {bad option "-foo": must be -defaultextension, -filetypes, -initialdir, -initialfile, -multiple, -parent, -title, or -typevariable}
test winDialog-5.3 {GetFileName: many arguments} -constraints {
    nt testwinevent
} -body {
    start {tk_getOpenFile -initialdir [initialdir] -parent . -title test -initialfile foo}
    then {
        Click cancel
    }
} -result {0}
} -result 0
test winDialog-5.4 {GetFileName: Tcl_GetIndexFromObj() != TCL_OK} -constraints {
    nt
} -body {
    tk_getOpenFile -foo bar -abc
} -returnCodes error -result {bad option "-foo": must be -defaultextension, -filetypes, -initialdir, -initialfile, -multiple, -parent, -title, or -typevariable}
test winDialog-5.5 {GetFileName: Tcl_GetIndexFromObj() == TCL_OK} -constraints {
    nt testwinevent
} -body {
    start {set x [tk_getOpenFile -title bar]}
    set y [then {
        Click cancel
    }]
    # Note this also tests fix for 
    # Note this also tests fix for
    # https://core.tcl-lang.org/tk/tktview/4a0451f5291b3c9168cc560747dae9264e1d2ef6
    # $x is expected to be empty
    append x $y
} -result {0}
} -result 0
test winDialog-5.6 {GetFileName: valid option, but missing value} -constraints {
    nt
} -body {
    tk_getOpenFile -initialdir bar -title
} -returnCodes error -result {value for "-title" missing}

test winDialog-5.7 {GetFileName: extension begins with .} -constraints {
437
438
439
440
441
442
443
444

445
446
447
448
449
450
451
437
438
439
440
441
442
443

444
445
446
447
448
449
450
451







-
+







} -cleanup {
    unset msg
} -result bar.foo
test winDialog-5.9 {GetFileName: file types} -constraints {
    nt testwinevent
} -body {
    #        case FILE_TYPES:
    

    start {tk_getSaveFile -filetypes {{"foo files" .foo FOOF}} -title Foo}
    # XXX - currently disabled for vista style dialogs because the file
    # types control has no control ID and we don't have a mechanism to
    # locate it.
    if {[vista?]} {
        then {
            Click cancel
500
501
502
503
504
505
506
507

508
509
510
511
512
513
514
500
501
502
503
504
505
506

507
508
509
510
511
512
513
514







-
+







    }
    return $x
} -result [file normalize [file join ~ "5 12 1"]]

test winDialog-5.12.2 {tk_getSaveFile: initial directory: ~user} -constraints {
    nt testwinevent
} -body {
    

    # Note: this test will fail on Tcl versions 8.6.4 and earlier due
    # to a bug in file normalize for names of the form ~xxx that
    # returns the wrong dir on Windows.  In particular (in Win8 at
    # least) it returned /users/Default instead of /users/USERNAME...

    unset -nocomplain x
    start {set x [tk_getSaveFile \
541
542
543
544
545
546
547
548

549
550
551
552
553
554
555
541
542
543
544
545
546
547

548
549
550
551
552
553
554
555







-
+







    }
    string equal $x [file join $newdir testfile]
} -result 1

test winDialog-5.12.4 {tk_getSaveFile: initial directory: unicode} -constraints {
    nt testwinevent
} -body {
    set dir [tcltest::makeDirectory "\u0167\u00e9\u015d\u0167"]
    set dir [tcltest::makeDirectory "ŧéŝŧ"]
    unset -nocomplain x
    start {set x [tk_getSaveFile \
                      -initialdir $dir \
                      -initialfile "testfile" -title Foo]}
    then {
        Click ok
    }
587
588
589
590
591
592
593
594












595
596
597
598
599
600
601
602
603
604
605




606
607
608
609
610
611
612
587
588
589
590
591
592
593

594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627







-
+
+
+
+
+
+
+
+
+
+
+
+











+
+
+
+







        }
    } finally {
        cd $cur
    }
    string equal $x [file join $dir testfile]
} -result 1

test winDialog-5.12.7 {tk_getOpenFile: initial directory: ~} -constraints {
test winDialog-5.12.7 {tk_getOpenFile: initial directory: ~} -setup {
    # Ensure there's at least one file in the home directory in CI environments
    set makeEmpty [expr {![llength [glob -nocomplain -type f -directory ~ *]]}]
    if {$makeEmpty} {
	for {set i 1} {$i < 1000} {incr i} {
	    # Technically a race condition...
	    set actualFilename [format "~/tkWinDialog5_12_7_%03d" $i]
	    if {![file exists $actualFilename]} break
	}
	close [open $actualFilename w]
    }
} -constraints {
    nt testwinevent
} -body {
    set fn [file tail [lindex [glob -types f ~/*] 0]]
    unset -nocomplain x
    start {set x [tk_getOpenFile \
                      -initialdir ~ \
                      -initialfile $fn -title Foo]}
    then {
        Click ok
    }
    string equal $x [file normalize [file join ~ $fn]]
} -cleanup {
    if {$makeEmpty} {
	file delete $actualFilename
    }
} -result 1

test winDialog-5.12.8 {tk_getOpenFile: initial directory: .} -constraints {
    nt testwinevent
} -body {
    # Windows remembers dirs from previous selections so use
    # a subdir for this test, not [initialdir] itself
627
628
629
630
631
632
633
634

635
636
637
638
639
640
641
642
643
644
645
646
647
648

649
650
651
652
653
654
655
656







-
+







    }
    string equal $x $path
} -result 1

test winDialog-5.12.9 {tk_getOpenFile: initial directory: unicode} -constraints {
    nt testwinevent
} -body {
    set dir [tcltest::makeDirectory "\u0167\u00e9\u015d\u0167"]
    set dir [tcltest::makeDirectory "ŧéŝŧ"]
    set path [tcltest::makeFile "" testfile $dir]
    unset -nocomplain x
    start {set x [tk_getOpenFile \
                      -initialdir $dir \
                      -initialfile "testfile" -title Foo]}
    then {
        Click ok
722
723
724
725
726
727
728
729

730
731
732
733
734

735
736
737
738
739

740
741
742
743
744
745
746
737
738
739
740
741
742
743

744
745
746
747
748

749
750
751
752
753

754
755
756
757
758
759
760
761







-
+




-
+




-
+







    toplevel .t
    set x 0
    start {tk_getOpenFile -parent .t -title Parent; set x 1}
    then {
        destroy .t
    }
    return $x
} -result {1}
} -result 1
test winDialog-5.17 {GetFileName: title} -constraints {
    nt testwinevent
} -body {
#        case FILE_TITLE:
   

    start {tk_getOpenFile -title Narf}
    then {
        Click cancel
    }
} -result {0}
} -result 0
if {[vista?]} {
    # In the newer file dialogs, the file type widget does not even exist
    # if no file types specified
    test winDialog-5.18 {GetFileName: no filter specified} -constraints {
        nt testwinevent
    } -body {
        #    if (ofn.lpstrFilter == NULL)
790
791
792
793
794
795
796
797

798
799
800
801
802
803
804
805
806
807
808
809
810
811

812
813
814
815
816
817
818
819







-
+







        destroy .t
    }
} -result {}
test winDialog-5.21 {GetFileName: call GetOpenFileName} -constraints {
    nt testwinevent english
} -body {
#        winCode = GetOpenFileName(&ofn);
   

    start {tk_getOpenFile -title Open}
    then {
        set x [GetText ok]
        Click cancel
    }
    return $x
} -result {&Open}
837
838
839
840
841
842
843
844

845
846
847
848
849
850

851
852
853
854
855

856
857
858
859
860
861
862
852
853
854
855
856
857
858

859
860
861
862
863
864

865
866
867
868
869

870
871
872
873
874
875
876
877







-
+





-
+




-
+







    # MacOS type that is correct, but has embedded nulls.

    start {set x [catch {tk_getSaveFile -filetypes {{"foo" .foo {\0\0\0\0}}}}]}
    then {
        Click cancel
    }
    return $x
} -result {0}
} -result 0
test winDialog-5.25 {GetFileName: file types: MakeFilter() succeeds} -constraints {
    nt
} -body {
    # MacOS type that is correct, but has embedded high-bit chars.

    start {set x [catch {tk_getSaveFile -filetypes {{"foo" .foo {\u2022\u2022\u2022\u2022}}}}]}
    start {set x [catch {tk_getSaveFile -filetypes {{"foo" .foo {••••}}}}]}
    then {
        Click cancel
    }
    return $x
} -result {0}
} -result 0


test winDialog-6.1 {MakeFilter} -constraints {emptyTest nt} -body {}


test winDialog-7.1 {Tk_MessageBoxObjCmd} -constraints {emptyTest nt} -body {}

873
874
875
876
877
878
879
880

881
882
883
884
885
886
887
888
889
890
891
892
893
894
895

896
897
898
899
900
901
902
903
904
905
906
907
908

909
910
911
912
913
914
915
888
889
890
891
892
893
894

895
896
897
898
899
900
901
902
903
904
905
906
907
908
909

910
911
912
913
914
915
916
917
918
919
920
921
922

923
924
925
926
927
928
929
930







-
+














-
+












-
+







} -body {
    start {set x [tk_chooseDirectory]}
    set y [then {
        Click cancel
    }]
    # $x should be "" on a Cancel
    append x $y
} -result {0}
} -result 0
test winDialog-9.2 {Tk_ChooseDirectoryObjCmd: one argument} -constraints {
    nt
} -body {
    tk_chooseDirectory -foo
} -returnCodes error -result {bad option "-foo": must be -initialdir, -mustexist, -parent, or -title}
test winDialog-9.3 {Tk_ChooseDirectoryObjCmd: many arguments} -constraints {
    nt testwinevent
} -body {
    start {
        tk_chooseDirectory -initialdir [initialdir] -mustexist 1 -parent . -title test
    }
    then {
        Click cancel
    }
} -result {0}
} -result 0
test winDialog-9.4 {Tk_ChooseDirectoryObjCmd: Tcl_GetIndexFromObj() != TCL_OK} -constraints {
    nt
} -body {
    tk_chooseDirectory -foo bar -abc
} -returnCodes error -result {bad option "-foo": must be -initialdir, -mustexist, -parent, or -title}
test winDialog-9.5 {Tk_ChooseDirectoryObjCmd: Tcl_GetIndexFromObj() == TCL_OK} -constraints {
    nt testwinevent
} -body {
    start {tk_chooseDirectory -title bar}
    then {
        Click cancel
    }
} -result {0}
} -result 0
test winDialog-9.6 {Tk_ChooseDirectoryObjCmd: valid option, but missing value} -constraints {
    nt
} -body {
    tk_chooseDirectory -initialdir bar -title
} -returnCodes error -result {value for "-title" missing}
test winDialog-9.7 {Tk_ChooseDirectoryObjCmd: -initialdir} -constraints {
    nt testwinevent
923
924
925
926
927
928
929
930

931
932
933
934
935
936
937
938
939
940
941
942
943
944

945
946
947
948
949
950
951
952







-
+







    string tolower [set x]
} -result [string tolower [initialdir]]
test winDialog-9.8 {Tk_ChooseDirectoryObjCmd: initial directory: Tcl_TranslateFilename()} -constraints {
    nt
} -body {
#        if (Tcl_TranslateFileName(interp, string,
#            &utfDirString) == NULL)
   

    tk_chooseDirectory -initialdir ~12x/455
} -returnCodes error -result {user "12x" doesn't exist}


test winDialog-10.1 {Tk_FontchooserObjCmd: no arguments} -constraints {
    nt testwinevent
} -body {
1029
1030
1031
1032
1033
1034
1035
1036

1037
1038
1039
1040
1041
1042
1043
1044

1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1044
1045
1046
1047
1048
1049
1050

1051
1052
1053
1054
1055
1056
1057
1058

1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072







-
+







-
+













test winDialog-10.9 {Tk_FontchooserObjCmd: -title} -constraints {
    nt testwinevent
} -setup {
    array set a {text failed}
} -body {
    start {
        tk fontchooser configure -command ApplyFont \
            -title  "\u041f\u0440\u0438\u0432\u0435\u0442"
            -title  "Привет"
        tk fontchooser show
    }
    then {
        array set a [testgetwindowinfo $::tk_dialog]
        Click cancel
    }
    set a(text)
} -result "\u041f\u0440\u0438\u0432\u0435\u0442"
} -result "Привет"

if {[testConstraint testwinevent]} {
    catch {testwinevent debug 0}
}

# cleanup
cleanupTests
return

# Local variables:
# mode: tcl
# End:

Changes to tests/winFont.test.
1
2
3
4
5
6
7

8
9
10


11
12
13
14
15
16
17
1
2
3
4
5
6

7
8


9
10
11
12
13
14
15
16
17






-
+

-
-
+
+







# This file is a Tcl script to test out the procedures in tkWinFont.c.
# It is organized in the standard fashion for Tcl tests.
#
# Many of these tests are visually oriented and cannot be checked
# programmatically (such as "does an underlined font appear to be
# underlined?"); these tests attempt to exercise the code in question,
# but there are no results that can be checked. 
# but there are no results that can be checked.
#
# Copyright (c) 1996-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1996-1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
namespace import ::tcltest::*
tcltest::configure {*}$argv
tcltest::loadTestedCommands

33
34
35
36
37
38
39
40

41
42
43
44
45

46
47
48
49
50
51
52
33
34
35
36
37
38
39

40
41
42
43
44

45
46
47
48
49
50
51
52







-
+




-
+







} -result {}


test winfont-2.1 {TkpGetFontFromAttributes procedure: pointsize} -constraints {
    win
} -body {
    expr {[font actual {-size -10} -size] > 0}
} -result {1}
} -result 1
test winfont-2.2 {TkpGetFontFromAttributes procedure: pointsize} -constraints {
    win
} -body {
    expr {[font actual {-family Arial} -size] > 0}
} -result {1}
} -result 1
test winfont-2.3 {TkpGetFontFromAttributes procedure: normal weight} -constraints {
    win
} -body {
    font actual {-weight normal} -weight
} -result {normal}
test winfont-2.4 {TkpGetFontFromAttributes procedure: bold weight} -constraints {
    win
67
68
69
70
71
72
73
74

75
76
77
78
79
80
81
82
83

84
85
86
87
88
89
90
91
92

93
94
95
96
97
98
99
67
68
69
70
71
72
73

74
75
76
77
78
79
80
81
82

83
84
85
86
87
88
89
90
91

92
93
94
95
96
97
98
99







-
+








-
+








-
+







    win
} -setup {
    set x {}
} -body {
    lappend x [font actual {-family "Times"} -family]
    lappend x [font actual {-family "New York"} -family]
    lappend x [font actual {-family "Times New Roman"} -family]
} -result {{Times New Roman} {Times New Roman} {Times New Roman}}
} -result {Times Times {Times New Roman}}
test winfont-2.8 {TkpGetFontFromAttributes procedure: Courier fonts} -constraints {
    win
} -setup {
    set x {}
} -body {
    lappend x [font actual {-family "Courier"} -family]
    lappend x [font actual {-family "Monaco"} -family]
    lappend x [font actual {-family "Courier New"} -family]
} -result {{Courier New} {Courier New} {Courier New}}
} -match regexp -result {Courier (Courier|Monaco) {Courier New}}
test winfont-2.9 {TkpGetFontFromAttributes procedure: Helvetica fonts} -constraints {
    win
} -setup {
    set x {}
} -body {
    lappend x [font actual {-family "Helvetica"} -family]
    lappend x [font actual {-family "Geneva"} -family]
    lappend x [font actual {-family "Arial"} -family]
} -result {Arial Arial Arial}
} -match regexp -result {Helvetica (Helvetica|Geneva) Arial}
test winfont-2.10 {TkpGetFontFromAttributes procedure: fallback} -constraints {
    win
} -body {
    # No way to get it to fail! Any font name is acceptable.
} -result {}


137
138
139
140
141
142
143
144

145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163

164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182

183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201

202
203
204
205
206
207
208
137
138
139
140
141
142
143

144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162

163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181

182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200

201
202
203
204
205
206
207
208







-
+


















-
+


















-
+


















-
+







} -body {
    label .t.l -padx 0 -pady 0 -bd 0 -highlightthickness 0 -justify left \
        -text "0" -font systemfixed
    pack .t.l
    update
    set ax [winfo reqwidth .t.l]
    set ay [winfo reqheight .t.l]
   

    .t.l config -wrap 0 -text "000000"
    list [expr {[winfo reqwidth .t.l] eq 6*$ax}] \
        [expr {[winfo reqheight .t.l] eq $ay}]
} -cleanup {
    destroy .t.l
} -result {1 1}

test winfont-5.2 {Tk_MeasureChars procedure: static width buffer exceeded} -constraints {
    win
} -setup {
    destroy .t.l
}  -body {
    label .t.l -padx 0 -pady 0 -bd 0 -highlightthickness 0 -justify left \
        -text "0" -font systemfixed
    pack .t.l
    update
    set ax [winfo reqwidth .t.l]
    set ay [winfo reqheight .t.l]
   

    .t.l config -wrap 100000 -text "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
    list [expr {[winfo reqwidth .t.l] eq 256*$ax}] \
        [expr {[winfo reqheight .t.l] eq $ay}]
} -cleanup {
    destroy .t.l
} -result {1 1}

test winfont-5.3 {Tk_MeasureChars procedure: all chars did fit} -constraints {
    win
} -setup {
    destroy .t.l
}  -body {
    label .t.l -padx 0 -pady 0 -bd 0 -highlightthickness 0 -justify left \
        -text "0" -font systemfixed
    pack .t.l
    update
    set ax [winfo reqwidth .t.l]
    set ay [winfo reqheight .t.l]
   

    .t.l config -wrap [expr {$ax*10}] -text "00000000"
    list [expr {[winfo reqwidth .t.l] eq 8*$ax}] \
        [expr {[winfo reqheight .t.l] eq $ay}]
} -cleanup {
    destroy .t.l
} -result {1 1}

test winfont-5.4 {Tk_MeasureChars procedure: not all chars fit} -constraints {
    win
} -setup {
    destroy .t.l
}  -body {
    label .t.l -padx 0 -pady 0 -bd 0 -highlightthickness 0 -justify left \
        -text "0" -font systemfixed
    pack .t.l
    update
    set ax [winfo reqwidth .t.l]
    set ay [winfo reqheight .t.l]
   

    .t.l config -wrap [expr {$ax*6}] -text "00000000"
    list [expr {[winfo reqwidth .t.l] eq 6*$ax}] \
        [expr {[winfo reqheight .t.l] eq 2*$ay}]
} -cleanup {
    destroy .t.l
} -result {1 1}

217
218
219
220
221
222
223
224

225
226
227
228
229
230
231
232
233
234
235
236
237

238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256

257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275

276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294

295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313

314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330

331
332
333
334
335
336
337
338
339
340

341
342
343
344
345
346
347
217
218
219
220
221
222
223

224
225
226
227
228
229
230
231
232
233
234
235
236

237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255

256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274

275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293

294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312

313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329

330
331
332
333
334
335
336
337
338
339

340
341
342
343
344
345
346
347







-
+












-
+


















-
+


















-
+


















-
+


















-
+
















-
+









-
+







    update

    .t.c dchars $t 0 end
    .t.c insert $t 0 "0000"
    .t.c index $t @[expr {int($cx*2.5)}],1
} -cleanup {
    destroy .t.c
} -result {2}
} -result 2

test winfont-5.6 {Tk_MeasureChars procedure: at least one char on line} -constraints {
    win
} -setup {
    destroy .t.l
}  -body {
    label .t.l -padx 0 -pady 0 -bd 0 -highlightthickness 0 -justify left \
        -text "0" -font systemfixed
    pack .t.l
    update
    set ax [winfo reqwidth .t.l]
    set ay [winfo reqheight .t.l]
   

    .t.l config -text "000000" -wrap 1
    list [expr {[winfo reqwidth .t.l] eq $ax}] \
        [expr {[winfo reqheight .t.l] eq 6*$ay}]
} -cleanup {
    destroy .t.l
} -result {1 1}

test winfont-5.7 {Tk_MeasureChars procedure: whole words} -constraints {
    win
} -setup {
    destroy .t.l
}  -body {
    label .t.l -padx 0 -pady 0 -bd 0 -highlightthickness 0 -justify left \
        -text "0" -font systemfixed
    pack .t.l
    update
    set ax [winfo reqwidth .t.l]
    set ay [winfo reqheight .t.l]
   

    .t.l config -wrap [expr {$ax*8}] -text "000000 0000"
    list [expr {[winfo reqwidth .t.l] eq 6*$ax}] \
        [expr {[winfo reqheight .t.l] eq 2*$ay}]
} -cleanup {
    destroy .t.l
} -result {1 1}

test winfont-5.8 {Tk_MeasureChars procedure: already saw space in line} -constraints {
    win
} -setup {
    destroy .t.l
}  -body {
    label .t.l -padx 0 -pady 0 -bd 0 -highlightthickness 0 -justify left \
        -text "0" -font systemfixed
    pack .t.l
    update
    set ax [winfo reqwidth .t.l]
    set ay [winfo reqheight .t.l]
   

    .t.l config -wrap [expr {$ax*12}] -text "000000    0000000"
    list [expr {[winfo reqwidth .t.l] eq 7*$ax}] \
        [expr {[winfo reqheight .t.l] eq 2*$ay}]
} -cleanup {
    destroy .t.l
} -result {1 1}

test winfont-5.9 {Tk_MeasureChars procedure: internal spaces significant} -constraints {
    win
} -setup {
    destroy .t.l
}  -body {
    label .t.l -padx 0 -pady 0 -bd 0 -highlightthickness 0 -justify left \
        -text "0" -font systemfixed
    pack .t.l
    update
    set ax [winfo reqwidth .t.l]
    set ay [winfo reqheight .t.l]
   

    .t.l config -wrap [expr {$ax*12}] -text "000  00   00000"
    list [expr {[winfo reqwidth .t.l] eq 7*$ax}] \
        [expr {[winfo reqheight .t.l] eq 2*$ay}]
} -cleanup {
    destroy .t.l
} -result {1 1}

test winfont-5.10 {Tk_MeasureChars procedure: make first part of word fit} -constraints {
    win
} -setup {
    destroy .t.l
}  -body {
    label .t.l -padx 0 -pady 0 -bd 0 -highlightthickness 0 -justify left \
        -text "0" -font systemfixed
    pack .t.l
    update
    set ax [winfo reqwidth .t.l]
    set ay [winfo reqheight .t.l]
   

    .t.l config -wrap [expr {$ax*12}] -text "0000000000000000"
    list [expr {[winfo reqwidth .t.l] eq 12*$ax}] \
        [expr {[winfo reqheight .t.l] eq 2*$ay}]
} -cleanup {
    destroy .t.l
} -result {1 1}

test winfont-5.11 {Tk_MeasureChars procedure: check for kerning} -constraints {
    win nonPortable
} -setup {
    destroy .t.l
}  -body {
    label .t.l -padx 0 -pady 0 -bd 0 -highlightthickness 0 -justify left \
        -text "0" -font systemfixed
    pack .t.l
    update
   

    set font [.t.l cget -font]
    .t.l config -font {{MS Sans Serif} 8} -text "W"
    set width [winfo reqwidth .t.l]
    .t.l config -text "XaYoYaKaWx"
    set x [lindex [getsize] 0]
    .t.l config -font $font
    expr {$x < ($width*10)}
} -cleanup {
    destroy .t.l
} -result {1}
} -result 1


test winfont-6.1 {Tk_DrawChars procedure: loop test} -constraints win -setup {
    destroy .t.l
}  -body {
    label .t.l -padx 0 -pady 0 -bd 0 -highlightthickness 0 -justify left \
        -text "0" -font systemfixed
371
372
373
374
375
376
377
378

379
380
381
382
383

384
385
386
387
388
389
390
391
392
371
372
373
374
375
376
377

378
379
380
381
382

383
384
385
386
387
388
389
390
391
392







-
+




-
+









} -body {
    font actual {arial 10 bold italic underline overstrike}
} -result {-family Arial -size 10 -weight bold -slant italic -underline 1 -overstrike 1}
test winfont-7.3 {AllocFont procedure: extract info from textmetric} -constraints {
    win
} -body {
    font metric {arial 10 bold italic underline overstrike} -fixed
} -result {0}
} -result 0
test winfont-7.4 {AllocFont procedure: extract info from textmetric} -constraints {
    win
} -body {
    font metric systemfixed -fixed
} -result {1}
} -result 1

# cleanup
cleanupTests
return

# Local variables:
# mode: tcl
# End:

Changes to tests/winMenu.test.
1
2
3
4
5
6
7


8
9
10
11
12
13
14
1
2
3
4
5


6
7
8
9
10
11
12
13
14





-
-
+
+







# This file is a Tcl script to test menus in Tk.  It is
# organized in the standard fashion for Tcl tests. This
# file tests the Macintosh-specific features of the menu
# system.
#
# Copyright (c) 1995-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1995-1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
namespace import ::tcltest::*
tcltest::configure {*}$argv
tcltest::loadTestedCommands

477
478
479
480
481
482
483
484

485
486
487
488
489
490
491
477
478
479
480
481
482
483

484
485
486
487
488
489
490
491







-
+







    .m1 add command -command {error 1} -label "winMenu-11.2: Please select this menu item."
    list [.m1 post 40 40] [update] [set foo] [unset foo] [destroy .m1]
} -result {{} {} {1 {1
    while executing
"error 1"
    (menu invoke)}} {} {}}

   

# Can't test WM_MENUCHAR

test winMenu-11.4 {TkWinHandleMenuEvent - WM_MEASUREITEM} -constraints {
    win userInteraction
} -setup {
    destroy .m1
} -body {
784
785
786
787
788
789
790
791

792
793
794
795
796
797
798
784
785
786
787
788
789
790

791
792
793
794
795
796
797
798







-
+







test winMenu-22.1 {DrawMenuUnderline} -constraints win -setup {
    destroy .m1
} -body {
    menu .m1
    .m1 add command -label foo -underline 0
    set tearoff [tk::TearOffMenu .m1 40 40]
    list [update] [destroy .m1]
} -result {{} {}}  
} -result {{} {}}


test winMenu-23.1 {Don't know how to test MenuKeyBindProc} -constraints {
    win emptyTest
} -body {}


1339
1340
1341
1342
1343
1344
1345
1346

1347
1348
1349
1350
1351
1352
1353
1339
1340
1341
1342
1343
1344
1345

1346
1347
1348
1349
1350
1351
1352
1353







-
+







    menu .m1 -tearoff 0
    .m1 add command -label one
    .m1 add command -label two -columnbreak 1
    .m1 add command -label three
    .m1 add command -label four
    .m1 add command -label five -columnbreak 1
    .m1 add command -label six
    list [update idletasks] [destroy .m1]   
    list [update idletasks] [destroy .m1]
} -result {{} {}}


test winMenu-33.1 {TkpNotifyTopLevelCreate - no menu yet} -constraints {
    win
} -setup {
    destroy .m1 .t2
Changes to tests/winMsgbox.test.
1
2
3

4
5
6
7
8
9
10
1
2

3
4
5
6
7
8
9
10


-
+







# This file is a Tcl script to test the Windows specific message box
#
# Copyright (c) 2007 Pat Thoyts <[email protected]>
# Copyright © 2007 Pat Thoyts <[email protected]>

package require tcltest 2.2
namespace import ::tcltest::*
tcltest::configure {*}$argv
tcltest::loadTestedCommands

testConstraint getwindowinfo [expr {[llength [info command ::testgetwindowinfo]] > 0}]
220
221
222
223
224
225
226
227

228
229
230
231
232
233
234

235
236
237
238
239
240
241
220
221
222
223
224
225
226

227
228
229
230
231
232
233

234
235
236
237
238
239
240
241







-
+






-
+







    win getwindowinfo
} -setup {
    wm iconify .
    unset -nocomplain info
} -body {
    global windowInfo
    set title "winMsgbox-2.2 [pid]"
    set message "\u041f\u043e\u0438\u0441\u043a\u0020\u0441\u0442\u0440\u0430\u043d\u0438\u0446"
    set message "Поиск страниц"
    after 100 [list GetWindowInfo $title 2]
    set r [tk_messageBox -type ok -title $title -message $message]
    array set info $windowInfo
    lappend r $info(childtext)
} -cleanup {
    wm deiconify .
} -result [list ok "\u041f\u043e\u0438\u0441\u043a\u0020\u0441\u0442\u0440\u0430\u043d\u0438\u0446"]
} -result [list ok "Поиск страниц"]

test winMsgbox-2.4 {tk_messageBox message (empty)} -constraints {
    win getwindowinfo
} -setup {
    wm iconify .
    unset -nocomplain info
} -body {
272
273
274
275
276
277
278
279
280


281
282
283
284
285
286
287

288
289
290
291
292
293
294
295
296
297
298
299
300
272
273
274
275
276
277
278


279
280
281
282
283
284
285
286

287
288
289
290
291
292
293
294
295
296
297
298
299
300







-
-
+
+






-
+













    win getwindowinfo
} -setup {
    wm iconify .
    unset -nocomplain info
} -body {
    global windowInfo
    set title "winMsgbox-3.1 [pid]"
    set message "\u041f\u043e\u0438\u0441\u043a"
    set detail "\u0441\u0442\u0440\u0430\u043d\u0438\u0446"
    set message "Поиск"
    set detail "страниц"
    after 100 [list GetWindowInfo $title 2]
    set r [tk_messageBox -type ok -title $title -message $message -detail $detail]
    array set info $windowInfo
    lappend r $info(childtext)
} -cleanup {
    wm deiconify .
} -result [list ok "\u041f\u043e\u0438\u0441\u043a\n\n\u0441\u0442\u0440\u0430\u043d\u0438\u0446"]
} -result [list ok "Поиск\n\nстраниц"]

# -------------------------------------------------------------------------

if {[testConstraint testwinevent]} {
    catch {testwinevent debug 0}
}
cleanupTests
return

# Local variables:
# mode: tcl
# indent-tabs-mode: nil
# End:
Changes to tests/winSend.test.
1
2
3
4
5
6
7



8
9
10

11
12
13
14
15
16
17
1
2
3
4



5
6
7
8
9

10
11
12
13
14
15
16
17




-
-
-
+
+
+


-
+







# This file is a Tcl script to test out the "send" command and the
# other procedures in the file tkSend.c.  It is organized in the
# standard fashion for Tcl tests.
#
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1994 Sun Microsystems, Inc.
# Copyright © 1994-1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.1
package require tcltest 2.2
eval tcltest::configure $argv
tcltest::loadTestedCommands

# Compute a script that will load Tk into a child interpreter.

foreach pkg [info loaded] {
    if {[lindex $pkg 1] == "Tk"} {
148
149
150
151
152
153
154
155

156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174

175
176
177
178
179
180
181
148
149
150
151
152
153
154

155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173

174
175
176
177
178
179
180
181







-
+


















-
+







    list [catch {send $interp {expr {2 / 0}}} msg] $msg $errorCode $errorInfo
} "1 {divide by zero} {ARITH DIVZERO {divide by zero}} {divide by zero\n    while executing\n\"expr {2 / 0}\"\n    invoked from within\n\"send \$interp {expr {2 / 0}}\"}"

test winSend-3.1 {TkGetInterpNames} winSend {
    set origLength [llength $currentInterps]
    set newLength [llength [winfo interps]]
    expr {($newLength - 2) == $origLength}
} {1}
} 1

test winSend-4.1 {DeleteProc - changing name of app} winSend {
    newApp a
    list [a eval tk appname foo] [interp delete a]
} {foo {}}
test winSend-4.2 {DeleteProc - normal} winSend {
    newApp a
    list [interp delete a]
} {{}}

test winSend-5.1 {ExecuteRemoteObject - no error} winSend {
    set newInterps [winfo interps]
    foreach interp $newInterps {
	if {[lsearch $currentInterps $interp] < 0} {
	    break
	}
    }
    list [send $interp {send [tk appname] {expr {2 / 1}}}]
} {2}
} 2
test winSend-5.2 {ExecuteRemoteObject - error} winSend {
    set newInterps [winfo interps]
    foreach interp $newInterps {
	if {[lsearch $currentInterps $interp] < 0} {
	    break
	}
    }
264
265
266
267
268
269
270
271

272
273
274
275
276
277
278
264
265
266
267
268
269
270

271
272
273
274
275
276
277
278







-
+







    foreach interp $newInterps {
	if {[lsearch $currentInterps $interp] < 0} {
	    break
	}
    }
    set command "dde services Tk {}"
    list [catch "send \{$interp\} \{$command\}"]
} {0}
} 0

test winSend-7.1 {DDEExitProc} winSend {
    newApp testApp
    list [interp delete testApp]
} {{}}

test winSend-8.1 {SendDdeConnect} winSend {
308
309
310
311
312
313
314
315

316
317
318

319
320
321
322
323
324
325
308
309
310
311
312
313
314

315
316
317

318
319
320
321
322
323
324
325







-
+


-
+







    list [catch {dde request} msg] $msg
} {1 {wrong # args: should be "dde request serviceName topicName value"}}
test winSend-10.7 {Tk_DDEObjCmd - services wrong num args} winSend {
    list [catch {dde services} msg] $msg
} {1 {wrong # args: should be "dde services serviceName topicName"}}
test winSend-10.8 {Tk_DDEObjCmd - null service name} winSend {
    list [catch {dde services {} {tktest #2}}]
} {0}
} 0
test winSend-10.9 {Tk_DDEObjCmd - null topic name} winSend {
    list [catch {dde services {Tk} {}}]
} {0}
} 0
test winSend-10.10 {Tk_DDEObjCmd - execute - nothing to execute} winSend {
    set newInterps [winfo interps]
    foreach interp $newInterps {
	if {[lsearch $currentInterps $interp] < 0} {
	    break
	}
    }
Changes to tests/winWm.test.
1
2
3
4
5
6
7
8
9


10
11
12
13
14
15
16

17
18
19
20
21
22
23
1
2
3
4
5
6
7


8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24







-
-
+
+







+







# This file tests  is a Tcl script to test the procedures in the file
# tkWinWm.c.  It is organized in the standard fashion for Tcl tests.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1996 by Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
namespace import ::tcltest::*
tcltest::configure {*}$argv
tcltest::loadTestedCommands

testConstraint failsOnUbuntu [expr {![info exists ::env(CI)] || ![string match Linux $::tcl_platform(os)]}]

test winWm-1.1 {TkWmMapWindow} -constraints win -setup {
    destroy .t
} -body {
    toplevel .t
    wm override .t 1
    wm geometry .t +0+0
241
242
243
244
245
246
247
248

249
250
251
252
253
254
255
242
243
244
245
246
247
248

249
250
251
252
253
254
255
256







-
+







    toplevel .t
    frame .t.f -width 150 -height 50 -background red
    pack .t.f
    wm geometry .t -0-0
    update
    set y [winfo rooty .t]
    lappend result [winfo height .t]
    menu .t.m
    menu .t.m -tearoff 1
    .t configure -menu .t.m
    .t.m add command -label foo
    .t.m add command -label "thisisreallylong"
    .t.m add command -label "thisisreallylong"
    update
    lappend result [winfo height .t]
    lappend result [expr {$y - [winfo rooty .t]}]
270
271
272
273
274
275
276
277

278
279
280
281
282
283
284
271
272
273
274
275
276
277

278
279
280
281
282
283
284
285







-
+







test winWm-6.2 {wm attributes} -constraints win -setup {
    destroy .t
} -body {
    toplevel .t
    wm attributes .t -disabled
} -cleanup {
    destroy .t
} -result {0}
} -result 0
test winWm-6.3 {wm attributes} -constraints win -setup {
    destroy .t
} -body {
    # This isn't quite the correct error message yet, but it works.
    toplevel .t
    wm attributes .t -foo
} -cleanup {
444
445
446
447
448
449
450
451

452
453
454
455
456
457
458
445
446
447
448
449
450
451

452
453
454
455
456
457
458
459







-
+







} -result {}

test winWm-9.0 "Bug #2799589 - delayed activation of destroyed window" -constraints win -setup {
    proc winwm90click {w} {
        if {![winfo ismapped $w]} { update }
        event generate $w <Enter>
        focus -force $w
        event generate $w <ButtonPress-1> -x 5 -y 5
        event generate $w <Button-1> -x 5 -y 5
        event generate $w <ButtonRelease-1> -x 5 -y 5
    }
    proc winwm90proc3 {} {
        global winwm90done winwm90check
        set w .sd
        toplevel $w
        pack [button $w.b -text "OK" -command {set winwm90check 1}]
470
471
472
473
474
475
476
477

478
479
480
481
482
483
484
485
486
487
488

489
490
491
492
493
494
495

496
497
498
499
500
501
502
471
472
473
474
475
476
477

478
479
480
481
482
483
484
485
486
487
488

489
490
491
492
493
494
495

496
497
498
499
500
501
502
503







-
+










-
+






-
+







        toplevel $w
        pack [button $w.b -text "Do dialog" -command [list winwm90proc2 $w]]
        bind $w.b <Map> {bind %W <Map> {}; after idle {winwm90click %W}}
    }
    global winwm90done
    set winwm90done wait
    toplevel .t
} -body {    
} -body {
    pack [button .t.b -text "Show" -command {winwm90proc1 .tx}]
    bind .t.b <Map> {bind %W <Map> {}; after idle {winwm90click %W}}
    after 5000 {set winwm90done timeout}
    vwait winwm90done
    set winwm90done
} -cleanup {
    foreach cmd {proc1 proc2 proc3 click} {
        rename winwm90$cmd {}
    }
    destroy .tx .t .sd
} -result {ok} 
} -result ok

test winWm-9.1 "delayed activation of grabbed destroyed window" -constraints win -setup {
    proc winwm91click {w} {
        if {![winfo ismapped $w]} { update }
        event generate $w <Enter>
        focus -force $w
        event generate $w <ButtonPress-1> -x 5 -y 5
        event generate $w <Button-1> -x 5 -y 5
        event generate $w <ButtonRelease-1> -x 5 -y 5
    }
    proc winwm91proc3 {} {
        global winwm91done winwm91check
        set w .sd
        toplevel $w
        pack [button $w.b -text "OK" -command {set winwm91check 1}]
515
516
517
518
519
520
521
522

523
524
525
526
527
528
529
530
531
532
533

534
535

536
537
538
539
540
541
542
543
544

545
546
547

548
549
550

551
552

553
554
555
556
557
558
559
516
517
518
519
520
521
522

523
524
525
526
527
528
529
530
531
532
533

534
535

536
537
538
539
540
541
542
543
544

545
546
547

548
549
550

551
552

553
554
555
556
557
558
559
560







-
+










-
+

-
+








-
+


-
+


-
+

-
+







        pack [button $w.b -text "Do dialog" -command [list winwm91proc2 $w]]
        bind $w.b <Map> {bind %W <Map> {}; after idle {winwm91click %W}}
    }
    destroy .t
    global winwm91done
    set winwm91done wait
    toplevel .t
} -body {    
} -body {
    pack [button .t.b -text "Show" -command {winwm91proc1 .tx}]
    bind .t.b <Map> {bind %W <Map> {}; after idle {winwm91click %W}}
    after 5000 {set winwm91done timeout}
    vwait winwm91done
    set winwm91done
} -cleanup {
    foreach cmd {proc1 proc2 proc3 click} {
        rename winwm91$cmd {}
    }
    destroy .tx .t .sd
} -result {ok}
} -result ok

test winWm-9.2 "check wm forget for unmapped parent (#3205464,#2967911)" -setup {
test winWm-9.2 "check wm forget for unmapped parent (#3205464,#2967911)" -constraints failsOnUbuntu -setup {
    destroy .t
    toplevel .t
    set winwm92 {}
    frame .t.f -background blue -height 200 -width 200
    frame .t.f.x -background red -height 100 -width 100
} -body {
    pack .t.f.x
    pack .t.f
    lappend aid [after 2000 {set ::winwm92 timeout}] [after 100 {
    lappend aid [after 5000 {set ::winwm92 timeout}] [after 500 {
        wm manage .t.f
        wm iconify .t
        lappend aid [after 100 {
        lappend aid [after 500 {
            wm forget .t.f
            wm deiconify .t
            lappend aid [after 100 {
            lappend aid [after 500 {
                pack .t.f
                lappend aid [after 100 {
                lappend aid [after 500 {
		    set ::winwm92 [expr {
			    [winfo rooty .t.f.x] == 0 ? "failed" : "ok"}]}]
            }]
        }]
    }]
    vwait ::winwm92
    foreach id $aid {
Changes to tests/window.test.
1
2
3
4
5


6
7
8
9
10
11
12
1
2
3


4
5
6
7
8
9
10
11
12



-
-
+
+







# This file is a Tcl script to test the procedures in the file
# tkWindow.c.  It is organized in the standard fashion for Tcl tests.
#
# Copyright (c) 1995 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1995 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
namespace import ::tcltest::*
tcltest::configure {*}$argv
tcltest::loadTestedCommands
namespace import ::tk::test::loadTkCommand
Changes to tests/winfo.test.
1
2
3
4
5
6



7
8
9
10
11
12



13
14
15
16
17
18
19
1
2
3



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22



-
-
-
+
+
+






+
+
+







# This file is a Tcl script to test out the "winfo" command.  It is
# organized in the standard fashion for Tcl tests.
#
# Copyright (c) 1994 The Regents of the University of California.
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1994 The Regents of the University of California.
# Copyright © 1994-1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
namespace import ::tcltest::*
tcltest::configure {*}$argv
tcltest::loadTestedCommands

testConstraint failsOnUbuntu [expr {![info exists ::env(CI)] || ![string match Linux $::tcl_platform(os)]}]
testConstraint failsOnXQuarz [expr {$tcl_platform(os) ne "Darwin" || [tk windowingsystem] ne "x11" }]

# eatColors --
# Creates a toplevel window and allocates enough colors in it to
# use up all the slots in the colormap.
#
# Arguments:
# w -        Name of toplevel window to create.
170
171
172
173
174
175
176
177

178
179
180
181
182
183
184
185
186
187
188
189
190
191

192
193
194

195
196
197
198
199
200
201
202
203
204
205

206
207
208

209
210
211
212
213
214
215
173
174
175
176
177
178
179

180
181
182
183
184
185
186
187
188
189
190
191
192
193

194
195
196

197
198
199
200
201
202
203
204
205
206
207

208
209
210

211
212
213
214
215
216
217
218







-
+













-
+


-
+










-
+


-
+







    update

    set x [winfo containing -display .t.f [expr {[winfo rootx .t]+600}] \
        [expr {[winfo rooty .t.f]+450}]]
    expr {($x == ".") || ($x == "")}
} -cleanup {
    destroy .t
} -result {1}
} -result 1


test winfo-5.1 {"winfo interps" command} -body {
    winfo interps a
} -returnCodes error -result {wrong # args: should be "winfo interps ?-displayof window?"}
test winfo-5.2 {"winfo interps" command} -body {
    winfo interps a b c
} -returnCodes error -result {wrong # args: should be "winfo interps ?-displayof window?"}
test winfo-5.3 {"winfo interps" command} -body {
    winfo interps -displayof geek
} -returnCodes error -result {bad window path name "geek"}
test winfo-5.4 {"winfo interps" command} -constraints unix -body {
    expr {[lsearch -exact [winfo interps] [tk appname]] >= 0}
} -result {1}
} -result 1
test winfo-5.5 {"winfo interps" command} -constraints unix -body {
    expr {[lsearch -exact [winfo interps -displayof .] [tk appname]] >= 0}
} -result {1}
} -result 1


test winfo-6.1 {"winfo exists" command} -body {
    winfo exists
} -returnCodes error -result {wrong # args: should be "winfo exists window"}
test winfo-6.2 {"winfo exists" command} -body {
    winfo exists a b
} -returnCodes error -result {wrong # args: should be "winfo exists window"}
test winfo-6.3 {"winfo exists" command} -body {
    winfo exists gorp
} -result {0}
} -result 0
test winfo-6.4 {"winfo exists" command} -body {
    winfo exists .
} -result {1}
} -result 1
test winfo-6.5 {"winfo exists" command} -setup {
    destroy .b
} -body {
    button .b -text "Test button"
    set x [winfo exists .b]
    pack .b
    update
286
287
288
289
290
291
292
293
294


295
296
297
298
299

300
301
302
303
304
305
306
289
290
291
292
293
294
295


296
297
298
299
300
301

302
303
304
305
306
307
308
309







-
-
+
+




-
+







    winfo viewable
} -returnCodes error -result {wrong # args: should be "winfo viewable window"}
test winfo-9.2 {"winfo viewable" command} -body {
    winfo viewable foo
} -returnCodes error -result {bad window path name "foo"}
test winfo-9.3 {"winfo viewable" command} -body {
    winfo viewable .
} -result {1}
test winfo-9.4 {"winfo viewable" command} -body {
} -result 1
test winfo-9.4 {"winfo viewable" command} -constraints failsOnUbuntu -body {
    wm iconify .
    winfo viewable .
} -cleanup {
    wm deiconify .
} -result {0}
} -result 0
test winfo-9.5 {"winfo viewable" command} -setup {
    deleteWindows
} -body {
    frame .f1 -width 100 -height 100 -relief raised -bd 2
    place .f1 -x 0 -y 0
    frame .f1.f2 -width 50 -height 50 -relief raised -bd 2
    place .f1.f2 -x 0 -y 0
316
317
318
319
320
321
322
323

324
325
326
327
328
329
330
319
320
321
322
323
324
325

326
327
328
329
330
331
332
333







-
+







    frame .f1.f2 -width 50 -height 50 -relief raised -bd 2
    place .f1.f2 -x 0 -y 0
    update
    list [winfo viewable .f1] [winfo viewable .f1.f2]
} -cleanup {
    deleteWindows
} -result {0 0}
test winfo-9.7 {"winfo viewable" command} -setup {
test winfo-9.7 {"winfo viewable" command} -constraints {failsOnUbuntu failsOnXQuarz} -setup {
    deleteWindows
} -body {
    frame .f1 -width 100 -height 100 -relief raised -bd 2
    place .f1 -x 0 -y 0
    frame .f1.f2 -width 50 -height 50 -relief raised -bd 2
    place .f1.f2 -x 0 -y 0
    update
340
341
342
343
344
345
346
347

348
349
350
351
352
353
354
355
356
357
358
359
360
361

362
363
364

365
366
367
368

369
370
371
372
373
374
375
343
344
345
346
347
348
349

350
351
352
353
354
355
356
357
358
359
360
361
362
363

364
365
366

367
368
369
370

371
372
373
374
375
376
377
378







-
+













-
+


-
+



-
+







    winfo visualid
} -returnCodes error -result {wrong # args: should be "winfo visualid window"}
test winfo-10.2 {"winfo visualid" command} -body {
    winfo visualid gorp
} -returnCodes error -result {bad window path name "gorp"}
test winfo-10.3 {"winfo visualid" command} -body {
    expr {2 + [winfo visualid .] - [winfo visualid .]}
} -result {2}
} -result 2


test winfo-11.1 {"winfo visualid" command} -body {
    winfo visualsavailable
} -returnCodes error -result {wrong # args: should be "winfo visualsavailable window ?includeids?"}
test winfo-11.2 {"winfo visualid" command} -body {
    winfo visualsavailable gorp
} -returnCodes error -result {bad window path name "gorp"}
test winfo-11.3 {"winfo visualid" command} -body {
    winfo visualsavailable . includeids foo
} -returnCodes error -result {wrong # args: should be "winfo visualsavailable window ?includeids?"}
test winfo-11.4 {"winfo visualid" command} -body {
    llength [lindex [winfo visualsa .] 0]
} -result {2}
} -result 2
test winfo-11.5 {"winfo visualid" command} -body {
    llength [lindex [winfo visualsa . includeids] 0]
} -result {3}
} -result 3
test winfo-11.6 {"winfo visualid" command} -body {
    set x [lindex [lindex [winfo visualsa . includeids] 0] 2]
    expr {$x + 2 - $x}
} -result {2}
} -result 2


test winfo-12.1 {GetDisplayOf procedure} -body {
    winfo atom - foo x
} -returnCodes error -result {wrong # args: should be "winfo atom ?-displayof window? name"}
test winfo-12.2 {GetDisplayOf procedure} -body {
    winfo atom -d bad_window x
Changes to tests/wm.test.
1
2
3
4
5
6
7



8
9
10
11
12
13
14

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29



30
31
32
33
34
35
36



37
38
39
40
41
42
43
1
2
3
4



5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

39
40
41
42
43
44
45
46
47
48




-
-
-
+
+
+






-
+















+
+
+






-
+
+
+







# This file is a Tcl script to test out Tk's interactions with the window
# manager, including the "wm" command. It is organized in the standard fashion
# for Tcl tests.
#
# Copyright (c) 1992-1994 The Regents of the University of California.
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1992-1994 The Regents of the University of California.
# Copyright © 1994-1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

# This file tests window manager interactions that work across platforms.
# Window manager tests that only work on a specific platform should be placed
# in unixWm.test or winWm.test.

package require tcltest 2.1
package require tcltest 2.2
eval tcltest::configure $argv
tcltest::loadTestedCommands

wm deiconify .
if {![winfo ismapped .]} {
    tkwait visibility .
}

proc stdWindow {} {
    destroy .t
    toplevel .t -width 100 -height 50
    wm geom .t +0+0
    update
}

testConstraint failsOnUbuntu [expr {![info exists ::env(CI)] || ![string match Linux $::tcl_platform(os)]}]
testConstraint failsOnXQuarz [expr {$tcl_platform(os) ne "Darwin" || [tk windowingsystem] ne "x11" }]

# [raise] and [lower] may return before the window manager has completed the
# operation. The raiseDelay procedure idles for a while to give the operation
# a chance to complete.
#

proc raiseDelay {} {
    after 100; update
    after 100;
    update
    update idletasks
}

# How to carry out a small delay while processing events

proc eventDelay {{delay 200}} {
    after $delay "set done 1" ; vwait done
}
779
780
781
782
783
784
785
786

787
788
789
790
791
792
793
794
795
796

797
798
799
800
801
802
803
804
805
806

807
808

809
810
811

812
813
814

815
816
817
818
819
820
821
784
785
786
787
788
789
790

791
792
793
794
795
796
797
798
799
800

801
802
803
804
805
806
807
808
809
810

811
812

813
814
815

816
817
818

819
820
821
822
823
824
825
826







-
+









-
+









-
+

-
+


-
+


-
+







test wm-iconify-2.3 {Misc errors} -body {
    toplevel .t2
    wm geom .t2 +0+0
    wm iconwindow .t .t2
    wm iconify .t2
} -returnCodes error -cleanup {
    destroy .t2
} -result {can't iconify .t2: it is an icon for .t}
} -result {can't iconify ".t2": it is an icon for ".t"}
# test embedded window for Windows
test wm-iconify-2.4.1 {Misc errors} -constraints win -setup {
    destroy .t2
} -body {
    frame .t.f -container 1
    toplevel .t2 -use [winfo id .t.f]
    wm iconify .t2
} -returnCodes error -cleanup {
    destroy .t2 .r.f
} -result {can't iconify .t2: the container does not support the request}
} -result {can't iconify ".t2": the container does not support the request}
# test embedded window for other platforms
test wm-iconify-2.4.2 {Misc errors} -constraints !win -setup {
    destroy .t2
} -body {
    frame .t.f -container 1
    toplevel .t2 -use [winfo id .t.f]
    wm iconify .t2
} -returnCodes error -cleanup {
    destroy .t2 .r.f
} -result {can't iconify .t2: it is an embedded window}
} -result {can't iconify ".t2": it is an embedded window}

test wm-iconify-3.1 {iconify behavior} -body {
test wm-iconify-3.1 {iconify behavior} -constraints failsOnUbuntu -body {
    toplevel .t2
    wm geom .t2 -0+0
    update
    update idletasks
    set result [winfo ismapped .t2]
    wm iconify .t2
    update
    update idletasks
    lappend result [winfo ismapped .t2]
} -cleanup {
    destroy .t2
} -result {1 0}


### wm iconmask ###
1409
1410
1411
1412
1413
1414
1415
1416

1417
1418
1419
1420
1421
1422
1423
1414
1415
1416
1417
1418
1419
1420

1421
1422
1423
1424
1425
1426
1427
1428







-
+







    deleteWindows
} -body {
    wm stackorder .
} -result {.}

deleteWindows

test wm-stackorder-3.1 {unmapped toplevel} -body {
test wm-stackorder-3.1 {unmapped toplevel} -constraints failsOnUbuntu -body {
    toplevel .t1 ; update
    toplevel .t2 ; update
    wm iconify .t1
    wm stackorder .
} -cleanup {
    destroy .t1 .t2
} -result {. .t2}
1480
1481
1482
1483
1484
1485
1486
1487

1488
1489
1490
1491
1492
1493
1494

1495
1496
1497
1498
1499
1500
1501
1502

1503
1504
1505
1506
1507
1508
1509
1510

1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526

1527
1528

1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540

1541
1542
1543
1544
1545
1546
1547
1548
1549
1550

1551
1552

1553
1554
1555
1556
1557
1558
1559
1485
1486
1487
1488
1489
1490
1491

1492
1493
1494
1495
1496
1497
1498

1499
1500
1501
1502
1503
1504
1505
1506

1507
1508
1509
1510
1511
1512
1513
1514

1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530

1531
1532

1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544

1545
1546
1547
1548
1549
1550
1551
1552
1553
1554

1555
1556

1557
1558
1559
1560
1561
1562
1563
1564







-
+






-
+







-
+







-
+















-
+

-
+











-
+









-
+

-
+








test wm-stackorder-4.1 {wm stackorder isabove|isbelow} -body {
    toplevel .t ; update
    raise .t
    wm stackorder . isabove .t
} -cleanup {
    destroy .t
} -result {0}
} -result 0
test wm-stackorder-4.2 {wm stackorder isabove|isbelow} -body {
    toplevel .t ; update
    raise .t
    wm stackorder . isbelow .t
} -cleanup {
    destroy .t
} -result {1}
} -result 1
test wm-stackorder-4.3 {wm stackorder isabove|isbelow} -body {
    toplevel .t ; update
    raise .
    raiseDelay
    wm stackorder .t isa .
} -cleanup {
    destroy .t
} -result {0}
} -result 0
test wm-stackorder-4.4 {wm stackorder isabove|isbelow} -body {
    toplevel .t ; update
    raise .
    raiseDelay
    wm stackorder .t isb .
} -cleanup {
    destroy .t
} -result {1}
} -result 1
deleteWindows

test wm-stackorder-5.1 {a menu is not a toplevel} -body {
    toplevel .t
    menu .t.m -type menubar
    .t.m add cascade -label "File"
    .t configure -menu .t.m
    update
    raise .
    raiseDelay
    wm stackorder .
} -cleanup {
    destroy .t
} -result {.t .}
test wm-stackorder-5.2 {A normal toplevel can't be raised above an \
    overrideredirect toplevel on unix} -constraints x11 -body {
    overrideredirect toplevel on unix} -constraints {x11 failsOnUbuntu failsOnXQuarz} -body {
    toplevel .t
    tkwait visibility .t	    
    tkwait visibility .t
    wm overrideredirect .t 1
    raise .
    update
    raiseDelay
    wm stackorder . isabove .t
} -cleanup {
    destroy .t
} -result 0
test wm-stackorder-5.2.1 {A normal toplevel can be raised above an \
    overrideredirect toplevel on macOS or win} -constraints aquaOrWin32 -body {
    toplevel .t
    tkwait visibility .t	    
    tkwait visibility .t
    wm overrideredirect .t 1
    raise .
    update
    raiseDelay
    wm stackorder . isabove .t
} -cleanup {
    destroy .t
} -result 1
test wm-stackorder-5.3 {An overrideredirect window\
        can be explicitly lowered} -body {
        can be explicitly lowered} -constraints failsOnXQuarz -body {
    toplevel .t
    tkwait visibility .t	    
    tkwait visibility .t
    wm overrideredirect .t 1
    lower .t
    update
    raiseDelay
    wm stackorder .t isbelow .
} -cleanup {
    destroy .t
1591
1592
1593
1594
1595
1596
1597
1598

1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609

1610
1611

1612
1613
1614
1615
1616
1617
1618
1596
1597
1598
1599
1600
1601
1602

1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613

1614
1615

1616
1617
1618
1619
1620
1621
1622
1623







-
+










-
+

-
+







} -result {t Apa {}}


### wm transient ###
test wm-transient-1.1 {usage} -returnCodes error -body {
    catch {destroy .t} ; toplevel .t
    wm transient .t 1 2
} -result {wrong # args: should be "wm transient window ?master?"}
} -result {wrong # args: should be "wm transient window ?window?"}
test wm-transient-1.2 {usage} -returnCodes error -body {
    catch {destroy .t} ; toplevel .t
    wm transient .t foo
} -result {bad window path name "foo"}
test wm-transient-1.3 {usage} -returnCodes error -body {
    catch {destroy .t} ; toplevel .t
    wm transient foo .t
} -result {bad window path name "foo"}
deleteWindows
test wm-transient-1.4 {usage} -returnCodes error -body {
    toplevel .master
    toplevel .top
    toplevel .subject
    wm transient .subject .master
    wm transient .subject .top
    wm iconify .subject
} -cleanup {
    deleteWindows
} -result {can't iconify ".subject": it is a transient}
test wm-transient-1.5 {usage} -returnCodes error -body {
    toplevel .icon -bg blue
    toplevel .top
1626
1627
1628
1629
1630
1631
1632
1633

1634
1635
1636


1637
1638
1639

1640
1641
1642
1643
1644
1645
1646
1647
1648
1649

1650
1651
1652
1653



1654
1655
1656

1657
1658

1659
1660
1661

1662
1663
1664

1665
1666
1667
1668
1669
1670
1671
1672
1673




1674
1675

1676
1677
1678
1679

1680
1681
1682
1683
1684



1685
1686
1687

1688
1689
1690
1691
1692
1693
1694
1695
1696



1697
1698
1699
1700

1701
1702
1703
1704
1705
1706

1707
1708
1709
1710

1711
1712
1713
1714


1715
1716
1717

1718
1719
1720
1721
1722
1723
1724
1725
1726
1727



1728
1729
1730

1731
1732
1733
1734
1735
1736
1737
1738


1739
1740
1741


1742
1743
1744
1745



1746
1747
1748
1749
1750
1751


1752
1753
1754

1755
1756
1757
1758
1759




1760
1761
1762


1763
1764
1765
1766
1767
1768
1769
1770
1771
1772

1773
1774
1775

1776
1777
1778

1779
1780
1781

1782
1783
1784
1785
1786
1787

1788
1789

1790
1791

1792
1793

1794
1795
1796
1797
1798
1799
1800
1801


1802
1803
1804


1805
1806
1807
1808
1809
1810
1811
1812


1813
1814
1815

1816
1817
1818


1819
1820
1821
1822
1823
1824
1825
1826

1827
1828
1829

1830
1831
1832

1833
1834
1835


1836
1837
1838
1839
1840
1841

1842
1843

1844
1845
1846
1847
1848
1849
1850
1851
1852


1853
1854
1855
1856
1857
1858
1859



1860
1861
1862
1863
1864
1865
1866
1867

1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882


1883
1884
1885


1886
1887
1888
1889
1890

1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902

1903
1904
1905
1906
1907
1908
1909
1631
1632
1633
1634
1635
1636
1637

1638
1639


1640
1641
1642
1643

1644
1645
1646
1647
1648
1649
1650
1651
1652
1653

1654
1655



1656
1657
1658
1659
1660

1661
1662

1663
1664
1665

1666
1667
1668

1669
1670
1671
1672
1673
1674




1675
1676
1677
1678
1679

1680
1681
1682
1683

1684
1685
1686



1687
1688
1689
1690
1691

1692
1693
1694
1695
1696
1697
1698



1699
1700
1701
1702
1703
1704

1705
1706
1707
1708
1709
1710

1711
1712
1713
1714

1715
1716
1717


1718
1719
1720
1721

1722
1723
1724
1725
1726
1727
1728
1729



1730
1731
1732
1733
1734

1735
1736
1737
1738
1739
1740
1741


1742
1743
1744


1745
1746
1747



1748
1749
1750
1751
1752
1753
1754


1755
1756
1757
1758

1759
1760




1761
1762
1763
1764
1765


1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776

1777
1778
1779

1780
1781
1782

1783
1784
1785

1786
1787
1788
1789
1790
1791

1792
1793

1794
1795

1796
1797

1798
1799
1800
1801
1802
1803
1804


1805
1806
1807


1808
1809
1810
1811
1812
1813
1814
1815


1816
1817
1818
1819

1820
1821


1822
1823
1824
1825
1826
1827
1828
1829
1830

1831
1832
1833

1834
1835
1836

1837
1838


1839
1840
1841
1842
1843
1844
1845

1846
1847

1848
1849
1850
1851
1852
1853
1854
1855


1856
1857
1858
1859
1860
1861



1862
1863
1864
1865
1866
1867
1868
1869
1870
1871

1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885


1886
1887
1888


1889
1890
1891
1892
1893
1894

1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906

1907
1908
1909
1910
1911
1912
1913
1914







-
+

-
-
+
+


-
+









-
+

-
-
-
+
+
+


-
+

-
+


-
+


-
+





-
-
-
-
+
+
+
+

-
+



-
+


-
-
-
+
+
+


-
+






-
-
-
+
+
+



-
+





-
+



-
+


-
-
+
+


-
+







-
-
-
+
+
+


-
+






-
-
+
+

-
-
+
+

-
-
-
+
+
+




-
-
+
+


-
+

-
-
-
-
+
+
+
+

-
-
+
+









-
+


-
+


-
+


-
+





-
+

-
+

-
+

-
+






-
-
+
+

-
-
+
+






-
-
+
+


-
+

-
-
+
+







-
+


-
+


-
+

-
-
+
+





-
+

-
+







-
-
+
+




-
-
-
+
+
+







-
+













-
-
+
+

-
-
+
+




-
+











-
+







    toplevel .icon -bg blue
    toplevel .top
    wm iconwindow .top .icon
    toplevel .dummy
    wm transient .dummy .icon
} -cleanup {
    deleteWindows
} -result {can't make ".icon" a master: it is an icon for .top}
} -result {can't make ".icon" a container: it is an icon for .top}
test wm-transient-1.7 {usage} -returnCodes error -body {
    toplevel .master
    wm transient .master .master
    toplevel .top
    wm transient .top .top
} -cleanup {
    deleteWindows
} -result {setting ".master" as master creates a transient/master cycle}
} -result {can't set ".top" as container: would cause management loop}
test wm-transient-1.8 {usage} -returnCodes error -body {
    toplevel .t1
    toplevel .t2
    toplevel .t3
    wm transient .t2 .t1
    wm transient .t3 .t2
    wm transient .t1 .t3
} -cleanup {
    deleteWindows
} -result {setting ".t3" as master creates a transient/master cycle}
} -result {can't set ".t3" as container: would cause management loop}
test wm-transient-1.9 {usage} -returnCodes error -body {
    toplevel .master
    frame .master.f
    wm transient .master .master.f
    toplevel .top
    frame .top.f
    wm transient .top .top.f
} -cleanup {
    deleteWindows
} -result {setting ".master" as master creates a transient/master cycle}
} -result {can't set ".top" as container: would cause management loop}

test wm-transient-2.1 {basic get/set of master} -setup {
test wm-transient-2.1 {basic get/set of toplevel} -setup {
    set results [list]
} -body {
    toplevel .master
    toplevel .top
    toplevel .subject
    lappend results [wm transient .subject]
    wm transient .subject .master
    wm transient .subject .top
    lappend results [wm transient .subject]
    wm transient .subject {}
    lappend results [wm transient .subject]
} -cleanup {
    deleteWindows
} -result {{} .master {}}
test wm-transient-2.2 {first toplevel parent of non-toplevel master is used} -body {
    toplevel .master
    frame .master.f
} -result {{} .top {}}
test wm-transient-2.2 {first toplevel parent of non-toplevel container window is used} -body {
    toplevel .top
    frame .top.f
    toplevel .subject
    wm transient .subject .master.f
    wm transient .subject .top.f
    wm transient .subject
} -cleanup {
    deleteWindows
} -result {.master}
} -result {.top}

test wm-transient-3.1 {transient toplevel is withdrawn
        when mapped if master is withdrawn} -body {
    toplevel .master
    wm withdraw .master
        when mapped if toplevel is withdrawn} -body {
    toplevel .top
    wm withdraw .top
    update
    toplevel .subject
    wm transient .subject .master
    wm transient .subject .top
    update
    list [wm state .subject] [winfo ismapped .subject]
} -cleanup {
    deleteWindows
} -result {withdrawn 0}
test wm-transient-3.2 {already mapped transient toplevel
        takes on withdrawn state of master} -body {
    toplevel .master
    wm withdraw .master
        takes on withdrawn state of toplevel} -body {
    toplevel .top
    wm withdraw .top
    update
    toplevel .subject
    update
    wm transient .subject .master
    wm transient .subject .top
    update
    list [wm state .subject] [winfo ismapped .subject]
} -cleanup {
    deleteWindows
} -result {withdrawn 0}
test wm-transient-3.3 {withdraw/deiconify on the master
test wm-transient-3.3 {withdraw/deiconify on the toplevel
        also does a withdraw/deiconify on the transient} -setup {
    set results [list]
} -body {
    toplevel .master
    toplevel .top
    toplevel .subject
    update
    wm transient .subject .master
    wm withdraw .master
    wm transient .subject .top
    wm withdraw .top
    update
    lappend results [wm state .subject] [winfo ismapped .subject]
    wm deiconify .master
    wm deiconify .top
    update
    lappend results [wm state .subject] [winfo ismapped .subject]
} -cleanup {
    deleteWindows
} -result {withdrawn 0 normal 1}

test wm-transient-4.1 {transient toplevel is withdrawn
        when mapped if master is iconic} -body {
    toplevel .master
    wm iconify .master
        when mapped if toplevel is iconic} -constraints {failsOnUbuntu failsOnXQuarz} -body {
    toplevel .top
    wm iconify .top
    update
    toplevel .subject
    wm transient .subject .master
    wm transient .subject .top
    update
    list [wm state .subject] [winfo ismapped .subject]
} -cleanup {
    deleteWindows
} -result {withdrawn 0}
test wm-transient-4.2 {already mapped transient toplevel
        is withdrawn if master is iconic} -body {
    toplevel .master
        is withdrawn if toplevel is iconic} -constraints failsOnUbuntu -body {
    toplevel .top
    raiseDelay
    wm iconify .master
    update
    wm iconify .top
    update idletasks
    toplevel .subject
    update
    wm transient .subject .master
    update
    update idletasks
    wm transient .subject .top
    update idletasks
    list [wm state .subject] [winfo ismapped .subject]
} -cleanup {
    deleteWindows
} -result {withdrawn 0}
test wm-transient-4.3 {iconify/deiconify on the master
        does a withdraw/deiconify on the transient} -setup {
test wm-transient-4.3 {iconify/deiconify on the toplevel
        does a withdraw/deiconify on the transient} -constraints failsOnUbuntu -setup {
    set results [list]
} -body {
    toplevel .master
    toplevel .top
    toplevel .subject
    update
    wm transient .subject .master
    wm iconify .master
    update
    update idletasks
    wm transient .subject .top
    wm iconify .top
    update idletasks
    lappend results [wm state .subject] [winfo ismapped .subject]
    wm deiconify .master
    update
    wm deiconify .top
    update idletasks
    lappend results [wm state .subject] [winfo ismapped .subject]
} -cleanup {
    deleteWindows
} -result {withdrawn 0 normal 1}

test wm-transient-5.1 {an error during transient command should not
        cause the map/unmap binding to be deleted} -setup {
    set results [list]
} -body {
    toplevel .master
    toplevel .top
    toplevel .subject
    update
    wm transient .subject .master
    wm transient .subject .top
    # Expect a bad window path error here
    lappend results [catch {wm transient .subject .bad}]
    wm withdraw .master
    wm withdraw .top
    update
    lappend results [wm state .subject]
    wm deiconify .master
    wm deiconify .top
    update
    lappend results [wm state .subject]
} -cleanup {
    deleteWindows
} -result {1 withdrawn normal}
test wm-transient-5.2 {remove transient property when master
test wm-transient-5.2 {remove transient property when toplevel
        is destroyed} -body {
    toplevel .master
    toplevel .top
    toplevel .subject
    wm transient .subject .master
    wm transient .subject .top
    update
    destroy .master
    destroy .top
    update
    wm transient .subject
} -cleanup {
    deleteWindows
} -result {}
test wm-transient-5.3 {remove transient property from window
        that had never been mapped when master is destroyed} -body {
    toplevel .master
        that had never been mapped when toplevel is destroyed} -body {
    toplevel .top
    toplevel .subject
    wm transient .subject .master
    destroy .master
    wm transient .subject .top
    destroy .top
    wm transient .subject
} -cleanup {
    deleteWindows
} -result {}

test wm-transient-6.1 {a withdrawn transient does not track
        state changes in the master} -body {
    toplevel .master
        state changes in the toplevel} -body {
    toplevel .top
    toplevel .subject
    update
    wm transient .subject .master
    wm transient .subject .top
    wm withdraw .subject
    wm withdraw .master
    wm deiconify .master
    wm withdraw .top
    wm deiconify .top
    # idle handler should not map the transient
    update
    wm state .subject
} -cleanup {
    deleteWindows
} -result {withdrawn}
test wm-transient-6.2 {a withdrawn transient does not track
        state changes in the master} -setup {
        state changes in the toplevel} -setup {
    set results [list]
} -body {
    toplevel .master
    toplevel .top
    toplevel .subject
    update
    wm transient .subject .master
    wm transient .subject .top
    wm withdraw .subject
    wm withdraw .master
    wm deiconify .master
    wm withdraw .top
    wm deiconify .top
    # idle handler should not map the transient
    update
    lappend results [wm state .subject]
    wm deiconify .subject
    lappend results [wm state .subject]
    wm withdraw .master
    wm withdraw .top
    lappend results [wm state .subject]
    wm deiconify .master
    wm deiconify .top
    # idle handler should map transient
    update
    lappend results [wm state .subject]
} -cleanup {
    deleteWindows
} -result {withdrawn normal withdrawn normal}
test wm-transient-6.3 {a withdrawn transient does not track
        state changes in the master} -body {
    toplevel .master
        state changes in the toplevel} -body {
    toplevel .top
    toplevel .subject
    update
    # withdraw before making window a transient
    wm withdraw .subject
    wm transient .subject .master
    wm withdraw .master
    wm deiconify .master
    wm transient .subject .top
    wm withdraw .top
    wm deiconify .top
    # idle handler should not map the transient
    update
    wm state .subject
} -cleanup {
    deleteWindows
} -result {withdrawn}

# wm-transient-7.*: See SF Tk Bug #592201 "wm transient fails with two masters"
# wm-transient-7.*: See SF Tk Bug #592201 "wm transient fails with two toplevels"
# wm-transient-7.3 through 7.5 all caused panics on Unix in Tk 8.4b1.
# 7.1 and 7.2 added to catch (potential) future errors.
#
test wm-transient-7.1 {Destroying transient} -body {
    toplevel .t
    toplevel .transient
    wm transient .transient .t
    destroy .transient
    destroy .t
    # OK: the above did not cause a panic.
} -cleanup {
    deleteWindows
}
test wm-transient-7.2 {Destroying master} -body {
    toplevel .t
test wm-transient-7.2 {Destroying toplevel} -body {
    toplevel .top
    toplevel .transient
    wm transient .transient .t
    destroy .t
    wm transient .transient .top
    destroy .top
    wm transient .transient
} -cleanup {
    deleteWindows
} -result {}
test wm-transient-7.3 {Reassign transient, destroy old master} -body {
test wm-transient-7.3 {Reassign transient, destroy old toplevel} -body {
    toplevel .t1
    toplevel .t2
    toplevel .transient
    wm transient .transient .t1
    wm transient .transient .t2
    destroy .t1	;# Caused panic in 8.4b1
    destroy .t2
    destroy .transient
} -cleanup {
    deleteWindows
}
test wm-transient-7.4 {Reassign transient, destroy new master} -body {
test wm-transient-7.4 {Reassign transient, destroy new toplevel} -body {
    toplevel .t1
    toplevel .t2
    toplevel .transient
    wm transient .transient .t1
    wm transient .transient .t2
    destroy .t2 	;# caused panic in 8.4b1
    destroy .t1
1920
1921
1922
1923
1924
1925
1926
1927

1928
1929
1930
1931
1932


1933
1934
1935
1936
1937
1938
1939
1925
1926
1927
1928
1929
1930
1931

1932
1933
1934
1935


1936
1937
1938
1939
1940
1941
1942
1943
1944







-
+



-
-
+
+







    destroy .transient
    destroy .t2 	;# caused panic in 8.4b1
    destroy .t1		;# so did this
} -cleanup {
    deleteWindows
}

test wm-transient-8.1 {transient to withdrawn window, Bug 1163496} -setup {
test wm-transient-8.1 {transient to withdrawn window, Bug 1163496} -constraints {failsOnUbuntu failsOnXQuarz} -setup {
    deleteWindows
    set result {}
} -body {
    # Verifies that transients stay on top of their masters, even if they were
    # made transients when those masters were withdrawn.
    # Verifies that transients stay on top of their toplevels, even if they were
    # made transients when those toplevels were withdrawn.
    toplevel .t1; wm withdraw  .t1;     update
    toplevel .t2; wm transient .t2 .t1; update
    lappend result [winfo ismapped .t1] [winfo ismapped .t2]
    wm deiconify .t1; update
    lappend result [winfo ismapped .t1] [winfo ismapped .t2]
    raise .t1; update
    lappend result [lsearch -all -inline -glob [wm stackorder .] ".t?"]
1997
1998
1999
2000
2001
2002
2003
2004

2005
2006
2007
2008
2009
2010
2011
2012

2013
2014
2015
2016
2017
2018
2019
2002
2003
2004
2005
2006
2007
2008

2009
2010
2011
2012
2013
2014
2015
2016

2017
2018
2019
2020
2021
2022
2023
2024







-
+







-
+







test wm-state-2.7 {state change before map} -body {
    toplevel .t
    wm iconify .t
    wm state .t
} -cleanup {
    deleteWindows
} -result {iconic}
test wm-state-2.8 {state change after map} -body {
test wm-state-2.8 {state change after map} -constraints failsOnUbuntu -body {
    toplevel .t
    update
    wm state .t iconic
    wm state .t
} -cleanup {
    deleteWindows
} -result {iconic}
test wm-state-2.9 {state change after map} -body {
test wm-state-2.9 {state change after map} -constraints failsOnUbuntu -body {
    toplevel .t
    update
    wm iconify .t
    wm state .t
} -cleanup {
    deleteWindows
} -result {iconic}
2273
2274
2275
2276
2277
2278
2279
2280

2281
2282
2283
2284
2285
2286
2287
2288
2289

2290
2291
2292
2293
2294
2295
2296
2297
2298

2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312





2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323

2324
2325
2326

2327
2328
2329

2330
2331
2332
2333
2334
2335
2336
2278
2279
2280
2281
2282
2283
2284

2285
2286
2287
2288
2289
2290
2291
2292
2293

2294
2295
2296
2297
2298
2299
2300
2301
2302

2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329

2330
2331

2332
2333
2334

2335
2336
2337

2338
2339
2340
2341
2342
2343
2344
2345







-
+








-
+








-
+














+
+
+
+
+







-


-
+


-
+


-
+







test wm-forget-1.1 "bug #2009788: forget toplevel can cause crash" -body {
    toplevel .parent
    toplevel .parent.child
    wm forget .parent.child
    winfo exists .parent.child
} -cleanup {
    deleteWindows
}  -result {1}
}  -result 1
test wm-forget-1.2 "bug #2009788: forget toplevel can cause crash" -body {
    toplevel .parent
    update
    toplevel .parent.child
    wm forget .parent.child
    winfo exists .parent.child
} -cleanup {
    deleteWindows
}  -result {1}
}  -result 1
test wm-forget-1.3 "bug #2009788: forget toplevel can cause crash" -body {
    toplevel .parent
    toplevel .parent.child
    wm forget .parent.child
    wm manage .parent.child
    winfo exists .parent.child
} -cleanup {
    deleteWindows
}  -result {1}
}  -result 1
test wm-forget-1.4 "pack into unmapped toplevel causes crash" -body {
    toplevel .parent
    toplevel .parent.child
    wm forget .parent.child
    pack [button .parent.child.button -text Hello]
    after 250 {destroy .parent}
    tkwait window .parent
} -cleanup {
    deleteWindows
} -result {}

test wm-forget-2 {bug [e9112ef96e] - [wm forget] doesn't completely} -setup {
    catch {destroy .l .f.b .f}
    set res {}
    if {[tk windowingsystem] == "aqua"} {
	proc doUpdate {} {update idletasks}
    } else {
	proc doUpdate {} {update}
    }
} -body {
    label .l -text "Top Dot"
    frame .f
    button .f.b -text Hello -command "puts Hello!"
    pack .l -side top
    pack .f.b
    pack .f -side bottom
    update
    set res [winfo manager .f]
    pack forget .f
    update
    doUpdate
    lappend res [winfo manager .f]
    wm manage .f
    update
    doUpdate
    lappend res [winfo manager .f]
    wm forget .f
    update
    doUpdate
    lappend res [winfo manager .f]
} -cleanup {
    destroy .l .f.b .f
    unset res
} -result {pack {} wm {}}

# FIXME:
Changes to tests/xmfbox.test.
1
2
3
4
5
6
7
8
9


10
11
12
13
14
15
16
1
2
3
4
5
6
7


8
9
10
11
12
13
14
15
16







-
-
+
+







# xmfbox.test --
#
#	This file is a Tcl script to test the file dialog that's used
#	when the tk_strictMotif flag is set. Because the file dialog
#	runs in a modal loop, the only way to test it sufficiently is
#	to call the internal Tcl procedures in xmfbox.tcl directly.
#
# Copyright (c) 1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# Contributions from Don Porter, NIST, 2002.  (not subject to US copyright)
# All rights reserved.

package require tcltest 2.2
namespace import ::tcltest::*
tcltest::configure {*}$argv
tcltest::loadTestedCommands
Changes to unix/Makefile.in.
92
93
94
95
96
97
98
99

100
101
102
103
104
105
106
92
93
94
95
96
97
98

99
100
101
102
103
104
105
106







-
+







# Directory in which to install html documentation:
HTML_INSTALL_DIR	= $(INSTALL_ROOT)$(HTML_DIR)

# Directory in which to install the configuration file tkConfig.sh:
CONFIG_INSTALL_DIR	= $(INSTALL_ROOT)$(libdir)

# Directory in which to install the demo files:
DEMO_INSTALL_DIR	= $(INSTALL_ROOT)$(TK_LIBRARY)/demos
DEMO_INSTALL_DIR	= $(INSTALL_ROOT)@DEMO_DIR@

# The directory containing the Tcl sources and headers appropriate
# for this version of Tk ("srcdir" will be replaced or has already
# been replaced by the configure script):
TCLDIR   = @TCL_SRC_DIR@
TCL_GENERIC_DIR		= $(TCLDIR)/generic

185
186
187
188
189
190
191
192
193


194
195
196
197
198
199
200
185
186
187
188
189
190
191


192
193
194
195
196
197
198
199
200







-
-
+
+







# XStringToKeysym is plenty fast, so you needn't define REDO_KEYSYM_LOOKUP.
KEYSYM_FLAGS		=
#KEYSYM_FLAGS		= -DREDO_KEYSYM_LOOKUP

# Tk does not used deprecated Tcl constructs so it should
# compile fine with -DTCL_NO_DEPRECATED. To remove its own
# set of deprecated code uncomment the second line.
NO_DEPRECATED_FLAGS	=
#NO_DEPRECATED_FLAGS	= -DTK_NO_DEPRECATED
NO_DEPRECATED_FLAGS	= -DTCL_NO_DEPRECATED
#NO_DEPRECATED_FLAGS	= -DTCL_NO_DEPRECATED -DTK_NO_DEPRECATED

# Some versions of make, like SGI's, use the following variable to
# determine which shell to use for executing commands:
SHELL			= @SHELL@

# BUILD_TCLSH is the fully qualified path name of the tclsh shell
# in the Tcl build directory. Test that need to be run in the
225
226
227
228
229
230
231
232

233
234
235
236
237
238
239
225
226
227
228
229
230
231

232
233
234
235
236
237
238
239







-
+







INSTALL			= $(SHELL) $(UNIX_DIR)/install-sh -c
INSTALL_PROGRAM		= ${INSTALL}
INSTALL_LIBRARY		= ${INSTALL}
INSTALL_DATA		= ${INSTALL} -m 644
INSTALL_DATA_DIR	= ${INSTALL} -d -m 755

# The symbol below provides support for dynamic loading and shared
# libraries.  See configure.in for a description of what it means.
# libraries.  See configure.ac for a description of what it means.
# The value of the symbol is normally set by the configure script.

SHLIB_CFLAGS		= @SHLIB_CFLAGS@ -DBUILD_tk

# To enable support for stubs in Tcl.
STUB_LIB_FILE		= @TK_STUB_LIB_FILE@

264
265
266
267
268
269
270
271

272
273
274
275
276
277
278
264
265
266
267
268
269
270

271
272
273
274
275
276
277
278







-
+








# Libraries to use when linking.  This definition is determined by the
# configure script.
LIBS = @LIBS@ $(X11_LIB_SWITCHES) @TCL_LIBS@
WISH_LIBS = $(TCL_LIB_SPEC) @LIBS@ $(X11_LIB_SWITCHES) @TCL_LIBS@ @EXTRA_WISH_LIBS@

# The symbols below provide support for dynamic loading and shared
# libraries.  See configure.in for a description of what the
# libraries.  See configure.ac for a description of what the
# symbols mean.  The values of the symbols are normally set by the
# configure script.  You shouldn't normally need to modify any of
# these definitions by hand.

STLIB_LD		= @STLIB_LD@
SHLIB_LD		= @SHLIB_LD@
SHLIB_LD_LIBS		= @SHLIB_LD_LIBS@
325
326
327
328
329
330
331
332
333
334



335
336
337
338
339
340
341
342
343
344
345




346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361

362
363
364
365
366
367
368
369
370
371
372
373
374
375



376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394

395
396
397
398
399
400
401
402
403
404
405

406
407
408
409
410
411
412
325
326
327
328
329
330
331



332
333
334
335
336
337
338
339
340
341




342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360

361
362
363
364
365
366
367
368
369
370
371
372
373


374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394

395
396
397
398
399
400
401
402
403
404
405

406
407
408
409
410
411
412
413







-
-
-
+
+
+







-
-
-
-
+
+
+
+















-
+












-
-
+
+
+


















-
+










-
+








# Flags to be passed to installManPage to control how the manpages
# should be installed (symlinks, compression, package name suffix).
MAN_FLAGS               = @MAN_FLAGS@

CC			= @CC@

CC_SWITCHES_NO_STUBS = ${CFLAGS} ${CFLAGS_WARNING} ${SHLIB_CFLAGS} \
-I${UNIX_DIR} -I${GENERIC_DIR} -I${BMAP_DIR} -I${TCL_GENERIC_DIR} \
-I${TCL_PLATFORM_DIR} ${@TK_WINDOWINGSYSTEM@_INCLUDES} ${AC_FLAGS} \
CC_SWITCHES_NO_STUBS = -I${UNIX_DIR} -I${GENERIC_DIR} -I${BMAP_DIR} \
${@TK_WINDOWINGSYSTEM@_INCLUDES} ${CFLAGS} ${CFLAGS_WARNING} \
${SHLIB_CFLAGS} -I${TCL_GENERIC_DIR} -I${TCL_PLATFORM_DIR} ${AC_FLAGS} \
${PROTO_FLAGS} ${SECURITY_FLAGS} ${MEM_DEBUG_FLAGS} ${KEYSYM_FLAGS} \
${NO_DEPRECATED_FLAGS} @EXTRA_CC_SWITCHES@

CC_SWITCHES = $(CC_SWITCHES_NO_STUBS) @TCL_STUB_FLAGS@

APP_CC_SWITCHES = $(CC_SWITCHES_NO_STUBS) @EXTRA_APP_CC_SWITCHES@

DEPEND_SWITCHES = ${CFLAGS} -I${UNIX_DIR} -I${GENERIC_DIR} -I${BMAP_DIR} \
-I${TCL_GENERIC_DIR} -I${TCL_PLATFORM_DIR} ${@TK_WINDOWINGSYSTEM@_INCLUDES} \
${AC_FLAGS} ${PROTO_FLAGS} ${SECURITY_FLAGS} ${MEM_DEBUG_FLAGS} \
${KEYSYM_FLAGS} @EXTRA_CC_SWITCHES@
DEPEND_SWITCHES = -I${UNIX_DIR} -I${GENERIC_DIR} -I${BMAP_DIR} \
${@TK_WINDOWINGSYSTEM@_INCLUDES} ${CFLAGS} -I${TCL_GENERIC_DIR} \
-I${TCL_PLATFORM_DIR} ${AC_FLAGS} ${PROTO_FLAGS} ${SECURITY_FLAGS} \
${MEM_DEBUG_FLAGS} ${KEYSYM_FLAGS} @EXTRA_CC_SWITCHES@

WISH_OBJS = tkAppInit.o

TKTEST_OBJS = tkTestInit.o tkTest.o tkSquare.o tkOldTest.o \
	$(@TK_WINDOWINGSYSTEM@_TKTEST_OBJS)

WIDG_OBJS = tkButton.o tkEntry.o tkFrame.o tkListbox.o \
	tkMenu.o tkMenubutton.o tkMenuDraw.o tkMessage.o \
	tkPanedWindow.o tkScale.o tkScrollbar.o

CANV_OBJS = tkCanvas.o tkCanvArc.o tkCanvBmap.o tkCanvImg.o \
	tkCanvLine.o tkCanvPoly.o tkCanvPs.o tkCanvText.o \
	tkCanvUtil.o tkCanvWind.o tkRectOval.o tkTrig.o

IMAGE_OBJS = tkImage.o tkImgBmap.o tkImgGIF.o tkImgPNG.o tkImgPPM.o \
	tkImgPhoto.o tkImgPhInstance.o
	tkImgPhoto.o tkImgPhInstance.o tkImgListFormat.o tkImgSVGnano.o

TEXT_OBJS = tkText.o tkTextBTree.o tkTextDisp.o tkTextImage.o tkTextIndex.o \
	tkTextMark.o tkTextTag.o tkTextWind.o

# either tkUnixFont.o (default) or tkUnixRFont.o (if --enable-xft)
#
FONT_OBJS = @UNIX_FONT_OBJS@

GENERIC_OBJS = tk3d.o tkArgv.o tkAtom.o tkBind.o tkBitmap.o tkBusy.o \
	tkClipboard.o \
	tkCmds.o tkColor.o tkConfig.o tkConsole.o tkCursor.o tkError.o \
	tkEvent.o tkFocus.o tkFont.o tkGet.o tkGC.o tkGeometry.o tkGrab.o \
	tkGrid.o tkMain.o tkObj.o tkOldConfig.o tkOption.o tkPack.o tkPlace.o \
	tkSelect.o tkStyle.o tkUndo.o tkUtil.o tkVisual.o tkWindow.o
	tkGrid.o tkMain.o tkObj.o tkOldConfig.o tkOption.o tkPack.o \
	tkPkgConfig.o tkPlace.o	tkSelect.o tkStyle.o tkUndo.o tkUtil.o \
	tkVisual.o tkWindow.o

TTK_OBJS = \
	ttkBlink.o ttkButton.o ttkCache.o ttkClamTheme.o ttkClassicTheme.o \
	ttkDefaultTheme.o ttkElements.o ttkEntry.o ttkFrame.o ttkImage.o \
	ttkInit.o ttkLabel.o ttkLayout.o ttkManager.o ttkNotebook.o \
	ttkPanedwindow.o ttkProgress.o ttkScale.o ttkScrollbar.o ttkScroll.o \
	ttkSeparator.o ttkSquare.o ttkState.o \
	ttkTagSet.o ttkTheme.o ttkTrace.o ttkTrack.o ttkTreeview.o \
	ttkWidget.o ttkStubInit.o

STUB_OBJS = tkStubInit.o

STUB_LIB_OBJS = tkStubLib.o ttkStubLib.o

X11_OBJS = tkUnix.o tkUnix3d.o tkUnixButton.o tkUnixColor.o tkUnixConfig.o \
	tkUnixCursor.o tkUnixDraw.o tkUnixEmbed.o tkUnixEvent.o \
	tkUnixFocus.o  $(FONT_OBJS) tkUnixInit.o tkUnixKey.o tkUnixMenu.o \
	tkUnixMenubu.o tkUnixScale.o tkUnixScrlbr.o tkUnixSelect.o \
	tkUnixSend.o tkUnixWm.o tkUnixXId.o
	tkUnixSend.o tkUnixSysNotify.o tkUnixSysTray.o tkUnixWm.o tkUnixXId.o

AQUA_OBJS = tkMacOSXBitmap.o tkMacOSXButton.o tkMacOSXClipboard.o \
	tkMacOSXColor.o tkMacOSXConfig.o tkMacOSXCursor.o tkMacOSXDebug.o \
	tkMacOSXDialog.o tkMacOSXDraw.o tkMacOSXEmbed.o tkMacOSXEntry.o \
	tkMacOSXEvent.o tkMacOSXFont.o tkMacOSXHLEvents.o tkMacOSXImage.o \
	tkMacOSXInit.o tkMacOSXKeyboard.o tkMacOSXKeyEvent.o \
	tkMacOSXMenu.o \
	tkMacOSXMenubutton.o tkMacOSXMenus.o tkMacOSXMouseEvent.o \
	tkMacOSXNotify.o tkMacOSXRegion.o tkMacOSXScrlbr.o tkMacOSXSend.o \
	tkMacOSXServices.o tkMacOSXSubwindows.o tkMacOSXWindowEvent.o \
	tkMacOSXWm.o tkMacOSXXStubs.o \
	tkMacOSXWm.o tkMacOSXXStubs.o tkMacOSXSysTray.o\
	tkFileFilter.o tkMacWinMenu.o tkPointer.o tkUnix3d.o tkUnixScale.o \
	xcolors.o xdraw.o xgc.o ximage.o xutil.o \
	ttkMacOSXTheme.o

AQUA_TKTEST_OBJS = tkMacOSXTest.o

OBJS =  $(GENERIC_OBJS) $(WIDG_OBJS) $(CANV_OBJS) $(IMAGE_OBJS) $(TEXT_OBJS) \
430
431
432
433
434
435
436

437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454

455
456

457
458
459
460
461
462
463
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458

459
460
461
462
463
464
465
466







+


















+

-
+







	$(GENERIC_DIR)/tkError.c $(GENERIC_DIR)/tkEvent.c \
	$(GENERIC_DIR)/tkFocus.c $(GENERIC_DIR)/tkFont.c \
	$(GENERIC_DIR)/tkGet.c $(GENERIC_DIR)/tkGC.c \
	$(GENERIC_DIR)/tkGeometry.c $(GENERIC_DIR)/tkGrab.c \
	$(GENERIC_DIR)/tkGrid.c $(GENERIC_DIR)/tkConsole.c \
	$(GENERIC_DIR)/tkMain.c $(GENERIC_DIR)/tkOption.c \
	$(GENERIC_DIR)/tkPack.c $(GENERIC_DIR)/tkPlace.c \
	$(GENERIC_DIR)/tkPkgConfig.c \
	$(GENERIC_DIR)/tkSelect.c $(GENERIC_DIR)/tkStyle.c \
	$(GENERIC_DIR)/tkUndo.c $(GENERIC_DIR)/tkUtil.c \
	$(GENERIC_DIR)/tkVisual.c $(GENERIC_DIR)/tkWindow.c \
	$(GENERIC_DIR)/tkButton.c $(GENERIC_DIR)/tkObj.c \
	$(GENERIC_DIR)/tkEntry.c $(GENERIC_DIR)/tkFrame.c \
	$(GENERIC_DIR)/tkListbox.c $(GENERIC_DIR)/tkMenu.c \
	$(GENERIC_DIR)/tkMenubutton.c $(GENERIC_DIR)/tkMenuDraw.c \
	$(GENERIC_DIR)/tkMessage.c $(GENERIC_DIR)/tkPanedWindow.c \
	$(GENERIC_DIR)/tkScale.c $(GENERIC_DIR)/tkScrollbar.c \
	$(GENERIC_DIR)/tkCanvas.c $(GENERIC_DIR)/tkCanvArc.c \
	$(GENERIC_DIR)/tkCanvBmap.c $(GENERIC_DIR)/tkCanvImg.c \
	$(GENERIC_DIR)/tkCanvLine.c $(GENERIC_DIR)/tkCanvPoly.c \
	$(GENERIC_DIR)/tkCanvPs.c $(GENERIC_DIR)/tkCanvText.c \
	$(GENERIC_DIR)/tkCanvUtil.c \
	$(GENERIC_DIR)/tkCanvWind.c $(GENERIC_DIR)/tkRectOval.c \
	$(GENERIC_DIR)/tkTrig.c $(GENERIC_DIR)/tkImage.c \
	$(GENERIC_DIR)/tkImgBmap.c $(GENERIC_DIR)/tkImgGIF.c \
	$(GENERIC_DIR)/tkImgPNG.c $(GENERIC_DIR)/tkImgPPM.c \
	$(GENERIC_DIR)/tkImgSVGnano.c $(GENERIC_DIR)/tkImgSVGnano.c \
	$(GENERIC_DIR)/tkImgPhoto.c $(GENERIC_DIR)/tkImgPhInstance.c \
	$(GENERIC_DIR)/tkText.c \
	$(GENERIC_DIR)/tkImgListFormat.c $(GENERIC_DIR)/tkText.c \
	$(GENERIC_DIR)/tkTextBTree.c $(GENERIC_DIR)/tkTextDisp.c \
	$(GENERIC_DIR)/tkTextImage.c \
	$(GENERIC_DIR)/tkTextIndex.c $(GENERIC_DIR)/tkTextMark.c \
	$(GENERIC_DIR)/tkTextTag.c $(GENERIC_DIR)/tkTextWind.c \
	$(GENERIC_DIR)/tkOldConfig.c $(GENERIC_DIR)/tkOldTest.c \
	$(GENERIC_DIR)/tkSquare.c $(GENERIC_DIR)/tkTest.c \
	$(GENERIC_DIR)/tkStubInit.c
506
507
508
509
510
511
512
513
514
515



516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532

533
534
535
536
537
538
539
509
510
511
512
513
514
515



516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534

535
536
537
538
539
540
541
542







-
-
-
+
+
+
















-
+







	$(UNIX_DIR)/tkUnixEmbed.c $(UNIX_DIR)/tkUnixEvent.c \
	$(UNIX_DIR)/tkUnixFocus.c \
	$(UNIX_DIR)/tkUnixRFont.c \
	$(UNIX_DIR)/tkUnixFont.c $(UNIX_DIR)/tkUnixInit.c \
	$(UNIX_DIR)/tkUnixKey.c \
	$(UNIX_DIR)/tkUnixMenu.c $(UNIX_DIR)/tkUnixMenubu.c \
	$(UNIX_DIR)/tkUnixScale.c $(UNIX_DIR)/tkUnixScrlbr.c \
	$(UNIX_DIR)/tkUnixSelect.c \
	$(UNIX_DIR)/tkUnixSend.c $(UNIX_DIR)/tkUnixWm.c \
	$(UNIX_DIR)/tkUnixXId.c
	$(UNIX_DIR)/tkUnixSelect.c $(UNIX_DIR)/tkUnixSend.c \
	$(UNIX_DIR)/tkUnixSysNotify $(UNIX_DIR)/tkUnixSysTray.c \
	$(UNIX_DIR)/tkUnixWm.c $(UNIX_DIR)/tkUnixXId.c

AQUA_SRCS = \
	$(MAC_OSX_DIR)/tkMacOSXBitmap.c $(MAC_OSX_DIR)/tkMacOSXButton.c \
	$(MAC_OSX_DIR)/tkMacOSXClipboard.c $(MAC_OSX_DIR)/tkMacOSXColor.c \
	$(MAC_OSX_DIR)/tkMacOSXConfig.c $(MAC_OSX_DIR)/tkMacOSXCursor.c \
	$(MAC_OSX_DIR)/tkMacOSXDebug.c $(MAC_OSX_DIR)/tkMacOSXDialog.c \
	$(MAC_OSX_DIR)/tkMacOSXDraw.c $(MAC_OSX_DIR)/tkMacOSXEmbed.c \
	$(MAC_OSX_DIR)/tkMacOSXEntry.c $(MAC_OSX_DIR)/tkMacOSXEvent.c \
	$(MAC_OSX_DIR)/tkMacOSXFont.c $(MAC_OSX_DIR)/tkMacOSXHLEvents.c \
	$(MAC_OSX_DIR)/tkMacOSXImage.c \
	$(MAC_OSX_DIR)/tkMacOSXInit.c $(MAC_OSX_DIR)/tkMacOSXKeyboard.c \
	$(MAC_OSX_DIR)/tkMacOSXKeyEvent.c \
	$(MAC_OSX_DIR)/tkMacOSXMenu.c \
	$(MAC_OSX_DIR)/tkMacOSXMenubutton.c $(MAC_OSX_DIR)/tkMacOSXMenus.c \
	$(MAC_OSX_DIR)/tkMacOSXMouseEvent.c $(MAC_OSX_DIR)/tkMacOSXNotify.c \
	$(MAC_OSX_DIR)/tkMacOSXRegion.c $(MAC_OSX_DIR)/tkMacOSXScrlbr.c \
	$(MAC_OSX_DIR)/tkMacOSXServices.c \
	$(MAC_OSX_DIR)/tkMacOSXServices.c $(MAC_OSX_DIR)/tkMacOSXSysTray.c \
	$(MAC_OSX_DIR)/tkMacOSXSend.c $(MAC_OSX_DIR)/tkMacOSXSubwindows.c \
	$(MAC_OSX_DIR)/tkMacOSXTest.c $(MAC_OSX_DIR)/tkMacOSXWindowEvent.c \
	$(MAC_OSX_DIR)/tkMacOSXWm.c $(MAC_OSX_DIR)/tkMacOSXXStubs.c \
	$(GENERIC_DIR)/tkFileFilter.c $(GENERIC_DIR)/tkMacWinMenu.c \
	$(GENERIC_DIR)/tkPointer.c $(UNIX_DIR)/tkUnix3d.c \
	$(UNIX_DIR)/tkUnixScale.c $(XLIB_DIR)/xcolors.c $(XLIB_DIR)/xdraw.c \
	$(XLIB_DIR)/xgc.c $(XLIB_DIR)/ximage.c $(XLIB_DIR)/xutil.c \
570
571
572
573
574
575
576
577

578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
573
574
575
576
577
578
579

580
581
582
583
584
585





586
587
588
589
590
591
592







-
+





-
-
-
-
-








SHELL_ENV = \
	@LD_LIBRARY_PATH_VAR@="`pwd`:${TCL_BIN_DIR}:$${@LD_LIBRARY_PATH_VAR@}"; \
	export @LD_LIBRARY_PATH_VAR@; \
	TCL_LIBRARY=$(TCLDIR)/library; export TCL_LIBRARY; \
	TK_LIBRARY=@TK_SRC_DIR@/library; export TK_LIBRARY;

all: binaries libraries doc
all: binaries libraries

binaries: ${LIB_FILE} ${WISH_EXE}

libraries:

$(TOP_DIR)/doc/man.macros:
	$(INSTALL_DATA) $(TCLDIR)/doc/man.macros $(TOP_DIR)/doc/man.macros

doc: $(TOP_DIR)/doc/man.macros

# The following target is configured by autoconf to generate either
# a shared library or non-shared library for Tk.
${LIB_FILE}: ${STUB_LIB_FILE} @LIB_RSRC_FILE@ ${OBJS}
	rm -f $@
	@MAKE_LIB@

${STUB_LIB_FILE}: ${STUB_LIB_OBJS}
630
631
632
633
634
635
636
637
638


639
640
641
642
643
644
645
628
629
630
631
632
633
634


635
636
637
638
639
640
641
642
643







-
-
+
+







# picking up an already installed version of the Tcl or
# Tk shared libraries.

$(TKTEST_EXE): $(TKTEST_OBJS) $(TK_LIB_FILE)
	$(MAKE) tktest-real LIB_RUNTIME_DIR="`pwd`:$(TCL_BIN_DIR)"

tktest-real: ${TK_STUB_LIB_FILE}
	${CC} ${CFLAGS} ${LDFLAGS} $(TKTEST_OBJS) ${TK_STUB_LIB_FILE} ${TCL_STUB_LIB_SPEC} @TK_BUILD_LIB_SPEC@ \
		$(WISH_LIBS) $(CC_SEARCH_FLAGS) -o $(TKTEST_EXE)
	${CC} ${CFLAGS} ${LDFLAGS} $(TKTEST_OBJS) @TK_BUILD_LIB_SPEC@ $(WISH_LIBS) \
		${TK_STUB_LIB_FILE} ${TCL_STUB_LIB_SPEC} $(CC_SEARCH_FLAGS) -o $(TKTEST_EXE)

# # FIXME: This xttest rule seems to be broken in a number of ways.  It should
# # use CC_SEARCH_FLAGS, it does not include the shared lib location logic from
# # tktest, and it is not clear where this test.o object file comes from.
#
# xttest: test.o tkTest.o tkSquare.o $(TK_LIB_FILE) ${TK_STUB_LIB_FILE}
# 	${CC} ${CFLAGS} ${LDFLAGS} test.o tkTest.o tkSquare.o \
725
726
727
728
729
730
731
732

733
734
735

736
737
738
739

740
741

742
743


744
745
746
747
748
749
750
751
752
753


754
755
756
757
758
759
760
761
762
763
764
765
766


767
768
769
770
771
772
773
723
724
725
726
727
728
729

730
731
732

733
734
735
736

737
738

739
740

741
742
743
744
745
746
747
748
749
750


751
752
753
754
755
756
757
758
759
760
761
762
763


764
765
766
767
768
769
770
771
772







-
+


-
+



-
+

-
+

-
+
+








-
-
+
+











-
-
+
+







		else true; \
		fi; \
	    done;
	@if test "x$(TK_SHARED_BUILD)" = "x1"; then \
	    echo "Creating package index $(PKG_INDEX)"; \
	    rm -f "$(PKG_INDEX)"; \
	    (\
	    echo "if {[catch {package present Tcl 8.6.0}]} return";\
	    echo "if {[catch {package present Tcl 8.6-}]} return";\
	    relative=`echo | awk '{ORS=" "; split("$(TK_PKG_DIR)",a,"/"); for (f in a) {print ".."}}'`;\
	    if test "x$(DLL_INSTALL_DIR)" != "x$(BIN_INSTALL_DIR)"; then \
	    echo "package ifneeded Tk $(MAJOR_VERSION).$(MINOR_VERSION)$(PATCH_LEVEL) [list load [file normalize [file join \$$dir $${relative}$(TK_LIB_FILE)]] Tk]";\
	    echo "package ifneeded tk $(MAJOR_VERSION).$(MINOR_VERSION)$(PATCH_LEVEL) [list load [file normalize [file join \$$dir $${relative}$(TK_LIB_FILE)]]]";\
	    else \
	    echo "if {(\$$::tcl_platform(platform) eq \"unix\") && ([info exists ::env(DISPLAY)]";\
	    echo "	|| ([info exists ::argv] && (\"-display\" in \$$::argv)))} {";\
	    echo "    package ifneeded Tk $(MAJOR_VERSION).$(MINOR_VERSION)$(PATCH_LEVEL) [list load [file normalize [file join \$$dir $${relative}.. bin $(TK_LIB_FILE)]] Tk]";\
	    echo "    package ifneeded tk $(MAJOR_VERSION).$(MINOR_VERSION)$(PATCH_LEVEL) [list load [file normalize [file join \$$dir $${relative}.. bin $(TK_LIB_FILE)]]]";\
	    echo "} else {";\
	    echo "    package ifneeded Tk $(MAJOR_VERSION).$(MINOR_VERSION)$(PATCH_LEVEL) [list load [file normalize [file join \$$dir $${relative}.. bin tk${MAJOR_VERSION}${MINOR_VERSION}.dll]] Tk]";\
	    echo "    package ifneeded tk $(MAJOR_VERSION).$(MINOR_VERSION)$(PATCH_LEVEL) [list load [file normalize [file join \$$dir $${relative}.. bin tk${MAJOR_VERSION}${MINOR_VERSION}.dll]]]";\
	    echo "}";\
	    fi \
	    fi; \
	    echo "package ifneeded Tk $(MAJOR_VERSION).$(MINOR_VERSION)$(PATCH_LEVEL) [list package require -exact tk $(MAJOR_VERSION).$(MINOR_VERSION)$(PATCH_LEVEL)]"\
	    ) > "$(PKG_INDEX)"; \
	    fi
	@echo "Installing $(LIB_FILE) to $(DLL_INSTALL_DIR)/"
	@@INSTALL_LIB@
	@chmod 555 "$(DLL_INSTALL_DIR)/$(LIB_FILE)"
	@if test -f "tk${MAJOR_VERSION}${MINOR_VERSION}.dll"; then \
	    $(INSTALL_LIBRARY) "tk${MAJOR_VERSION}${MINOR_VERSION}.dll" "$(DLL_INSTALL_DIR)";\
	    chmod 555 "$(DLL_INSTALL_DIR)/tk${MAJOR_VERSION}${MINOR_VERSION}.dll";\
	    $(INSTALL_LIBRARY) "../win/libtk${MAJOR_VERSION}${MINOR_VERSION}.a" "$(LIB_INSTALL_DIR)";\
	    chmod 555 "$(LIB_INSTALL_DIR)/libtk${MAJOR_VERSION}${MINOR_VERSION}.a";\
	    $(INSTALL_LIBRARY) "../win/libtk${MAJOR_VERSION}${MINOR_VERSION}.dll.a" "$(LIB_INSTALL_DIR)";\
	    chmod 555 "$(LIB_INSTALL_DIR)/libtk${MAJOR_VERSION}${MINOR_VERSION}.dll.a";\
	fi
	@echo "Installing ${WISH_EXE} as $(BIN_INSTALL_DIR)/wish$(VERSION)${EXE_SUFFIX}"
	@$(INSTALL_PROGRAM) ${WISH_EXE} "$(BIN_INSTALL_DIR)/wish$(VERSION)${EXE_SUFFIX}"
	@echo "Installing tkConfig.sh to $(CONFIG_INSTALL_DIR)/"
	@$(INSTALL_DATA) tkConfig.sh "$(CONFIG_INSTALL_DIR)/tkConfig.sh"
	@if test "$(STUB_LIB_FILE)" != "" ; then \
	    echo "Installing $(STUB_LIB_FILE) to $(LIB_INSTALL_DIR)/"; \
	    @INSTALL_STUB_LIB@ ; \
	fi
	@EXTRA_INSTALL_BINARIES@
	@echo "Installing pkg-config file to $(LIB_INSTALL_DIR)/pkgconfig/"
	@$(INSTALL_DATA_DIR) $(LIB_INSTALL_DIR)/pkgconfig
	@$(INSTALL_DATA) tk.pc $(LIB_INSTALL_DIR)/pkgconfig/tk.pc
	@$(INSTALL_DATA_DIR) "$(LIB_INSTALL_DIR)/pkgconfig"
	@$(INSTALL_DATA) tk.pc "$(LIB_INSTALL_DIR)/pkgconfig/tk.pc"

install-libraries: libraries
	@for i in "$(SCRIPT_INSTALL_DIR)" "$(SCRIPT_INSTALL_DIR)/images" \
		"$(SCRIPT_INSTALL_DIR)/msgs" "$(SCRIPT_INSTALL_DIR)/ttk"; \
	    do \
	    if [ -n "$$i" -a ! -d "$$i" ] ; then \
		echo "Making directory $$i"; \
1010
1011
1012
1013
1014
1015
1016


























1017
1018
1019
1020
1021
1022
1023
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkOldConfig.c

tkOption.o: $(GENERIC_DIR)/tkOption.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkOption.c

tkPack.o: $(GENERIC_DIR)/tkPack.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkPack.c

# TIP #59, embedding of configuration information into the binary library.
#
# Part of Tk's configuration information are the paths where it was installed
# and where it will look for its libraries (which can be different). We derive
# this information from the variables which can be overridden by the user. As
# every path can be configured separately we do not remember one general
# prefix/exec_prefix but all the different paths individually.

tkPkgConfig.o: $(GENERIC_DIR)/tkPkgConfig.c
	$(CC) -c $(CC_SWITCHES)					\
		-DCFG_INSTALL_LIBDIR="\"$(LIB_INSTALL_DIR)\"" \
		-DCFG_INSTALL_BINDIR="\"$(BIN_INSTALL_DIR)\"" \
		-DCFG_INSTALL_SCRDIR="\"$(SCRIPT_INSTALL_DIR)\"" \
		-DCFG_INSTALL_INCDIR="\"$(INCLUDE_INSTALL_DIR)\"" \
		-DCFG_INSTALL_DOCDIR="\"$(MAN_INSTALL_DIR)\"" \
		-DCFG_INSTALL_DEMODIR="\"$(DEMO_INSTALL_DIR)\"" \
		\
		-DCFG_RUNTIME_LIBDIR="\"$(libdir)\"" \
		-DCFG_RUNTIME_BINDIR="\"$(bindir)\"" \
		-DCFG_RUNTIME_SCRDIR="\"$(TK_LIBRARY)\"" \
		-DCFG_RUNTIME_INCDIR="\"$(includedir)\"" \
		-DCFG_RUNTIME_DOCDIR="\"$(mandir)\"" \
		-DCFG_RUNTIME_DEMODIR="\"$(DEMO_INSTALL_DIR)\"" \
		\
		$(GENERIC_DIR)/tkPkgConfig.c

tkPlace.o: $(GENERIC_DIR)/tkPlace.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkPlace.c

tkSelect.o: $(GENERIC_DIR)/tkSelect.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkSelect.c

1107
1108
1109
1110
1111
1112
1113



1114
1115
1116
1117
1118
1119
1120
1121
1122



1123
1124
1125
1126
1127
1128
1129
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160







+
+
+









+
+
+








tkImage.o: $(GENERIC_DIR)/tkImage.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkImage.c

tkImgBmap.o: $(GENERIC_DIR)/tkImgBmap.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkImgBmap.c

tkImgListFormat.o: $(GENERIC_DIR)/tkImgListFormat.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkImgListFormat.c

tkImgGIF.o: $(GENERIC_DIR)/tkImgGIF.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkImgGIF.c

tkImgPNG.o: $(GENERIC_DIR)/tkImgPNG.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkImgPNG.c

tkImgPPM.o: $(GENERIC_DIR)/tkImgPPM.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkImgPPM.c

tkImgSVGnano.o: $(GENERIC_DIR)/tkImgSVGnano.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkImgSVGnano.c

tkImgPhoto.o: $(GENERIC_DIR)/tkImgPhoto.c $(GENERIC_DIR)/tkImgPhoto.h
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkImgPhoto.c

tkImgPhInstance.o: $(GENERIC_DIR)/tkImgPhInstance.c $(GENERIC_DIR)/tkImgPhoto.h
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkImgPhInstance.c

tkOldTest.o: $(GENERIC_DIR)/tkOldTest.c
1202
1203
1204
1205
1206
1207
1208
1209

1210
1211
1212
1213
1214
1215
1216
1233
1234
1235
1236
1237
1238
1239

1240
1241
1242
1243
1244
1245
1246
1247







-
+







	$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixFont.c

# NB: tkUnixRFont.o uses nondefault CFLAGS
tkUnixRFont.o: $(UNIX_DIR)/tkUnixRFont.c
	$(CC) -c $(CC_SWITCHES) $(XFT_CFLAGS) $(UNIX_DIR)/tkUnixRFont.c

tkUnixInit.o: $(UNIX_DIR)/tkUnixInit.c tkConfig.sh
	$(CC) -c $(CC_SWITCHES) -DTK_LIBRARY=\"${TK_LIBRARY}\" \
	$(CC) -c $(CC_SWITCHES) \
	    $(UNIX_DIR)/tkUnixInit.c

tkUnixKey.o: $(UNIX_DIR)/tkUnixKey.c
	$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixKey.c

tkUnixMenu.o: $(UNIX_DIR)/tkUnixMenu.c
	$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixMenu.c
1226
1227
1228
1229
1230
1231
1232






1233
1234
1235
1236
1237
1238
1239
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276







+
+
+
+
+
+








tkUnixSelect.o: $(UNIX_DIR)/tkUnixSelect.c
	$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixSelect.c

tkUnixSend.o: $(UNIX_DIR)/tkUnixSend.c
	$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixSend.c

tkUnixSysNotify.o: $(UNIX_DIR)/tkUnixSysNotify.c
	$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixSysNotify.c

tkUnixSysTray.o: $(UNIX_DIR)/tkUnixSysTray.c
	$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixSysTray.c

tkUnixWm.o: $(UNIX_DIR)/tkUnixWm.c
	$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixWm.c

tkUnixXId.o: $(UNIX_DIR)/tkUnixXId.c
	$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixXId.c

tkMacOSXBitmap.o: $(MAC_OSX_DIR)/tkMacOSXBitmap.c
1278
1279
1280
1281
1282
1283
1284
1285

1286
1287
1288
1289
1290
1291
1292
1315
1316
1317
1318
1319
1320
1321

1322
1323
1324
1325
1326
1327
1328
1329







-
+







tkMacOSXHLEvents.o: $(MAC_OSX_DIR)/tkMacOSXHLEvents.c
	$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXHLEvents.c

tkMacOSXImage.o: $(MAC_OSX_DIR)/tkMacOSXImage.c
	$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXImage.c

tkMacOSXInit.o: $(MAC_OSX_DIR)/tkMacOSXInit.c tkConfig.sh
	$(CC) -c $(CC_SWITCHES) -DTK_LIBRARY=\"${TK_LIBRARY}\" \
	$(CC) -c $(CC_SWITCHES) \
	    $(MAC_OSX_DIR)/tkMacOSXInit.c

tkMacOSXKeyboard.o: $(MAC_OSX_DIR)/tkMacOSXKeyboard.c
	$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXKeyboard.c

tkMacOSXKeyEvent.o: $(MAC_OSX_DIR)/tkMacOSXKeyEvent.c
	$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXKeyEvent.c
1332
1333
1334
1335
1336
1337
1338



1339
1340
1341
1342
1343
1344
1345
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385







+
+
+








tkMacOSXWm.o: $(MAC_OSX_DIR)/tkMacOSXWm.c
	$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXWm.c

tkMacOSXXStubs.o: $(MAC_OSX_DIR)/tkMacOSXXStubs.c
	$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXXStubs.c

tkMacOSXSysTray.o: $(MAC_OSX_DIR)/tkMacOSXSysTray.c
	$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXSysTray.c

tkFileFilter.o: $(GENERIC_DIR)/tkFileFilter.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkFileFilter.c

tkMacWinMenu.o: $(GENERIC_DIR)/tkMacWinMenu.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkMacWinMenu.c

tkPointer.o: $(GENERIC_DIR)/tkPointer.c
1473
1474
1475
1476
1477
1478
1479
1480

1481
1482
1483
1484
1485
1486
1487
1513
1514
1515
1516
1517
1518
1519

1520
1521
1522
1523
1524
1525
1526
1527







-
+







	@echo "Warning: ttkStubInit.c may be out of date."
	@echo "Developers may want to run \"make genstubs\" to regenerate."
	@echo "This warning can be safely ignored, do not report as a bug!"

genstubs:
	$(TCL_EXE) $(TOOL_DIR)/genStubs.tcl $(GENERIC_DIR) \
		$(GENERIC_DIR)/tk.decls $(GENERIC_DIR)/tkInt.decls
	$(TCL_EXE) $(TTK_DIR)/ttkGenStubs.tcl $(TTK_DIR) $(TTK_DIR)/ttk.decls
	$(TCL_EXE) $(TOOL_DIR)/genStubs.tcl $(TTK_DIR) $(TTK_DIR)/ttk.decls

#
# Target to check that all exported functions have an entry in the stubs
# tables.
#

checkstubs: $(TK_LIB_FILE)
1527
1528
1529
1530
1531
1532
1533
1534

1535
1536
1537
1538
1539
1540
1541



1542

1543
1544
1545
1546
1547
1548
1549




1550

1551
1552
1553
1554




1555
1556

1557
1558
1559
1560
1561
1562


1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573





1574
1575
1576
1577
1578
1579
1580
1581
1582






1583
1584
1585
1586

1587
1588
1589
1590
1591
1592
1593
1594
1595









1596
1597
1598
1599

1600

1601
1602
1603



1604
1605
1606
1607


1608
1609
1610
1611
1612



1613
1614
1615
1616
1617
1618
1619
1620
1621








1622
1623
1624
1625
1626



1627
1628
1629

1630
1631
1632

1633
1634
1635

1636
1637
1638

1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651

1652
1653
1654

1655
1656
1657
1658


1659
1660
1661


1662
1663
1664
1665





1666
1667
1668
1669
1670
1671
1672
1567
1568
1569
1570
1571
1572
1573

1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584

1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596

1597
1598



1599
1600
1601
1602


1603
1604
1605
1606
1607


1608
1609
1610
1611
1612
1613
1614
1615





1616
1617
1618
1619
1620
1621
1622
1623






1624
1625
1626
1627
1628
1629

1630
1631
1632
1633









1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645

1646
1647
1648



1649
1650
1651
1652
1653


1654
1655
1656
1657



1658
1659
1660









1661
1662
1663
1664
1665
1666
1667
1668
1669
1670



1671
1672
1673
1674
1675

1676
1677
1678

1679
1680
1681

1682
1683
1684

1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697

1698
1699
1700

1701
1702
1703


1704
1705
1706


1707
1708
1709
1710


1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722







-
+







+
+
+
-
+







+
+
+
+
-
+

-
-
-
+
+
+
+
-
-
+




-
-
+
+






-
-
-
-
-
+
+
+
+
+



-
-
-
-
-
-
+
+
+
+
+
+
-



+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+



-
+

+
-
-
-
+
+
+


-
-
+
+


-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+


-
-
-
+
+
+


-
+


-
+


-
+


-
+












-
+


-
+


-
-
+
+

-
-
+
+


-
-
+
+
+
+
+







	mkdir -p RPMS/i386
	rpmbuild -bb THIS.TK.SPEC
	mv RPMS/i386/*.rpm .
	rm -rf RPMS THIS.TK.SPEC

#
# Target to create a proper Tk distribution from information in the
# master source directory.  DISTDIR must be defined to indicate where
# source directory.  DISTDIR must be defined to indicate where
# to put the distribution.  DISTDIR must be an absolute path name.
#

DISTROOT = /tmp/dist
DISTNAME = tk${VERSION}${PATCH_LEVEL}
ZIPNAME	 = tk${MAJOR_VERSION}${MINOR_VERSION}${PATCH_LEVEL}-src.zip
DISTDIR	 = $(DISTROOT)/$(DISTNAME)
DIST_INSTALL_DATA   = CPPROG='cp -p' $(INSTALL) -m 644
DIST_INSTALL_SCRIPT = CPPROG='cp -p' $(INSTALL) -m 755

$(UNIX_DIR)/configure: $(UNIX_DIR)/configure.in $(UNIX_DIR)/tcl.m4 \
$(UNIX_DIR)/configure: $(UNIX_DIR)/configure.ac $(UNIX_DIR)/tcl.m4 \
		$(UNIX_DIR)/aclocal.m4
	cd $(UNIX_DIR); autoconf
$(MAC_OSX_DIR)/configure: $(MAC_OSX_DIR)/configure.ac $(UNIX_DIR)/configure
	cd $(MAC_OSX_DIR); autoconf
$(UNIX_DIR)/tkConfig.h.in: $(MAC_OSX_DIR)/configure
	cd $(MAC_OSX_DIR); autoheader; touch $@

$(TOP_DIR)/manifest.uuid:
	printf "git." >$(TOP_DIR)/manifest.uuid
	git rev-parse HEAD >>$(TOP_DIR)/manifest.uuid

dist:   $(UNIX_DIR)/configure $(UNIX_DIR)/tkConfig.h.in $(UNIX_DIR)/tk.pc.in $(MAC_OSX_DIR)/configure $(TOP_DIR)/doc/man.macros genstubs
dist:	$(UNIX_DIR)/configure $(UNIX_DIR)/tkConfig.h.in $(UNIX_DIR)/tk.pc.in $(MAC_OSX_DIR)/configure $(TOP_DIR)/doc/man.macros $(TOP_DIR)/manifest.uuid
	rm -rf $(DISTDIR)
	mkdir -p $(DISTDIR)/unix
	cp -p $(UNIX_DIR)/*.c $(UNIX_DIR)/*.h $(DISTDIR)/unix
	cp $(TOP_DIR)/license.terms $(UNIX_DIR)/Makefile.in $(DISTDIR)/unix
	$(INSTALL_DATA_DIR) $(DISTDIR)/unix
	$(DIST_INSTALL_DATA) $(TOP_DIR)/manifest.uuid $(DISTDIR)
	$(DIST_INSTALL_DATA) $(UNIX_DIR)/*.c $(UNIX_DIR)/*.h $(DISTDIR)/unix
	$(DIST_INSTALL_DATA) $(TOP_DIR)/license.terms $(UNIX_DIR)/Makefile.in $(DISTDIR)/unix
	chmod 664 $(DISTDIR)/unix/Makefile.in
	cp $(UNIX_DIR)/configure $(UNIX_DIR)/configure.in $(UNIX_DIR)/tk.spec \
	$(DIST_INSTALL_DATA) $(UNIX_DIR)/configure.ac $(UNIX_DIR)/tk.spec \
		$(UNIX_DIR)/aclocal.m4 $(UNIX_DIR)/tcl.m4 \
		$(UNIX_DIR)/tkConfig.sh.in $(UNIX_DIR)/install-sh \
		$(UNIX_DIR)/README $(UNIX_DIR)/installManPage \
		$(UNIX_DIR)/tkConfig.h.in $(UNIX_DIR)/tk.pc.in $(DISTDIR)/unix
	chmod 775 $(DISTDIR)/unix/configure $(DISTDIR)/unix/configure.in
	mkdir $(DISTDIR)/bitmaps
	$(DIST_INSTALL_SCRIPT) $(UNIX_DIR)/configure $(DISTDIR)/unix
	$(INSTALL_DATA_DIR) $(DISTDIR)/bitmaps
	@(cd $(TOP_DIR); for i in bitmaps/* ; do \
	    if [ -f $$i ] ; then \
		sed -e 's/static char/static unsigned char/' \
		       $$i > $(DISTDIR)/$$i; \
	    fi; \
	done;)
	mkdir $(DISTDIR)/generic
	cp -p $(GENERIC_DIR)/*.[ch] $(DISTDIR)/generic
	cp -p $(GENERIC_DIR)/*.decls $(DISTDIR)/generic
	cp -p $(GENERIC_DIR)/README $(DISTDIR)/generic
	cp -p $(TOP_DIR)/changes $(TOP_DIR)/ChangeLog \
	$(INSTALL_DATA_DIR) $(DISTDIR)/generic
	$(DIST_INSTALL_DATA) $(GENERIC_DIR)/*.[ch] $(DISTDIR)/generic
	$(DIST_INSTALL_DATA) $(GENERIC_DIR)/*.decls $(DISTDIR)/generic
	$(DIST_INSTALL_DATA) $(GENERIC_DIR)/README $(DISTDIR)/generic
	$(DIST_INSTALL_DATA) $(TOP_DIR)/changes $(TOP_DIR)/ChangeLog \
		$(TOP_DIR)/ChangeLog.2??? $(TOP_DIR)/README.md \
		$(TOP_DIR)/license.terms $(DISTDIR)
	rm -f $(DISTDIR)/generic/blt*.[ch]
	mkdir $(DISTDIR)/generic/ttk
	cp -p $(TTK_DIR)/*.[ch] $(TTK_DIR)/ttk.decls \
		$(TTK_DIR)/ttkGenStubs.tcl $(DISTDIR)/generic/ttk
	mkdir $(DISTDIR)/win
	cp $(TOP_DIR)/win/Makefile.in $(DISTDIR)/win
	cp $(TOP_DIR)/win/configure.in \
	$(INSTALL_DATA_DIR) $(DISTDIR)/generic/ttk
	$(DIST_INSTALL_DATA) $(TTK_DIR)/*.[ch] $(TTK_DIR)/ttk.decls \
		$(DISTDIR)/generic/ttk
	$(INSTALL_DATA_DIR) $(DISTDIR)/win
	$(DIST_INSTALL_DATA) $(TOP_DIR)/win/Makefile.in $(DISTDIR)/win
	$(DIST_INSTALL_DATA) $(TOP_DIR)/win/configure.ac \
		$(TOP_DIR)/win/configure \
		$(TOP_DIR)/win/tkConfig.sh.in \
		$(TOP_DIR)/win/aclocal.m4 $(TOP_DIR)/win/tcl.m4 \
		$(DISTDIR)/win
	$(DIST_INSTALL_SCRIPT) $(TOP_DIR)/win/configure $(DISTDIR)/win
	cp -p $(TOP_DIR)/win/*.[ch] $(TOP_DIR)/win/*.bat $(DISTDIR)/win
	cp -p $(TOP_DIR)/win/*.vc $(DISTDIR)/win
	cp -p $(TOP_DIR)/win/README $(DISTDIR)/win
	cp -p $(TOP_DIR)/license.terms $(DISTDIR)/win
	mkdir $(DISTDIR)/win/rc
	cp -p $(TOP_DIR)/win/wish.exe.manifest.in $(DISTDIR)/win/
	cp -p $(TOP_DIR)/win/rc/*.{rc,cur,ico,bmp} $(DISTDIR)/win/rc
	mkdir $(DISTDIR)/macosx
	cp -p $(MAC_OSX_DIR)/GNUmakefile $(MAC_OSX_DIR)/README \
	$(DIST_INSTALL_DATA) $(TOP_DIR)/win/*.[ch] $(TOP_DIR)/win/*.bat $(DISTDIR)/win
	$(DIST_INSTALL_DATA) $(TOP_DIR)/win/*.vc $(DISTDIR)/win
	$(DIST_INSTALL_DATA) $(TOP_DIR)/win/README $(DISTDIR)/win
	$(DIST_INSTALL_DATA) $(TOP_DIR)/license.terms $(DISTDIR)/win
	$(INSTALL_DATA_DIR) $(DISTDIR)/win/rc
	$(DIST_INSTALL_DATA) $(TOP_DIR)/win/wish.exe.manifest.in $(DISTDIR)/win/
	$(DIST_INSTALL_DATA) $(TOP_DIR)/win/rc/*.{rc,cur,ico,bmp} $(DISTDIR)/win/rc
	$(INSTALL_DATA_DIR) $(DISTDIR)/macosx
	$(DIST_INSTALL_DATA) $(MAC_OSX_DIR)/GNUmakefile $(MAC_OSX_DIR)/README \
		$(MAC_OSX_DIR)/*.icns $(MAC_OSX_DIR)/*.tiff \
		$(MAC_OSX_DIR)/*.[ch] $(MAC_OSX_DIR)/*.in \
		$(MAC_OSX_DIR)/*.ac $(MAC_OSX_DIR)/*.xcconfig \
		$(MAC_OSX_DIR)/*.sdef $(MAC_OSX_DIR)/configure \
		$(MAC_OSX_DIR)/*.sdef \
		$(DISTDIR)/macosx
	$(DIST_INSTALL_SCRIPT) $(MAC_OSX_DIR)/configure $(DISTDIR)/macosx
	cp -p $(TOP_DIR)/license.terms $(DISTDIR)/macosx
	mkdir $(DISTDIR)/macosx/Tk.xcode
	cp -p $(MAC_OSX_DIR)/Tk.xcode/project.pbxproj \
	$(DIST_INSTALL_DATA) $(TOP_DIR)/license.terms $(DISTDIR)/macosx
	$(INSTALL_DATA_DIR) $(DISTDIR)/macosx/Tk.xcode
	$(DIST_INSTALL_DATA) $(MAC_OSX_DIR)/Tk.xcode/project.pbxproj \
		$(MAC_OSX_DIR)/Tk.xcode/default.pbxuser \
		$(DISTDIR)/macosx/Tk.xcode
	mkdir $(DISTDIR)/macosx/Tk.xcodeproj
	cp -p $(MAC_OSX_DIR)/Tk.xcodeproj/project.pbxproj \
	$(INSTALL_DATA_DIR) $(DISTDIR)/macosx/Tk.xcodeproj
	$(DIST_INSTALL_DATA) $(MAC_OSX_DIR)/Tk.xcodeproj/project.pbxproj \
		$(MAC_OSX_DIR)/Tk.xcodeproj/default.pbxuser \
		$(DISTDIR)/macosx/Tk.xcodeproj
	mkdir $(DISTDIR)/compat
	cp -p $(TOP_DIR)/license.terms $(TOP_DIR)/compat/unistd.h \
		$(TOP_DIR)/compat/stdlib.h \
	$(INSTALL_DATA_DIR) $(DISTDIR)/compat
	$(DIST_INSTALL_DATA) $(TOP_DIR)/license.terms $(TOP_DIR)/compat/stdint.h \
		$(TOP_DIR)/compat/stdbool.h $(DISTDIR)/compat
		$(DISTDIR)/compat
	mkdir $(DISTDIR)/xlib
	cp -p $(XLIB_DIR)/*.[ch] $(DISTDIR)/xlib
	cp -p $(TOP_DIR)/license.terms $(DISTDIR)/xlib
	mkdir $(DISTDIR)/xlib/X11
	cp -p $(XLIB_DIR)/X11/*.h $(DISTDIR)/xlib/X11
	cp -p $(TOP_DIR)/license.terms $(DISTDIR)/xlib/X11
	mkdir $(DISTDIR)/library
	cp -p $(TOP_DIR)/license.terms $(TOP_DIR)/library/*.tcl \
	$(INSTALL_DATA_DIR) $(DISTDIR)/xlib
	$(DIST_INSTALL_DATA) $(XLIB_DIR)/*.[ch] $(DISTDIR)/xlib
	$(DIST_INSTALL_DATA) $(TOP_DIR)/license.terms $(DISTDIR)/xlib
	$(INSTALL_DATA_DIR) $(DISTDIR)/xlib/X11
	$(DIST_INSTALL_DATA) $(XLIB_DIR)/X11/*.h $(DISTDIR)/xlib/X11
	$(DIST_INSTALL_DATA) $(TOP_DIR)/license.terms $(DISTDIR)/xlib/X11
	$(INSTALL_DATA_DIR) $(DISTDIR)/library
	$(DIST_INSTALL_DATA) $(TOP_DIR)/license.terms $(TOP_DIR)/library/*.tcl \
		$(TOP_DIR)/library/tclIndex \
		$(DISTDIR)/library
	mkdir $(DISTDIR)/library/ttk
	cp -p $(TOP_DIR)/library/ttk/*.tcl $(DISTDIR)/library/ttk
	mkdir $(DISTDIR)/library/images
	$(INSTALL_DATA_DIR) $(DISTDIR)/library/ttk
	$(DIST_INSTALL_DATA) $(TOP_DIR)/library/ttk/*.tcl $(DISTDIR)/library/ttk
	$(INSTALL_DATA_DIR) $(DISTDIR)/library/images
	@(cd $(TOP_DIR); for i in library/images/* ; do \
	    if [ -f $$i ] ; then \
		cp $$i $(DISTDIR)/$$i; \
		$(DIST_INSTALL_DATA) $$i $(DISTDIR)/$$i; \
	    fi; \
	done;)
	mkdir $(DISTDIR)/library/msgs
	$(INSTALL_DATA_DIR) $(DISTDIR)/library/msgs
	@(cd $(TOP_DIR); for i in library/msgs/*.msg ; do \
	    if [ -f $$i ] ; then \
		cp $$i $(DISTDIR)/$$i; \
		$(DIST_INSTALL_DATA) $$i $(DISTDIR)/$$i; \
	    fi; \
	done;)
	mkdir $(DISTDIR)/library/demos
	$(INSTALL_DATA_DIR) $(DISTDIR)/library/demos
	cp -pr $(TOP_DIR)/library/demos/*.tcl \
		$(TOP_DIR)/library/demos/*.msg \
		$(TOP_DIR)/library/demos/tclIndex \
		$(TOP_DIR)/library/demos/browse \
		$(TOP_DIR)/library/demos/hello $(TOP_DIR)/library/demos/ixset \
		$(TOP_DIR)/library/demos/rmt $(TOP_DIR)/library/demos/rolodex \
		$(TOP_DIR)/library/demos/square \
		$(TOP_DIR)/library/demos/tcolor \
		$(TOP_DIR)/library/demos/timer \
		$(TOP_DIR)/library/demos/widget \
		$(TOP_DIR)/library/demos/README \
		$(TOP_DIR)/license.terms $(DISTDIR)/library/demos
	mkdir $(DISTDIR)/library/demos/images
	$(INSTALL_DATA_DIR) $(DISTDIR)/library/demos/images
	@(cd $(TOP_DIR); for i in library/demos/images/* ; do \
	    if [ -f $$i ] ; then \
		cp $$i $(DISTDIR)/$$i; \
		$(DIST_INSTALL_DATA) $$i $(DISTDIR)/$$i; \
	    fi; \
	done;)
	mkdir $(DISTDIR)/doc
	cp -p $(TOP_DIR)/license.terms $(TOP_DIR)/doc/*.[13n] \
	$(INSTALL_DATA_DIR) $(DISTDIR)/doc
	$(DIST_INSTALL_DATA) $(TOP_DIR)/license.terms $(TOP_DIR)/doc/*.[13n] \
		$(TOP_DIR)/doc/man.macros $(DISTDIR)/doc
	mkdir $(DISTDIR)/tests
	cp -p $(TOP_DIR)/license.terms $(TEST_DIR)/*.{test,tcl} \
	$(INSTALL_DATA_DIR) $(DISTDIR)/tests
	$(DIST_INSTALL_DATA) $(TOP_DIR)/license.terms $(TEST_DIR)/*.{test,tcl} \
		$(TEST_DIR)/README $(TEST_DIR)/*.{gif,png,ppm,xbm} \
		$(TEST_DIR)/option.file* $(DISTDIR)/tests
	mkdir $(DISTDIR)/tests/ttk
	cp -p $(TEST_DIR)/ttk/*.{test,tcl} $(DISTDIR)/tests/ttk
	$(INSTALL_DATA_DIR) $(DISTDIR)/tests/ttk
	$(DIST_INSTALL_DATA) $(TEST_DIR)/ttk/*.{test,tcl} $(DISTDIR)/tests/ttk
	cp -p $(TOP_DIR)/.travis.yml $(DISTDIR)
	mkdir -p $(DISTDIR)/.github/workflows
	cp -p $(TOP_DIR)/.github/workflows/*.yml $(DISTDIR)/.github/workflows

alldist: dist
	rm -f $(DISTROOT)/$(DISTNAME)-src.tar.gz $(DISTROOT)/$(ZIPNAME)
	cd $(DISTROOT); tar cf $(DISTNAME)-src.tar $(DISTNAME); \
		gzip -9 $(DISTNAME)-src.tar; zip -qr8 $(ZIPNAME) $(DISTNAME)

#
Changes to unix/configure.

more than 10,000 changes

Added unix/configure.ac.






































































































































































































































































































































































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
! /bin/bash -norc
dnl	This file is an input file used by the GNU "autoconf" program to
dnl	generate the file "configure", which is run during Tk installation
dnl	to configure the system for the local environment.

AC_INIT([tk],[8.7])
AC_PREREQ([2.69])

dnl This is only used when included from macosx/configure.ac
m4_ifdef([SC_USE_CONFIG_HEADERS], [
    AC_CONFIG_HEADERS([tkConfig.h:../unix/tkConfig.h.in])
    AC_CONFIG_COMMANDS_PRE([DEFS="-DHAVE_TK_CONFIG_H  -imacros tkConfig.h"])
    AH_TOP([
    #ifndef _TKCONFIG
    #define _TKCONFIG])
    AH_BOTTOM([
    /* Undef unused package specific autoheader defines so that we can
     * include both tclConfig.h and tkConfig.h at the same time: */
    /* override */ #undef PACKAGE_NAME
    /* override */ #undef PACKAGE_STRING
    /* override */ #undef PACKAGE_TARNAME
    #endif /* _TKCONFIG */])
])

TK_VERSION=8.7
TK_MAJOR_VERSION=8
TK_MINOR_VERSION=7
TK_PATCH_LEVEL="a4"
VERSION=${TK_VERSION}
LOCALES="cs da de el en en_gb eo es fr hu it nl pl pt ru sv"

#--------------------------------------------------------------------
# Find and load the tclConfig.sh file
#--------------------------------------------------------------------

SC_PATH_TCLCONFIG
SC_LOAD_TCLCONFIG

if test "${TCL_MAJOR_VERSION}" -lt 9 ; then
if test "${TCL_MAJOR_VERSION}" -ne 8 ; then
    AC_MSG_ERROR([${PACKAGE_NAME} ${PACKAGE_VERSION} requires Tcl 8.6+
Found config for Tcl ${TCL_VERSION}])
fi
if test "${TCL_MINOR_VERSION}" -lt 6 ; then
    AC_MSG_ERROR([${PACKAGE_NAME} ${PACKAGE_VERSION} requires Tcl 8.6+
Found config for Tcl ${TCL_VERSION}])
fi
fi

SC_PROG_TCLSH
SC_BUILD_TCLSH

#------------------------------------------------------------------------
# Handle the --prefix=... option
#------------------------------------------------------------------------

if test "${prefix}" = "NONE"; then
    prefix="$TCL_PREFIX"
fi
if test "${exec_prefix}" = "NONE"; then
    exec_prefix=$prefix
fi
# Make sure srcdir is fully qualified!
srcdir="`cd "$srcdir" ; pwd`"
TK_SRC_DIR="`cd "$srcdir"/..; pwd`"

#------------------------------------------------------------------------
# Compress and/or soft link the manpages?
#------------------------------------------------------------------------

SC_CONFIG_MANPAGES

#------------------------------------------------------------------------
# Standard compiler checks
#------------------------------------------------------------------------

# If the user did not set CFLAGS, set it now to keep
# the AC_PROG_CC macro from adding "-g -O2".
if test "${CFLAGS+set}" != "set" ; then
    CFLAGS=""
fi

AC_PROG_CC
AC_C_INLINE

#------------------------------------------------------------------------
# If we're using GCC, see if the compiler understands -pipe.  If so, use it.
# It makes compiling go faster.  (This is only a performance feature.)
#------------------------------------------------------------------------

if test -z "$no_pipe" && test -n "$GCC"; then
    AC_CACHE_CHECK([if the compiler understands -pipe],
	tcl_cv_cc_pipe, [
	hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -pipe"
	AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],[tcl_cv_cc_pipe=yes],[tcl_cv_cc_pipe=no])
	CFLAGS=$hold_cflags])
    if test $tcl_cv_cc_pipe = yes; then
	CFLAGS="$CFLAGS -pipe"
    fi
fi

#------------------------------------------------------------------------
# Embedded configuration information, encoding to use for the values, TIP #59
#------------------------------------------------------------------------

SC_TCL_CFG_ENCODING

SC_ENABLE_SHARED

#--------------------------------------------------------------------
# The statements below define a collection of compile flags.  This
# macro depends on the value of SHARED_BUILD, and should be called
# after SC_ENABLE_SHARED checks the configure switches.
#--------------------------------------------------------------------

SC_CONFIG_CFLAGS

SC_ENABLE_SYMBOLS

#--------------------------------------------------------------------
#	Detect what compiler flags to set for 64-bit support.
#--------------------------------------------------------------------

SC_TCL_EARLY_FLAGS

SC_TCL_64BIT_FLAGS

#--------------------------------------------------------------------
#	Check endianness because we can optimize some operations
#--------------------------------------------------------------------

AC_C_BIGENDIAN

#------------------------------------------------------------------------
# If Tcl and Tk are installed in different places, adjust the library
# search path to reflect this.
#------------------------------------------------------------------------

LIB_RUNTIME_DIR='$(libdir)'

if test "$TCL_EXEC_PREFIX" != "$exec_prefix"; then
    LIB_RUNTIME_DIR="${LIB_RUNTIME_DIR}:${TCL_EXEC_PREFIX}/lib"
fi

if test "$TCL_PREFIX" != "$prefix"; then
    AC_MSG_WARN([
        Different --prefix selected for Tk and Tcl!
        [[package require tk]] may not work correctly in tclsh.])
fi

#--------------------------------------------------------------------
#	Include sys/select.h if it exists and if it supplies things
#	that appear to be useful and aren't already in sys/types.h.
#	This appears to be true only on the RS/6000 under AIX.  Some
#	systems like OSF/1 have a sys/select.h that's of no use, and
#	other systems like SCO UNIX have a sys/select.h that's
#	pernicious.  If "fd_set" isn't defined anywhere then set a
#	special flag.
#--------------------------------------------------------------------

AC_CACHE_CHECK([for fd_set in sys/types], tcl_cv_type_fd_set, [
    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>]], [[fd_set readMask, writeMask;]])],[tcl_cv_type_fd_set=yes],[tcl_cv_type_fd_set=no])])
tk_ok=$tcl_cv_type_fd_set
if test $tk_ok = no; then
    AC_CACHE_CHECK([for fd_mask in sys/select], tcl_cv_grep_fd_mask, [
	AC_EGREP_HEADER(fd_mask, sys/select.h,
	     tcl_cv_grep_fd_mask=present, tcl_cv_grep_fd_mask=missing)])
    if test $tcl_cv_grep_fd_mask = present; then
	AC_DEFINE(HAVE_SYS_SELECT_H, 1, [Should we include <sys/select.h>?])
	tk_ok=yes
    fi
fi
if test $tk_ok = no; then
    AC_DEFINE(NO_FD_SET, 1, [Do we have fd_set?])
fi

#------------------------------------------------------------------------------
#       Find out all about time handling differences.
#------------------------------------------------------------------------------

AC_CHECK_HEADERS(sys/time.h)
m4_warn([obsolete],
[Update your code to rely only on HAVE_SYS_TIME_H,
then remove this warning and the obsolete code below it.
All current systems provide time.h; it need not be checked for.
Not all systems provide sys/time.h, but those that do, all allow
you to include it and time.h simultaneously.])dnl
AC_CHECK_HEADERS_ONCE([sys/time.h])
# Obsolete code to be removed.
if test $ac_cv_header_sys_time_h = yes; then
  AC_DEFINE([TIME_WITH_SYS_TIME],[1],[Define to 1 if you can safely include both <sys/time.h>
	     and <time.h>.  This macro is obsolete.])
fi
# End of obsolete code.


#--------------------------------------------------------------------
#	Check for various typedefs and provide substitutes if
#	they don't exist.
#--------------------------------------------------------------------

AC_TYPE_MODE_T
AC_TYPE_PID_T
AC_TYPE_SIZE_T

AC_CHECK_TYPES([intptr_t, uintptr_t],,,[[
#include <stdint.h>
]])

#-------------------------------------------
#     In OS/390 struct pwd has no pw_gecos field
#-------------------------------------------

AC_CACHE_CHECK([pw_gecos in struct pwd], tcl_cv_pwd_pw_gecos, [
    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <pwd.h>]], [[struct passwd pwd; (void)pwd.pw_gecos;]])],[tcl_cv_pwd_pw_gecos=yes],[tcl_cv_pwd_pw_gecos=no])])
if test $tcl_cv_pwd_pw_gecos = yes; then
    AC_DEFINE(HAVE_PW_GECOS, 1, [Does struct password have a pw_gecos field?])
fi

#--------------------------------------------------------------------
#	On Mac OS X, we can build either with X11 or with Aqua
#--------------------------------------------------------------------

if test "`uname -s`" = "Darwin" ; then
    AC_MSG_CHECKING([whether to use Aqua])
    AC_ARG_ENABLE(aqua,
	AS_HELP_STRING([--enable-aqua=yes|no],[use Aqua windowingsystem on Mac OS X (default: no)]),
	[tk_aqua=$enableval], [tk_aqua=no])
    if test $tk_aqua = yes -o $tk_aqua = cocoa; then
	tk_aqua=yes
	if test $tcl_corefoundation = no; then
	    AC_MSG_WARN([Aqua can only be used when CoreFoundation is available])
	    tk_aqua=no
	fi
	if test ! -d /System/Library/Frameworks/Cocoa.framework; then
	    AC_MSG_WARN([Aqua can only be used when Cocoa is available])
	    tk_aqua=no
	fi
	if test "`uname -r | awk -F. '{print [$]1}'`" -lt 9; then
	    AC_MSG_WARN([Aqua requires Mac OS X 10.5 or later])
	    tk_aqua=no
	fi
    fi
    AC_MSG_RESULT([$tk_aqua])
    if test "$fat_32_64" = yes; then
	if test $tk_aqua = no; then
	    AC_CACHE_CHECK([for 64-bit X11], tcl_cv_lib_x11_64, [
		for v in CFLAGS CPPFLAGS LDFLAGS; do
		    eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"'
		done
		CPPFLAGS="$CPPFLAGS -I/usr/X11R6/include"
		LDFLAGS="$LDFLAGS -L/usr/X11R6/lib -lX11"
		AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <X11/Xlib.h>]], [[XrmInitialize();]])],[tcl_cv_lib_x11_64=yes],[tcl_cv_lib_x11_64=no])
		for v in CFLAGS CPPFLAGS LDFLAGS; do
		    eval $v'="$hold_'$v'"'
		done])
	fi
	# remove 64-bit arch flags from CFLAGS et al. for combined 32 & 64 bit
	# fat builds if configuration does not support 64-bit.
	if test "$tcl_cv_lib_x11_64" = no; then
	    AC_MSG_NOTICE([Removing 64-bit architectures from compiler & linker flags])
	    for v in CFLAGS CPPFLAGS LDFLAGS; do
		eval $v'="`echo "$'$v' "|sed -e "s/-arch ppc64 / /g" -e "s/-arch x86_64 / /g"`"'
	    done
	fi
    fi
    if test $tk_aqua = no; then
	# check if weak linking whole libraries is possible.
	AC_CACHE_CHECK([if ld accepts -weak-l flag], tcl_cv_ld_weak_l, [
	    hold_ldflags=$LDFLAGS
	    LDFLAGS="$LDFLAGS -Wl,-weak-lm"
	    AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <math.h>]], [[double f = sin(1.0);]])],[tcl_cv_ld_weak_l=yes],[tcl_cv_ld_weak_l=no])
	    LDFLAGS=$hold_ldflags])
    fi
    AC_CHECK_HEADERS(AvailabilityMacros.h)
    if test "$ac_cv_header_AvailabilityMacros_h" = yes; then
	AC_CACHE_CHECK([if weak import is available], tcl_cv_cc_weak_import, [
	    hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror"
	    AC_LINK_IFELSE([AC_LANG_PROGRAM([[
		    #ifdef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
		    #if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1020
		    #error __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1020
		    #endif
		    #elif MAC_OS_X_VERSION_MIN_REQUIRED < 1020
		    #error MAC_OS_X_VERSION_MIN_REQUIRED < 1020
		    #endif
		    int rand(void) __attribute__((weak_import));
		]], [[rand();]])],[tcl_cv_cc_weak_import=yes],[tcl_cv_cc_weak_import=no])
	    CFLAGS=$hold_cflags])
	if test $tcl_cv_cc_weak_import = yes; then
	    AC_DEFINE(HAVE_WEAK_IMPORT, 1, [Is weak import available?])
	fi
	AC_CACHE_CHECK([if Darwin SUSv3 extensions are available],
	    tcl_cv_cc_darwin_c_source, [
	    hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror"
	    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
		    #ifdef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
		    #if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1050
		    #error __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1050
		    #endif
		    #elif MAC_OS_X_VERSION_MIN_REQUIRED < 1050
		    #error MAC_OS_X_VERSION_MIN_REQUIRED < 1050
		    #endif
		    #define _DARWIN_C_SOURCE 1
		    #include <sys/cdefs.h>
		]], [[]])],[tcl_cv_cc_darwin_c_source=yes],[tcl_cv_cc_darwin_c_source=no])
	    CFLAGS=$hold_cflags])
	if test $tcl_cv_cc_darwin_c_source = yes; then
	    AC_DEFINE(_DARWIN_C_SOURCE, 1,
		    [Are Darwin SUSv3 extensions available?])
	fi
    fi
else
    tk_aqua=no
fi

if test $tk_aqua = yes; then
    AC_DEFINE(MAC_OSX_TK, 1, [Are we building TkAqua?])
    LIBS="$LIBS -framework Cocoa -framework Carbon -framework IOKit -framework Security"
    if test -d /System/Library/Frameworks/UserNotifications.framework; then
        LIBS="$LIBS -framework UserNotifications"
    fi
    EXTRA_CC_SWITCHES='-std=gnu99 -x objective-c'
    TK_WINDOWINGSYSTEM=AQUA
    if test -n "${enable_symbols}" -a "${enable_symbols}" != no; then
        AC_DEFINE(TK_MAC_DEBUG, 1, [Are TkAqua debug messages enabled?])
    fi
else
    #--------------------------------------------------------------------
    #	Locate the X11 header files and the X11 library archive.  Try
    #	the ac_path_x macro first, but if it doesn't find the X stuff
    #	(e.g. because there's no xmkmf program) then check through
    #	a list of possible directories.  Under some conditions the
    #	autoconf macro will return an include directory that contains
    #	no include files, so double-check its result just to be safe.
    #--------------------------------------------------------------------

    SC_PATH_X
    TK_WINDOWINGSYSTEM=X11
fi

#--------------------------------------------------------------------
#	Various manipulations on the search path used at runtime to
#	find shared libraries:
#	1. If the X library binaries are in a non-standard directory,
#	   add the X library location into that search path.
#	2. On systems such as AIX and Ultrix that use "-L" as the
#	   search path option, colons cannot be used to separate
#	   directories from each other. Change colons to " -L".
#	3. Create two sets of search flags, one for use in cc lines
#	   and the other for when the linker is invoked directly.  In
#	   the second case, '-Wl,' must be stripped off and commas must
#	   be replaced by spaces.
#--------------------------------------------------------------------

if test "x${x_libraries}" != "x"; then
  if test "x${x_libraries}" != "xNONE"; then
    LIB_RUNTIME_DIR="${LIB_RUNTIME_DIR}:${x_libraries}"
  fi
fi
if test "${TCL_LD_SEARCH_FLAGS}" = '-L${LIB_RUNTIME_DIR}'; then
    LIB_RUNTIME_DIR=`echo ${LIB_RUNTIME_DIR} |sed -e 's/:/ -L/g'`
fi

#--------------------------------------------------------------------
#	Check for the existence of various libraries.  The order here
#	is important, so that then end up in the right order in the
#	command line generated by make.  The -lsocket and -lnsl libraries
#	require a couple of special tricks:
#	1. Use "connect" and "accept" to check for -lsocket, and
#	   "gethostbyname" to check for -lnsl.
#	2. Use each function name only once:  can't redo a check because
#	   autoconf caches the results of the last check and won't redo it.
#	3. Use -lnsl and -lsocket only if they supply procedures that
#	   aren't already present in the normal libraries.  This is because
#	   IRIX 5.2 has libraries, but they aren't needed and they're
#	   bogus:  they goof up name resolution if used.
#	4. On some SVR4 systems, can't use -lsocket without -lnsl too.
#	   To get around this problem, check for both libraries together
#	   if -lsocket doesn't work by itself.
#--------------------------------------------------------------------

if test $tk_aqua = no; then
    AC_CHECK_LIB(Xbsd, main, [LIBS="$LIBS -lXbsd"])
fi

#--------------------------------------------------------------------
# One more check related to the X libraries.  The standard releases
# of Ultrix don't support the "xauth" mechanism, so send won't work
# unless TK_NO_SECURITY is defined.  However, there are usually copies
# of the MIT X server available as well, which do support xauth.
# Check for the MIT stuff and use it if it exists.
#
# Note: can't use ac_check_lib macro (at least, not in Autoconf 2.1)
# because it can't deal with the "-" in the library name.
#--------------------------------------------------------------------

if test -d /usr/include/mit -a $tk_aqua = no; then
    AC_MSG_CHECKING([MIT X libraries])
    tk_oldCFlags=$CFLAGS
    CFLAGS="$CFLAGS -I/usr/include/mit"
    tk_oldLibs=$LIBS
    LIBS="$LIBS -lX11-mit"
    AC_LINK_IFELSE([AC_LANG_PROGRAM([[
	#include <X11/Xlib.h>
    ]], [[
	XOpenDisplay(0);
    ]])],[
	AC_MSG_RESULT([yes])
	XLIBSW="-lX11-mit"
	XINCLUDES="-I/usr/include/mit"
    ],[AC_MSG_RESULT(no)])
    CFLAGS=$tk_oldCFlags
    LIBS=$tk_oldLibs
fi

#--------------------------------------------------------------------
#	Check for freetype / fontconfig / Xft support.
#--------------------------------------------------------------------

if test $tk_aqua = no; then
    AC_MSG_CHECKING([whether to use xft])
    AC_ARG_ENABLE(xft,
	AS_HELP_STRING([--enable-xft],[use freetype/fontconfig/xft (default: on)]),
	[enable_xft=$enableval], [enable_xft="default"])
    XFT_CFLAGS=""
    XFT_LIBS=""
    if test "$enable_xft" = "no" ; then
	AC_MSG_RESULT([$enable_xft])
    else
	found_xft="yes"
	dnl make sure package configurator (xft-config or pkg-config
	dnl says that xft is present.
	XFT_CFLAGS=`xft-config --cflags 2>/dev/null` || found_xft="no"
	XFT_LIBS=`xft-config --libs 2>/dev/null` || found_xft="no"
	if test "$found_xft" = "no" ; then
	    found_xft=yes
	    XFT_CFLAGS=`pkg-config --cflags xft fontconfig 2>/dev/null` || found_xft="no"
	    XFT_LIBS=`pkg-config --libs xft fontconfig 2>/dev/null` || found_xft="no"
	fi
	AC_MSG_RESULT([$found_xft])
	dnl make sure that compiling against Xft header file doesn't bomb
	if test "$found_xft" = "yes" ; then
	    tk_oldCFlags=$CFLAGS
	    CFLAGS="$CFLAGS $XINCLUDES $XFT_CFLAGS"
	    tk_oldLibs=$LIBS
	    LIBS="$tk_oldLIBS $XFT_LIBS $XLIBSW"
	    AC_CHECK_HEADER(X11/Xft/Xft.h, [], [
		found_xft=no
	    ],[#include <X11/Xlib.h>])
	    CFLAGS=$tk_oldCFlags
	    LIBS=$tk_oldLibs
	fi
	dnl make sure that linking against Xft libraries finds freetype
	if test "$found_xft" = "yes" ; then
	    tk_oldCFlags=$CFLAGS
	    CFLAGS="$CFLAGS $XINCLUDES $XFT_CFLAGS"
	    tk_oldLibs=$LIBS
	    LIBS="$tk_oldLIBS $XFT_LIBS $XLIBSW"
	    AC_CHECK_LIB(Xft, XftFontOpen, [], [
		found_xft=no
	    ])
	    CFLAGS=$tk_oldCFlags
	    LIBS=$tk_oldLibs
	fi
	dnl make sure that linking against fontconfig libraries finds Fc* symbols
	if test "$found_xft" = "yes" ; then
	    tk_oldCFlags=$CFLAGS
	    CFLAGS="$CFLAGS $XINCLUDES $XFT_CFLAGS"
	    tk_oldLibs=$LIBS
	    LIBS="$tk_oldLIBS $XFT_LIBS $XLIBSW -lfontconfig"
	    AC_CHECK_LIB(fontconfig, FcFontSort, [
		XFT_LIBS="$XFT_LIBS -lfontconfig"
	    ], [])
	    CFLAGS=$tk_oldCFlags
	    LIBS=$tk_oldLibs
	fi
	dnl print a warning if xft is unusable and was specifically requested
	if test "$found_xft" = "no" ; then
	    if test "$enable_xft" = "yes" ; then
		AC_MSG_WARN([Can't find xft configuration, or xft is unusable])
	    fi
	    enable_xft=no
	    XFT_CFLAGS=""
	    XFT_LIBS=""
	else
            enable_xft=yes
	fi
    fi
    if test $enable_xft = "yes" ; then
	UNIX_FONT_OBJS=tkUnixRFont.o
	AC_DEFINE(HAVE_XFT, 1, [Have we turned on XFT (antialiased fonts)?])
    else
	UNIX_FONT_OBJS=tkUnixFont.o
    fi
    AC_SUBST(XFT_CFLAGS)
    AC_SUBST(XFT_LIBS)
    AC_SUBST(UNIX_FONT_OBJS)
fi

#--------------------------------------------------------------------
# XXX Do this last.
# It might modify XLIBSW which could affect other tests.
#
# Check whether the header and library for the XScreenSaver
# extension are available, and set HAVE_XSS if so.
# XScreenSaver is needed for Tk_GetUserInactiveTime().
#--------------------------------------------------------------------

if test $tk_aqua = no; then
    tk_oldCFlags=$CFLAGS
    CFLAGS="$CFLAGS $XINCLUDES"
    tk_oldLibs=$LIBS
    LIBS="$tk_oldLibs $XLIBSW"
    xss_header_found=no
    xss_lib_found=no
    AC_MSG_CHECKING([whether to try to use XScreenSaver])
    AC_ARG_ENABLE(xss,
	AS_HELP_STRING([--enable-xss],[use XScreenSaver for activity timer (default: on)]),
	[enable_xss=$enableval], [enable_xss=yes])
    if test "$enable_xss" = "no" ; then
	AC_MSG_RESULT([$enable_xss])
    else
	AC_MSG_RESULT([$enable_xss])
	AC_CHECK_HEADER(X11/extensions/scrnsaver.h, [
	    xss_header_found=yes
	],,[#include <X11/Xlib.h>])
	AC_CHECK_FUNC(XScreenSaverQueryInfo,,[
	    AC_CHECK_LIB(Xext, XScreenSaverQueryInfo, [
		XLIBSW="$XLIBSW -lXext"
		xss_lib_found=yes
	    ], [
		AC_CHECK_LIB(Xss, XScreenSaverQueryInfo, [
		    if test "$tcl_cv_ld_weak_l" = yes; then
			# On Darwin, weak link libXss if possible,
			# as it is only available on Tiger or later.
			XLIBSW="$XLIBSW -Wl,-weak-lXss -lXext"
		    else
			XLIBSW="$XLIBSW -lXss -lXext"
		    fi
		    xss_lib_found=yes
		],, -lXext)
	    ])
	])
    fi
    if test $enable_xss = yes -a $xss_lib_found = yes -a $xss_header_found = yes; then
	AC_DEFINE(HAVE_XSS, 1, [Is XScreenSaver available?])
    fi
    CFLAGS=$tk_oldCFlags
    LIBS=$tk_oldLibs
fi

#--------------------------------------------------------------------
#	Figure out whether "char" is unsigned.  If so, set a
#	#define for __CHAR_UNSIGNED__.
#--------------------------------------------------------------------

AC_C_CHAR_UNSIGNED

#--------------------------------------------------------------------
#	The statements below define a collection of symbols related to
#	building libtk as a shared library instead of a static library.
#--------------------------------------------------------------------

eval eval "TK_UNSHARED_LIB_SUFFIX=${UNSHARED_LIB_SUFFIX}"
eval eval "TK_SHARED_LIB_SUFFIX=${SHARED_LIB_SUFFIX}"
eval "TK_LIB_FILE=libtk${LIB_SUFFIX}"

# tkConfig.sh needs a version of the _LIB_SUFFIX that has been eval'ed
# since on some platforms TK_LIB_FILE contains shell escapes.

eval "TK_LIB_FILE=${TK_LIB_FILE}"

if test "${SHARED_BUILD}" = "1" -a "${SHLIB_SUFFIX}" != ""; then
    SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \${TCL_STUB_LIB_SPEC}"
    TCL_STUB_FLAGS="-DUSE_TCL_STUBS"
fi

test -z "$TK_LIBRARY" && TK_LIBRARY='$(prefix)/lib/tk$(VERSION)'
PRIVATE_INCLUDE_DIR='$(includedir)'
HTML_DIR='$(DISTDIR)/html'
TK_PKG_DIR='tk$(VERSION)'
TK_RSRC_FILE='tk$(VERSION).rsrc'
WISH_RSRC_FILE='wish$(VERSION).rsrc'

# Note:  in the following variable, it's important to use the absolute
# path name of the Tcl directory rather than "..":  this is because
# AIX remembers this path and will attempt to use it at run-time to look
# up the Tcl library.

if test "`uname -s`" = "Darwin" ; then
    SC_ENABLE_FRAMEWORK
    TK_SHLIB_LD_EXTRAS="-compatibility_version ${TK_VERSION} -current_version ${TK_VERSION}`echo ${TK_PATCH_LEVEL} | awk ['{match($0, "\\\.[0-9]+"); print substr($0,RSTART,RLENGTH)}']`"
    TK_SHLIB_LD_EXTRAS="${TK_SHLIB_LD_EXTRAS}"' -install_name "${DYLIB_INSTALL_DIR}/${TK_LIB_FILE}" -unexported_symbols_list $$(f=$(TK_LIB_FILE).E && nm -gp tkMacOSX*.o 2>/dev/null | awk "/^[[0-9a-f]]+ . \.objc/ {print \$$3}" > $$f && nm -gjp "$(TCL_BIN_DIR)"/$(TCL_STUB_LIB_FILE) | grep ^_[[^_]] >> $$f && echo $$f)'
    echo "$LDFLAGS " | grep -q -- '-prebind ' && TK_SHLIB_LD_EXTRAS="${TK_SHLIB_LD_EXTRAS}"' -seg1addr 0xb000000'
    TK_SHLIB_LD_EXTRAS="${TK_SHLIB_LD_EXTRAS}"' -sectcreate __TEXT __info_plist Tk-Info.plist'
    EXTRA_WISH_LIBS='-sectcreate __TEXT __info_plist Wish-Info.plist'
    EXTRA_WISH_LIBS=${EXTRA_WISH_LIBS}' -sectcreate __TEXT __credits_html Credits.html'
    EXTRA_APP_CC_SWITCHES="${EXTRA_APP_CC_SWITCHES}"' -mdynamic-no-pic'
    AC_CONFIG_FILES([Tk-Info.plist:../macosx/Tk-Info.plist.in Wish-Info.plist:../macosx/Wish-Info.plist.in Credits.html:../macosx/Credits.html.in])
    for l in ${LOCALES}; do CFBUNDLELOCALIZATIONS="${CFBUNDLELOCALIZATIONS}<string>$l</string>"; done
    TK_YEAR="`date +%Y`"
fi

if test "$FRAMEWORK_BUILD" = "1" ; then
    AC_DEFINE(TK_FRAMEWORK, 1, [Is Tk built as a framework?])
    # Construct a fake local framework structure to make linking with
    # '-framework Tk' and running of tktest work
    AC_CONFIG_COMMANDS([Tk.framework], [n=Tk &&
        f=$n.framework && v=Versions/$VERSION &&
        rm -rf $f && mkdir -p $f/$v/Resources &&
        ln -s $v/$n $v/Resources $f && ln -s ../../../$n $f/$v &&
        ln -s ../../../../$n-Info.plist $f/$v/Resources/Info.plist &&
        if test $tk_aqua = yes; then ln -s ../../../../$n.rsrc $f/$v/Resources; fi &&
        unset n f v
    ], VERSION=${TK_VERSION} && tk_aqua=${tk_aqua})
    LD_LIBRARY_PATH_VAR="DYLD_FRAMEWORK_PATH"
    if test "${libdir}" = '${exec_prefix}/lib'; then
        # override libdir default
        libdir="/Library/Frameworks"
    fi
    TK_LIB_FILE="Tk"
    TK_LIB_FLAG="-framework Tk"
    TK_BUILD_LIB_SPEC="-F`pwd | sed -e 's/ /\\\\ /g'` -framework Tk"
    TK_LIB_SPEC="-F${libdir} -framework Tk"
    libdir="${libdir}/Tk.framework/Versions/\${VERSION}"
    TK_LIBRARY="${libdir}/Resources/Scripts"
    TK_PKG_DIR="Resources/Scripts"
    TK_RSRC_FILE="Tk.rsrc"
    WISH_RSRC_FILE="Wish.rsrc"
    includedir="${libdir}/Headers"
    PRIVATE_INCLUDE_DIR="${libdir}/PrivateHeaders"
    HTML_DIR="${libdir}/Resources/Documentation/Reference/Tk"
    EXTRA_INSTALL="install-private-headers html-tk"
    EXTRA_BUILD_HTML='@ln -fs contents.htm "$(HTML_INSTALL_DIR)"/TkTOC.html'
    EXTRA_INSTALL_BINARIES='@echo "Installing Info.plist to $(LIB_INSTALL_DIR)/Resources/" && $(INSTALL_DATA_DIR) "$(LIB_INSTALL_DIR)/Resources" && $(INSTALL_DATA) Tk-Info.plist "$(LIB_INSTALL_DIR)/Resources/Info.plist"'
    EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Installing Credits.html to $(LIB_INSTALL_DIR)/Resources/" && $(INSTALL_DATA_DIR) "$(LIB_INSTALL_DIR)/Resources" && $(INSTALL_DATA) Credits.html "$(LIB_INSTALL_DIR)/Resources"'
    EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Installing license.terms to $(LIB_INSTALL_DIR)/Resources/" && $(INSTALL_DATA) "$(TOP_DIR)/license.terms" "$(LIB_INSTALL_DIR)/Resources"'
    if test $tk_aqua = yes; then
	EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Installing Images to $(LIB_INSTALL_DIR)/Resources/" && $(INSTALL_DATA_DIR) "$(LIB_INSTALL_DIR)/Resources" && for i in Tk.tiff Tk.icns; do $(INSTALL_DATA) "$(MAC_OSX_DIR)/$$i" "$(LIB_INSTALL_DIR)/Resources"; done'
	EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Installing wish$(VERSION) script to $(INSTALL_ROOT)/'"${bindir}"'/" && $(INSTALL_DATA_DIR) "$(INSTALL_ROOT)/'"${bindir}"'" && printf > "$(INSTALL_ROOT)/'"${bindir}"'/wish$(VERSION)" "#!/bin/sh\n\"\$$(dirname \$$0)'"`eval d="${bindir}"; echo "$d" | sed -e 's#/[^/][^/]*#/..#g'`"'$(bindir)/Wish\" \"\$$@\"" && chmod +x "$(INSTALL_ROOT)/'"${bindir}"'/wish$(VERSION)"'
	bindir="${libdir}/Resources/Wish.app/Contents/MacOS"
	EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Installing Info.plist to $(BIN_INSTALL_DIR)/.." && $(INSTALL_DATA) Wish-Info.plist "$(BIN_INSTALL_DIR)/../Info.plist" && mv -f "$(BIN_INSTALL_DIR)/wish$(VERSION)" "$(BIN_INSTALL_DIR)/Wish"'
	EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Installing Wish.icns to $(BIN_INSTALL_DIR)/../Resources" && $(INSTALL_DATA_DIR) "$(BIN_INSTALL_DIR)/../Resources"'
	EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && $(INSTALL_DATA) "$(MAC_OSX_DIR)/Tk.icns" "$(BIN_INSTALL_DIR)/../Resources/Wish.icns"'
	EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Installing Wish.sdef to $(BIN_INSTALL_DIR)/../Resources" && $(INSTALL_DATA) "$(MAC_OSX_DIR)/Wish.sdef" "$(BIN_INSTALL_DIR)/../Resources"'
	EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Installing Credits.html to $(BIN_INSTALL_DIR)/../Resources" && $(INSTALL_DATA) Credits.html "$(BIN_INSTALL_DIR)/../Resources"'
    fi
    EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Finalizing Tk.framework" && rm -f "$(LIB_INSTALL_DIR)/../Current" && ln -s "$(VERSION)" "$(LIB_INSTALL_DIR)/../Current" && for f in "$(LIB_FILE)" tkConfig.sh Resources Headers PrivateHeaders; do rm -f "$(LIB_INSTALL_DIR)/../../$$f" && ln -s "Versions/Current/$$f" "$(LIB_INSTALL_DIR)/../.."; done && f="$(STUB_LIB_FILE)" && rm -f "$(LIB_INSTALL_DIR)/../../$$f" && ln -s "Versions/$(VERSION)/$$f" "$(LIB_INSTALL_DIR)/../.."'
    # Don't use AC_DEFINE for the following as the framework version define
    # needs to go into the Makefile even when using autoheader, so that we
    # can pick up a potential make override of VERSION. Also, don't put this
    # into CFLAGS as it should not go into tkConfig.sh
    EXTRA_CC_SWITCHES="$EXTRA_CC_SWITCHES"' -DTK_FRAMEWORK_VERSION=\"$(VERSION)\"'
else
    if test $tk_aqua = yes; then
        EXTRA_INSTALL_BINARIES='@echo "Installing Images to $(LIB_INSTALL_DIR)/" && $(INSTALL_DATA_DIR) "$(LIB_INSTALL_DIR)" && for i in Tk.tiff Tk.icns; do $(INSTALL_DATA) "$(MAC_OSX_DIR)/$$i" "$(LIB_INSTALL_DIR)"; done'
    fi
    # libdir must be a fully qualified path and not ${exec_prefix}/lib
    eval libdir="$libdir"
    if test "${ac_cv_cygwin}" = "yes" -a "$SHARED_BUILD" = "1"; then
	TK_LIB_FLAG="-ltk`echo ${TK_VERSION} | tr -d .`"
	TK_BUILD_LIB_SPEC="-L\$(TOP_DIR)/win ${TK_LIB_FLAG}"
    else
	if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then
	    TK_LIB_FLAG="-ltk${TK_VERSION}"
	else
	    TK_LIB_FLAG="-ltk`echo ${TK_VERSION} | tr -d .`"
	fi
	TK_BUILD_LIB_SPEC="-L`pwd | sed -e 's/ /\\\\ /g'` ${TK_LIB_FLAG}"
    fi
    TK_LIB_SPEC="-L${libdir} ${TK_LIB_FLAG}"
fi

#--------------------------------------------------------------------
#       The statements below define various symbols relating to Tk
#       stub support.
#--------------------------------------------------------------------

# Replace ${VERSION} with contents of ${TK_VERSION}
eval "TK_STUB_LIB_FILE=libtkstub${TK_UNSHARED_LIB_SUFFIX}"
eval "TK_STUB_LIB_DIR=${libdir}"

if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then
    TK_STUB_LIB_FLAG="-ltkstub${TK_VERSION}"
else
    TK_STUB_LIB_FLAG="-ltkstub`echo ${TK_VERSION} | tr -d .`"
fi

TK_BUILD_STUB_LIB_SPEC="-L`pwd | sed -e 's/ /\\\\ /g'` ${TK_STUB_LIB_FLAG}"
TK_STUB_LIB_SPEC="-L${TK_STUB_LIB_DIR} ${TK_STUB_LIB_FLAG}"
TK_BUILD_STUB_LIB_PATH="`pwd`/${TK_STUB_LIB_FILE}"
TK_STUB_LIB_PATH="${TK_STUB_LIB_DIR}/${TK_STUB_LIB_FILE}"

# Install time header dir can be set via --includedir
eval "TK_INCLUDE_SPEC=\"-I${includedir}\""

#------------------------------------------------------------------------
# Demo dir
#------------------------------------------------------------------------

AS_IF([test x"${DEMO_DIR}" = x], [DEMO_DIR='$(TK_LIBRARY)/demos'])
eval "TK_DEMO_DIR=\"`echo ${DEMO_DIR} | tr '()' '{}'`\""
eval "TK_DEMO_DIR=\"`echo ${TK_DEMO_DIR} | tr '()' '{}'`\""
AC_SUBST(DEMO_DIR)
AC_SUBST(TK_DEMO_DIR)

#------------------------------------------------------------------------
# tkConfig.sh refers to this by a different name
#------------------------------------------------------------------------

TK_SHARED_BUILD=${SHARED_BUILD}

AC_SUBST(TK_VERSION)
AC_SUBST(TK_MAJOR_VERSION)
AC_SUBST(TK_MINOR_VERSION)
AC_SUBST(TK_PATCH_LEVEL)
AC_SUBST(TK_YEAR)

AC_SUBST(TK_LIB_FILE)
AC_SUBST(TK_LIB_FLAG)
AC_SUBST(TK_LIB_SPEC)
AC_SUBST(TK_STUB_LIB_FILE)
AC_SUBST(TK_STUB_LIB_FLAG)
AC_SUBST(TK_STUB_LIB_SPEC)
AC_SUBST(TK_STUB_LIB_PATH)
AC_SUBST(TK_INCLUDE_SPEC)
AC_SUBST(TK_BUILD_STUB_LIB_SPEC)
AC_SUBST(TK_BUILD_STUB_LIB_PATH)

AC_SUBST(TK_SRC_DIR)

AC_SUBST(TK_SHARED_BUILD)
AC_SUBST(LD_LIBRARY_PATH_VAR)

AC_SUBST(TK_BUILD_LIB_SPEC)

AC_SUBST(TCL_STUB_FLAGS)
AC_SUBST(XINCLUDES)
AC_SUBST(XLIBSW)
AC_SUBST(LOCALES)

AC_SUBST(TK_WINDOWINGSYSTEM)
AC_SUBST(TK_PKG_DIR)
AC_SUBST(TK_LIBRARY)
AC_SUBST(LIB_RUNTIME_DIR)
AC_SUBST(PRIVATE_INCLUDE_DIR)
AC_SUBST(HTML_DIR)

AC_SUBST(EXTRA_CC_SWITCHES)
AC_SUBST(EXTRA_APP_CC_SWITCHES)
AC_SUBST(EXTRA_INSTALL)
AC_SUBST(EXTRA_INSTALL_BINARIES)
AC_SUBST(EXTRA_BUILD_HTML)
AC_SUBST(EXTRA_WISH_LIBS)
AC_SUBST(CFBUNDLELOCALIZATIONS)

AC_SUBST(TK_RSRC_FILE)
AC_SUBST(WISH_RSRC_FILE)
AC_SUBST(LIB_RSRC_FILE)
AC_SUBST(APP_RSRC_FILE)
AC_SUBST(REZ)
AC_SUBST(REZ_FLAGS)

AC_CONFIG_FILES([
    Makefile:../unix/Makefile.in
    tkConfig.sh:../unix/tkConfig.sh.in
    tk.pc:../unix/tk.pc.in
])
AC_OUTPUT

dnl Local Variables:
dnl mode: autoconf
dnl End:
Deleted unix/configure.in.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
















































































































































































































































































































































































































































































































































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#! /bin/bash -norc
dnl	This file is an input file used by the GNU "autoconf" program to
dnl	generate the file "configure", which is run during Tk installation
dnl	to configure the system for the local environment.

AC_INIT([tk],[8.6])
AC_PREREQ(2.59)

dnl This is only used when included from macosx/configure.ac
m4_ifdef([SC_USE_CONFIG_HEADERS], [
    AC_CONFIG_HEADERS([tkConfig.h:../unix/tkConfig.h.in])
    AC_CONFIG_COMMANDS_PRE([DEFS="-DHAVE_TK_CONFIG_H  -imacros tkConfig.h"])
    AH_TOP([
    #ifndef _TKCONFIG
    #define _TKCONFIG])
    AH_BOTTOM([
    /* Undef unused package specific autoheader defines so that we can
     * include both tclConfig.h and tkConfig.h at the same time: */
    /* override */ #undef PACKAGE_NAME
    /* override */ #undef PACKAGE_STRING
    /* override */ #undef PACKAGE_TARNAME
    #endif /* _TKCONFIG */])
])

TK_VERSION=8.6
TK_MAJOR_VERSION=8
TK_MINOR_VERSION=6
TK_PATCH_LEVEL=".10"
VERSION=${TK_VERSION}
LOCALES="cs da de el en en_gb eo es fr hu it nl pl pt ru sv"

#--------------------------------------------------------------------
# Find and load the tclConfig.sh file
#--------------------------------------------------------------------

SC_PATH_TCLCONFIG
SC_LOAD_TCLCONFIG

if test "${TCL_MAJOR_VERSION}" -ne 8 ; then
    AC_MSG_ERROR([${PACKAGE_NAME} ${PACKAGE_VERSION} requires Tcl 8.6+
Found config for Tcl ${TCL_VERSION}])
fi
if test "${TCL_MINOR_VERSION}" -lt 6 ; then
    AC_MSG_ERROR([${PACKAGE_NAME} ${PACKAGE_VERSION} requires Tcl 8.6+
Found config for Tcl ${TCL_VERSION}])
fi

SC_PROG_TCLSH
SC_BUILD_TCLSH

#------------------------------------------------------------------------
# Handle the --prefix=... option
#------------------------------------------------------------------------

if test "${prefix}" = "NONE"; then
    prefix="$TCL_PREFIX"
fi
if test "${exec_prefix}" = "NONE"; then
    exec_prefix=$prefix
fi
# Make sure srcdir is fully qualified!
srcdir="`cd "$srcdir" ; pwd`"
TK_SRC_DIR="`cd "$srcdir"/..; pwd`"

#------------------------------------------------------------------------
# Compress and/or soft link the manpages?
#------------------------------------------------------------------------

SC_CONFIG_MANPAGES

#------------------------------------------------------------------------
# Standard compiler checks
#------------------------------------------------------------------------

# If the user did not set CFLAGS, set it now to keep
# the AC_PROG_CC macro from adding "-g -O2".
if test "${CFLAGS+set}" != "set" ; then
    CFLAGS=""
fi

AC_PROG_CC
AC_C_INLINE

#--------------------------------------------------------------------
# Supply a substitute for stdlib.h if it doesn't define strtol,
# strtoul, or strtod (which it doesn't in some versions of SunOS).
#--------------------------------------------------------------------

AC_CHECK_HEADER(stdlib.h, tk_ok=1, tk_ok=0)
AC_EGREP_HEADER(strtol, stdlib.h, , tk_ok=0)
AC_EGREP_HEADER(strtoul, stdlib.h, , tk_ok=0)
AC_EGREP_HEADER(strtod, stdlib.h, , tk_ok=0)
if test $tk_ok = 0; then
    AC_DEFINE(NO_STDLIB_H, 1, [Do we have <stdlib.h>?])
fi

#------------------------------------------------------------------------
# If we're using GCC, see if the compiler understands -pipe.  If so, use it.
# It makes compiling go faster.  (This is only a performance feature.)
#------------------------------------------------------------------------

if test -z "$no_pipe" && test -n "$GCC"; then
    AC_CACHE_CHECK([if the compiler understands -pipe],
	tcl_cv_cc_pipe, [
	hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -pipe"
	AC_TRY_COMPILE(,, tcl_cv_cc_pipe=yes, tcl_cv_cc_pipe=no)
	CFLAGS=$hold_cflags])
    if test $tcl_cv_cc_pipe = yes; then
	CFLAGS="$CFLAGS -pipe"
    fi
fi

#------------------------------------------------------------------------
# Threads support - this auto-enables if Tcl was compiled threaded
#------------------------------------------------------------------------

SC_ENABLE_THREADS

# Add the threads support libraries
LIBS="$LIBS$THREADS_LIBS"

SC_ENABLE_SHARED

#--------------------------------------------------------------------
# The statements below define a collection of compile flags.  This
# macro depends on the value of SHARED_BUILD, and should be called
# after SC_ENABLE_SHARED checks the configure switches.
#--------------------------------------------------------------------

SC_CONFIG_CFLAGS

SC_ENABLE_SYMBOLS

#--------------------------------------------------------------------
#	Detect what compiler flags to set for 64-bit support.
#--------------------------------------------------------------------

SC_TCL_EARLY_FLAGS

SC_TCL_64BIT_FLAGS

#--------------------------------------------------------------------
#	Check endianness because we can optimize some operations
#--------------------------------------------------------------------

AC_C_BIGENDIAN

#------------------------------------------------------------------------
# If Tcl and Tk are installed in different places, adjust the library
# search path to reflect this.
#------------------------------------------------------------------------

LIB_RUNTIME_DIR='$(libdir)'

if test "$TCL_EXEC_PREFIX" != "$exec_prefix"; then
    LIB_RUNTIME_DIR="${LIB_RUNTIME_DIR}:${TCL_EXEC_PREFIX}/lib"
fi

if test "$TCL_PREFIX" != "$prefix"; then
    AC_MSG_WARN([
        Different --prefix selected for Tk and Tcl!
        [[package require Tk]] may not work correctly in tclsh.])
fi

#--------------------------------------------------------------------
#	Include sys/select.h if it exists and if it supplies things
#	that appear to be useful and aren't already in sys/types.h.
#	This appears to be true only on the RS/6000 under AIX.  Some
#	systems like OSF/1 have a sys/select.h that's of no use, and
#	other systems like SCO UNIX have a sys/select.h that's
#	pernicious.  If "fd_set" isn't defined anywhere then set a
#	special flag.
#--------------------------------------------------------------------

AC_CACHE_CHECK([for fd_set in sys/types], tcl_cv_type_fd_set, [
    AC_TRY_COMPILE([#include <sys/types.h>],[fd_set readMask, writeMask;],
	tcl_cv_type_fd_set=yes, tcl_cv_type_fd_set=no)])
tk_ok=$tcl_cv_type_fd_set
if test $tk_ok = no; then
    AC_CACHE_CHECK([for fd_mask in sys/select], tcl_cv_grep_fd_mask, [
	AC_EGREP_HEADER(fd_mask, sys/select.h,
	     tcl_cv_grep_fd_mask=present, tcl_cv_grep_fd_mask=missing)])
    if test $tcl_cv_grep_fd_mask = present; then
	AC_DEFINE(HAVE_SYS_SELECT_H, 1, [Should we include <sys/select.h>?])
	tk_ok=yes
    fi
fi
if test $tk_ok = no; then
    AC_DEFINE(NO_FD_SET, 1, [Do we have fd_set?])
fi

#------------------------------------------------------------------------------
#       Find out all about time handling differences.
#------------------------------------------------------------------------------

AC_CHECK_HEADERS(sys/time.h)
AC_HEADER_TIME

#--------------------------------------------------------------------
#	Check for various typedefs and provide substitutes if
#	they don't exist.
#--------------------------------------------------------------------

AC_TYPE_MODE_T
AC_TYPE_PID_T
AC_TYPE_SIZE_T
AC_TYPE_UID_T

AC_CHECK_TYPE([intptr_t], [
    AC_DEFINE([HAVE_INTPTR_T], 1, [Do we have the intptr_t type?])], [
    AC_CACHE_CHECK([for pointer-size signed integer type], tcl_cv_intptr_t, [
    for tcl_cv_intptr_t in "int" "long" "long long" none; do
	if test "$tcl_cv_intptr_t" != none; then
	    AC_COMPILE_IFELSE([AC_LANG_BOOL_COMPILE_TRY([AC_INCLUDES_DEFAULT],
		    [[sizeof (void *) <= sizeof ($tcl_cv_intptr_t)]])],
		[tcl_ok=yes], [tcl_ok=no])
	    test "$tcl_ok" = yes && break; fi
    done])
    if test "$tcl_cv_intptr_t" != none; then
	AC_DEFINE_UNQUOTED([intptr_t], [$tcl_cv_intptr_t], [Signed integer
	   type wide enough to hold a pointer.])
    fi
])
AC_CHECK_TYPE([uintptr_t], [
    AC_DEFINE([HAVE_UINTPTR_T], 1, [Do we have the uintptr_t type?])], [
    AC_CACHE_CHECK([for pointer-size unsigned integer type], tcl_cv_uintptr_t, [
    for tcl_cv_uintptr_t in "unsigned int" "unsigned long" "unsigned long long" \
	    none; do
	if test "$tcl_cv_uintptr_t" != none; then
	    AC_COMPILE_IFELSE([AC_LANG_BOOL_COMPILE_TRY([AC_INCLUDES_DEFAULT],
		    [[sizeof (void *) <= sizeof ($tcl_cv_uintptr_t)]])],
		[tcl_ok=yes], [tcl_ok=no])
	    test "$tcl_ok" = yes && break; fi
    done])
    if test "$tcl_cv_uintptr_t" != none; then
	AC_DEFINE_UNQUOTED([uintptr_t], [$tcl_cv_uintptr_t], [Unsigned integer
	   type wide enough to hold a pointer.])
    fi
])

#-------------------------------------------
#     In OS/390 struct pwd has no pw_gecos field
#-------------------------------------------

AC_CACHE_CHECK([pw_gecos in struct pwd], tcl_cv_pwd_pw_gecos, [
    AC_TRY_COMPILE([#include <pwd.h>],
	    [struct passwd pwd; pwd.pw_gecos;],
	    tcl_cv_pwd_pw_gecos=yes, tcl_cv_pwd_pw_gecos=no)])
if test $tcl_cv_pwd_pw_gecos = yes; then
    AC_DEFINE(HAVE_PW_GECOS, 1, [Does struct password have a pw_gecos field?])
fi

#--------------------------------------------------------------------
#	On Mac OS X, we can build either with X11 or with Aqua
#--------------------------------------------------------------------

if test "`uname -s`" = "Darwin" ; then
    AC_MSG_CHECKING([whether to use Aqua])
    AC_ARG_ENABLE(aqua,
	AC_HELP_STRING([--enable-aqua=yes|no],
	    [use Aqua windowingsystem on Mac OS X (default: no)]),
	[tk_aqua=$enableval], [tk_aqua=no])
    if test $tk_aqua = yes -o $tk_aqua = cocoa; then
	tk_aqua=yes
	if test $tcl_corefoundation = no; then
	    AC_MSG_WARN([Aqua can only be used when CoreFoundation is available])
	    tk_aqua=no
	fi
	if test ! -d /System/Library/Frameworks/Cocoa.framework; then
	    AC_MSG_WARN([Aqua can only be used when Cocoa is available])
	    tk_aqua=no
	fi
	if test "`uname -r | awk -F. '{print [$]1}'`" -lt 9; then
	    AC_MSG_WARN([Aqua requires Mac OS X 10.5 or later])
	    tk_aqua=no
	fi
    fi
    AC_MSG_RESULT([$tk_aqua])
    if test "$fat_32_64" = yes; then
	if test $tk_aqua = no; then
	    AC_CACHE_CHECK([for 64-bit X11], tcl_cv_lib_x11_64, [
		for v in CFLAGS CPPFLAGS LDFLAGS; do
		    eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"'
		done
		CPPFLAGS="$CPPFLAGS -I/usr/X11R6/include"
		LDFLAGS="$LDFLAGS -L/usr/X11R6/lib -lX11"
		AC_TRY_LINK([#include <X11/Xlib.h>], [XrmInitialize();],
		    tcl_cv_lib_x11_64=yes, tcl_cv_lib_x11_64=no)
		for v in CFLAGS CPPFLAGS LDFLAGS; do
		    eval $v'="$hold_'$v'"'
		done])
	fi
	# remove 64-bit arch flags from CFLAGS et al. for combined 32 & 64 bit
	# fat builds if configuration does not support 64-bit.
	if test "$tcl_cv_lib_x11_64" = no; then
	    AC_MSG_NOTICE([Removing 64-bit architectures from compiler & linker flags])
	    for v in CFLAGS CPPFLAGS LDFLAGS; do
		eval $v'="`echo "$'$v' "|sed -e "s/-arch ppc64 / /g" -e "s/-arch x86_64 / /g"`"'
	    done
	fi
    fi
    if test $tk_aqua = no; then
	# check if weak linking whole libraries is possible.
	AC_CACHE_CHECK([if ld accepts -weak-l flag], tcl_cv_ld_weak_l, [
	    hold_ldflags=$LDFLAGS
	    LDFLAGS="$LDFLAGS -Wl,-weak-lm"
	    AC_TRY_LINK([#include <math.h>], [double f = sin(1.0);],
		tcl_cv_ld_weak_l=yes, tcl_cv_ld_weak_l=no)
	    LDFLAGS=$hold_ldflags])
    fi
    AC_CHECK_HEADERS(AvailabilityMacros.h)
    if test "$ac_cv_header_AvailabilityMacros_h" = yes; then
	AC_CACHE_CHECK([if weak import is available], tcl_cv_cc_weak_import, [
	    hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror"
	    AC_TRY_LINK([
		    #ifdef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
		    #if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1020
		    #error __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1020
		    #endif
		    #elif MAC_OS_X_VERSION_MIN_REQUIRED < 1020
		    #error MAC_OS_X_VERSION_MIN_REQUIRED < 1020
		    #endif
		    int rand(void) __attribute__((weak_import));
		], [rand();],
		tcl_cv_cc_weak_import=yes, tcl_cv_cc_weak_import=no)
	    CFLAGS=$hold_cflags])
	if test $tcl_cv_cc_weak_import = yes; then
	    AC_DEFINE(HAVE_WEAK_IMPORT, 1, [Is weak import available?])
	fi
	AC_CACHE_CHECK([if Darwin SUSv3 extensions are available],
	    tcl_cv_cc_darwin_c_source, [
	    hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror"
	    AC_TRY_COMPILE([
		    #ifdef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
		    #if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1050
		    #error __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1050
		    #endif
		    #elif MAC_OS_X_VERSION_MIN_REQUIRED < 1050
		    #error MAC_OS_X_VERSION_MIN_REQUIRED < 1050
		    #endif
		    #define _DARWIN_C_SOURCE 1
		    #include <sys/cdefs.h>
		],,tcl_cv_cc_darwin_c_source=yes, tcl_cv_cc_darwin_c_source=no)
	    CFLAGS=$hold_cflags])
	if test $tcl_cv_cc_darwin_c_source = yes; then
	    AC_DEFINE(_DARWIN_C_SOURCE, 1,
		    [Are Darwin SUSv3 extensions available?])
	fi
    fi
else
    tk_aqua=no
fi

if test $tk_aqua = yes; then
    AC_DEFINE(MAC_OSX_TK, 1, [Are we building TkAqua?])
    LIBS="$LIBS -framework Cocoa -framework Carbon -framework IOKit"
    EXTRA_CC_SWITCHES='-std=gnu99 -x objective-c'
    TK_WINDOWINGSYSTEM=AQUA
    if test -n "${enable_symbols}" -a "${enable_symbols}" != no; then
        AC_DEFINE(TK_MAC_DEBUG, 1, [Are TkAqua debug messages enabled?])
    fi
else
    #--------------------------------------------------------------------
    #	Locate the X11 header files and the X11 library archive.  Try
    #	the ac_path_x macro first, but if it doesn't find the X stuff
    #	(e.g. because there's no xmkmf program) then check through
    #	a list of possible directories.  Under some conditions the
    #	autoconf macro will return an include directory that contains
    #	no include files, so double-check its result just to be safe.
    #--------------------------------------------------------------------

    SC_PATH_X
    TK_WINDOWINGSYSTEM=X11
fi

#--------------------------------------------------------------------
#	Various manipulations on the search path used at runtime to
#	find shared libraries:
#	1. If the X library binaries are in a non-standard directory,
#	   add the X library location into that search path.
#	2. On systems such as AIX and Ultrix that use "-L" as the
#	   search path option, colons cannot be used to separate
#	   directories from each other. Change colons to " -L".
#	3. Create two sets of search flags, one for use in cc lines
#	   and the other for when the linker is invoked directly.  In
#	   the second case, '-Wl,' must be stripped off and commas must
#	   be replaced by spaces.
#--------------------------------------------------------------------

if test "x${x_libraries}" != "x"; then
  if test "x${x_libraries}" != "xNONE"; then
    LIB_RUNTIME_DIR="${LIB_RUNTIME_DIR}:${x_libraries}"
  fi
fi
if test "${TCL_LD_SEARCH_FLAGS}" = '-L${LIB_RUNTIME_DIR}'; then
    LIB_RUNTIME_DIR=`echo ${LIB_RUNTIME_DIR} |sed -e 's/:/ -L/g'`
fi

#--------------------------------------------------------------------
#	Check for the existence of various libraries.  The order here
#	is important, so that then end up in the right order in the
#	command line generated by make.  The -lsocket and -lnsl libraries
#	require a couple of special tricks:
#	1. Use "connect" and "accept" to check for -lsocket, and
#	   "gethostbyname" to check for -lnsl.
#	2. Use each function name only once:  can't redo a check because
#	   autoconf caches the results of the last check and won't redo it.
#	3. Use -lnsl and -lsocket only if they supply procedures that
#	   aren't already present in the normal libraries.  This is because
#	   IRIX 5.2 has libraries, but they aren't needed and they're
#	   bogus:  they goof up name resolution if used.
#	4. On some SVR4 systems, can't use -lsocket without -lnsl too.
#	   To get around this problem, check for both libraries together
#	   if -lsocket doesn't work by itself.
#--------------------------------------------------------------------

if test $tk_aqua = no; then
    AC_CHECK_LIB(Xbsd, main, [LIBS="$LIBS -lXbsd"])
fi

#--------------------------------------------------------------------
# One more check related to the X libraries.  The standard releases
# of Ultrix don't support the "xauth" mechanism, so send won't work
# unless TK_NO_SECURITY is defined.  However, there are usually copies
# of the MIT X server available as well, which do support xauth.
# Check for the MIT stuff and use it if it exists.
#
# Note: can't use ac_check_lib macro (at least, not in Autoconf 2.1)
# because it can't deal with the "-" in the library name.
#--------------------------------------------------------------------

if test -d /usr/include/mit -a $tk_aqua = no; then
    AC_MSG_CHECKING([MIT X libraries])
    tk_oldCFlags=$CFLAGS
    CFLAGS="$CFLAGS -I/usr/include/mit"
    tk_oldLibs=$LIBS
    LIBS="$LIBS -lX11-mit"
    AC_TRY_LINK([
	#include <X11/Xlib.h>
    ], [
	XOpenDisplay(0);
    ], [
	AC_MSG_RESULT([yes])
	XLIBSW="-lX11-mit"
	XINCLUDES="-I/usr/include/mit"
    ], AC_MSG_RESULT([no]))
    CFLAGS=$tk_oldCFlags
    LIBS=$tk_oldLibs
fi

#--------------------------------------------------------------------
#	Check for freetype / fontconfig / Xft support.
#--------------------------------------------------------------------

if test $tk_aqua = no; then
    AC_MSG_CHECKING([whether to use xft])
    AC_ARG_ENABLE(xft,
	AC_HELP_STRING([--enable-xft],
	    [use freetype/fontconfig/xft (default: on)]),
	[enable_xft=$enableval], [enable_xft="default"])
    XFT_CFLAGS=""
    XFT_LIBS=""
    if test "$enable_xft" = "no" ; then
	AC_MSG_RESULT([$enable_xft])
    else
	found_xft="yes"
	dnl make sure package configurator (xft-config or pkg-config
	dnl says that xft is present.
	XFT_CFLAGS=`xft-config --cflags 2>/dev/null` || found_xft="no"
	XFT_LIBS=`xft-config --libs 2>/dev/null` || found_xft="no"
	if test "$found_xft" = "no" ; then
	    found_xft=yes
	    XFT_CFLAGS=`pkg-config --cflags xft fontconfig 2>/dev/null` || found_xft="no"
	    XFT_LIBS=`pkg-config --libs xft fontconfig 2>/dev/null` || found_xft="no"
	fi
	AC_MSG_RESULT([$found_xft])
	dnl make sure that compiling against Xft header file doesn't bomb
	if test "$found_xft" = "yes" ; then
	    tk_oldCFlags=$CFLAGS
	    CFLAGS="$CFLAGS $XINCLUDES $XFT_CFLAGS"
	    tk_oldLibs=$LIBS
	    LIBS="$tk_oldLIBS $XFT_LIBS $XLIBSW"
	    AC_CHECK_HEADER(X11/Xft/Xft.h, [], [
		found_xft=no
	    ],[#include <X11/Xlib.h>])
	    CFLAGS=$tk_oldCFlags
	    LIBS=$tk_oldLibs
	fi
	dnl make sure that linking against Xft libraries finds freetype
	if test "$found_xft" = "yes" ; then
	    tk_oldCFlags=$CFLAGS
	    CFLAGS="$CFLAGS $XINCLUDES $XFT_CFLAGS"
	    tk_oldLibs=$LIBS
	    LIBS="$tk_oldLIBS $XFT_LIBS $XLIBSW"
	    AC_CHECK_LIB(Xft, XftFontOpen, [], [
		found_xft=no
	    ])
	    CFLAGS=$tk_oldCFlags
	    LIBS=$tk_oldLibs
	fi
	dnl make sure that linking against fontconfig libraries finds Fc* symbols
	if test "$found_xft" = "yes" ; then
	    tk_oldCFlags=$CFLAGS
	    CFLAGS="$CFLAGS $XINCLUDES $XFT_CFLAGS"
	    tk_oldLibs=$LIBS
	    LIBS="$tk_oldLIBS $XFT_LIBS $XLIBSW -lfontconfig"
	    AC_CHECK_LIB(fontconfig, FcFontSort, [
		XFT_LIBS="$XFT_LIBS -lfontconfig"
	    ], [])
	    CFLAGS=$tk_oldCFlags
	    LIBS=$tk_oldLibs
	fi
	dnl print a warning if xft is unusable and was specifically requested
	if test "$found_xft" = "no" ; then
	    if test "$enable_xft" = "yes" ; then
		AC_MSG_WARN([Can't find xft configuration, or xft is unusable])
	    fi
	    enable_xft=no
	    XFT_CFLAGS=""
	    XFT_LIBS=""
	else
            enable_xft=yes
	fi
    fi
    if test $enable_xft = "yes" ; then
	UNIX_FONT_OBJS=tkUnixRFont.o
	AC_DEFINE(HAVE_XFT, 1, [Have we turned on XFT (antialiased fonts)?])
    else
	UNIX_FONT_OBJS=tkUnixFont.o
    fi
    AC_SUBST(XFT_CFLAGS)
    AC_SUBST(XFT_LIBS)
    AC_SUBST(UNIX_FONT_OBJS)
fi

#--------------------------------------------------------------------
#	Check for XkbKeycodeToKeysym.
#--------------------------------------------------------------------

if test $tk_aqua = no; then
    tk_oldCFlags=$CFLAGS
    tk_oldLibs=$LIBS
    CFLAGS="$CFLAGS $XINCLUDES"
    LIBS="$LIBS $XLIBSW"
    AC_CHECK_HEADER(X11/XKBlib.h, [
	xkblib_header_found=yes
    ], [
	xkblib_header_found=no
    ], [#include <X11/Xlib.h>])
    if test $xkblib_header_found = "yes" ; then
	AC_CHECK_LIB(X11, XkbKeycodeToKeysym, [
	    xkbkeycodetokeysym_found=yes
	], [
	    xkbkeycodetokeysym_found=no
	])
    else
	xkbkeycodetokeysym_found=no
    fi
    if test $xkbkeycodetokeysym_found = "yes" ; then
	AC_DEFINE(HAVE_XKBKEYCODETOKEYSYM, 1, [Do we have XkbKeycodeToKeysym?])
    fi
    CFLAGS=$tk_oldCFlags
    LIBS=$tk_oldLibs
fi

#--------------------------------------------------------------------
# Check whether XKeycodeToKeysym is deprecated in X11 headers.
#--------------------------------------------------------------------

if test $tk_aqua = no && test "$GCC" = yes; then
    AC_MSG_CHECKING([whether XKeycodeToKeysym is deprecated])
    tk_oldCFlags=$CFLAGS
    CFLAGS="$CFLAGS -Werror"
    AC_TRY_LINK([
	#include <X11/Xlib.h>
    ], [
	XKeycodeToKeysym(0,0,0);
    ], [
	AC_MSG_RESULT([no])
    ], [
    AC_MSG_RESULT([yes])
	AC_DEFINE(XKEYCODETOKEYSYM_IS_DEPRECATED, 1, [Is XKeycodeToKeysym deprecated?])
	])
    CFLAGS=$tk_oldCFlags
fi

#--------------------------------------------------------------------
# XXX Do this last.
# It might modify XLIBSW which could affect other tests.
#
# Check whether the header and library for the XScreenSaver
# extension are available, and set HAVE_XSS if so.
# XScreenSaver is needed for Tk_GetUserInactiveTime().
#--------------------------------------------------------------------

if test $tk_aqua = no; then
    tk_oldCFlags=$CFLAGS
    CFLAGS="$CFLAGS $XINCLUDES"
    tk_oldLibs=$LIBS
    LIBS="$tk_oldLibs $XLIBSW"
    xss_header_found=no
    xss_lib_found=no
    AC_MSG_CHECKING([whether to try to use XScreenSaver])
    AC_ARG_ENABLE(xss,
	AC_HELP_STRING([--enable-xss],
	    [use XScreenSaver for activity timer (default: on)]),
	[enable_xss=$enableval], [enable_xss=yes])
    if test "$enable_xss" = "no" ; then
	AC_MSG_RESULT([$enable_xss])
    else
	AC_MSG_RESULT([$enable_xss])
	AC_CHECK_HEADER(X11/extensions/scrnsaver.h, [
	    xss_header_found=yes
	],,[#include <X11/Xlib.h>])
	AC_CHECK_FUNC(XScreenSaverQueryInfo,,[
	    AC_CHECK_LIB(Xext, XScreenSaverQueryInfo, [
		XLIBSW="$XLIBSW -lXext"
		xss_lib_found=yes
	    ], [
		AC_CHECK_LIB(Xss, XScreenSaverQueryInfo, [
		    if test "$tcl_cv_ld_weak_l" = yes; then
			# On Darwin, weak link libXss if possible,
			# as it is only available on Tiger or later.
			XLIBSW="$XLIBSW -Wl,-weak-lXss -lXext"
		    else
			XLIBSW="$XLIBSW -lXss -lXext"
		    fi
		    xss_lib_found=yes
		],, -lXext)
	    ])
	])
    fi
    if test $enable_xss = yes -a $xss_lib_found = yes -a $xss_header_found = yes; then
	AC_DEFINE(HAVE_XSS, 1, [Is XScreenSaver available?])
    fi
    CFLAGS=$tk_oldCFlags
    LIBS=$tk_oldLibs
fi

#--------------------------------------------------------------------
#	Figure out whether "char" is unsigned.  If so, set a
#	#define for __CHAR_UNSIGNED__.
#--------------------------------------------------------------------

AC_C_CHAR_UNSIGNED

#--------------------------------------------------------------------
#	The statements below define a collection of symbols related to
#	building libtk as a shared library instead of a static library.
#--------------------------------------------------------------------

eval eval "TK_UNSHARED_LIB_SUFFIX=${UNSHARED_LIB_SUFFIX}"
eval eval "TK_SHARED_LIB_SUFFIX=${SHARED_LIB_SUFFIX}"
eval "TK_LIB_FILE=libtk${LIB_SUFFIX}"

# tkConfig.sh needs a version of the _LIB_SUFFIX that has been eval'ed
# since on some platforms TK_LIB_FILE contains shell escapes.

eval "TK_LIB_FILE=${TK_LIB_FILE}"

if test "${SHARED_BUILD}" = "1" -a "${SHLIB_SUFFIX}" != ""; then
    SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \${TCL_STUB_LIB_SPEC}"
    TCL_STUB_FLAGS="-DUSE_TCL_STUBS"
fi

test -z "$TK_LIBRARY" && TK_LIBRARY='$(prefix)/lib/tk$(VERSION)'
PRIVATE_INCLUDE_DIR='$(includedir)'
HTML_DIR='$(DISTDIR)/html'
TK_PKG_DIR='tk$(VERSION)'
TK_RSRC_FILE='tk$(VERSION).rsrc'
WISH_RSRC_FILE='wish$(VERSION).rsrc'

# Note:  in the following variable, it's important to use the absolute
# path name of the Tcl directory rather than "..":  this is because
# AIX remembers this path and will attempt to use it at run-time to look
# up the Tcl library.

if test "`uname -s`" = "Darwin" ; then
    SC_ENABLE_FRAMEWORK
    TK_SHLIB_LD_EXTRAS="-compatibility_version ${TK_VERSION} -current_version ${TK_VERSION}`echo ${TK_PATCH_LEVEL} | awk ['{match($0, "\\\.[0-9]+"); print substr($0,RSTART,RLENGTH)}']`"
    TK_SHLIB_LD_EXTRAS="${TK_SHLIB_LD_EXTRAS}"' -install_name "${DYLIB_INSTALL_DIR}/${TK_LIB_FILE}" -unexported_symbols_list $$(f=$(TK_LIB_FILE).E && nm -gp tkMacOSX*.o 2>/dev/null | awk "/^[[0-9a-f]]+ . \.objc/ {print \$$3}" > $$f && nm -gjp "$(TCL_BIN_DIR)"/$(TCL_STUB_LIB_FILE) | grep ^_[[^_]] >> $$f && echo $$f)'
    echo "$LDFLAGS " | grep -q -- '-prebind ' && TK_SHLIB_LD_EXTRAS="${TK_SHLIB_LD_EXTRAS}"' -seg1addr 0xb000000'
    TK_SHLIB_LD_EXTRAS="${TK_SHLIB_LD_EXTRAS}"' -sectcreate __TEXT __info_plist Tk-Info.plist'
    EXTRA_WISH_LIBS='-sectcreate __TEXT __info_plist Wish-Info.plist'
    EXTRA_APP_CC_SWITCHES="${EXTRA_APP_CC_SWITCHES}"' -mdynamic-no-pic'
    AC_CONFIG_FILES([Tk-Info.plist:../macosx/Tk-Info.plist.in Wish-Info.plist:../macosx/Wish-Info.plist.in])
    for l in ${LOCALES}; do CFBUNDLELOCALIZATIONS="${CFBUNDLELOCALIZATIONS}<string>$l</string>"; done
    TK_YEAR="`date +%Y`"
fi

if test "$FRAMEWORK_BUILD" = "1" ; then
    AC_DEFINE(TK_FRAMEWORK, 1, [Is Tk built as a framework?])
    # Construct a fake local framework structure to make linking with
    # '-framework Tk' and running of tktest work
    AC_CONFIG_COMMANDS([Tk.framework], [n=Tk &&
        f=$n.framework && v=Versions/$VERSION &&
        rm -rf $f && mkdir -p $f/$v/Resources &&
        ln -s $v/$n $v/Resources $f && ln -s ../../../$n $f/$v &&
        ln -s ../../../../$n-Info.plist $f/$v/Resources/Info.plist &&
        if test $tk_aqua = yes; then ln -s ../../../../$n.rsrc $f/$v/Resources; fi &&
        unset n f v
    ], VERSION=${TK_VERSION} && tk_aqua=${tk_aqua})
    LD_LIBRARY_PATH_VAR="DYLD_FRAMEWORK_PATH"
    if test "${libdir}" = '${exec_prefix}/lib'; then
        # override libdir default
        libdir="/Library/Frameworks"
    fi
    TK_LIB_FILE="Tk"
    TK_LIB_FLAG="-framework Tk"
    TK_BUILD_LIB_SPEC="-F`pwd | sed -e 's/ /\\\\ /g'` -framework Tk"
    TK_LIB_SPEC="-F${libdir} -framework Tk"
    libdir="${libdir}/Tk.framework/Versions/\${VERSION}"
    TK_LIBRARY="${libdir}/Resources/Scripts"
    TK_PKG_DIR="Resources/Scripts"
    TK_RSRC_FILE="Tk.rsrc"
    WISH_RSRC_FILE="Wish.rsrc"
    includedir="${libdir}/Headers"
    PRIVATE_INCLUDE_DIR="${libdir}/PrivateHeaders"
    HTML_DIR="${libdir}/Resources/Documentation/Reference/Tk"
    EXTRA_INSTALL="install-private-headers html-tk"
    EXTRA_BUILD_HTML='@ln -fs contents.htm "$(HTML_INSTALL_DIR)"/TkTOC.html'
    EXTRA_INSTALL_BINARIES='@echo "Installing Info.plist to $(LIB_INSTALL_DIR)/Resources/" && $(INSTALL_DATA_DIR) "$(LIB_INSTALL_DIR)/Resources" && $(INSTALL_DATA) Tk-Info.plist "$(LIB_INSTALL_DIR)/Resources/Info.plist"'
    EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Installing license.terms to $(LIB_INSTALL_DIR)/Resources/" && $(INSTALL_DATA) "$(TOP_DIR)/license.terms" "$(LIB_INSTALL_DIR)/Resources"'
    if test $tk_aqua = yes; then
	EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Installing Images to $(LIB_INSTALL_DIR)/Resources/" && $(INSTALL_DATA_DIR) "$(LIB_INSTALL_DIR)/Resources" && for i in Tk.tiff Tk.icns; do $(INSTALL_DATA) "$(MAC_OSX_DIR)/$$i" "$(LIB_INSTALL_DIR)/Resources"; done'
	EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Installing wish$(VERSION) script to $(INSTALL_ROOT)/'"${bindir}"'/" && $(INSTALL_DATA_DIR) "$(INSTALL_ROOT)/'"${bindir}"'" && printf > "$(INSTALL_ROOT)/'"${bindir}"'/wish$(VERSION)" "#!/bin/sh\n\"\$$(dirname \$$0)'"`eval d="${bindir}"; echo "$d" | sed -e 's#/[^/][^/]*#/..#g'`"'$(bindir)/Wish\" \"\$$@\"" && chmod +x "$(INSTALL_ROOT)/'"${bindir}"'/wish$(VERSION)"'
	bindir="${libdir}/Resources/Wish.app/Contents/MacOS"
	EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Installing Info.plist to $(BIN_INSTALL_DIR)/.." && $(INSTALL_DATA) Wish-Info.plist "$(BIN_INSTALL_DIR)/../Info.plist" && mv -f "$(BIN_INSTALL_DIR)/wish$(VERSION)" "$(BIN_INSTALL_DIR)/Wish"'
	EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Installing Wish.icns to $(BIN_INSTALL_DIR)/../Resources" && $(INSTALL_DATA_DIR) "$(BIN_INSTALL_DIR)/../Resources"'
	EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && $(INSTALL_DATA) "$(MAC_OSX_DIR)/Tk.icns" "$(BIN_INSTALL_DIR)/../Resources/Wish.icns"'
	EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Installing Wish.sdef to $(BIN_INSTALL_DIR)/../Resources" && $(INSTALL_DATA) "$(MAC_OSX_DIR)/Wish.sdef" "$(BIN_INSTALL_DIR)/../Resources"'
    fi
    EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Finalizing Tk.framework" && rm -f "$(LIB_INSTALL_DIR)/../Current" && ln -s "$(VERSION)" "$(LIB_INSTALL_DIR)/../Current" && for f in "$(LIB_FILE)" tkConfig.sh Resources Headers PrivateHeaders; do rm -f "$(LIB_INSTALL_DIR)/../../$$f" && ln -s "Versions/Current/$$f" "$(LIB_INSTALL_DIR)/../.."; done && f="$(STUB_LIB_FILE)" && rm -f "$(LIB_INSTALL_DIR)/../../$$f" && ln -s "Versions/$(VERSION)/$$f" "$(LIB_INSTALL_DIR)/../.."'
    # Don't use AC_DEFINE for the following as the framework version define
    # needs to go into the Makefile even when using autoheader, so that we
    # can pick up a potential make override of VERSION. Also, don't put this
    # into CFLAGS as it should not go into tkConfig.sh
    EXTRA_CC_SWITCHES="$EXTRA_CC_SWITCHES"' -DTK_FRAMEWORK_VERSION=\"$(VERSION)\"'
else
    if test $tk_aqua = yes; then
        EXTRA_INSTALL_BINARIES='@echo "Installing Images to $(LIB_INSTALL_DIR)/" && $(INSTALL_DATA_DIR) "$(LIB_INSTALL_DIR)" && for i in Tk.tiff Tk.icns; do $(INSTALL_DATA) "$(MAC_OSX_DIR)/$$i" "$(LIB_INSTALL_DIR)"; done'
    fi
    # libdir must be a fully qualified path and not ${exec_prefix}/lib
    eval libdir="$libdir"
    if test "${ac_cv_cygwin}" = "yes" -a "$SHARED_BUILD" = "1"; then
	TK_LIB_FLAG="-ltk`echo ${TK_VERSION} | tr -d .`"
	TK_BUILD_LIB_SPEC="-L\$(TOP_DIR)/win ${TK_LIB_FLAG}"
    else
	if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then
	    TK_LIB_FLAG="-ltk${TK_VERSION}"
	else
	    TK_LIB_FLAG="-ltk`echo ${TK_VERSION} | tr -d .`"
	fi
	TK_BUILD_LIB_SPEC="-L`pwd | sed -e 's/ /\\\\ /g'` ${TK_LIB_FLAG}"
    fi
    TK_LIB_SPEC="-L${libdir} ${TK_LIB_FLAG}"
fi

#--------------------------------------------------------------------
#       The statements below define various symbols relating to Tk
#       stub support.
#--------------------------------------------------------------------

# Replace ${VERSION} with contents of ${TK_VERSION}
eval "TK_STUB_LIB_FILE=libtkstub${TK_UNSHARED_LIB_SUFFIX}"
eval "TK_STUB_LIB_DIR=${libdir}"

if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then
    TK_STUB_LIB_FLAG="-ltkstub${TK_VERSION}"
else
    TK_STUB_LIB_FLAG="-ltkstub`echo ${TK_VERSION} | tr -d .`"
fi

TK_BUILD_STUB_LIB_SPEC="-L`pwd | sed -e 's/ /\\\\ /g'` ${TK_STUB_LIB_FLAG}"
TK_STUB_LIB_SPEC="-L${TK_STUB_LIB_DIR} ${TK_STUB_LIB_FLAG}"
TK_BUILD_STUB_LIB_PATH="`pwd`/${TK_STUB_LIB_FILE}"
TK_STUB_LIB_PATH="${TK_STUB_LIB_DIR}/${TK_STUB_LIB_FILE}"

# Install time header dir can be set via --includedir
eval "TK_INCLUDE_SPEC=\"-I${includedir}\""

#------------------------------------------------------------------------
# tkConfig.sh refers to this by a different name
#------------------------------------------------------------------------

TK_SHARED_BUILD=${SHARED_BUILD}

AC_SUBST(TK_VERSION)
AC_SUBST(TK_MAJOR_VERSION)
AC_SUBST(TK_MINOR_VERSION)
AC_SUBST(TK_PATCH_LEVEL)
AC_SUBST(TK_YEAR)

AC_SUBST(TK_LIB_FILE)
AC_SUBST(TK_LIB_FLAG)
AC_SUBST(TK_LIB_SPEC)
AC_SUBST(TK_STUB_LIB_FILE)
AC_SUBST(TK_STUB_LIB_FLAG)
AC_SUBST(TK_STUB_LIB_SPEC)
AC_SUBST(TK_STUB_LIB_PATH)
AC_SUBST(TK_INCLUDE_SPEC)
AC_SUBST(TK_BUILD_STUB_LIB_SPEC)
AC_SUBST(TK_BUILD_STUB_LIB_PATH)

AC_SUBST(TK_SRC_DIR)

AC_SUBST(TK_SHARED_BUILD)
AC_SUBST(LD_LIBRARY_PATH_VAR)

AC_SUBST(TK_BUILD_LIB_SPEC)

AC_SUBST(TCL_STUB_FLAGS)
AC_SUBST(XINCLUDES)
AC_SUBST(XLIBSW)
AC_SUBST(LOCALES)

AC_SUBST(TK_WINDOWINGSYSTEM)
AC_SUBST(TK_PKG_DIR)
AC_SUBST(TK_LIBRARY)
AC_SUBST(LIB_RUNTIME_DIR)
AC_SUBST(PRIVATE_INCLUDE_DIR)
AC_SUBST(HTML_DIR)

AC_SUBST(EXTRA_CC_SWITCHES)
AC_SUBST(EXTRA_APP_CC_SWITCHES)
AC_SUBST(EXTRA_INSTALL)
AC_SUBST(EXTRA_INSTALL_BINARIES)
AC_SUBST(EXTRA_BUILD_HTML)
AC_SUBST(EXTRA_WISH_LIBS)
AC_SUBST(CFBUNDLELOCALIZATIONS)

AC_SUBST(TK_RSRC_FILE)
AC_SUBST(WISH_RSRC_FILE)
AC_SUBST(LIB_RSRC_FILE)
AC_SUBST(APP_RSRC_FILE)
AC_SUBST(REZ)
AC_SUBST(REZ_FLAGS)

AC_CONFIG_FILES([
    Makefile:../unix/Makefile.in
    tkConfig.sh:../unix/tkConfig.sh.in
    tk.pc:../unix/tk.pc.in
])
AC_OUTPUT

dnl Local Variables:
dnl mode: autoconf
dnl End:
Changes to unix/install-sh.
1
2
3
4

5
6
7
8
9
10
11
1
2
3

4
5
6
7
8
9
10
11



-
+







#!/bin/sh
# install - install a program, script, or datafile

scriptversion=2011-04-20.01; # UTC
scriptversion=2020-07-26.22; # UTC

# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
# following copyright and license.
#
# Copyright (C) 1994 X Consortium
#
31
32
33
34
35
36
37
38

39
40
41
42
43

44
45
46

47
48

49
50
51
52
53

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85




86
87
88
89
90
91
92
93
94
95
96
97
98
99
100

101
102
103
104
105
106
107
31
32
33
34
35
36
37

38
39
40
41
42
43
44
45
46

47
48

49
50

51


52



53
54
55
56
57
58
59
60
61
62
63
64
65
66











67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88

89
90
91
92
93
94
95
96







-
+





+


-
+

-
+

-

-
-
+
-
-
-














-
-
-
-
-
-
-
-
-
-
-




+
+
+
+














-
+







# ings in this Software without prior written authorization from the X Consor-
# tium.
#
#
# FSF changes to this file are in the public domain.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# `make' implicit rules from creating a file called install from it
# 'make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch.

tab='	'
nl='
'
IFS=" ""	$nl"
IFS=" $tab$nl"

# set DOITPROG to echo to test this script
# Set DOITPROG to "echo" to test this script.

# Don't use :- since 4.3BSD and earlier shells don't like it.
doit=${DOITPROG-}
if test -z "$doit"; then
  doit_exec=exec
doit_exec=${doit:-exec}
else
  doit_exec=$doit
fi

# Put in absolute file names if you don't have them in your path;
# or use environment vars.

chgrpprog=${CHGRPPROG-chgrp}
chmodprog=${CHMODPROG-chmod}
chownprog=${CHOWNPROG-chown}
cmpprog=${CMPPROG-cmp}
cpprog=${CPPROG-cp}
mkdirprog=${MKDIRPROG-mkdir}
mvprog=${MVPROG-mv}
rmprog=${RMPROG-rm}
stripprog=${STRIPPROG-strip}

posix_glob='?'
initialize_posix_glob='
  test "$posix_glob" != "?" || {
    if (set -f) 2>/dev/null; then
      posix_glob=
    else
      posix_glob=:
    fi
  }
'

posix_mkdir=

# Desired mode of installed file.
mode=0755

# Create dirs (including intermediate dirs) using mode 755.
# This is like GNU 'install' as of coreutils 8.32 (2020).
mkdir_umask=22

chgrpcmd=
chmodcmd=$chmodprog
chowncmd=
mvcmd=$mvprog
rmcmd="$rmprog -f"
stripcmd=

src=
dst=
dir_arg=
dst_arg=

copy_on_change=false
no_target_directory=
is_target_a_directory=possibly

usage="\
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
   or: $0 [OPTION]... SRCFILES... DIRECTORY
   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
   or: $0 [OPTION]... -d DIRECTORIES...

116
117
118
119
120
121
122
123

124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141

142
143
144
145
146

147
148
149
150
151
152





153
154
155

156
157
158
159
160

161


162
163






164
165

166
167
168
169
170


171
172
173


174
175
176
177
178










179
180
181
182
183
184
185
186
187
188
189
190
191
192




193
194
195
196
197
198
199
200
201

202
203
204









205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222

223
224

225
226
227
228
229

230
231

232
233
234
235
236
237
238
239

240
241

242
243
244
245
246
247
248
105
106
107
108
109
110
111

112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129

130
131
132
133
134

135






136
137
138
139
140
141
142

143
144
145
146
147

148
149
150
151


152
153
154
155
156
157
158

159
160
161
162


163
164
165


166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208

209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238

239
240

241
242
243
244
245

246
247

248
249
250
251
252
253
254
255

256
257

258
259
260
261
262
263
264
265







-
+

















-
+




-
+
-
-
-
-
-
-
+
+
+
+
+


-
+




-
+

+
+
-
-
+
+
+
+
+
+

-
+



-
-
+
+

-
-
+
+





+
+
+
+
+
+
+
+
+
+














+
+
+
+








-
+



+
+
+
+
+
+
+
+
+

















-
+

-
+




-
+

-
+







-
+

-
+







  -c            (ignored)
  -C            install only if different (preserve the last data modification time)
  -d            create directories instead of installing files.
  -g GROUP      $chgrpprog installed files to GROUP.
  -m MODE       $chmodprog installed files to MODE.
  -o USER       $chownprog installed files to USER.
  -s            $stripprog installed files.
  -S            $stripprog installed files.
  -S OPTION     $stripprog installed files using OPTION.
  -t DIRECTORY  install into DIRECTORY.
  -T            report an error if DSTFILE is a directory.

Environment variables override the default commands:
  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
  RMPROG STRIPPROG
"

while test $# -ne 0; do
  case $1 in
    -c) ;;

    -C) copy_on_change=true;;

    -d) dir_arg=true;;

    -g) chgrpcmd="$chgrpprog $2"
	shift;;
        shift;;

    --help) echo "$usage"; exit $?;;

    -m) mode=$2
	case $mode in
        case $mode in
	  *' '* | *'	'* | *'
'*	  | *'*'* | *'?'* | *'['*)
	    echo "$0: invalid mode: $mode" >&2
	    exit 1;;
	esac
	shift;;
          *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
            echo "$0: invalid mode: $mode" >&2
            exit 1;;
        esac
        shift;;

    -o) chowncmd="$chownprog $2"
	shift;;
        shift;;

    -s) stripcmd=$stripprog;;

    -S) stripcmd="$stripprog $2"
	shift;;
        shift;;

    -t)
        is_target_a_directory=always
    -t) dst_arg=$2
	shift;;
        dst_arg=$2
        # Protect names problematic for 'test' and other utilities.
        case $dst_arg in
          -* | [=\(\)!]) dst_arg=./$dst_arg;;
        esac
        shift;;

    -T) no_target_directory=true;;
    -T) is_target_a_directory=never;;

    --version) echo "$0 $scriptversion"; exit $?;;

    --)	shift
	break;;
    --) shift
        break;;

    -*)	echo "$0: invalid option: $1" >&2
	exit 1;;
    -*) echo "$0: invalid option: $1" >&2
        exit 1;;

    *)  break;;
  esac
  shift
done

# We allow the use of options -d and -T together, by making -d
# take the precedence; this is for compatibility with GNU install.

if test -n "$dir_arg"; then
  if test -n "$dst_arg"; then
    echo "$0: target directory not allowed when installing a directory." >&2
    exit 1
  fi
fi

if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
  # When -d is used, all remaining arguments are directories to create.
  # When -t is used, the destination is already specified.
  # Otherwise, the last argument is the destination.  Remove it from $@.
  for arg
  do
    if test -n "$dst_arg"; then
      # $@ is not empty: it contains at least $arg.
      set fnord "$@" "$dst_arg"
      shift # fnord
    fi
    shift # arg
    dst_arg=$arg
    # Protect names problematic for 'test' and other utilities.
    case $dst_arg in
      -* | [=\(\)!]) dst_arg=./$dst_arg;;
    esac
  done
fi

if test $# -eq 0; then
  if test -z "$dir_arg"; then
    echo "$0: no input file specified." >&2
    exit 1
  fi
  # It's OK to call `install-sh -d' without argument.
  # It's OK to call 'install-sh -d' without argument.
  # This can happen when creating conditional directories.
  exit 0
fi

if test -z "$dir_arg"; then
  if test $# -gt 1 || test "$is_target_a_directory" = always; then
    if test ! -d "$dst_arg"; then
      echo "$0: $dst_arg: Is not a directory." >&2
      exit 1
    fi
  fi
fi

if test -z "$dir_arg"; then
  do_exit='(exit $ret); exit $ret'
  trap "ret=129; $do_exit" 1
  trap "ret=130; $do_exit" 2
  trap "ret=141; $do_exit" 13
  trap "ret=143; $do_exit" 15

  # Set umask so as not to create temps with too-generous modes.
  # However, 'strip' requires both read and write access to temps.
  case $mode in
    # Optimize common cases.
    *644) cp_umask=133;;
    *755) cp_umask=22;;

    *[0-7])
      if test -z "$stripcmd"; then
	u_plus_rw=
        u_plus_rw=
      else
	u_plus_rw='% 200'
        u_plus_rw='% 200'
      fi
      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
    *)
      if test -z "$stripcmd"; then
	u_plus_rw=
        u_plus_rw=
      else
	u_plus_rw=,u+rw
        u_plus_rw=,u+rw
      fi
      cp_umask=$mode$u_plus_rw;;
  esac
fi

for src
do
  # Protect names starting with `-'.
  # Protect names problematic for 'test' and other utilities.
  case $src in
    -*) src=./$src;;
    -* | [=\(\)!]) src=./$src;;
  esac

  if test -n "$dir_arg"; then
    dst=$src
    dstdir=$dst
    test -d "$dstdir"
    dstdir_status=$?
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270

271
272
273
274
275



276
277
278





279
280
281
282

283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311





312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340







341
342
343


344
345
346
347
348
349
350








351




352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378





























379
380
381
382
383
384
385


386
387
388
389
390

391
392
393
394
395
396
397



398
399
400
401
402
403
404

405
406
407

408
409
410
411
412
413
414

415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433


















434
435
436
437
438
439
440
441





442
443
444
445
446
447
448
449
450
451
452
453
454
455


456
457
458
459
460











461

462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477


478
479
480

481
482
483

484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511















512
513
514


515
516
517
518
519
520
521
522
523

524
525
526

527
528
273
274
275
276
277
278
279

280




281

282

283



284
285
286
287
288

289
290
291
292
293
294
295


296

























297
298
299
300
301
302
303
304
305
306
307
308
309
310
311























312
313
314
315
316
317
318
319


320
321







322
323
324
325
326
327
328
329
330
331
332
333
334



























335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363

364
365
366
367


368
369
370
371
372
373

374
375
376
377
378



379
380
381
382
383


384
385

386
387
388

389
390
391
392
393
394
395

396
397


















398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418





419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435


436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453

454
455
456
457
458
459
460
461
462
463
464
465
466
467
468


469
470



471
472
473

474

475
476
477
478
479
480
481
482
483
484
485
486















487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502


503
504
505
506
507
508
509
510
511
512

513
514
515

516
517
518







-

-
-
-
-

-
+
-

-
-
-
+
+
+


-
+
+
+
+
+


-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-




+
+
+
+
+






-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+

+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-




-
-
+
+




-
+




-
-
-
+
+
+


-
-


-
+


-
+






-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
-
-
-
-
+
+
+
+
+












-
-
+
+





+
+
+
+
+
+
+
+
+
+
+
-
+














-
-
+
+
-
-
-
+


-
+
-












-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
+
+








-
+


-
+


      exit 1
    fi

    if test -z "$dst_arg"; then
      echo "$0: no destination specified." >&2
      exit 1
    fi

    dst=$dst_arg
    # Protect names starting with `-'.
    case $dst in
      -*) dst=./$dst;;
    esac

    # If destination is a directory, append the input filename; won't work
    # If destination is a directory, append the input filename.
    # if double slashes aren't ignored.
    if test -d "$dst"; then
      if test -n "$no_target_directory"; then
	echo "$0: $dst_arg: Is a directory" >&2
	exit 1
      if test "$is_target_a_directory" = never; then
        echo "$0: $dst_arg: Is a directory" >&2
        exit 1
      fi
      dstdir=$dst
      dst=$dstdir/`basename "$src"`
      dstbase=`basename "$src"`
      case $dst in
	*/) dst=$dst$dstbase;;
	*)  dst=$dst/$dstbase;;
      esac
      dstdir_status=0
    else
      # Prefer dirname, but fall back on a substitute if dirname fails.
      dstdir=`
      dstdir=`dirname "$dst"`
	(dirname "$dst") 2>/dev/null ||
	expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
	     X"$dst" : 'X\(//\)[^/]' \| \
	     X"$dst" : 'X\(//\)$' \| \
	     X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
	echo X"$dst" |
	    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
		   s//\1/
		   q
		 }
		 /^X\(\/\/\)[^/].*/{
		   s//\1/
		   q
		 }
		 /^X\(\/\/\)$/{
		   s//\1/
		   q
		 }
		 /^X\(\/\).*/{
		   s//\1/
		   q
		 }
		 s/.*/./; q'
      `

      test -d "$dstdir"
      dstdir_status=$?
    fi
  fi

  case $dstdir in
    */) dstdirslash=$dstdir;;
    *)  dstdirslash=$dstdir/;;
  esac

  obsolete_mkdir_used=false

  if test $dstdir_status != 0; then
    case $posix_mkdir in
      '')
	# Create intermediate dirs using mode 755 as modified by the umask.
	# This is like FreeBSD 'install' as of 1997-10-28.
	umask=`umask`
	case $stripcmd.$umask in
	  # Optimize common cases.
	  *[2367][2367]) mkdir_umask=$umask;;
	  .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;

	  *[0-7])
	    mkdir_umask=`expr $umask + 22 \
	      - $umask % 100 % 40 + $umask % 20 \
	      - $umask % 10 % 4 + $umask % 2
	    `;;
	  *) mkdir_umask=$umask,go-w;;
	esac

	# With -d, create the new directory with the user-specified mode.
	# Otherwise, rely on $mkdir_umask.
	if test -n "$dir_arg"; then
	  mkdir_mode=-m$mode
	else
	  mkdir_mode=
	fi
        # With -d, create the new directory with the user-specified mode.
        # Otherwise, rely on $mkdir_umask.
        if test -n "$dir_arg"; then
          mkdir_mode=-m$mode
        else
          mkdir_mode=
        fi

	posix_mkdir=false
	case $umask in
        posix_mkdir=false
	# The $RANDOM variable is not portable (e.g., dash).  Use it
	  *[123567][0-7][0-7])
	    # POSIX mkdir -p sets u+wx bits regardless of umask, which
	    # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
	    ;;
	  *)
	    tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
	    trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
	# here however when possible just to lower collision chance.
	tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$

	trap '
	  ret=$?
	  rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null
	  exit $ret
	' 0

	# Because "mkdir -p" follows existing symlinks and we likely work
	# directly in world-writeable /tmp, make sure that the '$tmpdir'
	# directory is successfully created first before we actually test
	# 'mkdir -p'.
	    if (umask $mkdir_umask &&
		exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
	    then
	      if test -z "$dir_arg" || {
		   # Check for POSIX incompatibilities with -m.
		   # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
		   # other-writeable bit of parent directory when it shouldn't.
		   # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
		   ls_ld_tmpdir=`ls -ld "$tmpdir"`
		   case $ls_ld_tmpdir in
		     d????-?r-*) different_mode=700;;
		     d????-?--*) different_mode=755;;
		     *) false;;
		   esac &&
		   $mkdirprog -m$different_mode -p -- "$tmpdir" && {
		     ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
		     test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
		   }
		 }
	      then posix_mkdir=:
	      fi
	      rmdir "$tmpdir/d" "$tmpdir"
	    else
	      # Remove any dirs left behind by ancient mkdir implementations.
	      rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
	    fi
	    trap '' 0;;
	if (umask $mkdir_umask &&
	    $mkdirprog $mkdir_mode "$tmpdir" &&
	    exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
	then
	  if test -z "$dir_arg" || {
	       # Check for POSIX incompatibilities with -m.
	       # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
	       # other-writable bit of parent directory when it shouldn't.
	       # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
	       test_tmpdir="$tmpdir/a"
	       ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
	       case $ls_ld_tmpdir in
		 d????-?r-*) different_mode=700;;
		 d????-?--*) different_mode=755;;
		 *) false;;
	       esac &&
	       $mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
		 ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
		 test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
	       }
	     }
	  then posix_mkdir=:
	  fi
	  rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
	else
	  # Remove any dirs left behind by ancient mkdir implementations.
	  rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
	fi
	trap '' 0;;
	esac;;
    esac

    if
      $posix_mkdir && (
	umask $mkdir_umask &&
	$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
        umask $mkdir_umask &&
        $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
      )
    then :
    else

      # The umask is ridiculous, or mkdir does not conform to POSIX,
      # mkdir does not conform to POSIX,
      # or it failed possibly due to a race condition.  Create the
      # directory the slow way, step by step, checking for races as we go.

      case $dstdir in
	/*) prefix='/';;
	-*) prefix='./';;
	*)  prefix='';;
        /*) prefix='/';;
        [-=\(\)!]*) prefix='./';;
        *)  prefix='';;
      esac

      eval "$initialize_posix_glob"

      oIFS=$IFS
      IFS=/
      $posix_glob set -f
      set -f
      set fnord $dstdir
      shift
      $posix_glob set +f
      set +f
      IFS=$oIFS

      prefixes=

      for d
      do
	test -z "$d" && continue
        test X"$d" = X && continue

	prefix=$prefix$d
	if test -d "$prefix"; then
	  prefixes=
	else
	  if $posix_mkdir; then
	    (umask=$mkdir_umask &&
	     $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
	    # Don't fail if two instances are running concurrently.
	    test -d "$prefix" || exit 1
	  else
	    case $prefix in
	      *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
	      *) qprefix=$prefix;;
	    esac
	    prefixes="$prefixes '$qprefix'"
	  fi
	fi
	prefix=$prefix/
        prefix=$prefix$d
        if test -d "$prefix"; then
          prefixes=
        else
          if $posix_mkdir; then
            (umask $mkdir_umask &&
             $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
            # Don't fail if two instances are running concurrently.
            test -d "$prefix" || exit 1
          else
            case $prefix in
              *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
              *) qprefix=$prefix;;
            esac
            prefixes="$prefixes '$qprefix'"
          fi
        fi
        prefix=$prefix/
      done

      if test -n "$prefixes"; then
	# Don't fail if two instances are running concurrently.
	(umask $mkdir_umask &&
	 eval "\$doit_exec \$mkdirprog $prefixes") ||
	  test -d "$dstdir" || exit 1
	obsolete_mkdir_used=true
        # Don't fail if two instances are running concurrently.
        (umask $mkdir_umask &&
         eval "\$doit_exec \$mkdirprog $prefixes") ||
          test -d "$dstdir" || exit 1
        obsolete_mkdir_used=true
      fi
    fi
  fi

  if test -n "$dir_arg"; then
    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
  else

    # Make a couple of temp file names in the proper directory.
    dsttmp=$dstdir/_inst.$$_
    rmtmp=$dstdir/_rm.$$_
    dsttmp=${dstdirslash}_inst.$$_
    rmtmp=${dstdirslash}_rm.$$_

    # Trap to clean up those temp files at exit.
    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0

    # Copy the file name to the temp name.
    (umask $cp_umask &&
     { test -z "$stripcmd" || {
	 # Create $dsttmp read-write so that cp doesn't create it read-only,
	 # which would cause strip to fail.
	 if test -z "$doit"; then
	   : >"$dsttmp" # No need to fork-exec 'touch'.
	 else
	   $doit touch "$dsttmp"
	 fi
       }
     } &&
    (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
     $doit_exec $cpprog "$src" "$dsttmp") &&

    # and set any options; do chmod last to preserve setuid bits.
    #
    # If any of these fail, we abort the whole thing.  If we want to
    # ignore errors from any of these, just make sure not to ignore
    # errors from the above "$doit $cpprog $src $dsttmp" command.
    #
    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&

    # If -C, don't bother to copy if it wouldn't change the file.
    if $copy_on_change &&
       old=`LC_ALL=C ls -dlL "$dst"	2>/dev/null` &&
       new=`LC_ALL=C ls -dlL "$dsttmp"	2>/dev/null` &&
       old=`LC_ALL=C ls -dlL "$dst"     2>/dev/null` &&
       new=`LC_ALL=C ls -dlL "$dsttmp"  2>/dev/null` &&

       eval "$initialize_posix_glob" &&
       $posix_glob set -f &&
       set -f &&
       set X $old && old=:$2:$4:$5:$6 &&
       set X $new && new=:$2:$4:$5:$6 &&
       $posix_glob set +f &&
       set +f &&

       test "$old" = "$new" &&
       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
    then
      rm -f "$dsttmp"
    else
      # Rename the file to the real destination.
      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||

      # The rename failed, perhaps because mv can't rename something else
      # to itself, or perhaps because mv is so ancient that it does not
      # support -f.
      {
	# Now remove or move aside any old file at destination location.
	# We try this two ways since rm can't unlink itself on some
	# systems and the destination file might be busy for other
	# reasons.  In this case, the final cleanup might fail but the new
	# file should still install successfully.
	{
	  test ! -f "$dst" ||
	  $doit $rmcmd -f "$dst" 2>/dev/null ||
	  { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
	    { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
	  } ||
	  { echo "$0: cannot unlink or rename $dst" >&2
	    (exit 1); exit 1
	  }
	} &&
        # Now remove or move aside any old file at destination location.
        # We try this two ways since rm can't unlink itself on some
        # systems and the destination file might be busy for other
        # reasons.  In this case, the final cleanup might fail but the new
        # file should still install successfully.
        {
          test ! -f "$dst" ||
          $doit $rmcmd -f "$dst" 2>/dev/null ||
          { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
            { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
          } ||
          { echo "$0: cannot unlink or rename $dst" >&2
            (exit 1); exit 1
          }
        } &&

	# Now rename the file to the real destination.
	$doit $mvcmd "$dsttmp" "$dst"
        # Now rename the file to the real destination.
        $doit $mvcmd "$dsttmp" "$dst"
      }
    fi || exit 1

    trap '' 0
  fi
done

# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC"
# End:
Changes to unix/installManPage.
39
40
41
42
43
44
45
46

47
48
49
50
51
52
53
39
40
41
42
43
44
45

46
47
48
49
50
51
52
53







-
+








ManPage=$1
Dir=$2
if test -f $ManPage ; then : ; else
    echo "source manual page file must exist"
    exit 1
fi
if test -d $Dir ; then : ; else
if test -d "$Dir" ; then : ; else
    echo "target directory must exist"
    exit 1
fi
test -z "$SymOrLoc" && SymOrLoc="$Dir/"

########################################################################
### Extract Target Names from Manual Page
95
96
97
98
99
100
101
102

103
104
105
106
107
108
109
110
111
112

113
114
115
116
117
118



119
120

121
122
123
124
125
95
96
97
98
99
100
101

102
103
104
105
106
107
108
109
110
111

112
113
114
115



116
117
118
119

120
121
122
123
124
125







-
+









-
+



-
-
-
+
+
+

-
+





Name=`basename $ManPage .$Section`
SrcDir=`dirname $ManPage`

########################################################################
### Process Page to Create Target Pages
###

Specials="FindPhoto FontId MeasureChar"
Specials="DString Thread Notifier RegExp library packagens pkgMkIndex safesock FindPhoto FontId MeasureChar"
for n in $Specials; do
    if [ "$Name" = "$n" ] ; then
	Names="$n $Names"
    fi
done

First=""
for Target in $Names; do
    Target=$Target.$Section$Suffix
    rm -f $Dir/$Target $Dir/$Target.*
    rm -f "$Dir/$Target" "$Dir/$Target.*"
    if test -z "$First" ; then
	First=$Target
	sed -e "/man\.macros/r $SrcDir/man.macros" -e "/man\.macros/d" \
	    $ManPage > $Dir/$First
	chmod 644 $Dir/$First
	$Gzip $Dir/$First
	    $ManPage > "$Dir/$First"
	chmod 644 "$Dir/$First"
	$Gzip "$Dir/$First"
    else
	ln $SymOrLoc$First$Gz $Dir/$Target$Gz
	ln $SymOrLoc"$First$Gz" "$Dir/$Target$Gz"
    fi
done

########################################################################
exit 0
Changes to unix/tcl.m4.
24
25
26
27
28
29
30
31

32
33

34
35
36
37
38
39
40
24
25
26
27
28
29
30

31
32

33
34
35
36
37
38
39
40







-
+

-
+







    # the alternative search directory is invoked by --with-tcl
    #

    if test x"${no_tcl}" = x ; then
	# we reset no_tcl in case something fails here
	no_tcl=true
	AC_ARG_WITH(tcl,
	    AC_HELP_STRING([--with-tcl],
	    AS_HELP_STRING([--with-tcl],
		[directory containing tcl configuration (tclConfig.sh)]),
	    with_tclconfig="${withval}")
	    [with_tclconfig="${withval}"])
	AC_MSG_CHECKING([for Tcl configuration])
	AC_CACHE_VAL(ac_cv_c_tclconfig,[

	    # First check to see if --with-tcl was specified.
	    if test x"${with_tclconfig}" != x ; then
		case "${with_tclconfig}" in
		    */tclConfig.sh )
89
90
91
92
93
94
95
96

97
98
99
100


101
102
103
104
105
106
107
89
90
91
92
93
94
95

96
97
98


99
100
101
102
103
104
105
106
107







-
+


-
-
+
+







	    if test x"${ac_cv_c_tclconfig}" = x ; then
		for i in `ls -d ${libdir} 2>/dev/null` \
			`ls -d ${exec_prefix}/lib 2>/dev/null` \
			`ls -d ${prefix}/lib 2>/dev/null` \
			`ls -d /usr/local/lib 2>/dev/null` \
			`ls -d /usr/contrib/lib 2>/dev/null` \
			`ls -d /usr/pkg/lib 2>/dev/null` \
			`ls -d /usr/lib/tcl8.6 2>/dev/null` \
			`ls -d /usr/lib/tcl8.7 2>/dev/null` \
			`ls -d /usr/lib 2>/dev/null` \
			`ls -d /usr/lib64 2>/dev/null` \
			`ls -d /usr/local/lib/tcl8.6 2>/dev/null` \
			`ls -d /usr/local/lib/tcl/tcl8.6 2>/dev/null` \
			`ls -d /usr/local/lib/tcl8.7 2>/dev/null` \
			`ls -d /usr/local/lib/tcl/tcl8.7 2>/dev/null` \
			; do
		    if test -f "$i/tclConfig.sh" ; then
			ac_cv_c_tclconfig="`(cd $i; pwd)`"
			break
		    fi
		done
	    fi
157
158
159
160
161
162
163
164

165
166

167
168
169
170
171
172
173
157
158
159
160
161
162
163

164
165

166
167
168
169
170
171
172
173







-
+

-
+







    # the alternative search directory is invoked by --with-tk
    #

    if test x"${no_tk}" = x ; then
	# we reset no_tk in case something fails here
	no_tk=true
	AC_ARG_WITH(tk,
	    AC_HELP_STRING([--with-tk],
	    AS_HELP_STRING([--with-tk],
		[directory containing tk configuration (tkConfig.sh)]),
	    with_tkconfig="${withval}")
	    [with_tkconfig="${withval}"])
	AC_MSG_CHECKING([for Tk configuration])
	AC_CACHE_VAL(ac_cv_c_tkconfig,[

	    # First check to see if --with-tkconfig was specified.
	    if test x"${with_tkconfig}" != x ; then
		case "${with_tkconfig}" in
		    */tkConfig.sh )
222
223
224
225
226
227
228
229

230
231
232
233


234
235
236
237
238
239
240
222
223
224
225
226
227
228

229
230
231


232
233
234
235
236
237
238
239
240







-
+


-
-
+
+







	    if test x"${ac_cv_c_tkconfig}" = x ; then
		for i in `ls -d ${libdir} 2>/dev/null` \
			`ls -d ${exec_prefix}/lib 2>/dev/null` \
			`ls -d ${prefix}/lib 2>/dev/null` \
			`ls -d /usr/local/lib 2>/dev/null` \
			`ls -d /usr/contrib/lib 2>/dev/null` \
			`ls -d /usr/pkg/lib 2>/dev/null` \
			`ls -d /usr/lib/tk8.6 2>/dev/null` \
			`ls -d /usr/lib/tk8.7 2>/dev/null` \
			`ls -d /usr/lib 2>/dev/null` \
			`ls -d /usr/lib64 2>/dev/null` \
			`ls -d /usr/local/lib/tk8.6 2>/dev/null` \
			`ls -d /usr/local/lib/tcl/tk8.6 2>/dev/null` \
			`ls -d /usr/local/lib/tk8.7 2>/dev/null` \
			`ls -d /usr/local/lib/tcl/tk8.7 2>/dev/null` \
			; do
		    if test -f "$i/tkConfig.sh" ; then
			ac_cv_c_tkconfig="`(cd $i; pwd)`"
			break
		    fi
		done
	    fi
504
505
506
507
508
509
510
511

512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529

530
531
532
533
534
535
536
504
505
506
507
508
509
510

511
512
513








514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529







-
+


-
-
-
-
-
-
-
-








+







#	Sets the following vars:
#		SHARED_BUILD	Value of 1 or 0
#------------------------------------------------------------------------

AC_DEFUN([SC_ENABLE_SHARED], [
    AC_MSG_CHECKING([how to build libraries])
    AC_ARG_ENABLE(shared,
	AC_HELP_STRING([--enable-shared],
	AS_HELP_STRING([--enable-shared],
	    [build and link with shared libraries (default: on)]),
	[tcl_ok=$enableval], [tcl_ok=yes])

    if test "${enable_shared+set}" = set; then
	enableval="$enable_shared"
	tcl_ok=$enableval
    else
	tcl_ok=yes
    fi

    if test "$tcl_ok" = "yes" ; then
	AC_MSG_RESULT([shared])
	SHARED_BUILD=1
    else
	AC_MSG_RESULT([static])
	SHARED_BUILD=0
	AC_DEFINE(STATIC_BUILD, 1, [Is this a static build?])
    fi
    AC_SUBST(SHARED_BUILD)
])

#------------------------------------------------------------------------
# SC_ENABLE_FRAMEWORK --
#
#	Allows the building of shared libraries into frameworks
#
546
547
548
549
550
551
552
553

554
555
556
557
558
559
560
539
540
541
542
543
544
545

546
547
548
549
550
551
552
553







-
+







#		FRAMEWORK_BUILD	Value of 1 or 0
#------------------------------------------------------------------------

AC_DEFUN([SC_ENABLE_FRAMEWORK], [
    if test "`uname -s`" = "Darwin" ; then
	AC_MSG_CHECKING([how to package libraries])
	AC_ARG_ENABLE(framework,
	    AC_HELP_STRING([--enable-framework],
	    AS_HELP_STRING([--enable-framework],
		[package shared libraries in MacOSX frameworks (default: off)]),
	    [enable_framework=$enableval], [enable_framework=no])
	if test $enable_framework = yes; then
	    if test $SHARED_BUILD = 0; then
		AC_MSG_WARN([Frameworks can only be built if --enable-shared is yes])
		enable_framework=no
	    fi
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
566
567
568
569
570
571
572











































































































573
574
575
576
577
578
579







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







		AC_MSG_RESULT([static library])
	    fi
	    FRAMEWORK_BUILD=0
	fi
    fi
])

#------------------------------------------------------------------------
# SC_ENABLE_THREADS --
#
#	Specify if thread support should be enabled
#
# Arguments:
#	none
#
# Results:
#
#	Adds the following arguments to configure:
#		--enable-threads
#
#	Sets the following vars:
#		THREADS_LIBS	Thread library(s)
#
#	Defines the following vars:
#		TCL_THREADS
#		_REENTRANT
#		_THREAD_SAFE
#------------------------------------------------------------------------

AC_DEFUN([SC_ENABLE_THREADS], [
    AC_ARG_ENABLE(threads,
	AC_HELP_STRING([--enable-threads],
	    [build with threads (default: on)]),
	[tcl_ok=$enableval], [tcl_ok=yes])

    if test "${TCL_THREADS}" = 1; then
	tcl_threaded_core=1;
    fi

    if test "$tcl_ok" = "yes" -o "${TCL_THREADS}" = 1; then
	TCL_THREADS=1
	# USE_THREAD_ALLOC tells us to try the special thread-based
	# allocator that significantly reduces lock contention
	AC_DEFINE(USE_THREAD_ALLOC, 1,
	    [Do we want to use the threaded memory allocator?])
	AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?])
	if test "`uname -s`" = "SunOS" ; then
	    AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1,
		    [Do we really want to follow the standard? Yes we do!])
	fi
	AC_DEFINE(_THREAD_SAFE, 1, [Do we want the thread-safe OS API?])
	AC_CHECK_LIB(pthread,pthread_mutex_init,tcl_ok=yes,tcl_ok=no)
	if test "$tcl_ok" = "no"; then
	    # Check a little harder for __pthread_mutex_init in the same
	    # library, as some systems hide it there until pthread.h is
	    # defined.  We could alternatively do an AC_TRY_COMPILE with
	    # pthread.h, but that will work with libpthread really doesn't
	    # exist, like AIX 4.2.  [Bug: 4359]
	    AC_CHECK_LIB(pthread, __pthread_mutex_init,
		tcl_ok=yes, tcl_ok=no)
	fi

	if test "$tcl_ok" = "yes"; then
	    # The space is needed
	    THREADS_LIBS=" -lpthread"
	else
	    AC_CHECK_LIB(pthreads, pthread_mutex_init,
		tcl_ok=yes, tcl_ok=no)
	    if test "$tcl_ok" = "yes"; then
		# The space is needed
		THREADS_LIBS=" -lpthreads"
	    else
		AC_CHECK_LIB(c, pthread_mutex_init,
		    tcl_ok=yes, tcl_ok=no)
		if test "$tcl_ok" = "no"; then
		    AC_CHECK_LIB(c_r, pthread_mutex_init,
			tcl_ok=yes, tcl_ok=no)
		    if test "$tcl_ok" = "yes"; then
			# The space is needed
			THREADS_LIBS=" -pthread"
		    else
			TCL_THREADS=0
			AC_MSG_WARN([Don't know how to find pthread lib on your system - you must disable thread support or edit the LIBS in the Makefile...])
		    fi
		fi
	    fi
	fi

	# Does the pthread-implementation provide
	# 'pthread_attr_setstacksize' ?

	ac_saved_libs=$LIBS
	LIBS="$LIBS $THREADS_LIBS"
	AC_CHECK_FUNCS(pthread_attr_setstacksize pthread_atfork)
	LIBS=$ac_saved_libs
    else
	TCL_THREADS=0
    fi
    # Do checking message here to not mess up interleaved configure output
    AC_MSG_CHECKING([for building with threads])
    if test "${TCL_THREADS}" = 1; then
	AC_DEFINE(TCL_THREADS, 1, [Are we building with threads enabled?])
	if test "${tcl_threaded_core}" = 1; then
	    AC_MSG_RESULT([yes (threaded core)])
	else
	    AC_MSG_RESULT([yes])
	fi
    else
	AC_MSG_RESULT([no])
    fi

    AC_SUBST(TCL_THREADS)
])

#------------------------------------------------------------------------
# SC_ENABLE_SYMBOLS --
#
#	Specify if debugging symbols should be used.
#	Memory (TCL_MEM_DEBUG) and compile (TCL_COMPILE_DEBUG) debugging
#	can also be enabled.
#
711
712
713
714
715
716
717
718

719
720
721
722
723
724
725
597
598
599
600
601
602
603

604
605
606
607
608
609
610
611







-
+







#		LDFLAGS_DEFAULT	Sets to $(LDFLAGS_DEBUG) if true
#				Sets to $(LDFLAGS_OPTIMIZE) if false
#------------------------------------------------------------------------

AC_DEFUN([SC_ENABLE_SYMBOLS], [
    AC_MSG_CHECKING([for build with symbols])
    AC_ARG_ENABLE(symbols,
	AC_HELP_STRING([--enable-symbols],
	AS_HELP_STRING([--enable-symbols],
	    [build with debugging symbols (default: off)]),
	[tcl_ok=$enableval], [tcl_ok=no])
# FIXME: Currently, LDFLAGS_DEFAULT is not used, it should work like CFLAGS_DEFAULT.
    if test "$tcl_ok" = "no"; then
	CFLAGS_DEFAULT='$(CFLAGS_OPTIMIZE)'
	LDFLAGS_DEFAULT='$(LDFLAGS_OPTIMIZE)'
	AC_DEFINE(NDEBUG, 1, [Is no debugging enabled?])
770
771
772
773
774
775
776
777

778
779
780
781
782
783
784
656
657
658
659
660
661
662

663
664
665
666
667
668
669
670







-
+







#
#	Defines the following vars:
#		HAVE_LANGINFO	Triggers use of nl_langinfo if defined.
#------------------------------------------------------------------------

AC_DEFUN([SC_ENABLE_LANGINFO], [
    AC_ARG_ENABLE(langinfo,
	AC_HELP_STRING([--enable-langinfo],
	AS_HELP_STRING([--enable-langinfo],
	    [use nl_langinfo if possible to determine encoding at startup, otherwise use old heuristic (default: on)]),
	[langinfo_ok=$enableval], [langinfo_ok=yes])

    HAVE_LANGINFO=0
    if test "$langinfo_ok" = "yes"; then
	AC_CHECK_HEADER(langinfo.h,[langinfo_ok=yes],[langinfo_ok=no])
    fi
822
823
824
825
826
827
828
829

830
831
832


833
834
835
836
837

838
839
840
841
842
843
844

845
846
847
848
849
850
851
852
853
854
855
856
857
858

859
860
861
862
863
864
865

866
867
868
869
870
871
872
873
874
875
876

877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892


893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
708
709
710
711
712
713
714

715
716


717
718
719
720
721
722

723
724
725
726
727
728
729

730
731
732
733
734
735
736
737
738
739
740
741
742
743

744
745
746
747
748
749
750

751
752
753
754
755
756
757
758
759
760
761

762

763
764
765
766
767
768
769
770

771
772
773
774


775
776
777
778
779
780
781
782






783
784
785
786
787
788
789







-
+

-
-
+
+




-
+






-
+













-
+






-
+










-
+
-








-




-
-
+
+






-
-
-
-
-
-







#			according to the user's selection.
#
#--------------------------------------------------------------------

AC_DEFUN([SC_CONFIG_MANPAGES], [
    AC_MSG_CHECKING([whether to use symlinks for manpages])
    AC_ARG_ENABLE(man-symlinks,
	AC_HELP_STRING([--enable-man-symlinks],
	AS_HELP_STRING([--enable-man-symlinks],
	    [use symlinks for the manpages (default: off)]),
	test "$enableval" != "no" && MAN_FLAGS="$MAN_FLAGS --symlinks",
	enableval="no")
	[test "$enableval" != "no" && MAN_FLAGS="$MAN_FLAGS --symlinks"],
	[enableval="no"])
    AC_MSG_RESULT([$enableval])

    AC_MSG_CHECKING([whether to compress the manpages])
    AC_ARG_ENABLE(man-compression,
	AC_HELP_STRING([--enable-man-compression=PROG],
	AS_HELP_STRING([--enable-man-compression=PROG],
	    [compress the manpages with PROG (default: off)]),
	[case $enableval in
	    yes) AC_MSG_ERROR([missing argument to --enable-man-compression]);;
	    no)  ;;
	    *)   MAN_FLAGS="$MAN_FLAGS --compress $enableval";;
	esac],
	enableval="no")
	[enableval="no"])
    AC_MSG_RESULT([$enableval])
    if test "$enableval" != "no"; then
	AC_MSG_CHECKING([for compressed file suffix])
	touch TeST
	$enableval TeST
	Z=`ls TeST* | sed 's/^....//'`
	rm -f TeST*
	MAN_FLAGS="$MAN_FLAGS --extension $Z"
	AC_MSG_RESULT([$Z])
    fi

    AC_MSG_CHECKING([whether to add a package name suffix for the manpages])
    AC_ARG_ENABLE(man-suffix,
	AC_HELP_STRING([--enable-man-suffix=STRING],
	AS_HELP_STRING([--enable-man-suffix=STRING],
	    [use STRING as a suffix to manpage file names (default: no, AC_PACKAGE_NAME if enabled without specifying STRING)]),
	[case $enableval in
	    yes) enableval="AC_PACKAGE_NAME" MAN_FLAGS="$MAN_FLAGS --suffix $enableval";;
	    no)  ;;
	    *)   MAN_FLAGS="$MAN_FLAGS --suffix $enableval";;
	esac],
	enableval="no")
	[enableval="no"])
    AC_MSG_RESULT([$enableval])

    AC_SUBST(MAN_FLAGS)
])

#--------------------------------------------------------------------
# SC_CONFIG_SYSTEM
#
#	Determine what the system is (some things cannot be easily checked
#	on a feature-driven basis, alas). This can usually be done via the
#	"uname" command, but there are a few systems, like Next, where
#	"uname" command.
#	this doesn't work.
#
# Arguments:
#	none
#
# Results:
#	Defines the following var:
#
#	system -	System/platform/version identification code.
#
#--------------------------------------------------------------------

AC_DEFUN([SC_CONFIG_SYSTEM], [
    AC_CACHE_CHECK([system version], tcl_cv_sys_version, [
	if test -f /usr/lib/NextStep/software_version; then
	    tcl_cv_sys_version=NEXTSTEP-`awk '/3/,/3/' /usr/lib/NextStep/software_version`
	if test "${TEA_PLATFORM}" = "windows" ; then
	    tcl_cv_sys_version=windows
	else
	    tcl_cv_sys_version=`uname -s`-`uname -r`
	    if test "$?" -ne 0 ; then
		AC_MSG_WARN([can't find uname command])
		tcl_cv_sys_version=unknown
	    else
		# Special check for weird MP-RAS system (uname returns weird
		# results, and the version is kept in special file).

		if test -r /etc/.relid -a "X`uname -n`" = "X`uname -s`" ; then
		    tcl_cv_sys_version=MP-RAS-`awk '{print $[3]}' /etc/.relid`
		fi
		if test "`uname -s`" = "AIX" ; then
		    tcl_cv_sys_version=AIX-`uname -v`.`uname -r`
		fi
		if test "`uname -s`" = "NetBSD" -a -f /etc/debian_version ; then
		    tcl_cv_sys_version=NetBSD-Debian
		fi
	    fi
960
961
962
963
964
965
966
967
968


969
970
971
972
973
974
975
838
839
840
841
842
843
844


845
846
847
848
849
850
851
852
853







-
-
+
+







#                       into a shared library.
#       SHLIB_LD_LIBS - Dependent libraries for the linker to scan when
#                       creating shared libraries.  This symbol typically
#                       goes at the end of the "ld" commands that build
#                       shared libraries. The value of the symbol defaults to
#                       "${LIBS}" if all of the dependent libraries should
#                       be specified when creating a shared library.  If
#                       dependent libraries should not be specified (as on
#                       SunOS 4.x, where they cause the link to fail, or in
#                       dependent libraries should not be specified (as on some
#                       SunOS systems, where they cause the link to fail, or in
#                       general if Tcl and Tk aren't themselves shared
#                       libraries), then this symbol has an empty string
#                       as its value.
#       SHLIB_SUFFIX -  Suffix to use for the names of dynamically loadable
#                       extensions.  An empty string means we don't know how
#                       to use shared libraries on this platform.
# TCL_SHLIB_LD_EXTRAS - Additional element which are added to SHLIB_LD_LIBS
1002
1003
1004
1005
1006
1007
1008
1009

1010
1011
1012
1013
1014
1015
1016
1017
1018

1019
1020
1021
1022
1023
1024
1025
880
881
882
883
884
885
886

887
888
889
890
891
892
893
894
895

896
897
898
899
900
901
902
903







-
+








-
+








AC_DEFUN([SC_CONFIG_CFLAGS], [

    # Step 0.a: Enable 64 bit support?

    AC_MSG_CHECKING([if 64bit support is requested])
    AC_ARG_ENABLE(64bit,
	AC_HELP_STRING([--enable-64bit],
	AS_HELP_STRING([--enable-64bit],
	    [enable 64bit support (default: off)]),
	[do64bit=$enableval], [do64bit=no])
    AC_MSG_RESULT([$do64bit])

    # Step 0.b: Enable Solaris 64 bit VIS support?

    AC_MSG_CHECKING([if 64bit Sparc VIS support is requested])
    AC_ARG_ENABLE(64bit-vis,
	AC_HELP_STRING([--enable-64bit-vis],
	AS_HELP_STRING([--enable-64bit-vis],
	    [enable 64bit Sparc VIS support (default: off)]),
	[do64bitVIS=$enableval], [do64bitVIS=no])
    AC_MSG_RESULT([$do64bitVIS])
    # Force 64bit on with VIS
    AS_IF([test "$do64bitVIS" = "yes"], [do64bit=yes])

    # Step 0.c: Check if visibility support is available. Do this here so
1040
1041
1042
1043
1044
1045
1046
1047

1048
1049
1050
1051
1052
1053
1054
918
919
920
921
922
923
924

925
926
927
928
929
930
931
932







-
+







	AC_DEFINE(HAVE_HIDDEN, [1], [Compiler support for module scope symbols])
    ])

    # Step 0.d: Disable -rpath support?

    AC_MSG_CHECKING([if rpath support is requested])
    AC_ARG_ENABLE(rpath,
	AC_HELP_STRING([--disable-rpath],
	AS_HELP_STRING([--disable-rpath],
	    [disable rpath support (default: on)]),
	[doRpath=$enableval], [doRpath=yes])
    AC_MSG_RESULT([$doRpath])

    # Step 1: set the variable "system" to hold the name and version number
    # for the system.

1076
1077
1078
1079
1080
1081
1082
1083









1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094

1095
1096
1097

1098
1099
1100
1101
1102
1103
1104
954
955
956
957
958
959
960

961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979

980
981
982

983
984
985
986
987
988
989
990







-
+
+
+
+
+
+
+
+
+










-
+


-
+







    UNSHARED_LIB_SUFFIX=""
    TCL_TRIM_DOTS='`echo ${VERSION} | tr -d .`'
    ECHO_VERSION='`echo ${VERSION}`'
    TCL_LIB_VERSIONS_OK=ok
    CFLAGS_DEBUG=-g
    AS_IF([test "$GCC" = yes], [
	CFLAGS_OPTIMIZE=-O2
	CFLAGS_WARNING="-Wall"
	CFLAGS_WARNING="-Wall -Wextra -Wshadow -Wundef -Wwrite-strings -Wpointer-arith -finput-charset=UTF-8"
	case "${CC}" in
	    *++|*++-*)
		;;
	    *)
		CFLAGS_WARNING="${CFLAGS_WARNING} -Wc++-compat -fextended-identifiers -Wdeclaration-after-statement"
		;;
	esac

    ], [
	CFLAGS_OPTIMIZE=-O
	CFLAGS_WARNING=""
    ])
    AC_CHECK_TOOL(AR, ar)
    STLIB_LD='${AR} cr'
    LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH"
    PLAT_OBJS=""
    PLAT_SRCS=""
    LDAIX_SRC=""
    AS_IF([test "x${SHLIB_VERSION}" = x],[SHLIB_VERSION=".1.0"],[SHLIB_VERSION=".${SHLIB_VERSION}"])
    AS_IF([test "x${SHLIB_VERSION}" = x], [SHLIB_VERSION="1.0"])
    case $system in
	AIX-*)
	    AS_IF([test "${TCL_THREADS}" = "1" -a "$GCC" != "yes"], [
	    AS_IF([test "$GCC" != "yes"], [
		# AIX requires the _r compiler when gcc isn't being used
		case "${CC}" in
		    *_r|*_r\ *)
			# ok ...
			;;
		    *)
			# Make sure only first arg gets _r
1185
1186
1187
1188
1189
1190
1191
1192
1193


1194
1195
1196
1197
1198
1199
1200
1071
1072
1073
1074
1075
1076
1077


1078
1079
1080
1081
1082
1083
1084
1085
1086







-
-
+
+







	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS="-ldl"
	    LDFLAGS="$LDFLAGS -export-dynamic"
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    ;;
	CYGWIN_*|MINGW32*)
	    SHLIB_CFLAGS=""
	CYGWIN_*|MINGW32_*|MSYS_*)
	    SHLIB_CFLAGS="-fno-common"
	    SHLIB_LD='${CC} -shared'
	    SHLIB_SUFFIX=".dll"
	    DL_OBJS="tclLoadDl.o"
	    PLAT_OBJS='${CYGWIN_OBJS}'
	    PLAT_SRCS='${CYGWIN_SRCS}'
	    DL_LIBS="-ldl"
	    CC_SEARCH_FLAGS=""
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1097
1098
1099
1100
1101
1102
1103



1104
1105
1106
1107
1108
1109
1110







-
-
-







		], [],
		ac_cv_cygwin=no,
		ac_cv_cygwin=yes)
	    )
	    if test "$ac_cv_cygwin" = "no"; then
		AC_MSG_ERROR([${CC} is not a cygwin compiler.])
	    fi
	    if test "x${TCL_THREADS}" = "x0"; then
		AC_MSG_ERROR([CYGWIN compile is only supported with --enable-threads])
	    fi
	    do64bit_ok=yes
	    if test "x${SHARED_BUILD}" = "x1"; then
		echo "running cd ../win; ${CONFIG_SHELL-/bin/sh} ./configure $ac_configure_args"
		# The eval makes quoting arguments work.
		if cd ../win; eval ${CONFIG_SHELL-/bin/sh} ./configure $ac_configure_args; cd ../unix
		then :
		else
1285
1286
1287
1288
1289
1290
1291
1292

1293
1294
1295
1296
1297
1298
1299
1168
1169
1170
1171
1172
1173
1174

1175
1176
1177
1178
1179
1180
1181
1182







-
+







		AS_IF([test "$GCC" = yes], [
		    case `${CC} -dumpmachine` in
			hppa64*)
			    # 64-bit gcc in use.  Fix flags for GNU ld.
			    do64bit_ok=yes
			    SHLIB_LD='${CC} -shared'
			    AS_IF([test $doRpath = yes], [
				CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
				CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'])
			    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
			    ;;
			*)
			    AC_MSG_WARN([64bit mode not supported with GCC on $system])
			    ;;
		    esac
		], [
1320
1321
1322
1323
1324
1325
1326
1327

1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338

1339
1340
1341
1342
1343
1344
1345
1203
1204
1205
1206
1207
1208
1209

1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220

1221
1222
1223
1224
1225
1226
1227
1228







-
+










-
+







	    SHLIB_CFLAGS=""
	    SHLIB_LD="ld -shared -rdata_shared"
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS=""
	    AC_LIBOBJ(mkstemp)
	    AS_IF([test $doRpath = yes], [
		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
		CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'
		LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])
	    ;;
	IRIX-6.*)
	    SHLIB_CFLAGS=""
	    SHLIB_LD="ld -n32 -shared -rdata_shared"
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS=""
	    AC_LIBOBJ(mkstemp)
	    AS_IF([test $doRpath = yes], [
		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
		CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'
		LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])
	    AS_IF([test "$GCC" = yes], [
		CFLAGS="$CFLAGS -mabi=n32"
		LDFLAGS="$LDFLAGS -mabi=n32"
	    ], [
		case $system in
		    IRIX-6.3)
1357
1358
1359
1360
1361
1362
1363
1364

1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381

1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395

1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411

1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438


1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466

1467
1468

1469
1470
1471
1472
1473
1474
1475




1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490

1491
1492
1493
1494
1495
1496




1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509


1510
1511
1512
1513
1514




1515
1516
1517
1518
1519
1520
1521
1240
1241
1242
1243
1244
1245
1246

1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263

1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277

1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293

1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309












1310
1311











1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327

1328
1329

1330
1331
1332





1333
1334
1335
1336

1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349

1350
1351





1352
1353
1354
1355

1356
1357
1358

1359
1360
1361
1362
1363
1364


1365
1366





1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377







-
+
















-
+













-
+















-
+















-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
















-
+

-
+


-
-
-
-
-
+
+
+
+
-













-
+

-
-
-
-
-
+
+
+
+
-



-






-
-
+
+
-
-
-
-
-
+
+
+
+







	    SHLIB_CFLAGS=""
	    SHLIB_LD="ld -n32 -shared -rdata_shared"
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS=""
	    AC_LIBOBJ(mkstemp)
	    AS_IF([test $doRpath = yes], [
		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
		CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'
		LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])

	    # Check to enable 64-bit flags for compiler/linker

	    AS_IF([test "$do64bit" = yes], [
	        AS_IF([test "$GCC" = yes], [
	            AC_MSG_WARN([64bit mode not supported by gcc])
	        ], [
	            do64bit_ok=yes
	            SHLIB_LD="ld -64 -shared -rdata_shared"
	            CFLAGS="$CFLAGS -64"
	            LDFLAGS_ARCH="-64"
	        ])
	    ])
	    ;;
	Linux*|GNU*|NetBSD-Debian)
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_CFLAGS="-fPIC -fno-common"
	    SHLIB_SUFFIX=".so"

	    CFLAGS_OPTIMIZE="-O2"
	    # egcs-2.91.66 on Redhat Linux 6.0 generates lots of warnings
	    # when you inline the string and math operations.  Turn this off to
	    # get rid of the warnings.
	    #CFLAGS_OPTIMIZE="${CFLAGS_OPTIMIZE} -D__NO_STRING_INLINES -D__NO_MATH_INLINES"

	    SHLIB_LD='${CC} ${CFLAGS} ${LDFLAGS} -shared'
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS="-ldl"
	    LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
	    AS_IF([test $doRpath = yes], [
		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
		CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'])
	    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
	    AS_IF([test "`uname -m`" = "alpha"], [CFLAGS="$CFLAGS -mieee"])
	    AS_IF([test $do64bit = yes], [
		AC_CACHE_CHECK([if compiler accepts -m64 flag], tcl_cv_cc_m64, [
		    hold_cflags=$CFLAGS
		    CFLAGS="$CFLAGS -m64"
		    AC_TRY_LINK(,, tcl_cv_cc_m64=yes, tcl_cv_cc_m64=no)
		    CFLAGS=$hold_cflags])
		AS_IF([test $tcl_cv_cc_m64 = yes], [
		    CFLAGS="$CFLAGS -m64"
		    do64bit_ok=yes
		])
	   ])

	    # The combo of gcc + glibc has a bug related to inlining of
	    # functions like strtod(). The -fno-builtin flag should address
	    # functions like strtol()/strtoul(). The -fno-builtin flag should address
	    # this problem but it does not work. The -fno-inline flag is kind
	    # of overkill but it works. Disable inlining only when one of the
	    # files in compat/*.c is being linked in.

	    AS_IF([test x"${USE_COMPAT}" != x],[CFLAGS="$CFLAGS -fno-inline"])
	    ;;
	Lynx*)
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_SUFFIX=".so"
	    CFLAGS_OPTIMIZE=-02
	    SHLIB_LD='${CC} -shared'
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS="-mshared -ldl"
	    LD_FLAGS="-Wl,--export-dynamic"
	    AS_IF([test $doRpath = yes], [
		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
	    ;;
	MP-RAS-02*)
	    SHLIB_CFLAGS="-K PIC"
	    SHLIB_LD='${CC} -G'
	    SHLIB_LD_LIBS=""
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS="-ldl"
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
		CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'
		LD_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'])
	    ;;
	MP-RAS-*)
	    SHLIB_CFLAGS="-K PIC"
	    SHLIB_LD='${CC} -G'
	    SHLIB_LD_LIBS=""
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS="-ldl"
	    LDFLAGS="$LDFLAGS -Wl,-Bexport"
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    ;;
	OpenBSD-*)
	    arch=`arch -s`
	    case "$arch" in
	    alpha|sparc64)
		SHLIB_CFLAGS="-fPIC"
		;;
	    *)
		SHLIB_CFLAGS="-fpic"
		;;
	    esac
	    SHLIB_LD='${CC} ${SHLIB_CFLAGS} -shared'
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS=""
	    AS_IF([test $doRpath = yes], [
		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
		CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'])
	    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
	    SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so${SHLIB_VERSION}'
	    SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.${SHLIB_VERSION}'
	    LDFLAGS="-Wl,-export-dynamic"
	    CFLAGS_OPTIMIZE="-O2"
	    AS_IF([test "${TCL_THREADS}" = "1"], [
		# On OpenBSD:	Compile with -pthread
		#		Don't link with -lpthread
		LIBS=`echo $LIBS | sed s/-lpthread//`
		CFLAGS="$CFLAGS -pthread"
	    # On OpenBSD:	Compile with -pthread
	    #		Don't link with -lpthread
	    LIBS=`echo $LIBS | sed s/-lpthread//`
	    CFLAGS="$CFLAGS -pthread"
	    ])
	    # OpenBSD doesn't do version numbers with dots.
	    UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
	    TCL_LIB_VERSIONS_OK=nodots
	    ;;
	NetBSD-*)
	    # NetBSD has ELF and can use 'cc -shared' to build shared libs
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_LD='${CC} ${SHLIB_CFLAGS} -shared'
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS=""
	    LDFLAGS="$LDFLAGS -export-dynamic"
	    AS_IF([test $doRpath = yes], [
		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
		CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'])
	    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
	    AS_IF([test "${TCL_THREADS}" = "1"], [
		# The -pthread needs to go in the CFLAGS, not LIBS
		LIBS=`echo $LIBS | sed s/-pthread//`
		CFLAGS="$CFLAGS -pthread"
	    	LDFLAGS="$LDFLAGS -pthread"
	    # The -pthread needs to go in the CFLAGS, not LIBS
	    LIBS=`echo $LIBS | sed s/-pthread//`
	    CFLAGS="$CFLAGS -pthread"
	    LDFLAGS="$LDFLAGS -pthread"
	    ])
	    ;;
	DragonFly-*|FreeBSD-*)
	    # This configuration from FreeBSD Ports.
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_LD="${CC} -shared"
	    SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,-soname,\$[@]"
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS=""
	    AS_IF([test $doRpath = yes], [
		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
		CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'
		LD_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'])
	    AS_IF([test "${TCL_THREADS}" = "1"], [
		# The -pthread needs to go in the LDFLAGS, not LIBS
		LIBS=`echo $LIBS | sed s/-pthread//`
		CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
		LDFLAGS="$LDFLAGS $PTHREAD_LIBS"])
	    # The -pthread needs to go in the LDFLAGS, not LIBS
	    LIBS=`echo $LIBS | sed s/-pthread//`
	    CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
	    LDFLAGS="$LDFLAGS $PTHREAD_LIBS"
	    case $system in
	    FreeBSD-3.*)
		# Version numbers are dot-stripped by system policy.
		TCL_TRIM_DOTS=`echo ${VERSION} | tr -d .`
		UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
		SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so'
		TCL_LIB_VERSIONS_OK=nodots
1601
1602
1603
1604
1605
1606
1607
1608

1609
1610
1611
1612
1613
1614
1615
1457
1458
1459
1460
1461
1462
1463

1464
1465
1466
1467
1468
1469
1470
1471







-
+







	    LD_SEARCH_FLAGS=""
	    LD_LIBRARY_PATH_VAR="DYLD_LIBRARY_PATH"
	    AC_DEFINE(MAC_OSX_TCL, 1, [Is this a Mac I see before me?])
	    PLAT_OBJS='${MAC_OSX_OBJS}'
	    PLAT_SRCS='${MAC_OSX_SRCS}'
	    AC_MSG_CHECKING([whether to use CoreFoundation])
	    AC_ARG_ENABLE(corefoundation,
		AC_HELP_STRING([--enable-corefoundation],
		AS_HELP_STRING([--enable-corefoundation],
		    [use CoreFoundation API on MacOSX (default: on)]),
		[tcl_corefoundation=$enableval], [tcl_corefoundation=yes])
	    AC_MSG_RESULT([$tcl_corefoundation])
	    AS_IF([test $tcl_corefoundation = yes], [
		AC_CACHE_CHECK([for CoreFoundation.framework],
			tcl_cv_lib_corefoundation, [
		    hold_libs=$LIBS
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713

1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726








1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749


1750
1751
1752


1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1509
1510
1511
1512
1513
1514
1515










1516
1517
1518
1519
1520
1521

























1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533

1534
1535
1536
1537
1538









1539
1540
1541
1542
1543
1544
1545
1546

1547
1548
1549
1550
1551

1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565


1566
1567
1568


1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579





























1580
1581
1582
1583
1584
1585
1586







-
-
-
-
-
-
-
-
-
-






-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-












-
+




-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-





-














-
-
+
+

-
-
+
+









-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







			AC_DEFINE(NO_COREFOUNDATION_64, 1,
			    [Is Darwin CoreFoundation unavailable for 64-bit?])
                        LDFLAGS="$LDFLAGS -Wl,-no_arch_warnings"
		    ])
		])
	    ])
	    ;;
	NEXTSTEP-*)
	    SHLIB_CFLAGS=""
	    SHLIB_LD='${CC} -nostdlib -r'
	    SHLIB_LD_LIBS=""
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadNext.o"
	    DL_LIBS=""
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    ;;
	OS/390-*)
	    SHLIB_LD_LIBS=""
	    CFLAGS_OPTIMIZE=""		# Optimizer is buggy
	    AC_DEFINE(_OE_SOCKETS, 1,	# needed in sys/socket.h
		[Should OS/390 do the right thing with sockets?])
	    ;;
	OSF1-1.0|OSF1-1.1|OSF1-1.2)
	    # OSF/1 1.[012] from OSF, and derivatives, including Paragon OSF/1
	    SHLIB_CFLAGS=""
	    # Hack: make package name same as library name
	    SHLIB_LD='ld -R -export $@:'
	    SHLIB_LD_LIBS=""
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadOSF.o"
	    DL_LIBS=""
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    ;;
	OSF1-1.*)
	    # OSF/1 1.3 from OSF using ELF, and derivatives, including AD2
	    SHLIB_CFLAGS="-fPIC"
	    AS_IF([test "$SHARED_BUILD" = 1], [SHLIB_LD="ld -shared"], [
	        SHLIB_LD="ld -non_shared"
	    ])
	    SHLIB_LD_LIBS=""
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS=""
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    ;;
	OSF1-V*)
	    # Digital OSF/1
	    SHLIB_CFLAGS=""
	    AS_IF([test "$SHARED_BUILD" = 1], [
	        SHLIB_LD='ld -shared -expect_unresolved "*"'
	    ], [
	        SHLIB_LD='ld -non_shared -expect_unresolved "*"'
	    ])
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS=""
	    AS_IF([test $doRpath = yes], [
		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
		CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'
		LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])
	    AS_IF([test "$GCC" = yes], [CFLAGS="$CFLAGS -mieee"], [
		CFLAGS="$CFLAGS -DHAVE_TZSET -std1 -ieee"])
	    # see pthread_intro(3) for pthread support on osf1, k.furukawa
	    AS_IF([test "${TCL_THREADS}" = 1], [
		CFLAGS="$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE"
		CFLAGS="$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64"
		LIBS=`echo $LIBS | sed s/-lpthreads//`
		AS_IF([test "$GCC" = yes], [
		    LIBS="$LIBS -lpthread -lmach -lexc"
		], [
		    CFLAGS="$CFLAGS -pthread"
		    LDFLAGS="$LDFLAGS -pthread"
	    CFLAGS="$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE"
	    CFLAGS="$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64"
	    LIBS=`echo $LIBS | sed s/-lpthreads//`
	    AS_IF([test "$GCC" = yes], [
		LIBS="$LIBS -lpthread -lmach -lexc"
	    ], [
		CFLAGS="$CFLAGS -pthread"
		LDFLAGS="$LDFLAGS -pthread"
		])
	    ])
	    ;;
	QNX-6*)
	    # QNX RTP
	    # This may work for all QNX, but it was only reported for v6.
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_LD="ld -Bshareable -x"
	    SHLIB_LD_LIBS=""
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    # dlopen is in -lc on QNX
	    DL_LIBS=""
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    ;;
	SCO_SV-3.2*)
	    # Note, dlopen is available only on SCO 3.2.5 and greater. However,
	    # this test works, since "uname -s" was non-standard in 3.2.4 and
	    # below.
	    AS_IF([test "$GCC" = yes], [
	    	SHLIB_CFLAGS="-fPIC -melf"
	    	LDFLAGS="$LDFLAGS -melf -Wl,-Bexport"
		SHLIB_CFLAGS="-fPIC -melf"
		LDFLAGS="$LDFLAGS -melf -Wl,-Bexport"
	    ], [
	    	SHLIB_CFLAGS="-Kpic -belf"
	    	LDFLAGS="$LDFLAGS -belf -Wl,-Bexport"
		SHLIB_CFLAGS="-Kpic -belf"
		LDFLAGS="$LDFLAGS -belf -Wl,-Bexport"
	    ])
	    SHLIB_LD="ld -G"
	    SHLIB_LD_LIBS=""
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS=""
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    ;;
	SINIX*5.4*)
	    SHLIB_CFLAGS="-K PIC"
	    SHLIB_LD='${CC} -G'
	    SHLIB_LD_LIBS=""
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS="-ldl"
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    ;;
	SunOS-4*)
	    SHLIB_CFLAGS="-PIC"
	    SHLIB_LD="ld"
	    SHLIB_LD_LIBS=""
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS="-ldl"
	    CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}'
	    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}

	    # SunOS can't handle version numbers with dots in them in library
	    # specs, like -ltcl7.5, so use -ltcl75 instead.  Also, it
	    # requires an extra version number at the end of .so file names.
	    # So, the library has to have a name like libtcl75.so.1.0

	    SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so${SHLIB_VERSION}'
	    UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
	    TCL_LIB_VERSIONS_OK=nodots
	    ;;
	SunOS-5.[[0-6]])
	    # Careful to not let 5.10+ fall into this case

	    # Note: If _REENTRANT isn't defined, then Solaris
	    # won't define thread-safe library routines.

	    AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?])
1955
1956
1957
1958
1959
1960
1961
1962

1963
1964
1965
1966
1967
1968
1969
1744
1745
1746
1747
1748
1749
1750

1751
1752
1753
1754
1755
1756
1757
1758







-
+







dnl # both CPPFLAGS and CFLAGS (unlike our compile and link) but configure's
dnl # preprocessing tests use only CPPFLAGS.
    AC_CONFIG_COMMANDS_PRE([CFLAGS="${CFLAGS} ${CPPFLAGS}"; CPPFLAGS=""])

    # Step 4: disable dynamic loading if requested via a command-line switch.

    AC_ARG_ENABLE(load,
	AC_HELP_STRING([--enable-load],
	AS_HELP_STRING([--enable-load],
	    [allow dynamic loading and "load" command (default: on)]),
	[tcl_ok=$enableval], [tcl_ok=yes])
    AS_IF([test "$tcl_ok" = no], [DL_OBJS=""])

    AS_IF([test "x$DL_OBJS" != x], [BUILD_DLTEST="\$(DLTEST_TARGETS)"], [
	AC_MSG_WARN([Can't figure out how to do dynamic loading or shared libraries on this system.])
	SHLIB_CFLAGS=""
1982
1983
1984
1985
1986
1987
1988
1989



1990

1991
1992


1993
1994
1995
1996
1997
1998
1999
1771
1772
1773
1774
1775
1776
1777

1778
1779
1780
1781
1782


1783
1784
1785
1786
1787
1788
1789
1790
1791







-
+
+
+

+
-
-
+
+







    # libraries to the right flags for gcc, instead of those for the
    # standard manufacturer compiler.

    AS_IF([test "$DL_OBJS" != "tclLoadNone.o" -a "$GCC" = yes], [
	case $system in
	    AIX-*) ;;
	    BSD/OS*) ;;
	    CYGWIN_*|MINGW32_*) ;;
	    CYGWIN_*|MINGW32_*|MSYS_*) ;;
	    HP_UX*) ;;
	    Darwin-*) ;;
	    IRIX*) ;;
	    Linux*|GNU*) ;;
	    NetBSD-*|DragonFly-*|FreeBSD-*|OpenBSD-*) ;;
	    Darwin-*) ;;
	    NetBSD-*|OpenBSD-*) ;;
	    OSF1-V*) ;;
	    SCO_SV-3.2*) ;;
	    *) SHLIB_CFLAGS="-fPIC" ;;
	esac])

    AS_IF([test "$tcl_cv_cc_visibility_hidden" != yes], [
	AC_DEFINE(MODULE_SCOPE, [extern],
	    [No Compiler support for module scope symbols])
2055
2056
2057
2058
2059
2060
2061


2062
2063
2064
2065
2066
2067
2068
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862







+
+







	    tcl_cv_cast_to_union=no)
	)
	if test "$tcl_cv_cast_to_union" = "yes"; then
	    AC_DEFINE(HAVE_CAST_TO_UNION, 1,
		    [Defined when compiler supports casting to union type.])
	fi

    AC_CHECK_HEADER(stdbool.h, [AC_DEFINE(HAVE_STDBOOL_H, 1, [Do we have <stdbool.h>?])],)

    # FIXME: This subst was left in only because the TCL_DL_LIBS
    # entry in tclConfig.sh uses it. It is not clear why someone
    # would use TCL_DL_LIBS instead of TCL_LIBS.
    AC_SUBST(DL_LIBS)

    AC_SUBST(DL_OBJS)
    AC_SUBST(PLAT_OBJS)
2098
2099
2100
2101
2102
2103
2104
2105
2106


2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
1892
1893
1894
1895
1896
1897
1898


1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910

1911
1912
1913
1914
1915

1916
1917
1918
1919
1920
1921
1922







-
-
+
+










-





-







])

#--------------------------------------------------------------------
# SC_MISSING_POSIX_HEADERS
#
#	Supply substitutes for missing POSIX header files.  Special
#	notes:
#	    - stdlib.h doesn't define strtol, strtoul, or
#	      strtod insome versions of SunOS
#	    - stdlib.h doesn't define strtol or strtoul in some
#	      versions of SunOS
#	    - some versions of string.h don't declare procedures such
#	      as strstr
#
# Arguments:
#	none
#
# Results:
#
#	Defines some of the following vars:
#		NO_DIRENT_H
#		NO_VALUES_H
#		NO_STDLIB_H
#		NO_STRING_H
#		NO_SYS_WAIT_H
#		NO_DLFCN_H
#		HAVE_SYS_PARAM_H
#
#		HAVE_STRING_H ?
#
#--------------------------------------------------------------------

AC_DEFUN([SC_MISSING_POSIX_HEADERS], [
    AC_CACHE_CHECK([dirent.h], tcl_cv_dirent_h, [
    AC_TRY_LINK([#include <sys/types.h>
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
1940
1941
1942
1943
1944
1945
1946


1947
1948
1949

1950
1951
1952
1953
1954
1955
1956







-
-



-







closedir(d);
], tcl_cv_dirent_h=yes, tcl_cv_dirent_h=no)])

    if test $tcl_cv_dirent_h = no; then
	AC_DEFINE(NO_DIRENT_H, 1, [Do we have <dirent.h>?])
    fi

    AC_CHECK_HEADER(float.h, , [AC_DEFINE(NO_FLOAT_H, 1, [Do we have <float.h>?])])
    AC_CHECK_HEADER(values.h, , [AC_DEFINE(NO_VALUES_H, 1, [Do we have <values.h>?])])
    AC_CHECK_HEADER(stdlib.h, tcl_ok=1, tcl_ok=0)
    AC_EGREP_HEADER(strtol, stdlib.h, , tcl_ok=0)
    AC_EGREP_HEADER(strtoul, stdlib.h, , tcl_ok=0)
    AC_EGREP_HEADER(strtod, stdlib.h, , tcl_ok=0)
    if test $tcl_ok = 0; then
	AC_DEFINE(NO_STDLIB_H, 1, [Do we have <stdlib.h>?])
    fi
    AC_CHECK_HEADER(string.h, tcl_ok=1, tcl_ok=0)
    AC_EGREP_HEADER(strstr, string.h, , tcl_ok=0)
    AC_EGREP_HEADER(strerror, string.h, , tcl_ok=0)

2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2081
2082
2083
2084
2085
2086
2087




2088
2089
2090
2091
2092
2093
2094







-
-
-
-







    SC_CONFIG_SYSTEM
    AC_MSG_CHECKING([FIONBIO vs. O_NONBLOCK for nonblocking I/O])
    case $system in
	OSF*)
	    AC_DEFINE(USE_FIONBIO, 1, [Should we use FIONBIO?])
	    AC_MSG_RESULT([FIONBIO])
	    ;;
	SunOS-4*)
	    AC_DEFINE(USE_FIONBIO, 1, [Should we use FIONBIO?])
	    AC_MSG_RESULT([FIONBIO])
	    ;;
	*)
	    AC_MSG_RESULT([O_NONBLOCK])
	    ;;
    esac
])

#--------------------------------------------------------------------
2335
2336
2337
2338
2339
2340
2341
2342

2343
2344
2345
2346
2347
2348
2349
2120
2121
2122
2123
2124
2125
2126

2127
2128
2129
2130
2131
2132
2133
2134







-
+







	AC_TRY_COMPILE([#include <time.h>], [struct tm tm; tm.tm_tzadj;],
	    tcl_cv_member_tm_tzadj=yes, tcl_cv_member_tm_tzadj=no)])
    if test $tcl_cv_member_tm_tzadj = yes ; then
	AC_DEFINE(HAVE_TM_TZADJ, 1, [Should we use the tm_tzadj field of struct tm?])
    fi

    AC_CACHE_CHECK([tm_gmtoff in struct tm], tcl_cv_member_tm_gmtoff, [
	AC_TRY_COMPILE([#include <time.h>], [struct tm tm; tm.tm_gmtoff;],
	AC_TRY_COMPILE([#include <time.h>], [struct tm tm; (void)tm.tm_gmtoff;],
	    tcl_cv_member_tm_gmtoff=yes, tcl_cv_member_tm_gmtoff=no)])
    if test $tcl_cv_member_tm_gmtoff = yes ; then
	AC_DEFINE(HAVE_TM_GMTOFF, 1, [Should we use the tm_gmtoff field of struct tm?])
    fi

    #
    # Its important to include time.h in this check, as some systems
2374
2375
2376
2377
2378
2379
2380
2381

2382
2383
2384
2385
2386







2387
2388
2389
2390
2391
2392
2393
2159
2160
2161
2162
2163
2164
2165

2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185







-
+





+
+
+
+
+
+
+







])

#--------------------------------------------------------------------
# SC_TCL_LINK_LIBS
#
#	Search for the libraries needed to link the Tcl shell.
#	Things like the math library (-lm) and socket stuff (-lsocket vs.
#	-lnsl) are dealt with here.
#	-lnsl) or thread library (-lpthread) are dealt with here.
#
# Arguments:
#	None.
#
# Results:
#
#	Sets the following vars:
#		THREADS_LIBS	Thread library(s)
#
#	Defines the following vars:
#		_REENTRANT
#		_THREAD_SAFE
#
#	Might append to the following vars:
#		LIBS
#		MATH_LIBS
#
#	Might define the following vars:
#		HAVE_NET_ERRNO_H
2438
2439
2440
2441
2442
2443
2444

















































2445
2446
2447
2448
2449
2450
2451
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    if test "$tcl_checkBoth" = 1; then
	tk_oldLibs=$LIBS
	LIBS="$LIBS -lsocket -lnsl"
	AC_CHECK_FUNC(accept, tcl_checkNsl=0, [LIBS=$tk_oldLibs])
    fi
    AC_CHECK_FUNC(gethostbyname, , [AC_CHECK_LIB(nsl, gethostbyname,
	    [LIBS="$LIBS -lnsl"])])

    AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?])
    AC_DEFINE(_THREAD_SAFE, 1, [Do we want the thread-safe OS API?])
    AC_CHECK_LIB(pthread,pthread_mutex_init,tcl_ok=yes,tcl_ok=no)
    if test "$tcl_ok" = "no"; then
	# Check a little harder for __pthread_mutex_init in the same
	# library, as some systems hide it there until pthread.h is
	# defined.  We could alternatively do an AC_TRY_COMPILE with
	# pthread.h, but that will work with libpthread really doesn't
	# exist, like AIX 4.2.  [Bug: 4359]
	AC_CHECK_LIB(pthread, __pthread_mutex_init,
		tcl_ok=yes, tcl_ok=no)
    fi

    if test "$tcl_ok" = "yes"; then
	# The space is needed
	THREADS_LIBS=" -lpthread"
    else
	AC_CHECK_LIB(pthreads, pthread_mutex_init,
	_ok=yes, tcl_ok=no)
	if test "$tcl_ok" = "yes"; then
	    # The space is needed
	    THREADS_LIBS=" -lpthreads"
	else
	    AC_CHECK_LIB(c, pthread_mutex_init,
		    tcl_ok=yes, tcl_ok=no)
	    if test "$tcl_ok" = "no"; then
		AC_CHECK_LIB(c_r, pthread_mutex_init,
			tcl_ok=yes, tcl_ok=no)
		if test "$tcl_ok" = "yes"; then
		    # The space is needed
		    THREADS_LIBS=" -pthread"
		else
		    AC_MSG_WARN([Don't know how to find pthread lib on your system - you must edit the LIBS in the Makefile...])
		fi
	    fi
	fi
    fi

    # Does the pthread-implementation provide
    # 'pthread_attr_setstacksize' ?

    ac_saved_libs=$LIBS
    LIBS="$LIBS $THREADS_LIBS"
    AC_CHECK_FUNCS(pthread_attr_setstacksize pthread_atfork)
    LIBS=$ac_saved_libs

    # TIP #509
    AC_CHECK_DECLS([PTHREAD_MUTEX_RECURSIVE],tcl_ok=yes,tcl_ok=no, [[#include <pthread.h>]])
])

#--------------------------------------------------------------------
# SC_TCL_EARLY_FLAGS
#
#	Check for what flags are needed to be passed so the correct OS
#	features are available.
2513
2514
2515
2516
2517
2518
2519
2520

2521
2522
2523
2524
2525
2526
2527
2528


2529
2530
2531
2532
2533
2534
2535
2354
2355
2356
2357
2358
2359
2360

2361
2362
2363
2364
2365
2366
2367


2368
2369
2370
2371
2372
2373
2374
2375
2376







-
+






-
-
+
+







AC_DEFUN([SC_TCL_64BIT_FLAGS], [
    AC_MSG_CHECKING([for 64-bit integer type])
    AC_CACHE_VAL(tcl_cv_type_64bit,[
	tcl_cv_type_64bit=none
	# See if the compiler knows natively about __int64
	AC_TRY_COMPILE(,[__int64 value = (__int64) 0;],
	    tcl_type_64bit=__int64, tcl_type_64bit="long long")
	# See if we should use long anyway  Note that we substitute in the
	# See if we could use long anyway  Note that we substitute in the
	# type that is our current guess for a 64-bit type inside this check
	# program, so it should be modified only carefully...
        AC_TRY_COMPILE(,[switch (0) {
            case 1: case (sizeof(]${tcl_type_64bit}[)==sizeof(long)): ;
        }],tcl_cv_type_64bit=${tcl_type_64bit})])
    if test "${tcl_cv_type_64bit}" = none ; then
	AC_DEFINE(TCL_WIDE_INT_IS_LONG, 1, [Are wide integers to be implemented with C 'long's?])
	AC_MSG_RESULT([using long])
	AC_DEFINE(TCL_WIDE_INT_IS_LONG, 1, [Do 'long' and 'long long' have the same size (64-bit)?])
	AC_MSG_RESULT([yes])
    else
	AC_DEFINE_UNQUOTED(TCL_WIDE_INT_TYPE,${tcl_cv_type_64bit},
	    [What type should be used to define wide integers?])
	AC_MSG_RESULT([${tcl_cv_type_64bit}])

	# Now check for auxiliary declarations
	AC_CACHE_CHECK([for struct dirent64], tcl_cv_struct_dirent64,[
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600



2601
2602
2603
2604
2605
2606

2607
2608
2609
2610
2611
2612
2613
2432
2433
2434
2435
2436
2437
2438



2439
2440
2441
2442
2443
2444
2445
2446

2447
2448
2449
2450
2451
2452
2453
2454







-
-
-
+
+
+





-
+







#	Will define the following vars:
#		TCL_CFGVAL_ENCODING
#
#--------------------------------------------------------------------

AC_DEFUN([SC_TCL_CFG_ENCODING], [
    AC_ARG_WITH(encoding,
	AC_HELP_STRING([--with-encoding],
	    [encoding for configuration values (default: iso8859-1)]),
	with_tcencoding=${withval})
	AS_HELP_STRING([--with-encoding],
	    [encoding for configuration values (default: utf-8)]),
	[with_tcencoding=${withval}])

    if test x"${with_tcencoding}" != x ; then
	AC_DEFINE_UNQUOTED(TCL_CFGVAL_ENCODING,"${with_tcencoding}",
	    [What encoding should be used for embedded configuration info?])
    else
	AC_DEFINE(TCL_CFGVAL_ENCODING,"iso8859-1",
	AC_DEFINE(TCL_CFGVAL_ENCODING,"utf-8",
	    [What encoding should be used for embedded configuration info?])
    fi
])

#--------------------------------------------------------------------
# SC_TCL_CHECK_BROKEN_FUNC
#
2624
2625
2626
2627
2628
2629
2630



2631

2632
2633
2634
2635
2636
2637
2638
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474

2475
2476
2477
2478
2479
2480
2481
2482







+
+
+
-
+







#
#--------------------------------------------------------------------

AC_DEFUN([SC_TCL_CHECK_BROKEN_FUNC],[
    AC_CHECK_FUNC($1, tcl_ok=1, tcl_ok=0)
    if test ["$tcl_ok"] = 1; then
	AC_CACHE_CHECK([proper ]$1[ implementation], [tcl_cv_]$1[_unbroken],
	    AC_TRY_RUN([[
#include <stdlib.h>
#include <string.h>
	    AC_TRY_RUN([[int main() {]$2[}]],[tcl_cv_]$1[_unbroken]=ok,
int main() {]$2[}]],[tcl_cv_]$1[_unbroken]=ok,
		[tcl_cv_]$1[_unbroken]=broken,[tcl_cv_]$1[_unbroken]=unknown))
	if test ["$tcl_cv_]$1[_unbroken"] = "ok"; then
	    tcl_ok=1
	else
	    tcl_ok=0
	fi
    fi
3067
3068
3069
3070
3071
3072
3073



























































































































3074
3075
3076
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



if test "x$NEED_FAKE_RFC2553" = "x1"; then
   AC_DEFINE([NEED_FAKE_RFC2553], 1,
        [Use compat implementation of getaddrinfo() and friends])
   AC_LIBOBJ([fake-rfc2553])
   AC_CHECK_FUNC(strlcpy)
fi
])

#------------------------------------------------------------------------
# SC_CC_FOR_BUILD
#	For cross compiles, locate a C compiler that can generate native binaries.
#
# Arguments:
#	none
#
# Results:
#	Substitutes the following vars:
#		CC_FOR_BUILD
#		EXEEXT_FOR_BUILD
#------------------------------------------------------------------------

dnl Get a default for CC_FOR_BUILD to put into Makefile.
AC_DEFUN([AX_CC_FOR_BUILD],[# Put a plausible default for CC_FOR_BUILD in Makefile.
    if test -z "$CC_FOR_BUILD"; then
      if test "x$cross_compiling" = "xno"; then
        CC_FOR_BUILD='$(CC)'
      else
        AC_MSG_CHECKING([for gcc])
        AC_CACHE_VAL(ac_cv_path_cc, [
            search_path=`echo ${PATH} | sed -e 's/:/ /g'`
            for dir in $search_path ; do
                for j in `ls -r $dir/gcc 2> /dev/null` \
                        `ls -r $dir/gcc 2> /dev/null` ; do
                    if test x"$ac_cv_path_cc" = x ; then
                        if test -f "$j" ; then
                            ac_cv_path_cc=$j
                            break
                        fi
                    fi
                done
            done
        ])
      fi
    fi
    AC_SUBST(CC_FOR_BUILD)
    # Also set EXEEXT_FOR_BUILD.
    if test "x$cross_compiling" = "xno"; then
      EXEEXT_FOR_BUILD='$(EXEEXT)'
      OBJEXT_FOR_BUILD='$(OBJEXT)'
    else
      OBJEXT_FOR_BUILD='.no'
      AC_CACHE_CHECK([for build system executable suffix], bfd_cv_build_exeext,
        [rm -f conftest*
         echo 'int main () { return 0; }' > conftest.c
         bfd_cv_build_exeext=
         ${CC_FOR_BUILD} -o conftest conftest.c 1>&5 2>&5
         for file in conftest.*; do
           case $file in
           *.c | *.o | *.obj | *.ilk | *.pdb) ;;
           *) bfd_cv_build_exeext=`echo $file | sed -e s/conftest//` ;;
           esac
         done
         rm -f conftest*
         test x"${bfd_cv_build_exeext}" = x && bfd_cv_build_exeext=no])
      EXEEXT_FOR_BUILD=""
      test x"${bfd_cv_build_exeext}" != xno && EXEEXT_FOR_BUILD=${bfd_cv_build_exeext}
    fi
    AC_SUBST(EXEEXT_FOR_BUILD)])dnl
    AC_SUBST(OBJEXT_FOR_BUILD)])dnl
])


#------------------------------------------------------------------------
# SC_ZIPFS_SUPPORT
#	Locate a zip encoder installed on the system path, or none.
#
# Arguments:
#	none
#
# Results:
#	Substitutes the following vars:
#		ZIP_PROG
#       ZIP_PROG_OPTIONS
#       ZIP_PROG_VFSSEARCH
#       ZIP_INSTALL_OBJS
#------------------------------------------------------------------------

AC_DEFUN([SC_ZIPFS_SUPPORT], [
    ZIP_PROG=""
    ZIP_PROG_OPTIONS=""
    ZIP_PROG_VFSSEARCH=""
    ZIP_INSTALL_OBJS=""

    AC_MSG_CHECKING([for zip])
    AC_CACHE_VAL(ac_cv_path_zip, [
    search_path=`echo ${PATH} | sed -e 's/:/ /g'`
    for dir in $search_path ; do
        for j in `ls -r $dir/zip 2> /dev/null` \
            `ls -r $dir/zip 2> /dev/null` ; do
        if test x"$ac_cv_path_zip" = x ; then
            if test -f "$j" ; then
            ac_cv_path_zip=$j
            break
            fi
        fi
        done
    done
    ])
    if test -f "$ac_cv_path_zip" ; then
        ZIP_PROG="$ac_cv_path_zip"
        AC_MSG_RESULT([$ZIP_PROG])
        ZIP_PROG_OPTIONS="-rq"
        ZIP_PROG_VFSSEARCH="*"
        AC_MSG_RESULT([Found INFO Zip in environment])
        # Use standard arguments for zip
    else
        # It is not an error if an installed version of Zip can't be located.
        # We can use the locally distributed minizip instead
        ZIP_PROG="./minizip${EXEEXT_FOR_BUILD}"
        ZIP_PROG_OPTIONS="-o -r"
        ZIP_PROG_VFSSEARCH="*"
        ZIP_INSTALL_OBJS="minizip${EXEEXT_FOR_BUILD}"
        AC_MSG_RESULT([No zip found on PATH. Building minizip])
    fi
    AC_SUBST(ZIP_PROG)
    AC_SUBST(ZIP_PROG_OPTIONS)
    AC_SUBST(ZIP_PROG_VFSSEARCH)
    AC_SUBST(ZIP_INSTALL_OBJS)
])

# Local Variables:
# mode: autoconf
# End:
Changes to unix/tk.pc.in.
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5
6
7
8
9
10
11
12
13
14






+







# tk pkg-config source file

prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
demodir=@TK_DEMO_DIR@

Name: The Tk Toolkit
Description: Tk is a cross-platform graphical user interface toolkit, the standard GUI not only for Tcl, but for many other dynamic languages as well.
URL: https://www.tcl-lang.org/
Version: @TK_VERSION@@TK_PATCH_LEVEL@
Requires: tcl >= 8.6
Libs: -L${libdir} @TK_LIB_FLAG@ @TK_STUB_LIB_FLAG@
Changes to unix/tk.spec.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15


16
17
18
19
20
21
22
1
2
3
4
5
6

7
8
9
10
11
12
13


14
15
16
17
18
19
20
21
22






-
+






-
-
+
+







# This file is the basis for a binary Tk Linux RPM.

%{!?directory:%define directory /usr/local}

Name:          tk
Summary:       Tk graphical toolkit for the Tcl scripting language.
Version:       8.6.10
Version:       8.7a4
Release:       2
License:       BSD
Group:         Development/Languages
Source:        http://prdownloads.sourceforge.net/tcl/tk%{version}-src.tar.gz
URL:           https://www.tcl-lang.org/
Buildroot:     /var/tmp/%{name}%{version}
Buildrequires: XFree86-devel tcl >= %version
Requires:      tcl >= %version
Buildrequires: XFree86-devel tcl >= 8.6.0
Requires:      tcl >= 8.6.0

%description
The Tcl (Tool Command Language) provides a powerful platform for
creating integration applications that tie together diverse
applications, protocols, devices, and frameworks.  When paired with
the Tk toolkit, Tcl provides the fastest and most powerful way to
create GUI applications that run on PCs, Unix, and Mac OS X.  Tcl
Changes to unix/tkAppInit.c.
11
12
13
14
15
16
17

18
19



20



21
22
23
24
25
26
27
28
29
30
31
32



33


34
35
36
37
38
39
40
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

43
44
45
46
47
48
49
50
51







+


+
+
+

+
+
+












+
+
+
-
+
+







 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#undef BUILD_tk
#undef STATIC_BUILD
#include "tk.h"
#include "tkPort.h"

#ifdef TK_TEST
#ifdef __cplusplus
extern "C" {
#endif
extern Tcl_PackageInitProc Tktest_Init;
#ifdef __cplusplus
}
#endif
#endif /* TK_TEST */

/*
 * The following #if block allows you to change the AppInit function by using
 * a #define of TCL_LOCAL_APPINIT instead of rewriting this entire file. The
 * #if checks for that #define and uses Tcl_AppInit if it doesn't exist.
 */

#ifndef TK_LOCAL_APPINIT
#define TK_LOCAL_APPINIT Tcl_AppInit
#endif
#ifndef MODULE_SCOPE
#   ifdef __cplusplus
#	define MODULE_SCOPE extern "C"
#   else
#   define MODULE_SCOPE extern
#	define MODULE_SCOPE extern
#   endif
#endif
MODULE_SCOPE int TK_LOCAL_APPINIT(Tcl_Interp *);
MODULE_SCOPE int main(int, char **);

/*
 * The following #if block allows you to change how Tcl finds the startup
 * script, prime the library or encoding paths, fiddle with the argv, etc.,
69
70
71
72
73
74
75



76
77
78
79
80
81
82
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96







+
+
+







int
main(
    int argc,			/* Number of command-line arguments. */
    char **argv)		/* Values of command-line arguments. */
{
#ifdef TK_LOCAL_MAIN_HOOK
    TK_LOCAL_MAIN_HOOK(&argc, &argv);
#elif (TCL_MAJOR_VERSION > 8) || (TCL_MINOR_VERSION > 6)
    /* This doesn't work with Tcl 8.6 */
    TclZipfs_AppHook(&argc, &argv);
#endif

    Tk_Main(argc, argv, TK_LOCAL_APPINIT);
    return 0;			/* Needed only to prevent compiler warning. */
}

/*
106
107
108
109
110
111
112







113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140







+
+
+
+
+
+
+







	return TCL_ERROR;
    }

    if (Tk_Init(interp) == TCL_ERROR) {
	return TCL_ERROR;
    }
    Tcl_StaticPackage(interp, "Tk", Tk_Init, Tk_SafeInit);

#if defined(USE_CUSTOM_EXIT_PROC)
    if (TkpWantsExitProc()) {
	/* The cast below avoids warnings from old gcc compilers. */
	Tcl_SetExitProc((void *)TkpExitProc);
    }
#endif

#ifdef TK_TEST
    if (Tktest_Init(interp) == TCL_ERROR) {
	return TCL_ERROR;
    }
    Tcl_StaticPackage(interp, "Tktest", Tktest_Init, 0);
#endif /* TK_TEST */
Changes to unix/tkConfig.h.in.
1
2
3
4
5



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41


42
43
44
45

46
47

48
49
50



51
52
53
54
55
56
57
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

25
26
27
28
29
30
31
32
33
34
35
36



37
38
39


40
41
42



43


44
45
46
47
48
49
50
51
52
53
54
55
56
57





+
+
+
















-
+











-
-
-



-
-
+
+

-
-
-
+
-
-
+



+
+
+







/* ../unix/tkConfig.h.in.  Generated from configure.ac by autoheader.  */


    #ifndef _TKCONFIG
    #define _TKCONFIG

/* Define if building universal (internal helper macro) */
#undef AC_APPLE_UNIVERSAL_BUILD

/* Define to 1 if you have the <AvailabilityMacros.h> header file. */
#undef HAVE_AVAILABILITYMACROS_H

/* Defined when compiler supports casting to union type. */
#undef HAVE_CAST_TO_UNION

/* Do we have access to Darwin CoreFoundation.framework? */
#undef HAVE_COREFOUNDATION

/* Is 'DIR64' in <sys/types.h>? */
#undef HAVE_DIR64

/* Compiler support for module scope symbols */
#undef HAVE_HIDDEN

/* Do we have the intptr_t type? */
/* Define to 1 if the system has the type `intptr_t'. */
#undef HAVE_INTPTR_T

/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H

/* Define to 1 if you have the `Xft' library (-lXft). */
#undef HAVE_LIBXFT

/* Define to 1 if you have the `lseek64' function. */
#undef HAVE_LSEEK64

/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H

/* Define to 1 if you have the `open64' function. */
#undef HAVE_OPEN64

/* Define to 1 if you have the `pthread_atfork' function. */
#undef HAVE_PTHREAD_ATFORK
/* Does struct password have a pw_gecos field? */
#undef HAVE_PW_GECOS

/* Define to 1 if you have the `pthread_attr_setstacksize' function. */
#undef HAVE_PTHREAD_ATTR_SETSTACKSIZE

/* Do we have <stdbool.h>? */
/* Does struct password have a pw_gecos field? */
#undef HAVE_PW_GECOS
#undef HAVE_STDBOOL_H

/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H

/* Define to 1 if you have the <stdio.h> header file. */
#undef HAVE_STDIO_H

/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H

/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H

75
76
77
78
79
80
81
82

83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
75
76
77
78
79
80
81

82
83
84
85
86
87
88
89
90
91
92
93



94
95
96
97
98
99
100







-
+











-
-
-








/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H

/* Is off64_t in <sys/types.h>? */
#undef HAVE_TYPE_OFF64_T

/* Do we have the uintptr_t type? */
/* Define to 1 if the system has the type `uintptr_t'. */
#undef HAVE_UINTPTR_T

/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H

/* Is weak import available? */
#undef HAVE_WEAK_IMPORT

/* Have we turned on XFT (antialiased fonts)? */
#undef HAVE_XFT

/* Do we have XkbKeycodeToKeysym? */
#undef HAVE_XKBKEYCODETOKEYSYM

/* Is XScreenSaver available? */
#undef HAVE_XSS

/* Is this a Mac I see before me? */
#undef MAC_OSX_TCL

/* Are we building TkAqua? */
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131



132
133
134
135
136
137
138
139



140



141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162

163
164
165
166
167
168
169


170
171
172
173
174
175
176
177
178
179
180
181
182
183
184










185
186

187
188
189
190
191
192
193
108
109
110
111
112
113
114



115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135

136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161



162

163
164
165
166
167

168
169
170
171
172
173
174
175
176
177







178
179
180
181
182
183
184
185
186
187


188
189
190
191
192
193
194
195







-
-
-











+
+
+







-
+
+
+

+
+
+



















-
-
-
+
-





-
+
+








-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
+








/* Is Darwin CoreFoundation unavailable for 64-bit? */
#undef NO_COREFOUNDATION_64

/* Do we have fd_set? */
#undef NO_FD_SET

/* Do we have <stdlib.h>? */
#undef NO_STDLIB_H

/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT

/* Define to the full name of this package. */
#undef PACKAGE_NAME

/* Define to the full name and version of this package. */
#undef PACKAGE_STRING

/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME

/* Define to the home page for this package. */
#undef PACKAGE_URL

/* Define to the version of this package. */
#undef PACKAGE_VERSION

/* Is this a static build? */
#undef STATIC_BUILD

/* Define to 1 if you have the ANSI C header files. */
/* Define to 1 if all of the C90 standard headers exist (not just the ones
   required in a freestanding environment). This macro is provided for
   backward compatibility; new code need not use it. */
#undef STDC_HEADERS

/* What encoding should be used for embedded configuration info? */
#undef TCL_CFGVAL_ENCODING

/* Is this a 64-bit build? */
#undef TCL_CFG_DO64BIT

/* Is this an optimized build? */
#undef TCL_CFG_OPTIMIZED

/* Is bytecode debugging enabled? */
#undef TCL_COMPILE_DEBUG

/* Are bytecode statistics enabled? */
#undef TCL_COMPILE_STATS

/* Is memory debugging enabled? */
#undef TCL_MEM_DEBUG

/* What is the default extension for shared libraries? */
#undef TCL_SHLIB_EXT

/* Are we building with threads enabled? */
#undef TCL_THREADS

/* Do 'long' and 'long long' have the same size (64-bit)? */
/* Are wide integers to be implemented with C 'long's? */
#undef TCL_WIDE_INT_IS_LONG

/* What type should be used to define wide integers? */
#undef TCL_WIDE_INT_TYPE

/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. This
   macro is obsolete. */
#undef TIME_WITH_SYS_TIME

/* Is Tk built as a framework? */
#undef TK_FRAMEWORK

/* Are TkAqua debug messages enabled? */
#undef TK_MAC_DEBUG

/* Do we want to use the threaded memory allocator? */
#undef USE_THREAD_ALLOC

/* Define to 1 if your processor stores words with the most significant byte
   first (like Motorola and SPARC, unlike Intel and VAX). */
#undef WORDS_BIGENDIAN

/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
   significant byte first (like Motorola and SPARC, unlike Intel). */
#if defined AC_APPLE_UNIVERSAL_BUILD
# if defined __BIG_ENDIAN__
#  define WORDS_BIGENDIAN 1
# endif
#else
# ifndef WORDS_BIGENDIAN
#  undef WORDS_BIGENDIAN
# endif
/* Is XKeycodeToKeysym deprecated? */
#undef XKEYCODETOKEYSYM_IS_DEPRECATED
#endif

/* Are Darwin SUSv3 extensions available? */
#undef _DARWIN_C_SOURCE

/* Add the _ISOC99_SOURCE flag when building */
#undef _ISOC99_SOURCE

202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218


219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238

239
240
241

242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
204
205
206
207
208
209
210



211
212
213
214
215
216

217
218
219
220
221
222



223
224
225
226
227
228



229
230
231

232
233
234

235
236
237






238
239
240
241
242
243
244







-
-
-






-
+
+




-
-
-






-
-
-



-
+


-
+


-
-
-
-
-
-








/* Do we really want to follow the standard? Yes we do! */
#undef _POSIX_PTHREAD_SEMANTICS

/* Do we want the reentrant OS API? */
#undef _REENTRANT

/* Do we want the thread-safe OS API? */
#undef _THREAD_SAFE

/* Do we want to use the XOPEN network library? */
#undef _XOPEN_SOURCE

/* Do we want to use the XOPEN network library? */
#undef _XOPEN_SOURCE_EXTENDED

/* Define to 1 if type `char' is unsigned and you are not using gcc.  */
/* Define to 1 if type `char' is unsigned and your compiler does not
   predefine this macro.  */
#ifndef __CHAR_UNSIGNED__
# undef __CHAR_UNSIGNED__
#endif

/* Define to `int' if <sys/types.h> doesn't define. */
#undef gid_t

/* Define to `__inline__' or `__inline' if that's what the C compiler
   calls it, or to nothing if 'inline' is not supported under any name.  */
#ifndef __cplusplus
#undef inline
#endif

/* Signed integer type wide enough to hold a pointer. */
#undef intptr_t

/* Define to `int' if <sys/types.h> does not define. */
#undef mode_t

/* Define to `int' if <sys/types.h> does not define. */
/* Define as a signed integer type capable of holding a process identifier. */
#undef pid_t

/* Define to `unsigned' if <sys/types.h> does not define. */
/* Define to `unsigned int' if <sys/types.h> does not define. */
#undef size_t

/* Define to `int' if <sys/types.h> doesn't define. */
#undef uid_t

/* Unsigned integer type wide enough to hold a pointer. */
#undef uintptr_t


    /* Undef unused package specific autoheader defines so that we can
     * include both tclConfig.h and tkConfig.h at the same time: */
    /* override */ #undef PACKAGE_NAME
    /* override */ #undef PACKAGE_STRING
    /* override */ #undef PACKAGE_TARNAME
    #endif /* _TKCONFIG */
Changes to unix/tkConfig.sh.in.
91
92
93
94
95
96
97



91
92
93
94
95
96
97
98
99
100







+
+
+
TK_STUB_LIB_SPEC='@TK_STUB_LIB_SPEC@'

# Path to the Tk stub library in the build directory.
TK_BUILD_STUB_LIB_PATH='@TK_BUILD_STUB_LIB_PATH@'

# Path to the Tk stub library in the install directory.
TK_STUB_LIB_PATH='@TK_STUB_LIB_PATH@'

# Top-level directory in which Tk's demo files are installed.
TK_DEMO_DIR='@TK_DEMO_DIR@'
Changes to unix/tkUnix.c.
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
16
17
18
19

20
21
22
23
24
25
26
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15
16
17
18

19
20
21
22
23
24
25
26







-
+










-
+







/*
 * tkUnix.c --
 *
 *	This file contains procedures that are UNIX/X-specific, and will
 *	probably have to be written differently for Windows or Macintosh
 *	platforms.
 *
 * 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.
 */

#include "tkInt.h"
#ifdef HAVE_XSS
#   include <X11/extensions/scrnsaver.h>
#   ifdef __APPLE__
/* Support for weak-linked libXss. */
#	define HaveXSSLibrary()	(XScreenSaverQueryInfo != NULL)
#	define HaveXSSLibrary()	(&XScreenSaverQueryInfo != NULL)
#   else
/* Other platforms always link libXss. */
#	define HaveXSSLibrary()	(1)
#   endif
#endif

/*
104
105
106
107
108
109
110





111
112
113
114
115
116
117
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122







+
+
+
+
+







void
Tk_UpdatePointer(
    Tk_Window tkwin,		/* Window to which pointer event is reported.
				 * May be NULL. */
    int x, int y,		/* Pointer location in root coords. */
    int state)			/* Modifier state mask. */
{
  (void)tkwin;
  (void)x;
  (void)y;
  (void)state;

  /*
   * This function intentionally left blank
   */
}

/*
 *----------------------------------------------------------------------
Changes to unix/tkUnix3d.c.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







/*
 * tkUnix3d.c --
 *
 *	This file contains the platform specific routines for drawing 3d
 *	borders in the Motif style.
 *
 * 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.
 */

#include "tkInt.h"
#include "tk3d.h"
42
43
44
45
46
47
48
49

50
51
52
53
54
55
56
42
43
44
45
46
47
48

49
50
51
52
53
54
55
56







-
+







 *
 *----------------------------------------------------------------------
 */

TkBorder *
TkpGetBorder(void)
{
    UnixBorder *borderPtr = ckalloc(sizeof(UnixBorder));
    UnixBorder *borderPtr = (UnixBorder *)ckalloc(sizeof(UnixBorder));

    borderPtr->solidGC = NULL;
    return (TkBorder *) borderPtr;
}

/*
 *----------------------------------------------------------------------
Changes to unix/tkUnixButton.c.
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







/*
 * tkUnixButton.c --
 *
 *	This file implements the Unix specific portion of the button 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.
 */

#include "tkInt.h"
#include "tkButton.h"
169
170
171
172
173
174
175
176

177
178
179
180
181
182
183
169
170
171
172
173
174
175

176
177
178
179
180
181
182
183







-
+







    Pixmap pixmap;
    int depth;

    /*
     * Sanity check.
     */

    if (tkwin == NULL || display == None || d == None || bgBorder == NULL
    if (tkwin == NULL || display == NULL || d == None || bgBorder == NULL
	    || indicatorColor == NULL) {
	return;
    }

    if (disableColor == NULL) {
	disableColor = bg_brdr->bgColorPtr;
    }
322
323
324
325
326
327
328
329

330
331
332
333

334
335
336
337
338
339
340
322
323
324
325
326
327
328

329
330



331
332
333
334
335
336
337
338







-
+

-
-
-
+







 *	Registers an event handler for the widget.
 *
 *----------------------------------------------------------------------
 */

TkButton *
TkpCreateButton(
    Tk_Window tkwin)
    TCL_UNUSED(Tk_Window))
{
    UnixButton *butPtr = ckalloc(sizeof(UnixButton));

    return (TkButton *) butPtr;
    return (TkButton *)ckalloc(sizeof(UnixButton));
}

/*
 *----------------------------------------------------------------------
 *
 * TkpDisplayButton --
 *
392
393
394
395
396
397
398
399

400
401
402
403
404
405
406
390
391
392
393
394
395
396

397
398
399
400
401
402
403
404







-
+







    }
}

void
TkpDisplayButton(
    ClientData clientData)	/* Information about widget. */
{
    register TkButton *butPtr = (TkButton *) clientData;
    TkButton *butPtr = (TkButton *)clientData;
    GC gc;
    Tk_3DBorder border;
    Pixmap pixmap;
    int x = 0;			/* Initialization only needed to stop compiler
				 * warning. */
    int y, relief;
    Tk_Window tkwin = butPtr->tkwin;
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
801
802
803
804
805
806
807


808
809
810
811
812
813
814







-
-







	 */

	Tk_Draw3DRectangle(tkwin, pixmap, border, inset, inset,
		Tk_Width(tkwin) - 2*inset, Tk_Height(tkwin) - 2*inset,
		butPtr->borderWidth, relief);
    }
    if (butPtr->highlightWidth > 0) {
	GC gc;

	if (butPtr->flags & GOT_FOCUS) {
	    gc = Tk_GCForColor(butPtr->highlightColorPtr, pixmap);
	} else {
	    gc = Tk_GCForColor(Tk_3DBorderColor(butPtr->highlightBorder),
		    pixmap);
	}

856
857
858
859
860
861
862
863

864
865
866
867
868
869
870
852
853
854
855
856
857
858

859
860
861
862
863
864
865
866







-
+







 *	The button's window may change size.
 *
 *----------------------------------------------------------------------
 */

void
TkpComputeButtonGeometry(
    register TkButton *butPtr)	/* Button whose geometry may have changed. */
    TkButton *butPtr)	/* Button whose geometry may have changed. */
{
    int width, height, avgWidth, txtWidth, txtHeight;
    int haveImage = 0, haveText = 0;
    Tk_FontMetrics fm;

    butPtr->inset = butPtr->highlightWidth + butPtr->borderWidth;

Changes to unix/tkUnixColor.c.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







/*
 * tkUnixColor.c --
 *
 *	This file contains the platform specific color routines needed for X
 *	support.
 *
 * 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.
 */

#include "tkUnixInt.h"
#include "tkColor.h"
181
182
183
184
185
186
187
188

189
190
191
192
193
194
195
181
182
183
184
185
186
187

188
189
190
191
192
193
194
195







-
+







	if (XAllocColor(display, colormap, &color) != 0) {
	    DeleteStressedCmap(display, colormap);
	} else {
	    FindClosestColor(tkwin, &color, &color);
	}
    }

    tkColPtr = ckalloc(sizeof(TkColor));
    tkColPtr = (TkColor *)ckalloc(sizeof(TkColor));
    tkColPtr->color = color;

    return tkColPtr;
}

/*
 *----------------------------------------------------------------------
216
217
218
219
220
221
222
223

224
225
226
227
228
229
230
216
217
218
219
220
221
222

223
224
225
226
227
228
229
230







-
+







TkpGetColorByValue(
    Tk_Window tkwin,		/* Window in which color will be used. */
    XColor *colorPtr)		/* Red, green, and blue fields indicate
				 * desired color. */
{
    Display *display = Tk_Display(tkwin);
    Colormap colormap = Tk_Colormap(tkwin);
    TkColor *tkColPtr = ckalloc(sizeof(TkColor));
    TkColor *tkColPtr = (TkColor *)ckalloc(sizeof(TkColor));

    tkColPtr->color.red = colorPtr->red;
    tkColPtr->color.green = colorPtr->green;
    tkColPtr->color.blue = colorPtr->blue;
    if (XAllocColor(display, colormap, &tkColPtr->color) != 0) {
	DeleteStressedCmap(display, colormap);
    } else {
265
266
267
268
269
270
271
272

273
274
275
276
277
278
279
280
281

282
283

284
285
286

287
288
289
290
291
292
293

294
295
296
297
298
299
300
265
266
267
268
269
270
271

272
273
274
275
276
277
278
279
280

281
282

283
284
285

286
287
288
289
290
291
292

293
294
295
296
297
298
299
300







-
+








-
+

-
+


-
+






-
+







{
    TkStressedCmap *stressPtr;
    double tmp, distance, closestDistance;
    int i, closest, numFound;
    XColor *colorPtr;
    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
    Colormap colormap = Tk_Colormap(tkwin);
    XVisualInfo template, *visInfoPtr;
    XVisualInfo templ, *visInfoPtr;

    /*
     * Find the TkStressedCmap structure for this colormap, or create a new
     * one if needed.
     */

    for (stressPtr = dispPtr->stressPtr; ; stressPtr = stressPtr->nextPtr) {
	if (stressPtr == NULL) {
	    stressPtr = ckalloc(sizeof(TkStressedCmap));
	    stressPtr = (TkStressedCmap *)ckalloc(sizeof(TkStressedCmap));
	    stressPtr->colormap = colormap;
	    template.visualid = XVisualIDFromVisual(Tk_Visual(tkwin));
	    templ.visualid = XVisualIDFromVisual(Tk_Visual(tkwin));

	    visInfoPtr = XGetVisualInfo(Tk_Display(tkwin),
		    VisualIDMask, &template, &numFound);
		    VisualIDMask, &templ, &numFound);
	    if (numFound < 1) {
		Tcl_Panic("FindClosestColor couldn't lookup visual");
	    }

	    stressPtr->numColors = visInfoPtr->colormap_size;
	    XFree((char *) visInfoPtr);
	    stressPtr->colorPtr =
	    stressPtr->colorPtr = (XColor *)
		    ckalloc(stressPtr->numColors * sizeof(XColor));
	    for (i = 0; i < stressPtr->numColors; i++) {
		stressPtr->colorPtr[i].pixel = (unsigned long) i;
	    }

	    XQueryColors(dispPtr->display, colormap, stressPtr->colorPtr,
		    stressPtr->numColors);
Changes to unix/tkUnixConfig.c.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







/*
 * tkUnixConfig.c --
 *
 *	This module implements the Unix system defaults for the configuration
 *	package.
 *
 * Copyright (c) 1997 by 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.
 */

#include "tkInt.h"

34
35
36
37
38
39
40




41
42
43
44
45
46
47
48
49
50
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54







+
+
+
+











Tcl_Obj *
TkpGetSystemDefault(
    Tk_Window tkwin,		/* A window to use. */
    const char *dbName,		/* The option database name. */
    const char *className)	/* The name of the option class. */
{
    (void)tkwin;
    (void)dbName;
    (void)className;

    return NULL;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Changes to unix/tkUnixCursor.c.
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







/*
 * tkUnixCursor.c --
 *
 *	This file contains X specific cursor manipulation routines.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright © 1995-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.
 */

#include "tkInt.h"

241
242
243
244
245
246
247
248

249
250
251
252
253
254
255
241
242
243
244
245
246
247

248
249
250
251
252
253
254
255







-
+







	    }
	}
    }

    if ((argv[0][0] != '@') && !inTkTable) {
	XColor fg, bg;
	unsigned int maskIndex;
	register const struct CursorName *namePtr;
	const struct CursorName *namePtr;
	TkDisplay *dispPtr;

	/*
	 * The cursor is to come from the standard cursor font. If one arg, it
	 * is cursor name (use black and white for fg and bg). If two args,
	 * they are name and fg color (ignore mask). If three args, they are
	 * name, fg, bg. Some of the code below is stolen from the
334
335
336
337
338
339
340
341

342
343
344
345
346
347
348
334
335
336
337
338
339
340

341
342
343
344
345
346
347
348







-
+







	}

	cursor = CreateCursorFromTableOrFile(interp, tkwin, argc, argv,
		tkCursorPtr);
    }

    if (cursor != None) {
	cursorPtr = ckalloc(sizeof(TkUnixCursor));
	cursorPtr = (TkUnixCursor *)ckalloc(sizeof(TkUnixCursor));
	cursorPtr->info.cursor = (Tk_Cursor) cursor;
	cursorPtr->display = display;
    }

  cleanup:
    if (argv != NULL) {
	ckfree(argv);
604
605
606
607
608
609
610
611

612
613
614
615
616
617
618
604
605
606
607
608
609
610

611
612
613
614
615
616
617
618







-
+







	    (unsigned) height);
    cursor = XCreatePixmapCursor(display, sourcePixmap,
	    maskPixmap, &fgColor, &bgColor, (unsigned) xHot, (unsigned) yHot);
    Tk_FreePixmap(display, sourcePixmap);
    Tk_FreePixmap(display, maskPixmap);

    if (cursor != None) {
	cursorPtr = ckalloc(sizeof(TkUnixCursor));
	cursorPtr = (TkUnixCursor *)ckalloc(sizeof(TkUnixCursor));
	cursorPtr->info.cursor = (Tk_Cursor) cursor;
	cursorPtr->display = display;
    }
    return (TkCursor *) cursorPtr;
}

/*
Changes to unix/tkUnixDefault.h.
18
19
20
21
22
23
24

25
26
27
28
29
30
31
32
33
34
35

36
37
38
39
40
41
42
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44







+











+







 * The definitions below provide symbolic names for the default colors.
 * NORMAL_BG -		Normal background color.
 * ACTIVE_BG -		Background color when widget is active.
 * SELECT_BG -		Background color for selected text.
 * TROUGH -		Background color for troughs in scales and scrollbars.
 * INDICATOR -		Color for indicator when button is selected.
 * DISABLED -		Foreground color when widget is disabled.
 * PLACEHOLDER_FG -	Foreground color for placeholder text.
 */

#define BLACK		"#000000"
#define WHITE		"#ffffff"

#define NORMAL_BG	"#d9d9d9"
#define ACTIVE_BG	"#ececec"
#define SELECT_BG	"#c3c3c3"
#define TROUGH		"#b3b3b3"
#define INDICATOR	WHITE
#define DISABLED	"#a3a3a3"
#define PLACEHOLDER_FG	"#b3b3b3"	/* grey70 */

/*
 * Defaults for labels, buttons, checkbuttons, and radiobuttons:
 */

#define DEF_BUTTON_ANCHOR		"center"
#define DEF_BUTTON_ACTIVE_BG_COLOR	ACTIVE_BG
59
60
61
62
63
64
65
66

67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83

84
85
86

87
88
89
90
91
92
93
61
62
63
64
65
66
67

68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84

85
86
87

88
89
90
91
92
93
94
95







-
+
















-
+


-
+







#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		BLACK
#define DEF_LABEL_HIGHLIGHT_WIDTH	"0"
#define DEF_BUTTON_HIGHLIGHT_WIDTH	"1"
#define DEF_BUTTON_IMAGE		((char *) NULL)
#define DEF_BUTTON_IMAGE		NULL
#define DEF_BUTTON_INDICATOR		"1"
#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		""
#define DEF_BUTTON_PADX			"3m"
#define DEF_LABCHKRAD_PADX		"1"
#define DEF_BUTTON_PADY			"1m"
#define DEF_LABCHKRAD_PADY		"1"
#define DEF_BUTTON_RELIEF		"raised"
#define DEF_LABCHKRAD_RELIEF		"flat"
#define DEF_BUTTON_REPEAT_DELAY		"0"
#define DEF_BUTTON_REPEAT_INTERVAL	"0"
#define DEF_BUTTON_SELECT_COLOR		INDICATOR
#define DEF_BUTTON_SELECT_MONO		BLACK
#define DEF_BUTTON_SELECT_IMAGE		((char *) NULL)
#define DEF_BUTTON_SELECT_IMAGE		NULL
#define DEF_BUTTON_STATE		"normal"
#define DEF_LABEL_TAKE_FOCUS		"0"
#define DEF_BUTTON_TAKE_FOCUS		((char *) NULL)
#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"
117
118
119
120
121
122
123
124

125
126
127
128
129
130
131
119
120
121
122
123
124
125

126
127
128
129
130
131
132
133







-
+







#define DEF_CANVAS_SCROLL_REGION	""
#define DEF_CANVAS_SELECT_COLOR		SELECT_BG
#define DEF_CANVAS_SELECT_MONO		BLACK
#define DEF_CANVAS_SELECT_BD_COLOR	"1"
#define DEF_CANVAS_SELECT_BD_MONO	"0"
#define DEF_CANVAS_SELECT_FG_COLOR	BLACK
#define DEF_CANVAS_SELECT_FG_MONO	WHITE
#define DEF_CANVAS_TAKE_FOCUS		((char *) NULL)
#define DEF_CANVAS_TAKE_FOCUS		NULL
#define DEF_CANVAS_WIDTH		"10c"
#define DEF_CANVAS_X_SCROLL_CMD		""
#define DEF_CANVAS_X_SCROLL_INCREMENT	"0"
#define DEF_CANVAS_Y_SCROLL_CMD		""
#define DEF_CANVAS_Y_SCROLL_INCREMENT	"0"

/*
148
149
150
151
152
153
154


155
156
157
158
159
160
161
162
163
164
165

166
167

168
169
170
171
172
173
174
175

176

177
178
179
180
181
182
183
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168

169
170

171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189







+
+










-
+

-
+








+

+







#define DEF_ENTRY_INSERT_BG		BLACK
#define DEF_ENTRY_INSERT_BD_COLOR	"0"
#define DEF_ENTRY_INSERT_BD_MONO	"0"
#define DEF_ENTRY_INSERT_OFF_TIME	"300"
#define DEF_ENTRY_INSERT_ON_TIME	"600"
#define DEF_ENTRY_INSERT_WIDTH		"2"
#define DEF_ENTRY_JUSTIFY		"left"
#define DEF_ENTRY_PLACEHOLDER		""
#define DEF_ENTRY_PLACEHOLDERFG		PLACEHOLDER_FG
#define DEF_ENTRY_READONLY_BG_COLOR	NORMAL_BG
#define DEF_ENTRY_READONLY_BG_MONO	WHITE
#define DEF_ENTRY_RELIEF		"sunken"
#define DEF_ENTRY_SCROLL_COMMAND	""
#define DEF_ENTRY_SELECT_COLOR		SELECT_BG
#define DEF_ENTRY_SELECT_MONO		BLACK
#define DEF_ENTRY_SELECT_BD_COLOR	"0"
#define DEF_ENTRY_SELECT_BD_MONO	"0"
#define DEF_ENTRY_SELECT_FG_COLOR	BLACK
#define DEF_ENTRY_SELECT_FG_MONO	WHITE
#define DEF_ENTRY_SHOW			((char *) NULL)
#define DEF_ENTRY_SHOW			NULL
#define DEF_ENTRY_STATE			"normal"
#define DEF_ENTRY_TAKE_FOCUS		((char *) NULL)
#define DEF_ENTRY_TAKE_FOCUS		NULL
#define DEF_ENTRY_TEXT_VARIABLE		""
#define DEF_ENTRY_WIDTH			"20"

/*
 * Defaults for frames:
 */

#define DEF_FRAME_BG_COLOR		NORMAL_BG
#define DEF_FRAME_BG_IMAGE		NULL
#define DEF_FRAME_BG_MONO		WHITE
#define DEF_FRAME_BG_TILE		"0"
#define DEF_FRAME_BORDER_WIDTH		"0"
#define DEF_FRAME_CLASS			"Frame"
#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
228
229
230
231
232
233
234
235

236
237
238
239
240
241
242
243
244
245




246
247
248

249
250
251


252
253

254
255
256


257
258
259

260
261
262


263
264

265
266
267
268
269
270
271
272
273
274
275

276
277
278
279
280
281
282
283
284
285
286
287
288
289
290


291
292
293
294
295
296
297
234
235
236
237
238
239
240

241
242
243
244
245
246
247




248
249
250
251
252
253

254
255


256
257
258

259
260


261
262
263
264

265
266


267
268
269

270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295


296
297
298
299
300
301
302
303
304







-
+






-
-
-
-
+
+
+
+


-
+

-
-
+
+

-
+

-
-
+
+


-
+

-
-
+
+

-
+











+













-
-
+
+







#define DEF_LISTBOX_SELECT_MONO		BLACK
#define DEF_LISTBOX_SELECT_BD		"0"
#define DEF_LISTBOX_SELECT_FG_COLOR	BLACK
#define DEF_LISTBOX_SELECT_FG_MONO	WHITE
#define DEF_LISTBOX_SELECT_MODE		"browse"
#define DEF_LISTBOX_SET_GRID		"0"
#define DEF_LISTBOX_STATE		"normal"
#define DEF_LISTBOX_TAKE_FOCUS		((char *) NULL)
#define DEF_LISTBOX_TAKE_FOCUS		NULL
#define DEF_LISTBOX_WIDTH		"20"

/*
 * Defaults for individual entries of menus:
 */

#define DEF_MENU_ENTRY_ACTIVE_BG	((char *) NULL)
#define DEF_MENU_ENTRY_ACTIVE_FG	((char *) NULL)
#define DEF_MENU_ENTRY_ACCELERATOR	((char *) NULL)
#define DEF_MENU_ENTRY_BG		((char *) NULL)
#define DEF_MENU_ENTRY_ACTIVE_BG	NULL
#define DEF_MENU_ENTRY_ACTIVE_FG	NULL
#define DEF_MENU_ENTRY_ACCELERATOR	NULL
#define DEF_MENU_ENTRY_BG		NULL
#define DEF_MENU_ENTRY_BITMAP		NULL
#define DEF_MENU_ENTRY_COLUMN_BREAK	"0"
#define DEF_MENU_ENTRY_COMMAND		((char *) NULL)
#define DEF_MENU_ENTRY_COMMAND		NULL
#define DEF_MENU_ENTRY_COMPOUND 	"none"
#define DEF_MENU_ENTRY_FG		((char *) NULL)
#define DEF_MENU_ENTRY_FONT		((char *) NULL)
#define DEF_MENU_ENTRY_FG		NULL
#define DEF_MENU_ENTRY_FONT		NULL
#define DEF_MENU_ENTRY_HIDE_MARGIN	"0"
#define DEF_MENU_ENTRY_IMAGE		((char *) NULL)
#define DEF_MENU_ENTRY_IMAGE		NULL
#define DEF_MENU_ENTRY_INDICATOR	"1"
#define DEF_MENU_ENTRY_LABEL		((char *) NULL)
#define DEF_MENU_ENTRY_MENU		((char *) NULL)
#define DEF_MENU_ENTRY_LABEL		NULL
#define DEF_MENU_ENTRY_MENU		NULL
#define DEF_MENU_ENTRY_OFF_VALUE	"0"
#define DEF_MENU_ENTRY_ON_VALUE		"1"
#define DEF_MENU_ENTRY_SELECT_IMAGE	((char *) NULL)
#define DEF_MENU_ENTRY_SELECT_IMAGE	NULL
#define DEF_MENU_ENTRY_STATE		"normal"
#define DEF_MENU_ENTRY_VALUE		((char *) NULL)
#define DEF_MENU_ENTRY_CHECK_VARIABLE	((char *) NULL)
#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		((char *) NULL)
#define DEF_MENU_ENTRY_SELECT		NULL
#define DEF_MENU_ENTRY_UNDERLINE	"-1"

/*
 * Defaults for menus overall:
 */

#define DEF_MENU_ACTIVE_BG_COLOR	ACTIVE_BG
#define DEF_MENU_ACTIVE_BG_MONO		BLACK
#define DEF_MENU_ACTIVE_BORDER_WIDTH	"1"
#define DEF_MENU_ACTIVE_FG_COLOR	BLACK
#define DEF_MENU_ACTIVE_FG_MONO		WHITE
#define DEF_MENU_ACTIVE_RELIEF		"raised"
#define DEF_MENU_BG_COLOR		NORMAL_BG
#define DEF_MENU_BG_MONO		WHITE
#define DEF_MENU_BORDER_WIDTH		"1"
#define DEF_MENU_CURSOR			"arrow"
#define DEF_MENU_DISABLED_FG_COLOR	DISABLED
#define DEF_MENU_DISABLED_FG_MONO	""
#define DEF_MENU_FONT			"TkMenuFont"
#define DEF_MENU_FG			BLACK
#define DEF_MENU_POST_COMMAND		""
#define DEF_MENU_RELIEF			"raised"
#define DEF_MENU_SELECT_COLOR		BLACK
#define DEF_MENU_SELECT_MONO		BLACK
#define DEF_MENU_TAKE_FOCUS		"0"
#define DEF_MENU_TEAROFF		"1"
#define DEF_MENU_TEAROFF_CMD		((char *) NULL)
#define DEF_MENU_TEAROFF		"0"
#define DEF_MENU_TEAROFF_CMD		NULL
#define DEF_MENU_TITLE			""
#define DEF_MENU_TYPE			"normal"

/*
 * Defaults for menubuttons:
 */

311
312
313
314
315
316
317
318

319
320
321
322
323
324
325
318
319
320
321
322
323
324

325
326
327
328
329
330
331
332







-
+







#define DEF_MENUBUTTON_FONT		"TkDefaultFont"
#define DEF_MENUBUTTON_FG		BLACK
#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	BLACK
#define DEF_MENUBUTTON_HIGHLIGHT_WIDTH	"0"
#define DEF_MENUBUTTON_IMAGE		((char *) NULL)
#define DEF_MENUBUTTON_IMAGE		NULL
#define DEF_MENUBUTTON_INDICATOR	"0"
#define DEF_MENUBUTTON_JUSTIFY		"center"
#define DEF_MENUBUTTON_MENU		""
#define DEF_MENUBUTTON_PADX		"4p"
#define DEF_MENUBUTTON_PADY		"3p"
#define DEF_MENUBUTTON_RELIEF		"flat"
#define DEF_MENUBUTTON_STATE		"normal"
421
422
423
424
425
426
427
428

429
430
431
432
433
434
435
428
429
430
431
432
433
434

435
436
437
438
439
440
441
442







-
+







#define DEF_SCALE_RESOLUTION		"1"
#define DEF_SCALE_TROUGH_COLOR		TROUGH
#define DEF_SCALE_TROUGH_MONO		WHITE
#define DEF_SCALE_SHOW_VALUE		"1"
#define DEF_SCALE_SLIDER_LENGTH		"30"
#define DEF_SCALE_SLIDER_RELIEF		"raised"
#define DEF_SCALE_STATE			"normal"
#define DEF_SCALE_TAKE_FOCUS		((char *) NULL)
#define DEF_SCALE_TAKE_FOCUS		NULL
#define DEF_SCALE_TICK_INTERVAL		"0"
#define DEF_SCALE_TO			"100"
#define DEF_SCALE_VARIABLE		""
#define DEF_SCALE_WIDTH			"15"

/*
 * Defaults for scrollbars:
448
449
450
451
452
453
454
455

456
457
458
459
460
461
462
455
456
457
458
459
460
461

462
463
464
465
466
467
468
469







-
+







#define DEF_SCROLLBAR_HIGHLIGHT		BLACK
#define DEF_SCROLLBAR_HIGHLIGHT_WIDTH	"0"
#define DEF_SCROLLBAR_JUMP		"0"
#define DEF_SCROLLBAR_ORIENT		"vertical"
#define DEF_SCROLLBAR_RELIEF		"sunken"
#define DEF_SCROLLBAR_REPEAT_DELAY	"300"
#define DEF_SCROLLBAR_REPEAT_INTERVAL	"100"
#define DEF_SCROLLBAR_TAKE_FOCUS	((char *) NULL)
#define DEF_SCROLLBAR_TAKE_FOCUS	NULL
#define DEF_SCROLLBAR_TROUGH_COLOR	TROUGH
#define DEF_SCROLLBAR_TROUGH_MONO	WHITE
#define DEF_SCROLLBAR_WIDTH		"11"

/*
 * Defaults for texts:
 */
496
497
498
499
500
501
502
503

504
505
506
507
508
509
510
503
504
505
506
507
508
509

510
511
512
513
514
515
516
517







-
+







#define DEF_TEXT_SET_GRID		"0"
#define DEF_TEXT_SPACING1		"0"
#define DEF_TEXT_SPACING2		"0"
#define DEF_TEXT_SPACING3		"0"
#define DEF_TEXT_STATE			"normal"
#define DEF_TEXT_TABS			""
#define DEF_TEXT_TABSTYLE		"tabular"
#define DEF_TEXT_TAKE_FOCUS		((char *) NULL)
#define DEF_TEXT_TAKE_FOCUS		NULL
#define DEF_TEXT_UNDO			"0"
#define DEF_TEXT_WIDTH			"80"
#define DEF_TEXT_WRAP			"char"
#define DEF_TEXT_XSCROLL_COMMAND	""
#define DEF_TEXT_YSCROLL_COMMAND	""

/*
Changes to unix/tkUnixDialog.c.
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







/*
 * tkUnixDialog.c --
 *
 *	Contains the Unix implementation of the common dialog boxes:
 *
 * 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.
 */

#include "tkUnixInt.h"

42
43
44
45
46
47
48
49

50
51
52
53
54
55
56
42
43
44
45
46
47
48

49
50
51
52
53
54
55
56







-
+







    Tcl_Obj *const *objv)	/* Arguments. */
{
    Tcl_Obj *cmdObj, **objs;
    int result;

    cmdObj = Tcl_NewStringObj(cmdName, -1);
    Tcl_IncrRefCount(cmdObj);
    objs = ckalloc(sizeof(Tcl_Obj *) * (objc+1));
    objs = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj *) * (objc+1));
    objs[0] = cmdObj;
    memcpy(objs+1, objv, sizeof(Tcl_Obj *) * (unsigned)objc);

    result = Tcl_EvalObjv(interp, objc+1, objs, 0);

    Tcl_DecrRefCount(cmdObj);
    ckfree(objs);
Changes to unix/tkUnixDraw.c.
1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

28
29
30
31
32
33
34
1
2
3
4
5

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

27
28
29
30
31
32
33
34





-
+




















-
+







/*
 * tkUnixDraw.c --
 *
 *	This file contains X specific drawing routines.
 *
 * 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.
 */

#include "tkInt.h"

#ifndef _WIN32
#include "tkUnixInt.h"
#endif

/*
 * The following structure is used to pass information to ScrollRestrictProc
 * from TkScrollWindow.
 */

typedef struct ScrollInfo {
    int done;			/* Flag is 0 until filtering is done. */
    Display *display;		/* Display to filter. */
    Window window;		/* Window to filter. */
    TkRegion region;		/* Region into which damage is accumulated. */
    Region region;		/* Region into which damage is accumulated. */
    int dx, dy;			/* Amount by which window was shifted. */
} ScrollInfo;

/*
 * Forward declarations for functions declared later in this file:
 */

57
58
59
60
61
62
63
64

65
66
67
68
69
70
71
57
58
59
60
61
62
63

64
65
66
67
68
69
70
71







-
+







int
TkScrollWindow(
    Tk_Window tkwin,		/* The window to be scrolled. */
    GC gc,			/* GC for window to be scrolled. */
    int x, int y, int width, int height,
				/* Position rectangle to be scrolled. */
    int dx, int dy,		/* Distance rectangle should be moved. */
    TkRegion damageRgn)		/* Region to accumulate damage in. */
    Region damageRgn)		/* Region to accumulate damage in. */
{
    Tk_RestrictProc *prevProc;
    ClientData prevArg;
    ScrollInfo info;

    XCopyArea(Tk_Display(tkwin), Tk_WindowId(tkwin), Tk_WindowId(tkwin), gc,
	    x, y, (unsigned) width, (unsigned) height, x+dx, y+dy);
86
87
88
89
90
91
92
93

94
95
96
97
98
99
100
86
87
88
89
90
91
92

93
94
95
96
97
98
99
100







-
+







    TkpSync(info.display);
    prevProc = Tk_RestrictEvents(ScrollRestrictProc, &info, &prevArg);
    while (!info.done) {
	Tcl_ServiceEvent(TCL_WINDOW_EVENTS);
    }
    Tk_RestrictEvents(prevProc, prevArg, &prevArg);

    if (XEmptyRegion((Region) damageRgn)) {
    if (XEmptyRegion(damageRgn)) {
	return 0;
    } else {
	return 1;
    }
}

/*
137
138
139
140
141
142
143
144
145


146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164


165
166
167
168


169
170
171
172
173
174
175
137
138
139
140
141
142
143


144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162


163
164
165
166


167
168
169
170
171
172
173
174
175







-
-
+
+

















-
-
+
+


-
-
+
+







    if (eventPtr->type == NoExpose) {
	info->done = 1;
    } else if (eventPtr->type == GraphicsExpose) {
	rect.x = eventPtr->xgraphicsexpose.x;
	rect.y = eventPtr->xgraphicsexpose.y;
	rect.width = eventPtr->xgraphicsexpose.width;
	rect.height = eventPtr->xgraphicsexpose.height;
	XUnionRectWithRegion(&rect, (Region) info->region,
		(Region) info->region);
	XUnionRectWithRegion(&rect, info->region,
		info->region);

	if (eventPtr->xgraphicsexpose.count == 0) {
	    info->done = 1;
	}
    } else if (eventPtr->type == Expose) {
	/*
	 * This case is tricky. This event was already queued before the
	 * XCopyArea was issued. If this area overlaps the area being copied,
	 * then some of the copied area may be invalid. The easiest way to
	 * handle this case is to mark both the original area and the shifted
	 * area as damaged.
	 */

	rect.x = eventPtr->xexpose.x;
	rect.y = eventPtr->xexpose.y;
	rect.width = eventPtr->xexpose.width;
	rect.height = eventPtr->xexpose.height;
	XUnionRectWithRegion(&rect, (Region) info->region,
		(Region) info->region);
	XUnionRectWithRegion(&rect, info->region,
		info->region);
	rect.x += info->dx;
	rect.y += info->dy;
	XUnionRectWithRegion(&rect, (Region) info->region,
		(Region) info->region);
	XUnionRectWithRegion(&rect, info->region,
		info->region);
    } else {
	return TK_DEFER_EVENT;
    }
    return TK_DISCARD_EVENT;
}

/*
198
199
200
201
202
203
204


205
206
207
208
209
210
211

212
213
214
215
216
217
218
219
220
221
222
223
224
225

226

227
228
229
230
231
232

233
234
235
236
237
238
239
240
241
242
243
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

213
214
215
216
217
218
219
220
221
222
223
224
225
226

227
228
229
230
231
232
233
234

235
236
237
238
239
240
241
242
243
244
245
246







+
+






-
+













-
+

+





-
+











TkpDrawHighlightBorder(
    Tk_Window tkwin,
    GC fgGC,
    GC bgGC,
    int highlightWidth,
    Drawable drawable)
{
    (void)bgGC;

    TkDrawInsetFocusHighlight(tkwin, fgGC, highlightWidth, drawable, 0);
}

/*
 *----------------------------------------------------------------------
 *
 * TkpDrawFrame --
 * TkpDrawFrameEx --
 *
 *	This function draws the rectangular frame area.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Draws inside the tkwin area.
 *
 *----------------------------------------------------------------------
 */

void
TkpDrawFrame(
TkpDrawFrameEx(
    Tk_Window tkwin,
    Drawable drawable,
    Tk_3DBorder border,
    int highlightWidth,
    int borderWidth,
    int relief)
{
    Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), border, highlightWidth,
    Tk_Fill3DRectangle(tkwin, drawable, border, highlightWidth,
	    highlightWidth, Tk_Width(tkwin) - 2*highlightWidth,
	    Tk_Height(tkwin) - 2*highlightWidth, borderWidth, relief);
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Changes to unix/tkUnixEmbed.c.
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
16








-
+







/*
 * tkUnixEmbed.c --
 *
 *	This file contains platform-specific functions for UNIX to provide
 *	basic operations needed for application embedding (where one
 *	application can use as its main window an internal window from some
 *	other application). Also includes code to support busy windows.
 *
 * 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.
 */

#include "tkUnixInt.h"
#include "tkBusy.h"
102
103
104
105
106
107
108
109

110
111
112
113
114
115
116
102
103
104
105
106
107
108

109
110
111
112
113
114
115
116







-
+







    TkWindow *winPtr = (TkWindow *) tkwin;
    TkWindow *usePtr;
    int anyError;
    Window parent;
    Tk_ErrorHandler handler;
    Container *containerPtr;
    XWindowAttributes parentAtts;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (winPtr->window != None) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"can't modify container after widget is created", -1));
	Tcl_SetErrorCode(interp, "TK", "EMBED", "POST_CREATE", NULL);
	return TCL_ERROR;
174
175
176
177
178
179
180
181

182
183
184
185
186
187
188
174
175
176
177
178
179
180

181
182
183
184
185
186
187
188







-
+







	if (containerPtr->parent == parent) {
	    winPtr->flags |= TK_BOTH_HALVES;
	    containerPtr->parentPtr->flags |= TK_BOTH_HALVES;
	    break;
	}
    }
    if (containerPtr == NULL) {
	containerPtr = ckalloc(sizeof(Container));
	containerPtr = (Container *)ckalloc(sizeof(Container));
	containerPtr->parent = parent;
	containerPtr->parentRoot = parentAtts.root;
	containerPtr->parentPtr = NULL;
	containerPtr->wrapper = None;
	containerPtr->nextPtr = tsdPtr->firstContainerPtr;
	tsdPtr->firstContainerPtr = containerPtr;
    }
212
213
214
215
216
217
218
219

220
221
222
223
224
225
226
212
213
214
215
216
217
218

219
220
221
222
223
224
225
226







-
+







TkpMakeWindow(
    TkWindow *winPtr,		/* Tk's information about the window that is
				 * to be instantiated. */
    Window parent)		/* Window system token for the parent in which
				 * the window is to be created. */
{
    Container *containerPtr;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (winPtr->flags & TK_EMBEDDED) {
	/*
	 * This window is embedded. Don't create the new window in the given
	 * parent; instead, create it as a child of the root window of the
	 * container's screen. The window will get reparented into a wrapper
268
269
270
271
272
273
274
275

276
277
278
279
280
281
282
283
284

285
286
287
288
289
290
291
268
269
270
271
272
273
274

275
276
277
278
279
280
281
282
283

284
285
286
287
288
289
290
291







-
+








-
+







void
TkpMakeContainer(
    Tk_Window tkwin)		/* Token for a window that is about to become
				 * a container. */
{
    TkWindow *winPtr = (TkWindow *) tkwin;
    Container *containerPtr;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    /*
     * Register the window as a container so that, for example, we can find
     * out later if the embedded app. is in the same process.
     */

    Tk_MakeWindowExist(tkwin);
    containerPtr = ckalloc(sizeof(Container));
    containerPtr = (Container *)ckalloc(sizeof(Container));
    containerPtr->parent = Tk_WindowId(tkwin);
    containerPtr->parentRoot = RootWindowOfScreen(Tk_Screen(tkwin));
    containerPtr->parentPtr = winPtr;
    containerPtr->wrapper = None;
    containerPtr->embeddedPtr = NULL;
    containerPtr->nextPtr = tsdPtr->firstContainerPtr;
    tsdPtr->firstContainerPtr = containerPtr;
328
329
330
331
332
333
334
335


336
337
338
339
340
341
342
328
329
330
331
332
333
334

335
336
337
338
339
340
341
342
343







-
+
+








static int
EmbedErrorProc(
    ClientData clientData,	/* Points to integer to set. */
    XErrorEvent *errEventPtr)	/* Points to information about error (not
				 * used). */
{
    int *iPtr = clientData;
    int *iPtr = (int *)clientData;
    (void)errEventPtr;

    *iPtr = 1;
    return 0;
}

/*
 *----------------------------------------------------------------------
358
359
360
361
362
363
364
365

366
367
368
369
370
371
372
359
360
361
362
363
364
365

366
367
368
369
370
371
372
373







-
+







 */

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);
    }
}

/*
390
391
392
393
394
395
396
397

398
399
400

401
402
403
404
405
406
407
391
392
393
394
395
396
397

398
399
400

401
402
403
404
405
406
407
408







-
+


-
+







 */

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;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    /*
     * Ignore any X protocol errors that happen in this function (almost any
     * operation could fail, for example, if the embedded application has
     * deleted its window).
     */
495
496
497
498
499
500
501
502

503
504
505
506
507
508
509
510

511
512
513
514
515
516
517
496
497
498
499
500
501
502

503
504
505
506
507
508
509
510

511
512
513
514
515
516
517
518







-
+







-
+







 */

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->wrapper != None) {

	    /*
	     * Ignore errors, since the embedded application could have
	     * deleted its window.
550
551
552
553
554
555
556
557

558
559
560
561
562
563
564
551
552
553
554
555
556
557

558
559
560
561
562
563
564
565







-
+







 */

static void
EmbedFocusProc(
    ClientData clientData,	/* Token for container window. */
    XEvent *eventPtr)		/* ResizeRequest event. */
{
    Container *containerPtr = clientData;
    Container *containerPtr = (Container *)clientData;
    Tk_ErrorHandler errHandler;
    Display *display;

    display = Tk_Display(containerPtr->parentPtr);
    if (eventPtr->type == FocusIn) {
	/*
	 * The focus just arrived at the container. Change the X focus to move
708
709
710
711
712
713
714
715

716
717
718
719
720
721
722
709
710
711
712
713
714
715

716
717
718
719
720
721
722
723







-
+








TkWindow *
TkpGetOtherWindow(
    TkWindow *winPtr)		/* Tk's structure for a container or embedded
				 * window. */
{
    Container *containerPtr;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    for (containerPtr = tsdPtr->firstContainerPtr;
            containerPtr != NULL;
	    containerPtr = containerPtr->nextPtr) {
	if (containerPtr->embeddedPtr == winPtr) {
	    return containerPtr->parentPtr;
754
755
756
757
758
759
760
761

762
763
764
765
766
767
768
755
756
757
758
759
760
761

762
763
764
765
766
767
768
769







-
+







    TkWindow *winPtr,		/* Window to which the event was originally
				 * reported. */
    XEvent *eventPtr)		/* X event to redirect (should be KeyPress or
				 * KeyRelease). */
{
    Container *containerPtr;
    Window saved;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    /*
     * First, find the top-level window corresponding to winPtr.
     */

    while (1) {
826
827
828
829
830
831
832
833

834
835
836
837
838
839
840
827
828
829
830
831
832
833

834
835
836
837
838
839
840
841







-
+







				 * window; should be embedded. */
    int force)			/* One means that the container should claim
				 * the focus if it doesn't currently have
				 * it. */
{
    XEvent event;
    Container *containerPtr;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (!(topLevelPtr->flags & TK_EMBEDDED)) {
	return;
    }

    for (containerPtr = tsdPtr->firstContainerPtr;
868
869
870
871
872
873
874
875

876
877
878
879
880
881
882
883
884
885

886

887
888
889
890
891
892
893
869
870
871
872
873
874
875

876
877
878
879
880
881
882
883
884
885

886
887
888
889
890
891
892
893
894
895







-
+









-
+

+







 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TkpTestembedCmd(
    ClientData clientData,	/* Main window for application. */
    ClientData dummy,	/* Main window for application. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])		/* Argument strings. */
{
    int all;
    Container *containerPtr;
    Tcl_DString dString;
    char buffer[50];
    Tcl_Interp *embeddedInterp = NULL, *parentInterp = NULL;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    (void)dummy;

    if ((objc > 1) && (strcmp(Tcl_GetString(objv[1]), "all") == 0)) {
	all = 1;
    } else {
	all = 0;
    }
    Tcl_DStringInit(&dString);
903
904
905
906
907
908
909
910

911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927

928
929
930
931
932
933
934
905
906
907
908
909
910
911

912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928

929
930
931
932
933
934
935
936







-
+
















-
+







	    continue;
	}
	Tcl_DStringStartSublist(&dString);
	/* Parent id */
	if (containerPtr->parent == None) {
	    Tcl_DStringAppendElement(&dString, "");
	} else if (all) {
	    sprintf(buffer, "0x%lx", containerPtr->parent);
	    sprintf(buffer, "0x%" TCL_Z_MODIFIER "x", (size_t) containerPtr->parent);
	    Tcl_DStringAppendElement(&dString, buffer);
	} else {
	    Tcl_DStringAppendElement(&dString, "XXX");
	}
	/* Parent pathName */
	if (containerPtr->parentPtr == NULL ||
	    parentInterp != interp) {
	    Tcl_DStringAppendElement(&dString, "");
	} else {
	    Tcl_DStringAppendElement(&dString,
		    containerPtr->parentPtr->pathName);
	}
        /* Wrapper */
	if (containerPtr->wrapper == None) {
	    Tcl_DStringAppendElement(&dString, "");
	} else if (all) {
	    sprintf(buffer, "0x%lx", containerPtr->wrapper);
	    sprintf(buffer, "0x%" TCL_Z_MODIFIER "x", (size_t) containerPtr->wrapper);
	    Tcl_DStringAppendElement(&dString, buffer);
	} else {
	    Tcl_DStringAppendElement(&dString, "XXX");
	}
	/* Embedded window pathName */
	if (containerPtr->embeddedPtr == NULL ||
	    embeddedInterp != interp) {
963
964
965
966
967
968
969
970

971
972
973
974
975
976
977
965
966
967
968
969
970
971

972
973
974
975
976
977
978
979







-
+








static void
EmbedWindowDeleted(
    TkWindow *winPtr)		/* Tk's information about window that was
				 * deleted. */
{
    Container *containerPtr, *prevPtr;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    /*
     * Find the Container structure for this window work. Delete the
     * information about the embedded application and free the container's
     * record.
     */
1021
1022
1023
1024
1025
1026
1027
1028

1029
1030
1031
1032
1033
1034
1035
1023
1024
1025
1026
1027
1028
1029

1030
1031
1032
1033
1034
1035
1036
1037







-
+







 */

Window
TkUnixContainerId(
    TkWindow *winPtr)		/* Tk's structure for an embedded window. */
{
    Container *containerPtr;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    for (containerPtr = tsdPtr->firstContainerPtr;
            containerPtr != NULL; containerPtr = containerPtr->nextPtr) {
	if (containerPtr->embeddedPtr == winPtr) {
	    return containerPtr->parent;
	}
1174
1175
1176
1177
1178
1179
1180

1181
1182
1183
1184
1185
1186
1187
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190







+







    Tk_Window tkRef,
    Window *parentPtr,
    Tk_Window tkParent,
    TkBusy busy)
{
    Window root, parent, *dummy;
    unsigned int count;
    (void)busy;

    if (winPtr->flags & TK_REPARENTED) {
	/*
	 * This works around a bug in the implementation of menubars for
	 * non-MacIntosh window systems (Win32 and X11). Tk doesn't reset the
	 * pointers to the parent window when the menu is reparented (since
	 * winPtr->parentPtr points to the wrong window). We get around this
Changes to unix/tkUnixEvent.c.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15
16



17
18

19
20
21
22
23
24
25
26
1
2
3
4
5
6

7
8
9
10
11
12
13
14


15
16
17


18

19
20
21
22
23
24
25






-
+







-
-
+
+
+
-
-
+
-







/*
 * tkUnixEvent.c --
 *
 *	This file implements an event source for X displays for the UNIX
 *	version of Tk.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright © 1995-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.
 */

#include "tkUnixInt.h"
#include <signal.h>
#ifdef HAVE_XKBKEYCODETOKEYSYM
#  include <X11/XKBlib.h>
#undef register /* Keyword "register" is used in XKBlib.h, so don't try tricky things here */
#define XkbOpenDisplay XkbOpenDisplay_ /* Move out of the way, conflicting definitions */
#include <X11/XKBlib.h>
#else
#  define XkbOpenDisplay(D,V,E,M,m,R) ((V),(E),(M),(m),(R),(NULL))
#undef XkbOpenDisplay
#endif

/*
 * The following static indicates whether this module has been initialized in
 * the current thread.
 */

typedef struct {
88
89
90
91
92
93
94
95

96
97
98

99
100
101
102
103
104
105
87
88
89
90
91
92
93

94
95
96
97
98
99
100
101
102
103
104
105







-
+



+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
DisplayExitHandler(
    ClientData clientData)	/* Not used. */
    ClientData dummy)	/* Not used. */
{
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    (void)dummy;

    Tcl_DeleteEventSource(DisplaySetupProc, DisplayCheckProc, NULL);
    tsdPtr->initialized = 0;
}

/*
 *----------------------------------------------------------------------
125
126
127
128
129
130
131
132
133
134

135
136
137
138
139
140
141
125
126
127
128
129
130
131

132

133
134
135
136
137
138
139
140







-

-
+







    TkDisplay *dispPtr;
    Display *display;
    int event = 0;
    int error = 0;
    int major = 1;
    int minor = 0;
    int reason = 0;
    unsigned int use_xkb = 0;
    /* Disabled, until we have a better test. See [Bug 3613668] */
#if 0 && defined(XKEYCODETOKEYSYM_IS_DEPRECATED) && defined(TCL_THREADS)
#if 0
    static int xinited = 0;
    static Tcl_Mutex xinitMutex = NULL;

    if (!xinited) {
	Tcl_MutexLock(&xinitMutex);
	if (!xinited) {
	    /* Necessary for threaded apps, of no consequence otherwise  */
150
151
152
153
154
155
156
157

158
159
160
161
162
163

164
165
166
167
168
169
170
171
172
173
174
175
176
177
178

179
180
181
182
183
184
185
186
187
188
149
150
151
152
153
154
155

156
157
158


159

160
161
162









163
164
165

166
167
168

169
170
171
172
173
174
175







-
+


-
-

-
+


-
-
-
-
-
-
-
-
-



-
+


-







	}
	Tcl_MutexUnlock(&xinitMutex);
    }
#endif

    /*
    ** Bug [3607830]: Before using Xkb, it must be initialized and confirmed
    **                that the serve supports it.  The XkbOpenDisplay call
    **                that the server supports it.  The XkbOpenDisplay call
    **                will perform this check and return NULL if the extension
    **                is not supported.
    **
    ** Work around un-const-ified Xkb headers using (char *) cast.
    */
    display = XkbOpenDisplay((char *)displayNameStr, &event, &error, &major,
    display = XkbOpenDisplay(displayNameStr, &event, &error, &major,
	    &minor, &reason);

    if (display == NULL) {
	/*fprintf(stderr,"event=%d error=%d major=%d minor=%d reason=%d\nDisabling xkb\n",
	event, error, major, minor, reason);*/
	display = XOpenDisplay(displayNameStr);
    } else {
	use_xkb = TK_DISPLAY_USE_XKB;
	/*fprintf(stderr, "Using xkb %d.%d\n", major, minor);*/
    }

    if (display == NULL) {
	return NULL;
    }
    dispPtr = ckalloc(sizeof(TkDisplay));
    dispPtr = (TkDisplay *)ckalloc(sizeof(TkDisplay));
    memset(dispPtr, 0, sizeof(TkDisplay));
    dispPtr->display = display;
    dispPtr->flags |= use_xkb;
#ifdef TK_USE_INPUT_METHODS
    OpenIM(dispPtr);
    XRegisterIMInstantiateCallback(dispPtr->display, NULL, NULL, NULL,
	    InstantiateIMCallback, (XPointer) dispPtr);
#endif
    Tcl_CreateFileHandler(ConnectionNumber(display), TCL_READABLE,
	    DisplayFileProc, dispPtr);
307
308
309
310
311
312
313
314

315
316
317
318

319
320
321
322
323
324
325
294
295
296
297
298
299
300

301
302
303
304
305
306
307
308
309
310
311
312
313







-
+




+







 *	Tcl even if there is no more data on the X connection.
 *
 *----------------------------------------------------------------------
 */

static void
DisplaySetupProc(
    ClientData clientData,	/* Not used. */
    ClientData dummy,	/* Not used. */
    int flags)
{
    TkDisplay *dispPtr;
    static Tcl_Time blockTime = { 0, 0 };
    (void)dummy;

    if (!(flags & TCL_WINDOW_EVENTS)) {
	return;
    }

    for (dispPtr = TkGetDisplayList(); dispPtr != NULL;
	    dispPtr = dispPtr->nextPtr) {
439
440
441
442
443
444
445
446

447
448
449

450
451
452
453
454
455
456
427
428
429
430
431
432
433

434
435
436
437
438
439
440
441
442
443
444
445







-
+



+







 *	Moves queued events onto the Tcl event queue.
 *
 *----------------------------------------------------------------------
 */

static void
DisplayCheckProc(
    ClientData clientData,	/* Not used. */
    ClientData dummy,	/* Not used. */
    int flags)
{
    TkDisplay *dispPtr;
    (void)dummy;

    if (!(flags & TCL_WINDOW_EVENTS)) {
	return;
    }

    for (dispPtr = TkGetDisplayList(); dispPtr != NULL;
	    dispPtr = dispPtr->nextPtr) {
477
478
479
480
481
482
483
484

485
486

487
488
489
490
491
492
493
466
467
468
469
470
471
472

473
474
475
476
477
478
479
480
481
482
483







-
+


+







 */

static void
DisplayFileProc(
    ClientData clientData,	/* The display pointer. */
    int flags)			/* Should be TCL_READABLE. */
{
    TkDisplay *dispPtr = (TkDisplay *) clientData;
    TkDisplay *dispPtr = (TkDisplay *)clientData;
    Display *display = dispPtr->display;
    int numFound;
    (void)flags;

    XFlush(display);
    numFound = XEventsQueued(display, QueuedAfterReading);
    if (numFound == 0) {
	/*
	 * Things are very tricky if there aren't any events readable at this
	 * point (after all, there was supposedly data available on the
504
505
506
507
508
509
510
511

512
513

514
515
516
517
518
519
520
494
495
496
497
498
499
500

501
502

503
504
505
506
507
508
509
510







-
+

-
+







	 * such an error, generate a NoOp protocol request to exercise the
	 * connection to the server, then return. However, must disable
	 * SIGPIPE while sending the request, or else the process will die
	 * from the signal and won't invoke the X error function to print a
	 * nice (?!) message.
	 */

	void (*oldHandler)();
	void (*oldHandler)(int);

	oldHandler = (void (*)()) signal(SIGPIPE, SIG_IGN);
	oldHandler = (void (*)(int)) signal(SIGPIPE, SIG_IGN);
	XNoOp(display);
	XFlush(display);
	(void) signal(SIGPIPE, oldHandler);
    }

    TransferXEventsToTcl(display);
}
690
691
692
693
694
695
696


697
698
699
700
701
702
703
704
705
706
707
708
709
710


711
712
713
714
715
716
717
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711







+
+














+
+







static void
InstantiateIMCallback(
    Display      *display,
    XPointer     client_data,
    XPointer     call_data)
{
    TkDisplay    *dispPtr;
    (void)display;
    (void)call_data;

    dispPtr = (TkDisplay *) client_data;
    OpenIM(dispPtr);
    XUnregisterIMInstantiateCallback(dispPtr->display, NULL, NULL, NULL,
	    InstantiateIMCallback, (XPointer) dispPtr);
}

static void
DestroyIMCallback(
    XIM         im,
    XPointer    client_data,
    XPointer    call_data)
{
    TkDisplay   *dispPtr;
    (void)im;
    (void)call_data;

    dispPtr = (TkDisplay *) client_data;
    dispPtr->inputMethod = NULL;
    ++dispPtr->ximGeneration;
    XRegisterIMInstantiateCallback(dispPtr->display, NULL, NULL, NULL,
	    InstantiateIMCallback, (XPointer) dispPtr);
}
Changes to unix/tkUnixFocus.c.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







/*
 * tkUnixFocus.c --
 *
 *	This file contains platform specific functions that manage focus for
 *	Tk.
 *
 * 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.
 */

#include "tkUnixInt.h"

Changes to unix/tkUnixFont.c.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15
16
17
18
19
20
21


22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

39

40
41
42
43

44
45
46
47
48
49
50
1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16
17
18
19


20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

40
41
42
43

44
45
46
47
48
49
50
51






-
+












-
-
+
+

















+
-
+



-
+







/*
 * tkUnixFont.c --
 *
 *	Contains the Unix implementation of the platform-independent font
 *	package interface.
 *
 * 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.
 */

#include "tkUnixInt.h"
#include "tkFont.h"

/*
 * The preferred font encodings.
 */

static const char *const encodingList[] = {
    "iso8859-1", "jis0208", "jis0212", NULL
static const char encodingList[][10] = {
    "iso8859-1", "jis0208", "jis0212"
};

/*
 * The following structure represents a font family. It is assumed that all
 * screen fonts constructed from the same "font family" share certain
 * properties; all screen fonts with the same "font family" point to a shared
 * instance of this structure. The most important shared property is the
 * character existence metrics, used to determine if a screen font can display
 * a given Unicode character.
 *
 * Under Unix, there are three attributes that uniquely identify a "font
 * family": the foundry, face name, and charset.
 */

#define FONTMAP_SHIFT		10

#define FONTMAP_BITSPERPAGE	(1 << FONTMAP_SHIFT)
#define FONTMAP_NUMCHARS	0x40000
#define FONTMAP_PAGES		(0x30000 / FONTMAP_BITSPERPAGE)
#define FONTMAP_PAGES		(FONTMAP_NUMCHARS / FONTMAP_BITSPERPAGE)

typedef struct FontFamily {
    struct FontFamily *nextPtr;	/* Next in list of all known font families. */
    int refCount;		/* How many SubFonts are referring to this
    size_t refCount;		/* How many SubFonts are referring to this
				 * FontFamily. When the refCount drops to
				 * zero, this FontFamily may be freed. */
    /*
     * Key.
     */

    Tk_Uid foundry;		/* Foundry key for this FontFamily. */
188
189
190
191
192
193
194
195

196
197
198
199
200
201
202
203
204
205

206
207
208
209
210
211
212
189
190
191
192
193
194
195

196
197
198
199
200
201
202
203
204
205

206
207
208
209
210
211
212
213







-
+









-
+







    {NULL,		NULL}
};

/*
 * Functions used only in this file.
 */

static void		FontPkgCleanup(ClientData clientData);
static void		FontPkgCleanup(void *clientData);
static FontFamily *	AllocFontFamily(Display *display,
			    XFontStruct *fontStructPtr, int base);
static SubFont *	CanUseFallback(UnixFont *fontPtr,
			    const char *fallbackName, int ch,
			    SubFont **fixSubFontPtrPtr);
static SubFont *	CanUseFallbackWithAliases(UnixFont *fontPtr,
			    const char *fallbackName, int ch,
			    Tcl_DString *nameTriedPtr,
			    SubFont **fixSubFontPtrPtr);
static int		ControlUtfProc(ClientData clientData, const char *src,
static int		ControlUtfProc(void *clientData, const char *src,
			    int srcLen, int flags, Tcl_EncodingState*statePtr,
			    char *dst, int dstLen, int *srcReadPtr,
			    int *dstWrotePtr, int *dstCharsPtr);
static XFontStruct *	CreateClosestFont(Tk_Window tkwin,
			    const TkFontAttributes *faPtr,
			    const TkXLFDAttributes *xaPtr);
static SubFont *	FindSubFontForChar(UnixFont *fontPtr, int ch,
233
234
235
236
237
238
239
240

241
242
243
244

245
246
247
248
249
250
251
234
235
236
237
238
239
240

241
242
243
244

245
246
247
248
249
250
251
252







-
+



-
+







static char **		ListFontOrAlias(Display *display, const char*faceName,
			    int *numNamesPtr);
static unsigned		RankAttributes(FontAttributes *wantPtr,
			    FontAttributes *gotPtr);
static void		ReleaseFont(UnixFont *fontPtr);
static void		ReleaseSubFont(Display *display, SubFont *subFontPtr);
static int		SeenName(const char *name, Tcl_DString *dsPtr);
static int		Ucs2beToUtfProc(ClientData clientData, const char*src,
static int		Ucs2beToUtfProc(void *clientData, const char*src,
			    int srcLen, int flags, Tcl_EncodingState*statePtr,
			    char *dst, int dstLen, int *srcReadPtr,
			    int *dstWrotePtr, int *dstCharsPtr);
static int		UtfToUcs2beProc(ClientData clientData, const char*src,
static int		UtfToUcs2beProc(void *clientData, const char*src,
			    int srcLen, int flags, Tcl_EncodingState*statePtr,
			    char *dst, int dstLen, int *srcReadPtr,
			    int *dstWrotePtr, int *dstCharsPtr);

/*
 *-------------------------------------------------------------------------
 *
262
263
264
265
266
267
268
269

270
271

272
273
274
275
276
277
278
263
264
265
266
267
268
269

270
271

272
273
274
275
276
277
278
279







-
+

-
+







 *	Releases thread-specific resources used by font pkg.
 *
 *-------------------------------------------------------------------------
 */

static void
FontPkgCleanup(
    ClientData clientData)
    TCL_UNUSED(void *))
{
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (tsdPtr->controlFamily.encoding != NULL) {
	FontFamily *familyPtr = &tsdPtr->controlFamily;
	int i;

	Tcl_FreeEncoding(familyPtr->encoding);
301
302
303
304
305
306
307
308

309
310

311
312
313
314
315
316
317
302
303
304
305
306
307
308

309
310

311
312
313
314
315
316
317
318







-
+

-
+







 *	None.
 *
 *-------------------------------------------------------------------------
 */

void
TkpFontPkgInit(
    TkMainInfo *mainPtr)	/* The application being created. */
    TCL_UNUSED(TkMainInfo *))	/* The application being created. */
{
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    SubFont dummy;
    int i;
    Tcl_Encoding ucs2;

    if (tsdPtr->controlFamily.encoding == NULL) {

357
358
359
360
361
362
363
364

365
366
367
368


369
370
371
372
373
374
375
358
359
360
361
362
363
364

365
366
367


368
369
370
371
372
373
374
375
376







-
+


-
-
+
+







 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
ControlUtfProc(
    ClientData clientData,	/* Not used. */
    TCL_UNUSED(void *),	/* Not used. */
    const char *src,		/* Source string in UTF-8. */
    int srcLen,			/* Source string length in bytes. */
    int flags,			/* Conversion control flags. */
    Tcl_EncodingState *statePtr,/* Place for conversion routine to store state
    TCL_UNUSED(int),			/* Conversion control flags. */
    TCL_UNUSED(Tcl_EncodingState *),/* Place for conversion routine to store state
				 * information used during a piecewise
				 * conversion. Contents of statePtr are
				 * initialized and/or reset by conversion
				 * routine under control of flags argument. */
    char *dst,			/* Output buffer in which converted string is
				 * stored. */
    int dstLen,			/* The maximum length of output buffer in
385
386
387
388
389
390
391
392
393


394
395
396
397
398
399
400
386
387
388
389
390
391
392


393
394
395
396
397
398
399
400
401







-
-
+
+







    int *dstCharsPtr)		/* Filled with the number of characters that
				 * correspond to the bytes stored in the
				 * output buffer. */
{
    const char *srcStart, *srcEnd;
    char *dstStart, *dstEnd;
    int ch, result;
    static char hexChars[] = "0123456789abcdef";
    static char mapChars[] = {
    static const char hexChars[] = "0123456789ABCDEF";
    static const char mapChars[] = {
	0, 0, 0, 0, 0, 0, 0,
	'a', 'b', 't', 'n', 'v', 'f', 'r'
    };

    result = TCL_OK;

    srcStart = src;
424
425
426
427
428
429
430
431
432
433
434




435
436
437
438
439
440
441
425
426
427
428
429
430
431




432
433
434
435
436
437
438
439
440
441
442







-
-
-
-
+
+
+
+







	    dst[3] = hexChars[(ch >> 8) & 0xF];
	    dst[4] = hexChars[(ch >> 4) & 0xF];
	    dst[5] = hexChars[ch & 0xF];
	    dst += 6;
	} else {
	    /* TODO we can do better here */
	    dst[1] = 'u';
	    dst[2] = 'f';
	    dst[3] = 'f';
	    dst[4] = 'f';
	    dst[5] = 'd';
	    dst[2] = 'F';
	    dst[3] = 'F';
	    dst[4] = 'F';
	    dst[5] = 'D';
	    dst += 6;
	}
    }
    *srcReadPtr = src - srcStart;
    *dstWrotePtr = dst - dstStart;
    *dstCharsPtr = dst - dstStart;
    return result;
455
456
457
458
459
460
461
462

463
464
465
466

467
468
469
470
471
472
473
456
457
458
459
460
461
462

463
464
465
466

467
468
469
470
471
472
473
474







-
+



-
+







 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
Ucs2beToUtfProc(
    ClientData clientData,	/* Not used. */
    TCL_UNUSED(void *),		/* Not used. */
    const char *src,		/* Source string in Unicode. */
    int srcLen,			/* Source string length in bytes. */
    int flags,			/* Conversion control flags. */
    Tcl_EncodingState *statePtr,/* Place for conversion routine to store state
    TCL_UNUSED(Tcl_EncodingState *),/* Place for conversion routine to store state
				 * information used during a piecewise
				 * conversion. Contents of statePtr are
				 * initialized and/or reset by conversion
				 * routine under control of flags argument. */
    char *dst,			/* Output buffer in which converted string is
				 * stored. */
    int dstLen,			/* The maximum length of output buffer in
551
552
553
554
555
556
557
558

559
560
561
562
563

564
565
566
567
568
569
570
552
553
554
555
556
557
558

559
560
561
562
563

564
565
566
567
568
569
570
571







-
+




-
+







 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
UtfToUcs2beProc(
    ClientData clientData,	/* TableEncodingData that specifies
    TCL_UNUSED(void *),	/* TableEncodingData that specifies
				 * encoding. */
    const char *src,		/* Source string in UTF-8. */
    int srcLen,			/* Source string length in bytes. */
    int flags,			/* Conversion control flags. */
    Tcl_EncodingState *statePtr,/* Place for conversion routine to store state
    TCL_UNUSED(Tcl_EncodingState *),/* Place for conversion routine to store state
				 * information used during a piecewise
				 * conversion. Contents of statePtr are
				 * initialized and/or reset by conversion
				 * routine under control of flags argument. */
    char *dst,			/* Output buffer in which converted string is
				 * stored. */
    int dstLen,			/* The maximum length of output buffer in
700
701
702
703
704
705
706
707

708
709
710
711
712
713
714
715
716
717
718
719
720
721
722

723
724
725
726
727
728
729
701
702
703
704
705
706
707

708
709
710
711
712
713
714
715
716
717
718
719
720
721
722

723
724
725
726
727
728
729
730







-
+














-
+







	 * out and lost. But make sure we don't have an "-option value" string
	 * since TkFontParseXLFD would return a false success when attempting
	 * to parse it.
	 */

	if (name[0] == '-') {
	    if (name[1] != '*') {
		char *dash;
		const char *dash;

		dash = strchr(name + 1, '-');
		if ((dash == NULL) || (isspace(UCHAR(dash[-1])))) {
		    return NULL;
		}
	    }
	} else if (name[0] != '*') {
	    return NULL;
	}
	if (TkFontParseXLFD(name, &fa.fa, &fa.xa) != TCL_OK) {
	    return NULL;
	}
	fontStructPtr = CreateClosestFont(tkwin, &fa.fa, &fa.xa);
    }
    fontPtr = ckalloc(sizeof(UnixFont));
    fontPtr = (UnixFont *)ckalloc(sizeof(UnixFont));
    InitFont(tkwin, fontStructPtr, fontPtr);

    return (TkFont *) fontPtr;
}

/*
 *---------------------------------------------------------------------------
771
772
773
774
775
776
777
778

779
780
781
782
783
784
785
772
773
774
775
776
777
778

779
780
781
782
783
784
785
786







-
+







    XFontStruct *fontStructPtr;

    TkInitXLFDAttributes(&xa);
    fontStructPtr = CreateClosestFont(tkwin, faPtr, &xa);

    fontPtr = (UnixFont *) tkFontPtr;
    if (fontPtr == NULL) {
	fontPtr = ckalloc(sizeof(UnixFont));
	fontPtr = (UnixFont *)ckalloc(sizeof(UnixFont));
    } else {
	ReleaseFont(fontPtr);
    }
    InitFont(tkwin, fontStructPtr, fontPtr);

    fontPtr->font.fa.underline = faPtr->underline;
    fontPtr->font.fa.overstrike = faPtr->overstrike;
834
835
836
837
838
839
840
841
842


843
844
845
846
847
848
849
850
851

852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870

871
872
873
874
875
876
877

878
879
880
881
882
883
884
835
836
837
838
839
840
841


842
843
844
845
846
847
848
849
850
851

852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870

871
872
873
874
875
876
877

878
879
880
881
882
883
884
885







-
-
+
+








-
+


















-
+






-
+







 */

void
TkpGetFontFamilies(
    Tcl_Interp *interp,		/* Interp to hold result. */
    Tk_Window tkwin)		/* For display to query. */
{
    int i, new, numNames;
    const char *family, **nameList;
    int i, isNew, numNames;
    char *family, **nameList;
    Tcl_HashTable familyTable;
    Tcl_HashEntry *hPtr;
    Tcl_HashSearch search;
    Tcl_Obj *resultPtr, *strPtr;

    Tcl_InitHashTable(&familyTable, TCL_STRING_KEYS);
    nameList = ListFonts(Tk_Display(tkwin), "*", &numNames);
    for (i = 0; i < numNames; i++) {
	const char *familyEnd;
	char *familyEnd;

	family = strchr(nameList[i] + 1, '-');
	if (family == NULL) {
	    /*
	     * Apparently, sometimes ListFonts() can return a font name with
	     * zero or one '-' character in it. This is probably indicative of
	     * a server misconfiguration, but crashing because of it is a very
	     * bad idea anyway. [Bug 1475865]
	     */

	    continue;
	}
	family++;			/* Advance to char after '-'. */
	familyEnd = strchr(family, '-');
	if (familyEnd == NULL) {
	    continue;			/* See comment above. */
	}
	*familyEnd = '\0';
	Tcl_CreateHashEntry(&familyTable, family, &new);
	Tcl_CreateHashEntry(&familyTable, family, &isNew);
    }
    XFreeFontNames(nameList);

    hPtr = Tcl_FirstHashEntry(&familyTable, &search);
    resultPtr = Tcl_NewObj();
    while (hPtr != NULL) {
	strPtr = Tcl_NewStringObj(Tcl_GetHashKey(&familyTable, hPtr), -1);
	strPtr = Tcl_NewStringObj((const char *)Tcl_GetHashKey(&familyTable, hPtr), -1);
	Tcl_ListObjAppendElement(NULL, resultPtr, strPtr);
	hPtr = Tcl_NextHashEntry(&search);
    }
    Tcl_SetObjResult(interp, resultPtr);

    Tcl_DeleteHashTable(&familyTable);
}
1198
1199
1200
1201
1202
1203
1204
1205

1206
1207
1208
1209
1210
1211
1212
1199
1200
1201
1202
1203
1204
1205

1206
1207
1208
1209
1210
1211
1212
1213







-
+







 */

int
TkpMeasureCharsInContext(
    Tk_Font tkfont,		/* Font in which characters will be drawn. */
    const char *source,		/* UTF-8 string to be displayed. Need not be
				 * '\0' terminated. */
    int numBytes,		/* Maximum number of bytes to consider from
    TCL_UNUSED(int),		/* Maximum number of bytes to consider from
				 * source string in all. */
    int rangeStart,		/* Index of first byte to measure. */
    int rangeLength,		/* Length of range to measure in bytes. */
    int maxLength,		/* If >= 0, maxLength specifies the longest
				 * permissible line length; don't consider any
				 * character that would cross this x-position.
				 * If < 0, then line length is unbounded and
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1221
1222
1223
1224
1225
1226
1227

1228
1229
1230
1231
1232
1233
1234







-







				 * no characters fit. TK_ISOLATE_END means
				 * that the last character should not be
				 * considered in context with the rest of the
				 * string (used for breaking lines). */
    int *lengthPtr)		/* Filled with x-location just after the
				 * terminating character. */
{
    (void) numBytes; /*unused*/
    return Tk_MeasureChars(tkfont, source + rangeStart, rangeLength,
	    maxLength, flags, lengthPtr);
}

/*
 *---------------------------------------------------------------------------
 *
1369
1370
1371
1372
1373
1374
1375



1376
1377
1378
1379
1380
1381
1382
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385







+
+
+







 *
 * TkpDrawCharsInContext --
 *
 *	Draw a string of characters on the screen like Tk_DrawChars(), but
 *	with access to all the characters on the line for context. On X11 this
 *	context isn't consulted, so we just call Tk_DrawChars().
 *
 *      Note: TK_DRAW_IN_CONTEXT being currently defined only on macOS, this
 *            function is unused (and possibly unfinished). See [7655f65ae7].
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Information gets drawn on the screen.
 *
 *---------------------------------------------------------------------------
1392
1393
1394
1395
1396
1397
1398
1399

1400
1401
1402
1403
1404
1405
1406
1407






























1408
1409
1410
1411
1412


1413
1414
1415
1416
1417
1418
1419
1420
1395
1396
1397
1398
1399
1400
1401

1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443


1444
1445
1446
1447
1448
1449
1450
1451
1452
1453







-
+








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
-
+
+








    const char *source,		/* UTF-8 string to be displayed. Need not be
				 * '\0' terminated. All Tk meta-characters
				 * (tabs, control characters, and newlines)
				 * should be stripped out of the string that
				 * is passed to this function. If they are not
				 * stripped out, they will be displayed as
				 * regular printing characters. */
    int numBytes,		/* Number of bytes in string. */
    TCL_UNUSED(int),		/* Number of bytes in string. */
    int rangeStart,		/* Index of first byte to draw. */
    int rangeLength,		/* Length of range to draw in bytes. */
    int x, int y)		/* Coordinates at which to place origin of the
				 * whole (not just the range) string when
				 * drawing. */
{
    int widthUntilStart;

    Tk_MeasureChars(tkfont, source, rangeStart, -1, 0, &widthUntilStart);
    Tk_DrawChars(display, drawable, gc, tkfont, source + rangeStart,
	    rangeLength, x+widthUntilStart, y);
}

void
TkpDrawAngledCharsInContext(
    Display *display,		/* Display on which to draw. */
    Drawable drawable,		/* Window or pixmap in which to draw. */
    GC gc,			/* Graphics context for drawing characters. */
    Tk_Font tkfont,		/* Font in which characters will be drawn; must
				 * be the same as font used in GC. */
    const char * source,	/* UTF-8 string to be displayed. Need not be
				 * '\0' terminated. All Tk meta-characters
				 * (tabs, control characters, and newlines)
				 * should be stripped out of the string that is
				 * passed to this function. If they are not
				 * stripped out, they will be displayed as
				 * regular printing characters. */
    int numBytes,		/* Number of bytes in string. */
    int rangeStart,		/* Index of first byte to draw. */
    int rangeLength,		/* Length of range to draw in bytes. */
    double x, double y,		/* Coordinates at which to place origin of the
				 * whole (not just the range) string when
				 * drawing. */
    double angle)		/* What angle to put text at, in degrees. */
{
    int widthUntilStart;
    double sinA = sin(angle * PI/180.0), cosA = cos(angle * PI/180.0);

    (void) numBytes; /*unused*/

    Tk_MeasureChars(tkfont, source, rangeStart, -1, 0, &widthUntilStart);
    Tk_DrawChars(display, drawable, gc, tkfont, source + rangeStart,
	    rangeLength, x+widthUntilStart, y);
    TkDrawAngledChars(display, drawable, gc, tkfont, source + rangeStart,
	    rangeLength, x+cosA*widthUntilStart, y-sinA*widthUntilStart, angle);
}

/*
 *-------------------------------------------------------------------------
 *
 * CreateClosestFont --
 *
 *	Helper for TkpGetNativeFont() and TkpGetFontFromAttributes(). Given a
1570
1571
1572
1573
1574
1575
1576
1577

1578
1579
1580
1581
1582
1583
1584
1603
1604
1605
1606
1607
1608
1609

1610
1611
1612
1613
1614
1615
1616
1617







-
+







static void
InitFont(
    Tk_Window tkwin,		/* For screen where font will be used. */
    XFontStruct *fontStructPtr,	/* X information about font. */
    UnixFont *fontPtr)		/* Filled with information constructed from
				 * the above arguments. */
{
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    unsigned long value;
    int minHi, maxHi, minLo, maxLo, fixed, width, limit, i, n;
    FontAttributes fa;
    TkFontAttributes *faPtr;
    TkFontMetrics *fmPtr;
    SubFont *controlPtr, *subFontPtr;
1676
1677
1678
1679
1680
1681
1682
1683

1684
1685
1686
1687
1688
1689
1690
1709
1710
1711
1712
1713
1714
1715

1716
1717
1718
1719
1720
1721
1722
1723







-
+







	/*
	 * If the XA_UNDERLINE_THICKNESS property does not exist, the X manual
	 * recommends using the width of the stem on a capital letter. I don't
	 * know of a way to get the stem width of a letter, so guess and use
	 * 1/3 the width of a capital I.
	 */

	fontPtr->barHeight = fontPtr->widths['I'] / 3;
	fontPtr->barHeight = fontPtr->widths[(unsigned char)'I'] / 3;
	if (fontPtr->barHeight == 0) {
	    fontPtr->barHeight = 1;
	}
    }
    if (fontPtr->underlinePos + fontPtr->barHeight > fontStructPtr->descent) {
	/*
	 * If this set of cobbled together values would cause the bottom of
1817
1818
1819
1820
1821
1822
1823
1824

1825
1826
1827
1828
1829
1830

1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849

1850
1851
1852
1853
1854
1855
1856
1850
1851
1852
1853
1854
1855
1856

1857
1858
1859
1860
1861
1862

1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881

1882
1883
1884
1885
1886
1887
1888
1889







-
+





-
+


















-
+







 */

static FontFamily *
AllocFontFamily(
    Display *display,		/* Display in which font will be used. */
    XFontStruct *fontStructPtr,	/* Screen font whose FontFamily is to be
				 * returned. */
    int base)			/* Non-zero if this font family is to be used
    TCL_UNUSED(int))			/* Non-zero if this font family is to be used
				 * in the base font of a font object. */
{
    FontFamily *familyPtr;
    FontAttributes fa;
    Tcl_Encoding encoding;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    GetFontAttributes(display, fontStructPtr, &fa);
    encoding = Tcl_GetEncoding(NULL, GetEncodingAlias(fa.xa.charset));

    familyPtr = tsdPtr->fontFamilyList;
    for (; familyPtr != NULL; familyPtr = familyPtr->nextPtr) {
	if ((familyPtr->faceName == fa.fa.family)
		&& (familyPtr->foundry == fa.xa.foundry)
		&& (familyPtr->encoding == encoding)) {
	    if (encoding) {
		Tcl_FreeEncoding(encoding);
	    }
	    familyPtr->refCount++;
	    return familyPtr;
	}
    }

    familyPtr = ckalloc(sizeof(FontFamily));
    familyPtr = (FontFamily *)ckalloc(sizeof(FontFamily));
    memset(familyPtr, 0, sizeof(FontFamily));
    familyPtr->nextPtr = tsdPtr->fontFamilyList;
    tsdPtr->fontFamilyList = familyPtr;

    /*
     * Set key for this FontFamily.
     */
1899
1900
1901
1902
1903
1904
1905
1906

1907
1908
1909
1910
1911
1912
1913
1914

1915
1916
1917
1918
1919
1920
1921
1932
1933
1934
1935
1936
1937
1938

1939
1940
1941
1942
1943
1944
1945


1946
1947
1948
1949
1950
1951
1952
1953







-
+






-
-
+







 */

static void
FreeFontFamily(
    FontFamily *familyPtr)	/* The FontFamily to delete. */
{
    FontFamily **familyPtrPtr;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    int i;

    if (familyPtr == NULL) {
	return;
    }
    familyPtr->refCount--;
    if (familyPtr->refCount > 0) {
    if (familyPtr->refCount-- > 1) {
	return;
    }
    if (familyPtr->encoding) {
	Tcl_FreeEncoding(familyPtr->encoding);
    }
    for (i = 0; i < FONTMAP_PAGES; i++) {
	if (familyPtr->fontMap[i] != NULL) {
1975
1976
1977
1978
1979
1980
1981
1982

1983
1984
1985
1986
1987
1988
1989
2007
2008
2009
2010
2011
2012
2013

2014
2015
2016
2017
2018
2019
2020
2021







-
+







    const char *const *aliases;
    char **nameList;
    const char *const *anyFallbacks;
    const char *const *const *fontFallbacks;
    SubFont *subFontPtr;
    Tcl_DString ds;

    if (ch < 0 || ch > 0x30000) {
    if (ch < 0 || ch >= FONTMAP_NUMCHARS) {
	ch = 0xFFFD;
    }

    for (i = 0; i < fontPtr->numSubFonts; i++) {
	if (FontMapLookup(&fontPtr->subFontArray[i], ch)) {
	    return &fontPtr->subFontArray[i];
	}
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083




2084
2085
2086
2087
2088
2089
2090
2105
2106
2107
2108
2109
2110
2111




2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122







-
-
-
-
+
+
+
+







    /*
     * Try all face names available in the whole system until we find one that
     * can be used.
     */

    nameList = ListFonts(fontPtr->display, "*", &numNames);
    for (i = 0; i < numNames; i++) {
	fallback = strchr(nameList[i] + 1, '-') + 1;
	strchr(fallback, '-')[0] = '\0';
	if (SeenName(fallback, &ds) == 0) {
	    subFontPtr = CanUseFallback(fontPtr, fallback, ch,
	char *fallbck = strchr(nameList[i] + 1, '-') + 1;
	strchr(fallbck, '-')[0] = '\0';
	if (SeenName(fallbck, &ds) == 0) {
	    subFontPtr = CanUseFallback(fontPtr, fallbck, ch,
		    fixSubFontPtrPtr);
	    if (subFontPtr != NULL) {
		XFreeFontNames(nameList);
		goto end;
	    }
	}
    }
2129
2130
2131
2132
2133
2134
2135
2136

2137
2138
2139
2140
2141
2142
2143
2161
2162
2163
2164
2165
2166
2167

2168
2169
2170
2171
2172
2173
2174
2175







-
+







FontMapLookup(
    SubFont *subFontPtr,	/* Contains font mapping cache to be queried
				 * and possibly updated. */
    int ch)			/* Character to be tested. */
{
    int row, bitOffset;

    if (ch < 0 ||  ch >= 0x30000) {
    if (ch < 0 ||  ch >= FONTMAP_NUMCHARS) {
	return 0;
    }
    row = ch >> FONTMAP_SHIFT;
    if (subFontPtr->fontMap[row] == NULL) {
	FontMapLoadPage(subFontPtr, row);
    }
    bitOffset = ch & (FONTMAP_BITSPERPAGE - 1);
2172
2173
2174
2175
2176
2177
2178
2179

2180
2181
2182
2183
2184
2185
2186
2204
2205
2206
2207
2208
2209
2210

2211
2212
2213
2214
2215
2216
2217
2218







-
+







FontMapInsert(
    SubFont *subFontPtr,	/* Contains font mapping cache to be
				 * updated. */
    int ch)			/* Character to be added to cache. */
{
    int row, bitOffset;

    if (ch >= 0 &&  ch < 0x30000) {
    if (ch >= 0 &&  ch < FONTMAP_NUMCHARS) {
	row = ch >> FONTMAP_SHIFT;
	if (subFontPtr->fontMap[row] == NULL) {
	    FontMapLoadPage(subFontPtr, row);
	}
	bitOffset = ch & (FONTMAP_BITSPERPAGE - 1);
	subFontPtr->fontMap[row][bitOffset >> 3] |= 1 << (bitOffset & 7);
    }
2213
2214
2215
2216
2217
2218
2219
2220

2221
2222
2223

2224
2225
2226
2227
2228
2229
2230
2245
2246
2247
2248
2249
2250
2251

2252
2253
2254

2255
2256
2257
2258
2259
2260
2261
2262







-
+


-
+







{
    char buf[16], src[6];
    int minHi, maxHi, minLo, maxLo, scale, checkLo;
    int i, end, bitOffset, isTwoByteFont, n;
    Tcl_Encoding encoding;
    XFontStruct *fontStructPtr;
    XCharStruct *widths;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    subFontPtr->fontMap[row] = ckalloc(FONTMAP_BITSPERPAGE / 8);
    subFontPtr->fontMap[row] = (char *)ckalloc(FONTMAP_BITSPERPAGE / 8);
    memset(subFontPtr->fontMap[row], 0, FONTMAP_BITSPERPAGE / 8);

    if (subFontPtr->familyPtr == &tsdPtr->controlFamily) {
	return;
    }

    fontStructPtr = subFontPtr->fontStructPtr;
2454
2455
2456
2457
2458
2459
2460
2461

2462
2463
2464
2465
2466
2467
2468
2486
2487
2488
2489
2490
2491
2492

2493
2494
2495
2496
2497
2498
2499
2500







-
+







    want.fa.size = (double)-fontPtr->pixelSize;

    hateFoundry = NULL;
    hateCharset = NULL;
    numEncodings = 0;
    Tcl_DStringInit(&dsEncodings);

    charset = NULL;	/* lint, since numNames must be > 0 to get here. */
    charset = NULL;	/* numNames must be > 0 to get here. */

  retry:
    bestIdx[0] = -1;
    bestIdx[1] = -1;
    bestScore[0] = (unsigned) -1;
    bestScore[1] = (unsigned) -1;
    for (nameIdx = 0; nameIdx < numNames; nameIdx++) {
2548
2549
2550
2551
2552
2553
2554
2555

2556
2557
2558
2559
2560
2561
2562
2580
2581
2582
2583
2584
2585
2586

2587
2588
2589
2590
2591
2592
2593
2594







-
+







    crossout:
	if (nameList == nameListOrig) {
	    /*
	     * Not allowed to change pointers to memory that X gives you, so
	     * make a copy.
	     */

	    nameList = ckalloc(numNames * sizeof(char *));
	    nameList = (char **)ckalloc(numNames * sizeof(char *));
	    memcpy(nameList, nameListOrig, numNames * sizeof(char *));
	}
	nameList[nameIdx] = NULL;
    }

    fontStructPtr = GetScreenFont(display, &want, nameList, bestIdx,
	    bestScore);
2593
2594
2595
2596
2597
2598
2599
2600

2601
2602
2603
2604

2605
2606
2607
2608
2609
2610
2611
2625
2626
2627
2628
2629
2630
2631

2632
2633
2634
2635

2636
2637
2638
2639
2640
2641
2642
2643







-
+



-
+







	ckfree(nameList);
    }
    XFreeFontNames(nameListOrig);

    if (fontPtr->numSubFonts >= SUBFONT_SPACE) {
	SubFont *newPtr;

	newPtr = ckalloc(sizeof(SubFont) * (fontPtr->numSubFonts + 1));
	newPtr = (SubFont *)ckalloc(sizeof(SubFont) * (fontPtr->numSubFonts + 1));
	memcpy(newPtr, fontPtr->subFontArray,
		fontPtr->numSubFonts * sizeof(SubFont));
	if (fixSubFontPtrPtr != NULL) {
	    register SubFont *fixSubFontPtr = *fixSubFontPtrPtr;
	    SubFont *fixSubFontPtr = *fixSubFontPtrPtr;

	    if (fixSubFontPtr != &fontPtr->controlSubFont) {
		*fixSubFontPtrPtr =
			newPtr + (fixSubFontPtr - fontPtr->subFontArray);
	    }
	}
	if (fontPtr->subFontArray != fontPtr->staticSubFonts) {
2683
2684
2685
2686
2687
2688
2689
2690

2691
2692
2693
2694
2695
2696
2697
2698

2699
2700
2701
2702
2703
2704
2705
2715
2716
2717
2718
2719
2720
2721

2722
2723
2724
2725
2726
2727
2728
2729

2730
2731
2732
2733
2734
2735
2736
2737







-
+







-
+







	} else if (diff < 0) {
	    penalty += 150;
	    diff = -diff;
	}
	penalty += diff;
    }
    if (gotPtr->xa.charset != wantPtr->xa.charset) {
	int i;
	size_t i;
	const char *gotAlias, *wantAlias;

	penalty += 65000;
	gotAlias = GetEncodingAlias(gotPtr->xa.charset);
	wantAlias = GetEncodingAlias(wantPtr->xa.charset);
	if (strcmp(gotAlias, wantAlias) != 0) {
	    penalty += 30000;
	    for (i = 0; encodingList[i] != NULL; i++) {
	    for (i = 0; i < sizeof(encodingList)/sizeof(encodingList[0]); i++) {
		if (strcmp(gotAlias, encodingList[i]) == 0) {
		    penalty -= 30000;
		    break;
		}
		penalty += 20000;
	    }
	}
3062
3063
3064
3065
3066
3067
3068
3069

3070
3071
3072
3073

3074
3075
3076
3077
3078
3079






3080
3081
3082
3083
3084
3085
3086
3087







3088
3089
3090
3091




3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107


3108
3109
3110

3111
3112
3113
3114
3115
3116
3117







3118
3119
3120



3121
3122
3123
3124
3125
3126
3127
3094
3095
3096
3097
3098
3099
3100

3101
3102
3103
3104
3105
3106






3107
3108
3109
3110
3111
3112
3113







3114
3115
3116
3117
3118
3119
3120
3121



3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139


3140
3141
3142
3143
3144
3145







3146
3147
3148
3149
3150
3151
3152
3153


3154
3155
3156
3157
3158
3159
3160
3161
3162
3163







-
+




+
-
-
-
-
-
-
+
+
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
+
+
+
+














-
-
+
+



+
-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
+
+
+







    int *realWidthPtr, int *realHeightPtr)
{
    int width, height;
    TkFont *fontPtr = (TkFont *) tkfont;
    Pixmap bitmap;
    GC bitmapGC;
    XGCValues values;
    XImage *image;
    XImage *image = NULL;

    (void) Tk_MeasureChars(tkfont, source, numBytes, -1, 0, &width);
    height = fontPtr->fm.ascent + fontPtr->fm.descent;

    if ((width > 0) && (height > 0)) {
    bitmap = Tk_GetPixmap(display, drawable, width, height, 1);
    values.graphics_exposures = False;
    values.foreground = BlackPixel(display, DefaultScreen(display));
    bitmapGC = XCreateGC(display, bitmap, GCGraphicsExposures|GCForeground,
	    &values);
    XFillRectangle(display, bitmap, bitmapGC, 0, 0, width, height);
	bitmap = Tk_GetPixmap(display, drawable, width, height, 1);
	values.graphics_exposures = False;
	values.foreground = BlackPixel(display, DefaultScreen(display));
	bitmapGC = XCreateGC(display, bitmap, GCGraphicsExposures|GCForeground,
		&values);
	XFillRectangle(display, bitmap, bitmapGC, 0, 0, width, height);

    values.font = Tk_FontId(tkfont);
    values.foreground = WhitePixel(display, DefaultScreen(display));
    values.background = BlackPixel(display, DefaultScreen(display));
    XChangeGC(display, bitmapGC, GCFont|GCForeground|GCBackground, &values);
    Tk_DrawChars(display, bitmap, bitmapGC, tkfont, source, numBytes, 0,
	    fontPtr->fm.ascent);
    XFreeGC(display, bitmapGC);
	values.font = Tk_FontId(tkfont);
	values.foreground = WhitePixel(display, DefaultScreen(display));
	values.background = BlackPixel(display, DefaultScreen(display));
	XChangeGC(display, bitmapGC, GCFont|GCForeground|GCBackground, &values);
	Tk_DrawChars(display, bitmap, bitmapGC, tkfont, source, numBytes, 0,
		fontPtr->fm.ascent);
	XFreeGC(display, bitmapGC);

    image = XGetImage(display, bitmap, 0, 0, width, height, AllPlanes,
	    ZPixmap);
    Tk_FreePixmap(display, bitmap);
	image = XGetImage(display, bitmap, 0, 0, width, height, AllPlanes,
		ZPixmap);
	Tk_FreePixmap(display, bitmap);
    }

    *realWidthPtr = width;
    *realHeightPtr = height;
    return image;
}

static inline XImage *
InitDestImage(
    Display *display,
    Drawable drawable,
    int width,
    int height,
    Pixmap *bitmapPtr)
{
    Pixmap bitmap;
    XImage *image;
    Pixmap bitmap = None;
    XImage *image = NULL;
    GC bitmapGC;
    XGCValues values;

    if ((width > 0) && (height > 0)) {
    bitmap = Tk_GetPixmap(display, drawable, width, height, 1);
    values.graphics_exposures = False;
    values.foreground = BlackPixel(display, DefaultScreen(display));
    bitmapGC = XCreateGC(display, bitmap, GCGraphicsExposures|GCForeground,
	    &values);
    XFillRectangle(display, bitmap, bitmapGC, 0, 0, width, height);
    XFreeGC(display, bitmapGC);
	bitmap = Tk_GetPixmap(display, drawable, width, height, 1);
	values.graphics_exposures = False;
	values.foreground = BlackPixel(display, DefaultScreen(display));
	bitmapGC = XCreateGC(display, bitmap, GCGraphicsExposures|GCForeground,
		&values);
	XFillRectangle(display, bitmap, bitmapGC, 0, 0, width, height);
	XFreeGC(display, bitmapGC);

    image = XGetImage(display, bitmap, 0, 0, width, height, AllPlanes,
	    ZPixmap);
	image = XGetImage(display, bitmap, 0, 0, width, height, AllPlanes,
		ZPixmap);
    }
    *bitmapPtr = bitmap;
    return image;
}

void
TkDrawAngledChars(
    Display *display,		/* Display on which to draw. */
Changes to unix/tkUnixInit.c.
1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16
17

18
19
20
21
22
23
24
1
2
3
4
5

6
7
8
9
10
11
12
13
14
15
16

17
18
19
20
21
22
23
24





-
+










-
+







/*
 * tkUnixInit.c --
 *
 *	This file contains Unix-specific interpreter initialization functions.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright © 1995-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.
 */

#include "tkUnixInt.h"

#ifdef HAVE_COREFOUNDATION
static int		GetLibraryPath(Tcl_Interp *interp);
#else
#define GetLibraryPath(dummy)	(void)0
#define GetLibraryPath(dummy)	(void)dummy
#endif /* HAVE_COREFOUNDATION */

/*
 *----------------------------------------------------------------------
 *
 * TkpInit --
 *
37
38
39
40
41
42
43


44
45
46
47
48
49
50
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52







+
+








int
TkpInit(
    Tcl_Interp *interp)
{
    TkCreateXEventSource();
    GetLibraryPath(interp);
    Tktray_Init(interp);
    (void)SysNotify_Init (interp);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TkpGetAppName --
128
129
130
131
132
133
134

135
136
137
138
139
140
141
142
143
144
145
146
147
148
149

150




151
152
153

154
155
156
157
158
159
160
161
162
130
131
132
133
134
135
136
137
138
139
140
141

142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158

159
160
161
162
163
164
165
166
167
168
169







+




-










+

+
+
+
+

-

+









 *
 * Side effects:
 *	Same as for Tcl_MacOSXOpenVersionedBundleResources.
 *
 *----------------------------------------------------------------------
 */

#ifdef TK_FRAMEWORK
static int
GetLibraryPath(
    Tcl_Interp *interp)
{
#ifdef TK_FRAMEWORK
    int foundInFramework = TCL_ERROR;
    char tkLibPath[PATH_MAX + 1];

    foundInFramework = Tcl_MacOSXOpenVersionedBundleResources(interp,
	    "com.tcltk.tklibrary", TK_FRAMEWORK_VERSION, 0, PATH_MAX,
	    tkLibPath);
    if (tkLibPath[0] != '\0') {
        Tcl_SetVar2(interp, "tk_library", NULL, tkLibPath, TCL_GLOBAL_ONLY);
    }
    return foundInFramework;
}
#else
static int
GetLibraryPath(
    TCL_UNUSED(Tcl_Interp *))
{
    return TCL_ERROR;
#endif
}
#endif
#endif /* HAVE_COREFOUNDATION */

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Changes to unix/tkUnixInt.h.
20
21
22
23
24
25
26



27

28
29
30
31
32
33
34
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38







+
+
+

+







/*
 * Prototypes for procedures that are referenced in files other than the ones
 * they're defined in.
 */

#include "tkIntPlatDecls.h"

MODULE_SCOPE  int       Tktray_Init (Tcl_Interp* interp);
MODULE_SCOPE  int       SysNotify_Init (Tcl_Interp* interp);

#endif /* _TKUNIXINT */


/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
Changes to unix/tkUnixKey.c.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15
16


17
18
19
20
21

22
23
24
25
26
27
28

29
30
31
32
33
34
35
1
2
3
4
5
6

7
8
9
10
11
12
13
14


15
16





17







18
19
20
21
22
23
24
25






-
+







-
-
+
+
-
-
-
-
-
+
-
-
-
-
-
-
-
+







/*
 * tkUnixKey.c --
 *
 *	This file contains routines for dealing with international keyboard
 *	input.
 *
 * Copyright (c) 1997 by 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.
 */

#include "tkInt.h"

/*
** Bug [3607830]: Before using Xkb, it must be initialized.  TkpOpenDisplay
#undef register /* Keyword "register" is used in XKBlib.h, so don't try tricky things here */
#define XkbOpenDisplay XkbOpenDisplay_ /* Move out of the way, conflicting definitions */
**                does this and sets the USE_XKB flag if xkb is supported.
**                (should this be function ptr?)
*/
#ifdef HAVE_XKBKEYCODETOKEYSYM
#  include <X11/XKBlib.h>
#include <X11/XKBlib.h>
#else
#  define XkbKeycodeToKeysym(D,K,G,L) XKeycodeToKeysym(D,K,L)
#endif
#define TkKeycodeToKeysym(D,K,G,L)		\
    ((D)->flags & TK_DISPLAY_USE_XKB) ?		\
      XkbKeycodeToKeysym((D)->display,K,G,L) :	\
      XKeycodeToKeysym((D)->display,K,L)
#undef XkbOpenDisplay

/*
 * Prototypes for local functions defined in this file:
 */

/*
 *----------------------------------------------------------------------
106
107
108
109
110
111
112
113

114
115
116
117
118
119
120
121
122
123
124

125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141

142
143
144
145
146
147
148
149
96
97
98
99
100
101
102

103
104
105
106
107
108
109
110
111
112
113

114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130

131

132
133
134
135
136
137
138







-
+










-
+
















-
+
-








const char *
TkpGetString(
    TkWindow *winPtr,		/* Window where event occurred */
    XEvent *eventPtr,		/* X keyboard event. */
    Tcl_DString *dsPtr)		/* Initialized, empty string to hold result. */
{
    int len;
    TkSizeT len;
    Tcl_DString buf;
    TkKeyEvent *kePtr = (TkKeyEvent *) eventPtr;

    /*
     * If we have the value cached already, use it now. [Bug 1373712]
     */

    if (kePtr->charValuePtr != NULL) {
	Tcl_DStringSetLength(dsPtr, kePtr->charValueLen);
	memcpy(Tcl_DStringValue(dsPtr), kePtr->charValuePtr,
		(unsigned) kePtr->charValueLen+1);
		kePtr->charValueLen+1);
	return Tcl_DStringValue(dsPtr);
    }

    /*
     * Only do this for KeyPress events, otherwise
     * further Xlib function behavior might be undefined.
     */

    if (eventPtr->type != KeyPress) {
	len = 0;
	Tcl_DStringSetLength(dsPtr, len);
	goto done;
    }

#ifdef TK_USE_INPUT_METHODS
    if ((winPtr->dispPtr->flags & TK_DISPLAY_USE_IM)
	    && (winPtr->inputContext != NULL)
	    && (winPtr->inputContext != NULL)) {
	    && (eventPtr->type == KeyPress)) {
	Status status;

#if X_HAVE_UTF8_STRING
	Tcl_DStringSetLength(dsPtr, TCL_DSTRING_STATIC_SIZE-1);
	len = Xutf8LookupString(winPtr->inputContext, &eventPtr->xkey,
		Tcl_DStringValue(dsPtr), Tcl_DStringLength(dsPtr),
		&kePtr->keysym, &status);
190
191
192
193
194
195
196
197

198
199
200
201
202
203
204
205
179
180
181
182
183
184
185

186

187
188
189
190
191
192
193







-
+
-







	Tcl_DStringFree(&buf);
#endif /* X_HAVE_UTF8_STRING */
    } else
#endif /* TK_USE_INPUT_METHODS */
    {
	/*
	 * Fall back to convert a keyboard event to a UTF-8 string using
	 * XLookupString. This is used when input methods are turned off and
	 * XLookupString. This is used when input methods are turned off.
	 * for KeyRelease events.
	 *
	 * Note: XLookupString() normally returns a single ISO Latin 1 or
	 * ASCII control character.
	 */

	Tcl_DStringInit(&buf);
	Tcl_DStringSetLength(&buf, TCL_DSTRING_STATIC_SIZE-1);
225
226
227
228
229
230
231
232

233
234

235
236
237
238
239
240

241
242
243
244
245
246
247
213
214
215
216
217
218
219

220
221

222
223
224
225
226
227

228
229
230
231
232
233
234
235







-
+

-
+





-
+







    /*
     * Cache the string in the event so that if/when we return to this
     * function, we will be able to produce it without asking X. This stops us
     * from having to reenter the XIM engine. [Bug 1373712]
     */

done:
    kePtr->charValuePtr = ckalloc(len + 1);
    kePtr->charValuePtr = (char *)ckalloc(len + 1);
    kePtr->charValueLen = len;
    memcpy(kePtr->charValuePtr, Tcl_DStringValue(dsPtr), (unsigned) len + 1);
    memcpy(kePtr->charValuePtr, Tcl_DStringValue(dsPtr), len + 1);
    return Tcl_DStringValue(dsPtr);
}

/*
 * When mapping from a keysym to a keycode, need information about the
 * modifier state to be used so that when they call TkKeycodeToKeysym taking
 * modifier state to be used so that when they call XbkKeycodeToKeysym taking
 * into account the xkey.state, they will get back the original keysym.
 */

void
TkpSetKeycodeAndState(
    Tk_Window tkwin,
    KeySym keySym,
311
312
313
314
315
316
317








318
319
320
321
322
323
324
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320







+
+
+
+
+
+
+
+







TkpGetKeySym(
    TkDisplay *dispPtr,		/* Display in which to map keycode. */
    XEvent *eventPtr)		/* Description of X event. */
{
    KeySym sym;
    int index;
    TkKeyEvent* kePtr = (TkKeyEvent*) eventPtr;

    /*
     * X11 keycodes always lie in the inclusive range [8,255].
     */

    if (eventPtr->xkey.keycode > 0xff) {
        return NoSymbol;
    }

    /*
     * Refresh the mapping information if it's stale. This must happen before
     * we do any input method processing. [Bug 3599312]
     */

    if (dispPtr->bindInfoStale) {
359
360
361
362
363
364
365
366

367
368
369
370
371
372
373
374




375
376
377
378
379

380
381

382
383
384
385
386
387
388
389
390
391
392

393
394
395
396
397
398
399
355
356
357
358
359
360
361

362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378

379
380

381
382
383
384
385
386
387
388
389
390
391

392
393
394
395
396
397
398
399







-
+








+
+
+
+




-
+

-
+










-
+







	index = 2;
    }
    if ((eventPtr->xkey.state & ShiftMask)
	    || ((dispPtr->lockUsage != LU_IGNORE)
	    && (eventPtr->xkey.state & LockMask))) {
	index += 1;
    }
    sym = TkKeycodeToKeysym(dispPtr, eventPtr->xkey.keycode, 0,
    sym = XkbKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode, 0,
	    index);

    /*
     * Special handling: if the key was shifted because of Lock, but lock is
     * only caps lock, not shift lock, and the shifted keysym isn't upper-case
     * alphabetic, then switch back to the unshifted keysym.
     */

#ifndef XK_Oslash
    /* XK_Oslash is the official name, but might not be present in older X11 headers */
#   define XK_Oslash XK_Ooblique
#endif
    if ((index & 1) && !(eventPtr->xkey.state & ShiftMask)
	    && (dispPtr->lockUsage == LU_CAPS)) {
	if (!(((sym >= XK_A) && (sym <= XK_Z))
		|| ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis))
		|| ((sym >= XK_Ooblique) && (sym <= XK_Thorn)))) {
		|| ((sym >= XK_Oslash) && (sym <= XK_Thorn)))) {
	    index &= ~1;
	    sym = TkKeycodeToKeysym(dispPtr, eventPtr->xkey.keycode,
	    sym = XkbKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode,
		    0, index);
	}
    }

    /*
     * Another bit of special handling: if this is a shifted key and there is
     * no keysym defined, then use the keysym for the unshifted key.
     */

    if ((index & 1) && (sym == NoSymbol)) {
	sym = TkKeycodeToKeysym(dispPtr, eventPtr->xkey.keycode,
	sym = XkbKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode,
		0, index & ~1);
    }
    return sym;
}

/*
 *--------------------------------------------------------------
435
436
437
438
439
440
441
442

443
444
445
446
447
448
449
435
436
437
438
439
440
441

442
443
444
445
446
447
448
449







-
+








    dispPtr->lockUsage = LU_IGNORE;
    codePtr = modMapPtr->modifiermap + modMapPtr->max_keypermod*LockMapIndex;
    for (count = modMapPtr->max_keypermod; count > 0; count--, codePtr++) {
	if (*codePtr == 0) {
	    continue;
	}
	keysym = TkKeycodeToKeysym(dispPtr, *codePtr, 0, 0);
	keysym = XkbKeycodeToKeysym(dispPtr->display, *codePtr, 0, 0);
	if (keysym == XK_Shift_Lock) {
	    dispPtr->lockUsage = LU_SHIFT;
	    break;
	}
	if (keysym == XK_Caps_Lock) {
	    dispPtr->lockUsage = LU_CAPS;
	    break;
461
462
463
464
465
466
467
468


469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489

490
491
492
493
494
495
496
461
462
463
464
465
466
467

468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489

490
491
492
493
494
495
496
497







-
+
+




















-
+







    dispPtr->altModMask = 0;
    codePtr = modMapPtr->modifiermap;
    max = 8 * modMapPtr->max_keypermod;
    for (i = 0; i < max; i++, codePtr++) {
	if (*codePtr == 0) {
	    continue;
	}
	keysym = TkKeycodeToKeysym(dispPtr, *codePtr, 0, 0);
	keysym = XkbKeycodeToKeysym(dispPtr->display, *codePtr, 0, 0);

	if (keysym == XK_Mode_switch) {
	    dispPtr->modeModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
	}
	if ((keysym == XK_Meta_L) || (keysym == XK_Meta_R)) {
	    dispPtr->metaModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
	}
	if ((keysym == XK_Alt_L) || (keysym == XK_Alt_R)) {
	    dispPtr->altModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
	}
    }

    /*
     * Create an array of the keycodes for all modifier keys.
     */

    if (dispPtr->modKeyCodes != NULL) {
	ckfree(dispPtr->modKeyCodes);
    }
    dispPtr->numModKeyCodes = 0;
    arraySize = KEYCODE_ARRAY_SIZE;
    dispPtr->modKeyCodes = ckalloc(KEYCODE_ARRAY_SIZE * sizeof(KeyCode));
    dispPtr->modKeyCodes = (KeyCode *)ckalloc(KEYCODE_ARRAY_SIZE * sizeof(KeyCode));
    for (i = 0, codePtr = modMapPtr->modifiermap; i < max; i++, codePtr++) {
	if (*codePtr == 0) {
	    continue;
	}

	/*
	 * Make sure that the keycode isn't already in the array.
509
510
511
512
513
514
515
516

517
518
519
520
521
522
523
510
511
512
513
514
515
516

517
518
519
520
521
522
523
524







-
+







	    KeyCode *newCodes;

	    /*
	     * Ran out of space in the array; grow it.
	     */

	    arraySize *= 2;
	    newCodes = ckalloc(arraySize * sizeof(KeyCode));
	    newCodes = (KeyCode *)ckalloc(arraySize * sizeof(KeyCode));
	    memcpy(newCodes, dispPtr->modKeyCodes,
		    dispPtr->numModKeyCodes * sizeof(KeyCode));
	    ckfree(dispPtr->modKeyCodes);
	    dispPtr->modKeyCodes = newCodes;
	}
	dispPtr->modKeyCodes[dispPtr->numModKeyCodes] = *codePtr;
	dispPtr->numModKeyCodes++;
Changes to unix/tkUnixMenu.c.
1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16
17
18
19
1
2
3
4
5

6
7
8
9
10
11

12
13
14
15
16
17
18





-
+





-







/*
 * tkUnixMenu.c --
 *
 *	This module implements the UNIX platform-specific features of menus.
 *
 * 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.
 */

#include "default.h"
#include "tkUnixInt.h"
#include "tkMenu.h"

/*
 * Constants used for menu drawing.
 */

141
142
143
144
145
146
147
148

149
150
151
152
153
154
155
140
141
142
143
144
145
146

147
148
149
150
151
152
153
154







-
+







 *	All platform-specific allocations are freed up.
 *
 *----------------------------------------------------------------------
 */

void
TkpDestroyMenu(
    TkMenu *menuPtr)
    TCL_UNUSED(TkMenu *))
{
    /*
     * Nothing to do.
     */
}

/*
167
168
169
170
171
172
173
174

175
176
177
178
179
180
181
166
167
168
169
170
171
172

173
174
175
176
177
178
179
180







-
+







 *	All platform specific allocations are freed up.
 *
 *----------------------------------------------------------------------
 */

void
TkpDestroyMenuEntry(
    TkMenuEntry *mEntryPtr)
    TCL_UNUSED(TkMenuEntry *))
{
    /*
     * Nothing to do.
     */
}

/*
195
196
197
198
199
200
201
202

203
204
205
206
207
208
209
194
195
196
197
198
199
200

201
202
203
204
205
206
207
208







-
+







 *	if any need it.
 *
 *----------------------------------------------------------------------
 */

int
TkpConfigureMenuEntry(
    register TkMenuEntry *mePtr)/* Information about menu entry; may or may
    TkMenuEntry *mePtr)/* Information about menu entry; may or may
				 * not already have values for some fields. */
{
    /*
     * If this is a cascade menu, and the child menu exists, check to see if
     * the child menu is a help menu.
     */

235
236
237
238
239
240
241
242

243
244
245
246
247
248
249
234
235
236
237
238
239
240

241
242
243
244
245
246
247
248







-
+







 *	None on Unix.
 *
 *----------------------------------------------------------------------
 */

int
TkpMenuNewEntry(
    TkMenuEntry *mePtr)
    TCL_UNUSED(TkMenuEntry *))
{
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
288
289
290
291
292
293
294
295
296
297



298
299
300
301
302
303
304
287
288
289
290
291
292
293



294
295
296
297
298
299
300
301
302
303







-
-
-
+
+
+







 *	Recompute geometry of given window.
 *
 *----------------------------------------------------------------------
 */

void
TkpSetMainMenubar(
    Tcl_Interp *interp,
    Tk_Window tkwin,
    const char *menuName)
    TCL_UNUSED(Tcl_Interp *),
    TCL_UNUSED(Tk_Window),
    TCL_UNUSED(const char *))
{
    /*
     * Nothing to do.
     */
}

/*
319
320
321
322
323
324
325
326
327


328
329
330
331
332
333
334
318
319
320
321
322
323
324


325
326
327
328
329
330
331
332
333







-
-
+
+







 *----------------------------------------------------------------------
 */

static void
GetMenuIndicatorGeometry(
    TkMenu *menuPtr,		/* The menu we are drawing. */
    TkMenuEntry *mePtr,		/* The entry we are interested in. */
    Tk_Font tkfont,		/* The precalculated font */
    const Tk_FontMetrics *fmPtr,/* The precalculated metrics */
    TCL_UNUSED(Tk_Font),		/* The precalculated font */
    TCL_UNUSED(const Tk_FontMetrics *),/* The precalculated metrics */
    int *widthPtr,		/* The resulting width */
    int *heightPtr)		/* The resulting height */
{
    int borderWidth;

    if ((mePtr->type == CHECK_BUTTON_ENTRY)
	    || (mePtr->type == RADIO_BUTTON_ENTRY)) {
439
440
441
442
443
444
445
446

447
448
449
450
451
452
453
454
455
438
439
440
441
442
443
444

445
446

447
448
449
450
451
452
453







-
+

-







    	bgBorder = activeBorder;

	if ((menuPtr->menuType == MENUBAR)
		&& ((menuPtr->postedCascade == NULL)
		|| (menuPtr->postedCascade != mePtr))) {
	    relief = TK_RELIEF_FLAT;
	} else {
	    relief = TK_RELIEF_RAISED;
	    Tk_GetReliefFromObj(NULL, menuPtr->activeReliefPtr, &relief);
	}

	Tk_GetPixelsFromObj(NULL, menuPtr->tkwin,
		menuPtr->activeBorderWidthPtr, &activeBorderWidth);
	Tk_Fill3DRectangle(menuPtr->tkwin, d, bgBorder, x, y, width, height,
		activeBorderWidth, relief);
    } else {
	Tk_Fill3DRectangle(menuPtr->tkwin, d, bgBorder, x, y, width, height,
		0, TK_RELIEF_FLAT);
520
521
522
523
524
525
526
527

528
529
530
531
532
533
534
518
519
520
521
522
523
524

525
526
527
528
529
530
531
532







-
+







	const char *accel = Tcl_GetString(mePtr->accelPtr);
	int left = x + mePtr->labelWidth + activeBorderWidth
		+ mePtr->indicatorSpace;

	if (menuPtr->menuType == MENUBAR) {
	    left += 5;
	}
    	Tk_DrawChars(menuPtr->display, d, gc, tkfont, accel,
	Tk_DrawChars(menuPtr->display, d, gc, tkfont, accel,
		mePtr->accelLength, left,
		(y + (height + fmPtr->ascent - fmPtr->descent) / 2));
    }
}

/*
 *----------------------------------------------------------------------
550
551
552
553
554
555
556
557
558


559
560
561

562
563
564
565
566
567
568
548
549
550
551
552
553
554


555
556
557
558

559
560
561
562
563
564
565
566







-
-
+
+


-
+







DrawMenuEntryIndicator(
    TkMenu *menuPtr,		/* The menu we are drawing */
    TkMenuEntry *mePtr,		/* The entry we are drawing */
    Drawable d,			/* The drawable to draw into */
    Tk_3DBorder border,		/* The background color */
    XColor *indicatorColor,	/* The color to draw indicators with */
    XColor *disableColor,	/* The color use use when disabled */
    Tk_Font tkfont,		/* The font to draw with */
    const Tk_FontMetrics *fmPtr,/* The font metrics of the font */
    TCL_UNUSED(Tk_Font),		/* The font to draw with */
    TCL_UNUSED(const Tk_FontMetrics *),/* The font metrics of the font */
    int x,			/* The left of the entry rect */
    int y,			/* The top of the entry rect */
    int width,			/* Width of menu entry */
    TCL_UNUSED(int),			/* Width of menu entry */
    int height)			/* Height of menu entry */
{
    /*
     * Draw check-button indicator.
     */

    if ((mePtr->type == CHECK_BUTTON_ENTRY) && mePtr->indicatorOn) {
619
620
621
622
623
624
625
626

627
628
629
630



631
632
633
634
635
636
637
638
639
640
641
642
643
617
618
619
620
621
622
623

624
625



626
627
628
629
630
631
632
633

634
635
636
637
638
639
640







-
+

-
-
-
+
+
+





-







 *
 *----------------------------------------------------------------------
 */

static void
DrawMenuSeparator(
    TkMenu *menuPtr,		/* The menu we are drawing */
    TkMenuEntry *mePtr,		/* The entry we are drawing */
    TCL_UNUSED(TkMenuEntry *),		/* The entry we are drawing */
    Drawable d,			/* The drawable we are using */
    GC gc,			/* The gc to draw into */
    Tk_Font tkfont,		/* The font to draw with */
    const Tk_FontMetrics *fmPtr,/* The font metrics from the font */
    TCL_UNUSED(GC),			/* The gc to draw into */
    TCL_UNUSED(Tk_Font),		/* The font to draw with */
    TCL_UNUSED(const Tk_FontMetrics *),/* The font metrics from the font */
    int x, int y,
    int width, int height)
{
    XPoint points[2];
    Tk_3DBorder border;

    if (menuPtr->menuType == MENUBAR) {
	return;
    }

    points[0].x = x;
    points[0].y = y + height/2;
    points[1].x = x + width - 1;
786
787
788
789
790
791
792
793

794
795
796
797
798
799
800
783
784
785
786
787
788
789

790
791
792
793
794
795
796
797







-
+







		    imageWidth, imageHeight, d, leftEdge + imageXOffset,
		    (int) (y + (mePtr->height-imageHeight)/2 + imageYOffset));
    	} else {
	    Tk_RedrawImage(mePtr->image, 0, 0, imageWidth,
		    imageHeight, d, leftEdge + imageXOffset,
		    (int) (y + (mePtr->height-imageHeight)/2 + imageYOffset));
    	}
    } else if (mePtr->bitmapPtr != None) {
    } else if (mePtr->bitmapPtr != NULL) {
	Pixmap bitmap = Tk_GetBitmapFromObj(menuPtr->tkwin, mePtr->bitmapPtr);

	XCopyPlane(menuPtr->display, bitmap, d,	gc, 0, 0,
		(unsigned) imageWidth, (unsigned) imageHeight,
		leftEdge + imageXOffset,
		(int) (y + (mePtr->height - imageHeight)/2 + imageYOffset), 1);
    }
814
815
816
817
818
819
820
821

822
823
824
825
826
827
828
811
812
813
814
815
816
817

818
819
820
821
822
823
824
825







-
+







    }

    if (mePtr->state == ENTRY_DISABLED) {
	if (menuPtr->disabledFgPtr == NULL) {
	    XFillRectangle(menuPtr->display, d, menuPtr->disabledGC, x, y,
		    (unsigned) width, (unsigned) height);
	} else if ((mePtr->image != NULL)
		&& (menuPtr->disabledImageGC != None)) {
		&& (menuPtr->disabledImageGC != NULL)) {
	    XFillRectangle(menuPtr->display, d, menuPtr->disabledImageGC,
		    leftEdge + imageXOffset,
		    (int) (y + (mePtr->height - imageHeight)/2 + imageYOffset),
		    (unsigned) imageWidth, (unsigned) imageHeight);
	}
    }
}
848
849
850
851
852
853
854
855

856
857
858
859
860
861
862

863
864
865
866
867

868
869
870
871
872
873
874
845
846
847
848
849
850
851

852
853
854
855
856
857
858

859
860
861
862
863

864
865
866
867
868
869
870
871







-
+






-
+




-
+







    TkMenu *menuPtr,		/* The menu to draw into */
    TkMenuEntry *mePtr,		/* The entry we are drawing */
    Drawable d,			/* What we are drawing into */
    GC gc,			/* The gc to draw into */
    Tk_Font tkfont,		/* The precalculated font */
    const Tk_FontMetrics *fmPtr,/* The precalculated font metrics */
    int x, int y,
    int width, int height)
    TCL_UNUSED(int), int height)
{
    if ((mePtr->underline >= 0) && (mePtr->labelPtr != NULL)) {
	int len;

	len = Tcl_GetCharLength(mePtr->labelPtr);
	if (mePtr->underline < len) {
	    int activeBorderWidth, leftEdge;
	    int activeBorderWidth, leftEdge, ch;
	    const char *label, *start, *end;

	    label = Tcl_GetString(mePtr->labelPtr);
	    start = Tcl_UtfAtIndex(label, mePtr->underline);
	    end = Tcl_UtfNext(start);
	    end = start + TkUtfToUniChar(start, &ch);

	    Tk_GetPixelsFromObj(NULL, menuPtr->tkwin,
		    menuPtr->activeBorderWidthPtr, &activeBorderWidth);
	    leftEdge = x + mePtr->indicatorSpace + activeBorderWidth;
	    if (menuPtr->menuType == MENUBAR) {
		leftEdge += 5;
	    }
927
928
929
930
931
932
933
934

935
936
937
938
939
940
941
942

943
944
945
946
947
948
949
924
925
926
927
928
929
930

931
932
933
934
935
936
937
938

939
940
941
942
943
944
945
946







-
+







-
+







 *	The menu is posted.
 *
 *----------------------------------------------------------------------
 */

int
TkpPostTearoffMenu(
    Tcl_Interp *interp,		/* The interpreter of the menu */
    TCL_UNUSED(Tcl_Interp *),		/* The interpreter of the menu */
    TkMenu *menuPtr,		/* The menu we are posting */
    int x, int y, int index)	/* The root X,Y coordinates where the
				 * specified entry will be posted */
{
    int vRootX, vRootY, vRootWidth, vRootHeight;
    int result;

    if (index >= menuPtr->numEntries) {
    if (index >= (int)menuPtr->numEntries) {
	index = menuPtr->numEntries - 1;
    }
    if (index >= 0) {
	y -= menuPtr->entries[index]->y;
    }

    TkActivateMenuEntry(menuPtr, -1);
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026



1027
1028
1029
1030
1031
1032
1033
1014
1015
1016
1017
1018
1019
1020



1021
1022
1023
1024
1025
1026
1027
1028
1029
1030







-
-
-
+
+
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
GetMenuSeparatorGeometry(
    TkMenu *menuPtr,		/* The menu we are measuring */
    TkMenuEntry *mePtr,		/* The entry we are measuring */
    Tk_Font tkfont,		/* The precalculated font */
    TCL_UNUSED(TkMenu *),		/* The menu we are measuring */
    TCL_UNUSED(TkMenuEntry *),		/* The entry we are measuring */
    TCL_UNUSED(Tk_Font),		/* The precalculated font */
    const Tk_FontMetrics *fmPtr,/* The precalcualted font metrics */
    int *widthPtr,		/* The resulting width */
    int *heightPtr)		/* The resulting height */
{
    *widthPtr = 0;
    *heightPtr = fmPtr->linespace;
}
1047
1048
1049
1050
1051
1052
1053
1054

1055
1056
1057
1058
1059
1060

1061
1062
1063
1064
1065
1066
1067
1044
1045
1046
1047
1048
1049
1050

1051
1052
1053
1054
1055
1056

1057
1058
1059
1060
1061
1062
1063
1064







-
+





-
+







 *
 *----------------------------------------------------------------------
 */

static void
GetTearoffEntryGeometry(
    TkMenu *menuPtr,		/* The menu we are drawing */
    TkMenuEntry *mePtr,		/* The entry we are measuring */
    TCL_UNUSED(TkMenuEntry *),		/* The entry we are measuring */
    Tk_Font tkfont,		/* The precalculated font */
    const Tk_FontMetrics *fmPtr,/* The precalculated font metrics */
    int *widthPtr,		/* The resulting width */
    int *heightPtr)		/* The resulting height */
{
    if (menuPtr->menuType != MASTER_MENU) {
    if (menuPtr->menuType != MAIN_MENU) {
	*heightPtr = 0;
	*widthPtr = 0;
    } else {
	*heightPtr = fmPtr->linespace;
	*widthPtr = Tk_TextWidth(tkfont, "W", 1);
    }
}
1088
1089
1090
1091
1092
1093
1094
1095

1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1085
1086
1087
1088
1089
1090
1091

1092
1093
1094
1095
1096
1097
1098


1099
1100
1101
1102
1103
1104
1105







-
+






-
-







TkpComputeMenubarGeometry(
    TkMenu *menuPtr)		/* Structure describing menu. */
{
    Tk_Font tkfont, menuFont;
    Tk_FontMetrics menuMetrics, entryMetrics, *fmPtr;
    int width, height, i, j, x, y, currentRowHeight, maxWidth;
    int maxWindowWidth, lastRowBreak, lastEntry;
    int borderWidth, activeBorderWidth, helpMenuIndex = -1;
    int activeBorderWidth, helpMenuIndex = -1;
    TkMenuEntry *mePtr;

    if (menuPtr->tkwin == NULL) {
	return;
    }

    Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->borderWidthPtr,
	    &borderWidth);
    Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->activeBorderWidthPtr,
	    &activeBorderWidth);
    maxWidth = 0;
    if (menuPtr->numEntries == 0) {
	height = 0;
    } else {
	int borderWidth;
1118
1119
1120
1121
1122
1123
1124
1125

1126
1127
1128
1129
1130
1131
1132
1133
1134

1135
1136
1137
1138
1139
1140
1141
1113
1114
1115
1116
1117
1118
1119

1120
1121
1122
1123
1124
1125
1126
1127
1128

1129
1130
1131
1132
1133
1134
1135
1136







-
+








-
+







		&borderWidth);
	x = y = borderWidth;
	lastRowBreak = 0;

	/*
	 * On the Mac especially, getting font metrics can be quite slow, so
	 * we want to do it intelligently. We are going to precalculate them
	 * and pass them down to all of the measureing and drawing routines.
	 * and pass them down to all of the measuring and drawing routines.
	 * We will measure the font metrics of the menu once, and if an entry
	 * has a font set, we will measure it as we come to it, and then we
	 * decide which set to give the geometry routines.
	 */

	menuFont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr);
	Tk_GetFontMetrics(menuFont, &menuMetrics);

	for (i = 0; i < menuPtr->numEntries; i++) {
	for (i = 0; i < (int)menuPtr->numEntries; i++) {
	    mePtr = menuPtr->entries[i];
	    mePtr->entryFlags &= ~ENTRY_LAST_COLUMN;
	    if (mePtr->fontPtr != NULL) {
		tkfont = Tk_GetFontFromObj(menuPtr->tkwin, mePtr->fontPtr);
		Tk_GetFontMetrics(tkfont, &entryMetrics);
		fmPtr = &entryMetrics;
	    } else {
1204
1205
1206
1207
1208
1209
1210
1211

1212
1213
1214
1215
1216
1217
1218
1199
1200
1201
1202
1203
1204
1205

1206
1207
1208
1209
1210
1211
1212
1213







-
+







	    lastEntry--;
	}
	if ((lastEntry >= 0) && (x + menuPtr->entries[lastEntry]->width
		+ borderWidth > maxWidth)) {
	    maxWidth = x + menuPtr->entries[lastEntry]->width + borderWidth;
	}
	x = borderWidth;
	for (j = lastRowBreak; j < menuPtr->numEntries; j++) {
	for (j = lastRowBreak; j < (int)menuPtr->numEntries; j++) {
	    if (j == helpMenuIndex) {
		continue;
	    }
	    menuPtr->entries[j]->y = y + currentRowHeight
		    - menuPtr->entries[j]->height;
	    menuPtr->entries[j]->x = x;
	    x += menuPtr->entries[j]->width;
1265
1266
1267
1268
1269
1270
1271
1272

1273
1274
1275
1276



1277
1278
1279
1280
1281
1282
1283
1284

1285
1286
1287
1288
1289
1290
1291
1260
1261
1262
1263
1264
1265
1266

1267
1268



1269
1270
1271
1272
1273
1274
1275
1276
1277
1278

1279
1280
1281
1282
1283
1284
1285
1286







-
+

-
-
-
+
+
+







-
+







 *
 *----------------------------------------------------------------------
 */

static void
DrawTearoffEntry(
    TkMenu *menuPtr,		/* The menu we are drawing */
    TkMenuEntry *mePtr,		/* The entry we are drawing */
    TCL_UNUSED(TkMenuEntry *),		/* The entry we are drawing */
    Drawable d,			/* The drawable we are drawing into */
    GC gc,			/* The gc we are drawing with */
    Tk_Font tkfont,		/* The font we are drawing with */
    const Tk_FontMetrics *fmPtr,/* The metrics we are drawing with */
    TCL_UNUSED(GC),			/* The gc we are drawing with */
    TCL_UNUSED(Tk_Font),		/* The font we are drawing with */
    TCL_UNUSED(const Tk_FontMetrics *),/* The metrics we are drawing with */
    int x, int y,
    int width, int height)
{
    XPoint points[2];
    int segmentWidth, maxX;
    Tk_3DBorder border;

    if (menuPtr->menuType != MASTER_MENU) {
    if (menuPtr->menuType != MAIN_MENU) {
	return;
    }

    points[0].x = x;
    points[0].y = y + height/2;
    points[1].y = points[0].y;
    segmentWidth = 6;
1320
1321
1322
1323
1324
1325
1326
1327
1328


1329
1330
1331
1332
1333
1334
1335
1315
1316
1317
1318
1319
1320
1321


1322
1323
1324
1325
1326
1327
1328
1329
1330







-
-
+
+







 *	Alt-key bindings.
 *
 *--------------------------------------------------------------
 */

void
TkpInitializeMenuBindings(
    Tcl_Interp *interp,		/* The interpreter to set. */
    Tk_BindingTable bindingTable)
    TCL_UNUSED(Tcl_Interp *),		/* The interpreter to set. */
    TCL_UNUSED(Tk_BindingTable))
				/* The table to add to. */
{
    /*
     * Nothing to do.
     */
}

1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380





1381
1382

1383
1384
1385

1386
1387
1388
1389
1390
1391
1392
1364
1365
1366
1367
1368
1369
1370





1371
1372
1373
1374
1375
1376

1377
1378
1379

1380
1381
1382
1383
1384
1385
1386
1387







-
-
-
-
-
+
+
+
+
+

-
+


-
+







	return;
    }

    for (cascadeEntryPtr = menuPtr->menuRefPtr->parentEntryPtr;
	    cascadeEntryPtr != NULL;
	    cascadeEntryPtr = cascadeEntryPtr->nextCascadePtr) {
	if ((cascadeEntryPtr->menuPtr->menuType == MENUBAR)
		&& (cascadeEntryPtr->menuPtr->masterMenuPtr->tkwin != NULL)
		&& (menuPtr->masterMenuPtr->tkwin != NULL)) {
	    TkMenu *masterMenuPtr = cascadeEntryPtr->menuPtr->masterMenuPtr;
	    char *helpMenuName = ckalloc(strlen(Tk_PathName(
		    masterMenuPtr->tkwin)) + strlen(".help") + 1);
		&& (cascadeEntryPtr->menuPtr->mainMenuPtr->tkwin != NULL)
		&& (menuPtr->mainMenuPtr->tkwin != NULL)) {
	    TkMenu *mainMenuPtr = cascadeEntryPtr->menuPtr->mainMenuPtr;
	    char *helpMenuName = (char *)ckalloc(strlen(Tk_PathName(
		    mainMenuPtr->tkwin)) + strlen(".help") + 1);

	    strcpy(helpMenuName, Tk_PathName(masterMenuPtr->tkwin));
	    strcpy(helpMenuName, Tk_PathName(mainMenuPtr->tkwin));
	    strcat(helpMenuName, ".help");
	    if (strcmp(helpMenuName,
		    Tk_PathName(menuPtr->masterMenuPtr->tkwin)) == 0) {
		    Tk_PathName(menuPtr->mainMenuPtr->tkwin)) == 0) {
		cascadeEntryPtr->entryFlags |= ENTRY_HELP_MENU;
	    } else {
		cascadeEntryPtr->entryFlags &= ~ENTRY_HELP_MENU;
	    }
	    ckfree(helpMenuName);
	}
    }
1706
1707
1708
1709
1710
1711
1712
1713

1714
1715
1716
1717
1718
1719
1720
1701
1702
1703
1704
1705
1706
1707

1708
1709
1710
1711
1712
1713
1714
1715







-
+







     * and give all of the geometry/drawing the entry's font and metrics.
     */

    menuFont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr);
    Tk_GetFontMetrics(menuFont, &menuMetrics);
    accelSpace = Tk_TextWidth(menuFont, "M", 1);

    for (i = 0; i < menuPtr->numEntries; i++) {
    for (i = 0; i < (int)menuPtr->numEntries; i++) {
	mePtr = menuPtr->entries[i];
	if (mePtr->fontPtr == NULL) {
	    tkfont = menuFont;
	    fmPtr = &menuMetrics;
	} else {
	    tkfont = Tk_GetFontFromObj(menuPtr->tkwin, mePtr->fontPtr);
	    Tk_GetFontMetrics(tkfont, &entryMetrics);
1801
1802
1803
1804
1805
1806
1807
1808

1809
1810
1811
1812
1813
1814
1815
1796
1797
1798
1799
1800
1801
1802

1803
1804
1805
1806
1807
1808
1809
1810







-
+







	    windowHeight = y;
	}
    }

    if (accelWidth != 0) {
	labelWidth += accelSpace;
    }
    for (j = lastColumnBreak; j < menuPtr->numEntries; j++) {
    for (j = lastColumnBreak; j < (int)menuPtr->numEntries; j++) {
	menuPtr->entries[j]->indicatorSpace = indicatorSpace;
	menuPtr->entries[j]->labelWidth = labelWidth;
	menuPtr->entries[j]->width = indicatorSpace + labelWidth
		+ accelWidth + 2 * activeBorderWidth;
	menuPtr->entries[j]->x = x;
	menuPtr->entries[j]->entryFlags |= ENTRY_LAST_COLUMN;
    }
1848
1849
1850
1851
1852
1853
1854
1855
1856


1857
1858
1859
1860
1861
1862
1863
1843
1844
1845
1846
1847
1848
1849


1850
1851
1852
1853
1854
1855
1856
1857
1858







-
-
+
+







 *	An idle handler is set up to do the reconfiguration.
 *
 *----------------------------------------------------------------------
 */

void
TkpMenuNotifyToplevelCreate(
    Tcl_Interp *interp,		/* The interp the menu lives in. */
    const char *menuName)	/* The name of the menu to reconfigure. */
    TCL_UNUSED(Tcl_Interp *),	/* The interp the menu lives in. */
    TCL_UNUSED(const char *))	/* The name of the menu to reconfigure. */
{
    /*
     * Nothing to do.
     */
}

/*
Changes to unix/tkUnixMenubu.c.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

29
30
31
32
33
34
35

36
37

38
39
40
41
42
43
44
1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

28
29
30
31
32
33
34

35
36

37
38
39
40
41
42
43
44






-
+




















-
+






-
+

-
+







/*
 * tkUnixMenubu.c --
 *
 *	This file implements the Unix specific portion of 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.
 */

#include "tkInt.h"
#include "tkMenubutton.h"


/*
 *----------------------------------------------------------------------
 *
 * TkpCreateMenuButton --
 *
 *	Allocate a new TkMenuButton structure.
 *
 * Results:
 *	Returns a newly allocated TkMenuButton structure.
 *
 * Side effects:
 *	Registers an event handler for the widget.
 *	None
 *
 *----------------------------------------------------------------------
 */

TkMenuButton *
TkpCreateMenuButton(
    Tk_Window tkwin)
    TCL_UNUSED(Tk_Window))
{
    return ckalloc(sizeof(TkMenuButton));
    return (TkMenuButton *)ckalloc(sizeof(TkMenuButton));
}

/*
 *----------------------------------------------------------------------
 *
 * TkpDisplayMenuButton --
 *
54
55
56
57
58
59
60
61

62
63
64
65
66
67
68

69
70
71
72
73
74
75
54
55
56
57
58
59
60

61
62
63
64
65
66
67

68
69
70
71
72
73
74
75







-
+






-
+







 *----------------------------------------------------------------------
 */

void
TkpDisplayMenuButton(
    ClientData clientData)	/* Information about widget. */
{
    register TkMenuButton *mbPtr = (TkMenuButton *) clientData;
    TkMenuButton *mbPtr = (TkMenuButton *)clientData;
    GC gc;
    Tk_3DBorder border;
    Pixmap pixmap;
    int x = 0;			/* Initialization needed only to stop compiler
				 * warning. */
    int y = 0;
    register Tk_Window tkwin = mbPtr->tkwin;
    Tk_Window tkwin = mbPtr->tkwin;
    int fullWidth, fullHeight;
    int textXOffset, textYOffset;
    int imageWidth, imageHeight;
    int imageXOffset, imageYOffset;
    int width = 0, height = 0;
				/* Image information that will be used to
				 * restrict disabled pixmap as well */
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
276
277
278
279
280
281
282


283
284
285
286
287
288
289







-
-







	Tk_Draw3DRectangle(tkwin, pixmap, border,
		mbPtr->highlightWidth, mbPtr->highlightWidth,
		Tk_Width(tkwin) - 2*mbPtr->highlightWidth,
		Tk_Height(tkwin) - 2*mbPtr->highlightWidth,
		mbPtr->borderWidth, mbPtr->relief);
    }
    if (mbPtr->highlightWidth != 0) {
	GC gc;

	if (mbPtr->flags & GOT_FOCUS) {
	    gc = Tk_GCForColor(mbPtr->highlightColorPtr, pixmap);
	} else {
	    gc = Tk_GCForColor(mbPtr->highlightBgColorPtr, pixmap);
	}
	Tk_DrawFocusHighlight(tkwin, gc, mbPtr->highlightWidth, pixmap);
    }
317
318
319
320
321
322
323

324
325
326
327
328
329
330
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329







+







 *----------------------------------------------------------------------
 */

void
TkpDestroyMenuButton(
    TkMenuButton *mbPtr)
{
    (void)mbPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * TkpComputeMenuButtonGeometry --
 *
Changes to unix/tkUnixPort.h.
14
15
16
17
18
19
20
21
22
23
24
25





26
27

28
29

30
31
32


33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

48
49

50
51
52
53
54
55
56

57
58


59
60
61
62
63
64
65
14
15
16
17
18
19
20





21
22
23
24
25


26


27



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

44
45

46
47
48
49
50
51


52


53
54
55
56
57
58
59
60
61







-
-
-
-
-
+
+
+
+
+
-
-
+
-
-
+
-
-
-
+
+














-
+

-
+





-
-
+
-
-
+
+








#ifndef _UNIXPORT
#define _UNIXPORT

#define __UNIX__ 1

#include <stdio.h>
#include <ctype.h>
#include <fcntl.h>
#include <limits.h>
#include <math.h>
#include <pwd.h>
#include <pwd.h>
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <ctype.h>
#ifdef NO_STDLIB_H
#   include "../compat/stdlib.h"
#include <math.h>
#else
#   include <stdlib.h>
#include <string.h>
#endif
#include <assert.h>
#include <string.h>
#include <limits.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/file.h>
#ifdef HAVE_SYS_SELECT_H
#   include <sys/select.h>
#endif
#include <sys/stat.h>
#ifndef _TCL
#   include <tcl.h>
#endif
#if TIME_WITH_SYS_TIME
#   include <sys/time.h>
#   include <time.h>
#else
#   if HAVE_SYS_TIME_H
#       include <sys/time.h>
#	include <sys/time.h>
#   else
#       include <time.h>
#	include <time.h>
#   endif
#endif
#if HAVE_INTTYPES_H
#    include <inttypes.h>
#endif
#ifndef NO_UNISTD_H
#   include <unistd.h>
#include <unistd.h>
#else
#   include "../compat/unistd.h"
#if defined(__GNUC__) && !defined(__cplusplus)
#   pragma GCC diagnostic ignored "-Wc++-compat"
#endif
#include <X11/Xlib.h>
#include <X11/cursorfont.h>
#include <X11/keysym.h>
#include <X11/Xatom.h>
#include <X11/Xproto.h>
#include <X11/Xresource.h>
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126













127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
102
103
104
105
106
107
108














109
110
111
112
113
114
115
116
117
118
119
120
121












122
123
124
125
126
127
128







-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-







 * Define "NBBY" (number of bits per byte) if it's not already defined.
 */

#ifndef NBBY
#   define NBBY 8
#endif

#ifdef __CYGWIN__
#   include "tkIntXlibDecls.h"
#   define UINT unsigned int
#   define HWND void *
#   define HDC void *
#   define HINSTANCE void *
#   define COLORREF void *
#   define HMENU void *
#   define TkWinDCState void
#   define HPALETTE void *
#   define WNDPROC void *
#   define WPARAM void *
#   define LPARAM void *
#   define LRESULT void *
#include "tkIntXlibDecls.h"
#define UINT unsigned int
#define HWND void *
#define HDC void *
#define HINSTANCE void *
#define COLORREF void *
#define HMENU void *
#define TkWinDCState void
#define HPALETTE void *
#define WNDPROC void *
#define WPARAM void *
#define LPARAM void *
#define LRESULT void *

#else /* !__CYGWIN__ */
    /*
     * The TkPutImage macro strips off the color table information, which isn't
     * needed for X.
     */

#   define TkPutImage(colors, ncolors, display, pixels, gc, image, srcx, srcy, destx, desty, width, height) \
		XPutImage(display, pixels, gc, image, srcx, srcy, destx, \
		desty, width, height);

#endif /* !__CYGWIN__ */

/*
 * Supply macros for seek offsets, if they're not already provided by
 * an include file.
 */

#ifndef SEEK_SET
186
187
188
189
190
191
192






193
169
170
171
172
173
174
175
176
177
178
179
180
181
182







+
+
+
+
+
+

 */

#ifndef __CYGWIN__
#define TkpPrintWindowId(buf,w) \
	sprintf((buf), "%#08lx", (unsigned long) (w))
#endif

/*
 * Used by tkWindow.c
 */

#define TkpHandleMapOrUnmap(tkwin, event)  Tk_HandleEvent(event)

#endif /* _UNIXPORT */
Changes to unix/tkUnixRFont.c.
1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
1
2
3
4
5

6
7
8
9
10
11
12
13
14

15
16
17
18
19
20
21





-
+








-







/*
 * tkUnixRFont.c --
 *
 *	Alternate implementation of tkUnixFont.c using Xft.
 *
 * Copyright (c) 2002-2003 Keith Packard
 * Copyright © 2002-2003 Keith Packard
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tkUnixInt.h"
#include "tkFont.h"
#include <X11/Xft/Xft.h>
#include <ctype.h>

#define MAX_CACHED_COLORS 16

typedef struct {
    XftFont *ftFont;
    XftFont *ft0Font;
    FcPattern *source;
52
53
54
55
56
57
58





59
60



61








62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84

85
86
87
88
89
90
91
92
51
52
53
54
55
56
57
58
59
60
61
62


63
64
65

66
67
68
69
70
71
72
73
74
75



76
77
78
79
80
81
82
83
84
85
86
87
88





89

90
91
92
93
94
95
96







+
+
+
+
+
-
-
+
+
+
-
+
+
+
+
+
+
+
+


-
-
-













-
-
-
-
-
+
-








typedef struct {
    Region clipRegion;		/* The clipping region, or None. */
} ThreadSpecificData;
static Tcl_ThreadDataKey dataKey;

/*
 *-------------------------------------------------------------------------
 *
 * TkpFontPkgInit --
 *
 *	This procedure is called when an application is created. It
 * Package initialization:
 * 	Nothing to do here except register the fact that we're using Xft in
 *	initializes all the structures that are used by the
 *	platform-dependant code on a per application basis.
 *	Note that this is called before TkpInit() !
 * 	the TIP 59 configuration database.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *-------------------------------------------------------------------------
 */

#ifndef TCL_CFGVAL_ENCODING
#define TCL_CFGVAL_ENCODING "ascii"
#endif

static int utf8ToUcs4(const char *source, FcChar32 *c, int numBytes)
{
    if (numBytes >= 6) {
    	return TkUtfToUniChar(source, (int *)c);
    }
    return FcUtf8ToUcs4((const FcChar8 *)source, c, numBytes);
}

void
TkpFontPkgInit(
    TkMainInfo *mainPtr)	/* The application being created. */
{
    static const Tcl_Config cfg[] = {
	{ "fontsystem", "xft" },
	{ 0,0 }
    };

    (void)mainPtr;
    Tcl_RegisterConfig(mainPtr->interp, "tk", cfg, TCL_CFGVAL_ENCODING);
}

static XftFont *
GetFont(
    UnixFtFont *fontPtr,
    FcChar32 ucs4,
    double angle)
199
200
201
202
203
204
205
206

207
208
209
210
211
212
213
203
204
205
206
207
208
209

210
211
212
213
214
215
216
217







-
+







	weight = XFT_WEIGHT_MEDIUM;
    }
    if (XftPatternGetInteger(ftFont->pattern, XFT_SLANT, 0,
	    &slant) != XftResultMatch) {
	slant = XFT_SLANT_ROMAN;
    }

#if DEBUG_FONTSEL
#ifdef DEBUG_FONTSEL
    printf("family %s size %d weight %d slant %d\n",
	    family, (int)size, weight, slant);
#endif /* DEBUG_FONTSEL */

    faPtr->family = Tk_GetUid(family);
    faPtr->size = size;
    faPtr->weight = (weight > XFT_WEIGHT_MEDIUM) ? TK_FW_BOLD : TK_FW_NORMAL;
250
251
252
253
254
255
256

















257
258
259
260
261
262
263
264
265
266
267
268


269
270
271

272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289

290
291
292
293
294
295
296
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288

289
290
291
292

293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310

311
312
313
314
315
316
317
318







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+











-
+
+


-
+

















-
+







 *	also allocates a new UnixFtFont.
 *
 * Results:
 * 	On error, frees fontPtr and returns NULL, otherwise returns fontPtr.
 *
 *---------------------------------------------------------------------------
 */

static void
FinishedWithFont(
    UnixFtFont *fontPtr);

static int
InitFontErrorProc(
    ClientData clientData,
    TCL_UNUSED(XErrorEvent *))
{
    int *errorFlagPtr = (int *)clientData;

    if (errorFlagPtr != NULL) {
	*errorFlagPtr = 1;
    }
    return 0;
}

static UnixFtFont *
InitFont(
    Tk_Window tkwin,
    FcPattern *pattern,
    UnixFtFont *fontPtr)
{
    FcFontSet *set;
    FcCharSet *charset;
    FcResult result;
    XftFont *ftFont;
    int i, iWidth;
    int i, iWidth, errorFlag;
    Tk_ErrorHandler handler;

    if (!fontPtr) {
	fontPtr = ckalloc(sizeof(UnixFtFont));
	fontPtr = (UnixFtFont *)ckalloc(sizeof(UnixFtFont));
    }

    FcConfigSubstitute(0, pattern, FcMatchPattern);
    XftDefaultSubstitute(Tk_Display(tkwin), Tk_ScreenNumber(tkwin), pattern);

    /*
     * Generate the list of fonts
     */

    set = FcFontSort(0, pattern, FcTrue, NULL, &result);
    if (!set || set->nfont == 0) {
	ckfree(fontPtr);
	return NULL;
    }

    fontPtr->fontset = set;
    fontPtr->pattern = pattern;
    fontPtr->faces = ckalloc(set->nfont * sizeof(UnixFtFace));
    fontPtr->faces = (UnixFtFace *)ckalloc(set->nfont * sizeof(UnixFtFace));
    fontPtr->nfaces = set->nfont;

    /*
     * Fill in information about each returned font
     */

    for (i = 0; i < set->nfont; i++) {
312
313
314
315
316
317
318



319






320
321
322






323
324
325
326
327
328
329
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366







+
+
+

+
+
+
+
+
+



+
+
+
+
+
+







    fontPtr->ncolors = 0;
    fontPtr->firstColor = -1;

    /*
     * Fill in platform-specific fields of TkFont.
     */

    errorFlag = 0;
    handler = Tk_CreateErrorHandler(Tk_Display(tkwin),
		    -1, -1, -1, InitFontErrorProc, (ClientData) &errorFlag);
    ftFont = GetFont(fontPtr, 0, 0.0);
    if ((ftFont == NULL) || errorFlag) {
	Tk_DeleteErrorHandler(handler);
	FinishedWithFont(fontPtr);
	ckfree(fontPtr);
	return NULL;
    }
    fontPtr->font.fid = XLoadFont(Tk_Display(tkwin), "fixed");
    GetTkFontAttributes(ftFont, &fontPtr->font.fa);
    GetTkFontMetrics(ftFont, &fontPtr->font.fm);
    Tk_DeleteErrorHandler(handler);
    if (errorFlag) {
	FinishedWithFont(fontPtr);
	ckfree(fontPtr);
	return NULL;
    }

    /*
     * Fontconfig can't report any information about the position or thickness
     * of underlines or overstrikes. Thus, we use some defaults that are
     * hacked around from backup defaults in tkUnixFont.c, which are in turn
     * based on recommendations in the X manual. The comments from that file
     * leading to these computations were:
340
341
342
343
344
345
346



347






348
349
350
351
352
353
354
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400







+
+
+

+
+
+
+
+
+







     * Fontconfig at all. [Bug 1961455]
     */

    {
	TkFont *fPtr = &fontPtr->font;

	fPtr->underlinePos = fPtr->fm.descent / 2;
	handler = Tk_CreateErrorHandler(Tk_Display(tkwin),
			-1, -1, -1, InitFontErrorProc, (ClientData) &errorFlag);
	errorFlag = 0;
	Tk_MeasureChars((Tk_Font) fPtr, "I", 1, -1, 0, &iWidth);
	Tk_DeleteErrorHandler(handler);
	if (errorFlag) {
	    FinishedWithFont(fontPtr);
	    ckfree(fontPtr);
	    return NULL;
	}
	fPtr->underlineHeight = iWidth / 3;
	if (fPtr->underlineHeight == 0) {
	    fPtr->underlineHeight = 1;
	}
	if (fPtr->underlineHeight + fPtr->underlinePos > fPtr->fm.descent) {
	    fPtr->underlineHeight = fPtr->fm.descent - fPtr->underlinePos;
	    if (fPtr->underlineHeight == 0) {
402
403
404
405
406
407
408
409

410
411
412
413
414
415
416
448
449
450
451
452
453
454

455
456
457
458
459
460
461
462







-
+







TkFont *
TkpGetNativeFont(
    Tk_Window tkwin,		/* For display where font will be used. */
    const char *name)		/* Platform-specific font name. */
{
    UnixFtFont *fontPtr;
    FcPattern *pattern;
#if DEBUG_FONTSEL
#ifdef DEBUG_FONTSEL
    printf("TkpGetNativeFont %s\n", name);
#endif /* DEBUG_FONTSEL */

    pattern = XftXlfdParse(name, FcFalse, FcFalse);
    if (!pattern) {
	return NULL;
    }
440
441
442
443
444
445
446
447

448
449
450
451
452
453
454
486
487
488
489
490
491
492

493
494
495
496
497
498
499
500







-
+







    const TkFontAttributes *faPtr)
				/* Set of attributes to match. */
{
    XftPattern *pattern;
    int weight, slant;
    UnixFtFont *fontPtr;

#if DEBUG_FONTSEL
#ifdef DEBUG_FONTSEL
    printf("TkpGetFontFromAttributes %s-%d %d %d\n", faPtr->family,
	    faPtr->size, faPtr->weight, faPtr->slant);
#endif /* DEBUG_FONTSEL */
    pattern = XftPatternCreate();
    if (faPtr->family) {
	XftPatternAddString(pattern, XFT_FAMILY, faPtr->family);
    }
620
621
622
623
624
625
626
627

628
629

630
631
632
633
634
635
636
666
667
668
669
670
671
672

673
674

675
676
677
678
679
680
681
682







-
+

-
+







 *	character.
 *
 *----------------------------------------------------------------------
 */

void
TkpGetFontAttrsForChar(
    Tk_Window tkwin,		/* Window on the font's display */
    TCL_UNUSED(Tk_Window),	/* Window on the font's display */
    Tk_Font tkfont,		/* Font to query */
    int c,			/* Character of interest */
    int c,         		/* Character of interest */
    TkFontAttributes *faPtr)	/* Output: Font attributes */
{
    UnixFtFont *fontPtr = (UnixFtFont *) tkfont;
				/* Structure describing the logical font */
    FcChar32 ucs4 = (FcChar32) c;
				/* UCS-4 character to map */
    XftFont *ftFont = GetFont(fontPtr, ucs4, 0.0);
665
666
667
668
669
670
671
672
673



674
675
676
677


678
679
680
681
682
683
684
711
712
713
714
715
716
717


718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733







-
-
+
+
+




+
+







				 * terminating character. */
{
    UnixFtFont *fontPtr = (UnixFtFont *) tkfont;
    XftFont *ftFont;
    FcChar32 c;
    XGlyphInfo extents;
    int clen, curX, newX, curByte, newByte, sawNonSpace;
    int termByte = 0, termX = 0;
#if DEBUG_FONTSEL
    int termByte = 0, termX = 0, errorFlag = 0;
    Tk_ErrorHandler handler;
#ifdef DEBUG_FONTSEL
    char string[256];
    int len = 0;
#endif /* DEBUG_FONTSEL */

    handler = Tk_CreateErrorHandler(fontPtr->display,
	    -1, -1, -1, InitFontErrorProc, &errorFlag);
    curX = 0;
    curByte = 0;
    sawNonSpace = 0;
    while (numBytes > 0) {
	int unichar;

	clen = TkUtfToUniChar(source, &unichar);
701
702
703
704
705
706
707
708

709
710
711
712

713





714
715
716
717
718
719
720
750
751
752
753
754
755
756

757
758
759
760
761
762

763
764
765
766
767
768
769
770
771
772
773
774







-
+




+
-
+
+
+
+
+







		termX = curX;
		sawNonSpace = 0;
	    }
	} else {
	    sawNonSpace = 1;
	}

#if DEBUG_FONTSEL
#ifdef DEBUG_FONTSEL
	string[len++] = (char) c;
#endif /* DEBUG_FONTSEL */
	ftFont = GetFont(fontPtr, c, 0.0);

	if (!errorFlag) {
	XftTextExtents32(fontPtr->display, ftFont, &c, 1, &extents);
	    XftTextExtents32(fontPtr->display, ftFont, &c, 1, &extents);
	} else {
	    extents.xOff = 0;
	    errorFlag = 0;
	}

	newX = curX + extents.xOff;
	newByte = curByte + clen;
	if (maxLength >= 0 && newX > maxLength) {
	    if (flags & TK_PARTIAL_OK ||
		    (flags & TK_AT_LEAST_ONE && curByte == 0)) {
		curX = newX;
735
736
737
738
739
740
741

742

743
744
745
746
747
748
749
789
790
791
792
793
794
795
796

797
798
799
800
801
802
803
804







+
-
+







	    }
	    break;
	}

	curX = newX;
	curByte = newByte;
    }
    Tk_DeleteErrorHandler(handler);
#if DEBUG_FONTSEL
#ifdef DEBUG_FONTSEL
    string[len] = '\0';
    printf("MeasureChars %s length %d bytes %d\n", string, curX, curByte);
#endif /* DEBUG_FONTSEL */
    *lengthPtr = curX;
    return curByte;
}

875
876
877
878
879
880
881
882

883
884
885
886
887
888
889
890
891
892
893
894
895
896
897

898
899
900
901
902
903
904
930
931
932
933
934
935
936

937
938
939
940
941
942
943
944
945
946
947
948
949
950
951

952
953
954
955
956
957
958
959







-
+














-
+







    int clen, nspec, xStart = x;
    XftGlyphFontSpec specs[NUM_SPEC];
    XGlyphInfo metrics;
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (fontPtr->ftDraw == 0) {
#if DEBUG_FONTSEL
#ifdef DEBUG_FONTSEL
	printf("Switch to drawable 0x%x\n", drawable);
#endif /* DEBUG_FONTSEL */
	fontPtr->ftDraw = XftDrawCreate(display, drawable,
		DefaultVisual(display, fontPtr->screen),
		DefaultColormap(display, fontPtr->screen));
    } else {
	Tk_ErrorHandler handler =
		Tk_CreateErrorHandler(display, -1, -1, -1, NULL, NULL);

	XftDrawChange(fontPtr->ftDraw, drawable);
	Tk_DeleteErrorHandler(handler);
    }
    XGetGCValues(display, gc, GCForeground, &values);
    xftcolor = LookUpColor(display, fontPtr, values.foreground);
    if (tsdPtr->clipRegion != None) {
    if (tsdPtr->clipRegion != NULL) {
	XftDrawSetClip(fontPtr->ftDraw, tsdPtr->clipRegion);
    }
    nspec = 0;
    while (numBytes > 0) {
	XftFont *ftFont;
	FcChar32 c;

940
941
942
943
944
945
946
947

948
949
950
951
952
953
954
995
996
997
998
999
1000
1001

1002
1003
1004
1005
1006
1007
1008
1009







-
+







	}
    }
    if (nspec) {
	XftDrawGlyphFontSpec(fontPtr->ftDraw, xftcolor, specs, nspec);
    }

  doUnderlineStrikeout:
    if (tsdPtr->clipRegion != None) {
    if (tsdPtr->clipRegion != NULL) {
	XftDrawSetClip(fontPtr->ftDraw, NULL);
    }
    if (fontPtr->font.fa.underline != 0) {
	XFillRectangle(display, drawable, gc, xStart,
		y + fontPtr->font.underlinePos, (unsigned) (x - xStart),
		(unsigned) fontPtr->font.underlineHeight);
    }
1010
1011
1012
1013
1014
1015
1016
1017

1018
1019
1020
1021
1022
1023
1024
1065
1066
1067
1068
1069
1070
1071

1072
1073
1074
1075
1076
1077
1078
1079







-
+







    int clen, nglyph;
    FT_UInt glyphs[NUM_SPEC];
    XGlyphInfo metrics;
    XftFont *currentFtFont;
    int originX, originY;

    if (fontPtr->ftDraw == 0) {
#if DEBUG_FONTSEL
#ifdef DEBUG_FONTSEL
	printf("Switch to drawable 0x%x\n", drawable);
#endif /* DEBUG_FONTSEL */
	fontPtr->ftDraw = XftDrawCreate(display, drawable,
		DefaultVisual(display, fontPtr->screen),
		DefaultColormap(display, fontPtr->screen));
    } else {
	Tk_ErrorHandler handler =
1032
1033
1034
1035
1036
1037
1038
1039

1040
1041
1042
1043
1044
1045
1046
1087
1088
1089
1090
1091
1092
1093

1094
1095
1096
1097
1098
1099
1100
1101







-
+







    xftcolor = LookUpColor(display, fontPtr, values.foreground);
    if (tsdPtr->clipRegion != None) {
	XftDrawSetClip(fontPtr->ftDraw, tsdPtr->clipRegion);
    }

    nglyph = 0;
    currentFtFont = NULL;
    originX = originY = 0;		/* lint */
    originX = originY = 0;

    while (numBytes > 0) {
	XftFont *ftFont;
	FcChar32 c;

	clen = utf8ToUcs4(source, &c, numBytes);
	if (clen <= 0) {
1119
1120
1121
1122
1123
1124
1125
1126

1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141

1142
1143
1144
1145
1146
1147
1148
1174
1175
1176
1177
1178
1179
1180

1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195

1196
1197
1198
1199
1200
1201
1202
1203







-
+














-
+







#else /* !XFT_HAS_FIXED_ROTATED_PLACEMENT */
    int clen, nspec;
    XftGlyphFontSpec specs[NUM_SPEC];
    XGlyphInfo metrics;
    double sinA = sin(angle * PI/180.0), cosA = cos(angle * PI/180.0);

    if (fontPtr->ftDraw == 0) {
#if DEBUG_FONTSEL
#ifdef DEBUG_FONTSEL
	printf("Switch to drawable 0x%x\n", drawable);
#endif /* DEBUG_FONTSEL */
	fontPtr->ftDraw = XftDrawCreate(display, drawable,
		DefaultVisual(display, fontPtr->screen),
		DefaultColormap(display, fontPtr->screen));
    } else {
	Tk_ErrorHandler handler =
		Tk_CreateErrorHandler(display, -1, -1, -1, NULL, NULL);

	XftDrawChange(fontPtr->ftDraw, drawable);
	Tk_DeleteErrorHandler(handler);
    }
    XGetGCValues(display, gc, GCForeground, &values);
    xftcolor = LookUpColor(display, fontPtr, values.foreground);
    if (tsdPtr->clipRegion != None) {
    if (tsdPtr->clipRegion != NULL) {
	XftDrawSetClip(fontPtr->ftDraw, tsdPtr->clipRegion);
    }
    nspec = 0;
    while (numBytes > 0) {
	XftFont *ftFont, *ft0Font;
	FcChar32 c;

1186
1187
1188
1189
1190
1191
1192
1193

1194
1195
1196
1197
1198
1199
1200
1241
1242
1243
1244
1245
1246
1247

1248
1249
1250
1251
1252
1253
1254
1255







-
+







    }
    if (nspec) {
	XftDrawGlyphFontSpec(fontPtr->ftDraw, xftcolor, specs, nspec);
    }
#endif /* XFT_HAS_FIXED_ROTATED_PLACEMENT */

  doUnderlineStrikeout:
    if (tsdPtr->clipRegion != None) {
    if (tsdPtr->clipRegion != NULL) {
	XftDrawSetClip(fontPtr->ftDraw, NULL);
    }
    if (fontPtr->font.fa.underline || fontPtr->font.fa.overstrike) {
	XPoint points[5];
	double width = (x - xStart) * cosA + (yStart - y) * sinA;
	double barHeight = fontPtr->font.underlineHeight;
	double dy = fontPtr->font.underlinePos;
1244
1245
1246
1247
1248
1249
1250
1251





















1252






























































1253
1254

1255
1256
1257
1258
1259

1260
1261
1262
1263
1264
1265
1266
1267
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391

1392
1393
1394
1395
1396

1397
1398
1399
1400
1401
1402
1403
1404
1405








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+




-
+








		XFillPolygon(display, drawable, gc, points, 5, Complex,
			CoordModeOrigin);
		XDrawLines(display, drawable, gc, points, 5, CoordModeOrigin);
	    }
	}
    }
}

/*
 *---------------------------------------------------------------------------
 *
 * TkpDrawCharsInContext --
 *
 *	Draw a string of characters on the screen like Tk_DrawChars(), but
 *	with access to all the characters on the line for context. On X11 this
 *	context isn't consulted, so we just call Tk_DrawChars().
 *
 *      Note: TK_DRAW_IN_CONTEXT being currently defined only on macOS, this
 *            function is unused (and possibly unfinished). See [7655f65ae7].
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Information gets drawn on the screen.
 *
 *---------------------------------------------------------------------------
 */

void
TkpDrawCharsInContext(
    Display *display,		/* Display on which to draw. */
    Drawable drawable,		/* Window or pixmap in which to draw. */
    GC gc,			/* Graphics context for drawing characters. */
    Tk_Font tkfont,		/* Font in which characters will be drawn;
				 * must be the same as font used in GC. */
    const char *source,		/* UTF-8 string to be displayed. Need not be
				 * '\0' terminated. All Tk meta-characters
				 * (tabs, control characters, and newlines)
				 * should be stripped out of the string that
				 * is passed to this function. If they are not
				 * stripped out, they will be displayed as
				 * regular printing characters. */
    int numBytes,		/* Number of bytes in string. */
    int rangeStart,		/* Index of first byte to draw. */
    int rangeLength,		/* Length of range to draw in bytes. */
    int x, int y)		/* Coordinates at which to place origin of the
				 * whole (not just the range) string when
				 * drawing. */
{
    int widthUntilStart;

    (void) numBytes; /*unused*/

    Tk_MeasureChars(tkfont, source, rangeStart, -1, 0, &widthUntilStart);
    Tk_DrawChars(display, drawable, gc, tkfont, source + rangeStart,
	    rangeLength, x+widthUntilStart, y);
}

void
TkpDrawAngledCharsInContext(
    Display *display,		/* Display on which to draw. */
    Drawable drawable,		/* Window or pixmap in which to draw. */
    GC gc,			/* Graphics context for drawing characters. */
    Tk_Font tkfont,		/* Font in which characters will be drawn; must
				 * be the same as font used in GC. */
    const char * source,	/* UTF-8 string to be displayed. Need not be
				 * '\0' terminated. All Tk meta-characters
				 * (tabs, control characters, and newlines)
				 * should be stripped out of the string that is
				 * passed to this function. If they are not
				 * stripped out, they will be displayed as
				 * regular printing characters. */
    int numBytes,		/* Number of bytes in string. */
    int rangeStart,		/* Index of first byte to draw. */
    int rangeLength,		/* Length of range to draw in bytes. */
    double x, double y,		/* Coordinates at which to place origin of the
				 * whole (not just the range) string when
				 * drawing. */
    double angle)		/* What angle to put text at, in degrees. */
{
    int widthUntilStart;
    double sinA = sin(angle * PI/180.0), cosA = cos(angle * PI/180.0);

    (void) numBytes; /*unused*/

    Tk_MeasureChars(tkfont, source, rangeStart, -1, 0, &widthUntilStart);
    TkDrawAngledChars(display, drawable, gc, tkfont, source + rangeStart,
	    rangeLength, x+cosA*widthUntilStart, y-sinA*widthUntilStart, angle);
}

void
TkUnixSetXftClipRegion(
    TkRegion clipRegion)	/* The clipping region to install. */
    Region clipRegion)	/* The clipping region to install. */
{
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    tsdPtr->clipRegion = (Region) clipRegion;
    tsdPtr->clipRegion = clipRegion;
}

/*
 * Local Variables:
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Changes to unix/tkUnixScale.c.
1
2
3
4
5
6
7


8
9
10
11
12
13
14
1
2
3
4
5


6
7
8
9
10
11
12
13
14





-
-
+
+







/*
 * tkUnixScale.c --
 *
 *	This file implements the X specific portion of the scrollbar widget.
 *
 * Copyright (c) 1996 by Sun Microsystems, Inc.
 * Copyright (c) 1998-2000 by Scriptics Corporation.
 * Copyright © 1996 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.
 */

#include "tkInt.h"
#include "tkScale.h"
46
47
48
49
50
51
52
53

54
55

56
57
58
59
60
61
62
46
47
48
49
50
51
52

53
54

55
56
57
58
59
60
61
62







-
+

-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

TkScale *
TkpCreateScale(
    Tk_Window tkwin)
    TCL_UNUSED(Tk_Window))
{
    return ckalloc(sizeof(TkScale));
    return (TkScale *)ckalloc(sizeof(TkScale));
}

/*
 *----------------------------------------------------------------------
 *
 * TkpDestroyScale --
 *
252
253
254
255
256
257
258
259

260
261
262
263
264
265
266
267
268
269
270

271
272
273
274
275
276
277
252
253
254
255
256
257
258

259
260
261
262
263
264
265
266
267
268
269

270
271
272
273
274
275
276
277







-
+










-
+







 *	corresponds to "value".
 *
 *----------------------------------------------------------------------
 */

static void
DisplayVerticalValue(
    register TkScale *scalePtr,	/* Information about widget in which to
    TkScale *scalePtr,	/* Information about widget in which to
				 * display value. */
    Drawable drawable,		/* Pixmap or window in which to draw the
				 * value. */
    double value,		/* Y-coordinate of number to display,
				 * specified in application coords, not in
				 * pixels (we'll compute pixels). */
    int rightEdge,		/* X-coordinate of right edge of text,
				 * specified in pixels. */
    const char *format)		/* Format string to use for the value */
{
    register Tk_Window tkwin = scalePtr->tkwin;
    Tk_Window tkwin = scalePtr->tkwin;
    int y, width, length;
    char valueString[TCL_DOUBLE_SPACE];
    Tk_FontMetrics fm;

    Tk_GetFontMetrics(scalePtr->tkfont, &fm);
    y = TkScaleValueToPixel(scalePtr, value) + fm.ascent/2;
    if (snprintf(valueString, TCL_DOUBLE_SPACE, format, value) < 0) {
321
322
323
324
325
326
327
328

329
330
331
332
333
334
335
321
322
323
324
325
326
327

328
329
330
331
332
333
334
335







-
+







    Drawable drawable,		/* Where to display scale (window or
				 * pixmap). */
    XRectangle *drawnAreaPtr)	/* Initally contains area of window; if only a
				 * part of the scale is redrawn, gets modified
				 * to reflect the part of the window that was
				 * redrawn. */
{
    register Tk_Window tkwin = scalePtr->tkwin;
    Tk_Window tkwin = scalePtr->tkwin;
    int x, y, width, height, shadowWidth;
    double tickInterval = scalePtr->tickInterval;
    Tk_3DBorder sliderBorder;

    /*
     * Display the information from bottom to top across the window.
     */
475
476
477
478
479
480
481
482

483
484
485
486
487
488
489
490
491
492
493

494
495
496
497
498
499
500
475
476
477
478
479
480
481

482
483
484
485
486
487
488
489
490
491
492

493
494
495
496
497
498
499
500







-
+










-
+







 *	that corresponds to "value".
 *
 *----------------------------------------------------------------------
 */

static void
DisplayHorizontalValue(
    register TkScale *scalePtr,	/* Information about widget in which to
    TkScale *scalePtr,	/* Information about widget in which to
				 * display value. */
    Drawable drawable,		/* Pixmap or window in which to draw the
				 * value. */
    double value,		/* X-coordinate of number to display,
				 * specified in application coords, not in
				 * pixels (we'll compute pixels). */
    int top,			/* Y-coordinate of top edge of text, specified
				 * in pixels. */
    const char *format)		/* Format string to use for the value */
{
    register Tk_Window tkwin = scalePtr->tkwin;
    Tk_Window tkwin = scalePtr->tkwin;
    int x, y, length, width;
    char valueString[TCL_DOUBLE_SPACE];
    Tk_FontMetrics fm;

    x = TkScaleValueToPixel(scalePtr, value);
    Tk_GetFontMetrics(scalePtr->tkfont, &fm);
    y = top + fm.ascent;
542
543
544
545
546
547
548
549

550
551
552
553
554
555
556
542
543
544
545
546
547
548

549
550
551
552
553
554
555
556







-
+







 *----------------------------------------------------------------------
 */

void
TkpDisplayScale(
    ClientData clientData)	/* Widget record for scale. */
{
    TkScale *scalePtr = (TkScale *) clientData;
    TkScale *scalePtr = (TkScale *)clientData;
    Tk_Window tkwin = scalePtr->tkwin;
    Tcl_Interp *interp = scalePtr->interp;
    Pixmap pixmap;
    int result;
    char string[TCL_DOUBLE_SPACE];
    XRectangle drawnArea;
    Tcl_DString buf;
571
572
573
574
575
576
577
578

579
580
581
582
583
584
585
571
572
573
574
575
576
577

578
579
580
581
582
583
584
585







-
+







		scalePtr->value) < 0) {
	    string[TCL_DOUBLE_SPACE - 1] = '\0';
	}
	Tcl_DStringInit(&buf);
	Tcl_DStringAppend(&buf, scalePtr->command, -1);
	Tcl_DStringAppend(&buf, " ", -1);
	Tcl_DStringAppend(&buf, string, -1);
	result = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, 0);
	result = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, TCL_EVAL_GLOBAL);
	Tcl_DStringFree(&buf);
	if (result != TCL_OK) {
	    Tcl_AddErrorInfo(interp, "\n    (command executed by scale)");
	    Tcl_BackgroundException(interp, result);
	}
	Tcl_Release(interp);
    }
Changes to unix/tkUnixScrlbr.c.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







/*
 * tkUnixScrollbar.c --
 *
 *	This file implements the Unix specific portion of 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.
 */

#include "tkInt.h"
#include "tkScrollbar.h"
59
60
61
62
63
64
65
66

67
68
69
70
71
72
73
59
60
61
62
63
64
65

66
67
68
69
70
71
72
73







-
+







 *----------------------------------------------------------------------
 */

TkScrollbar *
TkpCreateScrollbar(
    Tk_Window tkwin)
{
    UnixScrollbar *scrollPtr = ckalloc(sizeof(UnixScrollbar));
    UnixScrollbar *scrollPtr = (UnixScrollbar *)ckalloc(sizeof(UnixScrollbar));

    scrollPtr->troughGC = NULL;
    scrollPtr->copyGC = NULL;

    Tk_CreateEventHandler(tkwin,
	    ExposureMask|StructureNotifyMask|FocusChangeMask,
	    TkScrollbarEventProc, scrollPtr);
93
94
95
96
97
98
99
100
101


102
103
104
105
106
107
108
93
94
95
96
97
98
99


100
101
102
103
104
105
106
107
108







-
-
+
+







 *--------------------------------------------------------------
 */

void
TkpDisplayScrollbar(
    ClientData clientData)	/* Information about window. */
{
    register TkScrollbar *scrollPtr = (TkScrollbar *) clientData;
    register Tk_Window tkwin = scrollPtr->tkwin;
    TkScrollbar *scrollPtr = (TkScrollbar *)clientData;
    Tk_Window tkwin = scrollPtr->tkwin;
    XPoint points[7];
    Tk_3DBorder border;
    int relief, width, elementBorderWidth;
    Pixmap pixmap;

    if ((scrollPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {
	goto done;
273
274
275
276
277
278
279
280

281
282
283
284
285
286
287
273
274
275
276
277
278
279

280
281
282
283
284
285
286
287







-
+







 *	The scrollbar will be displayed differently.
 *
 *----------------------------------------------------------------------
 */

extern void
TkpComputeScrollbarGeometry(
    register TkScrollbar *scrollPtr)
    TkScrollbar *scrollPtr)
				/* Scrollbar whose geometry may have
				 * changed. */
{
    int width, fieldLength;

    if (scrollPtr->highlightWidth < 0) {
	scrollPtr->highlightWidth = 0;
390
391
392
393
394
395
396
397

398
399
400
401
402

403
404
405
406
407
408

409
410
411
412

413
414
415
416
417
418
419
390
391
392
393
394
395
396

397
398
399
400
401

402
403
404
405
406
407

408
409
410
411

412
413
414
415
416
417
418
419







-
+




-
+





-
+



-
+







 *	Configuration info may get changed.
 *
 *----------------------------------------------------------------------
 */

void
TkpConfigureScrollbar(
    register TkScrollbar *scrollPtr)
    TkScrollbar *scrollPtr)
				/* Information about widget; may or may not
				 * already have values for some fields. */
{
    XGCValues gcValues;
    GC new;
    GC newGC;
    UnixScrollbar *unixScrollPtr = (UnixScrollbar *) scrollPtr;

    Tk_SetBackgroundFromBorder(scrollPtr->tkwin, scrollPtr->bgBorder);

    gcValues.foreground = scrollPtr->troughColorPtr->pixel;
    new = Tk_GetGC(scrollPtr->tkwin, GCForeground, &gcValues);
    newGC = Tk_GetGC(scrollPtr->tkwin, GCForeground, &gcValues);
    if (unixScrollPtr->troughGC != NULL) {
	Tk_FreeGC(scrollPtr->display, unixScrollPtr->troughGC);
    }
    unixScrollPtr->troughGC = new;
    unixScrollPtr->troughGC = newGC;
    if (unixScrollPtr->copyGC == NULL) {
	gcValues.graphics_exposures = False;
	unixScrollPtr->copyGC = Tk_GetGC(scrollPtr->tkwin,
		GCGraphicsExposures, &gcValues);
    }
}

433
434
435
436
437
438
439
440

441
442
443
444
445

446
447
448
449
450
451
452
433
434
435
436
437
438
439

440
441
442
443
444

445
446
447
448
449
450
451
452







-
+




-
+







 *	None.
 *
 *--------------------------------------------------------------
 */

int
TkpScrollbarPosition(
    register TkScrollbar *scrollPtr,
    TkScrollbar *scrollPtr,
				/* Scrollbar widget record. */
    int x, int y)		/* Coordinates within scrollPtr's window. */
{
    int length, width, tmp;
    register const int inset = scrollPtr->inset;
    const int inset = scrollPtr->inset;

    if (scrollPtr->vertical) {
	length = Tk_Height(scrollPtr->tkwin);
	width = Tk_Width(scrollPtr->tkwin);
    } else {
	tmp = x;
	x = y;
Changes to unix/tkUnixSelect.c.
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







/*
 * tkUnixSelect.c --
 *
 *	This file contains X specific routines for manipulating selections.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright © 1995-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.
 */

#include "tkInt.h"
#include "tkSelect.h"
236
237
238
239
240
241
242
243

244
245
246


247
248
249
250
251
252
253

254
255
256
257
258
259
260
236
237
238
239
240
241
242

243
244


245
246
247
248
249
250
251
252

253
254
255
256
257
258
259
260







-
+

-
-
+
+






-
+







 *	until eventually there's no more selection to fetch.
 *
 *----------------------------------------------------------------------
 */

void
TkSelPropProc(
    register XEvent *eventPtr)	/* X PropertyChange event. */
    XEvent *eventPtr)	/* X PropertyChange event. */
{
    register IncrInfo *incrPtr;
    register TkSelHandler *selPtr;
    IncrInfo *incrPtr;
    TkSelHandler *selPtr;
    int length, numItems;
    unsigned long i;
    Atom target, formatType;
    long buffer[TK_SEL_WORDS_AT_ONCE];
    TkDisplay *dispPtr = TkGetDisplay(eventPtr->xany.display);
    Tk_ErrorHandler errorHandler;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    /*
     * See if this event announces the deletion of a property being used for
     * an INCR transfer. If so, then add the next chunk of data to the
     * property.
     */
352
353
354
355
356
357
358
359

360
361
362
363
364
365
366
352
353
354
355
356
357
358

359
360
361
362
363
364
365
366







-
+







		if (numItems > TK_SEL_BYTES_AT_ONCE) {
		    Tcl_Panic("selection handler returned too many bytes");
		}
	    }
	    ((char *) buffer)[numItems] = 0;

	    errorHandler = Tk_CreateErrorHandler(eventPtr->xproperty.display,
		    -1, -1, -1, (int (*)()) NULL, NULL);
		    -1, -1, -1, NULL, NULL);

	    /*
	     * Encode the data using the proper format for each type.
	     */

	    if ((formatType == XA_STRING)
		    || (dispPtr && formatType==dispPtr->utf8Atom)
445
446
447
448
449
450
451
452

453
454
455
456
457
458
459
445
446
447
448
449
450
451

452
453
454
455
456
457
458
459







-
+







		/*
		 * Preserve any left-over bytes.
		 */

		if (srcLen > 3) {
		    Tcl_Panic("selection conversion left too many bytes unconverted");
		}
		memcpy(incrPtr->converts[i].buffer, src, (size_t) srcLen+1);
		memcpy(incrPtr->converts[i].buffer, src, srcLen + 1);
		Tcl_DStringFree(&ds);
	    } else {
		/*
		 * Set the property to the encoded string value.
		 */

		char *propPtr = (char *) SelCvtToX((char *) buffer,
515
516
517
518
519
520
521
522

523
524
525

526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543

544
545
546
547
548
549
550
551
552
553
554
555
515
516
517
518
519
520
521

522
523
524

525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542

543
544
545
546
547

548
549
550
551
552
553
554







-
+


-
+

















-
+




-







 *
 *--------------------------------------------------------------
 */

void
TkSelEventProc(
    Tk_Window tkwin,		/* Window for which event was targeted. */
    register XEvent *eventPtr)	/* X event: either SelectionClear,
    XEvent *eventPtr)	/* X event: either SelectionClear,
				 * SelectionRequest, or SelectionNotify. */
{
    register TkWindow *winPtr = (TkWindow *) tkwin;
    TkWindow *winPtr = (TkWindow *) tkwin;
    TkDisplay *dispPtr = winPtr->dispPtr;
    Tcl_Interp *interp;

    /*
     * Case #1: SelectionClear events.
     */

    if (eventPtr->type == SelectionClear) {
	TkSelClearSelection(tkwin, eventPtr);
    }

    /*
     * Case #2: SelectionNotify events. Call the relevant function to handle
     * the incoming selection.
     */

    if (eventPtr->type == SelectionNotify) {
	register TkSelRetrievalInfo *retrPtr;
	TkSelRetrievalInfo *retrPtr;
	char *propInfo, **propInfoPtr = &propInfo;
	Atom type;
	int format, result;
	unsigned long numItems, bytesAfter;
	Tcl_DString ds;

	for (retrPtr = pendingRetrievals; ; retrPtr = retrPtr->nextPtr) {
	    if (retrPtr == NULL) {
		return;
	    }
	    if ((retrPtr->winPtr == winPtr)
		    && (retrPtr->selection == eventPtr->xselection.selection)
587
588
589
590
591
592
593

594
595
596
597
598
599
600
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600







+







	    retrPtr->result = TCL_ERROR;
	    XFree(propInfo);
	    return;
	}
	if ((type == XA_STRING) || (type == dispPtr->textAtom)
		|| (type == dispPtr->compoundTextAtom)) {
	    Tcl_Encoding encoding;
		Tcl_DString ds;

	    if (format != 8) {
		Tcl_SetObjResult(retrPtr->interp, Tcl_ObjPrintf(
			"bad format for string selection: wanted \"8\", got \"%d\"",
			format));
		Tcl_SetErrorCode(retrPtr->interp, "TK", "SELECTION", "FORMAT",
			NULL);
645
646
647
648
649
650
651
652

653
654
655
656
657
658
659
645
646
647
648
649
650
651

652
653
654
655
656
657
658
659







-
+







		Tcl_SetErrorCode(retrPtr->interp, "TK", "SELECTION", "FORMAT",
			NULL);
		retrPtr->result = TCL_ERROR;
		return;
	    }

	    if (propInfo[numItems] != '\0') {
		propData = ckalloc(numItems + 1);
		propData = (char *)ckalloc(numItems + 1);
		strcpy(propData, propInfo);
		propData[numItems] = '\0';
	    }
	    retrPtr->result = retrPtr->proc(retrPtr->clientData,
		    retrPtr->interp, propData);
	    if (propData != propInfo) {
		ckfree(propData);
738
739
740
741
742
743
744
745

746
747
748
749
750
751
752
738
739
740
741
742
743
744

745
746
747
748
749
750
751
752







-
+







 *----------------------------------------------------------------------
 */

static void
SelTimeoutProc(
    ClientData clientData)	/* Information about retrieval in progress. */
{
    register TkSelRetrievalInfo *retrPtr = clientData;
    TkSelRetrievalInfo *retrPtr = (TkSelRetrievalInfo *)clientData;

    /*
     * Make sure that the retrieval is still in progress. Then see how long
     * it's been since any sort of response was received from the other side.
     */

    if (retrPtr->result != -1) {
762
763
764
765
766
767
768
769

770
771
772
773
774
775
776
762
763
764
765
766
767
768

769
770
771
772
773
774
775
776







-
+








	Tcl_SetObjResult(retrPtr->interp, Tcl_NewStringObj(
		"selection owner didn't respond", -1));
	Tcl_SetErrorCode(retrPtr->interp, "TK", "SELECTION", "IGNORED", NULL);
	retrPtr->result = TCL_ERROR;
    } else {
	retrPtr->timeout = Tcl_CreateTimerHandler(1000, SelTimeoutProc,
		(ClientData) retrPtr);
		retrPtr);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * ConvertSelection --
792
793
794
795
796
797
798
799

800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816

817
818
819
820


821
822
823
824
825
826
827
792
793
794
795
796
797
798

799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815

816
817
818


819
820
821
822
823
824
825
826
827







-
+
















-
+


-
-
+
+








static void
ConvertSelection(
    TkWindow *winPtr,		/* Window that received the conversion
				 * request; may not be selection's current
				 * owner, be we set it to the current
				 * owner. */
    register XSelectionRequestEvent *eventPtr)
    XSelectionRequestEvent *eventPtr)
				/* Event describing request. */
{
	union {
		XSelectionEvent xsel;
		XEvent ev;
	} reply;	/* Used to notify requestor that selection
				 * info is ready. */
    int multiple;		/* Non-zero means a MULTIPLE request is being
				 * handled. */
    IncrInfo incr;		/* State of selection conversion. */
    Atom singleInfo[2];		/* incr.multAtoms points here except for
				 * multiple conversions. */
    unsigned long i;
    Tk_ErrorHandler errorHandler;
    TkSelectionInfo *infoPtr;
    TkSelInProgress ip;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    errorHandler = Tk_CreateErrorHandler(eventPtr->display, -1, -1,-1,
	    (int (*)()) NULL, NULL);
    errorHandler = Tk_CreateErrorHandler(eventPtr->display, -1, -1,
	    -1, NULL, NULL);

    /*
     * Initialize the reply event.
     */

    reply.xsel.type = SelectionNotify;
    reply.xsel.serial = 0;
889
890
891
892
893
894
895
896

897
898
899
900
901

902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922

923
924
925
926
927
928
929
889
890
891
892
893
894
895

896
897
898
899
900

901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921

922
923
924
925
926
927
928
929







-
+




-
+




















-
+







    /*
     * Loop through all of the requested conversions, and either return the
     * entire converted selection, if it can be returned in a single bunch, or
     * return INCR information only (the actual selection will be returned
     * below).
     */

    incr.converts = ckalloc(incr.numConversions * sizeof(ConvertInfo));
    incr.converts = (ConvertInfo *)ckalloc(incr.numConversions * sizeof(ConvertInfo));
    incr.numIncrs = 0;
    for (i = 0; i < incr.numConversions; i++) {
	Atom target, property, type;
	long buffer[TK_SEL_WORDS_AT_ONCE];
	register TkSelHandler *selPtr;
	TkSelHandler *selPtr;
	int numItems, format;
	char *propPtr;

	target = incr.multAtoms[2*i];
	property = incr.multAtoms[2*i + 1];
	incr.converts[i].offset = -1;
	incr.converts[i].buffer[0] = '\0';

	for (selPtr = winPtr->selHandlerList; selPtr != NULL;
		selPtr = selPtr->nextPtr) {
	    if ((selPtr->target == target)
		    && (selPtr->selection == eventPtr->selection)) {
		break;
	    }
	}

	if (selPtr == NULL) {
	    /*
	     * Nobody seems to know about this kind of request. If it's of a
	     * sort that we can handle without any help, do it. Otherwise mark
	     * the request as an errror.
	     * the request as an error.
	     */

	    numItems = TkSelDefaultSelection(infoPtr, target, (char *) buffer,
		    TK_SEL_BYTES_AT_ONCE, &type);
	    if (numItems < 0) {
		incr.multAtoms[2*i + 1] = None;
		continue;
1060
1061
1062
1063
1064
1065
1066
1067

1068
1069
1070
1071
1072
1073
1074
1060
1061
1062
1063
1064
1065
1066

1067
1068
1069
1070
1071
1072
1073
1074







-
+







	IncrInfo *incrPtr2;

	while (incr.numIncrs > 0) {
	    Tcl_DoOneEvent(0);
	}
	Tcl_DeleteTimerHandler(incr.timeout);
	errorHandler = Tk_CreateErrorHandler(winPtr->display,
		-1, -1, -1, (int (*)()) NULL, NULL);
		-1, -1, -1, NULL, NULL);
	XSelectInput(reply.xsel.display, reply.xsel.requestor, 0L);
	Tk_DeleteErrorHandler(errorHandler);
	if (tsdPtr->pendingIncrs == &incr) {
	    tsdPtr->pendingIncrs = incr.nextPtr;
	} else {
	    for (incrPtr2 = tsdPtr->pendingIncrs; incrPtr2 != NULL;
		    incrPtr2 = incrPtr2->nextPtr) {
1120
1121
1122
1123
1124
1125
1126
1127

1128
1129

1130
1131
1132
1133
1134
1135
1136
1120
1121
1122
1123
1124
1125
1126

1127
1128

1129
1130
1131
1132
1133
1134
1135
1136







-
+

-
+







 *
 *----------------------------------------------------------------------
 */

static void
SelRcvIncrProc(
    ClientData clientData,	/* Information about retrieval. */
    register XEvent *eventPtr)	/* X PropertyChange event. */
    XEvent *eventPtr)	/* X PropertyChange event. */
{
    register TkSelRetrievalInfo *retrPtr = clientData;
    TkSelRetrievalInfo *retrPtr = (TkSelRetrievalInfo *)clientData;
    char *propInfo, **propInfoPtr = &propInfo;
    Atom type;
    int format, result;
    unsigned long numItems, bytesAfter;
    Tcl_Interp *interp;

    if ((eventPtr->xproperty.atom != retrPtr->property)
1370
1371
1372
1373
1374
1375
1376
1377

1378
1379
1380
1381
1382
1383
1384
1370
1371
1372
1373
1374
1375
1376

1377
1378
1379
1380
1381
1382
1383
1384







-
+








static void
IncrTimeoutProc(
    ClientData clientData)	/* Information about INCR-mode selection
				 * retrieval for which we are selection
				 * owner. */
{
    register IncrInfo *incrPtr = clientData;
    IncrInfo *incrPtr = (IncrInfo *)clientData;

    incrPtr->idleTime++;
    if (incrPtr->idleTime >= 5) {
	incrPtr->numIncrs = 0;
    } else {
	incrPtr->timeout = Tcl_CreateTimerHandler(1000, IncrTimeoutProc,
		incrPtr);
1431
1432
1433
1434
1435
1436
1437
1438

1439
1440
1441
1442
1443
1444
1445
1431
1432
1433
1434
1435
1436
1437

1438
1439
1440
1441
1442
1443
1444
1445







-
+







     * 2. If type is anything else, convert each field from an ASCII number to
     *    a 32-bit binary number.
     */

    if (Tcl_SplitList(NULL, string, &numFields, &field) != TCL_OK) {
	return NULL;
    }
    propPtr = ckalloc(numFields * sizeof(long));
    propPtr = (long *)ckalloc(numFields * sizeof(long));

    /*
     * Convert the fields one-by-one.
     */

    for (i=0 ; i<numFields ; i++) {
	if (type == XA_ATOM) {
1483
1484
1485
1486
1487
1488
1489
1490

1491
1492
1493
1494
1495
1496
1497
1483
1484
1485
1486
1487
1488
1489

1490
1491
1492
1493
1494
1495
1496
1497







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
SelCvtFromX32(
    register long *propPtr,	/* Property value from X. */
    long *propPtr,	/* Property value from X. */
    int numValues,		/* Number of 32-bit values in property. */
    Atom type,			/* Type of property Should not be XA_STRING
				 * (if so, don't bother calling this function
				 * at all). */
    Tk_Window tkwin,		/* Window to use for atom conversion. */
    Tcl_DString *dsPtr)		/* Where to store the converted string. */
{
1516
1517
1518
1519
1520
1521
1522
1523

1524
1525

1526
1527
1528

1529
1530
1531
1532
1533
1534
1535
1516
1517
1518
1519
1520
1521
1522

1523
1524

1525
1526
1527

1528
1529
1530
1531
1532
1533
1534
1535







-
+

-
+


-
+







	}
    }
    Tcl_DStringAppend(dsPtr, " ", 1);
}

static void
SelCvtFromX8(
    register char *propPtr,	/* Property value from X. */
    char *propPtr,	/* Property value from X. */
    int numValues,		/* Number of 8-bit values in property. */
    Atom type,			/* Type of property Should not be XA_STRING
    TCL_UNUSED(Atom),			/* Type of property Should not be XA_STRING
				 * (if so, don't bother calling this function
				 * at all). */
    Tk_Window tkwin,		/* Window to use for atom conversion. */
    TCL_UNUSED(Tk_Window),		/* Window to use for atom conversion. */
    Tcl_DString *dsPtr)		/* Where to store the converted string. */
{
    /*
     * Convert each long in the property to a string value, which is a
     * hexadecimal string. We build the list in a Tcl_DString because this is
     * easier than trying to get the quoting correct ourselves.
     */
Changes to unix/tkUnixSend.c.
1
2
3
4
5
6
7
8
9



10
11
12
13
14
15
16
1
2
3
4
5
6



7
8
9
10
11
12
13
14
15
16






-
-
-
+
+
+







/*
 * tkUnixSend.c --
 *
 *	This file provides functions that implement the "send" command,
 *	allowing commands to be passed from interpreter to interpreter.
 *
 * Copyright (c) 1989-1994 The Regents of the University of California.
 * Copyright (c) 1994-1996 Sun Microsystems, Inc.
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 * Copyright © 1989-1994 The Regents of the University of California.
 * Copyright © 1994-1996 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 "tkUnixInt.h"

265
266
267
268
269
270
271
272

273
274
275
276
277
278
279
265
266
267
268
269
270
271

272
273
274
275
276
277
278
279







-
+








    if (dispPtr->commTkwin == NULL) {
	SendInit(interp, dispPtr);
    }

    handler = Tk_CreateErrorHandler(dispPtr->display, -1, -1, -1, NULL, NULL);

    regPtr = ckalloc(sizeof(NameRegistry));
    regPtr = (NameRegistry *)ckalloc(sizeof(NameRegistry));
    regPtr->dispPtr = dispPtr;
    regPtr->locked = 0;
    regPtr->modified = 0;
    regPtr->allocedByX = 1;
    propertyPtr = &regPtr->property;

    if (lock && !localData.sendDebug) {
475
476
477
478
479
480
481
482

483
484
485
486
487
488
489
475
476
477
478
479
480
481

482
483
484
485
486
487
488
489







-
+







{
    char id[30], *newProp;
    int idLength, newBytes;

    sprintf(id, "%x ", (unsigned) commWindow);
    idLength = strlen(id);
    newBytes = idLength + strlen(name) + 1;
    newProp = ckalloc(regPtr->propLength + newBytes);
    newProp = (char *)ckalloc(regPtr->propLength + newBytes);
    strcpy(newProp, id);
    strcpy(newProp+idLength, name);
    if (regPtr->property != NULL) {
	memcpy(newProp + newBytes, regPtr->property, regPtr->propLength);
	if (regPtr->allocedByX) {
	    XFree(regPtr->property);
	} else {
804
805
806
807
808
809
810
811

812
813
814
815
816
817
818
804
805
806
807
808
809
810

811
812
813
814
815
816
817
818







-
+







    TkWindow *winPtr = (TkWindow *) tkwin;
    TkDisplay *dispPtr = winPtr->dispPtr;
    NameRegistry *regPtr;
    Tcl_Interp *interp;
    const char *actualName;
    Tcl_DString dString;
    int offset, i;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    interp = winPtr->mainPtr->interp;
    if (dispPtr->commTkwin == NULL) {
	SendInit(interp, winPtr->dispPtr);
    }

826
827
828
829
830
831
832
833

834
835
836
837
838
839
840
826
827
828
829
830
831
832

833
834
835
836
837
838
839
840







-
+







	if (riPtr == NULL) {
	    /*
	     * This interpreter isn't currently registered; create the data
	     * structure that will be used to register it locally, plus add
	     * the "send" command to the interpreter.
	     */

	    riPtr = ckalloc(sizeof(RegisteredInterp));
	    riPtr = (RegisteredInterp *)ckalloc(sizeof(RegisteredInterp));
	    riPtr->interp = interp;
	    riPtr->dispPtr = winPtr->dispPtr;
	    riPtr->nextPtr = tsdPtr->interpListPtr;
	    tsdPtr->interpListPtr = riPtr;
	    riPtr->name = NULL;
	    Tcl_CreateObjCommand(interp, "send", Tk_SendObjCmd, riPtr, DeleteProc);
	    if (Tcl_IsSafe(interp)) {
910
911
912
913
914
915
916
917

918
919
920
921
922
923
924
910
911
912
913
914
915
916

917
918
919
920
921
922
923
924







-
+







     * We've now got a name to use. Store it in the name registry and in the
     * local entry for this application, plus put it in a property on the
     * commWindow.
     */

    RegAddName(regPtr, actualName, Tk_WindowId(dispPtr->commTkwin));
    RegClose(regPtr);
    riPtr->name = ckalloc(strlen(actualName) + 1);
    riPtr->name = (char *)ckalloc(strlen(actualName) + 1);
    strcpy(riPtr->name, actualName);
    if (actualName != name) {
	Tcl_DStringFree(&dString);
    }
    UpdateCommWindow(dispPtr);

    return riPtr->name;
939
940
941
942
943
944
945
946

947
948
949
950
951
952
953
954
955
956
957
958
959
960
961

962
963
964
965
966
967
968
969
970

971
972
973
974
975
976
977
939
940
941
942
943
944
945

946
947
948
949
950
951
952
953
954
955
956
957
958
959
960

961
962
963
964
965
966
967
968
969

970
971
972
973
974
975
976
977







-
+














-
+








-
+







 *	See the user documentation.
 *
 *--------------------------------------------------------------
 */

int
Tk_SendObjCmd(
    ClientData clientData,	/* Information about sender (only dispPtr
    TCL_UNUSED(void *),	/* Information about sender (only dispPtr
				 * field is used). */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument strings. */
{
    enum {
	SEND_ASYNC, SEND_DISPLAYOF, SEND_LAST
    };
    static const char *const sendOptions[] = {
	"-async",   "-displayof",   "--",  NULL
    };
    TkWindow *winPtr;
    Window commWindow;
    PendingCommand pending;
    register RegisteredInterp *riPtr;
    RegisteredInterp *riPtr;
    const char *destName;
    int result, index, async, i, firstArg;
    Tk_RestrictProc *prevProc;
    ClientData prevArg;
    TkDisplay *dispPtr;
    Tcl_Time timeout;
    NameRegistry *regPtr;
    Tcl_DString request;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    Tcl_Interp *localInterp;	/* Used when the interpreter to send the
				 * command to is within the same process. */

    /*
     * Process options, if any.
     */
1171
1172
1173
1174
1175
1176
1177
1178

1179
1180
1181
1182
1183
1184
1185
1171
1172
1173
1174
1175
1176
1177

1178
1179
1180
1181
1182
1183
1184
1185







-
+







		if (ValidateName(pending.dispPtr, pending.target,
			pending.commWindow, 1)) {
		    msg = "target application died or uses a Tk version before 4.0";
		} else {
		    msg = "target application died";
		}
		pending.code = TCL_ERROR;
		pending.result = ckalloc(strlen(msg) + 1);
		pending.result = (char *)ckalloc(strlen(msg) + 1);
		strcpy(pending.result, msg);
		pending.gotResponse = 1;
	    } else {
		Tcl_GetTime(&timeout);
		timeout.sec += 2;
	    }
	}
1352
1353
1354
1355
1356
1357
1358
1359

1360
1361
1362
1363
1364
1365
1366
1352
1353
1354
1355
1356
1357
1358

1359
1360
1361
1362
1363
1364
1365
1366







-
+







 *	Sets up various data structures and windows.
 *
 *--------------------------------------------------------------
 */

static int
SendInit(
    Tcl_Interp *interp,		/* Interpreter to use for error reporting (no
    TCL_UNUSED(Tcl_Interp *),	/* Interpreter to use for error reporting (no
				 * errors are ever returned, but the
				 * interpreter is needed anyway). */
    TkDisplay *dispPtr)		/* Display to initialize. */
{
    XSetWindowAttributes atts;

    /*
1415
1416
1417
1418
1419
1420
1421
1422

1423
1424
1425
1426
1427
1428
1429

1430
1431
1432
1433
1434
1435
1436
1415
1416
1417
1418
1419
1420
1421

1422
1423
1424
1425
1426
1427
1428

1429
1430
1431
1432
1433
1434
1435
1436







-
+






-
+







 */

static void
SendEventProc(
    ClientData clientData,	/* Display information. */
    XEvent *eventPtr)		/* Information about event. */
{
    TkDisplay *dispPtr = clientData;
    TkDisplay *dispPtr = (TkDisplay *)clientData;
    char *propInfo, **propInfoPtr = &propInfo;
    const char *p;
    int result, actualFormat;
    unsigned long numItems, bytesAfter;
    Atom actualType;
    Tcl_Interp *remoteInterp;	/* Interp in which to execute the command. */
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if ((eventPtr->xproperty.atom != dispPtr->commProperty)
	    || (eventPtr->xproperty.state != PropertyNewValue)) {
	return;
    }

1694
1695
1696
1697
1698
1699
1700
1701

1702
1703
1704
1705
1706

1707
1708
1709
1710

1711
1712
1713
1714
1715
1716
1717
1694
1695
1696
1697
1698
1699
1700

1701
1702
1703
1704
1705

1706
1707
1708
1709

1710
1711
1712
1713
1714
1715
1716
1717







-
+




-
+



-
+







	    for (pcPtr = tsdPtr->pendingCommands; pcPtr != NULL;
		    pcPtr = pcPtr->nextPtr) {
		if ((serial != pcPtr->serial) || (pcPtr->result != NULL)) {
		    continue;
		}
		pcPtr->code = code;
		if (resultString != NULL) {
		    pcPtr->result = ckalloc(strlen(resultString) + 1);
		    pcPtr->result = (char *)ckalloc(strlen(resultString) + 1);
		    strcpy(pcPtr->result, resultString);
		}
		if (code == TCL_ERROR) {
		    if (errorInfo != NULL) {
			pcPtr->errorInfo = ckalloc(strlen(errorInfo) + 1);
			pcPtr->errorInfo = (char *)ckalloc(strlen(errorInfo) + 1);
			strcpy(pcPtr->errorInfo, errorInfo);
		    }
		    if (errorCode != NULL) {
			pcPtr->errorCode = ckalloc(strlen(errorCode) + 1);
			pcPtr->errorCode = (char *)ckalloc(strlen(errorCode) + 1);
			strcpy(pcPtr->errorCode, errorCode);
		    }
		}
		pcPtr->gotResponse = 1;
		break;
	    }
	} else {
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781

1782
1783
1784
1785



1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799

1800
1801
1802
1803
1804
1805
1806
1770
1771
1772
1773
1774
1775
1776

1777
1778
1779

1780
1781



1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797

1798
1799
1800
1801
1802
1803
1804
1805







-



-
+

-
-
-
+
+
+













-
+







}

/*
 * The function below is invoked if an error occurs during the XChangeProperty
 * operation above.
 */

	/* ARGSUSED */
static int
AppendErrorProc(
    ClientData clientData,	/* Command to mark complete, or NULL. */
    XErrorEvent *errorPtr)	/* Information about error. */
    TCL_UNUSED(XErrorEvent *))	/* Information about error. */
{
    PendingCommand *pendingPtr = clientData;
    register PendingCommand *pcPtr;
    ThreadSpecificData *tsdPtr =
    PendingCommand *pendingPtr = (PendingCommand *)clientData;
    PendingCommand *pcPtr;
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (pendingPtr == NULL) {
	return 0;
    }

    /*
     * Make sure this command is still pending.
     */

    for (pcPtr = tsdPtr->pendingCommands; pcPtr != NULL;
	    pcPtr = pcPtr->nextPtr) {
	if ((pcPtr == pendingPtr) && (pcPtr->result == NULL)) {
	    pcPtr->result = ckalloc(strlen(pcPtr->target) + 50);
	    pcPtr->result = (char *)ckalloc(strlen(pcPtr->target) + 50);
	    sprintf(pcPtr->result, "no application named \"%s\"",
		    pcPtr->target);
	    pcPtr->code = TCL_ERROR;
	    pcPtr->gotResponse = 1;
	    break;
	}
    }
1825
1826
1827
1828
1829
1830
1831
1832
1833


1834
1835

1836
1837
1838
1839
1840
1841
1842
1824
1825
1826
1827
1828
1829
1830


1831
1832
1833

1834
1835
1836
1837
1838
1839
1840
1841







-
-
+
+

-
+







 */

static void
DeleteProc(
    ClientData clientData)	/* Info about registration, passed as
				 * ClientData. */
{
    RegisteredInterp *riPtr = clientData;
    register RegisteredInterp *riPtr2;
    RegisteredInterp *riPtr = (RegisteredInterp *)clientData;
    RegisteredInterp *riPtr2;
    NameRegistry *regPtr;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    regPtr = RegOpen(riPtr->interp, riPtr->dispPtr, 1);
    RegDeleteName(regPtr, riPtr->name);
    RegClose(regPtr);

    if (tsdPtr->interpListPtr == riPtr) {
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881


1882
1883
1884
1885
1886
1887
1888
1869
1870
1871
1872
1873
1874
1875

1876
1877


1878
1879
1880
1881
1882
1883
1884
1885
1886







-


-
-
+
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

    /* ARGSUSED */
static Tk_RestrictAction
SendRestrictProc(
    ClientData clientData,		/* Not used. */
    register XEvent *eventPtr)		/* Event that just arrived. */
    TCL_UNUSED(void *),		/* Not used. */
    XEvent *eventPtr)		/* Event that just arrived. */
{
    TkDisplay *dispPtr;

    if (eventPtr->type != PropertyNotify) {
	return TK_DEFER_EVENT;
    }
    for (dispPtr = TkGetDisplayList(); dispPtr != NULL;
1917
1918
1919
1920
1921
1922
1923
1924

1925
1926
1927
1928
1929
1930
1931
1915
1916
1917
1918
1919
1920
1921

1922
1923
1924
1925
1926
1927
1928
1929







-
+







static void
UpdateCommWindow(
    TkDisplay *dispPtr)		/* Display whose commWindow is to be
				 * updated. */
{
    Tcl_DString names;
    RegisteredInterp *riPtr;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    Tcl_DStringInit(&names);
    for (riPtr = tsdPtr->interpListPtr; riPtr != NULL;
	    riPtr = riPtr->nextPtr) {
	Tcl_DStringAppendElement(&names, riPtr->name);
    }
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971

1972
1973
1974
1975
1976
1977
1978
1948
1949
1950
1951
1952
1953
1954

1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967

1968
1969
1970
1971
1972
1973
1974
1975







-













-
+







 *
 * Side effects:
 *	Depends on option; see below.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
int
TkpTestsendCmd(
    ClientData clientData,	/* Main window for application. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])		/* Argument strings. */
{
    enum {
	TESTSEND_BOGUS, TESTSEND_PROP, TESTSEND_SERIAL
    };
    static const char *const testsendOptions[] = {
	"bogus",   "prop",   "serial",  NULL
    };
    TkWindow *winPtr = clientData;
    TkWindow *winPtr = (TkWindow *)clientData;
    Tk_ErrorHandler handler;
    int index;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv,
		"option ?arg ...?");
	return TCL_ERROR;
2048
2049
2050
2051
2052
2053
2054
2055

2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2045
2046
2047
2048
2049
2050
2051

2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063







-
+











	    XChangeProperty(winPtr->dispPtr->display, w, propName, XA_STRING,
		    8, PropModeReplace, (unsigned char*)Tcl_DStringValue(&tmp),
		    p-Tcl_DStringValue(&tmp));
            Tk_DeleteErrorHandler(handler);
	    Tcl_DStringFree(&tmp);
	}
    } else if (index == TESTSEND_SERIAL) {
	Tcl_SetObjResult(interp, Tcl_NewIntObj(localData.sendSerial+1));
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(localData.sendSerial+1));
    }
    return TCL_OK;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Added unix/tkUnixSysNotify.c.





























































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
 * tkUnixSysNotify.c --
 *
 * 	tkUnixSysNotify.c implements a "sysnotify" Tcl command which
 * 	permits one to post system notifications based on the libnotify API.
 *
 * Copyright © 2020 Kevin Walzer/WordTech Communications LLC.
 * Copyright © 2020 Christian Werner for runtime linking
 *
 * 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 "tkUnixInt.h"

/*
 * Runtime linking of libnotify.
 */

typedef int	(*fn_ln_init)(const char *);
typedef void	(*fn_ln_uninit)(void);
typedef void *	(*fn_ln_notification_new)(const char *, const char *,
			const char *, void *);
typedef int	(*fn_ln_notification_show)(void *, int *);

static struct {
    int				nopen;
    Tcl_LoadHandle		lib;
    fn_ln_init			init;
    fn_ln_uninit		uninit;
    fn_ln_notification_new	notification_new;
    fn_ln_notification_show	notification_show;
} ln_fns = {
    0, NULL, NULL, NULL, NULL, NULL
};

#define notify_init			ln_fns.init
#define notify_uninit			ln_fns.uninit
#define notify_notification_new		ln_fns.notification_new
#define notify_notification_show	ln_fns.notification_show

TCL_DECLARE_MUTEX(ln_mutex);

/*
 * Forward declarations for procedures defined in this file.
 */

static void	SysNotifyDeleteCmd(void *);
static int	SysNotifyCmd(void *, Tcl_Interp *, int, Tcl_Obj * const*);

/*
 *----------------------------------------------------------------------
 *
 * SysNotifyDeleteCmd --
 *
 *      Delete notification and clean up.
 *
 * Results:
 *	Window destroyed.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
SysNotifyDeleteCmd (
    TCL_UNUSED(void *))
{
    Tcl_MutexLock(&ln_mutex);
    if (--ln_fns.nopen == 0) {
	if (notify_uninit) {
	    notify_uninit();
	}
	if (ln_fns.lib != NULL) {
	    Tcl_FSUnloadFile(NULL, ln_fns.lib);
	}
	memset(&ln_fns, 0, sizeof(ln_fns));
    }
    Tcl_MutexUnlock(&ln_mutex);
}

/*
 *----------------------------------------------------------------------
 *
 * SysNotifyCreateCmd --
 *
 *      Create tray command and (unreal) window.
 *
 * Results:
 *	Icon tray and hidden window created.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
SysNotifyCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    const char *title;
    const char *message;
    const char *icon;
    void *notif;

    if (objc < 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "title message");
	return TCL_ERROR;
    }

    /*
     * Pass strings to notification, and use a sane platform-specific
     * icon in the alert.
     */

    title = Tcl_GetString(objv[1]);
    message = Tcl_GetString(objv[2]);
    icon = "dialog-information";

    /*
     * Call to notify_init should go here to prevent test suite failure.
     */

    if (notify_init && notify_notification_new && notify_notification_show) {
	Tcl_Encoding enc;
	Tcl_DString dst, dsm;

	enc = Tcl_GetEncoding(NULL, "utf-8");
	Tcl_ExternalToUtfDString(enc, title, -1, &dst);
	Tcl_ExternalToUtfDString(enc, message, -1, &dsm);
	notify_init("Wish");
	notif = notify_notification_new(title, message, icon, NULL);
	notify_notification_show(notif, NULL);
	Tcl_DStringFree(&dsm);
	Tcl_DStringFree(&dst);
	Tcl_FreeEncoding(enc);
    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * SysNotify_Init --
 *
 *      Initialize the command.
 *
 * Results:
 *	Command initialized.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
SysNotify_Init(
    Tcl_Interp *interp)
{
    Tcl_MutexLock(&ln_mutex);
    if (ln_fns.nopen == 0) {
	int i = 0;
	Tcl_Obj *nameobj;
	static const char *lnlibs[] = {
	    "libnotify.so.4",
	    "libnotify.so.3",
	    "libnotify.so.2",
	    "libnotify.so.1",
	    "libnotify.so",
	    NULL
	};

	while (lnlibs[i] != NULL) {
	    Tcl_ResetResult(interp);
	    nameobj = Tcl_NewStringObj(lnlibs[i], -1);
	    Tcl_IncrRefCount(nameobj);
	    if (Tcl_LoadFile(interp, nameobj, NULL, 0, NULL, &ln_fns.lib)
		    == TCL_OK) {
		Tcl_DecrRefCount(nameobj);
		break;
	    }
	    Tcl_DecrRefCount(nameobj);
	    ++i;
	}
	if (ln_fns.lib != NULL) {
#define LN_SYM(name)							\
	    ln_fns.name = (fn_ln_ ## name)				\
		Tcl_FindSymbol(NULL, ln_fns.lib, "notify_" #name)
	    LN_SYM(init);
	    LN_SYM(uninit);
	    LN_SYM(notification_new);
	    LN_SYM(notification_show);
#undef LN_SYM
	}
    }
    ln_fns.nopen++;
    Tcl_MutexUnlock(&ln_mutex);

    Tcl_CreateObjCommand(interp, "::tk::sysnotify::_sysnotify", SysNotifyCmd,
	    interp, SysNotifyDeleteCmd);
    return TCL_OK;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * coding: utf-8
 * End:
 */

Added unix/tkUnixSysTray.c.




























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
 * tkUnixSysTray.c --
 *
 * 	tkUnixSysTray.c implements a "systray" Tcl command which permits to
 * 	change the system tray/taskbar icon of a Tk toplevel window and
 * 	to post system notifications.
 *
 * Copyright © 2005 Anton Kovalenko.
 * Copyright © 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.
 */

#include "tkInt.h"
#include "tkUnixInt.h"

/*
 * Based extensively on the tktray extension package. Here we are removing
 * non-essential parts of tktray.
 */

#include <time.h>
#include <string.h>
#include <stdio.h>

#include <X11/X.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>

/* XEmbed definitions
 * See http://www.freedesktop.org/wiki/Standards_2fxembed_2dspec
 * */
#define XEMBED_MAPPED           (1<<0)
/* System tray opcodes
 * See http://www.freedesktop.org/wiki/Standards_2fsystemtray_2dspec
 * */
#define SYSTEM_TRAY_REQUEST_DOCK    0
#define SYSTEM_TRAY_BEGIN_MESSAGE   1
#define SYSTEM_TRAY_CANCEL_MESSAGE  2

/* Flags of widget configuration options */
#define ICON_CONF_IMAGE         (1<<0)  /* Image changed */
#define ICON_CONF_REDISPLAY     (1<<1)  /* Redisplay required */
#define ICON_CONF_XEMBED        (1<<2)  /* Remapping or unmapping required */
#define ICON_CONF_CLASS         (1<<3)   /* TODO WM_CLASS update required */
#define ICON_CONF_FIRST_TIME    (1<<4)  /* For IconConfigureMethod invoked by the constructor */

/* Widget states */
#define ICON_FLAG_REDRAW_PENDING    (1<<0)
#define ICON_FLAG_ARGB32            (1<<1)
#define ICON_FLAG_DIRTY_EDGES       (1<<2)

#define TKU_NO_BAD_WINDOW_BEGIN(display) \
    { Tk_ErrorHandler error__handler = \
	    Tk_CreateErrorHandler(display, BadWindow, -1, -1, NULL, NULL);
#define TKU_NO_BAD_WINDOW_END Tk_DeleteErrorHandler(error__handler); }

/*Declaration for utility functions.*/
static void TKU_WmWithdraw(Tk_Window winPtr, Tcl_Interp* interp);
static Tk_Window TKU_GetWrapper(Tk_Window winPtr);
void TKU_AddInput(Display* dpy, Window win, long add_to_mask);
static Tk_Window TKU_Wrapper(Tk_Window w, Tcl_Interp* interp);
static Window TKU_XID(Tk_Window w);

/* Customized window withdraw */
static void
TKU_WmWithdraw(
    Tk_Window winPtr,
    TCL_UNUSED(Tcl_Interp *))
{
    TkpWmSetState((TkWindow*)winPtr, WithdrawnState);
}

/* The wrapper should exist */
static Tk_Window
TKU_GetWrapper(
    Tk_Window winPtr)
{
    return (Tk_Window)
	    TkpGetWrapperWindow((TkWindow*)winPtr);
}

/* Subscribe for extra X11 events (needed for MANAGER selection) */
void
TKU_AddInput(
    Display* dpy,
    Window win,
    long add_to_mask)
{
    XWindowAttributes xswa;
    TKU_NO_BAD_WINDOW_BEGIN(dpy)
        XGetWindowAttributes(dpy,win,&xswa);
        XSelectInput(dpy,win,xswa.your_event_mask|add_to_mask);
    TKU_NO_BAD_WINDOW_END
}

/* Get Tk Window wrapper (make it exist if ny) */
static Tk_Window
TKU_Wrapper(
    Tk_Window w,
    Tcl_Interp* interp)
{
    Tk_Window wrapper = TKU_GetWrapper(w);
    if (!wrapper) {
	Tk_MakeWindowExist(w);
	TKU_WmWithdraw(w, interp);
	Tk_MapWindow(w);
	wrapper = (Tk_Window) TKU_GetWrapper(w);
    }
    return wrapper;
}

/* Return X window id for Tk window (make it exist if ny) */
static Window
TKU_XID(
    Tk_Window w)
{
    Window xid = Tk_WindowId(w);
    if (xid == None) {
	Tk_MakeWindowExist(w);
	xid = Tk_WindowId(w);
    }
    return xid;
}

/* Data structure representing dock widget */
typedef struct {
    /* standard for widget */
    Tk_Window tkwin, drawingWin;
    Window wrapper;
    Window myManager;
    Window trayManager;

    Tk_OptionTable options;
    Tcl_Interp *interp;
    Tcl_Command widgetCmd;

    Tk_Image image; /* image to be drawn */

    /* Only one of imageVisualInstance and photo is needed for argb32
     * operations. Unless imageString changes, imageVisualInstance is
     * always valid for the same drawingWin instance, but photo is
     * invalidated by any "whole image" type change. */

    Tk_Image imageVisualInstance; /* image instance for use with argb32 */
    Tk_PhotoHandle photo;	  /* !null if it's really a photo */

    /* Offscreen pixmap is created for a given imageWidth,
     * imageHeight, drawingWin, and invalidated (and freed) on image
     * resize or drawingWin destruction.

     * Contents of this pixmap is synced on demand; when image changes
     * but is not resized, pixmap is marked as out-of-sync. Next time
     * when redisplay is needed, pixmap is updated before drawing
     * operation.
     */

    Pixmap offscreenPixmap;
    /* There is no need to recreate GC ever; it remains valid once
     * created */

    GC offscreenGC;

    /* XImage for drawing ARGB32 photo on offscreenPixmap.  Should be
     * freed and nullified each time when a pixmap is freed.  Needed
     * (and created) when redrawing an image being a photo on ARGB32
     * offscreen pixmap. */
    XImage *offscreenImage;	/* for photo (argb32) drawing code */

    Visual *bestVisual;		/* Visual, when it's specified by tray
				 * manager AND is guessed to be
				 * ARGB32 */
    Colormap bestColormap;	/* Colormap for bestVisual */

    Atom aMANAGER;
    Atom a_NET_SYSTEM_TRAY_Sn;
    Atom a_XEMBED_INFO;
    Atom a_NET_SYSTEM_TRAY_MESSAGE_DATA;
    Atom a_NET_SYSTEM_TRAY_OPCODE;
    Atom a_NET_SYSTEM_TRAY_ORIENTATION;
    Atom a_NET_SYSTEM_TRAY_VISUAL;

    int flags; /* ICON_FLAG_ - see defines above */
    int msgid; /* Last balloon message ID */
    int useShapeExt;

    int x,y,width,height;
    int imageWidth, imageHeight;
    int requestedWidth, requestedHeight;
    int visible; /* whether XEMBED_MAPPED should be set */
    int docked;	 /* whether an icon should be docked */
    char *imageString, /* option: -image as string */
	 *classString; /* option: -class as string */
} DockIcon;

/*
 * Forward declarations for procedures defined in this file.
 */

static int TrayIconCreateCmd(ClientData cd, Tcl_Interp *interp,
			     int objc,  Tcl_Obj *const objv[]);
static int TrayIconObjectCmd(ClientData cd, Tcl_Interp *interp,
			     int objc,  Tcl_Obj *const objv[]);
static int TrayIconConfigureMethod(DockIcon *icon, Tcl_Interp* interp,
				   int objc,  Tcl_Obj *const objv[],
				   int addflags);
static int PostBalloon(DockIcon* icon, const char * utf8msg,
		       long timeout);
static void CancelBalloon(DockIcon* icon, int msgid);
static int QueryTrayOrientation(DockIcon* icon);

static void TrayIconDeleteProc(ClientData cd );
static Atom DockSelectionAtomFor(Tk_Window tkwin);
static void DockToManager(DockIcon *icon);
static void CreateTrayIconWindow(DockIcon *icon);

static void TrayIconRequestSize(DockIcon* icon, int w, int h);
static void TrayIconForceImageChange(DockIcon* icon);
static void TrayIconUpdate(DockIcon* icon, int mask);

static void EventuallyRedrawIcon(DockIcon* icon);
static void DisplayIcon(ClientData cd);

static void RetargetEvent(DockIcon *icon, XEvent *ev);

static void TrayIconEvent(ClientData cd, XEvent* ev);
static void UserIconEvent(ClientData cd, XEvent* ev);
static void TrayIconWrapperEvent(ClientData cd, XEvent* ev);
static int IconGenericHandler(ClientData cd, XEvent *ev);

int Tktray_Init (Tcl_Interp* interp );

/*
 *----------------------------------------------------------------------
 *
 * TrayIconObjectCmd --
 *
 * 	Manage attributes of tray icon.
 *
 * Results:
 *	Various values of the tray icon are set and retrieved.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TrayIconObjectCmd(
    ClientData cd,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    DockIcon *icon = (DockIcon*)cd;
    int bbox[4] = {0,0,0,0};
    Tcl_Obj * bboxObj;
    int wcmd;
    int i;
    XWindowAttributes xwa;
    Window bogus;
    int msgid;

    enum {XWC_CONFIGURE = 0, XWC_CGET, XWC_BALLOON, XWC_CANCEL,
            XWC_BBOX, XWC_DOCKED, XWC_ORIENTATION};
    const char *st_wcmd[] = {"configure", "cget", "balloon", "cancel",
            "bbox", "docked", "orientation", NULL};

    long timeout = 0;
    Tcl_Obj* optionValue;

    if (objc<2) {
	Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?");
	return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObj(interp, objv[1], st_wcmd,
            "subcommand", TCL_EXACT, &wcmd) != TCL_OK) {
	return TCL_ERROR;
    }

    switch (wcmd) {
    case XWC_CONFIGURE:
	return TrayIconConfigureMethod(icon,interp,objc-2,objv+2,0);

    case XWC_CGET:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp,2,objv,"option");
	    return TCL_ERROR;
	}
	optionValue = Tk_GetOptionValue(interp,(char*)icon,
                icon->options,objv[2],icon->tkwin);
	if (optionValue) {
	    Tcl_SetObjResult(interp,optionValue);
	    return TCL_OK;
	} else {
	    return TCL_ERROR;
	}

    case XWC_BALLOON:
	if ((objc != 3) && (objc != 4)) {
	    Tcl_WrongNumArgs(interp, 2, objv, "message ?timeout?");
	    return TCL_ERROR;
	}
	if (objc == 4) {
	    if (Tcl_GetLongFromObj(interp,objv[3],&timeout) != TCL_OK)
		return TCL_ERROR;
	}
	msgid = PostBalloon(icon,Tcl_GetString(objv[2]), timeout);
	Tcl_SetObjResult(interp,Tcl_NewIntObj(msgid));
	return TCL_OK;

    case XWC_CANCEL:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "messageId");
	    return TCL_ERROR;
	}
	if (Tcl_GetIntFromObj(interp,objv[2],&msgid) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (msgid)
	    CancelBalloon(icon,msgid);
	return TCL_OK;

    case XWC_BBOX:
	if (icon->drawingWin) {
	    XGetWindowAttributes(Tk_Display(icon->drawingWin),
                    TKU_XID(icon->drawingWin), &xwa);

	    XTranslateCoordinates(Tk_Display(icon->drawingWin),
                    TKU_XID(icon->drawingWin), xwa.root, 0,0,
                    &icon->x, &icon->y, &bogus);
	    bbox[0] = icon->x;
	    bbox[1] = icon->y;
	    bbox[2] = bbox[0] + icon->width - 1;
	    bbox[3] = bbox[1] + icon->height - 1;
	}
	bboxObj = Tcl_NewObj();
	for (i = 0; i < 4; ++i) {
	    Tcl_ListObjAppendElement(interp, bboxObj, Tcl_NewIntObj(bbox[i]));
	}
	Tcl_SetObjResult(interp, bboxObj);
	return TCL_OK;

    case XWC_DOCKED:
	Tcl_SetObjResult(interp, Tcl_NewBooleanObj(icon->myManager != None));
	return TCL_OK;

    case XWC_ORIENTATION:
	if (icon->myManager == None || icon->wrapper == None) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj("none", -1));
	} else {
	    switch(QueryTrayOrientation(icon)) {
	    case 0:
		Tcl_SetObjResult(interp, Tcl_NewStringObj("horizontal", -1));
		break;
	    case 1:
		Tcl_SetObjResult(interp, Tcl_NewStringObj("vertical", -1));
		break;
	    default:
		Tcl_SetObjResult(interp, Tcl_NewStringObj("unknown", -1));
		break;
	    }
	}
	return TCL_OK;
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * QueryTrayOrientation --
 *
 * 	Obtain the orientation of the tray icon.
 *
 * Results:
 *	Orientation is returned.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
QueryTrayOrientation(
    DockIcon* icon)
{
    Atom retType = None;
    int retFormat = 32;
    unsigned long retNitems, retBytesAfter;
    unsigned char *retProp = NULL;
    int result = -1;

    if (icon->wrapper != None && icon->myManager != None) {
	XGetWindowProperty(Tk_Display(icon->tkwin),
			   icon->myManager,
			   icon->a_NET_SYSTEM_TRAY_ORIENTATION,
			   /* offset */ 0,
			   /* length */ 1,
			   /* delete */ False,
			   /* type */ XA_CARDINAL,
			   &retType, &retFormat, &retNitems,
			   &retBytesAfter, &retProp);
	if (retType == XA_CARDINAL && retFormat == 32 && retNitems == 1) {
	    result = (int) *(long*)retProp;
	}
	if (retProp) {
	    XFree(retProp);
	}
    }
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * DockSelectionAtomFor --
 *
 * 	Obtain the dock selection atom.
 *
 * Results:
 *	Selection returned.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static Atom
DockSelectionAtomFor(
    Tk_Window tkwin)
{
    char buf[256];
    /* no snprintf in C89 */
    sprintf(buf,"_NET_SYSTEM_TRAY_S%d",Tk_ScreenNumber(tkwin));
    return Tk_InternAtom(tkwin,buf);
}

/*
 *----------------------------------------------------------------------
 *
 * XembedSetState --
 *
 * 	Set the xembed state.
 *
 * Results:
 *	Updates the xembed state.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
XembedSetState(
    DockIcon *icon,
    long xembedState)
{
    long info[] = { 0, 0 };
    info[1] = xembedState;
    if (icon->drawingWin) {
	XChangeProperty(Tk_Display(icon->drawingWin),
			icon->wrapper,
			icon->a_XEMBED_INFO,
			icon->a_XEMBED_INFO, 32,
			PropModeReplace, (unsigned char*)info, 2);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * XembedRequestDock --
 *
 * 	Obtain the docking window.
 *
 * Results:
 *	The dock window is requested.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
XembedRequestDock(
    DockIcon *icon)
{
    Tk_Window tkwin = icon->drawingWin;
    XEvent ev;
    Display *dpy = Tk_Display(tkwin);

    memset(&ev, 0, sizeof(ev));
    ev.xclient.type = ClientMessage;
    ev.xclient.window = icon->myManager;
    ev.xclient.message_type = icon->a_NET_SYSTEM_TRAY_OPCODE;
    ev.xclient.format = 32;
    ev.xclient.data.l[0] = 0;
    ev.xclient.data.l[1] = SYSTEM_TRAY_REQUEST_DOCK;
    ev.xclient.data.l[2] = icon->wrapper;
    ev.xclient.data.l[3] = 0;
    ev.xclient.data.l[4] = 0;
    XSendEvent(dpy, icon->myManager, True, StructureNotifyMask|SubstructureNotifyMask, &ev);
 }

/*
 *----------------------------------------------------------------------
 *
 * CheckArgbVisual --
 *
 * 	Find out if a visual is recommended and if it looks like argb32.
 *
 * Results:
 *	Render the visual as needed.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
CheckArgbVisual(
    DockIcon *icon)
{
    /* Find out if a visual is recommended and if it looks like argb32.
     * For such visuals we should:
     * Recreate a window if it's created but the depth is wrong;
     * Don't use ParentRelative but blank background.
     * For photo images, draw into a window by XPutImage.
     */
    Atom retType = None;
    int retFormat = 32;
    unsigned long retNitems, retBytesAfter;
    unsigned char *retProp = NULL;
    Visual *match = NULL;
    int depth = 0;
    Colormap cmap = None;

    TKU_NO_BAD_WINDOW_BEGIN(Tk_Display(icon->tkwin))
        XGetWindowProperty(Tk_Display(icon->tkwin),
                icon->trayManager,
                icon->a_NET_SYSTEM_TRAY_VISUAL,
                /* offset */ 0,
                /* length */ 1,
                /* delete */ False,
                /* type */ XA_VISUALID,
                &retType, &retFormat, &retNitems,
                &retBytesAfter, &retProp);
    TKU_NO_BAD_WINDOW_END
    if (retType == XA_VISUALID &&
	    retNitems == 1 &&
	    retFormat == 32) {
	char numeric[256];
	sprintf(numeric,"%ld",*(long*)retProp);
	XFree(retProp);
	match = Tk_GetVisual(icon->interp, icon->tkwin,
                numeric, &depth, &cmap);
    }
    if (match&& depth == 32 &&
	    match->red_mask == 0xFF0000UL &&
	    match->green_mask == 0x00FF00UL &&
	    match->blue_mask == 0x0000FFUL) {
	icon->bestVisual = match;
	icon->bestColormap = cmap;
    } else {
	icon->bestVisual = NULL;
	icon->bestColormap = None;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * CreateTrayIconWindow --
 *
 * 	Create and configure the window for the icon tray.
 *
 * Results:
 *	The window is created and displayed.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
CreateTrayIconWindow(
    DockIcon *icon)
{
    Tcl_SavedResult oldResult;
    Tk_Window tkwin;
    Tk_Window wrapper;
    XSetWindowAttributes attr;

    Tcl_SaveResult(icon->interp, &oldResult);
    /* Use the same name (tail) as the widget name, to enable
     * name-based icon management for supporting trays, as promised by
     * the docs.
     */
    tkwin = icon->drawingWin = Tk_CreateWindow(icon->interp, icon->tkwin,
            Tk_Name(icon->tkwin), "");
    if (tkwin) {
	Tk_SetClass(icon->drawingWin,icon->classString);
	Tk_CreateEventHandler(icon->drawingWin,ExposureMask|StructureNotifyMask|
                ButtonPressMask|ButtonReleaseMask|
                EnterWindowMask|LeaveWindowMask|PointerMotionMask,
                TrayIconEvent,(ClientData)icon);
	if(icon->bestVisual) {
	    Tk_SetWindowVisual(icon->drawingWin,icon->bestVisual,
                    32,icon->bestColormap);
	    icon->flags |= ICON_FLAG_ARGB32;
	    Tk_SetWindowBackground(tkwin, 0);
	} else {
	    Tk_SetWindowBackgroundPixmap(tkwin, ParentRelative);
	    icon->flags &= ~ICON_FLAG_ARGB32;
	}
	Tk_MakeWindowExist(tkwin);
	TKU_WmWithdraw(tkwin,icon->interp);
	wrapper = TKU_Wrapper(tkwin,icon->interp);

	attr.override_redirect = True;
	Tk_ChangeWindowAttributes(wrapper,CWOverrideRedirect,&attr);
	Tk_CreateEventHandler(wrapper,StructureNotifyMask,TrayIconWrapperEvent,(ClientData)icon);
	if (!icon->bestVisual) {
	    Tk_SetWindowBackgroundPixmap(wrapper, ParentRelative);
	} else {
	    Tk_SetWindowBackground(tkwin, 0);
	}
	icon->wrapper = TKU_XID(wrapper);
	TrayIconForceImageChange(icon);
    } else {
	Tcl_BackgroundError(icon->interp);
    }
    Tcl_RestoreResult(icon->interp, &oldResult);
}

/*
 *----------------------------------------------------------------------
 *
 * DockToManager --
 *
 * 	Helper function to manage icon in display.
 *
 * Results:
 *	Icon is created and displayed.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
DockToManager(
    DockIcon *icon)
{
    icon->myManager = icon->trayManager;
    Tk_SendVirtualEvent(icon->tkwin,Tk_GetUid("IconCreate"), NULL);
    XembedSetState(icon, icon->visible ? XEMBED_MAPPED : 0);
    XembedRequestDock(icon);
}

static const
Tk_OptionSpec IconOptionSpec[] = {
    {TK_OPTION_STRING,"-image","image","Image",
        (char *) NULL, -1, offsetof(DockIcon, imageString),
        TK_OPTION_NULL_OK, NULL,
        ICON_CONF_IMAGE | ICON_CONF_REDISPLAY},
    {TK_OPTION_STRING,"-class","class","Class",
        "TrayIcon", -1, offsetof(DockIcon, classString),
        0, NULL, ICON_CONF_CLASS},
    {TK_OPTION_BOOLEAN,"-docked","docked","Docked",
        "1", -1, offsetof(DockIcon, docked), 0, NULL,
        ICON_CONF_XEMBED | ICON_CONF_REDISPLAY},
    {TK_OPTION_BOOLEAN,"-shape","shape","Shape",
        "0", -1, offsetof(DockIcon, useShapeExt), 0, NULL,
        ICON_CONF_IMAGE | ICON_CONF_REDISPLAY},
    {TK_OPTION_BOOLEAN,"-visible","visible","Visible",
        "1", -1, offsetof(DockIcon, visible), 0, NULL,
        ICON_CONF_XEMBED | ICON_CONF_REDISPLAY},
    {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0}
};

/*
 *----------------------------------------------------------------------
 *
 * TrayIconRequestSize --
 *
 * 	Set icon size.
 *
 * Results:
 *	Icon size is obtained/set.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
TrayIconRequestSize(
    DockIcon* icon,
    int w,
    int h)
{
    if (icon->drawingWin) {
	if (icon->requestedWidth != w ||
	        icon->requestedHeight != h) {
	    Tk_SetMinimumRequestSize(icon->drawingWin,w,h);
	    Tk_GeometryRequest(icon->drawingWin,w,h);
	    Tk_SetGrid(icon->drawingWin,1,1,w,h);
	    icon->requestedWidth = w;
	    icon->requestedHeight = h;
	}
    } else {
	/* Sign that no size is requested yet */
	icon->requestedWidth = 0;
	icon->requestedHeight = 0;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TrayIconImageChanged --
 *
 * 	Fires when icon state changes.
 *
 * Results:
 *	Icon changes are rendered.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
TrayIconImageChanged(
    ClientData cd,
    int x,
    int y,
    int w,
    int h,
    int imgw,
    int imgh)
{
    DockIcon *icon = (DockIcon*) cd;
    if (imgw != icon->imageWidth || imgh != icon->imageHeight) {
	if (icon->offscreenImage) {
	    XDestroyImage(icon->offscreenImage);
	    icon->offscreenImage = NULL;
	}
	if (icon->offscreenPixmap) {
	    /* its size is bad */
	    Tk_FreePixmap(Tk_Display(icon->tkwin), icon->offscreenPixmap);
	    icon->offscreenPixmap = None;
	}
	/* if some image dimension decreases,
	 * empty areas around the image should be cleared */
	if (imgw < icon->imageWidth || imgh < icon->imageHeight) {
	    icon->flags |= ICON_FLAG_DIRTY_EDGES;
	}
    }
    icon->imageWidth = imgw;
    icon->imageHeight = imgh;
    if (imgw == w && imgh == h && x == 0 && y == 0) {
	icon->photo = NULL;	/* invalidate */
    }
    TrayIconRequestSize(icon,imgw,imgh);
    EventuallyRedrawIcon(icon);
}

/*
 *----------------------------------------------------------------------
 *
 * IgnoreImageChange --
 *
 * 	Currently no-op.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
IgnoreImageChange(
    TCL_UNUSED(void *),
    TCL_UNUSED(int),
    TCL_UNUSED(int),
    TCL_UNUSED(int),
    TCL_UNUSED(int),
    TCL_UNUSED(int),
    TCL_UNUSED(int))
{
}

/*
 *----------------------------------------------------------------------
 *
 * ForceImageChange --
 *
 * 	Push icon changes through.
 *
 * Results:
 *	Icon image is updated.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
TrayIconForceImageChange(
    DockIcon* icon)
{
    if (icon->image) {
	int w,h;
	Tk_SizeOfImage(icon->image,&w,&h);
	TrayIconImageChanged((ClientData)icon,0,0,w,h,w,h);
    }
}

/*
 *----------------------------------------------------------------------
 *
 *  EventuallyRedrawIcon --
 *
 * 	Update image icon.
 *
 * Results:
 *	Icon image is updated.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
EventuallyRedrawIcon(
    DockIcon* icon)
{
    if (icon->drawingWin && icon->myManager) {	/* don't redraw invisible icon */
	if (!(icon->flags & ICON_FLAG_REDRAW_PENDING)) { /* don't schedule multiple redraw ops */
	    icon->flags |= ICON_FLAG_REDRAW_PENDING;
	    Tcl_DoWhenIdle(DisplayIcon,(ClientData)icon);
	}
    }
}

/*
 *----------------------------------------------------------------------
 *
 *  DisplayIcon --
 *
 * 	Main function for displaying icon.
 *
 * Results:
 *	Icon image is displayed.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
DisplayIcon(
    ClientData cd)
{
    DockIcon *icon = (DockIcon*)cd;
    int w = icon->imageWidth, h = icon->imageHeight;
    int imgx, imgy, outx, outy, outw, outh;
    imgx = (icon->width >= w) ? 0 : -(icon->width - w)/2;
    imgy = (icon->height >= h) ? 0 : -(icon->height - h)/2;
    outx = (icon->width >= w) ? (icon->width - w)/2 : 0;
    outy = (icon->height >= h) ? (icon->height - h)/2 : 0;
    outw = (icon->width >= w) ? w : icon->width;
    outh = (icon->height >= h) ? h : icon->height;

    icon->flags &= (~ICON_FLAG_REDRAW_PENDING);

    if (icon->drawingWin && icon->docked) {
	if (icon->flags & ICON_FLAG_ARGB32) {
	    /* ARGB32 redraw: never use a ParentRelative method, and
	       no need to clear window except FIXME when its size changed.
	       Draw on the offscreen pixmap instead, then copy to the window.
	     */
	    if (icon->offscreenPixmap == None) {
		icon->offscreenPixmap = Tk_GetPixmap(Tk_Display(icon->drawingWin),
                        Tk_WindowId(icon->drawingWin), w, h, 32);
	    }
	    if (!icon->photo) {
		icon->photo = Tk_FindPhoto(icon->interp, icon->imageString);
	    }
	    if (!icon->photo && !icon->imageVisualInstance) {
		Tcl_SavedResult saved;
		Tcl_SaveResult(icon->interp,&saved);
		icon->imageVisualInstance = Tk_GetImage(icon->interp,icon->drawingWin,
                        icon->imageString, IgnoreImageChange,(ClientData)NULL);
		Tcl_RestoreResult(icon->interp,&saved);
	    }
	    if (icon->photo && !icon->offscreenImage) {
		icon->offscreenImage = XGetImage(Tk_Display(icon->drawingWin),
                        icon->offscreenPixmap, 0, 0, w, h, AllPlanes, ZPixmap);
	    }
	    if (icon->offscreenGC == None) {
		XGCValues gcv;
		gcv.function = GXcopy;
		gcv.plane_mask = AllPlanes;
		gcv.foreground = 0;
		gcv.background = 0;
		icon->offscreenGC = Tk_GetGC(icon->drawingWin,
                        GCFunction|GCPlaneMask|GCForeground|GCBackground, &gcv);
	    }
	    if (icon->flags & ICON_FLAG_DIRTY_EDGES) {
		XClearWindow(Tk_Display(icon->drawingWin), TKU_XID(icon->drawingWin));
		icon->flags &= ~ICON_FLAG_DIRTY_EDGES;
	    }
	    if (icon->photo) {
		Tk_PhotoImageBlock pib;
		int cx,cy;
		XImage *xim = icon->offscreenImage;
		/* redraw photo using raw data */
		Tk_PhotoGetImage(icon->photo,&pib);
		for (cy = 0; cy < h; ++cy) {
		    for (cx = 0; cx < w; ++cx) {
			XPutPixel(xim,cx,cy,
				  (*(pib.pixelPtr +
				     pib.pixelSize*cx +
				     pib.pitch*cy +
				     pib.offset[0])<<16) |
				  (*(pib.pixelPtr +
				     pib.pixelSize*cx +
				     pib.pitch*cy +
				     pib.offset[1])<<8) |
				  (*(pib.pixelPtr +
				     pib.pixelSize*cx +
				     pib.pitch*cy +
				     pib.offset[2])) |
				  (pib.offset[3] ?
				   (*(pib.pixelPtr +
				      pib.pixelSize*cx +
				      pib.pitch*cy +
				      pib.offset[3])<<24) : 0));
		    }
		}
		XPutImage(Tk_Display(icon->drawingWin),
			icon->offscreenPixmap,
			icon->offscreenGC,
			icon->offscreenImage,
			0,0,0,0,w,h);
	    } else {
		XFillRectangle(Tk_Display(icon->drawingWin),
			icon->offscreenPixmap,
			icon->offscreenGC,
			0,0,w,h);
		if (icon->imageVisualInstance) {
		    Tk_RedrawImage(icon->imageVisualInstance,
                            0,0,w,h,
                            icon->offscreenPixmap,
                            0,0);
		}
	    }
	    XCopyArea(Tk_Display(icon->drawingWin),
                    icon->offscreenPixmap,
                    TKU_XID(icon->drawingWin),
                    icon->offscreenGC,
                    imgx,imgy,outw,outh,outx,outy);
	} else {
	    /* Non-argb redraw: clear window and draw an image over it.
	       For photos it gives a correct alpha blending with a parent
	       window background, even if it's a fancy pixmap (proved to
	       work with lxpanel fancy backgrounds).
	    */
	    XClearWindow(Tk_Display(icon->drawingWin),
                    TKU_XID(icon->drawingWin));
	    if (icon->image && icon->visible) {
		Tk_RedrawImage(icon->image,imgx,imgy,outw,outh,
                        TKU_XID(icon->drawingWin), outx, outy);
	    }
	}
    }
}

/*
 *----------------------------------------------------------------------
 *
 *  RetargetEvent --
 *
 * 	Redirect X events to widgets.
 *
 * Results:
 *	Icon image is displayed.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
RetargetEvent(
    DockIcon *icon,
    XEvent *ev)
{
    int send = 0;
    Window* saveWin1 = NULL, *saveWin2 = NULL;
    if (!icon->visible)
	return;
    switch (ev->type) {
    case MotionNotify:
	send = 1;
	saveWin1 = &ev->xmotion.subwindow;
	saveWin2 = &ev->xmotion.window;
	break;
    case LeaveNotify:
    case EnterNotify:
	send = 1;
	saveWin1 = &ev->xcrossing.subwindow;
	saveWin2 = &ev->xcrossing.window;
	break;
    case ButtonPress:
    case ButtonRelease:
	send = 1;
	saveWin1 = &ev->xbutton.subwindow;
	saveWin2 = &ev->xbutton.window;
	break;
    case MappingNotify:
	send = 1;
	saveWin1 = &ev->xmapping.window;
    }
    if (saveWin1) {
	Tk_MakeWindowExist(icon->tkwin);
	*saveWin1 = Tk_WindowId(icon->tkwin);
	if (saveWin2) *saveWin2 = *saveWin1;
    }
    if (send) {
	ev->xany.send_event = 0x147321ac;
	Tk_HandleEvent(ev);
    }
}

/*
 *----------------------------------------------------------------------
 *
 *  TrayIconWrapperEvent --
 *
 * 	Ensure automapping in root window is done in withdrawn state.
 *
 * Results:
 *	Icon image is displayed.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
TrayIconWrapperEvent(
    ClientData cd,
    XEvent* ev)
{
  /* Some embedders, like Docker, add icon windows to save set
   * (XAddToSaveSet), so when they crash the icon is reparented to root.
   * We have to make sure that automatic mapping in root is done in
   * withdrawn state (no way to prevent it entirely)
   */
    DockIcon *icon = (DockIcon*)cd;
    XWindowAttributes attr;
    if (icon->drawingWin) {
	switch(ev->type) {
	case ReparentNotify:
	    /* With virtual roots and screen roots etc, the only way
	       to check for reparent-to-root is to ask for this root
	       first */
	    XGetWindowAttributes(ev->xreparent.display,
                    ev->xreparent.window, &attr);
	    if (attr.root == ev->xreparent.parent) {
		/* upon reparent to root, */
		if (icon->drawingWin) {
		    /* we were sent away to root */
		    TKU_WmWithdraw(icon->drawingWin,icon->interp);
		    if (icon->myManager)
			Tk_SendVirtualEvent(icon->tkwin,Tk_GetUid("IconDestroy"), NULL);
		    icon->myManager = None;
		}
	    } /* Reparenting into some other embedder is theoretically possible,
	       * and everything would just work in this case.
               */
	    break;
	}
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TrayIconEvent --
 *
 * 	Handle X events.
 *
 * Results:
 *	Events are handled and processed.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
TrayIconEvent(
    ClientData cd,
    XEvent* ev)
{
    DockIcon *icon = (DockIcon*)cd;

    switch (ev->type) {
    case Expose:
	if (!ev->xexpose.count)
	    EventuallyRedrawIcon(icon);
	break;

    case DestroyNotify:
	/* If anonymous window is destroyed first, then either
	 * something went wrong with a tray (if -visible) or we just
	 * reconfigured to invisibility: nothing to be done in both
	 * cases.
	 * If unreal window is destroyed first, freeing the data structures
	 * is the only thing to do.
	 */
	if (icon->myManager) {
	    Tk_SendVirtualEvent(icon->tkwin,Tk_GetUid("IconDestroy"), NULL);
	}
	Tcl_CancelIdleCall(DisplayIcon,(ClientData)icon);
	icon->flags &= ~ICON_FLAG_REDRAW_PENDING;
	icon->drawingWin = NULL;
	icon->requestedWidth = 0; /* trigger re-request on recreation */
	icon->requestedHeight = 0;
	icon->wrapper = None;
	icon->myManager = None;
	break;

    case ConfigureNotify:
	Tk_SendVirtualEvent(icon->tkwin,Tk_GetUid("IconConfigure"), NULL);
	if (icon->width != ev->xconfigure.width ||
	        icon->height != ev->xconfigure.height) {
	    icon->width = ev->xconfigure.width;
	    icon->height = ev->xconfigure.height;
	    icon->flags |= ICON_FLAG_DIRTY_EDGES;
	    EventuallyRedrawIcon(icon);
	}
	RetargetEvent(icon,ev);
	break;

    case MotionNotify:  /* fall through */
    case ButtonPress:   /* fall through */
    case ButtonRelease: /* fall through */
    case EnterNotify:   /* fall through */
    case LeaveNotify:
	RetargetEvent(icon,ev);
	break;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * UserIconEvent --
 *
 * 	Handle user events.
 *
 * Results:
 *	Events are handled and processed.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
UserIconEvent(
    ClientData cd,
    XEvent* ev)
{
    DockIcon *icon = (DockIcon*)cd;

    switch (ev->type) {

    case DestroyNotify:
	Tk_DeleteGenericHandler(IconGenericHandler, (ClientData)icon);
	if(icon->drawingWin) {
	    icon->visible = 0;
	    Tcl_CancelIdleCall(DisplayIcon,(ClientData)icon);
	    icon->flags &= ~ICON_FLAG_REDRAW_PENDING;
	    Tk_DestroyWindow(icon->drawingWin);
	}
	if(icon->imageVisualInstance) {
	    Tk_FreeImage(icon->imageVisualInstance);
	    icon->image = NULL;
	}
	if(icon->offscreenImage) {
	    XDestroyImage(icon->offscreenImage);
	    icon->offscreenImage = NULL;
	}
	if(icon->offscreenGC) {
	    Tk_FreeGC(Tk_Display(icon->tkwin),icon->offscreenGC);
	    icon->offscreenGC = NULL;
	}
	if(icon->offscreenPixmap) {
	    Tk_FreePixmap(Tk_Display(icon->tkwin),icon->offscreenPixmap);
	}
	if(icon->image) {
	    Tk_FreeImage(icon->image);
	    icon->image = NULL;
	}
	if(icon->widgetCmd)
	    Tcl_DeleteCommandFromToken(icon->interp,icon->widgetCmd);
	Tk_FreeConfigOptions((char*)icon, icon->options, icon->tkwin);
	break;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * PostBalloon --
 *
 * 	Display tooltip/balloon window over tray icon.
 *
 * Results:
 *	Window is displayed.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
PostBalloon(
    DockIcon *icon,
    const char *utf8msg,
    long timeout)
{
    Tk_Window tkwin = icon -> tkwin;
    Display* dpy = Tk_Display(tkwin);
    int length = strlen(utf8msg);
    XEvent ev;

    if (!(icon->drawingWin) || (icon->myManager == None))
	return 0;

    /* overflow protection */
    if (icon->msgid < 0)
	icon->msgid = 0;

    memset(&ev, 0, sizeof(ev));
    ev.xclient.type = ClientMessage;
    ev.xclient.window = icon->wrapper;
    ev.xclient.message_type = icon->a_NET_SYSTEM_TRAY_OPCODE;
    ev.xclient.format = 32;
    ev.xclient.data.l[0] = CurrentTime;
    ev.xclient.data.l[1] = SYSTEM_TRAY_BEGIN_MESSAGE;
    ev.xclient.data.l[2] = timeout;
    ev.xclient.data.l[3] = length;
    ev.xclient.data.l[4] = ++icon->msgid;
    TKU_NO_BAD_WINDOW_BEGIN(Tk_Display(icon->tkwin))
	XSendEvent(dpy, icon->myManager , True, StructureNotifyMask|SubstructureNotifyMask, &ev);
        XSync(dpy, False);

        /* Sending message elements */
        while (length>0) {
	    ev.type = ClientMessage;
	    ev.xclient.window = icon->wrapper;
	    ev.xclient.message_type = icon->a_NET_SYSTEM_TRAY_MESSAGE_DATA;
	    ev.xclient.format = 8;
	    memset(ev.xclient.data.b,0,20);
	    strncpy(ev.xclient.data.b,utf8msg,length<20?length:20);
	    XSendEvent(dpy, icon->myManager, True, StructureNotifyMask|SubstructureNotifyMask, &ev);
	    XSync(dpy,False);
	    utf8msg += 20;
	    length -= 20;
        }
    TKU_NO_BAD_WINDOW_END;
    return icon->msgid;
}

/*
 *----------------------------------------------------------------------
 *
 * CancelBalloon --
 *
 * 	Remove balloon from display over tray icon.
 *
 * Results:
 *	Window is destroyed.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
CancelBalloon(
    DockIcon *icon,
    int msgid)
{
    Tk_Window tkwin = icon -> tkwin;
    Display* dpy = Tk_Display(tkwin);
    XEvent ev;

    if (!(icon->drawingWin) || (icon->myManager == None))
	return;
    /* overflow protection */
    if (icon->msgid < 0)
	icon->msgid = 0;

    memset(&ev, 0, sizeof(ev));
    ev.type = ClientMessage;
    ev.xclient.window = icon->wrapper;
    ev.xclient.message_type = icon->a_NET_SYSTEM_TRAY_OPCODE;
    ev.xclient.format = 32;
    ev.xclient.data.l[0] = CurrentTime;
    ev.xclient.data.l[1] = SYSTEM_TRAY_CANCEL_MESSAGE;
    ev.xclient.data.l[2]  =msgid;
    TKU_NO_BAD_WINDOW_BEGIN(Tk_Display(icon->tkwin))
	XSendEvent(dpy, icon->myManager , True,
                StructureNotifyMask|SubstructureNotifyMask, &ev);
    TKU_NO_BAD_WINDOW_END
}

/*
 *----------------------------------------------------------------------
 *
 * IconGenericHandler --
 *
 * 	Process non-tk events.
 *
 * Results:
 *	Events are processed.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
IconGenericHandler(
    ClientData cd,
    XEvent *ev)
{
    DockIcon *icon = (DockIcon*)cd;

    if ((ev->type == ClientMessage) &&
	    (ev->xclient.message_type == icon->aMANAGER) &&
	    ((Atom)ev->xclient.data.l[1] == icon->a_NET_SYSTEM_TRAY_Sn)) {
	icon->trayManager = (Window)ev->xclient.data.l[2];
	XSelectInput(ev->xclient.display,icon->trayManager,StructureNotifyMask);
	if (icon->myManager == None)
	    TrayIconUpdate(icon, ICON_CONF_XEMBED);
	return 1;
    }
    if (ev->type == DestroyNotify) {
	if (ev->xdestroywindow.window == icon->trayManager) {
	    icon->trayManager = None;
	}
	if (ev->xdestroywindow.window == icon->myManager) {
	    icon->myManager = None;
	    icon->wrapper = None;
	    if (icon->drawingWin) {
		Tk_DestroyWindow(icon->drawingWin);
		icon->drawingWin = NULL;
	    }
	}
    }
    return 0;
}

/*
 *----------------------------------------------------------------------
 *
 * TrayIconUpdate --
 *
 * 	Get in touch with new options that are certainly valid.
 *
 * Results:
 *	Options updated.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
TrayIconUpdate(
    DockIcon *icon,
    int mask)
{
    /* why should someone need this option?
     * anyway, let's handle it if we provide it.
     */
    if (mask & ICON_CONF_CLASS) {
	if (icon->drawingWin)
	    Tk_SetClass(icon->drawingWin,Tk_GetUid(icon->classString));
    }
    /*
     * First, ensure right icon visibility.
     * If should be visible and not yet managed,
     * we have to get the tray or wait for it.
     * If should be invisible and managed,
     * real-window is simply destroyed.
     * If should be invisible and not managed,
     * generic handler should be abandoned.
     */
    if (mask & ICON_CONF_XEMBED) {
	if (icon->myManager == None &&
	        icon->trayManager != None &&
	        icon->docked) {
	    CheckArgbVisual(icon);
	    if (icon->drawingWin &&
		    ((icon->bestVisual && !(icon->flags & ICON_FLAG_ARGB32)) ||
		     (!icon->bestVisual && (icon->flags & ICON_FLAG_ARGB32)))) {
		icon->myManager = None;
		icon->wrapper = None;
		icon->requestedWidth = icon->requestedHeight = 0;
		Tk_DestroyWindow(icon->drawingWin);
		icon->drawingWin = NULL;
	    }
	    if (!icon->drawingWin) {
		CreateTrayIconWindow(icon);
	    }
	    if (icon->drawingWin) {
		DockToManager(icon);
	    }
	}
	if (icon->myManager != None &&
	        icon->drawingWin != NULL &&
	        !icon->docked) {
	    Tk_DestroyWindow(icon->drawingWin);
	    icon->drawingWin = NULL;
	    icon->myManager = None;
	    icon->wrapper = None;
	}
	if (icon->drawingWin) {
	    XembedSetState(icon, icon->visible ? XEMBED_MAPPED : 0);
	}
    }
    if (mask & ICON_CONF_IMAGE) {
	TrayIconForceImageChange(icon);
    }
    if (mask & ICON_CONF_REDISPLAY) {
	EventuallyRedrawIcon(icon);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TrayIconConfigureMethod --
 *
 *      Returns TCL_ERROR if some option is invalid,
 *      or else retrieve resource references and free old resources.
 *
 * Results:
 *	Widget configured.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TrayIconConfigureMethod(
    DockIcon *icon,
    Tcl_Interp* interp,
    int objc,
    Tcl_Obj *const objv[],
    int addflags)
{
    Tk_SavedOptions saved;
    Tk_Image newImage = NULL;
    int mask = 0;

    if (objc <= 1 && !(addflags & ICON_CONF_FIRST_TIME)) {
	Tcl_Obj* info = Tk_GetOptionInfo(interp, (char*)icon, icon->options,
                objc? objv[0] : NULL, icon->tkwin);
	if (info) {
	    Tcl_SetObjResult(interp,info);
	    return TCL_OK;
	} else {
	    return TCL_ERROR; /* msg by Tk_GetOptionInfo */
	}
    }

    if (Tk_SetOptions(interp,(char*)icon,icon->options,objc,objv,
            icon->tkwin,&saved,&mask) != TCL_OK) {
	return TCL_ERROR; /* msg by Tk_SetOptions */
    }
    mask |= addflags;
    /* now check option validity */
    if (mask & ICON_CONF_IMAGE) {
	if (icon->imageString) {
	    newImage = Tk_GetImage(interp, icon->tkwin, icon->imageString,
                    TrayIconImageChanged, (ClientData)icon);
	    if (!newImage) {
		Tk_RestoreSavedOptions(&saved);
		return TCL_ERROR; /* msg by Tk_GetImage */
	    }
	}
	if (icon->image) {
	    Tk_FreeImage(icon->image);
	    icon->image = NULL;
	}
	if (icon->imageVisualInstance) {
	    Tk_FreeImage(icon->imageVisualInstance);
	    icon->imageVisualInstance = NULL;
	}
	icon->image = newImage; /* may be null, as intended */
	icon->photo = NULL; /* invalidate photo reference */
    }
    Tk_FreeSavedOptions(&saved);
    /* Now as we are reconfigured... */
    TrayIconUpdate(icon,mask);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TrayIconDeleteProc --
 *
 *      Delete tray window and clean up.
 *
 * Results:
 *	Window destroyed.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
TrayIconDeleteProc(
    ClientData cd )
{
    DockIcon *icon = (DockIcon *)cd;
    Tk_DestroyWindow(icon->tkwin);
}

/*
 *----------------------------------------------------------------------
 *
 * TrayIconCreateCmd --
 *
 *      Create tray command and (unreal) window.
 *
 * Results:
 *	Icon tray and hidden window created.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TrayIconCreateCmd(
    ClientData cd,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tk_Window mainWindow = (Tk_Window)cd;
    DockIcon *icon;

    icon = (DockIcon*)attemptckalloc(sizeof(DockIcon));
    if (!icon) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("running out of memory", -1));
	goto handleErrors;
    }
    memset(icon,0,sizeof(*icon));

    if (objc < 2||(objc%2)) {
	Tcl_WrongNumArgs(interp, 1, objv, "pathName ?option value ...?");
	goto handleErrors;
    }

    /* It's not a toplevel window by now. It really doesn't matter,
     * because it's not really shown.
     */
    icon->tkwin = Tk_CreateWindowFromPath(interp, mainWindow,
            Tcl_GetString(objv[1]),"");
    if (icon->tkwin == NULL) {
	goto handleErrors;
    }

    /* Subscribe to StructureNotify */
    TKU_AddInput(Tk_Display(icon->tkwin),
            RootWindowOfScreen(Tk_Screen(icon->tkwin)),StructureNotifyMask);
    TKU_AddInput(Tk_Display(icon->tkwin),
            RootWindow(Tk_Display(icon->tkwin),0),StructureNotifyMask);
    /* Spec says "screen 0" not "default", but... */
    TKU_AddInput(Tk_Display(icon->tkwin),
            DefaultRootWindow(Tk_Display(icon->tkwin)),StructureNotifyMask);

    /* Early tracking of DestroyNotify is essential */
    Tk_CreateEventHandler(icon->tkwin,StructureNotifyMask,
            UserIconEvent,(ClientData)icon);

    /* Now try setting options */
    icon->options = Tk_CreateOptionTable(interp,IconOptionSpec);
    /* Class name is used for retrieving defaults, so... */
    Tk_SetClass(icon->tkwin, Tk_GetUid("TrayIcon"));
    if (Tk_InitOptions(interp,(char*)icon,icon->options,icon->tkwin) != TCL_OK) {
	goto handleErrors;
    }

    icon->a_NET_SYSTEM_TRAY_Sn = DockSelectionAtomFor(icon->tkwin);
    icon->a_NET_SYSTEM_TRAY_OPCODE = Tk_InternAtom(icon->tkwin,"_NET_SYSTEM_TRAY_OPCODE");
    icon->a_NET_SYSTEM_TRAY_MESSAGE_DATA = Tk_InternAtom(icon->tkwin,"_NET_SYSTEM_TRAY_MESSAGE_DATA");
    icon->a_NET_SYSTEM_TRAY_ORIENTATION = Tk_InternAtom(icon->tkwin,"_NET_SYSTEM_TRAY_ORIENTATION");
    icon->a_NET_SYSTEM_TRAY_VISUAL = Tk_InternAtom(icon->tkwin,"_NET_SYSTEM_TRAY_VISUAL");
    icon->a_XEMBED_INFO = Tk_InternAtom(icon->tkwin,"_XEMBED_INFO");
    icon->aMANAGER = Tk_InternAtom(icon->tkwin,"MANAGER");

    icon->interp = interp;

    icon->trayManager = XGetSelectionOwner(Tk_Display(icon->tkwin), icon->a_NET_SYSTEM_TRAY_Sn);
    if (icon->trayManager) {
	XSelectInput(Tk_Display(icon->tkwin),icon->trayManager, StructureNotifyMask);
    }

    Tk_CreateGenericHandler(IconGenericHandler, (ClientData)icon);

    if (objc>3) {
	if (TrayIconConfigureMethod(icon, interp, objc-2, objv+2,
                ICON_CONF_XEMBED|ICON_CONF_IMAGE|ICON_CONF_FIRST_TIME) != TCL_OK) {
	    goto handleErrors;
	}
    }

    icon->widgetCmd = Tcl_CreateObjCommand(interp, Tcl_GetString(objv[1]),
            TrayIconObjectCmd, (ClientData)icon, TrayIconDeleteProc);

    /* Sometimes a command just can't be created... */
    if (!icon->widgetCmd) {
	goto handleErrors;
    }

    Tcl_SetObjResult(interp,objv[1]);
    return TCL_OK;

handleErrors:
    /* Rolling back */
    if (icon) {
	if (icon->options) {
	    Tk_DeleteOptionTable(icon->options);
	    icon->options = NULL;
	}
	if (icon->tkwin) {
	    /* Resources will be freed by DestroyNotify handler */
	    Tk_DestroyWindow(icon->tkwin);
	}
	ckfree((char*)icon);
    }
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * Tktray_Init --
 *
 *      Initialize the command.
 *
 * Results:
 *	Command initialized.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Tktray_Init(
    Tcl_Interp *interp)
{
    Tcl_CreateObjCommand(interp, "::tk::systray::_systray",
            TrayIconCreateCmd, Tk_MainWindow(interp), NULL);
    return TCL_OK;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 79
 * coding: utf-8
 * End:
 */
Changes to unix/tkUnixWm.c.
1
2
3
4
5
6
7
8
9
10


11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31


32
33
34
35
36
37
38
39

40
41
42
43
44
45
46
1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29


30
31
32
33
34
35
36
37
38

39
40
41
42
43
44
45
46








-
-
+
+



















-
-
+
+







-
+







/*
 * tkUnixWm.c --
 *
 *	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) 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.
 */

#include "tkUnixInt.h"

/*
 * A data structure of the following type holds information for each window
 * manager protocol (such as WM_DELETE_WINDOW) for which a handler (i.e. a Tcl
 * command) has been defined for a particular top-level window.
 */

typedef struct ProtocolHandler {
    Atom protocol;		/* Identifies the protocol. */
    struct ProtocolHandler *nextPtr;
				/* Next in list of protocol handlers for the
				 * same top-level window, or NULL for end of
				 * list. */
    Tcl_Interp *interp;		/* Interpreter in which to invoke command. */
    char command[1];		/* Tcl command to invoke when a client message
    Tcl_Interp *interp;	/* Interpreter in which to invoke command. */
    char command[TKFLEXARRAY];	/* Tcl command to invoke when a client message
				 * for this protocol arrives. The actual size
				 * of the structure varies to accommodate the
				 * needs of the actual command. THIS MUST BE
				 * THE LAST FIELD OF THE STRUCTURE. */
} ProtocolHandler;

#define HANDLER_SIZE(cmdLength) \
    ((unsigned) ((Tk_Offset(ProtocolHandler, command) + 1) + cmdLength))
    (offsetof(ProtocolHandler, command) + 1 + cmdLength)

/*
 * Data for [wm attributes] command:
 */

typedef struct {
    double alpha;		/* Transparency; 0.0=transparent, 1.0=opaque */
78
79
80
81
82
83
84
85

86
87
88
89
90
91
92
78
79
80
81
82
83
84

85
86
87
88
89
90
91
92







-
+







    char *iconName;		/* Name to display in icon. Malloced. */
    XWMHints hints;		/* Various pieces of information for window
				 * manager. */
    char *leaderName;		/* Path name of leader of window group
				 * (corresponds to hints.window_group).
				 * Malloc-ed. Note: this field doesn't get
				 * updated if leader is destroyed. */
    TkWindow *masterPtr;	/* Master window for TRANSIENT_FOR property,
    TkWindow *containerPtr;	/* Container window for TRANSIENT_FOR property,
				 * or NULL. */
    Tk_Window icon;		/* Window to use as icon for this window, or
				 * NULL. */
    Tk_Window iconFor;		/* Window for which this window is icon, or
				 * NULL if this isn't an icon for anyone. */
    int withdrawn;		/* Non-zero means window has been withdrawn. */

255
256
257
258
259
260
261
262

263
264
265
266
267
268
269
255
256
257
258
259
260
261

262
263
264
265
266
267
268
269







-
+







 *				allow the user to change the width of the
 *				window (controlled by "wm resizable" command).
 * WM_HEIGHT_NOT_RESIZABLE -	non-zero means that we're not supposed to
 *				allow the user to change the height of the
 *				window (controlled by "wm resizable" command).
 * WM_WITHDRAWN -		non-zero means that this window has explicitly
 *				been withdrawn. If it's a transient, it should
 *				not mirror state changes in the master.
 *				not mirror state changes in the container.
 */

#define WM_NEVER_MAPPED			1
#define WM_UPDATE_PENDING		2
#define WM_NEGATIVE_X			4
#define WM_NEGATIVE_Y			8
#define WM_UPDATE_SIZE_HINTS		0x10
308
309
310
311
312
313
314
315

316
317
318
319
320

321
322
323
324
325
326
327
308
309
310
311
312
313
314

315
316
317
318
319

320
321
322
323
324
325
326
327







-
+




-
+







static void		RemapWindows(TkWindow *winPtr, TkWindow *parentPtr);
static void		MenubarReqProc(ClientData clientData,
			    Tk_Window tkwin);

static const Tk_GeomMgr wmMgrType = {
    "wm",			/* name */
    TopLevelReqProc,		/* requestProc */
    NULL,			/* lostSlaveProc */
    NULL,			/* lostContentProc */
};
static const Tk_GeomMgr menubarMgrType = {
    "menubar",			/* name */
    MenubarReqProc,		/* requestProc */
    NULL,			/* lostSlaveProc */
    NULL,			/* lostContentProc */
};

/*
 * Structures of the following type are used for communication between
 * WaitForEvent, WaitRestrictProc, and WaitTimeoutProc.
 */

560
561
562
563
564
565
566
567

568
569
570

571
572
573
574

575
576
577
578
579
580
581
560
561
562
563
564
565
566

567
568
569

570
571
572
573

574
575
576
577
578
579
580
581







-
+


-
+



-
+







 *--------------------------------------------------------------
 */

void
TkWmNewWindow(
    TkWindow *winPtr)		/* Newly-created top-level window. */
{
    register WmInfo *wmPtr;
    WmInfo *wmPtr;
    TkDisplay *dispPtr = winPtr->dispPtr;

    wmPtr = ckalloc(sizeof(WmInfo));
    wmPtr = (WmInfo *)ckalloc(sizeof(WmInfo));
    memset(wmPtr, 0, sizeof(WmInfo));
    wmPtr->winPtr = winPtr;
    wmPtr->reparent = None;
    wmPtr->masterPtr = NULL;
    wmPtr->containerPtr = NULL;
    wmPtr->numTransients = 0;
    wmPtr->hints.flags = InputHint | StateHint;
    wmPtr->hints.input = True;
    wmPtr->hints.initial_state = NormalState;
    wmPtr->hints.icon_pixmap = None;
    wmPtr->hints.icon_window = None;
    wmPtr->hints.icon_x = wmPtr->hints.icon_y = 0;
655
656
657
658
659
660
661
662

663
664
665
666
667
668
669
655
656
657
658
659
660
661

662
663
664
665
666
667
668
669







-
+







 */

void
TkWmMapWindow(
    TkWindow *winPtr)		/* Top-level window that's about to be
				 * mapped. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    XTextProperty textProp;

    if (wmPtr->flags & WM_NEVER_MAPPED) {
	Tcl_DString ds;

	wmPtr->flags &= ~WM_NEVER_MAPPED;

680
681
682
683
684
685
686
687

688
689

690
691
692

693
694
695
696
697
698
699
700
701
702
703

704
705
706
707
708
709
710
680
681
682
683
684
685
686

687
688

689
690
691

692
693
694
695
696
697
698
699
700
701
702

703
704
705
706
707
708
709
710







-
+

-
+


-
+










-
+







	 * Store all the window-manager-related information for the window.
	 */

	TkWmSetClass(winPtr);
	UpdateTitle(winPtr);
	UpdatePhotoIcon(winPtr);

	if (wmPtr->masterPtr != NULL) {
	if (wmPtr->containerPtr != NULL) {
	    /*
	     * Don't map a transient if the master is not mapped.
	     * Don't map a transient if the container is not mapped.
	     */

	    if (!Tk_IsMapped(wmPtr->masterPtr)) {
	    if (!Tk_IsMapped(wmPtr->containerPtr)) {
		wmPtr->withdrawn = 1;
		wmPtr->hints.initial_state = WithdrawnState;
	    }

	    /*
	     * Make sure that we actually set the transient-for property, even
	     * if we are withdrawn. [Bug 1163496]
	     */

	    XSetTransientForHint(winPtr->display, wmPtr->wrapperPtr->window,
		    wmPtr->masterPtr->wmInfoPtr->wrapperPtr->window);
		    wmPtr->containerPtr->wmInfoPtr->wrapperPtr->window);
	}

	wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
	UpdateHints(winPtr);
	UpdateWmProtocols(wmPtr);
	if (wmPtr->cmdArgv != NULL) {
	    UpdateCommand(winPtr);
823
824
825
826
827
828
829
830

831
832
833
834
835
836
837
838
839

840
841
842
843
844
845
846
823
824
825
826
827
828
829

830
831
832
833
834
835
836
837
838

839
840
841
842
843
844
845
846







-
+








-
+







 *--------------------------------------------------------------
 */

void
TkWmDeadWindow(
    TkWindow *winPtr)		/* Top-level window that's being deleted. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr2;

    if (wmPtr == NULL) {
	return;
    }
    if ((WmInfo *) winPtr->dispPtr->firstWmPtr == wmPtr) {
	winPtr->dispPtr->firstWmPtr = wmPtr->nextPtr;
    } else {
	register WmInfo *prevPtr;
	WmInfo *prevPtr;

	for (prevPtr = (WmInfo *) winPtr->dispPtr->firstWmPtr; ;
		prevPtr = prevPtr->nextPtr) {
	    /* ASSERT: prevPtr != NULL [Bug 1789819] */
	    if (prevPtr->nextPtr == wmPtr) {
		prevPtr->nextPtr = wmPtr->nextPtr;
		break;
905
906
907
908
909
910
911
912

913
914
915
916
917

918
919

920
921

922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937


938
939
940

941
942
943
944
945
946

947
948

949
950
951
952
953
954
955
905
906
907
908
909
910
911

912
913
914
915
916

917
918

919
920

921
922
923
924
925
926
927
928
929
930
931
932
933
934
935


936
937
938
939

940
941
942
943
944
945

946
947

948
949
950
951
952
953
954
955







-
+




-
+

-
+

-
+














-
-
+
+


-
+





-
+

-
+







	ckfree(wmPtr->clientMachine);
    }
    if (wmPtr->flags & WM_UPDATE_PENDING) {
	Tcl_CancelIdleCall(UpdateGeometryInfo, winPtr);
    }

    /*
     * Reset all transient windows whose master is the dead window.
     * Reset all transient windows whose container is the dead window.
     */

    for (wmPtr2 = winPtr->dispPtr->firstWmPtr; wmPtr2 != NULL;
	    wmPtr2 = wmPtr2->nextPtr) {
	if (wmPtr2->masterPtr == winPtr) {
	if (wmPtr2->containerPtr == winPtr) {
	    wmPtr->numTransients--;
	    Tk_DeleteEventHandler((Tk_Window) wmPtr2->masterPtr,
	    Tk_DeleteEventHandler((Tk_Window) wmPtr2->containerPtr,
		    StructureNotifyMask, WmWaitMapProc, wmPtr2->winPtr);
	    wmPtr2->masterPtr = NULL;
	    wmPtr2->containerPtr = NULL;
	    if (!(wmPtr2->flags & WM_NEVER_MAPPED)) {
		XDeleteProperty(winPtr->display, wmPtr2->wrapperPtr->window,
			Tk_InternAtom((Tk_Window) winPtr, "WM_TRANSIENT_FOR"));

		/*
		 * FIXME: Need a call like Win32's UpdateWrapper() so we can
		 * recreate the wrapper and get rid of the transient window
		 * decorations.
		 */
	    }
	}
    }
    /* ASSERT: numTransients == 0 [Bug 1789819] */

    if (wmPtr->masterPtr != NULL) {
	wmPtr2 = wmPtr->masterPtr->wmInfoPtr;
    if (wmPtr->containerPtr != NULL) {
	wmPtr2 = wmPtr->containerPtr->wmInfoPtr;

	/*
	 * If we had a master, tell them that we aren't tied to them anymore
	 * If we had a container, tell them that we aren't tied to them anymore
	 */

	if (wmPtr2 != NULL) {
	    wmPtr2->numTransients--;
	}
	Tk_DeleteEventHandler((Tk_Window) wmPtr->masterPtr,
	Tk_DeleteEventHandler((Tk_Window) wmPtr->containerPtr,
		StructureNotifyMask, WmWaitMapProc, winPtr);
	wmPtr->masterPtr = NULL;
	wmPtr->containerPtr = NULL;
    }
    ckfree(wmPtr);
    winPtr->wmInfoPtr = NULL;
}

/*
 *--------------------------------------------------------------
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016

1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036

1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050



1051
1052
1053
1054
1055
1056
1057
1058
1059


1060
1061
1062
1063
1064
1065
1066
1001
1002
1003
1004
1005
1006
1007

1008
1009
1010
1011
1012
1013
1014

1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034

1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046



1047
1048
1049
1050
1051
1052
1053
1054
1055
1056


1057
1058
1059
1060
1061
1062
1063
1064
1065







-







-
+



















-
+











-
-
-
+
+
+







-
-
+
+







 * Tk_WmObjCmd --
 *
 *	This function is invoked to process the "wm" Tcl command.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
int
Tk_WmObjCmd(
    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;
    static const char *const optionStrings[] = {
	"aspect", "attributes", "client", "colormapwindows",
	"command", "deiconify", "focusmodel", "forget",
	"frame", "geometry", "grid", "group", "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_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, WMOPT_WITHDRAW };
    int index, length;
    int index;
    const char *argv1;
    TkWindow *winPtr;
    Tk_Window targetWin;
    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;

    if (objc < 2) {
    wrongNumArgs:
	Tcl_WrongNumArgs(interp, 1, objv, "option window ?arg ...?");
	return TCL_ERROR;
    }

    argv1 = Tcl_GetStringFromObj(objv[1], &length);
    if ((argv1[0] == 't') && (strncmp(argv1, "tracing", (size_t) length) == 0)
	    && (length >= 3)) {
    argv1 = Tcl_GetString(objv[1]);
    if ((argv1[0] == 't') && (strncmp(argv1, "tracing", objv[1]->length) == 0)
	    && (objv[1]->length >= 3)) {
	int wmTracing;

	if ((objc != 2) && (objc != 3)) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?boolean?");
	    return TCL_ERROR;
	}
	if (objc == 2) {
	    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(
		    dispPtr->flags & TK_DISPLAY_WM_TRACING));
	    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(
		    (dispPtr->flags & TK_DISPLAY_WM_TRACING) != 0));
	    return TCL_OK;
	}
	if (Tcl_GetBooleanFromObj(interp, objv[2], &wmTracing) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (wmTracing) {
	    dispPtr->flags |= TK_DISPLAY_WM_TRACING;
1178
1179
1180
1181
1182
1183
1184
1185

1186
1187
1188
1189
1190
1191

1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206




1207
1208
1209
1210
1211
1212
1213
1177
1178
1179
1180
1181
1182
1183

1184
1185
1186
1187
1188
1189

1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201




1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212







-
+





-
+











-
-
-
-
+
+
+
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmAspectCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    int numer1, denom1, numer2, denom2;

    if ((objc != 3) && (objc != 7)) {
	Tcl_WrongNumArgs(interp, 2, objv,
		"window ?minNumer minDenom maxNumer maxDenom?");
	return TCL_ERROR;
    }
    if (objc == 3) {
	if (wmPtr->sizeHintsFlags & PAspect) {
	    Tcl_Obj *results[4];

	    results[0] = Tcl_NewIntObj(wmPtr->minAspect.x);
	    results[1] = Tcl_NewIntObj(wmPtr->minAspect.y);
	    results[2] = Tcl_NewIntObj(wmPtr->maxAspect.x);
	    results[3] = Tcl_NewIntObj(wmPtr->maxAspect.y);
	    results[0] = Tcl_NewWideIntObj(wmPtr->minAspect.x);
	    results[1] = Tcl_NewWideIntObj(wmPtr->minAspect.y);
	    results[2] = Tcl_NewWideIntObj(wmPtr->maxAspect.x);
	    results[3] = Tcl_NewWideIntObj(wmPtr->maxAspect.y);
	    Tcl_SetObjResult(interp, Tcl_NewListObj(4, results));
	}
	return TCL_OK;
    }
    if (*Tcl_GetString(objv[3]) == '\0') {
	wmPtr->sizeHintsFlags &= ~PAspect;
    } else {
1311
1312
1313
1314
1315
1316
1317
1318

1319
1320
1321
1322
1323
1324
1325
1310
1311
1312
1313
1314
1315
1316

1317
1318
1319
1320
1321
1322
1323
1324







-
+







	if (Tcl_GetBooleanFromObj(interp, value,
		&wmPtr->reqState.fullscreen) != TCL_OK) {
	    return TCL_ERROR;
	}
	SetNetWmState(winPtr, "_NET_WM_STATE_FULLSCREEN",
		wmPtr->reqState.fullscreen);
	break;
    case _WMATT_LAST_ATTRIBUTE:	/* NOTREACHED */
    case _WMATT_LAST_ATTRIBUTE:
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
1341
1342
1343
1344
1345
1346
1347
1348

1349
1350

1351
1352

1353
1354
1355

1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1340
1341
1342
1343
1344
1345
1346

1347
1348

1349
1350

1351
1352
1353

1354
1355
1356

1357
1358
1359
1360
1361
1362
1363







-
+

-
+

-
+


-
+


-







{
    WmInfo *wmPtr = winPtr->wmInfoPtr;

    switch (attribute) {
    case WMATT_ALPHA:
	return Tcl_NewDoubleObj(wmPtr->attributes.alpha);
    case WMATT_TOPMOST:
	return Tcl_NewBooleanObj(wmPtr->attributes.topmost);
	return Tcl_NewWideIntObj(wmPtr->attributes.topmost != 0);
    case WMATT_ZOOMED:
	return Tcl_NewBooleanObj(wmPtr->attributes.zoomed);
	return Tcl_NewWideIntObj(wmPtr->attributes.zoomed != 0);
    case WMATT_FULLSCREEN:
	return Tcl_NewBooleanObj(wmPtr->attributes.fullscreen);
	return Tcl_NewWideIntObj(wmPtr->attributes.fullscreen != 0);
    case WMATT_TYPE:
	return GetNetWmType(winPtr);
    case _WMATT_LAST_ATTRIBUTE:	/*NOTREACHED*/
    case _WMATT_LAST_ATTRIBUTE:
	break;
    }
    /*NOTREACHED*/
    return NULL;
}

/*
 *----------------------------------------------------------------------
 *
 * WmAttributesCmd --
1381
1382
1383
1384
1385
1386
1387
1388

1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403

1404
1405
1406
1407
1408
1409
1410
1411
1412

1413
1414
1415
1416
1417
1418
1419
1420
1421
1422

1423
1424
1425
1426
1427
1428
1429
1379
1380
1381
1382
1383
1384
1385

1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400

1401
1402
1403
1404
1405
1406
1407
1408
1409

1410
1411
1412
1413
1414
1415
1416
1417
1418
1419

1420
1421
1422
1423
1424
1425
1426
1427







-
+














-
+








-
+









-
+







 * See also: TIP#231, EWMH.
 *
 *----------------------------------------------------------------------
 */

static int
WmAttributesCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    int attribute = 0;

    if (objc == 3) {		/* wm attributes $win */
	Tcl_Obj *result = Tcl_NewListObj(0,0);

	for (attribute = 0; attribute < _WMATT_LAST_ATTRIBUTE; ++attribute) {
	    Tcl_ListObjAppendElement(interp, result,
		    Tcl_NewStringObj(WmAttributeNames[attribute], -1));
	    Tcl_ListObjAppendElement(interp, result,
		    WmGetAttribute(winPtr, attribute));
		    WmGetAttribute(winPtr, (WmAttribute)attribute));
	}
	Tcl_SetObjResult(interp, result);
	return TCL_OK;
    } 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, attribute));
	Tcl_SetObjResult(interp, WmGetAttribute(winPtr, (WmAttribute)attribute));
	return TCL_OK;
    } 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,interp,attribute,objv[i+1]) != TCL_OK) {
	    if (WmSetAttribute(winPtr,interp,(WmAttribute)attribute,objv[i+1]) != TCL_OK) {
		return TCL_ERROR;
	    }
	}
	return TCL_OK;
    }

    Tcl_WrongNumArgs(interp, 2, objv, "window ?-attribute ?value ...??");
1445
1446
1447
1448
1449
1450
1451
1452

1453
1454
1455
1456
1457
1458

1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473

1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489

1490
1491
1492
1493
1494
1495
1496
1443
1444
1445
1446
1447
1448
1449

1450
1451
1452
1453
1454
1455

1456
1457

1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469

1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485

1486
1487
1488
1489
1490
1491
1492
1493







-
+





-
+

-












-
+















-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmClientCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    const char *argv3;
    int length;

    if ((objc != 3) && (objc != 4)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?name?");
	return TCL_ERROR;
    }
    if (objc == 3) {
	if (wmPtr->clientMachine != NULL) {
	    Tcl_SetObjResult(interp,
		    Tcl_NewStringObj(wmPtr->clientMachine, -1));
	}
	return TCL_OK;
    }
    argv3 = Tcl_GetStringFromObj(objv[3], &length);
    argv3 = Tcl_GetString(objv[3]);
    if (argv3[0] == 0) {
	if (wmPtr->clientMachine != NULL) {
	    ckfree(wmPtr->clientMachine);
	    wmPtr->clientMachine = NULL;
	    if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
		XDeleteProperty(winPtr->display, wmPtr->wrapperPtr->window,
			Tk_InternAtom((Tk_Window) winPtr,
				"WM_CLIENT_MACHINE"));
	    }
	}
	return TCL_OK;
    }
    if (wmPtr->clientMachine != NULL) {
	ckfree(wmPtr->clientMachine);
    }
    wmPtr->clientMachine = ckalloc(length + 1);
    wmPtr->clientMachine = (char *)ckalloc(objv[3]->length + 1);
    strcpy(wmPtr->clientMachine, argv3);
    if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
	XTextProperty textProp;
	Tcl_DString ds;

	Tcl_UtfToExternalDString(NULL, wmPtr->clientMachine, -1, &ds);
	if (XStringListToTextProperty(&(Tcl_DStringValue(&ds)), 1,
1537
1538
1539
1540
1541
1542
1543
1544

1545
1546
1547
1548
1549
1550
1551
1534
1535
1536
1537
1538
1539
1540

1541
1542
1543
1544
1545
1546
1547
1548







-
+







WmColormapwindowsCmd(
    Tk_Window tkwin,		/* 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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    Window *cmapList;
    TkWindow *winPtr2;
    int count, i, windowObjc, gotToplevel;
    Tcl_Obj **windowObjv, *resultObj;

    if ((objc != 3) && (objc != 4)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?windowList?");
1580
1581
1582
1583
1584
1585
1586
1587

1588
1589
1590
1591
1592
1593
1594
1577
1578
1579
1580
1581
1582
1583

1584
1585
1586
1587
1588
1589
1590
1591







-
+







	Tcl_SetObjResult(interp, resultObj);
	return TCL_OK;
    }
    if (Tcl_ListObjGetElements(interp, objv[3], &windowObjc, &windowObjv)
	    != TCL_OK) {
	return TCL_ERROR;
    }
    cmapList = ckalloc((windowObjc+1) * sizeof(Window));
    cmapList = (Window *)ckalloc((windowObjc+1) * sizeof(Window));
    gotToplevel = 0;
    for (i = 0; i < windowObjc; i++) {
	Tk_Window mapWin;

	if (TkGetWindowFromObj(interp, tkwin, windowObjv[i],
		&mapWin) != TCL_OK) {
	    ckfree(cmapList);
1632
1633
1634
1635
1636
1637
1638
1639

1640
1641
1642
1643
1644
1645

1646
1647
1648
1649
1650
1651
1652
1629
1630
1631
1632
1633
1634
1635

1636
1637
1638
1639
1640
1641

1642
1643
1644
1645
1646
1647
1648
1649







-
+





-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmCommandCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    const char *argv3;
    int cmdArgc;
    const char **cmdArgv;

    if ((objc != 3) && (objc != 4)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?value?");
	return TCL_ERROR;
1701
1702
1703
1704
1705
1706
1707
1708

1709
1710
1711
1712
1713
1714

1715
1716
1717
1718
1719
1720
1721
1698
1699
1700
1701
1702
1703
1704

1705
1706
1707
1708
1709
1710

1711
1712
1713
1714
1715
1716
1717
1718







-
+





-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmDeiconifyCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "window");
	return TCL_ERROR;
    }
    if (wmPtr->iconFor != NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
1751
1752
1753
1754
1755
1756
1757
1758

1759
1760
1761
1762
1763
1764

1765
1766
1767
1768
1769
1770
1771
1748
1749
1750
1751
1752
1753
1754

1755
1756
1757
1758
1759
1760

1761
1762
1763
1764
1765
1766
1767
1768







-
+





-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmFocusmodelCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    static const char *const optionStrings[] = {
	"active", "passive", NULL };
    enum options {
	OPT_ACTIVE, OPT_PASSIVE };
    int index;

    if ((objc != 3) && (objc != 4)) {
1806
1807
1808
1809
1810
1811
1812
1813

1814
1815
1816
1817



1818
1819

1820
1821
1822
1823
1824
1825
1826
1803
1804
1805
1806
1807
1808
1809

1810
1811



1812
1813
1814
1815

1816
1817
1818
1819
1820
1821
1822
1823







-
+

-
-
-
+
+
+

-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmForgetCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    TCL_UNUSED(Tk_Window),		/* Main window of the application. */
    TkWindow *winPtr,		/* Toplevel or Frame to work with */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
    TCL_UNUSED(Tcl_Interp *),		/* Current interpreter. */
    TCL_UNUSED(int),			/* Number of arguments. */
    TCL_UNUSED(Tcl_Obj *const *))	/* Argument objects. */
{
    register Tk_Window frameWin = (Tk_Window) winPtr;
    Tk_Window frameWin = (Tk_Window) winPtr;

    if (Tk_IsTopLevel(frameWin)) {
	TkFocusJoin(winPtr);
	Tk_UnmapWindow(frameWin);
	TkWmDeadWindow(winPtr);
	winPtr->flags &=
		~(TK_TOP_HIERARCHY|TK_TOP_LEVEL|TK_HAS_WRAPPER|TK_WIN_MANAGED);
1859
1860
1861
1862
1863
1864
1865
1866

1867
1868
1869
1870
1871
1872

1873
1874
1875
1876
1877
1878
1879
1856
1857
1858
1859
1860
1861
1862

1863
1864
1865
1866
1867
1868

1869
1870
1871
1872
1873
1874
1875
1876







-
+





-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmFrameCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    Window window;
    char buf[TCL_INTEGER_SPACE];

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "window");
	return TCL_ERROR;
    }
1901
1902
1903
1904
1905
1906
1907
1908

1909
1910
1911
1912
1913
1914

1915
1916
1917
1918
1919
1920
1921
1898
1899
1900
1901
1902
1903
1904

1905
1906
1907
1908
1909
1910

1911
1912
1913
1914
1915
1916
1917
1918







-
+





-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmGeometryCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    char xSign, ySign;
    int width, height;
    const char *argv3;

    if ((objc != 3) && (objc != 4)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?newGeometry?");
	return TCL_ERROR;
1961
1962
1963
1964
1965
1966
1967
1968

1969
1970
1971
1972
1973
1974

1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989




1990
1991
1992
1993
1994
1995
1996
1958
1959
1960
1961
1962
1963
1964

1965
1966
1967
1968
1969
1970

1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982




1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993







-
+





-
+











-
-
-
-
+
+
+
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmGridCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    int reqWidth, reqHeight, widthInc, heightInc;

    if ((objc != 3) && (objc != 7)) {
	Tcl_WrongNumArgs(interp, 2, objv,
		"window ?baseWidth baseHeight widthInc heightInc?");
	return TCL_ERROR;
    }
    if (objc == 3) {
	if (wmPtr->sizeHintsFlags & PBaseSize) {
	    Tcl_Obj *results[4];

	    results[0] = Tcl_NewIntObj(wmPtr->reqGridWidth);
	    results[1] = Tcl_NewIntObj(wmPtr->reqGridHeight);
	    results[2] = Tcl_NewIntObj(wmPtr->widthInc);
	    results[3] = Tcl_NewIntObj(wmPtr->heightInc);
	    results[0] = Tcl_NewWideIntObj(wmPtr->reqGridWidth);
	    results[1] = Tcl_NewWideIntObj(wmPtr->reqGridHeight);
	    results[2] = Tcl_NewWideIntObj(wmPtr->widthInc);
	    results[3] = Tcl_NewWideIntObj(wmPtr->heightInc);
	    Tcl_SetObjResult(interp, Tcl_NewListObj(4, results));
	}
	return TCL_OK;
    }
    if (*Tcl_GetString(objv[3]) == '\0') {
	/*
	 * Turn off gridding and reset the width and height to make sense as
2066
2067
2068
2069
2070
2071
2072
2073

2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089

2090
2091
2092
2093
2094
2095
2096
2063
2064
2065
2066
2067
2068
2069

2070
2071
2072
2073

2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084

2085
2086
2087
2088
2089
2090
2091
2092







-
+



-











-
+







WmGroupCmd(
    Tk_Window tkwin,		/* 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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    Tk_Window tkwin2;
    WmInfo *wmPtr2;
    const char *argv3;
    int length;

    if ((objc != 3) && (objc != 4)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?pathName?");
	return TCL_ERROR;
    }
    if (objc == 3) {
	if (wmPtr->hints.flags & WindowGroupHint) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(wmPtr->leaderName, -1));
	}
	return TCL_OK;
    }
    argv3 = Tcl_GetStringFromObj(objv[3], &length);
    argv3 = Tcl_GetString(objv[3]);
    if (*argv3 == '\0') {
	wmPtr->hints.flags &= ~WindowGroupHint;
	if (wmPtr->leaderName != NULL) {
	    ckfree(wmPtr->leaderName);
	}
	wmPtr->leaderName = NULL;
    } else {
2110
2111
2112
2113
2114
2115
2116
2117

2118
2119
2120
2121
2122
2123
2124
2106
2107
2108
2109
2110
2111
2112

2113
2114
2115
2116
2117
2118
2119
2120







-
+







	    CreateWrapper(wmPtr2);
	}
	if (wmPtr->leaderName != NULL) {
	    ckfree(wmPtr->leaderName);
	}
	wmPtr->hints.window_group = Tk_WindowId(wmPtr2->wrapperPtr);
	wmPtr->hints.flags |= WindowGroupHint;
	wmPtr->leaderName = ckalloc(length + 1);
	wmPtr->leaderName = (char *)ckalloc(objv[3]->length + 1);
	strcpy(wmPtr->leaderName, argv3);
    }
    UpdateHints(winPtr);
    return TCL_OK;
}

/*
2136
2137
2138
2139
2140
2141
2142
2143

2144
2145
2146
2147
2148
2149

2150
2151
2152
2153
2154
2155
2156
2132
2133
2134
2135
2136
2137
2138

2139
2140
2141
2142
2143
2144

2145
2146
2147
2148
2149
2150
2151
2152







-
+





-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmIconbitmapCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    Pixmap pixmap;
    const char *argv3;

    if ((objc < 3) || (objc > 4)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?bitmap?");
	return TCL_ERROR;
    }
2196
2197
2198
2199
2200
2201
2202
2203

2204
2205
2206
2207
2208
2209

2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223

2224
2225
2226
2227
2228
2229
2230
2231
2232

2233
2234
2235
2236
2237
2238
2239

2240
2241
2242
2243
2244
2245
2246
2192
2193
2194
2195
2196
2197
2198

2199
2200
2201
2202
2203
2204

2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218

2219
2220
2221
2222
2223
2224
2225
2226
2227

2228
2229
2230
2231
2232
2233
2234

2235
2236
2237
2238
2239
2240
2241
2242







-
+





-
+













-
+








-
+






-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmIconifyCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "window");
	return TCL_ERROR;
    }
    if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"can't iconify \"%s\": override-redirect flag is set",
		winPtr->pathName));
	Tcl_SetErrorCode(interp, "TK", "WM", "ICONIFY", "OVERRIDE_REDIRECT",
		NULL);
	return TCL_ERROR;
    }
    if (wmPtr->masterPtr != NULL) {
    if (wmPtr->containerPtr != NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"can't iconify \"%s\": it is a transient",
		winPtr->pathName));
	Tcl_SetErrorCode(interp, "TK", "WM", "ICONIFY", "TRANSIENT", NULL);
	return TCL_ERROR;
    }
    if (wmPtr->iconFor != NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"can't iconify %s: it is an icon for %s",
		"can't iconify \"%s\": it is an icon for \"%s\"",
		winPtr->pathName, Tk_PathName(wmPtr->iconFor)));
	Tcl_SetErrorCode(interp, "TK", "WM", "ICONIFY", "ICON", NULL);
	return TCL_ERROR;
    }
    if (winPtr->flags & TK_EMBEDDED) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"can't iconify %s: it is an embedded window",
		"can't iconify \"%s\": it is an embedded window",
		winPtr->pathName));
	Tcl_SetErrorCode(interp, "TK", "WM", "ICONIFY", "EMBEDDED", NULL);
	return TCL_ERROR;
    }
    if (TkpWmSetState(winPtr, IconicState) == 0) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"couldn't send iconify message to window manager", -1));
2271
2272
2273
2274
2275
2276
2277
2278

2279
2280
2281
2282
2283
2284
2285
2267
2268
2269
2270
2271
2272
2273

2274
2275
2276
2277
2278
2279
2280
2281







-
+







WmIconmaskCmd(
    Tk_Window tkwin,		/* 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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    Pixmap pixmap;
    const char *argv3;

    if ((objc != 3) && (objc != 4)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?bitmap?");
	return TCL_ERROR;
    }
2324
2325
2326
2327
2328
2329
2330
2331

2332
2333
2334
2335
2336
2337

2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355


2356
2357
2358
2359
2360
2361
2362
2320
2321
2322
2323
2324
2325
2326

2327
2328
2329
2330
2331
2332

2333
2334

2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348


2349
2350
2351
2352
2353
2354
2355
2356
2357







-
+





-
+

-














-
-
+
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmIconnameCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    const char *argv3;
    int length;

    if (objc > 4) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?newName?");
	return TCL_ERROR;
    }
    if (objc == 3) {
	if (wmPtr->iconName != NULL) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(wmPtr->iconName, -1));
	}
	return TCL_OK;
    } else {
	if (wmPtr->iconName != NULL) {
	    ckfree(wmPtr->iconName);
	}
	argv3 = Tcl_GetStringFromObj(objv[3], &length);
	wmPtr->iconName = ckalloc(length + 1);
	argv3 = Tcl_GetString(objv[3]);
	wmPtr->iconName = (char *)ckalloc(objv[3]->length + 1);
	strcpy(wmPtr->iconName, argv3);
	if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
	    UpdateTitle(winPtr);
	}
    }
    return TCL_OK;
}
2376
2377
2378
2379
2380
2381
2382
2383

2384
2385
2386
2387
2388
2389

2390
2391
2392
2393
2394
2395
2396
2371
2372
2373
2374
2375
2376
2377

2378
2379
2380
2381
2382
2383

2384
2385
2386
2387
2388
2389
2390
2391







-
+





-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmIconphotoCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    Tk_PhotoHandle photo;
    Tk_PhotoImageBlock block;
    int i, size = 0, width, height, index = 0, x, y, isDefault = 0;
    unsigned long *iconPropertyData;

    if (objc < 4) {
	Tcl_WrongNumArgs(interp, 2, objv,
2433
2434
2435
2436
2437
2438
2439
2440

2441
2442
2443
2444
2445
2446
2447
2428
2429
2430
2431
2432
2433
2434

2435
2436
2437
2438
2439
2440
2441
2442







-
+







    /*
     * We have calculated the size of the data. Try to allocate the needed
     * memory space. This is an unsigned long array (despite this being twice
     * as much as is really needed on LP64 platforms) because that's what X
     * defines CARD32 arrays to use. [Bug 2902814]
     */

    iconPropertyData = attemptckalloc(sizeof(unsigned long) * size);
    iconPropertyData = (unsigned long *)attemptckalloc(sizeof(unsigned long) * size);
    if (iconPropertyData == NULL) {
	return TCL_ERROR;
    }
    memset(iconPropertyData, 0, sizeof(unsigned long) * size);

    for (i = 3 + isDefault; i < objc; i++) {
	photo = Tk_FindPhoto(interp, Tcl_GetString(objv[i]));
2475
2476
2477
2478
2479
2480
2481
2482

2483
2484

2485
2486
2487
2488
2489
2490
2491
2470
2471
2472
2473
2474
2475
2476

2477
2478

2479
2480
2481
2482
2483
2484
2485
2486







-
+

-
+







	 * The image data will be encoded in the iconPropertyData array.
	 */

	iconPropertyData[index++] = (unsigned long) width;
	iconPropertyData[index++] = (unsigned long) height;
	for (y = 0; y < height; y++) {
	    for (x = 0; x < width; x++) {
		register unsigned char *pixelPtr =
		unsigned char *pixelPtr =
			block.pixelPtr + x*block.pixelSize + y*block.pitch;
		register unsigned long R, G, B, A;
		unsigned long R, G, B, A;

		R = pixelPtr[block.offset[0]];
		G = pixelPtr[block.offset[1]];
		B = pixelPtr[block.offset[2]];
		A = pixelPtr[block.offset[3]];
		iconPropertyData[index++] = A<<24 | R<<16 | G<<8 | B<<0;
	    }
2526
2527
2528
2529
2530
2531
2532
2533

2534
2535
2536
2537
2538
2539

2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551


2552
2553
2554
2555
2556
2557
2558
2521
2522
2523
2524
2525
2526
2527

2528
2529
2530
2531
2532
2533

2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544


2545
2546
2547
2548
2549
2550
2551
2552
2553







-
+





-
+










-
-
+
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmIconpositionCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    int x, y;

    if ((objc != 3) && (objc != 5)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?x y?");
	return TCL_ERROR;
    }
    if (objc == 3) {
	if (wmPtr->hints.flags & IconPositionHint) {
	    Tcl_Obj *results[2];

	    results[0] = Tcl_NewIntObj(wmPtr->hints.icon_x);
	    results[1] = Tcl_NewIntObj(wmPtr->hints.icon_y);
	    results[0] = Tcl_NewWideIntObj(wmPtr->hints.icon_x);
	    results[1] = Tcl_NewWideIntObj(wmPtr->hints.icon_y);
	    Tcl_SetObjResult(interp, Tcl_NewListObj(2, results));
	}
	return TCL_OK;
    }
    if (Tcl_GetString(objv[3])[0] == '\0') {
	wmPtr->hints.flags &= ~IconPositionHint;
    } else {
2589
2590
2591
2592
2593
2594
2595
2596

2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607

2608
2609
2610
2611
2612
2613
2614
2584
2585
2586
2587
2588
2589
2590

2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601

2602
2603
2604
2605
2606
2607
2608
2609







-
+










-
+







WmIconwindowCmd(
    Tk_Window tkwin,		/* 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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    Tk_Window tkwin2;
    WmInfo *wmPtr2;
    XSetWindowAttributes atts;

    if ((objc != 3) && (objc != 4)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?pathName?");
	return TCL_ERROR;
    }
    if (objc == 3) {
	if (wmPtr->icon != NULL) {
	    Tcl_SetObjResult(interp, TkNewWindowObj(wmPtr->icon));
	    Tcl_SetObjResult(interp, Tk_NewWindowObj(wmPtr->icon));
	}
	return TCL_OK;
    }
    if (*Tcl_GetString(objv[3]) == '\0') {
	wmPtr->hints.flags &= ~IconWindowHint;
	if (wmPtr->icon != NULL) {
	    /*
2703
2704
2705
2706
2707
2708
2709
2710

2711
2712
2713
2714


2715
2716
2717


2718
2719
2720
2721
2722
2723
2724
2698
2699
2700
2701
2702
2703
2704

2705
2706
2707


2708
2709
2710


2711
2712
2713
2714
2715
2716
2717
2718
2719







-
+


-
-
+
+

-
-
+
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmManageCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    TCL_UNUSED(Tk_Window),		/* Main window of the application. */
    TkWindow *winPtr,		/* Toplevel or Frame to work with */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
    TCL_UNUSED(int),			/* Number of arguments. */
    TCL_UNUSED(Tcl_Obj *const *))	/* Argument objects. */
{
    register Tk_Window frameWin = (Tk_Window) winPtr;
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    Tk_Window frameWin = (Tk_Window) winPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;

    if (!Tk_IsTopLevel(frameWin)) {
	if (!Tk_IsManageable(frameWin)) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "window \"%s\" is not manageable: must be a frame,"
		    " labelframe or toplevel", Tk_PathName(frameWin)));
	    Tcl_SetErrorCode(interp, "TK", "WM", "MANAGE", NULL);
2765
2766
2767
2768
2769
2770
2771
2772

2773
2774
2775
2776
2777
2778

2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790


2791
2792
2793
2794
2795
2796
2797
2760
2761
2762
2763
2764
2765
2766

2767
2768
2769
2770
2771
2772

2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783


2784
2785
2786
2787
2788
2789
2790
2791
2792







-
+





-
+










-
-
+
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmMaxsizeCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    int width, height;

    if ((objc != 3) && (objc != 5)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?width height?");
	return TCL_ERROR;
    }
    if (objc == 3) {
	Tcl_Obj *results[2];

	GetMaxSize(wmPtr, &width, &height);
	results[0] = Tcl_NewIntObj(width);
	results[1] = Tcl_NewIntObj(height);
	results[0] = Tcl_NewWideIntObj(width);
	results[1] = Tcl_NewWideIntObj(height);
	Tcl_SetObjResult(interp, Tcl_NewListObj(2, results));
	return TCL_OK;
    }
    if ((Tcl_GetIntFromObj(interp, objv[3], &width) != TCL_OK)
	    || (Tcl_GetIntFromObj(interp, objv[4], &height) != TCL_OK)) {
	return TCL_ERROR;
    }
2824
2825
2826
2827
2828
2829
2830
2831

2832
2833
2834
2835
2836
2837

2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848


2849
2850
2851
2852
2853
2854
2855
2819
2820
2821
2822
2823
2824
2825

2826
2827
2828
2829
2830
2831

2832
2833
2834
2835
2836
2837
2838
2839
2840
2841


2842
2843
2844
2845
2846
2847
2848
2849
2850







-
+





-
+









-
-
+
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmMinsizeCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    int width, height;

    if ((objc != 3) && (objc != 5)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?width height?");
	return TCL_ERROR;
    }
    if (objc == 3) {
	Tcl_Obj *results[2];

	results[0] = Tcl_NewIntObj(wmPtr->minWidth);
	results[1] = Tcl_NewIntObj(wmPtr->minHeight);
	results[0] = Tcl_NewWideIntObj(wmPtr->minWidth);
	results[1] = Tcl_NewWideIntObj(wmPtr->minHeight);
	Tcl_SetObjResult(interp, Tcl_NewListObj(2, results));
	return TCL_OK;
    }
    if ((Tcl_GetIntFromObj(interp, objv[3], &width) != TCL_OK)
	    || (Tcl_GetIntFromObj(interp, objv[4], &height) != TCL_OK)) {
	return TCL_ERROR;
    }
2875
2876
2877
2878
2879
2880
2881
2882

2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897

2898
2899
2900
2901
2902
2903
2904
2870
2871
2872
2873
2874
2875
2876

2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891

2892
2893
2894
2895
2896
2897
2898
2899







-
+














-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmOverrideredirectCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    int boolean, curValue;
    XSetWindowAttributes atts;

    if ((objc != 3) && (objc != 4)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?boolean?");
	return TCL_ERROR;
    }
    curValue = Tk_Attributes((Tk_Window) winPtr)->override_redirect;
    if (objc == 3) {
	Tcl_SetObjResult(interp, Tcl_NewBooleanObj(curValue));
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(curValue != 0));
	return TCL_OK;
    }
    if (Tcl_GetBooleanFromObj(interp, objv[3], &boolean) != TCL_OK) {
	return TCL_ERROR;
    }
    if (curValue != boolean) {
	/*
2933
2934
2935
2936
2937
2938
2939
2940

2941
2942
2943
2944
2945
2946

2947
2948
2949
2950
2951
2952
2953
2928
2929
2930
2931
2932
2933
2934

2935
2936
2937
2938
2939
2940

2941
2942
2943
2944
2945
2946
2947
2948







-
+





-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmPositionfromCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    static const char *const optionStrings[] = {
	"program", "user", NULL };
    enum options {
	OPT_PROGRAM, OPT_USER };
    int index;

    if ((objc != 3) && (objc != 4)) {
3000
3001
3002
3003
3004
3005
3006
3007

3008
3009
3010
3011
3012
3013
3014


3015
3016
3017

3018
3019
3020
3021
3022
3023
3024
2995
2996
2997
2998
2999
3000
3001

3002
3003
3004
3005
3006
3007


3008
3009
3010
3011

3012
3013
3014
3015
3016
3017
3018
3019







-
+





-
-
+
+


-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmProtocolCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    register ProtocolHandler *protPtr, *prevPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    ProtocolHandler *protPtr, *prevPtr;
    Atom protocol;
    const char *cmd;
    int cmdLength;
    TkSizeT cmdLength;

    if ((objc < 3) || (objc > 5)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?name? ?command?");
	return TCL_ERROR;
    }
    if (objc == 3) {
	/*
3076
3077
3078
3079
3080
3081
3082
3083

3084
3085

3086
3087
3088
3089
3090
3091
3092
3071
3072
3073
3074
3075
3076
3077

3078
3079

3080
3081
3082
3083
3084
3085
3086
3087







-
+

-
+







	    } else {
		prevPtr->nextPtr = protPtr->nextPtr;
	    }
	    Tcl_EventuallyFree(protPtr, TCL_DYNAMIC);
	    break;
	}
    }
    cmd = Tcl_GetStringFromObj(objv[4], &cmdLength);
    cmd = TkGetStringFromObj(objv[4], &cmdLength);
    if (cmdLength > 0) {
	protPtr = ckalloc(HANDLER_SIZE(cmdLength));
	protPtr = (ProtocolHandler *)ckalloc(HANDLER_SIZE(cmdLength));
	protPtr->protocol = protocol;
	protPtr->nextPtr = wmPtr->protPtr;
	wmPtr->protPtr = protPtr;
	protPtr->interp = interp;
	memcpy(protPtr->command, cmd, cmdLength + 1);
    }
    if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
3110
3111
3112
3113
3114
3115
3116
3117

3118
3119
3120
3121
3122
3123

3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134


3135
3136
3137
3138
3139
3140
3141
3105
3106
3107
3108
3109
3110
3111

3112
3113
3114
3115
3116
3117

3118
3119
3120
3121
3122
3123
3124
3125
3126
3127


3128
3129
3130
3131
3132
3133
3134
3135
3136







-
+





-
+









-
-
+
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmResizableCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    int width, height;

    if ((objc != 3) && (objc != 5)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?width height?");
	return TCL_ERROR;
    }
    if (objc == 3) {
	Tcl_Obj *results[2];

	results[0] = Tcl_NewBooleanObj(!(wmPtr->flags&WM_WIDTH_NOT_RESIZABLE));
	results[1] = Tcl_NewBooleanObj(!(wmPtr->flags&WM_HEIGHT_NOT_RESIZABLE));
	results[0] = Tcl_NewWideIntObj(!(wmPtr->flags&WM_WIDTH_NOT_RESIZABLE));
	results[1] = Tcl_NewWideIntObj(!(wmPtr->flags&WM_HEIGHT_NOT_RESIZABLE));
	Tcl_SetObjResult(interp, Tcl_NewListObj(2, results));
	return TCL_OK;
    }
    if ((Tcl_GetBooleanFromObj(interp, objv[3], &width) != TCL_OK)
	    || (Tcl_GetBooleanFromObj(interp, objv[4], &height) != TCL_OK)) {
	return TCL_ERROR;
    }
3169
3170
3171
3172
3173
3174
3175
3176

3177
3178
3179
3180
3181
3182

3183
3184
3185
3186
3187
3188
3189
3164
3165
3166
3167
3168
3169
3170

3171
3172
3173
3174
3175
3176

3177
3178
3179
3180
3181
3182
3183
3184







-
+





-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmSizefromCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    static const char *const optionStrings[] = {
	"program", "user", NULL };
    enum options {
	OPT_PROGRAM, OPT_USER };
    int index;

    if ((objc != 3) && (objc != 4)) {
3336
3337
3338
3339
3340
3341
3342
3343

3344
3345
3346
3347
3348
3349
3350
3331
3332
3333
3334
3335
3336
3337

3338
3339
3340
3341
3342
3343
3344
3345







-
+







	    return TCL_ERROR;
	}
	if (index == OPT_ISABOVE) {
	    result = index1 > index2;
	} else { /* OPT_ISBELOW */
	    result = index1 < index2;
	}
	Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result));
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(result));
	return TCL_OK;
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
3361
3362
3363
3364
3365
3366
3367
3368

3369
3370
3371
3372
3373
3374

3375
3376
3377
3378
3379
3380
3381
3356
3357
3358
3359
3360
3361
3362

3363
3364
3365
3366
3367
3368

3369
3370
3371
3372
3373
3374
3375
3376







-
+





-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmStateCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    static const char *const optionStrings[] = {
	"normal", "iconic", "withdrawn", NULL };
    enum options {
	OPT_NORMAL, OPT_ICONIC, OPT_WITHDRAWN };
    int index;

    if ((objc < 3) || (objc > 4)) {
3404
3405
3406
3407
3408
3409
3410
3411

3412
3413
3414
3415
3416
3417
3418
3399
3400
3401
3402
3403
3404
3405

3406
3407
3408
3409
3410
3411
3412
3413







-
+







		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"can't iconify \"%s\": override-redirect flag is set",
			winPtr->pathName));
		Tcl_SetErrorCode(interp, "TK", "WM", "STATE",
			"OVERRIDE_REDIRECT", NULL);
		return TCL_ERROR;
	    }
	    if (wmPtr->masterPtr != NULL) {
	    if (wmPtr->containerPtr != NULL) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"can't iconify \"%s\": it is a transient",
			winPtr->pathName));
		Tcl_SetErrorCode(interp, "TK", "WM", "STATE", "TRANSIENT",
			NULL);
		return TCL_ERROR;
	    }
3467
3468
3469
3470
3471
3472
3473
3474

3475
3476
3477
3478
3479
3480

3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499


3500
3501
3502
3503
3504
3505
3506
3462
3463
3464
3465
3466
3467
3468

3469
3470
3471
3472
3473
3474

3475
3476

3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491


3492
3493
3494
3495
3496
3497
3498
3499
3500







-
+





-
+

-















-
-
+
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmTitleCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    const char *argv3;
    int length;

    if (objc > 4) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?newTitle?");
	return TCL_ERROR;
    }
    if (objc == 3) {
	if (wmPtr->title) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(wmPtr->title, -1));
	} else {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(winPtr->nameUid, -1));
	}
    } else {
	if (wmPtr->title != NULL) {
	    ckfree(wmPtr->title);
	}
	argv3 = Tcl_GetStringFromObj(objv[3], &length);
	wmPtr->title = ckalloc(length + 1);
	argv3 = Tcl_GetString(objv[3]);
	wmPtr->title = (char *)ckalloc(objv[3]->length + 1);
	strcpy(wmPtr->title, argv3);

	if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
	    UpdateTitle(winPtr);
	}
    }
    return TCL_OK;
3527
3528
3529
3530
3531
3532
3533
3534
3535


3536
3537
3538
3539

3540
3541
3542
3543
3544


3545
3546
3547
3548
3549

3550
3551

3552
3553
3554
3555
3556


3557
3558
3559
3560
3561
3562
3563
3564
3565
3566

3567
3568

3569
3570

3571
3572
3573
3574


3575
3576

3577
3578
3579

3580
3581

3582
3583
3584
3585
3586
3587
3588
3589
3590
3591

3592
3593
3594
3595
3596
3597
3598

3599
3600
3601
3602
3603
3604
3605


3606
3607
3608
3609


3610
3611
3612
3613
3614
3615

3616
3617
3618
3619



3620
3621
3622
3623
3624



3625
3626
3627
3628
3629


3630
3631
3632

3633
3634
3635
3636

3637
3638
3639
3640
3641
3642
3643
3644
3645

3646
3647
3648

3649
3650
3651
3652
3653
3654
3655
3521
3522
3523
3524
3525
3526
3527


3528
3529
3530
3531
3532

3533
3534
3535
3536


3537
3538
3539
3540
3541
3542

3543
3544

3545
3546
3547
3548


3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559

3560
3561

3562
3563

3564
3565
3566


3567
3568
3569

3570
3571
3572

3573
3574

3575
3576
3577
3578
3579
3580
3581
3582
3583
3584

3585
3586
3587
3588
3589
3590
3591

3592
3593
3594
3595
3596
3597


3598
3599
3600
3601


3602
3603
3604
3605
3606
3607
3608

3609
3610



3611
3612
3613
3614
3615



3616
3617
3618
3619
3620
3621


3622
3623
3624
3625

3626
3627
3628
3629

3630
3631
3632
3633
3634
3635
3636
3637
3638

3639
3640
3641

3642
3643
3644
3645
3646
3647
3648
3649







-
-
+
+



-
+



-
-
+
+




-
+

-
+



-
-
+
+









-
+

-
+

-
+


-
-
+
+

-
+


-
+

-
+









-
+






-
+





-
-
+
+


-
-
+
+





-
+

-
-
-
+
+
+


-
-
-
+
+
+



-
-
+
+


-
+



-
+








-
+


-
+







WmTransientCmd(
    Tk_Window tkwin,		/* 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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    TkWindow *masterPtr = wmPtr->masterPtr, *w;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    TkWindow *containerPtr = wmPtr->containerPtr, *w;
    WmInfo *wmPtr2;

    if ((objc != 3) && (objc != 4)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?master?");
	Tcl_WrongNumArgs(interp, 2, objv, "window ?window?");
	return TCL_ERROR;
    }
    if (objc == 3) {
	if (masterPtr != NULL) {
	    Tcl_SetObjResult(interp, TkNewWindowObj((Tk_Window) masterPtr));
	if (containerPtr != NULL) {
	    Tcl_SetObjResult(interp, Tk_NewWindowObj((Tk_Window) containerPtr));
	}
	return TCL_OK;
    }
    if (Tcl_GetString(objv[3])[0] == '\0') {
	if (masterPtr != NULL) {
	if (containerPtr != NULL) {
	    /*
	     * If we had a master, tell them that we aren't tied to them
	     * If we had a container, tell them that we aren't tied to them
	     * anymore
	     */

	    masterPtr->wmInfoPtr->numTransients--;
	    Tk_DeleteEventHandler((Tk_Window) masterPtr, StructureNotifyMask,
	    containerPtr->wmInfoPtr->numTransients--;
	    Tk_DeleteEventHandler((Tk_Window) containerPtr, StructureNotifyMask,
		    WmWaitMapProc, winPtr);

	    /*
	     * FIXME: Need a call like Win32's UpdateWrapper() so we can
	     * recreate the wrapper and get rid of the transient window
	     * decorations.
	     */
	}

	wmPtr->masterPtr = NULL;
	wmPtr->containerPtr = NULL;
    } else {
	Tk_Window masterWin;
	Tk_Window container;

	if (TkGetWindowFromObj(interp, tkwin, objv[3], &masterWin)!=TCL_OK) {
	if (TkGetWindowFromObj(interp, tkwin, objv[3], &container)!=TCL_OK) {
	    return TCL_ERROR;
	}
	masterPtr = (TkWindow *) masterWin;
	while (!Tk_TopWinHierarchy(masterPtr)) {
	containerPtr = (TkWindow *) container;
	while (!Tk_TopWinHierarchy(containerPtr)) {
	    /*
	     * Ensure that the master window is actually a Tk toplevel.
	     * Ensure that the container window is actually a Tk toplevel.
	     */

	    masterPtr = masterPtr->parentPtr;
	    containerPtr = containerPtr->parentPtr;
	}
	Tk_MakeWindowExist((Tk_Window) masterPtr);
	Tk_MakeWindowExist((Tk_Window) containerPtr);

	if (wmPtr->iconFor != NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "can't make \"%s\" a transient: it is an icon for %s",
		    Tcl_GetString(objv[2]), Tk_PathName(wmPtr->iconFor)));
	    Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "ICON", NULL);
	    return TCL_ERROR;
	}

	wmPtr2 = masterPtr->wmInfoPtr;
	wmPtr2 = containerPtr->wmInfoPtr;
	if (wmPtr2->wrapperPtr == NULL) {
	    CreateWrapper(wmPtr2);
	}

	if (wmPtr2->iconFor != NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "can't make \"%s\" a master: it is an icon for %s",
		    "can't make \"%s\" a container: it is an icon for %s",
		    Tcl_GetString(objv[3]), Tk_PathName(wmPtr2->iconFor)));
	    Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "ICON", NULL);
	    return TCL_ERROR;
	}

	for (w = masterPtr; w != NULL && w->wmInfoPtr != NULL;
	     w = (TkWindow *)w->wmInfoPtr->masterPtr) {
	for (w = containerPtr; w != NULL && w->wmInfoPtr != NULL;
	     w = (TkWindow *)w->wmInfoPtr->containerPtr) {
	    if (w == winPtr) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "setting \"%s\" as master creates a transient/master cycle",
		    Tk_PathName(masterPtr)));
		    "can't set \"%s\" as container: would cause management loop",
		    Tk_PathName(containerPtr)));
		Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "SELF", NULL);
		return TCL_ERROR;
	    }
	}

	if (masterPtr != wmPtr->masterPtr) {
	if (containerPtr != wmPtr->containerPtr) {
	    /*
	     * Remove old master map/unmap binding before setting the new
	     * master. The event handler will ensure that transient states
	     * reflect the state of the master.
	     * Remove old container map/unmap binding before setting the new
	     * container. The event handler will ensure that transient states
	     * reflect the state of the container.
	     */

	    if (wmPtr->masterPtr != NULL) {
		wmPtr->masterPtr->wmInfoPtr->numTransients--;
		Tk_DeleteEventHandler((Tk_Window) wmPtr->masterPtr,
	    if (wmPtr->containerPtr != NULL) {
		wmPtr->containerPtr->wmInfoPtr->numTransients--;
		Tk_DeleteEventHandler((Tk_Window) wmPtr->containerPtr,
			StructureNotifyMask, WmWaitMapProc, winPtr);
	    }

	    masterPtr->wmInfoPtr->numTransients++;
	    Tk_CreateEventHandler((Tk_Window) masterPtr,
	    containerPtr->wmInfoPtr->numTransients++;
	    Tk_CreateEventHandler((Tk_Window) containerPtr,
		    StructureNotifyMask, WmWaitMapProc, winPtr);

	    wmPtr->masterPtr = masterPtr;
	    wmPtr->containerPtr = containerPtr;
	}
    }
    if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
	if (wmPtr->masterPtr != NULL && !Tk_IsMapped(wmPtr->masterPtr)) {
	if (wmPtr->containerPtr != NULL && !Tk_IsMapped(wmPtr->containerPtr)) {
	    if (TkpWmSetState(winPtr, WithdrawnState) == 0) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"couldn't send withdraw message to window manager",
			-1));
		Tcl_SetErrorCode(interp, "TK", "WM", "COMMUNICATION", NULL);
		return TCL_ERROR;
	    }
	} else {
	    if (wmPtr->masterPtr != NULL) {
	    if (wmPtr->containerPtr != NULL) {
		XSetTransientForHint(winPtr->display,
			wmPtr->wrapperPtr->window,
			wmPtr->masterPtr->wmInfoPtr->wrapperPtr->window);
			wmPtr->containerPtr->wmInfoPtr->wrapperPtr->window);
	    } else {
		XDeleteProperty(winPtr->display, wmPtr->wrapperPtr->window,
			Tk_InternAtom((Tk_Window) winPtr,"WM_TRANSIENT_FOR"));
	    }
	}
    }
    return TCL_OK;
3670
3671
3672
3673
3674
3675
3676
3677

3678
3679
3680
3681
3682
3683

3684
3685
3686
3687
3688
3689
3690
3664
3665
3666
3667
3668
3669
3670

3671
3672
3673
3674
3675
3676

3677
3678
3679
3680
3681
3682
3683
3684







-
+





-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
WmWithdrawCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "window");
	return TCL_ERROR;
    }
    if (wmPtr->iconFor != NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
3717
3718
3719
3720
3721
3722
3723
3724

3725
3726
3727
3728
3729
3730
3731
3732
3733


3734
3735

3736
3737
3738
3739
3740
3741
3742
3711
3712
3713
3714
3715
3716
3717

3718
3719
3720
3721
3722
3723
3724
3725


3726
3727
3728

3729
3730
3731
3732
3733
3734
3735
3736







-
+







-
-
+
+

-
+







	Tcl_DoWhenIdle(UpdateGeometryInfo, winPtr);
	wmPtr->flags |= WM_UPDATE_PENDING;
    }
}

/*
 * Invoked when a MapNotify or UnmapNotify event is delivered for a toplevel
 * that is the master of a transient toplevel.
 * that is the container of a transient toplevel.
 */

static void
WmWaitMapProc(
    ClientData clientData,	/* Pointer to window. */
    XEvent *eventPtr)		/* Information about event. */
{
    TkWindow *winPtr = clientData;
    TkWindow *masterPtr = winPtr->wmInfoPtr->masterPtr;
    TkWindow *winPtr = (TkWindow *)clientData;
    TkWindow *containerPtr = winPtr->wmInfoPtr->containerPtr;

    if (masterPtr == NULL) {
    if (containerPtr == NULL) {
	return;
    }

    if (eventPtr->type == MapNotify) {
	if (!(winPtr->wmInfoPtr->flags & WM_WITHDRAWN)) {
	    (void) TkpWmSetState(winPtr, NormalState);
	}
3776
3777
3778
3779
3780
3781
3782
3783

3784
3785
3786
3787
3788
3789
3790
3770
3771
3772
3773
3774
3775
3776

3777
3778
3779
3780
3781
3782
3783
3784







-
+







				 * requested geometry for tkwin. */
    int reqHeight,		/* Height (in grid units) corresponding to the
				 * requested geometry for tkwin. */
    int widthInc, int heightInc)/* Pixel increments corresponding to a change
				 * of one grid unit. */
{
    TkWindow *winPtr = (TkWindow *) tkwin;
    register WmInfo *wmPtr;
    WmInfo *wmPtr;

    /*
     * Ensure widthInc and heightInc are greater than 0
     */

    if (widthInc <= 0) {
	widthInc = 1;
3881
3882
3883
3884
3885
3886
3887
3888

3889
3890
3891
3892
3893
3894
3895
3875
3876
3877
3878
3879
3880
3881

3882
3883
3884
3885
3886
3887
3888
3889







-
+








void
Tk_UnsetGrid(
    Tk_Window tkwin)		/* Token for window that is currently
				 * controlling gridding. */
{
    TkWindow *winPtr = (TkWindow *) tkwin;
    register WmInfo *wmPtr;
    WmInfo *wmPtr;

    /*
     * Find the top-level window for tkwin, plus the window manager
     * information.
     */

    while (!(winPtr->flags & TK_TOP_HIERARCHY)) {
4414
4415
4416
4417
4418
4419
4420
4421

4422
4423
4424
4425
4426
4427
4428
4408
4409
4410
4411
4412
4413
4414

4415
4416
4417
4418
4419
4420
4421
4422







-
+







	(StructureNotifyMask | PropertyChangeMask);

static void
WrapperEventProc(
    ClientData clientData,	/* Information about toplevel window. */
    XEvent *eventPtr)		/* Event that just happened. */
{
    WmInfo *wmPtr = clientData;
    WmInfo *wmPtr = (WmInfo *)clientData;
    XEvent mapEvent;
    TkDisplay *dispPtr = wmPtr->winPtr->dispPtr;

    wmPtr->flags |= WM_VROOT_OFFSET_STALE;
    if (eventPtr->type == DestroyNotify) {
	Tk_ErrorHandler handler;

4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504

4505
4506
4507
4508
4509
4510
4511
4488
4489
4490
4491
4492
4493
4494

4495
4496

4497
4498
4499
4500
4501
4502
4503
4504







-


-
+







 * Side effects:
 *	Arrange for the window to be resized to satisfy the request (this
 *	happens as a when-idle action).
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static void
TopLevelReqProc(
    ClientData dummy,		/* Not used. */
    TCL_UNUSED(void *),		/* Not used. */
    Tk_Window tkwin)		/* Information about window. */
{
    TkWindow *winPtr = (TkWindow *) tkwin;
    WmInfo *wmPtr = winPtr->wmInfoPtr;

    if (wmPtr == NULL) {
	return;
4564
4565
4566
4567
4568
4569
4570
4571
4572


4573
4574
4575
4576
4577
4578
4579
4557
4558
4559
4560
4561
4562
4563


4564
4565
4566
4567
4568
4569
4570
4571
4572







-
-
+
+







 *----------------------------------------------------------------------
 */

static void
UpdateGeometryInfo(
    ClientData clientData)	/* Pointer to the window's record. */
{
    register TkWindow *winPtr = clientData;
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    TkWindow *winPtr = (TkWindow *)clientData;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    int x, y, width, height, min, max;
    unsigned long serial;

    wmPtr->flags &= ~WM_UPDATE_PENDING;

    /*
     * Compute the new size for the top-level window. See the user
4826
4827
4828
4829
4830
4831
4832
4833

4834
4835
4836
4837
4838
4839
4840
4819
4820
4821
4822
4823
4824
4825

4826
4827
4828
4829
4830
4831
4832
4833







-
+








static void
UpdateSizeHints(
    TkWindow *winPtr,
    int newWidth,
    int newHeight)
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    XSizeHints *hintsPtr;
    int maxWidth, maxHeight;

    wmPtr->flags &= ~WM_UPDATE_SIZE_HINTS;

    hintsPtr = XAllocSizeHints();
    if (hintsPtr == NULL) {
5303
5304
5305
5306
5307
5308
5309
5310

5311
5312
5313
5314
5315
5316
5317
5296
5297
5298
5299
5300
5301
5302

5303
5304
5305
5306
5307
5308
5309
5310







-
+







 */

static Tk_RestrictAction
WaitRestrictProc(
    ClientData clientData,	/* Pointer to WaitRestrictInfo structure. */
    XEvent *eventPtr)		/* Event that is about to be handled. */
{
    WaitRestrictInfo *infoPtr = clientData;
    WaitRestrictInfo *infoPtr = (WaitRestrictInfo *)clientData;

    if (eventPtr->type == ReparentNotify) {
	return TK_PROCESS_EVENT;
    }
    if (((eventPtr->xany.window != infoPtr->wmInfoPtr->wrapperPtr->window)
	    && (eventPtr->xany.window != infoPtr->wmInfoPtr->reparent))
	    || (eventPtr->xany.display != infoPtr->display)) {
5459
5460
5461
5462
5463
5464
5465
5466

5467
5468
5469
5470
5471
5472


5473
5474
5475
5476
5477
5478
5479
5452
5453
5454
5455
5456
5457
5458

5459
5460
5461
5462
5463


5464
5465
5466
5467
5468
5469
5470
5471
5472







-
+




-
-
+
+







    }

    if (!Tk_HasWrapper(tkwin)) {
	return TCL_OK; /* error?? */
    }

    if (objc > 0) {
	atoms = ckalloc(sizeof(Atom) * objc);
	atoms = (Atom *)ckalloc(sizeof(Atom) * objc);
    }

    for (n = 0; n < objc; ++n) {
	Tcl_DString ds, dsName;
	int len;
	char *name = Tcl_GetStringFromObj(objv[n], &len);
	TkSizeT len;
	char *name = TkGetStringFromObj(objv[n], &len);

	Tcl_UtfToUpper(name);
	Tcl_UtfToExternalDString(NULL, name, len, &dsName);
	Tcl_DStringInit(&ds);
	Tcl_DStringAppend(&ds, "_NET_WM_WINDOW_TYPE_", 20);
	Tcl_DStringAppend(&ds, Tcl_DStringValue(&dsName),
		Tcl_DStringLength(&dsName));
5572
5573
5574
5575
5576
5577
5578
5579

5580
5581
5582

5583
5584
5585
5586
5587
5588
5589
5565
5566
5567
5568
5569
5570
5571

5572
5573
5574

5575
5576
5577
5578
5579
5580
5581
5582







-
+


-
+







ParseGeometry(
    Tcl_Interp *interp,		/* Used for error reporting. */
    const char *string,		/* String containing new geometry. Has the
				 * standard form "=wxh+x+y". */
    TkWindow *winPtr)		/* Pointer to top-level window whose geometry
				 * is to be changed. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    int x, y, width, height, flags;
    char *end;
    register const char *p = string;
    const char *p = string;

    /*
     * The leading "=" is optional.
     */

    if (*p == '=') {
	p++;
5708
5709
5710
5711
5712
5713
5714
5715

5716
5717
5718
5719
5720
5721
5722
5701
5702
5703
5704
5705
5706
5707

5708
5709
5710
5711
5712
5713
5714
5715







-
+







void
Tk_GetRootCoords(
    Tk_Window tkwin,		/* Token for window. */
    int *xPtr,			/* Where to store x-displacement of (0,0). */
    int *yPtr)			/* Where to store y-displacement of (0,0). */
{
    int x, y;
    register TkWindow *winPtr = (TkWindow *) tkwin;
    TkWindow *winPtr = (TkWindow *) tkwin;

    /*
     * Search back through this window's parents all the way to a top-level
     * window, combining the offsets of each window within its parent.
     */

    x = y = 0;
6175
6176
6177
6178
6179
6180
6181
6182

6183
6184
6185
6186
6187
6188
6189
6168
6169
6170
6171
6172
6173
6174

6175
6176
6177
6178
6179
6180
6181
6182







-
+








void
Tk_MoveToplevelWindow(
    Tk_Window tkwin,		/* Window to move. */
    int x, int y)		/* New location for window (within parent). */
{
    TkWindow *winPtr = (TkWindow *) tkwin;
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;

    if (!(winPtr->flags & TK_TOP_LEVEL)) {
	Tcl_Panic("Tk_MoveToplevelWindow called with non-toplevel window");
    }
    wmPtr->x = x;
    wmPtr->y = y;
    wmPtr->flags |= WM_MOVE_PENDING;
6223
6224
6225
6226
6227
6228
6229
6230

6231
6232

6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
6249

6250
6251
6252
6253
6254
6255
6256
6216
6217
6218
6219
6220
6221
6222

6223
6224

6225
6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241

6242
6243
6244
6245
6246
6247
6248
6249







-
+

-
+
















-
+







 *	The WM_PROTOCOLS property gets changed for wmPtr's window.
 *
 *----------------------------------------------------------------------
 */

static void
UpdateWmProtocols(
    register WmInfo *wmPtr)	/* Information about top-level window. */
    WmInfo *wmPtr)	/* Information about top-level window. */
{
    register ProtocolHandler *protPtr;
    ProtocolHandler *protPtr;
    Atom deleteWindowAtom, pingAtom;
    int count;
    Atom *arrayPtr, *atomPtr;

    /*
     * There are only two tricky parts here. First, there could be any number
     * of atoms for the window, so count them and malloc an array to hold all
     * of their atoms. Second, we *always* want to respond to the
     * WM_DELETE_WINDOW and _NET_WM_PING protocols, even if no-one's
     * officially asked.
     */

    for (protPtr = wmPtr->protPtr, count = 2; protPtr != NULL;
	    protPtr = protPtr->nextPtr, count++) {
	/* Empty loop body; we're just counting the handlers. */
    }
    arrayPtr = ckalloc(count * sizeof(Atom));
    arrayPtr = (Atom *)ckalloc(count * sizeof(Atom));
    deleteWindowAtom = Tk_InternAtom((Tk_Window) wmPtr->winPtr,
	    "WM_DELETE_WINDOW");
    pingAtom = Tk_InternAtom((Tk_Window) wmPtr->winPtr, "_NET_WM_PING");
    arrayPtr[0] = deleteWindowAtom;
    arrayPtr[1] = pingAtom;
    for (protPtr = wmPtr->protPtr, atomPtr = &arrayPtr[1];
	    protPtr != NULL; protPtr = protPtr->nextPtr) {
6284
6285
6286
6287
6288
6289
6290
6291

6292
6293
6294
6295
6296
6297
6298
6277
6278
6279
6280
6281
6282
6283

6284
6285
6286
6287
6288
6289
6290
6291







-
+








void
TkWmProtocolEventProc(
    TkWindow *winPtr,		/* Window to which the event was sent. */
    XEvent *eventPtr)		/* X event. */
{
    WmInfo *wmPtr;
    register ProtocolHandler *protPtr;
    ProtocolHandler *protPtr;
    Atom protocol;
    int result;
    const char *protocolName;
    Tcl_Interp *interp;

    protocol = (Atom) eventPtr->xclient.data.l[0];

6433
6434
6435
6436
6437
6438
6439
6440

6441
6442
6443
6444
6445
6446
6447
6448
6449
6450
6451
6452
6453
6454
6455
6456

6457
6458
6459
6460
6461
6462
6463
6464
6465
6466
6467
6468
6469
6470
6471
6472

6473
6474

6475
6476
6477
6478
6479
6480
6481
6426
6427
6428
6429
6430
6431
6432

6433
6434
6435
6436
6437
6438
6439
6440
6441
6442
6443
6444
6445
6446
6447
6448

6449
6450
6451
6452
6453
6454
6455
6456
6457
6458
6459
6460
6461
6462
6463
6464

6465
6466

6467
6468
6469
6470
6471
6472
6473
6474







-
+















-
+















-
+

-
+







    /*
     * Map X Window ids to a TkWindow of the wrapped toplevel.
     */

    Tcl_InitHashTable(&table, TCL_ONE_WORD_KEYS);
    TkWmStackorderToplevelWrapperMap(parentPtr, parentPtr->display, &table);

    window_ptr = windows = ckalloc((table.numEntries+1) * sizeof(TkWindow *));
    window_ptr = windows = (TkWindow **)ckalloc((table.numEntries+1) * sizeof(TkWindow *));
    if (windows == NULL) {
	return NULL;
    }

    /*
     * Special cases: If zero or one toplevels were mapped there is no need to
     * call XQueryTree.
     */

    switch (table.numEntries) {
    case 0:
	windows[0] = NULL;
	goto done;
    case 1:
	hPtr = Tcl_FirstHashEntry(&table, &search);
	windows[0] = Tcl_GetHashValue(hPtr);
	windows[0] = (TkWindow *)Tcl_GetHashValue(hPtr);
	windows[1] = NULL;
	goto done;
    }

    vRoot = parentPtr->wmInfoPtr->vRoot;
    if (vRoot == None) {
	vRoot = RootWindowOfScreen(Tk_Screen((Tk_Window) parentPtr));
    }

    if (XQueryTree(parentPtr->display, vRoot, &dummy1, &dummy2,
	    &children, &numChildren) == 0) {
	ckfree(windows);
	windows = NULL;
    } else {
	for (i = 0; i < numChildren; i++) {
	    hPtr = Tcl_FindHashEntry(&table, (char *) children[i]);
	    hPtr = Tcl_FindHashEntry(&table, children[i]);
	    if (hPtr != NULL) {
		childWinPtr = Tcl_GetHashValue(hPtr);
		childWinPtr = (TkWindow *)Tcl_GetHashValue(hPtr);
		*window_ptr++ = childWinPtr;
	    }
	}

	/*
	 * ASSERT: window_ptr - windows == table.numEntries
	 * (#matched toplevel windows == #children) [Bug 1789819]
6640
6641
6642
6643
6644
6645
6646
6647

6648
6649
6650
6651
6652
6653
6654
6633
6634
6635
6636
6637
6638
6639

6640
6641
6642
6643
6644
6645
6646
6647







-
+







    }

    /*
     * Make a new bigger array and use it to reset the property. Automatically
     * add the toplevel itself as the last element of the list.
     */

    newPtr = ckalloc((count+2) * sizeof(Window));
    newPtr = (Window *)ckalloc((count+2) * sizeof(Window));
    for (i = 0; i < count; i++) {
	newPtr[i] = oldPtr[i];
    }
    if (count == 0) {
	count++;
    }
    newPtr[count-1] = winPtr->window;
6875
6876
6877
6878
6879
6880
6881
6882

6883
6884
6885
6886
6887
6888
6889
6868
6869
6870
6871
6872
6873
6874

6875
6876
6877
6878
6879
6880
6881
6882







-
+







 *
 *----------------------------------------------------------------------
 */

static void
TkSetTransientFor(Tk_Window tkwin, Tk_Window parent)
{
    if (parent == None) {
    if (parent == NULL) {
	parent = Tk_Parent(tkwin);
	while (!Tk_IsTopLevel(parent))
	    parent = Tk_Parent(parent);
    }
    /*
     * Prevent crash due to incomplete initialization, or other problems.
     * [Bugs 3554026, 3561016]
6993
6994
6995
6996
6997
6998
6999
7000

7001
7002
7003
7004
7005
7006
7007
6986
6987
6988
6989
6990
6991
6992

6993
6994
6995
6996
6997
6998
6999
7000







-
+







CreateWrapper(
    WmInfo *wmPtr)		/* Window manager information for the
				 * window. */
{
    TkWindow *winPtr, *wrapperPtr;
    Window parent;
    Tcl_HashEntry *hPtr;
    int new;
    int isNew;

    winPtr = wmPtr->winPtr;
    if (winPtr->window == None) {
	Tk_MakeWindowExist((Tk_Window) winPtr);
    }

    /*
7037
7038
7039
7040
7041
7042
7043
7044

7045
7046
7047
7048
7049
7050
7051
7030
7031
7032
7033
7034
7035
7036

7037
7038
7039
7040
7041
7042
7043
7044







-
+







	    parent, wrapperPtr->changes.x, wrapperPtr->changes.y,
	    (unsigned) wrapperPtr->changes.width,
	    (unsigned) wrapperPtr->changes.height,
	    (unsigned) wrapperPtr->changes.border_width, wrapperPtr->depth,
	    InputOutput, wrapperPtr->visual,
	    wrapperPtr->dirtyAtts|CWOverrideRedirect, &wrapperPtr->atts);
    hPtr = Tcl_CreateHashEntry(&wrapperPtr->dispPtr->winTable,
	    (char *) wrapperPtr->window, &new);
	    (char *) wrapperPtr->window, &isNew);
    Tcl_SetHashValue(hPtr, wrapperPtr);
    wrapperPtr->mainPtr = winPtr->mainPtr;
    wrapperPtr->mainPtr->refCount++;
    wrapperPtr->dirtyAtts = 0;
    wrapperPtr->dirtyChanges = 0;
    wrapperPtr->wmInfoPtr = wmPtr;

7256
7257
7258
7259
7260
7261
7262
7263

7264
7265
7266
7267
7268
7269
7270
7249
7250
7251
7252
7253
7254
7255

7256
7257
7258
7259
7260
7261
7262
7263







-
+








static void
MenubarReqProc(
    ClientData clientData,	/* Pointer to the window manager information
				 * for tkwin's toplevel. */
    Tk_Window tkwin)		/* Handle for menubar window. */
{
    WmInfo *wmPtr = clientData;
    WmInfo *wmPtr = (WmInfo *)clientData;

    wmPtr->menuHeight = Tk_ReqHeight(tkwin);
    if (wmPtr->menuHeight <= 0) {
	wmPtr->menuHeight = 1;
    }
    wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
    if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {
7291
7292
7293
7294
7295
7296
7297
7298

7299
7300
7301
7302
7303
7304
7305
7284
7285
7286
7287
7288
7289
7290

7291
7292
7293
7294
7295
7296
7297
7298







-
+







 *----------------------------------------------------------------------
 */

TkWindow *
TkpGetWrapperWindow(
    TkWindow *winPtr)		/* A toplevel window pointer. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;

    if ((winPtr == NULL) || (wmPtr == NULL)) {
	return NULL;
    }

    return wmPtr->wrapperPtr;
}
7321
7322
7323
7324
7325
7326
7327
7328

7329
7330
7331
7332
7333
7334
7335
7336
7337
7338
7339
7340
7341
7342
7343
7344
7345
7346


7347
7348
7349
7350
7351
7352
7353
7314
7315
7316
7317
7318
7319
7320

7321
7322
7323
7324
7325
7326
7327
7328
7329
7330
7331
7332
7333
7334
7335
7336
7337


7338
7339
7340
7341
7342
7343
7344
7345
7346







-
+
















-
-
+
+







 *----------------------------------------------------------------------
 */

static void
UpdateCommand(
    TkWindow *winPtr)
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    Tcl_DString cmds, ds;
    int i, *offsets;
    char **cmdArgv;

    /*
     * Translate the argv strings into the external encoding. To avoid
     * allocating lots of memory, the strings are appended to a buffer with
     * nulls between each string.
     *
     * This code is tricky because we need to pass and array of pointers to
     * XSetCommand. However, we can't compute the pointers as we go because
     * the DString buffer space could get reallocated. So, store offsets for
     * each element as we go, then compute pointers from the offsets once the
     * entire DString is done.
     */

    cmdArgv = ckalloc(sizeof(char *) * wmPtr->cmdArgc);
    offsets = ckalloc(sizeof(int) * wmPtr->cmdArgc);
    cmdArgv = (char **)ckalloc(sizeof(char *) * wmPtr->cmdArgc);
    offsets = (int *)ckalloc(sizeof(int) * wmPtr->cmdArgc);
    Tcl_DStringInit(&cmds);
    for (i = 0; i < wmPtr->cmdArgc; i++) {
	Tcl_UtfToExternalDString(NULL, wmPtr->cmdArgv[i], -1, &ds);
	offsets[i] = Tcl_DStringLength(&cmds);
	Tcl_DStringAppend(&cmds, Tcl_DStringValue(&ds),
		Tcl_DStringLength(&ds)+1);
	Tcl_DStringFree(&ds);
Changes to unix/tkUnixXId.c.
1
2
3
4
5


6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
1
2
3


4
5
6
7
8
9
10
11
12

































13
14
15
16
17
18
19



-
-
+
+







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







/*
 * tkUnixXId.c --
 *
 * Copyright (c) 1993 The Regents of the University of California.
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 * Copyright © 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.
 */

#include "tkUnixInt.h"


/*
 *----------------------------------------------------------------------
 *
 * Tk_FreeXId --
 *
 *	This function is called to indicate that an X resource identifier is
 *	now free.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The identifier is added to the stack of free identifiers for its
 *	display, so that it can be re-used.
 *
 *----------------------------------------------------------------------
 */

void
Tk_FreeXId(
    Display *display,		/* Display for which xid was allocated. */
    XID xid)			/* Identifier that is no longer in use. */
{
    /*
     * This does nothing, because the XC-MISC extension takes care of
     * freeing XIDs for us.  It has been a standard X11 extension for
     * about 15 years as of 2008.  Keith Packard and another X.org
     * developer suggested that we remove the previous code that used:
     * #define XLIB_ILLEGAL_ACCESS.
     */
}


/*
 *----------------------------------------------------------------------
 *
 * Tk_GetPixmap --
 *
 *	Same as the XCreatePixmap function except that it manages resource
Changes to win/Makefile.in.
67
68
69
70
71
72
73
74
75
76
77
78

79
80
81
82
83
84
85
67
68
69
70
71
72
73



74

75
76
77
78
79
80
81
82







-
-
-

-
+







# Directory in which to install manual entries for Tk's C library
# procedures:
MAN3_INSTALL_DIR = $(MAN_INSTALL_DIR)/man3

# Directory in which to install manual entries for the built-in Tk commands:
MANN_INSTALL_DIR = $(MAN_INSTALL_DIR)/mann

# Libraries built with optimization switches have this additional extension
TK_DBGX = @TK_DBGX@

# Directory in which to install the pkgIndex.tcl file for loadable Tk
PKG_INSTALL_DIR		= $(LIB_INSTALL_DIR)/tk$(VERSION)$(TK_DBGX)
PKG_INSTALL_DIR		= $(LIB_INSTALL_DIR)/tk$(VERSION)

# Package index file for loadable Tk
PKG_INDEX		= $(PKG_INSTALL_DIR)/pkgIndex.tcl

# The directory containing the Tcl source and header files.
TCL_SRC_DIR		= @TCL_SRC_DIR@

125
126
127
128
129
130
131


132
133
134
135
136
137

138
139
140
141
142
143
144
145



146
147
148
149
150
151
152
122
123
124
125
126
127
128
129
130
131
132
133
134
135

136
137
138
139
140
141



142
143
144
145
146
147
148
149
150
151







+
+





-
+





-
-
-
+
+
+







TCL_GENERIC_NATIVE		= $(shell $(CYGPATH) '$(TCL_GENERIC_DIR)')
TCL_PLATFORM_NATIVE		= $(shell $(CYGPATH) '$(TCL_PLATFORM_DIR)')
TCL_SRC_DIR_NATIVE		= $(shell $(CYGPATH) '$(TCL_SRC_DIR)')

DLLSUFFIX		= @DLLSUFFIX@
LIBSUFFIX		= @LIBSUFFIX@
EXESUFFIX		= @EXESUFFIX@
VER			= @TK_MAJOR_VERSION@@TK_MINOR_VERSION@
DOTVER			= @TK_MAJOR_VERSION@.@TK_MINOR_VERSION@

TK_STUB_LIB_FILE	= @TK_STUB_LIB_FILE@
TK_LIB_FILE		= @TK_LIB_FILE@
TK_DLL_FILE		= @TK_DLL_FILE@
TEST_DLL_FILE		= tktest$(VER)${DLLSUFFIX}
TEST_LIB_FILE		= @LIBPREFIX@tktest$(VER)${LIBSUFFIX}
TEST_LIB_FILE		= @LIBPREFIX@tktest$(VER)${DLLSUFFIX}${LIBSUFFIX}

SHARED_LIBRARIES 	= $(TK_DLL_FILE) $(TK_STUB_LIB_FILE)
STATIC_LIBRARIES	= $(TK_LIB_FILE)

WISH			= wish$(VER)${EXESUFFIX}
TKTEST			= tktest${EXEEXT}
CAT32			= cat32$(EXEEXT)
MAN2TCL			= man2tcl$(EXEEXT)
TKTEST			= tktest${EXESUFFIX}
CAT32			= cat32${EXESUFFIX}
MAN2TCL			= man2tcl${EXESUFFIX}

@SET_MAKE@

# Setting the VPATH variable to a list of paths will cause the
# makefile to look into these paths when resolving .c to .obj
# dependencies.

164
165
166
167
168
169
170
171

172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209


210
211
212
213
214
215
216

217
218
219
220
221
222
223
163
164
165
166
167
168
169

170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185

186
187
188
189
190
191


192
193
194
195
196
197
198
199
200
201
202
203


204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220







-
+















-






-
-












-
-
+
+







+







LDFLAGS_OPTIMIZE = @LDFLAGS_OPTIMIZE@

# To change the compiler switches, for example to change from optimization to
# debugging symbols, change the following line:
#CFLAGS		= $(CFLAGS_DEBUG)
#CFLAGS		= $(CFLAGS_OPTIMIZE)
#CFLAGS		= $(CFLAGS_DEBUG) $(CFLAGS_OPTIMIZE)
CFLAGS		= @CFLAGS@ @CFLAGS_DEFAULT@ -D_ATL_XP_TARGETING
CFLAGS		= @CFLAGS@ @CFLAGS_DEFAULT@ -D_ATL_XP_TARGETING=1 -D__USE_MINGW_ANSI_STDIO=0

# Special compiler flags to use when building man2tcl on Windows.
MAN2TCLFLAGS	= @MAN2TCLFLAGS@

AR		= @AR@
RANLIB		= @RANLIB@
CC		= @CC@
RC		= @RC@
RES		= @RES@
TK_RES		= @TK_RES@
AC_FLAGS	= @EXTRA_CFLAGS@ @DEFS@ @TCL_DEFS@
CPPFLAGS	= @CPPFLAGS@
LDFLAGS		= @LDFLAGS@ @LDFLAGS_DEFAULT@
LDFLAGS_CONSOLE	= @LDFLAGS_CONSOLE@
LDFLAGS_WINDOW	= @LDFLAGS_WINDOW@
EXEEXT		= @EXEEXT@
OBJEXT		= @OBJEXT@
STLIB_LD	= @STLIB_LD@
SHLIB_LD	= @SHLIB_LD@
SHLIB_LD_LIBS	= @SHLIB_LD_LIBS@
SHLIB_CFLAGS	= @SHLIB_CFLAGS@
SHLIB_SUFFIX	= @SHLIB_SUFFIX@
VER		= @TK_MAJOR_VERSION@@TK_MINOR_VERSION@
DOTVER		= @TK_MAJOR_VERSION@.@TK_MINOR_VERSION@
LIBS		= $(TCL_STUB_LIB_FILE) @LIBS@ @LIBS_GUI@
RMDIR		= rm -rf
MKDIR		= mkdir -p
SHELL		= @SHELL@
RM		= rm -f
COPY		= cp

BUILD_TCLSH	= @BUILD_TCLSH@

# Tk does not used deprecated Tcl constructs so it should
# compile fine with -DTCL_NO_DEPRECATED. To remove its own
# set of deprecated code uncomment the second line.
NO_DEPRECATED_FLAGS	=
#NO_DEPRECATED_FLAGS	= -DTK_NO_DEPRECATED
NO_DEPRECATED_FLAGS	= -DTCL_NO_DEPRECATED
#NO_DEPRECATED_FLAGS	= -DTCL_NO_DEPRECATED -DTK_NO_DEPRECATED

# TCL_EXE is the name of a tclsh executable that is available *BEFORE*
# running make for the first time. Certain build targets (make genstubs)
# need it to be available on the PATH. This executable should *NOT* be
# required just to do a normal build although it can be required to run
# make dist.
TCL_EXE			= @TCLSH_PROG@
WINE    		= @WINE@

CC_SWITCHES = ${CFLAGS} ${CFLAGS_WARNING} ${SHLIB_CFLAGS} \
-I"${GENERIC_DIR_NATIVE}" -I"${WIN_DIR_NATIVE}" \
-I"${XLIB_DIR_NATIVE}" -I"${BITMAP_DIR_NATIVE}" \
-I"${TCL_GENERIC_NATIVE}" -I"${TCL_PLATFORM_NATIVE}" \
${AC_FLAGS} $(NO_DEPRECATED_FLAGS) -DUSE_TCL_STUBS

261
262
263
264
265
266
267

268
269
270
271
272
273
274
275
276
277

278
279
280
281
282
283
284
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283







+










+







	tkWinColor.$(OBJEXT) \
	tkWinConfig.$(OBJEXT) \
	tkWinCursor.$(OBJEXT) \
	tkWinDialog.$(OBJEXT) \
	tkWinDraw.$(OBJEXT) \
	tkWinEmbed.$(OBJEXT) \
	tkWinFont.$(OBJEXT) \
	tkWinIco.$(OBJEXT) \
	tkWinImage.$(OBJEXT) \
	tkWinInit.$(OBJEXT) \
	tkWinKey.$(OBJEXT) \
	tkWinMenu.$(OBJEXT) \
	tkWinPixmap.$(OBJEXT) \
	tkWinPointer.$(OBJEXT) \
	tkWinRegion.$(OBJEXT) \
	tkWinScrlbr.$(OBJEXT) \
	tkWinSend.$(OBJEXT) \
	tkWinSendCom.$(OBJEXT) \
	tkWinSysTray.$(OBJEXT) \
	tkWinWindow.$(OBJEXT) \
	tkWinWm.$(OBJEXT) \
	tkWinX.$(OBJEXT) \
	stubs.$(OBJEXT) \
	tk3d.$(OBJEXT) \
	tkArgv.$(OBJEXT) \
	tkAtom.$(OBJEXT) \
311
312
313
314
315
316
317

318
319
320

321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336

337
338
339
340
341
342
343
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345







+



+
















+







	tkGC.$(OBJEXT) \
	tkGeometry.$(OBJEXT) \
	tkGet.$(OBJEXT) \
	tkGrab.$(OBJEXT) \
	tkGrid.$(OBJEXT) \
	tkImage.$(OBJEXT) \
	tkImgBmap.$(OBJEXT) \
	tkImgListFormat.$(OBJEXT) \
	tkImgGIF.$(OBJEXT) \
	tkImgPNG.$(OBJEXT) \
	tkImgPPM.$(OBJEXT) \
	tkImgSVGnano.$(OBJEXT) \
	tkImgPhoto.$(OBJEXT) \
	tkImgPhInstance.$(OBJEXT) \
	tkImgUtil.$(OBJEXT) \
	tkListbox.$(OBJEXT) \
	tkMacWinMenu.$(OBJEXT) \
	tkMain.$(OBJEXT) \
	tkMain2.$(OBJEXT) \
	tkMenu.$(OBJEXT) \
	tkMenubutton.$(OBJEXT) \
	tkMenuDraw.$(OBJEXT) \
	tkMessage.$(OBJEXT) \
	tkPanedWindow.$(OBJEXT) \
	tkObj.$(OBJEXT) \
	tkOldConfig.$(OBJEXT) \
	tkOption.$(OBJEXT) \
	tkPack.$(OBJEXT) \
	tkPkgConfig.$(OBJEXT) \
	tkPlace.$(OBJEXT) \
	tkPointer.$(OBJEXT) \
	tkRectOval.$(OBJEXT) \
	tkScale.$(OBJEXT) \
	tkScrollbar.$(OBJEXT) \
	tkSelect.$(OBJEXT) \
	tkStyle.$(OBJEXT) \
433
434
435
436
437
438
439
440
441


442
443
444
445


446
447
448

449
450
451
452
453

454
455
456

457
458
459
460
461
462
463
435
436
437
438
439
440
441


442
443
444
445


446
447
448
449

450
451
452
453
454

455
456
457

458
459
460
461
462
463
464
465







-
-
+
+


-
-
+
+


-
+




-
+


-
+







# Specifying TESTFLAGS on the command line is the standard way to pass
# args to tcltest, ie:
#	% make test TESTFLAGS="-verbose bps -file fileName.test"

test: test-classic test-ttk

test-classic: binaries $(TKTEST) $(TEST_DLL_FILE) $(CAT32)
	$(SHELL_ENV) ./$(TKTEST) "$(ROOT_DIR_NATIVE)/tests/all.tcl" \
	$(TESTFLAGS) | ./$(CAT32)
	$(SHELL_ENV) $(WINE) ./$(TKTEST) "$(ROOT_DIR_NATIVE)/tests/all.tcl" \
	$(TESTFLAGS) | $(WINE) ./$(CAT32)

test-ttk: binaries $(TKTEST) $(TEST_DLL_FILE) $(CAT32)
	$(SHELL_ENV) ./$(TKTEST) "$(ROOT_DIR_NATIVE)/tests/ttk/all.tcl" \
	$(TESTFLAGS) | ./$(CAT32)
	$(SHELL_ENV) $(WINE) ./$(TKTEST) "$(ROOT_DIR_NATIVE)/tests/ttk/all.tcl" \
	$(TESTFLAGS) | $(WINE) ./$(CAT32)

runtest: binaries $(TKTEST) $(TEST_DLL_FILE)
	$(SHELL_ENV) ./$(TKTEST) $(TESTFLAGS) $(SCRIPT)
	$(SHELL_ENV) $(WINE) ./$(TKTEST) $(TESTFLAGS) $(SCRIPT)

# This target can be used to run wish from the build directory
# via `make shell` or `make shell SCRIPT=foo.tcl`
shell: binaries
	$(SHELL_ENV) ./$(WISH) $(SCRIPT)
	$(SHELL_ENV) $(WINE) ./$(WISH) $(SCRIPT)

demo: $(WISH)
	$(SHELL_ENV) ./$(WISH) $(ROOT_DIR)/library/demos/widget
	$(SHELL_ENV) $(WINE) ./$(WISH) $(ROOT_DIR)/library/demos/widget

# This target can be used to run wish inside either gdb or insight
gdb: binaries
	@echo "set env TCL_LIBRARY=$(TCL_SRC_DIR_NATIVE)/library" > gdb.run
	@echo "set env TK_LIBRARY=$(ROOT_DIR_NATIVE)/library" >> gdb.run
	PATH="$(TCL_BIN_DIR):$(PATH)"; export PATH; \
	gdb ./$(WISH) --command=gdb.run
481
482
483
484
485
486
487
488

489
490
491

492
493

494

495
496
497
498
499
500
501
483
484
485
486
487
488
489

490
491
492

493
494

495
496
497
498
499
500
501
502
503
504







-
+


-
+

-
+

+







		echo "Installing $$i to $(BIN_INSTALL_DIR)/"; \
		$(COPY) $$i "$(BIN_INSTALL_DIR)"; \
	    fi; \
	    done
	@echo "Creating package index $(PKG_INDEX)";
	@$(RM) $(PKG_INDEX);
	@(\
	echo "if {[catch {package present Tcl 8.6.0}]} return";\
	echo "if {[catch {package present Tcl 8.6-}]} return";\
	echo "if {(\$$::tcl_platform(platform) eq \"unix\") && ([info exists ::env(DISPLAY)]";\
	echo "	|| ([info exists ::argv] && (\"-display\" in \$$::argv)))} {";\
	echo "    package ifneeded Tk $(VERSION)$(PATCH_LEVEL) [list load [file normalize [file join \$$dir .. .. bin libtk$(VERSION).dll]] Tk]";\
	echo "    package ifneeded tk $(VERSION)$(PATCH_LEVEL) [list load [file normalize [file join \$$dir .. .. bin libtk$(VERSION).dll]]]";\
	echo "} else {";\
	echo "    package ifneeded Tk $(VERSION)$(PATCH_LEVEL) [list load [file normalize [file join \$$dir .. .. bin $(TK_DLL_FILE)]] Tk]";\
	echo "    package ifneeded tk $(VERSION)$(PATCH_LEVEL) [list load [file normalize [file join \$$dir .. .. bin $(TK_DLL_FILE)]]]";\
	echo "}";\
	echo "package ifneeded Tk $(VERSION)$(PATCH_LEVEL) [list package require -exact tk $(VERSION)$(PATCH_LEVEL)]";\
	) > $(PKG_INDEX);
	@for i in tkConfig.sh $(TK_LIB_FILE) $(TK_STUB_LIB_FILE); \
	    do \
	    if [ -f $$i ]; then \
		echo "Installing $$i to $(LIB_INSTALL_DIR)/"; \
		$(COPY) $$i "$(LIB_INSTALL_DIR)"; \
	    fi; \
702
703
704
705
706
707
708
709

710
711
712
713
714
715
716
705
706
707
708
709
710
711

712
713
714
715
716
717
718
719







-
+








.rc.$(RES):
	$(RC) @RC_OUT@ $@ @RC_TYPE@ @RC_DEFINES@ @RC_INCLUDE@ "$(GENERIC_DIR_NATIVE)" @RC_INCLUDE@ "$(TCL_GENERIC_NATIVE)" @RC_INCLUDE@ "$(RC_DIR_NATIVE)" @DEPARG@

depend:

cleanhelp:
	$(RM) *.hlp *.cnt *.hpj *.GID *.rtf man2tcl${EXEEXT}
	$(RM) *.hlp *.cnt *.hpj *.GID *.rtf man2tcl.exe

clean: cleanhelp
	$(RM) *.lib *.a *.exp *.dll *.res *.${OBJEXT} *~ \#* TAGS a.out
	$(RM) $(WISH) $(TKTEST) $(CAT32)
	$(RM) *.pch *.ilk *.pdb

distclean: clean
731
732
733
734
735
736
737
738

739
740
741
742
743
744
745
734
735
736
737
738
739
740

741
742
743
744
745
746
747
748







-
+







	@echo "This warning can be safely ignored, do not report as a bug!"

genstubs:
	$(TCL_EXE) "$(TCL_TOOL_DIR)/genStubs.tcl" \
	    "$(GENERIC_DIR_NATIVE)" \
	    "$(GENERIC_DIR_NATIVE)/tk.decls" \
	    "$(GENERIC_DIR_NATIVE)/tkInt.decls"
	$(TCL_EXE) "$(TTK_DIR)/ttkGenStubs.tcl" \
	$(TCL_EXE) "$(TCL_TOOL_DIR)/genStubs.tcl" \
	    "$(TTK_DIR)" \
	    "$(TTK_DIR)/ttk.decls"

#
# The list of all the targets that do not correspond to real files. This stops
# 'make' from getting confused when someone makes an error in a rule.
#
Changes to win/README.
1

2
3
4
5
6
7
8

1
2
3
4
5
6
7
8
-
+







Tk 8.6 for Windows
Tk 8.7 for Windows

Originally by Scott Stanton while at Sun Microsystems Labs

This is the directory where you configure and compile the Windows
version of Tk.  This directory also contains source files for Tk
that are specific to Microsoft Windows.  The rest of this file
contains information specific to the Windows version of Tk.
Changes to win/configure.
1
2
3

4

5



6
7
8
9
10



11
12
13





14
15
16

17
18


19
20



21
22
23

24
25
26
27


28
29
30
31
32
33













34
35
36
37





38
39
40
41
42











































































































































43




























44
45








































46

























47













































































































































48


49

50
51
52


53
54
55
56
57
58

59
60
61
62
63





64
65
66

67
68
69

70
71
72
73
74
75
76
77
78















79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101


102
103
104


105
106
107
108





109
110
111

112
113
114
115
116



117
118
119
120
121
122
123

124
125
126
127
128
129
130
131

132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169


170
171

172
173
174
175


176
177




178
179
180
181


182
183
184
185
186






187
188
189
190








191
192
193
194
195




196
197
198


199
200
201

202
203
204
205

206
207
208
209
210
211
212
213
214
215
216























217
218
219

220
221
222
223
224

225

226
227
228
229
230
231
232
233
234
235
236
237
238
239

240
241
242

243
244
245

246
247
248
249
250
251
252
253
254

255

256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272






273
274
275
276
277
278
279



280
281
282


283
284
285


286
287
288
289
290
291
292

293
294
295
296




297
298

299
300
301
302
303
304
305





306
307
308

309
310
311

312












































































































































313


















314
315
316
317


318
319
320
321
322
323
324
1
2

3
4
5

6
7
8
9
10



11
12
13
14


15
16
17
18
19
20
21

22
23
24
25
26


27
28
29



30




31
32

33
34
35


36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57





58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225


226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291

292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435

436
437


438
439
440
441
442
443
444

445
446
447
448
449
450
451
452
453
454
455
456


457
458
459

460









461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482












483



484
485



486
487




488
489
490
491
492



493





494
495
496







497








498






































499
500
501

502

503


504
505

506
507
508
509
510
511
512


513
514
515
516
517
518
519
520
521
522
523
524
525




526
527
528
529
530
531
532
533

534
535


536
537
538
539



540
541
542
543

544




545











546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570

571
572
573
574
575
576
577

578
579
580
581
582
583
584
585
586






587



588
589
590

591
592
593
594


595
596
597
598
599
600
601
602
603
604
605

606





607





608
609
610
611
612
613
614
615
616
617



618
619
620
621


622
623
624


625
626





627

628




629
630
631
632
633

634
635
636





637
638
639
640
641

642

643
644
645
646
647

648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819


-
+

+
-
+
+
+


-
-
-
+
+
+

-
-
+
+
+
+
+


-
+


+
+
-
-
+
+
+
-
-
-
+
-
-
-
-
+
+
-



-
-
+
+
+
+
+
+
+
+
+
+
+
+
+




+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
-
+

-
-
+
+





-
+





+
+
+
+
+

-
-
+


-
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







-
-
-
-
-
-
-
-
-
-
-
-

-
-
-
+
+
-
-
-
+
+
-
-
-
-
+
+
+
+
+
-
-
-
+
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+

-
+
-

-
-
+
+
-

+
+
+
+


-
-
+
+





+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
-


-
-
+
+
+
+
-
-
-
+
+


-
+
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
+





+
-
+








-
-
-
-
-
-
+
-
-
-
+


-
+



-
-




+

+




-

-
-
-
-
-

-
-
-
-
-
+
+
+
+
+
+




-
-
-
+
+
+

-
-
+
+

-
-
+
+
-
-
-
-
-

-
+
-
-
-
-
+
+
+
+

-
+


-
-
-
-
-
+
+
+
+
+
-

-
+



+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




+
+







#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.59.
# Generated by GNU Autoconf 2.70.
#
#
# Copyright (C) 2003 Free Software Foundation, Inc.
# Copyright (C) 1992-1996, 1998-2017, 2020 Free Software Foundation, Inc.
#
#
# This configure script is free software; the Free Software Foundation
# gives unlimited permission to copy, distribute and modify it.
## --------------------- ##
## M4sh Initialization.  ##
## --------------------- ##
## -------------------- ##
## M4sh Initialization. ##
## -------------------- ##

# Be Bourne compatible
if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
# Be more Bourne compatible
DUALCASE=1; export DUALCASE # for MKS sh
as_nop=:
if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
then :
  emulate sh
  NULLCMD=:
  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
  # is contrary to our usage.  Disable this feature.
  alias -g '${1+"$@"}'='"$@"'
  setopt NO_GLOB_SUBST
else $as_nop
elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
  set -o posix
  case `(set -o) 2>/dev/null` in #(
  *posix*) :
    set -o posix ;; #(
fi
DUALCASE=1; export DUALCASE # for MKS sh

  *) :
# Support unset when possible.
if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
  as_unset=unset
else
     ;;
esac
  as_unset=false
fi


# Work around bugs in pre-3.0 UWIN ksh.
$as_unset ENV MAIL MAILPATH

# Reset variables that may have inherited troublesome values from
# the environment.

# IFS needs to be set, to space, tab, and newline, in precisely that order.
# (If _AS_PATH_WALK were called with IFS unset, it would have the
# side effect of setting IFS to empty, thus disabling word splitting.)
# Quoting is to prevent editors from complaining about space-tab.
as_nl='
'
export as_nl
IFS=" ""	$as_nl"

PS1='$ '
PS2='> '
PS4='+ '

# Ensure predictable behavior from utilities with locale-dependent output.
LC_ALL=C
export LC_ALL
LANGUAGE=C
export LANGUAGE
# NLS nuisances.
for as_var in \
  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
  LC_TELEPHONE LC_TIME

# We cannot yet rely on "unset" to work, but we need these variables
# to be unset--not just set to an empty or harmless value--now, to
# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh).  This construct
# also avoids known problems related to "unset" and subshell syntax
# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
do eval test \${$as_var+y} \
  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
done

# Ensure that fds 0, 1, and 2 are open.
if (exec 3>&0) 2>/dev/null; then :; else exec 0</dev/null; fi
if (exec 3>&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
if (exec 3>&2)            ; then :; else exec 2>/dev/null; fi

# The user is always right.
if ${PATH_SEPARATOR+false} :; then
  PATH_SEPARATOR=:
  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
      PATH_SEPARATOR=';'
  }
fi


# Find who we are.  Look in the path if we contain no directory separator.
as_myself=
case $0 in #((
  *[\\/]* ) as_myself=$0 ;;
  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    test -r "$as_dir$0" && as_myself=$as_dir$0 && break
  done
IFS=$as_save_IFS

     ;;
esac
# We did not find ourselves, most probably we were run as `sh COMMAND'
# in which case we are not to be found in the path.
if test "x$as_myself" = x; then
  as_myself=$0
fi
if test ! -f "$as_myself"; then
  printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
  exit 1
fi


# Use a proper internal environment variable to ensure we don't fall
  # into an infinite loop, continuously re-executing ourselves.
  if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
    _as_can_reexec=no; export _as_can_reexec;
    # We cannot yet assume a decent shell, so we have to provide a
# neutralization value for shells without unset; and this also
# works around shells that cannot unset nonexistent variables.
# Preserve -v and -x to the replacement shell.
BASH_ENV=/dev/null
ENV=/dev/null
(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
case $- in # ((((
  *v*x* | *x*v* ) as_opts=-vx ;;
  *v* ) as_opts=-v ;;
  *x* ) as_opts=-x ;;
  * ) as_opts= ;;
esac
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
# Admittedly, this is quite paranoid, since all the known shells bail
# out after a failed `exec'.
printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
exit 255
  fi
  # We don't want this to propagate to other subprocesses.
          { _as_can_reexec=; unset _as_can_reexec;}
if test "x$CONFIG_SHELL" = x; then
  as_bourne_compatible="as_nop=:
if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
then :
  emulate sh
  NULLCMD=:
  # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
  # is contrary to our usage.  Disable this feature.
  alias -g '\${1+\"\$@\"}'='\"\$@\"'
  setopt NO_GLOB_SUBST
else \$as_nop
  case \`(set -o) 2>/dev/null\` in #(
  *posix*) :
    set -o posix ;; #(
  *) :
     ;;
esac
fi
"
  as_required="as_fn_return () { (exit \$1); }
as_fn_success () { as_fn_return 0; }
as_fn_failure () { as_fn_return 1; }
as_fn_ret_success () { return 0; }
as_fn_ret_failure () { return 1; }

exitcode=0
as_fn_success || { exitcode=1; echo as_fn_success failed.; }
as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
if ( set x; as_fn_ret_success y && test x = \"\$1\" )
then :

else \$as_nop
  exitcode=1; echo positional parameters were not saved.
fi
test x\$exitcode = x0 || exit 1
blah=\$(echo \$(echo blah))
test x\"\$blah\" = xblah || exit 1
test -x / || exit 1"
  as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
  as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
  eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
  test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
test \$(( 1 + 1 )) = 2 || exit 1"
  if (eval "$as_required") 2>/dev/null
then :
  as_have_required=yes
else $as_nop
  as_have_required=no
fi
  if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null
then :

else $as_nop
  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
as_found=false
for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
  as_found=:
  case $as_dir in #(
	 /*)
	   for as_base in sh bash ksh sh5; do
	     # Try only shells that exist, to save several forks.
	     as_shell=$as_dir$as_base
	     if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
		    as_run=a "$as_shell" -c "$as_bourne_compatible""$as_required" 2>/dev/null
then :
  CONFIG_SHELL=$as_shell as_have_required=yes
		   if as_run=a "$as_shell" -c "$as_bourne_compatible""$as_suggested" 2>/dev/null
then :
  break 2
fi
fi
	   done;;
       esac
  as_found=false
done
IFS=$as_save_IFS
if $as_found
then :
  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
    eval $as_var=C; export $as_var

else $as_nop
  if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
	      as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null
then :
  CONFIG_SHELL=$SHELL as_have_required=yes
fi
fi


      if test "x$CONFIG_SHELL" != x
then :
  export CONFIG_SHELL
             # We cannot yet assume a decent shell, so we have to provide a
# neutralization value for shells without unset; and this also
# works around shells that cannot unset nonexistent variables.
# Preserve -v and -x to the replacement shell.
BASH_ENV=/dev/null
ENV=/dev/null
(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
case $- in # ((((
  *v*x* | *x*v* ) as_opts=-vx ;;
  *v* ) as_opts=-v ;;
  *x* ) as_opts=-x ;;
  * ) as_opts= ;;
esac
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
# Admittedly, this is quite paranoid, since all the known shells bail
# out after a failed `exec'.
printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
exit 255
fi

    if test x$as_have_required = xno
then :
  printf "%s\n" "$0: This script requires a shell more modern than all"
  printf "%s\n" "$0: the shells that I found on your system."
  if test ${ZSH_VERSION+y} ; then
    printf "%s\n" "$0: In particular, zsh $ZSH_VERSION has bugs and should"
    printf "%s\n" "$0: be upgraded to zsh 4.3.4 or later."
  else
    printf "%s\n" "$0: Please tell [email protected] about your system,
$0: including any error possibly output before this
$0: message. Then install a modern shell, or manually run
$0: the script under such a shell if you do have one."
  fi
  exit 1
fi
fi
fi
SHELL=${CONFIG_SHELL-/bin/sh}
export SHELL
# Unset more variables known to interfere with behavior of common tools.
CLICOLOR_FORCE= GREP_OPTIONS=
unset CLICOLOR_FORCE GREP_OPTIONS

## --------------------- ##
## M4sh Shell Functions. ##
## --------------------- ##
# as_fn_unset VAR
# ---------------
# Portably unset VAR.
as_fn_unset ()
{
  { eval $1=; unset $1;}
}
    $as_unset $as_var
as_unset=as_fn_unset


# as_fn_set_status STATUS
# -----------------------
# Set $? to STATUS, without forking.
as_fn_set_status ()
{
  return $1
} # as_fn_set_status

# as_fn_exit STATUS
# -----------------
# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
as_fn_exit ()
{
  set +e
  as_fn_set_status $1
  exit $1
} # as_fn_exit
# as_fn_nop
# ---------
# Do nothing but, unlike ":", preserve the value of $?.
as_fn_nop ()
{
  return $?
}
as_nop=as_fn_nop

# as_fn_mkdir_p
# -------------
# Create "$as_dir" as a directory, including parents if necessary.
as_fn_mkdir_p ()
{

  case $as_dir in #(
  -*) as_dir=./$as_dir;;
  esac
  test -d "$as_dir" || eval $as_mkdir_p || {
    as_dirs=
    while :; do
      case $as_dir in #(
      *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
      *) as_qdir=$as_dir;;
      esac
      as_dirs="'$as_qdir' $as_dirs"
      as_dir=`$as_dirname -- "$as_dir" ||
$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
	 X"$as_dir" : 'X\(//\)[^/]' \| \
	 X"$as_dir" : 'X\(//\)$' \| \
	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
printf "%s\n" X"$as_dir" |
    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
	    s//\1/
	    q
	  }
	  /^X\(\/\/\)[^/].*/{
	    s//\1/
	    q
	  }
	  /^X\(\/\/\)$/{
	    s//\1/
	    q
	  }
	  /^X\(\/\).*/{
	    s//\1/
	    q
	  }
	  s/.*/./; q'`
      test -d "$as_dir" && break
    done
    test -z "$as_dirs" || eval "mkdir $as_dirs"
  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"


} # as_fn_mkdir_p

# as_fn_executable_p FILE
# -----------------------
# Test if FILE is an executable regular file.
as_fn_executable_p ()
{
  test -f "$1" && test -x "$1"
} # as_fn_executable_p
# as_fn_append VAR VALUE
# ----------------------
# Append the text in VALUE to the end of the definition contained in VAR. Take
# advantage of any shell optimizations that allow amortized linear growth over
# repeated appends, instead of the typical quadratic growth present in naive
# implementations.
if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
then :
  eval 'as_fn_append ()
  {
    eval $1+=\$2
  }'
else $as_nop
  as_fn_append ()
  {
    eval $1=\$$1\$2
  }
fi # as_fn_append

# as_fn_arith ARG...
# ------------------
# Perform arithmetic evaluation on the ARGs, and store the result in the
# global $as_val. Take advantage of shells that can avoid forks. The arguments
# must be portable across $(()) and expr.
if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
then :
  eval 'as_fn_arith ()
  {
    as_val=$(( $* ))
  }'
else $as_nop
  as_fn_arith ()
  {
    as_val=`expr "$@" || test $? -eq 1`
  }
fi # as_fn_arith

# as_fn_nop
# ---------
# Do nothing but, unlike ":", preserve the value of $?.
as_fn_nop ()
{
  return $?
}
as_nop=as_fn_nop

# as_fn_error STATUS ERROR [LINENO LOG_FD]
# ----------------------------------------
# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
# script with STATUS, using 1 if that was 0.
as_fn_error ()
{
  as_status=$1; test $as_status -eq 0 && as_status=1
  if test "$4"; then
    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
  fi
  printf "%s\n" "$as_me: error: $2" >&2
  as_fn_exit $as_status
done
} # as_fn_error

# Required to use basename.
if expr a : '\(a\)' >/dev/null 2>&1; then
if expr a : '\(a\)' >/dev/null 2>&1 &&
   test "X`expr 00001 : '.*\(...\)'`" = X001; then
  as_expr=expr
else
  as_expr=false
fi

if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
  as_basename=basename
else
  as_basename=false
fi

if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
  as_dirname=dirname
else
  as_dirname=false
fi

# Name of the executable.
as_me=`$as_basename "$0" ||
as_me=`$as_basename -- "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
	 X"$0" : 'X\(//\)$' \| \
	 X"$0" : 'X\(/\)$' \| \
	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
	 .     : '\(.\)' 2>/dev/null ||
echo X/"$0" |
    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
  	  /^X\/\(\/\/\)$/{ s//\1/; q; }
  	  /^X\/\(\/\).*/{ s//\1/; q; }
  	  s/.*/./; q'`


# PATH needs CR, and LINENO needs CR and PATH.
printf "%s\n" X/"$0" |
    sed '/^.*\/\([^/][^/]*\)\/*$/{
	    s//\1/
	    q
	  }
	  /^X\/\(\/\/\)$/{
	    s//\1/
	    q
	  }
	  /^X\/\(\/\).*/{
	    s//\1/
	    q
	  }
	  s/.*/./; q'`

# Avoid depending upon Character Ranges.
as_cr_letters='abcdefghijklmnopqrstuvwxyz'
as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
as_cr_Letters=$as_cr_letters$as_cr_LETTERS
as_cr_digits='0123456789'
as_cr_alnum=$as_cr_Letters$as_cr_digits

# The user is always right.
if test "${PATH_SEPARATOR+set}" != set; then
  echo "#! /bin/sh" >conf$$.sh
  echo  "exit 0"   >>conf$$.sh
  chmod +x conf$$.sh
  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
    PATH_SEPARATOR=';'
  else
    PATH_SEPARATOR=:
  fi
  rm -f conf$$.sh
fi


  as_lineno_1=$LINENO
  as_lineno_2=$LINENO
  as_lineno_1=$LINENO as_lineno_1a=$LINENO
  as_lineno_2=$LINENO as_lineno_2a=$LINENO
  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
  test "x$as_lineno_1" != "x$as_lineno_2" &&
  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
  eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
  test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
  # Find who we are.  Look in the path if we contain no path at all
  # relative or not.
  case $0 in
    *[\\/]* ) as_myself=$0 ;;
  # Blame Lee E. McMahon (1931-1989) for sed's syntax.  :-)
  sed -n '
    p
    /[$]LINENO/=
  ' <$as_myself |
    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
    sed '
  IFS=$as_save_IFS
  test -z "$as_dir" && as_dir=.
  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
done

      s/[$]LINENO.*/&-/
      t lineno
      b
       ;;
  esac
  # We did not find ourselves, most probably we were run as `sh COMMAND'
  # in which case we are not to be found in the path.
  if test "x$as_myself" = x; then
    as_myself=$0
  fi
      :lineno
  if test ! -f "$as_myself"; then
    { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2
   { (exit 1); exit 1; }; }
  fi
  case $CONFIG_SHELL in
  '')
    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
      N
do
  IFS=$as_save_IFS
  test -z "$as_dir" && as_dir=.
  for as_base in sh bash ksh sh5; do
	 case $as_dir in
	 /*)
	   if ("$as_dir/$as_base" -c '
  as_lineno_1=$LINENO
  as_lineno_2=$LINENO
  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
  test "x$as_lineno_1" != "x$as_lineno_2" &&
  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
	     $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
	     $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
	     CONFIG_SHELL=$as_dir/$as_base
	     export CONFIG_SHELL
	     exec "$CONFIG_SHELL" "$0" ${1+"$@"}
	   fi;;
	 esac
       done
done
;;
  esac

  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
  # uniformly replaced by the line number.  The first 'sed' inserts a
  # line-number line before each line; the second 'sed' does the real
  # work.  The second script uses 'N' to pair each line-number line
  # with the numbered line, and appends trailing '-' during
  # substitution so that $LINENO is not a special case at line end.
  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
  sed '=' <$as_myself |
    sed '
      N
      s,$,-,
      : loop
      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
      :loop
      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
      t loop
      s,-$,,
      s/-\n.*//
      s,^['$as_cr_digits']*\n,,
    ' >$as_me.lineno &&
  chmod +x $as_me.lineno ||
    { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
  chmod +x "$as_me.lineno" ||
    { printf "%s\n" "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
   { (exit 1); exit 1; }; }

  # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
  # already done that, so ensure we don't try to do so again and fall
  # in an infinite loop.  This has already happened in practice.
  _as_can_reexec=no; export _as_can_reexec
  # Don't try to exec as it changes $[0], causing all sort of problems
  # (the dirname of $[0] is not the place where we might find the
  # original and so on.  Autoconf is especially sensible to this).
  . ./$as_me.lineno
  # original and so on.  Autoconf is especially sensitive to this).
  . "./$as_me.lineno"
  # Exit status is that of the last command.
  exit
}


# Determine whether it's possible to make 'echo' print without a newline.
# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
# for compatibility with existing Makefiles.
ECHO_C= ECHO_N= ECHO_T=
case `echo -n x` in #(((((
-n*)
case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
  *c*,-n*) ECHO_N= ECHO_C='
' ECHO_T='	' ;;
  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
  case `echo 'xy\c'` in
  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
  xy)  ECHO_C='\c';;
  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
       ECHO_T='	';;
  esac;;
*)
  ECHO_N='-n';;
  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
esac

if expr a : '\(a\)' >/dev/null 2>&1; then
  as_expr=expr
# For backward compatibility with old third-party macros, we provide
# the shell variables $as_echo and $as_echo_n.  New code should use
# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
as_echo='printf %s\n'
else
  as_expr=false
fi
as_echo_n='printf %s'


rm -f conf$$ conf$$.exe conf$$.file
echo >conf$$.file
if test -d conf$$.dir; then
if ln -s conf$$.file conf$$ 2>/dev/null; then
  # We could just check for DJGPP; but this test a) works b) is more generic
  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
  if test -f conf$$.exe; then
  rm -f conf$$.dir/conf$$.file
    # Don't use ln at all; we don't have any links
    as_ln_s='cp -p'
  else
    as_ln_s='ln -s'
  fi
elif ln conf$$.file conf$$ 2>/dev/null; then
  as_ln_s=ln
else
  as_ln_s='cp -p'
fi
rm -f conf$$ conf$$.exe conf$$.file
else
  rm -f conf$$.dir
  mkdir conf$$.dir 2>/dev/null
fi
if (echo >conf$$.file) 2>/dev/null; then
  if ln -s conf$$.file conf$$ 2>/dev/null; then
    as_ln_s='ln -s'
    # ... but there are two gotchas:
    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
    # In both cases, we have to default to `cp -pR'.
    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
      as_ln_s='cp -pR'
  elif ln conf$$.file conf$$ 2>/dev/null; then
    as_ln_s=ln
  else
    as_ln_s='cp -pR'
  fi
else
  as_ln_s='cp -pR'
fi
rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
rmdir conf$$.dir 2>/dev/null

if mkdir -p . 2>/dev/null; then
  as_mkdir_p=:
  as_mkdir_p='mkdir -p "$as_dir"'
else
  test -d ./-p && rmdir ./-p
  as_mkdir_p=false
fi

as_test_x='test -x'
as_executable_p="test -f"
as_executable_p=as_fn_executable_p

# Sed expression to map a string onto a valid CPP name.
as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"

# Sed expression to map a string onto a valid variable name.
as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"


# IFS
# We need space, tab and new line, in precisely that order.
as_nl='
'
IFS=" 	$as_nl"

test -n "$DJDIR" || exec 7<&0 </dev/null
# CDPATH.
$as_unset CDPATH

exec 6>&1

# Name of the host.
# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
# so uname gets run too.
ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`

exec 6>&1

#
# Initializations.
#
ac_default_prefix=/usr/local
ac_clean_files=
ac_config_libobj_dir=.
LIBOBJS=
cross_compiling=no
subdirs=
MFLAGS=
MAKEFLAGS=
SHELL=${CONFIG_SHELL-/bin/sh}

# Maximum number of lines to put in a shell here document.
# This variable seems obsolete.  It should probably be removed, and
# only ac_max_sed_lines should be used.
: ${ac_max_here_lines=38}

# Identity of this package.
PACKAGE_NAME=
PACKAGE_TARNAME=
PACKAGE_VERSION=
PACKAGE_STRING=
PACKAGE_BUGREPORT=
PACKAGE_NAME=''
PACKAGE_TARNAME=''
PACKAGE_VERSION=''
PACKAGE_STRING=''
PACKAGE_BUGREPORT=''
PACKAGE_URL=''

ac_unique_file="../generic/tk.h"
# Factoring default headers for most tests.
ac_includes_default="\
#include <stdio.h>
#if HAVE_SYS_TYPES_H
# include <sys/types.h>
#include <stddef.h>
#ifdef HAVE_STDIO_H
# include <stdio.h>
#endif
#if HAVE_SYS_STAT_H
# include <sys/stat.h>
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#endif
#if STDC_HEADERS
# include <stdlib.h>
#ifdef HAVE_STRING_H
# include <string.h>
# include <stddef.h>
#else
# if HAVE_STDLIB_H
#  include <stdlib.h>
# endif
#endif
#if HAVE_STRING_H
#ifdef HAVE_INTTYPES_H
# if !STDC_HEADERS && HAVE_MEMORY_H
#  include <memory.h>
# endif
# include <string.h>
# include <inttypes.h>
#endif
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
#if HAVE_STRINGS_H
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#if HAVE_INTTYPES_H
# include <inttypes.h>
#else
# if HAVE_STDINT_H
#  include <stdint.h>
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
# endif
#endif
#if HAVE_UNISTD_H
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif"

ac_header_c_list=
ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP EGREP AR ac_ct_AR RANLIB ac_ct_RANLIB RC ac_ct_RC SET_MAKE TCL_THREADS TCL_VERSION TCL_BIN_DIR TCL_SRC_DIR TCL_LIB_FILE TCL_LIB_FLAG TCL_LIB_SPEC TCL_STUB_LIB_FILE TCL_STUB_LIB_FLAG TCL_STUB_LIB_SPEC TCL_DEFS CYGPATH CELIB_DIR DL_LIBS CFLAGS_DEBUG CFLAGS_OPTIMIZE CFLAGS_WARNING MAN2TCLFLAGS CFLAGS_DEFAULT LDFLAGS_DEFAULT VC_MANIFEST_EMBED_DLL VC_MANIFEST_EMBED_EXE BUILD_TCLSH TCLSH_PROG TK_WIN_VERSION MACHINE TK_VERSION TK_MAJOR_VERSION TK_MINOR_VERSION TK_PATCH_LEVEL TK_DBGX TK_LIB_FILE TK_DLL_FILE TK_STUB_LIB_FILE TK_STUB_LIB_FLAG TK_BUILD_STUB_LIB_SPEC TK_SRC_DIR TK_BIN_DIR TCL_MAJOR_VERSION TCL_MINOR_VERSION TCL_PATCH_LEVEL TCL_DBGX CFG_TK_SHARED_LIB_SUFFIX CFG_TK_UNSHARED_LIB_SUFFIX CFG_TK_EXPORT_FILE_SUFFIX EXTRA_CFLAGS DEPARG CC_OBJNAME CC_EXENAME LDFLAGS_DEBUG LDFLAGS_OPTIMIZE LDFLAGS_CONSOLE LDFLAGS_WINDOW TK_RES STLIB_LD SHLIB_LD SHLIB_LD_LIBS SHLIB_CFLAGS SHLIB_SUFFIX TK_SHARED_BUILD LIBS_GUI DLLSUFFIX LIBPREFIX LIBSUFFIX EXESUFFIX LIBRARIES MAKE_LIB MAKE_STUB_LIB POST_MAKE_LIB MAKE_DLL MAKE_EXE TK_LIB_FLAG TK_LIB_SPEC TK_BUILD_LIB_SPEC TK_STUB_LIB_SPEC TK_STUB_LIB_PATH TK_BUILD_STUB_LIB_PATH TK_CC_SEARCH_FLAGS TK_LD_SEARCH_FLAGS RC_OUT RC_TYPE RC_INCLUDE RC_DEFINE RC_DEFINES RES LIBOBJS LTLIBOBJS'
ac_subst_vars='LTLIBOBJS
LIBOBJS
RES
RC_DEFINES
RC_DEFINE
RC_INCLUDE
RC_TYPE
RC_OUT
TK_LD_SEARCH_FLAGS
TK_CC_SEARCH_FLAGS
TK_BUILD_STUB_LIB_PATH
TK_STUB_LIB_PATH
TK_STUB_LIB_SPEC
TK_BUILD_LIB_SPEC
TK_LIB_SPEC
TK_LIB_FLAG
MAKE_EXE
MAKE_DLL
POST_MAKE_LIB
MAKE_STUB_LIB
MAKE_LIB
LIBRARIES
EXESUFFIX
LIBSUFFIX
LIBPREFIX
DLLSUFFIX
LIBS_GUI
TK_SHARED_BUILD
SHLIB_SUFFIX
SHLIB_CFLAGS
SHLIB_LD_LIBS
SHLIB_LD
STLIB_LD
TK_RES
LDFLAGS_WINDOW
LDFLAGS_CONSOLE
LDFLAGS_OPTIMIZE
LDFLAGS_DEBUG
CC_EXENAME
CC_OBJNAME
DEPARG
EXTRA_CFLAGS
CFG_TK_EXPORT_FILE_SUFFIX
CFG_TK_UNSHARED_LIB_SUFFIX
CFG_TK_SHARED_LIB_SUFFIX
TCL_PATCH_LEVEL
TCL_MINOR_VERSION
TCL_MAJOR_VERSION
TK_BIN_DIR
TK_SRC_DIR
TK_BUILD_STUB_LIB_SPEC
TK_STUB_LIB_FLAG
TK_STUB_LIB_FILE
TK_DLL_FILE
TK_LIB_FILE
TK_PATCH_LEVEL
TK_MINOR_VERSION
TK_MAJOR_VERSION
TK_VERSION
MACHINE
TK_WIN_VERSION
TCLSH_PROG
BUILD_TCLSH
VC_MANIFEST_EMBED_EXE
VC_MANIFEST_EMBED_DLL
CPP
LDFLAGS_DEFAULT
CFLAGS_DEFAULT
MAN2TCLFLAGS
CFLAGS_WARNING
CFLAGS_OPTIMIZE
CFLAGS_DEBUG
DL_LIBS
WINE
CYGPATH
TCL_DEFS
TCL_STUB_LIB_SPEC
TCL_STUB_LIB_FLAG
TCL_STUB_LIB_FILE
TCL_LIB_SPEC
TCL_LIB_FLAG
TCL_LIB_FILE
TCL_ZIP_FILE
TCL_SRC_DIR
TCL_BIN_DIR
TCL_VERSION
SHARED_BUILD
SET_MAKE
RC
RANLIB
AR
EGREP
GREP
OBJEXT
EXEEXT
ac_ct_CC
CPPFLAGS
LDFLAGS
CFLAGS
CC
target_alias
host_alias
build_alias
LIBS
ECHO_T
ECHO_N
ECHO_C
DEFS
mandir
localedir
libdir
psdir
pdfdir
dvidir
htmldir
infodir
docdir
oldincludedir
includedir
runstatedir
localstatedir
sharedstatedir
sysconfdir
datadir
datarootdir
libexecdir
sbindir
bindir
program_transform_name
prefix
exec_prefix
PACKAGE_URL
PACKAGE_BUGREPORT
PACKAGE_STRING
PACKAGE_VERSION
PACKAGE_TARNAME
PACKAGE_NAME
PATH_SEPARATOR
SHELL
OBJEXT_FOR_BUILD'
ac_subst_files=''
ac_user_opts='
enable_option_checking
enable_shared
with_tcl
enable_64bit
enable_symbols
enable_embedded_manifest
'
      ac_precious_vars='build_alias
host_alias
target_alias
CC
CFLAGS
LDFLAGS
LIBS
CPPFLAGS
CPP'


# Initialize some variables set by options.
ac_init_help=
ac_init_version=false
ac_unrecognized_opts=
ac_unrecognized_sep=
# The variables have the same names as the options, with
# dashes changed to underlines.
cache_file=/dev/null
exec_prefix=NONE
no_create=
no_recursion=
prefix=NONE
333
334
335
336
337
338
339

340
341
342
343


344
345
346
347

348
349

350
351








352
353

354
355
356
357
358

359
360
361
362
363
364
365





366
367



368
369
370
371
372
373
374
828
829
830
831
832
833
834
835
836
837
838

839
840
841
842
843

844
845
846
847


848
849
850
851
852
853
854
855
856
857
858
859
860
861
862

863
864
865
866
867



868
869
870
871
872
873

874
875
876
877
878
879
880
881
882
883







+



-
+
+



-
+


+
-
-
+
+
+
+
+
+
+
+


+




-
+




-
-
-
+
+
+
+
+

-
+
+
+







x_libraries=NONE

# Installation directory options.
# These are left unexpanded so users can "make install exec_prefix=/foo"
# and all the variables that are supposed to be based on exec_prefix
# by default will actually change.
# Use braces instead of parens because sh, perl, etc. also accept them.
# (The list follows the same order as the GNU Coding Standards.)
bindir='${exec_prefix}/bin'
sbindir='${exec_prefix}/sbin'
libexecdir='${exec_prefix}/libexec'
datadir='${prefix}/share'
datarootdir='${prefix}/share'
datadir='${datarootdir}'
sysconfdir='${prefix}/etc'
sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var'
libdir='${exec_prefix}/lib'
runstatedir='${localstatedir}/run'
includedir='${prefix}/include'
oldincludedir='/usr/include'
docdir='${datarootdir}/doc/${PACKAGE}'
infodir='${prefix}/info'
mandir='${prefix}/man'
infodir='${datarootdir}/info'
htmldir='${docdir}'
dvidir='${docdir}'
pdfdir='${docdir}'
psdir='${docdir}'
libdir='${exec_prefix}/lib'
localedir='${datarootdir}/locale'
mandir='${datarootdir}/man'

ac_prev=
ac_dashdash=
for ac_option
do
  # If the previous option needs an argument, assign it.
  if test -n "$ac_prev"; then
    eval "$ac_prev=\$ac_option"
    eval $ac_prev=\$ac_option
    ac_prev=
    continue
  fi

  ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'`

  # Accept the important Cygnus configure options, so we can diagnose typos.
  case $ac_option in
  *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
  *=)   ac_optarg= ;;
  *)    ac_optarg=yes ;;
  esac

  case $ac_option in
  case $ac_dashdash$ac_option in
  --)
    ac_dashdash=yes ;;

  -bindir | --bindir | --bindi | --bind | --bin | --bi)
    ac_prev=bindir ;;
  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
    bindir=$ac_optarg ;;

  -build | --build | --buil | --bui | --bu)
382
383
384
385
386
387
388
389

390
391
392
393









394
395
396

397
398
399
400
401
402






















403
404
405

406
407
408
409
410
411
412
413










414
415

416
417
418
419
420
421
422
891
892
893
894
895
896
897

898
899



900
901
902
903
904
905
906
907
908
909
910

911
912





913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936

937
938







939
940
941
942
943
944
945
946
947
948
949

950
951
952
953
954
955
956
957







-
+

-
-
-
+
+
+
+
+
+
+
+
+


-
+

-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+

-
+







  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
    cache_file=$ac_optarg ;;

  --config-cache | -C)
    cache_file=config.cache ;;

  -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
  -datadir | --datadir | --datadi | --datad)
    ac_prev=datadir ;;
  -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
  | --da=*)
    datadir=$ac_optarg ;;
  -datadir=* | --datadir=* | --datadi=* | --datad=*)
    datadir=$ac_optarg ;;

  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
  | --dataroo | --dataro | --datar)
    ac_prev=datarootdir ;;
  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
    datarootdir=$ac_optarg ;;

  -disable-* | --disable-*)
    ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
    ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
    # Reject names that are not valid shell variable names.
    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
   { (exit 1); exit 1; }; }
    ac_feature=`echo $ac_feature | sed 's/-/_/g'`
    eval "enable_$ac_feature=no" ;;
    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
      as_fn_error $? "invalid feature name: \`$ac_useropt'"
    ac_useropt_orig=$ac_useropt
    ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
    case $ac_user_opts in
      *"
"enable_$ac_useropt"
"*) ;;
      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
	 ac_unrecognized_sep=', ';;
    esac
    eval enable_$ac_useropt=no ;;

  -docdir | --docdir | --docdi | --doc | --do)
    ac_prev=docdir ;;
  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
    docdir=$ac_optarg ;;

  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
    ac_prev=dvidir ;;
  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
    dvidir=$ac_optarg ;;

  -enable-* | --enable-*)
    ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
    ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
    # Reject names that are not valid shell variable names.
    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
   { (exit 1); exit 1; }; }
    ac_feature=`echo $ac_feature | sed 's/-/_/g'`
    case $ac_option in
      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
      *) ac_optarg=yes ;;
    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
      as_fn_error $? "invalid feature name: \`$ac_useropt'"
    ac_useropt_orig=$ac_useropt
    ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
    case $ac_user_opts in
      *"
"enable_$ac_useropt"
"*) ;;
      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
	 ac_unrecognized_sep=', ';;
    esac
    eval "enable_$ac_feature='$ac_optarg'" ;;
    eval enable_$ac_useropt=\$ac_optarg ;;

  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
  | --exec | --exe | --ex)
    ac_prev=exec_prefix ;;
  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
434
435
436
437
438
439
440






441
442
443
444
445
446
447
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988







+
+
+
+
+
+







  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
    ac_init_help=short ;;

  -host | --host | --hos | --ho)
    ac_prev=host_alias ;;
  -host=* | --host=* | --hos=* | --ho=*)
    host_alias=$ac_optarg ;;

  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
    ac_prev=htmldir ;;
  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
  | --ht=*)
    htmldir=$ac_optarg ;;

  -includedir | --includedir | --includedi | --included | --include \
  | --includ | --inclu | --incl | --inc)
    ac_prev=includedir ;;
  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
  | --includ=* | --inclu=* | --incl=* | --inc=*)
    includedir=$ac_optarg ;;
458
459
460
461
462
463
464
465





466
467

468
469
470
471

472
473
474
475
476
477
478
479
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012

1013

1014
1015

1016

1017
1018
1019
1020
1021
1022
1023








+
+
+
+
+

-
+
-


-
+
-








  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
  | --libexe | --libex | --libe)
    ac_prev=libexecdir ;;
  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
  | --libexe=* | --libex=* | --libe=*)
    libexecdir=$ac_optarg ;;

  -localedir | --localedir | --localedi | --localed | --locale)
    ac_prev=localedir ;;
  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
    localedir=$ac_optarg ;;

  -localstatedir | --localstatedir | --localstatedi | --localstated \
  | --localstate | --localstat | --localsta | --localst \
  | --localstate | --localstat | --localsta | --localst | --locals)
  | --locals | --local | --loca | --loc | --lo)
    ac_prev=localstatedir ;;
  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
  | --localstate=* | --localstat=* | --localsta=* | --localst=* \
  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
  | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
    localstatedir=$ac_optarg ;;

  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
    ac_prev=mandir ;;
  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
    mandir=$ac_optarg ;;

529
530
531
532
533
534
535










536
537
538
539









540
541
542
543
544
545
546
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109







+
+
+
+
+
+
+
+
+
+




+
+
+
+
+
+
+
+
+







  | --program-transform-nam=* | --program-transform-na=* \
  | --program-transform-n=* | --program-transform-=* \
  | --program-transform=* | --program-transfor=* \
  | --program-transfo=* | --program-transf=* \
  | --program-trans=* | --program-tran=* \
  | --progr-tra=* | --program-tr=* | --program-t=*)
    program_transform_name=$ac_optarg ;;

  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
    ac_prev=pdfdir ;;
  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
    pdfdir=$ac_optarg ;;

  -psdir | --psdir | --psdi | --psd | --ps)
    ac_prev=psdir ;;
  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
    psdir=$ac_optarg ;;

  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
  | -silent | --silent | --silen | --sile | --sil)
    silent=yes ;;

  -runstatedir | --runstatedir | --runstatedi | --runstated \
  | --runstate | --runstat | --runsta | --runst | --runs \
  | --run | --ru | --r)
    ac_prev=runstatedir ;;
  -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
  | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
  | --run=* | --ru=* | --r=*)
    runstatedir=$ac_optarg ;;

  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
    ac_prev=sbindir ;;
  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
  | --sbi=* | --sb=*)
    sbindir=$ac_optarg ;;

580
581
582
583
584
585
586
587

588
589
590
591
592
593
594
595










596
597

598
599
600

601
602
603


604
605
606










607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627


628
629
630
631
632
633

634
635


636
637
638


639
640
641
642
643

644
645
646


647
648
649
650
651
652
653
654
655









656
657
658
659





660
661


662
663
664



665
666
667
668
669

670
671
672
673
674
675
676


677
678

679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704








705
706
707
708
709
710
711
712
713






714
715
716
717
718
719
720


















721
722

723
724
725
726
727
728
729


730
731
732
733

734
735








736



737

738
739
740

741
742
743
744
745
746
747
748
749
750
751
752
753
754

755
756

757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772





773
774
775
776
777
778
779
1143
1144
1145
1146
1147
1148
1149

1150
1151







1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162

1163
1164
1165

1166
1167


1168
1169



1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198


1199
1200

1201
1202
1203
1204
1205
1206


1207
1208



1209
1210
1211
1212
1213
1214

1215
1216


1217
1218
1219
1220
1221
1222
1223
1224
1225


1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236


1237
1238
1239
1240
1241
1242

1243
1244
1245


1246
1247
1248

1249



1250




1251


1252
1253

1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268


1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290






1291
1292
1293
1294
1295
1296







1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315

1316
1317
1318
1319
1320
1321


1322
1323




1324


1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336

1337



1338














1339


1340
















1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352







-
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+

-
+


-
+

-
-
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+



















-
-
+
+
-





+
-
-
+
+
-
-
-
+
+




-
+

-
-
+
+







-
-
+
+
+
+
+
+
+
+
+


-
-
+
+
+
+
+

-
+
+

-
-
+
+
+
-

-
-
-
+
-
-
-
-

-
-
+
+
-

+













-
-











+
+
+
+
+
+
+
+



-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+





-
-
+
+
-
-
-
-
+
-
-
+
+
+
+
+
+
+
+

+
+
+
-
+
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+







  -v | -verbose | --verbose | --verbos | --verbo | --verb)
    verbose=yes ;;

  -version | --version | --versio | --versi | --vers | -V)
    ac_init_version=: ;;

  -with-* | --with-*)
    ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
    ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
    # Reject names that are not valid shell variable names.
    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
      { echo "$as_me: error: invalid package name: $ac_package" >&2
   { (exit 1); exit 1; }; }
    ac_package=`echo $ac_package| sed 's/-/_/g'`
    case $ac_option in
      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
      *) ac_optarg=yes ;;
    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
      as_fn_error $? "invalid package name: \`$ac_useropt'"
    ac_useropt_orig=$ac_useropt
    ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
    case $ac_user_opts in
      *"
"with_$ac_useropt"
"*) ;;
      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
	 ac_unrecognized_sep=', ';;
    esac
    eval "with_$ac_package='$ac_optarg'" ;;
    eval with_$ac_useropt=\$ac_optarg ;;

  -without-* | --without-*)
    ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
    ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
    # Reject names that are not valid shell variable names.
    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
      { echo "$as_me: error: invalid package name: $ac_package" >&2
    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
      as_fn_error $? "invalid package name: \`$ac_useropt'"
   { (exit 1); exit 1; }; }
    ac_package=`echo $ac_package | sed 's/-/_/g'`
    eval "with_$ac_package=no" ;;
    ac_useropt_orig=$ac_useropt
    ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
    case $ac_user_opts in
      *"
"with_$ac_useropt"
"*) ;;
      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
	 ac_unrecognized_sep=', ';;
    esac
    eval with_$ac_useropt=no ;;

  --x)
    # Obsolete; use --with-x.
    with_x=yes ;;

  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
  | --x-incl | --x-inc | --x-in | --x-i)
    ac_prev=x_includes ;;
  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
    x_includes=$ac_optarg ;;

  -x-libraries | --x-libraries | --x-librarie | --x-librari \
  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
    ac_prev=x_libraries ;;
  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
    x_libraries=$ac_optarg ;;

  -*) { echo "$as_me: error: unrecognized option: $ac_option
Try \`$0 --help' for more information." >&2
  -*) as_fn_error $? "unrecognized option: \`$ac_option'
Try \`$0 --help' for more information"
   { (exit 1); exit 1; }; }
    ;;

  *=*)
    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
    # Reject names that are not valid shell variable names.
    case $ac_envvar in #(
    expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
      { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
      '' | [0-9]* | *[!_$as_cr_alnum]* )
      as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
   { (exit 1); exit 1; }; }
    ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`
    eval "$ac_envvar='$ac_optarg'"
    esac
    eval $ac_envvar=\$ac_optarg
    export $ac_envvar ;;

  *)
    # FIXME: should be removed in autoconf 3.0.
    echo "$as_me: WARNING: you should use --build, --host, --target" >&2
    printf "%s\n" "$as_me: WARNING: you should use --build, --host, --target" >&2
    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
      echo "$as_me: WARNING: invalid host type: $ac_option" >&2
    : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
      printf "%s\n" "$as_me: WARNING: invalid host type: $ac_option" >&2
    : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
    ;;

  esac
done

if test -n "$ac_prev"; then
  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
  { echo "$as_me: error: missing argument to $ac_option" >&2
   { (exit 1); exit 1; }; }
  as_fn_error $? "missing argument to $ac_option"
fi

if test -n "$ac_unrecognized_opts"; then
  case $enable_option_checking in
    no) ;;
    fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
    *)     printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
  esac
fi

# Be sure to have absolute paths.
for ac_var in exec_prefix prefix
# Check all directory arguments for consistency.
for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
		datadir sysconfdir sharedstatedir localstatedir includedir \
		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
		libdir localedir mandir runstatedir
do
  eval ac_val=$`echo $ac_var`
  eval ac_val=\$$ac_var
  # Remove trailing slashes.
  case $ac_val in
    [\\/$]* | ?:[\\/]* | NONE | '' ) ;;
    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
    */ )
      ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
      eval $ac_var=\$ac_val;;
   { (exit 1); exit 1; }; };;
  esac
done

# Be sure to have absolute paths.
  # Be sure to have absolute directory names.
for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \
	      localstatedir libdir includedir oldincludedir infodir mandir
do
  eval ac_val=$`echo $ac_var`
  case $ac_val in
    [\\/$]* | ?:[\\/]* ) ;;
    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
    [\\/$]* | ?:[\\/]* )  continue;;
    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
   { (exit 1); exit 1; }; };;
  esac
  as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
done

# There might be people who depend on the old broken behavior: `$host'
# used to hold the argument of --host etc.
# FIXME: To remove some day.
build=$build_alias
host=$host_alias
target=$target_alias

# FIXME: To remove some day.
if test "x$host_alias" != x; then
  if test "x$build_alias" = x; then
    cross_compiling=maybe
    echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
    If a cross compiler is detected then cross compile mode will be used." >&2
  elif test "x$build_alias" != "x$host_alias"; then
    cross_compiling=yes
  fi
fi

ac_tool_prefix=
test -n "$host_alias" && ac_tool_prefix=$host_alias-

test "$silent" = yes && exec 6>/dev/null


ac_pwd=`pwd` && test -n "$ac_pwd" &&
ac_ls_di=`ls -di .` &&
ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
  as_fn_error $? "working directory cannot be determined"
test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
  as_fn_error $? "pwd does not report name of working directory"


# Find the source files, if location was not specified.
if test -z "$srcdir"; then
  ac_srcdir_defaulted=yes
  # Try the directory containing this script, then its parent.
  ac_confdir=`(dirname "$0") 2>/dev/null ||
$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
	 X"$0" : 'X\(//\)[^/]' \| \
	 X"$0" : 'X\(//\)$' \| \
	 X"$0" : 'X\(/\)' \| \
  # Try the directory containing this script, then the parent directory.
  ac_confdir=`$as_dirname -- "$as_myself" ||
$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
	 X"$as_myself" : 'X\(//\)[^/]' \| \
	 X"$as_myself" : 'X\(//\)$' \| \
	 X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
	 .     : '\(.\)' 2>/dev/null ||
echo X"$0" |
    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
  	  /^X\(\/\/\)$/{ s//\1/; q; }
  	  /^X\(\/\).*/{ s//\1/; q; }
  	  s/.*/./; q'`
printf "%s\n" X"$as_myself" |
    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
	    s//\1/
	    q
	  }
	  /^X\(\/\/\)[^/].*/{
	    s//\1/
	    q
	  }
	  /^X\(\/\/\)$/{
	    s//\1/
	    q
	  }
	  /^X\(\/\).*/{
	    s//\1/
	    q
	  }
	  s/.*/./; q'`
  srcdir=$ac_confdir
  if test ! -r $srcdir/$ac_unique_file; then
  if test ! -r "$srcdir/$ac_unique_file"; then
    srcdir=..
  fi
else
  ac_srcdir_defaulted=no
fi
if test ! -r $srcdir/$ac_unique_file; then
  if test "$ac_srcdir_defaulted" = yes; then
if test ! -r "$srcdir/$ac_unique_file"; then
  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2
   { (exit 1); exit 1; }; }
  else
    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
  as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
   { (exit 1); exit 1; }; }
  fi
fi
ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
ac_abs_confdir=`(
	cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
	pwd)`
# When building in place, set srcdir=.
if test "$ac_abs_confdir" = "$ac_pwd"; then
  srcdir=.
fi
# Remove unnecessary trailing slashes from srcdir.
# Double slashes in file names in object file debugging info
# mess up M-x gdb in Emacs.
(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null ||
case $srcdir in
  { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2
   { (exit 1); exit 1; }; }
srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'`
*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
ac_env_build_alias_set=${build_alias+set}
ac_env_build_alias_value=$build_alias
ac_cv_env_build_alias_set=${build_alias+set}
ac_cv_env_build_alias_value=$build_alias
ac_env_host_alias_set=${host_alias+set}
ac_env_host_alias_value=$host_alias
ac_cv_env_host_alias_set=${host_alias+set}
ac_cv_env_host_alias_value=$host_alias
ac_env_target_alias_set=${target_alias+set}
ac_env_target_alias_value=$target_alias
ac_cv_env_target_alias_set=${target_alias+set}
ac_cv_env_target_alias_value=$target_alias
ac_env_CC_set=${CC+set}
ac_env_CC_value=$CC
esac
ac_cv_env_CC_set=${CC+set}
ac_cv_env_CC_value=$CC
for ac_var in $ac_precious_vars; do
ac_env_CFLAGS_set=${CFLAGS+set}
ac_env_CFLAGS_value=$CFLAGS
ac_cv_env_CFLAGS_set=${CFLAGS+set}
ac_cv_env_CFLAGS_value=$CFLAGS
ac_env_LDFLAGS_set=${LDFLAGS+set}
ac_env_LDFLAGS_value=$LDFLAGS
ac_cv_env_LDFLAGS_set=${LDFLAGS+set}
ac_cv_env_LDFLAGS_value=$LDFLAGS
ac_env_CPPFLAGS_set=${CPPFLAGS+set}
ac_env_CPPFLAGS_value=$CPPFLAGS
ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set}
ac_cv_env_CPPFLAGS_value=$CPPFLAGS
ac_env_CPP_set=${CPP+set}
ac_env_CPP_value=$CPP
ac_cv_env_CPP_set=${CPP+set}
ac_cv_env_CPP_value=$CPP
  eval ac_env_${ac_var}_set=\${${ac_var}+set}
  eval ac_env_${ac_var}_value=\$${ac_var}
  eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
  eval ac_cv_env_${ac_var}_value=\$${ac_var}
done

#
# Report the --help message.
#
if test "$ac_init_help" = "long"; then
  # Omit some internal or obsolete options to make the list less imposing.
  # This message is too long to be a string in the A/UX 3.1 sh.
788
789
790
791
792
793
794
795

796
797
798
799
800
801
802
803
804
805
806

807
808

809
810
811
812
813
814
815
816
817
818
819
820



821
822
823
824
825
826
827
828
829

















830
831
832
833
834
835
836
837
838
839
840

841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862

863
864


865
866
867
868
869

870

871
872
873
874
875
876


877

878
879
880
881
882
883
884
885
886















887
888
889

890
891
892

893
894

895
896

897
898
899
900
901





902
903

904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928

929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949








950
951
952

953
954
955
956
957
958



959
960
961
962

963
964


965
966

967
968
969
970

971
972
973
































































































































































































974
975
976
977
978

979
980

981
982

983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001

1002
1003
1004
1005
1006
1007
1008
1009
1010
1011

1012
1013
1014







1015
1016
1017
1018
1019
1020
1021
1361
1362
1363
1364
1365
1366
1367

1368
1369
1370
1371
1372
1373



1374
1375

1376
1377

1378
1379
1380
1381
1382
1383
1384
1385
1386
1387



1388
1389
1390









1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421

1422
1423

1424
1425
1426
1427
1428
1429
1430
1431
1432

1433
1434
1435
1436
1437
1438
1439


1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453

1454
1455
1456

1457
1458
1459







1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476

1477
1478


1479


1480


1481
1482




1483
1484
1485
1486
1487


1488










1489














1490













1491







1492
1493
1494
1495
1496
1497
1498
1499



1500


1501



1502
1503
1504
1505
1506
1507

1508
1509
1510
1511
1512
1513

1514
1515
1516
1517

1518
1519


1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715

1716
1717

1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739

1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751



1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765







-
+





-
-
-


-
+

-
+









-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+











+


-


-









-






+
-
-
+
+





+

+




-

+
+
-
+


-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
+

-
-
+
-
-
+
-
-
+

-
-
-
-
+
+
+
+
+
-
-
+
-
-
-
-
-
-
-
-
-
-

-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
+
-
-

-
-
-
+
+
+



-
+


+
+

-
+



-
+

-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




-
+

-
+


+


















-
+










+
-
-
-
+
+
+
+
+
+
+







Defaults for the options are specified in brackets.

Configuration:
  -h, --help              display this help and exit
      --help=short        display options specific to this package
      --help=recursive    display the short help of all the included packages
  -V, --version           display version information and exit
  -q, --quiet, --silent   do not print \`checking...' messages
  -q, --quiet, --silent   do not print \`checking ...' messages
      --cache-file=FILE   cache test results in FILE [disabled]
  -C, --config-cache      alias for \`--cache-file=config.cache'
  -n, --no-create         do not create output files
      --srcdir=DIR        find the sources in DIR [configure dir or \`..']

_ACEOF

  cat <<_ACEOF
Installation directories:
  --prefix=PREFIX         install architecture-independent files in PREFIX
			  [$ac_default_prefix]
                          [$ac_default_prefix]
  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
			  [PREFIX]
                          [PREFIX]

By default, \`make install' will install all the files in
\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
an installation prefix other than \`$ac_default_prefix' using \`--prefix',
for instance \`--prefix=\$HOME'.

For better control, use the options below.

Fine tuning of the installation directories:
  --bindir=DIR           user executables [EPREFIX/bin]
  --sbindir=DIR          system admin executables [EPREFIX/sbin]
  --libexecdir=DIR       program executables [EPREFIX/libexec]
  --bindir=DIR            user executables [EPREFIX/bin]
  --sbindir=DIR           system admin executables [EPREFIX/sbin]
  --libexecdir=DIR        program executables [EPREFIX/libexec]
  --datadir=DIR          read-only architecture-independent data [PREFIX/share]
  --sysconfdir=DIR       read-only single-machine data [PREFIX/etc]
  --sharedstatedir=DIR   modifiable architecture-independent data [PREFIX/com]
  --localstatedir=DIR    modifiable single-machine data [PREFIX/var]
  --libdir=DIR           object code libraries [EPREFIX/lib]
  --includedir=DIR       C header files [PREFIX/include]
  --oldincludedir=DIR    C header files for non-gcc [/usr/include]
  --infodir=DIR          info documentation [PREFIX/info]
  --mandir=DIR           man documentation [PREFIX/man]
  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
  --runstatedir=DIR       modifiable per-process data [LOCALSTATEDIR/run]
  --libdir=DIR            object code libraries [EPREFIX/lib]
  --includedir=DIR        C header files [PREFIX/include]
  --oldincludedir=DIR     C header files for non-gcc [/usr/include]
  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]
  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]
  --infodir=DIR           info documentation [DATAROOTDIR/info]
  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]
  --mandir=DIR            man documentation [DATAROOTDIR/man]
  --docdir=DIR            documentation root [DATAROOTDIR/doc/PACKAGE]
  --htmldir=DIR           html documentation [DOCDIR]
  --dvidir=DIR            dvi documentation [DOCDIR]
  --pdfdir=DIR            pdf documentation [DOCDIR]
  --psdir=DIR             ps documentation [DOCDIR]
_ACEOF

  cat <<\_ACEOF
_ACEOF
fi

if test -n "$ac_init_help"; then

  cat <<\_ACEOF

Optional Features:
  --disable-option-checking  ignore unrecognized --enable/--with options
  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
  --enable-threads        build with threads (default: on)
  --enable-shared         build and link with shared libraries (default: on)
  --enable-64bit          enable 64bit support (where applicable)
  --enable-wince          enable Win/CE support (where applicable)
  --enable-symbols        build with debugging symbols (default: off)
  --enable-embedded-manifest
                          embed manifest if possible (default: yes)

Optional Packages:
  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
  --with-tcl              directory containing tcl configuration
                          (tclConfig.sh)
  --with-celib=DIR        use Windows/CE support library from DIR

Some influential environment variables:
  CC          C compiler command
  CFLAGS      C compiler flags
  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
              nonstandard directory <lib dir>
  LIBS        libraries to pass to the linker, e.g. -l<library>
  CPPFLAGS    C/C++ preprocessor flags, e.g. -I<include dir> if you have
              headers in a nonstandard directory <include dir>
  CPPFLAGS    (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
              you have headers in a nonstandard directory <include dir>
  CPP         C preprocessor

Use these variables to override the choices made by `configure' or to help
it to find libraries and programs with nonstandard names/locations.

Report bugs to the package provider.
_ACEOF
ac_status=$?
fi

if test "$ac_init_help" = "recursive"; then
  # If there are subdirs, report their specific --help.
  ac_popdir=`pwd`
  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
    test -d "$ac_dir" ||
      { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
    test -d $ac_dir || continue
      continue
    ac_builddir=.

if test "$ac_dir" != .; then
  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
  # A "../" for each directory in $ac_dir_suffix.
  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
else
  ac_dir_suffix= ac_top_builddir=
fi
case "$ac_dir" in
.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
*)
  ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
  # A ".." for each directory in $ac_dir_suffix.
  ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
  case $ac_top_builddir_sub in
  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
  esac ;;
esac
ac_abs_top_builddir=$ac_pwd
ac_abs_builddir=$ac_pwd$ac_dir_suffix
# for backward compatibility:
ac_top_builddir=$ac_top_build_prefix

case $srcdir in
  .)  # No --srcdir option.  We are building in place.
  .)  # We are building in place.
    ac_srcdir=.
    if test -z "$ac_top_builddir"; then
       ac_top_srcdir=.
    ac_top_srcdir=$ac_top_builddir_sub
    else
       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
    ac_abs_top_srcdir=$ac_pwd ;;
    fi ;;
  [\\/]* | ?:[\\/]* )  # Absolute path.
  [\\/]* | ?:[\\/]* )  # Absolute name.
    ac_srcdir=$srcdir$ac_dir_suffix;
    ac_top_srcdir=$srcdir ;;
  *) # Relative path.
    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
    ac_top_srcdir=$ac_top_builddir$srcdir ;;
    ac_top_srcdir=$srcdir
    ac_abs_top_srcdir=$srcdir ;;
  *) # Relative name.
    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
    ac_top_srcdir=$ac_top_build_prefix$srcdir
esac

    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
# Do not use `cd foo && pwd` to compute absolute paths, because
# the directories may not exist.
case `pwd` in
.) ac_abs_builddir="$ac_dir";;
*)
  case "$ac_dir" in
  .) ac_abs_builddir=`pwd`;;
  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
  *) ac_abs_builddir=`pwd`/"$ac_dir";;
  esac;;
esac
case $ac_abs_builddir in
.) ac_abs_top_builddir=${ac_top_builddir}.;;
*)
  case ${ac_top_builddir}. in
  .) ac_abs_top_builddir=$ac_abs_builddir;;
  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
  esac;;
esac
case $ac_abs_builddir in
.) ac_abs_srcdir=$ac_srcdir;;
*)
  case $ac_srcdir in
  .) ac_abs_srcdir=$ac_abs_builddir;;
ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
  esac;;
esac
case $ac_abs_builddir in
.) ac_abs_top_srcdir=$ac_top_srcdir;;
*)
  case $ac_top_srcdir in
  .) ac_abs_top_srcdir=$ac_abs_builddir;;
  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
  esac;;
esac

    cd $ac_dir
    # Check for guested configure; otherwise get Cygnus style configure.
    if test -f $ac_srcdir/configure.gnu; then
      echo
      $SHELL $ac_srcdir/configure.gnu  --help=recursive
    elif test -f $ac_srcdir/configure; then
      echo
    cd "$ac_dir" || { ac_status=$?; continue; }
    # Check for configure.gnu first; this name is used for a wrapper for
    # Metaconfig's "Configure" on case-insensitive file systems.
    if test -f "$ac_srcdir/configure.gnu"; then
      echo &&
      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
    elif test -f "$ac_srcdir/configure"; then
      echo &&
      $SHELL $ac_srcdir/configure  --help=recursive
    elif test -f $ac_srcdir/configure.ac ||
	   test -f $ac_srcdir/configure.in; then
      $SHELL "$ac_srcdir/configure" --help=recursive
      echo
      $ac_configure --help
    else
      echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
    fi
    cd $ac_popdir
      printf "%s\n" "$as_me: WARNING: no configuration information is in $ac_dir" >&2
    fi || ac_status=$?
    cd "$ac_pwd" || { ac_status=$?; break; }
  done
fi

test -n "$ac_init_help" && exit 0
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
  cat <<\_ACEOF
configure
generated by GNU Autoconf 2.70

Copyright (C) 2003 Free Software Foundation, Inc.
Copyright (C) 2020 Free Software Foundation, Inc.
This configure script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it.
_ACEOF
  exit 0
  exit
fi
exec 5>config.log
cat >&5 <<_ACEOF

## ------------------------ ##
## Autoconf initialization. ##
## ------------------------ ##

# ac_fn_c_try_compile LINENO
# --------------------------
# Try to compile conftest.$ac_ext, and return whether this succeeded.
ac_fn_c_try_compile ()
{
  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
  rm -f conftest.$ac_objext conftest.beam
  if { { ac_try="$ac_compile"
case "(($ac_try" in
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
  *) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
printf "%s\n" "$ac_try_echo"; } >&5
  (eval "$ac_compile") 2>conftest.err
  ac_status=$?
  if test -s conftest.err; then
    grep -v '^ *+' conftest.err >conftest.er1
    cat conftest.er1 >&5
    mv -f conftest.er1 conftest.err
  fi
  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; } && {
	 test -z "$ac_c_werror_flag" ||
	 test ! -s conftest.err
       } && test -s conftest.$ac_objext
then :
  ac_retval=0
else $as_nop
  printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

	ac_retval=1
fi
  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
  as_fn_set_status $ac_retval

} # ac_fn_c_try_compile

# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
# -------------------------------------------------------
# Tests whether HEADER exists and can be compiled using the include files in
# INCLUDES, setting the cache variable VAR accordingly.
ac_fn_c_check_header_compile ()
{
  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
printf %s "checking for $2... " >&6; }
if eval test \${$3+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
$4
#include <$2>
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  eval "$3=yes"
else $as_nop
  eval "$3=no"
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
eval ac_res=\$$3
	       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
printf "%s\n" "$ac_res" >&6; }
  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno

} # ac_fn_c_check_header_compile

# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
# -------------------------------------------
# Tests whether TYPE exists after having included INCLUDES, setting cache
# variable VAR accordingly.
ac_fn_c_check_type ()
{
  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
printf %s "checking for $2... " >&6; }
if eval test \${$3+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  eval "$3=no"
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
$4
int
main (void)
{
if (sizeof ($2))
	 return 0;
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
$4
int
main (void)
{
if (sizeof (($2)))
	    return 0;
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :

else $as_nop
  eval "$3=yes"
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
eval ac_res=\$$3
	       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
printf "%s\n" "$ac_res" >&6; }
  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno

} # ac_fn_c_check_type

# ac_fn_c_try_cpp LINENO
# ----------------------
# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
ac_fn_c_try_cpp ()
{
  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
  if { { ac_try="$ac_cpp conftest.$ac_ext"
case "(($ac_try" in
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
  *) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
printf "%s\n" "$ac_try_echo"; } >&5
  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
  ac_status=$?
  if test -s conftest.err; then
    grep -v '^ *+' conftest.err >conftest.er1
    cat conftest.er1 >&5
    mv -f conftest.er1 conftest.err
  fi
  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; } > conftest.i && {
	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
	 test ! -s conftest.err
       }
then :
  ac_retval=0
else $as_nop
  printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

    ac_retval=1
fi
  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
  as_fn_set_status $ac_retval

} # ac_fn_c_try_cpp
ac_configure_args_raw=
for ac_arg
do
  case $ac_arg in
  *\'*)
    ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
  esac
  as_fn_append ac_configure_args_raw " '$ac_arg'"
done

case $ac_configure_args_raw in
  *$as_nl*)
    ac_safe_unquote= ;;
  *)
    ac_unsafe_z='|&;<>()$`\\"*?[ ''	' # This string ends in space, tab.
    ac_unsafe_a="$ac_unsafe_z#~"
    ac_safe_unquote="s/ '\\([^$ac_unsafe_a][^$ac_unsafe_z]*\\)'/ \\1/g"
    ac_configure_args_raw=`      printf "%s\n" "$ac_configure_args_raw" | sed "$ac_safe_unquote"`;;
esac

cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.

It was created by $as_me, which was
generated by GNU Autoconf 2.59.  Invocation command line was
generated by GNU Autoconf 2.70.  Invocation command line was

  $ $0 $@
  $ $0$ac_configure_args_raw

_ACEOF
exec 5>>config.log
{
cat <<_ASUNAME
## --------- ##
## Platform. ##
## --------- ##

hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
uname -m = `(uname -m) 2>/dev/null || echo unknown`
uname -r = `(uname -r) 2>/dev/null || echo unknown`
uname -s = `(uname -s) 2>/dev/null || echo unknown`
uname -v = `(uname -v) 2>/dev/null || echo unknown`

/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`

/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
hostinfo               = `(hostinfo) 2>/dev/null               || echo unknown`
/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`
/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`

_ASUNAME

as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
  echo "PATH: $as_dir"
done
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    printf "%s\n" "PATH: $as_dir"
  done
IFS=$as_save_IFS

} >&5

cat >&5 <<_ACEOF


## ----------- ##
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048


1049
1050
1051

1052
1053

1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069

1070
1071
1072
1073
1074
1075
1076
1077


1078
1079
1080
1081
1082
1083


1084


1085
1086
1087
1088
1089
1090

1091
1092

1093
1094
1095




1096












1097
1098
1099


1100
1101
1102
1103



1104
1105
1106

1107
1108

1109


1110
1111
1112
1113

1114
1115

1116
1117
1118
1119
1120
1121





1122
1123
1124
1125
1126
1127
1128
1129



1130
1131
1132
1133
1134
1135





1136
1137
1138
1139
1140
1141
1142

1143
1144

1145
1146
1147

1148
1149
1150
1151
1152


1153
1154
1155


1156
1157

1158
1159

1160
1161
1162
1163
1164
1165
1166



1167
1168
1169
1170
1171

1172
1173
1174
1175
1176

1177
1178
1179
1180
1181

1182
1183
1184
1185
1186

1187
1188

1189
1190

1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207




















1208
1209





1210
1211
1212
1213
1214
1215
1216
1217
1218





1219
1220
1221


1222
1223
1224
1225
1226


1227
1228
1229





























































































































































































































































































































1230
1231
1232
1233

1234
1235
1236
1237
1238


1239
1240
1241
1242


1243
1244
1245
1246


1247
1248
1249
1250




1251
1252
1253
1254
1255
1256












1257
1258
1259
1260
1261
1262
1263
1264

1265
1266
1267
1268
1269

1270
1271
1272
1273


1274
1275
1276
1277




1278
1279



1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312

1313
1314
1315


1316
1317
1318
1319
1320
1321
1322
1773
1774
1775
1776
1777
1778
1779

1780
1781
1782
1783
1784
1785
1786
1787
1788
1789


1790
1791
1792
1793

1794
1795

1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811

1812


1813
1814
1815
1816


1817
1818
1819
1820
1821
1822


1823
1824
1825
1826
1827
1828
1829
1830
1831


1832
1833

1834

1835
1836
1837
1838
1839
1840

1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853


1854
1855
1856



1857
1858
1859
1860


1861
1862

1863

1864
1865
1866
1867


1868
1869

1870

1871
1872
1873


1874
1875
1876
1877
1878
1879
1880
1881
1882




1883
1884
1885

1886
1887
1888


1889
1890
1891
1892
1893
1894
1895
1896
1897
1898


1899
1900

1901

1902

1903
1904
1905
1906


1907
1908
1909


1910
1911
1912

1913
1914

1915
1916
1917
1918
1919



1920
1921
1922
1923
1924
1925


1926

1927



1928

1929



1930

1931



1932

1933
1934
1935

1936


1937
1938
1939












1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960

1961
1962
1963
1964
1965
1966
1967
1968
1969





1970
1971
1972
1973
1974
1975


1976
1977
1978
1979
1980


1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305

2306

2307
2308


2309
2310
2311
2312


2313
2314
2315
2316


2317
2318
2319
2320
2321
2322
2323
2324
2325
2326






2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338

2339
2340
2341
2342
2343


2344
2345
2346
2347
2348

2349
2350
2351
2352
2353
2354
2355




2356
2357
2358
2359

2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
















2375
2376
2377
2378
2379

2380
2381


2382
2383
2384
2385
2386
2387
2388
2389
2390







-










-
-
+
+


-
+

-
+















-
+
-
-




-
-
+
+




-
-
+
+

+
+




-
-
+

-
+
-


+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+

-
-
+
+

-
-
-
+
+
+

-
-
+

-
+
-
+
+


-
-
+

-
+
-



-
-
+
+
+
+
+




-
-
-
-
+
+
+
-



-
-
+
+
+
+
+





-
-
+

-
+
-

-
+



-
-
+
+

-
-
+
+

-
+

-
+




-
-
-
+
+
+



-
-
+
-

-
-
-
+
-

-
-
-
+
-

-
-
-
+
-

+

-
+
-
-



-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+
+
+
+
+




-
-
-
-
-
+
+
+
+
+

-
-
+
+



-
-
+
+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
+
-


-
-
+
+


-
-
+
+


-
-
+
+




+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-





-
-
+




-
+




+
+
-
-
-
-
+
+
+
+
-

+
+
+











-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-





-
+

-
-
+
+







# Strip out --no-create and --no-recursion so they do not pile up.
# Strip out --silent because we don't want to record it for future runs.
# Also quote any args containing shell meta-characters.
# Make two passes to allow for proper duplicate-argument suppression.
ac_configure_args=
ac_configure_args0=
ac_configure_args1=
ac_sep=
ac_must_keep_next=false
for ac_pass in 1 2
do
  for ac_arg
  do
    case $ac_arg in
    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
    | -silent | --silent | --silen | --sile | --sil)
      continue ;;
    *" "*|*"	"*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
      ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
    *\'*)
      ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
    esac
    case $ac_pass in
    1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
    1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
    2)
      ac_configure_args1="$ac_configure_args1 '$ac_arg'"
      as_fn_append ac_configure_args1 " '$ac_arg'"
      if test $ac_must_keep_next = true; then
	ac_must_keep_next=false # Got value, back to normal.
      else
	case $ac_arg in
	  *=* | --config-cache | -C | -disable-* | --disable-* \
	  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
	  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
	  | -with-* | --with-* | -without-* | --without-* | --x)
	    case "$ac_configure_args0 " in
	      "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
	    esac
	    ;;
	  -* ) ac_must_keep_next=true ;;
	esac
      fi
      ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
      as_fn_append ac_configure_args " '$ac_arg'"
      # Get rid of the leading space.
      ac_sep=" "
      ;;
    esac
  done
done
$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
{ ac_configure_args0=; unset ac_configure_args0;}
{ ac_configure_args1=; unset ac_configure_args1;}

# When interrupted or exit'd, cleanup temporary files, and complete
# config.log.  We remove comments because anyway the quotes in there
# would cause problems or look ugly.
# WARNING: Be sure not to use single quotes in there, as some shells,
# such as our DU 5.0 friend, will then `close' the trap.
# WARNING: Use '\'' to represent an apostrophe within the trap.
# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
trap 'exit_status=$?
  # Sanitize IFS.
  IFS=" ""	$as_nl"
  # Save into config.log some information that might help in debugging.
  {
    echo

    cat <<\_ASBOX
## ---------------- ##
    printf "%s\n" "## ---------------- ##
## Cache variables. ##
## ---------------- ##
## ---------------- ##"
_ASBOX
    echo
    # The following way of writing the cache mishandles newlines in values,
(
  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
    eval ac_val=\$$ac_var
    case $ac_val in #(
{
    *${as_nl}*)
      case $ac_var in #(
      *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
      esac
      case $ac_var in #(
      _ | IFS | as_nl) ;; #(
      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
      *) { eval $ac_var=; unset $ac_var;} ;;
      esac ;;
    esac
  done
  (set) 2>&1 |
    case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in
    *ac_space=\ *)
    case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
    *${as_nl}ac_space=\ *)
      sed -n \
	"s/'"'"'/'"'"'\\\\'"'"''"'"'/g;
	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
      ;;
	"s/'\''/'\''\\\\'\'''\''/g;
	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
      ;; #(
    *)
      sed -n \
	"s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
      ;;
    esac;
    esac |
}
    sort
)
    echo

    cat <<\_ASBOX
## ----------------- ##
    printf "%s\n" "## ----------------- ##
## Output variables. ##
## ----------------- ##
## ----------------- ##"
_ASBOX
    echo
    for ac_var in $ac_subst_vars
    do
      eval ac_val=$`echo $ac_var`
      echo "$ac_var='"'"'$ac_val'"'"'"
      eval ac_val=\$$ac_var
      case $ac_val in
      *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
      esac
      printf "%s\n" "$ac_var='\''$ac_val'\''"
    done | sort
    echo

    if test -n "$ac_subst_files"; then
      cat <<\_ASBOX
## ------------- ##
## Output files. ##
## ------------- ##
      printf "%s\n" "## ------------------- ##
## File substitutions. ##
## ------------------- ##"
_ASBOX
      echo
      for ac_var in $ac_subst_files
      do
	eval ac_val=$`echo $ac_var`
	echo "$ac_var='"'"'$ac_val'"'"'"
	eval ac_val=\$$ac_var
	case $ac_val in
	*\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
	esac
	printf "%s\n" "$ac_var='\''$ac_val'\''"
      done | sort
      echo
    fi

    if test -s confdefs.h; then
      cat <<\_ASBOX
## ----------- ##
      printf "%s\n" "## ----------- ##
## confdefs.h. ##
## ----------- ##
## ----------- ##"
_ASBOX
      echo
      sed "/^$/d" confdefs.h | sort
      cat confdefs.h
      echo
    fi
    test "$ac_signal" != 0 &&
      echo "$as_me: caught signal $ac_signal"
    echo "$as_me: exit $exit_status"
      printf "%s\n" "$as_me: caught signal $ac_signal"
    printf "%s\n" "$as_me: exit $exit_status"
  } >&5
  rm -f core *.core &&
  rm -rf conftest* confdefs* conf$$* $ac_clean_files &&
  rm -f core *.core core.conftest.* &&
    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
    exit $exit_status
     ' 0
' 0
for ac_signal in 1 2 13 15; do
  trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
  trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
done
ac_signal=0

# confdefs.h avoids OS command line length limits that DEFS can exceed.
rm -rf conftest* confdefs.h
# AIX cpp loses on an empty file, so make sure it contains at least a newline.
echo >confdefs.h
rm -f -r conftest* confdefs.h

printf "%s\n" "/* confdefs.h */" > confdefs.h

# Predefined preprocessor variables.

cat >>confdefs.h <<_ACEOF
#define PACKAGE_NAME "$PACKAGE_NAME"
printf "%s\n" "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h
_ACEOF


cat >>confdefs.h <<_ACEOF
#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
printf "%s\n" "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h
_ACEOF


cat >>confdefs.h <<_ACEOF
#define PACKAGE_VERSION "$PACKAGE_VERSION"
printf "%s\n" "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h
_ACEOF


cat >>confdefs.h <<_ACEOF
#define PACKAGE_STRING "$PACKAGE_STRING"
printf "%s\n" "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h
_ACEOF

printf "%s\n" "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h

cat >>confdefs.h <<_ACEOF
printf "%s\n" "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h
#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
_ACEOF


# Let the site file select an alternate cache file if it wants to.
# Prefer explicitly selected file to automatically selected ones.
if test -z "$CONFIG_SITE"; then
  if test "x$prefix" != xNONE; then
    CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
  else
    CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
  fi
fi
for ac_site_file in $CONFIG_SITE; do
  if test -r "$ac_site_file"; then
    { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
echo "$as_me: loading site script $ac_site_file" >&6;}
# Prefer an explicitly selected file to automatically selected ones.
if test -n "$CONFIG_SITE"; then
  ac_site_files="$CONFIG_SITE"
elif test "x$prefix" != xNONE; then
  ac_site_files="$prefix/share/config.site $prefix/etc/config.site"
else
  ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
fi

for ac_site_file in $ac_site_files
do
  case $ac_site_file in #(
  */*) :
     ;; #(
  *) :
    ac_site_file=./$ac_site_file ;;
esac
  if test -f "$ac_site_file" && test -r "$ac_site_file"; then
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
printf "%s\n" "$as_me: loading site script $ac_site_file" >&6;}
    sed 's/^/| /' "$ac_site_file" >&5
    . "$ac_site_file"
    . "$ac_site_file" \
      || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "failed to load site script $ac_site_file
See \`config.log' for more details" "$LINENO" 5; }
  fi
done

if test -r "$cache_file"; then
  # Some versions of bash will fail to source /dev/null (special
  # files actually), so we avoid doing that.
  if test -f "$cache_file"; then
    { echo "$as_me:$LINENO: loading cache $cache_file" >&5
echo "$as_me: loading cache $cache_file" >&6;}
  # Some versions of bash will fail to source /dev/null (special files
  # actually), so we avoid doing that.  DJGPP emulates it as a regular file.
  if test /dev/null != "$cache_file" && test -f "$cache_file"; then
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
printf "%s\n" "$as_me: loading cache $cache_file" >&6;}
    case $cache_file in
      [\\/]* | ?:[\\/]* ) . $cache_file;;
      *)                      . ./$cache_file;;
      [\\/]* | ?:[\\/]* ) . "$cache_file";;
      *)                      . "./$cache_file";;
    esac
  fi
else
  { echo "$as_me:$LINENO: creating cache $cache_file" >&5
echo "$as_me: creating cache $cache_file" >&6;}
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
printf "%s\n" "$as_me: creating cache $cache_file" >&6;}
  >$cache_file
fi

# Test code for whether the C compiler supports C89 (global declarations)
ac_c_conftest_c89_globals='
/* Does the compiler advertise C89 conformance?
   Do not test the value of __STDC__, because some compilers set it to 0
   while being otherwise adequately conformant. */
#if !defined __STDC__
# error "Compiler does not advertise C89 conformance"
#endif

#include <stddef.h>
#include <stdarg.h>
struct stat;
/* Most of the following tests are stolen from RCS 5.7 src/conf.sh.  */
struct buf { int x; };
struct buf * (*rcsopen) (struct buf *, struct stat *, int);
static char *e (p, i)
     char **p;
     int i;
{
  return p[i];
}
static char *f (char * (*g) (char **, int), char **p, ...)
{
  char *s;
  va_list v;
  va_start (v,p);
  s = g (p, va_arg (v,int));
  va_end (v);
  return s;
}

/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
   function prototypes and stuff, but not \xHH hex character constants.
   These do not provoke an error unfortunately, instead are silently treated
   as an "x".  The following induces an error, until -std is added to get
   proper ANSI mode.  Curiously \x00 != x always comes out true, for an
   array size at least.  It is necessary to write \x00 == 0 to get something
   that is true only with -std.  */
int osf4_cc_array ['\''\x00'\'' == 0 ? 1 : -1];

/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
   inside strings and character constants.  */
#define FOO(x) '\''x'\''
int xlc6_cc_array[FOO(a) == '\''x'\'' ? 1 : -1];

int test (int i, double x);
struct s1 {int (*f) (int a);};
struct s2 {int (*f) (double a);};
int pairnames (int, char **, int *(*)(struct buf *, struct stat *, int),
               int, int);'

# Test code for whether the C compiler supports C89 (body of main).
ac_c_conftest_c89_main='
ok |= (argc == 0 || f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]);
'

# Test code for whether the C compiler supports C99 (global declarations)
ac_c_conftest_c99_globals='
// Does the compiler advertise C99 conformance?
#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L
# error "Compiler does not advertise C99 conformance"
#endif

#include <stdbool.h>
extern int puts (const char *);
extern int printf (const char *, ...);
extern int dprintf (int, const char *, ...);
extern void *malloc (size_t);

// Check varargs macros.  These examples are taken from C99 6.10.3.5.
// dprintf is used instead of fprintf to avoid needing to declare
// FILE and stderr.
#define debug(...) dprintf (2, __VA_ARGS__)
#define showlist(...) puts (#__VA_ARGS__)
#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__))
static void
test_varargs_macros (void)
{
  int x = 1234;
  int y = 5678;
  debug ("Flag");
  debug ("X = %d\n", x);
  showlist (The first, second, and third items.);
  report (x>y, "x is %d but y is %d", x, y);
}

// Check long long types.
#define BIG64 18446744073709551615ull
#define BIG32 4294967295ul
#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0)
#if !BIG_OK
  #error "your preprocessor is broken"
#endif
#if BIG_OK
#else
  #error "your preprocessor is broken"
#endif
static long long int bignum = -9223372036854775807LL;
static unsigned long long int ubignum = BIG64;

struct incomplete_array
{
  int datasize;
  double data[];
};

struct named_init {
  int number;
  const wchar_t *name;
  double average;
};

typedef const char *ccp;

static inline int
test_restrict (ccp restrict text)
{
  // See if C++-style comments work.
  // Iterate through items via the restricted pointer.
  // Also check for declarations in for loops.
  for (unsigned int i = 0; *(text+i) != '\''\0'\''; ++i)
    continue;
  return 0;
}

// Check varargs and va_copy.
static bool
test_varargs (const char *format, ...)
{
  va_list args;
  va_start (args, format);
  va_list args_copy;
  va_copy (args_copy, args);

  const char *str = "";
  int number = 0;
  float fnumber = 0;

  while (*format)
    {
      switch (*format++)
	{
	case '\''s'\'': // string
	  str = va_arg (args_copy, const char *);
	  break;
	case '\''d'\'': // int
	  number = va_arg (args_copy, int);
	  break;
	case '\''f'\'': // float
	  fnumber = va_arg (args_copy, double);
	  break;
	default:
	  break;
	}
    }
  va_end (args_copy);
  va_end (args);

  return *str && number && fnumber;
}
'

# Test code for whether the C compiler supports C99 (body of main).
ac_c_conftest_c99_main='
  // Check bool.
  _Bool success = false;
  success |= (argc != 0);

  // Check restrict.
  if (test_restrict ("String literal") == 0)
    success = true;
  char *restrict newvar = "Another string";

  // Check varargs.
  success &= test_varargs ("s, d'\'' f .", "string", 65, 34.234);
  test_varargs_macros ();

  // Check flexible array members.
  struct incomplete_array *ia =
    malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10));
  ia->datasize = 10;
  for (int i = 0; i < ia->datasize; ++i)
    ia->data[i] = i * 1.234;

  // Check named initializers.
  struct named_init ni = {
    .number = 34,
    .name = L"Test wide string",
    .average = 543.34343,
  };

  ni.number = 58;

  int dynamic_array[ni.number];
  dynamic_array[0] = argv[0][0];
  dynamic_array[ni.number - 1] = 543;

  // work around unused variable warnings
  ok |= (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == '\''x'\''
	 || dynamic_array[ni.number - 1] != 543);
'

# Test code for whether the C compiler supports C11 (global declarations)
ac_c_conftest_c11_globals='
// Does the compiler advertise C11 conformance?
#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L
# error "Compiler does not advertise C11 conformance"
#endif

// Check _Alignas.
char _Alignas (double) aligned_as_double;
char _Alignas (0) no_special_alignment;
extern char aligned_as_int;
char _Alignas (0) _Alignas (int) aligned_as_int;

// Check _Alignof.
enum
{
  int_alignment = _Alignof (int),
  int_array_alignment = _Alignof (int[100]),
  char_alignment = _Alignof (char)
};
_Static_assert (0 < -_Alignof (int), "_Alignof is signed");

// Check _Noreturn.
int _Noreturn does_not_return (void) { for (;;) continue; }

// Check _Static_assert.
struct test_static_assert
{
  int x;
  _Static_assert (sizeof (int) <= sizeof (long int),
                  "_Static_assert does not work in struct");
  long int y;
};

// Check UTF-8 literals.
#define u8 syntax error!
char const utf8_literal[] = u8"happens to be ASCII" "another string";

// Check duplicate typedefs.
typedef long *long_ptr;
typedef long int *long_ptr;
typedef long_ptr long_ptr;

// Anonymous structures and unions -- taken from C11 6.7.2.1 Example 1.
struct anonymous
{
  union {
    struct { int i; int j; };
    struct { int k; long int l; } w;
  };
  int m;
} v1;
'

# Test code for whether the C compiler supports C11 (body of main).
ac_c_conftest_c11_main='
  _Static_assert ((offsetof (struct anonymous, i)
		   == offsetof (struct anonymous, w.k)),
		  "Anonymous union alignment botch");
  v1.i = 2;
  v1.w.k = 5;
  ok |= v1.i != 5;
'

# Test code for whether the C compiler supports C11 (complete).
ac_c_conftest_c11_program="${ac_c_conftest_c89_globals}
${ac_c_conftest_c99_globals}
${ac_c_conftest_c11_globals}

int
main (int argc, char **argv)
{
  int ok = 0;
  ${ac_c_conftest_c89_main}
  ${ac_c_conftest_c99_main}
  ${ac_c_conftest_c11_main}
  return ok;
}
"

# Test code for whether the C compiler supports C99 (complete).
ac_c_conftest_c99_program="${ac_c_conftest_c89_globals}
${ac_c_conftest_c99_globals}

int
main (int argc, char **argv)
{
  int ok = 0;
  ${ac_c_conftest_c89_main}
  ${ac_c_conftest_c99_main}
  return ok;
}
"

# Test code for whether the C compiler supports C89 (complete).
ac_c_conftest_c89_program="${ac_c_conftest_c89_globals}

int
main (int argc, char **argv)
{
  int ok = 0;
  ${ac_c_conftest_c89_main}
  return ok;
}
"

as_fn_append ac_header_c_list " stdio.h stdio_h HAVE_STDIO_H"
as_fn_append ac_header_c_list " stdlib.h stdlib_h HAVE_STDLIB_H"
as_fn_append ac_header_c_list " string.h string_h HAVE_STRING_H"
as_fn_append ac_header_c_list " inttypes.h inttypes_h HAVE_INTTYPES_H"
as_fn_append ac_header_c_list " stdint.h stdint_h HAVE_STDINT_H"
as_fn_append ac_header_c_list " strings.h strings_h HAVE_STRINGS_H"
as_fn_append ac_header_c_list " sys/stat.h sys_stat_h HAVE_SYS_STAT_H"
as_fn_append ac_header_c_list " sys/types.h sys_types_h HAVE_SYS_TYPES_H"
as_fn_append ac_header_c_list " unistd.h unistd_h HAVE_UNISTD_H"
# Check that the precious variables saved in the cache have kept the same
# value.
ac_cache_corrupted=false
for ac_var in `(set) 2>&1 |
for ac_var in $ac_precious_vars; do
	       sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do
  eval ac_old_set=\$ac_cv_env_${ac_var}_set
  eval ac_new_set=\$ac_env_${ac_var}_set
  eval ac_old_val="\$ac_cv_env_${ac_var}_value"
  eval ac_new_val="\$ac_env_${ac_var}_value"
  eval ac_old_val=\$ac_cv_env_${ac_var}_value
  eval ac_new_val=\$ac_env_${ac_var}_value
  case $ac_old_set,$ac_new_set in
    set,)
      { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
printf "%s\n" "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
      ac_cache_corrupted=: ;;
    ,set)
      { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
printf "%s\n" "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
      ac_cache_corrupted=: ;;
    ,);;
    *)
      if test "x$ac_old_val" != "x$ac_new_val"; then
	# differences in whitespace do not lead to failure.
	ac_old_val_w=`echo x $ac_old_val`
	ac_new_val_w=`echo x $ac_new_val`
	if test "$ac_old_val_w" != "$ac_new_val_w"; then
	{ echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
	{ echo "$as_me:$LINENO:   former value:  $ac_old_val" >&5
echo "$as_me:   former value:  $ac_old_val" >&2;}
	{ echo "$as_me:$LINENO:   current value: $ac_new_val" >&5
echo "$as_me:   current value: $ac_new_val" >&2;}
	  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
printf "%s\n" "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
	  ac_cache_corrupted=:
	else
	  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
printf "%s\n" "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
	  eval $ac_var=\$ac_old_val
	fi
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}:   former value:  \`$ac_old_val'" >&5
printf "%s\n" "$as_me:   former value:  \`$ac_old_val'" >&2;}
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}:   current value: \`$ac_new_val'" >&5
printf "%s\n" "$as_me:   current value: \`$ac_new_val'" >&2;}
	ac_cache_corrupted=:
      fi;;
  esac
  # Pass precious variables to config.status.
  if test "$ac_new_set" = set; then
    case $ac_new_val in
    *" "*|*"	"*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
      ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
    *\'*) ac_arg=$ac_var=`printf "%s\n" "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
    *) ac_arg=$ac_var=$ac_new_val ;;
    esac
    case " $ac_configure_args " in
      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
      *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
      *) as_fn_append ac_configure_args " '$ac_arg'" ;;
    esac
  fi
done
if $ac_cache_corrupted; then
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
  { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
echo "$as_me: error: changes in the environment can compromise the build" >&2;}
  { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
printf "%s\n" "$as_me: error: changes in the environment can compromise the build" >&2;}
  as_fn_error $? "run \`${MAKE-make} distclean' and/or \`rm $cache_file'
	    and start over" "$LINENO" 5
   { (exit 1); exit 1; }; }
fi
## -------------------- ##
## Main body of script. ##
## -------------------- ##

ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu





















# The following define is needed when building with Cygwin since newer
# versions of autoconf incorrectly set SHELL to /bin/bash instead of
# /bin/sh. The bash shell seems to suffer from some strange failures.
SHELL=/bin/sh

TK_VERSION=8.6
TK_VERSION=8.7
TK_MAJOR_VERSION=8
TK_MINOR_VERSION=6
TK_PATCH_LEVEL=".10"
TK_MINOR_VERSION=7
TK_PATCH_LEVEL="a4"
VER=$TK_MAJOR_VERSION$TK_MINOR_VERSION

#------------------------------------------------------------------------
# Handle the --prefix=... option
#------------------------------------------------------------------------

if test "${prefix}" = "NONE"; then
1333
1334
1335
1336
1337
1338
1339









1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353






1354
1355
1356
1357
1358
1359
1360

1361
1362
1363






1364
1365

1366
1367
1368
1369


1370
1371
1372
1373
1374
1375
1376


1377
1378
1379


1380

1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391






1392
1393
1394
1395
1396
1397
1398

1399
1400
1401






1402
1403

1404
1405
1406
1407


1408
1409
1410
1411
1412
1413
1414


1415
1416
1417


1418
1419









1420


1421
1422
1423
1424
1425
1426
1427


1428
1429
1430
1431
1432
1433






1434
1435
1436
1437
1438
1439
1440

1441
1442
1443






1444
1445

1446
1447
1448
1449


1450
1451
1452
1453
1454
1455
1456


1457
1458

1459
1460
1461

1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503

1504
1505
1506
1507
1508
1509
1510
1511
1512
1513






1514
1515
1516
1517
1518
1519
1520
1521

1522
1523
1524
1525







1526
1527
1528
1529
1530

1531
1532
1533
1534


1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545

1546
1547
1548
1549
1550
1551






1552
1553




























































































1554



1555
1556
















1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570








1571
1572
1573
1574
1575
1576
1577

1578
1579
1580
1581
1582








1583
1584
1585
1586


1587
1588
1589
1590
1591
1592
1593


1594
1595
1596


1597
1598
1599

1600
1601
1602

1603
1604
1605
1606
1607
1608
1609
1610
1611
1612








1613
1614
1615
1616
1617
1618
1619

1620
1621
1622
1623
1624








1625
1626
1627
1628


1629
1630
1631
1632
1633
1634
1635


1636
1637
1638


1639
1640
1641
1642
1643
1644













1645
1646
1647
1648
1649
1650
1651
1652
1653




1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664








1665
1666
1667
1668
1669



1670
1671

1672







1673
1674



1675
1676

1677
1678
1679
1680
1681
1682
1683
1684

1685
1686
1687
1688
1689
1690
1691
1692

1693
1694
1695



1696
1697
1698
1699
1700






















1701
1702
1703


1704
1705
1706
1707


1708
1709
1710
1711
1712





1713
1714
1715
1716

1717
1718
1719
1720
1721
1722
1723
1724
1725


1726
1727



1728
1729
1730




1731
1732
1733
1734
1735


1736
1737








1738
1739

1740

1741
1742
1743


1744



1745
1746




1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782

1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794










1795
1796
1797



1798
1799
1800
1801
1802
1803
1804
1805

1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816





1817
1818
1819
1820
1821
1822



1823
1824
1825
1826








1827
1828
1829
1830
1831
1832
1833
1834
1835
1836


























































1837
1838
1839
1840

1841
1842
1843
1844
1845
1846
1847
1848
1849








1850
1851
1852
1853





1854
1855

1856
1857
1858
1859
1860
1861


1862
1863
1864
1865
1866
1867




1868
1869
1870
1871
1872
1873
1874


1875
1876
1877
1878
1879
1880
1881
1882







1883
1884
1885
1886
1887
1888
1889
1890

1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902

1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921

1922
1923

1924
1925
1926
1927

1928
1929

1930
1931
1932
1933
1934
1935
1936










1937









1938
1939
1940
1941















1942
1943
1944
1945












1946


1947
1948





1949
1950
1951
1952

1953
1954
1955
1956
1957
1958
1959
1960
1961

1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980

1981
1982
1983
1984
1985



1986

1987
1988


1989
1990
1991
1992



1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012







2013
2014
2015



2016










2017
2018















































































2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042

2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068

2069
2070
2071
2072
2073

2074
2075
2076
2077
2078

2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098


2099
2100
2101
2102
2103
2104
2105


2106
2107

2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119














2120
2121

2122
2123
2124
2125
2126
2127
2128
2129

2130
2131
2132
2133
2134

2135
2136
2137
2138
2139
2140
2141
2142
2143

2144
2145
2146
2147
2148
2149
2150


2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180

2181
2182

2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199

2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216

2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276






2277
2278
2279

2280
2281
2282
2283
2284
2285
2286
2287
2288


2289
2290
2291
2292
2293
2294

2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314


2315
2316
2317
2318
2319
2320


2321
2322
2323
2324
2325


2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343

2344
2345
2346
2347

2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361


2362
2363
2364


2365
2366
2367
2368
2369
2370
2371

2372
2373
2374
2375
2376
2377
2378
2379
2380

2381
2382
2383
2384
2385

2386
2387
2388
2389
2390
2391
2392


2393
2394
2395

2396

2397
2398
2399
2400
2401
2402
2403







2404
2405
2406
2407


2408
2409
2410
2411
2412
2413
2414

2415
2416
2417
2418
2419
2420

2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435







2436
2437
2438

2439
2440
2441
2442






2443
2444
2445




2446
2447

2448
2449
2450
2451


2452
2453
2454


2455
2456
2457

2458
2459
2460



2461
2462


2463
2464
2465




2466
2467
2468
2469
2470

2471
2472
2473
2474
2475
2476
2477

2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495


2496
2497
2498
2499
2500





2501
2502


2503
2504
2505
2506
2507



2508
2509
2510
2511
2512

2513
2514

2515
2516
2517


2518
2519
2520
2521
2522
2523
2524
2525
2526



2527
2528
2529
2530
2531
2532
2533
2534



2535
2536

2537
2538
2539
2540

2541
2542
2543

2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557

2558
2559
2560
2561
2562



2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576


2577
2578
2579
2580
2581
2582
2583
2584








2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597

2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608







2609
2610

2611
2612
2613


2614
2615
2616
2617
2618

2619
2620

2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633






2634
2635
2636


2637
2638
2639
2640
2641
2642
2643
2644


2645
2646
2647
2648


2649
2650
2651
2652
2653
2654
2655
2656
2657




2658
2659

2660
2661
2662
2663
2664
2665
2666


2667
2668

2669
2670
2671

2672
2673
2674
2675


2676
2677
2678

2679
2680
2681
2682
2683
2684

2685
2686
2687
2688
2689
2690




2691
2692
2693
2694
2695
2696

2697
2698
2699

2700
2701
2702
2703
2704
2705

2706
2707
2708
2709
2710
2711
2712
2713
2714
2715



2716
2717

2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728

2729
2730
2731
2732
2733
2734
2735

2736


2737
2738
2739
2740
2741

2742
2743
2744
2745
2746


2747
2748
2749
2750
2751



2752
2753

2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767






2768
2769
2770
2771
2772
2773
2774

2775
2776
2777






2778
2779

2780
2781
2782
2783


2784
2785
2786
2787
2788
2789
2790


2791
2792
2793


2794

2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805






2806
2807
2808
2809
2810
2811
2812

2813
2814
2815






2816
2817

2818
2819
2820
2821


2822
2823
2824
2825
2826
2827
2828


2829
2830
2831


2832
2833









2834


2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846






2847
2848
2849
2850
2851
2852
2853

2854
2855
2856






2857
2858

2859
2860
2861
2862


2863
2864
2865
2866
2867
2868
2869


2870
2871
2872


2873

2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884






2885
2886
2887
2888
2889
2890
2891

2892
2893
2894






2895
2896

2897
2898
2899
2900


2901
2902
2903
2904
2905
2906
2907


2908
2909
2910


2911
2912









2913


2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925






2926
2927
2928
2929
2930
2931
2932

2933
2934
2935






2936
2937

2938
2939
2940
2941


2942
2943
2944
2945
2946
2947
2948


2949
2950
2951


2952

2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963






2964
2965
2966
2967
2968
2969
2970

2971
2972
2973






2974
2975

2976
2977
2978
2979


2980
2981
2982
2983
2984
2985
2986


2987
2988
2989


2990
2991









2992


2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003


3004
3005
3006
3007
3008





3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025


3026
3027
3028
3029


3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087




3088
3089
3090
3091
3092
3093

3094
3095
3096
3097
3098
3099




3100
3101
3102
3103


3104
3105
3106
3107


3108
3109
3110
3111

3112
3113
3114

3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141












3142
3143
3144
3145
3146
3147
3148
3149
3150


3151
3152
3153
3154
3155
3156
3157
3158

3159
3160
3161
3162
3163
3164
3165
3166
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425





2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439



2440
2441
2442
2443
2444
2445
2446

2447
2448
2449
2450

2451
2452
2453
2454
2455
2456
2457


2458
2459
2460


2461
2462
2463
2464
2465
2466
2467
2468
2469
2470





2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484



2485
2486
2487
2488
2489
2490
2491

2492
2493
2494
2495

2496
2497
2498
2499
2500
2501
2502


2503
2504
2505


2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518

2519
2520
2521
2522
2523
2524
2525


2526
2527
2528





2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542



2543
2544
2545
2546
2547
2548
2549

2550
2551
2552
2553

2554
2555
2556
2557
2558
2559
2560


2561
2562
2563

2564



2565
2566

























2567










2568




2569

2570
2571
2572
2573





2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588




2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599

2600
2601
2602
2603

2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615

2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628


2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724


2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745









2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761





2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772

2773
2774
2775
2776
2777
2778
2779


2780
2781
2782


2783
2784
2785
2786

2787

2788

2789
2790









2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806





2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817

2818
2819
2820
2821
2822
2823
2824


2825
2826
2827


2828
2829
2830
2831




2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849




2850
2851
2852
2853

2854
2855








2856
2857
2858
2859
2860
2861
2862
2863





2864
2865
2866


2867
2868
2869
2870
2871
2872
2873
2874
2875


2876
2877
2878
2879

2880




2881
2882
2883

2884
2885
2886
2887
2888
2889
2890
2891

2892
2893
2894
2895
2896
2897
2898





2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921


2922
2923




2924
2925





2926
2927
2928
2929
2930
2931
2932
2933

2934



2935
2936
2937
2938
2939
2940
2941
2942


2943
2944
2945



2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956


2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967

2968



2969
2970

2971
2972
2973
2974

2975
2976
2977
2978
2979


2980
































2981
2982











2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993


2994
2995
2996
2997
2998
2999
3000
3001
3002
3003

3004
3005

3006
3007
3008
3009





3010
3011
3012
3013
3014

3015




3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030










3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091

3092
3093
3094
3095
3096
3097
3098
3099


3100
3101
3102
3103
3104
3105
3106
3107
3108



3109
3110
3111
3112
3113
3114

3115
3116
3117
3118
3119


3120
3121
3122
3123




3124
3125
3126
3127

3128

3129
3130


3131
3132
3133
3134






3135
3136
3137
3138
3139
3140
3141




3142
3143
3144

3145
3146
3147
3148
3149
3150
3151
3152
3153
3154



3155



















3156
3157

3158




3159
3160

3161
3162
3163
3164




3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184




3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199




3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214


3215
3216
3217
3218
3219
3220
3221
3222

3223
3224
3225
3226
3227
3228
3229



3230



















3231
3232




3233
3234
3235

3236
3237

3238
3239
3240



3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257






3258
3259
3260
3261
3262
3263
3264
3265


3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279


3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359























3360






















3361



3362





3363
3364
3365



3366




















3367
3368





3369

3370
3371
3372

3373
3374
3375
3376









3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391

3392








3393





3394









3395







3396
3397






























3398


3399

















3400





3401











3402
































3403








3404






3405
3406
3407
3408
3409
3410
3411





3412
3413
3414
3415
3416
3417
3418
3419

3420




3421
3422
3423


3424
3425
3426
3427
3428



3429




















3430
3431




3432

3433
3434
3435
3436
3437


3438
3439

3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455

3456




3457














3458
3459



3460
3461







3462









3463





3464







3465
3466

3467

3468
3469
3470







3471
3472
3473
3474
3475
3476
3477

3478


3479
3480


3481




3482






3483















3484
3485
3486
3487
3488
3489
3490



3491




3492
3493
3494
3495
3496
3497



3498
3499
3500
3501


3502




3503
3504



3505
3506



3507



3508
3509
3510


3511
3512



3513
3514
3515
3516





3517







3518


















3519
3520





3521
3522
3523
3524
3525


3526
3527





3528
3529
3530





3531


3532



3533
3534









3535
3536
3537








3538
3539
3540


3541




3542
3543
3544

3545
3546






3547



3548


3549





3550
3551
3552







3553






3554
3555
3556







3557
3558
3559
3560
3561
3562
3563
3564













3565











3566
3567
3568
3569
3570
3571
3572


3573



3574
3575





3576


3577













3578
3579
3580
3581
3582
3583



3584
3585








3586
3587




3588
3589









3590
3591
3592
3593


3594







3595
3596


3597



3598




3599
3600



3601






3602






3603
3604
3605
3606






3607



3608






3609






3610



3611
3612
3613


3614











3615







3616

3617
3618
3619




3620


3621


3622
3623
3624




3625
3626
3627
3628

3629


3630

3631
3632
3633
3634
3635





3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649



3650
3651
3652
3653
3654
3655
3656

3657
3658
3659
3660

3661
3662
3663
3664
3665
3666
3667


3668
3669
3670


3671
3672
3673
3674
3675
3676
3677
3678
3679
3680





3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694



3695
3696
3697
3698
3699
3700
3701

3702
3703
3704
3705

3706
3707
3708
3709
3710
3711
3712


3713
3714
3715


3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728

3729
3730
3731
3732
3733
3734
3735
3736
3737





3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751



3752
3753
3754
3755
3756
3757
3758

3759
3760
3761
3762

3763
3764
3765
3766
3767
3768
3769


3770
3771
3772


3773
3774
3775
3776
3777
3778
3779
3780
3781
3782





3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796



3797
3798
3799
3800
3801
3802
3803

3804
3805
3806
3807

3808
3809
3810
3811
3812
3813
3814


3815
3816
3817


3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830

3831
3832
3833
3834
3835
3836
3837
3838
3839





3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853



3854
3855
3856
3857
3858
3859
3860

3861
3862
3863
3864

3865
3866
3867
3868
3869
3870
3871


3872
3873
3874


3875
3876
3877
3878
3879
3880
3881
3882
3883
3884





3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898



3899
3900
3901
3902
3903
3904
3905

3906
3907
3908
3909

3910
3911
3912
3913
3914
3915
3916


3917
3918
3919


3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932

3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943


3944
3945
3946




3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966


3967
3968
3969
3970


3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984





































3985
3986
3987
3988
3989




3990
3991
3992
3993






3994






3995
3996
3997
3998
3999
4000


4001
4002
4003
4004


4005
4006
4007
4008


4009

4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029










4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048


4049
4050
4051
4052
4053
4054
4055
4056


4057

4058
4059
4060
4061
4062
4063
4064







+
+
+
+
+
+
+
+
+









-
-
-
-
-
+
+
+
+
+
+







+
-
-
-
+
+
+
+
+
+

-
+



-
+
+





-
-
+
+

-
-
+
+

+






-
-
-
-
-
+
+
+
+
+
+







+
-
-
-
+
+
+
+
+
+

-
+



-
+
+





-
-
+
+

-
-
+
+


+
+
+
+
+
+
+
+
+
-
+
+





-
-
+
+

-
-
-
-
-
+
+
+
+
+
+







+
-
-
-
+
+
+
+
+
+

-
+



-
+
+





-
-
+
+

-
+
-
-
-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
-
-
-
-
-
-
-
-

-
-
-
-
+
-




-
-
-
-
-
+
+
+
+
+
+








+
-
-
-
-
+
+
+
+
+
+
+




-
+



-
+
+










-
+






+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+







+
-
-
-
-
-
+
+
+
+
+
+
+
+



-
+
+





-
-
+
+

-
-
+
+


-
+
-

-
+

-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+







+
-
-
-
-
-
+
+
+
+
+
+
+
+



-
+
+





-
-
+
+

-
-
+
+


-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+





-
-
-
-
+
+
+
+
-


-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
-
-
+

+
+
+
+
+
+
+
-
-
+
+
+

-
+
-
-
-
-



-
+







-
+



+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
+
+
-
-
-
-
+
+
-
-
-
-
-
+
+
+
+
+



-
+
-
-
-






+
+
-
-
+
+
+
-
-
-
+
+
+
+





+
+
-
-
+
+
+
+
+
+
+
+


+
-
+
-
-
-
+
+
-
+
+
+

-
+
+
+
+

-
-

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+

-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+

-
-
+
+
+







-
+

-




-
-
-
-
-
+
+
+
+
+
-

-
-
-
-
+
+
+




+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
+







-
-
+
+
+
+
+
+
+
+

-
-
-
+
+
+
+
+

-
+




-
-
+
+


-
-
-
-
+
+
+
+
-

-


-
-
+
+


-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-



-
+









-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+

-
+
-
-
-
-
+

-
+



-
-
-
-
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+

+
+
-
-
+
+
+
+
+



-
+






-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+

-
-
-
-
+
+
+
-
+

-
+
+

-
-
-
+
+
+














-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
+
+
+

+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
-
+
-
-
-
-
-
+


-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-

-
+
+

-
+



-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+
-
-
-
-
-
-
-
-
+
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-

-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
-
-
-
-
-
-

-
-
-
-
-
-







-
-
-
-
-
+
+
+
+
+
+


-
+
-
-
-
-



-
-
+
+



-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-

-
+
+



-
-
+
+
-
















-
+
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
+
+
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
+
-
-
-
-
-
-
-
+
+
-

-
+

+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-

-
-
+
+
-
-

-
-
-
-
+
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
+
-
-
-
-
+
+
+
+
+
+
-
-
-
+
+
+
+
-
-
+
-
-
-
-
+
+
-
-
-
+
+
-
-
-
+
-
-
-
+
+
+
-
-
+
+
-
-
-
+
+
+
+
-
-
-
-
-
+
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
+
+
+
+
+
-
-
+
+
-
-
-
-
-
+
+
+
-
-
-
-
-
+
-
-
+
-
-
-
+
+
-
-
-
-
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
+
+
+
-
-
+
-
-
-
-
+


-
+

-
-
-
-
-
-

-
-
-

-
-
+
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-

-
-
-
-
-
-
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
+
-
-
-
+
+
-
-
-
-
-
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
+
+
-
-
-
-
-
-
-
-
+
+
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
+
-
-
-
-
-
-
-
+
+
-
-
+
-
-
-
+
-
-
-
-
+
+
-
-
-
+
-
-
-
-
-
-
+
-
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
+
-
-
-
+
-
-
-
-
-
-
+
-
-
-
-
-
-

-
-
-
+
+
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
+
-
+
+

-
-
-
-
+
-
-

-
-
+
+

-
-
-
-
+
+
+

-
+
-
-

-





-
-
-
-
-
+
+
+
+
+
+







+
-
-
-
+
+
+
+
+
+

-
+



-
+
+





-
-
+
+

-
-
+
+

+






-
-
-
-
-
+
+
+
+
+
+







+
-
-
-
+
+
+
+
+
+

-
+



-
+
+





-
-
+
+

-
-
+
+


+
+
+
+
+
+
+
+
+
-
+
+







-
-
-
-
-
+
+
+
+
+
+







+
-
-
-
+
+
+
+
+
+

-
+



-
+
+





-
-
+
+

-
-
+
+

+






-
-
-
-
-
+
+
+
+
+
+







+
-
-
-
+
+
+
+
+
+

-
+



-
+
+





-
-
+
+

-
-
+
+


+
+
+
+
+
+
+
+
+
-
+
+







-
-
-
-
-
+
+
+
+
+
+







+
-
-
-
+
+
+
+
+
+

-
+



-
+
+





-
-
+
+

-
-
+
+

+






-
-
-
-
-
+
+
+
+
+
+







+
-
-
-
+
+
+
+
+
+

-
+



-
+
+





-
-
+
+

-
-
+
+


+
+
+
+
+
+
+
+
+
-
+
+









-
-
+
+

-
-
-
-
+
+
+
+
+















-
-
+
+


-
-
+
+












-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-





-
-
-
-
+
+
+
+
-
-
-
-
-
-
+
-
-
-
-
-
-
+
+
+
+


-
-
+
+


-
-
+
+


-
-
+
-


+

















-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+







-
-
+
+






-
-
+
-







#------------------------------------------------------------------------

# If the user did not set CFLAGS, set it now to keep
# the AC_PROG_CC macro from adding "-g -O2".
if test "${CFLAGS+set}" != "set" ; then
    CFLAGS=""
fi










ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
if test -n "$ac_tool_prefix"; then
  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
set dummy ${ac_tool_prefix}gcc; ac_word=$2
echo "$as_me:$LINENO: checking for $ac_word" >&5
echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
if test "${ac_cv_prog_CC+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_CC+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  if test -n "$CC"; then
  ac_cv_prog_CC="$CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
  for ac_exec_ext in '' $ac_executable_extensions; do
  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_CC="${ac_tool_prefix}gcc"
    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
done
  done
IFS=$as_save_IFS

fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
  echo "$as_me:$LINENO: result: $CC" >&5
echo "${ECHO_T}$CC" >&6
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
printf "%s\n" "$CC" >&6; }
else
  echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi


fi
if test -z "$ac_cv_prog_CC"; then
  ac_ct_CC=$CC
  # Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
echo "$as_me:$LINENO: checking for $ac_word" >&5
echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_CC+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  if test -n "$ac_ct_CC"; then
  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
  for ac_exec_ext in '' $ac_executable_extensions; do
  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_ac_ct_CC="gcc"
    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
done
  done
IFS=$as_save_IFS

fi
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
echo "${ECHO_T}$ac_ct_CC" >&6
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
printf "%s\n" "$ac_ct_CC" >&6; }
else
  echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi

  if test "x$ac_ct_CC" = x; then
    CC=""
  else
    case $cross_compiling:$ac_tool_warned in
yes:)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
  CC=$ac_ct_CC
    CC=$ac_ct_CC
  fi
else
  CC="$ac_cv_prog_CC"
fi

if test -z "$CC"; then
  if test -n "$ac_tool_prefix"; then
  # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
          if test -n "$ac_tool_prefix"; then
    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
set dummy ${ac_tool_prefix}cc; ac_word=$2
echo "$as_me:$LINENO: checking for $ac_word" >&5
echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
if test "${ac_cv_prog_CC+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_CC+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  if test -n "$CC"; then
  ac_cv_prog_CC="$CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
  for ac_exec_ext in '' $ac_executable_extensions; do
  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_CC="${ac_tool_prefix}cc"
    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
done
  done
IFS=$as_save_IFS

fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
  echo "$as_me:$LINENO: result: $CC" >&5
echo "${ECHO_T}$CC" >&6
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
printf "%s\n" "$CC" >&6; }
else
  echo "$as_me:$LINENO: result: no" >&5
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
echo "${ECHO_T}no" >&6
fi

printf "%s\n" "no" >&6; }
fi
if test -z "$ac_cv_prog_CC"; then
  ac_ct_CC=$CC
  # Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
echo "$as_me:$LINENO: checking for $ac_word" >&5
echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  if test -n "$ac_ct_CC"; then
  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  test -z "$as_dir" && as_dir=.
  for ac_exec_ext in '' $ac_executable_extensions; do
  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
    ac_cv_prog_ac_ct_CC="cc"
    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
done

fi
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
echo "${ECHO_T}$ac_ct_CC" >&6
else
  echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6
fi

  CC=$ac_ct_CC
else
  CC="$ac_cv_prog_CC"
fi
  fi

fi
if test -z "$CC"; then
  # Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
echo "$as_me:$LINENO: checking for $ac_word" >&5
echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
if test "${ac_cv_prog_CC+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_CC+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  if test -n "$CC"; then
  ac_cv_prog_CC="$CC" # Let the user override the test.
else
  ac_prog_rejected=no
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
  for ac_exec_ext in '' $ac_executable_extensions; do
  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
       ac_prog_rejected=yes
       continue
     fi
    ac_cv_prog_CC="cc"
    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
done
  done
IFS=$as_save_IFS

if test $ac_prog_rejected = yes; then
  # We found a bogon in the path, so make sure we never use it.
  set dummy $ac_cv_prog_CC
  shift
  if test $# != 0; then
    # We chose a different compiler from the bogus one.
    # However, it has the same basename, so the bogon will be chosen
    # first if we set CC to just the basename; use the full file name.
    shift
    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
    ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@"
  fi
fi
fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
printf "%s\n" "$CC" >&6; }
else
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
  echo "$as_me:$LINENO: result: $CC" >&5
echo "${ECHO_T}$CC" >&6


fi
if test -z "$CC"; then
  if test -n "$ac_tool_prefix"; then
  for ac_prog in cl.exe
  do
    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
set dummy $ac_tool_prefix$ac_prog; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_CC+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  if test -n "$CC"; then
  ac_cv_prog_CC="$CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
printf "%s\n" "$CC" >&6; }
else
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi


    test -n "$CC" && break
  done
fi
if test -z "$CC"; then
  ac_ct_CC=$CC
  for ac_prog in cl.exe
do
  # Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_CC+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  if test -n "$ac_ct_CC"; then
  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_ac_ct_CC="$ac_prog"
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

fi
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
printf "%s\n" "$ac_ct_CC" >&6; }
else
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
  echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6


  test -n "$ac_ct_CC" && break
done

  if test "x$ac_ct_CC" = x; then
    CC=""
  else
    case $cross_compiling:$ac_tool_warned in
yes:)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
    CC=$ac_ct_CC
  fi
fi

fi
if test -z "$CC"; then
  if test -n "$ac_tool_prefix"; then
  for ac_prog in cl
  do
    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
set dummy $ac_tool_prefix$ac_prog; ac_word=$2
echo "$as_me:$LINENO: checking for $ac_word" >&5
echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
if test "${ac_cv_prog_CC+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args.
set dummy ${ac_tool_prefix}clang; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_CC+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  if test -n "$CC"; then
  ac_cv_prog_CC="$CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
  for ac_exec_ext in '' $ac_executable_extensions; do
  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_CC="${ac_tool_prefix}clang"
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
done
  done
IFS=$as_save_IFS

fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
  echo "$as_me:$LINENO: result: $CC" >&5
echo "${ECHO_T}$CC" >&6
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
printf "%s\n" "$CC" >&6; }
else
  echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi

    test -n "$CC" && break

  done
fi
if test -z "$CC"; then
if test -z "$ac_cv_prog_CC"; then
  ac_ct_CC=$CC
  for ac_prog in cl
do
  # Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
echo "$as_me:$LINENO: checking for $ac_word" >&5
echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  # Extract the first word of "clang", so it can be a program name with args.
set dummy clang; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_CC+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  if test -n "$ac_ct_CC"; then
  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
  for ac_exec_ext in '' $ac_executable_extensions; do
  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
    ac_cv_prog_ac_ct_CC="$ac_prog"
    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_ac_ct_CC="clang"
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
done
  done
IFS=$as_save_IFS

fi
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
echo "${ECHO_T}$ac_ct_CC" >&6
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
printf "%s\n" "$ac_ct_CC" >&6; }
else
  echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi

  test -n "$ac_ct_CC" && break
done

  CC=$ac_ct_CC
  if test "x$ac_ct_CC" = x; then
    CC=""
  else
    case $cross_compiling:$ac_tool_warned in
yes:)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
    CC=$ac_ct_CC
  fi
else
  CC="$ac_cv_prog_CC"
fi

fi


test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
See \`config.log' for more details." >&5
echo "$as_me: error: no acceptable C compiler found in \$PATH
See \`config.log' for more details." >&2;}
test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "no acceptable C compiler found in \$PATH
See \`config.log' for more details" "$LINENO" 5; }
   { (exit 1); exit 1; }; }

# Provide some information about the compiler.
echo "$as_me:$LINENO:" \
     "checking for C compiler version" >&5
ac_compiler=`set X $ac_compile; echo $2`
{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
  (eval $ac_compiler --version </dev/null >&5) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }
printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
set X $ac_compile
ac_compiler=$2
for ac_option in --version -v -V -qversion -version; do
  { { ac_try="$ac_compiler $ac_option >&5"
case "(($ac_try" in
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
  *) ac_try_echo=$ac_try;;
{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
  (eval $ac_compiler -v </dev/null >&5) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
printf "%s\n" "$ac_try_echo"; } >&5
{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
  (eval $ac_compiler -V </dev/null >&5) 2>&5
  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
  ac_status=$?
  if test -s conftest.err; then
    sed '10a\
... rest of stderr output deleted ...
         10q' conftest.err >conftest.er1
    cat conftest.er1 >&5
  fi
  rm -f conftest.er1 conftest.err
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }
  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; }
done

cat >conftest.$ac_ext <<_ACEOF
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */

int
main ()
main (void)
{

  ;
  return 0;
}
_ACEOF
ac_clean_files_save=$ac_clean_files
ac_clean_files="$ac_clean_files a.out a.exe b.out"
ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
# Try to create an executable without -o first, disregard a.out.
# It will help us diagnose broken compilers, and finding out an intuition
# of exeext.
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
printf %s "checking whether the C compiler works... " >&6; }
ac_link_default=`printf "%s\n" "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6
ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5
  (eval $ac_link_default) 2>&5

# The possible output files:
ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"

ac_rmfiles=
for ac_file in $ac_files
do
  case $ac_file in
    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
    * ) ac_rmfiles="$ac_rmfiles $ac_file";;
  esac
done
rm -f $ac_rmfiles

if { { ac_try="$ac_link_default"
case "(($ac_try" in
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
  *) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
printf "%s\n" "$ac_try_echo"; } >&5
  (eval "$ac_link_default") 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; then
  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; }
  # Find the output, starting from the most likely.  This scheme is
# not robust to junk in `.', hence go to wildcards (a.*) only as a last
# resort.

then :
  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
# Be careful to initialize this variable, since it used to be cached.
# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile.
ac_cv_exeext=
# b.out is created by i960 compilers.
for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out
# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
# in a Makefile.  We should not override ac_cv_exeext if it was cached,
# so that the user can short-circuit this test for compilers unknown to
# Autoconf.
for ac_file in $ac_files ''
do
  test -f "$ac_file" || continue
  case $ac_file in
    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj )
    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
	;;
    conftest.$ac_ext )
	# This is the source file.
	;;
    [ab].out )
	# We found the default executable, but exeext='' is most
	# certainly right.
	break;;
    *.* )
	if test ${ac_cv_exeext+y} && test "$ac_cv_exeext" != no;
	then :; else
	ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
	# FIXME: I believe we export ac_cv_exeext for Libtool,
	   ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
	fi
	# We set ac_cv_exeext here because the later test for it is not
	# but it would be cool to find out if it's true.  Does anybody
	# maintain Libtool? --akim.
	export ac_cv_exeext
	# safe: cross compilers may not add the suffix if given an `-o'
	# argument, so we may need to know it at that point already.
	# Even if this section looks crufty: it has the advantage of
	# actually working.
	break;;
    * )
	break;;
  esac
done
test "$ac_cv_exeext" = no && ac_cv_exeext=

else
  echo "$as_me: failed program was:" >&5
else $as_nop
  ac_file=''
fi
if test -z "$ac_file"
then :
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
See \`config.log' for more details." >&5
echo "$as_me: error: C compiler cannot create executables
See \`config.log' for more details." >&2;}
as_fn_error 77 "C compiler cannot create executables
See \`config.log' for more details" "$LINENO" 5; }
   { (exit 77); exit 77; }; }
else $as_nop
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
printf "%s\n" "yes" >&6; }
fi

{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
printf %s "checking for C compiler default output file name... " >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
printf "%s\n" "$ac_file" >&6; }
ac_exeext=$ac_cv_exeext
echo "$as_me:$LINENO: result: $ac_file" >&5
echo "${ECHO_T}$ac_file" >&6

# Check the compiler produces executables we can run.  If not, either
# the compiler is broken, or we cross compile.
echo "$as_me:$LINENO: checking whether the C compiler works" >&5
echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6
# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
# If not cross compiling, check that we can run a simple program.
if test "$cross_compiling" != yes; then
  if { ac_try='./$ac_file'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
    cross_compiling=no
  else
    if test "$cross_compiling" = maybe; then
	cross_compiling=yes
    else
	{ { echo "$as_me:$LINENO: error: cannot run C compiled programs.
If you meant to cross compile, use \`--host'.
See \`config.log' for more details." >&5
echo "$as_me: error: cannot run C compiled programs.
If you meant to cross compile, use \`--host'.
See \`config.log' for more details." >&2;}
   { (exit 1); exit 1; }; }
    fi
  fi
fi
echo "$as_me:$LINENO: result: yes" >&5
echo "${ECHO_T}yes" >&6

rm -f a.out a.exe conftest$ac_cv_exeext b.out
rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
ac_clean_files=$ac_clean_files_save
# Check the compiler produces executables we can run.  If not, either
# the compiler is broken, or we cross compile.
echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6
echo "$as_me:$LINENO: result: $cross_compiling" >&5
echo "${ECHO_T}$cross_compiling" >&6

echo "$as_me:$LINENO: checking for suffix of executables" >&5
echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
  (eval $ac_link) 2>&5
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
printf %s "checking for suffix of executables... " >&6; }
if { { ac_try="$ac_link"
case "(($ac_try" in
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
  *) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
printf "%s\n" "$ac_try_echo"; } >&5
  (eval "$ac_link") 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; then
  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; }
then :
  # If both `conftest.exe' and `conftest' are `present' (well, observable)
# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
# work properly (i.e., refer to `conftest.exe'), while it won't with
# `rm'.
for ac_file in conftest.exe conftest conftest.*; do
  test -f "$ac_file" || continue
  case $ac_file in
    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;;
    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
	  export ac_cv_exeext
	  break;;
    * ) break;;
  esac
done
else
  { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
See \`config.log' for more details." >&5
echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
See \`config.log' for more details." >&2;}
else $as_nop
  { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "cannot compute suffix of executables: cannot compile and link
See \`config.log' for more details" "$LINENO" 5; }
   { (exit 1); exit 1; }; }
fi

rm -f conftest$ac_cv_exeext
echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
echo "${ECHO_T}$ac_cv_exeext" >&6
rm -f conftest conftest$ac_cv_exeext
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
printf "%s\n" "$ac_cv_exeext" >&6; }

rm -f conftest.$ac_ext
EXEEXT=$ac_cv_exeext
ac_exeext=$EXEEXT
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <stdio.h>
int
main (void)
{
FILE *f = fopen ("conftest.out", "w");
 return ferror (f) || fclose (f) != 0;
echo "$as_me:$LINENO: checking for suffix of object files" >&5
echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6
if test "${ac_cv_objext+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF

  ;
  return 0;
}
_ACEOF
ac_clean_files="$ac_clean_files conftest.out"
# Check that the compiler produces executables we can run.  If not, either
# the compiler is broken, or we cross compile.
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
printf %s "checking whether we are cross compiling... " >&6; }
if test "$cross_compiling" != yes; then
  { { ac_try="$ac_link"
case "(($ac_try" in
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
  *) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
printf "%s\n" "$ac_try_echo"; } >&5
  (eval "$ac_link") 2>&5
  ac_status=$?
  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; }
  if { ac_try='./conftest$ac_cv_exeext'
  { { case "(($ac_try" in
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
  *) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
printf "%s\n" "$ac_try_echo"; } >&5
  (eval "$ac_try") 2>&5
  ac_status=$?
  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; }; }; then
    cross_compiling=no
  else
    if test "$cross_compiling" = maybe; then
	cross_compiling=yes
    else
	{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot run C compiled programs.
If you meant to cross compile, use \`--host'.
See \`config.log' for more details" "$LINENO" 5; }
    fi
  fi
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
printf "%s\n" "$cross_compiling" >&6; }

rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
ac_clean_files=$ac_clean_files_save
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
printf %s "checking for suffix of object files... " >&6; }
if test ${ac_cv_objext+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main ()
main (void)
{

  ;
  return 0;
}
_ACEOF
rm -f conftest.o conftest.obj
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>&5
if { { ac_try="$ac_compile"
case "(($ac_try" in
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
  *) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
printf "%s\n" "$ac_try_echo"; } >&5
  (eval "$ac_compile") 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; then
  for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do
  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; }
then :
  for ac_file in conftest.o conftest.obj conftest.*; do
  test -f "$ac_file" || continue;
  case $ac_file in
    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;;
    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
       break;;
  esac
done
else
  echo "$as_me: failed program was:" >&5
else $as_nop
  printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
See \`config.log' for more details." >&5
echo "$as_me: error: cannot compute suffix of object files: cannot compile
See \`config.log' for more details." >&2;}
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "cannot compute suffix of object files: cannot compile
See \`config.log' for more details" "$LINENO" 5; }
   { (exit 1); exit 1; }; }
fi

rm -f conftest.$ac_cv_objext conftest.$ac_ext
fi
echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
echo "${ECHO_T}$ac_cv_objext" >&6
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
printf "%s\n" "$ac_cv_objext" >&6; }
OBJEXT=$ac_cv_objext
ac_objext=$OBJEXT
echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6
if test "${ac_cv_c_compiler_gnu+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5
printf %s "checking whether the compiler supports GNU C... " >&6; }
if test ${ac_cv_c_compiler_gnu+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */

int
main ()
main (void)
{
#ifndef __GNUC__
       choke me
#endif

  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
if ac_fn_c_try_compile "$LINENO"
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
then :
  ac_compiler_gnu=yes
else
else $as_nop
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

ac_compiler_gnu=no
  ac_compiler_gnu=no
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_cv_c_compiler_gnu=$ac_compiler_gnu

fi
echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6
GCC=`test $ac_compiler_gnu = yes && echo yes`
ac_test_CFLAGS=${CFLAGS+set}
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; }
ac_compiler_gnu=$ac_cv_c_compiler_gnu

if test $ac_compiler_gnu = yes; then
  GCC=yes
else
  GCC=
fi
ac_test_CFLAGS=${CFLAGS+y}
ac_save_CFLAGS=$CFLAGS
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
printf %s "checking whether $CC accepts -g... " >&6; }
if test ${ac_cv_prog_cc_g+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  ac_save_c_werror_flag=$ac_c_werror_flag
   ac_c_werror_flag=yes
   ac_cv_prog_cc_g=no
CFLAGS="-g"
echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6
if test "${ac_cv_prog_cc_g+set}" = set; then
   CFLAGS="-g"
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main (void)
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  ac_cv_prog_cc_g=yes
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
else $as_nop
  CFLAGS=""
      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main (void)
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF

else $as_nop
  ac_c_werror_flag=$ac_save_c_werror_flag
	 CFLAGS="-g"
	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main ()
main (void)
{

  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
if ac_fn_c_try_compile "$LINENO"
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
then :
  ac_cv_prog_cc_g=yes
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
ac_cv_prog_cc_g=no
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
   ac_c_werror_flag=$ac_save_c_werror_flag
fi
echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
echo "${ECHO_T}$ac_cv_prog_cc_g" >&6
if test "$ac_test_CFLAGS" = set; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
printf "%s\n" "$ac_cv_prog_cc_g" >&6; }
if test $ac_test_CFLAGS; then
  CFLAGS=$ac_save_CFLAGS
elif test $ac_cv_prog_cc_g = yes; then
  if test "$GCC" = yes; then
    CFLAGS="-g -O2"
  else
    CFLAGS="-g"
  fi
else
  if test "$GCC" = yes; then
    CFLAGS="-O2"
  else
    CFLAGS=
  fi
fi
echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5
echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6
if test "${ac_cv_prog_cc_stdc+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  ac_cv_prog_cc_stdc=no
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5
printf %s "checking for $CC option to enable C11 features... " >&6; }
if test ${ac_cv_prog_cc_c11+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  ac_cv_prog_cc_c11=no
ac_save_CC=$CC
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
$ac_c_conftest_c11_program
_ACEOF
for ac_arg in '' -std=gnu11
do
  CC="$ac_save_CC $ac_arg"
  if ac_fn_c_try_compile "$LINENO"
then :
  ac_cv_prog_cc_c11=$ac_arg
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam
  test "x$ac_cv_prog_cc_c11" != "xno" && break
done
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
rm -f conftest.$ac_ext
CC=$ac_save_CC

fi
# AC_CACHE_VAL
ac_prog_cc_stdc_options=
case "x$ac_cv_prog_cc_c11" in #(
  x) :
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
printf "%s\n" "none needed" >&6; } ;; #(
  xno) :
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
printf "%s\n" "unsupported" >&6; } ;; #(
  *) :
    ac_prog_cc_stdc_options=" $ac_cv_prog_cc_c11"
    CC="$CC$ac_prog_cc_stdc_options"
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5
printf "%s\n" "$ac_cv_prog_cc_c11" >&6; } ;;
esac
if test "x$ac_cv_prog_cc_c11" != xno
then :
  ac_prog_cc_stdc=c11
		 ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11
else $as_nop
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5
printf %s "checking for $CC option to enable C99 features... " >&6; }
if test ${ac_cv_prog_cc_c99+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  ac_cv_prog_cc_c99=no
ac_save_CC=$CC
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
$ac_c_conftest_c89_program
_ACEOF
for ac_arg in '' -std=gnu99 -std=c99 -c99 -AC99 -D_STDC_C99= -qlanglvl=extc1x -qlanglvl=extc99
do
  CC="$ac_save_CC $ac_arg"
  if ac_fn_c_try_compile "$LINENO"
then :
  ac_cv_prog_cc_c99=$ac_arg
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam
  test "x$ac_cv_prog_cc_c99" != "xno" && break
done
rm -f conftest.$ac_ext
CC=$ac_save_CC

fi
# AC_CACHE_VAL
ac_prog_cc_stdc_options=
case "x$ac_cv_prog_cc_c99" in #(
  x) :
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
printf "%s\n" "none needed" >&6; } ;; #(
  xno) :
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
printf "%s\n" "unsupported" >&6; } ;; #(
  *) :
    ac_prog_cc_stdc_options=" $ac_cv_prog_cc_c99"
    CC="$CC$ac_prog_cc_stdc_options"
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5
printf "%s\n" "$ac_cv_prog_cc_c99" >&6; } ;;
esac
if test "x$ac_cv_prog_cc_c99" != xno
then :
  ac_prog_cc_stdc=c99
		    ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99
else $as_nop
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5
printf %s "checking for $CC option to enable C89 features... " >&6; }
if test ${ac_cv_prog_cc_c89+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  ac_cv_prog_cc_c89=no
ac_save_CC=$CC
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <stdarg.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
struct buf { int x; };
FILE * (*rcsopen) (struct buf *, struct stat *, int);
static char *e (p, i)
     char **p;
     int i;
{
  return p[i];
}
static char *f (char * (*g) (char **, int), char **p, ...)
{
  char *s;
  va_list v;
  va_start (v,p);
  s = g (p, va_arg (v,int));
  va_end (v);
  return s;
}

$ac_c_conftest_c89_program
/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
   function prototypes and stuff, but not '\xHH' hex character constants.
   These don't provoke an error unfortunately, instead are silently treated
   as 'x'.  The following induces an error, until -std1 is added to get
   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
   array size at least.  It's necessary to write '\x00'==0 to get something
   that's true only with -std1.  */
int osf4_cc_array ['\x00' == 0 ? 1 : -1];

int test (int i, double x);
struct s1 {int (*f) (int a);};
struct s2 {int (*f) (double a);};
int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
int argc;
char **argv;
int
main ()
{
return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
  ;
  return 0;
}
_ACEOF
# Don't try gcc -ansi; that turns off useful extensions and
# breaks some systems' header files.
# AIX			-qlanglvl=ansi
for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
# Ultrix and OSF/1	-std1
# HP-UX 10.20 and later	-Ae
# HP-UX older versions	-Aa -D_HPUX_SOURCE
# SVR4			-Xc -D__EXTENSIONS__
for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
	-Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
do
  CC="$ac_save_CC $ac_arg"
  rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
  if ac_fn_c_try_compile "$LINENO"
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  ac_cv_prog_cc_stdc=$ac_arg
then :
  ac_cv_prog_cc_c89=$ac_arg
break
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

fi
rm -f conftest.err conftest.$ac_objext
rm -f core conftest.err conftest.$ac_objext conftest.beam
  test "x$ac_cv_prog_cc_c89" != "xno" && break
done
rm -f conftest.$ac_ext conftest.$ac_objext
rm -f conftest.$ac_ext
CC=$ac_save_CC

fi

case "x$ac_cv_prog_cc_stdc" in
  x|xno)
    echo "$as_me:$LINENO: result: none needed" >&5
echo "${ECHO_T}none needed" >&6 ;;
  *)
    echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5
echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
    CC="$CC $ac_cv_prog_cc_stdc" ;;
# AC_CACHE_VAL
ac_prog_cc_stdc_options=
case "x$ac_cv_prog_cc_c89" in #(
  x) :
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
printf "%s\n" "none needed" >&6; } ;; #(
  xno) :
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
printf "%s\n" "unsupported" >&6; } ;; #(
  *) :
    ac_prog_cc_stdc_options=" $ac_cv_prog_cc_c89"
    CC="$CC$ac_prog_cc_stdc_options"
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
printf "%s\n" "$ac_cv_prog_cc_c89" >&6; } ;;
esac

if test "x$ac_cv_prog_cc_c89" != xno
# Some people use a C++ compiler to compile C.  Since we use `exit',
# in C++ we need to declare it.  In case someone uses the same compiler
# for both compiling C and C++ we need to have the C++ compiler decide
# the declaration of exit, since it's the most demanding environment.
cat >conftest.$ac_ext <<_ACEOF
#ifndef __cplusplus
  choke me
#endif
then :
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  ac_prog_cc_stdc=c89
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
		       ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
else $as_nop
  ac_prog_cc_stdc=no
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  for ac_declaration in \
   '' \
   'extern "C" void std::exit (int) throw (); using std::exit;' \
   'extern "C" void std::exit (int); using std::exit;' \
   'extern "C" void exit (int) throw ();' \
   'extern "C" void exit (int);' \
   'void exit (int);'
do
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
$ac_declaration
#include <stdlib.h>
int
main ()
{
exit (42);
  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
		       ac_cv_prog_cc_stdc=no
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
fi
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  :

else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

continue
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
$ac_declaration
int
main ()
{

exit (42);
  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  break
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
done
rm -f conftest*
if test -n "$ac_declaration"; then
  echo '#ifdef __cplusplus' >>confdefs.h
  echo $ac_declaration      >>confdefs.h
  echo '#endif'             >>confdefs.h
fi

else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu


echo "$as_me:$LINENO: checking for inline" >&5
echo $ECHO_N "checking for inline... $ECHO_C" >&6
if test "${ac_cv_c_inline+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for inline" >&5
printf %s "checking for inline... " >&6; }
if test ${ac_cv_c_inline+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  ac_cv_c_inline=no
for ac_kw in inline __inline__ __inline; do
  cat >conftest.$ac_ext <<_ACEOF
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
#ifndef __cplusplus
typedef int foo_t;
static $ac_kw foo_t static_foo () {return 0; }
$ac_kw foo_t foo () {return 0; }
static $ac_kw foo_t static_foo (void) {return 0; }
$ac_kw foo_t foo (void) {return 0; }
#endif

_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
if ac_fn_c_try_compile "$LINENO"
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  ac_cv_c_inline=$ac_kw; break
then :
  ac_cv_c_inline=$ac_kw
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
  test "$ac_cv_c_inline" != no && break
done

fi
echo "$as_me:$LINENO: result: $ac_cv_c_inline" >&5
echo "${ECHO_T}$ac_cv_c_inline" >&6
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5
printf "%s\n" "$ac_cv_c_inline" >&6; }


case $ac_cv_c_inline in
  inline | yes) ;;
  *)
    case $ac_cv_c_inline in
      no) ac_val=;;
      *) ac_val=$ac_cv_c_inline;;
    esac
    cat >>confdefs.h <<_ACEOF
#ifndef __cplusplus
#define inline $ac_val
#endif
_ACEOF
    ;;
esac

ac_ext=c
ac_header= ac_cache=
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
for ac_item in $ac_header_c_list
echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6
# On Suns, sometimes $CPP names a directory.
if test -n "$CPP" && test -d "$CPP"; then
  CPP=
fi
if test -z "$CPP"; then
  if test "${ac_cv_prog_CPP+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
      # Double quotes because CPP needs to be expanded
    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
    do
      ac_preproc_ok=false
do
  if test $ac_cache; then
for ac_c_preproc_warn_flag in '' yes
do
  # Use a header file that comes with gcc, so configuring glibc
    ac_fn_c_check_header_compile "$LINENO" $ac_header ac_cv_header_$ac_cache "$ac_includes_default"
    if eval test \"x\$ac_cv_header_$ac_cache\" = xyes; then
  # with a fresh cross-compiler works.
  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
  # <limits.h> exists even on freestanding compilers.
  # On the NeXT, cc -E runs the code through the compiler's parser,
  # not just through cpp. "Syntax error" is here to catch this case.
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
      printf "%s\n" "#define $ac_item 1" >> confdefs.h
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
#ifdef __STDC__
# include <limits.h>
#else
# include <assert.h>
#endif
    fi
		     Syntax error
_ACEOF
if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
  ac_status=$?
    ac_header= ac_cache=
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } >/dev/null; then
  if test -s conftest.err; then
    ac_cpp_err=$ac_c_preproc_warn_flag
  elif test $ac_header; then
    ac_cache=$ac_item
    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
  else
    ac_cpp_err=
    ac_header=$ac_item
  fi
done
else
  ac_cpp_err=yes
fi
if test -z "$ac_cpp_err"; then
  :
else
  echo "$as_me: failed program was:" >&5







sed 's/^/| /' conftest.$ac_ext >&5

  # Broken: fails on valid input.
continue
if test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes
then :
fi
rm -f conftest.err conftest.$ac_ext

  # OK, works on sane cases.  Now check whether non-existent headers
  # can be detected and how.
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
printf "%s\n" "#define STDC_HEADERS 1" >>confdefs.h
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
#include <ac_nonexistent.h>
_ACEOF

if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } >/dev/null; then
  if test -s conftest.err; then
    ac_cpp_err=$ac_c_preproc_warn_flag
    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
  else
    ac_cpp_err=
  fi
else
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
printf %s "checking for grep that handles long lines and -e... " >&6; }
if test ${ac_cv_path_GREP+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  ac_cpp_err=yes
fi
if test -z "$ac_cpp_err"; then
  if test -z "$GREP"; then
  # Broken: success on invalid input.
continue
else
  echo "$as_me: failed program was:" >&5
  ac_path_GREP_found=false
  # Loop through the user's path and test for each of PROGNAME-LIST
  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
do
  IFS=$as_save_IFS
sed 's/^/| /' conftest.$ac_ext >&5

  # Passes both tests.
  case $as_dir in #(((
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
ac_preproc_ok=:
break
  esac
fi
rm -f conftest.err conftest.$ac_ext

done
    for ac_prog in grep ggrep
   do
# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
rm -f conftest.err conftest.$ac_ext
if $ac_preproc_ok; then
    for ac_exec_ext in '' $ac_executable_extensions; do
      ac_path_GREP="$as_dir$ac_prog$ac_exec_ext"
  break
fi

      as_fn_executable_p "$ac_path_GREP" || continue
    done
    ac_cv_prog_CPP=$CPP

# Check for GNU ac_path_GREP and select it if it is found.
  # Check for GNU $ac_path_GREP
case `"$ac_path_GREP" --version 2>&1` in
fi
  CPP=$ac_cv_prog_CPP
*GNU*)
  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
else
  ac_cv_prog_CPP=$CPP
fi
*)
  ac_count=0
  printf %s 0123456789 >"conftest.in"
  while :
echo "$as_me:$LINENO: result: $CPP" >&5
echo "${ECHO_T}$CPP" >&6
ac_preproc_ok=false
for ac_c_preproc_warn_flag in '' yes
do
  do
  # Use a header file that comes with gcc, so configuring glibc
  # with a fresh cross-compiler works.
  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
  # <limits.h> exists even on freestanding compilers.
  # On the NeXT, cc -E runs the code through the compiler's parser,
  # not just through cpp. "Syntax error" is here to catch this case.
  cat >conftest.$ac_ext <<_ACEOF
    cat "conftest.in" "conftest.in" >"conftest.tmp"
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
#ifdef __STDC__
# include <limits.h>
#else
# include <assert.h>
#endif
		     Syntax error
_ACEOF
if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
    mv "conftest.tmp" "conftest.in"
    cp "conftest.in" "conftest.nl"
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } >/dev/null; then
  if test -s conftest.err; then
    ac_cpp_err=$ac_c_preproc_warn_flag
    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
    printf "%s\n" 'GREP' >> "conftest.nl"
    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
    as_fn_arith $ac_count + 1 && ac_count=$as_val
    if test $ac_count -gt ${ac_path_GREP_max-0}; then
  else
    ac_cpp_err=
      # Best one so far, save it but keep looking for a better one
      ac_cv_path_GREP="$ac_path_GREP"
  fi
else
  ac_cpp_err=yes
fi
if test -z "$ac_cpp_err"; then
      ac_path_GREP_max=$ac_count
    fi
    # 10*(2^10) chars as input seems more than enough
  :
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

    test $ac_count -gt 10 && break
  # Broken: fails on valid input.
continue
  done
fi
rm -f conftest.err conftest.$ac_ext

  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
esac
  # OK, works on sane cases.  Now check whether non-existent headers
  # can be detected and how.
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
#include <ac_nonexistent.h>

      $ac_path_GREP_found && break 3
    done
_ACEOF
if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  done
  done
IFS=$as_save_IFS
  (exit $ac_status); } >/dev/null; then
  if test -s conftest.err; then
  if test -z "$ac_cv_path_GREP"; then
    ac_cpp_err=$ac_c_preproc_warn_flag
    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
  else
    ac_cpp_err=
    as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
  fi
else
  ac_cpp_err=yes
  ac_cv_path_GREP=$GREP
fi
if test -z "$ac_cpp_err"; then
  # Broken: success on invalid input.
continue
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

  # Passes both tests.
ac_preproc_ok=:
break
fi
rm -f conftest.err conftest.$ac_ext

{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
done
# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
rm -f conftest.err conftest.$ac_ext
if $ac_preproc_ok; then
  :
printf "%s\n" "$ac_cv_path_GREP" >&6; }
 GREP="$ac_cv_path_GREP"

else
  { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
See \`config.log' for more details." >&5
echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
See \`config.log' for more details." >&2;}
   { (exit 1); exit 1; }; }
fi

ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu

# Autoupdate added the next two lines to ensure that your configure
# script's behavior did not change.  They are probably safe to remove.

echo "$as_me:$LINENO: checking for egrep" >&5
echo $ECHO_N "checking for egrep... $ECHO_C" >&6
if test "${ac_cv_prog_egrep+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  if echo a | (grep -E '(a|b)') >/dev/null 2>&1
    then ac_cv_prog_egrep='grep -E'
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
printf %s "checking for egrep... " >&6; }
if test ${ac_cv_path_EGREP+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
   then ac_cv_path_EGREP="$GREP -E"
    else ac_cv_prog_egrep='egrep'
    fi
fi
echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5
echo "${ECHO_T}$ac_cv_prog_egrep" >&6
 EGREP=$ac_cv_prog_egrep


echo "$as_me:$LINENO: checking for ANSI C header files" >&5
echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
if test "${ac_cv_header_stdc+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
   else
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <float.h>

     if test -z "$EGREP"; then
  ac_path_EGREP_found=false
  # Loop through the user's path and test for each of PROGNAME-LIST
  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
do
  IFS=$as_save_IFS
int
main ()
  case $as_dir in #(((
{

  ;
    '') as_dir=./ ;;
    */) ;;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
    *) as_dir=$as_dir/ ;;
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  esac
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
    for ac_prog in egrep
   do
    for ac_exec_ext in '' $ac_executable_extensions; do
      ac_path_EGREP="$as_dir$ac_prog$ac_exec_ext"
      as_fn_executable_p "$ac_path_EGREP" || continue
# Check for GNU ac_path_EGREP and select it if it is found.
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  # Check for GNU $ac_path_EGREP
case `"$ac_path_EGREP" --version 2>&1` in
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  ac_cv_header_stdc=yes
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

ac_cv_header_stdc=no
*GNU*)
  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext

if test $ac_cv_header_stdc = yes; then
*)
  ac_count=0
  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
#include <string.h>

  printf %s 0123456789 >"conftest.in"
  while :
  do
    cat "conftest.in" "conftest.in" >"conftest.tmp"
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
    mv "conftest.tmp" "conftest.in"
  $EGREP "memchr" >/dev/null 2>&1; then
  :
else
  ac_cv_header_stdc=no
fi
rm -f conftest*

    cp "conftest.in" "conftest.nl"
    printf "%s\n" 'EGREP' >> "conftest.nl"
fi

    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
if test $ac_cv_header_stdc = yes; then
  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
  cat >conftest.$ac_ext <<_ACEOF
    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
    as_fn_arith $ac_count + 1 && ac_count=$as_val
    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
/* end confdefs.h.  */
#include <stdlib.h>

      # Best one so far, save it but keep looking for a better one
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
  $EGREP "free" >/dev/null 2>&1; then
  :
else
  ac_cv_header_stdc=no
      ac_cv_path_EGREP="$ac_path_EGREP"
fi
rm -f conftest*

fi

if test $ac_cv_header_stdc = yes; then
      ac_path_EGREP_max=$ac_count
    fi
    # 10*(2^10) chars as input seems more than enough
    test $ac_count -gt 10 && break
  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
  if test "$cross_compiling" = yes; then
  :
else
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
  done
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
/* end confdefs.h.  */
#include <ctype.h>
#if ((' ' & 0x0FF) == 0x020)
# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
#else
esac
# define ISLOWER(c) \
		   (('a' <= (c) && (c) <= 'i') \
		     || ('j' <= (c) && (c) <= 'r') \
		     || ('s' <= (c) && (c) <= 'z'))
# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
#endif

#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
int
main ()
      $ac_path_EGREP_found && break 3
    done
  done
{
  int i;
  done
  for (i = 0; i < 256; i++)
    if (XOR (islower (i), ISLOWER (i))
	|| toupper (i) != TOUPPER (i))
      exit(2);
  exit (0);
}
_ACEOF
rm -f conftest$ac_exeext
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
  (eval $ac_link) 2>&5
  ac_status=$?
IFS=$as_save_IFS
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  if test -z "$ac_cv_path_EGREP"; then
  :
    as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
  fi
else
  echo "$as_me: program exited with status $ac_status" >&5
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

  ac_cv_path_EGREP=$EGREP
( exit $ac_status )
ac_cv_header_stdc=no
fi
rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
fi

   fi
fi
fi
echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
echo "${ECHO_T}$ac_cv_header_stdc" >&6
if test $ac_cv_header_stdc = yes; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
printf "%s\n" "$ac_cv_path_EGREP" >&6; }
 EGREP="$ac_cv_path_EGREP"

cat >>confdefs.h <<\_ACEOF

#define STDC_HEADERS 1
_ACEOF

fi


if test -n "$ac_tool_prefix"; then
  # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
set dummy ${ac_tool_prefix}ar; ac_word=$2
echo "$as_me:$LINENO: checking for $ac_word" >&5
echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
if test "${ac_cv_prog_AR+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_AR+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  if test -n "$AR"; then
  ac_cv_prog_AR="$AR" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
  for ac_exec_ext in '' $ac_executable_extensions; do
  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_AR="${ac_tool_prefix}ar"
    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
done
  done
IFS=$as_save_IFS

fi
fi
AR=$ac_cv_prog_AR
if test -n "$AR"; then
  echo "$as_me:$LINENO: result: $AR" >&5
echo "${ECHO_T}$AR" >&6
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
printf "%s\n" "$AR" >&6; }
else
  echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi


fi
if test -z "$ac_cv_prog_AR"; then
  ac_ct_AR=$AR
  # Extract the first word of "ar", so it can be a program name with args.
set dummy ar; ac_word=$2
echo "$as_me:$LINENO: checking for $ac_word" >&5
echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
if test "${ac_cv_prog_ac_ct_AR+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_AR+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  if test -n "$ac_ct_AR"; then
  ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
  for ac_exec_ext in '' $ac_executable_extensions; do
  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_ac_ct_AR="ar"
    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
done
  done
IFS=$as_save_IFS

fi
fi
ac_ct_AR=$ac_cv_prog_ac_ct_AR
if test -n "$ac_ct_AR"; then
  echo "$as_me:$LINENO: result: $ac_ct_AR" >&5
echo "${ECHO_T}$ac_ct_AR" >&6
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
printf "%s\n" "$ac_ct_AR" >&6; }
else
  echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi

  if test "x$ac_ct_AR" = x; then
    AR=""
  else
    case $cross_compiling:$ac_tool_warned in
yes:)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
  AR=$ac_ct_AR
    AR=$ac_ct_AR
  fi
else
  AR="$ac_cv_prog_AR"
fi

if test -n "$ac_tool_prefix"; then
  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
set dummy ${ac_tool_prefix}ranlib; ac_word=$2
echo "$as_me:$LINENO: checking for $ac_word" >&5
echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
if test "${ac_cv_prog_RANLIB+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_RANLIB+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  if test -n "$RANLIB"; then
  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
  for ac_exec_ext in '' $ac_executable_extensions; do
  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
done
  done
IFS=$as_save_IFS

fi
fi
RANLIB=$ac_cv_prog_RANLIB
if test -n "$RANLIB"; then
  echo "$as_me:$LINENO: result: $RANLIB" >&5
echo "${ECHO_T}$RANLIB" >&6
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
printf "%s\n" "$RANLIB" >&6; }
else
  echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi


fi
if test -z "$ac_cv_prog_RANLIB"; then
  ac_ct_RANLIB=$RANLIB
  # Extract the first word of "ranlib", so it can be a program name with args.
set dummy ranlib; ac_word=$2
echo "$as_me:$LINENO: checking for $ac_word" >&5
echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_RANLIB+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  if test -n "$ac_ct_RANLIB"; then
  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
  for ac_exec_ext in '' $ac_executable_extensions; do
  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_ac_ct_RANLIB="ranlib"
    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
done
  done
IFS=$as_save_IFS

fi
fi
ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
if test -n "$ac_ct_RANLIB"; then
  echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5
echo "${ECHO_T}$ac_ct_RANLIB" >&6
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
printf "%s\n" "$ac_ct_RANLIB" >&6; }
else
  echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi

  if test "x$ac_ct_RANLIB" = x; then
    RANLIB=""
  else
    case $cross_compiling:$ac_tool_warned in
yes:)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
  RANLIB=$ac_ct_RANLIB
    RANLIB=$ac_ct_RANLIB
  fi
else
  RANLIB="$ac_cv_prog_RANLIB"
fi

if test -n "$ac_tool_prefix"; then
  # Extract the first word of "${ac_tool_prefix}windres", so it can be a program name with args.
set dummy ${ac_tool_prefix}windres; ac_word=$2
echo "$as_me:$LINENO: checking for $ac_word" >&5
echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
if test "${ac_cv_prog_RC+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_RC+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  if test -n "$RC"; then
  ac_cv_prog_RC="$RC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
  for ac_exec_ext in '' $ac_executable_extensions; do
  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_RC="${ac_tool_prefix}windres"
    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
done
  done
IFS=$as_save_IFS

fi
fi
RC=$ac_cv_prog_RC
if test -n "$RC"; then
  echo "$as_me:$LINENO: result: $RC" >&5
echo "${ECHO_T}$RC" >&6
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $RC" >&5
printf "%s\n" "$RC" >&6; }
else
  echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi


fi
if test -z "$ac_cv_prog_RC"; then
  ac_ct_RC=$RC
  # Extract the first word of "windres", so it can be a program name with args.
set dummy windres; ac_word=$2
echo "$as_me:$LINENO: checking for $ac_word" >&5
echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
if test "${ac_cv_prog_ac_ct_RC+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_RC+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  if test -n "$ac_ct_RC"; then
  ac_cv_prog_ac_ct_RC="$ac_ct_RC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
  for ac_exec_ext in '' $ac_executable_extensions; do
  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_ac_ct_RC="windres"
    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
done
  done
IFS=$as_save_IFS

fi
fi
ac_ct_RC=$ac_cv_prog_ac_ct_RC
if test -n "$ac_ct_RC"; then
  echo "$as_me:$LINENO: result: $ac_ct_RC" >&5
echo "${ECHO_T}$ac_ct_RC" >&6
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RC" >&5
printf "%s\n" "$ac_ct_RC" >&6; }
else
  echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi

  if test "x$ac_ct_RC" = x; then
    RC=""
  else
    case $cross_compiling:$ac_tool_warned in
yes:)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
  RC=$ac_ct_RC
    RC=$ac_ct_RC
  fi
else
  RC="$ac_cv_prog_RC"
fi


#--------------------------------------------------------------------
# Checks to see if the make program sets the $MAKE variable.
#--------------------------------------------------------------------

echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5
echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
printf %s "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
set x ${MAKE-make}
ac_make=`echo "" | sed 'y,:./+-,___p_,'`
if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
ac_make=`printf "%s\n" "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
if eval test \${ac_cv_prog_make_${ac_make}_set+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  cat >conftest.make <<\_ACEOF
SHELL = /bin/sh
all:
	@echo '@@@%%%=$(MAKE)=@@@%%%'
_ACEOF
# GNU make sometimes prints "make[1]: Entering ...", which would confuse us.
case `${MAKE-make} -f conftest.make 2>/dev/null` in
  *@@@%%%=?*=@@@%%%*)
    eval ac_cv_prog_make_${ac_make}_set=yes;;
  *)
    eval ac_cv_prog_make_${ac_make}_set=no;;
esac
rm -f conftest.make
fi
if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
  echo "$as_me:$LINENO: result: yes" >&5
echo "${ECHO_T}yes" >&6
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
printf "%s\n" "yes" >&6; }
  SET_MAKE=
else
  echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
  SET_MAKE="MAKE=${MAKE-make}"
fi


#--------------------------------------------------------------------
# Determines the correct binary file extension (.o, .obj, .exe etc.)
#--------------------------------------------------------------------




#--------------------------------------------------------------------
# Check whether --enable-threads or --disable-threads was given.
#--------------------------------------------------------------------


    echo "$as_me:$LINENO: checking for building with threads" >&5
echo $ECHO_N "checking for building with threads... $ECHO_C" >&6
    # Check whether --enable-threads or --disable-threads was given.
if test "${enable_threads+set}" = set; then
  enableval="$enable_threads"
  tcl_ok=$enableval
else
  tcl_ok=yes
fi;

    if test "$tcl_ok" = "yes"; then
	echo "$as_me:$LINENO: result: yes (default)" >&5
echo "${ECHO_T}yes (default)" >&6
	TCL_THREADS=1
	cat >>confdefs.h <<\_ACEOF
#define TCL_THREADS 1
_ACEOF

	# USE_THREAD_ALLOC tells us to try the special thread-based
	# allocator that significantly reduces lock contention
	cat >>confdefs.h <<\_ACEOF
#define USE_THREAD_ALLOC 1
_ACEOF

    else
	TCL_THREADS=0
	echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6
    fi



#--------------------------------------------------------------------
# The statements below define a collection of symbols related to
# building libtk as a shared library instead of a static library.
#--------------------------------------------------------------------


    echo "$as_me:$LINENO: checking how to build libraries" >&5
echo $ECHO_N "checking how to build libraries... $ECHO_C" >&6
    # Check whether --enable-shared or --disable-shared was given.
if test "${enable_shared+set}" = set; then
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to build libraries" >&5
printf %s "checking how to build libraries... " >&6; }
    # Check whether --enable-shared was given.
if test ${enable_shared+y}
  enableval="$enable_shared"
  tcl_ok=$enableval
else
  tcl_ok=yes
fi;

then :
    if test "${enable_shared+set}" = set; then
	enableval="$enable_shared"
	tcl_ok=$enableval
    else
	tcl_ok=yes
    fi
  enableval=$enable_shared; tcl_ok=$enableval
else $as_nop
  tcl_ok=yes
fi

    if test "$tcl_ok" = "yes" ; then
	echo "$as_me:$LINENO: result: shared" >&5
echo "${ECHO_T}shared" >&6
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: shared" >&5
printf "%s\n" "shared" >&6; }
	SHARED_BUILD=1
    else
	echo "$as_me:$LINENO: result: static" >&5
echo "${ECHO_T}static" >&6
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: static" >&5
printf "%s\n" "static" >&6; }
	SHARED_BUILD=0

cat >>confdefs.h <<\_ACEOF
#define STATIC_BUILD 1
printf "%s\n" "#define STATIC_BUILD 1" >>confdefs.h
_ACEOF

    fi



#--------------------------------------------------------------------
# Locate and source the tclConfig.sh file.
#--------------------------------------------------------------------


    #
    # Ok, lets find the tcl configuration
    # First, look for one uninstalled.
    # the alternative search directory is invoked by --with-tcl
    #

    if test x"${no_tcl}" = x ; then
	# we reset no_tcl in case something fails here
	no_tcl=true

# Check whether --with-tcl or --without-tcl was given.
if test "${with_tcl+set}" = set; then
  withval="$with_tcl"
  with_tclconfig="${withval}"
fi;
	echo "$as_me:$LINENO: checking for Tcl configuration" >&5
echo $ECHO_N "checking for Tcl configuration... $ECHO_C" >&6
	if test "${ac_cv_c_tclconfig+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
# Check whether --with-tcl was given.
if test ${with_tcl+y}
then :
  withval=$with_tcl; with_tclconfig="${withval}"
fi

	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for Tcl configuration" >&5
printf %s "checking for Tcl configuration... " >&6; }
	if test ${ac_cv_c_tclconfig+y}
then :
  printf %s "(cached) " >&6
else $as_nop


	    # First check to see if --with-tcl was specified.
	    if test x"${with_tclconfig}" != x ; then
		case "${with_tclconfig}" in
		    */tclConfig.sh )
			if test -f "${with_tclconfig}"; then
			    { echo "$as_me:$LINENO: WARNING: --with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself" >&5
echo "$as_me: WARNING: --with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself" >&2;}
			    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: --with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself" >&5
printf "%s\n" "$as_me: WARNING: --with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself" >&2;}
			    with_tclconfig="`echo "${with_tclconfig}" | sed 's!/tclConfig\.sh$!!'`"
			fi ;;
		esac
		if test -f "${with_tclconfig}/tclConfig.sh" ; then
		    ac_cv_c_tclconfig="`(cd "${with_tclconfig}"; pwd)`"
		else
		    { { echo "$as_me:$LINENO: error: ${with_tclconfig} directory doesn't contain tclConfig.sh" >&5
echo "$as_me: error: ${with_tclconfig} directory doesn't contain tclConfig.sh" >&2;}
		    as_fn_error $? "${with_tclconfig} directory doesn't contain tclConfig.sh" "$LINENO" 5
   { (exit 1); exit 1; }; }
		fi
	    fi

	    # then check for a private Tcl installation
	    if test x"${ac_cv_c_tclconfig}" = x ; then
		for i in \
			../tcl \
3216
3217
3218
3219
3220
3221
3222
3223
3224

3225
3226
3227
3228
3229
3230


3231
3232
3233
3234
3235
3236


3237
3238
3239
3240


3241
3242
3243
3244


3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288


3289
3290
3291
3292
3293
3294
3295



3296
3297
3298

3299
3300
3301
3302
3303
3304



3305

3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324







3325
3326

3327
3328
3329
3330
3331

3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343

3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361

3362
3363
3364
3365
3366
3367
3368
3369
3370
3371






3372
3373
3374
3375
3376
3377
3378

3379
3380
3381






3382
3383

3384
3385
3386
3387


3388
3389
3390
3391
3392
3393
3394
3395


3396



3397
3398
3399











































3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415







3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427

3428
3429
3430
3431
3432
3433
3434
3435
3436

3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455

3456
3457

3458
3459
3460
3461

3462
3463

3464
3465
3466
3467


3468
3469
3470
3471
3472
3473
3474
4114
4115
4116
4117
4118
4119
4120


4121

4122
4123
4124


4125
4126
4127
4128
4129
4130


4131
4132
4133
4134


4135
4136
4137
4138


4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157








4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179






4180
4181
4182

4183

4184






4185
4186
4187

4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200







4201
4202
4203
4204
4205
4206
4207
4208

4209


4210


4211












4212


4213










4214
4215
4216


4217

4218
4219
4220
4221





4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235



4236
4237
4238
4239
4240
4241
4242

4243
4244
4245
4246

4247
4248
4249
4250
4251
4252
4253
4254


4255
4256
4257
4258
4259
4260



4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313






4314
4315
4316
4317
4318
4319
4320




4321
4322
4323
4324
4325
4326
4327

4328
4329
4330
4331
4332
4333
4334



4335



















4336
4337

4338




4339
4340

4341
4342
4343


4344
4345
4346
4347
4348
4349
4350
4351
4352







-
-
+
-



-
-
+
+




-
-
+
+


-
-
+
+


-
-
+
+

















-
-
-
-
-
-
-
-



















+
+

-
-
-
-
-
-
+
+
+
-

-
+
-
-
-
-
-
-
+
+
+
-
+












-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
+
-
-

-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-

-
-
-
-
-
-
-
-
-
-



-
-
+
-




-
-
-
-
-
+
+
+
+
+
+







+
-
-
-
+
+
+
+
+
+

-
+



-
+
+






-
-
+
+

+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+










-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-







-
+






-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+

-
+
-
-
-
-
+

-
+


-
-
+
+







	    fi

fi


	if test x"${ac_cv_c_tclconfig}" = x ; then
	    TCL_BIN_DIR="# no Tcl configs found"
	    { { echo "$as_me:$LINENO: error: Can't find Tcl configuration definitions. Use --with-tcl to specify a directory containing tclConfig.sh" >&5
echo "$as_me: error: Can't find Tcl configuration definitions. Use --with-tcl to specify a directory containing tclConfig.sh" >&2;}
	    as_fn_error $? "Can't find Tcl configuration definitions. Use --with-tcl to specify a directory containing tclConfig.sh" "$LINENO" 5
   { (exit 1); exit 1; }; }
	else
	    no_tcl=
	    TCL_BIN_DIR="${ac_cv_c_tclconfig}"
	    echo "$as_me:$LINENO: result: found ${TCL_BIN_DIR}/tclConfig.sh" >&5
echo "${ECHO_T}found ${TCL_BIN_DIR}/tclConfig.sh" >&6
	    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: found ${TCL_BIN_DIR}/tclConfig.sh" >&5
printf "%s\n" "found ${TCL_BIN_DIR}/tclConfig.sh" >&6; }
	fi
    fi


    echo "$as_me:$LINENO: checking for existence of ${TCL_BIN_DIR}/tclConfig.sh" >&5
echo $ECHO_N "checking for existence of ${TCL_BIN_DIR}/tclConfig.sh... $ECHO_C" >&6
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for existence of ${TCL_BIN_DIR}/tclConfig.sh" >&5
printf %s "checking for existence of ${TCL_BIN_DIR}/tclConfig.sh... " >&6; }

    if test -f "${TCL_BIN_DIR}/tclConfig.sh" ; then
        echo "$as_me:$LINENO: result: loading" >&5
echo "${ECHO_T}loading" >&6
        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: loading" >&5
printf "%s\n" "loading" >&6; }
	. "${TCL_BIN_DIR}/tclConfig.sh"
    else
        echo "$as_me:$LINENO: result: could not find ${TCL_BIN_DIR}/tclConfig.sh" >&5
echo "${ECHO_T}could not find ${TCL_BIN_DIR}/tclConfig.sh" >&6
        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: could not find ${TCL_BIN_DIR}/tclConfig.sh" >&5
printf "%s\n" "could not find ${TCL_BIN_DIR}/tclConfig.sh" >&6; }
    fi

    #
    # If the TCL_BIN_DIR is the build directory (not the install directory),
    # then set the common variable name to the value of the build variables.
    # For example, the variable TCL_LIB_SPEC will be set to the value
    # of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC
    # instead of TCL_BUILD_LIB_SPEC since it will work with both an
    # installed and uninstalled version of Tcl.
    #

    if test -f $TCL_BIN_DIR/Makefile ; then
        TCL_LIB_SPEC=${TCL_BUILD_LIB_SPEC}
        TCL_STUB_LIB_SPEC=${TCL_BUILD_STUB_LIB_SPEC}
        TCL_STUB_LIB_PATH=${TCL_BUILD_STUB_LIB_PATH}
    fi

    #
    # eval is required to do the TCL_DBGX substitution
    #

    eval "TCL_LIB_FILE=\"${TCL_LIB_FILE}\""
    eval "TCL_LIB_FLAG=\"${TCL_LIB_FLAG}\""
    eval "TCL_LIB_SPEC=\"${TCL_LIB_SPEC}\""

    eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\""
    eval "TCL_STUB_LIB_FLAG=\"${TCL_STUB_LIB_FLAG}\""
    eval "TCL_STUB_LIB_SPEC=\"${TCL_STUB_LIB_SPEC}\""

















if test "${TCL_MAJOR_VERSION}" -lt 9 ; then
if test "${TCL_MAJOR_VERSION}" != "${TK_MAJOR_VERSION}"; then
    { { echo "$as_me:$LINENO: error: ${TCL_BIN_DIR}/tclConfig.sh is for Tcl ${TCL_VERSION}.
Tk ${TK_VERSION}${TK_PATCH_LEVEL} needs Tcl ${TK_VERSION}.
Use --with-tcl= option to indicate location of tclConfig.sh file for Tcl ${TK_VERSION}." >&5
echo "$as_me: error: ${TCL_BIN_DIR}/tclConfig.sh is for Tcl ${TCL_VERSION}.
Tk ${TK_VERSION}${TK_PATCH_LEVEL} needs Tcl ${TK_VERSION}.
Use --with-tcl= option to indicate location of tclConfig.sh file for Tcl ${TK_VERSION}." >&2;}
    as_fn_error $? "${TCL_BIN_DIR}/tclConfig.sh is for Tcl ${TCL_VERSION}.
Tk ${TK_VERSION}${TK_PATCH_LEVEL} needs Tcl 8.6+.
Use --with-tcl= option to indicate location of tclConfig.sh file for Tcl 8.6 or better." "$LINENO" 5
   { (exit 1); exit 1; }; }
fi
if test "${TCL_MINOR_VERSION}" -lt "${TK_MINOR_VERSION}"; then
if test "${TCL_MINOR_VERSION}" -lt 6; then
    { { echo "$as_me:$LINENO: error: ${TCL_BIN_DIR}/tclConfig.sh is for Tcl ${TCL_VERSION}.
Tk ${TK_VERSION}${TK_PATCH_LEVEL} needs Tcl ${TK_VERSION}.
Use --with-tcl= option to indicate location of tclConfig.sh file for Tcl ${TK_VERSION}." >&5
echo "$as_me: error: ${TCL_BIN_DIR}/tclConfig.sh is for Tcl ${TCL_VERSION}.
Tk ${TK_VERSION}${TK_PATCH_LEVEL} needs Tcl ${TK_VERSION}.
Use --with-tcl= option to indicate location of tclConfig.sh file for Tcl ${TK_VERSION}." >&2;}
    as_fn_error $? "${TCL_BIN_DIR}/tclConfig.sh is for Tcl ${TCL_VERSION}.
Tk ${TK_VERSION}${TK_PATCH_LEVEL} needs Tcl 8.6+.
Use --with-tcl= option to indicate location of tclConfig.sh file for Tcl 8.6 or better." "$LINENO" 5
   { (exit 1); exit 1; }; }
fi
fi

#--------------------------------------------------------------------
# The statements below define a collection of compile flags.  This
# macro depends on the value of SHARED_BUILD, and should be called
# after SC_ENABLE_SHARED checks the configure switches.
#--------------------------------------------------------------------



    # Step 0: Enable 64 bit support?

    echo "$as_me:$LINENO: checking if 64bit support is requested" >&5
echo $ECHO_N "checking if 64bit support is requested... $ECHO_C" >&6
    # Check whether --enable-64bit or --disable-64bit was given.
if test "${enable_64bit+set}" = set; then
  enableval="$enable_64bit"
  do64bit=$enableval
else
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if 64bit support is requested" >&5
printf %s "checking if 64bit support is requested... " >&6; }
    # Check whether --enable-64bit was given.
if test ${enable_64bit+y}
then :
  enableval=$enable_64bit; do64bit=$enableval
else $as_nop
  do64bit=no
fi;
fi
    echo "$as_me:$LINENO: result: $do64bit" >&5
echo "${ECHO_T}$do64bit" >&6

    # Cross-compiling options for Windows/CE builds

    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $do64bit" >&5
    echo "$as_me:$LINENO: checking if Windows/CE build is requested" >&5
echo $ECHO_N "checking if Windows/CE build is requested... $ECHO_C" >&6
    # Check whether --enable-wince or --disable-wince was given.
if test "${enable_wince+set}" = set; then
  enableval="$enable_wince"
  doWince=$enableval
else
  doWince=no
fi;
    echo "$as_me:$LINENO: result: $doWince" >&5
echo "${ECHO_T}$doWince" >&6

printf "%s\n" "$do64bit" >&6; }
    echo "$as_me:$LINENO: checking for Windows/CE celib directory" >&5
echo $ECHO_N "checking for Windows/CE celib directory... $ECHO_C" >&6

# Check whether --with-celib or --without-celib was given.
if test "${with_celib+set}" = set; then
  withval="$with_celib"
  CELIB_DIR=$withval
else
  CELIB_DIR=NO_CELIB
fi;
    echo "$as_me:$LINENO: result: $CELIB_DIR" >&5
echo "${ECHO_T}$CELIB_DIR" >&6

    # Set some defaults (may get changed below)
    EXTRA_CFLAGS=""

cat >>confdefs.h <<\_ACEOF
#define MODULE_SCOPE extern
printf "%s\n" "#define MODULE_SCOPE extern" >>confdefs.h
_ACEOF


    # Extract the first word of "cygpath", so it can be a program name with args.
set dummy cygpath; ac_word=$2
echo "$as_me:$LINENO: checking for $ac_word" >&5
echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
if test "${ac_cv_prog_CYGPATH+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_CYGPATH+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  if test -n "$CYGPATH"; then
  ac_cv_prog_CYGPATH="$CYGPATH" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
  for ac_exec_ext in '' $ac_executable_extensions; do
  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_CYGPATH="cygpath -m"
    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
done
  done
IFS=$as_save_IFS

  test -z "$ac_cv_prog_CYGPATH" && ac_cv_prog_CYGPATH="echo"
fi
fi
CYGPATH=$ac_cv_prog_CYGPATH
if test -n "$CYGPATH"; then
  echo "$as_me:$LINENO: result: $CYGPATH" >&5
echo "${ECHO_T}$CYGPATH" >&6
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CYGPATH" >&5
printf "%s\n" "$CYGPATH" >&6; }
else
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
  echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6
fi


    # Extract the first word of "wine", so it can be a program name with args.
set dummy wine; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_WINE+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  if test -n "$WINE"; then
  ac_cv_prog_WINE="$WINE" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_WINE="wine"
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

fi
fi
WINE=$ac_cv_prog_WINE
if test -n "$WINE"; then
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $WINE" >&5
printf "%s\n" "$WINE" >&6; }
else
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi



    SHLIB_SUFFIX=".dll"

    # MACHINE is IX86 for LINK, but this is used by the manifest,
    # which requires x86|amd64|ia64.
    MACHINE="X86"

    if test "$GCC" = "yes"; then

      echo "$as_me:$LINENO: checking for cross-compile version of gcc" >&5
echo $ECHO_N "checking for cross-compile version of gcc... $ECHO_C" >&6
if test "${ac_cv_cross+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for cross-compile version of gcc" >&5
printf %s "checking for cross-compile version of gcc... " >&6; }
if test ${ac_cv_cross+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */

	    #ifndef _WIN32
		#error cross-compiler
	    #endif

int
main ()
main (void)
{

  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
if ac_fn_c_try_compile "$LINENO"
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
then :
  ac_cv_cross=no
else
else $as_nop
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

ac_cv_cross=yes
  ac_cv_cross=yes
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext

fi
echo "$as_me:$LINENO: result: $ac_cv_cross" >&5
echo "${ECHO_T}$ac_cv_cross" >&6
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cross" >&5
printf "%s\n" "$ac_cv_cross" >&6; }

      if test "$ac_cv_cross" = "yes"; then
	case "$do64bit" in
	    amd64|x64|yes)
		CC="x86_64-w64-mingw32-${CC}"
		LD="x86_64-w64-mingw32-ld"
		AR="x86_64-w64-mingw32-ar"
3495
3496
3497
3498
3499
3500
3501
3502
3503


3504
3505
3506

3507
3508
3509
3510
3511
3512




3513
3514
3515


3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538







3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550

3551
3552
3553
3554
3555
3556
3557
3558
3559

3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578

3579
3580

3581
3582
3583
3584

3585
3586

3587
3588
3589
3590


3591
3592
3593

3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607






















































3608
3609
3610
3611
3612
3613
3614

3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628

3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642

3643
3644

3645
3646
3647
3648

3649
3650
3651


3652
3653
3654
3655


3656
3657
3658
3659
3660
3661
3662
3663
3664
3665


3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687


3688
3689
3690

3691
3692
3693
3694


3695
3696
3697
3698
3699
3700
3701


3702
3703
3704
3705
3706
3707
3708

3709
3710
3711
3712
3713
3714
3715
3716

3717
3718
3719
3720
3721



3722
3723
3724
3725
3726
3727
3728

3729
3730
3731
3732
3733
3734
3735
3736
3737

3738
3739
3740
3741
3742
3743
3744
4373
4374
4375
4376
4377
4378
4379


4380
4381
4382
4383

4384
4385
4386




4387
4388
4389
4390
4391


4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410






4411
4412
4413
4414
4415
4416
4417




4418
4419
4420
4421
4422
4423
4424

4425
4426
4427
4428
4429
4430
4431



4432



















4433
4434

4435




4436
4437

4438
4439
4440


4441
4442
4443


4444

4445
4446
4447










4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507

4508
4509
4510
4511
4512
4513
4514








4515














4516
4517

4518




4519
4520


4521
4522
4523
4524


4525
4526
4527
4528
4529
4530
4531
4532
4533
4534


4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556


4557
4558
4559
4560

4561
4562
4563


4564
4565
4566
4567
4568




4569
4570

4571
4572
4573
4574
4575

4576
4577
4578
4579
4580
4581
4582
4583

4584
4585
4586



4587
4588
4589
4590
4591
4592
4593
4594
4595

4596
4597
4598
4599
4600
4601
4602
4603
4604

4605
4606
4607
4608
4609
4610
4611
4612







-
-
+
+


-
+


-
-
-
-
+
+
+
+

-
-
+
+

















-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-







-
+






-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+

-
+
-
-
-
-
+

-
+


-
-
+
+

-
-
+
-



-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






-
+






-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+

-
+
-
-
-
-
+

-
-
+
+


-
-
+
+








-
-
+
+




















-
-
+
+


-
+


-
-
+
+



-
-
-
-
+
+
-





-
+







-
+


-
-
-
+
+
+






-
+








-
+








    if test "$GCC" = "yes" && test "$CYGPATH" != "echo" ; then
	conftest=/tmp/conftest.rc
	echo "STRINGTABLE BEGIN" > $conftest
	echo "101 \"name\"" >> $conftest
	echo "END" >> $conftest

	echo "$as_me:$LINENO: checking for Windows native path bug in windres" >&5
echo $ECHO_N "checking for Windows native path bug in windres... $ECHO_C" >&6
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for Windows native path bug in windres" >&5
printf %s "checking for Windows native path bug in windres... " >&6; }
	cyg_conftest=`$CYGPATH $conftest`
	if { ac_try='$RC -o conftest.res.o $cyg_conftest'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } ; then
	    echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6
  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; }; } ; then
	    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
	else
	    echo "$as_me:$LINENO: result: yes" >&5
echo "${ECHO_T}yes" >&6
	    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
printf "%s\n" "yes" >&6; }
	    CYGPATH=echo
	fi
	conftest=
	cyg_conftest=
    fi

    if test "$CYGPATH" = "echo"; then
        DEPARG='"$<"'
    else
        DEPARG='"$(shell $(CYGPATH) $<)"'
    fi

    # set various compiler flags depending on whether we are using gcc or cl

    if test "${GCC}" = "yes" ; then
	extra_cflags="-pipe"
	extra_ldflags="-pipe -static-libgcc"
	echo "$as_me:$LINENO: checking for mingw32 version of gcc" >&5
echo $ECHO_N "checking for mingw32 version of gcc... $ECHO_C" >&6
if test "${ac_cv_win32+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for mingw32 version of gcc" >&5
printf %s "checking for mingw32 version of gcc... " >&6; }
if test ${ac_cv_win32+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */

		#ifdef _WIN32
		    #error win32
		#endif

int
main ()
main (void)
{

  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
if ac_fn_c_try_compile "$LINENO"
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
then :
  ac_cv_win32=no
else
else $as_nop
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

ac_cv_win32=yes
  ac_cv_win32=yes
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext

fi
echo "$as_me:$LINENO: result: $ac_cv_win32" >&5
echo "${ECHO_T}$ac_cv_win32" >&6
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_win32" >&5
printf "%s\n" "$ac_cv_win32" >&6; }
	if test "$ac_cv_win32" != "yes"; then
	    { { echo "$as_me:$LINENO: error: ${CC} cannot produce win32 executables." >&5
echo "$as_me: error: ${CC} cannot produce win32 executables." >&2;}
	    as_fn_error $? "${CC} cannot produce win32 executables." "$LINENO" 5
   { (exit 1); exit 1; }; }
	fi

	hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -mwindows -municode -Dmain=xxmain"
	echo "$as_me:$LINENO: checking for working -municode linker flag" >&5
echo $ECHO_N "checking for working -municode linker flag... $ECHO_C" >&6
if test "${ac_cv_municode+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for working -municode linker flag" >&5
printf %s "checking for working -municode linker flag... " >&6; }
if test ${ac_cv_municode+y}
then :
  printf %s "(cached) " >&6
else $as_nop

# ac_fn_c_try_link LINENO
# -----------------------
# Try to link conftest.$ac_ext, and return whether this succeeded.
ac_fn_c_try_link ()
{
  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
  rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext
  if { { ac_try="$ac_link"
case "(($ac_try" in
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
  *) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
printf "%s\n" "$ac_try_echo"; } >&5
  (eval "$ac_link") 2>conftest.err
  ac_status=$?
  if test -s conftest.err; then
    grep -v '^ *+' conftest.err >conftest.er1
    cat conftest.er1 >&5
    mv -f conftest.er1 conftest.err
  fi
  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; } && {
	 test -z "$ac_c_werror_flag" ||
	 test ! -s conftest.err
       } && test -s conftest$ac_exeext && {
	 test "$cross_compiling" = yes ||
	 test -x conftest$ac_exeext
       }
then :
  ac_retval=0
else $as_nop
  printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

	ac_retval=1
fi
  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
  # interfere with the next link command; also delete a directory that is
  # left behind by Apple's compiler.  We do this before executing the actions.
  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
  as_fn_set_status $ac_retval

} # ac_fn_c_try_link
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

	#include <windows.h>
	int APIENTRY wWinMain(HINSTANCE a, HINSTANCE b, LPWSTR c, int d) {return 0;}

int
main ()
main (void)
{

  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext conftest$ac_exeext
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
if ac_fn_c_try_link "$LINENO"
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
then :
  ac_cv_municode=yes
else
else $as_nop
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

ac_cv_municode=no
  ac_cv_municode=no
fi
rm -f conftest.err conftest.$ac_objext \
      conftest$ac_exeext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext

fi
echo "$as_me:$LINENO: result: $ac_cv_municode" >&5
echo "${ECHO_T}$ac_cv_municode" >&6
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_municode" >&5
printf "%s\n" "$ac_cv_municode" >&6; }
	CFLAGS=$hold_cflags
	if test "$ac_cv_municode" = "yes" ; then
	    extra_ldflags="$extra_ldflags -municode"
	else
	    extra_cflags="$extra_cflags -DTCL_BROKEN_MAINARGS"
	fi
    fi

    echo "$as_me:$LINENO: checking compiler flags" >&5
echo $ECHO_N "checking compiler flags... $ECHO_C" >&6
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking compiler flags" >&5
printf %s "checking compiler flags... " >&6; }
    if test "${GCC}" = "yes" ; then
	SHLIB_LD=""
	SHLIB_LD_LIBS='${LIBS}'
	LIBS="-lnetapi32 -lkernel32 -luser32 -ladvapi32 -luserenv -lws2_32"
	# mingw needs to link ole32 and oleaut32 for [send], but MSVC doesn't
	LIBS_GUI="-lgdi32 -lcomdlg32 -limm32 -lcomctl32 -lshell32 -luuid -lole32 -loleaut32"
	STLIB_LD='${AR} cr'
	RC_OUT=-o
	RC_TYPE=
	RC_INCLUDE=--include
	RC_DEFINE=--define
	RES=res.o
	MAKE_LIB="\${STLIB_LD} \$@"
	MAKE_STUB_LIB="\${STLIB_LD} \$@"
	POST_MAKE_LIB="\${RANLIB} \$@"
	MAKE_EXE="\${CC} -o \$@"
	LIBPREFIX="lib"

	if test "${SHARED_BUILD}" = "0" ; then
	    # static
            echo "$as_me:$LINENO: result: using static flags" >&5
echo "${ECHO_T}using static flags" >&6
            { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: using static flags" >&5
printf "%s\n" "using static flags" >&6; }
	    runtime=
	    LIBRARIES="\${STATIC_LIBRARIES}"
	    EXESUFFIX="s\${DBGX}.exe"
	    EXESUFFIX="s.exe"
	else
	    # dynamic
            echo "$as_me:$LINENO: result: using shared flags" >&5
echo "${ECHO_T}using shared flags" >&6
            { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: using shared flags" >&5
printf "%s\n" "using shared flags" >&6; }

	    # ad-hoc check to see if CC supports -shared.
	    if "${CC}" -shared 2>&1 | egrep ': -shared not supported' >/dev/null; then
		{ { echo "$as_me:$LINENO: error: ${CC} does not support the -shared option.
                You will need to upgrade to a newer version of the toolchain." >&5
echo "$as_me: error: ${CC} does not support the -shared option.
                You will need to upgrade to a newer version of the toolchain." >&2;}
		as_fn_error $? "${CC} does not support the -shared option.
                You will need to upgrade to a newer version of the toolchain." "$LINENO" 5
   { (exit 1); exit 1; }; }
	    fi

	    runtime=
	    # Add SHLIB_LD_LIBS to the Make rule, not here.

	    EXESUFFIX="\${DBGX}.exe"
	    EXESUFFIX=".exe"
	    LIBRARIES="\${SHARED_LIBRARIES}"
	fi
	# Link with gcc since ld does not link to default libs like
	# -luser32 and -lmsvcrt by default.
	SHLIB_LD='${CC} -shared'
	SHLIB_LD_LIBS='${LIBS}'
	MAKE_DLL="\${SHLIB_LD} \$(LDFLAGS) -o \$@ ${extra_ldflags} \
	    -Wl,--out-implib,\$(patsubst %.dll,lib%.a,\$@)"
	    -Wl,--out-implib,\$(patsubst %.dll,lib%.dll.a,\$@)"
	# DLLSUFFIX is separate because it is the building block for
	# users of tclConfig.sh that may build shared or static.
	DLLSUFFIX="\${DBGX}.dll"
	LIBSUFFIX="\${DBGX}.a"
	LIBFLAGSUFFIX="\${DBGX}"
	DLLSUFFIX=".dll"
	LIBSUFFIX=".a"
	LIBFLAGSUFFIX=""
	SHLIB_SUFFIX=.dll

	EXTRA_CFLAGS="${extra_cflags}"

	CFLAGS_DEBUG=-g
	CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer"
	CFLAGS_WARNING="-Wall"
	CFLAGS_WARNING="-Wall -Wextra -Wshadow -Wundef -Wwrite-strings -Wpointer-arith -finput-charset=UTF-8"
	LDFLAGS_DEBUG=
	LDFLAGS_OPTIMIZE=

	case "${CC}" in
	    *++)
		CFLAGS_WARNING="${CFLAGS_WARNING} -Wno-format"
		;;
	    *)
		CFLAGS_WARNING="${CFLAGS_WARNING} -Wdeclaration-after-statement"
		CFLAGS_WARNING="${CFLAGS_WARNING} -Wc++-compat -fextended-identifiers -Wdeclaration-after-statement"
		;;
	esac

	# Specify the CC output file names based on the target name
	CC_OBJNAME="-o \$@"
	CC_EXENAME="-o \$@"

3758
3759
3760
3761
3762
3763
3764
3765
3766


3767
3768
3769
3770
3771


3772
3773
3774

3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786

3787
3788
3789
3790
3791
3792
3793
3794
3795

3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814

3815
3816

3817
3818
3819
3820

3821
3822
3823

3824
3825
3826
3827
3828


3829
3830
3831
3832
3833
3834
3835
3836


3837
3838
3839

3840
3841
3842
3843


3844
3845
3846
3847

3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861



3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873


3874
3875
3876
3877
3878
3879
3880
4626
4627
4628
4629
4630
4631
4632


4633
4634
4635
4636
4637


4638
4639
4640
4641

4642




4643
4644
4645
4646
4647
4648
4649

4650
4651
4652
4653
4654
4655
4656



4657



















4658
4659

4660




4661
4662
4663

4664
4665
4666
4667


4668
4669
4670
4671
4672
4673
4674
4675


4676
4677
4678
4679

4680
4681
4682


4683
4684
4685
4686
4687

4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699



4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712


4713
4714
4715
4716
4717
4718
4719
4720
4721







-
-
+
+



-
-
+
+


-
+
-
-
-
-







-
+






-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+

-
+
-
-
-
-
+


-
+



-
-
+
+






-
-
+
+


-
+


-
-
+
+



-
+











-
-
-
+
+
+










-
-
+
+







	#LDFLAGS_WINDOW="-mwindows -e _WinMain@16 ${extra_ldflags}"
	LDFLAGS_CONSOLE="-mconsole ${extra_ldflags}"
	LDFLAGS_WINDOW="-mwindows ${extra_ldflags}"

	case "$do64bit" in
	    amd64|x64|yes)
		MACHINE="AMD64" ; # assume AMD64 as default 64-bit build
		echo "$as_me:$LINENO: result:    Using 64-bit $MACHINE mode" >&5
echo "${ECHO_T}   Using 64-bit $MACHINE mode" >&6
		{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result:    Using 64-bit $MACHINE mode" >&5
printf "%s\n" "   Using 64-bit $MACHINE mode" >&6; }
		;;
	    ia64)
		MACHINE="IA64"
		echo "$as_me:$LINENO: result:    Using 64-bit $MACHINE mode" >&5
echo "${ECHO_T}   Using 64-bit $MACHINE mode" >&6
		{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result:    Using 64-bit $MACHINE mode" >&5
printf "%s\n" "   Using 64-bit $MACHINE mode" >&6; }
		;;
	    *)
		cat >conftest.$ac_ext <<_ACEOF
		cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */

		    #ifndef _WIN64
			#error 32-bit
		    #endif

int
main ()
main (void)
{

  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
if ac_fn_c_try_compile "$LINENO"
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
then :
  tcl_win_64bit=yes
else
else $as_nop
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

tcl_win_64bit=no
  tcl_win_64bit=no

fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
		if test "$tcl_win_64bit" = "yes" ; then
			do64bit=amd64
			MACHINE="AMD64"
			echo "$as_me:$LINENO: result:    Using 64-bit $MACHINE mode" >&5
echo "${ECHO_T}   Using 64-bit $MACHINE mode" >&6
			{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result:    Using 64-bit $MACHINE mode" >&5
printf "%s\n" "   Using 64-bit $MACHINE mode" >&6; }
		fi
		;;
	esac
    else
	if test "${SHARED_BUILD}" = "0" ; then
	    # static
            echo "$as_me:$LINENO: result: using static flags" >&5
echo "${ECHO_T}using static flags" >&6
            { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: using static flags" >&5
printf "%s\n" "using static flags" >&6; }
	    runtime=-MT
	    LIBRARIES="\${STATIC_LIBRARIES}"
	    EXESUFFIX="s\${DBGX}.exe"
	    EXESUFFIX="s.exe"
	else
	    # dynamic
            echo "$as_me:$LINENO: result: using shared flags" >&5
echo "${ECHO_T}using shared flags" >&6
            { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: using shared flags" >&5
printf "%s\n" "using shared flags" >&6; }
	    runtime=-MD
	    # Add SHLIB_LD_LIBS to the Make rule, not here.
	    LIBRARIES="\${SHARED_LIBRARIES}"
	    EXESUFFIX="\${DBGX}.exe"
	    EXESUFFIX=".exe"
	    case "x`echo \${VisualStudioVersion}`" in
		x1[4-9]*)
		    lflags="${lflags} -nodefaultlib:libucrt.lib"
		    ;;
		*)
		    ;;
	    esac
	fi
	MAKE_DLL="\${SHLIB_LD} \$(LDFLAGS) -out:\$@"
	# DLLSUFFIX is separate because it is the building block for
	# users of tclConfig.sh that may build shared or static.
	DLLSUFFIX="\${DBGX}.dll"
	LIBSUFFIX="\${DBGX}.lib"
	LIBFLAGSUFFIX="\${DBGX}"
	DLLSUFFIX=".dll"
	LIBSUFFIX=".lib"
	LIBFLAGSUFFIX=""

	if test "$do64bit" != "no" ; then
	    case "$do64bit" in
		amd64|x64|yes)
		    MACHINE="AMD64" ; # assume AMD64 as default 64-bit build
		    ;;
		ia64)
		    MACHINE="IA64"
		    ;;
	    esac
	    echo "$as_me:$LINENO: result:    Using 64-bit $MACHINE mode" >&5
echo "${ECHO_T}   Using 64-bit $MACHINE mode" >&6
	    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result:    Using 64-bit $MACHINE mode" >&5
printf "%s\n" "   Using 64-bit $MACHINE mode" >&6; }
	fi

	LIBS="netapi32.lib kernel32.lib user32.lib advapi32.lib userenv.lib ws2_32.lib"

	case "x`echo \${VisualStudioVersion}`" in
		x1[4-9]*)
		    LIBS="$LIBS ucrt.lib"
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010

4011
4012
4013
4014
4015
4016
4017
4018
4741
4742
4743
4744
4745
4746
4747








































































































4748

4749
4750
4751
4752
4753
4754
4755







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-







	    CFLAGS_DEBUG="-nologo -Z7 -Od -WX ${runtime}d"
	    # -O2 - create fast code (/Og /Oi /Ot /Oy /Ob2 /Gs /GF /Gy)
	    CFLAGS_OPTIMIZE="-nologo -O2 ${runtime}"
	    lflags="${lflags} -nologo"
	    LINKBIN="link"
	fi

	if test "$doWince" != "no" ; then
	    # Set defaults for common evc4/PPC2003 setup
	    # Currently Tcl requires 300+, possibly 420+ for sockets
	    CEVERSION=420; 		# could be 211 300 301 400 420 ...
	    TARGETCPU=ARMV4;	# could be ARMV4 ARM MIPS SH3 X86 ...
	    ARCH=ARM;		# could be ARM MIPS X86EM ...
	    PLATFORM="Pocket PC 2003"; # or "Pocket PC 2002"
	    if test "$doWince" != "yes"; then
		# If !yes then the user specified something
		# Reset ARCH to allow user to skip specifying it
		ARCH=
		eval `echo $doWince | awk -F "," '{ \
	if (length($1)) { printf "CEVERSION=\"%s\"\n", $1; \
	if ($1 < 400)	  { printf "PLATFORM=\"Pocket PC 2002\"\n" } }; \
	if (length($2)) { printf "TARGETCPU=\"%s\"\n", toupper($2) }; \
	if (length($3)) { printf "ARCH=\"%s\"\n", toupper($3) }; \
	if (length($4)) { printf "PLATFORM=\"%s\"\n", $4 }; \
		}'`
		if test "x${ARCH}" = "x" ; then
		    ARCH=$TARGETCPU;
		fi
	    fi
	    OSVERSION=WCE$CEVERSION;
	    if test "x${WCEROOT}" = "x" ; then
		WCEROOT="C:/Program Files/Microsoft eMbedded C++ 4.0"
		if test ! -d "${WCEROOT}" ; then
		    WCEROOT="C:/Program Files/Microsoft eMbedded Tools"
		fi
	    fi
	    if test "x${SDKROOT}" = "x" ; then
		SDKROOT="C:/Program Files/Windows CE Tools"
		if test ! -d "${SDKROOT}" ; then
		    SDKROOT="C:/Windows CE Tools"
		fi
	    fi
	    # The space-based-path will work for the Makefile, but will
	    # not work if AC_TRY_COMPILE is called.
	    WCEROOT=`echo "$WCEROOT" | sed -e 's!\\\!/!g'`
	    SDKROOT=`echo "$SDKROOT" | sed -e 's!\\\!/!g'`
	    CELIB_DIR=`echo "$CELIB_DIR" | sed -e 's!\\\!/!g'`
	    if test ! -d "${CELIB_DIR}/inc"; then
		{ { echo "$as_me:$LINENO: error: Invalid celib directory \"${CELIB_DIR}\"" >&5
echo "$as_me: error: Invalid celib directory \"${CELIB_DIR}\"" >&2;}
   { (exit 1); exit 1; }; }
	    fi
	    if test ! -d "${SDKROOT}/${OSVERSION}/${PLATFORM}/Lib/${TARGETCPU}"\
		-o ! -d "${WCEROOT}/EVC/${OSVERSION}/bin"; then
		{ { echo "$as_me:$LINENO: error: could not find PocketPC SDK or target compiler to enable WinCE mode $CEVERSION,$TARGETCPU,$ARCH,$PLATFORM" >&5
echo "$as_me: error: could not find PocketPC SDK or target compiler to enable WinCE mode $CEVERSION,$TARGETCPU,$ARCH,$PLATFORM" >&2;}
   { (exit 1); exit 1; }; }
	    else
		CEINCLUDE="${SDKROOT}/${OSVERSION}/${PLATFORM}/include"
		if test -d "${CEINCLUDE}/${TARGETCPU}" ; then
		    CEINCLUDE="${CEINCLUDE}/${TARGETCPU}"
		fi
		CELIBPATH="${SDKROOT}/${OSVERSION}/${PLATFORM}/Lib/${TARGETCPU}"
	    fi
	fi

	if test "$doWince" != "no" ; then
	    CEBINROOT="${WCEROOT}/EVC/${OSVERSION}/bin"
	    if test "${TARGETCPU}" = "X86"; then
		CC="${CEBINROOT}/cl.exe"
	    else
		CC="${CEBINROOT}/cl${ARCH}.exe"
	    fi
	    CC="\"${CC}\" -I\"${CELIB_DIR}/inc\" -I\"${CEINCLUDE}\""
	    RC="\"${WCEROOT}/Common/EVC/bin/rc.exe\""
	    arch=`echo ${ARCH} | awk '{print tolower($0)}'`
	    defs="${ARCH} _${ARCH}_ ${arch} PALM_SIZE _MT _DLL _WINDOWS"
	    for i in $defs ; do
		cat >>confdefs.h <<_ACEOF
#define $i 1
_ACEOF

	    done
#	    if test "${ARCH}" = "X86EM"; then
#		AC_DEFINE_UNQUOTED(_WIN32_WCE_EMULATION)
#	    fi
	    cat >>confdefs.h <<_ACEOF
#define _WIN32_WCE $CEVERSION
_ACEOF

	    cat >>confdefs.h <<_ACEOF
#define UNDER_CE $CEVERSION
_ACEOF

	    CFLAGS_DEBUG="-nologo -Zi -Od"
	    CFLAGS_OPTIMIZE="-nologo -O2"
	    lversion=`echo ${CEVERSION} | sed -e 's/\(.\)\(..\)/\1\.\2/'`
	    lflags="-nodefaultlib -MACHINE:${ARCH} -LIBPATH:\"${CELIBPATH}\" -subsystem:windowsce,${lversion} -nologo"
	    LINKBIN="\"${CEBINROOT}/link.exe\""

	    if test "${CEVERSION}" -lt 400 ; then
		LIBS="coredll.lib corelibc.lib winsock.lib"
	    else
		LIBS="coredll.lib corelibc.lib ws2.lib"
	    fi
	    # celib currently stuck at wce300 status
	    #LIBS="$LIBS \${CELIB_DIR}/wince-${ARCH}-pocket-${OSVERSION}-release/celib.lib"
	    LIBS="$LIBS \"\${CELIB_DIR}/wince-${ARCH}-pocket-wce300-release/celib.lib\""
	    LIBS_GUI="commctrl.lib commdlg.lib"
	else
	    LIBS_GUI="gdi32.lib comdlg32.lib imm32.lib comctl32.lib shell32.lib uuid.lib"
	LIBS_GUI="gdi32.lib comdlg32.lib imm32.lib comctl32.lib shell32.lib uuid.lib"
	fi

	SHLIB_LD="${LINKBIN} -dll -incremental:no ${lflags}"
	SHLIB_LD_LIBS='${LIBS}'
	# link -lib only works when -lib is the first arg
	STLIB_LD="${LINKBIN} -lib ${lflags}"
	RC_OUT=-fo
	RC_TYPE=-r
4035
4036
4037
4038
4039
4040
4041
4042

4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053

4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064








4065
4066
4067
4068
4069
4070
4071













































4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094

4095
4096
4097
4098
4099
4100

4101
4102

4103
4104
4105
4106
4107
4108

4109
4110


4111
4112

4113
4114
4115


4116
4117
4118
4119

4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135







4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147

4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158

4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177

4178
4179

4180
4181
4182
4183

4184
4185

4186
4187
4188
4189


4190
4191
4192
4193

4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207







4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220

4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233

4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252

4253
4254

4255
4256
4257
4258

4259
4260

4261
4262
4263
4264


4265
4266
4267
4268
4269



4270






4271


4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282







4283
4284
4285
4286
4287
4288
4289
4290

4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302

4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321

4322
4323

4324
4325
4326
4327

4328
4329

4330
4331
4332
4333


4334
4335
4336
4337

4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
























4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379

4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433

4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473

4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502

4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580






4581
4582

4583
4584
4585
4586
4587
4588
4589
4590

4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604

4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618

4619
4620

4621
4622
4623
4624

4625
4626
4627


4628
4629
4630


4631
4632
4633
4634

4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655


4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680

4681
4682
4683
4684

4685
4686
4687
4688
4689
4690
4691
4692
4693

4694
4695
4696
4697
4698



4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713

4714
4715

4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740

4741
4742
4743
4744

4745
4746
4747
4748
4749
4750
4751
4752
4753

4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773







4774
4775


4776
4777
4778
4779
4780
4781
4782
4783

4784
4785
4786
4787


4788
4789
4790

4791
4792
4793
4794
4795
4796
4797
4798
4799


4800
4801
4802
4803
4804
4805
4806
4807
4808

4809
4810
4811
4812
4813
4814
4815
4816

4817
4818
4819
4820
4821

4822
4823
4824
4825
4826
4827
4828
4829


4830
4831
4832


4833
4834
4835
4836
4837
4838
4839
4840
4841
4842

































4843
4844
4845
4846
4847
4848
4849




































4850






































































4851
4852


4853
4854
4855
4856
4857
4858
4859
4860

4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873


4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889

4890
4891
4892
4893


4894
4895
4896
4897
4898
4899
4900
4901
4902
4903





4904
4905
4906
4907
4908


4909
4910
4911
4912




4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933


4934
4935
4936
4937
4938


4939
4940
4941
4942
4943
4944
4945
4772
4773
4774
4775
4776
4777
4778

4779
4780
4781
4782
4783
4784
4785
4786
4787
4788


4789

4790
4791
4792
4793






4794
4795
4796
4797
4798
4799
4800
4801
4802






4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865





4866






4867
4868

4869






4870
4871

4872
4873
4874
4875
4876
4877


4878
4879
4880
4881


4882

4883
4884
4885
4886
4887
4888
4889
4890
4891






4892
4893
4894
4895
4896
4897
4898




4899
4900
4901
4902
4903
4904
4905

4906
4907
4908
4909
4910
4911
4912
4913
4914



4915



















4916
4917

4918




4919
4920

4921
4922
4923


4924
4925
4926
4927


4928

4929
4930
4931
4932
4933
4934
4935






4936
4937
4938
4939
4940
4941
4942




4943
4944
4945
4946
4947
4948
4949
4950

4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961



4962



















4963
4964

4965




4966
4967

4968
4969
4970


4971
4972
4973
4974



4975
4976
4977
4978
4979
4980
4981
4982
4983
4984

4985
4986
4987
4988
4989
4990
4991






4992
4993
4994
4995
4996
4997
4998




4999
5000
5001

5002
5003
5004
5005
5006
5007
5008
5009
5010
5011



5012



















5013
5014

5015




5016
5017

5018
5019
5020


5021
5022
5023
5024


5025

5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064


























5065






















































5066








































5067





5068























5069































































5070
5071

5072
5073
5074
5075
5076
5077
5078





5079
5080
5081
5082
5083
5084
5085

5086




5087
5088
5089

5090
5091
5092
5093
5094
5095
5096








5097














5098
5099

5100




5101
5102


5103
5104
5105


5106
5107
5108
5109


5110

5111
5112
5113
5114
5115
5116
5117













5118
5119

























5120




5121









5122

5123



5124
5125
5126
5127
5128













5129
5130

5131

























5132




5133









5134

5135
5136

5137
5138
5139
5140
5141
5142
5143
5144
5145







5146
5147
5148
5149
5150
5151
5152
5153

5154
5155
5156
5157
5158
5159

5160


5161

5162


5163
5164
5165


5166

5167
5168
5169
5170

5171


5172
5173
5174
5175
5176
5177
5178
5179
5180


5181

5182
5183
5184
5185
5186


5187

5188
5189


5190

5191
5192
5193
5194
5195


5196
5197
5198


5199
5200
5201
5202
5203
5204


5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242






5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350

5351
5352
5353
5354
5355
5356
5357
5358
5359

5360




5361
5362
5363
5364
5365
5366
5367
5368

5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385

5386
5387
5388


5389
5390
5391
5392
5393
5394
5395





5396
5397
5398
5399
5400
5401
5402
5403


5404
5405
5406



5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429


5430
5431
5432
5433
5434


5435
5436
5437
5438
5439
5440
5441
5442
5443







-
+









-
-
+
-




-
-
-
-
-
-
+
+
+
+
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


















-
-
-
-
-
+
-
-
-
-
-
-
+

-
+
-
-
-
-
-
-
+

-
+
+


+

-
-
+
+


-
-
+
-









-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-







-
+








-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+

-
+
-
-
-
-
+

-
+


-
-
+
+


-
-
+
-







-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-








-
+










-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+

-
+
-
-
-
-
+

-
+


-
-
+
+


-
-
-
+
+
+

+
+
+
+
+
+
-
+
+





-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-



-
+









-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+

-
+
-
-
-
-
+

-
+


-
-
+
+


-
-
+
-










+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-


-







-
-
-
-
-
+
+
+
+
+
+

-
+
-
-
-
-



-
+






-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+

-
+
-
-
-
-
+

-
-
+
+

-
-
+
+


-
-
+
-







-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
+
-
-
-
-
-
-
-
-
-
+
-

-
-
-
+
+
+


-
-
-
-
-
-
-
-
-
-
-
-
-
+

-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
+
-
-
-
-
-
-
-
-
-
+
-


-









-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
+
+




-

-
-
+
-

-
-
+
+

-
-
+
-




-

-
-
+
+







-
-
+
-





-
-
+
-


-
-
+
-





-
-
+
+

-
-
+
+




-
-




+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+
+







-
+
-
-
-
-








-
+
+















-
+


-
-
+
+





-
-
-
-
-
+
+
+
+
+



-
-
+
+

-
-
-
+
+
+
+



















-
-
+
+



-
-
+
+








	# Specify the CC output file names based on the target name
	CC_OBJNAME="-Fo\$@"
	CC_EXENAME="-Fe\"\$(shell \$(CYGPATH) '\$@')\""

	# Specify linker flags depending on the type of app being
	# built -- Console vs. Window.
	if test "$doWince" != "no" -a "${TARGETCPU}" != "X86"; then
	if test "${TARGETCPU}" != "X86"; then
	    LDFLAGS_CONSOLE="-link ${lflags}"
	    LDFLAGS_WINDOW=${LDFLAGS_CONSOLE}
	else
	    LDFLAGS_CONSOLE="-link -subsystem:console ${lflags}"
	    LDFLAGS_WINDOW="-link -subsystem:windows ${lflags}"
	fi
    fi

    if test "$do64bit" != "no" ; then
	cat >>confdefs.h <<\_ACEOF
#define TCL_CFG_DO64BIT 1
	printf "%s\n" "#define TCL_CFG_DO64BIT 1" >>confdefs.h
_ACEOF

    fi

    if test "${GCC}" = "yes" ; then
	echo "$as_me:$LINENO: checking for SEH support in compiler" >&5
echo $ECHO_N "checking for SEH support in compiler... $ECHO_C" >&6
if test "${tcl_cv_seh+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  if test "$cross_compiling" = yes; then
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for SEH support in compiler" >&5
printf %s "checking for SEH support in compiler... " >&6; }
if test ${tcl_cv_seh+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  if test "$cross_compiling" = yes
then :
  tcl_cv_seh=no
else
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
else $as_nop

# ac_fn_c_try_run LINENO
# ----------------------
# Try to run conftest.$ac_ext, and return whether this succeeded. Assumes that
# executables *can* be run.
ac_fn_c_try_run ()
{
  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
  if { { ac_try="$ac_link"
case "(($ac_try" in
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
  *) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
printf "%s\n" "$ac_try_echo"; } >&5
  (eval "$ac_link") 2>&5
  ac_status=$?
  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
  { { case "(($ac_try" in
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
  *) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
printf "%s\n" "$ac_try_echo"; } >&5
  (eval "$ac_try") 2>&5
  ac_status=$?
  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; }; }
then :
  ac_retval=0
else $as_nop
  printf "%s\n" "$as_me: program exited with status $ac_status" >&5
       printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

       ac_retval=$ac_status
fi
  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
  as_fn_set_status $ac_retval

} # ac_fn_c_try_run
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

	    #define WIN32_LEAN_AND_MEAN
	    #include <windows.h>
	    #undef WIN32_LEAN_AND_MEAN

	    int main(int argc, char** argv) {
		int a, b = 0;
		__try {
		    a = 666 / b;
		}
		__except (EXCEPTION_EXECUTE_HANDLER) {
		    return 0;
		}
		return 1;
	    }

_ACEOF
rm -f conftest$ac_exeext
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
  (eval $ac_link) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
if ac_fn_c_try_run "$LINENO"
  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
then :
  tcl_cv_seh=yes
else
else $as_nop
  echo "$as_me: program exited with status $ac_status" >&5
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

( exit $ac_status )
tcl_cv_seh=no
  tcl_cv_seh=no
fi
rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
  conftest.$ac_objext conftest.beam conftest.$ac_ext
fi


fi
echo "$as_me:$LINENO: result: $tcl_cv_seh" >&5
echo "${ECHO_T}$tcl_cv_seh" >&6
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_seh" >&5
printf "%s\n" "$tcl_cv_seh" >&6; }
	if test "$tcl_cv_seh" = "no" ; then

cat >>confdefs.h <<\_ACEOF
#define HAVE_NO_SEH 1
printf "%s\n" "#define HAVE_NO_SEH 1" >>confdefs.h
_ACEOF

	fi

	#
	# Check to see if the excpt.h include file provided contains the
	# definition for EXCEPTION_DISPOSITION; if not, which is the case
	# with Cygwin's version as of 2002-04-10, define it to be int,
	# sufficient for getting the current code to work.
	#
	echo "$as_me:$LINENO: checking for EXCEPTION_DISPOSITION support in include files" >&5
echo $ECHO_N "checking for EXCEPTION_DISPOSITION support in include files... $ECHO_C" >&6
if test "${tcl_cv_eh_disposition+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for EXCEPTION_DISPOSITION support in include files" >&5
printf %s "checking for EXCEPTION_DISPOSITION support in include files... " >&6; }
if test ${tcl_cv_eh_disposition+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */

#	    define WIN32_LEAN_AND_MEAN
#	    include <windows.h>
#	    undef WIN32_LEAN_AND_MEAN

int
main ()
main (void)
{

		EXCEPTION_DISPOSITION x;

  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
if ac_fn_c_try_compile "$LINENO"
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
then :
  tcl_cv_eh_disposition=yes
else
else $as_nop
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

tcl_cv_eh_disposition=no
  tcl_cv_eh_disposition=no
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext

fi
echo "$as_me:$LINENO: result: $tcl_cv_eh_disposition" >&5
echo "${ECHO_T}$tcl_cv_eh_disposition" >&6
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_eh_disposition" >&5
printf "%s\n" "$tcl_cv_eh_disposition" >&6; }
	if test "$tcl_cv_eh_disposition" = "no" ; then

cat >>confdefs.h <<\_ACEOF
#define EXCEPTION_DISPOSITION int
printf "%s\n" "#define EXCEPTION_DISPOSITION int" >>confdefs.h
_ACEOF

	fi

	# Check to see if winnt.h defines CHAR, SHORT, and LONG
	# even if VOID has already been #defined. The win32api
	# used by mingw and cygwin is known to do this.

	echo "$as_me:$LINENO: checking for winnt.h that ignores VOID define" >&5
echo $ECHO_N "checking for winnt.h that ignores VOID define... $ECHO_C" >&6
if test "${tcl_cv_winnt_ignore_void+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for winnt.h that ignores VOID define" >&5
printf %s "checking for winnt.h that ignores VOID define... " >&6; }
if test ${tcl_cv_winnt_ignore_void+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */

		#define VOID void
		#define WIN32_LEAN_AND_MEAN
		#include <windows.h>
		#undef WIN32_LEAN_AND_MEAN

int
main ()
main (void)
{

		CHAR c;
		SHORT s;
		LONG l;

  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
if ac_fn_c_try_compile "$LINENO"
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
then :
  tcl_cv_winnt_ignore_void=yes
else
else $as_nop
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

tcl_cv_winnt_ignore_void=no
  tcl_cv_winnt_ignore_void=no
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext

fi
echo "$as_me:$LINENO: result: $tcl_cv_winnt_ignore_void" >&5
echo "${ECHO_T}$tcl_cv_winnt_ignore_void" >&6
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_winnt_ignore_void" >&5
printf "%s\n" "$tcl_cv_winnt_ignore_void" >&6; }
	if test "$tcl_cv_winnt_ignore_void" = "yes" ; then

cat >>confdefs.h <<\_ACEOF
#define HAVE_WINNT_IGNORE_VOID 1
_ACEOF
printf "%s\n" "#define HAVE_WINNT_IGNORE_VOID 1" >>confdefs.h

	fi

	ac_fn_c_check_header_compile "$LINENO" "stdbool.h" "ac_cv_header_stdbool_h" "$ac_includes_default"
if test "x$ac_cv_header_stdbool_h" = xyes
then :

printf "%s\n" "#define HAVE_STDBOOL_H 1" >>confdefs.h

	fi
fi


	# See if the compiler supports casting to a union type.
	# This is used to stop gcc from printing a compiler
	# warning when initializing a union member.

	echo "$as_me:$LINENO: checking for cast to union support" >&5
echo $ECHO_N "checking for cast to union support... $ECHO_C" >&6
if test "${tcl_cv_cast_to_union+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for cast to union support" >&5
printf %s "checking for cast to union support... " >&6; }
if test ${tcl_cv_cast_to_union+y}
then :
  printf %s "(cached) " >&6
else $as_nop
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */

int
main ()
main (void)
{

		  union foo { int i; double d; };
		  union foo f = (union foo) (int) 0;

  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
if ac_fn_c_try_compile "$LINENO"
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
then :
  tcl_cv_cast_to_union=yes
else
else $as_nop
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

tcl_cv_cast_to_union=no
  tcl_cv_cast_to_union=no
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext

fi
echo "$as_me:$LINENO: result: $tcl_cv_cast_to_union" >&5
echo "${ECHO_T}$tcl_cv_cast_to_union" >&6
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cast_to_union" >&5
printf "%s\n" "$tcl_cv_cast_to_union" >&6; }
	if test "$tcl_cv_cast_to_union" = "yes"; then

cat >>confdefs.h <<\_ACEOF
#define HAVE_CAST_TO_UNION 1
printf "%s\n" "#define HAVE_CAST_TO_UNION 1" >>confdefs.h
_ACEOF

	fi
    fi

    # DL_LIBS is empty, but then we match the Unix version






ac_fn_c_check_type "$LINENO" "intptr_t" "ac_cv_type_intptr_t" "
#include <stdint.h>

"
if test "x$ac_cv_type_intptr_t" = xyes
then :

printf "%s\n" "#define HAVE_INTPTR_T 1" >>confdefs.h


fi
ac_fn_c_check_type "$LINENO" "uintptr_t" "ac_cv_type_uintptr_t" "
#include <stdint.h>

"
if test "x$ac_cv_type_uintptr_t" = xyes
then :

printf "%s\n" "#define HAVE_UINTPTR_T 1" >>confdefs.h


fi


#--------------------------------------------------------------------
# man2tcl needs this so that it can use errno.h
#--------------------------------------------------------------------

# On IRIX 5.3, sys/types and inttypes.h are conflicting.









for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
		  inttypes.h stdint.h unistd.h
do
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
echo "$as_me:$LINENO: checking for $ac_header" >&5
echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
if eval "test \"\${$as_ac_Header+set}\" = set"; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
$ac_includes_default
ac_fn_c_check_header_compile "$LINENO" "errno.h" "ac_cv_header_errno_h" "$ac_includes_default"

#include <$ac_header>
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  eval "$as_ac_Header=yes"
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

eval "$as_ac_Header=no"
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
if test `eval echo '${'$as_ac_Header'}'` = yes; then
  cat >>confdefs.h <<_ACEOF
#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
_ACEOF

fi

done


if test "${ac_cv_header_errno_h+set}" = set; then
  echo "$as_me:$LINENO: checking for errno.h" >&5
echo $ECHO_N "checking for errno.h... $ECHO_C" >&6
if test "${ac_cv_header_errno_h+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
fi
echo "$as_me:$LINENO: result: $ac_cv_header_errno_h" >&5
echo "${ECHO_T}$ac_cv_header_errno_h" >&6
if test "x$ac_cv_header_errno_h" = xyes
else
  # Is the header compilable?
echo "$as_me:$LINENO: checking errno.h usability" >&5
echo $ECHO_N "checking errno.h usability... $ECHO_C" >&6
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
$ac_includes_default
#include <errno.h>
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  ac_header_compiler=yes
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

then :
ac_header_compiler=no
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
echo "${ECHO_T}$ac_header_compiler" >&6

# Is the header present?
echo "$as_me:$LINENO: checking errno.h presence" >&5
echo $ECHO_N "checking errno.h presence... $ECHO_C" >&6
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
#include <errno.h>
_ACEOF
if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } >/dev/null; then
  if test -s conftest.err; then
    ac_cpp_err=$ac_c_preproc_warn_flag
    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
  else
else $as_nop
    ac_cpp_err=
  fi
else
  ac_cpp_err=yes
fi
if test -z "$ac_cpp_err"; then
  ac_header_preproc=yes
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

  ac_header_preproc=no
fi
rm -f conftest.err conftest.$ac_ext
echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
echo "${ECHO_T}$ac_header_preproc" >&6

# So?  What about this header?
case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
  yes:no: )
    { echo "$as_me:$LINENO: WARNING: errno.h: accepted by the compiler, rejected by the preprocessor!" >&5
echo "$as_me: WARNING: errno.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
    { echo "$as_me:$LINENO: WARNING: errno.h: proceeding with the compiler's result" >&5
echo "$as_me: WARNING: errno.h: proceeding with the compiler's result" >&2;}
    ac_header_preproc=yes
    ;;
  no:yes:* )
    { echo "$as_me:$LINENO: WARNING: errno.h: present but cannot be compiled" >&5
echo "$as_me: WARNING: errno.h: present but cannot be compiled" >&2;}
    { echo "$as_me:$LINENO: WARNING: errno.h:     check for missing prerequisite headers?" >&5
echo "$as_me: WARNING: errno.h:     check for missing prerequisite headers?" >&2;}
    { echo "$as_me:$LINENO: WARNING: errno.h: see the Autoconf documentation" >&5
echo "$as_me: WARNING: errno.h: see the Autoconf documentation" >&2;}
    { echo "$as_me:$LINENO: WARNING: errno.h:     section \"Present But Cannot Be Compiled\"" >&5
echo "$as_me: WARNING: errno.h:     section \"Present But Cannot Be Compiled\"" >&2;}
    { echo "$as_me:$LINENO: WARNING: errno.h: proceeding with the preprocessor's result" >&5
echo "$as_me: WARNING: errno.h: proceeding with the preprocessor's result" >&2;}
    { echo "$as_me:$LINENO: WARNING: errno.h: in the future, the compiler will take precedence" >&5
echo "$as_me: WARNING: errno.h: in the future, the compiler will take precedence" >&2;}
    (
      cat <<\_ASBOX
## ------------------------------------------ ##
## Report this to the AC_PACKAGE_NAME lists.  ##
## ------------------------------------------ ##
_ASBOX
    ) |
      sed "s/^/$as_me: WARNING:     /" >&2
    ;;
esac
echo "$as_me:$LINENO: checking for errno.h" >&5
echo $ECHO_N "checking for errno.h... $ECHO_C" >&6
if test "${ac_cv_header_errno_h+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  ac_cv_header_errno_h=$ac_header_preproc
fi
echo "$as_me:$LINENO: result: $ac_cv_header_errno_h" >&5
echo "${ECHO_T}$ac_cv_header_errno_h" >&6

fi
if test $ac_cv_header_errno_h = yes; then
  :
else
  MAN2TCLFLAGS="-DNO_ERRNO_H"
fi




#-------------------------------------------
#     Check for _strtoi64
#-------------------------------------------

echo "$as_me:$LINENO: checking availability of _strtoi64" >&5
echo $ECHO_N "checking availability of _strtoi64... $ECHO_C" >&6
if test "${tcl_cv_strtoi64+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking availability of _strtoi64" >&5
printf %s "checking availability of _strtoi64... " >&6; }
if test ${tcl_cv_strtoi64+y}
then :
  printf %s "(cached) " >&6
else $as_nop

    cat >conftest.$ac_ext <<_ACEOF
    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
#include <stdlib.h>
int
main ()
main (void)
{
_strtoi64(0,0,0)
  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext conftest$ac_exeext
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
if ac_fn_c_try_link "$LINENO"
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
then :
  tcl_cv_strtoi64=yes
else
else $as_nop
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

tcl_cv_strtoi64=no
  tcl_cv_strtoi64=no
fi
rm -f conftest.err conftest.$ac_objext \
      conftest$ac_exeext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
fi
echo "$as_me:$LINENO: result: $tcl_cv_strtoi64" >&5
echo "${ECHO_T}$tcl_cv_strtoi64" >&6
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_strtoi64" >&5
printf "%s\n" "$tcl_cv_strtoi64" >&6; }
if test $tcl_cv_strtoi64 = no; then

cat >>confdefs.h <<\_ACEOF
#define NO_STRTOI64 1
printf "%s\n" "#define NO_STRTOI64 1" >>confdefs.h
_ACEOF

fi

#--------------------------------------------------------------------
# Windows XP theme engine header for Ttk
#--------------------------------------------------------------------

echo "$as_me:$LINENO: checking for uxtheme.h" >&5
echo $ECHO_N "checking for uxtheme.h... $ECHO_C" >&6
if test "${ac_cv_header_uxtheme_h+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
#include <windows.h>

ac_fn_c_check_header_compile "$LINENO" "uxtheme.h" "ac_cv_header_uxtheme_h" "#include <windows.h>
"
#include <uxtheme.h>
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  ac_cv_header_uxtheme_h=yes
if test "x$ac_cv_header_uxtheme_h" = xyes
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

then :
ac_cv_header_uxtheme_h=no
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
echo "$as_me:$LINENO: result: $ac_cv_header_uxtheme_h" >&5
echo "${ECHO_T}$ac_cv_header_uxtheme_h" >&6
if test $ac_cv_header_uxtheme_h = yes; then
  cat >>confdefs.h <<\_ACEOF
#define HAVE_UXTHEME_H 1
  printf "%s\n" "#define HAVE_UXTHEME_H 1" >>confdefs.h
_ACEOF

else
  { echo "$as_me:$LINENO: xpnative theme will be unavailable" >&5
echo "$as_me: xpnative theme will be unavailable" >&6;}
else $as_nop
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: xpnative theme will be unavailable" >&5
printf "%s\n" "$as_me: xpnative theme will be unavailable" >&6;}
fi


echo "$as_me:$LINENO: checking for vssym32.h" >&5
echo $ECHO_N "checking for vssym32.h... $ECHO_C" >&6
if test "${ac_cv_header_vssym32_h+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
#include <windows.h>
ac_fn_c_check_header_compile "$LINENO" "vssym32.h" "ac_cv_header_vssym32_h" "#include <windows.h>
#include <uxtheme.h>

"
#include <vssym32.h>
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  ac_cv_header_vssym32_h=yes
if test "x$ac_cv_header_vssym32_h" = xyes
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

then :
ac_cv_header_vssym32_h=no
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
echo "$as_me:$LINENO: result: $ac_cv_header_vssym32_h" >&5
echo "${ECHO_T}$ac_cv_header_vssym32_h" >&6
if test $ac_cv_header_vssym32_h = yes; then
  cat >>confdefs.h <<\_ACEOF
#define HAVE_VSSYM32_H 1
  printf "%s\n" "#define HAVE_VSSYM32_H 1" >>confdefs.h
_ACEOF

fi



#--------------------------------------------------------------------
# Set the default compiler switches based on the --enable-symbols
# option.  This macro depends on C flags, and should be called
# after SC_CONFIG_CFLAGS macro is called.
#--------------------------------------------------------------------


    echo "$as_me:$LINENO: checking for build with symbols" >&5
echo $ECHO_N "checking for build with symbols... $ECHO_C" >&6
    # Check whether --enable-symbols or --disable-symbols was given.
if test "${enable_symbols+set}" = set; then
  enableval="$enable_symbols"
  tcl_ok=$enableval
else
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for build with symbols" >&5
printf %s "checking for build with symbols... " >&6; }
    # Check whether --enable-symbols was given.
if test ${enable_symbols+y}
then :
  enableval=$enable_symbols; tcl_ok=$enableval
else $as_nop
  tcl_ok=no
fi;
fi

# FIXME: Currently, LDFLAGS_DEFAULT is not used, it should work like CFLAGS_DEFAULT.
    if test "$tcl_ok" = "no"; then
	CFLAGS_DEFAULT='$(CFLAGS_OPTIMIZE)'
	LDFLAGS_DEFAULT='$(LDFLAGS_OPTIMIZE)'
	DBGX=""

cat >>confdefs.h <<\_ACEOF
#define NDEBUG 1
printf "%s\n" "#define NDEBUG 1" >>confdefs.h
_ACEOF

	echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }

	cat >>confdefs.h <<\_ACEOF
#define TCL_CFG_OPTIMIZED 1
	printf "%s\n" "#define TCL_CFG_OPTIMIZED 1" >>confdefs.h
_ACEOF

    else
	CFLAGS_DEFAULT='$(CFLAGS_DEBUG)'
	LDFLAGS_DEFAULT='$(LDFLAGS_DEBUG)'
	DBGX=g
	if test "$tcl_ok" = "yes"; then
	    echo "$as_me:$LINENO: result: yes (standard debugging)" >&5
echo "${ECHO_T}yes (standard debugging)" >&6
	    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes (standard debugging)" >&5
printf "%s\n" "yes (standard debugging)" >&6; }
	fi
    fi



    if test "$tcl_ok" = "mem" -o "$tcl_ok" = "all"; then

cat >>confdefs.h <<\_ACEOF
#define TCL_MEM_DEBUG 1
printf "%s\n" "#define TCL_MEM_DEBUG 1" >>confdefs.h
_ACEOF

    fi

    if test "$tcl_ok" = "compile" -o "$tcl_ok" = "all"; then

cat >>confdefs.h <<\_ACEOF
#define TCL_COMPILE_DEBUG 1
printf "%s\n" "#define TCL_COMPILE_DEBUG 1" >>confdefs.h
_ACEOF


cat >>confdefs.h <<\_ACEOF
#define TCL_COMPILE_STATS 1
printf "%s\n" "#define TCL_COMPILE_STATS 1" >>confdefs.h
_ACEOF

    fi

    if test "$tcl_ok" != "yes" -a "$tcl_ok" != "no"; then
	if test "$tcl_ok" = "all"; then
	    echo "$as_me:$LINENO: result: enabled symbols mem compile debugging" >&5
echo "${ECHO_T}enabled symbols mem compile debugging" >&6
	    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: enabled symbols mem compile debugging" >&5
printf "%s\n" "enabled symbols mem compile debugging" >&6; }
	else
	    echo "$as_me:$LINENO: result: enabled $tcl_ok debugging" >&5
echo "${ECHO_T}enabled $tcl_ok debugging" >&6
	    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: enabled $tcl_ok debugging" >&5
printf "%s\n" "enabled $tcl_ok debugging" >&6; }
	fi
    fi


TK_DBGX=${DBGX}

#--------------------------------------------------------------------
# Embed the manifest if we can determine how
#--------------------------------------------------------------------

ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
printf %s "checking how to run the C preprocessor... " >&6; }
# On Suns, sometimes $CPP names a directory.
if test -n "$CPP" && test -d "$CPP"; then
  CPP=
fi
if test -z "$CPP"; then
  if test ${ac_cv_prog_CPP+y}
then :
  printf %s "(cached) " >&6
else $as_nop
      # Double quotes because $CC needs to be expanded
    for CPP in "$CC -E" "$CC -E -traditional-cpp" cpp /lib/cpp
    do
      ac_preproc_ok=false
for ac_c_preproc_warn_flag in '' yes
do
  # Use a header file that comes with gcc, so configuring glibc
  # with a fresh cross-compiler works.
  # On the NeXT, cc -E runs the code through the compiler's parser,
  # not just through cpp. "Syntax error" is here to catch this case.
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <limits.h>
		     Syntax error
_ACEOF
if ac_fn_c_try_cpp "$LINENO"
then :

    echo "$as_me:$LINENO: checking whether to embed manifest" >&5
echo $ECHO_N "checking whether to embed manifest... $ECHO_C" >&6
    # Check whether --enable-embedded-manifest or --disable-embedded-manifest was given.
if test "${enable_embedded_manifest+set}" = set; then
  enableval="$enable_embedded_manifest"
  embed_ok=$enableval
else $as_nop
  # Broken: fails on valid input.
continue
fi
rm -f conftest.err conftest.i conftest.$ac_ext

  # OK, works on sane cases.  Now check whether nonexistent headers
  # can be detected and how.
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <ac_nonexistent.h>
_ACEOF
if ac_fn_c_try_cpp "$LINENO"
then :
  # Broken: success on invalid input.
continue
else $as_nop
  # Passes both tests.
ac_preproc_ok=:
break
fi
rm -f conftest.err conftest.i conftest.$ac_ext

done
# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
rm -f conftest.i conftest.err conftest.$ac_ext
if $ac_preproc_ok
then :
  break
fi

    done
    ac_cv_prog_CPP=$CPP

fi
  CPP=$ac_cv_prog_CPP
else
  ac_cv_prog_CPP=$CPP
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
printf "%s\n" "$CPP" >&6; }
ac_preproc_ok=false
for ac_c_preproc_warn_flag in '' yes
do
  # Use a header file that comes with gcc, so configuring glibc
  # with a fresh cross-compiler works.
  # On the NeXT, cc -E runs the code through the compiler's parser,
  # not just through cpp. "Syntax error" is here to catch this case.
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <limits.h>
		     Syntax error
_ACEOF
if ac_fn_c_try_cpp "$LINENO"
then :

else $as_nop
  # Broken: fails on valid input.
continue
fi
rm -f conftest.err conftest.i conftest.$ac_ext

  # OK, works on sane cases.  Now check whether nonexistent headers
  # can be detected and how.
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <ac_nonexistent.h>
_ACEOF
if ac_fn_c_try_cpp "$LINENO"
then :
  # Broken: success on invalid input.
continue
else $as_nop
  # Passes both tests.
ac_preproc_ok=:
break
fi
rm -f conftest.err conftest.i conftest.$ac_ext

done
# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
rm -f conftest.i conftest.err conftest.$ac_ext
if $ac_preproc_ok
then :

else $as_nop
  { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
See \`config.log' for more details" "$LINENO" 5; }
fi

ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu



    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to embed manifest" >&5
printf %s "checking whether to embed manifest... " >&6; }
    # Check whether --enable-embedded-manifest was given.
if test ${enable_embedded_manifest+y}
then :
  enableval=$enable_embedded_manifest; embed_ok=$enableval
else $as_nop
  embed_ok=yes
fi;
fi


    VC_MANIFEST_EMBED_DLL=
    VC_MANIFEST_EMBED_EXE=
    result=no
    if test "$embed_ok" = "yes" -a "${SHARED_BUILD}" = "1" \
       -a "$GCC" != "yes" ; then
	# Add the magic to embed the manifest into the dll/exe
	cat >conftest.$ac_ext <<_ACEOF
	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */

#if defined(_MSC_VER) && _MSC_VER >= 1400
print("manifest needed")
#endif

_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
  $EGREP "manifest needed" >/dev/null 2>&1; then
  $EGREP "manifest needed" >/dev/null 2>&1
then :

	# Could do a CHECK_PROG for mt, but should always be with MSVC8+
	# Could add 'if test -f' check, but manifest should be created
	# in this compiler case
	# Add in a manifest argument that may be specified
	# XXX Needs improvement so that the test for existence accounts
	# XXX for a provided (known) manifest
	VC_MANIFEST_EMBED_DLL="if test -f \[email protected] ; then mt.exe -nologo -manifest \[email protected] wish.exe.manifest -outputresource:\$@\;2 ; fi"
	VC_MANIFEST_EMBED_EXE="if test -f \[email protected] ; then mt.exe -nologo -manifest \[email protected] wish.exe.manifest -outputresource:\$@\;1 ; fi"
	result=yes
	if test "xwish.exe.manifest" != x ; then
	    result="yes (wish.exe.manifest)"
	fi

fi
rm -f conftest*
rm -rf conftest*

    fi
    echo "$as_me:$LINENO: result: $result" >&5
echo "${ECHO_T}$result" >&6
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $result" >&5
printf "%s\n" "$result" >&6; }





    echo "$as_me:$LINENO: checking for tclsh in Tcl build directory" >&5
echo $ECHO_N "checking for tclsh in Tcl build directory... $ECHO_C" >&6
    BUILD_TCLSH=${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT}
    echo "$as_me:$LINENO: result: $BUILD_TCLSH" >&5
echo "${ECHO_T}$BUILD_TCLSH" >&6
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for tclsh in Tcl build directory" >&5
printf %s "checking for tclsh in Tcl build directory... " >&6; }
    BUILD_TCLSH=${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${EXEEXT}
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $BUILD_TCLSH" >&5
printf "%s\n" "$BUILD_TCLSH" >&6; }



    echo "$as_me:$LINENO: checking for tclsh" >&5
echo $ECHO_N "checking for tclsh... $ECHO_C" >&6
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for tclsh" >&5
printf %s "checking for tclsh... " >&6; }

    if test "${ac_cv_path_tclsh+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
    if test ${ac_cv_path_tclsh+y}
then :
  printf %s "(cached) " >&6
else $as_nop

	search_path=`echo ${PATH} | sed -e 's/:/ /g'`
	for dir in $search_path ; do
	    for j in `ls -r $dir/tclsh[8-9]*.exe 2> /dev/null` \
		    `ls -r $dir/tclsh* 2> /dev/null` ; do
		if test x"$ac_cv_path_tclsh" = x ; then
		    if test -f "$j" ; then
			ac_cv_path_tclsh=$j
			break
		    fi
		fi
	    done
	done

fi


    if test -f "$ac_cv_path_tclsh" ; then
	TCLSH_PROG="$ac_cv_path_tclsh"
	echo "$as_me:$LINENO: result: $TCLSH_PROG" >&5
echo "${ECHO_T}$TCLSH_PROG" >&6
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $TCLSH_PROG" >&5
printf "%s\n" "$TCLSH_PROG" >&6; }
    else
	# It is not an error if an installed version of Tcl can't be located.
	TCLSH_PROG=""
	echo "$as_me:$LINENO: result: No tclsh found on PATH" >&5
echo "${ECHO_T}No tclsh found on PATH" >&6
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: No tclsh found on PATH" >&5
printf "%s\n" "No tclsh found on PATH" >&6; }
    fi



#------------------------------------------------------------------------
# tkConfig.sh refers to this by a different name
#------------------------------------------------------------------------
4953
4954
4955
4956
4957
4958
4959

4960




4961
4962
4963
4964
4965
4966
4967
5451
5452
5453
5454
5455
5456
5457
5458

5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469







+
-
+
+
+
+







TK_SHARED_LIB_SUFFIX="\${NODOT_VERSION}${DLLSUFFIX}"
TK_UNSHARED_LIB_SUFFIX="\${NODOT_VERSION}${LIBSUFFIX}"
TK_EXPORT_FILE_SUFFIX="\${NODOT_VERSION}${LIBSUFFIX}"

eval "TK_SRC_DIR=\"`cd $srcdir/..; pwd`\""

eval "TK_DLL_FILE=tk$VER${DLLSUFFIX}"
if test ${SHARED_BUILD} = 0 ; then
eval "TK_LIB_FILE=${LIBPREFIX}tk$VER${LIBSUFFIX}"
 eval "TK_LIB_FILE=${LIBPREFIX}tk${VER}${LIBSUFFIX}"
else
 eval "TK_LIB_FILE=${LIBPREFIX}tk${VER}${DLLSUFFIX}.a"
fi

eval "TK_STUB_LIB_FILE=${LIBPREFIX}tkstub${VER}${LIBSUFFIX}"
# FIXME: All of this var junk needs to be done in tcl.m4 !!!!
# I left out the other vars that also need to get defined here.
# we also need to double check about spaces in path names
eval "TK_LIB_FLAG=\"-ltk${VER}${LIBFLAGSUFFIX}\""
TK_LIB_SPEC="-L${libdir} ${TK_LIB_FLAG}"
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995

4996
4997
4998
4999
5000
5001
5002

5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5487
5488
5489
5490
5491
5492
5493




5494

5495
5496




5497

5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511


5512
5513
5514
5515
5516
5517
5518







-
-
-
-
+
-


-
-
-
-
+
-














-
-








#--------------------------------------------------------------------
# Adjust the defines for how the resources are built depending
# on symbols and static vs. shared.
#--------------------------------------------------------------------

if test ${SHARED_BUILD} = 0 -o "$TCL_NEEDS_EXP_FILE" = 0; then
    if test "${DBGX}" = "d"; then
        RC_DEFINES="${RC_DEFINE} STATIC_BUILD ${RC_DEFINE} DEBUG"
    else
        RC_DEFINES="${RC_DEFINE} STATIC_BUILD"
    RC_DEFINES="${RC_DEFINE} STATIC_BUILD"
    fi
    TK_RES=""
else
    if test "${DBGX}" = "d"; then
        RC_DEFINES="${RC_DEFINE} DEBUG"
    else
        RC_DEFINES=""
    RC_DEFINES=""
    fi
    TK_RES='tk.$(RES)'
fi

# The wish.exe.manifest requires these
# TK_WIN_VERSION is the 4 dotted pair Windows version format which needs
# the release level, and must account for interim release versioning
case "$TK_PATCH_LEVEL" in
     *a*) TK_RELEASE_LEVEL=0 ;;
     *b*) TK_RELEASE_LEVEL=1 ;;
     *)   TK_RELEASE_LEVEL=2 ;;
esac
TK_WIN_VERSION="$TK_VERSION.$TK_RELEASE_LEVEL.`echo $TK_PATCH_LEVEL | tr -d ab.`"

# X86|AMD64|IA64 for manifest









5094
5095
5096
5097
5098
5099
5100
5101


5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120

5121
5122
















5123

5124
5125
5126
5127
5128




5129
5130
5131
5132

5133
5134
5135
5136

5137
5138
5139



5140

5141
5142
5143


5144
5145
5146
5147
5148
5149
5150
5151
5152






















5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181

5182
5183







5184
5185
5186


5187
5188

5189
5190
5191
5192
5193
5194
5195
5196













5197
5198
5199
5200
5201
5202
5203
5204
5205



5206
5207
5208
5209
5210

5211
5212
5213
5214
5215
5216
5217






5218
5219
5220
5221
5222
5223
5224
5225


5226
5227
5228
5229
5230




5231
5232
5233
5234
5235
5236
5237
5238
5239

5240
5241
5242
5243
5244
5245
5246






5247
5248
5249





5250
5251
5252

5253
5254


5255
5256



5257
5258
5259

5260
5261
5262
5263


5264
5265
5266
5267
5268
5269













5270
5271
5272
5273





5274
5275







5276
5277
5278
5279
5280
5281

5282
5283

5284
5285
5286




5287
5288































































































































5289
5290
5291
5292
5293
5294

5295
5296
5297
5298
5299





5300
5301
5302

5303
5304
5305

5306
5307
5308
5309
5310
5311
5312
5313
5314















5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335

5336
5337
5338
5339
5340
5341
5342
5343




5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358





















5359
5360

5361
5362

5363
5364
5365
5366
5367
5368
5369







5370
5371
5372
5373

5374
5375
5376
5377
5378
5379
5380



5381
5382
5383

5384
5385
5386
5387
5388
5389
5390
5391
5392















5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404




5405
5406
5407
5408
5409
5410
5411




5412
5413
5414
5415

5416
5417
5418
5419

5420
5421

5422
5423
5424










5425
5426


5427
5428
5429
5430
5431


5432
5433
5434







5435
5436
5437
5438



5439
5440
5441
5442
5443

5444
5445
5446
5447
5448
5449
5450

5451
5452
5453



5454
5455

5456
5457

5458
5459
5460
5461
5462









5463

5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474



5475
5476
5477
5478
5479



5480
5481
5482
5483


5484
5485

5486
5487
5488
5489
5490
5491
5492
5493
5494

5495
5496

5497
5498
5499
5500
5501
5502
5503
5504
5505
5506



5507
5508
5509
5510
5511


5512

5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
5524



5525
5526

5527

5528
5529
5530



5531
5532

5533
5534
5535
5536




5537
5538
5539
5540


5541
5542
5543
5544
5545


5546
5547
5548




5549
5550
5551
5552


5553
5554

5555
5556


5557


5558
5559
5560
5561


5562
5563
5564
5565
5566





5567
5568
5569



5570
5571
5572

5573
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591



5592
5593
5594
5595
5596
5597
5598
5599
5600


5601
5602
5603
5604

5605
5606
5607
5608




5609


5610
5611
5612
5613
5614
5615
5616
5617
5618


5619
5620
5621


5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
5633
5634
5635

5636
5637
5638






5639
5640
5641
5642
5643
5644









5645



5646
5647



5648
5649
5650

5651
5652
5653
5654
5655
5656





5657
5658
5659

5660
5661
5662
5663
5664
5665
5666

5667
5668
5669
5670

5671
5672



5673
5674

5675
5676





5677
5678
5679
5680
5681
5682
5683


5684
5685
5686
5687


5688
5689
5690

5691
5692
5693



5694
5695
5696



5697
5698
5699
5700

















5701
5702

5703
5704
5705
5706
5707





5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721












5722
5723
5724
5725
5726
5727
5728
5729
5730









5731
5732
5733
5734
5735
5736

5737
5738
5739







5740
5741
5742

5743
5744
5745
5746
5747
5748
5749
5750
5751









5752
5753
5754
5755


5756
5757
5758
5759
5760








5761
5762


5763
5764
5765



5766
5767
5768
5769
5770





5771
5772
5773



5774
5775
5776
5777




5778
5779
5780
5781
5782





5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797


















5798
5799
5800
5801
5802
5803
5804
5805
5806
5807









5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
5822
5823
5824




















5825
5826


5827
5828
5829
5830






5831
5832
5833
5834
5835



5836
5837
5838
5839
5840
5841
5842


5843
5844









5845
5846
5847
5848

5849
5850
5851
5852
5853
5854
5855





5856
5857
5858
5859
5860
5861





5862
5863
5864
5865
5866
5867
5868
5869

5870
5871
5872
5873


5874
5875

5876
5877
5878
5879
5880
5881
5882
















5883
5884
5885
5886
5887
5888




















5889
5890
5891


5892
5893
5894
5895


5896
5897
5898
5899

5900
5901
5902
5903

5904
5905
5906
5907
5908
5909







5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920
5921
5922
5923
5924
5925
5926
5927
5928
5929











5930
5931
5932
5933
5934
5935

5936
5937
5938
5939
5940
5941
5942
5943
5944















5945
5946
5947

5948
5949
5950

5951
5952

5953
5954

5955
5956
5957
5958
5959





5960
5961
5962
5963
5964
5965
5966
5967
5968
5969
5970
5971
5972
5973
5974
5975
5976
5977
5978
5979
5980
5981
5982
5983
5984
5985
5986
5987
5988
5989
5990
5991
5992

5993
5994
5995
5996
5997
5998
5999
6000

6001
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019
6020
6021
6022
6023

6024
6025
6026
6027
6028







6029
6030
6031
6032
6033
6034
6035






6036
6037
6038







6039
6040
6041






6042
6043
6044










6045
6046




6047
6048


6049
6050
6051

6052
6053
6054
6055
6056
6057
6058
6059
6060
6061
6062
6063
6064
6065
6066
6067
6068
6069
6070



































6071
6072

6073
6074
6075
6076
6077

6078
6079
6080



6081
6082
6083
6084
6085
6086
6087
6088
6089
6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101

6102




6103
6104

5586
5587
5588
5589
5590
5591
5592

5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612

5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631

5632
5633




5634
5635
5636
5637
5638
5639
5640

5641
5642
5643


5644
5645


5646
5647
5648
5649
5650
5651


5652
5653
5654








5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682
5683
5684















5685
5686
5687
5688
5689

5690
5691

5692
5693
5694
5695
5696
5697
5698
5699


5700
5701
5702

5703
5704







5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717









5718
5719
5720

5721
5722
5723
5724
5725
5726
5727





5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740

5741
5742
5743
5744



5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759






5760
5761
5762
5763
5764
5765
5766


5767
5768
5769
5770
5771
5772
5773

5774
5775
5776
5777
5778


5779
5780
5781



5782




5783
5784

5785
5786
5787


5788
5789
5790
5791
5792
5793
5794
5795
5796
5797
5798
5799
5800
5801
5802
5803
5804
5805
5806
5807
5808
5809


5810
5811
5812
5813
5814
5815
5816






5817


5818

5819
5820
5821
5822
5823
5824


5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860
5861
5862
5863
5864
5865
5866
5867
5868
5869
5870
5871
5872
5873
5874
5875
5876
5877
5878
5879
5880
5881
5882
5883
5884
5885
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920
5921
5922
5923
5924
5925
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938
5939
5940
5941
5942
5943
5944
5945
5946
5947
5948
5949
5950
5951
5952
5953
5954
5955
5956

5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968


5969
5970
5971

5972









5973
5974
5975
5976
5977
5978
5979
5980
5981
5982
5983
5984
5985
5986
5987
5988
5989
5990
5991
5992
5993
5994












5995

5996








5997
5998
5999
6000















6001
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019
6020
6021


6022


6023







6024
6025
6026
6027
6028
6029
6030




6031







6032
6033
6034



6035









6036
6037
6038
6039
6040
6041
6042
6043
6044
6045
6046
6047
6048
6049
6050












6051
6052
6053
6054







6055
6056
6057
6058




6059




6060


6061



6062
6063
6064
6065
6066
6067
6068
6069
6070
6071


6072
6073





6074
6075



6076
6077
6078
6079
6080
6081
6082




6083
6084
6085





6086







6087



6088
6089
6090

6091
6092
6093

6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
6105
6106
6107
6108

6109
6110
6111
6112
6113
6114
6115
6116
6117



6118
6119
6120





6121
6122
6123
6124



6125
6126
6127

6128









6129
6130

6131
6132
6133
6134
6135
6136
6137
6138



6139
6140
6141
6142
6143



6144
6145

6146
6147



6148



6149



6150
6151
6152
6153

6154
6155
6156
6157


6158
6159
6160
6161

6162
6163
6164


6165
6166
6167
6168
6169
6170


6171
6172
6173
6174
6175
6176

6177
6178
6179


6180
6181
6182
6183
6184
6185


6186
6187
6188

6189
6190
6191
6192
6193

6194
6195
6196
6197


6198
6199

6200
6201
6202
6203
6204
6205
6206
6207
6208



6209
6210
6211
6212
6213

6214
6215
6216
6217
6218




6219
6220
6221
6222


6223
6224



6225
6226
6227









6228
6229
6230
6231
6232

6233




6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245




6246
6247

6248

6249
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263

6264
6265


6266
6267
6268
6269
6270
6271
6272
6273
6274



6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
6287
6288

6289
6290
6291
6292
6293

6294






6295
6296
6297
6298
6299

6300
6301
6302
6303
6304
6305
6306
6307
6308

6309
6310
6311
6312

6313
6314

6315
6316
6317
6318
6319
6320


6321
6322
6323
6324
6325
6326

6327
6328
6329


6330
6331
6332
6333


6334
6335



6336



6337
6338
6339



6340
6341
6342
6343



6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
6356
6357
6358
6359
6360
6361

6362





6363
6364
6365
6366
6367














6368
6369
6370
6371
6372
6373
6374
6375
6376
6377
6378
6379









6380
6381
6382
6383
6384
6385
6386
6387
6388






6389



6390
6391
6392
6393
6394
6395
6396



6397









6398
6399
6400
6401
6402
6403
6404
6405
6406




6407
6408





6409
6410
6411
6412
6413
6414
6415
6416


6417
6418



6419
6420
6421





6422
6423
6424
6425
6426



6427
6428
6429




6430
6431
6432
6433





6434
6435
6436
6437
6438















6439
6440
6441
6442
6443
6444
6445
6446
6447
6448
6449
6450
6451
6452
6453
6454
6455
6456










6457
6458
6459
6460
6461
6462
6463
6464
6465

















6466
6467
6468
6469
6470
6471
6472
6473
6474
6475
6476
6477
6478
6479
6480
6481
6482
6483
6484
6485


6486
6487




6488
6489
6490
6491
6492
6493





6494
6495
6496






6497
6498
6499


6500
6501
6502
6503
6504
6505
6506
6507
6508




6509







6510
6511
6512
6513
6514






6515
6516
6517
6518
6519








6520




6521
6522


6523







6524
6525
6526
6527
6528
6529
6530
6531
6532
6533
6534
6535
6536
6537
6538
6539
6540





6541
6542
6543
6544
6545
6546
6547
6548
6549
6550
6551
6552
6553
6554
6555
6556
6557
6558
6559
6560



6561
6562




6563
6564
6565
6566


6567
6568
6569
6570

6571






6572
6573
6574
6575
6576
6577
6578




















6579
6580
6581
6582
6583
6584
6585
6586
6587
6588
6589






6590
6591
6592







6593
6594
6595
6596
6597
6598
6599
6600
6601
6602
6603
6604
6605
6606
6607
6608
6609

6610
6611


6612


6613


6614
6615




6616
6617
6618
6619
6620

































6621






6622

6623
6624
6625





















6626





6627
6628
6629
6630
6631
6632
6633







6634
6635
6636
6637
6638
6639



6640
6641
6642
6643
6644
6645
6646



6647
6648
6649
6650
6651
6652



6653
6654
6655
6656
6657
6658
6659
6660
6661
6662

6663
6664
6665
6666
6667


6668
6669
6670
6671

6672
6673
6674

















6675
6676
6677
6678
6679
6680
6681
6682
6683
6684
6685
6686
6687
6688
6689
6690
6691
6692
6693
6694
6695
6696
6697
6698
6699
6700
6701
6702
6703
6704
6705
6706
6707
6708
6709
6710

6711

6712

6713

6714
6715

6716
6717
6718
6719
6720
6721
6722
6723
6724
6725
6726
6727
6728
6729
6730
6731
6732
6733
6734
6735
6736
6737
6738
6739

6740
6741
6742
6743
6744
6745
6746
6747
6748







-
+
+


















-
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+

-
-
-
-
+
+
+
+



-
+


-
-
+

-
-
+
+
+

+

-
-
+
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








-
-
-
-
-
-
-
-
-
-
-
-
-
-
-





-
+

-
+
+
+
+
+
+
+

-
-
+
+

-
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
-




+


-
-
-
-
-
+
+
+
+
+
+







-
+
+


-
-
-
+
+
+
+









+

-
-
-
-
-
-
+
+
+
+
+
+

-
-
+
+
+
+
+


-
+


+
+
-
-
+
+
+
-
-
-
+
-
-
-
-
+
+
-



-
-
+
+
+
+
+
+
+
+
+
+
+
+
+




+
+
+
+
+
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
+
-
-
+
-


+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
+





+
+
+
+
+

-
-
+


-
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







-
-
-
-
-
-
-
-
-
-
-
-

-
+
-
-
-
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
-
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
+
-
-
-
-
-
-
-
+
+
+
-
-
-
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
-
-
-
-
+
-
-
-
-
+
-
-
+
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
-
-
-
+
+
-
-
-
+
+
+
+
+
+
+
-
-
-
-
+
+
+
-
-
-
-
-
+
-
-
-
-
-
-
-
+
-
-
-
+
+
+
-

+

-
+





+
+
+
+
+
+
+
+
+
-
+








-
-
-
+
+
+
-
-
-
-
-
+
+
+

-
-
-
+
+

-
+
-
-
-
-
-
-
-
-
-
+

-
+







-
-
-
+
+
+


-
-
-
+
+
-
+

-
-
-

-
-
-

-
-
-
+
+
+

-
+

+

-
-
+
+
+

-
+


-
-
+
+
+
+


-
-
+
+




-
+
+

-
-
+
+
+
+


-
-
+
+

-
+


+
+
-
+
+


-
-
+
+
-




+
+
+
+
+
-
-
-
+
+
+


-
+




-
-
-
-




-
-


-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
+
+



-
+
-
-
-
-
+
+
+
+

+
+





-
-
-
-
+
+
-

-
+
+













-
+

-
-
+
+
+
+
+
+



-
-
-
+
+
+
+
+
+
+
+
+

+
+
+

-
+
+
+


-
+
-
-
-
-
-
-
+
+
+
+
+
-


+






-
+



-
+

-
+
+
+


+
-
-
+
+
+
+
+

-



-
-
+
+


-
-
+
+
-
-
-
+
-
-
-
+
+
+
-
-
-
+
+
+

-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
-
-
-
+
+
+
+
+
+
+
-
-
-
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
+
+
-
-
-
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
+
+
+
-
-
-
-
-
-

+
+
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
+
-
-
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
+
-
-
-
-
+
+
-
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
-
-
-
-
+
+


-
-
+



-
+
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+


-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
+

-
-
+
-
-
+
-
-
+

-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-

-
+


-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
-

+
+
+
+
-
-
+
+


-
+


-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+
-

-

-
+

-

+
+
+




















-
+

+
+
+
+


+







                              ac_config_files="$ac_config_files Makefile tkConfig.sh wish.exe.manifest"
ac_config_files="$ac_config_files Makefile tkConfig.sh wish.exe.manifest"

cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
# tests run on this system so they can be shared between configure
# scripts and configure runs, see configure's option --config-cache.
# It is not useful on other systems.  If it contains results you don't
# want to keep, you may remove or edit it.
#
# config.status only pays attention to the cache file if you give it
# the --recheck option to rerun configure.
#
# `ac_cv_env_foo' variables (set or unset) will be overridden when
# loading this file, other *unset* `ac_cv_foo' will be assigned the
# following values.

_ACEOF

# The following way of writing the cache mishandles newlines in values,
# but we know of no workaround that is simple, portable, and efficient.
# So, don't put newlines in cache variables' values.
# So, we kill variables containing newlines.
# Ultrix sh set writes to stderr and can't be redirected directly,
# and sets the high bit in the cache file unless we assign to the vars.
(
  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
    eval ac_val=\$$ac_var
    case $ac_val in #(
    *${as_nl}*)
      case $ac_var in #(
      *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
      esac
      case $ac_var in #(
      _ | IFS | as_nl) ;; #(
      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
      *) { eval $ac_var=; unset $ac_var;} ;;
      esac ;;
    esac
  done
{

  (set) 2>&1 |
    case `(ac_space=' '; set | grep ac_space) 2>&1` in
    *ac_space=\ *)
      # `set' does not quote correctly, so add quotes (double-quote
      # substitution turns \\\\ into \\, and sed turns \\ into \).
    case $as_nl`(ac_space=' '; set) 2>&1` in #(
    *${as_nl}ac_space=\ *)
      # `set' does not quote correctly, so add quotes: double-quote
      # substitution turns \\\\ into \\, and sed turns \\ into \.
      sed -n \
	"s/'/'\\\\''/g;
	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
      ;;
      ;; #(
    *)
      # `set' quotes correctly as required by POSIX, so do not add quotes.
      sed -n \
	"s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
      ;;
    esac;
} |
    esac |
    sort
) |
  sed '
     /^ac_cv_env_/b end
     t clear
     : clear
     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
     :clear
     s/^\([^=]*\)=\(.*[{}].*\)$/test ${\1+y} || &/
     t end
     /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
     : end' >>confcache
if diff $cache_file confcache >/dev/null 2>&1; then :; else
  if test -w $cache_file; then
    test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file"
    cat confcache >$cache_file
  else
    echo "not updating unwritable cache $cache_file"
     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
     :end' >>confcache
if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
  if test -w "$cache_file"; then
    if test "x$cache_file" != "x/dev/null"; then
      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
printf "%s\n" "$as_me: updating cache $cache_file" >&6;}
      if test ! -f "$cache_file" || test -h "$cache_file"; then
	cat confcache >"$cache_file"
      else
        case $cache_file in #(
        */* | ?:*)
	  mv -f confcache "$cache_file"$$ &&
	  mv -f "$cache_file"$$ "$cache_file" ;; #(
        *)
	  mv -f confcache "$cache_file" ;;
	esac
      fi
    fi
  else
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
printf "%s\n" "$as_me: not updating unwritable cache $cache_file" >&6;}
  fi
fi
rm -f confcache

test "x$prefix" = xNONE && prefix=$ac_default_prefix
# Let make expand exec_prefix.
test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'

# VPATH may cause trouble with some makes, so we remove $(srcdir),
# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
# trailing colons and then remove the whole line if VPATH becomes empty
# (actually we leave an empty line to preserve line numbers).
if test "x$srcdir" = x.; then
  ac_vpsub='/^[	 ]*VPATH[	 ]*=/{
s/:*\$(srcdir):*/:/;
s/:*\${srcdir}:*/:/;
s/:*@srcdir@:*/:/;
s/^\([^=]*=[	 ]*\):*/\1/;
s/:*$//;
s/^[^=]*=[	 ]*$//;
}'
fi

# Transform confdefs.h into DEFS.
# Protect against shell expansion while executing Makefile rules.
# Protect against Makefile macro expansion.
#
# If the first sed substitution is executed (which looks for macros that
# take arguments), then we branch to the quote section.  Otherwise,
# take arguments), then branch to the quote section.  Otherwise,
# look for a macro that doesn't take arguments.
cat >confdef2opt.sed <<\_ACEOF
ac_script='
:mline
/\\$/{
 N
 s,\\\n,,
 b mline
}
t clear
: clear
s,^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 (][^	 (]*([^)]*)\)[	 ]*\(.*\),-D\1=\2,g
:clear
s/^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 (][^	 (]*([^)]*)\)[	 ]*\(.*\)/-D\1=\2/g
t quote
s,^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 ][^	 ]*\)[	 ]*\(.*\),-D\1=\2,g
s/^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 ][^	 ]*\)[	 ]*\(.*\)/-D\1=\2/g
t quote
d
: quote
s,[	 `~#$^&*(){}\\|;'"<>?],\\&,g
s,\[,\\&,g
s,\],\\&,g
s,\$,$$,g
p
b any
:quote
s/[	 `~#$^&*(){}\\|;'\''"<>?]/\\&/g
s/\[/\\&/g
s/\]/\\&/g
s/\$/$$/g
H
:any
${
	g
	s/^\n//
	s/\n/ /g
	p
_ACEOF
# We use echo to avoid assuming a particular line-breaking character.
# The extra dot is to prevent the shell from consuming trailing
# line-breaks from the sub-command output.  A line-break within
# single-quotes doesn't work because, if this script is created in a
# platform that uses two characters for line-breaks (e.g., DOS), tr
# would break.
ac_LF_and_DOT=`echo; echo .`
DEFS=`sed -n -f confdef2opt.sed confdefs.h | tr "$ac_LF_and_DOT" ' .'`
}
'
DEFS=`sed -n "$ac_script" confdefs.h`
rm -f confdef2opt.sed


ac_libobjs=
ac_ltlibobjs=
U=
for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
  # 1. Remove the extension, and $U if already installed.
  ac_i=`echo "$ac_i" |
	 sed 's/\$U\././;s/\.o$//;s/\.obj$//'`
  # 2. Add them.
  ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext"
  ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo'
  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
  ac_i=`printf "%s\n" "$ac_i" | sed "$ac_script"`
  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
  #    will be set to the directory where LIBOBJS objects are built.
  as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
  as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
done
LIBOBJS=$ac_libobjs

LTLIBOBJS=$ac_ltlibobjs



: ${CONFIG_STATUS=./config.status}
: "${CONFIG_STATUS=./config.status}"
ac_write_fail=0
ac_clean_files_save=$ac_clean_files
ac_clean_files="$ac_clean_files $CONFIG_STATUS"
{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
echo "$as_me: creating $CONFIG_STATUS" >&6;}
cat >$CONFIG_STATUS <<_ACEOF
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
printf "%s\n" "$as_me: creating $CONFIG_STATUS" >&6;}
as_write_fail=0
cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
#! $SHELL
# Generated by $as_me.
# Run this file to recreate the current configuration.
# Compiler output produced by configure, useful for debugging
# configure, is in config.log if it exists.

debug=false
ac_cs_recheck=false
ac_cs_silent=false

SHELL=\${CONFIG_SHELL-$SHELL}
_ACEOF

cat >>$CONFIG_STATUS <<\_ACEOF
## --------------------- ##
## M4sh Initialization.  ##
## --------------------- ##
export SHELL
_ASEOF
cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
## -------------------- ##
## M4sh Initialization. ##
## -------------------- ##

# Be Bourne compatible
if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
# Be more Bourne compatible
DUALCASE=1; export DUALCASE # for MKS sh
as_nop=:
if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
then :
  emulate sh
  NULLCMD=:
  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
  # is contrary to our usage.  Disable this feature.
  alias -g '${1+"$@"}'='"$@"'
  setopt NO_GLOB_SUBST
else $as_nop
elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
  set -o posix
  case `(set -o) 2>/dev/null` in #(
  *posix*) :
    set -o posix ;; #(
fi
DUALCASE=1; export DUALCASE # for MKS sh

  *) :
# Support unset when possible.
if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
  as_unset=unset
else
     ;;
esac
  as_unset=false
fi


# Work around bugs in pre-3.0 UWIN ksh.
$as_unset ENV MAIL MAILPATH

# Reset variables that may have inherited troublesome values from
# the environment.

# IFS needs to be set, to space, tab, and newline, in precisely that order.
# (If _AS_PATH_WALK were called with IFS unset, it would have the
# side effect of setting IFS to empty, thus disabling word splitting.)
# Quoting is to prevent editors from complaining about space-tab.
as_nl='
'
export as_nl
IFS=" ""	$as_nl"

PS1='$ '
PS2='> '
PS4='+ '

# Ensure predictable behavior from utilities with locale-dependent output.
LC_ALL=C
export LC_ALL
LANGUAGE=C
export LANGUAGE
# NLS nuisances.
for as_var in \

# We cannot yet rely on "unset" to work, but we need these variables
# to be unset--not just set to an empty or harmless value--now, to
# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh).  This construct
# also avoids known problems related to "unset" and subshell syntax
# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
  LC_TELEPHONE LC_TIME
do
  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
    eval $as_var=C; export $as_var
do eval test \${$as_var+y} \
  else
    $as_unset $as_var
  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
  fi
done

# Ensure that fds 0, 1, and 2 are open.
if (exec 3>&0) 2>/dev/null; then :; else exec 0</dev/null; fi
if (exec 3>&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
if (exec 3>&2)            ; then :; else exec 2>/dev/null; fi
# Required to use basename.
if expr a : '\(a\)' >/dev/null 2>&1; then

# The user is always right.
if ${PATH_SEPARATOR+false} :; then
  PATH_SEPARATOR=:
  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
      PATH_SEPARATOR=';'
  }
fi


# Find who we are.  Look in the path if we contain no directory separator.
as_myself=
case $0 in #((
  *[\\/]* ) as_myself=$0 ;;
  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    test -r "$as_dir$0" && as_myself=$as_dir$0 && break
  done
IFS=$as_save_IFS

     ;;
esac
# We did not find ourselves, most probably we were run as `sh COMMAND'
# in which case we are not to be found in the path.
if test "x$as_myself" = x; then
  as_myself=$0
fi
if test ! -f "$as_myself"; then
  printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
  exit 1
fi



# as_fn_error STATUS ERROR [LINENO LOG_FD]
# ----------------------------------------
# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
# script with STATUS, using 1 if that was 0.
as_fn_error ()
{
  as_status=$1; test $as_status -eq 0 && as_status=1
  if test "$4"; then
    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
  fi
  printf "%s\n" "$as_me: error: $2" >&2
  as_fn_exit $as_status
} # as_fn_error



# as_fn_set_status STATUS
# -----------------------
# Set $? to STATUS, without forking.
as_fn_set_status ()
{
  return $1
} # as_fn_set_status

# as_fn_exit STATUS
# -----------------
# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
as_fn_exit ()
{
  set +e
  as_fn_set_status $1
  exit $1
} # as_fn_exit

# as_fn_unset VAR
# ---------------
# Portably unset VAR.
as_fn_unset ()
{
  { eval $1=; unset $1;}
}
as_unset=as_fn_unset

# as_fn_append VAR VALUE
# ----------------------
# Append the text in VALUE to the end of the definition contained in VAR. Take
# advantage of any shell optimizations that allow amortized linear growth over
# repeated appends, instead of the typical quadratic growth present in naive
# implementations.
if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
then :
  eval 'as_fn_append ()
  {
    eval $1+=\$2
  }'
else $as_nop
  as_fn_append ()
  {
    eval $1=\$$1\$2
  }
fi # as_fn_append

# as_fn_arith ARG...
# ------------------
# Perform arithmetic evaluation on the ARGs, and store the result in the
# global $as_val. Take advantage of shells that can avoid forks. The arguments
# must be portable across $(()) and expr.
if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
then :
  eval 'as_fn_arith ()
  {
    as_val=$(( $* ))
  }'
else $as_nop
  as_fn_arith ()
  {
    as_val=`expr "$@" || test $? -eq 1`
  }
fi # as_fn_arith


if expr a : '\(a\)' >/dev/null 2>&1 &&
   test "X`expr 00001 : '.*\(...\)'`" = X001; then
  as_expr=expr
else
  as_expr=false
fi

if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
  as_basename=basename
else
  as_basename=false
fi

if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
  as_dirname=dirname
else
  as_dirname=false
fi

# Name of the executable.
as_me=`$as_basename "$0" ||
as_me=`$as_basename -- "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
	 X"$0" : 'X\(//\)$' \| \
	 X"$0" : 'X\(/\)$' \| \
	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
	 .     : '\(.\)' 2>/dev/null ||
echo X/"$0" |
    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
  	  /^X\/\(\/\/\)$/{ s//\1/; q; }
  	  /^X\/\(\/\).*/{ s//\1/; q; }
  	  s/.*/./; q'`


# PATH needs CR, and LINENO needs CR and PATH.
printf "%s\n" X/"$0" |
    sed '/^.*\/\([^/][^/]*\)\/*$/{
	    s//\1/
	    q
	  }
	  /^X\/\(\/\/\)$/{
	    s//\1/
	    q
	  }
	  /^X\/\(\/\).*/{
	    s//\1/
	    q
	  }
	  s/.*/./; q'`

# Avoid depending upon Character Ranges.
as_cr_letters='abcdefghijklmnopqrstuvwxyz'
as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
as_cr_Letters=$as_cr_letters$as_cr_LETTERS
as_cr_digits='0123456789'
as_cr_alnum=$as_cr_Letters$as_cr_digits

# The user is always right.
if test "${PATH_SEPARATOR+set}" != set; then
  echo "#! /bin/sh" >conf$$.sh
  echo  "exit 0"   >>conf$$.sh
  chmod +x conf$$.sh
  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
    PATH_SEPARATOR=';'
  else
    PATH_SEPARATOR=:
  fi
  rm -f conf$$.sh
fi


# Determine whether it's possible to make 'echo' print without a newline.
  as_lineno_1=$LINENO
  as_lineno_2=$LINENO
  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
  test "x$as_lineno_1" != "x$as_lineno_2" &&
  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
  # Find who we are.  Look in the path if we contain no path at all
  # relative or not.
  case $0 in
# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
# for compatibility with existing Makefiles.
ECHO_C= ECHO_N= ECHO_T=
case `echo -n x` in #(((((
    *[\\/]* ) as_myself=$0 ;;
    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  test -z "$as_dir" && as_dir=.
  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
done

       ;;
  esac
  # We did not find ourselves, most probably we were run as `sh COMMAND'
  # in which case we are not to be found in the path.
  if test "x$as_myself" = x; then
    as_myself=$0
-n*)
  case `echo 'xy\c'` in
  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
  xy)  ECHO_C='\c';;
  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
       ECHO_T='	';;
  esac;;
*)
  ECHO_N='-n';;
esac

# For backward compatibility with old third-party macros, we provide
# the shell variables $as_echo and $as_echo_n.  New code should use
# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
as_echo='printf %s\n'
as_echo_n='printf %s'

rm -f conf$$ conf$$.exe conf$$.file
if test -d conf$$.dir; then
  rm -f conf$$.dir/conf$$.file
else
  fi
  if test ! -f "$as_myself"; then
  rm -f conf$$.dir
    { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
  mkdir conf$$.dir 2>/dev/null
   { (exit 1); exit 1; }; }
  fi
  case $CONFIG_SHELL in
  '')
    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
do
fi
if (echo >conf$$.file) 2>/dev/null; then
  if ln -s conf$$.file conf$$ 2>/dev/null; then
    as_ln_s='ln -s'
    # ... but there are two gotchas:
    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
  IFS=$as_save_IFS
  test -z "$as_dir" && as_dir=.
  for as_base in sh bash ksh sh5; do
	 case $as_dir in
    # In both cases, we have to default to `cp -pR'.
	 /*)
	   if ("$as_dir/$as_base" -c '
  as_lineno_1=$LINENO
  as_lineno_2=$LINENO
  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
  test "x$as_lineno_1" != "x$as_lineno_2" &&
  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
      as_ln_s='cp -pR'
  elif ln conf$$.file conf$$ 2>/dev/null; then
	     $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
	     $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
	     CONFIG_SHELL=$as_dir/$as_base
    as_ln_s=ln
	     export CONFIG_SHELL
	     exec "$CONFIG_SHELL" "$0" ${1+"$@"}
	   fi;;
	 esac
       done
done
;;
  esac

  else
    as_ln_s='cp -pR'
  fi
else
  as_ln_s='cp -pR'
fi
rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
rmdir conf$$.dir 2>/dev/null


# as_fn_mkdir_p
# -------------
# Create "$as_dir" as a directory, including parents if necessary.
as_fn_mkdir_p ()
{
  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
  # uniformly replaced by the line number.  The first 'sed' inserts a
  # line-number line before each line; the second 'sed' does the real
  # work.  The second script uses 'N' to pair each line-number line
  # with the numbered line, and appends trailing '-' during
  # substitution so that $LINENO is not a special case at line end.
  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
  sed '=' <$as_myself |
    sed '
      N
      s,$,-,

  case $as_dir in #(
  -*) as_dir=./$as_dir;;
  esac
      : loop
      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
      t loop
      s,-$,,
      s,^['$as_cr_digits']*\n,,
    ' >$as_me.lineno &&
  chmod +x $as_me.lineno ||
  test -d "$as_dir" || eval $as_mkdir_p || {
    as_dirs=
    while :; do
      case $as_dir in #(
    { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5
echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;}
   { (exit 1); exit 1; }; }

      *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
  # Don't try to exec as it changes $[0], causing all sort of problems
  # (the dirname of $[0] is not the place where we might find the
  # original and so on.  Autoconf is especially sensible to this).
  . ./$as_me.lineno
      *) as_qdir=$as_dir;;
  # Exit status is that of the last command.
  exit
      esac
}


      as_dirs="'$as_qdir' $as_dirs"
      as_dir=`$as_dirname -- "$as_dir" ||
$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
	 X"$as_dir" : 'X\(//\)[^/]' \| \
	 X"$as_dir" : 'X\(//\)$' \| \
	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
printf "%s\n" X"$as_dir" |
    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
	    s//\1/
	    q
case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
  *c*,-n*) ECHO_N= ECHO_C='
	  }
	  /^X\(\/\/\)[^/].*/{
' ECHO_T='	' ;;
  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
esac

	    s//\1/
	    q
if expr a : '\(a\)' >/dev/null 2>&1; then
  as_expr=expr
else
	  }
	  /^X\(\/\/\)$/{
	    s//\1/
	    q
	  }
	  /^X\(\/\).*/{
	    s//\1/
  as_expr=false
fi

rm -f conf$$ conf$$.exe conf$$.file
	    q
	  }
	  s/.*/./; q'`
echo >conf$$.file
if ln -s conf$$.file conf$$ 2>/dev/null; then
  # We could just check for DJGPP; but this test a) works b) is more generic
  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
  if test -f conf$$.exe; then
      test -d "$as_dir" && break
    # Don't use ln at all; we don't have any links
    as_ln_s='cp -p'
  else
    as_ln_s='ln -s'
  fi
elif ln conf$$.file conf$$ 2>/dev/null; then
  as_ln_s=ln
    done
else
  as_ln_s='cp -p'
fi
    test -z "$as_dirs" || eval "mkdir $as_dirs"
  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"

rm -f conf$$ conf$$.exe conf$$.file

} # as_fn_mkdir_p
if mkdir -p . 2>/dev/null; then
  as_mkdir_p=:
  as_mkdir_p='mkdir -p "$as_dir"'
else
  test -d ./-p && rmdir ./-p
  as_mkdir_p=false
fi


# as_fn_executable_p FILE
# -----------------------
# Test if FILE is an executable regular file.
as_fn_executable_p ()
{
  test -f "$1" && test -x "$1"
} # as_fn_executable_p
as_test_x='test -x'
as_executable_p="test -f"
as_executable_p=as_fn_executable_p

# Sed expression to map a string onto a valid CPP name.
as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"

# Sed expression to map a string onto a valid variable name.
as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"


# IFS
# We need space, tab and new line, in precisely that order.
as_nl='
exec 6>&1
## ----------------------------------- ##
## Main body of $CONFIG_STATUS script. ##
'
IFS=" 	$as_nl"

# CDPATH.
$as_unset CDPATH
## ----------------------------------- ##
_ASEOF
test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1

exec 6>&1

# Open the log real soon, to keep \$[0] and so on meaningful, and to
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# Save the log message, to keep $0 and so on meaningful, and to
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.  Logging --version etc. is OK.
# values after options handling.
exec 5>>config.log
{
  echo
  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
## Running $as_me. ##
_ASBOX
} >&5
cat >&5 <<_CSEOF

ac_log="
This file was extended by $as_me, which was
generated by GNU Autoconf 2.59.  Invocation command line was
generated by GNU Autoconf 2.70.  Invocation command line was

  CONFIG_FILES    = $CONFIG_FILES
  CONFIG_HEADERS  = $CONFIG_HEADERS
  CONFIG_LINKS    = $CONFIG_LINKS
  CONFIG_COMMANDS = $CONFIG_COMMANDS
  $ $0 $@

_CSEOF
echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5
echo >&5
on `(hostname || uname -n) 2>/dev/null | sed 1q`
"

_ACEOF

# Files that config.status was made for.
if test -n "$ac_config_files"; then
  echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS
case $ac_config_files in *"
"*) set x $ac_config_files; shift; ac_config_files=$*;;
fi
esac

if test -n "$ac_config_headers"; then
  echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS
fi

if test -n "$ac_config_links"; then
  echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS
fi

if test -n "$ac_config_commands"; then
  echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS
fi
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
# Files that config.status was made for.
config_files="$ac_config_files"

cat >>$CONFIG_STATUS <<\_ACEOF
_ACEOF

cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
ac_cs_usage="\
\`$as_me' instantiates files from templates according to the
current configuration.
\`$as_me' instantiates files and other configuration actions
from templates according to the current configuration.  Unless the files
and actions are specified as TAGs, all are instantiated by default.

Usage: $0 [OPTIONS] [FILE]...
Usage: $0 [OPTION]... [TAG]...

  -h, --help       print this help, then exit
  -V, --version    print version number, then exit
  -q, --quiet      do not print progress messages
  -V, --version    print version number and configuration settings, then exit
      --config     print configuration, then exit
  -q, --quiet, --silent
                   do not print progress messages
  -d, --debug      don't remove temporary files
      --recheck    update $as_me by reconfiguring in the same conditions
  --file=FILE[:TEMPLATE]
		   instantiate the configuration file FILE
      --file=FILE[:TEMPLATE]
                   instantiate the configuration file FILE

Configuration files:
$config_files

Report bugs to <bug-auto[email protected]>."
Report bugs to the package provider."

_ACEOF

cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_config=`printf "%s\n" "$ac_configure_args" | sed "$ac_safe_unquote"`
ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"`
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config='$ac_cs_config_escaped'
ac_cs_version="\\
config.status
configured by $0, generated by GNU Autoconf 2.59,
  with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
configured by $0, generated by GNU Autoconf 2.70,
  with options \\"\$ac_cs_config\\"

Copyright (C) 2003 Free Software Foundation, Inc.
Copyright (C) 2020 Free Software Foundation, Inc.
This config.status script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it."

ac_pwd='$ac_pwd'
srcdir=$srcdir
srcdir='$srcdir'
test -n "\$AWK" || AWK=awk
_ACEOF

cat >>$CONFIG_STATUS <<\_ACEOF
# If no file are specified by the user, then we need to provide default
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# The default lists apply if the user does not specify any file.
# value.  By we need to know if files were specified by the user.
ac_need_defaults=:
while test $# != 0
do
  case $1 in
  --*=?*)
    ac_option=`expr "X$1" : 'X\([^=]*\)='`
    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
    ac_shift=:
    ;;
  --*=*)
    ac_option=`expr "x$1" : 'x\([^=]*\)='`
    ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
  --*=)
    ac_option=`expr "X$1" : 'X\([^=]*\)='`
    ac_optarg=
    ac_shift=:
    ;;
  -*)
  *)
    ac_option=$1
    ac_optarg=$2
    ac_shift=shift
    ;;
  *) # This is not an option, so the user has probably given explicit
     # arguments.
     ac_option=$1
     ac_need_defaults=false;;
  esac

  case $ac_option in
  # Handling of the options.
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF
  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
    ac_cs_recheck=: ;;
  --version | --vers* | -V )
    echo "$ac_cs_version"; exit 0 ;;
  --he | --h)
  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
    printf "%s\n" "$ac_cs_version"; exit ;;
  --config | --confi | --conf | --con | --co | --c )
    # Conflict between --help and --header
    { { echo "$as_me:$LINENO: error: ambiguous option: $1
Try \`$0 --help' for more information." >&5
echo "$as_me: error: ambiguous option: $1
Try \`$0 --help' for more information." >&2;}
   { (exit 1); exit 1; }; };;
  --help | --hel | -h )
    echo "$ac_cs_usage"; exit 0 ;;
  --debug | --d* | -d )
    printf "%s\n" "$ac_cs_config"; exit ;;
  --debug | --debu | --deb | --de | --d | -d )
    debug=: ;;
  --file | --fil | --fi | --f )
    $ac_shift
    CONFIG_FILES="$CONFIG_FILES $ac_optarg"
    case $ac_optarg in
    ac_need_defaults=false;;
  --header | --heade | --head | --hea )
    $ac_shift
    CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
    *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
    '') as_fn_error $? "missing file argument" ;;
    esac
    as_fn_append CONFIG_FILES " '$ac_optarg'"
    ac_need_defaults=false;;
  --he | --h |  --help | --hel | -h )
    printf "%s\n" "$ac_cs_usage"; exit ;;
  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
  | -silent | --silent | --silen | --sile | --sil | --si | --s)
    ac_cs_silent=: ;;

  # This is an error.
  -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1
Try \`$0 --help' for more information." >&5
echo "$as_me: error: unrecognized option: $1
Try \`$0 --help' for more information." >&2;}
  -*) as_fn_error $? "unrecognized option: \`$1'
Try \`$0 --help' for more information." ;;
   { (exit 1); exit 1; }; } ;;

  *) ac_config_targets="$ac_config_targets $1" ;;
  *) as_fn_append ac_config_targets " $1"
     ac_need_defaults=false ;;

  esac
  shift
done

ac_configure_extra_args=

if $ac_cs_silent; then
  exec 6>/dev/null
  ac_configure_extra_args="$ac_configure_extra_args --silent"
fi

_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
if \$ac_cs_recheck; then
  echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
  exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
  set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
  shift
  \printf "%s\n" "running CONFIG_SHELL=$SHELL \$*" >&6
  CONFIG_SHELL='$SHELL'
  export CONFIG_SHELL
  exec "\$@"
fi

_ACEOF



cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
exec 5>>config.log
{
  echo
  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
## Running $as_me. ##
_ASBOX
  printf "%s\n" "$ac_log"
} >&5

_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
_ACEOF

cat >>$CONFIG_STATUS <<\_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1

# Handling of arguments.
for ac_config_target in $ac_config_targets
do
  case "$ac_config_target" in
  case $ac_config_target in
  # Handling of arguments.
  "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;;
  "tkConfig.sh" ) CONFIG_FILES="$CONFIG_FILES tkConfig.sh" ;;
  "wish.exe.manifest" ) CONFIG_FILES="$CONFIG_FILES wish.exe.manifest" ;;
  *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
    "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
    "tkConfig.sh") CONFIG_FILES="$CONFIG_FILES tkConfig.sh" ;;
    "wish.exe.manifest") CONFIG_FILES="$CONFIG_FILES wish.exe.manifest" ;;

  *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
   { (exit 1); exit 1; }; };;
  esac
done


# If the user did not use the arguments to specify the items to instantiate,
# then the envvar interface is used.  Set only those that are not.
# We use the long form for the default assignment because of an extremely
# bizarre bug on SunOS 4.1.3.
if $ac_need_defaults; then
  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
  test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files
fi

# Have a temporary directory for convenience.  Make it in the build tree
# simply because there is no reason to put it here, and in addition,
# simply because there is no reason against having it here, and in addition,
# creating and moving files from /tmp can sometimes cause problems.
# Create a temporary directory, and hook for its removal unless debugging.
# Hook for its removal unless debugging.
# Note that there is a small window in which the directory will not be cleaned:
# after its creation but before its name has been assigned to `$tmp'.
$debug ||
{
  tmp= ac_tmp=
  trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
  trap '{ (exit 1); exit 1; }' 1 2 13 15
  trap 'exit_status=$?
  : "${ac_tmp:=$tmp}"
  { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
' 0
  trap 'as_fn_exit 1' 1 2 13 15
}

# Create a (secure) tmp directory for tmp files.

{
  tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` &&
  test -n "$tmp" && test -d "$tmp"
  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
  test -d "$tmp"
}  ||
{
  tmp=./confstat$$-$RANDOM
  (umask 077 && mkdir $tmp)
  tmp=./conf$$-$RANDOM
  (umask 077 && mkdir "$tmp")
} ||
{
   echo "$me: cannot create a temporary directory in ." >&2
} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
   { (exit 1); exit 1; }
}

ac_tmp=$tmp

# Set up the scripts for CONFIG_FILES section.
_ACEOF

cat >>$CONFIG_STATUS <<_ACEOF
# No need to generate them if there are no CONFIG_FILES.
# This happens for instance with `./config.status config.h'.
if test -n "$CONFIG_FILES"; then

#
# CONFIG_FILES section.
#

ac_cr=`echo X | tr X '\015'`
# On cygwin, bash can eat \r inside `` if the user requested igncr.
# But we know of no other shell where ac_cr would be empty at this
# point, so we can use a bashism as a fallback.
if test "x$ac_cr" = x; then
  eval ac_cr=\$\'\\r\'
fi
ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
  ac_cs_awk_cr='\\r'
else
  ac_cs_awk_cr=$ac_cr
fi

echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
_ACEOF

# No need to generate the scripts if there are no CONFIG_FILES.

# This happens for instance when ./config.status config.h
if test -n "\$CONFIG_FILES"; then
  # Protect against being on the right side of a sed subst in config.status.
  sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g;
   s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF
{
  echo "cat >conf$$subs.awk <<_ACEOF" &&
  echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
  echo "_ACEOF"
} >conf$$subs.sh ||
s,@SHELL@,$SHELL,;t t
s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t
s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t
s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t
s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t
s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t
s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t
s,@exec_prefix@,$exec_prefix,;t t
s,@prefix@,$prefix,;t t
s,@program_transform_name@,$program_transform_name,;t t
s,@bindir@,$bindir,;t t
s,@sbindir@,$sbindir,;t t
s,@libexecdir@,$libexecdir,;t t
s,@datadir@,$datadir,;t t
  as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
ac_delim='%!_!# '
for ac_last_try in false false false false false :; do
  . ./conf$$subs.sh ||
    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5

  ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
  if test $ac_delim_n = $ac_delim_num; then
    break
  elif $ac_last_try; then
    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
s,@sysconfdir@,$sysconfdir,;t t
s,@sharedstatedir@,$sharedstatedir,;t t
s,@localstatedir@,$localstatedir,;t t
s,@libdir@,$libdir,;t t
s,@includedir@,$includedir,;t t
s,@oldincludedir@,$oldincludedir,;t t
s,@infodir@,$infodir,;t t
s,@mandir@,$mandir,;t t
s,@build_alias@,$build_alias,;t t
  else
    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
  fi
done
rm -f conf$$subs.sh

cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
_ACEOF
s,@host_alias@,$host_alias,;t t
s,@target_alias@,$target_alias,;t t
s,@DEFS@,$DEFS,;t t
s,@ECHO_C@,$ECHO_C,;t t
s,@ECHO_N@,$ECHO_N,;t t
s,@ECHO_T@,$ECHO_T,;t t
sed -n '
s,@LIBS@,$LIBS,;t t
s,@CC@,$CC,;t t
s,@CFLAGS@,$CFLAGS,;t t
h
s/^/S["/; s/!.*/"]=/
p
g
s/^[^!]*!//
:repl
t repl
s,@LDFLAGS@,$LDFLAGS,;t t
s,@CPPFLAGS@,$CPPFLAGS,;t t
s,@ac_ct_CC@,$ac_ct_CC,;t t
s/'"$ac_delim"'$//
s,@EXEEXT@,$EXEEXT,;t t
s,@OBJEXT@,$OBJEXT,;t t
s,@CPP@,$CPP,;t t
s,@EGREP@,$EGREP,;t t
s,@AR@,$AR,;t t
s,@ac_ct_AR@,$ac_ct_AR,;t t
s,@RANLIB@,$RANLIB,;t t
s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t
s,@RC@,$RC,;t t
t delim
:nl
h
s/\(.\{148\}\)..*/\1/
t more1
s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
p
n
b repl
s,@ac_ct_RC@,$ac_ct_RC,;t t
s,@SET_MAKE@,$SET_MAKE,;t t
s,@TCL_THREADS@,$TCL_THREADS,;t t
s,@TCL_VERSION@,$TCL_VERSION,;t t
:more1
s/["\\]/\\&/g; s/^/"/; s/$/"\\/
s,@TCL_BIN_DIR@,$TCL_BIN_DIR,;t t
s,@TCL_SRC_DIR@,$TCL_SRC_DIR,;t t
s,@TCL_LIB_FILE@,$TCL_LIB_FILE,;t t
s,@TCL_LIB_FLAG@,$TCL_LIB_FLAG,;t t
s,@TCL_LIB_SPEC@,$TCL_LIB_SPEC,;t t
p
g
s/.\{148\}//
t nl
:delim
h
s/\(.\{148\}\)..*/\1/
t more2
s,@TCL_STUB_LIB_FILE@,$TCL_STUB_LIB_FILE,;t t
s,@TCL_STUB_LIB_FLAG@,$TCL_STUB_LIB_FLAG,;t t
s/["\\]/\\&/g; s/^/"/; s/$/"/
p
s,@TCL_STUB_LIB_SPEC@,$TCL_STUB_LIB_SPEC,;t t
s,@TCL_DEFS@,$TCL_DEFS,;t t
s,@CYGPATH@,$CYGPATH,;t t
b
:more2
s/["\\]/\\&/g; s/^/"/; s/$/"\\/
s,@CELIB_DIR@,$CELIB_DIR,;t t
s,@DL_LIBS@,$DL_LIBS,;t t
s,@CFLAGS_DEBUG@,$CFLAGS_DEBUG,;t t
s,@CFLAGS_OPTIMIZE@,$CFLAGS_OPTIMIZE,;t t
s,@CFLAGS_WARNING@,$CFLAGS_WARNING,;t t
p
g
s/.\{148\}//
t delim
' <conf$$subs.awk | sed '
s,@MAN2TCLFLAGS@,$MAN2TCLFLAGS,;t t
s,@CFLAGS_DEFAULT@,$CFLAGS_DEFAULT,;t t
s,@LDFLAGS_DEFAULT@,$LDFLAGS_DEFAULT,;t t
/^[^""]/{
  N
  s/\n//
s,@VC_MANIFEST_EMBED_DLL@,$VC_MANIFEST_EMBED_DLL,;t t
s,@VC_MANIFEST_EMBED_EXE@,$VC_MANIFEST_EMBED_EXE,;t t
s,@BUILD_TCLSH@,$BUILD_TCLSH,;t t
s,@TCLSH_PROG@,$TCLSH_PROG,;t t
}
' >>$CONFIG_STATUS || ac_write_fail=1
rm -f conf$$subs.awk
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
s,@TK_WIN_VERSION@,$TK_WIN_VERSION,;t t
s,@MACHINE@,$MACHINE,;t t
s,@TK_VERSION@,$TK_VERSION,;t t
s,@TK_MAJOR_VERSION@,$TK_MAJOR_VERSION,;t t
s,@TK_MINOR_VERSION@,$TK_MINOR_VERSION,;t t
_ACAWK
cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
  for (key in S) S_is_set[key] = 1
  FS = ""

s,@TK_PATCH_LEVEL@,$TK_PATCH_LEVEL,;t t
s,@TK_DBGX@,$TK_DBGX,;t t
s,@TK_LIB_FILE@,$TK_LIB_FILE,;t t
s,@TK_DLL_FILE@,$TK_DLL_FILE,;t t
s,@TK_STUB_LIB_FILE@,$TK_STUB_LIB_FILE,;t t
s,@TK_STUB_LIB_FLAG@,$TK_STUB_LIB_FLAG,;t t
s,@TK_BUILD_STUB_LIB_SPEC@,$TK_BUILD_STUB_LIB_SPEC,;t t
s,@TK_SRC_DIR@,$TK_SRC_DIR,;t t
s,@TK_BIN_DIR@,$TK_BIN_DIR,;t t
s,@TCL_MAJOR_VERSION@,$TCL_MAJOR_VERSION,;t t
s,@TCL_MINOR_VERSION@,$TCL_MINOR_VERSION,;t t
s,@TCL_PATCH_LEVEL@,$TCL_PATCH_LEVEL,;t t
s,@TCL_DBGX@,$TCL_DBGX,;t t
s,@CFG_TK_SHARED_LIB_SUFFIX@,$CFG_TK_SHARED_LIB_SUFFIX,;t t
s,@CFG_TK_UNSHARED_LIB_SUFFIX@,$CFG_TK_UNSHARED_LIB_SUFFIX,;t t
}
{
  line = $ 0
  nfields = split(line, field, "@")
  substed = 0
  len = length(field[1])
  for (i = 2; i < nfields; i++) {
    key = field[i]
    keylen = length(key)
    if (S_is_set[key]) {
      value = S[key]
      line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
      len += length(value) + length(field[++i])
      substed = 1
    } else
      len += 1 + keylen
  }

s,@CFG_TK_EXPORT_FILE_SUFFIX@,$CFG_TK_EXPORT_FILE_SUFFIX,;t t
s,@EXTRA_CFLAGS@,$EXTRA_CFLAGS,;t t
s,@DEPARG@,$DEPARG,;t t
s,@CC_OBJNAME@,$CC_OBJNAME,;t t
s,@CC_EXENAME@,$CC_EXENAME,;t t
s,@LDFLAGS_DEBUG@,$LDFLAGS_DEBUG,;t t
s,@LDFLAGS_OPTIMIZE@,$LDFLAGS_OPTIMIZE,;t t
s,@LDFLAGS_CONSOLE@,$LDFLAGS_CONSOLE,;t t
s,@LDFLAGS_WINDOW@,$LDFLAGS_WINDOW,;t t
s,@TK_RES@,$TK_RES,;t t
  print line
}

_ACAWK
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
  sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
else
s,@STLIB_LD@,$STLIB_LD,;t t
s,@SHLIB_LD@,$SHLIB_LD,;t t
s,@SHLIB_LD_LIBS@,$SHLIB_LD_LIBS,;t t
s,@SHLIB_CFLAGS@,$SHLIB_CFLAGS,;t t
s,@SHLIB_SUFFIX@,$SHLIB_SUFFIX,;t t
s,@TK_SHARED_BUILD@,$TK_SHARED_BUILD,;t t
s,@LIBS_GUI@,$LIBS_GUI,;t t
s,@DLLSUFFIX@,$DLLSUFFIX,;t t
s,@LIBPREFIX@,$LIBPREFIX,;t t
s,@LIBSUFFIX@,$LIBSUFFIX,;t t
s,@EXESUFFIX@,$EXESUFFIX,;t t
s,@LIBRARIES@,$LIBRARIES,;t t
s,@MAKE_LIB@,$MAKE_LIB,;t t
s,@MAKE_STUB_LIB@,$MAKE_STUB_LIB,;t t
s,@POST_MAKE_LIB@,$POST_MAKE_LIB,;t t
s,@MAKE_DLL@,$MAKE_DLL,;t t
s,@MAKE_EXE@,$MAKE_EXE,;t t
  cat
fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
  || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
_ACEOF

# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
# trailing colons and then remove the whole line if VPATH becomes empty
# (actually we leave an empty line to preserve line numbers).
if test "x$srcdir" = x.; then
  ac_vpsub='/^[	 ]*VPATH[	 ]*=[	 ]*/{
h
s///
s/^/:/
s/[	 ]*$/:/
s/:\$(srcdir):/:/g
s/:\${srcdir}:/:/g
s/:@srcdir@:/:/g
s/^:*//
s/:*$//
s,@TK_LIB_FLAG@,$TK_LIB_FLAG,;t t
s,@TK_LIB_SPEC@,$TK_LIB_SPEC,;t t
x
s/\(=[	 ]*\).*/\1/
s,@TK_BUILD_LIB_SPEC@,$TK_BUILD_LIB_SPEC,;t t
s,@TK_STUB_LIB_SPEC@,$TK_STUB_LIB_SPEC,;t t
s,@TK_STUB_LIB_PATH@,$TK_STUB_LIB_PATH,;t t
s,@TK_BUILD_STUB_LIB_PATH@,$TK_BUILD_STUB_LIB_PATH,;t t
G
s/\n//
s/^[^=]*=[	 ]*$//
}'
fi

s,@TK_CC_SEARCH_FLAGS@,$TK_CC_SEARCH_FLAGS,;t t
s,@TK_LD_SEARCH_FLAGS@,$TK_LD_SEARCH_FLAGS,;t t
s,@RC_OUT@,$RC_OUT,;t t
s,@RC_TYPE@,$RC_TYPE,;t t
s,@RC_INCLUDE@,$RC_INCLUDE,;t t
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
fi # test -n "$CONFIG_FILES"

s,@RC_DEFINE@,$RC_DEFINE,;t t
s,@RC_DEFINES@,$RC_DEFINES,;t t
s,@RES@,$RES,;t t
s,@LIBOBJS@,$LIBOBJS,;t t
s,@LTLIBOBJS@,$LTLIBOBJS,;t t
CEOF

eval set X "  :F $CONFIG_FILES      "
shift
_ACEOF

for ac_tag
do
  case $ac_tag in
  :[FHLC]) ac_mode=$ac_tag; continue;;
  esac
  case $ac_mode$ac_tag in
  :[FHL]*:*);;
  :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
  :[FH]-) ac_tag=-:-;;
  cat >>$CONFIG_STATUS <<\_ACEOF
  # Split the substitutions into bite-sized pieces for seds with
  # small command number limits, like on Digital OSF/1 and HP-UX.
  ac_max_sed_lines=48
  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
  ac_sed_frag=1 # Number of current file.
  ac_beg=1 # First line for current file.
  ac_end=$ac_max_sed_lines # Line after last line for current file.
  ac_more_lines=:
  ac_sed_cmds=
  while $ac_more_lines; do
    if test $ac_beg -gt 1; then
  esac
  ac_save_IFS=$IFS
  IFS=:
  set x $ac_tag
  IFS=$ac_save_IFS
      sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
    else
      sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
    fi
    if test ! -s $tmp/subs.frag; then
      ac_more_lines=false
  shift
  ac_file=$1
  shift

  case $ac_mode in
    else
      # The purpose of the label and of the branching condition is to
      # speed up the sed processing (if there are no `@' at all, there
      # is no need to browse any of the substitutions).
      # These are the two extra sed commands mentioned above.
      (echo ':t
  /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed
      if test -z "$ac_sed_cmds"; then
  :L) ac_source=$1;;
	ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
      else
	ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
      fi
  :[FH])
    ac_file_inputs=
      ac_sed_frag=`expr $ac_sed_frag + 1`
      ac_beg=$ac_end
    for ac_f
      ac_end=`expr $ac_end + $ac_max_sed_lines`
    fi
  done
  if test -z "$ac_sed_cmds"; then
    ac_sed_cmds=cat
  fi
fi # test -n "$CONFIG_FILES"
    do
      case $ac_f in
      -) ac_f="$ac_tmp/stdin";;
      *) # Look for the file first in the build tree, then in the source tree
	 # (if the path is not absolute).  The absolute path cannot be DOS-style,
	 # because $ac_f cannot contain `:'.
	 test -f "$ac_f" ||
	   case $ac_f in
	   [\\/$]*) false;;
	   *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
	   esac ||
	   as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
      esac
      case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
      as_fn_append ac_file_inputs " '$ac_f'"
    done

_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF
for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue
  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
  case $ac_file in
    # Let's still pretend it is `configure' which instantiates (i.e., don't
    # use $as_me), people would be surprised to read:
    #    /* config.h.  Generated by config.status.  */
    configure_input='Generated from '`
	  printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
	`' by configure.'
    if test x"$ac_file" != x-; then
      configure_input="$ac_file.  $configure_input"
      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
printf "%s\n" "$as_me: creating $ac_file" >&6;}
    fi
    # Neutralize special characters interpreted by sed in replacement strings.
    case $configure_input in #(
    *\&* | *\|* | *\\* )
       ac_sed_conf_input=`printf "%s\n" "$configure_input" |
       sed 's/[\\\\&|]/\\\\&/g'`;; #(
    *) ac_sed_conf_input=$configure_input;;
    esac

    case $ac_tag in
  - | *:- | *:-:* ) # input from stdin
	cat >$tmp/stdin
	ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
    *:-:* | *:-) cat >"$ac_tmp/stdin" \
      || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
	ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
  *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
	ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
  * )   ac_file_in=$ac_file.in ;;
    esac
    ;;
  esac

  # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories.
  ac_dir=`(dirname "$ac_file") 2>/dev/null ||
  ac_dir=`$as_dirname -- "$ac_file" ||
$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
	 X"$ac_file" : 'X\(//\)[^/]' \| \
	 X"$ac_file" : 'X\(//\)$' \| \
	 X"$ac_file" : 'X\(/\)' \| \
	 X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
	 .     : '\(.\)' 2>/dev/null ||
echo X"$ac_file" |
    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
  	  /^X\(\/\/\)$/{ s//\1/; q; }
  	  /^X\(\/\).*/{ s//\1/; q; }
printf "%s\n" X"$ac_file" |
    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
	    s//\1/
	    q
	  }
	  /^X\(\/\/\)[^/].*/{
	    s//\1/
  	  s/.*/./; q'`
  { if $as_mkdir_p; then
    mkdir -p "$ac_dir"
  else
    as_dir="$ac_dir"
    as_dirs=
    while test ! -d "$as_dir"; do
      as_dirs="$as_dir $as_dirs"
      as_dir=`(dirname "$as_dir") 2>/dev/null ||
$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
	 X"$as_dir" : 'X\(//\)[^/]' \| \
	 X"$as_dir" : 'X\(//\)$' \| \
	 X"$as_dir" : 'X\(/\)' \| \
	 .     : '\(.\)' 2>/dev/null ||
echo X"$as_dir" |
    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
  	  /^X\(\/\/\)$/{ s//\1/; q; }
  	  /^X\(\/\).*/{ s//\1/; q; }
  	  s/.*/./; q'`
	    q
	  }
	  /^X\(\/\/\)$/{
	    s//\1/
	    q
	  }
	  /^X\(\/\).*/{
	    s//\1/
	    q
	  }
	  s/.*/./; q'`
    done
    test ! -n "$as_dirs" || mkdir $as_dirs
  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
   { (exit 1); exit 1; }; }; }

  as_dir="$ac_dir"; as_fn_mkdir_p
  ac_builddir=.

if test "$ac_dir" != .; then
  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
  # A "../" for each directory in $ac_dir_suffix.
  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
else
  ac_dir_suffix= ac_top_builddir=
fi
case "$ac_dir" in
.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
*)
  ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
  # A ".." for each directory in $ac_dir_suffix.
  ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
  case $ac_top_builddir_sub in
  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
  esac ;;
esac
ac_abs_top_builddir=$ac_pwd
ac_abs_builddir=$ac_pwd$ac_dir_suffix
# for backward compatibility:
ac_top_builddir=$ac_top_build_prefix

case $srcdir in
  .)  # No --srcdir option.  We are building in place.
  .)  # We are building in place.
    ac_srcdir=.
    if test -z "$ac_top_builddir"; then
       ac_top_srcdir=.
    ac_top_srcdir=$ac_top_builddir_sub
    else
       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
    ac_abs_top_srcdir=$ac_pwd ;;
    fi ;;
  [\\/]* | ?:[\\/]* )  # Absolute path.
  [\\/]* | ?:[\\/]* )  # Absolute name.
    ac_srcdir=$srcdir$ac_dir_suffix;
    ac_top_srcdir=$srcdir ;;
  *) # Relative path.
    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
    ac_top_srcdir=$ac_top_builddir$srcdir ;;
    ac_top_srcdir=$srcdir
    ac_abs_top_srcdir=$srcdir ;;
  *) # Relative name.
    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
    ac_top_srcdir=$ac_top_build_prefix$srcdir
esac

# Do not use `cd foo && pwd` to compute absolute paths, because
# the directories may not exist.
case `pwd` in
.) ac_abs_builddir="$ac_dir";;
*)
  case "$ac_dir" in
  .) ac_abs_builddir=`pwd`;;
  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
  *) ac_abs_builddir=`pwd`/"$ac_dir";;
  esac;;
esac
case $ac_abs_builddir in
.) ac_abs_top_builddir=${ac_top_builddir}.;;
*)
  case ${ac_top_builddir}. in
  .) ac_abs_top_builddir=$ac_abs_builddir;;
  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
  esac;;
esac
case $ac_abs_builddir in
.) ac_abs_srcdir=$ac_srcdir;;
*)
  case $ac_srcdir in
  .) ac_abs_srcdir=$ac_abs_builddir;;
  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
  esac;;
esac
case $ac_abs_builddir in
.) ac_abs_top_srcdir=$ac_top_srcdir;;
    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
*)
  case $ac_top_srcdir in
  .) ac_abs_top_srcdir=$ac_abs_builddir;;
  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
  esac;;
esac

ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix


  if test x"$ac_file" != x-; then
    { echo "$as_me:$LINENO: creating $ac_file" >&5
echo "$as_me: creating $ac_file" >&6;}
    rm -f "$ac_file"
  fi
  # Let's still pretend it is `configure' which instantiates (i.e., don't
  # use $as_me), people would be surprised to read:
  #    /* config.h.  Generated by config.status.  */
  if test x"$ac_file" = x-; then
    configure_input=
  else
    configure_input="$ac_file.  "
  fi
  configure_input=$configure_input"Generated from `echo $ac_file_in |
				     sed 's,.*/,,'` by configure."

  # First look for the input files in the build tree, otherwise in the
  # src tree.
  ac_file_inputs=`IFS=:
    for f in $ac_file_in; do
      case $f in
  case $ac_mode in
      -) echo $tmp/stdin ;;
      [\\/$]*)
	 # Absolute (can't be DOS-style, as IFS=:)
	 test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
echo "$as_me: error: cannot find input file: $f" >&2;}
  :F)
  #
  # CONFIG_FILE
  #

_ACEOF

   { (exit 1); exit 1; }; }
	 echo "$f";;
      *) # Relative
	 if test -f "$f"; then
	   # Build tree
	   echo "$f"
	 elif test -f "$srcdir/$f"; then
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# If the template does not know about datarootdir, expand it.
# FIXME: This hack should be removed a few years after 2.60.
ac_datarootdir_hack=; ac_datarootdir_seen=
ac_sed_dataroot='
/datarootdir/ {
	   # Source tree
	   echo "$srcdir/$f"
	 else
  p
  q
}
/@datadir@/p
/@docdir@/p
/@infodir@/p
/@localedir@/p
	   # /dev/null tree
	   { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
echo "$as_me: error: cannot find input file: $f" >&2;}
/@mandir@/p'
case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
*datarootdir*) ac_datarootdir_seen=yes;;
*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
printf "%s\n" "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
   { (exit 1); exit 1; }; }
	 fi;;
      esac
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
  ac_datarootdir_hack='
  s&@datadir@&$datadir&g
  s&@docdir@&$docdir&g
  s&@infodir@&$infodir&g
  s&@localedir@&$localedir&g
  s&@mandir@&$mandir&g
  s&\\\${datarootdir}&$datarootdir&g' ;;
esac
    done` || { (exit 1); exit 1; }
_ACEOF

# Neutralize VPATH when `$srcdir' = `.'.
# Shell code in configure.ac might set extrasub.
# FIXME: do we really want to maintain this feature?
cat >>$CONFIG_STATUS <<_ACEOF
  sed "$ac_vpsub
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_sed_extra="$ac_vpsub
$extrasub
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
:t
/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
s,@configure_input@,$configure_input,;t t
s,@srcdir@,$ac_srcdir,;t t
s,@abs_srcdir@,$ac_abs_srcdir,;t t
s,@top_srcdir@,$ac_top_srcdir,;t t
s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t
s,@builddir@,$ac_builddir,;t t
s,@abs_builddir@,$ac_abs_builddir,;t t
s,@top_builddir@,$ac_top_builddir,;t t
s,@abs_top_builddir@,$ac_abs_top_builddir,;t t
" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out
  rm -f $tmp/stdin
  if test x"$ac_file" != x-; then
    mv $tmp/out $ac_file
  else
    cat $tmp/out
    rm -f $tmp/out
  fi
s|@configure_input@|$ac_sed_conf_input|;t t
s&@top_builddir@&$ac_top_builddir_sub&;t t
s&@top_build_prefix@&$ac_top_build_prefix&;t t
s&@srcdir@&$ac_srcdir&;t t
s&@abs_srcdir@&$ac_abs_srcdir&;t t
s&@top_srcdir@&$ac_top_srcdir&;t t
s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
s&@builddir@&$ac_builddir&;t t
s&@abs_builddir@&$ac_abs_builddir&;t t
s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
$ac_datarootdir_hack
"
eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
  >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5

test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
  { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' \
      "$ac_tmp/out"`; test -z "$ac_out"; } &&
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
which seems to be undefined.  Please make sure it is defined" >&5
printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
which seems to be undefined.  Please make sure it is defined" >&2;}

  rm -f "$ac_tmp/stdin"
  case $ac_file in
  -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
  *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
  esac \
  || as_fn_error $? "could not create $ac_file" "$LINENO" 5
 ;;



  esac

done
done # for ac_tag
_ACEOF

cat >>$CONFIG_STATUS <<\_ACEOF

{ (exit 0); exit 0; }
as_fn_exit 0
_ACEOF
chmod +x $CONFIG_STATUS
ac_clean_files=$ac_clean_files_save

test $ac_write_fail = 0 ||
  as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5


# configure is writing to config.log, and then calls config.status.
# config.status does its own redirection, appending to config.log.
# Unfortunately, on DOS this fails, as config.log is still kept open
# by configure, so config.status won't be able to write to it; its
# output is simply discarded.  So we exec the FD to /dev/null,
# effectively closing config.log, so it can be properly (re)opened and
# appended to by config.status.  When coming back to configure, we
# need to make the FD available again.
if test "$no_create" != yes; then
  ac_cs_success=:
  ac_config_status_args=
  test "$silent" = yes &&
    ac_config_status_args="$ac_config_status_args --quiet"
  exec 5>/dev/null
  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
  exec 5>>config.log
  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
  # would make configure fail if this is the last instruction.
  $ac_cs_success || { (exit 1); exit 1; }
  $ac_cs_success || as_fn_exit 1
fi
if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
fi



Added win/configure.ac.



















































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
#! /bin/bash -norc
# This file is an input file used by the GNU "autoconf" program to
# generate the file "configure", which is run during Tk installation
# to configure the system for the local environment.

AC_INIT
AC_CONFIG_SRCDIR([../generic/tk.h])
AC_PREREQ([2.69])

# The following define is needed when building with Cygwin since newer
# versions of autoconf incorrectly set SHELL to /bin/bash instead of
# /bin/sh. The bash shell seems to suffer from some strange failures.
SHELL=/bin/sh

TK_VERSION=8.7
TK_MAJOR_VERSION=8
TK_MINOR_VERSION=7
TK_PATCH_LEVEL="a4"
VER=$TK_MAJOR_VERSION$TK_MINOR_VERSION

#------------------------------------------------------------------------
# Handle the --prefix=... option
#------------------------------------------------------------------------

if test "${prefix}" = "NONE"; then
    prefix=/usr/local
fi
if test "${exec_prefix}" = "NONE"; then
    exec_prefix=$prefix
fi
# libdir must be a fully qualified path (not ${exec_prefix}/lib)
eval libdir="$libdir"

#------------------------------------------------------------------------
# Standard compiler checks
#------------------------------------------------------------------------

# If the user did not set CFLAGS, set it now to keep
# the AC_PROG_CC macro from adding "-g -O2".
if test "${CFLAGS+set}" != "set" ; then
    CFLAGS=""
fi

AC_PROG_CC
AC_C_INLINE
AC_HEADER_STDC
AC_CHECK_INCLUDES_DEFAULT

AC_CHECK_TOOL(AR, ar)
AC_CHECK_TOOL(RANLIB, ranlib)
AC_CHECK_TOOL(RC, windres)

#--------------------------------------------------------------------
# Checks to see if the make program sets the $MAKE variable.
#--------------------------------------------------------------------

AC_PROG_MAKE_SET

#--------------------------------------------------------------------
# Determines the correct binary file extension (.o, .obj, .exe etc.)
#--------------------------------------------------------------------

AC_OBJEXT
AC_EXEEXT

#--------------------------------------------------------------------
# The statements below define a collection of symbols related to
# building libtk as a shared library instead of a static library.
#--------------------------------------------------------------------

SC_ENABLE_SHARED

#--------------------------------------------------------------------
# Locate and source the tclConfig.sh file.
#--------------------------------------------------------------------

SC_PATH_TCLCONFIG($TK_PATCH_LEVEL)
SC_LOAD_TCLCONFIG

if test "${TCL_MAJOR_VERSION}" -lt 9 ; then
if test "${TCL_MAJOR_VERSION}" != "${TK_MAJOR_VERSION}"; then
    AC_MSG_ERROR([${TCL_BIN_DIR}/tclConfig.sh is for Tcl ${TCL_VERSION}.
Tk ${TK_VERSION}${TK_PATCH_LEVEL} needs Tcl 8.6+.
Use --with-tcl= option to indicate location of tclConfig.sh file for Tcl 8.6 or better.])
fi
if test "${TCL_MINOR_VERSION}" -lt 6; then
    AC_MSG_ERROR([${TCL_BIN_DIR}/tclConfig.sh is for Tcl ${TCL_VERSION}.
Tk ${TK_VERSION}${TK_PATCH_LEVEL} needs Tcl 8.6+.
Use --with-tcl= option to indicate location of tclConfig.sh file for Tcl 8.6 or better.])
fi
fi

#--------------------------------------------------------------------
# The statements below define a collection of compile flags.  This
# macro depends on the value of SHARED_BUILD, and should be called
# after SC_ENABLE_SHARED checks the configure switches.
#--------------------------------------------------------------------

SC_CONFIG_CFLAGS

AC_CHECK_TYPES([intptr_t, uintptr_t],,,[[
#include <stdint.h>
]])

#--------------------------------------------------------------------
# man2tcl needs this so that it can use errno.h
#--------------------------------------------------------------------

AC_CHECK_HEADER(errno.h, , MAN2TCLFLAGS="-DNO_ERRNO_H")
AC_SUBST(MAN2TCLFLAGS)

#-------------------------------------------
#     Check for _strtoi64
#-------------------------------------------

AC_CACHE_CHECK([availability of _strtoi64], tcl_cv_strtoi64, [
    AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <stdlib.h>]], [[_strtoi64(0,0,0)]])],[tcl_cv_strtoi64=yes],[tcl_cv_strtoi64=no])])
if test $tcl_cv_strtoi64 = no; then
    AC_DEFINE(NO_STRTOI64, 1, [Is _strtoi64 function available?])
fi

#--------------------------------------------------------------------
# Windows XP theme engine header for Ttk
#--------------------------------------------------------------------

AC_CHECK_HEADER([uxtheme.h], [AC_DEFINE(HAVE_UXTHEME_H)],
	[AC_MSG_NOTICE([xpnative theme will be unavailable])],
	[#include <windows.h>])
AC_CHECK_HEADER([vssym32.h], [AC_DEFINE(HAVE_VSSYM32_H)], [],
	[#include <windows.h>
#include <uxtheme.h>])

#--------------------------------------------------------------------
# Set the default compiler switches based on the --enable-symbols
# option.  This macro depends on C flags, and should be called
# after SC_CONFIG_CFLAGS macro is called.
#--------------------------------------------------------------------

SC_ENABLE_SYMBOLS

#--------------------------------------------------------------------
# Embed the manifest if we can determine how
#--------------------------------------------------------------------

SC_EMBED_MANIFEST(wish.exe.manifest)

SC_BUILD_TCLSH
SC_PROG_TCLSH

#------------------------------------------------------------------------
# tkConfig.sh refers to this by a different name
#------------------------------------------------------------------------

TK_SHARED_BUILD=${SHARED_BUILD}

#--------------------------------------------------------------------
# Perform final evaluations of variables with possible substitutions.
#--------------------------------------------------------------------

TK_SHARED_LIB_SUFFIX="\${NODOT_VERSION}${DLLSUFFIX}"
TK_UNSHARED_LIB_SUFFIX="\${NODOT_VERSION}${LIBSUFFIX}"
TK_EXPORT_FILE_SUFFIX="\${NODOT_VERSION}${LIBSUFFIX}"

eval "TK_SRC_DIR=\"`cd $srcdir/..; pwd`\""

eval "TK_DLL_FILE=tk$VER${DLLSUFFIX}"
if test ${SHARED_BUILD} = 0 ; then
 eval "TK_LIB_FILE=${LIBPREFIX}tk${VER}${LIBSUFFIX}"
else
 eval "TK_LIB_FILE=${LIBPREFIX}tk${VER}${DLLSUFFIX}.a"
fi

eval "TK_STUB_LIB_FILE=${LIBPREFIX}tkstub${VER}${LIBSUFFIX}"
# FIXME: All of this var junk needs to be done in tcl.m4 !!!!
# I left out the other vars that also need to get defined here.
# we also need to double check about spaces in path names
eval "TK_LIB_FLAG=\"-ltk${VER}${LIBFLAGSUFFIX}\""
TK_LIB_SPEC="-L${libdir} ${TK_LIB_FLAG}"
TK_BUILD_LIB_SPEC="-L`pwd` ${TK_LIB_FLAG}"

eval "TK_STUB_LIB_FLAG=\"-ltkstub${VER}${LIBFLAGSUFFIX}\""
TK_BUILD_STUB_LIB_SPEC="-L`pwd` ${TK_STUB_LIB_FLAG}"

TK_STUB_LIB_SPEC="-L${libdir} ${TK_STUB_LIB_FLAG}"
TK_STUB_LIB_PATH="${libdir}/${TK_STUB_LIB_FILE}"
TK_BUILD_STUB_LIB_PATH="`pwd`/${TK_STUB_LIB_FILE}"

eval "DLLSUFFIX=${DLLSUFFIX}"
eval "LIBPREFIX=${LIBPREFIX}"
eval "LIBSUFFIX=${LIBSUFFIX}"
eval "EXESUFFIX=${EXESUFFIX}"

CFG_TK_SHARED_LIB_SUFFIX=${TK_SHARED_LIB_SUFFIX}
CFG_TK_UNSHARED_LIB_SUFFIX=${TK_UNSHARED_LIB_SUFFIX}
CFG_TK_EXPORT_FILE_SUFFIX=${TK_EXPORT_FILE_SUFFIX}

#--------------------------------------------------------------------
# Adjust the defines for how the resources are built depending
# on symbols and static vs. shared.
#--------------------------------------------------------------------

if test ${SHARED_BUILD} = 0 -o "$TCL_NEEDS_EXP_FILE" = 0; then
    RC_DEFINES="${RC_DEFINE} STATIC_BUILD"
    TK_RES=""
else
    RC_DEFINES=""
    TK_RES='tk.$(RES)'
fi

# The wish.exe.manifest requires these
# TK_WIN_VERSION is the 4 dotted pair Windows version format which needs
# the release level, and must account for interim release versioning
case "$TK_PATCH_LEVEL" in
     *a*) TK_RELEASE_LEVEL=0 ;;
     *b*) TK_RELEASE_LEVEL=1 ;;
     *)   TK_RELEASE_LEVEL=2 ;;
esac
TK_WIN_VERSION="$TK_VERSION.$TK_RELEASE_LEVEL.`echo $TK_PATCH_LEVEL | tr -d ab.`"
AC_SUBST(TK_WIN_VERSION)
# X86|AMD64|IA64 for manifest
AC_SUBST(MACHINE)

AC_SUBST(TK_VERSION)
AC_SUBST(TK_MAJOR_VERSION)
AC_SUBST(TK_MINOR_VERSION)
AC_SUBST(TK_PATCH_LEVEL)
AC_SUBST(TK_LIB_FILE)
AC_SUBST(TK_DLL_FILE)
AC_SUBST(TK_STUB_LIB_FILE)
AC_SUBST(TK_STUB_LIB_FLAG)
AC_SUBST(TK_BUILD_STUB_LIB_SPEC)
AC_SUBST(TK_SRC_DIR)
AC_SUBST(TK_BIN_DIR)

AC_SUBST(TCL_VERSION)
AC_SUBST(TCL_MAJOR_VERSION)
AC_SUBST(TCL_MINOR_VERSION)
AC_SUBST(TCL_PATCH_LEVEL)

AC_SUBST(TCL_SRC_DIR)
AC_SUBST(TCL_BIN_DIR)
AC_SUBST(CFG_TK_SHARED_LIB_SUFFIX)
AC_SUBST(CFG_TK_UNSHARED_LIB_SUFFIX)
AC_SUBST(CFG_TK_EXPORT_FILE_SUFFIX)

AC_SUBST(CFLAGS_DEFAULT)
AC_SUBST(EXTRA_CFLAGS)
AC_SUBST(CYGPATH)
AC_SUBST(DEPARG)
AC_SUBST(CC_OBJNAME)
AC_SUBST(CC_EXENAME)

# win/tcl.m4 doesn't set (LDFLAGS)
AC_SUBST(LDFLAGS_DEFAULT)
AC_SUBST(LDFLAGS_DEBUG)
AC_SUBST(LDFLAGS_OPTIMIZE)
AC_SUBST(LDFLAGS_CONSOLE)
AC_SUBST(LDFLAGS_WINDOW)
AC_SUBST(AR)
AC_SUBST(RANLIB)
AC_SUBST(TK_RES)

AC_SUBST(STLIB_LD)
AC_SUBST(SHLIB_LD)
AC_SUBST(SHLIB_LD_LIBS)
AC_SUBST(SHLIB_CFLAGS)
AC_SUBST(SHLIB_SUFFIX)
AC_SUBST(TK_SHARED_BUILD)

AC_SUBST(LIBS)
AC_SUBST(LIBS_GUI)
AC_SUBST(DLLSUFFIX)
AC_SUBST(LIBPREFIX)
AC_SUBST(LIBSUFFIX)
AC_SUBST(EXESUFFIX)
AC_SUBST(LIBRARIES)
AC_SUBST(MAKE_LIB)
AC_SUBST(MAKE_STUB_LIB)
AC_SUBST(POST_MAKE_LIB)
AC_SUBST(MAKE_DLL)
AC_SUBST(MAKE_EXE)

AC_SUBST(TK_LIB_FLAG)
AC_SUBST(TK_LIB_SPEC)
AC_SUBST(TK_BUILD_LIB_SPEC)
AC_SUBST(TK_STUB_LIB_SPEC)
AC_SUBST(TK_STUB_LIB_PATH)
AC_SUBST(TK_BUILD_STUB_LIB_PATH)

# undefined at this point for win
AC_SUBST(TK_CC_SEARCH_FLAGS)
AC_SUBST(TK_LD_SEARCH_FLAGS)

AC_SUBST(RC)
AC_SUBST(RC_OUT)
AC_SUBST(RC_TYPE)
AC_SUBST(RC_INCLUDE)
AC_SUBST(RC_DEFINE)
AC_SUBST(RC_DEFINES)
AC_SUBST(RES)

AC_CONFIG_FILES([Makefile tkConfig.sh wish.exe.manifest])
AC_OUTPUT

dnl Local Variables:
dnl mode: autoconf;
dnl End:
Deleted win/configure.in.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314


























































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#! /bin/bash -norc
# This file is an input file used by the GNU "autoconf" program to
# generate the file "configure", which is run during Tk installation
# to configure the system for the local environment.

AC_INIT(../generic/tk.h)
AC_PREREQ(2.59)

# The following define is needed when building with Cygwin since newer
# versions of autoconf incorrectly set SHELL to /bin/bash instead of
# /bin/sh. The bash shell seems to suffer from some strange failures.
SHELL=/bin/sh

TK_VERSION=8.6
TK_MAJOR_VERSION=8
TK_MINOR_VERSION=6
TK_PATCH_LEVEL=".10"
VER=$TK_MAJOR_VERSION$TK_MINOR_VERSION

#------------------------------------------------------------------------
# Handle the --prefix=... option
#------------------------------------------------------------------------

if test "${prefix}" = "NONE"; then
    prefix=/usr/local
fi
if test "${exec_prefix}" = "NONE"; then
    exec_prefix=$prefix
fi
# libdir must be a fully qualified path (not ${exec_prefix}/lib)
eval libdir="$libdir"

#------------------------------------------------------------------------
# Standard compiler checks
#------------------------------------------------------------------------

# If the user did not set CFLAGS, set it now to keep
# the AC_PROG_CC macro from adding "-g -O2".
if test "${CFLAGS+set}" != "set" ; then
    CFLAGS=""
fi

AC_PROG_CC
AC_C_INLINE
AC_HEADER_STDC

AC_CHECK_TOOL(AR, ar)
AC_CHECK_TOOL(RANLIB, ranlib)
AC_CHECK_TOOL(RC, windres)

#--------------------------------------------------------------------
# Checks to see if the make program sets the $MAKE variable.
#--------------------------------------------------------------------

AC_PROG_MAKE_SET

#--------------------------------------------------------------------
# Determines the correct binary file extension (.o, .obj, .exe etc.)
#--------------------------------------------------------------------

AC_OBJEXT
AC_EXEEXT

#--------------------------------------------------------------------
# Check whether --enable-threads or --disable-threads was given.
#--------------------------------------------------------------------

SC_ENABLE_THREADS

#--------------------------------------------------------------------
# The statements below define a collection of symbols related to
# building libtk as a shared library instead of a static library.
#--------------------------------------------------------------------

SC_ENABLE_SHARED

#--------------------------------------------------------------------
# Locate and source the tclConfig.sh file.
#--------------------------------------------------------------------

SC_PATH_TCLCONFIG($TK_PATCH_LEVEL)
SC_LOAD_TCLCONFIG

if test "${TCL_MAJOR_VERSION}" != "${TK_MAJOR_VERSION}"; then
    AC_MSG_ERROR([${TCL_BIN_DIR}/tclConfig.sh is for Tcl ${TCL_VERSION}.
Tk ${TK_VERSION}${TK_PATCH_LEVEL} needs Tcl ${TK_VERSION}.
Use --with-tcl= option to indicate location of tclConfig.sh file for Tcl ${TK_VERSION}.])
fi
if test "${TCL_MINOR_VERSION}" -lt "${TK_MINOR_VERSION}"; then
    AC_MSG_ERROR([${TCL_BIN_DIR}/tclConfig.sh is for Tcl ${TCL_VERSION}.
Tk ${TK_VERSION}${TK_PATCH_LEVEL} needs Tcl ${TK_VERSION}.
Use --with-tcl= option to indicate location of tclConfig.sh file for Tcl ${TK_VERSION}.])
fi

#--------------------------------------------------------------------
# The statements below define a collection of compile flags.  This
# macro depends on the value of SHARED_BUILD, and should be called
# after SC_ENABLE_SHARED checks the configure switches.
#--------------------------------------------------------------------

SC_CONFIG_CFLAGS

#--------------------------------------------------------------------
# man2tcl needs this so that it can use errno.h
#--------------------------------------------------------------------

AC_CHECK_HEADER(errno.h, , MAN2TCLFLAGS="-DNO_ERRNO_H")
AC_SUBST(MAN2TCLFLAGS)

#-------------------------------------------
#     Check for _strtoi64
#-------------------------------------------

AC_CACHE_CHECK([availability of _strtoi64], tcl_cv_strtoi64, [
    AC_TRY_LINK([#include <stdlib.h>],
	    [_strtoi64(0,0,0)],
	    tcl_cv_strtoi64=yes, tcl_cv_strtoi64=no)])
if test $tcl_cv_strtoi64 = no; then
    AC_DEFINE(NO_STRTOI64, 1, [Is _strtoi64 function available?])
fi

#--------------------------------------------------------------------
# Windows XP theme engine header for Ttk
#--------------------------------------------------------------------

AC_CHECK_HEADER([uxtheme.h], [AC_DEFINE(HAVE_UXTHEME_H)],
	[AC_MSG_NOTICE([xpnative theme will be unavailable])],
	[#include <windows.h>])
AC_CHECK_HEADER([vssym32.h], [AC_DEFINE(HAVE_VSSYM32_H)], [],
	[#include <windows.h>
#include <uxtheme.h>])

#--------------------------------------------------------------------
# Set the default compiler switches based on the --enable-symbols
# option.  This macro depends on C flags, and should be called
# after SC_CONFIG_CFLAGS macro is called.
#--------------------------------------------------------------------

SC_ENABLE_SYMBOLS

TK_DBGX=${DBGX}

#--------------------------------------------------------------------
# Embed the manifest if we can determine how
#--------------------------------------------------------------------

SC_EMBED_MANIFEST(wish.exe.manifest)

SC_BUILD_TCLSH
SC_PROG_TCLSH

#------------------------------------------------------------------------
# tkConfig.sh refers to this by a different name
#------------------------------------------------------------------------

TK_SHARED_BUILD=${SHARED_BUILD}

#--------------------------------------------------------------------
# Perform final evaluations of variables with possible substitutions.
#--------------------------------------------------------------------

TK_SHARED_LIB_SUFFIX="\${NODOT_VERSION}${DLLSUFFIX}"
TK_UNSHARED_LIB_SUFFIX="\${NODOT_VERSION}${LIBSUFFIX}"
TK_EXPORT_FILE_SUFFIX="\${NODOT_VERSION}${LIBSUFFIX}"

eval "TK_SRC_DIR=\"`cd $srcdir/..; pwd`\""

eval "TK_DLL_FILE=tk$VER${DLLSUFFIX}"
eval "TK_LIB_FILE=${LIBPREFIX}tk$VER${LIBSUFFIX}"

eval "TK_STUB_LIB_FILE=${LIBPREFIX}tkstub${VER}${LIBSUFFIX}"
# FIXME: All of this var junk needs to be done in tcl.m4 !!!!
# I left out the other vars that also need to get defined here.
# we also need to double check about spaces in path names
eval "TK_LIB_FLAG=\"-ltk${VER}${LIBFLAGSUFFIX}\""
TK_LIB_SPEC="-L${libdir} ${TK_LIB_FLAG}"
TK_BUILD_LIB_SPEC="-L`pwd` ${TK_LIB_FLAG}"

eval "TK_STUB_LIB_FLAG=\"-ltkstub${VER}${LIBFLAGSUFFIX}\""
TK_BUILD_STUB_LIB_SPEC="-L`pwd` ${TK_STUB_LIB_FLAG}"

TK_STUB_LIB_SPEC="-L${libdir} ${TK_STUB_LIB_FLAG}"
TK_STUB_LIB_PATH="${libdir}/${TK_STUB_LIB_FILE}"
TK_BUILD_STUB_LIB_PATH="`pwd`/${TK_STUB_LIB_FILE}"

eval "DLLSUFFIX=${DLLSUFFIX}"
eval "LIBPREFIX=${LIBPREFIX}"
eval "LIBSUFFIX=${LIBSUFFIX}"
eval "EXESUFFIX=${EXESUFFIX}"

CFG_TK_SHARED_LIB_SUFFIX=${TK_SHARED_LIB_SUFFIX}
CFG_TK_UNSHARED_LIB_SUFFIX=${TK_UNSHARED_LIB_SUFFIX}
CFG_TK_EXPORT_FILE_SUFFIX=${TK_EXPORT_FILE_SUFFIX}

#--------------------------------------------------------------------
# Adjust the defines for how the resources are built depending
# on symbols and static vs. shared.
#--------------------------------------------------------------------

if test ${SHARED_BUILD} = 0 -o "$TCL_NEEDS_EXP_FILE" = 0; then
    if test "${DBGX}" = "d"; then
        RC_DEFINES="${RC_DEFINE} STATIC_BUILD ${RC_DEFINE} DEBUG"
    else
        RC_DEFINES="${RC_DEFINE} STATIC_BUILD"
    fi
    TK_RES=""
else
    if test "${DBGX}" = "d"; then
        RC_DEFINES="${RC_DEFINE} DEBUG"
    else
        RC_DEFINES=""
    fi
    TK_RES='tk.$(RES)'
fi

# The wish.exe.manifest requires these
# TK_WIN_VERSION is the 4 dotted pair Windows version format which needs
# the release level, and must account for interim release versioning
case "$TK_PATCH_LEVEL" in
     *a*) TK_RELEASE_LEVEL=0 ;;
     *b*) TK_RELEASE_LEVEL=1 ;;
     *)   TK_RELEASE_LEVEL=2 ;;
esac
TK_WIN_VERSION="$TK_VERSION.$TK_RELEASE_LEVEL.`echo $TK_PATCH_LEVEL | tr -d ab.`"
AC_SUBST(TK_WIN_VERSION)
# X86|AMD64|IA64 for manifest
AC_SUBST(MACHINE)

AC_SUBST(TK_VERSION)
AC_SUBST(TK_MAJOR_VERSION)
AC_SUBST(TK_MINOR_VERSION)
AC_SUBST(TK_PATCH_LEVEL)
AC_SUBST(TK_DBGX)
AC_SUBST(TK_LIB_FILE)
AC_SUBST(TK_DLL_FILE)
AC_SUBST(TK_STUB_LIB_FILE)
AC_SUBST(TK_STUB_LIB_FLAG)
AC_SUBST(TK_BUILD_STUB_LIB_SPEC)
AC_SUBST(TK_SRC_DIR)
AC_SUBST(TK_BIN_DIR)

AC_SUBST(TCL_VERSION)
AC_SUBST(TCL_MAJOR_VERSION)
AC_SUBST(TCL_MINOR_VERSION)
AC_SUBST(TCL_PATCH_LEVEL)

AC_SUBST(TCL_SRC_DIR)
AC_SUBST(TCL_BIN_DIR)
AC_SUBST(TCL_DBGX)
AC_SUBST(CFG_TK_SHARED_LIB_SUFFIX)
AC_SUBST(CFG_TK_UNSHARED_LIB_SUFFIX)
AC_SUBST(CFG_TK_EXPORT_FILE_SUFFIX)

AC_SUBST(CFLAGS_DEFAULT)
AC_SUBST(EXTRA_CFLAGS)
AC_SUBST(CYGPATH)
AC_SUBST(DEPARG)
AC_SUBST(CC_OBJNAME)
AC_SUBST(CC_EXENAME)

# win/tcl.m4 doesn't set (LDFLAGS)
AC_SUBST(LDFLAGS_DEFAULT)
AC_SUBST(LDFLAGS_DEBUG)
AC_SUBST(LDFLAGS_OPTIMIZE)
AC_SUBST(LDFLAGS_CONSOLE)
AC_SUBST(LDFLAGS_WINDOW)
AC_SUBST(AR)
AC_SUBST(RANLIB)
AC_SUBST(TK_RES)

AC_SUBST(STLIB_LD)
AC_SUBST(SHLIB_LD)
AC_SUBST(SHLIB_LD_LIBS)
AC_SUBST(SHLIB_CFLAGS)
AC_SUBST(SHLIB_SUFFIX)
AC_SUBST(TK_SHARED_BUILD)

AC_SUBST(LIBS)
AC_SUBST(LIBS_GUI)
AC_SUBST(DLLSUFFIX)
AC_SUBST(LIBPREFIX)
AC_SUBST(LIBSUFFIX)
AC_SUBST(EXESUFFIX)
AC_SUBST(LIBRARIES)
AC_SUBST(MAKE_LIB)
AC_SUBST(MAKE_STUB_LIB)
AC_SUBST(POST_MAKE_LIB)
AC_SUBST(MAKE_DLL)
AC_SUBST(MAKE_EXE)

AC_SUBST(TK_LIB_FLAG)
AC_SUBST(TK_LIB_SPEC)
AC_SUBST(TK_BUILD_LIB_SPEC)
AC_SUBST(TK_STUB_LIB_SPEC)
AC_SUBST(TK_STUB_LIB_PATH)
AC_SUBST(TK_BUILD_STUB_LIB_PATH)

# undefined at this point for win
AC_SUBST(TK_CC_SEARCH_FLAGS)
AC_SUBST(TK_LD_SEARCH_FLAGS)

AC_SUBST(RC)
AC_SUBST(RC_OUT)
AC_SUBST(RC_TYPE)
AC_SUBST(RC_INCLUDE)
AC_SUBST(RC_DEFINE)
AC_SUBST(RC_DEFINES)
AC_SUBST(RES)

AC_OUTPUT(Makefile tkConfig.sh wish.exe.manifest)

dnl Local Variables:
dnl mode: autoconf;
dnl End:
Changes to win/makefile.vc.
16
17
18
19
20
21
22



23
24
25
26
27
28
29
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32







+
+
+








# General usage:
#   nmake [-nologo] -f makefile.vc [TARGET|MACRODEF [TARGET|MACRODEF] [...]]
#
# For MACRODEF, see TIP 477 (https://core.tcl-lang.org/tips/doc/trunk/tip/477.md)
# or examine Sections 6-8 in rules.vc. This makefile has the following
# values for the OPTS macro in addition to the ones described there.
#       noembed  = Embeds Tcl scripts into the wish executable. Currently only
#                  applicable for static builds. Non-static builds currently
#                  never embed.
#	noxp     = If you do not have the uxtheme.h header then you
#                  cannot include support for XP themeing.
#	square   = Include the demo square widget.
#
# Possible values for TARGET are:
#	release  -- Builds the core, the shell and the dlls. (default)
#	dlls     -- Just builds the windows extensions.
54
55
56
57
58
59
60
61

62
63
64
65
66
67
68
69

70
71
72
73
74
75
76
57
58
59
60
61
62
63

64
65
66
67
68
69
70
71

72
73
74
75
76
77
78
79







-
+







-
+







#
# NOTE: For older (Visual C++ 6 or the 2003 SDK), to use the Platform
# SDK (not expressly needed), run setenv.bat after vcvars32.bat
# according to the instructions for it.  This can also turn on the
# 64-bit compiler, if your SDK has it.
#
# Examples:
# Assumign Tcl sources lie in ../../tcl
# Assuming Tcl sources lie in ../../tcl
#       c:\tcl_src\win\>nmake -f makefile.vc release
# If Tcl sources are not in ../../tcl, use the TCLDIR macro to specify dir
#       c:\tcl_src\win\>nmake -f makefile.vc release TCLDIR=c:\src\tcl
# Run the test suite
#       c:\tcl_src\win\>nmake -f makefile.vc test
# Install Tk in location specified by INSTALLDIR macro
#       c:\tcl_src\win\>nmake -f makefile.vc install INSTALLDIR=c:\progra~1\tcl
# Build release with PDF files
# Build release with PDB files
#       c:\tcl_src\win\>nmake -f makefile.vc release OPTS=pdbs
# Build debug version
#       c:\tcl_src\win\>nmake -f makefile.vc release OPTS=symbols
#
###############################################################################

# The PROJECT macro is used by rules.vc for generating appropriate
98
99
100
101
102
103
104

105
106
107
108
109
110
111
112
113
114
115
116
117














118
119
120
121
122
123
124
125
126
127

128
129
130
131
132
133
134
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144

145
146
147
148
149
150
151
152







+













+
+
+
+
+
+
+
+
+
+
+
+
+
+









-
+







!message ***    Tcl sources.
!endif

# Extra makefile options processing for non-standard OPTS values ...
!if "$(OPTS)" == "" || [nmakehlp -f "$(OPTS)" "none"]
HAVE_UXTHEME_H    = 1
TTK_SQUARE_WIDGET = 0
TK_EMBED_SCRIPTS  = $(STATIC_BUILD)
!else
!if [nmakehlp -f $(OPTS) "noxp"]
!message *** Exclude support for XP theme
HAVE_UXTHEME_H  = 0
!else
HAVE_UXTHEME_H  = 1
!endif
!if [nmakehlp -f "$(OPTS)" "square"]
!message *** Include ttk square demo widget
TTK_SQUARE_WIDGET   = 1
!else
TTK_SQUARE_WIDGET   = 0
!endif
!if [nmakehlp -f $(OPTS) "noembed"]
!message *** Option noembed specified. Tk script library will not be appended to the binary.
TK_EMBED_SCRIPTS = 0
!else
!message *** Tk script library will be appended to the binary.
TK_EMBED_SCRIPTS = $(STATIC_BUILD)
!endif
!endif

TK_NO_DEPRECATED = 0
!if "$(CHECKS)" != "" && ![nmakehlp -f "$(CHECKS)" "none"]
!if [nmakehlp -f $(CHECKS) "nodep"]
TK_NO_DEPRECATED = 1
!endif
!endif

WISHC 		= "$(OUT_DIR)\$(WISHNAMEPREFIX)c$(VERSION)$(SUFX).exe"

TKTEST		= "$(OUT_DIR)\$(PROJECT)test.exe"
CAT32		= "$(OUT_DIR)\cat32.exe"

WISHOBJS = \
	$(TMP_DIR)\winMain.obj \
!if $(TCL_USE_STATIC_PACKAGES)
!if $(STATIC_BUILD) && !$(STATIC_BUILD)
	$(TCLDDELIB) \
	$(TCLREGLIB) \
!endif
	$(TMP_DIR)\wish.res

TKTESTOBJS = \
	$(TMP_DIR)\testMain.obj \
156
157
158
159
160
161
162

163
164
165
166
167
168
169
170
171
172

173
174
175
176
177
178
179
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199







+










+







	$(TMP_DIR)\tkWinColor.obj \
	$(TMP_DIR)\tkWinConfig.obj \
	$(TMP_DIR)\tkWinCursor.obj \
	$(TMP_DIR)\tkWinDialog.obj \
	$(TMP_DIR)\tkWinDraw.obj \
	$(TMP_DIR)\tkWinEmbed.obj \
	$(TMP_DIR)\tkWinFont.obj \
	$(TMP_DIR)\tkWinIco.obj \
	$(TMP_DIR)\tkWinImage.obj \
	$(TMP_DIR)\tkWinInit.obj \
	$(TMP_DIR)\tkWinKey.obj \
	$(TMP_DIR)\tkWinMenu.obj \
	$(TMP_DIR)\tkWinPixmap.obj \
	$(TMP_DIR)\tkWinPointer.obj \
	$(TMP_DIR)\tkWinRegion.obj \
	$(TMP_DIR)\tkWinScrlbr.obj \
	$(TMP_DIR)\tkWinSend.obj \
	$(TMP_DIR)\tkWinSendCom.obj \
	$(TMP_DIR)\tkWinSysTray.obj \
	$(TMP_DIR)\tkWinWindow.obj \
	$(TMP_DIR)\tkWinWm.obj \
	$(TMP_DIR)\tkWinX.obj \
	$(TMP_DIR)\stubs.obj \
	$(TMP_DIR)\tk3d.obj \
	$(TMP_DIR)\tkArgv.obj \
	$(TMP_DIR)\tkAtom.obj \
206
207
208
209
210
211
212

213
214
215

216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231

232
233
234
235
236
237
238
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261







+



+
















+







	$(TMP_DIR)\tkGC.obj \
	$(TMP_DIR)\tkGeometry.obj \
	$(TMP_DIR)\tkGet.obj \
	$(TMP_DIR)\tkGrab.obj \
	$(TMP_DIR)\tkGrid.obj \
	$(TMP_DIR)\tkImage.obj \
	$(TMP_DIR)\tkImgBmap.obj \
	$(TMP_DIR)\tkImgListFormat.obj \
	$(TMP_DIR)\tkImgGIF.obj \
	$(TMP_DIR)\tkImgPNG.obj \
	$(TMP_DIR)\tkImgPPM.obj \
	$(TMP_DIR)\tkImgSVGnano.obj \
	$(TMP_DIR)\tkImgPhoto.obj \
	$(TMP_DIR)\tkImgPhInstance.obj \
	$(TMP_DIR)\tkImgUtil.obj \
	$(TMP_DIR)\tkListbox.obj \
	$(TMP_DIR)\tkMacWinMenu.obj \
	$(TMP_DIR)\tkMain.obj \
	$(TMP_DIR)\tkMain2.obj \
	$(TMP_DIR)\tkMenu.obj \
	$(TMP_DIR)\tkMenubutton.obj \
	$(TMP_DIR)\tkMenuDraw.obj \
	$(TMP_DIR)\tkMessage.obj \
	$(TMP_DIR)\tkPanedWindow.obj \
	$(TMP_DIR)\tkObj.obj \
	$(TMP_DIR)\tkOldConfig.obj \
	$(TMP_DIR)\tkOption.obj \
	$(TMP_DIR)\tkPack.obj \
	$(TMP_DIR)\tkPkgConfig.obj \
	$(TMP_DIR)\tkPlace.obj \
	$(TMP_DIR)\tkPointer.obj \
	$(TMP_DIR)\tkRectOval.obj \
	$(TMP_DIR)\tkScale.obj \
	$(TMP_DIR)\tkScrollbar.obj \
	$(TMP_DIR)\tkSelect.obj \
	$(TMP_DIR)\tkStyle.obj \
295
296
297
298
299
300
301






302
303
304
305
306
307
308

309
310
311
312
313
314
315



316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336

337
338
339

















340
341
342
343
344
345
346
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336

337
338

339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366

367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394







+
+
+
+
+
+






-
+

-





+
+
+




















-
+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	$(TMP_DIR)\ttkStubLib.obj

### The following paths CANNOT have spaces in them as they appear on
### the left side of implicit rules.
XLIBDIR		= $(ROOT)\xlib
TTKDIR		= $(ROOT)\generic\ttk
BITMAPDIR	= $(ROOT)\bitmaps

# Directories where to build TIP430 ZIP files
# One for Tk - always built, contains Tk scripts
# One for Wish - for static builds, contains Tcl+Tk scripts
LIBTKVFS = $(OUT_DIR)\libtk.vfs
WISHSCRIPTZIP = $(OUT_DIR)\wish.zip

# Additional include and C macro definitions for the implicit rules
# defined in rules.vc
PRJ_INCLUDES	= -I"$(BITMAPDIR)" -I"$(XLIBDIR)"

CONFIG_DEFS     =/DSTDC_HEADERS=1 /DHAVE_SYS_TYPES_H=1 /DHAVE_SYS_STAT_H=1 \
		 /DHAVE_STDLIB_H=1 /DHAVE_STRING_H=1 /DHAVE_MEMORY_H=1 \
		 /DHAVE_STRING_H=1 /DHAVE_MEMORY_H=1 \
		 /DHAVE_STRINGS_H=1 \
		 /DSUPPORT_CONFIG_EMBEDDED \
!if $(HAVE_UXTHEME_H)
		 /DHAVE_UXTHEME_H=1 \
!endif
!if $(TTK_SQUARE_WIDGET)
		 /DTTK_SQUARE_WIDGET=1 \
!endif
!if $(TK_NO_DEPRECATED)
		 /DTK_NO_DEPRECATED=1
!endif

PRJ_DEFINES	= /DBUILD_ttk $(CONFIG_DEFS) /Dinline=__inline /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE

# Additional Link libraries needed beyond those in rules.vc
PRJ_LIBS   = netapi32.lib gdi32.lib user32.lib userenv.lib


#---------------------------------------------------------------------
# TkTest flags
#---------------------------------------------------------------------

!if "$(TESTPAT)" != ""
TESTFLAGS = $(TESTFLAGS) -file $(TESTPAT)
!endif

#---------------------------------------------------------------------
# Project specific targets
#---------------------------------------------------------------------

release:  setup $(TKSTUBLIB) $(WISH)
release:  setup $(TKSTUBLIB) $(WISH) libtkzip embed
all:	  release $(CAT32)
core:	  setup $(TKSTUBLIB) $(TKLIB)
cwish:	  $(WISHC)
libtkzip: setup $(TKSCRIPTZIP)
!if $(TK_EMBED_SCRIPTS)
!if $(STATIC_BUILD)
embed:    setup $(WISH) $(WISHSCRIPTZIP)
	@copy /y /b "$(WISH)"+"$(WISHSCRIPTZIP)" "$(WISH)"
!else
# Note this is currently dead code as TK_EMBED_SCRIPTS is always 0
# for non-static builds as the C code does not currently setup up
# a VFS for a non-static wish.
embed:    setup $(TKLIB) $(TKSCRIPTZIP)
	@copy /y /b "$(TKLIB)"+"$(TKSCRIPTZIP)" "$(TKLIB)"
!endif
!else
# ! TK_EMBED_SCRIPTS - still need to build the zip even if not embedded
embed: $(TKSCRIPTZIP)
!endif

install:  install-binaries install-libraries install-docs
!if $(SYMBOLS)
install:    install-pdbs
!endif
tktest:	  setup $(TKTEST) $(CAT32)

setup: default-setup
449
450
451
452
453
454
455






















456
457
458
459
460
461
462
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	$(_VC_MANIFEST_EMBED_EXE)


$(TKTEST): $(TKTESTOBJS) $(TKSTUBLIB) $(TKIMPLIB)
	$(GUIEXECMD) -stack:2300000 $**
	$(_VC_MANIFEST_EMBED_EXE)

TKSCRIPTZIPTOP = tk_library
#TKSCRIPTZIPTOP = "tk$(DOTVERSION)"
$(TKSCRIPTZIP): .PHONY
	@echo Building Tk library zip file
	@if not exist "$(LIBTKVFS)" $(MKDIR) "$(LIBTKVFS)"
	@if exist "$(LIBTKVFS)\$(TKSCRIPTZIPTOP)" $(RMDIR) "$(LIBTKVFS)\$(TKSCRIPTZIPTOP)"
	@$(CPYDIR) $(LIBDIR) "$(LIBTKVFS)\$(TKSCRIPTZIPTOP)"
	@echo file delete -force {$@} > "$(OUT_DIR)\zipper.tcl"
	@echo zipfs mkzip {$@} {$(LIBTKVFS)} {$(LIBTKVFS)} >> "$(OUT_DIR)\zipper.tcl"
	@cd "$(OUT_DIR)" && $(TCLSH) zipper.tcl

!if $(STATIC_BUILD)
$(WISHSCRIPTZIP): $(TKSCRIPTZIP)
	@echo Building Wish Tcl+Tk library zip file
	@if exist "$(LIBTKVFS)\tcl_library" $(RMDIR) "$(LIBTKVFS)\tcl_library"
	@echo file delete -force {$@} > "$(OUT_DIR)\zipper.tcl"
	@echo zipfs mount mnt "$(TCLSCRIPTZIP:\=/)" >> "$(OUT_DIR)\zipper.tcl"
	@echo file copy [file join [zipfs root] mnt tcl_library] "$(LIBTKVFS:\=/)" >> "$(OUT_DIR)\zipper.tcl"
	@echo zipfs mkzip {$@} {$(LIBTKVFS)} {$(LIBTKVFS)} >> "$(OUT_DIR)\zipper.tcl"
	@cd "$(OUT_DIR)" && $(TCLSH) zipper.tcl
!endif


$(CAT32): $(_TCLDIR)\win\cat.c
	$(cc32) $(cflags) $(crt) /D_CRT_NONSTDC_NO_DEPRECATE /DCONSOLE /DUNICODE /D_UNICODE -Fo$(TMP_DIR)\ $?
	$(CONEXECMD) /DCONSOLE -stack:16384 $(TMP_DIR)\cat.obj
	$(_VC_MANIFEST_EMBED_EXE)

#---------------------------------------------------------------------
526
527
528
529
530
531
532

533
534
535

536
537
538
539
540
541
542
543
544
545
546
547
548
549

550
551
552

553
554
555
556
557
558
559
596
597
598
599
600
601
602
603
604
605

606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623

624
625
626
627
628
629
630
631







+


-
+














+


-
+







	@$(CPY) "$(OUT_DIR)\*.pdb" "$(BIN_INSTALL_DIR)\"
# "emacs font-lock highlighting fix

#---------------------------------------------------------------------
# Special case object file targets
#---------------------------------------------------------------------

# Note: Static builds now always mandate statically linking Tcl registry etc.
$(TMP_DIR)\testMain.obj: $(WIN_DIR)\winMain.c
	$(cc32) $(appcflags_nostubs) /DTK_TEST /DUNICODE /D_UNICODE \
	    /DTCL_USE_STATIC_PACKAGES=$(TCL_USE_STATIC_PACKAGES) \
	    /DTCL_USE_STATIC_PACKAGES=$(STATIC_BUILD) \
	    -Fo$@ $?

$(TMP_DIR)\tkTest.obj: $(GENERICDIR)\tkTest.c
	$(cc32) $(appcflags_nostubs) -Fo$@ $?

$(TMP_DIR)\tkOldTest.obj: $(GENERICDIR)\tkOldTest.c
	$(cc32) $(appcflags_nostubs) -Fo$@ $?

$(TMP_DIR)\tkWinTest.obj: $(WIN_DIR)\tkWinTest.c
	$(cc32) $(appcflags_nostubs) -Fo$@ $?

$(TMP_DIR)\tkSquare.obj: $(GENERICDIR)\tkSquare.c
	$(cc32) $(appcflags_nostubs) -Fo$@ $?

# Note: Static builds now always mandate statically linking Tcl registry etc.
$(TMP_DIR)\winMain.obj: $(WIN_DIR)\winMain.c
	$(cc32) $(appcflags_nostubs) /DUNICODE /D_UNICODE \
	    /DTCL_USE_STATIC_PACKAGES=$(TCL_USE_STATIC_PACKAGES) \
	    /DTCL_USE_STATIC_PACKAGES=$(STATIC_BUILD) \
	    -Fo$@ $?

$(TMP_DIR)\tkMain2.obj: $(GENERICDIR)\tkMain.c
	$(cc32) $(pkgcflags) /DUNICODE /D_UNICODE -Fo$@ $?

# The following objects are part of the stub library and should not
# be built as DLL objects but none of the symbols should be exported
648
649
650
651
652
653
654
655

656
657
658

659
660

661

662
663
664
665
666
667
668
669
670
671
672
673
674


675
676
677
678
679
680
681
682

683
684
685
686
687
688
689
720
721
722
723
724
725
726

727
728
729

730
731

732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765







-
+


-
+

-
+

+













+
+








+







	@$(CPY) "$(TKLIB)" "$(BIN_INSTALL_DIR)\"
!endif
	@$(CPY) "$(TKIMPLIB)" "$(LIB_INSTALL_DIR)\"
	@$(CPY) "$(TKSTUBLIB)" "$(LIB_INSTALL_DIR)\"
!if !$(STATIC_BUILD)
	@echo creating package index
	@type << > $(OUT_DIR)\pkgIndex.tcl
if {[catch {package present Tcl 8.6.0}]} { return }
if {[catch {package present Tcl 8.6-}]} { return }
if {($$::tcl_platform(platform) eq "unix") && ([info exists ::env(DISPLAY)]
	|| ([info exists ::argv] && ("-display" in $$::argv)))} {
    package ifneeded Tk $(TK_PATCH_LEVEL) [list load [file join $$dir .. .. bin libtk$(DOTVERSION).dll] Tk]
    package ifneeded tk $(TK_PATCH_LEVEL) [list load [file normalize [file join $$dir .. .. bin libtk$(DOTVERSION).dll]]]
} else {
    package ifneeded Tk $(TK_PATCH_LEVEL) [list load [file join $$dir .. .. bin $(TKLIBNAME)] Tk]
    package ifneeded tk $(TK_PATCH_LEVEL) [list load [file normalize [file join $$dir .. .. bin $(TKLIBNAME)]]]
}
package ifneeded Tk $(TK_PATCH_LEVEL) [list package require -exact tk $(TK_PATCH_LEVEL)]
<<
	@$(CPY) $(OUT_DIR)\pkgIndex.tcl "$(SCRIPT_INSTALL_DIR)\"
!endif

#"

install-libraries:
	@echo installing Tk headers
	@$(CPY) "$(GENERICDIR)\tk.h" "$(INCLUDE_INSTALL_DIR)\"
	@$(CPY) "$(GENERICDIR)\tkDecls.h" "$(INCLUDE_INSTALL_DIR)\"
	@$(CPY) "$(GENERICDIR)\tkPlatDecls.h" "$(INCLUDE_INSTALL_DIR)\"
	@$(CPY) "$(GENERICDIR)\tkIntXlibDecls.h" "$(INCLUDE_INSTALL_DIR)\"
	@$(CPY) "$(XLIBDIR)\X11\*.h" "$(INCLUDE_INSTALL_DIR)\X11\"
	@$(CPY) "$(TKSCRIPTZIP)" "$(LIB_INSTALL_DIR)"
!if !$(TK_EMBED_SCRIPTS)
	@echo installing script library
	@$(CPY) "$(LIBDIR)\*" "$(SCRIPT_INSTALL_DIR)\"
	@echo installing theme library
	@$(CPY) "$(LIBDIR)\ttk\*" "$(SCRIPT_INSTALL_DIR)\ttk\"
	@echo installing images
	@$(CPY) "$(LIBDIR)\images\*" "$(SCRIPT_INSTALL_DIR)\images\"
	@echo installing language files
	@$(CPY) "$(LIBDIR)\msgs\*" "$(SCRIPT_INSTALL_DIR)\msgs\"
!endif
	@echo installing demos
	@$(CPY) "$(DEMODIR)\*" "$(DEMO_INSTALL_DIR)\"
	@$(CPY) "$(DEMODIR)\images\*" "$(DEMO_INSTALL_DIR)\images\"

#"

#---------------------------------------------------------------------
703
704
705
706
707
708
709





779
780
781
782
783
784
785
786
787
788
789
790







+
+
+
+
+
	@echo Removing $(WISH) ...
	@if exist $(WISH) del $(WISH)
	@echo Removing $(TKTEST) ...
	@if exist $(TKTEST) del $(TKTEST)
	@echo Removing $(TKSTUBLIB) ...
	@if exist $(TKSTUBLIB) del $(TKSTUBLIB)

.PHONY:

# Local Variables:
# mode: makefile
# End:
Deleted win/mkd.bat.
1
2
3
4
5
6
7
8
9
10
11
12












-
-
-
-
-
-
-
-
-
-
-
-
@echo off

if exist %1\nul goto end

md %1
if errorlevel 1 goto end

echo Created directory %1

:end


Changes to win/nmakehlp.c.
1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15






-
-
+
+







/*
 * ----------------------------------------------------------------------------
 * nmakehlp.c --
 *
 *	This is used to fix limitations within nmake and the environment.
 *
 * Copyright (c) 2002 by David Gravereaux.
 * Copyright (c) 2006 by Pat Thoyts
 * Copyright (c) 2002 David Gravereaux.
 * Copyright (c) 2006 Pat Thoyts
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 * ----------------------------------------------------------------------------
 */

#define _CRT_SECURE_NO_DEPRECATE
Changes to win/rc/tk.rc.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

24
25
26
27
28
29
30
1
2
3
4
5
6
7
8
9
10






11
12
13
14
15
16

17
18
19
20
21
22
23
24










-
-
-
-
-
-






-
+







//
// Version Resource Script
//

#include <windows.h>
#include <tk.h>

//
// build-up the name suffix that defines the type of build this is.
//
#if TCL_THREADS
#define SUFFIX_THREADS	    "t"
#else
#define SUFFIX_THREADS	    ""
#endif

#if DEBUG && !UNCHECKED
#define SUFFIX_DEBUG	    "g"
#else
#define SUFFIX_DEBUG	    ""
#endif

#define SUFFIX		    SUFFIX_THREADS SUFFIX_DEBUG
#define SUFFIX		    SUFFIX_DEBUG


VS_VERSION_INFO	VERSIONINFO
 FILEVERSION	TK_MAJOR_VERSION,TK_MINOR_VERSION,TK_RELEASE_LEVEL,TK_RELEASE_SERIAL
 PRODUCTVERSION	TK_MAJOR_VERSION,TK_MINOR_VERSION,TK_RELEASE_LEVEL,TK_RELEASE_SERIAL
 FILEFLAGSMASK	0x3fL
#ifdef DEBUG
40
41
42
43
44
45
46
47

48
49
50
51
52
53
54
34
35
36
37
38
39
40

41
42
43
44
45
46
47
48







-
+







    BEGIN
        BLOCK "040904b0"
        BEGIN
            VALUE "FileDescription", "Tk DLL\0"
            VALUE "OriginalFilename", "tk" STRINGIFY(TK_MAJOR_VERSION) STRINGIFY(TK_MINOR_VERSION) SUFFIX ".dll\0"
            VALUE "CompanyName", "ActiveState Corporation\0"
            VALUE "FileVersion", TK_PATCH_LEVEL
            VALUE "LegalCopyright", "Copyright \251 2001 by ActiveState Corporation, et al\0"
            VALUE "LegalCopyright", "Copyright \251 2001 ActiveState Corporation, et al\0"
            VALUE "ProductName", "Tk " TK_VERSION " for Windows\0"
            VALUE "ProductVersion", TK_PATCH_LEVEL
        END
    END
    BLOCK "VarFileInfo"
    BEGIN
        VALUE "Translation", 0x409, 1200
Changes to win/rc/wish.rc.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

30
31
32
33
34
35
36
1
2
3
4
5
6
7
8
9
10






11
12
13
14
15
16
17
18
19
20
21
22

23
24
25
26
27
28
29
30










-
-
-
-
-
-












-
+







//
// Version Resource Script
//

#include <windows.h>
#include <tk.h>

//
// build-up the name suffix that defines the type of build this is.
//
#if TCL_THREADS
#define SUFFIX_THREADS	    "t"
#else
#define SUFFIX_THREADS	    ""
#endif

#if STATIC_BUILD
#define SUFFIX_STATIC	    "s"
#else
#define SUFFIX_STATIC	    ""
#endif

#if DEBUG && !UNCHECKED
#define SUFFIX_DEBUG	    "g"
#else
#define SUFFIX_DEBUG	    ""
#endif

#define SUFFIX		    SUFFIX_THREADS SUFFIX_STATIC SUFFIX_DEBUG
#define SUFFIX		    SUFFIX_STATIC SUFFIX_DEBUG


VS_VERSION_INFO VERSIONINFO
 FILEVERSION    TK_MAJOR_VERSION,TK_MINOR_VERSION,TK_RELEASE_LEVEL,TK_RELEASE_SERIAL
 PRODUCTVERSION TK_MAJOR_VERSION,TK_MINOR_VERSION,TK_RELEASE_LEVEL,TK_RELEASE_SERIAL
 FILEFLAGSMASK	0x3fL
#ifdef DEBUG
46
47
48
49
50
51
52
53

54
55
56
57
58
59
60
40
41
42
43
44
45
46

47
48
49
50
51
52
53
54







-
+







    BEGIN
        BLOCK "040904b0"
        BEGIN
            VALUE "FileDescription", "Wish Application\0"
            VALUE "OriginalFilename", "wish" STRINGIFY(TK_MAJOR_VERSION) STRINGIFY(TK_MINOR_VERSION) SUFFIX ".exe\0"
            VALUE "CompanyName", "ActiveState Corporation\0"
            VALUE "FileVersion", TK_PATCH_LEVEL
            VALUE "LegalCopyright", "Copyright \251 2000 by ActiveState Corporation, et al\0"
            VALUE "LegalCopyright", "Copyright \251 2000 ActiveState Corporation, et al\0"
            VALUE "ProductName", "Tk " TK_VERSION " for Windows\0"
            VALUE "ProductVersion", TK_PATCH_LEVEL
        END
    END
    BLOCK "VarFileInfo"
    BEGIN
        VALUE "Translation", 0x409, 1200
Deleted win/rmd.bat.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20




















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@echo off

if not exist %1\nul goto end

echo Removing directory %1

if "%OS%" == "Windows_NT" goto winnt

deltree /y %1
if errorlevel 1 goto end
goto success

:winnt
rmdir /s /q %1
if errorlevel 1 goto end

:success
echo Deleted directory %1

:end
Changes to win/rules-ext.vc.
27
28
29
30
31
32
33
34

35
36
37
38

39
40
41
42
43
44
45
27
28
29
30
31
32
33

34
35
36
37

38
39
40
41
42
43
44
45







-
+



-
+







!if "$(PROJECT)" == "tcl"
!error The rules-ext.vc file is not intended for Tcl itself.
!endif

# We extract version numbers using the nmakehlp program. For now use
# the local copy of nmakehlp. Once we locate Tcl, we will use that
# one if it is newer.
!if [$(CC) -nologo "nmakehlp.c" -link -subsystem:console > nul]
!if [$(CC) -nologo -DNDEBUG "nmakehlp.c" -link -subsystem:console > nul]
!endif

# First locate the Tcl directory that we are working with.
!ifdef TCLDIR
!if "$(TCLDIR)" != ""

_RULESDIR = $(TCLDIR:/=\)

!else

# If an installation path is specified, that is also the Tcl directory.
# Also Tk never builds against an installed Tcl, it needs Tcl sources
Changes to win/rules.vc.
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

28
29
30
31
32
33
34
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

27
28
29
30
31
32
33
34








-
+

















-
+







#------------------------------------------------------------- -*- makefile -*-
# rules.vc --
#
# Part of the nmake based build system for Tcl and its extensions.
# This file does all the hard work in terms of parsing build options,
# compiler switches, defining common targets and macros. The Tcl makefile
# directly includes this. Extensions include it via "rules-ext.vc".
#
# See TIP 477 (https://core.tcl-lang.org/tips/doc/trunk/tip/477.md) for
# See TIP 477 (https://core.tcl-lang.org/tips/doc/main/tip/477.md) for
# detailed documentation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# Copyright (c) 2001-2003 David Gravereaux.
# Copyright (c) 2003-2008 Patrick Thoyts
# Copyright (c) 2017      Ashok P. Nadkarni
#------------------------------------------------------------------------------

!ifndef _RULES_VC
_RULES_VC = 1

# The following macros define the version of the rules.vc nmake build system
# For modifications that are not backward-compatible, you *must* change
# the major version.
RULES_VERSION_MAJOR = 1
RULES_VERSION_MINOR = 6
RULES_VERSION_MINOR = 8

# The PROJECT macro must be defined by parent makefile.
!if "$(PROJECT)" == ""
!error *** Error: Macro PROJECT not defined! Please define it before including rules.vc
!endif

!if "$(PRJ_PACKAGE_TCLNAME)" == ""
298
299
300
301
302
303
304
305

306
307
308
309
310
311
312
313
314
315
316

317
318
319
320
321
322
323
298
299
300
301
302
303
304

305
306
307
308
309
310
311
312
313
314
315

316
317
318
319
320
321
322
323







-
+










-
+







TCLINSTALL	= 1
TCLDIR          = $(_INSTALLDIR)\..
# NOTE: we will be resetting _INSTALLDIR to _INSTALLDIR/lib for extensions
# later so the \.. accounts for the /lib
_TCLDIR		= $(_INSTALLDIR)\..
_TCL_H          = $(_TCLDIR)\include\tcl.h

!else # exist(...) && ! $(NEED_TCL_SOURCE)
!else # exist(...) && !$(NEED_TCL_SOURCE)

!if [echo _TCLDIR = \> nmakehlp.out] \
   || [nmakehlp -L generic\tcl.h >> nmakehlp.out]
!error *** Could not locate Tcl source directory.
!endif
!include nmakehlp.out
TCLINSTALL      = 0
TCLDIR         = $(_TCLDIR)
_TCL_H          = $(_TCLDIR)\generic\tcl.h

!endif # exist(...) && ! $(NEED_TCL_SOURCE)
!endif # exist(...) && !$(NEED_TCL_SOURCE)

!endif # TCLDIR

!ifndef _TCL_H
MSG =^
Failed to find tcl.h. The TCLDIR macro is set incorrectly or is not set and default path does not contain tcl.h.
!error $(MSG)
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
411
412
413
414
415
416
417



418
419
420
421
422
423
424







-
-
-







#     compiler version 1200. This is kept only for legacy reasons as it
#     does not make sense for recent Microsoft compilers. Only used for
#     output directory names.
# ARCH - set to IX86 or AMD64 depending on 32- or 64-bit target
# NATIVE_ARCH - set to IX86 or AMD64 for the host machine
# MACHINE - same as $(ARCH) - legacy
# _VC_MANIFEST_EMBED_{DLL,EXE} - commands for embedding a manifest if needed
# CFG_ENCODING - set to an character encoding.
#   TBD - this is passed to compiler as TCL_CFGVAL_ENCODING but can't
#   see where it is used

cc32		= $(CC)   # built-in default.
link32		= link
lib32		= lib
rc32		= $(RC)   # built-in default.

#----------------------------------------------------------------
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517

518
519
520
521
522
523
524
496
497
498
499
500
501
502




503
504
505
506
507
508
509

510
511
512
513
514
515
516
517







-
-
-
-







-
+








# Since MSVC8 we must deal with manifest resources.
!if $(VCVERSION) >= 1400
_VC_MANIFEST_EMBED_EXE=if exist [email protected] mt -nologo -manifest [email protected] -outputresource:$@;1
_VC_MANIFEST_EMBED_DLL=if exist [email protected] mt -nologo -manifest [email protected] -outputresource:$@;2
!endif

!ifndef CFG_ENCODING
CFG_ENCODING	= \"cp1252\"
!endif

################################################################
# 4. Build the nmakehlp program
# This is a helper app we need to overcome nmake's limiting
# environment. We will call out to it to get various bits of
# information about supported compiler options etc.
#
# Tcl itself will always use the nmakehlp.c program which is
# in its own source. This is the "master" copy and kept updated.
# in its own source. It will be kept updated there.
#
# Extensions built against an installed Tcl will use the installed
# copy of Tcl's nmakehlp.c if there is one and their own version
# otherwise. In the latter case, they would also be using their own
# rules.vc. Note that older versions of Tcl do not install nmakehlp.c
# or rules.vc.
#
533
534
535
536
537
538
539
540

541
542
543
544
545
546
547
526
527
528
529
530
531
532

533
534
535
536
537
538
539
540







-
+







NMAKEHLPC = nmakehlp.c

!if !$(DOING_TCL)
!if $(TCLINSTALL)
!if exist("$(_TCLDIR)\lib\nmake\nmakehlp.c")
NMAKEHLPC = $(_TCLDIR)\lib\nmake\nmakehlp.c
!endif
!else # ! $(TCLINSTALL)
!else # !$(TCLINSTALL)
!if exist("$(_TCLDIR)\win\nmakehlp.c")
NMAKEHLPC = $(_TCLDIR)\win\nmakehlp.c
!endif
!endif # $(TCLINSTALL)
!endif # !$(DOING_TCL)

!endif # NMAKEHLPC
655
656
657
658
659
660
661


























































































































662
663

664
665
666
667
668
669
670
671
672
673
674
675
676

677
678
679


680
681
682
683
684
685
686
687
688

689

690
691
692
693
694
695
696
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777

778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793


794
795
796
797
798
799
800
801
802
803

804
805
806
807
808
809
810
811
812
813







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+













+

-
-
+
+








-
+

+







# If compiler has enabled link time optimization, linker must too with -ltcg
!ifdef CC_GL_OPT_ENABLED
!if [nmakehlp -l -ltcg $(LINKER_TESTFLAGS)]
LINKERFLAGS     = $(LINKERFLAGS) -ltcg
!endif
!endif


################################################################
# 6. Extract various version numbers from headers
# For Tcl and Tk, version numbers are extracted from tcl.h and tk.h
# respectively. For extensions, versions are extracted from the
# configure.in or configure.ac from the TEA configuration if it
# exists, and unset otherwise.
# Sets the following macros:
# TCL_MAJOR_VERSION
# TCL_MINOR_VERSION
# TCL_RELEASE_SERIAL
# TCL_PATCH_LEVEL
# TCL_PATCH_LETTER
# TCL_VERSION
# TK_MAJOR_VERSION
# TK_MINOR_VERSION
# TK_RELEASE_SERIAL
# TK_PATCH_LEVEL
# TK_PATCH_LETTER
# TK_VERSION
# DOTVERSION - set as (for example) 2.5
# VERSION - set as (for example 25)
#--------------------------------------------------------------

!if [echo REM = This file is generated from rules.vc > versions.vc]
!endif
!if [echo TCL_MAJOR_VERSION = \>> versions.vc] \
   && [nmakehlp -V "$(_TCL_H)" TCL_MAJOR_VERSION >> versions.vc]
!endif
!if [echo TCL_MINOR_VERSION = \>> versions.vc] \
   && [nmakehlp -V "$(_TCL_H)" TCL_MINOR_VERSION >> versions.vc]
!endif
!if [echo TCL_RELEASE_SERIAL = \>> versions.vc] \
   && [nmakehlp -V "$(_TCL_H)" TCL_RELEASE_SERIAL >> versions.vc]
!endif
!if [echo TCL_PATCH_LEVEL = \>> versions.vc] \
   && [nmakehlp -V "$(_TCL_H)" TCL_PATCH_LEVEL >> versions.vc]
!endif

!if defined(_TK_H)
!if [echo TK_MAJOR_VERSION = \>> versions.vc] \
   && [nmakehlp -V $(_TK_H) TK_MAJOR_VERSION >> versions.vc]
!endif
!if [echo TK_MINOR_VERSION = \>> versions.vc] \
   && [nmakehlp -V $(_TK_H) TK_MINOR_VERSION >> versions.vc]
!endif
!if [echo TK_RELEASE_SERIAL = \>> versions.vc] \
   && [nmakehlp -V "$(_TK_H)" TK_RELEASE_SERIAL >> versions.vc]
!endif
!if [echo TK_PATCH_LEVEL = \>> versions.vc] \
   && [nmakehlp -V $(_TK_H) TK_PATCH_LEVEL >> versions.vc]
!endif
!endif # _TK_H

!include versions.vc

TCL_VERSION	= $(TCL_MAJOR_VERSION)$(TCL_MINOR_VERSION)
TCL_DOTVERSION	= $(TCL_MAJOR_VERSION).$(TCL_MINOR_VERSION)
!if [nmakehlp -f $(TCL_PATCH_LEVEL) "a"]
TCL_PATCH_LETTER = a
!elseif [nmakehlp -f $(TCL_PATCH_LEVEL) "b"]
TCL_PATCH_LETTER = b
!else
TCL_PATCH_LETTER = .
!endif

!if defined(_TK_H)

TK_VERSION	= $(TK_MAJOR_VERSION)$(TK_MINOR_VERSION)
TK_DOTVERSION	= $(TK_MAJOR_VERSION).$(TK_MINOR_VERSION)
!if [nmakehlp -f $(TK_PATCH_LEVEL) "a"]
TK_PATCH_LETTER = a
!elseif [nmakehlp -f $(TK_PATCH_LEVEL) "b"]
TK_PATCH_LETTER = b
!else
TK_PATCH_LETTER = .
!endif

!endif

# Set DOTVERSION and VERSION
!if $(DOING_TCL)

DOTVERSION = $(TCL_MAJOR_VERSION).$(TCL_MINOR_VERSION)
VERSION = $(TCL_VERSION)

!elseif $(DOING_TK)

DOTVERSION = $(TK_DOTVERSION)
VERSION = $(TK_VERSION)

!else # Doing a non-Tk extension

# If parent makefile has not defined DOTVERSION, try to get it from TEA
# first from a configure.in file, and then from configure.ac
!ifndef DOTVERSION
!if [echo DOTVERSION = \> versions.vc] \
   || [nmakehlp -V $(ROOT)\configure.in ^[$(PROJECT)^] >> versions.vc]
!if [echo DOTVERSION = \> versions.vc] \
   || [nmakehlp -V $(ROOT)\configure.ac ^[$(PROJECT)^] >> versions.vc]
!error *** Could not figure out extension version. Please define DOTVERSION in parent makefile before including rules.vc.
!endif
!endif
!include versions.vc
!endif # DOTVERSION
VERSION         = $(DOTVERSION:.=)

!endif # $(DOING_TCL) ... etc.

# Windows RC files have 3 version components. Ensure this irrespective
# of how many components the package has specified. Basically, ensure
# minimum 4 components by appending 4 0's and then pick out the first 4.
# Also take care of the fact that DOTVERSION may have "a" or "b" instead
# of "." separating the version components.
DOTSEPARATED=$(DOTVERSION:a=.)
DOTSEPARATED=$(DOTSEPARATED:b=.)
!if [echo RCCOMMAVERSION = \> versions.vc] \
  || [for /f "tokens=1,2,3,4,5* delims=." %a in ("$(DOTSEPARATED).0.0.0.0") do echo %a,%b,%c,%d >> versions.vc]
!error *** Could not generate RCCOMMAVERSION ***
!endif
!include versions.vc

########################################################################
# 6. Parse the OPTS macro to work out the requested build configuration.
# 7. Parse the OPTS macro to work out the requested build configuration.
# Based on this, we will construct the actual switches to be passed to the
# compiler and linker using the macros defined in the previous section.
# The following macros are defined by this section based on OPTS
# STATIC_BUILD - 0 -> Tcl is to be built as a shared library
#                1 -> build as a static library and shell
# TCL_THREADS - legacy but always 1 on Windows since winsock requires it.
# DEBUG - 1 -> debug build, 0 -> release builds
# SYMBOLS - 1 -> generate PDB's, 0 -> no PDB's
# PROFILE - 1 -> generate profiling info, 0 -> no profiling
# PGO     - 1 -> profile based optimization, 0 -> no
# MSVCRT  - 1 -> link to dynamic C runtime even when building static Tcl build
#           0 -> link to static C runtime for static Tcl build.
#           Does not impact shared Tcl builds (STATIC_BUILD == 0)
#           Default: 1 for Tcl 8.7 and up, 0 otherwise.
# TCL_USE_STATIC_PACKAGES - 1 -> statically link the registry and dde extensions
#           in the Tcl shell. 0 -> keep them as shared libraries
#           Does not impact shared Tcl builds.
#           in the Tcl and Wish shell. 0 -> keep them as shared libraries. Does
#           not impact shared Tcl builds. Implied by STATIC_BUILD since Tcl 8.7.
# USE_THREAD_ALLOC - 1 -> Use a shared global free pool for allocation.
#           0 -> Use the non-thread allocator.
# UNCHECKED - 1 -> when doing a debug build with symbols, use the release
#           C runtime, 0 -> use the debug C runtime.
# USE_STUBS - 1 -> compile to use stubs interfaces, 0 -> direct linking
# CONFIG_CHECK - 1 -> check current build configuration against Tcl
#           configuration (ignored for Tcl itself)
# _USE_64BIT_TIME_T - forces a build using 64-bit time_t for 32-bit build
#           (CRT library should support this)
#           (CRT library should support this, not needed for Tcl 9.x)
# TCL_UTF_MAX=4 - forces a build allowing 4-byte UTF-8 sequences internally.
#           (Not needed for Tcl 9.x)
# Further, LINKERFLAGS are modified based on above.

# Default values for all the above
STATIC_BUILD	= 0
TCL_THREADS	= 1
DEBUG		= 0
SYMBOLS		= 0
725
726
727
728
729
730
731
732
733
734

735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757

758
759
760
761
762
763
764
765

766
767
768
769
770
771
772
842
843
844
845
846
847
848

849

850


851
852
853
854
855
856
857
858


859
860
861
862
863
864



865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883







-

-
+
-
-








-
-






-
-
-


+








+








!if [nmakehlp -f $(OPTS) "nomsvcrt"]
!message *** Doing nomsvcrt
MSVCRT		= 0
!else
!if [nmakehlp -f $(OPTS) "msvcrt"]
!message *** Doing msvcrt
MSVCRT		= 1
!else
!if !$(STATIC_BUILD)
!if $(TCL_MAJOR_VERSION) == 8 && $(TCL_MINOR_VERSION) < 7 && $(STATIC_BUILD)
MSVCRT		= 1
!else
MSVCRT		= 0
!endif
!endif
!endif # [nmakehlp -f $(OPTS) "nomsvcrt"]

!if [nmakehlp -f $(OPTS) "staticpkg"] && $(STATIC_BUILD)
!message *** Doing staticpkg
TCL_USE_STATIC_PACKAGES	= 1
!else
TCL_USE_STATIC_PACKAGES	= 0
!endif

!if [nmakehlp -f $(OPTS) "nothreads"]
!message *** Compile explicitly for non-threaded tcl
TCL_THREADS = 0
USE_THREAD_ALLOC= 0
!else
TCL_THREADS    = 1
USE_THREAD_ALLOC= 1
!endif

!if $(TCL_MAJOR_VERSION) == 8
!if [nmakehlp -f $(OPTS) "time64bit"]
!message *** Force 64-bit time_t
_USE_64BIT_TIME_T = 1
!endif

!if [nmakehlp -f $(OPTS) "utfmax"]
!message *** Force allowing 4-byte UTF-8 sequences internally
TCL_UTF_MAX = 4
!endif
!endif

# Yes, it's weird that the "symbols" option controls DEBUG and
# the "pdbs" option controls SYMBOLS. That's historical.
!if [nmakehlp -f $(OPTS) "symbols"]
!message *** Doing symbols
DEBUG		= 1
844
845
846
847
848
849
850
851

852
853
854
855
856
857
858
955
956
957
958
959
960
961

962
963
964
965
966
967
968
969







-
+







MSG=^
This compiler does not support profile guided optimization.
!error $(MSG)
!endif
!endif

################################################################
# 7. Parse the STATS macro to configure code instrumentation
# 8. Parse the STATS macro to configure code instrumentation
# The following macros are set by this section:
# TCL_MEM_DEBUG - 1 -> enables memory allocation instrumentation
#                 0 -> disables
# TCL_COMPILE_DEBUG - 1 -> enables byte compiler logging
#                     0 -> disables

# Default both are off
874
875
876
877
878
879
880
881

882
883
884
885
886
887
888
985
986
987
988
989
990
991

992
993
994
995
996
997
998
999







-
+







!else
TCL_COMPILE_DEBUG   = 0
!endif

!endif

####################################################################
# 8. Parse the CHECKS macro to configure additional compiler checks
# 9. Parse the CHECKS macro to configure additional compiler checks
# The following macros are set by this section:
# WARNINGS - compiler switches that control the warnings level
# TCL_NO_DEPRECATED - 1 -> disable support for deprecated functions
#                     0 -> enable deprecated functions

# Defaults - Permit deprecated functions and warning level 3
TCL_NO_DEPRECATED	    = 0
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1017
1018
1019
1020
1021
1022
1023





























































































1024
1025
1026
1027
1028
1029
1030







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







!if [nmakehlp -f $(CHECKS) "64bit"] && [nmakehlp -c -Wp64]
!message *** Doing 64bit portability warnings
WARNINGS		    = $(WARNINGS) -Wp64
!endif

!endif

################################################################
# 9. Extract various version numbers
# For Tcl and Tk, version numbers are extracted from tcl.h and tk.h
# respectively. For extensions, versions are extracted from the
# configure.in or configure.ac from the TEA configuration if it
# exists, and unset otherwise.
# Sets the following macros:
# TCL_MAJOR_VERSION
# TCL_MINOR_VERSION
# TCL_PATCH_LEVEL
# TCL_VERSION
# TK_MAJOR_VERSION
# TK_MINOR_VERSION
# TK_PATCH_LEVEL
# TK_VERSION
# DOTVERSION - set as (for example) 2.5
# VERSION - set as (for example 25)
#--------------------------------------------------------------

!if [echo REM = This file is generated from rules.vc > versions.vc]
!endif
!if [echo TCL_MAJOR_VERSION = \>> versions.vc] \
   && [nmakehlp -V "$(_TCL_H)" TCL_MAJOR_VERSION >> versions.vc]
!endif
!if [echo TCL_MINOR_VERSION = \>> versions.vc] \
   && [nmakehlp -V "$(_TCL_H)" TCL_MINOR_VERSION >> versions.vc]
!endif
!if [echo TCL_PATCH_LEVEL = \>> versions.vc] \
   && [nmakehlp -V "$(_TCL_H)" TCL_PATCH_LEVEL >> versions.vc]
!endif

!if defined(_TK_H)
!if [echo TK_MAJOR_VERSION = \>> versions.vc] \
   && [nmakehlp -V $(_TK_H) TK_MAJOR_VERSION >> versions.vc]
!endif
!if [echo TK_MINOR_VERSION = \>> versions.vc] \
   && [nmakehlp -V $(_TK_H) TK_MINOR_VERSION >> versions.vc]
!endif
!if [echo TK_PATCH_LEVEL = \>> versions.vc] \
   && [nmakehlp -V $(_TK_H) TK_PATCH_LEVEL >> versions.vc]
!endif
!endif # _TK_H

!include versions.vc

TCL_VERSION	= $(TCL_MAJOR_VERSION)$(TCL_MINOR_VERSION)
TCL_DOTVERSION	= $(TCL_MAJOR_VERSION).$(TCL_MINOR_VERSION)
!if defined(_TK_H)
TK_VERSION	= $(TK_MAJOR_VERSION)$(TK_MINOR_VERSION)
TK_DOTVERSION	= $(TK_MAJOR_VERSION).$(TK_MINOR_VERSION)
!endif

# Set DOTVERSION and VERSION
!if $(DOING_TCL)

DOTVERSION = $(TCL_MAJOR_VERSION).$(TCL_MINOR_VERSION)
VERSION = $(TCL_VERSION)

!elseif $(DOING_TK)

DOTVERSION = $(TK_DOTVERSION)
VERSION = $(TK_VERSION)

!else # Doing a non-Tk extension

# If parent makefile has not defined DOTVERSION, try to get it from TEA
# first from a configure.in file, and then from configure.ac
!ifndef DOTVERSION
!if [echo DOTVERSION = \> versions.vc] \
   || [nmakehlp -V $(ROOT)\configure.in ^[$(PROJECT)^] >> versions.vc]
!if [echo DOTVERSION = \> versions.vc] \
   || [nmakehlp -V $(ROOT)\configure.ac ^[$(PROJECT)^] >> versions.vc]
!error *** Could not figure out extension version. Please define DOTVERSION in parent makefile before including rules.vc.
!endif
!endif
!include versions.vc
!endif # DOTVERSION
VERSION         = $(DOTVERSION:.=)

!endif # $(DOING_TCL) ... etc.

# Windows RC files have 3 version components. Ensure this irrespective
# of how many components the package has specified. Basically, ensure
# minimum 4 components by appending 4 0's and then pick out the first 4.
# Also take care of the fact that DOTVERSION may have "a" or "b" instead
# of "." separating the version components.
DOTSEPARATED=$(DOTVERSION:a=.)
DOTSEPARATED=$(DOTSEPARATED:b=.)
!if [echo RCCOMMAVERSION = \> versions.vc] \
  || [for /f "tokens=1,2,3,4,5* delims=." %a in ("$(DOTSEPARATED).0.0.0.0") do echo %a,%b,%c,%d >> versions.vc]
!error *** Could not generate RCCOMMAVERSION ***
!endif
!include versions.vc

################################################################
# 10. Construct output directory and file paths
# Figure-out how to name our intermediate and output directories.
# In order to avoid inadvertent mixing of object files built using
# different compilers, build configurations etc.,
#
1044
1045
1046
1047
1048
1049
1050
1051

1052
1053
1054
1055
1056
1057
1058
1062
1063
1064
1065
1066
1067
1068

1069
1070
1071
1072
1073
1074
1075
1076







-
+







!if "$(MACHINE)" != "IX86"
BUILDDIRTOP =$(BUILDDIRTOP)_$(MACHINE)
!endif
!if $(VCVER) > 6
BUILDDIRTOP =$(BUILDDIRTOP)_VC$(VCVER)
!endif

!if !$(DEBUG) || $(DEBUG) && $(UNCHECKED)
!if !$(DEBUG) || $(TCL_VERSION) > 86 || $(DEBUG) && $(UNCHECKED)
SUFX	    = $(SUFX:g=)
!endif

TMP_DIRFULL = .\$(BUILDDIRTOP)\$(PROJECT)_ThreadedDynamicStaticX

!if !$(STATIC_BUILD)
TMP_DIRFULL = $(TMP_DIRFULL:Static=)
1095
1096
1097
1098
1099
1100
1101

1102

1103












1104

1105
1106
1107
1108
1109

1110
1111
1112
1113
1114
1115

1116
1117
1118
1119
1120
1121
1122
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122

1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147

1148
1149
1150
1151
1152
1153
1154
1155







+

+
-
+
+
+
+
+
+
+
+
+
+
+
+

+





+





-
+







!error *** Could not fully qualify path TMP_DIR=$(TMP_DIR)
!endif
!include nmakehlp.out

# The name of the stubs library for the project being built
STUBPREFIX      = $(PROJECT)stub

#
# Set up paths to various Tcl executables and libraries needed by extensions
#
!if $(DOING_TCL)

# TIP 430. Unused for 8.6 but no harm defining it to allow a common rules.vc
!if "$(TCL_PATCH_LETTER)" == "."
TCLSCRIPTZIPNAME = libtcl_$(TCL_MAJOR_VERSION)_$(TCL_MINOR_VERSION)_$(TCL_RELEASE_SERIAL).zip
!else
TCLSCRIPTZIPNAME = libtcl_$(TCL_MAJOR_VERSION)_$(TCL_MINOR_VERSION)_$(TCL_PATCH_LETTER)$(TCL_RELEASE_SERIAL).zip
!endif
!if "$(TK_PATCH_LETTER)" == "."
TKSCRIPTZIPNAME = libtk_$(TK_MAJOR_VERSION)_$(TK_MINOR_VERSION)_$(TK_RELEASE_SERIAL).zip
!else
TKSCRIPTZIPNAME = libtk_$(TK_MAJOR_VERSION)_$(TK_MINOR_VERSION)_$(TK_PATCH_LETTER)$(TK_RELEASE_SERIAL).zip
!endif

!if $(DOING_TCL)
TCLSHNAME       = $(PROJECT)sh$(VERSION)$(SUFX).exe
TCLSH		= $(OUT_DIR)\$(TCLSHNAME)
TCLIMPLIB	= $(OUT_DIR)\$(PROJECT)$(VERSION)$(SUFX).lib
TCLLIBNAME	= $(PROJECT)$(VERSION)$(SUFX).$(EXT)
TCLLIB		= $(OUT_DIR)\$(TCLLIBNAME)
TCLSCRIPTZIP    = $(OUT_DIR)\$(TCLSCRIPTZIPNAME)

TCLSTUBLIBNAME	= $(STUBPREFIX)$(VERSION).lib
TCLSTUBLIB	= $(OUT_DIR)\$(TCLSTUBLIBNAME)
TCL_INCLUDES    = -I"$(WIN_DIR)" -I"$(GENERICDIR)"

!else # ! $(DOING_TCL)
!else # !$(DOING_TCL)

!if $(TCLINSTALL) # Building against an installed Tcl

# When building extensions, we need to locate tclsh. Depending on version
# of Tcl we are building against, this may or may not have a "t" suffix.
# Try various possibilities in turn.
TCLSH		= $(_TCLDIR)\bin\tclsh$(TCL_VERSION)$(SUFX:t=).exe
1130
1131
1132
1133
1134
1135
1136

1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155

1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197







+



















+







# "t" suffix (e.g. 8.5 or 8.7). If lib not found check for that possibility.
!if !exist("$(TCLIMPLIB)")
TCLIMPLIB	= $(_TCLDIR)\lib\tcl$(TCL_VERSION)t$(SUFX:t=).lib
!endif
TCL_LIBRARY	= $(_TCLDIR)\lib
TCLREGLIB	= $(_TCLDIR)\lib\tclreg13$(SUFX:t=).lib
TCLDDELIB	= $(_TCLDIR)\lib\tcldde14$(SUFX:t=).lib
TCLSCRIPTZIP	= $(_TCLDIR)\lib\$(TCLSCRIPTZIPNAME)
TCLTOOLSDIR	= \must\have\tcl\sources\to\build\this\target
TCL_INCLUDES    = -I"$(_TCLDIR)\include"

!else # Building against Tcl sources

TCLSH		= $(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)$(SUFX:t=).exe
!if !exist($(TCLSH))
TCLSH		= $(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)t$(SUFX:t=).exe
!endif
TCLSTUBLIB	= $(_TCLDIR)\win\$(BUILDDIRTOP)\tclstub$(TCL_VERSION).lib
TCLIMPLIB	= $(_TCLDIR)\win\$(BUILDDIRTOP)\tcl$(TCL_VERSION)$(SUFX:t=).lib
# When building extensions, may be linking against Tcl that does not add
# "t" suffix (e.g. 8.5 or 8.7). If lib not found check for that possibility.
!if !exist("$(TCLIMPLIB)")
TCLIMPLIB	= $(_TCLDIR)\win\$(BUILDDIRTOP)\tcl$(TCL_VERSION)t$(SUFX:t=).lib
!endif
TCL_LIBRARY	= $(_TCLDIR)\library
TCLREGLIB	= $(_TCLDIR)\win\$(BUILDDIRTOP)\tclreg13$(SUFX:t=).lib
TCLDDELIB	= $(_TCLDIR)\win\$(BUILDDIRTOP)\tcldde14$(SUFX:t=).lib
TCLSCRIPTZIP	= $(_TCLDIR)\win\$(BUILDDIRTOP)\$(TCLSCRIPTZIPNAME)
TCLTOOLSDIR	= $(_TCLDIR)\tools
TCL_INCLUDES	= -I"$(_TCLDIR)\generic" -I"$(_TCLDIR)\win"

!endif # TCLINSTALL

tcllibs = "$(TCLSTUBLIB)" "$(TCLIMPLIB)"

1181
1182
1183
1184
1185
1186
1187
1188


1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202


1203

1204
1205
1206
1207
1208
1209
1210
1211
1212
1213


1214

1215
1216
1217
1218
1219
1220
1221
1216
1217
1218
1219
1220
1221
1222

1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263







-
+
+














+
+

+










+
+

+







TKIMPLIBNAME	= tk$(TK_VERSION)$(SUFX).lib

!if $(DOING_TK)
WISH 		= $(OUT_DIR)\$(WISHNAME)
TKSTUBLIB	= $(OUT_DIR)\$(TKSTUBLIBNAME)
TKIMPLIB	= $(OUT_DIR)\$(TKIMPLIBNAME)
TKLIB		= $(OUT_DIR)\$(TKLIBNAME)
TK_INCLUDES    = -I"$(WIN_DIR)" -I"$(GENERICDIR)"
TK_INCLUDES     = -I"$(WIN_DIR)" -I"$(GENERICDIR)"
TKSCRIPTZIP     = $(OUT_DIR)\$(TKSCRIPTZIPNAME)

!else # effectively NEED_TK

!if $(TKINSTALL) # Building against installed Tk
WISH		= $(_TKDIR)\bin\$(WISHNAME)
TKSTUBLIB	= $(_TKDIR)\lib\$(TKSTUBLIBNAME)
TKIMPLIB	= $(_TKDIR)\lib\$(TKIMPLIBNAME)
# When building extensions, may be linking against Tk that does not add
# "t" suffix (e.g. 8.5 or 8.7). If lib not found check for that possibility.
!if !exist("$(TKIMPLIB)")
TKIMPLIBNAME	= tk$(TK_VERSION)$(SUFX:t=).lib
TKIMPLIB	= $(_TKDIR)\lib\$(TKIMPLIBNAME)
!endif
TK_INCLUDES     = -I"$(_TKDIR)\include"
TKSCRIPTZIP     = $(_TKDIR)\lib\$(TKSCRIPTZIPNAME)

!else # Building against Tk sources

WISH		= $(_TKDIR)\win\$(BUILDDIRTOP)\$(WISHNAME)
TKSTUBLIB	= $(_TKDIR)\win\$(BUILDDIRTOP)\$(TKSTUBLIBNAME)
TKIMPLIB	= $(_TKDIR)\win\$(BUILDDIRTOP)\$(TKIMPLIBNAME)
# When building extensions, may be linking against Tk that does not add
# "t" suffix (e.g. 8.5 or 8.7). If lib not found check for that possibility.
!if !exist("$(TKIMPLIB)")
TKIMPLIBNAME	= tk$(TK_VERSION)$(SUFX:t=).lib
TKIMPLIB	= $(_TKDIR)\win\$(BUILDDIRTOP)\$(TKIMPLIBNAME)
!endif
TK_INCLUDES     = -I"$(_TKDIR)\generic" -I"$(_TKDIR)\win" -I"$(_TKDIR)\xlib"
TKSCRIPTZIP     = $(_TKDIR)\win\$(BUILDDIRTOP)\$(TKSCRIPTZIPNAME)

!endif # TKINSTALL

tklibs = "$(TKSTUBLIB)" "$(TKIMPLIB)"

!endif # $(DOING_TK)
!endif # $(DOING_TK) || $(NEED_TK)

# Various output paths
PRJIMPLIB	= $(OUT_DIR)\$(PROJECT)$(VERSION)$(SUFX).lib
1248
1249
1250
1251
1252
1253
1254

1255
1256
1257
1258
1259
1260
1261
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304







+








!if $(DOING_TCL) || $(DOING_TK)
LIB_INSTALL_DIR		= $(_INSTALLDIR)\lib
BIN_INSTALL_DIR		= $(_INSTALLDIR)\bin
DOC_INSTALL_DIR		= $(_INSTALLDIR)\doc
!if $(DOING_TCL)
SCRIPT_INSTALL_DIR	= $(_INSTALLDIR)\lib\$(PROJECT)$(TCL_MAJOR_VERSION).$(TCL_MINOR_VERSION)
MODULE_INSTALL_DIR	= $(_INSTALLDIR)\lib\tcl$(TCL_MAJOR_VERSION)
!else # DOING_TK
SCRIPT_INSTALL_DIR	= $(_INSTALLDIR)\lib\$(PROJECT)$(TK_MAJOR_VERSION).$(TK_MINOR_VERSION)
!endif
DEMO_INSTALL_DIR	= $(SCRIPT_INSTALL_DIR)\demos
INCLUDE_INSTALL_DIR	= $(_INSTALLDIR)\include

!else # extension other than Tk
1292
1293
1294
1295
1296
1297
1298
1299
1300


1301
1302
1303
1304
1305
1306
1307
1335
1336
1337
1338
1339
1340
1341


1342
1343
1344
1345
1346
1347
1348
1349
1350







-
-
+
+







# lflags - complete linker switches (subsumes ldebug) except subsystem type
# dlllflags - complete linker switches to build DLLs (subsumes lflags)
# conlflags - complete linker switches for console program (subsumes lflags)
# guilflags - complete linker switches for GUI program (subsumes lflags)
# baselibs - minimum Windows libraries required. Parent makefile can
#    define PRJ_LIBS before including rules.rc if additional libs are needed

OPTDEFINES	= /DTCL_CFGVAL_ENCODING=$(CFG_ENCODING) /DSTDC_HEADERS
!if $(VCVERSION) >= 1600
OPTDEFINES	= /DSTDC_HEADERS
!if $(VCVERSION) > 1600
OPTDEFINES	= $(OPTDEFINES) /DHAVE_STDINT_H=1
!else
OPTDEFINES	= $(OPTDEFINES) /DMP_NO_STDINT=1
!endif
!if $(VCVERSION) >= 1800
OPTDEFINES	= $(OPTDEFINES) /DHAVE_INTTYPES_H=1 /DHAVE_STDBOOL_H=1
!endif
1329
1330
1331
1332
1333
1334
1335
1336

1337
1338
1339
1340
1341
1342
1343
1372
1373
1374
1375
1376
1377
1378

1379
1380
1381
1382
1383
1384
1385
1386







-
+







!if $(TCL_NO_DEPRECATED)
OPTDEFINES	= $(OPTDEFINES) /DTCL_NO_DEPRECATED
!endif

!if $(USE_STUBS)
# Note we do not define USE_TCL_STUBS even when building tk since some
# test targets in tk do not use stubs
!if ! $(DOING_TCL)
!if !$(DOING_TCL)
USE_STUBS_DEFS  = /DUSE_TCL_STUBS /DUSE_TCLOO_STUBS
!if $(NEED_TK)
USE_STUBS_DEFS  = $(USE_STUBS_DEFS) /DUSE_TK_STUBS
!endif
!endif
!endif # USE_STUBS

1353
1354
1355
1356
1357
1358
1359

1360
1361
1362
1363
1364
1365
1366
1367
1368

1369
1370
1371
1372
1373
1374
1375
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420







+









+







!if "$(MACHINE)" == "AMD64"
OPTDEFINES	= $(OPTDEFINES) /DTCL_CFG_DO64BIT
!endif
!if $(VCVERSION) < 1300
OPTDEFINES	= $(OPTDEFINES) /DNO_STRTOI64=1
!endif

!if "$(TCL_MAJOR_VERSION)" == "8"
!if "$(_USE_64BIT_TIME_T)" == "1"
OPTDEFINES	= $(OPTDEFINES) /D_USE_64BIT_TIME_T=1
!endif
!if "$(TCL_UTF_MAX)" == "4"
OPTDEFINES	= $(OPTDEFINES) /DTCL_UTF_MAX=4
!endif

# _ATL_XP_TARGETING - Newer SDK's need this to build for XP
COMPILERFLAGS  = /D_ATL_XP_TARGETING
!endif

# Like the TEA system only set this non empty for non-Tk extensions
# Note: some extensions use PACKAGE_NAME and others use PACKAGE_TCLNAME
# so we pass both
!if !$(DOING_TCL) && !$(DOING_TK)
PKGNAMEFLAGS = /DPACKAGE_NAME="\"$(PRJ_PACKAGE_TCLNAME)\"" \
               /DPACKAGE_TCLNAME="\"$(PRJ_PACKAGE_TCLNAME)\"" \
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1531
1532
1533
1534
1535
1536
1537












1538
1539
1540
1541
1542
1543
1544







-
-
-
-
-
-
-
-
-
-
-
-







### Declarations common to all linker versions
lflags	= -nologo -machine:$(MACHINE) $(LINKERFLAGS) $(ldebug)

!if $(MSVCRT) && !($(DEBUG) && !$(UNCHECKED)) && $(VCVERSION) >= 1900
lflags	= $(lflags) -nodefaultlib:libucrt.lib
!endif

# Old linkers (Visual C++ 6 in particular) will link for fast loading
# on Win98. Since we do not support Win98 any more, we specify nowin98
# as recommended for NT and later. However, this is only required by
# IX86 on older compilers and only needed if we are not doing a static build.

!if "$(MACHINE)" == "IX86" && !$(STATIC_BUILD)
!if [nmakehlp -l -opt:nowin98 $(LINKER_TESTFLAGS)]
# Align sections for PE size savings.
lflags	= $(lflags) -opt:nowin98
!endif
!endif

dlllflags = $(lflags) -dll
conlflags = $(lflags) -subsystem:console
guilflags = $(lflags) -subsystem:windows

# Libraries that are required for every image.
# Extensions should define any additional libraries with $(PRJ_LIBS)
winlibs   = kernel32.lib advapi32.lib
1555
1556
1557
1558
1559
1560
1561
1562

1563
1564
1565
1566

1567
1568
1569
1570
1571
1572
1573
1588
1589
1590
1591
1592
1593
1594

1595
1596
1597
1598

1599
1600
1601
1602
1603
1604
1605
1606







-
+



-
+







!endif

default-target: $(DEFAULT_BUILD_TARGET)

!if $(MULTIPLATFORM_INSTALL)
default-pkgindex:
	@echo package ifneeded $(PRJ_PACKAGE_TCLNAME) $(DOTVERSION) \
	    [list load [file join $$dir $(PLATFORM_IDENTIFY) $(PRJLIBNAME)]] > $(OUT_DIR)\pkgIndex.tcl
	    [list load [file join $$dir $(PLATFORM_IDENTIFY) $(PRJLIBNAME)] [string totitle $(PRJ_PACKAGE_TCLNAME)]] > $(OUT_DIR)\pkgIndex.tcl
!else
default-pkgindex:
	@echo package ifneeded $(PRJ_PACKAGE_TCLNAME) $(DOTVERSION) \
	    [list load [file join $$dir $(PRJLIBNAME)]] > $(OUT_DIR)\pkgIndex.tcl
	    [list load [file join $$dir $(PRJLIBNAME)] [string totitle $(PRJ_PACKAGE_TCLNAME)]] > $(OUT_DIR)\pkgIndex.tcl
!endif

default-pkgindex-tea:
	@if exist $(ROOT)\pkgIndex.tcl.in nmakehlp -s << $(ROOT)\pkgIndex.tcl.in > $(OUT_DIR)\pkgIndex.tcl
@PACKAGE_VERSION@    $(DOTVERSION)
@PACKAGE_NAME@       $(PRJ_PACKAGE_TCLNAME)
@PACKAGE_TCLNAME@    $(PRJ_PACKAGE_TCLNAME)
1604
1605
1606
1607
1608
1609
1610


1611
1612
1613
1614
1615
1616
1617
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652







+
+







	@if not exist "$(SCRIPT_INSTALL_DIR)" mkdir "$(SCRIPT_INSTALL_DIR)"
	@$(CPY) $(PRJSTUBLIB) "$(SCRIPT_INSTALL_DIR)" >NUL

default-install-pdbs:
	@echo Installing PDBs to '$(LIB_INSTALL_DIR)'
	@if not exist "$(LIB_INSTALL_DIR)" mkdir "$(LIB_INSTALL_DIR)"
	@$(CPY) "$(OUT_DIR)\*.pdb" "$(LIB_INSTALL_DIR)\"

# "emacs font-lock highlighting fix

default-install-docs-html:
	@echo Installing documentation files to '$(DOC_INSTALL_DIR)'
	@if not exist "$(DOC_INSTALL_DIR)" mkdir "$(DOC_INSTALL_DIR)"
	@if exist $(DOCDIR) for %f in ("$(DOCDIR)\*.html" "$(DOCDIR)\*.css" "$(DOCDIR)\*.png") do @$(COPY) %f "$(DOC_INSTALL_DIR)"

default-install-docs-n:
1667
1668
1669
1670
1671
1672
1673
1674

1675
1676
1677
1678
1679
1680
1681
1702
1703
1704
1705
1706
1707
1708

1709
1710
1711
1712
1713
1714
1715
1716







-
+







	@if exist $(LIBDIR) for %f in ("$(LIBDIR)\*.tcl") do @$(COPY) %f "$(OUT_DIR)"
	$(DEBUGGER) $(TCLSH)

# Generation of Windows version resource
!ifdef RCFILE

# Note: don't use $** in below rule because there may be other dependencies
# and only the "master" rc must be passed to the resource compiler
# and only the "main" rc must be passed to the resource compiler
$(TMP_DIR)\$(PROJECT).res: $(RCDIR)\$(PROJECT).rc
	$(RESCMD) $(RCDIR)\$(PROJECT).rc

!else

# If parent makefile has not defined a resource definition file,
# we will generate one from standard template.
1721
1722
1723
1724
1725
1726
1727
1728

1729
1730
1731
1732
1733
1734
1735
1756
1757
1758
1759
1760
1761
1762

1763
1764
1765
1766
1767
1768
1769
1770







-
+








!ifndef DISABLE_IMPLICIT_RULES
DISABLE_IMPLICIT_RULES = 0
!endif

!if !$(DISABLE_IMPLICIT_RULES)
# Implicit rule definitions - only for building library objects. For stubs and
# main application, the master makefile should define explicit rules.
# main application, the makefile should define explicit rules.

{$(ROOT)}.c{$(TMP_DIR)}.obj::
	$(CCPKGCMD) @<<
$<
<<

{$(WIN_DIR)}.c{$(TMP_DIR)}.obj::
1762
1763
1764
1765
1766
1767
1768
1769

1770
1771
1772
1773
1774
1775
1776
1777



1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798

1799
1800
1801
1802
1803
1804
1805
1797
1798
1799
1800
1801
1802
1803

1804
1805
1806
1807
1808
1809



1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832

1833
1834
1835
1836
1837
1838
1839
1840







-
+





-
-
-
+
+
+




















-
+







!endif

################################################################
# 14. Sanity check selected options against Tcl build options
# When building an extension, certain configuration options should
# match the ones used when Tcl was built. Here we check and
# warn on a mismatch.
!if ! $(DOING_TCL)
!if !$(DOING_TCL)

!if $(TCLINSTALL) # Building against an installed Tcl
!if exist("$(_TCLDIR)\lib\nmake\tcl.nmake")
TCLNMAKECONFIG = "$(_TCLDIR)\lib\nmake\tcl.nmake"
!endif
!else # ! $(TCLINSTALL) - building against Tcl source
!if exist("$(OUT_DIR)\tcl.nmake")
TCLNMAKECONFIG = "$(OUT_DIR)\tcl.nmake"
!else # !$(TCLINSTALL) - building against Tcl source
!if exist("$(_TCLDIR)\win\$(BUILDDIRTOP)\tcl.nmake")
TCLNMAKECONFIG	= "$(_TCLDIR)\win\$(BUILDDIRTOP)\tcl.nmake"
!endif
!endif # TCLINSTALL

!if $(CONFIG_CHECK)
!ifdef TCLNMAKECONFIG
!include $(TCLNMAKECONFIG)

!if defined(CORE_MACHINE) && "$(CORE_MACHINE)" != "$(MACHINE)"
!error ERROR: Build target ($(MACHINE)) does not match the Tcl library architecture ($(CORE_MACHINE)).
!endif
!if $(TCL_VERSION) < 87 && defined(CORE_USE_THREAD_ALLOC) && $(CORE_USE_THREAD_ALLOC) != $(USE_THREAD_ALLOC)
!message WARNING: Value of USE_THREAD_ALLOC ($(USE_THREAD_ALLOC)) does not match its Tcl core value ($(CORE_USE_THREAD_ALLOC)).
!endif
!if defined(CORE_DEBUG) && $(CORE_DEBUG) != $(DEBUG)
!message WARNING: Value of DEBUG ($(DEBUG)) does not match its Tcl library configuration ($(DEBUG)).
!endif
!endif

!endif # TCLNMAKECONFIG

!endif # ! $(DOING_TCL)
!endif # !$(DOING_TCL)


#----------------------------------------------------------
# Display stats being used.
#----------------------------------------------------------

!if !$(DOING_TCL)
Changes to win/stubs.c.
1

2
3
4
5
6
7
8
9
10


11
12
13
14
15
16
17
18
19
20
21
22
23



24
25
26
27
28
29
30
31




32

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49









50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68

69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95



96
97


98
99
100
101
102
103
104



105
106
107
108
109
110
111
112



113
114
115
116
117
118
119
120



121
122
123
124
125
126
127


128
129
130
131
132
133
134
135



136
137
138
139
140
141
142
143
144




145
146
147
148
149
150
151
152
153
154





155

156
157
158
159
160
161
162
163




164
165
166
167
168
169
170
171
172




173
174
175
176
177
178
179
180
181
182
183






184
185
186
187
188
189
190
191



192
193
194
195
196
197
198
199



200
201
202
203
204
205
206
207
208
209





210
211
212
213
214
215
216
217
218
219
220
221







222
223
224
225
226
227
228


229
230
231
232
233
234
235
236



237
238
239
240
241
242
243
244
245




246
247
248
249
250
251
252
253
254
255
256






257
258
259
260
261
262
263
264
265
266





267
268
269
270
271
272
273


274
275
276
277
278
279
280
281
282




283
284
285
286
287
288
289
290
291




292
293
294
295
296
297
298
299
300




301
302
303
304
305
306
307
308
309




310
311
312
313
314
315
316
317
318




319
320
321
322
323
324
325
326
327




328
329
330
331
332
333
334
335
336




337
338
339
340
341
342
343
344
345
346
347
348
349
350









351
352
353
354
355
356
357
358
359
360





361
362
363
364
365
366
367
368
369




370
371
372
373
374
375
376
377
378
379
380
381







382
383
384
385
386
387
388
389
390
391
392

393
394
395
396
397
398
399








400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415


416
417
418
419
420
421
422


423
424
425
426
427
428
429


430
431
432
433
434
435
436

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70













71
72
73
74
75
76
77













78
79
80
81
82
83





84
85
86


87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168

169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512

513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
-
+









+
+













+
+
+








+
+
+
+
-
+

















+
+
+
+
+
+
+
+
+



-
-
-
-
-
-
-
-
-
-
-
-
-



+



-
-
-
-
-
-
-
-
-
-
-
-
-






-
-
-
-
-
+
+
+
-
-
+
+







+
+
+








+
+
+








+
+
+







+
+








+
+
+









+
+
+
+










+
+
+
+
+
-
+








+
+
+
+









+
+
+
+











+
+
+
+
+
+








+
+
+








+
+
+










+
+
+
+
+












+
+
+
+
+
+
+







+
+








+
+
+









+
+
+
+











+
+
+
+
+
+










+
+
+
+
+







+
+









+
+
+
+









+
+
+
+









+
+
+
+









+
+
+
+









+
+
+
+









+
+
+
+









+
+
+
+














+
+
+
+
+
+
+
+
+










+
+
+
+
+









+
+
+
+












+
+
+
+
+
+
+










-
+







+
+
+
+
+
+
+
+
















+
+







+
+







+
+







#include "tk.h"
#include "tkInt.h"

/*
 * Undocumented Xlib internal function
 */

int
_XInitImageFuncPtrs(
    XImage *image)
{
    (void)image;

    return Success;
}

/*
 * From Xutil.h
 */

void
XSetWMClientMachine(
    Display *display,
    Window w,
    XTextProperty *text_prop)
{
	(void)display;
	(void)w;
	(void)text_prop;
}

Status
XStringListToTextProperty(
    char **list,
    int count,
    XTextProperty *text_prop_return)
{
    (void)list;
    (void)count;
    (void)text_prop_return;

    return (Status) 0;
    return Success;
}

/*
 * From Xlib.h
 */

int
XChangeProperty(
    Display *display,
    Window w,
    Atom property,
    Atom type,
    int format,
    int mode,
    _Xconst unsigned char *data,
    int nelements)
{
    (void)display;
    (void)w;
    (void)property;
    (void)type;
    (void)format;
    (void)mode;
    (void)data;
    (void)nelements;

    return Success;
}

Cursor
XCreateGlyphCursor(
    Display *display,
    Font source_font,
    Font mask_font,
    unsigned int source_char,
    unsigned int mask_char,
    XColor _Xconst *foreground_color,
    XColor _Xconst *background_color)
{
    return 1;
}

XIC
XCreateIC(XIM xim, ...)
{
    (void)xim;
    return NULL;
}

Cursor
XCreatePixmapCursor(
    Display *display,
    Pixmap source,
    Pixmap mask,
    XColor *foreground_color,
    XColor *background_color,
    unsigned int x,
    unsigned int y)
{
    return (Cursor) NULL;
}

int
XDeleteProperty(
    Display *display,
    Window w,
    Atom property)
{
    return Success;
}

void
XDestroyIC(
    (void)display;
    (void)w;
    (void)property;
    XIC ic)
{

    return Success;
}

Bool
XFilterEvent(
    XEvent *event,
    Window window)
{
    (void)event;
    (void)window;

    return 0;
}

int
XForceScreenSaver(
    Display *display,
    int mode)
{
    (void)display;
    (void)mode;

    return Success;
}

int
XFreeCursor(
    Display *display,
    Cursor cursor)
{
    (void)display;
    (void)cursor;

    return Success;
}

GContext
XGContextFromGC(
    GC gc)
{
    (void)gc;

    return (GContext) NULL;
}

char *
XGetAtomName(
    Display *display,
    Atom atom)
{
    (void)display;
    (void)atom;

    return NULL;
}

int
XGetWindowAttributes(
    Display *display,
    Window w,
    XWindowAttributes *window_attributes_return)
{
    (void)display;
    (void)w;
    (void)window_attributes_return;

    return Success;
}

Status
XGetWMColormapWindows(
    Display *display,
    Window w,
    Window **windows_return,
    int *count_return)
{
    (void)display;
    (void)w;
    (void)windows_return;
    (void)count_return;

    return (Status) 0;
    return Success;
}

int
XIconifyWindow(
    Display *display,
    Window w,
    int screen_number)
{
    (void)display;
    (void)w;
    (void)screen_number;

    return Success;
}

XHostAddress *
XListHosts(
    Display *display,
    int *nhosts_return,
    Bool *state_return)
{
    (void)display;
    (void)nhosts_return;
    (void)state_return;

    return NULL;
}

int
XLookupColor(
    Display *display,
    Colormap colormap,
    _Xconst char *color_name,
    XColor *exact_def_return,
    XColor *screen_def_return)
{
    (void)display;
    (void)colormap;
    (void)color_name;
    (void)exact_def_return;
    (void)screen_def_return;

    return Success;
}

int
XNextEvent(
    Display *display,
    XEvent *event_return)
{
    (void)display;
    (void)event_return;

    return Success;
}

int
XPutBackEvent(
    Display *display,
    XEvent *event)
{
    (void)display;
    (void)event;

    return Success;
}

int
XQueryColors(
    Display *display,
    Colormap colormap,
    XColor *defs_in_out,
    int ncolors)
{
    (void)display;
    (void)colormap;
    (void)defs_in_out;
    (void)ncolors;

    return Success;
}

int
XQueryTree(
    Display *display,
    Window w,
    Window *root_return,
    Window *parent_return,
    Window **children_return,
    unsigned int *nchildren_return)
{
    (void)display;
    (void)w;
    (void)root_return;
    (void)parent_return;
    (void)children_return;
    (void)nchildren_return;

    return Success;
}

int
XRefreshKeyboardMapping(
    XMappingEvent *event_map)
{
    (void)event_map;

    return Success;
}

Window
XRootWindow(
    Display *display,
    int screen_number)
{
    (void)display;
    (void)screen_number;

    return (Window) NULL;
}

int
XSelectInput(
    Display *display,
    Window w,
    long event_mask)
{
    (void)display;
    (void)w;
    (void)event_mask;

    return Success;
}

int
XSendEvent(
    Display *display,
    Window w,
    Bool propagate,
    long event_mask,
    XEvent *event_send)
{
    (void)display;
    (void)w;
    (void)propagate;
    (void)event_mask;
    (void)event_send;

    return Success;
}

int
XSetCommand(
    Display *display,
    Window w,
    char **argv,
    int argc)
{
    (void)display;
    (void)w;
    (void)argv;
    (void)argc;

    return Success;
}

XErrorHandler
XSetErrorHandler(
    XErrorHandler handler)
{
    (void)handler;

    return NULL;
}

int
XSetIconName(
    Display *display,
    Window w,
    _Xconst char *icon_name)
{
    (void)display;
    (void)w;
    (void)icon_name;

    return Success;
}

int
XSetWindowBackground(
    Display *display,
    Window w,
    unsigned long background_pixel)
{
    (void)display;
    (void)w;
    (void)background_pixel;

    return Success;
}

int
XSetWindowBackgroundPixmap(
    Display *display,
    Window w,
    Pixmap background_pixmap)
{
    (void)display;
    (void)w;
    (void)background_pixmap;

    return Success;
}

int
XSetWindowBorder(
    Display *display,
    Window w,
    unsigned long border_pixel)
{
    (void)display;
    (void)w;
    (void)border_pixel;

    return Success;
}

int
XSetWindowBorderPixmap(
    Display *display,
    Window w,
    Pixmap border_pixmap)
{
    (void)display;
    (void)w;
    (void)border_pixmap;

    return Success;
}

int
XSetWindowBorderWidth(
    Display *display,
    Window w,
    unsigned int width)
{
    (void)display;
    (void)w;
    (void)width;

    return Success;
}

int
XSetWindowColormap(
    Display *display,
    Window w,
    Colormap colormap)
{
    (void)display;
    (void)w;
    (void)colormap;

    return Success;
}

Bool
XTranslateCoordinates(
    Display *display,
    Window src_w,
    Window dest_w,
    int src_x,
    int src_y,
    int *dest_x_return,
    int *dest_y_return,
    Window *child_return)
{
    (void)display;
    (void)src_w;
    (void)dest_w;
    (void)src_x;
    (void)src_y;
    (void)dest_x_return;
    (void)dest_y_return;
    (void)child_return;

    return 0;
}

int
XWindowEvent(
    Display *display,
    Window w,
    long event_mask,
    XEvent *event_return)
{
    (void)display;
    (void)w;
    (void)event_mask;
    (void)event_return;

    return Success;
}

int
XWithdrawWindow(
    Display *display,
    Window w,
    int screen_number)
{
    (void)display;
    (void)w;
    (void)screen_number;

    return Success;
}

int
XmbLookupString(
    XIC ic,
    XKeyPressedEvent *event,
    char *buffer_return,
    int bytes_buffer,
    KeySym *keysym_return,
    Status *status_return)
{
    (void)ic;
    (void)event;
    (void)buffer_return;
    (void)bytes_buffer;
    (void)keysym_return;
    (void)status_return;

    return Success;
}

int
XGetWindowProperty(
    Display *display,
    Window w,
    Atom property,
    long long_offset,
    long long_length,
    Bool delete,
    Bool del,
    Atom req_type,
    Atom *actual_type_return,
    int *actual_format_return,
    unsigned long *nitems_return,
    unsigned long *bytes_after_return,
    unsigned char **prop_return)
{
    (void)display;
    (void)w;
    (void)property;
    (void)long_offset;
    (void)long_length;
    (void)del;
    (void)req_type;

    *actual_type_return = None;
    *actual_format_return = 0;
    *nitems_return = 0;
    *bytes_after_return = 0;
    *prop_return = NULL;
    return BadValue;
}

/*
 * The following functions were implemented as macros under Windows.
 */

int
XFlush(
    Display *display)
{
    (void)display;

    return 0;
}

int
XGrabServer(
    Display *display)
{
    (void)display;

    return 0;
}

int
XUngrabServer(
    Display *display)
{
    (void)display;

    return 0;
}

int
XFree(
    void *data)
{
449
450
451
452
453
454
455


456
457
458
459
460
461
462
463
464


465
466
467
468
469
470
471
472
473
474













584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626







+
+









+
+










+
+
+
+
+
+
+
+
+
+
+
+
+
}

XAfterFunction
XSynchronize(
    Display *display,
    Bool onoff)
{
    (void)onoff;

    display->request++;
    return NULL;
}

int
XSync(
    Display *display,
    Bool discard)
{
    (void)discard;

    display->request++;
    return 0;
}

VisualID
XVisualIDFromVisual(
    Visual *visual)
{
    return visual->visualid;
}

int
XOffsetRegion(
    Region rgn,
	int dx,
	int dy)
{
    (void)rgn;
    (void)dx;
    (void)dy;

	return 0;
}
Changes to win/tcl.m4.
24
25
26
27
28
29
30
31

32
33

34
35
36
37
38
39
40
24
25
26
27
28
29
30

31
32

33
34
35
36
37
38
39
40







-
+

-
+







    # the alternative search directory is invoked by --with-tcl
    #

    if test x"${no_tcl}" = x ; then
	# we reset no_tcl in case something fails here
	no_tcl=true
	AC_ARG_WITH(tcl,
	    AC_HELP_STRING([--with-tcl],
	    AS_HELP_STRING([--with-tcl],
		[directory containing tcl configuration (tclConfig.sh)]),
	    with_tclconfig="${withval}")
	    [with_tclconfig="${withval}"])
	AC_MSG_CHECKING([for Tcl configuration])
	AC_CACHE_VAL(ac_cv_c_tclconfig,[

	    # First check to see if --with-tcl was specified.
	    if test x"${with_tclconfig}" != x ; then
		case "${with_tclconfig}" in
		    */tclConfig.sh )
142
143
144
145
146
147
148
149

150
151

152
153
154
155
156
157
158
142
143
144
145
146
147
148

149
150

151
152
153
154
155
156
157
158







-
+

-
+







    # the alternative search directory is invoked by --with-tk
    #

    if test x"${no_tk}" = x ; then
	# we reset no_tk in case something fails here
	no_tk=true
	AC_ARG_WITH(tk,
	    AC_HELP_STRING([--with-tk],
	    AS_HELP_STRING([--with-tk],
		[directory containing tk configuration (tkConfig.sh)]),
	    with_tkconfig="${withval}")
	    [with_tkconfig="${withval}"])
	AC_MSG_CHECKING([for Tk configuration])
	AC_CACHE_VAL(ac_cv_c_tkconfig,[

	    # First check to see if --with-tkconfig was specified.
	    if test x"${with_tkconfig}" != x ; then
		case "${with_tkconfig}" in
		    */tkConfig.sh )
247
248
249
250
251
252
253

254
255
256
257
258
259
260
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261







+







#
# Results:
#
#	Substitutes the following vars:
#		TCL_BIN_DIR
#		TCL_SRC_DIR
#		TCL_LIB_FILE
#		TCL_ZIP_FILE
#
#------------------------------------------------------------------------

AC_DEFUN([SC_LOAD_TCLCONFIG], [
    AC_MSG_CHECKING([for existence of ${TCL_BIN_DIR}/tclConfig.sh])

    if test -f "${TCL_BIN_DIR}/tclConfig.sh" ; then
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297

298
299
300
301
302
303
304
276
277
278
279
280
281
282








283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298







-
-
-
-
-
-
-
-








+








    if test -f $TCL_BIN_DIR/Makefile ; then
        TCL_LIB_SPEC=${TCL_BUILD_LIB_SPEC}
        TCL_STUB_LIB_SPEC=${TCL_BUILD_STUB_LIB_SPEC}
        TCL_STUB_LIB_PATH=${TCL_BUILD_STUB_LIB_PATH}
    fi

    #
    # eval is required to do the TCL_DBGX substitution
    #

    eval "TCL_LIB_FILE=\"${TCL_LIB_FILE}\""
    eval "TCL_LIB_FLAG=\"${TCL_LIB_FLAG}\""
    eval "TCL_LIB_SPEC=\"${TCL_LIB_SPEC}\""

    eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\""
    eval "TCL_STUB_LIB_FLAG=\"${TCL_STUB_LIB_FLAG}\""
    eval "TCL_STUB_LIB_SPEC=\"${TCL_STUB_LIB_SPEC}\""

    AC_SUBST(TCL_VERSION)
    AC_SUBST(TCL_BIN_DIR)
    AC_SUBST(TCL_SRC_DIR)

    AC_SUBST(TCL_ZIP_FILE)
    AC_SUBST(TCL_LIB_FILE)
    AC_SUBST(TCL_LIB_FLAG)
    AC_SUBST(TCL_LIB_SPEC)

    AC_SUBST(TCL_STUB_LIB_FILE)
    AC_SUBST(TCL_STUB_LIB_FLAG)
    AC_SUBST(TCL_STUB_LIB_SPEC)
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418

419
420
421
422
423
424
425
354
355
356
357
358
359
360








361
362
363
364
365
366
367
368




































369
370
371
372
373
374
375
376







-
-
-
-
-
-
-
-








-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+







#------------------------------------------------------------------------

AC_DEFUN([SC_ENABLE_SHARED], [
    AC_MSG_CHECKING([how to build libraries])
    AC_ARG_ENABLE(shared,
	[  --enable-shared         build and link with shared libraries (default: on)],
	[tcl_ok=$enableval], [tcl_ok=yes])

    if test "${enable_shared+set}" = set; then
	enableval="$enable_shared"
	tcl_ok=$enableval
    else
	tcl_ok=yes
    fi

    if test "$tcl_ok" = "yes" ; then
	AC_MSG_RESULT([shared])
	SHARED_BUILD=1
    else
	AC_MSG_RESULT([static])
	SHARED_BUILD=0
	AC_DEFINE(STATIC_BUILD, 1, [Is this a static build?])
    fi
])

#------------------------------------------------------------------------
# SC_ENABLE_THREADS --
#
#	Specify if thread support should be enabled
#
# Arguments:
#	none
#
# Results:
#
#	Adds the following arguments to configure:
#		--enable-threads=yes|no
#
#	Defines the following vars:
#		TCL_THREADS
#------------------------------------------------------------------------

AC_DEFUN([SC_ENABLE_THREADS], [
    AC_MSG_CHECKING(for building with threads)
    AC_ARG_ENABLE(threads, [  --enable-threads        build with threads (default: on)],
	[tcl_ok=$enableval], [tcl_ok=yes])

    if test "$tcl_ok" = "yes"; then
	AC_MSG_RESULT([yes (default)])
	TCL_THREADS=1
	AC_DEFINE(TCL_THREADS)
	# USE_THREAD_ALLOC tells us to try the special thread-based
	# allocator that significantly reduces lock contention
	AC_DEFINE(USE_THREAD_ALLOC)
    else
	TCL_THREADS=0
	AC_MSG_RESULT(no)
    fi
    AC_SUBST(TCL_THREADS)
    AC_SUBST(SHARED_BUILD)
])

#------------------------------------------------------------------------
# SC_ENABLE_SYMBOLS --
#
#	Specify if debugging symbols should be used.
#	Memory (TCL_MEM_DEBUG) and compile (TCL_COMPILE_DEBUG) debugging
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
389
390
391
392
393
394
395

396
397
398
399
400
401
402
403
404
405

406
407
408
409
410
411
412

413
414
415
416
417
418
419







-










-







-







#		--enable-symbols
#
#	Defines the following vars:
#		CFLAGS_DEFAULT	Sets to $(CFLAGS_DEBUG) if true
#				Sets to $(CFLAGS_OPTIMIZE) if false
#		LDFLAGS_DEFAULT	Sets to $(LDFLAGS_DEBUG) if true
#				Sets to $(LDFLAGS_OPTIMIZE) if false
#		DBGX		Debug library extension
#
#------------------------------------------------------------------------

AC_DEFUN([SC_ENABLE_SYMBOLS], [
    AC_MSG_CHECKING([for build with symbols])
    AC_ARG_ENABLE(symbols, [  --enable-symbols        build with debugging symbols (default: off)],    [tcl_ok=$enableval], [tcl_ok=no])
# FIXME: Currently, LDFLAGS_DEFAULT is not used, it should work like CFLAGS_DEFAULT.
    if test "$tcl_ok" = "no"; then
	CFLAGS_DEFAULT='$(CFLAGS_OPTIMIZE)'
	LDFLAGS_DEFAULT='$(LDFLAGS_OPTIMIZE)'
	DBGX=""
	AC_DEFINE(NDEBUG, 1, [Is no debugging enabled?])
	AC_MSG_RESULT([no])

	AC_DEFINE(TCL_CFG_OPTIMIZED)
    else
	CFLAGS_DEFAULT='$(CFLAGS_DEBUG)'
	LDFLAGS_DEFAULT='$(LDFLAGS_DEBUG)'
	DBGX=g
	if test "$tcl_ok" = "yes"; then
	    AC_MSG_RESULT([yes (standard debugging)])
	fi
    fi
    AC_SUBST(CFLAGS_DEFAULT)
    AC_SUBST(LDFLAGS_DEFAULT)

540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562

563
564
565
566
567
568
569
488
489
490
491
492
493
494











495
496
497
498
499
500
501
502
503
504
505
506
507







-
-
-
-
-
-
-
-
-
-
-





+








    # Step 0: Enable 64 bit support?

    AC_MSG_CHECKING([if 64bit support is requested])
    AC_ARG_ENABLE(64bit,[  --enable-64bit          enable 64bit support (where applicable)], [do64bit=$enableval], [do64bit=no])
    AC_MSG_RESULT($do64bit)

    # Cross-compiling options for Windows/CE builds

    AC_MSG_CHECKING([if Windows/CE build is requested])
    AC_ARG_ENABLE(wince,[  --enable-wince          enable Win/CE support (where applicable)], [doWince=$enableval], [doWince=no])
    AC_MSG_RESULT($doWince)

    AC_MSG_CHECKING([for Windows/CE celib directory])
    AC_ARG_WITH(celib,[  --with-celib=DIR        use Windows/CE support library from DIR],
	    CELIB_DIR=$withval, CELIB_DIR=NO_CELIB)
    AC_MSG_RESULT([$CELIB_DIR])

    # Set some defaults (may get changed below)
    EXTRA_CFLAGS=""
	AC_DEFINE(MODULE_SCOPE, [extern], [No need to mark inidividual symbols as hidden])

    AC_CHECK_PROG(CYGPATH, cygpath, cygpath -m, echo)
    AC_CHECK_PROG(WINE, wine, wine,)

    SHLIB_SUFFIX=".dll"

    # MACHINE is IX86 for LINK, but this is used by the manifest,
    # which requires x86|amd64|ia64.
    MACHINE="X86"

689
690
691
692
693
694
695
696

697
698
699
700
701
702
703
704
705
706
707
708
709
710

711
712
713
714
715
716
717
718

719
720
721
722
723



724
725
726
727
728
729
730

731
732
733
734
735
736
737
738
739

740
741
742
743
744
745
746
627
628
629
630
631
632
633

634
635
636
637
638
639
640
641
642
643
644
645
646
647

648
649
650
651
652
653
654
655

656
657
658



659
660
661
662
663
664
665
666
667

668
669
670
671
672
673
674
675
676

677
678
679
680
681
682
683
684







-
+













-
+







-
+


-
-
-
+
+
+






-
+








-
+







	LIBPREFIX="lib"

	if test "${SHARED_BUILD}" = "0" ; then
	    # static
            AC_MSG_RESULT([using static flags])
	    runtime=
	    LIBRARIES="\${STATIC_LIBRARIES}"
	    EXESUFFIX="s\${DBGX}.exe"
	    EXESUFFIX="s.exe"
	else
	    # dynamic
            AC_MSG_RESULT([using shared flags])

	    # ad-hoc check to see if CC supports -shared.
	    if "${CC}" -shared 2>&1 | egrep ': -shared not supported' >/dev/null; then
		AC_MSG_ERROR([${CC} does not support the -shared option.
                You will need to upgrade to a newer version of the toolchain.])
	    fi

	    runtime=
	    # Add SHLIB_LD_LIBS to the Make rule, not here.

	    EXESUFFIX="\${DBGX}.exe"
	    EXESUFFIX=".exe"
	    LIBRARIES="\${SHARED_LIBRARIES}"
	fi
	# Link with gcc since ld does not link to default libs like
	# -luser32 and -lmsvcrt by default.
	SHLIB_LD='${CC} -shared'
	SHLIB_LD_LIBS='${LIBS}'
	MAKE_DLL="\${SHLIB_LD} \$(LDFLAGS) -o \[$]@ ${extra_ldflags} \
	    -Wl,--out-implib,\$(patsubst %.dll,lib%.a,\[$]@)"
	    -Wl,--out-implib,\$(patsubst %.dll,lib%.dll.a,\[$]@)"
	# DLLSUFFIX is separate because it is the building block for
	# users of tclConfig.sh that may build shared or static.
	DLLSUFFIX="\${DBGX}.dll"
	LIBSUFFIX="\${DBGX}.a"
	LIBFLAGSUFFIX="\${DBGX}"
	DLLSUFFIX=".dll"
	LIBSUFFIX=".a"
	LIBFLAGSUFFIX=""
	SHLIB_SUFFIX=.dll

	EXTRA_CFLAGS="${extra_cflags}"

	CFLAGS_DEBUG=-g
	CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer"
	CFLAGS_WARNING="-Wall"
	CFLAGS_WARNING="-Wall -Wextra -Wshadow -Wundef -Wwrite-strings -Wpointer-arith -finput-charset=UTF-8"
	LDFLAGS_DEBUG=
	LDFLAGS_OPTIMIZE=

	case "${CC}" in
	    *++)
		CFLAGS_WARNING="${CFLAGS_WARNING} -Wno-format"
		;;
	    *)
		CFLAGS_WARNING="${CFLAGS_WARNING} -Wdeclaration-after-statement"
		CFLAGS_WARNING="${CFLAGS_WARNING} -Wc++-compat -fextended-identifiers -Wdeclaration-after-statement"
		;;
	esac

	# Specify the CC output file names based on the target name
	CC_OBJNAME="-o \[$]@"
	CC_EXENAME="-o \[$]@"

788
789
790
791
792
793
794
795

796
797
798
799
800
801
802

803
804
805
806
807
808
809
810
811
812
813
814
815
816



817
818
819
820
821
822
823
726
727
728
729
730
731
732

733
734
735
736
737
738
739

740
741
742
743
744
745
746
747
748
749
750
751



752
753
754
755
756
757
758
759
760
761







-
+






-
+











-
-
-
+
+
+







	esac
    else
	if test "${SHARED_BUILD}" = "0" ; then
	    # static
            AC_MSG_RESULT([using static flags])
	    runtime=-MT
	    LIBRARIES="\${STATIC_LIBRARIES}"
	    EXESUFFIX="s\${DBGX}.exe"
	    EXESUFFIX="s.exe"
	else
	    # dynamic
            AC_MSG_RESULT([using shared flags])
	    runtime=-MD
	    # Add SHLIB_LD_LIBS to the Make rule, not here.
	    LIBRARIES="\${SHARED_LIBRARIES}"
	    EXESUFFIX="\${DBGX}.exe"
	    EXESUFFIX=".exe"
	    case "x`echo \${VisualStudioVersion}`" in
		x1[[4-9]]*)
		    lflags="${lflags} -nodefaultlib:libucrt.lib"
		    ;;
		*)
		    ;;
	    esac
	fi
	MAKE_DLL="\${SHLIB_LD} \$(LDFLAGS) -out:\[$]@"
	# DLLSUFFIX is separate because it is the building block for
	# users of tclConfig.sh that may build shared or static.
	DLLSUFFIX="\${DBGX}.dll"
	LIBSUFFIX="\${DBGX}.lib"
	LIBFLAGSUFFIX="\${DBGX}"
	DLLSUFFIX=".dll"
	LIBSUFFIX=".lib"
	LIBFLAGSUFFIX=""

	if test "$do64bit" != "no" ; then
	    case "$do64bit" in
		amd64|x64|yes)
		    MACHINE="AMD64" ; # assume AMD64 as default 64-bit build
		    ;;
		ia64)
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951

952
953
954
955
956
957
958
959
792
793
794
795
796
797
798



























































































799

800
801
802
803
804
805
806







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-







	    CFLAGS_DEBUG="-nologo -Z7 -Od -WX ${runtime}d"
	    # -O2 - create fast code (/Og /Oi /Ot /Oy /Ob2 /Gs /GF /Gy)
	    CFLAGS_OPTIMIZE="-nologo -O2 ${runtime}"
	    lflags="${lflags} -nologo"
	    LINKBIN="link"
	fi

	if test "$doWince" != "no" ; then
	    # Set defaults for common evc4/PPC2003 setup
	    # Currently Tcl requires 300+, possibly 420+ for sockets
	    CEVERSION=420; 		# could be 211 300 301 400 420 ...
	    TARGETCPU=ARMV4;	# could be ARMV4 ARM MIPS SH3 X86 ...
	    ARCH=ARM;		# could be ARM MIPS X86EM ...
	    PLATFORM="Pocket PC 2003"; # or "Pocket PC 2002"
	    if test "$doWince" != "yes"; then
		# If !yes then the user specified something
		# Reset ARCH to allow user to skip specifying it
		ARCH=
		eval `echo $doWince | awk -F "," '{ \
	if (length([$]1)) { printf "CEVERSION=\"%s\"\n", [$]1; \
	if ([$]1 < 400)	  { printf "PLATFORM=\"Pocket PC 2002\"\n" } }; \
	if (length([$]2)) { printf "TARGETCPU=\"%s\"\n", toupper([$]2) }; \
	if (length([$]3)) { printf "ARCH=\"%s\"\n", toupper([$]3) }; \
	if (length([$]4)) { printf "PLATFORM=\"%s\"\n", [$]4 }; \
		}'`
		if test "x${ARCH}" = "x" ; then
		    ARCH=$TARGETCPU;
		fi
	    fi
	    OSVERSION=WCE$CEVERSION;
	    if test "x${WCEROOT}" = "x" ; then
		WCEROOT="C:/Program Files/Microsoft eMbedded C++ 4.0"
		if test ! -d "${WCEROOT}" ; then
		    WCEROOT="C:/Program Files/Microsoft eMbedded Tools"
		fi
	    fi
	    if test "x${SDKROOT}" = "x" ; then
		SDKROOT="C:/Program Files/Windows CE Tools"
		if test ! -d "${SDKROOT}" ; then
		    SDKROOT="C:/Windows CE Tools"
		fi
	    fi
	    # The space-based-path will work for the Makefile, but will
	    # not work if AC_TRY_COMPILE is called.
	    WCEROOT=`echo "$WCEROOT" | sed -e 's!\\\!/!g'`
	    SDKROOT=`echo "$SDKROOT" | sed -e 's!\\\!/!g'`
	    CELIB_DIR=`echo "$CELIB_DIR" | sed -e 's!\\\!/!g'`
	    if test ! -d "${CELIB_DIR}/inc"; then
		AC_MSG_ERROR([Invalid celib directory "${CELIB_DIR}"])
	    fi
	    if test ! -d "${SDKROOT}/${OSVERSION}/${PLATFORM}/Lib/${TARGETCPU}"\
		-o ! -d "${WCEROOT}/EVC/${OSVERSION}/bin"; then
		AC_MSG_ERROR([could not find PocketPC SDK or target compiler to enable WinCE mode [$CEVERSION,$TARGETCPU,$ARCH,$PLATFORM]])
	    else
		CEINCLUDE="${SDKROOT}/${OSVERSION}/${PLATFORM}/include"
		if test -d "${CEINCLUDE}/${TARGETCPU}" ; then
		    CEINCLUDE="${CEINCLUDE}/${TARGETCPU}"
		fi
		CELIBPATH="${SDKROOT}/${OSVERSION}/${PLATFORM}/Lib/${TARGETCPU}"
	    fi
	fi

	if test "$doWince" != "no" ; then
	    CEBINROOT="${WCEROOT}/EVC/${OSVERSION}/bin"
	    if test "${TARGETCPU}" = "X86"; then
		CC="${CEBINROOT}/cl.exe"
	    else
		CC="${CEBINROOT}/cl${ARCH}.exe"
	    fi
	    CC="\"${CC}\" -I\"${CELIB_DIR}/inc\" -I\"${CEINCLUDE}\""
	    RC="\"${WCEROOT}/Common/EVC/bin/rc.exe\""
	    arch=`echo ${ARCH} | awk '{print tolower([$]0)}'`
	    defs="${ARCH} _${ARCH}_ ${arch} PALM_SIZE _MT _DLL _WINDOWS"
	    for i in $defs ; do
		AC_DEFINE_UNQUOTED($i)
	    done
#	    if test "${ARCH}" = "X86EM"; then
#		AC_DEFINE_UNQUOTED(_WIN32_WCE_EMULATION)
#	    fi
	    AC_DEFINE_UNQUOTED(_WIN32_WCE, $CEVERSION)
	    AC_DEFINE_UNQUOTED(UNDER_CE, $CEVERSION)
	    CFLAGS_DEBUG="-nologo -Zi -Od"
	    CFLAGS_OPTIMIZE="-nologo -O2"
	    lversion=`echo ${CEVERSION} | sed -e 's/\(.\)\(..\)/\1\.\2/'`
	    lflags="-nodefaultlib -MACHINE:${ARCH} -LIBPATH:\"${CELIBPATH}\" -subsystem:windowsce,${lversion} -nologo"
	    LINKBIN="\"${CEBINROOT}/link.exe\""
	    AC_SUBST(CELIB_DIR)
	    if test "${CEVERSION}" -lt 400 ; then
		LIBS="coredll.lib corelibc.lib winsock.lib"
	    else
		LIBS="coredll.lib corelibc.lib ws2.lib"
	    fi
	    # celib currently stuck at wce300 status
	    #LIBS="$LIBS \${CELIB_DIR}/wince-${ARCH}-pocket-${OSVERSION}-release/celib.lib"
	    LIBS="$LIBS \"\${CELIB_DIR}/wince-${ARCH}-pocket-wce300-release/celib.lib\""
	    LIBS_GUI="commctrl.lib commdlg.lib"
	else
	    LIBS_GUI="gdi32.lib comdlg32.lib imm32.lib comctl32.lib shell32.lib uuid.lib"
	LIBS_GUI="gdi32.lib comdlg32.lib imm32.lib comctl32.lib shell32.lib uuid.lib"
	fi

	SHLIB_LD="${LINKBIN} -dll -incremental:no ${lflags}"
	SHLIB_LD_LIBS='${LIBS}'
	# link -lib only works when -lib is the first arg
	STLIB_LD="${LINKBIN} -lib ${lflags}"
	RC_OUT=-fo
	RC_TYPE=-r
976
977
978
979
980
981
982
983

984
985
986
987
988
989
990
823
824
825
826
827
828
829

830
831
832
833
834
835
836
837







-
+








	# Specify the CC output file names based on the target name
	CC_OBJNAME="-Fo\[$]@"
	CC_EXENAME="-Fe\"\$(shell \$(CYGPATH) '\[$]@')\""

	# Specify linker flags depending on the type of app being
	# built -- Console vs. Window.
	if test "$doWince" != "no" -a "${TARGETCPU}" != "X86"; then
	if test "${TARGETCPU}" != "X86"; then
	    LDFLAGS_CONSOLE="-link ${lflags}"
	    LDFLAGS_WINDOW=${LDFLAGS_CONSOLE}
	else
	    LDFLAGS_CONSOLE="-link -subsystem:console ${lflags}"
	    LDFLAGS_WINDOW="-link -subsystem:windows ${lflags}"
	fi
    fi
1064
1065
1066
1067
1068
1069
1070


1071
1072
1073
1074
1075
1076
1077
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926







+
+







        tcl_cv_winnt_ignore_void=no)
	)
	if test "$tcl_cv_winnt_ignore_void" = "yes" ; then
	    AC_DEFINE(HAVE_WINNT_IGNORE_VOID, 1,
		    [Defined when cygwin/mingw ignores VOID define in winnt.h])
	fi

	AC_CHECK_HEADER(stdbool.h, [AC_DEFINE(HAVE_STDBOOL_H, 1, [Do we have <stdbool.h>?])],)

	# See if the compiler supports casting to a union type.
	# This is used to stop gcc from printing a compiler
	# warning when initializing a union member.

	AC_CACHE_CHECK(for cast to union support,
	    tcl_cv_cast_to_union,
	    AC_TRY_COMPILE([],
1109
1110
1111
1112
1113
1114
1115
1116
1117


1118
1119

1120
1121
1122

1123
1124
1125
1126
1127
1128
1129
958
959
960
961
962
963
964


965
966
967

968
969
970

971
972
973
974
975
976
977
978







-
-
+
+

-
+


-
+







#		--with-tcl=...
#
#	Defines the following vars:
#		TCL_BIN_DIR	Full path to the tcl build dir.
#------------------------------------------------------------------------

AC_DEFUN([SC_WITH_TCL], [
    if test -d ../../tcl8.6$1/win;  then
	TCL_BIN_DEFAULT=../../tcl8.6$1/win
    if test -d ../../tcl8.7$1/win;  then
	TCL_BIN_DEFAULT=../../tcl8.7$1/win
    else
	TCL_BIN_DEFAULT=../../tcl8.6/win
	TCL_BIN_DEFAULT=../../tcl8.7/win
    fi

    AC_ARG_WITH(tcl, [  --with-tcl=DIR          use Tcl 8.6 binaries from DIR],
    AC_ARG_WITH(tcl, [  --with-tcl=DIR          use Tcl 8.7 binaries from DIR],
	    TCL_BIN_DIR=$withval, TCL_BIN_DIR=`cd $TCL_BIN_DEFAULT; pwd`)
    if test ! -d $TCL_BIN_DIR; then
	AC_MSG_ERROR(Tcl directory $TCL_BIN_DIR does not exist)
    fi
    if test ! -f $TCL_BIN_DIR/Makefile; then
	AC_MSG_ERROR(There is no Makefile in $TCL_BIN_DIR:  perhaps you did not specify the Tcl *build* directory (not the toplevel Tcl directory) or you forgot to configure Tcl?)
    else
1196
1197
1198
1199
1200
1201
1202
1203

1204
1205
1206
1207
1208
1209
1210
1045
1046
1047
1048
1049
1050
1051

1052
1053
1054
1055
1056
1057
1058
1059







-
+







# Results
#	Subst's the following values:
#		BUILD_TCLSH
#------------------------------------------------------------------------

AC_DEFUN([SC_BUILD_TCLSH], [
    AC_MSG_CHECKING([for tclsh in Tcl build directory])
    BUILD_TCLSH=${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT}
    BUILD_TCLSH=${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${EXEEXT}
    AC_MSG_RESULT($BUILD_TCLSH)
    AC_SUBST(BUILD_TCLSH)
])

#--------------------------------------------------------------------
# SC_TCL_CFG_ENCODING	TIP #59
#
1224
1225
1226
1227
1228
1229
1230
1231
1232

1233
1234
1235
1236
1237
1238
1239
1073
1074
1075
1076
1077
1078
1079


1080
1081
1082
1083
1084
1085
1086
1087







-
-
+








AC_DEFUN([SC_TCL_CFG_ENCODING], [
    AC_ARG_WITH(encoding, [  --with-encoding         encoding for configuration values], with_tcencoding=${withval})

    if test x"${with_tcencoding}" != x ; then
	AC_DEFINE_UNQUOTED(TCL_CFGVAL_ENCODING,"${with_tcencoding}")
    else
	# Default encoding on windows is not "iso8859-1"
	AC_DEFINE(TCL_CFGVAL_ENCODING,"cp1252")
	AC_DEFINE(TCL_CFGVAL_ENCODING,"utf-8")
    fi
])

#--------------------------------------------------------------------
# SC_EMBED_MANIFEST
#
#	Figure out if we can embed the manifest where necessary
1247
1248
1249
1250
1251
1252
1253
1254

1255
1256
1257
1258
1259
1260
1261
1095
1096
1097
1098
1099
1100
1101

1102
1103
1104
1105
1106
1107
1108
1109







-
+







#		VC_MANIFEST_EMBED_EXE
#
#--------------------------------------------------------------------

AC_DEFUN([SC_EMBED_MANIFEST], [
    AC_MSG_CHECKING(whether to embed manifest)
    AC_ARG_ENABLE(embedded-manifest,
	AC_HELP_STRING([--enable-embedded-manifest],
	AS_HELP_STRING([--enable-embedded-manifest],
		[embed manifest if possible (default: yes)]),
	[embed_ok=$enableval], [embed_ok=yes])

    VC_MANIFEST_EMBED_DLL=
    VC_MANIFEST_EMBED_EXE=
    result=no
    if test "$embed_ok" = "yes" -a "${SHARED_BUILD}" = "1" \
1280
1281
1282
1283
1284
1285
1286



























































































































1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
	fi
	])
    fi
    AC_MSG_RESULT([$result])
    AC_SUBST(VC_MANIFEST_EMBED_DLL)
    AC_SUBST(VC_MANIFEST_EMBED_EXE)
])

#------------------------------------------------------------------------
# SC_CC_FOR_BUILD
#	For cross compiles, locate a C compiler that can generate native binaries.
#
# Arguments:
#	none
#
# Results:
#	Substitutes the following vars:
#		CC_FOR_BUILD
#		EXEEXT_FOR_BUILD
#------------------------------------------------------------------------

dnl Get a default for CC_FOR_BUILD to put into Makefile.
AC_DEFUN([AX_CC_FOR_BUILD],
[# Put a plausible default for CC_FOR_BUILD in Makefile.
if test -z "$CC_FOR_BUILD"; then
  if test "x$cross_compiling" = "xno"; then
    CC_FOR_BUILD='$(CC)'
  else
    AC_MSG_CHECKING([for gcc])
    AC_CACHE_VAL(ac_cv_path_cc, [
	search_path=`echo ${PATH} | sed -e 's/:/ /g'`
	for dir in $search_path ; do
	    for j in `ls -r $dir/gcc 2> /dev/null` \
		    `ls -r $dir/gcc 2> /dev/null` ; do
		if test x"$ac_cv_path_cc" = x ; then
		    if test -f "$j" ; then
			ac_cv_path_cc=$j
			break
		    fi
		fi
	    done
	done
    ])
  fi
fi
AC_SUBST(CC_FOR_BUILD)
# Also set EXEEXT_FOR_BUILD.
if test "x$cross_compiling" = "xno"; then
  EXEEXT_FOR_BUILD='$(EXEEXT)'
  OBJEXT_FOR_BUILD='$(OBJEXT)'
else
  OBJEXT_FOR_BUILD='.no'
  AC_CACHE_CHECK([for build system executable suffix], bfd_cv_build_exeext,
    [rm -f conftest*
     echo 'int main () { return 0; }' > conftest.c
     bfd_cv_build_exeext=
     ${CC_FOR_BUILD} -o conftest conftest.c 1>&5 2>&5
     for file in conftest.*; do
       case $file in
       *.c | *.o | *.obj | *.ilk | *.pdb) ;;
       *) bfd_cv_build_exeext=`echo $file | sed -e s/conftest//` ;;
       esac
     done
     rm -f conftest*
     test x"${bfd_cv_build_exeext}" = x && bfd_cv_build_exeext=no])
  EXEEXT_FOR_BUILD=""
  test x"${bfd_cv_build_exeext}" != xno && EXEEXT_FOR_BUILD=${bfd_cv_build_exeext}
fi
AC_SUBST(EXEEXT_FOR_BUILD)])dnl
AC_SUBST(OBJEXT_FOR_BUILD)])dnl



#------------------------------------------------------------------------
# SC_ZIPFS_SUPPORT
#	Locate a zip encoder installed on the system path, or none.
#
# Arguments:
#	none
#
# Results:
#	Substitutes the following vars:
#		ZIP_PROG
#       ZIP_PROG_OPTIONS
#       ZIP_PROG_VFSSEARCH
#       ZIP_INSTALL_OBJS
#------------------------------------------------------------------------

AC_DEFUN([SC_ZIPFS_SUPPORT], [
    ZIP_PROG=""
    ZIP_PROG_OPTIONS=""
    ZIP_PROG_VFSSEARCH=""
    ZIP_INSTALL_OBJS=""

    AC_MSG_CHECKING([for zip])
    AC_CACHE_VAL(ac_cv_path_zip, [
    search_path=`echo ${PATH} | sed -e 's/:/ /g'`
    for dir in $search_path ; do
        for j in `ls -r $dir/zip 2> /dev/null` \
            `ls -r $dir/zip 2> /dev/null` ; do
        if test x"$ac_cv_path_zip" = x ; then
            if test -f "$j" ; then
            ac_cv_path_zip=$j
            break
            fi
        fi
        done
    done
    ])
    if test -f "$ac_cv_path_zip" ; then
        ZIP_PROG="$ac_cv_path_zip"
        AC_MSG_RESULT([$ZIP_PROG])
        ZIP_PROG_OPTIONS="-rq"
        ZIP_PROG_VFSSEARCH="*"
        AC_MSG_RESULT([Found INFO Zip in environment])
        # Use standard arguments for zip
    else
        # It is not an error if an installed version of Zip can't be located.
        # We can use the locally distributed minizip instead
        ZIP_PROG="./minizip${EXEEXT_FOR_BUILD}"
        ZIP_PROG_OPTIONS="-o -r"
        ZIP_PROG_VFSSEARCH="*"
        ZIP_INSTALL_OBJS="minizip${EXEEXT_FOR_BUILD}"
        AC_MSG_RESULT([No zip found on PATH building minizip])
    fi
    AC_SUBST(ZIP_PROG)
    AC_SUBST(ZIP_PROG_OPTIONS)
    AC_SUBST(ZIP_PROG_VFSSEARCH)
    AC_SUBST(ZIP_INSTALL_OBJS)
])
Changes to win/tkConfig.sh.in.
21
22
23
24
25
26
27

28
29


30
31
32
33
34
35
36
21
22
23
24
25
26
27
28


29
30
31
32
33
34
35
36
37







+
-
-
+
+








# -D flags for use with the C compiler.
TK_DEFS='@DEFS@'

# Flag, 1: we built a shared lib, 0 we didn't
TK_SHARED_BUILD=@TK_SHARED_BUILD@

# TK_DBGX used to be used to distinguish debug vs. non-debug builds.
# This indicates if Tk was build with debugging symbols
TK_DBGX=@TK_DBGX@
# This was a righteous pain so the core doesn't do that any more.
TK_DBGX=

# The name of the Tk library (may be either a .a file or a shared library):
TK_LIB_FILE='@TK_LIB_FILE@'

# Additional libraries to use when linking Tk.
TK_LIBS='@LIBS@ @LIBS_GUI@'

Changes to win/tkWin.h.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15
16
17
18
19
20
21


22
23
24
25

26
27
28




29
30
31
32
33
34
35
1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16
17
18
19
20

21
22
23
24
25

26
27
28

29
30
31
32
33
34
35
36
37
38
39






-
+













-
+
+



-
+


-
+
+
+
+







/*
 * tkWin.h --
 *
 *	Declarations of public types and interfaces that are only
 *	available under Windows.
 *
 * Copyright (c) 1996-1997 by Sun Microsystems, Inc.
 * Copyright (c) 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.
 */

#ifndef _TKWIN
#define _TKWIN

/*
 * We must specify the lower version we intend to support. In particular
 * the SystemParametersInfo API doesn't like to receive structures that
 * are larger than it expects which affects the font assignments.
 *
 * WINVER = 0x0500 means Windows 2000 and above
 * WINVER = 0x0600 means Windows Vista and above. Even though we still
 * support Windows XP, but the Vista-specifics are tested at runtime.
 */

#ifndef WINVER
#define WINVER 0x0500
#   define WINVER 0x0600
#endif
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0500
#   define _WIN32_WINNT 0x0600
#endif
#ifndef _WIN32_IE
#   define _WIN32_IE 0x0700
#endif

#ifndef _TK
#include <tk.h>
#endif

#define WIN32_LEAN_AND_MEAN
Changes to win/tkWin32Dll.c.
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







/*
 * tkWin32Dll.c --
 *
 *	This file contains a stub dll entry point.
 *
 * 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.
 */

#include "tkWinInt.h"
#ifndef STATIC_BUILD
100
101
102
103
104
105
106

107
108
109
110
111
112
113
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114







+







    HINSTANCE hInstance,
    DWORD reason,
    LPVOID reserved)
{
#ifdef HAVE_NO_SEH
    TCLEXCEPTION_REGISTRATION registration;
#endif
    (void)reserved;

    /*
     * If we are attaching to the DLL from a new process, tell Tk about the
     * hInstance to use.
     */

    switch (reason) {
130
131
132
133
134
135
136
137

138
139
140
141
142
143
144
131
132
133
134
135
136
137

138
139
140
141
142
143
144
145







-
+







	     * Construct an TCLEXCEPTION_REGISTRATION to protect the call to
	     * TkFinalize
	     */

	    "leaq	%[registration], %%rdx"		"\n\t"
	    "movq	%%gs:0,		%%rax"		"\n\t"
	    "movq	%%rax,		0x0(%%rdx)"	"\n\t" /* link */
	    "leaq	1f,		%%rax"		"\n\t"
	    "leaq	1f(%%rip),	%%rax"		"\n\t"
	    "movq	%%rax,		0x8(%%rdx)"	"\n\t" /* handler */
	    "movq	%%rbp,		0x10(%%rdx)"	"\n\t" /* rbp */
	    "movq	%%rsp,		0x18(%%rdx)"	"\n\t" /* rsp */
	    "movl	%[error],	0x20(%%rdx)"	"\n\t" /* status */

	    /*
	     * Link the TCLEXCEPTION_REGISTRATION on the chain
Changes to win/tkWin3d.c.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







/*
 * tkWin3d.c --
 *
 *	This file contains the platform specific routines for drawing 3D
 *	borders in the Windows 95 style.
 *
 * 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.
 */

#include "tkWinInt.h"
#include "tk3d.h"
39
40
41
42
43
44
45
46

47
48
49
50
51
52
53
39
40
41
42
43
44
45

46
47
48
49
50
51
52
53







-
+







 *
 *----------------------------------------------------------------------
 */

TkBorder *
TkpGetBorder(void)
{
    WinBorder *borderPtr = ckalloc(sizeof(WinBorder));
    WinBorder *borderPtr = (WinBorder *)ckalloc(sizeof(WinBorder));

    borderPtr->light2ColorPtr = NULL;
    borderPtr->dark2ColorPtr = NULL;
    return (TkBorder *) borderPtr;
}

/*
Changes to win/tkWinButton.c.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







/*
 * tkWinButton.c --
 *
 *	This file implements the Windows specific portion of the button
 *	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.
 */

#define OEMRESOURCE
#include "tkWinInt.h"
145
146
147
148
149
150
151
152

153
154
155
156
157
158
159
145
146
147
148
149
150
151

152
153
154
155
156
157
158
159







-
+







     */

    if (tsdPtr->boxesPtr != NULL && !(tsdPtr->boxesPtr->biWidth % 4)
	    && !(tsdPtr->boxesPtr->biHeight % 2)) {
	size = tsdPtr->boxesPtr->biSize
		+ (sizeof(RGBQUAD) << tsdPtr->boxesPtr->biBitCount)
		+ tsdPtr->boxesPtr->biSizeImage;
	newBitmap = ckalloc(size);
	newBitmap = (LPBITMAPINFOHEADER)ckalloc(size);
	memcpy(newBitmap, tsdPtr->boxesPtr, size);
	tsdPtr->boxesPtr = newBitmap;
	tsdPtr->boxWidth = tsdPtr->boxesPtr->biWidth / 4;
	tsdPtr->boxHeight = tsdPtr->boxesPtr->biHeight / 2;
	tsdPtr->boxesPalette = (DWORD*) (((LPSTR) tsdPtr->boxesPtr)
		+ tsdPtr->boxesPtr->biSize);
	tsdPtr->boxesBits = ((LPSTR) tsdPtr->boxesPalette)
178
179
180
181
182
183
184
185

186
187
188
189
190
191
192
178
179
180
181
182
183
184

185
186
187
188
189
190
191
192







-
+







 * Side effects:
 *	Updates some of.
 *
 *----------------------------------------------------------------------
 */

void
TkpButtonSetDefaults()
TkpButtonSetDefaults(void)
{
    int width = GetSystemMetrics(SM_CXEDGE);
	if (width > 0) {
	    sprintf(tkDefButtonBorderWidth, "%d", width);
	}
}

207
208
209
210
211
212
213

214
215

216
217
218
219
220
221
222
207
208
209
210
211
212
213
214
215

216
217
218
219
220
221
222
223







+

-
+







 */

TkButton *
TkpCreateButton(
    Tk_Window tkwin)
{
    WinButton *butPtr;
    (void)tkwin;

    butPtr = ckalloc(sizeof(WinButton));
    butPtr = (WinButton *)ckalloc(sizeof(WinButton));
    butPtr->hwnd = NULL;
    return (TkButton *) butPtr;
}

/*
 *----------------------------------------------------------------------
 *
312
313
314
315
316
317
318
319

320
321
322
323
324
325
326

327
328
329
330
331
332
333
313
314
315
316
317
318
319

320
321
322
323
324
325
326

327
328
329
330
331
332
333
334







-
+






-
+








void
TkpDisplayButton(
    ClientData clientData)	/* Information about widget. */
{
    TkWinDCState state;
    HDC dc;
    register TkButton *butPtr = (TkButton *) clientData;
    TkButton *butPtr = (TkButton *)clientData;
    GC gc;
    Tk_3DBorder border;
    Pixmap pixmap;
    int x = 0;			/* Initialization only needed to stop compiler
				 * warning. */
    int y, relief;
    register Tk_Window tkwin = butPtr->tkwin;
    Tk_Window tkwin = butPtr->tkwin;
    int width = 0, height = 0, haveImage = 0, haveText = 0, drawRing = 0;
    RECT rect;
    int defaultWidth;		/* Width of default ring. */
    int offset;			/* 0 means this is a label widget. 1 means it
				 * is a flavor of button, so we offset the
				 * text to make the button appear to move up
				 * and down as the relief changes. */
814
815
816
817
818
819
820
821

822
823
824
825
826
827
828
815
816
817
818
819
820
821

822
823
824
825
826
827
828
829







-
+







 *	The button's window may change size.
 *
 *----------------------------------------------------------------------
 */

void
TkpComputeButtonGeometry(
    register TkButton *butPtr)	/* Button whose geometry may have changed. */
    TkButton *butPtr)	/* Button whose geometry may have changed. */
{
    int txtWidth, txtHeight;	/* Width and height of text */
    int imgWidth, imgHeight;	/* Width and height of image */
    int width = 0, height = 0;	/* Width and height of button */
    int haveImage, haveText;
    int avgWidth;
    int minWidth;
1260
1261
1262
1263
1264
1265
1266
1267

1268
1269
1270
1271
1272
1273
1274
1275

1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290

1291
1292
1293
1294
1295
1296
1297

1298
1299
1300
1301
1302
1303
1304
1305

1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1261
1262
1263
1264
1265
1266
1267

1268
1269
1270
1271
1272
1273
1274
1275

1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290

1291
1292
1293
1294
1295
1296
1297

1298
1299
1300
1301
1302
1303
1304
1305

1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319







-
+







-
+














-
+






-
+







-
+













    case WM_ENABLE:
	break;

    case WM_PAINT: {
	PAINTSTRUCT ps;
	BeginPaint(hwnd, &ps);
	EndPaint(hwnd, &ps);
	TkpDisplayButton((ClientData)butPtr);
	TkpDisplayButton(butPtr);

	/*
	 * Special note: must cancel any existing idle handler for
	 * TkpDisplayButton; it's no longer needed, and TkpDisplayButton
	 * cleared the REDRAW_PENDING flag.
	 */

	Tcl_CancelIdleCall(TkpDisplayButton, (ClientData)butPtr);
	Tcl_CancelIdleCall(TkpDisplayButton, butPtr);
	return 0;
    }
    case BN_CLICKED: {
	/*
	 * OOPS: chromium fires WM_NULL regularly to ping if plugin is still
	 * alive. When using an external window (i.e. via the tcl plugin), this
	 * causes all buttons to fire once a second, so we need to make sure
	 * that we are not dealing with the chromium life check.
	*/
        if (wParam != 0 || lParam != 0) {
	    int code;
	    Tcl_Interp *interp = butPtr->info.interp;

	    if (butPtr->info.state != STATE_DISABLED) {
		Tcl_Preserve((ClientData)interp);
		Tcl_Preserve(interp);
		code = TkInvokeButton((TkButton*)butPtr);
		if (code != TCL_OK && code != TCL_CONTINUE
			&& code != TCL_BREAK) {
		    Tcl_AddErrorInfo(interp, "\n    (button invoke)");
		    Tcl_BackgroundException(interp, code);
		}
		Tcl_Release((ClientData)interp);
		Tcl_Release(interp);
	    }
	    Tcl_ServiceAll();
	    return 0;
	}
    }
    /* FALLTHRU */
    default:
	if (Tk_TranslateWinEvent(hwnd, message, wParam, lParam, &result)) {
	if (TkTranslateWinEvent(hwnd, message, wParam, lParam, &result)) {
	    return result;
	}
    }
    return DefWindowProcW(hwnd, message, wParam, lParam);
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Changes to win/tkWinClipboard.c.
1
2
3
4
5
6
7


8
9
10
11
12
13
14
1
2
3
4
5


6
7
8
9
10
11
12
13
14





-
-
+
+







/*
 * tkWinClipboard.c --
 *
 *	This file contains functions for managing the clipboard.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright (c) 1998-2000 by Scriptics Corporation.
 * Copyright © 1995-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.
 */

#include "tkWinInt.h"
#include "tkSelect.h"
74
75
76
77
78
79
80
81
82



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103

104
105
106
107
108
109
110
74
75
76
77
78
79
80


81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103

104
105
106
107
108
109
110
111







-
-
+
+
+




















-
+







    result = TCL_ERROR;
    if (IsClipboardFormatAvailable(CF_UNICODETEXT)) {
	handle = GetClipboardData(CF_UNICODETEXT);
	if (!handle) {
	    CloseClipboard();
	    goto error;
	}
	data = GlobalLock(handle);
	Tcl_WinTCharToUtf((LPCTSTR)data, -1, &ds);
	data = (char *)GlobalLock(handle);
	Tcl_DStringInit(&ds);
	Tcl_WCharToUtfDString((WCHAR *)data, wcslen((WCHAR *)data), &ds);
	GlobalUnlock(handle);
    } else if (IsClipboardFormatAvailable(CF_TEXT)) {
	/*
	 * Determine the encoding to use to convert this text.
	 */

	if (IsClipboardFormatAvailable(CF_LOCALE)) {
	    handle = GetClipboardData(CF_LOCALE);
	    if (!handle) {
		CloseClipboard();
		goto error;
	    }

	    /*
	     * Get the locale identifier, determine the proper code page to
	     * use, and find the corresponding encoding.
	     */

	    Tcl_DStringInit(&ds);
	    Tcl_DStringAppend(&ds, "cp######", -1);
	    data = GlobalLock(handle);
	    data = (char *)GlobalLock(handle);

	    /*
	     * Even though the documentation claims that GetLocaleInfo expects
	     * an LCID, on Windows 9x it really seems to expect a LanguageID.
	     */

	    locale = LANGIDFROMLCID(*((int*)data));
126
127
128
129
130
131
132
133

134
135
136
137
138
139
140
127
128
129
130
131
132
133

134
135
136
137
138
139
140
141







-
+







	if (!handle) {
	    if (encoding) {
		Tcl_FreeEncoding(encoding);
	    }
	    CloseClipboard();
	    goto error;
	}
	data = GlobalLock(handle);
	data = (char *)GlobalLock(handle);
	Tcl_ExternalToUtfDString(encoding, data, -1, &ds);
	GlobalUnlock(handle);
	if (encoding) {
	    Tcl_FreeEncoding(encoding);
	}
    } else if (IsClipboardFormatAvailable(CF_HDROP)) {
	DROPFILES *drop;
153
154
155
156
157
158
159
160


161
162
163
164
165
166
167
154
155
156
157
158
159
160

161
162
163
164
165
166
167
168
169







-
+
+







	    size_t len;

	    while (*fname != 0) {
		if (count) {
		    Tcl_DStringAppend(&ds, "\n", 1);
		}
		len = wcslen(fname);
		Tcl_WinTCharToUtf((LPCTSTR)fname, len * sizeof(WCHAR), &dsTmp);
		Tcl_DStringInit(&dsTmp);
		Tcl_WCharToUtfDString(fname, len, &dsTmp);
		Tcl_DStringAppend(&ds, Tcl_DStringValue(&dsTmp),
			Tcl_DStringLength(&dsTmp));
		Tcl_DStringFree(&dsTmp);
		fname += len + 1;
		count++;
	    }
	    noBackslash = (count > 0);
228
229
230
231
232
233
234


235
236
237
238
239
240
241
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245







+
+







    Display *display,
    Atom selection,
    Window owner,
    Time time)
{
    HWND hwnd = owner ? TkWinGetHWND(owner) : NULL;
    Tk_Window tkwin;
    (void)display;
    (void)time;

    /*
     * This is a gross hack because the Tk_InternAtom interface is broken. It
     * expects a Tk_Window, even though it only needs a Tk_Display.
     */

    tkwin = (Tk_Window) TkGetMainInfoList()->winPtr;
277
278
279
280
281
282
283

284
285
286
287
288
289
290
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295







+







{
    TkClipboardTarget *targetPtr;
    TkClipboardBuffer *cbPtr;
    HGLOBAL handle;
    char *buffer, *p, *rawText, *endPtr;
    int length;
    Tcl_DString ds;
    (void)format;

    for (targetPtr = dispPtr->clipTargetPtr; targetPtr != NULL;
	    targetPtr = targetPtr->nextPtr) {
	if (targetPtr->type == XA_STRING) {
	    break;
	}
    }
308
309
310
311
312
313
314
315

316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344















345
346
347
348
349
350
351
313
314
315
316
317
318
319

320
321
322
323
324
325
326
327
328
329
330
331
332
333
334















335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356







-
+














-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	}
    }

    /*
     * Copy the data and change EOL characters.
     */

    buffer = rawText = ckalloc(length + 1);
    buffer = rawText = (char *)ckalloc(length + 1);
    if (targetPtr != NULL) {
	for (cbPtr = targetPtr->firstBufferPtr; cbPtr != NULL;
		cbPtr = cbPtr->nextPtr) {
	    for (p = cbPtr->buffer, endPtr = p + cbPtr->length;
		    p < endPtr; p++) {
		if (*p == '\n') {
		    *buffer++ = '\r';
		}
		*buffer++ = *p;
	    }
	}
    }
    *buffer = '\0';

    Tcl_DStringInit(&ds);
    Tcl_WinUtfToTChar(rawText, -1, &ds);
    ckfree(rawText);
    handle = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE,
	    Tcl_DStringLength(&ds) + 2);
    if (!handle) {
	Tcl_DStringFree(&ds);
	return;
    }
    buffer = GlobalLock(handle);
    memcpy(buffer, Tcl_DStringValue(&ds),
	    Tcl_DStringLength(&ds) + 2);
    GlobalUnlock(handle);
    Tcl_DStringFree(&ds);
    SetClipboardData(CF_UNICODETEXT, handle);
	Tcl_DStringInit(&ds);
	Tcl_UtfToWCharDString(rawText, -1, &ds);
	ckfree(rawText);
	handle = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE,
		(unsigned) Tcl_DStringLength(&ds) + 2);
	if (!handle) {
	    Tcl_DStringFree(&ds);
	    return;
	}
	buffer = (char *)GlobalLock(handle);
	memcpy(buffer, Tcl_DStringValue(&ds),
		(unsigned) Tcl_DStringLength(&ds) + 2);
	GlobalUnlock(handle);
	Tcl_DStringFree(&ds);
	SetClipboardData(CF_UNICODETEXT, handle);
}

/*
 *----------------------------------------------------------------------
 *
 * TkSelUpdateClipboard --
 *
363
364
365
366
367
368
369


370
371
372
373
374
375
376
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383







+
+








void
TkSelUpdateClipboard(
    TkWindow *winPtr,
    TkClipboardTarget *targetPtr)
{
    HWND hwnd = TkWinGetHWND(winPtr->window);
    (void)targetPtr;

    UpdateClipboard(hwnd);
}

/*
 *----------------------------------------------------------------------
 *
 * UpdateClipboard --
415
416
417
418
419
420
421
422

423
424
425
426
427
428
429
422
423
424
425
426
427
428

429
430
431
432
433
434
435
436







-
+







 *
 *--------------------------------------------------------------
 */

void
TkSelEventProc(
    Tk_Window tkwin,		/* Window for which event was targeted. */
    register XEvent *eventPtr)	/* X event: either SelectionClear,
    XEvent *eventPtr)	/* X event: either SelectionClear,
				 * SelectionRequest, or SelectionNotify. */
{
    if (eventPtr->type == SelectionClear) {
	TkSelClearSelection(tkwin, eventPtr);
    }
}

442
443
444
445
446
447
448
449

450

451
452
453
454
455
456
457
458
459
449
450
451
452
453
454
455

456
457
458
459
460
461
462
463
464
465
466
467







-
+

+









 *	None.
 *
 *----------------------------------------------------------------------
 */

void
TkSelPropProc(
    register XEvent *eventPtr)	/* X PropertyChange event. */
    XEvent *eventPtr)	/* X PropertyChange event. */
{
    (void)eventPtr;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Changes to win/tkWinColor.c.
1
2
3
4
5
6
7


8
9
10
11
12
13
14
1
2
3
4
5


6
7
8
9
10
11
12
13
14





-
-
+
+







/*
 * tkWinColor.c --
 *
 *	Functions to map color names to system color values.
 *
 * Copyright (c) 1995 Sun Microsystems, Inc.
 * Copyright (c) 1994 Software Research Associates, Inc.
 * Copyright © 1995 Sun Microsystems, Inc.
 * Copyright © 1994 Software Research Associates, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tkWinInt.h"
#include "tkColor.h"
54
55
56
57
58
59
60

61
62
63
64
65
66
67
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68







+







    {"InactiveBorder",		COLOR_INACTIVEBORDER},
    {"InactiveCaption",		COLOR_INACTIVECAPTION},
    {"InactiveCaptionText",	COLOR_INACTIVECAPTIONTEXT},
    {"InfoBackground",		COLOR_INFOBK},
    {"InfoText",		COLOR_INFOTEXT},
    {"Menu",			COLOR_MENU},
    {"MenuText",		COLOR_MENUTEXT},
    {"PlaceHolderText",		COLOR_GRAYTEXT},
    {"Scrollbar",		COLOR_SCROLLBAR},
    {"Window",			COLOR_WINDOW},
    {"WindowFrame",		COLOR_WINDOWFRAME},
    {"WindowText",		COLOR_WINDOWTEXT}
};

/*
169
170
171
172
173
174
175
176

177
178
179
180
181
182
183
170
171
172
173
174
175
176

177
178
179
180
181
182
183
184







-
+







     * color index.
     */

    if (((strncasecmp(name, "system", 6) == 0)
	    && FindSystemColor(name+6, &color, &index))
	    || TkParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), name,
		    &color)) {
	winColPtr = ckalloc(sizeof(WinColor));
	winColPtr = (WinColor *)ckalloc(sizeof(WinColor));
	winColPtr->info.color = color;
	winColPtr->index = index;

	XAllocColor(Tk_Display(tkwin), Tk_Colormap(tkwin),
		&winColPtr->info.color);
 	return (TkColor *) winColPtr;
    }
207
208
209
210
211
212
213
214

215
216
217
218
219
220
221
208
209
210
211
212
213
214

215
216
217
218
219
220
221
222







-
+








TkColor *
TkpGetColorByValue(
    Tk_Window tkwin,		/* Window in which color will be used. */
    XColor *colorPtr)		/* Red, green, and blue fields indicate
				 * desired color. */
{
    WinColor *tkColPtr = ckalloc(sizeof(WinColor));
    WinColor *tkColPtr = (WinColor *)ckalloc(sizeof(WinColor));

    tkColPtr->info.color.red = colorPtr->red;
    tkColPtr->info.color.green = colorPtr->green;
    tkColPtr->info.color.blue = colorPtr->blue;
    tkColPtr->info.color.pixel = 0;
    tkColPtr->index = -1;
    XAllocColor(Tk_Display(tkwin), Tk_Colormap(tkwin), &tkColPtr->info.color);
270
271
272
273
274
275
276
277

278
279
280
281
282
283
284
271
272
273
274
275
276
277

278
279
280
281
282
283
284
285







-
+







 *----------------------------------------------------------------------
 */

int
TkWinIndexOfColor(
    XColor *colorPtr)
{
    register WinColor *winColPtr = (WinColor *) colorPtr;
    WinColor *winColPtr = (WinColor *) colorPtr;
    if (winColPtr->info.magic == COLOR_MAGIC) {
	return winColPtr->index;
    }
    return -1;
}

/*
303
304
305
306
307
308
309

310
311
312
313
314
315
316
317
318
319

320
321
322
323
324
325
326
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320

321
322
323
324
325
326
327
328







+









-
+







    Display *display,
    Colormap colormap,
    XColor *color)
{
    TkWinColormap *cmap = (TkWinColormap *) colormap;
    PALETTEENTRY entry, closeEntry;
    HDC dc = GetDC(NULL);
    (void)display;

    entry.peRed = (color->red) >> 8;
    entry.peGreen = (color->green) >> 8;
    entry.peBlue = (color->blue) >> 8;
    entry.peFlags = 0;

    if (GetDeviceCaps(dc, RASTERCAPS) & RC_PALETTE) {
	unsigned long sizePalette = GetDeviceCaps(dc, SIZEPALETTE);
	UINT newPixel, closePixel;
	int new;
	int isNew;
	size_t refCount;
	Tcl_HashEntry *entryPtr;
	UINT index;

	/*
	 * Find the nearest existing palette entry.
	 */
354
355
356
357
358
359
360
361
362


363
364
365
366
367

368
369
370
371
372
373
374
356
357
358
359
360
361
362


363
364
365
366
367
368

369
370
371
372
373
374
375
376







-
-
+
+




-
+







		ResizePalette(cmap->palette, cmap->size);
		SetPaletteEntries(cmap->palette, cmap->size - 1, 1, &entry);
	    }
	}

	color->pixel = PALETTERGB(entry.peRed, entry.peGreen, entry.peBlue);
	entryPtr = Tcl_CreateHashEntry(&cmap->refCounts,
		INT2PTR(color->pixel), &new);
	if (new) {
		INT2PTR(color->pixel), &isNew);
	if (isNew) {
	    refCount = 1;
	} else {
	    refCount = (size_t)Tcl_GetHashValue(entryPtr) + 1;
	}
	Tcl_SetHashValue(entryPtr, (void *)refCount);
	Tcl_SetHashValue(entryPtr, INT2PTR(refCount));
    } else {
	/*
	 * Determine what color will actually be used on non-colormap systems.
	 */

	color->pixel = GetNearestColor(dc,
		RGB(entry.peRed, entry.peGreen, entry.peBlue));
410
411
412
413
414
415
416


417
418
419
420
421
422
423
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427







+
+







    COLORREF cref;
    UINT count, index;
    size_t refCount;
    int i;
    PALETTEENTRY entry, *entries;
    Tcl_HashEntry *entryPtr;
    HDC dc = GetDC(NULL);
    (void)display;
    (void)planes;

    /*
     * We don't have to do anything for non-palette devices.
     */

    if (GetDeviceCaps(dc, RASTERCAPS) & RC_PALETTE) {
	/*
432
433
434
435
436
437
438
439

440
441
442
443
444
445
446
447
448
449

450
451
452
453
454
455
456
436
437
438
439
440
441
442

443
444
445
446
447
448
449
450
451
452

453
454
455
456
457
458
459
460







-
+









-
+







	    refCount = (size_t)Tcl_GetHashValue(entryPtr) - 1;
	    if (refCount == 0) {
		cref = pixels[i] & 0x00ffffff;
		index = GetNearestPaletteIndex(cmap->palette, cref);
		GetPaletteEntries(cmap->palette, index, 1, &entry);
		if (cref == RGB(entry.peRed, entry.peGreen, entry.peBlue)) {
		    count = cmap->size - index;
		    entries = ckalloc(sizeof(PALETTEENTRY) * count);
		    entries = (PALETTEENTRY *)ckalloc(sizeof(PALETTEENTRY) * count);
		    GetPaletteEntries(cmap->palette, index+1, count, entries);
		    SetPaletteEntries(cmap->palette, index, count, entries);
		    ckfree(entries);
		    cmap->size--;
		} else {
		    Tcl_Panic("Tried to free a color that isn't allocated");
		}
		Tcl_DeleteHashEntry(entryPtr);
	    } else {
		Tcl_SetHashValue(entryPtr, (size_t)refCount);
		Tcl_SetHashValue(entryPtr, INT2PTR(refCount));
	    }
	}
    }
    ReleaseDC(NULL, dc);
    return Success;
}

478
479
480
481
482
483
484
485

486
487




488
489
490
491
492
493
494
495
496
497
498
499

500
501
502
503
504
505
506
507
508
509
510
511
512

513
514
515
516
517
518
519
482
483
484
485
486
487
488

489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506

507
508
509
510
511
512
513
514
515
516
517
518
519

520
521
522
523
524
525
526
527







-
+


+
+
+
+











-
+












-
+







    int alloc)
{
    char logPalBuf[sizeof(LOGPALETTE) + 256 * sizeof(PALETTEENTRY)];
    LOGPALETTE *logPalettePtr;
    PALETTEENTRY *entryPtr;
    TkWinColormap *cmap;
    Tcl_HashEntry *hashPtr;
    int new;
    int isNew;
    UINT i;
    HPALETTE sysPal;
    (void)display;
    (void)w;
    (void)visual;
    (void)alloc;

    /*
     * Allocate a starting palette with all of the reserved colors.
     */

    logPalettePtr = (LOGPALETTE *) logPalBuf;
    logPalettePtr->palVersion = 0x300;
    sysPal = (HPALETTE) GetStockObject(DEFAULT_PALETTE);
    logPalettePtr->palNumEntries = GetPaletteEntries(sysPal, 0, 256,
	    logPalettePtr->palPalEntry);

    cmap = ckalloc(sizeof(TkWinColormap));
    cmap = (TkWinColormap *)ckalloc(sizeof(TkWinColormap));
    cmap->size = logPalettePtr->palNumEntries;
    cmap->stale = 0;
    cmap->palette = CreatePalette(logPalettePtr);

    /*
     * Add hash entries for each of the static colors.
     */

    Tcl_InitHashTable(&cmap->refCounts, TCL_ONE_WORD_KEYS);
    for (i = 0; i < logPalettePtr->palNumEntries; i++) {
	entryPtr = logPalettePtr->palPalEntry + i;
	hashPtr = Tcl_CreateHashEntry(&cmap->refCounts, INT2PTR(PALETTERGB(
		entryPtr->peRed, entryPtr->peGreen, entryPtr->peBlue)), &new);
		entryPtr->peRed, entryPtr->peGreen, entryPtr->peBlue)), &isNew);
	Tcl_SetHashValue(hashPtr, INT2PTR(1));
    }

    return (Colormap)cmap;
}

/*
535
536
537
538
539
540
541

542
543
544
545
546
547
548
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557







+








int
XFreeColormap(
    Display *display,
    Colormap colormap)
{
    TkWinColormap *cmap = (TkWinColormap *) colormap;
    (void)display;

    if (!DeleteObject(cmap->palette)) {
	Tcl_Panic("Unable to free colormap, palette is still selected");
    }
    Tcl_DeleteHashTable(&cmap->refCounts);
    ckfree(cmap);
    return Success;
Changes to win/tkWinConfig.c.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







/*
 * tkWinConfig.c --
 *
 *	This module implements the Windows system defaults for the
 *	configuration package.
 *
 * Copyright (c) 1997 by 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.
 */

#include "tkWinInt.h"

Changes to win/tkWinCursor.c.
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







/*
 * tkWinCursor.c --
 *
 *	This file contains Win32 specific cursor related routines.
 *
 * 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.
 */

#include "tkWinInt.h"

96
97
98
99
100
101
102

103
104
105
106

107
108
109
110
111
112
113
114
115
116

117
118
119
120
121
122
123
96
97
98
99
100
101
102
103
104
105
106

107
108
109
110
111
112
113
114
115
116

117
118
119
120
121
122
123
124







+



-
+









-
+







    Tk_Uid string)		/* Description of cursor. See manual entry for
				 * details on legal syntax. */
{
    struct CursorName *namePtr;
    TkWinCursor *cursorPtr;
    int argc;
    const char **argv = NULL;
    (void)tkwin;

    /*
     * All cursor names are valid lists of one element (for
     * Unix-compatability), even unadorned system cursor names.
     * Unix-compatibility), even unadorned system cursor names.
     */

    if (Tcl_SplitList(interp, string, &argc, &argv) != TCL_OK) {
	return NULL;
    }
    if (argc == 0) {
	goto badCursorSpec;
    }

    cursorPtr = ckalloc(sizeof(TkWinCursor));
    cursorPtr = (TkWinCursor *)ckalloc(sizeof(TkWinCursor));
    cursorPtr->info.cursor = (Tk_Cursor) cursorPtr;
    cursorPtr->winCursor = NULL;
    cursorPtr->system = 0;

    if (argv[0][0] == '@') {
	/*
	 * Check for system cursor of type @<filename>, where only the name is
197
198
199
200
201
202
203










204
205
206
207
208
209
210
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221







+
+
+
+
+
+
+
+
+
+







    const char *source,		/* Bitmap data for cursor shape. */
    const char *mask,		/* Bitmap data for cursor mask. */
    int width, int height,	/* Dimensions of cursor. */
    int xHot, int yHot,		/* Location of hot-spot in cursor. */
    XColor fgColor,		/* Foreground color for cursor. */
    XColor bgColor)		/* Background color for cursor. */
{
    (void)tkwin;
    (void)source;
    (void)mask;
    (void)width;
    (void)height;
    (void)xHot;
    (void)yHot;
    (void)fgColor;
    (void)bgColor;

    return NULL;
}

/*
 *----------------------------------------------------------------------
 *
 * TkpFreeCursor --
221
222
223
224
225
226
227


228
229
230
231
232
233
234
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247







+
+







 *----------------------------------------------------------------------
 */

void
TkpFreeCursor(
    TkCursor *cursorPtr)
{
    (void)cursorPtr;

    /* TkWinCursor *winCursorPtr = (TkWinCursor *) cursorPtr; */
}

/*
 *----------------------------------------------------------------------
 *
 * TkpSetCursor --
Changes to win/tkWinDefault.h.
64
65
66
67
68
69
70
71

72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

88
89
90

91
92
93
94
95
96
97
64
65
66
67
68
69
70

71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86

87
88
89

90
91
92
93
94
95
96
97







-
+















-
+


-
+







#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		HIGHLIGHT
#define DEF_LABEL_HIGHLIGHT_WIDTH	"0"
#define DEF_BUTTON_HIGHLIGHT_WIDTH	"1"
#define DEF_BUTTON_IMAGE		((char *) NULL)
#define DEF_BUTTON_IMAGE		NULL
#define DEF_BUTTON_INDICATOR		"1"
#define DEF_BUTTON_JUSTIFY		"center"
#define DEF_BUTTON_OFF_VALUE		"0"
#define DEF_BUTTON_ON_VALUE		"1"
#define DEF_BUTTON_OVER_RELIEF		""
#define DEF_BUTTON_PADX			"1"
#define DEF_LABCHKRAD_PADX		"1"
#define DEF_BUTTON_PADY			"1"
#define DEF_LABCHKRAD_PADY		"1"
#define DEF_BUTTON_RELIEF		"raised"
#define DEF_LABCHKRAD_RELIEF		"flat"
#define DEF_BUTTON_REPEAT_DELAY		"0"
#define DEF_BUTTON_REPEAT_INTERVAL	"0"
#define DEF_BUTTON_SELECT_COLOR		INDICATOR
#define DEF_BUTTON_SELECT_MONO		BLACK
#define DEF_BUTTON_SELECT_IMAGE		((char *) NULL)
#define DEF_BUTTON_SELECT_IMAGE		NULL
#define DEF_BUTTON_STATE		"normal"
#define DEF_LABEL_TAKE_FOCUS		"0"
#define DEF_BUTTON_TAKE_FOCUS		((char *) NULL)
#define DEF_BUTTON_TAKE_FOCUS		NULL
#define DEF_BUTTON_TEXT			""
#define DEF_BUTTON_TEXT_VARIABLE	""
#define DEF_BUTTON_TRISTATE_VALUE	""
#define DEF_BUTTON_UNDERLINE		"-1"
#define DEF_BUTTON_VALUE		""
#define DEF_BUTTON_WIDTH		"0"
#define DEF_BUTTON_WRAP_LENGTH		"0"
122
123
124
125
126
127
128
129

130
131
132
133
134
135
136
122
123
124
125
126
127
128

129
130
131
132
133
134
135
136







-
+







#define DEF_CANVAS_SCROLL_REGION	""
#define DEF_CANVAS_SELECT_COLOR		SELECT_BG
#define DEF_CANVAS_SELECT_MONO		BLACK
#define DEF_CANVAS_SELECT_BD_COLOR	"1"
#define DEF_CANVAS_SELECT_BD_MONO	"0"
#define DEF_CANVAS_SELECT_FG_COLOR	SELECT_FG
#define DEF_CANVAS_SELECT_FG_MONO	WHITE
#define DEF_CANVAS_TAKE_FOCUS		((char *) NULL)
#define DEF_CANVAS_TAKE_FOCUS		NULL
#define DEF_CANVAS_WIDTH		"10c"
#define DEF_CANVAS_X_SCROLL_CMD		""
#define DEF_CANVAS_X_SCROLL_INCREMENT	"0"
#define DEF_CANVAS_Y_SCROLL_CMD		""
#define DEF_CANVAS_Y_SCROLL_INCREMENT	"0"

/*
153
154
155
156
157
158
159


160
161
162
163
164
165
166
167
168
169
170

171
172

173
174
175
176
177
178
179
180

181

182
183
184
185
186
187
188
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171

172
173

174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192







+
+










-
+

-
+








+

+







#define DEF_ENTRY_INSERT_BG		TEXT_FG
#define DEF_ENTRY_INSERT_BD_COLOR	"0"
#define DEF_ENTRY_INSERT_BD_MONO	"0"
#define DEF_ENTRY_INSERT_OFF_TIME	"300"
#define DEF_ENTRY_INSERT_ON_TIME	"600"
#define DEF_ENTRY_INSERT_WIDTH		"2"
#define DEF_ENTRY_JUSTIFY		"left"
#define DEF_ENTRY_PLACEHOLDER		""
#define DEF_ENTRY_PLACEHOLDERFG		"SystemPlaceHolderText"
#define DEF_ENTRY_READONLY_BG_COLOR	"SystemButtonFace"
#define DEF_ENTRY_READONLY_BG_MONO	WHITE
#define DEF_ENTRY_RELIEF		"sunken"
#define DEF_ENTRY_SCROLL_COMMAND	""
#define DEF_ENTRY_SELECT_COLOR		SELECT_BG
#define DEF_ENTRY_SELECT_MONO		BLACK
#define DEF_ENTRY_SELECT_BD_COLOR	"0"
#define DEF_ENTRY_SELECT_BD_MONO	"0"
#define DEF_ENTRY_SELECT_FG_COLOR	SELECT_FG
#define DEF_ENTRY_SELECT_FG_MONO	WHITE
#define DEF_ENTRY_SHOW			((char *) NULL)
#define DEF_ENTRY_SHOW			NULL
#define DEF_ENTRY_STATE			"normal"
#define DEF_ENTRY_TAKE_FOCUS		((char *) NULL)
#define DEF_ENTRY_TAKE_FOCUS		NULL
#define DEF_ENTRY_TEXT_VARIABLE		""
#define DEF_ENTRY_WIDTH			"20"

/*
 * Defaults for frames:
 */

#define DEF_FRAME_BG_COLOR		NORMAL_BG
#define DEF_FRAME_BG_IMAGE		NULL
#define DEF_FRAME_BG_MONO		WHITE
#define DEF_FRAME_BG_TILE		"0"
#define DEF_FRAME_BORDER_WIDTH		"0"
#define DEF_FRAME_CLASS			"Frame"
#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
232
233
234
235
236
237
238
239

240
241
242
243
244
245
246
247
248
249




250
251
252

253
254
255


256
257

258
259
260


261
262
263

264
265
266


267
268

269
270
271
272
273
274
275
276
277
278
279

280
281
282
283
284
285
286
287
288
289
290
291
292
293
294


295
296
297
298
299
300
301
236
237
238
239
240
241
242

243
244
245
246
247
248
249




250
251
252
253
254
255

256
257


258
259
260

261
262


263
264
265
266

267
268


269
270
271

272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297


298
299
300
301
302
303
304
305
306







-
+






-
-
-
-
+
+
+
+


-
+

-
-
+
+

-
+

-
-
+
+


-
+

-
-
+
+

-
+











+













-
-
+
+







#define DEF_LISTBOX_SELECT_MONO		BLACK
#define DEF_LISTBOX_SELECT_BD		"0"
#define DEF_LISTBOX_SELECT_FG_COLOR	SELECT_FG
#define DEF_LISTBOX_SELECT_FG_MONO	WHITE
#define DEF_LISTBOX_SELECT_MODE		"browse"
#define DEF_LISTBOX_SET_GRID		"0"
#define DEF_LISTBOX_STATE		"normal"
#define DEF_LISTBOX_TAKE_FOCUS		((char *) NULL)
#define DEF_LISTBOX_TAKE_FOCUS		NULL
#define DEF_LISTBOX_WIDTH		"20"

/*
 * Defaults for individual entries of menus:
 */

#define DEF_MENU_ENTRY_ACTIVE_BG	((char *) NULL)
#define DEF_MENU_ENTRY_ACTIVE_FG	((char *) NULL)
#define DEF_MENU_ENTRY_ACCELERATOR	((char *) NULL)
#define DEF_MENU_ENTRY_BG		((char *) NULL)
#define DEF_MENU_ENTRY_ACTIVE_BG	NULL
#define DEF_MENU_ENTRY_ACTIVE_FG	NULL
#define DEF_MENU_ENTRY_ACCELERATOR	NULL
#define DEF_MENU_ENTRY_BG		NULL
#define DEF_MENU_ENTRY_BITMAP		NULL
#define DEF_MENU_ENTRY_COLUMN_BREAK	"0"
#define DEF_MENU_ENTRY_COMMAND		((char *) NULL)
#define DEF_MENU_ENTRY_COMMAND		NULL
#define DEF_MENU_ENTRY_COMPOUND 	"none"
#define DEF_MENU_ENTRY_FG		((char *) NULL)
#define DEF_MENU_ENTRY_FONT		((char *) NULL)
#define DEF_MENU_ENTRY_FG		NULL
#define DEF_MENU_ENTRY_FONT		NULL
#define DEF_MENU_ENTRY_HIDE_MARGIN	"0"
#define DEF_MENU_ENTRY_IMAGE		((char *) NULL)
#define DEF_MENU_ENTRY_IMAGE		NULL
#define DEF_MENU_ENTRY_INDICATOR	"1"
#define DEF_MENU_ENTRY_LABEL		((char *) NULL)
#define DEF_MENU_ENTRY_MENU		((char *) NULL)
#define DEF_MENU_ENTRY_LABEL		NULL
#define DEF_MENU_ENTRY_MENU		NULL
#define DEF_MENU_ENTRY_OFF_VALUE	"0"
#define DEF_MENU_ENTRY_ON_VALUE		"1"
#define DEF_MENU_ENTRY_SELECT_IMAGE	((char *) NULL)
#define DEF_MENU_ENTRY_SELECT_IMAGE	NULL
#define DEF_MENU_ENTRY_STATE		"normal"
#define DEF_MENU_ENTRY_VALUE		((char *) NULL)
#define DEF_MENU_ENTRY_CHECK_VARIABLE	((char *) NULL)
#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		((char *) NULL)
#define DEF_MENU_ENTRY_SELECT		NULL
#define DEF_MENU_ENTRY_UNDERLINE	"-1"

/*
 * Defaults for menus overall:
 */

#define DEF_MENU_ACTIVE_BG_COLOR	SELECT_BG
#define DEF_MENU_ACTIVE_BG_MONO		BLACK
#define DEF_MENU_ACTIVE_BORDER_WIDTH	"0"
#define DEF_MENU_ACTIVE_FG_COLOR	SELECT_FG
#define DEF_MENU_ACTIVE_FG_MONO		WHITE
#define DEF_MENU_ACTIVE_RELIEF		"flat"
#define DEF_MENU_BG_COLOR		MENU_BG
#define DEF_MENU_BG_MONO		WHITE
#define DEF_MENU_BORDER_WIDTH		"0"
#define DEF_MENU_CURSOR			"arrow"
#define DEF_MENU_DISABLED_FG_COLOR	DISABLED
#define DEF_MENU_DISABLED_FG_MONO	""
#define DEF_MENU_FONT			"TkMenuFont"
#define DEF_MENU_FG			MENU_FG
#define DEF_MENU_POST_COMMAND		""
#define DEF_MENU_RELIEF			"flat"
#define DEF_MENU_SELECT_COLOR		MENU_FG
#define DEF_MENU_SELECT_MONO		BLACK
#define DEF_MENU_TAKE_FOCUS		"0"
#define DEF_MENU_TEAROFF		"1"
#define DEF_MENU_TEAROFF_CMD		((char *) NULL)
#define DEF_MENU_TEAROFF		"0"
#define DEF_MENU_TEAROFF_CMD		NULL
#define DEF_MENU_TITLE			""
#define DEF_MENU_TYPE			"normal"

/*
 * Defaults for menubuttons:
 */

315
316
317
318
319
320
321
322

323
324
325
326
327
328
329
320
321
322
323
324
325
326

327
328
329
330
331
332
333
334







-
+







#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	HIGHLIGHT
#define DEF_MENUBUTTON_HIGHLIGHT_WIDTH	"0"
#define DEF_MENUBUTTON_IMAGE		((char *) NULL)
#define DEF_MENUBUTTON_IMAGE		NULL
#define DEF_MENUBUTTON_INDICATOR	"0"
#define DEF_MENUBUTTON_JUSTIFY		"center"
#define DEF_MENUBUTTON_MENU		""
#define DEF_MENUBUTTON_PADX		"4p"
#define DEF_MENUBUTTON_PADY		"3p"
#define DEF_MENUBUTTON_RELIEF		"flat"
#define DEF_MENUBUTTON_STATE		"normal"
425
426
427
428
429
430
431
432

433
434
435
436
437
438
439
430
431
432
433
434
435
436

437
438
439
440
441
442
443
444







-
+







#define DEF_SCALE_RESOLUTION		"1"
#define DEF_SCALE_TROUGH_COLOR		TROUGH
#define DEF_SCALE_TROUGH_MONO		WHITE
#define DEF_SCALE_SHOW_VALUE		"1"
#define DEF_SCALE_SLIDER_LENGTH		"30"
#define DEF_SCALE_SLIDER_RELIEF		"raised"
#define DEF_SCALE_STATE			"normal"
#define DEF_SCALE_TAKE_FOCUS		((char *) NULL)
#define DEF_SCALE_TAKE_FOCUS		NULL
#define DEF_SCALE_TICK_INTERVAL		"0"
#define DEF_SCALE_TO			"100"
#define DEF_SCALE_VARIABLE		""
#define DEF_SCALE_WIDTH			"15"

/*
 * Defaults for scrollbars:
452
453
454
455
456
457
458
459

460
461
462
463
464
465
466
457
458
459
460
461
462
463

464
465
466
467
468
469
470
471







-
+







#define DEF_SCROLLBAR_HIGHLIGHT	HIGHLIGHT
#define DEF_SCROLLBAR_HIGHLIGHT_WIDTH	"0"
#define DEF_SCROLLBAR_JUMP		"0"
#define DEF_SCROLLBAR_ORIENT		"vertical"
#define DEF_SCROLLBAR_RELIEF		"sunken"
#define DEF_SCROLLBAR_REPEAT_DELAY	"300"
#define DEF_SCROLLBAR_REPEAT_INTERVAL	"100"
#define DEF_SCROLLBAR_TAKE_FOCUS	((char *) NULL)
#define DEF_SCROLLBAR_TAKE_FOCUS	NULL
#define DEF_SCROLLBAR_TROUGH_COLOR	TROUGH
#define DEF_SCROLLBAR_TROUGH_MONO	WHITE
#define DEF_SCROLLBAR_WIDTH		"10"

/*
 * Defaults for texts:
 */
500
501
502
503
504
505
506
507

508
509
510
511
512
513
514
505
506
507
508
509
510
511

512
513
514
515
516
517
518
519







-
+







#define DEF_TEXT_SET_GRID		"0"
#define DEF_TEXT_SPACING1		"0"
#define DEF_TEXT_SPACING2		"0"
#define DEF_TEXT_SPACING3		"0"
#define DEF_TEXT_STATE			"normal"
#define DEF_TEXT_TABS			""
#define DEF_TEXT_TABSTYLE		"tabular"
#define DEF_TEXT_TAKE_FOCUS		((char *) NULL)
#define DEF_TEXT_TAKE_FOCUS		NULL
#define DEF_TEXT_UNDO			"0"
#define DEF_TEXT_WIDTH			"80"
#define DEF_TEXT_WRAP			"char"
#define DEF_TEXT_XSCROLL_COMMAND	""
#define DEF_TEXT_YSCROLL_COMMAND	""

/*
Changes to win/tkWinDialog.c.
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







/*
 * tkWinDialog.c --
 *
 *	Contains the Windows implementation of the common dialog boxes.
 *
 * 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.
 */

#include "tkWinInt.h"
#include "tkFileFilter.h"
419
420
421
422
423
424
425
426

427
428
429
430
431
432
433
419
420
421
422
423
424
425

426
427
428
429
430
431
432
433







-
+








    HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
        IFileSaveDialog *, REFIID, void **);
    ULONG ( STDMETHODCALLTYPE *AddRef )( IFileSaveDialog *);
    ULONG ( STDMETHODCALLTYPE *Release )( IFileSaveDialog *);
    HRESULT ( STDMETHODCALLTYPE *Show )(
        IFileSaveDialog *, HWND);
    HRESULT ( STDMETHODCALLTYPE *SetFileTypes )( IFileSaveDialog * this,
    HRESULT ( STDMETHODCALLTYPE *SetFileTypes )( IFileSaveDialog *,
        UINT, const TCLCOMDLG_FILTERSPEC *);
    HRESULT ( STDMETHODCALLTYPE *SetFileTypeIndex )(
        IFileSaveDialog *, UINT);
    HRESULT ( STDMETHODCALLTYPE *GetFileTypeIndex )(
         IFileSaveDialog *, UINT *);
    /* Actually pfde is IFileSaveDialogEvents* */
    HRESULT ( STDMETHODCALLTYPE *Advise )(
585
586
587
588
589
590
591
592

593
594
595
596
597
598
599
600
585
586
587
588
589
590
591

592

593
594
595
596
597
598
599







-
+
-







static int 		MakeFilter(Tcl_Interp *interp, Tcl_Obj *valuePtr,
			    Tcl_DString *dsPtr, Tcl_Obj *initialPtr,
			    int *indexPtr);
static UINT APIENTRY	OFNHookProc(HWND hdlg, UINT uMsg, WPARAM wParam,
			    LPARAM lParam);
static LRESULT CALLBACK MsgBoxCBTProc(int nCode, WPARAM wParam, LPARAM lParam);
static void		SetTkDialog(ClientData clientData);
static const char *ConvertExternalFilename(WCHAR *filename,
static const char *ConvertExternalFilename(LPCWSTR, Tcl_DString *);
			    Tcl_DString *dsPtr);
static void             LoadShellProcs(void);


/* Definitions of dynamically loaded Win32 calls */
typedef HRESULT (STDAPICALLTYPE SHCreateItemFromParsingNameProc)(
    PCWSTR pszPath, IBindCtx *pbc, REFIID riid, void **ppv);
struct ShellProcPointers {
626
627
628
629
630
631
632
633

634
635
636
637
638
639




640
641
642
643
644





645
646

647
648
649
650
651
652
653
625
626
627
628
629
630
631

632
633
634
635



636
637
638
639
640




641
642
643
644
645


646
647
648
649
650
651
652
653







-
+



-
-
-
+
+
+
+

-
-
-
-
+
+
+
+
+
-
-
+







 * Return value:
 *     None.
 *
 * Side effects:
 *     ShellProcs is populated.
 *-------------------------------------------------------------------------
 */
static void LoadShellProcs()
static void LoadShellProcs(void)
{
    static HMODULE shell32_handle = NULL;

    if (shell32_handle != NULL)
        return; /* We have already been through here. */

    if (shell32_handle != NULL) {
	return; /* We have already been through here. */
    }

    shell32_handle = GetModuleHandleW(L"shell32.dll");
    if (shell32_handle == NULL) /* Should never happen but check anyways. */
        return;

    ShellProcs.SHCreateItemFromParsingName =
    if (shell32_handle == NULL) { /* Should never happen but check anyways. */
	return;
    }

    ShellProcs.SHCreateItemFromParsingName = (SHCreateItemFromParsingNameProc*)
        (SHCreateItemFromParsingNameProc*) GetProcAddress(shell32_handle,
                                                         "SHCreateItemFromParsingName");
	    (void *)GetProcAddress(shell32_handle, "SHCreateItemFromParsingName");
}


/*
 *-------------------------------------------------------------------------
 *
 * EatSpuriousMessageBugFix --
715
716
717
718
719
720
721
722

723
724
725
726
727
728
729
715
716
717
718
719
720
721

722
723
724
725
726
727
728
729







-
+







 *-------------------------------------------------------------------------
 */

void
TkWinDialogDebug(
    int debug)
{
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    tsdPtr->debugFlag = debug;
}

/*
 *-------------------------------------------------------------------------
747
748
749
750
751
752
753
754

755
756
757
758
759
760
761
747
748
749
750
751
752
753

754
755
756
757
758
759
760
761







-
+







int
Tk_ChooseColorObjCmd(
    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, parent;
    Tk_Window tkwin = (Tk_Window)clientData, parent;
    HWND hWnd;
    int i, oldMode, winCode, result;
    CHOOSECOLORW chooseColor;
    static int inited = 0;
    static COLORREF dwCustColors[16];
    static long oldColor;		/* the color selected last time */
    static const char *const optionStrings[] = {
785
786
787
788
789
790
791
792

793
794
795
796
797
798
799
785
786
787
788
789
790
791

792
793
794
795
796
797
798
799







-
+







    chooseColor.lStructSize	= sizeof(CHOOSECOLOR);
    chooseColor.hwndOwner	= NULL;
    chooseColor.hInstance	= NULL;
    chooseColor.rgbResult	= oldColor;
    chooseColor.lpCustColors	= dwCustColors;
    chooseColor.Flags		= CC_RGBINIT | CC_FULLOPEN | CC_ENABLEHOOK;
    chooseColor.lCustData	= (LPARAM) NULL;
    chooseColor.lpfnHook	= (LPOFNHOOKPROC) ColorDlgHookProc;
    chooseColor.lpfnHook	= (LPOFNHOOKPROC)(void *)ColorDlgHookProc;
    chooseColor.lpTemplateName	= (LPWSTR) interp;

    for (i = 1; i < objc; i += 2) {
	int index;
	const char *string;
	Tcl_Obj *optionPtr, *valuePtr;

901
902
903
904
905
906
907
908

909
910
911

912
913
914
915
916
917
918
919
920
921
922
923
924

925

926
927
928
929
930
931
932
901
902
903
904
905
906
907

908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926

927
928
929
930
931
932
933
934







-
+



+













+
-
+







static UINT CALLBACK
ColorDlgHookProc(
    HWND hDlg,			/* Handle to the color dialog. */
    UINT uMsg,			/* Type of message. */
    WPARAM wParam,		/* First message parameter. */
    LPARAM lParam)		/* Second message parameter. */
{
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    const char *title;
    CHOOSECOLOR *ccPtr;
    (void)wParam;

    if (WM_INITDIALOG == uMsg) {

	/*
	 * Set the title string of the dialog.
	 */

	ccPtr = (CHOOSECOLOR *) lParam;
	title = (const char *) ccPtr->lCustData;

	if ((title != NULL) && (title[0] != '\0')) {
	    Tcl_DString ds;

	    Tcl_DStringInit(&ds);
	    SetWindowTextW(hDlg, (LPCWSTR)Tcl_WinUtfToTChar(title,-1,&ds));
	    SetWindowTextW(hDlg, Tcl_UtfToWCharDString(title, -1, &ds));
	    Tcl_DStringFree(&ds);
	}
	if (tsdPtr->debugFlag) {
	    tsdPtr->debugInterp = (Tcl_Interp *) ccPtr->lpTemplateName;
	    Tcl_DoWhenIdle(SetTkDialog, hDlg);
	}
	return TRUE;
1080
1081
1082
1083
1084
1085
1086
1087
1088


1089
1090
1091
1092
1093
1094
1095
1082
1083
1084
1085
1086
1087
1088


1089
1090
1091
1092
1093
1094
1095
1096
1097







-
-
+
+







    switch (oper) {
    case OFN_FILE_SAVE: options = saveOptions; break;
    case OFN_DIR_CHOOSE: options = dirOptions; break;
    case OFN_FILE_OPEN: options = openOptions; break;
    }

    ZeroMemory(optsPtr, sizeof(*optsPtr));
    // optsPtr->forceXPStyle = 1;
    optsPtr->tkwin = clientData;
    /* optsPtr->forceXPStyle = 1; */
    optsPtr->tkwin = (Tk_Window)clientData;
    optsPtr->confirmOverwrite = 1; /* By default we ask for confirmation */
    Tcl_DStringInit(&optsPtr->utfDirString);
    optsPtr->file[0] = 0;

    for (i = 1; i < objc; i += 2) {
	int index;
	const char *string;
1142
1143
1144
1145
1146
1147
1148
1149

1150
1151
1152
1153
1154
1155
1156
1144
1145
1146
1147
1148
1149
1150

1151
1152
1153
1154
1155
1156
1157
1158







-
+







	    Tcl_UtfToExternal(NULL, TkWinGetUnicodeEncoding(),
                              Tcl_DStringValue(&ds), Tcl_DStringLength(&ds), 0, NULL,
                              (char *) &optsPtr->file[0], sizeof(optsPtr->file),
                              NULL, NULL, NULL);
	    Tcl_DStringFree(&ds);
	    break;
	case FILE_PARENT:
	    optsPtr->tkwin = Tk_NameToWindow(interp, string, clientData);
	    optsPtr->tkwin = Tk_NameToWindow(interp, string, (Tk_Window)clientData);
	    if (optsPtr->tkwin == NULL)
		goto error_return;
	    break;
	case FILE_TITLE:
	    optsPtr->titleObj = valuePtr;
	    break;
	case FILE_TYPEVARIABLE:
1197
1198
1199
1200
1201
1202
1203
1204

1205
1206
1207
1208

1209
1210
1211
1212
1213
1214
1215
1199
1200
1201
1202
1203
1204
1205

1206
1207
1208
1209

1210
1211
1212
1213
1214
1215
1216
1217







-
+



-
+







 *      1 if new dialogs are available, 0 otherwise
 *
 * Side effects:
 *      Loads required procedures dynamically if available.
 *      If new dialogs are available, COM is also initialized.
 *----------------------------------------------------------------------
 */
static int VistaFileDialogsAvailable()
static int VistaFileDialogsAvailable(void)
{
    HRESULT hr;
    IFileDialog *fdlgPtr = NULL;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
        Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (tsdPtr->newFileDialogsState == FDLG_STATE_INIT) {
        tsdPtr->newFileDialogsState = FDLG_STATE_USE_OLD;
        LoadShellProcs();
        if (ShellProcs.SHCreateItemFromParsingName != NULL) {
            hr = CoInitialize(0);
1263
1264
1265
1266
1267
1268
1269
1270

1271
1272
1273
1274
1275
1276
1277
1265
1266
1267
1268
1269
1270
1271

1272
1273
1274
1275
1276
1277
1278
1279







-
+







    HWND hWnd;
    DWORD flags, nfilters, defaultFilterIndex;
    TCLCOMDLG_FILTERSPEC *filterPtr = NULL;
    IFileDialog *fdlgIf = NULL;
    IShellItem *dirIf = NULL;
    LPWSTR wstr;
    Tcl_Obj *resultObj = NULL;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    int oldMode;

    if (tsdPtr->newFileDialogsState != FDLG_STATE_USE_NEW) {
	Tcl_Panic("Internal error: GetFileNameVista: IFileDialog API not available");
	return TCL_ERROR;
    }
1367
1368
1369
1370
1371
1372
1373

1374
1375


1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387

1388

1389
1390
1391
1392
1393
1394
1395
1369
1370
1371
1372
1373
1374
1375
1376


1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391

1392
1393
1394
1395
1396
1397
1398
1399







+
-
-
+
+












+
-
+







        goto vamoose;

    if (optsPtr->extObj != NULL) {
        Tcl_DString ds;
        const char *src;

        src = Tcl_GetString(optsPtr->extObj);
        Tcl_DStringInit(&ds);
        wstr = (LPWSTR) Tcl_WinUtfToTChar(src, optsPtr->extObj->length, &ds);
        if (wstr[0] == L'.')
        wstr = Tcl_UtfToWCharDString(src, optsPtr->extObj->length, &ds);
        if (wstr[0] == '.')
            ++wstr;
        hr = fdlgIf->lpVtbl->SetDefaultExtension(fdlgIf, wstr);
        Tcl_DStringFree(&ds);
        if (FAILED(hr))
            goto vamoose;
    }

    if (optsPtr->titleObj != NULL) {
        Tcl_DString ds;
        const char *src;

        src = Tcl_GetString(optsPtr->titleObj);
        Tcl_DStringInit(&ds);
        wstr = (LPWSTR) Tcl_WinUtfToTChar(src, optsPtr->titleObj->length, &ds);
        wstr = Tcl_UtfToWCharDString(src, optsPtr->titleObj->length, &ds);
        hr = fdlgIf->lpVtbl->SetTitle(fdlgIf, wstr);
        Tcl_DStringFree(&ds);
        if (FAILED(hr))
            goto vamoose;
    }

    if (optsPtr->file[0]) {
1403
1404
1405
1406
1407
1408
1409
1410

1411
1412
1413
1414
1415
1416
1417
1407
1408
1409
1410
1411
1412
1413

1414
1415
1416
1417
1418
1419
1420
1421







-
+







        iniDirPath = Tcl_NewStringObj(Tcl_DStringValue(&optsPtr->utfDirString), -1);
        Tcl_IncrRefCount(iniDirPath);
        normPath = Tcl_FSGetNormalizedPath(interp, iniDirPath);
        /* XXX - Note on failures do not raise error, simply ignore ini dir */
        if (normPath) {
            LPCWSTR nativePath;
            Tcl_IncrRefCount(normPath);
            nativePath = Tcl_FSGetNativePath(normPath); /* Points INTO normPath*/
            nativePath = (LPCWSTR)Tcl_FSGetNativePath(normPath); /* Points INTO normPath*/
            if (nativePath) {
                hr = ShellProcs.SHCreateItemFromParsingName(
                    nativePath, NULL,
                    &IIDIShellItem, (void **) &dirIf);
                if (SUCCEEDED(hr)) {
                    /* Note we use SetFolder, not SetDefaultFolder - see MSDN */
                    fdlgIf->lpVtbl->SetFolder(fdlgIf, dirIf); /* Ignore errors */
1507
1508
1509
1510
1511
1512
1513

1514

1515
1516
1517
1518
1519
1520
1521
1511
1512
1513
1514
1515
1516
1517
1518

1519
1520
1521
1522
1523
1524
1525
1526







+
-
+







                hr = fdlgIf->lpVtbl->GetFileTypeIndex(fdlgIf, &ftix);
                if (SUCCEEDED(hr)) {
                    /* Note ftix is a 1-based index */
                    if (ftix > 0 && ftix <= nfilters) {
                        Tcl_DString ftds;
                        Tcl_Obj *ftobj;

                        Tcl_DStringInit(&ftds);
                        Tcl_WinTCharToUtf((LPCTSTR)filterPtr[ftix-1].pszName, -1, &ftds);
                        Tcl_WCharToUtfDString(filterPtr[ftix-1].pszName, wcslen(filterPtr[ftix-1].pszName), &ftds);
                        ftobj = Tcl_NewStringObj(Tcl_DStringValue(&ftds),
                                Tcl_DStringLength(&ftds));
                        Tcl_ObjSetVar2(interp, optsPtr->typeVariableObj, NULL,
                                ftobj, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG);
                        Tcl_DStringFree(&ftds);
                    }
                }
1569
1570
1571
1572
1573
1574
1575
1576

1577
1578
1579
1580
1581
1582
1583
1574
1575
1576
1577
1578
1579
1580

1581
1582
1583
1584
1585
1586
1587
1588







-
+







    OFNData ofnData;
    int cdlgerr;
    int filterIndex = 0, result = TCL_ERROR, winCode, oldMode;
    HWND hWnd;
    Tcl_DString utfFilterString, ds;
    Tcl_DString extString, filterString, dirString, titleString;
    const char *str;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
        Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    ZeroMemory(&ofnData, sizeof(OFNData));
    Tcl_DStringInit(&utfFilterString);
    Tcl_DStringInit(&dirString); /* XXX - original code was missing this
                                    leaving dirString uninitialized for
                                    the unlikely code path where cwd failed */
1594
1595
1596
1597
1598
1599
1600
1601

1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621

1622
1623
1624
1625
1626
1627
1628
1629






1630
1631

1632

1633
1634
1635
1636
1637

1638

1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653

1654

1655
1656
1657
1658
1659
1660
1661

1662

1663
1664
1665
1666
1667
1668
1669
1670
1599
1600
1601
1602
1603
1604
1605

1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625

1626
1627
1628
1629





1630
1631
1632
1633
1634
1635
1636
1637
1638

1639
1640

1641
1642
1643
1644

1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661

1662
1663
1664
1665
1666
1667
1668
1669
1670

1671

1672
1673
1674
1675
1676
1677
1678







-
+



















-
+



-
-
-
-
-
+
+
+
+
+
+


+
-
+

-



+
-
+















+
-
+







+
-
+
-







    ofn.lStructSize = sizeof(OPENFILENAME);
    ofn.hwndOwner = hWnd;
    ofn.hInstance = TkWinGetHInstance(ofn.hwndOwner);
    ofn.lpstrFile = optsPtr->file;
    ofn.nMaxFile = TK_MULTI_MAX_PATH;
    ofn.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | OFN_NOCHANGEDIR
	    | OFN_EXPLORER| OFN_ENABLEHOOK| OFN_ENABLESIZING;
    ofn.lpfnHook = (LPOFNHOOKPROC) OFNHookProc;
    ofn.lpfnHook = (LPOFNHOOKPROC)(void *)OFNHookProc;
    ofn.lCustData = (LPARAM) &ofnData;

    if (oper != OFN_FILE_SAVE) {
	ofn.Flags |= OFN_FILEMUSTEXIST;
    } else if (optsPtr->confirmOverwrite) {
	ofn.Flags |= OFN_OVERWRITEPROMPT;
    }
    if (tsdPtr->debugFlag != 0) {
	ofnData.interp = interp;
    }
    if (optsPtr->multi != 0) {
	ofn.Flags |= OFN_ALLOWMULTISELECT;

	/*
	 * Starting buffer size. The buffer will be expanded by the OFN dialog
	 * procedure when necessary
	 */

	ofnData.dynFileBufferSize = 512;
	ofnData.dynFileBuffer = ckalloc(512 * sizeof(WCHAR));
	ofnData.dynFileBuffer = (WCHAR *)ckalloc(512 * sizeof(WCHAR));
    }

    if (optsPtr->extObj != NULL) {
        str = Tcl_GetString(optsPtr->extObj);
        if (str[0] == '.')
            ++str;
	Tcl_WinUtfToTChar(str, -1, &extString);
	ofn.lpstrDefExt = (WCHAR *) Tcl_DStringValue(&extString);
	str = Tcl_GetString(optsPtr->extObj);
	if (str[0] == '.') {
	    ++str;
	}
	Tcl_DStringInit(&extString);
	ofn.lpstrDefExt = Tcl_UtfToWCharDString(str, -1, &extString);
    }

    Tcl_DStringInit(&filterString);
    Tcl_WinUtfToTChar(Tcl_DStringValue(&utfFilterString),
    ofn.lpstrFilter = Tcl_UtfToWCharDString(Tcl_DStringValue(&utfFilterString),
	    Tcl_DStringLength(&utfFilterString), &filterString);
    ofn.lpstrFilter = (WCHAR *) Tcl_DStringValue(&filterString);
    ofn.nFilterIndex = filterIndex;

    if (Tcl_DStringValue(&optsPtr->utfDirString)[0] != '\0') {
	Tcl_DStringInit(&dirString);
	Tcl_WinUtfToTChar(Tcl_DStringValue(&optsPtr->utfDirString),
	Tcl_UtfToWCharDString(Tcl_DStringValue(&optsPtr->utfDirString),
		Tcl_DStringLength(&optsPtr->utfDirString), &dirString);
    } else {
	/*
	 * NT 5.0 changed the meaning of lpstrInitialDir, so we have to ensure
	 * that we set the [pwd] if the user didn't specify anything else.
	 */

	Tcl_DString cwd;

	Tcl_DStringFree(&optsPtr->utfDirString);
	if ((Tcl_GetCwd(interp, &optsPtr->utfDirString) == NULL) ||
		(Tcl_TranslateFileName(interp,
                     Tcl_DStringValue(&optsPtr->utfDirString), &cwd) == NULL)) {
	    Tcl_ResetResult(interp);
	} else {
		Tcl_DStringInit(&dirString);
	    Tcl_WinUtfToTChar(Tcl_DStringValue(&cwd),
		Tcl_UtfToWCharDString(Tcl_DStringValue(&cwd),
		    Tcl_DStringLength(&cwd), &dirString);
	}
	Tcl_DStringFree(&cwd);
    }
    ofn.lpstrInitialDir = (WCHAR *) Tcl_DStringValue(&dirString);

    if (optsPtr->titleObj != NULL) {
	Tcl_DStringInit(&titleString);
	Tcl_WinUtfToTChar(Tcl_GetString(optsPtr->titleObj), -1, &titleString);
	ofn.lpstrTitle = Tcl_UtfToWCharDString(Tcl_GetString(optsPtr->titleObj), -1, &titleString);
	ofn.lpstrTitle = (WCHAR *) Tcl_DStringValue(&titleString);
    }

    /*
     * Popup the dialog.
     */

    oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
1909
1910
1911
1912
1913
1914
1915
1916

1917
1918
1919

1920
1921
1922
1923
1924
1925
1926
1917
1918
1919
1920
1921
1922
1923

1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935







-
+



+







static UINT APIENTRY
OFNHookProc(
    HWND hdlg,			/* Handle to child dialog window. */
    UINT uMsg,			/* Message identifier */
    WPARAM wParam,		/* Message parameter */
    LPARAM lParam)		/* Message parameter */
{
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    OPENFILENAME *ofnPtr;
    OFNData *ofnData;
    (void)wParam;

    if (uMsg == WM_INITDIALOG) {
	TkWinSetUserData(hdlg, lParam);
    } else if (uMsg == WM_NOTIFY) {
	OFNOTIFY *notifyPtr = (OFNOTIFY *) lParam;

	/*
1957
1958
1959
1960
1961
1962
1963
1964

1965
1966
1967
1968
1969
1970
1971
1966
1967
1968
1969
1970
1971
1972

1973
1974
1975
1976
1977
1978
1979
1980







-
+







	    /*
	     * Just empty the buffer if dirsize indicates an error. [Bug
	     * 3071836]
	     */

	    if ((selsize > 1) && (dirsize > 0)) {
		if (ofnData->dynFileBufferSize < buffersize) {
		    buffer = ckrealloc(buffer, buffersize * sizeof(WCHAR));
		    buffer = (WCHAR *)ckrealloc(buffer, buffersize * sizeof(WCHAR));
		    ofnData->dynFileBufferSize = buffersize;
		    ofnData->dynFileBuffer = buffer;
		}

		SendMessageW(hdlg, CDM_GETFOLDERPATH, dirsize, (LPARAM) buffer);
		buffer += dirsize;

2003
2004
2005
2006
2007
2008
2009
2010

2011
2012
2013
2014
2015
2016
2017
2012
2013
2014
2015
2016
2017
2018

2019
2020
2021
2022
2023
2024
2025
2026







-
+







		     */

		    Tcl_DString tmpfile;
		    ConvertExternalFilename(buffer, &tmpfile);
		    if (TCL_PATH_ABSOLUTE ==
			    Tcl_GetPathType(Tcl_DStringValue(&tmpfile))) {
			/* re-get the full path to the start of the buffer */
			buffer = (WCHAR *) ofnData->dynFileBuffer;
			buffer = ofnData->dynFileBuffer;
			SendMessageW(hdlg, CDM_GETSPEC, selsize, (LPARAM) buffer);
		    } else {
			*(buffer-1) = '\\';
		    }
		    buffer[selsize] = '\0'; /* Second NULL terminator. */
		    Tcl_DStringFree(&tmpfile);
		}
2089
2090
2091
2092
2093
2094
2095
2096

2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110

2111
2112
2113
2114
2115

2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133

2134
2135
2136
2137
2138
2139
2140
2098
2099
2100
2101
2102
2103
2104

2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118

2119
2120
2121
2122
2123

2124

2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140

2141
2142
2143
2144
2145
2146
2147
2148







-
+













-
+




-
+
-
















-
+








    if (flist.filters == NULL) {
	/*
	 * Use "All Files (*.*) as the default filter if none is specified
	 */
	const char *defaultFilter = "All Files (*.*)";

	p = filterStr = ckalloc(30);
	p = filterStr = (char *)ckalloc(30);

	strcpy(p, defaultFilter);
	p+= strlen(defaultFilter);

	*p++ = '\0';
	*p++ = '*';
	*p++ = '.';
	*p++ = '*';
	*p++ = '\0';
	*p++ = '\0';
	*p = '\0';

    } else {
	size_t len;
	TkSizeT len;

	if (valuePtr == NULL) {
	    len = 0;
	} else {
	    (void) Tcl_GetString(valuePtr);
	    (void) TkGetStringFromObj(valuePtr, &len);
	    len = valuePtr->length;
	}

	/*
	 * We format the filetype into a string understood by Windows: {"Text
	 * Documents" {.doc .txt} {TEXT}} becomes "Text Documents
	 * (*.doc,*.txt)\0*.doc;*.txt\0"
	 *
	 * See the Windows OPENFILENAME manual page for details on the filter
	 * string format.
	 */

	/*
	 * Since we may only add asterisks (*) to the filter, we need at most
	 * twice the size of the string to format the filter
	 */

	filterStr = ckalloc(len * 3);
	filterStr = (char *)ckalloc(len * 3);

	for (filterPtr = flist.filters, p = filterStr; filterPtr;
		filterPtr = filterPtr->next) {
	    const char *sep;
	    FileFilterClause *clausePtr;

	    /*
2216
2217
2218
2219
2220
2221
2222
2223

2224
2225

2226
2227
2228
2229
2230
2231
2232
2224
2225
2226
2227
2228
2229
2230

2231
2232

2233
2234
2235
2236
2237
2238
2239
2240







-
+

-
+







 */
static void FreeFilterVista(DWORD count, TCLCOMDLG_FILTERSPEC *dlgFilterPtr)
{
    if (dlgFilterPtr != NULL) {
        DWORD dw;
        for (dw = 0; dw < count; ++dw) {
            if (dlgFilterPtr[dw].pszName != NULL)
                ckfree(dlgFilterPtr[dw].pszName);
                ckfree((char *)dlgFilterPtr[dw].pszName);
            if (dlgFilterPtr[dw].pszSpec != NULL)
                ckfree(dlgFilterPtr[dw].pszSpec);
                ckfree((char *)dlgFilterPtr[dw].pszSpec);
        }
        ckfree(dlgFilterPtr);
    }
}

/*
 *----------------------------------------------------------------------
2279
2280
2281
2282
2283
2284
2285
2286

2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299

2300

2301
2302
2303

2304
2305
2306
2307
2308
2309
2310
2287
2288
2289
2290
2291
2292
2293

2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308

2309
2310
2311

2312
2313
2314
2315
2316
2317
2318
2319







-
+













+
-
+


-
+







        *dlgFilterPtrPtr = NULL;
        *countPtr = 0;
        return TCL_OK;
    }

    Tcl_DStringInit(&ds);
    Tcl_DStringInit(&patterns);
    dlgFilterPtr = ckalloc(flist.numFilters * sizeof(*dlgFilterPtr));
    dlgFilterPtr = (TCLCOMDLG_FILTERSPEC *)ckalloc(flist.numFilters * sizeof(*dlgFilterPtr));

    for (i = 0, filterPtr = flist.filters;
         filterPtr;
         filterPtr = filterPtr->next, ++i) {
	const char *sep;
	FileFilterClause *clausePtr;
	int nbytes;

	/* Check if this entry should be shown as the default */
	if (initial && strcmp(initial, filterPtr->name) == 0)
            initialIndex = i+1; /* Windows filter indices are 1-based */

	/* First stash away the text description of the pattern */
        Tcl_DStringInit(&ds);
	Tcl_WinUtfToTChar(filterPtr->name, -1, &ds);
        Tcl_UtfToWCharDString(filterPtr->name, -1, &ds);
	nbytes = Tcl_DStringLength(&ds); /* # bytes, not Unicode chars */
	nbytes += sizeof(WCHAR);         /* Terminating \0 */
	dlgFilterPtr[i].pszName = ckalloc(nbytes);
	dlgFilterPtr[i].pszName = (LPCWSTR)ckalloc(nbytes);
	memmove((void *) dlgFilterPtr[i].pszName, Tcl_DStringValue(&ds), nbytes);
	Tcl_DStringFree(&ds);

	/*
	 * Loop through and join patterns with a ";" Each "clause"
	 * corresponds to a single textual description (called typename)
	 * in the tk_getOpenFile docs. Each such typename may occur
2321
2322
2323
2324
2325
2326
2327

2328

2329
2330
2331

2332
2333
2334
2335
2336
2337
2338
2330
2331
2332
2333
2334
2335
2336
2337

2338
2339
2340

2341
2342
2343
2344
2345
2346
2347
2348







+
-
+


-
+







		Tcl_DStringAppend(&patterns, sep, -1);
		Tcl_DStringAppend(&patterns, globPtr->pattern, -1);
		sep = ";";
	    }
	}

	/* Again we need a Unicode form of the string */
        Tcl_DStringInit(&ds);
	Tcl_WinUtfToTChar(Tcl_DStringValue(&patterns), -1, &ds);
        Tcl_UtfToWCharDString(Tcl_DStringValue(&patterns), -1, &ds);
	nbytes = Tcl_DStringLength(&ds); /* # bytes, not Unicode chars */
	nbytes += sizeof(WCHAR);         /* Terminating \0 */
	dlgFilterPtr[i].pszSpec = ckalloc(nbytes);
	dlgFilterPtr[i].pszSpec = (LPCWSTR)ckalloc(nbytes);
	memmove((void *)dlgFilterPtr[i].pszSpec, Tcl_DStringValue(&ds), nbytes);
	Tcl_DStringFree(&ds);
	Tcl_DStringSetLength(&patterns, 0);
    }
    Tcl_DStringFree(&patterns);

    if (initialIndex == 0) {
2420
2421
2422
2423
2424
2425
2426
2427

2428
2429
2430
2431
2432
2433
2434
2430
2431
2432
2433
2434
2435
2436

2437
2438
2439
2440
2441
2442
2443
2444







-
+







int
Tk_ChooseDirectoryObjCmd(
    ClientData clientData,	/* Main window associated with interpreter. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
	WCHAR path[MAX_PATH];
    WCHAR path[MAX_PATH];
    int oldMode, result;
    LPCITEMIDLIST pidl;		/* Returned by browser */
    BROWSEINFOW bInfo;		/* Used by browser */
    ChooseDir cdCBData;	    /* Structure to pass back and forth */
    LPMALLOC pMalloc;		/* Used by shell */
    HWND hWnd;
    WCHAR saveDir[MAX_PATH];
2457
2458
2459
2460
2461
2462
2463

2464

2465
2466
2467
2468
2469
2470
2471
2467
2468
2469
2470
2471
2472
2473
2474

2475
2476
2477
2478
2479
2480
2481
2482







+
-
+







    cdCBData.interp = interp;
    cdCBData.mustExist = ofnOpts.mustExist;

    utfDir = Tcl_DStringValue(&ofnOpts.utfDirString);
    if (utfDir[0] != '\0') {
	LPCWSTR uniStr;

	Tcl_DStringInit(&tempString);
        Tcl_WinUtfToTChar(Tcl_DStringValue(&ofnOpts.utfDirString), -1,
	Tcl_UtfToWCharDString(Tcl_DStringValue(&ofnOpts.utfDirString), -1,
                          &tempString);
        uniStr = (WCHAR *) Tcl_DStringValue(&tempString);

        /* Convert possible relative path to full path to keep dialog happy. */

        GetFullPathNameW(uniStr, MAX_PATH, saveDir, NULL);
        wcsncpy(cdCBData.initDir, saveDir, MAX_PATH);
2489
2490
2491
2492
2493
2494
2495
2496
2497


2498
2499
2500
2501
2502
2503
2504
2500
2501
2502
2503
2504
2505
2506


2507
2508
2509
2510
2511
2512
2513
2514
2515







-
-
+
+







    bInfo.pidlRoot = NULL;
    if (wcslen(cdCBData.initDir) == 0) {
	GetCurrentDirectoryW(MAX_PATH, cdCBData.initDir);
    }
    bInfo.lParam = (LPARAM) &cdCBData;

    if (ofnOpts.titleObj != NULL) {
	bInfo.lpszTitle = (LPCWSTR)Tcl_WinUtfToTChar(
		Tcl_GetString(ofnOpts.titleObj), -1, &titleString);
	Tcl_DStringInit(&titleString);
	bInfo.lpszTitle = Tcl_UtfToWCharDString(Tcl_GetString(ofnOpts.titleObj), -1, &titleString);
    } else {
	bInfo.lpszTitle = L"Please choose a directory, then select OK.";
    }

    /*
     * Set flags to add edit box, status text line and use the new ui. Allow
     * override with magic variable (ignore errors in retrieval). See
2614
2615
2616
2617
2618
2619
2620
2621

2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640


2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652


2653
2654
2655
2656

2657
2658
2659
2660
2661
2662
2663
2625
2626
2627
2628
2629
2630
2631

2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650

2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662


2663
2664


2665
2666
2667
2668
2669
2670
2671
2672
2673
2674







-
+


















-
+
+










-
-
+
+
-
-


+







    LPARAM lpData)
{
    WCHAR selDir[MAX_PATH];
    ChooseDir *chooseDirSharedData = (ChooseDir *) lpData;
    Tcl_DString tempString;
    Tcl_DString initDirString;
    WCHAR string[MAX_PATH];
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (tsdPtr->debugFlag) {
	tsdPtr->debugInterp = (Tcl_Interp *) chooseDirSharedData->interp;
	Tcl_DoWhenIdle(SetTkDialog, hwnd);
    }
    chooseDirSharedData->retDir[0] = '\0';
    switch (message) {
    case BFFM_VALIDATEFAILEDW:
	/*
	 * First save and check to see if it is a valid path name, if so then
	 * make that path the one shown in the window. Otherwise, it failed
	 * the check and should be treated as such. Use
	 * Set/GetCurrentDirectory which allows relative path names and names
	 * with forward slashes. Use Tcl_TranslateFileName to make sure names
	 * like ~ are converted correctly.
	 */

	Tcl_WinTCharToUtf((LPCTSTR) lParam, -1, &initDirString);
	Tcl_DStringInit(&initDirString);
	Tcl_WCharToUtfDString((WCHAR *) lParam, wcslen((WCHAR *) lParam), &initDirString);
	if (Tcl_TranslateFileName(chooseDirSharedData->interp,
		Tcl_DStringValue(&initDirString), &tempString) == NULL) {
	    /*
	     * Should we expose the error (in the interp result) to the user
	     * at this point?
	     */

	    chooseDirSharedData->retDir[0] = '\0';
	    return 1;
	}
	Tcl_DStringFree(&initDirString);
	Tcl_WinUtfToTChar(Tcl_DStringValue(&tempString), -1, &initDirString);
	Tcl_DStringSetLength(&initDirString, 0);
	wcsncpy(string, Tcl_UtfToWCharDString(Tcl_DStringValue(&tempString), -1, &initDirString),
	Tcl_DStringFree(&tempString);
	wcsncpy(string, (WCHAR *) Tcl_DStringValue(&initDirString),
		MAX_PATH);
	Tcl_DStringFree(&initDirString);
	Tcl_DStringFree(&tempString);

	if (SetCurrentDirectoryW(string) == 0) {

	    /*
	     * Get the full path name to the user entry, at this point it does
	     * not exist so see if it is supposed to. Otherwise just return
	     * it.
2696
2697
2698
2699
2700
2701
2702
2703

2704
2705
2706

2707
2708
2709
2710
2711
2712
2713
2707
2708
2709
2710
2711
2712
2713

2714
2715
2716

2717
2718
2719
2720
2721
2722
2723
2724







-
+


-
+







	 * -enablenonfolders can be used to allow non folders to be selected.
	 *
	 * Not called when user changes edit box directly.
	 */

	if (SHGetPathFromIDListW((LPITEMIDLIST) lParam, selDir)) {
	    SendMessageW(hwnd, BFFM_SETSTATUSTEXTW, 0, (LPARAM) selDir);
	    // enable the OK button
	    /* enable the OK button */
	    SendMessageW(hwnd, BFFM_ENABLEOK, 0, (LPARAM) 1);
	} else {
	    // disable the OK button
	    /* disable the OK button */
	    SendMessageW(hwnd, BFFM_ENABLEOK, 0, (LPARAM) 0);
	}
	UpdateWindow(hwnd);
	return 1;

    case BFFM_INITIALIZED: {
	/*
2730
2731
2732
2733
2734
2735
2736
2737
2738


2739
2740
2741
2742
2743
2744
2745
2741
2742
2743
2744
2745
2746
2747


2748
2749
2750
2751
2752
2753
2754
2755
2756







-
-
+
+








	    if (SUCCEEDED(SHGetMalloc(&pMalloc))) {
		if (SUCCEEDED(SHGetDesktopFolder(&psfFolder))) {
		    LPITEMIDLIST pidlMain;
		    ULONG ulCount, ulAttr;

		    if (SUCCEEDED(psfFolder->lpVtbl->ParseDisplayName(
			    psfFolder, hwnd, NULL, (WCHAR *)
			    initDir, &ulCount,&pidlMain,&ulAttr))
			    psfFolder, hwnd, NULL, initDir,
			    &ulCount,&pidlMain,&ulAttr))
			    && (pidlMain != NULL)) {
			SendMessageW(hwnd, BFFM_SETSELECTIONW, FALSE,
				(LPARAM) pidlMain);
			pMalloc->lpVtbl->Free(pMalloc, pidlMain);
		    }
		    psfFolder->lpVtbl->Release(psfFolder);
		}
2777
2778
2779
2780
2781
2782
2783
2784

2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798

2799
2800
2801
2802
2803
2804
2805
2788
2789
2790
2791
2792
2793
2794

2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808

2809
2810
2811
2812
2813
2814
2815
2816







-
+













-
+







int
Tk_MessageBoxObjCmd(
    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, parent;
    Tk_Window tkwin = (Tk_Window)clientData, parent;
    HWND hWnd;
    Tcl_Obj *messageObj, *titleObj, *detailObj, *tmpObj;
    int defaultBtn, icon, type;
    int i, oldMode, winCode;
    UINT flags;
    static const char *const optionStrings[] = {
	"-default",	"-detail",	"-icon",	"-message",
	"-parent",	"-title",	"-type",	NULL
    };
    enum options {
	MSG_DEFAULT,	MSG_DETAIL,	MSG_ICON,	MSG_MESSAGE,
	MSG_PARENT,	MSG_TITLE,	MSG_TYPE
    };
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    Tcl_DString titleBuf, tmpBuf;
    LPCWSTR titlePtr, tmpPtr;
    const char *src;

    defaultBtn = -1;
    detailObj = NULL;
2925
2926
2927
2928
2929
2930
2931

2932

2933
2934

2935

2936
2937
2938
2939
2940
2941
2942
2936
2937
2938
2939
2940
2941
2942
2943

2944
2945
2946
2947

2948
2949
2950
2951
2952
2953
2954
2955







+
-
+


+
-
+







     */

    tsdPtr->hSmallIcon = TkWinGetIcon(parent, ICON_SMALL);
    tsdPtr->hBigIcon   = TkWinGetIcon(parent, ICON_BIG);
    tsdPtr->hMsgBoxHook = SetWindowsHookExW(WH_CBT, MsgBoxCBTProc, NULL,
	    GetCurrentThreadId());
    src = Tcl_GetString(tmpObj);
    Tcl_DStringInit(&tmpBuf);
    tmpPtr = (LPCWSTR)Tcl_WinUtfToTChar(src, tmpObj->length, &tmpBuf);
    tmpPtr = Tcl_UtfToWCharDString(src, tmpObj->length, &tmpBuf);
    if (titleObj != NULL) {
	src = Tcl_GetString(titleObj);
	Tcl_DStringInit(&titleBuf);
	titlePtr = (LPCWSTR)Tcl_WinUtfToTChar(src, titleObj->length, &titleBuf);
	titlePtr = Tcl_UtfToWCharDString(src, titleObj->length, &titleBuf);
    } else {
	titlePtr = L"";
	Tcl_DStringInit(&titleBuf);
    }
    winCode = MessageBoxW(hWnd, tmpPtr, titlePtr, flags);
    Tcl_DStringFree(&titleBuf);
    Tcl_DStringFree(&tmpBuf);
2959
2960
2961
2962
2963
2964
2965
2966

2967
2968
2969
2970
2971
2972
2973
2972
2973
2974
2975
2976
2977
2978

2979
2980
2981
2982
2983
2984
2985
2986







-
+








static LRESULT CALLBACK
MsgBoxCBTProc(
    int nCode,
    WPARAM wParam,
    LPARAM lParam)
{
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (nCode == HCBT_CREATEWND) {
	/*
	 * Window owned by our task is being created. Since the hook is
	 * installed just before the MessageBox call and removed after the
	 * MessageBox call, the window being created is either the message box
3006
3007
3008
3009
3010
3011
3012
3013

3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027

3028
3029
3030
3031
3032


3033
3034
3035
3036
3037
3038
3039
3019
3020
3021
3022
3023
3024
3025

3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039

3040
3041
3042
3043
3044

3045
3046
3047
3048
3049
3050
3051
3052
3053







-
+













-
+




-
+
+







 * ----------------------------------------------------------------------
 */

static void
SetTkDialog(
    ClientData clientData)
{
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    char buf[32];

    sprintf(buf, "0x%" TCL_Z_MODIFIER "x", (size_t)clientData);
    Tcl_SetVar2(tsdPtr->debugInterp, "tk_dialog", NULL, buf, TCL_GLOBAL_ONLY);
}

/*
 * Factored out a common pattern in use in this file.
 */

static const char *
ConvertExternalFilename(
    WCHAR *filename,
    LPCWSTR  filename,
    Tcl_DString *dsPtr)
{
    char *p;

    Tcl_WinTCharToUtf((LPCTSTR)filename, -1, dsPtr);
    Tcl_DStringInit(dsPtr);
    Tcl_WCharToUtfDString(filename, wcslen(filename), dsPtr);
    for (p = Tcl_DStringValue(dsPtr); *p != '\0'; p++) {
	/*
	 * Change the pathname to the Tcl "normalized" pathname, where back
	 * slashes are used instead of forward slashes
	 */

	if (*p == '\\') {
3062
3063
3064
3065
3066
3067
3068

3069

3070
3071
3072
3073
3074

3075
3076
3077
3078
3079
3080
3081
3076
3077
3078
3079
3080
3081
3082
3083

3084
3085
3086
3087
3088

3089
3090
3091
3092
3093
3094
3095
3096







+
-
+




-
+







    LOGFONTW *plf)
{
    Tcl_DString ds;
    Tcl_Obj *resObj;
    int pt = 0;

    resObj = Tcl_NewListObj(0, NULL);
    Tcl_DStringInit(&ds);
    Tcl_WinTCharToUtf((LPCTSTR)plf->lfFaceName, -1, &ds);
    Tcl_WCharToUtfDString(plf->lfFaceName, wcslen(plf->lfFaceName), &ds);
    Tcl_ListObjAppendElement(NULL, resObj,
	    Tcl_NewStringObj(Tcl_DStringValue(&ds), -1));
    Tcl_DStringFree(&ds);
    pt = -MulDiv(plf->lfHeight, 72, GetDeviceCaps(hdc, LOGPIXELSY));
    Tcl_ListObjAppendElement(NULL, resObj, Tcl_NewIntObj(pt));
    Tcl_ListObjAppendElement(NULL, resObj, Tcl_NewWideIntObj(pt));
    if (plf->lfWeight >= 700) {
	Tcl_ListObjAppendElement(NULL, resObj, Tcl_NewStringObj("bold", -1));
    }
    if (plf->lfItalic) {
	Tcl_ListObjAppendElement(NULL, resObj,
		Tcl_NewStringObj("italic", -1));
    }
3097
3098
3099
3100
3101
3102
3103
3104

3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118

3119
3120
3121
3122
3123
3124
3125
3126







-
+







    HDC hdc,
    LOGFONTW *logfontPtr)
{
    int objc;
    Tcl_Obj **objv, **tmpv;

    Tcl_ListObjGetElements(NULL, cmdObj, &objc, &objv);
    tmpv = ckalloc(sizeof(Tcl_Obj *) * (objc + 2));
    tmpv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj *) * (objc + 2));
    memcpy(tmpv, objv, sizeof(Tcl_Obj *) * objc);
    tmpv[objc] = GetFontObj(hdc, logfontPtr);
    TkBackgroundEvalObjv(interp, objc+1, tmpv, TCL_EVAL_GLOBAL);
    ckfree(tmpv);
}

/*
3135
3136
3137
3138
3139
3140
3141
3142

3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154

3155

3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174

3175
3176
3177
3178
3179
3180

3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198

3199
3200
3201
3202
3203
3204
3205
3150
3151
3152
3153
3154
3155
3156

3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170

3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189

3190
3191
3192
3193
3194
3195

3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213

3214
3215
3216
3217
3218
3219
3220
3221







-
+












+
-
+


















-
+





-
+

















-
+







    UINT msg,
    WPARAM wParam,
    LPARAM lParam)
{
    CHOOSEFONT *pcf = (CHOOSEFONT *) lParam;
    HWND hwndCtrl;
    static HookData *phd = NULL;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (WM_INITDIALOG == msg && lParam != 0) {
	phd = (HookData *) pcf->lCustData;
	phd->hwnd = hwndDlg;
	if (tsdPtr->debugFlag) {
	    tsdPtr->debugInterp = phd->interp;
	    Tcl_DoWhenIdle(SetTkDialog, hwndDlg);
	}
	if (phd->titleObj != NULL) {
	    Tcl_DString title;

	    Tcl_DStringInit(&title);
	    Tcl_WinUtfToTChar(Tcl_GetString(phd->titleObj), -1, &title);
	    Tcl_UtfToWCharDString(Tcl_GetString(phd->titleObj), -1, &title);
	    if (Tcl_DStringLength(&title) > 0) {
		SetWindowTextW(hwndDlg, (LPCWSTR) Tcl_DStringValue(&title));
	    }
	    Tcl_DStringFree(&title);
	}

	/*
	 * Disable the colour combobox (0x473) and its label (0x443).
	 */

	hwndCtrl = GetDlgItem(hwndDlg, 0x443);
	if (IsWindow(hwndCtrl)) {
	    EnableWindow(hwndCtrl, FALSE);
	}
	hwndCtrl = GetDlgItem(hwndDlg, 0x473);
	if (IsWindow(hwndCtrl)) {
	    EnableWindow(hwndCtrl, FALSE);
	}
	TkSendVirtualEvent(phd->parent, "TkFontchooserVisibility", NULL);
	Tk_SendVirtualEvent(phd->parent, "TkFontchooserVisibility", NULL);
	return 1; /* we handled the message */
    }

    if (WM_DESTROY == msg) {
	phd->hwnd = NULL;
	TkSendVirtualEvent(phd->parent, "TkFontchooserVisibility", NULL);
	Tk_SendVirtualEvent(phd->parent, "TkFontchooserVisibility", NULL);
	return 0;
    }

    /*
     * Handle apply button by calling the provided command script as a
     * background evaluation (ie: errors dont come back here).
     */

    if (WM_COMMAND == msg && LOWORD(wParam) == 1026) {
	LOGFONTW lf = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0}};
	HDC hdc = GetDC(hwndDlg);

	SendMessageW(hwndDlg, WM_CHOOSEFONT_GETLOGFONT, 0, (LPARAM) &lf);
	if (phd && phd->cmdObj) {
	    ApplyLogfont(phd->interp, phd->cmdObj, hdc, &lf);
	}
	if (phd && phd->parent) {
	    TkSendVirtualEvent(phd->parent, "TkFontchooserFontChanged", NULL);
	    Tk_SendVirtualEvent(phd->parent, "TkFontchooserFontChanged", NULL);
	}
	return 1;
    }
    return 0; /* pass on for default processing */
}

/*
3245
3246
3247
3248
3249
3250
3251
3252

3253
3254
3255
3256
3257
3258
3259
3261
3262
3263
3264
3265
3266
3267

3268
3269
3270
3271
3272
3273
3274
3275







-
+







	if (hdPtr->cmdObj) {
	    resObj = hdPtr->cmdObj;
	} else {
	    resObj = Tcl_NewStringObj("", 0);
	}
	break;
    case FontchooserVisible:
	resObj = Tcl_NewBooleanObj(hdPtr->hwnd && IsWindow(hdPtr->hwnd));
	resObj = Tcl_NewWideIntObj((hdPtr->hwnd != NULL) && IsWindow(hdPtr->hwnd));
	break;
    default:
	resObj = Tcl_NewStringObj("", 0);
    }
    return resObj;
}

3277
3278
3279
3280
3281
3282
3283
3284

3285
3286
3287
3288
3289
3290
3291

3292
3293
3294
3295
3296
3297
3298
3293
3294
3295
3296
3297
3298
3299

3300
3301
3302
3303
3304
3305
3306

3307
3308
3309
3310
3311
3312
3313
3314







-
+






-
+







static int
FontchooserConfigureCmd(
    ClientData clientData,	/* Main window */
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tk_Window tkwin = clientData;
    Tk_Window tkwin = (Tk_Window)clientData;
    HookData *hdPtr = NULL;
    int i, r = TCL_OK;
    static const char *const optionStrings[] = {
	"-parent", "-title", "-font", "-command", "-visible", NULL
    };

    hdPtr = Tcl_GetAssocData(interp, "::tk::fontchooser", NULL);
    hdPtr = (HookData *)Tcl_GetAssocData(interp, "::tk::fontchooser", NULL);

    /*
     * With no arguments we return all the options in a dict.
     */

    if (objc == 1) {
	Tcl_Obj *keyObj, *valueObj;
3421
3422
3423
3424
3425
3426
3427
3428

3429
3430
3431
3432
3433


3434
3435

3436
3437
3438
3439
3440
3441
3442
3437
3438
3439
3440
3441
3442
3443

3444
3445
3446
3447
3448
3449
3450
3451
3452

3453
3454
3455
3456
3457
3458
3459
3460







-
+





+
+

-
+







FontchooserShowCmd(
    ClientData clientData,	/* Main window */
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_DString ds;
    Tk_Window tkwin = clientData, parent;
    Tk_Window tkwin = (Tk_Window)clientData, parent;
    CHOOSEFONTW cf;
    LOGFONTW lf;
    HDC hdc;
    HookData *hdPtr;
    int r = TCL_OK, oldMode = 0;
    (void)objc;
    (void)objv;

    hdPtr = Tcl_GetAssocData(interp, "::tk::fontchooser", NULL);
    hdPtr = (HookData *)Tcl_GetAssocData(interp, "::tk::fontchooser", NULL);

    parent = tkwin;
    if (hdPtr->parentObj) {
	parent = Tk_NameToWindow(interp, Tcl_GetString(hdPtr->parentObj),
		tkwin);
	if (parent == NULL) {
	    return TCL_ERROR;
3465
3466
3467
3468
3469
3470
3471
3472
3473


3474
3475
3476
3477
3478
3479
3480
3483
3484
3485
3486
3487
3488
3489


3490
3491
3492
3493
3494
3495
3496
3497
3498







-
-
+
+







	Tk_Font f = Tk_AllocFontFromObj(interp, tkwin, hdPtr->fontObj);

	if (f == NULL) {
	    return TCL_ERROR;
	}
	fontPtr = (TkFont *) f;
	cf.Flags |= CF_INITTOLOGFONTSTRUCT;
	Tcl_WinUtfToTChar(fontPtr->fa.family, -1, &ds);
	wcsncpy(lf.lfFaceName, (WCHAR *)Tcl_DStringValue(&ds),
	Tcl_DStringInit(&ds);
	wcsncpy(lf.lfFaceName, Tcl_UtfToWCharDString(fontPtr->fa.family, -1, &ds),
		LF_FACESIZE-1);
	Tcl_DStringFree(&ds);
	lf.lfFaceName[LF_FACESIZE-1] = 0;
	lf.lfHeight = -MulDiv((int)(TkFontGetPoints(tkwin, fontPtr->fa.size) + 0.5),
	    GetDeviceCaps(hdc, LOGPIXELSY), 72);
	if (fontPtr->fa.weight == TK_FW_BOLD) {
	    lf.lfWeight = FW_BOLD;
3503
3504
3505
3506
3507
3508
3509
3510

3511
3512
3513
3514
3515
3516
3517
3521
3522
3523
3524
3525
3526
3527

3528
3529
3530
3531
3532
3533
3534
3535







-
+







    if (TCL_OK == r) {
	oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
	if (ChooseFontW(&cf)) {
	    if (hdPtr->cmdObj) {
		ApplyLogfont(hdPtr->interp, hdPtr->cmdObj, hdc, &lf);
	    }
	    if (hdPtr->parent) {
		TkSendVirtualEvent(hdPtr->parent, "TkFontchooserFontChanged", NULL);
		Tk_SendVirtualEvent(hdPtr->parent, "TkFontchooserFontChanged", NULL);
	    }
	}
	Tcl_SetServiceMode(oldMode);
	EnableWindow(cf.hwndOwner, 1);
    }

    ReleaseDC(cf.hwndOwner, hdc);
3529
3530
3531
3532
3533
3534
3535
3536

3537
3538
3539
3540
3541




3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561

3562
3563


3564
3565
3566
3567
3568
3569
3570
3547
3548
3549
3550
3551
3552
3553

3554
3555
3556
3557
3558

3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581

3582
3583

3584
3585
3586
3587
3588
3589
3590
3591
3592







-
+




-
+
+
+
+



















-
+

-
+
+







 *	destroy the dialog
 *
 * ----------------------------------------------------------------------
 */

static int
FontchooserHideCmd(
    ClientData clientData,	/* Main window */
    ClientData dummy,	/* Main window */
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    HookData *hdPtr = Tcl_GetAssocData(interp, "::tk::fontchooser", NULL);
    HookData *hdPtr = (HookData *)Tcl_GetAssocData(interp, "::tk::fontchooser", NULL);
    (void)dummy;
    (void)objc;
    (void)objv;

    if (hdPtr->hwnd && IsWindow(hdPtr->hwnd)) {
	EndDialog(hdPtr->hwnd, 0);
    }
    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 *
 * DeleteHookData --
 *
 *	Clean up the font chooser configuration data when the interp is
 *	destroyed.
 *
 * ----------------------------------------------------------------------
 */

static void
DeleteHookData(ClientData clientData, Tcl_Interp *interp)
DeleteHookData(ClientData clientData, Tcl_Interp *dummy)
{
    HookData *hdPtr = clientData;
    HookData *hdPtr = (HookData *)clientData;
    (void)dummy;

    if (hdPtr->parentObj) {
	Tcl_DecrRefCount(hdPtr->parentObj);
    }
    if (hdPtr->fontObj) {
	Tcl_DecrRefCount(hdPtr->fontObj);
    }
3593
3594
3595
3596
3597
3598
3599
3600

3601
3602


3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3615
3616
3617
3618
3619
3620
3621

3622
3623

3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638







-
+

-
+
+













    { "configure", FontchooserConfigureCmd, NULL },
    { "show", FontchooserShowCmd, NULL },
    { "hide", FontchooserHideCmd, NULL },
    { NULL, NULL, NULL }
};

int
TkInitFontchooser(Tcl_Interp *interp, ClientData clientData)
TkInitFontchooser(Tcl_Interp *interp, ClientData dummy)
{
    HookData *hdPtr = ckalloc(sizeof(HookData));
    HookData *hdPtr = (HookData *)ckalloc(sizeof(HookData));
    (void)dummy;

    memset(hdPtr, 0, sizeof(HookData));
    Tcl_SetAssocData(interp, "::tk::fontchooser", DeleteHookData, hdPtr);
    return TCL_OK;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Changes to win/tkWinDraw.c.
1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15






-
-
+
+







/*
 * tkWinDraw.c --
 *
 *	This file contains the Xlib emulation functions pertaining to actually
 *	drawing objects on a window.
 *
 * Copyright (c) 1995 Sun Microsystems, Inc.
 * Copyright (c) 1994 Software Research Associates, Inc.
 * Copyright © 1995 Sun Microsystems, Inc.
 * Copyright © 1994 Software Research Associates, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tkWinInt.h"

240
241
242
243
244
245
246
247

248
249
250
251
252
253
254
240
241
242
243
244
245
246

247
248
249
250
251
252
253
254







-
+







     * the last array if it is large enough.
     */

    if (npoints > tsdPtr->nWinPoints) {
	if (tsdPtr->winPoints != NULL) {
	    ckfree(tsdPtr->winPoints);
	}
	tsdPtr->winPoints = ckalloc(sizeof(POINT) * npoints);
	tsdPtr->winPoints = (POINT *)ckalloc(sizeof(POINT) * npoints);
	if (tsdPtr->winPoints == NULL) {
	    tsdPtr->nWinPoints = -1;
	    return NULL;
	}
	tsdPtr->nWinPoints = npoints;
    }

408
409
410
411
412
413
414
415

416
417
418
419
420
421
422
408
409
410
411
412
413
414

415
416
417
418
419
420
421
422







-
+







	    /*
	     * Case 2: transparent bitmaps are handled by setting the
	     * destination to the foreground color whenever the source pixel
	     * is set.
	     */

	    fgBrush = CreateSolidBrush(gc->foreground);
	    oldBrush = SelectObject(destDC, fgBrush);
	    oldBrush = (HBRUSH)SelectObject(destDC, fgBrush);
	    SetBkColor(destDC, RGB(255,255,255));
	    SetTextColor(destDC, RGB(0,0,0));
	    BitBlt(destDC, dest_x, dest_y, (int) width, (int) height, srcDC,
		    src_x, src_y, MASKPAT);
	    SelectObject(destDC, oldBrush);
	    DeleteObject(fgBrush);
	} else {
446
447
448
449
450
451
452
453

454
455
456
457
458
459
460
446
447
448
449
450
451
452

453
454
455
456
457
458
459
460







-
+







	     */

	    BitBlt(memDC, 0, 0, (int) width, (int) height, srcDC, src_x, src_y,
		    SRCCOPY);
	    BitBlt(memDC, 0, 0, (int) width, (int) height, maskDC,
		    dest_x - gc->clip_x_origin, dest_y - gc->clip_y_origin,
		    SRCAND);
	    oldBrush = SelectObject(destDC, fgBrush);
	    oldBrush = (HBRUSH)SelectObject(destDC, fgBrush);
	    BitBlt(destDC, dest_x, dest_y, (int) width, (int) height, memDC,
		    0, 0, MASKPAT);

	    /*
	     * Set background bits. Same as foreground, except we use ((NOT
	     * source) AND mask) and the background brush.
	     */
549
550
551
552
553
554
555
556

557
558
559

560
561
562
563
564
565
566
549
550
551
552
553
554
555

556
557
558

559
560
561
562
563
564
565
566







-
+


-
+







	/*
	 * Do not use a palette for TrueColor images.
	 */

	usePalette = (image->bits_per_pixel < 16);

	if (usePalette) {
	    infoPtr = ckalloc(sizeof(BITMAPINFOHEADER)
	    infoPtr = (BITMAPINFO *)ckalloc(sizeof(BITMAPINFOHEADER)
		    + sizeof(RGBQUAD)*ncolors);
	} else {
	    infoPtr = ckalloc(sizeof(BITMAPINFOHEADER));
	    infoPtr = (BITMAPINFO *)ckalloc(sizeof(BITMAPINFOHEADER));
	}

	infoPtr->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	infoPtr->bmiHeader.biWidth = image->width;
	infoPtr->bmiHeader.biHeight = -image->height; /* Top-down order */
	infoPtr->bmiHeader.biPlanes = 1;
	infoPtr->bmiHeader.biBitCount = image->bits_per_pixel;
587
588
589
590
591
592
593
594

595
596
597
598
599
600
601
602

603
604
605
606
607
608
609
587
588
589
590
591
592
593

594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610







-
+








+







    }
    if (!bitmap) {
	Tcl_Panic("Fail to allocate bitmap");
	DeleteDC(dcMem);
    	TkWinReleaseDrawableDC(d, dc, &state);
	return BadValue;
    }
    bitmap = SelectObject(dcMem, bitmap);
    bitmap = (HBITMAP)SelectObject(dcMem, bitmap);
    BitBlt(dc, dest_x, dest_y, (int) width, (int) height, dcMem, src_x, src_y,
	    SRCCOPY);
    DeleteObject(SelectObject(dcMem, bitmap));
    DeleteDC(dcMem);
    TkWinReleaseDrawableDC(d, dc, &state);
    return Success;
}

#undef XPutImage
int
XPutImage(
    Display *display,
    Drawable d,			/* Destination drawable. */
    GC gc,
    XImage *image,		/* Source image. */
    int src_x, int src_y,	/* Offset of subimage. */
667
668
669
670
671
672
673
674

675
676
677
678
679
680
681
682
683
684
685
686

687
688
689
690
691
692
693
668
669
670
671
672
673
674

675
676
677
678
679
680
681
682
683
684
685
686

687
688
689
690
691
692
693
694







-
+











-
+








	/*
	 * Select stipple pattern into destination dc.
	 */

	stipple = CreatePatternBrush(twdPtr->bitmap.handle);
	SetBrushOrgEx(dc, gc->ts_x_origin, gc->ts_y_origin, NULL);
	oldBrush = SelectObject(dc, stipple);
	oldBrush = (HBRUSH)SelectObject(dc, stipple);
	dcMem = CreateCompatibleDC(dc);

	/*
	 * For each rectangle, create a drawing surface which is the size of
	 * the rectangle and fill it with the background color. Then merge the
	 * result with the stipple pattern.
	 */

	while (nrectangles-- > 0) {
	    bitmap = CreateCompatibleBitmap(dc, rectangles[0].width,
		    rectangles[0].height);
	    oldBitmap = SelectObject(dcMem, bitmap);
	    oldBitmap = (HBITMAP)SelectObject(dcMem, bitmap);
	    rect.left = 0;
	    rect.top = 0;
	    rect.right = rectangles[0].width;
	    rect.bottom = rectangles[0].height;
	    FillRect(dcMem, &rect, brush);
	    BitBlt(dc, rectangles[0].x, rectangles[0].y, rectangles[0].width,
		    rectangles[0].height, dcMem, 0, 0, COPYFG);
714
715
716
717
718
719
720
721
722


723
724
725
726
727
728
729
715
716
717
718
719
720
721


722
723
724
725
726
727
728
729
730







-
-
+
+







		rect.top = rectangles[0].y;
		rect.bottom = rect.top + rectangles[0].height;
		FillRect(dc, &rect, brush);
		++rectangles;
	    }
	} else {
	    HPEN newPen = CreatePen(PS_NULL, 0, gc->foreground);
	    HPEN oldPen = SelectObject(dc, newPen);
	    oldBrush = SelectObject(dc, brush);
	    HPEN oldPen = (HPEN)SelectObject(dc, newPen);
	    oldBrush = (HBRUSH)SelectObject(dc, brush);

	    while (nrectangles-- > 0) {
		Rectangle(dc, rectangles[0].x, rectangles[0].y,
		    rectangles[0].x + rectangles[0].width + 1,
		    rectangles[0].y + rectangles[0].height + 1);
		++rectangles;
	    }
844
845
846
847
848
849
850
851

852
853
854
855
856
857
858
859

860
861

862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881

882
883
884
885
886
887
888
845
846
847
848
849
850
851

852
853
854
855
856
857
858
859

860
861

862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881

882
883
884
885
886
887
888
889







-
+







-
+

-
+



















-
+







	height = rect.bottom - rect.top;

	/*
	 * Select stipple pattern into destination dc.
	 */

	SetBrushOrgEx(dc, gc->ts_x_origin, gc->ts_y_origin, NULL);
	oldBrush = SelectObject(dc, CreatePatternBrush(twdPtr->bitmap.handle));
	oldBrush = (HBRUSH)SelectObject(dc, CreatePatternBrush(twdPtr->bitmap.handle));

	/*
	 * Create temporary drawing surface containing a copy of the
	 * destination equal in size to the bounding box of the object.
	 */

	dcMem = CreateCompatibleDC(dc);
	oldBitmap = SelectObject(dcMem, CreateCompatibleBitmap(dc, width,
	oldBitmap = (HBITMAP)SelectObject(dcMem, CreateCompatibleBitmap(dc, width,
		height));
	oldPen = SelectObject(dcMem, pen);
	oldPen = (HPEN)SelectObject(dcMem, pen);
	BitBlt(dcMem, 0, 0, width, height, dc, rect.left, rect.top, SRCCOPY);

	/*
	 * Translate the object for rendering in the temporary drawing
	 * surface.
	 */

	for (i = 0; i < npoints; i++) {
	    winPoints[i].x -= rect.left;
	    winPoints[i].y -= rect.top;
	}

	/*
	 * Draw the object in the foreground color and copy it to the
	 * destination wherever the pattern is set.
	 */

	SetPolyFillMode(dcMem, (gc->fill_rule == EvenOddRule) ? ALTERNATE
		: WINDING);
	oldMemBrush = SelectObject(dcMem, CreateSolidBrush(gc->foreground));
	oldMemBrush = (HBRUSH)SelectObject(dcMem, CreateSolidBrush(gc->foreground));
        MakeAndStrokePath(dcMem, winPoints, npoints, func);
	BitBlt(dc, rect.left, rect.top, width, height, dcMem, 0, 0, COPYFG);

	/*
	 * If we are rendering an opaque stipple, then draw the polygon in the
	 * background color and copy it to the destination wherever the
	 * pattern is clear.
897
898
899
900
901
902
903
904
905


906
907
908
909
910
911
912
898
899
900
901
902
903
904


905
906
907
908
909
910
911
912
913







-
-
+
+







	}

	SelectObject(dcMem, oldPen);
	DeleteObject(SelectObject(dcMem, oldMemBrush));
	DeleteObject(SelectObject(dcMem, oldBitmap));
	DeleteDC(dcMem);
    } else {
	oldPen = SelectObject(dc, pen);
	oldBrush = SelectObject(dc, CreateSolidBrush(gc->foreground));
	oldPen = (HPEN)SelectObject(dc, pen);
	oldBrush = (HBRUSH)SelectObject(dc, CreateSolidBrush(gc->foreground));
	SetROP2(dc, tkpWinRopModes[gc->function]);

	SetPolyFillMode(dc, (gc->fill_rule == EvenOddRule) ? ALTERNATE
		: WINDING);
        MakeAndStrokePath(dc, winPoints, npoints, func);
	SelectObject(dc, oldPen);
    }
982
983
984
985
986
987
988

989
990
991
992
993
994
995
996

997
998
999
1000
1001
1002
1003
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997

998
999
1000
1001
1002
1003
1004
1005







+







-
+







    int npoints,
    int shape,
    int mode)
{
    HPEN pen;
    TkWinDCState state;
    HDC dc;
    (void)shape;

    if (d == None) {
	return BadDrawable;
    }

    dc = TkWinGetDrawableDC(display, d, &state);

    pen = GetStockObject(NULL_PEN);
    pen = (HPEN)GetStockObject(NULL_PEN);
    RenderObject(dc, gc, points, npoints, mode, pen, Polygon);

    TkWinReleaseDrawableDC(d, dc, &state);
    return Success;
}

/*
1033
1034
1035
1036
1037
1038
1039
1040
1041


1042
1043
1044
1045
1046
1047
1048
1035
1036
1037
1038
1039
1040
1041


1042
1043
1044
1045
1046
1047
1048
1049
1050







-
-
+
+







	return BadDrawable;
    }

    dc = TkWinGetDrawableDC(display, d, &state);

    pen = SetUpGraphicsPort(gc);
    SetBkMode(dc, TRANSPARENT);
    oldPen = SelectObject(dc, pen);
    oldBrush = SelectObject(dc, GetStockObject(NULL_BRUSH));
    oldPen = (HPEN)SelectObject(dc, pen);
    oldBrush = (HBRUSH)SelectObject(dc, GetStockObject(NULL_BRUSH));
    SetROP2(dc, tkpWinRopModes[gc->function]);

    Rectangle(dc, x, y, (int) x+width+1, (int) y+height+1);

    DeleteObject(SelectObject(dc, oldPen));
    SelectObject(dc, oldBrush);
    TkWinReleaseDrawableDC(d, dc, &state);
1259
1260
1261
1262
1263
1264
1265
1266

1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279

1280
1281
1282
1283
1284
1285
1286
1261
1262
1263
1264
1265
1266
1267

1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280

1281
1282
1283
1284
1285
1286
1287
1288







-
+












-
+







    /*
     * Now draw a filled or open figure. Note that we have to increase the
     * size of the bounding box by one to account for the difference in pixel
     * definitions between X and Windows.
     */

    pen = SetUpGraphicsPort(gc);
    oldPen = SelectObject(dc, pen);
    oldPen = (HPEN)SelectObject(dc, pen);
    if (!fill) {
	/*
	 * Note that this call will leave a gap of one pixel at the end of the
	 * arc for thin arcs. We can't use ArcTo because it's only supported
	 * under Windows NT.
	 */

	SetBkMode(dc, TRANSPARENT);
	Arc(dc, x, y, (int) (x+width+1), (int) (y+height+1), xstart, ystart,
		xend, yend);
    } else {
	brush = CreateSolidBrush(gc->foreground);
	oldBrush = SelectObject(dc, brush);
	oldBrush = (HBRUSH)SelectObject(dc, brush);
	if (gc->arc_mode == ArcChord) {
	    Chord(dc, x, y, (int) (x+width+1), (int) (y+height+1),
		    xstart, ystart, xend, yend);
	} else if (gc->arc_mode == ArcPieSlice) {
	    Pie(dc, x, y, (int) (x+width+1), (int) (y+height+1),
		    xstart, ystart, xend, yend);
	}
1398
1399
1400
1401
1402
1403
1404
1405

1406
1407
1408

1409
1410
1411
1412
1413
1414
1415
1400
1401
1402
1403
1404
1405
1406

1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418







-
+



+







int
TkScrollWindow(
    Tk_Window tkwin,		/* The window to be scrolled. */
    GC gc,			/* GC for window to be scrolled. */
    int x, int y, int width, int height,
				/* Position rectangle to be scrolled. */
    int dx, int dy,		/* Distance rectangle should be moved. */
    TkRegion damageRgn)		/* Region to accumulate damage in. */
    Region damageRgn)		/* Region to accumulate damage in. */
{
    HWND hwnd = TkWinGetHWND(Tk_WindowId(tkwin));
    RECT scrollRect;
    (void)gc;

    scrollRect.left = x;
    scrollRect.top = y;
    scrollRect.right = x + width;
    scrollRect.bottom = y + height;
    return (ScrollWindowEx(hwnd, dx, dy, &scrollRect, NULL, (HRGN) damageRgn,
	    NULL, 0) == NULLREGION) ? 0 : 1;
1478
1479
1480
1481
1482
1483
1484


1485
1486
1487
1488
1489
1490
1491

1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505

1506

1507
1508
1509
1510
1511
1512

1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495

1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509

1510
1511
1512
1513
1514
1515
1516
1517

1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529







+
+






-
+













-
+

+





-
+











TkpDrawHighlightBorder(
    Tk_Window tkwin,
    GC fgGC,
    GC bgGC,
    int highlightWidth,
    Drawable drawable)
{
    (void)bgGC;

    TkDrawInsetFocusHighlight(tkwin, fgGC, highlightWidth, drawable, 0);
}

/*
 *----------------------------------------------------------------------
 *
 * TkpDrawFrame --
 * TkpDrawFrameEx --
 *
 *	This function draws the rectangular frame area.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Draws inside the tkwin area.
 *
 *----------------------------------------------------------------------
 */

void
TkpDrawFrame(
TkpDrawFrameEx(
    Tk_Window tkwin,
    Drawable drawable,
    Tk_3DBorder border,
    int highlightWidth,
    int borderWidth,
    int relief)
{
    Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), border, highlightWidth,
    Tk_Fill3DRectangle(tkwin, drawable, border, highlightWidth,
	    highlightWidth, Tk_Width(tkwin) - 2 * highlightWidth,
	    Tk_Height(tkwin) - 2 * highlightWidth, borderWidth, relief);
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Changes to win/tkWinEmbed.c.
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
16








-
+







/*
 * tkWinEmbed.c --
 *
 *	This file contains platform specific procedures for Windows platforms
 *	to provide basic operations needed for application embedding (where
 *	one application can use as its main window an internal window from
 *	another application).
 *
 * 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.
 */

#include "tkWinInt.h"

65
66
67
68
69
70
71
72

73
74
75
76
77
78
79
65
66
67
68
69
70
71

72
73
74
75
76
77
78
79







-
+







 *----------------------------------------------------------------------
 */

void
TkWinCleanupContainerList(void)
{
    Container *nextPtr;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    for (; tsdPtr->firstContainerPtr != NULL;
	    tsdPtr->firstContainerPtr = nextPtr) {
	nextPtr = tsdPtr->firstContainerPtr->nextPtr;
	ckfree(tsdPtr->firstContainerPtr);
    }
92
93
94
95
96
97
98
99
100
101
102

103
104
105
106





107
108
109
110
111
112
113
92
93
94
95
96
97
98

99
100

101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117







-


-
+




+
+
+
+
+







 *
 * Side effects:
 *	Currently it does not do anything.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
int
TkpTestembedCmd(
    ClientData clientData,
    ClientData dummy,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    (void)dummy;
    (void)interp;
    (void)objc;
    (void)objv;

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Tk_DetachEmbeddedWindow --
169
170
171
172
173
174
175
176

177
178
179
180
181
182
183
173
174
175
176
177
178
179

180
181
182
183
184
185
186
187







-
+







	while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {
	    /* empty body */
	}

	TkpWmSetState(winPtr, state);
	TkWmMapWindow(winPtr);
    }
    Tcl_Release((ClientData)winPtr);
    Tcl_Release(winPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * TkpUseWindow --
 *
327
328
329
330
331
332
333
334
335


336
337
338
339
340
341
342
331
332
333
334
335
336
337


338
339
340
341
342
343
344
345
346







-
-
+
+







    winPtr->flags &= ~(TK_MAPPED);

    /*
     * Preserve the winPtr and create an idle handler to map the embedded
     * window.
     */

    Tcl_Preserve((ClientData) winPtr);
    Tcl_DoWhenIdle((Tcl_IdleProc*) Tk_MapEmbeddedWindow, (ClientData) winPtr);
    Tcl_Preserve(winPtr);
    Tcl_DoWhenIdle((Tcl_IdleProc*) Tk_MapEmbeddedWindow, winPtr);

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
367
368
369
370
371
372
373
374

375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395

396
397
398
399
400
401
402
371
372
373
374
375
376
377

378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398

399
400
401
402
403
404
405
406







-
+




















-
+








    /*
     * Register the window as a container so that, for example, we can find
     * out later if the embedded app. is in the same process.
     */

    Tk_MakeWindowExist(tkwin);
    containerPtr = ckalloc(sizeof(Container));
    containerPtr = (Container *)ckalloc(sizeof(Container));
    containerPtr->parentPtr = winPtr;
    containerPtr->parentHWnd = Tk_GetHWND(Tk_WindowId(tkwin));
    containerPtr->embeddedHWnd = NULL;
    containerPtr->embeddedPtr = NULL;
    containerPtr->embeddedMenuHWnd = NULL;
    containerPtr->nextPtr = tsdPtr->firstContainerPtr;
    tsdPtr->firstContainerPtr = containerPtr;
    winPtr->flags |= TK_CONTAINER;

    /*
     * Unlike in tkUnixEmbed.c, we don't make any requests for events in the
     * embedded window here. Now we just allow the embedding of another TK
     * application into TK windows. When the embedded window makes a request,
     * that will be done by sending to the container window a WM_USER message,
     * which will be intercepted by TkWinContainerProc.
     *
     * We need to get structure events of the container itself, though.
     */

    Tk_CreateEventHandler(tkwin, StructureNotifyMask,
	    ContainerEventProc, (ClientData) containerPtr);
	    ContainerEventProc, containerPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * TkWinEmbeddedEventProc --
 *
1046
1047
1048
1049
1050
1051
1052


1053
1054
1055
1056
1057
1058
1059
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065







+
+







void
TkpRedirectKeyEvent(
    TkWindow *winPtr,		/* Window to which the event was originally
				 * reported. */
    XEvent *eventPtr)		/* X event to redirect (should be KeyPress or
				 * KeyRelease). */
{
    (void)winPtr;
    (void)eventPtr;
    /* not implemented */
}

/*
 *----------------------------------------------------------------------
 *
 * EmbedWindowDeleted --
Changes to win/tkWinFont.c.
1
2
3
4
5
6
7
8
9



10
11
12
13
14
15
16
1
2
3
4
5
6



7
8
9
10
11
12
13
14
15
16






-
-
-
+
+
+







/*
 * tkWinFont.c --
 *
 *	Contains the Windows implementation of the platform-independent font
 *	package interface.
 *
 * Copyright (c) 1994 Software Research Associates, Inc.
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 * Copyright © 1994 Software Research Associates, Inc.
 * Copyright © 1995-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 "tkWinInt.h"
#include "tkFont.h"
25
26
27
28
29
30
31

32

33
34
35
36
37
38
39
25
26
27
28
29
30
31
32

33
34
35
36
37
38
39
40







+
-
+







 *
 * Under Windows, a "font family" is uniquely identified by its face name.
 */

#define FONTMAP_SHIFT	    10

#define FONTMAP_BITSPERPAGE	(1 << FONTMAP_SHIFT)
#define FONTMAP_NUMCHARS	0x40000
#define FONTMAP_PAGES		(0x30000 / FONTMAP_BITSPERPAGE)
#define FONTMAP_PAGES		(FONTMAP_NUMCHARS / FONTMAP_BITSPERPAGE)

typedef struct FontFamily {
    struct FontFamily *nextPtr;	/* Next in list of all known font families. */
    size_t refCount;		/* How many SubFonts are referring to this
				 * FontFamily. When the refCount drops to
				 * zero, this FontFamily may be freed. */
    /*
210
211
212
213
214
215
216
217
218


219
220
221
222
223
224
225
211
212
213
214
215
216
217


218
219
220
221
222
223
224
225
226







-
-
+
+







			    LOGFONTW* logFontPtr);
static int		CreateNamedSystemFont(Tcl_Interp *interp,
			    Tk_Window tkwin, const char* name, HFONT hFont);
static int		LoadFontRanges(HDC hdc, HFONT hFont,
			    USHORT **startCount, USHORT **endCount,
			    int *symbolPtr);
static void		MultiFontTextOut(HDC hdc, WinFont *fontPtr,
			    const char *source, int numBytes, int x, int y,
			    double angle);
			    const char *source, int numBytes,
			    double x, double y, double angle);
static void		ReleaseFont(WinFont *fontPtr);
static inline void	ReleaseSubFont(SubFont *subFontPtr);
static int		SeenName(const char *name, Tcl_DString *dsPtr);
static inline HFONT	SelectFont(HDC hdc, WinFont *fontPtr,
			    SubFont *subFontPtr, double angle);
static inline void	SwapLong(PULONG p);
static inline void	SwapShort(USHORT *p);
295
296
297
298
299
300
301
302
303


304
305
306
307
308
309
310
296
297
298
299
300
301
302


303
304
305
306
307
308
309
310
311







-
-
+
+








    object = TkFindStateNum(NULL, NULL, systemMap, name);
    if (object < 0) {
	return NULL;
    }

    tkwin = (Tk_Window) ((TkWindow *) tkwin)->mainPtr->winPtr;
    fontPtr = ckalloc(sizeof(WinFont));
    InitFont(tkwin, GetStockObject(object), 0, fontPtr);
    fontPtr = (WinFont *)ckalloc(sizeof(WinFont));
    InitFont(tkwin, (HFONT)GetStockObject(object), 0, fontPtr);

    return (TkFont *) fontPtr;
}

/*
 *---------------------------------------------------------------------------
 *
553
554
555
556
557
558
559
560

561
562
563
564
565
566
567
554
555
556
557
558
559
560

561
562
563
564
565
566
567
568







-
+








  found:
    ReleaseDC(hwnd, hdc);

    hFont = GetScreenFont(faPtr, faceName,
	    (int)(TkFontGetPixels(tkwin, faPtr->size) + 0.5), 0.0);
    if (tkFontPtr == NULL) {
	fontPtr = ckalloc(sizeof(WinFont));
	fontPtr = (WinFont *)ckalloc(sizeof(WinFont));
    } else {
	fontPtr = (WinFont *) tkFontPtr;
	ReleaseFont(fontPtr);
    }
    InitFont(tkwin, hFont, faPtr->overstrike, fontPtr);

    return (TkFont *) fontPtr;
649
650
651
652
653
654
655
656
657


658
659

660
661
662
663


664
665
666
667
668
669
670
650
651
652
653
654
655
656


657
658
659
660
661
662
663
664

665
666
667
668
669
670
671
672
673







-
-
+
+


+



-
+
+







    ReleaseDC(hwnd, hdc);
    Tcl_SetObjResult(interp, resultObj);
}

static int CALLBACK
WinFontFamilyEnumProc(
    ENUMLOGFONTW *lfPtr,		/* Logical-font data. */
    NEWTEXTMETRIC *tmPtr,	/* Physical-font data (not used). */
    int fontType,		/* Type of font (not used). */
    TCL_UNUSED(NEWTEXTMETRIC *),	/* Physical-font data (not used). */
    TCL_UNUSED(int),		/* Type of font (not used). */
    LPARAM lParam)		/* Result object to hold result. */
{
    WCHAR *faceName = lfPtr->elfLogFont.lfFaceName;
    Tcl_Obj *resultObj = (Tcl_Obj *) lParam;
    Tcl_DString faceString;

    Tcl_WinTCharToUtf((LPCTSTR)lfPtr->elfLogFont.lfFaceName, -1, &faceString);
    Tcl_DStringInit(&faceString);
    Tcl_WCharToUtfDString(faceName, wcslen(faceName), &faceString);
    Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewStringObj(
	    Tcl_DStringValue(&faceString), Tcl_DStringLength(&faceString)));
    Tcl_DStringFree(&faceString);
    return 1;
}

/*
745
746
747
748
749
750
751
752

753
754
755
756
757
758
759
748
749
750
751
752
753
754

755
756
757
758
759
760
761
762







-
+







    HFONT oldfont;		/* Saved font from the device context */
    TEXTMETRICW tm;		/* Font metrics of the selected subfont */

    /*
     * Get the font attributes.
     */

    oldfont = SelectObject(hdc, thisSubFontPtr->hFont0);
    oldfont = (HFONT)SelectObject(hdc, thisSubFontPtr->hFont0);
    GetTextMetricsW(hdc, &tm);
    SelectObject(hdc, oldfont);
    ReleaseDC(fontPtr->hwnd, hdc);
    faPtr->family = familyPtr->faceName;
    faPtr->size = TkFontGetPoints(tkwin,
	    (double)(tm.tmInternalLeading - tm.tmHeight));
    faPtr->weight = (tm.tmWeight > FW_MEDIUM) ? TK_FW_BOLD : TK_FW_NORMAL;
823
824
825
826
827
828
829
830

831
832
833
834
835
836
837
826
827
828
829
830
831
832

833
834
835
836
837
838
839
840







-
+







	return 0;
    }

    fontPtr = (WinFont *) tkfont;

    hdc = GetDC(fontPtr->hwnd);
    lastSubFontPtr = &fontPtr->subFontArray[0];
    oldFont = SelectObject(hdc, lastSubFontPtr->hFont0);
    oldFont = (HFONT)SelectObject(hdc, lastSubFontPtr->hFont0);

    /*
     * A three step process:
     * 1. Find a contiguous range of characters that can all be represented by
     *    a single screen font.
     * 2. Convert those chars to the encoding of that font.
     * 3. Measure converted chars.
1009
1010
1011
1012
1013
1014
1015
1016

1017
1018
1019
1020
1021
1022
1023
1012
1013
1014
1015
1016
1017
1018

1019
1020
1021
1022
1023
1024
1025
1026







-
+







 */

int
TkpMeasureCharsInContext(
    Tk_Font tkfont,		/* Font in which characters will be drawn. */
    const char *source,		/* UTF-8 string to be displayed. Need not be
				 * '\0' terminated. */
    int numBytes,		/* Maximum number of bytes to consider from
    TCL_UNUSED(int),		/* Maximum number of bytes to consider from
				 * source string in all. */
    int rangeStart,		/* Index of first byte to measure. */
    int rangeLength,		/* Length of range to measure in bytes. */
    int maxLength,		/* If >= 0, maxLength specifies the longest
				 * permissible line length; don't consider any
				 * character that would cross this x-position.
				 * If < 0, then line length is unbounded and
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1034
1035
1036
1037
1038
1039
1040

1041
1042
1043
1044
1045
1046
1047







-







				 * no characters fit. TK_ISOLATE_END means
				 * that the last character should not be
				 * considered in context with the rest of the
				 * string (used for breaking lines). */
    int *lengthPtr)		/* Filled with x-location just after the
				 * terminating character. */
{
    (void) numBytes; /*unused*/
    return Tk_MeasureChars(tkfont, source + rangeStart, rangeLength,
	    maxLength, flags, lengthPtr);
}

/*
 *---------------------------------------------------------------------------
 *
1057
1058
1059
1060
1061
1062
1063
1064

1065
1066
1067
1068
1069
1070
1071
1059
1060
1061
1062
1063
1064
1065

1066
1067
1068
1069
1070
1071
1072
1073







-
+







 */

void
Tk_DrawChars(
    Display *display,		/* Display on which to draw. */
    Drawable drawable,		/* Window or pixmap in which to draw. */
    GC gc,			/* Graphics context for drawing characters. */
    Tk_Font tkfont,		/* Font in which characters will be drawn;
    TCL_UNUSED(Tk_Font),	/* Font in which characters will be drawn;
				 * must be the same as font used in GC. */
    const char *source,		/* UTF-8 string to be displayed. Need not be
				 * '\0' terminated. All Tk meta-characters
				 * (tabs, control characters, and newlines)
				 * should be stripped out of the string that
				 * is passed to this function. If they are not
				 * stripped out, they will be displayed as
1112
1113
1114
1115
1116
1117
1118
1119

1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134

1135
1136
1137
1138
1139
1140
1141
1114
1115
1116
1117
1118
1119
1120

1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135

1136
1137
1138
1139
1140
1141
1142
1143







-
+














-
+







	 * Select stipple pattern into destination dc.
	 */

	dcMem = CreateCompatibleDC(dc);

	stipple = CreatePatternBrush(twdPtr->bitmap.handle);
	SetBrushOrgEx(dc, gc->ts_x_origin, gc->ts_y_origin, NULL);
	oldBrush = SelectObject(dc, stipple);
	oldBrush = (HBRUSH)SelectObject(dc, stipple);

	SetTextAlign(dcMem, TA_LEFT | TA_BASELINE);
	SetTextColor(dcMem, gc->foreground);
	SetBkMode(dcMem, TRANSPARENT);
	SetBkColor(dcMem, RGB(0, 0, 0));

	/*
	 * Compute the bounding box and create a compatible bitmap.
	 */

	GetTextExtentPointA(dcMem, source, numBytes, &size);
	GetTextMetricsW(dcMem, &tm);
	size.cx -= tm.tmOverhang;
	bitmap = CreateCompatibleBitmap(dc, size.cx, size.cy);
	oldBitmap = SelectObject(dcMem, bitmap);
	oldBitmap = (HBITMAP)SelectObject(dcMem, bitmap);

	/*
	 * The following code is tricky because fonts are rendered in multiple
	 * colors. First we draw onto a black background and copy the white
	 * bits. Then we draw onto a white background and copy the black bits.
	 * Both the foreground and background bits of the font are ANDed with
	 * the stipple pattern as they are copied.
1181
1182
1183
1184
1185
1186
1187
1188

1189
1190
1191
1192
1193
1194
1195
1183
1184
1185
1186
1187
1188
1189

1190
1191
1192
1193
1194
1195
1196
1197







-
+







	 * Compute the bounding box and create a compatible bitmap.
	 */

	GetTextExtentPointA(dcMem, source, numBytes, &size);
	GetTextMetricsW(dcMem, &tm);
	size.cx -= tm.tmOverhang;
	bitmap = CreateCompatibleBitmap(dc, size.cx, size.cy);
	oldBitmap = SelectObject(dcMem, bitmap);
	oldBitmap = (HBITMAP)SelectObject(dcMem, bitmap);

	MultiFontTextOut(dcMem, fontPtr, source, numBytes, 0, tm.tmAscent,
		0.0);
	BitBlt(dc, x, y - tm.tmAscent, size.cx, size.cy, dcMem,
		0, 0, (DWORD) tkpWinBltModes[gc->function]);

	/*
1204
1205
1206
1207
1208
1209
1210
1211

1212
1213
1214
1215
1216
1217
1218
1206
1207
1208
1209
1210
1211
1212

1213
1214
1215
1216
1217
1218
1219
1220







-
+







}

void
TkDrawAngledChars(
    Display *display,		/* Display on which to draw. */
    Drawable drawable,		/* Window or pixmap in which to draw. */
    GC gc,			/* Graphics context for drawing characters. */
    Tk_Font tkfont,		/* Font in which characters will be drawn;
    TCL_UNUSED(Tk_Font),	/* Font in which characters will be drawn;
				 * must be the same as font used in GC. */
    const char *source,		/* UTF-8 string to be displayed. Need not be
				 * '\0' terminated. All Tk meta-characters
				 * (tabs, control characters, and newlines)
				 * should be stripped out of the string that
				 * is passed to this function. If they are not
				 * stripped out, they will be displayed as
1260
1261
1262
1263
1264
1265
1266
1267

1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282

1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293

1294
1295
1296
1297

1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314

1315
1316
1317
1318
1319
1320
1321
1262
1263
1264
1265
1266
1267
1268

1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283

1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294

1295
1296
1297
1298

1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315

1316
1317
1318
1319
1320
1321
1322
1323







-
+














-
+










-
+



-
+
















-
+







	 * Select stipple pattern into destination dc.
	 */

	dcMem = CreateCompatibleDC(dc);

	stipple = CreatePatternBrush(twdPtr->bitmap.handle);
	SetBrushOrgEx(dc, gc->ts_x_origin, gc->ts_y_origin, NULL);
	oldBrush = SelectObject(dc, stipple);
	oldBrush = (HBRUSH)SelectObject(dc, stipple);

	SetTextAlign(dcMem, TA_LEFT | TA_BASELINE);
	SetTextColor(dcMem, gc->foreground);
	SetBkMode(dcMem, TRANSPARENT);
	SetBkColor(dcMem, RGB(0, 0, 0));

	/*
	 * Compute the bounding box and create a compatible bitmap.
	 */

	GetTextExtentPointA(dcMem, source, numBytes, &size);
	GetTextMetricsW(dcMem, &tm);
	size.cx -= tm.tmOverhang;
	bitmap = CreateCompatibleBitmap(dc, size.cx, size.cy);
	oldBitmap = SelectObject(dcMem, bitmap);
	oldBitmap = (HBITMAP)SelectObject(dcMem, bitmap);

	/*
	 * The following code is tricky because fonts are rendered in multiple
	 * colors. First we draw onto a black background and copy the white
	 * bits. Then we draw onto a white background and copy the black bits.
	 * Both the foreground and background bits of the font are ANDed with
	 * the stipple pattern as they are copied.
	 */

	PatBlt(dcMem, 0, 0, size.cx, size.cy, BLACKNESS);
	MultiFontTextOut(dc, fontPtr, source, numBytes, (int)x, (int)y, angle);
	MultiFontTextOut(dc, fontPtr, source, numBytes, x, y, angle);
	BitBlt(dc, (int)x, (int)y - tm.tmAscent, size.cx, size.cy, dcMem,
		0, 0, 0xEA02E9);
	PatBlt(dcMem, 0, 0, size.cx, size.cy, WHITENESS);
	MultiFontTextOut(dc, fontPtr, source, numBytes, (int)x, (int)y, angle);
	MultiFontTextOut(dc, fontPtr, source, numBytes, x, y, angle);
	BitBlt(dc, (int)x, (int)y - tm.tmAscent, size.cx, size.cy, dcMem,
		0, 0, 0x8A0E06);

	/*
	 * Destroy the temporary bitmap and restore the device context.
	 */

	SelectObject(dcMem, oldBitmap);
	DeleteObject(bitmap);
	DeleteDC(dcMem);
	SelectObject(dc, oldBrush);
	DeleteObject(stipple);
    } else if (gc->function == GXcopy) {
	SetTextAlign(dc, TA_LEFT | TA_BASELINE);
	SetTextColor(dc, gc->foreground);
	SetBkMode(dc, TRANSPARENT);
	MultiFontTextOut(dc, fontPtr, source, numBytes, (int)x, (int)y, angle);
	MultiFontTextOut(dc, fontPtr, source, numBytes, x, y, angle);
    } else {
	HBITMAP oldBitmap, bitmap;
	HDC dcMem;
	TEXTMETRICW tm;
	SIZE size;

	dcMem = CreateCompatibleDC(dc);
1329
1330
1331
1332
1333
1334
1335
1336

1337
1338
1339
1340
1341
1342
1343
1331
1332
1333
1334
1335
1336
1337

1338
1339
1340
1341
1342
1343
1344
1345







-
+







	 * Compute the bounding box and create a compatible bitmap.
	 */

	GetTextExtentPointA(dcMem, source, numBytes, &size);
	GetTextMetricsW(dcMem, &tm);
	size.cx -= tm.tmOverhang;
	bitmap = CreateCompatibleBitmap(dc, size.cx, size.cy);
	oldBitmap = SelectObject(dcMem, bitmap);
	oldBitmap = (HBITMAP)SelectObject(dcMem, bitmap);

	MultiFontTextOut(dcMem, fontPtr, source, numBytes, 0, tm.tmAscent,
		angle);
	BitBlt(dc, (int)x, (int)y - tm.tmAscent, size.cx, size.cy, dcMem,
		0, 0, (DWORD) tkpWinBltModes[gc->function]);

	/*
1355
1356
1357
1358
1359
1360
1361
1362




1363
1364
1365
1366
1367
1368
1369
1357
1358
1359
1360
1361
1362
1363

1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374







-
+
+
+
+







 *---------------------------------------------------------------------------
 *
 * TkpDrawCharsInContext --
 *
 *	Draw a string of characters on the screen like Tk_DrawChars(), but
 *	with access to all the characters on the line for context. On Windows
 *	this context isn't consulted, so we just call Tk_DrawChars().
 *
  *
 *      Note: TK_DRAW_IN_CONTEXT being currently defined only on macOS, this
 *            function is unused (and possibly unfinished). See [7655f65ae7].
*
 * Results:
 *	None.
 *
 * Side effects:
 *	Information gets drawn on the screen.
 *
 *---------------------------------------------------------------------------
1379
1380
1381
1382
1383
1384
1385
1386

1387
1388
1389
1390
1391
1392
1393
1394





























1395
1396
1397
1398
1399


1400
1401
1402
1403
1404
1405
1406
1407
1384
1385
1386
1387
1388
1389
1390

1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431


1432
1433
1434
1435
1436
1437
1438
1439
1440
1441







-
+








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
-
+
+








    const char *source,		/* UTF-8 string to be displayed. Need not be
				 * '\0' terminated. All Tk meta-characters
				 * (tabs, control characters, and newlines)
				 * should be stripped out of the string that
				 * is passed to this function. If they are not
				 * stripped out, they will be displayed as
				 * regular printing characters. */
    int numBytes,		/* Number of bytes in string. */
    TCL_UNUSED(int),		/* Number of bytes in string. */
    int rangeStart,		/* Index of first byte to draw. */
    int rangeLength,		/* Length of range to draw in bytes. */
    int x, int y)		/* Coordinates at which to place origin of the
				 * whole (not just the range) string when
				 * drawing. */
{
    int widthUntilStart;

    Tk_MeasureChars(tkfont, source, rangeStart, -1, 0, &widthUntilStart);
    Tk_DrawChars(display, drawable, gc, tkfont, source + rangeStart,
	    rangeLength, x+widthUntilStart, y);
}

void
TkpDrawAngledCharsInContext(
    Display *display,		/* Display on which to draw. */
    Drawable drawable,		/* Window or pixmap in which to draw. */
    GC gc,			/* Graphics context for drawing characters. */
    Tk_Font tkfont,		/* Font in which characters will be drawn; must
				 * be the same as font used in GC. */
    const char * source,	/* UTF-8 string to be displayed. Need not be
				 * '\0' terminated. All Tk meta-characters
				 * (tabs, control characters, and newlines)
				 * should be stripped out of the string that is
				 * passed to this function. If they are not
				 * stripped out, they will be displayed as
				 * regular printing characters. */
    int numBytes,		/* Number of bytes in string. */
    int rangeStart,		/* Index of first byte to draw. */
    int rangeLength,		/* Length of range to draw in bytes. */
    double x, double y,		/* Coordinates at which to place origin of the
				 * whole (not just the range) string when
				 * drawing. */
    double angle)		/* What angle to put text at, in degrees. */
{
    int widthUntilStart;
    double sinA = sin(angle * PI/180.0), cosA = cos(angle * PI/180.0);
    (void) numBytes; /*unused*/

    Tk_MeasureChars(tkfont, source, rangeStart, -1, 0, &widthUntilStart);
    Tk_DrawChars(display, drawable, gc, tkfont, source + rangeStart,
	    rangeLength, x+widthUntilStart, y);
    TkDrawAngledChars(display, drawable, gc, tkfont, source + rangeStart,
	    rangeLength, x+cosA*widthUntilStart, y-sinA*widthUntilStart, angle);
}

/*
 *-------------------------------------------------------------------------
 *
 * MultiFontTextOut --
 *
 *	Helper function for Tk_DrawChars. Draws characters, using the various
1422
1423
1424
1425
1426
1427
1428
1429

1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440

1441
1442
1443
1444
1445
1446
1447
1456
1457
1458
1459
1460
1461
1462

1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482







-
+











+







static void
MultiFontTextOut(
    HDC hdc,			/* HDC to draw into. */
    WinFont *fontPtr,		/* Contains set of fonts to use when drawing
				 * following string. */
    const char *source,		/* Potentially multilingual UTF-8 string. */
    int numBytes,		/* Length of string in bytes. */
    int x, int y,		/* Coordinates at which to place origin of
    double x, double y,		/* Coordinates at which to place origin of
				 * string when drawing. */
    double angle)
{
    int ch;
    SIZE size;
    HFONT oldFont;
    FontFamily *familyPtr;
    Tcl_DString runString;
    const char *p, *end, *next;
    SubFont *lastSubFontPtr, *thisSubFontPtr;
    TEXTMETRICW tm;
    double sinA = sin(angle * PI/180.0), cosA = cos(angle * PI/180.0);

    lastSubFontPtr = &fontPtr->subFontArray[0];
    oldFont = SelectFont(hdc, fontPtr, lastSubFontPtr, angle);
    GetTextMetricsW(hdc, &tm);

    end = source + numBytes;
    for (p = source; p < end; ) {
1456
1457
1458
1459
1460
1461
1462
1463

1464
1465

1466
1467
1468
1469
1470


1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484

1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500

1501
1502

1503
1504
1505
1506
1507
1508
1509
1510

1511
1512
1513

1514
1515
1516
1517
1518
1519
1520
1491
1492
1493
1494
1495
1496
1497

1498
1499

1500
1501
1502
1503
1504

1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519

1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535

1536
1537

1538
1539
1540
1541
1542
1543
1544
1545

1546
1547
1548

1549
1550
1551
1552
1553
1554
1555
1556







-
+

-
+




-
+
+













-
+















-
+

-
+







-
+


-
+







	 */

	if ((thisSubFontPtr != lastSubFontPtr) || (p-source > 200)) {
	    if (p > source) {
		familyPtr = lastSubFontPtr->familyPtr;
 		Tcl_UtfToExternalDString(familyPtr->encoding, source,
			(int) (p - source), &runString);
		familyPtr->textOutProc(hdc, x-(tm.tmOverhang/2), y,
		familyPtr->textOutProc(hdc, (int)(x-(double)tm.tmOverhang/2.0), y,
			(WCHAR *)Tcl_DStringValue(&runString),
			Tcl_DStringLength(&runString)>>familyPtr->isWideFont);
			Tcl_DStringLength(&runString) >> familyPtr->isWideFont);
		familyPtr->getTextExtentPoint32Proc(hdc,
			(WCHAR *)Tcl_DStringValue(&runString),
			Tcl_DStringLength(&runString) >> familyPtr->isWideFont,
			&size);
		x += size.cx;
		x += cosA*size.cx;
		y -= sinA*size.cx;
		Tcl_DStringFree(&runString);
	    }
	    lastSubFontPtr = thisSubFontPtr;
	    source = p;
	    SelectFont(hdc, fontPtr, lastSubFontPtr, angle);
	    GetTextMetricsW(hdc, &tm);
	}
	p = next;
    }
    if (p > source) {
	familyPtr = lastSubFontPtr->familyPtr;
 	Tcl_UtfToExternalDString(familyPtr->encoding, source,
		(int) (p - source), &runString);
	familyPtr->textOutProc(hdc, x-(tm.tmOverhang/2), y,
	familyPtr->textOutProc(hdc, (int)(x-(double)tm.tmOverhang/2.0), y,
		(WCHAR *)Tcl_DStringValue(&runString),
		Tcl_DStringLength(&runString) >> familyPtr->isWideFont);
	Tcl_DStringFree(&runString);
    }
    SelectObject(hdc, oldFont);
}

static inline HFONT
SelectFont(
    HDC hdc,
    WinFont *fontPtr,
    SubFont *subFontPtr,
    double angle)
{
    if (angle == 0.0) {
	return SelectObject(hdc, subFontPtr->hFont0);
	return (HFONT)SelectObject(hdc, subFontPtr->hFont0);
    } else if (angle == subFontPtr->angle) {
	return SelectObject(hdc, subFontPtr->hFontAngled);
	return (HFONT)SelectObject(hdc, subFontPtr->hFontAngled);
    } else {
	if (subFontPtr->hFontAngled) {
	    DeleteObject(subFontPtr->hFontAngled);
	}
	subFontPtr->hFontAngled = GetScreenFont(&fontPtr->font.fa,
		subFontPtr->familyPtr->faceName, fontPtr->pixelSize, angle);
	if (subFontPtr->hFontAngled == NULL) {
	    return SelectObject(hdc, subFontPtr->hFont0);
	    return (HFONT)SelectObject(hdc, subFontPtr->hFont0);
	}
	subFontPtr->angle = angle;
	return SelectObject(hdc, subFontPtr->hFontAngled);
	return (HFONT)SelectObject(hdc, subFontPtr->hFontAngled);
    }
}

/*
 *---------------------------------------------------------------------------
 *
 * InitFont --
1558
1559
1560
1561
1562
1563
1564
1565

1566
1567
1568
1569
1570


1571
1572
1573
1574
1575
1576
1577
1594
1595
1596
1597
1598
1599
1600

1601
1602
1603
1604
1605

1606
1607
1608
1609
1610
1611
1612
1613
1614







-
+




-
+
+







    Tcl_DString faceString;
    TkFontAttributes *faPtr;
    WCHAR buf[LF_FACESIZE];

    window = Tk_WindowId(tkwin);
    hwnd = (window == None) ? NULL : TkWinGetHWND(window);
    hdc = GetDC(hwnd);
    oldFont = SelectObject(hdc, hFont);
    oldFont = (HFONT)SelectObject(hdc, hFont);

    GetTextMetricsW(hdc, &tm);

    GetTextFaceW(hdc, LF_FACESIZE, buf);
    Tcl_WinTCharToUtf((LPCTSTR)buf, -1, &faceString);
    Tcl_DStringInit(&faceString);
    Tcl_WCharToUtfDString(buf, wcslen(buf), &faceString);

    fontPtr->font.fid	= (Font) fontPtr;
    fontPtr->hwnd	= hwnd;
    fontPtr->pixelSize	= tm.tmHeight - tm.tmInternalLeading;

    faPtr		= &fontPtr->font.fa;
    faPtr->family	= Tk_GetUid(Tcl_DStringValue(&faceString));
1727
1728
1729
1730
1731
1732
1733
1734

1735
1736
1737
1738
1739
1740
1741
1742

1743
1744
1745

1746
1747


1748
1749
1750

1751
1752
1753
1754
1755
1756
1757
1758
1759
1760

1761
1762
1763
1764
1765
1766
1767
1764
1765
1766
1767
1768
1769
1770

1771
1772
1773
1774
1775
1776
1777
1778

1779
1780
1781

1782
1783

1784
1785
1786
1787

1788
1789
1790
1791
1792
1793
1794
1795
1796
1797

1798
1799
1800
1801
1802
1803
1804
1805







-
+







-
+


-
+

-
+
+


-
+









-
+







 */

static FontFamily *
AllocFontFamily(
    HDC hdc,			/* HDC in which font can be selected. */
    HFONT hFont,		/* Screen font whose FontFamily is to be
				 * returned. */
    int base)			/* Non-zero if this font family is to be used
    TCL_UNUSED(int))			/* Non-zero if this font family is to be used
				 * in the base font of a font object. */
{
    Tk_Uid faceName;
    FontFamily *familyPtr;
    Tcl_DString faceString;
    Tcl_Encoding encoding;
    WCHAR buf[LF_FACESIZE];
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    hFont = SelectObject(hdc, hFont);
    hFont = (HFONT)SelectObject(hdc, hFont);
    GetTextFaceW(hdc, LF_FACESIZE, buf);
    Tcl_WinTCharToUtf((LPCTSTR)buf, -1, &faceString);
    Tcl_DStringInit(&faceString);
    Tcl_WCharToUtfDString(buf, wcslen(buf), &faceString);
    faceName = Tk_GetUid(Tcl_DStringValue(&faceString));
    Tcl_DStringFree(&faceString);
    hFont = SelectObject(hdc, hFont);
    hFont = (HFONT)SelectObject(hdc, hFont);

    familyPtr = tsdPtr->fontFamilyList;
    for ( ; familyPtr != NULL; familyPtr = familyPtr->nextPtr) {
	if (familyPtr->faceName == faceName) {
	    familyPtr->refCount++;
	    return familyPtr;
	}
    }

    familyPtr = ckalloc(sizeof(FontFamily));
    familyPtr = (FontFamily *)ckalloc(sizeof(FontFamily));
    memset(familyPtr, 0, sizeof(FontFamily));
    familyPtr->nextPtr = tsdPtr->fontFamilyList;
    tsdPtr->fontFamilyList = familyPtr;

    /*
     * Set key for this FontFamily.
     */
1839
1840
1841
1842
1843
1844
1845
1846

1847
1848
1849
1850
1851
1852
1853
1877
1878
1879
1880
1881
1882
1883

1884
1885
1886
1887
1888
1889
1890
1891







-
+








static void
FreeFontFamily(
    FontFamily *familyPtr)	/* The FontFamily to delete. */
{
    int i;
    FontFamily **familyPtrPtr;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (familyPtr == NULL) {
	return;
    }
    if (familyPtr->refCount-- > 1) {
    	return;
1916
1917
1918
1919
1920
1921
1922
1923

1924
1925
1926
1927
1928
1929
1930
1954
1955
1956
1957
1958
1959
1960

1961
1962
1963
1964
1965
1966
1967
1968







-
+







    const char *const *aliases;
    const char *const *anyFallbacks;
    const char *const *const *fontFallbacks;
    const char *fallbackName;
    SubFont *subFontPtr;
    Tcl_DString ds;

    if ((ch < BASE_CHARS) || (ch >= 0x30000)) {
    if ((ch < BASE_CHARS) || (ch >= FONTMAP_NUMCHARS)) {
	return &fontPtr->subFontArray[0];
    }

    for (i = 0; i < fontPtr->numSubFonts; i++) {
	if (FontMapLookup(&fontPtr->subFontArray[i], ch)) {
	    return &fontPtr->subFontArray[i];
	}
2024
2025
2026
2027
2028
2029
2030
2031
2032


2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050




2051
2052
2053
2054
2055
2056
2057
2062
2063
2064
2065
2066
2067
2068


2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087

2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098







-
-
+
+

















-
+
+
+
+







    ReleaseDC(fontPtr->hwnd, hdc);
    return subFontPtr;
}

static int CALLBACK
WinFontCanUseProc(
    ENUMLOGFONTW *lfPtr,		/* Logical-font data. */
    NEWTEXTMETRIC *tmPtr,	/* Physical-font data (not used). */
    int fontType,		/* Type of font (not used). */
    TCL_UNUSED(NEWTEXTMETRIC *),	/* Physical-font data (not used). */
    TCL_UNUSED(int),		/* Type of font (not used). */
    LPARAM lParam)		/* Result object to hold result. */
{
    int ch;
    HDC hdc;
    WinFont *fontPtr;
    CanUse *canUsePtr;
    char *fallbackName;
    SubFont *subFontPtr;
    Tcl_DString faceString;
    Tcl_DString *nameTriedPtr;

    canUsePtr	    = (CanUse *) lParam;
    ch		    = canUsePtr->ch;
    hdc		    = canUsePtr->hdc;
    fontPtr	    = canUsePtr->fontPtr;
    nameTriedPtr    = canUsePtr->nameTriedPtr;

    fallbackName = Tcl_WinTCharToUtf((LPCTSTR)lfPtr->elfLogFont.lfFaceName, -1, &faceString);
    fallbackName = (char *) lfPtr->elfLogFont.lfFaceName;
    Tcl_DStringInit(&faceString);
    Tcl_WCharToUtfDString((WCHAR *)fallbackName, wcslen((WCHAR *)fallbackName), &faceString);
    fallbackName = Tcl_DStringValue(&faceString);

    if (SeenName(fallbackName, nameTriedPtr) == 0) {
	subFontPtr = CanUseFallback(hdc, fontPtr, fallbackName, ch,
		canUsePtr->subFontPtrPtr);
	if (subFontPtr != NULL) {
	    canUsePtr->subFontPtr = subFontPtr;
	    Tcl_DStringFree(&faceString);
2086
2087
2088
2089
2090
2091
2092
2093

2094
2095
2096
2097
2098
2099
2100
2127
2128
2129
2130
2131
2132
2133

2134
2135
2136
2137
2138
2139
2140
2141







-
+







FontMapLookup(
    SubFont *subFontPtr,	/* Contains font mapping cache to be queried
				 * and possibly updated. */
    int ch)			/* Character to be tested. */
{
    int row, bitOffset;

    if (ch < 0 || ch >= 0x30000) {
    if (ch < 0 || ch >= FONTMAP_NUMCHARS) {
	return 0;
    }

    row = ch >> FONTMAP_SHIFT;
    if (subFontPtr->fontMap[row] == NULL) {
	FontMapLoadPage(subFontPtr, row);
    }
2130
2131
2132
2133
2134
2135
2136
2137

2138
2139
2140
2141
2142
2143
2144
2171
2172
2173
2174
2175
2176
2177

2178
2179
2180
2181
2182
2183
2184
2185







-
+







FontMapInsert(
    SubFont *subFontPtr,	/* Contains font mapping cache to be
				 * updated. */
    int ch)			/* Character to be added to cache. */
{
    int row, bitOffset;

    if (ch >= 0 && ch < 0x30000) {
    if (ch >= 0 && ch < FONTMAP_NUMCHARS) {
	row = ch >> FONTMAP_SHIFT;
	if (subFontPtr->fontMap[row] == NULL) {
	    FontMapLoadPage(subFontPtr, row);
	}
	bitOffset = ch & (FONTMAP_BITSPERPAGE - 1);
	subFontPtr->fontMap[row][bitOffset >> 3] |= 1 << (bitOffset & 7);
    }
2170
2171
2172
2173
2174
2175
2176
2177

2178
2179

2180
2181
2182
2183
2184
2185
2186
2211
2212
2213
2214
2215
2216
2217

2218
2219

2220
2221
2222
2223
2224
2225
2226
2227







-
+

-
+







    int row)			/* Index of the page to be loaded into the
				 * cache. */
{
    FontFamily *familyPtr;
    Tcl_Encoding encoding;
    int i, j, bitOffset, end, segCount;
    USHORT *startCount, *endCount;
    char buf[16], src[4];
    char buf[16], src[6];

    subFontPtr->fontMap[row] = ckalloc(FONTMAP_BITSPERPAGE / 8);
    subFontPtr->fontMap[row] = (char *)ckalloc(FONTMAP_BITSPERPAGE / 8);
    memset(subFontPtr->fontMap[row], 0, FONTMAP_BITSPERPAGE / 8);

    familyPtr = subFontPtr->familyPtr;
    encoding = familyPtr->encoding;

    if (familyPtr->encoding == TkWinGetUnicodeEncoding()) {
	/*
2403
2404
2405
2406
2407
2408
2409
2410

2411
2412
2413
2414
2415
2416
2417
2444
2445
2446
2447
2448
2449
2450

2451
2452
2453
2454
2455
2456
2457
2458







-
+







	ReleaseSubFont(&subFont);
	return NULL;
    }

    if (fontPtr->numSubFonts >= SUBFONT_SPACE) {
	SubFont *newPtr;

    	newPtr = ckalloc(sizeof(SubFont) * (fontPtr->numSubFonts + 1));
    	newPtr = (SubFont *)ckalloc(sizeof(SubFont) * (fontPtr->numSubFonts + 1));
	memcpy(newPtr, fontPtr->subFontArray,
		fontPtr->numSubFonts * sizeof(SubFont));
	if (fontPtr->subFontArray != fontPtr->staticSubFonts) {
	    ckfree(fontPtr->subFontArray);
	}

	/*
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477

2478
2479
2480
2481
2482
2483
2484
2485
2486
2492
2493
2494
2495
2496
2497
2498

2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516

2517


2518
2519
2520
2521
2522
2523
2524







-


















-
+
-
-







    const char *faceName,	/* Overrides font family specified in font
				 * attributes. */
    int pixelSize,		/* Overrides size specified in font
				 * attributes. */
    double angle)		/* What is the desired orientation of the
				 * font. */
{
    Tcl_DString ds;
    HFONT hFont;
    LOGFONTW lf;

    memset(&lf, 0, sizeof(lf));
    lf.lfHeight		= -pixelSize;
    lf.lfWidth		= 0;
    lf.lfEscapement	= ROUND16(angle * 10);
    lf.lfOrientation	= ROUND16(angle * 10);
    lf.lfWeight = (faPtr->weight == TK_FW_NORMAL) ? FW_NORMAL : FW_BOLD;
    lf.lfItalic		= faPtr->slant;
    lf.lfUnderline	= faPtr->underline;
    lf.lfStrikeOut	= faPtr->overstrike;
    lf.lfCharSet	= DEFAULT_CHARSET;
    lf.lfOutPrecision	= OUT_TT_PRECIS;
    lf.lfClipPrecision	= CLIP_DEFAULT_PRECIS;
    lf.lfQuality	= DEFAULT_QUALITY;
    lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;

    Tcl_WinUtfToTChar(faceName, -1, &ds);
    MultiByteToWideChar(CP_UTF8, 0, faceName, -1, lf.lfFaceName, LF_FACESIZE);
    wcsncpy(lf.lfFaceName, (WCHAR *)Tcl_DStringValue(&ds), LF_FACESIZE-1);
    Tcl_DStringFree(&ds);
    lf.lfFaceName[LF_FACESIZE-1] = 0;
    hFont = CreateFontIndirectW(&lf);
    return hFont;
}

/*
 *-------------------------------------------------------------------------
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517

2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528

2529
2530
2531
2532
2533
2534
2535
2536
2537

2538
2539
2540
2541
2542
2543
2544
2543
2544
2545
2546
2547
2548
2549






2550











2551
2552
2553
2554
2555
2556
2557
2558
2559

2560
2561
2562
2563
2564
2565
2566
2567







-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
+








-
+







FamilyExists(
    HDC hdc,			/* HDC in which font family will be used. */
    const char *faceName)	/* Font family to query. */
{
    int result;
    Tcl_DString faceString;

    /*
     * Just immediately rule out the following fonts, because they look so
     * ugly on windows. The caller's fallback mechanism will cause the
     * corresponding appropriate TrueType fonts to be selected.
     */

    Tcl_DStringInit(&faceString);
    if (strcasecmp(faceName, "Courier") == 0) {
	return 0;
    }
    if (strcasecmp(faceName, "Times") == 0) {
	return 0;
    }
    if (strcasecmp(faceName, "Helvetica") == 0) {
	return 0;
    }

    Tcl_WinUtfToTChar(faceName, -1, &faceString);
    Tcl_UtfToWCharDString(faceName, -1, &faceString);

    /*
     * If the family exists, WinFontExistProc() will be called and
     * EnumFontFamilies() will return whatever WinFontExistProc() returns. If
     * the family doesn't exist, EnumFontFamilies() will just return a
     * non-zero value.
     */

    result = EnumFontFamiliesW(hdc, (WCHAR*) Tcl_DStringValue(&faceString),
    result = EnumFontFamiliesW(hdc, (WCHAR *)Tcl_DStringValue(&faceString),
	    (FONTENUMPROCW) WinFontExistProc, 0);
    Tcl_DStringFree(&faceString);
    return (result == 0);
}

static const char *
FamilyOrAliasExists(
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570




2571
2572
2573
2574
2575
2576
2577
2583
2584
2585
2586
2587
2588
2589




2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600







-
-
-
-
+
+
+
+







	}
    }
    return NULL;
}

static int CALLBACK
WinFontExistProc(
    ENUMLOGFONTW *lfPtr,		/* Logical-font data. */
    NEWTEXTMETRIC *tmPtr,	/* Physical-font data (not used). */
    int fontType,		/* Type of font (not used). */
    LPARAM lParam)		/* EnumFontData to hold result. */
    TCL_UNUSED(ENUMLOGFONTW *),		/* Logical-font data. */
    TCL_UNUSED(NEWTEXTMETRIC *),	/* Physical-font data (not used). */
    TCL_UNUSED(int),		/* Type of font (not used). */
    TCL_UNUSED(LPARAM))		/* EnumFontData to hold result. */
{
    return 0;
}

/*
 * The following data structures are used when querying a TrueType font file
 * to determine which characters the font supports.
2718
2719
2720
2721
2722
2723
2724
2725

2726
2727
2728
2729
2730
2731
2732
2741
2742
2743
2744
2745
2746
2747

2748
2749
2750
2751
2752
2753
2754
2755







-
+







    char *s;

    segCount = 0;
    startCount = NULL;
    endCount = NULL;
    *symbolPtr = 0;

    hFont = SelectObject(hdc, hFont);
    hFont = (HFONT)SelectObject(hdc, hFont);

    i = 0;
    s = (char *) &i;
    *s = '\1';
    swapped = 0;

    if (i == 1) {
2773
2774
2775
2776
2777
2778
2779
2780
2781


2782
2783
2784
2785
2786
2787
2788
2796
2797
2798
2799
2800
2801
2802


2803
2804
2805
2806
2807
2808
2809
2810
2811







-
-
+
+







	    if (subTable.any.format == 4) {
		if (swapped) {
		    SwapShort(&subTable.segment.segCountX2);
		}
		segCount = subTable.segment.segCountX2 / 2;
		cbData = segCount * sizeof(USHORT);

		startCount = ckalloc(cbData);
		endCount = ckalloc(cbData);
		startCount = (USHORT *)ckalloc(cbData);
		endCount = (USHORT *)ckalloc(cbData);

		offset = encTable.offset + sizeof(subTable.segment);
		GetFontData(hdc, cmapKey, (DWORD) offset, endCount, cbData);
		offset += cbData + sizeof(USHORT);
		GetFontData(hdc, cmapKey, (DWORD) offset, startCount, cbData);
		if (swapped) {
		    for (i = 0; i < segCount; i++) {
2817
2818
2819
2820
2821
2822
2823
2824
2825


2826
2827
2828
2829
2830
2831
2832
2840
2841
2842
2843
2844
2845
2846


2847
2848
2849
2850
2851
2852
2853
2854
2855







-
-
+
+







	/*
	 * Bitmap font. We should also support ranges for the other *_CHARSET
	 * values.
	 */

	segCount = 1;
	cbData = segCount * sizeof(USHORT);
	startCount = ckalloc(cbData);
	endCount = ckalloc(cbData);
	startCount = (USHORT *)ckalloc(cbData);
	endCount = (USHORT *)ckalloc(cbData);
	startCount[0] = 0x0000;
	endCount[0] = 0x00ff;
    }
    SelectObject(hdc, hFont);

    *startCountPtr = startCount;
    *endCountPtr = endCount;
Added win/tkWinIco.c.



































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
 * tkWinIco.h --
 *
 *	This file contains declarations for icon-manipulation routines
 *      in Windows.
 *
 * Copyright © 1995-1996 Microsoft Corp.
 * Copyright © 1998 Brueckner & Jarosch Ing.GmbH, Erfurt, Germany
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tkWinIco.h"

/*
 *----------------------------------------------------------------------
 *
 * DIBNumColors --
 *
 *	Calculates the number of entries in the color table, given by LPSTR
 *	lpbi - pointer to the CF_DIB memory block. Used by titlebar icon code.
 *
 * Results:
 *	WORD - Number of entries in the color table.
 *
 *----------------------------------------------------------------------
 */

static WORD
DIBNumColors(
    LPSTR lpbi)
{
    WORD wBitCount;
    DWORD dwClrUsed;

    dwClrUsed = ((LPBITMAPINFOHEADER) lpbi)->biClrUsed;

    if (dwClrUsed) {
	return (WORD) dwClrUsed;
    }

    wBitCount = ((LPBITMAPINFOHEADER) lpbi)->biBitCount;

    switch (wBitCount) {
    case 1:
	return 2;
    case 4:
	return 16;
    case 8:
	return 256;
    default:
	return 0;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * PaletteSize --
 *
 *	Calculates the number of bytes in the color table, as given by LPSTR
 *	lpbi - pointer to the CF_DIB memory block. Used by titlebar icon code.
 *
 * Results:
 *	Number of bytes in the color table
 *
 *----------------------------------------------------------------------
 */
static WORD
PaletteSize(
    LPSTR lpbi)
{
    return (WORD) (DIBNumColors(lpbi) * sizeof(RGBQUAD));
}

/*
 *----------------------------------------------------------------------
 *
 * FindDIBits --
 *
 *	Locate the image bits in a CF_DIB format DIB, as given by LPSTR lpbi -
 *	pointer to the CF_DIB memory block. Used by titlebar icon code.
 *
 * Results:
 *	pointer to the image bits
 *
 * Side effects: None
 *
 *
 *----------------------------------------------------------------------
 */

LPSTR
FindDIBBits(
    LPSTR lpbi)
{
    return lpbi + *((LPDWORD) lpbi) + PaletteSize(lpbi);
}

/*
 *----------------------------------------------------------------------
 *
 * BytesPerLine --
 *
 *	Calculates the number of bytes in one scan line, as given by
 *	LPBITMAPINFOHEADER lpBMIH - pointer to the BITMAPINFOHEADER that
 *	begins the CF_DIB block. Used by titlebar icon code.
 *
 * Results:
 *	number of bytes in one scan line (DWORD aligned)
 *
 *----------------------------------------------------------------------
 */

DWORD
BytesPerLine(
    LPBITMAPINFOHEADER lpBMIH)
{
    return WIDTHBYTES(lpBMIH->biWidth * lpBMIH->biPlanes * lpBMIH->biBitCount);
}
/*
 *----------------------------------------------------------------------
 *
 * CreateIcoFromPhoto --
 *
 *	Create ico pointer from Tk photo block.
 *
 * Results:
 *	Icon image is created from a valid Tk photo image.
 *
 * Side effects:
 *	Icon is created.
 *
 *----------------------------------------------------------------------
 */

HICON
CreateIcoFromPhoto(
    int width,                  /* Width of image. */
    int height,                 /* Height of image. */
    Tk_PhotoImageBlock block)   /* Image block to convert. */
{
    int idx, bufferSize;
    union {unsigned char *ptr; void *voidPtr;} bgraPixel;
    union {unsigned char *ptr; void *voidPtr;} bgraMask;
    HICON hIcon;
    BITMAPINFO bmInfo;
    ICONINFO iconInfo;

    /*
     * Don't use CreateIcon to create the icon, as it requires color
     * bitmap data in device-dependent format. Instead we use
     * CreateIconIndirect which takes device-independent bitmaps and
     * converts them as required. Initialise icon info structure.
     */

    ZeroMemory(&iconInfo, sizeof(iconInfo));
    iconInfo.fIcon = TRUE;

    /*
     * Create device-independent color bitmap.
     */

    ZeroMemory(&bmInfo, sizeof bmInfo);
    bmInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmInfo.bmiHeader.biWidth = width;
    bmInfo.bmiHeader.biHeight = -height;
    bmInfo.bmiHeader.biPlanes = 1;
    bmInfo.bmiHeader.biBitCount = 32;
    bmInfo.bmiHeader.biCompression = BI_RGB;

    iconInfo.hbmColor = CreateDIBSection(NULL, &bmInfo, DIB_RGB_COLORS,
            &bgraPixel.voidPtr, NULL, 0);
    if (!iconInfo.hbmColor) {
        return NULL;
    }

    /*
     * Convert the photo image data into BGRA format (RGBQUAD).
     */

    bufferSize = height * width * 4;
    for (idx = 0 ; idx < bufferSize ; idx += 4) {
        bgraPixel.ptr[idx] = block.pixelPtr[idx+2];
        bgraPixel.ptr[idx+1] = block.pixelPtr[idx+1];
        bgraPixel.ptr[idx+2] = block.pixelPtr[idx+0];
        bgraPixel.ptr[idx+3] = block.pixelPtr[idx+3];
    }

    /*
     * Create a dummy mask bitmap. The contents of this don't appear to
     * matter, as CreateIconIndirect will setup the icon mask based on the
     * alpha channel in our color bitmap.
     */

    bmInfo.bmiHeader.biBitCount = 1;

    iconInfo.hbmMask = CreateDIBSection(NULL, &bmInfo, DIB_RGB_COLORS,
            &bgraMask.voidPtr, NULL, 0);
    if (!iconInfo.hbmMask) {
        DeleteObject(iconInfo.hbmColor);
        return NULL;
    }

    ZeroMemory(bgraMask.ptr, width*height/8);

    /*
     * Create an icon from the bitmaps.
     */

    hIcon = CreateIconIndirect(&iconInfo);
    DeleteObject(iconInfo.hbmColor);
    DeleteObject(iconInfo.hbmMask);
    if (hIcon == NULL) {
        return NULL;
    }

    return hIcon;
}
/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Added win/tkWinIco.h.






































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
 * tkWinIco.h --
 *
 *	This file contains declarations for icon-manipulation routines
 *      in Windows.
 *
 * Copyright © 1995-1996 Microsoft Corp.
 * Copyright © 1998 Brueckner & Jarosch Ing.GmbH, Erfurt, Germany
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tkWin.h"
#include <windows.h>
#include <shellapi.h>

/*
 * These structures represent the contents of a icon, in terms of its image
 * or resource.
 */

typedef struct {
    UINT Width, Height, Colors;	/* Width, Height and bpp */
    LPBYTE lpBits;		/* Ptr to DIB bits */
    DWORD dwNumBytes;		/* How many bytes? */
    LPBITMAPINFO lpbi;		/* Ptr to header */
    LPBYTE lpXOR;		/* Ptr to XOR image bits */
    LPBYTE lpAND;		/* Ptr to AND image bits */
    HICON hIcon;		/* DAS ICON */
} ICONIMAGE, *LPICONIMAGE;

typedef struct {
    BOOL         bHasChanged;                     // Has image changed?
    TCHAR        szOriginalICOFileName[MAX_PATH]; // Original name
    TCHAR        szOriginalDLLFileName[MAX_PATH]; // Original name
    int          nNumImages;                      // How many images?
    ICONIMAGE    IconImages[1];                   // Image entries
} ICONRESOURCE, *LPICONRESOURCE;

/*
 * This structure is how we represent a block of the above items. We will
 * reallocate these structures according to how many images they need to
 * contain.
 */

typedef struct {
    int nNumImages;		/* How many images? */
    ICONIMAGE IconImages[1];	/* Image entries */
} BlockOfIconImages, *BlockOfIconImagesPtr;

/*
 * These two structures are used to read in icons from an 'icon directory'
 * (i.e. the contents of a .icr file, say). We only use these structures
 * temporarily, since we copy the information we want into a
 * BlockOfIconImages.
 */

typedef struct {
    BYTE bWidth;		/* Width of the image */
    BYTE bHeight;		/* Height of the image (times 2) */
    BYTE bColorCount;		/* Number of colors in image (0 if >=8bpp) */
    BYTE bReserved;		/* Reserved */
    WORD wPlanes;		/* Color Planes */
    WORD wBitCount;		/* Bits per pixel */
    DWORD dwBytesInRes;		/* How many bytes in this resource? */
    DWORD dwImageOffset;	/* Where in the file is this image */
} ICONDIRENTRY, *LPICONDIRENTRY;

typedef struct {
    WORD idReserved;		/* Reserved */
    WORD idType;		/* Resource type (1 for icons) */
    WORD idCount;		/* How many images? */
    ICONDIRENTRY idEntries[1];	/* The entries for each image */
} ICONDIR, *LPICONDIR;

/*
 * Used in BytesPerLine
 */

#define WIDTHBYTES(bits)	((((bits) + 31)>>5)<<2)

/*
 * The following are implemented in tkWinIco.c and also used in tkWinWm.c and tkWinSysTray.c.
 */

DWORD BytesPerLine(LPBITMAPINFOHEADER lpBMIH);
LPSTR FindDIBBits(LPSTR lpbi);
HICON CreateIcoFromPhoto(int width, int height,
                        Tk_PhotoImageBlock block);


/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */



Changes to win/tkWinImage.c.
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







/*
 * tkWinImage.c --
 *
 *	This file contains routines for manipulation full-color images.
 *
 * 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.
 */

#include "tkWinInt.h"

208
209
210
211
212
213
214
215




216
217
218
219
220
221
222
208
209
210
211
212
213
214

215
216
217
218
219
220
221
222
223
224
225







-
+
+
+
+







    int offset,
    char *data,
    unsigned int width,
    unsigned int height,
    int bitmap_pad,
    int bytes_per_line)
{
    XImage* imagePtr = ckalloc(sizeof(XImage));
    XImage* imagePtr = (XImage*)ckalloc(sizeof(XImage));
    (void)display;
    (void)visual;

    imagePtr->width = width;
    imagePtr->height = height;
    imagePtr->xoffset = offset;
    imagePtr->format = format;
    imagePtr->data = data;
    imagePtr->byte_order = LSBFirst;
    imagePtr->bitmap_unit = 8;
270
271
272
273
274
275
276
277

278
279
280
281
282
283
284
273
274
275
276
277
278
279

280
281
282
283
284
285
286
287







-
+







 *	Returns a newly allocated image containing the data from the given
 *	rectangle of the given drawable.
 *
 * Side effects:
 *	None.
 *
 * This procedure is adapted from the XGetImage implementation in TkNT. That
 * code is Copyright (c) 1994 Software Research Associates, Inc.
 * code is Copyright © 1994 Software Research Associates, Inc.
 *
 *----------------------------------------------------------------------
 */

static XImage *
XGetImageZPixmap(
    Display *display,
296
297
298
299
300
301
302

303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

319
320
321
322
323
324
325
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321

322
323
324
325
326
327
328
329







+















-
+







    HPALETTE hPal, hPalPrev1 = 0, hPalPrev2 = 0;
    int size;
    unsigned int n;
    unsigned int depth;
    unsigned char *data;
    TkWinDCState state;
    BOOL ret;
    (void)plane_mask;

    if (format != ZPixmap) {
	TkpDisplayWarning("Only ZPixmap types are implemented",
		"XGetImageZPixmap Failure");
	return NULL;
    }

    hdc = TkWinGetDrawableDC(display, d, &state);

    /*
     * Need to do a Blt operation to copy into a new bitmap.
     */

    hbmp = CreateCompatibleBitmap(hdc, (int) width, (int) height);
    hdcMem = CreateCompatibleDC(hdc);
    hbmpPrev = SelectObject(hdcMem, hbmp);
    hbmpPrev = (HBITMAP)SelectObject(hdcMem, hbmp);
    hPal = state.palette;
    if (hPal) {
	hPalPrev1 = SelectPalette(hdcMem, hPal, FALSE);
	n = RealizePalette(hdcMem);
	if (n > 0) {
	    UpdateColors(hdcMem);
	}
346
347
348
349
350
351
352
353

354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

372
373
374
375
376
377
378
350
351
352
353
354
355
356

357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374

375
376
377
378
379
380
381
382







-
+

















-
+







	depth = twdPtr->bitmap.depth;
    }

    size = sizeof(BITMAPINFO);
    if (depth <= 8) {
	size += sizeof(unsigned short) << depth;
    }
    bmInfo = ckalloc(size);
    bmInfo = (BITMAPINFO *)ckalloc(size);

    bmInfo->bmiHeader.biSize		= sizeof(BITMAPINFOHEADER);
    bmInfo->bmiHeader.biWidth		= width;
    bmInfo->bmiHeader.biHeight		= -(int) height;
    bmInfo->bmiHeader.biPlanes		= 1;
    bmInfo->bmiHeader.biBitCount	= depth;
    bmInfo->bmiHeader.biCompression	= BI_RGB;
    bmInfo->bmiHeader.biSizeImage	= 0;
    bmInfo->bmiHeader.biXPelsPerMeter	= 0;
    bmInfo->bmiHeader.biYPelsPerMeter	= 0;
    bmInfo->bmiHeader.biClrUsed		= 0;
    bmInfo->bmiHeader.biClrImportant	= 0;

    if (depth == 1) {
	unsigned char *p, *pend;

	GetDIBits(hdcMem, hbmp, 0, height, NULL, bmInfo, DIB_PAL_COLORS);
	data = ckalloc(bmInfo->bmiHeader.biSizeImage);
	data = (unsigned char *)ckalloc(bmInfo->bmiHeader.biSizeImage);
	if (!data) {
	    /* printf("Failed to allocate data area for XImage.\n"); */
	    ret_image = NULL;
	    goto cleanup;
	}
	ret_image = XCreateImage(display, NULL, depth, ZPixmap, 0, (char *) data,
		width, height, 32, (int) ((width + 31) >> 3) & ~1);
400
401
402
403
404
405
406
407

408
409
410
411
412
413
414
404
405
406
407
408
409
410

411
412
413
414
415
416
417
418







-
+







	}
    } else if (depth == 8) {
	unsigned short *palette;
	unsigned int i;
	unsigned char *p;

	GetDIBits(hdcMem, hbmp, 0, height, NULL, bmInfo, DIB_PAL_COLORS);
	data = ckalloc(bmInfo->bmiHeader.biSizeImage);
	data = (unsigned char *)ckalloc(bmInfo->bmiHeader.biSizeImage);
	if (!data) {
	    /* printf("Failed to allocate data area for XImage.\n"); */
	    ret_image = NULL;
	    goto cleanup;
	}
	ret_image = XCreateImage(display, NULL, 8, ZPixmap, 0, (char *) data,
		width, height, 8, (int) width);
431
432
433
434
435
436
437
438

439
440
441
442
443
444
445
435
436
437
438
439
440
441

442
443
444
445
446
447
448
449







-
+







	p = data;
	palette = (unsigned short *) bmInfo->bmiColors;
	for (i = 0; i < bmInfo->bmiHeader.biSizeImage; i++, p++) {
	    *p = (unsigned char) palette[*p];
	}
    } else if (depth == 16) {
	GetDIBits(hdcMem, hbmp, 0, height, NULL, bmInfo, DIB_RGB_COLORS);
	data = ckalloc(bmInfo->bmiHeader.biSizeImage);
	data = (unsigned char *)ckalloc(bmInfo->bmiHeader.biSizeImage);
	if (!data) {
	    /* printf("Failed to allocate data area for XImage.\n"); */
	    ret_image = NULL;
	    goto cleanup;
	}
	ret_image = XCreateImage(display, NULL, 16, ZPixmap, 0, (char *) data,
		width, height, 16, 0 /* will be calc'ed from bitmap_pad */);
457
458
459
460
461
462
463
464

465
466
467
468
469
470
471
461
462
463
464
465
466
467

468
469
470
471
472
473
474
475







-
+







	    ckfree(ret_image->data);
	    ckfree(ret_image);
	    ret_image = NULL;
	    goto cleanup;
	}
    } else {
	GetDIBits(hdcMem, hbmp, 0, height, NULL, bmInfo, DIB_RGB_COLORS);
	data = ckalloc(width * height * 4);
	data = (unsigned char *)ckalloc(width * height * 4);
	if (!data) {
	    /* printf("Failed to allocate data area for XImage.\n"); */
	    ret_image = NULL;
	    goto cleanup;
	}
	ret_image = XCreateImage(display, NULL, 32, ZPixmap, 0, (char *) data,
		width, height, 0, (int) width * 4);
480
481
482
483
484
485
486
487

488
489
490
491
492
493
494
484
485
486
487
488
489
490

491
492
493
494
495
496
497
498







-
+







	     * can likely be optimized for that. -- hobbs
	     */

	    unsigned char *smallBitData, *smallBitBase, *bigBitData;
	    unsigned int byte_width, h, w;

	    byte_width = ((width * 3 + 3) & ~(unsigned)3);
	    smallBitBase = ckalloc(byte_width * height);
	    smallBitBase = (unsigned char *)ckalloc(byte_width * height);
	    if (!smallBitBase) {
		ckfree(ret_image->data);
		ckfree(ret_image);
		ret_image = NULL;
		goto cleanup;
	    }
	    smallBitData = smallBitBase;
610
611
612
613
614
615
616
617

618
619
620
621
622
623
624
614
615
616
617
618
619
620

621
622
623
624
625
626
627
628







-
+







	COLORREF pixel;

	dc = TkWinGetDrawableDC(display, d, &state);

	imagePtr = XCreateImage(display, NULL, 32, format, 0, NULL,
		width, height, 32, 0);
	size = imagePtr->bytes_per_line * imagePtr->height;
	imagePtr->data = ckalloc(size);
	imagePtr->data = (char *)ckalloc(size);
	ZeroMemory(imagePtr->data, size);

	for (yy = 0; yy < height; yy++) {
	    for (xx = 0; xx < width; xx++) {
		pixel = GetPixel(dc, x+(int)xx, y+(int)yy);
		if (pixel == CLR_INVALID) {
		    break;
657
658
659
660
661
662
663
664

665
666
667
668
669
670
671
661
662
663
664
665
666
667

668
669
670
671
672
673
674
675







-
+








	    TkpDisplayWarning(errMsg, "XGetImage Failure");
	    return NULL;
	}

	imagePtr = XCreateImage(display, NULL, 1, XYBitmap, 0, NULL,
		width, height, 32, 0);
	imagePtr->data = ckalloc(imagePtr->bytes_per_line * imagePtr->height);
	imagePtr->data = (char *)ckalloc(imagePtr->bytes_per_line * imagePtr->height);

	dc = GetDC(NULL);

	GetDIBits(dc, twdPtr->bitmap.handle, 0, height, NULL,
		infoPtr, DIB_RGB_COLORS);

	infoPtr->bmiHeader.biSize		= sizeof(BITMAPINFOHEADER);
Changes to win/tkWinInit.c.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







/*
 * tkWinInit.c --
 *
 *	This file contains Windows-specific interpreter initialization
 *	functions.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright © 1995-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.
 */

#include "tkWinInt.h"

31
32
33
34
35
36
37

38
39
40


41
42

43
44
45
46
47
48
49
31
32
33
34
35
36
37
38
39
40

41
42
43
44
45
46
47
48
49
50
51
52







+


-
+
+


+







 *----------------------------------------------------------------------
 */

int
TkpInit(
    Tcl_Interp *interp)
{
    (void)interp;
    /*
     * This is necessary for static initialization, and is ok otherwise
     * because TkWinXInit flips a static bit to do its work just once.
     * because TkWinXInit flips a static bit to do its work just once. Also,
     * initialize the Windows systray command here.
     */

    WinIcoInit(interp);
    TkWinXInit(Tk_GetHINSTANCE());
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
133
134
135
136
137
138
139
140

141
142
143
144
145
146

147
148
149
150
151


152
153
154

155
156
157
158
159
160
161
136
137
138
139
140
141
142

143
144
145
146
147
148

149
150
151
152


153
154
155
156

157
158
159
160
161
162
163
164







-
+





-
+



-
-
+
+


-
+







	    return;
	}
    }
#endif /* !STATIC_BUILD */

    len = MultiByteToWideChar(CP_UTF8, 0, title, -1, titleString, TK_MAX_WARN_LEN);
    msgString = &titleString[len + 1];
    titleString[TK_MAX_WARN_LEN - 1] = L'\0';
    titleString[TK_MAX_WARN_LEN - 1] = '\0';
    MultiByteToWideChar(CP_UTF8, 0, msg, -1, msgString, (TK_MAX_WARN_LEN - 1) - len);
    /*
     * Truncate MessageBox string if it is too long to not overflow the screen
     * and cause possible oversized window error.
     */
    if (titleString[TK_MAX_WARN_LEN - 1] != L'\0') {
    if (titleString[TK_MAX_WARN_LEN - 1] != '\0') {
	memcpy(titleString + (TK_MAX_WARN_LEN - 5), L" ...", 5 * sizeof(WCHAR));
    }
    if (IsDebuggerPresent()) {
	titleString[len - 1] = L':';
	titleString[len] = L' ';
	titleString[len - 1] = ':';
	titleString[len] = ' ';
	OutputDebugStringW(titleString);
    } else {
	titleString[len - 1] = L'\0';
	titleString[len - 1] = '\0';
	MessageBoxW(NULL, msgString, titleString,
		MB_OK | MB_ICONEXCLAMATION | MB_SYSTEMMODAL
		| MB_SETFOREGROUND | MB_TOPMOST);
    }
}

/*
192
193
194
195
196
197
198

199

200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
195
196
197
198
199
200
201
202

203
204
205
206
207
208
209
210
211
212

213
214
215
216
217
218
219
220







+
-
+









-








	wsprintfW(sBuffer, L"Error Code: %08lX", hrError);
    }

    if ((p = wcsrchr(lpBuffer, '\r')) != NULL) {
	*p = '\0';
    }

    Tcl_DStringInit(&ds);
    Tcl_WinTCharToUtf((LPCTSTR)lpBuffer, -1, &ds);
    Tcl_WCharToUtfDString(lpBuffer, wcslen(lpBuffer), &ds);
    errPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds));
    Tcl_DStringFree(&ds);

    if (lpBuffer != sBuffer) {
	LocalFree((HLOCAL)lpBuffer);
    }

    return errPtr;
}


/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Changes to win/tkWinInt.h.
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







/*
 * tkWinInt.h --
 *
 *	This file contains declarations that are shared among the
 *	Windows-specific parts of Tk, but aren't used by the rest of Tk.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright (c) 1998-2000 by Scriptics Corporation.
 * Copyright (c) 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.
 */

#ifndef _TKWININT
#define _TKWININT
138
139
140
141
142
143
144



145
146
147
148
149
150
151
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154







+
+
+








/*
 * Internal functions used by more than one source file.
 */

#include "tkIntPlatDecls.h"

#ifdef __cplusplus
extern "C" {
#endif
/*
 * Special proc needed as tsd accessor function between
 * tkWinX.c:GenerateXEvent and tkWinClipboard.c:UpdateClipboard
 */

MODULE_SCOPE void TkWinUpdatingClipboard(int mode);

181
182
183
184
185
186
187

188
189
190
191
192
193
194
195
196
197
198
199
200
201
202




203
204
205
206
207
208







209
210
211
212
213
214
215
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230







+















+
+
+
+






+
+
+
+
+
+
+








/*
 * Values returned by TkWinGetPlatformTheme.
 */

#define TK_THEME_WIN_CLASSIC    1
#define TK_THEME_WIN_XP         2
#define TK_THEME_WIN_VISTA      3

/*
 * The following is implemented in tkWinWm and used by tkWinEmbed.c
 */

MODULE_SCOPE void		TkpWinToplevelWithDraw(TkWindow *winPtr);
MODULE_SCOPE void		TkpWinToplevelIconify(TkWindow *winPtr);
MODULE_SCOPE void		TkpWinToplevelDeiconify(TkWindow *winPtr);
MODULE_SCOPE long		TkpWinToplevelIsControlledByWm(TkWindow *winPtr);
MODULE_SCOPE long		TkpWinToplevelMove(TkWindow *winPtr, int x, int y);
MODULE_SCOPE long		TkpWinToplevelOverrideRedirect(TkWindow *winPtr,
			    int reqValue);
MODULE_SCOPE void		TkpWinToplevelDetachWindow(TkWindow *winPtr);
MODULE_SCOPE int		TkpWmGetState(TkWindow *winPtr);

MODULE_SCOPE int		TkTranslateWinEvent(HWND hwnd, UINT message,
			    WPARAM wParam, LPARAM lParam, LRESULT *result);
MODULE_SCOPE void		TkWinPointerEvent(HWND hwnd, int x, int y);

/*
 * The following is implemented in tkWinPointer.c and also used in tkWinWindow.c
 */

MODULE_SCOPE void		TkSetCursorPos(int x, int y);


/*
 * The following is implemented in tkWinSysTray.c
 */

MODULE_SCOPE  int       WinIcoInit (Tcl_Interp* interp);

/*
 * Common routines used in Windows implementation
 */
MODULE_SCOPE Tcl_Obj *	        TkWin32ErrorObj(HRESULT hrError);


/*
236
237
238
239
240
241
242
243




244
251
252
253
254
255
256
257
258
259
260
261
262
263








+
+
+
+

#ifndef GWLP_WNDPROC
#define GWLP_WNDPROC		GWL_WNDPROC
#define GWLP_HINSTANCE		GWL_HINSTANCE
#define GWLP_HWNDPARENT		GWL_HWNDPARENT
#define GWLP_USERDATA		GWL_USERDATA
#define GWLP_ID			GWL_ID
#endif /* !GWLP_WNDPROC */

#ifdef __cplusplus
}
#endif

#endif /* _TKWININT */
Changes to win/tkWinKey.c.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







/*
 * tkWinKey.c --
 *
 *	This file contains X emulation routines for keyboard related
 *	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.
 */

#include "tkWinInt.h"
#include "X11/XF86keysym.h"
94
95
96
97
98
99
100
101


102
103
104

105

106
107

108
109
110
111
112

113
114
115
116
117
118
119
94
95
96
97
98
99
100

101
102
103
104
105
106

107
108

109
110
111
112
113

114
115
116
117
118
119
120
121







-
+
+



+
-
+

-
+




-
+







				 * input context. */
    XEvent *eventPtr,		/* X keyboard event. */
    Tcl_DString *dsPtr)		/* Uninitialized or empty string to hold
				 * result. */
{
    XKeyEvent *keyEv = &eventPtr->xkey;
    int len;
    char buf[4];
    char buf[6];
    (void)winPtr;

    Tcl_DStringInit(dsPtr);
    if (keyEv->send_event == -1) {
	TkKeyEvent *ev = (TkKeyEvent *)keyEv;
	if (keyEv->nbytes > 0) {
	if (ev->nbytes > 0) {
	    Tcl_ExternalToUtfDString(TkWinGetKeyInputEncoding(),
		    keyEv->trans_chars, keyEv->nbytes, dsPtr);
		    ev->trans_chars, ev->nbytes, dsPtr);
	}
    } else if (keyEv->send_event == -3) {

	/*
	 * Special case for WM_UNICHAR and win2000 multi-lingal IME input
	 * Special case for WM_UNICHAR and win2000 multilingual IME input
	 */

	len = TkUniCharToUtf(keyEv->keycode, buf);
	Tcl_DStringAppend(dsPtr, buf, len);
    } else {
	/*
	 * This is an event generated from generic code. It has no nchars or
151
152
153
154
155
156
157


















158
159
160
161
162
163
164
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







KeySym
XKeycodeToKeysym(
    Display *display,
    unsigned int keycode,
    int index)
{
    int state = 0;
    (void)display;

    if (index & 0x01) {
	state |= ShiftMask;
    }
    return KeycodeToKeysym(keycode, state, 0);
}

KeySym
XkbKeycodeToKeysym(
    Display *display,
    unsigned int keycode,
    int group,
    int index)
{
    int state = 0;
    (void)display;
    (void)group;

    if (index & 0x01) {
	state |= ShiftMask;
    }
    return KeycodeToKeysym(keycode, state, 0);
}

500
501
502
503
504
505
506
507

508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523

524
525
526
527
528
529
530
531


532
533
534

535
536
537
538
539
540
541
542
543
544
545

546
547
548
549
550
551
552
553
554
555
556
557

558
559
560
561
562
563
564
520
521
522
523
524
525
526

527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542

543
544
545
546
547
548
549


550
551
552
553

554
555
556
557
558
559
560
561
562
563
564

565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585







-
+















-
+






-
-
+
+


-
+










-
+












+







     */

    if (dispPtr->modKeyCodes != NULL) {
	ckfree(dispPtr->modKeyCodes);
    }
    dispPtr->numModKeyCodes = 0;
    arraySize = KEYCODE_ARRAY_SIZE;
    dispPtr->modKeyCodes = ckalloc(KEYCODE_ARRAY_SIZE * sizeof(KeyCode));
    dispPtr->modKeyCodes = (KeyCode *)ckalloc(KEYCODE_ARRAY_SIZE * sizeof(KeyCode));
    for (i = 0, codePtr = modMapPtr->modifiermap; i < max; i++, codePtr++) {
	if (*codePtr == 0) {
	    continue;
	}

	/*
	 * Make sure that the keycode isn't already in the array.
	 */

	for (j = 0; j < dispPtr->numModKeyCodes; j++) {
	    if (dispPtr->modKeyCodes[j] == *codePtr) {
		goto nextModCode;
	    }
	}
	if (dispPtr->numModKeyCodes >= arraySize) {
	    KeyCode *new;
	    KeyCode *newKey;

	    /*
	     * Ran out of space in the array; grow it.
	     */

	    arraySize *= 2;
	    new = ckalloc(arraySize * sizeof(KeyCode));
	    memcpy(new, dispPtr->modKeyCodes,
	    newKey = (KeyCode *)ckalloc(arraySize * sizeof(KeyCode));
	    memcpy(newKey, dispPtr->modKeyCodes,
		    dispPtr->numModKeyCodes * sizeof(KeyCode));
	    ckfree(dispPtr->modKeyCodes);
	    dispPtr->modKeyCodes = new;
	    dispPtr->modKeyCodes = newKey;
	}
	dispPtr->modKeyCodes[dispPtr->numModKeyCodes] = *codePtr;
	dispPtr->numModKeyCodes++;
	nextModCode: continue;
    }
    XFreeModifiermap(modMapPtr);
}

/*
 * When mapping from a keysym to a keycode, need information about the
 * modifier state that should be used so that when they call XKeycodeToKeysym
 * modifier state that should be used so that when they call XkbKeycodeToKeysym
 * taking into account the xkey.state, they will get back the original keysym.
 */

void
TkpSetKeycodeAndState(
    Tk_Window tkwin,
    KeySym keySym,
    XEvent *eventPtr)
{
    int i;
    SHORT result;
    int shift;
    (void)tkwin;

    eventPtr->xkey.keycode = 0;
    if (keySym == NoSymbol) {
	return;
    }

    /*
607
608
609
610
611
612
613

614
615
616
617
618
619
620
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642







+







KeyCode
XKeysymToKeycode(
    Display *display,
    KeySym keysym)
{
    int i;
    SHORT result;
    (void)display;

    /*
     * We check our private map first for a virtual keycode, as VkKeyScan will
     * return values that don't map to X for the "extended" Syms. This may be
     * due to just casting problems below, but this works.
     */

652
653
654
655
656
657
658
659


660
661
662

663
664
665
666
667
668
669
674
675
676
677
678
679
680

681
682
683
684

685
686
687
688
689
690
691
692







-
+
+


-
+







 *----------------------------------------------------------------------
 */

XModifierKeymap	*
XGetModifierMapping(
    Display *display)
{
    XModifierKeymap *map = ckalloc(sizeof(XModifierKeymap));
    XModifierKeymap *map = (XModifierKeymap *)ckalloc(sizeof(XModifierKeymap));
    (void)display;

    map->max_keypermod = 1;
    map->modifiermap = ckalloc(sizeof(KeyCode) * 8);
    map->modifiermap = (KeyCode *)ckalloc(sizeof(KeyCode) * 8);
    map->modifiermap[ShiftMapIndex] = VK_SHIFT;
    map->modifiermap[LockMapIndex] = VK_CAPITAL;
    map->modifiermap[ControlMapIndex] = VK_CONTROL;
    map->modifiermap[Mod1MapIndex] = VK_NUMLOCK;
    map->modifiermap[Mod2MapIndex] = VK_MENU;
    map->modifiermap[Mod3MapIndex] = VK_SCROLL;
    map->modifiermap[Mod4MapIndex] = 0;
713
714
715
716
717
718
719


720
721
722
723
724
725
726
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751







+
+







 *----------------------------------------------------------------------
 */

KeySym
XStringToKeysym(
    _Xconst char *string)
{
    (void)string;

    return NoSymbol;
}

/*
 *----------------------------------------------------------------------
 *
 * XKeysymToString --
736
737
738
739
740
741
742


743
744
745
746
747
748
749
750
751
752
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779







+
+










 *----------------------------------------------------------------------
 */

char *
XKeysymToString(
    KeySym keysym)
{
    (void)keysym;

    return NULL;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Changes to win/tkWinMenu.c.
1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15






-
-
+
+







/*
 * tkWinMenu.c --
 *
 *	This module implements the Windows platform-specific features of
 *	menus.
 *
 * Copyright (c) 1996-1998 by Sun Microsystems, Inc.
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 * Copyright © 1996-1998 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.
 */

#define OEMRESOURCE
#include "tkWinInt.h"
229
230
231
232
233
234
235
236

237
238
239
240
241
242

243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259


260
261
262
263
264
265
266
229
230
231
232
233
234
235

236
237
238
239
240
241

242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257


258
259
260
261
262
263
264
265
266







-
+





-
+















-
-
+
+







 */

static int
GetNewID(
    TkMenuEntry *mePtr,		/* The menu we are working with. */
    WORD *menuIDPtr)		/* The resulting id. */
{
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    WORD curID = tsdPtr->lastCommandID;

    while (1) {
	Tcl_HashEntry *commandEntryPtr;
	int new;
	int isNew;

	/*
	 * Try the next ID number, taking care to wrap rather than stray
	 * into the system menu IDs.  [Bug 3235256]
	 */
	if (++curID >= 0xF000) {
	    curID = 1;
	}

	/* Return error when we've checked all IDs without success. */
	if (curID == tsdPtr->lastCommandID) {
	    return TCL_ERROR;
	}

	commandEntryPtr = Tcl_CreateHashEntry(&tsdPtr->commandTable,
		INT2PTR(curID), &new);
	if (new) {
		INT2PTR(curID), &isNew);
	if (isNew) {
	    Tcl_SetHashValue(commandEntryPtr, mePtr);
	    *menuIDPtr = curID;
	    tsdPtr->lastCommandID = curID;
	    return TCL_OK;
	}
    }
}
281
282
283
284
285
286
287
288

289
290
291
292
293
294
295
281
282
283
284
285
286
287

288
289
290
291
292
293
294
295







-
+







 *----------------------------------------------------------------------
 */

static void
FreeID(
    WORD commandID)
{
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    /*
     * If the menuHWND is NULL, this table has been finalized already.
     */

    if (tsdPtr->menuHWND != NULL) {
324
325
326
327
328
329
330
331

332
333
334
335
336
337
338
324
325
326
327
328
329
330

331
332
333
334
335
336
337
338







-
+







TkpNewMenu(
    TkMenu *menuPtr)		/* The common structure we are making the
				 * platform structure for. */
{
    HMENU winMenuHdl;
    Tcl_HashEntry *hashEntryPtr;
    int newEntry;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    winMenuHdl = CreatePopupMenu();
    if (winMenuHdl == NULL) {
    	Tcl_SetObjResult(menuPtr->interp, Tcl_NewStringObj(
		"No more menus can be allocated.", -1));
	Tcl_SetErrorCode(menuPtr->interp, "TK", "MENU", "SYSTEM_RESOURCES", NULL);
370
371
372
373
374
375
376
377

378
379
380
381
382
383
384
385
386
387
388
389
390
391

392
393
394
395
396
397
398
370
371
372
373
374
375
376

377
378
379
380
381
382
383
384
385
386
387
388
389
390

391
392
393
394
395
396
397
398







-
+













-
+








void
TkpDestroyMenu(
    TkMenu *menuPtr)		/* The common menu structure */
{
    HMENU winMenuHdl = (HMENU) menuPtr->platformData;
    const char *searchName;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (menuPtr->menuFlags & MENU_RECONFIGURE_PENDING) {
	Tcl_CancelIdleCall(ReconfigureWindowsMenu, menuPtr);
    }

    if (winMenuHdl == NULL) {
	return;
    }

    if (menuPtr->menuFlags & MENU_SYSTEM_MENU) {
	TkMenuEntry *searchEntryPtr;
	Tcl_HashTable *tablePtr = TkGetMenuHashTable(menuPtr->interp);
	char *menuName = Tcl_GetHashKey(tablePtr,
	char *menuName = (char *)Tcl_GetHashKey(tablePtr,
		menuPtr->menuRefPtr->hashEntryPtr);

	/*
	 * Search for the menu in the menubar, if it is present, get the
	 * wrapper window associated with the toplevel and reset its
	 * system menu to the default menu.
	 */
416
417
418
419
420
421
422
423

424
425
426
427
428
429
430
416
417
418
419
420
421
422

423
424
425
426
427
428
429
430







-
+







	/*
	 * Remove the menu from the menu hash table, then destroy the handle.
	 * If the menuHWND is NULL, this table has been finalized already.
	 */

	if (tsdPtr->menuHWND != NULL) {
	    Tcl_HashEntry *hashEntryPtr =
		Tcl_FindHashEntry(&tsdPtr->winMenuTable, (char *) winMenuHdl);
		Tcl_FindHashEntry(&tsdPtr->winMenuTable, winMenuHdl);

	    if (hashEntryPtr != NULL) {
		Tcl_DeleteHashEntry(hashEntryPtr);
	    }
	}
 	DestroyMenu(winMenuHdl);
    }
488
489
490
491
492
493
494
495

496
497
498

499
500
501

502
503
504

505
506
507
508
509
510
511
512
513

514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530

531
532
533
534
535
536
537
538
539

540
541
542
543
544

545
546
547
548
549
550
551
488
489
490
491
492
493
494

495
496
497

498
499
500

501
502
503

504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530

531
532
533
534
535
536
537
538
539

540
541
542
543
544

545
546
547
548
549
550
551
552







-
+


-
+


-
+


-
+









+
















-
+








-
+




-
+







GetEntryText(
    TkMenu *menuPtr,		/* The menu considered. */
    TkMenuEntry *mePtr)		/* A pointer to the menu entry. */
{
    char *itemText;

    if (mePtr->type == TEAROFF_ENTRY) {
	itemText = ckalloc(sizeof("(Tear-off)"));
	itemText = (char *)ckalloc(sizeof("(Tear-off)"));
	strcpy(itemText, "(Tear-off)");
    } else if (mePtr->imagePtr != NULL) {
	itemText = ckalloc(sizeof("(Image)"));
	itemText = (char *)ckalloc(sizeof("(Image)"));
	strcpy(itemText, "(Image)");
    } else if (mePtr->bitmapPtr != NULL) {
	itemText = ckalloc(sizeof("(Pixmap)"));
	itemText = (char *)ckalloc(sizeof("(Pixmap)"));
	strcpy(itemText, "(Pixmap)");
    } else if (mePtr->labelPtr == NULL || mePtr->labelLength == 0) {
	itemText = ckalloc(sizeof("( )"));
	itemText = (char *)ckalloc(sizeof("( )"));
	strcpy(itemText, "( )");
    } else {
	int i;
	const char *label = (mePtr->labelPtr == NULL) ? ""
		: Tcl_GetString(mePtr->labelPtr);
	const char *accel = ((menuPtr->menuType == MENUBAR) || (mePtr->accelPtr == NULL)) ? ""
		: Tcl_GetString(mePtr->accelPtr);
	const char *p, *next;
	Tcl_DString itemString;
	int ch;

	/*
	 * We have to construct the string with an ampersand preceeding the
	 * underline character, and a tab seperating the text and the accel
	 * text. We have to be careful with ampersands in the string.
	 */

	Tcl_DStringInit(&itemString);

	for (p = label, i = 0; *p != '\0'; i++, p = next) {
	    if (i == mePtr->underline) {
		Tcl_DStringAppend(&itemString, "&", 1);
	    }
	    if (*p == '&') {
		Tcl_DStringAppend(&itemString, "&", 1);
	    }
	    next = Tcl_UtfNext(p);
	    next = p + TkUtfToUniChar(p, &ch);
	    Tcl_DStringAppend(&itemString, p, (int) (next - p));
	}
	if (mePtr->accelLength > 0) {
	    Tcl_DStringAppend(&itemString, "\t", 1);
	    for (p = accel, i = 0; *p != '\0'; i++, p = next) {
		if (*p == '&') {
		    Tcl_DStringAppend(&itemString, "&", 1);
		}
		next = Tcl_UtfNext(p);
		next = p + TkUtfToUniChar(p, &ch);
		Tcl_DStringAppend(&itemString, p, (int) (next - p));
	    }
	}

	itemText = ckalloc(Tcl_DStringLength(&itemString) + 1);
	itemText = (char *)ckalloc(Tcl_DStringLength(&itemString) + 1);
	strcpy(itemText, Tcl_DStringValue(&itemString));
	Tcl_DStringFree(&itemString);
    }
    return itemText;
}

/*
565
566
567
568
569
570
571
572

573
574
575
576
577
578
579
566
567
568
569
570
571
572

573
574
575
576
577
578
579
580







-
+







 *----------------------------------------------------------------------
 */

static void
ReconfigureWindowsMenu(
    ClientData clientData)	/* The menu we are rebuilding */
{
    TkMenu *menuPtr = clientData;
    TkMenu *menuPtr = (TkMenu *)clientData;
    TkMenuEntry *mePtr;
    HMENU winMenuHdl = (HMENU) menuPtr->platformData;
    char *itemText = NULL;
    LPCWSTR lpNewItem;
    UINT flags;
    UINT itemID;
    int i, count, systemMenu = 0, base;
605
606
607
608
609
610
611

612

613
614
615
616
617
618
619
606
607
608
609
610
611
612
613

614
615
616
617
618
619
620
621







+
-
+







	if ((menuPtr->menuType == MENUBAR) && (mePtr->type == TEAROFF_ENTRY)) {
	    continue;
	}

	itemText = GetEntryText(menuPtr, mePtr);
	if ((menuPtr->menuType == MENUBAR)
		|| (menuPtr->menuFlags & MENU_SYSTEM_MENU)) {
		Tcl_DStringInit(&translatedText);
	    Tcl_WinUtfToTChar(itemText, -1, &translatedText);
		Tcl_UtfToWCharDString(itemText, -1, &translatedText);
	    lpNewItem = (LPCWSTR) Tcl_DStringValue(&translatedText);
	    flags |= MF_STRING;
	} else {
	    lpNewItem = (LPCWSTR) mePtr;
	    flags |= MF_OWNERDRAW;
	}

679
680
681
682
683
684
685
686

687
688
689
690
691
692
693
694
695
696
697

698
699
700
701
702
703
704
681
682
683
684
685
686
687

688
689
690
691
692
693
694
695
696
697
698

699
700
701
702
703
704
705
706







-
+










-
+







			    & MENU_SYSTEM_MENU)) {
		Tcl_DString ds;
		TkMenuReferences *menuRefPtr;
		TkMenu *systemMenuPtr = mePtr->childMenuRefPtr->menuPtr;

		Tcl_DStringInit(&ds);
		Tcl_DStringAppend(&ds,
			Tk_PathName(menuPtr->masterMenuPtr->tkwin), -1);
			Tk_PathName(menuPtr->mainMenuPtr->tkwin), -1);
		Tcl_DStringAppend(&ds, ".system", 7);

		menuRefPtr = TkFindMenuReferences(menuPtr->interp,
			Tcl_DStringValue(&ds));

		Tcl_DStringFree(&ds);

		if ((menuRefPtr != NULL)
			&& (menuRefPtr->menuPtr != NULL)
			&& (menuPtr->parentTopLevelPtr != NULL)
			&& (systemMenuPtr->masterMenuPtr
			&& (systemMenuPtr->mainMenuPtr
				== menuRefPtr->menuPtr)) {
		    HMENU systemMenuHdl = (HMENU) systemMenuPtr->platformData;
		    HWND wrapper = TkWinGetWrapperWindow(menuPtr
			    ->parentTopLevelPtr);

		    if (wrapper != NULL) {
			DestroyMenu(systemMenuHdl);
724
725
726
727
728
729
730
731

732
733
734
735
736
737
738
726
727
728
729
730
731
732

733
734
735
736
737
738
739
740







-
+







	    itemText = NULL;
	}
    }


    if ((menuPtr->menuType == MENUBAR)
	    && (menuPtr->parentTopLevelPtr != NULL)) {
	HANDLE bar = TkWinGetWrapperWindow(menuPtr->parentTopLevelPtr);
	HWND bar = TkWinGetWrapperWindow(menuPtr->parentTopLevelPtr);

	if (bar) {
	    DrawMenuBar(bar);
	}
    }

    menuPtr->menuFlags &= ~(MENU_RECONFIGURE_PENDING);
755
756
757
758
759
760
761
762

763
764
765
766
767
768
769
770
771
772

773

774
775
776
777
778
779
780
781
782
783
784

785
786
787
788
789
790
791
757
758
759
760
761
762
763

764
765
766
767
768
769
770
771
772
773

774
775
776
777
778
779
780
781
782
783
784
785
786

787
788
789
790
791
792
793
794







-
+









-
+

+










-
+







 *	The menu is posted and handled.
 *
 *----------------------------------------------------------------------
 */

int
TkpPostMenu(
    Tcl_Interp *interp,
    Tcl_Interp *dummy,
    TkMenu *menuPtr,
    int x, int y, int index)
{
    HMENU winMenuHdl = (HMENU) menuPtr->platformData;
    int result, flags;
    RECT noGoawayRect;
    POINT point;
    Tk_Window parentWindow = Tk_Parent(menuPtr->tkwin);
    int oldServiceMode = Tcl_GetServiceMode();
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    (void)dummy;

    tsdPtr->inPostMenu++;
    CallPendingReconfigureImmediately(menuPtr);

    result = TkPreprocessMenu(menuPtr);
    if (result != TCL_OK) {
	tsdPtr->inPostMenu--;
	return result;
    }

    if (index >= menuPtr->numEntries) {
    if (index >= (int)menuPtr->numEntries) {
	index = menuPtr->numEntries - 1;
    }
    if (index >= 0) {
	y -= menuPtr->entries[index]->y;
    }

    /*
835
836
837
838
839
840
841
842

843
844
845
846
847
848
849
838
839
840
841
842
843
844

845
846
847
848
849
850
851
852







-
+







    }

    TrackPopupMenu(winMenuHdl, flags, x, y, 0,
	    tsdPtr->menuHWND, &noGoawayRect);
    Tcl_SetServiceMode(oldServiceMode);

    GetCursorPos(&point);
    Tk_PointerEvent(NULL, point.x, point.y);
    TkWinPointerEvent(NULL, point.x, point.y);

    if (tsdPtr->inPostMenu) {
	tsdPtr->inPostMenu = 0;
    }
    return TCL_OK;
}

865
866
867
868
869
870
871
872

873
874
875
876
877
878

879
880

881
882
883
884
885
886
887
868
869
870
871
872
873
874

875
876
877
878
879
880
881
882
883

884
885
886
887
888
889
890
891







-
+






+

-
+







 *	The menu is posted.
 *
 *----------------------------------------------------------------------
 */

int
TkpPostTearoffMenu(
    Tcl_Interp *interp,		/* The interpreter of the menu */
    Tcl_Interp *dummy,		/* The interpreter of the menu */
    TkMenu *menuPtr,		/* The menu we are posting */
    int x, int y, int index)	/* The root X,Y coordinates where we are
				 * posting */
{
    int vRootX, vRootY, vRootWidth, vRootHeight;
    int result;
    (void)dummy;

    if (index >= menuPtr->numEntries) {
    if (index >= (int)menuPtr->numEntries) {
	index = menuPtr->numEntries - 1;
    }
    if (index >= 0) {
	y -= menuPtr->entries[index]->y;
    }

    TkActivateMenuEntry(menuPtr, -1);
1060
1061
1062
1063
1064
1065
1066
1067

1068
1069
1070
1071
1072
1073
1074
1064
1065
1066
1067
1068
1069
1070

1071
1072
1073
1074
1075
1076
1077
1078







-
+







    HWND hwnd,
    UINT message,
    WPARAM wParam,
    LPARAM lParam)
{
    static int nIdles = 0;
    LRESULT lResult = 1;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    switch(message) {
    case WM_ENTERIDLE:
	if ((wParam == MSGF_MENU) && (nIdles < 1)
		&& (hwnd == tsdPtr->embeddedMenuHWND)) {
	    Tcl_CreateTimerHandler(200, UpdateEmbeddedMenu,
1136
1137
1138
1139
1140
1141
1142
1143

1144

1145
1146
1147
1148
1149

1150
1151

1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163

1164
1165
1166

1167
1168
1169
1170
1171
1172
1173
1140
1141
1142
1143
1144
1145
1146

1147
1148
1149
1150
1151
1152
1153

1154
1155

1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167

1168
1169
1170

1171
1172
1173
1174
1175
1176
1177
1178







-
+

+




-
+

-
+











-
+


-
+







    LPARAM *plParam,
    LRESULT *plResult)
{
    Tcl_HashEntry *hashEntryPtr;
    int returnResult = 0;
    TkMenu *menuPtr;
    TkMenuEntry *mePtr;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    (void)phwnd;

    switch (*pMessage) {
    case WM_UNINITMENUPOPUP:
	hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable,
		(char *) *pwParam);
		*pwParam);
	if (hashEntryPtr != NULL) {
	    menuPtr = Tcl_GetHashValue(hashEntryPtr);
	    menuPtr = (TkMenu *)Tcl_GetHashValue(hashEntryPtr);
	    if ((menuPtr->menuRefPtr != NULL)
		    && (menuPtr->menuRefPtr->parentEntryPtr != NULL)) {
		TkPostSubmenu(menuPtr->interp,
			menuPtr->menuRefPtr->parentEntryPtr->menuPtr, NULL);
	    }
	}
	break;

    case WM_INITMENU:
	TkMenuInit();
	hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable,
		(char *) *pwParam);
		*pwParam);
	if (hashEntryPtr != NULL) {
	    tsdPtr->oldServiceMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
	    menuPtr = Tcl_GetHashValue(hashEntryPtr);
	    menuPtr = (TkMenu *)Tcl_GetHashValue(hashEntryPtr);
	    tsdPtr->modalMenuPtr = menuPtr;
	    CallPendingReconfigureImmediately(menuPtr);
	    RecursivelyClearActiveMenu(menuPtr);
	    if (!tsdPtr->inPostMenu) {
		Tcl_Interp *interp = menuPtr->interp;
		int code;

1195
1196
1197
1198
1199
1200
1201
1202

1203
1204
1205
1206
1207
1208
1209
1200
1201
1202
1203
1204
1205
1206

1207
1208
1209
1210
1211
1212
1213
1214







-
+







	    break;
	}
	hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->commandTable,
		INT2PTR(LOWORD(*pwParam)));
	if (hashEntryPtr == NULL) {
	    break;
	}
	mePtr = Tcl_GetHashValue(hashEntryPtr);
	mePtr = (TkMenuEntry *)Tcl_GetHashValue(hashEntryPtr);
	if (mePtr != NULL) {
	    TkMenuReferences *menuRefPtr;
	    TkMenuEntry *parentEntryPtr;
	    Tcl_Interp *interp;
	    int code;

	    /*
1241
1242
1243
1244
1245
1246
1247
1248

1249

1250

1251
1252

1253
1254
1255
1256
1257

1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272

1273
1274

1275
1276


1277
1278
1279
1280
1281
1282
1283
1246
1247
1248
1249
1250
1251
1252

1253
1254
1255

1256
1257

1258
1259
1260
1261
1262

1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277

1278
1279
1280
1281


1282
1283
1284
1285
1286
1287
1288
1289
1290







-
+

+
-
+

-
+




-
+














-
+


+
-
-
+
+







	    *plResult = 0;
	    returnResult = 1;
	}
	break;

    case WM_MENUCHAR: {
	hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable,
		(char *) *plParam);
		*plParam);
	if (hashEntryPtr != NULL) {
	    TkSizeT i, len;
	    int i, len, underline;
	    int underline;
	    Tcl_Obj *labelPtr;
	    LPCWSTR wlabel;
	    WCHAR *wlabel;
	    int menuChar;
	    Tcl_DString ds;

	    *plResult = 0;
	    menuPtr = Tcl_GetHashValue(hashEntryPtr);
	    menuPtr = (TkMenu *)Tcl_GetHashValue(hashEntryPtr);
	    /*
	     * Assume we have something directly convertable to Tcl_UniChar.
	     * True at least for wide systems.
	     */
	    menuChar = Tcl_UniCharToUpper(LOWORD(*pwParam));

	    Tcl_DStringInit(&ds);
	    for (i = 0; i < menuPtr->numEntries; i++) {
		underline = menuPtr->entries[i]->underline;
		labelPtr = menuPtr->entries[i]->labelPtr;
		if ((underline >= 0) && (labelPtr != NULL)) {
		    /*
		     * Ensure we don't exceed the label length, then check
		     */
		    const char *src = Tcl_GetStringFromObj(labelPtr, &len);
		    const char *src = TkGetStringFromObj(labelPtr, &len);

		    Tcl_DStringFree(&ds);
		    Tcl_DStringInit(&ds);
		    wlabel = (LPCWSTR) Tcl_WinUtfToTChar(src, len, &ds);
		    if ((underline < len) && (menuChar ==
		    wlabel = Tcl_UtfToWCharDString(src, len, &ds);
		    if (((TkSizeT)underline + 1 < len + 1) && (menuChar ==
				Tcl_UniCharToUpper(wlabel[underline]))) {
			*plResult = (2 << 16) | i;
			returnResult = 1;
			break;
		    }
		}
	    }
1321
1322
1323
1324
1325
1326
1327
1328

1329
1330
1331
1332
1333
1334
1335
1328
1329
1330
1331
1332
1333
1334

1335
1336
1337
1338
1339
1340
1341
1342







-
+







	    Tk_Font tkfont;

	    if (itemPtr->itemState & ODS_NOACCEL && !showMenuAccelerators) {
		drawingParameters |= DRAW_MENU_ENTRY_NOUNDERLINE;
	    }
	    mePtr = (TkMenuEntry *) itemPtr->itemData;
	    menuPtr = mePtr->menuPtr;
	    twdPtr = ckalloc(sizeof(TkWinDrawable));
	    twdPtr = (TkWinDrawable *)ckalloc(sizeof(TkWinDrawable));
	    twdPtr->type = TWD_WINDC;
	    twdPtr->winDC.hdc = itemPtr->hDC;

	    if (mePtr->state != ENTRY_DISABLED) {
		if (itemPtr->itemState & ODS_SELECTED) {
		    TkActivateMenuEntry(menuPtr, mePtr->index);
		} else {
1385
1386
1387
1388
1389
1390
1391
1392

1393
1394

1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413

1414
1415
1416
1417
1418
1419

1420
1421
1422
1423
1424
1425
1426
1427

1428
1429
1430
1431
1432
1433
1434
1392
1393
1394
1395
1396
1397
1398

1399
1400

1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419

1420
1421
1422
1423
1424
1425

1426
1427
1428
1429
1430
1431
1432
1433

1434
1435
1436
1437
1438
1439
1440
1441







-
+

-
+


















-
+





-
+







-
+







		Tcl_SetServiceMode(tsdPtr->oldServiceMode);
		RecursivelyClearActiveMenu(tsdPtr->modalMenuPtr);
	    }
	} else {
	    menuPtr = NULL;
	    if (*plParam != 0) {
		hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable,
			(char *) *plParam);
			*plParam);
		if (hashEntryPtr != NULL) {
		    menuPtr = Tcl_GetHashValue(hashEntryPtr);
		    menuPtr = (TkMenu *)Tcl_GetHashValue(hashEntryPtr);
		}
	    }

	    if (menuPtr != NULL) {
		long entryIndex = LOWORD(*pwParam);

                if ((menuPtr->menuType == MENUBAR) && menuPtr->tearoff) {
                    /*
                     * Windows passes the entry index starting at 0 for
                     * the first menu entry. However this entry #0 is the
                     * tearoff entry for Tk (the menu has -tearoff 1),
                     * which is ignored for MENUBAR menues on Windows.
                     */

                    entryIndex++;
                }
                mePtr = NULL;
		if (flags != 0xFFFF) {
		    if ((flags&MF_POPUP) && (entryIndex<menuPtr->numEntries)) {
		    if ((flags&MF_POPUP) && (entryIndex < (int)menuPtr->numEntries)) {
			mePtr = menuPtr->entries[entryIndex];
		    } else {
			hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->commandTable,
				INT2PTR(entryIndex));
			if (hashEntryPtr != NULL) {
			    mePtr = Tcl_GetHashValue(hashEntryPtr);
			    mePtr = (TkMenuEntry *)Tcl_GetHashValue(hashEntryPtr);
			}
		    }
		}

		if ((mePtr == NULL) || (mePtr->state == ENTRY_DISABLED)) {
		    TkActivateMenuEntry(menuPtr, -1);
		} else {
		    if (mePtr->index >= menuPtr->numEntries) {
		    if (mePtr->index >= (int)menuPtr->numEntries) {
			Tcl_Panic("Trying to activate an entry which doesn't exist");
		    }
		    TkActivateMenuEntry(menuPtr, mePtr->index);
		}
		MenuSelectEvent(menuPtr);
		Tcl_ServiceAll();
		*plResult = 0;
1457
1458
1459
1460
1461
1462
1463
1464

1465
1466
1467
1468
1469
1470
1471
1464
1465
1466
1467
1468
1469
1470

1471
1472
1473
1474
1475
1476
1477
1478







-
+







 *----------------------------------------------------------------------
 */

void
RecursivelyClearActiveMenu(
    TkMenu *menuPtr)		/* The menu to reset. */
{
    int i;
    TkSizeT i;
    TkMenuEntry *mePtr;

    TkActivateMenuEntry(menuPtr, -1);
    MenuSelectEvent(menuPtr);
    for (i = 0; i < menuPtr->numEntries; i++) {
    	mePtr = menuPtr->entries[i];
	if (mePtr->state == ENTRY_ACTIVE) {
1501
1502
1503
1504
1505
1506
1507
1508

1509
1510
1511
1512
1513
1514
1515
1516
1517

1518
1519
1520
1521
1522
1523
1524
1508
1509
1510
1511
1512
1513
1514

1515
1516
1517
1518
1519
1520
1521
1522
1523

1524
1525
1526
1527
1528
1529
1530
1531







-
+








-
+







void
TkpSetWindowMenuBar(
    Tk_Window tkwin,		/* The window we are putting the menubar
				 * into.*/
    TkMenu *menuPtr)		/* The menu we are inserting */
{
    HMENU winMenuHdl;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (menuPtr != NULL) {
	Tcl_HashEntry *hashEntryPtr;
	int newEntry;

	winMenuHdl = (HMENU) menuPtr->platformData;
	hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable,
		(char *) winMenuHdl);
		winMenuHdl);
	Tcl_DeleteHashEntry(hashEntryPtr);
	DestroyMenu(winMenuHdl);
	winMenuHdl = CreateMenu();
	hashEntryPtr = Tcl_CreateHashEntry(&tsdPtr->winMenuTable,
		(char *) winMenuHdl, &newEntry);
	Tcl_SetHashValue(hashEntryPtr, menuPtr);
	menuPtr->platformData = (TkMenuPlatformData) winMenuHdl;
1549
1550
1551
1552
1553
1554
1555




1556
1557
1558
1559
1560
1561
1562
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573







+
+
+
+







void
TkpSetMainMenubar(
    Tcl_Interp *interp,		/* The interpreter of the application */
    Tk_Window tkwin,		/* The frame we are setting up */
    const char *menuName)	/* The name of the menu to put in front. If
    				 * NULL, use the default menu bar. */
{
    (void)interp;
    (void)tkwin;
    (void)menuName;

    /*
     * Nothing to do.
     */
}

/*
 *----------------------------------------------------------------------
1579
1580
1581
1582
1583
1584
1585




1586
1587
1588
1589
1590
1591
1592
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607







+
+
+
+







    TkMenu *menuPtr,		/* The menu we are measuring */
    TkMenuEntry *mePtr,		/* The entry we are measuring */
    Tk_Font tkfont,		/* Precalculated font */
    const Tk_FontMetrics *fmPtr,/* Precalculated font metrics */
    int *widthPtr,		/* The resulting width */
    int *heightPtr)		/* The resulting height */
{
    (void)menuPtr;
    (void)tkfont;
    (void)fmPtr;

    *heightPtr = indicatorDimensions[0];
    if (mePtr->hideMargin) {
	*widthPtr = 0;
    } else {
	int borderWidth;

	Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,
1627
1628
1629
1630
1631
1632
1633






1634

1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654

1655
1656
1657
1658
1659
1660
1661
1662







+
+
+
+
+
+
-
+







    Tk_Font tkfont,		/* The precalculated font */
    const Tk_FontMetrics *fmPtr,/* The precalculated font metrics */
    int *widthPtr,		/* The resulting width */
    int *heightPtr)		/* The resulting height */
{
    *heightPtr = fmPtr->linespace;
    if (mePtr->type == CASCADE_ENTRY) {
        /*
         * Cascade entries have no accelerator but do show an arrow. Set
         * this field width to the width of the OBM_MNARROW system bitmap
         * used to display the arrow. I couldn't find how to query the
         * system for this value, therefore I resort to hardcoding.
         */
	*widthPtr = 0;
	*widthPtr = CASCADE_ARROW_WIDTH;
    } else if ((menuPtr->menuType != MENUBAR) && (mePtr->accelPtr != NULL)) {
	const char *accel = Tcl_GetString(mePtr->accelPtr);

	*widthPtr = Tk_TextWidth(tkfont, accel, mePtr->accelLength);
    } else {
    	*widthPtr = 0;
    }
1662
1663
1664
1665
1666
1667
1668



1669

1670
1671
1672
1673
1674
1675
1676
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692

1693
1694
1695
1696
1697
1698
1699
1700







+
+
+
-
+







    TkMenu *menuPtr,		/* The menu we are measuring */
    TkMenuEntry *mePtr,		/* The entry we are measuring */
    Tk_Font tkfont,		/* The precalculated font */
    const Tk_FontMetrics *fmPtr,/* The precalculated font metrics */
    int *widthPtr,		/* The resulting width */
    int *heightPtr)		/* The resulting height */
{
    (void)mePtr;
    (void)tkfont;

    if (menuPtr->menuType != MASTER_MENU) {
    if (menuPtr->menuType != MAIN_MENU) {
	*heightPtr = 0;
    } else {
	*heightPtr = fmPtr->linespace;
    }
    *widthPtr = 0;
}

1695
1696
1697
1698
1699
1700
1701




1702
1703
1704
1705
1706
1707
1708
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736







+
+
+
+







    TkMenu *menuPtr,		/* The menu we are measuring */
    TkMenuEntry *mePtr,		/* The entry we are measuring */
    Tk_Font tkfont,		/* The precalculated font */
    const Tk_FontMetrics *fmPtr,/* The precalcualted font metrics */
    int *widthPtr,		/* The resulting width */
    int *heightPtr)		/* The resulting height */
{
    (void)menuPtr;
    (void)mePtr;
    (void)tkfont;

    *widthPtr = 0;
    *heightPtr = fmPtr->linespace - (2 * fmPtr->descent);
}

/*
 *----------------------------------------------------------------------
 *
1808
1809
1810
1811
1812
1813
1814





1815
1816
1817
1818
1819
1820
1821
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854







+
+
+
+
+







    Tk_Font tkfont,		/* The precalculated font */
    const Tk_FontMetrics *fmPtr,/* The precalculated font metrics */
    int x,			/* Left edge */
    int y,			/* Top edge */
    int width,
    int height)
{
    (void)tkfont;
    (void)fmPtr;
    (void)width;
    (void)height;

    if ((mePtr->type == CHECK_BUTTON_ENTRY)
	    || (mePtr->type == RADIO_BUTTON_ENTRY)) {
    	if (mePtr->indicatorOn && (mePtr->entryFlags & ENTRY_SELECTED)) {
	    RECT rect;
	    GC whichGC;
	    int borderWidth, activeBorderWidth;

1888
1889
1890
1891
1892
1893
1894



1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912

1913
1914
1915
1916
1917
1918
1919
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947

1948
1949
1950
1951
1952
1953
1954
1955







+
+
+

















-
+







    int y,			/* top edge */
    int width,			/* Width of menu entry */
    int height)			/* Height of menu entry */
{
    int baseline;
    int leftEdge = x + mePtr->indicatorSpace + mePtr->labelWidth;
    const char *accel;
    (void)activeBorder;
    (void)width;
    (void)height;

    if (menuPtr->menuType == MENUBAR) {
        return;
    }

    if (mePtr->accelPtr != NULL) {
	accel = Tcl_GetString(mePtr->accelPtr);
    } else {
	accel = NULL;
    }

    baseline = y + (height + fmPtr->ascent - fmPtr->descent) / 2;

    /*
     * Draw disabled 3D text highlight only with the Win95/98 look.
     */

    if (TkWinGetPlatformTheme() == TK_THEME_WIN_CLASSIC) {
    if (TkWinGetPlatformTheme() != TK_THEME_WIN_XP) {
	if ((mePtr->state == ENTRY_DISABLED)
		&& (menuPtr->disabledFgPtr != NULL) && (accel != NULL)) {
	    COLORREF oldFgColor = gc->foreground;

	    gc->foreground = GetSysColor(COLOR_3DHILIGHT);
	    if (!(mePtr->entryFlags & ENTRY_PLATFORM_FLAG1)) {
		Tk_DrawChars(menuPtr->display, d, gc, tkfont, accel,
1931
1932
1933
1934
1935
1936
1937
1938
1939



1940
1941
1942
1943
1944
1945
1946
1967
1968
1969
1970
1971
1972
1973


1974
1975
1976
1977
1978
1979
1980
1981
1982
1983







-
-
+
+
+








/*
 *----------------------------------------------------------------------
 *
 * DrawMenuEntryArrow --
 *
 *	This function draws the arrow bitmap on the right side of a menu
 *	entry. This function is only used when drawing the arrow for a
 *	disabled cascade menu.
 *	entry. This function is only used when drawing the arrow for:
 *	 - a disabled cascade item
 *	 - a cascade item in any state in a torn-off menu
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
1961
1962
1963
1964
1965
1966
1967


1968
1969
1970
1971










1972
1973
1974
1975
1976
1977
1978
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027







+
+




+
+
+
+
+
+
+
+
+
+







    int drawArrow)		/* For cascade menus, whether of not to draw
				 * the arrow. I cannot figure out Windows'
				 * algorithm for where to draw this. */
{
    COLORREF oldFgColor;
    COLORREF oldBgColor;
    RECT rect;
    (void)gc;
    (void)activeBorder;

    if (!drawArrow || (mePtr->type != CASCADE_ENTRY)) {
	return;
    }

    /*
     * Don't draw the arrow if a submenu is not attached to this
     * cascade entry.
     */

    if ((mePtr->childMenuRefPtr == NULL)
           || (mePtr->childMenuRefPtr->menuPtr == NULL)) {
        return;
    }

    oldFgColor = gc->foreground;
    oldBgColor = gc->background;

    /*
     * Set bitmap bg to highlight color if the menu is highlighted.
     */
2031
2032
2033
2034
2035
2036
2037




2038
2039
2040
2041
2042
2043
2044
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097







+
+
+
+







    int x,			/* left edge */
    int y,			/* top edge */
    int width,			/* width of item */
    int height)			/* height of item */
{
    XPoint points[2];
    Tk_3DBorder border;
    (void)mePtr;
    (void)gc;
    (void)tkfont;
    (void)fmPtr;

    points[0].x = x;
    points[0].y = y + height / 2;
    points[1].x = x + width - 1;
    points[1].y = points[0].y;
    border = Tk_Get3DBorderFromObj(menuPtr->tkwin, menuPtr->borderPtr);
    Tk_Draw3DPolygon(menuPtr->tkwin, d, border, points, 2, 1,
2070
2071
2072
2073
2074
2075
2076



2077
2078
2079
2080
2081
2082

2083
2084
2085
2086

2087
2088
2089
2090
2091
2092
2093
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142

2143
2144
2145
2146
2147
2148
2149
2150







+
+
+






+



-
+







    Tk_Font tkfont,		/* The precalculated font */
    const Tk_FontMetrics *fmPtr,/* The precalculated font metrics */
    int x,			/* Left Edge */
    int y,			/* Top Edge */
    int width,			/* Width of entry */
    int height)			/* Height of entry */
{
    (void)fmPtr;
    (void)width;

    if ((mePtr->underline >= 0) && (mePtr->labelPtr != NULL)) {
	int len;

	len = Tcl_GetCharLength(mePtr->labelPtr);
	if (mePtr->underline < len) {
	    const char *label, *start, *end;
	    int ch;

	    label = Tcl_GetString(mePtr->labelPtr);
	    start = Tcl_UtfAtIndex(label, mePtr->underline);
	    end = Tcl_UtfNext(start);
	    end = start + TkUtfToUniChar(start, &ch);
	    Tk_UnderlineChars(menuPtr->display, d,
		    gc, tkfont, label, x + mePtr->indicatorSpace,
		    y + (height + fmPtr->ascent - fmPtr->descent) / 2,
		    (int) (start - label), (int) (end - label));
	}
    }
}
2109
2110
2111
2112
2113
2114
2115
2116

2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127

2128
2129
2130
2131
2132
2133
2134
2166
2167
2168
2169
2170
2171
2172

2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192







-
+











+







 *	The menu system may take over and process user events for menu input.
 *
 *--------------------------------------------------------------
 */

static int
TkWinMenuKeyObjCmd(
    ClientData clientData,	/* Unused. */
    ClientData dummy,	/* Unused. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    UINT scanCode;
    UINT virtualKey;
    XEvent *eventPtr;
    Tk_Window tkwin;
    TkWindow *winPtr;
    KeySym keySym;
    int i;
    (void)dummy;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "window keySym");
	return TCL_ERROR;
    }

    tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[1]),
2170
2171
2172
2173
2174
2175
2176
2177


2178
2179
2180
2181
2182
2183
2184
2185
2186





2187
2188
2189
2190
2191
2192
2193
2194
2228
2229
2230
2231
2232
2233
2234

2235
2236
2237
2238
2239






2240
2241
2242
2243
2244

2245
2246
2247
2248
2249
2250
2251







-
+
+



-
-
-
-
-
-
+
+
+
+
+
-







	    CallWindowProcW(DefWindowProcW, Tk_GetHWND(Tk_WindowId(tkwin)),
		    WM_SYSKEYDOWN, VK_F10, (int) (scanCode << 16));
	    break;
	default:
	    virtualKey = XKeysymToKeycode(winPtr->display, keySym);
	    scanCode = MapVirtualKeyW(virtualKey, 0);
	    if (0 != scanCode) {
		XKeyEvent xkey = eventPtr->xkey;
		TkKeyEvent xkey;
		memcpy(&xkey, eventPtr, sizeof(xkey));
		CallWindowProcW(DefWindowProcW, Tk_GetHWND(Tk_WindowId(tkwin)),
			WM_SYSKEYDOWN, virtualKey,
			(int) ((scanCode << 16) | (1 << 29)));
		if (xkey.nbytes > 0) {
		    for (i = 0; i < xkey.nbytes; i++) {
			CallWindowProcW(DefWindowProcW,
				Tk_GetHWND(Tk_WindowId(tkwin)), WM_SYSCHAR,
				xkey.trans_chars[i],
				(int) ((scanCode << 16) | (1 << 29)));
		for (i = 0; i < xkey.nbytes; i++) {
		    CallWindowProcW(DefWindowProcW,
			    Tk_GetHWND(Tk_WindowId(tkwin)), WM_SYSCHAR,
			    xkey.trans_chars[i],
			    (int) ((scanCode << 16) | (1 << 29)));
		    }
		}
	    }
	}
    } else if (eventPtr->type == KeyRelease) {
	switch (keySym) {
	case XK_Alt_L:
	    scanCode = MapVirtualKeyW(VK_LMENU, 0);
2253
2254
2255
2256
2257
2258
2259
2260

2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276

2277
2278
2279
2280
2281
2282

2283
2284
2285
2286
2287
2288
2289
2310
2311
2312
2313
2314
2315
2316

2317

2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331

2332
2333
2334
2335
2336
2337

2338
2339
2340
2341
2342
2343
2344
2345







-
+
-














-
+





-
+







     * windows events, so we need to invoke C code to generate the
     * WM_SYSKEYDOWNS and WM_SYSKEYUPs appropriately. Trick is, we can't
     * create a C level binding directly since we may want to modify the
     * binding in Tcl code.
     */

    (void) Tcl_CreateObjCommand(interp, "tk::WinMenuKey",
	    TkWinMenuKeyObjCmd,
	    TkWinMenuKeyObjCmd, Tk_MainWindow(interp), NULL);
	    (ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL);

    (void) Tk_CreateBinding(interp, bindingTable, (ClientData) uid,
	    "<Alt_L>", "tk::WinMenuKey %W %N", 0);

    (void) Tk_CreateBinding(interp, bindingTable, (ClientData) uid,
	    "<KeyRelease-Alt_L>", "tk::WinMenuKey %W %N", 0);

    (void) Tk_CreateBinding(interp, bindingTable, (ClientData) uid,
	    "<Alt_R>", "tk::WinMenuKey %W %N", 0);

    (void) Tk_CreateBinding(interp, bindingTable, (ClientData) uid,
	    "<KeyRelease-Alt_R>", "tk::WinMenuKey %W %N", 0);

    (void) Tk_CreateBinding(interp, bindingTable, (ClientData) uid,
	    "<Alt-KeyPress>", "tk::WinMenuKey %W %N", 0);
	    "<Alt-Key>", "tk::WinMenuKey %W %N", 0);

    (void) Tk_CreateBinding(interp, bindingTable, (ClientData) uid,
	    "<Alt-KeyRelease>", "tk::WinMenuKey %W %N", 0);

    (void) Tk_CreateBinding(interp, bindingTable, (ClientData) uid,
	    "<KeyPress-F10>", "tk::WinMenuKey %W %N", 0);
	    "<Key-F10>", "tk::WinMenuKey %W %N", 0);

    (void) Tk_CreateBinding(interp, bindingTable, (ClientData) uid,
	    "<KeyRelease-F10>", "tk::WinMenuKey %W %N", 0);
}

/*
 *----------------------------------------------------------------------
2437
2438
2439
2440
2441
2442
2443
2444

2445
2446
2447
2448
2449
2450
2451
2493
2494
2495
2496
2497
2498
2499

2500
2501
2502
2503
2504
2505
2506
2507







-
+







		(int) (y + (mePtr->height - imageHeight)/2 + imageYOffset), 1);
    }
    if ((mePtr->compound != COMPOUND_NONE) || !haveImage) {
    	if (mePtr->labelLength > 0) {
	    int baseline = y + (height + fmPtr->ascent - fmPtr->descent) / 2;
	    const char *label = Tcl_GetString(mePtr->labelPtr);

	    if (TkWinGetPlatformTheme() == TK_THEME_WIN_CLASSIC) {
	    if (TkWinGetPlatformTheme() != TK_THEME_WIN_XP) {
		/*
		 * Win 95/98 systems draw disabled menu text with a 3D
		 * highlight, unless the menu item is highlighted,
		 */

		if ((mePtr->state == ENTRY_DISABLED) &&
			!(mePtr->entryFlags & ENTRY_PLATFORM_FLAG1)) {
2533
2534
2535
2536
2537
2538
2539




2540
2541

2542
2543
2544
2545
2546
2547
2548
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600

2601
2602
2603
2604
2605
2606
2607
2608







+
+
+
+

-
+







    const Tk_FontMetrics *fmPtr,/* The metrics we are drawing with */
    int x, int y,
    int width, int height)
{
    XPoint points[2];
    int segmentWidth, maxX;
    Tk_3DBorder border;
    (void)mePtr;
    (void)gc;
    (void)tkfont;
    (void)fmPtr;

    if (menuPtr->menuType != MASTER_MENU) {
    if (menuPtr->menuType != MAIN_MENU) {
	return;
    }

    points[0].x = x;
    points[0].y = y + height/2;
    points[1].y = points[0].y;
    segmentWidth = 6;
2576
2577
2578
2579
2580
2581
2582
2583

2584
2585
2586
2587
2588
2589
2590
2636
2637
2638
2639
2640
2641
2642

2643
2644
2645
2646
2647
2648
2649
2650







-
+







 *	if any need it.
 *
 *----------------------------------------------------------------------
 */

int
TkpConfigureMenuEntry(
    register TkMenuEntry *mePtr)/* Information about menu entry; may or may
    TkMenuEntry *mePtr)/* Information about menu entry; may or may
				 * not already have values for some fields. */
{
    ScheduleMenuReconfigure(mePtr->menuPtr);
    return TCL_OK;
}

/*
2640
2641
2642
2643
2644
2645
2646
2647

2648
2649
2650
2651
2652
2653
2654
2700
2701
2702
2703
2704
2705
2706

2707
2708
2709
2710
2711
2712
2713
2714







-
+







     * animated menus.  [Bug 1329198]
     */

    if (mePtr->image != NULL) {
	menuDc = TkWinGetDrawableDC(menuPtr->display, menuDrawable, &dcState);

	memDc = CreateCompatibleDC(menuDc);
	oldBitmap = SelectObject(memDc,
	oldBitmap = (HBITMAP)SelectObject(memDc,
    			CreateCompatibleBitmap(menuDc, width, height) );

	memWinDraw.type = TWD_WINDC;
	memWinDraw.winDC.hdc = memDc;
	d = (Drawable)&memWinDraw;
	adjustedX = 0;
	adjustedY = padY;
2904
2905
2906
2907
2908
2909
2910



2911
2912
2913
2914
















2915
2916
2917
2918
2919
2920
2921
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974



2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997







+
+
+

-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    int x,			/* left edge */
    int y,			/* top edge */
    int width,			/* width of rectangle to draw */
    int height)			/* height of rectangle to draw */
{
    if (mePtr->state == ENTRY_ACTIVE
		|| (mePtr->entryFlags & ENTRY_PLATFORM_FLAG1)!=0 ) {
	int relief;
	int activeBorderWidth;

	bgBorder = activeBorder;
    }
    Tk_Fill3DRectangle(menuPtr->tkwin, d, bgBorder, x, y, width, height, 0,
	    TK_RELIEF_FLAT);

	if ((menuPtr->menuType == MENUBAR)
		&& ((menuPtr->postedCascade == NULL)
		|| (menuPtr->postedCascade != mePtr))) {
	    relief = TK_RELIEF_FLAT;
	} else {
	    Tk_GetReliefFromObj(NULL, menuPtr->activeReliefPtr, &relief);
	}
	Tk_GetPixelsFromObj(NULL, menuPtr->tkwin,
		menuPtr->activeBorderWidthPtr, &activeBorderWidth);
	Tk_Fill3DRectangle(menuPtr->tkwin, d, bgBorder, x, y, width, height,
		activeBorderWidth, relief);
    } else {
        Tk_Fill3DRectangle(menuPtr->tkwin, d, bgBorder, x, y, width, height, 0,
                TK_RELIEF_FLAT);
    }
}

/*
 *--------------------------------------------------------------
 *
 * TkpComputeStandardMenuGeometry --
 *
2965
2966
2967
2968
2969
2970
2971
2972

2973
2974
2975
2976
2977
2978
2979
3041
3042
3043
3044
3045
3046
3047

3048
3049
3050
3051
3052
3053
3054
3055







-
+








    menuFont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr);
    Tk_GetFontMetrics(menuFont, &menuMetrics);
    accelSpace = Tk_TextWidth(menuFont, "M", 1);
    Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,
	    menuPtr->activeBorderWidthPtr, &activeBorderWidth);

    for (i = 0; i < menuPtr->numEntries; i++) {
    for (i = 0; i < (int)menuPtr->numEntries; i++) {
	if (menuPtr->entries[i]->fontPtr == NULL) {
	    tkfont = menuFont;
	    fmPtr = &menuMetrics;
	} else {
	    tkfont = Tk_GetFontFromObj(menuPtr->tkwin,
		    menuPtr->entries[i]->fontPtr);
    	    Tk_GetFontMetrics(tkfont, &entryMetrics);
3049
3050
3051
3052
3053
3054
3055
3056

3057
3058
3059
3060
3061
3062
3063
3125
3126
3127
3128
3129
3130
3131

3132
3133
3134
3135
3136
3137
3138
3139







-
+







	    windowHeight = y;
	}
    }

    if (accelWidth != 0) {
	labelWidth += accelSpace;
    }
    for (j = lastColumnBreak; j < menuPtr->numEntries; j++) {
    for (j = lastColumnBreak; j < (int)menuPtr->numEntries; j++) {
	menuPtr->entries[j]->indicatorSpace = indicatorSpace;
	menuPtr->entries[j]->labelWidth = labelWidth;
	menuPtr->entries[j]->width = indicatorSpace + labelWidth
		+ accelWidth + 2 * activeBorderWidth;
	menuPtr->entries[j]->x = x;
	menuPtr->entries[j]->entryFlags |= ENTRY_LAST_COLUMN;
    }
3150
3151
3152
3153
3154
3155
3156
3157

3158
3159
3160
3161
3162
3163
3164
3226
3227
3228
3229
3230
3231
3232

3233
3234
3235
3236
3237
3238
3239
3240







-
+







{
    TkMenuReferences *menuRefPtr;
    TkMenu *menuPtr;

    if ((menuName != NULL) && (menuName[0] != '\0')) {
	menuRefPtr = TkFindMenuReferences(interp, menuName);
	if ((menuRefPtr != NULL) && (menuRefPtr->menuPtr != NULL)) {
	    for (menuPtr = menuRefPtr->menuPtr->masterMenuPtr; menuPtr != NULL;
	    for (menuPtr = menuRefPtr->menuPtr->mainMenuPtr; menuPtr != NULL;
		    menuPtr = menuPtr->nextInstancePtr) {
		if (menuPtr->menuType == MENUBAR) {
		    ScheduleMenuReconfigure(menuPtr);
		}
	    }
	}
    }
3183
3184
3185
3186
3187
3188
3189
3190

3191

3192
3193
3194
3195
3196
3197
3198
3259
3260
3261
3262
3263
3264
3265

3266
3267
3268
3269
3270
3271
3272
3273
3274
3275







-
+

+







 *----------------------------------------------------------------------
 */

HWND
Tk_GetMenuHWND(
    Tk_Window tkwin)
{
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    (void)tkwin;

    TkMenuInit();
    return tsdPtr->embeddedMenuHWND;
}

/*
 *----------------------------------------------------------------------
3208
3209
3210
3211
3212
3213
3214
3215

3216


3217
3218
3219
3220
3221
3222
3223
3285
3286
3287
3288
3289
3290
3291

3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302







-
+

+
+







 *	Menus have to be reinitialized next time.
 *
 *----------------------------------------------------------------------
 */

static void
MenuExitHandler(
    ClientData clientData)	    /* Not used */
    ClientData dummy)	    /* Not used */
{
    (void)dummy;

    UnregisterClassW(MENU_CLASS_NAME, Tk_GetHINSTANCE());
    UnregisterClassW(EMBEDDED_MENU_CLASS_NAME, Tk_GetHINSTANCE());
}

/*
 *----------------------------------------------------------------------
 *
3233
3234
3235
3236
3237
3238
3239
3240

3241
3242

3243

3244
3245
3246
3247
3248
3249
3250
3312
3313
3314
3315
3316
3317
3318

3319
3320

3321
3322
3323
3324
3325
3326
3327
3328
3329
3330







-
+

-
+

+







 *	Menus have to be reinitialized next time.
 *
 *----------------------------------------------------------------------
 */

static void
MenuThreadExitHandler(
    ClientData clientData)	    /* Not used */
    ClientData dummy)	    /* Not used */
{
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    (void)dummy;

    DestroyWindow(tsdPtr->menuHWND);
    DestroyWindow(tsdPtr->embeddedMenuHWND);
    tsdPtr->menuHWND = NULL;
    tsdPtr->embeddedMenuHWND = NULL;

    Tcl_DeleteHashTable(&tsdPtr->winMenuTable);
3273
3274
3275
3276
3277
3278
3279


3280
3281
3282
3283

3284
3285
3286
3287
3288
3289
3290
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364

3365
3366
3367
3368
3369
3370
3371
3372







+
+



-
+







Tcl_Obj *
TkWinGetMenuSystemDefault(
    Tk_Window tkwin,		/* A window to use. */
    const char *dbName,		/* The option database name. */
    const char *className)	/* The name of the option class. */
{
    Tcl_Obj *valuePtr = NULL;
    (void)tkwin;
    (void)className;

    if ((strcmp(dbName, "activeBorderWidth") == 0) ||
	    (strcmp(dbName, "borderWidth") == 0)) {
	valuePtr = Tcl_NewIntObj(defaultBorderWidth);
	valuePtr = Tcl_NewWideIntObj(defaultBorderWidth);
    } else if (strcmp(dbName, "font") == 0) {
	valuePtr = Tcl_NewStringObj(Tcl_DStringValue(&menuFontDString), -1);
    }

    return valuePtr;
}

3315
3316
3317
3318
3319
3320
3321
3322
3323

3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346

3347
3348
3349
3350
3351


3352
3353
3354
3355
3356



3357
3358
3359
3360
3361
3362
3363
3397
3398
3399
3400
3401
3402
3403


3404





3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421

3422
3423




3424
3425
3426
3427



3428
3429
3430
3431
3432
3433
3434
3435
3436
3437







-
-
+
-
-
-
-
-

















-
+

-
-
-
-
+
+


-
-
-
+
+
+







    HDC scratchDC;
    int bold = 0;
    int italic = 0;
    TEXTMETRICW tm;
    int pointSize;
    HFONT menuFont;
    /* See: [Bug #3239768] tk8.4.19 (and later) WIN32 menu font support */
    struct {
        NONCLIENTMETRICSW metrics;
    NONCLIENTMETRICSW metrics;
#if (WINVER < 0x0600)
        int padding;
#endif
    } nc;
    OSVERSIONINFOW os;

    /*
     * Set all of the default options. The loop will terminate when we run out
     * of options via a break statement.
     */

    defaultBorderWidth = GetSystemMetrics(SM_CXBORDER);
    if (GetSystemMetrics(SM_CYBORDER) > defaultBorderWidth) {
	defaultBorderWidth = GetSystemMetrics(SM_CYBORDER);
    }

    scratchDC = CreateDCW(L"DISPLAY", NULL, NULL, NULL);
    if (!firstTime) {
	Tcl_DStringFree(&menuFontDString);
    }
    Tcl_DStringInit(&menuFontDString);

    nc.metrics.cbSize = sizeof(nc);
    metrics.cbSize = sizeof(metrics);

    os.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
    GetVersionExW(&os);
    if (os.dwMajorVersion < 6) {
	nc.metrics.cbSize -= sizeof(int);
    if (TkWinGetPlatformTheme() != TK_THEME_WIN_VISTA) {
	metrics.cbSize -= sizeof(int);
    }

    SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, nc.metrics.cbSize,
	    &nc.metrics, 0);
    menuFont = CreateFontIndirectW(&nc.metrics.lfMenuFont);
    SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, metrics.cbSize,
	    &metrics, 0);
    menuFont = CreateFontIndirectW(&metrics.lfMenuFont);
    SelectObject(scratchDC, menuFont);
    GetTextMetricsW(scratchDC, &tm);
    GetTextFaceA(scratchDC, LF_FACESIZE, faceName);
    pointSize = MulDiv(tm.tmHeight - tm.tmInternalLeading,
	    72, GetDeviceCaps(scratchDC, LOGPIXELSY));
    if (tm.tmWeight >= 700) {
	bold = 1;
3476
3477
3478
3479
3480
3481
3482
3483

3484
3485
3486
3487
3488
3489
3490
3550
3551
3552
3553
3554
3555
3556

3557
3558
3559
3560
3561
3562
3563
3564







-
+







 *
 *----------------------------------------------------------------------
 */

void
TkpMenuThreadInit(void)
{
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    tsdPtr->menuHWND = CreateWindowW(MENU_CLASS_NAME, L"MenuWindow", WS_POPUP,
	    0, 0, 10, 10, NULL, NULL, Tk_GetHINSTANCE(), NULL);

    if (!tsdPtr->menuHWND) {
	Tcl_Panic("Failed to create the menu window");
Changes to win/tkWinPixmap.c.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







/*
 * tkWinPixmap.c --
 *
 *	This file contains the Xlib emulation functions pertaining to creating
 *	and destroying pixmaps.
 *
 * 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.
 */

#include "tkWinInt.h"

38
39
40
41
42
43
44
45

46
47
48
49
50
51
52
38
39
40
41
42
43
44

45
46
47
48
49
50
51
52







-
+







{
    TkWinDrawable *newTwdPtr, *twdPtr;
    int planes;
    Screen *screen;

    display->request++;

    newTwdPtr = ckalloc(sizeof(TkWinDrawable));
    newTwdPtr = (TkWinDrawable *)ckalloc(sizeof(TkWinDrawable));
    newTwdPtr->type = TWD_BITMAP;
    newTwdPtr->bitmap.depth = depth;
    twdPtr = (TkWinDrawable *) d;
    if (twdPtr->type != TWD_BITMAP) {
	if (twdPtr->window.winPtr == NULL) {
	    newTwdPtr->bitmap.colormap = DefaultColormap(display,
		    DefaultScreen(display));
204
205
206
207
208
209
210






211
212
213
214
215
216
217
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223







+
+
+
+
+
+







    int *y_return,
    unsigned int *width_return,
    unsigned int *height_return,
    unsigned int *border_width_return,
    unsigned int *depth_return)
{
    TkWinDrawable *twdPtr = (TkWinDrawable *)d;
    (void)display;
    (void)root_return;
    (void)x_return;
    (void)y_return;
    (void)border_width_return;
    (void)depth_return;

    if (twdPtr->type == TWD_BITMAP) {
	HDC dc;
	BITMAPINFO info;

	if (twdPtr->bitmap.handle == NULL) {
	    Tcl_Panic("XGetGeometry: invalid pixmap");
Changes to win/tkWinPointer.c.
1
2
3
4
5
6
7


8
9
10
11
12
13
14
1
2
3
4
5


6
7
8
9
10
11
12
13
14





-
-
+
+







/*
 * tkWinPointer.c --
 *
 *	Windows specific mouse tracking code.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 * Copyright © 1995-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 "tkWinInt.h"

89
90
91
92
93
94
95
96

97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112

113
114
115
116
117
118
119
89
90
91
92
93
94
95

96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111

112
113
114
115
116
117
118
119







-
+















-
+







    }
    return state;
}

/*
 *----------------------------------------------------------------------
 *
 * Tk_PointerEvent --
 * TkWinPointerEvent --
 *
 *	This procedure is called for each pointer-related event. It converts
 *	the position to root coords and updates the global pointer state
 *	machine. It also ensures that the mouse timer is scheduled.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	May queue events and change the grab state.
 *
 *----------------------------------------------------------------------
 */

void
Tk_PointerEvent(
TkWinPointerEvent(
    HWND hwnd,			/* Window for coords, or NULL for the root
				 * window. */
    int x, int y)		/* Coords relative to hwnd, or screen if hwnd
				 * is NULL. */
{
    POINT pos;
    int state;
175
176
177
178
179
180
181






182
183
184
185
186
187
188
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194







+
+
+
+
+
+







    Display *display,
    Window grab_window,
    Bool owner_events,
    int pointer_mode,
    int keyboard_mode,
    Time time)
{
    (void)display;
    (void)owner_events;
    (void)pointer_mode;
    (void)keyboard_mode;
    (void)time;

    keyboardWinPtr = TkWinGetWinPtr(grab_window);
    return GrabSuccess;
}

/*
 *----------------------------------------------------------------------
 *
200
201
202
203
204
205
206



207
208
209
210
211
212
213
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222







+
+
+







 */

int
XUngrabKeyboard(
    Display *display,
    Time time)
{
    (void)display;
    (void)time;

    keyboardWinPtr = NULL;
    return Success;
}

/*
 *----------------------------------------------------------------------
 *
222
223
224
225
226
227
228
229

230
231

232
233
234
235
236
237
238
239
240
241

242
243
244
245
246
247
248
231
232
233
234
235
236
237

238
239
240
241
242
243
244
245
246
247
248
249
250

251
252
253
254
255
256
257
258







-
+


+









-
+







 *	May schedule a new timer and/or generate enter/leave events.
 *
 *----------------------------------------------------------------------
 */

void
MouseTimerProc(
    ClientData clientData)
    ClientData dummy)
{
    POINT pos;
    (void)dummy;

    mouseTimerSet = 0;

    /*
     * Get the current mouse position and window. Don't do anything if the
     * mouse hasn't moved since the last time we looked.
     */

    GetCursorPos(&pos);
    Tk_PointerEvent(NULL, pos.x, pos.y);
    TkWinPointerEvent(NULL, pos.x, pos.y);
}

/*
 *----------------------------------------------------------------------
 *
 * TkWinCancelMouseTimer --
 *
286
287
288
289
290
291
292

293
294
295
296
297
298
299
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310







+







void
TkGetPointerCoords(
    Tk_Window tkwin,		/* Window that identifies screen on which
				 * lookup is to be done. */
    int *xPtr, int *yPtr)	/* Store pointer coordinates here. */
{
    POINT point;
    (void)tkwin;

    GetCursorPos(&point);
    *xPtr = point.x;
    *yPtr = point.y;
}

/*
323
324
325
326
327
328
329






330
331
332
333
334
335
336
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353







+
+
+
+
+
+







    Window *child_return,
    int *root_x_return,
    int *root_y_return,
    int *win_x_return,
    int *win_y_return,
    unsigned int *mask_return)
{
    (void)w;
    (void)root_return;
    (void)child_return;
    (void)win_x_return;
    (void)win_y_return;

    display->request++;
    TkGetPointerCoords(NULL, root_x_return, root_y_return);
    *mask_return = TkWinGetModifierState();
    return True;
}

/*
397
398
399
400
401
402
403






404
405
406
407
408
409
410
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433







+
+
+
+
+
+







    int src_y,
    unsigned int src_width,
    unsigned int src_height,
    int dest_x,
    int dest_y)
{
    RECT r;
    (void)display;
    (void)src_w;
    (void)src_x;
    (void)src_y;
    (void)src_width;
    (void)src_height;

    GetWindowRect(Tk_GetHWND(dest_w), &r);
    TkSetCursorPos(r.left+dest_x, r.top+dest_y);
    return Success;
}

void
441
442
443
444
445
446
447
448

449
450
451
452
453
454
455
464
465
466
467
468
469
470

471
472
473
474
475
476
477
478







-
+







XGetInputFocus(
    Display *display,
    Window *focus_return,
    int *revert_to_return)
{
    Tk_Window tkwin = Tk_HWNDToWindow(GetFocus());

    *focus_return = tkwin ? Tk_WindowId(tkwin) : None;
    *focus_return = tkwin ? Tk_WindowId(tkwin) : 0;
    *revert_to_return = RevertToParent;
    display->request++;
    return Success;
}

/*
 *----------------------------------------------------------------------
471
472
473
474
475
476
477



478
479
480
481
482
483
484
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510







+
+
+







int
XSetInputFocus(
    Display *display,
    Window focus,
    int revert_to,
    Time time)
{
    (void)revert_to;
    (void)time;

    display->request++;
    if (focus != None) {
	SetFocus(Tk_GetHWND(focus));
    }
    return Success;
}

Changes to win/tkWinPort.h.
17
18
19
20
21
22
23

24
25
26
27
28
29
30
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31







+







/*
 *---------------------------------------------------------------------------
 * The following sets of #includes and #ifdefs are required to get Tcl to
 * compile under the windows compilers.
 *---------------------------------------------------------------------------
 */

#include <stdio.h>
#include <wchar.h>
#include <io.h>
#include <stdlib.h>
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <malloc.h>
60
61
62
63
64
65
66



67
68
69
70
71
72
73
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77







+
+
+







#   define _TCHAR_DEFINED
#endif
#if defined(_MSC_VER) && defined(__STDC__)
    /* VS2005 SP1 misses this. See [Bug #3110161] */
    typedef _TCHAR TCHAR;
#endif

#if defined(__GNUC__) && !defined(__cplusplus)
#   pragma GCC diagnostic ignored "-Wc++-compat"
#endif
#include <X11/Xlib.h>
#include <X11/cursorfont.h>
#include <X11/keysym.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>

#ifndef __GNUC__
87
88
89
90
91
92
93

94
95
96
97
98



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118






119
120
121
122
123
124
125
126
127
128
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142







+





+
+
+




















+
+
+
+
+
+











#define REDO_KEYSYM_LOOKUP

/*
 * See ticket [916c1095438eae56]: GetVersionExW triggers warnings
 */
#if defined(_MSC_VER)
#   pragma warning(disable:4146)
#   pragma warning(disable:4267)
#   pragma warning(disable:4244)
#   pragma warning(disable:4311)
#   pragma warning(disable:4312)
#   pragma warning(disable:4996)
#if !defined(_WIN64)
#   pragma warning(disable:4305)
#endif
#endif

/*
 * The following macro checks to see whether there is buffered
 * input data available for a stdio FILE.
 */

#ifdef _MSC_VER
#    define TK_READ_DATA_PENDING(f) ((f)->_cnt > 0)
#else /* _MSC_VER */
#    define TK_READ_DATA_PENDING(f) ((f)->level > 0)
#endif /* _MSC_VER */

/*
 * The following Tk functions are implemented as macros under Windows.
 */

#define TkpGetPixel(p) (((((p)->red >> 8) & 0xff) \
	| ((p)->green & 0xff00) | (((p)->blue << 8) & 0xff0000)) | 0x20000000)

/*
 * Used by tkWindow.c
 */

#define TkpHandleMapOrUnmap(tkwin, event)  Tk_HandleEvent(event)

/*
 * These calls implement native bitmaps which are not currently
 * supported under Windows.  The macros eliminate the calls.
 */

#define TkpDefineNativeBitmaps()
#define TkpCreateNativeBitmap(display, source) None
#define TkpGetNativeAppBitmap(display, name, w, h) None

#endif /* _WINPORT */
Changes to win/tkWinRegion.c.
1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
1
2
3
4
5

6
7
8
9
10
11
12
13







14
15
16
17
18
19
20





-
+







-
-
-
-
-
-
-







/*
 * tkWinRegion.c --
 *
 *	Tk Region emulation code.
 *
 * 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.
 */

#include "tkWinInt.h"

#undef TkCreateRegion
#undef TkDestroyRegion
#undef TkClipBox
#undef TkIntersectRegion
#undef TkUnionRectWithRegion
#undef TkRectInRegion
#undef TkSubtractRegion

/*
 *----------------------------------------------------------------------
 *
 * TkCreateRegion --
 *
 *	Construct an empty region.
Changes to win/tkWinScrlbr.c.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







/*
 * tkWinScrollbar.c --
 *
 *	This file implements the Windows specific portion of 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.
 */

#include "tkWinInt.h"
#include "tkScrollbar.h"
78
79
80
81
82
83
84
85

86
87
88
89
90
91
92
78
79
80
81
82
83
84

85
86
87
88
89
90
91
92







-
+







    CreateProc,			/* createProc */
    NULL 			/* modalProc */
};

static void
WinScrollbarEventProc(ClientData clientData, XEvent *eventPtr)
{
    WinScrollbar *scrollPtr = clientData;
    WinScrollbar *scrollPtr = (WinScrollbar *)clientData;

    if (eventPtr->type == ButtonPress) {
	ModalLoop(scrollPtr, eventPtr);
    } else {
	TkScrollbarEventProc(clientData, eventPtr);
    }
}
117
118
119
120
121
122
123
124

125
126
127
128
129
130
131
117
118
119
120
121
122
123

124
125
126
127
128
129
130
131







-
+







    if (!initialized) {
	Tcl_MutexLock(&winScrlbrMutex);
	UpdateScrollbarMetrics();
	initialized = 1;
	Tcl_MutexUnlock(&winScrlbrMutex);
    }

    scrollPtr = ckalloc(sizeof(WinScrollbar));
    scrollPtr = (WinScrollbar *)ckalloc(sizeof(WinScrollbar));
    scrollPtr->winFlags = 0;
    scrollPtr->hwnd = NULL;

    Tk_CreateEventHandler(tkwin,
	    ExposureMask|StructureNotifyMask|FocusChangeMask|ButtonPressMask,
	    WinScrollbarEventProc, scrollPtr);

271
272
273
274
275
276
277
278

279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298

299
300
301
302
303
304
305
271
272
273
274
275
276
277

278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297

298
299
300
301
302
303
304
305







-
+



















-
+







 *--------------------------------------------------------------
 */

void
TkpDisplayScrollbar(
    ClientData clientData)	/* Information about window. */
{
    WinScrollbar *scrollPtr = (WinScrollbar *) clientData;
    WinScrollbar *scrollPtr = (WinScrollbar *)clientData;
    Tk_Window tkwin = scrollPtr->info.tkwin;

    scrollPtr->info.flags &= ~REDRAW_PENDING;
    if ((tkwin == NULL) || !Tk_IsMapped(tkwin)) {
	return;
    }

    /*
     * Destroy and recreate the scrollbar control if the orientation has
     * changed.
     */

    if (scrollPtr->lastVertical != scrollPtr->info.vertical) {
	HWND hwnd = Tk_GetHWND(Tk_WindowId(tkwin));

	SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONG_PTR) scrollPtr->oldProc);
	DestroyWindow(hwnd);

	CreateProc(tkwin, Tk_WindowId(Tk_Parent(tkwin)),
		(ClientData) scrollPtr);
		scrollPtr);
    } else {
	UpdateScrollbar(scrollPtr);
    }
}

/*
 *----------------------------------------------------------------------
379
380
381
382
383
384
385
386

387
388
389
390
391
392
393
379
380
381
382
383
384
385

386
387
388
389
390
391
392
393







-
+







 *	The scrollbar will be displayed differently.
 *
 *----------------------------------------------------------------------
 */

void
TkpComputeScrollbarGeometry(
    register TkScrollbar *scrollPtr)
    TkScrollbar *scrollPtr)
				/* Scrollbar whose geometry may have
				 * changed. */
{
    int fieldLength, minThumbSize;

    /*
     * Windows doesn't use focus rings on scrollbars, but we still perform
493
494
495
496
497
498
499
500

501
502
503
504
505
506
507
493
494
495
496
497
498
499

500
501
502
503
504
505
506
507







-
+







    case WM_VSCROLL: {
	Tcl_Interp *interp;
	Tcl_DString cmdString;
	int command = LOWORD(wParam);
	int code;

	GetCursorPos(&point);
	Tk_TranslateWinEvent(NULL, WM_MOUSEMOVE, 0,
	TkTranslateWinEvent(NULL, WM_MOUSEMOVE, 0,
		MAKELPARAM(point.x, point.y), &result);

	if (command == SB_ENDSCROLL) {
	    return 0;
	}

	/*
560
561
562
563
564
565
566
567

568
569
570
571
572
573
574
560
561
562
563
564
565
566

567
568
569
570
571
572
573
574







-
+







	Tcl_DStringFree(&cmdString);

	Tcl_ServiceAll();
	return 0;
    }

    default:
	if (Tk_TranslateWinEvent(hwnd, message, wParam, lParam, &result)) {
	if (TkTranslateWinEvent(hwnd, message, wParam, lParam, &result)) {
	    return result;
	}
    }
    return CallWindowProcW(scrollPtr->oldProc, hwnd, message, wParam, lParam);
}

/*
587
588
589
590
591
592
593
594

595
596
597

598
599
600
601
602
603
604
587
588
589
590
591
592
593

594
595
596
597
598
599
600
601
602
603
604
605







-
+



+







 *	None.
 *
 *----------------------------------------------------------------------
 */

void
TkpConfigureScrollbar(
    register TkScrollbar *scrollPtr)
    TkScrollbar *scrollPtr)
				/* Information about widget; may or may not
				 * already have values for some fields. */
{
    (void)scrollPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * ModalLoop --
 *
613
614
615
616
617
618
619
620

621
622
623
624
625
626
627
628
629

630
631
632
633
634
635
636
614
615
616
617
618
619
620

621
622
623
624
625
626
627
628
629

630
631
632
633
634
635
636
637







-
+








-
+







ModalLoop(
    WinScrollbar *scrollPtr,
    XEvent *eventPtr)
{
    int oldMode;

    if (scrollPtr->hwnd) {
	Tcl_Preserve((ClientData)scrollPtr);
	Tcl_Preserve(scrollPtr);
	scrollPtr->winFlags |= IN_MODAL_LOOP;
	oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
	TkWinResendEvent(scrollPtr->oldProc, scrollPtr->hwnd, eventPtr);
	(void) Tcl_SetServiceMode(oldMode);
	scrollPtr->winFlags &= ~IN_MODAL_LOOP;
	if (scrollPtr->hwnd && scrollPtr->winFlags & ALREADY_DEAD) {
	    DestroyWindow(scrollPtr->hwnd);
	}
	Tcl_Release((ClientData)scrollPtr);
	Tcl_Release(scrollPtr);
    }
}

/*
 *--------------------------------------------------------------
 *
 * TkpScrollbarPosition --
646
647
648
649
650
651
652
653

654
655
656
657
658
659
660
647
648
649
650
651
652
653

654
655
656
657
658
659
660
661







-
+







 *	None.
 *
 *--------------------------------------------------------------
 */

int
TkpScrollbarPosition(
    register TkScrollbar *scrollPtr,
    TkScrollbar *scrollPtr,
				/* Scrollbar widget record. */
    int x, int y)		/* Coordinates within scrollPtr's window. */
{
    int length, width, tmp;

    if (scrollPtr->vertical) {
	length = Tk_Height(scrollPtr->tkwin);
Changes to win/tkWinSend.c.
1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15






-
-
+
+







/*
 * tkWinSend.c --
 *
 *	This file provides functions that implement the "send" command,
 *	allowing commands to be passed from interpreter to interpreter.
 *
 * Copyright (c) 1997 by Sun Microsystems, Inc.
 * Copyright (c) 2003 Pat Thoyts <[email protected]>
 * Copyright © 1997 Sun Microsystems, Inc.
 * Copyright © 2003 Pat Thoyts <[email protected]>
 *
 * 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 "tkWinSendCom.h"
117
118
119
120
121
122
123


124
125
126
127
128
129
130
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132







+
+







				 * be named: it is just used to identify the
				 * application and the display.  */
    const char *name)		/* The name that will be used to refer to the
				 * interpreter in later "send" commands. Must
				 * be globally unique. */
{
#ifndef TK_SEND_ENABLED_ON_WINDOWS
    (void)tkwin;

    /*
     * Temporarily disabled for bug #858822
     */

    return name;
#else /* TK_SEND_ENABLED_ON_WINDOWS */

159
160
161
162
163
164
165
166

167
168
169
170
171
172
173
161
162
163
164
165
166
167

168
169
170
171
172
173
174
175







-
+







     * already then we can reuse all and just register the new name.
     */

    riPtr = Tcl_GetAssocData(interp, "tkWinSend::ri", NULL);
    if (riPtr == NULL) {
	LPUNKNOWN *objPtr;

	riPtr = ckalloc(sizeof(RegisteredInterp));
	riPtr = (RegisteredInterp *)ckalloc(sizeof(RegisteredInterp));
	memset(riPtr, 0, sizeof(RegisteredInterp));
	riPtr->interp = interp;

	objPtr = &riPtr->obj;
	hr = TkWinSendCom_CreateInstance(interp, &IID_IUnknown,
		(void **) objPtr);

209
210
211
212
213
214
215


216
217
218
219
220
221
222
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226







+
+







int
TkGetInterpNames(
    Tcl_Interp *interp,		/* Interpreter for returning a result. */
    Tk_Window tkwin)		/* Window whose display is to be used for the
				 * lookup. */
{
#ifndef TK_SEND_ENABLED_ON_WINDOWS
    (void)interp;
    (void)tkwin;
    /*
     * Temporarily disabled for bug #858822
     */

    return TCL_OK;
#else /* TK_SEND_ENABLED_ON_WINDOWS */

250
251
252
253
254
255
256

257

258
259
260
261
262
263
264
254
255
256
257
258
259
260
261

262
263
264
265
266
267
268
269







+
-
+







			if (wcsncmp(olestr, oleszStub,
				wcslen(oleszStub)) == 0) {
			    LPOLESTR p = olestr + wcslen(oleszStub);

			    if (*p) {
				Tcl_DString ds;

				Tcl_DStringInit(&ds);
				Tcl_WinTCharToUtf((LPCTSTR)(p + 1), -1, &ds);
				Tcl_WCharToUtfDString(p + 1, wcslen(p + 1), &ds);
				result = Tcl_ListObjAppendElement(interp,
					objList,
					Tcl_NewStringObj(Tcl_DStringValue(&ds),
						Tcl_DStringLength(&ds)));
				Tcl_DStringFree(&ds);
			    }
			}
615
616
617
618
619
620
621

622

623
624
625
626
627
628
629
620
621
622
623
624
625
626
627

628
629
630
631
632
633
634
635







+
-
+







    LPMONIKER pmkClass = NULL;
    HRESULT hr = CreateFileMoniker(TKWINSEND_REGISTRATION_BASE, &pmkClass);

    if (SUCCEEDED(hr)) {
	LPMONIKER pmkItem = NULL;
	Tcl_DString dString;

	Tcl_DStringInit(&dString);
	Tcl_WinUtfToTChar(name, -1, &dString);
	Tcl_UtfToWCharDString(name, -1, &dString);
	hr = CreateFileMoniker((LPOLESTR)Tcl_DStringValue(&dString), &pmkItem);
	Tcl_DStringFree(&dString);
	if (SUCCEEDED(hr)) {
	    hr = pmkClass->lpVtbl->ComposeWith(pmkClass, pmkItem, FALSE, ppmk);
	    pmkItem->lpVtbl->Release(pmkItem);
	}
	pmkClass->lpVtbl->Release(pmkClass);
729
730
731
732
733
734
735
736

737
738
739
740
741
742
743
744
745
746
747
748
749

750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765


766
767
768
769
770
771
772
735
736
737
738
739
740
741

742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770


771
772
773
774
775
776
777
778
779







-
+













+














-
-
+
+








static int
Send(
    LPDISPATCH pdispInterp,	/* Pointer to the remote interp's COM
				 * object. */
    Tcl_Interp *interp,		/* The local interpreter. */
    int async,			/* Flag for the calling style. */
    ClientData clientData,	/* The RegisteredInterp structure for this
    ClientData dummy,	/* The RegisteredInterp structure for this
				 * interp. */
    int objc,			/* Number of arguments to be sent. */
    Tcl_Obj *const objv[])	/* The arguments to be sent. */
{
    VARIANT vCmd, vResult;
    DISPPARAMS dp;
    EXCEPINFO ei;
    UINT uiErr = 0;
    HRESULT hr = S_OK, ehr = S_OK;
    Tcl_Obj *cmd = NULL;
    DISPID dispid;
    Tcl_DString ds;
    const char *src;
    (void)dummy;

    cmd = Tcl_ConcatObj(objc, objv);

    /*
     * Setup the arguments for the COM method call.
     */

    VariantInit(&vCmd);
    VariantInit(&vResult);
    memset(&dp, 0, sizeof(dp));
    memset(&ei, 0, sizeof(ei));

    vCmd.vt = VT_BSTR;
    src = Tcl_GetString(cmd);
    Tcl_WinUtfToTChar(src, cmd->length, &ds);
    vCmd.bstrVal = SysAllocString((WCHAR *) Tcl_DStringValue(&ds));
    Tcl_DStringInit(&ds);
    vCmd.bstrVal = SysAllocString(Tcl_UtfToWCharDString(src, cmd->length, &ds));
    Tcl_DStringFree(&ds);

    dp.cArgs = 1;
    dp.rgvarg = &vCmd;

    /*
     * Select the method to use based upon the async flag and call the method.
780
781
782
783
784
785
786

787

788
789
790
791
792
793
794
795
796
797
798
799


800

801
802
803
804
805
806
807
808
787
788
789
790
791
792
793
794

795

796
797
798
799
800
801
802
803
804
805
806
807
808

809

810
811
812
813
814
815
816







+
-
+
-











+
+
-
+
-








    /*
     * Convert the result into a string and place in the interps result.
     */

    ehr = VariantChangeType(&vResult, &vResult, 0, VT_BSTR);
    if (SUCCEEDED(ehr)) {
	Tcl_DStringInit(&ds);
	Tcl_WinTCharToUtf((LPCTSTR)vResult.bstrVal, SysStringLen(vResult.bstrVal) *
	Tcl_WCharToUtfDString(vResult.bstrVal, SysStringLen(vResult.bstrVal), &ds);
		sizeof (WCHAR), &ds);
	Tcl_DStringResult(interp, &ds);
    }

    /*
     * Errors are returned as dispatch exceptions. If an error code was
     * returned then we decode the exception and setup the Tcl error
     * variables.
     */

    if (hr == DISP_E_EXCEPTION && ei.bstrSource != NULL) {
	Tcl_Obj *opError, *opErrorCode, *opErrorInfo;

	Tcl_DStringInit(&ds);
	Tcl_WinTCharToUtf((LPCTSTR)ei.bstrSource, SysStringLen(ei.bstrSource) *
	Tcl_WCharToUtfDString(ei.bstrSource, SysStringLen(ei.bstrSource), &ds);
		sizeof (WCHAR), &ds);
	opError = Tcl_NewStringObj(Tcl_DStringValue(&ds),
		Tcl_DStringLength(&ds));
	Tcl_DStringFree(&ds);
	Tcl_ListObjIndex(interp, opError, 0, &opErrorCode);
	Tcl_SetObjErrorCode(interp, opErrorCode);
	Tcl_ListObjIndex(interp, opError, 1, &opErrorInfo);
	Tcl_AppendObjToErrorInfo(interp, opErrorInfo);
865
866
867
868
869
870
871
872

873
874

875
876
877

878
879

880
881
882
883
884
885
886
873
874
875
876
877
878
879

880
881

882
883
884

885
886

887
888
889
890
891
892
893
894







-
+

-
+


-
+

-
+








    opErrorCode = Tcl_DuplicateObj(opErrorCode);
    Tcl_IncrRefCount(opErrorCode);
    Tcl_ListObjAppendElement(interp, opErrorCode, opErrorInfo);
    /* TODO: Handle failure to append */

    src = Tcl_GetString(opError);
    Tcl_WinUtfToTChar(src, opError->length, &ds);
    Tcl_DStringInit(&ds);
    pExcepInfo->bstrDescription =
	    SysAllocString((WCHAR *) Tcl_DStringValue(&ds));
	    SysAllocString(Tcl_UtfToWCharDString(src, opError->length, &ds));
    Tcl_DStringFree(&ds);
    src = Tcl_GetString(opErrorCode);
    Tcl_WinUtfToTChar(src, opErrorCode->length, &ds);
    Tcl_DStringInit(&ds);
    pExcepInfo->bstrSource =
	    SysAllocString((WCHAR *) Tcl_DStringValue(&ds));
	    SysAllocString(Tcl_UtfToWCharDString(src, opErrorCode->length, &ds));
    Tcl_DStringFree(&ds);
    Tcl_DecrRefCount(opErrorCode);
    pExcepInfo->scode = E_FAIL;

    hr = CreateErrorInfo(&pCEI);
    if (!SUCCEEDED(hr)) {
	return;
919
920
921
922
923
924
925
926

927
928
929
930
931
932
933
927
928
929
930
931
932
933

934
935
936
937
938
939
940
941







-
+







    Tcl_Interp *interp,
    Tcl_Obj *cmdPtr)
{
    SendEvent *evPtr;

    TRACE("SendQueueCommand()\n");

    evPtr = ckalloc(sizeof(SendEvent));
    evPtr = (SendEvent *)ckalloc(sizeof(SendEvent));
    evPtr->header.proc = SendEventProc;
    evPtr->header.nextPtr = NULL;
    evPtr->interp = interp;
    Tcl_Preserve(evPtr->interp);

    if (Tcl_IsShared(cmdPtr)) {
	evPtr->cmdPtr = Tcl_DuplicateObj(cmdPtr);
961
962
963
964
965
966
967

968
969
970
971
972
973
974
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983







+








static int
SendEventProc(
    Tcl_Event *eventPtr,
    int flags)
{
    SendEvent *evPtr = (SendEvent *)eventPtr;
    (void)flags;

    TRACE("SendEventProc\n");

    Tcl_EvalObjEx(evPtr->interp, evPtr->cmdPtr,
	    TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL);

    Tcl_DecrRefCount(evPtr->cmdPtr);
Changes to win/tkWinSendCom.c.
9
10
11
12
13
14
15
16

17
18
19
20
21
22
23
9
10
11
12
13
14
15

16
17
18
19
20
21
22
23







-
+







 * We implement a COM class for use in registering Tcl interpreters with the
 * system's Running Object Table. This class implements an IDispatch interface
 * with the following method:
 *	Send(String cmd) As String
 * In other words the Send methods takes a string and evaluates this in the
 * Tcl interpreter. The result is returned as another string.
 *
 * Copyright (C) 2002 Pat Thoyts <[email protected]>
 * Copyright © 2002 Pat Thoyts <[email protected]>
 *
 * 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 "tkWinSendCom.h"
162
163
164
165
166
167
168
169

170
171
172
173
174
175


176
177
178
179


180
181
182
183
184
185
186
187
188
189

190
191

192
193
194
195
196
197
198
199

200
201

202
203
204
205
206
207
208
209
210
211
212

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228



229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246




247
248
249
250
251
252
253
162
163
164
165
166
167
168

169
170
171
172
173


174
175
176
177


178
179
180
181
182
183
184
185
186
187
188

189
190

191
192
193
194
195
196
197
198

199
200

201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261







-
+




-
-
+
+


-
-
+
+









-
+

-
+







-
+

-
+











+
















+
+
+


















+
+
+
+







static STDMETHODIMP
WinSendCom_QueryInterface(
    IDispatch *This,
    REFIID riid,
    void **ppvObject)
{
    HRESULT hr = E_NOINTERFACE;
    TkWinSendCom *this = (TkWinSendCom *) This;
    TkWinSendCom *sendCom = (TkWinSendCom *) This;
    *ppvObject = NULL;

    if (memcmp(riid, &IID_IUnknown, sizeof(IID)) == 0
	    || memcmp(riid, &IID_IDispatch, sizeof(IID)) == 0) {
	*ppvObject = (void **) this;
	this->lpVtbl->AddRef(This);
	*ppvObject = (void **) sendCom;
	sendCom->lpVtbl->AddRef(This);
	hr = S_OK;
    } else if (memcmp(riid, &IID_ISupportErrorInfo, sizeof(IID)) == 0) {
	*ppvObject = (void **) (this + 1);
	this->lpVtbl2->AddRef((ISupportErrorInfo *) (this + 1));
	*ppvObject = (void **) (sendCom + 1);
	sendCom->lpVtbl2->AddRef((ISupportErrorInfo *) (sendCom + 1));
	hr = S_OK;
    }
    return hr;
}

static STDMETHODIMP_(ULONG)
WinSendCom_AddRef(
    IDispatch *This)
{
    TkWinSendCom *this = (TkWinSendCom*)This;
    TkWinSendCom *sendCom = (TkWinSendCom*)This;

    return InterlockedIncrement(&this->refcount);
    return InterlockedIncrement(&sendCom->refcount);
}

static STDMETHODIMP_(ULONG)
WinSendCom_Release(
    IDispatch *This)
{
    long r = 0;
    TkWinSendCom *this = (TkWinSendCom*)This;
    TkWinSendCom *sendCom = (TkWinSendCom*)This;

    if ((r = InterlockedDecrement(&this->refcount)) == 0) {
    if ((r = InterlockedDecrement(&sendCom->refcount)) == 0) {
	TkWinSendCom_Destroy(This);
    }
    return r;
}

static STDMETHODIMP
WinSendCom_GetTypeInfoCount(
    IDispatch *This,
    UINT *pctinfo)
{
    HRESULT hr = E_POINTER;
    (void)This;

    if (pctinfo != NULL) {
	*pctinfo = 0;
	hr = S_OK;
    }
    return hr;
}

static STDMETHODIMP
WinSendCom_GetTypeInfo(
    IDispatch *This,
    UINT iTInfo,
    LCID lcid,
    ITypeInfo **ppTI)
{
    HRESULT hr = E_POINTER;
    (void)This;
    (void)iTInfo;
    (void)lcid;

    if (ppTI) {
	*ppTI = NULL;
	hr = E_NOTIMPL;
    }
    return hr;
}

static STDMETHODIMP
WinSendCom_GetIDsOfNames(
    IDispatch *This,
    REFIID riid,
    LPOLESTR *rgszNames,
    UINT cNames,
    LCID lcid,
    DISPID *rgDispId)
{
    HRESULT hr = E_POINTER;
    (void)This;
    (void)riid;
    (void)cNames;
    (void)lcid;

    if (rgDispId) {
	hr = DISP_E_UNKNOWNNAME;
	if (_wcsicmp(*rgszNames, L"Send") == 0) {
	    *rgDispId = TKWINSENDCOM_DISPID_SEND, hr = S_OK;
	} else if (_wcsicmp(*rgszNames, L"Async") == 0) {
	    *rgDispId = TKWINSENDCOM_DISPID_ASYNC, hr = S_OK;
265
266
267
268
269
270
271
272



273
274
275
276
277
278
279
280

281
282
283
284
285
286
287
288
289
290
291

292
293
294
295
296
297
298
273
274
275
276
277
278
279

280
281
282
283
284
285
286
287
288
289

290
291
292
293
294
295
296
297
298
299
300

301
302
303
304
305
306
307
308







-
+
+
+







-
+










-
+







    WORD wFlags,
    DISPPARAMS *pDispParams,
    VARIANT *pvarResult,
    EXCEPINFO *pExcepInfo,
    UINT *puArgErr)
{
    HRESULT hr = DISP_E_MEMBERNOTFOUND;
    TkWinSendCom *this = (TkWinSendCom*)This;
    TkWinSendCom *sendCom = (TkWinSendCom*)This;
    (void)riid;
    (void)lcid;

    switch (dispidMember) {
    case TKWINSENDCOM_DISPID_SEND:
	if (wFlags | DISPATCH_METHOD) {
	    if (pDispParams->cArgs != 1) {
		hr = DISP_E_BADPARAMCOUNT;
	    } else {
		hr = Send(this, pDispParams->rgvarg[0], pvarResult,
		hr = Send(sendCom, pDispParams->rgvarg[0], pvarResult,
			pExcepInfo, puArgErr);
	    }
	}
	break;

    case TKWINSENDCOM_DISPID_ASYNC:
	if (wFlags | DISPATCH_METHOD) {
	    if (pDispParams->cArgs != 1) {
		hr = DISP_E_BADPARAMCOUNT;
	    } else {
		hr = Async(this, pDispParams->rgvarg[0], pExcepInfo, puArgErr);
		hr = Async(sendCom, pDispParams->rgvarg[0], pExcepInfo, puArgErr);
	    }
	}
	break;
    }
    return hr;
}

309
310
311
312
313
314
315
316

317
318

319
320
321
322
323
324
325

326
327

328
329
330
331
332
333
334

335
336

337
338
339
340
341
342
343



344

345
346
347
348
349
350
351
319
320
321
322
323
324
325

326
327

328
329
330
331
332
333
334

335
336

337
338
339
340
341
342
343

344
345

346
347
348
349
350
351
352
353
354
355
356

357
358
359
360
361
362
363
364







-
+

-
+






-
+

-
+






-
+

-
+







+
+
+
-
+








static STDMETHODIMP
ISupportErrorInfo_QueryInterface(
    ISupportErrorInfo *This,
    REFIID riid,
    void **ppvObject)
{
    TkWinSendCom *this = (TkWinSendCom *)(This - 1);
    TkWinSendCom *sendCom = (TkWinSendCom *)(This - 1);

    return this->lpVtbl->QueryInterface((IDispatch *) this, riid, ppvObject);
    return sendCom->lpVtbl->QueryInterface((IDispatch *) sendCom, riid, ppvObject);
}

static STDMETHODIMP_(ULONG)
ISupportErrorInfo_AddRef(
    ISupportErrorInfo *This)
{
    TkWinSendCom *this = (TkWinSendCom *)(This - 1);
    TkWinSendCom *sendCom = (TkWinSendCom *)(This - 1);

    return InterlockedIncrement(&this->refcount);
    return InterlockedIncrement(&sendCom->refcount);
}

static STDMETHODIMP_(ULONG)
ISupportErrorInfo_Release(
    ISupportErrorInfo *This)
{
    TkWinSendCom *this = (TkWinSendCom *)(This - 1);
    TkWinSendCom *sendCom = (TkWinSendCom *)(This - 1);

    return this->lpVtbl->Release((IDispatch *) this);
    return sendCom->lpVtbl->Release((IDispatch *) sendCom);
}

static STDMETHODIMP
ISupportErrorInfo_InterfaceSupportsErrorInfo(
    ISupportErrorInfo *This,
    REFIID riid)
{
    (void)This;
    (void)riid;

    /*TkWinSendCom *this = (TkWinSendCom*)(This - 1);*/
    /*TkWinSendCom *sendCom = (TkWinSendCom*)(This - 1);*/
    return S_OK; /* or S_FALSE */
}

/*
 * ----------------------------------------------------------------------
 *
 * Async --
367
368
369
370
371
372
373

374
375
376
377
378
379
380
381
382
383
384
385
386
387

388

389
390
391
392
393
394
395
396
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402

403

404
405
406
407
408
409
410







+














+
-
+
-







    VARIANT Cmd,
    EXCEPINFO *pExcepInfo,
    UINT *puArgErr)
{
    HRESULT hr = S_OK;
    VARIANT vCmd;
    Tcl_DString ds;
    (void)puArgErr;

    VariantInit(&vCmd);

    hr = VariantChangeType(&vCmd, &Cmd, 0, VT_BSTR);
    if (FAILED(hr)) {
	Tcl_SetObjResult(obj->interp, Tcl_NewStringObj(
		"invalid args: Async(command)", -1));
	TkWinSend_SetExcepInfo(obj->interp, pExcepInfo);
	hr = DISP_E_EXCEPTION;
    }

    if (SUCCEEDED(hr) && obj->interp) {
	Tcl_Obj *scriptPtr;

	Tcl_DStringInit(&ds);
	Tcl_WinTCharToUtf((LPCTSTR)vCmd.bstrVal, SysStringLen(vCmd.bstrVal) *
	Tcl_WCharToUtfDString(vCmd.bstrVal, SysStringLen(vCmd.bstrVal), &ds);
		sizeof (WCHAR), &ds);
	scriptPtr =
		Tcl_NewStringObj(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds));
	Tcl_DStringFree(&ds);
	TkWinSend_QueueCommand(obj->interp, scriptPtr);
    }

    VariantClear(&vCmd);
414
415
416
417
418
419
420
421

422
423
424
425
426
427
428
429
430

431
432

433
434
435
436
437
438
439
440
441
442

443

444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461


462
463
464
465
466
467
468
428
429
430
431
432
433
434

435
436
437
438
439
440
441
442
443

444
445
446
447
448
449
450
451
452
453
454
455
456
457
458

459

460
461
462
463
464
465
466
467
468
469
470
471
472
473
474


475
476
477
478
479
480
481
482
483







-
+








-
+


+










+
-
+
-















-
-
+
+







 *	The interpreters state and result will be modified.
 *
 * ----------------------------------------------------------------------
 */

static HRESULT
Send(
    TkWinSendCom *obj,
    TkWinSendCom *comobj,
    VARIANT vCmd,
    VARIANT *pvResult,
    EXCEPINFO *pExcepInfo,
    UINT *puArgErr)
{
    HRESULT hr = S_OK;
    int result = TCL_OK;
    VARIANT v;
    register Tcl_Interp *interp = obj->interp;
    Tcl_Interp *interp = comobj->interp;
    Tcl_Obj *scriptPtr;
    Tcl_DString ds;
    (void)puArgErr;

    if (interp == NULL) {
	return S_OK;
    }
    VariantInit(&v);
    hr = VariantChangeType(&v, &vCmd, 0, VT_BSTR);
    if (!SUCCEEDED(hr)) {
	return hr;
    }

    Tcl_DStringInit(&ds);
    Tcl_WinTCharToUtf((LPCTSTR)v.bstrVal, SysStringLen(v.bstrVal) *
    Tcl_WCharToUtfDString(v.bstrVal, SysStringLen(v.bstrVal), &ds);
	    sizeof(WCHAR), &ds);
    scriptPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds));
    Tcl_DStringFree(&ds);
    Tcl_Preserve(interp);
    Tcl_IncrRefCount(scriptPtr);
    result = Tcl_EvalObjEx(interp, scriptPtr,
	    TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL);
    Tcl_DecrRefCount(scriptPtr);
    if (pvResult != NULL) {
	Tcl_Obj *obj;
	const char *src;

	VariantInit(pvResult);
	pvResult->vt = VT_BSTR;
	obj = Tcl_GetObjResult(interp);
	src = Tcl_GetString(obj);
	Tcl_WinUtfToTChar(src, obj->length, &ds);
	pvResult->bstrVal = SysAllocString((WCHAR *) Tcl_DStringValue(&ds));
	Tcl_DStringInit(&ds);
	pvResult->bstrVal = SysAllocString(Tcl_UtfToWCharDString(src, obj->length, &ds));
	Tcl_DStringFree(&ds);
    }
    if (result == TCL_ERROR) {
	hr = DISP_E_EXCEPTION;
	TkWinSend_SetExcepInfo(interp, pExcepInfo);
    }
    Tcl_Release(interp);
Changes to win/tkWinSendCom.h.
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







/*
 * tkWinSendCom.h --
 *
 *	This file provides procedures that implement the Windows "send"
 *	command, allowing commands to be passed from interpreter to
 *	interpreter.
 *
 * Copyright (C) 2002 Pat Thoyts <[email protected]>
 * Copyright © 2002 Pat Thoyts <[email protected]>
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#ifndef _tkWinSendCom_h_INCLUDE
#define _tkWinSendCom_h_INCLUDE
Added win/tkWinSysTray.c.




















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
 * tkWinSysTray.c --
 *
 * 	tkWinSysTray.c implements a "systray" Tcl command which permits to
 * 	change the system tray/taskbar icon of a Tk toplevel window and
 * 	a "sysnotify" command to post system notifications.
 *
 * Copyright © 1995-1996 Microsoft Corp.
 * Copyright © 1998 Brueckner & Jarosch Ing.GmbH, Erfurt, Germany
 * 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.
 */

#include "tkInt.h"
#include <windows.h>
#include <shellapi.h>
#include "tkWin.h"
#include "tkWinInt.h"
#include "tkWinIco.h"

/*
 * Based extensively on the winico extension and sample code from Microsoft.
 * Some of the code was adapted into tkWinWM.c to implement the "wm iconphoto"
 * command (TIP 159), and here we are borrowing that code to use Tk images
 * to create system tray icons instead of ico files. Additionally, we are
 * removing obsolete parts of the winico extension, and implementing
 * more of the Shell_Notification API to add balloon/system notifications.
 */

#define GETHINSTANCE Tk_GetHINSTANCE()

#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif

#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif

#ifdef _MSC_VER
/*
 * Earlier versions of MSVC don't know snprintf, but _snprintf is compatible.
 * Note that sprintf is deprecated.
 */
# define snprintf _snprintf
#endif

typedef struct IcoInfo {
    HICON hIcon;                /* icon handle returned by LoadIcon. */
    unsigned id;                /* Identifier for command;  used to
                                 * cancel it. */
    Tcl_Obj *taskbar_txt;       /* text to display in the taskbar */
    Tcl_Interp *interp;         /* interp which created the icon */
    Tcl_Obj *taskbar_command;   /* command to eval if events in the taskbar
                                 * arrive */
    int taskbar_flags;          /* taskbar related flags*/
    HWND hwndFocus;
    struct IcoInfo *nextPtr;
} IcoInfo;

/* Per-interp struture */
typedef struct IcoInterpInfo {
    HWND hwnd;                  /* Handler window */
    int counter;                /* Counter for IcoInfo id generation */
    IcoInfo *firstIcoPtr;       /* List of created IcoInfo */
    struct IcoInterpInfo *nextPtr;
} IcoInterpInfo;

#define TASKBAR_ICON 1
#define ICON_MESSAGE WM_USER + 1234

#define HANDLER_CLASS "Wtk_TaskbarHandler"
static HWND CreateTaskbarHandlerWindow(void);

static IcoInterpInfo *firstIcoInterpPtr = NULL;
static Tk_EventProc WinIcoDestroy;

/*
 * If someone wants to see the several masks somewhere on the screen...
 * set the ICO_DRAW define and feel free to make some Tcl commands
 * for accessing it.  The normal drawing of an Icon to a DC is really easy:
 * DrawIcon(hdc,x,y,hIcon) or , more complicated
 * DrawIconEx32PlusMoreParameters ...
 */

/* #define ICO_DRAW */
#ifdef ICO_DRAW
#define RectWidth(r)((r).right - (r).left + 1)
#define RectHeight(r)((r).bottom - (r).top + 1)

/*
 *----------------------------------------------------------------------
 *
 * DrawXORMask --
 *
 * 	Using DIB functions, draw XOR mask on hDC in Rect.
 *
 * Results:
 *	Icon is rendered.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static BOOL
DrawXORMask(
    HDC hDC,
    RECT Rect,
    LPLPICONIMAGE lpIcon)
{
    int x, y;

    /* Sanity checks */
    if (lpIcon == NULL)
        return FALSE;
    if (lpIcon->lpBits == NULL)
        return FALSE;

    /* Account for height*2 thing */
    lpIcon->lpbi->bmiHeader.biHeight /= 2;

    /* Locate it */
    x = Rect.left + ((RectWidth(Rect) - lpIcon->lpbi->bmiHeader.biWidth) / 2);
    y = Rect.top + ((RectHeight(Rect) - lpIcon->lpbi->bmiHeader.biHeight) / 2);

    /* Blast it to the screen */
    SetDIBitsToDevice(hDC, x, y,
            lpIcon->lpbi->bmiHeader.biWidth,
            lpIcon->lpbi->bmiHeader.biHeight,
            0, 0, 0, lpIcon->lpbi->bmiHeader.biHeight,
            lpIcon->lpXOR, lpIcon->lpbi, DIB_RGB_COLORS);

    /* UnAccount for height*2 thing */
    lpIcon->lpbi->bmiHeader.biHeight *= 2;

    return TRUE;
}

/*
 *----------------------------------------------------------------------
 *
 * DrawANDMask --
 *
 * 	Using DIB functions, draw AND mask on hDC in Rect.
 *
 * Results:
 *	Icon is rendered.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

BOOL
DrawANDMask(
    HDC hDC,
    RECT Rect,
    LPLPICONIMAGE lpIcon)
{
    LPBITMAPINFO lpbi;
    int x, y;

    /* Sanity checks */
    if (lpIcon == NULL)
        return FALSE;
    if (lpIcon->lpBits == NULL)
        return FALSE;

    /* Need a bitmap header for the mono mask */
    lpbi = ckalloc(sizeof(BITMAPINFO) + (2 * sizeof(RGBQUAD)));
    lpbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    lpbi->bmiHeader.biWidth = lpIcon->lpbi->bmiHeader.biWidth;
    lpbi->bmiHeader.biHeight = lpIcon->lpbi->bmiHeader.biHeight / 2;
    lpbi->bmiHeader.biPlanes = 1;
    lpbi->bmiHeader.biBitCount = 1;
    lpbi->bmiHeader.biCompression = BI_RGB;
    lpbi->miHeader.biSizeImage = 0;
    lpbi->bmiHeader.biXPelsPerMeter = 0;
    lpbi->bmiHeader.biYPelsPerMeter = 0;
    lpbi->bmiHeader.biClrUsed = 0;
    lpbi->bmiHeader.biClrImportant = 0;
    lpbi->bmiColors[0].rgbRed = 0;
    lpbi->bmiColors[0].rgbGreen = 0;
    lpbi->bmiColors[0].rgbBlue = 0;
    lpbi->bmiColors[0].rgbReserved = 0;
    lpbi->bmiColors[1].rgbRed = 255;
    lpbi->bmiColors[1].rgbGreen = 255;
    lpbi->bmiColors[1].rgbBlue = 255;
    lpbi->bmiColors[1].rgbReserved = 0;

    /* Locate it */
    x = Rect.left + ((RectWidth(Rect) - lpbi->bmiHeader.biWidth) / 2);
    y = Rect.top + ((RectHeight(Rect) - lpbi->bmiHeader.biHeight) / 2);

    /* Blast it to the screen */
    SetDIBitsToDevice(hDC, x, y,
            lpbi->bmiHeader.biWidth,
            lpbi->bmiHeader.biHeight,
            0, 0, 0, lpbi->bmiHeader.biHeight,
            lpIcon->lpAND, lpbi, DIB_RGB_COLORS);

    /* clean up */
    ckfree((char *) lpbi);

    return TRUE;
}
#endif /* ICO_DRAW */

/*
 *----------------------------------------------------------------------
 *
 * TaskbarOperation --
 *
 * 	Management of icon display.
 *
 * Results:
 *	Icon is displayed or deleted.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TaskbarOperation(
    IcoInterpInfo *icoInterpPtr,
    IcoInfo *icoPtr,
    int oper)
{
    NOTIFYICONDATAW ni;
    WCHAR *str;

    ni.cbSize = sizeof(NOTIFYICONDATAW);
    ni.hWnd = icoInterpPtr->hwnd;
    ni.uID = icoPtr->id;
    ni.uFlags = NIF_ICON | NIF_TIP | NIF_MESSAGE;
    ni.uCallbackMessage = ICON_MESSAGE;
    ni.hIcon = icoPtr->hIcon;

    if (icoPtr->taskbar_txt != NULL) {
        Tcl_DString dst;
        Tcl_DStringInit(&dst);
        str = (WCHAR *)Tcl_UtfToWCharDString(Tcl_GetString(icoPtr->taskbar_txt), -1, &dst);
        wcsncpy(ni.szTip, str, (Tcl_DStringLength(&dst) + 2) / 2);
        Tcl_DStringFree(&dst);
    } else {
        ni.szTip[0] = 0;
    }

    if (Shell_NotifyIconW(oper, &ni) == 1) {
        if (oper == NIM_ADD || oper == NIM_MODIFY) {
            icoPtr->taskbar_flags |= TASKBAR_ICON;
        }
        if (oper == NIM_DELETE) {
            icoPtr->taskbar_flags &= ~TASKBAR_ICON;
        }
    }
    /* Silently ignore error? */
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * NewIcon --
 *
 * 	Create icon for display in system tray.
 *
 * Results:
 *	Icon is created for display.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static IcoInfo *
NewIcon(
    Tcl_Interp *interp,
    IcoInterpInfo *icoInterpPtr,
    HICON hIcon)
{
    IcoInfo *icoPtr;

    icoPtr = (IcoInfo *)ckalloc(sizeof(IcoInfo));
    memset(icoPtr, 0, sizeof(IcoInfo));
    icoPtr->id = ++icoInterpPtr->counter;
    icoPtr->hIcon = hIcon;
    icoPtr->taskbar_txt = NULL;
    icoPtr->interp = interp;
    icoPtr->taskbar_command = NULL;
    icoPtr->taskbar_flags = 0;
    icoPtr->hwndFocus = NULL;
    icoPtr->nextPtr = icoInterpPtr->firstIcoPtr;
    icoInterpPtr->firstIcoPtr = icoPtr;
    return icoPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * FreeIcoPtr --
 *
 * 	Delete icon and free memory.
 *
 * Results:
 *	Icon is removed from display.
 *
 * Side effects:
 *	Memory/resources freed.
 *
 *----------------------------------------------------------------------
 */

static void
FreeIcoPtr(
    IcoInterpInfo *icoInterpPtr,
    IcoInfo *icoPtr)
{
    IcoInfo *prevPtr;
    if (icoInterpPtr->firstIcoPtr == icoPtr) {
        icoInterpPtr->firstIcoPtr = icoPtr->nextPtr;
    } else {
        for (prevPtr = icoInterpPtr->firstIcoPtr; prevPtr->nextPtr != icoPtr;
                prevPtr = prevPtr->nextPtr) {
            /* Empty loop body. */
        }
        prevPtr->nextPtr = icoPtr->nextPtr;
    }
    if (icoPtr->taskbar_flags & TASKBAR_ICON) {
        TaskbarOperation(icoInterpPtr, icoPtr, NIM_DELETE);
    }
    if (icoPtr->taskbar_txt != NULL) {
        Tcl_DecrRefCount(icoPtr->taskbar_txt);
    }
    if (icoPtr->taskbar_command != NULL) {
        Tcl_DecrRefCount(icoPtr->taskbar_command);
    }
    ckfree(icoPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * GetIcoPtr --
 *
 * 	Get pointer to icon for display.
 *
 * Results:
 *	Icon is obtained for display.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static IcoInfo *
GetIcoPtr(
    Tcl_Interp *interp,
    IcoInterpInfo *icoInterpPtr,
    const char *string)
{
    IcoInfo *icoPtr;
    unsigned id;
    const char *start;
    char *end;

    if (strncmp(string, "ico#", 4) != 0) {
        goto notfound;
    }
    start = string + 4;
    id = strtoul(start, &end, 10);
    if ((end == start) || (*end != 0)) {
        goto notfound;
    }
    for (icoPtr = icoInterpPtr->firstIcoPtr; icoPtr != NULL; icoPtr = icoPtr->nextPtr) {
        if (icoPtr->id == id) {
            return icoPtr;
        }
    }

notfound:
    Tcl_AppendResult(interp, "icon \"", string,
        "\" doesn't exist", (char *) NULL);
    return NULL;
}

/*
 *----------------------------------------------------------------------
 *
 * GetInt --
 *
 * Utility function for calculating buffer length.
 *
 * Results:
 *	Length.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
GetInt(
    long theint,
    char *buffer,
    size_t len)
{
    snprintf(buffer, len, "0x%lx", theint);
    buffer[len - 1] = 0;
    return (int) strlen(buffer);
}

/*
 *----------------------------------------------------------------------
 *
 * GetIntDec --
 *
 * Utility function for calculating buffer length.
 *
 * Results:
 *	Length.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
GetIntDec(
    long theint,
    char *buffer,
    size_t len)
{
    snprintf(buffer, len - 1, "%ld", theint);
    buffer[len - 1] = 0;
    return (int) strlen(buffer);
}

/*
 *----------------------------------------------------------------------
 *
 * TaskbarExpandPercents --
 *
 * Parse strings in taskbar display.
 *
 * Results:
 *	Strings.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static char*
TaskbarExpandPercents(
    IcoInfo *icoPtr,
    const char *msgstring,
    WPARAM wParam,
    LPARAM lParam,
    char *before,
    char *after,
    int *aftersize)
{
#define SPACELEFT (*aftersize-(dst-after)-1)
#define AFTERLEN ((*aftersize>0)?(*aftersize*2):1024)
#define ALLOCLEN ((len>AFTERLEN)?(len*2):AFTERLEN)
    char buffer[TCL_INTEGER_SPACE + 5];
    char* dst;
    dst = after;
    while (*before) {
        const char *ptr = before;
        int len = 1;
        if(*before == '%') {
            switch(before[1]){
                case 'M':
                case 'm': {
                    before++;
                    len = strlen(msgstring);
                    ptr = msgstring;
                    break;
                }
                /* case 'W': {
                   before++;
                   len = (int)strlen(winstring);
                   ptr = winstring;
                   break;
                   }
                */
                case 'i': {
                    before++;
                    snprintf(buffer, sizeof(buffer) - 1, "ico#%d", icoPtr->id);
                    len = strlen(buffer);
                    ptr = buffer;
                    break;
                }
                case 'w': {
                    before++;
                    len = GetInt((long)wParam,buffer, sizeof(buffer));
                    ptr = buffer;
                    break;
                }
                case 'l': {
                    before++;
                    len = GetInt((long)lParam,buffer, sizeof(buffer));
                    ptr = buffer;
                    break;
                }
                case 't': {
                    before++;
                    len = GetInt((long)GetTickCount(), buffer, sizeof(buffer));
                    ptr = buffer;
                    break;
                }
                case 'x': {
                    POINT pt;
                    GetCursorPos(&pt);
                    before++;
                    len = GetIntDec((long)pt.x, buffer, sizeof(buffer));
                    ptr = buffer;
                    break;
                }
                case 'y': {
                    POINT pt;
                    GetCursorPos(&pt);
                    before++;
                    len = GetIntDec((long)pt.y,buffer, sizeof(buffer));
                    ptr = buffer;
                    break;
                }
                case 'X': {
                    DWORD dw;
                    dw = GetMessagePos();
                    before++;
                    len = GetIntDec((long)LOWORD(dw),buffer, sizeof(buffer));
                    ptr = buffer;
                    break;
                }
                case 'Y': {
                    DWORD dw;
                    dw = GetMessagePos();
                    before++;
                    len = GetIntDec((long)HIWORD(dw),buffer, sizeof(buffer));
                    ptr = buffer;
                    break;
                }
                case 'H': {
                    before++;
                    len = GetInt(PTR2INT(icoPtr->hwndFocus), buffer, sizeof(buffer));
                    ptr = buffer;
                    break;
                }
                case '%': {
                    before++;
                    len = 1;
                    ptr = "%";
                    break;
                }
            }
        }
        if (SPACELEFT < len) {
            char *newspace;
            ptrdiff_t dist = dst - after;
            int alloclen = ALLOCLEN;
            newspace = (char *)ckalloc(alloclen);
            if (dist>0)
                memcpy(newspace, after, dist);
            if (after && *aftersize) {
                ckfree(after);
            }
            *aftersize =alloclen;
            after = newspace;
            dst = after + dist;
        }
        if (len > 0) {
            memcpy(dst, ptr, len);
        }
        dst += len;
        if ((dst-after)>(*aftersize-1)) {
            printf("oops\n");
        }
        before++;
    }
    *dst = 0;
    return after;
}

/*
 *----------------------------------------------------------------------
 *
 * TaskbarEval --
 *
 * Parse mouse and keyboard events over taskbar.
 *
 * Results:
 *	Event processing.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
TaskbarEval(
    IcoInfo *icoPtr,
    WPARAM wParam,
    LPARAM lParam)
{
    const char *msgstring = "none";
    char evalspace[200];
    int evalsize = 200;
    char *expanded;
    int fixup = 0;

    switch (lParam) {
    case WM_MOUSEMOVE:
        msgstring = "WM_MOUSEMOVE";
        icoPtr->hwndFocus = GetFocus();
        break;
    case WM_LBUTTONDOWN:
        msgstring = "WM_LBUTTONDOWN";
        fixup = 1;
        break;
    case WM_LBUTTONUP:
        msgstring = "WM_LBUTTONUP";
        fixup = 1;
        break;
    case WM_LBUTTONDBLCLK:
        msgstring = "WM_LBUTTONDBLCLK";
        fixup = 1;
        break;
    case WM_RBUTTONDOWN:
        msgstring = "WM_RBUTTONDOWN";
        fixup = 1;
        break;
    case WM_RBUTTONUP:
        msgstring = "WM_RBUTTONUP";
        fixup = 1;
        break;
    case WM_RBUTTONDBLCLK:
        msgstring = "WM_RBUTTONDBLCLK";
        fixup = 1;
        break;
    case WM_MBUTTONDOWN:
        msgstring = "WM_MBUTTONDOWN";
        fixup = 1;
        break;
    case WM_MBUTTONUP:
        msgstring = "WM_MBUTTONUP";
        fixup = 1;
        break;
    case WM_MBUTTONDBLCLK:
        msgstring = "WM_MBUTTONDBLCLK";
        fixup = 1;
        break;
    default:
        msgstring = "WM_NULL";
        fixup = 0;
    }
    expanded = TaskbarExpandPercents(icoPtr, msgstring, wParam, lParam,
            Tcl_GetString(icoPtr->taskbar_command), evalspace, &evalsize);
    if (icoPtr->interp != NULL) {
        int result;
        HWND hwnd = NULL;

        /* See http://support.microsoft.com/kb/q135788/
         * Seems to have moved to https://www.betaarchive.com/wiki/index.php/Microsoft_KB_Archive/135788 */
        if (fixup) {
            if (icoPtr->hwndFocus != NULL && IsWindow(icoPtr->hwndFocus)) {
                hwnd = icoPtr->hwndFocus;
            } else {
                Tk_Window tkwin = Tk_MainWindow(icoPtr->interp);
                if (tkwin != NULL) {
                    hwnd = Tk_GetHWND(Tk_WindowId(tkwin));
                }
            }
            if (hwnd != NULL) {
                SetForegroundWindow(hwnd);
            }
        }

        result = Tcl_GlobalEval(icoPtr->interp, expanded);

        if (hwnd != NULL) {
            /* See http://support.microsoft.com/kb/q135788/
             * Seems to have moved to https://www.betaarchive.com/wiki/index.php/Microsoft_KB_Archive/135788 */
            PostMessageW(hwnd, WM_NULL, 0, 0);
        }
        if (result != TCL_OK) {
            char buffer[100];
            sprintf(buffer, "\n  (command bound to taskbar-icon ico#%d)", icoPtr->id);
            Tcl_AddErrorInfo(icoPtr->interp, buffer);
            Tcl_BackgroundError(icoPtr->interp);
        }
    }
    if (expanded != evalspace) {
        ckfree(expanded);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TaskbarHandlerProc --
 *
 * 	Windows callback procedure, if ICON_MESSAGE arrives, try to execute
 * 	the taskbar_command.
 *
 * Results:
 *	Command execution.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static LRESULT CALLBACK
TaskbarHandlerProc(
    HWND hwnd,
    UINT message,
    WPARAM wParam,
    LPARAM lParam)
{
    static UINT msgTaskbarCreated = 0;
    IcoInterpInfo *icoInterpPtr;
    IcoInfo *icoPtr;

    switch (message) {
    case WM_CREATE:
        msgTaskbarCreated = RegisterWindowMessage(TEXT("TaskbarCreated"));
        break;

    case ICON_MESSAGE:
        for (icoInterpPtr = firstIcoInterpPtr; icoInterpPtr != NULL; icoInterpPtr = icoInterpPtr->nextPtr) {
            if (icoInterpPtr->hwnd == hwnd) {
                for (icoPtr = icoInterpPtr->firstIcoPtr; icoPtr != NULL; icoPtr = icoPtr->nextPtr) {
                    if (icoPtr->id == wParam) {
                        if (icoPtr->taskbar_command != NULL) {
                            TaskbarEval(icoPtr, wParam, lParam);
                        }
                        break;
                    }
                }
                break;
            }
        }
        break;

    default:
        /*
         * Check to see if explorer has been restarted and we need to
         * re-add our icons.
         */
        if (message == msgTaskbarCreated) {
            for (icoInterpPtr = firstIcoInterpPtr; icoInterpPtr != NULL; icoInterpPtr = icoInterpPtr->nextPtr) {
                if (icoInterpPtr->hwnd == hwnd) {
                    for (icoPtr = icoInterpPtr->firstIcoPtr; icoPtr != NULL; icoPtr = icoPtr->nextPtr) {
                        if (icoPtr->taskbar_flags & TASKBAR_ICON) {
                            TaskbarOperation(icoInterpPtr, icoPtr, NIM_ADD);
                        }
                    }
                    break;
                }
            }
        }
        return DefWindowProc(hwnd, message, wParam, lParam);
    }
    return 0;
}

/*
 *----------------------------------------------------------------------
 *
 * RegisterHandlerClass --
 *
 * 	Registers the handler window class.
 *
 * Results:
 *	Handler class registered.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
RegisterHandlerClass(
    HINSTANCE hInstance)
{
    WNDCLASS wndclass;
    memset(&wndclass, 0, sizeof(WNDCLASS));
    wndclass.style = 0;
    wndclass.lpfnWndProc = TaskbarHandlerProc;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = hInstance;
    wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
    wndclass.lpszMenuName = NULL;
    wndclass.lpszClassName = HANDLER_CLASS;
    return RegisterClass(&wndclass);
}

/*
 *----------------------------------------------------------------------
 *
 * CreateTaskbarHandlerWindow --
 *
 * 	Creates a hidden window to handle taskbar messages.
 *
 * Results:
 *	Hidden window created.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static HWND
CreateTaskbarHandlerWindow(void) {
    static int registered = 0;
    HINSTANCE hInstance = GETHINSTANCE;
    if (!registered) {
        if (!RegisterHandlerClass(hInstance))
            return 0;
        registered = 1;
    }
    return CreateWindow(HANDLER_CLASS, "", WS_OVERLAPPED, 0, 0,
            CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
}

/*
 *----------------------------------------------------------------------
 *
 * WinIcoDestroy --
 *
 *	Event handler to delete systray icons when interp main window
 *	is deleted, either by destroy, interp deletion or application
 *	exit.
 *
 * Results:
 *	Icon/window removed and memory freed.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
WinIcoDestroy(
    ClientData clientData,
    XEvent *eventPtr)
{
    IcoInterpInfo *icoInterpPtr = (IcoInterpInfo*) clientData;
    IcoInterpInfo *prevIcoInterpPtr;
    IcoInfo *icoPtr;
    IcoInfo *nextPtr;

    if (eventPtr->type != DestroyNotify) {
        return;
    }

    if (firstIcoInterpPtr == icoInterpPtr) {
        firstIcoInterpPtr = icoInterpPtr->nextPtr;
    } else {
        for (prevIcoInterpPtr = firstIcoInterpPtr; prevIcoInterpPtr->nextPtr != icoInterpPtr;
                prevIcoInterpPtr = prevIcoInterpPtr->nextPtr) {
            /* Empty loop body. */
        }
        prevIcoInterpPtr->nextPtr = icoInterpPtr->nextPtr;
    }

    DestroyWindow(icoInterpPtr->hwnd);
    for (icoPtr = icoInterpPtr->firstIcoPtr; icoPtr != NULL; icoPtr = nextPtr) {
            nextPtr = icoPtr->nextPtr;
        FreeIcoPtr(icoInterpPtr, icoPtr);
    }
    ckfree((char *) icoInterpPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * WinSystrayCmd --
 *
 * 	Main command for creating, displaying, and removing icons from taskbar.
 *
 * Results:
 *	Management of icon display in taskbar/system tray.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
WinSystrayCmd(
    ClientData clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    static const char *const cmdStrings[] = {
        "add", "delete", "modify", NULL
    };
    enum { CMD_ADD, CMD_DELETE, CMD_MODIFY };
    static const char *const optStrings[] = {
        "-image", "-text", "-callback", NULL
    };
    enum { OPT_IMAGE, OPT_TEXT, OPT_CALLBACK };
    int cmd, opt;

    HICON hIcon;
    int i;
    IcoInterpInfo *icoInterpPtr = (IcoInterpInfo*) clientData;
    IcoInfo *icoPtr = NULL;

    if (objc < 2) {
        Tcl_WrongNumArgs(interp, 1, objv, "command ...");
        return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObj(interp, objv[1], cmdStrings, "command",
            0, &cmd) == TCL_ERROR) {
        return TCL_ERROR;
    }
    switch (cmd) {
        case CMD_ADD:
        case CMD_MODIFY: {
            Tcl_Obj *imageObj = NULL, *textObj = NULL, *callbackObj = NULL;
            int optStart;
            int oper;
            if (cmd == CMD_ADD) {
                optStart = 2;
                oper = NIM_ADD;
            } else {
                optStart = 3;
                oper = NIM_MODIFY;
                if (objc != 5) {
                    Tcl_WrongNumArgs(interp, 2, objv, "id option value");
                    return TCL_ERROR;
                }
                icoPtr = GetIcoPtr(interp, icoInterpPtr, Tcl_GetString(objv[2]));
                if (icoPtr == NULL) {
                    return TCL_ERROR;
                }
            }
            for (i = optStart; i < objc; i += 2) {
                if (Tcl_GetIndexFromObj(interp, objv[i], optStrings, "option",
                        0, &opt) == TCL_ERROR) {
                    return TCL_ERROR;
                }
                if (i+1 >= objc) {
                    Tcl_AppendResult(interp,
                            "missing value for option \"", Tcl_GetString(objv[i]),
                            "\"", NULL);
                    return TCL_ERROR;
                }
                switch (opt) {
                    case OPT_IMAGE:
                        imageObj = objv[i+1];
                        break;
                    case OPT_TEXT:
                        textObj = objv[i+1];
                        break;
                    case OPT_CALLBACK:
                        callbackObj = objv[i+1];
                        break;
                }
            }
            if (cmd == CMD_ADD && imageObj == NULL) {
                Tcl_SetResult(interp, "missing required option \"-image\"", TCL_STATIC);
                return TCL_ERROR;
            }
            if (imageObj != NULL) {
                Tk_PhotoHandle photo;
                int width, height;
                Tk_PhotoImageBlock block;

                photo = Tk_FindPhoto(interp, Tcl_GetString(imageObj));
                if (photo == NULL) {
                    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                            "image \"%s\" doesn't exist", Tcl_GetString(imageObj)));
                    return TCL_ERROR;
                }
                Tk_PhotoGetSize(photo, &width, &height);
                Tk_PhotoGetImage(photo, &block);
                hIcon = CreateIcoFromPhoto(width, height, block);
                if (hIcon == NULL) {
                    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                            "failed to create an iconphoto with image \"%s\"", Tcl_GetString(imageObj)));
                    return TCL_ERROR;
                }
            }
            if (cmd == CMD_ADD) {
                icoPtr = NewIcon(interp, icoInterpPtr, hIcon);
            } else {
                if (imageObj != NULL) {
                    DestroyIcon(icoPtr->hIcon);
                    icoPtr->hIcon = hIcon;
                }
            }
            if (callbackObj != NULL) {
                if (icoPtr->taskbar_command != NULL) {
                    Tcl_DecrRefCount(icoPtr->taskbar_command);
                }
                icoPtr->taskbar_command = callbackObj;
                Tcl_IncrRefCount(icoPtr->taskbar_command);
            }
            if (textObj != NULL) {
                if (icoPtr->taskbar_txt != NULL) {
                    Tcl_DecrRefCount(icoPtr->taskbar_txt);
                }
                icoPtr->taskbar_txt = textObj;
                Tcl_IncrRefCount(icoPtr->taskbar_txt);
            }
            TaskbarOperation(icoInterpPtr, icoPtr, oper);
            if (cmd == CMD_ADD) {
                char buffer[5 + TCL_INTEGER_SPACE];
                int n;
                n = _snprintf(buffer, sizeof(buffer) - 1, "ico#%d", icoPtr->id);
                buffer[n] = 0;
                Tcl_SetObjResult(interp, Tcl_NewStringObj(buffer, n));
            }
            return TCL_OK;
        }
        case CMD_DELETE:
            if (objc != 3) {
                Tcl_WrongNumArgs(interp, 2, objv, "id");
                return TCL_ERROR;
            }
            icoPtr = GetIcoPtr(interp, icoInterpPtr, Tcl_GetString(objv[2]));
            if (icoPtr == NULL) {
                return TCL_ERROR;
            }
            FreeIcoPtr(icoInterpPtr, icoPtr);
            return TCL_OK;
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * WinSysNotifyCmd --
 *
 * 	Main command for creating and displaying notifications/balloons from system tray.
 *
 * Results:
 *	Display of notifications.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
WinSysNotifyCmd(
    ClientData clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    IcoInterpInfo *icoInterpPtr = (IcoInterpInfo*) clientData;
    IcoInfo *icoPtr;
    Tcl_DString infodst;
    Tcl_DString titledst;
    NOTIFYICONDATAW ni;
    char *msgtitle;
    char *msginfo;

    if (objc < 2) {
        Tcl_WrongNumArgs(interp, 1, objv, "command ...");
        return TCL_ERROR;
    }
    if (strcmp(Tcl_GetString(objv[1]), "notify") != 0) {
        Tcl_AppendResult(interp, "unknown subcommand \"", Tcl_GetString(objv[1]),
                "\": must be notify", NULL);
        return TCL_ERROR;
    }
    if (objc != 5) {
        Tcl_WrongNumArgs(interp, 2, objv, "id title detail");
        return TCL_ERROR;
    }

    icoPtr = GetIcoPtr(interp, icoInterpPtr, Tcl_GetString(objv[2]));
    if (icoPtr == NULL) {
        return TCL_ERROR;
    }

    ni.cbSize = sizeof(NOTIFYICONDATAW);
    ni.hWnd = icoInterpPtr->hwnd;
    ni.uID = icoPtr->id;
    ni.uFlags = NIF_INFO;
    ni.uCallbackMessage = ICON_MESSAGE;
    ni.hIcon = icoPtr->hIcon;
    ni.dwInfoFlags = NIIF_INFO; /* Use a sane platform-specific icon here.*/

    msgtitle = Tcl_GetString(objv[3]);
    msginfo = Tcl_GetString(objv[4]);

    /* Balloon notification for system tray icon. */
    if (msgtitle != NULL) {
        WCHAR *title;
        Tcl_DStringInit(&titledst);
        title = Tcl_UtfToWCharDString(msgtitle, -1, &titledst);
        wcsncpy(ni.szInfoTitle, title, (Tcl_DStringLength(&titledst) + 2) / 2);
        Tcl_DStringFree(&titledst);
    }
    if (msginfo != NULL) {
        WCHAR *info;
        Tcl_DStringInit(&infodst);
        info = Tcl_UtfToWCharDString(msginfo, -1, &infodst);
        wcsncpy(ni.szInfo, info, (Tcl_DStringLength(&infodst) + 2) / 2);
        Tcl_DStringFree(&infodst);
    }

    Shell_NotifyIconW(NIM_MODIFY, &ni);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * WinIcoInit --
 *
 * 	Initialize this package and create script-level commands.
 *
 * Results:
 *	Initialization of code.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
WinIcoInit(
    Tcl_Interp *interp)
{
    IcoInterpInfo *icoInterpPtr;
    Tk_Window mainWindow;

#ifdef USE_TCL_STUBS
    if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
        return TCL_ERROR;
    }
#endif
#ifdef USE_TK_STUBS
    if (Tk_InitStubs(interp, TK_VERSION, 0) == NULL) {
        return TCL_ERROR;
    }
#endif

    mainWindow = Tk_MainWindow(interp);
    if (mainWindow == NULL) {
        Tcl_SetResult(interp, "main window has been destroyed", TCL_STATIC);
        return TCL_ERROR;
    }

    icoInterpPtr = (IcoInterpInfo*) ckalloc(sizeof(IcoInterpInfo));
    icoInterpPtr->counter = 0;
    icoInterpPtr->firstIcoPtr = NULL;
    icoInterpPtr->hwnd = CreateTaskbarHandlerWindow();
    icoInterpPtr->nextPtr = firstIcoInterpPtr;
    firstIcoInterpPtr = icoInterpPtr;
    Tcl_CreateObjCommand(interp, "::tk::systray::_systray", WinSystrayCmd,
            (ClientData) icoInterpPtr, NULL);
    Tcl_CreateObjCommand(interp, "::tk::sysnotify::_sysnotify", WinSysNotifyCmd,
            (ClientData) icoInterpPtr, NULL);

    Tk_CreateEventHandler(mainWindow, StructureNotifyMask,
            WinIcoDestroy, (ClientData) icoInterpPtr);

    return TCL_OK;
}

/*
 * Local variables:
 * mode: c
 * indent-tabs-mode: nil
 * End:
 */
Changes to win/tkWinTest.c.
1
2
3
4
5
6
7
8
9



10
11
12
13
14
15
16
1
2
3
4
5
6



7
8
9
10
11
12
13
14
15
16






-
-
-
+
+
+







/*
 * tkWinTest.c --
 *
 *	Contains commands for platform specific tests for the Windows
 *	platform.
 *
 * Copyright (c) 1997 Sun Microsystems, Inc.
 * Copyright (c) 2000 by Scriptics Corporation.
 * Copyright (c) 2001 by ActiveState Corporation.
 * Copyright © 1997 Sun Microsystems, Inc.
 * Copyright © 2000 Scriptics Corporation.
 * Copyright © 2001 ActiveState Corporation.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#undef USE_TCL_STUBS
#define USE_TCL_STUBS
63
64
65
66
67
68
69
70

71
72

73
74

75
76

77
78

79
80
81
82
83
84
85
63
64
65
66
67
68
69

70
71

72
73

74
75

76
77

78
79
80
81
82
83
84
85







-
+

-
+

-
+

-
+

-
+







    Tcl_Interp *interp)		/* Interpreter to add commands to. */
{
    /*
     * Add commands for platform specific tests on MacOS here.
     */

    Tcl_CreateObjCommand(interp, "testclipboard", TestclipboardObjCmd,
	    (ClientData) Tk_MainWindow(interp), NULL);
	    Tk_MainWindow(interp), NULL);
    Tcl_CreateObjCommand(interp, "testwinevent", TestwineventObjCmd,
	    (ClientData) Tk_MainWindow(interp), NULL);
	    Tk_MainWindow(interp), NULL);
    Tcl_CreateObjCommand(interp, "testfindwindow", TestfindwindowObjCmd,
	    (ClientData) Tk_MainWindow(interp), NULL);
	    Tk_MainWindow(interp), NULL);
    Tcl_CreateObjCommand(interp, "testgetwindowinfo", TestgetwindowinfoObjCmd,
	    (ClientData) Tk_MainWindow(interp), NULL);
	    Tk_MainWindow(interp), NULL);
    Tcl_CreateObjCommand(interp, "testwinlocale", TestwinlocaleObjCmd,
	    (ClientData) Tk_MainWindow(interp), NULL);
	    Tk_MainWindow(interp), NULL);
    return TCL_OK;
}

struct TestFindControlState {
    int  id;
    HWND control;
};
173
174
175
176
177
178
179

180

181
182
183
184
185
186
187
173
174
175
176
177
178
179
180

181
182
183
184
185
186
187
188







+
-
+







	} else {
	    sprintf(msgBuf, "unknown error: %ld", error);
	}
	msg = msgBuf;
    } else {
	char *msgPtr;

	Tcl_DStringInit(&ds);
	Tcl_WinTCharToUtf((LPCTSTR)wMsgPtr, -1, &ds);
	Tcl_WCharToUtfDString(wMsgPtr, wcslen(wMsgPtr), &ds);
	LocalFree(wMsgPtr);

	msgPtr = Tcl_DStringValue(&ds);
	length = Tcl_DStringLength(&ds);

	/*
	 * Trim the trailing CR/LF from the system message.
226
227
228
229
230
231
232


233
234
235
236
237
238
239
240
241
242
243
244

245
246
247
248
249
250
251
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246

247
248
249
250
251
252
253
254







+
+











-
+








static int
SetSelectionResult(
    ClientData dummy,
    Tcl_Interp *interp,
    const char *selection)
{
    (void)dummy;

    Tcl_AppendResult(interp, selection, NULL);
    return TCL_OK;
}

static int
TestclipboardObjCmd(
    ClientData clientData,	/* Main window for application. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument values. */
{
    Tk_Window tkwin = (Tk_Window) clientData;
    Tk_Window tkwin = (Tk_Window)clientData;

    if (objc != 1) {
	Tcl_WrongNumArgs(interp, 1, objv, NULL);
	return TCL_ERROR;
    }
    return TkSelGetSelection(interp, tkwin, Tk_InternAtom(tkwin, "CLIPBOARD"),
	    XA_STRING, SetSelectionResult, NULL);
266
267
268
269
270
271
272
273

274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289










290
291
292
293
294
295

296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311

312
313
314
315
316
317
318
269
270
271
272
273
274
275

276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324

325
326
327
328
329
330
331
332







-
+
















+
+
+
+
+
+
+
+
+
+






+















-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TestwineventObjCmd(
    ClientData clientData,	/* Main window for application. */
    ClientData dummy,	/* Main window for application. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])		/* Argument strings. */
{
    HWND hwnd = 0;
    HWND child = 0;
    HWND control;
    int id;
    char *rest;
    UINT message;
    WPARAM wParam;
    LPARAM lParam;
    LRESULT result;
    static const TkStateMap messageMap[] = {
	{WM_LBUTTONDOWN,	"WM_LBUTTONDOWN"},
	{WM_LBUTTONUP,		"WM_LBUTTONUP"},
	{WM_LBUTTONDBLCLK,		"WM_LBUTTONDBLCLK"},
	{WM_MBUTTONDOWN,	"WM_MBUTTONDOWN"},
	{WM_MBUTTONUP,		"WM_MBUTTONUP"},
	{WM_MBUTTONDBLCLK,		"WM_MBUTTONDBLCLK"},
	{WM_RBUTTONDOWN,	"WM_RBUTTONDOWN"},
	{WM_RBUTTONUP,		"WM_RBUTTONUP"},
	{WM_RBUTTONDBLCLK,		"WM_RBUTTONDBLCLK"},
	{WM_XBUTTONDOWN,	"WM_XBUTTONDOWN"},
	{WM_XBUTTONUP,		"WM_XBUTTONUP"},
	{WM_XBUTTONDBLCLK,		"WM_XBUTTONDBLCLK"},
	{WM_CHAR,		"WM_CHAR"},
	{WM_GETTEXT,		"WM_GETTEXT"},
	{WM_SETTEXT,		"WM_SETTEXT"},
	{WM_COMMAND,            "WM_COMMAND"},
	{-1,			NULL}
    };
    (void)dummy;

    if ((objc == 3) && (strcmp(Tcl_GetString(objv[1]), "debug") == 0)) {
	int b;

	if (Tcl_GetBoolean(interp, Tcl_GetString(objv[2]), &b) != TCL_OK) {
	    return TCL_ERROR;
	}
	TkWinDialogDebug(b);
	return TCL_OK;
    }

    if (objc < 4) {
	return TCL_ERROR;
    }

    hwnd = INT2PTR(strtol(Tcl_GetString(objv[1]), &rest, 0));
    hwnd = (HWND)INT2PTR(strtol(Tcl_GetString(objv[1]), &rest, 0));
    if (rest == Tcl_GetString(objv[1])) {
	hwnd = FindWindowA(NULL, Tcl_GetString(objv[1]));
	if (hwnd == NULL) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj("no such window", -1));
	    return TCL_ERROR;
	}
    }
371
372
373
374
375
376
377
378
379
380
381
382
383







384
385
386


387
388
389
390
391



392
393
394
395
396
397
398
385
386
387
388
389
390
391






392
393
394
395
396
397
398
399


400
401
402
403



404
405
406
407
408
409
410
411
412
413







-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
+
+


-
-
-
+
+
+







	Tcl_AppendResult(interp, Tcl_DStringValue(&ds), NULL);
	Tcl_DStringFree(&ds);
	break;
    }
    case WM_SETTEXT: {
	Tcl_DString ds;

        control = TestFindControl(hwnd, id);
        if (control == NULL) {
            Tcl_SetObjResult(interp,
                             Tcl_ObjPrintf("Could not find control with id %d", id));
            return TCL_ERROR;
        }
	control = TestFindControl(hwnd, id);
	if (control == NULL) {
	    Tcl_SetObjResult(interp,
		    Tcl_ObjPrintf("Could not find control with id %d", id));
	    return TCL_ERROR;
	}
	Tcl_DStringInit(&ds);
	Tcl_UtfToExternalDString(NULL, Tcl_GetString(objv[4]), -1, &ds);
        result = SendMessageA(control, WM_SETTEXT, 0,
                                  (LPARAM) Tcl_DStringValue(&ds));
	result = SendMessageA(control, WM_SETTEXT, 0,
		(LPARAM) Tcl_DStringValue(&ds));
	Tcl_DStringFree(&ds);
	if (result == 0) {
            Tcl_SetObjResult(interp, Tcl_NewStringObj("failed to send text to dialog: ", -1));
            AppendSystemError(interp, GetLastError());
            return TCL_ERROR;
	    Tcl_SetObjResult(interp, Tcl_NewStringObj("failed to send text to dialog: ", -1));
	    AppendSystemError(interp, GetLastError());
	    return TCL_ERROR;
	}
	break;
    }
    case WM_COMMAND: {
	char buf[TCL_INTEGER_SPACE];
	if (objc < 5) {
	    wParam = MAKEWPARAM(id, 0);
412
413
414
415
416
417
418
419

420
421
422
423
424
425
426
427
428
429
430

431
432
433
434
435
436
437
438
439

440
441
442
443
444
445
446
447
448

449

450

451

452
453
454
455
456
457
458
427
428
429
430
431
432
433

434
435
436
437
438
439
440
441
442
443
444

445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465

466
467
468

469
470
471
472
473
474
475
476







-
+










-
+









+









+
-
+

+
-
+







    }
    }
    return TCL_OK;
}

/*
 *  testfindwindow title ?class?
 *	Find a Windows window using the FindWindowW API call. This takes the window
 *	Find a Windows window using the FindWindow API call. This takes the window
 *	title and optionally the window class and if found returns the HWND and
 *	raises an error if the window is not found.
 *	eg: testfindwindow Console TkTopLevel
 *	    Can find the console window if it is visible.
 *	eg: testfindwindow "TkTest #10201" "#32770"
 *	    Can find a messagebox window with this title.
 */

static int
TestfindwindowObjCmd(
    ClientData clientData,	/* Main window for application. */
    ClientData dummy,	/* Main window for application. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument values. */
{
	LPCWSTR title = NULL, windowClass = NULL;
    Tcl_DString titleString, classString;
    HWND hwnd = NULL;
    int r = TCL_OK;
    DWORD myPid;
    (void)dummy;

    Tcl_DStringInit(&classString);
    Tcl_DStringInit(&titleString);

    if (objc < 2 || objc > 3) {
        Tcl_WrongNumArgs(interp, 1, objv, "title ?class?");
        return TCL_ERROR;
    }

    Tcl_DStringInit(&titleString);
    title = (LPCWSTR)Tcl_WinUtfToTChar(Tcl_GetString(objv[1]), -1, &titleString);
    title = Tcl_UtfToWCharDString(Tcl_GetString(objv[1]), -1, &titleString);
    if (objc == 3) {
	Tcl_DStringInit(&classString);
        windowClass = (LPCWSTR)Tcl_WinUtfToTChar(Tcl_GetString(objv[2]), -1, &classString);
	windowClass = Tcl_UtfToWCharDString(Tcl_GetString(objv[2]), -1, &classString);
    }
    if (title[0] == 0)
        title = NULL;
    /* We want find a window the belongs to us and not some other process */
    hwnd = NULL;
    myPid = GetCurrentProcessId();
    while (1) {
471
472
473
474
475
476
477
478

479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494

495
496
497
498
499
500

501
502
503
504
505
506
507
508
509
510

511
512
513
514
515
516
517
518
519
520

521
522
523
524
525
526
527


528
529
530
531
532
533
534
535

536
537
538



539
540
541
542
543
544

545
546
547

548
549
550
551
552
553
554
555
556

557
558
559
560


561
562
563
564
565

566
567
568
569
570
571
572
573
574
575
489
490
491
492
493
494
495

496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511

512
513
514
515
516
517

518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538

539
540
541
542
543
544


545
546
547
548
549
550
551
552
553

554
555


556
557
558
559
560
561
562
563

564
565
566

567
568
569
570
571
572
573
574
575

576
577
578
579
580
581
582
583
584
585
586

587
588
589
590
591
592
593
594
595
596
597







-
+















-
+





-
+










+









-
+





-
-
+
+







-
+

-
-
+
+
+





-
+


-
+








-
+




+
+




-
+










    }

    if (hwnd == NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("failed to find window: ", -1));
	AppendSystemError(interp, GetLastError());
	r = TCL_ERROR;
    } else {
        Tcl_SetObjResult(interp, Tcl_NewWideIntObj((Tcl_WideInt)(((size_t)hwnd) + 1) - 1));
        Tcl_SetObjResult(interp, Tcl_NewWideIntObj(PTR2INT(hwnd)));
    }

    Tcl_DStringFree(&titleString);
    Tcl_DStringFree(&classString);
    return r;

}

static BOOL CALLBACK
EnumChildrenProc(
    HWND hwnd,
    LPARAM lParam)
{
    Tcl_Obj *listObj = (Tcl_Obj *) lParam;

    Tcl_ListObjAppendElement(NULL, listObj, Tcl_NewWideIntObj((Tcl_WideInt)(((size_t)hwnd) + 1) - 1));
    Tcl_ListObjAppendElement(NULL, listObj, Tcl_NewWideIntObj(PTR2INT(hwnd)));
    return TRUE;
}

static int
TestgetwindowinfoObjCmd(
    ClientData clientData,
    ClientData dummy,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_WideInt hwnd;
    Tcl_Obj *dictObj = NULL, *classObj = NULL, *textObj = NULL;
    Tcl_Obj *childrenObj = NULL;
    WCHAR buf[512];
    int cch, cchBuf = 256;
    Tcl_DString ds;
    (void)dummy;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "hwnd");
	return TCL_ERROR;
    }

    if (Tcl_GetWideIntFromObj(interp, objv[1], &hwnd) != TCL_OK)
	return TCL_ERROR;

    cch = GetClassNameW(INT2PTR(hwnd), buf, cchBuf);
    cch = GetClassNameW((HWND)INT2PTR(hwnd), buf, cchBuf);
    if (cch == 0) {
    	Tcl_SetObjResult(interp, Tcl_NewStringObj("failed to get class name: ", -1));
    	AppendSystemError(interp, GetLastError());
    	return TCL_ERROR;
    } else {
	Tcl_DString ds;
	Tcl_WinTCharToUtf((LPCTSTR)buf, -1, &ds);
	Tcl_DStringInit(&ds);
	Tcl_WCharToUtfDString(buf, wcslen(buf), &ds);
	classObj = Tcl_NewStringObj(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds));
	Tcl_DStringFree(&ds);
    }

    dictObj = Tcl_NewDictObj();
    Tcl_DictObjPut(interp, dictObj, Tcl_NewStringObj("class", 5), classObj);
    Tcl_DictObjPut(interp, dictObj, Tcl_NewStringObj("id", 2),
	    Tcl_NewWideIntObj(GetWindowLongPtrW(INT2PTR(hwnd), GWL_ID)));
	Tcl_NewWideIntObj(GetWindowLongPtr((HWND)(size_t)hwnd, GWL_ID)));

    cch = GetWindowTextW(INT2PTR(hwnd), buf, cchBuf);
    Tcl_WinTCharToUtf((LPCTSTR)buf, cch * sizeof (WCHAR), &ds);
    cch = GetWindowTextW((HWND)INT2PTR(hwnd), buf, cchBuf);
	Tcl_DStringInit(&ds);
    Tcl_WCharToUtfDString(buf, cch, &ds);
    textObj = Tcl_NewStringObj(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds));
    Tcl_DStringFree(&ds);

    Tcl_DictObjPut(interp, dictObj, Tcl_NewStringObj("text", 4), textObj);
    Tcl_DictObjPut(interp, dictObj, Tcl_NewStringObj("parent", 6),
	    Tcl_NewWideIntObj((Tcl_WideInt)(((size_t)GetParent((INT2PTR(hwnd)))) + 1) - 1));
	Tcl_NewWideIntObj(PTR2INT(GetParent((HWND)(size_t)hwnd))));

    childrenObj = Tcl_NewListObj(0, NULL);
    EnumChildWindows(INT2PTR(hwnd), EnumChildrenProc, (LPARAM)childrenObj);
    EnumChildWindows((HWND)(size_t)hwnd, EnumChildrenProc, (LPARAM)childrenObj);
    Tcl_DictObjPut(interp, dictObj, Tcl_NewStringObj("children", -1), childrenObj);

    Tcl_SetObjResult(interp, dictObj);
    return TCL_OK;
}

static int
TestwinlocaleObjCmd(
    ClientData clientData,	/* Main window for application. */
    ClientData dummy,	/* Main window for application. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument values. */
{
    (void)dummy;

    if (objc != 1) {
	Tcl_WrongNumArgs(interp, 1, objv, NULL);
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, Tcl_NewIntObj((int)GetThreadLocale()));
    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetThreadLocale()));
    return TCL_OK;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Changes to win/tkWinWindow.c.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







/*
 * tkWinWindow.c --
 *
 *	Xlib emulation routines for Windows related to creating, displaying
 *	and destroying windows.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright © 1995-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.
 */

#include "tkWinInt.h"
#include "tkBusy.h"
45
46
47
48
49
50
51
52

53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69

70
71
72
73
74

75
76
77
78
79
80
81
82
83

84
85
86
87
88
89
90
45
46
47
48
49
50
51

52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68

69
70
71
72
73

74
75
76
77
78
79
80
81
82

83
84
85
86
87
88
89
90







-
+
















-
+




-
+








-
+







 */

Window
Tk_AttachHWND(
    Tk_Window tkwin,
    HWND hwnd)
{
    int new;
    int isNew;
    Tcl_HashEntry *entryPtr;
    TkWinDrawable *twdPtr = (TkWinDrawable *) Tk_WindowId(tkwin);
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (!tsdPtr->initialized) {
	Tcl_InitHashTable(&tsdPtr->windowTable, TCL_ONE_WORD_KEYS);
	tsdPtr->initialized = 1;
    }

    /*
     * Allocate a new drawable if necessary. Otherwise, remove the previous
     * HWND from from the window table.
     */

    if (twdPtr == NULL) {
	twdPtr = ckalloc(sizeof(TkWinDrawable));
	twdPtr = (TkWinDrawable *)ckalloc(sizeof(TkWinDrawable));
	twdPtr->type = TWD_WINDOW;
	twdPtr->window.winPtr = (TkWindow *) tkwin;
    } else if (twdPtr->window.handle != NULL) {
	entryPtr = Tcl_FindHashEntry(&tsdPtr->windowTable,
		(char *)twdPtr->window.handle);
		twdPtr->window.handle);
	Tcl_DeleteHashEntry(entryPtr);
    }

    /*
     * Insert the new HWND into the window table.
     */

    twdPtr->window.handle = hwnd;
    entryPtr = Tcl_CreateHashEntry(&tsdPtr->windowTable, (char *)hwnd, &new);
    entryPtr = Tcl_CreateHashEntry(&tsdPtr->windowTable, (char *)hwnd, &isNew);
    Tcl_SetHashValue(entryPtr, tkwin);

    return (Window)twdPtr;
}

/*
 *----------------------------------------------------------------------
111
112
113
114
115
116
117
118

119
120
121
122
123
124
125
111
112
113
114
115
116
117

118
119
120
121
122
123
124
125







-
+







    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (!tsdPtr->initialized) {
	Tcl_InitHashTable(&tsdPtr->windowTable, TCL_ONE_WORD_KEYS);
	tsdPtr->initialized = 1;
    }
    entryPtr = Tcl_FindHashEntry(&tsdPtr->windowTable, (char *) hwnd);
    entryPtr = Tcl_FindHashEntry(&tsdPtr->windowTable, hwnd);
    if (entryPtr != NULL) {
	return (Tk_Window) Tcl_GetHashValue(entryPtr);
    }
    return NULL;
}

/*
310
311
312
313
314
315
316
317

318
319
320
321
322
323
324
310
311
312
313
314
315
316

317
318
319
320
321
322
323
324







-
+







    /*
     * Remove references to the window in the pointer module then release the
     * drawable.
     */

    TkPointerDeadWindow(winPtr);

    entryPtr = Tcl_FindHashEntry(&tsdPtr->windowTable, (char*)hwnd);
    entryPtr = Tcl_FindHashEntry(&tsdPtr->windowTable, hwnd);
    if (entryPtr != NULL) {
	Tcl_DeleteHashEntry(entryPtr);
    }

    ckfree(twdPtr);

    /*
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
748
749
750
751
752
753
754



























755
756
757
758
759
760
761







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







    XSetWindowAttributes* attributes)
{
    if (valueMask & CWCursor) {
	XDefineCursor(display, w, attributes->cursor);
    }
    return Success;
}

/*
 *----------------------------------------------------------------------
 *
 * XReparentWindow --
 *
 *	TODO: currently placeholder to satisfy Xlib stubs.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	TODO.
 *
 *----------------------------------------------------------------------
 */

int
XReparentWindow(
    Display *display,
    Window w,
    Window parent,
    int x,
    int y)
{
    return BadWindow;
}

/*
 *----------------------------------------------------------------------
 *
 * TkWinSetWindowPos --
 *
 *	Adjust the stacking order of a window relative to a second window (or
Changes to win/tkWinWm.c.
1
2
3
4
5
6
7
8
9
10


11
12
13
14
15
16

17
18
19
20
21
22
23
1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24








-
-
+
+






+







/*
 * tkWinWm.c --
 *
 *	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) 1995-1997 Sun Microsystems, Inc.
 * Copyright (c) 1998-2000 by Scriptics Corporation.
 * Copyright © 1995-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.
 */

#include "tkWinInt.h"
#include "tkWinIco.h"
#include <shellapi.h>

/*
 * These next two defines are only valid on Win2K/XP+.
 */

#ifndef WS_EX_LAYERED
53
54
55
56
57
58
59
60
61


62
63
64
65
66
67
68
69

70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
54
55
56
57
58
59
60


61
62
63
64
65
66
67
68
69

70
71
72
73
74
75
76
77
78
79
80




















































81
82
83
84
85
86
87







-
-
+
+







-
+










-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-








typedef struct ProtocolHandler {
    Atom protocol;		/* Identifies the protocol. */
    struct ProtocolHandler *nextPtr;
				/* Next in list of protocol handlers for the
				 * same top-level window, or NULL for end of
				 * list. */
    Tcl_Interp *interp;		/* Interpreter in which to invoke command. */
    char command[1];		/* Tcl command to invoke when a client message
    Tcl_Interp *interp;	/* Interpreter in which to invoke command. */
    char command[TKFLEXARRAY];	/* Tcl command to invoke when a client message
				 * for this protocol arrives. The actual size
				 * of the structure varies to accommodate the
				 * needs of the actual command. THIS MUST BE
				 * THE LAST FIELD OF THE STRUCTURE. */
} ProtocolHandler;

#define HANDLER_SIZE(cmdLength) \
    ((unsigned) ((Tk_Offset(ProtocolHandler, command) + 1) + cmdLength))
    (offsetof(ProtocolHandler, command) + 1 + cmdLength)

/*
 * Helper type passed via lParam to TkWmStackorderToplevelEnumProc
 */

typedef struct TkWmStackorderToplevelPair {
    Tcl_HashTable *table;
    TkWindow **windowPtr;
} TkWmStackorderToplevelPair;

/*
 * This structure represents the contents of a icon, in terms of its image.
 * The HICON is an internal Windows format. Most of these icon-specific
 * structures originated with the Winico extension. We stripped out unused
 * parts of that code, and integrated the code more naturally with Tcl.
 */

typedef struct {
    UINT Width, Height, Colors;	/* Width, Height and bpp */
    LPBYTE lpBits;		/* Ptr to DIB bits */
    DWORD dwNumBytes;		/* How many bytes? */
    LPBITMAPINFO lpbi;		/* Ptr to header */
    LPBYTE lpXOR;		/* Ptr to XOR image bits */
    LPBYTE lpAND;		/* Ptr to AND image bits */
    HICON hIcon;		/* DAS ICON */
} ICONIMAGE, *LPICONIMAGE;

/*
 * This structure is how we represent a block of the above items. We will
 * reallocate these structures according to how many images they need to
 * contain.
 */

typedef struct {
    int nNumImages;		/* How many images? */
    ICONIMAGE IconImages[1];	/* Image entries */
} BlockOfIconImages, *BlockOfIconImagesPtr;

/*
 * These two structures are used to read in icons from an 'icon directory'
 * (i.e. the contents of a .icr file, say). We only use these structures
 * temporarily, since we copy the information we want into a
 * BlockOfIconImages.
 */

typedef struct {
    BYTE bWidth;		/* Width of the image */
    BYTE bHeight;		/* Height of the image (times 2) */
    BYTE bColorCount;		/* Number of colors in image (0 if >=8bpp) */
    BYTE bReserved;		/* Reserved */
    WORD wPlanes;		/* Color Planes */
    WORD wBitCount;		/* Bits per pixel */
    DWORD dwBytesInRes;		/* How many bytes in this resource? */
    DWORD dwImageOffset;	/* Where in the file is this image */
} ICONDIRENTRY, *LPICONDIRENTRY;

typedef struct {
    WORD idReserved;		/* Reserved */
    WORD idType;		/* Resource type (1 for icons) */
    WORD idCount;		/* How many images? */
    ICONDIRENTRY idEntries[1];	/* The entries for each image */
} ICONDIR, *LPICONDIR;

/*
 * A pointer to one of these strucutures is associated with each toplevel.
 * This allows us to free up all memory associated with icon resources when a
 * window is deleted or if the window's icon is changed. They are simply
 * reference counted according to:
 *
173
174
175
176
177
178
179
180

181
182
183
184
185
186
187
122
123
124
125
126
127
128

129
130
131
132
133
134
135
136







-
+







    char *iconName;		/* Name to display in icon. Malloced. */
    XWMHints hints;		/* Various pieces of information for window
				 * manager. */
    char *leaderName;		/* Path name of leader of window group
				 * (corresponds to hints.window_group).
				 * Malloc-ed. Note: this field doesn't get
				 * updated if leader is destroyed. */
    TkWindow *masterPtr;	/* Master window for TRANSIENT_FOR property,
    TkWindow *containerPtr;	/* Container window for TRANSIENT_FOR property,
				 * or NULL. */
    Tk_Window icon;		/* Window to use as icon for this window, or
				 * NULL. */
    Tk_Window iconFor;		/* Window for which this window is icon, or
				 * NULL if this isn't an icon for anyone. */

    /*
311
312
313
314
315
316
317
318

319
320
321
322
323
324
325
260
261
262
263
264
265
266

267
268
269
270
271
272
273
274







-
+







 *				allow the user to change the width of the
 *				window (controlled by "wm resizable" command).
 * WM_HEIGHT_NOT_RESIZABLE -	Non-zero means that we're not supposed to
 *				allow the user to change the height of the
 *				window (controlled by "wm resizable" command).
 * WM_WITHDRAWN -		Non-zero means that this window has explicitly
 *				been withdrawn. If it's a transient, it should
 *				not mirror state changes in the master.
 *				not mirror state changes in the container.
 * WM_FULLSCREEN -		Non-zero means that this window has been placed
 *				in the full screen mode. It should be mapped at
 *				0,0 and be the width and height of the screen.
 */

#define WM_NEVER_MAPPED			(1<<0)
#define WM_UPDATE_PENDING		(1<<1)
360
361
362
363
364
365
366
367

368
369
370
371
372
373
374
309
310
311
312
313
314
315

316
317
318
319
320
321
322
323







-
+








static void		TopLevelReqProc(ClientData dummy, Tk_Window tkwin);
static void		RemapWindows(TkWindow *winPtr, HWND parentHWND);

static const Tk_GeomMgr wmMgrType = {
    "wm",			/* name */
    TopLevelReqProc,		/* requestProc */
    NULL,			/* lostSlaveProc */
    NULL,			/* lostContentProc */
};

typedef struct {
    HPALETTE systemPalette;	/* System palette; refers to the currently
				 * installed foreground logical palette. */
    TkWindow *createWindow;	/* Window that is being constructed. This
				 * value is set immediately before a call to
432
433
434
435
436
437
438

439
440
441
442
443
444
445
446
447
448
381
382
383
384
385
386
387
388
389
390

391
392
393
394
395
396
397







+


-







			    WPARAM wParam, LPARAM lParam);
static void		WmWaitVisibilityOrMapProc(ClientData clientData,
			    XEvent *eventPtr);
static BlockOfIconImagesPtr ReadIconOrCursorFromFile(Tcl_Interp *interp,
			    Tcl_Obj* fileName, BOOL isIcon);
static WinIconPtr	ReadIconFromFile(Tcl_Interp *interp,
			    Tcl_Obj *fileName);
static BOOL		AdjustIconImagePointers(LPICONIMAGE lpImage);
static WinIconPtr	GetIconFromPixmap(Display *dsPtr, Pixmap pixmap);
static int		ReadICOHeader(Tcl_Channel channel);
static BOOL		AdjustIconImagePointers(LPICONIMAGE lpImage);
static HICON		MakeIconOrCursorFromResource(LPICONIMAGE lpIcon,
			    BOOL isIcon);
static HICON		GetIcon(WinIconPtr titlebaricon, int icon_size);
static int		WinSetIcon(Tcl_Interp *interp,
			    WinIconPtr titlebaricon, Tk_Window tkw);
static void		FreeIconBlock(BlockOfIconImagesPtr lpIR);
static void		DecrIconRefCount(WinIconPtr titlebaricon);
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
489
490
491
492
493
494
495





















































































































































































496
497
498
499
500
501
502







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







static int		WmTransientCmd(Tk_Window tkwin,
			    TkWindow *winPtr, Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static int		WmWithdrawCmd(Tk_Window tkwin,
			    TkWindow *winPtr, Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static void		WmUpdateGeom(WmInfo *wmPtr, TkWindow *winPtr);

/*
 * Used in BytesPerLine
 */

#define WIDTHBYTES(bits)	((((bits) + 31)>>5)<<2)

/*
 *----------------------------------------------------------------------
 *
 * DIBNumColors --
 *
 *	Calculates the number of entries in the color table, given by LPSTR
 *	lpbi - pointer to the CF_DIB memory block. Used by titlebar icon code.
 *
 * Results:
 *	WORD - Number of entries in the color table.
 *
 *----------------------------------------------------------------------
 */

static WORD
DIBNumColors(
    LPSTR lpbi)
{
    WORD wBitCount;
    DWORD dwClrUsed;

    dwClrUsed = ((LPBITMAPINFOHEADER) lpbi)->biClrUsed;

    if (dwClrUsed) {
	return (WORD) dwClrUsed;
    }

    wBitCount = ((LPBITMAPINFOHEADER) lpbi)->biBitCount;

    switch (wBitCount) {
    case 1:
	return 2;
    case 4:
	return 16;
    case 8:
	return 256;
    default:
	return 0;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * PaletteSize --
 *
 *	Calculates the number of bytes in the color table, as given by LPSTR
 *	lpbi - pointer to the CF_DIB memory block. Used by titlebar icon code.
 *
 * Results:
 *	Number of bytes in the color table
 *
 *----------------------------------------------------------------------
 */
static WORD
PaletteSize(
    LPSTR lpbi)
{
    return (WORD) (DIBNumColors(lpbi) * sizeof(RGBQUAD));
}

/*
 *----------------------------------------------------------------------
 *
 * FindDIBits --
 *
 *	Locate the image bits in a CF_DIB format DIB, as given by LPSTR lpbi -
 *	pointer to the CF_DIB memory block. Used by titlebar icon code.
 *
 * Results:
 *	pointer to the image bits
 *
 * Side effects: None
 *
 *
 *----------------------------------------------------------------------
 */

static LPSTR
FindDIBBits(
    LPSTR lpbi)
{
    return lpbi + *((LPDWORD) lpbi) + PaletteSize(lpbi);
}

/*
 *----------------------------------------------------------------------
 *
 * BytesPerLine --
 *
 *	Calculates the number of bytes in one scan line, as given by
 *	LPBITMAPINFOHEADER lpBMIH - pointer to the BITMAPINFOHEADER that
 *	begins the CF_DIB block. Used by titlebar icon code.
 *
 * Results:
 *	number of bytes in one scan line (DWORD aligned)
 *
 *----------------------------------------------------------------------
 */

static DWORD
BytesPerLine(
    LPBITMAPINFOHEADER lpBMIH)
{
    return WIDTHBYTES(lpBMIH->biWidth * lpBMIH->biPlanes * lpBMIH->biBitCount);
}

/*
 *----------------------------------------------------------------------
 *
 * AdjustIconImagePointers --
 *
 *	Adjusts internal pointers in icon resource struct, as given by
 *	LPICONIMAGE lpImage - the resource to handle. Used by titlebar icon
 *	code.
 *
 * Results:
 *	BOOL - TRUE for success, FALSE for failure
 *
 *----------------------------------------------------------------------
 */

static BOOL
AdjustIconImagePointers(
    LPICONIMAGE lpImage)
{
    /*
     * Sanity check.
     */

    if (lpImage == NULL) {
	return FALSE;
    }

    /*
     * BITMAPINFO is at beginning of bits.
     */

    lpImage->lpbi = (LPBITMAPINFO) lpImage->lpBits;

    /*
     * Width - simple enough.
     */

    lpImage->Width = lpImage->lpbi->bmiHeader.biWidth;

    /*
     * Icons are stored in funky format where height is doubled so account for
     * that.
     */

    lpImage->Height = (lpImage->lpbi->bmiHeader.biHeight)/2;

    /*
     * How many colors?
     */

    lpImage->Colors = lpImage->lpbi->bmiHeader.biPlanes
	    * lpImage->lpbi->bmiHeader.biBitCount;

    /*
     * XOR bits follow the header and color table.
     */

    lpImage->lpXOR = (LPBYTE) FindDIBBits((LPSTR) lpImage->lpbi);

    /*
     * AND bits follow the XOR bits.
     */

    lpImage->lpAND = lpImage->lpXOR +
	    lpImage->Height*BytesPerLine((LPBITMAPINFOHEADER) lpImage->lpbi);
    return TRUE;
}

/*
 *----------------------------------------------------------------------
 *
 * MakeIconOrCursorFromResource --
 *
 *	Construct an actual HICON structure from the information in a
852
853
854
855
856
857
858
859

860
861
862
863
864
865
866
620
621
622
623
624
625
626

627
628
629
630
631
632
633
634







-
+







 *----------------------------------------------------------------------
 */

static int
InitWindowClass(
    WinIconPtr titlebaricon)
{
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (!tsdPtr->initialized) {
	tsdPtr->initialized = 1;
	tsdPtr->firstWindow = 1;
	tsdPtr->iconPtr = NULL;
    }
1113
1114
1115
1116
1117
1118
1119
1120

1121
1122
1123
1124
1125
1126
1127
881
882
883
884
885
886
887

888
889
890
891
892
893
894
895







-
+







HICON
TkWinGetIcon(
    Tk_Window tkwin,
    DWORD iconsize)
{
    WmInfo *wmPtr;
    HICON icon;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (tsdPtr->iconPtr != NULL) {
	/*
	 * return default toplevel icon
	 */

1237
1238
1239
1240
1241
1242
1243
1244
1245
1246


1247

1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263

1264
1265
1266
1267
1268
1269
1270
1005
1006
1007
1008
1009
1010
1011



1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030

1031
1032
1033
1034
1035
1036
1037
1038







-
-
-
+
+

+















-
+







	DWORD *res;
	const char *file;

	file = Tcl_TranslateFileName(interp, Tcl_GetString(fileName), &ds);
	if (file == NULL) {
	    return NULL;
	}
	Tcl_WinUtfToTChar(file, -1, &ds2);
	Tcl_DStringFree(&ds);
	res = (DWORD *)SHGetFileInfoW((WCHAR *)Tcl_DStringValue(&ds2), 0, &sfiSM,
	Tcl_DStringInit(&ds2);
	res = (DWORD *)SHGetFileInfoW(Tcl_UtfToWCharDString(file, -1, &ds2), 0, &sfiSM,
		sizeof(SHFILEINFO), SHGFI_SMALLICON|SHGFI_ICON);
	Tcl_DStringFree(&ds);

	if (res != 0) {
	    SHFILEINFOW sfi;
	    unsigned size;

	    Tcl_ResetResult(interp);
	    res = (DWORD *)SHGetFileInfoW((WCHAR *)Tcl_DStringValue(&ds2), 0, &sfi,
		    sizeof(SHFILEINFO), SHGFI_ICON);

	    /*
	     * Account for extra icon, if necessary.
	     */

	    size = sizeof(BlockOfIconImages)
		    + ((res != 0) ? sizeof(ICONIMAGE) : 0);
	    lpIR = ckalloc(size);
	    lpIR = (BlockOfIconImagesPtr)ckalloc(size);
	    if (lpIR == NULL) {
		if (res != 0) {
		    DestroyIcon(sfi.hIcon);
		}
		DestroyIcon(sfiSM.hIcon);
		Tcl_DStringFree(&ds2);
		return NULL;
1287
1288
1289
1290
1291
1292
1293
1294

1295
1296
1297
1298
1299
1300





































































1301
1302
1303
1304
1305
1306
1307
1055
1056
1057
1058
1059
1060
1061

1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144







-
+






+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







		lpIR->IconImages[1].Colors	= 4;
		lpIR->IconImages[1].hIcon	= sfi.hIcon;
	    }
	}
	Tcl_DStringFree(&ds2);
    }
    if (lpIR != NULL) {
	titlebaricon = ckalloc(sizeof(WinIconInstance));
	titlebaricon = (WinIconPtr)ckalloc(sizeof(WinIconInstance));
	titlebaricon->iconBlock = lpIR;
	titlebaricon->refCount = 1;
    }
    return titlebaricon;
}


/*
 *----------------------------------------------------------------------
 *
 * AdjustIconImagePointers --
 *
 *	Adjusts internal pointers in icon resource struct, as given by
 *	LPICONIMAGE lpImage - the resource to handle. Used by titlebar icon
 *	code.
 *
 * Results:
 *	BOOL - TRUE for success, FALSE for failure
 *
 *----------------------------------------------------------------------
 */

static BOOL
AdjustIconImagePointers(
    LPICONIMAGE lpImage)
{
    /*
     * Sanity check.
     */

    if (lpImage == NULL) {
	return FALSE;
    }

    /*
     * BITMAPINFO is at beginning of bits.
     */

    lpImage->lpbi = (LPBITMAPINFO) lpImage->lpBits;

    /*
     * Width - simple enough.
     */

    lpImage->Width = lpImage->lpbi->bmiHeader.biWidth;

    /*
     * Icons are stored in funky format where height is doubled so account for
     * that.
     */

    lpImage->Height = (lpImage->lpbi->bmiHeader.biHeight)/2;

    /*
     * How many colors?
     */

    lpImage->Colors = lpImage->lpbi->bmiHeader.biPlanes
	    * lpImage->lpbi->bmiHeader.biBitCount;

    /*
     * XOR bits follow the header and color table.
     */

    lpImage->lpXOR = (LPBYTE) FindDIBBits((LPSTR) lpImage->lpbi);

    /*
     * AND bits follow the XOR bits.
     */

    lpImage->lpAND = lpImage->lpXOR +
	    lpImage->Height*BytesPerLine((LPBITMAPINFOHEADER) lpImage->lpbi);
    return TRUE;
}

/*
 *----------------------------------------------------------------------
 *
 * GetIconFromPixmap --
 *
 *	Turn a Tk Pixmap (i.e. a bitmap) into an icon resource, if possible,
 *	otherwise NULL is returned.
1363
1364
1365
1366
1367
1368
1369
1370

1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391

1392
1393
1394
1395
1396
1397
1398
1200
1201
1202
1203
1204
1205
1206

1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227

1228
1229
1230
1231
1232
1233
1234
1235







-
+




















-
+







    icon.hbmColor = twdPtr->bitmap.handle;

    hIcon = CreateIconIndirect(&icon);
    if (hIcon == NULL) {
	return NULL;
    }

    lpIR = ckalloc(sizeof(BlockOfIconImages));
    lpIR = (BlockOfIconImagesPtr)ckalloc(sizeof(BlockOfIconImages));
    if (lpIR == NULL) {
	DestroyIcon(hIcon);
	return NULL;
    }

    lpIR->nNumImages = 1;
    lpIR->IconImages[0].Width = width;
    lpIR->IconImages[0].Height = height;
    lpIR->IconImages[0].Colors = 1 << twdPtr->bitmap.depth;
    lpIR->IconImages[0].hIcon = hIcon;

    /*
     * These fields are ignored.
     */

    lpIR->IconImages[0].lpBits = 0;
    lpIR->IconImages[0].dwNumBytes = 0;
    lpIR->IconImages[0].lpXOR = 0;
    lpIR->IconImages[0].lpAND = 0;

    titlebaricon = ckalloc(sizeof(WinIconInstance));
    titlebaricon = (WinIconPtr)ckalloc(sizeof(WinIconInstance));
    titlebaricon->iconBlock = lpIR;
    titlebaricon->refCount = 1;
    return titlebaricon;
}

/*
 *----------------------------------------------------------------------
1589
1590
1591
1592
1593
1594
1595
1596

1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614

1615
1616
1617
1618
1619
1620
1621

1622
1623
1624
1625
1626
1627
1628
1426
1427
1428
1429
1430
1431
1432

1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450

1451
1452
1453
1454
1455
1456
1457

1458
1459
1460
1461
1462
1463
1464
1465







-
+

















-
+






-
+







	return NULL;
    }

    /*
     * Allocate memory for the resource structure
     */

    lpIR = ckalloc(sizeof(BlockOfIconImages));
    lpIR = (BlockOfIconImagesPtr)ckalloc(sizeof(BlockOfIconImages));

    /*
     * Read in the header
     */

    lpIR->nNumImages = ReadICOHeader(channel);
    if (lpIR->nNumImages == -1) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("Invalid file header", -1));
	Tcl_Close(NULL, channel);
	ckfree(lpIR);
	return NULL;
    }

    /*
     * Adjust the size of the struct to account for the images.
     */

    lpIR = ckrealloc(lpIR, sizeof(BlockOfIconImages)
    lpIR = (BlockOfIconImagesPtr)ckrealloc(lpIR, sizeof(BlockOfIconImages)
	    + (lpIR->nNumImages - 1) * sizeof(ICONIMAGE));

    /*
     * Allocate enough memory for the icon directory entries.
     */

    lpIDE = ckalloc(lpIR->nNumImages * sizeof(ICONDIRENTRY));
    lpIDE = (LPICONDIRENTRY)ckalloc(lpIR->nNumImages * sizeof(ICONDIRENTRY));

    /*
     * Read in the icon directory entries.
     */

    dwBytesRead = Tcl_Read(channel, (char *) lpIDE,
	    (int) (lpIR->nNumImages * sizeof(ICONDIRENTRY)));
1649
1650
1651
1652
1653
1654
1655
1656

1657
1658
1659
1660
1661
1662
1663
1486
1487
1488
1489
1490
1491
1492

1493
1494
1495
1496
1497
1498
1499
1500







-
+







     */

    for (i=0 ; i<lpIR->nNumImages ; i++) {
	/*
	 * Allocate memory for the resource.
	 */

	lpIR->IconImages[i].lpBits = ckalloc(lpIDE[i].dwBytesInRes);
	lpIR->IconImages[i].lpBits = (LPBYTE)ckalloc(lpIDE[i].dwBytesInRes);
	lpIR->IconImages[i].dwNumBytes = lpIDE[i].dwBytesInRes;

	/*
	 * Seek to beginning of this image.
	 */

	if (Tcl_Seek(channel, lpIDE[i].dwImageOffset, FILE_BEGIN) == -1) {
1728
1729
1730
1731
1732
1733
1734
1735

1736
1737
1738
1739
1740
1741
1742
1565
1566
1567
1568
1569
1570
1571

1572
1573
1574
1575
1576
1577
1578
1579







-
+







 *----------------------------------------------------------------------
 */

static TkWindow *
GetTopLevel(
    HWND hwnd)
{
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    /*
     * If this function is called before the CreateWindowEx call has
     * completed, then the user data slot will not have been set yet, so we
     * use the global createWindow variable.
     */
1765
1766
1767
1768
1769
1770
1771
1772

1773
1774
1775
1776
1777
1778
1779
1602
1603
1604
1605
1606
1607
1608

1609
1610
1611
1612
1613
1614
1615
1616







-
+







 */

static void
SetLimits(
    HWND hwnd,
    MINMAXINFO *info)
{
    register WmInfo *wmPtr;
    WmInfo *wmPtr;
    int maxWidth, maxHeight;
    int minWidth, minHeight;
    int base;
    TkWindow *winPtr = GetTopLevel(hwnd);

    if (winPtr == NULL) {
	return;
1870
1871
1872
1873
1874
1875
1876
1877

1878
1879
1880
1881
1882
1883
1884
1707
1708
1709
1710
1711
1712
1713

1714
1715
1716
1717
1718
1719
1720
1721







-
+







#endif

    if (!initialized) {
	return;
    }
    initialized = 0;

    tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    tsdPtr = (ThreadSpecificData *)Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (!tsdPtr->initialized) {
	return;
    }
    tsdPtr->initialized = 0;

    UnregisterClassW(TK_WIN_TOPLEVEL_CLASS_NAME, hInstance);
1901
1902
1903
1904
1905
1906
1907
1908

1909
1910
1911
1912
1913
1914
1915
1738
1739
1740
1741
1742
1743
1744

1745
1746
1747
1748
1749
1750
1751
1752







-
+







 *--------------------------------------------------------------
 */

void
TkWmNewWindow(
    TkWindow *winPtr)		/* Newly-created top-level window. */
{
    register WmInfo *wmPtr = ckalloc(sizeof(WmInfo));
    WmInfo *wmPtr = (WmInfo *)ckalloc(sizeof(WmInfo));

    /*
     * Initialize full structure, then set what isn't NULL
     */

    ZeroMemory(wmPtr, sizeof(WmInfo));
    winPtr->wmInfoPtr = wmPtr;
1986
1987
1988
1989
1990
1991
1992
1993

1994
1995
1996
1997
1998
1999
2000
2001
2002

2003
2004
2005
2006
2007
2008
2009
1823
1824
1825
1826
1827
1828
1829

1830
1831
1832
1833
1834
1835
1836
1837
1838

1839
1840
1841
1842
1843
1844
1845
1846







-
+








-
+







 *----------------------------------------------------------------------
 */

static void
UpdateWrapper(
    TkWindow *winPtr)		/* Top-level window to redecorate. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    HWND parentHWND, oldWrapper = wmPtr->wrapper;
    HWND child, nextHWND, focusHWND;
    int x, y, width, height, state;
    WINDOWPLACEMENT place;
    HICON hSmallIcon = NULL;
    HICON hBigIcon = NULL;
    Tcl_DString titleString;
    int *childStateInfo = NULL;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (winPtr->window == None) {
	/*
	 * Ensure existence of the window to update the wrapper for.
	 */

2033
2034
2035
2036
2037
2038
2039
2040

2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057

2058
2059
2060
2061
2062
2063
2064
2065

2066
2067
2068

2069
2070
2071
2072
2073
2074
2075
1870
1871
1872
1873
1874
1875
1876

1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893

1894
1895
1896
1897
1898
1899
1900
1901

1902
1903
1904

1905
1906
1907
1908
1909
1910
1911
1912







-
+
















-
+







-
+


-
+







	    Tcl_Panic("UpdateWrapper: Container was destroyed");
	}
    } else {
	/*
	 * Pick the decorative frame style. Override redirect windows get
	 * created as undecorated popups if they have no transient parent,
	 * otherwise they are children. This allows splash screens to operate
	 * as an independent window, while having dropdows (like for a
	 * as an independent window, while having dropdowns (like for a
	 * combobox) not grab focus away from their parent. Transient windows
	 * get a modal dialog frame. Neither override, nor transient windows
	 * appear in the Windows taskbar. Note that a transient window does
	 * not resize by default, so we need to explicitly add the
	 * WS_THICKFRAME style if we want it to be resizeable.
	 */

	if (winPtr->atts.override_redirect) {
	    wmPtr->style = WM_OVERRIDE_STYLE;
	    wmPtr->exStyle = EX_OVERRIDE_STYLE;

	    /*
	     * Parent must be desktop even if we have a transient parent.
	     */

	    parentHWND = GetDesktopWindow();
	    if (wmPtr->masterPtr) {
	    if (wmPtr->containerPtr) {
		wmPtr->style |= WS_CHILD;
	    } else {
		wmPtr->style |= WS_POPUP;
	    }
	} else if (wmPtr->flags & WM_FULLSCREEN) {
	    wmPtr->style = WM_FULLSCREEN_STYLE;
	    wmPtr->exStyle = EX_FULLSCREEN_STYLE;
	} else if (wmPtr->masterPtr) {
	} else if (wmPtr->containerPtr) {
	    wmPtr->style = WM_TRANSIENT_STYLE;
	    wmPtr->exStyle = EX_TRANSIENT_STYLE;
	    parentHWND = Tk_GetHWND(Tk_WindowId(wmPtr->masterPtr));
	    parentHWND = Tk_GetHWND(Tk_WindowId(wmPtr->containerPtr));
	    if (! ((wmPtr->flags & WM_WIDTH_NOT_RESIZABLE)
		    && (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE))) {
		wmPtr->style |= WS_THICKFRAME;
	    }
	} else {
	    wmPtr->style = WM_TOPLEVEL_STYLE;
	    wmPtr->exStyle = EX_TOPLEVEL_STYLE;
2117
2118
2119
2120
2121
2122
2123

2124

2125
2126
2127
2128
2129
2130
2131
1954
1955
1956
1957
1958
1959
1960
1961

1962
1963
1964
1965
1966
1967
1968
1969







+
-
+








	/*
	 * Create the containing window, and set the user data to point to the
	 * TkWindow.
	 */

	tsdPtr->createWindow = winPtr;
	Tcl_DStringInit(&titleString);
	Tcl_WinUtfToTChar(((wmPtr->title != NULL) ?
	Tcl_UtfToWCharDString(((wmPtr->title != NULL) ?
		wmPtr->title : winPtr->nameUid), -1, &titleString);

	wmPtr->wrapper = CreateWindowExW(wmPtr->exStyle,
		TK_WIN_TOPLEVEL_CLASS_NAME,
		(LPCWSTR) Tcl_DStringValue(&titleString),
		wmPtr->style, x, y, width, height,
		parentHWND, NULL, Tk_GetHINSTANCE(), NULL);
2199
2200
2201
2202
2203
2204
2205
2206

2207
2208
2209
2210
2211

2212
2213
2214
2215

2216
2217
2218
2219
2220
2221
2222
2037
2038
2039
2040
2041
2042
2043

2044
2045
2046
2047
2048

2049
2050
2051
2052

2053
2054
2055
2056
2057
2058
2059
2060







-
+




-
+



-
+







    if (oldWrapper && (oldWrapper != wmPtr->wrapper)
	    && (oldWrapper != GetDesktopWindow())) {
	SetWindowLongPtrW(oldWrapper, GWLP_USERDATA, (LONG_PTR) 0);

	if (wmPtr->numTransients > 0) {
	    /*
	     * Unset the current wrapper as the parent for all transient
	     * children for whom this is the master
	     * children for whom this is the container
	     */

	    WmInfo *wmPtr2;

	    childStateInfo = ckalloc(wmPtr->numTransients * sizeof(int));
	    childStateInfo = (int *)ckalloc(wmPtr->numTransients * sizeof(int));
	    state = 0;
	    for (wmPtr2 = winPtr->dispPtr->firstWmPtr; wmPtr2 != NULL;
		    wmPtr2 = wmPtr2->nextPtr) {
		if (wmPtr2->masterPtr == winPtr
		if (wmPtr2->containerPtr == winPtr
			&& !(wmPtr2->flags & WM_NEVER_MAPPED)) {
		    childStateInfo[state++] = wmPtr2->hints.initial_state;
		    SetParent(TkWinGetHWND(wmPtr2->winPtr->window), NULL);
		}
	    }
	}

2287
2288
2289
2290
2291
2292
2293
2294

2295
2296
2297
2298
2299
2300
2301
2302

2303
2304
2305
2306
2307
2308
2309
2125
2126
2127
2128
2129
2130
2131

2132
2133
2134
2135
2136
2137
2138
2139

2140
2141
2142
2143
2144
2145
2146
2147







-
+







-
+







	SetMenu(wmPtr->wrapper, wmPtr->hMenu);
	wmPtr->flags &= ~WM_SYNC_PENDING;
    }

    if (childStateInfo) {
	if (wmPtr->numTransients > 0) {
	    /*
	     * Reset all transient children for whom this is the master.
	     * Reset all transient children for whom this is the container.
	     */

	    WmInfo *wmPtr2;

	    state = 0;
	    for (wmPtr2 = winPtr->dispPtr->firstWmPtr; wmPtr2 != NULL;
		    wmPtr2 = wmPtr2->nextPtr) {
		if (wmPtr2->masterPtr == winPtr
		if (wmPtr2->containerPtr == winPtr
			&& !(wmPtr2->flags & WM_NEVER_MAPPED)) {
		    UpdateWrapper(wmPtr2->winPtr);
		    TkpWmSetState(wmPtr2->winPtr, childStateInfo[state++]);
		}
	    }
	}

2350
2351
2352
2353
2354
2355
2356
2357
2358


2359
2360
2361
2362
2363
2364
2365
2366
2367

2368
2369
2370

2371
2372
2373
2374
2375
2376
2377
2188
2189
2190
2191
2192
2193
2194


2195
2196
2197
2198
2199
2200
2201
2202
2203
2204

2205
2206
2207

2208
2209
2210
2211
2212
2213
2214
2215







-
-
+
+








-
+


-
+







 */

void
TkWmMapWindow(
    TkWindow *winPtr)		/* Top-level window that's about to be
				 * mapped. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    ThreadSpecificData *tsdPtr =
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if (!tsdPtr->initialized) {
	InitWm();
    }

    if (wmPtr->flags & WM_NEVER_MAPPED) {
	/*
	 * Don't map a transient if the master is not mapped.
	 * Don't map a transient if the container is not mapped.
	 */

	if (wmPtr->masterPtr != NULL && !Tk_IsMapped(wmPtr->masterPtr)) {
	if (wmPtr->containerPtr != NULL && !Tk_IsMapped(wmPtr->containerPtr)) {
	    wmPtr->hints.initial_state = WithdrawnState;
	    return;
	}
    } else {
	if (wmPtr->hints.initial_state == WithdrawnState) {
	    return;
	}
2576
2577
2578
2579
2580
2581
2582
2583

2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597

2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612

2613
2614
2615
2616
2617

2618
2619

2620
2621
2622

2623
2624
2625
2626
2627
2628
2629
2414
2415
2416
2417
2418
2419
2420

2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434

2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449

2450
2451
2452
2453
2454

2455
2456

2457
2458
2459

2460
2461
2462
2463
2464
2465
2466
2467







-
+













-
+














-
+




-
+

-
+


-
+







 *--------------------------------------------------------------
 */

void
TkWmDeadWindow(
    TkWindow *winPtr)		/* Top-level window that's being deleted. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr2;

    if (wmPtr == NULL) {
	return;
    }

    /*
     * Clean up event related window info.
     */

    if (winPtr->dispPtr->firstWmPtr == wmPtr) {
	winPtr->dispPtr->firstWmPtr = wmPtr->nextPtr;
    } else {
	register WmInfo *prevPtr;
	WmInfo *prevPtr;

	for (prevPtr = winPtr->dispPtr->firstWmPtr; ;
		prevPtr = prevPtr->nextPtr) {
	    if (prevPtr == NULL) {
		Tcl_Panic("couldn't unlink window in TkWmDeadWindow");
	    }
	    if (prevPtr->nextPtr == wmPtr) {
		prevPtr->nextPtr = wmPtr->nextPtr;
		break;
	    }
	}
    }

    /*
     * Reset all transient windows whose master is the dead window.
     * Reset all transient windows whose container is the dead window.
     */

    for (wmPtr2 = winPtr->dispPtr->firstWmPtr; wmPtr2 != NULL;
	 wmPtr2 = wmPtr2->nextPtr) {
	if (wmPtr2->masterPtr == winPtr) {
	if (wmPtr2->containerPtr == winPtr) {
	    wmPtr->numTransients--;
	    Tk_DeleteEventHandler((Tk_Window) wmPtr2->masterPtr,
	    Tk_DeleteEventHandler((Tk_Window) wmPtr2->containerPtr,
		    VisibilityChangeMask|StructureNotifyMask,
		    WmWaitVisibilityOrMapProc, wmPtr2->winPtr);
	    wmPtr2->masterPtr = NULL;
	    wmPtr2->containerPtr = NULL;
	    if ((wmPtr2->wrapper != NULL)
		    && !(wmPtr2->flags & (WM_NEVER_MAPPED))) {
		UpdateWrapper(wmPtr2->winPtr);
	    }
	}
    }
    if (wmPtr->numTransients != 0)
2665
2666
2667
2668
2669
2670
2671
2672
2673


2674
2675
2676

2677
2678
2679
2680
2681
2682

2683
2684
2685

2686
2687
2688
2689
2690
2691
2692
2503
2504
2505
2506
2507
2508
2509


2510
2511
2512
2513

2514
2515
2516
2517
2518
2519

2520
2521
2522

2523
2524
2525
2526
2527
2528
2529
2530







-
-
+
+


-
+





-
+


-
+







    }
    if (wmPtr->clientMachine != NULL) {
	ckfree(wmPtr->clientMachine);
    }
    if (wmPtr->flags & WM_UPDATE_PENDING) {
	Tcl_CancelIdleCall(UpdateGeometryInfo, winPtr);
    }
    if (wmPtr->masterPtr != NULL) {
	wmPtr2 = wmPtr->masterPtr->wmInfoPtr;
    if (wmPtr->containerPtr != NULL) {
	wmPtr2 = wmPtr->containerPtr->wmInfoPtr;

	/*
	 * If we had a master, tell them that we aren't tied to them anymore.
	 * If we had a container, tell them that we aren't tied to them anymore.
	 */

	if (wmPtr2 != NULL) {
	    wmPtr2->numTransients--;
	}
	Tk_DeleteEventHandler((Tk_Window) wmPtr->masterPtr,
	Tk_DeleteEventHandler((Tk_Window) wmPtr->containerPtr,
		VisibilityChangeMask|StructureNotifyMask,
		WmWaitVisibilityOrMapProc, winPtr);
	wmPtr->masterPtr = NULL;
	wmPtr->containerPtr = NULL;
    }
    if (wmPtr->crefObj != NULL) {
	Tcl_DecrRefCount(wmPtr->crefObj);
	wmPtr->crefObj = NULL;
    }

    /*
2737
2738
2739
2740
2741
2742
2743


2744
2745
2746
2747
2748
2749
2750
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590







+
+







 *--------------------------------------------------------------
 */

void
TkWmSetClass(
    TkWindow *winPtr)		/* Newly-created top-level window. */
{
    (void)winPtr;

    /* Do nothing */
    return;
}

/*
 *----------------------------------------------------------------------
 *
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773

2774
2775
2776
2777
2778
2779
2780
2598
2599
2600
2601
2602
2603
2604

2605
2606
2607
2608
2609
2610
2611

2612
2613
2614
2615
2616
2617
2618
2619







-







-
+







 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
int
Tk_WmObjCmd(
    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;
    static const char *const optionStrings[] = {
	"aspect", "attributes", "client", "colormapwindows",
	"command", "deiconify", "focusmodel", "forget", "frame",
	"geometry", "grid", "group", "iconbitmap",
	"iconify", "iconmask", "iconname",
	"iconphoto", "iconposition",
	"iconwindow", "manage", "maxsize", "minsize", "overrideredirect",
2792
2793
2794
2795
2796
2797
2798
2799

2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810

2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822


2823
2824
2825
2826
2827
2828
2829
2631
2632
2633
2634
2635
2636
2637

2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648

2649

2650
2651
2652
2653
2654
2655
2656
2657
2658


2659
2660
2661
2662
2663
2664
2665
2666
2667







-
+










-
+
-









-
-
+
+







	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,
	WMOPT_WITHDRAW
    };
    int index;
    size_t length;
    TkSizeT length;
    const char *argv1;
    TkWindow *winPtr, **winPtrPtr = &winPtr;
    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;

    if (objc < 2) {
    wrongNumArgs:
	Tcl_WrongNumArgs(interp, 1, objv, "option window ?arg ...?");
	return TCL_ERROR;
    }

    argv1 = Tcl_GetString(objv[1]);
    argv1 = TkGetStringFromObj(objv[1], &length);
    length = objv[1]->length;
    if ((argv1[0] == 't') && !strncmp(argv1, "tracing", length)
	    && (length >= 3)) {
	int wmTracing;

	if ((objc != 2) && (objc != 3)) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?boolean?");
	    return TCL_ERROR;
	}
	if (objc == 2) {
	    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(
		    dispPtr->flags & TK_DISPLAY_WM_TRACING));
	    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(
		    (dispPtr->flags & TK_DISPLAY_WM_TRACING) != 0));
	    return TCL_OK;
	}
	if (Tcl_GetBooleanFromObj(interp, objv[2], &wmTracing) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (wmTracing) {
	    dispPtr->flags |= TK_DISPLAY_WM_TRACING;
2947
2948
2949
2950
2951
2952
2953
2954

2955

2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969




2970
2971
2972
2973
2974
2975
2976
2785
2786
2787
2788
2789
2790
2791

2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804




2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815







-
+

+










-
-
-
-
+
+
+
+







WmAspectCmd(
    Tk_Window tkwin,		/* 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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    int numer1, denom1, numer2, denom2;
    (void)tkwin;

    if ((objc != 3) && (objc != 7)) {
	Tcl_WrongNumArgs(interp, 2, objv,
		"window ?minNumer minDenom maxNumer maxDenom?");
	return TCL_ERROR;
    }
    if (objc == 3) {
	if (wmPtr->sizeHintsFlags & PAspect) {
	    Tcl_Obj *results[4];

	    results[0] = Tcl_NewIntObj(wmPtr->minAspect.x);
	    results[1] = Tcl_NewIntObj(wmPtr->minAspect.y);
	    results[2] = Tcl_NewIntObj(wmPtr->maxAspect.x);
	    results[3] = Tcl_NewIntObj(wmPtr->maxAspect.y);
	    results[0] = Tcl_NewWideIntObj(wmPtr->minAspect.x);
	    results[1] = Tcl_NewWideIntObj(wmPtr->minAspect.y);
	    results[2] = Tcl_NewWideIntObj(wmPtr->maxAspect.x);
	    results[3] = Tcl_NewWideIntObj(wmPtr->maxAspect.y);
	    Tcl_SetObjResult(interp, Tcl_NewListObj(4, results));
	}
	return TCL_OK;
    }
    if (*Tcl_GetString(objv[3]) == '\0') {
	wmPtr->sizeHintsFlags &= ~PAspect;
    } else {
3017
3018
3019
3020
3021
3022
3023
3024

3025
3026
3027
3028

3029
3030
3031
3032
3033
3034
3035
2856
2857
2858
2859
2860
2861
2862

2863
2864
2865
2866

2867
2868
2869
2870
2871
2872
2873
2874







-
+



-
+







WmAttributesCmd(
    Tk_Window tkwin,		/* 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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    LONG style, exStyle, styleBit, *stylePtr = NULL;
    const char *string;
    int i, boolean;
    size_t length;
    TkSizeT length;
    int config_fullscreen = 0, updatewrapper = 0;
    int fullscreen_attr_changed = 0, fullscreen_attr = 0;

    if ((objc < 3) || ((objc > 5) && ((objc%2) == 0))) {
    configArgs:
	Tcl_WrongNumArgs(interp, 2, objv,
		"window"
3051
3052
3053
3054
3055
3056
3057
3058

3059
3060
3061
3062

3063
3064
3065
3066

3067
3068
3069
3070

3071
3072
3073
3074
3075

3076
3077
3078
3079
3080
3081
3082
3083
2890
2891
2892
2893
2894
2895
2896

2897
2898
2899
2900

2901
2902
2903
2904

2905
2906
2907
2908

2909
2910
2911
2912
2913

2914

2915
2916
2917
2918
2919
2920
2921







-
+



-
+



-
+



-
+




-
+
-







	Tcl_ListObjAppendElement(NULL, objPtr,
		Tcl_NewStringObj("-transparentcolor", -1));
	Tcl_ListObjAppendElement(NULL, objPtr,
		wmPtr->crefObj ? wmPtr->crefObj : Tcl_NewObj());
	Tcl_ListObjAppendElement(NULL, objPtr,
		Tcl_NewStringObj("-disabled", -1));
	Tcl_ListObjAppendElement(NULL, objPtr,
		Tcl_NewBooleanObj((style & WS_DISABLED)));
		Tcl_NewWideIntObj((style & WS_DISABLED) != 0));
	Tcl_ListObjAppendElement(NULL, objPtr,
		Tcl_NewStringObj("-fullscreen", -1));
	Tcl_ListObjAppendElement(NULL, objPtr,
		Tcl_NewBooleanObj((wmPtr->flags & WM_FULLSCREEN)));
		Tcl_NewWideIntObj((wmPtr->flags & WM_FULLSCREEN) != 0));
	Tcl_ListObjAppendElement(NULL, objPtr,
		Tcl_NewStringObj("-toolwindow", -1));
	Tcl_ListObjAppendElement(NULL, objPtr,
		Tcl_NewBooleanObj((exStyle & WS_EX_TOOLWINDOW)));
		Tcl_NewWideIntObj((exStyle & WS_EX_TOOLWINDOW) != 0));
	Tcl_ListObjAppendElement(NULL, objPtr,
		Tcl_NewStringObj("-topmost", -1));
	Tcl_ListObjAppendElement(NULL, objPtr,
		Tcl_NewBooleanObj((exStyle & WS_EX_TOPMOST)));
		Tcl_NewWideIntObj((exStyle & WS_EX_TOPMOST) != 0));
	Tcl_SetObjResult(interp, objPtr);
	return TCL_OK;
    }
    for (i = 3; i < objc; i += 2) {
	string = Tcl_GetString(objv[i]);
	string = TkGetStringFromObj(objv[i], &length);
	length = objv[i]->length;
	if ((length < 2) || (string[0] != '-')) {
	    goto configArgs;
	}
	if (strncmp(string, "-disabled", length) == 0) {
	    stylePtr = &style;
	    styleBit = WS_DISABLED;
	} else if ((strncmp(string, "-alpha", length) == 0)
3137
3138
3139
3140
3141
3142
3143
3144

3145
3146
3147
3148
3149
3150
3151
3152
3153
2975
2976
2977
2978
2979
2980
2981

2982
2983

2984
2985
2986
2987
2988
2989
2990







-
+

-







		    if (dval < 0.0) {
			dval = 0;
		    } else if (dval > 1.0) {
			dval = 1;
		    }
		    wmPtr->alpha = dval;
		} else {			/* -transparentcolor */
		    const char *crefstr = Tcl_GetString(objv[i+1]);
		    const char *crefstr = TkGetStringFromObj(objv[i+1], &length);

		    length = objv[i+1]->length;
		    if (length == 0) {
			/* reset to no transparent color */
			if (wmPtr->crefObj) {
			    Tcl_DecrRefCount(wmPtr->crefObj);
			    wmPtr->crefObj = NULL;
			}
		    } else {
3201
3202
3203
3204
3205
3206
3207
3208
3209


3210
3211
3212
3213
3214
3215
3216
3217

3218
3219
3220
3221
3222
3223
3224
3038
3039
3040
3041
3042
3043
3044


3045
3046
3047
3048
3049
3050
3051
3052
3053

3054
3055
3056
3057
3058
3059
3060
3061







-
-
+
+







-
+







	    if ((i < objc-1)
		    && Tcl_GetBooleanFromObj(interp, objv[i+1], &boolean)
			    != TCL_OK) {
		return TCL_ERROR;
	    }
	    if (config_fullscreen) {
		if (objc == 4) {
		    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(
			    wmPtr->flags & WM_FULLSCREEN));
		    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(
			    (wmPtr->flags & WM_FULLSCREEN) != 0));
		} else {
		    fullscreen_attr_changed = 1;
		    fullscreen_attr = boolean;
		}
		config_fullscreen = 0;
	    } else if (objc == 4) {
		Tcl_SetObjResult(interp,
			Tcl_NewBooleanObj(*stylePtr & styleBit));
			Tcl_NewWideIntObj((*stylePtr & styleBit) != 0));
	    } else if (boolean) {
		*stylePtr |= styleBit;
	    } else {
		*stylePtr &= ~styleBit;
	    }
	}
	if ((styleBit == WS_EX_TOPMOST) && (wmPtr->wrapper != NULL)) {
3315
3316
3317
3318
3319
3320
3321
3322

3323
3324


3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337

3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353

3354
3355
3356
3357
3358
3359
3360
3152
3153
3154
3155
3156
3157
3158

3159
3160

3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174

3175

3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189

3190
3191
3192
3193
3194
3195
3196
3197







-
+

-
+
+












-
+
-














-
+







WmClientCmd(
    Tk_Window tkwin,		/* 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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    const char *argv3;
    size_t length;
    TkSizeT length;
    (void)tkwin;

    if ((objc != 3) && (objc != 4)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?name?");
	return TCL_ERROR;
    }
    if (objc == 3) {
	if (wmPtr->clientMachine != NULL) {
	    Tcl_SetObjResult(interp,
		    Tcl_NewStringObj(wmPtr->clientMachine, -1));
	}
	return TCL_OK;
    }
    argv3 = Tcl_GetString(objv[3]);
    argv3 = TkGetStringFromObj(objv[3], &length);
    length = objv[3]->length;
    if (argv3[0] == 0) {
	if (wmPtr->clientMachine != NULL) {
	    ckfree(wmPtr->clientMachine);
	    wmPtr->clientMachine = NULL;
	    if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
		XDeleteProperty(winPtr->display, winPtr->window,
			Tk_InternAtom((Tk_Window) winPtr,"WM_CLIENT_MACHINE"));
	    }
	}
	return TCL_OK;
    }
    if (wmPtr->clientMachine != NULL) {
	ckfree(wmPtr->clientMachine);
    }
    wmPtr->clientMachine = ckalloc(length + 1);
    wmPtr->clientMachine = (char *)ckalloc(length + 1);
    memcpy(wmPtr->clientMachine, argv3, length + 1);
    if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
	XTextProperty textProp;

	if (XStringListToTextProperty(&wmPtr->clientMachine, 1, &textProp)
		!= 0) {
	    XSetWMClientMachine(winPtr->display, winPtr->window,
3386
3387
3388
3389
3390
3391
3392
3393

3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411

3412
3413
3414
3415
3416
3417
3418
3419
3420

3421
3422
3423
3424
3425
3426
3427
3223
3224
3225
3226
3227
3228
3229

3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247

3248
3249
3250
3251
3252
3253
3254
3255
3256

3257
3258
3259
3260
3261
3262
3263
3264







-
+

















-
+








-
+







WmColormapwindowsCmd(
    Tk_Window tkwin,		/* 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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    TkWindow **cmapList, *winPtr2, **winPtr2Ptr = &winPtr2;
    int i, windowObjc, gotToplevel;
    Tcl_Obj **windowObjv, *resultObj;

    if ((objc != 3) && (objc != 4)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?windowList?");
	return TCL_ERROR;
    }
    if (objc == 3) {
	Tk_MakeWindowExist((Tk_Window) winPtr);
	resultObj = Tcl_NewObj();
	for (i = 0; i < wmPtr->cmapCount; i++) {
	    if ((i == (wmPtr->cmapCount-1))
		    && (wmPtr->flags & WM_ADDED_TOPLEVEL_COLORMAP)) {
		break;
	    }
	    Tcl_ListObjAppendElement(NULL, resultObj,
		    TkNewWindowObj((Tk_Window) wmPtr->cmapList[i]));
		    Tk_NewWindowObj((Tk_Window) wmPtr->cmapList[i]));
	}
	Tcl_SetObjResult(interp, resultObj);
	return TCL_OK;
    }
    if (Tcl_ListObjGetElements(interp, objv[3], &windowObjc, &windowObjv)
	    != TCL_OK) {
	return TCL_ERROR;
    }
    cmapList = ckalloc((windowObjc + 1) * sizeof(TkWindow*));
    cmapList = (TkWindow**)ckalloc((windowObjc + 1) * sizeof(TkWindow*));
    gotToplevel = 0;
    for (i = 0; i < windowObjc; i++) {
	if (TkGetWindowFromObj(interp, tkwin, windowObjv[i],
		(Tk_Window *) winPtr2Ptr) != TCL_OK) {
	    ckfree(cmapList);
	    return TCL_ERROR;
	}
3480
3481
3482
3483
3484
3485
3486
3487

3488
3489
3490

3491
3492
3493
3494
3495
3496
3497
3317
3318
3319
3320
3321
3322
3323

3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335







-
+



+







WmCommandCmd(
    Tk_Window tkwin,		/* 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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    const char *argv3;
    int cmdArgc;
    const char **cmdArgv;
    (void)tkwin;

    if ((objc != 3) && (objc != 4)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?value?");
	return TCL_ERROR;
    }
    if (objc == 3) {
	if (wmPtr->cmdArgv != NULL) {
3549
3550
3551
3552
3553
3554
3555
3556


3557
3558
3559
3560
3561
3562
3563
3387
3388
3389
3390
3391
3392
3393

3394
3395
3396
3397
3398
3399
3400
3401
3402







-
+
+







WmDeiconifyCmd(
    Tk_Window tkwin,		/* 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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    (void)tkwin;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "window");
	return TCL_ERROR;
    }
    if (wmPtr->iconFor != NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
3601
3602
3603
3604
3605
3606
3607
3608

3609
3610
3611
3612
3613
3614
3615

3616
3617
3618
3619
3620
3621
3622
3440
3441
3442
3443
3444
3445
3446

3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462







-
+







+







WmFocusmodelCmd(
    Tk_Window tkwin,		/* 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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    static const char *const optionStrings[] = {
	"active", "passive", NULL
    };
    enum options {
	OPT_ACTIVE, OPT_PASSIVE
    };
    int index;
    (void)tkwin;

    if ((objc != 3) && (objc != 4)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?active|passive?");
	return TCL_ERROR;
    }
    if (objc == 3) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
3653
3654
3655
3656
3657
3658
3659
3660

3661
3662
3663
3664





3665
3666
3667
3668
3669
3670
3671
3493
3494
3495
3496
3497
3498
3499

3500
3501
3502
3503

3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515







-
+



-
+
+
+
+
+







 *----------------------------------------------------------------------
 */

static int
WmForgetCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    TkWindow *winPtr,		/* Toplevel or Frame to work with */
    Tcl_Interp *interp,		/* Current interpreter. */
    Tcl_Interp *dummy,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    register Tk_Window frameWin = (Tk_Window) winPtr;
    Tk_Window frameWin = (Tk_Window) winPtr;
    (void)tkwin;
    (void)dummy;
    (void)objc;
    (void)objv;

    if (Tk_IsTopLevel(frameWin)) {
	Tk_UnmapWindow(frameWin);
	winPtr->flags &= ~(TK_TOP_HIERARCHY|TK_TOP_LEVEL|TK_HAS_WRAPPER|TK_WIN_MANAGED);
	Tk_MakeWindowExist((Tk_Window)winPtr->parentPtr);
	RemapWindows(winPtr, Tk_GetHWND(winPtr->parentPtr->window));

3705
3706
3707
3708
3709
3710
3711
3712

3713
3714

3715
3716
3717
3718
3719
3720
3721
3549
3550
3551
3552
3553
3554
3555

3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566







-
+


+







WmFrameCmd(
    Tk_Window tkwin,		/* 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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    HWND hwnd;
    char buf[TCL_INTEGER_SPACE];
    (void)tkwin;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "window");
	return TCL_ERROR;
    }
    if (Tk_WindowId((Tk_Window) winPtr) == None) {
	Tk_MakeWindowExist((Tk_Window) winPtr);
3750
3751
3752
3753
3754
3755
3756
3757

3758
3759
3760

3761
3762
3763
3764
3765
3766
3767
3595
3596
3597
3598
3599
3600
3601

3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613







-
+



+







WmGeometryCmd(
    Tk_Window tkwin,		/* 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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    char xSign, ySign;
    int width, height;
    const char *argv3;
    (void)tkwin;

    if ((objc != 3) && (objc != 4)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?newGeometry?");
	return TCL_ERROR;
    }

    if (objc == 3) {
3818
3819
3820
3821
3822
3823
3824
3825

3826

3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840




3841
3842
3843
3844
3845
3846
3847
3664
3665
3666
3667
3668
3669
3670

3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683




3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694







-
+

+










-
-
-
-
+
+
+
+







WmGridCmd(
    Tk_Window tkwin,		/* 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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    int reqWidth, reqHeight, widthInc, heightInc;
    (void)tkwin;

    if ((objc != 3) && (objc != 7)) {
	Tcl_WrongNumArgs(interp, 2, objv,
		"window ?baseWidth baseHeight widthInc heightInc?");
	return TCL_ERROR;
    }
    if (objc == 3) {
	if (wmPtr->sizeHintsFlags & PBaseSize) {
	    Tcl_Obj *results[4];

	    results[0] = Tcl_NewIntObj(wmPtr->reqGridWidth);
	    results[1] = Tcl_NewIntObj(wmPtr->reqGridHeight);
	    results[2] = Tcl_NewIntObj(wmPtr->widthInc);
	    results[3] = Tcl_NewIntObj(wmPtr->heightInc);
	    results[0] = Tcl_NewWideIntObj(wmPtr->reqGridWidth);
	    results[1] = Tcl_NewWideIntObj(wmPtr->reqGridHeight);
	    results[2] = Tcl_NewWideIntObj(wmPtr->widthInc);
	    results[3] = Tcl_NewWideIntObj(wmPtr->heightInc);
	    Tcl_SetObjResult(interp, Tcl_NewListObj(4, results));
	}
	return TCL_OK;
    }
    if (*Tcl_GetString(objv[3]) == '\0') {
	/*
	 * Turn off gridding and reset the width and height to make sense as
3916
3917
3918
3919
3920
3921
3922
3923

3924
3925
3926

3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938

3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956

3957
3958
3959
3960
3961
3962
3963
3763
3764
3765
3766
3767
3768
3769

3770
3771
3772

3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784

3785

3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801

3802
3803
3804
3805
3806
3807
3808
3809







-
+


-
+











-
+
-
















-
+







WmGroupCmd(
    Tk_Window tkwin,		/* 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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    Tk_Window tkwin2;
    const char *argv3;
    size_t length;
    TkSizeT length;

    if ((objc != 3) && (objc != 4)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?pathName?");
	return TCL_ERROR;
    }
    if (objc == 3) {
	if (wmPtr->hints.flags & WindowGroupHint) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(wmPtr->leaderName, -1));
	}
	return TCL_OK;
    }
    argv3 = Tcl_GetString(objv[3]);
    argv3 = TkGetStringFromObj(objv[3], &length);
    length = objv[3]->length;
    if (*argv3 == '\0') {
	wmPtr->hints.flags &= ~WindowGroupHint;
	if (wmPtr->leaderName != NULL) {
	    ckfree(wmPtr->leaderName);
	}
	wmPtr->leaderName = NULL;
    } else {
	if (TkGetWindowFromObj(interp, tkwin, objv[3], &tkwin2) != TCL_OK) {
	    return TCL_ERROR;
	}
	Tk_MakeWindowExist(tkwin2);
	if (wmPtr->leaderName != NULL) {
	    ckfree(wmPtr->leaderName);
	}
	wmPtr->hints.window_group = Tk_WindowId(tkwin2);
	wmPtr->hints.flags |= WindowGroupHint;
	wmPtr->leaderName = ckalloc(length + 1);
	wmPtr->leaderName = (char *)ckalloc(length + 1);
	memcpy(wmPtr->leaderName, argv3, length + 1);
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
3980
3981
3982
3983
3984
3985
3986
3987

3988
3989

3990
3991
3992
3993
3994
3995
3996
3826
3827
3828
3829
3830
3831
3832

3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843







-
+


+







WmIconbitmapCmd(
    Tk_Window tkwin,		/* 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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    TkWindow *useWinPtr = winPtr; /* window to apply to (NULL if -default) */
    const char *string;
    (void)tkwin;

    if ((objc < 3) || (objc > 5)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?-default? ?image?");
	return TCL_ERROR;
    } else if (objc == 5) {
	/*
	 * If we have 5 arguments, we must have a '-default' flag.
4116
4117
4118
4119
4120
4121
4122
4123



4124
4125
4126
4127
4128
4129
4130
4131

4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145

4146
4147
4148
4149
4150
4151
4152
4153
4154

4155
4156
4157
4158
4159
4160
4161
3963
3964
3965
3966
3967
3968
3969

3970
3971
3972
3973
3974
3975
3976
3977
3978
3979

3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993

3994
3995
3996
3997
3998
3999
4000
4001
4002

4003
4004
4005
4006
4007
4008
4009
4010







-
+
+
+







-
+













-
+








-
+







WmIconifyCmd(
    Tk_Window tkwin,		/* 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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    (void)tkwin;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "window");
	return TCL_ERROR;
    }
    if (winPtr->flags & TK_EMBEDDED) {
	if (!SendMessageW(wmPtr->wrapper, TK_ICONIFY, 0, 0)) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "can't iconify %s: the container does not support the request",
		    "can't iconify \"%s\": the container does not support the request",
		    winPtr->pathName));
	    Tcl_SetErrorCode(interp, "TK", "WM", "ICONIFY", "EMBEDDED", NULL);
	    return TCL_ERROR;
	}
    }
    if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"can't iconify \"%s\": override-redirect flag is set",
		winPtr->pathName));
	Tcl_SetErrorCode(interp, "TK", "WM", "ICONIFY", "OVERRIDE_REDIRECT",
		NULL);
	return TCL_ERROR;
    }
    if (wmPtr->masterPtr != NULL) {
    if (wmPtr->containerPtr != NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"can't iconify \"%s\": it is a transient",
		winPtr->pathName));
	Tcl_SetErrorCode(interp, "TK", "WM", "ICONIFY", "TRANSIENT", NULL);
	return TCL_ERROR;
    }
    if (wmPtr->iconFor != NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"can't iconify %s: it is an icon for %s",
		"can't iconify \"%s\": it is an icon for \"%s\"",
		winPtr->pathName, Tk_PathName(wmPtr->iconFor)));
	Tcl_SetErrorCode(interp, "TK", "WM", "ICONIFY", "ICON", NULL);
	return TCL_ERROR;
    }
    TkpWmSetState(winPtr, IconicState);
    return TCL_OK;
}
4181
4182
4183
4184
4185
4186
4187
4188

4189
4190
4191
4192
4193
4194
4195
4030
4031
4032
4033
4034
4035
4036

4037
4038
4039
4040
4041
4042
4043
4044







-
+







WmIconmaskCmd(
    Tk_Window tkwin,		/* 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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    Pixmap pixmap;
    const char *argv3;

    if ((objc != 3) && (objc != 4)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?bitmap?");
	return TCL_ERROR;
    }
4239
4240
4241
4242
4243
4244
4245
4246

4247
4248


4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262

4263
4264

4265
4266
4267
4268
4269
4270
4271
4088
4089
4090
4091
4092
4093
4094

4095
4096

4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111

4112


4113
4114
4115
4116
4117
4118
4119
4120







-
+

-
+
+













-
+
-
-
+







WmIconnameCmd(
    Tk_Window tkwin,		/* 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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    const char *argv3;
    size_t length;
    TkSizeT length;
    (void)tkwin;

    if (objc > 4) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?newName?");
	return TCL_ERROR;
    }
    if (objc == 3) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		(wmPtr->iconName ? wmPtr->iconName : ""), -1));
	return TCL_OK;
    } else {
	if (wmPtr->iconName != NULL) {
	    ckfree(wmPtr->iconName);
	}
	argv3 = Tcl_GetString(objv[3]);
	argv3 = TkGetStringFromObj(objv[3], &length);
	length = objv[3]->length;
	wmPtr->iconName = ckalloc(length + 1);
	wmPtr->iconName = (char *)ckalloc(length + 1);
	memcpy(wmPtr->iconName, argv3, length + 1);
	if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
	    XSetIconName(winPtr->display, winPtr->window, wmPtr->iconName);
	}
    }
    return TCL_OK;
}
4294
4295
4296
4297
4298
4299
4300
4301

4302
4303
4304
4305
4306
4307
4308

4309
4310
4311
4312
4313
4314
4315
4316
4143
4144
4145
4146
4147
4148
4149

4150


4151
4152
4153
4154

4155

4156
4157
4158
4159
4160
4161
4162







-
+
-
-




-
+
-







    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    TkWindow *useWinPtr = winPtr; /* window to apply to (NULL if -default) */
    Tk_PhotoHandle photo;
    Tk_PhotoImageBlock block;
    int i, width, height, idx, bufferSize, startObj = 3;
    int i, width, height, startObj = 3;
    union {unsigned char *ptr; void *voidPtr;} bgraPixel;
    union {unsigned char *ptr; void *voidPtr;} bgraMask;
    BlockOfIconImagesPtr lpIR;
    WinIconPtr titlebaricon = NULL;
    HICON hIcon;
    unsigned size;
    BITMAPINFO bmInfo;
    (void)tkwin;
    ICONINFO iconInfo;

    if (objc < 4) {
	Tcl_WrongNumArgs(interp, 2, objv,
		"window ?-default? image1 ?image2 ...?");
	return TCL_ERROR;
    }

4340
4341
4342
4343
4344
4345
4346
4347

4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431

4432
4433
4434
4435
4436
4437
4438
4439

4440
4441

4442
4443
4444
4445
4446
4447
4448
4449

4450
4451
4452

4453
4454
4455
4456
4457
4458
4459
4186
4187
4188
4189
4190
4191
4192

4193
4194
4195
4196
4197
4198


4199
4200
4201
4202
4203








































































4204


4205





4206
4207

4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219

4220
4221
4222
4223
4224
4225
4226
4227







-
+





-
-





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-

-
-
-
-
-
+

-
+








+


-
+








    /*
     * We have calculated the size of the data. Try to allocate the needed
     * memory space.
     */

    size = sizeof(BlockOfIconImages) + (sizeof(ICONIMAGE) * (objc-startObj-1));
    lpIR = attemptckalloc(size);
    lpIR = (BlockOfIconImagesPtr)attemptckalloc(size);
    if (lpIR == NULL) {
	return TCL_ERROR;
    }
    ZeroMemory(lpIR, size);

    lpIR->nNumImages = objc - startObj;

    for (i = startObj; i < objc; i++) {
	photo = Tk_FindPhoto(interp, Tcl_GetString(objv[i]));
	Tk_PhotoGetSize(photo, &width, &height);
	Tk_PhotoGetImage(photo, &block);

	/*
	 * Don't use CreateIcon to create the icon, as it requires color
	 * bitmap data in device-dependent format. Instead we use
	 * CreateIconIndirect which takes device-independent bitmaps and
	 * converts them as required. Initialise icon info structure.
	 */

	ZeroMemory(&iconInfo, sizeof(iconInfo));
	iconInfo.fIcon = TRUE;

	/*
	 * Create device-independent color bitmap.
	 */

	ZeroMemory(&bmInfo, sizeof bmInfo);
	bmInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	bmInfo.bmiHeader.biWidth = width;
	bmInfo.bmiHeader.biHeight = -height;
	bmInfo.bmiHeader.biPlanes = 1;
	bmInfo.bmiHeader.biBitCount = 32;
	bmInfo.bmiHeader.biCompression = BI_RGB;

	iconInfo.hbmColor = CreateDIBSection(NULL, &bmInfo, DIB_RGB_COLORS,
		&bgraPixel.voidPtr, NULL, 0);
	if (!iconInfo.hbmColor) {
	    ckfree(lpIR);
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "failed to create an iconphoto with image \"%s\"",
		    Tcl_GetString(objv[i])));
	    Tcl_SetErrorCode(interp, "TK", "WM", "ICONPHOTO", "IMAGE", NULL);
	    return TCL_ERROR;
	}

	/*
	 * Convert the photo image data into BGRA format (RGBQUAD).
	 */

	bufferSize = height * width * 4;
	for (idx = 0 ; idx < bufferSize ; idx += 4) {
	    bgraPixel.ptr[idx] = block.pixelPtr[idx+2];
	    bgraPixel.ptr[idx+1] = block.pixelPtr[idx+1];
	    bgraPixel.ptr[idx+2] = block.pixelPtr[idx+0];
	    bgraPixel.ptr[idx+3] = block.pixelPtr[idx+3];
	}

	/*
	 * Create a dummy mask bitmap. The contents of this don't appear to
	 * matter, as CreateIconIndirect will setup the icon mask based on the
	 * alpha channel in our color bitmap.
	 */

	bmInfo.bmiHeader.biBitCount = 1;

	iconInfo.hbmMask = CreateDIBSection(NULL, &bmInfo, DIB_RGB_COLORS,
		&bgraMask.voidPtr, NULL, 0);
	if (!iconInfo.hbmMask) {
	    DeleteObject(iconInfo.hbmColor);
	    ckfree(lpIR);
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "failed to create mask bitmap for \"%s\"",
		    Tcl_GetString(objv[i])));
	    Tcl_SetErrorCode(interp, "TK", "WM", "ICONPHOTO", "MASK", NULL);
	    return TCL_ERROR;
	}

	ZeroMemory(bgraMask.ptr, width*height/8);

	/*
	 * Create an icon from the bitmaps.
	 */

	hIcon = CreateIconIndirect(&iconInfo);
	hIcon = CreateIcoFromPhoto(width, height, block);
	DeleteObject(iconInfo.hbmColor);
	DeleteObject(iconInfo.hbmMask);
	if (hIcon == NULL) {
	    /*
	     * XXX should free up created icons.
	     */

	    ckfree(lpIR);
	    FreeIconBlock(lpIR);
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "failed to create icon for \"%s\"",
		    "failed to create an iconphoto with image \"%s\"",
		    Tcl_GetString(objv[i])));
	    Tcl_SetErrorCode(interp, "TK", "WM", "ICONPHOTO", "ICON", NULL);
	    return TCL_ERROR;
	}
	lpIR->IconImages[i-startObj].Width = width;
	lpIR->IconImages[i-startObj].Height = height;
	lpIR->IconImages[i-startObj].Colors = 4;
	lpIR->IconImages[i-startObj].hIcon = hIcon;
	lpIR->nNumImages++;
    }

    titlebaricon = ckalloc(sizeof(WinIconInstance));
    titlebaricon = (WinIconPtr)ckalloc(sizeof(WinIconInstance));
    titlebaricon->iconBlock = lpIR;
    titlebaricon->refCount = 1;
    if (WinSetIcon(interp, titlebaricon, (Tk_Window) useWinPtr) != TCL_OK) {
	/*
	 * We didn't use the titlebaricon after all.
	 */

4484
4485
4486
4487
4488
4489
4490
4491

4492

4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503


4504
4505
4506
4507
4508
4509
4510
4252
4253
4254
4255
4256
4257
4258

4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270


4271
4272
4273
4274
4275
4276
4277
4278
4279







-
+

+









-
-
+
+







WmIconpositionCmd(
    Tk_Window tkwin,		/* 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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    int x, y;
    (void)tkwin;

    if ((objc != 3) && (objc != 5)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?x y?");
	return TCL_ERROR;
    }
    if (objc == 3) {
	if (wmPtr->hints.flags & IconPositionHint) {
	    Tcl_Obj *results[2];

	    results[0] = Tcl_NewIntObj(wmPtr->hints.icon_x);
	    results[1] = Tcl_NewIntObj(wmPtr->hints.icon_y);
	    results[0] = Tcl_NewWideIntObj(wmPtr->hints.icon_x);
	    results[1] = Tcl_NewWideIntObj(wmPtr->hints.icon_y);
	    Tcl_SetObjResult(interp, Tcl_NewListObj(2, results));
	}
	return TCL_OK;
    }
    if (*Tcl_GetString(objv[3]) == '\0') {
	wmPtr->hints.flags &= ~IconPositionHint;
    } else {
4540
4541
4542
4543
4544
4545
4546
4547

4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558

4559
4560
4561
4562
4563
4564
4565
4309
4310
4311
4312
4313
4314
4315

4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326

4327
4328
4329
4330
4331
4332
4333
4334







-
+










-
+







WmIconwindowCmd(
    Tk_Window tkwin,		/* 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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    Tk_Window tkwin2;
    WmInfo *wmPtr2;
    XSetWindowAttributes atts;

    if ((objc != 3) && (objc != 4)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?pathName?");
	return TCL_ERROR;
    }
    if (objc == 3) {
	if (wmPtr->icon != NULL) {
	    Tcl_SetObjResult(interp, TkNewWindowObj(wmPtr->icon));
	    Tcl_SetObjResult(interp, Tk_NewWindowObj(wmPtr->icon));
	}
	return TCL_OK;
    }
    if (*Tcl_GetString(objv[3]) == '\0') {
	wmPtr->hints.flags &= ~IconWindowHint;
	if (wmPtr->icon != NULL) {
	    /*
4650
4651
4652
4653
4654
4655
4656
4657
4658





4659
4660
4661
4662
4663
4664
4665
4419
4420
4421
4422
4423
4424
4425


4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437







-
-
+
+
+
+
+







WmManageCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    TkWindow *winPtr,		/* Toplevel or Frame to work with */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    register Tk_Window frameWin = (Tk_Window) winPtr;
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    Tk_Window frameWin = (Tk_Window) winPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    (void)tkwin;
    (void)objc;
    (void)objv;

    if (!Tk_IsTopLevel(frameWin)) {
	if (!Tk_IsManageable(frameWin)) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "window \"%s\" is not manageable: must be a frame,"
		    " labelframe or toplevel", Tk_PathName(frameWin)));
	    Tcl_SetErrorCode(interp, "TK", "WM", "MANAGE", NULL);
4704
4705
4706
4707
4708
4709
4710
4711

4712

4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723


4724
4725
4726
4727
4728
4729
4730
4476
4477
4478
4479
4480
4481
4482

4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494


4495
4496
4497
4498
4499
4500
4501
4502
4503







-
+

+









-
-
+
+







WmMaxsizeCmd(
    Tk_Window tkwin,		/* 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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    int width, height;
    (void)tkwin;

    if ((objc != 3) && (objc != 5)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?width height?");
	return TCL_ERROR;
    }
    if (objc == 3) {
	Tcl_Obj *results[2];

	GetMaxSize(wmPtr, &width, &height);
	results[0] = Tcl_NewIntObj(width);
	results[1] = Tcl_NewIntObj(height);
	results[0] = Tcl_NewWideIntObj(width);
	results[1] = Tcl_NewWideIntObj(height);
	Tcl_SetObjResult(interp, Tcl_NewListObj(2, results));
	return TCL_OK;
    }
    if ((Tcl_GetIntFromObj(interp, objv[3], &width) != TCL_OK)
	    || (Tcl_GetIntFromObj(interp, objv[4], &height) != TCL_OK)) {
	return TCL_ERROR;
    }
4755
4756
4757
4758
4759
4760
4761
4762

4763

4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774


4775
4776
4777
4778
4779
4780
4781
4528
4529
4530
4531
4532
4533
4534

4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546


4547
4548
4549
4550
4551
4552
4553
4554
4555







-
+

+









-
-
+
+







WmMinsizeCmd(
    Tk_Window tkwin,		/* 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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    int width, height;
    (void)tkwin;

    if ((objc != 3) && (objc != 5)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?width height?");
	return TCL_ERROR;
    }
    if (objc == 3) {
	Tcl_Obj *results[2];

	GetMinSize(wmPtr, &width, &height);
	results[0] = Tcl_NewIntObj(width);
	results[1] = Tcl_NewIntObj(height);
	results[0] = Tcl_NewWideIntObj(width);
	results[1] = Tcl_NewWideIntObj(height);
	Tcl_SetObjResult(interp, Tcl_NewListObj(2, results));
	return TCL_OK;
    }
    if ((Tcl_GetIntFromObj(interp, objv[3], &width) != TCL_OK)
	    || (Tcl_GetIntFromObj(interp, objv[4], &height) != TCL_OK)) {
	return TCL_ERROR;
    }
4806
4807
4808
4809
4810
4811
4812
4813

4814
4815

4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833

4834
4835
4836
4837
4838
4839
4840
4580
4581
4582
4583
4584
4585
4586

4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607

4608
4609
4610
4611
4612
4613
4614
4615







-
+


+

















-
+







WmOverrideredirectCmd(
    Tk_Window tkwin,		/* 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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    int boolean, curValue;
    XSetWindowAttributes atts;
    (void)tkwin;

    if ((objc != 3) && (objc != 4)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?boolean?");
	return TCL_ERROR;
    }
    if (winPtr->flags & TK_EMBEDDED) {
	curValue = SendMessageW(wmPtr->wrapper, TK_OVERRIDEREDIRECT, -1, -1)-1;
	if (curValue < 0) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "Container does not support overrideredirect", -1));
	    Tcl_SetErrorCode(interp, "TK", "WM", "COMMUNICATION", NULL);
	    return TCL_ERROR;
	}
    } else {
	curValue = Tk_Attributes((Tk_Window) winPtr)->override_redirect;
    }
    if (objc == 3) {
	Tcl_SetObjResult(interp, Tcl_NewBooleanObj(curValue));
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(curValue != 0));
	return TCL_OK;
    }
    if (Tcl_GetBooleanFromObj(interp, objv[3], &boolean) != TCL_OK) {
	return TCL_ERROR;
    }
    if (curValue != boolean) {
	if (winPtr->flags & TK_EMBEDDED) {
4878
4879
4880
4881
4882
4883
4884
4885

4886
4887
4888
4889
4890
4891
4892

4893
4894
4895
4896
4897
4898
4899
4653
4654
4655
4656
4657
4658
4659

4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675







-
+







+







WmPositionfromCmd(
    Tk_Window tkwin,		/* 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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    static const char *const optionStrings[] = {
	"program", "user", NULL
    };
    enum options {
	OPT_PROGRAM, OPT_USER
    };
    int index;
    (void)tkwin;

    if ((objc != 3) && (objc != 4)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?user/program?");
	return TCL_ERROR;
    }
    if (objc == 3) {
	const char *sourceStr = "";
4946
4947
4948
4949
4950
4951
4952
4953
4954


4955
4956
4957

4958

4959
4960
4961
4962
4963
4964
4965
4722
4723
4724
4725
4726
4727
4728


4729
4730
4731
4732

4733
4734
4735
4736
4737
4738
4739
4740
4741
4742







-
-
+
+


-
+

+







WmProtocolCmd(
    Tk_Window tkwin,		/* 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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    register ProtocolHandler *protPtr, *prevPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    ProtocolHandler *protPtr, *prevPtr;
    Atom protocol;
    const char *cmd;
    size_t cmdLength;
    TkSizeT cmdLength;
    Tcl_Obj *resultObj;
    (void)tkwin;

    if ((objc < 3) || (objc > 5)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?name? ?command?");
	return TCL_ERROR;
    }
    if (objc == 3) {
	/*
5005
5006
5007
5008
5009
5010
5011
5012

5013
5014
5015

5016
5017
5018
5019
5020
5021
5022
4782
4783
4784
4785
4786
4787
4788

4789

4790

4791
4792
4793
4794
4795
4796
4797
4798







-
+
-

-
+







	    } else {
		prevPtr->nextPtr = protPtr->nextPtr;
	    }
	    Tcl_EventuallyFree(protPtr, TCL_DYNAMIC);
	    break;
	}
    }
    cmd = Tcl_GetString(objv[4]);
    cmd = TkGetStringFromObj(objv[4], &cmdLength);
    cmdLength = objv[4]->length;
    if (cmdLength > 0) {
	protPtr = ckalloc(HANDLER_SIZE(cmdLength));
	protPtr = (ProtocolHandler *)ckalloc(HANDLER_SIZE(cmdLength));
	protPtr->protocol = protocol;
	protPtr->nextPtr = wmPtr->protPtr;
	wmPtr->protPtr = protPtr;
	protPtr->interp = interp;
	memcpy(protPtr->command, cmd, cmdLength + 1);
    }
    return TCL_OK;
5043
5044
5045
5046
5047
5048
5049
5050

5051

5052
5053
5054
5055
5056
5057
5058
5059
5060
5061


5062
5063
5064
5065
5066
5067
5068
4819
4820
4821
4822
4823
4824
4825

4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836


4837
4838
4839
4840
4841
4842
4843
4844
4845







-
+

+








-
-
+
+







WmResizableCmd(
    Tk_Window tkwin,		/* 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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    int width, height;
    (void)tkwin;

    if ((objc != 3) && (objc != 5)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?width height?");
	return TCL_ERROR;
    }
    if (objc == 3) {
	Tcl_Obj *results[2];

	results[0] = Tcl_NewBooleanObj(!(wmPtr->flags&WM_WIDTH_NOT_RESIZABLE));
	results[1] = Tcl_NewBooleanObj(!(wmPtr->flags&WM_HEIGHT_NOT_RESIZABLE));
	results[0] = Tcl_NewWideIntObj(!(wmPtr->flags&WM_WIDTH_NOT_RESIZABLE));
	results[1] = Tcl_NewWideIntObj(!(wmPtr->flags&WM_HEIGHT_NOT_RESIZABLE));
	Tcl_SetObjResult(interp, Tcl_NewListObj(2, results));
	return TCL_OK;
    }
    if ((Tcl_GetBooleanFromObj(interp, objv[3], &width) != TCL_OK)
	    || (Tcl_GetBooleanFromObj(interp, objv[4], &height) != TCL_OK)) {
	return TCL_ERROR;
    }
5105
5106
5107
5108
5109
5110
5111
5112

5113
5114
5115
5116
5117
5118
5119

5120
5121
5122
5123
5124
5125
5126
4882
4883
4884
4885
4886
4887
4888

4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904







-
+







+







WmSizefromCmd(
    Tk_Window tkwin,		/* 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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    static const char *const optionStrings[] = {
	"program", "user", NULL
    };
    enum options {
	OPT_PROGRAM, OPT_USER
    };
    int index;
    (void)tkwin;

    if ((objc != 3) && (objc != 4)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?user|program?");
	return TCL_ERROR;
    }
    if (objc == 3) {
	const char *sourceStr = "";
5195
5196
5197
5198
5199
5200
5201
5202

5203
5204
5205
5206
5207
5208
5209
4973
4974
4975
4976
4977
4978
4979

4980
4981
4982
4983
4984
4985
4986
4987







-
+








    if (objc == 3) {
	windows = TkWmStackorderToplevel(winPtr);
	if (windows != NULL) {
	    resultObj = Tcl_NewObj();
	    for (windowPtr = windows; *windowPtr ; windowPtr++) {
		Tcl_ListObjAppendElement(NULL, resultObj,
			TkNewWindowObj((Tk_Window) *windowPtr));
			Tk_NewWindowObj((Tk_Window) *windowPtr));
	    }
	    Tcl_SetObjResult(interp, resultObj);
	    ckfree(windows);
	    return TCL_OK;
	} else {
	    return TCL_ERROR;
	}
5272
5273
5274
5275
5276
5277
5278
5279

5280
5281
5282
5283
5284
5285
5286
5050
5051
5052
5053
5054
5055
5056

5057
5058
5059
5060
5061
5062
5063
5064







-
+







	    return TCL_ERROR;
	}
	if (index == OPT_ISABOVE) {
	    result = index1 > index2;
	} else { /* OPT_ISBELOW */
	    result = index1 < index2;
	}
	Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result));
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(result));
	return TCL_OK;
    }
}

/*
 *----------------------------------------------------------------------
 *
5302
5303
5304
5305
5306
5307
5308
5309

5310
5311
5312
5313
5314
5315
5316

5317
5318
5319
5320
5321
5322
5323
5080
5081
5082
5083
5084
5085
5086

5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102







-
+







+







WmStateCmd(
    Tk_Window tkwin,		/* 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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    static const char *const optionStrings[] = {
	"normal", "iconic", "withdrawn", "zoomed", NULL
    };
    enum options {
	OPT_NORMAL, OPT_ICONIC, OPT_WITHDRAWN, OPT_ZOOMED
    };
    int index;
    (void)tkwin;

    if ((objc < 3) || (objc > 4)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?state?");
	return TCL_ERROR;
    }
    if (objc == 4) {
	if (wmPtr->iconFor != NULL) {
5375
5376
5377
5378
5379
5380
5381
5382

5383
5384
5385
5386
5387
5388
5389
5154
5155
5156
5157
5158
5159
5160

5161
5162
5163
5164
5165
5166
5167
5168







-
+







		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"can't iconify \"%s\": override-redirect flag is set",
			winPtr->pathName));
		Tcl_SetErrorCode(interp, "TK", "WM", "STATE",
			"OVERRIDE_REDIRECT", NULL);
		return TCL_ERROR;
	    }
	    if (wmPtr->masterPtr != NULL) {
	    if (wmPtr->containerPtr != NULL) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"can't iconify \"%s\": it is a transient",
			winPtr->pathName));
		Tcl_SetErrorCode(interp, "TK", "WM", "STATE", "TRANSIENT",
			NULL);
		return TCL_ERROR;
	    }
5442
5443
5444
5445
5446
5447
5448
5449

5450
5451

5452

5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471


5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484

5485
5486

5487
5488
5489
5490
5491

5492

5493
5494
5495
5496
5497
5498
5499
5221
5222
5223
5224
5225
5226
5227

5228
5229

5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250

5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264

5265


5266
5267
5268
5269
5270
5271
5272

5273
5274
5275
5276
5277
5278
5279
5280







-
+

-
+

+


















-
+
+












-
+
-
-
+





+
-
+







WmTitleCmd(
    Tk_Window tkwin,		/* 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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    const char *argv3;
    size_t length;
    TkSizeT length;
    HWND wrapper;
    (void)tkwin;

    if (objc > 4) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?newTitle?");
	return TCL_ERROR;
    }

    if (winPtr->flags & TK_EMBEDDED) {
	wrapper = (HWND) SendMessageW(wmPtr->wrapper, TK_GETFRAMEWID, 0, 0);
    } else {
	wrapper = wmPtr->wrapper;
    }
    if (objc == 3) {
	if (wrapper) {
	    WCHAR buf[256];
	    Tcl_DString titleString;
	    int size = 256;

	    GetWindowTextW(wrapper, buf, size);
	    Tcl_WinTCharToUtf((LPCTSTR)buf, -1, &titleString);
	    Tcl_DStringInit(&titleString);
	    Tcl_WCharToUtfDString(buf, wcslen(buf), &titleString);
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    Tcl_DStringValue(&titleString),
		    Tcl_DStringLength(&titleString)));
	    Tcl_DStringFree(&titleString);
	} else {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    (wmPtr->title ? wmPtr->title : winPtr->nameUid), -1));
	}
    } else {
	if (wmPtr->title != NULL) {
	    ckfree(wmPtr->title);
	}
	argv3 = Tcl_GetString(objv[3]);
	argv3 = TkGetStringFromObj(objv[3], &length);
	length = objv[3]->length;
	wmPtr->title = ckalloc(length + 1);
	wmPtr->title = (char *)ckalloc(length + 1);
	memcpy(wmPtr->title, argv3, length + 1);

	if (!(wmPtr->flags & WM_NEVER_MAPPED) && wmPtr->wrapper != NULL) {
	    Tcl_DString titleString;

	    Tcl_DStringInit(&titleString);
	    Tcl_WinUtfToTChar(wmPtr->title, -1, &titleString);
	    Tcl_UtfToWCharDString(wmPtr->title, -1, &titleString);
	    SetWindowTextW(wrapper, (LPCWSTR) Tcl_DStringValue(&titleString));
	    Tcl_DStringFree(&titleString);
	}
    }
    return TCL_OK;
}

5518
5519
5520
5521
5522
5523
5524
5525
5526


5527
5528
5529
5530

5531
5532
5533
5534
5535


5536
5537
5538
5539
5540

5541
5542

5543
5544
5545
5546
5547


5548
5549
5550
5551
5552

5553
5554
5555

5556
5557
5558

5559
5560

5561
5562
5563

5564
5565

5566
5567
5568
5569
5570
5571
5572
5573
5574
5575

5576
5577
5578
5579

5580
5581
5582
5583
5584
5585


5586
5587
5588
5589


5590
5591
5592
5593
5594

5595
5596
5597
5598



5599
5600
5601
5602
5603



5604
5605
5606
5607
5608
5609


5610
5611
5612
5613

5614
5615
5616
5617
5618
5619


5620
5621
5622
5623
5624
5625
5626
5299
5300
5301
5302
5303
5304
5305


5306
5307
5308
5309
5310

5311
5312
5313
5314


5315
5316
5317
5318
5319
5320

5321
5322

5323
5324
5325
5326


5327
5328
5329
5330
5331
5332

5333
5334
5335

5336
5337
5338

5339
5340

5341
5342
5343

5344
5345

5346
5347
5348
5349
5350
5351
5352
5353
5354
5355

5356
5357
5358
5359

5360
5361
5362
5363
5364


5365
5366
5367
5368


5369
5370
5371
5372
5373
5374

5375
5376



5377
5378
5379
5380
5381



5382
5383
5384
5385
5386
5387
5388


5389
5390
5391
5392
5393

5394
5395
5396
5397
5398


5399
5400
5401
5402
5403
5404
5405
5406
5407







-
-
+
+



-
+



-
-
+
+




-
+

-
+



-
-
+
+




-
+


-
+


-
+

-
+


-
+

-
+









-
+



-
+




-
-
+
+


-
-
+
+




-
+

-
-
-
+
+
+


-
-
-
+
+
+




-
-
+
+



-
+




-
-
+
+







WmTransientCmd(
    Tk_Window tkwin,		/* 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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    TkWindow *masterPtr = wmPtr->masterPtr, **masterPtrPtr = &masterPtr, *w;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    TkWindow *containerPtr = wmPtr->containerPtr, **containerPtrPtr = &containerPtr, *w;
    WmInfo *wmPtr2;

    if ((objc != 3) && (objc != 4)) {
	Tcl_WrongNumArgs(interp, 2, objv, "window ?master?");
	Tcl_WrongNumArgs(interp, 2, objv, "window ?window?");
	return TCL_ERROR;
    }
    if (objc == 3) {
	if (masterPtr != NULL) {
	    Tcl_SetObjResult(interp, TkNewWindowObj((Tk_Window) masterPtr));
	if (containerPtr != NULL) {
	    Tcl_SetObjResult(interp, Tk_NewWindowObj((Tk_Window) containerPtr));
	}
	return TCL_OK;
    }
    if (Tcl_GetString(objv[3])[0] == '\0') {
	if (masterPtr != NULL) {
	if (containerPtr != NULL) {
	    /*
	     * If we had a master, tell them that we aren't tied to them
	     * If we had a container, tell them that we aren't tied to them
	     * anymore.
	     */

	    masterPtr->wmInfoPtr->numTransients--;
	    Tk_DeleteEventHandler((Tk_Window) masterPtr,
	    containerPtr->wmInfoPtr->numTransients--;
	    Tk_DeleteEventHandler((Tk_Window) containerPtr,
		    VisibilityChangeMask|StructureNotifyMask,
		    WmWaitVisibilityOrMapProc, winPtr);
	}

	wmPtr->masterPtr = NULL;
	wmPtr->containerPtr = NULL;
    } else {
	if (TkGetWindowFromObj(interp, tkwin, objv[3],
		(Tk_Window *) masterPtrPtr) != TCL_OK) {
		(Tk_Window *) containerPtrPtr) != TCL_OK) {
	    return TCL_ERROR;
	}
	while (!Tk_TopWinHierarchy(masterPtr)) {
	while (!Tk_TopWinHierarchy(containerPtr)) {
	    /*
	     * Ensure that the master window is actually a Tk toplevel.
	     * Ensure that the container window is actually a Tk toplevel.
	     */

	    masterPtr = masterPtr->parentPtr;
	    containerPtr = containerPtr->parentPtr;
	}
	Tk_MakeWindowExist((Tk_Window) masterPtr);
	Tk_MakeWindowExist((Tk_Window) containerPtr);

	if (wmPtr->iconFor != NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "can't make \"%s\" a transient: it is an icon for %s",
		    Tcl_GetString(objv[2]), Tk_PathName(wmPtr->iconFor)));
	    Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "ICON", NULL);
	    return TCL_ERROR;
	}

	wmPtr2 = masterPtr->wmInfoPtr;
	wmPtr2 = containerPtr->wmInfoPtr;

	if (wmPtr2->iconFor != NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "can't make \"%s\" a master: it is an icon for %s",
		    "can't make \"%s\" a container: it is an icon for %s",
		    Tcl_GetString(objv[3]), Tk_PathName(wmPtr2->iconFor)));
	    Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "ICON", NULL);
	    return TCL_ERROR;
	}
	for (w = masterPtr; w != NULL && w->wmInfoPtr != NULL;
	     w = (TkWindow *)w->wmInfoPtr->masterPtr) {
	for (w = containerPtr; w != NULL && w->wmInfoPtr != NULL;
	     w = (TkWindow *)w->wmInfoPtr->containerPtr) {
	    if (w == winPtr) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "setting \"%s\" as master creates a transient/master cycle",
		    Tk_PathName(masterPtr)));
		    "can't set \"%s\" as container: would cause management loop",
		    Tk_PathName(containerPtr)));
		Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "SELF", NULL);
		return TCL_ERROR;
	    }
	}
	if (masterPtr != wmPtr->masterPtr) {
	if (containerPtr != wmPtr->containerPtr) {
	    /*
	     * Remove old master map/unmap binding before setting the new
	     * master. The event handler will ensure that transient states
	     * reflect the state of the master.
	     * Remove old container map/unmap binding before setting the new
	     * container. The event handler will ensure that transient states
	     * reflect the state of the container.
	     */

	    if (wmPtr->masterPtr != NULL) {
		wmPtr->masterPtr->wmInfoPtr->numTransients--;
		Tk_DeleteEventHandler((Tk_Window) wmPtr->masterPtr,
	    if (wmPtr->containerPtr != NULL) {
		wmPtr->containerPtr->wmInfoPtr->numTransients--;
		Tk_DeleteEventHandler((Tk_Window) wmPtr->containerPtr,
			VisibilityChangeMask|StructureNotifyMask,
			WmWaitVisibilityOrMapProc, winPtr);
	    }

	    masterPtr->wmInfoPtr->numTransients++;
	    Tk_CreateEventHandler((Tk_Window) masterPtr,
	    containerPtr->wmInfoPtr->numTransients++;
	    Tk_CreateEventHandler((Tk_Window) containerPtr,
		    VisibilityChangeMask|StructureNotifyMask,
		    WmWaitVisibilityOrMapProc, winPtr);

	    wmPtr->masterPtr = masterPtr;
	    wmPtr->containerPtr = containerPtr;
	}
    }
    if (!((wmPtr->flags & WM_NEVER_MAPPED)
	    && !(winPtr->flags & TK_EMBEDDED))) {
	if (wmPtr->masterPtr != NULL
		&& !Tk_IsMapped(wmPtr->masterPtr)) {
	if (wmPtr->containerPtr != NULL
		&& !Tk_IsMapped(wmPtr->containerPtr)) {
	    TkpWmSetState(winPtr, WithdrawnState);
	} else {
	    UpdateWrapper(winPtr);
	}
    }
    return TCL_OK;
}
5646
5647
5648
5649
5650
5651
5652
5653


5654
5655
5656
5657
5658
5659
5660
5427
5428
5429
5430
5431
5432
5433

5434
5435
5436
5437
5438
5439
5440
5441
5442







-
+
+







WmWithdrawCmd(
    Tk_Window tkwin,		/* 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. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    (void)tkwin;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "window");
	return TCL_ERROR;
    }
    if (wmPtr->iconFor != NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
5691
5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705


5706
5707

5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719

5720
5721
5722
5723
5724
5725
5726
5473
5474
5475
5476
5477
5478
5479

5480
5481
5482
5483
5484


5485
5486
5487

5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499

5500
5501
5502
5503
5504
5505
5506
5507







-





-
-
+
+

-
+











-
+







{
    if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {
	Tcl_DoWhenIdle(UpdateGeometryInfo, winPtr);
	wmPtr->flags |= WM_UPDATE_PENDING;
    }
}

	/*ARGSUSED*/
static void
WmWaitVisibilityOrMapProc(
    ClientData clientData,	/* Pointer to window. */
    XEvent *eventPtr)		/* Information about event. */
{
    TkWindow *winPtr = clientData;
    TkWindow *masterPtr = winPtr->wmInfoPtr->masterPtr;
    TkWindow *winPtr = (TkWindow *)clientData;
    TkWindow *containerPtr = winPtr->wmInfoPtr->containerPtr;

    if (masterPtr == NULL)
    if (containerPtr == NULL)
	return;

    if (eventPtr->type == MapNotify) {
	if (!(winPtr->wmInfoPtr->flags & WM_WITHDRAWN)) {
	    TkpWmSetState(winPtr, NormalState);
	}
    } else if (eventPtr->type == UnmapNotify) {
	TkpWmSetState(winPtr, WithdrawnState);
    }

    if (eventPtr->type == VisibilityNotify) {
	int state = masterPtr->wmInfoPtr->hints.initial_state;
	int state = containerPtr->wmInfoPtr->hints.initial_state;

	if ((state == NormalState) || (state == ZoomState)) {
	    state = winPtr->wmInfoPtr->hints.initial_state;
	    if ((state == NormalState) || (state == ZoomState)) {
		UpdateWrapper(winPtr);
	    }
	}
5758
5759
5760
5761
5762
5763
5764
5765

5766
5767
5768
5769
5770
5771
5772
5539
5540
5541
5542
5543
5544
5545

5546
5547
5548
5549
5550
5551
5552
5553







-
+







				 * requested geometry for tkwin. */
    int reqHeight,		/* Height (in grid units) corresponding to the
				 * requested geometry for tkwin. */
    int widthInc, int heightInc)/* Pixel increments corresponding to a change
				 * of one grid unit. */
{
    TkWindow *winPtr = (TkWindow *) tkwin;
    register WmInfo *wmPtr;
    WmInfo *wmPtr;

    /*
     * Ensure widthInc and heightInc are greater than 0
     */

    if (widthInc <= 0) {
	widthInc = 1;
5855
5856
5857
5858
5859
5860
5861
5862

5863
5864
5865
5866
5867
5868
5869
5636
5637
5638
5639
5640
5641
5642

5643
5644
5645
5646
5647
5648
5649
5650







-
+








void
Tk_UnsetGrid(
    Tk_Window tkwin)		/* Token for window that is currently
				 * controlling gridding. */
{
    TkWindow *winPtr = (TkWindow *) tkwin;
    register WmInfo *wmPtr;
    WmInfo *wmPtr;

    /*
     * Find the top-level window for tkwin, plus the window manager
     * information.
     */

    while (!(winPtr->flags & TK_TOP_HIERARCHY)) {
5914
5915
5916
5917
5918
5919
5920
5921

5922
5923
5924
5925
5926
5927
5928
5695
5696
5697
5698
5699
5700
5701

5702
5703
5704
5705
5706
5707
5708
5709







-
+







 */

static void
TopLevelEventProc(
    ClientData clientData,	/* Window for which event occurred. */
    XEvent *eventPtr)		/* Event that just happened. */
{
    register TkWindow *winPtr = clientData;
    TkWindow *winPtr = (TkWindow *)clientData;

    if (eventPtr->type == DestroyNotify) {
	Tk_ErrorHandler handler;

	if (!(winPtr->flags & TK_ALREADY_DEAD)) {
	    /*
	     * A top-level window was deleted externally (e.g., by the window
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968

5969
5970
5971
5972
5973
5974
5975
5735
5736
5737
5738
5739
5740
5741

5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756







-







+







 * Side effects:
 *	Arrange for the window to be resized to satisfy the request (this
 *	happens as a when-idle action).
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static void
TopLevelReqProc(
    ClientData dummy,		/* Not used. */
    Tk_Window tkwin)		/* Information about window. */
{
    TkWindow *winPtr = (TkWindow *) tkwin;
    WmInfo *wmPtr;
    (void)dummy;

    wmPtr = winPtr->wmInfoPtr;
    if (wmPtr) {
	if ((winPtr->flags & TK_EMBEDDED) && (wmPtr->wrapper != NULL)) {
	    SendMessageW(wmPtr->wrapper, TK_GEOMETRYREQ, Tk_ReqWidth(tkwin),
		Tk_ReqHeight(tkwin));
	}
6005
6006
6007
6008
6009
6010
6011
6012
6013


6014
6015
6016
6017
6018
6019
6020
5786
5787
5788
5789
5790
5791
5792


5793
5794
5795
5796
5797
5798
5799
5800
5801







-
-
+
+







UpdateGeometryInfo(
    ClientData clientData)	/* Pointer to the window's record. */
{
    int x, y;			/* Position of border on desktop. */
    int width, height;		/* Size of client area. */
    int min, max;
    RECT rect;
    register TkWindow *winPtr = clientData;
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    TkWindow *winPtr = (TkWindow *)clientData;
    WmInfo *wmPtr = winPtr->wmInfoPtr;

    wmPtr->flags &= ~WM_UPDATE_PENDING;

    /*
     * If the window is minimized or maximized, we should not update our
     * geometry since it will end up with the wrong values. ConfigureToplevel
     * will reschedule UpdateGeometryInfo when the state of the window
6286
6287
6288
6289
6290
6291
6292
6293

6294
6295
6296

6297
6298
6299
6300
6301
6302
6303
6067
6068
6069
6070
6071
6072
6073

6074
6075
6076

6077
6078
6079
6080
6081
6082
6083
6084







-
+


-
+







ParseGeometry(
    Tcl_Interp *interp,		/* Used for error reporting. */
    const char *string,		/* String containing new geometry. Has the
				 * standard form "=wxh+x+y". */
    TkWindow *winPtr)		/* Pointer to top-level window whose geometry
				 * is to be changed. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;
    int x, y, width, height, flags;
    char *end;
    register const char *p = string;
    const char *p = string;

    /*
     * The leading "=" is optional.
     */

    if (*p == '=') {
	p++;
6418
6419
6420
6421
6422
6423
6424
6425

6426
6427
6428
6429
6430
6431
6432
6199
6200
6201
6202
6203
6204
6205

6206
6207
6208
6209
6210
6211
6212
6213







-
+








void
Tk_GetRootCoords(
    Tk_Window tkwin,		/* Token for window. */
    int *xPtr,			/* Where to store x-displacement of (0,0). */
    int *yPtr)			/* Where to store y-displacement of (0,0). */
{
    register TkWindow *winPtr = (TkWindow *) tkwin;
    TkWindow *winPtr = (TkWindow *) tkwin;

    /*
     * If the window is mapped, let Windows figure out the translation.
     */

    if (winPtr->window != None) {
	HWND hwnd = Tk_GetHWND(winPtr->window);
6515
6516
6517
6518
6519
6520
6521


6522
6523
6524
6525
6526
6527
6528
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6311







+
+







    Tk_Window tkwin,		/* Window whose virtual root is to be
				 * queried. */
    int *xPtr, int *yPtr,	/* Store x and y offsets of virtual root
				 * here. */
    int *widthPtr, int *heightPtr)
				/* Store dimensions of virtual root here. */
{
    (void)tkwin;

    *xPtr = GetSystemMetrics(SM_XVIRTUALSCREEN);
    *yPtr = GetSystemMetrics(SM_YVIRTUALSCREEN);
    *widthPtr = GetSystemMetrics(SM_CXVIRTUALSCREEN);
    *heightPtr = GetSystemMetrics(SM_CYVIRTUALSCREEN);
}

/*
6547
6548
6549
6550
6551
6552
6553
6554

6555
6556
6557
6558
6559
6560
6561
6330
6331
6332
6333
6334
6335
6336

6337
6338
6339
6340
6341
6342
6343
6344







-
+








void
Tk_MoveToplevelWindow(
    Tk_Window tkwin,		/* Window to move. */
    int x, int y)		/* New location for window (within parent). */
{
    TkWindow *winPtr = (TkWindow *) tkwin;
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;

    if (!(winPtr->flags & TK_TOP_LEVEL)) {
	Tcl_Panic("Tk_MoveToplevelWindow called with non-toplevel window");
    }
    wmPtr->x = x;
    wmPtr->y = y;
    wmPtr->flags |= WM_MOVE_PENDING;
6598
6599
6600
6601
6602
6603
6604
6605

6606
6607
6608
6609
6610
6611
6612
6381
6382
6383
6384
6385
6386
6387

6388
6389
6390
6391
6392
6393
6394
6395







-
+








void
TkWmProtocolEventProc(
    TkWindow *winPtr,		/* Window to which the event was sent. */
    XEvent *eventPtr)		/* X event. */
{
    WmInfo *wmPtr;
    register ProtocolHandler *protPtr;
    ProtocolHandler *protPtr;
    Atom protocol;
    int result;
    Tcl_Interp *interp;

    wmPtr = winPtr->wmInfoPtr;
    if (wmPtr == NULL) {
	return;
6674
6675
6676
6677
6678
6679
6680
6681

6682
6683

6684
6685
6686
6687
6688
6689
6690
6457
6458
6459
6460
6461
6462
6463

6464
6465

6466
6467
6468
6469
6470
6471
6472
6473







-
+

-
+







    TkWindow *childWinPtr;

    TkWmStackorderToplevelPair *pair =
	    (TkWmStackorderToplevelPair *) lParam;

    /*fprintf(stderr, "Looking up HWND %d\n", hwnd);*/

    hPtr = Tcl_FindHashEntry(pair->table, (char *) hwnd);
    hPtr = Tcl_FindHashEntry(pair->table, hwnd);
    if (hPtr != NULL) {
	childWinPtr = Tcl_GetHashValue(hPtr);
	childWinPtr = (TkWindow *)Tcl_GetHashValue(hPtr);

	/*
	 * Double check that same HWND does not get passed twice.
	 */

	if (childWinPtr == NULL) {
	    Tcl_Panic("duplicate HWND in TkWmStackorderToplevelEnumProc");
6776
6777
6778
6779
6780
6781
6782
6783

6784
6785
6786
6787
6788
6789
6790
6791
6792
6793
6794
6795
6796

6797
6798
6799
6800
6801
6802
6803
6559
6560
6561
6562
6563
6564
6565

6566
6567
6568
6569
6570
6571
6572
6573
6574
6575
6576
6577
6578

6579
6580
6581
6582
6583
6584
6585
6586







-
+












-
+







    /*
     * Map HWND ids to a TkWindow of the wrapped toplevel.
     */

    Tcl_InitHashTable(&table, TCL_ONE_WORD_KEYS);
    TkWmStackorderToplevelWrapperMap(parentPtr, parentPtr->display, &table);

    windows = ckalloc((table.numEntries+1) * sizeof(TkWindow *));
    windows = (TkWindow **)ckalloc((table.numEntries+1) * sizeof(TkWindow *));

    /*
     * Special cases: If zero or one toplevels were mapped there is no need to
     * call EnumWindows.
     */

    switch (table.numEntries) {
    case 0:
	windows[0] = NULL;
	goto done;
    case 1:
	hPtr = Tcl_FirstHashEntry(&table, &search);
	windows[0] = Tcl_GetHashValue(hPtr);
	windows[0] = (TkWindow *)Tcl_GetHashValue(hPtr);
	windows[1] = NULL;
	goto done;
    }

    /*
     * We will be inserting into the array starting at the end and working our
     * way to the beginning since EnumWindows returns windows in highest to
6952
6953
6954
6955
6956
6957
6958
6959

6960
6961
6962
6963
6964
6965
6966
6735
6736
6737
6738
6739
6740
6741

6742
6743
6744
6745
6746
6747
6748
6749







-
+







    }

    /*
     * Make a new bigger array and use it to reset the property.
     * Automatically add the toplevel itself as the last element of the list.
     */

    newPtr = ckalloc((count+2) * sizeof(TkWindow *));
    newPtr = (TkWindow **)ckalloc((count+2) * sizeof(TkWindow *));
    if (count > 0) {
	memcpy(newPtr, oldPtr, count * sizeof(TkWindow*));
    }
    if (count == 0) {
	count++;
    }
    newPtr[count-1] = winPtr;
8093
8094
8095
8096
8097
8098
8099
8100

8101
8102
8103
8104
8105
8106
8107
7876
7877
7878
7879
7880
7881
7882

7883
7884
7885
7886
7887
7888
7889
7890







-
+








    if (winPtr && winPtr->window) {
	HWND child = Tk_GetHWND(winPtr->window);

	if (message == WM_SETFOCUS) {
	    SetFocus(child);
	    result = 0;
	} else if (!Tk_TranslateWinEvent(child, message, wParam, lParam,
	} else if (!TkTranslateWinEvent(child, message, wParam, lParam,
		&result)) {
	    result = DefWindowProcW(hwnd, message, wParam, lParam);
	}
    } else {
	result = DefWindowProcW(hwnd, message, wParam, lParam);
    }

8248
8249
8250
8251
8252
8253
8254
8255

8256
8257
8258
8259
8260
8261
8262
8031
8032
8033
8034
8035
8036
8037

8038
8039
8040
8041
8042
8043
8044
8045







-
+







 *
 *	This function is called to activate a Tk window.
 */

static void
GenerateActivateEvent(TkWindow * winPtr, const int *flagPtr)
{
    ActivateEvent *eventPtr = ckalloc(sizeof(ActivateEvent));
    ActivateEvent *eventPtr = (ActivateEvent *)ckalloc(sizeof(ActivateEvent));

    eventPtr->ev.proc = ActivateWindow;
    eventPtr->winPtr = winPtr;
    eventPtr->flagPtr = flagPtr;
    eventPtr->hwnd = Tk_GetHWND(winPtr->window);
    Tcl_QueueEvent((Tcl_Event *)eventPtr, TCL_QUEUE_TAIL);
}
8351
8352
8353
8354
8355
8356
8357
8358

8359
8360
8361
8362
8363
8364
8365
8134
8135
8136
8137
8138
8139
8140

8141
8142
8143
8144
8145
8146
8147
8148







-
+







 *----------------------------------------------------------------------
 */

void
TkWinSetForegroundWindow(
    TkWindow *winPtr)
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;

    if (wmPtr->wrapper != NULL) {
	SetForegroundWindow(wmPtr->wrapper);
    } else {
	SetForegroundWindow(Tk_GetHWND(winPtr->window));
    }
}
8381
8382
8383
8384
8385
8386
8387
8388

8389
8390
8391
8392
8393
8394
8395
8164
8165
8166
8167
8168
8169
8170

8171
8172
8173
8174
8175
8176
8177
8178







-
+







 *----------------------------------------------------------------------
 */

void
TkpWinToplevelWithDraw(
    TkWindow *winPtr)
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;

    wmPtr->flags |= WM_WITHDRAWN;
    TkpWmSetState(winPtr, WithdrawnState);
}

/*
 *----------------------------------------------------------------------
8432
8433
8434
8435
8436
8437
8438
8439

8440
8441
8442
8443
8444
8445
8446
8215
8216
8217
8218
8219
8220
8221

8222
8223
8224
8225
8226
8227
8228
8229







-
+







 *----------------------------------------------------------------------
 */

void
TkpWinToplevelDeiconify(
    TkWindow *winPtr)
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;

    wmPtr->flags &= ~WM_WITHDRAWN;

    /*
     * If WM_UPDATE_PENDING is true, a pending UpdateGeometryInfo may need to
     * be called first to update a withdrawn toplevel's geometry before it is
     * deiconified by TkpWmSetState. Don't bother if we've never been mapped.
8500
8501
8502
8503
8504
8505
8506
8507

8508
8509
8510
8511
8512
8513
8514
8283
8284
8285
8286
8287
8288
8289

8290
8291
8292
8293
8294
8295
8296
8297







-
+







 *----------------------------------------------------------------------
 */

long
TkpWinToplevelIsControlledByWm(
    TkWindow *winPtr)
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;

    if (!wmPtr) {
	return 0;
    }
    return ((wmPtr->width != -1) && (wmPtr->height != -1)) ? 1 : 0;
}

8530
8531
8532
8533
8534
8535
8536
8537

8538
8539
8540
8541
8542
8543
8544
8313
8314
8315
8316
8317
8318
8319

8320
8321
8322
8323
8324
8325
8326
8327







-
+







 */

long
TkpWinToplevelMove(
    TkWindow *winPtr,
    int x, int y)
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;

    if (wmPtr && x >= 0 && y >= 0 && !TkpWinToplevelIsControlledByWm(winPtr)) {
	Tk_MoveToplevelWindow((Tk_Window) winPtr, x, y);
    }
    return ((winPtr->changes.x << 16) & 0xffff0000)
	    | (winPtr->changes.y & 0xffff);
}
8562
8563
8564
8565
8566
8567
8568
8569

8570
8571
8572
8573
8574
8575
8576
8345
8346
8347
8348
8349
8350
8351

8352
8353
8354
8355
8356
8357
8358
8359







-
+








long
TkpWinToplevelOverrideRedirect(
    TkWindow *winPtr,
    int reqValue)
{
    int curValue;
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;

    curValue = Tk_Attributes((Tk_Window) winPtr)->override_redirect;
    if (reqValue < 0) {
	return curValue;
    }

    if (curValue != reqValue) {
8609
8610
8611
8612
8613
8614
8615
8616

8617
8618
8619
8620
8621
8622
8623
8392
8393
8394
8395
8396
8397
8398

8399
8400
8401
8402
8403
8404
8405
8406







-
+







 *----------------------------------------------------------------------
 */

void
TkpWinToplevelDetachWindow(
    TkWindow *winPtr)
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    WmInfo *wmPtr = winPtr->wmInfoPtr;

    if (winPtr->flags & TK_EMBEDDED) {
	int state = SendMessageW(wmPtr->wrapper, TK_STATE, -1, -1) - 1;

	SendMessageW(wmPtr->wrapper, TK_SETMENU, 0, 0);
	SendMessageW(wmPtr->wrapper, TK_DETACHWINDOW, 0, 0);
	winPtr->flags &= ~TK_EMBEDDED;
Changes to win/tkWinX.c.
1
2
3
4
5
6
7
8



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
1
2
3
4
5



6
7
8
9
10
11
12
13
14
15










16
17
18
19
20
21
22





-
-
-
+
+
+







-
-
-
-
-
-
-
-
-
-







/*
 * tkWinX.c --
 *
 *	This file contains Windows emulation procedures for X routines.
 *
 * Copyright (c) 1995-1996 Sun Microsystems, Inc.
 * Copyright (c) 1994 Software Research Associates, Inc.
 * Copyright (c) 1998-2000 by Scriptics Corporation.
 * Copyright © 1995-1996 Sun Microsystems, Inc.
 * Copyright © 1994 Software Research Associates, 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.
 */

#include "tkWinInt.h"

/*
 * The w32api 1.1 package (included in Mingw 1.1) does not define _WIN32_IE by
 * default. Define it here to gain access to the InitCommonControlsEx API in
 * commctrl.h.
 */

#ifndef _WIN32_IE
#define _WIN32_IE 0x0550 /* IE 5.5 */
#endif

#include <commctrl.h>
#ifdef _MSC_VER
#   pragma comment (lib, "comctl32.lib")
#   pragma comment (lib, "advapi32.lib")
#endif

/*
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
56
57
58
59
60
61
62

63
64
65
66
67
68
69







-







 * Declarations of static variables used in this file.
 */

static const char winScreenName[] = ":0"; /* Default name of windows display. */
static HINSTANCE tkInstance = NULL;	/* Application instance handle. */
static int childClassInitialized;	/* Registered child class? */
static WNDCLASSW childClass;		/* Window class for child windows. */
static int tkPlatformId = 0;		/* version of Windows platform */
static int tkWinTheme = 0;		/* See TkWinGetPlatformTheme */
static Tcl_Encoding keyInputEncoding = NULL;
					/* The current character encoding for
					 * keyboard input */
static int keyInputCharset = -1;	/* The Win32 CHARSET for the keyboard
					 * encoding */
static Tcl_Encoding unicodeEncoding = NULL;
101
102
103
104
105
106
107
108

109
110
111
112
113
114
115
90
91
92
93
94
95
96

97
98
99
100
101
102
103
104







-
+







/*
 * Forward declarations of functions used in this file.
 */

static void		GenerateXEvent(HWND hwnd, UINT message,
			    WPARAM wParam, LPARAM lParam);
static unsigned int	GetState(UINT message, WPARAM wParam, LPARAM lParam);
static void 		GetTranslatedKey(XKeyEvent *xkey, UINT type);
static void 		GetTranslatedKey(TkKeyEvent *xkey, UINT type);
static void		UpdateInputLanguage(int charset);
static int		HandleIMEComposition(HWND hwnd, LPARAM lParam);

/*
 *----------------------------------------------------------------------
 *
 * TkGetServerInfo --
132
133
134
135
136
137
138

139
140
141
142
143



144
145
146
147
148
149
150
121
122
123
124
125
126
127
128
129
130



131
132
133
134
135
136
137
138
139
140







+


-
-
-
+
+
+







    Tcl_Interp *interp,		/* The server information is returned in this
				 * interpreter's result. */
    Tk_Window tkwin)		/* Token for window; this selects a particular
				 * display and server. */
{
    static char buffer[32]; /* Empty string means not initialized yet. */
    OSVERSIONINFOW os;
    (void)tkwin;

    if (!buffer[0]) {
	HANDLE handle = GetModuleHandleW(L"NTDLL");
	int(__stdcall *getversion)(void *) =
		(int(__stdcall *)(void *))GetProcAddress(handle, "RtlGetVersion");
	HMODULE handle = GetModuleHandleW(L"NTDLL");
	int(__stdcall *getversion)(void *) = (int(__stdcall *)(void *))
		(void *)GetProcAddress(handle, "RtlGetVersion");
	os.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
	if (!getversion || getversion(&os)) {
	    GetVersionExW(&os);
	}
	/* Write the first character last, preventing multi-thread issues. */
	sprintf(buffer+1, "indows %d.%d %d %s", (int)os.dwMajorVersion,
		(int)os.dwMinorVersion, (int)os.dwBuildNumber,
266
267
268
269
270
271
272
273

274
275
276
277
278
279
280
281

282
283
284
285
286
287
288
256
257
258
259
260
261
262

263
264
265
266
267
268
269
270

271
272
273
274
275
276
277
278







-
+







-
+







    /*
     * Initialize input language info
     */

    if (GetLocaleInfoW(LANGIDFROMLCID(PTR2INT(GetKeyboardLayout(0))),
	       LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER,
	       (LPWSTR) &lpCP, sizeof(lpCP)/sizeof(WCHAR))
	    && TranslateCharsetInfo(INT2PTR(lpCP), &lpCs, TCI_SRCCODEPAGE)) {
	    && TranslateCharsetInfo((DWORD *)INT2PTR(lpCP), &lpCs, TCI_SRCCODEPAGE)) {
	UpdateInputLanguage((int) lpCs.ciCharset);
    }

    /*
     * Make sure we cleanup on finalize.
     */

    TkCreateExitHandler(TkWinXCleanup, (ClientData) hInstance);
    TkCreateExitHandler(TkWinXCleanup, hInstance);
}

/*
 *----------------------------------------------------------------------
 *
 * TkWinXCleanup --
 *
297
298
299
300
301
302
303
304

305
306
307
308
309
310
311
287
288
289
290
291
292
293

294
295
296
297
298
299
300
301







-
+







 *----------------------------------------------------------------------
 */

void
TkWinXCleanup(
    ClientData clientData)
{
    HINSTANCE hInstance = (HINSTANCE) clientData;
    HINSTANCE hInstance = (HINSTANCE)clientData;

    /*
     * Clean up our own class.
     */

    if (childClassInitialized) {
	childClassInitialized = 0;
324
325
326
327
328
329
330
331

332
333

334
335
336
337
338
339
340



341
342
343
344
345
346
347
348
349
350

351
352

353
354
355
356

357
358




359
360

361
362
363
364
365
366

367
368
369
370
371

372
373
374
375
376
377
378
379
380

381
382
383
384
385


386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
314
315
316
317
318
319
320

321
322

323

324
325
326



327
328
329




330
331
332
333
334

335
336

337
338
339
340
341
342


343
344
345
346
347

348
349
350
351



352
353
354
355
356

357
358
359
360
361
362
363
364
365

366
367
368
369
370
371
372
373
374
375
376
377



























378
379
380
381
382
383
384







-
+

-
+
-



-
-
-
+
+
+
-
-
-
-





-
+

-
+




+
-
-
+
+
+
+

-
+



-
-
-
+




-
+








-
+





+
+




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







    TkWinWmCleanup(hInstance);
    TkWinCleanupContainerList();
}

/*
 *----------------------------------------------------------------------
 *
 * TkWinGetPlatformId --
 * TkWinGetPlatformTheme --
 *
 *	Determines whether running under NT, 95, or Win32s, to allow runtime
 *	Return the Windows drawing style we should be using.
 *	conditional code. Win32s is no longer supported.
 *
 * Results:
 *	The return value is one of:
 *		VER_PLATFORM_WIN32s	   Win32s on Windows 3.1 (not supported)
 *		VER_PLATFORM_WIN32_WINDOWS Win32 on Windows 95, 98, ME (not supported)
 *		VER_PLATFORM_WIN32_NT	Win32 on Windows XP, Vista, Windows 7, Windows 8
 *	    TK_THEME_WIN_CLASSIC	95/98/NT or XP in classic mode
 *	    TK_THEME_WIN_XP		XP not in classic mode
 *	    TK_THEME_WIN_VISTA	Vista or higher
 *		VER_PLATFORM_WIN32_CE	Win32 on Windows CE
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TkWinGetPlatformId(void)
TkWinGetPlatformTheme(void)
{
    if (tkPlatformId == 0) {
    if (tkWinTheme == 0) {
	OSVERSIONINFOW os;

	os.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
	GetVersionExW(&os);

	tkPlatformId = os.dwPlatformId;

	if (os.dwPlatformId != VER_PLATFORM_WIN32_NT) {
	    Tcl_Panic("Windows NT is the only supported platform");
	}

	/*
	 * Set tkWinTheme to be TK_THEME_WIN_XP or TK_THEME_WIN_CLASSIC. The
	 * Set tkWinTheme to be TK_THEME_WIN_(CLASSIC|XP|VISTA). The
	 * TK_THEME_WIN_CLASSIC could be set even when running under XP if the
	 * windows classic theme was selected.
	 */

	if ((os.dwPlatformId == VER_PLATFORM_WIN32_NT) &&
		(os.dwMajorVersion == 5 && os.dwMinorVersion == 1)) {
	if (os.dwMajorVersion == 5 && os.dwMinorVersion >= 1) {
	    HKEY hKey;
	    LPCWSTR szSubKey = L"Control Panel\\Appearance";
	    LPCWSTR szCurrent = L"Current";
	    DWORD dwSize = 200;
	    char pBuffer[200];
	    WCHAR pBuffer[200];

	    memset(pBuffer, 0, dwSize);
	    if (RegOpenKeyExW(HKEY_CURRENT_USER, szSubKey, 0L,
		    KEY_READ, &hKey) != ERROR_SUCCESS) {
		tkWinTheme = TK_THEME_WIN_XP;
	    } else {
		RegQueryValueExW(hKey, szCurrent, NULL, NULL, (LPBYTE) pBuffer, &dwSize);
		RegCloseKey(hKey);
		if (strcmp(pBuffer, "Windows Standard") == 0) {
		if (wcscmp(pBuffer, L"Windows Standard") == 0) {
		    tkWinTheme = TK_THEME_WIN_CLASSIC;
		} else {
		    tkWinTheme = TK_THEME_WIN_XP;
		}
	    }
	} else if (os.dwMajorVersion > 5) {
	    tkWinTheme = TK_THEME_WIN_VISTA;
	} else {
	    tkWinTheme = TK_THEME_WIN_CLASSIC;
	}
    }
    return tkPlatformId;
}

/*
 *----------------------------------------------------------------------
 *
 * TkWinGetPlatformTheme --
 *
 *	Return the Windows drawing style we should be using.
 *
 * Results:
 *	The return value is one of:
 *	    TK_THEME_WIN_CLASSIC	95/98/NT or XP in classic mode
 *	    TK_THEME_WIN_XP		XP not in classic mode
 *
 * Side effects:
 *	Could invoke TkWinGetPlatformId.
 *
 *----------------------------------------------------------------------
 */

int
TkWinGetPlatformTheme(void)
{
    if (tkPlatformId == 0) {
	TkWinGetPlatformId();
    }
    return tkWinTheme;
}

/*
 *----------------------------------------------------------------------
 *
 * TkGetDefaultScreenName --
432
433
434
435
436
437
438
439

440
441


442
443
444
445
446
447
448
393
394
395
396
397
398
399

400
401
402
403
404
405
406
407
408
409
410
411







-
+


+
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

const char *
TkGetDefaultScreenName(
    Tcl_Interp *interp,		/* Not used. */
    Tcl_Interp *dummy,		/* Not used. */
    const char *screenName)	/* If NULL, use default string. */
{
    (void)dummy;

    if ((screenName == NULL) || (screenName[0] == '\0')) {
	screenName = winScreenName;
    }
    return screenName;
}

/*
487
488
489
490
491
492
493
494

495
496
497
498
499
500

501
502
503
504
505
506
507
450
451
452
453
454
455
456

457
458
459
460
461
462

463
464
465
466
467
468
469
470







-
+





-
+







     * information: the number of color planes and the number of pixels per
     * plane. Need to remember both quantities so that when constructing an
     * HBITMAP for offscreen rendering, we can specify the correct value for
     * the number of planes. Otherwise the HBITMAP won't be compatible with
     * the HWND and we'll just get blank spots copied onto the screen.
     */

    screen->ext_data = INT2PTR(GetDeviceCaps(dc, PLANES));
    screen->ext_data = (XExtData *)INT2PTR(GetDeviceCaps(dc, PLANES));
    screen->root_depth = GetDeviceCaps(dc, BITSPIXEL) * PTR2INT(screen->ext_data);

    if (screen->root_visual != NULL) {
	ckfree(screen->root_visual);
    }
    screen->root_visual = ckalloc(sizeof(Visual));
    screen->root_visual = (Visual *)ckalloc(sizeof(Visual));
    screen->root_visual->visualid = 0;
    if (GetDeviceCaps(dc, RASTERCAPS) & RC_PALETTE) {
	screen->root_visual->map_entries = GetDeviceCaps(dc, SIZEPALETTE);
	screen->root_visual->c_class = PseudoColor;
	screen->root_visual->red_mask = 0x0;
	screen->root_visual->green_mask = 0x0;
	screen->root_visual->blue_mask = 0x0;
539
540
541
542
543
544
545
546

547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567

568
569
570
571
572
573
574
575
576
577
578
579
580
581

582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621

622
623
624
625
626
627
628
629
630
631
632
633
634
635





636
637



















































638
639
640
641
642
643
644
502
503
504
505
506
507
508

509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526


527

528
529
530
531
532
533
534
535
536
537
538
539



540





































541
542

543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622







-
+

















-
-

-
+











-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-


-
+














+
+
+
+
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    screen->cmap = XCreateColormap(display, None, screen->root_visual,
	    AllocNone);
}

/*
 *----------------------------------------------------------------------
 *
 * TkpOpenDisplay --
 * TkpOpenDisplay/XkbOpenDisplay --
 *
 *	Create the Display structure and fill it with device specific
 *	information.
 *
 * Results:
 *	Returns a TkDisplay structure on success or NULL on failure.
 *
 * Side effects:
 *	Allocates a new TkDisplay structure.
 *
 *----------------------------------------------------------------------
 */

TkDisplay *
TkpOpenDisplay(
    const char *display_name)
{
    Screen *screen;
    TkWinDrawable *twdPtr;
    Display *display;
    ThreadSpecificData *tsdPtr =
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    DWORD initialWheelTick;

    if (tsdPtr->winDisplay != NULL) {
	if (!strcmp(tsdPtr->winDisplay->display->display_name, display_name)) {
	    return tsdPtr->winDisplay;
	} else {
	    return NULL;
	}
    }

    display = ckalloc(sizeof(Display));
    ZeroMemory(display, sizeof(Display));

    display = XkbOpenDisplay((char *)display_name, NULL, NULL, NULL, NULL, NULL);
    display->display_name = ckalloc(strlen(display_name) + 1);
    strcpy(display->display_name, display_name);

    display->cursor_font = 1;
    display->nscreens = 1;
    display->request = 1;
    display->qlen = 0;

    screen = ckalloc(sizeof(Screen));
    ZeroMemory(screen, sizeof(Screen));
    screen->display = display;

    /*
     * Set up the root window.
     */

    twdPtr = ckalloc(sizeof(TkWinDrawable));
    if (twdPtr == NULL) {
	return NULL;
    }
    twdPtr->type = TWD_WINDOW;
    twdPtr->window.winPtr = NULL;
    twdPtr->window.handle = NULL;
    screen->root = (Window)twdPtr;

    /*
     * Note that these pixel values are not palette relative.
     */

    screen->white_pixel = RGB(255, 255, 255);
    screen->black_pixel = RGB(0, 0, 0);
    screen->cmap = None;

    display->screens		= screen;
    display->nscreens		= 1;
    display->default_screen	= 0;

    TkWinDisplayChanged(display);

    tsdPtr->winDisplay = ckalloc(sizeof(TkDisplay));
    tsdPtr->winDisplay =(TkDisplay *) ckalloc(sizeof(TkDisplay));
    ZeroMemory(tsdPtr->winDisplay, sizeof(TkDisplay));
    tsdPtr->winDisplay->display = display;
    tsdPtr->updatingClipboard = FALSE;
    initialWheelTick = GetTickCount();
    tsdPtr->vWheelTickPrev = initialWheelTick;
    tsdPtr->hWheelTickPrev = initialWheelTick;
    tsdPtr->vWheelAcc = 0;
    tsdPtr->hWheelAcc = 0;

    /*
     * Key map info must be available immediately, because of "send event".
     */
    TkpInitKeymapInfo(tsdPtr->winDisplay);

    /*
     * Key map info must be available immediately, because of "send event".
     */
    TkpInitKeymapInfo(tsdPtr->winDisplay);

    return tsdPtr->winDisplay;
}

Display *
XkbOpenDisplay(
	const char *name,
	int *ev_rtrn,
	int *err_rtrn,
	int *major_rtrn,
	int *minor_rtrn,
	int *reason)
{
    Display *display = (Display *)ckalloc(sizeof(Display));
    Screen *screen = (Screen *)ckalloc(sizeof(Screen));
    TkWinDrawable *twdPtr = (TkWinDrawable *)ckalloc(sizeof(TkWinDrawable));

    ZeroMemory(screen, sizeof(Screen));
    ZeroMemory(display, sizeof(Display));

    /*
     * Note that these pixel values are not palette relative.
     */

    screen->white_pixel = RGB(255, 255, 255);
    screen->black_pixel = RGB(0, 0, 0);
    screen->cmap = None;

    display->screens		= screen;
    display->nscreens		= 1;
    display->default_screen	= 0;

    twdPtr->type = TWD_WINDOW;
    twdPtr->window.winPtr = NULL;
    twdPtr->window.handle = NULL;
    screen->root = (Window)twdPtr;
    screen->display = display;

    display->display_name = (char  *)ckalloc(strlen(name) + 1);
    strcpy(display->display_name, name);

    display->cursor_font = 1;
    display->nscreens = 1;
    display->request = 1;
    display->qlen = 0;

    if (ev_rtrn) *ev_rtrn = 0;
    if (err_rtrn) *err_rtrn = 0;
    if (major_rtrn) *major_rtrn = 0;
    if (minor_rtrn) *minor_rtrn = 0;
    if (reason) *reason = 0;

    return display;
}

/*
 *----------------------------------------------------------------------
 *
 * TkpCloseDisplay --
 *
 *	Closes and deallocates a Display structure created with the
672
673
674
675
676
677
678
679

680
681
682
683
684
685
686
650
651
652
653
654
655
656

657
658
659
660
661
662
663
664







-
+







	ckfree(display->display_name);
    }
    if (display->screens != NULL) {
	if (display->screens->root_visual != NULL) {
	    ckfree(display->screens->root_visual);
	}
	if (display->screens->root != None) {
	    ckfree(display->screens->root);
	    ckfree((char *)display->screens->root);
	}
	if (display->screens->cmap != None) {
	    XFreeColormap(display, display->screens->cmap);
	}
	ckfree(display->screens);
    }
    ckfree(display);
712
713
714
715
716
717
718
719

720
721
722
723
724
725
726
690
691
692
693
694
695
696

697
698
699
700
701
702
703
704







-
+







    if (dispPtr->clipWindow != NULL) {
	Tk_DeleteSelHandler(dispPtr->clipWindow, dispPtr->clipboardAtom,
		dispPtr->applicationAtom);
	Tk_DeleteSelHandler(dispPtr->clipWindow, dispPtr->clipboardAtom,
		dispPtr->windowAtom);

	Tk_DestroyWindow(dispPtr->clipWindow);
	Tcl_Release((ClientData) dispPtr->clipWindow);
	Tcl_Release(dispPtr->clipWindow);
	dispPtr->clipWindow = NULL;
    }
}

/*
 *----------------------------------------------------------------------
 *
738
739
740
741
742
743
744



745
746
747
748
749
750
751
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732







+
+
+







 */

int
XBell(
    Display *display,
    int percent)
{
    (void)display;
    (void)percent;

    MessageBeep(MB_OK);
    return Success;
}

/*
 *----------------------------------------------------------------------
 *
823
824
825
826
827
828
829
830

831
832
833
834
835
836
837
838
839

840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856

857
858
859
860
861
862
863
864
865
866
867
868
869
870
871

872
873
874
875
876
877
878
804
805
806
807
808
809
810

811
812
813
814
815
816
817
818
819

820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836

837
838
839
840
841
842
843
844
845
846
847
848
849
850
851

852
853
854
855
856
857
858
859







-
+








-
+
















-
+














-
+







    case WM_UNICHAR:
        if (wParam == UNICODE_NOCHAR) {
	    /* If wParam is UNICODE_NOCHAR and the application processes
	     * this message, then return TRUE. */
	    result = 1;
	} else {
	    /* If the event was translated, we must return 0 */
            if (Tk_TranslateWinEvent(hwnd, message, wParam, lParam, &result)) {
            if (TkTranslateWinEvent(hwnd, message, wParam, lParam, &result)) {
                result = 0;
	    } else {
	        result = 1;
	    }
	}
	break;

    default:
	if (!Tk_TranslateWinEvent(hwnd, message, wParam, lParam, &result)) {
	if (!TkTranslateWinEvent(hwnd, message, wParam, lParam, &result)) {
	    result = DefWindowProcW(hwnd, message, wParam, lParam);
	}
	break;
    }

    /*
     * Handle any newly queued events before returning control to Windows.
     */

    Tcl_ServiceAll();
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * Tk_TranslateWinEvent --
 * TkTranslateWinEvent --
 *
 *	This function is called by widget window functions to handle the
 *	translation from Win32 events to Tk events.
 *
 * Results:
 *	Returns 1 if the event was handled, else 0.
 *
 * Side effects:
 *	Depends on the event.
 *
 *----------------------------------------------------------------------
 */

int
Tk_TranslateWinEvent(
TkTranslateWinEvent(
    HWND hwnd,
    UINT message,
    WPARAM wParam,
    LPARAM lParam,
    LRESULT *resultPtr)
{
    *resultPtr = 0;
933
934
935
936
937
938
939
940

941
942
943
944
945
946
947
914
915
916
917
918
919
920

921
922
923
924
925
926
927
928







-
+







    case WM_XBUTTONDOWN:
    case WM_XBUTTONDBLCLK:
    case WM_LBUTTONUP:
    case WM_MBUTTONUP:
    case WM_RBUTTONUP:
    case WM_XBUTTONUP:
    case WM_MOUSEMOVE:
	Tk_PointerEvent(hwnd, (short) LOWORD(lParam), (short) HIWORD(lParam));
	TkWinPointerEvent(hwnd, (short) LOWORD(lParam), (short) HIWORD(lParam));
	return 1;

    case WM_SYSKEYDOWN:
    case WM_KEYDOWN:
	if (wParam == VK_PACKET) {
	    /*
	     * This will trigger WM_CHAR event(s) with unicode data.
996
997
998
999
1000
1001
1002
1003

1004
1005
1006
1007
1008
1009
1010
977
978
979
980
981
982
983

984
985
986
987
988
989
990
991







-
+







static void
GenerateXEvent(
    HWND hwnd,
    UINT message,
    WPARAM wParam,
    LPARAM lParam)
{
    XEvent event;
    union {XEvent x; TkKeyEvent key;} event;
    TkWindow *winPtr;
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if ((message == WM_MOUSEWHEEL) || (message == WM_MOUSEHWHEEL)) {
	union {LPARAM lParam; POINTS point;} root;
	POINT pos;
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033





1034
1035
1036
1037
1038
1039

1040
1041
1042
1043
1044




1045
1046

1047
1048
1049
1050
1051
1052


1053
1054
1055


1056
1057
1058
1059
1060
1061
1062
1003
1004
1005
1006
1007
1008
1009





1010
1011
1012
1013
1014
1015
1016
1017
1018
1019

1020
1021




1022
1023
1024
1025
1026

1027
1028
1029
1030
1031


1032
1033
1034


1035
1036
1037
1038
1039
1040
1041
1042
1043







-
-
-
-
-
+
+
+
+
+





-
+

-
-
-
-
+
+
+
+

-
+




-
-
+
+

-
-
+
+







    }

    winPtr = (TkWindow *) Tk_HWNDToWindow(hwnd);
    if (!winPtr || winPtr->window == None) {
	return;
    }

    memset(&event, 0, sizeof(XEvent));
    event.xany.serial = winPtr->display->request++;
    event.xany.send_event = False;
    event.xany.display = winPtr->display;
    event.xany.window = winPtr->window;
    memset(&event.x, 0, sizeof(XEvent));
    event.x.xany.serial = winPtr->display->request++;
    event.x.xany.send_event = False;
    event.x.xany.display = winPtr->display;
    event.x.xany.window = winPtr->window;

    switch (message) {
    case WM_PAINT: {
	PAINTSTRUCT ps;

	event.type = Expose;
	event.x.type = Expose;
	BeginPaint(hwnd, &ps);
	event.xexpose.x = ps.rcPaint.left;
	event.xexpose.y = ps.rcPaint.top;
	event.xexpose.width = ps.rcPaint.right - ps.rcPaint.left;
	event.xexpose.height = ps.rcPaint.bottom - ps.rcPaint.top;
	event.x.xexpose.x = ps.rcPaint.left;
	event.x.xexpose.y = ps.rcPaint.top;
	event.x.xexpose.width = ps.rcPaint.right - ps.rcPaint.left;
	event.x.xexpose.height = ps.rcPaint.bottom - ps.rcPaint.top;
	EndPaint(hwnd, &ps);
	event.xexpose.count = 0;
	event.x.xexpose.count = 0;
	break;
    }

    case WM_CLOSE:
	event.type = ClientMessage;
	event.xclient.message_type =
	event.x.type = ClientMessage;
	event.x.xclient.message_type =
		Tk_InternAtom((Tk_Window) winPtr, "WM_PROTOCOLS");
	event.xclient.format = 32;
	event.xclient.data.l[0] =
	event.x.xclient.format = 32;
	event.x.xclient.data.l[0] =
		Tk_InternAtom((Tk_Window) winPtr, "WM_DELETE_WINDOW");
	break;

    case WM_SETFOCUS:
    case WM_KILLFOCUS: {
	TkWindow *otherWinPtr = (TkWindow *) Tk_HWNDToWindow((HWND) wParam);

1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094




1095
1096
1097
1098
1099
1100
1101
1065
1066
1067
1068
1069
1070
1071




1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082







-
-
-
-
+
+
+
+







	    Tk_SetCaretPos((Tk_Window) winPtr, 0, 0, 0);
	}

	if (otherWinPtr == winPtr) {
	    return;
	}

	event.xany.window = winPtr->window;
	event.type = (message == WM_SETFOCUS) ? FocusIn : FocusOut;
	event.xfocus.mode = NotifyNormal;
	event.xfocus.detail = NotifyNonlinear;
	event.x.xany.window = winPtr->window;
	event.x.type = (message == WM_SETFOCUS) ? FocusIn : FocusOut;
	event.x.xfocus.mode = NotifyNormal;
	event.x.xfocus.detail = NotifyNonlinear;

	/*
	 * Destroy the caret if we own it. If we are moving to another Tk
	 * window, it will reclaim and reposition it with Tk_SetCaretPos.
	 */

	if (message == WM_KILLFOCUS) {
1109
1110
1111
1112
1113
1114
1115
1116
1117


1118
1119

1120
1121
1122
1123
1124
1125
1126
1090
1091
1092
1093
1094
1095
1096


1097
1098
1099

1100
1101
1102
1103
1104
1105
1106
1107







-
-
+
+

-
+







	    /*
	     * We want to avoid this event if we are the ones that caused this
	     * event.
	     */

	    return;
	}
	event.type = SelectionClear;
	event.xselectionclear.selection =
	event.x.type = SelectionClear;
	event.x.xselectionclear.selection =
		Tk_InternAtom((Tk_Window)winPtr, "CLIPBOARD");
	event.xselectionclear.time = TkpGetMS();
	event.x.xselectionclear.time = TkpGetMS();
	break;

    case WM_MOUSEWHEEL:
    case WM_MOUSEHWHEEL:
    case WM_CHAR:
    case WM_UNICHAR:
    case WM_SYSKEYDOWN:
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156









1157
1158
1159
1160
1161
1162
1163
1122
1123
1124
1125
1126
1127
1128









1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144







-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+







	clientPoint.y = root.point.y;
	ScreenToClient(hwnd, &clientPoint);

	/*
	 * Set up the common event fields.
	 */

	event.xbutton.root = RootWindow(winPtr->display, winPtr->screenNum);
	event.xbutton.subwindow = None;
	event.xbutton.x = clientPoint.x;
	event.xbutton.y = clientPoint.y;
	event.xbutton.x_root = root.point.x;
	event.xbutton.y_root = root.point.y;
	event.xbutton.state = state;
	event.xbutton.time = time;
	event.xbutton.same_screen = True;
	event.x.xbutton.root = RootWindow(winPtr->display, winPtr->screenNum);
	event.x.xbutton.subwindow = None;
	event.x.xbutton.x = clientPoint.x;
	event.x.xbutton.y = clientPoint.y;
	event.x.xbutton.x_root = root.point.x;
	event.x.xbutton.y_root = root.point.y;
	event.x.xbutton.state = state;
	event.x.xbutton.time = time;
	event.x.xbutton.same_screen = True;

	/*
	 * Now set up event specific fields.
	 */

	switch (message) {
	case WM_MOUSEWHEEL: {
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191




1192
1193
1194
1195
1196
1197
1198
1162
1163
1164
1165
1166
1167
1168




1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179







-
-
-
-
+
+
+
+







	     * We have invented a new X event type to handle this event. It
	     * still uses the KeyPress struct. However, the keycode field has
	     * been overloaded to hold the zDelta of the wheel. Set nbytes to
	     * 0 to prevent conversion of the keycode to a keysym in
	     * TkpGetString. [Bug 1118340].
	     */

	    event.type = MouseWheelEvent;
	    event.xany.send_event = -1;
	    event.xkey.nbytes = 0;
	    event.xkey.keycode = tsdPtr->vWheelAcc / WHEEL_DELTA * WHEEL_DELTA;
	    event.x.type = MouseWheelEvent;
	    event.x.xany.send_event = -1;
	    event.key.nbytes = 0;
	    event.x.xkey.keycode = tsdPtr->vWheelAcc / WHEEL_DELTA * WHEEL_DELTA;
	    tsdPtr->vWheelAcc = tsdPtr->vWheelAcc % WHEEL_DELTA;
	    break;
	}
	case WM_MOUSEHWHEEL: {
	    /*
	     * Support for high resolution wheels (horizontal).
	     */
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224





1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241




1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255



1256
1257
1258
1259
1260
1261
1262
1194
1195
1196
1197
1198
1199
1200





1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218




1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233



1234
1235
1236
1237
1238
1239
1240
1241
1242
1243







-
-
-
-
-
+
+
+
+
+













-
-
-
-
+
+
+
+











-
-
-
+
+
+







	     * We have invented a new X event type to handle this event. It
	     * still uses the KeyPress struct. However, the keycode field has
	     * been overloaded to hold the zDelta of the wheel. Set nbytes to
	     * 0 to prevent conversion of the keycode to a keysym in
	     * TkpGetString. [Bug 1118340].
	     */

	    event.type = MouseWheelEvent;
	    event.xany.send_event = -1;
	    event.xkey.nbytes = 0;
	    event.xkey.state |= ShiftMask;
	    event.xkey.keycode = tsdPtr->hWheelAcc / WHEEL_DELTA * WHEEL_DELTA;
	    event.x.type = MouseWheelEvent;
	    event.x.xany.send_event = -1;
	    event.key.nbytes = 0;
	    event.x.xkey.state |= ShiftMask;
	    event.x.xkey.keycode = tsdPtr->hWheelAcc / WHEEL_DELTA * WHEEL_DELTA;
	    tsdPtr->hWheelAcc = tsdPtr->hWheelAcc % WHEEL_DELTA;
	    break;
	}
	case WM_SYSKEYDOWN:
	case WM_KEYDOWN:
	    /*
	     * Check for translated characters in the event queue. Setting
	     * xany.send_event to -1 indicates to the Windows implementation
	     * of TkpGetString() that this event was generated by windows and
	     * that the Windows extension xkey.trans_chars is filled with the
	     * MBCS characters that came from the TranslateMessage call.
	     */

	    event.type = KeyPress;
	    event.xany.send_event = -1;
	    event.xkey.keycode = wParam;
	    GetTranslatedKey(&event.xkey, (message == WM_KEYDOWN) ? WM_CHAR :
	    event.x.type = KeyPress;
	    event.x.xany.send_event = -1;
	    event.x.xkey.keycode = wParam;
	    GetTranslatedKey(&event.key, (message == WM_KEYDOWN) ? WM_CHAR :
	            WM_SYSCHAR);
	    break;

	case WM_SYSKEYUP:
	case WM_KEYUP:
	    /*
	     * We don't check for translated characters on keyup because Tk
	     * won't know what to do with them. Instead, we wait for the
	     * WM_CHAR messages which will follow.
	     */

	    event.type = KeyRelease;
	    event.xkey.keycode = wParam;
	    event.xkey.nbytes = 0;
	    event.x.type = KeyRelease;
	    event.x.xkey.keycode = wParam;
	    event.key.nbytes = 0;
	    break;

	case WM_CHAR:
	    /*
	     * Synthesize both a KeyPress and a KeyRelease. Strings generated
	     * by Input Method Editor are handled in the following manner:
	     * 1. A series of WM_KEYDOWN & WM_KEYUP messages that cause
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291



1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306



1307
1308
1309


1310
1311
1312
1313
1314
1315
1316
1317
1318
1319


1320
1321
1322
1323
1324


1325
1326
1327
1328
1329
1330
1331
1332
1333






1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354

1355
1356
1357
1358
1359
1360
1361
1362
1363

1364
1365
1366
1367
1368
1369
1370
1263
1264
1265
1266
1267
1268
1269



1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284



1285
1286
1287
1288


1289
1290
1291
1292
1293
1294
1295
1296
1297
1298


1299
1300
1301
1302
1303


1304
1305
1306
1307
1308






1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334

1335
1336
1337
1338
1339
1340
1341
1342
1343

1344
1345
1346
1347
1348
1349
1350
1351







-
-
-
+
+
+












-
-
-
+
+
+

-
-
+
+








-
-
+
+



-
-
+
+



-
-
-
-
-
-
+
+
+
+
+
+




















-
+








-
+







	     *	  event. It is the event-consumer's responsibility to convert
	     *	  the string returned from XLookupString from system encoding
	     *	  to UTF-8.
	     * 5. And finally we get the WM_KEYUP for the "confirm typing"
	     *    character.
	     */

	    event.type = KeyPress;
	    event.xany.send_event = -1;
	    event.xkey.keycode = 0;
	    event.x.type = KeyPress;
	    event.x.xany.send_event = -1;
	    event.x.xkey.keycode = 0;
	    if ((int)wParam & 0xff00) {
		int ch1 = wParam & 0xffff;

		if ((ch1 & 0xfc00) == 0xd800) {
		    tsdPtr->surrogateBuffer = ch1;
		    return;
		}
		if ((ch1 & 0xfc00) == 0xdc00) {
		    ch1 = ((tsdPtr->surrogateBuffer & 0x3ff) << 10) |
			    (ch1 & 0x3ff) | 0x10000;
		    tsdPtr->surrogateBuffer = 0;
		}
		event.xany.send_event = -3;
		event.xkey.nbytes = 0;
		event.xkey.keycode = ch1;
		event.x.xany.send_event = -3;
		event.key.nbytes = 0;
		event.x.xkey.keycode = ch1;
	    } else {
		event.xkey.nbytes = 1;
		event.xkey.trans_chars[0] = (char) wParam;
		event.key.nbytes = 1;
		event.key.trans_chars[0] = (char) wParam;

		if (IsDBCSLeadByte((BYTE) wParam)) {
		    MSG msg;

		    if ((PeekMessageW(&msg, NULL, WM_CHAR, WM_CHAR,
		            PM_NOREMOVE) != 0)
			    && (msg.message == WM_CHAR)) {
			GetMessageW(&msg, NULL, WM_CHAR, WM_CHAR);
			event.xkey.nbytes = 2;
			event.xkey.trans_chars[1] = (char) msg.wParam;
			event.key.nbytes = 2;
			event.key.trans_chars[1] = (char) msg.wParam;
		   }
		}
	    }
	    Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
	    event.type = KeyRelease;
	    Tk_QueueWindowEvent(&event.x, TCL_QUEUE_TAIL);
	    event.x.type = KeyRelease;
	    break;

	case WM_UNICHAR: {
	    event.type = KeyPress;
	    event.xany.send_event = -3;
	    event.xkey.keycode = wParam;
	    event.xkey.nbytes = 0;
	    Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
	    event.type = KeyRelease;
	    event.x.type = KeyPress;
	    event.x.xany.send_event = -3;
	    event.x.xkey.keycode = wParam;
	    event.key.nbytes = 0;
	    Tk_QueueWindowEvent(&event.x, TCL_QUEUE_TAIL);
	    event.x.type = KeyRelease;
	    break;
	}

	}
	break;
    }

    default:
	/*
	 * Don't know how to translate this event, so ignore it. (It probably
	 * should not have got here, but ignoring it should be harmless.)
	 */

	return;
    }

    /*
     * Post the translated event to the main Tk event queue.
     */

    Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
    Tk_QueueWindowEvent(&event.x, TCL_QUEUE_TAIL);
}

/*
 *----------------------------------------------------------------------
 *
 * GetState --
 *
 *	This function constructs a state mask for the mouse buttons and
 *	modifier keys as they were before the event occured.
 *	modifier keys as they were before the event occurred.
 *
 * Results:
 *	Returns a composite value of all the modifier and button state flags
 *	that were set at the time the event occurred.
 *
 * Side effects:
 *	None.
1449
1450
1451
1452
1453
1454
1455
1456

1457
1458
1459
1460
1461
1462
1463
1430
1431
1432
1433
1434
1435
1436

1437
1438
1439
1440
1441
1442
1443
1444







-
+







 *	queue.
 *
 *----------------------------------------------------------------------
 */

static void
GetTranslatedKey(
    XKeyEvent *xkey,
    TkKeyEvent *xkey,
    UINT type)
{
    MSG msg;

    xkey->nbytes = 0;

    while ((xkey->nbytes < XMaxTransChars)
1472
1473
1474
1475
1476
1477
1478
1479

1480
1481
1482
1483
1484
1485
1486
1453
1454
1455
1456
1457
1458
1459

1460
1461
1462
1463
1464
1465
1466
1467







-
+







	 * If this is a normal character message, we may need to strip off the
	 * Alt modifier (e.g. Alt-digits). Note that we don't want to do this
	 * for system messages, because those were presumably generated as an
	 * Alt-char sequence (e.g. accelerator keys).
	 */

	if ((msg.message == WM_CHAR) && (msg.lParam & 0x20000000)) {
	    xkey->state = 0;
	    xkey->keyEvent.state = 0;
	}
	xkey->trans_chars[xkey->nbytes++] = (char) msg.wParam;

	if (((unsigned short) msg.wParam) > ((unsigned short) 0xff)) {
	    /*
	     * Some "addon" input devices, such as the popular PenPower
	     * Chinese writing pad, generate 16 bit values in WM_CHAR messages
1522
1523
1524
1525
1526
1527
1528
1529

1530
1531
1532
1533
1534
1535
1536
1537



1538


1539
1540
1541
1542
1543
1544
1545
1503
1504
1505
1506
1507
1508
1509

1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521

1522
1523
1524
1525
1526
1527
1528
1529
1530







-
+








+
+
+
-
+
+







    CHARSETINFO charsetInfo;
    Tcl_Encoding encoding;
    char codepage[4 + TCL_INTEGER_SPACE];

    if (keyInputCharset == charset) {
	return;
    }
    if (TranslateCharsetInfo(INT2PTR(charset), &charsetInfo,
    if (TranslateCharsetInfo((DWORD*)INT2PTR(charset), &charsetInfo,
	    TCI_SRCCHARSET) == 0) {
	/*
	 * Some mysterious failure.
	 */

	return;
    }

    if (charsetInfo.ciACP == CP_UTF8) {
	strcpy(codepage, "utf-8");
    } else {
    sprintf(codepage, "cp%d", charsetInfo.ciACP);
	sprintf(codepage, "cp%d", charsetInfo.ciACP);
    }

    if ((encoding = Tcl_GetEncoding(NULL, codepage)) == NULL) {
	/*
	 * The encoding is not supported by Tcl.
	 */

	return;
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1701
1702
1703
1704
1705
1706
1707
























1708
1709
1710
1711
1712
1713
1714







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







    ImmReleaseContext(hwnd, hIMC);
    return 1;
}

/*
 *----------------------------------------------------------------------
 *
 * Tk_FreeXId --
 *
 *	This interface is not needed under Windows.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void
Tk_FreeXId(
    Display *display,
    XID xid)
{
    /* Do nothing */
}

/*
 *----------------------------------------------------------------------
 *
 * TkWinResendEvent --
 *
 *	This function converts an X event into a Windows event and invokes the
 *	specified window function.
 *
 * Results:
 *	A standard Windows result.
1781
1782
1783
1784
1785
1786
1787
1788

1789
1790
1791
1792

1793
1794
1795
1796
1797
1798
1799
1742
1743
1744
1745
1746
1747
1748

1749
1750
1751
1752

1753
1754
1755
1756
1757
1758
1759
1760







-
+



-
+







	msg = WM_MBUTTONDOWN;
	wparam = MK_MBUTTON;
	break;
    case Button3:
	msg = WM_RBUTTONDOWN;
	wparam = MK_RBUTTON;
	break;
    case Button4:
    case Button8:
	msg = WM_XBUTTONDOWN;
	wparam = MAKEWPARAM(MK_XBUTTON1, XBUTTON1);
	break;
    case Button5:
    case Button9:
	msg = WM_XBUTTONDOWN;
	wparam = MAKEWPARAM(MK_XBUTTON2, XBUTTON2);
	break;
    default:
	return 0;
    }

1977
1978
1979
1980
1981
1982
1983
1984
1985


1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997

1998
1999
2000

2001
2002
2003
2004
2005
2006
2007
1938
1939
1940
1941
1942
1943
1944


1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961

1962
1963
1964
1965
1966
1967
1968
1969







-
-
+
+












+


-
+







 *----------------------------------------------------------------------
 *
 * Tk_GetUserInactiveTime --
 *
 *	Return the number of milliseconds the user was inactive.
 *
 * Results:
 *	Milliseconds of user inactive time or -1 if the user32.dll doesn't
 *	have the symbol GetLastInputInfo or GetLastInputInfo returns an error.
 *	Milliseconds of user inactive time or -1 if GetLastInputInfo
 *	returns an error.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

long
Tk_GetUserInactiveTime(
     Display *dpy)		/* Ignored on Windows */
{
    LASTINPUTINFO li;
    (void)dpy;

    li.cbSize = sizeof(li);
    if (!(BOOL)GetLastInputInfo(&li)) {
    if (!GetLastInputInfo(&li)) {
	return -1;
    }

    /*
     * Last input info is in milliseconds, since restart time.
     */

2015
2016
2017
2018
2019
2020
2021
2022

2023
2024
2025
2026
2027
2028
2029
2030
2031
2032

2033
2034
2035
2036
2037
2038
2039
1977
1978
1979
1980
1981
1982
1983

1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002







-
+










+







 *
 *	Reset the user inactivity timer
 *
 * Results:
 *	none
 *
 * Side effects:
 *	The user inactivity timer of the underlaying windowing system is reset
 *	The user inactivity timer of the underlying windowing system is reset
 *	to zero.
 *
 *----------------------------------------------------------------------
 */

void
Tk_ResetUserInactiveTime(
    Display *dpy)
{
    INPUT inp;
    (void)dpy;

    inp.type = INPUT_MOUSE;
    inp.mi.dx = 0;
    inp.mi.dy = 0;
    inp.mi.mouseData = 0;
    inp.mi.dwFlags = MOUSEEVENTF_MOVE;
    inp.mi.time = 0;
Changes to win/ttkWinMonitor.c.
18
19
20
21
22
23
24
25

26
27
28
29
30
31
32
18
19
20
21
22
23
24

25
26
27
28
29
30
31
32







-
+







 */

typedef struct {
    const char *name;
    int index;
} SystemColorEntry;

static SystemColorEntry sysColors[] = {
static const SystemColorEntry sysColors[] = {
	{ "System3dDarkShadow",		COLOR_3DDKSHADOW },
	{ "System3dLight",		COLOR_3DLIGHT },
	{ "SystemActiveBorder",		COLOR_ACTIVEBORDER },
	{ "SystemActiveCaption",	COLOR_ACTIVECAPTION },
	{ "SystemAppWorkspace",		COLOR_APPWORKSPACE },
	{ "SystemBackground",		COLOR_BACKGROUND },
	{ "SystemButtonFace",		COLOR_BTNFACE },
51
52
53
54
55
56
57
58

59
60
61
62
63
64
65
51
52
53
54
55
56
57

58
59
60
61
62
63
64
65







-
+







	{ "SystemWindowText",		COLOR_WINDOWTEXT },
	{ NULL, 0 }
};

static void RegisterSystemColors(Tcl_Interp *interp)
{
    Ttk_ResourceCache cache = Ttk_GetResourceCache(interp);
    SystemColorEntry *sysColor;
    const SystemColorEntry *sysColor;

    for (sysColor = sysColors; sysColor->name; ++sysColor) {
	DWORD pixel = GetSysColor(sysColor->index);
	XColor colorSpec;
	colorSpec.red = GetRValue(pixel) * 257;
	colorSpec.green = GetGValue(pixel) * 257;
	colorSpec.blue = GetBValue(pixel) * 257;
148
149
150
151
152
153
154
155

156
157
158
159
160
161
148
149
150
151
152
153
154

155
156
157
158
159
160
161







-
+






MODULE_SCOPE int TtkXPTheme_Init(Tcl_Interp *, HWND hwnd);

MODULE_SCOPE int Ttk_WinPlatformInit(Tcl_Interp *interp)
{
    HWND hwnd;

    hwnd = CreateThemeMonitorWindow(Tk_GetHINSTANCE(), interp);
    Ttk_RegisterCleanup(interp, (ClientData)hwnd, DestroyThemeMonitorWindow);
    Ttk_RegisterCleanup(interp, hwnd, DestroyThemeMonitorWindow);

    TtkWinTheme_Init(interp, hwnd);
    TtkXPTheme_Init(interp, hwnd);

    return TCL_OK;
}
Changes to win/ttkWinTheme.c.
1

2
3
4
5
6
7
8
9
10

11
12
13
14
15
16
17

1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
-
+








-
+







/* winTheme.c - Copyright (C) 2004 Pat Thoyts <[email protected]>
/* winTheme.c - Copyright © 2004 Pat Thoyts <[email protected]>
 */

#ifdef _MSC_VER
#define WIN32_LEAN_AND_MEAN
#endif

#include <tkWinInt.h>

#ifndef DFCS_HOT	/* Windows 98/Me, Windows 200/XP only */
#ifndef DFCS_HOT	/* Windows 98/Me, Windows 2000/XP only */
#define DFCS_HOT 0
#endif

#include "ttk/ttkTheme.h"

/*
 * BoxToRect --
50
51
52
53
54
55
56
57

58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78

79
80
81
82
83
84
85

86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101



102
103
104
105
106


107
108
109
110

111
112

113
114
115
116
117
118
119
50
51
52
53
54
55
56

57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77

78
79
80
81
82
83
84

85
86
87
88
89
90
91
92
93
94
95
96
97
98



99
100
101
102
103
104


105
106
107
108
109

110
111

112
113
114
115
116
117
118
119







-
+




















-
+






-
+













-
-
-
+
+
+



-
-
+
+



-
+

-
+







    }
}

/*------------------------------------------------------------------------
 * +++ State tables for FrameControlElements.
 */

static Ttk_StateTable checkbutton_statemap[] = { /* see also SF#1865898 */
static const Ttk_StateTable checkbutton_statemap[] = { /* see also SF#1865898 */
    { DFCS_BUTTON3STATE|DFCS_CHECKED|DFCS_INACTIVE,
    	TTK_STATE_ALTERNATE|TTK_STATE_DISABLED, 0 },
    { DFCS_BUTTON3STATE|DFCS_CHECKED|DFCS_PUSHED,
    	TTK_STATE_ALTERNATE|TTK_STATE_PRESSED, 0 },
    { DFCS_BUTTON3STATE|DFCS_CHECKED|DFCS_HOT,
    	TTK_STATE_ALTERNATE|TTK_STATE_ACTIVE, 0 },
    { DFCS_BUTTON3STATE|DFCS_CHECKED,
    	TTK_STATE_ALTERNATE, 0 },

    { DFCS_CHECKED|DFCS_INACTIVE, TTK_STATE_SELECTED|TTK_STATE_DISABLED, 0 },
    { DFCS_CHECKED|DFCS_PUSHED,   TTK_STATE_SELECTED|TTK_STATE_PRESSED, 0 },
    { DFCS_CHECKED|DFCS_HOT,      TTK_STATE_SELECTED|TTK_STATE_ACTIVE, 0 },
    { DFCS_CHECKED,	          TTK_STATE_SELECTED, 0 },

    { DFCS_INACTIVE, TTK_STATE_DISABLED, 0 },
    { DFCS_PUSHED,   TTK_STATE_PRESSED, 0 },
    { DFCS_HOT,      TTK_STATE_ACTIVE, 0 },
    { 0, 0, 0 },
};

static Ttk_StateTable pushbutton_statemap[] = {
static const Ttk_StateTable pushbutton_statemap[] = {
    { DFCS_INACTIVE,	  TTK_STATE_DISABLED, 0 },
    { DFCS_PUSHED,	  TTK_STATE_PRESSED, 0 },
    { DFCS_HOT,		  TTK_STATE_ACTIVE, 0 },
    { 0, 0, 0 }
};

static Ttk_StateTable arrow_statemap[] = {
static const Ttk_StateTable arrow_statemap[] = {
    { DFCS_INACTIVE,            TTK_STATE_DISABLED, 0 },
    { DFCS_PUSHED | DFCS_FLAT,  TTK_STATE_PRESSED,  0 },
    { 0, 0, 0 }
};

/*------------------------------------------------------------------------
 * +++ FrameControlElement --
 * 	General-purpose element for things drawn with DrawFrameControl
 */
typedef struct {
    const char *name;		/* element name */
    int classId;		/* class id for DrawFrameControl */
    int partId;			/* part id for DrawFrameControl  */
    int cxId;			/* system metric ids for width/height... */
    int cyId;			/* ... or size if FIXEDSIZE bit set */
    Ttk_StateTable *stateMap;	/* map Tk states to Win32 flags */
    unsigned cxId;			/* system metric ids for width/height... */
    unsigned cyId;			/* ... or size if FIXEDSIZE bit set */
    const Ttk_StateTable *stateMap;	/* map Tk states to Win32 flags */
    Ttk_Padding margins;	/* additional placement padding */
} FrameControlElementData;

#define _FIXEDSIZE  0x80000000L
#define _HALFMETRIC 0x40000000L
#define _FIXEDSIZE  0x80000000UL
#define _HALFMETRIC 0x40000000UL
#define FIXEDSIZE(id) (id|_FIXEDSIZE)
#define HALFMETRIC(id) (id|_HALFMETRIC)
#define GETMETRIC(m) \
    ((m) & _FIXEDSIZE ? (int)((m) & ~_FIXEDSIZE) : GetSystemMetrics((m)&0x0fffffff))
    ((m) & _FIXEDSIZE ? (int)((m) & ~_FIXEDSIZE) : GetSystemMetrics((m)&0xFFFFFFF))

static FrameControlElementData FrameControlElements[] = {
static const FrameControlElementData FrameControlElements[] = {
    { "Checkbutton.indicator",
	DFC_BUTTON, DFCS_BUTTONCHECK, FIXEDSIZE(13), FIXEDSIZE(13),
	checkbutton_statemap, {0,0,4,0} },
    { "Radiobutton.indicator",
    	DFC_BUTTON, DFCS_BUTTONRADIO, FIXEDSIZE(13), FIXEDSIZE(13),
	checkbutton_statemap, {0,0,4,0} },
    { "uparrow",
143
144
145
146
147
148
149
150

151
152




153
154
155
156
157
158
159
160
161
162
163

164
165
166

167
168
169
170
171
172
173
174

175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192



193
194
195
196

197
198






199
200
201
202
203
204

205
206
207

208
209
210
211


212
213
214
215
216
217
218
219
220
221
222
223

224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240

241
242
243


244
245
246
247

248
249






250
251
252
253
254
255

256
257
258

259
260
261
262


263
264
265
266
267
268
269
270
271
272

273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291

292
293

294
295

296
297
298


299
300
301
302

303
304
305

306
307

308




309
310
311
312
313
314
315
143
144
145
146
147
148
149

150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166

167
168
169
170
171
172
173
174
175
176
177
178

179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194



195
196
197
198
199
200

201
202
203
204
205
206
207
208
209
210
211
212
213
214

215
216
217

218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235

236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252

253
254


255
256
257
258
259

260
261
262
263
264
265
266
267
268
269
270
271
272
273

274
275
276

277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292

293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311

312
313

314
315

316
317


318
319
320
321
322

323
324
325

326
327

328
329
330
331
332
333
334
335
336
337
338
339
340







-
+


+
+
+
+










-
+



+







-
+















-
-
-
+
+
+



-
+


+
+
+
+
+
+





-
+


-
+




+
+











-
+
















-
+

-
-
+
+



-
+


+
+
+
+
+
+





-
+


-
+




+
+









-
+


















-
+

-
+

-
+

-
-
+
+



-
+


-
+

-
+

+
+
+
+








/* ---------------------------------------------------------------------- */

static void FrameControlElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    FrameControlElementData *p = clientData;
    FrameControlElementData *p = (FrameControlElementData *)clientData;
    int cx = GETMETRIC(p->cxId);
    int cy = GETMETRIC(p->cyId);
    (void)elementRecord;
    (void)tkwin;
    (void)paddingPtr;

    if (p->cxId & _HALFMETRIC) cx /= 2;
    if (p->cyId & _HALFMETRIC) cy /= 2;
    *widthPtr = cx + Ttk_PaddingWidth(p->margins);
    *heightPtr = cy + Ttk_PaddingHeight(p->margins);
}

static void FrameControlElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    FrameControlElementData *elementData = clientData;
    FrameControlElementData *elementData = (FrameControlElementData *)clientData;
    RECT rc = BoxToRect(Ttk_PadBox(b, elementData->margins));
    TkWinDCState dcState;
    HDC hdc = TkWinGetDrawableDC(Tk_Display(tkwin), d, &dcState);
    (void)elementRecord;

    DrawFrameControl(hdc, &rc,
	elementData->classId,
	elementData->partId|Ttk_StateTableLookup(elementData->stateMap, state));
    TkWinReleaseDrawableDC(d, hdc, &dcState);
}

static Ttk_ElementSpec FrameControlElementSpec = {
static const Ttk_ElementSpec FrameControlElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(NullElement),
    TtkNullElementOptions,
    FrameControlElementSize,
    FrameControlElementDraw
};

/*----------------------------------------------------------------------
 * +++ Border element implementation.
 */

typedef struct {
    Tcl_Obj	*reliefObj;
} BorderElement;

static Ttk_ElementOptionSpec BorderElementOptions[] = {
    { "-relief",TK_OPTION_RELIEF,Tk_Offset(BorderElement,reliefObj), "flat" },
    {NULL, 0, 0, NULL}
static const Ttk_ElementOptionSpec BorderElementOptions[] = {
    { "-relief",TK_OPTION_RELIEF, offsetof(BorderElement,reliefObj), "flat" },
    {NULL, TK_OPTION_BOOLEAN, 0, NULL}
};

static void BorderElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    (void)dummy;
    (void)elementRecord;
    (void)tkwin;
    (void)widthPtr;
    (void)heightPtr;

    paddingPtr->left = paddingPtr->right = GetSystemMetrics(SM_CXEDGE);
    paddingPtr->top = paddingPtr->bottom = GetSystemMetrics(SM_CYEDGE);
}

static void BorderElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    BorderElement *border = elementRecord;
    BorderElement *border = (BorderElement *)elementRecord;
    RECT rc = BoxToRect(b);
    int relief = TK_RELIEF_FLAT;
    TkWinDCState dcState;
    HDC hdc;
    (void)dummy;
    (void)state;

    Tk_GetReliefFromObj(NULL, border->reliefObj, &relief);

    if (relief != TK_RELIEF_FLAT) {
	UINT xFlags = (relief == TK_RELIEF_SOLID) ? BF_FLAT : 0;
	hdc = TkWinGetDrawableDC(Tk_Display(tkwin), d, &dcState);
	DrawEdge(hdc, &rc, ReliefToEdge(relief), BF_RECT | xFlags);
	TkWinReleaseDrawableDC(d, hdc, &dcState);
    }
}

static Ttk_ElementSpec BorderElementSpec = {
static const Ttk_ElementSpec BorderElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(BorderElement),
    BorderElementOptions,
    BorderElementSize,
    BorderElementDraw
};

/*
 * Entry field borders:
 * Sunken border; also fill with window color.
 */

typedef struct {
    Tcl_Obj	*backgroundObj;
} FieldElement;

static Ttk_ElementOptionSpec FieldElementOptions[] = {
static const Ttk_ElementOptionSpec FieldElementOptions[] = {
    { "-fieldbackground", TK_OPTION_BORDER,
    	Tk_Offset(FieldElement,backgroundObj), "white" },
    { NULL, 0, 0, NULL }
    	offsetof(FieldElement,backgroundObj), "white" },
    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
};

static void FieldElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    (void)dummy;
    (void)elementRecord;
    (void)tkwin;
    (void)widthPtr;
    (void)heightPtr;

    paddingPtr->left = paddingPtr->right = GetSystemMetrics(SM_CXEDGE);
    paddingPtr->top = paddingPtr->bottom = GetSystemMetrics(SM_CYEDGE);
}

static void FieldElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    FieldElement *field = elementRecord;
    FieldElement *field = (FieldElement *)elementRecord;
    Tk_3DBorder bg = Tk_Get3DBorderFromObj(tkwin, field->backgroundObj);
    RECT rc = BoxToRect(b);
    TkWinDCState dcState;
    HDC hdc;
    (void)dummy;
    (void)state;

    Tk_Fill3DRectangle(
	tkwin, d, bg, b.x, b.y, b.width, b.height, 0, TK_RELIEF_FLAT);

    hdc = TkWinGetDrawableDC(Tk_Display(tkwin), d, &dcState);
    DrawEdge(hdc, &rc, EDGE_SUNKEN, BF_RECT);
    TkWinReleaseDrawableDC(d, hdc, &dcState);
}

static Ttk_ElementSpec FieldElementSpec = {
static const Ttk_ElementSpec FieldElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(FieldElement),
    FieldElementOptions,
    FieldElementSize,
    FieldElementDraw
};

/*------------------------------------------------------------------------
 * +++ Button borders.
 *	Drawn with DrawFrameControl instead of DrawEdge;
 *	Also draw default indicator and focus ring.
 */
typedef struct {
    Tcl_Obj	*reliefObj;
    Tcl_Obj	*highlightColorObj;
    Tcl_Obj	*defaultStateObj;
} ButtonBorderElement;

static Ttk_ElementOptionSpec ButtonBorderElementOptions[] = {
static const Ttk_ElementOptionSpec ButtonBorderElementOptions[] = {
    { "-relief",TK_OPTION_RELIEF,
	Tk_Offset(ButtonBorderElement,reliefObj), "flat" },
	offsetof(ButtonBorderElement,reliefObj), "flat" },
    { "-highlightcolor",TK_OPTION_COLOR,
	Tk_Offset(ButtonBorderElement,highlightColorObj), "black" },
	offsetof(ButtonBorderElement,highlightColorObj), "black" },
    { "-default", TK_OPTION_ANY,
	Tk_Offset(ButtonBorderElement,defaultStateObj), "disabled" },
    {NULL, 0, 0, NULL}
	offsetof(ButtonBorderElement,defaultStateObj), "disabled" },
    {NULL, TK_OPTION_BOOLEAN, 0, NULL}
};

static void ButtonBorderElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    ButtonBorderElement *bd = elementRecord;
    ButtonBorderElement *bd = (ButtonBorderElement *)elementRecord;
    int relief = TK_RELIEF_RAISED;
    int defaultState = TTK_BUTTON_DEFAULT_DISABLED;
    Ttk_ButtonDefaultState defaultState = TTK_BUTTON_DEFAULT_DISABLED;
    short int cx, cy;
    (void)dummy;
    (void)tkwin;
    (void)widthPtr;
    (void)heightPtr;

    Tk_GetReliefFromObj(NULL, bd->reliefObj, &relief);
    Ttk_GetButtonDefaultStateFromObj(NULL, bd->defaultStateObj, &defaultState);
    cx = GetSystemMetrics(SM_CXEDGE);
    cy = GetSystemMetrics(SM_CYEDGE);

    /* Space for default indicator:
323
324
325
326
327
328
329
330

331
332
333

334
335

336
337
338

339
340
341
342
343
344
345
348
349
350
351
352
353
354

355
356
357

358
359

360
361
362
363
364
365
366
367
368
369
370
371







-
+


-
+

-
+



+







    cx += 2;
    cy += 2;

    *paddingPtr = Ttk_MakePadding(cx,cy,cx,cy);
}

static void ButtonBorderElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    ButtonBorderElement *bd = elementRecord;
    ButtonBorderElement *bd = (ButtonBorderElement *)elementRecord;
    int relief = TK_RELIEF_FLAT;
    int defaultState = TTK_BUTTON_DEFAULT_DISABLED;
    Ttk_ButtonDefaultState defaultState = TTK_BUTTON_DEFAULT_DISABLED;
    TkWinDCState dcState;
    HDC hdc;
    RECT rc;
    (void)dummy;

    Tk_GetReliefFromObj(NULL, bd->reliefObj, &relief);
    Ttk_GetButtonDefaultStateFromObj(NULL, bd->defaultStateObj, &defaultState);

    if (defaultState == TTK_BUTTON_DEFAULT_ACTIVE) {
	XColor *highlightColor =
	    Tk_GetColorFromObj(tkwin, bd->highlightColorObj);
363
364
365
366
367
368
369
370

371
372
373
374
375
376
377
378
379
380
381
382
383
384

385
386






387
388
389
390
391

392
393



394
395
396
397
398
399
400
401
402
403

404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419

420
421
422


423
424
425
426
427

428
429
430



431
432
433
434
435
436
437
389
390
391
392
393
394
395

396
397
398
399
400
401
402
403
404
405
406
407
408
409

410
411
412
413
414
415
416
417
418
419
420
421
422

423
424
425
426
427
428
429
430
431
432
433
434
435
436
437

438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453

454
455


456
457
458
459
460
461

462
463
464

465
466
467
468
469
470
471
472
473
474







-
+













-
+


+
+
+
+
+
+




-
+


+
+
+









-
+















-
+

-
-
+
+




-
+


-
+
+
+







	short int borderWidth = 3;	/* @@@ Use GetSystemMetrics?*/
	rc = BoxToRect(Ttk_PadBox(b, Ttk_UniformPadding(borderWidth)));
    	DrawFocusRect(hdc, &rc);
    }
    TkWinReleaseDrawableDC(d, hdc, &dcState);
}

static Ttk_ElementSpec ButtonBorderElementSpec = {
static const Ttk_ElementSpec ButtonBorderElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(ButtonBorderElement),
    ButtonBorderElementOptions,
    ButtonBorderElementSize,
    ButtonBorderElementDraw
};

/*------------------------------------------------------------------------
 * +++ Focus element.
 * 	Draw dashed focus rectangle.
 */

static void FocusElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    (void)dummy;
    (void)elementRecord;
    (void)tkwin;
    (void)widthPtr;
    (void)heightPtr;

    *paddingPtr = Ttk_UniformPadding(1);
}

static void FocusElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    (void)dummy;
    (void)elementRecord;

    if (state & TTK_STATE_FOCUS) {
	RECT rc = BoxToRect(b);
	TkWinDCState dcState;
	HDC hdc = TkWinGetDrawableDC(Tk_Display(tkwin), d, &dcState);
    	DrawFocusRect(hdc, &rc);
	TkWinReleaseDrawableDC(d, hdc, &dcState);
    }
}

static Ttk_ElementSpec FocusElementSpec = {
static const Ttk_ElementSpec FocusElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(NullElement),
    TtkNullElementOptions,
    FocusElementSize,
    FocusElementDraw
};

/* FillFocusElement --
 * 	Draws a focus ring filled with the selection color
 */

typedef struct {
    Tcl_Obj *fillColorObj;
} FillFocusElement;

static Ttk_ElementOptionSpec FillFocusElementOptions[] = {
static const Ttk_ElementOptionSpec FillFocusElementOptions[] = {
    { "-focusfill", TK_OPTION_COLOR,
	Tk_Offset(FillFocusElement,fillColorObj), "white" },
    {NULL, 0, 0, NULL}
	offsetof(FillFocusElement,fillColorObj), "white" },
    {NULL, TK_OPTION_BOOLEAN, 0, NULL}
};

	/* @@@ FIX THIS */
static void FillFocusElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    FillFocusElement *focus = elementRecord;
    FillFocusElement *focus = (FillFocusElement *)elementRecord;
    (void)dummy;

    if (state & TTK_STATE_FOCUS) {
	RECT rc = BoxToRect(b);
	TkWinDCState dcState;
	XColor *fillColor = Tk_GetColorFromObj(tkwin, focus->fillColorObj);
	GC gc = Tk_GCForColor(fillColor, d);
	HDC hdc;

451
452
453
454
455
456
457
458

459
460
461
462
463
464
465
488
489
490
491
492
493
494

495
496
497
498
499
500
501
502







-
+







    Drawable d, Ttk_Box b, unsigned int state)
{
    if (state & TTK_STATE_READONLY) {
    	FillFocusElementDraw(clientData, elementRecord, tkwin, d, b, state);
    }
}

static Ttk_ElementSpec ComboboxFocusElementSpec = {
static const Ttk_ElementSpec ComboboxFocusElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(FillFocusElement),
    FillFocusElementOptions,
    FocusElementSize,
    ComboboxFocusElementDraw
};

478
479
480
481
482
483
484
485

486
487
488
489
490
491
492
493

494
495
496
497
498
499
500
501
502
503
504

505
506
507
508


509
510

511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528

529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546



547
548
549
550

551
552
553
554





555
556

557
558
559
560
561
562
563
564
565
566
567

568
569
570
571
572


573
574
575
576
577
578
579
580
581
582
583

584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601


602
603

604
605
606
607

608
609
610
611





612
613

614
615
616
617
618
619
620
621
622
623
624

625
626
627
628
629



630
631
632
633
634
635
636

637
638
639
640
641
642
643
644
645
646
647
648
649

650
651






652
653
654
655
656
657

658
659
660
661
662




663
664
665
666
667

668
669
670
671
672
673
674
515
516
517
518
519
520
521

522
523
524
525
526
527
528
529

530
531
532
533
534
535
536
537
538
539
540

541
542
543
544
545
546
547
548

549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566

567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582



583
584
585
586
587
588

589
590
591


592
593
594
595
596
597

598
599
600
601
602
603
604
605
606
607
608

609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626

627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643


644
645
646

647
648
649
650

651
652
653


654
655
656
657
658
659

660
661
662
663
664
665
666
667
668
669
670

671
672
673
674
675
676
677
678
679
680
681
682
683
684
685

686
687
688
689
690
691
692
693
694
695
696
697
698

699
700
701
702
703
704
705
706
707
708
709
710
711
712

713
714
715
716
717
718
719
720
721
722
723
724
725
726

727
728
729
730
731
732
733
734







-
+







-
+










-
+




+
+

-
+

















-
+















-
-
-
+
+
+



-
+


-
-
+
+
+
+
+

-
+










-
+





+
+










-
+
















-
-
+
+

-
+



-
+


-
-
+
+
+
+
+

-
+










-
+





+
+
+






-
+












-
+


+
+
+
+
+
+





-
+





+
+
+
+




-
+








static const WORD Pattern[] = {
    0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa
};

static void TroughClientDataDeleteProc(void *clientData)
{
    TroughClientData *cd = clientData;
    TroughClientData *cd = (TroughClientData *)clientData;
    DeleteObject(cd->PatternBrush);
    DeleteObject(cd->PatternBitmap);
    ckfree(clientData);
}

static TroughClientData *TroughClientDataInit(Tcl_Interp *interp)
{
    TroughClientData *cd = ckalloc(sizeof(*cd));
    TroughClientData *cd = (TroughClientData *)ckalloc(sizeof(*cd));
    cd->PatternBitmap = CreateBitmap(8, 8, 1, 1, Pattern);
    cd->PatternBrush  = CreatePatternBrush(cd->PatternBitmap);
    Ttk_RegisterCleanup(interp, cd, TroughClientDataDeleteProc);
    return cd;
}

static void TroughElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    TroughClientData *cd = clientData;
    TroughClientData *cd = (TroughClientData *)clientData;
    TkWinDCState dcState;
    HDC hdc = TkWinGetDrawableDC(Tk_Display(tkwin), d, &dcState);
    HBRUSH hbr;
    COLORREF bk, oldbk, oldtxt;
    (void)elementRecord;
    (void)state;

    hbr = SelectObject(hdc, GetSysColorBrush(COLOR_SCROLLBAR));
    hbr = (HBRUSH)SelectObject(hdc, GetSysColorBrush(COLOR_SCROLLBAR));
    bk = GetSysColor(COLOR_3DHIGHLIGHT);
    oldtxt = SetTextColor(hdc, GetSysColor(COLOR_3DFACE));
    oldbk = SetBkColor(hdc, bk);

    /* WAS: if (bk (COLOR_3DHIGHLIGHT) == GetSysColor(COLOR_WINDOW)) ... */
    if (GetSysColor(COLOR_SCROLLBAR) == GetSysColor(COLOR_BTNFACE)) {
	/* Draw using the pattern brush */
	SelectObject(hdc, cd->PatternBrush);
    }

    PatBlt(hdc, b.x, b.y, b.width, b.height, PATCOPY);
    SetBkColor(hdc, oldbk);
    SetTextColor(hdc, oldtxt);
    SelectObject(hdc, hbr);
    TkWinReleaseDrawableDC(d, hdc, &dcState);
}

static Ttk_ElementSpec TroughElementSpec = {
static const Ttk_ElementSpec TroughElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(NullElement),
    TtkNullElementOptions,
    TtkNullElementSize,
    TroughElementDraw
};

/*------------------------------------------------------------------------
 * +++ Thumb element.
 */

typedef struct {
    Tcl_Obj *orientObj;
} ThumbElement;

static Ttk_ElementOptionSpec ThumbElementOptions[] = {
    { "-orient", TK_OPTION_ANY,Tk_Offset(ThumbElement,orientObj),"horizontal"},
    { NULL, 0, 0, NULL }
static const Ttk_ElementOptionSpec ThumbElementOptions[] = {
    { "-orient", TK_OPTION_ANY, offsetof(ThumbElement,orientObj),"horizontal"},
    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
};

static void ThumbElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    ThumbElement *thumbPtr = elementRecord;
    int orient;
    ThumbElement *thumbPtr = (ThumbElement *)elementRecord;
    Ttk_Orient orient;
    (void)dummy;
    (void)tkwin;
    (void)paddingPtr;

    Ttk_GetOrientFromObj(NULL, thumbPtr->orientObj, &orient);
    TtkGetOrientFromObj(NULL, thumbPtr->orientObj, &orient);
    if (orient == TTK_ORIENT_HORIZONTAL) {
	*widthPtr = GetSystemMetrics(SM_CXHTHUMB);
	*heightPtr = GetSystemMetrics(SM_CYHSCROLL);
    } else {
	*widthPtr = GetSystemMetrics(SM_CXVSCROLL);
	*heightPtr = GetSystemMetrics(SM_CYVTHUMB);
    }
}

static void ThumbElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    RECT rc = BoxToRect(b);
    TkWinDCState dcState;
    HDC hdc;
    (void)dummy;
    (void)elementRecord;

    /* Windows doesn't show a thumb when the scrollbar is disabled */
    if (state & TTK_STATE_DISABLED)
	return;

    hdc = TkWinGetDrawableDC(Tk_Display(tkwin), d, &dcState);
    DrawEdge(hdc, &rc, EDGE_RAISED, BF_RECT | BF_MIDDLE);
    TkWinReleaseDrawableDC(d, hdc, &dcState);
}

static Ttk_ElementSpec ThumbElementSpec = {
static const Ttk_ElementSpec ThumbElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(ThumbElement),
    ThumbElementOptions,
    ThumbElementSize,
    ThumbElementDraw
};

/* ----------------------------------------------------------------------
 * The slider element is the shaped thumb used in the slider widget.
 * Windows likes to call this a trackbar.
 */

typedef struct {
    Tcl_Obj *orientObj;  /* orientation of the slider widget */
} SliderElement;

static Ttk_ElementOptionSpec SliderElementOptions[] = {
    { "-orient", TK_OPTION_ANY, Tk_Offset(SliderElement,orientObj),
static const Ttk_ElementOptionSpec SliderElementOptions[] = {
    { "-orient", TK_OPTION_ANY, offsetof(SliderElement,orientObj),
      "horizontal" },
      { NULL, 0, 0, NULL }
      { NULL, TK_OPTION_BOOLEAN, 0, NULL }
};

static void SliderElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    SliderElement *slider = elementRecord;
    int orient;
    SliderElement *slider = (SliderElement *)elementRecord;
    Ttk_Orient orient;
    (void)dummy;
    (void)tkwin;
    (void)paddingPtr;

    Ttk_GetOrientFromObj(NULL, slider->orientObj, &orient);
    TtkGetOrientFromObj(NULL, slider->orientObj, &orient);
    if (orient == TTK_ORIENT_HORIZONTAL) {
	*widthPtr = (GetSystemMetrics(SM_CXHTHUMB) / 2) | 1;
	*heightPtr = GetSystemMetrics(SM_CYHSCROLL);
    } else {
	*widthPtr = GetSystemMetrics(SM_CXVSCROLL);
	*heightPtr = (GetSystemMetrics(SM_CYVTHUMB) / 2) | 1;
    }
}

static void SliderElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    RECT rc = BoxToRect(b);
    TkWinDCState dcState;
    HDC hdc;
    (void)dummy;
    (void)elementRecord;
    (void)state;

    hdc = TkWinGetDrawableDC(Tk_Display(tkwin), d, &dcState);
    DrawEdge(hdc, &rc, EDGE_RAISED, BF_RECT | BF_MIDDLE);
    TkWinReleaseDrawableDC(d, hdc, &dcState);
}

static Ttk_ElementSpec SliderElementSpec = {
static const Ttk_ElementSpec SliderElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(SliderElement),
    SliderElementOptions,
    SliderElementSize,
    SliderElementDraw
};

/*------------------------------------------------------------------------
 * +++ Notebook elements.
 */

static void ClientElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    (void)dummy;
    (void)elementRecord;
    (void)tkwin;
    (void)widthPtr;
    (void)heightPtr;

    paddingPtr->left = paddingPtr->right = GetSystemMetrics(SM_CXEDGE);
    paddingPtr->top = paddingPtr->bottom = GetSystemMetrics(SM_CYEDGE);
}

static void ClientElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    void *dummy, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    RECT rc = BoxToRect(b);
    TkWinDCState dcState;
    HDC hdc = TkWinGetDrawableDC(Tk_Display(tkwin), d, &dcState);
    (void)dummy;
    (void)elementRecord;
    (void)state;

    DrawEdge(hdc, &rc, EDGE_RAISED, BF_RECT | BF_SOFT);
    TkWinReleaseDrawableDC(d, hdc, &dcState);
}

static Ttk_ElementSpec ClientElementSpec = {
static const Ttk_ElementSpec ClientElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(NullElement),
    TtkNullElementOptions,
    ClientElementSize,
    ClientElementDraw
};

682
683
684
685
686
687
688
689
690


691
692
693
694
695
696
697
698
699
700
701


702
703
704
705
706
707
708
742
743
744
745
746
747
748


749
750
751
752
753
754
755
756
757
758
759
760

761
762
763
764
765
766
767
768
769







-
-
+
+










-
+
+







    TTK_GROUP("Button.border", TTK_FILL_BOTH,
	TTK_GROUP("Button.padding", TTK_FILL_BOTH,
	    TTK_NODE("Button.label", TTK_FILL_BOTH))))

TTK_LAYOUT("TCombobox",
    TTK_GROUP("Combobox.field", TTK_FILL_BOTH,
	TTK_NODE("Combobox.downarrow", TTK_PACK_RIGHT|TTK_FILL_Y)
	TTK_GROUP("Combobox.padding", TTK_PACK_LEFT|TTK_EXPAND|TTK_FILL_BOTH,
	    TTK_GROUP("Combobox.focus", TTK_PACK_LEFT|TTK_EXPAND|TTK_FILL_BOTH,
	TTK_GROUP("Combobox.padding", TTK_FILL_BOTH,
	    TTK_GROUP("Combobox.focus", TTK_FILL_BOTH,
		TTK_NODE("Combobox.textarea", TTK_FILL_BOTH)))))

TTK_END_LAYOUT_TABLE

/* ---------------------------------------------------------------------- */

MODULE_SCOPE
int TtkWinTheme_Init(Tcl_Interp *interp, HWND hwnd)
{
    Ttk_Theme themePtr, parentPtr;
    FrameControlElementData *fce = FrameControlElements;
    const FrameControlElementData *fce = FrameControlElements;
    (void)hwnd;

    parentPtr = Ttk_GetTheme(interp, "alt");
    themePtr = Ttk_CreateTheme(interp, "winnative", parentPtr);
    if (!themePtr) {
        return TCL_ERROR;
    }

718
719
720
721
722
723
724
725

726
727
728
729
730
731
732
733
779
780
781
782
783
784
785

786
787
788
789
790
791
792
793
794







-
+








    Ttk_RegisterElementSpec(themePtr, "Scrollbar.trough", &TroughElementSpec,
    	TroughClientDataInit(interp));

    Ttk_RegisterElementSpec(themePtr, "client", &ClientElementSpec, NULL);

    for (fce = FrameControlElements; fce->name != 0; ++fce) {
	Ttk_RegisterElementSpec(themePtr, fce->name,
		&FrameControlElementSpec, fce);
		&FrameControlElementSpec, (void *)fce);
    }

    Ttk_RegisterLayouts(themePtr, LayoutTable);

    Tcl_PkgProvide(interp, "ttk::theme::winnative", TTK_VERSION);
    return TCL_OK;
}

Changes to win/ttkWinXPTheme.c.
1
2
3
4
5
6
7



8
9
10
11
12
13
14
15
16
17

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
1
2
3
4



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

21
22
23


24
25
26
27
28
29
30
31


32
33
34
35
36
37
38




-
-
-
+
+
+










+


-



-
-








-
-







/*
 * Tk theme engine which uses the Windows XP "Visual Styles" API
 * Adapted from Georgios Petasis' XP theme patch.
 *
 * Copyright (c) 2003 by Georgios Petasis, [email protected].
 * Copyright (c) 2003 by Joe English
 * Copyright (c) 2003 by Pat Thoyts
 * Copyright © 2003 Georgios Petasis, [email protected].
 * Copyright © 2003 Joe English
 * Copyright © 2003 Pat Thoyts
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * See also:
 *
 * <URL: http://msdn.microsoft.com/library/en-us/
 *  	shellcc/platform/commctls/userex/refentry.asp >
 */

#include <tkWinInt.h>
#ifndef HAVE_UXTHEME_H
/* Stub for platforms that lack the XP theme API headers: */
#include <tkWinInt.h>
int TtkXPTheme_Init(Tcl_Interp *interp, HWND hwnd) { return TCL_OK; }
#else

#define WINVER 0x0501	/* Requires Windows XP APIs */

#include <windows.h>
#include <uxtheme.h>
#if defined(HAVE_VSSYM32_H) || _MSC_VER > 1500
#   include <vssym32.h>
#else
#   include <tmschema.h>
#endif

#include <tkWinInt.h>

#include "ttk/ttkTheme.h"

typedef HTHEME  (STDAPICALLTYPE OpenThemeDataProc)(HWND hwnd,
		 LPCWSTR pszClassList);
typedef HRESULT (STDAPICALLTYPE CloseThemeDataProc)(HTHEME hTheme);
typedef HRESULT (STDAPICALLTYPE DrawThemeBackgroundProc)(HTHEME hTheme,
                 HDC hdc, int iPartId, int iStateId, const RECT *pRect,
102
103
104
105
106
107
108
109

110
111

112
113
114
115
116
117
118
98
99
100
101
102
103
104

105
106

107
108
109
110
111
112
113
114







-
+

-
+







    *phlib = handle = LoadLibraryW(L"uxtheme.dll");
    if (handle != 0)
    {
	/*
	 * We have successfully loaded the library. Proceed in storing the
	 * addresses of the functions we want to use.
	 */
	XPThemeProcs *procs = ckalloc(sizeof(XPThemeProcs));
	XPThemeProcs *procs = (XPThemeProcs *)ckalloc(sizeof(XPThemeProcs));
#define LOADPROC(name) \
	(0 != (procs->name = (name ## Proc *)GetProcAddress(handle, #name) ))
	(0 != (procs->name = (name ## Proc *)(void *)GetProcAddress(handle, #name) ))

	if (   LOADPROC(OpenThemeData)
	    && LOADPROC(CloseThemeData)
	    && LOADPROC(GetThemePartSize)
	    && LOADPROC(GetThemeSysSize)
	    && LOADPROC(DrawThemeBackground)
	    && LOADPROC(GetThemeTextExtent)
134
135
136
137
138
139
140
141

142
143
144
145
146
147
148
149

150
151


152
153
154
155
156
157
158
130
131
132
133
134
135
136

137
138
139
140
141
142
143
144

145
146
147
148
149
150
151
152
153
154
155
156







-
+







-
+


+
+







 *
 *      Release any theme allocated resources.
 */

static void
XPThemeDeleteProc(void *clientData)
{
    XPThemeData *themeData = clientData;
    XPThemeData *themeData = (XPThemeData *)clientData;
    FreeLibrary(themeData->hlibrary);
    ckfree(clientData);
}

static int
XPThemeEnabled(Ttk_Theme theme, void *clientData)
{
    XPThemeData *themeData = clientData;
    XPThemeData *themeData = (XPThemeData *)clientData;
    int active = themeData->procs->IsThemeActive();
    int themed = themeData->procs->IsAppThemed();
    (void)theme;

    return (active && themed);
}

/*
 * BoxToRect --
 * 	Helper routine.  Returns a RECT data structure.
 */
166
167
168
169
170
171
172
173

174
175
176
177
178

179
180
181
182
183
184
185
186
187
188
189
190

191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209

210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226

227
228
229
230
231
232
233
234
235

236
237
238
239
240
241
242
243
244
245
246
247
248
249
250

251
252
253
254
255
256
257
258
259
260
261

262
263
264
265
266
267
268
269
270
271
272

273
274
275
276
277
278
279
280
281
282
283
284

285
286
287
288
289
290
291
292

293
294
295
296
297
298
299
300

301
302
303
304
305
306
307
308

309
310
311
312
313
314
315
316

317
318
319
320
321
322
323
324

325
326
327
328
329
330
331
332
333
334
335

336
337
338
339
340
341
342
343
344

345
346
347
348
349
350
351
164
165
166
167
168
169
170

171
172
173
174
175

176
177
178
179
180
181
182
183
184
185
186
187

188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206

207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223

224
225
226
227
228
229
230
231
232

233
234
235
236
237
238
239
240
241
242
243
244
245
246
247

248
249
250
251
252
253
254
255
256
257
258

259
260
261
262
263
264
265
266
267
268
269

270
271
272
273
274
275
276
277
278
279
280
281

282
283
284
285
286
287
288
289

290
291
292
293
294
295
296
297

298
299
300
301
302
303
304
305

306
307
308
309
310
311
312
313

314
315
316
317
318
319
320
321

322
323
324
325
326
327
328
329
330
331
332

333
334
335
336
337
338
339
340
341

342
343
344
345
346
347
348
349







-
+




-
+











-
+


















-
+
















-
+








-
+














-
+










-
+










-
+











-
+







-
+







-
+







-
+







-
+







-
+










-
+








-
+







    rc.right = b.x + b.width;
    return rc;
}

/*
 * Map Tk state bitmaps to XP style enumerated values.
 */
static Ttk_StateTable null_statemap[] = { {0,0,0} };
static const Ttk_StateTable null_statemap[] = { {0,0,0} };

/*
 * Pushbuttons (Tk: "Button")
 */
static Ttk_StateTable pushbutton_statemap[] =
static const Ttk_StateTable pushbutton_statemap[] =
{
    { PBS_DISABLED, 	TTK_STATE_DISABLED, 0 },
    { PBS_PRESSED, 	TTK_STATE_PRESSED, 0 },
    { PBS_HOT,		TTK_STATE_ACTIVE, 0 },
    { PBS_DEFAULTED,	TTK_STATE_ALTERNATE, 0 },
    { PBS_NORMAL, 	0, 0 }
};

/*
 * Checkboxes (Tk: "Checkbutton")
 */
static Ttk_StateTable checkbox_statemap[] =
static const Ttk_StateTable checkbox_statemap[] =
{
{CBS_MIXEDDISABLED, 	TTK_STATE_ALTERNATE|TTK_STATE_DISABLED, 0},
{CBS_MIXEDPRESSED, 	TTK_STATE_ALTERNATE|TTK_STATE_PRESSED, 0},
{CBS_MIXEDHOT,  	TTK_STATE_ALTERNATE|TTK_STATE_ACTIVE, 0},
{CBS_MIXEDNORMAL, 	TTK_STATE_ALTERNATE, 0},
{CBS_CHECKEDDISABLED,	TTK_STATE_SELECTED|TTK_STATE_DISABLED, 0},
{CBS_CHECKEDPRESSED,	TTK_STATE_SELECTED|TTK_STATE_PRESSED, 0},
{CBS_CHECKEDHOT,	TTK_STATE_SELECTED|TTK_STATE_ACTIVE, 0},
{CBS_CHECKEDNORMAL,	TTK_STATE_SELECTED, 0},
{CBS_UNCHECKEDDISABLED,	TTK_STATE_DISABLED, 0},
{CBS_UNCHECKEDPRESSED,	TTK_STATE_PRESSED, 0},
{CBS_UNCHECKEDHOT,	TTK_STATE_ACTIVE, 0},
{CBS_UNCHECKEDNORMAL,	0,0 }
};

/*
 * Radiobuttons:
 */
static Ttk_StateTable radiobutton_statemap[] =
static const Ttk_StateTable radiobutton_statemap[] =
{
{RBS_UNCHECKEDDISABLED,	TTK_STATE_ALTERNATE|TTK_STATE_DISABLED, 0},
{RBS_UNCHECKEDNORMAL,	TTK_STATE_ALTERNATE, 0},
{RBS_CHECKEDDISABLED,	TTK_STATE_SELECTED|TTK_STATE_DISABLED, 0},
{RBS_CHECKEDPRESSED,	TTK_STATE_SELECTED|TTK_STATE_PRESSED, 0},
{RBS_CHECKEDHOT,	TTK_STATE_SELECTED|TTK_STATE_ACTIVE, 0},
{RBS_CHECKEDNORMAL,	TTK_STATE_SELECTED, 0},
{RBS_UNCHECKEDDISABLED,	TTK_STATE_DISABLED, 0},
{RBS_UNCHECKEDPRESSED,	TTK_STATE_PRESSED, 0},
{RBS_UNCHECKEDHOT,	TTK_STATE_ACTIVE, 0},
{RBS_UNCHECKEDNORMAL,	0,0 }
};

/*
 * Groupboxes (tk: "frame")
 */
static Ttk_StateTable groupbox_statemap[] =
static const Ttk_StateTable groupbox_statemap[] =
{
{GBS_DISABLED,	TTK_STATE_DISABLED, 0},
{GBS_NORMAL,	0,0 }
};

/*
 * Edit fields (tk: "entry")
 */
static Ttk_StateTable edittext_statemap[] =
static const Ttk_StateTable edittext_statemap[] =
{
    { ETS_DISABLED,	TTK_STATE_DISABLED, 0 },
    { ETS_READONLY,	TTK_STATE_READONLY, 0 },
    { ETS_FOCUSED,	TTK_STATE_FOCUS, 0 },
    { ETS_HOT,		TTK_STATE_ACTIVE, 0 },
    { ETS_NORMAL,	0, 0 }
/* NOT USED: ETS_ASSIST, ETS_SELECTED */
};

/*
 * Combobox text field statemap:
 * Same as edittext_statemap, but doesn't use ETS_READONLY
 * (fixes: #1032409)
 */
static Ttk_StateTable combotext_statemap[] =
static const Ttk_StateTable combotext_statemap[] =
{
    { ETS_DISABLED,	TTK_STATE_DISABLED, 0 },
    { ETS_FOCUSED,	TTK_STATE_FOCUS, 0 },
    { ETS_HOT,		TTK_STATE_ACTIVE, 0 },
    { ETS_NORMAL,	0, 0 }
};

/*
 * Combobox button: (CBP_DROPDOWNBUTTON)
 */
static Ttk_StateTable combobox_statemap[] = {
static const Ttk_StateTable combobox_statemap[] = {
    { CBXS_DISABLED,	TTK_STATE_DISABLED, 0 },
    { CBXS_PRESSED, 	TTK_STATE_PRESSED, 0 },
    { CBXS_HOT, 	TTK_STATE_ACTIVE, 0 },
    { CBXS_HOT, 	TTK_STATE_HOVER, 0 },
    { CBXS_NORMAL, 	0, 0 }
};

/*
 * Toolbar buttons (TP_BUTTON):
 */
static Ttk_StateTable toolbutton_statemap[] =  {
static const Ttk_StateTable toolbutton_statemap[] =  {
    { TS_DISABLED, 	TTK_STATE_DISABLED, 0 },
    { TS_PRESSED,	TTK_STATE_PRESSED, 0 },
    { TS_HOTCHECKED,	TTK_STATE_SELECTED|TTK_STATE_ACTIVE, 0 },
    { TS_CHECKED, 	TTK_STATE_SELECTED, 0 },
    { TS_HOT,  		TTK_STATE_ACTIVE, 0 },
    { TS_NORMAL, 	0,0 }
};

/*
 * Scrollbars (Tk: "Scrollbar.thumb")
 */
static Ttk_StateTable scrollbar_statemap[] =
static const Ttk_StateTable scrollbar_statemap[] =
{
    { SCRBS_DISABLED, 	TTK_STATE_DISABLED, 0 },
    { SCRBS_PRESSED, 	TTK_STATE_PRESSED, 0 },
    { SCRBS_HOT,	TTK_STATE_ACTIVE, 0 },
    { SCRBS_NORMAL, 	0, 0 }
};

static Ttk_StateTable uparrow_statemap[] =
static const Ttk_StateTable uparrow_statemap[] =
{
    { ABS_UPDISABLED,	TTK_STATE_DISABLED, 0 },
    { ABS_UPPRESSED, 	TTK_STATE_PRESSED, 0 },
    { ABS_UPHOT,	TTK_STATE_ACTIVE, 0 },
    { ABS_UPNORMAL, 	0, 0 }
};

static Ttk_StateTable downarrow_statemap[] =
static const Ttk_StateTable downarrow_statemap[] =
{
    { ABS_DOWNDISABLED,	TTK_STATE_DISABLED, 0 },
    { ABS_DOWNPRESSED, 	TTK_STATE_PRESSED, 0 },
    { ABS_DOWNHOT,	TTK_STATE_ACTIVE, 0 },
    { ABS_DOWNNORMAL, 	0, 0 }
};

static Ttk_StateTable leftarrow_statemap[] =
static const Ttk_StateTable leftarrow_statemap[] =
{
    { ABS_LEFTDISABLED,	TTK_STATE_DISABLED, 0 },
    { ABS_LEFTPRESSED, 	TTK_STATE_PRESSED, 0 },
    { ABS_LEFTHOT,	TTK_STATE_ACTIVE, 0 },
    { ABS_LEFTNORMAL, 	0, 0 }
};

static Ttk_StateTable rightarrow_statemap[] =
static const Ttk_StateTable rightarrow_statemap[] =
{
    { ABS_RIGHTDISABLED,TTK_STATE_DISABLED, 0 },
    { ABS_RIGHTPRESSED, TTK_STATE_PRESSED, 0 },
    { ABS_RIGHTHOT,	TTK_STATE_ACTIVE, 0 },
    { ABS_RIGHTNORMAL, 	0, 0 }
};

static Ttk_StateTable spinbutton_statemap[] =
static const Ttk_StateTable spinbutton_statemap[] =
{
    { DNS_DISABLED,	TTK_STATE_DISABLED, 0 },
    { DNS_PRESSED,	TTK_STATE_PRESSED,  0 },
    { DNS_HOT,		TTK_STATE_ACTIVE,   0 },
    { DNS_NORMAL,	0,		    0 },
};

/*
 * Trackbar thumb: (Tk: "scale slider")
 */
static Ttk_StateTable scale_statemap[] =
static const Ttk_StateTable scale_statemap[] =
{
    { TUS_DISABLED, 	TTK_STATE_DISABLED, 0 },
    { TUS_PRESSED, 	TTK_STATE_PRESSED, 0 },
    { TUS_FOCUSED, 	TTK_STATE_FOCUS, 0 },
    { TUS_HOT,		TTK_STATE_ACTIVE, 0 },
    { TUS_NORMAL, 	0, 0 }
};

static Ttk_StateTable tabitem_statemap[] =
static const Ttk_StateTable tabitem_statemap[] =
{
    { TIS_DISABLED,     TTK_STATE_DISABLED, 0 },
    { TIS_SELECTED,     TTK_STATE_SELECTED, 0 },
    { TIS_HOT,          TTK_STATE_ACTIVE,   0 },
    { TIS_FOCUSED,      TTK_STATE_FOCUS,    0 },
    { TIS_NORMAL,       0,                  0 },
};
372
373
374
375
376
377
378
379

380
381
382
383

384
385
386
387
388
389
390






391
392
393
394
395
396
397
398

399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414

415
416

417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432

433
434
435
436
437




438
439
440
441
442
443
444
370
371
372
373
374
375
376

377
378
379
380

381
382






383
384
385
386
387
388
389
390
391
392
393
394
395

396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411

412
413

414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429

430
431




432
433
434
435
436
437
438
439
440
441
442







-
+



-
+

-
-
-
-
-
-
+
+
+
+
+
+







-
+















-
+

-
+















-
+

-
-
-
-
+
+
+
+







 *	This gives bogus metrics for some parts (in particular,
 *	BP_PUSHBUTTONS).  Set the IGNORE_THEMESIZE flag to skip this call.
 */

typedef struct 	/* XP element specifications */
{
    const char	*elementName;	/* Tk theme engine element name */
    Ttk_ElementSpec *elementSpec;
    const Ttk_ElementSpec *elementSpec;
    				/* Element spec (usually GenericElementSpec) */
    LPCWSTR	className;	/* Windows window class name */
    int 	partId;		/* BP_PUSHBUTTON, BP_CHECKBUTTON, etc. */
    Ttk_StateTable *statemap;	/* Map Tk states to XP states */
    const Ttk_StateTable *statemap;	/* Map Tk states to XP states */
    Ttk_Padding	padding;	/* See NOTE-GetThemeMargins */
    int  	flags;
#   define 	IGNORE_THEMESIZE 0x80000000 /* See NOTE-GetThemePartSize */
#   define 	PAD_MARGINS	 0x40000000 /* See NOTE-GetThemeMargins */
#   define 	HEAP_ELEMENT	 0x20000000 /* ElementInfo is on heap */
#   define 	HALF_HEIGHT	 0x10000000 /* Used by GenericSizedElements */
#   define 	HALF_WIDTH	 0x08000000 /* Used by GenericSizedElements */
    unsigned  	flags;
#   define 	IGNORE_THEMESIZE 0x80000000U /* See NOTE-GetThemePartSize */
#   define 	PAD_MARGINS	 0x40000000U /* See NOTE-GetThemeMargins */
#   define 	HEAP_ELEMENT	 0x20000000U /* ElementInfo is on heap */
#   define 	HALF_HEIGHT	 0x10000000U /* Used by GenericSizedElements */
#   define 	HALF_WIDTH	 0x08000000U /* Used by GenericSizedElements */
} ElementInfo;

typedef struct
{
    /*
     * Static data, initialized when element is registered:
     */
    ElementInfo	*info;
    const ElementInfo	*info;
    XPThemeProcs *procs;	/* Pointer to theme procedure table */

    /*
     * Dynamic data, allocated by InitElementData:
     */
    HTHEME	hTheme;
    HDC		hDC;
    HWND	hwnd;

    /* For TkWinDrawableReleaseDC: */
    Drawable	drawable;
    TkWinDCState dcState;
} ElementData;

static ElementData *
NewElementData(XPThemeProcs *procs, ElementInfo *info)
NewElementData(XPThemeProcs *procs, const ElementInfo *info)
{
    ElementData *elementData = ckalloc(sizeof(ElementData));
    ElementData *elementData = (ElementData *)ckalloc(sizeof(ElementData));

    elementData->procs = procs;
    elementData->info = info;
    elementData->hTheme = elementData->hDC = 0;

    return elementData;
}

/*
 * Destroy elements. If the element was created by the element factory
 * then the info member is dynamically allocated. Otherwise it was
 * static data from the C object and only the ElementData needs freeing.
 */
static void DestroyElementData(void *clientData)
{
    ElementData *elementData = clientData;
    ElementData *elementData = (ElementData *)clientData;
    if (elementData->info->flags & HEAP_ELEMENT) {
	ckfree(elementData->info->statemap);
	ckfree(elementData->info->className);
	ckfree(elementData->info->elementName);
	ckfree(elementData->info);
	ckfree((char *)elementData->info->statemap);
	ckfree((char *)elementData->info->className);
	ckfree((char *)elementData->info->elementName);
	ckfree((char *)elementData->info);
    }
    ckfree(clientData);
}

/*
 * InitElementData --
 * 	Looks up theme handle.  If Drawable argument is non-NULL,
493
494
495
496
497
498
499
500

501
502

503
504
505
506
507
508
509
510

511
512
513
514
515
516
517
491
492
493
494
495
496
497

498
499
500
501
502
503
504
505
506
507
508

509
510
511
512
513
514
515
516







-
+


+







-
+







 * such as radiobutton and checkbutton indicators, scrollbar arrows, etc.
 */

static void GenericElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    ElementData *elementData = clientData;
    ElementData *elementData = (ElementData *)clientData;
    HRESULT result;
    SIZE size;
    (void)elementRecord;

    if (!InitElementData(elementData, tkwin, 0))
	return;

    if (!(elementData->info->flags & IGNORE_THEMESIZE)) {
	result = elementData->procs->GetThemePartSize(
	    elementData->hTheme,
	    elementData->hDC,
	    NULL,
	    elementData->info->partId,
	    Ttk_StateTableLookup(elementData->info->statemap, 0),
	    NULL /*RECT *prc*/,
	    TS_TRUE,
	    &size);

	if (SUCCEEDED(result)) {
529
530
531
532
533
534
535
536

537

538
539
540
541
542
543
544
528
529
530
531
532
533
534

535
536
537
538
539
540
541
542
543
544







-
+

+







    }
}

static void GenericElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    ElementData *elementData = clientData;
    ElementData *elementData = (ElementData *)clientData;
    RECT rc;
    (void)elementRecord;

    if (!InitElementData(elementData, tkwin, d)) {
	return;
    }

    if (elementData->info->flags & PAD_MARGINS) {
    	b = Ttk_PadBox(b, elementData->info->padding);
552
553
554
555
556
557
558
559

560
561
562
563
564
565
566
552
553
554
555
556
557
558

559
560
561
562
563
564
565
566







-
+







	Ttk_StateTableLookup(elementData->info->statemap, state),
	&rc,
	NULL/*pContentRect*/);

    FreeElementData(elementData);
}

static Ttk_ElementSpec GenericElementSpec =
static const Ttk_ElementSpec GenericElementSpec =
{
    TK_STYLE_VERSION_2,
    sizeof(NullElement),
    TtkNullElementOptions,
    GenericElementSize,
    GenericElementDraw
};
574
575
576
577
578
579
580
581

582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599

600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617

618
619
620
621
622
623
624
625
626
627
628
629

630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646

647
648

649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666

667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685

686
687
688
689
690
691
692
693
694
695
696
697
698

699
700
701
702
703
704
705
574
575
576
577
578
579
580

581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598

599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616

617
618
619
620
621
622
623
624
625
626
627
628

629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645

646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666

667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685

686
687
688
689
690
691
692
693
694
695
696
697
698

699
700
701
702
703
704
705
706







-
+

















-
+

















-
+











-
+
















-
+


+

















-
+


















-
+












-
+







 */

static void
GenericSizedElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    ElementData *elementData = clientData;
    ElementData *elementData = (ElementData *)clientData;

    if (!InitElementData(elementData, tkwin, 0))
	return;

    GenericElementSize(clientData, elementRecord, tkwin,
	widthPtr, heightPtr, paddingPtr);

    *widthPtr = elementData->procs->GetThemeSysSize(NULL,
	(elementData->info->flags >> 8) & 0xff);
    *heightPtr = elementData->procs->GetThemeSysSize(NULL,
	elementData->info->flags & 0xff);
    if (elementData->info->flags & HALF_HEIGHT)
	*heightPtr /= 2;
    if (elementData->info->flags & HALF_WIDTH)
	*widthPtr /= 2;
}

static Ttk_ElementSpec GenericSizedElementSpec = {
static const Ttk_ElementSpec GenericSizedElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(NullElement),
    TtkNullElementOptions,
    GenericSizedElementSize,
    GenericElementDraw
};

/*----------------------------------------------------------------------
 * +++ Spinbox arrow element.
 *     These are half-height scrollbar buttons.
 */

static void
SpinboxArrowElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    ElementData *elementData = clientData;
    ElementData *elementData = (ElementData *)clientData;

    if (!InitElementData(elementData, tkwin, 0))
	return;

    GenericSizedElementSize(clientData, elementRecord, tkwin,
	widthPtr, heightPtr, paddingPtr);

    /* force the arrow button height to half size */
    *heightPtr /= 2;
}

static Ttk_ElementSpec SpinboxArrowElementSpec = {
static const Ttk_ElementSpec SpinboxArrowElementSpec = {
    TK_STYLE_VERSION_2,
    sizeof(NullElement),
    TtkNullElementOptions,
    SpinboxArrowElementSize,
    GenericElementDraw
};

/*----------------------------------------------------------------------
 * +++ Scrollbar thumb element.
 *     Same as a GenericElement, but don't draw in the disabled state.
 */

static void ThumbElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    ElementData *elementData = clientData;
    ElementData *elementData = (ElementData *)clientData;
    unsigned stateId = Ttk_StateTableLookup(elementData->info->statemap, state);
    RECT rc = BoxToRect(b);
    (void)elementRecord;

    /*
     * Don't draw the thumb if we are disabled.
     */
    if (state & TTK_STATE_DISABLED)
	return;

    if (!InitElementData(elementData, tkwin, d))
	return;

    elementData->procs->DrawThemeBackground(elementData->hTheme,
	elementData->hDC, elementData->info->partId, stateId,
	&rc, NULL);

    FreeElementData(elementData);
}

static Ttk_ElementSpec ThumbElementSpec =
static const Ttk_ElementSpec ThumbElementSpec =
{
    TK_STYLE_VERSION_2,
    sizeof(NullElement),
    TtkNullElementOptions,
    GenericElementSize,
    ThumbElementDraw
};

/*----------------------------------------------------------------------
 * +++ Progress bar element.
 *	Increases the requested length of PP_CHUNK and PP_CHUNKVERT parts
 *	so that indeterminate progress bars show 3 bars instead of 1.
 */

static void PbarElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    ElementData *elementData = clientData;
    ElementData *elementData = (ElementData *)clientData;
    int nBars = 3;

    GenericElementSize(clientData, elementRecord, tkwin,
    	widthPtr, heightPtr, paddingPtr);

    if (elementData->info->partId == PP_CHUNK) {
    	*widthPtr *= nBars;
    } else if (elementData->info->partId == PP_CHUNKVERT) {
    	*heightPtr *= nBars;
    }
}

static Ttk_ElementSpec PbarElementSpec =
static const Ttk_ElementSpec PbarElementSpec =
{
    TK_STYLE_VERSION_2,
    sizeof(NullElement),
    TtkNullElementOptions,
    PbarElementSize,
    GenericElementDraw
};
718
719
720
721
722
723
724
725

726
727

728
729
730
731
732
733
734
735
736
737
738
739

740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757

758
759
760
761
762
763
764

765
766
767
768
769
770
771
772

773
774
775
776
777
778
779
780
781
782
783
784
785
786
787

788
789
790
791
792
793
794
795
796

797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815

816
817
818

819
820

821
822
823
824
825
826
827
828
829
830
831
832
833

834
835
836
837
838
839
840


841
842
843
844
845
846

847
848

849
850
851
852
853
854
855
719
720
721
722
723
724
725

726
727
728
729
730
731
732
733
734
735
736
737
738
739
740

741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758

759
760
761
762
763
764
765

766
767
768
769
770
771
772
773

774
775
776
777
778
779
780
781
782
783
784
785
786
787
788

789
790
791
792
793
794
795
796
797

798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816

817
818
819

820
821

822
823
824
825
826
827
828
829
830
831
832
833
834

835
836
837
838
839
840


841
842
843
844
845
846
847

848
849

850
851
852
853
854
855
856
857







-
+


+











-
+

















-
+






-
+







-
+














-
+








-
+


















-
+


-
+

-
+












-
+





-
-
+
+





-
+

-
+







 *	The TIS_* and TILES_* definitions are identical, so
 * 	we can use the same statemap no matter what the partId.
 */
static void TabElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    ElementData *elementData = clientData;
    ElementData *elementData = (ElementData *)clientData;
    int partId = elementData->info->partId;
    RECT rc = BoxToRect(b);
    (void)elementRecord;

    if (!InitElementData(elementData, tkwin, d))
	return;
    if (state & TTK_STATE_USER1)
	partId = TABP_TABITEMLEFTEDGE;
    elementData->procs->DrawThemeBackground(
	elementData->hTheme, elementData->hDC, partId,
	Ttk_StateTableLookup(elementData->info->statemap, state), &rc, NULL);
    FreeElementData(elementData);
}

static Ttk_ElementSpec TabElementSpec =
static const Ttk_ElementSpec TabElementSpec =
{
    TK_STYLE_VERSION_2,
    sizeof(NullElement),
    TtkNullElementOptions,
    GenericElementSize,
    TabElementDraw
};

/*----------------------------------------------------------------------
 * +++  Tree indicator element.
 *
 *	Generic element, but don't display at all if TTK_STATE_LEAF (=USER2) set
 */

#define TTK_STATE_OPEN TTK_STATE_USER1
#define TTK_STATE_LEAF TTK_STATE_USER2

static Ttk_StateTable header_statemap[] =
static const Ttk_StateTable header_statemap[] =
{
    { HIS_PRESSED, 	TTK_STATE_PRESSED, 0 },
    { HIS_HOT,  	TTK_STATE_ACTIVE, 0 },
    { HIS_NORMAL, 	0,0 },
};

static Ttk_StateTable treeview_statemap[] =
static const Ttk_StateTable treeview_statemap[] =
{
    { TREIS_DISABLED, 	TTK_STATE_DISABLED, 0 },
    { TREIS_SELECTED,	TTK_STATE_SELECTED, 0},
    { TREIS_HOT, 	TTK_STATE_ACTIVE, 0 },
    { TREIS_NORMAL, 	0,0 },
};

static Ttk_StateTable tvpglyph_statemap[] =
static const Ttk_StateTable tvpglyph_statemap[] =
{
    { GLPS_OPENED, 	TTK_STATE_OPEN, 0 },
    { GLPS_CLOSED, 	0,0 },
};

static void TreeIndicatorElementDraw(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    Drawable d, Ttk_Box b, unsigned int state)
{
    if (!(state & TTK_STATE_LEAF)) {
        GenericElementDraw(clientData,elementRecord,tkwin,d,b,state);
    }
}

static Ttk_ElementSpec TreeIndicatorElementSpec =
static const Ttk_ElementSpec TreeIndicatorElementSpec =
{
    TK_STYLE_VERSION_2,
    sizeof(NullElement),
    TtkNullElementOptions,
    GenericElementSize,
    TreeIndicatorElementDraw
};

#if BROKEN_TEXT_ELEMENT
#ifdef BROKEN_TEXT_ELEMENT

/*
 *----------------------------------------------------------------------
 * Text element (does not work yet).
 *
 * According to "Using Windows XP Visual Styles",  we need to select
 * a font into the DC before calling DrawThemeText().
 * There's just no easy way to get an HFONT out of a Tk_Font.
 * Maybe GetThemeFont() would work?
 *
 */

typedef struct
{
    Tcl_Obj *textObj;
    Tcl_Obj *fontObj;
} TextElement;

static Ttk_ElementOptionSpec TextElementOptions[] =
static const Ttk_ElementOptionSpec TextElementOptions[] =
{
    { "-text", TK_OPTION_STRING,
	Tk_Offset(TextElement,textObj), "" },
	offsetof(TextElement,textObj), "" },
    { "-font", TK_OPTION_FONT,
	Tk_Offset(TextElement,fontObj), DEFAULT_FONT },
	offsetof(TextElement,fontObj), DEFAULT_FONT },
    { NULL }
};

static void TextElementSize(
    void *clientData, void *elementRecord, Tk_Window tkwin,
    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
    TextElement *element = elementRecord;
    ElementData *elementData = clientData;
    RECT rc = {0, 0};
    HRESULT hr = S_OK;
    const char *src;
    int len;
    TkSizeT len;
    Tcl_DString ds;

    if (!InitElementData(elementData, tkwin, 0))
	return;

    src = Tcl_GetStringFromObj(element->textObj, &len);
    Tcl_WinUtfToTChar(src, len, &ds);
    src = TkGetStringFromObj(element->textObj, &len);
    Tcl_DStringInit(&ds);
    hr = elementData->procs->GetThemeTextExtent(
	    elementData->hTheme,
	    elementData->hDC,
	    elementData->info->partId,
	    Ttk_StateTableLookup(elementData->info->statemap, 0),
	    (WCHAR *) Tcl_DStringValue(&ds),
	    Tcl_UtfToWCharDString(src, len, &ds),
	    -1,
	    DT_LEFT,// | DT_BOTTOM | DT_NOPREFIX,
	    DT_LEFT /* | DT_BOTTOM | DT_NOPREFIX */,
	    NULL,
	    &rc);

    if (SUCCEEDED(hr)) {
	*widthPtr = rc.right - rc.left;
	*heightPtr = rc.bottom - rc.top;
    }
865
866
867
868
869
870
871
872

873
874
875
876
877
878
879


880
881
882
883
884
885

886
887

888
889
890
891
892
893
894
895

896
897
898
899
900
901
902
867
868
869
870
871
872
873

874
875
876
877
878
879


880
881
882
883
884
885
886

887
888

889
890
891
892
893
894
895
896

897
898
899
900
901
902
903
904







-
+





-
-
+
+





-
+

-
+







-
+







    Drawable d, Ttk_Box b, unsigned int state)
{
    TextElement *element = elementRecord;
    ElementData *elementData = clientData;
    RECT rc = BoxToRect(b);
    HRESULT hr = S_OK;
    const char *src;
    int len;
    TkSizeT len;
    Tcl_DString ds;

    if (!InitElementData(elementData, tkwin, d))
	return;

    src = Tcl_GetStringFromObj(element->textObj, &len);
    Tcl_WinUtfToTChar(src, len, &ds);
    src = TkGetStringFromObj(element->textObj, &len);
    Tcl_DStringInit(&ds);
    hr = elementData->procs->DrawThemeText(
	    elementData->hTheme,
	    elementData->hDC,
	    elementData->info->partId,
	    Ttk_StateTableLookup(elementData->info->statemap, state),
	    (WCHAR *) Tcl_DStringValue(&ds),
	    Tcl_UtfToWCharDString(src, len, &ds),
	    -1,
	    DT_LEFT,// | DT_BOTTOM | DT_NOPREFIX,
	    DT_LEFT /* | DT_BOTTOM | DT_NOPREFIX */,
	    (state & TTK_STATE_DISABLED) ? DTT_GRAYED : 0,
	    &rc);

    Tcl_DStringFree(&ds);
    FreeElementData(elementData);
}

static Ttk_ElementSpec TextElementSpec =
static const Ttk_ElementSpec TextElementSpec =
{
    TK_STYLE_VERSION_2,
    sizeof(TextElement),
    TextElementOptions,
    TextElementSize,
    TextElementDraw
};
913
914
915
916
917
918
919
920
921


922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940


941
942
943
944
945
946


947
948
949
950
951
952
953
954
955
956
957
958
959
960
961

962
963
964
965
966
967
968
915
916
917
918
919
920
921


922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940


941
942
943
944
945
946


947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962

963
964
965
966
967
968
969
970







-
-
+
+

















-
-
+
+




-
-
+
+














-
+







    TTK_GROUP("Button.button", TTK_FILL_BOTH,
	TTK_GROUP("Button.focus", TTK_FILL_BOTH,
	    TTK_GROUP("Button.padding", TTK_FILL_BOTH,
		TTK_NODE("Button.label", TTK_FILL_BOTH)))))

TTK_LAYOUT("TMenubutton",
    TTK_NODE("Menubutton.dropdown", TTK_PACK_RIGHT|TTK_FILL_Y)
    TTK_GROUP("Menubutton.button", TTK_PACK_RIGHT|TTK_EXPAND|TTK_FILL_BOTH,
	    TTK_GROUP("Menubutton.padding", TTK_PACK_LEFT|TTK_EXPAND|TTK_FILL_X,
    TTK_GROUP("Menubutton.button", TTK_FILL_BOTH,
	    TTK_GROUP("Menubutton.padding", TTK_FILL_X,
	        TTK_NODE("Menubutton.label", 0))))

TTK_LAYOUT("Horizontal.TScrollbar",
    TTK_GROUP("Horizontal.Scrollbar.trough", TTK_FILL_X,
	TTK_NODE("Horizontal.Scrollbar.leftarrow", TTK_PACK_LEFT)
	TTK_NODE("Horizontal.Scrollbar.rightarrow", TTK_PACK_RIGHT)
	TTK_GROUP("Horizontal.Scrollbar.thumb", TTK_FILL_BOTH|TTK_UNIT,
	    TTK_NODE("Horizontal.Scrollbar.grip", 0))))

TTK_LAYOUT("Vertical.TScrollbar",
    TTK_GROUP("Vertical.Scrollbar.trough", TTK_FILL_Y,
	TTK_NODE("Vertical.Scrollbar.uparrow", TTK_PACK_TOP)
	TTK_NODE("Vertical.Scrollbar.downarrow", TTK_PACK_BOTTOM)
	TTK_GROUP("Vertical.Scrollbar.thumb", TTK_FILL_BOTH|TTK_UNIT,
	    TTK_NODE("Vertical.Scrollbar.grip", 0))))

TTK_LAYOUT("Horizontal.TScale",
    TTK_GROUP("Scale.focus", TTK_EXPAND|TTK_FILL_BOTH,
	TTK_GROUP("Horizontal.Scale.trough", TTK_EXPAND|TTK_FILL_BOTH,
    TTK_GROUP("Scale.focus", TTK_FILL_BOTH,
	TTK_GROUP("Horizontal.Scale.trough", TTK_FILL_BOTH,
	    TTK_NODE("Horizontal.Scale.track", TTK_FILL_X)
	    TTK_NODE("Horizontal.Scale.slider", TTK_PACK_LEFT) )))

TTK_LAYOUT("Vertical.TScale",
    TTK_GROUP("Scale.focus", TTK_EXPAND|TTK_FILL_BOTH,
	TTK_GROUP("Vertical.Scale.trough", TTK_EXPAND|TTK_FILL_BOTH,
    TTK_GROUP("Scale.focus", TTK_FILL_BOTH,
	TTK_GROUP("Vertical.Scale.trough", TTK_FILL_BOTH,
	    TTK_NODE("Vertical.Scale.track", TTK_FILL_Y)
	    TTK_NODE("Vertical.Scale.slider", TTK_PACK_TOP) )))

TTK_END_LAYOUT_TABLE

/*----------------------------------------------------------------------
 * +++ XP element info table:
 */

#define PAD(l,t,r,b) {l,t,r,b}
#define NOPAD {0,0,0,0}

/* name spec className partId statemap padding flags */

static ElementInfo ElementInfoTable[] = {
static const ElementInfo ElementInfoTable[] = {
    { "Checkbutton.indicator", &GenericElementSpec, L"BUTTON",
    	BP_CHECKBOX, checkbox_statemap, PAD(0, 0, 4, 0), PAD_MARGINS },
    { "Radiobutton.indicator", &GenericElementSpec, L"BUTTON",
    	BP_RADIOBUTTON, radiobutton_statemap, PAD(0, 0, 4, 0), PAD_MARGINS },
    { "Button.button", &GenericElementSpec, L"BUTTON",
    	BP_PUSHBUTTON, pushbutton_statemap, PAD(3, 3, 3, 3), IGNORE_THEMESIZE },
    { "Labelframe.border", &GenericElementSpec, L"BUTTON",
1040
1041
1042
1043
1044
1045
1046
1047
1048

1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061

1062
1063
1064
1065
1066
1067
1068
1042
1043
1044
1045
1046
1047
1048


1049
1050
1051
1052

1053
1054
1055
1056
1057
1058
1059
1060

1061
1062
1063
1064
1065
1066
1067
1068







-
-
+



-








-
+







	EP_EDITTEXT, edittext_statemap, PAD(1, 1, 1, 1), 0 },
    { "Spinbox.uparrow", &SpinboxArrowElementSpec, L"SPIN",
	SPNP_UP, spinbutton_statemap, NOPAD,
	PAD_MARGINS | ((SM_CXVSCROLL << 8) | SM_CYVSCROLL) },
    { "Spinbox.downarrow", &SpinboxArrowElementSpec, L"SPIN",
	SPNP_DOWN, spinbutton_statemap, NOPAD,
	PAD_MARGINS | ((SM_CXVSCROLL << 8) | SM_CYVSCROLL) },

#if BROKEN_TEXT_ELEMENT
#ifdef BROKEN_TEXT_ELEMENT
    { "Labelframe.text", &TextElementSpec, L"BUTTON",
    	BP_GROUPBOX, groupbox_statemap, NOPAD,0 },
#endif

    { 0,0,0,0,0,NOPAD,0 }
};
#undef PAD


static int
GetSysFlagFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int *resultPtr)
{
    static const char *names[] = {
    static const char *const names[] = {
	"SM_CXBORDER", "SM_CYBORDER", "SM_CXVSCROLL", "SM_CYVSCROLL",
	"SM_CXHSCROLL", "SM_CYHSCROLL", "SM_CXMENUCHECK", "SM_CYMENUCHECK",
	"SM_CXMENUSIZE", "SM_CYMENUSIZE", "SM_CXSIZE", "SM_CYSIZE", "SM_CXSMSIZE",
	"SM_CYSMSIZE", NULL
    };
    int flags[] = {
	SM_CXBORDER, SM_CYBORDER, SM_CXVSCROLL, SM_CYVSCROLL,
1108
1109
1110
1111
1112
1113
1114
1115

1116
1117
1118
1119
1120
1121
1122
1123

1124
1125
1126

1127
1128
1129

1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146



1147
1148
1149
1150
1151
1152
1153
1108
1109
1110
1111
1112
1113
1114

1115
1116
1117
1118
1119
1120
1121
1122

1123
1124
1125

1126
1127
1128

1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144


1145
1146
1147
1148
1149
1150
1151
1152
1153
1154







-
+







-
+


-
+


-
+















-
-
+
+
+







    Tcl_Interp *interp,
    void *clientData,
    Ttk_Theme theme,
    const char *elementName,
    int objc,
    Tcl_Obj *const objv[])
{
    XPThemeData *themeData = clientData;
    XPThemeData *themeData = (XPThemeData *)clientData;
    ElementInfo *elementPtr = NULL;
    ClientData elementData;
    LPCWSTR className;
    int partId = 0;
    Ttk_StateTable *stateTable;
    Ttk_Padding pad = {0, 0, 0, 0};
    int flags = 0;
    int length = 0;
    TkSizeT length = 0;
    char *name;
    LPWSTR wname;
    Ttk_ElementSpec *elementSpec = &GenericElementSpec;
    const Ttk_ElementSpec *elementSpec = &GenericElementSpec;
    Tcl_DString classBuf;

    static const char *optionStrings[] =
    static const char *const optionStrings[] =
	{ "-padding","-width","-height","-margins", "-syssize",
	  "-halfheight", "-halfwidth", NULL };
    enum { O_PADDING, O_WIDTH, O_HEIGHT, O_MARGINS, O_SYSSIZE,
	   O_HALFHEIGHT, O_HALFWIDTH };

    if (objc < 2) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
	    "missing required arguments 'class' and/or 'partId'", -1));
	Tcl_SetErrorCode(interp, "TTK", "VSAPI", "REQUIRED", NULL);
	return TCL_ERROR;
    }

    if (Tcl_GetIntFromObj(interp, objv[1], &partId) != TCL_OK) {
	return TCL_ERROR;
    }
    name = Tcl_GetStringFromObj(objv[0], &length);
    className = (LPCWSTR) Tcl_WinUtfToTChar(name, length, &classBuf);
    name = TkGetStringFromObj(objv[0], &length);
    Tcl_DStringInit(&classBuf);
    className = Tcl_UtfToWCharDString(name, length, &classBuf);

    /* flags or padding */
    if (objc > 3) {
	int i = 3, option = 0;
	for (i = 3; i < objc; i += 2) {
	    int tmp = 0;
	    if (i == objc -1) {
1214
1215
1216
1217
1218
1219
1220
1221

1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239

1240
1241
1242
1243

1244
1245
1246
1247
1248
1249
1250
1251

1252
1253
1254
1255
1256

1257
1258
1259
1260
1261
1262
1263
1215
1216
1217
1218
1219
1220
1221

1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239

1240
1241
1242
1243

1244
1245
1246
1247
1248
1249
1250
1251

1252
1253
1254
1255
1256

1257
1258
1259
1260
1261
1262
1263
1264







-
+

















-
+



-
+







-
+




-
+







    /* convert a statemap into a state table */
    if (objc > 2) {
	Tcl_Obj **specs;
	int n,j,count, status = TCL_OK;
	if (Tcl_ListObjGetElements(interp, objv[2], &count, &specs) != TCL_OK)
	    goto retErr;
	/* we over-allocate to ensure there is a terminating entry */
	stateTable = ckalloc(sizeof(Ttk_StateTable) * (count + 1));
	stateTable = (Ttk_StateTable *)ckalloc(sizeof(Ttk_StateTable) * (count + 1));
	memset(stateTable, 0, sizeof(Ttk_StateTable) * (count + 1));
	for (n = 0, j = 0; status == TCL_OK && n < count; n += 2, ++j) {
	    Ttk_StateSpec spec = {0,0};
	    status = Ttk_GetStateSpecFromObj(interp, specs[n], &spec);
	    if (status == TCL_OK) {
		stateTable[j].onBits = spec.onbits;
		stateTable[j].offBits = spec.offbits;
		status = Tcl_GetIntFromObj(interp, specs[n+1],
			&stateTable[j].index);
	    }
	}
	if (status != TCL_OK) {
	    ckfree(stateTable);
	    Tcl_DStringFree(&classBuf);
	    return status;
	}
    } else {
	stateTable = ckalloc(sizeof(Ttk_StateTable));
	stateTable = (Ttk_StateTable *)ckalloc(sizeof(Ttk_StateTable));
	memset(stateTable, 0, sizeof(Ttk_StateTable));
    }

    elementPtr = ckalloc(sizeof(ElementInfo));
    elementPtr = (ElementInfo *)ckalloc(sizeof(ElementInfo));
    elementPtr->elementSpec = elementSpec;
    elementPtr->partId = partId;
    elementPtr->statemap = stateTable;
    elementPtr->padding = pad;
    elementPtr->flags = HEAP_ELEMENT | flags;

    /* set the element name to an allocated copy */
    name = ckalloc(strlen(elementName) + 1);
    name = (char *)ckalloc(strlen(elementName) + 1);
    strcpy(name, elementName);
    elementPtr->elementName = name;

    /* set the class name to an allocated copy */
    wname = ckalloc(Tcl_DStringLength(&classBuf) + sizeof(WCHAR));
    wname = (LPWSTR)ckalloc(Tcl_DStringLength(&classBuf) + sizeof(WCHAR));
    wcscpy(wname, className);
    elementPtr->className = wname;

    elementData = NewElementData(themeData->procs, elementPtr);
    Ttk_RegisterElementSpec(
	theme, elementName, elementPtr->elementSpec, elementData);

1277
1278
1279
1280
1281
1282
1283
1284

1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308

1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321

1322
1323
1324
1325
1326
1327
1328
1278
1279
1280
1281
1282
1283
1284

1285




1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304

1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317

1318
1319
1320
1321
1322
1323
1324
1325







-
+
-
-
-
-



















-
+












-
+








MODULE_SCOPE int TtkXPTheme_Init(Tcl_Interp *interp, HWND hwnd)
{
    XPThemeData *themeData;
    XPThemeProcs *procs;
    HINSTANCE hlibrary;
    Ttk_Theme themePtr, parentPtr, vistaPtr;
    ElementInfo *infoPtr;
    const ElementInfo *infoPtr;
    OSVERSIONINFOW os;

    os.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
    GetVersionExW(&os);

    procs = LoadXPThemeProcs(&hlibrary);
    if (!procs)
	return TCL_ERROR;
    procs->stubWindow = hwnd;

    /*
     * Create the new style engine.
     */
    parentPtr = Ttk_GetTheme(interp, "winnative");
    themePtr = Ttk_CreateTheme(interp, "xpnative", parentPtr);

    if (!themePtr)
        return TCL_ERROR;

    /*
     * Set theme data and cleanup proc
     */

    themeData = ckalloc(sizeof(XPThemeData));
    themeData = (XPThemeData *)ckalloc(sizeof(XPThemeData));
    themeData->procs = procs;
    themeData->hlibrary = hlibrary;

    Ttk_SetThemeEnabledProc(themePtr, XPThemeEnabled, themeData);
    Ttk_RegisterCleanup(interp, themeData, XPThemeDeleteProc);
    Ttk_RegisterElementFactory(interp, "vsapi", Ttk_CreateVsapiElement, themeData);

    /*
     * Create the vista theme on suitable platform versions and set the theme
     * enable function. The theme itself is defined in script.
     */

    if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && os.dwMajorVersion > 5) {
    if (TkWinGetPlatformTheme() == TK_THEME_WIN_VISTA) {
	vistaPtr = Ttk_CreateTheme(interp, "vista", themePtr);
	if (vistaPtr) {
	    Ttk_SetThemeEnabledProc(vistaPtr, XPThemeEnabled, themeData);
	}
    }

    /*
Changes to win/winMain.c.
9
10
11
12
13
14
15

16
17
18
19
20
21
22
23
24
25
26
27



28
29








30
31
32
33
34
35
36



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56



57


58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73


74
75
76
77
78
79
80
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74

75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101







+












+
+
+


+
+
+
+
+
+
+
+







+
+
+




















+
+
+
-
+
+
















+
+







 * 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.
 */

#include "tk.h"
#include "tkWinInt.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN
#include <locale.h>
#include <stdlib.h>
#include <tchar.h>

#if defined(__GNUC__)
int _CRT_glob = 0;
#endif /* __GNUC__ */

#ifdef TK_TEST
#ifdef __cplusplus
extern "C" {
#endif
extern Tcl_PackageInitProc Tktest_Init;
#endif /* TK_TEST */

#if !defined(TCL_USE_STATIC_PACKAGES)
#   if TCL_MAJOR_VERSION > 8 || TCL_MINOR_VERSION > 6
#	define TCL_USE_STATIC_PACKAGES 1
#   else
#	define TCL_USE_STATIC_PACKAGES 0
#   endif
#endif

#if defined(STATIC_BUILD) && TCL_USE_STATIC_PACKAGES
extern Tcl_PackageInitProc Registry_Init;
extern Tcl_PackageInitProc Dde_Init;
extern Tcl_PackageInitProc Dde_SafeInit;
#endif

#ifdef __cplusplus
}
#endif
#ifdef TCL_BROKEN_MAINARGS
static void setargv(int *argcPtr, TCHAR ***argvPtr);
#endif

/*
 * Forward declarations for procedures defined later in this file:
 */

static BOOL consoleRequired = TRUE;

/*
 * The following #if block allows you to change the AppInit function by using
 * a #define of TCL_LOCAL_APPINIT instead of rewriting this entire file. The
 * #if checks for that #define and uses Tcl_AppInit if it doesn't exist.
 */

#ifndef TK_LOCAL_APPINIT
#define TK_LOCAL_APPINIT Tcl_AppInit
#endif
#ifndef MODULE_SCOPE
#   ifdef __cplusplus
#	define MODULE_SCOPE extern "C"
#   else
#   define MODULE_SCOPE extern
#	define MODULE_SCOPE extern
#   endif
#endif
MODULE_SCOPE int TK_LOCAL_APPINIT(Tcl_Interp *interp);

/*
 * The following #if block allows you to change how Tcl finds the startup
 * script, prime the library or encoding paths, fiddle with the argv, etc.,
 * without needing to rewrite Tk_Main()
 */

#ifdef TK_LOCAL_MAIN_HOOK
MODULE_SCOPE int TK_LOCAL_MAIN_HOOK(int *argc, TCHAR ***argv);
#endif

/* Make sure the stubbed variants of those are never used. */
#undef Tcl_ObjSetVar2
#undef Tcl_NewStringObj



/*
 *----------------------------------------------------------------------
 *
 * _tWinMain --
 *
 *	Main entry point from Windows.
102
103
104
105
106
107
108




109
110
111
112
113
114
115
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140







+
+
+
+







    LPTSTR lpszCmdLine,
    int nCmdShow)
#endif
{
    TCHAR **argv;
    int argc;
    TCHAR *p;
    (void)hInstance;
    (void)hPrevInstance;
    (void)lpszCmdLine;
    (void)nCmdShow;

    /*
     * Create the console channels and install them as the standard channels.
     * All I/O will be discarded until Tk_CreateConsoleWindow is called to
     * attach the console to a text widget.
     */

141
142
143
144
145
146
147



148
149
150
151
152
153
154
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182







+
+
+







	if (*p == '\\') {
	    *p = '/';
	}
    }

#ifdef TK_LOCAL_MAIN_HOOK
    TK_LOCAL_MAIN_HOOK(&argc, &argv);
#elif defined(UNICODE) && ((TCL_MAJOR_VERSION > 8) || (TCL_MINOR_VERSION > 6))
    /* This doesn't work on Windows without UNICODE, neither does it work with Tcl 8.6 */
    TclZipfs_AppHook(&argc, &argv);
#endif

    Tk_Main(argc, argv, TK_LOCAL_APPINIT);
    return 0;			/* Needed only to prevent compiler warning. */
}

/*
192
193
194
195
196
197
198
199

200
201
202
203
204

205
206
207
208
209
210
211
220
221
222
223
224
225
226

227
228
229
230
231

232
233
234
235
236
237
238
239







-
+




-
+







	    return TCL_ERROR;
	}
    }
#if defined(STATIC_BUILD) && TCL_USE_STATIC_PACKAGES
    if (Registry_Init(interp) == TCL_ERROR) {
	return TCL_ERROR;
    }
    Tcl_StaticPackage(interp, "registry", Registry_Init, 0);
    Tcl_StaticPackage(interp, "Registry", Registry_Init, 0);

    if (Dde_Init(interp) == TCL_ERROR) {
	return TCL_ERROR;
    }
    Tcl_StaticPackage(interp, "dde", Dde_Init, Dde_SafeInit);
    Tcl_StaticPackage(interp, "Dde", Dde_Init, Dde_SafeInit);
#endif

#ifdef TK_TEST
    if (Tktest_Init(interp) == TCL_ERROR) {
	return TCL_ERROR;
    }
    Tcl_StaticPackage(interp, "Tktest", Tktest_Init, 0);
233
234
235
236
237
238
239

240
241
242
243
244
245
246
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275







+







     * run interactively. Typically the startup file is "~/.apprc" where "app"
     * is the name of the application. If this line is deleted then no user-
     * specific startup file will be run under any conditions.
     */

    Tcl_ObjSetVar2(interp, Tcl_NewStringObj("tcl_rcFileName", -1), NULL,
	    Tcl_NewStringObj("~/wishrc.tcl", -1), TCL_GLOBAL_ONLY);

    return TCL_OK;
}

#if defined(TK_TEST)
/*
 *----------------------------------------------------------------------
 *
261
262
263
264
265
266
267

268
269
270
271
272
273
274
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304







+







#ifdef TCL_BROKEN_MAINARGS
int
main(
    int argc,
    char **dummy)
{
    TCHAR **argv;
    (void)dummy;
#else
int
_tmain(
    int argc,
    TCHAR **argv)
{
#endif
360
361
362
363
364
365
366
367

368
369
370
371
372
373
374
390
391
392
393
394
395
396

397
398
399
400
401
402
403
404







-
+







	}
    }

    /* Make sure we don't call ckalloc through the (not yet initialized) stub table */
    #undef Tcl_Alloc
    #undef Tcl_DbCkalloc

    argSpace = ckalloc(size * sizeof(char *)
    argSpace = (TCHAR *)ckalloc(size * sizeof(char *)
	    + (_tcslen(cmdLine) * sizeof(TCHAR)) + sizeof(TCHAR));
    argv = (TCHAR **) argSpace;
    argSpace += size * (sizeof(char *)/sizeof(TCHAR));
    size--;

    p = cmdLine;
    for (argc = 0; argc < size; argc++) {
Changes to xlib/X11/X.h.
1
2
3
4
5
6
7
8
9
10
























11

12
13
14
15
16
17
18
19
20

21
22
23
24
25
26
27
28
29
30
31
32

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50


51

52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

67
68
69
70
71
72
73
74
75
76
77

78
79
80
81
82
83
84
85




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

31

32
33
34
35
36
37
38

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55





56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83

84
85
86
87
88
89
90
91
92
93


94

95
96
97
98
99
100
101
-
-
-
-






+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-







-
+












+



-
-
-
-
-










+
+

+














-
+









-
-
+
-







/*
 *	$XConsortium: X.h,v 1.66 88/09/06 15:55:56 jim Exp $
 */

/* Definitions for the X window system likely to be used by applications */

#ifndef X_H
#define X_H

/***********************************************************

Copyright 1987, 1998  The Open Group

Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.


Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
and the Massachusetts Institute of Technology, Cambridge, Massachusetts.

                        All Rights Reserved

Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the names of Digital or MIT not be
supporting documentation, and that the name of Digital not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.

DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.

******************************************************************/

#define X_PROTOCOL	11		/* current protocol version */
#define X_PROTOCOL_REVISION 0		/* current minor version */

#if defined(MAC_OSX_TK)
#   define Cursor XCursor
#   define Region XRegion
#endif

/* Resources */

#ifdef _WIN64
typedef unsigned __int64 XID;
#else
typedef unsigned long XID;
#endif

typedef XID Window;
typedef XID Drawable;
#ifndef _XTYPEDEF_FONT
#  define _XTYPEDEF_FONT
typedef XID Font;
#endif
typedef XID Pixmap;
typedef XID Cursor;
typedef XID Colormap;
typedef XID GContext;
typedef XID KeySym;

typedef unsigned long Mask;

typedef unsigned long Atom;

typedef unsigned long VisualID;

typedef unsigned long Time;

typedef unsigned long KeyCode;	/* In order to use IME, the Macintosh needs
typedef unsigned int KeyCode;	/* In order to use IME, the Macintosh needs
				 * to pack 3 bytes into the keyCode field in
				 * the XEvent.  In the real X.h, a KeyCode is
				 * defined as a short, which wouldn't be big
				 * enough. */

/*****************************************************************
 * RESERVED RESOURCE AND CONSTANT DEFINITIONS
 *****************************************************************/

#ifndef _WIN32
#   define None              0L      /* See bug [9e31fd9449] and below */
/* #define None              0L      See bug [9e31fd9449] and below */
#endif

#define ParentRelative       1L	/* background pixmap in CreateWindow
				    and ChangeWindowAttributes */

#define CopyFromParent       0L	/* border pixmap in CreateWindow
				       and ChangeWindowAttributes
				   special VisualID and special window
169
170
171
172
173
174
175

176

177
178
179
180
181
182
183
184
185

186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
185
186
187
188
189
190
191
192

193
194
195
196
197
198
199
200


201

202
203
204
205
206
207
208

209

210
211
212
213
214
215
216







+
-
+







-
-
+
-







-

-







#define PropertyNotify		28
#define SelectionClear		29
#define SelectionRequest	30
#define SelectionNotify		31
#define ColormapNotify		32
#define ClientMessage		33
#define MappingNotify		34
#define GenericEvent		35
#define LASTEvent		35	/* must be bigger than any event # */
#define LASTEvent		36	/* must be bigger than any event # */


/* Key masks. Used as modifiers to GrabButton and GrabKey, results of QueryPointer,
   state in various key-, mouse-, and button-related events. */

#define ShiftMask		(1<<0)
#define LockMask		(1<<1)
#ifndef _WIN32
#   define ControlMask		(1<<2) /* See bug [9e31fd9449] and below */
/* #define ControlMask		(1<<2) See bug [9e31fd9449] and below */
#endif
#define Mod1Mask		(1<<3)
#define Mod2Mask		(1<<4)
#define Mod3Mask		(1<<5)
#define Mod4Mask		(1<<6)
#define Mod5Mask		(1<<7)

/* See bug [9e31fd9449], this way prevents conflicts with Win32 headers */
#ifdef _WIN32
enum _Bug9e31fd9449 { None = 0, ControlMask = (1<<2) };
#endif

/* modifier names.  Used to build a SetModifierMapping request or
   to read a GetModifierMapping request.  These correspond to the
   masks defined above. */
#define ShiftMapIndex		0
#define LockMapIndex		1
#define ControlMapIndex		2
259
260
261
262
263
264
265
266

267
268




269
270
271
272
273
274
275
272
273
274
275
276
277
278

279
280
281
282
283
284
285
286
287
288
289
290
291
292







-
+


+
+
+
+







/* Circulation request */

#define PlaceOnTop		0
#define PlaceOnBottom		1

/* protocol families */

#define FamilyInternet		0
#define FamilyInternet		0	/* IPv4 */
#define FamilyDECnet		1
#define FamilyChaos		2
#define FamilyInternet6		6	/* IPv6 */

/* authentication families not tied to a specific protocol */
#define FamilyServerInterpreted 5

/* Property notification */

#define PropertyNewValue	0
#define PropertyDelete		1

/* Color Map notification */
674
675
676
677
678
679
680
681
682
683
684
685
686
691
692
693
694
695
696
697





698







-
-
-
-
-



/* Byte order  used in imageByteOrder and bitmapBitOrder */

#define LSBFirst		0
#define MSBFirst		1

#if defined(MAC_OSX_TK)
#   undef Cursor
#   undef Region
#endif

#endif /* X_H */
Changes to xlib/X11/Xfuncproto.h.
1
2

3
4
5
6
7
8
9
10
11
12
13





















14
15
16
17
18
19
20
21
22
23
24
25
26
27

28
29
30
31
32
33
34
35
36
37
38









39
40
41
42
43
44
45
46
47
48
49

50
51


52
53

54
55
56
57

58














































































































































59
60

1
2











3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69


70
71
72

73


74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
-

+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+













-
+











+
+
+
+
+
+
+
+
+











+
-
-
+
+

-
+
-
-


+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


/* $XConsortium: Xfuncproto.h,v 1.7 91/05/13 20:49:21 rws Exp $ */
/*
 *
 * Copyright 1989, 1991 by the Massachusetts Institute of Technology
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee is hereby granted, provided
 * that the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation, and that the name of M.I.T. not be used in advertising
 * or publicity pertaining to distribution of the software without specific,
 * written prior permission. M.I.T. makes no representations about the
 * suitability of this software for any purpose.  It is provided "as is"
 * without express or implied warranty.
Copyright 1989, 1991, 1998  The Open Group

Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
 *
 */

/* Definitions to make function prototypes manageable */

#ifndef _XFUNCPROTO_H_
#define _XFUNCPROTO_H_

#ifndef NeedFunctionPrototypes
#define NeedFunctionPrototypes 1
#endif /* NeedFunctionPrototypes */

#ifndef NeedVarargsPrototypes
#define NeedVarargsPrototypes 0
#define NeedVarargsPrototypes 1
#endif /* NeedVarargsPrototypes */

#if NeedFunctionPrototypes

#ifndef NeedNestedPrototypes
#define NeedNestedPrototypes 1
#endif /* NeedNestedPrototypes */

#ifndef _Xconst
#define _Xconst const
#endif /* _Xconst */

/* Function prototype configuration (see configure for more info) */
#if !defined(NARROWPROTO) && \
    (defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__))
#define NARROWPROTO
#endif
#ifndef FUNCPROTO
#define FUNCPROTO 15
#endif

#ifndef NeedWidePrototypes
#ifdef NARROWPROTO
#define NeedWidePrototypes 0
#else
#define NeedWidePrototypes 1		/* default to make interropt. easier */
#endif
#endif /* NeedWidePrototypes */

#endif /* NeedFunctionPrototypes */

#ifndef _XFUNCPROTOBEGIN
#ifdef __cplusplus
#define _XFUNCPROTOBEGIN extern "C" {
#if defined(__cplusplus) || defined(c_plusplus) /* for C++ V2.0 */
#define _XFUNCPROTOBEGIN extern "C" {	/* do not leave open across includes */
#define _XFUNCPROTOEND }
#endif
#else

#ifndef _XFUNCPROTOBEGIN
#define _XFUNCPROTOBEGIN
#define _XFUNCPROTOEND
#endif
#endif /* _XFUNCPROTOBEGIN */

/* http://clang.llvm.org/docs/LanguageExtensions.html#has-attribute */
#ifndef __has_attribute
# define __has_attribute(x) 0  /* Compatibility with non-clang compilers. */
#endif
#ifndef __has_feature
# define __has_feature(x) 0    /* Compatibility with non-clang compilers. */
#endif
#ifndef __has_extension
# define __has_extension(x) 0  /* Compatibility with non-clang compilers. */
#endif

/* Added in X11R6.9, so available in any version of modular xproto */
#if __has_attribute(__sentinel__) || (defined(__GNUC__) && (__GNUC__ >= 4))
# define _X_SENTINEL(x) __attribute__ ((__sentinel__(x)))
#else
# define _X_SENTINEL(x)
#endif /* GNUC >= 4 */

/* Added in X11R6.9, so available in any version of modular xproto */
#if (__has_attribute(visibility) || (defined(__GNUC__) && (__GNUC__ >= 4))) \
    && !defined(__CYGWIN__) && !defined(__MINGW32__)
# define _X_EXPORT      __attribute__((visibility("default")))
# define _X_HIDDEN      __attribute__((visibility("hidden")))
# define _X_INTERNAL    __attribute__((visibility("internal")))
#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550)
# define _X_EXPORT      __global
# define _X_HIDDEN      __hidden
# define _X_INTERNAL    __hidden
#else /* not gcc >= 4 and not Sun Studio >= 8 */
# define _X_EXPORT
# define _X_HIDDEN
# define _X_INTERNAL
#endif /* GNUC >= 4 */

/* Branch prediction hints for individual conditionals */
/* requires xproto >= 7.0.9 */
#if defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 303)
# define _X_LIKELY(x)   __builtin_expect(!!(x), 1)
# define _X_UNLIKELY(x) __builtin_expect(!!(x), 0)
#else /* not gcc >= 3.3 */
# define _X_LIKELY(x)   (x)
# define _X_UNLIKELY(x) (x)
#endif

/* Bulk branch prediction hints via marking error path functions as "cold" */
/* requires xproto >= 7.0.25 */
#if __has_attribute(__cold__) || \
    (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 403)) /* 4.3+ */
# define _X_COLD __attribute__((__cold__))
#else
# define _X_COLD /* nothing */
#endif

/* Added in X11R6.9, so available in any version of modular xproto */
#if __has_attribute(deprecated) \
    || (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 301)) \
    || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x5130))
# define _X_DEPRECATED  __attribute__((deprecated))
#else /* not gcc >= 3.1 */
# define _X_DEPRECATED
#endif

/* requires xproto >= 7.0.30 */
#if __has_extension(attribute_deprecated_with_message) || \
                (defined(__GNUC__) && ((__GNUC__ >= 5) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5))))
# define _X_DEPRECATED_MSG(_msg) __attribute__((deprecated(_msg)))
#else
# define _X_DEPRECATED_MSG(_msg) _X_DEPRECATED
#endif

/* requires xproto >= 7.0.17 */
#if __has_attribute(noreturn) \
    || (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 205)) \
    || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590))
# define _X_NORETURN __attribute((noreturn))
#else
# define _X_NORETURN
#endif /* GNUC  */

/* Added in X11R6.9, so available in any version of modular xproto */
#if __has_attribute(__format__) \
    || defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 203)
# define _X_ATTRIBUTE_PRINTF(x,y) __attribute__((__format__(__printf__,x,y)))
#else /* not gcc >= 2.3 */
# define _X_ATTRIBUTE_PRINTF(x,y)
#endif

/* requires xproto >= 7.0.22 - since this uses either gcc or C99 variable
   argument macros, must be only used inside #ifdef _X_NONNULL guards, as
   many legacy X clients are compiled in C89 mode still. */
#if __has_attribute(nonnull) \
    && defined(__STDC_VERSION__) && (__STDC_VERSION__ - 0 >= 199901L) /* C99 */
#define _X_NONNULL(...)  __attribute__((nonnull(__VA_ARGS__)))
#elif __has_attribute(nonnull) \
    || defined(__GNUC__) &&  ((__GNUC__ * 100 + __GNUC_MINOR__) >= 303)
#define _X_NONNULL(args...)  __attribute__((nonnull(args)))
#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ - 0 >= 199901L) /* C99 */
#define _X_NONNULL(...)  /* */
#endif

/* requires xproto >= 7.0.22 */
#if __has_attribute(__unused__) \
    || defined(__GNUC__) &&  ((__GNUC__ * 100 + __GNUC_MINOR__) >= 205)
#define _X_UNUSED  __attribute__((__unused__))
#else
#define _X_UNUSED  /* */
#endif

/* C99 keyword "inline" or equivalent extensions in pre-C99 compilers */
/* requires xproto >= 7.0.9
   (introduced in 7.0.8 but didn't support all compilers until 7.0.9) */
#if defined(inline) /* assume autoconf set it correctly */ || \
   (defined(__STDC_VERSION__) && (__STDC_VERSION__ - 0 >= 199901L)) /* C99 */ || \
   (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550))
# define _X_INLINE inline
#elif defined(__GNUC__) && !defined(__STRICT_ANSI__) /* gcc w/C89+extensions */
# define _X_INLINE __inline__
#else
# define _X_INLINE
#endif

/* C99 keyword "restrict" or equivalent extensions in pre-C99 compilers */
/* requires xproto >= 7.0.21 */
#ifndef _X_RESTRICT_KYWD
# if defined(restrict) /* assume autoconf set it correctly */ || \
    (defined(__STDC_VERSION__) && (__STDC_VERSION__ - 0 >= 199901L) /* C99 */ \
     && !defined(__cplusplus)) /* Workaround g++ issue on Solaris */
#  define _X_RESTRICT_KYWD  restrict
# elif defined(__GNUC__) && !defined(__STRICT_ANSI__) /* gcc w/C89+extensions */
#  define _X_RESTRICT_KYWD __restrict__
# else
#  define _X_RESTRICT_KYWD
# endif
#endif

/* requires xproto >= 7.0.30 */
#if __has_attribute(no_sanitize_thread)
# define _X_NOTSAN __attribute__((no_sanitize_thread))
#else
# define _X_NOTSAN
#endif

#endif /* _XFUNCPROTO_H_ */
Changes to xlib/X11/Xlib.h.
1
2

3
4
5
6
7
8
9
10
11









12
13
14
15
16
17














18
19
20
21
22
23
24
25
26


27
28

29

30
31



32
33
34


35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50



51
52
53

































54
55
56
57
58
59
60

1
2









3
4
5
6
7
8
9
10
11






12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32


33
34
35

36
37
38


39
40
41
42


43
44



45
46
47
48






49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
-

+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+







-
-
+
+

-
+

+
-
-
+
+
+

-
-
+
+
-
-
-




-
-
-
-
-
-



+
+
+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







/* $XConsortium: Xlib.h,v 11.221 93/07/02 14:13:28 gildea Exp $ */
/*

 * Copyright 1985, 1986, 1987, 1991 by the Massachusetts Institute of Technology
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee is hereby granted, provided
 * that the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation, and that the name of M.I.T. not be used in advertising
 * or publicity pertaining to distribution of the software without specific,
 * written prior permission. M.I.T. makes no representations about the
Copyright 1985, 1986, 1987, 1991, 1998  The Open Group

Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.

The above copyright notice and this permission notice shall be included in
 * suitability of this software for any purpose.  It is provided "as is"
 * without express or implied warranty.
 *
 * X Window System is a Trademark of MIT.
 *
 */
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.

*/


/*
 *	Xlib.h - Header definition and support file for the C subroutine
 *	interface library (Xlib) to the X Window System Protocol (V11).
 *	Structures and symbols starting with "_" are private to the library.
 */
#ifndef _XLIB_H_
#define _XLIB_H_
#ifndef _X11_XLIB_H_
#define _X11_XLIB_H_

#define XlibSpecificationRelease 5
#define XlibSpecificationRelease 6

#include <sys/types.h>
#if !defined(MAC_OSX_TK)
#   include <X11/X.h>

#if defined(__SCO__) || defined(__UNIXWARE__)
#include <stdint.h>
#endif
#ifdef MAC_OSX_TK
#   include <X11/X.h>

#include <X11/X.h>
#   define Cursor XCursor
#   define Region XRegion
#endif

/* applications should not depend on these two headers being included! */
#include <X11/Xfuncproto.h>

#ifndef X_WCHAR
#ifdef X_NOT_STDC_ENV
#define X_WCHAR
#endif
#endif

#ifndef X_WCHAR
#include <stddef.h>
#else
#ifdef __UNIXOS2__
#include <stdlib.h>
#else
/* replace this with #include or typedef appropriate for your system */
typedef unsigned long wchar_t;
#endif
#endif

#ifndef EXTERN
#   define EXTERN extern TCL_STORAGE_CLASS
#endif
#if defined(STATIC_BUILD) || !defined(_WIN32)
# ifndef TCL_STORAGE_CLASS
#   define TCL_STORAGE_CLASS
# endif
#elif defined(BUILD_tk)
# undef TCL_STORAGE_CLASS
# define TCL_STORAGE_CLASS __declspec(dllexport)
#elif !defined(TCL_STORAGE_CLASS)
# define TCL_STORAGE_CLASS __declspec(dllimport)
#endif

EXTERN int
_Xmblen(
    char *str,
    int len
    );

/* API mentioning "UTF8" or "utf8" is an XFree86 extension, introduced in
   November 2000. Its presence is indicated through the following macro. */
#define X_HAVE_UTF8_STRING 1

/* The Xlib structs are full of implicit padding to properly align members.
   We can't clean that up without breaking ABI, so tell clang not to bother
   complaining about it. */
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wpadded"
#endif

typedef char *XPointer;

#define Bool int
#if defined(MAC_OSX_TK)
/* Use define rather than typedef, since may need to undefine this later */
#define Status int
124
125
126
127
128
129
130
131



132
133
134
135
136
137
138
161
162
163
164
165
166
167

168
169
170
171
172
173
174
175
176
177







-
+
+
+








/*
 * Extensions need a way to hang private data on some structures.
 */
typedef struct _XExtData {
	int number;		/* number returned by XRegisterExtension */
	struct _XExtData *next;	/* next item on list of data for structure */
	int (*free_private)();	/* called to free private storage */
	int (*free_private)(	/* called to free private storage */
	struct _XExtData *extension
	);
	XPointer private_data;	/* data private to this extension. */
} XExtData;

/*
 * This file contains structures used by the extension mechanism.
 */
typedef struct {		/* public to extension, cannot be changed */
217
218
219
220
221
222
223



224
225
226
227
228
229
230
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272







+
+
+







} Depth;

/*
 * Information about the screen.  The contents of this structure are
 * implementation dependent.  A Screen should be treated as opaque
 * by application code.
 */

struct _XDisplay;		/* Forward declare before use for C++ */

typedef struct {
	XExtData *ext_data;	/* hook for extension to hang data */
	struct _XDisplay *display;/* back pointer to display structure */
	Window root;		/* Root window id. */
	int width, height;	/* width and height of screen */
	int mwidth, mheight;	/* width and height of  in millimeters */
	int ndepths;		/* number of depths possible */
307
308
309
310
311
312
313










314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338











339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384



385


386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401







402
403
404
405
406
407
408







+
+
+
+
+
+
+
+
+
+



















-
-
-

-
-
+
+
+
+
+
+
+
+
+
+
+





-
-
-
-
-
-
-








typedef struct {
	int family;		/* for example FamilyInternet */
	int length;		/* length of address, in bytes */
	char *address;		/* pointer to where to find the bytes */
} XHostAddress;

/*
 * Data structure for ServerFamilyInterpreted addresses in host routines
 */
typedef struct {
	int typelength;		/* length of type string, in bytes */
	int valuelength;	/* length of value string, in bytes */
	char *type;		/* pointer to where to find the type string */
	char *value;		/* pointer to where to find the address */
} XServerInterpretedAddress;

/*
 * Data structure for "image" data, used by image manipulation routines.
 */
typedef struct _XImage {
    int width, height;		/* size of image */
    int xoffset;		/* number of pixels offset in X direction */
    int format;			/* XYBitmap, XYPixmap, ZPixmap */
    char *data;			/* pointer to image data */
    int byte_order;		/* data byte order, LSBFirst, MSBFirst */
    int bitmap_unit;		/* quant. of scanline 8, 16, 32 */
    int bitmap_bit_order;	/* LSBFirst, MSBFirst */
    int bitmap_pad;		/* 8, 16, 32 either XY or ZPixmap */
    int depth;			/* depth of image */
    int bytes_per_line;		/* accelarator to next line */
    int bits_per_pixel;		/* bits per pixel (ZPixmap) */
    unsigned long red_mask;	/* bits in z arrangment */
    unsigned long green_mask;
    unsigned long blue_mask;
    XPointer obdata;		/* hook for the object routines to hang on */
#if defined(MAC_OSX_TK)
    int pixelpower;		/* n such that pixels are 2^n x 2^n blocks*/
#endif
    struct funcs {		/* image manipulation routines */
	struct _XImage *(*create_image)();
#if NeedFunctionPrototypes
	struct _XImage *(*create_image)(
		struct _XDisplay* /* display */,
		Visual*		/* visual */,
		unsigned int	/* depth */,
		int		/* format */,
		int		/* offset */,
		char*		/* data */,
		unsigned int	/* width */,
		unsigned int	/* height */,
		int		/* bitmap_pad */,
		int		/* bytes_per_line */);
	int (*destroy_image)        (struct _XImage *);
	unsigned long (*get_pixel)  (struct _XImage *, int, int);
	int (*put_pixel)            (struct _XImage *, int, int, unsigned long);
	struct _XImage *(*sub_image)(struct _XImage *, int, int, unsigned int, unsigned int);
	int (*add_pixel)            (struct _XImage *, long);
#else
	int (*destroy_image)();
	unsigned long (*get_pixel)();
	int (*put_pixel)();
	struct _XImage *(*sub_image)();
	int (*add_pixel)();
#endif
	} f;
} XImage;

/*
 * Data structure for XReconfigureWindow
 */
typedef struct {
439
440
441
442
443
444
445
446

447
448
449


450
451
452
453
454
455
456







457
458
459
460
461
462
463

464
465

466

467
468
469
470
471




472
473
474



475
476
477
478
479
480

481
482
483
484
485



486
487
488
489
490
491
492
493
494
495
496
497
498
499
500


501
502
503
504
505
506
507
508
509
510
511
512

513
514
515
516
517
518
519
520
521
522
523
524
525

526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544

545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565

566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583

584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600

601
602
603
604
605
606
607
490
491
492
493
494
495
496

497
498


499
500
501
502





503
504
505
506
507
508
509
510
511
512
513
514
515

516
517

518
519
520
521




522
523
524
525
526
527

528
529
530
531
532
533
534
535

536
537
538



539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554


555
556
557
558
559
560
561
562
563
564
565
566
567

568
569
570
571
572
573
574
575
576
577
578
579
580

581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599

600
601
602
603
604
605
606
607



608
609
610
611
612
613
614
615
616
617

618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635

636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652

653
654
655
656
657
658
659
660







-
+

-
-
+
+


-
-
-
-
-
+
+
+
+
+
+
+






-
+

-
+

+

-
-
-
-
+
+
+
+


-
+
+
+





-
+


-
-
-
+
+
+













-
-
+
+











-
+












-
+


















-
+







-
-
-










-
+

















-
+
















-
+







/*
 * Display datatype maintaining display specific data.
 * The contents of this structure are implementation dependent.
 * A Display should be treated as opaque by application code.
 */
typedef struct _XDisplay {
	XExtData *ext_data;	/* hook for extension to hang data */
	struct _XFreeFuncs *free_funcs; /* internal free functions */
	struct _XPrivate *private1;
	int fd;			/* Network socket. */
	int conn_checker;         /* ugly thing used by _XEventsQueued */
	int proto_major_version;/* maj. version of server's X protocol */
	int private2;
	int proto_major_version;/* major version of server's X protocol */
	int proto_minor_version;/* minor version of servers X protocol */
	char *vendor;		/* vendor of the server hardware */
        XID resource_base;	/* resource ID base */
	XID resource_mask;	/* resource ID mask bits */
	XID resource_id;	/* allocator current ID */
	int resource_shift;	/* allocator shift to correct bits */
	XID (*resource_alloc)(); /* allocator function */
        XID private3;
	XID private4;
	XID private5;
	int private6;
	XID (*resource_alloc)(	/* allocator function */
		struct _XDisplay*
	);
	int byte_order;		/* screen byte order, LSBFirst, MSBFirst */
	int bitmap_unit;	/* padding and data requirements */
	int bitmap_pad;		/* padding requirements on bitmaps */
	int bitmap_bit_order;	/* LeastSignificant or MostSignificant */
	int nformats;		/* number of pixmap formats in list */
	ScreenFormat *pixmap_format;	/* pixmap format list */
	int vnumber;		/* Xlib's X protocol version number. */
	int private8;
	int release;		/* release of the server */
	struct _XSQEvent *head, *tail;	/* Input event queue. */
	struct _XPrivate *private9, *private10;
	int qlen;		/* Length of input event queue */
	unsigned long last_request_read; /* seq number of last event read */
	unsigned long request;	/* sequence number of last request. */
	char *last_req;		/* beginning of last request, or dummy */
	char *buffer;		/* Output buffer starting address. */
	char *bufptr;		/* Output buffer index pointer. */
	char *bufmax;		/* Output buffer maximum+1 address. */
	XPointer private11;
	XPointer private12;
	XPointer private13;
	XPointer private14;
	unsigned max_request_size; /* maximum number 32 bit words in request*/
	struct _XrmHashBucketRec *db;
	int (*synchandler)();	/* Synchronization handler */
	int (*private15)(
		struct _XDisplay*
		);
	char *display_name;	/* "host:display" string used on this connect*/
	int default_screen;	/* default screen for operations */
	int nscreens;		/* number of screens on this server*/
	Screen *screens;	/* pointer to list of screens */
	unsigned long motion_buffer;	/* size of motion buffer */
	unsigned long flags;	/* internal connection flags */
	unsigned long private16;
	int min_keycode;	/* minimum defined keycode */
	int max_keycode;	/* maximum defined keycode */
	KeySym *keysyms;	/* This server's keysyms */
	XModifierKeymap *modifiermap;	/* This server's modifier keymap */
	int keysyms_per_keycode;/* number of rows */
	XPointer private17;
	XPointer private18;
	int private19;
	char *xdefaults;	/* contents of defaults from server */
	char *scratch_buffer;	/* place to hang scratch buffer */
	unsigned long scratch_length;	/* length of scratch buffer */
	int ext_number;		/* extension number on this display */
	struct _XExten *ext_procs; /* extensions initialized on this display */
	/*
	 * the following can be fixed size, as the protocol defines how
	 * much address space is available.
	 * While this could be done using the extension vector, there
	 * may be MANY events processed, so a search through the extension
	 * list to find the right procedure for each event might be
	 * expensive if many extensions are being used.
	 */
	Bool (*event_vec[128])();  /* vector for wire to event */
	Status (*wire_vec[128])(); /* vector for event to wire */
	Bool (*event_vec[128])(void);  /* vector for wire to event */
	Status (*wire_vec[128])(void); /* vector for event to wire */
	KeySym lock_meaning;	   /* for XLookupString */
	struct _XLockInfo *lock;   /* multi-thread state, display lock */
	struct _XInternalAsync *async_handlers; /* for internal async */
	unsigned long bigreq_size; /* max size of big requests */
	struct _XLockPtrs *lock_fns; /* pointers to threads functions */
	/* things above this line should not move, for binary compatibility */
	struct _XKeytrans *key_bindings; /* for XLookupString */
	Font cursor_font;	   /* for XCreateFontCursor */
	struct _XDisplayAtoms *atoms; /* for XInternAtom */
	unsigned int mode_switch;  /* keyboard group modifiers */
	struct _XContextDB *context_db; /* context database */
	Bool (**error_vec)();      /* vector for wire to error */
	Bool (**error_vec)(void);      /* vector for wire to error */
	/*
	 * Xcms information
	 */
	struct {
	   XPointer defaultCCCs;  /* pointer to an array of default XcmsCCC */
	   XPointer clientCmaps;  /* pointer to linked list of XcmsCmapRec */
	   XPointer perVisualIntensityMaps;
				  /* linked list of XcmsIntensityMap */
	} cms;
	struct _XIMFilter *im_filters;
	struct _XSQEvent *qfree; /* unallocated event queue elements */
	unsigned long next_event_serial_num; /* inserted into next queue elt */
	int (*savedsynchandler)(); /* user synchandler when Xlib usurps */
	int (*savedsynchandler)(void); /* user synchandler when Xlib usurps */
} Display;

#if NeedFunctionPrototypes	/* prototypes require event type definitions */
#undef _XEVENT_
#endif
#ifndef _XEVENT_

#define XMaxTransChars 7

/*
 * Definitions of specific events.
 */
typedef struct {
	int type;		/* of event */
	unsigned long serial;	/* # of last request processed by server */
	Bool send_event;	/* true if this came from a SendEvent request */
	Display *display;	/* Display the event was read from */
	Window window;	        /* "event" window it is reported relative to */
	Window root;	        /* root window that the event occured on */
	Window root;	        /* root window that the event occurred on */
	Window subwindow;	/* child window */
	Time time;		/* milliseconds */
	int x, y;		/* pointer x, y coordinates in event window */
	int x_root, y_root;	/* coordinates relative to root */
	unsigned int state;	/* key or button mask */
	unsigned int keycode;	/* detail */
	Bool same_screen;	/* same screen flag */
	char trans_chars[XMaxTransChars];
				/* translated characters */
	unsigned char nbytes;
} XKeyEvent;
typedef XKeyEvent XKeyPressedEvent;
typedef XKeyEvent XKeyReleasedEvent;

typedef struct {
	int type;		/* of event */
	unsigned long serial;	/* # of last request processed by server */
	Bool send_event;	/* true if this came from a SendEvent request */
	Display *display;	/* Display the event was read from */
	Window window;	        /* "event" window it is reported relative to */
	Window root;	        /* root window that the event occured on */
	Window root;	        /* root window that the event occurred on */
	Window subwindow;	/* child window */
	Time time;		/* milliseconds */
	int x, y;		/* pointer x, y coordinates in event window */
	int x_root, y_root;	/* coordinates relative to root */
	unsigned int state;	/* key or button mask */
	unsigned int button;	/* detail */
	Bool same_screen;	/* same screen flag */
} XButtonEvent;
typedef XButtonEvent XButtonPressedEvent;
typedef XButtonEvent XButtonReleasedEvent;

typedef struct {
	int type;		/* of event */
	unsigned long serial;	/* # of last request processed by server */
	Bool send_event;	/* true if this came from a SendEvent request */
	Display *display;	/* Display the event was read from */
	Window window;	        /* "event" window reported relative to */
	Window root;	        /* root window that the event occured on */
	Window root;	        /* root window that the event occurred on */
	Window subwindow;	/* child window */
	Time time;		/* milliseconds */
	int x, y;		/* pointer x, y coordinates in event window */
	int x_root, y_root;	/* coordinates relative to root */
	unsigned int state;	/* key or button mask */
	char is_hint;		/* detail */
	Bool same_screen;	/* same screen flag */
} XMotionEvent;
typedef XMotionEvent XPointerMovedEvent;

typedef struct {
	int type;		/* of event */
	unsigned long serial;	/* # of last request processed by server */
	Bool send_event;	/* true if this came from a SendEvent request */
	Display *display;	/* Display the event was read from */
	Window window;	        /* "event" window reported relative to */
	Window root;	        /* root window that the event occured on */
	Window root;	        /* root window that the event occurred on */
	Window subwindow;	/* child window */
	Time time;		/* milliseconds */
	int x, y;		/* pointer x, y coordinates in event window */
	int x_root, y_root;	/* coordinates relative to root */
	int mode;		/* NotifyNormal, NotifyGrab, NotifyUngrab */
	int detail;
	/*
617
618
619
620
621
622
623
624


625
626
627
628
629
630
631
670
671
672
673
674
675
676

677
678
679
680
681
682
683
684
685







-
+
+








typedef struct {
	int type;		/* FocusIn or FocusOut */
	unsigned long serial;	/* # of last request processed by server */
	Bool send_event;	/* true if this came from a SendEvent request */
	Display *display;	/* Display the event was read from */
	Window window;		/* window of event */
	int mode;		/* NotifyNormal, NotifyGrab, NotifyUngrab */
	int mode;		/* NotifyNormal, NotifyWhileGrabbed,
				   NotifyGrab, NotifyUngrab */
	int detail;
	/*
	 * NotifyAncestor, NotifyVirtual, NotifyInferior,
	 * NotifyNonlinear,NotifyNonlinearVirtual, NotifyPointer,
	 * NotifyPointerRoot, NotifyDetailNone
	 */
} XFocusChangeEvent;
918
919
920
921
922
923
924



























925
926
927
928
929
930
931
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	int type;
	unsigned long serial;	/* # of last request processed by server */
	Bool send_event;	/* true if this came from a SendEvent request */
	Display *display;/* Display the event was read from */
	Window window;	/* window on which event was requested in event mask */
} XAnyEvent;


/***************************************************************
 *
 * GenericEvent.  This event is the standard event for all newer extensions.
 */

typedef struct
    {
    int            type;         /* of event. Always GenericEvent */
    unsigned long  serial;       /* # of last request processed */
    Bool           send_event;   /* true if from SendEvent request */
    Display        *display;     /* Display the event was read from */
    int            extension;    /* major opcode of extension that caused the event */
    int            evtype;       /* actual event type. */
    } XGenericEvent;

typedef struct {
    int            type;         /* of event. Always GenericEvent */
    unsigned long  serial;       /* # of last request processed */
    Bool           send_event;   /* true if from SendEvent request */
    Display        *display;     /* Display the event was read from */
    int            extension;    /* major opcode of extension that caused the event */
    int            evtype;       /* actual event type. */
    unsigned int   cookie;
    void           *data;
} XGenericEventCookie;

/*
 * this union is defined so Xlib can always use the same sized
 * event structure internally, to avoid memory fragmentation.
 */
typedef union _XEvent {
        int type;		/* must not be changed; first element */
	XAnyEvent xany;
955
956
957
958
959
960
961


962
963
964
965
966
967
968
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051







+
+







	XSelectionRequestEvent xselectionrequest;
	XSelectionEvent xselection;
	XColormapEvent xcolormap;
	XClientMessageEvent xclient;
	XMappingEvent xmapping;
	XErrorEvent xerror;
	XKeymapEvent xkeymap;
	XGenericEvent xgeneric;
	XGenericEventCookie xcookie;
	XID pad[24];
} XEvent;
#endif

#define XAllocID(dpy) ((*(dpy)->resource_alloc)((dpy)))

/*
1036
1037
1038
1039
1040
1041
1042




1043


1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
















1059







1060











1061
1062


















1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081

1082
1083
1084
1085
1086
1087

1088
1089
1090
1091
1092

1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109












1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125





1126
1127
1128
1129
1130
1131
1132
1133
1134









1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
























1146
1147
1148
1149
1150
1151























1152
1153
1154
1155
1156
1157
1158
1159
1160
1161















1162
1163
1164
1165
1166
1167
1168
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129

1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162

1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269

1270



1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283






1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327






1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382







+
+
+
+
-
+
+















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



















+






+





+

















+
+
+
+
+
+
+
+
+
+
+
+






-

-
-
-





+
+
+
+
+



-
-
-
-
-
-
+
+
+
+
+
+
+
+
+











+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+










+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







		XFontStruct *font; } XEDataObject;

typedef struct {
    XRectangle      max_ink_extent;
    XRectangle      max_logical_extent;
} XFontSetExtents;

/* unused:
typedef void (*XOMProc)();
 */

typedef struct _XFontSet *XFontSet;
typedef struct _XOM *XOM;
typedef struct _XOC *XOC, *XFontSet;

typedef struct {
    char           *chars;
    int             nchars;
    int             delta;
    XFontSet        font_set;
} XmbTextItem;

typedef struct {
    wchar_t        *chars;
    int             nchars;
    int             delta;
    XFontSet        font_set;
} XwcTextItem;

#define XNRequiredCharSet "requiredCharSet"
#define XNQueryOrientation "queryOrientation"
#define XNBaseFontName "baseFontName"
#define XNOMAutomatic "omAutomatic"
#define XNMissingCharSet "missingCharSet"
#define XNDefaultString "defaultString"
#define XNOrientation "orientation"
#define XNDirectionalDependentDrawing "directionalDependentDrawing"
#define XNContextualDrawing "contextualDrawing"
#define XNFontInfo "fontInfo"

typedef struct {
    int charset_count;
    char **charset_list;
} XOMCharSetList;

typedef void (*XIMProc)();
typedef enum {
    XOMOrientation_LTR_TTB,
    XOMOrientation_RTL_TTB,
    XOMOrientation_TTB_LTR,
    XOMOrientation_TTB_RTL,
    XOMOrientation_Context
} XOrientation;

typedef struct {
    int num_orientation;
    XOrientation *orientation;	/* Input Text description */
} XOMOrientation;

typedef struct {
    int num_font;
    XFontStruct **font_struct_list;
    char **font_name_list;
} XOMFontInfo;

typedef struct _XIM *XIM;
typedef struct _XIC *XIC;

typedef void (*XIMProc)(
    XIM,
    XPointer,
    XPointer
);

typedef Bool (*XICProc)(
    XIC,
    XPointer,
    XPointer
);

typedef void (*XIDProc)(
    Display*,
    XPointer,
    XPointer
);

typedef unsigned long XIMStyle;

typedef struct {
    unsigned short count_styles;
    XIMStyle *supported_styles;
} XIMStyles;

#define XIMPreeditArea		0x0001L
#define XIMPreeditCallbacks	0x0002L
#define XIMPreeditPosition	0x0004L
#define XIMPreeditNothing	0x0008L
#define XIMPreeditNone		0x0010L
#define XIMStatusArea		0x0100L
#define XIMStatusCallbacks	0x0200L
#define XIMStatusNothing	0x0400L
#define XIMStatusNone		0x0800L

#define XNVaNestedList "XNVaNestedList"
#define XNQueryInputStyle "queryInputStyle"
#define XNClientWindow "clientWindow"
#define XNInputStyle "inputStyle"
#define XNFocusWindow "focusWindow"
#define XNResourceName "resourceName"
#define XNResourceClass "resourceClass"
#define XNGeometryCallback "geometryCallback"
#define XNDestroyCallback "destroyCallback"
#define XNFilterEvents "filterEvents"
#define XNPreeditStartCallback "preeditStartCallback"
#define XNPreeditDoneCallback "preeditDoneCallback"
#define XNPreeditDrawCallback "preeditDrawCallback"
#define XNPreeditCaretCallback "preeditCaretCallback"
#define XNPreeditStateNotifyCallback "preeditStateNotifyCallback"
#define XNPreeditAttributes "preeditAttributes"
#define XNStatusStartCallback "statusStartCallback"
#define XNStatusDoneCallback "statusDoneCallback"
#define XNStatusDrawCallback "statusDrawCallback"
#define XNStatusAttributes "statusAttributes"
#define XNArea "area"
#define XNAreaNeeded "areaNeeded"
#define XNSpotLocation "spotLocation"
#define XNColormap "colorMap"
#define XNStdColormap "stdColorMap"
#define XNForeground "foreground"
#define XNBackground "background"
#define XNBackgroundPixmap "backgroundPixmap"
#define XNFontSet "fontSet"
#define XNLineSpace "lineSpace"
#define XNCursor "cursor"

#define XNQueryIMValuesList "queryIMValuesList"
#define XNQueryICValuesList "queryICValuesList"
#define XNVisiblePosition "visiblePosition"
#define XNR6PreeditCallback "r6PreeditCallback"
#define XNStringConversionCallback "stringConversionCallback"
#define XNStringConversion "stringConversion"
#define XNResetState "resetState"
#define XNHotKey "hotKey"
#define XNHotKeyState "hotKeyState"
#define XNPreeditState "preeditState"
#define XNSeparatorofNestedList "separatorofNestedList"

#define XBufferOverflow		-1
#define XLookupNone		1
#define XLookupChars		2
#define XLookupKeySym		3
#define XLookupBoth		4

#if NeedFunctionPrototypes
typedef void *XVaNestedList;
#else
typedef XPointer XVaNestedList;
#endif

typedef struct {
    XPointer client_data;
    XIMProc callback;
} XIMCallback;

typedef struct {
    XPointer client_data;
    XICProc callback;
} XICCallback;

typedef unsigned long XIMFeedback;

#define XIMReverse	1
#define XIMUnderline	(1<<1)
#define XIMHighlight	(1<<2)
#define XIMPrimary 	(1<<5)
#define XIMSecondary	(1<<6)
#define XIMTertiary 	(1<<7)
#define XIMReverse		1L
#define XIMUnderline		(1L<<1)
#define XIMHighlight		(1L<<2)
#define XIMPrimary	 	(1L<<5)
#define XIMSecondary		(1L<<6)
#define XIMTertiary	 	(1L<<7)
#define XIMVisibleToForward 	(1L<<8)
#define XIMVisibleToBackword 	(1L<<9)
#define XIMVisibleToCenter 	(1L<<10)

typedef struct _XIMText {
    unsigned short length;
    XIMFeedback *feedback;
    Bool encoding_is_wchar;
    union {
	char *multi_byte;
	wchar_t *wide_char;
    } string;
} XIMText;

typedef	unsigned long	 XIMPreeditState;

#define	XIMPreeditUnKnown	0L
#define	XIMPreeditEnable	1L
#define	XIMPreeditDisable	(1L<<1)

typedef	struct	_XIMPreeditStateNotifyCallbackStruct {
    XIMPreeditState state;
} XIMPreeditStateNotifyCallbackStruct;

typedef	unsigned long	 XIMResetState;

#define	XIMInitialState		1L
#define	XIMPreserveState	(1L<<1)

typedef unsigned long XIMStringConversionFeedback;

#define	XIMStringConversionLeftEdge	(0x00000001)
#define	XIMStringConversionRightEdge	(0x00000002)
#define	XIMStringConversionTopEdge	(0x00000004)
#define	XIMStringConversionBottomEdge	(0x00000008)
#define	XIMStringConversionConcealed	(0x00000010)
#define	XIMStringConversionWrapped	(0x00000020)

typedef struct _XIMPreeditDrawCallbackStruct {
    int caret;		/* Cursor offset within pre-edit string */
    int chg_first;	/* Starting change position */
    int chg_length;	/* Length of the change in character count */
    XIMText *text;
} XIMPreeditDrawCallbackStruct;
typedef struct _XIMStringConversionText {
    unsigned short length;
    XIMStringConversionFeedback *feedback;
    Bool encoding_is_wchar;
    union {
	char *mbs;
	wchar_t *wcs;
    } string;
} XIMStringConversionText;

typedef	unsigned short	XIMStringConversionPosition;

typedef	unsigned short	XIMStringConversionType;

#define	XIMStringConversionBuffer	(0x0001)
#define	XIMStringConversionLine		(0x0002)
#define	XIMStringConversionWord		(0x0003)
#define	XIMStringConversionChar		(0x0004)

typedef	unsigned short	XIMStringConversionOperation;

#define	XIMStringConversionSubstitution	(0x0001)
#define	XIMStringConversionRetrieval	(0x0002)

typedef enum {
    XIMForwardChar, XIMBackwardChar,
    XIMForwardWord, XIMBackwardWord,
    XIMCaretUp, XIMCaretDown,
    XIMNextLine, XIMPreviousLine,
    XIMLineStart, XIMLineEnd,
    XIMAbsolutePosition,
    XIMDontChange
} XIMCaretDirection;

typedef struct _XIMStringConversionCallbackStruct {
    XIMStringConversionPosition position;
    XIMCaretDirection direction;
    XIMStringConversionOperation operation;
    unsigned short factor;
    XIMStringConversionText *text;
} XIMStringConversionCallbackStruct;

typedef struct _XIMPreeditDrawCallbackStruct {
    int caret;		/* Cursor offset within pre-edit string */
    int chg_first;	/* Starting change position */
    int chg_length;	/* Length of the change in character count */
    XIMText *text;
} XIMPreeditDrawCallbackStruct;

typedef enum {
    XIMIsInvisible,	/* Disable caret feedback */
    XIMIsPrimary,	/* UI defined caret feedback */
    XIMIsSecondary	/* UI defined caret feedback */
} XIMCaretStyle;

1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193




















1194
1195
1196






















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































1197




1198
1199
1200
1201
1202


1203
1204
1205
1206
1207


1208

1395
1396
1397
1398
1399
1400
1401






1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046


4047
4048



4049
4050
4051
4052

4053







-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+



-
-
+
+
-
-
-


+
+
-
+
    XIMStatusDataType type;
    union {
	XIMText *text;
	Pixmap  bitmap;
    } data;
} XIMStatusDrawCallbackStruct;

typedef int (*XErrorHandler) (	    /* WARNING, this type not in Xlib spec */
#if NeedFunctionPrototypes
    Display*		/* display */,
    XErrorEvent*	/* error_event */
#endif
);
typedef struct _XIMHotKeyTrigger {
    KeySym	 keysym;
    int		 modifier;
    int		 modifier_mask;
} XIMHotKeyTrigger;

typedef struct _XIMHotKeyTriggers {
    int			 num_hot_key;
    XIMHotKeyTrigger	*key;
} XIMHotKeyTriggers;

typedef	unsigned long	 XIMHotKeyState;

#define	XIMHotKeyStateON	(0x0001L)
#define	XIMHotKeyStateOFF	(0x0002L)

typedef struct {
    unsigned short count_values;
    char **supported_values;
} XIMValuesList;

_XFUNCPROTOBEGIN

#if defined(WIN32) && !defined(_XLIBINT_)
#define _Xdebug *_Xdebug_p
#endif

EXTERN int _Xdebug;

EXTERN XFontStruct *XLoadQueryFont(
    Display*		/* display */,
    _Xconst char*	/* name */
);

EXTERN XFontStruct *XQueryFont(
    Display*		/* display */,
    XID			/* font_ID */
);


EXTERN XTimeCoord *XGetMotionEvents(
    Display*		/* display */,
    Window		/* w */,
    Time		/* start */,
    Time		/* stop */,
    int*		/* nevents_return */
);

EXTERN XModifierKeymap *XDeleteModifiermapEntry(
    XModifierKeymap*	/* modmap */,
#if NeedWidePrototypes
    unsigned int	/* keycode_entry */,
#else
    KeyCode		/* keycode_entry */,
#endif
    int			/* modifier */
);

EXTERN XModifierKeymap	*XGetModifierMapping(
    Display*		/* display */
);

EXTERN XModifierKeymap	*XInsertModifiermapEntry(
    XModifierKeymap*	/* modmap */,
#if NeedWidePrototypes
    unsigned int	/* keycode_entry */,
#else
    KeyCode		/* keycode_entry */,
#endif
    int			/* modifier */
);

EXTERN XModifierKeymap *XNewModifiermap(
    int			/* max_keys_per_mod */
);

EXTERN XImage *XCreateImage(
    Display*		/* display */,
    Visual*		/* visual */,
    unsigned int	/* depth */,
    int			/* format */,
    int			/* offset */,
    char*		/* data */,
    unsigned int	/* width */,
    unsigned int	/* height */,
    int			/* bitmap_pad */,
    int			/* bytes_per_line */
);
EXTERN Status XInitImage(
    XImage*		/* image */
);
EXTERN XImage *XGetImage(
    Display*		/* display */,
    Drawable		/* d */,
    int			/* x */,
    int			/* y */,
    unsigned int	/* width */,
    unsigned int	/* height */,
    unsigned long	/* plane_mask */,
    int			/* format */
);
EXTERN XImage *XGetSubImage(
    Display*		/* display */,
    Drawable		/* d */,
    int			/* x */,
    int			/* y */,
    unsigned int	/* width */,
    unsigned int	/* height */,
    unsigned long	/* plane_mask */,
    int			/* format */,
    XImage*		/* dest_image */,
    int			/* dest_x */,
    int			/* dest_y */
);

/*
 * X function declarations.
 */
EXTERN Display *XOpenDisplay(
    _Xconst char*	/* display_name */
);

EXTERN void XrmInitialize(
    void
);

EXTERN char *XFetchBytes(
    Display*		/* display */,
    int*		/* nbytes_return */
);
EXTERN char *XFetchBuffer(
    Display*		/* display */,
    int*		/* nbytes_return */,
    int			/* buffer */
);
EXTERN char *XGetAtomName(
    Display*		/* display */,
    Atom		/* atom */
);
EXTERN Status XGetAtomNames(
    Display*		/* dpy */,
    Atom*		/* atoms */,
    int			/* count */,
    char**		/* names_return */
);
EXTERN char *XGetDefault(
    Display*		/* display */,
    _Xconst char*	/* program */,
    _Xconst char*	/* option */
);
EXTERN char *XDisplayName(
    _Xconst char*	/* string */
);
EXTERN char *XKeysymToString(
    KeySym		/* keysym */
);

EXTERN int (*XSynchronize(
    Display*		/* display */,
    Bool		/* onoff */
))(
    Display*		/* display */
);
EXTERN int (*XSetAfterFunction(
    Display*		/* display */,
    int (*) (
	     Display*	/* display */
            )		/* procedure */
))(
    Display*		/* display */
);
EXTERN Atom XInternAtom(
    Display*		/* display */,
    _Xconst char*	/* atom_name */,
    Bool		/* only_if_exists */
);
EXTERN Status XInternAtoms(
    Display*		/* dpy */,
    char**		/* names */,
    int			/* count */,
    Bool		/* onlyIfExists */,
    Atom*		/* atoms_return */
);
EXTERN Colormap XCopyColormapAndFree(
    Display*		/* display */,
    Colormap		/* colormap */
);
EXTERN Colormap XCreateColormap(
    Display*		/* display */,
    Window		/* w */,
    Visual*		/* visual */,
    int			/* alloc */
);
EXTERN Cursor XCreatePixmapCursor(
    Display*		/* display */,
    Pixmap		/* source */,
    Pixmap		/* mask */,
    XColor*		/* foreground_color */,
    XColor*		/* background_color */,
    unsigned int	/* x */,
    unsigned int	/* y */
);
EXTERN Cursor XCreateGlyphCursor(
    Display*		/* display */,
    Font		/* source_font */,
    Font		/* mask_font */,
    unsigned int	/* source_char */,
    unsigned int	/* mask_char */,
    XColor _Xconst *	/* foreground_color */,
    XColor _Xconst *	/* background_color */
);
EXTERN Cursor XCreateFontCursor(
    Display*		/* display */,
    unsigned int	/* shape */
);
EXTERN Font XLoadFont(
    Display*		/* display */,
    _Xconst char*	/* name */
);
EXTERN GC XCreateGC(
    Display*		/* display */,
    Drawable		/* d */,
    unsigned long	/* valuemask */,
    XGCValues*		/* values */
);
EXTERN GContext XGContextFromGC(
    GC			/* gc */
);
EXTERN void XFlushGC(
    Display*		/* display */,
    GC			/* gc */
);
EXTERN Pixmap XCreatePixmap(
    Display*		/* display */,
    Drawable		/* d */,
    unsigned int	/* width */,
    unsigned int	/* height */,
    unsigned int	/* depth */
);
EXTERN Pixmap XCreateBitmapFromData(
    Display*		/* display */,
    Drawable		/* d */,
    _Xconst char*	/* data */,
    unsigned int	/* width */,
    unsigned int	/* height */
);
EXTERN Pixmap XCreatePixmapFromBitmapData(
    Display*		/* display */,
    Drawable		/* d */,
    char*		/* data */,
    unsigned int	/* width */,
    unsigned int	/* height */,
    unsigned long	/* fg */,
    unsigned long	/* bg */,
    unsigned int	/* depth */
);
EXTERN Window XCreateSimpleWindow(
    Display*		/* display */,
    Window		/* parent */,
    int			/* x */,
    int			/* y */,
    unsigned int	/* width */,
    unsigned int	/* height */,
    unsigned int	/* border_width */,
    unsigned long	/* border */,
    unsigned long	/* background */
);
EXTERN Window XGetSelectionOwner(
    Display*		/* display */,
    Atom		/* selection */
);
EXTERN Window XCreateWindow(
    Display*		/* display */,
    Window		/* parent */,
    int			/* x */,
    int			/* y */,
    unsigned int	/* width */,
    unsigned int	/* height */,
    unsigned int	/* border_width */,
    int			/* depth */,
    unsigned int	/* class */,
    Visual*		/* visual */,
    unsigned long	/* valuemask */,
    XSetWindowAttributes*	/* attributes */
);
EXTERN Colormap *XListInstalledColormaps(
    Display*		/* display */,
    Window		/* w */,
    int*		/* num_return */
);
EXTERN char **XListFonts(
    Display*		/* display */,
    _Xconst char*	/* pattern */,
    int			/* maxnames */,
    int*		/* actual_count_return */
);
EXTERN char **XListFontsWithInfo(
    Display*		/* display */,
    _Xconst char*	/* pattern */,
    int			/* maxnames */,
    int*		/* count_return */,
    XFontStruct**	/* info_return */
);
EXTERN char **XGetFontPath(
    Display*		/* display */,
    int*		/* npaths_return */
);
EXTERN char **XListExtensions(
    Display*		/* display */,
    int*		/* nextensions_return */
);
EXTERN Atom *XListProperties(
    Display*		/* display */,
    Window		/* w */,
    int*		/* num_prop_return */
);
EXTERN XHostAddress *XListHosts(
    Display*		/* display */,
    int*		/* nhosts_return */,
    Bool*		/* state_return */
);
EXTERN _X_DEPRECATED KeySym XKeycodeToKeysym(
    Display*		/* display */,
#if NeedWidePrototypes
    unsigned int	/* keycode */,
#else
    KeyCode		/* keycode */,
#endif
    int			/* index */
);
EXTERN KeySym XLookupKeysym(
    XKeyEvent*		/* key_event */,
    int			/* index */
);
EXTERN KeySym *XGetKeyboardMapping(
    Display*		/* display */,
#if NeedWidePrototypes
    unsigned int	/* first_keycode */,
#else
    KeyCode		/* first_keycode */,
#endif
    int			/* keycode_count */,
    int*		/* keysyms_per_keycode_return */
);
EXTERN KeySym XStringToKeysym(
    _Xconst char*	/* string */
);
EXTERN long XMaxRequestSize(
    Display*		/* display */
);
EXTERN long XExtendedMaxRequestSize(
    Display*		/* display */
);
EXTERN char *XResourceManagerString(
    Display*		/* display */
);
EXTERN char *XScreenResourceString(
	Screen*		/* screen */
);
EXTERN unsigned long XDisplayMotionBufferSize(
    Display*		/* display */
);
EXTERN VisualID XVisualIDFromVisual(
    Visual*		/* visual */
);

/* multithread routines */

EXTERN Status XInitThreads(
    void
);

EXTERN void XLockDisplay(
    Display*		/* display */
);

EXTERN void XUnlockDisplay(
    Display*		/* display */
);

/* routines for dealing with extensions */

EXTERN XExtCodes *XInitExtension(
    Display*		/* display */,
    _Xconst char*	/* name */
);

EXTERN XExtCodes *XAddExtension(
    Display*		/* display */
);
EXTERN XExtData *XFindOnExtensionList(
    XExtData**		/* structure */,
    int			/* number */
);
EXTERN XExtData **XEHeadOfExtensionList(
    XEDataObject	/* object */
);

/* these are routines for which there are also macros */
EXTERN Window XRootWindow(
    Display*		/* display */,
    int			/* screen_number */
);
EXTERN Window XDefaultRootWindow(
    Display*		/* display */
);
EXTERN Window XRootWindowOfScreen(
    Screen*		/* screen */
);
EXTERN Visual *XDefaultVisual(
    Display*		/* display */,
    int			/* screen_number */
);
EXTERN Visual *XDefaultVisualOfScreen(
    Screen*		/* screen */
);
EXTERN GC XDefaultGC(
    Display*		/* display */,
    int			/* screen_number */
);
EXTERN GC XDefaultGCOfScreen(
    Screen*		/* screen */
);
EXTERN unsigned long XBlackPixel(
    Display*		/* display */,
    int			/* screen_number */
);
EXTERN unsigned long XWhitePixel(
    Display*		/* display */,
    int			/* screen_number */
);
EXTERN unsigned long XAllPlanes(
    void
);
EXTERN unsigned long XBlackPixelOfScreen(
    Screen*		/* screen */
);
EXTERN unsigned long XWhitePixelOfScreen(
    Screen*		/* screen */
);
EXTERN unsigned long XNextRequest(
    Display*		/* display */
);
EXTERN unsigned long XLastKnownRequestProcessed(
    Display*		/* display */
);
EXTERN char *XServerVendor(
    Display*		/* display */
);
EXTERN char *XDisplayString(
    Display*		/* display */
);
EXTERN Colormap XDefaultColormap(
    Display*		/* display */,
    int			/* screen_number */
);
EXTERN Colormap XDefaultColormapOfScreen(
    Screen*		/* screen */
);
EXTERN Display *XDisplayOfScreen(
    Screen*		/* screen */
);
EXTERN Screen *XScreenOfDisplay(
    Display*		/* display */,
    int			/* screen_number */
);
EXTERN Screen *XDefaultScreenOfDisplay(
    Display*		/* display */
);
EXTERN long XEventMaskOfScreen(
    Screen*		/* screen */
);

EXTERN int XScreenNumberOfScreen(
    Screen*		/* screen */
);

typedef int (*XErrorHandler) (	    /* WARNING, this type not in Xlib spec */
    Display*		/* display */,
    XErrorEvent*	/* error_event */
);

EXTERN XErrorHandler XSetErrorHandler (
    XErrorHandler	/* handler */
);


typedef int (*XIOErrorHandler) (    /* WARNING, this type not in Xlib spec */
    Display*		/* display */
);

EXTERN XIOErrorHandler XSetIOErrorHandler (
    XIOErrorHandler	/* handler */
);


EXTERN XPixmapFormatValues *XListPixmapFormats(
    Display*		/* display */,
    int*		/* count_return */
);
EXTERN int *XListDepths(
    Display*		/* display */,
    int			/* screen_number */,
    int*		/* count_return */
);

/* ICCCM routines for things that don't require special include files; */
/* other declarations are given in Xutil.h                             */
EXTERN Status XReconfigureWMWindow(
    Display*		/* display */,
    Window		/* w */,
    int			/* screen_number */,
    unsigned int	/* mask */,
    XWindowChanges*	/* changes */
);

EXTERN Status XGetWMProtocols(
    Display*		/* display */,
    Window		/* w */,
    Atom**		/* protocols_return */,
    int*		/* count_return */
);
EXTERN Status XSetWMProtocols(
    Display*		/* display */,
    Window		/* w */,
    Atom*		/* protocols */,
    int			/* count */
);
EXTERN Status XIconifyWindow(
    Display*		/* display */,
    Window		/* w */,
    int			/* screen_number */
);
EXTERN Status XWithdrawWindow(
    Display*		/* display */,
    Window		/* w */,
    int			/* screen_number */
);
EXTERN Status XGetCommand(
    Display*		/* display */,
    Window		/* w */,
    char***		/* argv_return */,
    int*		/* argc_return */
);
EXTERN Status XGetWMColormapWindows(
    Display*		/* display */,
    Window		/* w */,
    Window**		/* windows_return */,
    int*		/* count_return */
);
EXTERN Status XSetWMColormapWindows(
    Display*		/* display */,
    Window		/* w */,
    Window*		/* colormap_windows */,
    int			/* count */
);
EXTERN void XFreeStringList(
    char**		/* list */
);
EXTERN int XSetTransientForHint(
    Display*		/* display */,
    Window		/* w */,
    Window		/* prop_window */
);

/* The following are given in alphabetical order */

EXTERN int XActivateScreenSaver(
    Display*		/* display */
);

EXTERN int XAddHost(
    Display*		/* display */,
    XHostAddress*	/* host */
);

EXTERN int XAddHosts(
    Display*		/* display */,
    XHostAddress*	/* hosts */,
    int			/* num_hosts */
);

EXTERN int XAddToExtensionList(
    struct _XExtData**	/* structure */,
    XExtData*		/* ext_data */
);

EXTERN int XAddToSaveSet(
    Display*		/* display */,
    Window		/* w */
);

EXTERN Status XAllocColor(
    Display*		/* display */,
    Colormap		/* colormap */,
    XColor*		/* screen_in_out */
);

EXTERN Status XAllocColorCells(
    Display*		/* display */,
    Colormap		/* colormap */,
    Bool	        /* contig */,
    unsigned long*	/* plane_masks_return */,
    unsigned int	/* nplanes */,
    unsigned long*	/* pixels_return */,
    unsigned int 	/* npixels */
);

EXTERN Status XAllocColorPlanes(
    Display*		/* display */,
    Colormap		/* colormap */,
    Bool		/* contig */,
    unsigned long*	/* pixels_return */,
    int			/* ncolors */,
    int			/* nreds */,
    int			/* ngreens */,
    int			/* nblues */,
    unsigned long*	/* rmask_return */,
    unsigned long*	/* gmask_return */,
    unsigned long*	/* bmask_return */
);

EXTERN Status XAllocNamedColor(
    Display*		/* display */,
    Colormap		/* colormap */,
    _Xconst char*	/* color_name */,
    XColor*		/* screen_def_return */,
    XColor*		/* exact_def_return */
);

EXTERN int XAllowEvents(
    Display*		/* display */,
    int			/* event_mode */,
    Time		/* time */
);

EXTERN int XAutoRepeatOff(
    Display*		/* display */
);

EXTERN int XAutoRepeatOn(
    Display*		/* display */
);

EXTERN int XBell(
    Display*		/* display */,
    int			/* percent */
);

EXTERN int XBitmapBitOrder(
    Display*		/* display */
);

EXTERN int XBitmapPad(
    Display*		/* display */
);

EXTERN int XBitmapUnit(
    Display*		/* display */
);

EXTERN int XCellsOfScreen(
    Screen*		/* screen */
);

EXTERN int XChangeActivePointerGrab(
    Display*		/* display */,
    unsigned int	/* event_mask */,
    Cursor		/* cursor */,
    Time		/* time */
);

EXTERN int XChangeGC(
    Display*		/* display */,
    GC			/* gc */,
    unsigned long	/* valuemask */,
    XGCValues*		/* values */
);

EXTERN int XChangeKeyboardControl(
    Display*		/* display */,
    unsigned long	/* value_mask */,
    XKeyboardControl*	/* values */
);

EXTERN int XChangeKeyboardMapping(
    Display*		/* display */,
    int			/* first_keycode */,
    int			/* keysyms_per_keycode */,
    KeySym*		/* keysyms */,
    int			/* num_codes */
);

EXTERN int XChangePointerControl(
    Display*		/* display */,
    Bool		/* do_accel */,
    Bool		/* do_threshold */,
    int			/* accel_numerator */,
    int			/* accel_denominator */,
    int			/* threshold */
);

EXTERN int XChangeProperty(
    Display*		/* display */,
    Window		/* w */,
    Atom		/* property */,
    Atom		/* type */,
    int			/* format */,
    int			/* mode */,
    _Xconst unsigned char*	/* data */,
    int			/* nelements */
);

EXTERN int XChangeSaveSet(
    Display*		/* display */,
    Window		/* w */,
    int			/* change_mode */
);

EXTERN int XChangeWindowAttributes(
    Display*		/* display */,
    Window		/* w */,
    unsigned long	/* valuemask */,
    XSetWindowAttributes* /* attributes */
);

EXTERN Bool XCheckIfEvent(
    Display*		/* display */,
    XEvent*		/* event_return */,
    Bool (*) (
	       Display*			/* display */,
               XEvent*			/* event */,
               XPointer			/* arg */
             )		/* predicate */,
    XPointer		/* arg */
);

EXTERN Bool XCheckMaskEvent(
    Display*		/* display */,
    long		/* event_mask */,
    XEvent*		/* event_return */
);

EXTERN Bool XCheckTypedEvent(
    Display*		/* display */,
    int			/* event_type */,
    XEvent*		/* event_return */
);

EXTERN Bool XCheckTypedWindowEvent(
    Display*		/* display */,
    Window		/* w */,
    int			/* event_type */,
    XEvent*		/* event_return */
);

EXTERN Bool XCheckWindowEvent(
    Display*		/* display */,
    Window		/* w */,
    long		/* event_mask */,
    XEvent*		/* event_return */
);

EXTERN int XCirculateSubwindows(
    Display*		/* display */,
    Window		/* w */,
    int			/* direction */
);

EXTERN int XCirculateSubwindowsDown(
    Display*		/* display */,
    Window		/* w */
);

EXTERN int XCirculateSubwindowsUp(
    Display*		/* display */,
    Window		/* w */
);

EXTERN int XClearArea(
    Display*		/* display */,
    Window		/* w */,
    int			/* x */,
    int			/* y */,
    unsigned int	/* width */,
    unsigned int	/* height */,
    Bool		/* exposures */
);

EXTERN int XClearWindow(
    Display*		/* display */,
    Window		/* w */
);

EXTERN int XCloseDisplay(
    Display*		/* display */
);

EXTERN int XConfigureWindow(
    Display*		/* display */,
    Window		/* w */,
    unsigned int	/* value_mask */,
    XWindowChanges*	/* values */
);

EXTERN int XConnectionNumber(
    Display*		/* display */
);

EXTERN int XConvertSelection(
    Display*		/* display */,
    Atom		/* selection */,
    Atom 		/* target */,
    Atom		/* property */,
    Window		/* requestor */,
    Time		/* time */
);

EXTERN int XCopyArea(
    Display*		/* display */,
    Drawable		/* src */,
    Drawable		/* dest */,
    GC			/* gc */,
    int			/* src_x */,
    int			/* src_y */,
    unsigned int	/* width */,
    unsigned int	/* height */,
    int			/* dest_x */,
    int			/* dest_y */
);

EXTERN int XCopyGC(
    Display*		/* display */,
    GC			/* src */,
    unsigned long	/* valuemask */,
    GC			/* dest */
);

EXTERN int XCopyPlane(
    Display*		/* display */,
    Drawable		/* src */,
    Drawable		/* dest */,
    GC			/* gc */,
    int			/* src_x */,
    int			/* src_y */,
    unsigned int	/* width */,
    unsigned int	/* height */,
    int			/* dest_x */,
    int			/* dest_y */,
    unsigned long	/* plane */
);

EXTERN int XDefaultDepth(
    Display*		/* display */,
    int			/* screen_number */
);

EXTERN int XDefaultDepthOfScreen(
    Screen*		/* screen */
);

EXTERN int XDefaultScreen(
    Display*		/* display */
);

EXTERN int XDefineCursor(
    Display*		/* display */,
    Window		/* w */,
    Cursor		/* cursor */
);

EXTERN int XDeleteProperty(
    Display*		/* display */,
    Window		/* w */,
    Atom		/* property */
);

EXTERN int XDestroyWindow(
    Display*		/* display */,
    Window		/* w */
);

EXTERN int XDestroySubwindows(
    Display*		/* display */,
    Window		/* w */
);

EXTERN int XDoesBackingStore(
    Screen*		/* screen */
);

EXTERN Bool XDoesSaveUnders(
    Screen*		/* screen */
);

EXTERN int XDisableAccessControl(
    Display*		/* display */
);


EXTERN int XDisplayCells(
    Display*		/* display */,
    int			/* screen_number */
);

EXTERN int XDisplayHeight(
    Display*		/* display */,
    int			/* screen_number */
);

EXTERN int XDisplayHeightMM(
    Display*		/* display */,
    int			/* screen_number */
);

EXTERN int XDisplayKeycodes(
    Display*		/* display */,
    int*		/* min_keycodes_return */,
    int*		/* max_keycodes_return */
);

EXTERN int XDisplayPlanes(
    Display*		/* display */,
    int			/* screen_number */
);

EXTERN int XDisplayWidth(
    Display*		/* display */,
    int			/* screen_number */
);

EXTERN int XDisplayWidthMM(
    Display*		/* display */,
    int			/* screen_number */
);

EXTERN int XDrawArc(
    Display*		/* display */,
    Drawable		/* d */,
    GC			/* gc */,
    int			/* x */,
    int			/* y */,
    unsigned int	/* width */,
    unsigned int	/* height */,
    int			/* angle1 */,
    int			/* angle2 */
);

EXTERN int XDrawArcs(
    Display*		/* display */,
    Drawable		/* d */,
    GC			/* gc */,
    XArc*		/* arcs */,
    int			/* narcs */
);

EXTERN int XDrawImageString(
    Display*		/* display */,
    Drawable		/* d */,
    GC			/* gc */,
    int			/* x */,
    int			/* y */,
    _Xconst char*	/* string */,
    int			/* length */
);

EXTERN int XDrawImageString16(
    Display*		/* display */,
    Drawable		/* d */,
    GC			/* gc */,
    int			/* x */,
    int			/* y */,
    _Xconst XChar2b*	/* string */,
    int			/* length */
);

EXTERN int XDrawLine(
    Display*		/* display */,
    Drawable		/* d */,
    GC			/* gc */,
    int			/* x1 */,
    int			/* y1 */,
    int			/* x2 */,
    int			/* y2 */
);

EXTERN int XDrawLines(
    Display*		/* display */,
    Drawable		/* d */,
    GC			/* gc */,
    XPoint*		/* points */,
    int			/* npoints */,
    int			/* mode */
);

EXTERN int XDrawPoint(
    Display*		/* display */,
    Drawable		/* d */,
    GC			/* gc */,
    int			/* x */,
    int			/* y */
);

EXTERN int XDrawPoints(
    Display*		/* display */,
    Drawable		/* d */,
    GC			/* gc */,
    XPoint*		/* points */,
    int			/* npoints */,
    int			/* mode */
);

EXTERN int XDrawRectangle(
    Display*		/* display */,
    Drawable		/* d */,
    GC			/* gc */,
    int			/* x */,
    int			/* y */,
    unsigned int	/* width */,
    unsigned int	/* height */
);

EXTERN int XDrawRectangles(
    Display*		/* display */,
    Drawable		/* d */,
    GC			/* gc */,
    XRectangle*		/* rectangles */,
    int			/* nrectangles */
);

EXTERN int XDrawSegments(
    Display*		/* display */,
    Drawable		/* d */,
    GC			/* gc */,
    XSegment*		/* segments */,
    int			/* nsegments */
);

EXTERN int XDrawString(
    Display*		/* display */,
    Drawable		/* d */,
    GC			/* gc */,
    int			/* x */,
    int			/* y */,
    _Xconst char*	/* string */,
    int			/* length */
);

EXTERN int XDrawString16(
    Display*		/* display */,
    Drawable		/* d */,
    GC			/* gc */,
    int			/* x */,
    int			/* y */,
    _Xconst XChar2b*	/* string */,
    int			/* length */
);

EXTERN int XDrawText(
    Display*		/* display */,
    Drawable		/* d */,
    GC			/* gc */,
    int			/* x */,
    int			/* y */,
    XTextItem*		/* items */,
    int			/* nitems */
);

EXTERN int XDrawText16(
    Display*		/* display */,
    Drawable		/* d */,
    GC			/* gc */,
    int			/* x */,
    int			/* y */,
    XTextItem16*	/* items */,
    int			/* nitems */
);

EXTERN int XEnableAccessControl(
    Display*		/* display */
);

EXTERN int XEventsQueued(
    Display*		/* display */,
    int			/* mode */
);

EXTERN Status XFetchName(
    Display*		/* display */,
    Window		/* w */,
    char**		/* window_name_return */
);

EXTERN int XFillArc(
    Display*		/* display */,
    Drawable		/* d */,
    GC			/* gc */,
    int			/* x */,
    int			/* y */,
    unsigned int	/* width */,
    unsigned int	/* height */,
    int			/* angle1 */,
    int			/* angle2 */
);

EXTERN int XFillArcs(
    Display*		/* display */,
    Drawable		/* d */,
    GC			/* gc */,
    XArc*		/* arcs */,
    int			/* narcs */
);

EXTERN int XFillPolygon(
    Display*		/* display */,
    Drawable		/* d */,
    GC			/* gc */,
    XPoint*		/* points */,
    int			/* npoints */,
    int			/* shape */,
    int			/* mode */
);

EXTERN int XFillRectangle(
    Display*		/* display */,
    Drawable		/* d */,
    GC			/* gc */,
    int			/* x */,
    int			/* y */,
    unsigned int	/* width */,
    unsigned int	/* height */
);

EXTERN int XFillRectangles(
    Display*		/* display */,
    Drawable		/* d */,
    GC			/* gc */,
    XRectangle*		/* rectangles */,
    int			/* nrectangles */
);

EXTERN int XFlush(
    Display*		/* display */
);

EXTERN int XForceScreenSaver(
    Display*		/* display */,
    int			/* mode */
);

EXTERN int XFree(
    void*		/* data */
);

EXTERN int XFreeColormap(
    Display*		/* display */,
    Colormap		/* colormap */
);

EXTERN int XFreeColors(
    Display*		/* display */,
    Colormap		/* colormap */,
    unsigned long*	/* pixels */,
    int			/* npixels */,
    unsigned long	/* planes */
);

EXTERN int XFreeCursor(
    Display*		/* display */,
    Cursor		/* cursor */
);

EXTERN int XFreeExtensionList(
    char**		/* list */
);

EXTERN int XFreeFont(
    Display*		/* display */,
    XFontStruct*	/* font_struct */
);

EXTERN int XFreeFontInfo(
    char**		/* names */,
    XFontStruct*	/* free_info */,
    int			/* actual_count */
);

EXTERN int XFreeFontNames(
    char**		/* list */
);

EXTERN int XFreeFontPath(
    char**		/* list */
);

EXTERN int XFreeGC(
    Display*		/* display */,
    GC			/* gc */
);

EXTERN int XFreeModifiermap(
    XModifierKeymap*	/* modmap */
);

EXTERN int XFreePixmap(
    Display*		/* display */,
    Pixmap		/* pixmap */
);

EXTERN int XGeometry(
    Display*		/* display */,
    int			/* screen */,
    _Xconst char*	/* position */,
    _Xconst char*	/* default_position */,
    unsigned int	/* bwidth */,
    unsigned int	/* fwidth */,
    unsigned int	/* fheight */,
    int			/* xadder */,
    int			/* yadder */,
    int*		/* x_return */,
    int*		/* y_return */,
    int*		/* width_return */,
    int*		/* height_return */
);

EXTERN int XGetErrorDatabaseText(
    Display*		/* display */,
    _Xconst char*	/* name */,
    _Xconst char*	/* message */,
    _Xconst char*	/* default_string */,
    char*		/* buffer_return */,
    int			/* length */
);

EXTERN int XGetErrorText(
    Display*		/* display */,
    int			/* code */,
    char*		/* buffer_return */,
    int			/* length */
);

EXTERN Bool XGetFontProperty(
    XFontStruct*	/* font_struct */,
    Atom		/* atom */,
    unsigned long*	/* value_return */
);

EXTERN Status XGetGCValues(
    Display*		/* display */,
    GC			/* gc */,
    unsigned long	/* valuemask */,
    XGCValues*		/* values_return */
);

EXTERN Status XGetGeometry(
    Display*		/* display */,
    Drawable		/* d */,
    Window*		/* root_return */,
    int*		/* x_return */,
    int*		/* y_return */,
    unsigned int*	/* width_return */,
    unsigned int*	/* height_return */,
    unsigned int*	/* border_width_return */,
    unsigned int*	/* depth_return */
);

EXTERN Status XGetIconName(
    Display*		/* display */,
    Window		/* w */,
    char**		/* icon_name_return */
);

EXTERN int XGetInputFocus(
    Display*		/* display */,
    Window*		/* focus_return */,
    int*		/* revert_to_return */
);

EXTERN int XGetKeyboardControl(
    Display*		/* display */,
    XKeyboardState*	/* values_return */
);

EXTERN int XGetPointerControl(
    Display*		/* display */,
    int*		/* accel_numerator_return */,
    int*		/* accel_denominator_return */,
    int*		/* threshold_return */
);

EXTERN int XGetPointerMapping(
    Display*		/* display */,
    unsigned char*	/* map_return */,
    int			/* nmap */
);

EXTERN int XGetScreenSaver(
    Display*		/* display */,
    int*		/* timeout_return */,
    int*		/* interval_return */,
    int*		/* prefer_blanking_return */,
    int*		/* allow_exposures_return */
);

EXTERN Status XGetTransientForHint(
    Display*		/* display */,
    Window		/* w */,
    Window*		/* prop_window_return */
);

EXTERN int XGetWindowProperty(
    Display*		/* display */,
    Window		/* w */,
    Atom		/* property */,
    long		/* long_offset */,
    long		/* long_length */,
    Bool		/* delete */,
    Atom		/* req_type */,
    Atom*		/* actual_type_return */,
    int*		/* actual_format_return */,
    unsigned long*	/* nitems_return */,
    unsigned long*	/* bytes_after_return */,
    unsigned char**	/* prop_return */
);

EXTERN Status XGetWindowAttributes(
    Display*		/* display */,
    Window		/* w */,
    XWindowAttributes*	/* window_attributes_return */
);

EXTERN int XGrabButton(
    Display*		/* display */,
    unsigned int	/* button */,
    unsigned int	/* modifiers */,
    Window		/* grab_window */,
    Bool		/* owner_events */,
    unsigned int	/* event_mask */,
    int			/* pointer_mode */,
    int			/* keyboard_mode */,
    Window		/* confine_to */,
    Cursor		/* cursor */
);

EXTERN int XGrabKey(
    Display*		/* display */,
    int			/* keycode */,
    unsigned int	/* modifiers */,
    Window		/* grab_window */,
    Bool		/* owner_events */,
    int			/* pointer_mode */,
    int			/* keyboard_mode */
);

EXTERN int XGrabKeyboard(
    Display*		/* display */,
    Window		/* grab_window */,
    Bool		/* owner_events */,
    int			/* pointer_mode */,
    int			/* keyboard_mode */,
    Time		/* time */
);

EXTERN int XGrabPointer(
    Display*		/* display */,
    Window		/* grab_window */,
    Bool		/* owner_events */,
    unsigned int	/* event_mask */,
    int			/* pointer_mode */,
    int			/* keyboard_mode */,
    Window		/* confine_to */,
    Cursor		/* cursor */,
    Time		/* time */
);

EXTERN int XGrabServer(
    Display*		/* display */
);

EXTERN int XHeightMMOfScreen(
    Screen*		/* screen */
);

EXTERN int XHeightOfScreen(
    Screen*		/* screen */
);

EXTERN int XIfEvent(
    Display*		/* display */,
    XEvent*		/* event_return */,
    Bool (*) (
	       Display*			/* display */,
               XEvent*			/* event */,
               XPointer			/* arg */
             )		/* predicate */,
    XPointer		/* arg */
);

EXTERN int XImageByteOrder(
    Display*		/* display */
);

EXTERN int XInstallColormap(
    Display*		/* display */,
    Colormap		/* colormap */
);

EXTERN KeyCode XKeysymToKeycode(
    Display*		/* display */,
    KeySym		/* keysym */
);

EXTERN int XKillClient(
    Display*		/* display */,
    XID			/* resource */
);

EXTERN Status XLookupColor(
    Display*		/* display */,
    Colormap		/* colormap */,
    _Xconst char*	/* color_name */,
    XColor*		/* exact_def_return */,
    XColor*		/* screen_def_return */
);

EXTERN int XLowerWindow(
    Display*		/* display */,
    Window		/* w */
);

EXTERN int XMapRaised(
    Display*		/* display */,
    Window		/* w */
);

EXTERN int XMapSubwindows(
    Display*		/* display */,
    Window		/* w */
);

EXTERN int XMapWindow(
    Display*		/* display */,
    Window		/* w */
);

EXTERN int XMaskEvent(
    Display*		/* display */,
    long		/* event_mask */,
    XEvent*		/* event_return */
);

EXTERN int XMaxCmapsOfScreen(
    Screen*		/* screen */
);

EXTERN int XMinCmapsOfScreen(
    Screen*		/* screen */
);

EXTERN int XMoveResizeWindow(
    Display*		/* display */,
    Window		/* w */,
    int			/* x */,
    int			/* y */,
    unsigned int	/* width */,
    unsigned int	/* height */
);

EXTERN int XMoveWindow(
    Display*		/* display */,
    Window		/* w */,
    int			/* x */,
    int			/* y */
);

EXTERN int XNextEvent(
    Display*		/* display */,
    XEvent*		/* event_return */
);

EXTERN int XNoOp(
    Display*		/* display */
);

EXTERN Status XParseColor(
    Display*		/* display */,
    Colormap		/* colormap */,
    _Xconst char*	/* spec */,
    XColor*		/* exact_def_return */
);

EXTERN int XParseGeometry(
    _Xconst char*	/* parsestring */,
    int*		/* x_return */,
    int*		/* y_return */,
    unsigned int*	/* width_return */,
    unsigned int*	/* height_return */
);

EXTERN int XPeekEvent(
    Display*		/* display */,
    XEvent*		/* event_return */
);

EXTERN int XPeekIfEvent(
    Display*		/* display */,
    XEvent*		/* event_return */,
    Bool (*) (
	       Display*		/* display */,
               XEvent*		/* event */,
               XPointer		/* arg */
             )		/* predicate */,
    XPointer		/* arg */
);

EXTERN int XPending(
    Display*		/* display */
);

EXTERN int XPlanesOfScreen(
    Screen*		/* screen */
);

EXTERN int XProtocolRevision(
    Display*		/* display */
);

EXTERN int XProtocolVersion(
    Display*		/* display */
);


EXTERN int XPutBackEvent(
    Display*		/* display */,
    XEvent*		/* event */
);

EXTERN int XPutImage(
    Display*		/* display */,
    Drawable		/* d */,
    GC			/* gc */,
    XImage*		/* image */,
    int			/* src_x */,
    int			/* src_y */,
    int			/* dest_x */,
    int			/* dest_y */,
    unsigned int	/* width */,
    unsigned int	/* height */
);

EXTERN int XQLength(
    Display*		/* display */
);

EXTERN Status XQueryBestCursor(
    Display*		/* display */,
    Drawable		/* d */,
    unsigned int        /* width */,
    unsigned int	/* height */,
    unsigned int*	/* width_return */,
    unsigned int*	/* height_return */
);

EXTERN Status XQueryBestSize(
    Display*		/* display */,
    int			/* class */,
    Drawable		/* which_screen */,
    unsigned int	/* width */,
    unsigned int	/* height */,
    unsigned int*	/* width_return */,
    unsigned int*	/* height_return */
);

EXTERN Status XQueryBestStipple(
    Display*		/* display */,
    Drawable		/* which_screen */,
    unsigned int	/* width */,
    unsigned int	/* height */,
    unsigned int*	/* width_return */,
    unsigned int*	/* height_return */
);

EXTERN Status XQueryBestTile(
    Display*		/* display */,
    Drawable		/* which_screen */,
    unsigned int	/* width */,
    unsigned int	/* height */,
    unsigned int*	/* width_return */,
    unsigned int*	/* height_return */
);

EXTERN int XQueryColor(
    Display*		/* display */,
    Colormap		/* colormap */,
    XColor*		/* def_in_out */
);

EXTERN int XQueryColors(
    Display*		/* display */,
    Colormap		/* colormap */,
    XColor*		/* defs_in_out */,
    int			/* ncolors */
);

EXTERN Bool XQueryExtension(
    Display*		/* display */,
    _Xconst char*	/* name */,
    int*		/* major_opcode_return */,
    int*		/* first_event_return */,
    int*		/* first_error_return */
);

EXTERN int XQueryKeymap(
    Display*		/* display */,
    char [32]		/* keys_return */
);

EXTERN Bool XQueryPointer(
    Display*		/* display */,
    Window		/* w */,
    Window*		/* root_return */,
    Window*		/* child_return */,
    int*		/* root_x_return */,
    int*		/* root_y_return */,
    int*		/* win_x_return */,
    int*		/* win_y_return */,
    unsigned int*       /* mask_return */
);

EXTERN int XQueryTextExtents(
    Display*		/* display */,
    XID			/* font_ID */,
    _Xconst char*	/* string */,
    int			/* nchars */,
    int*		/* direction_return */,
    int*		/* font_ascent_return */,
    int*		/* font_descent_return */,
    XCharStruct*	/* overall_return */
);

EXTERN int XQueryTextExtents16(
    Display*		/* display */,
    XID			/* font_ID */,
    _Xconst XChar2b*	/* string */,
    int			/* nchars */,
    int*		/* direction_return */,
    int*		/* font_ascent_return */,
    int*		/* font_descent_return */,
    XCharStruct*	/* overall_return */
);

EXTERN Status XQueryTree(
    Display*		/* display */,
    Window		/* w */,
    Window*		/* root_return */,
    Window*		/* parent_return */,
    Window**		/* children_return */,
    unsigned int*	/* nchildren_return */
);

EXTERN int XRaiseWindow(
    Display*		/* display */,
    Window		/* w */
);

EXTERN int XReadBitmapFile(
    Display*		/* display */,
    Drawable 		/* d */,
    _Xconst char*	/* filename */,
    unsigned int*	/* width_return */,
    unsigned int*	/* height_return */,
    Pixmap*		/* bitmap_return */,
    int*		/* x_hot_return */,
    int*		/* y_hot_return */
);

EXTERN int XReadBitmapFileData(
    _Xconst char*	/* filename */,
    unsigned int*	/* width_return */,
    unsigned int*	/* height_return */,
    unsigned char**	/* data_return */,
    int*		/* x_hot_return */,
    int*		/* y_hot_return */
);

EXTERN int XRebindKeysym(
    Display*		/* display */,
    KeySym		/* keysym */,
    KeySym*		/* list */,
    int			/* mod_count */,
    _Xconst unsigned char*	/* string */,
    int			/* bytes_string */
);

EXTERN int XRecolorCursor(
    Display*		/* display */,
    Cursor		/* cursor */,
    XColor*		/* foreground_color */,
    XColor*		/* background_color */
);

EXTERN int XRefreshKeyboardMapping(
    XMappingEvent*	/* event_map */
);

EXTERN int XRemoveFromSaveSet(
    Display*		/* display */,
    Window		/* w */
);

EXTERN int XRemoveHost(
    Display*		/* display */,
    XHostAddress*	/* host */
);

EXTERN int XRemoveHosts(
    Display*		/* display */,
    XHostAddress*	/* hosts */,
    int			/* num_hosts */
);

EXTERN int XReparentWindow(
    Display*		/* display */,
    Window		/* w */,
    Window		/* parent */,
    int			/* x */,
    int			/* y */
);

EXTERN int XResetScreenSaver(
    Display*		/* display */
);

EXTERN int XResizeWindow(
    Display*		/* display */,
    Window		/* w */,
    unsigned int	/* width */,
    unsigned int	/* height */
);

EXTERN int XRestackWindows(
    Display*		/* display */,
    Window*		/* windows */,
    int			/* nwindows */
);

EXTERN int XRotateBuffers(
    Display*		/* display */,
    int			/* rotate */
);

EXTERN int XRotateWindowProperties(
    Display*		/* display */,
    Window		/* w */,
    Atom*		/* properties */,
    int			/* num_prop */,
    int			/* npositions */
);

EXTERN int XScreenCount(
    Display*		/* display */
);

EXTERN int XSelectInput(
    Display*		/* display */,
    Window		/* w */,
    long		/* event_mask */
);

EXTERN Status XSendEvent(
    Display*		/* display */,
    Window		/* w */,
    Bool		/* propagate */,
    long		/* event_mask */,
    XEvent*		/* event_send */
);

EXTERN int XSetAccessControl(
    Display*		/* display */,
    int			/* mode */
);

EXTERN int XSetArcMode(
    Display*		/* display */,
    GC			/* gc */,
    int			/* arc_mode */
);

EXTERN int XSetBackground(
    Display*		/* display */,
    GC			/* gc */,
    unsigned long	/* background */
);

EXTERN int XSetClipMask(
    Display*		/* display */,
    GC			/* gc */,
    Pixmap		/* pixmap */
);

EXTERN int XSetClipOrigin(
    Display*		/* display */,
    GC			/* gc */,
    int			/* clip_x_origin */,
    int			/* clip_y_origin */
);

EXTERN int XSetClipRectangles(
    Display*		/* display */,
    GC			/* gc */,
    int			/* clip_x_origin */,
    int			/* clip_y_origin */,
    XRectangle*		/* rectangles */,
    int			/* n */,
    int			/* ordering */
);

EXTERN int XSetCloseDownMode(
    Display*		/* display */,
    int			/* close_mode */
);

EXTERN int XSetCommand(
    Display*		/* display */,
    Window		/* w */,
    char**		/* argv */,
    int			/* argc */
);

EXTERN int XSetDashes(
    Display*		/* display */,
    GC			/* gc */,
    int			/* dash_offset */,
    _Xconst char*	/* dash_list */,
    int			/* n */
);

EXTERN int XSetFillRule(
    Display*		/* display */,
    GC			/* gc */,
    int			/* fill_rule */
);

EXTERN int XSetFillStyle(
    Display*		/* display */,
    GC			/* gc */,
    int			/* fill_style */
);

EXTERN int XSetFont(
    Display*		/* display */,
    GC			/* gc */,
    Font		/* font */
);

EXTERN int XSetFontPath(
    Display*		/* display */,
    char**		/* directories */,
    int			/* ndirs */
);

EXTERN int XSetForeground(
    Display*		/* display */,
    GC			/* gc */,
    unsigned long	/* foreground */
);

EXTERN int XSetFunction(
    Display*		/* display */,
    GC			/* gc */,
    int			/* function */
);

EXTERN int XSetGraphicsExposures(
    Display*		/* display */,
    GC			/* gc */,
    Bool		/* graphics_exposures */
);

EXTERN int XSetIconName(
    Display*		/* display */,
    Window		/* w */,
    _Xconst char*	/* icon_name */
);

EXTERN int XSetInputFocus(
    Display*		/* display */,
    Window		/* focus */,
    int			/* revert_to */,
    Time		/* time */
);

EXTERN int XSetLineAttributes(
    Display*		/* display */,
    GC			/* gc */,
    unsigned int	/* line_width */,
    int			/* line_style */,
    int			/* cap_style */,
    int			/* join_style */
);

EXTERN int XSetModifierMapping(
    Display*		/* display */,
    XModifierKeymap*	/* modmap */
);

EXTERN int XSetPlaneMask(
    Display*		/* display */,
    GC			/* gc */,
    unsigned long	/* plane_mask */
);

EXTERN int XSetPointerMapping(
    Display*		/* display */,
    _Xconst unsigned char*	/* map */,
    int			/* nmap */
);

EXTERN int XSetScreenSaver(
    Display*		/* display */,
    int			/* timeout */,
    int			/* interval */,
    int			/* prefer_blanking */,
    int			/* allow_exposures */
);

EXTERN int XSetSelectionOwner(
    Display*		/* display */,
    Atom	        /* selection */,
    Window		/* owner */,
    Time		/* time */
);

EXTERN int XSetState(
    Display*		/* display */,
    GC			/* gc */,
    unsigned long 	/* foreground */,
    unsigned long	/* background */,
    int			/* function */,
    unsigned long	/* plane_mask */
);

EXTERN int XSetStipple(
    Display*		/* display */,
    GC			/* gc */,
    Pixmap		/* stipple */
);

EXTERN int XSetSubwindowMode(
    Display*		/* display */,
    GC			/* gc */,
    int			/* subwindow_mode */
);

EXTERN int XSetTSOrigin(
    Display*		/* display */,
    GC			/* gc */,
    int			/* ts_x_origin */,
    int			/* ts_y_origin */
);

EXTERN int XSetTile(
    Display*		/* display */,
    GC			/* gc */,
    Pixmap		/* tile */
);

EXTERN int XSetWindowBackground(
    Display*		/* display */,
    Window		/* w */,
    unsigned long	/* background_pixel */
);

EXTERN int XSetWindowBackgroundPixmap(
    Display*		/* display */,
    Window		/* w */,
    Pixmap		/* background_pixmap */
);

EXTERN int XSetWindowBorder(
    Display*		/* display */,
    Window		/* w */,
    unsigned long	/* border_pixel */
);

EXTERN int XSetWindowBorderPixmap(
    Display*		/* display */,
    Window		/* w */,
    Pixmap		/* border_pixmap */
);

EXTERN int XSetWindowBorderWidth(
    Display*		/* display */,
    Window		/* w */,
    unsigned int	/* width */
);

EXTERN int XSetWindowColormap(
    Display*		/* display */,
    Window		/* w */,
    Colormap		/* colormap */
);

EXTERN int XStoreBuffer(
    Display*		/* display */,
    _Xconst char*	/* bytes */,
    int			/* nbytes */,
    int			/* buffer */
);

EXTERN int XStoreBytes(
    Display*		/* display */,
    _Xconst char*	/* bytes */,
    int			/* nbytes */
);

EXTERN int XStoreColor(
    Display*		/* display */,
    Colormap		/* colormap */,
    XColor*		/* color */
);

EXTERN int XStoreColors(
    Display*		/* display */,
    Colormap		/* colormap */,
    XColor*		/* color */,
    int			/* ncolors */
);

EXTERN int XStoreName(
    Display*		/* display */,
    Window		/* w */,
    _Xconst char*	/* window_name */
);

EXTERN int XStoreNamedColor(
    Display*		/* display */,
    Colormap		/* colormap */,
    _Xconst char*	/* color */,
    unsigned long	/* pixel */,
    int			/* flags */
);

EXTERN int XSync(
    Display*		/* display */,
    Bool		/* discard */
);

EXTERN int XTextExtents(
    XFontStruct*	/* font_struct */,
    _Xconst char*	/* string */,
    int			/* nchars */,
    int*		/* direction_return */,
    int*		/* font_ascent_return */,
    int*		/* font_descent_return */,
    XCharStruct*	/* overall_return */
);

EXTERN int XTextExtents16(
    XFontStruct*	/* font_struct */,
    _Xconst XChar2b*	/* string */,
    int			/* nchars */,
    int*		/* direction_return */,
    int*		/* font_ascent_return */,
    int*		/* font_descent_return */,
    XCharStruct*	/* overall_return */
);

EXTERN int XTextWidth(
    XFontStruct*	/* font_struct */,
    _Xconst char*	/* string */,
    int			/* count */
);

EXTERN int XTextWidth16(
    XFontStruct*	/* font_struct */,
    _Xconst XChar2b*	/* string */,
    int			/* count */
);

EXTERN Bool XTranslateCoordinates(
    Display*		/* display */,
    Window		/* src_w */,
    Window		/* dest_w */,
    int			/* src_x */,
    int			/* src_y */,
    int*		/* dest_x_return */,
    int*		/* dest_y_return */,
    Window*		/* child_return */
);

EXTERN int XUndefineCursor(
    Display*		/* display */,
    Window		/* w */
);

EXTERN int XUngrabButton(
    Display*		/* display */,
    unsigned int	/* button */,
    unsigned int	/* modifiers */,
    Window		/* grab_window */
);

EXTERN int XUngrabKey(
    Display*		/* display */,
    int			/* keycode */,
    unsigned int	/* modifiers */,
    Window		/* grab_window */
);

EXTERN int XUngrabKeyboard(
    Display*		/* display */,
    Time		/* time */
);

EXTERN int XUngrabPointer(
    Display*		/* display */,
    Time		/* time */
);

EXTERN int XUngrabServer(
    Display*		/* display */
);

EXTERN int XUninstallColormap(
    Display*		/* display */,
    Colormap		/* colormap */
);

EXTERN int XUnloadFont(
    Display*		/* display */,
    Font		/* font */
);

EXTERN int XUnmapSubwindows(
    Display*		/* display */,
    Window		/* w */
);

EXTERN int XUnmapWindow(
    Display*		/* display */,
    Window		/* w */
);

EXTERN int XVendorRelease(
    Display*		/* display */
);

EXTERN int XWarpPointer(
    Display*		/* display */,
    Window		/* src_w */,
    Window		/* dest_w */,
    int			/* src_x */,
    int			/* src_y */,
    unsigned int	/* src_width */,
    unsigned int	/* src_height */,
    int			/* dest_x */,
    int			/* dest_y */
);

EXTERN int XWidthMMOfScreen(
    Screen*		/* screen */
);

EXTERN int XWidthOfScreen(
    Screen*		/* screen */
);

EXTERN int XWindowEvent(
    Display*		/* display */,
    Window		/* w */,
    long		/* event_mask */,
    XEvent*		/* event_return */
);

EXTERN int XWriteBitmapFile(
    Display*		/* display */,
    _Xconst char*	/* filename */,
    Pixmap		/* bitmap */,
    unsigned int	/* width */,
    unsigned int	/* height */,
    int			/* x_hot */,
    int			/* y_hot */
);

EXTERN Bool XSupportsLocale (void);

EXTERN char *XSetLocaleModifiers(
    const char*		/* modifier_list */
);

EXTERN XOM XOpenOM(
    Display*			/* display */,
    struct _XrmHashBucketRec*	/* rdb */,
    _Xconst char*		/* res_name */,
    _Xconst char*		/* res_class */
);

EXTERN Status XCloseOM(
    XOM			/* om */
);

EXTERN char *XSetOMValues(
    XOM			/* om */,
    ...
) _X_SENTINEL(0);

EXTERN char *XGetOMValues(
    XOM			/* om */,
    ...
) _X_SENTINEL(0);

EXTERN Display *XDisplayOfOM(
    XOM			/* om */
);

EXTERN char *XLocaleOfOM(
    XOM			/* om */
);

EXTERN XOC XCreateOC(
    XOM			/* om */,
    ...
) _X_SENTINEL(0);

EXTERN void XDestroyOC(
    XOC			/* oc */
);

EXTERN XOM XOMOfOC(
    XOC			/* oc */
);

EXTERN char *XSetOCValues(
    XOC			/* oc */,
    ...
) _X_SENTINEL(0);

EXTERN char *XGetOCValues(
    XOC			/* oc */,
    ...
) _X_SENTINEL(0);

EXTERN XFontSet XCreateFontSet(
    Display*		/* display */,
    _Xconst char*	/* base_font_name_list */,
    char***		/* missing_charset_list */,
    int*		/* missing_charset_count */,
    char**		/* def_string */
);

EXTERN void XFreeFontSet(
    Display*		/* display */,
    XFontSet		/* font_set */
);

EXTERN int XFontsOfFontSet(
    XFontSet		/* font_set */,
    XFontStruct***	/* font_struct_list */,
    char***		/* font_name_list */
);

EXTERN char *XBaseFontNameListOfFontSet(
    XFontSet		/* font_set */
);

EXTERN char *XLocaleOfFontSet(
    XFontSet		/* font_set */
);

EXTERN Bool XContextDependentDrawing(
    XFontSet		/* font_set */
);

EXTERN Bool XDirectionalDependentDrawing(
    XFontSet		/* font_set */
);

EXTERN Bool XContextualDrawing(
    XFontSet		/* font_set */
);

EXTERN XFontSetExtents *XExtentsOfFontSet(
    XFontSet		/* font_set */
);

EXTERN int XmbTextEscapement(
    XFontSet		/* font_set */,
    _Xconst char*	/* text */,
    int			/* bytes_text */
);

EXTERN int XwcTextEscapement(
    XFontSet		/* font_set */,
    _Xconst wchar_t*	/* text */,
    int			/* num_wchars */
);

EXTERN int Xutf8TextEscapement(
    XFontSet		/* font_set */,
    _Xconst char*	/* text */,
    int			/* bytes_text */
);

EXTERN int XmbTextExtents(
    XFontSet		/* font_set */,
    _Xconst char*	/* text */,
    int			/* bytes_text */,
    XRectangle*		/* overall_ink_return */,
    XRectangle*		/* overall_logical_return */
);

EXTERN int XwcTextExtents(
    XFontSet		/* font_set */,
    _Xconst wchar_t*	/* text */,
    int			/* num_wchars */,
    XRectangle*		/* overall_ink_return */,
    XRectangle*		/* overall_logical_return */
);

EXTERN int Xutf8TextExtents(
    XFontSet		/* font_set */,
    _Xconst char*	/* text */,
    int			/* bytes_text */,
    XRectangle*		/* overall_ink_return */,
    XRectangle*		/* overall_logical_return */
);

EXTERN Status XmbTextPerCharExtents(
    XFontSet		/* font_set */,
    _Xconst char*	/* text */,
    int			/* bytes_text */,
    XRectangle*		/* ink_extents_buffer */,
    XRectangle*		/* logical_extents_buffer */,
    int			/* buffer_size */,
    int*		/* num_chars */,
    XRectangle*		/* overall_ink_return */,
    XRectangle*		/* overall_logical_return */
);

EXTERN Status XwcTextPerCharExtents(
    XFontSet		/* font_set */,
    _Xconst wchar_t*	/* text */,
    int			/* num_wchars */,
    XRectangle*		/* ink_extents_buffer */,
    XRectangle*		/* logical_extents_buffer */,
    int			/* buffer_size */,
    int*		/* num_chars */,
    XRectangle*		/* overall_ink_return */,
    XRectangle*		/* overall_logical_return */
);

EXTERN Status Xutf8TextPerCharExtents(
    XFontSet		/* font_set */,
    _Xconst char*	/* text */,
    int			/* bytes_text */,
    XRectangle*		/* ink_extents_buffer */,
    XRectangle*		/* logical_extents_buffer */,
    int			/* buffer_size */,
    int*		/* num_chars */,
    XRectangle*		/* overall_ink_return */,
    XRectangle*		/* overall_logical_return */
);

EXTERN void XmbDrawText(
    Display*		/* display */,
    Drawable		/* d */,
    GC			/* gc */,
    int			/* x */,
    int			/* y */,
    XmbTextItem*	/* text_items */,
    int			/* nitems */
);

EXTERN void XwcDrawText(
    Display*		/* display */,
    Drawable		/* d */,
    GC			/* gc */,
    int			/* x */,
    int			/* y */,
    XwcTextItem*	/* text_items */,
    int			/* nitems */
);

EXTERN void Xutf8DrawText(
    Display*		/* display */,
    Drawable		/* d */,
    GC			/* gc */,
    int			/* x */,
    int			/* y */,
    XmbTextItem*	/* text_items */,
    int			/* nitems */
);

EXTERN void XmbDrawString(
    Display*		/* display */,
    Drawable		/* d */,
    XFontSet		/* font_set */,
    GC			/* gc */,
    int			/* x */,
    int			/* y */,
    _Xconst char*	/* text */,
    int			/* bytes_text */
);

EXTERN void XwcDrawString(
    Display*		/* display */,
    Drawable		/* d */,
    XFontSet		/* font_set */,
    GC			/* gc */,
    int			/* x */,
    int			/* y */,
    _Xconst wchar_t*	/* text */,
    int			/* num_wchars */
);

EXTERN void Xutf8DrawString(
    Display*		/* display */,
    Drawable		/* d */,
    XFontSet		/* font_set */,
    GC			/* gc */,
    int			/* x */,
    int			/* y */,
    _Xconst char*	/* text */,
    int			/* bytes_text */
);

EXTERN void XmbDrawImageString(
    Display*		/* display */,
    Drawable		/* d */,
    XFontSet		/* font_set */,
    GC			/* gc */,
    int			/* x */,
    int			/* y */,
    _Xconst char*	/* text */,
    int			/* bytes_text */
);

EXTERN void XwcDrawImageString(
    Display*		/* display */,
    Drawable		/* d */,
    XFontSet		/* font_set */,
    GC			/* gc */,
    int			/* x */,
    int			/* y */,
    _Xconst wchar_t*	/* text */,
    int			/* num_wchars */
);

EXTERN void Xutf8DrawImageString(
    Display*		/* display */,
    Drawable		/* d */,
    XFontSet		/* font_set */,
    GC			/* gc */,
    int			/* x */,
    int			/* y */,
    _Xconst char*	/* text */,
    int			/* bytes_text */
);

EXTERN XIM XOpenIM(
    Display*			/* dpy */,
    struct _XrmHashBucketRec*	/* rdb */,
    char*			/* res_name */,
    char*			/* res_class */
);

EXTERN Status XCloseIM(
    XIM /* im */
);

EXTERN char *XGetIMValues(
    XIM /* im */, ...
) _X_SENTINEL(0);

EXTERN char *XSetIMValues(
    XIM /* im */, ...
) _X_SENTINEL(0);

EXTERN Display *XDisplayOfIM(
    XIM /* im */
);

EXTERN char *XLocaleOfIM(
    XIM /* im*/
);

EXTERN XIC XCreateIC(
    XIM /* im */, ...
) _X_SENTINEL(0);

EXTERN void XDestroyIC(
    XIC /* ic */
);

EXTERN void XSetICFocus(
    XIC /* ic */
);

EXTERN void XUnsetICFocus(
    XIC /* ic */
);

EXTERN wchar_t *XwcResetIC(
    XIC /* ic */
);

EXTERN char *XmbResetIC(
    XIC /* ic */
);

EXTERN char *Xutf8ResetIC(
    XIC /* ic */
);

EXTERN char *XSetICValues(
    XIC /* ic */, ...
) _X_SENTINEL(0);

EXTERN char *XGetICValues(
    XIC /* ic */, ...
) _X_SENTINEL(0);

EXTERN XIM XIMOfIC(
    XIC /* ic */
);

EXTERN Bool XFilterEvent(
    XEvent*	/* event */,
    Window	/* window */
);

EXTERN int XmbLookupString(
    XIC			/* ic */,
    XKeyPressedEvent*	/* event */,
    char*		/* buffer_return */,
    int			/* bytes_buffer */,
    KeySym*		/* keysym_return */,
    Status*		/* status_return */
);

EXTERN int XwcLookupString(
    XIC			/* ic */,
    XKeyPressedEvent*	/* event */,
    wchar_t*		/* buffer_return */,
    int			/* wchars_buffer */,
    KeySym*		/* keysym_return */,
    Status*		/* status_return */
);

EXTERN int Xutf8LookupString(
    XIC			/* ic */,
    XKeyPressedEvent*	/* event */,
    char*		/* buffer_return */,
    int			/* bytes_buffer */,
    KeySym*		/* keysym_return */,
    Status*		/* status_return */
);

EXTERN XVaNestedList XVaCreateNestedList(
    int /*unused*/, ...
) _X_SENTINEL(0);

/* internal connections for IMs */

EXTERN Bool XRegisterIMInstantiateCallback(
    Display*			/* dpy */,
    struct _XrmHashBucketRec*	/* rdb */,
    char*			/* res_name */,
    char*			/* res_class */,
    XIDProc			/* callback */,
    XPointer			/* client_data */
);

EXTERN Bool XUnregisterIMInstantiateCallback(
    Display*			/* dpy */,
    struct _XrmHashBucketRec*	/* rdb */,
    char*			/* res_name */,
    char*			/* res_class */,
    XIDProc			/* callback */,
    XPointer			/* client_data */
);

typedef void (*XConnectionWatchProc)(
    Display*			/* dpy */,
    XPointer			/* client_data */,
    int				/* fd */,
    Bool			/* opening */,	 /* open or close flag */
    XPointer*			/* watch_data */ /* open sets, close uses */
);


EXTERN Status XInternalConnectionNumbers(
    Display*			/* dpy */,
    int**			/* fd_return */,
    int*			/* count_return */
);

EXTERN void XProcessInternalConnection(
    Display*			/* dpy */,
    int				/* fd */
);

EXTERN Status XAddConnectionWatch(
    Display*			/* dpy */,
    XConnectionWatchProc	/* callback */,
    XPointer			/* client_data */
);

EXTERN void XRemoveConnectionWatch(
    Display*			/* dpy */,
    XConnectionWatchProc	/* callback */,
    XPointer			/* client_data */
);

EXTERN void XSetAuthorization(
    char *			/* name */,
    int				/* namelen */,
    char *			/* data */,
    int				/* datalen */
);

EXTERN int _Xmbtowc(
    wchar_t *			/* wstr */,
    char *			/* str */,
    int				/* len */
);

EXTERN int _Xwctomb(
    char *			/* str */,
    wchar_t			/* wc */
);

EXTERN Bool XGetEventData(
    Display*			/* dpy */,
    XGenericEventCookie*	/* cookie*/
);

EXTERN void XFreeEventData(
    Display*			/* dpy */,
    XGenericEventCookie*	/* cookie*/
);

#include "tkIntXlibDecls.h"

_XFUNCPROTOEND

#ifdef __clang__
#pragma clang diagnostic pop
#if defined(MAC_OSX_TK)
#   undef Cursor
#   undef Region
#endif

_XFUNCPROTOEND

#endif /* _XLIB_H_ */
#endif /* _X11_XLIB_H_ */
Changes to xlib/X11/Xutil.h.
1
2
3
























4

5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28


29
30


31



32

33


34
35
36
37
38
39
40

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

27

28
29
30
31
32
33
34

35
36
37
38
39
40
41
42
43
44
45
46
47
48


49
50
51
52
53
54
55
56
57
58

59

60
61
62
63
64
65
66
67
68
-


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-







-
+













-
-
+
+


+
+

+
+
+
-
+
-
+
+







/* $XConsortium: Xutil.h,v 11.73 91/07/30 16:21:37 rws Exp $ */

/***********************************************************

Copyright 1987, 1998  The Open Group

Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.


Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
and the Massachusetts Institute of Technology, Cambridge, Massachusetts.

                        All Rights Reserved

Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the names of Digital or MIT not be
supporting documentation, and that the name of Digital not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.

DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.

******************************************************************/

#ifndef _XUTIL_H_
#define _XUTIL_H_
#ifndef _X11_XUTIL_H_
#define _X11_XUTIL_H_

/* You must include <X11/Xlib.h> before including this file */
#include <X11/Xlib.h>
#include <X11/keysym.h>

/* The Xlib structs are full of implicit padding to properly align members.
   We can't clean that up without breaking ABI, so tell clang not to bother
   complaining about it. */
#if defined(MAC_OSX_TK)
#ifdef __clang__
#   define Region XRegion
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wpadded"
#endif

/*
 * Bitmask returned by XParseGeometry().  Each bit tells if the corresponding
 * value (x, y, width, height) was found in the parsed string.
 */
#define NoValue		0x0000
108
109
110
111
112
113
114

115
116
117
118
119
120
121
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150







+







#define IconPixmapHint		(1L << 2)
#define IconWindowHint		(1L << 3)
#define IconPositionHint 	(1L << 4)
#define IconMaskHint		(1L << 5)
#define WindowGroupHint		(1L << 6)
#define AllHints (InputHint|StateHint|IconPixmapHint|IconWindowHint| \
IconPositionHint|IconMaskHint|WindowGroupHint)
#define XUrgencyHint		(1L << 8)

/* definitions for initial window state */
#define WithdrawnState 0	/* for windows that are not mapped */
#define NormalState 1	/* most applications want to start this way */
#define IconicState 3	/* application wants to start as an icon */

/*
142
143
144
145
146
147
148
149



150
151
152
153
154
155
156
157
158
159
160
161
162
































163
164
165
166
167
168
169
170
171
172
173
174
175
176

177
178
179
180
181
182
183
184
185
186
187
188
189
190

191



192
193

194
195
196

197
198
199

200
201
202

203

204
205
206
207











208
209
210
211
212
213
214
171
172
173
174
175
176
177

178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253

254
255
256
257
258
259

260
261
262

263
264
265

266
267
268

269
270
271
272



273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290







-
+
+
+













+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+














+













-
+

+
+
+

-
+


-
+


-
+


-
+

+

-
-
-
+
+
+
+
+
+
+
+
+
+
+







#define XLocaleNotSupported -2
#define XConverterNotFound -3

typedef enum {
    XStringStyle,		/* STRING */
    XCompoundTextStyle,		/* COMPOUND_TEXT */
    XTextStyle,			/* text in owner's encoding (current locale)*/
    XStdICCTextStyle		/* STRING, else COMPOUND_TEXT */
    XStdICCTextStyle,		/* STRING, else COMPOUND_TEXT */
    /* The following is an XFree86 extension, introduced in November 2000 */
    XUTF8StringStyle		/* UTF8_STRING */
} XICCEncodingStyle;

typedef struct {
	int min_width, min_height;
	int max_width, max_height;
	int width_inc, height_inc;
} XIconSize;

typedef struct {
	char *res_name;
	char *res_class;
} XClassHint;

#ifndef EXTERN
#   define EXTERN extern TCL_STORAGE_CLASS
#endif
#if defined(STATIC_BUILD) || !defined(_WIN32)
# ifndef TCL_STORAGE_CLASS
#   define TCL_STORAGE_CLASS
# endif
#elif defined(BUILD_tk)
# undef TCL_STORAGE_CLASS
# define TCL_STORAGE_CLASS __declspec(dllexport)
#elif !defined(TCL_STORAGE_CLASS)
# define TCL_STORAGE_CLASS __declspec(dllimport)
#endif

#ifdef XUTIL_DEFINE_FUNCTIONS
EXTERN int XDestroyImage(
        XImage *ximage);
EXTERN unsigned long XGetPixel(
        XImage *ximage,
        int x, int y);
EXTERN int XPutPixel(
        XImage *ximage,
        int x, int y,
        unsigned long pixel);
EXTERN XImage *XSubImage(
        XImage *ximage,
        int x, int y,
        unsigned int width, unsigned int height);
EXTERN int XAddPixel(
        XImage *ximage,
        long value);
#else
/*
 * These macros are used to give some sugar to the image routines so that
 * naive people are more comfortable with them.
 */
#define XDestroyImage(ximage) \
	((*((ximage)->f.destroy_image))((ximage)))
#define XGetPixel(ximage, x, y) \
	((*((ximage)->f.get_pixel))((ximage), (x), (y)))
#define XPutPixel(ximage, x, y, pixel) \
	((*((ximage)->f.put_pixel))((ximage), (x), (y), (pixel)))
#define XSubImage(ximage, x, y, width, height)  \
	((*((ximage)->f.sub_image))((ximage), (x), (y), (width), (height)))
#define XAddPixel(ximage, value) \
	((*((ximage)->f.add_pixel))((ximage), (value)))
#endif

/*
 * Compose sequence status structure, used in calling XLookupString.
 */
typedef struct _XComposeStatus {
    XPointer compose_ptr;	/* state table pointer */
    int chars_matched;		/* match state */
} XComposeStatus;

/*
 * Keysym macros, used on Keysyms to test for classes of symbols
 */
#define IsKeypadKey(keysym) \
  (((unsigned)(keysym) >= XK_KP_Space) && ((unsigned)(keysym) <= XK_KP_Equal))
  (((KeySym)(keysym) >= XK_KP_Space) && ((KeySym)(keysym) <= XK_KP_Equal))

#define IsPrivateKeypadKey(keysym) \
  (((KeySym)(keysym) >= 0x11000000) && ((KeySym)(keysym) <= 0x1100FFFF))

#define IsCursorKey(keysym) \
  (((unsigned)(keysym) >= XK_Home)     && ((unsigned)(keysym) <  XK_Select))
  (((KeySym)(keysym) >= XK_Home)     && ((KeySym)(keysym) <  XK_Select))

#define IsPFKey(keysym) \
  (((unsigned)(keysym) >= XK_KP_F1)     && ((unsigned)(keysym) <= XK_KP_F4))
  (((KeySym)(keysym) >= XK_KP_F1)     && ((KeySym)(keysym) <= XK_KP_F4))

#define IsFunctionKey(keysym) \
  (((unsigned)(keysym) >= XK_F1)       && ((unsigned)(keysym) <= XK_F35))
  (((KeySym)(keysym) >= XK_F1)       && ((KeySym)(keysym) <= XK_F35))

#define IsMiscFunctionKey(keysym) \
  (((unsigned)(keysym) >= XK_Select)   && ((unsigned)(keysym) <= XK_Break))
  (((KeySym)(keysym) >= XK_Select)   && ((KeySym)(keysym) <= XK_Break))

#ifdef XK_XKB_KEYS
#define IsModifierKey(keysym) \
  ((((unsigned)(keysym) >= XK_Shift_L) && ((unsigned)(keysym) <= XK_Hyper_R)) \
   || ((unsigned)(keysym) == XK_Mode_switch) \
   || ((unsigned)(keysym) == XK_Num_Lock))
  ((((KeySym)(keysym) >= XK_Shift_L) && ((KeySym)(keysym) <= XK_Hyper_R)) \
   || (((KeySym)(keysym) >= XK_ISO_Lock) && \
       ((KeySym)(keysym) <= XK_ISO_Level5_Lock)) \
   || ((KeySym)(keysym) == XK_Mode_switch) \
   || ((KeySym)(keysym) == XK_Num_Lock))
#else
#define IsModifierKey(keysym) \
  ((((KeySym)(keysym) >= XK_Shift_L) && ((KeySym)(keysym) <= XK_Hyper_R)) \
   || ((KeySym)(keysym) == XK_Mode_switch) \
   || ((KeySym)(keysym) == XK_Num_Lock))
#endif
/*
 * opaque reference to Region data type
 */
typedef struct _XRegion *Region;

/* Return values from XRectInRegion() */

297
298
299
300
301
302
303
304

305
306
307
308
309
310

311
312
313
314
315
316

317
318
319
320
321
322

323
324
325
326
327
328

329
330
331
332
333
334

335
336
337
338
339
340
341

342
343
344
345
346
347

348
349
350
351
352
353

354
355
356
357
358
359
360
361

362
363
364
365
366
367

368
369
370
371
372
373

374
375
376
377
378
379
380

381
382
383
384
385
386
387
388
389

390
391
392
393
394
395
396
397

398
399
400
401
402
403
404
405
406

407
408
409
410
411
412
413
414

415
416
417
418
419
420
421
422
423
424

425
426
427
428
429
430
431
432
433

434
435
436
437
438
439
440
441
442

443
444
445
446
447
448
449
450






451
452

453
454
455
456
457
458
459
460

461
462
463
464
465
466
467

468
469
470
471
472
473
474
475

476
477
478
479
480
481
482
483

484
485
486
487
488
489
490
491
492

493
494
495
496
497
498
499
500
501
502

503
504
505
506
507
508
509
510

511
512
513
514

515





516
517
518

519
520
521
522
523
524
525
526
527
528

529
530
531
532
533
534
535
536
537
538

539
540
541
542
543
544
545
546

547
548
549
550
551
552
553
554

555
556
557
558
559
560
561
562

563
564
565
566
567
568
569
570
571
572

573
574
575
576
577
578
579
580
581

582
583
584
585
586
587
588
589

590
591
592
593
594
595
596
597
598

599
600
601
602
603
604
605
606

607
608
609
610
611
612
613
614
615
616

617
618
619
620
621
622
623
624
625

626
627
628
629
630
631
632
633
634
635
636
637
638

639
640
641
642
643

644





645
646
647

648
649
650
651
652
653
654
655

656
657
658
659
660
661
662
663

664
665
666
667
668
669
670
671

672
673
674
675
676
677
678
679

680
681
682
683
684
685
686
687
688
689
690
691
692
693
694













695
696
697
698
699
700
701
702
703
704
705
706
707

708
709
710
711
712
713
714
715
716

717
718
719
720
721
722
723
724

725
726
727
728
729
730
731
732
733

734
735
736
737
738
739
740
741

742
743
744
745

746





747
748
749

750
751
752
753
754
755
756
757

758
759
760
761
762
763





764
765
766
767

768
769
770
771
772
773





774
775
776


777
778
779








780
781
782
783

784
785
786
787
788
789
790
791

792
793
794
795
796




797
798
799
800

801
802
803
804
805
806











807
808
809

810
811
812
813
814
815
816
817

818
819
820
821
822
823
824
825

826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841

842
843
844
845
846
847




848
849
850
851
852
853
854
855

373
374
375
376
377
378
379

380

381

382
383

384

385

386
387

388

389

390
391

392

393

394
395

396

397

398
399

400

401
402

403
404

405

406

407
408

409




410

411

412
413
414

415
416

417

418

419
420

421

422

423
424

425

426
427

428
429

430

431
432
433
434

435
436

437

438
439
440

441
442

443

444
445
446
447

448
449

450

451
452
453

454
455

456

457
458
459
460
461

462
463

464

465
466
467
468

469
470

471

472
473
474
475

476
477

478

479
480
481
482

483
484
485
486
487
488
489
490
491

492

493
494
495

496
497

498

499
500

501
502

503

504
505
506

507
508

509

510
511
512

513
514

515

516
517
518
519

520
521

522

523
524
525
526
527

528
529

530

531
532
533

534
535

536

537
538
539
540

541
542
543
544
545
546
547

548

549
550
551
552
553

554
555

556

557
558
559
560
561

562
563

564

565
566
567

568
569

570

571
572
573

574
575

576

577
578
579

580
581

582

583
584
585
586
587

588
589

590

591
592
593
594

595
596

597

598
599
600

601
602

603

604
605
606
607

608
609

610

611
612
613

614
615

616

617
618
619
620
621

622
623

624

625
626
627
628

629
630

631

632
633
634
635
636
637
638
639

640
641

642

643
644
645
646
647

648
649
650
651
652
653
654

655

656
657
658

659
660

661

662
663
664

665
666

667

668
669
670

671
672

673

674
675
676

677
678

679

680
681
682
683
684
685
686
687
688

689
690


691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712

713
714

715

716
717
718
719

720
721

722

723
724
725

726
727

728

729
730
731
732

733
734

735

736
737
738

739
740

741

742
743
744
745

746
747
748
749
750
751
752

753

754
755
756

757
758

759






760
761
762
763
764

765
766

767






768
769
770
771
772

773
774
775
776



777
778
779
780
781
782
783
784

785
786

787

788
789
790

791
792

793





794
795
796
797

798
799

800






801
802
803
804
805
806
807
808
809
810
811
812
813

814

815
816
817

818
819

820

821
822
823

824
825

826

827
828
829
830
831
832
833
834
835
836
837

838
839

840

841
842
843

844
845
846
847
848
849
850
851





852







-
+
-

-


-
+
-

-


-
+
-

-


-
+
-

-


-
+
-

-


-
+
-


-


-
+
-

-


-
+
-
-
-
-

-
+
-



-


-
+
-

-


-
+
-

-


-
+
-


-


-
+
-




-


-
+
-



-


-
+
-




-


-
+
-



-


-
+
-





-


-
+
-




-


-
+
-




-


-
+
-




-


+
+
+
+
+
+

-
+
-



-


-
+
-


-


-
+
-



-


-
+
-



-


-
+
-




-


-
+
-





-


-
+
-



-


-
+
-



+
-
+
+
+
+
+


-
+
-





-


-
+
-





-


-
+
-



-


-
+
-



-


-
+
-



-


-
+
-





-


-
+
-




-


-
+
-



-


-
+
-




-


-
+
-



-


-
+
-





-


-
+
-




-


-
+
-








-


-
+
-




+
-
+
+
+
+
+


-
+
-



-


-
+
-



-


-
+
-



-


-
+
-



-


-
+
-









-


-
-
+
+
+
+
+
+
+
+
+
+
+
+
+









-


-
+
-




-


-
+
-



-


-
+
-




-


-
+
-



-


-
+
-



+
-
+
+
+
+
+


-
+
-



-


-
+
-
-
-
-
-
-
+
+
+
+
+
-


-
+
-
-
-
-
-
-
+
+
+
+
+
-


+
+
-
-
-
+
+
+
+
+
+
+
+
-


-
+
-



-


-
+
-
-
-
-
-
+
+
+
+
-


-
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+


-
+
-



-


-
+
-



-


-
+
-











-


-
+
-



-

+
+
+
+



-
-
-
-
-
+
#define XUniqueContext()       ((XContext) XrmUniqueQuark())
#define XStringToContext(string)   ((XContext) XrmStringToQuark(string))

_XFUNCPROTOBEGIN

/* The following declarations are alphabetized. */

extern XClassHint *XAllocClassHint (
EXTERN XClassHint *XAllocClassHint (
#if NeedFunctionPrototypes
    void
#endif
);

extern XIconSize *XAllocIconSize (
EXTERN XIconSize *XAllocIconSize (
#if NeedFunctionPrototypes
    void
#endif
);

extern XSizeHints *XAllocSizeHints (
EXTERN XSizeHints *XAllocSizeHints (
#if NeedFunctionPrototypes
    void
#endif
);

extern XStandardColormap *XAllocStandardColormap (
EXTERN XStandardColormap *XAllocStandardColormap (
#if NeedFunctionPrototypes
    void
#endif
);

extern XWMHints *XAllocWMHints (
EXTERN XWMHints *XAllocWMHints (
#if NeedFunctionPrototypes
    void
#endif
);

extern void XClipBox(
EXTERN int XClipBox(
#if NeedFunctionPrototypes
    Region		/* r */,
    XRectangle*		/* rect_return */
#endif
);

extern Region XCreateRegion(
EXTERN Region XCreateRegion(
#if NeedFunctionPrototypes
    void
#endif
);

extern char *XDefaultString(
EXTERN const char *XDefaultString (void);
#if NeedFunctionPrototypes
    void
#endif
);

extern int XDeleteContext(
EXTERN int XDeleteContext(
#if NeedFunctionPrototypes
    Display*		/* display */,
    XID			/* rid */,
    XContext		/* context */
#endif
);

extern void XDestroyRegion(
EXTERN int XDestroyRegion(
#if NeedFunctionPrototypes
    Region		/* r */
#endif
);

extern Bool XEmptyRegion(
EXTERN int XEmptyRegion(
#if NeedFunctionPrototypes
    Region		/* r */
#endif
);

extern Bool XEqualRegion(
EXTERN int XEqualRegion(
#if NeedFunctionPrototypes
    Region		/* r1 */,
    Region		/* r2 */
#endif
);

extern int XFindContext(
EXTERN int XFindContext(
#if NeedFunctionPrototypes
    Display*		/* display */,
    XID			/* rid */,
    XContext		/* context */,
    XPointer*		/* data_return */
#endif
);

extern Status XGetClassHint(
EXTERN Status XGetClassHint(
#if NeedFunctionPrototypes
    Display*		/* display */,
    Window		/* w */,
    XClassHint*		/* class_hints_return */
#endif
);

extern Status XGetIconSizes(
EXTERN Status XGetIconSizes(
#if NeedFunctionPrototypes
    Display*		/* display */,
    Window		/* w */,
    XIconSize**		/* size_list_return */,
    int*		/* count_return */
#endif
);

extern Status XGetNormalHints(
EXTERN Status XGetNormalHints(
#if NeedFunctionPrototypes
    Display*		/* display */,
    Window		/* w */,
    XSizeHints*		/* hints_return */
#endif
);

extern Status XGetRGBColormaps(
EXTERN Status XGetRGBColormaps(
#if NeedFunctionPrototypes
    Display*		/* display */,
    Window		/* w */,
    XStandardColormap** /* stdcmap_return */,
    int*		/* count_return */,
    Atom		/* property */
#endif
);

extern Status XGetSizeHints(
EXTERN Status XGetSizeHints(
#if NeedFunctionPrototypes
    Display*		/* display */,
    Window		/* w */,
    XSizeHints*		/* hints_return */,
    Atom		/* property */
#endif
);

extern Status XGetStandardColormap(
EXTERN Status XGetStandardColormap(
#if NeedFunctionPrototypes
    Display*		/* display */,
    Window		/* w */,
    XStandardColormap*	/* colormap_return */,
    Atom		/* property */
#endif
);

extern Status XGetTextProperty(
EXTERN Status XGetTextProperty(
#if NeedFunctionPrototypes
    Display*		/* display */,
    Window		/* window */,
    XTextProperty*	/* text_prop_return */,
    Atom		/* property */
#endif
);

EXTERN XVisualInfo *XGetVisualInfo(
    Display*		/* display */,
    long		/* vinfo_mask */,
    XVisualInfo*	/* vinfo_template */,
    int*		/* nitems_return */
);

extern Status XGetWMClientMachine(
EXTERN Status XGetWMClientMachine(
#if NeedFunctionPrototypes
    Display*		/* display */,
    Window		/* w */,
    XTextProperty*	/* text_prop_return */
#endif
);

extern XWMHints *XGetWMHints(
EXTERN XWMHints *XGetWMHints(
#if NeedFunctionPrototypes
    Display*		/* display */,
    Window		/* w */
#endif
);

extern Status XGetWMIconName(
EXTERN Status XGetWMIconName(
#if NeedFunctionPrototypes
    Display*		/* display */,
    Window		/* w */,
    XTextProperty*	/* text_prop_return */
#endif
);

extern Status XGetWMName(
EXTERN Status XGetWMName(
#if NeedFunctionPrototypes
    Display*		/* display */,
    Window		/* w */,
    XTextProperty*	/* text_prop_return */
#endif
);

extern Status XGetWMNormalHints(
EXTERN Status XGetWMNormalHints(
#if NeedFunctionPrototypes
    Display*		/* display */,
    Window		/* w */,
    XSizeHints*		/* hints_return */,
    long*		/* supplied_return */
#endif
);

extern Status XGetWMSizeHints(
EXTERN Status XGetWMSizeHints(
#if NeedFunctionPrototypes
    Display*		/* display */,
    Window		/* w */,
    XSizeHints*		/* hints_return */,
    long*		/* supplied_return */,
    Atom		/* property */
#endif
);

extern Status XGetZoomHints(
EXTERN Status XGetZoomHints(
#if NeedFunctionPrototypes
    Display*		/* display */,
    Window		/* w */,
    XSizeHints*		/* zhints_return */
#endif
);

extern void XIntersectRegion(
EXTERN int XIntersectRegion(
#if NeedFunctionPrototypes
    Region		/* sra */,
    Region		/* srb */,
    Region		/* dr_return */
);
#endif

EXTERN void XConvertCase(
    KeySym		/* sym */,
    KeySym*		/* lower */,
    KeySym*		/* upper */
);

extern int XLookupString(
EXTERN int XLookupString(
#if NeedFunctionPrototypes
    XKeyEvent*		/* event_struct */,
    char*		/* buffer_return */,
    int			/* bytes_buffer */,
    KeySym*		/* keysym_return */,
    XComposeStatus*	/* status_in_out */
#endif
);

extern Status XMatchVisualInfo(
EXTERN Status XMatchVisualInfo(
#if NeedFunctionPrototypes
    Display*		/* display */,
    int			/* screen */,
    int			/* depth */,
    int			/* class */,
    XVisualInfo*	/* vinfo_return */
#endif
);

extern int XOffsetRegion(
EXTERN int XOffsetRegion(
#if NeedFunctionPrototypes
    Region		/* r */,
    int			/* dx */,
    int			/* dy */
#endif
);

extern Bool XPointInRegion(
EXTERN Bool XPointInRegion(
#if NeedFunctionPrototypes
    Region		/* r */,
    int			/* x */,
    int			/* y */
#endif
);

extern Region XPolygonRegion(
EXTERN Region XPolygonRegion(
#if NeedFunctionPrototypes
    XPoint*		/* points */,
    int			/* n */,
    int			/* fill_rule */
#endif
);

extern int XRectInRegion(
EXTERN int XRectInRegion(
#if NeedFunctionPrototypes
    Region		/* r */,
    int			/* x */,
    int			/* y */,
    unsigned int	/* width */,
    unsigned int	/* height */
#endif
);

extern int XSaveContext(
EXTERN int XSaveContext(
#if NeedFunctionPrototypes
    Display*		/* display */,
    XID			/* rid */,
    XContext		/* context */,
    _Xconst char*	/* data */
#endif
);

extern void XSetClassHint(
EXTERN int XSetClassHint(
#if NeedFunctionPrototypes
    Display*		/* display */,
    Window		/* w */,
    XClassHint*		/* class_hints */
#endif
);

extern void XSetIconSizes(
EXTERN int XSetIconSizes(
#if NeedFunctionPrototypes
    Display*		/* display */,
    Window		/* w */,
    XIconSize*		/* size_list */,
    int			/* count */
#endif
);

extern void XSetNormalHints(
EXTERN int XSetNormalHints(
#if NeedFunctionPrototypes
    Display*		/* display */,
    Window		/* w */,
    XSizeHints*		/* hints */
#endif
);

extern void XSetRGBColormaps(
EXTERN void XSetRGBColormaps(
#if NeedFunctionPrototypes
    Display*		/* display */,
    Window		/* w */,
    XStandardColormap*	/* stdcmaps */,
    int			/* count */,
    Atom		/* property */
#endif
);

extern void XSetSizeHints(
EXTERN int XSetSizeHints(
#if NeedFunctionPrototypes
    Display*		/* display */,
    Window		/* w */,
    XSizeHints*		/* hints */,
    Atom		/* property */
#endif
);

extern void XSetStandardProperties(
EXTERN int XSetStandardProperties(
#if NeedFunctionPrototypes
    Display*		/* display */,
    Window		/* w */,
    _Xconst char*	/* window_name */,
    _Xconst char*	/* icon_name */,
    Pixmap		/* icon_pixmap */,
    char**		/* argv */,
    int			/* argc */,
    XSizeHints*		/* hints */
#endif
);

extern void XSetTextProperty(
EXTERN void XSetTextProperty(
#if NeedFunctionPrototypes
    Display*		/* display */,
    Window		/* w */,
    XTextProperty*	/* text_prop */,
    Atom		/* property */
);
#endif

EXTERN void XSetWMClientMachine(
    Display*		/* display */,
    Window		/* w */,
    XTextProperty*	/* text_prop */
);

extern void XSetWMHints(
EXTERN int XSetWMHints(
#if NeedFunctionPrototypes
    Display*		/* display */,
    Window		/* w */,
    XWMHints*		/* wm_hints */
#endif
);

extern void XSetWMIconName(
EXTERN void XSetWMIconName(
#if NeedFunctionPrototypes
    Display*		/* display */,
    Window		/* w */,
    XTextProperty*	/* text_prop */
#endif
);

extern void XSetWMName(
EXTERN void XSetWMName(
#if NeedFunctionPrototypes
    Display*		/* display */,
    Window		/* w */,
    XTextProperty*	/* text_prop */
#endif
);

extern void XSetWMNormalHints(
EXTERN void XSetWMNormalHints(
#if NeedFunctionPrototypes
    Display*		/* display */,
    Window		/* w */,
    XSizeHints*		/* hints */
#endif
);

extern void XSetWMProperties(
EXTERN void XSetWMProperties(
#if NeedFunctionPrototypes
    Display*		/* display */,
    Window		/* w */,
    XTextProperty*	/* window_name */,
    XTextProperty*	/* icon_name */,
    char**		/* argv */,
    int			/* argc */,
    XSizeHints*		/* normal_hints */,
    XWMHints*		/* wm_hints */,
    XClassHint*		/* class_hints */
#endif
);

extern void XmbSetWMProperties(
#if NeedFunctionPrototypes
EXTERN void XmbSetWMProperties(
    Display*		/* display */,
    Window		/* w */,
    _Xconst char*	/* window_name */,
    _Xconst char*	/* icon_name */,
    char**		/* argv */,
    int			/* argc */,
    XSizeHints*		/* normal_hints */,
    XWMHints*		/* wm_hints */,
    XClassHint*		/* class_hints */
);

EXTERN void Xutf8SetWMProperties(
    Display*		/* display */,
    Window		/* w */,
    _Xconst char*	/* window_name */,
    _Xconst char*	/* icon_name */,
    char**		/* argv */,
    int			/* argc */,
    XSizeHints*		/* normal_hints */,
    XWMHints*		/* wm_hints */,
    XClassHint*		/* class_hints */
#endif
);

extern void XSetWMSizeHints(
EXTERN void XSetWMSizeHints(
#if NeedFunctionPrototypes
    Display*		/* display */,
    Window		/* w */,
    XSizeHints*		/* hints */,
    Atom		/* property */
#endif
);

extern void XSetRegion(
EXTERN int XSetRegion(
#if NeedFunctionPrototypes
    Display*		/* display */,
    GC			/* gc */,
    Region		/* r */
#endif
);

extern void XSetStandardColormap(
EXTERN void XSetStandardColormap(
#if NeedFunctionPrototypes
    Display*		/* display */,
    Window		/* w */,
    XStandardColormap*	/* colormap */,
    Atom		/* property */
#endif
);

extern void XSetZoomHints(
EXTERN int XSetZoomHints(
#if NeedFunctionPrototypes
    Display*		/* display */,
    Window		/* w */,
    XSizeHints*		/* zhints */
#endif
);

extern void XShrinkRegion(
EXTERN int XShrinkRegion(
#if NeedFunctionPrototypes
    Region		/* r */,
    int			/* dx */,
    int			/* dy */
);
#endif

EXTERN Status XStringListToTextProperty(
    char**		/* list */,
    int			/* count */,
    XTextProperty*	/* text_prop_return */
);

extern void XSubtractRegion(
EXTERN int XSubtractRegion(
#if NeedFunctionPrototypes
    Region		/* sra */,
    Region		/* srb */,
    Region		/* dr_return */
#endif
);

extern int XmbTextListToTextProperty(
EXTERN int XmbTextListToTextProperty(
#if NeedFunctionPrototypes
    Display*		/* display */,
    char**		/* list */,
    int			/* count */,
    XICCEncodingStyle	/* style */,
    XTextProperty*	/* text_prop_return */
    Display*		display,
    char**		list,
    int			count,
    XICCEncodingStyle	style,
    XTextProperty*	text_prop_return
#endif
);

extern int XwcTextListToTextProperty(
EXTERN int XwcTextListToTextProperty(
#if NeedFunctionPrototypes
    Display*		/* display */,
    wchar_t**		/* list */,
    int			/* count */,
    XICCEncodingStyle	/* style */,
    XTextProperty*	/* text_prop_return */
    Display*		display,
    wchar_t**		list,
    int			count,
    XICCEncodingStyle	style,
    XTextProperty*	text_prop_return
#endif
);

EXTERN int Xutf8TextListToTextProperty(
    Display*		display,
extern void XwcFreeStringList(
#if NeedFunctionPrototypes
    wchar_t**		/* list */
    char**		list,
    int			count,
    XICCEncodingStyle	style,
    XTextProperty*	text_prop_return
);

EXTERN void XwcFreeStringList(
    wchar_t**		list
#endif
);

extern Status XTextPropertyToStringList(
EXTERN Status XTextPropertyToStringList(
#if NeedFunctionPrototypes
    XTextProperty*	/* text_prop */,
    char***		/* list_return */,
    int*		/* count_return */
#endif
);

extern int XmbTextPropertyToTextList(
EXTERN int XmbTextPropertyToTextList(
#if NeedFunctionPrototypes
    Display*		/* display */,
    XTextProperty*	/* text_prop */,
    char***		/* list_return */,
    int*		/* count_return */
    Display*		display,
    const XTextProperty* text_prop,
    char***		list_return,
    int*		count_return
#endif
);

extern int XwcTextPropertyToTextList(
EXTERN int XwcTextPropertyToTextList(
#if NeedFunctionPrototypes
    Display*		/* display */,
    XTextProperty*	/* text_prop */,
    wchar_t***		/* list_return */,
    int*		/* count_return */
#endif
    Display*		display,
    const XTextProperty* text_prop,
    wchar_t***		list_return,
    int*		count_return
);

EXTERN int Xutf8TextPropertyToTextList(
    Display*		display,
    const XTextProperty* text_prop,
    char***		list_return,
    int*		count_return
);

extern void XUnionRectWithRegion(
EXTERN int XUnionRectWithRegion(
#if NeedFunctionPrototypes
    XRectangle*		/* rectangle */,
    Region		/* src_region */,
    Region		/* dest_region_return */
#endif
);

extern int XUnionRegion(
EXTERN int XUnionRegion(
#if NeedFunctionPrototypes
    Region		/* sra */,
    Region		/* srb */,
    Region		/* dr_return */
#endif
);

extern int XWMGeometry(
EXTERN int XWMGeometry(
#if NeedFunctionPrototypes
    Display*		/* display */,
    int			/* screen_number */,
    _Xconst char*	/* user_geometry */,
    _Xconst char*	/* default_geometry */,
    unsigned int	/* border_width */,
    XSizeHints*		/* hints */,
    int*		/* x_return */,
    int*		/* y_return */,
    int*		/* width_return */,
    int*		/* height_return */,
    int*		/* gravity_return */
#endif
);

extern void XXorRegion(
EXTERN int XXorRegion(
#if NeedFunctionPrototypes
    Region		/* sra */,
    Region		/* srb */,
    Region		/* dr_return */
#endif
);

#ifdef __clang__
#pragma clang diagnostic pop
#endif

_XFUNCPROTOEND

#if defined(MAC_OSX_TK)
#   undef Region
#endif

#endif /* _XUTIL_H_ */
#endif /* _X11_XUTIL_H_ */
Changes to xlib/X11/cursorfont.h.

1






























2
3
4
5
6
7
8
1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







/*
/* $XConsortium: cursorfont.h,v 1.2 88/09/06 16:44:27 jim Exp $ */

Copyright 1987, 1998  The Open Group

Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.

The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

Except as contained in this notice, the name of The Open Group shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from The Open Group.

*/

#ifndef _X11_CURSORFONT_H_
#define _X11_CURSORFONT_H_

#define XC_num_glyphs 154
#define XC_X_cursor 0
#define XC_arrow 2
#define XC_based_arrow_down 4
#define XC_based_arrow_up 6
#define XC_boat 8
#define XC_bogosity 10
73
74
75
76
77
78
79


103
104
105
106
107
108
109
110
111







+
+
#define XC_top_tee 140
#define XC_trek 142
#define XC_ul_angle 144
#define XC_umbrella 146
#define XC_ur_angle 148
#define XC_watch 150
#define XC_xterm 152

#endif /* _X11_CURSORFONT_H_ */
Changes to xlib/X11/keysym.h.

1


2





3
4

















5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

29
30
31
32



33













34
35

1

2
3
4
5
6
7
8
9


10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

27
28
29
30
31
32
33

34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
+
-
+
+

+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-







-
+















+




+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+


+
/***********************************************************
/* $XConsortium: keysym.h,v 1.13 91/03/13 20:09:49 rws Exp $ */

Copyright 1987, 1998  The Open Group

Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
/***********************************************************
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.


Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
and the Massachusetts Institute of Technology, Cambridge, Massachusetts.

                        All Rights Reserved

Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the names of Digital or MIT not be
supporting documentation, and that the name of Digital not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.

DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.

******************************************************************/

/* default keysyms */
#define XK_MISCELLANY
#define XK_XKB_KEYS
#define XK_LATIN1
#define XK_LATIN2
#define XK_LATIN3
#define XK_LATIN4
#define XK_LATIN8
#define XK_LATIN9
#define XK_CAUCASUS
#define XK_GREEK
#define XK_KATAKANA
#define XK_ARABIC
#define XK_CYRILLIC
#define XK_HEBREW
#define XK_THAI
#define XK_KOREAN
#define XK_ARMENIAN
#define XK_GEORGIAN
#define XK_VIETNAMESE
#define XK_CURRENCY
#define XK_MATHEMATICAL
#define XK_BRAILLE
#define XK_SINHALA

#include <X11/keysymdef.h>

Changes to xlib/X11/keysymdef.h.


1






2


3
4
















5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21
22
23
24
25
26


































































27

28
29
30
31

32
33

34
35
36
37
38
39
40
41
42
43
44
45










46
47
48
49
50
51





52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71






















72
73
74
75
76
77
78
79
80
81
82
83
84
85











86
87
88
89
90
91
92
93

94
95
96
97
98
99
100
101
102
103
104
105
106
107
108














109
110

111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138



























139
140
141
142
143
144
145
146
147
148
149










150
151
152
153
154
155


156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219




























































220
221
222
223
224
225
226
227
228






229
230
231
232
233
234
235
236
237








238
239
240














































































































































































































241
242



243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341

































































































342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441




































































































442
443
444
445
446


447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501




















































502
503
504
505
506





507
508
509
510
511


512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536






















537
538
539
540
541
542


543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581




































582
583











584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659






































































660
661
662
663
664


665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717


















































718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831













































































































832
833
834
835

836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914











































































915
916
917
918

919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971

















































972
973
974
975
976



977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
























1004
1005
1006
1007
1008




1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094




















































































1095
1096
1097
1098
1099


1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121



















1122
1123
1124
1125
1126

1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169








































1170
1171
















































































































































































































































1172
1173
1174
1175

1176
1177
1178
1179
1180
1181
1182

1183
1
2

3
4
5
6
7
8
9
10
11


12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

28
29
30
31
32
33
34

35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114

115
116
117
118

119
120

121
122
123










124
125
126
127
128
129
130
131
132
133
134
135
136
137
138

139
140
141
142
143
144
145
146

















147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171











172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189

190
191














192
193
194
195
196
197
198
199
200
201
202
203
204
205
206

207
208



























209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236










237
238
239
240
241
242
243
244
245
246
247
248
249
250


251
252
253
254
255
256




























































257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319






320
321
322
323
324
325
326








327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543


544
545
546
547
548

































































































549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646



































































































647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749


750
751
752
753
754




















































755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806





807
808
809
810
811
812
813
814


815
816
817
818
819






















820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845


846
847
848
849
850




































851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905






































































906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978


979
980
981
982
983


















































984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040











































































































1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158











































































1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242

















































1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294


1295
1296
1297
1298
1299
1300
























1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327


1328
1329
1330
1331
1332
1333
1334



















































































1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421


1422
1423
1424
1425
1426



















1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449

1450
1451
1452
1453








































1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
+
+
-
+
+
+
+
+
+

+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-







-
+













+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+



-
+

-
+


-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+





-
+
+
+
+
+



-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+







-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+




-
-
+
+




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
-
-
-
-
-
+
+
+
+
+
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+


-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
-
+
+



-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+



-
-
+
+



-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




-
-
+
+



-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


+
+
+
+
+
+
+
+
+
+
+






-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
-
+
+



-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




+




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




+




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
-
+
+
+



-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
-
+
+
+
+



-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
-
+
+



-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




-
+



-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




+







+

/***********************************************************
Copyright 1987, 1994, 1998  The Open Group
/* $XConsortium: keysymdef.h,v 1.15 93/04/02 10:57:36 rws Exp $ */

Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.

The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
/***********************************************************
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

Except as contained in this notice, the name of The Open Group shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from The Open Group.


Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts
and the Massachusetts Institute of Technology, Cambridge, Massachusetts.

                        All Rights Reserved

Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the names of Digital or MIT not be
supporting documentation, and that the name of Digital not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.

DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.

******************************************************************/

/*
 * The "X11 Window System Protocol" standard defines in Appendix A the
 * keysym codes. These 29-bit integer values identify characters or
 * functions associated with each key (e.g., via the visible
 * engraving) of a keyboard layout. This file assigns mnemonic macro
 * names for these keysyms.
 *
 * This file is also compiled (by src/util/makekeys.c in libX11) into
 * hash tables that can be accessed with X11 library functions such as
 * XStringToKeysym() and XKeysymToString().
 *
 * Where a keysym corresponds one-to-one to an ISO 10646 / Unicode
 * character, this is noted in a comment that provides both the U+xxxx
 * Unicode position, as well as the official Unicode name of the
 * character.
 *
 * Where the correspondence is either not one-to-one or semantically
 * unclear, the Unicode position and name are enclosed in
 * parentheses. Such legacy keysyms should be considered deprecated
 * and are not recommended for use in future keyboard mappings.
 *
 * For any future extension of the keysyms with characters already
 * found in ISO 10646 / Unicode, the following algorithm shall be
 * used. The new keysym code position will simply be the character's
 * Unicode number plus 0x01000000. The keysym values in the range
 * 0x01000100 to 0x0110ffff are reserved to represent Unicode
 * characters in the range U+0100 to U+10FFFF.
 *
 * While most newer Unicode-based X11 clients do already accept
 * Unicode-mapped keysyms in the range 0x01000100 to 0x0110ffff, it
 * will remain necessary for clients -- in the interest of
 * compatibility with existing servers -- to also understand the
 * existing legacy keysym values in the range 0x0100 to 0x20ff.
 *
 * Where several mnemonic names are defined for the same keysym in this
 * file, all but the first one listed should be considered deprecated.
 *
 * Mnemonic names for keysyms are defined in this file with lines
 * that match one of these Perl regular expressions:
 *
 *    /^\#define XK_([a-zA-Z_0-9]+)\s+0x([0-9a-f]+)\s*\/\* U+([0-9A-F]{4,6}) (.*) \*\/\s*$/
 *    /^\#define XK_([a-zA-Z_0-9]+)\s+0x([0-9a-f]+)\s*\/\*\(U+([0-9A-F]{4,6}) (.*)\)\*\/\s*$/
 *    /^\#define XK_([a-zA-Z_0-9]+)\s+0x([0-9a-f]+)\s*(\/\*\s*(.*)\s*\*\/)?\s*$/
 *
 * Before adding new keysyms, please do consider the following: In
 * addition to the keysym names defined in this file, the
 * XStringToKeysym() and XKeysymToString() functions will also handle
 * any keysym string of the form "U0020" to "U007E" and "U00A0" to
 * "U10FFFF" for all possible Unicode characters. In other words,
 * every possible Unicode character has already a keysym string
 * defined algorithmically, even if it is not listed here. Therefore,
 * defining an additional keysym macro is only necessary where a
 * non-hexadecimal mnemonic name is needed, or where the new keysym
 * does not represent any existing Unicode character.
 *
 * When adding new keysyms to this file, do not forget to also update the
 * following as needed:
 *
 *   - the mappings in src/KeyBind.c in the libX11 repo
 *     https://gitlab.freedesktop.org/xorg/lib/libx11
 *
 *   - the protocol specification in specs/keysyms.xml in this repo
 *     https://gitlab.freedesktop.org/xorg/proto/xorgproto
 *
 */

#define XK_VoidSymbol		0xFFFFFF	/* void symbol */
#define XK_VoidSymbol                  0xffffff  /* Void symbol */

#ifdef XK_MISCELLANY
/*
 * TTY Functions, cleverly chosen to map to ascii, for convenience of
 * TTY function keys, cleverly chosen to map to ASCII, for convenience of
 * programming, but could have been arbitrary (at the cost of lookup
 * tables in client code.
 * tables in client code).
 */

#define XK_BackSpace		0xFF08	/* back space, back char */
#define XK_Tab			0xFF09
#define XK_Linefeed		0xFF0A	/* Linefeed, LF */
#define XK_Clear		0xFF0B
#define XK_Return		0xFF0D	/* Return, enter */
#define XK_Pause		0xFF13	/* Pause, hold */
#define XK_Scroll_Lock		0xFF14
#define XK_Sys_Req		0xFF15
#define XK_Escape		0xFF1B
#define XK_Delete		0xFFFF	/* Delete, rubout */
#define XK_BackSpace                     0xff08  /* Back space, back char */
#define XK_Tab                           0xff09
#define XK_Linefeed                      0xff0a  /* Linefeed, LF */
#define XK_Clear                         0xff0b
#define XK_Return                        0xff0d  /* Return, enter */
#define XK_Pause                         0xff13  /* Pause, hold */
#define XK_Scroll_Lock                   0xff14
#define XK_Sys_Req                       0xff15
#define XK_Escape                        0xff1b
#define XK_Delete                        0xffff  /* Delete, rubout */



/* International & multi-key character composition */

#define XK_Multi_key		0xFF20  /* Multi-key character compose */
#define XK_Multi_key                     0xff20  /* Multi-key character compose */
#define XK_Codeinput                     0xff37
#define XK_SingleCandidate               0xff3c
#define XK_MultipleCandidate             0xff3d
#define XK_PreviousCandidate             0xff3e

/* Japanese keyboard support */

#define XK_Kanji		0xFF21	/* Kanji, Kanji convert */
#define XK_Muhenkan		0xFF22  /* Cancel Conversion */
#define XK_Henkan_Mode		0xFF23  /* Start/Stop Conversion */
#define XK_Henkan		0xFF23  /* Alias for Henkan_Mode */
#define XK_Romaji		0xFF24  /* to Romaji */
#define XK_Hiragana		0xFF25  /* to Hiragana */
#define XK_Katakana		0xFF26  /* to Katakana */
#define XK_Hiragana_Katakana	0xFF27  /* Hiragana/Katakana toggle */
#define XK_Zenkaku		0xFF28  /* to Zenkaku */
#define XK_Hankaku		0xFF29  /* to Hankaku */
#define XK_Zenkaku_Hankaku	0xFF2A  /* Zenkaku/Hankaku toggle */
#define XK_Touroku		0xFF2B  /* Add to Dictionary */
#define XK_Massyo		0xFF2C  /* Delete from Dictionary */
#define XK_Kana_Lock		0xFF2D  /* Kana Lock */
#define XK_Kana_Shift		0xFF2E  /* Kana Shift */
#define XK_Eisu_Shift		0xFF2F  /* Alphanumeric Shift */
#define XK_Eisu_toggle		0xFF30  /* Alphanumeric toggle */
#define XK_Kanji                         0xff21  /* Kanji, Kanji convert */
#define XK_Muhenkan                      0xff22  /* Cancel Conversion */
#define XK_Henkan_Mode                   0xff23  /* Start/Stop Conversion */
#define XK_Henkan                        0xff23  /* Alias for Henkan_Mode */
#define XK_Romaji                        0xff24  /* to Romaji */
#define XK_Hiragana                      0xff25  /* to Hiragana */
#define XK_Katakana                      0xff26  /* to Katakana */
#define XK_Hiragana_Katakana             0xff27  /* Hiragana/Katakana toggle */
#define XK_Zenkaku                       0xff28  /* to Zenkaku */
#define XK_Hankaku                       0xff29  /* to Hankaku */
#define XK_Zenkaku_Hankaku               0xff2a  /* Zenkaku/Hankaku toggle */
#define XK_Touroku                       0xff2b  /* Add to Dictionary */
#define XK_Massyo                        0xff2c  /* Delete from Dictionary */
#define XK_Kana_Lock                     0xff2d  /* Kana Lock */
#define XK_Kana_Shift                    0xff2e  /* Kana Shift */
#define XK_Eisu_Shift                    0xff2f  /* Alphanumeric Shift */
#define XK_Eisu_toggle                   0xff30  /* Alphanumeric toggle */
#define XK_Kanji_Bangou                  0xff37  /* Codeinput */
#define XK_Zen_Koho                      0xff3d  /* Multiple/All Candidate(s) */
#define XK_Mae_Koho                      0xff3e  /* Previous Candidate */

/* 0xff31 thru 0xff3f are under XK_KOREAN */

/* Cursor control & motion */

#define XK_Home			0xFF50
#define XK_Left			0xFF51	/* Move left, left arrow */
#define XK_Up			0xFF52	/* Move up, up arrow */
#define XK_Right		0xFF53	/* Move right, right arrow */
#define XK_Down			0xFF54	/* Move down, down arrow */
#define XK_Prior		0xFF55	/* Prior, previous */
#define XK_Page_Up		0xFF55
#define XK_Next			0xFF56	/* Next */
#define XK_Page_Down		0xFF56
#define XK_End			0xFF57	/* EOL */
#define XK_Begin		0xFF58	/* BOL */
#define XK_Home                          0xff50
#define XK_Left                          0xff51  /* Move left, left arrow */
#define XK_Up                            0xff52  /* Move up, up arrow */
#define XK_Right                         0xff53  /* Move right, right arrow */
#define XK_Down                          0xff54  /* Move down, down arrow */
#define XK_Prior                         0xff55  /* Prior, previous */
#define XK_Page_Up                       0xff55
#define XK_Next                          0xff56  /* Next */
#define XK_Page_Down                     0xff56
#define XK_End                           0xff57  /* EOL */
#define XK_Begin                         0xff58  /* BOL */

/* Special Windows keyboard keys */

#define XK_Win_L		0xFF5B	/* Left-hand Windows */
#define XK_Win_R		0xFF5C	/* Right-hand Windows */
#define XK_App			0xFF5D	/* Menu key */

/* Misc Functions */
/* Misc functions */

#define XK_Select		0xFF60	/* Select, mark */
#define XK_Print		0xFF61
#define XK_Execute		0xFF62	/* Execute, run, do */
#define XK_Insert		0xFF63	/* Insert, insert here */
#define XK_Undo			0xFF65	/* Undo, oops */
#define XK_Redo			0xFF66	/* redo, again */
#define XK_Menu			0xFF67
#define XK_Find			0xFF68	/* Find, search */
#define XK_Cancel		0xFF69	/* Cancel, stop, abort, exit */
#define XK_Help			0xFF6A	/* Help, ? */
#define XK_Break		0xFF6B
#define XK_Mode_switch		0xFF7E	/* Character set switch */
#define XK_script_switch        0xFF7E  /* Alias for mode_switch */
#define XK_Num_Lock		0xFF7F
#define XK_Select                        0xff60  /* Select, mark */
#define XK_Print                         0xff61
#define XK_Execute                       0xff62  /* Execute, run, do */
#define XK_Insert                        0xff63  /* Insert, insert here */
#define XK_Undo                          0xff65
#define XK_Redo                          0xff66  /* Redo, again */
#define XK_Menu                          0xff67
#define XK_Find                          0xff68  /* Find, search */
#define XK_Cancel                        0xff69  /* Cancel, stop, abort, exit */
#define XK_Help                          0xff6a  /* Help */
#define XK_Break                         0xff6b
#define XK_Mode_switch                   0xff7e  /* Character set switch */
#define XK_script_switch                 0xff7e  /* Alias for mode_switch */
#define XK_Num_Lock                      0xff7f

/* Keypad Functions, keypad numbers cleverly chosen to map to ascii */
/* Keypad functions, keypad numbers cleverly chosen to map to ASCII */

#define XK_KP_Space		0xFF80	/* space */
#define XK_KP_Tab		0xFF89
#define XK_KP_Enter		0xFF8D	/* enter */
#define XK_KP_F1		0xFF91	/* PF1, KP_A, ... */
#define XK_KP_F2		0xFF92
#define XK_KP_F3		0xFF93
#define XK_KP_F4		0xFF94
#define XK_KP_Home		0xFF95
#define XK_KP_Left		0xFF96
#define XK_KP_Up		0xFF97
#define XK_KP_Right		0xFF98
#define XK_KP_Down		0xFF99
#define XK_KP_Prior		0xFF9A
#define XK_KP_Page_Up		0xFF9A
#define XK_KP_Next		0xFF9B
#define XK_KP_Page_Down		0xFF9B
#define XK_KP_End		0xFF9C
#define XK_KP_Begin		0xFF9D
#define XK_KP_Insert		0xFF9E
#define XK_KP_Delete		0xFF9F
#define XK_KP_Equal		0xFFBD	/* equals */
#define XK_KP_Multiply		0xFFAA
#define XK_KP_Add		0xFFAB
#define XK_KP_Separator		0xFFAC	/* separator, often comma */
#define XK_KP_Subtract		0xFFAD
#define XK_KP_Decimal		0xFFAE
#define XK_KP_Divide		0xFFAF
#define XK_KP_Space                      0xff80  /* Space */
#define XK_KP_Tab                        0xff89
#define XK_KP_Enter                      0xff8d  /* Enter */
#define XK_KP_F1                         0xff91  /* PF1, KP_A, ... */
#define XK_KP_F2                         0xff92
#define XK_KP_F3                         0xff93
#define XK_KP_F4                         0xff94
#define XK_KP_Home                       0xff95
#define XK_KP_Left                       0xff96
#define XK_KP_Up                         0xff97
#define XK_KP_Right                      0xff98
#define XK_KP_Down                       0xff99
#define XK_KP_Prior                      0xff9a
#define XK_KP_Page_Up                    0xff9a
#define XK_KP_Next                       0xff9b
#define XK_KP_Page_Down                  0xff9b
#define XK_KP_End                        0xff9c
#define XK_KP_Begin                      0xff9d
#define XK_KP_Insert                     0xff9e
#define XK_KP_Delete                     0xff9f
#define XK_KP_Equal                      0xffbd  /* Equals */
#define XK_KP_Multiply                   0xffaa
#define XK_KP_Add                        0xffab
#define XK_KP_Separator                  0xffac  /* Separator, often comma */
#define XK_KP_Subtract                   0xffad
#define XK_KP_Decimal                    0xffae
#define XK_KP_Divide                     0xffaf

#define XK_KP_0			0xFFB0
#define XK_KP_1			0xFFB1
#define XK_KP_2			0xFFB2
#define XK_KP_3			0xFFB3
#define XK_KP_4			0xFFB4
#define XK_KP_5			0xFFB5
#define XK_KP_6			0xFFB6
#define XK_KP_7			0xFFB7
#define XK_KP_8			0xFFB8
#define XK_KP_9			0xFFB9
#define XK_KP_0                          0xffb0
#define XK_KP_1                          0xffb1
#define XK_KP_2                          0xffb2
#define XK_KP_3                          0xffb3
#define XK_KP_4                          0xffb4
#define XK_KP_5                          0xffb5
#define XK_KP_6                          0xffb6
#define XK_KP_7                          0xffb7
#define XK_KP_8                          0xffb8
#define XK_KP_9                          0xffb9



/*
 * Auxilliary Functions; note the duplicate definitions for left and right
 * function keys;  Sun keyboards and a few other manufactures have such
 * Auxiliary functions; note the duplicate definitions for left and right
 * function keys;  Sun keyboards and a few other manufacturers have such
 * function key groups on the left and/or right sides of the keyboard.
 * We've not found a keyboard with more than 35 function keys total.
 */

#define XK_F1			0xFFBE
#define XK_F2			0xFFBF
#define XK_F3			0xFFC0
#define XK_F4			0xFFC1
#define XK_F5			0xFFC2
#define XK_F6			0xFFC3
#define XK_F7			0xFFC4
#define XK_F8			0xFFC5
#define XK_F9			0xFFC6
#define XK_F10			0xFFC7
#define XK_F11			0xFFC8
#define XK_L1			0xFFC8
#define XK_F12			0xFFC9
#define XK_L2			0xFFC9
#define XK_F13			0xFFCA
#define XK_L3			0xFFCA
#define XK_F14			0xFFCB
#define XK_L4			0xFFCB
#define XK_F15			0xFFCC
#define XK_L5			0xFFCC
#define XK_F16			0xFFCD
#define XK_L6			0xFFCD
#define XK_F17			0xFFCE
#define XK_L7			0xFFCE
#define XK_F18			0xFFCF
#define XK_L8			0xFFCF
#define XK_F19			0xFFD0
#define XK_L9			0xFFD0
#define XK_F20			0xFFD1
#define XK_L10			0xFFD1
#define XK_F21			0xFFD2
#define XK_R1			0xFFD2
#define XK_F22			0xFFD3
#define XK_R2			0xFFD3
#define XK_F23			0xFFD4
#define XK_R3			0xFFD4
#define XK_F24			0xFFD5
#define XK_R4			0xFFD5
#define XK_F25			0xFFD6
#define XK_R5			0xFFD6
#define XK_F26			0xFFD7
#define XK_R6			0xFFD7
#define XK_F27			0xFFD8
#define XK_R7			0xFFD8
#define XK_F28			0xFFD9
#define XK_R8			0xFFD9
#define XK_F29			0xFFDA
#define XK_R9			0xFFDA
#define XK_F30			0xFFDB
#define XK_R10			0xFFDB
#define XK_F31			0xFFDC
#define XK_R11			0xFFDC
#define XK_F32			0xFFDD
#define XK_R12			0xFFDD
#define XK_F33			0xFFDE
#define XK_R13			0xFFDE
#define XK_F34			0xFFDF
#define XK_R14			0xFFDF
#define XK_F35			0xFFE0
#define XK_R15			0xFFE0
#define XK_F1                            0xffbe
#define XK_F2                            0xffbf
#define XK_F3                            0xffc0
#define XK_F4                            0xffc1
#define XK_F5                            0xffc2
#define XK_F6                            0xffc3
#define XK_F7                            0xffc4
#define XK_F8                            0xffc5
#define XK_F9                            0xffc6
#define XK_F10                           0xffc7
#define XK_F11                           0xffc8
#define XK_L1                            0xffc8
#define XK_F12                           0xffc9
#define XK_L2                            0xffc9
#define XK_F13                           0xffca
#define XK_L3                            0xffca
#define XK_F14                           0xffcb
#define XK_L4                            0xffcb
#define XK_F15                           0xffcc
#define XK_L5                            0xffcc
#define XK_F16                           0xffcd
#define XK_L6                            0xffcd
#define XK_F17                           0xffce
#define XK_L7                            0xffce
#define XK_F18                           0xffcf
#define XK_L8                            0xffcf
#define XK_F19                           0xffd0
#define XK_L9                            0xffd0
#define XK_F20                           0xffd1
#define XK_L10                           0xffd1
#define XK_F21                           0xffd2
#define XK_R1                            0xffd2
#define XK_F22                           0xffd3
#define XK_R2                            0xffd3
#define XK_F23                           0xffd4
#define XK_R3                            0xffd4
#define XK_F24                           0xffd5
#define XK_R4                            0xffd5
#define XK_F25                           0xffd6
#define XK_R5                            0xffd6
#define XK_F26                           0xffd7
#define XK_R6                            0xffd7
#define XK_F27                           0xffd8
#define XK_R7                            0xffd8
#define XK_F28                           0xffd9
#define XK_R8                            0xffd9
#define XK_F29                           0xffda
#define XK_R9                            0xffda
#define XK_F30                           0xffdb
#define XK_R10                           0xffdb
#define XK_F31                           0xffdc
#define XK_R11                           0xffdc
#define XK_F32                           0xffdd
#define XK_R12                           0xffdd
#define XK_F33                           0xffde
#define XK_R13                           0xffde
#define XK_F34                           0xffdf
#define XK_R14                           0xffdf
#define XK_F35                           0xffe0
#define XK_R15                           0xffe0

/* Modifiers */

#define XK_Shift_L		0xFFE1	/* Left shift */
#define XK_Shift_R		0xFFE2	/* Right shift */
#define XK_Control_L		0xFFE3	/* Left control */
#define XK_Control_R		0xFFE4	/* Right control */
#define XK_Caps_Lock		0xFFE5	/* Caps lock */
#define XK_Shift_Lock		0xFFE6	/* Shift lock */
#define XK_Shift_L                       0xffe1  /* Left shift */
#define XK_Shift_R                       0xffe2  /* Right shift */
#define XK_Control_L                     0xffe3  /* Left control */
#define XK_Control_R                     0xffe4  /* Right control */
#define XK_Caps_Lock                     0xffe5  /* Caps lock */
#define XK_Shift_Lock                    0xffe6  /* Shift lock */

#define XK_Meta_L		0xFFE7	/* Left meta */
#define XK_Meta_R		0xFFE8	/* Right meta */
#define XK_Alt_L		0xFFE9	/* Left alt */
#define XK_Alt_R		0xFFEA	/* Right alt */
#define XK_Super_L		0xFFEB	/* Left super */
#define XK_Super_R		0xFFEC	/* Right super */
#define XK_Hyper_L		0xFFED	/* Left hyper */
#define XK_Hyper_R		0xFFEE	/* Right hyper */
#define XK_Meta_L                        0xffe7  /* Left meta */
#define XK_Meta_R                        0xffe8  /* Right meta */
#define XK_Alt_L                         0xffe9  /* Left alt */
#define XK_Alt_R                         0xffea  /* Right alt */
#define XK_Super_L                       0xffeb  /* Left super */
#define XK_Super_R                       0xffec  /* Right super */
#define XK_Hyper_L                       0xffed  /* Left hyper */
#define XK_Hyper_R                       0xffee  /* Right hyper */
#endif /* XK_MISCELLANY */

/*
 * Keyboard (XKB) Extension function and modifier keys
 * (from Appendix C of "The X Keyboard Extension: Protocol Specification")
 * Byte 3 = 0xfe
 */

#ifdef XK_XKB_KEYS
#define XK_ISO_Lock                      0xfe01
#define XK_ISO_Level2_Latch              0xfe02
#define XK_ISO_Level3_Shift              0xfe03
#define XK_ISO_Level3_Latch              0xfe04
#define XK_ISO_Level3_Lock               0xfe05
#define XK_ISO_Level5_Shift              0xfe11
#define XK_ISO_Level5_Latch              0xfe12
#define XK_ISO_Level5_Lock               0xfe13
#define XK_ISO_Group_Shift               0xff7e  /* Alias for mode_switch */
#define XK_ISO_Group_Latch               0xfe06
#define XK_ISO_Group_Lock                0xfe07
#define XK_ISO_Next_Group                0xfe08
#define XK_ISO_Next_Group_Lock           0xfe09
#define XK_ISO_Prev_Group                0xfe0a
#define XK_ISO_Prev_Group_Lock           0xfe0b
#define XK_ISO_First_Group               0xfe0c
#define XK_ISO_First_Group_Lock          0xfe0d
#define XK_ISO_Last_Group                0xfe0e
#define XK_ISO_Last_Group_Lock           0xfe0f

#define XK_ISO_Left_Tab                  0xfe20
#define XK_ISO_Move_Line_Up              0xfe21
#define XK_ISO_Move_Line_Down            0xfe22
#define XK_ISO_Partial_Line_Up           0xfe23
#define XK_ISO_Partial_Line_Down         0xfe24
#define XK_ISO_Partial_Space_Left        0xfe25
#define XK_ISO_Partial_Space_Right       0xfe26
#define XK_ISO_Set_Margin_Left           0xfe27
#define XK_ISO_Set_Margin_Right          0xfe28
#define XK_ISO_Release_Margin_Left       0xfe29
#define XK_ISO_Release_Margin_Right      0xfe2a
#define XK_ISO_Release_Both_Margins      0xfe2b
#define XK_ISO_Fast_Cursor_Left          0xfe2c
#define XK_ISO_Fast_Cursor_Right         0xfe2d
#define XK_ISO_Fast_Cursor_Up            0xfe2e
#define XK_ISO_Fast_Cursor_Down          0xfe2f
#define XK_ISO_Continuous_Underline      0xfe30
#define XK_ISO_Discontinuous_Underline   0xfe31
#define XK_ISO_Emphasize                 0xfe32
#define XK_ISO_Center_Object             0xfe33
#define XK_ISO_Enter                     0xfe34

#define XK_dead_grave                    0xfe50
#define XK_dead_acute                    0xfe51
#define XK_dead_circumflex               0xfe52
#define XK_dead_tilde                    0xfe53
#define XK_dead_perispomeni              0xfe53  /* alias for dead_tilde */
#define XK_dead_macron                   0xfe54
#define XK_dead_breve                    0xfe55
#define XK_dead_abovedot                 0xfe56
#define XK_dead_diaeresis                0xfe57
#define XK_dead_abovering                0xfe58
#define XK_dead_doubleacute              0xfe59
#define XK_dead_caron                    0xfe5a
#define XK_dead_cedilla                  0xfe5b
#define XK_dead_ogonek                   0xfe5c
#define XK_dead_iota                     0xfe5d
#define XK_dead_voiced_sound             0xfe5e
#define XK_dead_semivoiced_sound         0xfe5f
#define XK_dead_belowdot                 0xfe60
#define XK_dead_hook                     0xfe61
#define XK_dead_horn                     0xfe62
#define XK_dead_stroke                   0xfe63
#define XK_dead_abovecomma               0xfe64
#define XK_dead_psili                    0xfe64  /* alias for dead_abovecomma */
#define XK_dead_abovereversedcomma       0xfe65
#define XK_dead_dasia                    0xfe65  /* alias for dead_abovereversedcomma */
#define XK_dead_doublegrave              0xfe66
#define XK_dead_belowring                0xfe67
#define XK_dead_belowmacron              0xfe68
#define XK_dead_belowcircumflex          0xfe69
#define XK_dead_belowtilde               0xfe6a
#define XK_dead_belowbreve               0xfe6b
#define XK_dead_belowdiaeresis           0xfe6c
#define XK_dead_invertedbreve            0xfe6d
#define XK_dead_belowcomma               0xfe6e
#define XK_dead_currency                 0xfe6f

/* extra dead elements for German T3 layout */
#define XK_dead_lowline                  0xfe90
#define XK_dead_aboveverticalline        0xfe91
#define XK_dead_belowverticalline        0xfe92
#define XK_dead_longsolidusoverlay       0xfe93

/* dead vowels for universal syllable entry */
#define XK_dead_a                        0xfe80
#define XK_dead_A                        0xfe81
#define XK_dead_e                        0xfe82
#define XK_dead_E                        0xfe83
#define XK_dead_i                        0xfe84
#define XK_dead_I                        0xfe85
#define XK_dead_o                        0xfe86
#define XK_dead_O                        0xfe87
#define XK_dead_u                        0xfe88
#define XK_dead_U                        0xfe89
#define XK_dead_small_schwa              0xfe8a
#define XK_dead_capital_schwa            0xfe8b

#define XK_dead_greek                    0xfe8c

#define XK_First_Virtual_Screen          0xfed0
#define XK_Prev_Virtual_Screen           0xfed1
#define XK_Next_Virtual_Screen           0xfed2
#define XK_Last_Virtual_Screen           0xfed4
#define XK_Terminate_Server              0xfed5

#define XK_AccessX_Enable                0xfe70
#define XK_AccessX_Feedback_Enable       0xfe71
#define XK_RepeatKeys_Enable             0xfe72
#define XK_SlowKeys_Enable               0xfe73
#define XK_BounceKeys_Enable             0xfe74
#define XK_StickyKeys_Enable             0xfe75
#define XK_MouseKeys_Enable              0xfe76
#define XK_MouseKeys_Accel_Enable        0xfe77
#define XK_Overlay1_Enable               0xfe78
#define XK_Overlay2_Enable               0xfe79
#define XK_AudibleBell_Enable            0xfe7a

#define XK_Pointer_Left                  0xfee0
#define XK_Pointer_Right                 0xfee1
#define XK_Pointer_Up                    0xfee2
#define XK_Pointer_Down                  0xfee3
#define XK_Pointer_UpLeft                0xfee4
#define XK_Pointer_UpRight               0xfee5
#define XK_Pointer_DownLeft              0xfee6
#define XK_Pointer_DownRight             0xfee7
#define XK_Pointer_Button_Dflt           0xfee8
#define XK_Pointer_Button1               0xfee9
#define XK_Pointer_Button2               0xfeea
#define XK_Pointer_Button3               0xfeeb
#define XK_Pointer_Button4               0xfeec
#define XK_Pointer_Button5               0xfeed
#define XK_Pointer_DblClick_Dflt         0xfeee
#define XK_Pointer_DblClick1             0xfeef
#define XK_Pointer_DblClick2             0xfef0
#define XK_Pointer_DblClick3             0xfef1
#define XK_Pointer_DblClick4             0xfef2
#define XK_Pointer_DblClick5             0xfef3
#define XK_Pointer_Drag_Dflt             0xfef4
#define XK_Pointer_Drag1                 0xfef5
#define XK_Pointer_Drag2                 0xfef6
#define XK_Pointer_Drag3                 0xfef7
#define XK_Pointer_Drag4                 0xfef8
#define XK_Pointer_Drag5                 0xfefd

#define XK_Pointer_EnableKeys            0xfef9
#define XK_Pointer_Accelerate            0xfefa
#define XK_Pointer_DfltBtnNext           0xfefb
#define XK_Pointer_DfltBtnPrev           0xfefc

/* Single-Stroke Multiple-Character N-Graph Keysyms For The X Input Method */

#define XK_ch                            0xfea0
#define XK_Ch                            0xfea1
#define XK_CH                            0xfea2
#define XK_c_h                           0xfea3
#define XK_C_h                           0xfea4
#define XK_C_H                           0xfea5

#endif /* XK_XKB_KEYS */

/*
 * 3270 Terminal Keys
 * Byte 3 = 0xfd
 */

#ifdef XK_3270
#define XK_3270_Duplicate                0xfd01
#define XK_3270_FieldMark                0xfd02
#define XK_3270_Right2                   0xfd03
#define XK_3270_Left2                    0xfd04
#define XK_3270_BackTab                  0xfd05
#define XK_3270_EraseEOF                 0xfd06
#define XK_3270_EraseInput               0xfd07
#define XK_3270_Reset                    0xfd08
#define XK_3270_Quit                     0xfd09
#define XK_3270_PA1                      0xfd0a
#define XK_3270_PA2                      0xfd0b
#define XK_3270_PA3                      0xfd0c
#define XK_3270_Test                     0xfd0d
#define XK_3270_Attn                     0xfd0e
#define XK_3270_CursorBlink              0xfd0f
#define XK_3270_AltCursor                0xfd10
#define XK_3270_KeyClick                 0xfd11
#define XK_3270_Jump                     0xfd12
#define XK_3270_Ident                    0xfd13
#define XK_3270_Rule                     0xfd14
#define XK_3270_Copy                     0xfd15
#define XK_3270_Play                     0xfd16
#define XK_3270_Setup                    0xfd17
#define XK_3270_Record                   0xfd18
#define XK_3270_ChangeScreen             0xfd19
#define XK_3270_DeleteWord               0xfd1a
#define XK_3270_ExSelect                 0xfd1b
#define XK_3270_CursorSelect             0xfd1c
#define XK_3270_PrintScreen              0xfd1d
#define XK_3270_Enter                    0xfd1e
#endif /* XK_3270 */

/*
 *  Latin 1
 *  Byte 3 = 0
 * Latin 1
 * (ISO/IEC 8859-1 = Unicode U+0020..U+00FF)
 * Byte 3 = 0
 */
#ifdef XK_LATIN1
#define XK_space               0x020
#define XK_exclam              0x021
#define XK_quotedbl            0x022
#define XK_numbersign          0x023
#define XK_dollar              0x024
#define XK_percent             0x025
#define XK_ampersand           0x026
#define XK_apostrophe          0x027
#define XK_quoteright          0x027	/* deprecated */
#define XK_parenleft           0x028
#define XK_parenright          0x029
#define XK_asterisk            0x02a
#define XK_plus                0x02b
#define XK_comma               0x02c
#define XK_minus               0x02d
#define XK_period              0x02e
#define XK_slash               0x02f
#define XK_0                   0x030
#define XK_1                   0x031
#define XK_2                   0x032
#define XK_3                   0x033
#define XK_4                   0x034
#define XK_5                   0x035
#define XK_6                   0x036
#define XK_7                   0x037
#define XK_8                   0x038
#define XK_9                   0x039
#define XK_colon               0x03a
#define XK_semicolon           0x03b
#define XK_less                0x03c
#define XK_equal               0x03d
#define XK_greater             0x03e
#define XK_question            0x03f
#define XK_at                  0x040
#define XK_A                   0x041
#define XK_B                   0x042
#define XK_C                   0x043
#define XK_D                   0x044
#define XK_E                   0x045
#define XK_F                   0x046
#define XK_G                   0x047
#define XK_H                   0x048
#define XK_I                   0x049
#define XK_J                   0x04a
#define XK_K                   0x04b
#define XK_L                   0x04c
#define XK_M                   0x04d
#define XK_N                   0x04e
#define XK_O                   0x04f
#define XK_P                   0x050
#define XK_Q                   0x051
#define XK_R                   0x052
#define XK_S                   0x053
#define XK_T                   0x054
#define XK_U                   0x055
#define XK_V                   0x056
#define XK_W                   0x057
#define XK_X                   0x058
#define XK_Y                   0x059
#define XK_Z                   0x05a
#define XK_bracketleft         0x05b
#define XK_backslash           0x05c
#define XK_bracketright        0x05d
#define XK_asciicircum         0x05e
#define XK_underscore          0x05f
#define XK_grave               0x060
#define XK_quoteleft           0x060	/* deprecated */
#define XK_a                   0x061
#define XK_b                   0x062
#define XK_c                   0x063
#define XK_d                   0x064
#define XK_e                   0x065
#define XK_f                   0x066
#define XK_g                   0x067
#define XK_h                   0x068
#define XK_i                   0x069
#define XK_j                   0x06a
#define XK_k                   0x06b
#define XK_l                   0x06c
#define XK_m                   0x06d
#define XK_n                   0x06e
#define XK_o                   0x06f
#define XK_p                   0x070
#define XK_q                   0x071
#define XK_r                   0x072
#define XK_s                   0x073
#define XK_t                   0x074
#define XK_u                   0x075
#define XK_v                   0x076
#define XK_w                   0x077
#define XK_x                   0x078
#define XK_y                   0x079
#define XK_z                   0x07a
#define XK_braceleft           0x07b
#define XK_bar                 0x07c
#define XK_braceright          0x07d
#define XK_asciitilde          0x07e
#define XK_space                         0x0020  /* U+0020 SPACE */
#define XK_exclam                        0x0021  /* U+0021 EXCLAMATION MARK */
#define XK_quotedbl                      0x0022  /* U+0022 QUOTATION MARK */
#define XK_numbersign                    0x0023  /* U+0023 NUMBER SIGN */
#define XK_dollar                        0x0024  /* U+0024 DOLLAR SIGN */
#define XK_percent                       0x0025  /* U+0025 PERCENT SIGN */
#define XK_ampersand                     0x0026  /* U+0026 AMPERSAND */
#define XK_apostrophe                    0x0027  /* U+0027 APOSTROPHE */
#define XK_quoteright                    0x0027  /* deprecated */
#define XK_parenleft                     0x0028  /* U+0028 LEFT PARENTHESIS */
#define XK_parenright                    0x0029  /* U+0029 RIGHT PARENTHESIS */
#define XK_asterisk                      0x002a  /* U+002A ASTERISK */
#define XK_plus                          0x002b  /* U+002B PLUS SIGN */
#define XK_comma                         0x002c  /* U+002C COMMA */
#define XK_minus                         0x002d  /* U+002D HYPHEN-MINUS */
#define XK_period                        0x002e  /* U+002E FULL STOP */
#define XK_slash                         0x002f  /* U+002F SOLIDUS */
#define XK_0                             0x0030  /* U+0030 DIGIT ZERO */
#define XK_1                             0x0031  /* U+0031 DIGIT ONE */
#define XK_2                             0x0032  /* U+0032 DIGIT TWO */
#define XK_3                             0x0033  /* U+0033 DIGIT THREE */
#define XK_4                             0x0034  /* U+0034 DIGIT FOUR */
#define XK_5                             0x0035  /* U+0035 DIGIT FIVE */
#define XK_6                             0x0036  /* U+0036 DIGIT SIX */
#define XK_7                             0x0037  /* U+0037 DIGIT SEVEN */
#define XK_8                             0x0038  /* U+0038 DIGIT EIGHT */
#define XK_9                             0x0039  /* U+0039 DIGIT NINE */
#define XK_colon                         0x003a  /* U+003A COLON */
#define XK_semicolon                     0x003b  /* U+003B SEMICOLON */
#define XK_less                          0x003c  /* U+003C LESS-THAN SIGN */
#define XK_equal                         0x003d  /* U+003D EQUALS SIGN */
#define XK_greater                       0x003e  /* U+003E GREATER-THAN SIGN */
#define XK_question                      0x003f  /* U+003F QUESTION MARK */
#define XK_at                            0x0040  /* U+0040 COMMERCIAL AT */
#define XK_A                             0x0041  /* U+0041 LATIN CAPITAL LETTER A */
#define XK_B                             0x0042  /* U+0042 LATIN CAPITAL LETTER B */
#define XK_C                             0x0043  /* U+0043 LATIN CAPITAL LETTER C */
#define XK_D                             0x0044  /* U+0044 LATIN CAPITAL LETTER D */
#define XK_E                             0x0045  /* U+0045 LATIN CAPITAL LETTER E */
#define XK_F                             0x0046  /* U+0046 LATIN CAPITAL LETTER F */
#define XK_G                             0x0047  /* U+0047 LATIN CAPITAL LETTER G */
#define XK_H                             0x0048  /* U+0048 LATIN CAPITAL LETTER H */
#define XK_I                             0x0049  /* U+0049 LATIN CAPITAL LETTER I */
#define XK_J                             0x004a  /* U+004A LATIN CAPITAL LETTER J */
#define XK_K                             0x004b  /* U+004B LATIN CAPITAL LETTER K */
#define XK_L                             0x004c  /* U+004C LATIN CAPITAL LETTER L */
#define XK_M                             0x004d  /* U+004D LATIN CAPITAL LETTER M */
#define XK_N                             0x004e  /* U+004E LATIN CAPITAL LETTER N */
#define XK_O                             0x004f  /* U+004F LATIN CAPITAL LETTER O */
#define XK_P                             0x0050  /* U+0050 LATIN CAPITAL LETTER P */
#define XK_Q                             0x0051  /* U+0051 LATIN CAPITAL LETTER Q */
#define XK_R                             0x0052  /* U+0052 LATIN CAPITAL LETTER R */
#define XK_S                             0x0053  /* U+0053 LATIN CAPITAL LETTER S */
#define XK_T                             0x0054  /* U+0054 LATIN CAPITAL LETTER T */
#define XK_U                             0x0055  /* U+0055 LATIN CAPITAL LETTER U */
#define XK_V                             0x0056  /* U+0056 LATIN CAPITAL LETTER V */
#define XK_W                             0x0057  /* U+0057 LATIN CAPITAL LETTER W */
#define XK_X                             0x0058  /* U+0058 LATIN CAPITAL LETTER X */
#define XK_Y                             0x0059  /* U+0059 LATIN CAPITAL LETTER Y */
#define XK_Z                             0x005a  /* U+005A LATIN CAPITAL LETTER Z */
#define XK_bracketleft                   0x005b  /* U+005B LEFT SQUARE BRACKET */
#define XK_backslash                     0x005c  /* U+005C REVERSE SOLIDUS */
#define XK_bracketright                  0x005d  /* U+005D RIGHT SQUARE BRACKET */
#define XK_asciicircum                   0x005e  /* U+005E CIRCUMFLEX ACCENT */
#define XK_underscore                    0x005f  /* U+005F LOW LINE */
#define XK_grave                         0x0060  /* U+0060 GRAVE ACCENT */
#define XK_quoteleft                     0x0060  /* deprecated */
#define XK_a                             0x0061  /* U+0061 LATIN SMALL LETTER A */
#define XK_b                             0x0062  /* U+0062 LATIN SMALL LETTER B */
#define XK_c                             0x0063  /* U+0063 LATIN SMALL LETTER C */
#define XK_d                             0x0064  /* U+0064 LATIN SMALL LETTER D */
#define XK_e                             0x0065  /* U+0065 LATIN SMALL LETTER E */
#define XK_f                             0x0066  /* U+0066 LATIN SMALL LETTER F */
#define XK_g                             0x0067  /* U+0067 LATIN SMALL LETTER G */
#define XK_h                             0x0068  /* U+0068 LATIN SMALL LETTER H */
#define XK_i                             0x0069  /* U+0069 LATIN SMALL LETTER I */
#define XK_j                             0x006a  /* U+006A LATIN SMALL LETTER J */
#define XK_k                             0x006b  /* U+006B LATIN SMALL LETTER K */
#define XK_l                             0x006c  /* U+006C LATIN SMALL LETTER L */
#define XK_m                             0x006d  /* U+006D LATIN SMALL LETTER M */
#define XK_n                             0x006e  /* U+006E LATIN SMALL LETTER N */
#define XK_o                             0x006f  /* U+006F LATIN SMALL LETTER O */
#define XK_p                             0x0070  /* U+0070 LATIN SMALL LETTER P */
#define XK_q                             0x0071  /* U+0071 LATIN SMALL LETTER Q */
#define XK_r                             0x0072  /* U+0072 LATIN SMALL LETTER R */
#define XK_s                             0x0073  /* U+0073 LATIN SMALL LETTER S */
#define XK_t                             0x0074  /* U+0074 LATIN SMALL LETTER T */
#define XK_u                             0x0075  /* U+0075 LATIN SMALL LETTER U */
#define XK_v                             0x0076  /* U+0076 LATIN SMALL LETTER V */
#define XK_w                             0x0077  /* U+0077 LATIN SMALL LETTER W */
#define XK_x                             0x0078  /* U+0078 LATIN SMALL LETTER X */
#define XK_y                             0x0079  /* U+0079 LATIN SMALL LETTER Y */
#define XK_z                             0x007a  /* U+007A LATIN SMALL LETTER Z */
#define XK_braceleft                     0x007b  /* U+007B LEFT CURLY BRACKET */
#define XK_bar                           0x007c  /* U+007C VERTICAL LINE */
#define XK_braceright                    0x007d  /* U+007D RIGHT CURLY BRACKET */
#define XK_asciitilde                    0x007e  /* U+007E TILDE */

#define XK_nobreakspace        0x0a0
#define XK_exclamdown          0x0a1
#define XK_cent        	       0x0a2
#define XK_sterling            0x0a3
#define XK_currency            0x0a4
#define XK_yen                 0x0a5
#define XK_brokenbar           0x0a6
#define XK_section             0x0a7
#define XK_diaeresis           0x0a8
#define XK_copyright           0x0a9
#define XK_ordfeminine         0x0aa
#define XK_guillemotleft       0x0ab	/* left angle quotation mark */
#define XK_notsign             0x0ac
#define XK_hyphen              0x0ad
#define XK_registered          0x0ae
#define XK_macron              0x0af
#define XK_degree              0x0b0
#define XK_plusminus           0x0b1
#define XK_twosuperior         0x0b2
#define XK_threesuperior       0x0b3
#define XK_acute               0x0b4
#define XK_mu                  0x0b5
#define XK_paragraph           0x0b6
#define XK_periodcentered      0x0b7
#define XK_cedilla             0x0b8
#define XK_onesuperior         0x0b9
#define XK_masculine           0x0ba
#define XK_guillemotright      0x0bb	/* right angle quotation mark */
#define XK_onequarter          0x0bc
#define XK_onehalf             0x0bd
#define XK_threequarters       0x0be
#define XK_questiondown        0x0bf
#define XK_Agrave              0x0c0
#define XK_Aacute              0x0c1
#define XK_Acircumflex         0x0c2
#define XK_Atilde              0x0c3
#define XK_Adiaeresis          0x0c4
#define XK_Aring               0x0c5
#define XK_AE                  0x0c6
#define XK_Ccedilla            0x0c7
#define XK_Egrave              0x0c8
#define XK_Eacute              0x0c9
#define XK_Ecircumflex         0x0ca
#define XK_Ediaeresis          0x0cb
#define XK_Igrave              0x0cc
#define XK_Iacute              0x0cd
#define XK_Icircumflex         0x0ce
#define XK_Idiaeresis          0x0cf
#define XK_ETH                 0x0d0
#define XK_Eth                 0x0d0	/* deprecated */
#define XK_Ntilde              0x0d1
#define XK_Ograve              0x0d2
#define XK_Oacute              0x0d3
#define XK_Ocircumflex         0x0d4
#define XK_Otilde              0x0d5
#define XK_Odiaeresis          0x0d6
#define XK_multiply            0x0d7
#define XK_Oslash              0x0d8
#define XK_Ooblique            0x0d8
#define XK_Ugrave              0x0d9
#define XK_Uacute              0x0da
#define XK_Ucircumflex         0x0db
#define XK_Udiaeresis          0x0dc
#define XK_Yacute              0x0dd
#define XK_THORN               0x0de
#define XK_Thorn               0x0de	/* deprecated */
#define XK_ssharp              0x0df
#define XK_agrave              0x0e0
#define XK_aacute              0x0e1
#define XK_acircumflex         0x0e2
#define XK_atilde              0x0e3
#define XK_adiaeresis          0x0e4
#define XK_aring               0x0e5
#define XK_ae                  0x0e6
#define XK_ccedilla            0x0e7
#define XK_egrave              0x0e8
#define XK_eacute              0x0e9
#define XK_ecircumflex         0x0ea
#define XK_ediaeresis          0x0eb
#define XK_igrave              0x0ec
#define XK_iacute              0x0ed
#define XK_icircumflex         0x0ee
#define XK_idiaeresis          0x0ef
#define XK_eth                 0x0f0
#define XK_ntilde              0x0f1
#define XK_ograve              0x0f2
#define XK_oacute              0x0f3
#define XK_ocircumflex         0x0f4
#define XK_otilde              0x0f5
#define XK_odiaeresis          0x0f6
#define XK_division            0x0f7
#define XK_oslash              0x0f8
#define XK_ugrave              0x0f9
#define XK_uacute              0x0fa
#define XK_ucircumflex         0x0fb
#define XK_udiaeresis          0x0fc
#define XK_yacute              0x0fd
#define XK_thorn               0x0fe
#define XK_ydiaeresis          0x0ff
#define XK_nobreakspace                  0x00a0  /* U+00A0 NO-BREAK SPACE */
#define XK_exclamdown                    0x00a1  /* U+00A1 INVERTED EXCLAMATION MARK */
#define XK_cent                          0x00a2  /* U+00A2 CENT SIGN */
#define XK_sterling                      0x00a3  /* U+00A3 POUND SIGN */
#define XK_currency                      0x00a4  /* U+00A4 CURRENCY SIGN */
#define XK_yen                           0x00a5  /* U+00A5 YEN SIGN */
#define XK_brokenbar                     0x00a6  /* U+00A6 BROKEN BAR */
#define XK_section                       0x00a7  /* U+00A7 SECTION SIGN */
#define XK_diaeresis                     0x00a8  /* U+00A8 DIAERESIS */
#define XK_copyright                     0x00a9  /* U+00A9 COPYRIGHT SIGN */
#define XK_ordfeminine                   0x00aa  /* U+00AA FEMININE ORDINAL INDICATOR */
#define XK_guillemotleft                 0x00ab  /* U+00AB LEFT-POINTING DOUBLE ANGLE QUOTATION MARK */
#define XK_notsign                       0x00ac  /* U+00AC NOT SIGN */
#define XK_hyphen                        0x00ad  /* U+00AD SOFT HYPHEN */
#define XK_registered                    0x00ae  /* U+00AE REGISTERED SIGN */
#define XK_macron                        0x00af  /* U+00AF MACRON */
#define XK_degree                        0x00b0  /* U+00B0 DEGREE SIGN */
#define XK_plusminus                     0x00b1  /* U+00B1 PLUS-MINUS SIGN */
#define XK_twosuperior                   0x00b2  /* U+00B2 SUPERSCRIPT TWO */
#define XK_threesuperior                 0x00b3  /* U+00B3 SUPERSCRIPT THREE */
#define XK_acute                         0x00b4  /* U+00B4 ACUTE ACCENT */
#define XK_mu                            0x00b5  /* U+00B5 MICRO SIGN */
#define XK_paragraph                     0x00b6  /* U+00B6 PILCROW SIGN */
#define XK_periodcentered                0x00b7  /* U+00B7 MIDDLE DOT */
#define XK_cedilla                       0x00b8  /* U+00B8 CEDILLA */
#define XK_onesuperior                   0x00b9  /* U+00B9 SUPERSCRIPT ONE */
#define XK_masculine                     0x00ba  /* U+00BA MASCULINE ORDINAL INDICATOR */
#define XK_guillemotright                0x00bb  /* U+00BB RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK */
#define XK_onequarter                    0x00bc  /* U+00BC VULGAR FRACTION ONE QUARTER */
#define XK_onehalf                       0x00bd  /* U+00BD VULGAR FRACTION ONE HALF */
#define XK_threequarters                 0x00be  /* U+00BE VULGAR FRACTION THREE QUARTERS */
#define XK_questiondown                  0x00bf  /* U+00BF INVERTED QUESTION MARK */
#define XK_Agrave                        0x00c0  /* U+00C0 LATIN CAPITAL LETTER A WITH GRAVE */
#define XK_Aacute                        0x00c1  /* U+00C1 LATIN CAPITAL LETTER A WITH ACUTE */
#define XK_Acircumflex                   0x00c2  /* U+00C2 LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
#define XK_Atilde                        0x00c3  /* U+00C3 LATIN CAPITAL LETTER A WITH TILDE */
#define XK_Adiaeresis                    0x00c4  /* U+00C4 LATIN CAPITAL LETTER A WITH DIAERESIS */
#define XK_Aring                         0x00c5  /* U+00C5 LATIN CAPITAL LETTER A WITH RING ABOVE */
#define XK_AE                            0x00c6  /* U+00C6 LATIN CAPITAL LETTER AE */
#define XK_Ccedilla                      0x00c7  /* U+00C7 LATIN CAPITAL LETTER C WITH CEDILLA */
#define XK_Egrave                        0x00c8  /* U+00C8 LATIN CAPITAL LETTER E WITH GRAVE */
#define XK_Eacute                        0x00c9  /* U+00C9 LATIN CAPITAL LETTER E WITH ACUTE */
#define XK_Ecircumflex                   0x00ca  /* U+00CA LATIN CAPITAL LETTER E WITH CIRCUMFLEX */
#define XK_Ediaeresis                    0x00cb  /* U+00CB LATIN CAPITAL LETTER E WITH DIAERESIS */
#define XK_Igrave                        0x00cc  /* U+00CC LATIN CAPITAL LETTER I WITH GRAVE */
#define XK_Iacute                        0x00cd  /* U+00CD LATIN CAPITAL LETTER I WITH ACUTE */
#define XK_Icircumflex                   0x00ce  /* U+00CE LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
#define XK_Idiaeresis                    0x00cf  /* U+00CF LATIN CAPITAL LETTER I WITH DIAERESIS */
#define XK_ETH                           0x00d0  /* U+00D0 LATIN CAPITAL LETTER ETH */
#define XK_Eth                           0x00d0  /* deprecated */
#define XK_Ntilde                        0x00d1  /* U+00D1 LATIN CAPITAL LETTER N WITH TILDE */
#define XK_Ograve                        0x00d2  /* U+00D2 LATIN CAPITAL LETTER O WITH GRAVE */
#define XK_Oacute                        0x00d3  /* U+00D3 LATIN CAPITAL LETTER O WITH ACUTE */
#define XK_Ocircumflex                   0x00d4  /* U+00D4 LATIN CAPITAL LETTER O WITH CIRCUMFLEX */
#define XK_Otilde                        0x00d5  /* U+00D5 LATIN CAPITAL LETTER O WITH TILDE */
#define XK_Odiaeresis                    0x00d6  /* U+00D6 LATIN CAPITAL LETTER O WITH DIAERESIS */
#define XK_multiply                      0x00d7  /* U+00D7 MULTIPLICATION SIGN */
#define XK_Oslash                        0x00d8  /* U+00D8 LATIN CAPITAL LETTER O WITH STROKE */
#define XK_Ooblique                      0x00d8  /* U+00D8 LATIN CAPITAL LETTER O WITH STROKE */
#define XK_Ugrave                        0x00d9  /* U+00D9 LATIN CAPITAL LETTER U WITH GRAVE */
#define XK_Uacute                        0x00da  /* U+00DA LATIN CAPITAL LETTER U WITH ACUTE */
#define XK_Ucircumflex                   0x00db  /* U+00DB LATIN CAPITAL LETTER U WITH CIRCUMFLEX */
#define XK_Udiaeresis                    0x00dc  /* U+00DC LATIN CAPITAL LETTER U WITH DIAERESIS */
#define XK_Yacute                        0x00dd  /* U+00DD LATIN CAPITAL LETTER Y WITH ACUTE */
#define XK_THORN                         0x00de  /* U+00DE LATIN CAPITAL LETTER THORN */
#define XK_Thorn                         0x00de  /* deprecated */
#define XK_ssharp                        0x00df  /* U+00DF LATIN SMALL LETTER SHARP S */
#define XK_agrave                        0x00e0  /* U+00E0 LATIN SMALL LETTER A WITH GRAVE */
#define XK_aacute                        0x00e1  /* U+00E1 LATIN SMALL LETTER A WITH ACUTE */
#define XK_acircumflex                   0x00e2  /* U+00E2 LATIN SMALL LETTER A WITH CIRCUMFLEX */
#define XK_atilde                        0x00e3  /* U+00E3 LATIN SMALL LETTER A WITH TILDE */
#define XK_adiaeresis                    0x00e4  /* U+00E4 LATIN SMALL LETTER A WITH DIAERESIS */
#define XK_aring                         0x00e5  /* U+00E5 LATIN SMALL LETTER A WITH RING ABOVE */
#define XK_ae                            0x00e6  /* U+00E6 LATIN SMALL LETTER AE */
#define XK_ccedilla                      0x00e7  /* U+00E7 LATIN SMALL LETTER C WITH CEDILLA */
#define XK_egrave                        0x00e8  /* U+00E8 LATIN SMALL LETTER E WITH GRAVE */
#define XK_eacute                        0x00e9  /* U+00E9 LATIN SMALL LETTER E WITH ACUTE */
#define XK_ecircumflex                   0x00ea  /* U+00EA LATIN SMALL LETTER E WITH CIRCUMFLEX */
#define XK_ediaeresis                    0x00eb  /* U+00EB LATIN SMALL LETTER E WITH DIAERESIS */
#define XK_igrave                        0x00ec  /* U+00EC LATIN SMALL LETTER I WITH GRAVE */
#define XK_iacute                        0x00ed  /* U+00ED LATIN SMALL LETTER I WITH ACUTE */
#define XK_icircumflex                   0x00ee  /* U+00EE LATIN SMALL LETTER I WITH CIRCUMFLEX */
#define XK_idiaeresis                    0x00ef  /* U+00EF LATIN SMALL LETTER I WITH DIAERESIS */
#define XK_eth                           0x00f0  /* U+00F0 LATIN SMALL LETTER ETH */
#define XK_ntilde                        0x00f1  /* U+00F1 LATIN SMALL LETTER N WITH TILDE */
#define XK_ograve                        0x00f2  /* U+00F2 LATIN SMALL LETTER O WITH GRAVE */
#define XK_oacute                        0x00f3  /* U+00F3 LATIN SMALL LETTER O WITH ACUTE */
#define XK_ocircumflex                   0x00f4  /* U+00F4 LATIN SMALL LETTER O WITH CIRCUMFLEX */
#define XK_otilde                        0x00f5  /* U+00F5 LATIN SMALL LETTER O WITH TILDE */
#define XK_odiaeresis                    0x00f6  /* U+00F6 LATIN SMALL LETTER O WITH DIAERESIS */
#define XK_division                      0x00f7  /* U+00F7 DIVISION SIGN */
#define XK_oslash                        0x00f8  /* U+00F8 LATIN SMALL LETTER O WITH STROKE */
#define XK_ooblique                      0x00f8  /* U+00F8 LATIN SMALL LETTER O WITH STROKE */
#define XK_ugrave                        0x00f9  /* U+00F9 LATIN SMALL LETTER U WITH GRAVE */
#define XK_uacute                        0x00fa  /* U+00FA LATIN SMALL LETTER U WITH ACUTE */
#define XK_ucircumflex                   0x00fb  /* U+00FB LATIN SMALL LETTER U WITH CIRCUMFLEX */
#define XK_udiaeresis                    0x00fc  /* U+00FC LATIN SMALL LETTER U WITH DIAERESIS */
#define XK_yacute                        0x00fd  /* U+00FD LATIN SMALL LETTER Y WITH ACUTE */
#define XK_thorn                         0x00fe  /* U+00FE LATIN SMALL LETTER THORN */
#define XK_ydiaeresis                    0x00ff  /* U+00FF LATIN SMALL LETTER Y WITH DIAERESIS */
#endif /* XK_LATIN1 */

/*
 *   Latin 2
 *   Byte 3 = 1
 * Latin 2
 * Byte 3 = 1
 */

#ifdef XK_LATIN2
#define XK_Aogonek             0x1a1
#define XK_breve               0x1a2
#define XK_Lstroke             0x1a3
#define XK_Lcaron              0x1a5
#define XK_Sacute              0x1a6
#define XK_Scaron              0x1a9
#define XK_Scedilla            0x1aa
#define XK_Tcaron              0x1ab
#define XK_Zacute              0x1ac
#define XK_Zcaron              0x1ae
#define XK_Zabovedot           0x1af
#define XK_aogonek             0x1b1
#define XK_ogonek              0x1b2
#define XK_lstroke             0x1b3
#define XK_lcaron              0x1b5
#define XK_sacute              0x1b6
#define XK_caron               0x1b7
#define XK_scaron              0x1b9
#define XK_scedilla            0x1ba
#define XK_tcaron              0x1bb
#define XK_zacute              0x1bc
#define XK_doubleacute         0x1bd
#define XK_zcaron              0x1be
#define XK_zabovedot           0x1bf
#define XK_Racute              0x1c0
#define XK_Abreve              0x1c3
#define XK_Lacute              0x1c5
#define XK_Cacute              0x1c6
#define XK_Ccaron              0x1c8
#define XK_Eogonek             0x1ca
#define XK_Ecaron              0x1cc
#define XK_Dcaron              0x1cf
#define XK_Dstroke             0x1d0
#define XK_Nacute              0x1d1
#define XK_Ncaron              0x1d2
#define XK_Odoubleacute        0x1d5
#define XK_Rcaron              0x1d8
#define XK_Uring               0x1d9
#define XK_Udoubleacute        0x1db
#define XK_Tcedilla            0x1de
#define XK_racute              0x1e0
#define XK_abreve              0x1e3
#define XK_lacute              0x1e5
#define XK_cacute              0x1e6
#define XK_ccaron              0x1e8
#define XK_eogonek             0x1ea
#define XK_ecaron              0x1ec
#define XK_dcaron              0x1ef
#define XK_dstroke             0x1f0
#define XK_nacute              0x1f1
#define XK_ncaron              0x1f2
#define XK_odoubleacute        0x1f5
#define XK_Aogonek                       0x01a1  /* U+0104 LATIN CAPITAL LETTER A WITH OGONEK */
#define XK_breve                         0x01a2  /* U+02D8 BREVE */
#define XK_Lstroke                       0x01a3  /* U+0141 LATIN CAPITAL LETTER L WITH STROKE */
#define XK_Lcaron                        0x01a5  /* U+013D LATIN CAPITAL LETTER L WITH CARON */
#define XK_Sacute                        0x01a6  /* U+015A LATIN CAPITAL LETTER S WITH ACUTE */
#define XK_Scaron                        0x01a9  /* U+0160 LATIN CAPITAL LETTER S WITH CARON */
#define XK_Scedilla                      0x01aa  /* U+015E LATIN CAPITAL LETTER S WITH CEDILLA */
#define XK_Tcaron                        0x01ab  /* U+0164 LATIN CAPITAL LETTER T WITH CARON */
#define XK_Zacute                        0x01ac  /* U+0179 LATIN CAPITAL LETTER Z WITH ACUTE */
#define XK_Zcaron                        0x01ae  /* U+017D LATIN CAPITAL LETTER Z WITH CARON */
#define XK_Zabovedot                     0x01af  /* U+017B LATIN CAPITAL LETTER Z WITH DOT ABOVE */
#define XK_aogonek                       0x01b1  /* U+0105 LATIN SMALL LETTER A WITH OGONEK */
#define XK_ogonek                        0x01b2  /* U+02DB OGONEK */
#define XK_lstroke                       0x01b3  /* U+0142 LATIN SMALL LETTER L WITH STROKE */
#define XK_lcaron                        0x01b5  /* U+013E LATIN SMALL LETTER L WITH CARON */
#define XK_sacute                        0x01b6  /* U+015B LATIN SMALL LETTER S WITH ACUTE */
#define XK_caron                         0x01b7  /* U+02C7 CARON */
#define XK_scaron                        0x01b9  /* U+0161 LATIN SMALL LETTER S WITH CARON */
#define XK_scedilla                      0x01ba  /* U+015F LATIN SMALL LETTER S WITH CEDILLA */
#define XK_tcaron                        0x01bb  /* U+0165 LATIN SMALL LETTER T WITH CARON */
#define XK_zacute                        0x01bc  /* U+017A LATIN SMALL LETTER Z WITH ACUTE */
#define XK_doubleacute                   0x01bd  /* U+02DD DOUBLE ACUTE ACCENT */
#define XK_zcaron                        0x01be  /* U+017E LATIN SMALL LETTER Z WITH CARON */
#define XK_zabovedot                     0x01bf  /* U+017C LATIN SMALL LETTER Z WITH DOT ABOVE */
#define XK_Racute                        0x01c0  /* U+0154 LATIN CAPITAL LETTER R WITH ACUTE */
#define XK_Abreve                        0x01c3  /* U+0102 LATIN CAPITAL LETTER A WITH BREVE */
#define XK_Lacute                        0x01c5  /* U+0139 LATIN CAPITAL LETTER L WITH ACUTE */
#define XK_Cacute                        0x01c6  /* U+0106 LATIN CAPITAL LETTER C WITH ACUTE */
#define XK_Ccaron                        0x01c8  /* U+010C LATIN CAPITAL LETTER C WITH CARON */
#define XK_Eogonek                       0x01ca  /* U+0118 LATIN CAPITAL LETTER E WITH OGONEK */
#define XK_Ecaron                        0x01cc  /* U+011A LATIN CAPITAL LETTER E WITH CARON */
#define XK_Dcaron                        0x01cf  /* U+010E LATIN CAPITAL LETTER D WITH CARON */
#define XK_Dstroke                       0x01d0  /* U+0110 LATIN CAPITAL LETTER D WITH STROKE */
#define XK_Nacute                        0x01d1  /* U+0143 LATIN CAPITAL LETTER N WITH ACUTE */
#define XK_Ncaron                        0x01d2  /* U+0147 LATIN CAPITAL LETTER N WITH CARON */
#define XK_Odoubleacute                  0x01d5  /* U+0150 LATIN CAPITAL LETTER O WITH DOUBLE ACUTE */
#define XK_Rcaron                        0x01d8  /* U+0158 LATIN CAPITAL LETTER R WITH CARON */
#define XK_Uring                         0x01d9  /* U+016E LATIN CAPITAL LETTER U WITH RING ABOVE */
#define XK_Udoubleacute                  0x01db  /* U+0170 LATIN CAPITAL LETTER U WITH DOUBLE ACUTE */
#define XK_Tcedilla                      0x01de  /* U+0162 LATIN CAPITAL LETTER T WITH CEDILLA */
#define XK_racute                        0x01e0  /* U+0155 LATIN SMALL LETTER R WITH ACUTE */
#define XK_abreve                        0x01e3  /* U+0103 LATIN SMALL LETTER A WITH BREVE */
#define XK_lacute                        0x01e5  /* U+013A LATIN SMALL LETTER L WITH ACUTE */
#define XK_cacute                        0x01e6  /* U+0107 LATIN SMALL LETTER C WITH ACUTE */
#define XK_ccaron                        0x01e8  /* U+010D LATIN SMALL LETTER C WITH CARON */
#define XK_eogonek                       0x01ea  /* U+0119 LATIN SMALL LETTER E WITH OGONEK */
#define XK_ecaron                        0x01ec  /* U+011B LATIN SMALL LETTER E WITH CARON */
#define XK_dcaron                        0x01ef  /* U+010F LATIN SMALL LETTER D WITH CARON */
#define XK_dstroke                       0x01f0  /* U+0111 LATIN SMALL LETTER D WITH STROKE */
#define XK_nacute                        0x01f1  /* U+0144 LATIN SMALL LETTER N WITH ACUTE */
#define XK_ncaron                        0x01f2  /* U+0148 LATIN SMALL LETTER N WITH CARON */
#define XK_odoubleacute                  0x01f5  /* U+0151 LATIN SMALL LETTER O WITH DOUBLE ACUTE */
#define XK_udoubleacute        0x1fb
#define XK_rcaron              0x1f8
#define XK_uring               0x1f9
#define XK_tcedilla            0x1fe
#define XK_abovedot            0x1ff
#define XK_rcaron                        0x01f8  /* U+0159 LATIN SMALL LETTER R WITH CARON */
#define XK_uring                         0x01f9  /* U+016F LATIN SMALL LETTER U WITH RING ABOVE */
#define XK_udoubleacute                  0x01fb  /* U+0171 LATIN SMALL LETTER U WITH DOUBLE ACUTE */
#define XK_tcedilla                      0x01fe  /* U+0163 LATIN SMALL LETTER T WITH CEDILLA */
#define XK_abovedot                      0x01ff  /* U+02D9 DOT ABOVE */
#endif /* XK_LATIN2 */

/*
 *   Latin 3
 *   Byte 3 = 2
 * Latin 3
 * Byte 3 = 2
 */

#ifdef XK_LATIN3
#define XK_Hstroke             0x2a1
#define XK_Hcircumflex         0x2a6
#define XK_Iabovedot           0x2a9
#define XK_Gbreve              0x2ab
#define XK_Jcircumflex         0x2ac
#define XK_hstroke             0x2b1
#define XK_hcircumflex         0x2b6
#define XK_idotless            0x2b9
#define XK_gbreve              0x2bb
#define XK_jcircumflex         0x2bc
#define XK_Cabovedot           0x2c5
#define XK_Ccircumflex         0x2c6
#define XK_Gabovedot           0x2d5
#define XK_Gcircumflex         0x2d8
#define XK_Ubreve              0x2dd
#define XK_Scircumflex         0x2de
#define XK_cabovedot           0x2e5
#define XK_ccircumflex         0x2e6
#define XK_gabovedot           0x2f5
#define XK_gcircumflex         0x2f8
#define XK_ubreve              0x2fd
#define XK_scircumflex         0x2fe
#define XK_Hstroke                       0x02a1  /* U+0126 LATIN CAPITAL LETTER H WITH STROKE */
#define XK_Hcircumflex                   0x02a6  /* U+0124 LATIN CAPITAL LETTER H WITH CIRCUMFLEX */
#define XK_Iabovedot                     0x02a9  /* U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE */
#define XK_Gbreve                        0x02ab  /* U+011E LATIN CAPITAL LETTER G WITH BREVE */
#define XK_Jcircumflex                   0x02ac  /* U+0134 LATIN CAPITAL LETTER J WITH CIRCUMFLEX */
#define XK_hstroke                       0x02b1  /* U+0127 LATIN SMALL LETTER H WITH STROKE */
#define XK_hcircumflex                   0x02b6  /* U+0125 LATIN SMALL LETTER H WITH CIRCUMFLEX */
#define XK_idotless                      0x02b9  /* U+0131 LATIN SMALL LETTER DOTLESS I */
#define XK_gbreve                        0x02bb  /* U+011F LATIN SMALL LETTER G WITH BREVE */
#define XK_jcircumflex                   0x02bc  /* U+0135 LATIN SMALL LETTER J WITH CIRCUMFLEX */
#define XK_Cabovedot                     0x02c5  /* U+010A LATIN CAPITAL LETTER C WITH DOT ABOVE */
#define XK_Ccircumflex                   0x02c6  /* U+0108 LATIN CAPITAL LETTER C WITH CIRCUMFLEX */
#define XK_Gabovedot                     0x02d5  /* U+0120 LATIN CAPITAL LETTER G WITH DOT ABOVE */
#define XK_Gcircumflex                   0x02d8  /* U+011C LATIN CAPITAL LETTER G WITH CIRCUMFLEX */
#define XK_Ubreve                        0x02dd  /* U+016C LATIN CAPITAL LETTER U WITH BREVE */
#define XK_Scircumflex                   0x02de  /* U+015C LATIN CAPITAL LETTER S WITH CIRCUMFLEX */
#define XK_cabovedot                     0x02e5  /* U+010B LATIN SMALL LETTER C WITH DOT ABOVE */
#define XK_ccircumflex                   0x02e6  /* U+0109 LATIN SMALL LETTER C WITH CIRCUMFLEX */
#define XK_gabovedot                     0x02f5  /* U+0121 LATIN SMALL LETTER G WITH DOT ABOVE */
#define XK_gcircumflex                   0x02f8  /* U+011D LATIN SMALL LETTER G WITH CIRCUMFLEX */
#define XK_ubreve                        0x02fd  /* U+016D LATIN SMALL LETTER U WITH BREVE */
#define XK_scircumflex                   0x02fe  /* U+015D LATIN SMALL LETTER S WITH CIRCUMFLEX */
#endif /* XK_LATIN3 */


/*
 *   Latin 4
 *   Byte 3 = 3
 * Latin 4
 * Byte 3 = 3
 */

#ifdef XK_LATIN4
#define XK_kra                 0x3a2
#define XK_kappa               0x3a2	/* deprecated */
#define XK_Rcedilla            0x3a3
#define XK_Itilde              0x3a5
#define XK_Lcedilla            0x3a6
#define XK_Emacron             0x3aa
#define XK_Gcedilla            0x3ab
#define XK_Tslash              0x3ac
#define XK_rcedilla            0x3b3
#define XK_itilde              0x3b5
#define XK_lcedilla            0x3b6
#define XK_emacron             0x3ba
#define XK_gcedilla            0x3bb
#define XK_tslash              0x3bc
#define XK_ENG                 0x3bd
#define XK_eng                 0x3bf
#define XK_Amacron             0x3c0
#define XK_Iogonek             0x3c7
#define XK_Eabovedot           0x3cc
#define XK_Imacron             0x3cf
#define XK_Ncedilla            0x3d1
#define XK_Omacron             0x3d2
#define XK_Kcedilla            0x3d3
#define XK_Uogonek             0x3d9
#define XK_Utilde              0x3dd
#define XK_Umacron             0x3de
#define XK_amacron             0x3e0
#define XK_iogonek             0x3e7
#define XK_eabovedot           0x3ec
#define XK_imacron             0x3ef
#define XK_ncedilla            0x3f1
#define XK_omacron             0x3f2
#define XK_kcedilla            0x3f3
#define XK_uogonek             0x3f9
#define XK_utilde              0x3fd
#define XK_umacron             0x3fe
#define XK_kra                           0x03a2  /* U+0138 LATIN SMALL LETTER KRA */
#define XK_kappa                         0x03a2  /* deprecated */
#define XK_Rcedilla                      0x03a3  /* U+0156 LATIN CAPITAL LETTER R WITH CEDILLA */
#define XK_Itilde                        0x03a5  /* U+0128 LATIN CAPITAL LETTER I WITH TILDE */
#define XK_Lcedilla                      0x03a6  /* U+013B LATIN CAPITAL LETTER L WITH CEDILLA */
#define XK_Emacron                       0x03aa  /* U+0112 LATIN CAPITAL LETTER E WITH MACRON */
#define XK_Gcedilla                      0x03ab  /* U+0122 LATIN CAPITAL LETTER G WITH CEDILLA */
#define XK_Tslash                        0x03ac  /* U+0166 LATIN CAPITAL LETTER T WITH STROKE */
#define XK_rcedilla                      0x03b3  /* U+0157 LATIN SMALL LETTER R WITH CEDILLA */
#define XK_itilde                        0x03b5  /* U+0129 LATIN SMALL LETTER I WITH TILDE */
#define XK_lcedilla                      0x03b6  /* U+013C LATIN SMALL LETTER L WITH CEDILLA */
#define XK_emacron                       0x03ba  /* U+0113 LATIN SMALL LETTER E WITH MACRON */
#define XK_gcedilla                      0x03bb  /* U+0123 LATIN SMALL LETTER G WITH CEDILLA */
#define XK_tslash                        0x03bc  /* U+0167 LATIN SMALL LETTER T WITH STROKE */
#define XK_ENG                           0x03bd  /* U+014A LATIN CAPITAL LETTER ENG */
#define XK_eng                           0x03bf  /* U+014B LATIN SMALL LETTER ENG */
#define XK_Amacron                       0x03c0  /* U+0100 LATIN CAPITAL LETTER A WITH MACRON */
#define XK_Iogonek                       0x03c7  /* U+012E LATIN CAPITAL LETTER I WITH OGONEK */
#define XK_Eabovedot                     0x03cc  /* U+0116 LATIN CAPITAL LETTER E WITH DOT ABOVE */
#define XK_Imacron                       0x03cf  /* U+012A LATIN CAPITAL LETTER I WITH MACRON */
#define XK_Ncedilla                      0x03d1  /* U+0145 LATIN CAPITAL LETTER N WITH CEDILLA */
#define XK_Omacron                       0x03d2  /* U+014C LATIN CAPITAL LETTER O WITH MACRON */
#define XK_Kcedilla                      0x03d3  /* U+0136 LATIN CAPITAL LETTER K WITH CEDILLA */
#define XK_Uogonek                       0x03d9  /* U+0172 LATIN CAPITAL LETTER U WITH OGONEK */
#define XK_Utilde                        0x03dd  /* U+0168 LATIN CAPITAL LETTER U WITH TILDE */
#define XK_Umacron                       0x03de  /* U+016A LATIN CAPITAL LETTER U WITH MACRON */
#define XK_amacron                       0x03e0  /* U+0101 LATIN SMALL LETTER A WITH MACRON */
#define XK_iogonek                       0x03e7  /* U+012F LATIN SMALL LETTER I WITH OGONEK */
#define XK_eabovedot                     0x03ec  /* U+0117 LATIN SMALL LETTER E WITH DOT ABOVE */
#define XK_imacron                       0x03ef  /* U+012B LATIN SMALL LETTER I WITH MACRON */
#define XK_ncedilla                      0x03f1  /* U+0146 LATIN SMALL LETTER N WITH CEDILLA */
#define XK_omacron                       0x03f2  /* U+014D LATIN SMALL LETTER O WITH MACRON */
#define XK_kcedilla                      0x03f3  /* U+0137 LATIN SMALL LETTER K WITH CEDILLA */
#define XK_uogonek                       0x03f9  /* U+0173 LATIN SMALL LETTER U WITH OGONEK */
#define XK_utilde                        0x03fd  /* U+0169 LATIN SMALL LETTER U WITH TILDE */
#define XK_umacron                       0x03fe  /* U+016B LATIN SMALL LETTER U WITH MACRON */
#endif /* XK_LATIN4 */

/*
 * Latin 9
 * Byte 3 = 0x13
 */

#ifdef XK_LATIN9
#define XK_OE                            0x13bc  /* U+0152 LATIN CAPITAL LIGATURE OE */
#define XK_oe                            0x13bd  /* U+0153 LATIN SMALL LIGATURE OE */
#define XK_Ydiaeresis                    0x13be  /* U+0178 LATIN CAPITAL LETTER Y WITH DIAERESIS */
#endif /* XK_LATIN9 */

/*
 * Katakana
 * Byte 3 = 4
 */

#ifdef XK_KATAKANA
#define XK_overline				       0x47e
#define XK_kana_fullstop                               0x4a1
#define XK_kana_openingbracket                         0x4a2
#define XK_kana_closingbracket                         0x4a3
#define XK_kana_comma                                  0x4a4
#define XK_kana_conjunctive                            0x4a5
#define XK_kana_middledot                              0x4a5  /* deprecated */
#define XK_kana_WO                                     0x4a6
#define XK_kana_a                                      0x4a7
#define XK_kana_i                                      0x4a8
#define XK_kana_u                                      0x4a9
#define XK_kana_e                                      0x4aa
#define XK_kana_o                                      0x4ab
#define XK_kana_ya                                     0x4ac
#define XK_kana_yu                                     0x4ad
#define XK_kana_yo                                     0x4ae
#define XK_kana_tsu                                    0x4af
#define XK_kana_tu                                     0x4af  /* deprecated */
#define XK_prolongedsound                              0x4b0
#define XK_kana_A                                      0x4b1
#define XK_kana_I                                      0x4b2
#define XK_kana_U                                      0x4b3
#define XK_kana_E                                      0x4b4
#define XK_kana_O                                      0x4b5
#define XK_kana_KA                                     0x4b6
#define XK_kana_KI                                     0x4b7
#define XK_kana_KU                                     0x4b8
#define XK_kana_KE                                     0x4b9
#define XK_kana_KO                                     0x4ba
#define XK_kana_SA                                     0x4bb
#define XK_kana_SHI                                    0x4bc
#define XK_kana_SU                                     0x4bd
#define XK_kana_SE                                     0x4be
#define XK_kana_SO                                     0x4bf
#define XK_kana_TA                                     0x4c0
#define XK_kana_CHI                                    0x4c1
#define XK_kana_TI                                     0x4c1  /* deprecated */
#define XK_kana_TSU                                    0x4c2
#define XK_kana_TU                                     0x4c2  /* deprecated */
#define XK_kana_TE                                     0x4c3
#define XK_kana_TO                                     0x4c4
#define XK_kana_NA                                     0x4c5
#define XK_kana_NI                                     0x4c6
#define XK_kana_NU                                     0x4c7
#define XK_kana_NE                                     0x4c8
#define XK_kana_NO                                     0x4c9
#define XK_kana_HA                                     0x4ca
#define XK_kana_HI                                     0x4cb
#define XK_kana_FU                                     0x4cc
#define XK_kana_HU                                     0x4cc  /* deprecated */
#define XK_kana_HE                                     0x4cd
#define XK_kana_HO                                     0x4ce
#define XK_kana_MA                                     0x4cf
#define XK_kana_MI                                     0x4d0
#define XK_kana_MU                                     0x4d1
#define XK_kana_ME                                     0x4d2
#define XK_kana_MO                                     0x4d3
#define XK_kana_YA                                     0x4d4
#define XK_kana_YU                                     0x4d5
#define XK_kana_YO                                     0x4d6
#define XK_kana_RA                                     0x4d7
#define XK_kana_RI                                     0x4d8
#define XK_kana_RU                                     0x4d9
#define XK_kana_RE                                     0x4da
#define XK_kana_RO                                     0x4db
#define XK_kana_WA                                     0x4dc
#define XK_kana_N                                      0x4dd
#define XK_voicedsound                                 0x4de
#define XK_semivoicedsound                             0x4df
#define XK_kana_switch          0xFF7E  /* Alias for mode_switch */
#define XK_overline                      0x047e  /* U+203E OVERLINE */
#define XK_kana_fullstop                 0x04a1  /* U+3002 IDEOGRAPHIC FULL STOP */
#define XK_kana_openingbracket           0x04a2  /* U+300C LEFT CORNER BRACKET */
#define XK_kana_closingbracket           0x04a3  /* U+300D RIGHT CORNER BRACKET */
#define XK_kana_comma                    0x04a4  /* U+3001 IDEOGRAPHIC COMMA */
#define XK_kana_conjunctive              0x04a5  /* U+30FB KATAKANA MIDDLE DOT */
#define XK_kana_middledot                0x04a5  /* deprecated */
#define XK_kana_WO                       0x04a6  /* U+30F2 KATAKANA LETTER WO */
#define XK_kana_a                        0x04a7  /* U+30A1 KATAKANA LETTER SMALL A */
#define XK_kana_i                        0x04a8  /* U+30A3 KATAKANA LETTER SMALL I */
#define XK_kana_u                        0x04a9  /* U+30A5 KATAKANA LETTER SMALL U */
#define XK_kana_e                        0x04aa  /* U+30A7 KATAKANA LETTER SMALL E */
#define XK_kana_o                        0x04ab  /* U+30A9 KATAKANA LETTER SMALL O */
#define XK_kana_ya                       0x04ac  /* U+30E3 KATAKANA LETTER SMALL YA */
#define XK_kana_yu                       0x04ad  /* U+30E5 KATAKANA LETTER SMALL YU */
#define XK_kana_yo                       0x04ae  /* U+30E7 KATAKANA LETTER SMALL YO */
#define XK_kana_tsu                      0x04af  /* U+30C3 KATAKANA LETTER SMALL TU */
#define XK_kana_tu                       0x04af  /* deprecated */
#define XK_prolongedsound                0x04b0  /* U+30FC KATAKANA-HIRAGANA PROLONGED SOUND MARK */
#define XK_kana_A                        0x04b1  /* U+30A2 KATAKANA LETTER A */
#define XK_kana_I                        0x04b2  /* U+30A4 KATAKANA LETTER I */
#define XK_kana_U                        0x04b3  /* U+30A6 KATAKANA LETTER U */
#define XK_kana_E                        0x04b4  /* U+30A8 KATAKANA LETTER E */
#define XK_kana_O                        0x04b5  /* U+30AA KATAKANA LETTER O */
#define XK_kana_KA                       0x04b6  /* U+30AB KATAKANA LETTER KA */
#define XK_kana_KI                       0x04b7  /* U+30AD KATAKANA LETTER KI */
#define XK_kana_KU                       0x04b8  /* U+30AF KATAKANA LETTER KU */
#define XK_kana_KE                       0x04b9  /* U+30B1 KATAKANA LETTER KE */
#define XK_kana_KO                       0x04ba  /* U+30B3 KATAKANA LETTER KO */
#define XK_kana_SA                       0x04bb  /* U+30B5 KATAKANA LETTER SA */
#define XK_kana_SHI                      0x04bc  /* U+30B7 KATAKANA LETTER SI */
#define XK_kana_SU                       0x04bd  /* U+30B9 KATAKANA LETTER SU */
#define XK_kana_SE                       0x04be  /* U+30BB KATAKANA LETTER SE */
#define XK_kana_SO                       0x04bf  /* U+30BD KATAKANA LETTER SO */
#define XK_kana_TA                       0x04c0  /* U+30BF KATAKANA LETTER TA */
#define XK_kana_CHI                      0x04c1  /* U+30C1 KATAKANA LETTER TI */
#define XK_kana_TI                       0x04c1  /* deprecated */
#define XK_kana_TSU                      0x04c2  /* U+30C4 KATAKANA LETTER TU */
#define XK_kana_TU                       0x04c2  /* deprecated */
#define XK_kana_TE                       0x04c3  /* U+30C6 KATAKANA LETTER TE */
#define XK_kana_TO                       0x04c4  /* U+30C8 KATAKANA LETTER TO */
#define XK_kana_NA                       0x04c5  /* U+30CA KATAKANA LETTER NA */
#define XK_kana_NI                       0x04c6  /* U+30CB KATAKANA LETTER NI */
#define XK_kana_NU                       0x04c7  /* U+30CC KATAKANA LETTER NU */
#define XK_kana_NE                       0x04c8  /* U+30CD KATAKANA LETTER NE */
#define XK_kana_NO                       0x04c9  /* U+30CE KATAKANA LETTER NO */
#define XK_kana_HA                       0x04ca  /* U+30CF KATAKANA LETTER HA */
#define XK_kana_HI                       0x04cb  /* U+30D2 KATAKANA LETTER HI */
#define XK_kana_FU                       0x04cc  /* U+30D5 KATAKANA LETTER HU */
#define XK_kana_HU                       0x04cc  /* deprecated */
#define XK_kana_HE                       0x04cd  /* U+30D8 KATAKANA LETTER HE */
#define XK_kana_HO                       0x04ce  /* U+30DB KATAKANA LETTER HO */
#define XK_kana_MA                       0x04cf  /* U+30DE KATAKANA LETTER MA */
#define XK_kana_MI                       0x04d0  /* U+30DF KATAKANA LETTER MI */
#define XK_kana_MU                       0x04d1  /* U+30E0 KATAKANA LETTER MU */
#define XK_kana_ME                       0x04d2  /* U+30E1 KATAKANA LETTER ME */
#define XK_kana_MO                       0x04d3  /* U+30E2 KATAKANA LETTER MO */
#define XK_kana_YA                       0x04d4  /* U+30E4 KATAKANA LETTER YA */
#define XK_kana_YU                       0x04d5  /* U+30E6 KATAKANA LETTER YU */
#define XK_kana_YO                       0x04d6  /* U+30E8 KATAKANA LETTER YO */
#define XK_kana_RA                       0x04d7  /* U+30E9 KATAKANA LETTER RA */
#define XK_kana_RI                       0x04d8  /* U+30EA KATAKANA LETTER RI */
#define XK_kana_RU                       0x04d9  /* U+30EB KATAKANA LETTER RU */
#define XK_kana_RE                       0x04da  /* U+30EC KATAKANA LETTER RE */
#define XK_kana_RO                       0x04db  /* U+30ED KATAKANA LETTER RO */
#define XK_kana_WA                       0x04dc  /* U+30EF KATAKANA LETTER WA */
#define XK_kana_N                        0x04dd  /* U+30F3 KATAKANA LETTER N */
#define XK_voicedsound                   0x04de  /* U+309B KATAKANA-HIRAGANA VOICED SOUND MARK */
#define XK_semivoicedsound               0x04df  /* U+309C KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK */
#define XK_kana_switch                   0xff7e  /* Alias for mode_switch */
#endif /* XK_KATAKANA */

/*
 *  Arabic
 *  Byte 3 = 5
 * Arabic
 * Byte 3 = 5
 */

#ifdef XK_ARABIC
#define XK_Arabic_comma                                0x5ac
#define XK_Arabic_semicolon                            0x5bb
#define XK_Arabic_question_mark                        0x5bf
#define XK_Arabic_hamza                                0x5c1
#define XK_Arabic_maddaonalef                          0x5c2
#define XK_Arabic_hamzaonalef                          0x5c3
#define XK_Arabic_hamzaonwaw                           0x5c4
#define XK_Arabic_hamzaunderalef                       0x5c5
#define XK_Arabic_hamzaonyeh                           0x5c6
#define XK_Arabic_alef                                 0x5c7
#define XK_Arabic_beh                                  0x5c8
#define XK_Arabic_tehmarbuta                           0x5c9
#define XK_Arabic_teh                                  0x5ca
#define XK_Arabic_theh                                 0x5cb
#define XK_Arabic_jeem                                 0x5cc
#define XK_Arabic_hah                                  0x5cd
#define XK_Arabic_khah                                 0x5ce
#define XK_Arabic_dal                                  0x5cf
#define XK_Arabic_thal                                 0x5d0
#define XK_Arabic_ra                                   0x5d1
#define XK_Arabic_zain                                 0x5d2
#define XK_Arabic_seen                                 0x5d3
#define XK_Arabic_sheen                                0x5d4
#define XK_Arabic_sad                                  0x5d5
#define XK_Arabic_dad                                  0x5d6
#define XK_Arabic_tah                                  0x5d7
#define XK_Arabic_zah                                  0x5d8
#define XK_Arabic_ain                                  0x5d9
#define XK_Arabic_ghain                                0x5da
#define XK_Arabic_tatweel                              0x5e0
#define XK_Arabic_feh                                  0x5e1
#define XK_Arabic_qaf                                  0x5e2
#define XK_Arabic_kaf                                  0x5e3
#define XK_Arabic_lam                                  0x5e4
#define XK_Arabic_meem                                 0x5e5
#define XK_Arabic_noon                                 0x5e6
#define XK_Arabic_ha                                   0x5e7
#define XK_Arabic_heh                                  0x5e7  /* deprecated */
#define XK_Arabic_waw                                  0x5e8
#define XK_Arabic_alefmaksura                          0x5e9
#define XK_Arabic_yeh                                  0x5ea
#define XK_Arabic_fathatan                             0x5eb
#define XK_Arabic_dammatan                             0x5ec
#define XK_Arabic_kasratan                             0x5ed
#define XK_Arabic_fatha                                0x5ee
#define XK_Arabic_damma                                0x5ef
#define XK_Arabic_kasra                                0x5f0
#define XK_Arabic_shadda                               0x5f1
#define XK_Arabic_sukun                                0x5f2
#define XK_Arabic_switch        0xFF7E  /* Alias for mode_switch */
#define XK_Arabic_comma                  0x05ac  /* U+060C ARABIC COMMA */
#define XK_Arabic_semicolon              0x05bb  /* U+061B ARABIC SEMICOLON */
#define XK_Arabic_question_mark          0x05bf  /* U+061F ARABIC QUESTION MARK */
#define XK_Arabic_hamza                  0x05c1  /* U+0621 ARABIC LETTER HAMZA */
#define XK_Arabic_maddaonalef            0x05c2  /* U+0622 ARABIC LETTER ALEF WITH MADDA ABOVE */
#define XK_Arabic_hamzaonalef            0x05c3  /* U+0623 ARABIC LETTER ALEF WITH HAMZA ABOVE */
#define XK_Arabic_hamzaonwaw             0x05c4  /* U+0624 ARABIC LETTER WAW WITH HAMZA ABOVE */
#define XK_Arabic_hamzaunderalef         0x05c5  /* U+0625 ARABIC LETTER ALEF WITH HAMZA BELOW */
#define XK_Arabic_hamzaonyeh             0x05c6  /* U+0626 ARABIC LETTER YEH WITH HAMZA ABOVE */
#define XK_Arabic_alef                   0x05c7  /* U+0627 ARABIC LETTER ALEF */
#define XK_Arabic_beh                    0x05c8  /* U+0628 ARABIC LETTER BEH */
#define XK_Arabic_tehmarbuta             0x05c9  /* U+0629 ARABIC LETTER TEH MARBUTA */
#define XK_Arabic_teh                    0x05ca  /* U+062A ARABIC LETTER TEH */
#define XK_Arabic_theh                   0x05cb  /* U+062B ARABIC LETTER THEH */
#define XK_Arabic_jeem                   0x05cc  /* U+062C ARABIC LETTER JEEM */
#define XK_Arabic_hah                    0x05cd  /* U+062D ARABIC LETTER HAH */
#define XK_Arabic_khah                   0x05ce  /* U+062E ARABIC LETTER KHAH */
#define XK_Arabic_dal                    0x05cf  /* U+062F ARABIC LETTER DAL */
#define XK_Arabic_thal                   0x05d0  /* U+0630 ARABIC LETTER THAL */
#define XK_Arabic_ra                     0x05d1  /* U+0631 ARABIC LETTER REH */
#define XK_Arabic_zain                   0x05d2  /* U+0632 ARABIC LETTER ZAIN */
#define XK_Arabic_seen                   0x05d3  /* U+0633 ARABIC LETTER SEEN */
#define XK_Arabic_sheen                  0x05d4  /* U+0634 ARABIC LETTER SHEEN */
#define XK_Arabic_sad                    0x05d5  /* U+0635 ARABIC LETTER SAD */
#define XK_Arabic_dad                    0x05d6  /* U+0636 ARABIC LETTER DAD */
#define XK_Arabic_tah                    0x05d7  /* U+0637 ARABIC LETTER TAH */
#define XK_Arabic_zah                    0x05d8  /* U+0638 ARABIC LETTER ZAH */
#define XK_Arabic_ain                    0x05d9  /* U+0639 ARABIC LETTER AIN */
#define XK_Arabic_ghain                  0x05da  /* U+063A ARABIC LETTER GHAIN */
#define XK_Arabic_tatweel                0x05e0  /* U+0640 ARABIC TATWEEL */
#define XK_Arabic_feh                    0x05e1  /* U+0641 ARABIC LETTER FEH */
#define XK_Arabic_qaf                    0x05e2  /* U+0642 ARABIC LETTER QAF */
#define XK_Arabic_kaf                    0x05e3  /* U+0643 ARABIC LETTER KAF */
#define XK_Arabic_lam                    0x05e4  /* U+0644 ARABIC LETTER LAM */
#define XK_Arabic_meem                   0x05e5  /* U+0645 ARABIC LETTER MEEM */
#define XK_Arabic_noon                   0x05e6  /* U+0646 ARABIC LETTER NOON */
#define XK_Arabic_ha                     0x05e7  /* U+0647 ARABIC LETTER HEH */
#define XK_Arabic_heh                    0x05e7  /* deprecated */
#define XK_Arabic_waw                    0x05e8  /* U+0648 ARABIC LETTER WAW */
#define XK_Arabic_alefmaksura            0x05e9  /* U+0649 ARABIC LETTER ALEF MAKSURA */
#define XK_Arabic_yeh                    0x05ea  /* U+064A ARABIC LETTER YEH */
#define XK_Arabic_fathatan               0x05eb  /* U+064B ARABIC FATHATAN */
#define XK_Arabic_dammatan               0x05ec  /* U+064C ARABIC DAMMATAN */
#define XK_Arabic_kasratan               0x05ed  /* U+064D ARABIC KASRATAN */
#define XK_Arabic_fatha                  0x05ee  /* U+064E ARABIC FATHA */
#define XK_Arabic_damma                  0x05ef  /* U+064F ARABIC DAMMA */
#define XK_Arabic_kasra                  0x05f0  /* U+0650 ARABIC KASRA */
#define XK_Arabic_shadda                 0x05f1  /* U+0651 ARABIC SHADDA */
#define XK_Arabic_sukun                  0x05f2  /* U+0652 ARABIC SUKUN */
#define XK_Arabic_switch                 0xff7e  /* Alias for mode_switch */
#endif /* XK_ARABIC */

/*
 * Cyrillic
 * Byte 3 = 6
 */
#ifdef XK_CYRILLIC
#define XK_Serbian_dje                                 0x6a1
#define XK_Macedonia_gje                               0x6a2
#define XK_Cyrillic_io                                 0x6a3
#define XK_Ukrainian_ie                                0x6a4
#define XK_Ukranian_je                                 0x6a4  /* deprecated */
#define XK_Macedonia_dse                               0x6a5
#define XK_Ukrainian_i                                 0x6a6
#define XK_Ukranian_i                                  0x6a6  /* deprecated */
#define XK_Ukrainian_yi                                0x6a7
#define XK_Ukranian_yi                                 0x6a7  /* deprecated */
#define XK_Cyrillic_je                                 0x6a8
#define XK_Serbian_je                                  0x6a8  /* deprecated */
#define XK_Cyrillic_lje                                0x6a9
#define XK_Serbian_lje                                 0x6a9  /* deprecated */
#define XK_Cyrillic_nje                                0x6aa
#define XK_Serbian_nje                                 0x6aa  /* deprecated */
#define XK_Serbian_tshe                                0x6ab
#define XK_Macedonia_kje                               0x6ac
#define XK_Byelorussian_shortu                         0x6ae
#define XK_Cyrillic_dzhe                               0x6af
#define XK_Serbian_dze                                 0x6af  /* deprecated */
#define XK_numerosign                                  0x6b0
#define XK_Serbian_DJE                                 0x6b1
#define XK_Macedonia_GJE                               0x6b2
#define XK_Cyrillic_IO                                 0x6b3
#define XK_Ukrainian_IE                                0x6b4
#define XK_Ukranian_JE                                 0x6b4  /* deprecated */
#define XK_Macedonia_DSE                               0x6b5
#define XK_Ukrainian_I                                 0x6b6
#define XK_Ukranian_I                                  0x6b6  /* deprecated */
#define XK_Ukrainian_YI                                0x6b7
#define XK_Ukranian_YI                                 0x6b7  /* deprecated */
#define XK_Cyrillic_JE                                 0x6b8
#define XK_Serbian_JE                                  0x6b8  /* deprecated */
#define XK_Cyrillic_LJE                                0x6b9
#define XK_Serbian_LJE                                 0x6b9  /* deprecated */
#define XK_Cyrillic_NJE                                0x6ba
#define XK_Serbian_NJE                                 0x6ba  /* deprecated */
#define XK_Serbian_TSHE                                0x6bb
#define XK_Macedonia_KJE                               0x6bc
#define XK_Byelorussian_SHORTU                         0x6be
#define XK_Cyrillic_DZHE                               0x6bf
#define XK_Serbian_DZE                                 0x6bf  /* deprecated */
#define XK_Cyrillic_yu                                 0x6c0
#define XK_Cyrillic_a                                  0x6c1
#define XK_Cyrillic_be                                 0x6c2
#define XK_Cyrillic_tse                                0x6c3
#define XK_Cyrillic_de                                 0x6c4
#define XK_Cyrillic_ie                                 0x6c5
#define XK_Cyrillic_ef                                 0x6c6
#define XK_Cyrillic_ghe                                0x6c7
#define XK_Cyrillic_ha                                 0x6c8
#define XK_Cyrillic_i                                  0x6c9
#define XK_Cyrillic_shorti                             0x6ca
#define XK_Cyrillic_ka                                 0x6cb
#define XK_Cyrillic_el                                 0x6cc
#define XK_Cyrillic_em                                 0x6cd
#define XK_Cyrillic_en                                 0x6ce
#define XK_Cyrillic_o                                  0x6cf
#define XK_Cyrillic_pe                                 0x6d0
#define XK_Cyrillic_ya                                 0x6d1
#define XK_Cyrillic_er                                 0x6d2
#define XK_Cyrillic_es                                 0x6d3
#define XK_Cyrillic_te                                 0x6d4
#define XK_Cyrillic_u                                  0x6d5
#define XK_Cyrillic_zhe                                0x6d6
#define XK_Cyrillic_ve                                 0x6d7
#define XK_Cyrillic_softsign                           0x6d8
#define XK_Cyrillic_yeru                               0x6d9
#define XK_Cyrillic_ze                                 0x6da
#define XK_Cyrillic_sha                                0x6db
#define XK_Cyrillic_e                                  0x6dc
#define XK_Cyrillic_shcha                              0x6dd
#define XK_Cyrillic_che                                0x6de
#define XK_Cyrillic_hardsign                           0x6df
#define XK_Cyrillic_YU                                 0x6e0
#define XK_Cyrillic_A                                  0x6e1
#define XK_Cyrillic_BE                                 0x6e2
#define XK_Cyrillic_TSE                                0x6e3
#define XK_Cyrillic_DE                                 0x6e4
#define XK_Cyrillic_IE                                 0x6e5
#define XK_Cyrillic_EF                                 0x6e6
#define XK_Cyrillic_GHE                                0x6e7
#define XK_Cyrillic_HA                                 0x6e8
#define XK_Cyrillic_I                                  0x6e9
#define XK_Cyrillic_SHORTI                             0x6ea
#define XK_Cyrillic_KA                                 0x6eb
#define XK_Cyrillic_EL                                 0x6ec
#define XK_Cyrillic_EM                                 0x6ed
#define XK_Cyrillic_EN                                 0x6ee
#define XK_Cyrillic_O                                  0x6ef
#define XK_Cyrillic_PE                                 0x6f0
#define XK_Cyrillic_YA                                 0x6f1
#define XK_Cyrillic_ER                                 0x6f2
#define XK_Cyrillic_ES                                 0x6f3
#define XK_Cyrillic_TE                                 0x6f4
#define XK_Cyrillic_U                                  0x6f5
#define XK_Cyrillic_ZHE                                0x6f6
#define XK_Cyrillic_VE                                 0x6f7
#define XK_Cyrillic_SOFTSIGN                           0x6f8
#define XK_Cyrillic_YERU                               0x6f9
#define XK_Cyrillic_ZE                                 0x6fa
#define XK_Cyrillic_SHA                                0x6fb
#define XK_Cyrillic_E                                  0x6fc
#define XK_Cyrillic_SHCHA                              0x6fd
#define XK_Cyrillic_CHE                                0x6fe
#define XK_Cyrillic_HARDSIGN                           0x6ff
#define XK_Serbian_dje                   0x06a1  /* U+0452 CYRILLIC SMALL LETTER DJE */
#define XK_Macedonia_gje                 0x06a2  /* U+0453 CYRILLIC SMALL LETTER GJE */
#define XK_Cyrillic_io                   0x06a3  /* U+0451 CYRILLIC SMALL LETTER IO */
#define XK_Ukrainian_ie                  0x06a4  /* U+0454 CYRILLIC SMALL LETTER UKRAINIAN IE */
#define XK_Ukranian_je                   0x06a4  /* deprecated */
#define XK_Macedonia_dse                 0x06a5  /* U+0455 CYRILLIC SMALL LETTER DZE */
#define XK_Ukrainian_i                   0x06a6  /* U+0456 CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I */
#define XK_Ukranian_i                    0x06a6  /* deprecated */
#define XK_Ukrainian_yi                  0x06a7  /* U+0457 CYRILLIC SMALL LETTER YI */
#define XK_Ukranian_yi                   0x06a7  /* deprecated */
#define XK_Cyrillic_je                   0x06a8  /* U+0458 CYRILLIC SMALL LETTER JE */
#define XK_Serbian_je                    0x06a8  /* deprecated */
#define XK_Cyrillic_lje                  0x06a9  /* U+0459 CYRILLIC SMALL LETTER LJE */
#define XK_Serbian_lje                   0x06a9  /* deprecated */
#define XK_Cyrillic_nje                  0x06aa  /* U+045A CYRILLIC SMALL LETTER NJE */
#define XK_Serbian_nje                   0x06aa  /* deprecated */
#define XK_Serbian_tshe                  0x06ab  /* U+045B CYRILLIC SMALL LETTER TSHE */
#define XK_Macedonia_kje                 0x06ac  /* U+045C CYRILLIC SMALL LETTER KJE */
#define XK_Ukrainian_ghe_with_upturn     0x06ad  /* U+0491 CYRILLIC SMALL LETTER GHE WITH UPTURN */
#define XK_Byelorussian_shortu           0x06ae  /* U+045E CYRILLIC SMALL LETTER SHORT U */
#define XK_Cyrillic_dzhe                 0x06af  /* U+045F CYRILLIC SMALL LETTER DZHE */
#define XK_Serbian_dze                   0x06af  /* deprecated */
#define XK_numerosign                    0x06b0  /* U+2116 NUMERO SIGN */
#define XK_Serbian_DJE                   0x06b1  /* U+0402 CYRILLIC CAPITAL LETTER DJE */
#define XK_Macedonia_GJE                 0x06b2  /* U+0403 CYRILLIC CAPITAL LETTER GJE */
#define XK_Cyrillic_IO                   0x06b3  /* U+0401 CYRILLIC CAPITAL LETTER IO */
#define XK_Ukrainian_IE                  0x06b4  /* U+0404 CYRILLIC CAPITAL LETTER UKRAINIAN IE */
#define XK_Ukranian_JE                   0x06b4  /* deprecated */
#define XK_Macedonia_DSE                 0x06b5  /* U+0405 CYRILLIC CAPITAL LETTER DZE */
#define XK_Ukrainian_I                   0x06b6  /* U+0406 CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I */
#define XK_Ukranian_I                    0x06b6  /* deprecated */
#define XK_Ukrainian_YI                  0x06b7  /* U+0407 CYRILLIC CAPITAL LETTER YI */
#define XK_Ukranian_YI                   0x06b7  /* deprecated */
#define XK_Cyrillic_JE                   0x06b8  /* U+0408 CYRILLIC CAPITAL LETTER JE */
#define XK_Serbian_JE                    0x06b8  /* deprecated */
#define XK_Cyrillic_LJE                  0x06b9  /* U+0409 CYRILLIC CAPITAL LETTER LJE */
#define XK_Serbian_LJE                   0x06b9  /* deprecated */
#define XK_Cyrillic_NJE                  0x06ba  /* U+040A CYRILLIC CAPITAL LETTER NJE */
#define XK_Serbian_NJE                   0x06ba  /* deprecated */
#define XK_Serbian_TSHE                  0x06bb  /* U+040B CYRILLIC CAPITAL LETTER TSHE */
#define XK_Macedonia_KJE                 0x06bc  /* U+040C CYRILLIC CAPITAL LETTER KJE */
#define XK_Ukrainian_GHE_WITH_UPTURN     0x06bd  /* U+0490 CYRILLIC CAPITAL LETTER GHE WITH UPTURN */
#define XK_Byelorussian_SHORTU           0x06be  /* U+040E CYRILLIC CAPITAL LETTER SHORT U */
#define XK_Cyrillic_DZHE                 0x06bf  /* U+040F CYRILLIC CAPITAL LETTER DZHE */
#define XK_Serbian_DZE                   0x06bf  /* deprecated */
#define XK_Cyrillic_yu                   0x06c0  /* U+044E CYRILLIC SMALL LETTER YU */
#define XK_Cyrillic_a                    0x06c1  /* U+0430 CYRILLIC SMALL LETTER A */
#define XK_Cyrillic_be                   0x06c2  /* U+0431 CYRILLIC SMALL LETTER BE */
#define XK_Cyrillic_tse                  0x06c3  /* U+0446 CYRILLIC SMALL LETTER TSE */
#define XK_Cyrillic_de                   0x06c4  /* U+0434 CYRILLIC SMALL LETTER DE */
#define XK_Cyrillic_ie                   0x06c5  /* U+0435 CYRILLIC SMALL LETTER IE */
#define XK_Cyrillic_ef                   0x06c6  /* U+0444 CYRILLIC SMALL LETTER EF */
#define XK_Cyrillic_ghe                  0x06c7  /* U+0433 CYRILLIC SMALL LETTER GHE */
#define XK_Cyrillic_ha                   0x06c8  /* U+0445 CYRILLIC SMALL LETTER HA */
#define XK_Cyrillic_i                    0x06c9  /* U+0438 CYRILLIC SMALL LETTER I */
#define XK_Cyrillic_shorti               0x06ca  /* U+0439 CYRILLIC SMALL LETTER SHORT I */
#define XK_Cyrillic_ka                   0x06cb  /* U+043A CYRILLIC SMALL LETTER KA */
#define XK_Cyrillic_el                   0x06cc  /* U+043B CYRILLIC SMALL LETTER EL */
#define XK_Cyrillic_em                   0x06cd  /* U+043C CYRILLIC SMALL LETTER EM */
#define XK_Cyrillic_en                   0x06ce  /* U+043D CYRILLIC SMALL LETTER EN */
#define XK_Cyrillic_o                    0x06cf  /* U+043E CYRILLIC SMALL LETTER O */
#define XK_Cyrillic_pe                   0x06d0  /* U+043F CYRILLIC SMALL LETTER PE */
#define XK_Cyrillic_ya                   0x06d1  /* U+044F CYRILLIC SMALL LETTER YA */
#define XK_Cyrillic_er                   0x06d2  /* U+0440 CYRILLIC SMALL LETTER ER */
#define XK_Cyrillic_es                   0x06d3  /* U+0441 CYRILLIC SMALL LETTER ES */
#define XK_Cyrillic_te                   0x06d4  /* U+0442 CYRILLIC SMALL LETTER TE */
#define XK_Cyrillic_u                    0x06d5  /* U+0443 CYRILLIC SMALL LETTER U */
#define XK_Cyrillic_zhe                  0x06d6  /* U+0436 CYRILLIC SMALL LETTER ZHE */
#define XK_Cyrillic_ve                   0x06d7  /* U+0432 CYRILLIC SMALL LETTER VE */
#define XK_Cyrillic_softsign             0x06d8  /* U+044C CYRILLIC SMALL LETTER SOFT SIGN */
#define XK_Cyrillic_yeru                 0x06d9  /* U+044B CYRILLIC SMALL LETTER YERU */
#define XK_Cyrillic_ze                   0x06da  /* U+0437 CYRILLIC SMALL LETTER ZE */
#define XK_Cyrillic_sha                  0x06db  /* U+0448 CYRILLIC SMALL LETTER SHA */
#define XK_Cyrillic_e                    0x06dc  /* U+044D CYRILLIC SMALL LETTER E */
#define XK_Cyrillic_shcha                0x06dd  /* U+0449 CYRILLIC SMALL LETTER SHCHA */
#define XK_Cyrillic_che                  0x06de  /* U+0447 CYRILLIC SMALL LETTER CHE */
#define XK_Cyrillic_hardsign             0x06df  /* U+044A CYRILLIC SMALL LETTER HARD SIGN */
#define XK_Cyrillic_YU                   0x06e0  /* U+042E CYRILLIC CAPITAL LETTER YU */
#define XK_Cyrillic_A                    0x06e1  /* U+0410 CYRILLIC CAPITAL LETTER A */
#define XK_Cyrillic_BE                   0x06e2  /* U+0411 CYRILLIC CAPITAL LETTER BE */
#define XK_Cyrillic_TSE                  0x06e3  /* U+0426 CYRILLIC CAPITAL LETTER TSE */
#define XK_Cyrillic_DE                   0x06e4  /* U+0414 CYRILLIC CAPITAL LETTER DE */
#define XK_Cyrillic_IE                   0x06e5  /* U+0415 CYRILLIC CAPITAL LETTER IE */
#define XK_Cyrillic_EF                   0x06e6  /* U+0424 CYRILLIC CAPITAL LETTER EF */
#define XK_Cyrillic_GHE                  0x06e7  /* U+0413 CYRILLIC CAPITAL LETTER GHE */
#define XK_Cyrillic_HA                   0x06e8  /* U+0425 CYRILLIC CAPITAL LETTER HA */
#define XK_Cyrillic_I                    0x06e9  /* U+0418 CYRILLIC CAPITAL LETTER I */
#define XK_Cyrillic_SHORTI               0x06ea  /* U+0419 CYRILLIC CAPITAL LETTER SHORT I */
#define XK_Cyrillic_KA                   0x06eb  /* U+041A CYRILLIC CAPITAL LETTER KA */
#define XK_Cyrillic_EL                   0x06ec  /* U+041B CYRILLIC CAPITAL LETTER EL */
#define XK_Cyrillic_EM                   0x06ed  /* U+041C CYRILLIC CAPITAL LETTER EM */
#define XK_Cyrillic_EN                   0x06ee  /* U+041D CYRILLIC CAPITAL LETTER EN */
#define XK_Cyrillic_O                    0x06ef  /* U+041E CYRILLIC CAPITAL LETTER O */
#define XK_Cyrillic_PE                   0x06f0  /* U+041F CYRILLIC CAPITAL LETTER PE */
#define XK_Cyrillic_YA                   0x06f1  /* U+042F CYRILLIC CAPITAL LETTER YA */
#define XK_Cyrillic_ER                   0x06f2  /* U+0420 CYRILLIC CAPITAL LETTER ER */
#define XK_Cyrillic_ES                   0x06f3  /* U+0421 CYRILLIC CAPITAL LETTER ES */
#define XK_Cyrillic_TE                   0x06f4  /* U+0422 CYRILLIC CAPITAL LETTER TE */
#define XK_Cyrillic_U                    0x06f5  /* U+0423 CYRILLIC CAPITAL LETTER U */
#define XK_Cyrillic_ZHE                  0x06f6  /* U+0416 CYRILLIC CAPITAL LETTER ZHE */
#define XK_Cyrillic_VE                   0x06f7  /* U+0412 CYRILLIC CAPITAL LETTER VE */
#define XK_Cyrillic_SOFTSIGN             0x06f8  /* U+042C CYRILLIC CAPITAL LETTER SOFT SIGN */
#define XK_Cyrillic_YERU                 0x06f9  /* U+042B CYRILLIC CAPITAL LETTER YERU */
#define XK_Cyrillic_ZE                   0x06fa  /* U+0417 CYRILLIC CAPITAL LETTER ZE */
#define XK_Cyrillic_SHA                  0x06fb  /* U+0428 CYRILLIC CAPITAL LETTER SHA */
#define XK_Cyrillic_E                    0x06fc  /* U+042D CYRILLIC CAPITAL LETTER E */
#define XK_Cyrillic_SHCHA                0x06fd  /* U+0429 CYRILLIC CAPITAL LETTER SHCHA */
#define XK_Cyrillic_CHE                  0x06fe  /* U+0427 CYRILLIC CAPITAL LETTER CHE */
#define XK_Cyrillic_HARDSIGN             0x06ff  /* U+042A CYRILLIC CAPITAL LETTER HARD SIGN */
#endif /* XK_CYRILLIC */

/*
 * Greek
 * (based on an early draft of, and not quite identical to, ISO/IEC 8859-7)
 * Byte 3 = 7
 */

#ifdef XK_GREEK
#define XK_Greek_ALPHAaccent                           0x7a1
#define XK_Greek_EPSILONaccent                         0x7a2
#define XK_Greek_ETAaccent                             0x7a3
#define XK_Greek_IOTAaccent                            0x7a4
#define XK_Greek_IOTAdieresis                          0x7a5
#define XK_Greek_IOTAdiaeresis                         0x7a5
#define XK_Greek_OMICRONaccent                         0x7a7
#define XK_Greek_UPSILONaccent                         0x7a8
#define XK_Greek_UPSILONdieresis                       0x7a9
#define XK_Greek_OMEGAaccent                           0x7ab
#define XK_Greek_accentdieresis                        0x7ae
#define XK_Greek_horizbar                              0x7af
#define XK_Greek_alphaaccent                           0x7b1
#define XK_Greek_epsilonaccent                         0x7b2
#define XK_Greek_etaaccent                             0x7b3
#define XK_Greek_iotaaccent                            0x7b4
#define XK_Greek_iotadieresis                          0x7b5
#define XK_Greek_iotaaccentdieresis                    0x7b6
#define XK_Greek_omicronaccent                         0x7b7
#define XK_Greek_upsilonaccent                         0x7b8
#define XK_Greek_upsilondieresis                       0x7b9
#define XK_Greek_upsilonaccentdieresis                 0x7ba
#define XK_Greek_omegaaccent                           0x7bb
#define XK_Greek_ALPHA                                 0x7c1
#define XK_Greek_BETA                                  0x7c2
#define XK_Greek_GAMMA                                 0x7c3
#define XK_Greek_DELTA                                 0x7c4
#define XK_Greek_EPSILON                               0x7c5
#define XK_Greek_ZETA                                  0x7c6
#define XK_Greek_ETA                                   0x7c7
#define XK_Greek_THETA                                 0x7c8
#define XK_Greek_IOTA                                  0x7c9
#define XK_Greek_KAPPA                                 0x7ca
#define XK_Greek_LAMDA                                 0x7cb
#define XK_Greek_LAMBDA                                0x7cb
#define XK_Greek_MU                                    0x7cc
#define XK_Greek_NU                                    0x7cd
#define XK_Greek_XI                                    0x7ce
#define XK_Greek_OMICRON                               0x7cf
#define XK_Greek_PI                                    0x7d0
#define XK_Greek_RHO                                   0x7d1
#define XK_Greek_SIGMA                                 0x7d2
#define XK_Greek_TAU                                   0x7d4
#define XK_Greek_UPSILON                               0x7d5
#define XK_Greek_PHI                                   0x7d6
#define XK_Greek_CHI                                   0x7d7
#define XK_Greek_PSI                                   0x7d8
#define XK_Greek_OMEGA                                 0x7d9
#define XK_Greek_alpha                                 0x7e1
#define XK_Greek_beta                                  0x7e2
#define XK_Greek_gamma                                 0x7e3
#define XK_Greek_delta                                 0x7e4
#define XK_Greek_epsilon                               0x7e5
#define XK_Greek_zeta                                  0x7e6
#define XK_Greek_eta                                   0x7e7
#define XK_Greek_theta                                 0x7e8
#define XK_Greek_iota                                  0x7e9
#define XK_Greek_kappa                                 0x7ea
#define XK_Greek_lamda                                 0x7eb
#define XK_Greek_lambda                                0x7eb
#define XK_Greek_mu                                    0x7ec
#define XK_Greek_nu                                    0x7ed
#define XK_Greek_xi                                    0x7ee
#define XK_Greek_omicron                               0x7ef
#define XK_Greek_pi                                    0x7f0
#define XK_Greek_rho                                   0x7f1
#define XK_Greek_sigma                                 0x7f2
#define XK_Greek_finalsmallsigma                       0x7f3
#define XK_Greek_tau                                   0x7f4
#define XK_Greek_upsilon                               0x7f5
#define XK_Greek_phi                                   0x7f6
#define XK_Greek_chi                                   0x7f7
#define XK_Greek_psi                                   0x7f8
#define XK_Greek_omega                                 0x7f9
#define XK_Greek_switch         0xFF7E  /* Alias for mode_switch */
#define XK_Greek_ALPHAaccent             0x07a1  /* U+0386 GREEK CAPITAL LETTER ALPHA WITH TONOS */
#define XK_Greek_EPSILONaccent           0x07a2  /* U+0388 GREEK CAPITAL LETTER EPSILON WITH TONOS */
#define XK_Greek_ETAaccent               0x07a3  /* U+0389 GREEK CAPITAL LETTER ETA WITH TONOS */
#define XK_Greek_IOTAaccent              0x07a4  /* U+038A GREEK CAPITAL LETTER IOTA WITH TONOS */
#define XK_Greek_IOTAdieresis            0x07a5  /* U+03AA GREEK CAPITAL LETTER IOTA WITH DIALYTIKA */
#define XK_Greek_IOTAdiaeresis           0x07a5  /* old typo */
#define XK_Greek_OMICRONaccent           0x07a7  /* U+038C GREEK CAPITAL LETTER OMICRON WITH TONOS */
#define XK_Greek_UPSILONaccent           0x07a8  /* U+038E GREEK CAPITAL LETTER UPSILON WITH TONOS */
#define XK_Greek_UPSILONdieresis         0x07a9  /* U+03AB GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA */
#define XK_Greek_OMEGAaccent             0x07ab  /* U+038F GREEK CAPITAL LETTER OMEGA WITH TONOS */
#define XK_Greek_accentdieresis          0x07ae  /* U+0385 GREEK DIALYTIKA TONOS */
#define XK_Greek_horizbar                0x07af  /* U+2015 HORIZONTAL BAR */
#define XK_Greek_alphaaccent             0x07b1  /* U+03AC GREEK SMALL LETTER ALPHA WITH TONOS */
#define XK_Greek_epsilonaccent           0x07b2  /* U+03AD GREEK SMALL LETTER EPSILON WITH TONOS */
#define XK_Greek_etaaccent               0x07b3  /* U+03AE GREEK SMALL LETTER ETA WITH TONOS */
#define XK_Greek_iotaaccent              0x07b4  /* U+03AF GREEK SMALL LETTER IOTA WITH TONOS */
#define XK_Greek_iotadieresis            0x07b5  /* U+03CA GREEK SMALL LETTER IOTA WITH DIALYTIKA */
#define XK_Greek_iotaaccentdieresis      0x07b6  /* U+0390 GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS */
#define XK_Greek_omicronaccent           0x07b7  /* U+03CC GREEK SMALL LETTER OMICRON WITH TONOS */
#define XK_Greek_upsilonaccent           0x07b8  /* U+03CD GREEK SMALL LETTER UPSILON WITH TONOS */
#define XK_Greek_upsilondieresis         0x07b9  /* U+03CB GREEK SMALL LETTER UPSILON WITH DIALYTIKA */
#define XK_Greek_upsilonaccentdieresis   0x07ba  /* U+03B0 GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS */
#define XK_Greek_omegaaccent             0x07bb  /* U+03CE GREEK SMALL LETTER OMEGA WITH TONOS */
#define XK_Greek_ALPHA                   0x07c1  /* U+0391 GREEK CAPITAL LETTER ALPHA */
#define XK_Greek_BETA                    0x07c2  /* U+0392 GREEK CAPITAL LETTER BETA */
#define XK_Greek_GAMMA                   0x07c3  /* U+0393 GREEK CAPITAL LETTER GAMMA */
#define XK_Greek_DELTA                   0x07c4  /* U+0394 GREEK CAPITAL LETTER DELTA */
#define XK_Greek_EPSILON                 0x07c5  /* U+0395 GREEK CAPITAL LETTER EPSILON */
#define XK_Greek_ZETA                    0x07c6  /* U+0396 GREEK CAPITAL LETTER ZETA */
#define XK_Greek_ETA                     0x07c7  /* U+0397 GREEK CAPITAL LETTER ETA */
#define XK_Greek_THETA                   0x07c8  /* U+0398 GREEK CAPITAL LETTER THETA */
#define XK_Greek_IOTA                    0x07c9  /* U+0399 GREEK CAPITAL LETTER IOTA */
#define XK_Greek_KAPPA                   0x07ca  /* U+039A GREEK CAPITAL LETTER KAPPA */
#define XK_Greek_LAMDA                   0x07cb  /* U+039B GREEK CAPITAL LETTER LAMDA */
#define XK_Greek_LAMBDA                  0x07cb  /* U+039B GREEK CAPITAL LETTER LAMDA */
#define XK_Greek_MU                      0x07cc  /* U+039C GREEK CAPITAL LETTER MU */
#define XK_Greek_NU                      0x07cd  /* U+039D GREEK CAPITAL LETTER NU */
#define XK_Greek_XI                      0x07ce  /* U+039E GREEK CAPITAL LETTER XI */
#define XK_Greek_OMICRON                 0x07cf  /* U+039F GREEK CAPITAL LETTER OMICRON */
#define XK_Greek_PI                      0x07d0  /* U+03A0 GREEK CAPITAL LETTER PI */
#define XK_Greek_RHO                     0x07d1  /* U+03A1 GREEK CAPITAL LETTER RHO */
#define XK_Greek_SIGMA                   0x07d2  /* U+03A3 GREEK CAPITAL LETTER SIGMA */
#define XK_Greek_TAU                     0x07d4  /* U+03A4 GREEK CAPITAL LETTER TAU */
#define XK_Greek_UPSILON                 0x07d5  /* U+03A5 GREEK CAPITAL LETTER UPSILON */
#define XK_Greek_PHI                     0x07d6  /* U+03A6 GREEK CAPITAL LETTER PHI */
#define XK_Greek_CHI                     0x07d7  /* U+03A7 GREEK CAPITAL LETTER CHI */
#define XK_Greek_PSI                     0x07d8  /* U+03A8 GREEK CAPITAL LETTER PSI */
#define XK_Greek_OMEGA                   0x07d9  /* U+03A9 GREEK CAPITAL LETTER OMEGA */
#define XK_Greek_alpha                   0x07e1  /* U+03B1 GREEK SMALL LETTER ALPHA */
#define XK_Greek_beta                    0x07e2  /* U+03B2 GREEK SMALL LETTER BETA */
#define XK_Greek_gamma                   0x07e3  /* U+03B3 GREEK SMALL LETTER GAMMA */
#define XK_Greek_delta                   0x07e4  /* U+03B4 GREEK SMALL LETTER DELTA */
#define XK_Greek_epsilon                 0x07e5  /* U+03B5 GREEK SMALL LETTER EPSILON */
#define XK_Greek_zeta                    0x07e6  /* U+03B6 GREEK SMALL LETTER ZETA */
#define XK_Greek_eta                     0x07e7  /* U+03B7 GREEK SMALL LETTER ETA */
#define XK_Greek_theta                   0x07e8  /* U+03B8 GREEK SMALL LETTER THETA */
#define XK_Greek_iota                    0x07e9  /* U+03B9 GREEK SMALL LETTER IOTA */
#define XK_Greek_kappa                   0x07ea  /* U+03BA GREEK SMALL LETTER KAPPA */
#define XK_Greek_lamda                   0x07eb  /* U+03BB GREEK SMALL LETTER LAMDA */
#define XK_Greek_lambda                  0x07eb  /* U+03BB GREEK SMALL LETTER LAMDA */
#define XK_Greek_mu                      0x07ec  /* U+03BC GREEK SMALL LETTER MU */
#define XK_Greek_nu                      0x07ed  /* U+03BD GREEK SMALL LETTER NU */
#define XK_Greek_xi                      0x07ee  /* U+03BE GREEK SMALL LETTER XI */
#define XK_Greek_omicron                 0x07ef  /* U+03BF GREEK SMALL LETTER OMICRON */
#define XK_Greek_pi                      0x07f0  /* U+03C0 GREEK SMALL LETTER PI */
#define XK_Greek_rho                     0x07f1  /* U+03C1 GREEK SMALL LETTER RHO */
#define XK_Greek_sigma                   0x07f2  /* U+03C3 GREEK SMALL LETTER SIGMA */
#define XK_Greek_finalsmallsigma         0x07f3  /* U+03C2 GREEK SMALL LETTER FINAL SIGMA */
#define XK_Greek_tau                     0x07f4  /* U+03C4 GREEK SMALL LETTER TAU */
#define XK_Greek_upsilon                 0x07f5  /* U+03C5 GREEK SMALL LETTER UPSILON */
#define XK_Greek_phi                     0x07f6  /* U+03C6 GREEK SMALL LETTER PHI */
#define XK_Greek_chi                     0x07f7  /* U+03C7 GREEK SMALL LETTER CHI */
#define XK_Greek_psi                     0x07f8  /* U+03C8 GREEK SMALL LETTER PSI */
#define XK_Greek_omega                   0x07f9  /* U+03C9 GREEK SMALL LETTER OMEGA */
#define XK_Greek_switch                  0xff7e  /* Alias for mode_switch */
#endif /* XK_GREEK */

/*
 * Technical
 * (from the DEC VT330/VT420 Technical Character Set, http://vt100.net/charsets/technical.html)
 * Byte 3 = 8
 */

#ifdef XK_TECHNICAL
#define XK_leftradical                                 0x8a1
#define XK_topleftradical                              0x8a2
#define XK_horizconnector                              0x8a3
#define XK_topintegral                                 0x8a4
#define XK_botintegral                                 0x8a5
#define XK_vertconnector                               0x8a6
#define XK_topleftsqbracket                            0x8a7
#define XK_botleftsqbracket                            0x8a8
#define XK_toprightsqbracket                           0x8a9
#define XK_botrightsqbracket                           0x8aa
#define XK_topleftparens                               0x8ab
#define XK_botleftparens                               0x8ac
#define XK_toprightparens                              0x8ad
#define XK_botrightparens                              0x8ae
#define XK_leftmiddlecurlybrace                        0x8af
#define XK_rightmiddlecurlybrace                       0x8b0
#define XK_topleftsummation                            0x8b1
#define XK_botleftsummation                            0x8b2
#define XK_topvertsummationconnector                   0x8b3
#define XK_botvertsummationconnector                   0x8b4
#define XK_toprightsummation                           0x8b5
#define XK_botrightsummation                           0x8b6
#define XK_rightmiddlesummation                        0x8b7
#define XK_lessthanequal                               0x8bc
#define XK_notequal                                    0x8bd
#define XK_greaterthanequal                            0x8be
#define XK_integral                                    0x8bf
#define XK_therefore                                   0x8c0
#define XK_variation                                   0x8c1
#define XK_infinity                                    0x8c2
#define XK_nabla                                       0x8c5
#define XK_approximate                                 0x8c8
#define XK_similarequal                                0x8c9
#define XK_ifonlyif                                    0x8cd
#define XK_implies                                     0x8ce
#define XK_identical                                   0x8cf
#define XK_radical                                     0x8d6
#define XK_includedin                                  0x8da
#define XK_includes                                    0x8db
#define XK_intersection                                0x8dc
#define XK_union                                       0x8dd
#define XK_logicaland                                  0x8de
#define XK_logicalor                                   0x8df
#define XK_partialderivative                           0x8ef
#define XK_function                                    0x8f6
#define XK_leftarrow                                   0x8fb
#define XK_uparrow                                     0x8fc
#define XK_rightarrow                                  0x8fd
#define XK_downarrow                                   0x8fe
#define XK_leftradical                   0x08a1  /* U+23B7 RADICAL SYMBOL BOTTOM */
#define XK_topleftradical                0x08a2  /*(U+250C BOX DRAWINGS LIGHT DOWN AND RIGHT)*/
#define XK_horizconnector                0x08a3  /*(U+2500 BOX DRAWINGS LIGHT HORIZONTAL)*/
#define XK_topintegral                   0x08a4  /* U+2320 TOP HALF INTEGRAL */
#define XK_botintegral                   0x08a5  /* U+2321 BOTTOM HALF INTEGRAL */
#define XK_vertconnector                 0x08a6  /*(U+2502 BOX DRAWINGS LIGHT VERTICAL)*/
#define XK_topleftsqbracket              0x08a7  /* U+23A1 LEFT SQUARE BRACKET UPPER CORNER */
#define XK_botleftsqbracket              0x08a8  /* U+23A3 LEFT SQUARE BRACKET LOWER CORNER */
#define XK_toprightsqbracket             0x08a9  /* U+23A4 RIGHT SQUARE BRACKET UPPER CORNER */
#define XK_botrightsqbracket             0x08aa  /* U+23A6 RIGHT SQUARE BRACKET LOWER CORNER */
#define XK_topleftparens                 0x08ab  /* U+239B LEFT PARENTHESIS UPPER HOOK */
#define XK_botleftparens                 0x08ac  /* U+239D LEFT PARENTHESIS LOWER HOOK */
#define XK_toprightparens                0x08ad  /* U+239E RIGHT PARENTHESIS UPPER HOOK */
#define XK_botrightparens                0x08ae  /* U+23A0 RIGHT PARENTHESIS LOWER HOOK */
#define XK_leftmiddlecurlybrace          0x08af  /* U+23A8 LEFT CURLY BRACKET MIDDLE PIECE */
#define XK_rightmiddlecurlybrace         0x08b0  /* U+23AC RIGHT CURLY BRACKET MIDDLE PIECE */
#define XK_topleftsummation              0x08b1
#define XK_botleftsummation              0x08b2
#define XK_topvertsummationconnector     0x08b3
#define XK_botvertsummationconnector     0x08b4
#define XK_toprightsummation             0x08b5
#define XK_botrightsummation             0x08b6
#define XK_rightmiddlesummation          0x08b7
#define XK_lessthanequal                 0x08bc  /* U+2264 LESS-THAN OR EQUAL TO */
#define XK_notequal                      0x08bd  /* U+2260 NOT EQUAL TO */
#define XK_greaterthanequal              0x08be  /* U+2265 GREATER-THAN OR EQUAL TO */
#define XK_integral                      0x08bf  /* U+222B INTEGRAL */
#define XK_therefore                     0x08c0  /* U+2234 THEREFORE */
#define XK_variation                     0x08c1  /* U+221D PROPORTIONAL TO */
#define XK_infinity                      0x08c2  /* U+221E INFINITY */
#define XK_nabla                         0x08c5  /* U+2207 NABLA */
#define XK_approximate                   0x08c8  /* U+223C TILDE OPERATOR */
#define XK_similarequal                  0x08c9  /* U+2243 ASYMPTOTICALLY EQUAL TO */
#define XK_ifonlyif                      0x08cd  /* U+21D4 LEFT RIGHT DOUBLE ARROW */
#define XK_implies                       0x08ce  /* U+21D2 RIGHTWARDS DOUBLE ARROW */
#define XK_identical                     0x08cf  /* U+2261 IDENTICAL TO */
#define XK_radical                       0x08d6  /* U+221A SQUARE ROOT */
#define XK_includedin                    0x08da  /* U+2282 SUBSET OF */
#define XK_includes                      0x08db  /* U+2283 SUPERSET OF */
#define XK_intersection                  0x08dc  /* U+2229 INTERSECTION */
#define XK_union                         0x08dd  /* U+222A UNION */
#define XK_logicaland                    0x08de  /* U+2227 LOGICAL AND */
#define XK_logicalor                     0x08df  /* U+2228 LOGICAL OR */
#define XK_partialderivative             0x08ef  /* U+2202 PARTIAL DIFFERENTIAL */
#define XK_function                      0x08f6  /* U+0192 LATIN SMALL LETTER F WITH HOOK */
#define XK_leftarrow                     0x08fb  /* U+2190 LEFTWARDS ARROW */
#define XK_uparrow                       0x08fc  /* U+2191 UPWARDS ARROW */
#define XK_rightarrow                    0x08fd  /* U+2192 RIGHTWARDS ARROW */
#define XK_downarrow                     0x08fe  /* U+2193 DOWNWARDS ARROW */
#endif /* XK_TECHNICAL */

/*
 *  Special
 *  Byte 3 = 9
 * Special
 * (from the DEC VT100 Special Graphics Character Set)
 * Byte 3 = 9
 */

#ifdef XK_SPECIAL
#define XK_blank                                       0x9df
#define XK_soliddiamond                                0x9e0
#define XK_checkerboard                                0x9e1
#define XK_ht                                          0x9e2
#define XK_ff                                          0x9e3
#define XK_cr                                          0x9e4
#define XK_lf                                          0x9e5
#define XK_nl                                          0x9e8
#define XK_vt                                          0x9e9
#define XK_lowrightcorner                              0x9ea
#define XK_uprightcorner                               0x9eb
#define XK_upleftcorner                                0x9ec
#define XK_lowleftcorner                               0x9ed
#define XK_crossinglines                               0x9ee
#define XK_horizlinescan1                              0x9ef
#define XK_horizlinescan3                              0x9f0
#define XK_horizlinescan5                              0x9f1
#define XK_horizlinescan7                              0x9f2
#define XK_horizlinescan9                              0x9f3
#define XK_leftt                                       0x9f4
#define XK_rightt                                      0x9f5
#define XK_bott                                        0x9f6
#define XK_topt                                        0x9f7
#define XK_vertbar                                     0x9f8
#define XK_blank                         0x09df
#define XK_soliddiamond                  0x09e0  /* U+25C6 BLACK DIAMOND */
#define XK_checkerboard                  0x09e1  /* U+2592 MEDIUM SHADE */
#define XK_ht                            0x09e2  /* U+2409 SYMBOL FOR HORIZONTAL TABULATION */
#define XK_ff                            0x09e3  /* U+240C SYMBOL FOR FORM FEED */
#define XK_cr                            0x09e4  /* U+240D SYMBOL FOR CARRIAGE RETURN */
#define XK_lf                            0x09e5  /* U+240A SYMBOL FOR LINE FEED */
#define XK_nl                            0x09e8  /* U+2424 SYMBOL FOR NEWLINE */
#define XK_vt                            0x09e9  /* U+240B SYMBOL FOR VERTICAL TABULATION */
#define XK_lowrightcorner                0x09ea  /* U+2518 BOX DRAWINGS LIGHT UP AND LEFT */
#define XK_uprightcorner                 0x09eb  /* U+2510 BOX DRAWINGS LIGHT DOWN AND LEFT */
#define XK_upleftcorner                  0x09ec  /* U+250C BOX DRAWINGS LIGHT DOWN AND RIGHT */
#define XK_lowleftcorner                 0x09ed  /* U+2514 BOX DRAWINGS LIGHT UP AND RIGHT */
#define XK_crossinglines                 0x09ee  /* U+253C BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */
#define XK_horizlinescan1                0x09ef  /* U+23BA HORIZONTAL SCAN LINE-1 */
#define XK_horizlinescan3                0x09f0  /* U+23BB HORIZONTAL SCAN LINE-3 */
#define XK_horizlinescan5                0x09f1  /* U+2500 BOX DRAWINGS LIGHT HORIZONTAL */
#define XK_horizlinescan7                0x09f2  /* U+23BC HORIZONTAL SCAN LINE-7 */
#define XK_horizlinescan9                0x09f3  /* U+23BD HORIZONTAL SCAN LINE-9 */
#define XK_leftt                         0x09f4  /* U+251C BOX DRAWINGS LIGHT VERTICAL AND RIGHT */
#define XK_rightt                        0x09f5  /* U+2524 BOX DRAWINGS LIGHT VERTICAL AND LEFT */
#define XK_bott                          0x09f6  /* U+2534 BOX DRAWINGS LIGHT UP AND HORIZONTAL */
#define XK_topt                          0x09f7  /* U+252C BOX DRAWINGS LIGHT DOWN AND HORIZONTAL */
#define XK_vertbar                       0x09f8  /* U+2502 BOX DRAWINGS LIGHT VERTICAL */
#endif /* XK_SPECIAL */

/*
 *  Publishing
 *  Byte 3 = a
 * Publishing
 * (these are probably from a long forgotten DEC Publishing
 * font that once shipped with DECwrite)
 * Byte 3 = 0x0a
 */

#ifdef XK_PUBLISHING
#define XK_emspace                                     0xaa1
#define XK_enspace                                     0xaa2
#define XK_em3space                                    0xaa3
#define XK_em4space                                    0xaa4
#define XK_digitspace                                  0xaa5
#define XK_punctspace                                  0xaa6
#define XK_thinspace                                   0xaa7
#define XK_hairspace                                   0xaa8
#define XK_emdash                                      0xaa9
#define XK_endash                                      0xaaa
#define XK_signifblank                                 0xaac
#define XK_ellipsis                                    0xaae
#define XK_doubbaselinedot                             0xaaf
#define XK_onethird                                    0xab0
#define XK_twothirds                                   0xab1
#define XK_onefifth                                    0xab2
#define XK_twofifths                                   0xab3
#define XK_threefifths                                 0xab4
#define XK_fourfifths                                  0xab5
#define XK_onesixth                                    0xab6
#define XK_fivesixths                                  0xab7
#define XK_careof                                      0xab8
#define XK_figdash                                     0xabb
#define XK_leftanglebracket                            0xabc
#define XK_decimalpoint                                0xabd
#define XK_rightanglebracket                           0xabe
#define XK_marker                                      0xabf
#define XK_oneeighth                                   0xac3
#define XK_threeeighths                                0xac4
#define XK_fiveeighths                                 0xac5
#define XK_seveneighths                                0xac6
#define XK_trademark                                   0xac9
#define XK_signaturemark                               0xaca
#define XK_trademarkincircle                           0xacb
#define XK_leftopentriangle                            0xacc
#define XK_rightopentriangle                           0xacd
#define XK_emopencircle                                0xace
#define XK_emopenrectangle                             0xacf
#define XK_leftsinglequotemark                         0xad0
#define XK_rightsinglequotemark                        0xad1
#define XK_leftdoublequotemark                         0xad2
#define XK_rightdoublequotemark                        0xad3
#define XK_prescription                                0xad4
#define XK_minutes                                     0xad6
#define XK_seconds                                     0xad7
#define XK_latincross                                  0xad9
#define XK_hexagram                                    0xada
#define XK_filledrectbullet                            0xadb
#define XK_filledlefttribullet                         0xadc
#define XK_filledrighttribullet                        0xadd
#define XK_emfilledcircle                              0xade
#define XK_emfilledrect                                0xadf
#define XK_enopencircbullet                            0xae0
#define XK_enopensquarebullet                          0xae1
#define XK_openrectbullet                              0xae2
#define XK_opentribulletup                             0xae3
#define XK_opentribulletdown                           0xae4
#define XK_openstar                                    0xae5
#define XK_enfilledcircbullet                          0xae6
#define XK_enfilledsqbullet                            0xae7
#define XK_filledtribulletup                           0xae8
#define XK_filledtribulletdown                         0xae9
#define XK_leftpointer                                 0xaea
#define XK_rightpointer                                0xaeb
#define XK_club                                        0xaec
#define XK_diamond                                     0xaed
#define XK_heart                                       0xaee
#define XK_maltesecross                                0xaf0
#define XK_dagger                                      0xaf1
#define XK_doubledagger                                0xaf2
#define XK_checkmark                                   0xaf3
#define XK_ballotcross                                 0xaf4
#define XK_musicalsharp                                0xaf5
#define XK_musicalflat                                 0xaf6
#define XK_malesymbol                                  0xaf7
#define XK_femalesymbol                                0xaf8
#define XK_telephone                                   0xaf9
#define XK_telephonerecorder                           0xafa
#define XK_phonographcopyright                         0xafb
#define XK_caret                                       0xafc
#define XK_singlelowquotemark                          0xafd
#define XK_doublelowquotemark                          0xafe
#define XK_cursor                                      0xaff
#define XK_emspace                       0x0aa1  /* U+2003 EM SPACE */
#define XK_enspace                       0x0aa2  /* U+2002 EN SPACE */
#define XK_em3space                      0x0aa3  /* U+2004 THREE-PER-EM SPACE */
#define XK_em4space                      0x0aa4  /* U+2005 FOUR-PER-EM SPACE */
#define XK_digitspace                    0x0aa5  /* U+2007 FIGURE SPACE */
#define XK_punctspace                    0x0aa6  /* U+2008 PUNCTUATION SPACE */
#define XK_thinspace                     0x0aa7  /* U+2009 THIN SPACE */
#define XK_hairspace                     0x0aa8  /* U+200A HAIR SPACE */
#define XK_emdash                        0x0aa9  /* U+2014 EM DASH */
#define XK_endash                        0x0aaa  /* U+2013 EN DASH */
#define XK_signifblank                   0x0aac  /*(U+2423 OPEN BOX)*/
#define XK_ellipsis                      0x0aae  /* U+2026 HORIZONTAL ELLIPSIS */
#define XK_doubbaselinedot               0x0aaf  /* U+2025 TWO DOT LEADER */
#define XK_onethird                      0x0ab0  /* U+2153 VULGAR FRACTION ONE THIRD */
#define XK_twothirds                     0x0ab1  /* U+2154 VULGAR FRACTION TWO THIRDS */
#define XK_onefifth                      0x0ab2  /* U+2155 VULGAR FRACTION ONE FIFTH */
#define XK_twofifths                     0x0ab3  /* U+2156 VULGAR FRACTION TWO FIFTHS */
#define XK_threefifths                   0x0ab4  /* U+2157 VULGAR FRACTION THREE FIFTHS */
#define XK_fourfifths                    0x0ab5  /* U+2158 VULGAR FRACTION FOUR FIFTHS */
#define XK_onesixth                      0x0ab6  /* U+2159 VULGAR FRACTION ONE SIXTH */
#define XK_fivesixths                    0x0ab7  /* U+215A VULGAR FRACTION FIVE SIXTHS */
#define XK_careof                        0x0ab8  /* U+2105 CARE OF */
#define XK_figdash                       0x0abb  /* U+2012 FIGURE DASH */
#define XK_leftanglebracket              0x0abc  /*(U+27E8 MATHEMATICAL LEFT ANGLE BRACKET)*/
#define XK_decimalpoint                  0x0abd  /*(U+002E FULL STOP)*/
#define XK_rightanglebracket             0x0abe  /*(U+27E9 MATHEMATICAL RIGHT ANGLE BRACKET)*/
#define XK_marker                        0x0abf
#define XK_oneeighth                     0x0ac3  /* U+215B VULGAR FRACTION ONE EIGHTH */
#define XK_threeeighths                  0x0ac4  /* U+215C VULGAR FRACTION THREE EIGHTHS */
#define XK_fiveeighths                   0x0ac5  /* U+215D VULGAR FRACTION FIVE EIGHTHS */
#define XK_seveneighths                  0x0ac6  /* U+215E VULGAR FRACTION SEVEN EIGHTHS */
#define XK_trademark                     0x0ac9  /* U+2122 TRADE MARK SIGN */
#define XK_signaturemark                 0x0aca  /*(U+2613 SALTIRE)*/
#define XK_trademarkincircle             0x0acb
#define XK_leftopentriangle              0x0acc  /*(U+25C1 WHITE LEFT-POINTING TRIANGLE)*/
#define XK_rightopentriangle             0x0acd  /*(U+25B7 WHITE RIGHT-POINTING TRIANGLE)*/
#define XK_emopencircle                  0x0ace  /*(U+25CB WHITE CIRCLE)*/
#define XK_emopenrectangle               0x0acf  /*(U+25AF WHITE VERTICAL RECTANGLE)*/
#define XK_leftsinglequotemark           0x0ad0  /* U+2018 LEFT SINGLE QUOTATION MARK */
#define XK_rightsinglequotemark          0x0ad1  /* U+2019 RIGHT SINGLE QUOTATION MARK */
#define XK_leftdoublequotemark           0x0ad2  /* U+201C LEFT DOUBLE QUOTATION MARK */
#define XK_rightdoublequotemark          0x0ad3  /* U+201D RIGHT DOUBLE QUOTATION MARK */
#define XK_prescription                  0x0ad4  /* U+211E PRESCRIPTION TAKE */
#define XK_permille                      0x0ad5  /* U+2030 PER MILLE SIGN */
#define XK_minutes                       0x0ad6  /* U+2032 PRIME */
#define XK_seconds                       0x0ad7  /* U+2033 DOUBLE PRIME */
#define XK_latincross                    0x0ad9  /* U+271D LATIN CROSS */
#define XK_hexagram                      0x0ada
#define XK_filledrectbullet              0x0adb  /*(U+25AC BLACK RECTANGLE)*/
#define XK_filledlefttribullet           0x0adc  /*(U+25C0 BLACK LEFT-POINTING TRIANGLE)*/
#define XK_filledrighttribullet          0x0add  /*(U+25B6 BLACK RIGHT-POINTING TRIANGLE)*/
#define XK_emfilledcircle                0x0ade  /*(U+25CF BLACK CIRCLE)*/
#define XK_emfilledrect                  0x0adf  /*(U+25AE BLACK VERTICAL RECTANGLE)*/
#define XK_enopencircbullet              0x0ae0  /*(U+25E6 WHITE BULLET)*/
#define XK_enopensquarebullet            0x0ae1  /*(U+25AB WHITE SMALL SQUARE)*/
#define XK_openrectbullet                0x0ae2  /*(U+25AD WHITE RECTANGLE)*/
#define XK_opentribulletup               0x0ae3  /*(U+25B3 WHITE UP-POINTING TRIANGLE)*/
#define XK_opentribulletdown             0x0ae4  /*(U+25BD WHITE DOWN-POINTING TRIANGLE)*/
#define XK_openstar                      0x0ae5  /*(U+2606 WHITE STAR)*/
#define XK_enfilledcircbullet            0x0ae6  /*(U+2022 BULLET)*/
#define XK_enfilledsqbullet              0x0ae7  /*(U+25AA BLACK SMALL SQUARE)*/
#define XK_filledtribulletup             0x0ae8  /*(U+25B2 BLACK UP-POINTING TRIANGLE)*/
#define XK_filledtribulletdown           0x0ae9  /*(U+25BC BLACK DOWN-POINTING TRIANGLE)*/
#define XK_leftpointer                   0x0aea  /*(U+261C WHITE LEFT POINTING INDEX)*/
#define XK_rightpointer                  0x0aeb  /*(U+261E WHITE RIGHT POINTING INDEX)*/
#define XK_club                          0x0aec  /* U+2663 BLACK CLUB SUIT */
#define XK_diamond                       0x0aed  /* U+2666 BLACK DIAMOND SUIT */
#define XK_heart                         0x0aee  /* U+2665 BLACK HEART SUIT */
#define XK_maltesecross                  0x0af0  /* U+2720 MALTESE CROSS */
#define XK_dagger                        0x0af1  /* U+2020 DAGGER */
#define XK_doubledagger                  0x0af2  /* U+2021 DOUBLE DAGGER */
#define XK_checkmark                     0x0af3  /* U+2713 CHECK MARK */
#define XK_ballotcross                   0x0af4  /* U+2717 BALLOT X */
#define XK_musicalsharp                  0x0af5  /* U+266F MUSIC SHARP SIGN */
#define XK_musicalflat                   0x0af6  /* U+266D MUSIC FLAT SIGN */
#define XK_malesymbol                    0x0af7  /* U+2642 MALE SIGN */
#define XK_femalesymbol                  0x0af8  /* U+2640 FEMALE SIGN */
#define XK_telephone                     0x0af9  /* U+260E BLACK TELEPHONE */
#define XK_telephonerecorder             0x0afa  /* U+2315 TELEPHONE RECORDER */
#define XK_phonographcopyright           0x0afb  /* U+2117 SOUND RECORDING COPYRIGHT */
#define XK_caret                         0x0afc  /* U+2038 CARET */
#define XK_singlelowquotemark            0x0afd  /* U+201A SINGLE LOW-9 QUOTATION MARK */
#define XK_doublelowquotemark            0x0afe  /* U+201E DOUBLE LOW-9 QUOTATION MARK */
#define XK_cursor                        0x0aff
#endif /* XK_PUBLISHING */

/*
 *  APL
 *  Byte 3 = b
 * APL
 * Byte 3 = 0x0b
 */

#ifdef XK_APL
#define XK_leftcaret                                   0xba3
#define XK_rightcaret                                  0xba6
#define XK_downcaret                                   0xba8
#define XK_upcaret                                     0xba9
#define XK_overbar                                     0xbc0
#define XK_downtack                                    0xbc2
#define XK_upshoe                                      0xbc3
#define XK_downstile                                   0xbc4
#define XK_underbar                                    0xbc6
#define XK_jot                                         0xbca
#define XK_quad                                        0xbcc
#define XK_uptack                                      0xbce
#define XK_circle                                      0xbcf
#define XK_upstile                                     0xbd3
#define XK_downshoe                                    0xbd6
#define XK_rightshoe                                   0xbd8
#define XK_leftshoe                                    0xbda
#define XK_lefttack                                    0xbdc
#define XK_righttack                                   0xbfc
#define XK_leftcaret                     0x0ba3  /*(U+003C LESS-THAN SIGN)*/
#define XK_rightcaret                    0x0ba6  /*(U+003E GREATER-THAN SIGN)*/
#define XK_downcaret                     0x0ba8  /*(U+2228 LOGICAL OR)*/
#define XK_upcaret                       0x0ba9  /*(U+2227 LOGICAL AND)*/
#define XK_overbar                       0x0bc0  /*(U+00AF MACRON)*/
#define XK_downtack                      0x0bc2  /* U+22A4 DOWN TACK */
#define XK_upshoe                        0x0bc3  /*(U+2229 INTERSECTION)*/
#define XK_downstile                     0x0bc4  /* U+230A LEFT FLOOR */
#define XK_underbar                      0x0bc6  /*(U+005F LOW LINE)*/
#define XK_jot                           0x0bca  /* U+2218 RING OPERATOR */
#define XK_quad                          0x0bcc  /* U+2395 APL FUNCTIONAL SYMBOL QUAD */
#define XK_uptack                        0x0bce  /* U+22A5 UP TACK */
#define XK_circle                        0x0bcf  /* U+25CB WHITE CIRCLE */
#define XK_upstile                       0x0bd3  /* U+2308 LEFT CEILING */
#define XK_downshoe                      0x0bd6  /*(U+222A UNION)*/
#define XK_rightshoe                     0x0bd8  /*(U+2283 SUPERSET OF)*/
#define XK_leftshoe                      0x0bda  /*(U+2282 SUBSET OF)*/
#define XK_lefttack                      0x0bdc  /* U+22A3 LEFT TACK */
#define XK_righttack                     0x0bfc  /* U+22A2 RIGHT TACK */
#endif /* XK_APL */

/*
 * Hebrew
 * Byte 3 = c
 * Byte 3 = 0x0c
 */

#ifdef XK_HEBREW
#define XK_hebrew_doublelowline                        0xcdf
#define XK_hebrew_aleph                                0xce0
#define XK_hebrew_bet                                  0xce1
#define XK_hebrew_beth                                 0xce1  /* deprecated */
#define XK_hebrew_gimel                                0xce2
#define XK_hebrew_gimmel                               0xce2  /* deprecated */
#define XK_hebrew_dalet                                0xce3
#define XK_hebrew_daleth                               0xce3  /* deprecated */
#define XK_hebrew_he                                   0xce4
#define XK_hebrew_waw                                  0xce5
#define XK_hebrew_zain                                 0xce6
#define XK_hebrew_zayin                                0xce6  /* deprecated */
#define XK_hebrew_chet                                 0xce7
#define XK_hebrew_het                                  0xce7  /* deprecated */
#define XK_hebrew_tet                                  0xce8
#define XK_hebrew_teth                                 0xce8  /* deprecated */
#define XK_hebrew_yod                                  0xce9
#define XK_hebrew_finalkaph                            0xcea
#define XK_hebrew_kaph                                 0xceb
#define XK_hebrew_lamed                                0xcec
#define XK_hebrew_finalmem                             0xced
#define XK_hebrew_mem                                  0xcee
#define XK_hebrew_finalnun                             0xcef
#define XK_hebrew_nun                                  0xcf0
#define XK_hebrew_samech                               0xcf1
#define XK_hebrew_samekh                               0xcf1  /* deprecated */
#define XK_hebrew_ayin                                 0xcf2
#define XK_hebrew_finalpe                              0xcf3
#define XK_hebrew_pe                                   0xcf4
#define XK_hebrew_finalzade                            0xcf5
#define XK_hebrew_finalzadi                            0xcf5  /* deprecated */
#define XK_hebrew_zade                                 0xcf6
#define XK_hebrew_zadi                                 0xcf6  /* deprecated */
#define XK_hebrew_qoph                                 0xcf7
#define XK_hebrew_kuf                                  0xcf7  /* deprecated */
#define XK_hebrew_resh                                 0xcf8
#define XK_hebrew_shin                                 0xcf9
#define XK_hebrew_taw                                  0xcfa
#define XK_hebrew_taf                                  0xcfa  /* deprecated */
#define XK_Hebrew_switch        0xFF7E  /* Alias for mode_switch */
#define XK_hebrew_doublelowline          0x0cdf  /* U+2017 DOUBLE LOW LINE */
#define XK_hebrew_aleph                  0x0ce0  /* U+05D0 HEBREW LETTER ALEF */
#define XK_hebrew_bet                    0x0ce1  /* U+05D1 HEBREW LETTER BET */
#define XK_hebrew_beth                   0x0ce1  /* deprecated */
#define XK_hebrew_gimel                  0x0ce2  /* U+05D2 HEBREW LETTER GIMEL */
#define XK_hebrew_gimmel                 0x0ce2  /* deprecated */
#define XK_hebrew_dalet                  0x0ce3  /* U+05D3 HEBREW LETTER DALET */
#define XK_hebrew_daleth                 0x0ce3  /* deprecated */
#define XK_hebrew_he                     0x0ce4  /* U+05D4 HEBREW LETTER HE */
#define XK_hebrew_waw                    0x0ce5  /* U+05D5 HEBREW LETTER VAV */
#define XK_hebrew_zain                   0x0ce6  /* U+05D6 HEBREW LETTER ZAYIN */
#define XK_hebrew_zayin                  0x0ce6  /* deprecated */
#define XK_hebrew_chet                   0x0ce7  /* U+05D7 HEBREW LETTER HET */
#define XK_hebrew_het                    0x0ce7  /* deprecated */
#define XK_hebrew_tet                    0x0ce8  /* U+05D8 HEBREW LETTER TET */
#define XK_hebrew_teth                   0x0ce8  /* deprecated */
#define XK_hebrew_yod                    0x0ce9  /* U+05D9 HEBREW LETTER YOD */
#define XK_hebrew_finalkaph              0x0cea  /* U+05DA HEBREW LETTER FINAL KAF */
#define XK_hebrew_kaph                   0x0ceb  /* U+05DB HEBREW LETTER KAF */
#define XK_hebrew_lamed                  0x0cec  /* U+05DC HEBREW LETTER LAMED */
#define XK_hebrew_finalmem               0x0ced  /* U+05DD HEBREW LETTER FINAL MEM */
#define XK_hebrew_mem                    0x0cee  /* U+05DE HEBREW LETTER MEM */
#define XK_hebrew_finalnun               0x0cef  /* U+05DF HEBREW LETTER FINAL NUN */
#define XK_hebrew_nun                    0x0cf0  /* U+05E0 HEBREW LETTER NUN */
#define XK_hebrew_samech                 0x0cf1  /* U+05E1 HEBREW LETTER SAMEKH */
#define XK_hebrew_samekh                 0x0cf1  /* deprecated */
#define XK_hebrew_ayin                   0x0cf2  /* U+05E2 HEBREW LETTER AYIN */
#define XK_hebrew_finalpe                0x0cf3  /* U+05E3 HEBREW LETTER FINAL PE */
#define XK_hebrew_pe                     0x0cf4  /* U+05E4 HEBREW LETTER PE */
#define XK_hebrew_finalzade              0x0cf5  /* U+05E5 HEBREW LETTER FINAL TSADI */
#define XK_hebrew_finalzadi              0x0cf5  /* deprecated */
#define XK_hebrew_zade                   0x0cf6  /* U+05E6 HEBREW LETTER TSADI */
#define XK_hebrew_zadi                   0x0cf6  /* deprecated */
#define XK_hebrew_qoph                   0x0cf7  /* U+05E7 HEBREW LETTER QOF */
#define XK_hebrew_kuf                    0x0cf7  /* deprecated */
#define XK_hebrew_resh                   0x0cf8  /* U+05E8 HEBREW LETTER RESH */
#define XK_hebrew_shin                   0x0cf9  /* U+05E9 HEBREW LETTER SHIN */
#define XK_hebrew_taw                    0x0cfa  /* U+05EA HEBREW LETTER TAV */
#define XK_hebrew_taf                    0x0cfa  /* deprecated */
#define XK_Hebrew_switch                 0xff7e  /* Alias for mode_switch */
#endif /* XK_HEBREW */

/*
 * Thai
 * Byte 3 = 0x0d
 */

#ifdef XK_THAI
#define XK_Thai_kokai                    0x0da1  /* U+0E01 THAI CHARACTER KO KAI */
#define XK_Thai_khokhai                  0x0da2  /* U+0E02 THAI CHARACTER KHO KHAI */
#define XK_Thai_khokhuat                 0x0da3  /* U+0E03 THAI CHARACTER KHO KHUAT */
#define XK_Thai_khokhwai                 0x0da4  /* U+0E04 THAI CHARACTER KHO KHWAI */
#define XK_Thai_khokhon                  0x0da5  /* U+0E05 THAI CHARACTER KHO KHON */
#define XK_Thai_khorakhang               0x0da6  /* U+0E06 THAI CHARACTER KHO RAKHANG */
#define XK_Thai_ngongu                   0x0da7  /* U+0E07 THAI CHARACTER NGO NGU */
#define XK_Thai_chochan                  0x0da8  /* U+0E08 THAI CHARACTER CHO CHAN */
#define XK_Thai_choching                 0x0da9  /* U+0E09 THAI CHARACTER CHO CHING */
#define XK_Thai_chochang                 0x0daa  /* U+0E0A THAI CHARACTER CHO CHANG */
#define XK_Thai_soso                     0x0dab  /* U+0E0B THAI CHARACTER SO SO */
#define XK_Thai_chochoe                  0x0dac  /* U+0E0C THAI CHARACTER CHO CHOE */
#define XK_Thai_yoying                   0x0dad  /* U+0E0D THAI CHARACTER YO YING */
#define XK_Thai_dochada                  0x0dae  /* U+0E0E THAI CHARACTER DO CHADA */
#define XK_Thai_topatak                  0x0daf  /* U+0E0F THAI CHARACTER TO PATAK */
#define XK_Thai_thothan                  0x0db0  /* U+0E10 THAI CHARACTER THO THAN */
#define XK_Thai_thonangmontho            0x0db1  /* U+0E11 THAI CHARACTER THO NANGMONTHO */
#define XK_Thai_thophuthao               0x0db2  /* U+0E12 THAI CHARACTER THO PHUTHAO */
#define XK_Thai_nonen                    0x0db3  /* U+0E13 THAI CHARACTER NO NEN */
#define XK_Thai_dodek                    0x0db4  /* U+0E14 THAI CHARACTER DO DEK */
#define XK_Thai_totao                    0x0db5  /* U+0E15 THAI CHARACTER TO TAO */
#define XK_Thai_thothung                 0x0db6  /* U+0E16 THAI CHARACTER THO THUNG */
#define XK_Thai_thothahan                0x0db7  /* U+0E17 THAI CHARACTER THO THAHAN */
#define XK_Thai_thothong                 0x0db8  /* U+0E18 THAI CHARACTER THO THONG */
#define XK_Thai_nonu                     0x0db9  /* U+0E19 THAI CHARACTER NO NU */
#define XK_Thai_bobaimai                 0x0dba  /* U+0E1A THAI CHARACTER BO BAIMAI */
#define XK_Thai_popla                    0x0dbb  /* U+0E1B THAI CHARACTER PO PLA */
#define XK_Thai_phophung                 0x0dbc  /* U+0E1C THAI CHARACTER PHO PHUNG */
#define XK_Thai_fofa                     0x0dbd  /* U+0E1D THAI CHARACTER FO FA */
#define XK_Thai_phophan                  0x0dbe  /* U+0E1E THAI CHARACTER PHO PHAN */
#define XK_Thai_fofan                    0x0dbf  /* U+0E1F THAI CHARACTER FO FAN */
#define XK_Thai_phosamphao               0x0dc0  /* U+0E20 THAI CHARACTER PHO SAMPHAO */
#define XK_Thai_moma                     0x0dc1  /* U+0E21 THAI CHARACTER MO MA */
#define XK_Thai_yoyak                    0x0dc2  /* U+0E22 THAI CHARACTER YO YAK */
#define XK_Thai_rorua                    0x0dc3  /* U+0E23 THAI CHARACTER RO RUA */
#define XK_Thai_ru                       0x0dc4  /* U+0E24 THAI CHARACTER RU */
#define XK_Thai_loling                   0x0dc5  /* U+0E25 THAI CHARACTER LO LING */
#define XK_Thai_lu                       0x0dc6  /* U+0E26 THAI CHARACTER LU */
#define XK_Thai_wowaen                   0x0dc7  /* U+0E27 THAI CHARACTER WO WAEN */
#define XK_Thai_sosala                   0x0dc8  /* U+0E28 THAI CHARACTER SO SALA */
#define XK_Thai_sorusi                   0x0dc9  /* U+0E29 THAI CHARACTER SO RUSI */
#define XK_Thai_sosua                    0x0dca  /* U+0E2A THAI CHARACTER SO SUA */
#define XK_Thai_hohip                    0x0dcb  /* U+0E2B THAI CHARACTER HO HIP */
#define XK_Thai_lochula                  0x0dcc  /* U+0E2C THAI CHARACTER LO CHULA */
#define XK_Thai_oang                     0x0dcd  /* U+0E2D THAI CHARACTER O ANG */
#define XK_Thai_honokhuk                 0x0dce  /* U+0E2E THAI CHARACTER HO NOKHUK */
#define XK_Thai_paiyannoi                0x0dcf  /* U+0E2F THAI CHARACTER PAIYANNOI */
#define XK_Thai_saraa                    0x0dd0  /* U+0E30 THAI CHARACTER SARA A */
#define XK_Thai_maihanakat               0x0dd1  /* U+0E31 THAI CHARACTER MAI HAN-AKAT */
#define XK_Thai_saraaa                   0x0dd2  /* U+0E32 THAI CHARACTER SARA AA */
#define XK_Thai_saraam                   0x0dd3  /* U+0E33 THAI CHARACTER SARA AM */
#define XK_Thai_sarai                    0x0dd4  /* U+0E34 THAI CHARACTER SARA I */
#define XK_Thai_saraii                   0x0dd5  /* U+0E35 THAI CHARACTER SARA II */
#define XK_Thai_saraue                   0x0dd6  /* U+0E36 THAI CHARACTER SARA UE */
#define XK_Thai_sarauee                  0x0dd7  /* U+0E37 THAI CHARACTER SARA UEE */
#define XK_Thai_sarau                    0x0dd8  /* U+0E38 THAI CHARACTER SARA U */
#define XK_Thai_sarauu                   0x0dd9  /* U+0E39 THAI CHARACTER SARA UU */
#define XK_Thai_phinthu                  0x0dda  /* U+0E3A THAI CHARACTER PHINTHU */
#define XK_Thai_maihanakat_maitho        0x0dde
#define XK_Thai_baht                     0x0ddf  /* U+0E3F THAI CURRENCY SYMBOL BAHT */
#define XK_Thai_sarae                    0x0de0  /* U+0E40 THAI CHARACTER SARA E */
#define XK_Thai_saraae                   0x0de1  /* U+0E41 THAI CHARACTER SARA AE */
#define XK_Thai_sarao                    0x0de2  /* U+0E42 THAI CHARACTER SARA O */
#define XK_Thai_saraaimaimuan            0x0de3  /* U+0E43 THAI CHARACTER SARA AI MAIMUAN */
#define XK_Thai_saraaimaimalai           0x0de4  /* U+0E44 THAI CHARACTER SARA AI MAIMALAI */
#define XK_Thai_lakkhangyao              0x0de5  /* U+0E45 THAI CHARACTER LAKKHANGYAO */
#define XK_Thai_maiyamok                 0x0de6  /* U+0E46 THAI CHARACTER MAIYAMOK */
#define XK_Thai_maitaikhu                0x0de7  /* U+0E47 THAI CHARACTER MAITAIKHU */
#define XK_Thai_maiek                    0x0de8  /* U+0E48 THAI CHARACTER MAI EK */
#define XK_Thai_maitho                   0x0de9  /* U+0E49 THAI CHARACTER MAI THO */
#define XK_Thai_maitri                   0x0dea  /* U+0E4A THAI CHARACTER MAI TRI */
#define XK_Thai_maichattawa              0x0deb  /* U+0E4B THAI CHARACTER MAI CHATTAWA */
#define XK_Thai_thanthakhat              0x0dec  /* U+0E4C THAI CHARACTER THANTHAKHAT */
#define XK_Thai_nikhahit                 0x0ded  /* U+0E4D THAI CHARACTER NIKHAHIT */
#define XK_Thai_leksun                   0x0df0  /* U+0E50 THAI DIGIT ZERO */
#define XK_Thai_leknung                  0x0df1  /* U+0E51 THAI DIGIT ONE */
#define XK_Thai_leksong                  0x0df2  /* U+0E52 THAI DIGIT TWO */
#define XK_Thai_leksam                   0x0df3  /* U+0E53 THAI DIGIT THREE */
#define XK_Thai_leksi                    0x0df4  /* U+0E54 THAI DIGIT FOUR */
#define XK_Thai_lekha                    0x0df5  /* U+0E55 THAI DIGIT FIVE */
#define XK_Thai_lekhok                   0x0df6  /* U+0E56 THAI DIGIT SIX */
#define XK_Thai_lekchet                  0x0df7  /* U+0E57 THAI DIGIT SEVEN */
#define XK_Thai_lekpaet                  0x0df8  /* U+0E58 THAI DIGIT EIGHT */
#define XK_Thai_lekkao                   0x0df9  /* U+0E59 THAI DIGIT NINE */
#endif /* XK_THAI */

/*
 * Korean
 * Byte 3 = 0x0e
 */

#ifdef XK_KOREAN

#define XK_Hangul                        0xff31  /* Hangul start/stop(toggle) */
#define XK_Hangul_Start                  0xff32  /* Hangul start */
#define XK_Hangul_End                    0xff33  /* Hangul end, English start */
#define XK_Hangul_Hanja                  0xff34  /* Start Hangul->Hanja Conversion */
#define XK_Hangul_Jamo                   0xff35  /* Hangul Jamo mode */
#define XK_Hangul_Romaja                 0xff36  /* Hangul Romaja mode */
#define XK_Hangul_Codeinput              0xff37  /* Hangul code input mode */
#define XK_Hangul_Jeonja                 0xff38  /* Jeonja mode */
#define XK_Hangul_Banja                  0xff39  /* Banja mode */
#define XK_Hangul_PreHanja               0xff3a  /* Pre Hanja conversion */
#define XK_Hangul_PostHanja              0xff3b  /* Post Hanja conversion */
#define XK_Hangul_SingleCandidate        0xff3c  /* Single candidate */
#define XK_Hangul_MultipleCandidate      0xff3d  /* Multiple candidate */
#define XK_Hangul_PreviousCandidate      0xff3e  /* Previous candidate */
#define XK_Hangul_Special                0xff3f  /* Special symbols */
#define XK_Hangul_switch                 0xff7e  /* Alias for mode_switch */

/* Hangul Consonant Characters */
#define XK_Hangul_Kiyeog                 0x0ea1
#define XK_Hangul_SsangKiyeog            0x0ea2
#define XK_Hangul_KiyeogSios             0x0ea3
#define XK_Hangul_Nieun                  0x0ea4
#define XK_Hangul_NieunJieuj             0x0ea5
#define XK_Hangul_NieunHieuh             0x0ea6
#define XK_Hangul_Dikeud                 0x0ea7
#define XK_Hangul_SsangDikeud            0x0ea8
#define XK_Hangul_Rieul                  0x0ea9
#define XK_Hangul_RieulKiyeog            0x0eaa
#define XK_Hangul_RieulMieum             0x0eab
#define XK_Hangul_RieulPieub             0x0eac
#define XK_Hangul_RieulSios              0x0ead
#define XK_Hangul_RieulTieut             0x0eae
#define XK_Hangul_RieulPhieuf            0x0eaf
#define XK_Hangul_RieulHieuh             0x0eb0
#define XK_Hangul_Mieum                  0x0eb1
#define XK_Hangul_Pieub                  0x0eb2
#define XK_Hangul_SsangPieub             0x0eb3
#define XK_Hangul_PieubSios              0x0eb4
#define XK_Hangul_Sios                   0x0eb5
#define XK_Hangul_SsangSios              0x0eb6
#define XK_Hangul_Ieung                  0x0eb7
#define XK_Hangul_Jieuj                  0x0eb8
#define XK_Hangul_SsangJieuj             0x0eb9
#define XK_Hangul_Cieuc                  0x0eba
#define XK_Hangul_Khieuq                 0x0ebb
#define XK_Hangul_Tieut                  0x0ebc
#define XK_Hangul_Phieuf                 0x0ebd
#define XK_Hangul_Hieuh                  0x0ebe

/* Hangul Vowel Characters */
#define XK_Hangul_A                      0x0ebf
#define XK_Hangul_AE                     0x0ec0
#define XK_Hangul_YA                     0x0ec1
#define XK_Hangul_YAE                    0x0ec2
#define XK_Hangul_EO                     0x0ec3
#define XK_Hangul_E                      0x0ec4
#define XK_Hangul_YEO                    0x0ec5
#define XK_Hangul_YE                     0x0ec6
#define XK_Hangul_O                      0x0ec7
#define XK_Hangul_WA                     0x0ec8
#define XK_Hangul_WAE                    0x0ec9
#define XK_Hangul_OE                     0x0eca
#define XK_Hangul_YO                     0x0ecb
#define XK_Hangul_U                      0x0ecc
#define XK_Hangul_WEO                    0x0ecd
#define XK_Hangul_WE                     0x0ece
#define XK_Hangul_WI                     0x0ecf
#define XK_Hangul_YU                     0x0ed0
#define XK_Hangul_EU                     0x0ed1
#define XK_Hangul_YI                     0x0ed2
#define XK_Hangul_I                      0x0ed3

/* Hangul syllable-final (JongSeong) Characters */
#define XK_Hangul_J_Kiyeog               0x0ed4
#define XK_Hangul_J_SsangKiyeog          0x0ed5
#define XK_Hangul_J_KiyeogSios           0x0ed6
#define XK_Hangul_J_Nieun                0x0ed7
#define XK_Hangul_J_NieunJieuj           0x0ed8
#define XK_Hangul_J_NieunHieuh           0x0ed9
#define XK_Hangul_J_Dikeud               0x0eda
#define XK_Hangul_J_Rieul                0x0edb
#define XK_Hangul_J_RieulKiyeog          0x0edc
#define XK_Hangul_J_RieulMieum           0x0edd
#define XK_Hangul_J_RieulPieub           0x0ede
#define XK_Hangul_J_RieulSios            0x0edf
#define XK_Hangul_J_RieulTieut           0x0ee0
#define XK_Hangul_J_RieulPhieuf          0x0ee1
#define XK_Hangul_J_RieulHieuh           0x0ee2
#define XK_Hangul_J_Mieum                0x0ee3
#define XK_Hangul_J_Pieub                0x0ee4
#define XK_Hangul_J_PieubSios            0x0ee5
#define XK_Hangul_J_Sios                 0x0ee6
#define XK_Hangul_J_SsangSios            0x0ee7
#define XK_Hangul_J_Ieung                0x0ee8
#define XK_Hangul_J_Jieuj                0x0ee9
#define XK_Hangul_J_Cieuc                0x0eea
#define XK_Hangul_J_Khieuq               0x0eeb
#define XK_Hangul_J_Tieut                0x0eec
#define XK_Hangul_J_Phieuf               0x0eed
#define XK_Hangul_J_Hieuh                0x0eee

/* Ancient Hangul Consonant Characters */
#define XK_Hangul_RieulYeorinHieuh       0x0eef
#define XK_Hangul_SunkyeongeumMieum      0x0ef0
#define XK_Hangul_SunkyeongeumPieub      0x0ef1
#define XK_Hangul_PanSios                0x0ef2
#define XK_Hangul_KkogjiDalrinIeung      0x0ef3
#define XK_Hangul_SunkyeongeumPhieuf     0x0ef4
#define XK_Hangul_YeorinHieuh            0x0ef5

/* Ancient Hangul Vowel Characters */
#define XK_Hangul_AraeA                  0x0ef6
#define XK_Hangul_AraeAE                 0x0ef7

/* Ancient Hangul syllable-final (JongSeong) Characters */
#define XK_Hangul_J_PanSios              0x0ef8
#define XK_Hangul_J_KkogjiDalrinIeung    0x0ef9
#define XK_Hangul_J_YeorinHieuh          0x0efa

/* Korean currency symbol */
#define XK_Korean_Won                    0x0eff  /*(U+20A9 WON SIGN)*/

#endif /* XK_KOREAN */

#ifdef XK_CURRENCY
#define XK_EuroSign                      0x20ac  /* U+20AC EURO SIGN */
#endif /* XK_CURRENCY */

#ifdef XK_BRAILLE
#define XK_braille_dot_1                 0xfff1
#define XK_braille_dot_2                 0xfff2
#define XK_braille_dot_3                 0xfff3
#define XK_braille_dot_4                 0xfff4
#define XK_braille_dot_5                 0xfff5
#define XK_braille_dot_6                 0xfff6
#define XK_braille_dot_7                 0xfff7
#define XK_braille_dot_8                 0xfff8
#define XK_braille_dot_9                 0xfff9
#define XK_braille_dot_10                0xfffa
#endif /* XK_BRAILLE */

/* Multimedia keys, defined same as on Linux
 * /usr/include/pkg/libxkbcommon/xkbcommon/xkbcommon-keysyms.h
 */

#ifndef TK_NO_DEPRECATED
#define XK_XF86AudioLowerVolume	0x1008FF11   /* Volume control down        */
#define XK_XF86AudioMute	0x1008FF12   /* Mute sound from the system */
#define XK_XF86AudioRaiseVolume	0x1008FF13   /* Volume control up          */
#define XK_XF86AudioPlay	0x1008FF14   /* Start playing of audio >   */
#define XK_XF86AudioStop	0x1008FF15   /* Stop playing audio         */
#define XK_XF86AudioPrev	0x1008FF16   /* Previous track             */
#define XK_XF86AudioNext	0x1008FF17   /* Next track                 */
#endif /* !TK_NO_DEPRECATED */

Changes to xlib/xcolors.c.
1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15






-
-
+
+







/*
 * xcolors.c --
 *
 *	This file contains the routines used to map from X color names to RGB
 *	and pixel values.
 *
 * Copyright (c) 1996 by Sun Microsystems, Inc.
 * Copyright (c) 2012 by Jan Nijtmans
 * Copyright (c) 1996 Sun Microsystems, Inc.
 * Copyright (c) 2012 Jan Nijtmans
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tkInt.h"

40
41
42
43
44
45
46
47

48
49

50
51
52
53

54
55
56


57
58

59
60
61
62
63
64
65
66

67
68

69
70
71
72


73
74
75
76
77
78





79
80
81
82
83


84
85

86
87
88
89



90
91
92
93


94
95
96

97
98
99
100
101



102
103
104


105
106
107
108
109

110
111

112
113
114

115
116
117
118
119
120

121
122
123

124
125
126
127

128
129

130
131
132

133
134
135
136
137
138




139
140
141

142
143
144
145



146
147
148
149
150



151
152
153
154
155


156
157
158
159
160
161
162
163
164







165
166

167
168
169
170


171
172
173


174
175
176
177
178
179

180
181
182
183

184
185

186
187
188

189
190
191

192
193
194
195
196
197

198
199

200
201
202
203

204
205
206
207

208
209
210
211
212
213

214
215
216
217
218

219
220

221
222
223
224
225


226
227

228
229
230
231
232
233
234
40
41
42
43
44
45
46

47
48

49
50
51
52

53
54


55
56
57

58
59
60
61
62
63
64
65

66
67

68
69
70


71
72
73





74
75
76
77
78
79
80
81


82
83
84

85
86



87
88
89
90
91


92
93
94
95

96
97
98



99
100
101
102


103
104
105
106
107
108

109
110

111
112
113

114
115
116
117
118
119

120
121
122

123
124
125
126

127
128

129
130
131

132
133
134




135
136
137
138
139
140

141
142



143
144
145
146
147



148
149
150
151
152
153


154
155
156
157







158
159
160
161
162
163
164
165

166
167
168


169
170
171


172
173
174
175
176
177
178

179
180
181
182

183
184

185
186
187

188
189
190

191
192
193
194
195
196

197
198

199
200
201
202

203
204
205
206

207
208
209
210
211
212

213
214
215
216
217

218
219

220
221
222
223


224
225
226

227
228
229
230
231
232
233
234







-
+

-
+



-
+

-
-
+
+

-
+







-
+

-
+


-
-
+
+

-
-
-
-
-
+
+
+
+
+



-
-
+
+

-
+

-
-
-
+
+
+


-
-
+
+


-
+


-
-
-
+
+
+

-
-
+
+




-
+

-
+


-
+





-
+


-
+



-
+

-
+


-
+


-
-
-
-
+
+
+
+


-
+

-
-
-
+
+
+


-
-
-
+
+
+



-
-
+
+


-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
+


-
-
+
+

-
-
+
+





-
+



-
+

-
+


-
+


-
+





-
+

-
+



-
+



-
+





-
+




-
+

-
+



-
-
+
+

-
+







 * are handled by this table, above that is handled especially.
 */

typedef char elem[32];

static const elem xColors[] = {
    /* Colors starting with 'a' */
    "liceBlue\0                   \360\370\377",
    "liceBlue\0                   \360\370\377\0",
    "ntiqueWhite\0    \213\203\170\315\300\260\356\337\314\377\357\333\372\353\327\4",
    "qua\0                        \000\377\377",
    "qua\0                        \000\377\377\0",
    "quamarine\0      \105\213\164\146\315\252\166\356\306\177\377\324\177\377\324\4",
    "zure\0           \203\213\213\301\315\315\340\356\356\360\377\377\360\377\377\4",
    /* Colors starting with 'b' */
    "eige\0                       \365\365\334",
    "eige\0                       \365\365\334\0",
    "isque\0          \213\175\153\315\267\236\356\325\267\377\344\304\377\344\304\4",
    "lack\0                       \000\000\000",
    "lanchedAlmond\0              \377\353\315",
    "lack\0                       \000\000\000\0",
    "lanchedAlmond\0              \377\353\315\0",
    "lue\0            \000\000\213\000\000\315\000\000\356\000\000\377\000\000\377\4",
    "lueViolet\0                  \212\053\342",
    "lueViolet\0                  \212\053\342\0",
    "rown\0           \213\043\043\315\063\063\356\073\073\377\100\100\245\052\052\4",
    "urlywood\0       \213\163\125\315\252\175\356\305\221\377\323\233\336\270\207\4",
    /* Colors starting with 'c' */
    "adetBlue\0       \123\206\213\172\305\315\216\345\356\230\365\377\137\236\240\4",
    "hartreuse\0      \105\213\000\146\315\000\166\356\000\177\377\000\177\377\000\4",
    "hocolate\0       \213\105\023\315\146\035\356\166\041\377\177\044\322\151\036\4",
    "oral\0           \213\076\057\315\133\105\356\152\120\377\162\126\377\177\120\4",
    "ornflowerBlue\0              \144\225\355",
    "ornflowerBlue\0              \144\225\355\0",
    "ornsilk\0        \213\210\170\315\310\261\356\350\315\377\370\334\377\370\334\4",
    "rimson\0                     \334\024\074",
    "rimson\0                     \334\024\074\0",
    "yan\0            \000\213\213\000\315\315\000\356\356\000\377\377\000\377\377\4",
    /* Colors starting with 'd' */
    "arkBlue\0                    \000\000\213",
    "arkCyan\0                    \000\213\213",
    "arkBlue\0                    \000\000\213\0",
    "arkCyan\0                    \000\213\213\0",
    "arkGoldenrod\0   \213\145\010\315\225\014\356\255\016\377\271\017\270\206\013\4",
    "arkGray\0                    \251\251\251",
    "arkGreen\0                   \000\144\000",
    "arkGrey\0                    \251\251\251",
    "arkKhaki\0                   \275\267\153",
    "arkMagenta\0                 \213\000\213",
    "arkGray\0                    \251\251\251\0",
    "arkGreen\0                   \000\144\000\0",
    "arkGrey\0                    \251\251\251\0",
    "arkKhaki\0                   \275\267\153\0",
    "arkMagenta\0                 \213\000\213\0",
    "arkOliveGreen\0  \156\213\075\242\315\132\274\356\150\312\377\160\125\153\057\4",
    "arkOrange\0      \213\105\000\315\146\000\356\166\000\377\177\000\377\214\000\4",
    "arkOrchid\0      \150\042\213\232\062\315\262\072\356\277\076\377\231\062\314\4",
    "arkRed\0                     \213\000\000",
    "arkSalmon\0                  \351\226\172",
    "arkRed\0                     \213\000\000\0",
    "arkSalmon\0                  \351\226\172\0",
    "arkSeaGreen\0    \151\213\151\233\315\233\264\356\264\301\377\301\217\274\217\4",
    "arkSlateBlue\0               \110\075\213",
    "arkSlateBlue\0               \110\075\213\0",
    "arkSlateGray\0   \122\213\213\171\315\315\215\356\356\227\377\377\057\117\117\4",
    "arkSlateGrey\0               \057\117\117",
    "arkTurquoise\0               \000\316\321",
    "arkViolet\0                  \224\000\323",
    "arkSlateGrey\0               \057\117\117\0",
    "arkTurquoise\0               \000\316\321\0",
    "arkViolet\0                  \224\000\323\0",
    "eepPink\0        \213\012\120\315\020\166\356\022\211\377\024\223\377\024\223\4",
    "eepSkyBlue\0     \000\150\213\000\232\315\000\262\356\000\277\377\000\277\377\4",
    "imGray\0                     \151\151\151",
    "imGrey\0                     \151\151\151",
    "imGray\0                     \151\151\151\0",
    "imGrey\0                     \151\151\151\0",
    "odgerBlue\0      \020\116\213\030\164\315\034\206\356\036\220\377\036\220\377\4",
    /* Colors starting with 'e' */
    "\377" /* placeholder */,
    "\377                              \0" /* placeholder */,
    /* Colors starting with 'f' */
    "irebrick\0       \213\032\032\315\046\046\356\054\054\377\060\060\262\042\042\4",
    "loralWhite\0                 \377\372\360",
    "orestGreen\0                 \042\213\042",
    "uchsia\0                     \377\000\377",
    "loralWhite\0                 \377\372\360\0",
    "orestGreen\0                 \042\213\042\0",
    "uchsia\0                     \377\000\377\0",
    /* Colors starting with 'g' */
    "ainsboro\0                   \334\334\334",
    "hostWhite\0                  \370\370\377",
    "ainsboro\0                   \334\334\334\0",
    "hostWhite\0                  \370\370\377\0",
    "old\0            \213\165\000\315\255\000\356\311\000\377\327\000\377\327\000\4",
    "oldenrod\0       \213\151\024\315\233\035\356\264\042\377\301\045\332\245\040\4",
    "ray\0\024\024\024\022\022\022\017\017\017\015\015\015\012\012\012"
	    "\010\010\010\005\005\005\003\003\003\200\200\200\10",
    "ray0\0                       \000\000\000",
    "ray0\0                       \000\000\000\0",
    "reen\0           \000\213\000\000\315\000\000\356\000\000\377\000\000\200\000\4",
    "reenYellow\0                 \255\377\057",
    "reenYellow\0                 \255\377\057\0",
    "rey\0\024\024\024\022\022\022\017\017\017\015\015\015\012\012\012"
	    "\010\010\010\005\005\005\003\003\003\200\200\200\10",
    "rey0\0                       \000\000\000",
    "rey0\0                       \000\000\000\0",
    /* Colors starting with 'h' */
    "oneydew\0        \203\213\203\301\315\301\340\356\340\360\377\360\360\377\360\4",
    "otPink\0         \213\072\142\315\140\220\356\152\247\377\156\264\377\151\264\4",
    /* Colors starting with 'i' */
    "ndianRed\0       \213\072\072\315\125\125\356\143\143\377\152\152\315\134\134\4",
    "ndigo\0                      \113\000\202",
    "ndigo\0                      \113\000\202\0",
    "vory\0           \213\213\203\315\315\301\356\356\340\377\377\360\377\377\360\4",
    /* Colors starting with 'j' */
    "\377" /* placeholder */,
    "\377                              \0" /* placeholder */,
    /* Colors starting with 'k' */
    "haki\0           \213\206\116\315\306\163\356\346\205\377\366\217\360\346\214\4",
    /* Colors starting with 'l' */
    "avender\0                    \346\346\372",
    "avender\0                    \346\346\372\0",
    "avenderBlush\0   \213\203\206\315\301\305\356\340\345\377\360\365\377\360\365\4",
    "awnGreen\0                   \174\374\000",
    "awnGreen\0                   \174\374\000\0",
    "emonChiffon\0    \213\211\160\315\311\245\356\351\277\377\372\315\377\372\315\4",
    "ightBlue\0       \150\203\213\232\300\315\262\337\356\277\357\377\255\330\346\4",
    "ightCoral\0                  \360\200\200",
    "ightCoral\0                  \360\200\200\0",
    "ightCyan\0       \172\213\213\264\315\315\321\356\356\340\377\377\340\377\377\4",
    "ightGoldenrod\0  \213\201\114\315\276\160\356\334\202\377\354\213\356\335\202\4",
    "ightGoldenrodYellow\0        \372\372\322",
    "ightGray\0                   \323\323\323",
    "ightGreen\0                  \220\356\220",
    "ightGrey\0                   \323\323\323",
    "ightGoldenrodYellow\0        \372\372\322\0",
    "ightGray\0                   \323\323\323\0",
    "ightGreen\0                  \220\356\220\0",
    "ightGrey\0                   \323\323\323\0",
    "ightPink\0       \213\137\145\315\214\225\356\242\255\377\256\271\377\266\301\4",
    "ightSalmon\0     \213\127\102\315\201\142\356\225\162\377\240\172\377\240\172\4",
    "ightSeaGreen\0               \040\262\252",
    "ightSeaGreen\0               \040\262\252\0",
    "ightSkyBlue\0    \140\173\213\215\266\315\244\323\356\260\342\377\207\316\372\4",
    "ightSlateBlue\0              \204\160\377",
    "ightSlateGray\0              \167\210\231",
    "ightSlateGrey\0              \167\210\231",
    "ightSlateBlue\0              \204\160\377\0",
    "ightSlateGray\0              \167\210\231\0",
    "ightSlateGrey\0              \167\210\231\0",
    "ightSteelBlue\0  \156\173\213\242\265\315\274\322\356\312\341\377\260\304\336\4",
    "ightYellow\0     \213\213\172\315\315\264\356\356\321\377\377\340\377\377\340\4",
    "ime\0                        \000\377\000",
    "imeGreen\0                   \062\315\062",
    "inen\0                       \372\360\346",
    "ime\0                        \000\377\000\0",
    "imeGreen\0                   \062\315\062\0",
    "inen\0                       \372\360\346\0",
    /* Colors starting with 'm' */
    "agenta\0         \213\000\213\315\000\315\356\000\356\377\000\377\377\000\377\4",
    "aroon\0          \213\034\142\315\051\220\356\060\247\377\064\263\200\000\000\4",
    "ediumAquamarine\0            \146\315\252",
    "ediumBlue\0                  \000\000\315",
    "ediumAquamarine\0            \146\315\252\0",
    "ediumBlue\0                  \000\000\315\0",
    "ediumOrchid\0    \172\067\213\264\122\315\321\137\356\340\146\377\272\125\323\4",
    "ediumPurple\0    \135\107\213\211\150\315\237\171\356\253\202\377\223\160\333\4",
    "ediumSeaGreen\0              \074\263\161",
    "ediumSlateBlue\0             \173\150\356",
    "ediumSpringGreen\0           \000\372\232",
    "ediumTurquoise\0             \110\321\314",
    "ediumVioletRed\0             \307\025\205",
    "idnightBlue\0                \031\031\160",
    "intCream\0                   \365\377\372",
    "ediumSeaGreen\0              \074\263\161\0",
    "ediumSlateBlue\0             \173\150\356\0",
    "ediumSpringGreen\0           \000\372\232\0",
    "ediumTurquoise\0             \110\321\314\0",
    "ediumVioletRed\0             \307\025\205\0",
    "idnightBlue\0                \031\031\160\0",
    "intCream\0                   \365\377\372\0",
    "istyRose\0       \213\175\173\315\267\265\356\325\322\377\344\341\377\344\341\4",
    "occasin\0                    \377\344\265",
    "occasin\0                    \377\344\265\0",
    /* Colors starting with 'n' */
    "avajoWhite\0     \213\171\136\315\263\213\356\317\241\377\336\255\377\336\255\4",
    "avy\0                        \000\000\200",
    "avyBlue\0                    \000\000\200",
    "avy\0                        \000\000\200\0",
    "avyBlue\0                    \000\000\200\0",
    /* Colors starting with 'o' */
    "ldLace\0                     \375\365\346",
    "live\0                       \200\200\000",
    "ldLace\0                     \375\365\346\0",
    "live\0                       \200\200\000\0",
    "liveDrab\0       \151\213\042\232\315\062\263\356\072\300\377\076\153\216\043\4",
    "range\0          \213\132\000\315\205\000\356\232\000\377\245\000\377\245\000\4",
    "rangeRed\0       \213\045\000\315\067\000\356\100\000\377\105\000\377\105\000\4",
    "rchid\0          \213\107\211\315\151\311\356\172\351\377\203\372\332\160\326\4",
    /* Colors starting with 'p' */
    "aleGoldenrod\0               \356\350\252",
    "aleGoldenrod\0               \356\350\252\0",
    "aleGreen\0       \124\213\124\174\315\174\220\356\220\232\377\232\230\373\230\4",
    "aleTurquoise\0   \146\213\213\226\315\315\256\356\356\273\377\377\257\356\356\4",
    "aleVioletRed\0   \213\107\135\315\150\211\356\171\237\377\202\253\333\160\223\4",
    "apayaWhip\0                  \377\357\325",
    "apayaWhip\0                  \377\357\325\0",
    "eachPuff\0       \213\167\145\315\257\225\356\313\255\377\332\271\377\332\271\4",
    "eru\0                        \315\205\077",
    "eru\0                        \315\205\077\0",
    "ink\0            \213\143\154\315\221\236\356\251\270\377\265\305\377\300\313\4",
    "lum\0            \213\146\213\315\226\315\356\256\356\377\273\377\335\240\335\4",
    "owderBlue\0                  \260\340\346",
    "owderBlue\0                  \260\340\346\0",
    "urple\0          \125\032\213\175\046\315\221\054\356\233\060\377\200\000\200\4",
    /* Colors starting with 'q' */
    "\377" /* placeholder */,
    "\377                              \0" /* placeholder */,
    /* Colors starting with 'r' */
    "ed\0             \213\000\000\315\000\000\356\000\000\377\000\000\377\000\000\4",
    "osyBrown\0       \213\151\151\315\233\233\356\264\264\377\301\301\274\217\217\4",
    "oyalBlue\0       \047\100\213\072\137\315\103\156\356\110\166\377\101\151\341\4",
    /* Colors starting with 's' */
    "addleBrown\0                 \213\105\023",
    "addleBrown\0                 \213\105\023\0",
    "almon\0          \213\114\071\315\160\124\356\202\142\377\214\151\372\200\162\4",
    "andyBrown\0                  \364\244\140",
    "andyBrown\0                  \364\244\140\0",
    "eaGreen\0        \056\213\127\103\315\200\116\356\224\124\377\237\056\213\127\4",
    "eashell\0        \213\206\202\315\305\277\356\345\336\377\365\356\377\365\356\4",
    "ienna\0          \213\107\046\315\150\071\356\171\102\377\202\107\240\122\055\4",
    "ilver\0                      \300\300\300",
    "ilver\0                      \300\300\300\0",
    "kyBlue\0         \112\160\213\154\246\315\176\300\356\207\316\377\207\316\353\4",
    "lateBlue\0       \107\074\213\151\131\315\172\147\356\203\157\377\152\132\315\4",
    "lateGray\0       \154\173\213\237\266\315\271\323\356\306\342\377\160\200\220\4",
    "lateGrey\0                   \160\200\220",
    "lateGrey\0                   \160\200\220\0",
    "now\0            \213\211\211\315\311\311\356\351\351\377\372\372\377\372\372\4",
    "pringGreen\0     \000\213\105\000\315\146\000\356\166\000\377\177\000\377\177\4",
    "teelBlue\0       \066\144\213\117\224\315\134\254\356\143\270\377\106\202\264\4",
    /* Colors starting with 't' */
    "an\0             \213\132\053\315\205\077\356\232\111\377\245\117\322\264\214\4",
    "eal\0                        \000\200\200",
    "eal\0                        \000\200\200\0",
    "histle\0         \213\173\213\315\265\315\356\322\356\377\341\377\330\277\330\4",
    "omato\0          \213\066\046\315\117\071\356\134\102\377\143\107\377\143\107\4",
    "urquoise\0       \000\206\213\000\305\315\000\345\356\000\365\377\100\340\320\4",
    /* Colors starting with 'u' */
    "\377" /* placeholder */,
    "\377                              \0" /* placeholder */,
    /* Colors starting with 'v' */
    "iolet\0                      \356\202\356",
    "iolet\0                      \356\202\356\0",
    "ioletRed\0       \213\042\122\315\062\170\356\072\214\377\076\226\320\040\220\4",
    /* Colors starting with 'w' */
    "heat\0           \213\176\146\315\272\226\356\330\256\377\347\272\365\336\263\4",
    "hite\0                       \377\377\377",
    "hiteSmoke\0                  \365\365\365",
    "hite\0                       \377\377\377\0",
    "hiteSmoke\0                  \365\365\365\0",
    /* Colors starting with 'x' */
    "\377" /* placeholder */,
    "\377                              \0" /* placeholder */,
    /* Colors starting with 'y' */
    "ellow\0          \213\213\000\315\315\000\356\356\000\377\377\000\377\377\000\4",
    "ellowGreen\0                 \232\315\062\0"
};

/*
 *----------------------------------------------------------------------
337
338
339
340
341
342
343



344
345
346
347
348
349
350

351
352
353
354
355
356
357
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352

353
354
355
356
357
358
359
360







+
+
+






-
+







Status
XParseColor(
    Display *display,
    Colormap map,
    const char *spec,
    XColor *colorPtr)
{
    (void)display;
    (void)map;

    if (spec[0] == '#') {
	char *p;
	Tcl_WideInt value = parseHex64bit(++spec, &p);

	/*
	 * If *p does not point to the end of the string, there were invalid
	 * digits in the spec. Ergo, it is not a vailid color string.
	 * digits in the spec. Ergo, it is not a valid color string.
	 * (Bug f0188aca9e)
	 */

	if (*p != '\0') {
	    return 0;
	}

Changes to xlib/xgc.c.
9
10
11
12
13
14
15
16
17
18
19


20
21
22
23
24
25
26
27
28
29
30
31
32
33







34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

55
56
57
58
59
60
61
62
63
64
65
66
9
10
11
12
13
14
15




16
17










18
19


20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

47
48




49
50
51
52
53
54
55







-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-


-
-
+
+
+
+
+
+
+




















-
+

-
-
-
-







 * 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.
 */

#include "tkInt.h"

#if !defined(MAC_OSX_TK)
#   include <X11/Xlib.h>
#   define gcCacheSize 0
#include <X11/Xlib.h>
#if defined(MAC_OSX_TK)
#   define TkpInitGCCache(gc)
#   define TkpFreeGCCache(gc)
#   define TkpGetGCCache(gc)
#else
#   include <tkMacOSXInt.h>
#   include <X11/Xlib.h>
#   include <X11/X.h>
#   define Cursor XCursor
#   define Region XRegion
#   define gcCacheSize sizeof(TkpGCCache)
#endif

#undef TkSetRegion


#define MAX_DASH_LIST_SIZE 10
typedef struct {
    XGCValues gc;
    char dash[MAX_DASH_LIST_SIZE];
} XGCValuesWithDash;

/*
 *----------------------------------------------------------------------
 *
 * AllocClipMask --
 *
 *	Static helper proc to allocate new or clear existing TkpClipMask.
 *
 * Results:
 *	Returns ptr to the new/cleared TkpClipMask.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static TkpClipMask *AllocClipMask(GC gc) {
    TkpClipMask *clip_mask = (TkpClipMask*) gc->clip_mask;

    if (clip_mask == NULL) {
	clip_mask = ckalloc(sizeof(TkpClipMask));
	clip_mask = (TkpClipMask *)ckalloc(sizeof(TkpClipMask));
	gc->clip_mask = (Pixmap) clip_mask;
#ifdef MAC_OSX_TK
    } else if (clip_mask->type == TKP_CLIP_REGION) {
	TkpReleaseRegion(clip_mask->value.region);
#endif
    }
    return clip_mask;
}

/*
 *----------------------------------------------------------------------
 *
75
76
77
78
79
80
81
82
83
84
85
86
87

88
89
90
91
92
93
94
64
65
66
67
68
69
70






71
72
73
74
75
76
77
78







-
-
-
-
-
-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static void FreeClipMask(GC gc) {
    if (gc->clip_mask != None) {
#ifdef MAC_OSX_TK
	if (((TkpClipMask*) gc->clip_mask)->type == TKP_CLIP_REGION) {
	    TkpReleaseRegion(((TkpClipMask*) gc->clip_mask)->value.region);
	}
#endif
	ckfree(gc->clip_mask);
	ckfree((char *)gc->clip_mask);
	gc->clip_mask = None;
    }
}

/*
 *----------------------------------------------------------------------
 *
109
110
111
112
113
114
115

116
117
118
119
120
121
122
123
124
125
126

127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148


149
150
151

152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129


130
131
132
133

134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149


150
151
152






















153
154
155
156
157
158
159







+








-
-
-
+




















-
-
+
+


-
+















-
-



-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







XCreateGC(
    Display *display,
    Drawable d,
    unsigned long mask,
    XGCValues *values)
{
    GC gp;
    (void)d;

    /*
     * In order to have room for a dash list, MAX_DASH_LIST_SIZE extra chars
     * are defined, which is invisible from the outside. The list is assumed
     * to end with a 0-char, so this must be set explicitly during
     * initialization.
     */

#define MAX_DASH_LIST_SIZE 10

    gp = ckalloc(sizeof(XGCValues) + MAX_DASH_LIST_SIZE + gcCacheSize);
    gp = (GC)ckalloc(sizeof(XGCValuesWithDash));
    if (!gp) {
	return NULL;
    }

#define InitField(name,maskbit,default) \
	(gp->name = (mask & (maskbit)) ? values->name : (default))

    InitField(function,		  GCFunction,		GXcopy);
    InitField(plane_mask,	  GCPlaneMask,		(unsigned long)(~0));
    InitField(foreground,	  GCForeground,
	    BlackPixelOfScreen(DefaultScreenOfDisplay(display)));
    InitField(background,	  GCBackground,
	    WhitePixelOfScreen(DefaultScreenOfDisplay(display)));
    InitField(line_width,	  GCLineWidth,		1);
    InitField(line_style,	  GCLineStyle,		LineSolid);
    InitField(cap_style,	  GCCapStyle,		0);
    InitField(join_style,	  GCJoinStyle,		0);
    InitField(fill_style,	  GCFillStyle,		FillSolid);
    InitField(fill_rule,	  GCFillRule,		WindingRule);
    InitField(arc_mode,		  GCArcMode,		ArcPieSlice);
    InitField(tile,		  GCTile,		None);
    InitField(stipple,		  GCStipple,		None);
    InitField(tile,		  GCTile,		0);
    InitField(stipple,		  GCStipple,		0);
    InitField(ts_x_origin,	  GCTileStipXOrigin,	0);
    InitField(ts_y_origin,	  GCTileStipYOrigin,	0);
    InitField(font,		  GCFont,		None);
    InitField(font,		  GCFont,		0);
    InitField(subwindow_mode,	  GCSubwindowMode,	ClipByChildren);
    InitField(graphics_exposures, GCGraphicsExposures,	True);
    InitField(clip_x_origin,	  GCClipXOrigin,	0);
    InitField(clip_y_origin,	  GCClipYOrigin,	0);
    InitField(dash_offset,	  GCDashOffset,		0);
    InitField(dashes,		  GCDashList,		4);
    (&(gp->dashes))[1] = 0;

    gp->clip_mask = None;
    if (mask & GCClipMask) {
	TkpClipMask *clip_mask = AllocClipMask(gp);

	clip_mask->type = TKP_CLIP_PIXMAP;
	clip_mask->value.pixmap = values->clip_mask;
    }
    TkpInitGCCache(gp);

    return gp;
}

#ifdef MAC_OSX_TK
/*
 *----------------------------------------------------------------------
 *
 * TkpGetGCCache --
 *
 * Results:
 *	Pointer to the TkpGCCache at the end of the GC.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

TkpGCCache*
TkpGetGCCache(GC gc) {
    return (gc ? (TkpGCCache*)(((char*) gc) + sizeof(XGCValues) +
	    MAX_DASH_LIST_SIZE) : NULL);
}
#endif

/*
 *----------------------------------------------------------------------
 *
 * XChangeGC --
 *
 *	Changes the GC components specified by valuemask for the specified GC.
 *
264
265
266
267
268
269
270


271
272
273
274
275
276
277
278
279
280
223
224
225
226
227
228
229
230
231
232
233

234
235
236
237
238
239
240







+
+


-







 *----------------------------------------------------------------------
 */

int XFreeGC(
    Display *d,
    GC gc)
{
    (void)d;

    if (gc != NULL) {
	FreeClipMask(gc);
	TkpFreeGCCache(gc);
	ckfree(gc);
    }
    return Success;
}

/*
 *----------------------------------------------------------------------
295
296
297
298
299
300
301


302
303
304
305
306
307
308
309
310
311


312
313
314
315
316
317
318
319
320
321
322
323
324

325
326
327
328
329
330
331
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296







+
+










+
+













+








int
XSetForeground(
    Display *display,
    GC gc,
    unsigned long foreground)
{
    (void)display;

    gc->foreground = foreground;
    return Success;
}

int
XSetBackground(
    Display *display,
    GC gc,
    unsigned long background)
{
    (void)display;

    gc->background = background;
    return Success;
}

int
XSetDashes(
    Display *display,
    GC gc,
    int dash_offset,
    _Xconst char *dash_list,
    int n)
{
    char *p = &(gc->dashes);
    (void)display;

#ifdef TkWinDeleteBrush
    TkWinDeleteBrush(gc->fgBrush);
    TkWinDeletePen(gc->fgPen);
    TkWinDeleteBrush(gc->bgBrush);
    TkWinDeletePen(gc->fgExtPen);
#endif
340
341
342
343
344
345
346


347
348
349
350
351
352
353
354
355
356


357
358
359
360
361
362
363
364
365
366


367
368
369
370
371
372
373
374
375
376


377
378
379
380
381
382
383
384
385
386
387


388
389
390
391
392
393
394
395
396
397


398
399
400
401
402
403
404
405
406
407


408
409
410
411
412
413
414
415
416
417
418
419
420


421
422
423
424
425
426
427
428
429
430
431
432
433
434


435
436
437
438
439
440
441
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424







+
+










+
+










+
+










+
+











+
+










+
+










+
+













+
+














+
+








int
XSetFunction(
    Display *display,
    GC gc,
    int function)
{
    (void)display;

    gc->function = function;
    return Success;
}

int
XSetFillRule(
    Display *display,
    GC gc,
    int fill_rule)
{
    (void)display;

    gc->fill_rule = fill_rule;
    return Success;
}

int
XSetFillStyle(
    Display *display,
    GC gc,
    int fill_style)
{
    (void)display;

    gc->fill_style = fill_style;
    return Success;
}

int
XSetTSOrigin(
    Display *display,
    GC gc,
    int x, int y)
{
    (void)display;

    gc->ts_x_origin = x;
    gc->ts_y_origin = y;
    return Success;
}

int
XSetFont(
    Display *display,
    GC gc,
    Font font)
{
    (void)display;

    gc->font = font;
    return Success;
}

int
XSetArcMode(
    Display *display,
    GC gc,
    int arc_mode)
{
    (void)display;

    gc->arc_mode = arc_mode;
    return Success;
}

int
XSetStipple(
    Display *display,
    GC gc,
    Pixmap stipple)
{
    (void)display;

    gc->stipple = stipple;
    return Success;
}

int
XSetLineAttributes(
    Display *display,
    GC gc,
    unsigned int line_width,
    int line_style,
    int cap_style,
    int join_style)
{
    (void)display;

    gc->line_width = line_width;
    gc->line_style = line_style;
    gc->cap_style = cap_style;
    gc->join_style = join_style;
    return Success;
}

int
XSetClipOrigin(
    Display *display,
    GC gc,
    int clip_x_origin,
    int clip_y_origin)
{
    (void)display;

    gc->clip_x_origin = clip_x_origin;
    gc->clip_y_origin = clip_y_origin;
    return Success;
}

/*
 *----------------------------------------------------------------------
460
461
462
463
464
465
466


467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486


487
488
489
490
491
492
493
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458



459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477







+
+







-
-
-










+
+








int
TkSetRegion(
    Display *display,
    GC gc,
    TkRegion r)
{
    (void)display;

    if (r == NULL) {
	Tcl_Panic("must not pass NULL to TkSetRegion for compatibility with X11; use XSetClipMask instead");
    } else {
	TkpClipMask *clip_mask = AllocClipMask(gc);

	clip_mask->type = TKP_CLIP_REGION;
	clip_mask->value.region = r;
#ifdef MAC_OSX_TK
	TkpRetainRegion(r);
#endif
    }
    return Success;
}

int
XSetClipMask(
    Display *display,
    GC gc,
    Pixmap pixmap)
{
    (void)display;

    if (pixmap == None) {
	FreeClipMask(gc);
    } else {
	TkpClipMask *clip_mask = AllocClipMask(gc);

	clip_mask->type = TKP_CLIP_PIXMAP;
	clip_mask->value.pixmap = pixmap;
538
539
540
541
542
543
544

545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563






564
565
566
567
568
569
570
571
572
573
574




575
576
577
578
579
580
581
582
583




584

585
586
587
588
589
590
591
592




593
594
595
596

597
598
599
600
601
602
603


604
605
606
607
608
609
610
611
612
613
614
615


616
617
618

619
620
621
622
623
624
625
626
627
628








629
630
631





632
633
634
635
636
637
638
639
640
641


642
643
644

645
646
647
648


649
650
651
652
653
654


655
656
657

658
659
660
661


662
663


















































































































































































































































































664
665
666
667
668
669
670
671
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558

559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581

582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597

598
599
600
601
602



603
604












605
606
607
608

609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627



628
629
630
631
632
633
634
635
636
637
638
639



640
641



642




643
644






645
646
647
648

649
650
651
652
653
654
655


656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937







+



















+
+
+
+
+
+




-






+
+
+
+









+
+
+
+
-
+








+
+
+
+



-
+




-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+


-
+










+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+







-
-
-
+
+
-
-
-
+
-
-
-
-
+
+
-
-
-
-
-
-
+
+


-
+




+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








    Drawable d,
    GC gc,
    XPoint *points,
    int npoints,
    int mode)
{
    int res = Success;
    (void)mode;

    while (npoints-- > 0) {
	res = XDrawLine(display, d, gc,
		points[0].x, points[0].y, points[0].x, points[0].y);
	if (res != Success) break;
	++points;
    }
    return res;
}

#if !defined(MAC_OSX_TK)
int
XDrawSegments(
    Display *display,
    Drawable d,
    GC gc,
    XSegment *segments,
    int nsegments)
{
    (void)display;
    (void)d;
    (void)gc;
    (void)segments;
    (void)nsegments;

    return BadDrawable;
}
#endif

#if 0
char *
XFetchBuffer(
    Display *display,
    int *nbytes_return,
    int buffer)
{
    (void)display;
    (void)nbytes_return;
    (void)buffer;

    return (char *) 0;
}

Status
XFetchName(
    Display *display,
    Window w,
    char **window_name_return)
{
    (void)display;
    (void)w;
    (void)window_name_return;

    return (Status) 0;
    return Success;
}

Atom *
XListProperties(
    Display* display,
    Window w,
    int *num_prop_return)
{
    (void)display;
    (void)w;
    (void)num_prop_return;

    return (Atom *) 0;
}

void
int
XMapRaised(
    Display *display,
    Window w)
{
}

void
    (void)display;
    (void)w;
XPutImage(
    Display *display,
    Drawable d,
    GC gc,
    XImage *image,
    int src_x,
    int src_y,
    int dest_x,
    int dest_y,
    unsigned int width,
    unsigned int height)
{

    return Success;
}

void
int
XQueryTextExtents(
    Display *display,
    XID font_ID,
    _Xconst char *string,
    int nchars,
    int *direction_return,
    int *font_ascent_return,
    int *font_descent_return,
    XCharStruct *overall_return)
{
    (void)display;
    (void)font_ID;
    (void)string;
    (void)nchars;
    (void)direction_return;
    (void)font_ascent_return;
    (void)font_descent_return;
    (void)overall_return;
}

void

    return Success;
}

int
XReparentWindow(
    Display *display,
    Window w,
    Window parent,
    int x,
    int y)
{
}

void
    (void)display;
    (void)w;
XRotateBuffers(
    Display *display,
    int rotate)
    (void)parent;
{
}

void
    (void)x;
    (void)y;
XStoreBuffer(
    Display *display,
    _Xconst char *bytes,
    int nbytes,
    int buffer)
{

    return BadWindow;
}

void
int
XUndefineCursor(
    Display *display,
    Window w)
{
    (void)display;
    (void)w;
}
#endif

    return Success;
}

XVaNestedList
XVaCreateNestedList(
    int unused, ...)
{
    (void)unused;
    return NULL;
}

char *
XSetICValues(
    XIC xic, ...)
{
    (void)xic;
    return NULL;
}

char *
XGetICValues(
    XIC xic, ...)
{
    (void)xic;
    return NULL;
}

void
XSetICFocus(
    XIC xic)
{
    (void)xic;
}

Window
XCreateWindow(
    Display *display,
	Window parent,
	int x,
	int y,
    unsigned int width,
	unsigned int height,
    unsigned int border_width,
	int depth,
	unsigned int clazz,
    Visual *visual,
	unsigned long value_mask,
    XSetWindowAttributes *attributes)
{
    (void)display;
    (void)parent;
    (void)x;
    (void)y;
    (void)width;
    (void)height;
    (void)border_width;
    (void)depth;
    (void)clazz;
    (void)visual;
    (void)value_mask;
    (void)attributes;

	return 0;
}

int
XPointInRegion(
    Region rgn,
	int x,
	int y)
{
    (void)rgn;
    (void)x;
    (void)y;

	return 0;
}

int
XUnionRegion(
    Region srca,
	Region srcb,
	Region dr_return)
{
    (void)srca;
    (void)srcb;
    (void)dr_return;

	return 0;
}

Region
XPolygonRegion(
    XPoint *pts,
	int n,
	int rule)
{
    (void)pts;
    (void)n;
    (void)rule;

    return 0;
}

void
XDestroyIC(
    XIC ic)
{
    (void)ic;
}

Cursor
XCreatePixmapCursor(
    Display *display,
    Pixmap source,
    Pixmap mask,
    XColor *foreground_color,
    XColor *background_color,
    unsigned int x,
    unsigned int y)
{
    (void)display;
    (void)source;
    (void)mask;
    (void)foreground_color;
    (void)background_color;
    (void)x;
    (void)y;

    return (Cursor) NULL;
}

Cursor
XCreateGlyphCursor(
    Display *display,
    Font source_font,
    Font mask_font,
    unsigned int source_char,
    unsigned int mask_char,
    XColor _Xconst *foreground_color,
    XColor _Xconst *background_color)
{
    (void)display;
    (void)source_font;
    (void)mask_font;
    (void)source_char;
    (void)mask_char;
    (void)foreground_color;
    (void)background_color;

    return (Cursor) NULL;
}

XFontSet
XCreateFontSet(
    Display *display		/* display */,
    _Xconst char *base_font_name_list	/* base_font_name_list */,
    char ***missing_charset_list		/* missing_charset_list */,
    int *missing_charset_count		/* missing_charset_count */,
    char **def_string		/* def_string */
) {
    (void)display;
    (void)base_font_name_list;
    (void)missing_charset_list;
    (void)missing_charset_count;
    (void)def_string;

    return (XFontSet)0;
}

void
XFreeFontSet(
    Display *display,		/* display */
    XFontSet fontset		/* font_set */
) {
    (void)display;
    (void)fontset;
}

void
XFreeStringList(
    char **list		/* list */
) {
    (void)list;
}

Status
XCloseIM(
    XIM im /* im */
) {
    (void)im;

    return Success;
}

Bool
XRegisterIMInstantiateCallback(
    Display *dpy			/* dpy */,
    struct _XrmHashBucketRec *rdb	/* rdb */,
    char *res_name			/* res_name */,
    char *res_class			/* res_class */,
    XIDProc callback			/* callback */,
    XPointer client_data			/* client_data */
) {
    (void)dpy;
    (void)rdb;
    (void)res_name;
    (void)res_class;
    (void)callback;
    (void)client_data;

    return False;
}

Bool
XUnregisterIMInstantiateCallback(
    Display *dpy			/* dpy */,
    struct _XrmHashBucketRec *rdb	/* rdb */,
    char *res_name			/* res_name */,
    char *res_class			/* res_class */,
    XIDProc callback			/* callback */,
    XPointer client_data			/* client_data */
) {
    (void)dpy;
    (void)rdb;
    (void)res_name;
    (void)res_class;
    (void)callback;
    (void)client_data;

    return False;
}

char *
XSetLocaleModifiers(
    const char *modifier_list		/* modifier_list */
) {
    (void)modifier_list;

    return NULL;
}

XIM XOpenIM(
    Display *dpy			/* dpy */,
    struct _XrmHashBucketRec *rdb	/* rdb */,
    char *res_name			/* res_name */,
    char *res_class			/* res_class */
) {
    (void)dpy;
    (void)rdb;
    (void)res_name;
    (void)res_class;

    return NULL;
}

char *
XGetIMValues(
    XIM im /* im */, ...
) {
    (void)im;

    return NULL;
}

char *
XSetIMValues(
    XIM im /* im */, ...
) {
    (void)im;

    return NULL;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Changes to xlib/xutil.c.
32
33
34
35
36
37
38


39
40
41
42
43
44
45
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47







+
+







Atom
XInternAtom(
    Display *display,
    _Xconst char *atom_name,
    Bool only_if_exists)
{
    static Atom atom = XA_LAST_PREDEFINED;
    (void)atom_name;
    (void)only_if_exists;

    display->request++;
    return ++atom;
}

/*
 *----------------------------------------------------------------------
60
61
62
63
64
65
66
67

68
69
70
71
72
73
74
62
63
64
65
66
67
68

69
70
71
72
73
74
75
76







-
+







XVisualInfo *
XGetVisualInfo(
    Display *display,
    long vinfo_mask,
    XVisualInfo *vinfo_template,
    int *nitems_return)
{
    XVisualInfo *info = ckalloc(sizeof(XVisualInfo));
    XVisualInfo *info = (XVisualInfo *)ckalloc(sizeof(XVisualInfo));

    info->visual = DefaultVisual(display, 0);
    info->visualid = info->visual->visualid;
    info->screen = 0;
    info->depth = info->visual->bits_per_rgb;
    info->c_class = info->visual->c_class;
    info->colormap_size = info->visual->map_entries;